Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky:
"The big one is support for fake NUMA, splitting a really large machine
in more manageable piece improves performance in some cases, e.g. for
a KVM host.
The FICON Link Incident handling has been improved, this helps the
operator to identify degraded or non-operational FICON connections.
The save and restore of floating point and vector registers has been
overhauled to allow the future use of vector registers in the kernel.
A few small enhancement, magic sys-requests for the vt220 console via
SCLP, some more assembler code has been converted to C, the PCI error
handling is improved.
And the usual cleanup and bug fixing"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (59 commits)
s390/jump_label: Use %*ph to print small buffers
s390/sclp_vt220: support magic sysrequests
s390/ctrlchar: improve handling of magic sysrequests
s390/numa: remove superfluous ARCH_WANT defines
s390/3270: redraw screen on unsolicited device end
s390/dcssblk: correct out of bounds array indexes
s390/mm: simplify page table alloc/free code
s390/pci: move debug messages to debugfs
s390/nmi: initialize control register 0 earlier
s390/zcrypt: use msleep() instead of mdelay()
s390/hmcdrv: fix interrupt registration
s390/setup: fix novx parameter
s390/uaccess: remove uaccess_primary kernel parameter
s390: remove unneeded sizeof(void *) comparisons
s390/facilities: remove transactional-execution bits
s390/numa: re-add DIE sched_domain_topology_level
s390/dasd: enhance CUIR scope detection
s390/dasd: fix failing path verification
s390/vdso: emit a GNU hash
s390/numa: make core to node mapping data dynamic
...
diff --git a/.get_maintainer.ignore b/.get_maintainer.ignore
new file mode 100644
index 0000000..cca6d87
--- /dev/null
+++ b/.get_maintainer.ignore
@@ -0,0 +1 @@
+Christoph Hellwig <hch@lst.de>
diff --git a/.mailmap b/.mailmap
index b4091b7..4b31af5 100644
--- a/.mailmap
+++ b/.mailmap
@@ -17,6 +17,7 @@
Al Viro <viro@ftp.linux.org.uk>
Al Viro <viro@zenIV.linux.org.uk>
Andreas Herrmann <aherrman@de.ibm.com>
+Andrey Ryabinin <ryabinin.a.a@gmail.com> <a.ryabinin@samsung.com>
Andrew Morton <akpm@linux-foundation.org>
Andrew Vasquez <andrew.vasquez@qlogic.com>
Andy Adamson <andros@citi.umich.edu>
diff --git a/Documentation/ABI/stable/sysfs-bus-vmbus b/Documentation/ABI/stable/sysfs-bus-vmbus
new file mode 100644
index 0000000..636e938
--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-bus-vmbus
@@ -0,0 +1,29 @@
+What: /sys/bus/vmbus/devices/vmbus_*/id
+Date: Jul 2009
+KernelVersion: 2.6.31
+Contact: K. Y. Srinivasan <kys@microsoft.com>
+Description: The VMBus child_relid of the device's primary channel
+Users: tools/hv/lsvmbus
+
+What: /sys/bus/vmbus/devices/vmbus_*/class_id
+Date: Jul 2009
+KernelVersion: 2.6.31
+Contact: K. Y. Srinivasan <kys@microsoft.com>
+Description: The VMBus interface type GUID of the device
+Users: tools/hv/lsvmbus
+
+What: /sys/bus/vmbus/devices/vmbus_*/device_id
+Date: Jul 2009
+KernelVersion: 2.6.31
+Contact: K. Y. Srinivasan <kys@microsoft.com>
+Description: The VMBus interface instance GUID of the device
+Users: tools/hv/lsvmbus
+
+What: /sys/bus/vmbus/devices/vmbus_*/channel_vp_mapping
+Date: Jul 2015
+KernelVersion: 4.2.0
+Contact: K. Y. Srinivasan <kys@microsoft.com>
+Description: The mapping of which primary/sub channels are bound to which
+ Virtual Processors.
+ Format: <channel's child_relid:the bound cpu's number>
+Users: tools/hv/lsvmbus
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-loopback b/Documentation/ABI/testing/configfs-usb-gadget-loopback
index 9aae5bf..06beefbc 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-loopback
+++ b/Documentation/ABI/testing/configfs-usb-gadget-loopback
@@ -5,4 +5,4 @@
The attributes:
qlen - depth of loopback queue
- bulk_buflen - buffer length
+ buflen - buffer length
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-sourcesink b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink
index 29477c3..bc7ff73 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-sourcesink
+++ b/Documentation/ABI/testing/configfs-usb-gadget-sourcesink
@@ -9,4 +9,4 @@
isoc_maxpacket - 0 - 1023 (fs), 0 - 1024 (hs/ss)
isoc_mult - 0..2 (hs/ss only)
isoc_maxburst - 0..15 (ss only)
- qlen - buffer length
+ buflen - buffer length
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm3x b/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm3x
index b4d0b99..d72ca17 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm3x
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm3x
@@ -112,7 +112,7 @@
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Mask to apply to all the context ID comparator.
-What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/ctxid_val
+What: /sys/bus/coresight/devices/<memory_map>.[etm|ptm]/ctxid_pid
Date: November 2014
KernelVersion: 3.19
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x b/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
index 2fe2e3d..2355ed8 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
@@ -249,7 +249,7 @@
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (RW) Select which context ID comparator to work with.
-What: /sys/bus/coresight/devices/<memory_map>.etm/ctxid_val
+What: /sys/bus/coresight/devices/<memory_map>.etm/ctxid_pid
Date: April 2015
KernelVersion: 4.01
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 70c9b1a..42d360f 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -413,6 +413,11 @@
to compute the calories burnt by the user.
What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale_available
+What: /sys/.../iio:deviceX/in_anglvel_scale_available
+What: /sys/.../iio:deviceX/in_magn_scale_available
+What: /sys/.../iio:deviceX/in_illuminance_scale_available
+What: /sys/.../iio:deviceX/in_intensity_scale_available
+What: /sys/.../iio:deviceX/in_proximity_scale_available
What: /sys/.../iio:deviceX/in_voltageX_scale_available
What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available
What: /sys/.../iio:deviceX/out_voltageX_scale_available
@@ -488,7 +493,7 @@
Description:
Specifies the output powerdown mode.
DAC output stage is disconnected from the amplifier and
- 1kohm_to_gnd: connected to ground via an 1kOhm resistor,
+ 1kohm_to_gnd: connected to ground via an 1kOhm resistor,
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,
@@ -498,9 +503,9 @@
outX_powerdown_mode_available. If Y is not present the
mode is shared across all outputs.
-What: /sys/.../iio:deviceX/out_votlageY_powerdown_mode_available
+What: /sys/.../iio:deviceX/out_voltageY_powerdown_mode_available
What: /sys/.../iio:deviceX/out_voltage_powerdown_mode_available
-What: /sys/.../iio:deviceX/out_altvotlageY_powerdown_mode_available
+What: /sys/.../iio:deviceX/out_altvoltageY_powerdown_mode_available
What: /sys/.../iio:deviceX/out_altvoltage_powerdown_mode_available
KernelVersion: 2.6.38
Contact: linux-iio@vger.kernel.org
@@ -1035,13 +1040,6 @@
Description:
Number of scans contained by the buffer.
-What: /sys/bus/iio/devices/iio:deviceX/buffer/bytes_per_datum
-KernelVersion: 2.6.37
-Contact: linux-iio@vger.kernel.org
-Description:
- Bytes per scan. Due to alignment fun, the scan may be larger
- than implied directly by the scan_element parameters.
-
What: /sys/bus/iio/devices/iio:deviceX/buffer/enable
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs b/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
index 5235e6c..bbb0392 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
+++ b/Documentation/ABI/testing/sysfs-bus-iio-trigger-sysfs
@@ -9,3 +9,12 @@
automated testing or in situations, where other trigger methods
are not applicable. For example no RTC or spare GPIOs.
X is the IIO index of the trigger.
+
+What: /sys/bus/iio/devices/triggerX/name
+KernelVersion: 2.6.39
+Contact: linux-iio@vger.kernel.org
+Description:
+ The name attribute holds a description string for the current
+ trigger. In order to associate the trigger with an IIO device
+ one should write this name string to
+ /sys/bus/iio/devices/iio:deviceY/trigger/current_trigger.
diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb
index e5cc763..864637f 100644
--- a/Documentation/ABI/testing/sysfs-bus-usb
+++ b/Documentation/ABI/testing/sysfs-bus-usb
@@ -114,6 +114,20 @@
enabled for the device. Developer can write y/Y/1 or n/N/0 to
the file to enable/disable the feature.
+What: /sys/bus/usb/devices/.../power/usb3_hardware_lpm
+Date: June 2015
+Contact: Kevin Strasser <kevin.strasser@linux.intel.com>
+Description:
+ If CONFIG_PM is set and a USB 3.0 lpm-capable device is plugged
+ in to a xHCI host which supports link PM, it will check if U1
+ and U2 exit latencies have been set in the BOS descriptor; if
+ the check is is passed and the host supports USB3 hardware LPM,
+ USB3 hardware LPM will be enabled for the device and the USB
+ device directory will contain a file named
+ power/usb3_hardware_lpm. The file holds a string value (enable
+ or disable) indicating whether or not USB3 hardware LPM is
+ enabled for the device.
+
What: /sys/bus/usb/devices/.../removable
Date: February 2012
Contact: Matthew Garrett <mjg@redhat.com>
diff --git a/Documentation/ABI/testing/sysfs-driver-sunxi-sid b/Documentation/ABI/testing/sysfs-driver-sunxi-sid
deleted file mode 100644
index ffb9536..0000000
--- a/Documentation/ABI/testing/sysfs-driver-sunxi-sid
+++ /dev/null
@@ -1,22 +0,0 @@
-What: /sys/devices/*/<our-device>/eeprom
-Date: August 2013
-Contact: Oliver Schinagl <oliver@schinagl.nl>
-Description: read-only access to the SID (Security-ID) on current
- A-series SoC's from Allwinner. Currently supports A10, A10s, A13
- and A20 CPU's. The earlier A1x series of SoCs exports 16 bytes,
- whereas the newer A20 SoC exposes 512 bytes split into sections.
- Besides the 16 bytes of SID, there's also an SJTAG area,
- HDMI-HDCP key and some custom keys. Below a quick overview, for
- details see the user manual:
- 0x000 128 bit root-key (sun[457]i)
- 0x010 128 bit boot-key (sun7i)
- 0x020 64 bit security-jtag-key (sun7i)
- 0x028 16 bit key configuration (sun7i)
- 0x02b 16 bit custom-vendor-key (sun7i)
- 0x02c 320 bit low general key (sun7i)
- 0x040 32 bit read-control access (sun7i)
- 0x064 224 bit low general key (sun7i)
- 0x080 2304 bit HDCP-key (sun7i)
- 0x1a0 768 bit high general key (sun7i)
-Users: any user space application which wants to read the SID on
- Allwinner's A-series of CPU's.
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index b6a6a2e..9e08606 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -15,7 +15,7 @@
80211.xml debugobjects.xml sh.xml regulator.xml \
alsa-driver-api.xml writing-an-alsa-driver.xml \
tracepoint.xml drm.xml media_api.xml w1.xml \
- writing_musb_glue_layer.xml crypto-API.xml
+ writing_musb_glue_layer.xml crypto-API.xml iio.xml
include Documentation/DocBook/media/Makefile
diff --git a/Documentation/DocBook/iio.tmpl b/Documentation/DocBook/iio.tmpl
new file mode 100644
index 0000000..06bb53d
--- /dev/null
+++ b/Documentation/DocBook/iio.tmpl
@@ -0,0 +1,697 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="iioid">
+ <bookinfo>
+ <title>Industrial I/O driver developer's guide </title>
+
+ <authorgroup>
+ <author>
+ <firstname>Daniel</firstname>
+ <surname>Baluta</surname>
+ <affiliation>
+ <address>
+ <email>daniel.baluta@intel.com</email>
+ </address>
+ </affiliation>
+ </author>
+ </authorgroup>
+
+ <copyright>
+ <year>2015</year>
+ <holder>Intel Corporation</holder>
+ </copyright>
+
+ <legalnotice>
+ <para>
+ This documentation is free software; you can redistribute
+ it and/or modify it under the terms of the GNU General Public
+ License version 2.
+ </para>
+ </legalnotice>
+ </bookinfo>
+
+ <toc></toc>
+
+ <chapter id="intro">
+ <title>Introduction</title>
+ <para>
+ The main purpose of the Industrial I/O subsystem (IIO) is to provide
+ support for devices that in some sense perform either analog-to-digital
+ conversion (ADC) or digital-to-analog conversion (DAC) or both. The aim
+ is to fill the gap between the somewhat similar hwmon and input
+ subsystems.
+ Hwmon is directed at low sample rate sensors used to monitor and
+ control the system itself, like fan speed control or temperature
+ measurement. Input is, as its name suggests, focused on human interaction
+ input devices (keyboard, mouse, touchscreen). In some cases there is
+ considerable overlap between these and IIO.
+ </para>
+ <para>
+ Devices that fall into this category include:
+ <itemizedlist>
+ <listitem>
+ analog to digital converters (ADCs)
+ </listitem>
+ <listitem>
+ accelerometers
+ </listitem>
+ <listitem>
+ capacitance to digital converters (CDCs)
+ </listitem>
+ <listitem>
+ digital to analog converters (DACs)
+ </listitem>
+ <listitem>
+ gyroscopes
+ </listitem>
+ <listitem>
+ inertial measurement units (IMUs)
+ </listitem>
+ <listitem>
+ color and light sensors
+ </listitem>
+ <listitem>
+ magnetometers
+ </listitem>
+ <listitem>
+ pressure sensors
+ </listitem>
+ <listitem>
+ proximity sensors
+ </listitem>
+ <listitem>
+ temperature sensors
+ </listitem>
+ </itemizedlist>
+ Usually these sensors are connected via SPI or I2C. A common use case of the
+ sensors devices is to have combined functionality (e.g. light plus proximity
+ sensor).
+ </para>
+ </chapter>
+ <chapter id='iiosubsys'>
+ <title>Industrial I/O core</title>
+ <para>
+ The Industrial I/O core offers:
+ <itemizedlist>
+ <listitem>
+ a unified framework for writing drivers for many different types of
+ embedded sensors.
+ </listitem>
+ <listitem>
+ a standard interface to user space applications manipulating sensors.
+ </listitem>
+ </itemizedlist>
+ The implementation can be found under <filename>
+ drivers/iio/industrialio-*</filename>
+ </para>
+ <sect1 id="iiodevice">
+ <title> Industrial I/O devices </title>
+
+!Finclude/linux/iio/iio.h iio_dev
+!Fdrivers/iio/industrialio-core.c iio_device_alloc
+!Fdrivers/iio/industrialio-core.c iio_device_free
+!Fdrivers/iio/industrialio-core.c iio_device_register
+!Fdrivers/iio/industrialio-core.c iio_device_unregister
+
+ <para>
+ An IIO device usually corresponds to a single hardware sensor and it
+ provides all the information needed by a driver handling a device.
+ Let's first have a look at the functionality embedded in an IIO
+ device then we will show how a device driver makes use of an IIO
+ device.
+ </para>
+ <para>
+ There are two ways for a user space application to interact
+ with an IIO driver.
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/</filename>, this
+ represents a hardware sensor and groups together the data
+ channels of the same chip.
+ </listitem>
+ <listitem>
+ <filename>/dev/iio:deviceX</filename>, character device node
+ interface used for buffered data transfer and for events information
+ retrieval.
+ </listitem>
+ </itemizedlist>
+ </para>
+ A typical IIO driver will register itself as an I2C or SPI driver and will
+ create two routines, <function> probe </function> and <function> remove
+ </function>. At <function>probe</function>:
+ <itemizedlist>
+ <listitem>call <function>iio_device_alloc</function>, which allocates memory
+ for an IIO device.
+ </listitem>
+ <listitem> initialize IIO device fields with driver specific information
+ (e.g. device name, device channels).
+ </listitem>
+ <listitem>call <function> iio_device_register</function>, this registers the
+ device with the IIO core. After this call the device is ready to accept
+ requests from user space applications.
+ </listitem>
+ </itemizedlist>
+ At <function>remove</function>, we free the resources allocated in
+ <function>probe</function> in reverse order:
+ <itemizedlist>
+ <listitem><function>iio_device_unregister</function>, unregister the device
+ from the IIO core.
+ </listitem>
+ <listitem><function>iio_device_free</function>, free the memory allocated
+ for the IIO device.
+ </listitem>
+ </itemizedlist>
+
+ <sect2 id="iioattr"> <title> IIO device sysfs interface </title>
+ <para>
+ Attributes are sysfs files used to expose chip info and also allowing
+ applications to set various configuration parameters. For device
+ with index X, attributes can be found under
+ <filename>/sys/bus/iio/iio:deviceX/ </filename> directory.
+ Common attributes are:
+ <itemizedlist>
+ <listitem><filename>name</filename>, description of the physical
+ chip.
+ </listitem>
+ <listitem><filename>dev</filename>, shows the major:minor pair
+ associated with <filename>/dev/iio:deviceX</filename> node.
+ </listitem>
+ <listitem><filename>sampling_frequency_available</filename>,
+ available discrete set of sampling frequency values for
+ device.
+ </listitem>
+ </itemizedlist>
+ Available standard attributes for IIO devices are described in the
+ <filename>Documentation/ABI/testing/sysfs-bus-iio </filename> file
+ in the Linux kernel sources.
+ </para>
+ </sect2>
+ <sect2 id="iiochannel"> <title> IIO device channels </title>
+!Finclude/linux/iio/iio.h iio_chan_spec structure.
+ <para>
+ An IIO device channel is a representation of a data channel. An
+ IIO device can have one or multiple channels. For example:
+ <itemizedlist>
+ <listitem>
+ a thermometer sensor has one channel representing the
+ temperature measurement.
+ </listitem>
+ <listitem>
+ a light sensor with two channels indicating the measurements in
+ the visible and infrared spectrum.
+ </listitem>
+ <listitem>
+ an accelerometer can have up to 3 channels representing
+ acceleration on X, Y and Z axes.
+ </listitem>
+ </itemizedlist>
+ An IIO channel is described by the <type> struct iio_chan_spec
+ </type>. A thermometer driver for the temperature sensor in the
+ example above would have to describe its channel as follows:
+ <programlisting>
+ static const struct iio_chan_spec temp_channel[] = {
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ },
+ };
+
+ </programlisting>
+ Channel sysfs attributes exposed to userspace are specified in
+ the form of <emphasis>bitmasks</emphasis>. Depending on their
+ shared info, attributes can be set in one of the following masks:
+ <itemizedlist>
+ <listitem><emphasis>info_mask_separate</emphasis>, attributes will
+ be specific to this channel</listitem>
+ <listitem><emphasis>info_mask_shared_by_type</emphasis>,
+ attributes are shared by all channels of the same type</listitem>
+ <listitem><emphasis>info_mask_shared_by_dir</emphasis>, attributes
+ are shared by all channels of the same direction </listitem>
+ <listitem><emphasis>info_mask_shared_by_all</emphasis>,
+ attributes are shared by all channels</listitem>
+ </itemizedlist>
+ When there are multiple data channels per channel type we have two
+ ways to distinguish between them:
+ <itemizedlist>
+ <listitem> set <emphasis> .modified</emphasis> field of <type>
+ iio_chan_spec</type> to 1. Modifiers are specified using
+ <emphasis>.channel2</emphasis> field of the same
+ <type>iio_chan_spec</type> structure and are used to indicate a
+ physically unique characteristic of the channel such as its direction
+ or spectral response. For example, a light sensor can have two channels,
+ one for infrared light and one for both infrared and visible light.
+ </listitem>
+ <listitem> set <emphasis>.indexed </emphasis> field of
+ <type>iio_chan_spec</type> to 1. In this case the channel is
+ simply another instance with an index specified by the
+ <emphasis>.channel</emphasis> field.
+ </listitem>
+ </itemizedlist>
+ Here is how we can make use of the channel's modifiers:
+ <programlisting>
+ static const struct iio_chan_spec light_channels[] = {
+ {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_IR,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ },
+ {
+ .type = IIO_LIGHT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_shared = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ },
+
+ }
+ </programlisting>
+ This channel's definition will generate two separate sysfs files
+ for raw data retrieval:
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/in_intensity_ir_raw</filename>
+ </listitem>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/in_intensity_both_raw</filename>
+ </listitem>
+ </itemizedlist>
+ one file for processed data:
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/in_illuminance_input
+ </filename>
+ </listitem>
+ </itemizedlist>
+ and one shared sysfs file for sampling frequency:
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/iio:deviceX/sampling_frequency.
+ </filename>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Here is how we can make use of the channel's indexing:
+ <programlisting>
+ static const struct iio_chan_spec light_channels[] = {
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 0,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ },
+ {
+ .type = IIO_VOLTAGE,
+ .indexed = 1,
+ .channel = 1,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ },
+ }
+ </programlisting>
+ This will generate two separate attributes files for raw data
+ retrieval:
+ <itemizedlist>
+ <listitem>
+ <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage0_raw</filename>,
+ representing voltage measurement for channel 0.
+ </listitem>
+ <listitem>
+ <filename>/sys/bus/iio/devices/iio:deviceX/in_voltage1_raw</filename>,
+ representing voltage measurement for channel 1.
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="iiobuffer"> <title> Industrial I/O buffers </title>
+!Finclude/linux/iio/buffer.h iio_buffer
+!Edrivers/iio/industrialio-buffer.c
+
+ <para>
+ The Industrial I/O core offers a way for continuous data capture
+ based on a trigger source. Multiple data channels can be read at once
+ from <filename>/dev/iio:deviceX</filename> character device node,
+ thus reducing the CPU load.
+ </para>
+
+ <sect2 id="iiobuffersysfs">
+ <title>IIO buffer sysfs interface </title>
+ <para>
+ An IIO buffer has an associated attributes directory under <filename>
+ /sys/bus/iio/iio:deviceX/buffer/</filename>. Here are the existing
+ attributes:
+ <itemizedlist>
+ <listitem>
+ <emphasis>length</emphasis>, the total number of data samples
+ (capacity) that can be stored by the buffer.
+ </listitem>
+ <listitem>
+ <emphasis>enable</emphasis>, activate buffer capture.
+ </listitem>
+ </itemizedlist>
+
+ </para>
+ </sect2>
+ <sect2 id="iiobuffersetup"> <title> IIO buffer setup </title>
+ <para>The meta information associated with a channel reading
+ placed in a buffer is called a <emphasis> scan element </emphasis>.
+ The important bits configuring scan elements are exposed to
+ userspace applications via the <filename>
+ /sys/bus/iio/iio:deviceX/scan_elements/</filename> directory. This
+ file contains attributes of the following form:
+ <itemizedlist>
+ <listitem><emphasis>enable</emphasis>, used for enabling a channel.
+ If and only if its attribute is non zero, then a triggered capture
+ will contain data samples for this channel.
+ </listitem>
+ <listitem><emphasis>type</emphasis>, description of the scan element
+ data storage within the buffer and hence the form in which it is
+ read from user space. Format is <emphasis>
+ [be|le]:[s|u]bits/storagebitsXrepeat[>>shift] </emphasis>.
+ <itemizedlist>
+ <listitem> <emphasis>be</emphasis> or <emphasis>le</emphasis>, specifies
+ big or little endian.
+ </listitem>
+ <listitem>
+ <emphasis>s </emphasis>or <emphasis>u</emphasis>, specifies if
+ signed (2's complement) or unsigned.
+ </listitem>
+ <listitem><emphasis>bits</emphasis>, is the number of valid data
+ bits.
+ </listitem>
+ <listitem><emphasis>storagebits</emphasis>, is the number of bits
+ (after padding) that it occupies in the buffer.
+ </listitem>
+ <listitem>
+ <emphasis>shift</emphasis>, if specified, is the shift that needs
+ to be applied prior to masking out unused bits.
+ </listitem>
+ <listitem>
+ <emphasis>repeat</emphasis>, specifies the number of bits/storagebits
+ repetitions. When the repeat element is 0 or 1, then the repeat
+ value is omitted.
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ For example, a driver for a 3-axis accelerometer with 12 bit
+ resolution where data is stored in two 8-bits registers as
+ follows:
+ <programlisting>
+ 7 6 5 4 3 2 1 0
+ +---+---+---+---+---+---+---+---+
+ |D3 |D2 |D1 |D0 | X | X | X | X | (LOW byte, address 0x06)
+ +---+---+---+---+---+---+---+---+
+
+ 7 6 5 4 3 2 1 0
+ +---+---+---+---+---+---+---+---+
+ |D11|D10|D9 |D8 |D7 |D6 |D5 |D4 | (HIGH byte, address 0x07)
+ +---+---+---+---+---+---+---+---+
+ </programlisting>
+
+ will have the following scan element type for each axis:
+ <programlisting>
+ $ cat /sys/bus/iio/devices/iio:device0/scan_elements/in_accel_y_type
+ le:s12/16>>4
+ </programlisting>
+ A user space application will interpret data samples read from the
+ buffer as two byte little endian signed data, that needs a 4 bits
+ right shift before masking out the 12 valid bits of data.
+ </para>
+ <para>
+ For implementing buffer support a driver should initialize the following
+ fields in <type>iio_chan_spec</type> definition:
+ <programlisting>
+ struct iio_chan_spec {
+ /* other members */
+ int scan_index
+ struct {
+ char sign;
+ u8 realbits;
+ u8 storagebits;
+ u8 shift;
+ u8 repeat;
+ enum iio_endian endianness;
+ } scan_type;
+ };
+ </programlisting>
+ The driver implementing the accelerometer described above will
+ have the following channel definition:
+ <programlisting>
+ struct struct iio_chan_spec accel_channels[] = {
+ {
+ .type = IIO_ACCEL,
+ .modified = 1,
+ .channel2 = IIO_MOD_X,
+ /* other stuff here */
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 12,
+ .storgebits = 16,
+ .shift = 4,
+ .endianness = IIO_LE,
+ },
+ }
+ /* similar for Y (with channel2 = IIO_MOD_Y, scan_index = 1)
+ * and Z (with channel2 = IIO_MOD_Z, scan_index = 2) axis
+ */
+ }
+ </programlisting>
+ </para>
+ <para>
+ Here <emphasis> scan_index </emphasis> defines the order in which
+ the enabled channels are placed inside the buffer. Channels with a lower
+ scan_index will be placed before channels with a higher index. Each
+ channel needs to have a unique scan_index.
+ </para>
+ <para>
+ Setting scan_index to -1 can be used to indicate that the specific
+ channel does not support buffered capture. In this case no entries will
+ be created for the channel in the scan_elements directory.
+ </para>
+ </sect2>
+ </sect1>
+
+ <sect1 id="iiotrigger"> <title> Industrial I/O triggers </title>
+!Finclude/linux/iio/trigger.h iio_trigger
+!Edrivers/iio/industrialio-trigger.c
+ <para>
+ In many situations it is useful for a driver to be able to
+ capture data based on some external event (trigger) as opposed
+ to periodically polling for data. An IIO trigger can be provided
+ by a device driver that also has an IIO device based on hardware
+ generated events (e.g. data ready or threshold exceeded) or
+ provided by a separate driver from an independent interrupt
+ source (e.g. GPIO line connected to some external system, timer
+ interrupt or user space writing a specific file in sysfs). A
+ trigger may initiate data capture for a number of sensors and
+ also it may be completely unrelated to the sensor itself.
+ </para>
+
+ <sect2 id="iiotrigsysfs"> <title> IIO trigger sysfs interface </title>
+ There are two locations in sysfs related to triggers:
+ <itemizedlist>
+ <listitem><filename>/sys/bus/iio/devices/triggerY</filename>,
+ this file is created once an IIO trigger is registered with
+ the IIO core and corresponds to trigger with index Y. Because
+ triggers can be very different depending on type there are few
+ standard attributes that we can describe here:
+ <itemizedlist>
+ <listitem>
+ <emphasis>name</emphasis>, trigger name that can be later
+ used for association with a device.
+ </listitem>
+ <listitem>
+ <emphasis>sampling_frequency</emphasis>, some timer based
+ triggers use this attribute to specify the frequency for
+ trigger calls.
+ </listitem>
+ </itemizedlist>
+ </listitem>
+ <listitem>
+ <filename>/sys/bus/iio/devices/iio:deviceX/trigger/</filename>, this
+ directory is created once the device supports a triggered
+ buffer. We can associate a trigger with our device by writing
+ the trigger's name in the <filename>current_trigger</filename> file.
+ </listitem>
+ </itemizedlist>
+ </sect2>
+
+ <sect2 id="iiotrigattr"> <title> IIO trigger setup</title>
+
+ <para>
+ Let's see a simple example of how to setup a trigger to be used
+ by a driver.
+
+ <programlisting>
+ struct iio_trigger_ops trigger_ops = {
+ .set_trigger_state = sample_trigger_state,
+ .validate_device = sample_validate_device,
+ }
+
+ struct iio_trigger *trig;
+
+ /* first, allocate memory for our trigger */
+ trig = iio_trigger_alloc(dev, "trig-%s-%d", name, idx);
+
+ /* setup trigger operations field */
+ trig->ops = &trigger_ops;
+
+ /* now register the trigger with the IIO core */
+ iio_trigger_register(trig);
+ </programlisting>
+ </para>
+ </sect2>
+
+ <sect2 id="iiotrigsetup"> <title> IIO trigger ops</title>
+!Finclude/linux/iio/trigger.h iio_trigger_ops
+ <para>
+ Notice that a trigger has a set of operations attached:
+ <itemizedlist>
+ <listitem>
+ <function>set_trigger_state</function>, switch the trigger on/off
+ on demand.
+ </listitem>
+ <listitem>
+ <function>validate_device</function>, function to validate the
+ device when the current trigger gets changed.
+ </listitem>
+ </itemizedlist>
+ </para>
+ </sect2>
+ </sect1>
+ <sect1 id="iiotriggered_buffer">
+ <title> Industrial I/O triggered buffers </title>
+ <para>
+ Now that we know what buffers and triggers are let's see how they
+ work together.
+ </para>
+ <sect2 id="iiotrigbufsetup"> <title> IIO triggered buffer setup</title>
+!Edrivers/iio/industrialio-triggered-buffer.c
+!Finclude/linux/iio/iio.h iio_buffer_setup_ops
+
+
+ <para>
+ A typical triggered buffer setup looks like this:
+ <programlisting>
+ const struct iio_buffer_setup_ops sensor_buffer_setup_ops = {
+ .preenable = sensor_buffer_preenable,
+ .postenable = sensor_buffer_postenable,
+ .postdisable = sensor_buffer_postdisable,
+ .predisable = sensor_buffer_predisable,
+ };
+
+ irqreturn_t sensor_iio_pollfunc(int irq, void *p)
+ {
+ pf->timestamp = iio_get_time_ns();
+ return IRQ_WAKE_THREAD;
+ }
+
+ irqreturn_t sensor_trigger_handler(int irq, void *p)
+ {
+ u16 buf[8];
+ int i = 0;
+
+ /* read data for each active channel */
+ for_each_set_bit(bit, active_scan_mask, masklength)
+ buf[i++] = sensor_get_data(bit)
+
+ iio_push_to_buffers_with_timestamp(indio_dev, buf, timestamp);
+
+ iio_trigger_notify_done(trigger);
+ return IRQ_HANDLED;
+ }
+
+ /* setup triggered buffer, usually in probe function */
+ iio_triggered_buffer_setup(indio_dev, sensor_iio_polfunc,
+ sensor_trigger_handler,
+ sensor_buffer_setup_ops);
+ </programlisting>
+ </para>
+ The important things to notice here are:
+ <itemizedlist>
+ <listitem><function> iio_buffer_setup_ops</function>, the buffer setup
+ functions to be called at predefined points in the buffer configuration
+ sequence (e.g. before enable, after disable). If not specified, the
+ IIO core uses the default <type>iio_triggered_buffer_setup_ops</type>.
+ </listitem>
+ <listitem><function>sensor_iio_pollfunc</function>, the function that
+ will be used as top half of poll function. It should do as little
+ processing as possible, because it runs in interrupt context. The most
+ common operation is recording of the current timestamp and for this reason
+ one can use the IIO core defined <function>iio_pollfunc_store_time
+ </function> function.
+ </listitem>
+ <listitem><function>sensor_trigger_handler</function>, the function that
+ will be used as bottom half of the poll function. This runs in the
+ context of a kernel thread and all the processing takes place here.
+ It usually reads data from the device and stores it in the internal
+ buffer together with the timestamp recorded in the top half.
+ </listitem>
+ </itemizedlist>
+ </sect2>
+ </sect1>
+ </chapter>
+ <chapter id='iioresources'>
+ <title> Resources </title>
+ IIO core may change during time so the best documentation to read is the
+ source code. There are several locations where you should look:
+ <itemizedlist>
+ <listitem>
+ <filename>drivers/iio/</filename>, contains the IIO core plus
+ and directories for each sensor type (e.g. accel, magnetometer,
+ etc.)
+ </listitem>
+ <listitem>
+ <filename>include/linux/iio/</filename>, contains the header
+ files, nice to read for the internal kernel interfaces.
+ </listitem>
+ <listitem>
+ <filename>include/uapi/linux/iio/</filename>, contains files to be
+ used by user space applications.
+ </listitem>
+ <listitem>
+ <filename>tools/iio/</filename>, contains tools for rapidly
+ testing buffers, events and device creation.
+ </listitem>
+ <listitem>
+ <filename>drivers/staging/iio/</filename>, contains code for some
+ drivers or experimental features that are not yet mature enough
+ to be moved out.
+ </listitem>
+ </itemizedlist>
+ <para>
+ Besides the code, there are some good online documentation sources:
+ <itemizedlist>
+ <listitem>
+ <ulink url="http://marc.info/?l=linux-iio"> Industrial I/O mailing
+ list </ulink>
+ </listitem>
+ <listitem>
+ <ulink url="http://wiki.analog.com/software/linux/docs/iio/iio">
+ Analog Device IIO wiki page </ulink>
+ </listitem>
+ <listitem>
+ <ulink url="https://fosdem.org/2015/schedule/event/iiosdr/">
+ Using the Linux IIO framework for SDR, Lars-Peter Clausen's
+ presentation at FOSDEM </ulink>
+ </listitem>
+ </itemizedlist>
+ </para>
+ </chapter>
+</book>
+
+<!--
+vim: softtabstop=2:shiftwidth=2:expandtab:textwidth=72
+-->
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 65a6db2..62938eb 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -17,6 +17,7 @@
- "arm,coresight-tmc", "arm,primecell";
- "arm,coresight-funnel", "arm,primecell";
- "arm,coresight-etm3x", "arm,primecell";
+ - "arm,coresight-etm4x", "arm,primecell";
- "qcom,coresight-replicator1x", "arm,primecell";
* reg: physical base address and length of the register
diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt
index d6b794c..91e6e5c 100644
--- a/Documentation/devicetree/bindings/arm/cpus.txt
+++ b/Documentation/devicetree/bindings/arm/cpus.txt
@@ -199,6 +199,7 @@
"qcom,kpss-acc-v1"
"qcom,kpss-acc-v2"
"rockchip,rk3066-smp"
+ "ste,dbx500-smp"
- cpu-release-addr
Usage: required for systems that have an "enable-method"
diff --git a/Documentation/devicetree/bindings/dma/apm-xgene-dma.txt b/Documentation/devicetree/bindings/dma/apm-xgene-dma.txt
index d305876..c53e0b0 100644
--- a/Documentation/devicetree/bindings/dma/apm-xgene-dma.txt
+++ b/Documentation/devicetree/bindings/dma/apm-xgene-dma.txt
@@ -35,7 +35,7 @@
device_type = "dma";
reg = <0x0 0x1f270000 0x0 0x10000>,
<0x0 0x1f200000 0x0 0x10000>,
- <0x0 0x1b008000 0x0 0x2000>,
+ <0x0 0x1b000000 0x0 0x400000>,
<0x0 0x1054a000 0x0 0x100>;
interrupts = <0x0 0x82 0x4>,
<0x0 0xb8 0x4>,
diff --git a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
index 45414bb..f61d5af 100644
--- a/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
+++ b/Documentation/devicetree/bindings/extcon/extcon-palmas.txt
@@ -10,8 +10,11 @@
Optional Properties:
- ti,wakeup : To enable the wakeup comparator in probe
- - ti,enable-id-detection: Perform ID detection.
+ - ti,enable-id-detection: Perform ID detection. If id-gpio is specified
+ it performs id-detection using GPIO else using OTG core.
- ti,enable-vbus-detection: Perform VBUS detection.
+ - id-gpio: gpio for GPIO ID detection. See gpio binding.
+ - debounce-delay-ms: debounce delay for GPIO ID pin in milliseconds.
palmas-usb {
compatible = "ti,twl6035-usb", "ti,palmas-usb";
diff --git a/Documentation/devicetree/bindings/iio/adc/mcp320x.txt b/Documentation/devicetree/bindings/iio/adc/mcp320x.txt
index b851843..2a1f3af 100644
--- a/Documentation/devicetree/bindings/iio/adc/mcp320x.txt
+++ b/Documentation/devicetree/bindings/iio/adc/mcp320x.txt
@@ -18,6 +18,7 @@
"mcp3202"
"mcp3204"
"mcp3208"
+ "mcp3301"
Examples:
diff --git a/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt b/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
index 3eb40e2..1aad051 100644
--- a/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
+++ b/Documentation/devicetree/bindings/iio/adc/vf610-adc.txt
@@ -17,6 +17,11 @@
- Frequency in normal mode (ADLPC=0, ADHSC=0)
- Frequency in high-speed mode (ADLPC=0, ADHSC=1)
- Frequency in low-power mode (ADLPC=1, ADHSC=0)
+- min-sample-time: Minimum sampling time in nanoseconds. This value has
+ to be chosen according to the conversion mode and the connected analog
+ source resistance (R_as) and capacitance (C_as). Refer the datasheet's
+ operating requirements. A safe default across a wide range of R_as and
+ C_as as well as conversion modes is 1000ns.
Example:
adc0: adc@4003b000 {
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/mmc35240.txt b/Documentation/devicetree/bindings/iio/magnetometer/mmc35240.txt
new file mode 100644
index 0000000..a01235c
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/magnetometer/mmc35240.txt
@@ -0,0 +1,13 @@
+* MEMSIC MMC35240 magnetometer sensor
+
+Required properties:
+
+ - compatible : should be "memsic,mmc35240"
+ - reg : the I2C address of the magnetometer
+
+Example:
+
+mmc35240@30 {
+ compatible = "memsic,mmc35240";
+ reg = <0x30>;
+};
diff --git a/Documentation/devicetree/bindings/iio/st-sensors.txt b/Documentation/devicetree/bindings/iio/st-sensors.txt
index 8a6be3b..d3ccdb1 100644
--- a/Documentation/devicetree/bindings/iio/st-sensors.txt
+++ b/Documentation/devicetree/bindings/iio/st-sensors.txt
@@ -35,6 +35,7 @@
- st,lsm303dl-accel
- st,lsm303dlm-accel
- st,lsm330-accel
+- st,lsm303agr-accel
Gyroscopes:
- st,l3g4200d-gyro
@@ -46,6 +47,7 @@
- st,lsm330-gyro
Magnetometers:
+- st,lsm303agr-magn
- st,lsm303dlh-magn
- st,lsm303dlhc-magn
- st,lsm303dlm-magn
diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
index c03eec1..3443e0f 100644
--- a/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
+++ b/Documentation/devicetree/bindings/iommu/arm,smmu-v3.txt
@@ -35,3 +35,6 @@
NOTE: this only applies to the SMMU itself, not
masters connected upstream of the SMMU.
+
+- hisilicon,broken-prefetch-cmd
+ : Avoid sending CMD_PREFETCH_* commands to the SMMU.
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
index 5d0376b..211e778 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
@@ -17,7 +17,6 @@
"fsl,imx6sx-usdhc"
Optional properties:
-- fsl,cd-controller : Indicate to use controller internal card detection
- fsl,wp-controller : Indicate to use controller internal write protection
- fsl,delay-line : Specify the number of delay cells for override mode.
This is used to set the clock delay for DLL(Delay Line) on override mode
@@ -35,7 +34,6 @@
compatible = "fsl,imx51-esdhc";
reg = <0x70004000 0x4000>;
interrupts = <1>;
- fsl,cd-controller;
fsl,wp-controller;
};
diff --git a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
similarity index 78%
rename from Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
rename to Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
index fabdf64..d543ed3 100644
--- a/Documentation/devicetree/bindings/misc/allwinner,sunxi-sid.txt
+++ b/Documentation/devicetree/bindings/nvmem/allwinner,sunxi-sid.txt
@@ -4,6 +4,10 @@
- compatible: "allwinner,sun4i-a10-sid" or "allwinner,sun7i-a20-sid"
- reg: Should contain registers location and length
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
Example for sun4i:
sid@01c23800 {
compatible = "allwinner,sun4i-a10-sid";
diff --git a/Documentation/devicetree/bindings/nvmem/nvmem.txt b/Documentation/devicetree/bindings/nvmem/nvmem.txt
new file mode 100644
index 0000000..b52bc11
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/nvmem.txt
@@ -0,0 +1,80 @@
+= NVMEM(Non Volatile Memory) Data Device Tree Bindings =
+
+This binding is intended to represent the location of hardware
+configuration data stored in NVMEMs like eeprom, efuses and so on.
+
+On a significant proportion of boards, the manufacturer has stored
+some data on NVMEM, for the OS to be able to retrieve these information
+and act upon it. Obviously, the OS has to know about where to retrieve
+these data from, and where they are stored on the storage device.
+
+This document is here to document this.
+
+= Data providers =
+Contains bindings specific to provider drivers and data cells as children
+of this node.
+
+Optional properties:
+ read-only: Mark the provider as read only.
+
+= Data cells =
+These are the child nodes of the provider which contain data cell
+information like offset and size in nvmem provider.
+
+Required properties:
+reg: specifies the offset in byte within the storage device.
+
+Optional properties:
+
+bits: Is pair of bit location and number of bits, which specifies offset
+ in bit and number of bits within the address range specified by reg property.
+ Offset takes values from 0-7.
+
+For example:
+
+ /* Provider */
+ qfprom: qfprom@00700000 {
+ ...
+
+ /* Data cells */
+ tsens_calibration: calib@404 {
+ reg = <0x404 0x10>;
+ };
+
+ tsens_calibration_bckp: calib_bckp@504 {
+ reg = <0x504 0x11>;
+ bits = <6 128>
+ };
+
+ pvs_version: pvs-version@6 {
+ reg = <0x6 0x2>
+ bits = <7 2>
+ };
+
+ speed_bin: speed-bin@c{
+ reg = <0xc 0x1>;
+ bits = <2 3>;
+
+ };
+ ...
+ };
+
+= Data consumers =
+Are device nodes which consume nvmem data cells/providers.
+
+Required-properties:
+nvmem-cells: list of phandle to the nvmem data cells.
+nvmem-cell-names: names for the each nvmem-cells specified. Required if
+ nvmem-cells is used.
+
+Optional-properties:
+nvmem : list of phandles to nvmem providers.
+nvmem-names: names for the each nvmem provider. required if nvmem is used.
+
+For example:
+
+ tsens {
+ ...
+ nvmem-cells = <&tsens_calibration>;
+ nvmem-cell-names = "calibration";
+ };
diff --git a/Documentation/devicetree/bindings/nvmem/qfprom.txt b/Documentation/devicetree/bindings/nvmem/qfprom.txt
new file mode 100644
index 0000000..4ad68b7
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/qfprom.txt
@@ -0,0 +1,35 @@
+= Qualcomm QFPROM device tree bindings =
+
+This binding is intended to represent QFPROM which is found in most QCOM SOCs.
+
+Required properties:
+- compatible: should be "qcom,qfprom"
+- reg: Should contain registers location and length
+
+= Data cells =
+Are child nodes of qfprom, bindings of which as described in
+bindings/nvmem/nvmem.txt
+
+Example:
+
+ qfprom: qfprom@00700000 {
+ compatible = "qcom,qfprom";
+ reg = <0x00700000 0x8000>;
+ ...
+ /* Data cells */
+ tsens_calibration: calib@404 {
+ reg = <0x4404 0x10>;
+ };
+ };
+
+
+= Data consumers =
+Are device nodes which consume nvmem data cells.
+
+For example:
+
+ tsens {
+ ...
+ nvmem-cells = <&tsens_calibration>;
+ nvmem-cell-names = "calibration";
+ };
diff --git a/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt b/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt
new file mode 100644
index 0000000..bd61b46
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-lpc18xx-usb-otg.txt
@@ -0,0 +1,26 @@
+NXP LPC18xx/43xx internal USB OTG PHY binding
+---------------------------------------------
+
+This file contains documentation for the internal USB OTG PHY found
+in NXP LPC18xx and LPC43xx SoCs.
+
+Required properties:
+- compatible : must be "nxp,lpc1850-usb-otg-phy"
+- clocks : must be exactly one entry
+See: Documentation/devicetree/bindings/clock/clock-bindings.txt
+- #phy-cells : must be 0 for this phy
+See: Documentation/devicetree/bindings/phy/phy-bindings.txt
+
+The phy node must be a child of the creg syscon node.
+
+Example:
+creg: syscon@40043000 {
+ compatible = "nxp,lpc1850-creg", "syscon", "simple-mfd";
+ reg = <0x40043000 0x1000>;
+
+ usb0_otg_phy: phy@004 {
+ compatible = "nxp,lpc1850-usb-otg-phy";
+ clocks = <&ccu1 CLK_USB0>;
+ #phy-cells = <0>;
+ };
+};
diff --git a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
index 16528b9..0cebf74 100644
--- a/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
+++ b/Documentation/devicetree/bindings/phy/sun4i-usb-phy.txt
@@ -7,6 +7,8 @@
* allwinner,sun5i-a13-usb-phy
* allwinner,sun6i-a31-usb-phy
* allwinner,sun7i-a20-usb-phy
+ * allwinner,sun8i-a23-usb-phy
+ * allwinner,sun8i-a33-usb-phy
- reg : a list of offset + length pairs
- reg-names :
* "phy_ctrl"
@@ -17,12 +19,21 @@
- clock-names :
* "usb_phy" for sun4i, sun5i or sun7i
* "usb0_phy", "usb1_phy" and "usb2_phy" for sun6i
+ * "usb0_phy", "usb1_phy" for sun8i
- resets : a list of phandle + reset specifier pairs
- reset-names :
* "usb0_reset"
* "usb1_reset"
* "usb2_reset" for sun4i, sun6i or sun7i
+Optional properties:
+- usb0_id_det-gpios : gpio phandle for reading the otg id pin value
+- usb0_vbus_det-gpios : gpio phandle for detecting the presence of usb0 vbus
+- usb0_vbus_power-supply: power-supply phandle for usb0 vbus presence detect
+- usb0_vbus-supply : regulator phandle for controller usb0 vbus
+- usb1_vbus-supply : regulator phandle for controller usb1 vbus
+- usb2_vbus-supply : regulator phandle for controller usb2 vbus
+
Example:
usbphy: phy@0x01c13400 {
#phy-cells = <1>;
@@ -32,6 +43,13 @@
reg-names = "phy_ctrl", "pmu1", "pmu2";
clocks = <&usb_clk 8>;
clock-names = "usb_phy";
- resets = <&usb_clk 1>, <&usb_clk 2>;
- reset-names = "usb1_reset", "usb2_reset";
+ resets = <&usb_clk 0>, <&usb_clk 1>, <&usb_clk 2>;
+ reset-names = "usb0_reset", "usb1_reset", "usb2_reset";
+ pinctrl-names = "default";
+ pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
+ usb0_id_det-gpios = <&pio 7 19 GPIO_ACTIVE_HIGH>; /* PH19 */
+ usb0_vbus_det-gpios = <&pio 7 22 GPIO_ACTIVE_HIGH>; /* PH22 */
+ usb0_vbus-supply = <®_usb0_vbus>;
+ usb1_vbus-supply = <®_usb1_vbus>;
+ usb2_vbus-supply = <®_usb2_vbus>;
};
diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
index 305e3df..9cf9446 100644
--- a/Documentation/devicetree/bindings/phy/ti-phy.txt
+++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
@@ -82,6 +82,9 @@
- id: If there are multiple instance of the same type, in order to
differentiate between each instance "id" can be used (e.g., multi-lane PCIe
PHY). If "id" is not provided, it is set to default value of '1'.
+ - syscon-pllreset: Handle to system control region that contains the
+ CTRL_CORE_SMA_SW_0 register and register offset to the CTRL_CORE_SMA_SW_0
+ register that contains the SATA_PLL_SOFT_RESET bit. Only valid for sata_phy.
This is usually a subnode of ocp2scp to which it is connected.
@@ -100,3 +103,16 @@
"sysclk",
"refclk";
};
+
+sata_phy: phy@4A096000 {
+ compatible = "ti,phy-pipe3-sata";
+ reg = <0x4A096000 0x80>, /* phy_rx */
+ <0x4A096400 0x64>, /* phy_tx */
+ <0x4A096800 0x40>; /* pll_ctrl */
+ reg-names = "phy_rx", "phy_tx", "pll_ctrl";
+ ctrl-module = <&omap_control_sata>;
+ clocks = <&sys_clkin1>, <&sata_ref_clk>;
+ clock-names = "sysclk", "refclk";
+ syscon-pllreset = <&scm_conf 0x3fc>;
+ #phy-cells = <0>;
+};
diff --git a/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt b/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt
new file mode 100644
index 0000000..0e6d875
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/qcom,coincell-charger.txt
@@ -0,0 +1,48 @@
+Qualcomm Coincell Charger:
+
+The hardware block controls charging for a coincell or capacitor that is
+used to provide power backup for certain features of the power management
+IC (PMIC)
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: must be: "qcom,pm8941-coincell"
+
+- reg:
+ Usage: required
+ Value type: <u32>
+ Definition: base address of the coincell charger registers
+
+- qcom,rset-ohms:
+ Usage: required
+ Value type: <u32>
+ Definition: resistance (in ohms) for current-limiting resistor
+ must be one of: 800, 1200, 1700, 2100
+
+- qcom,vset-millivolts:
+ Usage: required
+ Value type: <u32>
+ Definition: voltage (in millivolts) to apply for charging
+ must be one of: 2500, 3000, 3100, 3200
+
+- qcom,charger-disable:
+ Usage: optional
+ Value type: <boolean>
+ Definition: definining this property disables charging
+
+This charger is a sub-node of one of the 8941 PMIC blocks, and is specified
+as a child node in DTS of that node. See ../mfd/qcom,spmi-pmic.txt and
+../mfd/qcom-pm8xxx.txt
+
+Example:
+
+ pm8941@0 {
+ coincell@2800 {
+ compatible = "qcom,pm8941-coincell";
+ reg = <0x2800>;
+
+ qcom,rset-ohms = <2100>;
+ qcom,vset-millivolts = <3000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/serial/atmel-usart.txt b/Documentation/devicetree/bindings/serial/atmel-usart.txt
index 90787aa..e6e6142 100644
--- a/Documentation/devicetree/bindings/serial/atmel-usart.txt
+++ b/Documentation/devicetree/bindings/serial/atmel-usart.txt
@@ -22,6 +22,8 @@
memory peripheral interface and USART DMA channel ID, FIFO configuration.
Refer to dma.txt and atmel-dma.txt for details.
- dma-names: "rx" for RX channel, "tx" for TX channel.
+- atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
+ capable USARTs.
<chip> compatible description:
- at91rm9200: legacy USART support
@@ -57,4 +59,5 @@
dmas = <&dma0 2 0x3>,
<&dma0 2 0x204>;
dma-names = "tx", "rx";
+ atmel,fifo-size = <32>;
};
diff --git a/Documentation/devicetree/bindings/serial/axis,etraxfs-uart.txt b/Documentation/devicetree/bindings/serial/axis,etraxfs-uart.txt
index ebcbb62..51b3c9e 100644
--- a/Documentation/devicetree/bindings/serial/axis,etraxfs-uart.txt
+++ b/Documentation/devicetree/bindings/serial/axis,etraxfs-uart.txt
@@ -6,7 +6,7 @@
- interrupts: device interrupt
Optional properties:
-- {dtr,dsr,ri,cd}-gpios: specify a GPIO for DTR/DSR/RI/CD
+- {dtr,dsr,rng,dcd}-gpios: specify a GPIO for DTR/DSR/RI/DCD
line respectively.
Example:
@@ -16,4 +16,8 @@
reg = <0xb0026000 0x1000>;
interrupts = <68>;
status = "disabled";
+ dtr-gpios = <&sysgpio 0 GPIO_ACTIVE_LOW>;
+ dsr-gpios = <&sysgpio 1 GPIO_ACTIVE_LOW>;
+ rng-gpios = <&sysgpio 2 GPIO_ACTIVE_LOW>;
+ dcd-gpios = <&sysgpio 3 GPIO_ACTIVE_LOW>;
};
diff --git a/Documentation/devicetree/bindings/serial/omap_serial.txt b/Documentation/devicetree/bindings/serial/omap_serial.txt
index 54c2a15..7a71b5d 100644
--- a/Documentation/devicetree/bindings/serial/omap_serial.txt
+++ b/Documentation/devicetree/bindings/serial/omap_serial.txt
@@ -4,6 +4,9 @@
- compatible : should be "ti,omap2-uart" for OMAP2 controllers
- compatible : should be "ti,omap3-uart" for OMAP3 controllers
- compatible : should be "ti,omap4-uart" for OMAP4 controllers
+- compatible : should be "ti,am4372-uart" for AM437x controllers
+- compatible : should be "ti,am3352-uart" for AM335x controllers
+- compatible : should be "ti,dra742-uart" for DRA7x controllers
- reg : address and length of the register space
- interrupts or interrupts-extended : Should contain the uart interrupt
specifier or both the interrupt
diff --git a/Documentation/devicetree/bindings/sound/mt8173-max98090.txt b/Documentation/devicetree/bindings/sound/mt8173-max98090.txt
index 829bd26..519e97c 100644
--- a/Documentation/devicetree/bindings/sound/mt8173-max98090.txt
+++ b/Documentation/devicetree/bindings/sound/mt8173-max98090.txt
@@ -3,11 +3,13 @@
Required properties:
- compatible : "mediatek,mt8173-max98090"
- mediatek,audio-codec: the phandle of the MAX98090 audio codec
+- mediatek,platform: the phandle of MT8173 ASoC platform
Example:
sound {
compatible = "mediatek,mt8173-max98090";
mediatek,audio-codec = <&max98090>;
+ mediatek,platform = <&afe>;
};
diff --git a/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt
index 61e98c9..f205ce9 100644
--- a/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt
+++ b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt
@@ -3,11 +3,13 @@
Required properties:
- compatible : "mediatek,mt8173-rt5650-rt5676"
- mediatek,audio-codec: the phandles of rt5650 and rt5676 codecs
+- mediatek,platform: the phandle of MT8173 ASoC platform
Example:
sound {
compatible = "mediatek,mt8173-rt5650-rt5676";
mediatek,audio-codec = <&rt5650 &rt5676>;
+ mediatek,platform = <&afe>;
};
diff --git a/Documentation/devicetree/bindings/spi/spi-ath79.txt b/Documentation/devicetree/bindings/spi/spi-ath79.txt
index f1ad9c3..9c696fa 100644
--- a/Documentation/devicetree/bindings/spi/spi-ath79.txt
+++ b/Documentation/devicetree/bindings/spi/spi-ath79.txt
@@ -3,7 +3,7 @@
Required properties:
- compatible: has to be "qca,<soc-type>-spi", "qca,ar7100-spi" as fallback.
- reg: Base address and size of the controllers memory area
-- clocks: phandle to the AHB clock.
+- clocks: phandle of the AHB clock.
- clock-names: has to be "ahb".
- #address-cells: <1>, as required by generic SPI binding.
- #size-cells: <0>, also as required by generic SPI binding.
@@ -12,9 +12,9 @@
Example:
- spi@1F000000 {
+ spi@1f000000 {
compatible = "qca,ar9132-spi", "qca,ar7100-spi";
- reg = <0x1F000000 0x10>;
+ reg = <0x1f000000 0x10>;
clocks = <&pll 2>;
clock-names = "ahb";
diff --git a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
index 3075377..555fb11 100644
--- a/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
+++ b/Documentation/devicetree/bindings/staging/iio/adc/mxs-lradc.txt
@@ -1,4 +1,4 @@
-* Freescale i.MX28 LRADC device driver
+* Freescale MXS LRADC device driver
Required properties:
- compatible: Should be "fsl,imx23-lradc" for i.MX23 SoC and "fsl,imx28-lradc"
diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
new file mode 100644
index 0000000..862cd7c
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.txt
@@ -0,0 +1,29 @@
+Allwinner sun4i A10 musb DRC/OTG controller
+-------------------------------------------
+
+Required properties:
+ - compatible : "allwinner,sun4i-a10-musb", "allwinner,sun6i-a31-musb"
+ or "allwinner,sun8i-a33-musb"
+ - reg : mmio address range of the musb controller
+ - clocks : clock specifier for the musb controller ahb gate clock
+ - reset : reset specifier for the ahb reset (A31 and newer only)
+ - interrupts : interrupt to which the musb controller is connected
+ - interrupt-names : must be "mc"
+ - phys : phy specifier for the otg phy
+ - phy-names : must be "usb"
+ - dr_mode : Dual-Role mode must be "host" or "otg"
+ - extcon : extcon specifier for the otg phy
+
+Example:
+
+ usb_otg: usb@01c13000 {
+ compatible = "allwinner,sun4i-a10-musb";
+ reg = <0x01c13000 0x0400>;
+ clocks = <&ahb_gates 0>;
+ interrupts = <38>;
+ interrupt-names = "mc";
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ extcon = <&usbphy 0>;
+ status = "disabled";
+ };
diff --git a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
index 553e2fa..d71ef07 100644
--- a/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
+++ b/Documentation/devicetree/bindings/usb/ci-hdrc-usb2.txt
@@ -30,6 +30,21 @@
argument that indicate usb controller index
- disable-over-current: (FSL only) disable over current detect
- external-vbus-divider: (FSL only) enables off-chip resistor divider for Vbus
+- itc-setting: interrupt threshold control register control, the setting
+ should be aligned with ITC bits at register USBCMD.
+- ahb-burst-config: it is vendor dependent, the required value should be
+ aligned with AHBBRST at SBUSCFG, the range is from 0x0 to 0x7. This
+ property is used to change AHB burst configuration, check the chipidea
+ spec for meaning of each value. If this property is not existed, it
+ will use the reset value.
+- tx-burst-size-dword: it is vendor dependent, the tx burst size in dword
+ (4 bytes), This register represents the maximum length of a the burst
+ in 32-bit words while moving data from system memory to the USB
+ bus, changing this value takes effect only the SBUSCFG.AHBBRST is 0.
+- rx-burst-size-dword: it is vendor dependent, the rx burst size in dword
+ (4 bytes), This register represents the maximum length of a the burst
+ in 32-bit words while moving data from the USB bus to system memory,
+ changing this value takes effect only the SBUSCFG.AHBBRST is 0.
Example:
@@ -41,4 +56,9 @@
phys = <&usb_phy0>;
phy-names = "usb-phy";
vbus-supply = <®_usb0_vbus>;
+ gadget-itc-setting = <0x4>; /* 4 micro-frames */
+ /* Incremental burst of unspecified length */
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>; /* 64 bytes */
+ rx-burst-size-dword = <0x10>;
};
diff --git a/Documentation/devicetree/bindings/usb/generic.txt b/Documentation/devicetree/bindings/usb/generic.txt
index 477d5bb..bba8257 100644
--- a/Documentation/devicetree/bindings/usb/generic.txt
+++ b/Documentation/devicetree/bindings/usb/generic.txt
@@ -11,6 +11,19 @@
"peripheral" and "otg". In case this attribute isn't
passed via DT, USB DRD controllers should default to
OTG.
+ - otg-rev: tells usb driver the release number of the OTG and EH supplement
+ with which the device and its descriptors are compliant,
+ in binary-coded decimal (i.e. 2.0 is 0200H). This
+ property is used if any real OTG features(HNP/SRP/ADP)
+ is enabled, if ADP is required, otg-rev should be
+ 0x0200 or above.
+ - hnp-disable: tells OTG controllers we want to disable OTG HNP, normally HNP
+ is the basic function of real OTG except you want it
+ to be a srp-capable only B device.
+ - srp-disable: tells OTG controllers we want to disable OTG SRP, SRP is
+ optional for OTG device.
+ - adp-disable: tells OTG controllers we want to disable OTG ADP, ADP is
+ optional for OTG device.
This is an attribute to a USB controller such as:
@@ -21,4 +34,6 @@
usb-phy = <&usb2_phy>, <&usb3,phy>;
maximum-speed = "super-speed";
dr_mode = "otg";
+ otg-rev = <0x0200>;
+ adp-disable;
};
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index bd8d9e7..8654a3e 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -52,6 +52,10 @@
Optional properties:
- dr_mode: One of "host", "peripheral" or "otg". Defaults to "otg"
+- switch-gpio: A phandle + gpio-specifier pair. Some boards are using Dual
+ SPDT USB Switch, witch is cotrolled by GPIO to de/multiplex
+ D+/D- USB lines between connectors.
+
- qcom,phy-init-sequence: PHY configuration sequence values. This is related to Device
Mode Eye Diagram test. Start address at which these values will be
written is ULPI_EXT_VENDOR_SPECIFIC. Value of -1 is reserved as
diff --git a/Documentation/devicetree/bindings/usb/qcom,usb-8x16-phy.txt b/Documentation/devicetree/bindings/usb/qcom,usb-8x16-phy.txt
new file mode 100644
index 0000000..2cb2168
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/qcom,usb-8x16-phy.txt
@@ -0,0 +1,76 @@
+Qualcomm's APQ8016/MSM8916 USB transceiver controller
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: Should contain "qcom,usb-8x16-phy".
+
+- reg:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: USB PHY base address and length of the register map
+
+- clocks:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: See clock-bindings.txt section "consumers". List of
+ two clock specifiers for interface and core controller
+ clocks.
+
+- clock-names:
+ Usage: required
+ Value type: <string>
+ Definition: Must contain "iface" and "core" strings.
+
+- vddcx-supply:
+ Usage: required
+ Value type: <phandle>
+ Definition: phandle to the regulator VDCCX supply node.
+
+- v1p8-supply:
+ Usage: required
+ Value type: <phandle>
+ Definition: phandle to the regulator 1.8V supply node.
+
+- v3p3-supply:
+ Usage: required
+ Value type: <phandle>
+ Definition: phandle to the regulator 3.3V supply node.
+
+- resets:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: See reset.txt section "consumers". PHY reset specifier.
+
+- reset-names:
+ Usage: required
+ Value type: <string>
+ Definition: Must contain "phy" string.
+
+- switch-gpio:
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: Some boards are using Dual SPDT USB Switch, witch is
+ controlled by GPIO to de/multiplex D+/D- USB lines
+ between connectors.
+
+Example:
+ usb_phy: phy@78d9000 {
+ compatible = "qcom,usb-8x16-phy";
+ reg = <0x78d9000 0x400>;
+
+ vddcx-supply = <&pm8916_s1_corner>;
+ v1p8-supply = <&pm8916_l7>;
+ v3p3-supply = <&pm8916_l13>;
+
+ clocks = <&gcc GCC_USB_HS_AHB_CLK>,
+ <&gcc GCC_USB_HS_SYSTEM_CLK>;
+ clock-names = "iface", "core";
+
+ resets = <&gcc GCC_USB2A_PHY_BCR>;
+ reset-names = "phy";
+
+ // D+/D- lines: 1 - Routed to HUB, 0 - Device connector
+ switch-gpio = <&pm8916_gpios 4 GPIO_ACTIVE_HIGH>;
+ };
+
diff --git a/Documentation/fb/sm712fb.txt b/Documentation/fb/sm712fb.txt
new file mode 100644
index 0000000..c388442
--- /dev/null
+++ b/Documentation/fb/sm712fb.txt
@@ -0,0 +1,31 @@
+What is sm712fb?
+=================
+
+This is a graphics framebuffer driver for Silicon Motion SM712 based processors.
+
+How to use it?
+==============
+
+Switching modes is done using the video=sm712fb:... boot parameter.
+
+If you want, for example, enable a resolution of 1280x1024x24bpp you should
+pass to the kernel this command line: "video=sm712fb:0x31B".
+
+You should not compile-in vesafb.
+
+Currently supported video modes are:
+
+[Graphic modes]
+
+bpp | 640x480 800x600 1024x768 1280x1024
+----+--------------------------------------------
+ 8 | 0x301 0x303 0x305 0x307
+ 16 | 0x311 0x314 0x317 0x31A
+ 24 | 0x312 0x315 0x318 0x31B
+
+Missing Features
+================
+(alias TODO list)
+
+ * 2D acceleratrion
+ * dual-head support
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index b35a64b..9494afb 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -212,7 +212,10 @@
- show() methods should return the number of bytes printed into the
buffer. This is the return value of scnprintf().
-- show() should always use scnprintf().
+- show() must not use snprintf() when formatting the value to be
+ returned to user space. If you can guarantee that an overflow
+ will never happen you can use sprintf() otherwise you must use
+ scnprintf().
- store() should return the number of bytes used from the buffer. If the
entire buffer has been used, just return the count argument.
diff --git a/Documentation/hwmon/nct7904 b/Documentation/hwmon/nct7904
index 014f112..57fffe3 100644
--- a/Documentation/hwmon/nct7904
+++ b/Documentation/hwmon/nct7904
@@ -35,11 +35,11 @@
temp[2-9]_input CPU temperatures (1/1000 degree,
0.125 degree resolution)
-fan[1-4]_mode R/W, 0/1 for manual or SmartFan mode
+pwm[1-4]_enable R/W, 1/2 for manual or SmartFan mode
Setting SmartFan mode is supported only if it has been
previously configured by BIOS (or configuration EEPROM)
-fan[1-4]_pwm R/O in SmartFan mode, R/W in manual control mode
+pwm[1-4] R/O in SmartFan mode, R/W in manual control mode
The driver checks sensor control registers and does not export the sensors
that are not enabled. Anyway, a sensor that is enabled may actually be not
diff --git a/Documentation/input/alps.txt b/Documentation/input/alps.txt
index c86f2f1..1fec113 100644
--- a/Documentation/input/alps.txt
+++ b/Documentation/input/alps.txt
@@ -119,8 +119,10 @@
byte 5: 0 z6 z5 z4 z3 z2 z1 z0
Protocol Version 2 DualPoint devices send standard PS/2 mouse packets for
-the DualPoint Stick. For non interleaved dualpoint devices the pointingstick
-buttons get reported separately in the PSM, PSR and PSL bits.
+the DualPoint Stick. The M, R and L bits signal the combined status of both
+the pointingstick and touchpad buttons, except for Dell dualpoint devices
+where the pointingstick buttons get reported separately in the PSM, PSR
+and PSL bits.
Dualpoint device -- interleaved packet format
---------------------------------------------
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 611c522..141f847 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -124,6 +124,8 @@
'H' 00-7F linux/hiddev.h conflict!
'H' 00-0F linux/hidraw.h conflict!
'H' 01 linux/mei.h conflict!
+'H' 02 linux/mei.h conflict!
+'H' 03 linux/mei.h conflict!
'H' 00-0F sound/asound.h conflict!
'H' 20-40 sound/asound_fm.h conflict!
'H' 80-8F sound/sfnt_info.h conflict!
diff --git a/Documentation/misc-devices/mei/mei.txt b/Documentation/misc-devices/mei/mei.txt
index 8d47501..91c1fa3 100644
--- a/Documentation/misc-devices/mei/mei.txt
+++ b/Documentation/misc-devices/mei/mei.txt
@@ -96,7 +96,7 @@
IOCTL
=====
-The Intel MEI Driver supports the following IOCTL command:
+The Intel MEI Driver supports the following IOCTL commands:
IOCTL_MEI_CONNECT_CLIENT Connect to firmware Feature (client).
usage:
@@ -125,6 +125,49 @@
data that can be sent or received. (e.g. if MTU=2K, can send
requests up to bytes 2k and received responses up to 2k bytes).
+ IOCTL_MEI_NOTIFY_SET: enable or disable event notifications
+
+ Usage:
+ uint32_t enable;
+ ioctl(fd, IOCTL_MEI_NOTIFY_SET, &enable);
+
+ Inputs:
+ uint32_t enable = 1;
+ or
+ uint32_t enable[disable] = 0;
+
+ Error returns:
+ EINVAL Wrong IOCTL Number
+ ENODEV Device is not initialized or the client not connected
+ ENOMEM Unable to allocate memory to client internal data.
+ EFAULT Fatal Error (e.g. Unable to access user input data)
+ EOPNOTSUPP if the device doesn't support the feature
+
+ Notes:
+ The client must be connected in order to enable notification events
+
+
+ IOCTL_MEI_NOTIFY_GET : retrieve event
+
+ Usage:
+ uint32_t event;
+ ioctl(fd, IOCTL_MEI_NOTIFY_GET, &event);
+
+ Outputs:
+ 1 - if an event is pending
+ 0 - if there is no even pending
+
+ Error returns:
+ EINVAL Wrong IOCTL Number
+ ENODEV Device is not initialized or the client not connected
+ ENOMEM Unable to allocate memory to client internal data.
+ EFAULT Fatal Error (e.g. Unable to access user input data)
+ EOPNOTSUPP if the device doesn't support the feature
+
+ Notes:
+ The client must be connected and event notification has to be enabled
+ in order to receive an event
+
Intel ME Applications
=====================
diff --git a/Documentation/nvmem/nvmem.txt b/Documentation/nvmem/nvmem.txt
new file mode 100644
index 0000000..dbd40d8
--- /dev/null
+++ b/Documentation/nvmem/nvmem.txt
@@ -0,0 +1,152 @@
+ NVMEM SUBSYSTEM
+ Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+This document explains the NVMEM Framework along with the APIs provided,
+and how to use it.
+
+1. Introduction
+===============
+*NVMEM* is the abbreviation for Non Volatile Memory layer. It is used to
+retrieve configuration of SOC or Device specific data from non volatile
+memories like eeprom, efuses and so on.
+
+Before this framework existed, NVMEM drivers like eeprom were stored in
+drivers/misc, where they all had to duplicate pretty much the same code to
+register a sysfs file, allow in-kernel users to access the content of the
+devices they were driving, etc.
+
+This was also a problem as far as other in-kernel users were involved, since
+the solutions used were pretty much different from one driver to another, there
+was a rather big abstraction leak.
+
+This framework aims at solve these problems. It also introduces DT
+representation for consumer devices to go get the data they require (MAC
+Addresses, SoC/Revision ID, part numbers, and so on) from the NVMEMs. This
+framework is based on regmap, so that most of the abstraction available in
+regmap can be reused, across multiple types of buses.
+
+NVMEM Providers
++++++++++++++++
+
+NVMEM provider refers to an entity that implements methods to initialize, read
+and write the non-volatile memory.
+
+2. Registering/Unregistering the NVMEM provider
+===============================================
+
+A NVMEM provider can register with NVMEM core by supplying relevant
+nvmem configuration to nvmem_register(), on success core would return a valid
+nvmem_device pointer.
+
+nvmem_unregister(nvmem) is used to unregister a previously registered provider.
+
+For example, a simple qfprom case:
+
+static struct nvmem_config econfig = {
+ .name = "qfprom",
+ .owner = THIS_MODULE,
+};
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+ ...
+ econfig.dev = &pdev->dev;
+ nvmem = nvmem_register(&econfig);
+ ...
+}
+
+It is mandatory that the NVMEM provider has a regmap associated with its
+struct device. Failure to do would return error code from nvmem_register().
+
+NVMEM Consumers
++++++++++++++++
+
+NVMEM consumers are the entities which make use of the NVMEM provider to
+read from and to NVMEM.
+
+3. NVMEM cell based consumer APIs
+=================================
+
+NVMEM cells are the data entries/fields in the NVMEM.
+The NVMEM framework provides 3 APIs to read/write NVMEM cells.
+
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+
+void *nvmem_cell_read(struct nvmem_cell *cell, ssize_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, ssize_t len);
+
+*nvmem_cell_get() apis will get a reference to nvmem cell for a given id,
+and nvmem_cell_read/write() can then read or write to the cell.
+Once the usage of the cell is finished the consumer should call *nvmem_cell_put()
+to free all the allocation memory for the cell.
+
+4. Direct NVMEM device based consumer APIs
+==========================================
+
+In some instances it is necessary to directly read/write the NVMEM.
+To facilitate such consumers NVMEM framework provides below apis.
+
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+ const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+ size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+ size_t bytes, void *buf);
+int nvmem_device_cell_read(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf);
+
+Before the consumers can read/write NVMEM directly, it should get hold
+of nvmem_controller from one of the *nvmem_device_get() api.
+
+The difference between these apis and cell based apis is that these apis always
+take nvmem_device as parameter.
+
+5. Releasing a reference to the NVMEM
+=====================================
+
+When a consumers no longer needs the NVMEM, it has to release the reference
+to the NVMEM it has obtained using the APIs mentioned in the above section.
+The NVMEM framework provides 2 APIs to release a reference to the NVMEM.
+
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+
+Both these APIs are used to release a reference to the NVMEM and
+devm_nvmem_cell_put and devm_nvmem_device_put destroys the devres associated
+with this NVMEM.
+
+Userspace
++++++++++
+
+6. Userspace binary interface
+==============================
+
+Userspace can read/write the raw NVMEM file located at
+/sys/bus/nvmem/devices/*/nvmem
+
+ex:
+
+hexdump /sys/bus/nvmem/devices/qfprom0/nvmem
+
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+*
+00000a0 db10 2240 0000 e000 0c00 0c00 0000 0c00
+0000000 0000 0000 0000 0000 0000 0000 0000 0000
+...
+*
+0001000
+
+7. DeviceTree Binding
+=====================
+
+See Documentation/devicetree/bindings/nvmem/nvmem.txt
diff --git a/Documentation/power/suspend-and-cpuhotplug.txt b/Documentation/power/suspend-and-cpuhotplug.txt
index 2850df3..2fc9095 100644
--- a/Documentation/power/suspend-and-cpuhotplug.txt
+++ b/Documentation/power/suspend-and-cpuhotplug.txt
@@ -72,7 +72,7 @@
|
v
Disable regular cpu hotplug
- by setting cpu_hotplug_disabled=1
+ by increasing cpu_hotplug_disabled
|
v
Release cpu_add_remove_lock
@@ -89,7 +89,7 @@
execution during resume):
* enable_nonboot_cpus() which involves:
| Acquire cpu_add_remove_lock
- | Reset cpu_hotplug_disabled to 0, thereby enabling regular cpu hotplug
+ | Decrease cpu_hotplug_disabled, thereby enabling regular cpu hotplug
| Call _cpu_up() [for all those cpus in the frozen_cpus mask, in a loop]
| Release cpu_add_remove_lock
v
@@ -120,7 +120,7 @@
Acquire cpu_add_remove_lock
|
v
- If cpu_hotplug_disabled is 1
+ If cpu_hotplug_disabled > 0
return gracefully
|
|
diff --git a/Documentation/s390/00-INDEX b/Documentation/s390/00-INDEX
index 10c874e..9189535 100644
--- a/Documentation/s390/00-INDEX
+++ b/Documentation/s390/00-INDEX
@@ -16,8 +16,6 @@
- hints for debugging on s390 systems.
driver-model.txt
- information on s390 devices and the driver model.
-kvm.txt
- - ioctl calls to /dev/kvm on s390.
monreader.txt
- information on accessing the z/VM monitor stream from Linux.
qeth.txt
diff --git a/Documentation/s390/kvm.txt b/Documentation/s390/kvm.txt
deleted file mode 100644
index 85f3280..0000000
--- a/Documentation/s390/kvm.txt
+++ /dev/null
@@ -1,125 +0,0 @@
-*** BIG FAT WARNING ***
-The kvm module is currently in EXPERIMENTAL state for s390. This means that
-the interface to the module is not yet considered to remain stable. Thus, be
-prepared that we keep breaking your userspace application and guest
-compatibility over and over again until we feel happy with the result. Make sure
-your guest kernel, your host kernel, and your userspace launcher are in a
-consistent state.
-
-This Documentation describes the unique ioctl calls to /dev/kvm, the resulting
-kvm-vm file descriptors, and the kvm-vcpu file descriptors that differ from x86.
-
-1. ioctl calls to /dev/kvm
-KVM does support the following ioctls on s390 that are common with other
-architectures and do behave the same:
-KVM_GET_API_VERSION
-KVM_CREATE_VM (*) see note
-KVM_CHECK_EXTENSION
-KVM_GET_VCPU_MMAP_SIZE
-
-Notes:
-* KVM_CREATE_VM may fail on s390, if the calling process has multiple
-threads and has not called KVM_S390_ENABLE_SIE before.
-
-In addition, on s390 the following architecture specific ioctls are supported:
-ioctl: KVM_S390_ENABLE_SIE
-args: none
-see also: include/linux/kvm.h
-This call causes the kernel to switch on PGSTE in the user page table. This
-operation is needed in order to run a virtual machine, and it requires the
-calling process to be single-threaded. Note that the first call to KVM_CREATE_VM
-will implicitly try to switch on PGSTE if the user process has not called
-KVM_S390_ENABLE_SIE before. User processes that want to launch multiple threads
-before creating a virtual machine have to call KVM_S390_ENABLE_SIE, or will
-observe an error calling KVM_CREATE_VM. Switching on PGSTE is a one-time
-operation, is not reversible, and will persist over the entire lifetime of
-the calling process. It does not have any user-visible effect other than a small
-performance penalty.
-
-2. ioctl calls to the kvm-vm file descriptor
-KVM does support the following ioctls on s390 that are common with other
-architectures and do behave the same:
-KVM_CREATE_VCPU
-KVM_SET_USER_MEMORY_REGION (*) see note
-KVM_GET_DIRTY_LOG (**) see note
-
-Notes:
-* kvm does only allow exactly one memory slot on s390, which has to start
- at guest absolute address zero and at a user address that is aligned on any
- page boundary. This hardware "limitation" allows us to have a few unique
- optimizations. The memory slot doesn't have to be filled
- with memory actually, it may contain sparse holes. That said, with different
- user memory layout this does still allow a large flexibility when
- doing the guest memory setup.
-** KVM_GET_DIRTY_LOG doesn't work properly yet. The user will receive an empty
-log. This ioctl call is only needed for guest migration, and we intend to
-implement this one in the future.
-
-In addition, on s390 the following architecture specific ioctls for the kvm-vm
-file descriptor are supported:
-ioctl: KVM_S390_INTERRUPT
-args: struct kvm_s390_interrupt *
-see also: include/linux/kvm.h
-This ioctl is used to submit a floating interrupt for a virtual machine.
-Floating interrupts may be delivered to any virtual cpu in the configuration.
-Only some interrupt types defined in include/linux/kvm.h make sense when
-submitted as floating interrupts. The following interrupts are not considered
-to be useful as floating interrupts, and a call to inject them will result in
--EINVAL error code: program interrupts and interprocessor signals. Valid
-floating interrupts are:
-KVM_S390_INT_VIRTIO
-KVM_S390_INT_SERVICE
-
-3. ioctl calls to the kvm-vcpu file descriptor
-KVM does support the following ioctls on s390 that are common with other
-architectures and do behave the same:
-KVM_RUN
-KVM_GET_REGS
-KVM_SET_REGS
-KVM_GET_SREGS
-KVM_SET_SREGS
-KVM_GET_FPU
-KVM_SET_FPU
-
-In addition, on s390 the following architecture specific ioctls for the
-kvm-vcpu file descriptor are supported:
-ioctl: KVM_S390_INTERRUPT
-args: struct kvm_s390_interrupt *
-see also: include/linux/kvm.h
-This ioctl is used to submit an interrupt for a specific virtual cpu.
-Only some interrupt types defined in include/linux/kvm.h make sense when
-submitted for a specific cpu. The following interrupts are not considered
-to be useful, and a call to inject them will result in -EINVAL error code:
-service processor calls and virtio interrupts. Valid interrupt types are:
-KVM_S390_PROGRAM_INT
-KVM_S390_SIGP_STOP
-KVM_S390_RESTART
-KVM_S390_SIGP_SET_PREFIX
-KVM_S390_INT_EMERGENCY
-
-ioctl: KVM_S390_STORE_STATUS
-args: unsigned long
-see also: include/linux/kvm.h
-This ioctl stores the state of the cpu at the guest real address given as
-argument, unless one of the following values defined in include/linux/kvm.h
-is given as argument:
-KVM_S390_STORE_STATUS_NOADDR - the CPU stores its status to the save area in
-absolute lowcore as defined by the principles of operation
-KVM_S390_STORE_STATUS_PREFIXED - the CPU stores its status to the save area in
-its prefix page just like the dump tool that comes with zipl. This is useful
-to create a system dump for use with lkcdutils or crash.
-
-ioctl: KVM_S390_SET_INITIAL_PSW
-args: struct kvm_s390_psw *
-see also: include/linux/kvm.h
-This ioctl can be used to set the processor status word (psw) of a stopped cpu
-prior to running it with KVM_RUN. Note that this call is not required to modify
-the psw during sie intercepts that fall back to userspace because struct kvm_run
-does contain the psw, and this value is evaluated during reentry of KVM_RUN
-after the intercept exit was recognized.
-
-ioctl: KVM_S390_INITIAL_RESET
-args: none
-see also: include/linux/kvm.h
-This ioctl can be used to perform an initial cpu reset as defined by the
-principles of operation. The target cpu has to be in stopped state.
diff --git a/Documentation/target/tcm_mod_builder.py b/Documentation/target/tcm_mod_builder.py
index 949de19..cda56df 100755
--- a/Documentation/target/tcm_mod_builder.py
+++ b/Documentation/target/tcm_mod_builder.py
@@ -199,7 +199,8 @@
buf += "#include <linux/string.h>\n"
buf += "#include <linux/configfs.h>\n"
buf += "#include <linux/ctype.h>\n"
- buf += "#include <asm/unaligned.h>\n\n"
+ buf += "#include <asm/unaligned.h>\n"
+ buf += "#include <scsi/scsi_proto.h>\n\n"
buf += "#include <target/target_core_base.h>\n"
buf += "#include <target/target_core_fabric.h>\n"
buf += "#include <target/target_core_fabric_configfs.h>\n"
@@ -230,8 +231,14 @@
buf += " }\n"
buf += " tpg->" + fabric_mod_port + " = " + fabric_mod_port + ";\n"
buf += " tpg->" + fabric_mod_port + "_tpgt = tpgt;\n\n"
- buf += " ret = core_tpg_register(&" + fabric_mod_name + "_ops, wwn,\n"
- buf += " &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n"
+
+ if proto_ident == "FC":
+ buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_FCP);\n"
+ elif proto_ident == "SAS":
+ buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_SAS);\n"
+ elif proto_ident == "iSCSI":
+ buf += " ret = core_tpg_register(wwn, &tpg->se_tpg, SCSI_PROTOCOL_ISCSI);\n"
+
buf += " if (ret < 0) {\n"
buf += " kfree(tpg);\n"
buf += " return NULL;\n"
@@ -292,7 +299,7 @@
buf += "static const struct target_core_fabric_ops " + fabric_mod_name + "_ops = {\n"
buf += " .module = THIS_MODULE,\n"
- buf += " .name = " + fabric_mod_name + ",\n"
+ buf += " .name = \"" + fabric_mod_name + "\",\n"
buf += " .get_fabric_name = " + fabric_mod_name + "_get_fabric_name,\n"
buf += " .tpg_get_wwn = " + fabric_mod_name + "_get_fabric_wwn,\n"
buf += " .tpg_get_tag = " + fabric_mod_name + "_get_tag,\n"
@@ -322,17 +329,17 @@
buf += " .fabric_make_tpg = " + fabric_mod_name + "_make_tpg,\n"
buf += " .fabric_drop_tpg = " + fabric_mod_name + "_drop_tpg,\n"
buf += "\n"
- buf += " .tfc_wwn_attrs = " + fabric_mod_name + "_wwn_attrs;\n"
+ buf += " .tfc_wwn_attrs = " + fabric_mod_name + "_wwn_attrs,\n"
buf += "};\n\n"
buf += "static int __init " + fabric_mod_name + "_init(void)\n"
buf += "{\n"
- buf += " return target_register_template(" + fabric_mod_name + "_ops);\n"
+ buf += " return target_register_template(&" + fabric_mod_name + "_ops);\n"
buf += "};\n\n"
buf += "static void __exit " + fabric_mod_name + "_exit(void)\n"
buf += "{\n"
- buf += " target_unregister_template(" + fabric_mod_name + "_ops);\n"
+ buf += " target_unregister_template(&" + fabric_mod_name + "_ops);\n"
buf += "};\n\n"
buf += "MODULE_DESCRIPTION(\"" + fabric_mod_name.upper() + " series fabric driver\");\n"
diff --git a/Documentation/trace/coresight.txt b/Documentation/trace/coresight.txt
index 77d14d5..0a5c329 100644
--- a/Documentation/trace/coresight.txt
+++ b/Documentation/trace/coresight.txt
@@ -15,7 +15,7 @@
that have many SoCs and other components like GPU and DMA engines. ARM has
developed a HW assisted tracing solution by means of different components, each
being added to a design at synthesis time to cater to specific tracing needs.
-Compoments are generally categorised as source, link and sinks and are
+Components are generally categorised as source, link and sinks and are
(usually) discovered using the AMBA bus.
"Sources" generate a compressed stream representing the processor instruction
@@ -138,7 +138,7 @@
The registering function is taking a "struct coresight_device *csdev" and
register the device with the core framework. The unregister function takes
-a reference to a "strut coresight_device", obtained at registration time.
+a reference to a "struct coresight_device", obtained at registration time.
If everything goes well during the registration process the new devices will
show up under /sys/bus/coresight/devices, as showns here for a TC2 platform:
diff --git a/Documentation/usb/gadget-testing.txt b/Documentation/usb/gadget-testing.txt
index 5926780..b24d3ef 100644
--- a/Documentation/usb/gadget-testing.txt
+++ b/Documentation/usb/gadget-testing.txt
@@ -237,9 +237,7 @@
-----------------------------
device: run the gadget
-host: test-usb
-
-http://www.linux-usb.org/usbtest/testusb.c
+host: test-usb (tools/usb/testusb.c)
8. MASS STORAGE function
========================
@@ -586,9 +584,8 @@
-------------------------------
device: run the gadget
-host: test-usb
+host: test-usb (tools/usb/testusb.c)
-http://www.linux-usb.org/usbtest/testusb.c
16. UAC1 function
=================
diff --git a/Documentation/usb/power-management.txt b/Documentation/usb/power-management.txt
index b5f8391..4a15c90 100644
--- a/Documentation/usb/power-management.txt
+++ b/Documentation/usb/power-management.txt
@@ -521,10 +521,10 @@
lower power state(L1 for usb2.0 devices, or U1/U2 for usb3.0 devices),
which state device can enter and resume very quickly.
-The user interface for controlling USB2 hardware LPM is located in the
+The user interface for controlling hardware LPM is located in the
power/ subdirectory of each USB device's sysfs directory, that is, in
/sys/bus/usb/devices/.../power/ where "..." is the device's ID. The
-relevant attribute files is usb2_hardware_lpm.
+relevant attribute files are usb2_hardware_lpm and usb3_hardware_lpm.
power/usb2_hardware_lpm
@@ -537,6 +537,17 @@
can write y/Y/1 or n/N/0 to the file to enable/disable
USB2 hardware LPM manually. This is for test purpose mainly.
+ power/usb3_hardware_lpm
+
+ When a USB 3.0 lpm-capable device is plugged in to a
+ xHCI host which supports link PM, it will check if U1
+ and U2 exit latencies have been set in the BOS
+ descriptor; if the check is is passed and the host
+ supports USB3 hardware LPM, USB3 hardware LPM will be
+ enabled for the device and this file will be created.
+ The file holds a string value (enable or disable)
+ indicating whether or not USB3 hardware LPM is
+ enabled for the device.
USB Port Power Control
----------------------
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index a7926a9..a4ebcb7 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -3277,6 +3277,7 @@
struct {
#define KVM_SYSTEM_EVENT_SHUTDOWN 1
#define KVM_SYSTEM_EVENT_RESET 2
+#define KVM_SYSTEM_EVENT_CRASH 3
__u32 type;
__u64 flags;
} system_event;
@@ -3296,6 +3297,10 @@
KVM_SYSTEM_EVENT_RESET -- the guest has requested a reset of the VM.
As with SHUTDOWN, userspace can choose to ignore the request, or
to schedule the reset to occur in the future and may call KVM_RUN again.
+ KVM_SYSTEM_EVENT_CRASH -- the guest crash occurred and the guest
+ has requested a crash condition maintenance. Userspace can choose
+ to ignore the request, or to gather VM memory core dump and/or
+ reset/shutdown of the VM.
/* Fix the size of the union. */
char padding[256];
diff --git a/MAINTAINERS b/MAINTAINERS
index 8424d58..8b3115c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3587,6 +3587,15 @@
F: drivers/gpu/drm/rockchip/
F: Documentation/devicetree/bindings/video/rockchip*
+DRM DRIVERS FOR STI
+M: Benjamin Gaignard <benjamin.gaignard@linaro.org>
+M: Vincent Abriou <vincent.abriou@st.com>
+L: dri-devel@lists.freedesktop.org
+T: git http://git.linaro.org/people/benjamin.gaignard/kernel.git
+S: Maintained
+F: drivers/gpu/drm/sti
+F: Documentation/devicetree/bindings/gpu/st,stih4xx.txt
+
DSBR100 USB FM RADIO DRIVER
M: Alexey Klimov <klimov.linux@gmail.com>
L: linux-media@vger.kernel.org
@@ -4957,6 +4966,7 @@
F: drivers/video/fbdev/hyperv_fb.c
F: include/linux/hyperv.h
F: tools/hv/
+F: Documentation/ABI/stable/sysfs-bus-vmbus
I2C OVER PARALLEL PORT
M: Jean Delvare <jdelvare@suse.com>
@@ -5600,6 +5610,7 @@
IRQCHIP DRIVERS
M: Thomas Gleixner <tglx@linutronix.de>
M: Jason Cooper <jason@lakedaemon.net>
+M: Marc Zyngier <marc.zyngier@arm.com>
L: linux-kernel@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
@@ -5608,11 +5619,14 @@
F: drivers/irqchip/
IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
-M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+M: Jiang Liu <jiang.liu@linux.intel.com>
+M: Marc Zyngier <marc.zyngier@arm.com>
S: Maintained
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
F: Documentation/IRQ-domain.txt
F: include/linux/irqdomain.h
F: kernel/irq/irqdomain.c
+F: kernel/irq/msi.c
ISAPNP
M: Jaroslav Kysela <perex@perex.cz>
@@ -5836,6 +5850,7 @@
KERNEL NFSD, SUNRPC, AND LOCKD SERVERS
M: "J. Bruce Fields" <bfields@fieldses.org>
+M: Jeff Layton <jlayton@poochiereds.net>
L: linux-nfs@vger.kernel.org
W: http://nfs.sourceforge.net/
S: Supported
@@ -5898,7 +5913,6 @@
F: Documentation/s390/kvm.txt
F: arch/s390/include/asm/kvm*
F: arch/s390/kvm/
-F: drivers/s390/kvm/
KERNEL VIRTUAL MACHINE (KVM) FOR ARM
M: Christoffer Dall <christoffer.dall@linaro.org>
@@ -6838,6 +6852,12 @@
S: Maintained
F: drivers/media/usb/msi2500/
+MSYSTEMS DISKONCHIP G3 MTD DRIVER
+M: Robert Jarzmik <robert.jarzmik@free.fr>
+L: linux-mtd@lists.infradead.org
+S: Maintained
+F: drivers/mtd/devices/docg3*
+
MT9M032 APTINA SENSOR DRIVER
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
@@ -7278,6 +7298,15 @@
F: drivers/block/nvme*
F: include/linux/nvme.h
+NVMEM FRAMEWORK
+M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+M: Maxime Ripard <maxime.ripard@free-electrons.com>
+S: Maintained
+F: drivers/nvmem/
+F: Documentation/devicetree/bindings/nvmem/
+F: include/linux/nvmem-consumer.h
+F: include/linux/nvmem-provider.h
+
NXP-NCI NFC DRIVER
M: Clément Perrochaud <clement.perrochaud@effinnov.com>
R: Charles Gorand <charles.gorand@effinnov.com>
@@ -9313,6 +9342,15 @@
F: drivers/media/i2c/ov2659.c
F: include/media/ov2659.h
+SILICON MOTION SM712 FRAME BUFFER DRIVER
+M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+M: Teddy Wang <teddy.wang@siliconmotion.com>
+M: Sudip Mukherjee <sudip@vectorindia.org>
+L: linux-fbdev@vger.kernel.org
+S: Maintained
+F: drivers/video/fbdev/sm712*
+F: Documentation/fb/sm712fb.txt
+
SIS 190 ETHERNET DRIVER
M: Francois Romieu <romieu@fr.zoreil.com>
L: netdev@vger.kernel.org
@@ -9710,11 +9748,6 @@
S: Maintained
F: drivers/staging/olpc_dcon/
-STAGING - OZMO DEVICES USB OVER WIFI DRIVER
-M: Shigekatsu Tateno <shigekatsu.tateno@atmel.com>
-S: Maintained
-F: drivers/staging/ozwpan/
-
STAGING - PARALLEL LCD/KEYPAD PANEL DRIVER
M: Willy Tarreau <willy@meta-x.org>
S: Odd Fixes
@@ -9733,14 +9766,6 @@
S: Maintained
F: drivers/staging/rtl8723au/
-STAGING - SILICON MOTION SM7XX FRAME BUFFER DRIVER
-M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
-M: Teddy Wang <teddy.wang@siliconmotion.com>
-M: Sudip Mukherjee <sudip@vectorindia.org>
-L: linux-fbdev@vger.kernel.org
-S: Maintained
-F: drivers/staging/sm7xxfb/
-
STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER
M: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
M: Teddy Wang <teddy.wang@siliconmotion.com>
@@ -10890,6 +10915,15 @@
F: include/linux/virtio_*.h
F: include/uapi/linux/virtio_*.h
+VIRTIO DRIVERS FOR S390
+M: Christian Borntraeger <borntraeger@de.ibm.com>
+M: Cornelia Huck <cornelia.huck@de.ibm.com>
+L: linux-s390@vger.kernel.org
+L: virtualization@lists.linux-foundation.org
+L: kvm@vger.kernel.org
+S: Supported
+F: drivers/s390/virtio/
+
VIRTIO GPU DRIVER
M: David Airlie <airlied@linux.ie>
M: Gerd Hoffmann <kraxel@redhat.com>
diff --git a/Makefile b/Makefile
index a9ad490..c361593 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 4
PATCHLEVEL = 2
SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION =
NAME = Hurr durr I'ma sheep
# *DOCUMENTATION*
@@ -597,6 +597,11 @@
# Defaults to vmlinux, but the arch makefile usually adds further targets
all: vmlinux
+# The arch Makefile can set ARCH_{CPP,A,C}FLAGS to override the default
+# values of the respective KBUILD_* variables
+ARCH_CPPFLAGS :=
+ARCH_AFLAGS :=
+ARCH_CFLAGS :=
include arch/$(SRCARCH)/Makefile
KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,)
@@ -848,10 +853,10 @@
mod_compress_cmd = true
ifdef CONFIG_MODULE_COMPRESS
ifdef CONFIG_MODULE_COMPRESS_GZIP
- mod_compress_cmd = gzip -n
+ mod_compress_cmd = gzip -n -f
endif # CONFIG_MODULE_COMPRESS_GZIP
ifdef CONFIG_MODULE_COMPRESS_XZ
- mod_compress_cmd = xz
+ mod_compress_cmd = xz -f
endif # CONFIG_MODULE_COMPRESS_XZ
endif # CONFIG_MODULE_COMPRESS
export mod_compress_cmd
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index bf9e9d3..f515a4d 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -3,6 +3,7 @@
default y
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
+ select ARCH_USE_CMPXCHG_LOCKREF
select HAVE_AOUT
select HAVE_IDE
select HAVE_OPROFILE
diff --git a/arch/alpha/include/asm/spinlock.h b/arch/alpha/include/asm/spinlock.h
index 37b570d..fed9c6f 100644
--- a/arch/alpha/include/asm/spinlock.h
+++ b/arch/alpha/include/asm/spinlock.h
@@ -16,6 +16,11 @@
#define arch_spin_unlock_wait(x) \
do { cpu_relax(); } while ((x)->lock)
+static inline int arch_spin_value_unlocked(arch_spinlock_t lock)
+{
+ return lock.lock == 0;
+}
+
static inline void arch_spin_unlock(arch_spinlock_t * lock)
{
mb();
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 91cf405..bd4670d 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -313,11 +313,11 @@
config ARC_PAGE_SIZE_16K
bool "16KB"
- depends on ARC_MMU_V3
+ depends on ARC_MMU_V3 || ARC_MMU_V4
config ARC_PAGE_SIZE_4K
bool "4KB"
- depends on ARC_MMU_V3
+ depends on ARC_MMU_V3 || ARC_MMU_V4
endchoice
@@ -365,6 +365,11 @@
default y
depends on !ARC_CANT_LLSC
+config ARC_STAR_9000923308
+ bool "Workaround for llock/scond livelock"
+ default y
+ depends on ISA_ARCV2 && SMP && ARC_HAS_LLSC
+
config ARC_HAS_SWAPE
bool "Insn: SWAPE (endian-swap)"
default y
@@ -379,6 +384,10 @@
dest operands with 2 possible source operands.
default y
+config ARC_HAS_DIV_REM
+ bool "Insn: div, divu, rem, remu"
+ default y
+
config ARC_HAS_RTC
bool "Local 64-bit r/o cycle counter"
default n
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index 46d8731..8a27a48 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -36,8 +36,16 @@
cflags-$(CONFIG_ARC_HAS_LLSC) += -mlock
cflags-$(CONFIG_ARC_HAS_SWAPE) += -mswape
+ifdef CONFIG_ISA_ARCV2
+
ifndef CONFIG_ARC_HAS_LL64
-cflags-$(CONFIG_ISA_ARCV2) += -mno-ll64
+cflags-y += -mno-ll64
+endif
+
+ifndef CONFIG_ARC_HAS_DIV_REM
+cflags-y += -mno-div-rem
+endif
+
endif
cflags-$(CONFIG_ARC_DW2_UNWIND) += -fasynchronous-unwind-tables
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 070f588..c8f57b8 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -89,11 +89,10 @@
#define ECR_C_BIT_DTLB_LD_MISS 8
#define ECR_C_BIT_DTLB_ST_MISS 9
-
/* Auxiliary registers */
#define AUX_IDENTITY 4
#define AUX_INTR_VEC_BASE 0x25
-
+#define AUX_NON_VOL 0x5e
/*
* Floating Pt Registers
@@ -240,9 +239,9 @@
struct bcr_perip {
#ifdef CONFIG_CPU_BIG_ENDIAN
- unsigned int start:8, pad2:8, sz:8, pad:8;
+ unsigned int start:8, pad2:8, sz:8, ver:8;
#else
- unsigned int pad:8, sz:8, pad2:8, start:8;
+ unsigned int ver:8, sz:8, pad2:8, start:8;
#endif
};
diff --git a/arch/arc/include/asm/atomic.h b/arch/arc/include/asm/atomic.h
index 03484cb..87d18ae 100644
--- a/arch/arc/include/asm/atomic.h
+++ b/arch/arc/include/asm/atomic.h
@@ -23,33 +23,60 @@
#define atomic_set(v, i) (((v)->counter) = (i))
-#ifdef CONFIG_ISA_ARCV2
-#define PREFETCHW " prefetchw [%1] \n"
-#else
-#define PREFETCHW
+#ifdef CONFIG_ARC_STAR_9000923308
+
+#define SCOND_FAIL_RETRY_VAR_DEF \
+ unsigned int delay = 1, tmp; \
+
+#define SCOND_FAIL_RETRY_ASM \
+ " bz 4f \n" \
+ " ; --- scond fail delay --- \n" \
+ " mov %[tmp], %[delay] \n" /* tmp = delay */ \
+ "2: brne.d %[tmp], 0, 2b \n" /* while (tmp != 0) */ \
+ " sub %[tmp], %[tmp], 1 \n" /* tmp-- */ \
+ " rol %[delay], %[delay] \n" /* delay *= 2 */ \
+ " b 1b \n" /* start over */ \
+ "4: ; --- success --- \n" \
+
+#define SCOND_FAIL_RETRY_VARS \
+ ,[delay] "+&r" (delay),[tmp] "=&r" (tmp) \
+
+#else /* !CONFIG_ARC_STAR_9000923308 */
+
+#define SCOND_FAIL_RETRY_VAR_DEF
+
+#define SCOND_FAIL_RETRY_ASM \
+ " bnz 1b \n" \
+
+#define SCOND_FAIL_RETRY_VARS
+
#endif
#define ATOMIC_OP(op, c_op, asm_op) \
static inline void atomic_##op(int i, atomic_t *v) \
{ \
- unsigned int temp; \
+ unsigned int val; \
+ SCOND_FAIL_RETRY_VAR_DEF \
\
__asm__ __volatile__( \
- "1: \n" \
- PREFETCHW \
- " llock %0, [%1] \n" \
- " " #asm_op " %0, %0, %2 \n" \
- " scond %0, [%1] \n" \
- " bnz 1b \n" \
- : "=&r"(temp) /* Early clobber, to prevent reg reuse */ \
- : "r"(&v->counter), "ir"(i) \
+ "1: llock %[val], [%[ctr]] \n" \
+ " " #asm_op " %[val], %[val], %[i] \n" \
+ " scond %[val], [%[ctr]] \n" \
+ " \n" \
+ SCOND_FAIL_RETRY_ASM \
+ \
+ : [val] "=&r" (val) /* Early clobber to prevent reg reuse */ \
+ SCOND_FAIL_RETRY_VARS \
+ : [ctr] "r" (&v->counter), /* Not "m": llock only supports reg direct addr mode */ \
+ [i] "ir" (i) \
: "cc"); \
} \
#define ATOMIC_OP_RETURN(op, c_op, asm_op) \
static inline int atomic_##op##_return(int i, atomic_t *v) \
{ \
- unsigned int temp; \
+ unsigned int val; \
+ SCOND_FAIL_RETRY_VAR_DEF \
\
/* \
* Explicit full memory barrier needed before/after as \
@@ -58,19 +85,21 @@
smp_mb(); \
\
__asm__ __volatile__( \
- "1: \n" \
- PREFETCHW \
- " llock %0, [%1] \n" \
- " " #asm_op " %0, %0, %2 \n" \
- " scond %0, [%1] \n" \
- " bnz 1b \n" \
- : "=&r"(temp) \
- : "r"(&v->counter), "ir"(i) \
+ "1: llock %[val], [%[ctr]] \n" \
+ " " #asm_op " %[val], %[val], %[i] \n" \
+ " scond %[val], [%[ctr]] \n" \
+ " \n" \
+ SCOND_FAIL_RETRY_ASM \
+ \
+ : [val] "=&r" (val) \
+ SCOND_FAIL_RETRY_VARS \
+ : [ctr] "r" (&v->counter), \
+ [i] "ir" (i) \
: "cc"); \
\
smp_mb(); \
\
- return temp; \
+ return val; \
}
#else /* !CONFIG_ARC_HAS_LLSC */
@@ -150,6 +179,9 @@
#undef ATOMIC_OPS
#undef ATOMIC_OP_RETURN
#undef ATOMIC_OP
+#undef SCOND_FAIL_RETRY_VAR_DEF
+#undef SCOND_FAIL_RETRY_ASM
+#undef SCOND_FAIL_RETRY_VARS
/**
* __atomic_add_unless - add unless the number is a given value
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 91694ec..69095da 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -20,20 +20,20 @@
struct pt_regs {
/* Real registers */
- long bta; /* bta_l1, bta_l2, erbta */
+ unsigned long bta; /* bta_l1, bta_l2, erbta */
- long lp_start, lp_end, lp_count;
+ unsigned long lp_start, lp_end, lp_count;
- long status32; /* status32_l1, status32_l2, erstatus */
- long ret; /* ilink1, ilink2 or eret */
- long blink;
- long fp;
- long r26; /* gp */
+ unsigned long status32; /* status32_l1, status32_l2, erstatus */
+ unsigned long ret; /* ilink1, ilink2 or eret */
+ unsigned long blink;
+ unsigned long fp;
+ unsigned long r26; /* gp */
- long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
+ unsigned long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
- long sp; /* user/kernel sp depending on where we came from */
- long orig_r0;
+ unsigned long sp; /* User/Kernel depending on where we came from */
+ unsigned long orig_r0;
/*
* To distinguish bet excp, syscall, irq
@@ -55,13 +55,13 @@
unsigned long event;
};
- long user_r25;
+ unsigned long user_r25;
};
#else
struct pt_regs {
- long orig_r0;
+ unsigned long orig_r0;
union {
struct {
@@ -76,26 +76,26 @@
unsigned long event;
};
- long bta; /* bta_l1, bta_l2, erbta */
+ unsigned long bta; /* bta_l1, bta_l2, erbta */
- long user_r25;
+ unsigned long user_r25;
- long r26; /* gp */
- long fp;
- long sp; /* user/kernel sp depending on where we came from */
+ unsigned long r26; /* gp */
+ unsigned long fp;
+ unsigned long sp; /* user/kernel sp depending on where we came from */
- long r12;
+ unsigned long r12;
/*------- Below list auto saved by h/w -----------*/
- long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
+ unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
- long blink;
- long lp_end, lp_start, lp_count;
+ unsigned long blink;
+ unsigned long lp_end, lp_start, lp_count;
- long ei, ldi, jli;
+ unsigned long ei, ldi, jli;
- long ret;
- long status32;
+ unsigned long ret;
+ unsigned long status32;
};
#endif
@@ -103,10 +103,10 @@
/* Callee saved registers - need to be saved only when you are scheduled out */
struct callee_regs {
- long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13;
+ unsigned long r25, r24, r23, r22, r21, r20, r19, r18, r17, r16, r15, r14, r13;
};
-#define instruction_pointer(regs) (unsigned long)((regs)->ret)
+#define instruction_pointer(regs) ((regs)->ret)
#define profile_pc(regs) instruction_pointer(regs)
/* return 1 if user mode or 0 if kernel mode */
@@ -142,7 +142,7 @@
static inline long regs_return_value(struct pt_regs *regs)
{
- return regs->r0;
+ return (long)regs->r0;
}
#endif /* !__ASSEMBLY__ */
diff --git a/arch/arc/include/asm/spinlock.h b/arch/arc/include/asm/spinlock.h
index e1651df..db8c59d 100644
--- a/arch/arc/include/asm/spinlock.h
+++ b/arch/arc/include/asm/spinlock.h
@@ -18,9 +18,518 @@
#define arch_spin_unlock_wait(x) \
do { while (arch_spin_is_locked(x)) cpu_relax(); } while (0)
+#ifdef CONFIG_ARC_HAS_LLSC
+
+/*
+ * A normal LLOCK/SCOND based system, w/o need for livelock workaround
+ */
+#ifndef CONFIG_ARC_STAR_9000923308
+
static inline void arch_spin_lock(arch_spinlock_t *lock)
{
- unsigned int tmp = __ARCH_SPIN_LOCK_LOCKED__;
+ unsigned int val;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "1: llock %[val], [%[slock]] \n"
+ " breq %[val], %[LOCKED], 1b \n" /* spin while LOCKED */
+ " scond %[LOCKED], [%[slock]] \n" /* acquire */
+ " bnz 1b \n"
+ " \n"
+ : [val] "=&r" (val)
+ : [slock] "r" (&(lock->slock)),
+ [LOCKED] "r" (__ARCH_SPIN_LOCK_LOCKED__)
+ : "memory", "cc");
+
+ smp_mb();
+}
+
+/* 1 - lock taken successfully */
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+ unsigned int val, got_it = 0;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "1: llock %[val], [%[slock]] \n"
+ " breq %[val], %[LOCKED], 4f \n" /* already LOCKED, just bail */
+ " scond %[LOCKED], [%[slock]] \n" /* acquire */
+ " bnz 1b \n"
+ " mov %[got_it], 1 \n"
+ "4: \n"
+ " \n"
+ : [val] "=&r" (val),
+ [got_it] "+&r" (got_it)
+ : [slock] "r" (&(lock->slock)),
+ [LOCKED] "r" (__ARCH_SPIN_LOCK_LOCKED__)
+ : "memory", "cc");
+
+ smp_mb();
+
+ return got_it;
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+ smp_mb();
+
+ lock->slock = __ARCH_SPIN_LOCK_UNLOCKED__;
+
+ smp_mb();
+}
+
+/*
+ * Read-write spinlocks, allowing multiple readers but only one writer.
+ * Unfair locking as Writers could be starved indefinitely by Reader(s)
+ */
+
+static inline void arch_read_lock(arch_rwlock_t *rw)
+{
+ unsigned int val;
+
+ smp_mb();
+
+ /*
+ * zero means writer holds the lock exclusively, deny Reader.
+ * Otherwise grant lock to first/subseq reader
+ *
+ * if (rw->counter > 0) {
+ * rw->counter--;
+ * ret = 1;
+ * }
+ */
+
+ __asm__ __volatile__(
+ "1: llock %[val], [%[rwlock]] \n"
+ " brls %[val], %[WR_LOCKED], 1b\n" /* <= 0: spin while write locked */
+ " sub %[val], %[val], 1 \n" /* reader lock */
+ " scond %[val], [%[rwlock]] \n"
+ " bnz 1b \n"
+ " \n"
+ : [val] "=&r" (val)
+ : [rwlock] "r" (&(rw->counter)),
+ [WR_LOCKED] "ir" (0)
+ : "memory", "cc");
+
+ smp_mb();
+}
+
+/* 1 - lock taken successfully */
+static inline int arch_read_trylock(arch_rwlock_t *rw)
+{
+ unsigned int val, got_it = 0;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "1: llock %[val], [%[rwlock]] \n"
+ " brls %[val], %[WR_LOCKED], 4f\n" /* <= 0: already write locked, bail */
+ " sub %[val], %[val], 1 \n" /* counter-- */
+ " scond %[val], [%[rwlock]] \n"
+ " bnz 1b \n" /* retry if collided with someone */
+ " mov %[got_it], 1 \n"
+ " \n"
+ "4: ; --- done --- \n"
+
+ : [val] "=&r" (val),
+ [got_it] "+&r" (got_it)
+ : [rwlock] "r" (&(rw->counter)),
+ [WR_LOCKED] "ir" (0)
+ : "memory", "cc");
+
+ smp_mb();
+
+ return got_it;
+}
+
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+ unsigned int val;
+
+ smp_mb();
+
+ /*
+ * If reader(s) hold lock (lock < __ARCH_RW_LOCK_UNLOCKED__),
+ * deny writer. Otherwise if unlocked grant to writer
+ * Hence the claim that Linux rwlocks are unfair to writers.
+ * (can be starved for an indefinite time by readers).
+ *
+ * if (rw->counter == __ARCH_RW_LOCK_UNLOCKED__) {
+ * rw->counter = 0;
+ * ret = 1;
+ * }
+ */
+
+ __asm__ __volatile__(
+ "1: llock %[val], [%[rwlock]] \n"
+ " brne %[val], %[UNLOCKED], 1b \n" /* while !UNLOCKED spin */
+ " mov %[val], %[WR_LOCKED] \n"
+ " scond %[val], [%[rwlock]] \n"
+ " bnz 1b \n"
+ " \n"
+ : [val] "=&r" (val)
+ : [rwlock] "r" (&(rw->counter)),
+ [UNLOCKED] "ir" (__ARCH_RW_LOCK_UNLOCKED__),
+ [WR_LOCKED] "ir" (0)
+ : "memory", "cc");
+
+ smp_mb();
+}
+
+/* 1 - lock taken successfully */
+static inline int arch_write_trylock(arch_rwlock_t *rw)
+{
+ unsigned int val, got_it = 0;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "1: llock %[val], [%[rwlock]] \n"
+ " brne %[val], %[UNLOCKED], 4f \n" /* !UNLOCKED, bail */
+ " mov %[val], %[WR_LOCKED] \n"
+ " scond %[val], [%[rwlock]] \n"
+ " bnz 1b \n" /* retry if collided with someone */
+ " mov %[got_it], 1 \n"
+ " \n"
+ "4: ; --- done --- \n"
+
+ : [val] "=&r" (val),
+ [got_it] "+&r" (got_it)
+ : [rwlock] "r" (&(rw->counter)),
+ [UNLOCKED] "ir" (__ARCH_RW_LOCK_UNLOCKED__),
+ [WR_LOCKED] "ir" (0)
+ : "memory", "cc");
+
+ smp_mb();
+
+ return got_it;
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *rw)
+{
+ unsigned int val;
+
+ smp_mb();
+
+ /*
+ * rw->counter++;
+ */
+ __asm__ __volatile__(
+ "1: llock %[val], [%[rwlock]] \n"
+ " add %[val], %[val], 1 \n"
+ " scond %[val], [%[rwlock]] \n"
+ " bnz 1b \n"
+ " \n"
+ : [val] "=&r" (val)
+ : [rwlock] "r" (&(rw->counter))
+ : "memory", "cc");
+
+ smp_mb();
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *rw)
+{
+ smp_mb();
+
+ rw->counter = __ARCH_RW_LOCK_UNLOCKED__;
+
+ smp_mb();
+}
+
+#else /* CONFIG_ARC_STAR_9000923308 */
+
+/*
+ * HS38x4 could get into a LLOCK/SCOND livelock in case of multiple overlapping
+ * coherency transactions in the SCU. The exclusive line state keeps rotating
+ * among contenting cores leading to a never ending cycle. So break the cycle
+ * by deferring the retry of failed exclusive access (SCOND). The actual delay
+ * needed is function of number of contending cores as well as the unrelated
+ * coherency traffic from other cores. To keep the code simple, start off with
+ * small delay of 1 which would suffice most cases and in case of contention
+ * double the delay. Eventually the delay is sufficient such that the coherency
+ * pipeline is drained, thus a subsequent exclusive access would succeed.
+ */
+
+#define SCOND_FAIL_RETRY_VAR_DEF \
+ unsigned int delay, tmp; \
+
+#define SCOND_FAIL_RETRY_ASM \
+ " ; --- scond fail delay --- \n" \
+ " mov %[tmp], %[delay] \n" /* tmp = delay */ \
+ "2: brne.d %[tmp], 0, 2b \n" /* while (tmp != 0) */ \
+ " sub %[tmp], %[tmp], 1 \n" /* tmp-- */ \
+ " rol %[delay], %[delay] \n" /* delay *= 2 */ \
+ " b 1b \n" /* start over */ \
+ " \n" \
+ "4: ; --- done --- \n" \
+
+#define SCOND_FAIL_RETRY_VARS \
+ ,[delay] "=&r" (delay), [tmp] "=&r" (tmp) \
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+ unsigned int val;
+ SCOND_FAIL_RETRY_VAR_DEF;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "0: mov %[delay], 1 \n"
+ "1: llock %[val], [%[slock]] \n"
+ " breq %[val], %[LOCKED], 0b \n" /* spin while LOCKED */
+ " scond %[LOCKED], [%[slock]] \n" /* acquire */
+ " bz 4f \n" /* done */
+ " \n"
+ SCOND_FAIL_RETRY_ASM
+
+ : [val] "=&r" (val)
+ SCOND_FAIL_RETRY_VARS
+ : [slock] "r" (&(lock->slock)),
+ [LOCKED] "r" (__ARCH_SPIN_LOCK_LOCKED__)
+ : "memory", "cc");
+
+ smp_mb();
+}
+
+/* 1 - lock taken successfully */
+static inline int arch_spin_trylock(arch_spinlock_t *lock)
+{
+ unsigned int val, got_it = 0;
+ SCOND_FAIL_RETRY_VAR_DEF;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "0: mov %[delay], 1 \n"
+ "1: llock %[val], [%[slock]] \n"
+ " breq %[val], %[LOCKED], 4f \n" /* already LOCKED, just bail */
+ " scond %[LOCKED], [%[slock]] \n" /* acquire */
+ " bz.d 4f \n"
+ " mov.z %[got_it], 1 \n" /* got it */
+ " \n"
+ SCOND_FAIL_RETRY_ASM
+
+ : [val] "=&r" (val),
+ [got_it] "+&r" (got_it)
+ SCOND_FAIL_RETRY_VARS
+ : [slock] "r" (&(lock->slock)),
+ [LOCKED] "r" (__ARCH_SPIN_LOCK_LOCKED__)
+ : "memory", "cc");
+
+ smp_mb();
+
+ return got_it;
+}
+
+static inline void arch_spin_unlock(arch_spinlock_t *lock)
+{
+ smp_mb();
+
+ lock->slock = __ARCH_SPIN_LOCK_UNLOCKED__;
+
+ smp_mb();
+}
+
+/*
+ * Read-write spinlocks, allowing multiple readers but only one writer.
+ * Unfair locking as Writers could be starved indefinitely by Reader(s)
+ */
+
+static inline void arch_read_lock(arch_rwlock_t *rw)
+{
+ unsigned int val;
+ SCOND_FAIL_RETRY_VAR_DEF;
+
+ smp_mb();
+
+ /*
+ * zero means writer holds the lock exclusively, deny Reader.
+ * Otherwise grant lock to first/subseq reader
+ *
+ * if (rw->counter > 0) {
+ * rw->counter--;
+ * ret = 1;
+ * }
+ */
+
+ __asm__ __volatile__(
+ "0: mov %[delay], 1 \n"
+ "1: llock %[val], [%[rwlock]] \n"
+ " brls %[val], %[WR_LOCKED], 0b\n" /* <= 0: spin while write locked */
+ " sub %[val], %[val], 1 \n" /* reader lock */
+ " scond %[val], [%[rwlock]] \n"
+ " bz 4f \n" /* done */
+ " \n"
+ SCOND_FAIL_RETRY_ASM
+
+ : [val] "=&r" (val)
+ SCOND_FAIL_RETRY_VARS
+ : [rwlock] "r" (&(rw->counter)),
+ [WR_LOCKED] "ir" (0)
+ : "memory", "cc");
+
+ smp_mb();
+}
+
+/* 1 - lock taken successfully */
+static inline int arch_read_trylock(arch_rwlock_t *rw)
+{
+ unsigned int val, got_it = 0;
+ SCOND_FAIL_RETRY_VAR_DEF;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "0: mov %[delay], 1 \n"
+ "1: llock %[val], [%[rwlock]] \n"
+ " brls %[val], %[WR_LOCKED], 4f\n" /* <= 0: already write locked, bail */
+ " sub %[val], %[val], 1 \n" /* counter-- */
+ " scond %[val], [%[rwlock]] \n"
+ " bz.d 4f \n"
+ " mov.z %[got_it], 1 \n" /* got it */
+ " \n"
+ SCOND_FAIL_RETRY_ASM
+
+ : [val] "=&r" (val),
+ [got_it] "+&r" (got_it)
+ SCOND_FAIL_RETRY_VARS
+ : [rwlock] "r" (&(rw->counter)),
+ [WR_LOCKED] "ir" (0)
+ : "memory", "cc");
+
+ smp_mb();
+
+ return got_it;
+}
+
+static inline void arch_write_lock(arch_rwlock_t *rw)
+{
+ unsigned int val;
+ SCOND_FAIL_RETRY_VAR_DEF;
+
+ smp_mb();
+
+ /*
+ * If reader(s) hold lock (lock < __ARCH_RW_LOCK_UNLOCKED__),
+ * deny writer. Otherwise if unlocked grant to writer
+ * Hence the claim that Linux rwlocks are unfair to writers.
+ * (can be starved for an indefinite time by readers).
+ *
+ * if (rw->counter == __ARCH_RW_LOCK_UNLOCKED__) {
+ * rw->counter = 0;
+ * ret = 1;
+ * }
+ */
+
+ __asm__ __volatile__(
+ "0: mov %[delay], 1 \n"
+ "1: llock %[val], [%[rwlock]] \n"
+ " brne %[val], %[UNLOCKED], 0b \n" /* while !UNLOCKED spin */
+ " mov %[val], %[WR_LOCKED] \n"
+ " scond %[val], [%[rwlock]] \n"
+ " bz 4f \n"
+ " \n"
+ SCOND_FAIL_RETRY_ASM
+
+ : [val] "=&r" (val)
+ SCOND_FAIL_RETRY_VARS
+ : [rwlock] "r" (&(rw->counter)),
+ [UNLOCKED] "ir" (__ARCH_RW_LOCK_UNLOCKED__),
+ [WR_LOCKED] "ir" (0)
+ : "memory", "cc");
+
+ smp_mb();
+}
+
+/* 1 - lock taken successfully */
+static inline int arch_write_trylock(arch_rwlock_t *rw)
+{
+ unsigned int val, got_it = 0;
+ SCOND_FAIL_RETRY_VAR_DEF;
+
+ smp_mb();
+
+ __asm__ __volatile__(
+ "0: mov %[delay], 1 \n"
+ "1: llock %[val], [%[rwlock]] \n"
+ " brne %[val], %[UNLOCKED], 4f \n" /* !UNLOCKED, bail */
+ " mov %[val], %[WR_LOCKED] \n"
+ " scond %[val], [%[rwlock]] \n"
+ " bz.d 4f \n"
+ " mov.z %[got_it], 1 \n" /* got it */
+ " \n"
+ SCOND_FAIL_RETRY_ASM
+
+ : [val] "=&r" (val),
+ [got_it] "+&r" (got_it)
+ SCOND_FAIL_RETRY_VARS
+ : [rwlock] "r" (&(rw->counter)),
+ [UNLOCKED] "ir" (__ARCH_RW_LOCK_UNLOCKED__),
+ [WR_LOCKED] "ir" (0)
+ : "memory", "cc");
+
+ smp_mb();
+
+ return got_it;
+}
+
+static inline void arch_read_unlock(arch_rwlock_t *rw)
+{
+ unsigned int val;
+
+ smp_mb();
+
+ /*
+ * rw->counter++;
+ */
+ __asm__ __volatile__(
+ "1: llock %[val], [%[rwlock]] \n"
+ " add %[val], %[val], 1 \n"
+ " scond %[val], [%[rwlock]] \n"
+ " bnz 1b \n"
+ " \n"
+ : [val] "=&r" (val)
+ : [rwlock] "r" (&(rw->counter))
+ : "memory", "cc");
+
+ smp_mb();
+}
+
+static inline void arch_write_unlock(arch_rwlock_t *rw)
+{
+ unsigned int val;
+
+ smp_mb();
+
+ /*
+ * rw->counter = __ARCH_RW_LOCK_UNLOCKED__;
+ */
+ __asm__ __volatile__(
+ "1: llock %[val], [%[rwlock]] \n"
+ " scond %[UNLOCKED], [%[rwlock]]\n"
+ " bnz 1b \n"
+ " \n"
+ : [val] "=&r" (val)
+ : [rwlock] "r" (&(rw->counter)),
+ [UNLOCKED] "r" (__ARCH_RW_LOCK_UNLOCKED__)
+ : "memory", "cc");
+
+ smp_mb();
+}
+
+#undef SCOND_FAIL_RETRY_VAR_DEF
+#undef SCOND_FAIL_RETRY_ASM
+#undef SCOND_FAIL_RETRY_VARS
+
+#endif /* CONFIG_ARC_STAR_9000923308 */
+
+#else /* !CONFIG_ARC_HAS_LLSC */
+
+static inline void arch_spin_lock(arch_spinlock_t *lock)
+{
+ unsigned int val = __ARCH_SPIN_LOCK_LOCKED__;
/*
* This smp_mb() is technically superfluous, we only need the one
@@ -33,7 +542,7 @@
__asm__ __volatile__(
"1: ex %0, [%1] \n"
" breq %0, %2, 1b \n"
- : "+&r" (tmp)
+ : "+&r" (val)
: "r"(&(lock->slock)), "ir"(__ARCH_SPIN_LOCK_LOCKED__)
: "memory");
@@ -48,26 +557,27 @@
smp_mb();
}
+/* 1 - lock taken successfully */
static inline int arch_spin_trylock(arch_spinlock_t *lock)
{
- unsigned int tmp = __ARCH_SPIN_LOCK_LOCKED__;
+ unsigned int val = __ARCH_SPIN_LOCK_LOCKED__;
smp_mb();
__asm__ __volatile__(
"1: ex %0, [%1] \n"
- : "+r" (tmp)
+ : "+r" (val)
: "r"(&(lock->slock))
: "memory");
smp_mb();
- return (tmp == __ARCH_SPIN_LOCK_UNLOCKED__);
+ return (val == __ARCH_SPIN_LOCK_UNLOCKED__);
}
static inline void arch_spin_unlock(arch_spinlock_t *lock)
{
- unsigned int tmp = __ARCH_SPIN_LOCK_UNLOCKED__;
+ unsigned int val = __ARCH_SPIN_LOCK_UNLOCKED__;
/*
* RELEASE barrier: given the instructions avail on ARCv2, full barrier
@@ -77,7 +587,7 @@
__asm__ __volatile__(
" ex %0, [%1] \n"
- : "+r" (tmp)
+ : "+r" (val)
: "r"(&(lock->slock))
: "memory");
@@ -90,19 +600,12 @@
/*
* Read-write spinlocks, allowing multiple readers but only one writer.
+ * Unfair locking as Writers could be starved indefinitely by Reader(s)
*
* The spinlock itself is contained in @counter and access to it is
* serialized with @lock_mutex.
- *
- * Unfair locking as Writers could be starved indefinitely by Reader(s)
*/
-/* Would read_trylock() succeed? */
-#define arch_read_can_lock(x) ((x)->counter > 0)
-
-/* Would write_trylock() succeed? */
-#define arch_write_can_lock(x) ((x)->counter == __ARCH_RW_LOCK_UNLOCKED__)
-
/* 1 - lock taken successfully */
static inline int arch_read_trylock(arch_rwlock_t *rw)
{
@@ -173,6 +676,11 @@
arch_spin_unlock(&(rw->lock_mutex));
}
+#endif
+
+#define arch_read_can_lock(x) ((x)->counter > 0)
+#define arch_write_can_lock(x) ((x)->counter == __ARCH_RW_LOCK_UNLOCKED__)
+
#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
diff --git a/arch/arc/include/asm/spinlock_types.h b/arch/arc/include/asm/spinlock_types.h
index 662627c..4e1ef5f 100644
--- a/arch/arc/include/asm/spinlock_types.h
+++ b/arch/arc/include/asm/spinlock_types.h
@@ -26,7 +26,9 @@
*/
typedef struct {
volatile unsigned int counter;
+#ifndef CONFIG_ARC_HAS_LLSC
arch_spinlock_t lock_mutex;
+#endif
} arch_rwlock_t;
#define __ARCH_RW_LOCK_UNLOCKED__ 0x01000000
diff --git a/arch/arc/include/uapi/asm/ptrace.h b/arch/arc/include/uapi/asm/ptrace.h
index 76a7739..0b3ef63 100644
--- a/arch/arc/include/uapi/asm/ptrace.h
+++ b/arch/arc/include/uapi/asm/ptrace.h
@@ -32,20 +32,20 @@
*/
struct user_regs_struct {
- long pad;
+ unsigned long pad;
struct {
- long bta, lp_start, lp_end, lp_count;
- long status32, ret, blink, fp, gp;
- long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
- long sp;
+ unsigned long bta, lp_start, lp_end, lp_count;
+ unsigned long status32, ret, blink, fp, gp;
+ unsigned long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
+ unsigned long sp;
} scratch;
- long pad2;
+ unsigned long pad2;
struct {
- long r25, r24, r23, r22, r21, r20;
- long r19, r18, r17, r16, r15, r14, r13;
+ unsigned long r25, r24, r23, r22, r21, r20;
+ unsigned long r19, r18, r17, r16, r15, r14, r13;
} callee;
- long efa; /* break pt addr, for break points in delay slots */
- long stop_pc; /* give dbg stop_pc after ensuring brkpt trap */
+ unsigned long efa; /* break pt addr, for break points in delay slots */
+ unsigned long stop_pc; /* give dbg stop_pc after ensuring brkpt trap */
};
#endif /* !__ASSEMBLY__ */
diff --git a/arch/arc/kernel/setup.c b/arch/arc/kernel/setup.c
index 18cc015..cabde9d 100644
--- a/arch/arc/kernel/setup.c
+++ b/arch/arc/kernel/setup.c
@@ -47,6 +47,7 @@
struct bcr_perip uncached_space;
struct bcr_generic bcr;
struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
+ unsigned long perip_space;
FIX_PTR(cpu);
READ_BCR(AUX_IDENTITY, cpu->core);
@@ -56,7 +57,12 @@
cpu->vec_base = read_aux_reg(AUX_INTR_VEC_BASE);
READ_BCR(ARC_REG_D_UNCACH_BCR, uncached_space);
- BUG_ON((uncached_space.start << 24) != ARC_UNCACHED_ADDR_SPACE);
+ if (uncached_space.ver < 3)
+ perip_space = uncached_space.start << 24;
+ else
+ perip_space = read_aux_reg(AUX_NON_VOL) & 0xF0000000;
+
+ BUG_ON(perip_space != ARC_UNCACHED_ADDR_SPACE);
READ_BCR(ARC_REG_MUL_BCR, cpu->extn_mpy);
@@ -330,6 +336,10 @@
pr_warn("CONFIG_ARC_FPU_SAVE_RESTORE needed for working apps\n");
else if (!cpu->extn.fpu_dp && fpu_enabled)
panic("FPU non-existent, disable CONFIG_ARC_FPU_SAVE_RESTORE\n");
+
+ if (is_isa_arcv2() && IS_ENABLED(CONFIG_SMP) && cpu->isa.atomic &&
+ !IS_ENABLED(CONFIG_ARC_STAR_9000923308))
+ panic("llock/scond livelock workaround missing\n");
}
/*
diff --git a/arch/arc/kernel/time.c b/arch/arc/kernel/time.c
index 3364d2b..4294761 100644
--- a/arch/arc/kernel/time.c
+++ b/arch/arc/kernel/time.c
@@ -203,34 +203,24 @@
return 0;
}
-static void arc_clkevent_set_mode(enum clock_event_mode mode,
- struct clock_event_device *dev)
+static int arc_clkevent_set_periodic(struct clock_event_device *dev)
{
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- /*
- * At X Hz, 1 sec = 1000ms -> X cycles;
- * 10ms -> X / 100 cycles
- */
- arc_timer_event_setup(arc_get_core_freq() / HZ);
- break;
- case CLOCK_EVT_MODE_ONESHOT:
- break;
- default:
- break;
- }
-
- return;
+ /*
+ * At X Hz, 1 sec = 1000ms -> X cycles;
+ * 10ms -> X / 100 cycles
+ */
+ arc_timer_event_setup(arc_get_core_freq() / HZ);
+ return 0;
}
static DEFINE_PER_CPU(struct clock_event_device, arc_clockevent_device) = {
- .name = "ARC Timer0",
- .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
- .mode = CLOCK_EVT_MODE_UNUSED,
- .rating = 300,
- .irq = TIMER0_IRQ, /* hardwired, no need for resources */
- .set_next_event = arc_clkevent_set_next_event,
- .set_mode = arc_clkevent_set_mode,
+ .name = "ARC Timer0",
+ .features = CLOCK_EVT_FEAT_ONESHOT |
+ CLOCK_EVT_FEAT_PERIODIC,
+ .rating = 300,
+ .irq = TIMER0_IRQ, /* hardwired, no need for resources */
+ .set_next_event = arc_clkevent_set_next_event,
+ .set_state_periodic = arc_clkevent_set_periodic,
};
static irqreturn_t timer_irq_handler(int irq, void *dev_id)
@@ -240,7 +230,7 @@
* irq_set_chip_and_handler() asked for handle_percpu_devid_irq()
*/
struct clock_event_device *evt = this_cpu_ptr(&arc_clockevent_device);
- int irq_reenable = evt->mode == CLOCK_EVT_MODE_PERIODIC;
+ int irq_reenable = clockevent_state_periodic(evt);
/*
* Any write to CTRL reg ACks the interrupt, we rewrite the
diff --git a/arch/arc/lib/memcpy-archs.S b/arch/arc/lib/memcpy-archs.S
index 1b2b3ac..0cab0b8 100644
--- a/arch/arc/lib/memcpy-archs.S
+++ b/arch/arc/lib/memcpy-archs.S
@@ -206,7 +206,7 @@
ld.ab r6, [r1, 4]
prefetch [r1, 28] ;Prefetch the next read location
ld.ab r8, [r1,4]
- prefetch [r3, 32] ;Prefetch the next write location
+ prefetchw [r3, 32] ;Prefetch the next write location
SHIFT_1 (r7, r6, 8)
or r7, r7, r5
diff --git a/arch/arc/lib/memset-archs.S b/arch/arc/lib/memset-archs.S
index 92d573c..365b183 100644
--- a/arch/arc/lib/memset-archs.S
+++ b/arch/arc/lib/memset-archs.S
@@ -10,12 +10,6 @@
#undef PREALLOC_NOT_AVAIL
-#ifdef PREALLOC_NOT_AVAIL
-#define PREWRITE(A,B) prefetchw [(A),(B)]
-#else
-#define PREWRITE(A,B) prealloc [(A),(B)]
-#endif
-
ENTRY(memset)
prefetchw [r0] ; Prefetch the write location
mov.f 0, r2
@@ -51,9 +45,15 @@
;;; Convert len to Dwords, unfold x8
lsr.f lp_count, lp_count, 6
+
lpnz @.Lset64bytes
;; LOOP START
- PREWRITE(r3, 64) ;Prefetch the next write location
+#ifdef PREALLOC_NOT_AVAIL
+ prefetchw [r3, 64] ;Prefetch the next write location
+#else
+ prealloc [r3, 64]
+#endif
+#ifdef CONFIG_ARC_HAS_LL64
std.ab r4, [r3, 8]
std.ab r4, [r3, 8]
std.ab r4, [r3, 8]
@@ -62,16 +62,45 @@
std.ab r4, [r3, 8]
std.ab r4, [r3, 8]
std.ab r4, [r3, 8]
+#else
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+#endif
.Lset64bytes:
lsr.f lp_count, r2, 5 ;Last remaining max 124 bytes
lpnz .Lset32bytes
;; LOOP START
prefetchw [r3, 32] ;Prefetch the next write location
+#ifdef CONFIG_ARC_HAS_LL64
std.ab r4, [r3, 8]
std.ab r4, [r3, 8]
std.ab r4, [r3, 8]
std.ab r4, [r3, 8]
+#else
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+ st.ab r4, [r3, 4]
+#endif
.Lset32bytes:
and.f lp_count, r2, 0x1F ;Last remaining 31 bytes
diff --git a/arch/arc/plat-axs10x/axs10x.c b/arch/arc/plat-axs10x/axs10x.c
index 99f7da5..e7769c3 100644
--- a/arch/arc/plat-axs10x/axs10x.c
+++ b/arch/arc/plat-axs10x/axs10x.c
@@ -389,6 +389,21 @@
static void __init axs103_early_init(void)
{
+ /*
+ * AXS103 configurations for SMP/QUAD configurations share device tree
+ * which defaults to 90 MHz. However recent failures of Quad config
+ * revealed P&R timing violations so clamp it down to safe 50 MHz
+ * Instead of duplicating defconfig/DT for SMP/QUAD, add a small hack
+ *
+ * This hack is really hacky as of now. Fix it properly by getting the
+ * number of cores as return value of platform's early SMP callback
+ */
+#ifdef CONFIG_ARC_MCIP
+ unsigned int num_cores = (read_aux_reg(ARC_REG_MCIP_BCR) >> 16) & 0x3F;
+ if (num_cores > 2)
+ arc_set_core_freq(50 * 1000000);
+#endif
+
switch (arc_get_core_freq()/1000000) {
case 33:
axs103_set_freq(1, 1, 1);
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 07ab3d2..7451b44 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -312,6 +312,9 @@
PHONY += bzImage $(BOOT_TARGETS) $(INSTALL_TARGETS)
+bootpImage uImage: zImage
+zImage: Image
+
$(BOOT_TARGETS): vmlinux
$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index 21fcc44..b76f9a2 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -210,7 +210,7 @@
};
uart0: serial@44e09000 {
- compatible = "ti,omap3-uart";
+ compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart1";
clock-frequency = <48000000>;
reg = <0x44e09000 0x2000>;
@@ -221,7 +221,7 @@
};
uart1: serial@48022000 {
- compatible = "ti,omap3-uart";
+ compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart2";
clock-frequency = <48000000>;
reg = <0x48022000 0x2000>;
@@ -232,7 +232,7 @@
};
uart2: serial@48024000 {
- compatible = "ti,omap3-uart";
+ compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart3";
clock-frequency = <48000000>;
reg = <0x48024000 0x2000>;
@@ -243,7 +243,7 @@
};
uart3: serial@481a6000 {
- compatible = "ti,omap3-uart";
+ compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart4";
clock-frequency = <48000000>;
reg = <0x481a6000 0x2000>;
@@ -252,7 +252,7 @@
};
uart4: serial@481a8000 {
- compatible = "ti,omap3-uart";
+ compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart5";
clock-frequency = <48000000>;
reg = <0x481a8000 0x2000>;
@@ -261,7 +261,7 @@
};
uart5: serial@481aa000 {
- compatible = "ti,omap3-uart";
+ compatible = "ti,am3352-uart", "ti,omap3-uart";
ti,hwmods = "uart6";
clock-frequency = <48000000>;
reg = <0x481aa000 0x2000>;
diff --git a/arch/arm/boot/dts/dra7.dtsi b/arch/arm/boot/dts/dra7.dtsi
index 8f1e25b..e60677e 100644
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -116,7 +116,7 @@
ranges = <0 0x2000 0x2000>;
scm_conf: scm_conf@0 {
- compatible = "syscon";
+ compatible = "syscon", "simple-bus";
reg = <0x0 0x1400>;
#address-cells = <1>;
#size-cells = <1>;
@@ -397,7 +397,7 @@
};
uart1: serial@4806a000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4806a000 0x100>;
interrupts-extended = <&crossbar_mpu GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart1";
@@ -408,7 +408,7 @@
};
uart2: serial@4806c000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4806c000 0x100>;
interrupts = <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart2";
@@ -419,7 +419,7 @@
};
uart3: serial@48020000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48020000 0x100>;
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart3";
@@ -430,7 +430,7 @@
};
uart4: serial@4806e000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4806e000 0x100>;
interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart4";
@@ -441,7 +441,7 @@
};
uart5: serial@48066000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48066000 0x100>;
interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart5";
@@ -452,7 +452,7 @@
};
uart6: serial@48068000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48068000 0x100>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart6";
@@ -463,7 +463,7 @@
};
uart7: serial@48420000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48420000 0x100>;
interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart7";
@@ -472,7 +472,7 @@
};
uart8: serial@48422000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48422000 0x100>;
interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart8";
@@ -481,7 +481,7 @@
};
uart9: serial@48424000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x48424000 0x100>;
interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart9";
@@ -490,7 +490,7 @@
};
uart10: serial@4ae2b000 {
- compatible = "ti,omap4-uart";
+ compatible = "ti,dra742-uart", "ti,omap4-uart";
reg = <0x4ae2b000 0x100>;
interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "uart10";
@@ -1140,6 +1140,7 @@
ctrl-module = <&omap_control_sata>;
clocks = <&sys_clkin1>, <&sata_ref_clk>;
clock-names = "sysclk", "refclk";
+ syscon-pllreset = <&scm_conf 0x3fc>;
#phy-cells = <0>;
};
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index d720133..2db9943 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -138,8 +138,8 @@
mipi_phy: video-phy@10020710 {
compatible = "samsung,s5pv210-mipi-video-phy";
- reg = <0x10020710 8>;
#phy-cells = <1>;
+ syscon = <&pmu_system_controller>;
};
pd_cam: cam-power-domain@10023C00 {
diff --git a/arch/arm/boot/dts/exynos4210-origen.dts b/arch/arm/boot/dts/exynos4210-origen.dts
index e0abfc3..e050d85 100644
--- a/arch/arm/boot/dts/exynos4210-origen.dts
+++ b/arch/arm/boot/dts/exynos4210-origen.dts
@@ -127,6 +127,10 @@
};
};
+&cpu0 {
+ cpu0-supply = <&buck1_reg>;
+};
+
&fimd {
pinctrl-0 = <&lcd_en &lcd_clk &lcd_data24 &pwm0_out>;
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/exynos4210-trats.dts b/arch/arm/boot/dts/exynos4210-trats.dts
index 98f3ce6..ba34886 100644
--- a/arch/arm/boot/dts/exynos4210-trats.dts
+++ b/arch/arm/boot/dts/exynos4210-trats.dts
@@ -188,6 +188,10 @@
};
};
+&cpu0 {
+ cpu0-supply = <&varm_breg>;
+};
+
&dsi_0 {
vddcore-supply = <&vusb_reg>;
vddio-supply = <&vmipi_reg>;
diff --git a/arch/arm/boot/dts/exynos4210-universal_c210.dts b/arch/arm/boot/dts/exynos4210-universal_c210.dts
index d4f2b11..775892b 100644
--- a/arch/arm/boot/dts/exynos4210-universal_c210.dts
+++ b/arch/arm/boot/dts/exynos4210-universal_c210.dts
@@ -548,6 +548,10 @@
};
};
+&cpu0 {
+ cpu0-supply = <&vdd_arm_reg>;
+};
+
&pinctrl_1 {
hdmi_hpd: hdmi-hpd {
samsung,pins = "gpx3-7";
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi
index 10d3c17..3e5ba66 100644
--- a/arch/arm/boot/dts/exynos4210.dtsi
+++ b/arch/arm/boot/dts/exynos4210.dtsi
@@ -40,6 +40,18 @@
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0x900>;
+ clocks = <&clock CLK_ARM_CLK>;
+ clock-names = "cpu";
+ clock-latency = <160000>;
+
+ operating-points = <
+ 1200000 1250000
+ 1000000 1150000
+ 800000 1075000
+ 500000 975000
+ 400000 975000
+ 200000 950000
+ >;
cooling-min-level = <4>;
cooling-max-level = <2>;
#cooling-cells = <2>; /* min followed by max */
diff --git a/arch/arm/boot/dts/imx25-pdk.dts b/arch/arm/boot/dts/imx25-pdk.dts
index dd45e69..9351296 100644
--- a/arch/arm/boot/dts/imx25-pdk.dts
+++ b/arch/arm/boot/dts/imx25-pdk.dts
@@ -10,6 +10,7 @@
*/
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
#include "imx25.dtsi"
@@ -114,8 +115,8 @@
&esdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1>;
- cd-gpios = <&gpio2 1 0>;
- wp-gpios = <&gpio2 0 0>;
+ cd-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx35.dtsi b/arch/arm/boot/dts/imx35.dtsi
index b6478e9..e6540b5 100644
--- a/arch/arm/boot/dts/imx35.dtsi
+++ b/arch/arm/boot/dts/imx35.dtsi
@@ -286,8 +286,8 @@
can1: can@53fe4000 {
compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
reg = <0x53fe4000 0x1000>;
- clocks = <&clks 33>;
- clock-names = "ipg";
+ clocks = <&clks 33>, <&clks 33>;
+ clock-names = "ipg", "per";
interrupts = <43>;
status = "disabled";
};
@@ -295,8 +295,8 @@
can2: can@53fe8000 {
compatible = "fsl,imx35-flexcan", "fsl,p1010-flexcan";
reg = <0x53fe8000 0x1000>;
- clocks = <&clks 34>;
- clock-names = "ipg";
+ clocks = <&clks 34>, <&clks 34>;
+ clock-names = "ipg", "per";
interrupts = <44>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx51-apf51dev.dts b/arch/arm/boot/dts/imx51-apf51dev.dts
index 93d3ea1..0f3fe29 100644
--- a/arch/arm/boot/dts/imx51-apf51dev.dts
+++ b/arch/arm/boot/dts/imx51-apf51dev.dts
@@ -98,7 +98,7 @@
&esdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1>;
- cd-gpios = <&gpio2 29 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio2 29 GPIO_ACTIVE_LOW>;
bus-width = <4>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts
index e9337ad..3bc1883 100644
--- a/arch/arm/boot/dts/imx53-ard.dts
+++ b/arch/arm/boot/dts/imx53-ard.dts
@@ -103,8 +103,8 @@
&esdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1>;
- cd-gpios = <&gpio1 1 0>;
- wp-gpios = <&gpio1 9 0>;
+ cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts
index d0e0f57..53f4088 100644
--- a/arch/arm/boot/dts/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/imx53-m53evk.dts
@@ -124,8 +124,8 @@
&esdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1>;
- cd-gpios = <&gpio1 1 0>;
- wp-gpios = <&gpio1 9 0>;
+ cd-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53-qsb-common.dtsi b/arch/arm/boot/dts/imx53-qsb-common.dtsi
index ab4ba39..b0d5542 100644
--- a/arch/arm/boot/dts/imx53-qsb-common.dtsi
+++ b/arch/arm/boot/dts/imx53-qsb-common.dtsi
@@ -147,8 +147,8 @@
&esdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc3>;
- cd-gpios = <&gpio3 11 0>;
- wp-gpios = <&gpio3 12 0>;
+ cd-gpios = <&gpio3 11 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>;
bus-width = <8>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53-smd.dts b/arch/arm/boot/dts/imx53-smd.dts
index 1d32557..fc89ce1 100644
--- a/arch/arm/boot/dts/imx53-smd.dts
+++ b/arch/arm/boot/dts/imx53-smd.dts
@@ -41,8 +41,8 @@
&esdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1>;
- cd-gpios = <&gpio3 13 0>;
- wp-gpios = <&gpio4 11 0>;
+ cd-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio4 11 GPIO_ACTIVE_HIGH>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx53-tqma53.dtsi b/arch/arm/boot/dts/imx53-tqma53.dtsi
index 4f1f0e2..e03373a 100644
--- a/arch/arm/boot/dts/imx53-tqma53.dtsi
+++ b/arch/arm/boot/dts/imx53-tqma53.dtsi
@@ -41,8 +41,8 @@
pinctrl-0 = <&pinctrl_esdhc2>,
<&pinctrl_esdhc2_cdwp>;
vmmc-supply = <®_3p3v>;
- wp-gpios = <&gpio1 2 0>;
- cd-gpios = <&gpio1 4 0>;
+ wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx53-tx53.dtsi b/arch/arm/boot/dts/imx53-tx53.dtsi
index 704bd72..d3e50b2 100644
--- a/arch/arm/boot/dts/imx53-tx53.dtsi
+++ b/arch/arm/boot/dts/imx53-tx53.dtsi
@@ -183,7 +183,7 @@
};
&esdhc1 {
- cd-gpios = <&gpio3 24 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
fsl,wp-controller;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1>;
@@ -191,7 +191,7 @@
};
&esdhc2 {
- cd-gpios = <&gpio3 25 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
fsl,wp-controller;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc2>;
diff --git a/arch/arm/boot/dts/imx53-voipac-bsb.dts b/arch/arm/boot/dts/imx53-voipac-bsb.dts
index c17d3ad..fc51b87 100644
--- a/arch/arm/boot/dts/imx53-voipac-bsb.dts
+++ b/arch/arm/boot/dts/imx53-voipac-bsb.dts
@@ -119,8 +119,8 @@
&esdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc2>;
- cd-gpios = <&gpio3 25 0>;
- wp-gpios = <&gpio2 19 0>;
+ cd-gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6dl-riotboard.dts b/arch/arm/boot/dts/imx6dl-riotboard.dts
index 43cb3fd..5111f51 100644
--- a/arch/arm/boot/dts/imx6dl-riotboard.dts
+++ b/arch/arm/boot/dts/imx6dl-riotboard.dts
@@ -305,8 +305,8 @@
&usdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
- cd-gpios = <&gpio1 4 0>;
- wp-gpios = <&gpio1 2 0>;
+ cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
@@ -314,8 +314,8 @@
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
- cd-gpios = <&gpio7 0 0>;
- wp-gpios = <&gpio7 1 0>;
+ cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-arm2.dts b/arch/arm/boot/dts/imx6q-arm2.dts
index 78df05e..d6515f7 100644
--- a/arch/arm/boot/dts/imx6q-arm2.dts
+++ b/arch/arm/boot/dts/imx6q-arm2.dts
@@ -11,6 +11,7 @@
*/
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
#include "imx6q.dtsi"
/ {
@@ -196,8 +197,8 @@
};
&usdhc3 {
- cd-gpios = <&gpio6 11 0>;
- wp-gpios = <&gpio6 14 0>;
+ cd-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio6 14 GPIO_ACTIVE_HIGH>;
vmmc-supply = <®_3p3v>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3
diff --git a/arch/arm/boot/dts/imx6q-gk802.dts b/arch/arm/boot/dts/imx6q-gk802.dts
index 703539c..00bd63e 100644
--- a/arch/arm/boot/dts/imx6q-gk802.dts
+++ b/arch/arm/boot/dts/imx6q-gk802.dts
@@ -7,6 +7,7 @@
*/
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
#include "imx6q.dtsi"
/ {
@@ -161,7 +162,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
bus-width = <4>;
- cd-gpios = <&gpio6 11 0>;
+ cd-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6q-tbs2910.dts b/arch/arm/boot/dts/imx6q-tbs2910.dts
index a43abfa..5645d52 100644
--- a/arch/arm/boot/dts/imx6q-tbs2910.dts
+++ b/arch/arm/boot/dts/imx6q-tbs2910.dts
@@ -251,7 +251,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
bus-width = <4>;
- cd-gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
@@ -260,7 +260,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
bus-width = <4>;
- cd-gpios = <&gpio2 0 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
vmmc-supply = <®_3p3v>;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi b/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi
index e6d9195..f4d6ae5 100644
--- a/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-aristainetos.dtsi
@@ -173,7 +173,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1>;
vmmc-supply = <®_3p3v>;
- cd-gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio4 7 GPIO_ACTIVE_LOW>;
status = "okay";
};
@@ -181,7 +181,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
vmmc-supply = <®_3p3v>;
- cd-gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio4 8 GPIO_ACTIVE_LOW>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi b/arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi
index 1d85de2..a47a039 100644
--- a/arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-aristainetos2.dtsi
@@ -392,7 +392,7 @@
&usdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1>;
- cd-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
no-1-8-v;
status = "okay";
};
@@ -400,7 +400,7 @@
&usdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
- cd-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio4 5 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
no-1-8-v;
status = "okay";
diff --git a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
index 59e5d15..ff41f83 100644
--- a/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-cubox-i.dtsi
@@ -258,6 +258,6 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_cubox_i_usdhc2_aux &pinctrl_cubox_i_usdhc2>;
vmmc-supply = <®_3p3v>;
- cd-gpios = <&gpio1 4 0>;
+ cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi b/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi
index 2c253d6..45e7c39 100644
--- a/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-dfi-fs700-m60.dtsi
@@ -1,3 +1,5 @@
+#include <dt-bindings/gpio/gpio.h>
+
/ {
regulators {
compatible = "simple-bus";
@@ -181,7 +183,7 @@
&usdhc2 { /* module slot */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
- cd-gpios = <&gpio2 2 0>;
+ cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
index b5756c2..4493f6e 100644
--- a/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw52xx.dtsi
@@ -318,7 +318,7 @@
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
- cd-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
index 86f03c1..a857d12 100644
--- a/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw53xx.dtsi
@@ -324,7 +324,7 @@
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
- cd-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
index 4a8d97f..1afe338 100644
--- a/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-gw54xx.dtsi
@@ -417,7 +417,7 @@
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
- cd-gpios = <&gpio7 0 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
index 62a82f3..6dd0b76 100644
--- a/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-hummingboard.dtsi
@@ -299,6 +299,6 @@
&pinctrl_hummingboard_usdhc2
>;
vmmc-supply = <®_3p3v>;
- cd-gpios = <&gpio1 4 0>;
+ cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
index 3af16df..d7fe667 100644
--- a/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-nitrogen6x.dtsi
@@ -453,7 +453,7 @@
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
- cd-gpios = <&gpio7 0 0>;
+ cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
@@ -461,7 +461,7 @@
&usdhc4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc4>;
- cd-gpios = <&gpio2 6 0>;
+ cd-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
index 1ce6133..9e6ecd9 100644
--- a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi
@@ -409,8 +409,8 @@
&usdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
- cd-gpios = <&gpio1 4 0>;
- wp-gpios = <&gpio1 2 0>;
+ cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
status = "disabled";
};
@@ -418,7 +418,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3
&pinctrl_usdhc3_cdwp>;
- cd-gpios = <&gpio1 27 0>;
- wp-gpios = <&gpio1 29 0>;
+ cd-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/imx6qdl-rex.dtsi b/arch/arm/boot/dts/imx6qdl-rex.dtsi
index 488a640..3373fd9 100644
--- a/arch/arm/boot/dts/imx6qdl-rex.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-rex.dtsi
@@ -342,7 +342,7 @@
pinctrl-0 = <&pinctrl_usdhc2>;
bus-width = <4>;
cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
- wp-gpios = <&gpio2 3 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
status = "okay";
};
@@ -351,6 +351,6 @@
pinctrl-0 = <&pinctrl_usdhc3>;
bus-width = <4>;
cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
- wp-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 3b24b126..e329ca5 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -467,8 +467,8 @@
pinctrl-0 = <&pinctrl_usdhc3>;
pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
- cd-gpios = <&gpio6 15 0>;
- wp-gpios = <&gpio1 13 0>;
+ cd-gpios = <&gpio6 15 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
index e00c44f..7823793 100644
--- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
@@ -448,8 +448,8 @@
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
- cd-gpios = <&gpio7 0 0>;
- wp-gpios = <&gpio7 1 0>;
+ cd-gpios = <&gpio7 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio7 1 GPIO_ACTIVE_HIGH>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
@@ -457,7 +457,7 @@
&usdhc4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc4>;
- cd-gpios = <&gpio2 6 0>;
+ cd-gpios = <&gpio2 6 GPIO_ACTIVE_LOW>;
vmmc-supply = <®_3p3v>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index a626e6d..944eb81 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -562,8 +562,8 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc2>;
bus-width = <8>;
- cd-gpios = <&gpio2 2 0>;
- wp-gpios = <&gpio2 3 0>;
+ cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
status = "okay";
};
@@ -571,8 +571,8 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
bus-width = <8>;
- cd-gpios = <&gpio2 0 0>;
- wp-gpios = <&gpio2 1 0>;
+ cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-tx6.dtsi b/arch/arm/boot/dts/imx6qdl-tx6.dtsi
index f02b80b..da08de3 100644
--- a/arch/arm/boot/dts/imx6qdl-tx6.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-tx6.dtsi
@@ -680,7 +680,7 @@
pinctrl-0 = <&pinctrl_usdhc1>;
bus-width = <4>;
no-1-8-v;
- cd-gpios = <&gpio7 2 0>;
+ cd-gpios = <&gpio7 2 GPIO_ACTIVE_LOW>;
fsl,wp-controller;
status = "okay";
};
@@ -690,7 +690,7 @@
pinctrl-0 = <&pinctrl_usdhc2>;
bus-width = <4>;
no-1-8-v;
- cd-gpios = <&gpio7 3 0>;
+ cd-gpios = <&gpio7 3 GPIO_ACTIVE_LOW>;
fsl,wp-controller;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index 5fb0916..9e096d8 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -9,6 +9,8 @@
*
*/
+#include <dt-bindings/gpio/gpio.h>
+
/ {
regulators {
compatible = "simple-bus";
@@ -250,13 +252,13 @@
&usdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1>;
- cd-gpios = <&gpio1 2 0>;
+ cd-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>;
status = "okay";
};
&usdhc3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc3>;
- cd-gpios = <&gpio3 9 0>;
+ cd-gpios = <&gpio3 9 GPIO_ACTIVE_LOW>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index e6d1359..b57033e 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -181,10 +181,10 @@
interrupt-names = "msi";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
- interrupt-map = <0 0 0 1 &intc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
- <0 0 0 2 &intc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
- <0 0 0 3 &intc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
- <0 0 0 4 &intc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-map = <0 0 0 1 &gpc GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &gpc GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &gpc GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &gpc GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6QDL_CLK_PCIE_AXI>,
<&clks IMX6QDL_CLK_LVDS1_GATE>,
<&clks IMX6QDL_CLK_PCIE_REF_125M>;
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 945887d..b84dff2 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -617,8 +617,8 @@
pinctrl-1 = <&pinctrl_usdhc1_100mhz>;
pinctrl-2 = <&pinctrl_usdhc1_200mhz>;
bus-width = <8>;
- cd-gpios = <&gpio4 7 0>;
- wp-gpios = <&gpio4 6 0>;
+ cd-gpios = <&gpio4 7 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
status = "okay";
};
@@ -627,8 +627,8 @@
pinctrl-0 = <&pinctrl_usdhc2>;
pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
- cd-gpios = <&gpio5 0 0>;
- wp-gpios = <&gpio4 29 0>;
+ cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio4 29 GPIO_ACTIVE_HIGH>;
status = "okay";
};
@@ -637,6 +637,6 @@
pinctrl-0 = <&pinctrl_usdhc3>;
pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
- cd-gpios = <&gpio3 22 0>;
+ cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6sx-sabreauto.dts b/arch/arm/boot/dts/imx6sx-sabreauto.dts
index e3c0b63..115f3fd 100644
--- a/arch/arm/boot/dts/imx6sx-sabreauto.dts
+++ b/arch/arm/boot/dts/imx6sx-sabreauto.dts
@@ -49,7 +49,7 @@
pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
bus-width = <8>;
- cd-gpios = <&gpio7 10 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio7 10 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>;
keep-power-in-suspend;
enable-sdio-wakeup;
@@ -61,7 +61,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc4>;
bus-width = <8>;
- cd-gpios = <&gpio7 11 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio7 11 GPIO_ACTIVE_LOW>;
no-1-8-v;
keep-power-in-suspend;
enable-sdio-wakup;
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dtsi b/arch/arm/boot/dts/imx6sx-sdb.dtsi
index cef04ce..ac88c34 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dtsi
+++ b/arch/arm/boot/dts/imx6sx-sdb.dtsi
@@ -293,7 +293,7 @@
pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
bus-width = <8>;
- cd-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio2 10 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio2 15 GPIO_ACTIVE_HIGH>;
keep-power-in-suspend;
enable-sdio-wakeup;
@@ -304,7 +304,7 @@
&usdhc4 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc4>;
- cd-gpios = <&gpio6 21 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio6 21 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio6 20 GPIO_ACTIVE_HIGH>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx7d-sdb.dts b/arch/arm/boot/dts/imx7d-sdb.dts
index 4d1a4b9..fdd1d7c 100644
--- a/arch/arm/boot/dts/imx7d-sdb.dts
+++ b/arch/arm/boot/dts/imx7d-sdb.dts
@@ -234,8 +234,8 @@
&usdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1>;
- cd-gpios = <&gpio5 0 0>;
- wp-gpios = <&gpio5 1 0>;
+ cd-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>;
enable-sdio-wakeup;
keep-power-in-suspend;
status = "okay";
diff --git a/arch/arm/boot/dts/k2e-clocks.dtsi b/arch/arm/boot/dts/k2e-clocks.dtsi
index 4773d6a..d56d68f 100644
--- a/arch/arm/boot/dts/k2e-clocks.dtsi
+++ b/arch/arm/boot/dts/k2e-clocks.dtsi
@@ -13,9 +13,8 @@
#clock-cells = <0>;
compatible = "ti,keystone,main-pll-clock";
clocks = <&refclksys>;
- reg = <0x02620350 4>, <0x02310110 4>;
- reg-names = "control", "multiplier";
- fixed-postdiv = <2>;
+ reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+ reg-names = "control", "multiplier", "post-divider";
};
papllclk: papllclk@2620358 {
diff --git a/arch/arm/boot/dts/k2e.dtsi b/arch/arm/boot/dts/k2e.dtsi
index 1b6494f..675fb8e 100644
--- a/arch/arm/boot/dts/k2e.dtsi
+++ b/arch/arm/boot/dts/k2e.dtsi
@@ -131,10 +131,17 @@
<GIC_SPI 376 IRQ_TYPE_EDGE_RISING>;
};
};
+
+ mdio: mdio@24200f00 {
+ compatible = "ti,keystone_mdio", "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x24200f00 0x100>;
+ status = "disabled";
+ clocks = <&clkcpgmac>;
+ clock-names = "fck";
+ bus_freq = <2500000>;
+ };
/include/ "k2e-netcp.dtsi"
};
};
-
-&mdio {
- reg = <0x24200f00 0x100>;
-};
diff --git a/arch/arm/boot/dts/k2hk-clocks.dtsi b/arch/arm/boot/dts/k2hk-clocks.dtsi
index d5adee3..af9b719 100644
--- a/arch/arm/boot/dts/k2hk-clocks.dtsi
+++ b/arch/arm/boot/dts/k2hk-clocks.dtsi
@@ -22,9 +22,8 @@
#clock-cells = <0>;
compatible = "ti,keystone,main-pll-clock";
clocks = <&refclksys>;
- reg = <0x02620350 4>, <0x02310110 4>;
- reg-names = "control", "multiplier";
- fixed-postdiv = <2>;
+ reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+ reg-names = "control", "multiplier", "post-divider";
};
papllclk: papllclk@2620358 {
diff --git a/arch/arm/boot/dts/k2hk.dtsi b/arch/arm/boot/dts/k2hk.dtsi
index ae64724..d0810a5 100644
--- a/arch/arm/boot/dts/k2hk.dtsi
+++ b/arch/arm/boot/dts/k2hk.dtsi
@@ -98,6 +98,17 @@
#gpio-cells = <2>;
gpio,syscon-dev = <&devctrl 0x25c>;
};
+
+ mdio: mdio@02090300 {
+ compatible = "ti,keystone_mdio", "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x02090300 0x100>;
+ status = "disabled";
+ clocks = <&clkcpgmac>;
+ clock-names = "fck";
+ bus_freq = <2500000>;
+ };
/include/ "k2hk-netcp.dtsi"
};
};
diff --git a/arch/arm/boot/dts/k2l-clocks.dtsi b/arch/arm/boot/dts/k2l-clocks.dtsi
index eb1e3e2..ef8464b 100644
--- a/arch/arm/boot/dts/k2l-clocks.dtsi
+++ b/arch/arm/boot/dts/k2l-clocks.dtsi
@@ -22,9 +22,8 @@
#clock-cells = <0>;
compatible = "ti,keystone,main-pll-clock";
clocks = <&refclksys>;
- reg = <0x02620350 4>, <0x02310110 4>;
- reg-names = "control", "multiplier";
- fixed-postdiv = <2>;
+ reg = <0x02620350 4>, <0x02310110 4>, <0x02310108 4>;
+ reg-names = "control", "multiplier", "post-divider";
};
papllclk: papllclk@2620358 {
diff --git a/arch/arm/boot/dts/k2l.dtsi b/arch/arm/boot/dts/k2l.dtsi
index 0e00748..49fd414 100644
--- a/arch/arm/boot/dts/k2l.dtsi
+++ b/arch/arm/boot/dts/k2l.dtsi
@@ -29,7 +29,6 @@
};
soc {
-
/include/ "k2l-clocks.dtsi"
uart2: serial@02348400 {
@@ -79,6 +78,17 @@
#gpio-cells = <2>;
gpio,syscon-dev = <&devctrl 0x24c>;
};
+
+ mdio: mdio@26200f00 {
+ compatible = "ti,keystone_mdio", "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x26200f00 0x100>;
+ status = "disabled";
+ clocks = <&clkcpgmac>;
+ clock-names = "fck";
+ bus_freq = <2500000>;
+ };
/include/ "k2l-netcp.dtsi"
};
};
@@ -96,7 +106,3 @@
/* Pin muxed. Enabled and configured by Bootloader */
status = "disabled";
};
-
-&mdio {
- reg = <0x26200f00 0x100>;
-};
diff --git a/arch/arm/boot/dts/keystone.dtsi b/arch/arm/boot/dts/keystone.dtsi
index e7a6f6d..72816d6 100644
--- a/arch/arm/boot/dts/keystone.dtsi
+++ b/arch/arm/boot/dts/keystone.dtsi
@@ -267,17 +267,6 @@
1 0 0x21000A00 0x00000100>;
};
- mdio: mdio@02090300 {
- compatible = "ti,keystone_mdio", "ti,davinci_mdio";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x02090300 0x100>;
- status = "disabled";
- clocks = <&clkpa>;
- clock-names = "fck";
- bus_freq = <2500000>;
- };
-
kirq0: keystone_irq@26202a0 {
compatible = "ti,keystone-irq";
interrupts = <GIC_SPI 4 IRQ_TYPE_EDGE_RISING>;
diff --git a/arch/arm/boot/dts/omap2430.dtsi b/arch/arm/boot/dts/omap2430.dtsi
index 11a7963..2390f38 100644
--- a/arch/arm/boot/dts/omap2430.dtsi
+++ b/arch/arm/boot/dts/omap2430.dtsi
@@ -51,7 +51,8 @@
};
scm_conf: scm_conf@270 {
- compatible = "syscon";
+ compatible = "syscon",
+ "simple-bus";
reg = <0x270 0x240>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 7d31c6f..abc4473 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -191,7 +191,8 @@
};
omap4_padconf_global: omap4_padconf_global@5a0 {
- compatible = "syscon";
+ compatible = "syscon",
+ "simple-bus";
reg = <0x5a0 0x170>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
index c8fd648..b1a1263 100644
--- a/arch/arm/boot/dts/omap5.dtsi
+++ b/arch/arm/boot/dts/omap5.dtsi
@@ -180,7 +180,8 @@
};
omap5_padconf_global: omap5_padconf_global@5a0 {
- compatible = "syscon";
+ compatible = "syscon",
+ "simple-bus";
reg = <0x5a0 0xec>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts
index bd35b06..9bc72a3 100644
--- a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts
+++ b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts
@@ -17,3 +17,13 @@
status = "ok";
};
};
+
+&spmi_bus {
+ pm8941@0 {
+ coincell@2800 {
+ status = "ok";
+ qcom,rset-ohms = <2100>;
+ qcom,vset-millivolts = <3000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom-pm8941.dtsi b/arch/arm/boot/dts/qcom-pm8941.dtsi
index aa774e6..968f104 100644
--- a/arch/arm/boot/dts/qcom-pm8941.dtsi
+++ b/arch/arm/boot/dts/qcom-pm8941.dtsi
@@ -125,6 +125,12 @@
interrupts = <0x0 0x36 0x0 IRQ_TYPE_EDGE_RISING>;
qcom,external-resistor-micro-ohms = <10000>;
};
+
+ coincell@2800 {
+ compatible = "qcom,pm8941-coincell";
+ reg = <0x2800>;
+ status = "disabled";
+ };
};
usid1: pm8941@1 {
diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi
index a75f328..b8f81fb 100644
--- a/arch/arm/boot/dts/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi
@@ -15,6 +15,33 @@
#include "skeleton.dtsi"
/ {
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ enable-method = "ste,dbx500-smp";
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+ core1 {
+ cpu = <&CPU1>;
+ };
+ };
+ };
+ CPU0: cpu@300 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0x300>;
+ };
+ CPU1: cpu@301 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a9";
+ reg = <0x301>;
+ };
+ };
+
soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -22,32 +49,6 @@
interrupt-parent = <&intc>;
ranges;
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu-map {
- cluster0 {
- core0 {
- cpu = <&CPU0>;
- };
- core1 {
- cpu = <&CPU1>;
- };
- };
- };
- CPU0: cpu@0 {
- device_type = "cpu";
- compatible = "arm,cortex-a9";
- reg = <0>;
- };
- CPU1: cpu@1 {
- device_type = "cpu";
- compatible = "arm,cortex-a9";
- reg = <1>;
- };
- };
-
ptm@801ae000 {
compatible = "arm,coresight-etm3x", "arm,primecell";
reg = <0x801ae000 0x1000>;
diff --git a/arch/arm/boot/dts/ste-nomadik-nhk15.dts b/arch/arm/boot/dts/ste-nomadik-nhk15.dts
index 3d0b875..3d25dba 100644
--- a/arch/arm/boot/dts/ste-nomadik-nhk15.dts
+++ b/arch/arm/boot/dts/ste-nomadik-nhk15.dts
@@ -17,6 +17,7 @@
};
aliases {
+ serial1 = &uart1;
stmpe-i2c0 = &stmpe0;
stmpe-i2c1 = &stmpe1;
};
diff --git a/arch/arm/boot/dts/ste-nomadik-s8815.dts b/arch/arm/boot/dts/ste-nomadik-s8815.dts
index 85d3b95..3c140d0 100644
--- a/arch/arm/boot/dts/ste-nomadik-s8815.dts
+++ b/arch/arm/boot/dts/ste-nomadik-s8815.dts
@@ -15,6 +15,10 @@
bootargs = "root=/dev/ram0 console=ttyAMA1,115200n8 earlyprintk";
};
+ aliases {
+ serial1 = &uart1;
+ };
+
src@101e0000 {
/* These chrystal drivers are not used on this board */
disable-sxtalo;
diff --git a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
index 9a5f2ba..ef794a3 100644
--- a/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
+++ b/arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
@@ -757,6 +757,7 @@
clock-names = "uartclk", "apb_pclk";
pinctrl-names = "default";
pinctrl-0 = <&uart0_default_mux>;
+ status = "disabled";
};
uart1: uart@101fb000 {
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 92828a1..b48dd4f 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -61,6 +61,7 @@
movlt scno, #(__NR_restart_syscall - __NR_SYSCALL_BASE)
ldmia sp, {r0 - r6} @ have to reload r0 - r6
b local_restart @ ... and off we go
+ENDPROC(ret_fast_syscall)
/*
* "slow" syscall return path. "why" tells us if this was a real syscall.
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index bd755d9..29e2991 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -399,6 +399,9 @@
sub lr, r4, r5 @ mmu has been enabled
add r3, r7, lr
ldrd r4, [r3, #0] @ get secondary_data.pgdir
+ARM_BE8(eor r4, r4, r5) @ Swap r5 and r4 in BE:
+ARM_BE8(eor r5, r4, r5) @ it can be done in 3 steps
+ARM_BE8(eor r4, r4, r5) @ without using a temp reg.
ldr r8, [r3, #8] @ get secondary_data.swapper_pg_dir
badr lr, __enable_mmu @ return address
mov r13, r12 @ __secondary_switched address
diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c
index efe17dd..54a5aea 100644
--- a/arch/arm/kernel/vdso.c
+++ b/arch/arm/kernel/vdso.c
@@ -296,7 +296,6 @@
*/
void update_vsyscall(struct timekeeper *tk)
{
- struct timespec xtime_coarse;
struct timespec64 *wtm = &tk->wall_to_monotonic;
if (!cntvct_ok) {
@@ -308,10 +307,10 @@
vdso_write_begin(vdso_data);
- xtime_coarse = __current_kernel_time();
vdso_data->tk_is_cntvct = tk_is_cntvct(tk);
- vdso_data->xtime_coarse_sec = xtime_coarse.tv_sec;
- vdso_data->xtime_coarse_nsec = xtime_coarse.tv_nsec;
+ vdso_data->xtime_coarse_sec = tk->xtime_sec;
+ vdso_data->xtime_coarse_nsec = (u32)(tk->tkr_mono.xtime_nsec >>
+ tk->tkr_mono.shift);
vdso_data->wtm_clock_sec = wtm->tv_sec;
vdso_data->wtm_clock_nsec = wtm->tv_nsec;
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c
index 3e58d71..4b39af2 100644
--- a/arch/arm/lib/uaccess_with_memcpy.c
+++ b/arch/arm/lib/uaccess_with_memcpy.c
@@ -96,7 +96,7 @@
}
/* the mmap semaphore is taken only if not in an atomic context */
- atomic = in_atomic();
+ atomic = faulthandler_disabled();
if (!atomic)
down_read(¤t->mm->mmap_sem);
diff --git a/arch/arm/mach-exynos/pm_domains.c b/arch/arm/mach-exynos/pm_domains.c
index 6001f1c..4a87e86 100644
--- a/arch/arm/mach-exynos/pm_domains.c
+++ b/arch/arm/mach-exynos/pm_domains.c
@@ -146,9 +146,8 @@
pd->base = of_iomap(np, 0);
if (!pd->base) {
pr_warn("%s: failed to map memory\n", __func__);
- kfree(pd->pd.name);
+ kfree_const(pd->pd.name);
kfree(pd);
- of_node_put(np);
continue;
}
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 8e52621..e1d2e99 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -392,6 +392,7 @@
.irq_mask = wakeupgen_mask,
.irq_unmask = wakeupgen_unmask,
.irq_retrigger = irq_chip_retrigger_hierarchy,
+ .irq_set_type = irq_chip_set_type_parent,
.flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
#ifdef CONFIG_SMP
.irq_set_affinity = irq_chip_set_affinity_parent,
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index d78c12e..486cc4d 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -2373,6 +2373,9 @@
* registers. This address is needed early so the OCP registers that
* are part of the device's address space can be ioremapped properly.
*
+ * If SYSC access is not needed, the registers will not be remapped
+ * and non-availability of MPU access is not treated as an error.
+ *
* Returns 0 on success, -EINVAL if an invalid hwmod is passed, and
* -ENXIO on absent or invalid register target address space.
*/
@@ -2387,6 +2390,11 @@
_save_mpu_port_index(oh);
+ /* if we don't need sysc access we don't need to ioremap */
+ if (!oh->class->sysc)
+ return 0;
+
+ /* we can't continue without MPU PORT if we need sysc access */
if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
return -ENXIO;
@@ -2396,8 +2404,10 @@
oh->name);
/* Extract the IO space from device tree blob */
- if (!np)
+ if (!np) {
+ pr_err("omap_hwmod: %s: no dt node\n", oh->name);
return -ENXIO;
+ }
va_start = of_iomap(np, index + oh->mpu_rt_idx);
} else {
@@ -2456,13 +2466,11 @@
oh->name, np->name);
}
- if (oh->class->sysc) {
- r = _init_mpu_rt_base(oh, NULL, index, np);
- if (r < 0) {
- WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
- oh->name);
- return 0;
- }
+ r = _init_mpu_rt_base(oh, NULL, index, np);
+ if (r < 0) {
+ WARN(1, "omap_hwmod: %s: doesn't have mpu register target base\n",
+ oh->name);
+ return 0;
}
r = _init_clocks(oh, NULL);
diff --git a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
index 2606c66..562247b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_7xx_data.c
@@ -827,8 +827,7 @@
.syss_offs = 0x0014,
.sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- SIDLE_SMART_WKUP),
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
.sysc_fields = &omap_hwmod_sysc_type1,
};
@@ -844,7 +843,7 @@
.class = &dra7xx_gpmc_hwmod_class,
.clkdm_name = "l3main1_clkdm",
/* Skip reset for CONFIG_OMAP_GPMC_DEBUG for bootloader timings */
- .flags = HWMOD_SWSUP_SIDLE | DEBUG_OMAP_GPMC_HWMOD_FLAGS,
+ .flags = DEBUG_OMAP_GPMC_HWMOD_FLAGS,
.main_clk = "l3_iclk_div",
.prcm = {
.omap4 = {
diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c
index 4550d24..c011e22 100644
--- a/arch/arm/net/bpf_jit_32.c
+++ b/arch/arm/net/bpf_jit_32.c
@@ -74,32 +74,52 @@
int bpf_jit_enable __read_mostly;
-static u64 jit_get_skb_b(struct sk_buff *skb, unsigned offset)
+static inline int call_neg_helper(struct sk_buff *skb, int offset, void *ret,
+ unsigned int size)
+{
+ void *ptr = bpf_internal_load_pointer_neg_helper(skb, offset, size);
+
+ if (!ptr)
+ return -EFAULT;
+ memcpy(ret, ptr, size);
+ return 0;
+}
+
+static u64 jit_get_skb_b(struct sk_buff *skb, int offset)
{
u8 ret;
int err;
- err = skb_copy_bits(skb, offset, &ret, 1);
+ if (offset < 0)
+ err = call_neg_helper(skb, offset, &ret, 1);
+ else
+ err = skb_copy_bits(skb, offset, &ret, 1);
return (u64)err << 32 | ret;
}
-static u64 jit_get_skb_h(struct sk_buff *skb, unsigned offset)
+static u64 jit_get_skb_h(struct sk_buff *skb, int offset)
{
u16 ret;
int err;
- err = skb_copy_bits(skb, offset, &ret, 2);
+ if (offset < 0)
+ err = call_neg_helper(skb, offset, &ret, 2);
+ else
+ err = skb_copy_bits(skb, offset, &ret, 2);
return (u64)err << 32 | ntohs(ret);
}
-static u64 jit_get_skb_w(struct sk_buff *skb, unsigned offset)
+static u64 jit_get_skb_w(struct sk_buff *skb, int offset)
{
u32 ret;
int err;
- err = skb_copy_bits(skb, offset, &ret, 4);
+ if (offset < 0)
+ err = call_neg_helper(skb, offset, &ret, 4);
+ else
+ err = skb_copy_bits(skb, offset, &ret, 4);
return (u64)err << 32 | ntohl(ret);
}
@@ -536,9 +556,6 @@
case BPF_LD | BPF_B | BPF_ABS:
load_order = 0;
load:
- /* the interpreter will deal with the negative K */
- if ((int)k < 0)
- return -ENOTSUPP;
emit_mov_i(r_off, k, ctx);
load_common:
ctx->seen |= SEEN_DATA | SEEN_CALL;
@@ -547,12 +564,24 @@
emit(ARM_SUB_I(r_scratch, r_skb_hl,
1 << load_order), ctx);
emit(ARM_CMP_R(r_scratch, r_off), ctx);
- condt = ARM_COND_HS;
+ condt = ARM_COND_GE;
} else {
emit(ARM_CMP_R(r_skb_hl, r_off), ctx);
condt = ARM_COND_HI;
}
+ /*
+ * test for negative offset, only if we are
+ * currently scheduled to take the fast
+ * path. this will update the flags so that
+ * the slowpath instruction are ignored if the
+ * offset is negative.
+ *
+ * for loard_order == 0 the HI condition will
+ * make loads at offset 0 take the slow path too.
+ */
+ _emit(condt, ARM_CMP_I(r_off, 0), ctx);
+
_emit(condt, ARM_ADD_R(r_scratch, r_off, r_skb_data),
ctx);
@@ -860,9 +889,11 @@
off = offsetof(struct sk_buff, vlan_tci);
emit(ARM_LDRH_I(r_A, r_skb, off), ctx);
if (code == (BPF_ANC | SKF_AD_VLAN_TAG))
- OP_IMM3(ARM_AND, r_A, r_A, VLAN_VID_MASK, ctx);
- else
- OP_IMM3(ARM_AND, r_A, r_A, VLAN_TAG_PRESENT, ctx);
+ OP_IMM3(ARM_AND, r_A, r_A, ~VLAN_TAG_PRESENT, ctx);
+ else {
+ OP_IMM3(ARM_LSR, r_A, r_A, 12, ctx);
+ OP_IMM3(ARM_AND, r_A, r_A, 0x1, ctx);
+ }
break;
case BPF_ANC | SKF_AD_QUEUE:
ctx->seen |= SEEN_SKB;
diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile
index 9d259d9..1160434 100644
--- a/arch/arm/vdso/Makefile
+++ b/arch/arm/vdso/Makefile
@@ -14,7 +14,7 @@
VDSO_LDFLAGS += -nostdlib -shared
VDSO_LDFLAGS += $(call cc-ldoption, -Wl$(comma)--hash-style=sysv)
VDSO_LDFLAGS += $(call cc-ldoption, -Wl$(comma)--build-id)
-VDSO_LDFLAGS += $(call cc-option, -fuse-ld=bfd)
+VDSO_LDFLAGS += $(call cc-ldoption, -fuse-ld=bfd)
obj-$(CONFIG_VDSO) += vdso.o
extra-$(CONFIG_VDSO) += vdso.lds
diff --git a/arch/arm64/boot/dts/apm/apm-storm.dtsi b/arch/arm64/boot/dts/apm/apm-storm.dtsi
index 0689c3f..58093ed 100644
--- a/arch/arm64/boot/dts/apm/apm-storm.dtsi
+++ b/arch/arm64/boot/dts/apm/apm-storm.dtsi
@@ -823,7 +823,7 @@
device_type = "dma";
reg = <0x0 0x1f270000 0x0 0x10000>,
<0x0 0x1f200000 0x0 0x10000>,
- <0x0 0x1b008000 0x0 0x2000>,
+ <0x0 0x1b000000 0x0 0x400000>,
<0x0 0x1054a000 0x0 0x100>;
interrupts = <0x0 0x82 0x4>,
<0x0 0xb8 0x4>,
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index 9d4aa18..e8ca6ea 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -122,12 +122,12 @@
/* Show what we know for posterity */
c16 = early_memremap(efi_to_phys(efi.systab->fw_vendor),
- sizeof(vendor));
+ sizeof(vendor) * sizeof(efi_char16_t));
if (c16) {
for (i = 0; i < (int) sizeof(vendor) - 1 && *c16; ++i)
vendor[i] = c16[i];
vendor[i] = '\0';
- early_memunmap(c16, sizeof(vendor));
+ early_memunmap(c16, sizeof(vendor) * sizeof(efi_char16_t));
}
pr_info("EFI v%u.%.02u by %s\n",
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index f860bfd..e163518 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -585,7 +585,8 @@
*
*/
ENTRY(cpu_switch_to)
- add x8, x0, #THREAD_CPU_CONTEXT
+ mov x10, #THREAD_CPU_CONTEXT
+ add x8, x0, x10
mov x9, sp
stp x19, x20, [x8], #16 // store callee-saved registers
stp x21, x22, [x8], #16
@@ -594,7 +595,7 @@
stp x27, x28, [x8], #16
stp x29, x9, [x8], #16
str lr, [x8]
- add x8, x1, #THREAD_CPU_CONTEXT
+ add x8, x1, x10
ldp x19, x20, [x8], #16 // restore callee-saved registers
ldp x21, x22, [x8], #16
ldp x23, x24, [x8], #16
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
index 240b75c..463fa2e 100644
--- a/arch/arm64/kernel/irq.c
+++ b/arch/arm64/kernel/irq.c
@@ -61,7 +61,7 @@
static bool migrate_one_irq(struct irq_desc *desc)
{
struct irq_data *d = irq_desc_get_irq_data(desc);
- const struct cpumask *affinity = d->affinity;
+ const struct cpumask *affinity = irq_data_get_affinity_mask(d);
struct irq_chip *c;
bool ret = false;
@@ -81,7 +81,7 @@
if (!c->irq_set_affinity)
pr_debug("IRQ%u: unable to set affinity\n", d->irq);
else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret)
- cpumask_copy(d->affinity, affinity);
+ cpumask_copy(irq_data_get_affinity_mask(d), affinity);
return ret;
}
diff --git a/arch/arm64/kernel/signal32.c b/arch/arm64/kernel/signal32.c
index 1670f15..948f0ad 100644
--- a/arch/arm64/kernel/signal32.c
+++ b/arch/arm64/kernel/signal32.c
@@ -168,7 +168,8 @@
* Other callers might not initialize the si_lsb field,
* so check explicitely for the right codes here.
*/
- if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)
+ if (from->si_signo == SIGBUS &&
+ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
#endif
break;
@@ -201,8 +202,6 @@
int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
- memset(to, 0, sizeof *to);
-
if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
copy_from_user(to->_sifields._pad,
from->_sifields._pad, SI_PAD_SIZE))
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index ec37ab3..97bc68f 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -199,16 +199,15 @@
*/
void update_vsyscall(struct timekeeper *tk)
{
- struct timespec xtime_coarse;
u32 use_syscall = strcmp(tk->tkr_mono.clock->name, "arch_sys_counter");
++vdso_data->tb_seq_count;
smp_wmb();
- xtime_coarse = __current_kernel_time();
vdso_data->use_syscall = use_syscall;
- vdso_data->xtime_coarse_sec = xtime_coarse.tv_sec;
- vdso_data->xtime_coarse_nsec = xtime_coarse.tv_nsec;
+ vdso_data->xtime_coarse_sec = tk->xtime_sec;
+ vdso_data->xtime_coarse_nsec = tk->tkr_mono.xtime_nsec >>
+ tk->tkr_mono.shift;
vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec;
vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec;
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index f02530e..85c5715 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -168,8 +168,8 @@
{
if (!(vcpu->arch.hcr_el2 & HCR_RW))
inject_abt32(vcpu, false, addr);
-
- inject_abt64(vcpu, false, addr);
+ else
+ inject_abt64(vcpu, false, addr);
}
/**
@@ -184,8 +184,8 @@
{
if (!(vcpu->arch.hcr_el2 & HCR_RW))
inject_abt32(vcpu, true, addr);
-
- inject_abt64(vcpu, true, addr);
+ else
+ inject_abt64(vcpu, true, addr);
}
/**
@@ -198,6 +198,6 @@
{
if (!(vcpu->arch.hcr_el2 & HCR_RW))
inject_undef32(vcpu);
-
- inject_undef64(vcpu);
+ else
+ inject_undef64(vcpu);
}
diff --git a/arch/avr32/kernel/time.c b/arch/avr32/kernel/time.c
index d0f771b..a124c55 100644
--- a/arch/avr32/kernel/time.c
+++ b/arch/avr32/kernel/time.c
@@ -18,6 +18,7 @@
#include <mach/pm.h>
+static bool disable_cpu_idle_poll;
static cycle_t read_cycle_count(struct clocksource *cs)
{
@@ -80,45 +81,45 @@
return 0;
}
-static void comparator_mode(enum clock_event_mode mode,
- struct clock_event_device *evdev)
+static int comparator_shutdown(struct clock_event_device *evdev)
{
- switch (mode) {
- case CLOCK_EVT_MODE_ONESHOT:
- pr_debug("%s: start\n", evdev->name);
- /* FALLTHROUGH */
- case CLOCK_EVT_MODE_RESUME:
+ pr_debug("%s: %s\n", __func__, evdev->name);
+ sysreg_write(COMPARE, 0);
+
+ if (disable_cpu_idle_poll) {
+ disable_cpu_idle_poll = false;
/*
- * If we're using the COUNT and COMPARE registers we
- * need to force idle poll.
+ * Only disable idle poll if we have forced that
+ * in a previous call.
*/
- cpu_idle_poll_ctrl(true);
- break;
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- sysreg_write(COMPARE, 0);
- pr_debug("%s: stop\n", evdev->name);
- if (evdev->mode == CLOCK_EVT_MODE_ONESHOT ||
- evdev->mode == CLOCK_EVT_MODE_RESUME) {
- /*
- * Only disable idle poll if we have forced that
- * in a previous call.
- */
- cpu_idle_poll_ctrl(false);
- }
- break;
- default:
- BUG();
+ cpu_idle_poll_ctrl(false);
}
+ return 0;
+}
+
+static int comparator_set_oneshot(struct clock_event_device *evdev)
+{
+ pr_debug("%s: %s\n", __func__, evdev->name);
+
+ disable_cpu_idle_poll = true;
+ /*
+ * If we're using the COUNT and COMPARE registers we
+ * need to force idle poll.
+ */
+ cpu_idle_poll_ctrl(true);
+
+ return 0;
}
static struct clock_event_device comparator = {
- .name = "avr32_comparator",
- .features = CLOCK_EVT_FEAT_ONESHOT,
- .shift = 16,
- .rating = 50,
- .set_next_event = comparator_next_event,
- .set_mode = comparator_mode,
+ .name = "avr32_comparator",
+ .features = CLOCK_EVT_FEAT_ONESHOT,
+ .shift = 16,
+ .rating = 50,
+ .set_next_event = comparator_next_event,
+ .set_state_shutdown = comparator_shutdown,
+ .set_state_oneshot = comparator_set_oneshot,
+ .tick_resume = comparator_set_oneshot,
};
void read_persistent_clock(struct timespec *ts)
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c
index 23b1a97..52c179b 100644
--- a/arch/avr32/mach-at32ap/clock.c
+++ b/arch/avr32/mach-at32ap/clock.c
@@ -80,6 +80,9 @@
{
unsigned long flags;
+ if (!clk)
+ return 0;
+
spin_lock_irqsave(&clk_lock, flags);
__clk_enable(clk);
spin_unlock_irqrestore(&clk_lock, flags);
@@ -106,6 +109,9 @@
{
unsigned long flags;
+ if (IS_ERR_OR_NULL(clk))
+ return;
+
spin_lock_irqsave(&clk_lock, flags);
__clk_disable(clk);
spin_unlock_irqrestore(&clk_lock, flags);
@@ -117,6 +123,9 @@
unsigned long flags;
unsigned long rate;
+ if (!clk)
+ return 0;
+
spin_lock_irqsave(&clk_lock, flags);
rate = clk->get_rate(clk);
spin_unlock_irqrestore(&clk_lock, flags);
@@ -129,6 +138,9 @@
{
unsigned long flags, actual_rate;
+ if (!clk)
+ return 0;
+
if (!clk->set_rate)
return -ENOSYS;
@@ -145,6 +157,9 @@
unsigned long flags;
long ret;
+ if (!clk)
+ return 0;
+
if (!clk->set_rate)
return -ENOSYS;
@@ -161,6 +176,9 @@
unsigned long flags;
int ret;
+ if (!clk)
+ return 0;
+
if (!clk->set_parent)
return -ENOSYS;
@@ -174,7 +192,7 @@
struct clk *clk_get_parent(struct clk *clk)
{
- return clk->parent;
+ return !clk ? NULL : clk->parent;
}
EXPORT_SYMBOL(clk_get_parent);
diff --git a/arch/m32r/include/asm/io.h b/arch/m32r/include/asm/io.h
index 0c3f25e..f8de767 100644
--- a/arch/m32r/include/asm/io.h
+++ b/arch/m32r/include/asm/io.h
@@ -174,6 +174,11 @@
#define iowrite16 writew
#define iowrite32 writel
+#define ioread16be(addr) be16_to_cpu(readw(addr))
+#define ioread32be(addr) be32_to_cpu(readl(addr))
+#define iowrite16be(v, addr) writew(cpu_to_be16(v), (addr))
+#define iowrite32be(v, addr) writel(cpu_to_be32(v), (addr))
+
#define mmiowb()
#define flush_write_buffers() do { } while (0) /* M32R_FIXME */
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index 753a623..0b6b40d 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -57,7 +57,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -91,6 +91,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -287,7 +288,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -320,7 +320,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -345,6 +344,7 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
@@ -355,6 +355,7 @@
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_HP is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
@@ -363,6 +364,7 @@
CONFIG_APNE=y
CONFIG_ZORRO8390=y
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -448,6 +450,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -536,6 +539,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -543,6 +547,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -571,14 +576,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index 1f93dca..eeb3a89 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -55,7 +55,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -89,6 +89,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -279,7 +280,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -302,7 +302,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -327,17 +326,20 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -406,6 +408,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -494,6 +497,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -501,6 +505,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -529,14 +534,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index 831b8b8..3a70066 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -55,7 +55,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -89,6 +89,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -283,7 +284,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -311,7 +311,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -336,6 +335,7 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
@@ -343,11 +343,13 @@
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
CONFIG_NE2000=y
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -428,6 +430,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -516,6 +519,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -523,6 +527,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -551,14 +556,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index 91fd187..0586b32 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -53,7 +53,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -87,6 +87,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -277,7 +278,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -301,7 +301,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -326,17 +325,20 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
CONFIG_BVME6000_NET=y
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -399,6 +401,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -487,6 +490,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -494,6 +498,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -522,14 +527,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 9d4934f..ad1dbce 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -55,7 +55,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -89,6 +89,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -279,7 +280,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -302,7 +302,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -327,6 +326,7 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
@@ -334,11 +334,13 @@
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -408,6 +410,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -496,6 +499,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -503,6 +507,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -531,14 +536,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 72bc187..b44acac 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -54,7 +54,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -88,6 +88,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -282,7 +283,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -311,7 +311,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -343,6 +342,7 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
@@ -351,12 +351,14 @@
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
CONFIG_MAC89x0=y
+# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
CONFIG_MACSONIC=y
CONFIG_MAC8390=y
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -430,6 +432,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -518,6 +521,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -525,6 +529,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -553,14 +558,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index 8fb6553..8afca37 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -64,7 +64,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -98,6 +98,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -301,7 +302,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -344,7 +344,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -376,6 +375,7 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
@@ -391,6 +391,7 @@
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
CONFIG_MAC89x0=y
+# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_HP is not set
CONFIG_BVME6000_NET=y
CONFIG_MVME16x_NET=y
@@ -403,6 +404,7 @@
CONFIG_APNE=y
CONFIG_ZORRO8390=y
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -510,6 +512,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -598,6 +601,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -605,6 +609,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -633,14 +638,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index f34491e..ef00875 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -52,7 +52,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -86,6 +86,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -276,7 +277,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -300,7 +300,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -325,6 +324,7 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
@@ -332,11 +332,13 @@
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -399,6 +401,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -487,6 +490,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -494,6 +498,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -522,14 +527,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 3d3614d..387c2bd 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -53,7 +53,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -87,6 +87,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -277,7 +278,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -301,7 +301,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -326,17 +325,20 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
CONFIG_MVME16x_NET=y
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -399,6 +401,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -487,6 +490,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -494,6 +498,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -522,14 +527,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 643e9c9..35355c1 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -53,7 +53,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -87,6 +87,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -280,7 +281,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -307,7 +307,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -332,6 +331,7 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
@@ -341,12 +341,14 @@
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_HP is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
CONFIG_NE2000=y
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -421,6 +423,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -509,6 +512,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -516,6 +520,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -544,14 +549,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 8fecc5a..8442d26 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -50,7 +50,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -84,6 +84,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -274,7 +275,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -298,7 +298,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -323,17 +322,20 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
CONFIG_SUN3LANCE=y
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
CONFIG_SUN3_82586=y
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -400,6 +402,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -487,6 +490,7 @@
CONFIG_TEST_FIRMWARE=m
CONFIG_TEST_UDELAY=m
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -494,6 +498,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -522,14 +527,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index 9902c5b..0e1b542 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -50,7 +50,7 @@
CONFIG_NET_IPGRE=m
CONFIG_NET_IPVTI=m
CONFIG_NET_FOU_IP_TUNNELS=y
-CONFIG_GENEVE=m
+CONFIG_GENEVE_CORE=m
CONFIG_INET_AH=m
CONFIG_INET_ESP=m
CONFIG_INET_IPCOMP=m
@@ -84,6 +84,7 @@
CONFIG_NF_CONNTRACK_TFTP=m
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=m
+CONFIG_NF_TABLES_NETDEV=m
CONFIG_NFT_EXTHDR=m
CONFIG_NFT_META=m
CONFIG_NFT_CT=m
@@ -274,7 +275,6 @@
CONFIG_BLK_DEV_DRBD=m
CONFIG_BLK_DEV_NBD=m
CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_PMEM=m
CONFIG_CDROM_PKTCDVD=m
CONFIG_ATA_OVER_ETH=m
CONFIG_DUMMY_IRQ=m
@@ -298,7 +298,6 @@
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
-CONFIG_DM_CACHE=m
CONFIG_DM_ERA=m
CONFIG_DM_MIRROR=m
CONFIG_DM_RAID=m
@@ -323,6 +322,7 @@
CONFIG_MACVTAP=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
+CONFIG_GENEVE=m
CONFIG_NETCONSOLE=m
CONFIG_NETCONSOLE_DYNAMIC=y
CONFIG_VETH=m
@@ -330,11 +330,13 @@
# CONFIG_NET_VENDOR_ARC is not set
# CONFIG_NET_CADENCE is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_EZCHIP is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
# CONFIG_NET_VENDOR_MICREL is not set
# CONFIG_NET_VENDOR_NATSEMI is not set
# CONFIG_NET_VENDOR_QUALCOMM is not set
+# CONFIG_NET_VENDOR_RENESAS is not set
# CONFIG_NET_VENDOR_ROCKER is not set
# CONFIG_NET_VENDOR_SAMSUNG is not set
# CONFIG_NET_VENDOR_SEEQ is not set
@@ -400,6 +402,7 @@
CONFIG_MSDOS_FS=m
CONFIG_VFAT_FS=m
CONFIG_PROC_KCORE=y
+CONFIG_PROC_CHILDREN=y
CONFIG_TMPFS=y
CONFIG_AFFS_FS=m
CONFIG_ECRYPT_FS=m
@@ -488,6 +491,7 @@
CONFIG_TEST_UDELAY=m
CONFIG_EARLY_PRINTK=y
CONFIG_ENCRYPTED_KEYS=m
+CONFIG_CRYPTO_RSA=m
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_CRYPTD=m
@@ -495,6 +499,7 @@
CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_CCM=m
CONFIG_CRYPTO_GCM=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
CONFIG_CRYPTO_CTS=m
CONFIG_CRYPTO_LRW=m
CONFIG_CRYPTO_PCBC=m
@@ -523,14 +528,15 @@
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_ZLIB=m
CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
CONFIG_CRYPTO_LZ4HC=m
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
-CONFIG_CRYPTO_DRBG_MENU=m
+CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_DRBG_HASH=y
CONFIG_CRYPTO_DRBG_CTR=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
+CONFIG_CRYPTO_USER_API_AEAD=m
# CONFIG_CRYPTO_HW is not set
CONFIG_XZ_DEC_TEST=m
diff --git a/arch/m68k/kernel/bootinfo_proc.c b/arch/m68k/kernel/bootinfo_proc.c
index 7ee853e..2a33a96 100644
--- a/arch/m68k/kernel/bootinfo_proc.c
+++ b/arch/m68k/kernel/bootinfo_proc.c
@@ -62,12 +62,10 @@
if (!bootinfo_size)
return -EINVAL;
- bootinfo_copy = kmalloc(bootinfo_size, GFP_KERNEL);
+ bootinfo_copy = kmemdup(bootinfo_tmp, bootinfo_size, GFP_KERNEL);
if (!bootinfo_copy)
return -ENOMEM;
- memcpy(bootinfo_copy, bootinfo_tmp, bootinfo_size);
-
pde = proc_create_data("bootinfo", 0400, NULL, &bootinfo_fops, NULL);
if (!pde) {
kfree(bootinfo_copy);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index cee5f93..199a835 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -151,7 +151,6 @@
select BCM7120_L2_IRQ
select BRCMSTB_L2_IRQ
select IRQ_MIPS_CPU
- select RAW_IRQ_ACCESSORS
select DMA_NONCOHERENT
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 01a644f..1ba2120 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -190,6 +190,7 @@
{
return ATH79_MISC_IRQ(5);
}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
unsigned int get_c0_compare_int(void)
{
diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index 56f5d08..b7fa9ae 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -42,7 +42,7 @@
cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), action);
if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
diff --git a/arch/mips/include/asm/mach-bcm63xx/dma-coherence.h b/arch/mips/include/asm/mach-bcm63xx/dma-coherence.h
deleted file mode 100644
index 11d3b57..0000000
--- a/arch/mips/include/asm/mach-bcm63xx/dma-coherence.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __ASM_MACH_BCM63XX_DMA_COHERENCE_H
-#define __ASM_MACH_BCM63XX_DMA_COHERENCE_H
-
-#include <asm/bmips.h>
-
-#define plat_post_dma_flush bmips_post_dma_flush
-
-#include <asm/mach-generic/dma-coherence.h>
-
-#endif /* __ASM_MACH_BCM63XX_DMA_COHERENCE_H */
diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h
index 9d81067..ae85694 100644
--- a/arch/mips/include/asm/pgtable.h
+++ b/arch/mips/include/asm/pgtable.h
@@ -182,8 +182,39 @@
* Make sure the buddy is global too (if it's !none,
* it better already be global)
*/
+#ifdef CONFIG_SMP
+ /*
+ * For SMP, multiple CPUs can race, so we need to do
+ * this atomically.
+ */
+#ifdef CONFIG_64BIT
+#define LL_INSN "lld"
+#define SC_INSN "scd"
+#else /* CONFIG_32BIT */
+#define LL_INSN "ll"
+#define SC_INSN "sc"
+#endif
+ unsigned long page_global = _PAGE_GLOBAL;
+ unsigned long tmp;
+
+ __asm__ __volatile__ (
+ " .set push\n"
+ " .set noreorder\n"
+ "1: " LL_INSN " %[tmp], %[buddy]\n"
+ " bnez %[tmp], 2f\n"
+ " or %[tmp], %[tmp], %[global]\n"
+ " " SC_INSN " %[tmp], %[buddy]\n"
+ " beqz %[tmp], 1b\n"
+ " nop\n"
+ "2:\n"
+ " .set pop"
+ : [buddy] "+m" (buddy->pte),
+ [tmp] "=&r" (tmp)
+ : [global] "r" (page_global));
+#else /* !CONFIG_SMP */
if (pte_none(*buddy))
pte_val(*buddy) = pte_val(*buddy) | _PAGE_GLOBAL;
+#endif /* CONFIG_SMP */
}
#endif
}
diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h
index 16f1ea9..03722d4 100644
--- a/arch/mips/include/asm/smp.h
+++ b/arch/mips/include/asm/smp.h
@@ -83,8 +83,6 @@
extern void play_dead(void);
#endif
-extern asmlinkage void smp_call_function_interrupt(void);
-
static inline void arch_send_call_function_single_ipi(int cpu)
{
extern struct plat_smp_ops *mp_ops; /* private */
diff --git a/arch/mips/include/asm/stackframe.h b/arch/mips/include/asm/stackframe.h
index 28d6d93..a71da57 100644
--- a/arch/mips/include/asm/stackframe.h
+++ b/arch/mips/include/asm/stackframe.h
@@ -152,6 +152,31 @@
.set noreorder
bltz k0, 8f
move k1, sp
+#ifdef CONFIG_EVA
+ /*
+ * Flush interAptiv's Return Prediction Stack (RPS) by writing
+ * EntryHi. Toggling Config7.RPS is slower and less portable.
+ *
+ * The RPS isn't automatically flushed when exceptions are
+ * taken, which can result in kernel mode speculative accesses
+ * to user addresses if the RPS mispredicts. That's harmless
+ * when user and kernel share the same address space, but with
+ * EVA the same user segments may be unmapped to kernel mode,
+ * even containing sensitive MMIO regions or invalid memory.
+ *
+ * This can happen when the kernel sets the return address to
+ * ret_from_* and jr's to the exception handler, which looks
+ * more like a tail call than a function call. If nested calls
+ * don't evict the last user address in the RPS, it will
+ * mispredict the return and fetch from a user controlled
+ * address into the icache.
+ *
+ * More recent EVA-capable cores with MAAR to restrict
+ * speculative accesses aren't affected.
+ */
+ MFC0 k0, CP0_ENTRYHI
+ MTC0 k0, CP0_ENTRYHI
+#endif
.set reorder
/* Called from user mode, new stack. */
get_saved_sp
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index af42e70..baa7b6f 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -407,7 +407,7 @@
.set noat
SAVE_ALL
FEXPORT(handle_\exception\ext)
- __BUILD_clear_\clear
+ __build_clear_\clear
.set at
__BUILD_\verbose \exception
move a0, sp
diff --git a/arch/mips/kernel/mips-mt-fpaff.c b/arch/mips/kernel/mips-mt-fpaff.c
index 3e4491a..789d7bf 100644
--- a/arch/mips/kernel/mips-mt-fpaff.c
+++ b/arch/mips/kernel/mips-mt-fpaff.c
@@ -154,7 +154,7 @@
unsigned long __user *user_mask_ptr)
{
unsigned int real_len;
- cpumask_t mask;
+ cpumask_t allowed, mask;
int retval;
struct task_struct *p;
@@ -173,7 +173,8 @@
if (retval)
goto out_unlock;
- cpumask_and(&mask, &p->thread.user_cpus_allowed, cpu_possible_mask);
+ cpumask_or(&allowed, &p->thread.user_cpus_allowed, &p->cpus_allowed);
+ cpumask_and(&mask, &allowed, cpu_active_mask);
out_unlock:
read_unlock(&tasklist_lock);
diff --git a/arch/mips/kernel/prom.c b/arch/mips/kernel/prom.c
index b130033..5fcec30 100644
--- a/arch/mips/kernel/prom.c
+++ b/arch/mips/kernel/prom.c
@@ -38,7 +38,7 @@
return mips_machine_name;
}
-#ifdef CONFIG_OF
+#ifdef CONFIG_USE_OF
void __init early_init_dt_add_memory_arch(u64 base, u64 size)
{
return add_memory_region(base, size, BOOT_MEM_RAM);
diff --git a/arch/mips/kernel/relocate_kernel.S b/arch/mips/kernel/relocate_kernel.S
index 74bab9d..c6bbf21 100644
--- a/arch/mips/kernel/relocate_kernel.S
+++ b/arch/mips/kernel/relocate_kernel.S
@@ -24,7 +24,7 @@
process_entry:
PTR_L s2, (s0)
- PTR_ADD s0, s0, SZREG
+ PTR_ADDIU s0, s0, SZREG
/*
* In case of a kdump/crash kernel, the indirection page is not
@@ -61,9 +61,9 @@
/* copy page word by word */
REG_L s5, (s2)
REG_S s5, (s4)
- PTR_ADD s4, s4, SZREG
- PTR_ADD s2, s2, SZREG
- LONG_SUB s6, s6, 1
+ PTR_ADDIU s4, s4, SZREG
+ PTR_ADDIU s2, s2, SZREG
+ LONG_ADDIU s6, s6, -1
beq s6, zero, process_entry
b copy_word
b process_entry
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index ad4d4463..a6f6b76 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -80,7 +80,7 @@
SAVE_STATIC
move s0, t2
move a0, sp
- daddiu a1, v0, __NR_64_Linux
+ move a1, v0
jal syscall_trace_enter
bltz v0, 2f # seccomp failed? Skip syscall
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 446cc65..4b20106 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -72,7 +72,7 @@
SAVE_STATIC
move s0, t2
move a0, sp
- daddiu a1, v0, __NR_N32_Linux
+ move a1, v0
jal syscall_trace_enter
bltz v0, 2f # seccomp failed? Skip syscall
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 19a7705..5d7f263 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -409,8 +409,6 @@
int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
- memset(to, 0, sizeof *to);
-
if (copy_from_user(to, from, 3*sizeof(int)) ||
copy_from_user(to->_sifields._pad,
from->_sifields._pad, SI_PAD_SIZE32))
diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c
index 336708a..78cf8c2 100644
--- a/arch/mips/kernel/smp-bmips.c
+++ b/arch/mips/kernel/smp-bmips.c
@@ -284,7 +284,7 @@
if (action == 0)
scheduler_ipi();
else
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
@@ -336,7 +336,7 @@
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index d0744cc..a31896c 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -192,16 +192,6 @@
cpu_startup_entry(CPUHP_ONLINE);
}
-/*
- * Call into both interrupt handlers, as we share the IPI for them
- */
-void __irq_entry smp_call_function_interrupt(void)
-{
- irq_enter();
- generic_smp_call_function_interrupt();
- irq_exit();
-}
-
static void stop_this_cpu(void *dummy)
{
/*
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index e207a43..8ea28e6 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -192,6 +192,7 @@
void show_stack(struct task_struct *task, unsigned long *sp)
{
struct pt_regs regs;
+ mm_segment_t old_fs = get_fs();
if (sp) {
regs.regs[29] = (unsigned long)sp;
regs.regs[31] = 0;
@@ -210,7 +211,13 @@
prepare_frametrace(®s);
}
}
+ /*
+ * show_stack() deals exclusively with kernel mode, so be sure to access
+ * the stack in the kernel (not user) address space.
+ */
+ set_fs(KERNEL_DS);
show_stacktrace(task, ®s);
+ set_fs(old_fs);
}
static void show_code(unsigned int __user *pc)
@@ -1519,6 +1526,7 @@
const int field = 2 * sizeof(unsigned long);
int multi_match = regs->cp0_status & ST0_TS;
enum ctx_state prev_state;
+ mm_segment_t old_fs = get_fs();
prev_state = exception_enter();
show_regs(regs);
@@ -1540,8 +1548,13 @@
dump_tlb_all();
}
+ if (!user_mode(regs))
+ set_fs(KERNEL_DS);
+
show_code((unsigned int __user *) regs->cp0_epc);
+ set_fs(old_fs);
+
/*
* Some chips may have other causes of machine check (e.g. SB1
* graduation timer)
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c
index af84bef..eb3efd1 100644
--- a/arch/mips/kernel/unaligned.c
+++ b/arch/mips/kernel/unaligned.c
@@ -438,7 +438,7 @@
: "memory"); \
} while(0)
-#define StoreDW(addr, value, res) \
+#define _StoreDW(addr, value, res) \
do { \
__asm__ __volatile__ ( \
".set\tpush\n\t" \
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 6ab1057..2c218c3 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -293,7 +293,7 @@
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
{
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
@@ -466,6 +466,7 @@
{
return ltq_perfcount_irq;
}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
unsigned int get_c0_compare_int(void)
{
diff --git a/arch/mips/loongson64/loongson-3/smp.c b/arch/mips/loongson64/loongson-3/smp.c
index 509877c..1a4738a 100644
--- a/arch/mips/loongson64/loongson-3/smp.c
+++ b/arch/mips/loongson64/loongson-3/smp.c
@@ -266,8 +266,11 @@
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
- if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ if (action & SMP_CALL_FUNCTION) {
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
+ }
if (action & SMP_ASK_C0COUNT) {
BUG_ON(cpu != 0);
diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
index 77d96db..aab218c 100644
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -160,18 +160,18 @@
protection_map[1] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
protection_map[2] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
protection_map[3] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
- protection_map[4] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_READ);
+ protection_map[4] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
protection_map[5] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
- protection_map[6] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_READ);
+ protection_map[6] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
protection_map[7] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
protection_map[8] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_NO_READ);
protection_map[9] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC);
protection_map[10] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE | _PAGE_NO_READ);
protection_map[11] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_EXEC | _PAGE_WRITE);
- protection_map[12] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_NO_READ);
+ protection_map[12] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
protection_map[13] = __pgprot(_page_cachable_default | _PAGE_PRESENT);
- protection_map[14] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE | _PAGE_NO_READ);
+ protection_map[14] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE);
protection_map[15] = __pgprot(_page_cachable_default | _PAGE_PRESENT | _PAGE_WRITE);
} else {
diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c
index 36c0f26..852a41c 100644
--- a/arch/mips/mm/fault.c
+++ b/arch/mips/mm/fault.c
@@ -133,7 +133,8 @@
#endif
goto bad_area;
}
- if (!(vma->vm_flags & VM_READ)) {
+ if (!(vma->vm_flags & VM_READ) &&
+ exception_epc(regs) != address) {
#if 0
pr_notice("Cpu%d[%s:%d:%0*lx:%ld:%0*lx] RI violation\n",
raw_smp_processor_id(),
diff --git a/arch/mips/mti-malta/malta-int.c b/arch/mips/mti-malta/malta-int.c
index d1392f8..fa8f591 100644
--- a/arch/mips/mti-malta/malta-int.c
+++ b/arch/mips/mti-malta/malta-int.c
@@ -222,7 +222,7 @@
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
{
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c
index 5625b19..b7bf721 100644
--- a/arch/mips/mti-malta/malta-time.c
+++ b/arch/mips/mti-malta/malta-time.c
@@ -154,6 +154,7 @@
return mips_cpu_perf_irq;
}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
unsigned int get_c0_compare_int(void)
{
@@ -171,14 +172,17 @@
static void __init init_rtc(void)
{
- /* stop the clock whilst setting it up */
- CMOS_WRITE(RTC_SET | RTC_24H, RTC_CONTROL);
+ unsigned char freq, ctrl;
- /* 32KHz time base */
- CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT);
+ /* Set 32KHz time base if not already set */
+ freq = CMOS_READ(RTC_FREQ_SELECT);
+ if ((freq & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ)
+ CMOS_WRITE(RTC_REF_CLCK_32KHZ, RTC_FREQ_SELECT);
- /* start the clock */
- CMOS_WRITE(RTC_24H, RTC_CONTROL);
+ /* Ensure SET bit is clear so RTC can run */
+ ctrl = CMOS_READ(RTC_CONTROL);
+ if (ctrl & RTC_SET)
+ CMOS_WRITE(ctrl & ~RTC_SET, RTC_CONTROL);
}
void __init plat_time_init(void)
diff --git a/arch/mips/mti-sead3/sead3-time.c b/arch/mips/mti-sead3/sead3-time.c
index e1d6989..a120b7a 100644
--- a/arch/mips/mti-sead3/sead3-time.c
+++ b/arch/mips/mti-sead3/sead3-time.c
@@ -77,6 +77,7 @@
return MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
return -1;
}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
unsigned int get_c0_compare_int(void)
{
diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c
index dc3e327..f5fff22 100644
--- a/arch/mips/netlogic/common/smp.c
+++ b/arch/mips/netlogic/common/smp.c
@@ -86,7 +86,7 @@
{
clear_c0_eimr(irq);
ack_c0_eirr(irq);
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
set_c0_eimr(irq);
}
diff --git a/arch/mips/paravirt/paravirt-smp.c b/arch/mips/paravirt/paravirt-smp.c
index 42181c7..f8d3e08 100644
--- a/arch/mips/paravirt/paravirt-smp.c
+++ b/arch/mips/paravirt/paravirt-smp.c
@@ -114,7 +114,7 @@
static irqreturn_t paravirt_function_interrupt(int irq, void *dev_id)
{
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
diff --git a/arch/mips/pistachio/time.c b/arch/mips/pistachio/time.c
index 7c73fcb..8a37734 100644
--- a/arch/mips/pistachio/time.c
+++ b/arch/mips/pistachio/time.c
@@ -26,6 +26,7 @@
{
return gic_get_c0_perfcount_int();
}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
int get_c0_fdc_int(void)
{
diff --git a/arch/mips/pmcs-msp71xx/msp_smp.c b/arch/mips/pmcs-msp71xx/msp_smp.c
index 1017058..ffa0f71 100644
--- a/arch/mips/pmcs-msp71xx/msp_smp.c
+++ b/arch/mips/pmcs-msp71xx/msp_smp.c
@@ -44,7 +44,7 @@
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
{
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
index 53707aa..8c624a8 100644
--- a/arch/mips/ralink/irq.c
+++ b/arch/mips/ralink/irq.c
@@ -89,6 +89,7 @@
{
return rt_perfcount_irq;
}
+EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
unsigned int get_c0_compare_int(void)
{
diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c
index 3fbaef9..16ec4e1 100644
--- a/arch/mips/sgi-ip27/ip27-irq.c
+++ b/arch/mips/sgi-ip27/ip27-irq.c
@@ -107,10 +107,14 @@
scheduler_ipi();
} else if (pend0 & (1UL << CPU_CALL_A_IRQ)) {
LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ);
- smp_call_function_interrupt();
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
} else if (pend0 & (1UL << CPU_CALL_B_IRQ)) {
LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ);
- smp_call_function_interrupt();
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
} else
#endif
{
diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c
index af7d44e..4c71aea 100644
--- a/arch/mips/sibyte/bcm1480/smp.c
+++ b/arch/mips/sibyte/bcm1480/smp.c
@@ -29,8 +29,6 @@
#include <asm/sibyte/bcm1480_regs.h>
#include <asm/sibyte/bcm1480_int.h>
-extern void smp_call_function_interrupt(void);
-
/*
* These are routines for dealing with the bcm1480 smp capabilities
* independent of board/firmware
@@ -184,6 +182,9 @@
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
- if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ if (action & SMP_CALL_FUNCTION) {
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
+ }
}
diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c
index c0c4b3f..1cf66f5 100644
--- a/arch/mips/sibyte/sb1250/smp.c
+++ b/arch/mips/sibyte/sb1250/smp.c
@@ -172,6 +172,9 @@
if (action & SMP_RESCHEDULE_YOURSELF)
scheduler_ipi();
- if (action & SMP_CALL_FUNCTION)
- smp_call_function_interrupt();
+ if (action & SMP_CALL_FUNCTION) {
+ irq_enter();
+ generic_smp_call_function_interrupt();
+ irq_exit();
+ }
}
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c
index 42e02a2..efc3fa5 100644
--- a/arch/powerpc/kernel/pci_of_scan.c
+++ b/arch/powerpc/kernel/pci_of_scan.c
@@ -191,6 +191,9 @@
pci_device_add(dev, bus);
+ /* Setup MSI caps & disable MSI/MSI-X interrupts */
+ pci_msi_setup_pci_dev(dev);
+
return dev;
}
EXPORT_SYMBOL(of_create_pci_dev);
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index d3a831a..da50e0c 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -966,8 +966,6 @@
int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
{
- memset(to, 0, sizeof *to);
-
if (copy_from_user(to, from, 3*sizeof(int)) ||
copy_from_user(to->_sifields._pad,
from->_sifields._pad, SI_PAD_SIZE32))
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 5cf5e6e..7cf0df8 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -1478,7 +1478,7 @@
}
/* Unmask the event */
- if (eeh_enabled())
+ if (ret == EEH_NEXT_ERR_NONE && eeh_enabled())
enable_irq(eeh_event_irq);
return ret;
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 5738d31..85cbc96 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -2220,7 +2220,7 @@
static __be64 *pnv_pci_ioda2_table_do_alloc_pages(int nid, unsigned shift,
unsigned levels, unsigned long limit,
- unsigned long *current_offset)
+ unsigned long *current_offset, unsigned long *total_allocated)
{
struct page *tce_mem = NULL;
__be64 *addr, *tmp;
@@ -2236,6 +2236,7 @@
}
addr = page_address(tce_mem);
memset(addr, 0, allocated);
+ *total_allocated += allocated;
--levels;
if (!levels) {
@@ -2245,7 +2246,7 @@
for (i = 0; i < entries; ++i) {
tmp = pnv_pci_ioda2_table_do_alloc_pages(nid, shift,
- levels, limit, current_offset);
+ levels, limit, current_offset, total_allocated);
if (!tmp)
break;
@@ -2267,7 +2268,7 @@
struct iommu_table *tbl)
{
void *addr;
- unsigned long offset = 0, level_shift;
+ unsigned long offset = 0, level_shift, total_allocated = 0;
const unsigned window_shift = ilog2(window_size);
unsigned entries_shift = window_shift - page_shift;
unsigned table_shift = max_t(unsigned, entries_shift + 3, PAGE_SHIFT);
@@ -2286,7 +2287,7 @@
/* Allocate TCE table */
addr = pnv_pci_ioda2_table_do_alloc_pages(nid, level_shift,
- levels, tce_table_size, &offset);
+ levels, tce_table_size, &offset, &total_allocated);
/* addr==NULL means that the first level allocation failed */
if (!addr)
@@ -2308,7 +2309,7 @@
page_shift);
tbl->it_level_size = 1ULL << (level_shift - 3);
tbl->it_indirect_levels = levels - 1;
- tbl->it_allocated_size = offset;
+ tbl->it_allocated_size = total_allocated;
pr_devel("Created TCE table: ws=%08llx ts=%lx @%08llx\n",
window_size, tce_table_size, bus_offset);
diff --git a/arch/s390/include/asm/etr.h b/arch/s390/include/asm/etr.h
index 629b79a..f7e5c36 100644
--- a/arch/s390/include/asm/etr.h
+++ b/arch/s390/include/asm/etr.h
@@ -214,6 +214,9 @@
void etr_switch_to_local(void);
void etr_sync_check(void);
+/* notifier for syncs */
+extern struct atomic_notifier_head s390_epoch_delta_notifier;
+
/* STP interruption parameter */
struct stp_irq_parm {
unsigned int _pad0 : 14;
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index c4f4c52..3d012e0 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -259,6 +259,9 @@
u32 diagnose_10;
u32 diagnose_44;
u32 diagnose_9c;
+ u32 diagnose_258;
+ u32 diagnose_308;
+ u32 diagnose_500;
};
#define PGM_OPERATION 0x01
@@ -630,7 +633,6 @@
static inline void kvm_arch_hardware_disable(void) {}
static inline void kvm_arch_check_processor_compat(void *rtn) {}
-static inline void kvm_arch_exit(void) {}
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) {}
static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c
index bff5e3b..8ba3243 100644
--- a/arch/s390/kernel/cache.c
+++ b/arch/s390/kernel/cache.c
@@ -138,6 +138,8 @@
union cache_topology ct;
enum cache_type ctype;
+ if (!test_facility(34))
+ return -EOPNOTSUPP;
if (!this_cpu_ci)
return -EINVAL;
ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 9e733d9..627887b 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -58,6 +58,9 @@
static DEFINE_PER_CPU(struct clock_event_device, comparators);
+ATOMIC_NOTIFIER_HEAD(s390_epoch_delta_notifier);
+EXPORT_SYMBOL(s390_epoch_delta_notifier);
+
/*
* Scheduler clock - returns current time in nanosec units.
*/
@@ -752,7 +755,7 @@
static int etr_sync_clock(void *data)
{
static int first;
- unsigned long long clock, old_clock, delay, delta;
+ unsigned long long clock, old_clock, clock_delta, delay, delta;
struct clock_sync_data *etr_sync;
struct etr_aib *sync_port, *aib;
int port;
@@ -789,6 +792,9 @@
delay = (unsigned long long)
(aib->edf2.etv - sync_port->edf2.etv) << 32;
delta = adjust_time(old_clock, clock, delay);
+ clock_delta = clock - old_clock;
+ atomic_notifier_call_chain(&s390_epoch_delta_notifier, 0,
+ &clock_delta);
etr_sync->fixup_cc = delta;
fixup_clock_comparator(delta);
/* Verify that the clock is properly set. */
@@ -1526,7 +1532,7 @@
static int stp_sync_clock(void *data)
{
static int first;
- unsigned long long old_clock, delta;
+ unsigned long long old_clock, delta, new_clock, clock_delta;
struct clock_sync_data *stp_sync;
int rc;
@@ -1551,7 +1557,11 @@
old_clock = get_tod_clock();
rc = chsc_sstpc(stp_page, STP_OP_SYNC, 0);
if (rc == 0) {
- delta = adjust_time(old_clock, get_tod_clock(), 0);
+ new_clock = get_tod_clock();
+ delta = adjust_time(old_clock, new_clock, 0);
+ clock_delta = new_clock - old_clock;
+ atomic_notifier_call_chain(&s390_epoch_delta_notifier,
+ 0, &clock_delta);
fixup_clock_comparator(delta);
rc = chsc_sstpi(stp_page, &stp_info,
sizeof(struct stp_sstpi));
diff --git a/arch/s390/kvm/diag.c b/arch/s390/kvm/diag.c
index fc7ec95..5fbfb88 100644
--- a/arch/s390/kvm/diag.c
+++ b/arch/s390/kvm/diag.c
@@ -27,13 +27,13 @@
start = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4];
end = vcpu->run->s.regs.gprs[vcpu->arch.sie_block->ipa & 0xf] + 4096;
+ vcpu->stat.diagnose_10++;
if (start & ~PAGE_MASK || end & ~PAGE_MASK || start >= end
|| start < 2 * PAGE_SIZE)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
VCPU_EVENT(vcpu, 5, "diag release pages %lX %lX", start, end);
- vcpu->stat.diagnose_10++;
/*
* We checked for start >= end above, so lets check for the
@@ -75,6 +75,9 @@
u16 rx = (vcpu->arch.sie_block->ipa & 0xf0) >> 4;
u16 ry = (vcpu->arch.sie_block->ipa & 0x0f);
+ VCPU_EVENT(vcpu, 3, "diag page reference parameter block at 0x%llx",
+ vcpu->run->s.regs.gprs[rx]);
+ vcpu->stat.diagnose_258++;
if (vcpu->run->s.regs.gprs[rx] & 7)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
rc = read_guest(vcpu, vcpu->run->s.regs.gprs[rx], rx, &parm, sizeof(parm));
@@ -85,6 +88,9 @@
switch (parm.subcode) {
case 0: /* TOKEN */
+ VCPU_EVENT(vcpu, 3, "pageref token addr 0x%llx "
+ "select mask 0x%llx compare mask 0x%llx",
+ parm.token_addr, parm.select_mask, parm.compare_mask);
if (vcpu->arch.pfault_token != KVM_S390_PFAULT_TOKEN_INVALID) {
/*
* If the pagefault handshake is already activated,
@@ -114,6 +120,7 @@
* the cancel, therefore to reduce code complexity, we assume
* all outstanding tokens are already pending.
*/
+ VCPU_EVENT(vcpu, 3, "pageref cancel addr 0x%llx", parm.token_addr);
if (parm.token_addr || parm.select_mask ||
parm.compare_mask || parm.zarch)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -174,7 +181,8 @@
unsigned int reg = vcpu->arch.sie_block->ipa & 0xf;
unsigned long subcode = vcpu->run->s.regs.gprs[reg] & 0xffff;
- VCPU_EVENT(vcpu, 5, "diag ipl functions, subcode %lx", subcode);
+ VCPU_EVENT(vcpu, 3, "diag ipl functions, subcode %lx", subcode);
+ vcpu->stat.diagnose_308++;
switch (subcode) {
case 3:
vcpu->run->s390_reset_flags = KVM_S390_RESET_CLEAR;
@@ -202,6 +210,7 @@
{
int ret;
+ vcpu->stat.diagnose_500++;
/* No virtio-ccw notification? Get out quickly. */
if (!vcpu->kvm->arch.css_support ||
(vcpu->run->s.regs.gprs[1] != KVM_S390_VIRTIO_CCW_NOTIFY))
diff --git a/arch/s390/kvm/guestdbg.c b/arch/s390/kvm/guestdbg.c
index e97b345..47518a3 100644
--- a/arch/s390/kvm/guestdbg.c
+++ b/arch/s390/kvm/guestdbg.c
@@ -473,10 +473,45 @@
vcpu->arch.sie_block->iprcc &= ~PGM_PER;
}
+#define pssec(vcpu) (vcpu->arch.sie_block->gcr[1] & _ASCE_SPACE_SWITCH)
+#define hssec(vcpu) (vcpu->arch.sie_block->gcr[13] & _ASCE_SPACE_SWITCH)
+#define old_ssec(vcpu) ((vcpu->arch.sie_block->tecmc >> 31) & 0x1)
+#define old_as_is_home(vcpu) !(vcpu->arch.sie_block->tecmc & 0xffff)
+
void kvm_s390_handle_per_event(struct kvm_vcpu *vcpu)
{
+ int new_as;
+
if (debug_exit_required(vcpu))
vcpu->guest_debug |= KVM_GUESTDBG_EXIT_PENDING;
filter_guest_per_event(vcpu);
+
+ /*
+ * Only RP, SAC, SACF, PT, PTI, PR, PC instructions can trigger
+ * a space-switch event. PER events enforce space-switch events
+ * for these instructions. So if no PER event for the guest is left,
+ * we might have to filter the space-switch element out, too.
+ */
+ if (vcpu->arch.sie_block->iprcc == PGM_SPACE_SWITCH) {
+ vcpu->arch.sie_block->iprcc = 0;
+ new_as = psw_bits(vcpu->arch.sie_block->gpsw).as;
+
+ /*
+ * If the AS changed from / to home, we had RP, SAC or SACF
+ * instruction. Check primary and home space-switch-event
+ * controls. (theoretically home -> home produced no event)
+ */
+ if (((new_as == PSW_AS_HOME) ^ old_as_is_home(vcpu)) &&
+ (pssec(vcpu) || hssec(vcpu)))
+ vcpu->arch.sie_block->iprcc = PGM_SPACE_SWITCH;
+
+ /*
+ * PT, PTI, PR, PC instruction operate on primary AS only. Check
+ * if the primary-space-switch-event control was or got set.
+ */
+ if (new_as == PSW_AS_PRIMARY && !old_as_is_home(vcpu) &&
+ (pssec(vcpu) || old_ssec(vcpu)))
+ vcpu->arch.sie_block->iprcc = PGM_SPACE_SWITCH;
+ }
}
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index c98d897..b277d50 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -30,7 +30,6 @@
#define IOINT_SCHID_MASK 0x0000ffff
#define IOINT_SSID_MASK 0x00030000
#define IOINT_CSSID_MASK 0x03fc0000
-#define IOINT_AI_MASK 0x04000000
#define PFAULT_INIT 0x0600
#define PFAULT_DONE 0x0680
#define VIRTIO_PARAM 0x0d00
@@ -72,9 +71,13 @@
static int ckc_irq_pending(struct kvm_vcpu *vcpu)
{
+ preempt_disable();
if (!(vcpu->arch.sie_block->ckc <
- get_tod_clock_fast() + vcpu->arch.sie_block->epoch))
+ get_tod_clock_fast() + vcpu->arch.sie_block->epoch)) {
+ preempt_enable();
return 0;
+ }
+ preempt_enable();
return ckc_interrupts_enabled(vcpu);
}
@@ -311,8 +314,8 @@
li->irq.ext.ext_params2 = 0;
spin_unlock(&li->lock);
- VCPU_EVENT(vcpu, 4, "interrupt: pfault init parm:%x,parm64:%llx",
- 0, ext.ext_params2);
+ VCPU_EVENT(vcpu, 4, "deliver: pfault init token 0x%llx",
+ ext.ext_params2);
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
KVM_S390_INT_PFAULT_INIT,
0, ext.ext_params2);
@@ -368,7 +371,7 @@
spin_unlock(&fi->lock);
if (deliver) {
- VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx",
+ VCPU_EVENT(vcpu, 3, "deliver: machine check mcic 0x%llx",
mchk.mcic);
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
KVM_S390_MCHK,
@@ -403,7 +406,7 @@
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
int rc;
- VCPU_EVENT(vcpu, 4, "%s", "interrupt: cpu restart");
+ VCPU_EVENT(vcpu, 3, "%s", "deliver: cpu restart");
vcpu->stat.deliver_restart_signal++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0);
@@ -427,7 +430,6 @@
clear_bit(IRQ_PEND_SET_PREFIX, &li->pending_irqs);
spin_unlock(&li->lock);
- VCPU_EVENT(vcpu, 4, "interrupt: set prefix to %x", prefix.address);
vcpu->stat.deliver_prefix_signal++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
KVM_S390_SIGP_SET_PREFIX,
@@ -450,7 +452,7 @@
clear_bit(IRQ_PEND_EXT_EMERGENCY, &li->pending_irqs);
spin_unlock(&li->lock);
- VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp emerg");
+ VCPU_EVENT(vcpu, 4, "%s", "deliver: sigp emerg");
vcpu->stat.deliver_emergency_signal++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_EMERGENCY,
cpu_addr, 0);
@@ -477,7 +479,7 @@
clear_bit(IRQ_PEND_EXT_EXTERNAL, &li->pending_irqs);
spin_unlock(&li->lock);
- VCPU_EVENT(vcpu, 4, "%s", "interrupt: sigp ext call");
+ VCPU_EVENT(vcpu, 4, "%s", "deliver: sigp ext call");
vcpu->stat.deliver_external_call++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
KVM_S390_INT_EXTERNAL_CALL,
@@ -506,7 +508,7 @@
memset(&li->irq.pgm, 0, sizeof(pgm_info));
spin_unlock(&li->lock);
- VCPU_EVENT(vcpu, 4, "interrupt: pgm check code:%x, ilc:%x",
+ VCPU_EVENT(vcpu, 3, "deliver: program irq code 0x%x, ilc:%d",
pgm_info.code, ilc);
vcpu->stat.deliver_program_int++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
@@ -622,7 +624,7 @@
clear_bit(IRQ_PEND_EXT_SERVICE, &fi->pending_irqs);
spin_unlock(&fi->lock);
- VCPU_EVENT(vcpu, 4, "interrupt: sclp parm:%x",
+ VCPU_EVENT(vcpu, 4, "deliver: sclp parameter 0x%x",
ext.ext_params);
vcpu->stat.deliver_service_signal++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, KVM_S390_INT_SERVICE,
@@ -651,9 +653,6 @@
struct kvm_s390_interrupt_info,
list);
if (inti) {
- trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
- KVM_S390_INT_PFAULT_DONE, 0,
- inti->ext.ext_params2);
list_del(&inti->list);
fi->counters[FIRQ_CNTR_PFAULT] -= 1;
}
@@ -662,6 +661,12 @@
spin_unlock(&fi->lock);
if (inti) {
+ trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
+ KVM_S390_INT_PFAULT_DONE, 0,
+ inti->ext.ext_params2);
+ VCPU_EVENT(vcpu, 4, "deliver: pfault done token 0x%llx",
+ inti->ext.ext_params2);
+
rc = put_guest_lc(vcpu, EXT_IRQ_CP_SERVICE,
(u16 *)__LC_EXT_INT_CODE);
rc |= put_guest_lc(vcpu, PFAULT_DONE,
@@ -691,7 +696,7 @@
list);
if (inti) {
VCPU_EVENT(vcpu, 4,
- "interrupt: virtio parm:%x,parm64:%llx",
+ "deliver: virtio parm: 0x%x,parm64: 0x%llx",
inti->ext.ext_params, inti->ext.ext_params2);
vcpu->stat.deliver_virtio_interrupt++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
@@ -741,7 +746,7 @@
struct kvm_s390_interrupt_info,
list);
if (inti) {
- VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type);
+ VCPU_EVENT(vcpu, 4, "deliver: I/O 0x%llx", inti->type);
vcpu->stat.deliver_io_int++;
trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id,
inti->type,
@@ -855,7 +860,9 @@
goto no_timer;
}
+ preempt_disable();
now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
+ preempt_enable();
sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
/* underflow */
@@ -864,7 +871,7 @@
__set_cpu_idle(vcpu);
hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
- VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
+ VCPU_EVENT(vcpu, 4, "enabled wait via clock comparator: %llu ns", sltime);
no_timer:
srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
kvm_vcpu_block(vcpu);
@@ -894,7 +901,9 @@
u64 now, sltime;
vcpu = container_of(timer, struct kvm_vcpu, arch.ckc_timer);
+ preempt_disable();
now = get_tod_clock_fast() + vcpu->arch.sie_block->epoch;
+ preempt_enable();
sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
/*
@@ -968,6 +977,10 @@
{
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
+ VCPU_EVENT(vcpu, 3, "inject: program irq code 0x%x", irq->u.pgm.code);
+ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
+ irq->u.pgm.code, 0);
+
li->irq.pgm = irq->u.pgm;
set_bit(IRQ_PEND_PROG, &li->pending_irqs);
return 0;
@@ -978,9 +991,6 @@
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
struct kvm_s390_irq irq;
- VCPU_EVENT(vcpu, 3, "inject: program check %d (from kernel)", code);
- trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT, code,
- 0, 1);
spin_lock(&li->lock);
irq.u.pgm.code = code;
__inject_prog(vcpu, &irq);
@@ -996,10 +1006,6 @@
struct kvm_s390_irq irq;
int rc;
- VCPU_EVENT(vcpu, 3, "inject: prog irq %d (from kernel)",
- pgm_info->code);
- trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_PROGRAM_INT,
- pgm_info->code, 0, 1);
spin_lock(&li->lock);
irq.u.pgm = *pgm_info;
rc = __inject_prog(vcpu, &irq);
@@ -1012,11 +1018,11 @@
{
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
- VCPU_EVENT(vcpu, 3, "inject: external irq params:%x, params2:%llx",
- irq->u.ext.ext_params, irq->u.ext.ext_params2);
+ VCPU_EVENT(vcpu, 4, "inject: pfault init parameter block at 0x%llx",
+ irq->u.ext.ext_params2);
trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_PFAULT_INIT,
irq->u.ext.ext_params,
- irq->u.ext.ext_params2, 2);
+ irq->u.ext.ext_params2);
li->irq.ext = irq->u.ext;
set_bit(IRQ_PEND_PFAULT_INIT, &li->pending_irqs);
@@ -1045,10 +1051,10 @@
struct kvm_s390_extcall_info *extcall = &li->irq.extcall;
uint16_t src_id = irq->u.extcall.code;
- VCPU_EVENT(vcpu, 3, "inject: external call source-cpu:%u",
+ VCPU_EVENT(vcpu, 4, "inject: external call source-cpu:%u",
src_id);
trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_EXTERNAL_CALL,
- src_id, 0, 2);
+ src_id, 0);
/* sending vcpu invalid */
if (src_id >= KVM_MAX_VCPUS ||
@@ -1070,10 +1076,10 @@
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
struct kvm_s390_prefix_info *prefix = &li->irq.prefix;
- VCPU_EVENT(vcpu, 3, "inject: set prefix to %x (from user)",
+ VCPU_EVENT(vcpu, 3, "inject: set prefix to %x",
irq->u.prefix.address);
trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_SET_PREFIX,
- irq->u.prefix.address, 0, 2);
+ irq->u.prefix.address, 0);
if (!is_vcpu_stopped(vcpu))
return -EBUSY;
@@ -1090,7 +1096,7 @@
struct kvm_s390_stop_info *stop = &li->irq.stop;
int rc = 0;
- trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_STOP, 0, 0, 2);
+ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_SIGP_STOP, 0, 0);
if (irq->u.stop.flags & ~KVM_S390_STOP_SUPP_FLAGS)
return -EINVAL;
@@ -1114,8 +1120,8 @@
{
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
- VCPU_EVENT(vcpu, 3, "inject: restart type %llx", irq->type);
- trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0, 2);
+ VCPU_EVENT(vcpu, 3, "%s", "inject: restart int");
+ trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_RESTART, 0, 0);
set_bit(IRQ_PEND_RESTART, &li->pending_irqs);
return 0;
@@ -1126,10 +1132,10 @@
{
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
- VCPU_EVENT(vcpu, 3, "inject: emergency %u\n",
+ VCPU_EVENT(vcpu, 4, "inject: emergency from cpu %u",
irq->u.emerg.code);
trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_EMERGENCY,
- irq->u.emerg.code, 0, 2);
+ irq->u.emerg.code, 0);
set_bit(irq->u.emerg.code, li->sigp_emerg_pending);
set_bit(IRQ_PEND_EXT_EMERGENCY, &li->pending_irqs);
@@ -1142,10 +1148,10 @@
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
struct kvm_s390_mchk_info *mchk = &li->irq.mchk;
- VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx",
+ VCPU_EVENT(vcpu, 3, "inject: machine check mcic 0x%llx",
irq->u.mchk.mcic);
trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_MCHK, 0,
- irq->u.mchk.mcic, 2);
+ irq->u.mchk.mcic);
/*
* Because repressible machine checks can be indicated along with
@@ -1172,9 +1178,9 @@
{
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
- VCPU_EVENT(vcpu, 3, "inject: type %x", KVM_S390_INT_CLOCK_COMP);
+ VCPU_EVENT(vcpu, 3, "%s", "inject: clock comparator external");
trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_CLOCK_COMP,
- 0, 0, 2);
+ 0, 0);
set_bit(IRQ_PEND_EXT_CLOCK_COMP, &li->pending_irqs);
atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
@@ -1185,9 +1191,9 @@
{
struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int;
- VCPU_EVENT(vcpu, 3, "inject: type %x", KVM_S390_INT_CPU_TIMER);
+ VCPU_EVENT(vcpu, 3, "%s", "inject: cpu timer external");
trace_kvm_s390_inject_vcpu(vcpu->vcpu_id, KVM_S390_INT_CPU_TIMER,
- 0, 0, 2);
+ 0, 0);
set_bit(IRQ_PEND_EXT_CPU_TIMER, &li->pending_irqs);
atomic_set_mask(CPUSTAT_EXT_INT, li->cpuflags);
@@ -1435,20 +1441,20 @@
inti->ext.ext_params2 = s390int->parm64;
break;
case KVM_S390_INT_SERVICE:
- VM_EVENT(kvm, 5, "inject: sclp parm:%x", s390int->parm);
+ VM_EVENT(kvm, 4, "inject: sclp parm:%x", s390int->parm);
inti->ext.ext_params = s390int->parm;
break;
case KVM_S390_INT_PFAULT_DONE:
inti->ext.ext_params2 = s390int->parm64;
break;
case KVM_S390_MCHK:
- VM_EVENT(kvm, 5, "inject: machine check parm64:%llx",
+ VM_EVENT(kvm, 3, "inject: machine check mcic 0x%llx",
s390int->parm64);
inti->mchk.cr14 = s390int->parm; /* upper bits are not used */
inti->mchk.mcic = s390int->parm64;
break;
case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX:
- if (inti->type & IOINT_AI_MASK)
+ if (inti->type & KVM_S390_INT_IO_AI_MASK)
VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)");
else
VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x",
@@ -1535,8 +1541,6 @@
switch (irq->type) {
case KVM_S390_PROGRAM_INT:
- VCPU_EVENT(vcpu, 3, "inject: program check %d (from user)",
- irq->u.pgm.code);
rc = __inject_prog(vcpu, irq);
break;
case KVM_S390_SIGP_SET_PREFIX:
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 1903f02..98df53c 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -28,6 +28,7 @@
#include <linux/vmalloc.h>
#include <asm/asm-offsets.h>
#include <asm/lowcore.h>
+#include <asm/etr.h>
#include <asm/pgtable.h>
#include <asm/nmi.h>
#include <asm/switch_to.h>
@@ -108,6 +109,9 @@
{ "diagnose_10", VCPU_STAT(diagnose_10) },
{ "diagnose_44", VCPU_STAT(diagnose_44) },
{ "diagnose_9c", VCPU_STAT(diagnose_9c) },
+ { "diagnose_258", VCPU_STAT(diagnose_258) },
+ { "diagnose_308", VCPU_STAT(diagnose_308) },
+ { "diagnose_500", VCPU_STAT(diagnose_500) },
{ NULL }
};
@@ -124,6 +128,7 @@
}
static struct gmap_notifier gmap_notifier;
+debug_info_t *kvm_s390_dbf;
/* Section: not file related */
int kvm_arch_hardware_enable(void)
@@ -134,24 +139,69 @@
static void kvm_gmap_notifier(struct gmap *gmap, unsigned long address);
+/*
+ * This callback is executed during stop_machine(). All CPUs are therefore
+ * temporarily stopped. In order not to change guest behavior, we have to
+ * disable preemption whenever we touch the epoch of kvm and the VCPUs,
+ * so a CPU won't be stopped while calculating with the epoch.
+ */
+static int kvm_clock_sync(struct notifier_block *notifier, unsigned long val,
+ void *v)
+{
+ struct kvm *kvm;
+ struct kvm_vcpu *vcpu;
+ int i;
+ unsigned long long *delta = v;
+
+ list_for_each_entry(kvm, &vm_list, vm_list) {
+ kvm->arch.epoch -= *delta;
+ kvm_for_each_vcpu(i, vcpu, kvm) {
+ vcpu->arch.sie_block->epoch -= *delta;
+ }
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block kvm_clock_notifier = {
+ .notifier_call = kvm_clock_sync,
+};
+
int kvm_arch_hardware_setup(void)
{
gmap_notifier.notifier_call = kvm_gmap_notifier;
gmap_register_ipte_notifier(&gmap_notifier);
+ atomic_notifier_chain_register(&s390_epoch_delta_notifier,
+ &kvm_clock_notifier);
return 0;
}
void kvm_arch_hardware_unsetup(void)
{
gmap_unregister_ipte_notifier(&gmap_notifier);
+ atomic_notifier_chain_unregister(&s390_epoch_delta_notifier,
+ &kvm_clock_notifier);
}
int kvm_arch_init(void *opaque)
{
+ kvm_s390_dbf = debug_register("kvm-trace", 32, 1, 7 * sizeof(long));
+ if (!kvm_s390_dbf)
+ return -ENOMEM;
+
+ if (debug_register_view(kvm_s390_dbf, &debug_sprintf_view)) {
+ debug_unregister(kvm_s390_dbf);
+ return -ENOMEM;
+ }
+
/* Register floating interrupt controller interface. */
return kvm_register_device_ops(&kvm_flic_ops, KVM_DEV_TYPE_FLIC);
}
+void kvm_arch_exit(void)
+{
+ debug_unregister(kvm_s390_dbf);
+}
+
/* Section: device related */
long kvm_arch_dev_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
@@ -281,10 +331,12 @@
switch (cap->cap) {
case KVM_CAP_S390_IRQCHIP:
+ VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_IRQCHIP");
kvm->arch.use_irqchip = 1;
r = 0;
break;
case KVM_CAP_S390_USER_SIGP:
+ VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_SIGP");
kvm->arch.user_sigp = 1;
r = 0;
break;
@@ -295,8 +347,11 @@
r = 0;
} else
r = -EINVAL;
+ VM_EVENT(kvm, 3, "ENABLE: CAP_S390_VECTOR_REGISTERS %s",
+ r ? "(not available)" : "(success)");
break;
case KVM_CAP_S390_USER_STSI:
+ VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_STSI");
kvm->arch.user_stsi = 1;
r = 0;
break;
@@ -314,6 +369,8 @@
switch (attr->attr) {
case KVM_S390_VM_MEM_LIMIT_SIZE:
ret = 0;
+ VM_EVENT(kvm, 3, "QUERY: max guest memory: %lu bytes",
+ kvm->arch.gmap->asce_end);
if (put_user(kvm->arch.gmap->asce_end, (u64 __user *)attr->addr))
ret = -EFAULT;
break;
@@ -330,7 +387,13 @@
unsigned int idx;
switch (attr->attr) {
case KVM_S390_VM_MEM_ENABLE_CMMA:
+ /* enable CMMA only for z10 and later (EDAT_1) */
+ ret = -EINVAL;
+ if (!MACHINE_IS_LPAR || !MACHINE_HAS_EDAT1)
+ break;
+
ret = -EBUSY;
+ VM_EVENT(kvm, 3, "%s", "ENABLE: CMMA support");
mutex_lock(&kvm->lock);
if (atomic_read(&kvm->online_vcpus) == 0) {
kvm->arch.use_cmma = 1;
@@ -339,6 +402,11 @@
mutex_unlock(&kvm->lock);
break;
case KVM_S390_VM_MEM_CLR_CMMA:
+ ret = -EINVAL;
+ if (!kvm->arch.use_cmma)
+ break;
+
+ VM_EVENT(kvm, 3, "%s", "RESET: CMMA states");
mutex_lock(&kvm->lock);
idx = srcu_read_lock(&kvm->srcu);
s390_reset_cmma(kvm->arch.gmap->mm);
@@ -374,6 +442,7 @@
}
}
mutex_unlock(&kvm->lock);
+ VM_EVENT(kvm, 3, "SET: max guest memory: %lu bytes", new_limit);
break;
}
default:
@@ -400,22 +469,26 @@
kvm->arch.crypto.crycb->aes_wrapping_key_mask,
sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
kvm->arch.crypto.aes_kw = 1;
+ VM_EVENT(kvm, 3, "%s", "ENABLE: AES keywrapping support");
break;
case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
get_random_bytes(
kvm->arch.crypto.crycb->dea_wrapping_key_mask,
sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
kvm->arch.crypto.dea_kw = 1;
+ VM_EVENT(kvm, 3, "%s", "ENABLE: DEA keywrapping support");
break;
case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
kvm->arch.crypto.aes_kw = 0;
memset(kvm->arch.crypto.crycb->aes_wrapping_key_mask, 0,
sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
+ VM_EVENT(kvm, 3, "%s", "DISABLE: AES keywrapping support");
break;
case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
kvm->arch.crypto.dea_kw = 0;
memset(kvm->arch.crypto.crycb->dea_wrapping_key_mask, 0,
sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
+ VM_EVENT(kvm, 3, "%s", "DISABLE: DEA keywrapping support");
break;
default:
mutex_unlock(&kvm->lock);
@@ -440,6 +513,7 @@
if (gtod_high != 0)
return -EINVAL;
+ VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x\n", gtod_high);
return 0;
}
@@ -459,12 +533,15 @@
return r;
mutex_lock(&kvm->lock);
+ preempt_disable();
kvm->arch.epoch = gtod - host_tod;
kvm_s390_vcpu_block_all(kvm);
kvm_for_each_vcpu(vcpu_idx, cur_vcpu, kvm)
cur_vcpu->arch.sie_block->epoch = kvm->arch.epoch;
kvm_s390_vcpu_unblock_all(kvm);
+ preempt_enable();
mutex_unlock(&kvm->lock);
+ VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx\n", gtod);
return 0;
}
@@ -496,6 +573,7 @@
if (copy_to_user((void __user *)attr->addr, >od_high,
sizeof(gtod_high)))
return -EFAULT;
+ VM_EVENT(kvm, 3, "QUERY: TOD extension: 0x%x\n", gtod_high);
return 0;
}
@@ -509,9 +587,12 @@
if (r)
return r;
+ preempt_disable();
gtod = host_tod + kvm->arch.epoch;
+ preempt_enable();
if (copy_to_user((void __user *)attr->addr, >od, sizeof(gtod)))
return -EFAULT;
+ VM_EVENT(kvm, 3, "QUERY: TOD base: 0x%llx\n", gtod);
return 0;
}
@@ -821,7 +902,9 @@
}
/* Enable storage key handling for the guest */
- s390_enable_skey();
+ r = s390_enable_skey();
+ if (r)
+ goto out;
for (i = 0; i < args->count; i++) {
hva = gfn_to_hva(kvm, args->start_gfn + i);
@@ -879,8 +962,7 @@
if (kvm->arch.use_irqchip) {
/* Set up dummy routing. */
memset(&routing, 0, sizeof(routing));
- kvm_set_irq_routing(kvm, &routing, 0, 0);
- r = 0;
+ r = kvm_set_irq_routing(kvm, &routing, 0, 0);
}
break;
}
@@ -1043,7 +1125,7 @@
sprintf(debug_name, "kvm-%u", current->pid);
- kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
+ kvm->arch.dbf = debug_register(debug_name, 32, 1, 7 * sizeof(long));
if (!kvm->arch.dbf)
goto out_err;
@@ -1086,7 +1168,7 @@
mutex_init(&kvm->arch.ipte_mutex);
debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
- VM_EVENT(kvm, 3, "%s", "vm created");
+ VM_EVENT(kvm, 3, "vm created with type %lu", type);
if (type & KVM_VM_S390_UCONTROL) {
kvm->arch.gmap = NULL;
@@ -1103,6 +1185,7 @@
kvm->arch.epoch = 0;
spin_lock_init(&kvm->arch.start_stop_lock);
+ KVM_EVENT(3, "vm 0x%p created by pid %u", kvm, current->pid);
return 0;
out_err:
@@ -1110,6 +1193,7 @@
free_page((unsigned long)kvm->arch.model.fac);
debug_unregister(kvm->arch.dbf);
free_page((unsigned long)(kvm->arch.sca));
+ KVM_EVENT(3, "creation of vm failed: %d", rc);
return rc;
}
@@ -1131,7 +1215,7 @@
if (kvm_is_ucontrol(vcpu->kvm))
gmap_free(vcpu->arch.gmap);
- if (kvm_s390_cmma_enabled(vcpu->kvm))
+ if (vcpu->kvm->arch.use_cmma)
kvm_s390_vcpu_unsetup_cmma(vcpu);
free_page((unsigned long)(vcpu->arch.sie_block));
@@ -1166,6 +1250,7 @@
gmap_free(kvm->arch.gmap);
kvm_s390_destroy_adapters(kvm);
kvm_s390_clear_float_irqs(kvm);
+ KVM_EVENT(3, "vm 0x%p destroyed", kvm);
}
/* Section: vcpu related */
@@ -1300,7 +1385,9 @@
void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
{
mutex_lock(&vcpu->kvm->lock);
+ preempt_disable();
vcpu->arch.sie_block->epoch = vcpu->kvm->arch.epoch;
+ preempt_enable();
mutex_unlock(&vcpu->kvm->lock);
if (!kvm_is_ucontrol(vcpu->kvm))
vcpu->arch.gmap = vcpu->kvm->arch.gmap;
@@ -1378,7 +1465,7 @@
}
vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
- if (kvm_s390_cmma_enabled(vcpu->kvm)) {
+ if (vcpu->kvm->arch.use_cmma) {
rc = kvm_s390_vcpu_setup_cmma(vcpu);
if (rc)
return rc;
@@ -1771,18 +1858,6 @@
return rc;
}
-bool kvm_s390_cmma_enabled(struct kvm *kvm)
-{
- if (!MACHINE_IS_LPAR)
- return false;
- /* only enable for z10 and later */
- if (!MACHINE_HAS_EDAT1)
- return false;
- if (!kvm->arch.use_cmma)
- return false;
- return true;
-}
-
static bool ibs_enabled(struct kvm_vcpu *vcpu)
{
return atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_IBS;
@@ -1790,10 +1865,10 @@
static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu)
{
- if (!vcpu->requests)
- return 0;
retry:
kvm_s390_vcpu_request_handled(vcpu);
+ if (!vcpu->requests)
+ return 0;
/*
* We use MMU_RELOAD just to re-arm the ipte notifier for the
* guest prefix page. gmap_ipte_notify will wait on the ptl lock.
@@ -2404,6 +2479,7 @@
case KVM_CAP_S390_CSS_SUPPORT:
if (!vcpu->kvm->arch.css_support) {
vcpu->kvm->arch.css_support = 1;
+ VM_EVENT(vcpu->kvm, 3, "%s", "ENABLE: CSS support");
trace_kvm_s390_enable_css(vcpu->kvm);
}
r = 0;
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index c570478..c446aab 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -27,6 +27,13 @@
#define TDB_FORMAT1 1
#define IS_ITDB_VALID(vcpu) ((*(char *)vcpu->arch.sie_block->itdba == TDB_FORMAT1))
+extern debug_info_t *kvm_s390_dbf;
+#define KVM_EVENT(d_loglevel, d_string, d_args...)\
+do { \
+ debug_sprintf_event(kvm_s390_dbf, d_loglevel, d_string "\n", \
+ d_args); \
+} while (0)
+
#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
do { \
debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \
@@ -65,6 +72,8 @@
static inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix)
{
+ VCPU_EVENT(vcpu, 3, "set prefix of cpu %03u to 0x%x", vcpu->vcpu_id,
+ prefix);
vcpu->arch.sie_block->prefix = prefix >> GUEST_PREFIX_SHIFT;
kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu);
@@ -217,8 +226,6 @@
void kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu);
int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu);
void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu);
-/* is cmma enabled */
-bool kvm_s390_cmma_enabled(struct kvm *kvm);
unsigned long kvm_s390_fac_list_mask_size(void);
extern unsigned long kvm_s390_fac_list_mask[];
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index ad42422..4d21dc4 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -53,11 +53,14 @@
kvm_s390_set_psw_cc(vcpu, 3);
return 0;
}
+ VCPU_EVENT(vcpu, 3, "SCK: setting guest TOD to 0x%llx", val);
val = (val - hostclk) & ~0x3fUL;
mutex_lock(&vcpu->kvm->lock);
+ preempt_disable();
kvm_for_each_vcpu(i, cpup, vcpu->kvm)
cpup->arch.sie_block->epoch = val;
+ preempt_enable();
mutex_unlock(&vcpu->kvm->lock);
kvm_s390_set_psw_cc(vcpu, 0);
@@ -98,8 +101,6 @@
return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
kvm_s390_set_prefix(vcpu, address);
-
- VCPU_EVENT(vcpu, 5, "setting prefix to %x", address);
trace_kvm_s390_handle_prefix(vcpu, 1, address);
return 0;
}
@@ -129,7 +130,7 @@
if (rc)
return kvm_s390_inject_prog_cond(vcpu, rc);
- VCPU_EVENT(vcpu, 5, "storing prefix to %x", address);
+ VCPU_EVENT(vcpu, 3, "STPX: storing prefix 0x%x into 0x%llx", address, operand2);
trace_kvm_s390_handle_prefix(vcpu, 0, address);
return 0;
}
@@ -155,7 +156,7 @@
if (rc)
return kvm_s390_inject_prog_cond(vcpu, rc);
- VCPU_EVENT(vcpu, 5, "storing cpu address to %llx", ga);
+ VCPU_EVENT(vcpu, 3, "STAP: storing cpu address (%u) to 0x%llx", vcpu_id, ga);
trace_kvm_s390_handle_stap(vcpu, ga);
return 0;
}
@@ -167,6 +168,7 @@
return rc;
rc = s390_enable_skey();
+ VCPU_EVENT(vcpu, 3, "%s", "enabling storage keys for guest");
trace_kvm_s390_skey_related_inst(vcpu);
vcpu->arch.sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE);
return rc;
@@ -370,7 +372,7 @@
&fac, sizeof(fac));
if (rc)
return rc;
- VCPU_EVENT(vcpu, 5, "store facility list value %x", fac);
+ VCPU_EVENT(vcpu, 3, "STFL: store facility list 0x%x", fac);
trace_kvm_s390_handle_stfl(vcpu, fac);
return 0;
}
@@ -468,7 +470,7 @@
if (rc)
return kvm_s390_inject_prog_cond(vcpu, rc);
- VCPU_EVENT(vcpu, 5, "%s", "store cpu id");
+ VCPU_EVENT(vcpu, 3, "STIDP: store cpu id 0x%llx", stidp_data);
return 0;
}
@@ -521,7 +523,7 @@
ar_t ar;
vcpu->stat.instruction_stsi++;
- VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2);
+ VCPU_EVENT(vcpu, 3, "STSI: fc: %u sel1: %u sel2: %u", fc, sel1, sel2);
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
@@ -758,10 +760,10 @@
struct gmap *gmap;
int i;
- VCPU_EVENT(vcpu, 5, "cmma release %d pages", entries);
+ VCPU_EVENT(vcpu, 4, "ESSA: release %d pages", entries);
gmap = vcpu->arch.gmap;
vcpu->stat.instruction_essa++;
- if (!kvm_s390_cmma_enabled(vcpu->kvm))
+ if (!vcpu->kvm->arch.use_cmma)
return kvm_s390_inject_program_int(vcpu, PGM_OPERATION);
if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
@@ -829,7 +831,7 @@
if (ga & 3)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
- VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
+ VCPU_EVENT(vcpu, 4, "LCTL: r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, ga);
nr_regs = ((reg3 - reg1) & 0xf) + 1;
@@ -868,7 +870,7 @@
if (ga & 3)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
- VCPU_EVENT(vcpu, 5, "stctl r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
+ VCPU_EVENT(vcpu, 4, "STCTL r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
trace_kvm_s390_handle_stctl(vcpu, 0, reg1, reg3, ga);
reg = reg1;
@@ -902,7 +904,7 @@
if (ga & 7)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
- VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
+ VCPU_EVENT(vcpu, 4, "LCTLG: r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, ga);
nr_regs = ((reg3 - reg1) & 0xf) + 1;
@@ -940,7 +942,7 @@
if (ga & 7)
return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
- VCPU_EVENT(vcpu, 5, "stctg r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
+ VCPU_EVENT(vcpu, 4, "STCTG r1:%d, r3:%d, addr: 0x%llx", reg1, reg3, ga);
trace_kvm_s390_handle_stctl(vcpu, 1, reg1, reg3, ga);
reg = reg1;
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 72e58bd..da690b6 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -205,9 +205,6 @@
*reg &= 0xffffffff00000000UL;
*reg |= SIGP_STATUS_INCORRECT_STATE;
return SIGP_CC_STATUS_STORED;
- } else if (rc == 0) {
- VCPU_EVENT(vcpu, 4, "set prefix of cpu %02x to %x",
- dst_vcpu->vcpu_id, irq.u.prefix.address);
}
return rc;
@@ -371,7 +368,8 @@
return rc;
}
-static int handle_sigp_order_in_user_space(struct kvm_vcpu *vcpu, u8 order_code)
+static int handle_sigp_order_in_user_space(struct kvm_vcpu *vcpu, u8 order_code,
+ u16 cpu_addr)
{
if (!vcpu->kvm->arch.user_sigp)
return 0;
@@ -414,9 +412,8 @@
default:
vcpu->stat.instruction_sigp_unknown++;
}
-
- VCPU_EVENT(vcpu, 4, "sigp order %u: completely handled in user space",
- order_code);
+ VCPU_EVENT(vcpu, 3, "SIGP: order %u for CPU %d handled in userspace",
+ order_code, cpu_addr);
return 1;
}
@@ -435,7 +432,7 @@
return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
order_code = kvm_s390_get_base_disp_rs(vcpu, NULL);
- if (handle_sigp_order_in_user_space(vcpu, order_code))
+ if (handle_sigp_order_in_user_space(vcpu, order_code, cpu_addr))
return -EOPNOTSUPP;
if (r1 % 2)
diff --git a/arch/s390/kvm/trace-s390.h b/arch/s390/kvm/trace-s390.h
index 3208d33..cc1d6c6 100644
--- a/arch/s390/kvm/trace-s390.h
+++ b/arch/s390/kvm/trace-s390.h
@@ -105,11 +105,22 @@
{KVM_S390_PROGRAM_INT, "program interrupt"}, \
{KVM_S390_SIGP_SET_PREFIX, "sigp set prefix"}, \
{KVM_S390_RESTART, "sigp restart"}, \
+ {KVM_S390_INT_PFAULT_INIT, "pfault init"}, \
+ {KVM_S390_INT_PFAULT_DONE, "pfault done"}, \
+ {KVM_S390_MCHK, "machine check"}, \
+ {KVM_S390_INT_CLOCK_COMP, "clock comparator"}, \
+ {KVM_S390_INT_CPU_TIMER, "cpu timer"}, \
{KVM_S390_INT_VIRTIO, "virtio interrupt"}, \
{KVM_S390_INT_SERVICE, "sclp interrupt"}, \
{KVM_S390_INT_EMERGENCY, "sigp emergency"}, \
{KVM_S390_INT_EXTERNAL_CALL, "sigp ext call"}
+#define get_irq_name(__type) \
+ (__type > KVM_S390_INT_IO_MAX ? \
+ __print_symbolic(__type, kvm_s390_int_type) : \
+ (__type & KVM_S390_INT_IO_AI_MASK ? \
+ "adapter I/O interrupt" : "subchannel I/O interrupt"))
+
TRACE_EVENT(kvm_s390_inject_vm,
TP_PROTO(__u64 type, __u32 parm, __u64 parm64, int who),
TP_ARGS(type, parm, parm64, who),
@@ -131,22 +142,19 @@
TP_printk("inject%s: type:%x (%s) parm:%x parm64:%llx",
(__entry->who == 1) ? " (from kernel)" :
(__entry->who == 2) ? " (from user)" : "",
- __entry->inttype,
- __print_symbolic(__entry->inttype, kvm_s390_int_type),
+ __entry->inttype, get_irq_name(__entry->inttype),
__entry->parm, __entry->parm64)
);
TRACE_EVENT(kvm_s390_inject_vcpu,
- TP_PROTO(unsigned int id, __u64 type, __u32 parm, __u64 parm64, \
- int who),
- TP_ARGS(id, type, parm, parm64, who),
+ TP_PROTO(unsigned int id, __u64 type, __u32 parm, __u64 parm64),
+ TP_ARGS(id, type, parm, parm64),
TP_STRUCT__entry(
__field(int, id)
__field(__u32, inttype)
__field(__u32, parm)
__field(__u64, parm64)
- __field(int, who)
),
TP_fast_assign(
@@ -154,15 +162,12 @@
__entry->inttype = type & 0x00000000ffffffff;
__entry->parm = parm;
__entry->parm64 = parm64;
- __entry->who = who;
),
- TP_printk("inject%s (vcpu %d): type:%x (%s) parm:%x parm64:%llx",
- (__entry->who == 1) ? " (from kernel)" :
- (__entry->who == 2) ? " (from user)" : "",
+ TP_printk("inject (vcpu %d): type:%x (%s) parm:%x parm64:%llx",
__entry->id, __entry->inttype,
- __print_symbolic(__entry->inttype, kvm_s390_int_type),
- __entry->parm, __entry->parm64)
+ get_irq_name(__entry->inttype), __entry->parm,
+ __entry->parm64)
);
/*
@@ -189,8 +194,8 @@
TP_printk("deliver interrupt (vcpu %d): type:%x (%s) " \
"data:%08llx %016llx",
__entry->id, __entry->inttype,
- __print_symbolic(__entry->inttype, kvm_s390_int_type),
- __entry->data0, __entry->data1)
+ get_irq_name(__entry->inttype), __entry->data0,
+ __entry->data1)
);
/*
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index fee782a..8d2e516 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -448,13 +448,13 @@
EMIT6_DISP_LH(0xe3000000, 0x0004, REG_SKB_DATA, REG_0,
BPF_REG_1, offsetof(struct sk_buff, data));
}
- /* BPF compatibility: clear A (%b7) and X (%b8) registers */
- if (REG_SEEN(BPF_REG_7))
- /* lghi %b7,0 */
- EMIT4_IMM(0xa7090000, BPF_REG_7, 0);
- if (REG_SEEN(BPF_REG_8))
- /* lghi %b8,0 */
- EMIT4_IMM(0xa7090000, BPF_REG_8, 0);
+ /* BPF compatibility: clear A (%b0) and X (%b7) registers */
+ if (REG_SEEN(BPF_REG_A))
+ /* lghi %ba,0 */
+ EMIT4_IMM(0xa7090000, BPF_REG_A, 0);
+ if (REG_SEEN(BPF_REG_X))
+ /* lghi %bx,0 */
+ EMIT4_IMM(0xa7090000, BPF_REG_X, 0);
}
/*
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 0a47bd3..4ca78ed 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -355,13 +355,12 @@
return error;
}
-static int sq_dev_remove(struct device *dev, struct subsys_interface *sif)
+static void sq_dev_remove(struct device *dev, struct subsys_interface *sif)
{
unsigned int cpu = dev->id;
struct kobject *kobj = sq_kobject[cpu];
kobject_put(kobj);
- return 0;
}
static struct subsys_interface sq_interface = {
diff --git a/arch/sparc/include/asm/visasm.h b/arch/sparc/include/asm/visasm.h
index 1f0aa20..6424249 100644
--- a/arch/sparc/include/asm/visasm.h
+++ b/arch/sparc/include/asm/visasm.h
@@ -28,16 +28,10 @@
* Must preserve %o5 between VISEntryHalf and VISExitHalf */
#define VISEntryHalf \
- rd %fprs, %o5; \
- andcc %o5, FPRS_FEF, %g0; \
- be,pt %icc, 297f; \
- sethi %hi(298f), %g7; \
- sethi %hi(VISenterhalf), %g1; \
- jmpl %g1 + %lo(VISenterhalf), %g0; \
- or %g7, %lo(298f), %g7; \
- clr %o5; \
-297: wr %o5, FPRS_FEF, %fprs; \
-298:
+ VISEntry
+
+#define VISExitHalf \
+ VISExit
#define VISEntryHalfFast(fail_label) \
rd %fprs, %o5; \
@@ -47,7 +41,7 @@
ba,a,pt %xcc, fail_label; \
297: wr %o5, FPRS_FEF, %fprs;
-#define VISExitHalf \
+#define VISExitHalfFast \
wr %o5, 0, %fprs;
#ifndef __ASSEMBLY__
diff --git a/arch/sparc/lib/NG4memcpy.S b/arch/sparc/lib/NG4memcpy.S
index 140527a..83aeeb1 100644
--- a/arch/sparc/lib/NG4memcpy.S
+++ b/arch/sparc/lib/NG4memcpy.S
@@ -240,8 +240,11 @@
add %o0, 0x40, %o0
bne,pt %icc, 1b
LOAD(prefetch, %g1 + 0x200, #n_reads_strong)
+#ifdef NON_USER_COPY
+ VISExitHalfFast
+#else
VISExitHalf
-
+#endif
brz,pn %o2, .Lexit
cmp %o2, 19
ble,pn %icc, .Lsmall_unaligned
diff --git a/arch/sparc/lib/VISsave.S b/arch/sparc/lib/VISsave.S
index b320ae9..a063d84 100644
--- a/arch/sparc/lib/VISsave.S
+++ b/arch/sparc/lib/VISsave.S
@@ -44,9 +44,8 @@
stx %g3, [%g6 + TI_GSR]
2: add %g6, %g1, %g3
- cmp %o5, FPRS_DU
- be,pn %icc, 6f
- sll %g1, 3, %g1
+ mov FPRS_DU | FPRS_DL | FPRS_FEF, %o5
+ sll %g1, 3, %g1
stb %o5, [%g3 + TI_FPSAVED]
rd %gsr, %g2
add %g6, %g1, %g3
@@ -80,65 +79,3 @@
.align 32
80: jmpl %g7 + %g0, %g0
nop
-
-6: ldub [%g3 + TI_FPSAVED], %o5
- or %o5, FPRS_DU, %o5
- add %g6, TI_FPREGS+0x80, %g2
- stb %o5, [%g3 + TI_FPSAVED]
-
- sll %g1, 5, %g1
- add %g6, TI_FPREGS+0xc0, %g3
- wr %g0, FPRS_FEF, %fprs
- membar #Sync
- stda %f32, [%g2 + %g1] ASI_BLK_P
- stda %f48, [%g3 + %g1] ASI_BLK_P
- membar #Sync
- ba,pt %xcc, 80f
- nop
-
- .align 32
-80: jmpl %g7 + %g0, %g0
- nop
-
- .align 32
-VISenterhalf:
- ldub [%g6 + TI_FPDEPTH], %g1
- brnz,a,pn %g1, 1f
- cmp %g1, 1
- stb %g0, [%g6 + TI_FPSAVED]
- stx %fsr, [%g6 + TI_XFSR]
- clr %o5
- jmpl %g7 + %g0, %g0
- wr %g0, FPRS_FEF, %fprs
-
-1: bne,pn %icc, 2f
- srl %g1, 1, %g1
- ba,pt %xcc, vis1
- sub %g7, 8, %g7
-2: addcc %g6, %g1, %g3
- sll %g1, 3, %g1
- andn %o5, FPRS_DU, %g2
- stb %g2, [%g3 + TI_FPSAVED]
-
- rd %gsr, %g2
- add %g6, %g1, %g3
- stx %g2, [%g3 + TI_GSR]
- add %g6, %g1, %g2
- stx %fsr, [%g2 + TI_XFSR]
- sll %g1, 5, %g1
-3: andcc %o5, FPRS_DL, %g0
- be,pn %icc, 4f
- add %g6, TI_FPREGS, %g2
-
- add %g6, TI_FPREGS+0x40, %g3
- membar #Sync
- stda %f0, [%g2 + %g1] ASI_BLK_P
- stda %f16, [%g3 + %g1] ASI_BLK_P
- membar #Sync
- ba,pt %xcc, 4f
- nop
-
- .align 32
-4: and %o5, FPRS_DU, %o5
- jmpl %g7 + %g0, %g0
- wr %o5, FPRS_FEF, %fprs
diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c
index 1d649a9..8069ce1 100644
--- a/arch/sparc/lib/ksyms.c
+++ b/arch/sparc/lib/ksyms.c
@@ -135,10 +135,6 @@
void VISenter(void);
EXPORT_SYMBOL(VISenter);
-/* CRYPTO code needs this */
-void VISenterhalf(void);
-EXPORT_SYMBOL(VISenterhalf);
-
extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *);
extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *,
unsigned long *);
diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index e8c2c04..c667e10 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -113,8 +113,6 @@
if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
return -EFAULT;
- memset(to, 0, sizeof(*to));
-
err = __get_user(to->si_signo, &from->si_signo);
err |= __get_user(to->si_errno, &from->si_errno);
err |= __get_user(to->si_code, &from->si_code);
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index 99c9ff8..6b755d1 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -1139,7 +1139,7 @@
void __init free_initrd_mem(unsigned long begin, unsigned long end)
{
- free_bootmem(__pa(begin), end - begin);
+ free_bootmem_late(__pa(begin), end - begin);
}
static int __init setup_initrd(char *str)
diff --git a/arch/tile/kernel/sysfs.c b/arch/tile/kernel/sysfs.c
index a3ed12f..825867c 100644
--- a/arch/tile/kernel/sysfs.c
+++ b/arch/tile/kernel/sysfs.c
@@ -198,16 +198,13 @@
return err;
}
-static int hv_stats_device_remove(struct device *dev,
- struct subsys_interface *sif)
+static void hv_stats_device_remove(struct device *dev,
+ struct subsys_interface *sif)
{
int cpu = dev->id;
- if (!cpu_online(cpu))
- return 0;
-
- sysfs_remove_file(&dev->kobj, &dev_attr_hv_stats.attr);
- return 0;
+ if (cpu_online(cpu))
+ sysfs_remove_file(&dev->kobj, &dev_attr_hv_stats.attr);
}
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 2c82bd1..7d69afd 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -1193,6 +1193,10 @@
unsigned int e820_type = 0;
unsigned long m = efi->efi_memmap;
+#ifdef CONFIG_X86_64
+ m |= (u64)efi->efi_memmap_hi << 32;
+#endif
+
d = (efi_memory_desc_t *)(m + (i * efi->efi_memdesc_size));
switch (d->type) {
case EFI_RESERVED_TYPE:
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index bb187a6..a7e257d 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -140,6 +140,7 @@
*/
andl $~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
movl RIP(%rsp), %ecx /* User %eip */
+ movq RAX(%rsp), %rax
RESTORE_RSI_RDI
xorl %edx, %edx /* Do not leak kernel information */
xorq %r8, %r8
@@ -205,7 +206,6 @@
movl RDX(%rsp), %edx /* arg3 */
movl RSI(%rsp), %ecx /* arg4 */
movl RDI(%rsp), %r8d /* arg5 */
- movl %ebp, %r9d /* arg6 */
.endm
.macro auditsys_exit exit
@@ -220,7 +220,6 @@
1: setbe %al /* 1 if error, 0 if not */
movzbl %al, %edi /* zero-extend that into %edi */
call __audit_syscall_exit
- movq RAX(%rsp), %rax /* reload syscall return value */
movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT), %edi
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
@@ -236,6 +235,7 @@
sysenter_auditsys:
auditsys_entry_common
+ movl %ebp, %r9d /* reload 6th syscall arg */
jmp sysenter_dispatch
sysexit_audit:
@@ -336,7 +336,7 @@
* 32-bit zero extended:
*/
ASM_STAC
-1: movl (%r8), %ebp
+1: movl (%r8), %r9d
_ASM_EXTABLE(1b, ia32_badarg)
ASM_CLAC
orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
@@ -346,7 +346,7 @@
cstar_do_call:
/* 32-bit syscall -> 64-bit C ABI argument conversion */
movl %edi, %r8d /* arg5 */
- movl %ebp, %r9d /* arg6 */
+ /* r9 already loaded */ /* arg6 */
xchg %ecx, %esi /* rsi:arg2, rcx:arg4 */
movl %ebx, %edi /* arg1 */
movl %edx, %edx /* arg3 (zero extension) */
@@ -358,7 +358,6 @@
call *ia32_sys_call_table(, %rax, 8)
movq %rax, RAX(%rsp)
1:
- movl RCX(%rsp), %ebp
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
@@ -369,6 +368,7 @@
RESTORE_RSI_RDI_RDX
movl RIP(%rsp), %ecx
movl EFLAGS(%rsp), %r11d
+ movq RAX(%rsp), %rax
xorq %r10, %r10
xorq %r9, %r9
xorq %r8, %r8
@@ -392,7 +392,9 @@
#ifdef CONFIG_AUDITSYSCALL
cstar_auditsys:
+ movl %r9d, R9(%rsp) /* register to be clobbered by call */
auditsys_entry_common
+ movl R9(%rsp), %r9d /* reload 6th syscall arg */
jmp cstar_dispatch
sysretl_audit:
@@ -404,14 +406,16 @@
testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
jz cstar_auditsys
#endif
+ xchgl %r9d, %ebp
SAVE_EXTRA_REGS
xorl %eax, %eax /* Do not leak kernel information */
movq %rax, R11(%rsp)
movq %rax, R10(%rsp)
- movq %rax, R9(%rsp)
+ movq %r9, R9(%rsp)
movq %rax, R8(%rsp)
movq %rsp, %rdi /* &pt_regs -> arg1 */
call syscall_trace_enter
+ movl R9(%rsp), %r9d
/* Reload arg registers from stack. (see sysenter_tracesys) */
movl RCX(%rsp), %ecx
@@ -421,6 +425,7 @@
movl %eax, %eax /* zero extension */
RESTORE_EXTRA_REGS
+ xchgl %ebp, %r9d
jmp cstar_do_call
END(entry_SYSCALL_compat)
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
index a0bf89f..4e10d73 100644
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -280,21 +280,6 @@
set_ldt(NULL, 0);
}
-/*
- * load one particular LDT into the current CPU
- */
-static inline void load_LDT_nolock(mm_context_t *pc)
-{
- set_ldt(pc->ldt, pc->size);
-}
-
-static inline void load_LDT(mm_context_t *pc)
-{
- preempt_disable();
- load_LDT_nolock(pc);
- preempt_enable();
-}
-
static inline unsigned long get_desc_base(const struct desc_struct *desc)
{
return (unsigned)(desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24));
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 49ec903..c12e845 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -252,6 +252,11 @@
int size;
};
+struct rsvd_bits_validate {
+ u64 rsvd_bits_mask[2][4];
+ u64 bad_mt_xwr;
+};
+
/*
* x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level
* 32-bit). The kvm_mmu structure abstracts the details of the current mmu
@@ -289,8 +294,15 @@
u64 *pae_root;
u64 *lm_root;
- u64 rsvd_bits_mask[2][4];
- u64 bad_mt_xwr;
+
+ /*
+ * check zero bits on shadow page table entries, these
+ * bits include not only hardware reserved bits but also
+ * the bits spte never used.
+ */
+ struct rsvd_bits_validate shadow_zero_check;
+
+ struct rsvd_bits_validate guest_rsvd_check;
/*
* Bitmap: bit set = last pte in walk
@@ -358,6 +370,11 @@
struct list_head head;
};
+/* Hyper-V per vcpu emulation context */
+struct kvm_vcpu_hv {
+ u64 hv_vapic;
+};
+
struct kvm_vcpu_arch {
/*
* rip and regs accesses must go through
@@ -514,8 +531,7 @@
/* used for guest single stepping over the given code position */
unsigned long singlestep_rip;
- /* fields used by HYPER-V emulation */
- u64 hv_vapic;
+ struct kvm_vcpu_hv hyperv;
cpumask_var_t wbinvd_dirty_mask;
@@ -586,6 +602,17 @@
struct kvm_lapic *logical_map[16][16];
};
+/* Hyper-V emulation context */
+struct kvm_hv {
+ u64 hv_guest_os_id;
+ u64 hv_hypercall;
+ u64 hv_tsc_page;
+
+ /* Hyper-v based guest crash (NT kernel bugcheck) parameters */
+ u64 hv_crash_param[HV_X64_MSR_CRASH_PARAMS];
+ u64 hv_crash_ctl;
+};
+
struct kvm_arch {
unsigned int n_used_mmu_pages;
unsigned int n_requested_mmu_pages;
@@ -645,16 +672,14 @@
/* reads protected by irq_srcu, writes by irq_lock */
struct hlist_head mask_notifier_list;
- /* fields used by HYPER-V emulation */
- u64 hv_guest_os_id;
- u64 hv_hypercall;
- u64 hv_tsc_page;
+ struct kvm_hv hyperv;
#ifdef CONFIG_KVM_MMU_AUDIT
int audit_point;
#endif
bool boot_vcpu_runs_old_kvmclock;
+ u32 bsp_vcpu_id;
u64 disabled_quirks;
};
@@ -1203,5 +1228,7 @@
const struct kvm_userspace_memory_region *mem);
int x86_set_memory_region(struct kvm *kvm,
const struct kvm_userspace_memory_region *mem);
+bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu);
+bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu);
#endif /* _ASM_X86_KVM_HOST_H */
diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h
index 09b9620..364d274 100644
--- a/arch/x86/include/asm/mmu.h
+++ b/arch/x86/include/asm/mmu.h
@@ -9,8 +9,7 @@
* we put the segment information here.
*/
typedef struct {
- void *ldt;
- int size;
+ struct ldt_struct *ldt;
#ifdef CONFIG_X86_64
/* True if mm supports a task running in 32 bit compatibility mode. */
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 804a3a6..984abfe 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -34,6 +34,50 @@
#endif
/*
+ * ldt_structs can be allocated, used, and freed, but they are never
+ * modified while live.
+ */
+struct ldt_struct {
+ /*
+ * Xen requires page-aligned LDTs with special permissions. This is
+ * needed to prevent us from installing evil descriptors such as
+ * call gates. On native, we could merge the ldt_struct and LDT
+ * allocations, but it's not worth trying to optimize.
+ */
+ struct desc_struct *entries;
+ int size;
+};
+
+static inline void load_mm_ldt(struct mm_struct *mm)
+{
+ struct ldt_struct *ldt;
+
+ /* lockless_dereference synchronizes with smp_store_release */
+ ldt = lockless_dereference(mm->context.ldt);
+
+ /*
+ * Any change to mm->context.ldt is followed by an IPI to all
+ * CPUs with the mm active. The LDT will not be freed until
+ * after the IPI is handled by all such CPUs. This means that,
+ * if the ldt_struct changes before we return, the values we see
+ * will be safe, and the new values will be loaded before we run
+ * any user code.
+ *
+ * NB: don't try to convert this to use RCU without extreme care.
+ * We would still need IRQs off, because we don't want to change
+ * the local LDT after an IPI loaded a newer value than the one
+ * that we can see.
+ */
+
+ if (unlikely(ldt))
+ set_ldt(ldt->entries, ldt->size);
+ else
+ clear_LDT();
+
+ DEBUG_LOCKS_WARN_ON(preemptible());
+}
+
+/*
* Used for LDT copy/destruction.
*/
int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
@@ -78,12 +122,12 @@
* was called and then modify_ldt changed
* prev->context.ldt but suppressed an IPI to this CPU.
* In this case, prev->context.ldt != NULL, because we
- * never free an LDT while the mm still exists. That
- * means that next->context.ldt != prev->context.ldt,
- * because mms never share an LDT.
+ * never set context.ldt to NULL while the mm still
+ * exists. That means that next->context.ldt !=
+ * prev->context.ldt, because mms never share an LDT.
*/
if (unlikely(prev->context.ldt != next->context.ldt))
- load_LDT_nolock(&next->context);
+ load_mm_ldt(next);
}
#ifdef CONFIG_SMP
else {
@@ -106,7 +150,7 @@
load_cr3(next->pgd);
trace_tlb_flush(TLB_FLUSH_ON_TASK_SWITCH, TLB_FLUSH_ALL);
load_mm_cr4(next);
- load_LDT_nolock(&next->context);
+ load_mm_ldt(next);
}
}
#endif
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index c163215..aaf59b7 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -7,6 +7,7 @@
struct ms_hyperv_info {
u32 features;
+ u32 misc_features;
u32 hints;
};
@@ -20,4 +21,8 @@
void hv_setup_vmbus_irq(void (*handler)(void));
void hv_remove_vmbus_irq(void);
+void hv_setup_kexec_handler(void (*handler)(void));
+void hv_remove_kexec_handler(void);
+void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs));
+void hv_remove_crash_handler(void);
#endif
diff --git a/arch/x86/include/asm/sigcontext.h b/arch/x86/include/asm/sigcontext.h
index 6fe6b18..9dfce4e 100644
--- a/arch/x86/include/asm/sigcontext.h
+++ b/arch/x86/include/asm/sigcontext.h
@@ -57,9 +57,9 @@
unsigned long ip;
unsigned long flags;
unsigned short cs;
- unsigned short __pad2; /* Was called gs, but was always zero. */
- unsigned short __pad1; /* Was called fs, but was always zero. */
- unsigned short ss;
+ unsigned short gs;
+ unsigned short fs;
+ unsigned short __pad0;
unsigned long err;
unsigned long trapno;
unsigned long oldmask;
diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h
index 751bf4b..d7f3b3b 100644
--- a/arch/x86/include/asm/switch_to.h
+++ b/arch/x86/include/asm/switch_to.h
@@ -79,12 +79,12 @@
#else /* CONFIG_X86_32 */
/* frame pointer must be last for get_wchan */
-#define SAVE_CONTEXT "pushq %%rbp ; movq %%rsi,%%rbp\n\t"
-#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp\t"
+#define SAVE_CONTEXT "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
+#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
#define __EXTRA_CLOBBER \
, "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
- "r12", "r13", "r14", "r15", "flags"
+ "r12", "r13", "r14", "r15"
#ifdef CONFIG_CC_STACKPROTECTOR
#define __switch_canary \
@@ -100,11 +100,7 @@
#define __switch_canary_iparam
#endif /* CC_STACKPROTECTOR */
-/*
- * There is no need to save or restore flags, because flags are always
- * clean in kernel mode, with the possible exception of IOPL. Kernel IOPL
- * has no effect.
- */
+/* Save restore flags to clear handle leaking NT */
#define switch_to(prev, next, last) \
asm volatile(SAVE_CONTEXT \
"movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index da772ed..448b7ca 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -47,6 +47,7 @@
#define CPU_BASED_MOV_DR_EXITING 0x00800000
#define CPU_BASED_UNCOND_IO_EXITING 0x01000000
#define CPU_BASED_USE_IO_BITMAPS 0x02000000
+#define CPU_BASED_MONITOR_TRAP_FLAG 0x08000000
#define CPU_BASED_USE_MSR_BITMAPS 0x10000000
#define CPU_BASED_MONITOR_EXITING 0x20000000
#define CPU_BASED_PAUSE_EXITING 0x40000000
@@ -367,29 +368,29 @@
#define TYPE_PHYSICAL_APIC_EVENT (10 << 12)
#define TYPE_PHYSICAL_APIC_INST (15 << 12)
-/* segment AR */
-#define SEGMENT_AR_L_MASK (1 << 13)
+/* segment AR in VMCS -- these are different from what LAR reports */
+#define VMX_SEGMENT_AR_L_MASK (1 << 13)
-#define AR_TYPE_ACCESSES_MASK 1
-#define AR_TYPE_READABLE_MASK (1 << 1)
-#define AR_TYPE_WRITEABLE_MASK (1 << 2)
-#define AR_TYPE_CODE_MASK (1 << 3)
-#define AR_TYPE_MASK 0x0f
-#define AR_TYPE_BUSY_64_TSS 11
-#define AR_TYPE_BUSY_32_TSS 11
-#define AR_TYPE_BUSY_16_TSS 3
-#define AR_TYPE_LDT 2
+#define VMX_AR_TYPE_ACCESSES_MASK 1
+#define VMX_AR_TYPE_READABLE_MASK (1 << 1)
+#define VMX_AR_TYPE_WRITEABLE_MASK (1 << 2)
+#define VMX_AR_TYPE_CODE_MASK (1 << 3)
+#define VMX_AR_TYPE_MASK 0x0f
+#define VMX_AR_TYPE_BUSY_64_TSS 11
+#define VMX_AR_TYPE_BUSY_32_TSS 11
+#define VMX_AR_TYPE_BUSY_16_TSS 3
+#define VMX_AR_TYPE_LDT 2
-#define AR_UNUSABLE_MASK (1 << 16)
-#define AR_S_MASK (1 << 4)
-#define AR_P_MASK (1 << 7)
-#define AR_L_MASK (1 << 13)
-#define AR_DB_MASK (1 << 14)
-#define AR_G_MASK (1 << 15)
-#define AR_DPL_SHIFT 5
-#define AR_DPL(ar) (((ar) >> AR_DPL_SHIFT) & 3)
+#define VMX_AR_UNUSABLE_MASK (1 << 16)
+#define VMX_AR_S_MASK (1 << 4)
+#define VMX_AR_P_MASK (1 << 7)
+#define VMX_AR_L_MASK (1 << 13)
+#define VMX_AR_DB_MASK (1 << 14)
+#define VMX_AR_G_MASK (1 << 15)
+#define VMX_AR_DPL_SHIFT 5
+#define VMX_AR_DPL(ar) (((ar) >> VMX_AR_DPL_SHIFT) & 3)
-#define AR_RESERVD_MASK 0xfffe0f00
+#define VMX_AR_RESERVD_MASK 0xfffe0f00
#define TSS_PRIVATE_MEMSLOT (KVM_USER_MEM_SLOTS + 0)
#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT (KVM_USER_MEM_SLOTS + 1)
diff --git a/arch/x86/include/uapi/asm/hyperv.h b/arch/x86/include/uapi/asm/hyperv.h
index f36d56b..f0412c5 100644
--- a/arch/x86/include/uapi/asm/hyperv.h
+++ b/arch/x86/include/uapi/asm/hyperv.h
@@ -27,6 +27,8 @@
#define HV_X64_MSR_VP_RUNTIME_AVAILABLE (1 << 0)
/* Partition Reference Counter (HV_X64_MSR_TIME_REF_COUNT) available*/
#define HV_X64_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
+/* Partition reference TSC MSR is available */
+#define HV_X64_MSR_REFERENCE_TSC_AVAILABLE (1 << 9)
/* A partition's reference time stamp counter (TSC) page */
#define HV_X64_MSR_REFERENCE_TSC 0x40000021
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
index a4ae82e..cd54147 100644
--- a/arch/x86/include/uapi/asm/kvm.h
+++ b/arch/x86/include/uapi/asm/kvm.h
@@ -354,7 +354,7 @@
struct kvm_sync_regs {
};
-#define KVM_QUIRK_LINT0_REENABLED (1 << 0)
-#define KVM_QUIRK_CD_NW_CLEARED (1 << 1)
+#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
+#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1)
#endif /* _ASM_X86_KVM_H */
diff --git a/arch/x86/include/uapi/asm/sigcontext.h b/arch/x86/include/uapi/asm/sigcontext.h
index 0e8a973..40836a9 100644
--- a/arch/x86/include/uapi/asm/sigcontext.h
+++ b/arch/x86/include/uapi/asm/sigcontext.h
@@ -177,24 +177,9 @@
__u64 rip;
__u64 eflags; /* RFLAGS */
__u16 cs;
-
- /*
- * Prior to 2.5.64 ("[PATCH] x86-64 updates for 2.5.64-bk3"),
- * Linux saved and restored fs and gs in these slots. This
- * was counterproductive, as fsbase and gsbase were never
- * saved, so arch_prctl was presumably unreliable.
- *
- * If these slots are ever needed for any other purpose, there
- * is some risk that very old 64-bit binaries could get
- * confused. I doubt that many such binaries still work,
- * though, since the same patch in 2.5.64 also removed the
- * 64-bit set_thread_area syscall, so it appears that there is
- * no TLS API that works in both pre- and post-2.5.64 kernels.
- */
- __u16 __pad2; /* Was gs. */
- __u16 __pad1; /* Was fs. */
-
- __u16 ss;
+ __u16 gs;
+ __u16 fs;
+ __u16 __pad0;
__u64 err;
__u64 trapno;
__u64 oldmask;
diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
index 1fe9218..37fee27 100644
--- a/arch/x86/include/uapi/asm/vmx.h
+++ b/arch/x86/include/uapi/asm/vmx.h
@@ -58,6 +58,7 @@
#define EXIT_REASON_INVALID_STATE 33
#define EXIT_REASON_MSR_LOAD_FAIL 34
#define EXIT_REASON_MWAIT_INSTRUCTION 36
+#define EXIT_REASON_MONITOR_TRAP_FLAG 37
#define EXIT_REASON_MONITOR_INSTRUCTION 39
#define EXIT_REASON_PAUSE_INSTRUCTION 40
#define EXIT_REASON_MCE_DURING_VMENTRY 41
@@ -106,6 +107,7 @@
{ EXIT_REASON_MSR_READ, "MSR_READ" }, \
{ EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
{ EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
+ { EXIT_REASON_MONITOR_TRAP_FLAG, "MONITOR_TRAP_FLAG" }, \
{ EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
{ EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
{ EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index dcb5285..cde732c 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1424,7 +1424,7 @@
{
u64 msr;
- if (cpu_has_apic)
+ if (!cpu_has_apic)
return;
rdmsrl(MSR_IA32_APICBASE, msr);
@@ -1483,10 +1483,13 @@
static __init void x2apic_disable(void)
{
- u32 x2apic_id;
+ u32 x2apic_id, state = x2apic_state;
- if (x2apic_state != X2APIC_ON)
- goto out;
+ x2apic_mode = 0;
+ x2apic_state = X2APIC_DISABLED;
+
+ if (state != X2APIC_ON)
+ return;
x2apic_id = read_apic_id();
if (x2apic_id >= 255)
@@ -1494,9 +1497,6 @@
__x2apic_disable();
register_lapic_address(mp_lapic_addr);
-out:
- x2apic_state = X2APIC_DISABLED;
- x2apic_mode = 0;
}
static __init void x2apic_enable(void)
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 845dc0d..206052e 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -943,7 +943,7 @@
*/
if (irq < nr_legacy_irqs() && data->count == 1) {
if (info->ioapic_trigger != data->trigger)
- mp_register_handler(irq, data->trigger);
+ mp_register_handler(irq, info->ioapic_trigger);
data->entry.trigger = data->trigger = info->ioapic_trigger;
data->entry.polarity = data->polarity = info->ioapic_polarity;
}
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index f813261..2683f36 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -322,7 +322,7 @@
irq_data->chip = &lapic_controller;
irq_data->chip_data = data;
irq_data->hwirq = virq + i;
- err = assign_irq_vector_policy(virq, irq_data->node, data,
+ err = assign_irq_vector_policy(virq + i, irq_data->node, data,
info);
if (err)
goto error;
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 922c5e0..cb9e5df 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1410,7 +1410,7 @@
load_sp0(t, ¤t->thread);
set_tss_desc(cpu, t);
load_TR_desc();
- load_LDT(&init_mm.context);
+ load_mm_ldt(&init_mm);
clear_all_debug_regs();
dbg_restore_debug_regs();
@@ -1459,7 +1459,7 @@
load_sp0(t, thread);
set_tss_desc(cpu, t);
load_TR_desc();
- load_LDT(&init_mm.context);
+ load_mm_ldt(&init_mm);
t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 6236a54..3c98639 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -377,17 +377,16 @@
return err;
}
-static int mc_device_remove(struct device *dev, struct subsys_interface *sif)
+static void mc_device_remove(struct device *dev, struct subsys_interface *sif)
{
int cpu = dev->id;
if (!cpu_online(cpu))
- return 0;
+ return;
pr_debug("CPU%d removed\n", cpu);
microcode_fini_cpu(cpu);
sysfs_remove_group(&dev->kobj, &mc_attr_group);
- return 0;
}
static struct subsys_interface mc_cpu_interface = {
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index aad4bd8..f794bfa 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -18,6 +18,7 @@
#include <linux/efi.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/kexec.h>
#include <asm/processor.h>
#include <asm/hypervisor.h>
#include <asm/hyperv.h>
@@ -28,10 +29,14 @@
#include <asm/i8259.h>
#include <asm/apic.h>
#include <asm/timer.h>
+#include <asm/reboot.h>
struct ms_hyperv_info ms_hyperv;
EXPORT_SYMBOL_GPL(ms_hyperv);
+static void (*hv_kexec_handler)(void);
+static void (*hv_crash_handler)(struct pt_regs *regs);
+
#if IS_ENABLED(CONFIG_HYPERV)
static void (*vmbus_handler)(void);
@@ -67,8 +72,47 @@
}
EXPORT_SYMBOL_GPL(hv_setup_vmbus_irq);
EXPORT_SYMBOL_GPL(hv_remove_vmbus_irq);
+
+void hv_setup_kexec_handler(void (*handler)(void))
+{
+ hv_kexec_handler = handler;
+}
+EXPORT_SYMBOL_GPL(hv_setup_kexec_handler);
+
+void hv_remove_kexec_handler(void)
+{
+ hv_kexec_handler = NULL;
+}
+EXPORT_SYMBOL_GPL(hv_remove_kexec_handler);
+
+void hv_setup_crash_handler(void (*handler)(struct pt_regs *regs))
+{
+ hv_crash_handler = handler;
+}
+EXPORT_SYMBOL_GPL(hv_setup_crash_handler);
+
+void hv_remove_crash_handler(void)
+{
+ hv_crash_handler = NULL;
+}
+EXPORT_SYMBOL_GPL(hv_remove_crash_handler);
#endif
+static void hv_machine_shutdown(void)
+{
+ if (kexec_in_progress && hv_kexec_handler)
+ hv_kexec_handler();
+ native_machine_shutdown();
+}
+
+static void hv_machine_crash_shutdown(struct pt_regs *regs)
+{
+ if (hv_crash_handler)
+ hv_crash_handler(regs);
+ native_machine_crash_shutdown(regs);
+}
+
+
static uint32_t __init ms_hyperv_platform(void)
{
u32 eax;
@@ -114,6 +158,7 @@
* Extract the features and hints
*/
ms_hyperv.features = cpuid_eax(HYPERV_CPUID_FEATURES);
+ ms_hyperv.misc_features = cpuid_edx(HYPERV_CPUID_FEATURES);
ms_hyperv.hints = cpuid_eax(HYPERV_CPUID_ENLIGHTMENT_INFO);
printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n",
@@ -141,6 +186,8 @@
no_timer_check = 1;
#endif
+ machine_ops.shutdown = hv_machine_shutdown;
+ machine_ops.crash_shutdown = hv_machine_crash_shutdown;
}
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 3658de4..9469dfa 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -2179,21 +2179,25 @@
int idx = segment >> 3;
if ((segment & SEGMENT_TI_MASK) == SEGMENT_LDT) {
+ struct ldt_struct *ldt;
+
if (idx > LDT_ENTRIES)
return 0;
- if (idx > current->active_mm->context.size)
+ /* IRQs are off, so this synchronizes with smp_store_release */
+ ldt = lockless_dereference(current->active_mm->context.ldt);
+ if (!ldt || idx > ldt->size)
return 0;
- desc = current->active_mm->context.ldt;
+ desc = &ldt->entries[idx];
} else {
if (idx > GDT_ENTRIES)
return 0;
- desc = raw_cpu_ptr(gdt_page.gdt);
+ desc = raw_cpu_ptr(gdt_page.gdt) + idx;
}
- return get_desc_base(desc + idx);
+ return get_desc_base(desc);
}
#ifdef CONFIG_COMPAT
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index b9826a9..6326ae2 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2534,7 +2534,7 @@
if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) {
cpuc->shared_regs = allocate_shared_regs(cpu);
if (!cpuc->shared_regs)
- return NOTIFY_BAD;
+ goto err;
}
if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
@@ -2542,18 +2542,27 @@
cpuc->constraint_list = kzalloc(sz, GFP_KERNEL);
if (!cpuc->constraint_list)
- return NOTIFY_BAD;
+ goto err_shared_regs;
cpuc->excl_cntrs = allocate_excl_cntrs(cpu);
- if (!cpuc->excl_cntrs) {
- kfree(cpuc->constraint_list);
- kfree(cpuc->shared_regs);
- return NOTIFY_BAD;
- }
+ if (!cpuc->excl_cntrs)
+ goto err_constraint_list;
+
cpuc->excl_thread_id = 0;
}
return NOTIFY_OK;
+
+err_constraint_list:
+ kfree(cpuc->constraint_list);
+ cpuc->constraint_list = NULL;
+
+err_shared_regs:
+ kfree(cpuc->shared_regs);
+ cpuc->shared_regs = NULL;
+
+err:
+ return NOTIFY_BAD;
}
static void intel_pmu_cpu_starting(int cpu)
diff --git a/arch/x86/kernel/cpu/perf_event_intel_cqm.c b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
index 1880761..377e8f8 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_cqm.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_cqm.c
@@ -952,6 +952,14 @@
return 0;
/*
+ * Getting up-to-date values requires an SMP IPI which is not
+ * possible if we're being called in interrupt context. Return
+ * the cached values instead.
+ */
+ if (unlikely(in_interrupt()))
+ goto out;
+
+ /*
* Notice that we don't perform the reading of an RMID
* atomically, because we can't hold a spin lock across the
* IPIs.
@@ -1247,7 +1255,7 @@
cpumask_set_cpu(cpu, &cqm_cpumask);
}
-static void intel_cqm_cpu_prepare(unsigned int cpu)
+static void intel_cqm_cpu_starting(unsigned int cpu)
{
struct intel_pqr_state *state = &per_cpu(pqr_state, cpu);
struct cpuinfo_x86 *c = &cpu_data(cpu);
@@ -1288,13 +1296,11 @@
unsigned int cpu = (unsigned long)hcpu;
switch (action & ~CPU_TASKS_FROZEN) {
- case CPU_UP_PREPARE:
- intel_cqm_cpu_prepare(cpu);
- break;
case CPU_DOWN_PREPARE:
intel_cqm_cpu_exit(cpu);
break;
case CPU_STARTING:
+ intel_cqm_cpu_starting(cpu);
cqm_pick_event_reader(cpu);
break;
}
@@ -1365,7 +1371,7 @@
goto out;
for_each_online_cpu(i) {
- intel_cqm_cpu_prepare(i);
+ intel_cqm_cpu_starting(i);
cqm_pick_event_reader(i);
}
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 79de954..d25097c 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -270,7 +270,7 @@
dst_fpu->fpregs_active = 0;
dst_fpu->last_cpu = -1;
- if (src_fpu->fpstate_active)
+ if (src_fpu->fpstate_active && cpu_has_fpu)
fpu_copy(dst_fpu, src_fpu);
return 0;
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index 0b39173..d14e9ac 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -40,7 +40,12 @@
write_cr0(cr0);
/* Flush out any pending x87 state: */
- asm volatile ("fninit");
+#ifdef CONFIG_MATH_EMULATION
+ if (!cpu_has_fpu)
+ fpstate_init_soft(¤t->thread.fpu.state.soft);
+ else
+#endif
+ asm volatile ("fninit");
}
/*
@@ -351,9 +356,15 @@
setup_clear_cpu_cap(X86_FEATURE_XSAVE);
setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
+ setup_clear_cpu_cap(X86_FEATURE_XSAVEC);
setup_clear_cpu_cap(X86_FEATURE_XSAVES);
setup_clear_cpu_cap(X86_FEATURE_AVX);
setup_clear_cpu_cap(X86_FEATURE_AVX2);
+ setup_clear_cpu_cap(X86_FEATURE_AVX512F);
+ setup_clear_cpu_cap(X86_FEATURE_AVX512PF);
+ setup_clear_cpu_cap(X86_FEATURE_AVX512ER);
+ setup_clear_cpu_cap(X86_FEATURE_AVX512CD);
+ setup_clear_cpu_cap(X86_FEATURE_MPX);
return 1;
}
diff --git a/arch/x86/kernel/ldt.c b/arch/x86/kernel/ldt.c
index c37886d..2bcc052 100644
--- a/arch/x86/kernel/ldt.c
+++ b/arch/x86/kernel/ldt.c
@@ -12,6 +12,7 @@
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/smp.h>
+#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/uaccess.h>
@@ -20,82 +21,82 @@
#include <asm/mmu_context.h>
#include <asm/syscalls.h>
-#ifdef CONFIG_SMP
+/* context.lock is held for us, so we don't need any locking. */
static void flush_ldt(void *current_mm)
{
- if (current->active_mm == current_mm)
- load_LDT(¤t->active_mm->context);
+ mm_context_t *pc;
+
+ if (current->active_mm != current_mm)
+ return;
+
+ pc = ¤t->active_mm->context;
+ set_ldt(pc->ldt->entries, pc->ldt->size);
}
-#endif
-static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
+/* The caller must call finalize_ldt_struct on the result. LDT starts zeroed. */
+static struct ldt_struct *alloc_ldt_struct(int size)
{
- void *oldldt, *newldt;
- int oldsize;
+ struct ldt_struct *new_ldt;
+ int alloc_size;
- if (mincount <= pc->size)
- return 0;
- oldsize = pc->size;
- mincount = (mincount + (PAGE_SIZE / LDT_ENTRY_SIZE - 1)) &
- (~(PAGE_SIZE / LDT_ENTRY_SIZE - 1));
- if (mincount * LDT_ENTRY_SIZE > PAGE_SIZE)
- newldt = vmalloc(mincount * LDT_ENTRY_SIZE);
+ if (size > LDT_ENTRIES)
+ return NULL;
+
+ new_ldt = kmalloc(sizeof(struct ldt_struct), GFP_KERNEL);
+ if (!new_ldt)
+ return NULL;
+
+ BUILD_BUG_ON(LDT_ENTRY_SIZE != sizeof(struct desc_struct));
+ alloc_size = size * LDT_ENTRY_SIZE;
+
+ /*
+ * Xen is very picky: it requires a page-aligned LDT that has no
+ * trailing nonzero bytes in any page that contains LDT descriptors.
+ * Keep it simple: zero the whole allocation and never allocate less
+ * than PAGE_SIZE.
+ */
+ if (alloc_size > PAGE_SIZE)
+ new_ldt->entries = vzalloc(alloc_size);
else
- newldt = (void *)__get_free_page(GFP_KERNEL);
+ new_ldt->entries = kzalloc(PAGE_SIZE, GFP_KERNEL);
- if (!newldt)
- return -ENOMEM;
-
- if (oldsize)
- memcpy(newldt, pc->ldt, oldsize * LDT_ENTRY_SIZE);
- oldldt = pc->ldt;
- memset(newldt + oldsize * LDT_ENTRY_SIZE, 0,
- (mincount - oldsize) * LDT_ENTRY_SIZE);
-
- paravirt_alloc_ldt(newldt, mincount);
-
-#ifdef CONFIG_X86_64
- /* CHECKME: Do we really need this ? */
- wmb();
-#endif
- pc->ldt = newldt;
- wmb();
- pc->size = mincount;
- wmb();
-
- if (reload) {
-#ifdef CONFIG_SMP
- preempt_disable();
- load_LDT(pc);
- if (!cpumask_equal(mm_cpumask(current->mm),
- cpumask_of(smp_processor_id())))
- smp_call_function(flush_ldt, current->mm, 1);
- preempt_enable();
-#else
- load_LDT(pc);
-#endif
+ if (!new_ldt->entries) {
+ kfree(new_ldt);
+ return NULL;
}
- if (oldsize) {
- paravirt_free_ldt(oldldt, oldsize);
- if (oldsize * LDT_ENTRY_SIZE > PAGE_SIZE)
- vfree(oldldt);
- else
- put_page(virt_to_page(oldldt));
- }
- return 0;
+
+ new_ldt->size = size;
+ return new_ldt;
}
-static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
+/* After calling this, the LDT is immutable. */
+static void finalize_ldt_struct(struct ldt_struct *ldt)
{
- int err = alloc_ldt(new, old->size, 0);
- int i;
+ paravirt_alloc_ldt(ldt->entries, ldt->size);
+}
- if (err < 0)
- return err;
+/* context.lock is held */
+static void install_ldt(struct mm_struct *current_mm,
+ struct ldt_struct *ldt)
+{
+ /* Synchronizes with lockless_dereference in load_mm_ldt. */
+ smp_store_release(¤t_mm->context.ldt, ldt);
- for (i = 0; i < old->size; i++)
- write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE);
- return 0;
+ /* Activate the LDT for all CPUs using current_mm. */
+ on_each_cpu_mask(mm_cpumask(current_mm), flush_ldt, current_mm, true);
+}
+
+static void free_ldt_struct(struct ldt_struct *ldt)
+{
+ if (likely(!ldt))
+ return;
+
+ paravirt_free_ldt(ldt->entries, ldt->size);
+ if (ldt->size * LDT_ENTRY_SIZE > PAGE_SIZE)
+ vfree(ldt->entries);
+ else
+ kfree(ldt->entries);
+ kfree(ldt);
}
/*
@@ -104,17 +105,37 @@
*/
int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
{
+ struct ldt_struct *new_ldt;
struct mm_struct *old_mm;
int retval = 0;
mutex_init(&mm->context.lock);
- mm->context.size = 0;
old_mm = current->mm;
- if (old_mm && old_mm->context.size > 0) {
- mutex_lock(&old_mm->context.lock);
- retval = copy_ldt(&mm->context, &old_mm->context);
- mutex_unlock(&old_mm->context.lock);
+ if (!old_mm) {
+ mm->context.ldt = NULL;
+ return 0;
}
+
+ mutex_lock(&old_mm->context.lock);
+ if (!old_mm->context.ldt) {
+ mm->context.ldt = NULL;
+ goto out_unlock;
+ }
+
+ new_ldt = alloc_ldt_struct(old_mm->context.ldt->size);
+ if (!new_ldt) {
+ retval = -ENOMEM;
+ goto out_unlock;
+ }
+
+ memcpy(new_ldt->entries, old_mm->context.ldt->entries,
+ new_ldt->size * LDT_ENTRY_SIZE);
+ finalize_ldt_struct(new_ldt);
+
+ mm->context.ldt = new_ldt;
+
+out_unlock:
+ mutex_unlock(&old_mm->context.lock);
return retval;
}
@@ -125,53 +146,47 @@
*/
void destroy_context(struct mm_struct *mm)
{
- if (mm->context.size) {
-#ifdef CONFIG_X86_32
- /* CHECKME: Can this ever happen ? */
- if (mm == current->active_mm)
- clear_LDT();
-#endif
- paravirt_free_ldt(mm->context.ldt, mm->context.size);
- if (mm->context.size * LDT_ENTRY_SIZE > PAGE_SIZE)
- vfree(mm->context.ldt);
- else
- put_page(virt_to_page(mm->context.ldt));
- mm->context.size = 0;
- }
+ free_ldt_struct(mm->context.ldt);
+ mm->context.ldt = NULL;
}
static int read_ldt(void __user *ptr, unsigned long bytecount)
{
- int err;
+ int retval;
unsigned long size;
struct mm_struct *mm = current->mm;
- if (!mm->context.size)
- return 0;
+ mutex_lock(&mm->context.lock);
+
+ if (!mm->context.ldt) {
+ retval = 0;
+ goto out_unlock;
+ }
+
if (bytecount > LDT_ENTRY_SIZE * LDT_ENTRIES)
bytecount = LDT_ENTRY_SIZE * LDT_ENTRIES;
- mutex_lock(&mm->context.lock);
- size = mm->context.size * LDT_ENTRY_SIZE;
+ size = mm->context.ldt->size * LDT_ENTRY_SIZE;
if (size > bytecount)
size = bytecount;
- err = 0;
- if (copy_to_user(ptr, mm->context.ldt, size))
- err = -EFAULT;
- mutex_unlock(&mm->context.lock);
- if (err < 0)
- goto error_return;
+ if (copy_to_user(ptr, mm->context.ldt->entries, size)) {
+ retval = -EFAULT;
+ goto out_unlock;
+ }
+
if (size != bytecount) {
- /* zero-fill the rest */
- if (clear_user(ptr + size, bytecount - size) != 0) {
- err = -EFAULT;
- goto error_return;
+ /* Zero-fill the rest and pretend we read bytecount bytes. */
+ if (clear_user(ptr + size, bytecount - size)) {
+ retval = -EFAULT;
+ goto out_unlock;
}
}
- return bytecount;
-error_return:
- return err;
+ retval = bytecount;
+
+out_unlock:
+ mutex_unlock(&mm->context.lock);
+ return retval;
}
static int read_default_ldt(void __user *ptr, unsigned long bytecount)
@@ -195,6 +210,8 @@
struct desc_struct ldt;
int error;
struct user_desc ldt_info;
+ int oldsize, newsize;
+ struct ldt_struct *new_ldt, *old_ldt;
error = -EINVAL;
if (bytecount != sizeof(ldt_info))
@@ -213,34 +230,39 @@
goto out;
}
- mutex_lock(&mm->context.lock);
- if (ldt_info.entry_number >= mm->context.size) {
- error = alloc_ldt(¤t->mm->context,
- ldt_info.entry_number + 1, 1);
- if (error < 0)
- goto out_unlock;
- }
-
- /* Allow LDTs to be cleared by the user. */
- if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
- if (oldmode || LDT_empty(&ldt_info)) {
- memset(&ldt, 0, sizeof(ldt));
- goto install;
+ if ((oldmode && !ldt_info.base_addr && !ldt_info.limit) ||
+ LDT_empty(&ldt_info)) {
+ /* The user wants to clear the entry. */
+ memset(&ldt, 0, sizeof(ldt));
+ } else {
+ if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
+ error = -EINVAL;
+ goto out;
}
+
+ fill_ldt(&ldt, &ldt_info);
+ if (oldmode)
+ ldt.avl = 0;
}
- if (!IS_ENABLED(CONFIG_X86_16BIT) && !ldt_info.seg_32bit) {
- error = -EINVAL;
+ mutex_lock(&mm->context.lock);
+
+ old_ldt = mm->context.ldt;
+ oldsize = old_ldt ? old_ldt->size : 0;
+ newsize = max((int)(ldt_info.entry_number + 1), oldsize);
+
+ error = -ENOMEM;
+ new_ldt = alloc_ldt_struct(newsize);
+ if (!new_ldt)
goto out_unlock;
- }
- fill_ldt(&ldt, &ldt_info);
- if (oldmode)
- ldt.avl = 0;
+ if (old_ldt)
+ memcpy(new_ldt->entries, old_ldt->entries, oldsize * LDT_ENTRY_SIZE);
+ new_ldt->entries[ldt_info.entry_number] = ldt;
+ finalize_ldt_struct(new_ldt);
- /* Install the new entry ... */
-install:
- write_ldt_entry(mm->context.ldt, ldt_info.entry_number, &ldt);
+ install_ldt(mm, new_ldt);
+ free_ldt_struct(old_ldt);
error = 0;
out_unlock:
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 397688b..c27cad7 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -408,6 +408,7 @@
static void mwait_idle(void)
{
if (!current_set_polling_and_test()) {
+ trace_cpu_idle_rcuidle(1, smp_processor_id());
if (this_cpu_has(X86_BUG_CLFLUSH_MONITOR)) {
smp_mb(); /* quirk */
clflush((void *)¤t_thread_info()->flags);
@@ -419,6 +420,7 @@
__sti_mwait(0, 0);
else
local_irq_enable();
+ trace_cpu_idle_rcuidle(PWR_EVENT_EXIT, smp_processor_id());
} else {
local_irq_enable();
}
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 71d7849..f6b9163 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -121,11 +121,11 @@
void release_thread(struct task_struct *dead_task)
{
if (dead_task->mm) {
- if (dead_task->mm->context.size) {
+ if (dead_task->mm->context.ldt) {
pr_warn("WARNING: dead process %s still has LDT? <%p/%d>\n",
dead_task->comm,
dead_task->mm->context.ldt,
- dead_task->mm->context.size);
+ dead_task->mm->context.ldt->size);
BUG();
}
}
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 206996c..71820c4 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -93,8 +93,15 @@
COPY(r15);
#endif /* CONFIG_X86_64 */
+#ifdef CONFIG_X86_32
COPY_SEG_CPL3(cs);
COPY_SEG_CPL3(ss);
+#else /* !CONFIG_X86_32 */
+ /* Kernel saves and restores only the CS segment register on signals,
+ * which is the bare minimum needed to allow mixed 32/64-bit code.
+ * App's signal handler can save/restore other segments if needed. */
+ COPY_SEG_CPL3(cs);
+#endif /* CONFIG_X86_32 */
get_user_ex(tmpflags, &sc->flags);
regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
@@ -154,9 +161,8 @@
#else /* !CONFIG_X86_32 */
put_user_ex(regs->flags, &sc->flags);
put_user_ex(regs->cs, &sc->cs);
- put_user_ex(0, &sc->__pad2);
- put_user_ex(0, &sc->__pad1);
- put_user_ex(regs->ss, &sc->ss);
+ put_user_ex(0, &sc->gs);
+ put_user_ex(0, &sc->fs);
#endif /* CONFIG_X86_32 */
put_user_ex(fpstate, &sc->fpstate);
@@ -451,19 +457,9 @@
regs->sp = (unsigned long)frame;
- /*
- * Set up the CS and SS registers to run signal handlers in
- * 64-bit mode, even if the handler happens to be interrupting
- * 32-bit or 16-bit code.
- *
- * SS is subtle. In 64-bit mode, we don't need any particular
- * SS descriptor, but we do need SS to be valid. It's possible
- * that the old SS is entirely bogus -- this can happen if the
- * signal we're trying to deliver is #GP or #SS caused by a bad
- * SS value.
- */
+ /* Set up the CS register to run signal handlers in 64-bit mode,
+ even if the handler happens to be interrupting 32-bit code. */
regs->cs = __USER_CS;
- regs->ss = __USER_DS;
return 0;
}
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index 9b4d51d..0ccb53a 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -5,6 +5,7 @@
#include <linux/mm.h>
#include <linux/ptrace.h>
#include <asm/desc.h>
+#include <asm/mmu_context.h>
unsigned long convert_ip_to_linear(struct task_struct *child, struct pt_regs *regs)
{
@@ -27,13 +28,14 @@
struct desc_struct *desc;
unsigned long base;
- seg &= ~7UL;
+ seg >>= 3;
mutex_lock(&child->mm->context.lock);
- if (unlikely((seg >> 3) >= child->mm->context.size))
+ if (unlikely(!child->mm->context.ldt ||
+ seg >= child->mm->context.ldt->size))
addr = -1L; /* bogus selector, access would fault */
else {
- desc = child->mm->context.ldt + seg;
+ desc = &child->mm->context.ldt->entries[seg];
base = get_desc_base(desc);
/* 16-bit code segment? */
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index 67d215c..a1ff508 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -12,7 +12,9 @@
kvm-$(CONFIG_KVM_ASYNC_PF) += $(KVM)/async_pf.o
kvm-y += x86.o mmu.o emulate.o i8259.o irq.o lapic.o \
- i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o
+ i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
+ hyperv.o
+
kvm-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += assigned-dev.o iommu.o
kvm-intel-y += vmx.o pmu_intel.o
kvm-amd-y += svm.o pmu_amd.o
diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c
new file mode 100644
index 0000000..a8160d2
--- /dev/null
+++ b/arch/x86/kvm/hyperv.c
@@ -0,0 +1,377 @@
+/*
+ * KVM Microsoft Hyper-V emulation
+ *
+ * derived from arch/x86/kvm/x86.c
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ * Copyright (C) 2008 Qumranet, Inc.
+ * Copyright IBM Corporation, 2008
+ * Copyright 2010 Red Hat, Inc. and/or its affiliates.
+ * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * Authors:
+ * Avi Kivity <avi@qumranet.com>
+ * Yaniv Kamay <yaniv@qumranet.com>
+ * Amit Shah <amit.shah@qumranet.com>
+ * Ben-Ami Yassour <benami@il.ibm.com>
+ * Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "x86.h"
+#include "lapic.h"
+#include "hyperv.h"
+
+#include <linux/kvm_host.h>
+#include <trace/events/kvm.h>
+
+#include "trace.h"
+
+static bool kvm_hv_msr_partition_wide(u32 msr)
+{
+ bool r = false;
+
+ switch (msr) {
+ case HV_X64_MSR_GUEST_OS_ID:
+ case HV_X64_MSR_HYPERCALL:
+ case HV_X64_MSR_REFERENCE_TSC:
+ case HV_X64_MSR_TIME_REF_COUNT:
+ case HV_X64_MSR_CRASH_CTL:
+ case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+ r = true;
+ break;
+ }
+
+ return r;
+}
+
+static int kvm_hv_msr_get_crash_data(struct kvm_vcpu *vcpu,
+ u32 index, u64 *pdata)
+{
+ struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+
+ if (WARN_ON_ONCE(index >= ARRAY_SIZE(hv->hv_crash_param)))
+ return -EINVAL;
+
+ *pdata = hv->hv_crash_param[index];
+ return 0;
+}
+
+static int kvm_hv_msr_get_crash_ctl(struct kvm_vcpu *vcpu, u64 *pdata)
+{
+ struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+
+ *pdata = hv->hv_crash_ctl;
+ return 0;
+}
+
+static int kvm_hv_msr_set_crash_ctl(struct kvm_vcpu *vcpu, u64 data, bool host)
+{
+ struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+
+ if (host)
+ hv->hv_crash_ctl = data & HV_X64_MSR_CRASH_CTL_NOTIFY;
+
+ if (!host && (data & HV_X64_MSR_CRASH_CTL_NOTIFY)) {
+
+ vcpu_debug(vcpu, "hv crash (0x%llx 0x%llx 0x%llx 0x%llx 0x%llx)\n",
+ hv->hv_crash_param[0],
+ hv->hv_crash_param[1],
+ hv->hv_crash_param[2],
+ hv->hv_crash_param[3],
+ hv->hv_crash_param[4]);
+
+ /* Send notification about crash to user space */
+ kvm_make_request(KVM_REQ_HV_CRASH, vcpu);
+ }
+
+ return 0;
+}
+
+static int kvm_hv_msr_set_crash_data(struct kvm_vcpu *vcpu,
+ u32 index, u64 data)
+{
+ struct kvm_hv *hv = &vcpu->kvm->arch.hyperv;
+
+ if (WARN_ON_ONCE(index >= ARRAY_SIZE(hv->hv_crash_param)))
+ return -EINVAL;
+
+ hv->hv_crash_param[index] = data;
+ return 0;
+}
+
+static int kvm_hv_set_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data,
+ bool host)
+{
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_hv *hv = &kvm->arch.hyperv;
+
+ switch (msr) {
+ case HV_X64_MSR_GUEST_OS_ID:
+ hv->hv_guest_os_id = data;
+ /* setting guest os id to zero disables hypercall page */
+ if (!hv->hv_guest_os_id)
+ hv->hv_hypercall &= ~HV_X64_MSR_HYPERCALL_ENABLE;
+ break;
+ case HV_X64_MSR_HYPERCALL: {
+ u64 gfn;
+ unsigned long addr;
+ u8 instructions[4];
+
+ /* if guest os id is not set hypercall should remain disabled */
+ if (!hv->hv_guest_os_id)
+ break;
+ if (!(data & HV_X64_MSR_HYPERCALL_ENABLE)) {
+ hv->hv_hypercall = data;
+ break;
+ }
+ gfn = data >> HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT;
+ addr = gfn_to_hva(kvm, gfn);
+ if (kvm_is_error_hva(addr))
+ return 1;
+ kvm_x86_ops->patch_hypercall(vcpu, instructions);
+ ((unsigned char *)instructions)[3] = 0xc3; /* ret */
+ if (__copy_to_user((void __user *)addr, instructions, 4))
+ return 1;
+ hv->hv_hypercall = data;
+ mark_page_dirty(kvm, gfn);
+ break;
+ }
+ case HV_X64_MSR_REFERENCE_TSC: {
+ u64 gfn;
+ HV_REFERENCE_TSC_PAGE tsc_ref;
+
+ memset(&tsc_ref, 0, sizeof(tsc_ref));
+ hv->hv_tsc_page = data;
+ if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
+ break;
+ gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
+ if (kvm_write_guest(
+ kvm,
+ gfn << HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT,
+ &tsc_ref, sizeof(tsc_ref)))
+ return 1;
+ mark_page_dirty(kvm, gfn);
+ break;
+ }
+ case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+ return kvm_hv_msr_set_crash_data(vcpu,
+ msr - HV_X64_MSR_CRASH_P0,
+ data);
+ case HV_X64_MSR_CRASH_CTL:
+ return kvm_hv_msr_set_crash_ctl(vcpu, data, host);
+ default:
+ vcpu_unimpl(vcpu, "Hyper-V uhandled wrmsr: 0x%x data 0x%llx\n",
+ msr, data);
+ return 1;
+ }
+ return 0;
+}
+
+static int kvm_hv_set_msr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
+{
+ struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv;
+
+ switch (msr) {
+ case HV_X64_MSR_APIC_ASSIST_PAGE: {
+ u64 gfn;
+ unsigned long addr;
+
+ if (!(data & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE)) {
+ hv->hv_vapic = data;
+ if (kvm_lapic_enable_pv_eoi(vcpu, 0))
+ return 1;
+ break;
+ }
+ gfn = data >> HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT;
+ addr = kvm_vcpu_gfn_to_hva(vcpu, gfn);
+ if (kvm_is_error_hva(addr))
+ return 1;
+ if (__clear_user((void __user *)addr, PAGE_SIZE))
+ return 1;
+ hv->hv_vapic = data;
+ kvm_vcpu_mark_page_dirty(vcpu, gfn);
+ if (kvm_lapic_enable_pv_eoi(vcpu,
+ gfn_to_gpa(gfn) | KVM_MSR_ENABLED))
+ return 1;
+ break;
+ }
+ case HV_X64_MSR_EOI:
+ return kvm_hv_vapic_msr_write(vcpu, APIC_EOI, data);
+ case HV_X64_MSR_ICR:
+ return kvm_hv_vapic_msr_write(vcpu, APIC_ICR, data);
+ case HV_X64_MSR_TPR:
+ return kvm_hv_vapic_msr_write(vcpu, APIC_TASKPRI, data);
+ default:
+ vcpu_unimpl(vcpu, "Hyper-V uhandled wrmsr: 0x%x data 0x%llx\n",
+ msr, data);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int kvm_hv_get_msr_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+ u64 data = 0;
+ struct kvm *kvm = vcpu->kvm;
+ struct kvm_hv *hv = &kvm->arch.hyperv;
+
+ switch (msr) {
+ case HV_X64_MSR_GUEST_OS_ID:
+ data = hv->hv_guest_os_id;
+ break;
+ case HV_X64_MSR_HYPERCALL:
+ data = hv->hv_hypercall;
+ break;
+ case HV_X64_MSR_TIME_REF_COUNT: {
+ data =
+ div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100);
+ break;
+ }
+ case HV_X64_MSR_REFERENCE_TSC:
+ data = hv->hv_tsc_page;
+ break;
+ case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+ return kvm_hv_msr_get_crash_data(vcpu,
+ msr - HV_X64_MSR_CRASH_P0,
+ pdata);
+ case HV_X64_MSR_CRASH_CTL:
+ return kvm_hv_msr_get_crash_ctl(vcpu, pdata);
+ default:
+ vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
+ return 1;
+ }
+
+ *pdata = data;
+ return 0;
+}
+
+static int kvm_hv_get_msr(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+ u64 data = 0;
+ struct kvm_vcpu_hv *hv = &vcpu->arch.hyperv;
+
+ switch (msr) {
+ case HV_X64_MSR_VP_INDEX: {
+ int r;
+ struct kvm_vcpu *v;
+
+ kvm_for_each_vcpu(r, v, vcpu->kvm) {
+ if (v == vcpu) {
+ data = r;
+ break;
+ }
+ }
+ break;
+ }
+ case HV_X64_MSR_EOI:
+ return kvm_hv_vapic_msr_read(vcpu, APIC_EOI, pdata);
+ case HV_X64_MSR_ICR:
+ return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata);
+ case HV_X64_MSR_TPR:
+ return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata);
+ case HV_X64_MSR_APIC_ASSIST_PAGE:
+ data = hv->hv_vapic;
+ break;
+ default:
+ vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
+ return 1;
+ }
+ *pdata = data;
+ return 0;
+}
+
+int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host)
+{
+ if (kvm_hv_msr_partition_wide(msr)) {
+ int r;
+
+ mutex_lock(&vcpu->kvm->lock);
+ r = kvm_hv_set_msr_pw(vcpu, msr, data, host);
+ mutex_unlock(&vcpu->kvm->lock);
+ return r;
+ } else
+ return kvm_hv_set_msr(vcpu, msr, data);
+}
+
+int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
+{
+ if (kvm_hv_msr_partition_wide(msr)) {
+ int r;
+
+ mutex_lock(&vcpu->kvm->lock);
+ r = kvm_hv_get_msr_pw(vcpu, msr, pdata);
+ mutex_unlock(&vcpu->kvm->lock);
+ return r;
+ } else
+ return kvm_hv_get_msr(vcpu, msr, pdata);
+}
+
+bool kvm_hv_hypercall_enabled(struct kvm *kvm)
+{
+ return kvm->arch.hyperv.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE;
+}
+
+int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
+{
+ u64 param, ingpa, outgpa, ret;
+ uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0;
+ bool fast, longmode;
+
+ /*
+ * hypercall generates UD from non zero cpl and real mode
+ * per HYPER-V spec
+ */
+ if (kvm_x86_ops->get_cpl(vcpu) != 0 || !is_protmode(vcpu)) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 0;
+ }
+
+ longmode = is_64_bit_mode(vcpu);
+
+ if (!longmode) {
+ param = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDX) << 32) |
+ (kvm_register_read(vcpu, VCPU_REGS_RAX) & 0xffffffff);
+ ingpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RBX) << 32) |
+ (kvm_register_read(vcpu, VCPU_REGS_RCX) & 0xffffffff);
+ outgpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDI) << 32) |
+ (kvm_register_read(vcpu, VCPU_REGS_RSI) & 0xffffffff);
+ }
+#ifdef CONFIG_X86_64
+ else {
+ param = kvm_register_read(vcpu, VCPU_REGS_RCX);
+ ingpa = kvm_register_read(vcpu, VCPU_REGS_RDX);
+ outgpa = kvm_register_read(vcpu, VCPU_REGS_R8);
+ }
+#endif
+
+ code = param & 0xffff;
+ fast = (param >> 16) & 0x1;
+ rep_cnt = (param >> 32) & 0xfff;
+ rep_idx = (param >> 48) & 0xfff;
+
+ trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa);
+
+ switch (code) {
+ case HV_X64_HV_NOTIFY_LONG_SPIN_WAIT:
+ kvm_vcpu_on_spin(vcpu);
+ break;
+ default:
+ res = HV_STATUS_INVALID_HYPERCALL_CODE;
+ break;
+ }
+
+ ret = res | (((u64)rep_done & 0xfff) << 32);
+ if (longmode) {
+ kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
+ } else {
+ kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32);
+ kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0xffffffff);
+ }
+
+ return 1;
+}
diff --git a/arch/x86/kvm/hyperv.h b/arch/x86/kvm/hyperv.h
new file mode 100644
index 0000000..c7bce55
--- /dev/null
+++ b/arch/x86/kvm/hyperv.h
@@ -0,0 +1,32 @@
+/*
+ * KVM Microsoft Hyper-V emulation
+ *
+ * derived from arch/x86/kvm/x86.c
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ * Copyright (C) 2008 Qumranet, Inc.
+ * Copyright IBM Corporation, 2008
+ * Copyright 2010 Red Hat, Inc. and/or its affiliates.
+ * Copyright (C) 2015 Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * Authors:
+ * Avi Kivity <avi@qumranet.com>
+ * Yaniv Kamay <yaniv@qumranet.com>
+ * Amit Shah <amit.shah@qumranet.com>
+ * Ben-Ami Yassour <benami@il.ibm.com>
+ * Andrey Smetanin <asmetanin@virtuozzo.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef __ARCH_X86_KVM_HYPERV_H__
+#define __ARCH_X86_KVM_HYPERV_H__
+
+int kvm_hv_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data, bool host);
+int kvm_hv_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata);
+bool kvm_hv_hypercall_enabled(struct kvm *kvm);
+int kvm_hv_hypercall(struct kvm_vcpu *vcpu);
+
+#endif
diff --git a/arch/x86/kvm/i8259.c b/arch/x86/kvm/i8259.c
index fef922f..7cc2360 100644
--- a/arch/x86/kvm/i8259.c
+++ b/arch/x86/kvm/i8259.c
@@ -651,15 +651,10 @@
return NULL;
}
-void kvm_destroy_pic(struct kvm *kvm)
+void kvm_destroy_pic(struct kvm_pic *vpic)
{
- struct kvm_pic *vpic = kvm->arch.vpic;
-
- if (vpic) {
- kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_master);
- kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_slave);
- kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS, &vpic->dev_eclr);
- kvm->arch.vpic = NULL;
- kfree(vpic);
- }
+ kvm_io_bus_unregister_dev(vpic->kvm, KVM_PIO_BUS, &vpic->dev_master);
+ kvm_io_bus_unregister_dev(vpic->kvm, KVM_PIO_BUS, &vpic->dev_slave);
+ kvm_io_bus_unregister_dev(vpic->kvm, KVM_PIO_BUS, &vpic->dev_eclr);
+ kfree(vpic);
}
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index ad68c73..3d782a2 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -74,7 +74,7 @@
};
struct kvm_pic *kvm_create_pic(struct kvm *kvm);
-void kvm_destroy_pic(struct kvm *kvm);
+void kvm_destroy_pic(struct kvm_pic *vpic);
int kvm_pic_read_irq(struct kvm *kvm);
void kvm_pic_update_irq(struct kvm_pic *s);
@@ -85,11 +85,11 @@
static inline int irqchip_in_kernel(struct kvm *kvm)
{
- int ret;
+ struct kvm_pic *vpic = pic_irqchip(kvm);
- ret = (pic_irqchip(kvm) != NULL);
+ /* Read vpic before kvm->irq_routing. */
smp_rmb();
- return ret;
+ return vpic != NULL;
}
void kvm_pic_reset(struct kvm_kpic_state *s);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 954e98a..9a3e342 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1595,7 +1595,7 @@
for (i = 0; i < APIC_LVT_NUM; i++)
apic_set_reg(apic, APIC_LVTT + 0x10 * i, APIC_LVT_MASKED);
apic_update_lvtt(apic);
- if (!(vcpu->kvm->arch.disabled_quirks & KVM_QUIRK_LINT0_REENABLED))
+ if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_LINT0_REENABLED))
apic_set_reg(apic, APIC_LVT0,
SET_APIC_DELIVERY_MODE(0, APIC_MODE_EXTINT));
apic_manage_nmi_watchdog(apic, kvm_apic_get_reg(apic, APIC_LVT0));
@@ -1900,8 +1900,9 @@
if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention))
return;
- kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
- sizeof(u32));
+ if (kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data,
+ sizeof(u32)))
+ return;
apic_set_tpr(vcpu->arch.apic, data & 0xff);
}
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 7195274..7640379 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -91,7 +91,7 @@
static inline bool kvm_hv_vapic_assist_page_enabled(struct kvm_vcpu *vcpu)
{
- return vcpu->arch.hv_vapic & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE;
+ return vcpu->arch.hyperv.hv_vapic & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE;
}
int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data);
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 4417146..fb16a8e 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -357,12 +357,6 @@
{
return ACCESS_ONCE(*sptep);
}
-
-static bool __check_direct_spte_mmio_pf(u64 spte)
-{
- /* It is valid if the spte is zapped. */
- return spte == 0ull;
-}
#else
union split_spte {
struct {
@@ -478,23 +472,6 @@
return spte.spte;
}
-
-static bool __check_direct_spte_mmio_pf(u64 spte)
-{
- union split_spte sspte = (union split_spte)spte;
- u32 high_mmio_mask = shadow_mmio_mask >> 32;
-
- /* It is valid if the spte is zapped. */
- if (spte == 0ull)
- return true;
-
- /* It is valid if the spte is being zapped. */
- if (sspte.spte_low == 0ull &&
- (sspte.spte_high & high_mmio_mask) == high_mmio_mask)
- return true;
-
- return false;
-}
#endif
static bool spte_is_locklessly_modifiable(u64 spte)
@@ -3291,6 +3268,25 @@
return vcpu->arch.nested_mmu.translate_gpa(vcpu, vaddr, access, exception);
}
+static bool
+__is_rsvd_bits_set(struct rsvd_bits_validate *rsvd_check, u64 pte, int level)
+{
+ int bit7 = (pte >> 7) & 1, low6 = pte & 0x3f;
+
+ return (pte & rsvd_check->rsvd_bits_mask[bit7][level-1]) |
+ ((rsvd_check->bad_mt_xwr & (1ull << low6)) != 0);
+}
+
+static bool is_rsvd_bits_set(struct kvm_mmu *mmu, u64 gpte, int level)
+{
+ return __is_rsvd_bits_set(&mmu->guest_rsvd_check, gpte, level);
+}
+
+static bool is_shadow_zero_bits_set(struct kvm_mmu *mmu, u64 spte, int level)
+{
+ return __is_rsvd_bits_set(&mmu->shadow_zero_check, spte, level);
+}
+
static bool quickly_check_mmio_pf(struct kvm_vcpu *vcpu, u64 addr, bool direct)
{
if (direct)
@@ -3299,46 +3295,62 @@
return vcpu_match_mmio_gva(vcpu, addr);
}
-
-/*
- * On direct hosts, the last spte is only allows two states
- * for mmio page fault:
- * - It is the mmio spte
- * - It is zapped or it is being zapped.
- *
- * This function completely checks the spte when the last spte
- * is not the mmio spte.
- */
-static bool check_direct_spte_mmio_pf(u64 spte)
-{
- return __check_direct_spte_mmio_pf(spte);
-}
-
-static u64 walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr)
+/* return true if reserved bit is detected on spte. */
+static bool
+walk_shadow_page_get_mmio_spte(struct kvm_vcpu *vcpu, u64 addr, u64 *sptep)
{
struct kvm_shadow_walk_iterator iterator;
- u64 spte = 0ull;
+ u64 sptes[PT64_ROOT_LEVEL], spte = 0ull;
+ int root, leaf;
+ bool reserved = false;
if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
- return spte;
+ goto exit;
walk_shadow_page_lockless_begin(vcpu);
- for_each_shadow_entry_lockless(vcpu, addr, iterator, spte)
+
+ for (shadow_walk_init(&iterator, vcpu, addr), root = iterator.level;
+ shadow_walk_okay(&iterator);
+ __shadow_walk_next(&iterator, spte)) {
+ leaf = iterator.level;
+ spte = mmu_spte_get_lockless(iterator.sptep);
+
+ sptes[leaf - 1] = spte;
+
if (!is_shadow_present_pte(spte))
break;
+
+ reserved |= is_shadow_zero_bits_set(&vcpu->arch.mmu, spte,
+ leaf);
+ }
+
walk_shadow_page_lockless_end(vcpu);
- return spte;
+ if (reserved) {
+ pr_err("%s: detect reserved bits on spte, addr 0x%llx, dump hierarchy:\n",
+ __func__, addr);
+ while (root >= leaf) {
+ pr_err("------ spte 0x%llx level %d.\n",
+ sptes[root - 1], root);
+ root--;
+ }
+ }
+exit:
+ *sptep = spte;
+ return reserved;
}
int handle_mmio_page_fault_common(struct kvm_vcpu *vcpu, u64 addr, bool direct)
{
u64 spte;
+ bool reserved;
if (quickly_check_mmio_pf(vcpu, addr, direct))
return RET_MMIO_PF_EMULATE;
- spte = walk_shadow_page_get_mmio_spte(vcpu, addr);
+ reserved = walk_shadow_page_get_mmio_spte(vcpu, addr, &spte);
+ if (unlikely(reserved))
+ return RET_MMIO_PF_BUG;
if (is_mmio_spte(spte)) {
gfn_t gfn = get_mmio_spte_gfn(spte);
@@ -3356,13 +3368,6 @@
}
/*
- * It's ok if the gva is remapped by other cpus on shadow guest,
- * it's a BUG if the gfn is not a mmio page.
- */
- if (direct && !check_direct_spte_mmio_pf(spte))
- return RET_MMIO_PF_BUG;
-
- /*
* If the page table is zapped by other cpus, let CPU fault again on
* the address.
*/
@@ -3604,19 +3609,21 @@
#include "paging_tmpl.h"
#undef PTTYPE
-static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
- struct kvm_mmu *context)
+static void
+__reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
+ struct rsvd_bits_validate *rsvd_check,
+ int maxphyaddr, int level, bool nx, bool gbpages,
+ bool pse)
{
- int maxphyaddr = cpuid_maxphyaddr(vcpu);
u64 exb_bit_rsvd = 0;
u64 gbpages_bit_rsvd = 0;
u64 nonleaf_bit8_rsvd = 0;
- context->bad_mt_xwr = 0;
+ rsvd_check->bad_mt_xwr = 0;
- if (!context->nx)
+ if (!nx)
exb_bit_rsvd = rsvd_bits(63, 63);
- if (!guest_cpuid_has_gbpages(vcpu))
+ if (!gbpages)
gbpages_bit_rsvd = rsvd_bits(7, 7);
/*
@@ -3626,80 +3633,95 @@
if (guest_cpuid_is_amd(vcpu))
nonleaf_bit8_rsvd = rsvd_bits(8, 8);
- switch (context->root_level) {
+ switch (level) {
case PT32_ROOT_LEVEL:
/* no rsvd bits for 2 level 4K page table entries */
- context->rsvd_bits_mask[0][1] = 0;
- context->rsvd_bits_mask[0][0] = 0;
- context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[0][0];
+ rsvd_check->rsvd_bits_mask[0][1] = 0;
+ rsvd_check->rsvd_bits_mask[0][0] = 0;
+ rsvd_check->rsvd_bits_mask[1][0] =
+ rsvd_check->rsvd_bits_mask[0][0];
- if (!is_pse(vcpu)) {
- context->rsvd_bits_mask[1][1] = 0;
+ if (!pse) {
+ rsvd_check->rsvd_bits_mask[1][1] = 0;
break;
}
if (is_cpuid_PSE36())
/* 36bits PSE 4MB page */
- context->rsvd_bits_mask[1][1] = rsvd_bits(17, 21);
+ rsvd_check->rsvd_bits_mask[1][1] = rsvd_bits(17, 21);
else
/* 32 bits PSE 4MB page */
- context->rsvd_bits_mask[1][1] = rsvd_bits(13, 21);
+ rsvd_check->rsvd_bits_mask[1][1] = rsvd_bits(13, 21);
break;
case PT32E_ROOT_LEVEL:
- context->rsvd_bits_mask[0][2] =
+ rsvd_check->rsvd_bits_mask[0][2] =
rsvd_bits(maxphyaddr, 63) |
rsvd_bits(5, 8) | rsvd_bits(1, 2); /* PDPTE */
- context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
+ rsvd_check->rsvd_bits_mask[0][1] = exb_bit_rsvd |
rsvd_bits(maxphyaddr, 62); /* PDE */
- context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+ rsvd_check->rsvd_bits_mask[0][0] = exb_bit_rsvd |
rsvd_bits(maxphyaddr, 62); /* PTE */
- context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
+ rsvd_check->rsvd_bits_mask[1][1] = exb_bit_rsvd |
rsvd_bits(maxphyaddr, 62) |
rsvd_bits(13, 20); /* large page */
- context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[0][0];
+ rsvd_check->rsvd_bits_mask[1][0] =
+ rsvd_check->rsvd_bits_mask[0][0];
break;
case PT64_ROOT_LEVEL:
- context->rsvd_bits_mask[0][3] = exb_bit_rsvd |
- nonleaf_bit8_rsvd | rsvd_bits(7, 7) | rsvd_bits(maxphyaddr, 51);
- context->rsvd_bits_mask[0][2] = exb_bit_rsvd |
- nonleaf_bit8_rsvd | gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51);
- context->rsvd_bits_mask[0][1] = exb_bit_rsvd |
+ rsvd_check->rsvd_bits_mask[0][3] = exb_bit_rsvd |
+ nonleaf_bit8_rsvd | rsvd_bits(7, 7) |
rsvd_bits(maxphyaddr, 51);
- context->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+ rsvd_check->rsvd_bits_mask[0][2] = exb_bit_rsvd |
+ nonleaf_bit8_rsvd | gbpages_bit_rsvd |
rsvd_bits(maxphyaddr, 51);
- context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
- context->rsvd_bits_mask[1][2] = exb_bit_rsvd |
+ rsvd_check->rsvd_bits_mask[0][1] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 51);
+ rsvd_check->rsvd_bits_mask[0][0] = exb_bit_rsvd |
+ rsvd_bits(maxphyaddr, 51);
+ rsvd_check->rsvd_bits_mask[1][3] =
+ rsvd_check->rsvd_bits_mask[0][3];
+ rsvd_check->rsvd_bits_mask[1][2] = exb_bit_rsvd |
gbpages_bit_rsvd | rsvd_bits(maxphyaddr, 51) |
rsvd_bits(13, 29);
- context->rsvd_bits_mask[1][1] = exb_bit_rsvd |
+ rsvd_check->rsvd_bits_mask[1][1] = exb_bit_rsvd |
rsvd_bits(maxphyaddr, 51) |
rsvd_bits(13, 20); /* large page */
- context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[0][0];
+ rsvd_check->rsvd_bits_mask[1][0] =
+ rsvd_check->rsvd_bits_mask[0][0];
break;
}
}
-static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
- struct kvm_mmu *context, bool execonly)
+static void reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
+ struct kvm_mmu *context)
{
- int maxphyaddr = cpuid_maxphyaddr(vcpu);
+ __reset_rsvds_bits_mask(vcpu, &context->guest_rsvd_check,
+ cpuid_maxphyaddr(vcpu), context->root_level,
+ context->nx, guest_cpuid_has_gbpages(vcpu),
+ is_pse(vcpu));
+}
+
+static void
+__reset_rsvds_bits_mask_ept(struct rsvd_bits_validate *rsvd_check,
+ int maxphyaddr, bool execonly)
+{
int pte;
- context->rsvd_bits_mask[0][3] =
+ rsvd_check->rsvd_bits_mask[0][3] =
rsvd_bits(maxphyaddr, 51) | rsvd_bits(3, 7);
- context->rsvd_bits_mask[0][2] =
+ rsvd_check->rsvd_bits_mask[0][2] =
rsvd_bits(maxphyaddr, 51) | rsvd_bits(3, 6);
- context->rsvd_bits_mask[0][1] =
+ rsvd_check->rsvd_bits_mask[0][1] =
rsvd_bits(maxphyaddr, 51) | rsvd_bits(3, 6);
- context->rsvd_bits_mask[0][0] = rsvd_bits(maxphyaddr, 51);
+ rsvd_check->rsvd_bits_mask[0][0] = rsvd_bits(maxphyaddr, 51);
/* large page */
- context->rsvd_bits_mask[1][3] = context->rsvd_bits_mask[0][3];
- context->rsvd_bits_mask[1][2] =
+ rsvd_check->rsvd_bits_mask[1][3] = rsvd_check->rsvd_bits_mask[0][3];
+ rsvd_check->rsvd_bits_mask[1][2] =
rsvd_bits(maxphyaddr, 51) | rsvd_bits(12, 29);
- context->rsvd_bits_mask[1][1] =
+ rsvd_check->rsvd_bits_mask[1][1] =
rsvd_bits(maxphyaddr, 51) | rsvd_bits(12, 20);
- context->rsvd_bits_mask[1][0] = context->rsvd_bits_mask[0][0];
+ rsvd_check->rsvd_bits_mask[1][0] = rsvd_check->rsvd_bits_mask[0][0];
for (pte = 0; pte < 64; pte++) {
int rwx_bits = pte & 7;
@@ -3707,10 +3729,64 @@
if (mt == 0x2 || mt == 0x3 || mt == 0x7 ||
rwx_bits == 0x2 || rwx_bits == 0x6 ||
(rwx_bits == 0x4 && !execonly))
- context->bad_mt_xwr |= (1ull << pte);
+ rsvd_check->bad_mt_xwr |= (1ull << pte);
}
}
+static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu,
+ struct kvm_mmu *context, bool execonly)
+{
+ __reset_rsvds_bits_mask_ept(&context->guest_rsvd_check,
+ cpuid_maxphyaddr(vcpu), execonly);
+}
+
+/*
+ * the page table on host is the shadow page table for the page
+ * table in guest or amd nested guest, its mmu features completely
+ * follow the features in guest.
+ */
+void
+reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context)
+{
+ __reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
+ boot_cpu_data.x86_phys_bits,
+ context->shadow_root_level, context->nx,
+ guest_cpuid_has_gbpages(vcpu), is_pse(vcpu));
+}
+EXPORT_SYMBOL_GPL(reset_shadow_zero_bits_mask);
+
+/*
+ * the direct page table on host, use as much mmu features as
+ * possible, however, kvm currently does not do execution-protection.
+ */
+static void
+reset_tdp_shadow_zero_bits_mask(struct kvm_vcpu *vcpu,
+ struct kvm_mmu *context)
+{
+ if (guest_cpuid_is_amd(vcpu))
+ __reset_rsvds_bits_mask(vcpu, &context->shadow_zero_check,
+ boot_cpu_data.x86_phys_bits,
+ context->shadow_root_level, false,
+ cpu_has_gbpages, true);
+ else
+ __reset_rsvds_bits_mask_ept(&context->shadow_zero_check,
+ boot_cpu_data.x86_phys_bits,
+ false);
+
+}
+
+/*
+ * as the comments in reset_shadow_zero_bits_mask() except it
+ * is the shadow page table for intel nested guest.
+ */
+static void
+reset_ept_shadow_zero_bits_mask(struct kvm_vcpu *vcpu,
+ struct kvm_mmu *context, bool execonly)
+{
+ __reset_rsvds_bits_mask_ept(&context->shadow_zero_check,
+ boot_cpu_data.x86_phys_bits, execonly);
+}
+
static void update_permission_bitmask(struct kvm_vcpu *vcpu,
struct kvm_mmu *mmu, bool ept)
{
@@ -3889,6 +3965,7 @@
update_permission_bitmask(vcpu, context, false);
update_last_pte_bitmap(vcpu, context);
+ reset_tdp_shadow_zero_bits_mask(vcpu, context);
}
void kvm_init_shadow_mmu(struct kvm_vcpu *vcpu)
@@ -3916,6 +3993,7 @@
context->base_role.smap_andnot_wp
= smap && !is_write_protection(vcpu);
context->base_role.smm = is_smm(vcpu);
+ reset_shadow_zero_bits_mask(vcpu, context);
}
EXPORT_SYMBOL_GPL(kvm_init_shadow_mmu);
@@ -3939,6 +4017,7 @@
update_permission_bitmask(vcpu, context, true);
reset_rsvds_bits_mask_ept(vcpu, context, execonly);
+ reset_ept_shadow_zero_bits_mask(vcpu, context, execonly);
}
EXPORT_SYMBOL_GPL(kvm_init_shadow_ept_mmu);
@@ -4860,28 +4939,6 @@
return nr_mmu_pages;
}
-int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4])
-{
- struct kvm_shadow_walk_iterator iterator;
- u64 spte;
- int nr_sptes = 0;
-
- if (!VALID_PAGE(vcpu->arch.mmu.root_hpa))
- return nr_sptes;
-
- walk_shadow_page_lockless_begin(vcpu);
- for_each_shadow_entry_lockless(vcpu, addr, iterator, spte) {
- sptes[iterator.level-1] = spte;
- nr_sptes++;
- if (!is_shadow_present_pte(spte))
- break;
- }
- walk_shadow_page_lockless_end(vcpu);
-
- return nr_sptes;
-}
-EXPORT_SYMBOL_GPL(kvm_mmu_get_spte_hierarchy);
-
void kvm_mmu_destroy(struct kvm_vcpu *vcpu)
{
kvm_mmu_unload(vcpu);
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index 398d21c..e4202e4 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -50,9 +50,11 @@
return ((1ULL << (e - s + 1)) - 1) << s;
}
-int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *vcpu, u64 addr, u64 sptes[4]);
void kvm_mmu_set_mmio_spte_mask(u64 mmio_mask);
+void
+reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context);
+
/*
* Return values of handle_mmio_page_fault_common:
* RET_MMIO_PF_EMULATE: it is a real mmio page fault, emulate the instruction
diff --git a/arch/x86/kvm/mtrr.c b/arch/x86/kvm/mtrr.c
index de1d2d8..9e8bf13 100644
--- a/arch/x86/kvm/mtrr.c
+++ b/arch/x86/kvm/mtrr.c
@@ -120,6 +120,16 @@
return mtrr_state->deftype & IA32_MTRR_DEF_TYPE_TYPE_MASK;
}
+static u8 mtrr_disabled_type(void)
+{
+ /*
+ * Intel SDM 11.11.2.2: all MTRRs are disabled when
+ * IA32_MTRR_DEF_TYPE.E bit is cleared, and the UC
+ * memory type is applied to all of physical memory.
+ */
+ return MTRR_TYPE_UNCACHABLE;
+}
+
/*
* Three terms are used in the following code:
* - segment, it indicates the address segments covered by fixed MTRRs.
@@ -434,6 +444,8 @@
/* output fields. */
int mem_type;
+ /* mtrr is completely disabled? */
+ bool mtrr_disabled;
/* [start, end) is not fully covered in MTRRs? */
bool partial_map;
@@ -549,7 +561,7 @@
static void mtrr_lookup_start(struct mtrr_iter *iter)
{
if (!mtrr_is_enabled(iter->mtrr_state)) {
- iter->partial_map = true;
+ iter->mtrr_disabled = true;
return;
}
@@ -563,6 +575,7 @@
iter->mtrr_state = mtrr_state;
iter->start = start;
iter->end = end;
+ iter->mtrr_disabled = false;
iter->partial_map = false;
iter->fixed = false;
iter->range = NULL;
@@ -656,15 +669,19 @@
return MTRR_TYPE_WRBACK;
}
- /* It is not covered by MTRRs. */
- if (iter.partial_map) {
- /*
- * We just check one page, partially covered by MTRRs is
- * impossible.
- */
- WARN_ON(type != -1);
- type = mtrr_default_type(mtrr_state);
- }
+ if (iter.mtrr_disabled)
+ return mtrr_disabled_type();
+
+ /* not contained in any MTRRs. */
+ if (type == -1)
+ return mtrr_default_type(mtrr_state);
+
+ /*
+ * We just check one page, partially covered by MTRRs is
+ * impossible.
+ */
+ WARN_ON(iter.partial_map);
+
return type;
}
EXPORT_SYMBOL_GPL(kvm_mtrr_get_guest_memory_type);
@@ -689,6 +706,9 @@
return false;
}
+ if (iter.mtrr_disabled)
+ return true;
+
if (!iter.partial_map)
return true;
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 0f67d7e..736e6ab 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -128,14 +128,6 @@
*access &= mask;
}
-static bool FNAME(is_rsvd_bits_set)(struct kvm_mmu *mmu, u64 gpte, int level)
-{
- int bit7 = (gpte >> 7) & 1, low6 = gpte & 0x3f;
-
- return (gpte & mmu->rsvd_bits_mask[bit7][level-1]) |
- ((mmu->bad_mt_xwr & (1ull << low6)) != 0);
-}
-
static inline int FNAME(is_present_gpte)(unsigned long pte)
{
#if PTTYPE != PTTYPE_EPT
@@ -172,7 +164,7 @@
struct kvm_mmu_page *sp, u64 *spte,
u64 gpte)
{
- if (FNAME(is_rsvd_bits_set)(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
+ if (is_rsvd_bits_set(&vcpu->arch.mmu, gpte, PT_PAGE_TABLE_LEVEL))
goto no_present;
if (!FNAME(is_present_gpte)(gpte))
@@ -353,8 +345,7 @@
if (unlikely(!FNAME(is_present_gpte)(pte)))
goto error;
- if (unlikely(FNAME(is_rsvd_bits_set)(mmu, pte,
- walker->level))) {
+ if (unlikely(is_rsvd_bits_set(mmu, pte, walker->level))) {
errcode |= PFERR_RSVD_MASK | PFERR_PRESENT_MASK;
goto error;
}
diff --git a/arch/x86/kvm/pmu_amd.c b/arch/x86/kvm/pmu_amd.c
index 886aa25..39b9112 100644
--- a/arch/x86/kvm/pmu_amd.c
+++ b/arch/x86/kvm/pmu_amd.c
@@ -133,8 +133,6 @@
/* MSR_K7_PERFCTRn */
pmc = get_gp_pmc(pmu, msr, MSR_K7_PERFCTR0);
if (pmc) {
- if (!msr_info->host_initiated)
- data = (s64)data;
pmc->counter += data - pmc_read_counter(pmc);
return 0;
}
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index bbc678a..74d8257 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1173,6 +1173,10 @@
if (!is_mmio && !kvm_arch_has_assigned_device(vcpu->kvm))
return 0;
+ if (!kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED) &&
+ kvm_read_cr0(vcpu) & X86_CR0_CD)
+ return _PAGE_NOCACHE;
+
mtrr = kvm_mtrr_get_guest_memory_type(vcpu, gfn);
return mtrr2protval[mtrr];
}
@@ -1667,13 +1671,10 @@
if (!vcpu->fpu_active)
cr0 |= X86_CR0_TS;
- /*
- * re-enable caching here because the QEMU bios
- * does not do it - this results in some delay at
- * reboot
- */
- if (!(vcpu->kvm->arch.disabled_quirks & KVM_QUIRK_CD_NW_CLEARED))
- cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
+
+ /* These are emulated via page tables. */
+ cr0 &= ~(X86_CR0_CD | X86_CR0_NW);
+
svm->vmcb->save.cr0 = cr0;
mark_dirty(svm->vmcb, VMCB_CR);
update_cr0_intercept(svm);
@@ -2106,6 +2107,7 @@
vcpu->arch.mmu.get_pdptr = nested_svm_get_tdp_pdptr;
vcpu->arch.mmu.inject_page_fault = nested_svm_inject_npf_exit;
vcpu->arch.mmu.shadow_root_level = get_npt_level();
+ reset_shadow_zero_bits_mask(vcpu, &vcpu->arch.mmu);
vcpu->arch.walk_mmu = &vcpu->arch.nested_mmu;
}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 5b4e938..da1590e 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2443,10 +2443,10 @@
CPU_BASED_CR8_LOAD_EXITING | CPU_BASED_CR8_STORE_EXITING |
#endif
CPU_BASED_MOV_DR_EXITING | CPU_BASED_UNCOND_IO_EXITING |
- CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_EXITING |
- CPU_BASED_RDPMC_EXITING | CPU_BASED_RDTSC_EXITING |
- CPU_BASED_PAUSE_EXITING | CPU_BASED_TPR_SHADOW |
- CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
+ CPU_BASED_USE_IO_BITMAPS | CPU_BASED_MONITOR_TRAP_FLAG |
+ CPU_BASED_MONITOR_EXITING | CPU_BASED_RDPMC_EXITING |
+ CPU_BASED_RDTSC_EXITING | CPU_BASED_PAUSE_EXITING |
+ CPU_BASED_TPR_SHADOW | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS;
/*
* We can allow some features even when not supported by the
* hardware. For example, L1 can specify an MSR bitmap - and we
@@ -3423,12 +3423,12 @@
vmx_segment_cache_clear(to_vmx(vcpu));
guest_tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
- if ((guest_tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
+ if ((guest_tr_ar & VMX_AR_TYPE_MASK) != VMX_AR_TYPE_BUSY_64_TSS) {
pr_debug_ratelimited("%s: tss fixup for long mode. \n",
__func__);
vmcs_write32(GUEST_TR_AR_BYTES,
- (guest_tr_ar & ~AR_TYPE_MASK)
- | AR_TYPE_BUSY_64_TSS);
+ (guest_tr_ar & ~VMX_AR_TYPE_MASK)
+ | VMX_AR_TYPE_BUSY_64_TSS);
}
vmx_set_efer(vcpu, vcpu->arch.efer | EFER_LMA);
}
@@ -3719,7 +3719,7 @@
return 0;
else {
int ar = vmx_read_guest_seg_ar(vmx, VCPU_SREG_SS);
- return AR_DPL(ar);
+ return VMX_AR_DPL(ar);
}
}
@@ -3847,11 +3847,11 @@
if (cs.unusable)
return false;
- if (~cs.type & (AR_TYPE_CODE_MASK|AR_TYPE_ACCESSES_MASK))
+ if (~cs.type & (VMX_AR_TYPE_CODE_MASK|VMX_AR_TYPE_ACCESSES_MASK))
return false;
if (!cs.s)
return false;
- if (cs.type & AR_TYPE_WRITEABLE_MASK) {
+ if (cs.type & VMX_AR_TYPE_WRITEABLE_MASK) {
if (cs.dpl > cs_rpl)
return false;
} else {
@@ -3901,7 +3901,7 @@
return false;
if (!var.present)
return false;
- if (~var.type & (AR_TYPE_CODE_MASK|AR_TYPE_WRITEABLE_MASK)) {
+ if (~var.type & (VMX_AR_TYPE_CODE_MASK|VMX_AR_TYPE_WRITEABLE_MASK)) {
if (var.dpl < rpl) /* DPL < RPL */
return false;
}
@@ -5759,73 +5759,9 @@
return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0);
}
-static u64 ept_rsvd_mask(u64 spte, int level)
-{
- int i;
- u64 mask = 0;
-
- for (i = 51; i > boot_cpu_data.x86_phys_bits; i--)
- mask |= (1ULL << i);
-
- if (level == 4)
- /* bits 7:3 reserved */
- mask |= 0xf8;
- else if (spte & (1ULL << 7))
- /*
- * 1GB/2MB page, bits 29:12 or 20:12 reserved respectively,
- * level == 1 if the hypervisor is using the ignored bit 7.
- */
- mask |= (PAGE_SIZE << ((level - 1) * 9)) - PAGE_SIZE;
- else if (level > 1)
- /* bits 6:3 reserved */
- mask |= 0x78;
-
- return mask;
-}
-
-static void ept_misconfig_inspect_spte(struct kvm_vcpu *vcpu, u64 spte,
- int level)
-{
- printk(KERN_ERR "%s: spte 0x%llx level %d\n", __func__, spte, level);
-
- /* 010b (write-only) */
- WARN_ON((spte & 0x7) == 0x2);
-
- /* 110b (write/execute) */
- WARN_ON((spte & 0x7) == 0x6);
-
- /* 100b (execute-only) and value not supported by logical processor */
- if (!cpu_has_vmx_ept_execute_only())
- WARN_ON((spte & 0x7) == 0x4);
-
- /* not 000b */
- if ((spte & 0x7)) {
- u64 rsvd_bits = spte & ept_rsvd_mask(spte, level);
-
- if (rsvd_bits != 0) {
- printk(KERN_ERR "%s: rsvd_bits = 0x%llx\n",
- __func__, rsvd_bits);
- WARN_ON(1);
- }
-
- /* bits 5:3 are _not_ reserved for large page or leaf page */
- if ((rsvd_bits & 0x38) == 0) {
- u64 ept_mem_type = (spte & 0x38) >> 3;
-
- if (ept_mem_type == 2 || ept_mem_type == 3 ||
- ept_mem_type == 7) {
- printk(KERN_ERR "%s: ept_mem_type=0x%llx\n",
- __func__, ept_mem_type);
- WARN_ON(1);
- }
- }
- }
-}
-
static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
{
- u64 sptes[4];
- int nr_sptes, i, ret;
+ int ret;
gpa_t gpa;
gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
@@ -5846,13 +5782,7 @@
return 1;
/* It is the real ept misconfig */
- printk(KERN_ERR "EPT: Misconfiguration.\n");
- printk(KERN_ERR "EPT: GPA: 0x%llx\n", gpa);
-
- nr_sptes = kvm_mmu_get_spte_hierarchy(vcpu, gpa, sptes);
-
- for (i = PT64_ROOT_LEVEL; i > PT64_ROOT_LEVEL - nr_sptes; --i)
- ept_misconfig_inspect_spte(vcpu, sptes[i-1], i);
+ WARN_ON(1);
vcpu->run->exit_reason = KVM_EXIT_UNKNOWN;
vcpu->run->hw.hardware_exit_reason = EXIT_REASON_EPT_MISCONFIG;
@@ -6246,6 +6176,11 @@
return handle_nop(vcpu);
}
+static int handle_monitor_trap(struct kvm_vcpu *vcpu)
+{
+ return 1;
+}
+
static int handle_monitor(struct kvm_vcpu *vcpu)
{
printk_once(KERN_WARNING "kvm: MONITOR instruction emulated as NOP!\n");
@@ -6408,8 +6343,12 @@
*/
static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
unsigned long exit_qualification,
- u32 vmx_instruction_info, gva_t *ret)
+ u32 vmx_instruction_info, bool wr, gva_t *ret)
{
+ gva_t off;
+ bool exn;
+ struct kvm_segment s;
+
/*
* According to Vol. 3B, "Information for VM Exits Due to Instruction
* Execution", on an exit, vmx_instruction_info holds most of the
@@ -6434,22 +6373,63 @@
/* Addr = segment_base + offset */
/* offset = base + [index * scale] + displacement */
- *ret = vmx_get_segment_base(vcpu, seg_reg);
+ off = exit_qualification; /* holds the displacement */
if (base_is_valid)
- *ret += kvm_register_read(vcpu, base_reg);
+ off += kvm_register_read(vcpu, base_reg);
if (index_is_valid)
- *ret += kvm_register_read(vcpu, index_reg)<<scaling;
- *ret += exit_qualification; /* holds the displacement */
+ off += kvm_register_read(vcpu, index_reg)<<scaling;
+ vmx_get_segment(vcpu, &s, seg_reg);
+ *ret = s.base + off;
if (addr_size == 1) /* 32 bit */
*ret &= 0xffffffff;
- /*
- * TODO: throw #GP (and return 1) in various cases that the VM*
- * instructions require it - e.g., offset beyond segment limit,
- * unusable or unreadable/unwritable segment, non-canonical 64-bit
- * address, and so on. Currently these are not checked.
- */
+ /* Checks for #GP/#SS exceptions. */
+ exn = false;
+ if (is_protmode(vcpu)) {
+ /* Protected mode: apply checks for segment validity in the
+ * following order:
+ * - segment type check (#GP(0) may be thrown)
+ * - usability check (#GP(0)/#SS(0))
+ * - limit check (#GP(0)/#SS(0))
+ */
+ if (wr)
+ /* #GP(0) if the destination operand is located in a
+ * read-only data segment or any code segment.
+ */
+ exn = ((s.type & 0xa) == 0 || (s.type & 8));
+ else
+ /* #GP(0) if the source operand is located in an
+ * execute-only code segment
+ */
+ exn = ((s.type & 0xa) == 8);
+ }
+ if (exn) {
+ kvm_queue_exception_e(vcpu, GP_VECTOR, 0);
+ return 1;
+ }
+ if (is_long_mode(vcpu)) {
+ /* Long mode: #GP(0)/#SS(0) if the memory address is in a
+ * non-canonical form. This is an only check for long mode.
+ */
+ exn = is_noncanonical_address(*ret);
+ } else if (is_protmode(vcpu)) {
+ /* Protected mode: #GP(0)/#SS(0) if the segment is unusable.
+ */
+ exn = (s.unusable != 0);
+ /* Protected mode: #GP(0)/#SS(0) if the memory
+ * operand is outside the segment limit.
+ */
+ exn = exn || (off + sizeof(u64) > s.limit);
+ }
+ if (exn) {
+ kvm_queue_exception_e(vcpu,
+ seg_reg == VCPU_SREG_SS ?
+ SS_VECTOR : GP_VECTOR,
+ 0);
+ return 1;
+ }
+
return 0;
}
@@ -6471,7 +6451,7 @@
int maxphyaddr = cpuid_maxphyaddr(vcpu);
if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
- vmcs_read32(VMX_INSTRUCTION_INFO), &gva))
+ vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva))
return 1;
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr,
@@ -6999,7 +6979,7 @@
field_value);
} else {
if (get_vmx_mem_address(vcpu, exit_qualification,
- vmx_instruction_info, &gva))
+ vmx_instruction_info, true, &gva))
return 1;
/* _system ok, as nested_vmx_check_permission verified cpl=0 */
kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva,
@@ -7036,7 +7016,7 @@
(((vmx_instruction_info) >> 3) & 0xf));
else {
if (get_vmx_mem_address(vcpu, exit_qualification,
- vmx_instruction_info, &gva))
+ vmx_instruction_info, false, &gva))
return 1;
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva,
&field_value, (is_64_bit_mode(vcpu) ? 8 : 4), &e)) {
@@ -7128,7 +7108,7 @@
return 1;
if (get_vmx_mem_address(vcpu, exit_qualification,
- vmx_instruction_info, &vmcs_gva))
+ vmx_instruction_info, true, &vmcs_gva))
return 1;
/* ok to use *_system, as nested_vmx_check_permission verified cpl=0 */
if (kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, vmcs_gva,
@@ -7184,7 +7164,7 @@
* operand is read even if it isn't needed (e.g., for type==global)
*/
if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
- vmx_instruction_info, &gva))
+ vmx_instruction_info, false, &gva))
return 1;
if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand,
sizeof(operand), &e)) {
@@ -7282,6 +7262,7 @@
[EXIT_REASON_EPT_MISCONFIG] = handle_ept_misconfig,
[EXIT_REASON_PAUSE_INSTRUCTION] = handle_pause,
[EXIT_REASON_MWAIT_INSTRUCTION] = handle_mwait,
+ [EXIT_REASON_MONITOR_TRAP_FLAG] = handle_monitor_trap,
[EXIT_REASON_MONITOR_INSTRUCTION] = handle_monitor,
[EXIT_REASON_INVEPT] = handle_invept,
[EXIT_REASON_INVVPID] = handle_invvpid,
@@ -7542,6 +7523,8 @@
return true;
case EXIT_REASON_MWAIT_INSTRUCTION:
return nested_cpu_has(vmcs12, CPU_BASED_MWAIT_EXITING);
+ case EXIT_REASON_MONITOR_TRAP_FLAG:
+ return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_TRAP_FLAG);
case EXIT_REASON_MONITOR_INSTRUCTION:
return nested_cpu_has(vmcs12, CPU_BASED_MONITOR_EXITING);
case EXIT_REASON_PAUSE_INSTRUCTION:
@@ -8650,7 +8633,10 @@
if (kvm_read_cr0(vcpu) & X86_CR0_CD) {
ipat = VMX_EPT_IPAT_BIT;
- cache = MTRR_TYPE_UNCACHABLE;
+ if (kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_CD_NW_CLEARED))
+ cache = MTRR_TYPE_WRBACK;
+ else
+ cache = MTRR_TYPE_UNCACHABLE;
goto exit;
}
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 5ef2560..4bbc2a1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -29,6 +29,7 @@
#include "cpuid.h"
#include "assigned-dev.h"
#include "pmu.h"
+#include "hyperv.h"
#include <linux/clocksource.h>
#include <linux/interrupt.h>
@@ -221,11 +222,9 @@
void kvm_define_shared_msr(unsigned slot, u32 msr)
{
BUG_ON(slot >= KVM_NR_SHARED_MSRS);
+ shared_msrs_global.msrs[slot] = msr;
if (slot >= shared_msrs_global.nr)
shared_msrs_global.nr = slot + 1;
- shared_msrs_global.msrs[slot] = msr;
- /* we need ensured the shared_msr_global have been updated */
- smp_wmb();
}
EXPORT_SYMBOL_GPL(kvm_define_shared_msr);
@@ -526,7 +525,8 @@
}
for (i = 0; i < ARRAY_SIZE(pdpte); ++i) {
if (is_present_gpte(pdpte[i]) &&
- (pdpte[i] & vcpu->arch.mmu.rsvd_bits_mask[0][2])) {
+ (pdpte[i] &
+ vcpu->arch.mmu.guest_rsvd_check.rsvd_bits_mask[0][2])) {
ret = 0;
goto out;
}
@@ -949,6 +949,8 @@
MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW,
HV_X64_MSR_GUEST_OS_ID, HV_X64_MSR_HYPERCALL,
HV_X64_MSR_TIME_REF_COUNT, HV_X64_MSR_REFERENCE_TSC,
+ HV_X64_MSR_CRASH_P0, HV_X64_MSR_CRASH_P1, HV_X64_MSR_CRASH_P2,
+ HV_X64_MSR_CRASH_P3, HV_X64_MSR_CRASH_P4, HV_X64_MSR_CRASH_CTL,
HV_X64_MSR_APIC_ASSIST_PAGE, MSR_KVM_ASYNC_PF_EN, MSR_KVM_STEAL_TIME,
MSR_KVM_PV_EOI_EN,
@@ -1217,11 +1219,6 @@
__func__, base_khz, scaled_khz, shift, *pmultiplier);
}
-static inline u64 get_kernel_ns(void)
-{
- return ktime_get_boot_ns();
-}
-
#ifdef CONFIG_X86_64
static atomic_t kvm_guest_has_master_clock = ATOMIC_INIT(0);
#endif
@@ -1869,123 +1866,6 @@
return r;
}
-static bool kvm_hv_hypercall_enabled(struct kvm *kvm)
-{
- return kvm->arch.hv_hypercall & HV_X64_MSR_HYPERCALL_ENABLE;
-}
-
-static bool kvm_hv_msr_partition_wide(u32 msr)
-{
- bool r = false;
- switch (msr) {
- case HV_X64_MSR_GUEST_OS_ID:
- case HV_X64_MSR_HYPERCALL:
- case HV_X64_MSR_REFERENCE_TSC:
- case HV_X64_MSR_TIME_REF_COUNT:
- r = true;
- break;
- }
-
- return r;
-}
-
-static int set_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 data)
-{
- struct kvm *kvm = vcpu->kvm;
-
- switch (msr) {
- case HV_X64_MSR_GUEST_OS_ID:
- kvm->arch.hv_guest_os_id = data;
- /* setting guest os id to zero disables hypercall page */
- if (!kvm->arch.hv_guest_os_id)
- kvm->arch.hv_hypercall &= ~HV_X64_MSR_HYPERCALL_ENABLE;
- break;
- case HV_X64_MSR_HYPERCALL: {
- u64 gfn;
- unsigned long addr;
- u8 instructions[4];
-
- /* if guest os id is not set hypercall should remain disabled */
- if (!kvm->arch.hv_guest_os_id)
- break;
- if (!(data & HV_X64_MSR_HYPERCALL_ENABLE)) {
- kvm->arch.hv_hypercall = data;
- break;
- }
- gfn = data >> HV_X64_MSR_HYPERCALL_PAGE_ADDRESS_SHIFT;
- addr = gfn_to_hva(kvm, gfn);
- if (kvm_is_error_hva(addr))
- return 1;
- kvm_x86_ops->patch_hypercall(vcpu, instructions);
- ((unsigned char *)instructions)[3] = 0xc3; /* ret */
- if (__copy_to_user((void __user *)addr, instructions, 4))
- return 1;
- kvm->arch.hv_hypercall = data;
- mark_page_dirty(kvm, gfn);
- break;
- }
- case HV_X64_MSR_REFERENCE_TSC: {
- u64 gfn;
- HV_REFERENCE_TSC_PAGE tsc_ref;
- memset(&tsc_ref, 0, sizeof(tsc_ref));
- kvm->arch.hv_tsc_page = data;
- if (!(data & HV_X64_MSR_TSC_REFERENCE_ENABLE))
- break;
- gfn = data >> HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT;
- if (kvm_write_guest(kvm, gfn << HV_X64_MSR_TSC_REFERENCE_ADDRESS_SHIFT,
- &tsc_ref, sizeof(tsc_ref)))
- return 1;
- mark_page_dirty(kvm, gfn);
- break;
- }
- default:
- vcpu_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x "
- "data 0x%llx\n", msr, data);
- return 1;
- }
- return 0;
-}
-
-static int set_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 data)
-{
- switch (msr) {
- case HV_X64_MSR_APIC_ASSIST_PAGE: {
- u64 gfn;
- unsigned long addr;
-
- if (!(data & HV_X64_MSR_APIC_ASSIST_PAGE_ENABLE)) {
- vcpu->arch.hv_vapic = data;
- if (kvm_lapic_enable_pv_eoi(vcpu, 0))
- return 1;
- break;
- }
- gfn = data >> HV_X64_MSR_APIC_ASSIST_PAGE_ADDRESS_SHIFT;
- addr = kvm_vcpu_gfn_to_hva(vcpu, gfn);
- if (kvm_is_error_hva(addr))
- return 1;
- if (__clear_user((void __user *)addr, PAGE_SIZE))
- return 1;
- vcpu->arch.hv_vapic = data;
- kvm_vcpu_mark_page_dirty(vcpu, gfn);
- if (kvm_lapic_enable_pv_eoi(vcpu, gfn_to_gpa(gfn) | KVM_MSR_ENABLED))
- return 1;
- break;
- }
- case HV_X64_MSR_EOI:
- return kvm_hv_vapic_msr_write(vcpu, APIC_EOI, data);
- case HV_X64_MSR_ICR:
- return kvm_hv_vapic_msr_write(vcpu, APIC_ICR, data);
- case HV_X64_MSR_TPR:
- return kvm_hv_vapic_msr_write(vcpu, APIC_TASKPRI, data);
- default:
- vcpu_unimpl(vcpu, "HYPER-V unimplemented wrmsr: 0x%x "
- "data 0x%llx\n", msr, data);
- return 1;
- }
-
- return 0;
-}
-
static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
{
gpa_t gpa = data & ~0x3f;
@@ -2105,7 +1985,7 @@
if (guest_cpuid_has_tsc_adjust(vcpu)) {
if (!msr_info->host_initiated) {
s64 adj = data - vcpu->arch.ia32_tsc_adjust_msr;
- kvm_x86_ops->adjust_tsc_offset(vcpu, adj, true);
+ adjust_tsc_offset_guest(vcpu, adj);
}
vcpu->arch.ia32_tsc_adjust_msr = data;
}
@@ -2224,15 +2104,10 @@
*/
break;
case HV_X64_MSR_GUEST_OS_ID ... HV_X64_MSR_SINT15:
- if (kvm_hv_msr_partition_wide(msr)) {
- int r;
- mutex_lock(&vcpu->kvm->lock);
- r = set_msr_hyperv_pw(vcpu, msr, data);
- mutex_unlock(&vcpu->kvm->lock);
- return r;
- } else
- return set_msr_hyperv(vcpu, msr, data);
- break;
+ case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+ case HV_X64_MSR_CRASH_CTL:
+ return kvm_hv_set_msr_common(vcpu, msr, data,
+ msr_info->host_initiated);
case MSR_IA32_BBL_CR_CTL3:
/* Drop writes to this legacy MSR -- see rdmsr
* counterpart for further detail.
@@ -2315,68 +2190,6 @@
return 0;
}
-static int get_msr_hyperv_pw(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
-{
- u64 data = 0;
- struct kvm *kvm = vcpu->kvm;
-
- switch (msr) {
- case HV_X64_MSR_GUEST_OS_ID:
- data = kvm->arch.hv_guest_os_id;
- break;
- case HV_X64_MSR_HYPERCALL:
- data = kvm->arch.hv_hypercall;
- break;
- case HV_X64_MSR_TIME_REF_COUNT: {
- data =
- div_u64(get_kernel_ns() + kvm->arch.kvmclock_offset, 100);
- break;
- }
- case HV_X64_MSR_REFERENCE_TSC:
- data = kvm->arch.hv_tsc_page;
- break;
- default:
- vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
- return 1;
- }
-
- *pdata = data;
- return 0;
-}
-
-static int get_msr_hyperv(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
-{
- u64 data = 0;
-
- switch (msr) {
- case HV_X64_MSR_VP_INDEX: {
- int r;
- struct kvm_vcpu *v;
- kvm_for_each_vcpu(r, v, vcpu->kvm) {
- if (v == vcpu) {
- data = r;
- break;
- }
- }
- break;
- }
- case HV_X64_MSR_EOI:
- return kvm_hv_vapic_msr_read(vcpu, APIC_EOI, pdata);
- case HV_X64_MSR_ICR:
- return kvm_hv_vapic_msr_read(vcpu, APIC_ICR, pdata);
- case HV_X64_MSR_TPR:
- return kvm_hv_vapic_msr_read(vcpu, APIC_TASKPRI, pdata);
- case HV_X64_MSR_APIC_ASSIST_PAGE:
- data = vcpu->arch.hv_vapic;
- break;
- default:
- vcpu_unimpl(vcpu, "Hyper-V unhandled rdmsr: 0x%x\n", msr);
- return 1;
- }
- *pdata = data;
- return 0;
-}
-
int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
{
switch (msr_info->index) {
@@ -2493,14 +2306,10 @@
msr_info->data = 0x20000000;
break;
case HV_X64_MSR_GUEST_OS_ID ... HV_X64_MSR_SINT15:
- if (kvm_hv_msr_partition_wide(msr_info->index)) {
- int r;
- mutex_lock(&vcpu->kvm->lock);
- r = get_msr_hyperv_pw(vcpu, msr_info->index, &msr_info->data);
- mutex_unlock(&vcpu->kvm->lock);
- return r;
- } else
- return get_msr_hyperv(vcpu, msr_info->index, &msr_info->data);
+ case HV_X64_MSR_CRASH_P0 ... HV_X64_MSR_CRASH_P4:
+ case HV_X64_MSR_CRASH_CTL:
+ return kvm_hv_get_msr_common(vcpu,
+ msr_info->index, &msr_info->data);
break;
case MSR_IA32_BBL_CR_CTL3:
/* This legacy MSR exists but isn't fully documented in current
@@ -2651,6 +2460,7 @@
case KVM_CAP_TSC_DEADLINE_TIMER:
case KVM_CAP_ENABLE_CAP_VM:
case KVM_CAP_DISABLE_QUIRKS:
+ case KVM_CAP_SET_BOOT_CPU_ID:
#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
case KVM_CAP_ASSIGN_DEV_IRQ:
case KVM_CAP_PCI_2_3:
@@ -3817,30 +3627,25 @@
r = kvm_ioapic_init(kvm);
if (r) {
mutex_lock(&kvm->slots_lock);
- kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
- &vpic->dev_master);
- kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
- &vpic->dev_slave);
- kvm_io_bus_unregister_dev(kvm, KVM_PIO_BUS,
- &vpic->dev_eclr);
+ kvm_destroy_pic(vpic);
mutex_unlock(&kvm->slots_lock);
- kfree(vpic);
goto create_irqchip_unlock;
}
} else
goto create_irqchip_unlock;
- smp_wmb();
- kvm->arch.vpic = vpic;
- smp_wmb();
r = kvm_setup_default_irq_routing(kvm);
if (r) {
mutex_lock(&kvm->slots_lock);
mutex_lock(&kvm->irq_lock);
kvm_ioapic_destroy(kvm);
- kvm_destroy_pic(kvm);
+ kvm_destroy_pic(vpic);
mutex_unlock(&kvm->irq_lock);
mutex_unlock(&kvm->slots_lock);
+ goto create_irqchip_unlock;
}
+ /* Write kvm->irq_routing before kvm->arch.vpic. */
+ smp_wmb();
+ kvm->arch.vpic = vpic;
create_irqchip_unlock:
mutex_unlock(&kvm->lock);
break;
@@ -3967,6 +3772,15 @@
r = kvm_vm_ioctl_reinject(kvm, &control);
break;
}
+ case KVM_SET_BOOT_CPU_ID:
+ r = 0;
+ mutex_lock(&kvm->lock);
+ if (atomic_read(&kvm->online_vcpus) != 0)
+ r = -EBUSY;
+ else
+ kvm->arch.bsp_vcpu_id = arg;
+ mutex_unlock(&kvm->lock);
+ break;
case KVM_XEN_HVM_CONFIG: {
r = -EFAULT;
if (copy_from_user(&kvm->arch.xen_hvm_config, argp,
@@ -5882,66 +5696,6 @@
}
EXPORT_SYMBOL_GPL(kvm_emulate_halt);
-int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
-{
- u64 param, ingpa, outgpa, ret;
- uint16_t code, rep_idx, rep_cnt, res = HV_STATUS_SUCCESS, rep_done = 0;
- bool fast, longmode;
-
- /*
- * hypercall generates UD from non zero cpl and real mode
- * per HYPER-V spec
- */
- if (kvm_x86_ops->get_cpl(vcpu) != 0 || !is_protmode(vcpu)) {
- kvm_queue_exception(vcpu, UD_VECTOR);
- return 0;
- }
-
- longmode = is_64_bit_mode(vcpu);
-
- if (!longmode) {
- param = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDX) << 32) |
- (kvm_register_read(vcpu, VCPU_REGS_RAX) & 0xffffffff);
- ingpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RBX) << 32) |
- (kvm_register_read(vcpu, VCPU_REGS_RCX) & 0xffffffff);
- outgpa = ((u64)kvm_register_read(vcpu, VCPU_REGS_RDI) << 32) |
- (kvm_register_read(vcpu, VCPU_REGS_RSI) & 0xffffffff);
- }
-#ifdef CONFIG_X86_64
- else {
- param = kvm_register_read(vcpu, VCPU_REGS_RCX);
- ingpa = kvm_register_read(vcpu, VCPU_REGS_RDX);
- outgpa = kvm_register_read(vcpu, VCPU_REGS_R8);
- }
-#endif
-
- code = param & 0xffff;
- fast = (param >> 16) & 0x1;
- rep_cnt = (param >> 32) & 0xfff;
- rep_idx = (param >> 48) & 0xfff;
-
- trace_kvm_hv_hypercall(code, fast, rep_cnt, rep_idx, ingpa, outgpa);
-
- switch (code) {
- case HV_X64_HV_NOTIFY_LONG_SPIN_WAIT:
- kvm_vcpu_on_spin(vcpu);
- break;
- default:
- res = HV_STATUS_INVALID_HYPERCALL_CODE;
- break;
- }
-
- ret = res | (((u64)rep_done & 0xfff) << 32);
- if (longmode) {
- kvm_register_write(vcpu, VCPU_REGS_RAX, ret);
- } else {
- kvm_register_write(vcpu, VCPU_REGS_RDX, ret >> 32);
- kvm_register_write(vcpu, VCPU_REGS_RAX, ret & 0xffffffff);
- }
-
- return 1;
-}
-
/*
* kvm_pv_kick_cpu_op: Kick a vcpu.
*
@@ -6327,6 +6081,7 @@
static void process_smi(struct kvm_vcpu *vcpu)
{
struct kvm_segment cs, ds;
+ struct desc_ptr dt;
char buf[512];
u32 cr0;
@@ -6359,6 +6114,10 @@
kvm_x86_ops->set_cr4(vcpu, 0);
+ /* Undocumented: IDT limit is set to zero on entry to SMM. */
+ dt.address = dt.size = 0;
+ kvm_x86_ops->set_idt(vcpu, &dt);
+
__kvm_set_dr(vcpu, 7, DR7_FIXED_1);
cs.selector = (vcpu->arch.smbase >> 4) & 0xffff;
@@ -6513,6 +6272,12 @@
vcpu_scan_ioapic(vcpu);
if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
kvm_vcpu_reload_apic_access_page(vcpu);
+ if (kvm_check_request(KVM_REQ_HV_CRASH, vcpu)) {
+ vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
+ vcpu->run->system_event.type = KVM_SYSTEM_EVENT_CRASH;
+ r = 0;
+ goto out;
+ }
}
if (kvm_check_request(KVM_REQ_EVENT, vcpu) || req_int_win) {
@@ -7535,6 +7300,17 @@
kvm_x86_ops->check_processor_compatibility(rtn);
}
+bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu)
+{
+ return vcpu->kvm->arch.bsp_vcpu_id == vcpu->vcpu_id;
+}
+EXPORT_SYMBOL_GPL(kvm_vcpu_is_reset_bsp);
+
+bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
+{
+ return (vcpu->arch.apic_base & MSR_IA32_APICBASE_BSP) != 0;
+}
+
bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
{
return irqchip_in_kernel(vcpu->kvm) == (vcpu->arch.apic != NULL);
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index edc8cdc..2f822cd 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -147,6 +147,16 @@
return kvm_register_write(vcpu, reg, val);
}
+static inline u64 get_kernel_ns(void)
+{
+ return ktime_get_boot_ns();
+}
+
+static inline bool kvm_check_has_quirk(struct kvm *kvm, u64 quirk)
+{
+ return !(kvm->arch.disabled_quirks & quirk);
+}
+
void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
void kvm_set_pending_timer(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c
index f37e84a..3d8f2e4 100644
--- a/arch/x86/math-emu/fpu_entry.c
+++ b/arch/x86/math-emu/fpu_entry.c
@@ -29,7 +29,6 @@
#include <asm/uaccess.h>
#include <asm/traps.h>
-#include <asm/desc.h>
#include <asm/user.h>
#include <asm/fpu/internal.h>
@@ -181,7 +180,7 @@
math_abort(FPU_info, SIGILL);
}
- code_descriptor = LDT_DESCRIPTOR(FPU_CS);
+ code_descriptor = FPU_get_ldt_descriptor(FPU_CS);
if (SEG_D_SIZE(code_descriptor)) {
/* The above test may be wrong, the book is not clear */
/* Segmented 32 bit protected mode */
diff --git a/arch/x86/math-emu/fpu_system.h b/arch/x86/math-emu/fpu_system.h
index 9ccecb6..5e044d5 100644
--- a/arch/x86/math-emu/fpu_system.h
+++ b/arch/x86/math-emu/fpu_system.h
@@ -16,9 +16,24 @@
#include <linux/kernel.h>
#include <linux/mm.h>
-/* s is always from a cpu register, and the cpu does bounds checking
- * during register load --> no further bounds checks needed */
-#define LDT_DESCRIPTOR(s) (((struct desc_struct *)current->mm->context.ldt)[(s) >> 3])
+#include <asm/desc.h>
+#include <asm/mmu_context.h>
+
+static inline struct desc_struct FPU_get_ldt_descriptor(unsigned seg)
+{
+ static struct desc_struct zero_desc;
+ struct desc_struct ret = zero_desc;
+
+#ifdef CONFIG_MODIFY_LDT_SYSCALL
+ seg >>= 3;
+ mutex_lock(¤t->mm->context.lock);
+ if (current->mm->context.ldt && seg < current->mm->context.ldt->size)
+ ret = current->mm->context.ldt->entries[seg];
+ mutex_unlock(¤t->mm->context.lock);
+#endif
+ return ret;
+}
+
#define SEG_D_SIZE(x) ((x).b & (3 << 21))
#define SEG_G_BIT(x) ((x).b & (1 << 23))
#define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1)
diff --git a/arch/x86/math-emu/get_address.c b/arch/x86/math-emu/get_address.c
index 6ef5e99..8300db7 100644
--- a/arch/x86/math-emu/get_address.c
+++ b/arch/x86/math-emu/get_address.c
@@ -20,7 +20,6 @@
#include <linux/stddef.h>
#include <asm/uaccess.h>
-#include <asm/desc.h>
#include "fpu_system.h"
#include "exception.h"
@@ -158,7 +157,7 @@
addr->selector = PM_REG_(segment);
}
- descriptor = LDT_DESCRIPTOR(PM_REG_(segment));
+ descriptor = FPU_get_ldt_descriptor(addr->selector);
base_address = SEG_BASE_ADDR(descriptor);
address = base_address + offset;
limit = base_address
diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
index cc5ccc4..b9c78f3 100644
--- a/arch/x86/mm/ioremap.c
+++ b/arch/x86/mm/ioremap.c
@@ -63,8 +63,6 @@
!PageReserved(pfn_to_page(start_pfn + i)))
return 1;
- WARN_ONCE(1, "ioremap on RAM pfn 0x%lx\n", start_pfn);
-
return 0;
}
@@ -94,7 +92,6 @@
pgprot_t prot;
int retval;
void __iomem *ret_addr;
- int ram_region;
/* Don't allow wraparound or zero size */
last_addr = phys_addr + size - 1;
@@ -117,23 +114,15 @@
/*
* Don't allow anybody to remap normal RAM that we're using..
*/
- /* First check if whole region can be identified as RAM or not */
- ram_region = region_is_ram(phys_addr, size);
- if (ram_region > 0) {
- WARN_ONCE(1, "ioremap on RAM at 0x%lx - 0x%lx\n",
- (unsigned long int)phys_addr,
- (unsigned long int)last_addr);
+ pfn = phys_addr >> PAGE_SHIFT;
+ last_pfn = last_addr >> PAGE_SHIFT;
+ if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
+ __ioremap_check_ram) == 1) {
+ WARN_ONCE(1, "ioremap on RAM at %pa - %pa\n",
+ &phys_addr, &last_addr);
return NULL;
}
- /* If could not be identified(-1), check page by page */
- if (ram_region < 0) {
- pfn = phys_addr >> PAGE_SHIFT;
- last_pfn = last_addr >> PAGE_SHIFT;
- if (walk_system_ram_range(pfn, last_pfn - pfn + 1, NULL,
- __ioremap_check_ram) == 1)
- return NULL;
- }
/*
* Mappings have to be page-aligned
*/
diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c
index 9d518d6..844b06d 100644
--- a/arch/x86/mm/mmap.c
+++ b/arch/x86/mm/mmap.c
@@ -126,3 +126,10 @@
mm->get_unmapped_area = arch_get_unmapped_area_topdown;
}
}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+ if (vma->vm_flags & VM_MPX)
+ return "[mpx]";
+ return NULL;
+}
diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index 7a657f5..db1b0bc 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -20,20 +20,6 @@
#define CREATE_TRACE_POINTS
#include <asm/trace/mpx.h>
-static const char *mpx_mapping_name(struct vm_area_struct *vma)
-{
- return "[mpx]";
-}
-
-static struct vm_operations_struct mpx_vma_ops = {
- .name = mpx_mapping_name,
-};
-
-static int is_mpx_vma(struct vm_area_struct *vma)
-{
- return (vma->vm_ops == &mpx_vma_ops);
-}
-
static inline unsigned long mpx_bd_size_bytes(struct mm_struct *mm)
{
if (is_64bit_mm(mm))
@@ -53,9 +39,6 @@
/*
* This is really a simplified "vm_mmap". it only handles MPX
* bounds tables (the bounds directory is user-allocated).
- *
- * Later on, we use the vma->vm_ops to uniquely identify these
- * VMAs.
*/
static unsigned long mpx_mmap(unsigned long len)
{
@@ -101,7 +84,6 @@
ret = -ENOMEM;
goto out;
}
- vma->vm_ops = &mpx_vma_ops;
if (vm_flags & VM_LOCKED) {
up_write(&mm->mmap_sem);
@@ -812,7 +794,7 @@
* so stop immediately and return an error. This
* probably results in a SIGSEGV.
*/
- if (!is_mpx_vma(vma))
+ if (!(vma->vm_flags & VM_MPX))
return -EINVAL;
len = min(vma->vm_end, end) - addr;
@@ -945,9 +927,9 @@
* lots of tables even though we have no actual table
* entries in use.
*/
- while (next && is_mpx_vma(next))
+ while (next && (next->vm_flags & VM_MPX))
next = next->vm_next;
- while (prev && is_mpx_vma(prev))
+ while (prev && (prev->vm_flags & VM_MPX))
prev = prev->vm_prev;
/*
* We know 'start' and 'end' lie within an area controlled
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 3250f23..90b924a 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -117,7 +117,7 @@
} else {
unsigned long addr;
unsigned long nr_pages =
- f->flush_end - f->flush_start / PAGE_SIZE;
+ (f->flush_end - f->flush_start) / PAGE_SIZE;
addr = f->flush_start;
while (addr < f->flush_end) {
__flush_tlb_single(addr);
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 579a8fd..be2e7a2 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -269,7 +269,7 @@
EMIT4(0x48, 0x8B, 0x46, /* mov rax, qword ptr [rsi + 16] */
offsetof(struct bpf_array, map.max_entries));
EMIT3(0x48, 0x39, 0xD0); /* cmp rax, rdx */
-#define OFFSET1 44 /* number of bytes to jump */
+#define OFFSET1 47 /* number of bytes to jump */
EMIT2(X86_JBE, OFFSET1); /* jbe out */
label1 = cnt;
@@ -278,15 +278,15 @@
*/
EMIT2_off32(0x8B, 0x85, -STACKSIZE + 36); /* mov eax, dword ptr [rbp - 516] */
EMIT3(0x83, 0xF8, MAX_TAIL_CALL_CNT); /* cmp eax, MAX_TAIL_CALL_CNT */
-#define OFFSET2 33
+#define OFFSET2 36
EMIT2(X86_JA, OFFSET2); /* ja out */
label2 = cnt;
EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */
EMIT2_off32(0x89, 0x85, -STACKSIZE + 36); /* mov dword ptr [rbp - 516], eax */
/* prog = array->prog[index]; */
- EMIT4(0x48, 0x8D, 0x44, 0xD6); /* lea rax, [rsi + rdx * 8 + 0x50] */
- EMIT1(offsetof(struct bpf_array, prog));
+ EMIT4_off32(0x48, 0x8D, 0x84, 0xD6, /* lea rax, [rsi + rdx * 8 + offsetof(...)] */
+ offsetof(struct bpf_array, prog));
EMIT3(0x48, 0x8B, 0x00); /* mov rax, qword ptr [rax] */
/* if (prog == NULL)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index cfba30f..e4308fe 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -972,6 +972,11 @@
static int __init arch_parse_efi_cmdline(char *str)
{
+ if (!str) {
+ pr_warn("need at least one option\n");
+ return -EINVAL;
+ }
+
if (parse_option_str(str, "old_map"))
set_bit(EFI_OLD_MEMMAP, &efi.flags);
if (parse_option_str(str, "debug"))
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 0d7dd1f..9ab5279 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -22,6 +22,7 @@
#include <asm/fpu/internal.h>
#include <asm/debugreg.h>
#include <asm/cpu.h>
+#include <asm/mmu_context.h>
#ifdef CONFIG_X86_32
__visible unsigned long saved_context_ebx;
@@ -153,7 +154,7 @@
syscall_init(); /* This sets MSR_*STAR and related */
#endif
load_TR_desc(); /* This does ltr */
- load_LDT(¤t->active_mm->context); /* This does lldt */
+ load_mm_ldt(current->active_mm); /* This does lldt */
fpu__resume_cpu();
}
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index e88fda8..4841453 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -8,7 +8,7 @@
select PARAVIRT_CLOCK
select XEN_HAVE_PVMMU
depends on X86_64 || (X86_32 && X86_PAE)
- depends on X86_TSC
+ depends on X86_LOCAL_APIC && X86_TSC
help
This is the Linux Xen port. Enabling this will allow the
kernel to boot in a paravirtualized environment under the
@@ -17,7 +17,7 @@
config XEN_DOM0
def_bool y
depends on XEN && PCI_XEN && SWIOTLB_XEN
- depends on X86_LOCAL_APIC && X86_IO_APIC && ACPI && PCI
+ depends on X86_IO_APIC && ACPI && PCI
config XEN_PVHVM
def_bool y
diff --git a/arch/x86/xen/Makefile b/arch/x86/xen/Makefile
index 7322755..4b6e29a 100644
--- a/arch/x86/xen/Makefile
+++ b/arch/x86/xen/Makefile
@@ -13,13 +13,13 @@
obj-y := enlighten.o setup.o multicalls.o mmu.o irq.o \
time.o xen-asm.o xen-asm_$(BITS).o \
grant-table.o suspend.o platform-pci-unplug.o \
- p2m.o
+ p2m.o apic.o
obj-$(CONFIG_EVENT_TRACING) += trace.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= spinlock.o
obj-$(CONFIG_XEN_DEBUG_FS) += debugfs.o
-obj-$(CONFIG_XEN_DOM0) += apic.o vga.o
+obj-$(CONFIG_XEN_DOM0) += vga.o
obj-$(CONFIG_SWIOTLB_XEN) += pci-swiotlb-xen.o
obj-$(CONFIG_XEN_EFI) += efi.o
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 0b95c9b..11d6fb4 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -483,6 +483,7 @@
pte_t pte;
unsigned long pfn;
struct page *page;
+ unsigned char dummy;
ptep = lookup_address((unsigned long)v, &level);
BUG_ON(ptep == NULL);
@@ -492,6 +493,32 @@
pte = pfn_pte(pfn, prot);
+ /*
+ * Careful: update_va_mapping() will fail if the virtual address
+ * we're poking isn't populated in the page tables. We don't
+ * need to worry about the direct map (that's always in the page
+ * tables), but we need to be careful about vmap space. In
+ * particular, the top level page table can lazily propagate
+ * entries between processes, so if we've switched mms since we
+ * vmapped the target in the first place, we might not have the
+ * top-level page table entry populated.
+ *
+ * We disable preemption because we want the same mm active when
+ * we probe the target and when we issue the hypercall. We'll
+ * have the same nominal mm, but if we're a kernel thread, lazy
+ * mm dropping could change our pgd.
+ *
+ * Out of an abundance of caution, this uses __get_user() to fault
+ * in the target address just in case there's some obscure case
+ * in which the target address isn't readable.
+ */
+
+ preempt_disable();
+
+ pagefault_disable(); /* Avoid warnings due to being atomic. */
+ __get_user(dummy, (unsigned char __user __force *)v);
+ pagefault_enable();
+
if (HYPERVISOR_update_va_mapping((unsigned long)v, pte, 0))
BUG();
@@ -503,6 +530,8 @@
BUG();
} else
kmap_flush_unused();
+
+ preempt_enable();
}
static void xen_alloc_ldt(struct desc_struct *ldt, unsigned entries)
@@ -510,6 +539,17 @@
const unsigned entries_per_page = PAGE_SIZE / LDT_ENTRY_SIZE;
int i;
+ /*
+ * We need to mark the all aliases of the LDT pages RO. We
+ * don't need to call vm_flush_aliases(), though, since that's
+ * only responsible for flushing aliases out the TLBs, not the
+ * page tables, and Xen will flush the TLB for us if needed.
+ *
+ * To avoid confusing future readers: none of this is necessary
+ * to load the LDT. The hypervisor only checks this when the
+ * LDT is faulted in due to subsequent descriptor access.
+ */
+
for(i = 0; i < entries; i += entries_per_page)
set_aliased_prot(ldt + i, PAGE_KERNEL_RO);
}
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index c20fe29..2292721 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -101,17 +101,15 @@
#ifdef CONFIG_XEN_DOM0
void __init xen_init_vga(const struct dom0_vga_console_info *, size_t size);
-void __init xen_init_apic(void);
#else
static inline void __init xen_init_vga(const struct dom0_vga_console_info *info,
size_t size)
{
}
-static inline void __init xen_init_apic(void)
-{
-}
#endif
+void __init xen_init_apic(void);
+
#ifdef CONFIG_XEN_EFI
extern void xen_efi_init(void);
#else
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index e5b872b..3bd3504 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -14,12 +14,15 @@
select GENERIC_IRQ_SHOW
select GENERIC_PCI_IOMAP
select GENERIC_SCHED_CLOCK
+ select HAVE_DMA_API_DEBUG
+ select HAVE_DMA_ATTRS
select HAVE_FUNCTION_TRACER
select HAVE_IRQ_TIME_ACCOUNTING
select HAVE_OPROFILE
select HAVE_PERF_EVENTS
select IRQ_DOMAIN
select MODULES_USE_ELF_RELA
+ select PERF_USE_VMALLOC
select VIRT_TO_BUS
help
Xtensa processors are 32-bit RISC machines designed by Tensilica
@@ -61,9 +64,7 @@
def_bool y
config MMU
- bool
- default n if !XTENSA_VARIANT_CUSTOM
- default XTENSA_VARIANT_MMU if XTENSA_VARIANT_CUSTOM
+ def_bool n
config VARIANT_IRQ_SWITCH
def_bool n
@@ -71,9 +72,6 @@
config HAVE_XTENSA_GPIO32
def_bool n
-config MAY_HAVE_SMP
- def_bool n
-
menu "Processor type and features"
choice
@@ -100,7 +98,6 @@
config XTENSA_VARIANT_CUSTOM
bool "Custom Xtensa processor configuration"
- select MAY_HAVE_SMP
select HAVE_XTENSA_GPIO32
help
Select this variant to use a custom Xtensa processor configuration.
@@ -126,10 +123,21 @@
bool "Core variant has a Full MMU (TLB, Pages, Protection, etc)"
depends on XTENSA_VARIANT_CUSTOM
default y
+ select MMU
help
Build a Conventional Kernel with full MMU support,
ie: it supports a TLB with auto-loading, page protection.
+config XTENSA_VARIANT_HAVE_PERF_EVENTS
+ bool "Core variant has Performance Monitor Module"
+ depends on XTENSA_VARIANT_CUSTOM
+ default n
+ help
+ Enable if core variant has Performance Monitor Module with
+ External Registers Interface.
+
+ If unsure, say N.
+
config XTENSA_UNALIGNED_USER
bool "Unaligned memory access in use space"
help
@@ -143,7 +151,7 @@
config HAVE_SMP
bool "System Supports SMP (MX)"
- depends on MAY_HAVE_SMP
+ depends on XTENSA_VARIANT_CUSTOM
select XTENSA_MX
help
This option is use to indicate that the system-on-a-chip (SOC)
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild
index 5b478ac..63c223d 100644
--- a/arch/xtensa/include/asm/Kbuild
+++ b/arch/xtensa/include/asm/Kbuild
@@ -2,7 +2,6 @@
generic-y += bug.h
generic-y += clkdev.h
generic-y += cputime.h
-generic-y += device.h
generic-y += div64.h
generic-y += emergency-restart.h
generic-y += errno.h
diff --git a/arch/xtensa/include/asm/atomic.h b/arch/xtensa/include/asm/atomic.h
index 00b7d46..ebcd1f6 100644
--- a/arch/xtensa/include/asm/atomic.h
+++ b/arch/xtensa/include/asm/atomic.h
@@ -29,7 +29,7 @@
*
* Locking interrupts looks like this:
*
- * rsil a15, LOCKLEVEL
+ * rsil a15, TOPLEVEL
* <code>
* wsr a15, PS
* rsync
@@ -106,7 +106,7 @@
unsigned int vval; \
\
__asm__ __volatile__( \
- " rsil a15, "__stringify(LOCKLEVEL)"\n"\
+ " rsil a15, "__stringify(TOPLEVEL)"\n"\
" l32i %0, %2, 0\n" \
" " #op " %0, %0, %1\n" \
" s32i %0, %2, 0\n" \
@@ -124,7 +124,7 @@
unsigned int vval; \
\
__asm__ __volatile__( \
- " rsil a15,"__stringify(LOCKLEVEL)"\n" \
+ " rsil a15,"__stringify(TOPLEVEL)"\n" \
" l32i %0, %2, 0\n" \
" " #op " %0, %0, %1\n" \
" s32i %0, %2, 0\n" \
@@ -272,7 +272,7 @@
unsigned int vval;
__asm__ __volatile__(
- " rsil a15,"__stringify(LOCKLEVEL)"\n"
+ " rsil a15,"__stringify(TOPLEVEL)"\n"
" l32i %0, %2, 0\n"
" xor %1, %4, %3\n"
" and %0, %0, %4\n"
@@ -306,7 +306,7 @@
unsigned int vval;
__asm__ __volatile__(
- " rsil a15,"__stringify(LOCKLEVEL)"\n"
+ " rsil a15,"__stringify(TOPLEVEL)"\n"
" l32i %0, %2, 0\n"
" or %0, %0, %1\n"
" s32i %0, %2, 0\n"
diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h
index 370b26f..201e900 100644
--- a/arch/xtensa/include/asm/cmpxchg.h
+++ b/arch/xtensa/include/asm/cmpxchg.h
@@ -34,7 +34,7 @@
return new;
#else
__asm__ __volatile__(
- " rsil a15, "__stringify(LOCKLEVEL)"\n"
+ " rsil a15, "__stringify(TOPLEVEL)"\n"
" l32i %0, %1, 0\n"
" bne %0, %2, 1f\n"
" s32i %3, %1, 0\n"
@@ -123,7 +123,7 @@
#else
unsigned long tmp;
__asm__ __volatile__(
- " rsil a15, "__stringify(LOCKLEVEL)"\n"
+ " rsil a15, "__stringify(TOPLEVEL)"\n"
" l32i %0, %1, 0\n"
" s32i %2, %1, 0\n"
" wsr a15, ps\n"
diff --git a/arch/xtensa/include/asm/device.h b/arch/xtensa/include/asm/device.h
new file mode 100644
index 0000000..fe1f5c8
--- /dev/null
+++ b/arch/xtensa/include/asm/device.h
@@ -0,0 +1,19 @@
+/*
+ * Arch specific extensions to struct device
+ *
+ * This file is released under the GPLv2
+ */
+#ifndef _ASM_XTENSA_DEVICE_H
+#define _ASM_XTENSA_DEVICE_H
+
+struct dma_map_ops;
+
+struct dev_archdata {
+ /* DMA operations on that device */
+ struct dma_map_ops *dma_ops;
+};
+
+struct pdev_archdata {
+};
+
+#endif /* _ASM_XTENSA_DEVICE_H */
diff --git a/arch/xtensa/include/asm/dma-mapping.h b/arch/xtensa/include/asm/dma-mapping.h
index 1f5f6dc..f01cb30 100644
--- a/arch/xtensa/include/asm/dma-mapping.h
+++ b/arch/xtensa/include/asm/dma-mapping.h
@@ -1,11 +1,10 @@
/*
- * include/asm-xtensa/dma-mapping.h
- *
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2003 - 2005 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
*/
#ifndef _XTENSA_DMA_MAPPING_H
@@ -13,142 +12,67 @@
#include <asm/cache.h>
#include <asm/io.h>
+
+#include <asm-generic/dma-coherent.h>
+
#include <linux/mm.h>
#include <linux/scatterlist.h>
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
-/*
- * DMA-consistent mapping functions.
- */
+extern struct dma_map_ops xtensa_dma_map_ops;
-extern void *consistent_alloc(int, size_t, dma_addr_t, unsigned long);
-extern void consistent_free(void*, size_t, dma_addr_t);
-extern void consistent_sync(void*, size_t, int);
-
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag);
-
-void dma_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
-
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction direction)
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
- BUG_ON(direction == DMA_NONE);
- consistent_sync(ptr, size, direction);
- return virt_to_phys(ptr);
+ if (dev && dev->archdata.dma_ops)
+ return dev->archdata.dma_ops;
+ else
+ return &xtensa_dma_map_ops;
}
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction direction)
+#include <asm-generic/dma-mapping-common.h>
+
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+#define dma_free_noncoherent(d, s, v, h) dma_free_attrs(d, s, v, h, NULL)
+#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+#define dma_free_coherent(d, s, c, h) dma_free_attrs(d, s, c, h, NULL)
+
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t gfp,
+ struct dma_attrs *attrs)
{
- BUG_ON(direction == DMA_NONE);
+ void *ret;
+ struct dma_map_ops *ops = get_dma_ops(dev);
+
+ if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
+ return ret;
+
+ ret = ops->alloc(dev, size, dma_handle, gfp, attrs);
+ debug_dma_alloc_coherent(dev, size, *dma_handle, ret);
+
+ return ret;
}
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
- enum dma_data_direction direction)
+static inline void dma_free_attrs(struct device *dev, size_t size,
+ void *vaddr, dma_addr_t dma_handle,
+ struct dma_attrs *attrs)
{
- int i;
- struct scatterlist *sg;
+ struct dma_map_ops *ops = get_dma_ops(dev);
- BUG_ON(direction == DMA_NONE);
+ if (dma_release_from_coherent(dev, get_order(size), vaddr))
+ return;
- for_each_sg(sglist, sg, nents, i) {
- BUG_ON(!sg_page(sg));
-
- sg->dma_address = sg_phys(sg);
- consistent_sync(sg_virt(sg), sg->length, direction);
- }
-
- return nents;
+ ops->free(dev, size, vaddr, dma_handle, attrs);
+ debug_dma_free_coherent(dev, size, vaddr, dma_handle);
}
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page, unsigned long offset,
- size_t size, enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
- return (dma_addr_t)(page_to_pfn(page)) * PAGE_SIZE + offset;
-}
-
-static inline void
-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-
-static inline void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
- enum dma_data_direction direction)
-{
- BUG_ON(direction == DMA_NONE);
-}
-
-static inline void
-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
- consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
-}
-
-static inline void
-dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
- size_t size, enum dma_data_direction direction)
-{
- consistent_sync((void *)bus_to_virt(dma_handle), size, direction);
-}
-
-static inline void
-dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
-
- consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction);
-}
-
-static inline void
-dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
-
- consistent_sync((void *)bus_to_virt(dma_handle)+offset,size,direction);
-}
-static inline void
-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist, int nelems,
- enum dma_data_direction dir)
-{
- int i;
- struct scatterlist *sg;
-
- for_each_sg(sglist, sg, nelems, i)
- consistent_sync(sg_virt(sg), sg->length, dir);
-}
-
-static inline void
-dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction dir)
-{
- int i;
- struct scatterlist *sg;
-
- for_each_sg(sglist, sg, nelems, i)
- consistent_sync(sg_virt(sg), sg->length, dir);
-}
static inline int
dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
- return 0;
+ struct dma_map_ops *ops = get_dma_ops(dev);
+
+ debug_dma_mapping_error(dev, dma_addr);
+ return ops->mapping_error(dev, dma_addr);
}
static inline int
@@ -168,39 +92,7 @@
return 0;
}
-static inline void
-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
- enum dma_data_direction direction)
-{
- consistent_sync(vaddr, size, direction);
-}
-
-/* Not supported for now */
-static inline int dma_mmap_coherent(struct device *dev,
- struct vm_area_struct *vma, void *cpu_addr,
- dma_addr_t dma_addr, size_t size)
-{
- return -EINVAL;
-}
-
-static inline int dma_get_sgtable(struct device *dev, struct sg_table *sgt,
- void *cpu_addr, dma_addr_t dma_addr,
- size_t size)
-{
- return -EINVAL;
-}
-
-static inline void *dma_alloc_attrs(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag,
- struct dma_attrs *attrs)
-{
- return NULL;
-}
-
-static inline void dma_free_attrs(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle,
- struct dma_attrs *attrs)
-{
-}
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+ enum dma_data_direction direction);
#endif /* _XTENSA_DMA_MAPPING_H */
diff --git a/arch/xtensa/include/asm/irqflags.h b/arch/xtensa/include/asm/irqflags.h
index ea36674..8e090c7 100644
--- a/arch/xtensa/include/asm/irqflags.h
+++ b/arch/xtensa/include/asm/irqflags.h
@@ -6,6 +6,7 @@
* for more details.
*
* Copyright (C) 2001 - 2005 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
*/
#ifndef _XTENSA_IRQFLAGS_H
@@ -23,8 +24,27 @@
static inline unsigned long arch_local_irq_save(void)
{
unsigned long flags;
- asm volatile("rsil %0, "__stringify(LOCKLEVEL)
+#if XTENSA_FAKE_NMI
+#if defined(CONFIG_DEBUG_KERNEL) && (LOCKLEVEL | TOPLEVEL) >= XCHAL_DEBUGLEVEL
+ unsigned long tmp;
+
+ asm volatile("rsr %0, ps\t\n"
+ "extui %1, %0, 0, 4\t\n"
+ "bgei %1, "__stringify(LOCKLEVEL)", 1f\t\n"
+ "rsil %0, "__stringify(LOCKLEVEL)"\n"
+ "1:"
+ : "=a" (flags), "=a" (tmp) :: "memory");
+#else
+ asm volatile("rsr %0, ps\t\n"
+ "or %0, %0, %1\t\n"
+ "xsr %0, ps\t\n"
+ "rsync"
+ : "=&a" (flags) : "a" (LOCKLEVEL) : "memory");
+#endif
+#else
+ asm volatile("rsil %0, "__stringify(LOCKLEVEL)
: "=a" (flags) :: "memory");
+#endif
return flags;
}
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
index b61bdf0..83e2e4bc 100644
--- a/arch/xtensa/include/asm/processor.h
+++ b/arch/xtensa/include/asm/processor.h
@@ -1,11 +1,10 @@
/*
- * include/asm-xtensa/processor.h
- *
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001 - 2008 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
*/
#ifndef _XTENSA_PROCESSOR_H
@@ -45,6 +44,14 @@
#define STACK_TOP_MAX STACK_TOP
/*
+ * General exception cause assigned to fake NMI. Fake NMI needs to be handled
+ * differently from other interrupts, but it uses common kernel entry/exit
+ * code.
+ */
+
+#define EXCCAUSE_MAPPED_NMI 62
+
+/*
* General exception cause assigned to debug exceptions. Debug exceptions go
* to their own vector, rather than the general exception vectors (user,
* kernel, double); and their specific causes are reported via DEBUGCAUSE
@@ -65,10 +72,30 @@
#define VALID_DOUBLE_EXCEPTION_ADDRESS 64
+#define XTENSA_INT_LEVEL(intno) _XTENSA_INT_LEVEL(intno)
+#define _XTENSA_INT_LEVEL(intno) XCHAL_INT##intno##_LEVEL
+
+#define XTENSA_INTLEVEL_MASK(level) _XTENSA_INTLEVEL_MASK(level)
+#define _XTENSA_INTLEVEL_MASK(level) (XCHAL_INTLEVEL##level##_MASK)
+
+#define IS_POW2(v) (((v) & ((v) - 1)) == 0)
+
+#define PROFILING_INTLEVEL XTENSA_INT_LEVEL(XCHAL_PROFILING_INTERRUPT)
+
/* LOCKLEVEL defines the interrupt level that masks all
* general-purpose interrupts.
*/
+#if defined(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) && \
+ defined(XCHAL_PROFILING_INTERRUPT) && \
+ PROFILING_INTLEVEL == XCHAL_EXCM_LEVEL && \
+ XCHAL_EXCM_LEVEL > 1 && \
+ IS_POW2(XTENSA_INTLEVEL_MASK(PROFILING_INTLEVEL))
+#define LOCKLEVEL (XCHAL_EXCM_LEVEL - 1)
+#else
#define LOCKLEVEL XCHAL_EXCM_LEVEL
+#endif
+#define TOPLEVEL XCHAL_EXCM_LEVEL
+#define XTENSA_FAKE_NMI (LOCKLEVEL < TOPLEVEL)
/* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE
* registers
diff --git a/arch/xtensa/include/asm/stacktrace.h b/arch/xtensa/include/asm/stacktrace.h
index 6a05fcb..fe06e8e 100644
--- a/arch/xtensa/include/asm/stacktrace.h
+++ b/arch/xtensa/include/asm/stacktrace.h
@@ -33,4 +33,12 @@
int (*fn)(struct stackframe *frame, void *data),
void *data);
+void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
+ int (*kfn)(struct stackframe *frame, void *data),
+ int (*ufn)(struct stackframe *frame, void *data),
+ void *data);
+void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
+ int (*ufn)(struct stackframe *frame, void *data),
+ void *data);
+
#endif /* _XTENSA_STACKTRACE_H */
diff --git a/arch/xtensa/include/asm/traps.h b/arch/xtensa/include/asm/traps.h
index 677bfcf..28f33a8 100644
--- a/arch/xtensa/include/asm/traps.h
+++ b/arch/xtensa/include/asm/traps.h
@@ -25,30 +25,39 @@
{
#if XCHAL_NUM_AREGS > 16
__asm__ __volatile__ (
- " call12 1f\n"
+ " call8 1f\n"
" _j 2f\n"
" retw\n"
" .align 4\n"
"1:\n"
+#if XCHAL_NUM_AREGS == 32
+ " _entry a1, 32\n"
+ " addi a8, a0, 3\n"
+ " _entry a1, 16\n"
+ " mov a12, a12\n"
+ " retw\n"
+#else
" _entry a1, 48\n"
- " addi a12, a0, 3\n"
-#if XCHAL_NUM_AREGS > 32
- " .rept (" __stringify(XCHAL_NUM_AREGS) " - 32) / 12\n"
+ " call12 1f\n"
+ " retw\n"
+ " .align 4\n"
+ "1:\n"
+ " .rept (" __stringify(XCHAL_NUM_AREGS) " - 16) / 12\n"
" _entry a1, 48\n"
" mov a12, a0\n"
" .endr\n"
-#endif
- " _entry a1, 48\n"
+ " _entry a1, 16\n"
#if XCHAL_NUM_AREGS % 12 == 0
- " mov a8, a8\n"
-#elif XCHAL_NUM_AREGS % 12 == 4
" mov a12, a12\n"
-#elif XCHAL_NUM_AREGS % 12 == 8
+#elif XCHAL_NUM_AREGS % 12 == 4
" mov a4, a4\n"
+#elif XCHAL_NUM_AREGS % 12 == 8
+ " mov a8, a8\n"
#endif
" retw\n"
+#endif
"2:\n"
- : : : "a12", "a13", "memory");
+ : : : "a8", "a9", "memory");
#else
__asm__ __volatile__ (
" mov a12, a12\n"
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile
index d3a0f0f..50137bc 100644
--- a/arch/xtensa/kernel/Makefile
+++ b/arch/xtensa/kernel/Makefile
@@ -13,6 +13,7 @@
obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o
obj-$(CONFIG_FUNCTION_TRACER) += mcount.o
obj-$(CONFIG_SMP) += smp.o mxhead.o
+obj-$(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) += perf_event.o
AFLAGS_head.o += -mtext-section-literals
@@ -27,10 +28,11 @@
#
# Replicate rules in scripts/Makefile.build
-sed-y = -e 's/\*(\(\.[a-z]*it\|\.ref\|\)\.text)/*(\1.literal \1.text)/g' \
- -e 's/\.text\.unlikely/.literal.unlikely .text.unlikely/g' \
- -e 's/\*(\(\.text .*\))/*(.literal \1)/g' \
- -e 's/\*(\(\.text\.[a-z]*\))/*(\1.literal \1)/g'
+sed-y = -e ':a; s/\*(\([^)]*\)\.text\.unlikely/*(\1.literal.unlikely .{text}.unlikely/; ta; ' \
+ -e ':b; s/\*(\([^)]*\)\.text\(\.[a-z]*\)/*(\1.{text}\2.literal .{text}\2/; tb; ' \
+ -e ':c; s/\*(\([^)]*\)\(\.[a-z]*it\|\.ref\)\.text/*(\1\2.literal \2.{text}/; tc; ' \
+ -e ':d; s/\*(\([^)]\+ \|\)\.text/*(\1.literal .{text}/; td; ' \
+ -e 's/\.{text}/.text/g'
quiet_cmd__cpp_lds_S = LDS $@
cmd__cpp_lds_S = $(CPP) $(cpp_flags) -P -C -Uxtensa -D__ASSEMBLY__ $< \
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 82bbfa5..5041303 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -1,6 +1,4 @@
/*
- * arch/xtensa/kernel/entry.S
- *
* Low-level exception handling
*
* This file is subject to the terms and conditions of the GNU General Public
@@ -8,6 +6,7 @@
* for more details.
*
* Copyright (C) 2004 - 2008 by Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
*
* Chris Zankel <chris@zankel.net>
*
@@ -75,6 +74,27 @@
#endif
.endm
+
+ .macro irq_save flags tmp
+#if XTENSA_FAKE_NMI
+#if defined(CONFIG_DEBUG_KERNEL) && (LOCKLEVEL | TOPLEVEL) >= XCHAL_DEBUGLEVEL
+ rsr \flags, ps
+ extui \tmp, \flags, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
+ bgei \tmp, LOCKLEVEL, 99f
+ rsil \tmp, LOCKLEVEL
+99:
+#else
+ movi \tmp, LOCKLEVEL
+ rsr \flags, ps
+ or \flags, \flags, \tmp
+ xsr \flags, ps
+ rsync
+#endif
+#else
+ rsil \flags, LOCKLEVEL
+#endif
+ .endm
+
/* ----------------- DEFAULT FIRST LEVEL EXCEPTION HANDLERS ----------------- */
/*
@@ -122,6 +142,7 @@
/* Save SAR and turn off single stepping */
movi a2, 0
+ wsr a2, depc # terminate user stack trace with 0
rsr a3, sar
xsr a2, icountlevel
s32i a3, a1, PT_SAR
@@ -301,7 +322,18 @@
s32i a14, a1, PT_AREG14
s32i a15, a1, PT_AREG15
+ _bnei a2, 1, 1f
+
+ /* Copy spill slots of a0 and a1 to imitate movsp
+ * in order to keep exception stack continuous
+ */
+ l32i a3, a1, PT_SIZE
+ l32i a0, a1, PT_SIZE + 4
+ s32e a3, a1, -16
+ s32e a0, a1, -12
1:
+ l32i a0, a1, PT_AREG0 # restore saved a0
+ wsr a0, depc
#ifdef KERNEL_STACK_OVERFLOW_CHECK
@@ -340,75 +372,88 @@
/* It is now save to restore the EXC_TABLE_FIXUP variable. */
- rsr a0, exccause
+ rsr a2, exccause
movi a3, 0
- rsr a2, excsave1
- s32i a0, a1, PT_EXCCAUSE
- s32i a3, a2, EXC_TABLE_FIXUP
+ rsr a0, excsave1
+ s32i a2, a1, PT_EXCCAUSE
+ s32i a3, a0, EXC_TABLE_FIXUP
- /* All unrecoverable states are saved on stack, now, and a1 is valid,
- * so we can allow exceptions and interrupts (*) again.
- * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
+ /* All unrecoverable states are saved on stack, now, and a1 is valid.
+ * Now we can allow exceptions again. In case we've got an interrupt
+ * PS.INTLEVEL is set to LOCKLEVEL disabling furhter interrupts,
+ * otherwise it's left unchanged.
*
- * (*) We only allow interrupts if they were previously enabled and
- * we're not handling an IRQ
+ * Set PS(EXCM = 0, UM = 0, RING = 0, OWB = 0, WOE = 1, INTLEVEL = X)
*/
rsr a3, ps
- addi a0, a0, -EXCCAUSE_LEVEL1_INTERRUPT
- movi a2, LOCKLEVEL
+ s32i a3, a1, PT_PS # save ps
+
+#if XTENSA_FAKE_NMI
+ /* Correct PS needs to be saved in the PT_PS:
+ * - in case of exception or level-1 interrupt it's in the PS,
+ * and is already saved.
+ * - in case of medium level interrupt it's in the excsave2.
+ */
+ movi a0, EXCCAUSE_MAPPED_NMI
+ extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
+ beq a2, a0, .Lmedium_level_irq
+ bnei a2, EXCCAUSE_LEVEL1_INTERRUPT, .Lexception
+ beqz a3, .Llevel1_irq # level-1 IRQ sets ps.intlevel to 0
+
+.Lmedium_level_irq:
+ rsr a0, excsave2
+ s32i a0, a1, PT_PS # save medium-level interrupt ps
+ bgei a3, LOCKLEVEL, .Lexception
+
+.Llevel1_irq:
+ movi a3, LOCKLEVEL
+
+.Lexception:
+ movi a0, 1 << PS_WOE_BIT
+ or a3, a3, a0
+#else
+ addi a2, a2, -EXCCAUSE_LEVEL1_INTERRUPT
+ movi a0, LOCKLEVEL
extui a3, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
# a3 = PS.INTLEVEL
- moveqz a3, a2, a0 # a3 = LOCKLEVEL iff interrupt
+ moveqz a3, a0, a2 # a3 = LOCKLEVEL iff interrupt
movi a2, 1 << PS_WOE_BIT
or a3, a3, a2
- rsr a0, exccause
- xsr a3, ps
+ rsr a2, exccause
+#endif
- s32i a3, a1, PT_PS # save ps
+ /* restore return address (or 0 if return to userspace) */
+ rsr a0, depc
+ wsr a3, ps
+ rsync # PS.WOE => rsync => overflow
/* Save lbeg, lend */
- rsr a2, lbeg
+ rsr a4, lbeg
rsr a3, lend
- s32i a2, a1, PT_LBEG
+ s32i a4, a1, PT_LBEG
s32i a3, a1, PT_LEND
/* Save SCOMPARE1 */
#if XCHAL_HAVE_S32C1I
- rsr a2, scompare1
- s32i a2, a1, PT_SCOMPARE1
+ rsr a3, scompare1
+ s32i a3, a1, PT_SCOMPARE1
#endif
/* Save optional registers. */
- save_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT
+ save_xtregs_opt a1 a3 a4 a5 a6 a7 PT_XTREGS_OPT
-#ifdef CONFIG_TRACE_IRQFLAGS
- l32i a4, a1, PT_DEPC
- /* Double exception means we came here with an exception
- * while PS.EXCM was set, i.e. interrupts disabled.
- */
- bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
- l32i a4, a1, PT_EXCCAUSE
- bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
- /* We came here with an interrupt means interrupts were enabled
- * and we've just disabled them.
- */
- movi a4, trace_hardirqs_off
- callx4 a4
-1:
-#endif
-
/* Go to second-level dispatcher. Set up parameters to pass to the
* exception handler and call the exception handler.
*/
rsr a4, excsave1
mov a6, a1 # pass stack frame
- mov a7, a0 # pass EXCCAUSE
- addx4 a4, a0, a4
+ mov a7, a2 # pass EXCCAUSE
+ addx4 a4, a2, a4
l32i a4, a4, EXC_TABLE_DEFAULT # load handler
/* Call the second-level handler */
@@ -419,8 +464,17 @@
.global common_exception_return
common_exception_return:
+#if XTENSA_FAKE_NMI
+ l32i a2, a1, PT_EXCCAUSE
+ movi a3, EXCCAUSE_MAPPED_NMI
+ beq a2, a3, .LNMIexit
+#endif
1:
- rsil a2, LOCKLEVEL
+ irq_save a2, a3
+#ifdef CONFIG_TRACE_IRQFLAGS
+ movi a4, trace_hardirqs_off
+ callx4 a4
+#endif
/* Jump if we are returning from kernel exceptions. */
@@ -445,6 +499,10 @@
/* Call do_signal() */
+#ifdef CONFIG_TRACE_IRQFLAGS
+ movi a4, trace_hardirqs_on
+ callx4 a4
+#endif
rsil a2, 0
movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*)
mov a6, a1
@@ -453,6 +511,10 @@
3: /* Reschedule */
+#ifdef CONFIG_TRACE_IRQFLAGS
+ movi a4, trace_hardirqs_on
+ callx4 a4
+#endif
rsil a2, 0
movi a4, schedule # void schedule (void)
callx4 a4
@@ -471,6 +533,12 @@
j 1b
#endif
+#if XTENSA_FAKE_NMI
+.LNMIexit:
+ l32i a3, a1, PT_PS
+ _bbci.l a3, PS_UM_BIT, 4f
+#endif
+
5:
#ifdef CONFIG_DEBUG_TLB_SANITY
l32i a4, a1, PT_DEPC
@@ -481,16 +549,8 @@
6:
4:
#ifdef CONFIG_TRACE_IRQFLAGS
- l32i a4, a1, PT_DEPC
- /* Double exception means we came here with an exception
- * while PS.EXCM was set, i.e. interrupts disabled.
- */
- bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 1f
- l32i a4, a1, PT_EXCCAUSE
- bnei a4, EXCCAUSE_LEVEL1_INTERRUPT, 1f
- /* We came here with an interrupt means interrupts were enabled
- * and we'll reenable them on return.
- */
+ extui a4, a3, PS_INTLEVEL_SHIFT, PS_INTLEVEL_WIDTH
+ bgei a4, LOCKLEVEL, 1f
movi a4, trace_hardirqs_on
callx4 a4
1:
@@ -568,12 +628,13 @@
* (if we have restored WSBITS-1 frames).
*/
+2:
#if XCHAL_HAVE_THREADPTR
l32i a3, a1, PT_THREADPTR
wur a3, threadptr
#endif
-2: j common_exception_exit
+ j common_exception_exit
/* This is the kernel exception exit.
* We avoided to do a MOVSP when we entered the exception, but we
@@ -1561,6 +1622,13 @@
rfde
9: l32i a0, a1, TASK_ACTIVE_MM # unlikely case mm == 0
+ bnez a0, 8b
+
+ /* Even more unlikely case active_mm == 0.
+ * We can get here with NMI in the middle of context_switch that
+ * touches vmalloc area.
+ */
+ movi a0, init_mm
j 8b
#if (DCACHE_WAY_SIZE > PAGE_SIZE)
@@ -1820,7 +1888,7 @@
mov a12, a0
.endr
#endif
- _entry a1, 48
+ _entry a1, 16
#if XCHAL_NUM_AREGS % 12 == 0
mov a8, a8
#elif XCHAL_NUM_AREGS % 12 == 4
@@ -1844,7 +1912,7 @@
ENTRY(_switch_to)
- entry a1, 16
+ entry a1, 48
mov a11, a3 # and 'next' (a3)
@@ -1864,10 +1932,8 @@
/* Disable ints while we manipulate the stack pointer. */
- rsil a14, LOCKLEVEL
- rsr a3, excsave1
+ irq_save a14, a3
rsync
- s32i a3, a3, EXC_TABLE_FIXUP /* enter critical section */
/* Switch CPENABLE */
@@ -1888,9 +1954,7 @@
*/
rsr a3, excsave1 # exc_table
- movi a6, 0
addi a7, a5, PT_REGS_OFFSET
- s32i a6, a3, EXC_TABLE_FIXUP
s32i a7, a3, EXC_TABLE_KSTK
/* restore context of the task 'next' */
diff --git a/arch/xtensa/kernel/irq.c b/arch/xtensa/kernel/irq.c
index 3eee94f..6df31ca 100644
--- a/arch/xtensa/kernel/irq.c
+++ b/arch/xtensa/kernel/irq.c
@@ -28,7 +28,7 @@
#include <asm/uaccess.h>
#include <asm/platform.h>
-atomic_t irq_err_count;
+DECLARE_PER_CPU(unsigned long, nmi_count);
asmlinkage void do_IRQ(int hwirq, struct pt_regs *regs)
{
@@ -57,11 +57,16 @@
int arch_show_interrupts(struct seq_file *p, int prec)
{
+ unsigned cpu __maybe_unused;
#ifdef CONFIG_SMP
show_ipi_list(p, prec);
#endif
- seq_printf(p, "%*s: ", prec, "ERR");
- seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
+#if XTENSA_FAKE_NMI
+ seq_printf(p, "%*s:", prec, "NMI");
+ for_each_online_cpu(cpu)
+ seq_printf(p, " %10lu", per_cpu(nmi_count, cpu));
+ seq_puts(p, " Non-maskable interrupts\n");
+#endif
return 0;
}
@@ -106,6 +111,12 @@
irq_set_chip_and_handler_name(irq, irq_chip,
handle_percpu_irq, "timer");
irq_clear_status_flags(irq, IRQ_LEVEL);
+#ifdef XCHAL_INTTYPE_MASK_PROFILING
+ } else if (mask & XCHAL_INTTYPE_MASK_PROFILING) {
+ irq_set_chip_and_handler_name(irq, irq_chip,
+ handle_percpu_irq, "profiling");
+ irq_set_status_flags(irq, IRQ_LEVEL);
+#endif
} else {/* XCHAL_INTTYPE_MASK_WRITE_ERROR */
/* XCHAL_INTTYPE_MASK_NMI */
irq_set_chip_and_handler_name(irq, irq_chip,
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c
index e8b76b8..fb75ebf 100644
--- a/arch/xtensa/kernel/pci-dma.c
+++ b/arch/xtensa/kernel/pci-dma.c
@@ -1,6 +1,4 @@
/*
- * arch/xtensa/kernel/pci-dma.c
- *
* DMA coherent memory allocation.
*
* This program is free software; you can redistribute it and/or modify it
@@ -9,6 +7,7 @@
* option) any later version.
*
* Copyright (C) 2002 - 2005 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
*
* Based on version for i386.
*
@@ -25,13 +24,107 @@
#include <asm/io.h>
#include <asm/cacheflush.h>
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+ enum dma_data_direction dir)
+{
+ switch (dir) {
+ case DMA_BIDIRECTIONAL:
+ __flush_invalidate_dcache_range((unsigned long)vaddr, size);
+ break;
+
+ case DMA_FROM_DEVICE:
+ __invalidate_dcache_range((unsigned long)vaddr, size);
+ break;
+
+ case DMA_TO_DEVICE:
+ __flush_dcache_range((unsigned long)vaddr, size);
+ break;
+
+ case DMA_NONE:
+ BUG();
+ break;
+ }
+}
+EXPORT_SYMBOL(dma_cache_sync);
+
+static void xtensa_sync_single_for_cpu(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ void *vaddr;
+
+ switch (dir) {
+ case DMA_BIDIRECTIONAL:
+ case DMA_FROM_DEVICE:
+ vaddr = bus_to_virt(dma_handle);
+ __invalidate_dcache_range((unsigned long)vaddr, size);
+ break;
+
+ case DMA_NONE:
+ BUG();
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void xtensa_sync_single_for_device(struct device *dev,
+ dma_addr_t dma_handle, size_t size,
+ enum dma_data_direction dir)
+{
+ void *vaddr;
+
+ switch (dir) {
+ case DMA_BIDIRECTIONAL:
+ case DMA_TO_DEVICE:
+ vaddr = bus_to_virt(dma_handle);
+ __flush_dcache_range((unsigned long)vaddr, size);
+ break;
+
+ case DMA_NONE:
+ BUG();
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void xtensa_sync_sg_for_cpu(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+ xtensa_sync_single_for_cpu(dev, sg_dma_address(s),
+ sg_dma_len(s), dir);
+ }
+}
+
+static void xtensa_sync_sg_for_device(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+ xtensa_sync_single_for_device(dev, sg_dma_address(s),
+ sg_dma_len(s), dir);
+ }
+}
+
/*
* Note: We assume that the full memory space is always mapped to 'kseg'
* Otherwise we have to use page attributes (not implemented).
*/
-void *
-dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag)
+static void *xtensa_dma_alloc(struct device *dev, size_t size,
+ dma_addr_t *handle, gfp_t flag,
+ struct dma_attrs *attrs)
{
unsigned long ret;
unsigned long uncached = 0;
@@ -52,20 +145,15 @@
BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR ||
ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1);
+ uncached = ret + XCHAL_KSEG_BYPASS_VADDR - XCHAL_KSEG_CACHED_VADDR;
+ *handle = virt_to_bus((void *)ret);
+ __invalidate_dcache_range(ret, size);
- if (ret != 0) {
- memset((void*) ret, 0, size);
- uncached = ret+XCHAL_KSEG_BYPASS_VADDR-XCHAL_KSEG_CACHED_VADDR;
- *handle = virt_to_bus((void*)ret);
- __flush_invalidate_dcache_range(ret, size);
- }
-
- return (void*)uncached;
+ return (void *)uncached;
}
-EXPORT_SYMBOL(dma_alloc_coherent);
-void dma_free_coherent(struct device *hwdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
+static void xtensa_dma_free(struct device *hwdev, size_t size, void *vaddr,
+ dma_addr_t dma_handle, struct dma_attrs *attrs)
{
unsigned long addr = (unsigned long)vaddr +
XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR;
@@ -75,24 +163,79 @@
free_pages(addr, get_order(size));
}
-EXPORT_SYMBOL(dma_free_coherent);
-
-void consistent_sync(void *vaddr, size_t size, int direction)
+static dma_addr_t xtensa_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
- switch (direction) {
- case PCI_DMA_NONE:
- BUG();
- case PCI_DMA_FROMDEVICE: /* invalidate only */
- __invalidate_dcache_range((unsigned long)vaddr,
- (unsigned long)size);
- break;
+ dma_addr_t dma_handle = page_to_phys(page) + offset;
- case PCI_DMA_TODEVICE: /* writeback only */
- case PCI_DMA_BIDIRECTIONAL: /* writeback and invalidate */
- __flush_invalidate_dcache_range((unsigned long)vaddr,
- (unsigned long)size);
- break;
+ BUG_ON(PageHighMem(page));
+ xtensa_sync_single_for_device(dev, dma_handle, size, dir);
+ return dma_handle;
+}
+
+static void xtensa_unmap_page(struct device *dev, dma_addr_t dma_handle,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ xtensa_sync_single_for_cpu(dev, dma_handle, size, dir);
+}
+
+static int xtensa_map_sg(struct device *dev, struct scatterlist *sg,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+ s->dma_address = xtensa_map_page(dev, sg_page(s), s->offset,
+ s->length, dir, attrs);
+ }
+ return nents;
+}
+
+static void xtensa_unmap_sg(struct device *dev,
+ struct scatterlist *sg, int nents,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(sg, s, nents, i) {
+ xtensa_unmap_page(dev, sg_dma_address(s),
+ sg_dma_len(s), dir, attrs);
}
}
-EXPORT_SYMBOL(consistent_sync);
+
+int xtensa_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+ return 0;
+}
+
+struct dma_map_ops xtensa_dma_map_ops = {
+ .alloc = xtensa_dma_alloc,
+ .free = xtensa_dma_free,
+ .map_page = xtensa_map_page,
+ .unmap_page = xtensa_unmap_page,
+ .map_sg = xtensa_map_sg,
+ .unmap_sg = xtensa_unmap_sg,
+ .sync_single_for_cpu = xtensa_sync_single_for_cpu,
+ .sync_single_for_device = xtensa_sync_single_for_device,
+ .sync_sg_for_cpu = xtensa_sync_sg_for_cpu,
+ .sync_sg_for_device = xtensa_sync_sg_for_device,
+ .mapping_error = xtensa_dma_mapping_error,
+};
+EXPORT_SYMBOL(xtensa_dma_map_ops);
+
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16)
+
+static int __init xtensa_dma_init(void)
+{
+ dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+ return 0;
+}
+fs_initcall(xtensa_dma_init);
diff --git a/arch/xtensa/kernel/perf_event.c b/arch/xtensa/kernel/perf_event.c
new file mode 100644
index 0000000..54f0118
--- /dev/null
+++ b/arch/xtensa/kernel/perf_event.c
@@ -0,0 +1,454 @@
+/*
+ * Xtensa Performance Monitor Module driver
+ * See Tensilica Debug User's Guide for PMU registers documentation.
+ *
+ * Copyright (C) 2015 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/perf_event.h>
+#include <linux/platform_device.h>
+
+#include <asm/processor.h>
+#include <asm/stacktrace.h>
+
+/* Global control/status for all perf counters */
+#define XTENSA_PMU_PMG 0x1000
+/* Perf counter values */
+#define XTENSA_PMU_PM(i) (0x1080 + (i) * 4)
+/* Perf counter control registers */
+#define XTENSA_PMU_PMCTRL(i) (0x1100 + (i) * 4)
+/* Perf counter status registers */
+#define XTENSA_PMU_PMSTAT(i) (0x1180 + (i) * 4)
+
+#define XTENSA_PMU_PMG_PMEN 0x1
+
+#define XTENSA_PMU_COUNTER_MASK 0xffffffffULL
+#define XTENSA_PMU_COUNTER_MAX 0x7fffffff
+
+#define XTENSA_PMU_PMCTRL_INTEN 0x00000001
+#define XTENSA_PMU_PMCTRL_KRNLCNT 0x00000008
+#define XTENSA_PMU_PMCTRL_TRACELEVEL 0x000000f0
+#define XTENSA_PMU_PMCTRL_SELECT_SHIFT 8
+#define XTENSA_PMU_PMCTRL_SELECT 0x00001f00
+#define XTENSA_PMU_PMCTRL_MASK_SHIFT 16
+#define XTENSA_PMU_PMCTRL_MASK 0xffff0000
+
+#define XTENSA_PMU_MASK(select, mask) \
+ (((select) << XTENSA_PMU_PMCTRL_SELECT_SHIFT) | \
+ ((mask) << XTENSA_PMU_PMCTRL_MASK_SHIFT) | \
+ XTENSA_PMU_PMCTRL_TRACELEVEL | \
+ XTENSA_PMU_PMCTRL_INTEN)
+
+#define XTENSA_PMU_PMSTAT_OVFL 0x00000001
+#define XTENSA_PMU_PMSTAT_INTASRT 0x00000010
+
+struct xtensa_pmu_events {
+ /* Array of events currently on this core */
+ struct perf_event *event[XCHAL_NUM_PERF_COUNTERS];
+ /* Bitmap of used hardware counters */
+ unsigned long used_mask[BITS_TO_LONGS(XCHAL_NUM_PERF_COUNTERS)];
+};
+static DEFINE_PER_CPU(struct xtensa_pmu_events, xtensa_pmu_events);
+
+static const u32 xtensa_hw_ctl[] = {
+ [PERF_COUNT_HW_CPU_CYCLES] = XTENSA_PMU_MASK(0, 0x1),
+ [PERF_COUNT_HW_INSTRUCTIONS] = XTENSA_PMU_MASK(2, 0xffff),
+ [PERF_COUNT_HW_CACHE_REFERENCES] = XTENSA_PMU_MASK(10, 0x1),
+ [PERF_COUNT_HW_CACHE_MISSES] = XTENSA_PMU_MASK(12, 0x1),
+ /* Taken and non-taken branches + taken loop ends */
+ [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = XTENSA_PMU_MASK(2, 0x490),
+ /* Instruction-related + other global stall cycles */
+ [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = XTENSA_PMU_MASK(4, 0x1ff),
+ /* Data-related global stall cycles */
+ [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = XTENSA_PMU_MASK(3, 0x1ff),
+};
+
+#define C(_x) PERF_COUNT_HW_CACHE_##_x
+
+static const u32 xtensa_cache_ctl[][C(OP_MAX)][C(RESULT_MAX)] = {
+ [C(L1D)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = XTENSA_PMU_MASK(10, 0x1),
+ [C(RESULT_MISS)] = XTENSA_PMU_MASK(10, 0x2),
+ },
+ [C(OP_WRITE)] = {
+ [C(RESULT_ACCESS)] = XTENSA_PMU_MASK(11, 0x1),
+ [C(RESULT_MISS)] = XTENSA_PMU_MASK(11, 0x2),
+ },
+ },
+ [C(L1I)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = XTENSA_PMU_MASK(8, 0x1),
+ [C(RESULT_MISS)] = XTENSA_PMU_MASK(8, 0x2),
+ },
+ },
+ [C(DTLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = XTENSA_PMU_MASK(9, 0x1),
+ [C(RESULT_MISS)] = XTENSA_PMU_MASK(9, 0x8),
+ },
+ },
+ [C(ITLB)] = {
+ [C(OP_READ)] = {
+ [C(RESULT_ACCESS)] = XTENSA_PMU_MASK(7, 0x1),
+ [C(RESULT_MISS)] = XTENSA_PMU_MASK(7, 0x8),
+ },
+ },
+};
+
+static int xtensa_pmu_cache_event(u64 config)
+{
+ unsigned int cache_type, cache_op, cache_result;
+ int ret;
+
+ cache_type = (config >> 0) & 0xff;
+ cache_op = (config >> 8) & 0xff;
+ cache_result = (config >> 16) & 0xff;
+
+ if (cache_type >= ARRAY_SIZE(xtensa_cache_ctl) ||
+ cache_op >= C(OP_MAX) ||
+ cache_result >= C(RESULT_MAX))
+ return -EINVAL;
+
+ ret = xtensa_cache_ctl[cache_type][cache_op][cache_result];
+
+ if (ret == 0)
+ return -EINVAL;
+
+ return ret;
+}
+
+static inline uint32_t xtensa_pmu_read_counter(int idx)
+{
+ return get_er(XTENSA_PMU_PM(idx));
+}
+
+static inline void xtensa_pmu_write_counter(int idx, uint32_t v)
+{
+ set_er(v, XTENSA_PMU_PM(idx));
+}
+
+static void xtensa_perf_event_update(struct perf_event *event,
+ struct hw_perf_event *hwc, int idx)
+{
+ uint64_t prev_raw_count, new_raw_count;
+ int64_t delta;
+
+ do {
+ prev_raw_count = local64_read(&hwc->prev_count);
+ new_raw_count = xtensa_pmu_read_counter(event->hw.idx);
+ } while (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
+ new_raw_count) != prev_raw_count);
+
+ delta = (new_raw_count - prev_raw_count) & XTENSA_PMU_COUNTER_MASK;
+
+ local64_add(delta, &event->count);
+ local64_sub(delta, &hwc->period_left);
+}
+
+static bool xtensa_perf_event_set_period(struct perf_event *event,
+ struct hw_perf_event *hwc, int idx)
+{
+ bool rc = false;
+ s64 left;
+
+ if (!is_sampling_event(event)) {
+ left = XTENSA_PMU_COUNTER_MAX;
+ } else {
+ s64 period = hwc->sample_period;
+
+ left = local64_read(&hwc->period_left);
+ if (left <= -period) {
+ left = period;
+ local64_set(&hwc->period_left, left);
+ hwc->last_period = period;
+ rc = true;
+ } else if (left <= 0) {
+ left += period;
+ local64_set(&hwc->period_left, left);
+ hwc->last_period = period;
+ rc = true;
+ }
+ if (left > XTENSA_PMU_COUNTER_MAX)
+ left = XTENSA_PMU_COUNTER_MAX;
+ }
+
+ local64_set(&hwc->prev_count, -left);
+ xtensa_pmu_write_counter(idx, -left);
+ perf_event_update_userpage(event);
+
+ return rc;
+}
+
+static void xtensa_pmu_enable(struct pmu *pmu)
+{
+ set_er(get_er(XTENSA_PMU_PMG) | XTENSA_PMU_PMG_PMEN, XTENSA_PMU_PMG);
+}
+
+static void xtensa_pmu_disable(struct pmu *pmu)
+{
+ set_er(get_er(XTENSA_PMU_PMG) & ~XTENSA_PMU_PMG_PMEN, XTENSA_PMU_PMG);
+}
+
+static int xtensa_pmu_event_init(struct perf_event *event)
+{
+ int ret;
+
+ switch (event->attr.type) {
+ case PERF_TYPE_HARDWARE:
+ if (event->attr.config >= ARRAY_SIZE(xtensa_hw_ctl) ||
+ xtensa_hw_ctl[event->attr.config] == 0)
+ return -EINVAL;
+ event->hw.config = xtensa_hw_ctl[event->attr.config];
+ return 0;
+
+ case PERF_TYPE_HW_CACHE:
+ ret = xtensa_pmu_cache_event(event->attr.config);
+ if (ret < 0)
+ return ret;
+ event->hw.config = ret;
+ return 0;
+
+ case PERF_TYPE_RAW:
+ /* Not 'previous counter' select */
+ if ((event->attr.config & XTENSA_PMU_PMCTRL_SELECT) ==
+ (1 << XTENSA_PMU_PMCTRL_SELECT_SHIFT))
+ return -EINVAL;
+ event->hw.config = (event->attr.config &
+ (XTENSA_PMU_PMCTRL_KRNLCNT |
+ XTENSA_PMU_PMCTRL_TRACELEVEL |
+ XTENSA_PMU_PMCTRL_SELECT |
+ XTENSA_PMU_PMCTRL_MASK)) |
+ XTENSA_PMU_PMCTRL_INTEN;
+ return 0;
+
+ default:
+ return -ENOENT;
+ }
+}
+
+/*
+ * Starts/Stops a counter present on the PMU. The PMI handler
+ * should stop the counter when perf_event_overflow() returns
+ * !0. ->start() will be used to continue.
+ */
+static void xtensa_pmu_start(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+
+ if (WARN_ON_ONCE(idx == -1))
+ return;
+
+ if (flags & PERF_EF_RELOAD) {
+ WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
+ xtensa_perf_event_set_period(event, hwc, idx);
+ }
+
+ hwc->state = 0;
+
+ set_er(hwc->config, XTENSA_PMU_PMCTRL(idx));
+}
+
+static void xtensa_pmu_stop(struct perf_event *event, int flags)
+{
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+
+ if (!(hwc->state & PERF_HES_STOPPED)) {
+ set_er(0, XTENSA_PMU_PMCTRL(idx));
+ set_er(get_er(XTENSA_PMU_PMSTAT(idx)),
+ XTENSA_PMU_PMSTAT(idx));
+ hwc->state |= PERF_HES_STOPPED;
+ }
+
+ if ((flags & PERF_EF_UPDATE) &&
+ !(event->hw.state & PERF_HES_UPTODATE)) {
+ xtensa_perf_event_update(event, &event->hw, idx);
+ event->hw.state |= PERF_HES_UPTODATE;
+ }
+}
+
+/*
+ * Adds/Removes a counter to/from the PMU, can be done inside
+ * a transaction, see the ->*_txn() methods.
+ */
+static int xtensa_pmu_add(struct perf_event *event, int flags)
+{
+ struct xtensa_pmu_events *ev = this_cpu_ptr(&xtensa_pmu_events);
+ struct hw_perf_event *hwc = &event->hw;
+ int idx = hwc->idx;
+
+ if (__test_and_set_bit(idx, ev->used_mask)) {
+ idx = find_first_zero_bit(ev->used_mask,
+ XCHAL_NUM_PERF_COUNTERS);
+ if (idx == XCHAL_NUM_PERF_COUNTERS)
+ return -EAGAIN;
+
+ __set_bit(idx, ev->used_mask);
+ hwc->idx = idx;
+ }
+ ev->event[idx] = event;
+
+ hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+
+ if (flags & PERF_EF_START)
+ xtensa_pmu_start(event, PERF_EF_RELOAD);
+
+ perf_event_update_userpage(event);
+ return 0;
+}
+
+static void xtensa_pmu_del(struct perf_event *event, int flags)
+{
+ struct xtensa_pmu_events *ev = this_cpu_ptr(&xtensa_pmu_events);
+
+ xtensa_pmu_stop(event, PERF_EF_UPDATE);
+ __clear_bit(event->hw.idx, ev->used_mask);
+ perf_event_update_userpage(event);
+}
+
+static void xtensa_pmu_read(struct perf_event *event)
+{
+ xtensa_perf_event_update(event, &event->hw, event->hw.idx);
+}
+
+static int callchain_trace(struct stackframe *frame, void *data)
+{
+ struct perf_callchain_entry *entry = data;
+
+ perf_callchain_store(entry, frame->pc);
+ return 0;
+}
+
+void perf_callchain_kernel(struct perf_callchain_entry *entry,
+ struct pt_regs *regs)
+{
+ xtensa_backtrace_kernel(regs, PERF_MAX_STACK_DEPTH,
+ callchain_trace, NULL, entry);
+}
+
+void perf_callchain_user(struct perf_callchain_entry *entry,
+ struct pt_regs *regs)
+{
+ xtensa_backtrace_user(regs, PERF_MAX_STACK_DEPTH,
+ callchain_trace, entry);
+}
+
+void perf_event_print_debug(void)
+{
+ unsigned long flags;
+ unsigned i;
+
+ local_irq_save(flags);
+ pr_info("CPU#%d: PMG: 0x%08lx\n", smp_processor_id(),
+ get_er(XTENSA_PMU_PMG));
+ for (i = 0; i < XCHAL_NUM_PERF_COUNTERS; ++i)
+ pr_info("PM%d: 0x%08lx, PMCTRL%d: 0x%08lx, PMSTAT%d: 0x%08lx\n",
+ i, get_er(XTENSA_PMU_PM(i)),
+ i, get_er(XTENSA_PMU_PMCTRL(i)),
+ i, get_er(XTENSA_PMU_PMSTAT(i)));
+ local_irq_restore(flags);
+}
+
+irqreturn_t xtensa_pmu_irq_handler(int irq, void *dev_id)
+{
+ irqreturn_t rc = IRQ_NONE;
+ struct xtensa_pmu_events *ev = this_cpu_ptr(&xtensa_pmu_events);
+ unsigned i;
+
+ for (i = find_first_bit(ev->used_mask, XCHAL_NUM_PERF_COUNTERS);
+ i < XCHAL_NUM_PERF_COUNTERS;
+ i = find_next_bit(ev->used_mask, XCHAL_NUM_PERF_COUNTERS, i + 1)) {
+ uint32_t v = get_er(XTENSA_PMU_PMSTAT(i));
+ struct perf_event *event = ev->event[i];
+ struct hw_perf_event *hwc = &event->hw;
+ u64 last_period;
+
+ if (!(v & XTENSA_PMU_PMSTAT_OVFL))
+ continue;
+
+ set_er(v, XTENSA_PMU_PMSTAT(i));
+ xtensa_perf_event_update(event, hwc, i);
+ last_period = hwc->last_period;
+ if (xtensa_perf_event_set_period(event, hwc, i)) {
+ struct perf_sample_data data;
+ struct pt_regs *regs = get_irq_regs();
+
+ perf_sample_data_init(&data, 0, last_period);
+ if (perf_event_overflow(event, &data, regs))
+ xtensa_pmu_stop(event, 0);
+ }
+
+ rc = IRQ_HANDLED;
+ }
+ return rc;
+}
+
+static struct pmu xtensa_pmu = {
+ .pmu_enable = xtensa_pmu_enable,
+ .pmu_disable = xtensa_pmu_disable,
+ .event_init = xtensa_pmu_event_init,
+ .add = xtensa_pmu_add,
+ .del = xtensa_pmu_del,
+ .start = xtensa_pmu_start,
+ .stop = xtensa_pmu_stop,
+ .read = xtensa_pmu_read,
+};
+
+static void xtensa_pmu_setup(void)
+{
+ unsigned i;
+
+ set_er(0, XTENSA_PMU_PMG);
+ for (i = 0; i < XCHAL_NUM_PERF_COUNTERS; ++i) {
+ set_er(0, XTENSA_PMU_PMCTRL(i));
+ set_er(get_er(XTENSA_PMU_PMSTAT(i)), XTENSA_PMU_PMSTAT(i));
+ }
+}
+
+static int xtensa_pmu_notifier(struct notifier_block *self,
+ unsigned long action, void *data)
+{
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_STARTING:
+ xtensa_pmu_setup();
+ break;
+
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static int __init xtensa_pmu_init(void)
+{
+ int ret;
+ int irq = irq_create_mapping(NULL, XCHAL_PROFILING_INTERRUPT);
+
+ perf_cpu_notifier(xtensa_pmu_notifier);
+#if XTENSA_FAKE_NMI
+ enable_irq(irq);
+#else
+ ret = request_irq(irq, xtensa_pmu_irq_handler, IRQF_PERCPU,
+ "pmu", NULL);
+ if (ret < 0)
+ return ret;
+#endif
+
+ ret = perf_pmu_register(&xtensa_pmu, "cpu", PERF_TYPE_RAW);
+ if (ret)
+ free_irq(irq, NULL);
+
+ return ret;
+}
+early_initcall(xtensa_pmu_init);
diff --git a/arch/xtensa/kernel/stacktrace.c b/arch/xtensa/kernel/stacktrace.c
index 7d2c317..7538d80 100644
--- a/arch/xtensa/kernel/stacktrace.c
+++ b/arch/xtensa/kernel/stacktrace.c
@@ -1,11 +1,12 @@
/*
- * arch/xtensa/kernel/stacktrace.c
+ * Kernel and userspace stack tracing.
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2001 - 2013 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
*/
#include <linux/export.h>
#include <linux/sched.h>
@@ -13,6 +14,170 @@
#include <asm/stacktrace.h>
#include <asm/traps.h>
+#include <asm/uaccess.h>
+
+#if IS_ENABLED(CONFIG_OPROFILE) || IS_ENABLED(CONFIG_PERF_EVENTS)
+
+/* Address of common_exception_return, used to check the
+ * transition from kernel to user space.
+ */
+extern int common_exception_return;
+
+/* A struct that maps to the part of the frame containing the a0 and
+ * a1 registers.
+ */
+struct frame_start {
+ unsigned long a0;
+ unsigned long a1;
+};
+
+void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
+ int (*ufn)(struct stackframe *frame, void *data),
+ void *data)
+{
+ unsigned long windowstart = regs->windowstart;
+ unsigned long windowbase = regs->windowbase;
+ unsigned long a0 = regs->areg[0];
+ unsigned long a1 = regs->areg[1];
+ unsigned long pc = regs->pc;
+ struct stackframe frame;
+ int index;
+
+ if (!depth--)
+ return;
+
+ frame.pc = pc;
+ frame.sp = a1;
+
+ if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
+ return;
+
+ /* Two steps:
+ *
+ * 1. Look through the register window for the
+ * previous PCs in the call trace.
+ *
+ * 2. Look on the stack.
+ */
+
+ /* Step 1. */
+ /* Rotate WINDOWSTART to move the bit corresponding to
+ * the current window to the bit #0.
+ */
+ windowstart = (windowstart << WSBITS | windowstart) >> windowbase;
+
+ /* Look for bits that are set, they correspond to
+ * valid windows.
+ */
+ for (index = WSBITS - 1; (index > 0) && depth; depth--, index--)
+ if (windowstart & (1 << index)) {
+ /* Get the PC from a0 and a1. */
+ pc = MAKE_PC_FROM_RA(a0, pc);
+ /* Read a0 and a1 from the
+ * corresponding position in AREGs.
+ */
+ a0 = regs->areg[index * 4];
+ a1 = regs->areg[index * 4 + 1];
+
+ frame.pc = pc;
+ frame.sp = a1;
+
+ if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
+ return;
+ }
+
+ /* Step 2. */
+ /* We are done with the register window, we need to
+ * look through the stack.
+ */
+ if (!depth)
+ return;
+
+ /* Start from the a1 register. */
+ /* a1 = regs->areg[1]; */
+ while (a0 != 0 && depth--) {
+ struct frame_start frame_start;
+ /* Get the location for a1, a0 for the
+ * previous frame from the current a1.
+ */
+ unsigned long *psp = (unsigned long *)a1;
+
+ psp -= 4;
+
+ /* Check if the region is OK to access. */
+ if (!access_ok(VERIFY_READ, psp, sizeof(frame_start)))
+ return;
+ /* Copy a1, a0 from user space stack frame. */
+ if (__copy_from_user_inatomic(&frame_start, psp,
+ sizeof(frame_start)))
+ return;
+
+ pc = MAKE_PC_FROM_RA(a0, pc);
+ a0 = frame_start.a0;
+ a1 = frame_start.a1;
+
+ frame.pc = pc;
+ frame.sp = a1;
+
+ if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
+ return;
+ }
+}
+EXPORT_SYMBOL(xtensa_backtrace_user);
+
+void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
+ int (*kfn)(struct stackframe *frame, void *data),
+ int (*ufn)(struct stackframe *frame, void *data),
+ void *data)
+{
+ unsigned long pc = regs->depc > VALID_DOUBLE_EXCEPTION_ADDRESS ?
+ regs->depc : regs->pc;
+ unsigned long sp_start, sp_end;
+ unsigned long a0 = regs->areg[0];
+ unsigned long a1 = regs->areg[1];
+
+ sp_start = a1 & ~(THREAD_SIZE - 1);
+ sp_end = sp_start + THREAD_SIZE;
+
+ /* Spill the register window to the stack first. */
+ spill_registers();
+
+ /* Read the stack frames one by one and create the PC
+ * from the a0 and a1 registers saved there.
+ */
+ while (a1 > sp_start && a1 < sp_end && depth--) {
+ struct stackframe frame;
+ unsigned long *psp = (unsigned long *)a1;
+
+ frame.pc = pc;
+ frame.sp = a1;
+
+ if (kernel_text_address(pc) && kfn(&frame, data))
+ return;
+
+ if (pc == (unsigned long)&common_exception_return) {
+ regs = (struct pt_regs *)a1;
+ if (user_mode(regs)) {
+ if (ufn == NULL)
+ return;
+ xtensa_backtrace_user(regs, depth, ufn, data);
+ return;
+ }
+ a0 = regs->areg[0];
+ a1 = regs->areg[1];
+ continue;
+ }
+
+ sp_start = a1;
+
+ pc = MAKE_PC_FROM_RA(a0, pc);
+ a0 = *(psp - 4);
+ a1 = *(psp - 3);
+ }
+}
+EXPORT_SYMBOL(xtensa_backtrace_kernel);
+
+#endif
void walk_stackframe(unsigned long *sp,
int (*fn)(struct stackframe *frame, void *data),
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 9d2f45f..42d441f 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -62,6 +62,7 @@
extern void do_illegal_instruction (struct pt_regs*);
extern void do_interrupt (struct pt_regs*);
+extern void do_nmi(struct pt_regs *);
extern void do_unaligned_user (struct pt_regs*);
extern void do_multihit (struct pt_regs*, unsigned long);
extern void do_page_fault (struct pt_regs*, unsigned long);
@@ -146,6 +147,9 @@
#if XTENSA_HAVE_COPROCESSOR(7)
COPROCESSOR(7),
#endif
+#if XTENSA_FAKE_NMI
+{ EXCCAUSE_MAPPED_NMI, 0, do_nmi },
+#endif
{ EXCCAUSE_MAPPED_DEBUG, 0, do_debug },
{ -1, -1, 0 }
@@ -199,6 +203,28 @@
extern void do_IRQ(int, struct pt_regs *);
+#if XTENSA_FAKE_NMI
+
+irqreturn_t xtensa_pmu_irq_handler(int irq, void *dev_id);
+
+DEFINE_PER_CPU(unsigned long, nmi_count);
+
+void do_nmi(struct pt_regs *regs)
+{
+ struct pt_regs *old_regs;
+
+ if ((regs->ps & PS_INTLEVEL_MASK) < LOCKLEVEL)
+ trace_hardirqs_off();
+
+ old_regs = set_irq_regs(regs);
+ nmi_enter();
+ ++*this_cpu_ptr(&nmi_count);
+ xtensa_pmu_irq_handler(0, NULL);
+ nmi_exit();
+ set_irq_regs(old_regs);
+}
+#endif
+
void do_interrupt(struct pt_regs *regs)
{
static const unsigned int_level_mask[] = {
@@ -211,8 +237,11 @@
XCHAL_INTLEVEL6_MASK,
XCHAL_INTLEVEL7_MASK,
};
- struct pt_regs *old_regs = set_irq_regs(regs);
+ struct pt_regs *old_regs;
+ trace_hardirqs_off();
+
+ old_regs = set_irq_regs(regs);
irq_enter();
for (;;) {
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S
index 1b397a9..abcdb52 100644
--- a/arch/xtensa/kernel/vectors.S
+++ b/arch/xtensa/kernel/vectors.S
@@ -627,7 +627,11 @@
wsr a0, excsave2
rsr a0, epc\level
wsr a0, epc1
+ .if \level <= LOCKLEVEL
movi a0, EXCCAUSE_LEVEL1_INTERRUPT
+ .else
+ movi a0, EXCCAUSE_MAPPED_NMI
+ .endif
wsr a0, exccause
rsr a0, eps\level
# branch to user or kernel vector
@@ -682,11 +686,13 @@
.align 4
_SimulateUserKernelVectorException:
addi a0, a0, (1 << PS_EXCM_BIT)
+#if !XTENSA_FAKE_NMI
wsr a0, ps
+#endif
bbsi.l a0, PS_UM_BIT, 1f # branch if user mode
- rsr a0, excsave2 # restore a0
+ xsr a0, excsave2 # restore a0
j _KernelExceptionVector # simulate kernel vector exception
-1: rsr a0, excsave2 # restore a0
+1: xsr a0, excsave2 # restore a0
j _UserExceptionVector # simulate user vector exception
#endif
diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c
index 83a44a3..c9784c1 100644
--- a/arch/xtensa/mm/fault.c
+++ b/arch/xtensa/mm/fault.c
@@ -15,6 +15,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/hardirq.h>
+#include <linux/perf_event.h>
#include <linux/uaccess.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>
@@ -142,6 +143,12 @@
}
up_read(&mm->mmap_sem);
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
+ if (flags & VM_FAULT_MAJOR)
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
+ else if (flags & VM_FAULT_MINOR)
+ perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
+
return;
/* Something tried to access memory that isn't in our memory map..
diff --git a/arch/xtensa/oprofile/backtrace.c b/arch/xtensa/oprofile/backtrace.c
index 5f03a59..8f95203 100644
--- a/arch/xtensa/oprofile/backtrace.c
+++ b/arch/xtensa/oprofile/backtrace.c
@@ -2,168 +2,26 @@
* @file backtrace.c
*
* @remark Copyright 2008 Tensilica Inc.
+ * Copyright (C) 2015 Cadence Design Systems Inc.
* @remark Read the file COPYING
*
*/
#include <linux/oprofile.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
#include <asm/ptrace.h>
-#include <asm/uaccess.h>
-#include <asm/traps.h>
+#include <asm/stacktrace.h>
-/* Address of common_exception_return, used to check the
- * transition from kernel to user space.
- */
-extern int common_exception_return;
-
-/* A struct that maps to the part of the frame containing the a0 and
- * a1 registers.
- */
-struct frame_start {
- unsigned long a0;
- unsigned long a1;
-};
-
-static void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth)
+static int xtensa_backtrace_cb(struct stackframe *frame, void *data)
{
- unsigned long windowstart = regs->windowstart;
- unsigned long windowbase = regs->windowbase;
- unsigned long a0 = regs->areg[0];
- unsigned long a1 = regs->areg[1];
- unsigned long pc = MAKE_PC_FROM_RA(a0, regs->pc);
- int index;
-
- /* First add the current PC to the trace. */
- if (pc != 0 && pc <= TASK_SIZE)
- oprofile_add_trace(pc);
- else
- return;
-
- /* Two steps:
- *
- * 1. Look through the register window for the
- * previous PCs in the call trace.
- *
- * 2. Look on the stack.
- */
-
- /* Step 1. */
- /* Rotate WINDOWSTART to move the bit corresponding to
- * the current window to the bit #0.
- */
- windowstart = (windowstart << WSBITS | windowstart) >> windowbase;
-
- /* Look for bits that are set, they correspond to
- * valid windows.
- */
- for (index = WSBITS - 1; (index > 0) && depth; depth--, index--)
- if (windowstart & (1 << index)) {
- /* Read a0 and a1 from the
- * corresponding position in AREGs.
- */
- a0 = regs->areg[index * 4];
- a1 = regs->areg[index * 4 + 1];
- /* Get the PC from a0 and a1. */
- pc = MAKE_PC_FROM_RA(a0, pc);
-
- /* Add the PC to the trace. */
- if (pc != 0 && pc <= TASK_SIZE)
- oprofile_add_trace(pc);
- else
- return;
- }
-
- /* Step 2. */
- /* We are done with the register window, we need to
- * look through the stack.
- */
- if (depth > 0) {
- /* Start from the a1 register. */
- /* a1 = regs->areg[1]; */
- while (a0 != 0 && depth--) {
-
- struct frame_start frame_start;
- /* Get the location for a1, a0 for the
- * previous frame from the current a1.
- */
- unsigned long *psp = (unsigned long *)a1;
- psp -= 4;
-
- /* Check if the region is OK to access. */
- if (!access_ok(VERIFY_READ, psp, sizeof(frame_start)))
- return;
- /* Copy a1, a0 from user space stack frame. */
- if (__copy_from_user_inatomic(&frame_start, psp,
- sizeof(frame_start)))
- return;
-
- a0 = frame_start.a0;
- a1 = frame_start.a1;
- pc = MAKE_PC_FROM_RA(a0, pc);
-
- if (pc != 0 && pc <= TASK_SIZE)
- oprofile_add_trace(pc);
- else
- return;
- }
- }
-}
-
-static void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth)
-{
- unsigned long pc = regs->pc;
- unsigned long *psp;
- unsigned long sp_start, sp_end;
- unsigned long a0 = regs->areg[0];
- unsigned long a1 = regs->areg[1];
-
- sp_start = a1 & ~(THREAD_SIZE-1);
- sp_end = sp_start + THREAD_SIZE;
-
- /* Spill the register window to the stack first. */
- spill_registers();
-
- /* Read the stack frames one by one and create the PC
- * from the a0 and a1 registers saved there.
- */
- while (a1 > sp_start && a1 < sp_end && depth--) {
- pc = MAKE_PC_FROM_RA(a0, pc);
-
- /* Add the PC to the trace. */
- oprofile_add_trace(pc);
- if (pc == (unsigned long) &common_exception_return) {
- regs = (struct pt_regs *)a1;
- if (user_mode(regs)) {
- pc = regs->pc;
- if (pc != 0 && pc <= TASK_SIZE)
- oprofile_add_trace(pc);
- else
- return;
- return xtensa_backtrace_user(regs, depth);
- }
- a0 = regs->areg[0];
- a1 = regs->areg[1];
- continue;
- }
-
- psp = (unsigned long *)a1;
-
- a0 = *(psp - 4);
- a1 = *(psp - 3);
-
- if (a1 <= (unsigned long)psp)
- return;
-
- }
- return;
+ oprofile_add_trace(frame->pc);
+ return 0;
}
void xtensa_backtrace(struct pt_regs * const regs, unsigned int depth)
{
if (user_mode(regs))
- xtensa_backtrace_user(regs, depth);
+ xtensa_backtrace_user(regs, depth, xtensa_backtrace_cb, NULL);
else
- xtensa_backtrace_kernel(regs, depth);
+ xtensa_backtrace_kernel(regs, depth, xtensa_backtrace_cb,
+ xtensa_backtrace_cb, NULL);
}
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c
index 8ab021b..976a385 100644
--- a/arch/xtensa/platforms/iss/network.c
+++ b/arch/xtensa/platforms/iss/network.c
@@ -105,13 +105,17 @@
va_start(ap, str);
while ((arg = va_arg(ap, char**)) != NULL) {
- if (*str == '\0')
+ if (*str == '\0') {
+ va_end(ap);
return NULL;
+ }
end = strchr(str, ',');
if (end != str)
*arg = str;
- if (end == NULL)
+ if (end == NULL) {
+ va_end(ap);
return NULL;
+ }
*end++ = '\0';
str = end;
}
diff --git a/block/bio.c b/block/bio.c
index 2a00d34..d6e5ba3 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1831,8 +1831,9 @@
* Allocates and returns a new bio which represents @sectors from the start of
* @bio, and updates @bio to represent the remaining sectors.
*
- * The newly allocated bio will point to @bio's bi_io_vec; it is the caller's
- * responsibility to ensure that @bio is not freed before the split.
+ * Unless this is a discard request the newly allocated bio will point
+ * to @bio's bi_io_vec; it is the caller's responsibility to ensure that
+ * @bio is not freed before the split.
*/
struct bio *bio_split(struct bio *bio, int sectors,
gfp_t gfp, struct bio_set *bs)
@@ -1842,7 +1843,15 @@
BUG_ON(sectors <= 0);
BUG_ON(sectors >= bio_sectors(bio));
- split = bio_clone_fast(bio, gfp, bs);
+ /*
+ * Discards need a mutable bio_vec to accommodate the payload
+ * required by the DSM TRIM and UNMAP commands.
+ */
+ if (bio->bi_rw & REQ_DISCARD)
+ split = bio_clone_bioset(bio, gfp, bs);
+ else
+ split = bio_clone_fast(bio, gfp, bs);
+
if (!split)
return NULL;
@@ -2009,6 +2018,7 @@
bio->bi_css = blkcg_css;
return 0;
}
+EXPORT_SYMBOL_GPL(bio_associate_blkcg);
/**
* bio_associate_current - associate a bio with %current
@@ -2039,6 +2049,7 @@
bio->bi_css = task_get_css(current, blkio_cgrp_id);
return 0;
}
+EXPORT_SYMBOL_GPL(bio_associate_current);
/**
* bio_disassociate_task - undo bio_associate_current()
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 9da02c0..d6283b3 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -718,8 +718,12 @@
return -EINVAL;
disk = get_gendisk(MKDEV(major, minor), &part);
- if (!disk || part)
+ if (!disk)
return -EINVAL;
+ if (part) {
+ put_disk(disk);
+ return -EINVAL;
+ }
rcu_read_lock();
spin_lock_irq(disk->queue->queue_lock);
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 12600bf..e0057d0 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -241,8 +241,8 @@
* Description:
* Enables a low level driver to set a hard upper limit,
* max_hw_sectors, on the size of requests. max_hw_sectors is set by
- * the device driver based upon the combined capabilities of I/O
- * controller and storage device.
+ * the device driver based upon the capabilities of the I/O
+ * controller.
*
* max_sectors is a soft limit imposed by the block layer for
* filesystem type requests. This value can be overridden on a
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index a3da677..b8efe36 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -393,8 +393,6 @@
struct scatterlist *cipher = areq_ctx->cipher;
struct scatterlist *hsg = areq_ctx->hsg;
struct scatterlist *tsg = areq_ctx->tsg;
- struct scatterlist *assoc1;
- struct scatterlist *assoc2;
unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
unsigned int cryptlen = req->cryptlen;
struct page *dstp;
@@ -412,27 +410,19 @@
cryptlen += ivsize;
}
- if (sg_is_last(assoc))
- return -EINVAL;
-
- assoc1 = assoc + 1;
- if (sg_is_last(assoc1))
- return -EINVAL;
-
- assoc2 = assoc + 2;
- if (!sg_is_last(assoc2))
+ if (assoc->length < 12)
return -EINVAL;
sg_init_table(hsg, 2);
- sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
- sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
+ sg_set_page(hsg, sg_page(assoc), 4, assoc->offset);
+ sg_set_page(hsg + 1, sg_page(assoc), 4, assoc->offset + 8);
sg_init_table(tsg, 1);
- sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
+ sg_set_page(tsg, sg_page(assoc), 4, assoc->offset + 4);
areq_ctx->cryptlen = cryptlen;
- areq_ctx->headlen = assoc->length + assoc2->length;
- areq_ctx->trailen = assoc1->length;
+ areq_ctx->headlen = 8;
+ areq_ctx->trailen = 4;
areq_ctx->sg = dst;
areq_ctx->complete = authenc_esn_geniv_ahash_done;
@@ -563,8 +553,6 @@
struct scatterlist *cipher = areq_ctx->cipher;
struct scatterlist *hsg = areq_ctx->hsg;
struct scatterlist *tsg = areq_ctx->tsg;
- struct scatterlist *assoc1;
- struct scatterlist *assoc2;
unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
struct page *srcp;
u8 *vsrc;
@@ -580,27 +568,19 @@
cryptlen += ivsize;
}
- if (sg_is_last(assoc))
- return -EINVAL;
-
- assoc1 = assoc + 1;
- if (sg_is_last(assoc1))
- return -EINVAL;
-
- assoc2 = assoc + 2;
- if (!sg_is_last(assoc2))
+ if (assoc->length < 12)
return -EINVAL;
sg_init_table(hsg, 2);
- sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
- sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
+ sg_set_page(hsg, sg_page(assoc), 4, assoc->offset);
+ sg_set_page(hsg + 1, sg_page(assoc), 4, assoc->offset + 8);
sg_init_table(tsg, 1);
- sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
+ sg_set_page(tsg, sg_page(assoc), 4, assoc->offset + 4);
areq_ctx->cryptlen = cryptlen;
- areq_ctx->headlen = assoc->length + assoc2->length;
- areq_ctx->trailen = assoc1->length;
+ areq_ctx->headlen = 8;
+ areq_ctx->trailen = 4;
areq_ctx->sg = src;
areq_ctx->complete = authenc_esn_verify_ahash_done;
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 6e973b8..4e2e6aa 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -184,4 +184,6 @@
source "drivers/nvdimm/Kconfig"
+source "drivers/nvmem/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index b64b49f..4c270f5 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -165,3 +165,4 @@
obj-$(CONFIG_THUNDERBOLT) += thunderbolt/
obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/
obj-$(CONFIG_ANDROID) += android/
+obj-$(CONFIG_NVMEM) += nvmem/
diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c
index ff6d8ad..fb76552 100644
--- a/drivers/acpi/acpi_pnp.c
+++ b/drivers/acpi/acpi_pnp.c
@@ -153,6 +153,7 @@
{"AEI0250"}, /* PROLiNK 1456VH ISA PnP K56flex Fax Modem */
{"AEI1240"}, /* Actiontec ISA PNP 56K X2 Fax Modem */
{"AKY1021"}, /* Rockwell 56K ACF II Fax+Data+Voice Modem */
+ {"ALI5123"}, /* ALi Fast Infrared Controller */
{"AZT4001"}, /* AZT3005 PnP SOUND DEVICE */
{"BDP3336"}, /* Best Data Products Inc. Smart One 336F PnP Modem */
{"BRI0A49"}, /* Boca Complete Ofc Communicator 14.4 Data-FAX */
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 717afcd..88dbbb1 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -231,7 +231,7 @@
dev_warn(&device->dev, "Failed to change power state to %s\n",
acpi_power_state_string(state));
} else {
- device->power.state = state;
+ device->power.state = target_state;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Device [%s] transitioned to %s\n",
device->pnp.bus_id,
diff --git a/drivers/acpi/nfit.c b/drivers/acpi/nfit.c
index 628a42c..cf0fd96 100644
--- a/drivers/acpi/nfit.c
+++ b/drivers/acpi/nfit.c
@@ -702,11 +702,11 @@
u16 flags = to_nfit_memdev(dev)->flags;
return sprintf(buf, "%s%s%s%s%s\n",
- flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save " : "",
- flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore " : "",
- flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush " : "",
- flags & ACPI_NFIT_MEM_ARMED ? "arm " : "",
- flags & ACPI_NFIT_MEM_HEALTH_OBSERVED ? "smart " : "");
+ flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save_fail " : "",
+ flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore_fail " : "",
+ flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush_fail " : "",
+ flags & ACPI_NFIT_MEM_ARMED ? "not_armed " : "",
+ flags & ACPI_NFIT_MEM_HEALTH_OBSERVED ? "smart_event " : "");
}
static DEVICE_ATTR_RO(flags);
@@ -849,12 +849,12 @@
if ((mem_flags & ACPI_NFIT_MEM_FAILED_MASK) == 0)
continue;
- dev_info(acpi_desc->dev, "%s: failed: %s%s%s%s\n",
+ dev_info(acpi_desc->dev, "%s flags:%s%s%s%s\n",
nvdimm_name(nvdimm),
- mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? "save " : "",
- mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? "restore " : "",
- mem_flags & ACPI_NFIT_MEM_FLUSH_FAILED ? "flush " : "",
- mem_flags & ACPI_NFIT_MEM_ARMED ? "arm " : "");
+ mem_flags & ACPI_NFIT_MEM_SAVE_FAILED ? " save_fail" : "",
+ mem_flags & ACPI_NFIT_MEM_RESTORE_FAILED ? " restore_fail":"",
+ mem_flags & ACPI_NFIT_MEM_FLUSH_FAILED ? " flush_fail" : "",
+ mem_flags & ACPI_NFIT_MEM_ARMED ? " not_armed" : "");
}
@@ -1024,7 +1024,7 @@
wmb_pmem();
}
-static u64 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw)
+static u32 read_blk_stat(struct nfit_blk *nfit_blk, unsigned int bw)
{
struct nfit_blk_mmio *mmio = &nfit_blk->mmio[DCR];
u64 offset = nfit_blk->stat_offset + mmio->size * bw;
@@ -1032,7 +1032,7 @@
if (mmio->num_lines)
offset = to_interleave_offset(offset, mmio);
- return readq(mmio->base + offset);
+ return readl(mmio->base + offset);
}
static void write_blk_ctl(struct nfit_blk *nfit_blk, unsigned int bw,
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index 815f75e..2922f1f 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -32,6 +32,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/types.h>
+#include <linux/workqueue.h>
#include <acpi/video.h>
ACPI_MODULE_NAME("video");
@@ -41,6 +42,7 @@
static bool backlight_notifier_registered;
static struct notifier_block backlight_nb;
+static struct work_struct backlight_notify_work;
static enum acpi_backlight_type acpi_backlight_cmdline = acpi_backlight_undef;
static enum acpi_backlight_type acpi_backlight_dmi = acpi_backlight_undef;
@@ -262,6 +264,13 @@
{ },
};
+/* This uses a workqueue to avoid various locking ordering issues */
+static void acpi_video_backlight_notify_work(struct work_struct *work)
+{
+ if (acpi_video_get_backlight_type() != acpi_backlight_video)
+ acpi_video_unregister_backlight();
+}
+
static int acpi_video_backlight_notify(struct notifier_block *nb,
unsigned long val, void *bd)
{
@@ -269,9 +278,8 @@
/* A raw bl registering may change video -> native */
if (backlight->props.type == BACKLIGHT_RAW &&
- val == BACKLIGHT_REGISTERED &&
- acpi_video_get_backlight_type() != acpi_backlight_video)
- acpi_video_unregister_backlight();
+ val == BACKLIGHT_REGISTERED)
+ schedule_work(&backlight_notify_work);
return NOTIFY_OK;
}
@@ -304,6 +312,8 @@
acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
ACPI_UINT32_MAX, find_video, NULL,
&video_caps, NULL);
+ INIT_WORK(&backlight_notify_work,
+ acpi_video_backlight_notify_work);
backlight_nb.notifier_call = acpi_video_backlight_notify;
backlight_nb.priority = 0;
if (backlight_register_notifier(&backlight_nb) == 0)
diff --git a/drivers/ata/ahci_brcmstb.c b/drivers/ata/ahci_brcmstb.c
index ce1e3a8..14b7305 100644
--- a/drivers/ata/ahci_brcmstb.c
+++ b/drivers/ata/ahci_brcmstb.c
@@ -92,7 +92,7 @@
* Other architectures (e.g., ARM) either do not support big endian, or
* else leave I/O in little endian mode.
*/
- if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(__BIG_ENDIAN))
+ if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
return __raw_readl(addr);
else
return readl_relaxed(addr);
@@ -101,7 +101,7 @@
static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
{
/* See brcm_sata_readreg() comments */
- if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(__BIG_ENDIAN))
+ if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
__raw_writel(val, addr);
else
writel_relaxed(val, addr);
@@ -209,6 +209,7 @@
priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
}
+#ifdef CONFIG_PM_SLEEP
static int brcm_ahci_suspend(struct device *dev)
{
struct ata_host *host = dev_get_drvdata(dev);
@@ -231,6 +232,7 @@
brcm_sata_phys_enable(priv);
return ahci_platform_resume(dev);
}
+#endif
static struct scsi_host_template ahci_platform_sht = {
AHCI_SHT(DRV_NAME),
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index e83fc3d..790e0de 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -694,11 +694,11 @@
* RETURNS:
* Block address read from @tf.
*/
-u64 ata_tf_read_block(const struct ata_taskfile *tf, struct ata_device *dev)
+u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev)
{
u64 block = 0;
- if (!dev || tf->flags & ATA_TFLAG_LBA) {
+ if (tf->flags & ATA_TFLAG_LBA) {
if (tf->flags & ATA_TFLAG_LBA48) {
block |= (u64)tf->hob_lbah << 40;
block |= (u64)tf->hob_lbam << 32;
@@ -2147,24 +2147,6 @@
return 0;
}
-static void ata_dev_config_sense_reporting(struct ata_device *dev)
-{
- unsigned int err_mask;
-
- if (!ata_id_has_sense_reporting(dev->id))
- return;
-
- if (ata_id_sense_reporting_enabled(dev->id))
- return;
-
- err_mask = ata_dev_set_feature(dev, SETFEATURE_SENSE_DATA, 0x1);
- if (err_mask) {
- ata_dev_dbg(dev,
- "failed to enable Sense Data Reporting, Emask 0x%x\n",
- err_mask);
- }
-}
-
/**
* ata_dev_configure - Configure the specified ATA/ATAPI device
* @dev: Target device to configure
@@ -2387,7 +2369,7 @@
dev->devslp_timing[i] = sata_setting[j];
}
}
- ata_dev_config_sense_reporting(dev);
+
dev->cdb_len = 16;
}
@@ -2478,6 +2460,10 @@
dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128,
dev->max_sectors);
+ if (dev->horkage & ATA_HORKAGE_MAX_SEC_1024)
+ dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_1024,
+ dev->max_sectors);
+
if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48)
dev->max_sectors = ATA_MAX_SECTORS_LBA48;
@@ -4146,6 +4132,12 @@
{ "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 },
{ "Slimtype DVD A DS8A9SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 },
+ /*
+ * Causes silent data corruption with higher max sects.
+ * http://lkml.kernel.org/g/x49wpy40ysk.fsf@segfault.boston.devel.redhat.com
+ */
+ { "ST380013AS", "3.20", ATA_HORKAGE_MAX_SEC_1024 },
+
/* Devices we expect to fail diagnostics */
/* Devices where NCQ should be avoided */
@@ -4174,9 +4166,10 @@
{ "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ |
ATA_HORKAGE_FIRMWARE_WARN },
- /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */
+ /* drives which fail FPDMA_AA activation (some may freeze afterwards) */
{ "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA },
{ "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA },
+ { "VB0250EAVER", "HPG7", ATA_HORKAGE_BROKEN_FPDMA_AA },
/* Blacklist entries taken from Silicon Image 3124/3132
Windows driver .inf file - also several Linux problem reports */
@@ -4229,7 +4222,7 @@
ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
- { "Micron_M5[15]0*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
+ { "Micron_M5[15]0_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Crucial_CT*M550*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
@@ -4237,6 +4230,11 @@
ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Samsung SSD 8*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
+ { "FCCT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
+ ATA_HORKAGE_ZERO_AFTER_TRIM, },
+
+ /* devices that don't properly handle TRIM commands */
+ { "SuperSSpeed S238*", NULL, ATA_HORKAGE_NOTRIM, },
/*
* As defined, the DRAT (Deterministic Read After Trim) and RZAT
@@ -4501,7 +4499,8 @@
else /* In the ancient relic department - skip all of this */
return 0;
- err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
+ /* On some disks, this command causes spin-up, so we need longer timeout */
+ err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 15000);
DPRINTK("EXIT, err_mask=%x\n", err_mask);
return err_mask;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7465031..cb0508a 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1592,8 +1592,6 @@
tf->hob_lbah = buf[10];
tf->nsect = buf[12];
tf->hob_nsect = buf[13];
- if (ata_id_has_ncq_autosense(dev->id))
- tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16];
return 0;
}
@@ -1630,70 +1628,6 @@
}
/**
- * ata_eh_request_sense - perform REQUEST_SENSE_DATA_EXT
- * @dev: device to perform REQUEST_SENSE_SENSE_DATA_EXT to
- * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
- * @dfl_sense_key: default sense key to use
- *
- * Perform REQUEST_SENSE_DATA_EXT after the device reported CHECK
- * SENSE. This function is EH helper.
- *
- * LOCKING:
- * Kernel thread context (may sleep).
- *
- * RETURNS:
- * encoded sense data on success, 0 on failure or if sense data
- * is not available.
- */
-static u32 ata_eh_request_sense(struct ata_queued_cmd *qc,
- struct scsi_cmnd *cmd)
-{
- struct ata_device *dev = qc->dev;
- struct ata_taskfile tf;
- unsigned int err_mask;
-
- if (!cmd)
- return 0;
-
- DPRINTK("ATA request sense\n");
- ata_dev_warn(dev, "request sense\n");
- if (!ata_id_sense_reporting_enabled(dev->id)) {
- ata_dev_warn(qc->dev, "sense data reporting disabled\n");
- return 0;
- }
- ata_tf_init(dev, &tf);
-
- tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
- tf.flags |= ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
- tf.command = ATA_CMD_REQ_SENSE_DATA;
- tf.protocol = ATA_PROT_NODATA;
-
- err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
- /*
- * ACS-4 states:
- * The device may set the SENSE DATA AVAILABLE bit to one in the
- * STATUS field and clear the ERROR bit to zero in the STATUS field
- * to indicate that the command returned completion without an error
- * and the sense data described in table 306 is available.
- *
- * IOW the 'ATA_SENSE' bit might not be set even though valid
- * sense data is available.
- * So check for both.
- */
- if ((tf.command & ATA_SENSE) ||
- tf.lbah != 0 || tf.lbam != 0 || tf.lbal != 0) {
- ata_scsi_set_sense(cmd, tf.lbah, tf.lbam, tf.lbal);
- qc->flags |= ATA_QCFLAG_SENSE_VALID;
- ata_dev_warn(dev, "sense data %02x/%02x/%02x\n",
- tf.lbah, tf.lbam, tf.lbal);
- } else {
- ata_dev_warn(dev, "request sense failed stat %02x emask %x\n",
- tf.command, err_mask);
- }
- return err_mask;
-}
-
-/**
* atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
* @dev: device to perform REQUEST_SENSE to
* @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
@@ -1855,19 +1789,6 @@
memcpy(&qc->result_tf, &tf, sizeof(tf));
qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ;
- if (qc->result_tf.auxiliary) {
- char sense_key, asc, ascq;
-
- sense_key = (qc->result_tf.auxiliary >> 16) & 0xff;
- asc = (qc->result_tf.auxiliary >> 8) & 0xff;
- ascq = qc->result_tf.auxiliary & 0xff;
- ata_dev_dbg(dev, "NCQ Autosense %02x/%02x/%02x\n",
- sense_key, asc, ascq);
- ata_scsi_set_sense(qc->scsicmd, sense_key, asc, ascq);
- ata_scsi_set_sense_information(qc->scsicmd, &qc->result_tf);
- qc->flags |= ATA_QCFLAG_SENSE_VALID;
- }
-
ehc->i.err_mask &= ~AC_ERR_DEV;
}
@@ -1897,27 +1818,6 @@
return ATA_EH_RESET;
}
- /*
- * Sense data reporting does not work if the
- * device fault bit is set.
- */
- if ((stat & ATA_SENSE) && !(stat & ATA_DF) &&
- !(qc->flags & ATA_QCFLAG_SENSE_VALID)) {
- if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) {
- tmp = ata_eh_request_sense(qc, qc->scsicmd);
- if (tmp)
- qc->err_mask |= tmp;
- else
- ata_scsi_set_sense_information(qc->scsicmd, tf);
- } else {
- ata_dev_warn(qc->dev, "sense data available but port frozen\n");
- }
- }
-
- /* Set by NCQ autosense or request sense above */
- if (qc->flags & ATA_QCFLAG_SENSE_VALID)
- return 0;
-
if (stat & (ATA_ERR | ATA_DF))
qc->err_mask |= AC_ERR_DEV;
else
@@ -2661,15 +2561,14 @@
#ifdef CONFIG_ATA_VERBOSE_ERROR
if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
- ATA_SENSE | ATA_ERR)) {
+ ATA_ERR)) {
if (res->command & ATA_BUSY)
ata_dev_err(qc->dev, "status: { Busy }\n");
else
- ata_dev_err(qc->dev, "status: { %s%s%s%s%s}\n",
+ ata_dev_err(qc->dev, "status: { %s%s%s%s}\n",
res->command & ATA_DRDY ? "DRDY " : "",
res->command & ATA_DF ? "DF " : "",
res->command & ATA_DRQ ? "DRQ " : "",
- res->command & ATA_SENSE ? "SENSE " : "",
res->command & ATA_ERR ? "ERR " : "");
}
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 7ccc084..85aa761 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -460,6 +460,13 @@
ATA_LFLAG_NO_SRST |
ATA_LFLAG_ASSUME_ATA;
}
+ } else if (vendor == 0x11ab && devid == 0x4140) {
+ /* Marvell 4140 quirks */
+ ata_for_each_link(link, ap, EDGE) {
+ /* port 4 is for SEMB device and it doesn't like SRST */
+ if (link->pmp == 4)
+ link->flags |= ATA_LFLAG_DISABLED;
+ }
}
}
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 3131adc..0d7f0da 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -270,28 +270,13 @@
ata_scsi_park_show, ata_scsi_park_store);
EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
-void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
+static void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq)
{
- if (!cmd)
- return;
-
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
scsi_build_sense_buffer(0, cmd->sense_buffer, sk, asc, ascq);
}
-void ata_scsi_set_sense_information(struct scsi_cmnd *cmd,
- const struct ata_taskfile *tf)
-{
- u64 information;
-
- if (!cmd)
- return;
-
- information = ata_tf_read_block(tf, NULL);
- scsi_set_sense_information(cmd->sense_buffer, information);
-}
-
static ssize_t
ata_scsi_em_message_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -1792,9 +1777,7 @@
((cdb[2] & 0x20) || need_sense)) {
ata_gen_passthru_sense(qc);
} else {
- if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
- cmd->result = SAM_STAT_CHECK_CONDITION;
- } else if (!need_sense) {
+ if (!need_sense) {
cmd->result = SAM_STAT_GOOD;
} else {
/* TODO: decide which descriptor format to use
@@ -2568,7 +2551,8 @@
rbuf[14] = (lowest_aligned >> 8) & 0x3f;
rbuf[15] = lowest_aligned;
- if (ata_id_has_trim(args->id)) {
+ if (ata_id_has_trim(args->id) &&
+ !(dev->horkage & ATA_HORKAGE_NOTRIM)) {
rbuf[14] |= 0x80; /* LBPME */
if (ata_id_has_zero_after_trim(args->id) &&
diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c
index d6c37bc..e2d9497 100644
--- a/drivers/ata/libata-transport.c
+++ b/drivers/ata/libata-transport.c
@@ -569,6 +569,8 @@
if (!ata_id_has_trim(ata_dev->id))
mode = "unsupported";
+ else if (ata_dev->horkage & ATA_HORKAGE_NOTRIM)
+ mode = "forced_unsupported";
else if (ata_dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM)
mode = "forced_unqueued";
else if (ata_fpdma_dsm_supported(ata_dev))
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index a998a17..f840ca1 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -67,8 +67,7 @@
extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
u64 block, u32 n_block, unsigned int tf_flags,
unsigned int tag);
-extern u64 ata_tf_read_block(const struct ata_taskfile *tf,
- struct ata_device *dev);
+extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev);
extern unsigned ata_exec_internal(struct ata_device *dev,
struct ata_taskfile *tf, const u8 *cdb,
int dma_dir, void *buf, unsigned int buflen,
@@ -138,9 +137,6 @@
struct scsi_host_template *sht);
extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
extern int ata_scsi_offline_dev(struct ata_device *dev);
-extern void ata_scsi_set_sense(struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq);
-extern void ata_scsi_set_sense_information(struct scsi_cmnd *cmd,
- const struct ata_taskfile *tf);
extern void ata_scsi_media_change_notify(struct ata_device *dev);
extern void ata_scsi_hotplug(struct work_struct *work);
extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 3a18a8a..fab504f 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -1238,8 +1238,12 @@
readl(mmio + PDC_SDRAM_CONTROL);
/* Turn on for ECC */
- pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
- PDC_DIMM_SPD_TYPE, &spd0);
+ if (!pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
+ PDC_DIMM_SPD_TYPE, &spd0)) {
+ pr_err("Failed in i2c read: device=%#x, subaddr=%#x\n",
+ PDC_DIMM0_SPD_DEV_ADDRESS, PDC_DIMM_SPD_TYPE);
+ return 1;
+ }
if (spd0 == 0x02) {
data |= (0x01 << 16);
writel(data, mmio + PDC_SDRAM_CONTROL);
@@ -1380,8 +1384,12 @@
/* ECC initiliazation. */
- pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
- PDC_DIMM_SPD_TYPE, &spd0);
+ if (!pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
+ PDC_DIMM_SPD_TYPE, &spd0)) {
+ pr_err("Failed in i2c read: device=%#x, subaddr=%#x\n",
+ PDC_DIMM0_SPD_DEV_ADDRESS, PDC_DIMM_SPD_TYPE);
+ return 1;
+ }
if (spd0 == 0x02) {
void *buf;
VPRINTK("Start ECC initialization\n");
diff --git a/drivers/auxdisplay/ks0108.c b/drivers/auxdisplay/ks0108.c
index 5b93852..816de9e 100644
--- a/drivers/auxdisplay/ks0108.c
+++ b/drivers/auxdisplay/ks0108.c
@@ -23,6 +23,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -90,17 +92,19 @@
void ks0108_startline(unsigned char startline)
{
- ks0108_writedata(min(startline,(unsigned char)63) | bit(6) | bit(7));
+ ks0108_writedata(min_t(unsigned char, startline, 63) | bit(6) |
+ bit(7));
}
void ks0108_address(unsigned char address)
{
- ks0108_writedata(min(address,(unsigned char)63) | bit(6));
+ ks0108_writedata(min_t(unsigned char, address, 63) | bit(6));
}
void ks0108_page(unsigned char page)
{
- ks0108_writedata(min(page,(unsigned char)7) | bit(3) | bit(4) | bit(5) | bit(7));
+ ks0108_writedata(min_t(unsigned char, page, 7) | bit(3) | bit(4) |
+ bit(5) | bit(7));
}
EXPORT_SYMBOL_GPL(ks0108_writedata);
@@ -121,52 +125,71 @@
}
EXPORT_SYMBOL_GPL(ks0108_isinited);
+static void ks0108_parport_attach(struct parport *port)
+{
+ struct pardev_cb ks0108_cb;
+
+ if (port->base != ks0108_port)
+ return;
+
+ memset(&ks0108_cb, 0, sizeof(ks0108_cb));
+ ks0108_cb.flags = PARPORT_DEV_EXCL;
+ ks0108_pardevice = parport_register_dev_model(port, KS0108_NAME,
+ &ks0108_cb, 0);
+ if (!ks0108_pardevice) {
+ pr_err("ERROR: parport didn't register new device\n");
+ return;
+ }
+ if (parport_claim(ks0108_pardevice)) {
+ pr_err("could not claim access to parport %i. Aborting.\n",
+ ks0108_port);
+ goto err_unreg_device;
+ }
+
+ ks0108_parport = port;
+ ks0108_inited = 1;
+ return;
+
+err_unreg_device:
+ parport_unregister_device(ks0108_pardevice);
+ ks0108_pardevice = NULL;
+}
+
+static void ks0108_parport_detach(struct parport *port)
+{
+ if (port->base != ks0108_port)
+ return;
+
+ if (!ks0108_pardevice) {
+ pr_err("%s: already unregistered.\n", KS0108_NAME);
+ return;
+ }
+
+ parport_release(ks0108_pardevice);
+ parport_unregister_device(ks0108_pardevice);
+ ks0108_pardevice = NULL;
+ ks0108_parport = NULL;
+}
+
/*
* Module Init & Exit
*/
+static struct parport_driver ks0108_parport_driver = {
+ .name = "ks0108",
+ .match_port = ks0108_parport_attach,
+ .detach = ks0108_parport_detach,
+ .devmodel = true,
+};
+
static int __init ks0108_init(void)
{
- int result;
- int ret = -EINVAL;
-
- ks0108_parport = parport_find_base(ks0108_port);
- if (ks0108_parport == NULL) {
- printk(KERN_ERR KS0108_NAME ": ERROR: "
- "parport didn't find %i port\n", ks0108_port);
- goto none;
- }
-
- ks0108_pardevice = parport_register_device(ks0108_parport, KS0108_NAME,
- NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
- if (ks0108_pardevice == NULL) {
- printk(KERN_ERR KS0108_NAME ": ERROR: "
- "parport didn't register new device\n");
- goto none;
- }
-
- result = parport_claim(ks0108_pardevice);
- if (result != 0) {
- printk(KERN_ERR KS0108_NAME ": ERROR: "
- "can't claim %i parport, maybe in use\n", ks0108_port);
- ret = result;
- goto registered;
- }
-
- ks0108_inited = 1;
- return 0;
-
-registered:
- parport_unregister_device(ks0108_pardevice);
-
-none:
- return ret;
+ return parport_register_driver(&ks0108_parport_driver);
}
static void __exit ks0108_exit(void)
{
- parport_release(ks0108_pardevice);
- parport_unregister_device(ks0108_pardevice);
+ parport_unregister_driver(&ks0108_parport_driver);
}
module_init(ks0108_init);
diff --git a/drivers/base/base.h b/drivers/base/base.h
index fd3347d..1782f3a 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -63,7 +63,7 @@
* binding of drivers which were unable to get all the resources needed by
* the device; typically because it depends on another driver getting
* probed first.
- * @device - pointer back to the struct class that this structure is
+ * @device - pointer back to the struct device that this structure is
* associated with.
*
* Nothing outside of the driver core should ever touch these fields.
@@ -134,6 +134,7 @@
/* /sys/devices directory */
extern struct kset *devices_kset;
+extern void devices_kset_move_last(struct device *dev);
#if defined(CONFIG_MODULES) && defined(CONFIG_SYSFS)
extern void module_add_driver(struct module *mod, struct device_driver *drv);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index dafae6d..fc5a558 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -534,6 +534,52 @@
struct kset *devices_kset;
/**
+ * devices_kset_move_before - Move device in the devices_kset's list.
+ * @deva: Device to move.
+ * @devb: Device @deva should come before.
+ */
+static void devices_kset_move_before(struct device *deva, struct device *devb)
+{
+ if (!devices_kset)
+ return;
+ pr_debug("devices_kset: Moving %s before %s\n",
+ dev_name(deva), dev_name(devb));
+ spin_lock(&devices_kset->list_lock);
+ list_move_tail(&deva->kobj.entry, &devb->kobj.entry);
+ spin_unlock(&devices_kset->list_lock);
+}
+
+/**
+ * devices_kset_move_after - Move device in the devices_kset's list.
+ * @deva: Device to move
+ * @devb: Device @deva should come after.
+ */
+static void devices_kset_move_after(struct device *deva, struct device *devb)
+{
+ if (!devices_kset)
+ return;
+ pr_debug("devices_kset: Moving %s after %s\n",
+ dev_name(deva), dev_name(devb));
+ spin_lock(&devices_kset->list_lock);
+ list_move(&deva->kobj.entry, &devb->kobj.entry);
+ spin_unlock(&devices_kset->list_lock);
+}
+
+/**
+ * devices_kset_move_last - move the device to the end of devices_kset's list.
+ * @dev: device to move
+ */
+void devices_kset_move_last(struct device *dev)
+{
+ if (!devices_kset)
+ return;
+ pr_debug("devices_kset: Moving %s to end of list\n", dev_name(dev));
+ spin_lock(&devices_kset->list_lock);
+ list_move_tail(&dev->kobj.entry, &devices_kset->list);
+ spin_unlock(&devices_kset->list_lock);
+}
+
+/**
* device_create_file - create sysfs attribute file for device.
* @dev: device.
* @attr: device attribute descriptor.
@@ -1923,12 +1969,15 @@
break;
case DPM_ORDER_DEV_AFTER_PARENT:
device_pm_move_after(dev, new_parent);
+ devices_kset_move_after(dev, new_parent);
break;
case DPM_ORDER_PARENT_BEFORE_DEV:
device_pm_move_before(new_parent, dev);
+ devices_kset_move_before(new_parent, dev);
break;
case DPM_ORDER_DEV_LAST:
device_pm_move_last(dev);
+ devices_kset_move_last(dev);
break;
}
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 78720e7..91bbb19 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -41,7 +41,7 @@
cpu->node_id = to_nid;
}
-static int __ref cpu_subsys_online(struct device *dev)
+static int cpu_subsys_online(struct device *dev)
{
struct cpu *cpu = container_of(dev, struct cpu, dev);
int cpuid = dev->id;
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index a638bbb..cc2b1d4 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -304,6 +304,14 @@
goto probe_failed;
}
+ /*
+ * Ensure devices are listed in devices_kset in correct order
+ * It's important to move Dev to the end of devices_kset before
+ * calling .probe, because it could be recursive and parent Dev
+ * should always go first
+ */
+ devices_kset_move_last(dev);
+
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
diff --git a/drivers/base/devres.c b/drivers/base/devres.c
index c8a53d1..8754646 100644
--- a/drivers/base/devres.c
+++ b/drivers/base/devres.c
@@ -297,10 +297,10 @@
if (!dr) {
add_dr(dev, &new_dr->node);
dr = new_dr;
- new_dr = NULL;
+ new_res = NULL;
}
spin_unlock_irqrestore(&dev->devres_lock, flags);
- devres_free(new_dr);
+ devres_free(new_res);
return dr->data;
}
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 894bda1..8524450 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -443,7 +443,7 @@
return -ENOMEM;
fwn->name = kstrdup_const(name, GFP_KERNEL);
if (!fwn->name) {
- kfree(fwn);
+ devres_free(fwn);
return -ENOMEM;
}
diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c
index 81751a4..56486d9 100644
--- a/drivers/base/regmap/regcache-rbtree.c
+++ b/drivers/base/regmap/regcache-rbtree.c
@@ -296,11 +296,20 @@
if (!blk)
return -ENOMEM;
- present = krealloc(rbnode->cache_present,
- BITS_TO_LONGS(blklen) * sizeof(*present), GFP_KERNEL);
- if (!present) {
- kfree(blk);
- return -ENOMEM;
+ if (BITS_TO_LONGS(blklen) > BITS_TO_LONGS(rbnode->blklen)) {
+ present = krealloc(rbnode->cache_present,
+ BITS_TO_LONGS(blklen) * sizeof(*present),
+ GFP_KERNEL);
+ if (!present) {
+ kfree(blk);
+ return -ENOMEM;
+ }
+
+ memset(present + BITS_TO_LONGS(rbnode->blklen), 0,
+ (BITS_TO_LONGS(blklen) - BITS_TO_LONGS(rbnode->blklen))
+ * sizeof(*present));
+ } else {
+ present = rbnode->cache_present;
}
/* insert the register value in the correct place in the rbnode block */
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c
index 4a2ef09..f504232 100644
--- a/drivers/block/mtip32xx/mtip32xx.c
+++ b/drivers/block/mtip32xx/mtip32xx.c
@@ -3756,6 +3756,14 @@
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
u32 host_cap_64 = readl(dd->mmio + HOST_CAP) & HOST_CAP_64;
+ /*
+ * For flush requests, request_idx starts at the end of the
+ * tag space. Since we don't support FLUSH/FUA, simply return
+ * 0 as there's nothing to be done.
+ */
+ if (request_idx >= MTIP_MAX_COMMAND_SLOTS)
+ return 0;
+
cmd->command = dmam_alloc_coherent(&dd->pdev->dev, CMD_DMA_ALLOC_SZ,
&cmd->command_dma, GFP_KERNEL);
if (!cmd->command)
diff --git a/drivers/block/null_blk.c b/drivers/block/null_blk.c
index 69de41a..3177b24 100644
--- a/drivers/block/null_blk.c
+++ b/drivers/block/null_blk.c
@@ -240,19 +240,19 @@
while ((entry = llist_del_all(&cq->list)) != NULL) {
entry = llist_reverse_order(entry);
do {
+ struct request_queue *q = NULL;
+
cmd = container_of(entry, struct nullb_cmd, ll_list);
entry = entry->next;
+ if (cmd->rq)
+ q = cmd->rq->q;
end_cmd(cmd);
- if (cmd->rq) {
- struct request_queue *q = cmd->rq->q;
-
- if (!q->mq_ops && blk_queue_stopped(q)) {
- spin_lock(q->queue_lock);
- if (blk_queue_stopped(q))
- blk_start_queue(q);
- spin_unlock(q->queue_lock);
- }
+ if (q && !q->mq_ops && blk_queue_stopped(q)) {
+ spin_lock(q->queue_lock);
+ if (blk_queue_stopped(q))
+ blk_start_queue(q);
+ spin_unlock(q->queue_lock);
}
} while (entry);
}
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index d94529d..bc67a93 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -523,6 +523,7 @@
# define rbd_assert(expr) ((void) 0)
#endif /* !RBD_DEBUG */
+static void rbd_osd_copyup_callback(struct rbd_obj_request *obj_request);
static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request);
static void rbd_img_parent_read(struct rbd_obj_request *obj_request);
static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
@@ -1818,6 +1819,16 @@
obj_request_done_set(obj_request);
}
+static void rbd_osd_call_callback(struct rbd_obj_request *obj_request)
+{
+ dout("%s: obj %p\n", __func__, obj_request);
+
+ if (obj_request_img_data_test(obj_request))
+ rbd_osd_copyup_callback(obj_request);
+ else
+ obj_request_done_set(obj_request);
+}
+
static void rbd_osd_req_callback(struct ceph_osd_request *osd_req,
struct ceph_msg *msg)
{
@@ -1866,6 +1877,8 @@
rbd_osd_discard_callback(obj_request);
break;
case CEPH_OSD_OP_CALL:
+ rbd_osd_call_callback(obj_request);
+ break;
case CEPH_OSD_OP_NOTIFY_ACK:
case CEPH_OSD_OP_WATCH:
rbd_osd_trivial_callback(obj_request);
@@ -2530,13 +2543,15 @@
}
static void
-rbd_img_obj_copyup_callback(struct rbd_obj_request *obj_request)
+rbd_osd_copyup_callback(struct rbd_obj_request *obj_request)
{
struct rbd_img_request *img_request;
struct rbd_device *rbd_dev;
struct page **pages;
u32 page_count;
+ dout("%s: obj %p\n", __func__, obj_request);
+
rbd_assert(obj_request->type == OBJ_REQUEST_BIO ||
obj_request->type == OBJ_REQUEST_NODATA);
rbd_assert(obj_request_img_data_test(obj_request));
@@ -2563,9 +2578,7 @@
if (!obj_request->result)
obj_request->xferred = obj_request->length;
- /* Finish up with the normal image object callback */
-
- rbd_img_obj_callback(obj_request);
+ obj_request_done_set(obj_request);
}
static void
@@ -2650,7 +2663,6 @@
/* All set, send it off. */
- orig_request->callback = rbd_img_obj_copyup_callback;
osdc = &rbd_dev->rbd_client->client->osdc;
img_result = rbd_obj_request_submit(osdc, orig_request);
if (!img_result)
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index ced9677..954c002 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -369,8 +369,8 @@
return;
}
- if (work_pending(&blkif->persistent_purge_work)) {
- pr_alert_ratelimited("Scheduled work from previous purge is still pending, cannot purge list\n");
+ if (work_busy(&blkif->persistent_purge_work)) {
+ pr_alert_ratelimited("Scheduled work from previous purge is still busy, cannot purge list\n");
return;
}
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 6d89ed3..7a8a73f 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -179,6 +179,7 @@
((_segs + SEGS_PER_INDIRECT_FRAME - 1)/SEGS_PER_INDIRECT_FRAME)
static int blkfront_setup_indirect(struct blkfront_info *info);
+static int blkfront_gather_backend_features(struct blkfront_info *info);
static int get_id_from_freelist(struct blkfront_info *info)
{
@@ -1128,8 +1129,10 @@
* Add the used indirect page back to the list of
* available pages for indirect grefs.
*/
- indirect_page = pfn_to_page(s->indirect_grants[i]->pfn);
- list_add(&indirect_page->lru, &info->indirect_pages);
+ if (!info->feature_persistent) {
+ indirect_page = pfn_to_page(s->indirect_grants[i]->pfn);
+ list_add(&indirect_page->lru, &info->indirect_pages);
+ }
s->indirect_grants[i]->gref = GRANT_INVALID_REF;
list_add_tail(&s->indirect_grants[i]->node, &info->grants);
}
@@ -1519,7 +1522,7 @@
info->shadow_free = info->ring.req_prod_pvt;
info->shadow[BLK_RING_SIZE(info)-1].req.u.rw.id = 0x0fffffff;
- rc = blkfront_setup_indirect(info);
+ rc = blkfront_gather_backend_features(info);
if (rc) {
kfree(copy);
return rc;
@@ -1720,20 +1723,13 @@
static int blkfront_setup_indirect(struct blkfront_info *info)
{
- unsigned int indirect_segments, segs;
+ unsigned int segs;
int err, i;
- err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
- "feature-max-indirect-segments", "%u", &indirect_segments,
- NULL);
- if (err) {
- info->max_indirect_segments = 0;
+ if (info->max_indirect_segments == 0)
segs = BLKIF_MAX_SEGMENTS_PER_REQUEST;
- } else {
- info->max_indirect_segments = min(indirect_segments,
- xen_blkif_max_segments);
+ else
segs = info->max_indirect_segments;
- }
err = fill_grant_buffer(info, (segs + INDIRECT_GREFS(segs)) * BLK_RING_SIZE(info));
if (err)
@@ -1797,6 +1793,68 @@
}
/*
+ * Gather all backend feature-*
+ */
+static int blkfront_gather_backend_features(struct blkfront_info *info)
+{
+ int err;
+ int barrier, flush, discard, persistent;
+ unsigned int indirect_segments;
+
+ info->feature_flush = 0;
+
+ err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+ "feature-barrier", "%d", &barrier,
+ NULL);
+
+ /*
+ * If there's no "feature-barrier" defined, then it means
+ * we're dealing with a very old backend which writes
+ * synchronously; nothing to do.
+ *
+ * If there are barriers, then we use flush.
+ */
+ if (!err && barrier)
+ info->feature_flush = REQ_FLUSH | REQ_FUA;
+ /*
+ * And if there is "feature-flush-cache" use that above
+ * barriers.
+ */
+ err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+ "feature-flush-cache", "%d", &flush,
+ NULL);
+
+ if (!err && flush)
+ info->feature_flush = REQ_FLUSH;
+
+ err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+ "feature-discard", "%d", &discard,
+ NULL);
+
+ if (!err && discard)
+ blkfront_setup_discard(info);
+
+ err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+ "feature-persistent", "%u", &persistent,
+ NULL);
+ if (err)
+ info->feature_persistent = 0;
+ else
+ info->feature_persistent = persistent;
+
+ err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
+ "feature-max-indirect-segments", "%u", &indirect_segments,
+ NULL);
+ if (err)
+ info->max_indirect_segments = 0;
+ else
+ info->max_indirect_segments = min(indirect_segments,
+ xen_blkif_max_segments);
+
+ return blkfront_setup_indirect(info);
+}
+
+/*
* Invoked when the backend is finally 'ready' (and has told produced
* the details about the physical device - #sectors, size, etc).
*/
@@ -1807,7 +1865,6 @@
unsigned int physical_sector_size;
unsigned int binfo;
int err;
- int barrier, flush, discard, persistent;
switch (info->connected) {
case BLKIF_STATE_CONNECTED:
@@ -1864,48 +1921,7 @@
if (err != 1)
physical_sector_size = sector_size;
- info->feature_flush = 0;
-
- err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
- "feature-barrier", "%d", &barrier,
- NULL);
-
- /*
- * If there's no "feature-barrier" defined, then it means
- * we're dealing with a very old backend which writes
- * synchronously; nothing to do.
- *
- * If there are barriers, then we use flush.
- */
- if (!err && barrier)
- info->feature_flush = REQ_FLUSH | REQ_FUA;
- /*
- * And if there is "feature-flush-cache" use that above
- * barriers.
- */
- err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
- "feature-flush-cache", "%d", &flush,
- NULL);
-
- if (!err && flush)
- info->feature_flush = REQ_FLUSH;
-
- err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
- "feature-discard", "%d", &discard,
- NULL);
-
- if (!err && discard)
- blkfront_setup_discard(info);
-
- err = xenbus_gather(XBT_NIL, info->xbdev->otherend,
- "feature-persistent", "%u", &persistent,
- NULL);
- if (err)
- info->feature_persistent = 0;
- else
- info->feature_persistent = persistent;
-
- err = blkfront_setup_indirect(info);
+ err = blkfront_gather_backend_features(info);
if (err) {
xenbus_dev_fatal(info->xbdev, err, "setup_indirect at %s",
info->xbdev->otherend);
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index fb655e8..763301c 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -496,10 +496,9 @@
kfree(meta);
}
-static struct zram_meta *zram_meta_alloc(int device_id, u64 disksize)
+static struct zram_meta *zram_meta_alloc(char *pool_name, u64 disksize)
{
size_t num_pages;
- char pool_name[8];
struct zram_meta *meta = kmalloc(sizeof(*meta), GFP_KERNEL);
if (!meta)
@@ -512,7 +511,6 @@
goto out_error;
}
- snprintf(pool_name, sizeof(pool_name), "zram%d", device_id);
meta->mem_pool = zs_create_pool(pool_name, GFP_NOIO | __GFP_HIGHMEM);
if (!meta->mem_pool) {
pr_err("Error creating memory pool\n");
@@ -1031,7 +1029,7 @@
return -EINVAL;
disksize = PAGE_ALIGN(disksize);
- meta = zram_meta_alloc(zram->disk->first_minor, disksize);
+ meta = zram_meta_alloc(zram->disk->disk_name, disksize);
if (!meta)
return -ENOMEM;
diff --git a/drivers/bluetooth/btbcm.c b/drivers/bluetooth/btbcm.c
index 1e1a432..9ceb8ac 100644
--- a/drivers/bluetooth/btbcm.c
+++ b/drivers/bluetooth/btbcm.c
@@ -472,12 +472,11 @@
/* Read Verbose Config Version Info */
skb = btbcm_read_verbose_config(hdev);
- if (IS_ERR(skb))
- return PTR_ERR(skb);
-
- BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1],
- get_unaligned_le16(skb->data + 5));
- kfree_skb(skb);
+ if (!IS_ERR(skb)) {
+ BT_INFO("%s: BCM: chip id %u build %4.4u", hdev->name, skb->data[1],
+ get_unaligned_le16(skb->data + 5));
+ kfree_skb(skb);
+ }
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index da8faf7..5643b65 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -429,7 +429,7 @@
static void start_khwrngd(void)
{
hwrng_fill = kthread_run(hwrng_fillfn, NULL, "hwrng");
- if (hwrng_fill == ERR_PTR(-ENOMEM)) {
+ if (IS_ERR(hwrng_fill)) {
pr_err("hwrng_fill thread creation failed");
hwrng_fill = NULL;
}
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index fdb0f9b..8069b36 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -243,17 +243,15 @@
* @misc: device to unregister
*
* Unregister a miscellaneous device that was previously
- * successfully registered with misc_register(). Success
- * is indicated by a zero return, a negative errno code
- * indicates an error.
+ * successfully registered with misc_register().
*/
-int misc_deregister(struct miscdevice *misc)
+void misc_deregister(struct miscdevice *misc)
{
int i = DYNAMIC_MINORS - misc->minor - 1;
if (WARN_ON(list_empty(&misc->list)))
- return -EINVAL;
+ return;
mutex_lock(&misc_mtx);
list_del(&misc->list);
@@ -261,7 +259,6 @@
if (i < DYNAMIC_MINORS && i >= 0)
clear_bit(i, misc_minors);
mutex_unlock(&misc_mtx);
- return 0;
}
EXPORT_SYMBOL(misc_register);
@@ -281,10 +278,9 @@
static int __init misc_init(void)
{
int err;
+ struct proc_dir_entry *ret;
-#ifdef CONFIG_PROC_FS
- proc_create("misc", 0, NULL, &misc_proc_fops);
-#endif
+ ret = proc_create("misc", 0, NULL, &misc_proc_fops);
misc_class = class_create(THIS_MODULE, "misc");
err = PTR_ERR(misc_class);
if (IS_ERR(misc_class))
@@ -300,7 +296,8 @@
printk("unable to get major %d for misc devices\n", MISC_MAJOR);
class_destroy(misc_class);
fail_remove:
- remove_proc_entry("misc", NULL);
+ if (ret)
+ remove_proc_entry("misc", NULL);
return err;
}
subsys_initcall(misc_init);
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 9df78e2..97c2d8d 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -702,7 +702,7 @@
seq_printf(seq, "%ds%s\n", nvram[10],
nvram[10] < 8 ? ", no memory test" : "");
- vmode = (nvram[14] << 8) || nvram[15];
+ vmode = (nvram[14] << 8) | nvram[15];
seq_printf(seq,
"Video mode : %s colors, %d columns, %s %s monitor\n",
colors[vmode & 7],
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index 014c9d9..f5a45d8 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -430,7 +430,7 @@
int i,major,minor,day,year,month,flag;
unsigned char signature[7] = { 0x54,0x4f,0x53,0x48,0x49,0x42,0x41 };
SMMRegisters regs;
- void __iomem *bios = ioremap_cache(0xf0000, 0x10000);
+ void __iomem *bios = ioremap(0xf0000, 0x10000);
if (!bios)
return -ENOMEM;
diff --git a/drivers/char/xillybus/xillybus_pcie.c b/drivers/char/xillybus/xillybus_pcie.c
index d8266bc..9418300 100644
--- a/drivers/char/xillybus/xillybus_pcie.c
+++ b/drivers/char/xillybus/xillybus_pcie.c
@@ -193,14 +193,16 @@
}
/*
- * In theory, an attempt to set the DMA mask to 64 and dma_using_dac=1
- * is the right thing. But some unclever PCIe drivers report it's OK
- * when the hardware drops those 64-bit PCIe packets. So trust
- * nobody and use 32 bits DMA addressing in any case.
+ * Some (old and buggy?) hardware drops 64-bit addressed PCIe packets,
+ * even when the PCIe driver claims that a 64-bit mask is OK. On the
+ * other hand, on some architectures, 64-bit addressing is mandatory.
+ * So go for the 64-bit mask only when failing is the other option.
*/
if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
endpoint->dma_using_dac = 0;
+ } else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) {
+ endpoint->dma_using_dac = 1;
} else {
dev_err(endpoint->dev, "Failed to set DMA mask. Aborting.\n");
return -ENODEV;
diff --git a/drivers/clk/pxa/clk-pxa3xx.c b/drivers/clk/pxa/clk-pxa3xx.c
index 4b93a1e..ac03ba4 100644
--- a/drivers/clk/pxa/clk-pxa3xx.c
+++ b/drivers/clk/pxa/clk-pxa3xx.c
@@ -126,7 +126,7 @@
PARENTS(pxa3xx_sbus) = { "ring_osc_60mhz", "system_bus" };
PARENTS(pxa3xx_smemcbus) = { "ring_osc_60mhz", "smemc" };
-#define CKEN_AB(bit) ((CKEN_ ## bit > 31) ? &CKENA : &CKENB)
+#define CKEN_AB(bit) ((CKEN_ ## bit > 31) ? &CKENB : &CKENA)
#define PXA3XX_CKEN(dev_id, con_id, parents, mult_lp, div_lp, mult_hp, \
div_hp, bit, is_lp, flags) \
PXA_CKEN(dev_id, con_id, bit, parents, mult_lp, div_lp, \
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index b8ff3c6..c96de14 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -661,6 +661,9 @@
{
struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
+ if (!ch->cs_enabled)
+ return;
+
sh_cmt_stop(ch, FLAG_CLOCKSOURCE);
pm_genpd_syscore_poweroff(&ch->cmt->pdev->dev);
}
@@ -669,6 +672,9 @@
{
struct sh_cmt_channel *ch = cs_to_sh_cmt(cs);
+ if (!ch->cs_enabled)
+ return;
+
pm_genpd_syscore_poweron(&ch->cmt->pdev->dev);
sh_cmt_start(ch, FLAG_CLOCKSOURCE);
}
diff --git a/drivers/clocksource/timer-imx-gpt.c b/drivers/clocksource/timer-imx-gpt.c
index 2d59038..86c7eb6 100644
--- a/drivers/clocksource/timer-imx-gpt.c
+++ b/drivers/clocksource/timer-imx-gpt.c
@@ -462,6 +462,7 @@
BUG_ON(!imxtm->base);
imxtm->type = type;
+ imxtm->irq = irq;
_mxc_timer_init(imxtm);
}
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 26063af..9bb09ce 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1002,7 +1002,7 @@
int ret = 0;
/* Some related CPUs might not be present (physically hotplugged) */
- for_each_cpu_and(j, policy->related_cpus, cpu_present_mask) {
+ for_each_cpu(j, policy->real_cpus) {
if (j == policy->kobj_cpu)
continue;
@@ -1019,7 +1019,7 @@
unsigned int j;
/* Some related CPUs might not be present (physically hotplugged) */
- for_each_cpu_and(j, policy->related_cpus, cpu_present_mask) {
+ for_each_cpu(j, policy->real_cpus) {
if (j == policy->kobj_cpu)
continue;
@@ -1163,11 +1163,14 @@
if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL))
goto err_free_cpumask;
+ if (!zalloc_cpumask_var(&policy->real_cpus, GFP_KERNEL))
+ goto err_free_rcpumask;
+
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &dev->kobj,
"cpufreq");
if (ret) {
pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
- goto err_free_rcpumask;
+ goto err_free_real_cpus;
}
INIT_LIST_HEAD(&policy->policy_list);
@@ -1184,6 +1187,8 @@
return policy;
+err_free_real_cpus:
+ free_cpumask_var(policy->real_cpus);
err_free_rcpumask:
free_cpumask_var(policy->related_cpus);
err_free_cpumask:
@@ -1234,6 +1239,7 @@
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
cpufreq_policy_put_kobj(policy, notify);
+ free_cpumask_var(policy->real_cpus);
free_cpumask_var(policy->related_cpus);
free_cpumask_var(policy->cpus);
kfree(policy);
@@ -1258,14 +1264,17 @@
pr_debug("adding CPU %u\n", cpu);
- /*
- * Only possible if 'cpu' wasn't physically present earlier and we are
- * here from subsys_interface add callback. A hotplug notifier will
- * follow and we will handle it like logical CPU hotplug then. For now,
- * just create the sysfs link.
- */
- if (cpu_is_offline(cpu))
- return add_cpu_dev_symlink(per_cpu(cpufreq_cpu_data, cpu), cpu);
+ if (cpu_is_offline(cpu)) {
+ /*
+ * Only possible if we are here from the subsys_interface add
+ * callback. A hotplug notifier will follow and we will handle
+ * it as CPU online then. For now, just create the sysfs link,
+ * unless there is no policy or the link is already present.
+ */
+ policy = per_cpu(cpufreq_cpu_data, cpu);
+ return policy && !cpumask_test_and_set_cpu(cpu, policy->real_cpus)
+ ? add_cpu_dev_symlink(policy, cpu) : 0;
+ }
if (!down_read_trylock(&cpufreq_rwsem))
return 0;
@@ -1307,6 +1316,10 @@
/* related cpus should atleast have policy->cpus */
cpumask_or(policy->related_cpus, policy->related_cpus, policy->cpus);
+ /* Remember which CPUs have been present at the policy creation time. */
+ if (!recover_policy)
+ cpumask_and(policy->real_cpus, policy->cpus, cpu_present_mask);
+
/*
* affected cpus must always be the one, which are online. We aren't
* managing offline cpus here.
@@ -1420,8 +1433,7 @@
return ret;
}
-static int __cpufreq_remove_dev_prepare(struct device *dev,
- struct subsys_interface *sif)
+static int __cpufreq_remove_dev_prepare(struct device *dev)
{
unsigned int cpu = dev->id;
int ret = 0;
@@ -1437,10 +1449,8 @@
if (has_target()) {
ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP);
- if (ret) {
+ if (ret)
pr_err("%s: Failed to stop governor\n", __func__);
- return ret;
- }
}
down_write(&policy->rwsem);
@@ -1473,8 +1483,7 @@
return ret;
}
-static int __cpufreq_remove_dev_finish(struct device *dev,
- struct subsys_interface *sif)
+static int __cpufreq_remove_dev_finish(struct device *dev)
{
unsigned int cpu = dev->id;
int ret;
@@ -1492,10 +1501,8 @@
/* If cpu is last user of policy, free policy */
if (has_target()) {
ret = __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT);
- if (ret) {
+ if (ret)
pr_err("%s: Failed to exit governor\n", __func__);
- return ret;
- }
}
/*
@@ -1506,10 +1513,6 @@
if (cpufreq_driver->exit)
cpufreq_driver->exit(policy);
- /* Free the policy only if the driver is getting removed. */
- if (sif)
- cpufreq_policy_free(policy, true);
-
return 0;
}
@@ -1518,45 +1521,42 @@
*
* Removes the cpufreq interface for a CPU device.
*/
-static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
+static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif)
{
unsigned int cpu = dev->id;
- int ret;
+ struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
- /*
- * Only possible if 'cpu' is getting physically removed now. A hotplug
- * notifier should have already been called and we just need to remove
- * link or free policy here.
- */
- if (cpu_is_offline(cpu)) {
- struct cpufreq_policy *policy = per_cpu(cpufreq_cpu_data, cpu);
- struct cpumask mask;
+ if (!policy)
+ return;
- if (!policy)
- return 0;
-
- cpumask_copy(&mask, policy->related_cpus);
- cpumask_clear_cpu(cpu, &mask);
-
- /*
- * Free policy only if all policy->related_cpus are removed
- * physically.
- */
- if (cpumask_intersects(&mask, cpu_present_mask)) {
- remove_cpu_dev_symlink(policy, cpu);
- return 0;
- }
-
- cpufreq_policy_free(policy, true);
- return 0;
+ if (cpu_online(cpu)) {
+ __cpufreq_remove_dev_prepare(dev);
+ __cpufreq_remove_dev_finish(dev);
}
- ret = __cpufreq_remove_dev_prepare(dev, sif);
+ cpumask_clear_cpu(cpu, policy->real_cpus);
- if (!ret)
- ret = __cpufreq_remove_dev_finish(dev, sif);
+ if (cpumask_empty(policy->real_cpus)) {
+ cpufreq_policy_free(policy, true);
+ return;
+ }
- return ret;
+ if (cpu != policy->kobj_cpu) {
+ remove_cpu_dev_symlink(policy, cpu);
+ } else {
+ /*
+ * The CPU owning the policy object is going away. Move it to
+ * another suitable CPU.
+ */
+ unsigned int new_cpu = cpumask_first(policy->real_cpus);
+ struct device *new_dev = get_cpu_device(new_cpu);
+
+ dev_dbg(dev, "%s: Moving policy object to CPU%u\n", __func__, new_cpu);
+
+ sysfs_remove_link(&new_dev->kobj, "cpufreq");
+ policy->kobj_cpu = new_cpu;
+ WARN_ON(kobject_move(&policy->kobj, &new_dev->kobj));
+ }
}
static void handle_update(struct work_struct *work)
@@ -2395,11 +2395,11 @@
break;
case CPU_DOWN_PREPARE:
- __cpufreq_remove_dev_prepare(dev, NULL);
+ __cpufreq_remove_dev_prepare(dev);
break;
case CPU_POST_DEAD:
- __cpufreq_remove_dev_finish(dev, NULL);
+ __cpufreq_remove_dev_finish(dev);
break;
case CPU_DOWN_FAILED:
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
index ae5b2bd..fa3dd84 100644
--- a/drivers/cpufreq/exynos-cpufreq.c
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -180,7 +180,7 @@
ret = exynos5250_cpufreq_init(exynos_info);
} else {
pr_err("%s: Unknown SoC type\n", __func__);
- return -ENODEV;
+ ret = -ENODEV;
}
if (ret)
@@ -188,12 +188,14 @@
if (exynos_info->set_freq == NULL) {
dev_err(&pdev->dev, "No set_freq function (ERR)\n");
+ ret = -EINVAL;
goto err_vdd_arm;
}
arm_regulator = regulator_get(NULL, "vdd_arm");
if (IS_ERR(arm_regulator)) {
dev_err(&pdev->dev, "failed to get resource vdd_arm\n");
+ ret = -EINVAL;
goto err_vdd_arm;
}
@@ -225,7 +227,7 @@
regulator_put(arm_regulator);
err_vdd_arm:
kfree(exynos_info);
- return -EINVAL;
+ return ret;
}
static struct platform_driver exynos_cpufreq_platdrv = {
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 15ada47..fcb929e 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -681,6 +681,7 @@
.get_max = core_get_max_pstate,
.get_min = core_get_min_pstate,
.get_turbo = knl_get_turbo_pstate,
+ .get_scaling = core_get_scaling,
.set = core_set_pstate,
},
};
diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
index e362860..cd593c1 100644
--- a/drivers/cpufreq/loongson2_cpufreq.c
+++ b/drivers/cpufreq/loongson2_cpufreq.c
@@ -20,7 +20,7 @@
#include <asm/clock.h>
#include <asm/idle.h>
-#include <asm/mach-loongson/loongson.h>
+#include <asm/mach-loongson64/loongson.h>
static uint nowait;
diff --git a/drivers/crypto/caam/caamhash.c b/drivers/crypto/caam/caamhash.c
index dae1e80..f9c7875 100644
--- a/drivers/crypto/caam/caamhash.c
+++ b/drivers/crypto/caam/caamhash.c
@@ -909,13 +909,14 @@
state->buflen_1;
u32 *sh_desc = ctx->sh_desc_fin, *desc;
dma_addr_t ptr = ctx->sh_desc_fin_dma;
- int sec4_sg_bytes;
+ int sec4_sg_bytes, sec4_sg_src_index;
int digestsize = crypto_ahash_digestsize(ahash);
struct ahash_edesc *edesc;
int ret = 0;
int sh_len;
- sec4_sg_bytes = (1 + (buflen ? 1 : 0)) * sizeof(struct sec4_sg_entry);
+ sec4_sg_src_index = 1 + (buflen ? 1 : 0);
+ sec4_sg_bytes = sec4_sg_src_index * sizeof(struct sec4_sg_entry);
/* allocate space for base edesc and hw desc commands, link tables */
edesc = kmalloc(sizeof(struct ahash_edesc) + DESC_JOB_IO_LEN +
@@ -942,7 +943,7 @@
state->buf_dma = try_buf_map_to_sec4_sg(jrdev, edesc->sec4_sg + 1,
buf, state->buf_dma, buflen,
last_buflen);
- (edesc->sec4_sg + sec4_sg_bytes - 1)->len |= SEC4_SG_LEN_FIN;
+ (edesc->sec4_sg + sec4_sg_src_index - 1)->len |= SEC4_SG_LEN_FIN;
edesc->sec4_sg_dma = dma_map_single(jrdev, edesc->sec4_sg,
sec4_sg_bytes, DMA_TO_DEVICE);
diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c
index 7ba495f..402631a 100644
--- a/drivers/crypto/ixp4xx_crypto.c
+++ b/drivers/crypto/ixp4xx_crypto.c
@@ -905,7 +905,6 @@
crypt->mode |= NPE_OP_NOT_IN_PLACE;
/* This was never tested by Intel
* for more than one dst buffer, I think. */
- BUG_ON(req->dst->length < nbytes);
req_ctx->dst = NULL;
if (!chainup_buffers(dev, req->dst, nbytes, &dst_hook,
flags, DMA_FROM_DEVICE))
diff --git a/drivers/crypto/nx/nx-sha256.c b/drivers/crypto/nx/nx-sha256.c
index 08f8d5c..becb738 100644
--- a/drivers/crypto/nx/nx-sha256.c
+++ b/drivers/crypto/nx/nx-sha256.c
@@ -71,7 +71,6 @@
struct sha256_state *sctx = shash_desc_ctx(desc);
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
- struct nx_sg *in_sg;
struct nx_sg *out_sg;
u64 to_process = 0, leftover, total;
unsigned long irq_flags;
@@ -97,7 +96,6 @@
NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
- in_sg = nx_ctx->in_sg;
max_sg_len = min_t(u64, nx_ctx->ap->sglen,
nx_driver.of.max_sg_len/sizeof(struct nx_sg));
max_sg_len = min_t(u64, max_sg_len,
@@ -114,17 +112,12 @@
}
do {
- /*
- * to_process: the SHA256_BLOCK_SIZE data chunk to process in
- * this update. This value is also restricted by the sg list
- * limits.
- */
- to_process = total - to_process;
- to_process = to_process & ~(SHA256_BLOCK_SIZE - 1);
+ int used_sgs = 0;
+ struct nx_sg *in_sg = nx_ctx->in_sg;
if (buf_len) {
data_len = buf_len;
- in_sg = nx_build_sg_list(nx_ctx->in_sg,
+ in_sg = nx_build_sg_list(in_sg,
(u8 *) sctx->buf,
&data_len,
max_sg_len);
@@ -133,15 +126,27 @@
rc = -EINVAL;
goto out;
}
+ used_sgs = in_sg - nx_ctx->in_sg;
}
+ /* to_process: SHA256_BLOCK_SIZE aligned chunk to be
+ * processed in this iteration. This value is restricted
+ * by sg list limits and number of sgs we already used
+ * for leftover data. (see above)
+ * In ideal case, we could allow NX_PAGE_SIZE * max_sg_len,
+ * but because data may not be aligned, we need to account
+ * for that too. */
+ to_process = min_t(u64, total,
+ (max_sg_len - 1 - used_sgs) * NX_PAGE_SIZE);
+ to_process = to_process & ~(SHA256_BLOCK_SIZE - 1);
+
data_len = to_process - buf_len;
in_sg = nx_build_sg_list(in_sg, (u8 *) data,
&data_len, max_sg_len);
nx_ctx->op.inlen = (nx_ctx->in_sg - in_sg) * sizeof(struct nx_sg);
- to_process = (data_len + buf_len);
+ to_process = data_len + buf_len;
leftover = total - to_process;
/*
diff --git a/drivers/crypto/nx/nx-sha512.c b/drivers/crypto/nx/nx-sha512.c
index aff0fe5..b6e183d 100644
--- a/drivers/crypto/nx/nx-sha512.c
+++ b/drivers/crypto/nx/nx-sha512.c
@@ -71,7 +71,6 @@
struct sha512_state *sctx = shash_desc_ctx(desc);
struct nx_crypto_ctx *nx_ctx = crypto_tfm_ctx(&desc->tfm->base);
struct nx_csbcpb *csbcpb = (struct nx_csbcpb *)nx_ctx->csbcpb;
- struct nx_sg *in_sg;
struct nx_sg *out_sg;
u64 to_process, leftover = 0, total;
unsigned long irq_flags;
@@ -97,7 +96,6 @@
NX_CPB_FDM(csbcpb) |= NX_FDM_INTERMEDIATE;
NX_CPB_FDM(csbcpb) |= NX_FDM_CONTINUATION;
- in_sg = nx_ctx->in_sg;
max_sg_len = min_t(u64, nx_ctx->ap->sglen,
nx_driver.of.max_sg_len/sizeof(struct nx_sg));
max_sg_len = min_t(u64, max_sg_len,
@@ -114,18 +112,12 @@
}
do {
- /*
- * to_process: the SHA512_BLOCK_SIZE data chunk to process in
- * this update. This value is also restricted by the sg list
- * limits.
- */
- to_process = total - leftover;
- to_process = to_process & ~(SHA512_BLOCK_SIZE - 1);
- leftover = total - to_process;
+ int used_sgs = 0;
+ struct nx_sg *in_sg = nx_ctx->in_sg;
if (buf_len) {
data_len = buf_len;
- in_sg = nx_build_sg_list(nx_ctx->in_sg,
+ in_sg = nx_build_sg_list(in_sg,
(u8 *) sctx->buf,
&data_len, max_sg_len);
@@ -133,8 +125,20 @@
rc = -EINVAL;
goto out;
}
+ used_sgs = in_sg - nx_ctx->in_sg;
}
+ /* to_process: SHA512_BLOCK_SIZE aligned chunk to be
+ * processed in this iteration. This value is restricted
+ * by sg list limits and number of sgs we already used
+ * for leftover data. (see above)
+ * In ideal case, we could allow NX_PAGE_SIZE * max_sg_len,
+ * but because data may not be aligned, we need to account
+ * for that too. */
+ to_process = min_t(u64, total,
+ (max_sg_len - 1 - used_sgs) * NX_PAGE_SIZE);
+ to_process = to_process & ~(SHA512_BLOCK_SIZE - 1);
+
data_len = to_process - buf_len;
in_sg = nx_build_sg_list(in_sg, (u8 *) data,
&data_len, max_sg_len);
@@ -146,7 +150,7 @@
goto out;
}
- to_process = (data_len + buf_len);
+ to_process = data_len + buf_len;
leftover = total - to_process;
/*
diff --git a/drivers/crypto/qat/qat_common/qat_algs.c b/drivers/crypto/qat/qat_common/qat_algs.c
index 067402c..df427c0 100644
--- a/drivers/crypto/qat/qat_common/qat_algs.c
+++ b/drivers/crypto/qat/qat_common/qat_algs.c
@@ -73,7 +73,8 @@
ICP_QAT_HW_CIPHER_KEY_CONVERT, \
ICP_QAT_HW_CIPHER_DECRYPT)
-static atomic_t active_dev;
+static DEFINE_MUTEX(algs_lock);
+static unsigned int active_devs;
struct qat_alg_buf {
uint32_t len;
@@ -1280,7 +1281,10 @@
int qat_algs_register(void)
{
- if (atomic_add_return(1, &active_dev) == 1) {
+ int ret = 0;
+
+ mutex_lock(&algs_lock);
+ if (++active_devs == 1) {
int i;
for (i = 0; i < ARRAY_SIZE(qat_algs); i++)
@@ -1289,21 +1293,25 @@
CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC :
CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC;
- return crypto_register_algs(qat_algs, ARRAY_SIZE(qat_algs));
+ ret = crypto_register_algs(qat_algs, ARRAY_SIZE(qat_algs));
}
- return 0;
+ mutex_unlock(&algs_lock);
+ return ret;
}
int qat_algs_unregister(void)
{
- if (atomic_sub_return(1, &active_dev) == 0)
- return crypto_unregister_algs(qat_algs, ARRAY_SIZE(qat_algs));
- return 0;
+ int ret = 0;
+
+ mutex_lock(&algs_lock);
+ if (--active_devs == 0)
+ ret = crypto_unregister_algs(qat_algs, ARRAY_SIZE(qat_algs));
+ mutex_unlock(&algs_lock);
+ return ret;
}
int qat_algs_init(void)
{
- atomic_set(&active_dev, 0);
crypto_get_default_rng();
return 0;
}
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 59892126..d3629b7 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -48,6 +48,8 @@
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |\
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
+#define ATC_MAX_DSCR_TRIALS 10
+
/*
* Initial number of descriptors to allocate for each channel. This could
* be increased during dma usage.
@@ -285,28 +287,19 @@
*
* @current_len: the number of bytes left before reading CTRLA
* @ctrla: the value of CTRLA
- * @desc: the descriptor containing the transfer width
*/
-static inline int atc_calc_bytes_left(int current_len, u32 ctrla,
- struct at_desc *desc)
+static inline int atc_calc_bytes_left(int current_len, u32 ctrla)
{
- return current_len - ((ctrla & ATC_BTSIZE_MAX) << desc->tx_width);
-}
+ u32 btsize = (ctrla & ATC_BTSIZE_MAX);
+ u32 src_width = ATC_REG_TO_SRC_WIDTH(ctrla);
-/**
- * atc_calc_bytes_left_from_reg - calculates the number of bytes left according
- * to the current value of CTRLA.
- *
- * @current_len: the number of bytes left before reading CTRLA
- * @atchan: the channel to read CTRLA for
- * @desc: the descriptor containing the transfer width
- */
-static inline int atc_calc_bytes_left_from_reg(int current_len,
- struct at_dma_chan *atchan, struct at_desc *desc)
-{
- u32 ctrla = channel_readl(atchan, CTRLA);
-
- return atc_calc_bytes_left(current_len, ctrla, desc);
+ /*
+ * According to the datasheet, when reading the Control A Register
+ * (ctrla), the Buffer Transfer Size (btsize) bitfield refers to the
+ * number of transfers completed on the Source Interface.
+ * So btsize is always a number of source width transfers.
+ */
+ return current_len - (btsize << src_width);
}
/**
@@ -320,7 +313,7 @@
struct at_desc *desc_first = atc_first_active(atchan);
struct at_desc *desc;
int ret;
- u32 ctrla, dscr;
+ u32 ctrla, dscr, trials;
/*
* If the cookie doesn't match to the currently running transfer then
@@ -346,15 +339,82 @@
* the channel's DSCR register and compare it against the value
* of the hardware linked list structure of each child
* descriptor.
+ *
+ * The CTRLA register provides us with the amount of data
+ * already read from the source for the current child
+ * descriptor. So we can compute a more accurate residue by also
+ * removing the number of bytes corresponding to this amount of
+ * data.
+ *
+ * However, the DSCR and CTRLA registers cannot be read both
+ * atomically. Hence a race condition may occur: the first read
+ * register may refer to one child descriptor whereas the second
+ * read may refer to a later child descriptor in the list
+ * because of the DMA transfer progression inbetween the two
+ * reads.
+ *
+ * One solution could have been to pause the DMA transfer, read
+ * the DSCR and CTRLA then resume the DMA transfer. Nonetheless,
+ * this approach presents some drawbacks:
+ * - If the DMA transfer is paused, RX overruns or TX underruns
+ * are more likey to occur depending on the system latency.
+ * Taking the USART driver as an example, it uses a cyclic DMA
+ * transfer to read data from the Receive Holding Register
+ * (RHR) to avoid RX overruns since the RHR is not protected
+ * by any FIFO on most Atmel SoCs. So pausing the DMA transfer
+ * to compute the residue would break the USART driver design.
+ * - The atc_pause() function masks interrupts but we'd rather
+ * avoid to do so for system latency purpose.
+ *
+ * Then we'd rather use another solution: the DSCR is read a
+ * first time, the CTRLA is read in turn, next the DSCR is read
+ * a second time. If the two consecutive read values of the DSCR
+ * are the same then we assume both refers to the very same
+ * child descriptor as well as the CTRLA value read inbetween
+ * does. For cyclic tranfers, the assumption is that a full loop
+ * is "not so fast".
+ * If the two DSCR values are different, we read again the CTRLA
+ * then the DSCR till two consecutive read values from DSCR are
+ * equal or till the maxium trials is reach.
+ * This algorithm is very unlikely not to find a stable value for
+ * DSCR.
*/
- ctrla = channel_readl(atchan, CTRLA);
- rmb(); /* ensure CTRLA is read before DSCR */
dscr = channel_readl(atchan, DSCR);
+ rmb(); /* ensure DSCR is read before CTRLA */
+ ctrla = channel_readl(atchan, CTRLA);
+ for (trials = 0; trials < ATC_MAX_DSCR_TRIALS; ++trials) {
+ u32 new_dscr;
+
+ rmb(); /* ensure DSCR is read after CTRLA */
+ new_dscr = channel_readl(atchan, DSCR);
+
+ /*
+ * If the DSCR register value has not changed inside the
+ * DMA controller since the previous read, we assume
+ * that both the dscr and ctrla values refers to the
+ * very same descriptor.
+ */
+ if (likely(new_dscr == dscr))
+ break;
+
+ /*
+ * DSCR has changed inside the DMA controller, so the
+ * previouly read value of CTRLA may refer to an already
+ * processed descriptor hence could be outdated.
+ * We need to update ctrla to match the current
+ * descriptor.
+ */
+ dscr = new_dscr;
+ rmb(); /* ensure DSCR is read before CTRLA */
+ ctrla = channel_readl(atchan, CTRLA);
+ }
+ if (unlikely(trials >= ATC_MAX_DSCR_TRIALS))
+ return -ETIMEDOUT;
/* for the first descriptor we can be more accurate */
if (desc_first->lli.dscr == dscr)
- return atc_calc_bytes_left(ret, ctrla, desc_first);
+ return atc_calc_bytes_left(ret, ctrla);
ret -= desc_first->len;
list_for_each_entry(desc, &desc_first->tx_list, desc_node) {
@@ -365,16 +425,14 @@
}
/*
- * For the last descriptor in the chain we can calculate
+ * For the current descriptor in the chain we can calculate
* the remaining bytes using the channel's register.
- * Note that the transfer width of the first and last
- * descriptor may differ.
*/
- if (!desc->lli.dscr)
- ret = atc_calc_bytes_left_from_reg(ret, atchan, desc);
+ ret = atc_calc_bytes_left(ret, ctrla);
} else {
/* single transfer */
- ret = atc_calc_bytes_left_from_reg(ret, atchan, desc_first);
+ ctrla = channel_readl(atchan, CTRLA);
+ ret = atc_calc_bytes_left(ret, ctrla);
}
return ret;
@@ -726,7 +784,6 @@
desc->txd.cookie = -EBUSY;
desc->total_len = desc->len = len;
- desc->tx_width = dwidth;
/* set end-of-link to the last link descriptor of list*/
set_desc_eol(desc);
@@ -804,10 +861,6 @@
first->txd.cookie = -EBUSY;
first->total_len = len;
- /* set transfer width for the calculation of the residue */
- first->tx_width = src_width;
- prev->tx_width = src_width;
-
/* set end-of-link to the last link descriptor of list*/
set_desc_eol(desc);
@@ -956,10 +1009,6 @@
first->txd.cookie = -EBUSY;
first->total_len = total_len;
- /* set transfer width for the calculation of the residue */
- first->tx_width = reg_width;
- prev->tx_width = reg_width;
-
/* first link descriptor of list is responsible of flags */
first->txd.flags = flags; /* client is in control of this ack */
@@ -1077,12 +1126,6 @@
desc->txd.cookie = 0;
desc->len = len;
- /*
- * Although we only need the transfer width for the first and
- * the last descriptor, its easier to set it to all descriptors.
- */
- desc->tx_width = src_width;
-
atc_desc_chain(&first, &prev, desc);
/* update the lengths and addresses for the next loop cycle */
@@ -1256,7 +1299,6 @@
/* First descriptor of the chain embedds additional information */
first->txd.cookie = -EBUSY;
first->total_len = buf_len;
- first->tx_width = reg_width;
return &first->txd;
diff --git a/drivers/dma/at_hdmac_regs.h b/drivers/dma/at_hdmac_regs.h
index bc8d5eb..7f5a082 100644
--- a/drivers/dma/at_hdmac_regs.h
+++ b/drivers/dma/at_hdmac_regs.h
@@ -112,6 +112,7 @@
#define ATC_SRC_WIDTH_BYTE (0x0 << 24)
#define ATC_SRC_WIDTH_HALFWORD (0x1 << 24)
#define ATC_SRC_WIDTH_WORD (0x2 << 24)
+#define ATC_REG_TO_SRC_WIDTH(r) (((r) >> 24) & 0x3)
#define ATC_DST_WIDTH_MASK (0x3 << 28) /* Destination Single Transfer Size */
#define ATC_DST_WIDTH(x) ((x) << 28)
#define ATC_DST_WIDTH_BYTE (0x0 << 28)
@@ -182,7 +183,6 @@
* @txd: support for the async_tx api
* @desc_node: node on the channed descriptors list
* @len: descriptor byte count
- * @tx_width: transfer width
* @total_len: total transaction byte count
*/
struct at_desc {
@@ -194,7 +194,6 @@
struct dma_async_tx_descriptor txd;
struct list_head desc_node;
size_t len;
- u32 tx_width;
size_t total_len;
/* Interleaved data */
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index cf1213d..40afa2a 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -359,18 +359,19 @@
* descriptor view 2 since some fields of the configuration register
* depend on transfer size and src/dest addresses.
*/
- if (at_xdmac_chan_is_cyclic(atchan)) {
+ if (at_xdmac_chan_is_cyclic(atchan))
reg = AT_XDMAC_CNDC_NDVIEW_NDV1;
- at_xdmac_chan_write(atchan, AT_XDMAC_CC, first->lld.mbr_cfg);
- } else if (first->lld.mbr_ubc & AT_XDMAC_MBR_UBC_NDV3) {
+ else if (first->lld.mbr_ubc & AT_XDMAC_MBR_UBC_NDV3)
reg = AT_XDMAC_CNDC_NDVIEW_NDV3;
- } else {
- /*
- * No need to write AT_XDMAC_CC reg, it will be done when the
- * descriptor is fecthed.
- */
+ else
reg = AT_XDMAC_CNDC_NDVIEW_NDV2;
- }
+ /*
+ * Even if the register will be updated from the configuration in the
+ * descriptor when using view 2 or higher, the PROT bit won't be set
+ * properly. This bit can be modified only by using the channel
+ * configuration register.
+ */
+ at_xdmac_chan_write(atchan, AT_XDMAC_CC, first->lld.mbr_cfg);
reg |= AT_XDMAC_CNDC_NDDUP
| AT_XDMAC_CNDC_NDSUP
@@ -681,15 +682,16 @@
desc->lld.mbr_sa = mem;
desc->lld.mbr_da = atchan->sconfig.dst_addr;
}
- desc->lld.mbr_cfg = atchan->cfg;
- dwidth = at_xdmac_get_dwidth(desc->lld.mbr_cfg);
+ dwidth = at_xdmac_get_dwidth(atchan->cfg);
fixed_dwidth = IS_ALIGNED(len, 1 << dwidth)
- ? at_xdmac_get_dwidth(desc->lld.mbr_cfg)
+ ? dwidth
: AT_XDMAC_CC_DWIDTH_BYTE;
desc->lld.mbr_ubc = AT_XDMAC_MBR_UBC_NDV2 /* next descriptor view */
| AT_XDMAC_MBR_UBC_NDEN /* next descriptor dst parameter update */
| AT_XDMAC_MBR_UBC_NSEN /* next descriptor src parameter update */
| (len >> fixed_dwidth); /* microblock length */
+ desc->lld.mbr_cfg = (atchan->cfg & ~AT_XDMAC_CC_DWIDTH_MASK) |
+ AT_XDMAC_CC_DWIDTH(fixed_dwidth);
dev_dbg(chan2dev(chan),
"%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n",
__func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc);
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 4a4cce1..3ff284c 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -689,6 +689,10 @@
struct dma_chan *ch = dma_request_slave_channel_reason(dev, name);
if (IS_ERR(ch))
return NULL;
+
+ dma_cap_set(DMA_PRIVATE, ch->device->cap_mask);
+ ch->device->privatecnt++;
+
return ch;
}
EXPORT_SYMBOL_GPL(dma_request_slave_channel);
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index fbaf1ea..f1325f6 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -162,10 +162,11 @@
config &= ~0x7;
config |= op_mode;
- if (IS_ENABLED(__BIG_ENDIAN))
- config |= XOR_DESCRIPTOR_SWAP;
- else
- config &= ~XOR_DESCRIPTOR_SWAP;
+#if defined(__BIG_ENDIAN)
+ config |= XOR_DESCRIPTOR_SWAP;
+#else
+ config &= ~XOR_DESCRIPTOR_SWAP;
+#endif
writel_relaxed(config, XOR_CONFIG(chan));
chan->current_type = type;
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index f513f77..ecab4ea0 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2328,7 +2328,7 @@
desc->txd.callback = last->txd.callback;
desc->txd.callback_param = last->txd.callback_param;
}
- last->last = false;
+ desc->last = false;
dma_cookie_assign(&desc->txd);
@@ -2623,6 +2623,7 @@
desc->rqcfg.brst_len = 1;
desc->rqcfg.brst_len = get_burst_len(desc, len);
+ desc->bytes_requested = len;
desc->txd.flags = flags;
diff --git a/drivers/dma/virt-dma.c b/drivers/dma/virt-dma.c
index 7d2c17d..6f80432 100644
--- a/drivers/dma/virt-dma.c
+++ b/drivers/dma/virt-dma.c
@@ -29,7 +29,7 @@
spin_lock_irqsave(&vc->lock, flags);
cookie = dma_cookie_assign(tx);
- list_move_tail(&vd->node, &vc->desc_submitted);
+ list_add_tail(&vd->node, &vc->desc_submitted);
spin_unlock_irqrestore(&vc->lock, flags);
dev_dbg(vc->chan.device->dev, "vchan %p: txd %p[%x]: submitted\n",
@@ -83,10 +83,8 @@
cb_data = vd->tx.callback_param;
list_del(&vd->node);
- if (async_tx_test_ack(&vd->tx))
- list_add(&vd->node, &vc->desc_allocated);
- else
- vc->desc_free(vd);
+
+ vc->desc_free(vd);
if (cb)
cb(cb_data);
@@ -98,13 +96,9 @@
while (!list_empty(head)) {
struct virt_dma_desc *vd = list_first_entry(head,
struct virt_dma_desc, node);
- if (async_tx_test_ack(&vd->tx)) {
- list_move_tail(&vd->node, &vc->desc_allocated);
- } else {
- dev_dbg(vc->chan.device->dev, "txd %p: freeing\n", vd);
- list_del(&vd->node);
- vc->desc_free(vd);
- }
+ list_del(&vd->node);
+ dev_dbg(vc->chan.device->dev, "txd %p: freeing\n", vd);
+ vc->desc_free(vd);
}
}
EXPORT_SYMBOL_GPL(vchan_dma_desc_free_list);
@@ -114,7 +108,6 @@
dma_cookie_init(&vc->chan);
spin_lock_init(&vc->lock);
- INIT_LIST_HEAD(&vc->desc_allocated);
INIT_LIST_HEAD(&vc->desc_submitted);
INIT_LIST_HEAD(&vc->desc_issued);
INIT_LIST_HEAD(&vc->desc_completed);
diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h
index 189e75d..181b952 100644
--- a/drivers/dma/virt-dma.h
+++ b/drivers/dma/virt-dma.h
@@ -29,7 +29,6 @@
spinlock_t lock;
/* protected by vc.lock */
- struct list_head desc_allocated;
struct list_head desc_submitted;
struct list_head desc_issued;
struct list_head desc_completed;
@@ -56,16 +55,11 @@
struct virt_dma_desc *vd, unsigned long tx_flags)
{
extern dma_cookie_t vchan_tx_submit(struct dma_async_tx_descriptor *);
- unsigned long flags;
dma_async_tx_descriptor_init(&vd->tx, &vc->chan);
vd->tx.flags = tx_flags;
vd->tx.tx_submit = vchan_tx_submit;
- spin_lock_irqsave(&vc->lock, flags);
- list_add_tail(&vd->node, &vc->desc_allocated);
- spin_unlock_irqrestore(&vc->lock, flags);
-
return &vd->tx;
}
@@ -128,8 +122,7 @@
}
/**
- * vchan_get_all_descriptors - obtain all allocated, submitted and issued
- * descriptors
+ * vchan_get_all_descriptors - obtain all submitted and issued descriptors
* vc: virtual channel to get descriptors from
* head: list of descriptors found
*
@@ -141,7 +134,6 @@
static inline void vchan_get_all_descriptors(struct virt_dma_chan *vc,
struct list_head *head)
{
- list_splice_tail_init(&vc->desc_allocated, head);
list_splice_tail_init(&vc->desc_submitted, head);
list_splice_tail_init(&vc->desc_issued, head);
list_splice_tail_init(&vc->desc_completed, head);
@@ -149,14 +141,11 @@
static inline void vchan_free_chan_resources(struct virt_dma_chan *vc)
{
- struct virt_dma_desc *vd;
unsigned long flags;
LIST_HEAD(head);
spin_lock_irqsave(&vc->lock, flags);
vchan_get_all_descriptors(vc, &head);
- list_for_each_entry(vd, &head, node)
- async_tx_clear_ack(&vd->tx);
spin_unlock_irqrestore(&vc->lock, flags);
vchan_dma_desc_free_list(vc, &head);
diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c
index 620fd55ec..dff22ab 100644
--- a/drivers/dma/xgene-dma.c
+++ b/drivers/dma/xgene-dma.c
@@ -111,6 +111,7 @@
#define XGENE_DMA_MEM_RAM_SHUTDOWN 0xD070
#define XGENE_DMA_BLK_MEM_RDY 0xD074
#define XGENE_DMA_BLK_MEM_RDY_VAL 0xFFFFFFFF
+#define XGENE_DMA_RING_CMD_SM_OFFSET 0x8000
/* X-Gene SoC EFUSE csr register and bit defination */
#define XGENE_SOC_JTAG1_SHADOW 0x18
@@ -1887,6 +1888,8 @@
return -ENOMEM;
}
+ pdma->csr_ring_cmd += XGENE_DMA_RING_CMD_SM_OFFSET;
+
/* Get efuse csr region */
res = platform_get_resource(pdev, IORESOURCE_MEM, 3);
if (!res) {
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c
index 3515b38..711d8ad 100644
--- a/drivers/edac/ppc4xx_edac.c
+++ b/drivers/edac/ppc4xx_edac.c
@@ -920,7 +920,7 @@
*/
for (row = 0; row < mci->nr_csrows; row++) {
- struct csrow_info *csi = &mci->csrows[row];
+ struct csrow_info *csi = mci->csrows[row];
/*
* Get the configuration settings for this
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c
index ad87f26..4b9f09c 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -20,10 +20,12 @@
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/extcon.h>
@@ -46,6 +48,9 @@
#define HPDET_DEBOUNCE 500
#define DEFAULT_MICD_TIMEOUT 2000
+#define MICD_DBTIME_TWO_READINGS 2
+#define MICD_DBTIME_FOUR_READINGS 4
+
#define MICD_LVL_1_TO_7 (ARIZONA_MICD_LVL_1 | ARIZONA_MICD_LVL_2 | \
ARIZONA_MICD_LVL_3 | ARIZONA_MICD_LVL_4 | \
ARIZONA_MICD_LVL_5 | ARIZONA_MICD_LVL_6 | \
@@ -94,6 +99,8 @@
int hpdet_ip_version;
struct extcon_dev *edev;
+
+ struct gpio_desc *micd_pol_gpio;
};
static const struct arizona_micd_config micd_default_modes[] = {
@@ -204,6 +211,10 @@
if (arizona->pdata.micd_pol_gpio > 0)
gpio_set_value_cansleep(arizona->pdata.micd_pol_gpio,
info->micd_modes[mode].gpio);
+ else
+ gpiod_set_value_cansleep(info->micd_pol_gpio,
+ info->micd_modes[mode].gpio);
+
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
ARIZONA_MICD_BIAS_SRC_MASK,
info->micd_modes[mode].bias <<
@@ -757,10 +768,11 @@
mutex_lock(&info->lock);
dev_dbg(info->arizona->dev, "MICD timed out, reporting HP\n");
- arizona_identify_headphone(info);
info->detecting = false;
+ arizona_identify_headphone(info);
+
arizona_stop_mic(info);
mutex_unlock(&info->lock);
@@ -820,12 +832,18 @@
/* Due to jack detect this should never happen */
if (!(val & ARIZONA_MICD_STS)) {
dev_warn(arizona->dev, "Detected open circuit\n");
+ info->mic = false;
+ arizona_stop_mic(info);
info->detecting = false;
+ arizona_identify_headphone(info);
goto handled;
}
/* If we got a high impedence we should have a headset, report it. */
if (info->detecting && (val & ARIZONA_MICD_LVL_8)) {
+ info->mic = true;
+ info->detecting = false;
+
arizona_identify_headphone(info);
ret = extcon_set_cable_state_(info->edev,
@@ -841,8 +859,6 @@
ret);
}
- info->mic = true;
- info->detecting = false;
goto handled;
}
@@ -855,10 +871,11 @@
if (info->detecting && (val & MICD_LVL_1_TO_7)) {
if (info->jack_flips >= info->micd_num_modes * 10) {
dev_dbg(arizona->dev, "Detected HP/line\n");
- arizona_identify_headphone(info);
info->detecting = false;
+ arizona_identify_headphone(info);
+
arizona_stop_mic(info);
} else {
info->micd_mode++;
@@ -1110,12 +1127,12 @@
regmap_update_bits(arizona->regmap, reg, mask, level);
}
-static int arizona_extcon_of_get_pdata(struct arizona *arizona)
+static int arizona_extcon_device_get_pdata(struct arizona *arizona)
{
struct arizona_pdata *pdata = &arizona->pdata;
unsigned int val = ARIZONA_ACCDET_MODE_HPL;
- of_property_read_u32(arizona->dev->of_node, "wlf,hpdet-channel", &val);
+ device_property_read_u32(arizona->dev, "wlf,hpdet-channel", &val);
switch (val) {
case ARIZONA_ACCDET_MODE_HPL:
case ARIZONA_ACCDET_MODE_HPR:
@@ -1127,6 +1144,24 @@
pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL;
}
+ device_property_read_u32(arizona->dev, "wlf,micd-detect-debounce",
+ &pdata->micd_detect_debounce);
+
+ device_property_read_u32(arizona->dev, "wlf,micd-bias-start-time",
+ &pdata->micd_bias_start_time);
+
+ device_property_read_u32(arizona->dev, "wlf,micd-rate",
+ &pdata->micd_rate);
+
+ device_property_read_u32(arizona->dev, "wlf,micd-dbtime",
+ &pdata->micd_dbtime);
+
+ device_property_read_u32(arizona->dev, "wlf,micd-timeout",
+ &pdata->micd_timeout);
+
+ pdata->micd_force_micbias = device_property_read_bool(arizona->dev,
+ "wlf,micd-force-micbias");
+
return 0;
}
@@ -1147,10 +1182,8 @@
if (!info)
return -ENOMEM;
- if (IS_ENABLED(CONFIG_OF)) {
- if (!dev_get_platdata(arizona->dev))
- arizona_extcon_of_get_pdata(arizona);
- }
+ if (!dev_get_platdata(arizona->dev))
+ arizona_extcon_device_get_pdata(arizona);
info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD");
if (IS_ERR(info->micvdd)) {
@@ -1241,6 +1274,27 @@
arizona->pdata.micd_pol_gpio, ret);
goto err_register;
}
+ } else {
+ if (info->micd_modes[0].gpio)
+ mode = GPIOD_OUT_HIGH;
+ else
+ mode = GPIOD_OUT_LOW;
+
+ /* We can't use devm here because we need to do the get
+ * against the MFD device, as that is where the of_node
+ * will reside, but if we devm against that the GPIO
+ * will not be freed if the extcon driver is unloaded.
+ */
+ info->micd_pol_gpio = gpiod_get_optional(arizona->dev,
+ "wlf,micd-pol",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(info->micd_pol_gpio)) {
+ ret = PTR_ERR(info->micd_pol_gpio);
+ dev_err(arizona->dev,
+ "Failed to get microphone polarity GPIO: %d\n",
+ ret);
+ goto err_register;
+ }
}
if (arizona->pdata.hpdet_id_gpio > 0) {
@@ -1251,7 +1305,7 @@
if (ret != 0) {
dev_err(arizona->dev, "Failed to request GPIO%d: %d\n",
arizona->pdata.hpdet_id_gpio, ret);
- goto err_register;
+ goto err_gpio;
}
}
@@ -1267,11 +1321,19 @@
arizona->pdata.micd_rate
<< ARIZONA_MICD_RATE_SHIFT);
- if (arizona->pdata.micd_dbtime)
+ switch (arizona->pdata.micd_dbtime) {
+ case MICD_DBTIME_FOUR_READINGS:
regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
ARIZONA_MICD_DBTIME_MASK,
- arizona->pdata.micd_dbtime
- << ARIZONA_MICD_DBTIME_SHIFT);
+ ARIZONA_MICD_DBTIME);
+ break;
+ case MICD_DBTIME_TWO_READINGS:
+ regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1,
+ ARIZONA_MICD_DBTIME_MASK, 0);
+ break;
+ default:
+ break;
+ }
BUILD_BUG_ON(ARRAY_SIZE(arizona_micd_levels) != 0x40);
@@ -1295,7 +1357,7 @@
dev_err(arizona->dev,
"MICD ranges must be sorted\n");
ret = -EINVAL;
- goto err_input;
+ goto err_gpio;
}
}
}
@@ -1314,7 +1376,7 @@
dev_err(arizona->dev, "Unsupported MICD level %d\n",
info->micd_ranges[i].max);
ret = -EINVAL;
- goto err_input;
+ goto err_gpio;
}
dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n",
@@ -1387,7 +1449,7 @@
if (ret != 0) {
dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n",
ret);
- goto err_input;
+ goto err_gpio;
}
ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1);
@@ -1458,7 +1520,8 @@
arizona_set_irq_wake(arizona, jack_irq_rise, 0);
err_rise:
arizona_free_irq(arizona, jack_irq_rise, info);
-err_input:
+err_gpio:
+ gpiod_put(info->micd_pol_gpio);
err_register:
pm_runtime_disable(&pdev->dev);
return ret;
@@ -1470,6 +1533,8 @@
struct arizona *arizona = info->arizona;
int jack_irq_rise, jack_irq_fall;
+ gpiod_put(info->micd_pol_gpio);
+
pm_runtime_disable(&pdev->dev);
regmap_update_bits(arizona->regmap,
diff --git a/drivers/extcon/extcon-gpio.c b/drivers/extcon/extcon-gpio.c
index 355459a..57c24fa 100644
--- a/drivers/extcon/extcon-gpio.c
+++ b/drivers/extcon/extcon-gpio.c
@@ -65,22 +65,6 @@
return IRQ_HANDLED;
}
-static ssize_t extcon_gpio_print_state(struct extcon_dev *edev, char *buf)
-{
- struct device *dev = edev->dev.parent;
- struct gpio_extcon_data *extcon_data = dev_get_drvdata(dev);
- const char *state;
-
- if (extcon_get_state(edev))
- state = extcon_data->state_on;
- else
- state = extcon_data->state_off;
-
- if (state)
- return sprintf(buf, "%s\n", state);
- return -EINVAL;
-}
-
static int gpio_extcon_probe(struct platform_device *pdev)
{
struct gpio_extcon_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -110,8 +94,6 @@
extcon_data->state_on = pdata->state_on;
extcon_data->state_off = pdata->state_off;
extcon_data->check_on_resume = pdata->check_on_resume;
- if (pdata->state_on && pdata->state_off)
- extcon_data->edev->print_state = extcon_gpio_print_state;
ret = devm_gpio_request_one(&pdev->dev, extcon_data->gpio, GPIOF_DIR_IN,
pdev->name);
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c
index fac2f14..cc5e7bc 100644
--- a/drivers/extcon/extcon-max77843.c
+++ b/drivers/extcon/extcon-max77843.c
@@ -781,6 +781,15 @@
/* Support virtual irq domain for max77843 MUIC device */
INIT_WORK(&info->irq_work, max77843_muic_irq_work);
+ /* Clear IRQ bits before request IRQs */
+ ret = regmap_bulk_read(max77843->regmap_muic,
+ MAX77843_MUIC_REG_INT1, info->status,
+ MAX77843_MUIC_IRQ_NUM);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to Clear IRQ bits\n");
+ goto err_muic_irq;
+ }
+
for (i = 0; i < ARRAY_SIZE(max77843_muic_irqs); i++) {
struct max77843_muic_irq *muic_irq = &max77843_muic_irqs[i];
unsigned int virq = 0;
diff --git a/drivers/extcon/extcon-palmas.c b/drivers/extcon/extcon-palmas.c
index 080d5cc..93c30a8 100644
--- a/drivers/extcon/extcon-palmas.c
+++ b/drivers/extcon/extcon-palmas.c
@@ -28,6 +28,11 @@
#include <linux/mfd/palmas.h>
#include <linux/of.h>
#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/workqueue.h>
+
+#define USB_GPIO_DEBOUNCE_MS 20 /* ms */
static const unsigned int palmas_extcon_cable[] = {
EXTCON_USB,
@@ -35,8 +40,6 @@
EXTCON_NONE,
};
-static const int mutually_exclusive[] = {0x3, 0x0};
-
static void palmas_usb_wakeup(struct palmas *palmas, int enable)
{
if (enable)
@@ -120,19 +123,54 @@
return IRQ_HANDLED;
}
+static void palmas_gpio_id_detect(struct work_struct *work)
+{
+ int id;
+ struct palmas_usb *palmas_usb = container_of(to_delayed_work(work),
+ struct palmas_usb,
+ wq_detectid);
+ struct extcon_dev *edev = palmas_usb->edev;
+
+ if (!palmas_usb->id_gpiod)
+ return;
+
+ id = gpiod_get_value_cansleep(palmas_usb->id_gpiod);
+
+ if (id) {
+ extcon_set_cable_state_(edev, EXTCON_USB_HOST, false);
+ dev_info(palmas_usb->dev, "USB-HOST cable is detached\n");
+ } else {
+ extcon_set_cable_state_(edev, EXTCON_USB_HOST, true);
+ dev_info(palmas_usb->dev, "USB-HOST cable is attached\n");
+ }
+}
+
+static irqreturn_t palmas_gpio_id_irq_handler(int irq, void *_palmas_usb)
+{
+ struct palmas_usb *palmas_usb = _palmas_usb;
+
+ queue_delayed_work(system_power_efficient_wq, &palmas_usb->wq_detectid,
+ palmas_usb->sw_debounce_jiffies);
+
+ return IRQ_HANDLED;
+}
+
static void palmas_enable_irq(struct palmas_usb *palmas_usb)
{
palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
PALMAS_USB_VBUS_CTRL_SET,
PALMAS_USB_VBUS_CTRL_SET_VBUS_ACT_COMP);
- palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
- PALMAS_USB_ID_CTRL_SET, PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP);
+ if (palmas_usb->enable_id_detection) {
+ palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+ PALMAS_USB_ID_CTRL_SET,
+ PALMAS_USB_ID_CTRL_SET_ID_ACT_COMP);
- palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
- PALMAS_USB_ID_INT_EN_HI_SET,
- PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
- PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
+ palmas_write(palmas_usb->palmas, PALMAS_USB_OTG_BASE,
+ PALMAS_USB_ID_INT_EN_HI_SET,
+ PALMAS_USB_ID_INT_EN_HI_SET_ID_GND |
+ PALMAS_USB_ID_INT_EN_HI_SET_ID_FLOAT);
+ }
if (palmas_usb->enable_vbus_detection)
palmas_vbus_irq_handler(palmas_usb->vbus_irq, palmas_usb);
@@ -171,20 +209,37 @@
palmas_usb->wakeup = pdata->wakeup;
}
+ palmas_usb->id_gpiod = devm_gpiod_get_optional(&pdev->dev, "id",
+ GPIOD_IN);
+ if (IS_ERR(palmas_usb->id_gpiod)) {
+ dev_err(&pdev->dev, "failed to get id gpio\n");
+ return PTR_ERR(palmas_usb->id_gpiod);
+ }
+
+ if (palmas_usb->enable_id_detection && palmas_usb->id_gpiod) {
+ palmas_usb->enable_id_detection = false;
+ palmas_usb->enable_gpio_id_detection = true;
+ }
+
+ if (palmas_usb->enable_gpio_id_detection) {
+ u32 debounce;
+
+ if (of_property_read_u32(node, "debounce-delay-ms", &debounce))
+ debounce = USB_GPIO_DEBOUNCE_MS;
+
+ status = gpiod_set_debounce(palmas_usb->id_gpiod,
+ debounce * 1000);
+ if (status < 0)
+ palmas_usb->sw_debounce_jiffies = msecs_to_jiffies(debounce);
+ }
+
+ INIT_DELAYED_WORK(&palmas_usb->wq_detectid, palmas_gpio_id_detect);
+
palmas->usb = palmas_usb;
palmas_usb->palmas = palmas;
palmas_usb->dev = &pdev->dev;
- palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data,
- PALMAS_ID_OTG_IRQ);
- palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data,
- PALMAS_ID_IRQ);
- palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data,
- PALMAS_VBUS_OTG_IRQ);
- palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
- PALMAS_VBUS_IRQ);
-
palmas_usb_wakeup(palmas, palmas_usb->wakeup);
platform_set_drvdata(pdev, palmas_usb);
@@ -195,16 +250,18 @@
dev_err(&pdev->dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
- palmas_usb->edev->mutually_exclusive = mutually_exclusive;
status = devm_extcon_dev_register(&pdev->dev, palmas_usb->edev);
if (status) {
dev_err(&pdev->dev, "failed to register extcon device\n");
- kfree(palmas_usb->edev->name);
return status;
}
if (palmas_usb->enable_id_detection) {
+ palmas_usb->id_otg_irq = regmap_irq_get_virq(palmas->irq_data,
+ PALMAS_ID_OTG_IRQ);
+ palmas_usb->id_irq = regmap_irq_get_virq(palmas->irq_data,
+ PALMAS_ID_IRQ);
status = devm_request_threaded_irq(palmas_usb->dev,
palmas_usb->id_irq,
NULL, palmas_id_irq_handler,
@@ -214,12 +271,35 @@
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->id_irq, status);
- kfree(palmas_usb->edev->name);
+ return status;
+ }
+ } else if (palmas_usb->enable_gpio_id_detection) {
+ palmas_usb->gpio_id_irq = gpiod_to_irq(palmas_usb->id_gpiod);
+ if (palmas_usb->gpio_id_irq < 0) {
+ dev_err(&pdev->dev, "failed to get id irq\n");
+ return palmas_usb->gpio_id_irq;
+ }
+ status = devm_request_threaded_irq(&pdev->dev,
+ palmas_usb->gpio_id_irq,
+ NULL,
+ palmas_gpio_id_irq_handler,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING |
+ IRQF_ONESHOT,
+ "palmas_usb_id",
+ palmas_usb);
+ if (status < 0) {
+ dev_err(&pdev->dev,
+ "failed to request handler for id irq\n");
return status;
}
}
if (palmas_usb->enable_vbus_detection) {
+ palmas_usb->vbus_otg_irq = regmap_irq_get_virq(palmas->irq_data,
+ PALMAS_VBUS_OTG_IRQ);
+ palmas_usb->vbus_irq = regmap_irq_get_virq(palmas->irq_data,
+ PALMAS_VBUS_IRQ);
status = devm_request_threaded_irq(palmas_usb->dev,
palmas_usb->vbus_irq, NULL,
palmas_vbus_irq_handler,
@@ -229,12 +309,13 @@
if (status < 0) {
dev_err(&pdev->dev, "can't get IRQ %d, err %d\n",
palmas_usb->vbus_irq, status);
- kfree(palmas_usb->edev->name);
return status;
}
}
palmas_enable_irq(palmas_usb);
+ /* perform initial detection */
+ palmas_gpio_id_detect(&palmas_usb->wq_detectid.work);
device_set_wakeup_capable(&pdev->dev, true);
return 0;
}
@@ -243,7 +324,7 @@
{
struct palmas_usb *palmas_usb = platform_get_drvdata(pdev);
- kfree(palmas_usb->edev->name);
+ cancel_delayed_work_sync(&palmas_usb->wq_detectid);
return 0;
}
@@ -258,6 +339,8 @@
enable_irq_wake(palmas_usb->vbus_irq);
if (palmas_usb->enable_id_detection)
enable_irq_wake(palmas_usb->id_irq);
+ if (palmas_usb->enable_gpio_id_detection)
+ enable_irq_wake(palmas_usb->gpio_id_irq);
}
return 0;
}
@@ -271,6 +354,8 @@
disable_irq_wake(palmas_usb->vbus_irq);
if (palmas_usb->enable_id_detection)
disable_irq_wake(palmas_usb->id_irq);
+ if (palmas_usb->enable_gpio_id_detection)
+ disable_irq_wake(palmas_usb->gpio_id_irq);
}
return 0;
};
diff --git a/drivers/extcon/extcon-rt8973a.c b/drivers/extcon/extcon-rt8973a.c
index 92c9392..11592e9 100644
--- a/drivers/extcon/extcon-rt8973a.c
+++ b/drivers/extcon/extcon-rt8973a.c
@@ -693,7 +693,6 @@
static struct i2c_driver rt8973a_muic_i2c_driver = {
.driver = {
.name = "rt8973a",
- .owner = THIS_MODULE,
.pm = &rt8973a_muic_pm_ops,
.of_match_table = rt8973a_dt_match,
},
diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c
index 817dece..0ffefef 100644
--- a/drivers/extcon/extcon-sm5502.c
+++ b/drivers/extcon/extcon-sm5502.c
@@ -685,7 +685,6 @@
static struct i2c_driver sm5502_muic_i2c_driver = {
.driver = {
.name = "sm5502",
- .owner = THIS_MODULE,
.pm = &sm5502_muic_pm_ops,
.of_match_table = sm5502_dt_match,
},
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
index a2a4453..2b2fecf 100644
--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -15,6 +15,7 @@
*/
#include <linux/extcon.h>
+#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/interrupt.h>
diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c
index 76157ab..a07addd 100644
--- a/drivers/extcon/extcon.c
+++ b/drivers/extcon/extcon.c
@@ -124,25 +124,35 @@
return -EINVAL;
}
-static int find_cable_index_by_name(struct extcon_dev *edev, const char *name)
+static int find_cable_id_by_name(struct extcon_dev *edev, const char *name)
{
- unsigned int id = EXTCON_NONE;
+ int id = -EINVAL;
int i = 0;
- if (edev->max_supported == 0)
- return -EINVAL;
-
- /* Find the the number of extcon cable */
+ /* Find the id of extcon cable */
while (extcon_name[i]) {
if (!strncmp(extcon_name[i], name, CABLE_NAME_MAX)) {
id = i;
break;
}
+ i++;
}
- if (id == EXTCON_NONE)
+ return id;
+}
+
+static int find_cable_index_by_name(struct extcon_dev *edev, const char *name)
+{
+ int id;
+
+ if (edev->max_supported == 0)
return -EINVAL;
+ /* Find the the number of extcon cable */
+ id = find_cable_id_by_name(edev, name);
+ if (id < 0)
+ return id;
+
return find_cable_index_by_id(edev, id);
}
@@ -162,14 +172,6 @@
int i, count = 0;
struct extcon_dev *edev = dev_get_drvdata(dev);
- if (edev->print_state) {
- int ret = edev->print_state(edev, buf);
-
- if (ret >= 0)
- return ret;
- /* Use default if failed */
- }
-
if (edev->max_supported == 0)
return sprintf(buf, "%u\n", edev->state);
@@ -228,9 +230,11 @@
struct extcon_cable *cable = container_of(attr, struct extcon_cable,
attr_state);
+ int i = cable->cable_index;
+
return sprintf(buf, "%d\n",
extcon_get_cable_state_(cable->edev,
- cable->cable_index));
+ cable->edev->supported_cable[i]));
}
/**
@@ -260,23 +264,31 @@
unsigned long flags;
bool attached;
+ if (!edev)
+ return -EINVAL;
+
spin_lock_irqsave(&edev->lock, flags);
if (edev->state != ((edev->state & ~mask) | (state & mask))) {
+ u32 old_state;
+
if (check_mutually_exclusive(edev, (edev->state & ~mask) |
(state & mask))) {
spin_unlock_irqrestore(&edev->lock, flags);
return -EPERM;
}
- for (index = 0; index < edev->max_supported; index++) {
- if (is_extcon_changed(edev->state, state, index, &attached))
- raw_notifier_call_chain(&edev->nh[index], attached, edev);
- }
-
+ old_state = edev->state;
edev->state &= ~mask;
edev->state |= state & mask;
+ for (index = 0; index < edev->max_supported; index++) {
+ if (is_extcon_changed(old_state, edev->state, index,
+ &attached))
+ raw_notifier_call_chain(&edev->nh[index],
+ attached, edev);
+ }
+
/* This could be in interrupt handler */
prop_buf = (char *)get_zeroed_page(GFP_ATOMIC);
if (prop_buf) {
@@ -328,6 +340,9 @@
*/
int extcon_set_state(struct extcon_dev *edev, u32 state)
{
+ if (!edev)
+ return -EINVAL;
+
return extcon_update_state(edev, 0xffffffff, state);
}
EXPORT_SYMBOL_GPL(extcon_set_state);
@@ -341,6 +356,9 @@
{
int index;
+ if (!edev)
+ return -EINVAL;
+
index = find_cable_index_by_id(edev, id);
if (index < 0)
return index;
@@ -361,8 +379,13 @@
*/
int extcon_get_cable_state(struct extcon_dev *edev, const char *cable_name)
{
- return extcon_get_cable_state_(edev, find_cable_index_by_name
- (edev, cable_name));
+ int id;
+
+ id = find_cable_id_by_name(edev, cable_name);
+ if (id < 0)
+ return id;
+
+ return extcon_get_cable_state_(edev, id);
}
EXPORT_SYMBOL_GPL(extcon_get_cable_state);
@@ -380,6 +403,9 @@
u32 state;
int index;
+ if (!edev)
+ return -EINVAL;
+
index = find_cable_index_by_id(edev, id);
if (index < 0)
return index;
@@ -404,8 +430,13 @@
int extcon_set_cable_state(struct extcon_dev *edev,
const char *cable_name, bool cable_state)
{
- return extcon_set_cable_state_(edev, find_cable_index_by_name
- (edev, cable_name), cable_state);
+ int id;
+
+ id = find_cable_id_by_name(edev, cable_name);
+ if (id < 0)
+ return id;
+
+ return extcon_set_cable_state_(edev, id, cable_state);
}
EXPORT_SYMBOL_GPL(extcon_set_cable_state);
@@ -417,6 +448,9 @@
{
struct extcon_dev *sd;
+ if (!extcon_name)
+ return ERR_PTR(-EINVAL);
+
mutex_lock(&extcon_dev_list_lock);
list_for_each_entry(sd, &extcon_dev_list, entry) {
if (!strcmp(sd->name, extcon_name))
@@ -545,6 +579,9 @@
unsigned long flags;
int ret, idx;
+ if (!edev || !nb)
+ return -EINVAL;
+
idx = find_cable_index_by_id(edev, id);
spin_lock_irqsave(&edev->lock, flags);
@@ -567,6 +604,9 @@
unsigned long flags;
int ret, idx;
+ if (!edev || !nb)
+ return -EINVAL;
+
idx = find_cable_index_by_id(edev, id);
spin_lock_irqsave(&edev->lock, flags);
@@ -627,6 +667,9 @@
{
struct extcon_dev *edev;
+ if (!supported_cable)
+ return ERR_PTR(-EINVAL);
+
edev = kzalloc(sizeof(*edev), GFP_KERNEL);
if (!edev)
return ERR_PTR(-ENOMEM);
@@ -727,7 +770,7 @@
return ret;
}
- if (!edev->supported_cable)
+ if (!edev || !edev->supported_cable)
return -EINVAL;
for (; edev->supported_cable[index] != EXTCON_NONE; index++);
@@ -933,6 +976,9 @@
{
int index;
+ if (!edev)
+ return;
+
mutex_lock(&extcon_dev_list_lock);
list_del(&edev->entry);
mutex_unlock(&extcon_dev_list_lock);
@@ -1039,6 +1085,9 @@
struct device_node *node;
struct extcon_dev *edev;
+ if (!dev)
+ return ERR_PTR(-EINVAL);
+
if (!dev->of_node) {
dev_err(dev, "device does not have a device node entry\n");
return ERR_PTR(-EINVAL);
diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c
index 87add3f..e415945 100644
--- a/drivers/firmware/broadcom/bcm47xx_nvram.c
+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c
@@ -245,4 +245,4 @@
}
EXPORT_SYMBOL(bcm47xx_nvram_get_contents);
-MODULE_LICENSE("GPLv2");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index 4fd9961..d425374 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -305,10 +305,17 @@
return ret;
}
-static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem)
+static void cper_print_mem(const char *pfx, const struct cper_sec_mem_err *mem,
+ int len)
{
struct cper_mem_err_compact cmem;
+ /* Don't trust UEFI 2.1/2.2 structure with bad validation bits */
+ if (len == sizeof(struct cper_sec_mem_err_old) &&
+ (mem->validation_bits & ~(CPER_MEM_VALID_RANK_NUMBER - 1))) {
+ pr_err(FW_WARN "valid bits set for fields beyond structure\n");
+ return;
+ }
if (mem->validation_bits & CPER_MEM_VALID_ERROR_STATUS)
printk("%s""error_status: 0x%016llx\n", pfx, mem->error_status);
if (mem->validation_bits & CPER_MEM_VALID_PA)
@@ -405,8 +412,10 @@
} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PLATFORM_MEM)) {
struct cper_sec_mem_err *mem_err = (void *)(gdata + 1);
printk("%s""section_type: memory error\n", newpfx);
- if (gdata->error_data_length >= sizeof(*mem_err))
- cper_print_mem(newpfx, mem_err);
+ if (gdata->error_data_length >=
+ sizeof(struct cper_sec_mem_err_old))
+ cper_print_mem(newpfx, mem_err,
+ gdata->error_data_length);
else
goto err_section_too_small;
} else if (!uuid_le_cmp(*sec_type, CPER_SEC_PCIE)) {
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 9fa8084..d6144e3 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -58,6 +58,11 @@
static int __init parse_efi_cmdline(char *str)
{
+ if (!str) {
+ pr_warn("need at least one option\n");
+ return -EINVAL;
+ }
+
if (parse_option_str(str, "noruntime"))
disable_runtime = true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 0165783..f7b49d5c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1130,6 +1130,9 @@
uint32_t me_feature_version;
uint32_t ce_feature_version;
uint32_t pfp_feature_version;
+ uint32_t rlc_feature_version;
+ uint32_t mec_feature_version;
+ uint32_t mec2_feature_version;
struct amdgpu_ring gfx_ring[AMDGPU_MAX_GFX_RINGS];
unsigned num_gfx_rings;
struct amdgpu_ring compute_ring[AMDGPU_MAX_COMPUTE_RINGS];
@@ -1614,6 +1617,9 @@
#define AMDGPU_MAX_VCE_HANDLES 16
#define AMDGPU_VCE_FIRMWARE_OFFSET 256
+#define AMDGPU_VCE_HARVEST_VCE0 (1 << 0)
+#define AMDGPU_VCE_HARVEST_VCE1 (1 << 1)
+
struct amdgpu_vce {
struct amdgpu_bo *vcpu_bo;
uint64_t gpu_addr;
@@ -1626,6 +1632,7 @@
const struct firmware *fw; /* VCE firmware */
struct amdgpu_ring ring[AMDGPU_MAX_VCE_RINGS];
struct amdgpu_irq_src irq;
+ unsigned harvest_config;
};
/*
@@ -1635,6 +1642,7 @@
/* SDMA firmware */
const struct firmware *fw;
uint32_t fw_version;
+ uint32_t feature_version;
struct amdgpu_ring ring;
};
@@ -1862,6 +1870,12 @@
typedef uint32_t (*amdgpu_block_rreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
typedef void (*amdgpu_block_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t, uint32_t);
+struct amdgpu_ip_block_status {
+ bool valid;
+ bool sw;
+ bool hw;
+};
+
struct amdgpu_device {
struct device *dev;
struct drm_device *ddev;
@@ -2004,7 +2018,7 @@
const struct amdgpu_ip_block_version *ip_blocks;
int num_ip_blocks;
- bool *ip_block_enabled;
+ struct amdgpu_ip_block_status *ip_block_status;
struct mutex mn_lock;
DECLARE_HASHTABLE(mn_hash, 7);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index d79009b..99f158e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1191,8 +1191,9 @@
return -EINVAL;
}
- adev->ip_block_enabled = kcalloc(adev->num_ip_blocks, sizeof(bool), GFP_KERNEL);
- if (adev->ip_block_enabled == NULL)
+ adev->ip_block_status = kcalloc(adev->num_ip_blocks,
+ sizeof(struct amdgpu_ip_block_status), GFP_KERNEL);
+ if (adev->ip_block_status == NULL)
return -ENOMEM;
if (adev->ip_blocks == NULL) {
@@ -1203,18 +1204,18 @@
for (i = 0; i < adev->num_ip_blocks; i++) {
if ((amdgpu_ip_block_mask & (1 << i)) == 0) {
DRM_ERROR("disabled ip block: %d\n", i);
- adev->ip_block_enabled[i] = false;
+ adev->ip_block_status[i].valid = false;
} else {
if (adev->ip_blocks[i].funcs->early_init) {
r = adev->ip_blocks[i].funcs->early_init((void *)adev);
if (r == -ENOENT)
- adev->ip_block_enabled[i] = false;
+ adev->ip_block_status[i].valid = false;
else if (r)
return r;
else
- adev->ip_block_enabled[i] = true;
+ adev->ip_block_status[i].valid = true;
} else {
- adev->ip_block_enabled[i] = true;
+ adev->ip_block_status[i].valid = true;
}
}
}
@@ -1227,11 +1228,12 @@
int i, r;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_enabled[i])
+ if (!adev->ip_block_status[i].valid)
continue;
r = adev->ip_blocks[i].funcs->sw_init((void *)adev);
if (r)
return r;
+ adev->ip_block_status[i].sw = true;
/* need to do gmc hw init early so we can allocate gpu mem */
if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
r = amdgpu_vram_scratch_init(adev);
@@ -1243,11 +1245,12 @@
r = amdgpu_wb_init(adev);
if (r)
return r;
+ adev->ip_block_status[i].hw = true;
}
}
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_enabled[i])
+ if (!adev->ip_block_status[i].sw)
continue;
/* gmc hw init is done early */
if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC)
@@ -1255,6 +1258,7 @@
r = adev->ip_blocks[i].funcs->hw_init((void *)adev);
if (r)
return r;
+ adev->ip_block_status[i].hw = true;
}
return 0;
@@ -1265,7 +1269,7 @@
int i = 0, r;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_enabled[i])
+ if (!adev->ip_block_status[i].valid)
continue;
/* enable clockgating to save power */
r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
@@ -1287,7 +1291,7 @@
int i, r;
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
- if (!adev->ip_block_enabled[i])
+ if (!adev->ip_block_status[i].hw)
continue;
if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) {
amdgpu_wb_fini(adev);
@@ -1300,14 +1304,16 @@
return r;
r = adev->ip_blocks[i].funcs->hw_fini((void *)adev);
/* XXX handle errors */
+ adev->ip_block_status[i].hw = false;
}
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
- if (!adev->ip_block_enabled[i])
+ if (!adev->ip_block_status[i].sw)
continue;
r = adev->ip_blocks[i].funcs->sw_fini((void *)adev);
/* XXX handle errors */
- adev->ip_block_enabled[i] = false;
+ adev->ip_block_status[i].sw = false;
+ adev->ip_block_status[i].valid = false;
}
return 0;
@@ -1318,7 +1324,7 @@
int i, r;
for (i = adev->num_ip_blocks - 1; i >= 0; i--) {
- if (!adev->ip_block_enabled[i])
+ if (!adev->ip_block_status[i].valid)
continue;
/* ungate blocks so that suspend can properly shut them down */
r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev,
@@ -1336,7 +1342,7 @@
int i, r;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_block_enabled[i])
+ if (!adev->ip_block_status[i].valid)
continue;
r = adev->ip_blocks[i].funcs->resume(adev);
if (r)
@@ -1582,8 +1588,8 @@
amdgpu_fence_driver_fini(adev);
amdgpu_fbdev_fini(adev);
r = amdgpu_fini(adev);
- kfree(adev->ip_block_enabled);
- adev->ip_block_enabled = NULL;
+ kfree(adev->ip_block_status);
+ adev->ip_block_status = NULL;
adev->accel_working = false;
/* free i2c buses */
amdgpu_i2c_fini(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index ae43b58..4afc507 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -449,7 +449,7 @@
* vital here, so they are not reported back to userspace.
*/
static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
- struct amdgpu_bo_va *bo_va)
+ struct amdgpu_bo_va *bo_va, uint32_t operation)
{
struct ttm_validate_buffer tv, *entry;
struct amdgpu_bo_list_entry *vm_bos;
@@ -485,7 +485,9 @@
if (r)
goto error_unlock;
- r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem);
+
+ if (operation == AMDGPU_VA_OP_MAP)
+ r = amdgpu_vm_bo_update(adev, bo_va, &bo_va->bo->tbo.mem);
error_unlock:
mutex_unlock(&bo_va->vm->mutex);
@@ -580,7 +582,7 @@
}
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE))
- amdgpu_gem_va_update_vm(adev, bo_va);
+ amdgpu_gem_va_update_vm(adev, bo_va, args->operation);
drm_gem_object_unreference_unlocked(gobj);
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 52dff75..bc0fac6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -180,17 +180,17 @@
if (vm) {
/* do context switch */
amdgpu_vm_flush(ring, vm, ib->sync.last_vm_update);
+
+ if (ring->funcs->emit_gds_switch)
+ amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id,
+ ib->gds_base, ib->gds_size,
+ ib->gws_base, ib->gws_size,
+ ib->oa_base, ib->oa_size);
+
+ if (ring->funcs->emit_hdp_flush)
+ amdgpu_ring_emit_hdp_flush(ring);
}
- if (vm && ring->funcs->emit_gds_switch)
- amdgpu_ring_emit_gds_switch(ring, ib->vm->ids[ring->idx].id,
- ib->gds_base, ib->gds_size,
- ib->gws_base, ib->gws_size,
- ib->oa_base, ib->oa_size);
-
- if (ring->funcs->emit_hdp_flush)
- amdgpu_ring_emit_hdp_flush(ring);
-
old_ctx = ring->current_ctx;
for (i = 0; i < num_ibs; ++i) {
ib = &ibs[i];
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 5533434..3bfe67d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -235,7 +235,7 @@
for (i = 0; i < adev->num_ip_blocks; i++) {
if (adev->ip_blocks[i].type == type &&
- adev->ip_block_enabled[i]) {
+ adev->ip_block_status[i].valid) {
ip.hw_ip_version_major = adev->ip_blocks[i].major;
ip.hw_ip_version_minor = adev->ip_blocks[i].minor;
ip.capabilities_flags = 0;
@@ -274,7 +274,7 @@
for (i = 0; i < adev->num_ip_blocks; i++)
if (adev->ip_blocks[i].type == type &&
- adev->ip_block_enabled[i] &&
+ adev->ip_block_status[i].valid &&
count < AMDGPU_HW_IP_INSTANCE_MAX_COUNT)
count++;
@@ -317,16 +317,17 @@
break;
case AMDGPU_INFO_FW_GFX_RLC:
fw_info.ver = adev->gfx.rlc_fw_version;
- fw_info.feature = 0;
+ fw_info.feature = adev->gfx.rlc_feature_version;
break;
case AMDGPU_INFO_FW_GFX_MEC:
- if (info->query_fw.index == 0)
+ if (info->query_fw.index == 0) {
fw_info.ver = adev->gfx.mec_fw_version;
- else if (info->query_fw.index == 1)
+ fw_info.feature = adev->gfx.mec_feature_version;
+ } else if (info->query_fw.index == 1) {
fw_info.ver = adev->gfx.mec2_fw_version;
- else
+ fw_info.feature = adev->gfx.mec2_feature_version;
+ } else
return -EINVAL;
- fw_info.feature = 0;
break;
case AMDGPU_INFO_FW_SMC:
fw_info.ver = adev->pm.fw_version;
@@ -336,7 +337,7 @@
if (info->query_fw.index >= 2)
return -EINVAL;
fw_info.ver = adev->sdma[info->query_fw.index].fw_version;
- fw_info.feature = 0;
+ fw_info.feature = adev->sdma[info->query_fw.index].feature_version;
break;
default:
return -EINVAL;
@@ -416,7 +417,7 @@
return n ? -EFAULT : 0;
}
case AMDGPU_INFO_DEV_INFO: {
- struct drm_amdgpu_info_device dev_info;
+ struct drm_amdgpu_info_device dev_info = {};
struct amdgpu_cu_info cu_info;
dev_info.device_id = dev->pdev->device;
@@ -459,6 +460,7 @@
memcpy(&dev_info.cu_bitmap[0], &cu_info.bitmap[0], sizeof(cu_info.bitmap));
dev_info.vram_type = adev->mc.vram_type;
dev_info.vram_bit_width = adev->mc.vram_width;
+ dev_info.vce_harvest_config = adev->vce.harvest_config;
return copy_to_user(out, &dev_info,
min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 2f7a5ef..f5c2255 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -374,7 +374,7 @@
unsigned height_in_mb = ALIGN(height / 16, 2);
unsigned fs_in_mb = width_in_mb * height_in_mb;
- unsigned image_size, tmp, min_dpb_size, num_dpb_buffer;
+ unsigned image_size, tmp, min_dpb_size, num_dpb_buffer, min_ctx_size;
image_size = width * height;
image_size += image_size / 2;
@@ -466,6 +466,8 @@
num_dpb_buffer = (le32_to_cpu(msg[59]) & 0xff) + 2;
min_dpb_size = image_size * num_dpb_buffer;
+ min_ctx_size = ((width + 255) / 16) * ((height + 255) / 16)
+ * 16 * num_dpb_buffer + 52 * 1024;
break;
default:
@@ -486,6 +488,7 @@
buf_sizes[0x1] = dpb_size;
buf_sizes[0x2] = image_size;
+ buf_sizes[0x4] = min_ctx_size;
return 0;
}
@@ -628,6 +631,13 @@
return -EINVAL;
}
+ } else if (cmd == 0x206) {
+ if ((end - start) < ctx->buf_sizes[4]) {
+ DRM_ERROR("buffer (%d) to small (%d / %d)!\n", cmd,
+ (unsigned)(end - start),
+ ctx->buf_sizes[4]);
+ return -EINVAL;
+ }
} else if ((cmd != 0x100) && (cmd != 0x204)) {
DRM_ERROR("invalid UVD command %X!\n", cmd);
return -EINVAL;
@@ -755,9 +765,10 @@
struct amdgpu_uvd_cs_ctx ctx = {};
unsigned buf_sizes[] = {
[0x00000000] = 2048,
- [0x00000001] = 32 * 1024 * 1024,
- [0x00000002] = 2048 * 1152 * 3,
+ [0x00000001] = 0xFFFFFFFF,
+ [0x00000002] = 0xFFFFFFFF,
[0x00000003] = 2048,
+ [0x00000004] = 0xFFFFFFFF,
};
struct amdgpu_ib *ib = &parser->ibs[ib_idx];
int r;
diff --git a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
index ab83cc1..15df46c 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik_sdma.c
@@ -500,6 +500,7 @@
amdgpu_ucode_print_sdma_hdr(&hdr->header);
fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
+ adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
fw_data = (const __le32 *)
(adev->sdma[i].fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0);
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
index 1a2d419..ace870a 100644
--- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c
@@ -494,29 +494,67 @@
amdgpu_free_extended_power_table(adev);
}
+#define ixSMUSVI_NB_CURRENTVID 0xD8230044
+#define CURRENT_NB_VID_MASK 0xff000000
+#define CURRENT_NB_VID__SHIFT 24
+#define ixSMUSVI_GFX_CURRENTVID 0xD8230048
+#define CURRENT_GFX_VID_MASK 0xff000000
+#define CURRENT_GFX_VID__SHIFT 24
+
static void
cz_dpm_debugfs_print_current_performance_level(struct amdgpu_device *adev,
struct seq_file *m)
{
+ struct cz_power_info *pi = cz_get_pi(adev);
struct amdgpu_clock_voltage_dependency_table *table =
&adev->pm.dpm.dyn_state.vddc_dependency_on_sclk;
- u32 current_index =
- (RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX) &
- TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX_MASK) >>
- TARGET_AND_CURRENT_PROFILE_INDEX__CURR_SCLK_INDEX__SHIFT;
- u32 sclk, tmp;
- u16 vddc;
+ struct amdgpu_uvd_clock_voltage_dependency_table *uvd_table =
+ &adev->pm.dpm.dyn_state.uvd_clock_voltage_dependency_table;
+ struct amdgpu_vce_clock_voltage_dependency_table *vce_table =
+ &adev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table;
+ u32 sclk_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX),
+ TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX);
+ u32 uvd_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
+ TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX);
+ u32 vce_index = REG_GET_FIELD(RREG32_SMC(ixTARGET_AND_CURRENT_PROFILE_INDEX_2),
+ TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX);
+ u32 sclk, vclk, dclk, ecclk, tmp;
+ u16 vddnb, vddgfx;
- if (current_index >= NUM_SCLK_LEVELS) {
- seq_printf(m, "invalid dpm profile %d\n", current_index);
+ if (sclk_index >= NUM_SCLK_LEVELS) {
+ seq_printf(m, "invalid sclk dpm profile %d\n", sclk_index);
} else {
- sclk = table->entries[current_index].clk;
- tmp = (RREG32_SMC(ixSMU_VOLTAGE_STATUS) &
- SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL_MASK) >>
- SMU_VOLTAGE_STATUS__SMU_VOLTAGE_CURRENT_LEVEL__SHIFT;
- vddc = cz_convert_8bit_index_to_voltage(adev, (u16)tmp);
- seq_printf(m, "power level %d sclk: %u vddc: %u\n",
- current_index, sclk, vddc);
+ sclk = table->entries[sclk_index].clk;
+ seq_printf(m, "%u sclk: %u\n", sclk_index, sclk);
+ }
+
+ tmp = (RREG32_SMC(ixSMUSVI_NB_CURRENTVID) &
+ CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT;
+ vddnb = cz_convert_8bit_index_to_voltage(adev, (u16)tmp);
+ tmp = (RREG32_SMC(ixSMUSVI_GFX_CURRENTVID) &
+ CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT;
+ vddgfx = cz_convert_8bit_index_to_voltage(adev, (u16)tmp);
+ seq_printf(m, "vddnb: %u vddgfx: %u\n", vddnb, vddgfx);
+
+ seq_printf(m, "uvd %sabled\n", pi->uvd_power_gated ? "dis" : "en");
+ if (!pi->uvd_power_gated) {
+ if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
+ seq_printf(m, "invalid uvd dpm level %d\n", uvd_index);
+ } else {
+ vclk = uvd_table->entries[uvd_index].vclk;
+ dclk = uvd_table->entries[uvd_index].dclk;
+ seq_printf(m, "%u uvd vclk: %u dclk: %u\n", uvd_index, vclk, dclk);
+ }
+ }
+
+ seq_printf(m, "vce %sabled\n", pi->vce_power_gated ? "dis" : "en");
+ if (!pi->vce_power_gated) {
+ if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) {
+ seq_printf(m, "invalid vce dpm level %d\n", vce_index);
+ } else {
+ ecclk = vce_table->entries[vce_index].ecclk;
+ seq_printf(m, "%u vce ecclk: %u\n", vce_index, ecclk);
+ }
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 6e77964..e70a26f 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -2632,6 +2632,7 @@
struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ unsigned type;
switch (mode) {
case DRM_MODE_DPMS_ON:
@@ -2640,6 +2641,9 @@
dce_v10_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v10_0_vga_enable(crtc, false);
+ /* Make sure VBLANK interrupt is still enabled */
+ type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
+ amdgpu_irq_update(adev, &adev->crtc_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v10_0_crtc_load_lut(crtc);
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index 7f7abb0..dcb402e 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -2631,6 +2631,7 @@
struct drm_device *dev = crtc->dev;
struct amdgpu_device *adev = dev->dev_private;
struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
+ unsigned type;
switch (mode) {
case DRM_MODE_DPMS_ON:
@@ -2639,6 +2640,9 @@
dce_v11_0_vga_enable(crtc, true);
amdgpu_atombios_crtc_blank(crtc, ATOM_DISABLE);
dce_v11_0_vga_enable(crtc, false);
+ /* Make sure VBLANK interrupt is still enabled */
+ type = amdgpu_crtc_idx_to_irq_type(adev, amdgpu_crtc->crtc_id);
+ amdgpu_irq_update(adev, &adev->crtc_irq, type);
drm_vblank_post_modeset(dev, amdgpu_crtc->crtc_id);
dce_v11_0_crtc_load_lut(crtc);
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
index 2c188fb..0d8bf2c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v7_0.c
@@ -2561,7 +2561,7 @@
* sheduling on the ring. This function schedules the IB
* on the gfx ring for execution by the GPU.
*/
-static void gfx_v7_0_ring_emit_ib(struct amdgpu_ring *ring,
+static void gfx_v7_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
struct amdgpu_ib *ib)
{
bool need_ctx_switch = ring->current_ctx != ib->ctx;
@@ -2569,15 +2569,10 @@
u32 next_rptr = ring->wptr + 5;
/* drop the CE preamble IB for the same context */
- if ((ring->type == AMDGPU_RING_TYPE_GFX) &&
- (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) &&
- !need_ctx_switch)
+ if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch)
return;
- if (ring->type == AMDGPU_RING_TYPE_COMPUTE)
- control |= INDIRECT_BUFFER_VALID;
-
- if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX)
+ if (need_ctx_switch)
next_rptr += 2;
next_rptr += 4;
@@ -2588,7 +2583,7 @@
amdgpu_ring_write(ring, next_rptr);
/* insert SWITCH_BUFFER packet before first IB in the ring frame */
- if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) {
+ if (need_ctx_switch) {
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
amdgpu_ring_write(ring, 0);
}
@@ -2611,6 +2606,35 @@
amdgpu_ring_write(ring, control);
}
+static void gfx_v7_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
+ struct amdgpu_ib *ib)
+{
+ u32 header, control = 0;
+ u32 next_rptr = ring->wptr + 5;
+
+ control |= INDIRECT_BUFFER_VALID;
+ next_rptr += 4;
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+ amdgpu_ring_write(ring, WRITE_DATA_DST_SEL(5) | WR_CONFIRM);
+ amdgpu_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
+ amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff);
+ amdgpu_ring_write(ring, next_rptr);
+
+ header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
+
+ control |= ib->length_dw |
+ (ib->vm ? (ib->vm->ids[ring->idx].id << 24) : 0);
+
+ amdgpu_ring_write(ring, header);
+ amdgpu_ring_write(ring,
+#ifdef __BIG_ENDIAN
+ (2 << 0) |
+#endif
+ (ib->gpu_addr & 0xFFFFFFFC));
+ amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF);
+ amdgpu_ring_write(ring, control);
+}
+
/**
* gfx_v7_0_ring_test_ib - basic ring IB test
*
@@ -3056,6 +3080,8 @@
mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
amdgpu_ucode_print_gfx_hdr(&mec_hdr->header);
adev->gfx.mec_fw_version = le32_to_cpu(mec_hdr->header.ucode_version);
+ adev->gfx.mec_feature_version = le32_to_cpu(
+ mec_hdr->ucode_feature_version);
gfx_v7_0_cp_compute_enable(adev, false);
@@ -3078,6 +3104,8 @@
mec2_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->data;
amdgpu_ucode_print_gfx_hdr(&mec2_hdr->header);
adev->gfx.mec2_fw_version = le32_to_cpu(mec2_hdr->header.ucode_version);
+ adev->gfx.mec2_feature_version = le32_to_cpu(
+ mec2_hdr->ucode_feature_version);
/* MEC2 */
fw_data = (const __le32 *)
@@ -4042,6 +4070,8 @@
hdr = (const struct rlc_firmware_header_v1_0 *)adev->gfx.rlc_fw->data;
amdgpu_ucode_print_rlc_hdr(&hdr->header);
adev->gfx.rlc_fw_version = le32_to_cpu(hdr->header.ucode_version);
+ adev->gfx.rlc_feature_version = le32_to_cpu(
+ hdr->ucode_feature_version);
gfx_v7_0_rlc_stop(adev);
@@ -5098,7 +5128,7 @@
dev_info(adev->dev, " CP_HPD_EOP_CONTROL=0x%08X\n",
RREG32(mmCP_HPD_EOP_CONTROL));
- for (queue = 0; queue < 8; i++) {
+ for (queue = 0; queue < 8; queue++) {
cik_srbm_select(adev, me, pipe, queue, 0);
dev_info(adev->dev, " queue: %d\n", queue);
dev_info(adev->dev, " CP_PQ_WPTR_POLL_CNTL=0x%08X\n",
@@ -5555,7 +5585,7 @@
.get_wptr = gfx_v7_0_ring_get_wptr_gfx,
.set_wptr = gfx_v7_0_ring_set_wptr_gfx,
.parse_cs = NULL,
- .emit_ib = gfx_v7_0_ring_emit_ib,
+ .emit_ib = gfx_v7_0_ring_emit_ib_gfx,
.emit_fence = gfx_v7_0_ring_emit_fence_gfx,
.emit_semaphore = gfx_v7_0_ring_emit_semaphore,
.emit_vm_flush = gfx_v7_0_ring_emit_vm_flush,
@@ -5571,7 +5601,7 @@
.get_wptr = gfx_v7_0_ring_get_wptr_compute,
.set_wptr = gfx_v7_0_ring_set_wptr_compute,
.parse_cs = NULL,
- .emit_ib = gfx_v7_0_ring_emit_ib,
+ .emit_ib = gfx_v7_0_ring_emit_ib_compute,
.emit_fence = gfx_v7_0_ring_emit_fence_compute,
.emit_semaphore = gfx_v7_0_ring_emit_semaphore,
.emit_vm_flush = gfx_v7_0_ring_emit_vm_flush,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 1c7c992..20e2cfd 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -587,6 +587,7 @@
int err;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
+ const struct gfx_firmware_header_v1_0 *cp_hdr;
DRM_DEBUG("\n");
@@ -611,6 +612,9 @@
err = amdgpu_ucode_validate(adev->gfx.pfp_fw);
if (err)
goto out;
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.pfp_fw->data;
+ adev->gfx.pfp_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
+ adev->gfx.pfp_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_me.bin", chip_name);
err = request_firmware(&adev->gfx.me_fw, fw_name, adev->dev);
@@ -619,6 +623,9 @@
err = amdgpu_ucode_validate(adev->gfx.me_fw);
if (err)
goto out;
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.me_fw->data;
+ adev->gfx.me_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
+ adev->gfx.me_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ce.bin", chip_name);
err = request_firmware(&adev->gfx.ce_fw, fw_name, adev->dev);
@@ -627,12 +634,18 @@
err = amdgpu_ucode_validate(adev->gfx.ce_fw);
if (err)
goto out;
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.ce_fw->data;
+ adev->gfx.ce_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
+ adev->gfx.ce_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_rlc.bin", chip_name);
err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev);
if (err)
goto out;
err = amdgpu_ucode_validate(adev->gfx.rlc_fw);
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.rlc_fw->data;
+ adev->gfx.rlc_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
+ adev->gfx.rlc_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec.bin", chip_name);
err = request_firmware(&adev->gfx.mec_fw, fw_name, adev->dev);
@@ -641,6 +654,9 @@
err = amdgpu_ucode_validate(adev->gfx.mec_fw);
if (err)
goto out;
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
+ adev->gfx.mec_fw_version = le32_to_cpu(cp_hdr->header.ucode_version);
+ adev->gfx.mec_feature_version = le32_to_cpu(cp_hdr->ucode_feature_version);
snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_mec2.bin", chip_name);
err = request_firmware(&adev->gfx.mec2_fw, fw_name, adev->dev);
@@ -648,6 +664,12 @@
err = amdgpu_ucode_validate(adev->gfx.mec2_fw);
if (err)
goto out;
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)
+ adev->gfx.mec2_fw->data;
+ adev->gfx.mec2_fw_version = le32_to_cpu(
+ cp_hdr->header.ucode_version);
+ adev->gfx.mec2_feature_version = le32_to_cpu(
+ cp_hdr->ucode_feature_version);
} else {
err = 0;
adev->gfx.mec2_fw = NULL;
@@ -1983,6 +2005,7 @@
adev->gfx.config.max_shader_engines = 1;
adev->gfx.config.max_tile_pipes = 2;
adev->gfx.config.max_sh_per_se = 1;
+ adev->gfx.config.max_backends_per_se = 2;
switch (adev->pdev->revision) {
case 0xc4:
@@ -1991,7 +2014,6 @@
case 0xcc:
/* B10 */
adev->gfx.config.max_cu_per_sh = 8;
- adev->gfx.config.max_backends_per_se = 2;
break;
case 0xc5:
case 0x81:
@@ -2000,14 +2022,12 @@
case 0xcd:
/* B8 */
adev->gfx.config.max_cu_per_sh = 6;
- adev->gfx.config.max_backends_per_se = 2;
break;
case 0xc6:
case 0xca:
case 0xce:
/* B6 */
adev->gfx.config.max_cu_per_sh = 6;
- adev->gfx.config.max_backends_per_se = 2;
break;
case 0xc7:
case 0x87:
@@ -2015,7 +2035,6 @@
default:
/* B4 */
adev->gfx.config.max_cu_per_sh = 4;
- adev->gfx.config.max_backends_per_se = 1;
break;
}
@@ -2275,7 +2294,6 @@
hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
amdgpu_ucode_print_rlc_hdr(&hdr->header);
- adev->gfx.rlc_fw_version = le32_to_cpu(hdr->header.ucode_version);
fw_data = (const __le32 *)(adev->gfx.rlc_fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
@@ -2361,12 +2379,6 @@
amdgpu_ucode_print_gfx_hdr(&pfp_hdr->header);
amdgpu_ucode_print_gfx_hdr(&ce_hdr->header);
amdgpu_ucode_print_gfx_hdr(&me_hdr->header);
- adev->gfx.pfp_fw_version = le32_to_cpu(pfp_hdr->header.ucode_version);
- adev->gfx.ce_fw_version = le32_to_cpu(ce_hdr->header.ucode_version);
- adev->gfx.me_fw_version = le32_to_cpu(me_hdr->header.ucode_version);
- adev->gfx.me_feature_version = le32_to_cpu(me_hdr->ucode_feature_version);
- adev->gfx.ce_feature_version = le32_to_cpu(ce_hdr->ucode_feature_version);
- adev->gfx.pfp_feature_version = le32_to_cpu(pfp_hdr->ucode_feature_version);
gfx_v8_0_cp_gfx_enable(adev, false);
@@ -2622,7 +2634,6 @@
mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
amdgpu_ucode_print_gfx_hdr(&mec_hdr->header);
- adev->gfx.mec_fw_version = le32_to_cpu(mec_hdr->header.ucode_version);
fw_data = (const __le32 *)
(adev->gfx.mec_fw->data +
@@ -2641,7 +2652,6 @@
mec2_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->data;
amdgpu_ucode_print_gfx_hdr(&mec2_hdr->header);
- adev->gfx.mec2_fw_version = le32_to_cpu(mec2_hdr->header.ucode_version);
fw_data = (const __le32 *)
(adev->gfx.mec2_fw->data +
@@ -3125,7 +3135,7 @@
WREG32(mmCP_MEC_DOORBELL_RANGE_LOWER,
AMDGPU_DOORBELL_KIQ << 2);
WREG32(mmCP_MEC_DOORBELL_RANGE_UPPER,
- 0x7FFFF << 2);
+ AMDGPU_DOORBELL_MEC_RING7 << 2);
}
tmp = RREG32(mmCP_HQD_PQ_DOORBELL_CONTROL);
tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
@@ -3753,7 +3763,7 @@
amdgpu_ring_write(ring, 0x20); /* poll interval */
}
-static void gfx_v8_0_ring_emit_ib(struct amdgpu_ring *ring,
+static void gfx_v8_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
struct amdgpu_ib *ib)
{
bool need_ctx_switch = ring->current_ctx != ib->ctx;
@@ -3761,15 +3771,10 @@
u32 next_rptr = ring->wptr + 5;
/* drop the CE preamble IB for the same context */
- if ((ring->type == AMDGPU_RING_TYPE_GFX) &&
- (ib->flags & AMDGPU_IB_FLAG_PREAMBLE) &&
- !need_ctx_switch)
+ if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && !need_ctx_switch)
return;
- if (ring->type == AMDGPU_RING_TYPE_COMPUTE)
- control |= INDIRECT_BUFFER_VALID;
-
- if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX)
+ if (need_ctx_switch)
next_rptr += 2;
next_rptr += 4;
@@ -3780,7 +3785,7 @@
amdgpu_ring_write(ring, next_rptr);
/* insert SWITCH_BUFFER packet before first IB in the ring frame */
- if (need_ctx_switch && ring->type == AMDGPU_RING_TYPE_GFX) {
+ if (need_ctx_switch) {
amdgpu_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
amdgpu_ring_write(ring, 0);
}
@@ -3803,6 +3808,36 @@
amdgpu_ring_write(ring, control);
}
+static void gfx_v8_0_ring_emit_ib_compute(struct amdgpu_ring *ring,
+ struct amdgpu_ib *ib)
+{
+ u32 header, control = 0;
+ u32 next_rptr = ring->wptr + 5;
+
+ control |= INDIRECT_BUFFER_VALID;
+
+ next_rptr += 4;
+ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
+ amdgpu_ring_write(ring, WRITE_DATA_DST_SEL(5) | WR_CONFIRM);
+ amdgpu_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
+ amdgpu_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff);
+ amdgpu_ring_write(ring, next_rptr);
+
+ header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
+
+ control |= ib->length_dw |
+ (ib->vm ? (ib->vm->ids[ring->idx].id << 24) : 0);
+
+ amdgpu_ring_write(ring, header);
+ amdgpu_ring_write(ring,
+#ifdef __BIG_ENDIAN
+ (2 << 0) |
+#endif
+ (ib->gpu_addr & 0xFFFFFFFC));
+ amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF);
+ amdgpu_ring_write(ring, control);
+}
+
static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
u64 seq, unsigned flags)
{
@@ -4224,7 +4259,7 @@
.get_wptr = gfx_v8_0_ring_get_wptr_gfx,
.set_wptr = gfx_v8_0_ring_set_wptr_gfx,
.parse_cs = NULL,
- .emit_ib = gfx_v8_0_ring_emit_ib,
+ .emit_ib = gfx_v8_0_ring_emit_ib_gfx,
.emit_fence = gfx_v8_0_ring_emit_fence_gfx,
.emit_semaphore = gfx_v8_0_ring_emit_semaphore,
.emit_vm_flush = gfx_v8_0_ring_emit_vm_flush,
@@ -4240,7 +4275,7 @@
.get_wptr = gfx_v8_0_ring_get_wptr_compute,
.set_wptr = gfx_v8_0_ring_set_wptr_compute,
.parse_cs = NULL,
- .emit_ib = gfx_v8_0_ring_emit_ib,
+ .emit_ib = gfx_v8_0_ring_emit_ib_compute,
.emit_fence = gfx_v8_0_ring_emit_fence_compute,
.emit_semaphore = gfx_v8_0_ring_emit_semaphore,
.emit_vm_flush = gfx_v8_0_ring_emit_vm_flush,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index d789588..a988dfb 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -121,6 +121,7 @@
int err, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
+ const struct sdma_firmware_header_v1_0 *hdr;
DRM_DEBUG("\n");
@@ -142,6 +143,9 @@
err = amdgpu_ucode_validate(adev->sdma[i].fw);
if (err)
goto out;
+ hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
+ adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
+ adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
if (adev->firmware.smu_load) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
@@ -541,8 +545,6 @@
hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
amdgpu_ucode_print_sdma_hdr(&hdr->header);
fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
- adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
-
fw_data = (const __le32 *)
(adev->sdma[i].fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 7bb37b9..2b86569 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -159,6 +159,7 @@
int err, i;
struct amdgpu_firmware_info *info = NULL;
const struct common_firmware_header *header = NULL;
+ const struct sdma_firmware_header_v1_0 *hdr;
DRM_DEBUG("\n");
@@ -183,6 +184,9 @@
err = amdgpu_ucode_validate(adev->sdma[i].fw);
if (err)
goto out;
+ hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
+ adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
+ adev->sdma[i].feature_version = le32_to_cpu(hdr->ucode_feature_version);
if (adev->firmware.smu_load) {
info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
@@ -630,8 +634,6 @@
hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma[i].fw->data;
amdgpu_ucode_print_sdma_hdr(&hdr->header);
fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
- adev->sdma[i].fw_version = le32_to_cpu(hdr->header.ucode_version);
-
fw_data = (const __le32 *)
(adev->sdma[i].fw->data +
le32_to_cpu(hdr->header.ucode_array_offset_bytes));
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index d62c4002..d1064ca 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -35,6 +35,8 @@
#include "oss/oss_2_0_d.h"
#include "oss/oss_2_0_sh_mask.h"
#include "gca/gfx_8_0_d.h"
+#include "smu/smu_7_1_2_d.h"
+#include "smu/smu_7_1_2_sh_mask.h"
#define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04
#define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10
@@ -112,6 +114,10 @@
mutex_lock(&adev->grbm_idx_mutex);
for (idx = 0; idx < 2; ++idx) {
+
+ if (adev->vce.harvest_config & (1 << idx))
+ continue;
+
if(idx == 0)
WREG32_P(mmGRBM_GFX_INDEX, 0,
~GRBM_GFX_INDEX__VCE_INSTANCE_MASK);
@@ -190,10 +196,52 @@
return 0;
}
+#define ixVCE_HARVEST_FUSE_MACRO__ADDRESS 0xC0014074
+#define VCE_HARVEST_FUSE_MACRO__SHIFT 27
+#define VCE_HARVEST_FUSE_MACRO__MASK 0x18000000
+
+static unsigned vce_v3_0_get_harvest_config(struct amdgpu_device *adev)
+{
+ u32 tmp;
+ unsigned ret;
+
+ if (adev->flags & AMDGPU_IS_APU)
+ tmp = (RREG32_SMC(ixVCE_HARVEST_FUSE_MACRO__ADDRESS) &
+ VCE_HARVEST_FUSE_MACRO__MASK) >>
+ VCE_HARVEST_FUSE_MACRO__SHIFT;
+ else
+ tmp = (RREG32_SMC(ixCC_HARVEST_FUSES) &
+ CC_HARVEST_FUSES__VCE_DISABLE_MASK) >>
+ CC_HARVEST_FUSES__VCE_DISABLE__SHIFT;
+
+ switch (tmp) {
+ case 1:
+ ret = AMDGPU_VCE_HARVEST_VCE0;
+ break;
+ case 2:
+ ret = AMDGPU_VCE_HARVEST_VCE1;
+ break;
+ case 3:
+ ret = AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1;
+ break;
+ default:
+ ret = 0;
+ }
+
+ return ret;
+}
+
static int vce_v3_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ adev->vce.harvest_config = vce_v3_0_get_harvest_config(adev);
+
+ if ((adev->vce.harvest_config &
+ (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1)) ==
+ (AMDGPU_VCE_HARVEST_VCE0 | AMDGPU_VCE_HARVEST_VCE1))
+ return -ENOENT;
+
vce_v3_0_set_ring_funcs(adev);
vce_v3_0_set_irq_funcs(adev);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index f69b925..5ae5c69 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -355,6 +355,7 @@
planes->overlays[i]->base.possible_crtcs = 1 << crtc->id;
drm_crtc_helper_add(&crtc->base, &lcdc_crtc_helper_funcs);
+ drm_crtc_vblank_reset(&crtc->base);
dc->crtc = &crtc->base;
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 60b0c13..ef6182b 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -313,6 +313,12 @@
pm_runtime_enable(dev->dev);
+ ret = drm_vblank_init(dev, 1);
+ if (ret < 0) {
+ dev_err(dev->dev, "failed to initialize vblank\n");
+ goto err_periph_clk_disable;
+ }
+
ret = atmel_hlcdc_dc_modeset_init(dev);
if (ret < 0) {
dev_err(dev->dev, "failed to initialize mode setting\n");
@@ -321,12 +327,6 @@
drm_mode_config_reset(dev);
- ret = drm_vblank_init(dev, 1);
- if (ret < 0) {
- dev_err(dev->dev, "failed to initialize vblank\n");
- goto err_periph_clk_disable;
- }
-
pm_runtime_get_sync(dev->dev);
ret = drm_irq_install(dev, dc->hlcdc->irq);
pm_runtime_put_sync(dev->dev);
@@ -559,7 +559,7 @@
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
static int atmel_hlcdc_dc_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 5b59d5ad..9dcc728 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -196,7 +196,12 @@
}
funcs = connector->helper_private;
- new_encoder = funcs->best_encoder(connector);
+
+ if (funcs->atomic_best_encoder)
+ new_encoder = funcs->atomic_best_encoder(connector,
+ connector_state);
+ else
+ new_encoder = funcs->best_encoder(connector);
if (!new_encoder) {
DRM_DEBUG_ATOMIC("No suitable encoder found for [CONNECTOR:%d:%s]\n",
@@ -229,6 +234,9 @@
}
}
+ if (WARN_ON(!connector_state->crtc))
+ return -EINVAL;
+
connector_state->best_encoder = new_encoder;
idx = drm_crtc_index(connector_state->crtc);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 357bd04..fed7483 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -5398,12 +5398,9 @@
if (encoder->funcs->reset)
encoder->funcs->reset(encoder);
- list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
- connector->status = connector_status_unknown;
-
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head)
if (connector->funcs->reset)
connector->funcs->reset(connector);
- }
}
EXPORT_SYMBOL(drm_mode_config_reset);
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index 778bbb6..eb603f1de 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -873,9 +873,10 @@
from an EDID retrieval */
if (port->connector) {
mutex_lock(&mgr->destroy_connector_lock);
- list_add(&port->connector->destroy_list, &mgr->destroy_connector_list);
+ list_add(&port->next, &mgr->destroy_connector_list);
mutex_unlock(&mgr->destroy_connector_lock);
schedule_work(&mgr->destroy_connector_work);
+ return;
}
drm_dp_port_teardown_pdt(port, port->pdt);
@@ -1294,7 +1295,6 @@
goto retry;
}
DRM_DEBUG_KMS("failed to dpcd write %d %d\n", tosend, ret);
- WARN(1, "fail\n");
return -EIO;
}
@@ -2660,7 +2660,7 @@
static void drm_dp_destroy_connector_work(struct work_struct *work)
{
struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, destroy_connector_work);
- struct drm_connector *connector;
+ struct drm_dp_mst_port *port;
/*
* Not a regular list traverse as we have to drop the destroy
@@ -2669,15 +2669,21 @@
*/
for (;;) {
mutex_lock(&mgr->destroy_connector_lock);
- connector = list_first_entry_or_null(&mgr->destroy_connector_list, struct drm_connector, destroy_list);
- if (!connector) {
+ port = list_first_entry_or_null(&mgr->destroy_connector_list, struct drm_dp_mst_port, next);
+ if (!port) {
mutex_unlock(&mgr->destroy_connector_lock);
break;
}
- list_del(&connector->destroy_list);
+ list_del(&port->next);
mutex_unlock(&mgr->destroy_connector_lock);
- mgr->cbs->destroy_connector(mgr, connector);
+ mgr->cbs->destroy_connector(mgr, port->connector);
+
+ drm_dp_port_teardown_pdt(port, port->pdt);
+
+ if (!port->input && port->vcpi.vcpi > 0)
+ drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi);
+ kfree(port);
}
}
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index f9cc68f..b50fa0a 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -75,7 +75,7 @@
module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600);
static void store_vblank(struct drm_device *dev, int crtc,
- unsigned vblank_count_inc,
+ u32 vblank_count_inc,
struct timeval *t_vblank)
{
struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 842d6b8..2a65235 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -1745,7 +1745,6 @@
spin_lock_init(&ctx->lock);
platform_set_drvdata(pdev, ctx);
- pm_runtime_set_active(dev);
pm_runtime_enable(dev);
ret = exynos_drm_ippdrv_register(ippdrv);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 8040ed2..f1c6b76 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -593,8 +593,7 @@
gsc_write(cfg, GSC_IN_CON);
- ctx->rotation = cfg &
- (GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
+ ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0;
*swap = ctx->rotation;
return 0;
@@ -857,8 +856,7 @@
gsc_write(cfg, GSC_IN_CON);
- ctx->rotation = cfg &
- (GSC_IN_ROT_90 | GSC_IN_ROT_270) ? 1 : 0;
+ ctx->rotation = (cfg & GSC_IN_ROT_90) ? 1 : 0;
*swap = ctx->rotation;
return 0;
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 99e2864..4a00990 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1064,6 +1064,7 @@
{
struct hdmi_context *hdata = ctx_from_connector(connector);
struct edid *edid;
+ int ret;
if (!hdata->ddc_adpt)
return -ENODEV;
@@ -1079,7 +1080,11 @@
drm_mode_connector_update_edid_property(connector, edid);
- return drm_add_edid_modes(connector, edid);
+ ret = drm_add_edid_modes(connector, edid);
+
+ kfree(edid);
+
+ return ret;
}
static int hdmi_find_phy_conf(struct hdmi_context *hdata, u32 pixel_clock)
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index cae98db..4706b56 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -718,6 +718,10 @@
/* handling VSYNC */
if (val & MXR_INT_STATUS_VSYNC) {
+ /* vsync interrupt use different bit for read and clear */
+ val |= MXR_INT_CLEAR_VSYNC;
+ val &= ~MXR_INT_STATUS_VSYNC;
+
/* interlace scan need to check shadow register */
if (ctx->interlace) {
base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0));
@@ -743,11 +747,6 @@
out:
/* clear interrupts */
- if (~val & MXR_INT_EN_VSYNC) {
- /* vsync interrupt use different bit for read and clear */
- val &= ~MXR_INT_EN_VSYNC;
- val |= MXR_INT_CLEAR_VSYNC;
- }
mixer_reg_write(res, MXR_INT_STATUS, val);
spin_unlock(&res->reg_slock);
@@ -907,8 +906,8 @@
}
/* enable vsync interrupt */
- mixer_reg_writemask(res, MXR_INT_EN, MXR_INT_EN_VSYNC,
- MXR_INT_EN_VSYNC);
+ mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
+ mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC);
return 0;
}
@@ -918,7 +917,13 @@
struct mixer_context *mixer_ctx = crtc->ctx;
struct mixer_resources *res = &mixer_ctx->mixer_res;
+ if (!mixer_ctx->powered) {
+ mixer_ctx->int_en &= MXR_INT_EN_VSYNC;
+ return;
+ }
+
/* disable vsync interrupt */
+ mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
}
@@ -1047,6 +1052,8 @@
mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET);
+ if (ctx->int_en & MXR_INT_EN_VSYNC)
+ mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC);
mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
mixer_win_reset(ctx);
}
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index fe1599d..424228b 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -606,8 +606,6 @@
tda998x_write_if(struct tda998x_priv *priv, uint8_t bit, uint16_t addr,
uint8_t *buf, size_t size)
{
- buf[PB(0)] = tda998x_cksum(buf, size);
-
reg_clear(priv, REG_DIP_IF_FLAGS, bit);
reg_write_range(priv, addr, buf, size);
reg_set(priv, REG_DIP_IF_FLAGS, bit);
@@ -627,6 +625,8 @@
buf[PB(4)] = p->audio_frame[4];
buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */
+ buf[PB(0)] = tda998x_cksum(buf, sizeof(buf));
+
tda998x_write_if(priv, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf,
sizeof(buf));
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5f27290..fd1de45 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3303,15 +3303,14 @@
#define I915_READ64(reg) dev_priv->uncore.funcs.mmio_readq(dev_priv, (reg), true)
#define I915_READ64_2x32(lower_reg, upper_reg) ({ \
- u32 upper = I915_READ(upper_reg); \
- u32 lower = I915_READ(lower_reg); \
- u32 tmp = I915_READ(upper_reg); \
- if (upper != tmp) { \
- upper = tmp; \
- lower = I915_READ(lower_reg); \
- WARN_ON(I915_READ(upper_reg) != upper); \
- } \
- (u64)upper << 32 | lower; })
+ u32 upper, lower, tmp; \
+ tmp = I915_READ(upper_reg); \
+ do { \
+ upper = tmp; \
+ lower = I915_READ(lower_reg); \
+ tmp = I915_READ(upper_reg); \
+ } while (upper != tmp); \
+ (u64)upper << 32 | lower; })
#define POSTING_READ(reg) (void)I915_READ_NOTRACE(reg)
#define POSTING_READ16(reg) (void)I915_READ16_NOTRACE(reg)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 56b52a4..31e8269 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -1923,6 +1923,17 @@
vma->vm->insert_entries(vma->vm, pages,
vma->node.start,
cache_level, pte_flags);
+
+ /* Note the inconsistency here is due to absence of the
+ * aliasing ppgtt on gen4 and earlier. Though we always
+ * request PIN_USER for execbuffer (translated to LOCAL_BIND),
+ * without the appgtt, we cannot honour that request and so
+ * must substitute it with a global binding. Since we do this
+ * behind the upper layers back, we need to explicitly set
+ * the bound flag ourselves.
+ */
+ vma->bound |= GLOBAL_BIND;
+
}
if (dev_priv->mm.aliasing_ppgtt && flags & LOCAL_BIND) {
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 633bd1f..d19c9db 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -464,7 +464,10 @@
}
/* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
- args->phys_swizzle_mode = args->swizzle_mode;
+ if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
+ args->phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN;
+ else
+ args->phys_swizzle_mode = args->swizzle_mode;
if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
diff --git a/drivers/gpu/drm/i915/intel_atomic.c b/drivers/gpu/drm/i915/intel_atomic.c
index 7ed8033..8e35e0d 100644
--- a/drivers/gpu/drm/i915/intel_atomic.c
+++ b/drivers/gpu/drm/i915/intel_atomic.c
@@ -129,8 +129,9 @@
struct drm_atomic_state *state,
bool async)
{
- int ret;
- int i;
+ struct drm_crtc_state *crtc_state;
+ struct drm_crtc *crtc;
+ int ret, i;
if (async) {
DRM_DEBUG_KMS("i915 does not yet support async commit\n");
@@ -142,48 +143,18 @@
return ret;
/* Point of no return */
-
- /*
- * FIXME: The proper sequence here will eventually be:
- *
- * drm_atomic_helper_swap_state(dev, state)
- * drm_atomic_helper_commit_modeset_disables(dev, state);
- * drm_atomic_helper_commit_planes(dev, state);
- * drm_atomic_helper_commit_modeset_enables(dev, state);
- * drm_atomic_helper_wait_for_vblanks(dev, state);
- * drm_atomic_helper_cleanup_planes(dev, state);
- * drm_atomic_state_free(state);
- *
- * once we have full atomic modeset. For now, just manually update
- * plane states to avoid clobbering good states with dummy states
- * while nuclear pageflipping.
- */
- for (i = 0; i < dev->mode_config.num_total_plane; i++) {
- struct drm_plane *plane = state->planes[i];
-
- if (!plane)
- continue;
-
- plane->state->state = state;
- swap(state->plane_states[i], plane->state);
- plane->state->state = NULL;
- }
+ drm_atomic_helper_swap_state(dev, state);
/* swap crtc_scaler_state */
- for (i = 0; i < dev->mode_config.num_crtc; i++) {
- struct drm_crtc *crtc = state->crtcs[i];
- if (!crtc) {
- continue;
- }
-
- to_intel_crtc(crtc)->config->scaler_state =
- to_intel_crtc_state(state->crtc_states[i])->scaler_state;
+ for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ to_intel_crtc(crtc)->config = to_intel_crtc_state(crtc->state);
if (INTEL_INFO(dev)->gen >= 9)
skl_detach_scalers(to_intel_crtc(crtc));
+
+ drm_atomic_helper_commit_planes_on_crtc(crtc_state);
}
- drm_atomic_helper_commit_planes(dev, state);
drm_atomic_helper_wait_for_vblanks(dev, state);
drm_atomic_helper_cleanup_planes(dev, state);
drm_atomic_state_free(state);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 30e0f54..87476ff 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11826,7 +11826,9 @@
goto encoder_retry;
}
- pipe_config->dither = pipe_config->pipe_bpp != base_bpp;
+ /* Dithering seems to not pass-through bits correctly when it should, so
+ * only enable it on 6bpc panels. */
+ pipe_config->dither = pipe_config->pipe_bpp == 6*3;
DRM_DEBUG_KMS("plane bpp: %i, pipe bpp: %i, dithering: %i\n",
base_bpp, pipe_config->pipe_bpp, pipe_config->dither);
@@ -12624,17 +12626,17 @@
modeset_update_crtc_power_domains(state);
- drm_atomic_helper_commit_planes(dev, state);
-
/* Now enable the clocks, plane, pipe, and connectors that we set up. */
for_each_crtc_in_state(state, crtc, crtc_state, i) {
- if (!needs_modeset(crtc->state) || !crtc->state->enable)
+ if (!needs_modeset(crtc->state) || !crtc->state->enable) {
+ drm_atomic_helper_commit_planes_on_crtc(crtc_state);
continue;
+ }
update_scanline_offset(to_intel_crtc(crtc));
dev_priv->display.crtc_enable(crtc);
- intel_crtc_enable_planes(crtc);
+ drm_atomic_helper_commit_planes_on_crtc(crtc_state);
}
/* FIXME: add subpixel order */
@@ -12891,20 +12893,11 @@
return 0;
}
-static bool primary_plane_visible(struct drm_crtc *crtc)
-{
- struct intel_plane_state *plane_state =
- to_intel_plane_state(crtc->primary->state);
-
- return plane_state->visible;
-}
-
static int intel_crtc_set_config(struct drm_mode_set *set)
{
struct drm_device *dev;
struct drm_atomic_state *state = NULL;
struct intel_crtc_state *pipe_config;
- bool primary_plane_was_visible;
int ret;
BUG_ON(!set);
@@ -12943,38 +12936,8 @@
intel_update_pipe_size(to_intel_crtc(set->crtc));
- primary_plane_was_visible = primary_plane_visible(set->crtc);
-
ret = intel_set_mode_with_config(set->crtc, pipe_config, true);
- if (ret == 0 &&
- pipe_config->base.enable &&
- pipe_config->base.planes_changed &&
- !needs_modeset(&pipe_config->base)) {
- struct intel_crtc *intel_crtc = to_intel_crtc(set->crtc);
-
- /*
- * We need to make sure the primary plane is re-enabled if it
- * has previously been turned off.
- */
- if (ret == 0 && !primary_plane_was_visible &&
- primary_plane_visible(set->crtc)) {
- WARN_ON(!intel_crtc->active);
- intel_post_enable_primary(set->crtc);
- }
-
- /*
- * In the fastboot case this may be our only check of the
- * state after boot. It would be better to only do it on
- * the first update, but we don't have a nice way of doing that
- * (and really, set_config isn't used much for high freq page
- * flipping, so increasing its cost here shouldn't be a big
- * deal).
- */
- if (i915.fastboot && ret == 0)
- intel_modeset_check_state(set->crtc->dev);
- }
-
if (ret) {
DRM_DEBUG_KMS("failed to set mode on [CRTC:%d], err = %d\n",
set->crtc->base.id, ret);
@@ -13305,6 +13268,9 @@
*/
if (IS_BROADWELL(dev))
intel_crtc->atomic.wait_vblank = true;
+
+ if (crtc_state)
+ intel_crtc->atomic.post_enable_primary = true;
}
/*
@@ -13317,6 +13283,10 @@
if (!state->visible || !fb)
intel_crtc->atomic.disable_ips = true;
+ if (!state->visible && old_state->visible &&
+ crtc_state && !needs_modeset(&crtc_state->base))
+ intel_crtc->atomic.pre_disable_primary = true;
+
intel_crtc->atomic.fb_bits |=
INTEL_FRONTBUFFER_PRIMARY(intel_crtc->pipe);
@@ -15034,6 +15004,7 @@
struct intel_plane_state *plane_state;
memset(crtc->config, 0, sizeof(*crtc->config));
+ crtc->config->base.crtc = &crtc->base;
crtc->config->quirks |= PIPE_CONFIG_QUIRK_INHERITED_MODE;
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 6e8faa2..1df0e1f 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -93,9 +93,6 @@
static const int skl_rates[] = { 162000, 216000, 270000,
324000, 432000, 540000 };
-static const int chv_rates[] = { 162000, 202500, 210000, 216000,
- 243000, 270000, 324000, 405000,
- 420000, 432000, 540000 };
static const int default_rates[] = { 162000, 270000, 540000 };
/**
@@ -1169,24 +1166,31 @@
return (intel_dp_max_link_bw(intel_dp) >> 3) + 1;
}
+static bool intel_dp_source_supports_hbr2(struct drm_device *dev)
+{
+ /* WaDisableHBR2:skl */
+ if (IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0)
+ return false;
+
+ if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) ||
+ (INTEL_INFO(dev)->gen >= 9))
+ return true;
+ else
+ return false;
+}
+
static int
intel_dp_source_rates(struct drm_device *dev, const int **source_rates)
{
if (IS_SKYLAKE(dev)) {
*source_rates = skl_rates;
return ARRAY_SIZE(skl_rates);
- } else if (IS_CHERRYVIEW(dev)) {
- *source_rates = chv_rates;
- return ARRAY_SIZE(chv_rates);
}
*source_rates = default_rates;
- if (IS_SKYLAKE(dev) && INTEL_REVID(dev) <= SKL_REVID_B0)
- /* WaDisableHBR2:skl */
- return (DP_LINK_BW_2_7 >> 3) + 1;
- else if (INTEL_INFO(dev)->gen >= 8 ||
- (IS_HASWELL(dev) && !IS_HSW_ULX(dev)))
+ /* This depends on the fact that 5.4 is last value in the array */
+ if (intel_dp_source_supports_hbr2(dev))
return (DP_LINK_BW_5_4 >> 3) + 1;
else
return (DP_LINK_BW_2_7 >> 3) + 1;
@@ -3941,10 +3945,15 @@
}
}
- /* Training Pattern 3 support, both source and sink */
+ /* Training Pattern 3 support, Intel platforms that support HBR2 alone
+ * have support for TP3 hence that check is used along with dpcd check
+ * to ensure TP3 can be enabled.
+ * SKL < B0: due it's WaDisableHBR2 is the only exception where TP3 is
+ * supported but still not enabled.
+ */
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x12 &&
intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED &&
- (IS_HASWELL(dev_priv) || INTEL_INFO(dev_priv)->gen >= 8)) {
+ intel_dp_source_supports_hbr2(dev)) {
intel_dp->use_tps3 = true;
DRM_DEBUG_KMS("Displayport TPS3 supported\n");
} else
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c
index 6e4cc53..600afdb 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -357,6 +357,16 @@
return MODE_OK;
}
+static struct drm_encoder *intel_mst_atomic_best_encoder(struct drm_connector *connector,
+ struct drm_connector_state *state)
+{
+ struct intel_connector *intel_connector = to_intel_connector(connector);
+ struct intel_dp *intel_dp = intel_connector->mst_port;
+ struct intel_crtc *crtc = to_intel_crtc(state->crtc);
+
+ return &intel_dp->mst_encoders[crtc->pipe]->base.base;
+}
+
static struct drm_encoder *intel_mst_best_encoder(struct drm_connector *connector)
{
struct intel_connector *intel_connector = to_intel_connector(connector);
@@ -367,6 +377,7 @@
static const struct drm_connector_helper_funcs intel_dp_mst_connector_helper_funcs = {
.get_modes = intel_dp_mst_get_modes,
.mode_valid = intel_dp_mst_mode_valid,
+ .atomic_best_encoder = intel_mst_atomic_best_encoder,
.best_encoder = intel_mst_best_encoder,
};
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 9b74ffa..7f2161a 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1012,6 +1012,8 @@
ret = intel_pin_and_map_ringbuffer_obj(ring->dev, ringbuf);
if (ret)
goto unpin_ctx_obj;
+
+ ctx_obj->dirty = true;
}
return ret;
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index a6d8a3e..260389a 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -1274,10 +1274,12 @@
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_reg_read *reg = data;
struct register_whitelist const *entry = whitelist;
+ unsigned size;
+ u64 offset;
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
- if (entry->offset == reg->offset &&
+ if (entry->offset == (reg->offset & -entry->size) &&
(1 << INTEL_INFO(dev)->gen & entry->gen_bitmask))
break;
}
@@ -1285,23 +1287,33 @@
if (i == ARRAY_SIZE(whitelist))
return -EINVAL;
+ /* We use the low bits to encode extra flags as the register should
+ * be naturally aligned (and those that are not so aligned merely
+ * limit the available flags for that register).
+ */
+ offset = entry->offset;
+ size = entry->size;
+ size |= reg->offset ^ offset;
+
intel_runtime_pm_get(dev_priv);
- switch (entry->size) {
+ switch (size) {
+ case 8 | 1:
+ reg->val = I915_READ64_2x32(offset, offset+4);
+ break;
case 8:
- reg->val = I915_READ64(reg->offset);
+ reg->val = I915_READ64(offset);
break;
case 4:
- reg->val = I915_READ(reg->offset);
+ reg->val = I915_READ(offset);
break;
case 2:
- reg->val = I915_READ16(reg->offset);
+ reg->val = I915_READ16(offset);
break;
case 1:
- reg->val = I915_READ8(reg->offset);
+ reg->val = I915_READ8(offset);
break;
default:
- MISSING_CASE(entry->size);
ret = -EINVAL;
goto out;
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 0d1dbb7..247a424 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -220,13 +220,15 @@
uint32_t op_mode = 0;
uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
- enum mdp4_frame_format frame_type = mdp4_get_frame_format(fb);
+ enum mdp4_frame_format frame_type;
if (!(crtc && fb)) {
DBG("%s: disabled!", mdp4_plane->name);
return 0;
}
+ frame_type = mdp4_get_frame_format(fb);
+
/* src values are in Q16 fixed point, convert to integer: */
src_x = src_x >> 16;
src_y = src_y >> 16;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 206f758..e253db5 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -76,7 +76,20 @@
static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *state)
{
+ int i;
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
+ int nplanes = mdp5_kms->dev->mode_config.num_total_plane;
+
+ for (i = 0; i < nplanes; i++) {
+ struct drm_plane *plane = state->planes[i];
+ struct drm_plane_state *plane_state = state->plane_states[i];
+
+ if (!plane)
+ continue;
+
+ mdp5_plane_complete_commit(plane, plane_state);
+ }
+
mdp5_disable(mdp5_kms);
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index e0eb245..e79ac09 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -227,6 +227,8 @@
struct drm_mode_object *obj);
uint32_t mdp5_plane_get_flush(struct drm_plane *plane);
void mdp5_plane_complete_flip(struct drm_plane *plane);
+void mdp5_plane_complete_commit(struct drm_plane *plane,
+ struct drm_plane_state *state);
enum mdp5_pipe mdp5_plane_pipe(struct drm_plane *plane);
struct drm_plane *mdp5_plane_init(struct drm_device *dev,
enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 57b8f56..2227556 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -31,8 +31,6 @@
uint32_t nformats;
uint32_t formats[32];
-
- bool enabled;
};
#define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base)
@@ -56,22 +54,6 @@
return state->fb && state->crtc;
}
-static int mdp5_plane_disable(struct drm_plane *plane)
-{
- struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
- struct mdp5_kms *mdp5_kms = get_kms(plane);
- enum mdp5_pipe pipe = mdp5_plane->pipe;
-
- DBG("%s: disable", mdp5_plane->name);
-
- if (mdp5_kms) {
- /* Release the memory we requested earlier from the SMP: */
- mdp5_smp_release(mdp5_kms->smp, pipe);
- }
-
- return 0;
-}
-
static void mdp5_plane_destroy(struct drm_plane *plane)
{
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
@@ -224,7 +206,6 @@
if (!plane_enabled(state)) {
to_mdp5_plane_state(state)->pending = true;
- mdp5_plane_disable(plane);
} else if (to_mdp5_plane_state(state)->mode_changed) {
int ret;
to_mdp5_plane_state(state)->pending = true;
@@ -602,6 +583,20 @@
return mdp5_plane->flush_mask;
}
+/* called after vsync in thread context */
+void mdp5_plane_complete_commit(struct drm_plane *plane,
+ struct drm_plane_state *state)
+{
+ struct mdp5_kms *mdp5_kms = get_kms(plane);
+ struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
+ enum mdp5_pipe pipe = mdp5_plane->pipe;
+
+ if (!plane_enabled(plane->state)) {
+ DBG("%s: free SMP", mdp5_plane->name);
+ mdp5_smp_release(mdp5_kms->smp, pipe);
+ }
+}
+
/* initialize plane */
struct drm_plane *mdp5_plane_init(struct drm_device *dev,
enum mdp5_pipe pipe, bool private_plane, uint32_t reg_offset)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
index 16702ae..64a27d8 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.c
@@ -34,22 +34,44 @@
* and CANNOT be re-allocated (eg: MMB0 and MMB1 both tied to RGB0).
*
* For each block that can be dynamically allocated, it can be either
- * free, or pending/in-use by a client. The updates happen in three steps:
+ * free:
+ * The block is free.
+ *
+ * pending:
+ * The block is allocated to some client and not free.
+ *
+ * configured:
+ * The block is allocated to some client, and assigned to that
+ * client in MDP5_MDP_SMP_ALLOC registers.
+ *
+ * inuse:
+ * The block is being actively used by a client.
+ *
+ * The updates happen in the following steps:
*
* 1) mdp5_smp_request():
* When plane scanout is setup, calculate required number of
- * blocks needed per client, and request. Blocks not inuse or
- * pending by any other client are added to client's pending
- * set.
+ * blocks needed per client, and request. Blocks neither inuse nor
+ * configured nor pending by any other client are added to client's
+ * pending set.
+ * For shrinking, blocks in pending but not in configured can be freed
+ * directly, but those already in configured will be freed later by
+ * mdp5_smp_commit.
*
* 2) mdp5_smp_configure():
* As hw is programmed, before FLUSH, MDP5_MDP_SMP_ALLOC registers
* are configured for the union(pending, inuse)
+ * Current pending is copied to configured.
+ * It is assumed that mdp5_smp_request and mdp5_smp_configure not run
+ * concurrently for the same pipe.
*
* 3) mdp5_smp_commit():
- * After next vblank, copy pending -> inuse. Optionally update
+ * After next vblank, copy configured -> inuse. Optionally update
* MDP5_SMP_ALLOC registers if there are newly unused blocks
*
+ * 4) mdp5_smp_release():
+ * Must be called after the pipe is disabled and no longer uses any SMB
+ *
* On the next vblank after changes have been committed to hw, the
* client's pending blocks become it's in-use blocks (and no-longer
* in-use blocks become available to other clients).
@@ -77,6 +99,9 @@
struct mdp5_client_smp_state client_state[MAX_CLIENTS];
};
+static void update_smp_state(struct mdp5_smp *smp,
+ u32 cid, mdp5_smp_state_t *assigned);
+
static inline
struct mdp5_kms *get_kms(struct mdp5_smp *smp)
{
@@ -149,7 +174,12 @@
for (i = cur_nblks; i > nblks; i--) {
int blk = find_first_bit(ps->pending, cnt);
clear_bit(blk, ps->pending);
- /* don't clear in global smp_state until _commit() */
+
+ /* clear in global smp_state if not in configured
+ * otherwise until _commit()
+ */
+ if (!test_bit(blk, ps->configured))
+ clear_bit(blk, smp->state);
}
}
@@ -223,10 +253,33 @@
/* Release SMP blocks for all clients of the pipe */
void mdp5_smp_release(struct mdp5_smp *smp, enum mdp5_pipe pipe)
{
- int i, nblks;
+ int i;
+ unsigned long flags;
+ int cnt = smp->blk_cnt;
- for (i = 0, nblks = 0; i < pipe2nclients(pipe); i++)
- smp_request_block(smp, pipe2client(pipe, i), 0);
+ for (i = 0; i < pipe2nclients(pipe); i++) {
+ mdp5_smp_state_t assigned;
+ u32 cid = pipe2client(pipe, i);
+ struct mdp5_client_smp_state *ps = &smp->client_state[cid];
+
+ spin_lock_irqsave(&smp->state_lock, flags);
+
+ /* clear hw assignment */
+ bitmap_or(assigned, ps->inuse, ps->configured, cnt);
+ update_smp_state(smp, CID_UNUSED, &assigned);
+
+ /* free to global pool */
+ bitmap_andnot(smp->state, smp->state, ps->pending, cnt);
+ bitmap_andnot(smp->state, smp->state, assigned, cnt);
+
+ /* clear client's infor */
+ bitmap_zero(ps->pending, cnt);
+ bitmap_zero(ps->configured, cnt);
+ bitmap_zero(ps->inuse, cnt);
+
+ spin_unlock_irqrestore(&smp->state_lock, flags);
+ }
+
set_fifo_thresholds(smp, pipe, 0);
}
@@ -274,12 +327,20 @@
u32 cid = pipe2client(pipe, i);
struct mdp5_client_smp_state *ps = &smp->client_state[cid];
- bitmap_or(assigned, ps->inuse, ps->pending, cnt);
+ /*
+ * if vblank has not happened since last smp_configure
+ * skip the configure for now
+ */
+ if (!bitmap_equal(ps->inuse, ps->configured, cnt))
+ continue;
+
+ bitmap_copy(ps->configured, ps->pending, cnt);
+ bitmap_or(assigned, ps->inuse, ps->configured, cnt);
update_smp_state(smp, cid, &assigned);
}
}
-/* step #3: after vblank, copy pending -> inuse: */
+/* step #3: after vblank, copy configured -> inuse: */
void mdp5_smp_commit(struct mdp5_smp *smp, enum mdp5_pipe pipe)
{
int cnt = smp->blk_cnt;
@@ -295,7 +356,7 @@
* using, which can be released and made available to other
* clients:
*/
- if (bitmap_andnot(released, ps->inuse, ps->pending, cnt)) {
+ if (bitmap_andnot(released, ps->inuse, ps->configured, cnt)) {
unsigned long flags;
spin_lock_irqsave(&smp->state_lock, flags);
@@ -306,7 +367,7 @@
update_smp_state(smp, CID_UNUSED, &released);
}
- bitmap_copy(ps->inuse, ps->pending, cnt);
+ bitmap_copy(ps->inuse, ps->configured, cnt);
}
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
index e47179f..5b6c236 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_smp.h
@@ -23,6 +23,7 @@
struct mdp5_client_smp_state {
mdp5_smp_state_t inuse;
+ mdp5_smp_state_t configured;
mdp5_smp_state_t pending;
};
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 1b22d8b..1ceb4f2 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -283,12 +283,8 @@
timeout = ktime_add_ms(ktime_get(), 1000);
- ret = msm_wait_fence_interruptable(dev, c->fence, &timeout);
- if (ret) {
- WARN_ON(ret); // TODO unswap state back? or??
- commit_destroy(c);
- return ret;
- }
+ /* uninterruptible wait */
+ msm_wait_fence(dev, c->fence, &timeout, false);
complete_commit(c);
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index b7ef56e..d3467b1 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -637,8 +637,8 @@
* Fences:
*/
-int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
- ktime_t *timeout)
+int msm_wait_fence(struct drm_device *dev, uint32_t fence,
+ ktime_t *timeout , bool interruptible)
{
struct msm_drm_private *priv = dev->dev_private;
int ret;
@@ -667,7 +667,12 @@
remaining_jiffies = timespec_to_jiffies(&ts);
}
- ret = wait_event_interruptible_timeout(priv->fence_event,
+ if (interruptible)
+ ret = wait_event_interruptible_timeout(priv->fence_event,
+ fence_completed(dev, fence),
+ remaining_jiffies);
+ else
+ ret = wait_event_timeout(priv->fence_event,
fence_completed(dev, fence),
remaining_jiffies);
@@ -853,7 +858,7 @@
return -EINVAL;
}
- return msm_wait_fence_interruptable(dev, args->fence, &timeout);
+ return msm_wait_fence(dev, args->fence, &timeout, true);
}
static const struct drm_ioctl_desc msm_ioctls[] = {
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index e7c5ea1..4ff0ec9 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -164,8 +164,8 @@
int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
-int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
- ktime_t *timeout);
+int msm_wait_fence(struct drm_device *dev, uint32_t fence,
+ ktime_t *timeout, bool interruptible);
int msm_queue_fence_cb(struct drm_device *dev,
struct msm_fence_cb *cb, uint32_t fence);
void msm_update_fence(struct drm_device *dev, uint32_t fence);
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index f211b80..c76cc85 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -460,7 +460,7 @@
if (op & MSM_PREP_NOSYNC)
timeout = NULL;
- ret = msm_wait_fence_interruptable(dev, fence, timeout);
+ ret = msm_wait_fence(dev, fence, timeout, true);
}
/* TODO cache maintenance */
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
index dd7a7ab..831461b 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -23,8 +23,12 @@
struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
- BUG_ON(!msm_obj->sgt); /* should have already pinned! */
- return msm_obj->sgt;
+ int npages = obj->size >> PAGE_SHIFT;
+
+ if (WARN_ON(!msm_obj->pages)) /* should have already pinned! */
+ return NULL;
+
+ return drm_prime_pages_to_sg(msm_obj->pages, npages);
}
void *msm_gem_prime_vmap(struct drm_gem_object *obj)
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 649024d..477cbb1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -128,6 +128,7 @@
nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL);
nvif_client_fini(&cli->base);
usif_client_fini(cli);
+ kfree(cli);
}
static void
@@ -865,8 +866,10 @@
pm_runtime_get_sync(dev->dev);
+ mutex_lock(&cli->mutex);
if (cli->abi16)
nouveau_abi16_fini(cli->abi16);
+ mutex_unlock(&cli->mutex);
mutex_lock(&drm->client.mutex);
list_del(&cli->head);
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c
index 775277f..dcfbbfa 100644
--- a/drivers/gpu/drm/nouveau/nouveau_platform.c
+++ b/drivers/gpu/drm/nouveau/nouveau_platform.c
@@ -92,6 +92,8 @@
return 0;
}
+#if IS_ENABLED(CONFIG_IOMMU_API)
+
static void nouveau_platform_probe_iommu(struct device *dev,
struct nouveau_platform_gpu *gpu)
{
@@ -158,6 +160,20 @@
}
}
+#else
+
+static void nouveau_platform_probe_iommu(struct device *dev,
+ struct nouveau_platform_gpu *gpu)
+{
+}
+
+static void nouveau_platform_remove_iommu(struct device *dev,
+ struct nouveau_platform_gpu *gpu)
+{
+}
+
+#endif
+
static int nouveau_platform_probe(struct platform_device *pdev)
{
struct nouveau_platform_gpu *gpu;
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index 18f4497..7464aef3 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -175,15 +175,24 @@
node->page_shift = 12;
switch (drm->device.info.family) {
+ case NV_DEVICE_INFO_V0_TNT:
+ case NV_DEVICE_INFO_V0_CELSIUS:
+ case NV_DEVICE_INFO_V0_KELVIN:
+ case NV_DEVICE_INFO_V0_RANKINE:
+ case NV_DEVICE_INFO_V0_CURIE:
+ break;
case NV_DEVICE_INFO_V0_TESLA:
if (drm->device.info.chipset != 0x50)
node->memtype = (nvbo->tile_flags & 0x7f00) >> 8;
break;
case NV_DEVICE_INFO_V0_FERMI:
case NV_DEVICE_INFO_V0_KEPLER:
+ case NV_DEVICE_INFO_V0_MAXWELL:
node->memtype = (nvbo->tile_flags & 0xff00) >> 8;
break;
default:
+ NV_WARN(drm, "%s: unhandled family type %x\n", __func__,
+ drm->device.info.family);
break;
}
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
index 4ef602c..495c576 100644
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv04_fbcon.c
@@ -203,7 +203,7 @@
if (ret)
return ret;
- if (RING_SPACE(chan, 49)) {
+ if (RING_SPACE(chan, 49 + (device->info.chipset >= 0x11 ? 4 : 0))) {
nouveau_fbcon_gpu_lockup(info);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 7da7958..981342d 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -979,7 +979,7 @@
{
struct nv50_mast *mast = nv50_mast(nv_crtc->base.dev);
- if (show && nv_crtc->cursor.nvbo)
+ if (show && nv_crtc->cursor.nvbo && nv_crtc->base.enabled)
nv50_crtc_cursor_show(nv_crtc);
else
nv50_crtc_cursor_hide(nv_crtc);
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
index 394c89a..901130b 100644
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c
@@ -188,7 +188,7 @@
if (ret)
return ret;
- ret = RING_SPACE(chan, 59);
+ ret = RING_SPACE(chan, 58);
if (ret) {
nouveau_fbcon_gpu_lockup(info);
return ret;
@@ -252,6 +252,7 @@
OUT_RING(chan, info->var.yres_virtual);
OUT_RING(chan, upper_32_bits(fb->vma.offset));
OUT_RING(chan, lower_32_bits(fb->vma.offset));
+ FIRE_RING(chan);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
index 6124667..fcd2e5f 100644
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
@@ -188,7 +188,7 @@
return -EINVAL;
}
- ret = RING_SPACE(chan, 60);
+ ret = RING_SPACE(chan, 58);
if (ret) {
WARN_ON(1);
nouveau_fbcon_gpu_lockup(info);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c
index 9ef6728..7f2f05f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf110.c
@@ -809,7 +809,7 @@
case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break;
default:
nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl);
- return 0x0000;
+ return NULL;
}
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index 5606c25..ca11ddb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -663,6 +663,37 @@
gf100_gr_zbc_clear_depth(priv, index);
}
+/**
+ * Wait until GR goes idle. GR is considered idle if it is disabled by the
+ * MC (0x200) register, or GR is not busy and a context switch is not in
+ * progress.
+ */
+int
+gf100_gr_wait_idle(struct gf100_gr_priv *priv)
+{
+ unsigned long end_jiffies = jiffies + msecs_to_jiffies(2000);
+ bool gr_enabled, ctxsw_active, gr_busy;
+
+ do {
+ /*
+ * required to make sure FIFO_ENGINE_STATUS (0x2640) is
+ * up-to-date
+ */
+ nv_rd32(priv, 0x400700);
+
+ gr_enabled = nv_rd32(priv, 0x200) & 0x1000;
+ ctxsw_active = nv_rd32(priv, 0x2640) & 0x8000;
+ gr_busy = nv_rd32(priv, 0x40060c) & 0x1;
+
+ if (!gr_enabled || (!gr_busy && !ctxsw_active))
+ return 0;
+ } while (time_before(jiffies, end_jiffies));
+
+ nv_error(priv, "wait for idle timeout (en: %d, ctxsw: %d, busy: %d)\n",
+ gr_enabled, ctxsw_active, gr_busy);
+ return -EAGAIN;
+}
+
void
gf100_gr_mmio(struct gf100_gr_priv *priv, const struct gf100_gr_pack *p)
{
@@ -699,7 +730,13 @@
while (addr < next) {
nv_wr32(priv, 0x400200, addr);
- nv_wait(priv, 0x400700, 0x00000002, 0x00000000);
+ /**
+ * Wait for GR to go idle after submitting a
+ * GO_IDLE bundle
+ */
+ if ((addr & 0xffff) == 0xe100)
+ gf100_gr_wait_idle(priv);
+ nv_wait(priv, 0x400700, 0x00000004, 0x00000000);
addr += init->pitch;
}
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
index 8af1a89..c9533fd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
@@ -181,6 +181,7 @@
int ppc_nr;
};
+int gf100_gr_wait_idle(struct gf100_gr_priv *);
void gf100_gr_mmio(struct gf100_gr_priv *, const struct gf100_gr_pack *);
void gf100_gr_icmd(struct gf100_gr_priv *, const struct gf100_gr_pack *);
void gf100_gr_mthd(struct gf100_gr_priv *, const struct gf100_gr_pack *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
index 2006c44..4cf36a3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c
@@ -332,9 +332,12 @@
nvkm_perfctx_dtor(struct nvkm_object *object)
{
struct nvkm_pm *ppm = (void *)object->engine;
+ struct nvkm_perfctx *ctx = (void *)object;
+
mutex_lock(&nv_subdev(ppm)->mutex);
- nvkm_engctx_destroy(&ppm->context->base);
- ppm->context = NULL;
+ nvkm_engctx_destroy(&ctx->base);
+ if (ppm->context == ctx)
+ ppm->context = NULL;
mutex_unlock(&nv_subdev(ppm)->mutex);
}
@@ -355,12 +358,11 @@
mutex_lock(&nv_subdev(ppm)->mutex);
if (ppm->context == NULL)
ppm->context = ctx;
+ if (ctx != ppm->context)
+ ret = -EBUSY;
mutex_unlock(&nv_subdev(ppm)->mutex);
- if (ctx != ppm->context)
- return -EBUSY;
-
- return 0;
+ return ret;
}
struct nvkm_oclass
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
index f67cdae..f4611e3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c
@@ -1285,6 +1285,44 @@
}
/**
+ * INIT_PLL_INDIRECT - opcode 0x59
+ *
+ */
+static void
+init_pll_indirect(struct nvbios_init *init)
+{
+ struct nvkm_bios *bios = init->bios;
+ u32 reg = nv_ro32(bios, init->offset + 1);
+ u16 addr = nv_ro16(bios, init->offset + 5);
+ u32 freq = (u32)nv_ro16(bios, addr) * 1000;
+
+ trace("PLL_INDIRECT\tR[0x%06x] =PLL= VBIOS[%04x] = %dkHz\n",
+ reg, addr, freq);
+ init->offset += 7;
+
+ init_prog_pll(init, reg, freq);
+}
+
+/**
+ * INIT_ZM_REG_INDIRECT - opcode 0x5a
+ *
+ */
+static void
+init_zm_reg_indirect(struct nvbios_init *init)
+{
+ struct nvkm_bios *bios = init->bios;
+ u32 reg = nv_ro32(bios, init->offset + 1);
+ u16 addr = nv_ro16(bios, init->offset + 5);
+ u32 data = nv_ro32(bios, addr);
+
+ trace("ZM_REG_INDIRECT\tR[0x%06x] = VBIOS[0x%04x] = 0x%08x\n",
+ reg, addr, data);
+ init->offset += 7;
+
+ init_wr32(init, addr, data);
+}
+
+/**
* INIT_SUB_DIRECT - opcode 0x5b
*
*/
@@ -2145,6 +2183,8 @@
[0x56] = { init_condition_time },
[0x57] = { init_ltime },
[0x58] = { init_zm_reg_sequence },
+ [0x59] = { init_pll_indirect },
+ [0x5a] = { init_zm_reg_indirect },
[0x5b] = { init_sub_direct },
[0x5c] = { init_jump },
[0x5e] = { init_i2c_if },
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
index 822d32a2..065e9f5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c
@@ -180,7 +180,8 @@
struct gt215_clk_info *info)
{
struct gt215_clk_priv *priv = (void *)clock;
- u32 oclk, sclk, sdiv, diff;
+ u32 oclk, sclk, sdiv;
+ s32 diff;
info->clk = 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c
index c0fdb89..24dcdfb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gk20a.c
@@ -38,6 +38,14 @@
nv_wr32(priv, 0x12004c, 0x4);
nv_wr32(priv, 0x122204, 0x2);
nv_rd32(priv, 0x122204);
+
+ /*
+ * Bug: increase clock timeout to avoid operation failure at high
+ * gpcclk rate.
+ */
+ nv_wr32(priv, 0x122354, 0x800);
+ nv_wr32(priv, 0x128328, 0x800);
+ nv_wr32(priv, 0x124320, 0x800);
}
static void
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
index 80614f1..282143f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c
@@ -50,7 +50,12 @@
{
struct nv04_instmem_priv *priv = (void *)nvkm_instmem(object);
struct nv04_instobj_priv *node = (void *)object;
+ struct nvkm_subdev *subdev = (void *)priv;
+
+ mutex_lock(&subdev->mutex);
nvkm_mm_free(&priv->heap, &node->mem);
+ mutex_unlock(&subdev->mutex);
+
nvkm_instobj_destroy(&node->base);
}
@@ -62,6 +67,7 @@
struct nv04_instmem_priv *priv = (void *)nvkm_instmem(parent);
struct nv04_instobj_priv *node;
struct nvkm_instobj_args *args = data;
+ struct nvkm_subdev *subdev = (void *)priv;
int ret;
if (!args->align)
@@ -72,8 +78,10 @@
if (ret)
return ret;
+ mutex_lock(&subdev->mutex);
ret = nvkm_mm_head(&priv->heap, 0, 1, args->size, args->size,
args->align, &node->mem);
+ mutex_unlock(&subdev->mutex);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index dd39f43..c387259 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -2299,8 +2299,7 @@
encoder_mode = atombios_get_encoder_mode(encoder);
if (connector && (radeon_audio != 0) &&
((encoder_mode == ATOM_ENCODER_MODE_HDMI) ||
- (ENCODER_MODE_IS_DP(encoder_mode) &&
- drm_detect_monitor_audio(radeon_connector_edid(connector)))))
+ ENCODER_MODE_IS_DP(encoder_mode)))
radeon_audio_mode_set(encoder, adjusted_mode);
}
diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c
index 68fd9fc..44480c1 100644
--- a/drivers/gpu/drm/radeon/dce6_afmt.c
+++ b/drivers/gpu/drm/radeon/dce6_afmt.c
@@ -93,30 +93,26 @@
struct radeon_device *rdev = encoder->dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
- u32 offset;
- if (!dig || !dig->afmt || !dig->afmt->pin)
+ if (!dig || !dig->afmt || !dig->pin)
return;
- offset = dig->afmt->offset;
-
- WREG32(AFMT_AUDIO_SRC_CONTROL + offset,
- AFMT_AUDIO_SRC_SELECT(dig->afmt->pin->id));
+ WREG32(AFMT_AUDIO_SRC_CONTROL + dig->afmt->offset,
+ AFMT_AUDIO_SRC_SELECT(dig->pin->id));
}
void dce6_afmt_write_latency_fields(struct drm_encoder *encoder,
- struct drm_connector *connector, struct drm_display_mode *mode)
+ struct drm_connector *connector,
+ struct drm_display_mode *mode)
{
struct radeon_device *rdev = encoder->dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
- u32 tmp = 0, offset;
+ u32 tmp = 0;
- if (!dig || !dig->afmt || !dig->afmt->pin)
+ if (!dig || !dig->afmt || !dig->pin)
return;
- offset = dig->afmt->pin->offset;
-
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
if (connector->latency_present[1])
tmp = VIDEO_LIPSYNC(connector->video_latency[1]) |
@@ -130,24 +126,24 @@
else
tmp = VIDEO_LIPSYNC(0) | AUDIO_LIPSYNC(0);
}
- WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp);
+ WREG32_ENDPOINT(dig->pin->offset,
+ AZ_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC, tmp);
}
void dce6_afmt_hdmi_write_speaker_allocation(struct drm_encoder *encoder,
- u8 *sadb, int sad_count)
+ u8 *sadb, int sad_count)
{
struct radeon_device *rdev = encoder->dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
- u32 offset, tmp;
+ u32 tmp;
- if (!dig || !dig->afmt || !dig->afmt->pin)
+ if (!dig || !dig->afmt || !dig->pin)
return;
- offset = dig->afmt->pin->offset;
-
/* program the speaker allocation */
- tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
+ tmp = RREG32_ENDPOINT(dig->pin->offset,
+ AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
tmp &= ~(DP_CONNECTION | SPEAKER_ALLOCATION_MASK);
/* set HDMI mode */
tmp |= HDMI_CONNECTION;
@@ -155,24 +151,24 @@
tmp |= SPEAKER_ALLOCATION(sadb[0]);
else
tmp |= SPEAKER_ALLOCATION(5); /* stereo */
- WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
+ WREG32_ENDPOINT(dig->pin->offset,
+ AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
}
void dce6_afmt_dp_write_speaker_allocation(struct drm_encoder *encoder,
- u8 *sadb, int sad_count)
+ u8 *sadb, int sad_count)
{
struct radeon_device *rdev = encoder->dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
- u32 offset, tmp;
+ u32 tmp;
- if (!dig || !dig->afmt || !dig->afmt->pin)
+ if (!dig || !dig->afmt || !dig->pin)
return;
- offset = dig->afmt->pin->offset;
-
/* program the speaker allocation */
- tmp = RREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
+ tmp = RREG32_ENDPOINT(dig->pin->offset,
+ AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
tmp &= ~(HDMI_CONNECTION | SPEAKER_ALLOCATION_MASK);
/* set DP mode */
tmp |= DP_CONNECTION;
@@ -180,13 +176,13 @@
tmp |= SPEAKER_ALLOCATION(sadb[0]);
else
tmp |= SPEAKER_ALLOCATION(5); /* stereo */
- WREG32_ENDPOINT(offset, AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
+ WREG32_ENDPOINT(dig->pin->offset,
+ AZ_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, tmp);
}
void dce6_afmt_write_sad_regs(struct drm_encoder *encoder,
- struct cea_sad *sads, int sad_count)
+ struct cea_sad *sads, int sad_count)
{
- u32 offset;
int i;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
@@ -206,11 +202,9 @@
{ AZ_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR13, HDMI_AUDIO_CODING_TYPE_WMA_PRO },
};
- if (!dig || !dig->afmt || !dig->afmt->pin)
+ if (!dig || !dig->afmt || !dig->pin)
return;
- offset = dig->afmt->pin->offset;
-
for (i = 0; i < ARRAY_SIZE(eld_reg_to_type); i++) {
u32 value = 0;
u8 stereo_freqs = 0;
@@ -237,7 +231,7 @@
value |= SUPPORTED_FREQUENCIES_STEREO(stereo_freqs);
- WREG32_ENDPOINT(offset, eld_reg_to_type[i][0], value);
+ WREG32_ENDPOINT(dig->pin->offset, eld_reg_to_type[i][0], value);
}
}
@@ -253,7 +247,7 @@
}
void dce6_hdmi_audio_set_dto(struct radeon_device *rdev,
- struct radeon_crtc *crtc, unsigned int clock)
+ struct radeon_crtc *crtc, unsigned int clock)
{
/* Two dtos; generally use dto0 for HDMI */
u32 value = 0;
@@ -272,7 +266,7 @@
}
void dce6_dp_audio_set_dto(struct radeon_device *rdev,
- struct radeon_crtc *crtc, unsigned int clock)
+ struct radeon_crtc *crtc, unsigned int clock)
{
/* Two dtos; generally use dto1 for DP */
u32 value = 0;
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index fa719c5..fbc8d88 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -245,6 +245,28 @@
static void radeon_audio_enable(struct radeon_device *rdev,
struct r600_audio_pin *pin, u8 enable_mask)
{
+ struct drm_encoder *encoder;
+ struct radeon_encoder *radeon_encoder;
+ struct radeon_encoder_atom_dig *dig;
+ int pin_count = 0;
+
+ if (!pin)
+ return;
+
+ if (rdev->mode_info.mode_config_initialized) {
+ list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) {
+ if (radeon_encoder_is_digital(encoder)) {
+ radeon_encoder = to_radeon_encoder(encoder);
+ dig = radeon_encoder->enc_priv;
+ if (dig->pin == pin)
+ pin_count++;
+ }
+ }
+
+ if ((pin_count > 1) && (enable_mask == 0))
+ return;
+ }
+
if (rdev->audio.funcs->enable)
rdev->audio.funcs->enable(rdev, pin, enable_mask);
}
@@ -336,24 +358,13 @@
static void radeon_audio_write_sad_regs(struct drm_encoder *encoder)
{
- struct radeon_encoder *radeon_encoder;
- struct drm_connector *connector;
- struct radeon_connector *radeon_connector = NULL;
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct cea_sad *sads;
int sad_count;
- list_for_each_entry(connector,
- &encoder->dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder) {
- radeon_connector = to_radeon_connector(connector);
- break;
- }
- }
-
- if (!radeon_connector) {
- DRM_ERROR("Couldn't find encoder's connector\n");
+ if (!connector)
return;
- }
sad_count = drm_edid_to_sad(radeon_connector_edid(connector), &sads);
if (sad_count <= 0) {
@@ -362,8 +373,6 @@
}
BUG_ON(!sads);
- radeon_encoder = to_radeon_encoder(encoder);
-
if (radeon_encoder->audio && radeon_encoder->audio->write_sad_regs)
radeon_encoder->audio->write_sad_regs(encoder, sads, sad_count);
@@ -372,27 +381,16 @@
static void radeon_audio_write_speaker_allocation(struct drm_encoder *encoder)
{
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
- struct drm_connector *connector;
- struct radeon_connector *radeon_connector = NULL;
u8 *sadb = NULL;
int sad_count;
- list_for_each_entry(connector,
- &encoder->dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder) {
- radeon_connector = to_radeon_connector(connector);
- break;
- }
- }
-
- if (!radeon_connector) {
- DRM_ERROR("Couldn't find encoder's connector\n");
+ if (!connector)
return;
- }
- sad_count = drm_edid_to_speaker_allocation(
- radeon_connector_edid(connector), &sadb);
+ sad_count = drm_edid_to_speaker_allocation(radeon_connector_edid(connector),
+ &sadb);
if (sad_count < 0) {
DRM_DEBUG("Couldn't read Speaker Allocation Data Block: %d\n",
sad_count);
@@ -406,26 +404,13 @@
}
static void radeon_audio_write_latency_fields(struct drm_encoder *encoder,
- struct drm_display_mode *mode)
+ struct drm_display_mode *mode)
{
- struct radeon_encoder *radeon_encoder;
- struct drm_connector *connector;
- struct radeon_connector *radeon_connector = 0;
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
- list_for_each_entry(connector,
- &encoder->dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder) {
- radeon_connector = to_radeon_connector(connector);
- break;
- }
- }
-
- if (!radeon_connector) {
- DRM_ERROR("Couldn't find encoder's connector\n");
+ if (!connector)
return;
- }
-
- radeon_encoder = to_radeon_encoder(encoder);
if (radeon_encoder->audio && radeon_encoder->audio->write_latency_fields)
radeon_encoder->audio->write_latency_fields(encoder, connector, mode);
@@ -451,29 +436,23 @@
}
void radeon_audio_detect(struct drm_connector *connector,
+ struct drm_encoder *encoder,
enum drm_connector_status status)
{
- struct radeon_device *rdev;
- struct radeon_encoder *radeon_encoder;
+ struct drm_device *dev = connector->dev;
+ struct radeon_device *rdev = dev->dev_private;
+ struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig;
- if (!connector || !connector->encoder)
- return;
-
- rdev = connector->encoder->dev->dev_private;
-
if (!radeon_audio_chipset_supported(rdev))
return;
- radeon_encoder = to_radeon_encoder(connector->encoder);
+ if (!radeon_encoder_is_digital(encoder))
+ return;
+
dig = radeon_encoder->enc_priv;
if (status == connector_status_connected) {
- if (!drm_detect_monitor_audio(radeon_connector_edid(connector))) {
- radeon_encoder->audio = NULL;
- return;
- }
-
if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -486,11 +465,17 @@
radeon_encoder->audio = rdev->audio.hdmi_funcs;
}
- dig->afmt->pin = radeon_audio_get_pin(connector->encoder);
- radeon_audio_enable(rdev, dig->afmt->pin, 0xf);
+ if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ if (!dig->pin)
+ dig->pin = radeon_audio_get_pin(encoder);
+ radeon_audio_enable(rdev, dig->pin, 0xf);
+ } else {
+ radeon_audio_enable(rdev, dig->pin, 0);
+ dig->pin = NULL;
+ }
} else {
- radeon_audio_enable(rdev, dig->afmt->pin, 0);
- dig->afmt->pin = NULL;
+ radeon_audio_enable(rdev, dig->pin, 0);
+ dig->pin = NULL;
}
}
@@ -518,29 +503,18 @@
}
static int radeon_audio_set_avi_packet(struct drm_encoder *encoder,
- struct drm_display_mode *mode)
+ struct drm_display_mode *mode)
{
struct radeon_device *rdev = encoder->dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
- struct drm_connector *connector;
- struct radeon_connector *radeon_connector = NULL;
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE];
struct hdmi_avi_infoframe frame;
int err;
- list_for_each_entry(connector,
- &encoder->dev->mode_config.connector_list, head) {
- if (connector->encoder == encoder) {
- radeon_connector = to_radeon_connector(connector);
- break;
- }
- }
-
- if (!radeon_connector) {
- DRM_ERROR("Couldn't find encoder's connector\n");
- return -ENOENT;
- }
+ if (!connector)
+ return -EINVAL;
err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
if (err < 0) {
@@ -563,8 +537,8 @@
return err;
}
- if (dig && dig->afmt &&
- radeon_encoder->audio && radeon_encoder->audio->set_avi_packet)
+ if (dig && dig->afmt && radeon_encoder->audio &&
+ radeon_encoder->audio->set_avi_packet)
radeon_encoder->audio->set_avi_packet(rdev, dig->afmt->offset,
buffer, sizeof(buffer));
@@ -722,30 +696,41 @@
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
if (!dig || !dig->afmt)
return;
- radeon_audio_set_mute(encoder, true);
-
- radeon_audio_write_speaker_allocation(encoder);
- radeon_audio_write_sad_regs(encoder);
- radeon_audio_write_latency_fields(encoder, mode);
- radeon_audio_set_dto(encoder, mode->clock);
- radeon_audio_set_vbi_packet(encoder);
- radeon_hdmi_set_color_depth(encoder);
- radeon_audio_update_acr(encoder, mode->clock);
- radeon_audio_set_audio_packet(encoder);
- radeon_audio_select_pin(encoder);
-
- if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+ if (!connector)
return;
- radeon_audio_set_mute(encoder, false);
+ if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ radeon_audio_set_mute(encoder, true);
+
+ radeon_audio_write_speaker_allocation(encoder);
+ radeon_audio_write_sad_regs(encoder);
+ radeon_audio_write_latency_fields(encoder, mode);
+ radeon_audio_set_dto(encoder, mode->clock);
+ radeon_audio_set_vbi_packet(encoder);
+ radeon_hdmi_set_color_depth(encoder);
+ radeon_audio_update_acr(encoder, mode->clock);
+ radeon_audio_set_audio_packet(encoder);
+ radeon_audio_select_pin(encoder);
+
+ if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+ return;
+
+ radeon_audio_set_mute(encoder, false);
+ } else {
+ radeon_hdmi_set_color_depth(encoder);
+
+ if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+ return;
+ }
}
static void radeon_audio_dp_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode)
+ struct drm_display_mode *mode)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
@@ -759,22 +744,27 @@
if (!dig || !dig->afmt)
return;
- radeon_audio_write_speaker_allocation(encoder);
- radeon_audio_write_sad_regs(encoder);
- radeon_audio_write_latency_fields(encoder, mode);
- if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev))
- radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10);
- else
- radeon_audio_set_dto(encoder, dig_connector->dp_clock);
- radeon_audio_set_audio_packet(encoder);
- radeon_audio_select_pin(encoder);
-
- if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+ if (!connector)
return;
+
+ if (drm_detect_monitor_audio(radeon_connector_edid(connector))) {
+ radeon_audio_write_speaker_allocation(encoder);
+ radeon_audio_write_sad_regs(encoder);
+ radeon_audio_write_latency_fields(encoder, mode);
+ if (rdev->clock.dp_extclk || ASIC_IS_DCE5(rdev))
+ radeon_audio_set_dto(encoder, rdev->clock.default_dispclk * 10);
+ else
+ radeon_audio_set_dto(encoder, dig_connector->dp_clock);
+ radeon_audio_set_audio_packet(encoder);
+ radeon_audio_select_pin(encoder);
+
+ if (radeon_audio_set_avi_packet(encoder, mode) < 0)
+ return;
+ }
}
void radeon_audio_mode_set(struct drm_encoder *encoder,
- struct drm_display_mode *mode)
+ struct drm_display_mode *mode)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
diff --git a/drivers/gpu/drm/radeon/radeon_audio.h b/drivers/gpu/drm/radeon/radeon_audio.h
index 8438304..059cc30 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.h
+++ b/drivers/gpu/drm/radeon/radeon_audio.h
@@ -68,7 +68,8 @@
int radeon_audio_init(struct radeon_device *rdev);
void radeon_audio_detect(struct drm_connector *connector,
- enum drm_connector_status status);
+ struct drm_encoder *encoder,
+ enum drm_connector_status status);
u32 radeon_audio_endpoint_rreg(struct radeon_device *rdev,
u32 offset, u32 reg);
void radeon_audio_endpoint_wreg(struct radeon_device *rdev,
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c
index 3e5f6b7..c097d3a 100644
--- a/drivers/gpu/drm/radeon/radeon_combios.c
+++ b/drivers/gpu/drm/radeon/radeon_combios.c
@@ -1255,10 +1255,15 @@
if ((RBIOS16(tmp) == lvds->native_mode.hdisplay) &&
(RBIOS16(tmp + 2) == lvds->native_mode.vdisplay)) {
+ u32 hss = (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8;
+
+ if (hss > lvds->native_mode.hdisplay)
+ hss = (10 - 1) * 8;
+
lvds->native_mode.htotal = lvds->native_mode.hdisplay +
(RBIOS16(tmp + 17) - RBIOS16(tmp + 19)) * 8;
lvds->native_mode.hsync_start = lvds->native_mode.hdisplay +
- (RBIOS16(tmp + 21) - RBIOS16(tmp + 19) - 1) * 8;
+ hss;
lvds->native_mode.hsync_end = lvds->native_mode.hsync_start +
(RBIOS8(tmp + 23) * 8);
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index cebb65e..94b21ae 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1379,8 +1379,16 @@
/* updated in get modes as well since we need to know if it's analog or digital */
radeon_connector_update_scratch_regs(connector, ret);
- if (radeon_audio != 0)
- radeon_audio_detect(connector, ret);
+ if ((radeon_audio != 0) && radeon_connector->use_digital) {
+ const struct drm_connector_helper_funcs *connector_funcs =
+ connector->helper_private;
+
+ encoder = connector_funcs->best_encoder(connector);
+ if (encoder && (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)) {
+ radeon_connector_get_edid(connector);
+ radeon_audio_detect(connector, encoder, ret);
+ }
+ }
exit:
pm_runtime_mark_last_busy(connector->dev->dev);
@@ -1717,8 +1725,10 @@
radeon_connector_update_scratch_regs(connector, ret);
- if (radeon_audio != 0)
- radeon_audio_detect(connector, ret);
+ if ((radeon_audio != 0) && encoder) {
+ radeon_connector_get_edid(connector);
+ radeon_audio_detect(connector, encoder, ret);
+ }
out:
pm_runtime_mark_last_busy(connector->dev->dev);
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c
index 1162bfa..171d3e4 100644
--- a/drivers/gpu/drm/radeon/radeon_irq_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c
@@ -79,6 +79,11 @@
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector;
+ /* we can race here at startup, some boards seem to trigger
+ * hotplug irqs when they shouldn't. */
+ if (!rdev->mode_info.mode_config_initialized)
+ return;
+
mutex_lock(&mode_config->mutex);
if (mode_config->num_connector) {
list_for_each_entry(connector, &mode_config->connector_list, head)
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index 07909d8..aecc3e3 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -237,7 +237,6 @@
int offset;
bool last_buffer_filled_status;
int id;
- struct r600_audio_pin *pin;
};
struct radeon_mode_info {
@@ -439,6 +438,7 @@
uint8_t backlight_level;
int panel_mode;
struct radeon_afmt *afmt;
+ struct r600_audio_pin *pin;
int active_mst_links;
};
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index 882cccd..ac6fe40 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -490,7 +490,8 @@
else if (boot_cpu_data.x86 > 3)
tmp = pgprot_noncached(tmp);
#endif
-#if defined(__ia64__) || defined(__arm__) || defined(__powerpc__)
+#if defined(__ia64__) || defined(__arm__) || defined(__aarch64__) || \
+ defined(__powerpc__)
if (caching_flags & TTM_PL_FLAG_WC)
tmp = pgprot_writecombine(tmp);
else
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 654c8da..97ad3bc 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -2492,7 +2492,7 @@
ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes,
true, NULL);
if (unlikely(ret != 0))
- goto out_err;
+ goto out_err_nores;
ret = vmw_validate_buffers(dev_priv, sw_context);
if (unlikely(ret != 0))
@@ -2536,6 +2536,7 @@
vmw_resource_relocations_free(&sw_context->res_relocations);
vmw_fifo_commit(dev_priv, command_size);
+ mutex_unlock(&dev_priv->binding_mutex);
vmw_query_bo_switch_commit(dev_priv, sw_context);
ret = vmw_execbuf_fence_commands(file_priv, dev_priv,
@@ -2551,7 +2552,6 @@
DRM_ERROR("Fence submission error. Syncing.\n");
vmw_resource_list_unreserve(&sw_context->resource_list, false);
- mutex_unlock(&dev_priv->binding_mutex);
ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes,
(void *) fence);
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index f822fd2..884d82f 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -546,6 +546,12 @@
.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
+ .driver_data = APPLE_HAS_FN },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
+ .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 157c627..e6fce23 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1782,6 +1782,9 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -2463,6 +2466,9 @@
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_ISO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING8_JIS) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_ISO) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
{ }
diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 3318de6..a2dbbbe 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -356,6 +356,8 @@
struct cp2112_force_read_report report;
int ret;
+ if (size > sizeof(dev->read_data))
+ size = sizeof(dev->read_data);
report.report = CP2112_DATA_READ_FORCE_SEND;
report.length = cpu_to_be16(size);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index b04b082..b3b225b 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -142,6 +142,9 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291
#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_DEVICE_ID_APPLE_IRCONTROL 0x8240
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 3511bbab..e3c6364 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -462,12 +462,15 @@
static void hidinput_cleanup_battery(struct hid_device *dev)
{
+ const struct power_supply_desc *psy_desc;
+
if (!dev->battery)
return;
+ psy_desc = dev->battery->desc;
power_supply_unregister(dev->battery);
- kfree(dev->battery->desc->name);
- kfree(dev->battery->desc);
+ kfree(psy_desc->name);
+ kfree(psy_desc);
dev->battery = NULL;
}
#else /* !CONFIG_HID_BATTERY_STRENGTH */
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 6a9b05b..7c81125 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -778,9 +778,16 @@
/*
* some egalax touchscreens have "application == HID_DG_TOUCHSCREEN"
* for the stylus.
+ * The check for mt_report_id ensures we don't process
+ * HID_DG_CONTACTCOUNT from the pen report as it is outside the physical
+ * collection, but within the report ID.
*/
if (field->physical == HID_DG_STYLUS)
return 0;
+ else if ((field->physical == 0) &&
+ (field->report->id != td->mt_report_id) &&
+ (td->mt_report_id != -1))
+ return 0;
if (field->application == HID_DG_TOUCHSCREEN ||
field->application == HID_DG_TOUCHPAD)
diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c
index 9416731..b905d50 100644
--- a/drivers/hid/hid-uclogic.c
+++ b/drivers/hid/hid-uclogic.c
@@ -858,7 +858,7 @@
for (p = drvdata->rdesc;
p <= drvdata->rdesc + drvdata->rsize - 4;) {
if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
- p[3] < sizeof(params)) {
+ p[3] < ARRAY_SIZE(params)) {
v = params[p[3]];
put_unaligned(cpu_to_le32(v), (s32 *)p);
p += 4;
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index 53e7de7..20f9a65 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -87,6 +87,9 @@
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
+ { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS },
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 4c0ffca..01b937e 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -1271,17 +1271,52 @@
pad_input_dev = NULL;
wacom_wac->pad_registered = false;
fail_register_pad_input:
- input_unregister_device(touch_input_dev);
+ if (touch_input_dev)
+ input_unregister_device(touch_input_dev);
wacom_wac->touch_input = NULL;
wacom_wac->touch_registered = false;
fail_register_touch_input:
- input_unregister_device(pen_input_dev);
+ if (pen_input_dev)
+ input_unregister_device(pen_input_dev);
wacom_wac->pen_input = NULL;
wacom_wac->pen_registered = false;
fail_register_pen_input:
return error;
}
+/*
+ * Not all devices report physical dimensions from HID.
+ * Compute the default from hardcoded logical dimension
+ * and resolution before driver overwrites them.
+ */
+static void wacom_set_default_phy(struct wacom_features *features)
+{
+ if (features->x_resolution) {
+ features->x_phy = (features->x_max * 100) /
+ features->x_resolution;
+ features->y_phy = (features->y_max * 100) /
+ features->y_resolution;
+ }
+}
+
+static void wacom_calculate_res(struct wacom_features *features)
+{
+ /* set unit to "100th of a mm" for devices not reported by HID */
+ if (!features->unit) {
+ features->unit = 0x11;
+ features->unitExpo = -3;
+ }
+
+ features->x_resolution = wacom_calc_hid_res(features->x_max,
+ features->x_phy,
+ features->unit,
+ features->unitExpo);
+ features->y_resolution = wacom_calc_hid_res(features->y_max,
+ features->y_phy,
+ features->unit,
+ features->unitExpo);
+}
+
static void wacom_wireless_work(struct work_struct *work)
{
struct wacom *wacom = container_of(work, struct wacom, work);
@@ -1339,6 +1374,8 @@
if (wacom_wac1->features.type != INTUOSHT &&
wacom_wac1->features.type != BAMBOO_PT)
wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD;
+ wacom_set_default_phy(&wacom_wac1->features);
+ wacom_calculate_res(&wacom_wac1->features);
snprintf(wacom_wac1->pen_name, WACOM_NAME_MAX, "%s (WL) Pen",
wacom_wac1->features.name);
snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",
@@ -1357,7 +1394,9 @@
wacom_wac2->features =
*((struct wacom_features *)id->driver_data);
wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3;
+ wacom_set_default_phy(&wacom_wac2->features);
wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096;
+ wacom_calculate_res(&wacom_wac2->features);
snprintf(wacom_wac2->touch_name, WACOM_NAME_MAX,
"%s (WL) Finger",wacom_wac2->features.name);
snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX,
@@ -1405,39 +1444,6 @@
}
}
-/*
- * Not all devices report physical dimensions from HID.
- * Compute the default from hardcoded logical dimension
- * and resolution before driver overwrites them.
- */
-static void wacom_set_default_phy(struct wacom_features *features)
-{
- if (features->x_resolution) {
- features->x_phy = (features->x_max * 100) /
- features->x_resolution;
- features->y_phy = (features->y_max * 100) /
- features->y_resolution;
- }
-}
-
-static void wacom_calculate_res(struct wacom_features *features)
-{
- /* set unit to "100th of a mm" for devices not reported by HID */
- if (!features->unit) {
- features->unit = 0x11;
- features->unitExpo = -3;
- }
-
- features->x_resolution = wacom_calc_hid_res(features->x_max,
- features->x_phy,
- features->unit,
- features->unitExpo);
- features->y_resolution = wacom_calc_hid_res(features->y_max,
- features->y_phy,
- features->unit,
- features->unitExpo);
-}
-
static size_t wacom_compute_pktlen(struct hid_device *hdev)
{
struct hid_report_enum *report_enum;
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 232da89..0d24423 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2213,6 +2213,9 @@
features->x_max = 4096;
features->y_max = 4096;
}
+ else if (features->pktlen == WACOM_PKGLEN_BBTOUCH) {
+ features->device_type |= WACOM_DEVICETYPE_PAD;
+ }
}
/*
diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c
index 603ce97..c4dcab0 100644
--- a/drivers/hv/channel.c
+++ b/drivers/hv/channel.c
@@ -601,6 +601,7 @@
u64 aligned_data = 0;
int ret;
bool signal = false;
+ int num_vecs = ((bufferlen != 0) ? 3 : 1);
/* Setup the descriptor */
@@ -618,7 +619,8 @@
bufferlist[2].iov_base = &aligned_data;
bufferlist[2].iov_len = (packetlen_aligned - packetlen);
- ret = hv_ringbuffer_write(&channel->outbound, bufferlist, 3, &signal);
+ ret = hv_ringbuffer_write(&channel->outbound, bufferlist, num_vecs,
+ &signal);
/*
* Signalling the host is conditional on many factors:
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 4506a66..2f9aead 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -347,6 +347,7 @@
IDE = 0,
SCSI,
NIC,
+ ND_NIC,
MAX_PERF_CHN,
};
@@ -391,6 +392,7 @@
struct vmbus_channel *primary = channel->primary_channel;
int next_node;
struct cpumask available_mask;
+ struct cpumask *alloced_mask;
for (i = IDE; i < MAX_PERF_CHN; i++) {
if (!memcmp(type_guid->b, hp_devs[i].guid,
@@ -408,7 +410,6 @@
* channel, bind it to cpu 0.
*/
channel->numa_node = 0;
- cpumask_set_cpu(0, &channel->alloced_cpus_in_node);
channel->target_cpu = 0;
channel->target_vp = hv_context.vp_index[0];
return;
@@ -433,21 +434,38 @@
channel->numa_node = next_node;
primary = channel;
}
+ alloced_mask = &hv_context.hv_numa_map[primary->numa_node];
- if (cpumask_weight(&primary->alloced_cpus_in_node) ==
+ if (cpumask_weight(alloced_mask) ==
cpumask_weight(cpumask_of_node(primary->numa_node))) {
/*
* We have cycled through all the CPUs in the node;
* reset the alloced map.
*/
- cpumask_clear(&primary->alloced_cpus_in_node);
+ cpumask_clear(alloced_mask);
}
- cpumask_xor(&available_mask, &primary->alloced_cpus_in_node,
+ cpumask_xor(&available_mask, alloced_mask,
cpumask_of_node(primary->numa_node));
- cur_cpu = cpumask_next(-1, &available_mask);
- cpumask_set_cpu(cur_cpu, &primary->alloced_cpus_in_node);
+ cur_cpu = -1;
+ while (true) {
+ cur_cpu = cpumask_next(cur_cpu, &available_mask);
+ if (cur_cpu >= nr_cpu_ids) {
+ cur_cpu = -1;
+ cpumask_copy(&available_mask,
+ cpumask_of_node(primary->numa_node));
+ continue;
+ }
+
+ if (!cpumask_test_cpu(cur_cpu,
+ &primary->alloced_cpus_in_node)) {
+ cpumask_set_cpu(cur_cpu,
+ &primary->alloced_cpus_in_node);
+ cpumask_set_cpu(cur_cpu, alloced_mask);
+ break;
+ }
+ }
channel->target_cpu = cur_cpu;
channel->target_vp = hv_context.vp_index[cur_cpu];
@@ -469,6 +487,10 @@
{
struct vmbus_channel_message_header hdr;
+ /* Pre-Win2012R2 hosts don't support reconnect */
+ if (vmbus_proto_version < VERSION_WIN8_1)
+ return;
+
init_completion(&vmbus_connection.unload_event);
memset(&hdr, 0, sizeof(struct vmbus_channel_message_header));
hdr.msgtype = CHANNELMSG_UNLOAD;
diff --git a/drivers/hv/hv.c b/drivers/hv/hv.c
index d3943bc..6341be8 100644
--- a/drivers/hv/hv.c
+++ b/drivers/hv/hv.c
@@ -93,11 +93,14 @@
*/
static u64 do_hypercall(u64 control, void *input, void *output)
{
-#ifdef CONFIG_X86_64
- u64 hv_status = 0;
u64 input_address = (input) ? virt_to_phys(input) : 0;
u64 output_address = (output) ? virt_to_phys(output) : 0;
void *hypercall_page = hv_context.hypercall_page;
+#ifdef CONFIG_X86_64
+ u64 hv_status = 0;
+
+ if (!hypercall_page)
+ return (u64)ULLONG_MAX;
__asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8");
__asm__ __volatile__("call *%3" : "=a" (hv_status) :
@@ -112,13 +115,13 @@
u32 control_lo = control & 0xFFFFFFFF;
u32 hv_status_hi = 1;
u32 hv_status_lo = 1;
- u64 input_address = (input) ? virt_to_phys(input) : 0;
u32 input_address_hi = input_address >> 32;
u32 input_address_lo = input_address & 0xFFFFFFFF;
- u64 output_address = (output) ? virt_to_phys(output) : 0;
u32 output_address_hi = output_address >> 32;
u32 output_address_lo = output_address & 0xFFFFFFFF;
- void *hypercall_page = hv_context.hypercall_page;
+
+ if (!hypercall_page)
+ return (u64)ULLONG_MAX;
__asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi),
"=a"(hv_status_lo) : "d" (control_hi),
@@ -130,6 +133,56 @@
#endif /* !x86_64 */
}
+#ifdef CONFIG_X86_64
+static cycle_t read_hv_clock_tsc(struct clocksource *arg)
+{
+ cycle_t current_tick;
+ struct ms_hyperv_tsc_page *tsc_pg = hv_context.tsc_page;
+
+ if (tsc_pg->tsc_sequence != -1) {
+ /*
+ * Use the tsc page to compute the value.
+ */
+
+ while (1) {
+ cycle_t tmp;
+ u32 sequence = tsc_pg->tsc_sequence;
+ u64 cur_tsc;
+ u64 scale = tsc_pg->tsc_scale;
+ s64 offset = tsc_pg->tsc_offset;
+
+ rdtscll(cur_tsc);
+ /* current_tick = ((cur_tsc *scale) >> 64) + offset */
+ asm("mulq %3"
+ : "=d" (current_tick), "=a" (tmp)
+ : "a" (cur_tsc), "r" (scale));
+
+ current_tick += offset;
+ if (tsc_pg->tsc_sequence == sequence)
+ return current_tick;
+
+ if (tsc_pg->tsc_sequence != -1)
+ continue;
+ /*
+ * Fallback using MSR method.
+ */
+ break;
+ }
+ }
+ rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
+ return current_tick;
+}
+
+static struct clocksource hyperv_cs_tsc = {
+ .name = "hyperv_clocksource_tsc_page",
+ .rating = 425,
+ .read = read_hv_clock_tsc,
+ .mask = CLOCKSOURCE_MASK(64),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+#endif
+
+
/*
* hv_init - Main initialization routine.
*
@@ -139,7 +192,9 @@
{
int max_leaf;
union hv_x64_msr_hypercall_contents hypercall_msr;
+ union hv_x64_msr_hypercall_contents tsc_msr;
void *virtaddr = NULL;
+ void *va_tsc = NULL;
memset(hv_context.synic_event_page, 0, sizeof(void *) * NR_CPUS);
memset(hv_context.synic_message_page, 0,
@@ -183,6 +238,22 @@
hv_context.hypercall_page = virtaddr;
+#ifdef CONFIG_X86_64
+ if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
+ va_tsc = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL);
+ if (!va_tsc)
+ goto cleanup;
+ hv_context.tsc_page = va_tsc;
+
+ rdmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
+
+ tsc_msr.enable = 1;
+ tsc_msr.guest_physical_address = vmalloc_to_pfn(va_tsc);
+
+ wrmsrl(HV_X64_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
+ clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
+ }
+#endif
return 0;
cleanup:
@@ -216,6 +287,21 @@
vfree(hv_context.hypercall_page);
hv_context.hypercall_page = NULL;
}
+
+#ifdef CONFIG_X86_64
+ /*
+ * Cleanup the TSC page based CS.
+ */
+ if (ms_hyperv.features & HV_X64_MSR_REFERENCE_TSC_AVAILABLE) {
+ clocksource_change_rating(&hyperv_cs_tsc, 10);
+ clocksource_unregister(&hyperv_cs_tsc);
+
+ hypercall_msr.as_uint64 = 0;
+ wrmsrl(HV_X64_MSR_REFERENCE_TSC, hypercall_msr.as_uint64);
+ vfree(hv_context.tsc_page);
+ hv_context.tsc_page = NULL;
+ }
+#endif
}
/*
@@ -271,7 +357,7 @@
{
cycle_t current_tick;
- WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
+ WARN_ON(!clockevent_state_oneshot(evt));
rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
current_tick += delta;
@@ -279,31 +365,24 @@
return 0;
}
-static void hv_ce_setmode(enum clock_event_mode mode,
- struct clock_event_device *evt)
+static int hv_ce_shutdown(struct clock_event_device *evt)
+{
+ wrmsrl(HV_X64_MSR_STIMER0_COUNT, 0);
+ wrmsrl(HV_X64_MSR_STIMER0_CONFIG, 0);
+
+ return 0;
+}
+
+static int hv_ce_set_oneshot(struct clock_event_device *evt)
{
union hv_timer_config timer_cfg;
- switch (mode) {
- case CLOCK_EVT_MODE_PERIODIC:
- /* unsupported */
- break;
+ timer_cfg.enable = 1;
+ timer_cfg.auto_enable = 1;
+ timer_cfg.sintx = VMBUS_MESSAGE_SINT;
+ wrmsrl(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
- case CLOCK_EVT_MODE_ONESHOT:
- timer_cfg.enable = 1;
- timer_cfg.auto_enable = 1;
- timer_cfg.sintx = VMBUS_MESSAGE_SINT;
- wrmsrl(HV_X64_MSR_STIMER0_CONFIG, timer_cfg.as_uint64);
- break;
-
- case CLOCK_EVT_MODE_UNUSED:
- case CLOCK_EVT_MODE_SHUTDOWN:
- wrmsrl(HV_X64_MSR_STIMER0_COUNT, 0);
- wrmsrl(HV_X64_MSR_STIMER0_CONFIG, 0);
- break;
- case CLOCK_EVT_MODE_RESUME:
- break;
- }
+ return 0;
}
static void hv_init_clockevent_device(struct clock_event_device *dev, int cpu)
@@ -318,7 +397,8 @@
* references to the hv_vmbus module making it impossible to unload.
*/
- dev->set_mode = hv_ce_setmode;
+ dev->set_state_shutdown = hv_ce_shutdown;
+ dev->set_state_oneshot = hv_ce_set_oneshot;
dev->set_next_event = hv_ce_set_next_event;
}
@@ -329,6 +409,13 @@
size_t ced_size = sizeof(struct clock_event_device);
int cpu;
+ hv_context.hv_numa_map = kzalloc(sizeof(struct cpumask) * nr_node_ids,
+ GFP_ATOMIC);
+ if (hv_context.hv_numa_map == NULL) {
+ pr_err("Unable to allocate NUMA map\n");
+ goto err;
+ }
+
for_each_online_cpu(cpu) {
hv_context.event_dpc[cpu] = kmalloc(size, GFP_ATOMIC);
if (hv_context.event_dpc[cpu] == NULL) {
@@ -342,6 +429,7 @@
pr_err("Unable to allocate clock event device\n");
goto err;
}
+
hv_init_clockevent_device(hv_context.clk_evt[cpu], cpu);
hv_context.synic_message_page[cpu] =
@@ -390,6 +478,7 @@
{
int cpu;
+ kfree(hv_context.hv_numa_map);
for_each_online_cpu(cpu)
hv_synic_free_cpu(cpu);
}
@@ -503,8 +592,7 @@
/* Turn off clockevent device */
if (ms_hyperv.features & HV_X64_MSR_SYNTIMER_AVAILABLE)
- hv_ce_setmode(CLOCK_EVT_MODE_SHUTDOWN,
- hv_context.clk_evt[cpu]);
+ hv_ce_shutdown(hv_context.clk_evt[cpu]);
rdmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64);
@@ -530,6 +618,4 @@
rdmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
sctrl.enable = 0;
wrmsrl(HV_X64_MSR_SCONTROL, sctrl.as_uint64);
-
- hv_synic_free_cpu(cpu);
}
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index 8a725cd..b853b4b 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -62,11 +62,13 @@
enum {
DYNMEM_PROTOCOL_VERSION_1 = DYNMEM_MAKE_VERSION(0, 3),
DYNMEM_PROTOCOL_VERSION_2 = DYNMEM_MAKE_VERSION(1, 0),
+ DYNMEM_PROTOCOL_VERSION_3 = DYNMEM_MAKE_VERSION(2, 0),
DYNMEM_PROTOCOL_VERSION_WIN7 = DYNMEM_PROTOCOL_VERSION_1,
DYNMEM_PROTOCOL_VERSION_WIN8 = DYNMEM_PROTOCOL_VERSION_2,
+ DYNMEM_PROTOCOL_VERSION_WIN10 = DYNMEM_PROTOCOL_VERSION_3,
- DYNMEM_PROTOCOL_VERSION_CURRENT = DYNMEM_PROTOCOL_VERSION_WIN8
+ DYNMEM_PROTOCOL_VERSION_CURRENT = DYNMEM_PROTOCOL_VERSION_WIN10
};
@@ -1296,13 +1298,25 @@
if (dm->next_version == 0)
goto version_error;
- dm->next_version = 0;
memset(&version_req, 0, sizeof(struct dm_version_request));
version_req.hdr.type = DM_VERSION_REQUEST;
version_req.hdr.size = sizeof(struct dm_version_request);
version_req.hdr.trans_id = atomic_inc_return(&trans_id);
- version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN7;
- version_req.is_last_attempt = 1;
+ version_req.version.version = dm->next_version;
+
+ /*
+ * Set the next version to try in case current version fails.
+ * Win7 protocol ought to be the last one to try.
+ */
+ switch (version_req.version.version) {
+ case DYNMEM_PROTOCOL_VERSION_WIN8:
+ dm->next_version = DYNMEM_PROTOCOL_VERSION_WIN7;
+ version_req.is_last_attempt = 0;
+ break;
+ default:
+ dm->next_version = 0;
+ version_req.is_last_attempt = 1;
+ }
ret = vmbus_sendpacket(dm->dev->channel, &version_req,
sizeof(struct dm_version_request),
@@ -1442,7 +1456,7 @@
dm_device.dev = dev;
dm_device.state = DM_INITIALIZING;
- dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN7;
+ dm_device.next_version = DYNMEM_PROTOCOL_VERSION_WIN8;
init_completion(&dm_device.host_event);
init_completion(&dm_device.config_event);
INIT_LIST_HEAD(&dm_device.ha_region_list);
@@ -1474,7 +1488,7 @@
version_req.hdr.type = DM_VERSION_REQUEST;
version_req.hdr.size = sizeof(struct dm_version_request);
version_req.hdr.trans_id = atomic_inc_return(&trans_id);
- version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN8;
+ version_req.version.version = DYNMEM_PROTOCOL_VERSION_WIN10;
version_req.is_last_attempt = 0;
ret = vmbus_sendpacket(dev->channel, &version_req,
diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c
index b50dd33..db4b887 100644
--- a/drivers/hv/hv_fcopy.c
+++ b/drivers/hv/hv_fcopy.c
@@ -116,7 +116,7 @@
static void fcopy_send_data(struct work_struct *dummy)
{
- struct hv_start_fcopy smsg_out;
+ struct hv_start_fcopy *smsg_out = NULL;
int operation = fcopy_transaction.fcopy_msg->operation;
struct hv_start_fcopy *smsg_in;
void *out_src;
@@ -136,21 +136,24 @@
switch (operation) {
case START_FILE_COPY:
out_len = sizeof(struct hv_start_fcopy);
- memset(&smsg_out, 0, out_len);
- smsg_out.hdr.operation = operation;
+ smsg_out = kzalloc(sizeof(*smsg_out), GFP_KERNEL);
+ if (!smsg_out)
+ return;
+
+ smsg_out->hdr.operation = operation;
smsg_in = (struct hv_start_fcopy *)fcopy_transaction.fcopy_msg;
utf16s_to_utf8s((wchar_t *)smsg_in->file_name, W_MAX_PATH,
UTF16_LITTLE_ENDIAN,
- (__u8 *)&smsg_out.file_name, W_MAX_PATH - 1);
+ (__u8 *)&smsg_out->file_name, W_MAX_PATH - 1);
utf16s_to_utf8s((wchar_t *)smsg_in->path_name, W_MAX_PATH,
UTF16_LITTLE_ENDIAN,
- (__u8 *)&smsg_out.path_name, W_MAX_PATH - 1);
+ (__u8 *)&smsg_out->path_name, W_MAX_PATH - 1);
- smsg_out.copy_flags = smsg_in->copy_flags;
- smsg_out.file_size = smsg_in->file_size;
- out_src = &smsg_out;
+ smsg_out->copy_flags = smsg_in->copy_flags;
+ smsg_out->file_size = smsg_in->file_size;
+ out_src = smsg_out;
break;
default:
@@ -168,6 +171,8 @@
fcopy_transaction.state = HVUTIL_READY;
}
}
+ kfree(smsg_out);
+
return;
}
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index d85798d..74c38a9 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -353,6 +353,9 @@
return;
message = kzalloc(sizeof(*message), GFP_KERNEL);
+ if (!message)
+ return;
+
message->kvp_hdr.operation = operation;
message->kvp_hdr.pool = pool;
in_msg = kvp_transaction.kvp_msg;
diff --git a/drivers/hv/hv_utils_transport.c b/drivers/hv/hv_utils_transport.c
index ea7ba5e..6a9d80a 100644
--- a/drivers/hv/hv_utils_transport.c
+++ b/drivers/hv/hv_utils_transport.c
@@ -186,7 +186,7 @@
return -EINVAL;
} else if (hvt->mode == HVUTIL_TRANSPORT_NETLINK) {
cn_msg = kzalloc(sizeof(*cn_msg) + len, GFP_ATOMIC);
- if (!msg)
+ if (!cn_msg)
return -ENOMEM;
cn_msg->id.idx = hvt->cn_id.idx;
cn_msg->id.val = hvt->cn_id.val;
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index cddc0c9..3d70e36 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -141,7 +141,7 @@
struct {
u32 target_sint;
u32 target_vp;
- u16 base_flag_bumber;
+ u16 base_flag_number;
u16 flag_count;
u32 rsvdz;
} event_port_info;
@@ -517,6 +517,7 @@
u64 guestid;
void *hypercall_page;
+ void *tsc_page;
bool synic_initialized;
@@ -551,10 +552,23 @@
* Support PV clockevent device.
*/
struct clock_event_device *clk_evt[NR_CPUS];
+ /*
+ * To manage allocations in a NUMA node.
+ * Array indexed by numa node ID.
+ */
+ struct cpumask *hv_numa_map;
};
extern struct hv_context hv_context;
+struct ms_hyperv_tsc_page {
+ volatile u32 tsc_sequence;
+ u32 reserved1;
+ volatile u64 tsc_scale;
+ volatile s64 tsc_offset;
+ u64 reserved2[509];
+};
+
struct hv_ring_buffer_debug_info {
u32 current_interrupt_mask;
u32 current_read_index;
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 6361d12..70a1a9a 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -103,10 +103,9 @@
* there is room for the producer to send the pending packet.
*/
-static bool hv_need_to_signal_on_read(u32 old_rd,
- struct hv_ring_buffer_info *rbi)
+static bool hv_need_to_signal_on_read(u32 prev_write_sz,
+ struct hv_ring_buffer_info *rbi)
{
- u32 prev_write_sz;
u32 cur_write_sz;
u32 r_size;
u32 write_loc = rbi->ring_buffer->write_index;
@@ -123,10 +122,6 @@
cur_write_sz = write_loc >= read_loc ? r_size - (write_loc - read_loc) :
read_loc - write_loc;
- prev_write_sz = write_loc >= old_rd ? r_size - (write_loc - old_rd) :
- old_rd - write_loc;
-
-
if ((prev_write_sz < pending_sz) && (cur_write_sz >= pending_sz))
return true;
@@ -517,7 +512,6 @@
u32 next_read_location = 0;
u64 prev_indices = 0;
unsigned long flags;
- u32 old_read;
if (buflen <= 0)
return -EINVAL;
@@ -528,8 +522,6 @@
&bytes_avail_toread,
&bytes_avail_towrite);
- old_read = bytes_avail_toread;
-
/* Make sure there is something to read */
if (bytes_avail_toread < buflen) {
spin_unlock_irqrestore(&inring_info->ring_lock, flags);
@@ -560,7 +552,7 @@
spin_unlock_irqrestore(&inring_info->ring_lock, flags);
- *signal = hv_need_to_signal_on_read(old_read, inring_info);
+ *signal = hv_need_to_signal_on_read(bytes_avail_towrite, inring_info);
return 0;
}
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index cf20400..f19b6f7 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -39,6 +39,8 @@
#include <asm/mshyperv.h>
#include <linux/notifier.h>
#include <linux/ptrace.h>
+#include <linux/screen_info.h>
+#include <linux/kdebug.h>
#include "hyperv_vmbus.h"
static struct acpi_device *hv_acpi_dev;
@@ -48,12 +50,18 @@
static int irq;
-static int hyperv_panic_event(struct notifier_block *nb,
- unsigned long event, void *ptr)
+static void hyperv_report_panic(struct pt_regs *regs)
{
- struct pt_regs *regs;
+ static bool panic_reported;
- regs = current_pt_regs();
+ /*
+ * We prefer to report panic on 'die' chain as we have proper
+ * registers to report, but if we miss it (e.g. on BUG()) we need
+ * to report it on 'panic'.
+ */
+ if (panic_reported)
+ return;
+ panic_reported = true;
wrmsrl(HV_X64_MSR_CRASH_P0, regs->ip);
wrmsrl(HV_X64_MSR_CRASH_P1, regs->ax);
@@ -65,18 +73,37 @@
* Let Hyper-V know there is crash data available
*/
wrmsrl(HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_CRASH_NOTIFY);
+}
+
+static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
+ void *args)
+{
+ struct pt_regs *regs;
+
+ regs = current_pt_regs();
+
+ hyperv_report_panic(regs);
return NOTIFY_DONE;
}
+static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
+ void *args)
+{
+ struct die_args *die = (struct die_args *)args;
+ struct pt_regs *regs = die->regs;
+
+ hyperv_report_panic(regs);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block hyperv_die_block = {
+ .notifier_call = hyperv_die_event,
+};
static struct notifier_block hyperv_panic_block = {
.notifier_call = hyperv_panic_event,
};
-struct resource hyperv_mmio = {
- .name = "hyperv mmio",
- .flags = IORESOURCE_MEM,
-};
-EXPORT_SYMBOL_GPL(hyperv_mmio);
+struct resource *hyperv_mmio;
static int vmbus_exists(void)
{
@@ -414,6 +441,43 @@
}
static DEVICE_ATTR_RO(in_write_bytes_avail);
+static ssize_t channel_vp_mapping_show(struct device *dev,
+ struct device_attribute *dev_attr,
+ char *buf)
+{
+ struct hv_device *hv_dev = device_to_hv_device(dev);
+ struct vmbus_channel *channel = hv_dev->channel, *cur_sc;
+ unsigned long flags;
+ int buf_size = PAGE_SIZE, n_written, tot_written;
+ struct list_head *cur;
+
+ if (!channel)
+ return -ENODEV;
+
+ tot_written = snprintf(buf, buf_size, "%u:%u\n",
+ channel->offermsg.child_relid, channel->target_cpu);
+
+ spin_lock_irqsave(&channel->lock, flags);
+
+ list_for_each(cur, &channel->sc_list) {
+ if (tot_written >= buf_size - 1)
+ break;
+
+ cur_sc = list_entry(cur, struct vmbus_channel, sc_list);
+ n_written = scnprintf(buf + tot_written,
+ buf_size - tot_written,
+ "%u:%u\n",
+ cur_sc->offermsg.child_relid,
+ cur_sc->target_cpu);
+ tot_written += n_written;
+ }
+
+ spin_unlock_irqrestore(&channel->lock, flags);
+
+ return tot_written;
+}
+static DEVICE_ATTR_RO(channel_vp_mapping);
+
/* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */
static struct attribute *vmbus_attrs[] = {
&dev_attr_id.attr,
@@ -438,6 +502,7 @@
&dev_attr_in_write_index.attr,
&dev_attr_in_read_bytes_avail.attr,
&dev_attr_in_write_bytes_avail.attr,
+ &dev_attr_channel_vp_mapping.attr,
NULL,
};
ATTRIBUTE_GROUPS(vmbus);
@@ -763,38 +828,6 @@
}
}
-#ifdef CONFIG_HOTPLUG_CPU
-static int hyperv_cpu_disable(void)
-{
- return -ENOSYS;
-}
-
-static void hv_cpu_hotplug_quirk(bool vmbus_loaded)
-{
- static void *previous_cpu_disable;
-
- /*
- * Offlining a CPU when running on newer hypervisors (WS2012R2, Win8,
- * ...) is not supported at this moment as channel interrupts are
- * distributed across all of them.
- */
-
- if ((vmbus_proto_version == VERSION_WS2008) ||
- (vmbus_proto_version == VERSION_WIN7))
- return;
-
- if (vmbus_loaded) {
- previous_cpu_disable = smp_ops.cpu_disable;
- smp_ops.cpu_disable = hyperv_cpu_disable;
- pr_notice("CPU offlining is not supported by hypervisor\n");
- } else if (previous_cpu_disable)
- smp_ops.cpu_disable = previous_cpu_disable;
-}
-#else
-static void hv_cpu_hotplug_quirk(bool vmbus_loaded)
-{
-}
-#endif
/*
* vmbus_bus_init -Main vmbus driver initialization routine.
@@ -836,12 +869,14 @@
if (ret)
goto err_alloc;
- hv_cpu_hotplug_quirk(true);
+ if (vmbus_proto_version > VERSION_WIN7)
+ cpu_hotplug_disable();
/*
* Only register if the crash MSRs are available
*/
- if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+ register_die_notifier(&hyperv_die_block);
atomic_notifier_chain_register(&panic_notifier_list,
&hyperv_panic_block);
}
@@ -863,8 +898,8 @@
}
/**
- * __vmbus_child_driver_register - Register a vmbus's driver
- * @drv: Pointer to driver structure you want to register
+ * __vmbus_child_driver_register() - Register a vmbus's driver
+ * @hv_driver: Pointer to driver structure you want to register
* @owner: owner module of the drv
* @mod_name: module name string
*
@@ -896,7 +931,8 @@
/**
* vmbus_driver_unregister() - Unregister a vmbus's driver
- * @drv: Pointer to driver structure you want to un-register
+ * @hv_driver: Pointer to driver structure you want to
+ * un-register
*
* Un-register the given driver that was previous registered with a call to
* vmbus_driver_register()
@@ -982,30 +1018,184 @@
/*
- * VMBUS is an acpi enumerated device. Get the the information we
+ * VMBUS is an acpi enumerated device. Get the information we
* need from DSDT.
*/
-
+#define VTPM_BASE_ADDRESS 0xfed40000
static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
{
+ resource_size_t start = 0;
+ resource_size_t end = 0;
+ struct resource *new_res;
+ struct resource **old_res = &hyperv_mmio;
+ struct resource **prev_res = NULL;
+
switch (res->type) {
case ACPI_RESOURCE_TYPE_IRQ:
irq = res->data.irq.interrupts[0];
+ return AE_OK;
+
+ /*
+ * "Address" descriptors are for bus windows. Ignore
+ * "memory" descriptors, which are for registers on
+ * devices.
+ */
+ case ACPI_RESOURCE_TYPE_ADDRESS32:
+ start = res->data.address32.address.minimum;
+ end = res->data.address32.address.maximum;
break;
case ACPI_RESOURCE_TYPE_ADDRESS64:
- hyperv_mmio.start = res->data.address64.address.minimum;
- hyperv_mmio.end = res->data.address64.address.maximum;
+ start = res->data.address64.address.minimum;
+ end = res->data.address64.address.maximum;
break;
+
+ default:
+ /* Unused resource type */
+ return AE_OK;
+
}
+ /*
+ * Ignore ranges that are below 1MB, as they're not
+ * necessary or useful here.
+ */
+ if (end < 0x100000)
+ return AE_OK;
+
+ new_res = kzalloc(sizeof(*new_res), GFP_ATOMIC);
+ if (!new_res)
+ return AE_NO_MEMORY;
+
+ /* If this range overlaps the virtual TPM, truncate it. */
+ if (end > VTPM_BASE_ADDRESS && start < VTPM_BASE_ADDRESS)
+ end = VTPM_BASE_ADDRESS;
+
+ new_res->name = "hyperv mmio";
+ new_res->flags = IORESOURCE_MEM;
+ new_res->start = start;
+ new_res->end = end;
+
+ do {
+ if (!*old_res) {
+ *old_res = new_res;
+ break;
+ }
+
+ if ((*old_res)->end < new_res->start) {
+ new_res->sibling = *old_res;
+ if (prev_res)
+ (*prev_res)->sibling = new_res;
+ *old_res = new_res;
+ break;
+ }
+
+ prev_res = old_res;
+ old_res = &(*old_res)->sibling;
+
+ } while (1);
return AE_OK;
}
+static int vmbus_acpi_remove(struct acpi_device *device)
+{
+ struct resource *cur_res;
+ struct resource *next_res;
+
+ if (hyperv_mmio) {
+ for (cur_res = hyperv_mmio; cur_res; cur_res = next_res) {
+ next_res = cur_res->sibling;
+ kfree(cur_res);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * vmbus_allocate_mmio() - Pick a memory-mapped I/O range.
+ * @new: If successful, supplied a pointer to the
+ * allocated MMIO space.
+ * @device_obj: Identifies the caller
+ * @min: Minimum guest physical address of the
+ * allocation
+ * @max: Maximum guest physical address
+ * @size: Size of the range to be allocated
+ * @align: Alignment of the range to be allocated
+ * @fb_overlap_ok: Whether this allocation can be allowed
+ * to overlap the video frame buffer.
+ *
+ * This function walks the resources granted to VMBus by the
+ * _CRS object in the ACPI namespace underneath the parent
+ * "bridge" whether that's a root PCI bus in the Generation 1
+ * case or a Module Device in the Generation 2 case. It then
+ * attempts to allocate from the global MMIO pool in a way that
+ * matches the constraints supplied in these parameters and by
+ * that _CRS.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
+ resource_size_t min, resource_size_t max,
+ resource_size_t size, resource_size_t align,
+ bool fb_overlap_ok)
+{
+ struct resource *iter;
+ resource_size_t range_min, range_max, start, local_min, local_max;
+ const char *dev_n = dev_name(&device_obj->device);
+ u32 fb_end = screen_info.lfb_base + (screen_info.lfb_size << 1);
+ int i;
+
+ for (iter = hyperv_mmio; iter; iter = iter->sibling) {
+ if ((iter->start >= max) || (iter->end <= min))
+ continue;
+
+ range_min = iter->start;
+ range_max = iter->end;
+
+ /* If this range overlaps the frame buffer, split it into
+ two tries. */
+ for (i = 0; i < 2; i++) {
+ local_min = range_min;
+ local_max = range_max;
+ if (fb_overlap_ok || (range_min >= fb_end) ||
+ (range_max <= screen_info.lfb_base)) {
+ i++;
+ } else {
+ if ((range_min <= screen_info.lfb_base) &&
+ (range_max >= screen_info.lfb_base)) {
+ /*
+ * The frame buffer is in this window,
+ * so trim this into the part that
+ * preceeds the frame buffer.
+ */
+ local_max = screen_info.lfb_base - 1;
+ range_min = fb_end;
+ } else {
+ range_min = fb_end;
+ continue;
+ }
+ }
+
+ start = (local_min + align - 1) & ~(align - 1);
+ for (; start + size - 1 <= local_max; start += align) {
+ *new = request_mem_region_exclusive(start, size,
+ dev_n);
+ if (*new)
+ return 0;
+ }
+ }
+ }
+
+ return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(vmbus_allocate_mmio);
+
static int vmbus_acpi_add(struct acpi_device *device)
{
acpi_status result;
int ret_val = -ENODEV;
+ struct acpi_device *ancestor;
hv_acpi_dev = device;
@@ -1015,35 +1205,27 @@
if (ACPI_FAILURE(result))
goto acpi_walk_err;
/*
- * The parent of the vmbus acpi device (Gen2 firmware) is the VMOD that
- * has the mmio ranges. Get that.
+ * Some ancestor of the vmbus acpi device (Gen1 or Gen2
+ * firmware) is the VMOD that has the mmio ranges. Get that.
*/
- if (device->parent) {
- result = acpi_walk_resources(device->parent->handle,
- METHOD_NAME__CRS,
- vmbus_walk_resources, NULL);
+ for (ancestor = device->parent; ancestor; ancestor = ancestor->parent) {
+ result = acpi_walk_resources(ancestor->handle, METHOD_NAME__CRS,
+ vmbus_walk_resources, NULL);
if (ACPI_FAILURE(result))
- goto acpi_walk_err;
- if (hyperv_mmio.start && hyperv_mmio.end)
- request_resource(&iomem_resource, &hyperv_mmio);
+ continue;
+ if (hyperv_mmio)
+ break;
}
ret_val = 0;
acpi_walk_err:
complete(&probe_event);
+ if (ret_val)
+ vmbus_acpi_remove(device);
return ret_val;
}
-static int vmbus_acpi_remove(struct acpi_device *device)
-{
- int ret = 0;
-
- if (hyperv_mmio.start && hyperv_mmio.end)
- ret = release_resource(&hyperv_mmio);
- return ret;
-}
-
static const struct acpi_device_id vmbus_acpi_device_ids[] = {
{"VMBUS", 0},
{"VMBus", 0},
@@ -1060,6 +1242,29 @@
},
};
+static void hv_kexec_handler(void)
+{
+ int cpu;
+
+ hv_synic_clockevents_cleanup();
+ vmbus_initiate_unload();
+ for_each_online_cpu(cpu)
+ smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
+ hv_cleanup();
+};
+
+static void hv_crash_handler(struct pt_regs *regs)
+{
+ vmbus_initiate_unload();
+ /*
+ * In crash handler we can't schedule synic cleanup for all CPUs,
+ * doing the cleanup for current CPU only. This should be sufficient
+ * for kdump.
+ */
+ hv_synic_cleanup(NULL);
+ hv_cleanup();
+};
+
static int __init hv_acpi_init(void)
{
int ret, t;
@@ -1092,6 +1297,9 @@
if (ret)
goto cleanup;
+ hv_setup_kexec_handler(hv_kexec_handler);
+ hv_setup_crash_handler(hv_crash_handler);
+
return 0;
cleanup:
@@ -1104,13 +1312,16 @@
{
int cpu;
+ hv_remove_kexec_handler();
+ hv_remove_crash_handler();
vmbus_connection.conn_state = DISCONNECTED;
hv_synic_clockevents_cleanup();
vmbus_disconnect();
hv_remove_vmbus_irq();
tasklet_kill(&msg_dpc);
vmbus_free_channels();
- if (ms_hyperv.features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+ if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
+ unregister_die_notifier(&hyperv_die_block);
atomic_notifier_chain_unregister(&panic_notifier_list,
&hyperv_panic_block);
}
@@ -1120,8 +1331,10 @@
tasklet_kill(hv_context.event_dpc[cpu]);
smp_call_function_single(cpu, hv_synic_cleanup, NULL, 1);
}
+ hv_synic_free();
acpi_bus_unregister_driver(&vmbus_acpi_driver);
- hv_cpu_hotplug_quirk(false);
+ if (vmbus_proto_version > VERSION_WIN7)
+ cpu_hotplug_enable();
}
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index 37c16af..c848789 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -929,6 +929,21 @@
MODULE_DEVICE_TABLE(dmi, i8k_dmi_table);
+static struct dmi_system_id i8k_blacklist_dmi_table[] __initdata = {
+ {
+ /*
+ * CPU fan speed going up and down on Dell Studio XPS 8100
+ * for unknown reasons.
+ */
+ .ident = "Dell Studio XPS 8100",
+ .matches = {
+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Studio XPS 8100"),
+ },
+ },
+ { }
+};
+
/*
* Probe for the presence of a supported laptop.
*/
@@ -940,7 +955,8 @@
/*
* Get DMI information
*/
- if (!dmi_check_system(i8k_dmi_table)) {
+ if (!dmi_check_system(i8k_dmi_table) ||
+ dmi_check_system(i8k_blacklist_dmi_table)) {
if (!ignore_dmi && !force)
return -ENODEV;
diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c
index 9b55e67..85d106f 100644
--- a/drivers/hwmon/g762.c
+++ b/drivers/hwmon/g762.c
@@ -582,6 +582,7 @@
{ .compatible = "gmt,g763" },
{ },
};
+MODULE_DEVICE_TABLE(of, g762_dt_match);
/*
* Grab clock (a required property), enable it, get (fixed) clock frequency
diff --git a/drivers/hwmon/nct7802.c b/drivers/hwmon/nct7802.c
index 28fcb2e..fbfc02b 100644
--- a/drivers/hwmon/nct7802.c
+++ b/drivers/hwmon/nct7802.c
@@ -195,7 +195,7 @@
}
static int nct7802_write_voltage(struct nct7802_data *data, int nr, int index,
- unsigned int voltage)
+ unsigned long voltage)
{
int shift = 8 - REG_VOLTAGE_LIMIT_MSB_SHIFT[index - 1][nr];
int err;
diff --git a/drivers/hwmon/nct7904.c b/drivers/hwmon/nct7904.c
index b77b82f..08ff89d 100644
--- a/drivers/hwmon/nct7904.c
+++ b/drivers/hwmon/nct7904.c
@@ -412,8 +412,9 @@
return sprintf(buf, "%d\n", val);
}
-static ssize_t store_mode(struct device *dev, struct device_attribute *devattr,
- const char *buf, size_t count)
+static ssize_t store_enable(struct device *dev,
+ struct device_attribute *devattr,
+ const char *buf, size_t count)
{
int index = to_sensor_dev_attr(devattr)->index;
struct nct7904_data *data = dev_get_drvdata(dev);
@@ -422,18 +423,18 @@
if (kstrtoul(buf, 10, &val) < 0)
return -EINVAL;
- if (val > 1 || (val && !data->fan_mode[index]))
+ if (val < 1 || val > 2 || (val == 2 && !data->fan_mode[index]))
return -EINVAL;
ret = nct7904_write_reg(data, BANK_3, FANCTL1_FMR_REG + index,
- val ? data->fan_mode[index] : 0);
+ val == 2 ? data->fan_mode[index] : 0);
return ret ? ret : count;
}
-/* Return 0 for manual mode or 1 for SmartFan mode */
-static ssize_t show_mode(struct device *dev,
- struct device_attribute *devattr, char *buf)
+/* Return 1 for manual mode or 2 for SmartFan mode */
+static ssize_t show_enable(struct device *dev,
+ struct device_attribute *devattr, char *buf)
{
int index = to_sensor_dev_attr(devattr)->index;
struct nct7904_data *data = dev_get_drvdata(dev);
@@ -443,36 +444,36 @@
if (val < 0)
return val;
- return sprintf(buf, "%d\n", val ? 1 : 0);
+ return sprintf(buf, "%d\n", val ? 2 : 1);
}
/* 2 attributes per channel: pwm and mode */
-static SENSOR_DEVICE_ATTR(fan1_pwm, S_IRUGO | S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR,
show_pwm, store_pwm, 0);
-static SENSOR_DEVICE_ATTR(fan1_mode, S_IRUGO | S_IWUSR,
- show_mode, store_mode, 0);
-static SENSOR_DEVICE_ATTR(fan2_pwm, S_IRUGO | S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR,
+ show_enable, store_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR,
show_pwm, store_pwm, 1);
-static SENSOR_DEVICE_ATTR(fan2_mode, S_IRUGO | S_IWUSR,
- show_mode, store_mode, 1);
-static SENSOR_DEVICE_ATTR(fan3_pwm, S_IRUGO | S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR,
+ show_enable, store_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR,
show_pwm, store_pwm, 2);
-static SENSOR_DEVICE_ATTR(fan3_mode, S_IRUGO | S_IWUSR,
- show_mode, store_mode, 2);
-static SENSOR_DEVICE_ATTR(fan4_pwm, S_IRUGO | S_IWUSR,
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR,
+ show_enable, store_enable, 2);
+static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR,
show_pwm, store_pwm, 3);
-static SENSOR_DEVICE_ATTR(fan4_mode, S_IRUGO | S_IWUSR,
- show_mode, store_mode, 3);
+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IRUGO | S_IWUSR,
+ show_enable, store_enable, 3);
static struct attribute *nct7904_fanctl_attrs[] = {
- &sensor_dev_attr_fan1_pwm.dev_attr.attr,
- &sensor_dev_attr_fan1_mode.dev_attr.attr,
- &sensor_dev_attr_fan2_pwm.dev_attr.attr,
- &sensor_dev_attr_fan2_mode.dev_attr.attr,
- &sensor_dev_attr_fan3_pwm.dev_attr.attr,
- &sensor_dev_attr_fan3_mode.dev_attr.attr,
- &sensor_dev_attr_fan4_pwm.dev_attr.attr,
- &sensor_dev_attr_fan4_mode.dev_attr.attr,
+ &sensor_dev_attr_pwm1.dev_attr.attr,
+ &sensor_dev_attr_pwm1_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm2.dev_attr.attr,
+ &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm3.dev_attr.attr,
+ &sensor_dev_attr_pwm3_enable.dev_attr.attr,
+ &sensor_dev_attr_pwm4.dev_attr.attr,
+ &sensor_dev_attr_pwm4_enable.dev_attr.attr,
NULL
};
@@ -574,6 +575,7 @@
{"nct7904", 0},
{}
};
+MODULE_DEVICE_TABLE(i2c, nct7904_id);
static struct i2c_driver nct7904_driver = {
.class = I2C_CLASS_HWMON,
diff --git a/drivers/hwtracing/coresight/coresight-etm.h b/drivers/hwtracing/coresight/coresight-etm.h
index 098ffbe..b4481eb 100644
--- a/drivers/hwtracing/coresight/coresight-etm.h
+++ b/drivers/hwtracing/coresight/coresight-etm.h
@@ -183,7 +183,9 @@
* @seq_13_event: event causing the transition from 1 to 3.
* @seq_curr_state: current value of the sequencer register.
* @ctxid_idx: index for the context ID registers.
- * @ctxid_val: value for the context ID to trigger on.
+ * @ctxid_pid: value for the context ID to trigger on.
+ * @ctxid_vpid: Virtual PID seen by users if PID namespace is enabled, otherwise
+ * the same value of ctxid_pid.
* @ctxid_mask: mask applicable to all the context IDs.
* @sync_freq: Synchronisation frequency.
* @timestamp_event: Defines an event that requests the insertion
@@ -235,7 +237,8 @@
u32 seq_13_event;
u32 seq_curr_state;
u8 ctxid_idx;
- u32 ctxid_val[ETM_MAX_CTXID_CMP];
+ u32 ctxid_pid[ETM_MAX_CTXID_CMP];
+ u32 ctxid_vpid[ETM_MAX_CTXID_CMP];
u32 ctxid_mask;
u32 sync_freq;
u32 timestamp_event;
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c
index 018a00f..bf2476e 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x.c
@@ -237,8 +237,11 @@
drvdata->seq_curr_state = 0x0;
drvdata->ctxid_idx = 0x0;
- for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
- drvdata->ctxid_val[i] = 0x0;
+ for (i = 0; i < drvdata->nr_ctxid_cmp; i++) {
+ drvdata->ctxid_pid[i] = 0x0;
+ drvdata->ctxid_vpid[i] = 0x0;
+ }
+
drvdata->ctxid_mask = 0x0;
}
@@ -289,7 +292,7 @@
for (i = 0; i < drvdata->nr_ext_out; i++)
etm_writel(drvdata, ETM_DEFAULT_EVENT_VAL, ETMEXTOUTEVRn(i));
for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
- etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
+ etm_writel(drvdata, drvdata->ctxid_pid[i], ETMCIDCVRn(i));
etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
/* No external input selected */
@@ -1386,38 +1389,41 @@
}
static DEVICE_ATTR_RW(ctxid_idx);
-static ssize_t ctxid_val_show(struct device *dev,
+static ssize_t ctxid_pid_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
unsigned long val;
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
spin_lock(&drvdata->spinlock);
- val = drvdata->ctxid_val[drvdata->ctxid_idx];
+ val = drvdata->ctxid_vpid[drvdata->ctxid_idx];
spin_unlock(&drvdata->spinlock);
return sprintf(buf, "%#lx\n", val);
}
-static ssize_t ctxid_val_store(struct device *dev,
+static ssize_t ctxid_pid_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
int ret;
- unsigned long val;
+ unsigned long vpid, pid;
struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
- ret = kstrtoul(buf, 16, &val);
+ ret = kstrtoul(buf, 16, &vpid);
if (ret)
return ret;
+ pid = coresight_vpid_to_pid(vpid);
+
spin_lock(&drvdata->spinlock);
- drvdata->ctxid_val[drvdata->ctxid_idx] = val;
+ drvdata->ctxid_pid[drvdata->ctxid_idx] = pid;
+ drvdata->ctxid_vpid[drvdata->ctxid_idx] = vpid;
spin_unlock(&drvdata->spinlock);
return size;
}
-static DEVICE_ATTR_RW(ctxid_val);
+static DEVICE_ATTR_RW(ctxid_pid);
static ssize_t ctxid_mask_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -1609,7 +1615,7 @@
&dev_attr_seq_13_event.attr,
&dev_attr_seq_curr_state.attr,
&dev_attr_ctxid_idx.attr,
- &dev_attr_ctxid_val.attr,
+ &dev_attr_ctxid_pid.attr,
&dev_attr_ctxid_mask.attr,
&dev_attr_sync_freq.attr,
&dev_attr_timestamp_event.attr,
@@ -1912,6 +1918,11 @@
.mask = 0x0003ffff,
.data = "PTM 1.1",
},
+ { /* PTM 1.1 Qualcomm */
+ .id = 0x0003006f,
+ .mask = 0x0003ffff,
+ .data = "PTM 1.1",
+ },
{ 0, 0},
};
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 1312e99..254a81a 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -155,7 +155,7 @@
drvdata->base + TRCACATRn(i));
}
for (i = 0; i < drvdata->numcidc; i++)
- writeq_relaxed(drvdata->ctxid_val[i],
+ writeq_relaxed(drvdata->ctxid_pid[i],
drvdata->base + TRCCIDCVRn(i));
writel_relaxed(drvdata->ctxid_mask0, drvdata->base + TRCCIDCCTLR0);
writel_relaxed(drvdata->ctxid_mask1, drvdata->base + TRCCIDCCTLR1);
@@ -506,8 +506,11 @@
}
drvdata->ctxid_idx = 0x0;
- for (i = 0; i < drvdata->numcidc; i++)
- drvdata->ctxid_val[i] = 0x0;
+ for (i = 0; i < drvdata->numcidc; i++) {
+ drvdata->ctxid_pid[i] = 0x0;
+ drvdata->ctxid_vpid[i] = 0x0;
+ }
+
drvdata->ctxid_mask0 = 0x0;
drvdata->ctxid_mask1 = 0x0;
@@ -1815,7 +1818,7 @@
}
static DEVICE_ATTR_RW(ctxid_idx);
-static ssize_t ctxid_val_show(struct device *dev,
+static ssize_t ctxid_pid_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
@@ -1825,17 +1828,17 @@
spin_lock(&drvdata->spinlock);
idx = drvdata->ctxid_idx;
- val = (unsigned long)drvdata->ctxid_val[idx];
+ val = (unsigned long)drvdata->ctxid_vpid[idx];
spin_unlock(&drvdata->spinlock);
return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
}
-static ssize_t ctxid_val_store(struct device *dev,
+static ssize_t ctxid_pid_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
u8 idx;
- unsigned long val;
+ unsigned long vpid, pid;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
/*
@@ -1845,16 +1848,19 @@
*/
if (!drvdata->ctxid_size || !drvdata->numcidc)
return -EINVAL;
- if (kstrtoul(buf, 16, &val))
+ if (kstrtoul(buf, 16, &vpid))
return -EINVAL;
+ pid = coresight_vpid_to_pid(vpid);
+
spin_lock(&drvdata->spinlock);
idx = drvdata->ctxid_idx;
- drvdata->ctxid_val[idx] = (u64)val;
+ drvdata->ctxid_pid[idx] = (u64)pid;
+ drvdata->ctxid_vpid[idx] = (u64)vpid;
spin_unlock(&drvdata->spinlock);
return size;
}
-static DEVICE_ATTR_RW(ctxid_val);
+static DEVICE_ATTR_RW(ctxid_pid);
static ssize_t ctxid_masks_show(struct device *dev,
struct device_attribute *attr,
@@ -1949,7 +1955,7 @@
*/
for (j = 0; j < 8; j++) {
if (maskbyte & 1)
- drvdata->ctxid_val[i] &= ~(0xFF << (j * 8));
+ drvdata->ctxid_pid[i] &= ~(0xFF << (j * 8));
maskbyte >>= 1;
}
/* Select the next ctxid comparator mask value */
@@ -2193,7 +2199,7 @@
&dev_attr_res_idx.attr,
&dev_attr_res_ctrl.attr,
&dev_attr_ctxid_idx.attr,
- &dev_attr_ctxid_val.attr,
+ &dev_attr_ctxid_pid.attr,
&dev_attr_ctxid_masks.attr,
&dev_attr_vmid_idx.attr,
&dev_attr_vmid_val.attr,
@@ -2513,8 +2519,11 @@
drvdata->addr_type[1] = ETM_ADDR_TYPE_RANGE;
}
- for (i = 0; i < drvdata->numcidc; i++)
- drvdata->ctxid_val[i] = 0x0;
+ for (i = 0; i < drvdata->numcidc; i++) {
+ drvdata->ctxid_pid[i] = 0x0;
+ drvdata->ctxid_vpid[i] = 0x0;
+ }
+
drvdata->ctxid_mask0 = 0x0;
drvdata->ctxid_mask1 = 0x0;
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index e08e983..c341002 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -265,7 +265,9 @@
* @addr_type: Current status of the comparator register.
* @ctxid_idx: Context ID index selector.
* @ctxid_size: Size of the context ID field to consider.
- * @ctxid_val: Value of the context ID comparator.
+ * @ctxid_pid: Value of the context ID comparator.
+ * @ctxid_vpid: Virtual PID seen by users if PID namespace is enabled, otherwise
+ * the same value of ctxid_pid.
* @ctxid_mask0:Context ID comparator mask for comparator 0-3.
* @ctxid_mask1:Context ID comparator mask for comparator 4-7.
* @vmid_idx: VM ID index selector.
@@ -352,7 +354,8 @@
u8 addr_type[ETM_MAX_SINGLE_ADDR_CMP];
u8 ctxid_idx;
u8 ctxid_size;
- u64 ctxid_val[ETMv4_MAX_CTXID_CMP];
+ u64 ctxid_pid[ETMv4_MAX_CTXID_CMP];
+ u64 ctxid_vpid[ETMv4_MAX_CTXID_CMP];
u32 ctxid_mask0;
u32 ctxid_mask1;
u8 vmid_idx;
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index 7974b7c..963ac19 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -12,7 +12,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/io.h>
@@ -184,17 +183,7 @@
},
};
-static int __init replicator_init(void)
-{
- return platform_driver_register(&replicator_driver);
-}
-module_init(replicator_init);
-
-static void __exit replicator_exit(void)
-{
- platform_driver_unregister(&replicator_driver);
-}
-module_exit(replicator_exit);
+builtin_platform_driver(replicator_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("CoreSight Replicator driver");
diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c
index af162b4..025686d 100644
--- a/drivers/i2c/busses/i2c-bfin-twi.c
+++ b/drivers/i2c/busses/i2c-bfin-twi.c
@@ -692,7 +692,7 @@
platform_set_drvdata(pdev, iface);
- dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Contoller, "
+ dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Controller, "
"regs_base@%p\n", iface->regs_base);
return 0;
@@ -735,6 +735,6 @@
module_exit(i2c_bfin_twi_exit);
MODULE_AUTHOR("Bryan Wu, Sonic Zhang");
-MODULE_DESCRIPTION("Blackfin BF5xx on-chip I2C TWI Contoller Driver");
+MODULE_DESCRIPTION("Blackfin BF5xx on-chip I2C TWI Controller Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:i2c-bfin-twi");
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index d1c22e3..fc9bf7f 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1247,7 +1247,14 @@
u32 reg;
reg = omap_i2c_read_reg(dev, OMAP_I2C_SYSTEST_REG);
+ /* enable test mode */
reg |= OMAP_I2C_SYSTEST_ST_EN;
+ /* select SDA/SCL IO mode */
+ reg |= 3 << OMAP_I2C_SYSTEST_TMODE_SHIFT;
+ /* set SCL to high-impedance state (reset value is 0) */
+ reg |= OMAP_I2C_SYSTEST_SCL_O;
+ /* set SDA to high-impedance state (reset value is 0) */
+ reg |= OMAP_I2C_SYSTEST_SDA_O;
omap_i2c_write_reg(dev, OMAP_I2C_SYSTEST_REG, reg);
}
@@ -1257,7 +1264,11 @@
u32 reg;
reg = omap_i2c_read_reg(dev, OMAP_I2C_SYSTEST_REG);
+ /* restore reset values */
reg &= ~OMAP_I2C_SYSTEST_ST_EN;
+ reg &= ~OMAP_I2C_SYSTEST_TMODE_MASK;
+ reg &= ~OMAP_I2C_SYSTEST_SCL_O;
+ reg &= ~OMAP_I2C_SYSTEST_SDA_O;
omap_i2c_write_reg(dev, OMAP_I2C_SYSTEST_REG, reg);
}
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index e6d4935..c83e4d1 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -567,6 +567,9 @@
if (bri->prepare_recovery)
bri->prepare_recovery(adap);
+ bri->set_scl(adap, val);
+ ndelay(RECOVERY_NDELAY);
+
/*
* By this time SCL is high, as we need to give 9 falling-rising edges
*/
@@ -597,7 +600,6 @@
int i2c_generic_scl_recovery(struct i2c_adapter *adap)
{
- adap->bus_recovery_info->set_scl(adap, 1);
return i2c_generic_recovery(adap);
}
EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery);
@@ -1338,13 +1340,17 @@
struct i2c_client *of_find_i2c_device_by_node(struct device_node *node)
{
struct device *dev;
+ struct i2c_client *client;
- dev = bus_find_device(&i2c_bus_type, NULL, node,
- of_dev_node_match);
+ dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match);
if (!dev)
return NULL;
- return i2c_verify_client(dev);
+ client = i2c_verify_client(dev);
+ if (!client)
+ put_device(dev);
+
+ return client;
}
EXPORT_SYMBOL(of_find_i2c_device_by_node);
@@ -1352,13 +1358,17 @@
struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
{
struct device *dev;
+ struct i2c_adapter *adapter;
- dev = bus_find_device(&i2c_bus_type, NULL, node,
- of_dev_node_match);
+ dev = bus_find_device(&i2c_bus_type, NULL, node, of_dev_node_match);
if (!dev)
return NULL;
- return i2c_verify_adapter(dev);
+ adapter = i2c_verify_adapter(dev);
+ if (!adapter)
+ put_device(dev);
+
+ return adapter;
}
EXPORT_SYMBOL(of_find_i2c_adapter_by_node);
#else
diff --git a/drivers/i2c/i2c-slave-eeprom.c b/drivers/i2c/i2c-slave-eeprom.c
index 8223746..1da4496 100644
--- a/drivers/i2c/i2c-slave-eeprom.c
+++ b/drivers/i2c/i2c-slave-eeprom.c
@@ -80,9 +80,6 @@
struct eeprom_data *eeprom;
unsigned long flags;
- if (off + count > attr->size)
- return -EFBIG;
-
eeprom = dev_get_drvdata(container_of(kobj, struct device, kobj));
spin_lock_irqsave(&eeprom->buffer_lock, flags);
@@ -98,9 +95,6 @@
struct eeprom_data *eeprom;
unsigned long flags;
- if (off + count > attr->size)
- return -EFBIG;
-
eeprom = dev_get_drvdata(container_of(kobj, struct device, kobj));
spin_lock_irqsave(&eeprom->buffer_lock, flags);
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index 00e7bcb..a59047d 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -86,18 +86,6 @@
To compile this driver as a module, choose M here: the module
will be called kxsd9.
-config MMA8452
- tristate "Freescale MMA8452Q Accelerometer Driver"
- depends on I2C
- select IIO_BUFFER
- select IIO_TRIGGERED_BUFFER
- help
- Say yes here to build support for the Freescale MMA8452Q 3-axis
- accelerometer.
-
- To compile this driver as a module, choose M here: the module
- will be called mma8452.
-
config KXCJK1013
tristate "Kionix 3-Axis Accelerometer Driver"
depends on I2C
@@ -111,6 +99,18 @@
To compile this driver as a module, choose M here: the module will
be called kxcjk-1013.
+config MMA8452
+ tristate "Freescale MMA8452Q Accelerometer Driver"
+ depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for the Freescale MMA8452Q 3-axis
+ accelerometer.
+
+ To compile this driver as a module, choose M here: the module
+ will be called mma8452.
+
config MMA9551_CORE
tristate
@@ -140,6 +140,8 @@
config STK8312
tristate "Sensortek STK8312 3-Axis Accelerometer Driver"
depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
Say yes here to get support for the Sensortek STK8312 3-axis
accelerometer.
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index 75c6d21..f04b884 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -846,7 +846,6 @@
static struct i2c_driver bma180_driver = {
.driver = {
.name = "bma180",
- .owner = THIS_MODULE,
.pm = BMA180_PM_OPS,
},
.probe = bma180_probe,
diff --git a/drivers/iio/accel/bmc150-accel.c b/drivers/iio/accel/bmc150-accel.c
index cc5a357..0104cde 100644
--- a/drivers/iio/accel/bmc150-accel.c
+++ b/drivers/iio/accel/bmc150-accel.c
@@ -151,6 +151,7 @@
};
struct bmc150_accel_chip_info {
+ const char *name;
u8 chip_id;
const struct iio_chan_spec *channels;
int num_channels;
@@ -241,7 +242,6 @@
{500000, BMC150_ACCEL_SLEEP_500_MS},
{1000000, BMC150_ACCEL_SLEEP_1_SEC} };
-
static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
enum bmc150_power_modes mode,
int dur_us)
@@ -259,8 +259,9 @@
dur_val =
bmc150_accel_sleep_value_table[i].reg_value;
}
- } else
+ } else {
dur_val = 0;
+ }
if (dur_val < 0)
return -EINVAL;
@@ -288,7 +289,7 @@
for (i = 0; i < ARRAY_SIZE(bmc150_accel_samp_freq_table); ++i) {
if (bmc150_accel_samp_freq_table[i].val == val &&
- bmc150_accel_samp_freq_table[i].val2 == val2) {
+ bmc150_accel_samp_freq_table[i].val2 == val2) {
ret = i2c_smbus_write_byte_data(
data->client,
BMC150_ACCEL_REG_PMU_BW,
@@ -345,65 +346,6 @@
return 0;
}
-static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
-{
- int ret;
-
- ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "Error: Reading chip id\n");
- return ret;
- }
-
- dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
- if (ret != data->chip_info->chip_id) {
- dev_err(&data->client->dev, "Invalid chip %x\n", ret);
- return -ENODEV;
- }
-
- ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
- if (ret < 0)
- return ret;
-
- /* Set Bandwidth */
- ret = bmc150_accel_set_bw(data, BMC150_ACCEL_DEF_BW, 0);
- if (ret < 0)
- return ret;
-
- /* Set Default Range */
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_PMU_RANGE,
- BMC150_ACCEL_DEF_RANGE_4G);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "Error writing reg_pmu_range\n");
- return ret;
- }
-
- data->range = BMC150_ACCEL_DEF_RANGE_4G;
-
- /* Set default slope duration and thresholds */
- data->slope_thres = BMC150_ACCEL_DEF_SLOPE_THRESHOLD;
- data->slope_dur = BMC150_ACCEL_DEF_SLOPE_DURATION;
- ret = bmc150_accel_update_slope(data);
- if (ret < 0)
- return ret;
-
- /* Set default as latched interrupts */
- ret = i2c_smbus_write_byte_data(data->client,
- BMC150_ACCEL_REG_INT_RST_LATCH,
- BMC150_ACCEL_INT_MODE_LATCH_INT |
- BMC150_ACCEL_INT_MODE_LATCH_RESET);
- if (ret < 0) {
- dev_err(&data->client->dev,
- "Error writing reg_int_rst_latch\n");
- return ret;
- }
-
- return 0;
-}
-
static int bmc150_accel_get_bw(struct bmc150_accel_data *data, int *val,
int *val2)
{
@@ -437,12 +379,13 @@
{
int ret;
- if (on)
+ if (on) {
ret = pm_runtime_get_sync(&data->client->dev);
- else {
+ } else {
pm_runtime_mark_last_busy(&data->client->dev);
ret = pm_runtime_put_autosuspend(&data->client->dev);
}
+
if (ret < 0) {
dev_err(&data->client->dev,
"Failed: bmc150_accel_set_power_state for %d\n", on);
@@ -514,13 +457,13 @@
}
/*
- * We will expect the enable and disable to do operation in
- * in reverse order. This will happen here anyway as our
- * resume operation uses sync mode runtime pm calls, the
- * suspend operation will be delayed by autosuspend delay
- * So the disable operation will still happen in reverse of
- * enable operation. When runtime pm is disabled the mode
- * is always on so sequence doesn't matter
+ * We will expect the enable and disable to do operation in reverse
+ * order. This will happen here anyway, as our resume operation uses
+ * sync mode runtime pm calls. The suspend operation will be delayed
+ * by autosuspend delay.
+ * So the disable operation will still happen in reverse order of
+ * enable operation. When runtime pm is disabled the mode is always on,
+ * so sequence doesn't matter.
*/
ret = bmc150_accel_set_power_state(data, state);
if (ret < 0)
@@ -574,7 +517,6 @@
return ret;
}
-
static int bmc150_accel_set_scale(struct bmc150_accel_data *data, int val)
{
int ret, i;
@@ -674,8 +616,9 @@
if (chan->type == IIO_TEMP) {
*val = BMC150_ACCEL_TEMP_CENTER_VAL;
return IIO_VAL_INT;
- } else
+ } else {
return -EINVAL;
+ }
case IIO_CHAN_INFO_SCALE:
*val = 0;
switch (chan->type) {
@@ -776,7 +719,7 @@
switch (info) {
case IIO_EV_INFO_VALUE:
- data->slope_thres = val & 0xFF;
+ data->slope_thres = val & BMC150_ACCEL_SLOPE_THRES_MASK;
break;
case IIO_EV_INFO_PERIOD:
data->slope_dur = val & BMC150_ACCEL_SLOPE_DUR_MASK;
@@ -793,7 +736,6 @@
enum iio_event_type type,
enum iio_event_direction dir)
{
-
struct bmc150_accel_data *data = iio_priv(indio_dev);
return data->ev_enable_state;
@@ -827,7 +769,7 @@
}
static int bmc150_accel_validate_trigger(struct iio_dev *indio_dev,
- struct iio_trigger *trig)
+ struct iio_trigger *trig)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
int i;
@@ -963,6 +905,7 @@
u16 buffer[BMC150_ACCEL_FIFO_LENGTH * 3];
int64_t tstamp;
uint64_t sample_period;
+
ret = i2c_smbus_read_byte_data(data->client,
BMC150_ACCEL_REG_FIFO_STATUS);
if (ret < 0) {
@@ -1120,6 +1063,7 @@
static const struct bmc150_accel_chip_info bmc150_accel_chip_info_tbl[] = {
[bmc150] = {
+ .name = "BMC150A",
.chip_id = 0xFA,
.channels = bmc150_accel_channels,
.num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1129,6 +1073,7 @@
{76590, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bmi055] = {
+ .name = "BMI055A",
.chip_id = 0xFA,
.channels = bmc150_accel_channels,
.num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1138,6 +1083,7 @@
{76590, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bma255] = {
+ .name = "BMA0255",
.chip_id = 0xFA,
.channels = bmc150_accel_channels,
.num_channels = ARRAY_SIZE(bmc150_accel_channels),
@@ -1147,6 +1093,7 @@
{76590, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bma250e] = {
+ .name = "BMA250E",
.chip_id = 0xF9,
.channels = bma250e_accel_channels,
.num_channels = ARRAY_SIZE(bma250e_accel_channels),
@@ -1156,6 +1103,7 @@
{306457, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bma222e] = {
+ .name = "BMA222E",
.chip_id = 0xF8,
.channels = bma222e_accel_channels,
.num_channels = ARRAY_SIZE(bma222e_accel_channels),
@@ -1165,6 +1113,7 @@
{1225831, BMC150_ACCEL_DEF_RANGE_16G} },
},
[bma280] = {
+ .name = "BMA0280",
.chip_id = 0xFB,
.channels = bma280_accel_channels,
.num_channels = ARRAY_SIZE(bma280_accel_channels),
@@ -1255,7 +1204,7 @@
}
static int bmc150_accel_trigger_set_state(struct iio_trigger *trig,
- bool state)
+ bool state)
{
struct bmc150_accel_trigger *t = iio_trigger_get_drvdata(trig);
struct bmc150_accel_data *data = t->data;
@@ -1314,26 +1263,32 @@
dir = IIO_EV_DIR_RISING;
if (ret & BMC150_ACCEL_ANY_MOTION_BIT_X)
- iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
- 0,
- IIO_MOD_X,
- IIO_EV_TYPE_ROC,
- dir),
- data->timestamp);
+ iio_push_event(indio_dev,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
+ 0,
+ IIO_MOD_X,
+ IIO_EV_TYPE_ROC,
+ dir),
+ data->timestamp);
+
if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Y)
- iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
- 0,
- IIO_MOD_Y,
- IIO_EV_TYPE_ROC,
- dir),
- data->timestamp);
+ iio_push_event(indio_dev,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
+ 0,
+ IIO_MOD_Y,
+ IIO_EV_TYPE_ROC,
+ dir),
+ data->timestamp);
+
if (ret & BMC150_ACCEL_ANY_MOTION_BIT_Z)
- iio_push_event(indio_dev, IIO_MOD_EVENT_CODE(IIO_ACCEL,
- 0,
- IIO_MOD_Z,
- IIO_EV_TYPE_ROC,
- dir),
- data->timestamp);
+ iio_push_event(indio_dev,
+ IIO_MOD_EVENT_CODE(IIO_ACCEL,
+ 0,
+ IIO_MOD_Z,
+ IIO_EV_TYPE_ROC,
+ dir),
+ data->timestamp);
+
return ret;
}
@@ -1365,7 +1320,9 @@
BMC150_ACCEL_INT_MODE_LATCH_INT |
BMC150_ACCEL_INT_MODE_LATCH_RESET);
if (ret)
- dev_err(&data->client->dev, "Error writing reg_int_rst_latch\n");
+ dev_err(&data->client->dev,
+ "Error writing reg_int_rst_latch\n");
+
ret = IRQ_HANDLED;
} else {
ret = IRQ_NONE;
@@ -1403,22 +1360,8 @@
return IRQ_NONE;
}
-static const char *bmc150_accel_match_acpi_device(struct device *dev, int *data)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
-
- if (!id)
- return NULL;
-
- *data = (int) id->driver_data;
-
- return dev_name(dev);
-}
-
static int bmc150_accel_gpio_probe(struct i2c_client *client,
- struct bmc150_accel_data *data)
+ struct bmc150_accel_data *data)
{
struct device *dev;
struct gpio_desc *gpio;
@@ -1611,6 +1554,70 @@
.postdisable = bmc150_accel_buffer_postdisable,
};
+static int bmc150_accel_chip_init(struct bmc150_accel_data *data)
+{
+ int ret, i;
+
+ ret = i2c_smbus_read_byte_data(data->client, BMC150_ACCEL_REG_CHIP_ID);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error: Reading chip id\n");
+ return ret;
+ }
+
+ dev_dbg(&data->client->dev, "Chip Id %x\n", ret);
+ for (i = 0; i < ARRAY_SIZE(bmc150_accel_chip_info_tbl); i++) {
+ if (bmc150_accel_chip_info_tbl[i].chip_id == ret) {
+ data->chip_info = &bmc150_accel_chip_info_tbl[i];
+ break;
+ }
+ }
+
+ if (!data->chip_info) {
+ dev_err(&data->client->dev, "Unsupported chip %x\n", ret);
+ return -ENODEV;
+ }
+
+ ret = bmc150_accel_set_mode(data, BMC150_ACCEL_SLEEP_MODE_NORMAL, 0);
+ if (ret < 0)
+ return ret;
+
+ /* Set Bandwidth */
+ ret = bmc150_accel_set_bw(data, BMC150_ACCEL_DEF_BW, 0);
+ if (ret < 0)
+ return ret;
+
+ /* Set Default Range */
+ ret = i2c_smbus_write_byte_data(data->client,
+ BMC150_ACCEL_REG_PMU_RANGE,
+ BMC150_ACCEL_DEF_RANGE_4G);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Error writing reg_pmu_range\n");
+ return ret;
+ }
+
+ data->range = BMC150_ACCEL_DEF_RANGE_4G;
+
+ /* Set default slope duration and thresholds */
+ data->slope_thres = BMC150_ACCEL_DEF_SLOPE_THRESHOLD;
+ data->slope_dur = BMC150_ACCEL_DEF_SLOPE_DURATION;
+ ret = bmc150_accel_update_slope(data);
+ if (ret < 0)
+ return ret;
+
+ /* Set default as latched interrupts */
+ ret = i2c_smbus_write_byte_data(data->client,
+ BMC150_ACCEL_REG_INT_RST_LATCH,
+ BMC150_ACCEL_INT_MODE_LATCH_INT |
+ BMC150_ACCEL_INT_MODE_LATCH_RESET);
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "Error writing reg_int_rst_latch\n");
+ return ret;
+ }
+
+ return 0;
+}
+
static int bmc150_accel_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -1618,7 +1625,6 @@
struct iio_dev *indio_dev;
int ret;
const char *name = NULL;
- int chip_id = 0;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -1628,15 +1634,8 @@
i2c_set_clientdata(client, indio_dev);
data->client = client;
- if (id) {
+ if (id)
name = id->name;
- chip_id = id->driver_data;
- }
-
- if (ACPI_HANDLE(&client->dev))
- name = bmc150_accel_match_acpi_device(&client->dev, &chip_id);
-
- data->chip_info = &bmc150_accel_chip_info_tbl[chip_id];
ret = bmc150_accel_chip_init(data);
if (ret < 0)
@@ -1647,7 +1646,7 @@
indio_dev->dev.parent = &client->dev;
indio_dev->channels = data->chip_info->channels;
indio_dev->num_channels = data->chip_info->num_channels;
- indio_dev->name = name;
+ indio_dev->name = name ? name : data->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &bmc150_accel_info;
@@ -1663,7 +1662,7 @@
if (client->irq < 0)
client->irq = bmc150_accel_gpio_probe(client, data);
- if (client->irq >= 0) {
+ if (client->irq > 0) {
ret = devm_request_threaded_irq(
&client->dev, client->irq,
bmc150_accel_irq_handler,
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index 0d9bd35..3292bc0 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -658,10 +658,8 @@
int ret, i;
enum kxcjk1013_mode store_mode;
-
for (i = 0; i < ARRAY_SIZE(KXCJK1013_scale_table); ++i) {
if (KXCJK1013_scale_table[i].scale == val) {
-
ret = kxcjk1013_get_mode(data, &store_mode);
if (ret < 0)
return ret;
@@ -820,7 +818,6 @@
enum iio_event_type type,
enum iio_event_direction dir)
{
-
struct kxcjk1013_data *data = iio_priv(indio_dev);
return data->ev_enable_state;
@@ -1243,7 +1240,7 @@
if (client->irq < 0)
client->irq = kxcjk1013_gpio_probe(client, data);
- if (client->irq >= 0) {
+ if (client->irq > 0) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
kxcjk1013_data_rdy_trig_poll,
kxcjk1013_event_handler,
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index e8e2077..b921d84 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -16,7 +16,6 @@
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-#include <linux/iio/trigger_consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
@@ -24,54 +23,51 @@
#include <linux/iio/events.h>
#include <linux/delay.h>
-#define MMA8452_STATUS 0x00
-#define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */
-#define MMA8452_OUT_Y 0x03
-#define MMA8452_OUT_Z 0x05
-#define MMA8452_INT_SRC 0x0c
-#define MMA8452_WHO_AM_I 0x0d
-#define MMA8452_DATA_CFG 0x0e
-#define MMA8452_HP_FILTER_CUTOFF 0x0f
-#define MMA8452_HP_FILTER_CUTOFF_SEL_MASK (BIT(0) | BIT(1))
-#define MMA8452_TRANSIENT_CFG 0x1d
-#define MMA8452_TRANSIENT_CFG_ELE BIT(4)
-#define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1)
-#define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0)
-#define MMA8452_TRANSIENT_SRC 0x1e
-#define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1)
-#define MMA8452_TRANSIENT_SRC_YTRANSE BIT(3)
-#define MMA8452_TRANSIENT_SRC_ZTRANSE BIT(5)
-#define MMA8452_TRANSIENT_THS 0x1f
-#define MMA8452_TRANSIENT_THS_MASK 0x7f
-#define MMA8452_TRANSIENT_COUNT 0x20
-#define MMA8452_OFF_X 0x2f
-#define MMA8452_OFF_Y 0x30
-#define MMA8452_OFF_Z 0x31
-#define MMA8452_CTRL_REG1 0x2a
-#define MMA8452_CTRL_REG2 0x2b
-#define MMA8452_CTRL_REG2_RST BIT(6)
-#define MMA8452_CTRL_REG4 0x2d
-#define MMA8452_CTRL_REG5 0x2e
+#define MMA8452_STATUS 0x00
+#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
+#define MMA8452_OUT_X 0x01 /* MSB first, 12-bit */
+#define MMA8452_OUT_Y 0x03
+#define MMA8452_OUT_Z 0x05
+#define MMA8452_INT_SRC 0x0c
+#define MMA8452_WHO_AM_I 0x0d
+#define MMA8452_DATA_CFG 0x0e
+#define MMA8452_DATA_CFG_FS_MASK GENMASK(1, 0)
+#define MMA8452_DATA_CFG_FS_2G 0
+#define MMA8452_DATA_CFG_FS_4G 1
+#define MMA8452_DATA_CFG_FS_8G 2
+#define MMA8452_DATA_CFG_HPF_MASK BIT(4)
+#define MMA8452_HP_FILTER_CUTOFF 0x0f
+#define MMA8452_HP_FILTER_CUTOFF_SEL_MASK GENMASK(1, 0)
+#define MMA8452_TRANSIENT_CFG 0x1d
+#define MMA8452_TRANSIENT_CFG_HPF_BYP BIT(0)
+#define MMA8452_TRANSIENT_CFG_CHAN(chan) BIT(chan + 1)
+#define MMA8452_TRANSIENT_CFG_ELE BIT(4)
+#define MMA8452_TRANSIENT_SRC 0x1e
+#define MMA8452_TRANSIENT_SRC_XTRANSE BIT(1)
+#define MMA8452_TRANSIENT_SRC_YTRANSE BIT(3)
+#define MMA8452_TRANSIENT_SRC_ZTRANSE BIT(5)
+#define MMA8452_TRANSIENT_THS 0x1f
+#define MMA8452_TRANSIENT_THS_MASK GENMASK(6, 0)
+#define MMA8452_TRANSIENT_COUNT 0x20
+#define MMA8452_CTRL_REG1 0x2a
+#define MMA8452_CTRL_ACTIVE BIT(0)
+#define MMA8452_CTRL_DR_MASK GENMASK(5, 3)
+#define MMA8452_CTRL_DR_SHIFT 3
+#define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */
+#define MMA8452_CTRL_REG2 0x2b
+#define MMA8452_CTRL_REG2_RST BIT(6)
+#define MMA8452_CTRL_REG4 0x2d
+#define MMA8452_CTRL_REG5 0x2e
+#define MMA8452_OFF_X 0x2f
+#define MMA8452_OFF_Y 0x30
+#define MMA8452_OFF_Z 0x31
-#define MMA8452_MAX_REG 0x31
+#define MMA8452_MAX_REG 0x31
-#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
+#define MMA8452_INT_DRDY BIT(0)
+#define MMA8452_INT_TRANS BIT(5)
-#define MMA8452_CTRL_DR_MASK (BIT(5) | BIT(4) | BIT(3))
-#define MMA8452_CTRL_DR_SHIFT 3
-#define MMA8452_CTRL_DR_DEFAULT 0x4 /* 50 Hz sample frequency */
-#define MMA8452_CTRL_ACTIVE BIT(0)
-
-#define MMA8452_DATA_CFG_FS_MASK (BIT(1) | BIT(0))
-#define MMA8452_DATA_CFG_FS_2G 0
-#define MMA8452_DATA_CFG_FS_4G 1
-#define MMA8452_DATA_CFG_FS_8G 2
-#define MMA8452_DATA_CFG_HPF_MASK BIT(4)
-
-#define MMA8452_INT_DRDY BIT(0)
-#define MMA8452_INT_TRANS BIT(5)
-
-#define MMA8452_DEVICE_ID 0x2a
+#define MMA8452_DEVICE_ID 0x2a
struct mma8452_data {
struct i2c_client *client;
@@ -91,30 +87,34 @@
return ret;
if ((ret & MMA8452_STATUS_DRDY) == MMA8452_STATUS_DRDY)
return 0;
+
msleep(20);
}
dev_err(&data->client->dev, "data not ready\n");
+
return -EIO;
}
static int mma8452_read(struct mma8452_data *data, __be16 buf[3])
{
int ret = mma8452_drdy(data);
+
if (ret < 0)
return ret;
- return i2c_smbus_read_i2c_block_data(data->client,
- MMA8452_OUT_X, 3 * sizeof(__be16), (u8 *) buf);
+
+ return i2c_smbus_read_i2c_block_data(data->client, MMA8452_OUT_X,
+ 3 * sizeof(__be16), (u8 *)buf);
}
-static ssize_t mma8452_show_int_plus_micros(char *buf,
- const int (*vals)[2], int n)
+static ssize_t mma8452_show_int_plus_micros(char *buf, const int (*vals)[2],
+ int n)
{
size_t len = 0;
while (n-- > 0)
- len += scnprintf(buf + len, PAGE_SIZE - len,
- "%d.%06d ", vals[n][0], vals[n][1]);
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%d.%06d ",
+ vals[n][0], vals[n][1]);
/* replace trailing space by newline */
buf[len - 1] = '\n';
@@ -123,7 +123,7 @@
}
static int mma8452_get_int_plus_micros_index(const int (*vals)[2], int n,
- int val, int val2)
+ int val, int val2)
{
while (n-- > 0)
if (val == vals[n][0] && val2 == vals[n][1])
@@ -147,7 +147,7 @@
* Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
* The userspace interface uses m/s^2 and we declare micro units
* So scale factor is given by:
- * 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
*/
static const int mma8452_scales[3][2] = {
{0, 9577}, {0, 19154}, {0, 38307}
@@ -178,17 +178,19 @@
};
static ssize_t mma8452_show_samp_freq_avail(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
return mma8452_show_int_plus_micros(buf, mma8452_samp_freq,
- ARRAY_SIZE(mma8452_samp_freq));
+ ARRAY_SIZE(mma8452_samp_freq));
}
static ssize_t mma8452_show_scale_avail(struct device *dev,
- struct device_attribute *attr, char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
return mma8452_show_int_plus_micros(buf, mma8452_scales,
- ARRAY_SIZE(mma8452_scales));
+ ARRAY_SIZE(mma8452_scales));
}
static ssize_t mma8452_show_hp_cutoff_avail(struct device *dev,
@@ -205,22 +207,23 @@
static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mma8452_show_samp_freq_avail);
static IIO_DEVICE_ATTR(in_accel_scale_available, S_IRUGO,
- mma8452_show_scale_avail, NULL, 0);
+ mma8452_show_scale_avail, NULL, 0);
static IIO_DEVICE_ATTR(in_accel_filter_high_pass_3db_frequency_available,
- S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0);
+ S_IRUGO, mma8452_show_hp_cutoff_avail, NULL, 0);
static int mma8452_get_samp_freq_index(struct mma8452_data *data,
- int val, int val2)
+ int val, int val2)
{
return mma8452_get_int_plus_micros_index(mma8452_samp_freq,
- ARRAY_SIZE(mma8452_samp_freq), val, val2);
+ ARRAY_SIZE(mma8452_samp_freq),
+ val, val2);
}
-static int mma8452_get_scale_index(struct mma8452_data *data,
- int val, int val2)
+static int mma8452_get_scale_index(struct mma8452_data *data, int val, int val2)
{
return mma8452_get_int_plus_micros_index(mma8452_scales,
- ARRAY_SIZE(mma8452_scales), val, val2);
+ ARRAY_SIZE(mma8452_scales),
+ val, val2);
}
static int mma8452_get_hp_filter_index(struct mma8452_data *data,
@@ -229,7 +232,7 @@
int i = mma8452_get_odr_index(data);
return mma8452_get_int_plus_micros_index(mma8452_hp_filter_cutoff[i],
- ARRAY_SIZE(mma8452_scales[0]), val, val2);
+ ARRAY_SIZE(mma8452_hp_filter_cutoff[0]), val, val2);
}
static int mma8452_read_hp_filter(struct mma8452_data *data, int *hz, int *uHz)
@@ -266,25 +269,31 @@
mutex_unlock(&data->lock);
if (ret < 0)
return ret;
- *val = sign_extend32(
- be16_to_cpu(buffer[chan->scan_index]) >> 4, 11);
+
+ *val = sign_extend32(be16_to_cpu(buffer[chan->scan_index]) >> 4,
+ 11);
+
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
i = data->data_cfg & MMA8452_DATA_CFG_FS_MASK;
*val = mma8452_scales[i][0];
*val2 = mma8452_scales[i][1];
+
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SAMP_FREQ:
i = mma8452_get_odr_index(data);
*val = mma8452_samp_freq[i][0];
*val2 = mma8452_samp_freq[i][1];
+
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_CALIBBIAS:
- ret = i2c_smbus_read_byte_data(data->client, MMA8452_OFF_X +
- chan->scan_index);
+ ret = i2c_smbus_read_byte_data(data->client,
+ MMA8452_OFF_X + chan->scan_index);
if (ret < 0)
return ret;
+
*val = sign_extend32(ret, 7);
+
return IIO_VAL_INT;
case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
if (data->data_cfg & MMA8452_DATA_CFG_HPF_MASK) {
@@ -295,21 +304,23 @@
*val = 0;
*val2 = 0;
}
+
return IIO_VAL_INT_PLUS_MICRO;
}
+
return -EINVAL;
}
static int mma8452_standby(struct mma8452_data *data)
{
return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
- data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE);
+ data->ctrl_reg1 & ~MMA8452_CTRL_ACTIVE);
}
static int mma8452_active(struct mma8452_data *data)
{
return i2c_smbus_write_byte_data(data->client, MMA8452_CTRL_REG1,
- data->ctrl_reg1);
+ data->ctrl_reg1);
}
static int mma8452_change_config(struct mma8452_data *data, u8 reg, u8 val)
@@ -334,6 +345,7 @@
ret = 0;
fail:
mutex_unlock(&data->lock);
+
return ret;
}
@@ -344,12 +356,13 @@
i = mma8452_get_hp_filter_index(data, val, val2);
if (i < 0)
- return -EINVAL;
+ return i;
reg = i2c_smbus_read_byte_data(data->client,
MMA8452_HP_FILTER_CUTOFF);
if (reg < 0)
return reg;
+
reg &= ~MMA8452_HP_FILTER_CUTOFF_SEL_MASK;
reg |= i;
@@ -370,25 +383,30 @@
case IIO_CHAN_INFO_SAMP_FREQ:
i = mma8452_get_samp_freq_index(data, val, val2);
if (i < 0)
- return -EINVAL;
+ return i;
data->ctrl_reg1 &= ~MMA8452_CTRL_DR_MASK;
data->ctrl_reg1 |= i << MMA8452_CTRL_DR_SHIFT;
+
return mma8452_change_config(data, MMA8452_CTRL_REG1,
- data->ctrl_reg1);
+ data->ctrl_reg1);
case IIO_CHAN_INFO_SCALE:
i = mma8452_get_scale_index(data, val, val2);
if (i < 0)
- return -EINVAL;
+ return i;
+
data->data_cfg &= ~MMA8452_DATA_CFG_FS_MASK;
data->data_cfg |= i;
+
return mma8452_change_config(data, MMA8452_DATA_CFG,
- data->data_cfg);
+ data->data_cfg);
case IIO_CHAN_INFO_CALIBBIAS:
if (val < -128 || val > 127)
return -EINVAL;
- return mma8452_change_config(data, MMA8452_OFF_X +
- chan->scan_index, val);
+
+ return mma8452_change_config(data,
+ MMA8452_OFF_X + chan->scan_index,
+ val);
case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:
if (val == 0 && val2 == 0) {
@@ -399,8 +417,9 @@
if (ret < 0)
return ret;
}
+
return mma8452_change_config(data, MMA8452_DATA_CFG,
- data->data_cfg);
+ data->data_cfg);
default:
return -EINVAL;
@@ -425,6 +444,7 @@
return ret;
*val = ret & MMA8452_TRANSIENT_THS_MASK;
+
return IIO_VAL_INT;
case IIO_EV_INFO_PERIOD:
@@ -437,6 +457,7 @@
mma8452_get_odr_index(data)];
*val = us / USEC_PER_SEC;
*val2 = us % USEC_PER_SEC;
+
return IIO_VAL_INT_PLUS_MICRO;
case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
@@ -453,6 +474,7 @@
if (ret < 0)
return ret;
}
+
return IIO_VAL_INT_PLUS_MICRO;
default:
@@ -472,19 +494,22 @@
switch (info) {
case IIO_EV_INFO_VALUE:
- return mma8452_change_config(data, MMA8452_TRANSIENT_THS,
- val & MMA8452_TRANSIENT_THS_MASK);
+ if (val < 0 || val > MMA8452_TRANSIENT_THS_MASK)
+ return -EINVAL;
+
+ return mma8452_change_config(data, MMA8452_TRANSIENT_THS, val);
case IIO_EV_INFO_PERIOD:
steps = (val * USEC_PER_SEC + val2) /
mma8452_transient_time_step_us[
mma8452_get_odr_index(data)];
- if (steps > 0xff)
+ if (steps < 0 || steps > 0xff)
return -EINVAL;
return mma8452_change_config(data, MMA8452_TRANSIENT_COUNT,
steps);
+
case IIO_EV_INFO_HIGH_PASS_FILTER_3DB:
reg = i2c_smbus_read_byte_data(data->client,
MMA8452_TRANSIENT_CFG);
@@ -499,6 +524,7 @@
if (ret < 0)
return ret;
}
+
return mma8452_change_config(data, MMA8452_TRANSIENT_CFG, reg);
default:
@@ -557,21 +583,21 @@
if (src & MMA8452_TRANSIENT_SRC_XTRANSE)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_X,
- IIO_EV_TYPE_THRESH,
+ IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING),
ts);
if (src & MMA8452_TRANSIENT_SRC_YTRANSE)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Y,
- IIO_EV_TYPE_THRESH,
+ IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING),
ts);
if (src & MMA8452_TRANSIENT_SRC_ZTRANSE)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_ACCEL, 0, IIO_MOD_Z,
- IIO_EV_TYPE_THRESH,
+ IIO_EV_TYPE_MAG,
IIO_EV_DIR_RISING),
ts);
}
@@ -608,15 +634,16 @@
u8 buffer[16]; /* 3 16-bit channels + padding + ts */
int ret;
- ret = mma8452_read(data, (__be16 *) buffer);
+ ret = mma8452_read(data, (__be16 *)buffer);
if (ret < 0)
goto done;
iio_push_to_buffers_with_timestamp(indio_dev, buffer,
- iio_get_time_ns());
+ iio_get_time_ns());
done:
iio_trigger_notify_done(indio_dev->trig);
+
return IRQ_HANDLED;
}
@@ -644,7 +671,7 @@
static const struct iio_event_spec mma8452_transient_event[] = {
{
- .type = IIO_EV_TYPE_THRESH,
+ .type = IIO_EV_TYPE_MAG,
.dir = IIO_EV_DIR_RISING,
.mask_separate = BIT(IIO_EV_INFO_ENABLE),
.mask_shared_by_type = BIT(IIO_EV_INFO_VALUE) |
@@ -674,10 +701,10 @@
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
- BIT(IIO_CHAN_INFO_CALIBBIAS), \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
- BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY), \
.scan_index = idx, \
.scan_type = { \
.sign = 's', \
@@ -780,6 +807,7 @@
return ret;
indio_dev->trig = trig;
+
return 0;
}
@@ -849,7 +877,7 @@
data->data_cfg = MMA8452_DATA_CFG_FS_2G;
ret = i2c_smbus_write_byte_data(client, MMA8452_DATA_CFG,
- data->data_cfg);
+ data->data_cfg);
if (ret < 0)
return ret;
@@ -891,14 +919,14 @@
}
data->ctrl_reg1 = MMA8452_CTRL_ACTIVE |
- (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
+ (MMA8452_CTRL_DR_DEFAULT << MMA8452_CTRL_DR_SHIFT);
ret = i2c_smbus_write_byte_data(client, MMA8452_CTRL_REG1,
data->ctrl_reg1);
if (ret < 0)
goto trigger_cleanup;
ret = iio_triggered_buffer_setup(indio_dev, NULL,
- mma8452_trigger_handler, NULL);
+ mma8452_trigger_handler, NULL);
if (ret < 0)
goto trigger_cleanup;
@@ -968,6 +996,7 @@
{ .compatible = "fsl,mma8452" },
{ }
};
+MODULE_DEVICE_TABLE(of, mma8452_dt_ids);
static struct i2c_driver mma8452_driver = {
.driver = {
diff --git a/drivers/iio/accel/mma9551_core.c b/drivers/iio/accel/mma9551_core.c
index 2fd2a99..c34c5ce 100644
--- a/drivers/iio/accel/mma9551_core.c
+++ b/drivers/iio/accel/mma9551_core.c
@@ -297,7 +297,7 @@
* Returns: 0 on success, negative value on failure.
*/
int mma9551_read_config_word(struct i2c_client *client, u8 app_id,
- u16 reg, u16 *val)
+ u16 reg, u16 *val)
{
int ret;
__be16 v;
@@ -328,12 +328,12 @@
* Returns: 0 on success, negative value on failure.
*/
int mma9551_write_config_word(struct i2c_client *client, u8 app_id,
- u16 reg, u16 val)
+ u16 reg, u16 val)
{
__be16 v = cpu_to_be16(val);
return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
- (u8 *) &v, 2, NULL, 0);
+ (u8 *)&v, 2, NULL, 0);
}
EXPORT_SYMBOL(mma9551_write_config_word);
@@ -373,7 +373,7 @@
* @client: I2C client
* @app_id: Application ID
* @reg: Application register
- * @len: Length of array to read in bytes
+ * @len: Length of array to read (in words)
* @buf: Array of words to read
*
* Read multiple configuration registers (word-sized registers).
@@ -385,23 +385,22 @@
* Returns: 0 on success, negative value on failure.
*/
int mma9551_read_config_words(struct i2c_client *client, u8 app_id,
- u16 reg, u8 len, u16 *buf)
+ u16 reg, u8 len, u16 *buf)
{
int ret, i;
- int len_words = len / sizeof(u16);
__be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
- if (len_words > ARRAY_SIZE(be_buf)) {
+ if (len > ARRAY_SIZE(be_buf)) {
dev_err(&client->dev, "Invalid buffer size %d\n", len);
return -EINVAL;
}
ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
- reg, NULL, 0, (u8 *) be_buf, len);
+ reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16));
if (ret < 0)
return ret;
- for (i = 0; i < len_words; i++)
+ for (i = 0; i < len; i++)
buf[i] = be16_to_cpu(be_buf[i]);
return 0;
@@ -413,7 +412,7 @@
* @client: I2C client
* @app_id: Application ID
* @reg: Application register
- * @len: Length of array to read in bytes
+ * @len: Length of array to read (in words)
* @buf: Array of words to read
*
* Read multiple status registers (word-sized registers).
@@ -428,20 +427,19 @@
u16 reg, u8 len, u16 *buf)
{
int ret, i;
- int len_words = len / sizeof(u16);
__be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
- if (len_words > ARRAY_SIZE(be_buf)) {
+ if (len > ARRAY_SIZE(be_buf)) {
dev_err(&client->dev, "Invalid buffer size %d\n", len);
return -EINVAL;
}
ret = mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
- reg, NULL, 0, (u8 *) be_buf, len);
+ reg, NULL, 0, (u8 *)be_buf, len * sizeof(u16));
if (ret < 0)
return ret;
- for (i = 0; i < len_words; i++)
+ for (i = 0; i < len; i++)
buf[i] = be16_to_cpu(be_buf[i]);
return 0;
@@ -453,7 +451,7 @@
* @client: I2C client
* @app_id: Application ID
* @reg: Application register
- * @len: Length of array to write in bytes
+ * @len: Length of array to write (in words)
* @buf: Array of words to write
*
* Write multiple configuration registers (word-sized registers).
@@ -468,19 +466,18 @@
u16 reg, u8 len, u16 *buf)
{
int i;
- int len_words = len / sizeof(u16);
__be16 be_buf[(MMA9551_MAX_MAILBOX_DATA_REGS - 1) / 2];
- if (len_words > ARRAY_SIZE(be_buf)) {
+ if (len > ARRAY_SIZE(be_buf)) {
dev_err(&client->dev, "Invalid buffer size %d\n", len);
return -EINVAL;
}
- for (i = 0; i < len_words; i++)
+ for (i = 0; i < len; i++)
be_buf[i] = cpu_to_be16(buf[i]);
return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG,
- reg, (u8 *) be_buf, len, NULL, 0);
+ reg, (u8 *)be_buf, len * sizeof(u16), NULL, 0);
}
EXPORT_SYMBOL(mma9551_write_config_words);
diff --git a/drivers/iio/accel/mma9551_core.h b/drivers/iio/accel/mma9551_core.h
index 79939e4..5e88e64 100644
--- a/drivers/iio/accel/mma9551_core.h
+++ b/drivers/iio/accel/mma9551_core.h
@@ -53,13 +53,13 @@
int mma9551_read_status_byte(struct i2c_client *client, u8 app_id,
u16 reg, u8 *val);
int mma9551_read_config_word(struct i2c_client *client, u8 app_id,
- u16 reg, u16 *val);
+ u16 reg, u16 *val);
int mma9551_write_config_word(struct i2c_client *client, u8 app_id,
- u16 reg, u16 val);
+ u16 reg, u16 val);
int mma9551_read_status_word(struct i2c_client *client, u8 app_id,
u16 reg, u16 *val);
int mma9551_read_config_words(struct i2c_client *client, u8 app_id,
- u16 reg, u8 len, u16 *buf);
+ u16 reg, u8 len, u16 *buf);
int mma9551_read_status_words(struct i2c_client *client, u8 app_id,
u16 reg, u8 len, u16 *buf);
int mma9551_write_config_words(struct i2c_client *client, u8 app_id,
diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c
index 8bfc618..771858c 100644
--- a/drivers/iio/accel/mma9553.c
+++ b/drivers/iio/accel/mma9553.c
@@ -182,6 +182,10 @@
struct mma9553_data {
struct i2c_client *client;
+ /*
+ * 1. Serialize access to HW (requested by mma9551_core API).
+ * 2. Serialize sequences that power on/off the device and access HW.
+ */
struct mutex mutex;
struct mma9553_conf_regs conf;
struct mma9553_event events[MMA9553_EVENTS_INFO_SIZE];
@@ -322,7 +326,8 @@
int ret;
ret = mma9551_read_status_words(data->client, MMA9551_APPID_PEDOMETER,
- MMA9553_REG_STATUS, sizeof(u32), buf);
+ MMA9553_REG_STATUS, ARRAY_SIZE(buf),
+ buf);
if (ret < 0) {
dev_err(&data->client->dev,
"error reading status and stepcnt\n");
@@ -342,10 +347,10 @@
struct mma9553_event *ev_step_detect;
bool activity_enabled;
- activity_enabled =
- mma9553_is_any_event_enabled(data, true, IIO_ACTIVITY);
- ev_step_detect =
- mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD, IIO_EV_DIR_NONE);
+ activity_enabled = mma9553_is_any_event_enabled(data, true,
+ IIO_ACTIVITY);
+ ev_step_detect = mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD,
+ IIO_EV_DIR_NONE);
/*
* If both step detector and activity are enabled, use the MRGFL bit.
@@ -371,9 +376,8 @@
return ret;
}
- ret = mma9551_gpio_config(data->client,
- MMA9553_DEFAULT_GPIO_PIN,
- appid, bitnum, MMA9553_DEFAULT_GPIO_POLARITY);
+ ret = mma9551_gpio_config(data->client, MMA9553_DEFAULT_GPIO_PIN, appid,
+ bitnum, MMA9553_DEFAULT_GPIO_POLARITY);
if (ret < 0)
return ret;
data->gpio_bitnum = bitnum;
@@ -394,17 +398,16 @@
* a device identification command to differentiate the MMA9553L
* from the MMA9550L.
*/
- ret =
- mma9551_read_config_words(data->client, MMA9551_APPID_PEDOMETER,
- MMA9553_REG_CONF_SLEEPMIN,
- sizeof(data->conf), (u16 *) &data->conf);
+ ret = mma9551_read_config_words(data->client, MMA9551_APPID_PEDOMETER,
+ MMA9553_REG_CONF_SLEEPMIN,
+ sizeof(data->conf) / sizeof(u16),
+ (u16 *)&data->conf);
if (ret < 0) {
dev_err(&data->client->dev,
"failed to read configuration registers\n");
return ret;
}
-
/* Reset GPIO */
data->gpio_bitnum = MMA9553_MAX_BITNUM;
ret = mma9553_conf_gpio(data);
@@ -419,18 +422,18 @@
data->conf.sleepmin = MMA9553_DEFAULT_SLEEPMIN;
data->conf.sleepmax = MMA9553_DEFAULT_SLEEPMAX;
data->conf.sleepthd = MMA9553_DEFAULT_SLEEPTHD;
- data->conf.config =
- mma9553_set_bits(data->conf.config, 1, MMA9553_MASK_CONF_CONFIG);
+ data->conf.config = mma9553_set_bits(data->conf.config, 1,
+ MMA9553_MASK_CONF_CONFIG);
/*
* Clear the activity debounce counter when the activity level changes,
* so that the confidence level applies for any activity level.
*/
data->conf.config = mma9553_set_bits(data->conf.config, 1,
MMA9553_MASK_CONF_ACT_DBCNTM);
- ret =
- mma9551_write_config_words(data->client, MMA9551_APPID_PEDOMETER,
- MMA9553_REG_CONF_SLEEPMIN,
- sizeof(data->conf), (u16 *) &data->conf);
+ ret = mma9551_write_config_words(data->client, MMA9551_APPID_PEDOMETER,
+ MMA9553_REG_CONF_SLEEPMIN,
+ sizeof(data->conf) / sizeof(u16),
+ (u16 *)&data->conf);
if (ret < 0) {
dev_err(&data->client->dev,
"failed to write configuration registers\n");
@@ -567,7 +570,7 @@
return IIO_VAL_INT;
case IIO_CHAN_INFO_CALIBHEIGHT:
tmp = mma9553_get_bits(data->conf.height_weight,
- MMA9553_MASK_CONF_HEIGHT);
+ MMA9553_MASK_CONF_HEIGHT);
*val = tmp / 100; /* cm to m */
*val2 = (tmp % 100) * 10000;
return IIO_VAL_INT_PLUS_MICRO;
@@ -719,7 +722,6 @@
enum iio_event_type type,
enum iio_event_direction dir)
{
-
struct mma9553_data *data = iio_priv(indio_dev);
struct mma9553_event *event;
@@ -1026,22 +1028,22 @@
return IRQ_HANDLED;
}
- ev_prev_activity =
- mma9553_get_event(data, IIO_ACTIVITY,
- mma9553_activity_to_mod(data->activity),
- IIO_EV_DIR_FALLING);
- ev_activity =
- mma9553_get_event(data, IIO_ACTIVITY,
- mma9553_activity_to_mod(activity),
- IIO_EV_DIR_RISING);
- ev_step_detect =
- mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD, IIO_EV_DIR_NONE);
+ ev_prev_activity = mma9553_get_event(data, IIO_ACTIVITY,
+ mma9553_activity_to_mod(
+ data->activity),
+ IIO_EV_DIR_FALLING);
+ ev_activity = mma9553_get_event(data, IIO_ACTIVITY,
+ mma9553_activity_to_mod(activity),
+ IIO_EV_DIR_RISING);
+ ev_step_detect = mma9553_get_event(data, IIO_STEPS, IIO_NO_MOD,
+ IIO_EV_DIR_NONE);
if (ev_step_detect->enabled && (stepcnt != data->stepcnt)) {
data->stepcnt = stepcnt;
iio_push_event(indio_dev,
IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
- IIO_EV_DIR_NONE, IIO_EV_TYPE_CHANGE, 0, 0, 0),
+ IIO_EV_DIR_NONE,
+ IIO_EV_TYPE_CHANGE, 0, 0, 0),
data->timestamp);
}
@@ -1051,17 +1053,19 @@
if (ev_prev_activity && ev_prev_activity->enabled)
iio_push_event(indio_dev,
IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- ev_prev_activity->info->mod,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH, 0, 0, 0),
+ ev_prev_activity->info->mod,
+ IIO_EV_DIR_FALLING,
+ IIO_EV_TYPE_THRESH, 0, 0,
+ 0),
data->timestamp);
if (ev_activity && ev_activity->enabled)
iio_push_event(indio_dev,
IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- ev_activity->info->mod,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH, 0, 0, 0),
+ ev_activity->info->mod,
+ IIO_EV_DIR_RISING,
+ IIO_EV_TYPE_THRESH, 0, 0,
+ 0),
data->timestamp);
}
mutex_unlock(&data->mutex);
@@ -1145,7 +1149,7 @@
if (client->irq < 0)
client->irq = mma9553_gpio_probe(client);
- if (client->irq >= 0) {
+ if (client->irq > 0) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
mma9553_irq_handler,
mma9553_event_handler,
@@ -1156,7 +1160,6 @@
client->irq);
goto out_poweroff;
}
-
}
ret = iio_device_register(indio_dev);
diff --git a/drivers/iio/accel/st_accel.h b/drivers/iio/accel/st_accel.h
index aa10019..468f21f 100644
--- a/drivers/iio/accel/st_accel.h
+++ b/drivers/iio/accel/st_accel.h
@@ -26,6 +26,7 @@
#define LSM303DLH_ACCEL_DEV_NAME "lsm303dlh_accel"
#define LSM303DLM_ACCEL_DEV_NAME "lsm303dlm_accel"
#define LSM330_ACCEL_DEV_NAME "lsm330_accel"
+#define LSM303AGR_ACCEL_DEV_NAME "lsm303agr_accel"
/**
* struct st_sensors_platform_data - default accel platform data
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 4002e64..ff30f88 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -226,12 +226,14 @@
static const struct st_sensor_settings st_accel_sensors_settings[] = {
{
.wai = ST_ACCEL_1_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS3DH_ACCEL_DEV_NAME,
[1] = LSM303DLHC_ACCEL_DEV_NAME,
[2] = LSM330D_ACCEL_DEV_NAME,
[3] = LSM330DL_ACCEL_DEV_NAME,
[4] = LSM330DLC_ACCEL_DEV_NAME,
+ [5] = LSM303AGR_ACCEL_DEV_NAME,
},
.ch = (struct iio_chan_spec *)st_accel_12bit_channels,
.odr = {
@@ -297,6 +299,7 @@
},
{
.wai = ST_ACCEL_2_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS331DLH_ACCEL_DEV_NAME,
[1] = LSM303DL_ACCEL_DEV_NAME,
@@ -359,6 +362,7 @@
},
{
.wai = ST_ACCEL_3_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM330_ACCEL_DEV_NAME,
},
@@ -437,6 +441,7 @@
},
{
.wai = ST_ACCEL_4_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS3LV02DL_ACCEL_DEV_NAME,
},
@@ -494,6 +499,7 @@
},
{
.wai = ST_ACCEL_5_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS331DL_ACCEL_DEV_NAME,
},
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
index d4ad72c..8b9cc84 100644
--- a/drivers/iio/accel/st_accel_i2c.c
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -68,6 +68,10 @@
.compatible = "st,lsm330-accel",
.data = LSM330_ACCEL_DEV_NAME,
},
+ {
+ .compatible = "st,lsm303agr-accel",
+ .data = LSM303AGR_ACCEL_DEV_NAME,
+ },
{},
};
MODULE_DEVICE_TABLE(of, st_accel_of_match);
@@ -116,13 +120,13 @@
{ LSM303DL_ACCEL_DEV_NAME },
{ LSM303DLM_ACCEL_DEV_NAME },
{ LSM330_ACCEL_DEV_NAME },
+ { LSM303AGR_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(i2c, st_accel_id_table);
static struct i2c_driver st_accel_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "st-accel-i2c",
.of_match_table = of_match_ptr(st_accel_of_match),
},
diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
index 12ec293..54b61a3 100644
--- a/drivers/iio/accel/st_accel_spi.c
+++ b/drivers/iio/accel/st_accel_spi.c
@@ -57,6 +57,7 @@
{ LSM303DL_ACCEL_DEV_NAME },
{ LSM303DLM_ACCEL_DEV_NAME },
{ LSM330_ACCEL_DEV_NAME },
+ { LSM303AGR_ACCEL_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(spi, st_accel_id_table);
diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c
index d211d9f3..c764af2 100644
--- a/drivers/iio/accel/stk8312.c
+++ b/drivers/iio/accel/stk8312.c
@@ -11,17 +11,25 @@
*/
#include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
#define STK8312_REG_XOUT 0x00
#define STK8312_REG_YOUT 0x01
#define STK8312_REG_ZOUT 0x02
+#define STK8312_REG_INTSU 0x06
#define STK8312_REG_MODE 0x07
+#define STK8312_REG_SR 0x08
#define STK8312_REG_STH 0x13
#define STK8312_REG_RESET 0x20
#define STK8312_REG_AFECTRL 0x24
@@ -29,14 +37,21 @@
#define STK8312_REG_OTPDATA 0x3E
#define STK8312_REG_OTPCTRL 0x3F
-#define STK8312_MODE_ACTIVE 1
-#define STK8312_MODE_STANDBY 0
-#define STK8312_MODE_MASK 0x01
-#define STK8312_RNG_MASK 0xC0
+#define STK8312_MODE_ACTIVE BIT(0)
+#define STK8312_MODE_STANDBY 0x00
+#define STK8312_MODE_INT_AH_PP 0xC0 /* active-high, push-pull */
+#define STK8312_DREADY_BIT BIT(4)
+#define STK8312_RNG_6G 1
#define STK8312_RNG_SHIFT 6
-#define STK8312_READ_RETRIES 16
+#define STK8312_RNG_MASK GENMASK(7, 6)
+#define STK8312_SR_MASK GENMASK(2, 0)
+#define STK8312_SR_400HZ_IDX 0
+#define STK8312_ALL_CHANNEL_MASK GENMASK(2, 0)
+#define STK8312_ALL_CHANNEL_SIZE 3
#define STK8312_DRIVER_NAME "stk8312"
+#define STK8312_GPIO "stk8312_gpio"
+#define STK8312_IRQ_NAME "stk8312_event"
/*
* The accelerometer has two measurement ranges:
@@ -53,32 +68,56 @@
{0, 461600}, {1, 231100}
};
-#define STK8312_ACCEL_CHANNEL(reg, axis) { \
- .type = IIO_ACCEL, \
- .address = reg, \
- .modified = 1, \
- .channel2 = IIO_MOD_##axis, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+static const struct {
+ int val;
+ int val2;
+} stk8312_samp_freq_table[] = {
+ {400, 0}, {200, 0}, {100, 0}, {50, 0}, {25, 0},
+ {12, 500000}, {6, 250000}, {3, 125000}
+};
+
+#define STK8312_ACCEL_CHANNEL(index, reg, axis) { \
+ .type = IIO_ACCEL, \
+ .address = reg, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 8, \
+ .storagebits = 8, \
+ .endianness = IIO_CPU, \
+ }, \
}
static const struct iio_chan_spec stk8312_channels[] = {
- STK8312_ACCEL_CHANNEL(STK8312_REG_XOUT, X),
- STK8312_ACCEL_CHANNEL(STK8312_REG_YOUT, Y),
- STK8312_ACCEL_CHANNEL(STK8312_REG_ZOUT, Z),
+ STK8312_ACCEL_CHANNEL(0, STK8312_REG_XOUT, X),
+ STK8312_ACCEL_CHANNEL(1, STK8312_REG_YOUT, Y),
+ STK8312_ACCEL_CHANNEL(2, STK8312_REG_ZOUT, Z),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
};
struct stk8312_data {
struct i2c_client *client;
struct mutex lock;
- int range;
+ u8 range;
+ u8 sample_rate_idx;
u8 mode;
+ struct iio_trigger *dready_trig;
+ bool dready_trigger_on;
+ s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 64-bit timestamp */
};
static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL);
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("3.125 6.25 12.5 25 50 100 200 400");
+
static struct attribute *stk8312_attributes[] = {
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL,
};
@@ -105,22 +144,25 @@
if (ret < 0)
goto exit_err;
count--;
- } while (!(ret & 0x80) && count > 0);
+ } while (!(ret & BIT(7)) && count > 0);
- if (count == 0)
+ if (count == 0) {
+ ret = -ETIMEDOUT;
goto exit_err;
+ }
ret = i2c_smbus_read_byte_data(client, STK8312_REG_OTPDATA);
+ if (ret == 0)
+ ret = -EINVAL;
if (ret < 0)
goto exit_err;
- ret = i2c_smbus_write_byte_data(data->client,
- STK8312_REG_AFECTRL, ret);
+ ret = i2c_smbus_write_byte_data(data->client, STK8312_REG_AFECTRL, ret);
if (ret < 0)
goto exit_err;
msleep(150);
- return ret;
+ return 0;
exit_err:
dev_err(&client->dev, "failed to initialize sensor\n");
@@ -130,31 +172,19 @@
static int stk8312_set_mode(struct stk8312_data *data, u8 mode)
{
int ret;
- u8 masked_reg;
struct i2c_client *client = data->client;
- if (mode > 1)
- return -EINVAL;
- else if (mode == data->mode)
+ if (mode == data->mode)
return 0;
- ret = i2c_smbus_read_byte_data(client, STK8312_REG_MODE);
- if (ret < 0) {
- dev_err(&client->dev, "failed to change sensor mode\n");
- return ret;
- }
- masked_reg = ret & (~STK8312_MODE_MASK);
- masked_reg |= mode;
-
- ret = i2c_smbus_write_byte_data(client,
- STK8312_REG_MODE, masked_reg);
+ ret = i2c_smbus_write_byte_data(client, STK8312_REG_MODE, mode);
if (ret < 0) {
dev_err(&client->dev, "failed to change sensor mode\n");
return ret;
}
data->mode = mode;
- if (mode == STK8312_MODE_ACTIVE) {
+ if (mode & STK8312_MODE_ACTIVE) {
/* Need to run OTP sequence before entering active mode */
usleep_range(1000, 5000);
ret = stk8312_otp_init(data);
@@ -163,6 +193,92 @@
return ret;
}
+static int stk8312_set_interrupts(struct stk8312_data *data, u8 int_mask)
+{
+ int ret;
+ u8 mode;
+ struct i2c_client *client = data->client;
+
+ mode = data->mode;
+ /* We need to go in standby mode to modify registers */
+ ret = stk8312_set_mode(data, STK8312_MODE_STANDBY);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_write_byte_data(client, STK8312_REG_INTSU, int_mask);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to set interrupts\n");
+ stk8312_set_mode(data, mode);
+ return ret;
+ }
+
+ return stk8312_set_mode(data, mode);
+}
+
+static int stk8312_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct stk8312_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (state)
+ ret = stk8312_set_interrupts(data, STK8312_DREADY_BIT);
+ else
+ ret = stk8312_set_interrupts(data, 0x00);
+
+ if (ret < 0) {
+ dev_err(&data->client->dev, "failed to set trigger state\n");
+ return ret;
+ }
+
+ data->dready_trigger_on = state;
+
+ return 0;
+}
+
+static const struct iio_trigger_ops stk8312_trigger_ops = {
+ .set_trigger_state = stk8312_data_rdy_trigger_set_state,
+ .owner = THIS_MODULE,
+};
+
+static int stk8312_set_sample_rate(struct stk8312_data *data, u8 rate)
+{
+ int ret;
+ u8 masked_reg;
+ u8 mode;
+ struct i2c_client *client = data->client;
+
+ if (rate == data->sample_rate_idx)
+ return 0;
+
+ mode = data->mode;
+ /* We need to go in standby mode to modify registers */
+ ret = stk8312_set_mode(data, STK8312_MODE_STANDBY);
+ if (ret < 0)
+ return ret;
+
+ ret = i2c_smbus_read_byte_data(client, STK8312_REG_SR);
+ if (ret < 0)
+ goto err_activate;
+
+ masked_reg = (ret & (~STK8312_SR_MASK)) | rate;
+
+ ret = i2c_smbus_write_byte_data(client, STK8312_REG_SR, masked_reg);
+ if (ret < 0)
+ goto err_activate;
+
+ data->sample_rate_idx = rate;
+
+ return stk8312_set_mode(data, mode);
+
+err_activate:
+ dev_err(&client->dev, "failed to set sampling rate\n");
+ stk8312_set_mode(data, mode);
+
+ return ret;
+}
+
static int stk8312_set_range(struct stk8312_data *data, u8 range)
{
int ret;
@@ -182,21 +298,25 @@
return ret;
ret = i2c_smbus_read_byte_data(client, STK8312_REG_STH);
- if (ret < 0) {
- dev_err(&client->dev, "failed to change sensor range\n");
- return ret;
- }
+ if (ret < 0)
+ goto err_activate;
masked_reg = ret & (~STK8312_RNG_MASK);
masked_reg |= range << STK8312_RNG_SHIFT;
ret = i2c_smbus_write_byte_data(client, STK8312_REG_STH, masked_reg);
if (ret < 0)
- dev_err(&client->dev, "failed to change sensor range\n");
- else
- data->range = range;
+ goto err_activate;
+
+ data->range = range;
return stk8312_set_mode(data, mode);
+
+err_activate:
+ dev_err(&client->dev, "failed to change sensor range\n");
+ stk8312_set_mode(data, mode);
+
+ return ret;
}
static int stk8312_read_accel(struct stk8312_data *data, u8 address)
@@ -208,12 +328,10 @@
return -EINVAL;
ret = i2c_smbus_read_byte_data(client, address);
- if (ret < 0) {
+ if (ret < 0)
dev_err(&client->dev, "register read failed\n");
- return ret;
- }
- return sign_extend32(ret, 7);
+ return ret;
}
static int stk8312_read_raw(struct iio_dev *indio_dev,
@@ -221,20 +339,40 @@
int *val, int *val2, long mask)
{
struct stk8312_data *data = iio_priv(indio_dev);
-
- if (chan->type != IIO_ACCEL)
- return -EINVAL;
+ int ret;
switch (mask) {
case IIO_CHAN_INFO_RAW:
+ if (iio_buffer_enabled(indio_dev))
+ return -EBUSY;
mutex_lock(&data->lock);
- *val = stk8312_read_accel(data, chan->address);
+ ret = stk8312_set_mode(data, data->mode | STK8312_MODE_ACTIVE);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+ ret = stk8312_read_accel(data, chan->address);
+ if (ret < 0) {
+ stk8312_set_mode(data,
+ data->mode & (~STK8312_MODE_ACTIVE));
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+ *val = sign_extend32(ret, 7);
+ ret = stk8312_set_mode(data,
+ data->mode & (~STK8312_MODE_ACTIVE));
mutex_unlock(&data->lock);
+ if (ret < 0)
+ return ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
*val = stk8312_scale_table[data->range - 1][0];
*val2 = stk8312_scale_table[data->range - 1][1];
return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = stk8312_samp_freq_table[data->sample_rate_idx].val;
+ *val2 = stk8312_samp_freq_table[data->sample_rate_idx].val2;
+ return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
@@ -265,6 +403,20 @@
mutex_unlock(&data->lock);
return ret;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ for (i = 0; i < ARRAY_SIZE(stk8312_samp_freq_table); i++)
+ if (val == stk8312_samp_freq_table[i].val &&
+ val2 == stk8312_samp_freq_table[i].val2) {
+ index = i;
+ break;
+ }
+ if (index < 0)
+ return -EINVAL;
+ mutex_lock(&data->lock);
+ ret = stk8312_set_sample_rate(data, index);
+ mutex_unlock(&data->lock);
+
+ return ret;
}
return -EINVAL;
@@ -277,6 +429,105 @@
.attrs = &stk8312_attribute_group,
};
+static irqreturn_t stk8312_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct stk8312_data *data = iio_priv(indio_dev);
+ int bit, ret, i = 0;
+
+ mutex_lock(&data->lock);
+ /*
+ * Do a bulk read if all channels are requested,
+ * from 0x00 (XOUT) to 0x02 (ZOUT)
+ */
+ if (*(indio_dev->active_scan_mask) == STK8312_ALL_CHANNEL_MASK) {
+ ret = i2c_smbus_read_i2c_block_data(data->client,
+ STK8312_REG_XOUT,
+ STK8312_ALL_CHANNEL_SIZE,
+ data->buffer);
+ if (ret < STK8312_ALL_CHANNEL_SIZE) {
+ dev_err(&data->client->dev, "register read failed\n");
+ mutex_unlock(&data->lock);
+ goto err;
+ }
+ } else {
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ ret = stk8312_read_accel(data, bit);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ goto err;
+ }
+ data->buffer[i++] = ret;
+ }
+ }
+ mutex_unlock(&data->lock);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ pf->timestamp);
+err:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t stk8312_data_rdy_trig_poll(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct stk8312_data *data = iio_priv(indio_dev);
+
+ if (data->dready_trigger_on)
+ iio_trigger_poll(data->dready_trig);
+
+ return IRQ_HANDLED;
+}
+
+static int stk8312_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct stk8312_data *data = iio_priv(indio_dev);
+
+ return stk8312_set_mode(data, data->mode | STK8312_MODE_ACTIVE);
+}
+
+static int stk8312_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct stk8312_data *data = iio_priv(indio_dev);
+
+ return stk8312_set_mode(data, data->mode & (~STK8312_MODE_ACTIVE));
+}
+
+static const struct iio_buffer_setup_ops stk8312_buffer_setup_ops = {
+ .preenable = stk8312_buffer_preenable,
+ .postenable = iio_triggered_buffer_postenable,
+ .predisable = iio_triggered_buffer_predisable,
+ .postdisable = stk8312_buffer_postdisable,
+};
+
+static int stk8312_gpio_probe(struct i2c_client *client)
+{
+ struct device *dev;
+ struct gpio_desc *gpio;
+ int ret;
+
+ if (!client)
+ return -EINVAL;
+
+ dev = &client->dev;
+
+ /* data ready gpio interrupt pin */
+ gpio = devm_gpiod_get_index(dev, STK8312_GPIO, 0, GPIOD_IN);
+ if (IS_ERR(gpio)) {
+ dev_err(dev, "acpi gpio get index failed\n");
+ return PTR_ERR(gpio);
+ }
+
+ ret = gpiod_to_irq(gpio);
+ dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
+
+ return ret;
+}
+
static int stk8312_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -308,30 +559,91 @@
dev_err(&client->dev, "failed to reset sensor\n");
return ret;
}
- ret = stk8312_set_range(data, 1);
+ data->sample_rate_idx = STK8312_SR_400HZ_IDX;
+ ret = stk8312_set_range(data, STK8312_RNG_6G);
if (ret < 0)
return ret;
- ret = stk8312_set_mode(data, STK8312_MODE_ACTIVE);
+ ret = stk8312_set_mode(data,
+ STK8312_MODE_INT_AH_PP | STK8312_MODE_ACTIVE);
if (ret < 0)
return ret;
+ if (client->irq < 0)
+ client->irq = stk8312_gpio_probe(client);
+
+ if (client->irq >= 0) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ stk8312_data_rdy_trig_poll,
+ NULL,
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT,
+ STK8312_IRQ_NAME,
+ indio_dev);
+ if (ret < 0) {
+ dev_err(&client->dev, "request irq %d failed\n",
+ client->irq);
+ goto err_power_off;
+ }
+
+ data->dready_trig = devm_iio_trigger_alloc(&client->dev,
+ "%s-dev%d",
+ indio_dev->name,
+ indio_dev->id);
+ if (!data->dready_trig) {
+ ret = -ENOMEM;
+ goto err_power_off;
+ }
+
+ data->dready_trig->dev.parent = &client->dev;
+ data->dready_trig->ops = &stk8312_trigger_ops;
+ iio_trigger_set_drvdata(data->dready_trig, indio_dev);
+ ret = iio_trigger_register(data->dready_trig);
+ if (ret) {
+ dev_err(&client->dev, "iio trigger register failed\n");
+ goto err_power_off;
+ }
+ }
+
+ ret = iio_triggered_buffer_setup(indio_dev,
+ iio_pollfunc_store_time,
+ stk8312_trigger_handler,
+ &stk8312_buffer_setup_ops);
+ if (ret < 0) {
+ dev_err(&client->dev, "iio triggered buffer setup failed\n");
+ goto err_trigger_unregister;
+ }
+
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "device_register failed\n");
- stk8312_set_mode(data, STK8312_MODE_STANDBY);
+ goto err_buffer_cleanup;
}
+ return 0;
+
+err_buffer_cleanup:
+ iio_triggered_buffer_cleanup(indio_dev);
+err_trigger_unregister:
+ if (data->dready_trig)
+ iio_trigger_unregister(data->dready_trig);
+err_power_off:
+ stk8312_set_mode(data, STK8312_MODE_STANDBY);
return ret;
}
static int stk8312_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct stk8312_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
- return stk8312_set_mode(iio_priv(indio_dev), STK8312_MODE_STANDBY);
+ if (data->dready_trig)
+ iio_trigger_unregister(data->dready_trig);
+
+ return stk8312_set_mode(data, STK8312_MODE_STANDBY);
}
#ifdef CONFIG_PM_SLEEP
@@ -341,7 +653,7 @@
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
- return stk8312_set_mode(data, STK8312_MODE_STANDBY);
+ return stk8312_set_mode(data, data->mode & (~STK8312_MODE_ACTIVE));
}
static int stk8312_resume(struct device *dev)
@@ -350,7 +662,7 @@
data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
- return stk8312_set_mode(data, STK8312_MODE_ACTIVE);
+ return stk8312_set_mode(data, data->mode | STK8312_MODE_ACTIVE);
}
static SIMPLE_DEV_PM_OPS(stk8312_pm_ops, stk8312_suspend, stk8312_resume);
@@ -364,6 +676,7 @@
{"STK8312", 0},
{}
};
+MODULE_DEVICE_TABLE(i2c, stk8312_i2c_id);
static const struct acpi_device_id stk8312_acpi_id[] = {
{"STK8312", 0},
@@ -374,7 +687,7 @@
static struct i2c_driver stk8312_driver = {
.driver = {
- .name = "stk8312",
+ .name = STK8312_DRIVER_NAME,
.pm = STK8312_PM_OPS,
.acpi_match_table = ACPI_PTR(stk8312_acpi_id),
},
diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c
index 30950c6..80f77d8 100644
--- a/drivers/iio/accel/stk8ba50.c
+++ b/drivers/iio/accel/stk8ba50.c
@@ -11,26 +11,42 @@
*/
#include <linux/acpi.h>
+#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
#define STK8BA50_REG_XOUT 0x02
#define STK8BA50_REG_YOUT 0x04
#define STK8BA50_REG_ZOUT 0x06
#define STK8BA50_REG_RANGE 0x0F
+#define STK8BA50_REG_BWSEL 0x10
#define STK8BA50_REG_POWMODE 0x11
#define STK8BA50_REG_SWRST 0x14
+#define STK8BA50_REG_INTEN2 0x17
+#define STK8BA50_REG_INTMAP2 0x1A
#define STK8BA50_MODE_NORMAL 0
#define STK8BA50_MODE_SUSPEND 1
#define STK8BA50_MODE_POWERBIT BIT(7)
#define STK8BA50_DATA_SHIFT 6
#define STK8BA50_RESET_CMD 0xB6
+#define STK8BA50_SR_1792HZ_IDX 7
+#define STK8BA50_DREADY_INT_MASK 0x10
+#define STK8BA50_DREADY_INT_MAP 0x81
+#define STK8BA50_ALL_CHANNEL_MASK 7
+#define STK8BA50_ALL_CHANNEL_SIZE 6
#define STK8BA50_DRIVER_NAME "stk8ba50"
+#define STK8BA50_GPIO "stk8ba50_gpio"
+#define STK8BA50_IRQ_NAME "stk8ba50_event"
#define STK8BA50_SCALE_AVAIL "0.0384 0.0767 0.1534 0.3069"
@@ -50,35 +66,76 @@
*
* Locally, the range is stored as a table index.
*/
-static const int stk8ba50_scale_table[][2] = {
+static const struct {
+ u8 reg_val;
+ u32 scale_val;
+} stk8ba50_scale_table[] = {
{3, 38400}, {5, 76700}, {8, 153400}, {12, 306900}
};
+/* Sample rates are stored as { <register value>, <Hz value> } */
+static const struct {
+ u8 reg_val;
+ u16 samp_freq;
+} stk8ba50_samp_freq_table[] = {
+ {0x08, 14}, {0x09, 25}, {0x0A, 56}, {0x0B, 112},
+ {0x0C, 224}, {0x0D, 448}, {0x0E, 896}, {0x0F, 1792}
+};
+
+/* Used to map scan mask bits to their corresponding channel register. */
+static const int stk8ba50_channel_table[] = {
+ STK8BA50_REG_XOUT,
+ STK8BA50_REG_YOUT,
+ STK8BA50_REG_ZOUT
+};
+
struct stk8ba50_data {
struct i2c_client *client;
struct mutex lock;
int range;
+ u8 sample_rate_idx;
+ struct iio_trigger *dready_trig;
+ bool dready_trigger_on;
+ /*
+ * 3 x 16-bit channels (10-bit data, 6-bit padding) +
+ * 1 x 16 padding +
+ * 4 x 16 64-bit timestamp
+ */
+ s16 buffer[8];
};
-#define STK8BA50_ACCEL_CHANNEL(reg, axis) { \
- .type = IIO_ACCEL, \
- .address = reg, \
- .modified = 1, \
- .channel2 = IIO_MOD_##axis, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+#define STK8BA50_ACCEL_CHANNEL(index, reg, axis) { \
+ .type = IIO_ACCEL, \
+ .address = reg, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 10, \
+ .storagebits = 16, \
+ .shift = STK8BA50_DATA_SHIFT, \
+ .endianness = IIO_CPU, \
+ }, \
}
static const struct iio_chan_spec stk8ba50_channels[] = {
- STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_XOUT, X),
- STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_YOUT, Y),
- STK8BA50_ACCEL_CHANNEL(STK8BA50_REG_ZOUT, Z),
+ STK8BA50_ACCEL_CHANNEL(0, STK8BA50_REG_XOUT, X),
+ STK8BA50_ACCEL_CHANNEL(1, STK8BA50_REG_YOUT, Y),
+ STK8BA50_ACCEL_CHANNEL(2, STK8BA50_REG_ZOUT, Z),
+ IIO_CHAN_SOFT_TIMESTAMP(3),
};
static IIO_CONST_ATTR(in_accel_scale_available, STK8BA50_SCALE_AVAIL);
+static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("14 25 56 112 224 448 896 1792");
+
static struct attribute *stk8ba50_attributes[] = {
&iio_const_attr_in_accel_scale_available.dev_attr.attr,
+ &iio_const_attr_sampling_frequency_available.dev_attr.attr,
NULL,
};
@@ -97,72 +154,34 @@
return ret;
}
- return sign_extend32(ret >> STK8BA50_DATA_SHIFT, 9);
+ return ret;
}
-static int stk8ba50_read_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int *val, int *val2, long mask)
+static int stk8ba50_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct stk8ba50_data *data = iio_priv(indio_dev);
-
- switch (mask) {
- case IIO_CHAN_INFO_RAW:
- mutex_lock(&data->lock);
- *val = stk8ba50_read_accel(data, chan->address);
- mutex_unlock(&data->lock);
- return IIO_VAL_INT;
- case IIO_CHAN_INFO_SCALE:
- *val = 0;
- *val2 = stk8ba50_scale_table[data->range][1];
- return IIO_VAL_INT_PLUS_MICRO;
- }
-
- return -EINVAL;
-}
-
-static int stk8ba50_write_raw(struct iio_dev *indio_dev,
- struct iio_chan_spec const *chan,
- int val, int val2, long mask)
-{
int ret;
- int i;
- int index = -1;
- struct stk8ba50_data *data = iio_priv(indio_dev);
- switch (mask) {
- case IIO_CHAN_INFO_SCALE:
- if (val != 0)
- return -EINVAL;
-
- for (i = 0; i < ARRAY_SIZE(stk8ba50_scale_table); i++)
- if (val2 == stk8ba50_scale_table[i][1]) {
- index = i;
- break;
- }
- if (index < 0)
- return -EINVAL;
-
+ if (state)
ret = i2c_smbus_write_byte_data(data->client,
- STK8BA50_REG_RANGE,
- stk8ba50_scale_table[index][0]);
- if (ret < 0)
- dev_err(&data->client->dev,
- "failed to set measurement range\n");
- else
- data->range = index;
+ STK8BA50_REG_INTEN2, STK8BA50_DREADY_INT_MASK);
+ else
+ ret = i2c_smbus_write_byte_data(data->client,
+ STK8BA50_REG_INTEN2, 0x00);
- return ret;
- }
+ if (ret < 0)
+ dev_err(&data->client->dev, "failed to set trigger state\n");
+ else
+ data->dready_trigger_on = state;
- return -EINVAL;
+ return ret;
}
-static const struct iio_info stk8ba50_info = {
- .driver_module = THIS_MODULE,
- .read_raw = stk8ba50_read_raw,
- .write_raw = stk8ba50_write_raw,
- .attrs = &stk8ba50_attribute_group,
+static const struct iio_trigger_ops stk8ba50_trigger_ops = {
+ .set_trigger_state = stk8ba50_data_rdy_trigger_set_state,
+ .owner = THIS_MODULE,
};
static int stk8ba50_set_power(struct stk8ba50_data *data, bool mode)
@@ -192,6 +211,207 @@
return ret;
}
+static int stk8ba50_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct stk8ba50_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (iio_buffer_enabled(indio_dev))
+ return -EBUSY;
+ mutex_lock(&data->lock);
+ ret = stk8ba50_set_power(data, STK8BA50_MODE_NORMAL);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return -EINVAL;
+ }
+ ret = stk8ba50_read_accel(data, chan->address);
+ if (ret < 0) {
+ stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
+ mutex_unlock(&data->lock);
+ return -EINVAL;
+ }
+ *val = sign_extend32(ret >> STK8BA50_DATA_SHIFT, 9);
+ stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
+ mutex_unlock(&data->lock);
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ *val2 = stk8ba50_scale_table[data->range].scale_val;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = stk8ba50_samp_freq_table
+ [data->sample_rate_idx].samp_freq;
+ *val2 = 0;
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static int stk8ba50_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ int ret;
+ int i;
+ int index = -1;
+ struct stk8ba50_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ if (val != 0)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(stk8ba50_scale_table); i++)
+ if (val2 == stk8ba50_scale_table[i].scale_val) {
+ index = i;
+ break;
+ }
+ if (index < 0)
+ return -EINVAL;
+
+ ret = i2c_smbus_write_byte_data(data->client,
+ STK8BA50_REG_RANGE,
+ stk8ba50_scale_table[index].reg_val);
+ if (ret < 0)
+ dev_err(&data->client->dev,
+ "failed to set measurement range\n");
+ else
+ data->range = index;
+
+ return ret;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ for (i = 0; i < ARRAY_SIZE(stk8ba50_samp_freq_table); i++)
+ if (val == stk8ba50_samp_freq_table[i].samp_freq) {
+ index = i;
+ break;
+ }
+ if (index < 0)
+ return -EINVAL;
+
+ ret = i2c_smbus_write_byte_data(data->client,
+ STK8BA50_REG_BWSEL,
+ stk8ba50_samp_freq_table[index].reg_val);
+ if (ret < 0)
+ dev_err(&data->client->dev,
+ "failed to set sampling rate\n");
+ else
+ data->sample_rate_idx = index;
+
+ return ret;
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info stk8ba50_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = stk8ba50_read_raw,
+ .write_raw = stk8ba50_write_raw,
+ .attrs = &stk8ba50_attribute_group,
+};
+
+static irqreturn_t stk8ba50_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct stk8ba50_data *data = iio_priv(indio_dev);
+ int bit, ret, i = 0;
+
+ mutex_lock(&data->lock);
+ /*
+ * Do a bulk read if all channels are requested,
+ * from 0x02 (XOUT1) to 0x07 (ZOUT2)
+ */
+ if (*(indio_dev->active_scan_mask) == STK8BA50_ALL_CHANNEL_MASK) {
+ ret = i2c_smbus_read_i2c_block_data(data->client,
+ STK8BA50_REG_XOUT,
+ STK8BA50_ALL_CHANNEL_SIZE,
+ (u8 *)data->buffer);
+ if (ret < STK8BA50_ALL_CHANNEL_SIZE) {
+ dev_err(&data->client->dev, "register read failed\n");
+ goto err;
+ }
+ } else {
+ for_each_set_bit(bit, indio_dev->active_scan_mask,
+ indio_dev->masklength) {
+ ret = stk8ba50_read_accel(data,
+ stk8ba50_channel_table[bit]);
+ if (ret < 0)
+ goto err;
+
+ data->buffer[i++] = ret;
+ }
+ }
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buffer,
+ pf->timestamp);
+err:
+ mutex_unlock(&data->lock);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t stk8ba50_data_rdy_trig_poll(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct stk8ba50_data *data = iio_priv(indio_dev);
+
+ if (data->dready_trigger_on)
+ iio_trigger_poll(data->dready_trig);
+
+ return IRQ_HANDLED;
+}
+
+static int stk8ba50_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct stk8ba50_data *data = iio_priv(indio_dev);
+
+ return stk8ba50_set_power(data, STK8BA50_MODE_NORMAL);
+}
+
+static int stk8ba50_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct stk8ba50_data *data = iio_priv(indio_dev);
+
+ return stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
+}
+
+static const struct iio_buffer_setup_ops stk8ba50_buffer_setup_ops = {
+ .preenable = stk8ba50_buffer_preenable,
+ .postenable = iio_triggered_buffer_postenable,
+ .predisable = iio_triggered_buffer_predisable,
+ .postdisable = stk8ba50_buffer_postdisable,
+};
+
+static int stk8ba50_gpio_probe(struct i2c_client *client)
+{
+ struct device *dev;
+ struct gpio_desc *gpio;
+ int ret;
+
+ if (!client)
+ return -EINVAL;
+
+ dev = &client->dev;
+
+ /* data ready gpio interrupt pin */
+ gpio = devm_gpiod_get_index(dev, STK8BA50_GPIO, 0, GPIOD_IN);
+ if (IS_ERR(gpio)) {
+ dev_err(dev, "acpi gpio get index failed\n");
+ return PTR_ERR(gpio);
+ }
+
+ ret = gpiod_to_irq(gpio);
+ dev_dbg(dev, "GPIO resource, no:%d irq:%d\n", desc_to_gpio(gpio), ret);
+
+ return ret;
+}
+
static int stk8ba50_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
@@ -222,28 +442,104 @@
STK8BA50_REG_SWRST, STK8BA50_RESET_CMD);
if (ret < 0) {
dev_err(&client->dev, "failed to reset sensor\n");
- return ret;
+ goto err_power_off;
}
/* The default range is +/-2g */
data->range = 0;
+ /* The default sampling rate is 1792 Hz (maximum) */
+ data->sample_rate_idx = STK8BA50_SR_1792HZ_IDX;
+
+ /* Set up interrupts */
+ ret = i2c_smbus_write_byte_data(client,
+ STK8BA50_REG_INTEN2, STK8BA50_DREADY_INT_MASK);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to set up interrupts\n");
+ goto err_power_off;
+ }
+ ret = i2c_smbus_write_byte_data(client,
+ STK8BA50_REG_INTMAP2, STK8BA50_DREADY_INT_MAP);
+ if (ret < 0) {
+ dev_err(&client->dev, "failed to set up interrupts\n");
+ goto err_power_off;
+ }
+
+ if (client->irq < 0)
+ client->irq = stk8ba50_gpio_probe(client);
+
+ if (client->irq >= 0) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ stk8ba50_data_rdy_trig_poll,
+ NULL,
+ IRQF_TRIGGER_RISING |
+ IRQF_ONESHOT,
+ STK8BA50_IRQ_NAME,
+ indio_dev);
+ if (ret < 0) {
+ dev_err(&client->dev, "request irq %d failed\n",
+ client->irq);
+ goto err_power_off;
+ }
+
+ data->dready_trig = devm_iio_trigger_alloc(&client->dev,
+ "%s-dev%d",
+ indio_dev->name,
+ indio_dev->id);
+ if (!data->dready_trig) {
+ ret = -ENOMEM;
+ goto err_power_off;
+ }
+
+ data->dready_trig->dev.parent = &client->dev;
+ data->dready_trig->ops = &stk8ba50_trigger_ops;
+ iio_trigger_set_drvdata(data->dready_trig, indio_dev);
+ ret = iio_trigger_register(data->dready_trig);
+ if (ret) {
+ dev_err(&client->dev, "iio trigger register failed\n");
+ goto err_power_off;
+ }
+ }
+
+ ret = iio_triggered_buffer_setup(indio_dev,
+ iio_pollfunc_store_time,
+ stk8ba50_trigger_handler,
+ &stk8ba50_buffer_setup_ops);
+ if (ret < 0) {
+ dev_err(&client->dev, "iio triggered buffer setup failed\n");
+ goto err_trigger_unregister;
+ }
+
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "device_register failed\n");
- stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
+ goto err_buffer_cleanup;
}
return ret;
+
+err_buffer_cleanup:
+ iio_triggered_buffer_cleanup(indio_dev);
+err_trigger_unregister:
+ if (data->dready_trig)
+ iio_trigger_unregister(data->dready_trig);
+err_power_off:
+ stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
+ return ret;
}
static int stk8ba50_remove(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
+ struct stk8ba50_data *data = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
- return stk8ba50_set_power(iio_priv(indio_dev), STK8BA50_MODE_SUSPEND);
+ if (data->dready_trig)
+ iio_trigger_unregister(data->dready_trig);
+
+ return stk8ba50_set_power(data, STK8BA50_MODE_SUSPEND);
}
#ifdef CONFIG_PM_SLEEP
@@ -276,6 +572,7 @@
{"stk8ba50", 0},
{}
};
+MODULE_DEVICE_TABLE(i2c, stk8ba50_i2c_id);
static const struct acpi_device_id stk8ba50_acpi_id[] = {
{"STK8BA50", 0},
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index eb0cd89..50c103d 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -20,6 +20,9 @@
Say yes here to build support for Analog Devices AD7265 and AD7266
ADCs.
+ To compile this driver as a module, choose M here: the module will be
+ called ad7266.
+
config AD7291
tristate "Analog Devices AD7291 ADC driver"
depends on I2C
@@ -52,8 +55,6 @@
AD7277, AD7278, AD7475, AD7476, AD7477, AD7478, AD7466, AD7467, AD7468,
AD7495, AD7910, AD7920, AD7920 SPI analog to digital converters (ADC).
- If unsure, say N (but it's safe to say "Y").
-
To compile this driver as a module, choose M here: the
module will be called ad7476.
@@ -63,8 +64,7 @@
select AD_SIGMA_DELTA
help
Say yes here to build support for Analog Devices AD7787, AD7788, AD7789,
- AD7790 and AD7791 SPI analog to digital converters (ADC). If unsure, say
- N (but it is safe to say "Y").
+ AD7790 and AD7791 SPI analog to digital converters (ADC).
To compile this driver as a module, choose M here: the module will be
called ad7791.
@@ -76,7 +76,6 @@
help
Say yes here to build support for Analog Devices AD7785, AD7792, AD7793,
AD7794 and AD7795 SPI analog to digital converters (ADC).
- If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called AD7793.
@@ -89,7 +88,6 @@
help
Say yes here to build support for Analog Devices
AD7887 SPI analog to digital converter (ADC).
- If unsure, say N (but it's safe to say "Y").
To compile this driver as a module, choose M here: the
module will be called ad7887.
@@ -117,6 +115,9 @@
i2c analog to digital converters (ADC). Provides direct access
via sysfs.
+ To compile this driver as a module, choose M here: the module will be
+ called ad799x.
+
config AT91_ADC
tristate "Atmel AT91 ADC"
depends on ARCH_AT91
@@ -127,6 +128,9 @@
help
Say yes here to build support for Atmel AT91 ADC.
+ To compile this driver as a module, choose M here: the module will be
+ called at91_adc.
+
config AXP288_ADC
tristate "X-Powers AXP288 ADC driver"
depends on MFD_AXP20X
@@ -135,6 +139,9 @@
device. Depending on platform configuration, this general purpose ADC can
be used for sampling sensors such as thermal resistors.
+ To compile this driver as a module, choose M here: the module will be
+ called axp288_adc.
+
config BERLIN2_ADC
tristate "Marvell Berlin2 ADC driver"
depends on ARCH_BERLIN
@@ -151,6 +158,9 @@
This driver can also be built as a module. If chosen, the module name
will be da9150-gpadc.
+ To compile this driver as a module, choose M here: the module will be
+ called berlin2-adc.
+
config CC10001_ADC
tristate "Cosmic Circuits 10001 ADC driver"
depends on HAS_IOMEM && HAVE_CLK && REGULATOR
@@ -170,12 +180,18 @@
of SoCs for drivers such as the touchscreen and hwmon to use to share
this resource.
+ To compile this driver as a module, choose M here: the module will be
+ called exynos_adc.
+
config LP8788_ADC
tristate "LP8788 ADC driver"
depends on MFD_LP8788
help
Say yes here to build support for TI LP8788 ADC.
+ To compile this driver as a module, choose M here: the module will be
+ called lp8788_adc.
+
config MAX1027
tristate "Maxim max1027 ADC driver"
depends on SPI
@@ -185,6 +201,9 @@
Say yes here to build support for Maxim SPI ADC models
max1027, max1029 and max1031.
+ To compile this driver as a module, choose M here: the module will be
+ called max1027.
+
config MAX1363
tristate "Maxim max1363 ADC driver"
depends on I2C
@@ -201,13 +220,16 @@
max11646, max11647) Provides direct access via sysfs and buffered
data via the iio dev interface.
+ To compile this driver as a module, choose M here: the module will be
+ called max1363.
+
config MCP320X
tristate "Microchip Technology MCP3x01/02/04/08"
depends on SPI
help
Say yes here to build support for Microchip Technology's
- MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204 or
- MCP3208 analog to digital converter.
+ MCP3001, MCP3002, MCP3004, MCP3008, MCP3201, MCP3202, MCP3204,
+ MCP3208 or MCP3301 analog to digital converter.
This driver can also be built as a module. If so, the module will be
called mcp320x.
@@ -309,15 +331,18 @@
Say yes here to build support for Texas Instruments ADC
driver which is also a MFD client.
+ To compile this driver as a module, choose M here: the module will be
+ called ti_am335x_adc.
+
config TWL4030_MADC
tristate "TWL4030 MADC (Monitoring A/D Converter)"
depends on TWL4030_CORE
help
- This driver provides support for Triton TWL4030-MADC. The
- driver supports both RT and SW conversion methods.
+ This driver provides support for Triton TWL4030-MADC. The
+ driver supports both RT and SW conversion methods.
- This driver can also be built as a module. If so, the module will be
- called twl4030-madc.
+ This driver can also be built as a module. If so, the module will be
+ called twl4030-madc.
config TWL6030_GPADC
tristate "TWL6030 GPADC (General Purpose A/D Converter) Support"
@@ -350,6 +375,9 @@
Say yes here to access the ADC part of the Nano River
Technologies Viperboard.
+ To compile this driver as a module, choose M here: the module will be
+ called viperboard_adc.
+
config XILINX_XADC
tristate "Xilinx XADC driver"
depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
diff --git a/drivers/iio/adc/berlin2-adc.c b/drivers/iio/adc/berlin2-adc.c
index aecc9ad..4946d9b 100644
--- a/drivers/iio/adc/berlin2-adc.c
+++ b/drivers/iio/adc/berlin2-adc.c
@@ -26,7 +26,7 @@
#define BERLIN2_SM_CTRL 0x14
#define BERLIN2_SM_CTRL_SM_SOC_INT BIT(1)
#define BERLIN2_SM_CTRL_SOC_SM_INT BIT(2)
-#define BERLIN2_SM_CTRL_ADC_SEL(x) (BIT(x) << 5) /* 0-15 */
+#define BERLIN2_SM_CTRL_ADC_SEL(x) ((x) << 5) /* 0-15 */
#define BERLIN2_SM_CTRL_ADC_SEL_MASK (0xf << 5)
#define BERLIN2_SM_CTRL_ADC_POWER BIT(9)
#define BERLIN2_SM_CTRL_ADC_CLKSEL_DIV2 (0x0 << 10)
@@ -53,14 +53,14 @@
#define BERLIN2_SM_ADC_MASK 0x3ff
#define BERLIN2_SM_ADC_STATUS 0x1c
#define BERLIN2_SM_ADC_STATUS_DATA_RDY(x) BIT(x) /* 0-15 */
-#define BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK 0xf
+#define BERLIN2_SM_ADC_STATUS_DATA_RDY_MASK GENMASK(15, 0)
#define BERLIN2_SM_ADC_STATUS_INT_EN(x) (BIT(x) << 16) /* 0-15 */
-#define BERLIN2_SM_ADC_STATUS_INT_EN_MASK (0xf << 16)
+#define BERLIN2_SM_ADC_STATUS_INT_EN_MASK GENMASK(31, 16)
#define BERLIN2_SM_TSEN_STATUS 0x24
#define BERLIN2_SM_TSEN_STATUS_DATA_RDY BIT(0)
#define BERLIN2_SM_TSEN_STATUS_INT_EN BIT(1)
#define BERLIN2_SM_TSEN_DATA 0x28
-#define BERLIN2_SM_TSEN_MASK 0xfff
+#define BERLIN2_SM_TSEN_MASK GENMASK(9, 0)
#define BERLIN2_SM_TSEN_CTRL 0x74
#define BERLIN2_SM_TSEN_CTRL_START BIT(8)
#define BERLIN2_SM_TSEN_CTRL_SETTLING_4 (0x0 << 21) /* 4 us */
@@ -86,7 +86,7 @@
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
}
-static struct iio_chan_spec berlin2_adc_channels[] = {
+static const struct iio_chan_spec berlin2_adc_channels[] = {
BERLIN2_ADC_CHANNEL(0, IIO_VOLTAGE), /* external input */
BERLIN2_ADC_CHANNEL(1, IIO_VOLTAGE), /* external input */
BERLIN2_ADC_CHANNEL(2, IIO_VOLTAGE), /* external input */
@@ -103,7 +103,6 @@
BERLIN2_ADC_CHANNEL(7, IIO_VOLTAGE), /* reserved */
IIO_CHAN_SOFT_TIMESTAMP(8), /* timestamp */
};
-#define BERLIN2_N_CHANNELS ARRAY_SIZE(berlin2_adc_channels)
static int berlin2_adc_read(struct iio_dev *indio_dev, int channel)
{
@@ -221,7 +220,7 @@
return temp;
if (temp > 2047)
- temp = -(4096 - temp);
+ temp -= 4096;
/* Convert to milli Celsius */
*val = ((temp * 100000) / 264 - 270000);
@@ -286,8 +285,7 @@
int irq, tsen_irq;
int ret;
- indio_dev = devm_iio_device_alloc(&pdev->dev,
- sizeof(struct berlin2_adc_priv));
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv));
if (!indio_dev)
return -ENOMEM;
@@ -301,11 +299,11 @@
irq = platform_get_irq_byname(pdev, "adc");
if (irq < 0)
- return -ENODEV;
+ return irq;
tsen_irq = platform_get_irq_byname(pdev, "tsen");
if (tsen_irq < 0)
- return -ENODEV;
+ return tsen_irq;
ret = devm_request_irq(&pdev->dev, irq, berlin2_adc_irq, 0,
pdev->dev.driver->name, indio_dev);
@@ -325,8 +323,8 @@
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &berlin2_adc_info;
- indio_dev->num_channels = BERLIN2_N_CHANNELS;
indio_dev->channels = berlin2_adc_channels;
+ indio_dev->num_channels = ARRAY_SIZE(berlin2_adc_channels);
/* Power up the ADC */
regmap_update_bits(priv->regmap, BERLIN2_SM_CTRL,
diff --git a/drivers/iio/adc/cc10001_adc.c b/drivers/iio/adc/cc10001_adc.c
index 115f6e9..8254f52 100644
--- a/drivers/iio/adc/cc10001_adc.c
+++ b/drivers/iio/adc/cc10001_adc.c
@@ -62,6 +62,7 @@
struct regulator *reg;
u16 *buf;
+ bool shared;
struct mutex lock;
unsigned int start_delay_ns;
unsigned int eoc_delay_ns;
@@ -153,7 +154,8 @@
mutex_lock(&adc_dev->lock);
- cc10001_adc_power_up(adc_dev);
+ if (!adc_dev->shared)
+ cc10001_adc_power_up(adc_dev);
/* Calculate delay step for eoc and sampled data */
delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT;
@@ -177,7 +179,8 @@
}
done:
- cc10001_adc_power_down(adc_dev);
+ if (!adc_dev->shared)
+ cc10001_adc_power_down(adc_dev);
mutex_unlock(&adc_dev->lock);
@@ -196,7 +199,8 @@
unsigned int delay_ns;
u16 val;
- cc10001_adc_power_up(adc_dev);
+ if (!adc_dev->shared)
+ cc10001_adc_power_up(adc_dev);
/* Calculate delay step for eoc and sampled data */
delay_ns = adc_dev->eoc_delay_ns / CC10001_MAX_POLL_COUNT;
@@ -205,7 +209,8 @@
val = cc10001_adc_poll_done(indio_dev, chan->channel, delay_ns);
- cc10001_adc_power_down(adc_dev);
+ if (!adc_dev->shared)
+ cc10001_adc_power_down(adc_dev);
return val;
}
@@ -322,8 +327,10 @@
adc_dev = iio_priv(indio_dev);
channel_map = GENMASK(CC10001_ADC_NUM_CHANNELS - 1, 0);
- if (!of_property_read_u32(node, "adc-reserved-channels", &ret))
+ if (!of_property_read_u32(node, "adc-reserved-channels", &ret)) {
+ adc_dev->shared = true;
channel_map &= ~ret;
+ }
adc_dev->reg = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(adc_dev->reg))
@@ -368,6 +375,14 @@
adc_dev->eoc_delay_ns = NSEC_PER_SEC / adc_clk_rate;
adc_dev->start_delay_ns = adc_dev->eoc_delay_ns * CC10001_WAIT_CYCLES;
+ /*
+ * There is only one register to power-up/power-down the AUX ADC.
+ * If the ADC is shared among multiple CPUs, always power it up here.
+ * If the ADC is used only by the MIPS, power-up/power-down at runtime.
+ */
+ if (adc_dev->shared)
+ cc10001_adc_power_up(adc_dev);
+
/* Setup the ADC channels available on the device */
ret = cc10001_adc_channel_init(indio_dev, channel_map);
if (ret < 0)
@@ -402,6 +417,7 @@
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct cc10001_adc_device *adc_dev = iio_priv(indio_dev);
+ cc10001_adc_power_down(adc_dev);
iio_device_unregister(indio_dev);
iio_triggered_buffer_cleanup(indio_dev);
clk_disable_unprepare(adc_dev->adc_clk);
diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c
index 8d9c9b9..b19e4f9 100644
--- a/drivers/iio/adc/mcp320x.c
+++ b/drivers/iio/adc/mcp320x.c
@@ -25,6 +25,7 @@
* http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf mcp3201
* http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf mcp3202
* http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf mcp3204/08
+ * http://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf mcp3301
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -47,6 +48,7 @@
mcp3202,
mcp3204,
mcp3208,
+ mcp3301,
};
struct mcp320x_chip_info {
@@ -76,6 +78,7 @@
switch (device_index) {
case mcp3001:
case mcp3201:
+ case mcp3301:
return 0;
case mcp3002:
case mcp3202:
@@ -102,7 +105,7 @@
adc->tx_buf = mcp320x_channel_to_tx_data(device_index,
channel, differential);
- if (device_index != mcp3001 && device_index != mcp3201) {
+ if (device_index != mcp3001 && device_index != mcp3201 && device_index != mcp3301) {
ret = spi_sync(adc->spi, &adc->msg);
if (ret < 0)
return ret;
@@ -125,6 +128,8 @@
case mcp3204:
case mcp3208:
return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
+ case mcp3301:
+ return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12);
default:
return -EINVAL;
}
@@ -274,6 +279,11 @@
.num_channels = ARRAY_SIZE(mcp3208_channels),
.resolution = 12
},
+ [mcp3301] = {
+ .channels = mcp3201_channels,
+ .num_channels = ARRAY_SIZE(mcp3201_channels),
+ .resolution = 13
+ },
};
static int mcp320x_probe(struct spi_device *spi)
@@ -299,6 +309,8 @@
indio_dev->channels = chip_info->channels;
indio_dev->num_channels = chip_info->num_channels;
+ adc->chip_info = chip_info;
+
adc->transfer[0].tx_buf = &adc->tx_buf;
adc->transfer[0].len = sizeof(adc->tx_buf);
adc->transfer[1].rx_buf = adc->rx_buf;
@@ -367,6 +379,9 @@
.compatible = "mcp3208",
.data = &mcp320x_chip_infos[mcp3208],
}, {
+ .compatible = "mcp3301",
+ .data = &mcp320x_chip_infos[mcp3301],
+ }, {
}
};
MODULE_DEVICE_TABLE(of, mcp320x_dt_ids);
@@ -381,6 +396,7 @@
{ "mcp3202", mcp3202 },
{ "mcp3204", mcp3204 },
{ "mcp3208", mcp3208 },
+ { "mcp3301", mcp3301 },
{ }
};
MODULE_DEVICE_TABLE(spi, mcp320x_id);
diff --git a/drivers/iio/adc/mcp3422.c b/drivers/iio/adc/mcp3422.c
index b96c636..3555122 100644
--- a/drivers/iio/adc/mcp3422.c
+++ b/drivers/iio/adc/mcp3422.c
@@ -404,7 +404,6 @@
static struct i2c_driver mcp3422_driver = {
.driver = {
.name = "mcp3422",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(mcp3422_of_match),
},
.probe = mcp3422_probe,
diff --git a/drivers/iio/adc/ti-adc081c.c b/drivers/iio/adc/ti-adc081c.c
index b3a82b4..2c8374f 100644
--- a/drivers/iio/adc/ti-adc081c.c
+++ b/drivers/iio/adc/ti-adc081c.c
@@ -140,7 +140,6 @@
static struct i2c_driver adc081c_driver = {
.driver = {
.name = "adc081c",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(adc081c_of_match),
},
.probe = adc081c_probe,
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 480f335..6bf4c20 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -68,6 +68,9 @@
#define VF610_ADC_CLK_DIV8 0x60
#define VF610_ADC_CLK_MASK 0x60
#define VF610_ADC_ADLSMP_LONG 0x10
+#define VF610_ADC_ADSTS_SHORT 0x100
+#define VF610_ADC_ADSTS_NORMAL 0x200
+#define VF610_ADC_ADSTS_LONG 0x300
#define VF610_ADC_ADSTS_MASK 0x300
#define VF610_ADC_ADLPC_EN 0x80
#define VF610_ADC_ADHSC_EN 0x400
@@ -98,6 +101,8 @@
#define VF610_ADC_CALF 0x2
#define VF610_ADC_TIMEOUT msecs_to_jiffies(100)
+#define DEFAULT_SAMPLE_TIME 1000
+
enum clk_sel {
VF610_ADCIOC_BUSCLK_SET,
VF610_ADCIOC_ALTCLK_SET,
@@ -124,6 +129,17 @@
VF610_ADC_CONV_LOW_POWER,
};
+enum lst_adder_sel {
+ VF610_ADCK_CYCLES_3,
+ VF610_ADCK_CYCLES_5,
+ VF610_ADCK_CYCLES_7,
+ VF610_ADCK_CYCLES_9,
+ VF610_ADCK_CYCLES_13,
+ VF610_ADCK_CYCLES_17,
+ VF610_ADCK_CYCLES_21,
+ VF610_ADCK_CYCLES_25,
+};
+
struct vf610_adc_feature {
enum clk_sel clk_sel;
enum vol_ref vol_ref;
@@ -132,6 +148,8 @@
int clk_div;
int sample_rate;
int res_mode;
+ u32 lst_adder_index;
+ u32 default_sample_time;
bool calibration;
bool ovwren;
@@ -155,11 +173,13 @@
};
static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
+static const u32 vf610_lst_adder[] = { 3, 5, 7, 9, 13, 17, 21, 25 };
static inline void vf610_adc_calculate_rates(struct vf610_adc *info)
{
struct vf610_adc_feature *adc_feature = &info->adc_feature;
unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk);
+ u32 adck_period, lst_addr_min;
int divisor, i;
adck_rate = info->max_adck_rate[adc_feature->conv_mode];
@@ -174,6 +194,19 @@
}
/*
+ * Determine the long sample time adder value to be used based
+ * on the default minimum sample time provided.
+ */
+ adck_period = NSEC_PER_SEC / adck_rate;
+ lst_addr_min = adc_feature->default_sample_time / adck_period;
+ for (i = 0; i < ARRAY_SIZE(vf610_lst_adder); i++) {
+ if (vf610_lst_adder[i] > lst_addr_min) {
+ adc_feature->lst_adder_index = i;
+ break;
+ }
+ }
+
+ /*
* Calculate ADC sample frequencies
* Sample time unit is ADCK cycles. ADCK clk source is ipg clock,
* which is the same as bus clock.
@@ -182,12 +215,13 @@
* SFCAdder: fixed to 6 ADCK cycles
* AverageNum: 1, 4, 8, 16, 32 samples for hardware average.
* BCT (Base Conversion Time): fixed to 25 ADCK cycles for 12 bit mode
- * LSTAdder(Long Sample Time): fixed to 3 ADCK cycles
+ * LSTAdder(Long Sample Time): 3, 5, 7, 9, 13, 17, 21, 25 ADCK cycles
*/
adck_rate = ipg_rate / info->adc_feature.clk_div;
for (i = 0; i < ARRAY_SIZE(vf610_hw_avgs); i++)
info->sample_freq_avail[i] =
- adck_rate / (6 + vf610_hw_avgs[i] * (25 + 3));
+ adck_rate / (6 + vf610_hw_avgs[i] *
+ (25 + vf610_lst_adder[adc_feature->lst_adder_index]));
}
static inline void vf610_adc_cfg_init(struct vf610_adc *info)
@@ -347,8 +381,40 @@
break;
}
- /* Use the short sample mode */
- cfg_data &= ~(VF610_ADC_ADLSMP_LONG | VF610_ADC_ADSTS_MASK);
+ /*
+ * Set ADLSMP and ADSTS based on the Long Sample Time Adder value
+ * determined.
+ */
+ switch (adc_feature->lst_adder_index) {
+ case VF610_ADCK_CYCLES_3:
+ break;
+ case VF610_ADCK_CYCLES_5:
+ cfg_data |= VF610_ADC_ADSTS_SHORT;
+ break;
+ case VF610_ADCK_CYCLES_7:
+ cfg_data |= VF610_ADC_ADSTS_NORMAL;
+ break;
+ case VF610_ADCK_CYCLES_9:
+ cfg_data |= VF610_ADC_ADSTS_LONG;
+ break;
+ case VF610_ADCK_CYCLES_13:
+ cfg_data |= VF610_ADC_ADLSMP_LONG;
+ break;
+ case VF610_ADCK_CYCLES_17:
+ cfg_data |= VF610_ADC_ADLSMP_LONG;
+ cfg_data |= VF610_ADC_ADSTS_SHORT;
+ break;
+ case VF610_ADCK_CYCLES_21:
+ cfg_data |= VF610_ADC_ADLSMP_LONG;
+ cfg_data |= VF610_ADC_ADSTS_NORMAL;
+ break;
+ case VF610_ADCK_CYCLES_25:
+ cfg_data |= VF610_ADC_ADLSMP_LONG;
+ cfg_data |= VF610_ADC_ADSTS_NORMAL;
+ break;
+ default:
+ dev_err(info->dev, "error in sample time select\n");
+ }
/* update hardware average selection */
cfg_data &= ~VF610_ADC_AVGS_MASK;
@@ -635,7 +701,7 @@
struct vf610_adc *info = iio_priv(indio_dev);
if ((readval == NULL) ||
- (!(reg % 4) || (reg > VF610_REG_ADC_PCTL)))
+ ((reg % 4) || (reg > VF610_REG_ADC_PCTL)))
return -EINVAL;
*readval = readl(info->regs + reg);
@@ -713,6 +779,11 @@
of_property_read_u32_array(pdev->dev.of_node, "fsl,adck-max-frequency",
info->max_adck_rate, 3);
+ ret = of_property_read_u32(pdev->dev.of_node, "min-sample-time",
+ &info->adc_feature.default_sample_time);
+ if (ret)
+ info->adc_feature.default_sample_time = DEFAULT_SAMPLE_TIME;
+
platform_set_drvdata(pdev, indio_dev);
init_completion(&info->completion);
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index 9a40097..d338bb5 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -700,7 +700,6 @@
.remove = ssp_remove,
.driver = {
.pm = &ssp_pm_ops,
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(ssp_of_match),
.name = "sensorhub"
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index 8086cbc..2e7fdb5 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -126,6 +126,9 @@
int err, i = 0;
struct st_sensor_data *sdata = iio_priv(indio_dev);
+ if (sdata->sensor_settings->fs.addr == 0)
+ return 0;
+
err = st_sensors_match_fs(sdata->sensor_settings, fs, &i);
if (err < 0)
goto st_accel_set_fullscale_error;
@@ -479,46 +482,43 @@
int num_sensors_list,
const struct st_sensor_settings *sensor_settings)
{
- u8 wai;
int i, n, err;
+ u8 wai;
struct st_sensor_data *sdata = iio_priv(indio_dev);
+ for (i = 0; i < num_sensors_list; i++) {
+ for (n = 0; n < ST_SENSORS_MAX_4WAI; n++) {
+ if (strcmp(indio_dev->name,
+ sensor_settings[i].sensors_supported[n]) == 0) {
+ break;
+ }
+ }
+ if (n < ST_SENSORS_MAX_4WAI)
+ break;
+ }
+ if (i == num_sensors_list) {
+ dev_err(&indio_dev->dev, "device name %s not recognized.\n",
+ indio_dev->name);
+ return -ENODEV;
+ }
+
err = sdata->tf->read_byte(&sdata->tb, sdata->dev,
- ST_SENSORS_DEFAULT_WAI_ADDRESS, &wai);
+ sensor_settings[i].wai_addr, &wai);
if (err < 0) {
dev_err(&indio_dev->dev, "failed to read Who-Am-I register.\n");
- goto read_wai_error;
+ return err;
}
- for (i = 0; i < num_sensors_list; i++) {
- if (sensor_settings[i].wai == wai)
- break;
- }
- if (i == num_sensors_list)
- goto device_not_supported;
-
- for (n = 0; n < ARRAY_SIZE(sensor_settings[i].sensors_supported); n++) {
- if (strcmp(indio_dev->name,
- &sensor_settings[i].sensors_supported[n][0]) == 0)
- break;
- }
- if (n == ARRAY_SIZE(sensor_settings[i].sensors_supported)) {
- dev_err(&indio_dev->dev, "device name \"%s\" and WhoAmI (0x%02x) mismatch",
- indio_dev->name, wai);
- goto sensor_name_mismatch;
+ if (sensor_settings[i].wai != wai) {
+ dev_err(&indio_dev->dev, "%s: WhoAmI mismatch (0x%x).\n",
+ indio_dev->name, wai);
+ return -EINVAL;
}
sdata->sensor_settings =
(struct st_sensor_settings *)&sensor_settings[i];
return i;
-
-device_not_supported:
- dev_err(&indio_dev->dev, "device not supported: WhoAmI (0x%x).\n", wai);
-sensor_name_mismatch:
- err = -ENODEV;
-read_wai_error:
- return err;
}
EXPORT_SYMBOL(st_sensors_check_device_support);
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c
index f03b92f..c067e68 100644
--- a/drivers/iio/dac/ad5064.c
+++ b/drivers/iio/dac/ad5064.c
@@ -630,7 +630,6 @@
static struct i2c_driver ad5064_i2c_driver = {
.driver = {
.name = "ad5064",
- .owner = THIS_MODULE,
},
.probe = ad5064_i2c_probe,
.remove = ad5064_i2c_remove,
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 9de4c4d..130de9b 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -593,7 +593,6 @@
static struct i2c_driver ad5380_i2c_driver = {
.driver = {
.name = "ad5380",
- .owner = THIS_MODULE,
},
.probe = ad5380_i2c_probe,
.remove = ad5380_i2c_remove,
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 46bb62a..07e17d7 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -569,7 +569,6 @@
static struct i2c_driver ad5446_i2c_driver = {
.driver = {
.name = "ad5446",
- .owner = THIS_MODULE,
},
.probe = ad5446_i2c_probe,
.remove = ad5446_i2c_remove,
diff --git a/drivers/iio/dac/max5821.c b/drivers/iio/dac/max5821.c
index 6e91449..28b8748 100644
--- a/drivers/iio/dac/max5821.c
+++ b/drivers/iio/dac/max5821.c
@@ -392,7 +392,6 @@
.driver = {
.name = "max5821",
.pm = MAX5821_PM_OPS,
- .owner = THIS_MODULE,
},
.probe = max5821_probe,
.remove = max5821_remove,
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index 10a0dfc..9890c81 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -72,7 +72,6 @@
for (i = ADF4350_REG5; i >= ADF4350_REG0; i--) {
if ((st->regs_hw[i] != st->regs[i]) ||
((i == ADF4350_REG0) && doublebuf)) {
-
switch (i) {
case ADF4350_REG1:
case ADF4350_REG4:
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index b3d0e94..8d24393 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -53,7 +53,8 @@
config BMG160
tristate "BOSCH BMG160 Gyro Sensor"
depends on I2C
- select IIO_TRIGGERED_BUFFER if IIO_BUFFER
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Bosch BMG160 Tri-axis Gyro Sensor
driver. This driver also supports BMI055 gyroscope.
diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c
index 591bd55..26de876 100644
--- a/drivers/iio/gyro/adis16136.c
+++ b/drivers/iio/gyro/adis16136.c
@@ -473,6 +473,7 @@
ID_ADIS16133,
ID_ADIS16135,
ID_ADIS16136,
+ ID_ADIS16137,
};
static const struct adis16136_chip_info adis16136_chip_info[] = {
@@ -488,6 +489,10 @@
.precision = IIO_DEGREE_TO_RAD(450),
.fullscale = 24623,
},
+ [ID_ADIS16137] = {
+ .precision = IIO_DEGREE_TO_RAD(1000),
+ .fullscale = 24609,
+ },
};
static int adis16136_probe(struct spi_device *spi)
@@ -557,6 +562,7 @@
{ "adis16133", ID_ADIS16133 },
{ "adis16135", ID_ADIS16135 },
{ "adis16136", ID_ADIS16136 },
+ { "adis16137", ID_ADIS16137 },
{ }
};
MODULE_DEVICE_TABLE(spi, adis16136_ids);
diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
index 75fe0ed..00c6ad9 100644
--- a/drivers/iio/gyro/adis16260.c
+++ b/drivers/iio/gyro/adis16260.c
@@ -101,19 +101,24 @@
#define ADIS16260_SCAN_TEMP 3
#define ADIS16260_SCAN_ANGL 4
-/* Power down the device */
-static int adis16260_stop_device(struct iio_dev *indio_dev)
-{
- struct adis *adis = iio_priv(indio_dev);
- int ret;
- u16 val = ADIS16260_SLP_CNT_POWER_OFF;
+struct adis16260_chip_info {
+ unsigned int gyro_max_val;
+ unsigned int gyro_max_scale;
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
+};
- ret = adis_write_reg_16(adis, ADIS16260_SLP_CNT, val);
- if (ret)
- dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
+struct adis16260 {
+ const struct adis16260_chip_info *info;
- return ret;
-}
+ struct adis adis;
+};
+
+enum adis16260_type {
+ ADIS16251,
+ ADIS16260,
+ ADIS16266,
+};
static const struct iio_chan_spec adis16260_channels[] = {
ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
@@ -131,6 +136,55 @@
IIO_CHAN_SOFT_TIMESTAMP(5),
};
+static const struct iio_chan_spec adis16266_channels[] = {
+ ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
+ BIT(IIO_CHAN_INFO_CALIBBIAS) |
+ BIT(IIO_CHAN_INFO_CALIBSCALE),
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
+ ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+ ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+ ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct adis16260_chip_info adis16260_chip_info_table[] = {
+ [ADIS16251] = {
+ .gyro_max_scale = 80,
+ .gyro_max_val = IIO_RAD_TO_DEGREE(4368),
+ .channels = adis16260_channels,
+ .num_channels = ARRAY_SIZE(adis16260_channels),
+ },
+ [ADIS16260] = {
+ .gyro_max_scale = 320,
+ .gyro_max_val = IIO_RAD_TO_DEGREE(4368),
+ .channels = adis16260_channels,
+ .num_channels = ARRAY_SIZE(adis16260_channels),
+ },
+ [ADIS16266] = {
+ .gyro_max_scale = 14000,
+ .gyro_max_val = IIO_RAD_TO_DEGREE(3357),
+ .channels = adis16266_channels,
+ .num_channels = ARRAY_SIZE(adis16266_channels),
+ },
+};
+
+/* Power down the device */
+static int adis16260_stop_device(struct iio_dev *indio_dev)
+{
+ struct adis16260 *adis16260 = iio_priv(indio_dev);
+ int ret;
+ u16 val = ADIS16260_SLP_CNT_POWER_OFF;
+
+ ret = adis_write_reg_16(&adis16260->adis, ADIS16260_SLP_CNT, val);
+ if (ret)
+ dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
+
+ return ret;
+}
+
static const u8 adis16260_addresses[][2] = {
[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
};
@@ -140,7 +194,9 @@
int *val, int *val2,
long mask)
{
- struct adis *adis = iio_priv(indio_dev);
+ struct adis16260 *adis16260 = iio_priv(indio_dev);
+ const struct adis16260_chip_info *info = adis16260->info;
+ struct adis *adis = &adis16260->adis;
int ret;
u8 addr;
s16 val16;
@@ -152,15 +208,9 @@
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
- *val = 0;
- if (spi_get_device_id(adis->spi)->driver_data) {
- /* 0.01832 degree / sec */
- *val2 = IIO_DEGREE_TO_RAD(18320);
- } else {
- /* 0.07326 degree / sec */
- *val2 = IIO_DEGREE_TO_RAD(73260);
- }
- return IIO_VAL_INT_PLUS_MICRO;
+ *val = info->gyro_max_scale;
+ *val2 = info->gyro_max_val;
+ return IIO_VAL_FRACTIONAL;
case IIO_INCLI:
*val = 0;
*val2 = IIO_DEGREE_TO_RAD(36630);
@@ -224,7 +274,8 @@
int val2,
long mask)
{
- struct adis *adis = iio_priv(indio_dev);
+ struct adis16260 *adis16260 = iio_priv(indio_dev);
+ struct adis *adis = &adis16260->adis;
int ret;
u8 addr;
u8 t;
@@ -305,35 +356,42 @@
static int adis16260_probe(struct spi_device *spi)
{
+ const struct spi_device_id *id;
+ struct adis16260 *adis16260;
struct iio_dev *indio_dev;
- struct adis *adis;
int ret;
+ id = spi_get_device_id(spi);
+ if (!id)
+ return -ENODEV;
+
/* setup the industrialio driver allocated elements */
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis));
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16260));
if (!indio_dev)
return -ENOMEM;
- adis = iio_priv(indio_dev);
+ adis16260 = iio_priv(indio_dev);
/* this is only used for removal purposes */
spi_set_drvdata(spi, indio_dev);
- indio_dev->name = spi_get_device_id(spi)->name;
+ adis16260->info = &adis16260_chip_info_table[id->driver_data];
+
+ indio_dev->name = id->name;
indio_dev->dev.parent = &spi->dev;
indio_dev->info = &adis16260_info;
- indio_dev->channels = adis16260_channels;
- indio_dev->num_channels = ARRAY_SIZE(adis16260_channels);
+ indio_dev->channels = adis16260->info->channels;
+ indio_dev->num_channels = adis16260->info->num_channels;
indio_dev->modes = INDIO_DIRECT_MODE;
- ret = adis_init(adis, indio_dev, spi, &adis16260_data);
+ ret = adis_init(&adis16260->adis, indio_dev, spi, &adis16260_data);
if (ret)
return ret;
- ret = adis_setup_buffer_and_trigger(adis, indio_dev, NULL);
+ ret = adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL);
if (ret)
return ret;
/* Get the device into a sane initial state */
- ret = adis_initial_startup(adis);
+ ret = adis_initial_startup(&adis16260->adis);
if (ret)
goto error_cleanup_buffer_trigger;
ret = iio_device_register(indio_dev);
@@ -343,18 +401,18 @@
return 0;
error_cleanup_buffer_trigger:
- adis_cleanup_buffer_and_trigger(adis, indio_dev);
+ adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
return ret;
}
static int adis16260_remove(struct spi_device *spi)
{
struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct adis *adis = iio_priv(indio_dev);
+ struct adis16260 *adis16260 = iio_priv(indio_dev);
iio_device_unregister(indio_dev);
adis16260_stop_device(indio_dev);
- adis_cleanup_buffer_and_trigger(adis, indio_dev);
+ adis_cleanup_buffer_and_trigger(&adis16260->adis, indio_dev);
return 0;
}
@@ -364,11 +422,12 @@
* support for the on chip filtering.
*/
static const struct spi_device_id adis16260_id[] = {
- {"adis16260", 0},
- {"adis16265", 0},
- {"adis16250", 0},
- {"adis16255", 0},
- {"adis16251", 1},
+ {"adis16260", ADIS16260},
+ {"adis16265", ADIS16260},
+ {"adis16266", ADIS16266},
+ {"adis16250", ADIS16260},
+ {"adis16255", ADIS16260},
+ {"adis16251", ADIS16251},
{}
};
MODULE_DEVICE_TABLE(spi, adis16260_id);
diff --git a/drivers/iio/gyro/itg3200_core.c b/drivers/iio/gyro/itg3200_core.c
index f0fd940..c102a63 100644
--- a/drivers/iio/gyro/itg3200_core.c
+++ b/drivers/iio/gyro/itg3200_core.c
@@ -379,7 +379,6 @@
static struct i2c_driver itg3200_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "itg3200",
.pm = &itg3200_pm_ops,
},
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index ffe9664..4b993a5 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -131,6 +131,7 @@
static const struct st_sensor_settings st_gyro_sensors_settings[] = {
{
.wai = ST_GYRO_1_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = L3G4200D_GYRO_DEV_NAME,
[1] = LSM330DL_GYRO_DEV_NAME,
@@ -190,6 +191,7 @@
},
{
.wai = ST_GYRO_2_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = L3GD20_GYRO_DEV_NAME,
[1] = LSM330D_GYRO_DEV_NAME,
@@ -252,6 +254,7 @@
},
{
.wai = ST_GYRO_3_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = L3GD20_GYRO_DEV_NAME,
},
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
index 64480b1..6848451 100644
--- a/drivers/iio/gyro/st_gyro_i2c.c
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -99,7 +99,6 @@
static struct i2c_driver st_gyro_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "st-gyro-i2c",
.of_match_table = of_match_ptr(st_gyro_of_match),
},
diff --git a/drivers/iio/humidity/dht11.c b/drivers/iio/humidity/dht11.c
index 7d79a1a..1165b1c 100644
--- a/drivers/iio/humidity/dht11.c
+++ b/drivers/iio/humidity/dht11.c
@@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
+#include <linux/timekeeping.h>
#include <linux/iio/iio.h>
@@ -46,7 +47,8 @@
* Note that when reading the sensor actually 84 edges are detected, but
* since the last edge is not significant, we only store 83:
*/
-#define DHT11_EDGES_PER_READ (2*DHT11_BITS_PER_READ + DHT11_EDGES_PREAMBLE + 1)
+#define DHT11_EDGES_PER_READ (2 * DHT11_BITS_PER_READ + \
+ DHT11_EDGES_PREAMBLE + 1)
/* Data transmission timing (nano seconds) */
#define DHT11_START_TRANSMISSION 18 /* ms */
@@ -62,6 +64,7 @@
int irq;
struct completion completion;
+ /* The iio sysfs interface doesn't prevent concurrent reads: */
struct mutex lock;
s64 timestamp;
@@ -87,32 +90,20 @@
return ret;
}
-static int dht11_decode(struct dht11 *dht11, int offset)
+static int dht11_decode(struct dht11 *dht11, int offset, int timeres)
{
- int i, t, timing[DHT11_BITS_PER_READ], threshold,
- timeres = DHT11_SENSOR_RESPONSE;
+ int i, t, timing[DHT11_BITS_PER_READ], threshold;
unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
- /* Calculate timestamp resolution */
- for (i = 1; i < dht11->num_edges; ++i) {
- t = dht11->edges[i].ts - dht11->edges[i-1].ts;
- if (t > 0 && t < timeres)
- timeres = t;
- }
- if (2*timeres > DHT11_DATA_BIT_HIGH) {
- pr_err("dht11: timeresolution %d too bad for decoding\n",
- timeres);
- return -EIO;
- }
threshold = DHT11_DATA_BIT_HIGH / timeres;
- if (DHT11_DATA_BIT_LOW/timeres + 1 >= threshold)
+ 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)
+ 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;
}
@@ -126,7 +117,7 @@
if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
return -EIO;
- dht11->timestamp = iio_get_time_ns();
+ dht11->timestamp = ktime_get_real_ns();
if (hum_int < 20) { /* DHT22 */
dht11->temperature = (((temp_int & 0x7f) << 8) + temp_dec) *
((temp_int & 0x80) ? -100 : 100);
@@ -154,7 +145,7 @@
/* TODO: Consider making the handler safe for IRQ sharing */
if (dht11->num_edges < DHT11_EDGES_PER_READ && dht11->num_edges >= 0) {
- dht11->edges[dht11->num_edges].ts = iio_get_time_ns();
+ dht11->edges[dht11->num_edges].ts = ktime_get_real_ns();
dht11->edges[dht11->num_edges++].value =
gpio_get_value(dht11->gpio);
@@ -166,14 +157,26 @@
}
static int dht11_read_raw(struct iio_dev *iio_dev,
- const struct iio_chan_spec *chan,
+ const struct iio_chan_spec *chan,
int *val, int *val2, long m)
{
struct dht11 *dht11 = iio_priv(iio_dev);
- int ret;
+ int ret, timeres;
mutex_lock(&dht11->lock);
- if (dht11->timestamp + DHT11_DATA_VALID_TIME < iio_get_time_ns()) {
+ if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) {
+ timeres = ktime_get_resolution_ns();
+ if (DHT11_DATA_BIT_HIGH < 2 * timeres) {
+ dev_err(dht11->dev, "timeresolution %dns too low\n",
+ timeres);
+ /* In theory a better clock could become available
+ * at some point ... and there is no error code
+ * that really fits better.
+ */
+ ret = -EAGAIN;
+ goto err;
+ }
+
reinit_completion(&dht11->completion);
dht11->num_edges = 0;
@@ -192,13 +195,13 @@
goto err;
ret = wait_for_completion_killable_timeout(&dht11->completion,
- HZ);
+ HZ);
free_irq(dht11->irq, iio_dev);
if (ret == 0 && dht11->num_edges < DHT11_EDGES_PER_READ - 1) {
dev_err(&iio_dev->dev,
- "Only %d signal edges detected\n",
+ "Only %d signal edges detected\n",
dht11->num_edges);
ret = -ETIMEDOUT;
}
@@ -206,9 +209,10 @@
goto err;
ret = dht11_decode(dht11,
- dht11->num_edges == DHT11_EDGES_PER_READ ?
+ dht11->num_edges == DHT11_EDGES_PER_READ ?
DHT11_EDGES_PREAMBLE :
- DHT11_EDGES_PREAMBLE - 2);
+ DHT11_EDGES_PREAMBLE - 2,
+ timeres);
if (ret)
goto err;
}
@@ -261,9 +265,10 @@
dht11 = iio_priv(iio);
dht11->dev = dev;
- dht11->gpio = ret = of_get_gpio(node, 0);
+ ret = of_get_gpio(node, 0);
if (ret < 0)
return ret;
+ dht11->gpio = ret;
ret = devm_gpio_request_one(dev, dht11->gpio, GPIOF_IN, pdev->name);
if (ret)
return ret;
@@ -274,7 +279,7 @@
return -EINVAL;
}
- dht11->timestamp = iio_get_time_ns() - DHT11_DATA_VALID_TIME - 1;
+ dht11->timestamp = ktime_get_real_ns() - DHT11_DATA_VALID_TIME - 1;
dht11->num_edges = -1;
platform_set_drvdata(pdev, iio);
diff --git a/drivers/iio/humidity/si7005.c b/drivers/iio/humidity/si7005.c
index bdd586e..91972cc 100644
--- a/drivers/iio/humidity/si7005.c
+++ b/drivers/iio/humidity/si7005.c
@@ -177,7 +177,6 @@
static struct i2c_driver si7005_driver = {
.driver = {
.name = "si7005",
- .owner = THIS_MODULE,
},
.probe = si7005_probe,
.id_table = si7005_id,
diff --git a/drivers/iio/imu/adis16400_core.c b/drivers/iio/imu/adis16400_core.c
index 2fd68f2..abc4c50 100644
--- a/drivers/iio/imu/adis16400_core.c
+++ b/drivers/iio/imu/adis16400_core.c
@@ -139,7 +139,9 @@
ADIS16360,
ADIS16362,
ADIS16364,
+ ADIS16367,
ADIS16400,
+ ADIS16445,
ADIS16448,
};
@@ -622,6 +624,17 @@
IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
};
+static const struct iio_chan_spec adis16445_channels[] = {
+ ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
+ ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
+ ADIS16400_GYRO_CHAN(Z, ADIS16400_ZGYRO_OUT, 16),
+ ADIS16400_ACCEL_CHAN(X, ADIS16400_XACCL_OUT, 16),
+ ADIS16400_ACCEL_CHAN(Y, ADIS16400_YACCL_OUT, 16),
+ ADIS16400_ACCEL_CHAN(Z, ADIS16400_ZACCL_OUT, 16),
+ ADIS16400_TEMP_CHAN(ADIS16448_TEMP_OUT, 12),
+ IIO_CHAN_SOFT_TIMESTAMP(ADIS16400_SCAN_TIMESTAMP),
+};
+
static const struct iio_chan_spec adis16448_channels[] = {
ADIS16400_GYRO_CHAN(X, ADIS16400_XGYRO_OUT, 16),
ADIS16400_GYRO_CHAN(Y, ADIS16400_YGYRO_OUT, 16),
@@ -696,7 +709,8 @@
[ADIS16300] = {
.channels = adis16300_channels,
.num_channels = ARRAY_SIZE(adis16300_channels),
- .flags = ADIS16400_HAS_SLOW_MODE,
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
+ ADIS16400_HAS_SERIAL_NUMBER,
.gyro_scale_micro = IIO_DEGREE_TO_RAD(50000), /* 0.05 deg/s */
.accel_scale_micro = 5884,
.temp_scale_nano = 140000000, /* 0.14 C */
@@ -763,6 +777,18 @@
.set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq,
},
+ [ADIS16367] = {
+ .channels = adis16350_channels,
+ .num_channels = ARRAY_SIZE(adis16350_channels),
+ .flags = ADIS16400_HAS_PROD_ID | ADIS16400_HAS_SLOW_MODE |
+ ADIS16400_HAS_SERIAL_NUMBER,
+ .gyro_scale_micro = IIO_DEGREE_TO_RAD(2000), /* 0.2 deg/s */
+ .accel_scale_micro = IIO_G_TO_M_S_2(3333), /* 3.333 mg */
+ .temp_scale_nano = 136000000, /* 0.136 C */
+ .temp_offset = 25000000 / 136000, /* 25 C = 0x00 */
+ .set_freq = adis16400_set_freq,
+ .get_freq = adis16400_get_freq,
+ },
[ADIS16400] = {
.channels = adis16400_channels,
.num_channels = ARRAY_SIZE(adis16400_channels),
@@ -774,13 +800,26 @@
.set_freq = adis16400_set_freq,
.get_freq = adis16400_get_freq,
},
+ [ADIS16445] = {
+ .channels = adis16445_channels,
+ .num_channels = ARRAY_SIZE(adis16445_channels),
+ .flags = ADIS16400_HAS_PROD_ID |
+ ADIS16400_HAS_SERIAL_NUMBER |
+ ADIS16400_BURST_DIAG_STAT,
+ .gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
+ .accel_scale_micro = IIO_G_TO_M_S_2(250), /* 1/4000 g */
+ .temp_scale_nano = 73860000, /* 0.07386 C */
+ .temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
+ .set_freq = adis16334_set_freq,
+ .get_freq = adis16334_get_freq,
+ },
[ADIS16448] = {
.channels = adis16448_channels,
.num_channels = ARRAY_SIZE(adis16448_channels),
.flags = ADIS16400_HAS_PROD_ID |
ADIS16400_HAS_SERIAL_NUMBER |
ADIS16400_BURST_DIAG_STAT,
- .gyro_scale_micro = IIO_DEGREE_TO_RAD(10000), /* 0.01 deg/s */
+ .gyro_scale_micro = IIO_DEGREE_TO_RAD(40000), /* 0.04 deg/s */
.accel_scale_micro = IIO_G_TO_M_S_2(833), /* 1/1200 g */
.temp_scale_nano = 73860000, /* 0.07386 C */
.temp_offset = 31000000 / 73860, /* 31 C = 0x00 */
@@ -926,6 +965,7 @@
static const struct spi_device_id adis16400_id[] = {
{"adis16300", ADIS16300},
+ {"adis16305", ADIS16300},
{"adis16334", ADIS16334},
{"adis16350", ADIS16350},
{"adis16354", ADIS16350},
@@ -934,8 +974,10 @@
{"adis16362", ADIS16362},
{"adis16364", ADIS16364},
{"adis16365", ADIS16360},
+ {"adis16367", ADIS16367},
{"adis16400", ADIS16400},
{"adis16405", ADIS16400},
+ {"adis16445", ADIS16445},
{"adis16448", ADIS16448},
{}
};
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index 989605d..b94bfd3 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -110,6 +110,10 @@
struct adis16480_chip_info {
unsigned int num_channels;
const struct iio_chan_spec *channels;
+ unsigned int gyro_max_val;
+ unsigned int gyro_max_scale;
+ unsigned int accel_max_val;
+ unsigned int accel_max_scale;
};
struct adis16480 {
@@ -497,19 +501,21 @@
static int adis16480_read_raw(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, int *val, int *val2, long info)
{
+ struct adis16480 *st = iio_priv(indio_dev);
+
switch (info) {
case IIO_CHAN_INFO_RAW:
return adis_single_conversion(indio_dev, chan, 0, val);
case IIO_CHAN_INFO_SCALE:
switch (chan->type) {
case IIO_ANGL_VEL:
- *val = 0;
- *val2 = IIO_DEGREE_TO_RAD(20000); /* 0.02 degree/sec */
- return IIO_VAL_INT_PLUS_MICRO;
+ *val = st->chip_info->gyro_max_scale;
+ *val2 = st->chip_info->gyro_max_val;
+ return IIO_VAL_FRACTIONAL;
case IIO_ACCEL:
- *val = 0;
- *val2 = IIO_G_TO_M_S_2(800); /* 0.8 mg */
- return IIO_VAL_INT_PLUS_MICRO;
+ *val = st->chip_info->accel_max_scale;
+ *val2 = st->chip_info->accel_max_val;
+ return IIO_VAL_FRACTIONAL;
case IIO_MAGN:
*val = 0;
*val2 = 100; /* 0.0001 gauss */
@@ -674,18 +680,39 @@
[ADIS16375] = {
.channels = adis16485_channels,
.num_channels = ARRAY_SIZE(adis16485_channels),
+ /*
+ * storing the value in rad/degree and the scale in degree
+ * gives us the result in rad and better precession than
+ * storing the scale directly in rad.
+ */
+ .gyro_max_val = IIO_RAD_TO_DEGREE(22887),
+ .gyro_max_scale = 300,
+ .accel_max_val = IIO_M_S_2_TO_G(21973),
+ .accel_max_scale = 18,
},
[ADIS16480] = {
.channels = adis16480_channels,
.num_channels = ARRAY_SIZE(adis16480_channels),
+ .gyro_max_val = IIO_RAD_TO_DEGREE(22500),
+ .gyro_max_scale = 450,
+ .accel_max_val = IIO_M_S_2_TO_G(12500),
+ .accel_max_scale = 5,
},
[ADIS16485] = {
.channels = adis16485_channels,
.num_channels = ARRAY_SIZE(adis16485_channels),
+ .gyro_max_val = IIO_RAD_TO_DEGREE(22500),
+ .gyro_max_scale = 450,
+ .accel_max_val = IIO_M_S_2_TO_G(20000),
+ .accel_max_scale = 5,
},
[ADIS16488] = {
.channels = adis16480_channels,
.num_channels = ARRAY_SIZE(adis16480_channels),
+ .gyro_max_val = IIO_RAD_TO_DEGREE(22500),
+ .gyro_max_scale = 450,
+ .accel_max_val = IIO_M_S_2_TO_G(22500),
+ .accel_max_scale = 18,
},
};
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 65ce868..f0e0609 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -690,6 +690,10 @@
/* constant IIO attribute */
static IIO_CONST_ATTR_SAMP_FREQ_AVAIL("10 20 50 100 200 500");
+static IIO_CONST_ATTR(in_anglvel_scale_available,
+ "0.000133090 0.000266181 0.000532362 0.001064724");
+static IIO_CONST_ATTR(in_accel_scale_available,
+ "0.000598 0.001196 0.002392 0.004785");
static IIO_DEV_ATTR_SAMP_FREQ(S_IRUGO | S_IWUSR, inv_fifo_rate_show,
inv_mpu6050_fifo_rate_store);
static IIO_DEVICE_ATTR(in_gyro_matrix, S_IRUGO, inv_attr_show, NULL,
@@ -702,6 +706,8 @@
&iio_dev_attr_in_accel_matrix.dev_attr.attr,
&iio_dev_attr_sampling_frequency.dev_attr.attr,
&iio_const_attr_sampling_frequency_available.dev_attr.attr,
+ &iio_const_attr_in_accel_scale_available.dev_attr.attr,
+ &iio_const_attr_in_anglvel_scale_available.dev_attr.attr,
NULL,
};
@@ -921,7 +927,6 @@
.remove = inv_mpu_remove,
.id_table = inv_mpu_id,
.driver = {
- .owner = THIS_MODULE,
.name = "inv-mpu6050",
.pm = INV_MPU6050_PMOPS,
.acpi_match_table = ACPI_PTR(inv_acpi_match),
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c
index 462a010..82cdf50 100644
--- a/drivers/iio/imu/kmx61.c
+++ b/drivers/iio/imu/kmx61.c
@@ -1363,7 +1363,7 @@
if (client->irq < 0)
client->irq = kmx61_gpio_probe(client, data);
- if (client->irq >= 0) {
+ if (client->irq > 0) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
kmx61_data_rdy_trig_poll,
kmx61_event_handler,
@@ -1445,10 +1445,10 @@
err_iio_unregister_acc:
iio_device_unregister(data->acc_indio_dev);
err_buffer_cleanup_mag:
- if (client->irq >= 0)
+ if (client->irq > 0)
iio_triggered_buffer_cleanup(data->mag_indio_dev);
err_buffer_cleanup_acc:
- if (client->irq >= 0)
+ if (client->irq > 0)
iio_triggered_buffer_cleanup(data->acc_indio_dev);
err_trigger_unregister_motion:
iio_trigger_unregister(data->motion_trig);
@@ -1472,7 +1472,7 @@
iio_device_unregister(data->acc_indio_dev);
iio_device_unregister(data->mag_indio_dev);
- if (client->irq >= 0) {
+ if (client->irq > 0) {
iio_triggered_buffer_cleanup(data->acc_indio_dev);
iio_triggered_buffer_cleanup(data->mag_indio_dev);
iio_trigger_unregister(data->acc_dready_trig);
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 6eee1b0..d7e908a 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -71,8 +71,9 @@
if (avail >= to_wait) {
/* force a flush for non-blocking reads */
- if (!to_wait && !avail && to_flush)
- iio_buffer_flush_hwfifo(indio_dev, buf, to_flush);
+ if (!to_wait && avail < to_flush)
+ iio_buffer_flush_hwfifo(indio_dev, buf,
+ to_flush - avail);
return true;
}
@@ -90,9 +91,16 @@
/**
* iio_buffer_read_first_n_outer() - chrdev read for buffer access
+ * @filp: File structure pointer for the char device
+ * @buf: Destination buffer for iio buffer read
+ * @n: First n bytes to read
+ * @f_ps: Long offset provided by the user as a seek position
*
* This function relies on all buffer implementations having an
* iio_buffer as their first element.
+ *
+ * Return: negative values corresponding to error codes or ret != 0
+ * for ending the reading activity
**/
ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
size_t n, loff_t *f_ps)
@@ -100,8 +108,7 @@
struct iio_dev *indio_dev = filp->private_data;
struct iio_buffer *rb = indio_dev->buffer;
size_t datum_size;
- size_t to_wait = 0;
- size_t to_read;
+ size_t to_wait;
int ret;
if (!indio_dev->info)
@@ -119,14 +126,14 @@
if (!datum_size)
return 0;
- to_read = min_t(size_t, n / datum_size, rb->watermark);
-
- if (!(filp->f_flags & O_NONBLOCK))
- to_wait = to_read;
+ if (filp->f_flags & O_NONBLOCK)
+ to_wait = 0;
+ else
+ to_wait = min_t(size_t, n / datum_size, rb->watermark);
do {
ret = wait_event_interruptible(rb->pollq,
- iio_buffer_ready(indio_dev, rb, to_wait, to_read));
+ iio_buffer_ready(indio_dev, rb, to_wait, n / datum_size));
if (ret)
return ret;
@@ -143,6 +150,12 @@
/**
* iio_buffer_poll() - poll the buffer to find out if it has data
+ * @filp: File structure pointer for device access
+ * @wait: Poll table structure pointer for which the driver adds
+ * a wait queue
+ *
+ * Return: (POLLIN | POLLRDNORM) if data is available for reading
+ * or 0 for other cases
*/
unsigned int iio_buffer_poll(struct file *filp,
struct poll_table_struct *wait)
@@ -151,7 +164,7 @@
struct iio_buffer *rb = indio_dev->buffer;
if (!indio_dev->info)
- return -ENODEV;
+ return 0;
poll_wait(filp, &rb->pollq, wait);
if (iio_buffer_ready(indio_dev, rb, rb->watermark, 0))
@@ -1136,7 +1149,7 @@
EXPORT_SYMBOL_GPL(iio_scan_mask_query);
/**
- * struct iio_demux_table() - table describing demux memcpy ops
+ * struct iio_demux_table - table describing demux memcpy ops
* @from: index to copy from
* @to: index to copy to
* @length: how many bytes to copy
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 3524b0d..b3fcc2c 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -81,6 +81,14 @@
[IIO_MOD_X] = "x",
[IIO_MOD_Y] = "y",
[IIO_MOD_Z] = "z",
+ [IIO_MOD_X_AND_Y] = "x&y",
+ [IIO_MOD_X_AND_Z] = "x&z",
+ [IIO_MOD_Y_AND_Z] = "y&z",
+ [IIO_MOD_X_AND_Y_AND_Z] = "x&y&z",
+ [IIO_MOD_X_OR_Y] = "x|y",
+ [IIO_MOD_X_OR_Z] = "x|z",
+ [IIO_MOD_Y_OR_Z] = "y|z",
+ [IIO_MOD_X_OR_Y_OR_Z] = "x|y|z",
[IIO_MOD_ROOT_SUM_SQUARED_X_Y] = "sqrt(x^2+y^2)",
[IIO_MOD_SUM_SQUARED_X_Y_Z] = "x^2+y^2+z^2",
[IIO_MOD_LIGHT_BOTH] = "both",
@@ -398,10 +406,16 @@
/**
* iio_format_value() - Formats a IIO value into its string representation
- * @buf: The buffer to which the formated value gets written
- * @type: One of the IIO_VAL_... constants. This decides how the val and val2
- * parameters are formatted.
- * @vals: pointer to the values, exact meaning depends on the type parameter.
+ * @buf: The buffer to which the formatted value gets written
+ * @type: One of the IIO_VAL_... constants. This decides how the val
+ * and val2 parameters are formatted.
+ * @size: Number of IIO value entries contained in vals
+ * @vals: Pointer to the values, exact meaning depends on the
+ * type parameter.
+ *
+ * Return: 0 by default, a negative number on failure or the
+ * total number of characters written for a type that belongs
+ * to the IIO_VAL_... constant.
*/
ssize_t iio_format_value(char *buf, unsigned int type, int size, int *vals)
{
@@ -1088,6 +1102,11 @@
/**
* iio_chrdev_open() - chrdev file open for buffer access and ioctls
+ * @inode: Inode structure for identifying the device in the file system
+ * @filp: File structure for iio device used to keep and later access
+ * private data
+ *
+ * Return: 0 on success or -EBUSY if the device is already opened
**/
static int iio_chrdev_open(struct inode *inode, struct file *filp)
{
@@ -1106,7 +1125,11 @@
/**
* iio_chrdev_release() - chrdev file close buffer access and ioctls
- **/
+ * @inode: Inode structure pointer for the char device
+ * @filp: File structure pointer for the char device
+ *
+ * Return: 0 for successful release
+ */
static int iio_chrdev_release(struct inode *inode, struct file *filp)
{
struct iio_dev *indio_dev = container_of(inode->i_cdev,
diff --git a/drivers/iio/industrialio-event.c b/drivers/iio/industrialio-event.c
index 894d813..cae332b 100644
--- a/drivers/iio/industrialio-event.c
+++ b/drivers/iio/industrialio-event.c
@@ -32,6 +32,7 @@
* @dev_attr_list: list of event interface sysfs attribute
* @flags: file operations related flags including busy flag.
* @group: event interface sysfs attribute group
+ * @read_lock: lock to protect kfifo read operations
*/
struct iio_event_interface {
wait_queue_head_t wait;
@@ -75,6 +76,11 @@
/**
* iio_event_poll() - poll the event queue to find out if it has data
+ * @filep: File structure pointer to identify the device
+ * @wait: Poll table pointer to add the wait queue on
+ *
+ * Return: (POLLIN | POLLRDNORM) if data is available for reading
+ * or a negative error code on failure
*/
static unsigned int iio_event_poll(struct file *filep,
struct poll_table_struct *wait)
@@ -84,7 +90,7 @@
unsigned int events = 0;
if (!indio_dev->info)
- return -ENODEV;
+ return events;
poll_wait(filep, &ev_int->wait, wait);
diff --git a/drivers/iio/industrialio-trigger.c b/drivers/iio/industrialio-trigger.c
index d31098e..570606c 100644
--- a/drivers/iio/industrialio-trigger.c
+++ b/drivers/iio/industrialio-trigger.c
@@ -40,7 +40,14 @@
/**
* iio_trigger_read_name() - retrieve useful identifying name
- **/
+ * @dev: device associated with the iio_trigger
+ * @attr: pointer to the device_attribute structure that is
+ * being processed
+ * @buf: buffer to print the name into
+ *
+ * Return: a negative number on failure or the number of written
+ * characters on success.
+ */
static ssize_t iio_trigger_read_name(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -288,10 +295,17 @@
/**
* iio_trigger_read_current() - trigger consumer sysfs query current trigger
+ * @dev: device associated with an industrial I/O device
+ * @attr: pointer to the device_attribute structure that
+ * is being processed
+ * @buf: buffer where the current trigger name will be printed into
*
* For trigger consumers the current_trigger interface allows the trigger
* used by the device to be queried.
- **/
+ *
+ * Return: a negative number on failure, the number of characters written
+ * on success or 0 if no trigger is available
+ */
static ssize_t iio_trigger_read_current(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -305,11 +319,18 @@
/**
* iio_trigger_write_current() - trigger consumer sysfs set current trigger
+ * @dev: device associated with an industrial I/O device
+ * @attr: device attribute that is being processed
+ * @buf: string buffer that holds the name of the trigger
+ * @len: length of the trigger name held by buf
*
* For trigger consumers the current_trigger interface allows the trigger
* used for this device to be specified at run time based on the trigger's
* name.
- **/
+ *
+ * Return: negative error code on failure or length of the buffer
+ * on success
+ */
static ssize_t iio_trigger_write_current(struct device *dev,
struct device_attribute *attr,
const char *buf,
diff --git a/drivers/iio/industrialio-triggered-buffer.c b/drivers/iio/industrialio-triggered-buffer.c
index 15a5341..4b2858b 100644
--- a/drivers/iio/industrialio-triggered-buffer.c
+++ b/drivers/iio/industrialio-triggered-buffer.c
@@ -24,8 +24,8 @@
/**
* iio_triggered_buffer_setup() - Setup triggered buffer and pollfunc
* @indio_dev: IIO device structure
- * @pollfunc_bh: Function which will be used as pollfunc bottom half
- * @pollfunc_th: Function which will be used as pollfunc top half
+ * @h: Function which will be used as pollfunc top half
+ * @thread: Function which will be used as pollfunc bottom half
* @setup_ops: Buffer setup functions to use for this device.
* If NULL the default setup functions for triggered
* buffers will be used.
@@ -42,8 +42,8 @@
* iio_triggered_buffer_cleanup().
*/
int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
- irqreturn_t (*pollfunc_bh)(int irq, void *p),
- irqreturn_t (*pollfunc_th)(int irq, void *p),
+ irqreturn_t (*h)(int irq, void *p),
+ irqreturn_t (*thread)(int irq, void *p),
const struct iio_buffer_setup_ops *setup_ops)
{
struct iio_buffer *buffer;
@@ -57,8 +57,8 @@
iio_device_attach_buffer(indio_dev, buffer);
- indio_dev->pollfunc = iio_alloc_pollfunc(pollfunc_bh,
- pollfunc_th,
+ indio_dev->pollfunc = iio_alloc_pollfunc(h,
+ thread,
IRQF_ONESHOT,
indio_dev,
"%s_consumer%d",
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index a5c5925..7ed859a 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -86,7 +86,7 @@
depends on I2C
tristate "Capella CM3323 color light sensor"
help
- Say Y here if you want to build a driver for Capela CM3323
+ Say Y here if you want to build a driver for Capella CM3323
color sensor.
To compile this driver as a module, choose M here: the module will
@@ -168,6 +168,17 @@
To compile this driver as a module, choose M here:
the module will be called jsa1212.
+config RPR0521
+ tristate "ROHM RPR0521 ALS and proximity sensor driver"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Say Y here if you want to build support for ROHM's RPR0521
+ ambient light and proximity sensor device.
+
+ To compile this driver as a module, choose M here:
+ the module will be called rpr0521.
+
config SENSORS_LM3533
tristate "LM3533 ambient light sensor"
depends on MFD_LM3533
@@ -199,6 +210,27 @@
This driver can also be built as a module. If so, the module
will be called ltr501.
+config OPT3001
+ tristate "Texas Instruments OPT3001 Light Sensor"
+ depends on I2C
+ help
+ If you say Y or M here, you get support for Texas Instruments
+ OPT3001 Ambient Light Sensor.
+
+ If built as a dynamically linked module, it will be called
+ opt3001.
+
+config PA12203001
+ tristate "TXC PA12203001 light and proximity sensor"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ If you say yes here you get support for the TXC PA12203001
+ ambient light and proximity sensor.
+
+ This driver can also be built as a module. If so, the module
+ will be called pa12203001.
+
config STK3310
tristate "STK3310 ALS and proximity sensor"
depends on I2C
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index e2d50fd..91c74c0 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -19,6 +19,9 @@
obj-$(CONFIG_JSA1212) += jsa1212.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_LTR501) += ltr501.o
+obj-$(CONFIG_OPT3001) += opt3001.o
+obj-$(CONFIG_PA12203001) += pa12203001.o
+obj-$(CONFIG_RPR0521) += rpr0521.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
obj-$(CONFIG_STK3310) += stk3310.o
obj-$(CONFIG_TCS3414) += tcs3414.o
diff --git a/drivers/iio/light/acpi-als.c b/drivers/iio/light/acpi-als.c
index 1dafa07..60537ec 100644
--- a/drivers/iio/light/acpi-als.c
+++ b/drivers/iio/light/acpi-als.c
@@ -65,20 +65,20 @@
* to acpi_als_channels[], the evt_buffer below will grow
* automatically.
*/
-#define EVT_NR_SOURCES ARRAY_SIZE(acpi_als_channels)
-#define EVT_BUFFER_SIZE \
- (sizeof(s64) + (EVT_NR_SOURCES * sizeof(s32)))
+#define ACPI_ALS_EVT_NR_SOURCES ARRAY_SIZE(acpi_als_channels)
+#define ACPI_ALS_EVT_BUFFER_SIZE \
+ (sizeof(s64) + (ACPI_ALS_EVT_NR_SOURCES * sizeof(s32)))
struct acpi_als {
struct acpi_device *device;
struct mutex lock;
- s32 evt_buffer[EVT_BUFFER_SIZE];
+ s32 evt_buffer[ACPI_ALS_EVT_BUFFER_SIZE];
};
/*
* All types of properties the ACPI0008 block can report. The ALI, ALC, ALT
- * and ALP can all be handled by als_read_value() below, while the ALR is
+ * and ALP can all be handled by acpi_als_read_value() below, while the ALR is
* special.
*
* The _ALR property returns tables that can be used to fine-tune the values
@@ -93,7 +93,7 @@
#define ACPI_ALS_POLLING "_ALP"
#define ACPI_ALS_TABLES "_ALR"
-static int als_read_value(struct acpi_als *als, char *prop, s32 *val)
+static int acpi_als_read_value(struct acpi_als *als, char *prop, s32 *val)
{
unsigned long long temp_val;
acpi_status status;
@@ -122,11 +122,11 @@
mutex_lock(&als->lock);
- memset(buffer, 0, EVT_BUFFER_SIZE);
+ memset(buffer, 0, ACPI_ALS_EVT_BUFFER_SIZE);
switch (event) {
case ACPI_ALS_NOTIFY_ILLUMINANCE:
- ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &val);
+ ret = acpi_als_read_value(als, ACPI_ALS_ILLUMINANCE, &val);
if (ret < 0)
goto out;
*buffer++ = val;
@@ -159,7 +159,7 @@
if (chan->type != IIO_LIGHT)
return -EINVAL;
- ret = als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val);
+ ret = acpi_als_read_value(als, ACPI_ALS_ILLUMINANCE, &temp_val);
if (ret < 0)
return ret;
diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c
index 9ddde0c..e1b9fa5 100644
--- a/drivers/iio/light/apds9300.c
+++ b/drivers/iio/light/apds9300.c
@@ -515,7 +515,6 @@
static struct i2c_driver apds9300_driver = {
.driver = {
.name = APDS9300_DRV_NAME,
- .owner = THIS_MODULE,
.pm = APDS9300_PM_OPS,
},
.probe = apds9300_probe,
diff --git a/drivers/iio/light/bh1750.c b/drivers/iio/light/bh1750.c
index 564c2b3..8b41643 100644
--- a/drivers/iio/light/bh1750.c
+++ b/drivers/iio/light/bh1750.c
@@ -319,7 +319,6 @@
static struct i2c_driver bh1750_driver = {
.driver = {
.name = "bh1750",
- .owner = THIS_MODULE,
.pm = BH1750_PM_OPS,
},
.probe = bh1750_probe,
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index 5d12ae54..d6fd0da 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -353,12 +353,12 @@
{ .compatible = "capella,cm32181" },
{ }
};
+MODULE_DEVICE_TABLE(of, cm32181_of_match);
static struct i2c_driver cm32181_driver = {
.driver = {
.name = "cm32181",
.of_match_table = of_match_ptr(cm32181_of_match),
- .owner = THIS_MODULE,
},
.id_table = cm32181_id,
.probe = cm32181_probe,
diff --git a/drivers/iio/light/cm3232.c b/drivers/iio/light/cm3232.c
index 39c8d99..fe89b68 100644
--- a/drivers/iio/light/cm3232.c
+++ b/drivers/iio/light/cm3232.c
@@ -417,11 +417,11 @@
{.compatible = "capella,cm3232"},
{}
};
+MODULE_DEVICE_TABLE(of, cm3232_of_match);
static struct i2c_driver cm3232_driver = {
.driver = {
.name = "cm3232",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(cm3232_of_match),
#ifdef CONFIG_PM_SLEEP
.pm = &cm3232_pm_ops,
diff --git a/drivers/iio/light/cm3323.c b/drivers/iio/light/cm3323.c
index a1d4905..d823c11 100644
--- a/drivers/iio/light/cm3323.c
+++ b/drivers/iio/light/cm3323.c
@@ -29,7 +29,7 @@
#define CM3323_CONF_SD_BIT BIT(0) /* sensor disable */
#define CM3323_CONF_AF_BIT BIT(1) /* auto/manual force mode */
-#define CM3323_CONF_IT_MASK (BIT(4) | BIT(5) | BIT(6))
+#define CM3323_CONF_IT_MASK GENMASK(6, 4)
#define CM3323_CONF_IT_SHIFT 4
#define CM3323_INT_TIME_AVAILABLE "0.04 0.08 0.16 0.32 0.64 1.28"
@@ -133,9 +133,11 @@
return ret;
data->reg_conf = reg_conf;
+
return 0;
}
}
+
return -EINVAL;
}
@@ -148,6 +150,7 @@
if (bits >= ARRAY_SIZE(cm3323_int_time))
return -EINVAL;
+
return bits;
}
@@ -155,7 +158,7 @@
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
{
- int i, ret;
+ int ret;
struct cm3323_data *data = iio_priv(indio_dev);
switch (mask) {
@@ -172,14 +175,14 @@
return IIO_VAL_INT;
case IIO_CHAN_INFO_INT_TIME:
mutex_lock(&data->mutex);
- i = cm3323_get_it_bits(data);
- if (i < 0) {
+ ret = cm3323_get_it_bits(data);
+ if (ret < 0) {
mutex_unlock(&data->mutex);
- return -EINVAL;
+ return ret;
}
- *val = cm3323_int_time[i].val;
- *val2 = cm3323_int_time[i].val2;
+ *val = cm3323_int_time[ret].val;
+ *val2 = cm3323_int_time[ret].val2;
mutex_unlock(&data->mutex);
return IIO_VAL_INT_PLUS_MICRO;
@@ -243,11 +246,13 @@
dev_err(&client->dev, "cm3323 chip init failed\n");
return ret;
}
+
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "failed to register iio dev\n");
goto err_init;
}
+
return 0;
err_init:
cm3323_disable(indio_dev);
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
index 39fc67e..c8d7b5e 100644
--- a/drivers/iio/light/cm36651.c
+++ b/drivers/iio/light/cm36651.c
@@ -731,12 +731,12 @@
{ .compatible = "capella,cm36651" },
{ }
};
+MODULE_DEVICE_TABLE(of, cm36651_of_match);
static struct i2c_driver cm36651_driver = {
.driver = {
.name = "cm36651",
.of_match_table = cm36651_of_match,
- .owner = THIS_MODULE,
},
.probe = cm36651_probe,
.remove = cm36651_remove,
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
index 32b6449..6d41086 100644
--- a/drivers/iio/light/gp2ap020a00f.c
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -1634,13 +1634,13 @@
{ .compatible = "sharp,gp2ap020a00f" },
{ }
};
+MODULE_DEVICE_TABLE(of, gp2ap020a00f_of_match);
#endif
static struct i2c_driver gp2ap020a00f_driver = {
.driver = {
.name = GP2A_I2C_NAME,
.of_match_table = of_match_ptr(gp2ap020a00f_of_match),
- .owner = THIS_MODULE,
},
.probe = gp2ap020a00f_probe,
.remove = gp2ap020a00f_remove,
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index 0d24847..45ca056 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -284,8 +284,7 @@
goto error_free_dev_mem;
}
- indio_dev->num_channels =
- ARRAY_SIZE(prox_channels);
+ indio_dev->num_channels = ARRAY_SIZE(prox_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &prox_info;
indio_dev->name = name;
diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c
index c82f4a6..e2945a2 100644
--- a/drivers/iio/light/isl29125.c
+++ b/drivers/iio/light/isl29125.c
@@ -197,9 +197,21 @@
return IRQ_HANDLED;
}
+static IIO_CONST_ATTR(scale_available, "0.005722 0.152590");
+
+static struct attribute *isl29125_attributes[] = {
+ &iio_const_attr_scale_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group isl29125_attribute_group = {
+ .attrs = isl29125_attributes,
+};
+
static const struct iio_info isl29125_info = {
.read_raw = isl29125_read_raw,
.write_raw = isl29125_write_raw,
+ .attrs = &isl29125_attribute_group,
.driver_module = THIS_MODULE,
};
@@ -334,7 +346,6 @@
.driver = {
.name = ISL29125_DRV_NAME,
.pm = &isl29125_pm_ops,
- .owner = THIS_MODULE,
},
.probe = isl29125_probe,
.remove = isl29125_remove,
diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c
index 3a3af89..c4e8c6b 100644
--- a/drivers/iio/light/jsa1212.c
+++ b/drivers/iio/light/jsa1212.c
@@ -457,7 +457,6 @@
.driver = {
.name = JSA1212_DRIVER_NAME,
.pm = JSA1212_PM_OPS,
- .owner = THIS_MODULE,
.acpi_match_table = ACPI_PTR(jsa1212_acpi_match),
},
.probe = jsa1212_probe,
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index b5a0e66..809a961 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -1551,7 +1551,6 @@
.name = LTR501_DRV_NAME,
.pm = <r501_pm_ops,
.acpi_match_table = ACPI_PTR(ltr_acpi_match),
- .owner = THIS_MODULE,
},
.probe = ltr501_probe,
.remove = ltr501_remove,
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
new file mode 100644
index 0000000..923aa6a
--- /dev/null
+++ b/drivers/iio/light/opt3001.c
@@ -0,0 +1,804 @@
+/**
+ * opt3001.c - Texas Instruments OPT3001 Light Sensor
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Andreas Dannenberg <dannenberg@ti.com>
+ * Based on previous work from: Felipe Balbi <balbi@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 of the License
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+
+#define OPT3001_RESULT 0x00
+#define OPT3001_CONFIGURATION 0x01
+#define OPT3001_LOW_LIMIT 0x02
+#define OPT3001_HIGH_LIMIT 0x03
+#define OPT3001_MANUFACTURER_ID 0x7e
+#define OPT3001_DEVICE_ID 0x7f
+
+#define OPT3001_CONFIGURATION_RN_MASK (0xf << 12)
+#define OPT3001_CONFIGURATION_RN_AUTO (0xc << 12)
+
+#define OPT3001_CONFIGURATION_CT BIT(11)
+
+#define OPT3001_CONFIGURATION_M_MASK (3 << 9)
+#define OPT3001_CONFIGURATION_M_SHUTDOWN (0 << 9)
+#define OPT3001_CONFIGURATION_M_SINGLE (1 << 9)
+#define OPT3001_CONFIGURATION_M_CONTINUOUS (2 << 9) /* also 3 << 9 */
+
+#define OPT3001_CONFIGURATION_OVF BIT(8)
+#define OPT3001_CONFIGURATION_CRF BIT(7)
+#define OPT3001_CONFIGURATION_FH BIT(6)
+#define OPT3001_CONFIGURATION_FL BIT(5)
+#define OPT3001_CONFIGURATION_L BIT(4)
+#define OPT3001_CONFIGURATION_POL BIT(3)
+#define OPT3001_CONFIGURATION_ME BIT(2)
+
+#define OPT3001_CONFIGURATION_FC_MASK (3 << 0)
+
+/* The end-of-conversion enable is located in the low-limit register */
+#define OPT3001_LOW_LIMIT_EOC_ENABLE 0xc000
+
+#define OPT3001_REG_EXPONENT(n) ((n) >> 12)
+#define OPT3001_REG_MANTISSA(n) ((n) & 0xfff)
+
+/*
+ * 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.
+ */
+#define OPT3001_RESULT_READY_TIMEOUT msecs_to_jiffies(1000)
+
+struct opt3001 {
+ struct i2c_client *client;
+ struct device *dev;
+
+ struct mutex lock;
+ u16 ok_to_ignore_lock:1;
+ u16 result_ready:1;
+ wait_queue_head_t result_ready_queue;
+ u16 result;
+
+ u32 int_time;
+ u32 mode;
+
+ u16 high_thresh_mantissa;
+ u16 low_thresh_mantissa;
+
+ u8 high_thresh_exp;
+ u8 low_thresh_exp;
+};
+
+struct opt3001_scale {
+ int val;
+ int val2;
+};
+
+static const struct opt3001_scale opt3001_scales[] = {
+ {
+ .val = 40,
+ .val2 = 950000,
+ },
+ {
+ .val = 81,
+ .val2 = 900000,
+ },
+ {
+ .val = 163,
+ .val2 = 800000,
+ },
+ {
+ .val = 327,
+ .val2 = 600000,
+ },
+ {
+ .val = 655,
+ .val2 = 200000,
+ },
+ {
+ .val = 1310,
+ .val2 = 400000,
+ },
+ {
+ .val = 2620,
+ .val2 = 800000,
+ },
+ {
+ .val = 5241,
+ .val2 = 600000,
+ },
+ {
+ .val = 10483,
+ .val2 = 200000,
+ },
+ {
+ .val = 20966,
+ .val2 = 400000,
+ },
+ {
+ .val = 83865,
+ .val2 = 600000,
+ },
+};
+
+static int opt3001_find_scale(const struct opt3001 *opt, int val,
+ int val2, u8 *exponent)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(opt3001_scales); i++) {
+ const struct opt3001_scale *scale = &opt3001_scales[i];
+
+ /*
+ * Combine the integer and micro parts for comparison
+ * purposes. Use milli lux precision to avoid 32-bit integer
+ * overflows.
+ */
+ if ((val * 1000 + val2 / 1000) <=
+ (scale->val * 1000 + scale->val2 / 1000)) {
+ *exponent = i;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent,
+ u16 mantissa, int *val, int *val2)
+{
+ int lux;
+
+ lux = 10 * (mantissa << exponent);
+ *val = lux / 1000;
+ *val2 = (lux - (*val * 1000)) * 1000;
+}
+
+static void opt3001_set_mode(struct opt3001 *opt, u16 *reg, u16 mode)
+{
+ *reg &= ~OPT3001_CONFIGURATION_M_MASK;
+ *reg |= mode;
+ opt->mode = mode;
+}
+
+static IIO_CONST_ATTR_INT_TIME_AVAIL("0.1 0.8");
+
+static struct attribute *opt3001_attributes[] = {
+ &iio_const_attr_integration_time_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group opt3001_attribute_group = {
+ .attrs = opt3001_attributes,
+};
+
+static const struct iio_event_spec opt3001_event_spec[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
+static const struct iio_chan_spec opt3001_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_INT_TIME),
+ .event_spec = opt3001_event_spec,
+ .num_event_specs = ARRAY_SIZE(opt3001_event_spec),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2)
+{
+ int ret;
+ u16 mantissa;
+ u16 reg;
+ u8 exponent;
+ u16 value;
+
+ /*
+ * 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;
+ }
+
+ /* Reset data-ready indicator flag (will be set in the IRQ routine) */
+ 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) {
+ dev_err(opt->dev, "failed to read register %02x\n",
+ OPT3001_CONFIGURATION);
+ goto err;
+ }
+
+ reg = ret;
+ opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SINGLE);
+
+ ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+ reg);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to write register %02x\n",
+ OPT3001_CONFIGURATION);
+ 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);
+
+err:
+ /* 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;
+ }
+
+ exponent = OPT3001_REG_EXPONENT(opt->result);
+ mantissa = OPT3001_REG_MANTISSA(opt->result);
+
+ opt3001_to_iio_ret(opt, exponent, mantissa, val, val2);
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int opt3001_get_int_time(struct opt3001 *opt, int *val, int *val2)
+{
+ *val = 0;
+ *val2 = opt->int_time;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int opt3001_set_int_time(struct opt3001 *opt, int time)
+{
+ int ret;
+ u16 reg;
+
+ 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);
+ return ret;
+ }
+
+ reg = ret;
+
+ switch (time) {
+ case 100000:
+ reg &= ~OPT3001_CONFIGURATION_CT;
+ opt->int_time = 100000;
+ break;
+ case 800000:
+ reg |= OPT3001_CONFIGURATION_CT;
+ opt->int_time = 800000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+ reg);
+}
+
+static int opt3001_read_raw(struct iio_dev *iio,
+ struct iio_chan_spec const *chan, int *val, int *val2,
+ long mask)
+{
+ struct opt3001 *opt = iio_priv(iio);
+ int ret;
+
+ if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
+ return -EBUSY;
+
+ if (chan->type != IIO_LIGHT)
+ return -EINVAL;
+
+ mutex_lock(&opt->lock);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ ret = opt3001_get_lux(opt, val, val2);
+ break;
+ case IIO_CHAN_INFO_INT_TIME:
+ ret = opt3001_get_int_time(opt, val, val2);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ mutex_unlock(&opt->lock);
+
+ return ret;
+}
+
+static int opt3001_write_raw(struct iio_dev *iio,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ struct opt3001 *opt = iio_priv(iio);
+ int ret;
+
+ if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
+ return -EBUSY;
+
+ if (chan->type != IIO_LIGHT)
+ return -EINVAL;
+
+ if (mask != IIO_CHAN_INFO_INT_TIME)
+ return -EINVAL;
+
+ if (val != 0)
+ return -EINVAL;
+
+ mutex_lock(&opt->lock);
+ ret = opt3001_set_int_time(opt, val2);
+ mutex_unlock(&opt->lock);
+
+ return ret;
+}
+
+static int opt3001_read_event_value(struct iio_dev *iio,
+ const struct iio_chan_spec *chan, enum iio_event_type type,
+ enum iio_event_direction dir, enum iio_event_info info,
+ int *val, int *val2)
+{
+ struct opt3001 *opt = iio_priv(iio);
+ int ret = IIO_VAL_INT_PLUS_MICRO;
+
+ mutex_lock(&opt->lock);
+
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ opt3001_to_iio_ret(opt, opt->high_thresh_exp,
+ opt->high_thresh_mantissa, val, val2);
+ break;
+ case IIO_EV_DIR_FALLING:
+ opt3001_to_iio_ret(opt, opt->low_thresh_exp,
+ opt->low_thresh_mantissa, val, val2);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ mutex_unlock(&opt->lock);
+
+ return ret;
+}
+
+static int opt3001_write_event_value(struct iio_dev *iio,
+ const struct iio_chan_spec *chan, enum iio_event_type type,
+ enum iio_event_direction dir, enum iio_event_info info,
+ int val, int val2)
+{
+ struct opt3001 *opt = iio_priv(iio);
+ int ret;
+
+ u16 mantissa;
+ u16 value;
+ u16 reg;
+
+ u8 exponent;
+
+ if (val < 0)
+ return -EINVAL;
+
+ mutex_lock(&opt->lock);
+
+ ret = opt3001_find_scale(opt, val, val2, &exponent);
+ if (ret < 0) {
+ dev_err(opt->dev, "can't find scale for %d.%06u\n", val, val2);
+ goto err;
+ }
+
+ mantissa = (((val * 1000) + (val2 / 1000)) / 10) >> exponent;
+ value = (exponent << 12) | mantissa;
+
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ reg = OPT3001_HIGH_LIMIT;
+ opt->high_thresh_mantissa = mantissa;
+ opt->high_thresh_exp = exponent;
+ break;
+ case IIO_EV_DIR_FALLING:
+ reg = OPT3001_LOW_LIMIT;
+ opt->low_thresh_mantissa = mantissa;
+ opt->low_thresh_exp = exponent;
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = i2c_smbus_write_word_swapped(opt->client, reg, value);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to write register %02x\n", reg);
+ goto err;
+ }
+
+err:
+ mutex_unlock(&opt->lock);
+
+ return ret;
+}
+
+static int opt3001_read_event_config(struct iio_dev *iio,
+ const struct iio_chan_spec *chan, enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct opt3001 *opt = iio_priv(iio);
+
+ return opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS;
+}
+
+static int opt3001_write_event_config(struct iio_dev *iio,
+ const struct iio_chan_spec *chan, enum iio_event_type type,
+ enum iio_event_direction dir, int state)
+{
+ struct opt3001 *opt = iio_priv(iio);
+ int ret;
+ u16 mode;
+ u16 reg;
+
+ if (state && opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
+ return 0;
+
+ if (!state && opt->mode == OPT3001_CONFIGURATION_M_SHUTDOWN)
+ return 0;
+
+ mutex_lock(&opt->lock);
+
+ mode = state ? OPT3001_CONFIGURATION_M_CONTINUOUS
+ : OPT3001_CONFIGURATION_M_SHUTDOWN;
+
+ 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;
+ }
+
+ reg = ret;
+ opt3001_set_mode(opt, ®, mode);
+
+ ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+ reg);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to write register %02x\n",
+ OPT3001_CONFIGURATION);
+ goto err;
+ }
+
+err:
+ mutex_unlock(&opt->lock);
+
+ return ret;
+}
+
+static const struct iio_info opt3001_info = {
+ .driver_module = THIS_MODULE,
+ .attrs = &opt3001_attribute_group,
+ .read_raw = opt3001_read_raw,
+ .write_raw = opt3001_write_raw,
+ .read_event_value = opt3001_read_event_value,
+ .write_event_value = opt3001_write_event_value,
+ .read_event_config = opt3001_read_event_config,
+ .write_event_config = opt3001_write_event_config,
+};
+
+static int opt3001_read_id(struct opt3001 *opt)
+{
+ char manufacturer[2];
+ u16 device_id;
+ int ret;
+
+ ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_MANUFACTURER_ID);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to read register %02x\n",
+ OPT3001_MANUFACTURER_ID);
+ return ret;
+ }
+
+ manufacturer[0] = ret >> 8;
+ manufacturer[1] = ret & 0xff;
+
+ ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_DEVICE_ID);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to read register %02x\n",
+ OPT3001_DEVICE_ID);
+ return ret;
+ }
+
+ device_id = ret;
+
+ dev_info(opt->dev, "Found %c%c OPT%04x\n", manufacturer[0],
+ manufacturer[1], device_id);
+
+ return 0;
+}
+
+static int opt3001_configure(struct opt3001 *opt)
+{
+ int ret;
+ u16 reg;
+
+ 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);
+ return ret;
+ }
+
+ reg = ret;
+
+ /* Enable automatic full-scale setting mode */
+ reg &= ~OPT3001_CONFIGURATION_RN_MASK;
+ reg |= OPT3001_CONFIGURATION_RN_AUTO;
+
+ /* Reflect status of the device's integration time setting */
+ if (reg & OPT3001_CONFIGURATION_CT)
+ opt->int_time = 800000;
+ else
+ opt->int_time = 100000;
+
+ /* Ensure device is in shutdown initially */
+ opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SHUTDOWN);
+
+ /* Configure for latched window-style comparison operation */
+ reg |= OPT3001_CONFIGURATION_L;
+ reg &= ~OPT3001_CONFIGURATION_POL;
+ reg &= ~OPT3001_CONFIGURATION_ME;
+ reg &= ~OPT3001_CONFIGURATION_FC_MASK;
+
+ ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+ reg);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to write register %02x\n",
+ OPT3001_CONFIGURATION);
+ return ret;
+ }
+
+ ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_LOW_LIMIT);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to read register %02x\n",
+ OPT3001_LOW_LIMIT);
+ return ret;
+ }
+
+ opt->low_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
+ opt->low_thresh_exp = OPT3001_REG_EXPONENT(ret);
+
+ ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_HIGH_LIMIT);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to read register %02x\n",
+ OPT3001_HIGH_LIMIT);
+ return ret;
+ }
+
+ opt->high_thresh_mantissa = OPT3001_REG_MANTISSA(ret);
+ opt->high_thresh_exp = OPT3001_REG_EXPONENT(ret);
+
+ return 0;
+}
+
+static irqreturn_t opt3001_irq(int irq, void *_iio)
+{
+ struct iio_dev *iio = _iio;
+ struct opt3001 *opt = iio_priv(iio);
+ int ret;
+
+ if (!opt->ok_to_ignore_lock)
+ mutex_lock(&opt->lock);
+
+ 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 out;
+ }
+
+ if ((ret & OPT3001_CONFIGURATION_M_MASK) ==
+ OPT3001_CONFIGURATION_M_CONTINUOUS) {
+ if (ret & OPT3001_CONFIGURATION_FH)
+ iio_push_event(iio,
+ IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
+ iio_get_time_ns());
+ if (ret & OPT3001_CONFIGURATION_FL)
+ iio_push_event(iio,
+ IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
+ iio_get_time_ns());
+ } else if (ret & OPT3001_CONFIGURATION_CRF) {
+ 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 out;
+ }
+ opt->result = ret;
+ opt->result_ready = true;
+ wake_up(&opt->result_ready_queue);
+ }
+
+out:
+ if (!opt->ok_to_ignore_lock)
+ mutex_unlock(&opt->lock);
+
+ return IRQ_HANDLED;
+}
+
+static int opt3001_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device *dev = &client->dev;
+
+ struct iio_dev *iio;
+ struct opt3001 *opt;
+ int irq = client->irq;
+ int ret;
+
+ iio = devm_iio_device_alloc(dev, sizeof(*opt));
+ if (!iio)
+ return -ENOMEM;
+
+ opt = iio_priv(iio);
+ opt->client = client;
+ opt->dev = dev;
+
+ mutex_init(&opt->lock);
+ init_waitqueue_head(&opt->result_ready_queue);
+ i2c_set_clientdata(client, iio);
+
+ ret = opt3001_read_id(opt);
+ if (ret)
+ return ret;
+
+ ret = opt3001_configure(opt);
+ if (ret)
+ return ret;
+
+ iio->name = client->name;
+ iio->channels = opt3001_channels;
+ iio->num_channels = ARRAY_SIZE(opt3001_channels);
+ iio->dev.parent = dev;
+ iio->modes = INDIO_DIRECT_MODE;
+ iio->info = &opt3001_info;
+
+ ret = devm_iio_device_register(dev, iio);
+ if (ret) {
+ dev_err(dev, "failed to register IIO device\n");
+ 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;
+ }
+
+ return 0;
+}
+
+static int opt3001_remove(struct i2c_client *client)
+{
+ struct iio_dev *iio = i2c_get_clientdata(client);
+ struct opt3001 *opt = iio_priv(iio);
+ int ret;
+ u16 reg;
+
+ free_irq(client->irq, iio);
+
+ 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);
+ return ret;
+ }
+
+ reg = ret;
+ opt3001_set_mode(opt, ®, OPT3001_CONFIGURATION_M_SHUTDOWN);
+
+ ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_CONFIGURATION,
+ reg);
+ if (ret < 0) {
+ dev_err(opt->dev, "failed to write register %02x\n",
+ OPT3001_CONFIGURATION);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct i2c_device_id opt3001_id[] = {
+ { "opt3001", 0 },
+ { } /* Terminating Entry */
+};
+MODULE_DEVICE_TABLE(i2c, opt3001_id);
+
+static const struct of_device_id opt3001_of_match[] = {
+ { .compatible = "ti,opt3001" },
+ { }
+};
+
+static struct i2c_driver opt3001_driver = {
+ .probe = opt3001_probe,
+ .remove = opt3001_remove,
+ .id_table = opt3001_id,
+
+ .driver = {
+ .name = "opt3001",
+ .of_match_table = of_match_ptr(opt3001_of_match),
+ .owner = THIS_MODULE,
+ },
+};
+
+module_i2c_driver(opt3001_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Andreas Dannenberg <dannenberg@ti.com>");
+MODULE_DESCRIPTION("Texas Instruments OPT3001 Light Sensor Driver");
diff --git a/drivers/iio/light/pa12203001.c b/drivers/iio/light/pa12203001.c
new file mode 100644
index 0000000..45f7bde
--- /dev/null
+++ b/drivers/iio/light/pa12203001.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 2015 Intel Corporation
+ *
+ * Driver for TXC PA12203001 Proximity and Ambient Light Sensor.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ * To do: Interrupt support.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/mutex.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#define PA12203001_DRIVER_NAME "pa12203001"
+
+#define PA12203001_REG_CFG0 0x00
+#define PA12203001_REG_CFG1 0x01
+#define PA12203001_REG_CFG2 0x02
+#define PA12203001_REG_CFG3 0x03
+
+#define PA12203001_REG_ADL 0x0b
+#define PA12203001_REG_PDH 0x0e
+
+#define PA12203001_REG_POFS 0x10
+#define PA12203001_REG_PSET 0x11
+
+#define PA12203001_ALS_EN_MASK BIT(0)
+#define PA12203001_PX_EN_MASK BIT(1)
+#define PA12203001_PX_NORMAL_MODE_MASK GENMASK(7, 6)
+#define PA12203001_AFSR_MASK GENMASK(5, 4)
+#define PA12203001_AFSR_SHIFT 4
+
+#define PA12203001_PSCAN 0x03
+
+/* als range 31000, ps, als disabled */
+#define PA12203001_REG_CFG0_DEFAULT 0x30
+
+/* led current: 100 mA */
+#define PA12203001_REG_CFG1_DEFAULT 0x20
+
+/* ps mode: normal, interrupts not active */
+#define PA12203001_REG_CFG2_DEFAULT 0xcc
+
+#define PA12203001_REG_CFG3_DEFAULT 0x00
+
+#define PA12203001_SLEEP_DELAY_MS 3000
+
+#define PA12203001_CHIP_ENABLE 0xff
+#define PA12203001_CHIP_DISABLE 0x00
+
+/* available scales: corresponding to [500, 4000, 7000, 31000] lux */
+static const int pa12203001_scales[] = { 7629, 61036, 106813, 473029};
+
+struct pa12203001_data {
+ struct i2c_client *client;
+
+ /* protect device states */
+ struct mutex lock;
+
+ bool als_enabled;
+ bool px_enabled;
+ bool als_needs_enable;
+ bool px_needs_enable;
+
+ struct regmap *map;
+};
+
+static const struct {
+ u8 reg;
+ u8 val;
+} regvals[] = {
+ {PA12203001_REG_CFG0, PA12203001_REG_CFG0_DEFAULT},
+ {PA12203001_REG_CFG1, PA12203001_REG_CFG1_DEFAULT},
+ {PA12203001_REG_CFG2, PA12203001_REG_CFG2_DEFAULT},
+ {PA12203001_REG_CFG3, PA12203001_REG_CFG3_DEFAULT},
+ {PA12203001_REG_PSET, PA12203001_PSCAN},
+};
+
+static IIO_CONST_ATTR(in_illuminance_scale_available,
+ "0.007629 0.061036 0.106813 0.473029");
+
+static struct attribute *pa12203001_attrs[] = {
+ &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
+ NULL
+};
+
+static const struct attribute_group pa12203001_attr_group = {
+ .attrs = pa12203001_attrs,
+};
+
+static const struct iio_chan_spec pa12203001_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_PROXIMITY,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ }
+};
+
+static const struct regmap_range pa12203001_volatile_regs_ranges[] = {
+ regmap_reg_range(PA12203001_REG_ADL, PA12203001_REG_ADL + 1),
+ regmap_reg_range(PA12203001_REG_PDH, PA12203001_REG_PDH),
+};
+
+static const struct regmap_access_table pa12203001_volatile_regs = {
+ .yes_ranges = pa12203001_volatile_regs_ranges,
+ .n_yes_ranges = ARRAY_SIZE(pa12203001_volatile_regs_ranges),
+};
+
+static const struct regmap_config pa12203001_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = PA12203001_REG_PSET,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_table = &pa12203001_volatile_regs,
+};
+
+static inline int pa12203001_als_enable(struct pa12203001_data *data, u8 enable)
+{
+ int ret;
+
+ ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
+ PA12203001_ALS_EN_MASK, enable);
+ if (ret < 0)
+ return ret;
+
+ data->als_enabled = !!enable;
+
+ return 0;
+}
+
+static inline int pa12203001_px_enable(struct pa12203001_data *data, u8 enable)
+{
+ int ret;
+
+ ret = regmap_update_bits(data->map, PA12203001_REG_CFG0,
+ PA12203001_PX_EN_MASK, enable);
+ if (ret < 0)
+ return ret;
+
+ data->px_enabled = !!enable;
+
+ return 0;
+}
+
+static int pa12203001_set_power_state(struct pa12203001_data *data, bool on,
+ u8 mask)
+{
+#ifdef CONFIG_PM
+ int ret;
+
+ if (on && (mask & PA12203001_ALS_EN_MASK)) {
+ mutex_lock(&data->lock);
+ if (data->px_enabled) {
+ ret = pa12203001_als_enable(data,
+ PA12203001_ALS_EN_MASK);
+ if (ret < 0)
+ goto err;
+ } else {
+ data->als_needs_enable = true;
+ }
+ mutex_unlock(&data->lock);
+ }
+
+ if (on && (mask & PA12203001_PX_EN_MASK)) {
+ mutex_lock(&data->lock);
+ if (data->als_enabled) {
+ ret = pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
+ if (ret < 0)
+ goto err;
+ } else {
+ data->px_needs_enable = true;
+ }
+ mutex_unlock(&data->lock);
+ }
+
+ if (on) {
+ ret = pm_runtime_get_sync(&data->client->dev);
+ if (ret < 0)
+ pm_runtime_put_noidle(&data->client->dev);
+
+ } else {
+ pm_runtime_mark_last_busy(&data->client->dev);
+ ret = pm_runtime_put_autosuspend(&data->client->dev);
+ }
+
+ return ret;
+
+err:
+ mutex_unlock(&data->lock);
+ return ret;
+
+#endif
+ return 0;
+}
+
+static int pa12203001_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct pa12203001_data *data = iio_priv(indio_dev);
+ int ret;
+ u8 dev_mask;
+ unsigned int reg_byte;
+ __le16 reg_word;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_LIGHT:
+ dev_mask = PA12203001_ALS_EN_MASK;
+ ret = pa12203001_set_power_state(data, true, dev_mask);
+ if (ret < 0)
+ return ret;
+ /*
+ * ALS ADC value is stored in registers
+ * PA12203001_REG_ADL and in PA12203001_REG_ADL + 1.
+ */
+ ret = regmap_bulk_read(data->map, PA12203001_REG_ADL,
+ ®_word, 2);
+ if (ret < 0)
+ goto reg_err;
+
+ *val = le16_to_cpu(reg_word);
+ ret = pa12203001_set_power_state(data, false, dev_mask);
+ if (ret < 0)
+ return ret;
+ break;
+ case IIO_PROXIMITY:
+ dev_mask = PA12203001_PX_EN_MASK;
+ ret = pa12203001_set_power_state(data, true, dev_mask);
+ if (ret < 0)
+ return ret;
+ ret = regmap_read(data->map, PA12203001_REG_PDH,
+ ®_byte);
+ if (ret < 0)
+ goto reg_err;
+
+ *val = reg_byte;
+ ret = pa12203001_set_power_state(data, false, dev_mask);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ ret = regmap_read(data->map, PA12203001_REG_CFG0, ®_byte);
+ if (ret < 0)
+ return ret;
+ *val = 0;
+ reg_byte = (reg_byte & PA12203001_AFSR_MASK);
+ *val2 = pa12203001_scales[reg_byte >> 4];
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+
+reg_err:
+ pa12203001_set_power_state(data, false, dev_mask);
+ return ret;
+}
+
+static int pa12203001_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val,
+ int val2, long mask)
+{
+ struct pa12203001_data *data = iio_priv(indio_dev);
+ int i, ret, new_val;
+ unsigned int reg_byte;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ ret = regmap_read(data->map, PA12203001_REG_CFG0, ®_byte);
+ if (val != 0 || ret < 0)
+ return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(pa12203001_scales); i++) {
+ if (val2 == pa12203001_scales[i]) {
+ new_val = i << PA12203001_AFSR_SHIFT;
+ return regmap_update_bits(data->map,
+ PA12203001_REG_CFG0,
+ PA12203001_AFSR_MASK,
+ new_val);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static const struct iio_info pa12203001_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = pa12203001_read_raw,
+ .write_raw = pa12203001_write_raw,
+ .attrs = &pa12203001_attr_group,
+};
+
+static int pa12203001_init(struct iio_dev *indio_dev)
+{
+ struct pa12203001_data *data = iio_priv(indio_dev);
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(regvals); i++) {
+ ret = regmap_write(data->map, regvals[i].reg, regvals[i].val);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pa12203001_power_chip(struct iio_dev *indio_dev, u8 state)
+{
+ struct pa12203001_data *data = iio_priv(indio_dev);
+ int ret;
+
+ mutex_lock(&data->lock);
+ ret = pa12203001_als_enable(data, state);
+ if (ret < 0)
+ goto out;
+
+ ret = pa12203001_px_enable(data, state);
+
+out:
+ mutex_unlock(&data->lock);
+ return ret;
+}
+
+static int pa12203001_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct pa12203001_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev,
+ sizeof(struct pa12203001_data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+
+ data->map = devm_regmap_init_i2c(client, &pa12203001_regmap_config);
+ if (IS_ERR(data->map))
+ return PTR_ERR(data->map);
+
+ mutex_init(&data->lock);
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &pa12203001_info;
+ indio_dev->name = PA12203001_DRIVER_NAME;
+ indio_dev->channels = pa12203001_channels;
+ indio_dev->num_channels = ARRAY_SIZE(pa12203001_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = pa12203001_init(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ ret = pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
+ if (ret < 0)
+ return ret;
+
+ ret = pm_runtime_set_active(&client->dev);
+ if (ret < 0) {
+ pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
+ return ret;
+ }
+
+ pm_runtime_enable(&client->dev);
+ pm_runtime_set_autosuspend_delay(&client->dev,
+ PA12203001_SLEEP_DELAY_MS);
+ pm_runtime_use_autosuspend(&client->dev);
+
+ return iio_device_register(indio_dev);
+}
+
+static int pa12203001_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+ iio_device_unregister(indio_dev);
+
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+
+ return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
+}
+
+#if defined(CONFIG_PM_SLEEP) || defined(CONFIG_PM)
+static int pa12203001_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+
+ return pa12203001_power_chip(indio_dev, PA12203001_CHIP_DISABLE);
+}
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static int pa12203001_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+
+ return pa12203001_power_chip(indio_dev, PA12203001_CHIP_ENABLE);
+}
+#endif
+
+#ifdef CONFIG_PM
+static int pa12203001_runtime_resume(struct device *dev)
+{
+ struct pa12203001_data *data;
+
+ data = iio_priv(i2c_get_clientdata(to_i2c_client(dev)));
+
+ mutex_lock(&data->lock);
+ if (data->als_needs_enable) {
+ pa12203001_als_enable(data, PA12203001_ALS_EN_MASK);
+ data->als_needs_enable = false;
+ }
+ if (data->px_needs_enable) {
+ pa12203001_px_enable(data, PA12203001_PX_EN_MASK);
+ data->px_needs_enable = false;
+ }
+ mutex_unlock(&data->lock);
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops pa12203001_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pa12203001_suspend, pa12203001_resume)
+ SET_RUNTIME_PM_OPS(pa12203001_suspend, pa12203001_runtime_resume, NULL)
+};
+
+static const struct acpi_device_id pa12203001_acpi_match[] = {
+ { "TXCPA122", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(acpi, pa12203001_acpi_match);
+
+static const struct i2c_device_id pa12203001_id[] = {
+ {"txcpa122", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, pa12203001_id);
+
+static struct i2c_driver pa12203001_driver = {
+ .driver = {
+ .name = PA12203001_DRIVER_NAME,
+ .pm = &pa12203001_pm_ops,
+ .acpi_match_table = ACPI_PTR(pa12203001_acpi_match),
+ },
+ .probe = pa12203001_probe,
+ .remove = pa12203001_remove,
+ .id_table = pa12203001_id,
+
+};
+module_i2c_driver(pa12203001_driver);
+
+MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
+MODULE_DESCRIPTION("Driver for TXC PA12203001 Proximity and Light Sensor");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c
new file mode 100644
index 0000000..4b75bb0
--- /dev/null
+++ b/drivers/iio/light/rpr0521.c
@@ -0,0 +1,615 @@
+/*
+ * RPR-0521 ROHM Ambient Light and Proximity Sensor
+ *
+ * Copyright (c) 2015, Intel Corporation.
+ *
+ * This file is subject to the terms and conditions of version 2 of
+ * the GNU General Public License. See the file COPYING in the main
+ * directory of this archive for more details.
+ *
+ * IIO driver for RPR-0521RS (7-bit I2C slave address 0x38).
+ *
+ * TODO: illuminance channel, PM support, buffer
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/delay.h>
+#include <linux/acpi.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/pm_runtime.h>
+
+#define RPR0521_REG_SYSTEM_CTRL 0x40
+#define RPR0521_REG_MODE_CTRL 0x41
+#define RPR0521_REG_ALS_CTRL 0x42
+#define RPR0521_REG_PXS_CTRL 0x43
+#define RPR0521_REG_PXS_DATA 0x44 /* 16-bit, little endian */
+#define RPR0521_REG_ALS_DATA0 0x46 /* 16-bit, little endian */
+#define RPR0521_REG_ALS_DATA1 0x48 /* 16-bit, little endian */
+#define RPR0521_REG_ID 0x92
+
+#define RPR0521_MODE_ALS_MASK BIT(7)
+#define RPR0521_MODE_PXS_MASK BIT(6)
+#define RPR0521_MODE_MEAS_TIME_MASK GENMASK(3, 0)
+#define RPR0521_ALS_DATA0_GAIN_MASK GENMASK(5, 4)
+#define RPR0521_ALS_DATA0_GAIN_SHIFT 4
+#define RPR0521_ALS_DATA1_GAIN_MASK GENMASK(3, 2)
+#define RPR0521_ALS_DATA1_GAIN_SHIFT 2
+#define RPR0521_PXS_GAIN_MASK GENMASK(5, 4)
+#define RPR0521_PXS_GAIN_SHIFT 4
+
+#define RPR0521_MODE_ALS_ENABLE BIT(7)
+#define RPR0521_MODE_ALS_DISABLE 0x00
+#define RPR0521_MODE_PXS_ENABLE BIT(6)
+#define RPR0521_MODE_PXS_DISABLE 0x00
+
+#define RPR0521_MANUFACT_ID 0xE0
+#define RPR0521_DEFAULT_MEAS_TIME 0x06 /* ALS - 100ms, PXS - 100ms */
+
+#define RPR0521_DRV_NAME "RPR0521"
+#define RPR0521_REGMAP_NAME "rpr0521_regmap"
+
+#define RPR0521_SLEEP_DELAY_MS 2000
+
+#define RPR0521_ALS_SCALE_AVAIL "0.007812 0.015625 0.5 1"
+#define RPR0521_PXS_SCALE_AVAIL "0.125 0.5 1"
+
+struct rpr0521_gain {
+ int scale;
+ int uscale;
+};
+
+static const struct rpr0521_gain rpr0521_als_gain[4] = {
+ {1, 0}, /* x1 */
+ {0, 500000}, /* x2 */
+ {0, 15625}, /* x64 */
+ {0, 7812}, /* x128 */
+};
+
+static const struct rpr0521_gain rpr0521_pxs_gain[3] = {
+ {1, 0}, /* x1 */
+ {0, 500000}, /* x2 */
+ {0, 125000}, /* x4 */
+};
+
+enum rpr0521_channel {
+ RPR0521_CHAN_ALS_DATA0,
+ RPR0521_CHAN_ALS_DATA1,
+ RPR0521_CHAN_PXS,
+};
+
+struct rpr0521_reg_desc {
+ u8 address;
+ u8 device_mask;
+};
+
+static const struct rpr0521_reg_desc rpr0521_data_reg[] = {
+ [RPR0521_CHAN_ALS_DATA0] = {
+ .address = RPR0521_REG_ALS_DATA0,
+ .device_mask = RPR0521_MODE_ALS_MASK,
+ },
+ [RPR0521_CHAN_ALS_DATA1] = {
+ .address = RPR0521_REG_ALS_DATA1,
+ .device_mask = RPR0521_MODE_ALS_MASK,
+ },
+ [RPR0521_CHAN_PXS] = {
+ .address = RPR0521_REG_PXS_DATA,
+ .device_mask = RPR0521_MODE_PXS_MASK,
+ },
+};
+
+static const struct rpr0521_gain_info {
+ u8 reg;
+ u8 mask;
+ u8 shift;
+ const struct rpr0521_gain *gain;
+ int size;
+} rpr0521_gain[] = {
+ [RPR0521_CHAN_ALS_DATA0] = {
+ .reg = RPR0521_REG_ALS_CTRL,
+ .mask = RPR0521_ALS_DATA0_GAIN_MASK,
+ .shift = RPR0521_ALS_DATA0_GAIN_SHIFT,
+ .gain = rpr0521_als_gain,
+ .size = ARRAY_SIZE(rpr0521_als_gain),
+ },
+ [RPR0521_CHAN_ALS_DATA1] = {
+ .reg = RPR0521_REG_ALS_CTRL,
+ .mask = RPR0521_ALS_DATA1_GAIN_MASK,
+ .shift = RPR0521_ALS_DATA1_GAIN_SHIFT,
+ .gain = rpr0521_als_gain,
+ .size = ARRAY_SIZE(rpr0521_als_gain),
+ },
+ [RPR0521_CHAN_PXS] = {
+ .reg = RPR0521_REG_PXS_CTRL,
+ .mask = RPR0521_PXS_GAIN_MASK,
+ .shift = RPR0521_PXS_GAIN_SHIFT,
+ .gain = rpr0521_pxs_gain,
+ .size = ARRAY_SIZE(rpr0521_pxs_gain),
+ },
+};
+
+struct rpr0521_data {
+ struct i2c_client *client;
+
+ /* protect device params updates (e.g state, gain) */
+ struct mutex lock;
+
+ /* device active status */
+ bool als_dev_en;
+ bool pxs_dev_en;
+
+ /* optimize runtime pm ops - enable device only if needed */
+ bool als_ps_need_en;
+ bool pxs_ps_need_en;
+
+ struct regmap *regmap;
+};
+
+static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL);
+static IIO_CONST_ATTR(in_proximity_scale_available, RPR0521_PXS_SCALE_AVAIL);
+
+static struct attribute *rpr0521_attributes[] = {
+ &iio_const_attr_in_intensity_scale_available.dev_attr.attr,
+ &iio_const_attr_in_proximity_scale_available.dev_attr.attr,
+ NULL,
+};
+
+static const struct attribute_group rpr0521_attribute_group = {
+ .attrs = rpr0521_attributes,
+};
+
+static const struct iio_chan_spec rpr0521_channels[] = {
+ {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .address = RPR0521_CHAN_ALS_DATA0,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .modified = 1,
+ .address = RPR0521_CHAN_ALS_DATA1,
+ .channel2 = IIO_MOD_LIGHT_IR,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_PROXIMITY,
+ .address = RPR0521_CHAN_PXS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ }
+};
+
+static int rpr0521_als_enable(struct rpr0521_data *data, u8 status)
+{
+ int ret;
+
+ ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+ RPR0521_MODE_ALS_MASK,
+ status);
+ if (ret < 0)
+ return ret;
+
+ data->als_dev_en = true;
+
+ return 0;
+}
+
+static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status)
+{
+ int ret;
+
+ ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+ RPR0521_MODE_PXS_MASK,
+ status);
+ if (ret < 0)
+ return ret;
+
+ data->pxs_dev_en = true;
+
+ return 0;
+}
+
+/**
+ * rpr0521_set_power_state - handles runtime PM state and sensors enabled status
+ *
+ * @data: rpr0521 device private data
+ * @on: state to be set for devices in @device_mask
+ * @device_mask: bitmask specifying for which device we need to update @on state
+ *
+ * We rely on rpr0521_runtime_resume to enable our @device_mask devices, but
+ * if (for example) PXS was enabled (pxs_dev_en = true) by a previous call to
+ * rpr0521_runtime_resume and we want to enable ALS we MUST set ALS enable
+ * bit of RPR0521_REG_MODE_CTRL here because rpr0521_runtime_resume will not
+ * be called twice.
+ */
+static int rpr0521_set_power_state(struct rpr0521_data *data, bool on,
+ u8 device_mask)
+{
+#ifdef CONFIG_PM
+ int ret;
+ u8 update_mask = 0;
+
+ if (device_mask & RPR0521_MODE_ALS_MASK) {
+ if (on && !data->als_ps_need_en && data->pxs_dev_en)
+ update_mask |= RPR0521_MODE_ALS_MASK;
+ else
+ data->als_ps_need_en = on;
+ }
+
+ if (device_mask & RPR0521_MODE_PXS_MASK) {
+ if (on && !data->pxs_ps_need_en && data->als_dev_en)
+ update_mask |= RPR0521_MODE_PXS_MASK;
+ else
+ data->pxs_ps_need_en = on;
+ }
+
+ if (update_mask) {
+ ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+ update_mask, update_mask);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (on) {
+ ret = pm_runtime_get_sync(&data->client->dev);
+ } else {
+ pm_runtime_mark_last_busy(&data->client->dev);
+ ret = pm_runtime_put_autosuspend(&data->client->dev);
+ }
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "Failed: rpr0521_set_power_state for %d, ret %d\n",
+ on, ret);
+ if (on)
+ pm_runtime_put_noidle(&data->client->dev);
+
+ return ret;
+ }
+#endif
+ return 0;
+}
+
+static int rpr0521_get_gain(struct rpr0521_data *data, int chan,
+ int *val, int *val2)
+{
+ int ret, reg, idx;
+
+ ret = regmap_read(data->regmap, rpr0521_gain[chan].reg, ®);
+ if (ret < 0)
+ return ret;
+
+ idx = (rpr0521_gain[chan].mask & reg) >> rpr0521_gain[chan].shift;
+ *val = rpr0521_gain[chan].gain[idx].scale;
+ *val2 = rpr0521_gain[chan].gain[idx].uscale;
+
+ return 0;
+}
+
+static int rpr0521_set_gain(struct rpr0521_data *data, int chan,
+ int val, int val2)
+{
+ int i, idx = -EINVAL;
+
+ /* get gain index */
+ for (i = 0; i < rpr0521_gain[chan].size; i++)
+ if (val == rpr0521_gain[chan].gain[i].scale &&
+ val2 == rpr0521_gain[chan].gain[i].uscale) {
+ idx = i;
+ break;
+ }
+
+ if (idx < 0)
+ return idx;
+
+ return regmap_update_bits(data->regmap, rpr0521_gain[chan].reg,
+ rpr0521_gain[chan].mask,
+ idx << rpr0521_gain[chan].shift);
+}
+
+static int rpr0521_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct rpr0521_data *data = iio_priv(indio_dev);
+ int ret;
+ u8 device_mask;
+ __le16 raw_data;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ if (chan->type != IIO_INTENSITY && chan->type != IIO_PROXIMITY)
+ return -EINVAL;
+
+ device_mask = rpr0521_data_reg[chan->address].device_mask;
+
+ mutex_lock(&data->lock);
+ ret = rpr0521_set_power_state(data, true, device_mask);
+ if (ret < 0) {
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ ret = regmap_bulk_read(data->regmap,
+ rpr0521_data_reg[chan->address].address,
+ &raw_data, 2);
+ if (ret < 0) {
+ rpr0521_set_power_state(data, false, device_mask);
+ mutex_unlock(&data->lock);
+ return ret;
+ }
+
+ ret = rpr0521_set_power_state(data, false, device_mask);
+ mutex_unlock(&data->lock);
+ if (ret < 0)
+ return ret;
+
+ *val = le16_to_cpu(raw_data);
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ mutex_lock(&data->lock);
+ ret = rpr0521_get_gain(data, chan->address, val, val2);
+ mutex_unlock(&data->lock);
+ if (ret < 0)
+ return ret;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int rpr0521_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val,
+ int val2, long mask)
+{
+ struct rpr0521_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ mutex_lock(&data->lock);
+ ret = rpr0521_set_gain(data, chan->address, val, val2);
+ mutex_unlock(&data->lock);
+
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info rpr0521_info = {
+ .driver_module = THIS_MODULE,
+ .read_raw = rpr0521_read_raw,
+ .write_raw = rpr0521_write_raw,
+ .attrs = &rpr0521_attribute_group,
+};
+
+static int rpr0521_init(struct rpr0521_data *data)
+{
+ int ret;
+ int id;
+
+ ret = regmap_read(data->regmap, RPR0521_REG_ID, &id);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "Failed to read REG_ID register\n");
+ return ret;
+ }
+
+ if (id != RPR0521_MANUFACT_ID) {
+ dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
+ id, RPR0521_MANUFACT_ID);
+ return -ENODEV;
+ }
+
+ /* set default measurement time - 100 ms for both ALS and PS */
+ ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+ RPR0521_MODE_MEAS_TIME_MASK,
+ RPR0521_DEFAULT_MEAS_TIME);
+ if (ret) {
+ pr_err("regmap_update_bits returned %d\n", ret);
+ return ret;
+ }
+
+ ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
+ if (ret < 0)
+ return ret;
+ ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int rpr0521_poweroff(struct rpr0521_data *data)
+{
+ int ret;
+
+ ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
+ RPR0521_MODE_ALS_MASK |
+ RPR0521_MODE_PXS_MASK,
+ RPR0521_MODE_ALS_DISABLE |
+ RPR0521_MODE_PXS_DISABLE);
+ if (ret < 0)
+ return ret;
+
+ data->als_dev_en = false;
+ data->pxs_dev_en = false;
+
+ return 0;
+}
+
+static bool rpr0521_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case RPR0521_REG_MODE_CTRL:
+ case RPR0521_REG_ALS_CTRL:
+ case RPR0521_REG_PXS_CTRL:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static const struct regmap_config rpr0521_regmap_config = {
+ .name = RPR0521_REGMAP_NAME,
+
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = RPR0521_REG_ID,
+ .cache_type = REGCACHE_RBTREE,
+ .volatile_reg = rpr0521_is_volatile_reg,
+};
+
+static int rpr0521_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct rpr0521_data *data;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ regmap = devm_regmap_init_i2c(client, &rpr0521_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(&client->dev, "regmap_init failed!\n");
+ return PTR_ERR(regmap);
+ }
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ data->regmap = regmap;
+
+ mutex_init(&data->lock);
+
+ indio_dev->dev.parent = &client->dev;
+ indio_dev->info = &rpr0521_info;
+ indio_dev->name = RPR0521_DRV_NAME;
+ indio_dev->channels = rpr0521_channels;
+ indio_dev->num_channels = ARRAY_SIZE(rpr0521_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+
+ ret = rpr0521_init(data);
+ if (ret < 0) {
+ dev_err(&client->dev, "rpr0521 chip init failed\n");
+ return ret;
+ }
+ ret = iio_device_register(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ ret = pm_runtime_set_active(&client->dev);
+ if (ret < 0)
+ goto err_iio_unregister;
+
+ pm_runtime_enable(&client->dev);
+ pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS);
+ pm_runtime_use_autosuspend(&client->dev);
+
+ return 0;
+
+err_iio_unregister:
+ iio_device_unregister(indio_dev);
+ return ret;
+}
+
+static int rpr0521_remove(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(client);
+
+ pm_runtime_disable(&client->dev);
+ pm_runtime_set_suspended(&client->dev);
+ pm_runtime_put_noidle(&client->dev);
+
+ iio_device_unregister(indio_dev);
+ rpr0521_poweroff(iio_priv(indio_dev));
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rpr0521_runtime_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct rpr0521_data *data = iio_priv(indio_dev);
+ int ret;
+
+ /* disable channels and sets {als,pxs}_dev_en to false */
+ mutex_lock(&data->lock);
+ ret = rpr0521_poweroff(data);
+ mutex_unlock(&data->lock);
+
+ return ret;
+}
+
+static int rpr0521_runtime_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
+ struct rpr0521_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (data->als_ps_need_en) {
+ ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
+ if (ret < 0)
+ return ret;
+ data->als_ps_need_en = false;
+ }
+
+ if (data->pxs_ps_need_en) {
+ ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
+ if (ret < 0)
+ return ret;
+ data->pxs_ps_need_en = false;
+ }
+
+ return 0;
+}
+#endif
+
+static const struct dev_pm_ops rpr0521_pm_ops = {
+ SET_RUNTIME_PM_OPS(rpr0521_runtime_suspend,
+ rpr0521_runtime_resume, NULL)
+};
+
+static const struct acpi_device_id rpr0521_acpi_match[] = {
+ {"RPR0521", 0},
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, rpr0521_acpi_match);
+
+static const struct i2c_device_id rpr0521_id[] = {
+ {"rpr0521", 0},
+ { }
+};
+
+MODULE_DEVICE_TABLE(i2c, rpr0521_id);
+
+static struct i2c_driver rpr0521_driver = {
+ .driver = {
+ .name = RPR0521_DRV_NAME,
+ .pm = &rpr0521_pm_ops,
+ .acpi_match_table = ACPI_PTR(rpr0521_acpi_match),
+ },
+ .probe = rpr0521_probe,
+ .remove = rpr0521_remove,
+ .id_table = rpr0521_id,
+};
+
+module_i2c_driver(rpr0521_driver);
+
+MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
+MODULE_DESCRIPTION("RPR0521 ROHM Ambient Light and Proximity Sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c
index c1a2182..f101bb5 100644
--- a/drivers/iio/light/stk3310.c
+++ b/drivers/iio/light/stk3310.c
@@ -200,7 +200,7 @@
int *val, int *val2)
{
u8 reg;
- u16 buf;
+ __be16 buf;
int ret;
struct stk3310_data *data = iio_priv(indio_dev);
@@ -222,7 +222,7 @@
dev_err(&data->client->dev, "register read failed\n");
return ret;
}
- *val = swab16(buf);
+ *val = be16_to_cpu(buf);
return IIO_VAL_INT;
}
@@ -235,7 +235,7 @@
int val, int val2)
{
u8 reg;
- u16 buf;
+ __be16 buf;
int ret;
unsigned int index;
struct stk3310_data *data = iio_priv(indio_dev);
@@ -252,7 +252,7 @@
else
return -EINVAL;
- buf = swab16(val);
+ buf = cpu_to_be16(val);
ret = regmap_bulk_write(data->regmap, reg, &buf, 2);
if (ret < 0)
dev_err(&client->dev, "failed to set PS threshold!\n");
@@ -301,7 +301,7 @@
int *val, int *val2, long mask)
{
u8 reg;
- u16 buf;
+ __be16 buf;
int ret;
unsigned int index;
struct stk3310_data *data = iio_priv(indio_dev);
@@ -322,7 +322,7 @@
mutex_unlock(&data->lock);
return ret;
}
- *val = swab16(buf);
+ *val = be16_to_cpu(buf);
mutex_unlock(&data->lock);
return IIO_VAL_INT;
case IIO_CHAN_INFO_INT_TIME:
@@ -608,13 +608,7 @@
if (ret < 0)
return ret;
- ret = iio_device_register(indio_dev);
- if (ret < 0) {
- dev_err(&client->dev, "device_register failed\n");
- stk3310_set_state(data, STK3310_STATE_STANDBY);
- }
-
- if (client->irq <= 0)
+ if (client->irq < 0)
client->irq = stk3310_gpio_probe(client);
if (client->irq >= 0) {
@@ -629,6 +623,12 @@
client->irq);
}
+ ret = iio_device_register(indio_dev);
+ if (ret < 0) {
+ dev_err(&client->dev, "device_register failed\n");
+ stk3310_set_state(data, STK3310_STATE_STANDBY);
+ }
+
return ret;
}
@@ -676,6 +676,7 @@
{"STK3311", 0},
{}
};
+MODULE_DEVICE_TABLE(i2c, stk3310_i2c_id);
static const struct acpi_device_id stk3310_acpi_id[] = {
{"STK3310", 0},
diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c
index f8b1df0..f90f8c5 100644
--- a/drivers/iio/light/tcs3414.c
+++ b/drivers/iio/light/tcs3414.c
@@ -392,7 +392,6 @@
.driver = {
.name = TCS3414_DRV_NAME,
.pm = &tcs3414_pm_ops,
- .owner = THIS_MODULE,
},
.probe = tcs3414_probe,
.remove = tcs3414_remove,
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
index 7525699..1b530bf 100644
--- a/drivers/iio/light/tcs3472.c
+++ b/drivers/iio/light/tcs3472.c
@@ -366,7 +366,6 @@
.driver = {
.name = TCS3472_DRV_NAME,
.pm = &tcs3472_pm_ops,
- .owner = THIS_MODULE,
},
.probe = tcs3472_probe,
.remove = tcs3472_remove,
diff --git a/drivers/iio/light/tsl4531.c b/drivers/iio/light/tsl4531.c
index 63c26e2..2697918 100644
--- a/drivers/iio/light/tsl4531.c
+++ b/drivers/iio/light/tsl4531.c
@@ -247,7 +247,6 @@
.driver = {
.name = TSL4531_DRV_NAME,
.pm = TSL4531_PM_OPS,
- .owner = THIS_MODULE,
},
.probe = tsl4531_probe,
.remove = tsl4531_remove,
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index d948c47..c9d85bb 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -185,7 +185,6 @@
static struct i2c_driver vcnl4000_driver = {
.driver = {
.name = VCNL4000_DRV_NAME,
- .owner = THIS_MODULE,
},
.probe = vcnl4000_probe,
.id_table = vcnl4000_id,
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index dcadfc4..efb9350 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -90,6 +90,7 @@
config BMC150_MAGN
tristate "Bosch BMC150 Magnetometer Driver"
depends on I2C
+ select REGMAP_I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
index d4c1788..e330205 100644
--- a/drivers/iio/magnetometer/bmc150_magn.c
+++ b/drivers/iio/magnetometer/bmc150_magn.c
@@ -85,6 +85,7 @@
#define BMC150_MAGN_REG_HIGH_THRESH 0x50
#define BMC150_MAGN_REG_REP_XY 0x51
#define BMC150_MAGN_REG_REP_Z 0x52
+#define BMC150_MAGN_REG_REP_DATAMASK GENMASK(7, 0)
#define BMC150_MAGN_REG_TRIM_START 0x5D
#define BMC150_MAGN_REG_TRIM_END 0x71
@@ -559,7 +560,7 @@
}
ret = regmap_update_bits(data->regmap,
BMC150_MAGN_REG_REP_XY,
- 0xFF,
+ BMC150_MAGN_REG_REP_DATAMASK,
BMC150_MAGN_REPXY_TO_REGVAL
(val));
mutex_unlock(&data->mutex);
@@ -575,7 +576,7 @@
}
ret = regmap_update_bits(data->regmap,
BMC150_MAGN_REG_REP_Z,
- 0xFF,
+ BMC150_MAGN_REG_REP_DATAMASK,
BMC150_MAGN_REPZ_TO_REGVAL
(val));
mutex_unlock(&data->mutex);
@@ -588,17 +589,6 @@
}
}
-static int bmc150_magn_validate_trigger(struct iio_dev *indio_dev,
- struct iio_trigger *trig)
-{
- struct bmc150_magn_data *data = iio_priv(indio_dev);
-
- if (data->dready_trig != trig)
- return -EINVAL;
-
- return 0;
-}
-
static ssize_t bmc150_magn_show_samp_freq_avail(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -659,11 +649,12 @@
.attrs = &bmc150_magn_attrs_group,
.read_raw = bmc150_magn_read_raw,
.write_raw = bmc150_magn_write_raw,
- .validate_trigger = bmc150_magn_validate_trigger,
.driver_module = THIS_MODULE,
};
-static const unsigned long bmc150_magn_scan_masks[] = {0x07, 0};
+static const unsigned long bmc150_magn_scan_masks[] = {
+ BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
+ 0};
static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p)
{
@@ -674,7 +665,6 @@
mutex_lock(&data->mutex);
ret = bmc150_magn_read_xyz(data, data->buffer);
- mutex_unlock(&data->mutex);
if (ret < 0)
goto err;
@@ -682,7 +672,8 @@
pf->timestamp);
err:
- iio_trigger_notify_done(data->dready_trig);
+ mutex_unlock(&data->mutex);
+ iio_trigger_notify_done(indio_dev->trig);
return IRQ_HANDLED;
}
@@ -706,11 +697,11 @@
goto err_poweroff;
}
if (chip_id != BMC150_MAGN_CHIP_ID_VAL) {
- dev_err(&data->client->dev, "Invalid chip id 0x%x\n", ret);
+ dev_err(&data->client->dev, "Invalid chip id 0x%x\n", chip_id);
ret = -ENODEV;
goto err_poweroff;
}
- dev_dbg(&data->client->dev, "Chip id %x\n", ret);
+ dev_dbg(&data->client->dev, "Chip id %x\n", chip_id);
preset = bmc150_magn_presets_table[BMC150_MAGN_DEFAULT_PRESET];
ret = bmc150_magn_set_odr(data, preset.odr);
@@ -793,29 +784,23 @@
if (state == data->dready_trigger_on)
goto err_unlock;
- ret = bmc150_magn_set_power_state(data, state);
- if (ret < 0)
- goto err_unlock;
-
ret = regmap_update_bits(data->regmap, BMC150_MAGN_REG_INT_DRDY,
BMC150_MAGN_MASK_DRDY_EN,
state << BMC150_MAGN_SHIFT_DRDY_EN);
if (ret < 0)
- goto err_poweroff;
+ goto err_unlock;
data->dready_trigger_on = state;
if (state) {
ret = bmc150_magn_reset_intr(data);
if (ret < 0)
- goto err_poweroff;
+ goto err_unlock;
}
mutex_unlock(&data->mutex);
return 0;
-err_poweroff:
- bmc150_magn_set_power_state(data, false);
err_unlock:
mutex_unlock(&data->mutex);
return ret;
@@ -827,6 +812,27 @@
.owner = THIS_MODULE,
};
+static int bmc150_magn_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct bmc150_magn_data *data = iio_priv(indio_dev);
+
+ return bmc150_magn_set_power_state(data, true);
+}
+
+static int bmc150_magn_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct bmc150_magn_data *data = iio_priv(indio_dev);
+
+ return bmc150_magn_set_power_state(data, false);
+}
+
+static const struct iio_buffer_setup_ops bmc150_magn_buffer_setup_ops = {
+ .preenable = bmc150_magn_buffer_preenable,
+ .postenable = iio_triggered_buffer_postenable,
+ .predisable = iio_triggered_buffer_predisable,
+ .postdisable = bmc150_magn_buffer_postdisable,
+};
+
static int bmc150_magn_gpio_probe(struct i2c_client *client)
{
struct device *dev;
@@ -932,16 +938,6 @@
goto err_poweroff;
}
- ret = iio_triggered_buffer_setup(indio_dev,
- &iio_pollfunc_store_time,
- bmc150_magn_trigger_handler,
- NULL);
- if (ret < 0) {
- dev_err(&client->dev,
- "iio triggered buffer setup failed\n");
- goto err_trigger_unregister;
- }
-
ret = request_threaded_irq(client->irq,
iio_trigger_generic_data_rdy_poll,
NULL,
@@ -951,14 +947,24 @@
if (ret < 0) {
dev_err(&client->dev, "request irq %d failed\n",
client->irq);
- goto err_buffer_cleanup;
+ goto err_trigger_unregister;
}
}
+ ret = iio_triggered_buffer_setup(indio_dev,
+ iio_pollfunc_store_time,
+ bmc150_magn_trigger_handler,
+ &bmc150_magn_buffer_setup_ops);
+ if (ret < 0) {
+ dev_err(&client->dev,
+ "iio triggered buffer setup failed\n");
+ goto err_free_irq;
+ }
+
ret = iio_device_register(indio_dev);
if (ret < 0) {
dev_err(&client->dev, "unable to register iio device\n");
- goto err_free_irq;
+ goto err_buffer_cleanup;
}
ret = pm_runtime_set_active(&client->dev);
@@ -976,12 +982,11 @@
err_iio_unregister:
iio_device_unregister(indio_dev);
+err_buffer_cleanup:
+ iio_triggered_buffer_cleanup(indio_dev);
err_free_irq:
if (client->irq > 0)
free_irq(client->irq, data->dready_trig);
-err_buffer_cleanup:
- if (data->dready_trig)
- iio_triggered_buffer_cleanup(indio_dev);
err_trigger_unregister:
if (data->dready_trig)
iio_trigger_unregister(data->dready_trig);
@@ -1000,14 +1005,13 @@
pm_runtime_put_noidle(&client->dev);
iio_device_unregister(indio_dev);
+ iio_triggered_buffer_cleanup(indio_dev);
if (client->irq > 0)
free_irq(data->client->irq, data->dready_trig);
- if (data->dready_trig) {
- iio_triggered_buffer_cleanup(indio_dev);
+ if (data->dready_trig)
iio_trigger_unregister(data->dready_trig);
- }
mutex_lock(&data->mutex);
bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true);
@@ -1034,6 +1038,9 @@
return 0;
}
+/*
+ * Should be called with data->mutex held.
+ */
static int bmc150_magn_runtime_resume(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
@@ -1082,12 +1089,14 @@
static const struct acpi_device_id bmc150_magn_acpi_match[] = {
{"BMC150B", 0},
+ {"BMC156B", 0},
{},
};
MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
static const struct i2c_device_id bmc150_magn_id[] = {
{"bmc150_magn", 0},
+ {"bmc156_magn", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, bmc150_magn_id);
diff --git a/drivers/iio/magnetometer/mmc35240.c b/drivers/iio/magnetometer/mmc35240.c
index d927397..176e14a 100644
--- a/drivers/iio/magnetometer/mmc35240.c
+++ b/drivers/iio/magnetometer/mmc35240.c
@@ -202,8 +202,8 @@
coil_bit = MMC35240_CTRL0_RESET_BIT;
return regmap_update_bits(data->regmap, MMC35240_REG_CTRL0,
- MMC35240_CTRL0_REFILL_BIT,
- coil_bit);
+ coil_bit, coil_bit);
+
}
static int mmc35240_init(struct mmc35240_data *data)
@@ -222,14 +222,15 @@
/*
* make sure we restore sensor characteristics, by doing
- * a RESET/SET sequence
+ * a SET/RESET sequence, the axis polarity being naturally
+ * aligned after RESET
*/
- ret = mmc35240_hw_set(data, false);
+ ret = mmc35240_hw_set(data, true);
if (ret < 0)
return ret;
usleep_range(MMC53240_WAIT_SET_RESET, MMC53240_WAIT_SET_RESET + 1);
- ret = mmc35240_hw_set(data, true);
+ ret = mmc35240_hw_set(data, false);
if (ret < 0)
return ret;
@@ -315,31 +316,31 @@
static int mmc35240_raw_to_mgauss(struct mmc35240_data *data, int index,
__le16 buf[], int *val)
{
- int raw_x, raw_y, raw_z;
- int sens_x, sens_y, sens_z;
+ int raw[3];
+ int sens[3];
int nfo;
- raw_x = le16_to_cpu(buf[AXIS_X]);
- raw_y = le16_to_cpu(buf[AXIS_Y]);
- raw_z = le16_to_cpu(buf[AXIS_Z]);
+ raw[AXIS_X] = le16_to_cpu(buf[AXIS_X]);
+ raw[AXIS_Y] = le16_to_cpu(buf[AXIS_Y]);
+ raw[AXIS_Z] = le16_to_cpu(buf[AXIS_Z]);
- sens_x = mmc35240_props_table[data->res].sens[AXIS_X];
- sens_y = mmc35240_props_table[data->res].sens[AXIS_Y];
- sens_z = mmc35240_props_table[data->res].sens[AXIS_Z];
+ sens[AXIS_X] = mmc35240_props_table[data->res].sens[AXIS_X];
+ sens[AXIS_Y] = mmc35240_props_table[data->res].sens[AXIS_Y];
+ sens[AXIS_Z] = mmc35240_props_table[data->res].sens[AXIS_Z];
nfo = mmc35240_props_table[data->res].nfo;
switch (index) {
case AXIS_X:
- *val = (raw_x - nfo) * 1000 / sens_x;
+ *val = (raw[AXIS_X] - nfo) * 1000 / sens[AXIS_X];
break;
case AXIS_Y:
- *val = (raw_y - nfo) * 1000 / sens_y -
- (raw_z - nfo) * 1000 / sens_z;
+ *val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] -
+ (raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z];
break;
case AXIS_Z:
- *val = (raw_y - nfo) * 1000 / sens_y +
- (raw_z - nfo) * 1000 / sens_z;
+ *val = (raw[AXIS_Y] - nfo) * 1000 / sens[AXIS_Y] +
+ (raw[AXIS_Z] - nfo) * 1000 / sens[AXIS_Z];
break;
default:
return -EINVAL;
@@ -503,6 +504,7 @@
}
data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
data->client = client;
data->regmap = regmap;
data->res = MMC35240_16_BITS_SLOW;
@@ -557,6 +559,12 @@
SET_SYSTEM_SLEEP_PM_OPS(mmc35240_suspend, mmc35240_resume)
};
+static const struct of_device_id mmc35240_of_match[] = {
+ { .compatible = "memsic,mmc35240", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mmc35240_of_match);
+
static const struct acpi_device_id mmc35240_acpi_match[] = {
{"MMC35240", 0},
{ },
@@ -572,6 +580,7 @@
static struct i2c_driver mmc35240_driver = {
.driver = {
.name = MMC35240_DRV_NAME,
+ .of_match_table = mmc35240_of_match,
.pm = &mmc35240_pm_ops,
.acpi_match_table = ACPI_PTR(mmc35240_acpi_match),
},
diff --git a/drivers/iio/magnetometer/st_magn.h b/drivers/iio/magnetometer/st_magn.h
index 287691c..06a4d9c 100644
--- a/drivers/iio/magnetometer/st_magn.h
+++ b/drivers/iio/magnetometer/st_magn.h
@@ -18,6 +18,7 @@
#define LSM303DLHC_MAGN_DEV_NAME "lsm303dlhc_magn"
#define LSM303DLM_MAGN_DEV_NAME "lsm303dlm_magn"
#define LIS3MDL_MAGN_DEV_NAME "lis3mdl"
+#define LSM303AGR_MAGN_DEV_NAME "lsm303agr_magn"
int st_magn_common_probe(struct iio_dev *indio_dev);
void st_magn_common_remove(struct iio_dev *indio_dev);
@@ -25,6 +26,8 @@
#ifdef CONFIG_IIO_BUFFER
int st_magn_allocate_ring(struct iio_dev *indio_dev);
void st_magn_deallocate_ring(struct iio_dev *indio_dev);
+int st_magn_trig_set_state(struct iio_trigger *trig, bool state);
+#define ST_MAGN_TRIGGER_SET_STATE (&st_magn_trig_set_state)
#else /* CONFIG_IIO_BUFFER */
static inline int st_magn_probe_trigger(struct iio_dev *indio_dev, int irq)
{
diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c
index bf427dc..ecd3bd0 100644
--- a/drivers/iio/magnetometer/st_magn_buffer.c
+++ b/drivers/iio/magnetometer/st_magn_buffer.c
@@ -23,6 +23,13 @@
#include <linux/iio/common/st_sensors.h>
#include "st_magn.h"
+int st_magn_trig_set_state(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+
+ return st_sensors_set_dataready_irq(indio_dev, state);
+}
+
static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
{
return st_sensors_set_enable(indio_dev, true);
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index b4bcfb7..f8dc4b8 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -43,6 +43,7 @@
#define ST_MAGN_FS_AVL_8000MG 8000
#define ST_MAGN_FS_AVL_8100MG 8100
#define ST_MAGN_FS_AVL_12000MG 12000
+#define ST_MAGN_FS_AVL_15000MG 15000
#define ST_MAGN_FS_AVL_16000MG 16000
/* CUSTOM VALUES FOR SENSOR 0 */
@@ -157,6 +158,29 @@
#define ST_MAGN_2_OUT_Y_L_ADDR 0x2a
#define ST_MAGN_2_OUT_Z_L_ADDR 0x2c
+/* CUSTOM VALUES FOR SENSOR 3 */
+#define ST_MAGN_3_WAI_ADDR 0x4f
+#define ST_MAGN_3_WAI_EXP 0x40
+#define ST_MAGN_3_ODR_ADDR 0x60
+#define ST_MAGN_3_ODR_MASK 0x0c
+#define ST_MAGN_3_ODR_AVL_10HZ_VAL 0x00
+#define ST_MAGN_3_ODR_AVL_20HZ_VAL 0x01
+#define ST_MAGN_3_ODR_AVL_50HZ_VAL 0x02
+#define ST_MAGN_3_ODR_AVL_100HZ_VAL 0x03
+#define ST_MAGN_3_PW_ADDR 0x60
+#define ST_MAGN_3_PW_MASK 0x03
+#define ST_MAGN_3_PW_ON 0x00
+#define ST_MAGN_3_PW_OFF 0x03
+#define ST_MAGN_3_BDU_ADDR 0x62
+#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_FS_AVL_15000_GAIN 1500
+#define ST_MAGN_3_MULTIREAD_BIT false
+#define ST_MAGN_3_OUT_X_L_ADDR 0x68
+#define ST_MAGN_3_OUT_Y_L_ADDR 0x6a
+#define ST_MAGN_3_OUT_Z_L_ADDR 0x6c
+
static const struct iio_chan_spec st_magn_16bit_channels[] = {
ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
@@ -189,9 +213,26 @@
IIO_CHAN_SOFT_TIMESTAMP(3)
};
+static const struct iio_chan_spec st_magn_3_16bit_channels[] = {
+ ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+ BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+ ST_SENSORS_SCAN_X, 1, IIO_MOD_X, 's', IIO_LE, 16, 16,
+ ST_MAGN_3_OUT_X_L_ADDR),
+ ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+ BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+ ST_SENSORS_SCAN_Y, 1, IIO_MOD_Y, 's', IIO_LE, 16, 16,
+ ST_MAGN_3_OUT_Y_L_ADDR),
+ ST_SENSORS_LSM_CHANNELS(IIO_MAGN,
+ BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
+ ST_SENSORS_SCAN_Z, 1, IIO_MOD_Z, 's', IIO_LE, 16, 16,
+ ST_MAGN_3_OUT_Z_L_ADDR),
+ IIO_CHAN_SOFT_TIMESTAMP(3)
+};
+
static const struct st_sensor_settings st_magn_sensors_settings[] = {
{
.wai = 0, /* This sensor has no valid WhoAmI report 0 */
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM303DLH_MAGN_DEV_NAME,
},
@@ -268,6 +309,7 @@
},
{
.wai = ST_MAGN_1_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LSM303DLHC_MAGN_DEV_NAME,
[1] = LSM303DLM_MAGN_DEV_NAME,
@@ -346,6 +388,7 @@
},
{
.wai = ST_MAGN_2_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LIS3MDL_MAGN_DEV_NAME,
},
@@ -399,6 +442,48 @@
.multi_read_bit = ST_MAGN_2_MULTIREAD_BIT,
.bootime = 2,
},
+ {
+ .wai = ST_MAGN_3_WAI_EXP,
+ .wai_addr = ST_MAGN_3_WAI_ADDR,
+ .sensors_supported = {
+ [0] = LSM303AGR_MAGN_DEV_NAME,
+ },
+ .ch = (struct iio_chan_spec *)st_magn_3_16bit_channels,
+ .odr = {
+ .addr = ST_MAGN_3_ODR_ADDR,
+ .mask = ST_MAGN_3_ODR_MASK,
+ .odr_avl = {
+ { 10, ST_MAGN_3_ODR_AVL_10HZ_VAL, },
+ { 20, ST_MAGN_3_ODR_AVL_20HZ_VAL, },
+ { 50, ST_MAGN_3_ODR_AVL_50HZ_VAL, },
+ { 100, ST_MAGN_3_ODR_AVL_100HZ_VAL, },
+ },
+ },
+ .pw = {
+ .addr = ST_MAGN_3_PW_ADDR,
+ .mask = ST_MAGN_3_PW_MASK,
+ .value_on = ST_MAGN_3_PW_ON,
+ .value_off = ST_MAGN_3_PW_OFF,
+ },
+ .fs = {
+ .fs_avl = {
+ [0] = {
+ .num = ST_MAGN_FS_AVL_15000MG,
+ .gain = ST_MAGN_3_FS_AVL_15000_GAIN,
+ },
+ },
+ },
+ .bdu = {
+ .addr = ST_MAGN_3_BDU_ADDR,
+ .mask = ST_MAGN_3_BDU_MASK,
+ },
+ .drdy_irq = {
+ .addr = ST_MAGN_3_DRDY_IRQ_ADDR,
+ .mask_int1 = ST_MAGN_3_DRDY_INT_MASK,
+ },
+ .multi_read_bit = ST_MAGN_3_MULTIREAD_BIT,
+ .bootime = 2,
+ },
};
static int st_magn_read_raw(struct iio_dev *indio_dev,
@@ -477,6 +562,16 @@
.write_raw = &st_magn_write_raw,
};
+#ifdef CONFIG_IIO_TRIGGER
+static const struct iio_trigger_ops st_magn_trigger_ops = {
+ .owner = THIS_MODULE,
+ .set_trigger_state = ST_MAGN_TRIGGER_SET_STATE,
+};
+#define ST_MAGN_TRIGGER_OPS (&st_magn_trigger_ops)
+#else
+#define ST_MAGN_TRIGGER_OPS NULL
+#endif
+
int st_magn_common_probe(struct iio_dev *indio_dev)
{
struct st_sensor_data *mdata = iio_priv(indio_dev);
@@ -513,7 +608,8 @@
return err;
if (irq > 0) {
- err = st_sensors_allocate_trigger(indio_dev, NULL);
+ err = st_sensors_allocate_trigger(indio_dev,
+ ST_MAGN_TRIGGER_OPS);
if (err < 0)
goto st_magn_probe_trigger_error;
}
diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
index 5311d8a..8aa37af 100644
--- a/drivers/iio/magnetometer/st_magn_i2c.c
+++ b/drivers/iio/magnetometer/st_magn_i2c.c
@@ -36,6 +36,10 @@
.compatible = "st,lis3mdl-magn",
.data = LIS3MDL_MAGN_DEV_NAME,
},
+ {
+ .compatible = "st,lsm303agr-magn",
+ .data = LSM303AGR_MAGN_DEV_NAME,
+ },
{},
};
MODULE_DEVICE_TABLE(of, st_magn_of_match);
@@ -79,13 +83,13 @@
{ LSM303DLHC_MAGN_DEV_NAME },
{ LSM303DLM_MAGN_DEV_NAME },
{ LIS3MDL_MAGN_DEV_NAME },
+ { LSM303AGR_MAGN_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(i2c, st_magn_id_table);
static struct i2c_driver st_magn_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "st-magn-i2c",
.of_match_table = of_match_ptr(st_magn_of_match),
},
diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
index 7adacf1..0abca2c 100644
--- a/drivers/iio/magnetometer/st_magn_spi.c
+++ b/drivers/iio/magnetometer/st_magn_spi.c
@@ -51,6 +51,7 @@
{ LSM303DLHC_MAGN_DEV_NAME },
{ LSM303DLM_MAGN_DEV_NAME },
{ LIS3MDL_MAGN_DEV_NAME },
+ { LSM303AGR_MAGN_DEV_NAME },
{},
};
MODULE_DEVICE_TABLE(spi, st_magn_id_table);
diff --git a/drivers/iio/pressure/Kconfig b/drivers/iio/pressure/Kconfig
index fa62950..4745179 100644
--- a/drivers/iio/pressure/Kconfig
+++ b/drivers/iio/pressure/Kconfig
@@ -53,10 +53,10 @@
will be called mpl3115.
config MS5611
- tristate "Measurement Specialities MS5611 pressure sensor driver"
+ tristate "Measurement Specialties MS5611 pressure sensor driver"
help
- Say Y here to build support for the Measurement Specialities
- MS5611 pressure and temperature sensor.
+ Say Y here to build support for the Measurement Specialties
+ MS5611, MS5607 pressure and temperature sensors.
To compile this driver as a module, choose M here: the module will
be called ms5611_core.
diff --git a/drivers/iio/pressure/ms5611.h b/drivers/iio/pressure/ms5611.h
index 099c6cd..23b93c7 100644
--- a/drivers/iio/pressure/ms5611.h
+++ b/drivers/iio/pressure/ms5611.h
@@ -27,6 +27,18 @@
#define MS5611_PROM_WORDS_NB 8
+enum {
+ MS5611,
+ MS5607,
+};
+
+struct ms5611_chip_info {
+ u16 prom[MS5611_PROM_WORDS_NB];
+
+ int (*temp_and_pressure_compensate)(struct ms5611_chip_info *chip_info,
+ s32 *temp, s32 *pressure);
+};
+
struct ms5611_state {
void *client;
struct mutex lock;
@@ -36,9 +48,9 @@
int (*read_adc_temp_and_pressure)(struct device *dev,
s32 *temp, s32 *pressure);
- u16 prom[MS5611_PROM_WORDS_NB];
+ struct ms5611_chip_info *chip_info;
};
-int ms5611_probe(struct iio_dev *indio_dev, struct device *dev);
+int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type);
#endif /* _MS5611_H */
diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c
index e42c853..2f3d9b4 100644
--- a/drivers/iio/pressure/ms5611_core.c
+++ b/drivers/iio/pressure/ms5611_core.c
@@ -9,6 +9,7 @@
*
* Data sheet:
* http://www.meas-spec.com/downloads/MS5611-01BA03.pdf
+ * http://www.meas-spec.com/downloads/MS5607-02BA03.pdf
*
*/
@@ -50,7 +51,8 @@
struct ms5611_state *st = iio_priv(indio_dev);
for (i = 0; i < MS5611_PROM_WORDS_NB; i++) {
- ret = st->read_prom_word(&indio_dev->dev, i, &st->prom[i]);
+ ret = st->read_prom_word(&indio_dev->dev,
+ i, &st->chip_info->prom[i]);
if (ret < 0) {
dev_err(&indio_dev->dev,
"failed to read prom at %d\n", i);
@@ -58,7 +60,7 @@
}
}
- if (!ms5611_prom_is_valid(st->prom, MS5611_PROM_WORDS_NB)) {
+ if (!ms5611_prom_is_valid(st->chip_info->prom, MS5611_PROM_WORDS_NB)) {
dev_err(&indio_dev->dev, "PROM integrity check failed\n");
return -ENODEV;
}
@@ -70,22 +72,30 @@
s32 *temp, s32 *pressure)
{
int ret;
- s32 t, p;
- s64 off, sens, dt;
struct ms5611_state *st = iio_priv(indio_dev);
- ret = st->read_adc_temp_and_pressure(&indio_dev->dev, &t, &p);
+ ret = st->read_adc_temp_and_pressure(&indio_dev->dev, temp, pressure);
if (ret < 0) {
dev_err(&indio_dev->dev,
"failed to read temperature and pressure\n");
return ret;
}
- dt = t - (st->prom[5] << 8);
- off = ((s64)st->prom[2] << 16) + ((st->prom[4] * dt) >> 7);
- sens = ((s64)st->prom[1] << 15) + ((st->prom[3] * dt) >> 8);
+ return st->chip_info->temp_and_pressure_compensate(st->chip_info,
+ temp, pressure);
+}
- t = 2000 + ((st->prom[6] * dt) >> 23);
+static int ms5611_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
+ s32 *temp, s32 *pressure)
+{
+ s32 t = *temp, p = *pressure;
+ s64 off, sens, dt;
+
+ dt = t - (chip_info->prom[5] << 8);
+ off = ((s64)chip_info->prom[2] << 16) + ((chip_info->prom[4] * dt) >> 7);
+ sens = ((s64)chip_info->prom[1] << 15) + ((chip_info->prom[3] * dt) >> 8);
+
+ t = 2000 + ((chip_info->prom[6] * dt) >> 23);
if (t < 2000) {
s64 off2, sens2, t2;
@@ -111,6 +121,42 @@
return 0;
}
+static int ms5607_temp_and_pressure_compensate(struct ms5611_chip_info *chip_info,
+ s32 *temp, s32 *pressure)
+{
+ s32 t = *temp, p = *pressure;
+ s64 off, sens, dt;
+
+ dt = t - (chip_info->prom[5] << 8);
+ off = ((s64)chip_info->prom[2] << 17) + ((chip_info->prom[4] * dt) >> 6);
+ sens = ((s64)chip_info->prom[1] << 16) + ((chip_info->prom[3] * dt) >> 7);
+
+ t = 2000 + ((chip_info->prom[6] * dt) >> 23);
+ if (t < 2000) {
+ s64 off2, sens2, t2;
+
+ t2 = (dt * dt) >> 31;
+ off2 = (61 * (t - 2000) * (t - 2000)) >> 4;
+ sens2 = off2 << 1;
+
+ if (t < -1500) {
+ s64 tmp = (t + 1500) * (t + 1500);
+
+ off2 += 15 * tmp;
+ sens2 += (8 * tmp);
+ }
+
+ t -= t2;
+ off -= off2;
+ sens -= sens2;
+ }
+
+ *temp = t;
+ *pressure = (((p * sens) >> 21) - off) >> 15;
+
+ return 0;
+}
+
static int ms5611_reset(struct iio_dev *indio_dev)
{
int ret;
@@ -160,16 +206,23 @@
return -EINVAL;
}
+static struct ms5611_chip_info chip_info_tbl[] = {
+ [MS5611] = {
+ .temp_and_pressure_compensate = ms5611_temp_and_pressure_compensate,
+ },
+ [MS5607] = {
+ .temp_and_pressure_compensate = ms5607_temp_and_pressure_compensate,
+ }
+};
+
static const struct iio_chan_spec ms5611_channels[] = {
{
.type = IIO_PRESSURE,
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
- BIT(IIO_CHAN_INFO_SCALE)
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
},
{
.type = IIO_TEMP,
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
- BIT(IIO_CHAN_INFO_SCALE)
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
}
};
@@ -189,12 +242,13 @@
return ms5611_read_prom(indio_dev);
}
-int ms5611_probe(struct iio_dev *indio_dev, struct device *dev)
+int ms5611_probe(struct iio_dev *indio_dev, struct device *dev, int type)
{
int ret;
struct ms5611_state *st = iio_priv(indio_dev);
mutex_init(&st->lock);
+ st->chip_info = &chip_info_tbl[type];
indio_dev->dev.parent = dev;
indio_dev->name = dev->driver->name;
indio_dev->info = &ms5611_info;
diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c
index 748fd9a..245797d 100644
--- a/drivers/iio/pressure/ms5611_i2c.c
+++ b/drivers/iio/pressure/ms5611_i2c.c
@@ -104,11 +104,12 @@
st->read_adc_temp_and_pressure = ms5611_i2c_read_adc_temp_and_pressure;
st->client = client;
- return ms5611_probe(indio_dev, &client->dev);
+ return ms5611_probe(indio_dev, &client->dev, id->driver_data);
}
static const struct i2c_device_id ms5611_id[] = {
- { "ms5611", 0 },
+ { "ms5611", MS5611 },
+ { "ms5607", MS5607 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ms5611_id);
@@ -116,7 +117,6 @@
static struct i2c_driver ms5611_driver = {
.driver = {
.name = "ms5611",
- .owner = THIS_MODULE,
},
.id_table = ms5611_id,
.probe = ms5611_i2c_probe,
diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c
index 976726f..08ee6e8 100644
--- a/drivers/iio/pressure/ms5611_spi.c
+++ b/drivers/iio/pressure/ms5611_spi.c
@@ -103,11 +103,13 @@
st->read_adc_temp_and_pressure = ms5611_spi_read_adc_temp_and_pressure;
st->client = spi;
- return ms5611_probe(indio_dev, &spi->dev);
+ return ms5611_probe(indio_dev, &spi->dev,
+ spi_get_device_id(spi)->driver_data);
}
static const struct spi_device_id ms5611_id[] = {
- { "ms5611", 0 },
+ { "ms5611", MS5611 },
+ { "ms5607", MS5607 },
{ }
};
MODULE_DEVICE_TABLE(spi, ms5611_id);
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index e881fa6..eb41d2b 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -178,6 +178,7 @@
static const struct st_sensor_settings st_press_sensors_settings[] = {
{
.wai = ST_PRESS_LPS331AP_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LPS331AP_PRESS_DEV_NAME,
},
@@ -225,6 +226,7 @@
},
{
.wai = ST_PRESS_LPS001WP_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LPS001WP_PRESS_DEV_NAME,
},
@@ -260,6 +262,7 @@
},
{
.wai = ST_PRESS_LPS25H_WAI_EXP,
+ .wai_addr = ST_SENSORS_DEFAULT_WAI_ADDRESS,
.sensors_supported = {
[0] = LPS25H_PRESS_DEV_NAME,
},
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index 137788b..8fcf976 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -79,7 +79,6 @@
static struct i2c_driver st_press_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "st-press-i2c",
.of_match_table = of_match_ptr(st_press_of_match),
},
diff --git a/drivers/iio/temperature/mlx90614.c b/drivers/iio/temperature/mlx90614.c
index cb2e8ad..5d033a5 100644
--- a/drivers/iio/temperature/mlx90614.c
+++ b/drivers/iio/temperature/mlx90614.c
@@ -65,6 +65,13 @@
#define MLX90614_AUTOSLEEP_DELAY 5000 /* default autosleep delay */
+/* Magic constants */
+#define MLX90614_CONST_OFFSET_DEC -13657 /* decimal part of the Kelvin offset */
+#define MLX90614_CONST_OFFSET_REM 500000 /* remainder of offset (273.15*50) */
+#define MLX90614_CONST_SCALE 20 /* Scale in milliKelvin (0.02 * 1000) */
+#define MLX90614_CONST_RAW_EMISSIVITY_MAX 65535 /* max value for emissivity */
+#define MLX90614_CONST_EMISSIVITY_RESOLUTION 15259 /* 1/65535 ~ 0.000015259 */
+
struct mlx90614_data {
struct i2c_client *client;
struct mutex lock; /* for EEPROM access only */
@@ -204,11 +211,11 @@
*val = ret;
return IIO_VAL_INT;
case IIO_CHAN_INFO_OFFSET:
- *val = 13657;
- *val2 = 500000;
+ *val = MLX90614_CONST_OFFSET_DEC;
+ *val2 = MLX90614_CONST_OFFSET_REM;
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_SCALE:
- *val = 20;
+ *val = MLX90614_CONST_SCALE;
return IIO_VAL_INT;
case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
mlx90614_power_get(data, false);
@@ -221,12 +228,12 @@
if (ret < 0)
return ret;
- if (ret == 65535) {
+ if (ret == MLX90614_CONST_RAW_EMISSIVITY_MAX) {
*val = 1;
*val2 = 0;
} else {
*val = 0;
- *val2 = ret * 15259; /* 1/65535 ~ 0.000015259 */
+ *val2 = ret * MLX90614_CONST_EMISSIVITY_RESOLUTION;
}
return IIO_VAL_INT_PLUS_NANO;
default:
@@ -245,7 +252,8 @@
case IIO_CHAN_INFO_CALIBEMISSIVITY: /* 1/65535 / LSB */
if (val < 0 || val2 < 0 || val > 1 || (val == 1 && val2 != 0))
return -EINVAL;
- val = val * 65535 + val2 / 15259; /* 1/65535 ~ 0.000015259 */
+ val = val * MLX90614_CONST_RAW_EMISSIVITY_MAX +
+ val2 / MLX90614_CONST_EMISSIVITY_RESOLUTION;
mlx90614_power_get(data, false);
mutex_lock(&data->lock);
@@ -551,7 +559,6 @@
static struct i2c_driver mlx90614_driver = {
.driver = {
.name = "mlx90614",
- .owner = THIS_MODULE,
.pm = &mlx90614_pm_ops,
},
.probe = mlx90614_probe,
diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c
index 8f21f32..e78c106 100644
--- a/drivers/iio/temperature/tmp006.c
+++ b/drivers/iio/temperature/tmp006.c
@@ -36,9 +36,9 @@
#define TMP006_CONFIG_DRDY_EN BIT(8)
#define TMP006_CONFIG_DRDY BIT(7)
-#define TMP006_CONFIG_MOD_MASK 0x7000
+#define TMP006_CONFIG_MOD_MASK GENMASK(14, 12)
-#define TMP006_CONFIG_CR_MASK 0x0e00
+#define TMP006_CONFIG_CR_MASK GENMASK(11, 9)
#define TMP006_CONFIG_CR_SHIFT 9
#define TMP006_MANUFACTURER_MAGIC 0x5449
@@ -280,7 +280,6 @@
.driver = {
.name = "tmp006",
.pm = &tmp006_pm_ops,
- .owner = THIS_MODULE,
},
.probe = tmp006_probe,
.remove = tmp006_remove,
diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index b1b7323..bbbe018 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_provider.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c
@@ -736,6 +736,10 @@
/*
* T3 only supports 32 bits of size.
*/
+ if (sizeof(phys_addr_t) > 4) {
+ pr_warn_once(MOD "Cannot support dma_mrs on this platform.\n");
+ return ERR_PTR(-ENOTSUPP);
+ }
bl.size = 0xffffffff;
bl.addr = 0;
kva = 0;
diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c
index c7aab48..92d5183 100644
--- a/drivers/infiniband/hw/cxgb4/cq.c
+++ b/drivers/infiniband/hw/cxgb4/cq.c
@@ -814,7 +814,7 @@
printk(KERN_ERR MOD
"Unexpected cqe_status 0x%x for QPID=0x%0x\n",
CQE_STATUS(&cqe), CQE_QPID(&cqe));
- ret = -EINVAL;
+ wc->status = IB_WC_FATAL_ERR;
}
}
out:
diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c
index 2d7e503..871dbe5 100644
--- a/drivers/infiniband/hw/ipath/ipath_driver.c
+++ b/drivers/infiniband/hw/ipath/ipath_driver.c
@@ -31,6 +31,8 @@
* SOFTWARE.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
@@ -399,8 +401,8 @@
u32 bar0 = 0, bar1 = 0;
#ifdef CONFIG_X86_64
- if (WARN(pat_enabled(),
- "ipath needs PAT disabled, boot with nopat kernel parameter\n")) {
+ if (pat_enabled()) {
+ pr_warn("ipath needs PAT disabled, boot with nopat kernel parameter\n");
ret = -ENODEV;
goto bail;
}
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma.h b/drivers/infiniband/hw/ocrdma/ocrdma.h
index b396344..6a36338 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma.h
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#ifndef __OCRDMA_H__
#define __OCRDMA_H__
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_abi.h b/drivers/infiniband/hw/ocrdma/ocrdma_abi.h
index 1554cca..430b135 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_abi.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_abi.h
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#ifndef __OCRDMA_ABI_H__
#define __OCRDMA_ABI_H__
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
index 29b2767..44766fe 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#include <net/neighbour.h>
#include <net/netevent.h>
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.h b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h
index cf366fe..04a30ae 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.h
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#ifndef __OCRDMA_AH_H__
#define __OCRDMA_AH_H__
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
index 47615ff..aab391a 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.c
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) CNA Adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#include <linux/sched.h>
#include <linux/interrupt.h>
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
index e905972..7ed885c 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_hw.h
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) CNA Adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#ifndef __OCRDMA_HW_H__
#define __OCRDMA_HW_H__
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_main.c b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
index d98a707..b119a34 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_main.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_main.c
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#include <linux/module.h>
#include <linux/idr.h>
@@ -46,7 +61,7 @@
MODULE_VERSION(OCRDMA_ROCE_DRV_VERSION);
MODULE_DESCRIPTION(OCRDMA_ROCE_DRV_DESC " " OCRDMA_ROCE_DRV_VERSION);
MODULE_AUTHOR("Emulex Corporation");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
static LIST_HEAD(ocrdma_dev_list);
static DEFINE_SPINLOCK(ocrdma_devlist_lock);
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
index 02ad0ae..80006b2 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_sli.h
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#ifndef __OCRDMA_SLI_H__
#define __OCRDMA_SLI_H__
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
index 48d7ef5..69334e2 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.c
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2014 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#include <rdma/ib_addr.h>
#include <rdma/ib_pma.h>
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_stats.h b/drivers/infiniband/hw/ocrdma/ocrdma_stats.h
index 091edd6..c9e58d0 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_stats.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_stats.h
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2014 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#ifndef __OCRDMA_STATS_H__
#define __OCRDMA_STATS_H__
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
index 5bb61eb..bc84cd4 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#include <linux/dma-mapping.h>
#include <rdma/ib_verbs.h>
diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
index b15c608..eaccb2d 100644
--- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
+++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.h
@@ -1,21 +1,36 @@
-/*******************************************************************
- * This file is part of the Emulex RoCE Device Driver for *
- * RoCE (RDMA over Converged Ethernet) adapters. *
- * Copyright (C) 2008-2012 Emulex. All rights reserved. *
- * EMULEX and SLI are trademarks of Emulex. *
- * www.emulex.com *
- * *
- * 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. *
- * This program is distributed in the hope that it will be useful. *
- * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND *
- * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, *
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT, ARE *
- * DISCLAIMED, EXCEPT TO THE EXTENT THAT SUCH DISCLAIMERS ARE HELD *
- * TO BE LEGALLY INVALID. See the GNU General Public License for *
- * more details, a copy of which can be found in the file COPYING *
- * included with this package. *
+/* This file is part of the Emulex RoCE Device Driver for
+ * RoCE (RDMA over Converged Ethernet) adapters.
+ * Copyright (C) 2012-2015 Emulex. All rights reserved.
+ * EMULEX and SLI are trademarks of Emulex.
+ * www.emulex.com
+ *
+ * This software is available to you under a choice of one of two licenses.
+ * You may choose to be licensed under the terms of the GNU General Public
+ * License (GPL) Version 2, available from the file COPYING in the main
+ * directory of this source tree, or the BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contact Information:
* linux-drivers@emulex.com
@@ -23,7 +38,7 @@
* Emulex
* 3333 Susan Street
* Costa Mesa, CA 92626
- *******************************************************************/
+ */
#ifndef __OCRDMA_VERBS_H__
#define __OCRDMA_VERBS_H__
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
index 9e6ee82..851c821 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
@@ -177,7 +177,8 @@
else
size += ipoib_recvq_size * ipoib_max_conn_qp;
} else
- goto out_free_wq;
+ if (ret != -ENOSYS)
+ goto out_free_wq;
cq_attr.cqe = size;
priv->recv_cq = ib_create_cq(priv->ca, ipoib_ib_completion, NULL,
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 7717009..d851e18 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -775,6 +775,17 @@
ret = isert_rdma_post_recvl(isert_conn);
if (ret)
goto out_conn_dev;
+ /*
+ * Obtain the second reference now before isert_rdma_accept() to
+ * ensure that any initiator generated REJECT CM event that occurs
+ * asynchronously won't drop the last reference until the error path
+ * in iscsi_target_login_sess_out() does it's ->iscsit_free_conn() ->
+ * isert_free_conn() -> isert_put_conn() -> kref_put().
+ */
+ if (!kref_get_unless_zero(&isert_conn->kref)) {
+ isert_warn("conn %p connect_release is running\n", isert_conn);
+ goto out_conn_dev;
+ }
ret = isert_rdma_accept(isert_conn);
if (ret)
@@ -836,11 +847,6 @@
isert_info("conn %p\n", isert_conn);
- if (!kref_get_unless_zero(&isert_conn->kref)) {
- isert_warn("conn %p connect_release is running\n", isert_conn);
- return;
- }
-
mutex_lock(&isert_conn->mutex);
if (isert_conn->state != ISER_CONN_FULL_FEATURE)
isert_conn->state = ISER_CONN_UP;
diff --git a/drivers/input/input-leds.c b/drivers/input/input-leds.c
index 074a65e..766bf26 100644
--- a/drivers/input/input-leds.c
+++ b/drivers/input/input-leds.c
@@ -71,6 +71,18 @@
{
}
+static int input_leds_get_count(struct input_dev *dev)
+{
+ unsigned int led_code;
+ int count = 0;
+
+ for_each_set_bit(led_code, dev->ledbit, LED_CNT)
+ if (input_led_info[led_code].name)
+ count++;
+
+ return count;
+}
+
static int input_leds_connect(struct input_handler *handler,
struct input_dev *dev,
const struct input_device_id *id)
@@ -81,7 +93,7 @@
int led_no;
int error;
- num_leds = bitmap_weight(dev->ledbit, LED_CNT);
+ num_leds = input_leds_get_count(dev);
if (!num_leds)
return -ENXIO;
@@ -112,7 +124,7 @@
led->handle = &leds->handle;
led->code = led_code;
- if (WARN_ON(!input_led_info[led_code].name))
+ if (!input_led_info[led_code].name)
continue;
led->cdev.name = kasprintf(GFP_KERNEL, "%s::%s",
diff --git a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
index 27b6a3c..891797a 100644
--- a/drivers/input/joystick/turbografx.c
+++ b/drivers/input/joystick/turbografx.c
@@ -196,7 +196,7 @@
if (n_buttons[i] < 1)
continue;
- if (n_buttons[i] > 6) {
+ if (n_buttons[i] > ARRAY_SIZE(tgfx_buttons)) {
printk(KERN_ERR "turbografx.c: Invalid number of buttons %d\n", n_buttons[i]);
err = -EINVAL;
goto err_unreg_devs;
diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 097d721..c6dc644 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -246,7 +246,7 @@
* convert it to descriptor.
*/
if (!button->gpiod && gpio_is_valid(button->gpio)) {
- unsigned flags = 0;
+ unsigned flags = GPIOF_IN;
if (button->active_low)
flags |= GPIOF_ACTIVE_LOW;
diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c
index 10e140a..1ac898d 100644
--- a/drivers/input/misc/axp20x-pek.c
+++ b/drivers/input/misc/axp20x-pek.c
@@ -292,3 +292,4 @@
MODULE_DESCRIPTION("axp20x Power Button");
MODULE_AUTHOR("Carlo Caione <carlo@caione.org>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:axp20x-pek");
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c
index fc17b95..10c4e3d 100644
--- a/drivers/input/misc/twl4030-vibra.c
+++ b/drivers/input/misc/twl4030-vibra.c
@@ -183,7 +183,8 @@
if (pdata && pdata->coexist)
return true;
- if (of_find_node_by_name(node, "codec")) {
+ node = of_find_node_by_name(node, "codec");
+ if (node) {
of_node_put(node);
return true;
}
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
index 113d6f1..4d24686 100644
--- a/drivers/input/mouse/alps.c
+++ b/drivers/input/mouse/alps.c
@@ -20,6 +20,7 @@
#include <linux/input/mt.h>
#include <linux/serio.h>
#include <linux/libps2.h>
+#include <linux/dmi.h>
#include "psmouse.h"
#include "alps.h"
@@ -99,6 +100,7 @@
#define ALPS_FOUR_BUTTONS 0x40 /* 4 direction button present */
#define ALPS_PS2_INTERLEAVED 0x80 /* 3-byte PS/2 packet interleaved with
6-byte ALPS packet */
+#define ALPS_DELL 0x100 /* device is a Dell laptop */
#define ALPS_BUTTONPAD 0x200 /* device is a clickpad */
static const struct alps_model_info alps_model_data[] = {
@@ -251,9 +253,9 @@
return;
}
- /* Non interleaved V2 dualpoint has separate stick button bits */
+ /* Dell non interleaved V2 dualpoint has separate stick button bits */
if (priv->proto_version == ALPS_PROTO_V2 &&
- priv->flags == (ALPS_PASS | ALPS_DUALPOINT)) {
+ priv->flags == (ALPS_DELL | ALPS_PASS | ALPS_DUALPOINT)) {
left |= packet[0] & 1;
right |= packet[0] & 2;
middle |= packet[0] & 4;
@@ -2550,6 +2552,8 @@
priv->byte0 = protocol->byte0;
priv->mask0 = protocol->mask0;
priv->flags = protocol->flags;
+ if (dmi_name_in_vendors("Dell"))
+ priv->flags |= ALPS_DELL;
priv->x_max = 2000;
priv->y_max = 1400;
diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c
index b10709f..30e3442 100644
--- a/drivers/input/mouse/bcm5974.c
+++ b/drivers/input/mouse/bcm5974.c
@@ -2,6 +2,7 @@
* Apple USB BCM5974 (Macbook Air and Penryn Macbook Pro) multitouch driver
*
* Copyright (C) 2008 Henrik Rydberg (rydberg@euromail.se)
+ * Copyright (C) 2015 John Horan (knasher@gmail.com)
*
* The USB initialization and package decoding was made by
* Scott Shawcroft as part of the touchd user-space driver project:
@@ -91,6 +92,10 @@
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI 0x0290
#define USB_DEVICE_ID_APPLE_WELLSPRING8_ISO 0x0291
#define USB_DEVICE_ID_APPLE_WELLSPRING8_JIS 0x0292
+/* MacbookPro12,1 (2015) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI 0x0272
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_ISO 0x0273
+#define USB_DEVICE_ID_APPLE_WELLSPRING9_JIS 0x0274
#define BCM5974_DEVICE(prod) { \
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
@@ -152,6 +157,10 @@
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ANSI),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_ISO),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING8_JIS),
+ /* MacbookPro12,1 */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
/* Terminating entry */
{}
};
@@ -180,21 +189,47 @@
enum tp_type {
TYPE1, /* plain trackpad */
TYPE2, /* button integrated in trackpad */
- TYPE3 /* additional header fields since June 2013 */
+ TYPE3, /* additional header fields since June 2013 */
+ TYPE4 /* additional header field for pressure data */
};
/* trackpad finger data offsets, le16-aligned */
-#define FINGER_TYPE1 (13 * sizeof(__le16))
-#define FINGER_TYPE2 (15 * sizeof(__le16))
-#define FINGER_TYPE3 (19 * sizeof(__le16))
+#define HEADER_TYPE1 (13 * sizeof(__le16))
+#define HEADER_TYPE2 (15 * sizeof(__le16))
+#define HEADER_TYPE3 (19 * sizeof(__le16))
+#define HEADER_TYPE4 (23 * sizeof(__le16))
/* trackpad button data offsets */
+#define BUTTON_TYPE1 0
#define BUTTON_TYPE2 15
#define BUTTON_TYPE3 23
+#define BUTTON_TYPE4 31
/* list of device capability bits */
#define HAS_INTEGRATED_BUTTON 1
+/* trackpad finger data block size */
+#define FSIZE_TYPE1 (14 * sizeof(__le16))
+#define FSIZE_TYPE2 (14 * sizeof(__le16))
+#define FSIZE_TYPE3 (14 * sizeof(__le16))
+#define FSIZE_TYPE4 (15 * sizeof(__le16))
+
+/* offset from header to finger struct */
+#define DELTA_TYPE1 (0 * sizeof(__le16))
+#define DELTA_TYPE2 (0 * sizeof(__le16))
+#define DELTA_TYPE3 (0 * sizeof(__le16))
+#define DELTA_TYPE4 (1 * sizeof(__le16))
+
+/* usb control message mode switch data */
+#define USBMSG_TYPE1 8, 0x300, 0, 0, 0x1, 0x8
+#define USBMSG_TYPE2 8, 0x300, 0, 0, 0x1, 0x8
+#define USBMSG_TYPE3 8, 0x300, 0, 0, 0x1, 0x8
+#define USBMSG_TYPE4 2, 0x302, 2, 1, 0x1, 0x0
+
+/* Wellspring initialization constants */
+#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
+#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
+
/* trackpad finger structure, le16-aligned */
struct tp_finger {
__le16 origin; /* zero when switching track finger */
@@ -207,14 +242,13 @@
__le16 orientation; /* 16384 when point, else 15 bit angle */
__le16 touch_major; /* touch area, major axis */
__le16 touch_minor; /* touch area, minor axis */
- __le16 unused[3]; /* zeros */
+ __le16 unused[2]; /* zeros */
+ __le16 pressure; /* pressure on forcetouch touchpad */
__le16 multi; /* one finger: varies, more fingers: constant */
} __attribute__((packed,aligned(2)));
/* trackpad finger data size, empirically at least ten fingers */
#define MAX_FINGERS 16
-#define SIZEOF_FINGER sizeof(struct tp_finger)
-#define SIZEOF_ALL_FINGERS (MAX_FINGERS * SIZEOF_FINGER)
#define MAX_FINGER_ORIENTATION 16384
/* device-specific parameters */
@@ -232,8 +266,17 @@
int bt_datalen; /* data length of the button interface */
int tp_ep; /* the endpoint of the trackpad interface */
enum tp_type tp_type; /* type of trackpad interface */
- int tp_offset; /* offset to trackpad finger data */
+ int tp_header; /* bytes in header block */
int tp_datalen; /* data length of the trackpad interface */
+ int tp_button; /* offset to button data */
+ int tp_fsize; /* bytes in single finger block */
+ int tp_delta; /* offset from header to finger struct */
+ int um_size; /* usb control message length */
+ int um_req_val; /* usb control message value */
+ int um_req_idx; /* usb control message index */
+ int um_switch_idx; /* usb control message mode switch index */
+ int um_switch_on; /* usb control message mode switch on */
+ int um_switch_off; /* usb control message mode switch off */
struct bcm5974_param p; /* finger pressure limits */
struct bcm5974_param w; /* finger width limits */
struct bcm5974_param x; /* horizontal limits */
@@ -259,6 +302,24 @@
int slots[MAX_FINGERS]; /* slot assignments */
};
+/* trackpad finger block data, le16-aligned */
+static const struct tp_finger *get_tp_finger(const struct bcm5974 *dev, int i)
+{
+ const struct bcm5974_config *c = &dev->cfg;
+ u8 *f_base = dev->tp_data + c->tp_header + c->tp_delta;
+
+ return (const struct tp_finger *)(f_base + i * c->tp_fsize);
+}
+
+#define DATAFORMAT(type) \
+ type, \
+ HEADER_##type, \
+ HEADER_##type + (MAX_FINGERS) * (FSIZE_##type), \
+ BUTTON_##type, \
+ FSIZE_##type, \
+ DELTA_##type, \
+ USBMSG_##type
+
/* logical signal quality */
#define SN_PRESSURE 45 /* pressure signal-to-noise ratio */
#define SN_WIDTH 25 /* width signal-to-noise ratio */
@@ -273,7 +334,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
0,
0x84, sizeof(struct bt_data),
- 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE1),
{ SN_PRESSURE, 0, 256 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4824, 5342 },
@@ -286,7 +347,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
0,
0x84, sizeof(struct bt_data),
- 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE1),
{ SN_PRESSURE, 0, 256 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4824, 4824 },
@@ -299,7 +360,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING3_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
- 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4460, 5166 },
@@ -312,7 +373,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING4_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
- 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4620, 5140 },
@@ -325,7 +386,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
- 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4616, 5112 },
@@ -338,7 +399,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING5_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
- 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4415, 5050 },
@@ -351,7 +412,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING6_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
- 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4620, 5140 },
@@ -364,7 +425,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
- 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4750, 5280 },
@@ -377,7 +438,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
- 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4620, 5140 },
@@ -390,7 +451,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING7_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
- 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4750, 5280 },
@@ -403,7 +464,7 @@
USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS,
HAS_INTEGRATED_BUTTON,
0x84, sizeof(struct bt_data),
- 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ 0x81, DATAFORMAT(TYPE2),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4750, 5280 },
@@ -416,13 +477,26 @@
USB_DEVICE_ID_APPLE_WELLSPRING8_JIS,
HAS_INTEGRATED_BUTTON,
0, sizeof(struct bt_data),
- 0x83, TYPE3, FINGER_TYPE3, FINGER_TYPE3 + SIZEOF_ALL_FINGERS,
+ 0x83, DATAFORMAT(TYPE3),
{ SN_PRESSURE, 0, 300 },
{ SN_WIDTH, 0, 2048 },
{ SN_COORD, -4620, 5140 },
{ SN_COORD, -150, 6600 },
{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
},
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING9_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING9_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING9_JIS,
+ HAS_INTEGRATED_BUTTON,
+ 0, sizeof(struct bt_data),
+ 0x83, DATAFORMAT(TYPE4),
+ { SN_PRESSURE, 0, 300 },
+ { SN_WIDTH, 0, 2048 },
+ { SN_COORD, -4828, 5345 },
+ { SN_COORD, -203, 6803 },
+ { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
+ },
{}
};
@@ -549,19 +623,18 @@
struct input_dev *input = dev->input;
int raw_n, i, n = 0;
- if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
+ if (size < c->tp_header || (size - c->tp_header) % c->tp_fsize != 0)
return -EIO;
- /* finger data, le16-aligned */
- f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
- raw_n = (size - c->tp_offset) / SIZEOF_FINGER;
+ raw_n = (size - c->tp_header) / c->tp_fsize;
for (i = 0; i < raw_n; i++) {
- if (raw2int(f[i].touch_major) == 0)
+ f = get_tp_finger(dev, i);
+ if (raw2int(f->touch_major) == 0)
continue;
- dev->pos[n].x = raw2int(f[i].abs_x);
- dev->pos[n].y = c->y.min + c->y.max - raw2int(f[i].abs_y);
- dev->index[n++] = &f[i];
+ dev->pos[n].x = raw2int(f->abs_x);
+ dev->pos[n].y = c->y.min + c->y.max - raw2int(f->abs_y);
+ dev->index[n++] = f;
}
input_mt_assign_slots(input, dev->slots, dev->pos, n, 0);
@@ -572,32 +645,22 @@
input_mt_sync_frame(input);
- report_synaptics_data(input, c, f, raw_n);
+ report_synaptics_data(input, c, get_tp_finger(dev, 0), raw_n);
- /* type 2 reports button events via ibt only */
- if (c->tp_type == TYPE2) {
- int ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
+ /* later types report button events via integrated button only */
+ if (c->caps & HAS_INTEGRATED_BUTTON) {
+ int ibt = raw2int(dev->tp_data[c->tp_button]);
input_report_key(input, BTN_LEFT, ibt);
}
- if (c->tp_type == TYPE3)
- input_report_key(input, BTN_LEFT, dev->tp_data[BUTTON_TYPE3]);
-
input_sync(input);
return 0;
}
-/* Wellspring initialization constants */
-#define BCM5974_WELLSPRING_MODE_READ_REQUEST_ID 1
-#define BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID 9
-#define BCM5974_WELLSPRING_MODE_REQUEST_VALUE 0x300
-#define BCM5974_WELLSPRING_MODE_REQUEST_INDEX 0
-#define BCM5974_WELLSPRING_MODE_VENDOR_VALUE 0x01
-#define BCM5974_WELLSPRING_MODE_NORMAL_VALUE 0x08
-
static int bcm5974_wellspring_mode(struct bcm5974 *dev, bool on)
{
+ const struct bcm5974_config *c = &dev->cfg;
int retval = 0, size;
char *data;
@@ -605,7 +668,7 @@
if (dev->cfg.tp_type == TYPE3)
return 0;
- data = kmalloc(8, GFP_KERNEL);
+ data = kmalloc(c->um_size, GFP_KERNEL);
if (!data) {
dev_err(&dev->intf->dev, "out of memory\n");
retval = -ENOMEM;
@@ -616,28 +679,24 @@
size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
BCM5974_WELLSPRING_MODE_READ_REQUEST_ID,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
- BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
+ c->um_req_val, c->um_req_idx, data, c->um_size, 5000);
- if (size != 8) {
+ if (size != c->um_size) {
dev_err(&dev->intf->dev, "could not read from device\n");
retval = -EIO;
goto out;
}
/* apply the mode switch */
- data[0] = on ?
- BCM5974_WELLSPRING_MODE_VENDOR_VALUE :
- BCM5974_WELLSPRING_MODE_NORMAL_VALUE;
+ data[c->um_switch_idx] = on ? c->um_switch_on : c->um_switch_off;
/* write configuration */
size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
BCM5974_WELLSPRING_MODE_WRITE_REQUEST_ID,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- BCM5974_WELLSPRING_MODE_REQUEST_VALUE,
- BCM5974_WELLSPRING_MODE_REQUEST_INDEX, data, 8, 5000);
+ c->um_req_val, c->um_req_idx, data, c->um_size, 5000);
- if (size != 8) {
+ if (size != c->um_size) {
dev_err(&dev->intf->dev, "could not write to device\n");
retval = -EIO;
goto out;
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index ce3d400..2955f1d 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -783,19 +783,26 @@
struct elantech_data *etd = psmouse->private;
unsigned char *packet = psmouse->packet;
unsigned char packet_type = packet[3] & 0x03;
+ unsigned int ic_version;
bool sanity_check;
if (etd->tp_dev && (packet[3] & 0x0f) == 0x06)
return PACKET_TRACKPOINT;
+ /* This represents the version of IC body. */
+ ic_version = (etd->fw_version & 0x0f0000) >> 16;
+
/*
* Sanity check based on the constant bits of a packet.
* The constant bits change depending on the value of
- * the hardware flag 'crc_enabled' but are the same for
- * every packet, regardless of the type.
+ * the hardware flag 'crc_enabled' and the version of
+ * the IC body, but are the same for every packet,
+ * regardless of the type.
*/
if (etd->crc_enabled)
sanity_check = ((packet[3] & 0x08) == 0x00);
+ else if (ic_version == 7 && etd->samples[1] == 0x2A)
+ sanity_check = ((packet[3] & 0x1c) == 0x10);
else
sanity_check = ((packet[0] & 0x0c) == 0x04 &&
(packet[3] & 0x1c) == 0x10);
@@ -1116,6 +1123,7 @@
* Avatar AVIU-145A2 0x361f00 ? clickpad
* Fujitsu LIFEBOOK E544 0x470f00 d0, 12, 09 2 hw buttons
* Fujitsu LIFEBOOK E554 0x570f01 40, 14, 0c 2 hw buttons
+ * Fujitsu T725 0x470f01 05, 12, 09 2 hw buttons
* Fujitsu H730 0x570f00 c0, 14, 0c 3 hw buttons (**)
* Gigabyte U2442 0x450f01 58, 17, 0c 2 hw buttons
* Lenovo L430 0x350f02 b9, 15, 0c 2 hw buttons (*)
@@ -1167,7 +1175,7 @@
struct input_dev *dev = psmouse->dev;
struct elantech_data *etd = psmouse->private;
unsigned int x_min = 0, y_min = 0, x_max = 0, y_max = 0, width = 0;
- unsigned int x_res = 0, y_res = 0;
+ unsigned int x_res = 31, y_res = 31;
if (elantech_set_range(psmouse, &x_min, &y_min, &x_max, &y_max, &width))
return -1;
@@ -1232,8 +1240,6 @@
/* For X to recognize me as touchpad. */
input_set_abs_params(dev, ABS_X, x_min, x_max, 0, 0);
input_set_abs_params(dev, ABS_Y, y_min, y_max, 0, 0);
- input_abs_set_res(dev, ABS_X, x_res);
- input_abs_set_res(dev, ABS_Y, y_res);
/*
* range of pressure and width is the same as v2,
* report ABS_PRESSURE, ABS_TOOL_WIDTH for compatibility.
@@ -1246,8 +1252,6 @@
input_mt_init_slots(dev, ETP_MAX_FINGERS, 0);
input_set_abs_params(dev, ABS_MT_POSITION_X, x_min, x_max, 0, 0);
input_set_abs_params(dev, ABS_MT_POSITION_Y, y_min, y_max, 0, 0);
- input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
- input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res);
input_set_abs_params(dev, ABS_MT_PRESSURE, ETP_PMIN_V2,
ETP_PMAX_V2, 0, 0);
/*
@@ -1259,6 +1263,13 @@
break;
}
+ input_abs_set_res(dev, ABS_X, x_res);
+ input_abs_set_res(dev, ABS_Y, y_res);
+ if (etd->hw_version > 1) {
+ input_abs_set_res(dev, ABS_MT_POSITION_X, x_res);
+ input_abs_set_res(dev, ABS_MT_POSITION_Y, y_res);
+ }
+
etd->y_max = y_max;
etd->width = width;
@@ -1648,6 +1659,16 @@
etd->capabilities[0], etd->capabilities[1],
etd->capabilities[2]);
+ if (etd->hw_version != 1) {
+ if (etd->send_cmd(psmouse, ETP_SAMPLE_QUERY, etd->samples)) {
+ psmouse_err(psmouse, "failed to query sample data\n");
+ goto init_fail;
+ }
+ psmouse_info(psmouse,
+ "Elan sample query result %02x, %02x, %02x\n",
+ etd->samples[0], etd->samples[1], etd->samples[2]);
+ }
+
if (elantech_set_absolute_mode(psmouse)) {
psmouse_err(psmouse,
"failed to put touchpad into absolute mode.\n");
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h
index f965d15..e1cbf40 100644
--- a/drivers/input/mouse/elantech.h
+++ b/drivers/input/mouse/elantech.h
@@ -129,6 +129,7 @@
unsigned char reg_26;
unsigned char debug;
unsigned char capabilities[3];
+ unsigned char samples[3];
bool paritycheck;
bool jumpy_cursor;
bool reports_pressure;
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index 3a32caf..6025eb4 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -1484,12 +1484,12 @@
priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
psmouse_info(psmouse,
- "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n",
+ "Touchpad model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx/%#lx, board id: %lu, fw id: %lu\n",
SYN_ID_MODEL(priv->identity),
SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity),
priv->model_id,
priv->capabilities, priv->ext_cap, priv->ext_cap_0c,
- priv->board_id, priv->firmware_id);
+ priv->ext_cap_10, priv->board_id, priv->firmware_id);
set_input_params(psmouse, priv);
diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c
index b4d12e2..e36162b 100644
--- a/drivers/input/touchscreen/goodix.c
+++ b/drivers/input/touchscreen/goodix.c
@@ -15,6 +15,7 @@
*/
#include <linux/kernel.h>
+#include <linux/dmi.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>
@@ -34,6 +35,7 @@
int abs_y_max;
unsigned int max_touch_num;
unsigned int int_trigger_type;
+ bool rotated_screen;
};
#define GOODIX_MAX_HEIGHT 4096
@@ -60,6 +62,30 @@
IRQ_TYPE_LEVEL_HIGH,
};
+/*
+ * Those tablets have their coordinates origin at the bottom right
+ * of the tablet, as if rotated 180 degrees
+ */
+static const struct dmi_system_id rotated_screen[] = {
+#if defined(CONFIG_DMI) && defined(CONFIG_X86)
+ {
+ .ident = "WinBook TW100",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TW100")
+ }
+ },
+ {
+ .ident = "WinBook TW700",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TW700")
+ },
+ },
+#endif
+ {}
+};
+
/**
* goodix_i2c_read - read data from a register of the i2c slave device.
*
@@ -129,6 +155,11 @@
int input_y = get_unaligned_le16(&coor_data[3]);
int input_w = get_unaligned_le16(&coor_data[5]);
+ if (ts->rotated_screen) {
+ input_x = ts->abs_x_max - input_x;
+ input_y = ts->abs_y_max - input_y;
+ }
+
input_mt_slot(ts->input_dev, id);
input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, true);
input_report_abs(ts->input_dev, ABS_MT_POSITION_X, input_x);
@@ -223,6 +254,11 @@
ts->abs_y_max = GOODIX_MAX_HEIGHT;
ts->max_touch_num = GOODIX_MAX_CONTACTS;
}
+
+ ts->rotated_screen = dmi_check_system(rotated_screen);
+ if (ts->rotated_screen)
+ dev_dbg(&ts->client->dev,
+ "Applying '180 degrees rotated screen' quirk\n");
}
/**
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c
index f2c6c35..2c41107 100644
--- a/drivers/input/touchscreen/usbtouchscreen.c
+++ b/drivers/input/touchscreen/usbtouchscreen.c
@@ -627,6 +627,9 @@
goto err_out;
}
+ /* TSC-25 data sheet specifies a delay after the RESET command */
+ msleep(150);
+
/* set coordinate output rate */
buf[0] = buf[1] = 0xFF;
ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index a57e9b7..658ee39 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -76,8 +76,6 @@
* Domain for untranslated devices - only allocated
* if iommu=pt passed on kernel cmd line.
*/
-static struct protection_domain *pt_domain;
-
static const struct iommu_ops amd_iommu_ops;
static ATOMIC_NOTIFIER_HEAD(ppr_notifier);
@@ -96,7 +94,7 @@
struct protection_domain *domain; /* Domain the device is bound to */
u16 devid; /* PCI Device ID */
bool iommu_v2; /* Device can make use of IOMMUv2 */
- bool passthrough; /* Default for device is pt_domain */
+ bool passthrough; /* Device is identity mapped */
struct {
bool enabled;
int qdep;
@@ -116,7 +114,6 @@
struct kmem_cache *amd_iommu_irq_cache;
static void update_domain(struct protection_domain *domain);
-static int alloc_passthrough_domain(void);
static int protection_domain_init(struct protection_domain *domain);
/****************************************************************************
@@ -2167,15 +2164,17 @@
dev_data = get_dev_data(dev);
if (domain->flags & PD_IOMMUV2_MASK) {
- if (!dev_data->iommu_v2 || !dev_data->passthrough)
+ if (!dev_data->passthrough)
return -EINVAL;
- if (pdev_iommuv2_enable(pdev) != 0)
- return -EINVAL;
+ if (dev_data->iommu_v2) {
+ if (pdev_iommuv2_enable(pdev) != 0)
+ return -EINVAL;
- dev_data->ats.enabled = true;
- dev_data->ats.qdep = pci_ats_queue_depth(pdev);
- dev_data->pri_tlp = pci_pri_tlp_required(pdev);
+ dev_data->ats.enabled = true;
+ dev_data->ats.qdep = pci_ats_queue_depth(pdev);
+ dev_data->pri_tlp = pci_pri_tlp_required(pdev);
+ }
} else if (amd_iommu_iotlb_sup &&
pci_enable_ats(pdev, PAGE_SHIFT) == 0) {
dev_data->ats.enabled = true;
@@ -2221,15 +2220,6 @@
do_detach(head);
spin_unlock_irqrestore(&domain->lock, flags);
-
- /*
- * If we run in passthrough mode the device must be assigned to the
- * passthrough domain if it is detached from any other domain.
- * Make sure we can deassign from the pt_domain itself.
- */
- if (dev_data->passthrough &&
- (dev_data->domain == NULL && domain != pt_domain))
- __attach_device(dev_data, pt_domain);
}
/*
@@ -2249,7 +2239,7 @@
__detach_device(dev_data);
write_unlock_irqrestore(&amd_iommu_devtable_lock, flags);
- if (domain->flags & PD_IOMMUV2_MASK)
+ if (domain->flags & PD_IOMMUV2_MASK && dev_data->iommu_v2)
pdev_iommuv2_disable(to_pci_dev(dev));
else if (dev_data->ats.enabled)
pci_disable_ats(to_pci_dev(dev));
@@ -2287,17 +2277,15 @@
BUG_ON(!dev_data);
- if (dev_data->iommu_v2)
+ if (iommu_pass_through || dev_data->iommu_v2)
iommu_request_dm_for_dev(dev);
/* Domains are initialized for this device - have a look what we ended up with */
domain = iommu_get_domain_for_dev(dev);
- if (domain->type == IOMMU_DOMAIN_IDENTITY) {
+ if (domain->type == IOMMU_DOMAIN_IDENTITY)
dev_data->passthrough = true;
- dev->archdata.dma_ops = &nommu_dma_ops;
- } else {
+ else
dev->archdata.dma_ops = &amd_iommu_dma_ops;
- }
out:
iommu_completion_wait(iommu);
@@ -2862,8 +2850,17 @@
int __init amd_iommu_init_dma_ops(void)
{
+ swiotlb = iommu_pass_through ? 1 : 0;
iommu_detected = 1;
- swiotlb = 0;
+
+ /*
+ * In case we don't initialize SWIOTLB (actually the common case
+ * when AMD IOMMU is enabled), make sure there are global
+ * dma_ops set as a fall-back for devices not handled by this
+ * driver (for example non-PCI devices).
+ */
+ if (!swiotlb)
+ dma_ops = &nommu_dma_ops;
amd_iommu_stats_init();
@@ -2947,21 +2944,6 @@
return NULL;
}
-static int alloc_passthrough_domain(void)
-{
- if (pt_domain != NULL)
- return 0;
-
- /* allocate passthrough domain */
- pt_domain = protection_domain_alloc();
- if (!pt_domain)
- return -ENOMEM;
-
- pt_domain->mode = PAGE_MODE_NONE;
-
- return 0;
-}
-
static struct iommu_domain *amd_iommu_domain_alloc(unsigned type)
{
struct protection_domain *pdomain;
@@ -3222,33 +3204,6 @@
*
*****************************************************************************/
-int __init amd_iommu_init_passthrough(void)
-{
- struct iommu_dev_data *dev_data;
- struct pci_dev *dev = NULL;
- int ret;
-
- ret = alloc_passthrough_domain();
- if (ret)
- return ret;
-
- for_each_pci_dev(dev) {
- if (!check_device(&dev->dev))
- continue;
-
- dev_data = get_dev_data(&dev->dev);
- dev_data->passthrough = true;
-
- attach_device(&dev->dev, pt_domain);
- }
-
- amd_iommu_stats_init();
-
- pr_info("AMD-Vi: Initialized for Passthrough Mode\n");
-
- return 0;
-}
-
/* IOMMUv2 specific functions */
int amd_iommu_register_ppr_notifier(struct notifier_block *nb)
{
@@ -3363,7 +3318,12 @@
struct amd_iommu *iommu;
int qdep;
- BUG_ON(!dev_data->ats.enabled);
+ /*
+ There might be non-IOMMUv2 capable devices in an IOMMUv2
+ * domain.
+ */
+ if (!dev_data->ats.enabled)
+ continue;
qdep = dev_data->ats.qdep;
iommu = amd_iommu_rlookup_table[dev_data->devid];
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index dbda9ae..a24495e 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -2026,14 +2026,6 @@
return true;
}
-static int amd_iommu_init_dma(void)
-{
- if (iommu_pass_through)
- return amd_iommu_init_passthrough();
- else
- return amd_iommu_init_dma_ops();
-}
-
/****************************************************************************
*
* AMD IOMMU Initialization State Machine
@@ -2073,7 +2065,7 @@
init_state = ret ? IOMMU_INIT_ERROR : IOMMU_INTERRUPTS_EN;
break;
case IOMMU_INTERRUPTS_EN:
- ret = amd_iommu_init_dma();
+ ret = amd_iommu_init_dma_ops();
init_state = ret ? IOMMU_INIT_ERROR : IOMMU_DMA_OPS;
break;
case IOMMU_DMA_OPS:
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 3465faf..f7b875b 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -132,11 +132,19 @@
static void free_device_state(struct device_state *dev_state)
{
+ struct iommu_group *group;
+
/*
* First detach device from domain - No more PRI requests will arrive
* from that device after it is unbound from the IOMMUv2 domain.
*/
- iommu_detach_device(dev_state->domain, &dev_state->pdev->dev);
+ group = iommu_group_get(&dev_state->pdev->dev);
+ if (WARN_ON(!group))
+ return;
+
+ iommu_detach_group(dev_state->domain, group);
+
+ iommu_group_put(group);
/* Everything is down now, free the IOMMUv2 domain */
iommu_domain_free(dev_state->domain);
@@ -731,6 +739,7 @@
int amd_iommu_init_device(struct pci_dev *pdev, int pasids)
{
struct device_state *dev_state;
+ struct iommu_group *group;
unsigned long flags;
int ret, tmp;
u16 devid;
@@ -776,10 +785,16 @@
if (ret)
goto out_free_domain;
- ret = iommu_attach_device(dev_state->domain, &pdev->dev);
- if (ret != 0)
+ group = iommu_group_get(&pdev->dev);
+ if (!group)
goto out_free_domain;
+ ret = iommu_attach_group(dev_state->domain, group);
+ if (ret != 0)
+ goto out_drop_group;
+
+ iommu_group_put(group);
+
spin_lock_irqsave(&state_lock, flags);
if (__get_device_state(devid) != NULL) {
@@ -794,6 +809,9 @@
return 0;
+out_drop_group:
+ iommu_group_put(group);
+
out_free_domain:
iommu_domain_free(dev_state->domain);
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 8e9ec81..da902ba 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -199,9 +199,10 @@
* Stream table.
*
* Linear: Enough to cover 1 << IDR1.SIDSIZE entries
- * 2lvl: 8k L1 entries, 256 lazy entries per table (each table covers a PCI bus)
+ * 2lvl: 128k L1 entries,
+ * 256 lazy entries per table (each table covers a PCI bus)
*/
-#define STRTAB_L1_SZ_SHIFT 16
+#define STRTAB_L1_SZ_SHIFT 20
#define STRTAB_SPLIT 8
#define STRTAB_L1_DESC_DWORDS 1
@@ -269,10 +270,10 @@
#define ARM64_TCR_TG0_SHIFT 14
#define ARM64_TCR_TG0_MASK 0x3UL
#define CTXDESC_CD_0_TCR_IRGN0_SHIFT 8
-#define ARM64_TCR_IRGN0_SHIFT 24
+#define ARM64_TCR_IRGN0_SHIFT 8
#define ARM64_TCR_IRGN0_MASK 0x3UL
#define CTXDESC_CD_0_TCR_ORGN0_SHIFT 10
-#define ARM64_TCR_ORGN0_SHIFT 26
+#define ARM64_TCR_ORGN0_SHIFT 10
#define ARM64_TCR_ORGN0_MASK 0x3UL
#define CTXDESC_CD_0_TCR_SH0_SHIFT 12
#define ARM64_TCR_SH0_SHIFT 12
@@ -542,6 +543,9 @@
#define ARM_SMMU_FEAT_HYP (1 << 12)
u32 features;
+#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0)
+ u32 options;
+
struct arm_smmu_cmdq cmdq;
struct arm_smmu_evtq evtq;
struct arm_smmu_priq priq;
@@ -602,11 +606,35 @@
static DEFINE_SPINLOCK(arm_smmu_devices_lock);
static LIST_HEAD(arm_smmu_devices);
+struct arm_smmu_option_prop {
+ u32 opt;
+ const char *prop;
+};
+
+static struct arm_smmu_option_prop arm_smmu_options[] = {
+ { ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" },
+ { 0, NULL},
+};
+
static struct arm_smmu_domain *to_smmu_domain(struct iommu_domain *dom)
{
return container_of(dom, struct arm_smmu_domain, domain);
}
+static void parse_driver_options(struct arm_smmu_device *smmu)
+{
+ int i = 0;
+
+ do {
+ if (of_property_read_bool(smmu->dev->of_node,
+ arm_smmu_options[i].prop)) {
+ smmu->options |= arm_smmu_options[i].opt;
+ dev_notice(smmu->dev, "option %s\n",
+ arm_smmu_options[i].prop);
+ }
+ } while (arm_smmu_options[++i].opt);
+}
+
/* Low-level queue manipulation functions */
static bool queue_full(struct arm_smmu_queue *q)
{
@@ -1036,7 +1064,8 @@
arm_smmu_sync_ste_for_sid(smmu, sid);
/* It's likely that we'll want to use the new STE soon */
- arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd);
+ if (!(smmu->options & ARM_SMMU_OPT_SKIP_PREFETCH))
+ arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd);
}
static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent)
@@ -1064,7 +1093,7 @@
return 0;
size = 1 << (STRTAB_SPLIT + ilog2(STRTAB_STE_DWORDS) + 3);
- strtab = &cfg->strtab[sid >> STRTAB_SPLIT << STRTAB_L1_DESC_DWORDS];
+ strtab = &cfg->strtab[(sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS];
desc->span = STRTAB_SPLIT + 1;
desc->l2ptr = dma_zalloc_coherent(smmu->dev, size, &desc->l2ptr_dma,
@@ -2020,21 +2049,23 @@
{
void *strtab;
u64 reg;
- u32 size;
+ u32 size, l1size;
int ret;
struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
/* Calculate the L1 size, capped to the SIDSIZE */
size = STRTAB_L1_SZ_SHIFT - (ilog2(STRTAB_L1_DESC_DWORDS) + 3);
size = min(size, smmu->sid_bits - STRTAB_SPLIT);
- if (size + STRTAB_SPLIT < smmu->sid_bits)
+ cfg->num_l1_ents = 1 << size;
+
+ size += STRTAB_SPLIT;
+ if (size < smmu->sid_bits)
dev_warn(smmu->dev,
"2-level strtab only covers %u/%u bits of SID\n",
- size + STRTAB_SPLIT, smmu->sid_bits);
+ size, smmu->sid_bits);
- cfg->num_l1_ents = 1 << size;
- size = cfg->num_l1_ents * (STRTAB_L1_DESC_DWORDS << 3);
- strtab = dma_zalloc_coherent(smmu->dev, size, &cfg->strtab_dma,
+ l1size = cfg->num_l1_ents * (STRTAB_L1_DESC_DWORDS << 3);
+ strtab = dma_zalloc_coherent(smmu->dev, l1size, &cfg->strtab_dma,
GFP_KERNEL);
if (!strtab) {
dev_err(smmu->dev,
@@ -2055,8 +2086,7 @@
ret = arm_smmu_init_l1_strtab(smmu);
if (ret)
dma_free_coherent(smmu->dev,
- cfg->num_l1_ents *
- (STRTAB_L1_DESC_DWORDS << 3),
+ l1size,
strtab,
cfg->strtab_dma);
return ret;
@@ -2573,6 +2603,8 @@
if (irq > 0)
smmu->gerr_irq = irq;
+ parse_driver_options(smmu);
+
/* Probe the h/w */
ret = arm_smmu_device_probe(smmu);
if (ret)
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index a98a7b2..0649b94 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1830,8 +1830,9 @@
static void domain_exit(struct dmar_domain *domain)
{
+ struct dmar_drhd_unit *drhd;
+ struct intel_iommu *iommu;
struct page *freelist = NULL;
- int i;
/* Domain 0 is reserved, so dont process it */
if (!domain)
@@ -1851,8 +1852,10 @@
/* clear attached or cached domains */
rcu_read_lock();
- for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus)
- iommu_detach_domain(domain, g_iommus[i]);
+ for_each_active_iommu(iommu, drhd)
+ if (domain_type_is_vm(domain) ||
+ test_bit(iommu->seq_id, domain->iommu_bmp))
+ iommu_detach_domain(domain, iommu);
rcu_read_unlock();
dma_free_pagelist(freelist);
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c
index 692fe2b..c12bb93 100644
--- a/drivers/irqchip/irq-crossbar.c
+++ b/drivers/irqchip/irq-crossbar.c
@@ -68,7 +68,9 @@
.irq_mask = irq_chip_mask_parent,
.irq_unmask = irq_chip_unmask_parent,
.irq_retrigger = irq_chip_retrigger_hierarchy,
- .irq_set_wake = irq_chip_set_wake_parent,
+ .irq_set_type = irq_chip_set_type_parent,
+ .flags = IRQCHIP_MASK_ON_SUSPEND |
+ IRQCHIP_SKIP_SET_WAKE,
#ifdef CONFIG_SMP
.irq_set_affinity = irq_chip_set_affinity_parent,
#endif
diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c
index b7d54d4..ff4be05 100644
--- a/drivers/irqchip/irq-mips-gic.c
+++ b/drivers/irqchip/irq-mips-gic.c
@@ -538,7 +538,7 @@
static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
{
- smp_call_function_interrupt();
+ generic_smp_call_function_interrupt();
return IRQ_HANDLED;
}
diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c
index 8c91fd5eb..375be50 100644
--- a/drivers/isdn/gigaset/ser-gigaset.c
+++ b/drivers/isdn/gigaset/ser-gigaset.c
@@ -524,9 +524,18 @@
cs->hw.ser->tty = tty;
atomic_set(&cs->hw.ser->refcnt, 1);
init_completion(&cs->hw.ser->dead_cmp);
-
tty->disc_data = cs;
+ /* Set the amount of data we're willing to receive per call
+ * from the hardware driver to half of the input buffer size
+ * to leave some reserve.
+ * Note: We don't do flow control towards the hardware driver.
+ * If more data is received than will fit into the input buffer,
+ * it will be dropped and an error will be logged. This should
+ * never happen as the device is slow and the buffer size ample.
+ */
+ tty->receive_room = RBUFSIZE/2;
+
/* OK.. Initialization of the datastructures and the HW is done.. Now
* startup system and notify the LL that we are ready to run
*/
@@ -598,28 +607,6 @@
}
/*
- * Read on the tty.
- * Unused, received data goes only to the Gigaset driver.
- */
-static ssize_t
-gigaset_tty_read(struct tty_struct *tty, struct file *file,
- unsigned char __user *buf, size_t count)
-{
- return -EAGAIN;
-}
-
-/*
- * Write on the tty.
- * Unused, transmit data comes only from the Gigaset driver.
- */
-static ssize_t
-gigaset_tty_write(struct tty_struct *tty, struct file *file,
- const unsigned char *buf, size_t count)
-{
- return -EAGAIN;
-}
-
-/*
* Ioctl on the tty.
* Called in process context only.
* May be re-entered by multiple ioctl calling threads.
@@ -752,8 +739,6 @@
.open = gigaset_tty_open,
.close = gigaset_tty_close,
.hangup = gigaset_tty_hangup,
- .read = gigaset_tty_read,
- .write = gigaset_tty_write,
.ioctl = gigaset_tty_ioctl,
.receive_buf = gigaset_tty_receive,
.write_wakeup = gigaset_tty_wakeup,
diff --git a/drivers/macintosh/ans-lcd.c b/drivers/macintosh/ans-lcd.c
index 1a57e88..cd35079 100644
--- a/drivers/macintosh/ans-lcd.c
+++ b/drivers/macintosh/ans-lcd.c
@@ -7,7 +7,7 @@
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/fcntl.h>
-#include <linux/init.h>
+#include <linux/module.h>
#include <linux/delay.h>
#include <linux/fs.h>
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index b597273..bfec3bd 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -259,7 +259,7 @@
the ciphers you're going to use in the cryptoapi configuration.
For further information on dm-crypt and userspace tools see:
- <http://code.google.com/p/cryptsetup/wiki/DMCrypt>
+ <https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt>
To compile this code as a module, choose M here: the module will
be called dm-crypt.
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index ed2346d..e51de52 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -494,7 +494,7 @@
bitmap_super_t *sb;
unsigned long chunksize, daemon_sleep, write_behind;
- bitmap->storage.sb_page = alloc_page(GFP_KERNEL);
+ bitmap->storage.sb_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
if (bitmap->storage.sb_page == NULL)
return -ENOMEM;
bitmap->storage.sb_page->index = 0;
@@ -541,6 +541,7 @@
sb->state = cpu_to_le32(bitmap->flags);
bitmap->events_cleared = bitmap->mddev->events;
sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+ bitmap->mddev->bitmap_info.nodes = 0;
kunmap_atomic(sb);
@@ -558,6 +559,7 @@
unsigned long sectors_reserved = 0;
int err = -EINVAL;
struct page *sb_page;
+ loff_t offset = bitmap->mddev->bitmap_info.offset;
if (!bitmap->storage.file && !bitmap->mddev->bitmap_info.offset) {
chunksize = 128 * 1024 * 1024;
@@ -584,9 +586,9 @@
bm_blocks = ((bm_blocks+7) >> 3) + sizeof(bitmap_super_t);
/* to 4k blocks */
bm_blocks = DIV_ROUND_UP_SECTOR_T(bm_blocks, 4096);
- bitmap->mddev->bitmap_info.offset += bitmap->cluster_slot * (bm_blocks << 3);
+ offset = bitmap->mddev->bitmap_info.offset + (bitmap->cluster_slot * (bm_blocks << 3));
pr_info("%s:%d bm slot: %d offset: %llu\n", __func__, __LINE__,
- bitmap->cluster_slot, (unsigned long long)bitmap->mddev->bitmap_info.offset);
+ bitmap->cluster_slot, offset);
}
if (bitmap->storage.file) {
@@ -597,7 +599,7 @@
bitmap, bytes, sb_page);
} else {
err = read_sb_page(bitmap->mddev,
- bitmap->mddev->bitmap_info.offset,
+ offset,
sb_page,
0, sizeof(bitmap_super_t));
}
@@ -611,8 +613,16 @@
daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
write_behind = le32_to_cpu(sb->write_behind);
sectors_reserved = le32_to_cpu(sb->sectors_reserved);
- nodes = le32_to_cpu(sb->nodes);
- strlcpy(bitmap->mddev->bitmap_info.cluster_name, sb->cluster_name, 64);
+ /* XXX: This is a hack to ensure that we don't use clustering
+ * in case:
+ * - dm-raid is in use and
+ * - the nodes written in bitmap_sb is erroneous.
+ */
+ if (!bitmap->mddev->sync_super) {
+ nodes = le32_to_cpu(sb->nodes);
+ strlcpy(bitmap->mddev->bitmap_info.cluster_name,
+ sb->cluster_name, 64);
+ }
/* verify that the bitmap-specific fields are valid */
if (sb->magic != cpu_to_le32(BITMAP_MAGIC))
@@ -671,7 +681,7 @@
kunmap_atomic(sb);
/* Assiging chunksize is required for "re_read" */
bitmap->mddev->bitmap_info.chunksize = chunksize;
- if (nodes && (bitmap->cluster_slot < 0)) {
+ if (err == 0 && nodes && (bitmap->cluster_slot < 0)) {
err = md_setup_cluster(bitmap->mddev, nodes);
if (err) {
pr_err("%s: Could not setup cluster service (%d)\n",
@@ -1866,10 +1876,6 @@
if (IS_ERR(bitmap))
return PTR_ERR(bitmap);
- rv = bitmap_read_sb(bitmap);
- if (rv)
- goto err;
-
rv = bitmap_init_from_disk(bitmap, 0);
if (rv)
goto err;
diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c
index 3281437..aa1b41c 100644
--- a/drivers/md/dm-cache-policy-mq.c
+++ b/drivers/md/dm-cache-policy-mq.c
@@ -1471,5 +1471,3 @@
MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("mq cache policy");
-
-MODULE_ALIAS("dm-cache-default");
diff --git a/drivers/md/dm-cache-policy-smq.c b/drivers/md/dm-cache-policy-smq.c
index b6f2265..200366c 100644
--- a/drivers/md/dm-cache-policy-smq.c
+++ b/drivers/md/dm-cache-policy-smq.c
@@ -1686,7 +1686,7 @@
if (from_cblock(cache_size)) {
mq->cache_hit_bits = alloc_bitset(from_cblock(cache_size));
- if (!mq->cache_hit_bits && mq->cache_hit_bits) {
+ if (!mq->cache_hit_bits) {
DMERR("couldn't allocate cache hit bitset");
goto bad_cache_hit_bits;
}
@@ -1789,3 +1789,5 @@
MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("smq cache policy");
+
+MODULE_ALIAS("dm-cache-default");
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index b680da5..1fe93cf 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -424,6 +424,7 @@
wake_up(&cache->migration_wait);
mempool_free(mg, cache->migration_pool);
+ wake_worker(cache);
}
static int prealloc_data_structs(struct cache *cache, struct prealloc *p)
@@ -1966,6 +1967,7 @@
* this bio might require one, we pause until there are some
* prepared mappings to process.
*/
+ prealloc_used = true;
if (prealloc_data_structs(cache, &structs)) {
spin_lock_irqsave(&cache->lock, flags);
bio_list_merge(&cache->deferred_bios, &bios);
@@ -1981,7 +1983,6 @@
process_discard_bio(cache, &structs, bio);
else
process_bio(cache, &structs, bio);
- prealloc_used = true;
}
if (prealloc_used)
@@ -2010,6 +2011,7 @@
* this bio might require one, we pause until there are some
* prepared mappings to process.
*/
+ prealloc_used = true;
if (prealloc_data_structs(cache, &structs)) {
spin_lock_irqsave(&cache->lock, flags);
list_splice(&cells, &cache->deferred_cells);
@@ -2018,7 +2020,6 @@
}
process_cell(cache, &structs, cell);
- prealloc_used = true;
}
if (prealloc_used)
@@ -2080,6 +2081,7 @@
if (policy_writeback_work(cache->policy, &oblock, &cblock, busy))
break; /* no work to do */
+ prealloc_used = true;
if (prealloc_data_structs(cache, &structs) ||
get_cell(cache, oblock, &structs, &old_ocell)) {
policy_set_dirty(cache->policy, oblock);
@@ -2087,7 +2089,6 @@
}
writeback(cache, &structs, oblock, cblock, old_ocell);
- prealloc_used = true;
}
if (prealloc_used)
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 720ceeb..80a4395 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1919,9 +1919,7 @@
void dm_interface_exit(void)
{
- if (misc_deregister(&_dm_misc) < 0)
- DMERR("misc_deregister failed for control device");
-
+ misc_deregister(&_dm_misc);
dm_hash_exit();
}
diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 48dfe3c..6ba47cf 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1293,8 +1293,8 @@
return r;
disk_super = dm_block_data(copy);
- dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->data_mapping_root));
- dm_sm_dec_block(pmd->metadata_sm, le64_to_cpu(disk_super->device_details_root));
+ dm_btree_del(&pmd->info, le64_to_cpu(disk_super->data_mapping_root));
+ dm_btree_del(&pmd->details_info, le64_to_cpu(disk_super->device_details_root));
dm_sm_dec_block(pmd->metadata_sm, held_root);
return dm_tm_unlock(pmd->tm, copy);
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 1c50c58..d2bbe8c 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -666,16 +666,21 @@
requeue_deferred_cells(tc);
}
-static void error_retry_list(struct pool *pool)
+static void error_retry_list_with_code(struct pool *pool, int error)
{
struct thin_c *tc;
rcu_read_lock();
list_for_each_entry_rcu(tc, &pool->active_thins, list)
- error_thin_bio_list(tc, &tc->retry_on_resume_list, -EIO);
+ error_thin_bio_list(tc, &tc->retry_on_resume_list, error);
rcu_read_unlock();
}
+static void error_retry_list(struct pool *pool)
+{
+ return error_retry_list_with_code(pool, -EIO);
+}
+
/*
* This section of code contains the logic for processing a thin device's IO.
* Much of the code depends on pool object resources (lists, workqueues, etc)
@@ -2297,7 +2302,7 @@
if (get_pool_mode(pool) == PM_OUT_OF_DATA_SPACE && !pool->pf.error_if_no_space) {
pool->pf.error_if_no_space = true;
notify_of_pool_mode_change_to_oods(pool);
- error_retry_list(pool);
+ error_retry_list_with_code(pool, -ENOSPC);
}
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index ab37ae1..0d7ab20 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1729,7 +1729,8 @@
struct mapped_device *md = q->queuedata;
struct dm_table *map = dm_get_live_table_fast(md);
struct dm_target *ti;
- sector_t max_sectors, max_size = 0;
+ sector_t max_sectors;
+ int max_size = 0;
if (unlikely(!map))
goto out;
@@ -1742,18 +1743,10 @@
* Find maximum amount of I/O that won't need splitting
*/
max_sectors = min(max_io_len(bvm->bi_sector, ti),
- (sector_t) queue_max_sectors(q));
+ (sector_t) BIO_MAX_SECTORS);
max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size;
-
- /*
- * FIXME: this stop-gap fix _must_ be cleaned up (by passing a sector_t
- * to the targets' merge function since it holds sectors not bytes).
- * Just doing this as an interim fix for stable@ because the more
- * comprehensive cleanup of switching to sector_t will impact every
- * DM target that implements a ->merge hook.
- */
- if (max_size > INT_MAX)
- max_size = INT_MAX;
+ if (max_size < 0)
+ max_size = 0;
/*
* merge_bvec_fn() returns number of bytes
@@ -1761,13 +1754,13 @@
* max is precomputed maximal io size
*/
if (max_size && ti->type->merge)
- max_size = ti->type->merge(ti, bvm, biovec, (int) max_size);
+ max_size = ti->type->merge(ti, bvm, biovec, max_size);
/*
* If the target doesn't support merge method and some of the devices
- * provided their merge_bvec method (we know this by looking for the
- * max_hw_sectors that dm_set_device_limits may set), then we can't
- * allow bios with multiple vector entries. So always set max_size
- * to 0, and the code below allows just one page.
+ * provided their merge_bvec method (we know this by looking at
+ * queue_max_hw_sectors), then we can't allow bios with multiple vector
+ * entries. So always set max_size to 0, and the code below allows
+ * just one page.
*/
else if (queue_max_hw_sectors(q) <= PAGE_SIZE >> 9)
max_size = 0;
diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c
index fcfc4b9..0072190 100644
--- a/drivers/md/md-cluster.c
+++ b/drivers/md/md-cluster.c
@@ -44,6 +44,7 @@
/* md_cluster_info flags */
#define MD_CLUSTER_WAITING_FOR_NEWDISK 1
+#define MD_CLUSTER_SUSPEND_READ_BALANCING 2
struct md_cluster_info {
@@ -275,6 +276,9 @@
static void recover_prep(void *arg)
{
+ struct mddev *mddev = arg;
+ struct md_cluster_info *cinfo = mddev->cluster_info;
+ set_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state);
}
static void recover_slot(void *arg, struct dlm_slot *slot)
@@ -307,6 +311,7 @@
cinfo->slot_number = our_slot;
complete(&cinfo->completion);
+ clear_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state);
}
static const struct dlm_lockspace_ops md_ls_ops = {
@@ -816,12 +821,17 @@
resync_send(mddev, RESYNCING, 0, 0);
}
-static int area_resyncing(struct mddev *mddev, sector_t lo, sector_t hi)
+static int area_resyncing(struct mddev *mddev, int direction,
+ sector_t lo, sector_t hi)
{
struct md_cluster_info *cinfo = mddev->cluster_info;
int ret = 0;
struct suspend_info *s;
+ if ((direction == READ) &&
+ test_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state))
+ return 1;
+
spin_lock_irq(&cinfo->suspend_lock);
if (list_empty(&cinfo->suspend_list))
goto out;
diff --git a/drivers/md/md-cluster.h b/drivers/md/md-cluster.h
index 6817ee0..00defe2 100644
--- a/drivers/md/md-cluster.h
+++ b/drivers/md/md-cluster.h
@@ -18,7 +18,7 @@
int (*metadata_update_start)(struct mddev *mddev);
int (*metadata_update_finish)(struct mddev *mddev);
int (*metadata_update_cancel)(struct mddev *mddev);
- int (*area_resyncing)(struct mddev *mddev, sector_t lo, sector_t hi);
+ int (*area_resyncing)(struct mddev *mddev, int direction, sector_t lo, sector_t hi);
int (*add_new_disk_start)(struct mddev *mddev, struct md_rdev *rdev);
int (*add_new_disk_finish)(struct mddev *mddev);
int (*new_disk_ack)(struct mddev *mddev, bool ack);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index d429c30..e25f00f 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5382,6 +5382,8 @@
{
struct md_personality *pers = mddev->pers;
mddev_detach(mddev);
+ /* Ensure ->event_work is done */
+ flush_workqueue(md_misc_wq);
spin_lock(&mddev->lock);
mddev->ready = 0;
mddev->pers = NULL;
@@ -5757,7 +5759,7 @@
char *ptr;
int err;
- file = kmalloc(sizeof(*file), GFP_NOIO);
+ file = kzalloc(sizeof(*file), GFP_NOIO);
if (!file)
return -ENOMEM;
@@ -7437,7 +7439,7 @@
err = request_module("md-cluster");
if (err) {
pr_err("md-cluster module not found.\n");
- return err;
+ return -ENOENT;
}
spin_lock(&pers_lock);
diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h
index bf2b80d..8731b6e 100644
--- a/drivers/md/persistent-data/dm-btree-internal.h
+++ b/drivers/md/persistent-data/dm-btree-internal.h
@@ -138,4 +138,10 @@
extern struct dm_block_validator btree_node_validator;
+/*
+ * Value type for upper levels of multi-level btrees.
+ */
+extern void init_le64_type(struct dm_transaction_manager *tm,
+ struct dm_btree_value_type *vt);
+
#endif /* DM_BTREE_INTERNAL_H */
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c
index 9836c0a..4222f77 100644
--- a/drivers/md/persistent-data/dm-btree-remove.c
+++ b/drivers/md/persistent-data/dm-btree-remove.c
@@ -544,14 +544,6 @@
return r;
}
-static struct dm_btree_value_type le64_type = {
- .context = NULL,
- .size = sizeof(__le64),
- .inc = NULL,
- .dec = NULL,
- .equal = NULL
-};
-
int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
uint64_t *keys, dm_block_t *new_root)
{
@@ -559,12 +551,14 @@
int index = 0, r = 0;
struct shadow_spine spine;
struct btree_node *n;
+ struct dm_btree_value_type le64_vt;
+ init_le64_type(info->tm, &le64_vt);
init_shadow_spine(&spine, info);
for (level = 0; level < info->levels; level++) {
r = remove_raw(&spine, info,
(level == last_level ?
- &info->value_type : &le64_type),
+ &info->value_type : &le64_vt),
root, keys[level], (unsigned *)&index);
if (r < 0)
break;
@@ -654,11 +648,13 @@
int index = 0, r = 0;
struct shadow_spine spine;
struct btree_node *n;
+ struct dm_btree_value_type le64_vt;
uint64_t k;
+ init_le64_type(info->tm, &le64_vt);
init_shadow_spine(&spine, info);
for (level = 0; level < last_level; level++) {
- r = remove_raw(&spine, info, &le64_type,
+ r = remove_raw(&spine, info, &le64_vt,
root, keys[level], (unsigned *) &index);
if (r < 0)
goto out;
@@ -689,6 +685,7 @@
value_ptr(n, index));
delete_at(n, index);
+ keys[last_level] = k + 1ull;
} else
r = -ENODATA;
diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c
index 1b5e13e..0dee514 100644
--- a/drivers/md/persistent-data/dm-btree-spine.c
+++ b/drivers/md/persistent-data/dm-btree-spine.c
@@ -249,3 +249,40 @@
{
return s->root;
}
+
+static void le64_inc(void *context, const void *value_le)
+{
+ struct dm_transaction_manager *tm = context;
+ __le64 v_le;
+
+ memcpy(&v_le, value_le, sizeof(v_le));
+ dm_tm_inc(tm, le64_to_cpu(v_le));
+}
+
+static void le64_dec(void *context, const void *value_le)
+{
+ struct dm_transaction_manager *tm = context;
+ __le64 v_le;
+
+ memcpy(&v_le, value_le, sizeof(v_le));
+ dm_tm_dec(tm, le64_to_cpu(v_le));
+}
+
+static int le64_equal(void *context, const void *value1_le, const void *value2_le)
+{
+ __le64 v1_le, v2_le;
+
+ memcpy(&v1_le, value1_le, sizeof(v1_le));
+ memcpy(&v2_le, value2_le, sizeof(v2_le));
+ return v1_le == v2_le;
+}
+
+void init_le64_type(struct dm_transaction_manager *tm,
+ struct dm_btree_value_type *vt)
+{
+ vt->context = tm;
+ vt->size = sizeof(__le64);
+ vt->inc = le64_inc;
+ vt->dec = le64_dec;
+ vt->equal = le64_equal;
+}
diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c
index fdd3793..c7726ce 100644
--- a/drivers/md/persistent-data/dm-btree.c
+++ b/drivers/md/persistent-data/dm-btree.c
@@ -667,12 +667,7 @@
struct btree_node *n;
struct dm_btree_value_type le64_type;
- le64_type.context = NULL;
- le64_type.size = sizeof(__le64);
- le64_type.inc = NULL;
- le64_type.dec = NULL;
- le64_type.equal = NULL;
-
+ init_le64_type(info->tm, &le64_type);
init_shadow_spine(&spine, info);
for (level = 0; level < (info->levels - 1); level++) {
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index f80f1af..967a4ed 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -336,7 +336,7 @@
spin_lock_irqsave(&conf->device_lock, flags);
if (r1_bio->mddev->degraded == conf->raid_disks ||
(r1_bio->mddev->degraded == conf->raid_disks-1 &&
- !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags)))
+ test_bit(In_sync, &conf->mirrors[mirror].rdev->flags)))
uptodate = 1;
spin_unlock_irqrestore(&conf->device_lock, flags);
}
@@ -541,7 +541,7 @@
if ((conf->mddev->recovery_cp < this_sector + sectors) ||
(mddev_is_clustered(conf->mddev) &&
- md_cluster_ops->area_resyncing(conf->mddev, this_sector,
+ md_cluster_ops->area_resyncing(conf->mddev, READ, this_sector,
this_sector + sectors)))
choose_first = 1;
else
@@ -1111,7 +1111,8 @@
((bio_end_sector(bio) > mddev->suspend_lo &&
bio->bi_iter.bi_sector < mddev->suspend_hi) ||
(mddev_is_clustered(mddev) &&
- md_cluster_ops->area_resyncing(mddev, bio->bi_iter.bi_sector, bio_end_sector(bio))))) {
+ md_cluster_ops->area_resyncing(mddev, WRITE,
+ bio->bi_iter.bi_sector, bio_end_sector(bio))))) {
/* As the suspend_* range is controlled by
* userspace, we want an interruptible
* wait.
@@ -1124,7 +1125,7 @@
if (bio_end_sector(bio) <= mddev->suspend_lo ||
bio->bi_iter.bi_sector >= mddev->suspend_hi ||
(mddev_is_clustered(mddev) &&
- !md_cluster_ops->area_resyncing(mddev,
+ !md_cluster_ops->area_resyncing(mddev, WRITE,
bio->bi_iter.bi_sector, bio_end_sector(bio))))
break;
schedule();
@@ -1475,6 +1476,7 @@
{
char b[BDEVNAME_SIZE];
struct r1conf *conf = mddev->private;
+ unsigned long flags;
/*
* If it is not operational, then we have already marked it as dead
@@ -1494,14 +1496,13 @@
return;
}
set_bit(Blocked, &rdev->flags);
+ spin_lock_irqsave(&conf->device_lock, flags);
if (test_and_clear_bit(In_sync, &rdev->flags)) {
- unsigned long flags;
- spin_lock_irqsave(&conf->device_lock, flags);
mddev->degraded++;
set_bit(Faulty, &rdev->flags);
- spin_unlock_irqrestore(&conf->device_lock, flags);
} else
set_bit(Faulty, &rdev->flags);
+ spin_unlock_irqrestore(&conf->device_lock, flags);
/*
* if recovery is running, make sure it aborts.
*/
@@ -1567,7 +1568,10 @@
* Find all failed disks within the RAID1 configuration
* and mark them readable.
* Called under mddev lock, so rcu protection not needed.
+ * device_lock used to avoid races with raid1_end_read_request
+ * which expects 'In_sync' flags and ->degraded to be consistent.
*/
+ spin_lock_irqsave(&conf->device_lock, flags);
for (i = 0; i < conf->raid_disks; i++) {
struct md_rdev *rdev = conf->mirrors[i].rdev;
struct md_rdev *repl = conf->mirrors[conf->raid_disks + i].rdev;
@@ -1598,7 +1602,6 @@
sysfs_notify_dirent_safe(rdev->sysfs_state);
}
}
- spin_lock_irqsave(&conf->device_lock, flags);
mddev->degraded -= count;
spin_unlock_irqrestore(&conf->device_lock, flags);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 940f2f3..38c58e1 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -3556,6 +3556,7 @@
/* far_copies must be 1 */
conf->prev.stride = conf->dev_sectors;
}
+ conf->reshape_safe = conf->reshape_progress;
spin_lock_init(&conf->device_lock);
INIT_LIST_HEAD(&conf->retry_list);
@@ -3760,7 +3761,6 @@
}
conf->offset_diff = min_offset_diff;
- conf->reshape_safe = conf->reshape_progress;
clear_bit(MD_RECOVERY_SYNC, &mddev->recovery);
clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
@@ -4103,6 +4103,7 @@
conf->reshape_progress = size;
} else
conf->reshape_progress = 0;
+ conf->reshape_safe = conf->reshape_progress;
spin_unlock_irq(&conf->device_lock);
if (mddev->delta_disks && mddev->bitmap) {
@@ -4170,6 +4171,7 @@
rdev->new_data_offset = rdev->data_offset;
smp_wmb();
conf->reshape_progress = MaxSector;
+ conf->reshape_safe = MaxSector;
mddev->reshape_position = MaxSector;
spin_unlock_irq(&conf->device_lock);
return ret;
@@ -4524,6 +4526,7 @@
md_finish_reshape(conf->mddev);
smp_wmb();
conf->reshape_progress = MaxSector;
+ conf->reshape_safe = MaxSector;
spin_unlock_irq(&conf->device_lock);
/* read-ahead size must cover two whole stripes, which is
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 59e44e9..f757023 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2162,6 +2162,9 @@
if (!sc)
return -ENOMEM;
+ /* Need to ensure auto-resizing doesn't interfere */
+ mutex_lock(&conf->cache_size_mutex);
+
for (i = conf->max_nr_stripes; i; i--) {
nsh = alloc_stripe(sc, GFP_KERNEL);
if (!nsh)
@@ -2178,6 +2181,7 @@
kmem_cache_free(sc, nsh);
}
kmem_cache_destroy(sc);
+ mutex_unlock(&conf->cache_size_mutex);
return -ENOMEM;
}
/* Step 2 - Must use GFP_NOIO now.
@@ -2224,6 +2228,7 @@
} else
err = -ENOMEM;
+ mutex_unlock(&conf->cache_size_mutex);
/* Step 4, return new stripes to service */
while(!list_empty(&newstripes)) {
nsh = list_entry(newstripes.next, struct stripe_head, lru);
@@ -2251,7 +2256,7 @@
static int drop_one_stripe(struct r5conf *conf)
{
struct stripe_head *sh;
- int hash = (conf->max_nr_stripes - 1) % NR_STRIPE_HASH_LOCKS;
+ int hash = (conf->max_nr_stripes - 1) & STRIPE_HASH_LOCKS_MASK;
spin_lock_irq(conf->hash_locks + hash);
sh = get_free_stripe(conf, hash);
@@ -4061,8 +4066,10 @@
&first_bad, &bad_sectors))
set_bit(R5_ReadRepl, &dev->flags);
else {
- if (rdev)
+ if (rdev && !test_bit(Faulty, &rdev->flags))
set_bit(R5_NeedReplace, &dev->flags);
+ else
+ clear_bit(R5_NeedReplace, &dev->flags);
rdev = rcu_dereference(conf->disks[i].rdev);
clear_bit(R5_ReadRepl, &dev->flags);
}
@@ -5857,12 +5864,14 @@
pr_debug("%d stripes handled\n", handled);
spin_unlock_irq(&conf->device_lock);
- if (test_and_clear_bit(R5_ALLOC_MORE, &conf->cache_state)) {
+ if (test_and_clear_bit(R5_ALLOC_MORE, &conf->cache_state) &&
+ mutex_trylock(&conf->cache_size_mutex)) {
grow_one_stripe(conf, __GFP_NOWARN);
/* Set flag even if allocation failed. This helps
* slow down allocation requests when mem is short
*/
set_bit(R5_DID_ALLOC, &conf->cache_state);
+ mutex_unlock(&conf->cache_size_mutex);
}
async_tx_issue_pending_all();
@@ -5894,18 +5903,22 @@
return -EINVAL;
conf->min_nr_stripes = size;
+ mutex_lock(&conf->cache_size_mutex);
while (size < conf->max_nr_stripes &&
drop_one_stripe(conf))
;
+ mutex_unlock(&conf->cache_size_mutex);
err = md_allow_write(mddev);
if (err)
return err;
+ mutex_lock(&conf->cache_size_mutex);
while (size > conf->max_nr_stripes)
if (!grow_one_stripe(conf, GFP_KERNEL))
break;
+ mutex_unlock(&conf->cache_size_mutex);
return 0;
}
@@ -6371,11 +6384,19 @@
struct shrink_control *sc)
{
struct r5conf *conf = container_of(shrink, struct r5conf, shrinker);
- int ret = 0;
- while (ret < sc->nr_to_scan) {
- if (drop_one_stripe(conf) == 0)
- return SHRINK_STOP;
- ret++;
+ unsigned long ret = SHRINK_STOP;
+
+ if (mutex_trylock(&conf->cache_size_mutex)) {
+ ret= 0;
+ while (ret < sc->nr_to_scan &&
+ conf->max_nr_stripes > conf->min_nr_stripes) {
+ if (drop_one_stripe(conf) == 0) {
+ ret = SHRINK_STOP;
+ break;
+ }
+ ret++;
+ }
+ mutex_unlock(&conf->cache_size_mutex);
}
return ret;
}
@@ -6444,6 +6465,7 @@
goto abort;
spin_lock_init(&conf->device_lock);
seqcount_init(&conf->gen_lock);
+ mutex_init(&conf->cache_size_mutex);
init_waitqueue_head(&conf->wait_for_quiescent);
for (i = 0; i < NR_STRIPE_HASH_LOCKS; i++) {
init_waitqueue_head(&conf->wait_for_stripe[i]);
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 02c3bf8..d051442 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -482,7 +482,8 @@
*/
int active_name;
char cache_name[2][32];
- struct kmem_cache *slab_cache; /* for allocating stripes */
+ struct kmem_cache *slab_cache; /* for allocating stripes */
+ struct mutex cache_size_mutex; /* Protect changes to cache size */
int seq_flush, seq_write;
int quiesce;
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 0d35f58..5ab90f3 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -240,7 +240,7 @@
config DVB_TS2020
tristate "Montage Tehnology TS2020 based tuners"
- depends on DVB_CORE
+ depends on DVB_CORE && I2C
select REGMAP_I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
diff --git a/drivers/media/pci/cobalt/Kconfig b/drivers/media/pci/cobalt/Kconfig
index 3be1b2c..6a1c008 100644
--- a/drivers/media/pci/cobalt/Kconfig
+++ b/drivers/media/pci/cobalt/Kconfig
@@ -2,6 +2,7 @@
tristate "Cisco Cobalt support"
depends on VIDEO_V4L2 && I2C && MEDIA_CONTROLLER
depends on PCI_MSI && MTD_COMPLEX_MAPPINGS && GPIOLIB
+ depends on SND
select I2C_ALGOBIT
select VIDEO_ADV7604
select VIDEO_ADV7511
diff --git a/drivers/media/pci/cobalt/cobalt-irq.c b/drivers/media/pci/cobalt/cobalt-irq.c
index dd4bff9..d1f5898 100644
--- a/drivers/media/pci/cobalt/cobalt-irq.c
+++ b/drivers/media/pci/cobalt/cobalt-irq.c
@@ -139,7 +139,7 @@
also know about dropped frames. */
cb->vb.v4l2_buf.sequence = s->sequence++;
vb2_buffer_done(&cb->vb, (skip || s->unstable_frame) ?
- VB2_BUF_STATE_QUEUED : VB2_BUF_STATE_DONE);
+ VB2_BUF_STATE_REQUEUEING : VB2_BUF_STATE_DONE);
}
irqreturn_t cobalt_irq_handler(int irq, void *dev_id)
diff --git a/drivers/media/pci/ivtv/ivtvfb.c b/drivers/media/pci/ivtv/ivtvfb.c
index 4cb365d..8b95eef 100644
--- a/drivers/media/pci/ivtv/ivtvfb.c
+++ b/drivers/media/pci/ivtv/ivtvfb.c
@@ -38,6 +38,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fb.h>
@@ -1171,6 +1173,13 @@
{
int rc;
+#ifdef CONFIG_X86_64
+ if (pat_enabled()) {
+ pr_warn("ivtvfb needs PAT disabled, boot with nopat kernel parameter\n");
+ return -ENODEV;
+ }
+#endif
+
if (itv->osd_info) {
IVTVFB_ERR("Card %d already initialised\n", ivtvfb_card_id);
return -EBUSY;
@@ -1265,12 +1274,6 @@
int registered = 0;
int err;
-#ifdef CONFIG_X86_64
- if (WARN(pat_enabled(),
- "ivtvfb needs PAT disabled, boot with nopat kernel parameter\n")) {
- return -ENODEV;
- }
-#endif
if (ivtvfb_card_id < -1 || ivtvfb_card_id >= IVTV_MAX_CARDS) {
printk(KERN_ERR "ivtvfb: ivtvfb_card_id parameter is out of range (valid range: -1 - %d)\n",
diff --git a/drivers/media/pci/mantis/mantis_dma.c b/drivers/media/pci/mantis/mantis_dma.c
index 1d59c7e..87990ec 100644
--- a/drivers/media/pci/mantis/mantis_dma.c
+++ b/drivers/media/pci/mantis/mantis_dma.c
@@ -130,10 +130,11 @@
int mantis_dma_init(struct mantis_pci *mantis)
{
- int err = 0;
+ int err;
dprintk(MANTIS_DEBUG, 1, "Mantis DMA init");
- if (mantis_alloc_buffers(mantis) < 0) {
+ err = mantis_alloc_buffers(mantis);
+ if (err < 0) {
dprintk(MANTIS_ERROR, 1, "Error allocating DMA buffer");
/* Stop RISC Engine */
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 8939ebd..84fa6e9 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -184,125 +184,9 @@
return -EINVAL;
}
-static struct ir_raw_timings_manchester ir_rc5_timings = {
- .leader = RC5_UNIT,
- .pulse_space_start = 0,
- .clock = RC5_UNIT,
- .trailer_space = RC5_UNIT * 10,
-};
-
-static struct ir_raw_timings_manchester ir_rc5x_timings[2] = {
- {
- .leader = RC5_UNIT,
- .pulse_space_start = 0,
- .clock = RC5_UNIT,
- .trailer_space = RC5X_SPACE,
- },
- {
- .clock = RC5_UNIT,
- .trailer_space = RC5_UNIT * 10,
- },
-};
-
-static struct ir_raw_timings_manchester ir_rc5_sz_timings = {
- .leader = RC5_UNIT,
- .pulse_space_start = 0,
- .clock = RC5_UNIT,
- .trailer_space = RC5_UNIT * 10,
-};
-
-static int ir_rc5_validate_filter(const struct rc_scancode_filter *scancode,
- unsigned int important_bits)
-{
- /* all important bits of scancode should be set in mask */
- if (~scancode->mask & important_bits)
- return -EINVAL;
- /* extra bits in mask should be zero in data */
- if (scancode->mask & scancode->data & ~important_bits)
- return -EINVAL;
- return 0;
-}
-
-/**
- * ir_rc5_encode() - Encode a scancode as a stream of raw events
- *
- * @protocols: allowed protocols
- * @scancode: scancode filter describing scancode (helps distinguish between
- * protocol subtypes when scancode is ambiguous)
- * @events: array of raw ir events to write into
- * @max: maximum size of @events
- *
- * Returns: The number of events written.
- * -ENOBUFS if there isn't enough space in the array to fit the
- * encoding. In this case all @max events will have been written.
- * -EINVAL if the scancode is ambiguous or invalid.
- */
-static int ir_rc5_encode(u64 protocols,
- const struct rc_scancode_filter *scancode,
- struct ir_raw_event *events, unsigned int max)
-{
- int ret;
- struct ir_raw_event *e = events;
- unsigned int data, xdata, command, commandx, system;
-
- /* Detect protocol and convert scancode to raw data */
- if (protocols & RC_BIT_RC5 &&
- !ir_rc5_validate_filter(scancode, 0x1f7f)) {
- /* decode scancode */
- command = (scancode->data & 0x003f) >> 0;
- commandx = (scancode->data & 0x0040) >> 6;
- system = (scancode->data & 0x1f00) >> 8;
- /* encode data */
- data = !commandx << 12 | system << 6 | command;
-
- /* Modulate the data */
- ret = ir_raw_gen_manchester(&e, max, &ir_rc5_timings, RC5_NBITS,
- data);
- if (ret < 0)
- return ret;
- } else if (protocols & RC_BIT_RC5X &&
- !ir_rc5_validate_filter(scancode, 0x1f7f3f)) {
- /* decode scancode */
- xdata = (scancode->data & 0x00003f) >> 0;
- command = (scancode->data & 0x003f00) >> 8;
- commandx = (scancode->data & 0x004000) >> 14;
- system = (scancode->data & 0x1f0000) >> 16;
- /* commandx and system overlap, bits must match when encoded */
- if (commandx == (system & 0x1))
- return -EINVAL;
- /* encode data */
- data = 1 << 18 | system << 12 | command << 6 | xdata;
-
- /* Modulate the data */
- ret = ir_raw_gen_manchester(&e, max, &ir_rc5x_timings[0],
- CHECK_RC5X_NBITS,
- data >> (RC5X_NBITS-CHECK_RC5X_NBITS));
- if (ret < 0)
- return ret;
- ret = ir_raw_gen_manchester(&e, max - (e - events),
- &ir_rc5x_timings[1],
- RC5X_NBITS - CHECK_RC5X_NBITS,
- data);
- if (ret < 0)
- return ret;
- } else if (protocols & RC_BIT_RC5_SZ &&
- !ir_rc5_validate_filter(scancode, 0x2fff)) {
- /* RC5-SZ scancode is raw enough for Manchester as it is */
- ret = ir_raw_gen_manchester(&e, max, &ir_rc5_sz_timings,
- RC5_SZ_NBITS, scancode->data & 0x2fff);
- if (ret < 0)
- return ret;
- } else {
- return -EINVAL;
- }
-
- return e - events;
-}
-
static struct ir_raw_handler rc5_handler = {
.protocols = RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ,
.decode = ir_rc5_decode,
- .encode = ir_rc5_encode,
};
static int __init ir_rc5_decode_init(void)
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index f9c70ba..d16bc67 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -291,133 +291,11 @@
return -EINVAL;
}
-static struct ir_raw_timings_manchester ir_rc6_timings[4] = {
- {
- .leader = RC6_PREFIX_PULSE,
- .pulse_space_start = 0,
- .clock = RC6_UNIT,
- .invert = 1,
- .trailer_space = RC6_PREFIX_SPACE,
- },
- {
- .clock = RC6_UNIT,
- .invert = 1,
- },
- {
- .clock = RC6_UNIT * 2,
- .invert = 1,
- },
- {
- .clock = RC6_UNIT,
- .invert = 1,
- .trailer_space = RC6_SUFFIX_SPACE,
- },
-};
-
-static int ir_rc6_validate_filter(const struct rc_scancode_filter *scancode,
- unsigned int important_bits)
-{
- /* all important bits of scancode should be set in mask */
- if (~scancode->mask & important_bits)
- return -EINVAL;
- /* extra bits in mask should be zero in data */
- if (scancode->mask & scancode->data & ~important_bits)
- return -EINVAL;
- return 0;
-}
-
-/**
- * ir_rc6_encode() - Encode a scancode as a stream of raw events
- *
- * @protocols: allowed protocols
- * @scancode: scancode filter describing scancode (helps distinguish between
- * protocol subtypes when scancode is ambiguous)
- * @events: array of raw ir events to write into
- * @max: maximum size of @events
- *
- * Returns: The number of events written.
- * -ENOBUFS if there isn't enough space in the array to fit the
- * encoding. In this case all @max events will have been written.
- * -EINVAL if the scancode is ambiguous or invalid.
- */
-static int ir_rc6_encode(u64 protocols,
- const struct rc_scancode_filter *scancode,
- struct ir_raw_event *events, unsigned int max)
-{
- int ret;
- struct ir_raw_event *e = events;
-
- if (protocols & RC_BIT_RC6_0 &&
- !ir_rc6_validate_filter(scancode, 0xffff)) {
-
- /* Modulate the preamble */
- ret = ir_raw_gen_manchester(&e, max, &ir_rc6_timings[0], 0, 0);
- if (ret < 0)
- return ret;
-
- /* Modulate the header (Start Bit & Mode-0) */
- ret = ir_raw_gen_manchester(&e, max - (e - events),
- &ir_rc6_timings[1],
- RC6_HEADER_NBITS, (1 << 3));
- if (ret < 0)
- return ret;
-
- /* Modulate Trailer Bit */
- ret = ir_raw_gen_manchester(&e, max - (e - events),
- &ir_rc6_timings[2], 1, 0);
- if (ret < 0)
- return ret;
-
- /* Modulate rest of the data */
- ret = ir_raw_gen_manchester(&e, max - (e - events),
- &ir_rc6_timings[3], RC6_0_NBITS,
- scancode->data);
- if (ret < 0)
- return ret;
-
- } else if (protocols & (RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
- RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE) &&
- !ir_rc6_validate_filter(scancode, 0x8fffffff)) {
-
- /* Modulate the preamble */
- ret = ir_raw_gen_manchester(&e, max, &ir_rc6_timings[0], 0, 0);
- if (ret < 0)
- return ret;
-
- /* Modulate the header (Start Bit & Header-version 6 */
- ret = ir_raw_gen_manchester(&e, max - (e - events),
- &ir_rc6_timings[1],
- RC6_HEADER_NBITS, (1 << 3 | 6));
- if (ret < 0)
- return ret;
-
- /* Modulate Trailer Bit */
- ret = ir_raw_gen_manchester(&e, max - (e - events),
- &ir_rc6_timings[2], 1, 0);
- if (ret < 0)
- return ret;
-
- /* Modulate rest of the data */
- ret = ir_raw_gen_manchester(&e, max - (e - events),
- &ir_rc6_timings[3],
- fls(scancode->mask),
- scancode->data);
- if (ret < 0)
- return ret;
-
- } else {
- return -EINVAL;
- }
-
- return e - events;
-}
-
static struct ir_raw_handler rc6_handler = {
.protocols = RC_BIT_RC6_0 | RC_BIT_RC6_6A_20 |
RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 |
RC_BIT_RC6_MCE,
.decode = ir_rc6_decode,
- .encode = ir_rc6_encode,
};
static int __init ir_rc6_decode_init(void)
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c
index baeb597..85af7a8 100644
--- a/drivers/media/rc/nuvoton-cir.c
+++ b/drivers/media/rc/nuvoton-cir.c
@@ -526,130 +526,6 @@
return 0;
}
-static int nvt_write_wakeup_codes(struct rc_dev *dev,
- const u8 *wakeup_sample_buf, int count)
-{
- int i = 0;
- u8 reg, reg_learn_mode;
- unsigned long flags;
- struct nvt_dev *nvt = dev->priv;
-
- nvt_dbg_wake("writing wakeup samples");
-
- reg = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON);
- reg_learn_mode = reg & ~CIR_WAKE_IRCON_MODE0;
- reg_learn_mode |= CIR_WAKE_IRCON_MODE1;
-
- /* Lock the learn area to prevent racing with wake-isr */
- spin_lock_irqsave(&nvt->nvt_lock, flags);
-
- /* Enable fifo writes */
- nvt_cir_wake_reg_write(nvt, reg_learn_mode, CIR_WAKE_IRCON);
-
- /* Clear cir wake rx fifo */
- nvt_clear_cir_wake_fifo(nvt);
-
- if (count > WAKE_FIFO_LEN) {
- nvt_dbg_wake("HW FIFO too small for all wake samples");
- count = WAKE_FIFO_LEN;
- }
-
- if (count)
- pr_info("Wake samples (%d) =", count);
- else
- pr_info("Wake sample fifo cleared");
-
- /* Write wake samples to fifo */
- for (i = 0; i < count; i++) {
- pr_cont(" %02x", wakeup_sample_buf[i]);
- nvt_cir_wake_reg_write(nvt, wakeup_sample_buf[i],
- CIR_WAKE_WR_FIFO_DATA);
- }
- pr_cont("\n");
-
- /* Switch cir to wakeup mode and disable fifo writing */
- nvt_cir_wake_reg_write(nvt, reg, CIR_WAKE_IRCON);
-
- /* Set number of bytes needed for wake */
- nvt_cir_wake_reg_write(nvt, count ? count :
- CIR_WAKE_FIFO_CMP_BYTES,
- CIR_WAKE_FIFO_CMP_DEEP);
-
- spin_unlock_irqrestore(&nvt->nvt_lock, flags);
-
- return 0;
-}
-
-static int nvt_ir_raw_set_wakeup_filter(struct rc_dev *dev,
- struct rc_scancode_filter *sc_filter)
-{
- u8 *reg_buf;
- u8 buf_val;
- int i, ret, count;
- unsigned int val;
- struct ir_raw_event *raw;
- bool complete;
-
- /* Require both mask and data to be set before actually committing */
- if (!sc_filter->mask || !sc_filter->data)
- return 0;
-
- raw = kmalloc_array(WAKE_FIFO_LEN, sizeof(*raw), GFP_KERNEL);
- if (!raw)
- return -ENOMEM;
-
- ret = ir_raw_encode_scancode(dev->enabled_wakeup_protocols, sc_filter,
- raw, WAKE_FIFO_LEN);
- complete = (ret != -ENOBUFS);
- if (!complete)
- ret = WAKE_FIFO_LEN;
- else if (ret < 0)
- goto out_raw;
-
- reg_buf = kmalloc_array(WAKE_FIFO_LEN, sizeof(*reg_buf), GFP_KERNEL);
- if (!reg_buf) {
- ret = -ENOMEM;
- goto out_raw;
- }
-
- /* Inspect the ir samples */
- for (i = 0, count = 0; i < ret && count < WAKE_FIFO_LEN; ++i) {
- val = NS_TO_US((raw[i]).duration) / SAMPLE_PERIOD;
-
- /* Split too large values into several smaller ones */
- while (val > 0 && count < WAKE_FIFO_LEN) {
-
- /* Skip last value for better comparison tolerance */
- if (complete && i == ret - 1 && val < BUF_LEN_MASK)
- break;
-
- /* Clamp values to BUF_LEN_MASK at most */
- buf_val = (val > BUF_LEN_MASK) ? BUF_LEN_MASK : val;
-
- reg_buf[count] = buf_val;
- val -= buf_val;
- if ((raw[i]).pulse)
- reg_buf[count] |= BUF_PULSE_BIT;
- count++;
- }
- }
-
- ret = nvt_write_wakeup_codes(dev, reg_buf, count);
-
- kfree(reg_buf);
-out_raw:
- kfree(raw);
-
- return ret;
-}
-
-/* Dummy implementation. nuvoton is agnostic to the protocol used */
-static int nvt_ir_raw_change_wakeup_protocol(struct rc_dev *dev,
- u64 *rc_type)
-{
- return 0;
-}
-
/*
* nvt_tx_ir
*
@@ -1167,14 +1043,11 @@
/* Set up the rc device */
rdev->priv = nvt;
rdev->driver_type = RC_DRIVER_IR_RAW;
- rdev->encode_wakeup = true;
rdev->allowed_protocols = RC_BIT_ALL;
rdev->open = nvt_open;
rdev->close = nvt_close;
rdev->tx_ir = nvt_tx_ir;
rdev->s_tx_carrier = nvt_set_tx_carrier;
- rdev->s_wakeup_filter = nvt_ir_raw_set_wakeup_filter;
- rdev->change_wakeup_protocol = nvt_ir_raw_change_wakeup_protocol;
rdev->input_name = "Nuvoton w836x7hg Infrared Remote Transceiver";
rdev->input_phys = "nuvoton/cir0";
rdev->input_id.bustype = BUS_HOST;
diff --git a/drivers/media/rc/nuvoton-cir.h b/drivers/media/rc/nuvoton-cir.h
index 9d0e161..e1cf23c 100644
--- a/drivers/media/rc/nuvoton-cir.h
+++ b/drivers/media/rc/nuvoton-cir.h
@@ -63,7 +63,6 @@
*/
#define TX_BUF_LEN 256
#define RX_BUF_LEN 32
-#define WAKE_FIFO_LEN 67
struct nvt_dev {
struct pnp_dev *pdev;
diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
index 4b994aa..b68d4f76 100644
--- a/drivers/media/rc/rc-core-priv.h
+++ b/drivers/media/rc/rc-core-priv.h
@@ -25,8 +25,6 @@
u64 protocols; /* which are handled by this handler */
int (*decode)(struct rc_dev *dev, struct ir_raw_event event);
- int (*encode)(u64 protocols, const struct rc_scancode_filter *scancode,
- struct ir_raw_event *events, unsigned int max);
/* These two should only be used by the lirc decoder */
int (*raw_register)(struct rc_dev *dev);
@@ -152,44 +150,10 @@
#define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000)
#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
-/* functions for IR encoders */
-
-static inline void init_ir_raw_event_duration(struct ir_raw_event *ev,
- unsigned int pulse,
- u32 duration)
-{
- init_ir_raw_event(ev);
- ev->duration = duration;
- ev->pulse = pulse;
-}
-
-/**
- * struct ir_raw_timings_manchester - Manchester coding timings
- * @leader: duration of leader pulse (if any) 0 if continuing
- * existing signal (see @pulse_space_start)
- * @pulse_space_start: 1 for starting with pulse (0 for starting with space)
- * @clock: duration of each pulse/space in ns
- * @invert: if set clock logic is inverted
- * (0 = space + pulse, 1 = pulse + space)
- * @trailer_space: duration of trailer space in ns
- */
-struct ir_raw_timings_manchester {
- unsigned int leader;
- unsigned int pulse_space_start:1;
- unsigned int clock;
- unsigned int invert:1;
- unsigned int trailer_space;
-};
-
-int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max,
- const struct ir_raw_timings_manchester *timings,
- unsigned int n, unsigned int data);
-
/*
* Routines from rc-raw.c to be used internally and by decoders
*/
u64 ir_raw_get_allowed_protocols(void);
-u64 ir_raw_get_encode_protocols(void);
int ir_raw_event_register(struct rc_dev *dev);
void ir_raw_event_unregister(struct rc_dev *dev);
int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index b9e4645..b732ac6 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -30,7 +30,6 @@
static DEFINE_MUTEX(ir_raw_handler_lock);
static LIST_HEAD(ir_raw_handler_list);
static u64 available_protocols;
-static u64 encode_protocols;
static int ir_raw_event_thread(void *data)
{
@@ -241,146 +240,12 @@
return protocols;
}
-/* used internally by the sysfs interface */
-u64
-ir_raw_get_encode_protocols(void)
-{
- u64 protocols;
-
- mutex_lock(&ir_raw_handler_lock);
- protocols = encode_protocols;
- mutex_unlock(&ir_raw_handler_lock);
- return protocols;
-}
-
static int change_protocol(struct rc_dev *dev, u64 *rc_type)
{
/* the caller will update dev->enabled_protocols */
return 0;
}
-/**
- * ir_raw_gen_manchester() - Encode data with Manchester (bi-phase) modulation.
- * @ev: Pointer to pointer to next free event. *@ev is incremented for
- * each raw event filled.
- * @max: Maximum number of raw events to fill.
- * @timings: Manchester modulation timings.
- * @n: Number of bits of data.
- * @data: Data bits to encode.
- *
- * Encodes the @n least significant bits of @data using Manchester (bi-phase)
- * modulation with the timing characteristics described by @timings, writing up
- * to @max raw IR events using the *@ev pointer.
- *
- * Returns: 0 on success.
- * -ENOBUFS if there isn't enough space in the array to fit the
- * full encoded data. In this case all @max events will have been
- * written.
- */
-int ir_raw_gen_manchester(struct ir_raw_event **ev, unsigned int max,
- const struct ir_raw_timings_manchester *timings,
- unsigned int n, unsigned int data)
-{
- bool need_pulse;
- unsigned int i;
- int ret = -ENOBUFS;
-
- i = 1 << (n - 1);
-
- if (timings->leader) {
- if (!max--)
- return ret;
- if (timings->pulse_space_start) {
- init_ir_raw_event_duration((*ev)++, 1, timings->leader);
-
- if (!max--)
- return ret;
- init_ir_raw_event_duration((*ev), 0, timings->leader);
- } else {
- init_ir_raw_event_duration((*ev), 1, timings->leader);
- }
- i >>= 1;
- } else {
- /* continue existing signal */
- --(*ev);
- }
- /* from here on *ev will point to the last event rather than the next */
-
- while (n && i > 0) {
- need_pulse = !(data & i);
- if (timings->invert)
- need_pulse = !need_pulse;
- if (need_pulse == !!(*ev)->pulse) {
- (*ev)->duration += timings->clock;
- } else {
- if (!max--)
- goto nobufs;
- init_ir_raw_event_duration(++(*ev), need_pulse,
- timings->clock);
- }
-
- if (!max--)
- goto nobufs;
- init_ir_raw_event_duration(++(*ev), !need_pulse,
- timings->clock);
- i >>= 1;
- }
-
- if (timings->trailer_space) {
- if (!(*ev)->pulse)
- (*ev)->duration += timings->trailer_space;
- else if (!max--)
- goto nobufs;
- else
- init_ir_raw_event_duration(++(*ev), 0,
- timings->trailer_space);
- }
-
- ret = 0;
-nobufs:
- /* point to the next event rather than last event before returning */
- ++(*ev);
- return ret;
-}
-EXPORT_SYMBOL(ir_raw_gen_manchester);
-
-/**
- * ir_raw_encode_scancode() - Encode a scancode as raw events
- *
- * @protocols: permitted protocols
- * @scancode: scancode filter describing a single scancode
- * @events: array of raw events to write into
- * @max: max number of raw events
- *
- * Attempts to encode the scancode as raw events.
- *
- * Returns: The number of events written.
- * -ENOBUFS if there isn't enough space in the array to fit the
- * encoding. In this case all @max events will have been written.
- * -EINVAL if the scancode is ambiguous or invalid, or if no
- * compatible encoder was found.
- */
-int ir_raw_encode_scancode(u64 protocols,
- const struct rc_scancode_filter *scancode,
- struct ir_raw_event *events, unsigned int max)
-{
- struct ir_raw_handler *handler;
- int ret = -EINVAL;
-
- mutex_lock(&ir_raw_handler_lock);
- list_for_each_entry(handler, &ir_raw_handler_list, list) {
- if (handler->protocols & protocols && handler->encode) {
- ret = handler->encode(protocols, scancode, events, max);
- if (ret >= 0 || ret == -ENOBUFS)
- break;
- }
- }
- mutex_unlock(&ir_raw_handler_lock);
-
- return ret;
-}
-EXPORT_SYMBOL(ir_raw_encode_scancode);
-
/*
* Used to (un)register raw event clients
*/
@@ -463,8 +328,6 @@
list_for_each_entry(raw, &ir_raw_client_list, list)
ir_raw_handler->raw_register(raw->dev);
available_protocols |= ir_raw_handler->protocols;
- if (ir_raw_handler->encode)
- encode_protocols |= ir_raw_handler->protocols;
mutex_unlock(&ir_raw_handler_lock);
return 0;
@@ -481,8 +344,6 @@
list_for_each_entry(raw, &ir_raw_client_list, list)
ir_raw_handler->raw_unregister(raw->dev);
available_protocols &= ~ir_raw_handler->protocols;
- if (ir_raw_handler->encode)
- encode_protocols &= ~ir_raw_handler->protocols;
mutex_unlock(&ir_raw_handler_lock);
}
EXPORT_SYMBOL(ir_raw_handler_unregister);
diff --git a/drivers/media/rc/rc-loopback.c b/drivers/media/rc/rc-loopback.c
index d8bdf63..63dace8 100644
--- a/drivers/media/rc/rc-loopback.c
+++ b/drivers/media/rc/rc-loopback.c
@@ -26,7 +26,6 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/sched.h>
-#include <linux/slab.h>
#include <media/rc-core.h>
#define DRIVER_NAME "rc-loopback"
@@ -177,39 +176,6 @@
return 0;
}
-static int loop_set_wakeup_filter(struct rc_dev *dev,
- struct rc_scancode_filter *sc_filter)
-{
- static const unsigned int max = 512;
- struct ir_raw_event *raw;
- int ret;
- int i;
-
- /* fine to disable filter */
- if (!sc_filter->mask)
- return 0;
-
- /* encode the specified filter and loop it back */
- raw = kmalloc_array(max, sizeof(*raw), GFP_KERNEL);
- ret = ir_raw_encode_scancode(dev->enabled_wakeup_protocols, sc_filter,
- raw, max);
- /* still loop back the partial raw IR even if it's incomplete */
- if (ret == -ENOBUFS)
- ret = max;
- if (ret >= 0) {
- /* do the loopback */
- for (i = 0; i < ret; ++i)
- ir_raw_event_store(dev, &raw[i]);
- ir_raw_event_handle(dev);
-
- ret = 0;
- }
-
- kfree(raw);
-
- return ret;
-}
-
static int __init loop_init(void)
{
struct rc_dev *rc;
@@ -229,7 +195,6 @@
rc->map_name = RC_MAP_EMPTY;
rc->priv = &loopdev;
rc->driver_type = RC_DRIVER_IR_RAW;
- rc->encode_wakeup = true;
rc->allowed_protocols = RC_BIT_ALL;
rc->timeout = 100 * 1000 * 1000; /* 100 ms */
rc->min_timeout = 1;
@@ -244,7 +209,6 @@
rc->s_idle = loop_set_idle;
rc->s_learning_mode = loop_set_learning_mode;
rc->s_carrier_report = loop_set_carrier_report;
- rc->s_wakeup_filter = loop_set_wakeup_filter;
loopdev.txmask = RXMASK_REGULAR;
loopdev.txcarrier = 36000;
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 9d015db..0ff388a 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -865,8 +865,6 @@
} else {
enabled = dev->enabled_wakeup_protocols;
allowed = dev->allowed_wakeup_protocols;
- if (dev->encode_wakeup && !allowed)
- allowed = ir_raw_get_encode_protocols();
}
mutex_unlock(&dev->lock);
@@ -1408,16 +1406,13 @@
path ? path : "N/A");
kfree(path);
- if (dev->driver_type == RC_DRIVER_IR_RAW || dev->encode_wakeup) {
+ if (dev->driver_type == RC_DRIVER_IR_RAW) {
/* Load raw decoders, if they aren't already */
if (!raw_init) {
IR_dprintk(1, "Loading raw decoders\n");
ir_raw_init();
raw_init = true;
}
- }
-
- if (dev->driver_type == RC_DRIVER_IR_RAW) {
/* calls ir_register_device so unlock mutex here*/
mutex_unlock(&dev->lock);
rc = ir_raw_event_register(dev);
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 93b3154..a14c428 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -715,6 +715,7 @@
break;
case VB2_BUF_STATE_PREPARING:
case VB2_BUF_STATE_DEQUEUED:
+ case VB2_BUF_STATE_REQUEUEING:
/* nothing */
break;
}
@@ -1182,7 +1183,8 @@
if (WARN_ON(state != VB2_BUF_STATE_DONE &&
state != VB2_BUF_STATE_ERROR &&
- state != VB2_BUF_STATE_QUEUED))
+ state != VB2_BUF_STATE_QUEUED &&
+ state != VB2_BUF_STATE_REQUEUEING))
state = VB2_BUF_STATE_ERROR;
#ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -1199,22 +1201,30 @@
for (plane = 0; plane < vb->num_planes; ++plane)
call_void_memop(vb, finish, vb->planes[plane].mem_priv);
- /* Add the buffer to the done buffers list */
spin_lock_irqsave(&q->done_lock, flags);
- vb->state = state;
- if (state != VB2_BUF_STATE_QUEUED)
+ if (state == VB2_BUF_STATE_QUEUED ||
+ state == VB2_BUF_STATE_REQUEUEING) {
+ vb->state = VB2_BUF_STATE_QUEUED;
+ } else {
+ /* Add the buffer to the done buffers list */
list_add_tail(&vb->done_entry, &q->done_list);
+ vb->state = state;
+ }
atomic_dec(&q->owned_by_drv_count);
spin_unlock_irqrestore(&q->done_lock, flags);
- if (state == VB2_BUF_STATE_QUEUED) {
+ switch (state) {
+ case VB2_BUF_STATE_QUEUED:
+ return;
+ case VB2_BUF_STATE_REQUEUEING:
if (q->start_streaming_called)
__enqueue_in_driver(vb);
return;
+ default:
+ /* Inform any processes that may be waiting for buffers */
+ wake_up(&q->done_wq);
+ break;
}
-
- /* Inform any processes that may be waiting for buffers */
- wake_up(&q->done_wq);
}
EXPORT_SYMBOL_GPL(vb2_buffer_done);
@@ -1244,19 +1254,19 @@
static void vb2_warn_zero_bytesused(struct vb2_buffer *vb)
{
- static bool __check_once __read_mostly;
+ static bool check_once;
- if (__check_once)
+ if (check_once)
return;
- __check_once = true;
- __WARN();
+ check_once = true;
+ WARN_ON(1);
- pr_warn_once("use of bytesused == 0 is deprecated and will be removed in the future,\n");
+ pr_warn("use of bytesused == 0 is deprecated and will be removed in the future,\n");
if (vb->vb2_queue->allow_zero_bytesused)
- pr_warn_once("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n");
+ pr_warn("use VIDIOC_DECODER_CMD(V4L2_DEC_CMD_STOP) instead.\n");
else
- pr_warn_once("use the actual size instead.\n");
+ pr_warn("use the actual size instead.\n");
}
/**
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 3a27a84..9426276 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -2245,6 +2245,9 @@
{
int i;
+ if (!gpmc_base)
+ return;
+
gpmc_context.sysconfig = gpmc_read_reg(GPMC_SYSCONFIG);
gpmc_context.irqenable = gpmc_read_reg(GPMC_IRQENABLE);
gpmc_context.timeout_ctrl = gpmc_read_reg(GPMC_TIMEOUT_CONTROL);
@@ -2277,6 +2280,9 @@
{
int i;
+ if (!gpmc_base)
+ return;
+
gpmc_write_reg(GPMC_SYSCONFIG, gpmc_context.sysconfig);
gpmc_write_reg(GPMC_IRQENABLE, gpmc_context.irqenable);
gpmc_write_reg(GPMC_TIMEOUT_CONTROL, gpmc_context.timeout_ctrl);
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6538159..3f68dd2 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -115,7 +115,7 @@
config MFD_CROS_EC_SPI
tristate "ChromeOS Embedded Controller (SPI)"
- depends on MFD_CROS_EC && CROS_EC_PROTO && SPI && OF
+ depends on MFD_CROS_EC && CROS_EC_PROTO && SPI
---help---
If you say Y here, you get support for talking to the ChromeOS EC
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index bebf58a..a72ddb29 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -651,7 +651,7 @@
arizona->has_fully_powered_off = true;
- disable_irq(arizona->irq);
+ disable_irq_nosync(arizona->irq);
arizona_enable_reset(arizona);
regulator_bulk_disable(arizona->num_core_supplies,
arizona->core_supplies);
@@ -1141,10 +1141,6 @@
arizona->pdata.gpio_defaults[i]);
}
- pm_runtime_set_autosuspend_delay(arizona->dev, 100);
- pm_runtime_use_autosuspend(arizona->dev);
- pm_runtime_enable(arizona->dev);
-
/* Chip default */
if (!arizona->pdata.clk32k_src)
arizona->pdata.clk32k_src = ARIZONA_32KZ_MCLK2;
@@ -1245,11 +1241,17 @@
arizona->pdata.spk_fmt[i]);
}
+ pm_runtime_set_active(arizona->dev);
+ pm_runtime_enable(arizona->dev);
+
/* Set up for interrupts */
ret = arizona_irq_init(arizona);
if (ret != 0)
goto err_reset;
+ pm_runtime_set_autosuspend_delay(arizona->dev, 100);
+ pm_runtime_use_autosuspend(arizona->dev);
+
arizona_request_irq(arizona, ARIZONA_IRQ_CLKGEN_ERR, "CLKGEN error",
arizona_clkgen_err, arizona);
arizona_request_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, "Overclocked",
@@ -1278,10 +1280,6 @@
goto err_irq;
}
-#ifdef CONFIG_PM
- regulator_disable(arizona->dcvdd);
-#endif
-
return 0;
err_irq:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 42c3852..ccccc29 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -271,6 +271,16 @@
To compile this driver as a module, choose M here: the
module will be called hpilo.
+config QCOM_COINCELL
+ tristate "Qualcomm coincell charger support"
+ depends on MFD_SPMI_PMIC || COMPILE_TEST
+ help
+ This driver supports the coincell block found inside of
+ Qualcomm PMICs. The coincell charger provides a means to
+ charge a coincell battery or backup capacitor which is used
+ to maintain PMIC register and RTC state in the absence of
+ external power.
+
config SGI_GRU
tristate "SGI GRU driver"
depends on X86_UV && SMP
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index d056fb7..537d7f3 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -18,6 +18,7 @@
obj-$(CONFIG_TIFM_CORE) += tifm_core.o
obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o
obj-$(CONFIG_PHANTOM) += phantom.o
+obj-$(CONFIG_QCOM_COINCELL) += qcom-coincell.o
obj-$(CONFIG_SENSORS_BH1780) += bh1780gli.o
obj-$(CONFIG_SENSORS_BH1770) += bh1770glc.o
obj-$(CONFIG_SENSORS_APDS990X) += apds990x.o
diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c
index 705b881..d11187d 100644
--- a/drivers/misc/ad525x_dpot-i2c.c
+++ b/drivers/misc/ad525x_dpot-i2c.c
@@ -106,7 +106,6 @@
static struct i2c_driver ad_dpot_i2c_driver = {
.driver = {
.name = "ad_dpot",
- .owner = THIS_MODULE,
},
.probe = ad_dpot_i2c_probe,
.remove = ad_dpot_i2c_remove,
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index 3739ffa..a3e789b 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -1275,7 +1275,6 @@
static struct i2c_driver apds990x_driver = {
.driver = {
.name = "apds990x",
- .owner = THIS_MODULE,
.pm = &apds990x_pm_ops,
},
.probe = apds990x_probe,
diff --git a/drivers/misc/bh1770glc.c b/drivers/misc/bh1770glc.c
index b756381..753d7ec 100644
--- a/drivers/misc/bh1770glc.c
+++ b/drivers/misc/bh1770glc.c
@@ -1396,7 +1396,6 @@
static struct i2c_driver bh1770_driver = {
.driver = {
.name = "bh1770glc",
- .owner = THIS_MODULE,
.pm = &bh1770_pm_ops,
},
.probe = bh1770_probe,
diff --git a/drivers/misc/bmp085-i2c.c b/drivers/misc/bmp085-i2c.c
index a7c1629..f35c218 100644
--- a/drivers/misc/bmp085-i2c.c
+++ b/drivers/misc/bmp085-i2c.c
@@ -66,7 +66,6 @@
static struct i2c_driver bmp085_i2c_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = BMP085_NAME,
},
.id_table = bmp085_id,
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c
index 31f38bc..87cd747 100644
--- a/drivers/misc/cxl/sysfs.c
+++ b/drivers/misc/cxl/sysfs.c
@@ -443,12 +443,7 @@
struct afu_config_record *cr = to_cr(kobj);
struct cxl_afu *afu = to_cxl_afu(container_of(kobj->parent, struct device, kobj));
- u64 i, j, val, size = afu->crs_len;
-
- if (off > size)
- return 0;
- if (off + count > size)
- count = size - off;
+ u64 i, j, val;
for (i = 0; i < count;) {
val = cxl_afu_cr_read64(afu, cr->cr, off & ~0x7);
diff --git a/drivers/misc/ds1682.c b/drivers/misc/ds1682.c
index b909fb3..c711227 100644
--- a/drivers/misc/ds1682.c
+++ b/drivers/misc/ds1682.c
@@ -148,12 +148,6 @@
dev_dbg(&client->dev, "ds1682_eeprom_read(p=%p, off=%lli, c=%zi)\n",
buf, off, count);
- if (off >= DS1682_EEPROM_SIZE)
- return 0;
-
- if (off + count > DS1682_EEPROM_SIZE)
- count = DS1682_EEPROM_SIZE - off;
-
rc = i2c_smbus_read_i2c_block_data(client, DS1682_REG_EEPROM + off,
count, buf);
if (rc < 0)
@@ -171,12 +165,6 @@
dev_dbg(&client->dev, "ds1682_eeprom_write(p=%p, off=%lli, c=%zi)\n",
buf, off, count);
- if (off >= DS1682_EEPROM_SIZE)
- return -ENOSPC;
-
- if (off + count > DS1682_EEPROM_SIZE)
- count = DS1682_EEPROM_SIZE - off;
-
/* Write out to the device */
if (i2c_smbus_write_i2c_block_data(client, DS1682_REG_EEPROM + off,
count, buf) < 0)
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9536852f..04f2e1f 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -96,17 +96,4 @@
If unsure, say N.
-config EEPROM_SUNXI_SID
- tristate "Allwinner sunxi security ID support"
- depends on ARCH_SUNXI && SYSFS
- help
- This is a driver for the 'security ID' available on various Allwinner
- devices.
-
- Due to the potential risks involved with changing e-fuses,
- this driver is read-only.
-
- This driver can also be built as a module. If so, the module
- will be called sunxi_sid.
-
endmenu
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile
index 9507aec..fc1e81d 100644
--- a/drivers/misc/eeprom/Makefile
+++ b/drivers/misc/eeprom/Makefile
@@ -4,5 +4,4 @@
obj-$(CONFIG_EEPROM_MAX6875) += max6875.o
obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o
obj-$(CONFIG_EEPROM_93XX46) += eeprom_93xx46.o
-obj-$(CONFIG_EEPROM_SUNXI_SID) += sunxi_sid.o
obj-$(CONFIG_EEPROM_DIGSY_MTC_CFG) += digsy_mtc_eeprom.o
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 2d3db81..2b254f3 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -438,9 +438,6 @@
{
struct at24_data *at24;
- if (unlikely(off >= attr->size))
- return -EFBIG;
-
at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
return at24_write(at24, buf, off, count);
}
@@ -689,7 +686,6 @@
static struct i2c_driver at24_driver = {
.driver = {
.name = "at24",
- .owner = THIS_MODULE,
},
.probe = at24_probe,
.remove = at24_remove,
diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c
index b432873..7342fd6 100644
--- a/drivers/misc/eeprom/eeprom.c
+++ b/drivers/misc/eeprom/eeprom.c
@@ -88,11 +88,6 @@
struct eeprom_data *data = i2c_get_clientdata(client);
u8 slice;
- if (off > EEPROM_SIZE)
- return 0;
- if (off + count > EEPROM_SIZE)
- count = EEPROM_SIZE - off;
-
/* Only refresh slices which contain requested bytes */
for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++)
eeprom_update_client(client, slice);
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index 9ebeacd..a6bd9e3 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -48,13 +48,6 @@
dev = container_of(kobj, struct device, kobj);
edev = dev_get_drvdata(dev);
- if (unlikely(off >= edev->bin.size))
- return 0;
- if ((off + count) > edev->bin.size)
- count = edev->bin.size - off;
- if (unlikely(!count))
- return count;
-
cmd_addr = OP_READ << edev->addrlen;
if (edev->addrlen == 7) {
@@ -200,13 +193,6 @@
dev = container_of(kobj, struct device, kobj);
edev = dev_get_drvdata(dev);
- if (unlikely(off >= edev->bin.size))
- return -EFBIG;
- if ((off + count) > edev->bin.size)
- count = edev->bin.size - off;
- if (unlikely(!count))
- return count;
-
/* only write even number of bytes on 16-bit devices */
if (edev->addrlen == 6) {
step = 2;
diff --git a/drivers/misc/eeprom/max6875.c b/drivers/misc/eeprom/max6875.c
index 580ff9d..9aa4332 100644
--- a/drivers/misc/eeprom/max6875.c
+++ b/drivers/misc/eeprom/max6875.c
@@ -114,12 +114,6 @@
struct max6875_data *data = i2c_get_clientdata(client);
int slice, max_slice;
- if (off > USER_EEPROM_SIZE)
- return 0;
-
- if (off + count > USER_EEPROM_SIZE)
- count = USER_EEPROM_SIZE - off;
-
/* refresh slices which contain requested bytes */
max_slice = (off + count - 1) >> SLICE_BITS;
for (slice = (off >> SLICE_BITS); slice <= max_slice; slice++)
diff --git a/drivers/misc/eeprom/sunxi_sid.c b/drivers/misc/eeprom/sunxi_sid.c
deleted file mode 100644
index 8385177..0000000
--- a/drivers/misc/eeprom/sunxi_sid.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
- * http://www.linux-sunxi.org
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * This driver exposes the Allwinner security ID, efuses exported in byte-
- * sized chunks.
- */
-
-#include <linux/compiler.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/export.h>
-#include <linux/fs.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/kobject.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/random.h>
-#include <linux/slab.h>
-#include <linux/stat.h>
-#include <linux/sysfs.h>
-#include <linux/types.h>
-
-#define DRV_NAME "sunxi-sid"
-
-struct sunxi_sid_data {
- void __iomem *reg_base;
- unsigned int keysize;
-};
-
-/* We read the entire key, due to a 32 bit read alignment requirement. Since we
- * want to return the requested byte, this results in somewhat slower code and
- * uses 4 times more reads as needed but keeps code simpler. Since the SID is
- * only very rarely probed, this is not really an issue.
- */
-static u8 sunxi_sid_read_byte(const struct sunxi_sid_data *sid_data,
- const unsigned int offset)
-{
- u32 sid_key;
-
- if (offset >= sid_data->keysize)
- return 0;
-
- sid_key = ioread32be(sid_data->reg_base + round_down(offset, 4));
- sid_key >>= (offset % 4) * 8;
-
- return sid_key; /* Only return the last byte */
-}
-
-static ssize_t sid_read(struct file *fd, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
- loff_t pos, size_t size)
-{
- struct platform_device *pdev;
- struct sunxi_sid_data *sid_data;
- int i;
-
- pdev = to_platform_device(kobj_to_dev(kobj));
- sid_data = platform_get_drvdata(pdev);
-
- if (pos < 0 || pos >= sid_data->keysize)
- return 0;
- if (size > sid_data->keysize - pos)
- size = sid_data->keysize - pos;
-
- for (i = 0; i < size; i++)
- buf[i] = sunxi_sid_read_byte(sid_data, pos + i);
-
- return i;
-}
-
-static struct bin_attribute sid_bin_attr = {
- .attr = { .name = "eeprom", .mode = S_IRUGO, },
- .read = sid_read,
-};
-
-static int sunxi_sid_remove(struct platform_device *pdev)
-{
- device_remove_bin_file(&pdev->dev, &sid_bin_attr);
- dev_dbg(&pdev->dev, "driver unloaded\n");
-
- return 0;
-}
-
-static const struct of_device_id sunxi_sid_of_match[] = {
- { .compatible = "allwinner,sun4i-a10-sid", .data = (void *)16},
- { .compatible = "allwinner,sun7i-a20-sid", .data = (void *)512},
- {/* sentinel */},
-};
-MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
-
-static int sunxi_sid_probe(struct platform_device *pdev)
-{
- struct sunxi_sid_data *sid_data;
- struct resource *res;
- const struct of_device_id *of_dev_id;
- u8 *entropy;
- unsigned int i;
-
- sid_data = devm_kzalloc(&pdev->dev, sizeof(struct sunxi_sid_data),
- GFP_KERNEL);
- if (!sid_data)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- sid_data->reg_base = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(sid_data->reg_base))
- return PTR_ERR(sid_data->reg_base);
-
- of_dev_id = of_match_device(sunxi_sid_of_match, &pdev->dev);
- if (!of_dev_id)
- return -ENODEV;
- sid_data->keysize = (int)of_dev_id->data;
-
- platform_set_drvdata(pdev, sid_data);
-
- sid_bin_attr.size = sid_data->keysize;
- if (device_create_bin_file(&pdev->dev, &sid_bin_attr))
- return -ENODEV;
-
- entropy = kzalloc(sizeof(u8) * sid_data->keysize, GFP_KERNEL);
- for (i = 0; i < sid_data->keysize; i++)
- entropy[i] = sunxi_sid_read_byte(sid_data, i);
- add_device_randomness(entropy, sid_data->keysize);
- kfree(entropy);
-
- dev_dbg(&pdev->dev, "loaded\n");
-
- return 0;
-}
-
-static struct platform_driver sunxi_sid_driver = {
- .probe = sunxi_sid_probe,
- .remove = sunxi_sid_remove,
- .driver = {
- .name = DRV_NAME,
- .of_match_table = sunxi_sid_of_match,
- },
-};
-module_platform_driver(sunxi_sid_driver);
-
-MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
-MODULE_DESCRIPTION("Allwinner sunxi security id driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/misc/isl29003.c b/drivers/misc/isl29003.c
index 12c30b4..976df00 100644
--- a/drivers/misc/isl29003.c
+++ b/drivers/misc/isl29003.c
@@ -465,7 +465,6 @@
static struct i2c_driver isl29003_driver = {
.driver = {
.name = ISL29003_DRV_NAME,
- .owner = THIS_MODULE,
.pm = ISL29003_PM_OPS,
},
.probe = isl29003_probe,
diff --git a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
index e3e7f1d..0c3bb7e 100644
--- a/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
+++ b/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
@@ -274,7 +274,6 @@
static struct i2c_driver lis3lv02d_i2c_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
.pm = &lis3_pm_ops,
.of_match_table = of_match_ptr(lis3lv02d_i2c_dt_ids),
},
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
index 518914a..01447ca 100644
--- a/drivers/misc/mei/Makefile
+++ b/drivers/misc/mei/Makefile
@@ -11,7 +11,7 @@
mei-objs += amthif.o
mei-objs += wd.o
mei-objs += bus.o
-mei-objs += nfc.o
+mei-objs += bus-fixup.o
mei-$(CONFIG_DEBUG_FS) += debugfs.o
obj-$(CONFIG_INTEL_MEI_ME) += mei-me.o
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
new file mode 100644
index 0000000..3e536ca
--- /dev/null
+++ b/drivers/misc/mei/bus-fixup.c
@@ -0,0 +1,306 @@
+/*
+ *
+ * Intel Management Engine Interface (Intel MEI) Linux driver
+ * Copyright (c) 2003-2013, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/uuid.h>
+
+#include <linux/mei_cl_bus.h>
+
+#include "mei_dev.h"
+#include "client.h"
+
+#define MEI_UUID_NFC_INFO UUID_LE(0xd2de1625, 0x382d, 0x417d, \
+ 0x48, 0xa4, 0xef, 0xab, 0xba, 0x8a, 0x12, 0x06)
+
+static const uuid_le mei_nfc_info_guid = MEI_UUID_NFC_INFO;
+
+#define MEI_UUID_NFC_HCI UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, \
+ 0x94, 0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c)
+
+#define MEI_UUID_ANY NULL_UUID_LE
+
+/**
+ * number_of_connections - determine whether an client be on the bus
+ * according number of connections
+ * We support only clients:
+ * 1. with single connection
+ * 2. and fixed clients (max_number_of_connections == 0)
+ *
+ * @cldev: me clients device
+ */
+static void number_of_connections(struct mei_cl_device *cldev)
+{
+ dev_dbg(&cldev->dev, "running hook %s on %pUl\n",
+ __func__, mei_me_cl_uuid(cldev->me_cl));
+
+ if (cldev->me_cl->props.max_number_of_connections > 1)
+ cldev->do_match = 0;
+}
+
+/**
+ * blacklist - blacklist a client from the bus
+ *
+ * @cldev: me clients device
+ */
+static void blacklist(struct mei_cl_device *cldev)
+{
+ dev_dbg(&cldev->dev, "running hook %s on %pUl\n",
+ __func__, mei_me_cl_uuid(cldev->me_cl));
+ cldev->do_match = 0;
+}
+
+struct mei_nfc_cmd {
+ u8 command;
+ u8 status;
+ u16 req_id;
+ u32 reserved;
+ u16 data_size;
+ u8 sub_command;
+ u8 data[];
+} __packed;
+
+struct mei_nfc_reply {
+ u8 command;
+ u8 status;
+ u16 req_id;
+ u32 reserved;
+ u16 data_size;
+ u8 sub_command;
+ u8 reply_status;
+ u8 data[];
+} __packed;
+
+struct mei_nfc_if_version {
+ u8 radio_version_sw[3];
+ u8 reserved[3];
+ u8 radio_version_hw[3];
+ u8 i2c_addr;
+ u8 fw_ivn;
+ u8 vendor_id;
+ u8 radio_type;
+} __packed;
+
+
+#define MEI_NFC_CMD_MAINTENANCE 0x00
+#define MEI_NFC_SUBCMD_IF_VERSION 0x01
+
+/* Vendors */
+#define MEI_NFC_VENDOR_INSIDE 0x00
+#define MEI_NFC_VENDOR_NXP 0x01
+
+/* Radio types */
+#define MEI_NFC_VENDOR_INSIDE_UREAD 0x00
+#define MEI_NFC_VENDOR_NXP_PN544 0x01
+
+/**
+ * mei_nfc_if_version - get NFC interface version
+ *
+ * @cl: host client (nfc info)
+ * @ver: NFC interface version to be filled in
+ *
+ * Return: 0 on success; < 0 otherwise
+ */
+static int mei_nfc_if_version(struct mei_cl *cl,
+ struct mei_nfc_if_version *ver)
+{
+ struct mei_device *bus;
+ struct mei_nfc_cmd cmd = {
+ .command = MEI_NFC_CMD_MAINTENANCE,
+ .data_size = 1,
+ .sub_command = MEI_NFC_SUBCMD_IF_VERSION,
+ };
+ struct mei_nfc_reply *reply = NULL;
+ size_t if_version_length;
+ int bytes_recv, ret;
+
+ bus = cl->dev;
+
+ WARN_ON(mutex_is_locked(&bus->device_lock));
+
+ ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd), 1);
+ if (ret < 0) {
+ dev_err(bus->dev, "Could not send IF version cmd\n");
+ return ret;
+ }
+
+ /* to be sure on the stack we alloc memory */
+ if_version_length = sizeof(struct mei_nfc_reply) +
+ sizeof(struct mei_nfc_if_version);
+
+ reply = kzalloc(if_version_length, GFP_KERNEL);
+ if (!reply)
+ return -ENOMEM;
+
+ ret = 0;
+ bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
+ if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
+ dev_err(bus->dev, "Could not read IF version\n");
+ ret = -EIO;
+ goto err;
+ }
+
+ memcpy(ver, reply->data, sizeof(struct mei_nfc_if_version));
+
+ dev_info(bus->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
+ ver->fw_ivn, ver->vendor_id, ver->radio_type);
+
+err:
+ kfree(reply);
+ return ret;
+}
+
+/**
+ * mei_nfc_radio_name - derive nfc radio name from the interface version
+ *
+ * @ver: NFC radio version
+ *
+ * Return: radio name string
+ */
+static const char *mei_nfc_radio_name(struct mei_nfc_if_version *ver)
+{
+
+ if (ver->vendor_id == MEI_NFC_VENDOR_INSIDE) {
+ if (ver->radio_type == MEI_NFC_VENDOR_INSIDE_UREAD)
+ return "microread";
+ }
+
+ if (ver->vendor_id == MEI_NFC_VENDOR_NXP) {
+ if (ver->radio_type == MEI_NFC_VENDOR_NXP_PN544)
+ return "pn544";
+ }
+
+ return NULL;
+}
+
+/**
+ * mei_nfc - The nfc fixup function. The function retrieves nfc radio
+ * name and set is as device attribute so we can load
+ * the proper device driver for it
+ *
+ * @cldev: me client device (nfc)
+ */
+static void mei_nfc(struct mei_cl_device *cldev)
+{
+ struct mei_device *bus;
+ struct mei_cl *cl;
+ struct mei_me_client *me_cl = NULL;
+ struct mei_nfc_if_version ver;
+ const char *radio_name = NULL;
+ int ret;
+
+ bus = cldev->bus;
+
+ dev_dbg(bus->dev, "running hook %s: %pUl match=%d\n",
+ __func__, mei_me_cl_uuid(cldev->me_cl), cldev->do_match);
+
+ mutex_lock(&bus->device_lock);
+ /* we need to connect to INFO GUID */
+ cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY);
+ if (IS_ERR(cl)) {
+ ret = PTR_ERR(cl);
+ cl = NULL;
+ dev_err(bus->dev, "nfc hook alloc failed %d\n", ret);
+ goto out;
+ }
+
+ me_cl = mei_me_cl_by_uuid(bus, &mei_nfc_info_guid);
+ if (!me_cl) {
+ ret = -ENOTTY;
+ dev_err(bus->dev, "Cannot find nfc info %d\n", ret);
+ goto out;
+ }
+
+ ret = mei_cl_connect(cl, me_cl, NULL);
+ if (ret < 0) {
+ dev_err(&cldev->dev, "Can't connect to the NFC INFO ME ret = %d\n",
+ ret);
+ goto out;
+ }
+
+ mutex_unlock(&bus->device_lock);
+
+ ret = mei_nfc_if_version(cl, &ver);
+ if (ret)
+ goto disconnect;
+
+ radio_name = mei_nfc_radio_name(&ver);
+
+ if (!radio_name) {
+ ret = -ENOENT;
+ dev_err(&cldev->dev, "Can't get the NFC interface version ret = %d\n",
+ ret);
+ goto disconnect;
+ }
+
+ dev_dbg(bus->dev, "nfc radio %s\n", radio_name);
+ strlcpy(cldev->name, radio_name, sizeof(cldev->name));
+
+disconnect:
+ mutex_lock(&bus->device_lock);
+ if (mei_cl_disconnect(cl) < 0)
+ dev_err(bus->dev, "Can't disconnect the NFC INFO ME\n");
+
+ mei_cl_flush_queues(cl, NULL);
+
+out:
+ mei_cl_unlink(cl);
+ mutex_unlock(&bus->device_lock);
+ mei_me_cl_put(me_cl);
+ kfree(cl);
+
+ if (ret)
+ cldev->do_match = 0;
+
+ dev_dbg(bus->dev, "end of fixup match = %d\n", cldev->do_match);
+}
+
+#define MEI_FIXUP(_uuid, _hook) { _uuid, _hook }
+
+static struct mei_fixup {
+
+ const uuid_le uuid;
+ void (*hook)(struct mei_cl_device *cldev);
+} mei_fixups[] = {
+ MEI_FIXUP(MEI_UUID_ANY, number_of_connections),
+ MEI_FIXUP(MEI_UUID_NFC_INFO, blacklist),
+ MEI_FIXUP(MEI_UUID_NFC_HCI, mei_nfc),
+};
+
+/**
+ * mei_cl_dev_fixup - run fixup handlers
+ *
+ * @cldev: me client device
+ */
+void mei_cl_dev_fixup(struct mei_cl_device *cldev)
+{
+ struct mei_fixup *f;
+ const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mei_fixups); i++) {
+
+ f = &mei_fixups[i];
+ if (uuid_le_cmp(f->uuid, MEI_UUID_ANY) == 0 ||
+ uuid_le_cmp(f->uuid, *uuid) == 0)
+ f->hook(cldev);
+ }
+}
+
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 458aa5a..eef1c6b 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -30,276 +30,29 @@
#define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
#define to_mei_cl_device(d) container_of(d, struct mei_cl_device, dev)
-static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
-{
- struct mei_cl_device *device = to_mei_cl_device(dev);
- struct mei_cl_driver *driver = to_mei_cl_driver(drv);
- const struct mei_cl_device_id *id;
- const uuid_le *uuid;
- const char *name;
-
- if (!device)
- return 0;
-
- uuid = mei_me_cl_uuid(device->me_cl);
- name = device->name;
-
- if (!driver || !driver->id_table)
- return 0;
-
- id = driver->id_table;
-
- while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
-
- if (!uuid_le_cmp(*uuid, id->uuid)) {
- if (id->name[0]) {
- if (!strncmp(name, id->name, sizeof(id->name)))
- return 1;
- } else {
- return 1;
- }
- }
-
- id++;
- }
-
- return 0;
-}
-
-static int mei_cl_device_probe(struct device *dev)
-{
- struct mei_cl_device *device = to_mei_cl_device(dev);
- struct mei_cl_driver *driver;
- struct mei_cl_device_id id;
-
- if (!device)
- return 0;
-
- driver = to_mei_cl_driver(dev->driver);
- if (!driver || !driver->probe)
- return -ENODEV;
-
- dev_dbg(dev, "Device probe\n");
-
- strlcpy(id.name, device->name, sizeof(id.name));
-
- return driver->probe(device, &id);
-}
-
-static int mei_cl_device_remove(struct device *dev)
-{
- struct mei_cl_device *device = to_mei_cl_device(dev);
- struct mei_cl_driver *driver;
-
- if (!device || !dev->driver)
- return 0;
-
- if (device->event_cb) {
- device->event_cb = NULL;
- cancel_work_sync(&device->event_work);
- }
-
- driver = to_mei_cl_driver(dev->driver);
- if (!driver->remove) {
- dev->driver = NULL;
-
- return 0;
- }
-
- return driver->remove(device);
-}
-
-static ssize_t name_show(struct device *dev, struct device_attribute *a,
- char *buf)
-{
- struct mei_cl_device *device = to_mei_cl_device(dev);
- size_t len;
-
- len = snprintf(buf, PAGE_SIZE, "%s", device->name);
-
- return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
-}
-static DEVICE_ATTR_RO(name);
-
-static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
- char *buf)
-{
- struct mei_cl_device *device = to_mei_cl_device(dev);
- const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
- size_t len;
-
- len = snprintf(buf, PAGE_SIZE, "%pUl", uuid);
-
- return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
-}
-static DEVICE_ATTR_RO(uuid);
-
-static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
- char *buf)
-{
- struct mei_cl_device *device = to_mei_cl_device(dev);
- const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
- size_t len;
-
- len = snprintf(buf, PAGE_SIZE, "mei:%s:" MEI_CL_UUID_FMT ":",
- device->name, MEI_CL_UUID_ARGS(uuid->b));
-
- return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
-}
-static DEVICE_ATTR_RO(modalias);
-
-static struct attribute *mei_cl_dev_attrs[] = {
- &dev_attr_name.attr,
- &dev_attr_uuid.attr,
- &dev_attr_modalias.attr,
- NULL,
-};
-ATTRIBUTE_GROUPS(mei_cl_dev);
-
-static int mei_cl_uevent(struct device *dev, struct kobj_uevent_env *env)
-{
- struct mei_cl_device *device = to_mei_cl_device(dev);
- const uuid_le *uuid = mei_me_cl_uuid(device->me_cl);
-
- if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
- return -ENOMEM;
-
- if (add_uevent_var(env, "MEI_CL_NAME=%s", device->name))
- return -ENOMEM;
-
- if (add_uevent_var(env, "MODALIAS=mei:%s:" MEI_CL_UUID_FMT ":",
- device->name, MEI_CL_UUID_ARGS(uuid->b)))
- return -ENOMEM;
-
- return 0;
-}
-
-static struct bus_type mei_cl_bus_type = {
- .name = "mei",
- .dev_groups = mei_cl_dev_groups,
- .match = mei_cl_device_match,
- .probe = mei_cl_device_probe,
- .remove = mei_cl_device_remove,
- .uevent = mei_cl_uevent,
-};
-
-static void mei_cl_dev_release(struct device *dev)
-{
- struct mei_cl_device *device = to_mei_cl_device(dev);
-
- if (!device)
- return;
-
- mei_me_cl_put(device->me_cl);
- kfree(device);
-}
-
-static struct device_type mei_cl_device_type = {
- .release = mei_cl_dev_release,
-};
-
-struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev,
- uuid_le uuid)
-{
- struct mei_cl *cl;
-
- list_for_each_entry(cl, &dev->device_list, device_link) {
- if (cl->device && cl->device->me_cl &&
- !uuid_le_cmp(uuid, *mei_me_cl_uuid(cl->device->me_cl)))
- return cl;
- }
-
- return NULL;
-}
-
-struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
- struct mei_me_client *me_cl,
- struct mei_cl *cl,
- char *name)
-{
- struct mei_cl_device *device;
- int status;
-
- device = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
- if (!device)
- return NULL;
-
- device->me_cl = mei_me_cl_get(me_cl);
- if (!device->me_cl) {
- kfree(device);
- return NULL;
- }
-
- device->cl = cl;
- device->dev.parent = dev->dev;
- device->dev.bus = &mei_cl_bus_type;
- device->dev.type = &mei_cl_device_type;
-
- strlcpy(device->name, name, sizeof(device->name));
-
- dev_set_name(&device->dev, "mei:%s:%pUl", name, mei_me_cl_uuid(me_cl));
-
- status = device_register(&device->dev);
- if (status) {
- dev_err(dev->dev, "Failed to register MEI device\n");
- mei_me_cl_put(device->me_cl);
- kfree(device);
- return NULL;
- }
-
- cl->device = device;
-
- dev_dbg(&device->dev, "client %s registered\n", name);
-
- return device;
-}
-EXPORT_SYMBOL_GPL(mei_cl_add_device);
-
-void mei_cl_remove_device(struct mei_cl_device *device)
-{
- device_unregister(&device->dev);
-}
-EXPORT_SYMBOL_GPL(mei_cl_remove_device);
-
-int __mei_cl_driver_register(struct mei_cl_driver *driver, struct module *owner)
-{
- int err;
-
- driver->driver.name = driver->name;
- driver->driver.owner = owner;
- driver->driver.bus = &mei_cl_bus_type;
-
- err = driver_register(&driver->driver);
- if (err)
- return err;
-
- pr_debug("mei: driver [%s] registered\n", driver->driver.name);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(__mei_cl_driver_register);
-
-void mei_cl_driver_unregister(struct mei_cl_driver *driver)
-{
- driver_unregister(&driver->driver);
-
- pr_debug("mei: driver [%s] unregistered\n", driver->driver.name);
-}
-EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
-
+/**
+ * __mei_cl_send - internal client send (write)
+ *
+ * @cl: host client
+ * @buf: buffer to send
+ * @length: buffer length
+ * @blocking: wait for write completion
+ *
+ * Return: written size bytes or < 0 on error
+ */
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
bool blocking)
{
- struct mei_device *dev;
+ struct mei_device *bus;
struct mei_cl_cb *cb = NULL;
ssize_t rets;
if (WARN_ON(!cl || !cl->dev))
return -ENODEV;
- dev = cl->dev;
+ bus = cl->dev;
- mutex_lock(&dev->device_lock);
+ mutex_lock(&bus->device_lock);
if (!mei_cl_is_connected(cl)) {
rets = -ENODEV;
goto out;
@@ -327,16 +80,25 @@
rets = mei_cl_write(cl, cb, blocking);
out:
- mutex_unlock(&dev->device_lock);
+ mutex_unlock(&bus->device_lock);
if (rets < 0)
mei_io_cb_free(cb);
return rets;
}
+/**
+ * __mei_cl_recv - internal client receive (read)
+ *
+ * @cl: host client
+ * @buf: buffer to send
+ * @length: buffer length
+ *
+ * Return: read size in bytes of < 0 on error
+ */
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length)
{
- struct mei_device *dev;
+ struct mei_device *bus;
struct mei_cl_cb *cb;
size_t r_length;
ssize_t rets;
@@ -344,9 +106,9 @@
if (WARN_ON(!cl || !cl->dev))
return -ENODEV;
- dev = cl->dev;
+ bus = cl->dev;
- mutex_lock(&dev->device_lock);
+ mutex_lock(&bus->device_lock);
cb = mei_cl_read_cb(cl, NULL);
if (cb)
@@ -356,9 +118,10 @@
if (rets && rets != -EBUSY)
goto out;
+ /* wait on event only if there is no other waiter */
if (list_empty(&cl->rd_completed) && !waitqueue_active(&cl->rx_wait)) {
- mutex_unlock(&dev->device_lock);
+ mutex_unlock(&bus->device_lock);
if (wait_event_interruptible(cl->rx_wait,
(!list_empty(&cl->rd_completed)) ||
@@ -369,7 +132,7 @@
return -ERESTARTSYS;
}
- mutex_lock(&dev->device_lock);
+ mutex_lock(&bus->device_lock);
if (!mei_cl_is_connected(cl)) {
rets = -EBUSY;
@@ -396,14 +159,23 @@
free:
mei_io_cb_free(cb);
out:
- mutex_unlock(&dev->device_lock);
+ mutex_unlock(&bus->device_lock);
return rets;
}
-ssize_t mei_cl_send(struct mei_cl_device *device, u8 *buf, size_t length)
+/**
+ * mei_cl_send - me device send (write)
+ *
+ * @cldev: me client device
+ * @buf: buffer to send
+ * @length: buffer length
+ *
+ * Return: written size in bytes or < 0 on error
+ */
+ssize_t mei_cl_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
{
- struct mei_cl *cl = device->cl;
+ struct mei_cl *cl = cldev->cl;
if (cl == NULL)
return -ENODEV;
@@ -412,9 +184,18 @@
}
EXPORT_SYMBOL_GPL(mei_cl_send);
-ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length)
+/**
+ * mei_cl_recv - client receive (read)
+ *
+ * @cldev: me client device
+ * @buf: buffer to send
+ * @length: buffer length
+ *
+ * Return: read size in bytes of < 0 on error
+ */
+ssize_t mei_cl_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
{
- struct mei_cl *cl = device->cl;
+ struct mei_cl *cl = cldev->cl;
if (cl == NULL)
return -ENODEV;
@@ -423,135 +204,698 @@
}
EXPORT_SYMBOL_GPL(mei_cl_recv);
+/**
+ * mei_bus_event_work - dispatch rx event for a bus device
+ * and schedule new work
+ *
+ * @work: work
+ */
static void mei_bus_event_work(struct work_struct *work)
{
- struct mei_cl_device *device;
+ struct mei_cl_device *cldev;
- device = container_of(work, struct mei_cl_device, event_work);
+ cldev = container_of(work, struct mei_cl_device, event_work);
- if (device->event_cb)
- device->event_cb(device, device->events, device->event_context);
+ if (cldev->event_cb)
+ cldev->event_cb(cldev, cldev->events, cldev->event_context);
- device->events = 0;
+ cldev->events = 0;
/* Prepare for the next read */
- mei_cl_read_start(device->cl, 0, NULL);
+ if (cldev->events_mask & BIT(MEI_CL_EVENT_RX))
+ mei_cl_read_start(cldev->cl, 0, NULL);
}
-int mei_cl_register_event_cb(struct mei_cl_device *device,
+/**
+ * mei_cl_bus_notify_event - schedule notify cb on bus client
+ *
+ * @cl: host client
+ */
+void mei_cl_bus_notify_event(struct mei_cl *cl)
+{
+ struct mei_cl_device *cldev = cl->cldev;
+
+ if (!cldev || !cldev->event_cb)
+ return;
+
+ if (!(cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)))
+ return;
+
+ if (!cl->notify_ev)
+ return;
+
+ set_bit(MEI_CL_EVENT_NOTIF, &cldev->events);
+
+ schedule_work(&cldev->event_work);
+
+ cl->notify_ev = false;
+}
+
+/**
+ * mei_cl_bus_rx_event - schedule rx evenet
+ *
+ * @cl: host client
+ */
+void mei_cl_bus_rx_event(struct mei_cl *cl)
+{
+ struct mei_cl_device *cldev = cl->cldev;
+
+ if (!cldev || !cldev->event_cb)
+ return;
+
+ if (!(cldev->events_mask & BIT(MEI_CL_EVENT_RX)))
+ return;
+
+ set_bit(MEI_CL_EVENT_RX, &cldev->events);
+
+ schedule_work(&cldev->event_work);
+}
+
+/**
+ * mei_cl_register_event_cb - register event callback
+ *
+ * @cldev: me client devices
+ * @event_cb: callback function
+ * @events_mask: requested events bitmask
+ * @context: driver context data
+ *
+ * Return: 0 on success
+ * -EALREADY if an callback is already registered
+ * <0 on other errors
+ */
+int mei_cl_register_event_cb(struct mei_cl_device *cldev,
+ unsigned long events_mask,
mei_cl_event_cb_t event_cb, void *context)
{
- if (device->event_cb)
+ int ret;
+
+ if (cldev->event_cb)
return -EALREADY;
- device->events = 0;
- device->event_cb = event_cb;
- device->event_context = context;
- INIT_WORK(&device->event_work, mei_bus_event_work);
+ cldev->events = 0;
+ cldev->events_mask = events_mask;
+ cldev->event_cb = event_cb;
+ cldev->event_context = context;
+ INIT_WORK(&cldev->event_work, mei_bus_event_work);
- mei_cl_read_start(device->cl, 0, NULL);
+ if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
+ ret = mei_cl_read_start(cldev->cl, 0, NULL);
+ if (ret && ret != -EBUSY)
+ return ret;
+ }
+
+ if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) {
+ mutex_lock(&cldev->cl->dev->device_lock);
+ ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0);
+ mutex_unlock(&cldev->cl->dev->device_lock);
+ if (ret)
+ return ret;
+ }
return 0;
}
EXPORT_SYMBOL_GPL(mei_cl_register_event_cb);
-void *mei_cl_get_drvdata(const struct mei_cl_device *device)
+/**
+ * mei_cl_get_drvdata - driver data getter
+ *
+ * @cldev: mei client device
+ *
+ * Return: driver private data
+ */
+void *mei_cl_get_drvdata(const struct mei_cl_device *cldev)
{
- return dev_get_drvdata(&device->dev);
+ return dev_get_drvdata(&cldev->dev);
}
EXPORT_SYMBOL_GPL(mei_cl_get_drvdata);
-void mei_cl_set_drvdata(struct mei_cl_device *device, void *data)
+/**
+ * mei_cl_set_drvdata - driver data setter
+ *
+ * @cldev: mei client device
+ * @data: data to store
+ */
+void mei_cl_set_drvdata(struct mei_cl_device *cldev, void *data)
{
- dev_set_drvdata(&device->dev, data);
+ dev_set_drvdata(&cldev->dev, data);
}
EXPORT_SYMBOL_GPL(mei_cl_set_drvdata);
-int mei_cl_enable_device(struct mei_cl_device *device)
+/**
+ * mei_cl_enable_device - enable me client device
+ * create connection with me client
+ *
+ * @cldev: me client device
+ *
+ * Return: 0 on success and < 0 on error
+ */
+int mei_cl_enable_device(struct mei_cl_device *cldev)
{
- int err;
- struct mei_device *dev;
- struct mei_cl *cl = device->cl;
+ struct mei_device *bus = cldev->bus;
+ struct mei_cl *cl;
+ int ret;
- if (cl == NULL)
- return -ENODEV;
+ cl = cldev->cl;
- dev = cl->dev;
+ if (!cl) {
+ mutex_lock(&bus->device_lock);
+ cl = mei_cl_alloc_linked(bus, MEI_HOST_CLIENT_ID_ANY);
+ mutex_unlock(&bus->device_lock);
+ if (IS_ERR(cl))
+ return PTR_ERR(cl);
+ /* update pointers */
+ cldev->cl = cl;
+ cl->cldev = cldev;
+ }
- mutex_lock(&dev->device_lock);
-
+ mutex_lock(&bus->device_lock);
if (mei_cl_is_connected(cl)) {
- mutex_unlock(&dev->device_lock);
- dev_warn(dev->dev, "Already connected");
- return -EBUSY;
+ ret = 0;
+ goto out;
}
- err = mei_cl_connect(cl, device->me_cl, NULL);
- if (err < 0) {
- mutex_unlock(&dev->device_lock);
- dev_err(dev->dev, "Could not connect to the ME client");
-
- return err;
+ if (!mei_me_cl_is_active(cldev->me_cl)) {
+ dev_err(&cldev->dev, "me client is not active\n");
+ ret = -ENOTTY;
+ goto out;
}
- mutex_unlock(&dev->device_lock);
+ ret = mei_cl_connect(cl, cldev->me_cl, NULL);
+ if (ret < 0)
+ dev_err(&cldev->dev, "cannot connect\n");
- if (device->event_cb)
- mei_cl_read_start(device->cl, 0, NULL);
+out:
+ mutex_unlock(&bus->device_lock);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(mei_cl_enable_device);
-int mei_cl_disable_device(struct mei_cl_device *device)
+/**
+ * mei_cl_disable_device - disable me client device
+ * disconnect form the me client
+ *
+ * @cldev: me client device
+ *
+ * Return: 0 on success and < 0 on error
+ */
+int mei_cl_disable_device(struct mei_cl_device *cldev)
{
+ struct mei_device *bus;
+ struct mei_cl *cl;
int err;
- struct mei_device *dev;
- struct mei_cl *cl = device->cl;
- if (cl == NULL)
+ if (!cldev || !cldev->cl)
return -ENODEV;
- dev = cl->dev;
+ cl = cldev->cl;
- device->event_cb = NULL;
+ bus = cldev->bus;
- mutex_lock(&dev->device_lock);
+ cldev->event_cb = NULL;
+
+ mutex_lock(&bus->device_lock);
if (!mei_cl_is_connected(cl)) {
- dev_err(dev->dev, "Already disconnected");
+ dev_err(bus->dev, "Already disconnected");
err = 0;
goto out;
}
err = mei_cl_disconnect(cl);
- if (err < 0) {
- dev_err(dev->dev, "Could not disconnect from the ME client");
- goto out;
- }
-
- /* Flush queues and remove any pending read */
- mei_cl_flush_queues(cl, NULL);
+ if (err < 0)
+ dev_err(bus->dev, "Could not disconnect from the ME client");
out:
- mutex_unlock(&dev->device_lock);
- return err;
+ /* Flush queues and remove any pending read */
+ mei_cl_flush_queues(cl, NULL);
+ mei_cl_unlink(cl);
+ kfree(cl);
+ cldev->cl = NULL;
+
+ mutex_unlock(&bus->device_lock);
+ return err;
}
EXPORT_SYMBOL_GPL(mei_cl_disable_device);
-void mei_cl_bus_rx_event(struct mei_cl *cl)
+/**
+ * mei_cl_device_find - find matching entry in the driver id table
+ *
+ * @cldev: me client device
+ * @cldrv: me client driver
+ *
+ * Return: id on success; NULL if no id is matching
+ */
+static const
+struct mei_cl_device_id *mei_cl_device_find(struct mei_cl_device *cldev,
+ struct mei_cl_driver *cldrv)
{
- struct mei_cl_device *device = cl->device;
+ const struct mei_cl_device_id *id;
+ const uuid_le *uuid;
- if (!device || !device->event_cb)
+ uuid = mei_me_cl_uuid(cldev->me_cl);
+
+ id = cldrv->id_table;
+ while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
+ if (!uuid_le_cmp(*uuid, id->uuid)) {
+
+ if (!cldev->name[0])
+ return id;
+
+ if (!strncmp(cldev->name, id->name, sizeof(id->name)))
+ return id;
+ }
+
+ id++;
+ }
+
+ return NULL;
+}
+
+/**
+ * mei_cl_device_match - device match function
+ *
+ * @dev: device
+ * @drv: driver
+ *
+ * Return: 1 if matching device was found 0 otherwise
+ */
+static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ struct mei_cl_driver *cldrv = to_mei_cl_driver(drv);
+ const struct mei_cl_device_id *found_id;
+
+ if (!cldev)
+ return 0;
+
+ if (!cldev->do_match)
+ return 0;
+
+ if (!cldrv || !cldrv->id_table)
+ return 0;
+
+ found_id = mei_cl_device_find(cldev, cldrv);
+ if (found_id)
+ return 1;
+
+ return 0;
+}
+
+/**
+ * mei_cl_device_probe - bus probe function
+ *
+ * @dev: device
+ *
+ * Return: 0 on success; < 0 otherwise
+ */
+static int mei_cl_device_probe(struct device *dev)
+{
+ struct mei_cl_device *cldev;
+ struct mei_cl_driver *cldrv;
+ const struct mei_cl_device_id *id;
+
+ cldev = to_mei_cl_device(dev);
+ cldrv = to_mei_cl_driver(dev->driver);
+
+ if (!cldev)
+ return 0;
+
+ if (!cldrv || !cldrv->probe)
+ return -ENODEV;
+
+ id = mei_cl_device_find(cldev, cldrv);
+ if (!id)
+ return -ENODEV;
+
+ __module_get(THIS_MODULE);
+
+ return cldrv->probe(cldev, id);
+}
+
+/**
+ * mei_cl_device_remove - remove device from the bus
+ *
+ * @dev: device
+ *
+ * Return: 0 on success; < 0 otherwise
+ */
+static int mei_cl_device_remove(struct device *dev)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ struct mei_cl_driver *cldrv;
+ int ret = 0;
+
+ if (!cldev || !dev->driver)
+ return 0;
+
+ if (cldev->event_cb) {
+ cldev->event_cb = NULL;
+ cancel_work_sync(&cldev->event_work);
+ }
+
+ cldrv = to_mei_cl_driver(dev->driver);
+ if (cldrv->remove)
+ ret = cldrv->remove(cldev);
+
+ module_put(THIS_MODULE);
+ dev->driver = NULL;
+ return ret;
+
+}
+
+static ssize_t name_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ size_t len;
+
+ len = snprintf(buf, PAGE_SIZE, "%s", cldev->name);
+
+ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+static DEVICE_ATTR_RO(name);
+
+static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+ size_t len;
+
+ len = snprintf(buf, PAGE_SIZE, "%pUl", uuid);
+
+ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+static DEVICE_ATTR_RO(uuid);
+
+static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
+ char *buf)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+ size_t len;
+
+ len = snprintf(buf, PAGE_SIZE, "mei:%s:" MEI_CL_UUID_FMT ":",
+ cldev->name, MEI_CL_UUID_ARGS(uuid->b));
+
+ return (len >= PAGE_SIZE) ? (PAGE_SIZE - 1) : len;
+}
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *mei_cl_dev_attrs[] = {
+ &dev_attr_name.attr,
+ &dev_attr_uuid.attr,
+ &dev_attr_modalias.attr,
+ NULL,
+};
+ATTRIBUTE_GROUPS(mei_cl_dev);
+
+/**
+ * mei_cl_device_uevent - me client bus uevent handler
+ *
+ * @dev: device
+ * @env: uevent kobject
+ *
+ * Return: 0 on success -ENOMEM on when add_uevent_var fails
+ */
+static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+ const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
+
+ if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
+ return -ENOMEM;
+
+ if (add_uevent_var(env, "MODALIAS=mei:%s:" MEI_CL_UUID_FMT ":",
+ cldev->name, MEI_CL_UUID_ARGS(uuid->b)))
+ return -ENOMEM;
+
+ return 0;
+}
+
+static struct bus_type mei_cl_bus_type = {
+ .name = "mei",
+ .dev_groups = mei_cl_dev_groups,
+ .match = mei_cl_device_match,
+ .probe = mei_cl_device_probe,
+ .remove = mei_cl_device_remove,
+ .uevent = mei_cl_device_uevent,
+};
+
+static struct mei_device *mei_dev_bus_get(struct mei_device *bus)
+{
+ if (bus)
+ get_device(bus->dev);
+
+ return bus;
+}
+
+static void mei_dev_bus_put(struct mei_device *bus)
+{
+ if (bus)
+ put_device(bus->dev);
+}
+
+static void mei_cl_dev_release(struct device *dev)
+{
+ struct mei_cl_device *cldev = to_mei_cl_device(dev);
+
+ if (!cldev)
return;
- set_bit(MEI_CL_EVENT_RX, &device->events);
-
- schedule_work(&device->event_work);
+ mei_me_cl_put(cldev->me_cl);
+ mei_dev_bus_put(cldev->bus);
+ kfree(cldev);
}
+static struct device_type mei_cl_device_type = {
+ .release = mei_cl_dev_release,
+};
+
+/**
+ * mei_cl_dev_alloc - initialize and allocate mei client device
+ *
+ * @bus: mei device
+ * @me_cl: me client
+ *
+ * Return: allocated device structur or NULL on allocation failure
+ */
+static struct mei_cl_device *mei_cl_dev_alloc(struct mei_device *bus,
+ struct mei_me_client *me_cl)
+{
+ struct mei_cl_device *cldev;
+
+ cldev = kzalloc(sizeof(struct mei_cl_device), GFP_KERNEL);
+ if (!cldev)
+ return NULL;
+
+ device_initialize(&cldev->dev);
+ cldev->dev.parent = bus->dev;
+ cldev->dev.bus = &mei_cl_bus_type;
+ cldev->dev.type = &mei_cl_device_type;
+ cldev->bus = mei_dev_bus_get(bus);
+ cldev->me_cl = mei_me_cl_get(me_cl);
+ cldev->is_added = 0;
+ INIT_LIST_HEAD(&cldev->bus_list);
+
+ return cldev;
+}
+
+/**
+ * mei_cl_dev_setup - setup me client device
+ * run fix up routines and set the device name
+ *
+ * @bus: mei device
+ * @cldev: me client device
+ *
+ * Return: true if the device is eligible for enumeration
+ */
+static bool mei_cl_dev_setup(struct mei_device *bus,
+ struct mei_cl_device *cldev)
+{
+ cldev->do_match = 1;
+ mei_cl_dev_fixup(cldev);
+
+ if (cldev->do_match)
+ dev_set_name(&cldev->dev, "mei:%s:%pUl",
+ cldev->name, mei_me_cl_uuid(cldev->me_cl));
+
+ return cldev->do_match == 1;
+}
+
+/**
+ * mei_cl_bus_dev_add - add me client devices
+ *
+ * @cldev: me client device
+ *
+ * Return: 0 on success; < 0 on failre
+ */
+static int mei_cl_bus_dev_add(struct mei_cl_device *cldev)
+{
+ int ret;
+
+ dev_dbg(cldev->bus->dev, "adding %pUL\n", mei_me_cl_uuid(cldev->me_cl));
+ ret = device_add(&cldev->dev);
+ if (!ret)
+ cldev->is_added = 1;
+
+ return ret;
+}
+
+/**
+ * mei_cl_bus_dev_stop - stop the driver
+ *
+ * @cldev: me client device
+ */
+static void mei_cl_bus_dev_stop(struct mei_cl_device *cldev)
+{
+ if (cldev->is_added)
+ device_release_driver(&cldev->dev);
+}
+
+/**
+ * mei_cl_bus_dev_destroy - destroy me client devices object
+ *
+ * @cldev: me client device
+ */
+static void mei_cl_bus_dev_destroy(struct mei_cl_device *cldev)
+{
+ if (!cldev->is_added)
+ return;
+
+ device_del(&cldev->dev);
+
+ mutex_lock(&cldev->bus->cl_bus_lock);
+ list_del_init(&cldev->bus_list);
+ mutex_unlock(&cldev->bus->cl_bus_lock);
+
+ cldev->is_added = 0;
+ put_device(&cldev->dev);
+}
+
+/**
+ * mei_cl_bus_remove_device - remove a devices form the bus
+ *
+ * @cldev: me client device
+ */
+static void mei_cl_bus_remove_device(struct mei_cl_device *cldev)
+{
+ mei_cl_bus_dev_stop(cldev);
+ mei_cl_bus_dev_destroy(cldev);
+}
+
+/**
+ * mei_cl_bus_remove_devices - remove all devices form the bus
+ *
+ * @bus: mei device
+ */
+void mei_cl_bus_remove_devices(struct mei_device *bus)
+{
+ struct mei_cl_device *cldev, *next;
+
+ list_for_each_entry_safe(cldev, next, &bus->device_list, bus_list)
+ mei_cl_bus_remove_device(cldev);
+}
+
+
+/**
+ * mei_cl_dev_init - allocate and initializes an mei client devices
+ * based on me client
+ *
+ * @bus: mei device
+ * @me_cl: me client
+ */
+static void mei_cl_dev_init(struct mei_device *bus, struct mei_me_client *me_cl)
+{
+ struct mei_cl_device *cldev;
+
+ dev_dbg(bus->dev, "initializing %pUl", mei_me_cl_uuid(me_cl));
+
+ if (me_cl->bus_added)
+ return;
+
+ cldev = mei_cl_dev_alloc(bus, me_cl);
+ if (!cldev)
+ return;
+
+ mutex_lock(&cldev->bus->cl_bus_lock);
+ me_cl->bus_added = true;
+ list_add_tail(&cldev->bus_list, &bus->device_list);
+ mutex_unlock(&cldev->bus->cl_bus_lock);
+
+}
+
+/**
+ * mei_cl_bus_rescan - scan me clients list and add create
+ * devices for eligible clients
+ *
+ * @bus: mei device
+ */
+void mei_cl_bus_rescan(struct mei_device *bus)
+{
+ struct mei_cl_device *cldev, *n;
+ struct mei_me_client *me_cl;
+
+ down_read(&bus->me_clients_rwsem);
+ list_for_each_entry(me_cl, &bus->me_clients, list)
+ mei_cl_dev_init(bus, me_cl);
+ up_read(&bus->me_clients_rwsem);
+
+ mutex_lock(&bus->cl_bus_lock);
+ list_for_each_entry_safe(cldev, n, &bus->device_list, bus_list) {
+
+ if (!mei_me_cl_is_active(cldev->me_cl)) {
+ mei_cl_bus_remove_device(cldev);
+ continue;
+ }
+
+ if (cldev->is_added)
+ continue;
+
+ if (mei_cl_dev_setup(bus, cldev))
+ mei_cl_bus_dev_add(cldev);
+ else {
+ list_del_init(&cldev->bus_list);
+ put_device(&cldev->dev);
+ }
+ }
+ mutex_unlock(&bus->cl_bus_lock);
+
+ dev_dbg(bus->dev, "rescan end");
+}
+
+int __mei_cl_driver_register(struct mei_cl_driver *cldrv, struct module *owner)
+{
+ int err;
+
+ cldrv->driver.name = cldrv->name;
+ cldrv->driver.owner = owner;
+ cldrv->driver.bus = &mei_cl_bus_type;
+
+ err = driver_register(&cldrv->driver);
+ if (err)
+ return err;
+
+ pr_debug("mei: driver [%s] registered\n", cldrv->driver.name);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__mei_cl_driver_register);
+
+void mei_cl_driver_unregister(struct mei_cl_driver *cldrv)
+{
+ driver_unregister(&cldrv->driver);
+
+ pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
+}
+EXPORT_SYMBOL_GPL(mei_cl_driver_unregister);
+
+
int __init mei_cl_bus_init(void)
{
return bus_register(&mei_cl_bus_type);
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 6decbe1..a6c87c7 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -555,10 +555,10 @@
init_waitqueue_head(&cl->wait);
init_waitqueue_head(&cl->rx_wait);
init_waitqueue_head(&cl->tx_wait);
+ init_waitqueue_head(&cl->ev_wait);
INIT_LIST_HEAD(&cl->rd_completed);
INIT_LIST_HEAD(&cl->rd_pending);
INIT_LIST_HEAD(&cl->link);
- INIT_LIST_HEAD(&cl->device_link);
cl->writing_state = MEI_IDLE;
cl->state = MEI_FILE_INITIALIZING;
cl->dev = dev;
@@ -690,16 +690,12 @@
mei_wd_host_init(dev, me_cl);
mei_me_cl_put(me_cl);
- me_cl = mei_me_cl_by_uuid(dev, &mei_nfc_guid);
- if (me_cl)
- mei_nfc_host_init(dev, me_cl);
- mei_me_cl_put(me_cl);
-
-
dev->dev_state = MEI_DEV_ENABLED;
dev->reset_count = 0;
mutex_unlock(&dev->device_lock);
+ mei_cl_bus_rescan(dev);
+
pm_runtime_mark_last_busy(dev->dev);
dev_dbg(dev->dev, "rpm: autosuspend\n");
pm_runtime_autosuspend(dev->dev);
@@ -841,45 +837,22 @@
return ret;
}
-
-
/**
- * mei_cl_disconnect - disconnect host client from the me one
+ * __mei_cl_disconnect - disconnect host client from the me one
+ * internal function runtime pm has to be already acquired
*
* @cl: host client
*
- * Locking: called under "dev->device_lock" lock
- *
* Return: 0 on success, <0 on failure.
*/
-int mei_cl_disconnect(struct mei_cl *cl)
+static int __mei_cl_disconnect(struct mei_cl *cl)
{
struct mei_device *dev;
struct mei_cl_cb *cb;
int rets;
- if (WARN_ON(!cl || !cl->dev))
- return -ENODEV;
-
dev = cl->dev;
- cl_dbg(dev, cl, "disconnecting");
-
- if (!mei_cl_is_connected(cl))
- return 0;
-
- if (mei_cl_is_fixed_address(cl)) {
- mei_cl_set_disconnected(cl);
- return 0;
- }
-
- rets = pm_runtime_get(dev->dev);
- if (rets < 0 && rets != -EINPROGRESS) {
- pm_runtime_put_noidle(dev->dev);
- cl_err(dev, cl, "rpm: get failed %d\n", rets);
- return rets;
- }
-
cl->state = MEI_FILE_DISCONNECTING;
cb = mei_io_cb_init(cl, MEI_FOP_DISCONNECT, NULL);
@@ -915,11 +888,52 @@
if (!rets)
cl_dbg(dev, cl, "successfully disconnected from FW client.\n");
+ mei_io_cb_free(cb);
+ return rets;
+}
+
+/**
+ * mei_cl_disconnect - disconnect host client from the me one
+ *
+ * @cl: host client
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * Return: 0 on success, <0 on failure.
+ */
+int mei_cl_disconnect(struct mei_cl *cl)
+{
+ struct mei_device *dev;
+ int rets;
+
+ if (WARN_ON(!cl || !cl->dev))
+ return -ENODEV;
+
+ dev = cl->dev;
+
+ cl_dbg(dev, cl, "disconnecting");
+
+ if (!mei_cl_is_connected(cl))
+ return 0;
+
+ if (mei_cl_is_fixed_address(cl)) {
+ mei_cl_set_disconnected(cl);
+ return 0;
+ }
+
+ rets = pm_runtime_get(dev->dev);
+ if (rets < 0 && rets != -EINPROGRESS) {
+ pm_runtime_put_noidle(dev->dev);
+ cl_err(dev, cl, "rpm: get failed %d\n", rets);
+ return rets;
+ }
+
+ rets = __mei_cl_disconnect(cl);
+
cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
- mei_io_cb_free(cb);
return rets;
}
@@ -1064,11 +1078,23 @@
mutex_unlock(&dev->device_lock);
wait_event_timeout(cl->wait,
(cl->state == MEI_FILE_CONNECTED ||
+ cl->state == MEI_FILE_DISCONNECT_REQUIRED ||
cl->state == MEI_FILE_DISCONNECT_REPLY),
mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
mutex_lock(&dev->device_lock);
if (!mei_cl_is_connected(cl)) {
+ if (cl->state == MEI_FILE_DISCONNECT_REQUIRED) {
+ mei_io_list_flush(&dev->ctrl_rd_list, cl);
+ mei_io_list_flush(&dev->ctrl_wr_list, cl);
+ /* ignore disconnect return valuue;
+ * in case of failure reset will be invoked
+ */
+ __mei_cl_disconnect(cl);
+ rets = -EFAULT;
+ goto out;
+ }
+
/* timeout or something went really wrong */
if (!cl->status)
cl->status = -EFAULT;
@@ -1181,6 +1207,221 @@
}
/**
+ * mei_cl_notify_fop2req - convert fop to proper request
+ *
+ * @fop: client notification start response command
+ *
+ * Return: MEI_HBM_NOTIFICATION_START/STOP
+ */
+u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop)
+{
+ if (fop == MEI_FOP_NOTIFY_START)
+ return MEI_HBM_NOTIFICATION_START;
+ else
+ return MEI_HBM_NOTIFICATION_STOP;
+}
+
+/**
+ * mei_cl_notify_req2fop - convert notification request top file operation type
+ *
+ * @req: hbm notification request type
+ *
+ * Return: MEI_FOP_NOTIFY_START/STOP
+ */
+enum mei_cb_file_ops mei_cl_notify_req2fop(u8 req)
+{
+ if (req == MEI_HBM_NOTIFICATION_START)
+ return MEI_FOP_NOTIFY_START;
+ else
+ return MEI_FOP_NOTIFY_STOP;
+}
+
+/**
+ * mei_cl_irq_notify - send notification request in irq_thread context
+ *
+ * @cl: client
+ * @cb: callback block.
+ * @cmpl_list: complete list.
+ *
+ * Return: 0 on such and error otherwise.
+ */
+int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
+ struct mei_cl_cb *cmpl_list)
+{
+ struct mei_device *dev = cl->dev;
+ u32 msg_slots;
+ int slots;
+ int ret;
+ bool request;
+
+ msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
+ slots = mei_hbuf_empty_slots(dev);
+
+ if (slots < msg_slots)
+ return -EMSGSIZE;
+
+ request = mei_cl_notify_fop2req(cb->fop_type);
+ ret = mei_hbm_cl_notify_req(dev, cl, request);
+ if (ret) {
+ cl->status = ret;
+ list_move_tail(&cb->list, &cmpl_list->list);
+ return ret;
+ }
+
+ list_move_tail(&cb->list, &dev->ctrl_rd_list.list);
+ return 0;
+}
+
+/**
+ * mei_cl_notify_request - send notification stop/start request
+ *
+ * @cl: host client
+ * @file: associate request with file
+ * @request: 1 for start or 0 for stop
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * Return: 0 on such and error otherwise.
+ */
+int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request)
+{
+ struct mei_device *dev;
+ struct mei_cl_cb *cb;
+ enum mei_cb_file_ops fop_type;
+ int rets;
+
+ if (WARN_ON(!cl || !cl->dev))
+ return -ENODEV;
+
+ dev = cl->dev;
+
+ if (!dev->hbm_f_ev_supported) {
+ cl_dbg(dev, cl, "notifications not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ rets = pm_runtime_get(dev->dev);
+ if (rets < 0 && rets != -EINPROGRESS) {
+ pm_runtime_put_noidle(dev->dev);
+ cl_err(dev, cl, "rpm: get failed %d\n", rets);
+ return rets;
+ }
+
+ fop_type = mei_cl_notify_req2fop(request);
+ cb = mei_io_cb_init(cl, fop_type, file);
+ if (!cb) {
+ rets = -ENOMEM;
+ goto out;
+ }
+
+ if (mei_hbuf_acquire(dev)) {
+ if (mei_hbm_cl_notify_req(dev, cl, request)) {
+ rets = -ENODEV;
+ goto out;
+ }
+ list_add_tail(&cb->list, &dev->ctrl_rd_list.list);
+ } else {
+ list_add_tail(&cb->list, &dev->ctrl_wr_list.list);
+ }
+
+ mutex_unlock(&dev->device_lock);
+ wait_event_timeout(cl->wait, cl->notify_en == request,
+ mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
+ mutex_lock(&dev->device_lock);
+
+ if (cl->notify_en != request) {
+ mei_io_list_flush(&dev->ctrl_rd_list, cl);
+ mei_io_list_flush(&dev->ctrl_wr_list, cl);
+ if (!cl->status)
+ cl->status = -EFAULT;
+ }
+
+ rets = cl->status;
+
+out:
+ cl_dbg(dev, cl, "rpm: autosuspend\n");
+ pm_runtime_mark_last_busy(dev->dev);
+ pm_runtime_put_autosuspend(dev->dev);
+
+ mei_io_cb_free(cb);
+ return rets;
+}
+
+/**
+ * mei_cl_notify - raise notification
+ *
+ * @cl: host client
+ *
+ * Locking: called under "dev->device_lock" lock
+ */
+void mei_cl_notify(struct mei_cl *cl)
+{
+ struct mei_device *dev;
+
+ if (!cl || !cl->dev)
+ return;
+
+ dev = cl->dev;
+
+ if (!cl->notify_en)
+ return;
+
+ cl_dbg(dev, cl, "notify event");
+ cl->notify_ev = true;
+ wake_up_interruptible_all(&cl->ev_wait);
+
+ if (cl->ev_async)
+ kill_fasync(&cl->ev_async, SIGIO, POLL_PRI);
+
+ mei_cl_bus_notify_event(cl);
+}
+
+/**
+ * mei_cl_notify_get - get or wait for notification event
+ *
+ * @cl: host client
+ * @block: this request is blocking
+ * @notify_ev: true if notification event was received
+ *
+ * Locking: called under "dev->device_lock" lock
+ *
+ * Return: 0 on such and error otherwise.
+ */
+int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev)
+{
+ struct mei_device *dev;
+ int rets;
+
+ *notify_ev = false;
+
+ if (WARN_ON(!cl || !cl->dev))
+ return -ENODEV;
+
+ dev = cl->dev;
+
+ if (!mei_cl_is_connected(cl))
+ return -ENODEV;
+
+ if (cl->notify_ev)
+ goto out;
+
+ if (!block)
+ return -EAGAIN;
+
+ mutex_unlock(&dev->device_lock);
+ rets = wait_event_interruptible(cl->ev_wait, cl->notify_ev);
+ mutex_lock(&dev->device_lock);
+
+ if (rets < 0)
+ return rets;
+
+out:
+ *notify_ev = cl->notify_ev;
+ cl->notify_ev = false;
+ return 0;
+}
+
+/**
* mei_cl_read_start - the start read client message function.
*
* @cl: host client
@@ -1356,6 +1597,7 @@
struct mei_device *dev;
struct mei_msg_data *buf;
struct mei_msg_hdr mei_hdr;
+ int size;
int rets;
@@ -1367,10 +1609,10 @@
dev = cl->dev;
-
buf = &cb->buf;
+ size = buf->size;
- cl_dbg(dev, cl, "size=%d\n", buf->size);
+ cl_dbg(dev, cl, "size=%d\n", size);
rets = pm_runtime_get(dev->dev);
if (rets < 0 && rets != -EINPROGRESS) {
@@ -1394,21 +1636,21 @@
if (rets == 0) {
cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
- rets = buf->size;
+ rets = size;
goto out;
}
if (!mei_hbuf_acquire(dev)) {
cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n");
- rets = buf->size;
+ rets = size;
goto out;
}
/* Check for a maximum length */
- if (buf->size > mei_hbuf_max_len(dev)) {
+ if (size > mei_hbuf_max_len(dev)) {
mei_hdr.length = mei_hbuf_max_len(dev);
mei_hdr.msg_complete = 0;
} else {
- mei_hdr.length = buf->size;
+ mei_hdr.length = size;
mei_hdr.msg_complete = 1;
}
@@ -1430,6 +1672,7 @@
else
list_add_tail(&cb->list, &dev->write_list.list);
+ cb = NULL;
if (blocking && cl->writing_state != MEI_WRITE_COMPLETE) {
mutex_unlock(&dev->device_lock);
@@ -1444,7 +1687,7 @@
}
}
- rets = buf->size;
+ rets = size;
err:
cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(dev->dev);
@@ -1486,6 +1729,8 @@
case MEI_FOP_CONNECT:
case MEI_FOP_DISCONNECT:
+ case MEI_FOP_NOTIFY_STOP:
+ case MEI_FOP_NOTIFY_START:
if (waitqueue_active(&cl->wait))
wake_up(&cl->wait);
@@ -1528,6 +1773,12 @@
cl_dbg(dev, cl, "Waking up writing client!\n");
wake_up_interruptible(&cl->tx_wait);
}
+
+ /* synchronized under device mutex */
+ if (waitqueue_active(&cl->ev_wait)) {
+ cl_dbg(dev, cl, "Waking up waiting for event clients!\n");
+ wake_up_interruptible(&cl->ev_wait);
+ }
}
}
diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h
index 8d7f057..1c7cad0 100644
--- a/drivers/misc/mei/client.h
+++ b/drivers/misc/mei/client.h
@@ -219,6 +219,14 @@
void mei_host_client_init(struct work_struct *work);
+u8 mei_cl_notify_fop2req(enum mei_cb_file_ops fop);
+enum mei_cb_file_ops mei_cl_notify_req2fop(u8 request);
+int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request);
+int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
+ struct mei_cl_cb *cmpl_list);
+int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev);
+void mei_cl_notify(struct mei_cl *cl);
+
void mei_cl_all_disconnect(struct mei_device *dev);
void mei_cl_all_wakeup(struct mei_device *dev);
void mei_cl_all_write_clear(struct mei_device *dev);
diff --git a/drivers/misc/mei/debugfs.c b/drivers/misc/mei/debugfs.c
index eb86834..4b469cf 100644
--- a/drivers/misc/mei/debugfs.c
+++ b/drivers/misc/mei/debugfs.c
@@ -154,6 +154,12 @@
pos += scnprintf(buf + pos, bufsz - pos, "hbm features:\n");
pos += scnprintf(buf + pos, bufsz - pos, "\tPG: %01d\n",
dev->hbm_f_pg_supported);
+ pos += scnprintf(buf + pos, bufsz - pos, "\tDC: %01d\n",
+ dev->hbm_f_dc_supported);
+ pos += scnprintf(buf + pos, bufsz - pos, "\tDOT: %01d\n",
+ dev->hbm_f_dot_supported);
+ pos += scnprintf(buf + pos, bufsz - pos, "\tEV: %01d\n",
+ dev->hbm_f_ev_supported);
}
pos += scnprintf(buf + pos, bufsz - pos, "pg: %s, %s\n",
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index a4f2831..8eec887 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -52,6 +52,7 @@
MEI_CL_CS(ALREADY_STARTED);
MEI_CL_CS(OUT_OF_RESOURCES);
MEI_CL_CS(MESSAGE_SMALL);
+ MEI_CL_CS(NOT_ALLOWED);
default: return "unknown";
}
#undef MEI_CL_CCS
@@ -89,6 +90,7 @@
case MEI_CL_CONN_ALREADY_STARTED: return -EBUSY;
case MEI_CL_CONN_OUT_OF_RESOURCES: return -EBUSY;
case MEI_CL_CONN_MESSAGE_SMALL: return -EINVAL;
+ case MEI_CL_CONN_NOT_ALLOWED: return -EBUSY;
default: return -EINVAL;
}
}
@@ -299,6 +301,7 @@
enum_req = (struct hbm_host_enum_request *)dev->wr_msg.data;
memset(enum_req, 0, len);
enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
+ enum_req->allow_add = dev->hbm_f_dc_supported;
ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
if (ret) {
@@ -344,6 +347,180 @@
}
/**
+ * mei_hbm_add_cl_resp - send response to fw on client add request
+ *
+ * @dev: the device structure
+ * @addr: me address
+ * @status: response status
+ *
+ * Return: 0 on success and < 0 on failure
+ */
+static int mei_hbm_add_cl_resp(struct mei_device *dev, u8 addr, u8 status)
+{
+ struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
+ struct hbm_add_client_response *resp;
+ const size_t len = sizeof(struct hbm_add_client_response);
+ int ret;
+
+ dev_dbg(dev->dev, "adding client response\n");
+
+ resp = (struct hbm_add_client_response *)dev->wr_msg.data;
+
+ mei_hbm_hdr(mei_hdr, len);
+ memset(resp, 0, sizeof(struct hbm_add_client_response));
+
+ resp->hbm_cmd = MEI_HBM_ADD_CLIENT_RES_CMD;
+ resp->me_addr = addr;
+ resp->status = status;
+
+ ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+ if (ret)
+ dev_err(dev->dev, "add client response write failed: ret = %d\n",
+ ret);
+ return ret;
+}
+
+/**
+ * mei_hbm_fw_add_cl_req - request from the fw to add a client
+ *
+ * @dev: the device structure
+ * @req: add client request
+ *
+ * Return: 0 on success and < 0 on failure
+ */
+static int mei_hbm_fw_add_cl_req(struct mei_device *dev,
+ struct hbm_add_client_request *req)
+{
+ int ret;
+ u8 status = MEI_HBMS_SUCCESS;
+
+ BUILD_BUG_ON(sizeof(struct hbm_add_client_request) !=
+ sizeof(struct hbm_props_response));
+
+ ret = mei_hbm_me_cl_add(dev, (struct hbm_props_response *)req);
+ if (ret)
+ status = !MEI_HBMS_SUCCESS;
+
+ return mei_hbm_add_cl_resp(dev, req->me_addr, status);
+}
+
+/**
+ * mei_hbm_cl_notify_req - send notification request
+ *
+ * @dev: the device structure
+ * @cl: a client to disconnect from
+ * @start: true for start false for stop
+ *
+ * Return: 0 on success and -EIO on write failure
+ */
+int mei_hbm_cl_notify_req(struct mei_device *dev,
+ struct mei_cl *cl, u8 start)
+{
+
+ struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr;
+ struct hbm_notification_request *req;
+ const size_t len = sizeof(struct hbm_notification_request);
+ int ret;
+
+ mei_hbm_hdr(mei_hdr, len);
+ mei_hbm_cl_hdr(cl, MEI_HBM_NOTIFY_REQ_CMD, dev->wr_msg.data, len);
+
+ req = (struct hbm_notification_request *)dev->wr_msg.data;
+ req->start = start;
+
+ ret = mei_write_message(dev, mei_hdr, dev->wr_msg.data);
+ if (ret)
+ dev_err(dev->dev, "notify request failed: ret = %d\n", ret);
+
+ return ret;
+}
+
+/**
+ * notify_res_to_fop - convert notification response to the proper
+ * notification FOP
+ *
+ * @cmd: client notification start response command
+ *
+ * Return: MEI_FOP_NOTIFY_START or MEI_FOP_NOTIFY_STOP;
+ */
+static inline enum mei_cb_file_ops notify_res_to_fop(struct mei_hbm_cl_cmd *cmd)
+{
+ struct hbm_notification_response *rs =
+ (struct hbm_notification_response *)cmd;
+
+ return mei_cl_notify_req2fop(rs->start);
+}
+
+/**
+ * mei_hbm_cl_notify_start_res - update the client state according
+ * notify start response
+ *
+ * @dev: the device structure
+ * @cl: mei host client
+ * @cmd: client notification start response command
+ */
+static void mei_hbm_cl_notify_start_res(struct mei_device *dev,
+ struct mei_cl *cl,
+ struct mei_hbm_cl_cmd *cmd)
+{
+ struct hbm_notification_response *rs =
+ (struct hbm_notification_response *)cmd;
+
+ cl_dbg(dev, cl, "hbm: notify start response status=%d\n", rs->status);
+
+ if (rs->status == MEI_HBMS_SUCCESS ||
+ rs->status == MEI_HBMS_ALREADY_STARTED) {
+ cl->notify_en = true;
+ cl->status = 0;
+ } else {
+ cl->status = -EINVAL;
+ }
+}
+
+/**
+ * mei_hbm_cl_notify_stop_res - update the client state according
+ * notify stop response
+ *
+ * @dev: the device structure
+ * @cl: mei host client
+ * @cmd: client notification stop response command
+ */
+static void mei_hbm_cl_notify_stop_res(struct mei_device *dev,
+ struct mei_cl *cl,
+ struct mei_hbm_cl_cmd *cmd)
+{
+ struct hbm_notification_response *rs =
+ (struct hbm_notification_response *)cmd;
+
+ cl_dbg(dev, cl, "hbm: notify stop response status=%d\n", rs->status);
+
+ if (rs->status == MEI_HBMS_SUCCESS ||
+ rs->status == MEI_HBMS_NOT_STARTED) {
+ cl->notify_en = false;
+ cl->status = 0;
+ } else {
+ /* TODO: spec is not clear yet about other possible issues */
+ cl->status = -EINVAL;
+ }
+}
+
+/**
+ * mei_hbm_cl_notify - signal notification event
+ *
+ * @dev: the device structure
+ * @cmd: notification client message
+ */
+static void mei_hbm_cl_notify(struct mei_device *dev,
+ struct mei_hbm_cl_cmd *cmd)
+{
+ struct mei_cl *cl;
+
+ cl = mei_hbm_cl_find_by_cmd(dev, cmd);
+ if (cl)
+ mei_cl_notify(cl);
+}
+
+/**
* mei_hbm_prop_req - request property for a single client
*
* @dev: the device structure
@@ -610,8 +787,11 @@
if (rs->status == MEI_CL_CONN_SUCCESS)
cl->state = MEI_FILE_CONNECTED;
- else
+ else {
cl->state = MEI_FILE_DISCONNECT_REPLY;
+ if (rs->status == MEI_CL_CONN_NOT_FOUND)
+ mei_me_cl_del(dev, cl->me_cl);
+ }
cl->status = mei_cl_conn_status_to_errno(rs->status);
}
@@ -654,6 +834,12 @@
case MEI_FOP_DISCONNECT:
mei_hbm_cl_disconnect_res(dev, cl, rs);
break;
+ case MEI_FOP_NOTIFY_START:
+ mei_hbm_cl_notify_start_res(dev, cl, rs);
+ break;
+ case MEI_FOP_NOTIFY_STOP:
+ mei_hbm_cl_notify_stop_res(dev, cl, rs);
+ break;
default:
return;
}
@@ -694,6 +880,79 @@
}
/**
+ * mei_hbm_pg_enter_res - PG enter response received
+ *
+ * @dev: the device structure.
+ *
+ * Return: 0 on success, -EPROTO on state mismatch
+ */
+static int mei_hbm_pg_enter_res(struct mei_device *dev)
+{
+ if (mei_pg_state(dev) != MEI_PG_OFF ||
+ dev->pg_event != MEI_PG_EVENT_WAIT) {
+ dev_err(dev->dev, "hbm: pg entry response: state mismatch [%s, %d]\n",
+ mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
+ return -EPROTO;
+ }
+
+ dev->pg_event = MEI_PG_EVENT_RECEIVED;
+ wake_up(&dev->wait_pg);
+
+ return 0;
+}
+
+/**
+ * mei_hbm_pg_resume - process with PG resume
+ *
+ * @dev: the device structure.
+ */
+void mei_hbm_pg_resume(struct mei_device *dev)
+{
+ pm_request_resume(dev->dev);
+}
+EXPORT_SYMBOL_GPL(mei_hbm_pg_resume);
+
+/**
+ * mei_hbm_pg_exit_res - PG exit response received
+ *
+ * @dev: the device structure.
+ *
+ * Return: 0 on success, -EPROTO on state mismatch
+ */
+static int mei_hbm_pg_exit_res(struct mei_device *dev)
+{
+ if (mei_pg_state(dev) != MEI_PG_ON ||
+ (dev->pg_event != MEI_PG_EVENT_WAIT &&
+ dev->pg_event != MEI_PG_EVENT_IDLE)) {
+ dev_err(dev->dev, "hbm: pg exit response: state mismatch [%s, %d]\n",
+ mei_pg_state_str(mei_pg_state(dev)), dev->pg_event);
+ return -EPROTO;
+ }
+
+ switch (dev->pg_event) {
+ case MEI_PG_EVENT_WAIT:
+ dev->pg_event = MEI_PG_EVENT_RECEIVED;
+ wake_up(&dev->wait_pg);
+ break;
+ case MEI_PG_EVENT_IDLE:
+ /*
+ * If the driver is not waiting on this then
+ * this is HW initiated exit from PG.
+ * Start runtime pm resume sequence to exit from PG.
+ */
+ dev->pg_event = MEI_PG_EVENT_RECEIVED;
+ mei_hbm_pg_resume(dev);
+ break;
+ default:
+ WARN(1, "hbm: pg exit response: unexpected pg event = %d\n",
+ dev->pg_event);
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
+/**
* mei_hbm_config_features - check what hbm features and commands
* are supported by the fw
*
@@ -709,6 +968,17 @@
if (dev->version.major_version == HBM_MAJOR_VERSION_PGI &&
dev->version.minor_version >= HBM_MINOR_VERSION_PGI)
dev->hbm_f_pg_supported = 1;
+
+ if (dev->version.major_version >= HBM_MAJOR_VERSION_DC)
+ dev->hbm_f_dc_supported = 1;
+
+ /* disconnect on connect timeout instead of link reset */
+ if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT)
+ dev->hbm_f_dot_supported = 1;
+
+ /* Notification Event Support */
+ if (dev->version.major_version >= HBM_MAJOR_VERSION_EV)
+ dev->hbm_f_ev_supported = 1;
}
/**
@@ -740,6 +1010,8 @@
struct hbm_host_version_response *version_res;
struct hbm_props_response *props_res;
struct hbm_host_enum_response *enum_res;
+ struct hbm_add_client_request *add_cl_req;
+ int ret;
struct mei_hbm_cl_cmd *cl_cmd;
struct hbm_client_connect_request *disconnect_req;
@@ -828,24 +1100,17 @@
break;
case MEI_PG_ISOLATION_ENTRY_RES_CMD:
- dev_dbg(dev->dev, "power gate isolation entry response received\n");
- dev->pg_event = MEI_PG_EVENT_RECEIVED;
- if (waitqueue_active(&dev->wait_pg))
- wake_up(&dev->wait_pg);
+ dev_dbg(dev->dev, "hbm: power gate isolation entry response received\n");
+ ret = mei_hbm_pg_enter_res(dev);
+ if (ret)
+ return ret;
break;
case MEI_PG_ISOLATION_EXIT_REQ_CMD:
- dev_dbg(dev->dev, "power gate isolation exit request received\n");
- dev->pg_event = MEI_PG_EVENT_RECEIVED;
- if (waitqueue_active(&dev->wait_pg))
- wake_up(&dev->wait_pg);
- else
- /*
- * If the driver is not waiting on this then
- * this is HW initiated exit from PG.
- * Start runtime pm resume sequence to exit from PG.
- */
- pm_request_resume(dev->dev);
+ dev_dbg(dev->dev, "hbm: power gate isolation exit request received\n");
+ ret = mei_hbm_pg_exit_res(dev);
+ if (ret)
+ return ret;
break;
case HOST_CLIENT_PROPERTIES_RES_CMD:
@@ -937,6 +1202,39 @@
return -EIO;
}
break;
+
+ case MEI_HBM_ADD_CLIENT_REQ_CMD:
+ dev_dbg(dev->dev, "hbm: add client request received\n");
+ /*
+ * after the host receives the enum_resp
+ * message clients may be added or removed
+ */
+ if (dev->hbm_state <= MEI_HBM_ENUM_CLIENTS &&
+ dev->hbm_state >= MEI_HBM_STOPPED) {
+ dev_err(dev->dev, "hbm: add client: state mismatch, [%d, %d]\n",
+ dev->dev_state, dev->hbm_state);
+ return -EPROTO;
+ }
+ add_cl_req = (struct hbm_add_client_request *)mei_msg;
+ ret = mei_hbm_fw_add_cl_req(dev, add_cl_req);
+ if (ret) {
+ dev_err(dev->dev, "hbm: add client: failed to send response %d\n",
+ ret);
+ return -EIO;
+ }
+ dev_dbg(dev->dev, "hbm: add client request processed\n");
+ break;
+
+ case MEI_HBM_NOTIFY_RES_CMD:
+ dev_dbg(dev->dev, "hbm: notify response received\n");
+ mei_hbm_cl_res(dev, cl_cmd, notify_res_to_fop(cl_cmd));
+ break;
+
+ case MEI_HBM_NOTIFICATION_CMD:
+ dev_dbg(dev->dev, "hbm: notification\n");
+ mei_hbm_cl_notify(dev, cl_cmd);
+ break;
+
default:
BUG();
break;
diff --git a/drivers/misc/mei/hbm.h b/drivers/misc/mei/hbm.h
index 2544db7..a2025a5 100644
--- a/drivers/misc/mei/hbm.h
+++ b/drivers/misc/mei/hbm.h
@@ -54,6 +54,9 @@
int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl);
bool mei_hbm_version_is_supported(struct mei_device *dev);
int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd);
+void mei_hbm_pg_resume(struct mei_device *dev);
+int mei_hbm_cl_notify_req(struct mei_device *dev,
+ struct mei_cl *cl, u8 request);
#endif /* _MEI_HBM_H_ */
diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h
index 9eb7ed7..a8a68ac 100644
--- a/drivers/misc/mei/hw-me-regs.h
+++ b/drivers/misc/mei/hw-me-regs.h
@@ -117,12 +117,17 @@
#define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */
#define MEI_DEV_ID_WPT_LP_2 0x9CBB /* Wildcat Point LP 2 */
+#define MEI_DEV_ID_SPT 0x9D3A /* Sunrise Point */
+#define MEI_DEV_ID_SPT_2 0x9D3B /* Sunrise Point 2 */
+#define MEI_DEV_ID_SPT_H 0xA13A /* Sunrise Point H */
+#define MEI_DEV_ID_SPT_H_2 0xA13B /* Sunrise Point H 2 */
/*
* MEI HW Section
*/
/* Host Firmware Status Registers in PCI Config Space */
#define PCI_CFG_HFS_1 0x40
+# define PCI_CFG_HFS_1_D0I3_MSK 0x80000000
#define PCI_CFG_HFS_2 0x48
#define PCI_CFG_HFS_3 0x60
#define PCI_CFG_HFS_4 0x64
@@ -140,7 +145,8 @@
#define ME_CSR_HA 0xC
/* H_HGC_CSR - PGI register */
#define H_HPG_CSR 0x10
-
+/* H_D0I3C - D0I3 Control */
+#define H_D0I3C 0x800
/* register bits of H_CSR (Host Control Status register) */
/* Host Circular Buffer Depth - maximum number of 32-bit entries in CB */
@@ -159,7 +165,14 @@
#define H_IS 0x00000002
/* Host Interrupt Enable */
#define H_IE 0x00000001
+/* Host D0I3 Interrupt Enable */
+#define H_D0I3C_IE 0x00000020
+/* Host D0I3 Interrupt Status */
+#define H_D0I3C_IS 0x00000040
+/* H_CSR masks */
+#define H_CSR_IE_MASK (H_IE | H_D0I3C_IE)
+#define H_CSR_IS_MASK (H_IS | H_D0I3C_IS)
/* register bits of ME_CSR_HA (ME Control Status Host Access register) */
/* ME CB (Circular Buffer) Depth HRA (Host Read Access) - host read only
@@ -183,8 +196,14 @@
#define ME_IE_HRA 0x00000001
-/* register bits - H_HPG_CSR */
-#define H_HPG_CSR_PGIHEXR 0x00000001
-#define H_HPG_CSR_PGI 0x00000002
+/* H_HPG_CSR register bits */
+#define H_HPG_CSR_PGIHEXR 0x00000001
+#define H_HPG_CSR_PGI 0x00000002
+
+/* H_D0I3C register bits */
+#define H_D0I3C_CIP 0x00000001
+#define H_D0I3C_IR 0x00000002
+#define H_D0I3C_I3 0x00000004
+#define H_D0I3C_RR 0x00000008
#endif /* _MEI_HW_MEI_REGS_H_ */
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index 43d7101..65511d3 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -134,11 +134,40 @@
*/
static inline void mei_hcsr_set(struct mei_device *dev, u32 reg)
{
- reg &= ~H_IS;
+ reg &= ~H_CSR_IS_MASK;
mei_hcsr_write(dev, reg);
}
/**
+ * mei_me_d0i3c_read - Reads 32bit data from the D0I3C register
+ *
+ * @dev: the device structure
+ *
+ * Return: H_D0I3C register value (u32)
+ */
+static inline u32 mei_me_d0i3c_read(const struct mei_device *dev)
+{
+ u32 reg;
+
+ reg = mei_me_reg_read(to_me_hw(dev), H_D0I3C);
+ trace_mei_reg_read(dev->dev, "H_D0I3C", H_CSR, reg);
+
+ return reg;
+}
+
+/**
+ * mei_me_d0i3c_write - writes H_D0I3C register to device
+ *
+ * @dev: the device structure
+ * @reg: new register value
+ */
+static inline void mei_me_d0i3c_write(struct mei_device *dev, u32 reg)
+{
+ trace_mei_reg_write(dev->dev, "H_D0I3C", H_CSR, reg);
+ mei_me_reg_write(to_me_hw(dev), H_D0I3C, reg);
+}
+
+/**
* mei_me_fw_status - read fw status register from pci config space
*
* @dev: mei device
@@ -176,12 +205,25 @@
*/
static void mei_me_hw_config(struct mei_device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev->dev);
struct mei_me_hw *hw = to_me_hw(dev);
- u32 hcsr = mei_hcsr_read(dev);
+ u32 hcsr, reg;
+
/* Doesn't change in runtime */
+ hcsr = mei_hcsr_read(dev);
dev->hbuf_depth = (hcsr & H_CBD) >> 24;
+ reg = 0;
+ pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®);
+ hw->d0i3_supported =
+ ((reg & PCI_CFG_HFS_1_D0I3_MSK) == PCI_CFG_HFS_1_D0I3_MSK);
+
hw->pg_state = MEI_PG_OFF;
+ if (hw->d0i3_supported) {
+ reg = mei_me_d0i3c_read(dev);
+ if (reg & H_D0I3C_I3)
+ hw->pg_state = MEI_PG_ON;
+ }
}
/**
@@ -208,7 +250,7 @@
{
u32 hcsr = mei_hcsr_read(dev);
- if ((hcsr & H_IS) == H_IS)
+ if (hcsr & H_CSR_IS_MASK)
mei_hcsr_write(dev, hcsr);
}
/**
@@ -220,7 +262,7 @@
{
u32 hcsr = mei_hcsr_read(dev);
- hcsr |= H_IE;
+ hcsr |= H_CSR_IE_MASK;
mei_hcsr_set(dev, hcsr);
}
@@ -233,7 +275,7 @@
{
u32 hcsr = mei_hcsr_read(dev);
- hcsr &= ~H_IE;
+ hcsr &= ~H_CSR_IE_MASK;
mei_hcsr_set(dev, hcsr);
}
@@ -253,57 +295,6 @@
/* complete this write before we set host ready on another CPU */
mmiowb();
}
-/**
- * mei_me_hw_reset - resets fw via mei csr register.
- *
- * @dev: the device structure
- * @intr_enable: if interrupt should be enabled after reset.
- *
- * Return: always 0
- */
-static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
-{
- u32 hcsr = mei_hcsr_read(dev);
-
- /* H_RST may be found lit before reset is started,
- * for example if preceding reset flow hasn't completed.
- * In that case asserting H_RST will be ignored, therefore
- * we need to clean H_RST bit to start a successful reset sequence.
- */
- if ((hcsr & H_RST) == H_RST) {
- dev_warn(dev->dev, "H_RST is set = 0x%08X", hcsr);
- hcsr &= ~H_RST;
- mei_hcsr_set(dev, hcsr);
- hcsr = mei_hcsr_read(dev);
- }
-
- hcsr |= H_RST | H_IG | H_IS;
-
- if (intr_enable)
- hcsr |= H_IE;
- else
- hcsr &= ~H_IE;
-
- dev->recvd_hw_ready = false;
- mei_hcsr_write(dev, hcsr);
-
- /*
- * Host reads the H_CSR once to ensure that the
- * posted write to H_CSR completes.
- */
- hcsr = mei_hcsr_read(dev);
-
- if ((hcsr & H_RST) == 0)
- dev_warn(dev->dev, "H_RST is not set = 0x%08X", hcsr);
-
- if ((hcsr & H_RDY) == H_RDY)
- dev_warn(dev->dev, "H_RDY is not cleared 0x%08X", hcsr);
-
- if (intr_enable == false)
- mei_me_hw_reset_release(dev);
-
- return 0;
-}
/**
* mei_me_host_set_ready - enable device
@@ -314,7 +305,7 @@
{
u32 hcsr = mei_hcsr_read(dev);
- hcsr |= H_IE | H_IG | H_RDY;
+ hcsr |= H_CSR_IE_MASK | H_IG | H_RDY;
mei_hcsr_set(dev, hcsr);
}
@@ -601,13 +592,13 @@
}
/**
- * mei_me_pg_enter_sync - perform pg entry procedure
+ * mei_me_pg_legacy_enter_sync - perform legacy pg entry procedure
*
* @dev: the device structure
*
* Return: 0 on success an error code otherwise
*/
-int mei_me_pg_enter_sync(struct mei_device *dev)
+static int mei_me_pg_legacy_enter_sync(struct mei_device *dev)
{
struct mei_me_hw *hw = to_me_hw(dev);
unsigned long timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
@@ -638,13 +629,13 @@
}
/**
- * mei_me_pg_exit_sync - perform pg exit procedure
+ * mei_me_pg_legacy_exit_sync - perform legacy pg exit procedure
*
* @dev: the device structure
*
* Return: 0 on success an error code otherwise
*/
-int mei_me_pg_exit_sync(struct mei_device *dev)
+static int mei_me_pg_legacy_exit_sync(struct mei_device *dev)
{
struct mei_me_hw *hw = to_me_hw(dev);
unsigned long timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
@@ -712,8 +703,12 @@
*/
static bool mei_me_pg_is_enabled(struct mei_device *dev)
{
+ struct mei_me_hw *hw = to_me_hw(dev);
u32 reg = mei_me_mecsr_read(dev);
+ if (hw->d0i3_supported)
+ return true;
+
if ((reg & ME_PGIC_HRA) == 0)
goto notsupported;
@@ -723,7 +718,8 @@
return true;
notsupported:
- dev_dbg(dev->dev, "pg: not supported: HGP = %d hbm version %d.%d ?= %d.%d\n",
+ dev_dbg(dev->dev, "pg: not supported: d0i3 = %d HGP = %d hbm version %d.%d ?= %d.%d\n",
+ hw->d0i3_supported,
!!(reg & ME_PGIC_HRA),
dev->version.major_version,
dev->version.minor_version,
@@ -734,11 +730,211 @@
}
/**
- * mei_me_pg_intr - perform pg processing in interrupt thread handler
+ * mei_me_d0i3_set - write d0i3 register bit on mei device.
+ *
+ * @dev: the device structure
+ * @intr: ask for interrupt
+ *
+ * Return: D0I3C register value
+ */
+static u32 mei_me_d0i3_set(struct mei_device *dev, bool intr)
+{
+ u32 reg = mei_me_d0i3c_read(dev);
+
+ reg |= H_D0I3C_I3;
+ if (intr)
+ reg |= H_D0I3C_IR;
+ else
+ reg &= ~H_D0I3C_IR;
+ mei_me_d0i3c_write(dev, reg);
+ /* read it to ensure HW consistency */
+ reg = mei_me_d0i3c_read(dev);
+ return reg;
+}
+
+/**
+ * mei_me_d0i3_unset - clean d0i3 register bit on mei device.
+ *
+ * @dev: the device structure
+ *
+ * Return: D0I3C register value
+ */
+static u32 mei_me_d0i3_unset(struct mei_device *dev)
+{
+ u32 reg = mei_me_d0i3c_read(dev);
+
+ reg &= ~H_D0I3C_I3;
+ reg |= H_D0I3C_IR;
+ mei_me_d0i3c_write(dev, reg);
+ /* read it to ensure HW consistency */
+ reg = mei_me_d0i3c_read(dev);
+ return reg;
+}
+
+/**
+ * mei_me_d0i3_enter_sync - perform d0i3 entry procedure
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+static int mei_me_d0i3_enter_sync(struct mei_device *dev)
+{
+ struct mei_me_hw *hw = to_me_hw(dev);
+ unsigned long d0i3_timeout = mei_secs_to_jiffies(MEI_D0I3_TIMEOUT);
+ unsigned long pgi_timeout = mei_secs_to_jiffies(MEI_PGI_TIMEOUT);
+ int ret;
+ u32 reg;
+
+ reg = mei_me_d0i3c_read(dev);
+ if (reg & H_D0I3C_I3) {
+ /* we are in d0i3, nothing to do */
+ dev_dbg(dev->dev, "d0i3 set not needed\n");
+ ret = 0;
+ goto on;
+ }
+
+ /* PGI entry procedure */
+ dev->pg_event = MEI_PG_EVENT_WAIT;
+
+ ret = mei_hbm_pg(dev, MEI_PG_ISOLATION_ENTRY_REQ_CMD);
+ if (ret)
+ /* FIXME: should we reset here? */
+ goto out;
+
+ mutex_unlock(&dev->device_lock);
+ wait_event_timeout(dev->wait_pg,
+ dev->pg_event == MEI_PG_EVENT_RECEIVED, pgi_timeout);
+ mutex_lock(&dev->device_lock);
+
+ if (dev->pg_event != MEI_PG_EVENT_RECEIVED) {
+ ret = -ETIME;
+ goto out;
+ }
+ /* end PGI entry procedure */
+
+ dev->pg_event = MEI_PG_EVENT_INTR_WAIT;
+
+ reg = mei_me_d0i3_set(dev, true);
+ if (!(reg & H_D0I3C_CIP)) {
+ dev_dbg(dev->dev, "d0i3 enter wait not needed\n");
+ ret = 0;
+ goto on;
+ }
+
+ mutex_unlock(&dev->device_lock);
+ wait_event_timeout(dev->wait_pg,
+ dev->pg_event == MEI_PG_EVENT_INTR_RECEIVED, d0i3_timeout);
+ mutex_lock(&dev->device_lock);
+
+ if (dev->pg_event != MEI_PG_EVENT_INTR_RECEIVED) {
+ reg = mei_me_d0i3c_read(dev);
+ if (!(reg & H_D0I3C_I3)) {
+ ret = -ETIME;
+ goto out;
+ }
+ }
+
+ ret = 0;
+on:
+ hw->pg_state = MEI_PG_ON;
+out:
+ dev->pg_event = MEI_PG_EVENT_IDLE;
+ dev_dbg(dev->dev, "d0i3 enter ret = %d\n", ret);
+ return ret;
+}
+
+/**
+ * mei_me_d0i3_enter - perform d0i3 entry procedure
+ * no hbm PG handshake
+ * no waiting for confirmation; runs with interrupts
+ * disabled
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+static int mei_me_d0i3_enter(struct mei_device *dev)
+{
+ struct mei_me_hw *hw = to_me_hw(dev);
+ u32 reg;
+
+ reg = mei_me_d0i3c_read(dev);
+ if (reg & H_D0I3C_I3) {
+ /* we are in d0i3, nothing to do */
+ dev_dbg(dev->dev, "already d0i3 : set not needed\n");
+ goto on;
+ }
+
+ mei_me_d0i3_set(dev, false);
+on:
+ hw->pg_state = MEI_PG_ON;
+ dev->pg_event = MEI_PG_EVENT_IDLE;
+ dev_dbg(dev->dev, "d0i3 enter\n");
+ return 0;
+}
+
+/**
+ * mei_me_d0i3_exit_sync - perform d0i3 exit procedure
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+static int mei_me_d0i3_exit_sync(struct mei_device *dev)
+{
+ struct mei_me_hw *hw = to_me_hw(dev);
+ unsigned long timeout = mei_secs_to_jiffies(MEI_D0I3_TIMEOUT);
+ int ret;
+ u32 reg;
+
+ dev->pg_event = MEI_PG_EVENT_INTR_WAIT;
+
+ reg = mei_me_d0i3c_read(dev);
+ if (!(reg & H_D0I3C_I3)) {
+ /* we are not in d0i3, nothing to do */
+ dev_dbg(dev->dev, "d0i3 exit not needed\n");
+ ret = 0;
+ goto off;
+ }
+
+ reg = mei_me_d0i3_unset(dev);
+ if (!(reg & H_D0I3C_CIP)) {
+ dev_dbg(dev->dev, "d0i3 exit wait not needed\n");
+ ret = 0;
+ goto off;
+ }
+
+ mutex_unlock(&dev->device_lock);
+ wait_event_timeout(dev->wait_pg,
+ dev->pg_event == MEI_PG_EVENT_INTR_RECEIVED, timeout);
+ mutex_lock(&dev->device_lock);
+
+ if (dev->pg_event != MEI_PG_EVENT_INTR_RECEIVED) {
+ reg = mei_me_d0i3c_read(dev);
+ if (reg & H_D0I3C_I3) {
+ ret = -ETIME;
+ goto out;
+ }
+ }
+
+ ret = 0;
+off:
+ hw->pg_state = MEI_PG_OFF;
+out:
+ dev->pg_event = MEI_PG_EVENT_IDLE;
+
+ dev_dbg(dev->dev, "d0i3 exit ret = %d\n", ret);
+ return ret;
+}
+
+/**
+ * mei_me_pg_legacy_intr - perform legacy pg processing
+ * in interrupt thread handler
*
* @dev: the device structure
*/
-static void mei_me_pg_intr(struct mei_device *dev)
+static void mei_me_pg_legacy_intr(struct mei_device *dev)
{
struct mei_me_hw *hw = to_me_hw(dev);
@@ -752,6 +948,162 @@
}
/**
+ * mei_me_d0i3_intr - perform d0i3 processing in interrupt thread handler
+ *
+ * @dev: the device structure
+ */
+static void mei_me_d0i3_intr(struct mei_device *dev)
+{
+ struct mei_me_hw *hw = to_me_hw(dev);
+
+ if (dev->pg_event == MEI_PG_EVENT_INTR_WAIT &&
+ (hw->intr_source & H_D0I3C_IS)) {
+ dev->pg_event = MEI_PG_EVENT_INTR_RECEIVED;
+ if (hw->pg_state == MEI_PG_ON) {
+ hw->pg_state = MEI_PG_OFF;
+ if (dev->hbm_state != MEI_HBM_IDLE) {
+ /*
+ * force H_RDY because it could be
+ * wiped off during PG
+ */
+ dev_dbg(dev->dev, "d0i3 set host ready\n");
+ mei_me_host_set_ready(dev);
+ }
+ } else {
+ hw->pg_state = MEI_PG_ON;
+ }
+
+ wake_up(&dev->wait_pg);
+ }
+
+ if (hw->pg_state == MEI_PG_ON && (hw->intr_source & H_IS)) {
+ /*
+ * HW sent some data and we are in D0i3, so
+ * we got here because of HW initiated exit from D0i3.
+ * Start runtime pm resume sequence to exit low power state.
+ */
+ dev_dbg(dev->dev, "d0i3 want resume\n");
+ mei_hbm_pg_resume(dev);
+ }
+}
+
+/**
+ * mei_me_pg_intr - perform pg processing in interrupt thread handler
+ *
+ * @dev: the device structure
+ */
+static void mei_me_pg_intr(struct mei_device *dev)
+{
+ struct mei_me_hw *hw = to_me_hw(dev);
+
+ if (hw->d0i3_supported)
+ mei_me_d0i3_intr(dev);
+ else
+ mei_me_pg_legacy_intr(dev);
+}
+
+/**
+ * mei_me_pg_enter_sync - perform runtime pm entry procedure
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+int mei_me_pg_enter_sync(struct mei_device *dev)
+{
+ struct mei_me_hw *hw = to_me_hw(dev);
+
+ if (hw->d0i3_supported)
+ return mei_me_d0i3_enter_sync(dev);
+ else
+ return mei_me_pg_legacy_enter_sync(dev);
+}
+
+/**
+ * mei_me_pg_exit_sync - perform runtime pm exit procedure
+ *
+ * @dev: the device structure
+ *
+ * Return: 0 on success an error code otherwise
+ */
+int mei_me_pg_exit_sync(struct mei_device *dev)
+{
+ struct mei_me_hw *hw = to_me_hw(dev);
+
+ if (hw->d0i3_supported)
+ return mei_me_d0i3_exit_sync(dev);
+ else
+ return mei_me_pg_legacy_exit_sync(dev);
+}
+
+/**
+ * mei_me_hw_reset - resets fw via mei csr register.
+ *
+ * @dev: the device structure
+ * @intr_enable: if interrupt should be enabled after reset.
+ *
+ * Return: 0 on success an error code otherwise
+ */
+static int mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
+{
+ struct mei_me_hw *hw = to_me_hw(dev);
+ int ret;
+ u32 hcsr;
+
+ if (intr_enable) {
+ mei_me_intr_enable(dev);
+ if (hw->d0i3_supported) {
+ ret = mei_me_d0i3_exit_sync(dev);
+ if (ret)
+ return ret;
+ }
+ }
+
+ hcsr = mei_hcsr_read(dev);
+ /* H_RST may be found lit before reset is started,
+ * for example if preceding reset flow hasn't completed.
+ * In that case asserting H_RST will be ignored, therefore
+ * we need to clean H_RST bit to start a successful reset sequence.
+ */
+ if ((hcsr & H_RST) == H_RST) {
+ dev_warn(dev->dev, "H_RST is set = 0x%08X", hcsr);
+ hcsr &= ~H_RST;
+ mei_hcsr_set(dev, hcsr);
+ hcsr = mei_hcsr_read(dev);
+ }
+
+ hcsr |= H_RST | H_IG | H_CSR_IS_MASK;
+
+ if (!intr_enable)
+ hcsr &= ~H_CSR_IE_MASK;
+
+ dev->recvd_hw_ready = false;
+ mei_hcsr_write(dev, hcsr);
+
+ /*
+ * Host reads the H_CSR once to ensure that the
+ * posted write to H_CSR completes.
+ */
+ hcsr = mei_hcsr_read(dev);
+
+ if ((hcsr & H_RST) == 0)
+ dev_warn(dev->dev, "H_RST is not set = 0x%08X", hcsr);
+
+ if ((hcsr & H_RDY) == H_RDY)
+ dev_warn(dev->dev, "H_RDY is not cleared 0x%08X", hcsr);
+
+ if (!intr_enable) {
+ mei_me_hw_reset_release(dev);
+ if (hw->d0i3_supported) {
+ ret = mei_me_d0i3_enter(dev);
+ if (ret)
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/**
* mei_me_irq_quick_handler - The ISR of the MEI device
*
* @irq: The irq number
@@ -759,16 +1111,20 @@
*
* Return: irqreturn_t
*/
-
irqreturn_t mei_me_irq_quick_handler(int irq, void *dev_id)
{
- struct mei_device *dev = (struct mei_device *) dev_id;
- u32 hcsr = mei_hcsr_read(dev);
+ struct mei_device *dev = (struct mei_device *)dev_id;
+ struct mei_me_hw *hw = to_me_hw(dev);
+ u32 hcsr;
- if ((hcsr & H_IS) != H_IS)
+ hcsr = mei_hcsr_read(dev);
+ if (!(hcsr & H_CSR_IS_MASK))
return IRQ_NONE;
- /* clear H_IS bit in H_CSR */
+ hw->intr_source = hcsr & H_CSR_IS_MASK;
+ dev_dbg(dev->dev, "interrupt source 0x%08X.\n", hw->intr_source);
+
+ /* clear H_IS and H_D0I3C_IS bits in H_CSR to clear the interrupts */
mei_hcsr_write(dev, hcsr);
return IRQ_WAKE_THREAD;
@@ -796,11 +1152,6 @@
mutex_lock(&dev->device_lock);
mei_io_list_init(&complete_list);
- /* Ack the interrupt here
- * In case of MSI we don't go through the quick handler */
- if (pci_dev_msi_enabled(to_pci_dev(dev->dev)))
- mei_clear_interrupts(dev);
-
/* check if ME wants a reset */
if (!mei_hw_is_ready(dev) && dev->dev_state != MEI_DEV_RESETTING) {
dev_warn(dev->dev, "FW not ready: resetting.\n");
diff --git a/drivers/misc/mei/hw-me.h b/drivers/misc/mei/hw-me.h
index 6022d52..2ee14dc 100644
--- a/drivers/misc/mei/hw-me.h
+++ b/drivers/misc/mei/hw-me.h
@@ -50,13 +50,17 @@
* struct mei_me_hw - me hw specific data
*
* @cfg: per device generation config and ops
- * @mem_addr: io memory address
- * @pg_state: power gating state
+ * @mem_addr: io memory address
+ * @intr_source: interrupt source
+ * @pg_state: power gating state
+ * @d0i3_supported: di03 support
*/
struct mei_me_hw {
const struct mei_cfg *cfg;
void __iomem *mem_addr;
+ u32 intr_source;
enum mei_pg_state pg_state;
+ bool d0i3_supported;
};
#define to_me_hw(dev) (struct mei_me_hw *)((dev)->hw)
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index 16fef6d..4cebde8 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -31,14 +31,15 @@
#define MEI_IAMTHIF_STALL_TIMER 12 /* HPS */
#define MEI_IAMTHIF_READ_TIMER 10 /* HPS */
-#define MEI_PGI_TIMEOUT 1 /* PG Isolation time response 1 sec */
-#define MEI_HBM_TIMEOUT 1 /* 1 second */
+#define MEI_PGI_TIMEOUT 1 /* PG Isolation time response 1 sec */
+#define MEI_D0I3_TIMEOUT 5 /* D0i3 set/unset max response time */
+#define MEI_HBM_TIMEOUT 1 /* 1 second */
/*
* MEI Version
*/
-#define HBM_MINOR_VERSION 1
-#define HBM_MAJOR_VERSION 1
+#define HBM_MINOR_VERSION 0
+#define HBM_MAJOR_VERSION 2
/*
* MEI version with PGI support
@@ -46,6 +47,24 @@
#define HBM_MINOR_VERSION_PGI 1
#define HBM_MAJOR_VERSION_PGI 1
+/*
+ * MEI version with Dynamic clients support
+ */
+#define HBM_MINOR_VERSION_DC 0
+#define HBM_MAJOR_VERSION_DC 2
+
+/*
+ * MEI version with disconnect on connection timeout support
+ */
+#define HBM_MINOR_VERSION_DOT 0
+#define HBM_MAJOR_VERSION_DOT 2
+
+/*
+ * MEI version with notifcation support
+ */
+#define HBM_MINOR_VERSION_EV 0
+#define HBM_MAJOR_VERSION_EV 2
+
/* Host bus message command opcode */
#define MEI_HBM_CMD_OP_MSK 0x7f
/* Host bus message command RESPONSE */
@@ -81,6 +100,13 @@
#define MEI_PG_ISOLATION_EXIT_REQ_CMD 0x0b
#define MEI_PG_ISOLATION_EXIT_RES_CMD 0x8b
+#define MEI_HBM_ADD_CLIENT_REQ_CMD 0x0f
+#define MEI_HBM_ADD_CLIENT_RES_CMD 0x8f
+
+#define MEI_HBM_NOTIFY_REQ_CMD 0x10
+#define MEI_HBM_NOTIFY_RES_CMD 0x90
+#define MEI_HBM_NOTIFICATION_CMD 0x11
+
/*
* MEI Stop Reason
* used by hbm_host_stop_request.reason
@@ -136,6 +162,7 @@
MEI_CL_CONN_ALREADY_STARTED = MEI_HBMS_ALREADY_EXISTS,
MEI_CL_CONN_OUT_OF_RESOURCES = MEI_HBMS_REJECTED,
MEI_CL_CONN_MESSAGE_SMALL = MEI_HBMS_INVALID_PARAMETER,
+ MEI_CL_CONN_NOT_ALLOWED = MEI_HBMS_NOT_ALLOWED,
};
/*
@@ -213,9 +240,17 @@
u8 reserved[2];
} __packed;
+/**
+ * struct hbm_host_enum_request - enumeration request from host to fw
+ *
+ * @hbm_cmd: bus message command header
+ * @allow_add: allow dynamic clients add HBM version >= 2.0
+ * @reserved: reserved
+ */
struct hbm_host_enum_request {
u8 hbm_cmd;
- u8 reserved[3];
+ u8 allow_add;
+ u8 reserved[2];
} __packed;
struct hbm_host_enum_response {
@@ -248,6 +283,38 @@
} __packed;
/**
+ * struct hbm_add_client_request - request to add a client
+ * might be sent by fw after enumeration has already completed
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @reserved: reserved
+ * @client_properties: client properties
+ */
+struct hbm_add_client_request {
+ u8 hbm_cmd;
+ u8 me_addr;
+ u8 reserved[2];
+ struct mei_client_properties client_properties;
+} __packed;
+
+/**
+ * struct hbm_add_client_response - response to add a client
+ * sent by the host to report client addition status to fw
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @status: if HBMS_SUCCESS then the client can now accept connections.
+ * @reserved: reserved
+ */
+struct hbm_add_client_response {
+ u8 hbm_cmd;
+ u8 me_addr;
+ u8 status;
+ u8 reserved[1];
+} __packed;
+
+/**
* struct hbm_power_gate - power gate request/response
*
* @hbm_cmd: bus message command header
@@ -298,5 +365,62 @@
u8 reserved[MEI_FC_MESSAGE_RESERVED_LENGTH];
} __packed;
+#define MEI_HBM_NOTIFICATION_START 1
+#define MEI_HBM_NOTIFICATION_STOP 0
+/**
+ * struct hbm_notification_request - start/stop notification request
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @host_addr: address of the client in the driver
+ * @start: start = 1 or stop = 0 asynchronous notifications
+ */
+struct hbm_notification_request {
+ u8 hbm_cmd;
+ u8 me_addr;
+ u8 host_addr;
+ u8 start;
+} __packed;
+
+/**
+ * struct hbm_notification_response - start/stop notification response
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @host_addr: - address of the client in the driver
+ * @status: (mei_hbm_status) response status for the request
+ * - MEI_HBMS_SUCCESS: successful stop/start
+ * - MEI_HBMS_CLIENT_NOT_FOUND: if the connection could not be found.
+ * - MEI_HBMS_ALREADY_STARTED: for start requests for a previously
+ * started notification.
+ * - MEI_HBMS_NOT_STARTED: for stop request for a connected client for whom
+ * asynchronous notifications are currently disabled.
+ *
+ * @start: start = 1 or stop = 0 asynchronous notifications
+ * @reserved: reserved
+ */
+struct hbm_notification_response {
+ u8 hbm_cmd;
+ u8 me_addr;
+ u8 host_addr;
+ u8 status;
+ u8 start;
+ u8 reserved[3];
+} __packed;
+
+/**
+ * struct hbm_notification - notification event
+ *
+ * @hbm_cmd: bus message command header
+ * @me_addr: address of the client in ME
+ * @host_addr: address of the client in the driver
+ * @reserved: reserved for alignment
+ */
+struct hbm_notification {
+ u8 hbm_cmd;
+ u8 me_addr;
+ u8 host_addr;
+ u8 reserved[1];
+} __packed;
#endif
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
index 00c3865..e374661 100644
--- a/drivers/misc/mei/init.c
+++ b/drivers/misc/mei/init.c
@@ -331,7 +331,7 @@
mei_cancel_work(dev);
- mei_nfc_host_exit(dev);
+ mei_cl_bus_remove_devices(dev);
mutex_lock(&dev->device_lock);
@@ -390,6 +390,7 @@
INIT_LIST_HEAD(&dev->me_clients);
mutex_init(&dev->device_lock);
init_rwsem(&dev->me_clients_rwsem);
+ mutex_init(&dev->cl_bus_lock);
init_waitqueue_head(&dev->wait_hw_ready);
init_waitqueue_head(&dev->wait_pg);
init_waitqueue_head(&dev->wait_hbm_start);
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 3f34052..c418d78 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -403,6 +403,13 @@
if (ret)
return ret;
break;
+
+ case MEI_FOP_NOTIFY_START:
+ case MEI_FOP_NOTIFY_STOP:
+ ret = mei_cl_irq_notify(cl, cb, cmpl_list);
+ if (ret)
+ return ret;
+ break;
default:
BUG();
}
@@ -424,6 +431,24 @@
EXPORT_SYMBOL_GPL(mei_irq_write_handler);
+/**
+ * mei_connect_timeout - connect/disconnect timeouts
+ *
+ * @cl: host client
+ */
+static void mei_connect_timeout(struct mei_cl *cl)
+{
+ struct mei_device *dev = cl->dev;
+
+ if (cl->state == MEI_FILE_CONNECTING) {
+ if (dev->hbm_f_dot_supported) {
+ cl->state = MEI_FILE_DISCONNECT_REQUIRED;
+ wake_up(&cl->wait);
+ return;
+ }
+ }
+ mei_reset(dev);
+}
/**
* mei_timer - timer function.
@@ -464,7 +489,7 @@
if (cl->timer_count) {
if (--cl->timer_count == 0) {
dev_err(dev->dev, "timer: connect/disconnect timeout.\n");
- mei_reset(dev);
+ mei_connect_timeout(cl);
goto out;
}
}
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 8eb0a95..b2f2486 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -446,6 +446,45 @@
}
/**
+ * mei_ioctl_client_notify_request -
+ * propagate event notification request to client
+ *
+ * @file: pointer to file structure
+ * @request: 0 - disable, 1 - enable
+ *
+ * Return: 0 on success , <0 on error
+ */
+static int mei_ioctl_client_notify_request(struct file *file, u32 request)
+{
+ struct mei_cl *cl = file->private_data;
+
+ return mei_cl_notify_request(cl, file, request);
+}
+
+/**
+ * mei_ioctl_client_notify_get - wait for notification request
+ *
+ * @file: pointer to file structure
+ * @notify_get: 0 - disable, 1 - enable
+ *
+ * Return: 0 on success , <0 on error
+ */
+static int mei_ioctl_client_notify_get(struct file *file, u32 *notify_get)
+{
+ struct mei_cl *cl = file->private_data;
+ bool notify_ev;
+ bool block = (file->f_flags & O_NONBLOCK) == 0;
+ int rets;
+
+ rets = mei_cl_notify_get(cl, block, ¬ify_ev);
+ if (rets)
+ return rets;
+
+ *notify_get = notify_ev ? 1 : 0;
+ return 0;
+}
+
+/**
* mei_ioctl - the IOCTL function
*
* @file: pointer to file structure
@@ -459,6 +498,7 @@
struct mei_device *dev;
struct mei_cl *cl = file->private_data;
struct mei_connect_client_data connect_data;
+ u32 notify_get, notify_req;
int rets;
@@ -499,6 +539,33 @@
break;
+ case IOCTL_MEI_NOTIFY_SET:
+ dev_dbg(dev->dev, ": IOCTL_MEI_NOTIFY_SET.\n");
+ if (copy_from_user(¬ify_req,
+ (char __user *)data, sizeof(notify_req))) {
+ dev_dbg(dev->dev, "failed to copy data from userland\n");
+ rets = -EFAULT;
+ goto out;
+ }
+ rets = mei_ioctl_client_notify_request(file, notify_req);
+ break;
+
+ case IOCTL_MEI_NOTIFY_GET:
+ dev_dbg(dev->dev, ": IOCTL_MEI_NOTIFY_GET.\n");
+ rets = mei_ioctl_client_notify_get(file, ¬ify_get);
+ if (rets)
+ goto out;
+
+ dev_dbg(dev->dev, "copy connect data to user\n");
+ if (copy_to_user((char __user *)data,
+ ¬ify_get, sizeof(notify_get))) {
+ dev_dbg(dev->dev, "failed to copy data to userland\n");
+ rets = -EFAULT;
+ goto out;
+
+ }
+ break;
+
default:
dev_err(dev->dev, ": unsupported ioctl %d.\n", cmd);
rets = -ENOIOCTLCMD;
@@ -541,6 +608,7 @@
struct mei_cl *cl = file->private_data;
struct mei_device *dev;
unsigned int mask = 0;
+ bool notify_en;
if (WARN_ON(!cl || !cl->dev))
return POLLERR;
@@ -549,6 +617,7 @@
mutex_lock(&dev->device_lock);
+ notify_en = cl->notify_en && (req_events & POLLPRI);
if (dev->dev_state != MEI_DEV_ENABLED ||
!mei_cl_is_connected(cl)) {
@@ -561,6 +630,12 @@
goto out;
}
+ if (notify_en) {
+ poll_wait(file, &cl->ev_wait, wait);
+ if (cl->notify_ev)
+ mask |= POLLPRI;
+ }
+
if (req_events & (POLLIN | POLLRDNORM)) {
poll_wait(file, &cl->rx_wait, wait);
@@ -576,6 +651,26 @@
}
/**
+ * mei_fasync - asynchronous io support
+ *
+ * @fd: file descriptor
+ * @file: pointer to file structure
+ * @band: band bitmap
+ *
+ * Return: poll mask
+ */
+static int mei_fasync(int fd, struct file *file, int band)
+{
+
+ struct mei_cl *cl = file->private_data;
+
+ if (!mei_cl_is_connected(cl))
+ return POLLERR;
+
+ return fasync_helper(fd, file, band, &cl->ev_async);
+}
+
+/**
* fw_status_show - mei device attribute show method
*
* @device: device pointer
@@ -627,6 +722,7 @@
.release = mei_release,
.write = mei_write,
.poll = mei_poll,
+ .fasync = mei_fasync,
.llseek = no_llseek
};
@@ -682,7 +778,7 @@
/* Fill in the data structures */
devno = MKDEV(MAJOR(mei_devt), dev->minor);
cdev_init(&dev->cdev, &mei_fops);
- dev->cdev.owner = mei_fops.owner;
+ dev->cdev.owner = parent->driver->owner;
/* Add the device */
ret = cdev_add(&dev->cdev, devno, 1);
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 453f6a3..e25ee16 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -89,6 +89,7 @@
MEI_FILE_CONNECTED,
MEI_FILE_DISCONNECTING,
MEI_FILE_DISCONNECT_REPLY,
+ MEI_FILE_DISCONNECT_REQUIRED,
MEI_FILE_DISCONNECTED,
};
@@ -135,6 +136,8 @@
* @MEI_FOP_CONNECT: connect
* @MEI_FOP_DISCONNECT: disconnect
* @MEI_FOP_DISCONNECT_RSP: disconnect response
+ * @MEI_FOP_NOTIFY_START: start notification
+ * @MEI_FOP_NOTIFY_STOP: stop notification
*/
enum mei_cb_file_ops {
MEI_FOP_READ = 0,
@@ -142,6 +145,8 @@
MEI_FOP_CONNECT,
MEI_FOP_DISCONNECT,
MEI_FOP_DISCONNECT_RSP,
+ MEI_FOP_NOTIFY_START,
+ MEI_FOP_NOTIFY_STOP,
};
/*
@@ -178,7 +183,7 @@
* @client_id: me client id
* @mei_flow_ctrl_creds: flow control credits
* @connect_count: number connections to this client
- * @reserved: reserved
+ * @bus_added: added to bus
*/
struct mei_me_client {
struct list_head list;
@@ -187,7 +192,7 @@
u8 client_id;
u8 mei_flow_ctrl_creds;
u8 connect_count;
- u8 reserved;
+ u8 bus_added;
};
@@ -230,18 +235,21 @@
* @tx_wait: wait queue for tx completion
* @rx_wait: wait queue for rx completion
* @wait: wait queue for management operation
+ * @ev_wait: notification wait queue
+ * @ev_async: event async notification
* @status: connection status
* @me_cl: fw client connected
* @host_client_id: host id
* @mei_flow_ctrl_creds: transmit flow credentials
* @timer_count: watchdog timer for operation completion
* @reserved: reserved for alignment
+ * @notify_en: notification - enabled/disabled
+ * @notify_ev: pending notification event
* @writing_state: state of the tx
* @rd_pending: pending read credits
* @rd_completed: completed read
*
- * @device: device on the mei client bus
- * @device_link: link to bus clients
+ * @cldev: device on the mei client bus
*/
struct mei_cl {
struct list_head link;
@@ -250,19 +258,21 @@
wait_queue_head_t tx_wait;
wait_queue_head_t rx_wait;
wait_queue_head_t wait;
+ wait_queue_head_t ev_wait;
+ struct fasync_struct *ev_async;
int status;
struct mei_me_client *me_cl;
u8 host_client_id;
u8 mei_flow_ctrl_creds;
u8 timer_count;
u8 reserved;
+ u8 notify_en;
+ u8 notify_ev;
enum mei_file_transaction_states writing_state;
struct list_head rd_pending;
struct list_head rd_completed;
- /* MEI CL bus data */
- struct mei_cl_device *device;
- struct list_head device_link;
+ struct mei_cl_device *cldev;
};
/** struct mei_hw_ops
@@ -329,21 +339,16 @@
};
/* MEI bus API*/
-
-struct mei_cl_device *mei_cl_add_device(struct mei_device *dev,
- struct mei_me_client *me_cl,
- struct mei_cl *cl,
- char *name);
-void mei_cl_remove_device(struct mei_cl_device *device);
-
+void mei_cl_bus_rescan(struct mei_device *bus);
+void mei_cl_dev_fixup(struct mei_cl_device *dev);
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
bool blocking);
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length);
void mei_cl_bus_rx_event(struct mei_cl *cl);
-void mei_cl_bus_remove_devices(struct mei_device *dev);
+void mei_cl_bus_notify_event(struct mei_cl *cl);
+void mei_cl_bus_remove_devices(struct mei_device *bus);
int mei_cl_bus_init(void);
void mei_cl_bus_exit(void);
-struct mei_cl *mei_cl_bus_find_cl_by_uuid(struct mei_device *dev, uuid_le uuid);
/**
* enum mei_pg_event - power gating transition events
@@ -416,7 +421,10 @@
* @wr_msg : the buffer for hbm control messages
*
* @version : HBM protocol version in use
- * @hbm_f_pg_supported : hbm feature pgi protocol
+ * @hbm_f_pg_supported : hbm feature pgi protocol
+ * @hbm_f_dc_supported : hbm feature dynamic clients
+ * @hbm_f_dot_supported : hbm feature disconnect on timeout
+ * @hbm_f_ev_supported : hbm feature event notification
*
* @me_clients_rwsem: rw lock over me_clients list
* @me_clients : list of FW clients
@@ -447,6 +455,7 @@
* @reset_work : work item for the device reset
*
* @device_list : mei client bus list
+ * @cl_bus_lock : client bus list lock
*
* @dbgfs_dir : debugfs mei root directory
*
@@ -509,6 +518,9 @@
struct hbm_version version;
unsigned int hbm_f_pg_supported:1;
+ unsigned int hbm_f_dc_supported:1;
+ unsigned int hbm_f_dot_supported:1;
+ unsigned int hbm_f_ev_supported:1;
struct rw_semaphore me_clients_rwsem;
struct list_head me_clients;
@@ -543,6 +555,7 @@
/* List of bus devices */
struct list_head device_list;
+ struct mutex cl_bus_lock;
#if IS_ENABLED(CONFIG_DEBUG_FS)
struct dentry *dbgfs_dir;
diff --git a/drivers/misc/mei/nfc.c b/drivers/misc/mei/nfc.c
deleted file mode 100644
index 290ef30..0000000
--- a/drivers/misc/mei/nfc.c
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- *
- * Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2013, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-
-#include <linux/mei_cl_bus.h>
-
-#include "mei_dev.h"
-#include "client.h"
-
-struct mei_nfc_cmd {
- u8 command;
- u8 status;
- u16 req_id;
- u32 reserved;
- u16 data_size;
- u8 sub_command;
- u8 data[];
-} __packed;
-
-struct mei_nfc_reply {
- u8 command;
- u8 status;
- u16 req_id;
- u32 reserved;
- u16 data_size;
- u8 sub_command;
- u8 reply_status;
- u8 data[];
-} __packed;
-
-struct mei_nfc_if_version {
- u8 radio_version_sw[3];
- u8 reserved[3];
- u8 radio_version_hw[3];
- u8 i2c_addr;
- u8 fw_ivn;
- u8 vendor_id;
- u8 radio_type;
-} __packed;
-
-struct mei_nfc_connect {
- u8 fw_ivn;
- u8 vendor_id;
-} __packed;
-
-struct mei_nfc_connect_resp {
- u8 fw_ivn;
- u8 vendor_id;
- u16 me_major;
- u16 me_minor;
- u16 me_hotfix;
- u16 me_build;
-} __packed;
-
-struct mei_nfc_hci_hdr {
- u8 cmd;
- u8 status;
- u16 req_id;
- u32 reserved;
- u16 data_size;
-} __packed;
-
-#define MEI_NFC_CMD_MAINTENANCE 0x00
-#define MEI_NFC_CMD_HCI_SEND 0x01
-#define MEI_NFC_CMD_HCI_RECV 0x02
-
-#define MEI_NFC_SUBCMD_CONNECT 0x00
-#define MEI_NFC_SUBCMD_IF_VERSION 0x01
-
-#define MEI_NFC_HEADER_SIZE 10
-
-/**
- * struct mei_nfc_dev - NFC mei device
- *
- * @me_cl: NFC me client
- * @cl: NFC host client
- * @cl_info: NFC info host client
- * @init_work: perform connection to the info client
- * @fw_ivn: NFC Interface Version Number
- * @vendor_id: NFC manufacturer ID
- * @radio_type: NFC radio type
- * @bus_name: bus name
- *
- */
-struct mei_nfc_dev {
- struct mei_me_client *me_cl;
- struct mei_cl *cl;
- struct mei_cl *cl_info;
- struct work_struct init_work;
- u8 fw_ivn;
- u8 vendor_id;
- u8 radio_type;
- char *bus_name;
-};
-
-/* UUIDs for NFC F/W clients */
-const uuid_le mei_nfc_guid = UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50,
- 0x94, 0xd4, 0x50, 0x26,
- 0x67, 0x23, 0x77, 0x5c);
-
-static const uuid_le mei_nfc_info_guid = UUID_LE(0xd2de1625, 0x382d, 0x417d,
- 0x48, 0xa4, 0xef, 0xab,
- 0xba, 0x8a, 0x12, 0x06);
-
-/* Vendors */
-#define MEI_NFC_VENDOR_INSIDE 0x00
-#define MEI_NFC_VENDOR_NXP 0x01
-
-/* Radio types */
-#define MEI_NFC_VENDOR_INSIDE_UREAD 0x00
-#define MEI_NFC_VENDOR_NXP_PN544 0x01
-
-static void mei_nfc_free(struct mei_nfc_dev *ndev)
-{
- if (!ndev)
- return;
-
- if (ndev->cl) {
- list_del(&ndev->cl->device_link);
- mei_cl_unlink(ndev->cl);
- kfree(ndev->cl);
- }
-
- if (ndev->cl_info) {
- list_del(&ndev->cl_info->device_link);
- mei_cl_unlink(ndev->cl_info);
- kfree(ndev->cl_info);
- }
-
- mei_me_cl_put(ndev->me_cl);
- kfree(ndev);
-}
-
-static int mei_nfc_build_bus_name(struct mei_nfc_dev *ndev)
-{
- struct mei_device *dev;
-
- if (!ndev->cl)
- return -ENODEV;
-
- dev = ndev->cl->dev;
-
- switch (ndev->vendor_id) {
- case MEI_NFC_VENDOR_INSIDE:
- switch (ndev->radio_type) {
- case MEI_NFC_VENDOR_INSIDE_UREAD:
- ndev->bus_name = "microread";
- return 0;
-
- default:
- dev_err(dev->dev, "Unknown radio type 0x%x\n",
- ndev->radio_type);
-
- return -EINVAL;
- }
-
- case MEI_NFC_VENDOR_NXP:
- switch (ndev->radio_type) {
- case MEI_NFC_VENDOR_NXP_PN544:
- ndev->bus_name = "pn544";
- return 0;
- default:
- dev_err(dev->dev, "Unknown radio type 0x%x\n",
- ndev->radio_type);
-
- return -EINVAL;
- }
-
- default:
- dev_err(dev->dev, "Unknown vendor ID 0x%x\n",
- ndev->vendor_id);
-
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int mei_nfc_if_version(struct mei_nfc_dev *ndev)
-{
- struct mei_device *dev;
- struct mei_cl *cl;
-
- struct mei_nfc_cmd cmd;
- struct mei_nfc_reply *reply = NULL;
- struct mei_nfc_if_version *version;
- size_t if_version_length;
- int bytes_recv, ret;
-
- cl = ndev->cl_info;
- dev = cl->dev;
-
- memset(&cmd, 0, sizeof(struct mei_nfc_cmd));
- cmd.command = MEI_NFC_CMD_MAINTENANCE;
- cmd.data_size = 1;
- cmd.sub_command = MEI_NFC_SUBCMD_IF_VERSION;
-
- ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(struct mei_nfc_cmd), 1);
- if (ret < 0) {
- dev_err(dev->dev, "Could not send IF version cmd\n");
- return ret;
- }
-
- /* to be sure on the stack we alloc memory */
- if_version_length = sizeof(struct mei_nfc_reply) +
- sizeof(struct mei_nfc_if_version);
-
- reply = kzalloc(if_version_length, GFP_KERNEL);
- if (!reply)
- return -ENOMEM;
-
- bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
- if (bytes_recv < 0 || bytes_recv < sizeof(struct mei_nfc_reply)) {
- dev_err(dev->dev, "Could not read IF version\n");
- ret = -EIO;
- goto err;
- }
-
- version = (struct mei_nfc_if_version *)reply->data;
-
- ndev->fw_ivn = version->fw_ivn;
- ndev->vendor_id = version->vendor_id;
- ndev->radio_type = version->radio_type;
-
-err:
- kfree(reply);
- return ret;
-}
-
-static void mei_nfc_init(struct work_struct *work)
-{
- struct mei_device *dev;
- struct mei_cl_device *cldev;
- struct mei_nfc_dev *ndev;
- struct mei_cl *cl_info;
- struct mei_me_client *me_cl_info;
-
- ndev = container_of(work, struct mei_nfc_dev, init_work);
-
- cl_info = ndev->cl_info;
- dev = cl_info->dev;
-
- mutex_lock(&dev->device_lock);
-
- /* check for valid client id */
- me_cl_info = mei_me_cl_by_uuid(dev, &mei_nfc_info_guid);
- if (!me_cl_info) {
- mutex_unlock(&dev->device_lock);
- dev_info(dev->dev, "nfc: failed to find the info client\n");
- goto err;
- }
-
- if (mei_cl_connect(cl_info, me_cl_info, NULL) < 0) {
- mei_me_cl_put(me_cl_info);
- mutex_unlock(&dev->device_lock);
- dev_err(dev->dev, "Could not connect to the NFC INFO ME client");
-
- goto err;
- }
- mei_me_cl_put(me_cl_info);
- mutex_unlock(&dev->device_lock);
-
- if (mei_nfc_if_version(ndev) < 0) {
- dev_err(dev->dev, "Could not get the NFC interface version");
-
- goto err;
- }
-
- dev_info(dev->dev, "NFC MEI VERSION: IVN 0x%x Vendor ID 0x%x Type 0x%x\n",
- ndev->fw_ivn, ndev->vendor_id, ndev->radio_type);
-
- mutex_lock(&dev->device_lock);
-
- if (mei_cl_disconnect(cl_info) < 0) {
- mutex_unlock(&dev->device_lock);
- dev_err(dev->dev, "Could not disconnect the NFC INFO ME client");
-
- goto err;
- }
-
- mutex_unlock(&dev->device_lock);
-
- if (mei_nfc_build_bus_name(ndev) < 0) {
- dev_err(dev->dev, "Could not build the bus ID name\n");
- return;
- }
-
- cldev = mei_cl_add_device(dev, ndev->me_cl, ndev->cl,
- ndev->bus_name);
- if (!cldev) {
- dev_err(dev->dev, "Could not add the NFC device to the MEI bus\n");
-
- goto err;
- }
-
- cldev->priv_data = ndev;
-
-
- return;
-
-err:
- mutex_lock(&dev->device_lock);
- mei_nfc_free(ndev);
- mutex_unlock(&dev->device_lock);
-
-}
-
-
-int mei_nfc_host_init(struct mei_device *dev, struct mei_me_client *me_cl)
-{
- struct mei_nfc_dev *ndev;
- struct mei_cl *cl_info, *cl;
- int ret;
-
-
- /* in case of internal reset bail out
- * as the device is already setup
- */
- cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
- if (cl)
- return 0;
-
- ndev = kzalloc(sizeof(struct mei_nfc_dev), GFP_KERNEL);
- if (!ndev) {
- ret = -ENOMEM;
- goto err;
- }
-
- ndev->me_cl = mei_me_cl_get(me_cl);
- if (!ndev->me_cl) {
- ret = -ENODEV;
- goto err;
- }
-
- cl_info = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
- if (IS_ERR(cl_info)) {
- ret = PTR_ERR(cl_info);
- goto err;
- }
-
- list_add_tail(&cl_info->device_link, &dev->device_list);
-
- ndev->cl_info = cl_info;
-
- cl = mei_cl_alloc_linked(dev, MEI_HOST_CLIENT_ID_ANY);
- if (IS_ERR(cl)) {
- ret = PTR_ERR(cl);
- goto err;
- }
-
- list_add_tail(&cl->device_link, &dev->device_list);
-
- ndev->cl = cl;
-
- INIT_WORK(&ndev->init_work, mei_nfc_init);
- schedule_work(&ndev->init_work);
-
- return 0;
-
-err:
- mei_nfc_free(ndev);
-
- return ret;
-}
-
-void mei_nfc_host_exit(struct mei_device *dev)
-{
- struct mei_nfc_dev *ndev;
- struct mei_cl *cl;
- struct mei_cl_device *cldev;
-
- cl = mei_cl_bus_find_cl_by_uuid(dev, mei_nfc_guid);
- if (!cl)
- return;
-
- cldev = cl->device;
- if (!cldev)
- return;
-
- ndev = (struct mei_nfc_dev *)cldev->priv_data;
- if (ndev)
- cancel_work_sync(&ndev->init_work);
-
- cldev->priv_data = NULL;
-
- /* Need to remove the device here
- * since mei_nfc_free will unlink the clients
- */
- mei_cl_remove_device(cldev);
-
- mutex_lock(&dev->device_lock);
- mei_nfc_free(ndev);
- mutex_unlock(&dev->device_lock);
-}
-
-
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index 23f71f5..27678d8 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -82,6 +82,11 @@
{MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP, mei_me_pch8_cfg)},
{MEI_PCI_DEVICE(MEI_DEV_ID_WPT_LP_2, mei_me_pch8_cfg)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_SPT, mei_me_pch8_cfg)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, mei_me_pch8_cfg)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, mei_me_pch8_cfg)},
+ {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, mei_me_pch8_cfg)},
+
/* required last entry */
{0, }
};
@@ -128,6 +133,7 @@
const struct mei_cfg *cfg = (struct mei_cfg *)(ent->driver_data);
struct mei_device *dev;
struct mei_me_hw *hw;
+ unsigned int irqflags;
int err;
@@ -180,17 +186,12 @@
pci_enable_msi(pdev);
/* request and enable interrupt */
- if (pci_dev_msi_enabled(pdev))
- err = request_threaded_irq(pdev->irq,
- NULL,
- mei_me_irq_thread_handler,
- IRQF_ONESHOT, KBUILD_MODNAME, dev);
- else
- err = request_threaded_irq(pdev->irq,
+ irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
+
+ err = request_threaded_irq(pdev->irq,
mei_me_irq_quick_handler,
mei_me_irq_thread_handler,
- IRQF_SHARED, KBUILD_MODNAME, dev);
-
+ irqflags, KBUILD_MODNAME, dev);
if (err) {
dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
pdev->irq);
@@ -319,6 +320,7 @@
{
struct pci_dev *pdev = to_pci_dev(device);
struct mei_device *dev;
+ unsigned int irqflags;
int err;
dev = pci_get_drvdata(pdev);
@@ -327,17 +329,13 @@
pci_enable_msi(pdev);
+ irqflags = pci_dev_msi_enabled(pdev) ? IRQF_ONESHOT : IRQF_SHARED;
+
/* request and enable interrupt */
- if (pci_dev_msi_enabled(pdev))
- err = request_threaded_irq(pdev->irq,
- NULL,
- mei_me_irq_thread_handler,
- IRQF_ONESHOT, KBUILD_MODNAME, dev);
- else
- err = request_threaded_irq(pdev->irq,
+ err = request_threaded_irq(pdev->irq,
mei_me_irq_quick_handler,
mei_me_irq_thread_handler,
- IRQF_SHARED, KBUILD_MODNAME, dev);
+ irqflags, KBUILD_MODNAME, dev);
if (err) {
dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
diff --git a/drivers/misc/mic/scif/scif_nodeqp.c b/drivers/misc/mic/scif/scif_nodeqp.c
index 41e3bdb..6dfdae3 100644
--- a/drivers/misc/mic/scif/scif_nodeqp.c
+++ b/drivers/misc/mic/scif/scif_nodeqp.c
@@ -357,7 +357,7 @@
}
static struct scatterlist *
-scif_p2p_setsg(void __iomem *va, int page_size, int page_cnt)
+scif_p2p_setsg(phys_addr_t pa, int page_size, int page_cnt)
{
struct scatterlist *sg;
struct page *page;
@@ -368,16 +368,11 @@
return NULL;
sg_init_table(sg, page_cnt);
for (i = 0; i < page_cnt; i++) {
- page = vmalloc_to_page((void __force *)va);
- if (!page)
- goto p2p_sg_err;
+ page = pfn_to_page(pa >> PAGE_SHIFT);
sg_set_page(&sg[i], page, page_size, 0);
- va += page_size;
+ pa += page_size;
}
return sg;
-p2p_sg_err:
- kfree(sg);
- return NULL;
}
/* Init p2p mappings required to access peerdev from scifdev */
@@ -395,14 +390,14 @@
p2p = kzalloc(sizeof(*p2p), GFP_KERNEL);
if (!p2p)
return NULL;
- p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->va,
+ p2p->ppi_sg[SCIF_PPI_MMIO] = scif_p2p_setsg(psdev->mmio->pa,
PAGE_SIZE, num_mmio_pages);
if (!p2p->ppi_sg[SCIF_PPI_MMIO])
goto free_p2p;
p2p->sg_nentries[SCIF_PPI_MMIO] = num_mmio_pages;
sg_page_shift = get_order(min(psdev->aper->len, (u64)(1 << 30)));
num_aper_chunks = num_aper_pages >> (sg_page_shift - PAGE_SHIFT);
- p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->va,
+ p2p->ppi_sg[SCIF_PPI_APER] = scif_p2p_setsg(psdev->aper->pa,
1 << sg_page_shift,
num_aper_chunks);
p2p->sg_nentries[SCIF_PPI_APER] = num_aper_chunks;
diff --git a/drivers/misc/qcom-coincell.c b/drivers/misc/qcom-coincell.c
new file mode 100644
index 0000000..7b4a2da
--- /dev/null
+++ b/drivers/misc/qcom-coincell.c
@@ -0,0 +1,152 @@
+/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, Sony Mobile Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+struct qcom_coincell {
+ struct device *dev;
+ struct regmap *regmap;
+ u32 base_addr;
+};
+
+#define QCOM_COINCELL_REG_RSET 0x44
+#define QCOM_COINCELL_REG_VSET 0x45
+#define QCOM_COINCELL_REG_ENABLE 0x46
+
+#define QCOM_COINCELL_ENABLE BIT(7)
+
+static const int qcom_rset_map[] = { 2100, 1700, 1200, 800 };
+static const int qcom_vset_map[] = { 2500, 3200, 3100, 3000 };
+/* NOTE: for pm8921 and others, voltage of 2500 is 16 (10000b), not 0 */
+
+/* if enable==0, rset and vset are ignored */
+static int qcom_coincell_chgr_config(struct qcom_coincell *chgr, int rset,
+ int vset, bool enable)
+{
+ int i, j, rc;
+
+ /* if disabling, just do that and skip other operations */
+ if (!enable)
+ return regmap_write(chgr->regmap,
+ chgr->base_addr + QCOM_COINCELL_REG_ENABLE, 0);
+
+ /* find index for current-limiting resistor */
+ for (i = 0; i < ARRAY_SIZE(qcom_rset_map); i++)
+ if (rset == qcom_rset_map[i])
+ break;
+
+ if (i >= ARRAY_SIZE(qcom_rset_map)) {
+ dev_err(chgr->dev, "invalid rset-ohms value %d\n", rset);
+ return -EINVAL;
+ }
+
+ /* find index for charge voltage */
+ for (j = 0; j < ARRAY_SIZE(qcom_vset_map); j++)
+ if (vset == qcom_vset_map[j])
+ break;
+
+ if (j >= ARRAY_SIZE(qcom_vset_map)) {
+ dev_err(chgr->dev, "invalid vset-millivolts value %d\n", vset);
+ return -EINVAL;
+ }
+
+ rc = regmap_write(chgr->regmap,
+ chgr->base_addr + QCOM_COINCELL_REG_RSET, i);
+ if (rc) {
+ /*
+ * This is mainly to flag a bad base_addr (reg) from dts.
+ * Other failures writing to the registers should be
+ * extremely rare, or indicative of problems that
+ * should be reported elsewhere (eg. spmi failure).
+ */
+ dev_err(chgr->dev, "could not write to RSET register\n");
+ return rc;
+ }
+
+ rc = regmap_write(chgr->regmap,
+ chgr->base_addr + QCOM_COINCELL_REG_VSET, j);
+ if (rc)
+ return rc;
+
+ /* set 'enable' register */
+ return regmap_write(chgr->regmap,
+ chgr->base_addr + QCOM_COINCELL_REG_ENABLE,
+ QCOM_COINCELL_ENABLE);
+}
+
+static int qcom_coincell_probe(struct platform_device *pdev)
+{
+ struct device_node *node = pdev->dev.of_node;
+ struct qcom_coincell chgr;
+ u32 rset, vset;
+ bool enable;
+ int rc;
+
+ chgr.dev = &pdev->dev;
+
+ chgr.regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!chgr.regmap) {
+ dev_err(chgr.dev, "Unable to get regmap\n");
+ return -EINVAL;
+ }
+
+ rc = of_property_read_u32(node, "reg", &chgr.base_addr);
+ if (rc)
+ return rc;
+
+ enable = !of_property_read_bool(node, "qcom,charger-disable");
+
+ if (enable) {
+ rc = of_property_read_u32(node, "qcom,rset-ohms", &rset);
+ if (rc) {
+ dev_err(chgr.dev,
+ "can't find 'qcom,rset-ohms' in DT block");
+ return rc;
+ }
+
+ rc = of_property_read_u32(node, "qcom,vset-millivolts", &vset);
+ if (rc) {
+ dev_err(chgr.dev,
+ "can't find 'qcom,vset-millivolts' in DT block");
+ return rc;
+ }
+ }
+
+ return qcom_coincell_chgr_config(&chgr, rset, vset, enable);
+}
+
+static const struct of_device_id qcom_coincell_match_table[] = {
+ { .compatible = "qcom,pm8941-coincell", },
+ {}
+};
+
+MODULE_DEVICE_TABLE(of, qcom_coincell_match_table);
+
+static struct platform_driver qcom_coincell_driver = {
+ .driver = {
+ .name = "qcom-spmi-coincell",
+ .of_match_table = qcom_coincell_match_table,
+ },
+ .probe = qcom_coincell_probe,
+};
+
+module_platform_driver(qcom_coincell_driver);
+
+MODULE_DESCRIPTION("Qualcomm PMIC coincell charger driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 5027b8f..71b6455 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -36,8 +36,6 @@
#include <linux/skbuff.h>
#include <linux/ti_wilink_st.h>
#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
#define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */
static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
@@ -45,9 +43,6 @@
/**********************************************************************/
/* internal functions */
-struct ti_st_plat_data *dt_pdata;
-static struct ti_st_plat_data *get_platform_data(struct device *dev);
-
/**
* st_get_plat_device -
* function which returns the reference to the platform device
@@ -469,12 +464,7 @@
struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
pr_info(" %s", __func__);
- if (kim_gdata->kim_pdev->dev.of_node) {
- pr_debug("use device tree data");
- pdata = dt_pdata;
- } else {
- pdata = kim_gdata->kim_pdev->dev.platform_data;
- }
+ pdata = kim_gdata->kim_pdev->dev.platform_data;
do {
/* platform specific enabling code here */
@@ -482,9 +472,9 @@
pdata->chip_enable(kim_gdata);
/* Configure BT nShutdown to HIGH state */
- gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+ gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
mdelay(5); /* FIXME: a proper toggle */
- gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+ gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
mdelay(100);
/* re-initialize the completion */
reinit_completion(&kim_gdata->ldisc_installed);
@@ -534,18 +524,12 @@
{
long err = 0;
struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
- struct ti_st_plat_data *pdata;
+ struct ti_st_plat_data *pdata =
+ kim_gdata->kim_pdev->dev.platform_data;
struct tty_struct *tty = kim_gdata->core_data->tty;
reinit_completion(&kim_gdata->ldisc_installed);
- if (kim_gdata->kim_pdev->dev.of_node) {
- pr_debug("use device tree data");
- pdata = dt_pdata;
- } else
- pdata = kim_gdata->kim_pdev->dev.platform_data;
-
-
if (tty) { /* can be called before ldisc is installed */
/* Flush any pending characters in the driver and discipline. */
tty_ldisc_flush(tty);
@@ -566,11 +550,11 @@
}
/* By default configure BT nShutdown to LOW state */
- gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+ gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
mdelay(1);
- gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+ gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
mdelay(1);
- gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+ gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
/* platform specific disable */
if (pdata->chip_disable)
@@ -737,52 +721,13 @@
* board-*.c file
*/
-static const struct of_device_id kim_of_match[] = {
-{
- .compatible = "kim",
- },
- {}
-};
-MODULE_DEVICE_TABLE(of, kim_of_match);
-
-static struct ti_st_plat_data *get_platform_data(struct device *dev)
-{
- struct device_node *np = dev->of_node;
- const u32 *dt_property;
- int len;
-
- dt_pdata = kzalloc(sizeof(*dt_pdata), GFP_KERNEL);
- if (!dt_pdata)
- return NULL;
-
- dt_property = of_get_property(np, "dev_name", &len);
- if (dt_property)
- memcpy(&dt_pdata->dev_name, dt_property, len);
- of_property_read_u32(np, "nshutdown_gpio",
- &dt_pdata->nshutdown_gpio);
- of_property_read_u32(np, "flow_cntrl", &dt_pdata->flow_cntrl);
- of_property_read_u32(np, "baud_rate", &dt_pdata->baud_rate);
-
- return dt_pdata;
-}
-
static struct dentry *kim_debugfs_dir;
static int kim_probe(struct platform_device *pdev)
{
struct kim_data_s *kim_gdata;
- struct ti_st_plat_data *pdata;
+ struct ti_st_plat_data *pdata = pdev->dev.platform_data;
int err;
- if (pdev->dev.of_node)
- pdata = get_platform_data(&pdev->dev);
- else
- pdata = pdev->dev.platform_data;
-
- if (pdata == NULL) {
- dev_err(&pdev->dev, "Platform Data is missing\n");
- return -ENXIO;
- }
-
if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
/* multiple devices could exist */
st_kim_devices[pdev->id] = pdev;
@@ -863,16 +808,9 @@
static int kim_remove(struct platform_device *pdev)
{
/* free the GPIOs requested */
- struct ti_st_plat_data *pdata;
+ struct ti_st_plat_data *pdata = pdev->dev.platform_data;
struct kim_data_s *kim_gdata;
- if (pdev->dev.of_node) {
- pr_debug("use device tree data");
- pdata = dt_pdata;
- } else {
- pdata = pdev->dev.platform_data;
- }
-
kim_gdata = platform_get_drvdata(pdev);
/* Free the Bluetooth/FM/GPIO
@@ -890,22 +828,12 @@
kfree(kim_gdata);
kim_gdata = NULL;
- kfree(dt_pdata);
- dt_pdata = NULL;
-
return 0;
}
static int kim_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct ti_st_plat_data *pdata;
-
- if (pdev->dev.of_node) {
- pr_debug("use device tree data");
- pdata = dt_pdata;
- } else {
- pdata = pdev->dev.platform_data;
- }
+ struct ti_st_plat_data *pdata = pdev->dev.platform_data;
if (pdata->suspend)
return pdata->suspend(pdev, state);
@@ -915,14 +843,7 @@
static int kim_resume(struct platform_device *pdev)
{
- struct ti_st_plat_data *pdata;
-
- if (pdev->dev.of_node) {
- pr_debug("use device tree data");
- pdata = dt_pdata;
- } else {
- pdata = pdev->dev.platform_data;
- }
+ struct ti_st_plat_data *pdata = pdev->dev.platform_data;
if (pdata->resume)
return pdata->resume(pdev);
@@ -939,8 +860,6 @@
.resume = kim_resume,
.driver = {
.name = "kim",
- .owner = THIS_MODULE,
- .of_match_table = of_match_ptr(kim_of_match),
},
};
diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
index 518e1b7..93b4d67 100644
--- a/drivers/misc/ti-st/st_ll.c
+++ b/drivers/misc/ti-st/st_ll.c
@@ -26,7 +26,6 @@
#include <linux/ti_wilink_st.h>
/**********************************************************************/
-
/* internal functions */
static void send_ll_cmd(struct st_data_s *st_data,
unsigned char cmd)
@@ -54,13 +53,7 @@
/* communicate to platform about chip asleep */
kim_data = st_data->kim_data;
- if (kim_data->kim_pdev->dev.of_node) {
- pr_debug("use device tree data");
- pdata = dt_pdata;
- } else {
- pdata = kim_data->kim_pdev->dev.platform_data;
- }
-
+ pdata = kim_data->kim_pdev->dev.platform_data;
if (pdata->chip_asleep)
pdata->chip_asleep(NULL);
}
@@ -93,13 +86,7 @@
/* communicate to platform about chip wakeup */
kim_data = st_data->kim_data;
- if (kim_data->kim_pdev->dev.of_node) {
- pr_debug("use device tree data");
- pdata = dt_pdata;
- } else {
- pdata = kim_data->kim_pdev->dev.platform_data;
- }
-
+ pdata = kim_data->kim_pdev->dev.platform_data;
if (pdata->chip_awake)
pdata->chip_awake(NULL);
}
diff --git a/drivers/misc/tsl2550.c b/drivers/misc/tsl2550.c
index b003356..87a1337 100644
--- a/drivers/misc/tsl2550.c
+++ b/drivers/misc/tsl2550.c
@@ -446,7 +446,6 @@
static struct i2c_driver tsl2550_driver = {
.driver = {
.name = TSL2550_DRV_NAME,
- .owner = THIS_MODULE,
.pm = TSL2550_PM_OPS,
},
.probe = tsl2550_probe,
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 1916174..ffb5634 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -46,7 +46,7 @@
MODULE_AUTHOR("VMware, Inc.");
MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver");
-MODULE_VERSION("1.2.1.3-k");
+MODULE_VERSION("1.3.0.0-k");
MODULE_ALIAS("dmi:*:svnVMware*:*");
MODULE_ALIAS("vmware_vmmemctl");
MODULE_LICENSE("GPL");
@@ -110,9 +110,18 @@
*/
#define VMW_BALLOON_HV_PORT 0x5670
#define VMW_BALLOON_HV_MAGIC 0x456c6d6f
-#define VMW_BALLOON_PROTOCOL_VERSION 2
#define VMW_BALLOON_GUEST_ID 1 /* Linux */
+enum vmwballoon_capabilities {
+ /*
+ * Bit 0 is reserved and not associated to any capability.
+ */
+ VMW_BALLOON_BASIC_CMDS = (1 << 1),
+ VMW_BALLOON_BATCHED_CMDS = (1 << 2)
+};
+
+#define VMW_BALLOON_CAPABILITIES (VMW_BALLOON_BASIC_CMDS)
+
#define VMW_BALLOON_CMD_START 0
#define VMW_BALLOON_CMD_GET_TARGET 1
#define VMW_BALLOON_CMD_LOCK 2
@@ -120,32 +129,36 @@
#define VMW_BALLOON_CMD_GUEST_ID 4
/* error codes */
-#define VMW_BALLOON_SUCCESS 0
-#define VMW_BALLOON_FAILURE -1
-#define VMW_BALLOON_ERROR_CMD_INVALID 1
-#define VMW_BALLOON_ERROR_PPN_INVALID 2
-#define VMW_BALLOON_ERROR_PPN_LOCKED 3
-#define VMW_BALLOON_ERROR_PPN_UNLOCKED 4
-#define VMW_BALLOON_ERROR_PPN_PINNED 5
-#define VMW_BALLOON_ERROR_PPN_NOTNEEDED 6
-#define VMW_BALLOON_ERROR_RESET 7
-#define VMW_BALLOON_ERROR_BUSY 8
+#define VMW_BALLOON_SUCCESS 0
+#define VMW_BALLOON_FAILURE -1
+#define VMW_BALLOON_ERROR_CMD_INVALID 1
+#define VMW_BALLOON_ERROR_PPN_INVALID 2
+#define VMW_BALLOON_ERROR_PPN_LOCKED 3
+#define VMW_BALLOON_ERROR_PPN_UNLOCKED 4
+#define VMW_BALLOON_ERROR_PPN_PINNED 5
+#define VMW_BALLOON_ERROR_PPN_NOTNEEDED 6
+#define VMW_BALLOON_ERROR_RESET 7
+#define VMW_BALLOON_ERROR_BUSY 8
-#define VMWARE_BALLOON_CMD(cmd, data, result) \
-({ \
- unsigned long __stat, __dummy1, __dummy2; \
- __asm__ __volatile__ ("inl %%dx" : \
- "=a"(__stat), \
- "=c"(__dummy1), \
- "=d"(__dummy2), \
- "=b"(result) : \
- "0"(VMW_BALLOON_HV_MAGIC), \
- "1"(VMW_BALLOON_CMD_##cmd), \
- "2"(VMW_BALLOON_HV_PORT), \
- "3"(data) : \
- "memory"); \
- result &= -1UL; \
- __stat & -1UL; \
+#define VMW_BALLOON_SUCCESS_WITH_CAPABILITIES (0x03000000)
+
+#define VMWARE_BALLOON_CMD(cmd, data, result) \
+({ \
+ unsigned long __status, __dummy1, __dummy2; \
+ __asm__ __volatile__ ("inl %%dx" : \
+ "=a"(__status), \
+ "=c"(__dummy1), \
+ "=d"(__dummy2), \
+ "=b"(result) : \
+ "0"(VMW_BALLOON_HV_MAGIC), \
+ "1"(VMW_BALLOON_CMD_##cmd), \
+ "2"(VMW_BALLOON_HV_PORT), \
+ "3"(data) : \
+ "memory"); \
+ if (VMW_BALLOON_CMD_##cmd == VMW_BALLOON_CMD_START) \
+ result = __dummy1; \
+ result &= -1UL; \
+ __status & -1UL; \
})
#ifdef CONFIG_DEBUG_FS
@@ -223,11 +236,12 @@
*/
static bool vmballoon_send_start(struct vmballoon *b)
{
- unsigned long status, dummy;
+ unsigned long status, capabilities;
STATS_INC(b->stats.start);
- status = VMWARE_BALLOON_CMD(START, VMW_BALLOON_PROTOCOL_VERSION, dummy);
+ status = VMWARE_BALLOON_CMD(START, VMW_BALLOON_CAPABILITIES,
+ capabilities);
if (status == VMW_BALLOON_SUCCESS)
return true;
@@ -402,55 +416,37 @@
}
/*
- * Allocate (or reserve) a page for the balloon and notify the host. If host
- * refuses the page put it on "refuse" list and allocate another one until host
- * is satisfied. "Refused" pages are released at the end of inflation cycle
- * (when we allocate b->rate_alloc pages).
+ * Notify the host of a ballooned page. If host rejects the page put it on the
+ * refuse list, those refused page are then released at the end of the
+ * inflation cycle.
*/
-static int vmballoon_reserve_page(struct vmballoon *b, bool can_sleep)
+static int vmballoon_lock_page(struct vmballoon *b, struct page *page)
{
- struct page *page;
- gfp_t flags;
- unsigned int hv_status;
- int locked;
- flags = can_sleep ? VMW_PAGE_ALLOC_CANSLEEP : VMW_PAGE_ALLOC_NOSLEEP;
+ int locked, hv_status;
- do {
- if (!can_sleep)
- STATS_INC(b->stats.alloc);
- else
- STATS_INC(b->stats.sleep_alloc);
+ locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status);
+ if (locked > 0) {
+ STATS_INC(b->stats.refused_alloc);
- page = alloc_page(flags);
- if (!page) {
- if (!can_sleep)
- STATS_INC(b->stats.alloc_fail);
- else
- STATS_INC(b->stats.sleep_alloc_fail);
- return -ENOMEM;
+ if (hv_status == VMW_BALLOON_ERROR_RESET ||
+ hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED) {
+ __free_page(page);
+ return -EIO;
}
- /* inform monitor */
- locked = vmballoon_send_lock_page(b, page_to_pfn(page), &hv_status);
- if (locked > 0) {
- STATS_INC(b->stats.refused_alloc);
-
- if (hv_status == VMW_BALLOON_ERROR_RESET ||
- hv_status == VMW_BALLOON_ERROR_PPN_NOTNEEDED) {
- __free_page(page);
- return -EIO;
- }
-
- /*
- * Place page on the list of non-balloonable pages
- * and retry allocation, unless we already accumulated
- * too many of them, in which case take a breather.
- */
+ /*
+ * Place page on the list of non-balloonable pages
+ * and retry allocation, unless we already accumulated
+ * too many of them, in which case take a breather.
+ */
+ if (b->n_refused_pages < VMW_BALLOON_MAX_REFUSED) {
+ b->n_refused_pages++;
list_add(&page->lru, &b->refused_pages);
- if (++b->n_refused_pages >= VMW_BALLOON_MAX_REFUSED)
- return -EIO;
+ } else {
+ __free_page(page);
}
- } while (locked != 0);
+ return -EIO;
+ }
/* track allocated page */
list_add(&page->lru, &b->pages);
@@ -512,7 +508,7 @@
unsigned int i;
unsigned int allocations = 0;
int error = 0;
- bool alloc_can_sleep = false;
+ gfp_t flags = VMW_PAGE_ALLOC_NOSLEEP;
pr_debug("%s - size: %d, target %d\n", __func__, b->size, b->target);
@@ -543,19 +539,16 @@
__func__, goal, rate, b->rate_alloc);
for (i = 0; i < goal; i++) {
+ struct page *page;
- error = vmballoon_reserve_page(b, alloc_can_sleep);
- if (error) {
- if (error != -ENOMEM) {
- /*
- * Not a page allocation failure, stop this
- * cycle. Maybe we'll get new target from
- * the host soon.
- */
- break;
- }
+ if (flags == VMW_PAGE_ALLOC_NOSLEEP)
+ STATS_INC(b->stats.alloc);
+ else
+ STATS_INC(b->stats.sleep_alloc);
- if (alloc_can_sleep) {
+ page = alloc_page(flags);
+ if (!page) {
+ if (flags == VMW_PAGE_ALLOC_CANSLEEP) {
/*
* CANSLEEP page allocation failed, so guest
* is under severe memory pressure. Quickly
@@ -563,8 +556,10 @@
*/
b->rate_alloc = max(b->rate_alloc / 2,
VMW_BALLOON_RATE_ALLOC_MIN);
+ STATS_INC(b->stats.sleep_alloc_fail);
break;
}
+ STATS_INC(b->stats.alloc_fail);
/*
* NOSLEEP page allocation failed, so the guest is
@@ -579,11 +574,16 @@
if (i >= b->rate_alloc)
break;
- alloc_can_sleep = true;
+ flags = VMW_PAGE_ALLOC_CANSLEEP;
/* Lower rate for sleeping allocations. */
rate = b->rate_alloc;
+ continue;
}
+ error = vmballoon_lock_page(b, page);
+ if (error)
+ break;
+
if (++allocations > VMW_BALLOON_YIELD_THRESHOLD) {
cond_resched();
allocations = 0;
diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c
index a721b5d..9ec262a 100644
--- a/drivers/misc/vmw_vmci/vmci_host.c
+++ b/drivers/misc/vmw_vmci/vmci_host.c
@@ -1031,14 +1031,9 @@
void __exit vmci_host_exit(void)
{
- int error;
-
vmci_host_device_initialized = false;
- error = misc_deregister(&vmci_host_miscdev);
- if (error)
- pr_warn("Error unregistering character device: %d\n", error);
-
+ misc_deregister(&vmci_host_miscdev);
vmci_ctx_destroy(host_context);
vmci_qp_broker_exit();
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index c9c3d20..a1b820f 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -208,6 +208,8 @@
ret = snprintf(buf, PAGE_SIZE, "%d\n", locked);
+ mmc_blk_put(md);
+
return ret;
}
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index fd9a58e..6a0f9c7 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -779,6 +779,7 @@
config MMC_MTK
tristate "MediaTek SD/MMC Card Interface support"
+ depends on HAS_DMA
help
This selects the MediaTek(R) Secure digital and Multimedia card Interface.
If you have a machine with a integrated SD/MMC card reader, say Y or M here.
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index b2b411d..4d12032 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -1062,9 +1062,14 @@
if (status & (CTO_EN | CCRC_EN))
end_cmd = 1;
+ if (host->data || host->response_busy) {
+ end_trans = !end_cmd;
+ host->response_busy = 0;
+ }
if (status & (CTO_EN | DTO_EN))
hsmmc_command_incomplete(host, -ETIMEDOUT, end_cmd);
- else if (status & (CCRC_EN | DCRC_EN))
+ else if (status & (CCRC_EN | DCRC_EN | DEB_EN | CEB_EN |
+ BADA_EN))
hsmmc_command_incomplete(host, -EILSEQ, end_cmd);
if (status & ACE_EN) {
@@ -1081,10 +1086,6 @@
}
dev_dbg(mmc_dev(host->mmc), "AC12 err: 0x%x\n", ac12);
}
- if (host->data || host->response_busy) {
- end_trans = !end_cmd;
- host->response_busy = 0;
- }
}
OMAP_HSMMC_WRITE(host->base, STAT, status);
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index faf0cb9..c6b9f64 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -581,13 +581,8 @@
static unsigned int esdhc_pltfm_get_max_clock(struct sdhci_host *host)
{
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
- struct pltfm_imx_data *imx_data = pltfm_host->priv;
- struct esdhc_platform_data *boarddata = &imx_data->boarddata;
- if (boarddata->f_max && (boarddata->f_max < pltfm_host->clock))
- return boarddata->f_max;
- else
- return pltfm_host->clock;
+ return pltfm_host->clock;
}
static unsigned int esdhc_pltfm_get_min_clock(struct sdhci_host *host)
@@ -878,34 +873,19 @@
static int
sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
struct sdhci_host *host,
- struct esdhc_platform_data *boarddata)
+ struct pltfm_imx_data *imx_data)
{
struct device_node *np = pdev->dev.of_node;
-
- if (!np)
- return -ENODEV;
-
- if (of_get_property(np, "non-removable", NULL))
- boarddata->cd_type = ESDHC_CD_PERMANENT;
-
- if (of_get_property(np, "fsl,cd-controller", NULL))
- boarddata->cd_type = ESDHC_CD_CONTROLLER;
+ struct esdhc_platform_data *boarddata = &imx_data->boarddata;
+ int ret;
if (of_get_property(np, "fsl,wp-controller", NULL))
boarddata->wp_type = ESDHC_WP_CONTROLLER;
- boarddata->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
- if (gpio_is_valid(boarddata->cd_gpio))
- boarddata->cd_type = ESDHC_CD_GPIO;
-
boarddata->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
if (gpio_is_valid(boarddata->wp_gpio))
boarddata->wp_type = ESDHC_WP_GPIO;
- of_property_read_u32(np, "bus-width", &boarddata->max_bus_width);
-
- of_property_read_u32(np, "max-frequency", &boarddata->f_max);
-
if (of_find_property(np, "no-1-8-v", NULL))
boarddata->support_vsel = false;
else
@@ -916,29 +896,119 @@
mmc_of_parse_voltage(np, &host->ocr_mask);
+ /* sdr50 and sdr104 needs work on 1.8v signal voltage */
+ if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) &&
+ !IS_ERR(imx_data->pins_default)) {
+ imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,
+ ESDHC_PINCTRL_STATE_100MHZ);
+ imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl,
+ ESDHC_PINCTRL_STATE_200MHZ);
+ if (IS_ERR(imx_data->pins_100mhz) ||
+ IS_ERR(imx_data->pins_200mhz)) {
+ dev_warn(mmc_dev(host->mmc),
+ "could not get ultra high speed state, work on normal mode\n");
+ /*
+ * fall back to not support uhs by specify no 1.8v quirk
+ */
+ host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+ }
+ } else {
+ host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
+ }
+
/* call to generic mmc_of_parse to support additional capabilities */
- return mmc_of_parse(host->mmc);
+ ret = mmc_of_parse(host->mmc);
+ if (ret)
+ return ret;
+
+ if (!IS_ERR_VALUE(mmc_gpio_get_cd(host->mmc)))
+ host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+
+ return 0;
}
#else
static inline int
sdhci_esdhc_imx_probe_dt(struct platform_device *pdev,
struct sdhci_host *host,
- struct esdhc_platform_data *boarddata)
+ struct pltfm_imx_data *imx_data)
{
return -ENODEV;
}
#endif
+static int sdhci_esdhc_imx_probe_nondt(struct platform_device *pdev,
+ struct sdhci_host *host,
+ struct pltfm_imx_data *imx_data)
+{
+ struct esdhc_platform_data *boarddata = &imx_data->boarddata;
+ int err;
+
+ if (!host->mmc->parent->platform_data) {
+ dev_err(mmc_dev(host->mmc), "no board data!\n");
+ return -EINVAL;
+ }
+
+ imx_data->boarddata = *((struct esdhc_platform_data *)
+ host->mmc->parent->platform_data);
+ /* write_protect */
+ if (boarddata->wp_type == ESDHC_WP_GPIO) {
+ err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio);
+ if (err) {
+ dev_err(mmc_dev(host->mmc),
+ "failed to request write-protect gpio!\n");
+ return err;
+ }
+ host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
+ }
+
+ /* card_detect */
+ switch (boarddata->cd_type) {
+ case ESDHC_CD_GPIO:
+ err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
+ if (err) {
+ dev_err(mmc_dev(host->mmc),
+ "failed to request card-detect gpio!\n");
+ return err;
+ }
+ /* fall through */
+
+ case ESDHC_CD_CONTROLLER:
+ /* we have a working card_detect back */
+ host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+ break;
+
+ case ESDHC_CD_PERMANENT:
+ host->mmc->caps |= MMC_CAP_NONREMOVABLE;
+ break;
+
+ case ESDHC_CD_NONE:
+ break;
+ }
+
+ switch (boarddata->max_bus_width) {
+ case 8:
+ host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA;
+ break;
+ case 4:
+ host->mmc->caps |= MMC_CAP_4_BIT_DATA;
+ break;
+ case 1:
+ default:
+ host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
+ break;
+ }
+
+ return 0;
+}
+
static int sdhci_esdhc_imx_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id =
of_match_device(imx_esdhc_dt_ids, &pdev->dev);
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_host *host;
- struct esdhc_platform_data *boarddata;
int err;
struct pltfm_imx_data *imx_data;
- bool dt = true;
host = sdhci_pltfm_init(pdev, &sdhci_esdhc_imx_pdata, 0);
if (IS_ERR(host))
@@ -1030,84 +1100,12 @@
if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536)
host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
- boarddata = &imx_data->boarddata;
- if (sdhci_esdhc_imx_probe_dt(pdev, host, boarddata) < 0) {
- if (!host->mmc->parent->platform_data) {
- dev_err(mmc_dev(host->mmc), "no board data!\n");
- err = -EINVAL;
- goto disable_clk;
- }
- imx_data->boarddata = *((struct esdhc_platform_data *)
- host->mmc->parent->platform_data);
- dt = false;
- }
- /* write_protect */
- if (boarddata->wp_type == ESDHC_WP_GPIO && !dt) {
- err = mmc_gpio_request_ro(host->mmc, boarddata->wp_gpio);
- if (err) {
- dev_err(mmc_dev(host->mmc),
- "failed to request write-protect gpio!\n");
- goto disable_clk;
- }
- host->mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
- }
-
- /* card_detect */
- switch (boarddata->cd_type) {
- case ESDHC_CD_GPIO:
- if (dt)
- break;
- err = mmc_gpio_request_cd(host->mmc, boarddata->cd_gpio, 0);
- if (err) {
- dev_err(mmc_dev(host->mmc),
- "failed to request card-detect gpio!\n");
- goto disable_clk;
- }
- /* fall through */
-
- case ESDHC_CD_CONTROLLER:
- /* we have a working card_detect back */
- host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
- break;
-
- case ESDHC_CD_PERMANENT:
- host->mmc->caps |= MMC_CAP_NONREMOVABLE;
- break;
-
- case ESDHC_CD_NONE:
- break;
- }
-
- switch (boarddata->max_bus_width) {
- case 8:
- host->mmc->caps |= MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA;
- break;
- case 4:
- host->mmc->caps |= MMC_CAP_4_BIT_DATA;
- break;
- case 1:
- default:
- host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA;
- break;
- }
-
- /* sdr50 and sdr104 needs work on 1.8v signal voltage */
- if ((boarddata->support_vsel) && esdhc_is_usdhc(imx_data) &&
- !IS_ERR(imx_data->pins_default)) {
- imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl,
- ESDHC_PINCTRL_STATE_100MHZ);
- imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl,
- ESDHC_PINCTRL_STATE_200MHZ);
- if (IS_ERR(imx_data->pins_100mhz) ||
- IS_ERR(imx_data->pins_200mhz)) {
- dev_warn(mmc_dev(host->mmc),
- "could not get ultra high speed state, work on normal mode\n");
- /* fall back to not support uhs by specify no 1.8v quirk */
- host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
- }
- } else {
- host->quirks2 |= SDHCI_QUIRK2_NO_1_8_V;
- }
+ if (of_id)
+ err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data);
+ else
+ err = sdhci_esdhc_imx_probe_nondt(pdev, host, imx_data);
+ if (err)
+ goto disable_clk;
err = sdhci_add_host(host);
if (err)
diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h
index 3497cfa..a870c42 100644
--- a/drivers/mmc/host/sdhci-esdhc.h
+++ b/drivers/mmc/host/sdhci-esdhc.h
@@ -45,6 +45,6 @@
#define ESDHC_DMA_SYSCTL 0x40c
#define ESDHC_DMA_SNOOP 0x00000040
-#define ESDHC_HOST_CONTROL_RES 0x05
+#define ESDHC_HOST_CONTROL_RES 0x01
#endif /* _DRIVERS_MMC_SDHCI_ESDHC_H */
diff --git a/drivers/mmc/host/sdhci-pxav3.c b/drivers/mmc/host/sdhci-pxav3.c
index 9cd5fc6..946d37f 100644
--- a/drivers/mmc/host/sdhci-pxav3.c
+++ b/drivers/mmc/host/sdhci-pxav3.c
@@ -411,6 +411,7 @@
goto err_of_parse;
sdhci_get_of_property(pdev);
pdata = pxav3_get_mmc_pdata(dev);
+ pdev->dev.platform_data = pdata;
} else if (pdata) {
/* on-chip device */
if (pdata->flags & PXA_FLAG_CARD_PERMANENT)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index bc14452..1dbe932 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2866,6 +2866,7 @@
u32 max_current_caps;
unsigned int ocr_avail;
unsigned int override_timeout_clk;
+ u32 max_clk;
int ret;
WARN_ON(host == NULL);
@@ -2978,8 +2979,11 @@
GFP_KERNEL);
host->align_buffer = kmalloc(host->align_buffer_sz, GFP_KERNEL);
if (!host->adma_table || !host->align_buffer) {
- dma_free_coherent(mmc_dev(mmc), host->adma_table_sz,
- host->adma_table, host->adma_addr);
+ if (host->adma_table)
+ dma_free_coherent(mmc_dev(mmc),
+ host->adma_table_sz,
+ host->adma_table,
+ host->adma_addr);
kfree(host->align_buffer);
pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n",
mmc_hostname(mmc));
@@ -3047,18 +3051,22 @@
* Set host parameters.
*/
mmc->ops = &sdhci_ops;
- mmc->f_max = host->max_clk;
+ max_clk = host->max_clk;
+
if (host->ops->get_min_clock)
mmc->f_min = host->ops->get_min_clock(host);
else if (host->version >= SDHCI_SPEC_300) {
if (host->clk_mul) {
mmc->f_min = (host->max_clk * host->clk_mul) / 1024;
- mmc->f_max = host->max_clk * host->clk_mul;
+ max_clk = host->max_clk * host->clk_mul;
} else
mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
} else
mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
+ if (!mmc->f_max || (mmc->f_max && (mmc->f_max > max_clk)))
+ mmc->f_max = max_clk;
+
if (!(host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) {
host->timeout_clk = (caps[0] & SDHCI_TIMEOUT_CLK_MASK) >>
SDHCI_TIMEOUT_CLK_SHIFT;
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 317a494..a98dd4f 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -625,6 +625,23 @@
call_netdevice_notifiers(NETDEV_CHANGEADDR, bond_dev);
}
+static struct slave *bond_get_old_active(struct bonding *bond,
+ struct slave *new_active)
+{
+ struct slave *slave;
+ struct list_head *iter;
+
+ bond_for_each_slave(bond, slave, iter) {
+ if (slave == new_active)
+ continue;
+
+ if (ether_addr_equal(bond->dev->dev_addr, slave->dev->dev_addr))
+ return slave;
+ }
+
+ return NULL;
+}
+
/* bond_do_fail_over_mac
*
* Perform special MAC address swapping for fail_over_mac settings
@@ -652,6 +669,9 @@
if (!new_active)
return;
+ if (!old_active)
+ old_active = bond_get_old_active(bond, new_active);
+
if (old_active) {
ether_addr_copy(tmp_mac, new_active->dev->dev_addr);
ether_addr_copy(saddr.sa_data,
@@ -766,6 +786,7 @@
slave ? slave->dev->name : "NULL");
if (!slave || !bond->send_peer_notif ||
+ !netif_carrier_ok(bond->dev) ||
test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
return false;
@@ -1725,9 +1746,16 @@
err_undo_flags:
/* Enslave of first slave has failed and we need to fix master's mac */
- if (!bond_has_slaves(bond) &&
- ether_addr_equal_64bits(bond_dev->dev_addr, slave_dev->dev_addr))
- eth_hw_addr_random(bond_dev);
+ if (!bond_has_slaves(bond)) {
+ if (ether_addr_equal_64bits(bond_dev->dev_addr,
+ slave_dev->dev_addr))
+ eth_hw_addr_random(bond_dev);
+ if (bond_dev->type != ARPHRD_ETHER) {
+ ether_setup(bond_dev);
+ bond_dev->flags |= IFF_MASTER;
+ bond_dev->priv_flags &= ~IFF_TX_SKB_SHARING;
+ }
+ }
return res;
}
@@ -1916,6 +1944,7 @@
bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
netdev_info(bond_dev, "Destroying bond %s\n",
bond_dev->name);
+ bond_remove_proc_entry(bond);
unregister_netdevice(bond_dev);
}
return ret;
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index f4e40aa..945c095 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -577,10 +577,10 @@
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
- netif_receive_skb(skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_receive_skb(skb);
}
/**
@@ -642,10 +642,10 @@
}
at91_read_mb(dev, mb, cf);
- netif_receive_skb(skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_receive_skb(skb);
can_led_event(dev, CAN_LED_EVENT_RX);
}
@@ -802,10 +802,10 @@
return 0;
at91_poll_err_frame(dev, cf, reg_sr);
- netif_receive_skb(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += cf->can_dlc;
+ netif_receive_skb(skb);
return 1;
}
@@ -1067,10 +1067,10 @@
return;
at91_irq_err_state(dev, cf, new_state);
- netif_rx(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += cf->can_dlc;
+ netif_rx(skb);
priv->can.state = new_state;
}
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index 27ad312..57dadd5 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -424,10 +424,9 @@
cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
}
- netif_rx(skb);
-
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
}
static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
@@ -508,10 +507,9 @@
priv->can.state = state;
- netif_rx(skb);
-
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
return 0;
}
diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c
index c11d449..70a8cbb 100644
--- a/drivers/net/can/cc770/cc770.c
+++ b/drivers/net/can/cc770/cc770.c
@@ -504,10 +504,10 @@
for (i = 0; i < cf->can_dlc; i++)
cf->data[i] = cc770_read_reg(priv, msgobj[mo].data[i]);
}
- netif_rx(skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
}
static int cc770_err(struct net_device *dev, u8 status)
@@ -584,10 +584,10 @@
}
}
- netif_rx(skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
return 0;
}
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 6201c5a..b1e8d72 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -577,10 +577,10 @@
return 0;
do_bus_err(dev, cf, reg_esr);
- netif_receive_skb(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += cf->can_dlc;
+ netif_receive_skb(skb);
return 1;
}
@@ -622,10 +622,9 @@
if (unlikely(new_state == CAN_STATE_BUS_OFF))
can_bus_off(dev);
- netif_receive_skb(skb);
-
dev->stats.rx_packets++;
dev->stats.rx_bytes += cf->can_dlc;
+ netif_receive_skb(skb);
return 1;
}
@@ -670,10 +669,10 @@
}
flexcan_read_fifo(dev, cf);
- netif_receive_skb(skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_receive_skb(skb);
can_led_event(dev, CAN_LED_EVENT_RX);
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index e3d7e22..db9538d 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -1216,11 +1216,12 @@
cf->data[i] = (u8)(slot[j] >> shift);
}
}
- netif_receive_skb(skb);
/* Update statistics and read pointer */
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_receive_skb(skb);
+
rd = grcan_ring_add(rd, GRCAN_MSG_SIZE, dma->rx.size);
}
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index 32bd7f4..7b92e91 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -377,10 +377,9 @@
/* release receive buffer */
sja1000_write_cmdreg(priv, CMD_RRB);
- netif_rx(skb);
-
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
can_led_event(dev, CAN_LED_EVENT_RX);
}
@@ -484,10 +483,9 @@
can_bus_off(dev);
}
- netif_rx(skb);
-
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
return 0;
}
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index a23a7af..9a3f15c 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -218,10 +218,10 @@
memcpy(skb_put(skb, sizeof(struct can_frame)),
&cf, sizeof(struct can_frame));
- netif_rx_ni(skb);
sl->dev->stats.rx_packets++;
sl->dev->stats.rx_bytes += cf.can_dlc;
+ netif_rx_ni(skb);
}
/* parse tty input stream */
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index c1a95a3..b7e83c2 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1086,8 +1086,8 @@
if (ret)
goto out_clk;
- priv->power = devm_regulator_get(&spi->dev, "vdd");
- priv->transceiver = devm_regulator_get(&spi->dev, "xceiver");
+ priv->power = devm_regulator_get_optional(&spi->dev, "vdd");
+ priv->transceiver = devm_regulator_get_optional(&spi->dev, "xceiver");
if ((PTR_ERR(priv->power) == -EPROBE_DEFER) ||
(PTR_ERR(priv->transceiver) == -EPROBE_DEFER)) {
ret = -EPROBE_DEFER;
@@ -1222,17 +1222,16 @@
struct spi_device *spi = to_spi_device(dev);
struct mcp251x_priv *priv = spi_get_drvdata(spi);
- if (priv->after_suspend & AFTER_SUSPEND_POWER) {
+ if (priv->after_suspend & AFTER_SUSPEND_POWER)
mcp251x_power_enable(priv->power, 1);
+
+ if (priv->after_suspend & AFTER_SUSPEND_UP) {
+ mcp251x_power_enable(priv->transceiver, 1);
queue_work(priv->wq, &priv->restart_work);
} else {
- if (priv->after_suspend & AFTER_SUSPEND_UP) {
- mcp251x_power_enable(priv->transceiver, 1);
- queue_work(priv->wq, &priv->restart_work);
- } else {
- priv->after_suspend = 0;
- }
+ priv->after_suspend = 0;
}
+
priv->force_quit = 0;
enable_irq(spi->irq);
return 0;
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index e95a9e1..cf345cb 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -747,9 +747,9 @@
}
}
- netif_rx(skb);
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
return 0;
}
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 866bac0..2d39038 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -324,10 +324,9 @@
cf->data[i] = msg->msg.can_msg.msg[i];
}
- netif_rx(skb);
-
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
}
static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
@@ -400,10 +399,9 @@
stats->rx_errors++;
}
- netif_rx(skb);
-
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
}
/*
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
index 411c1af..0e5a449 100644
--- a/drivers/net/can/usb/esd_usb2.c
+++ b/drivers/net/can/usb/esd_usb2.c
@@ -301,13 +301,12 @@
cf->data[7] = rxerr;
}
- netif_rx(skb);
-
priv->bec.txerr = txerr;
priv->bec.rxerr = rxerr;
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
}
}
@@ -347,10 +346,9 @@
cf->data[i] = msg->msg.rx.data[i];
}
- netif_rx(skb);
-
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
}
return;
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c
index 72427f2..838545c 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb.c
@@ -526,9 +526,9 @@
hwts->hwtstamp = timeval_to_ktime(tv);
}
- netif_rx(skb);
mc->netdev->stats.rx_packets++;
mc->netdev->stats.rx_bytes += cf->can_dlc;
+ netif_rx(skb);
return 0;
}
@@ -659,12 +659,11 @@
hwts = skb_hwtstamps(skb);
hwts->hwtstamp = timeval_to_ktime(tv);
- /* push the skb */
- netif_rx(skb);
-
/* update statistics */
mc->netdev->stats.rx_packets++;
mc->netdev->stats.rx_bytes += cf->can_dlc;
+ /* push the skb */
+ netif_rx(skb);
return 0;
@@ -855,6 +854,18 @@
/*
* describe the PCAN-USB adapter
*/
+static const struct can_bittiming_const pcan_usb_const = {
+ .name = "pcan_usb",
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 64,
+ .brp_inc = 1,
+};
+
const struct peak_usb_adapter pcan_usb = {
.name = "PCAN-USB",
.device_id = PCAN_USB_PRODUCT_ID,
@@ -863,17 +874,7 @@
.clock = {
.freq = PCAN_USB_CRYSTAL_HZ / 2 ,
},
- .bittiming_const = {
- .name = "pcan_usb",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 64,
- .brp_inc = 1,
- },
+ .bittiming_const = &pcan_usb_const,
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb),
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 7921cff..5a2e341 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -792,9 +792,9 @@
dev->ep_msg_out = peak_usb_adapter->ep_msg_out[ctrl_idx];
dev->can.clock = peak_usb_adapter->clock;
- dev->can.bittiming_const = &peak_usb_adapter->bittiming_const;
+ dev->can.bittiming_const = peak_usb_adapter->bittiming_const;
dev->can.do_set_bittiming = peak_usb_set_bittiming;
- dev->can.data_bittiming_const = &peak_usb_adapter->data_bittiming_const;
+ dev->can.data_bittiming_const = peak_usb_adapter->data_bittiming_const;
dev->can.do_set_data_bittiming = peak_usb_set_data_bittiming;
dev->can.do_set_mode = peak_usb_set_mode;
dev->can.do_get_berr_counter = peak_usb_adapter->do_get_berr_counter;
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.h b/drivers/net/can/usb/peak_usb/pcan_usb_core.h
index 9e624f0..506fe50 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.h
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.h
@@ -48,8 +48,8 @@
u32 device_id;
u32 ctrlmode_supported;
struct can_clock clock;
- const struct can_bittiming_const bittiming_const;
- const struct can_bittiming_const data_bittiming_const;
+ const struct can_bittiming_const * const bittiming_const;
+ const struct can_bittiming_const * const data_bittiming_const;
unsigned int ctrl_count;
int (*intf_probe)(struct usb_interface *intf);
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
index 09d14e7..ce44a03 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
@@ -990,6 +990,30 @@
}
/* describes the PCAN-USB FD adapter */
+static const struct can_bittiming_const pcan_usb_fd_const = {
+ .name = "pcan_usb_fd",
+ .tseg1_min = 1,
+ .tseg1_max = 64,
+ .tseg2_min = 1,
+ .tseg2_max = 16,
+ .sjw_max = 16,
+ .brp_min = 1,
+ .brp_max = 1024,
+ .brp_inc = 1,
+};
+
+static const struct can_bittiming_const pcan_usb_fd_data_const = {
+ .name = "pcan_usb_fd",
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 1024,
+ .brp_inc = 1,
+};
+
const struct peak_usb_adapter pcan_usb_fd = {
.name = "PCAN-USB FD",
.device_id = PCAN_USBFD_PRODUCT_ID,
@@ -999,28 +1023,8 @@
.clock = {
.freq = PCAN_UFD_CRYSTAL_HZ,
},
- .bittiming_const = {
- .name = "pcan_usb_fd",
- .tseg1_min = 1,
- .tseg1_max = 64,
- .tseg2_min = 1,
- .tseg2_max = 16,
- .sjw_max = 16,
- .brp_min = 1,
- .brp_max = 1024,
- .brp_inc = 1,
- },
- .data_bittiming_const = {
- .name = "pcan_usb_fd",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 1024,
- .brp_inc = 1,
- },
+ .bittiming_const = &pcan_usb_fd_const,
+ .data_bittiming_const = &pcan_usb_fd_data_const,
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
@@ -1058,6 +1062,30 @@
};
/* describes the PCAN-USB Pro FD adapter */
+static const struct can_bittiming_const pcan_usb_pro_fd_const = {
+ .name = "pcan_usb_pro_fd",
+ .tseg1_min = 1,
+ .tseg1_max = 64,
+ .tseg2_min = 1,
+ .tseg2_max = 16,
+ .sjw_max = 16,
+ .brp_min = 1,
+ .brp_max = 1024,
+ .brp_inc = 1,
+};
+
+static const struct can_bittiming_const pcan_usb_pro_fd_data_const = {
+ .name = "pcan_usb_pro_fd",
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 1024,
+ .brp_inc = 1,
+};
+
const struct peak_usb_adapter pcan_usb_pro_fd = {
.name = "PCAN-USB Pro FD",
.device_id = PCAN_USBPROFD_PRODUCT_ID,
@@ -1067,28 +1095,8 @@
.clock = {
.freq = PCAN_UFD_CRYSTAL_HZ,
},
- .bittiming_const = {
- .name = "pcan_usb_pro_fd",
- .tseg1_min = 1,
- .tseg1_max = 64,
- .tseg2_min = 1,
- .tseg2_max = 16,
- .sjw_max = 16,
- .brp_min = 1,
- .brp_max = 1024,
- .brp_inc = 1,
- },
- .data_bittiming_const = {
- .name = "pcan_usb_pro_fd",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 1024,
- .brp_inc = 1,
- },
+ .bittiming_const = &pcan_usb_pro_fd_const,
+ .data_bittiming_const = &pcan_usb_pro_fd_data_const,
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
index dec5171..bbdd605 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c
@@ -553,9 +553,9 @@
hwts = skb_hwtstamps(skb);
hwts->hwtstamp = timeval_to_ktime(tv);
- netif_rx(skb);
netdev->stats.rx_packets++;
netdev->stats.rx_bytes += can_frame->can_dlc;
+ netif_rx(skb);
return 0;
}
@@ -670,9 +670,9 @@
peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv);
hwts = skb_hwtstamps(skb);
hwts->hwtstamp = timeval_to_ktime(tv);
- netif_rx(skb);
netdev->stats.rx_packets++;
netdev->stats.rx_bytes += can_frame->can_dlc;
+ netif_rx(skb);
return 0;
}
@@ -1004,6 +1004,18 @@
/*
* describe the PCAN-USB Pro adapter
*/
+static const struct can_bittiming_const pcan_usb_pro_const = {
+ .name = "pcan_usb_pro",
+ .tseg1_min = 1,
+ .tseg1_max = 16,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 1,
+ .brp_max = 1024,
+ .brp_inc = 1,
+};
+
const struct peak_usb_adapter pcan_usb_pro = {
.name = "PCAN-USB Pro",
.device_id = PCAN_USBPRO_PRODUCT_ID,
@@ -1012,17 +1024,7 @@
.clock = {
.freq = PCAN_USBPRO_CRYSTAL_HZ,
},
- .bittiming_const = {
- .name = "pcan_usb_pro",
- .tseg1_min = 1,
- .tseg1_max = 16,
- .tseg2_min = 1,
- .tseg2_max = 8,
- .sjw_max = 4,
- .brp_min = 1,
- .brp_max = 1024,
- .brp_inc = 1,
- },
+ .bittiming_const = &pcan_usb_pro_const,
/* size of device private data */
.sizeof_dev_private = sizeof(struct pcan_usb_pro_device),
diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c
index dd52c7a..de95b1c 100644
--- a/drivers/net/can/usb/usb_8dev.c
+++ b/drivers/net/can/usb/usb_8dev.c
@@ -461,10 +461,9 @@
priv->bec.txerr = txerr;
priv->bec.rxerr = rxerr;
- netif_rx(skb);
-
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
}
/* Read data and status frames */
@@ -494,10 +493,9 @@
else
memcpy(cf->data, msg->data, cf->can_dlc);
- netif_rx(skb);
-
stats->rx_packets++;
stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
can_led_event(priv->netdev, CAN_LED_EVENT_RX);
} else {
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 972982f..079897b 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -696,9 +696,20 @@
}
/* Include the pseudo-PHY address and the broadcast PHY address to
- * divert reads towards our workaround
+ * divert reads towards our workaround. This is only required for
+ * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such
+ * that we can use the regular SWITCH_MDIO master controller instead.
+ *
+ * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask
+ * to have a 1:1 mapping between Port address and PHY address in order
+ * to utilize the slave_mii_bus instance to read from Port PHYs. This is
+ * not what we want here, so we initialize phys_mii_mask 0 to always
+ * utilize the "master" MDIO bus backed by the "mdio-unimac" driver.
*/
- ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0));
+ if (of_machine_is_compatible("brcm,bcm7445d0"))
+ ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0));
+ else
+ ds->phys_mii_mask = 0;
rev = reg_readl(priv, REG_SWITCH_REVISION);
priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) &
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index fd8547c..5613424 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1163,7 +1163,7 @@
newfid = __ffs(ps->fid_mask);
ps->fid[port] = newfid;
- ps->fid_mask &= (1 << newfid);
+ ps->fid_mask &= ~(1 << newfid);
ps->bridge_mask[fid] &= ~(1 << port);
ps->bridge_mask[newfid] = 1 << port;
diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c
index 2d1ce3c..753887d 100644
--- a/drivers/net/ethernet/3com/3c59x.c
+++ b/drivers/net/ethernet/3com/3c59x.c
@@ -1763,16 +1763,9 @@
vp->rx_ring[i].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, PKT_BUF_SZ, PCI_DMA_FROMDEVICE));
}
if (i != RX_RING_SIZE) {
- int j;
pr_emerg("%s: no memory for rx ring\n", dev->name);
- for (j = 0; j < i; j++) {
- if (vp->rx_skbuff[j]) {
- dev_kfree_skb(vp->rx_skbuff[j]);
- vp->rx_skbuff[j] = NULL;
- }
- }
retval = -ENOMEM;
- goto err_free_irq;
+ goto err_free_skb;
}
/* Wrap the ring. */
vp->rx_ring[i-1].next = cpu_to_le32(vp->rx_ring_dma);
@@ -1782,7 +1775,13 @@
if (!retval)
goto out;
-err_free_irq:
+err_free_skb:
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ if (vp->rx_skbuff[i]) {
+ dev_kfree_skb(vp->rx_skbuff[i]);
+ vp->rx_skbuff[i] = NULL;
+ }
+ }
free_irq(dev->irq, dev);
err:
if (vortex_debug > 1)
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index c51014b..b52e0f6 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -65,7 +65,7 @@
obj-$(CONFIG_NET_VENDOR_QLOGIC) += qlogic/
obj-$(CONFIG_NET_VENDOR_QUALCOMM) += qualcomm/
obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
-obj-$(CONFIG_SH_ETH) += renesas/
+obj-$(CONFIG_NET_VENDOR_RENESAS) += renesas/
obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
obj-$(CONFIG_NET_VENDOR_ROCKER) += rocker/
obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index a626c43..cfa3704 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -801,6 +801,9 @@
void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
{
+ if (pdata->phy_dev)
+ phy_disconnect(pdata->phy_dev);
+
mdiobus_unregister(pdata->mdio_bus);
mdiobus_free(pdata->mdio_bus);
pdata->mdio_bus = NULL;
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
index 299eb43..a02ea7f8 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
@@ -1277,9 +1277,10 @@
mac_ops->tx_disable(pdata);
xgene_enet_napi_del(pdata);
- xgene_enet_mdio_remove(pdata);
- xgene_enet_delete_desc_rings(pdata);
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII)
+ xgene_enet_mdio_remove(pdata);
unregister_netdev(ndev);
+ xgene_enet_delete_desc_rings(pdata);
pdata->port_ops->shutdown(pdata);
free_netdev(ndev);
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index a90d736..f7fbdc9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -262,9 +262,9 @@
if (likely(skb)) {
(*pkts_compl)++;
(*bytes_compl) += skb->len;
+ dev_kfree_skb_any(skb);
}
- dev_kfree_skb_any(skb);
tx_buf->first_bd = 0;
tx_buf->skb = NULL;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 76b9052..5907c82 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1718,6 +1718,22 @@
offset += sizeof(u32);
data_buf += sizeof(u32);
written_so_far += sizeof(u32);
+
+ /* At end of each 4Kb page, release nvram lock to allow MFW
+ * chance to take it for its own use.
+ */
+ if ((cmd_flags & MCPR_NVM_COMMAND_LAST) &&
+ (written_so_far < buf_size)) {
+ DP(BNX2X_MSG_ETHTOOL | BNX2X_MSG_NVM,
+ "Releasing NVM lock after offset 0x%x\n",
+ (u32)(offset - sizeof(u32)));
+ bnx2x_release_nvram_lock(bp);
+ usleep_range(1000, 2000);
+ rc = bnx2x_acquire_nvram_lock(bp);
+ if (rc)
+ return rc;
+ }
+
cmd_flags = 0;
}
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index 64c1e9d..09ff09f 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -2126,6 +2126,8 @@
int ret = 0;
int timeout = 0;
u32 reg;
+ u32 dma_ctrl;
+ int i;
/* Disable TDMA to stop add more frames in TX DMA */
reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
@@ -2169,6 +2171,20 @@
ret = -ETIMEDOUT;
}
+ dma_ctrl = 0;
+ for (i = 0; i < priv->hw_params->rx_queues; i++)
+ dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
+ reg = bcmgenet_rdma_readl(priv, DMA_CTRL);
+ reg &= ~dma_ctrl;
+ bcmgenet_rdma_writel(priv, reg, DMA_CTRL);
+
+ dma_ctrl = 0;
+ for (i = 0; i < priv->hw_params->tx_queues; i++)
+ dma_ctrl |= (1 << (i + DMA_RING_BUF_EN_SHIFT));
+ reg = bcmgenet_tdma_readl(priv, DMA_CTRL);
+ reg &= ~dma_ctrl;
+ bcmgenet_tdma_writel(priv, reg, DMA_CTRL);
+
return ret;
}
@@ -2820,8 +2836,6 @@
netif_dbg(priv, tx_err, dev, "bcmgenet_timeout\n");
- bcmgenet_disable_tx_napi(priv);
-
for (q = 0; q < priv->hw_params->tx_queues; q++)
bcmgenet_dump_tx_queue(&priv->tx_rings[q]);
bcmgenet_dump_tx_queue(&priv->tx_rings[DESC_INDEX]);
@@ -2837,8 +2851,6 @@
bcmgenet_intrl2_0_writel(priv, int0_enable, INTRL2_CPU_MASK_CLEAR);
bcmgenet_intrl2_1_writel(priv, int1_enable, INTRL2_CPU_MASK_CLEAR);
- bcmgenet_enable_tx_napi(priv);
-
dev->trans_start = jiffies;
dev->stats.tx_errors++;
diff --git a/drivers/net/ethernet/brocade/bna/bnad.c b/drivers/net/ethernet/brocade/bna/bnad.c
index 0612b19..506047c 100644
--- a/drivers/net/ethernet/brocade/bna/bnad.c
+++ b/drivers/net/ethernet/brocade/bna/bnad.c
@@ -676,6 +676,7 @@
if (!next_cmpl->valid)
break;
}
+ packets++;
/* TODO: BNA_CQ_EF_LOCAL ? */
if (unlikely(flags & (BNA_CQ_EF_MAC_ERROR |
@@ -692,7 +693,6 @@
else
bnad_cq_setup_skb_frags(rcb, skb, sop_ci, nvecs, len);
- packets++;
rcb->rxq->rx_packets++;
rcb->rxq->rx_bytes += totlen;
ccb->bytes_per_intr += totlen;
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c
index caeb395..bf9eb2e 100644
--- a/drivers/net/ethernet/cadence/macb.c
+++ b/drivers/net/ethernet/cadence/macb.c
@@ -104,6 +104,57 @@
return bp->rx_buffers + bp->rx_buffer_size * macb_rx_ring_wrap(index);
}
+/* I/O accessors */
+static u32 hw_readl_native(struct macb *bp, int offset)
+{
+ return __raw_readl(bp->regs + offset);
+}
+
+static void hw_writel_native(struct macb *bp, int offset, u32 value)
+{
+ __raw_writel(value, bp->regs + offset);
+}
+
+static u32 hw_readl(struct macb *bp, int offset)
+{
+ return readl_relaxed(bp->regs + offset);
+}
+
+static void hw_writel(struct macb *bp, int offset, u32 value)
+{
+ writel_relaxed(value, bp->regs + offset);
+}
+
+/*
+ * Find the CPU endianness by using the loopback bit of NCR register. When the
+ * CPU is in big endian we need to program swaped mode for management
+ * descriptor access.
+ */
+static bool hw_is_native_io(void __iomem *addr)
+{
+ u32 value = MACB_BIT(LLB);
+
+ __raw_writel(value, addr + MACB_NCR);
+ value = __raw_readl(addr + MACB_NCR);
+
+ /* Write 0 back to disable everything */
+ __raw_writel(0, addr + MACB_NCR);
+
+ return value == MACB_BIT(LLB);
+}
+
+static bool hw_is_gem(void __iomem *addr, bool native_io)
+{
+ u32 id;
+
+ if (native_io)
+ id = __raw_readl(addr + MACB_MID);
+ else
+ id = readl_relaxed(addr + MACB_MID);
+
+ return MACB_BFEXT(IDNUM, id) >= 0x2;
+}
+
static void macb_set_hwaddr(struct macb *bp)
{
u32 bottom;
@@ -160,7 +211,7 @@
}
}
- netdev_info(bp->dev, "invalid hw address, using random\n");
+ dev_info(&bp->pdev->dev, "invalid hw address, using random\n");
eth_hw_addr_random(bp->dev);
}
@@ -252,7 +303,6 @@
struct macb *bp = netdev_priv(dev);
struct phy_device *phydev = bp->phy_dev;
unsigned long flags;
-
int status_change = 0;
spin_lock_irqsave(&bp->lock, flags);
@@ -449,14 +499,14 @@
static void macb_update_stats(struct macb *bp)
{
- u32 __iomem *reg = bp->regs + MACB_PFR;
u32 *p = &bp->hw_stats.macb.rx_pause_frames;
u32 *end = &bp->hw_stats.macb.tx_pause_frames + 1;
+ int offset = MACB_PFR;
WARN_ON((unsigned long)(end - p - 1) != (MACB_TPF - MACB_PFR) / 4);
- for(; p < end; p++, reg++)
- *p += readl_relaxed(reg);
+ for(; p < end; p++, offset += 4)
+ *p += bp->macb_reg_readl(bp, offset);
}
static int macb_halt_tx(struct macb *bp)
@@ -1107,12 +1157,6 @@
}
#endif
-static inline unsigned int macb_count_tx_descriptors(struct macb *bp,
- unsigned int len)
-{
- return (len + bp->max_tx_length - 1) / bp->max_tx_length;
-}
-
static unsigned int macb_tx_map(struct macb *bp,
struct macb_queue *queue,
struct sk_buff *skb)
@@ -1263,11 +1307,11 @@
* socket buffer: skb fragments of jumbo frames may need to be
* splitted into many buffer descriptors.
*/
- count = macb_count_tx_descriptors(bp, skb_headlen(skb));
+ count = DIV_ROUND_UP(skb_headlen(skb), bp->max_tx_length);
nr_frags = skb_shinfo(skb)->nr_frags;
for (f = 0; f < nr_frags; f++) {
frag_size = skb_frag_size(&skb_shinfo(skb)->frags[f]);
- count += macb_count_tx_descriptors(bp, frag_size);
+ count += DIV_ROUND_UP(frag_size, bp->max_tx_length);
}
spin_lock_irqsave(&bp->lock, flags);
@@ -1603,7 +1647,6 @@
static void macb_configure_dma(struct macb *bp)
{
u32 dmacfg;
- u32 tmp, ncr;
if (macb_is_gem(bp)) {
dmacfg = gem_readl(bp, DMACFG) & ~GEM_BF(RXBS, -1L);
@@ -1613,22 +1656,11 @@
dmacfg |= GEM_BIT(TXPBMS) | GEM_BF(RXBMS, -1L);
dmacfg &= ~GEM_BIT(ENDIA_PKT);
- /* Find the CPU endianness by using the loopback bit of net_ctrl
- * register. save it first. When the CPU is in big endian we
- * need to program swaped mode for management descriptor access.
- */
- ncr = macb_readl(bp, NCR);
- __raw_writel(MACB_BIT(LLB), bp->regs + MACB_NCR);
- tmp = __raw_readl(bp->regs + MACB_NCR);
-
- if (tmp == MACB_BIT(LLB))
+ if (bp->native_io)
dmacfg &= ~GEM_BIT(ENDIA_DESC);
else
dmacfg |= GEM_BIT(ENDIA_DESC); /* CPU in big endian */
- /* Restore net_ctrl */
- macb_writel(bp, NCR, ncr);
-
if (bp->dev->features & NETIF_F_HW_CSUM)
dmacfg |= GEM_BIT(TXCOEN);
else
@@ -1897,19 +1929,19 @@
static void gem_update_stats(struct macb *bp)
{
- int i;
+ unsigned int i;
u32 *p = &bp->hw_stats.gem.tx_octets_31_0;
for (i = 0; i < GEM_STATS_LEN; ++i, ++p) {
u32 offset = gem_statistics[i].offset;
- u64 val = readl_relaxed(bp->regs + offset);
+ u64 val = bp->macb_reg_readl(bp, offset);
bp->ethtool_stats[i] += val;
*p += val;
if (offset == GEM_OCTTXL || offset == GEM_OCTRXL) {
/* Add GEM_OCTTXH, GEM_OCTRXH */
- val = readl_relaxed(bp->regs + offset + 4);
+ val = bp->macb_reg_readl(bp, offset + 4);
bp->ethtool_stats[i] += ((u64)val) << 32;
*(++p) += val;
}
@@ -1976,7 +2008,7 @@
static void gem_get_ethtool_strings(struct net_device *dev, u32 sset, u8 *p)
{
- int i;
+ unsigned int i;
switch (sset) {
case ETH_SS_STATS:
@@ -2190,7 +2222,7 @@
if (dt_conf)
bp->caps = dt_conf->caps;
- if (macb_is_gem_hw(bp->regs)) {
+ if (hw_is_gem(bp->regs, bp->native_io)) {
bp->caps |= MACB_CAPS_MACB_IS_GEM;
dcfg = gem_readl(bp, DCFG1);
@@ -2201,10 +2233,11 @@
bp->caps |= MACB_CAPS_FIFO_MODE;
}
- netdev_dbg(bp->dev, "Cadence caps 0x%08x\n", bp->caps);
+ dev_dbg(&bp->pdev->dev, "Cadence caps 0x%08x\n", bp->caps);
}
static void macb_probe_queues(void __iomem *mem,
+ bool native_io,
unsigned int *queue_mask,
unsigned int *num_queues)
{
@@ -2219,7 +2252,7 @@
* we are early in the probe process and don't have the
* MACB_CAPS_MACB_IS_GEM flag positioned
*/
- if (!macb_is_gem_hw(mem))
+ if (!hw_is_gem(mem, native_io))
return;
/* bit 0 is never set but queue 0 always exists */
@@ -2786,6 +2819,7 @@
struct clk *pclk, *hclk, *tx_clk;
unsigned int queue_mask, num_queues;
struct macb_platform_data *pdata;
+ bool native_io;
struct phy_device *phydev;
struct net_device *dev;
struct resource *regs;
@@ -2794,6 +2828,11 @@
struct macb *bp;
int err;
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ mem = devm_ioremap_resource(&pdev->dev, regs);
+ if (IS_ERR(mem))
+ return PTR_ERR(mem);
+
if (np) {
const struct of_device_id *match;
@@ -2809,14 +2848,9 @@
if (err)
return err;
- regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mem = devm_ioremap_resource(&pdev->dev, regs);
- if (IS_ERR(mem)) {
- err = PTR_ERR(mem);
- goto err_disable_clocks;
- }
+ native_io = hw_is_native_io(mem);
- macb_probe_queues(mem, &queue_mask, &num_queues);
+ macb_probe_queues(mem, native_io, &queue_mask, &num_queues);
dev = alloc_etherdev_mq(sizeof(*bp), num_queues);
if (!dev) {
err = -ENOMEM;
@@ -2831,6 +2865,14 @@
bp->pdev = pdev;
bp->dev = dev;
bp->regs = mem;
+ bp->native_io = native_io;
+ if (native_io) {
+ bp->macb_reg_readl = hw_readl_native;
+ bp->macb_reg_writel = hw_writel_native;
+ } else {
+ bp->macb_reg_readl = hw_readl;
+ bp->macb_reg_writel = hw_writel;
+ }
bp->num_queues = num_queues;
bp->queue_mask = queue_mask;
if (macb_config)
@@ -2838,9 +2880,8 @@
bp->pclk = pclk;
bp->hclk = hclk;
bp->tx_clk = tx_clk;
- if (macb_config->jumbo_max_len) {
+ if (macb_config)
bp->jumbo_max_len = macb_config->jumbo_max_len;
- }
spin_lock_init(&bp->lock);
diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h
index d746559..1895b6b 100644
--- a/drivers/net/ethernet/cadence/macb.h
+++ b/drivers/net/ethernet/cadence/macb.h
@@ -429,18 +429,12 @@
| GEM_BF(name, value))
/* Register access macros */
-#define macb_readl(port,reg) \
- readl_relaxed((port)->regs + MACB_##reg)
-#define macb_writel(port,reg,value) \
- writel_relaxed((value), (port)->regs + MACB_##reg)
-#define gem_readl(port, reg) \
- readl_relaxed((port)->regs + GEM_##reg)
-#define gem_writel(port, reg, value) \
- writel_relaxed((value), (port)->regs + GEM_##reg)
-#define queue_readl(queue, reg) \
- readl_relaxed((queue)->bp->regs + (queue)->reg)
-#define queue_writel(queue, reg, value) \
- writel_relaxed((value), (queue)->bp->regs + (queue)->reg)
+#define macb_readl(port, reg) (port)->macb_reg_readl((port), MACB_##reg)
+#define macb_writel(port, reg, value) (port)->macb_reg_writel((port), MACB_##reg, (value))
+#define gem_readl(port, reg) (port)->macb_reg_readl((port), GEM_##reg)
+#define gem_writel(port, reg, value) (port)->macb_reg_writel((port), GEM_##reg, (value))
+#define queue_readl(queue, reg) (queue)->bp->macb_reg_readl((queue)->bp, (queue)->reg)
+#define queue_writel(queue, reg, value) (queue)->bp->macb_reg_writel((queue)->bp, (queue)->reg, (value))
/* Conditional GEM/MACB macros. These perform the operation to the correct
* register dependent on whether the device is a GEM or a MACB. For registers
@@ -785,6 +779,11 @@
struct macb {
void __iomem *regs;
+ bool native_io;
+
+ /* hardware IO accessors */
+ u32 (*macb_reg_readl)(struct macb *bp, int offset);
+ void (*macb_reg_writel)(struct macb *bp, int offset, u32 value);
unsigned int rx_tail;
unsigned int rx_prepared_head;
@@ -817,9 +816,9 @@
struct mii_bus *mii_bus;
struct phy_device *phy_dev;
- unsigned int link;
- unsigned int speed;
- unsigned int duplex;
+ int link;
+ int speed;
+ int duplex;
u32 caps;
unsigned int dma_burst_length;
@@ -843,9 +842,4 @@
return !!(bp->caps & MACB_CAPS_MACB_IS_GEM);
}
-static inline bool macb_is_gem_hw(void __iomem *addr)
-{
- return !!(MACB_BFEXT(IDNUM, readl_relaxed(addr + MACB_MID)) >= 0x2);
-}
-
#endif /* _MACB_H */
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index c4d6bbe..02e23e6 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -16,7 +16,6 @@
config THUNDER_NIC_PF
tristate "Thunder Physical function driver"
depends on 64BIT
- default ARCH_THUNDER
select THUNDER_NIC_BGX
---help---
This driver supports Thunder's NIC physical function.
@@ -29,14 +28,12 @@
config THUNDER_NIC_VF
tristate "Thunder Virtual function driver"
depends on 64BIT
- default ARCH_THUNDER
---help---
This driver supports Thunder's NIC virtual function
config THUNDER_NIC_BGX
tristate "Thunder MAC interface driver (BGX)"
depends on 64BIT
- default ARCH_THUNDER
---help---
This driver supports programming and controlling of MAC
interface from NIC physical function driver.
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index dda8a02..8aee250 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -125,6 +125,15 @@
*/
#define NICPF_CLK_PER_INT_TICK 2
+/* Time to wait before we decide that a SQ is stuck.
+ *
+ * Since both pkt rx and tx notifications are done with same CQ,
+ * when packets are being received at very high rate (eg: L2 forwarding)
+ * then freeing transmitted skbs will be delayed and watchdog
+ * will kick in, resetting interface. Hence keeping this value high.
+ */
+#define NICVF_TX_TIMEOUT (50 * HZ)
+
struct nicvf_cq_poll {
u8 cq_idx; /* Completion queue index */
struct napi_struct napi;
@@ -216,8 +225,9 @@
/* Tx */
u64 tx_frames_ok;
u64 tx_drops;
- u64 tx_busy;
u64 tx_tso;
+ u64 txq_stop;
+ u64 txq_wake;
};
struct nicvf {
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
index 16bd2d7..a4228e6 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
@@ -66,9 +66,10 @@
NICVF_DRV_STAT(rx_frames_jumbo),
NICVF_DRV_STAT(rx_drops),
NICVF_DRV_STAT(tx_frames_ok),
- NICVF_DRV_STAT(tx_busy),
NICVF_DRV_STAT(tx_tso),
NICVF_DRV_STAT(tx_drops),
+ NICVF_DRV_STAT(txq_stop),
+ NICVF_DRV_STAT(txq_wake),
};
static const struct nicvf_stat nicvf_queue_stats[] = {
@@ -126,6 +127,7 @@
static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
{
+ struct nicvf *nic = netdev_priv(netdev);
int stats, qidx;
if (sset != ETH_SS_STATS)
@@ -141,7 +143,7 @@
data += ETH_GSTRING_LEN;
}
- for (qidx = 0; qidx < MAX_RCV_QUEUES_PER_QS; qidx++) {
+ for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
sprintf(data, "rxq%d: %s", qidx,
nicvf_queue_stats[stats].name);
@@ -149,7 +151,7 @@
}
}
- for (qidx = 0; qidx < MAX_SND_QUEUES_PER_QS; qidx++) {
+ for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
sprintf(data, "txq%d: %s", qidx,
nicvf_queue_stats[stats].name);
@@ -170,12 +172,14 @@
static int nicvf_get_sset_count(struct net_device *netdev, int sset)
{
+ struct nicvf *nic = netdev_priv(netdev);
+
if (sset != ETH_SS_STATS)
return -EINVAL;
return nicvf_n_hw_stats + nicvf_n_drv_stats +
(nicvf_n_queue_stats *
- (MAX_RCV_QUEUES_PER_QS + MAX_SND_QUEUES_PER_QS)) +
+ (nic->qs->rq_cnt + nic->qs->sq_cnt)) +
BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT;
}
@@ -197,13 +201,13 @@
*(data++) = ((u64 *)&nic->drv_stats)
[nicvf_drv_stats[stat].index];
- for (qidx = 0; qidx < MAX_RCV_QUEUES_PER_QS; qidx++) {
+ for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
for (stat = 0; stat < nicvf_n_queue_stats; stat++)
*(data++) = ((u64 *)&nic->qs->rq[qidx].stats)
[nicvf_queue_stats[stat].index];
}
- for (qidx = 0; qidx < MAX_SND_QUEUES_PER_QS; qidx++) {
+ for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
for (stat = 0; stat < nicvf_n_queue_stats; stat++)
*(data++) = ((u64 *)&nic->qs->sq[qidx].stats)
[nicvf_queue_stats[stat].index];
@@ -543,6 +547,7 @@
{
struct nicvf *nic = netdev_priv(dev);
int err = 0;
+ bool if_up = netif_running(dev);
if (!channel->rx_count || !channel->tx_count)
return -EINVAL;
@@ -551,6 +556,9 @@
if (channel->tx_count > MAX_SND_QUEUES_PER_QS)
return -EINVAL;
+ if (if_up)
+ nicvf_stop(dev);
+
nic->qs->rq_cnt = channel->rx_count;
nic->qs->sq_cnt = channel->tx_count;
nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);
@@ -559,11 +567,9 @@
if (err)
return err;
- if (!netif_running(dev))
- return err;
+ if (if_up)
+ nicvf_open(dev);
- nicvf_stop(dev);
- nicvf_open(dev);
netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",
nic->qs->sq_cnt, nic->qs->rq_cnt);
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 8b119a0..3b90afb 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -234,7 +234,7 @@
nic->duplex == DUPLEX_FULL ?
"Full duplex" : "Half duplex");
netif_carrier_on(nic->netdev);
- netif_tx_wake_all_queues(nic->netdev);
+ netif_tx_start_all_queues(nic->netdev);
} else {
netdev_info(nic->netdev, "%s: Link is Down\n",
nic->netdev->name);
@@ -425,6 +425,7 @@
if (skb) {
prefetch(skb);
dev_consume_skb_any(skb);
+ sq->skbuff[cqe_tx->sqe_ptr] = (u64)NULL;
}
}
@@ -476,12 +477,13 @@
static int nicvf_cq_intr_handler(struct net_device *netdev, u8 cq_idx,
struct napi_struct *napi, int budget)
{
- int processed_cqe, work_done = 0;
+ int processed_cqe, work_done = 0, tx_done = 0;
int cqe_count, cqe_head;
struct nicvf *nic = netdev_priv(netdev);
struct queue_set *qs = nic->qs;
struct cmp_queue *cq = &qs->cq[cq_idx];
struct cqe_rx_t *cq_desc;
+ struct netdev_queue *txq;
spin_lock_bh(&cq->lock);
loop:
@@ -496,8 +498,8 @@
cqe_head = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, cq_idx) >> 9;
cqe_head &= 0xFFFF;
- netdev_dbg(nic->netdev, "%s cqe_count %d cqe_head %d\n",
- __func__, cqe_count, cqe_head);
+ netdev_dbg(nic->netdev, "%s CQ%d cqe_count %d cqe_head %d\n",
+ __func__, cq_idx, cqe_count, cqe_head);
while (processed_cqe < cqe_count) {
/* Get the CQ descriptor */
cq_desc = (struct cqe_rx_t *)GET_CQ_DESC(cq, cqe_head);
@@ -511,8 +513,8 @@
break;
}
- netdev_dbg(nic->netdev, "cq_desc->cqe_type %d\n",
- cq_desc->cqe_type);
+ netdev_dbg(nic->netdev, "CQ%d cq_desc->cqe_type %d\n",
+ cq_idx, cq_desc->cqe_type);
switch (cq_desc->cqe_type) {
case CQE_TYPE_RX:
nicvf_rcv_pkt_handler(netdev, napi, cq,
@@ -522,6 +524,7 @@
case CQE_TYPE_SEND:
nicvf_snd_pkt_handler(netdev, cq,
(void *)cq_desc, CQE_TYPE_SEND);
+ tx_done++;
break;
case CQE_TYPE_INVALID:
case CQE_TYPE_RX_SPLIT:
@@ -532,8 +535,9 @@
}
processed_cqe++;
}
- netdev_dbg(nic->netdev, "%s processed_cqe %d work_done %d budget %d\n",
- __func__, processed_cqe, work_done, budget);
+ netdev_dbg(nic->netdev,
+ "%s CQ%d processed_cqe %d work_done %d budget %d\n",
+ __func__, cq_idx, processed_cqe, work_done, budget);
/* Ring doorbell to inform H/W to reuse processed CQEs */
nicvf_queue_reg_write(nic, NIC_QSET_CQ_0_7_DOOR,
@@ -543,6 +547,19 @@
goto loop;
done:
+ /* Wakeup TXQ if its stopped earlier due to SQ full */
+ if (tx_done) {
+ txq = netdev_get_tx_queue(netdev, cq_idx);
+ if (netif_tx_queue_stopped(txq)) {
+ netif_tx_start_queue(txq);
+ nic->drv_stats.txq_wake++;
+ if (netif_msg_tx_err(nic))
+ netdev_warn(netdev,
+ "%s: Transmit queue wakeup SQ%d\n",
+ netdev->name, cq_idx);
+ }
+ }
+
spin_unlock_bh(&cq->lock);
return work_done;
}
@@ -554,15 +571,10 @@
struct net_device *netdev = napi->dev;
struct nicvf *nic = netdev_priv(netdev);
struct nicvf_cq_poll *cq;
- struct netdev_queue *txq;
cq = container_of(napi, struct nicvf_cq_poll, napi);
work_done = nicvf_cq_intr_handler(netdev, cq->cq_idx, napi, budget);
- txq = netdev_get_tx_queue(netdev, cq->cq_idx);
- if (netif_tx_queue_stopped(txq))
- netif_tx_wake_queue(txq);
-
if (work_done < budget) {
/* Slow packet rate, exit polling */
napi_complete(napi);
@@ -833,9 +845,9 @@
return NETDEV_TX_OK;
}
- if (!nicvf_sq_append_skb(nic, skb) && !netif_tx_queue_stopped(txq)) {
+ if (!netif_tx_queue_stopped(txq) && !nicvf_sq_append_skb(nic, skb)) {
netif_tx_stop_queue(txq);
- nic->drv_stats.tx_busy++;
+ nic->drv_stats.txq_stop++;
if (netif_msg_tx_err(nic))
netdev_warn(netdev,
"%s: Transmit ring full, stopping SQ%d\n",
@@ -859,7 +871,6 @@
nicvf_send_msg_to_pf(nic, &mbx);
netif_carrier_off(netdev);
- netif_tx_disable(netdev);
/* Disable RBDR & QS error interrupts */
for (qidx = 0; qidx < qs->rbdr_cnt; qidx++) {
@@ -894,6 +905,8 @@
kfree(cq_poll);
}
+ netif_tx_disable(netdev);
+
/* Free resources */
nicvf_config_data_transfer(nic, false);
@@ -988,6 +1001,9 @@
for (qidx = 0; qidx < qs->rbdr_cnt; qidx++)
nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx);
+ nic->drv_stats.txq_stop = 0;
+ nic->drv_stats.txq_wake = 0;
+
netif_carrier_on(netdev);
netif_tx_start_all_queues(netdev);
@@ -1278,6 +1294,7 @@
netdev->hw_features = netdev->features;
netdev->netdev_ops = &nicvf_netdev_ops;
+ netdev->watchdog_timeo = NICVF_TX_TIMEOUT;
INIT_WORK(&nic->reset_task, nicvf_reset_task);
@@ -1318,11 +1335,17 @@
pci_disable_device(pdev);
}
+static void nicvf_shutdown(struct pci_dev *pdev)
+{
+ nicvf_remove(pdev);
+}
+
static struct pci_driver nicvf_driver = {
.name = DRV_NAME,
.id_table = nicvf_id_table,
.probe = nicvf_probe,
.remove = nicvf_remove,
+ .shutdown = nicvf_shutdown,
};
static int __init nicvf_init_module(void)
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
index d69d228d..ca4240a 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c
@@ -103,9 +103,11 @@
/* Allocate a new page */
if (!nic->rb_page) {
- nic->rb_page = alloc_pages(gfp | __GFP_COMP, order);
+ nic->rb_page = alloc_pages(gfp | __GFP_COMP | __GFP_NOWARN,
+ order);
if (!nic->rb_page) {
- netdev_err(nic->netdev, "Failed to allocate new rcv buffer\n");
+ netdev_err(nic->netdev,
+ "Failed to allocate new rcv buffer\n");
return -ENOMEM;
}
nic->rb_page_offset = 0;
@@ -382,7 +384,8 @@
return;
if (sq->tso_hdrs)
- dma_free_coherent(&nic->pdev->dev, sq->dmem.q_len,
+ dma_free_coherent(&nic->pdev->dev,
+ sq->dmem.q_len * TSO_HEADER_SIZE,
sq->tso_hdrs, sq->tso_hdrs_phys);
kfree(sq->skbuff);
@@ -863,10 +866,11 @@
continue;
}
skb = (struct sk_buff *)sq->skbuff[sq->head];
+ if (skb)
+ dev_kfree_skb_any(skb);
atomic64_add(1, (atomic64_t *)&netdev->stats.tx_packets);
atomic64_add(hdr->tot_len,
(atomic64_t *)&netdev->stats.tx_bytes);
- dev_kfree_skb_any(skb);
nicvf_put_sq_desc(sq, hdr->subdesc_cnt + 1);
}
}
@@ -992,7 +996,7 @@
memset(gather, 0, SND_QUEUE_DESC_SIZE);
gather->subdesc_type = SQ_DESC_TYPE_GATHER;
- gather->ld_type = NIC_SEND_LD_TYPE_E_LDWB;
+ gather->ld_type = NIC_SEND_LD_TYPE_E_LDD;
gather->size = size;
gather->addr = data;
}
@@ -1048,7 +1052,7 @@
}
nicvf_sq_add_hdr_subdesc(sq, hdr_qentry,
seg_subdescs - 1, skb, seg_len);
- sq->skbuff[hdr_qentry] = 0;
+ sq->skbuff[hdr_qentry] = (u64)NULL;
qentry = nicvf_get_nxt_sqentry(sq, qentry);
desc_cnt += seg_subdescs;
@@ -1062,6 +1066,7 @@
/* Inform HW to xmit all TSO segments */
nicvf_queue_reg_write(nic, NIC_QSET_SQ_0_7_DOOR,
skb_get_queue_mapping(skb), desc_cnt);
+ nic->drv_stats.tx_tso++;
return 1;
}
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
index 8341bdf..f0937b7 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.h
@@ -62,7 +62,7 @@
#define SND_QUEUE_CNT 8
#define CMP_QUEUE_CNT 8 /* Max of RCV and SND qcount */
-#define SND_QSIZE SND_QUEUE_SIZE4
+#define SND_QSIZE SND_QUEUE_SIZE2
#define SND_QUEUE_LEN (1ULL << (SND_QSIZE + 10))
#define MAX_SND_QUEUE_LEN (1ULL << (SND_QUEUE_SIZE6 + 10))
#define SND_QUEUE_THRESH 2ULL
@@ -70,7 +70,10 @@
/* Since timestamp not enabled, otherwise 2 */
#define MAX_CQE_PER_PKT_XMIT 1
-#define CMP_QSIZE CMP_QUEUE_SIZE4
+/* Keep CQ and SQ sizes same, if timestamping
+ * is enabled this equation will change.
+ */
+#define CMP_QSIZE CMP_QUEUE_SIZE2
#define CMP_QUEUE_LEN (1ULL << (CMP_QSIZE + 10))
#define CMP_QUEUE_CQE_THRESH 0
#define CMP_QUEUE_TIMER_THRESH 220 /* 10usec */
@@ -87,7 +90,12 @@
#define MAX_CQES_FOR_TX ((SND_QUEUE_LEN / MIN_SQ_DESC_PER_PKT_XMIT) * \
MAX_CQE_PER_PKT_XMIT)
-#define RQ_CQ_DROP ((CMP_QUEUE_LEN - MAX_CQES_FOR_TX) / 256)
+/* Calculate number of CQEs to reserve for all SQEs.
+ * Its 1/256th level of CQ size.
+ * '+ 1' to account for pipelining
+ */
+#define RQ_CQ_DROP ((256 / (CMP_QUEUE_LEN / \
+ (CMP_QUEUE_LEN - MAX_CQES_FOR_TX))) + 1)
/* Descriptor size in bytes */
#define SND_QUEUE_DESC_SIZE 16
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 633ec05..b961a89 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -673,7 +673,10 @@
bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cmrx_cfg);
bgx_flush_dmac_addrs(bgx, lmacid);
- if (lmac->phydev)
+ if ((bgx->lmac_type != BGX_MODE_XFI) &&
+ (bgx->lmac_type != BGX_MODE_XLAUI) &&
+ (bgx->lmac_type != BGX_MODE_40G_KR) &&
+ (bgx->lmac_type != BGX_MODE_10G_KR) && lmac->phydev)
phy_disconnect(lmac->phydev);
lmac->phydev = NULL;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
index a11485f..c3c7db4 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
@@ -2332,10 +2332,11 @@
EXT_MEM1_SIZE_G(size));
}
} else {
- if (i & EXT_MEM_ENABLE_F)
+ if (i & EXT_MEM_ENABLE_F) {
size = t4_read_reg(adap, MA_EXT_MEMORY_BAR_A);
add_debugfs_mem(adap, "mc", MEM_MC,
EXT_MEM_SIZE_G(size));
+ }
}
de = debugfs_create_file_size("flash", S_IRUSR, adap->debugfs_root, adap,
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.h b/drivers/net/ethernet/emulex/benet/be_cmds.h
index 2716e6f..00e3a6b 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.h
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.h
@@ -620,6 +620,11 @@
BE_IF_FLAGS_VLAN_PROMISCUOUS |\
BE_IF_FLAGS_MCAST_PROMISCUOUS)
+#define BE_IF_EN_FLAGS (BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |\
+ BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_UNTAGGED)
+
+#define BE_IF_ALL_FILT_FLAGS (BE_IF_EN_FLAGS | BE_IF_FLAGS_ALL_PROMISCUOUS)
+
/* An RX interface is an object with one or more MAC addresses and
* filtering capabilities. */
struct be_cmd_req_if_create {
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 6f64242..6ca693b 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -273,6 +273,10 @@
if (ether_addr_equal(addr->sa_data, netdev->dev_addr))
return 0;
+ /* if device is not running, copy MAC to netdev->dev_addr */
+ if (!netif_running(netdev))
+ goto done;
+
/* The PMAC_ADD cmd may fail if the VF doesn't have FILTMGMT
* privilege or if PF did not provision the new MAC address.
* On BE3, this cmd will always fail if the VF doesn't have the
@@ -307,9 +311,9 @@
status = -EPERM;
goto err;
}
-
- memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
- dev_info(dev, "MAC address changed to %pM\n", mac);
+done:
+ ether_addr_copy(netdev->dev_addr, addr->sa_data);
+ dev_info(dev, "MAC address changed to %pM\n", addr->sa_data);
return 0;
err:
dev_warn(dev, "MAC address change to %pM failed\n", addr->sa_data);
@@ -2447,10 +2451,24 @@
be_eq_notify(eqo->adapter, eqo->q.id, false, true, num, 0);
}
+/* Free posted rx buffers that were not used */
+static void be_rxq_clean(struct be_rx_obj *rxo)
+{
+ struct be_queue_info *rxq = &rxo->q;
+ struct be_rx_page_info *page_info;
+
+ while (atomic_read(&rxq->used) > 0) {
+ page_info = get_rx_page_info(rxo);
+ put_page(page_info->page);
+ memset(page_info, 0, sizeof(*page_info));
+ }
+ BUG_ON(atomic_read(&rxq->used));
+ rxq->tail = 0;
+ rxq->head = 0;
+}
+
static void be_rx_cq_clean(struct be_rx_obj *rxo)
{
- struct be_rx_page_info *page_info;
- struct be_queue_info *rxq = &rxo->q;
struct be_queue_info *rx_cq = &rxo->cq;
struct be_rx_compl_info *rxcp;
struct be_adapter *adapter = rxo->adapter;
@@ -2487,16 +2505,6 @@
/* After cleanup, leave the CQ in unarmed state */
be_cq_notify(adapter, rx_cq->id, false, 0);
-
- /* Then free posted rx buffers that were not used */
- while (atomic_read(&rxq->used) > 0) {
- page_info = get_rx_page_info(rxo);
- put_page(page_info->page);
- memset(page_info, 0, sizeof(*page_info));
- }
- BUG_ON(atomic_read(&rxq->used));
- rxq->tail = 0;
- rxq->head = 0;
}
static void be_tx_compl_clean(struct be_adapter *adapter)
@@ -2576,8 +2584,8 @@
be_cmd_q_destroy(adapter, &eqo->q, QTYPE_EQ);
napi_hash_del(&eqo->napi);
netif_napi_del(&eqo->napi);
+ free_cpumask_var(eqo->affinity_mask);
}
- free_cpumask_var(eqo->affinity_mask);
be_queue_free(adapter, &eqo->q);
}
}
@@ -2594,13 +2602,7 @@
for_all_evt_queues(adapter, eqo, i) {
int numa_node = dev_to_node(&adapter->pdev->dev);
- if (!zalloc_cpumask_var(&eqo->affinity_mask, GFP_KERNEL))
- return -ENOMEM;
- cpumask_set_cpu(cpumask_local_spread(i, numa_node),
- eqo->affinity_mask);
- netif_napi_add(adapter->netdev, &eqo->napi, be_poll,
- BE_NAPI_WEIGHT);
- napi_hash_add(&eqo->napi);
+
aic = &adapter->aic_obj[i];
eqo->adapter = adapter;
eqo->idx = i;
@@ -2616,6 +2618,14 @@
rc = be_cmd_eq_create(adapter, eqo);
if (rc)
return rc;
+
+ if (!zalloc_cpumask_var(&eqo->affinity_mask, GFP_KERNEL))
+ return -ENOMEM;
+ cpumask_set_cpu(cpumask_local_spread(i, numa_node),
+ eqo->affinity_mask);
+ netif_napi_add(adapter->netdev, &eqo->napi, be_poll,
+ BE_NAPI_WEIGHT);
+ napi_hash_add(&eqo->napi);
}
return 0;
}
@@ -3354,13 +3364,54 @@
for_all_rx_queues(adapter, rxo, i) {
q = &rxo->q;
if (q->created) {
+ /* If RXQs are destroyed while in an "out of buffer"
+ * state, there is a possibility of an HW stall on
+ * Lancer. So, post 64 buffers to each queue to relieve
+ * the "out of buffer" condition.
+ * Make sure there's space in the RXQ before posting.
+ */
+ if (lancer_chip(adapter)) {
+ be_rx_cq_clean(rxo);
+ if (atomic_read(&q->used) == 0)
+ be_post_rx_frags(rxo, GFP_KERNEL,
+ MAX_RX_POST);
+ }
+
be_cmd_rxq_destroy(adapter, q);
be_rx_cq_clean(rxo);
+ be_rxq_clean(rxo);
}
be_queue_free(adapter, q);
}
}
+static void be_disable_if_filters(struct be_adapter *adapter)
+{
+ be_cmd_pmac_del(adapter, adapter->if_handle,
+ adapter->pmac_id[0], 0);
+
+ be_clear_uc_list(adapter);
+
+ /* The IFACE flags are enabled in the open path and cleared
+ * in the close path. When a VF gets detached from the host and
+ * assigned to a VM the following happens:
+ * - VF's IFACE flags get cleared in the detach path
+ * - IFACE create is issued by the VF in the attach path
+ * Due to a bug in the BE3/Skyhawk-R FW
+ * (Lancer FW doesn't have the bug), the IFACE capability flags
+ * specified along with the IFACE create cmd issued by a VF are not
+ * honoured by FW. As a consequence, if a *new* driver
+ * (that enables/disables IFACE flags in open/close)
+ * is loaded in the host and an *old* driver is * used by a VM/VF,
+ * the IFACE gets created *without* the needed flags.
+ * To avoid this, disable RX-filter flags only for Lancer.
+ */
+ if (lancer_chip(adapter)) {
+ be_cmd_rx_filter(adapter, BE_IF_ALL_FILT_FLAGS, OFF);
+ adapter->if_flags &= ~BE_IF_ALL_FILT_FLAGS;
+ }
+}
+
static int be_close(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
@@ -3373,6 +3424,8 @@
if (!(adapter->flags & BE_FLAGS_SETUP_DONE))
return 0;
+ be_disable_if_filters(adapter);
+
be_roce_dev_close(adapter);
if (adapter->flags & BE_FLAGS_NAPI_ENABLED) {
@@ -3392,7 +3445,6 @@
be_tx_compl_clean(adapter);
be_rx_qs_destroy(adapter);
- be_clear_uc_list(adapter);
for_all_evt_queues(adapter, eqo, i) {
if (msix_enabled(adapter))
@@ -3477,6 +3529,31 @@
return 0;
}
+static int be_enable_if_filters(struct be_adapter *adapter)
+{
+ int status;
+
+ status = be_cmd_rx_filter(adapter, BE_IF_EN_FLAGS, ON);
+ if (status)
+ return status;
+
+ /* For BE3 VFs, the PF programs the initial MAC address */
+ if (!(BEx_chip(adapter) && be_virtfn(adapter))) {
+ status = be_cmd_pmac_add(adapter, adapter->netdev->dev_addr,
+ adapter->if_handle,
+ &adapter->pmac_id[0], 0);
+ if (status)
+ return status;
+ }
+
+ if (adapter->vlans_added)
+ be_vid_config(adapter);
+
+ be_set_rx_mode(adapter->netdev);
+
+ return 0;
+}
+
static int be_open(struct net_device *netdev)
{
struct be_adapter *adapter = netdev_priv(netdev);
@@ -3490,6 +3567,10 @@
if (status)
goto err;
+ status = be_enable_if_filters(adapter);
+ if (status)
+ goto err;
+
status = be_irq_register(adapter);
if (status)
goto err;
@@ -3686,16 +3767,6 @@
}
}
-static void be_mac_clear(struct be_adapter *adapter)
-{
- if (adapter->pmac_id) {
- be_cmd_pmac_del(adapter, adapter->if_handle,
- adapter->pmac_id[0], 0);
- kfree(adapter->pmac_id);
- adapter->pmac_id = NULL;
- }
-}
-
#ifdef CONFIG_BE2NET_VXLAN
static void be_disable_vxlan_offloads(struct be_adapter *adapter)
{
@@ -3770,8 +3841,8 @@
#ifdef CONFIG_BE2NET_VXLAN
be_disable_vxlan_offloads(adapter);
#endif
- /* delete the primary mac along with the uc-mac list */
- be_mac_clear(adapter);
+ kfree(adapter->pmac_id);
+ adapter->pmac_id = NULL;
be_cmd_if_destroy(adapter, adapter->if_handle, 0);
@@ -3782,25 +3853,11 @@
return 0;
}
-static int be_if_create(struct be_adapter *adapter, u32 *if_handle,
- u32 cap_flags, u32 vf)
-{
- u32 en_flags;
-
- en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
- BE_IF_FLAGS_MULTICAST | BE_IF_FLAGS_PASS_L3L4_ERRORS |
- BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
-
- en_flags &= cap_flags;
-
- return be_cmd_if_create(adapter, cap_flags, en_flags, if_handle, vf);
-}
-
static int be_vfs_if_create(struct be_adapter *adapter)
{
struct be_resources res = {0};
+ u32 cap_flags, en_flags, vf;
struct be_vf_cfg *vf_cfg;
- u32 cap_flags, vf;
int status;
/* If a FW profile exists, then cap_flags are updated */
@@ -3821,8 +3878,12 @@
}
}
- status = be_if_create(adapter, &vf_cfg->if_handle,
- cap_flags, vf + 1);
+ en_flags = cap_flags & (BE_IF_FLAGS_UNTAGGED |
+ BE_IF_FLAGS_BROADCAST |
+ BE_IF_FLAGS_MULTICAST |
+ BE_IF_FLAGS_PASS_L3L4_ERRORS);
+ status = be_cmd_if_create(adapter, cap_flags, en_flags,
+ &vf_cfg->if_handle, vf + 1);
if (status)
return status;
}
@@ -4194,15 +4255,8 @@
memcpy(adapter->netdev->dev_addr, mac, ETH_ALEN);
memcpy(adapter->netdev->perm_addr, mac, ETH_ALEN);
- } else {
- /* Maybe the HW was reset; dev_addr must be re-programmed */
- memcpy(mac, adapter->netdev->dev_addr, ETH_ALEN);
}
- /* For BE3-R VFs, the PF programs the initial MAC address */
- if (!(BEx_chip(adapter) && be_virtfn(adapter)))
- be_cmd_pmac_add(adapter, mac, adapter->if_handle,
- &adapter->pmac_id[0], 0);
return 0;
}
@@ -4342,6 +4396,7 @@
static int be_setup(struct be_adapter *adapter)
{
struct device *dev = &adapter->pdev->dev;
+ u32 en_flags;
int status;
status = be_func_init(adapter);
@@ -4364,8 +4419,11 @@
if (status)
goto err;
- status = be_if_create(adapter, &adapter->if_handle,
- be_if_cap_flags(adapter), 0);
+ /* will enable all the needed filter flags in be_open() */
+ en_flags = BE_IF_FLAGS_RSS | BE_IF_FLAGS_DEFQ_RSS;
+ en_flags = en_flags & be_if_cap_flags(adapter);
+ status = be_cmd_if_create(adapter, be_if_cap_flags(adapter), en_flags,
+ &adapter->if_handle, 0);
if (status)
goto err;
@@ -4391,11 +4449,6 @@
dev_err(dev, "Please upgrade firmware to version >= 4.0\n");
}
- if (adapter->vlans_added)
- be_vid_config(adapter);
-
- be_set_rx_mode(adapter->netdev);
-
status = be_cmd_set_flow_control(adapter, adapter->tx_fc,
adapter->rx_fc);
if (status)
@@ -5121,7 +5174,7 @@
struct device *dev = &adapter->pdev->dev;
int status;
- if (lancer_chip(adapter) || BEx_chip(adapter))
+ if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
return;
if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) {
@@ -5168,7 +5221,7 @@
{
struct be_adapter *adapter = netdev_priv(netdev);
- if (lancer_chip(adapter) || BEx_chip(adapter))
+ if (lancer_chip(adapter) || BEx_chip(adapter) || be_is_mc(adapter))
return;
if (adapter->vxlan_port != port)
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 1eee73c..99d33e2 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -562,6 +562,7 @@
};
void fec_ptp_init(struct platform_device *pdev);
+void fec_ptp_stop(struct platform_device *pdev);
void fec_ptp_start_cyclecounter(struct net_device *ndev);
int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 42e20e5..b349e6f 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -1778,7 +1778,7 @@
return ret;
fep->mii_timeout = 0;
- init_completion(&fep->mdio_done);
+ reinit_completion(&fep->mdio_done);
/* start a read op */
writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
@@ -1817,7 +1817,7 @@
return ret;
fep->mii_timeout = 0;
- init_completion(&fep->mdio_done);
+ reinit_completion(&fep->mdio_done);
/* start a write op */
writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE |
@@ -3142,8 +3142,8 @@
fep->bufdesc_size;
/* Allocate memory for buffer descriptors. */
- cbd_base = dma_alloc_coherent(NULL, bd_size, &bd_dma,
- GFP_KERNEL);
+ cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma,
+ GFP_KERNEL);
if (!cbd_base) {
return -ENOMEM;
}
@@ -3431,6 +3431,12 @@
fep->reg_phy = NULL;
}
+ pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_get_noresume(&pdev->dev);
+ pm_runtime_set_active(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
fec_reset_phy(pdev);
if (fep->bufdesc_ex)
@@ -3465,8 +3471,6 @@
netif_carrier_off(ndev);
fec_enet_clk_enable(ndev, false);
pinctrl_pm_select_sleep_state(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
ret = register_netdev(ndev);
if (ret)
@@ -3481,8 +3485,6 @@
fep->rx_copybreak = COPYBREAK_DEFAULT;
INIT_WORK(&fep->tx_timeout_work, fec_enet_timeout_work);
- pm_runtime_set_autosuspend_delay(&pdev->dev, FEC_MDIO_PM_TIMEOUT);
- pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
@@ -3493,6 +3495,7 @@
failed_mii_init:
failed_irq:
failed_init:
+ fec_ptp_stop(pdev);
if (fep->reg_phy)
regulator_disable(fep->reg_phy);
failed_regulator:
@@ -3514,14 +3517,12 @@
struct net_device *ndev = platform_get_drvdata(pdev);
struct fec_enet_private *fep = netdev_priv(ndev);
- cancel_delayed_work_sync(&fep->time_keep);
cancel_work_sync(&fep->tx_timeout_work);
+ fec_ptp_stop(pdev);
unregister_netdev(ndev);
fec_enet_mii_remove(fep);
if (fep->reg_phy)
regulator_disable(fep->reg_phy);
- if (fep->ptp_clock)
- ptp_clock_unregister(fep->ptp_clock);
of_node_put(fep->phy_node);
free_netdev(ndev);
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index a15663a..f457a23 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -604,6 +604,16 @@
schedule_delayed_work(&fep->time_keep, HZ);
}
+void fec_ptp_stop(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct fec_enet_private *fep = netdev_priv(ndev);
+
+ cancel_delayed_work_sync(&fep->time_keep);
+ if (fep->ptp_clock)
+ ptp_clock_unregister(fep->ptp_clock);
+}
+
/**
* fec_ptp_check_pps_event
* @fep: the fec_enet_private structure handle
diff --git a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
index 56316db..cf8e546 100644
--- a/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
+++ b/drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
@@ -586,7 +586,8 @@
frag = skb_shinfo(skb)->frags;
while (nr_frags) {
CBDC_SC(bdp,
- BD_ENET_TX_STATS | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+ BD_ENET_TX_STATS | BD_ENET_TX_INTR | BD_ENET_TX_LAST |
+ BD_ENET_TX_TC);
CBDS_SC(bdp, BD_ENET_TX_READY);
if ((CBDR_SC(bdp) & BD_ENET_TX_WRAP) == 0)
diff --git a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
index b34214e..016743e 100644
--- a/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
+++ b/drivers/net/ethernet/freescale/fs_enet/mac-fec.c
@@ -110,7 +110,7 @@
}
#define FEC_NAPI_RX_EVENT_MSK (FEC_ENET_RXF | FEC_ENET_RXB)
-#define FEC_NAPI_TX_EVENT_MSK (FEC_ENET_TXF | FEC_ENET_TXB)
+#define FEC_NAPI_TX_EVENT_MSK (FEC_ENET_TXF)
#define FEC_RX_EVENT (FEC_ENET_RXF)
#define FEC_TX_EVENT (FEC_ENET_TXF)
#define FEC_ERR_EVENT_MSK (FEC_ENET_HBERR | FEC_ENET_BABR | \
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index ff87502..10b3bbbb 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -565,22 +565,6 @@
}
}
-static void lock_tx_qs(struct gfar_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->num_tx_queues; i++)
- spin_lock(&priv->tx_queue[i]->txlock);
-}
-
-static void unlock_tx_qs(struct gfar_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->num_tx_queues; i++)
- spin_unlock(&priv->tx_queue[i]->txlock);
-}
-
static int gfar_alloc_tx_queues(struct gfar_private *priv)
{
int i;
@@ -1376,7 +1360,6 @@
priv->dev = &ofdev->dev;
SET_NETDEV_DEV(dev, &ofdev->dev);
- spin_lock_init(&priv->bflock);
INIT_WORK(&priv->reset_task, gfar_reset_task);
platform_set_drvdata(ofdev, priv);
@@ -1470,9 +1453,8 @@
goto register_fail;
}
- device_init_wakeup(&dev->dev,
- priv->device_flags &
- FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ device_set_wakeup_capable(&dev->dev, priv->device_flags &
+ FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
/* fill out IRQ number and name fields */
for (i = 0; i < priv->num_grps; i++) {
@@ -1540,48 +1522,37 @@
struct gfar_private *priv = dev_get_drvdata(dev);
struct net_device *ndev = priv->ndev;
struct gfar __iomem *regs = priv->gfargrp[0].regs;
- unsigned long flags;
u32 tempval;
-
int magic_packet = priv->wol_en &&
(priv->device_flags &
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ if (!netif_running(ndev))
+ return 0;
+
+ disable_napi(priv);
+ netif_tx_lock(ndev);
netif_device_detach(ndev);
+ netif_tx_unlock(ndev);
- if (netif_running(ndev)) {
+ gfar_halt(priv);
- local_irq_save(flags);
- lock_tx_qs(priv);
+ if (magic_packet) {
+ /* Enable interrupt on Magic Packet */
+ gfar_write(®s->imask, IMASK_MAG);
- gfar_halt_nodisable(priv);
+ /* Enable Magic Packet mode */
+ tempval = gfar_read(®s->maccfg2);
+ tempval |= MACCFG2_MPEN;
+ gfar_write(®s->maccfg2, tempval);
- /* Disable Tx, and Rx if wake-on-LAN is disabled. */
+ /* re-enable the Rx block */
tempval = gfar_read(®s->maccfg1);
-
- tempval &= ~MACCFG1_TX_EN;
-
- if (!magic_packet)
- tempval &= ~MACCFG1_RX_EN;
-
+ tempval |= MACCFG1_RX_EN;
gfar_write(®s->maccfg1, tempval);
- unlock_tx_qs(priv);
- local_irq_restore(flags);
-
- disable_napi(priv);
-
- if (magic_packet) {
- /* Enable interrupt on Magic Packet */
- gfar_write(®s->imask, IMASK_MAG);
-
- /* Enable Magic Packet mode */
- tempval = gfar_read(®s->maccfg2);
- tempval |= MACCFG2_MPEN;
- gfar_write(®s->maccfg2, tempval);
- } else {
- phy_stop(priv->phydev);
- }
+ } else {
+ phy_stop(priv->phydev);
}
return 0;
@@ -1592,37 +1563,26 @@
struct gfar_private *priv = dev_get_drvdata(dev);
struct net_device *ndev = priv->ndev;
struct gfar __iomem *regs = priv->gfargrp[0].regs;
- unsigned long flags;
u32 tempval;
int magic_packet = priv->wol_en &&
(priv->device_flags &
FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
- if (!netif_running(ndev)) {
- netif_device_attach(ndev);
+ if (!netif_running(ndev))
return 0;
- }
- if (!magic_packet && priv->phydev)
+ if (magic_packet) {
+ /* Disable Magic Packet mode */
+ tempval = gfar_read(®s->maccfg2);
+ tempval &= ~MACCFG2_MPEN;
+ gfar_write(®s->maccfg2, tempval);
+ } else {
phy_start(priv->phydev);
-
- /* Disable Magic Packet mode, in case something
- * else woke us up.
- */
- local_irq_save(flags);
- lock_tx_qs(priv);
-
- tempval = gfar_read(®s->maccfg2);
- tempval &= ~MACCFG2_MPEN;
- gfar_write(®s->maccfg2, tempval);
+ }
gfar_start(priv);
- unlock_tx_qs(priv);
- local_irq_restore(flags);
-
netif_device_attach(ndev);
-
enable_napi(priv);
return 0;
@@ -2045,7 +2005,8 @@
/* Install our interrupt handlers for Error,
* Transmit, and Receive
*/
- err = request_irq(gfar_irq(grp, ER)->irq, gfar_error, 0,
+ err = request_irq(gfar_irq(grp, ER)->irq, gfar_error,
+ IRQF_NO_SUSPEND,
gfar_irq(grp, ER)->name, grp);
if (err < 0) {
netif_err(priv, intr, dev, "Can't get IRQ %d\n",
@@ -2068,7 +2029,8 @@
goto rx_irq_fail;
}
} else {
- err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt, 0,
+ err = request_irq(gfar_irq(grp, TX)->irq, gfar_interrupt,
+ IRQF_NO_SUSPEND,
gfar_irq(grp, TX)->name, grp);
if (err < 0) {
netif_err(priv, intr, dev, "Can't get IRQ %d\n",
@@ -2140,6 +2102,11 @@
/* Start Rx/Tx DMA and enable the interrupts */
gfar_start(priv);
+ /* force link state update after mac reset */
+ priv->oldlink = 0;
+ priv->oldspeed = 0;
+ priv->oldduplex = -1;
+
phy_start(priv->phydev);
enable_napi(priv);
@@ -2169,8 +2136,6 @@
if (err)
return err;
- device_set_wakeup_enable(&dev->dev, priv->wol_en);
-
return err;
}
diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h
index daa1d37..5545e41 100644
--- a/drivers/net/ethernet/freescale/gianfar.h
+++ b/drivers/net/ethernet/freescale/gianfar.h
@@ -1145,9 +1145,6 @@
int oldduplex;
int oldlink;
- /* Bitfield update lock */
- spinlock_t bflock;
-
uint32_t msg_enable;
struct work_struct reset_task;
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index fda12fb..5b90fcf 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -653,7 +653,6 @@
static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct gfar_private *priv = netdev_priv(dev);
- unsigned long flags;
if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
wol->wolopts != 0)
@@ -664,9 +663,7 @@
device_set_wakeup_enable(&dev->dev, wol->wolopts & WAKE_MAGIC);
- spin_lock_irqsave(&priv->bflock, flags);
- priv->wol_en = !!device_may_wakeup(&dev->dev);
- spin_unlock_irqrestore(&priv->bflock, flags);
+ priv->wol_en = !!device_may_wakeup(&dev->dev);
return 0;
}
@@ -903,27 +900,6 @@
return 0;
}
-static int gfar_comp_asc(const void *a, const void *b)
-{
- return memcmp(a, b, 4);
-}
-
-static int gfar_comp_desc(const void *a, const void *b)
-{
- return -memcmp(a, b, 4);
-}
-
-static void gfar_swap(void *a, void *b, int size)
-{
- u32 *_a = a;
- u32 *_b = b;
-
- swap(_a[0], _b[0]);
- swap(_a[1], _b[1]);
- swap(_a[2], _b[2]);
- swap(_a[3], _b[3]);
-}
-
/* Write a mask to filer cache */
static void gfar_set_mask(u32 mask, struct filer_table *tab)
{
@@ -1273,310 +1249,6 @@
return 0;
}
-/* Copy size filer entries */
-static void gfar_copy_filer_entries(struct gfar_filer_entry dst[0],
- struct gfar_filer_entry src[0], s32 size)
-{
- while (size > 0) {
- size--;
- dst[size].ctrl = src[size].ctrl;
- dst[size].prop = src[size].prop;
- }
-}
-
-/* Delete the contents of the filer-table between start and end
- * and collapse them
- */
-static int gfar_trim_filer_entries(u32 begin, u32 end, struct filer_table *tab)
-{
- int length;
-
- if (end > MAX_FILER_CACHE_IDX || end < begin)
- return -EINVAL;
-
- end++;
- length = end - begin;
-
- /* Copy */
- while (end < tab->index) {
- tab->fe[begin].ctrl = tab->fe[end].ctrl;
- tab->fe[begin++].prop = tab->fe[end++].prop;
-
- }
- /* Fill up with don't cares */
- while (begin < tab->index) {
- tab->fe[begin].ctrl = 0x60;
- tab->fe[begin].prop = 0xFFFFFFFF;
- begin++;
- }
-
- tab->index -= length;
- return 0;
-}
-
-/* Make space on the wanted location */
-static int gfar_expand_filer_entries(u32 begin, u32 length,
- struct filer_table *tab)
-{
- if (length == 0 || length + tab->index > MAX_FILER_CACHE_IDX ||
- begin > MAX_FILER_CACHE_IDX)
- return -EINVAL;
-
- gfar_copy_filer_entries(&(tab->fe[begin + length]), &(tab->fe[begin]),
- tab->index - length + 1);
-
- tab->index += length;
- return 0;
-}
-
-static int gfar_get_next_cluster_start(int start, struct filer_table *tab)
-{
- for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1);
- start++) {
- if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) ==
- (RQFCR_AND | RQFCR_CLE))
- return start;
- }
- return -1;
-}
-
-static int gfar_get_next_cluster_end(int start, struct filer_table *tab)
-{
- for (; (start < tab->index) && (start < MAX_FILER_CACHE_IDX - 1);
- start++) {
- if ((tab->fe[start].ctrl & (RQFCR_AND | RQFCR_CLE)) ==
- (RQFCR_CLE))
- return start;
- }
- return -1;
-}
-
-/* Uses hardwares clustering option to reduce
- * the number of filer table entries
- */
-static void gfar_cluster_filer(struct filer_table *tab)
-{
- s32 i = -1, j, iend, jend;
-
- while ((i = gfar_get_next_cluster_start(++i, tab)) != -1) {
- j = i;
- while ((j = gfar_get_next_cluster_start(++j, tab)) != -1) {
- /* The cluster entries self and the previous one
- * (a mask) must be identical!
- */
- if (tab->fe[i].ctrl != tab->fe[j].ctrl)
- break;
- if (tab->fe[i].prop != tab->fe[j].prop)
- break;
- if (tab->fe[i - 1].ctrl != tab->fe[j - 1].ctrl)
- break;
- if (tab->fe[i - 1].prop != tab->fe[j - 1].prop)
- break;
- iend = gfar_get_next_cluster_end(i, tab);
- jend = gfar_get_next_cluster_end(j, tab);
- if (jend == -1 || iend == -1)
- break;
-
- /* First we make some free space, where our cluster
- * element should be. Then we copy it there and finally
- * delete in from its old location.
- */
- if (gfar_expand_filer_entries(iend, (jend - j), tab) ==
- -EINVAL)
- break;
-
- gfar_copy_filer_entries(&(tab->fe[iend + 1]),
- &(tab->fe[jend + 1]), jend - j);
-
- if (gfar_trim_filer_entries(jend - 1,
- jend + (jend - j),
- tab) == -EINVAL)
- return;
-
- /* Mask out cluster bit */
- tab->fe[iend].ctrl &= ~(RQFCR_CLE);
- }
- }
-}
-
-/* Swaps the masked bits of a1<>a2 and b1<>b2 */
-static void gfar_swap_bits(struct gfar_filer_entry *a1,
- struct gfar_filer_entry *a2,
- struct gfar_filer_entry *b1,
- struct gfar_filer_entry *b2, u32 mask)
-{
- u32 temp[4];
- temp[0] = a1->ctrl & mask;
- temp[1] = a2->ctrl & mask;
- temp[2] = b1->ctrl & mask;
- temp[3] = b2->ctrl & mask;
-
- a1->ctrl &= ~mask;
- a2->ctrl &= ~mask;
- b1->ctrl &= ~mask;
- b2->ctrl &= ~mask;
-
- a1->ctrl |= temp[1];
- a2->ctrl |= temp[0];
- b1->ctrl |= temp[3];
- b2->ctrl |= temp[2];
-}
-
-/* Generate a list consisting of masks values with their start and
- * end of validity and block as indicator for parts belonging
- * together (glued by ANDs) in mask_table
- */
-static u32 gfar_generate_mask_table(struct gfar_mask_entry *mask_table,
- struct filer_table *tab)
-{
- u32 i, and_index = 0, block_index = 1;
-
- for (i = 0; i < tab->index; i++) {
-
- /* LSByte of control = 0 sets a mask */
- if (!(tab->fe[i].ctrl & 0xF)) {
- mask_table[and_index].mask = tab->fe[i].prop;
- mask_table[and_index].start = i;
- mask_table[and_index].block = block_index;
- if (and_index >= 1)
- mask_table[and_index - 1].end = i - 1;
- and_index++;
- }
- /* cluster starts and ends will be separated because they should
- * hold their position
- */
- if (tab->fe[i].ctrl & RQFCR_CLE)
- block_index++;
- /* A not set AND indicates the end of a depended block */
- if (!(tab->fe[i].ctrl & RQFCR_AND))
- block_index++;
- }
-
- mask_table[and_index - 1].end = i - 1;
-
- return and_index;
-}
-
-/* Sorts the entries of mask_table by the values of the masks.
- * Important: The 0xFF80 flags of the first and last entry of a
- * block must hold their position (which queue, CLusterEnable, ReJEct,
- * AND)
- */
-static void gfar_sort_mask_table(struct gfar_mask_entry *mask_table,
- struct filer_table *temp_table, u32 and_index)
-{
- /* Pointer to compare function (_asc or _desc) */
- int (*gfar_comp)(const void *, const void *);
-
- u32 i, size = 0, start = 0, prev = 1;
- u32 old_first, old_last, new_first, new_last;
-
- gfar_comp = &gfar_comp_desc;
-
- for (i = 0; i < and_index; i++) {
- if (prev != mask_table[i].block) {
- old_first = mask_table[start].start + 1;
- old_last = mask_table[i - 1].end;
- sort(mask_table + start, size,
- sizeof(struct gfar_mask_entry),
- gfar_comp, &gfar_swap);
-
- /* Toggle order for every block. This makes the
- * thing more efficient!
- */
- if (gfar_comp == gfar_comp_desc)
- gfar_comp = &gfar_comp_asc;
- else
- gfar_comp = &gfar_comp_desc;
-
- new_first = mask_table[start].start + 1;
- new_last = mask_table[i - 1].end;
-
- gfar_swap_bits(&temp_table->fe[new_first],
- &temp_table->fe[old_first],
- &temp_table->fe[new_last],
- &temp_table->fe[old_last],
- RQFCR_QUEUE | RQFCR_CLE |
- RQFCR_RJE | RQFCR_AND);
-
- start = i;
- size = 0;
- }
- size++;
- prev = mask_table[i].block;
- }
-}
-
-/* Reduces the number of masks needed in the filer table to save entries
- * This is done by sorting the masks of a depended block. A depended block is
- * identified by gluing ANDs or CLE. The sorting order toggles after every
- * block. Of course entries in scope of a mask must change their location with
- * it.
- */
-static int gfar_optimize_filer_masks(struct filer_table *tab)
-{
- struct filer_table *temp_table;
- struct gfar_mask_entry *mask_table;
-
- u32 and_index = 0, previous_mask = 0, i = 0, j = 0, size = 0;
- s32 ret = 0;
-
- /* We need a copy of the filer table because
- * we want to change its order
- */
- temp_table = kmemdup(tab, sizeof(*temp_table), GFP_KERNEL);
- if (temp_table == NULL)
- return -ENOMEM;
-
- mask_table = kcalloc(MAX_FILER_CACHE_IDX / 2 + 1,
- sizeof(struct gfar_mask_entry), GFP_KERNEL);
-
- if (mask_table == NULL) {
- ret = -ENOMEM;
- goto end;
- }
-
- and_index = gfar_generate_mask_table(mask_table, tab);
-
- gfar_sort_mask_table(mask_table, temp_table, and_index);
-
- /* Now we can copy the data from our duplicated filer table to
- * the real one in the order the mask table says
- */
- for (i = 0; i < and_index; i++) {
- size = mask_table[i].end - mask_table[i].start + 1;
- gfar_copy_filer_entries(&(tab->fe[j]),
- &(temp_table->fe[mask_table[i].start]), size);
- j += size;
- }
-
- /* And finally we just have to check for duplicated masks and drop the
- * second ones
- */
- for (i = 0; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
- if (tab->fe[i].ctrl == 0x80) {
- previous_mask = i++;
- break;
- }
- }
- for (; i < tab->index && i < MAX_FILER_CACHE_IDX; i++) {
- if (tab->fe[i].ctrl == 0x80) {
- if (tab->fe[i].prop == tab->fe[previous_mask].prop) {
- /* Two identical ones found!
- * So drop the second one!
- */
- gfar_trim_filer_entries(i, i, tab);
- } else
- /* Not identical! */
- previous_mask = i;
- }
- }
-
- kfree(mask_table);
-end: kfree(temp_table);
- return ret;
-}
-
/* Write the bit-pattern from software's buffer to hardware registers */
static int gfar_write_filer_table(struct gfar_private *priv,
struct filer_table *tab)
@@ -1586,11 +1258,10 @@
return -EBUSY;
/* Fill regular entries */
- for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].prop);
- i++)
+ for (; i < MAX_FILER_IDX && (tab->fe[i].ctrl | tab->fe[i].prop); i++)
gfar_write_filer(priv, i, tab->fe[i].ctrl, tab->fe[i].prop);
/* Fill the rest with fall-troughs */
- for (; i < MAX_FILER_IDX - 1; i++)
+ for (; i < MAX_FILER_IDX; i++)
gfar_write_filer(priv, i, 0x60, 0xFFFFFFFF);
/* Last entry must be default accept
* because that's what people expect
@@ -1624,7 +1295,6 @@
{
struct ethtool_flow_spec_container *j;
struct filer_table *tab;
- s32 i = 0;
s32 ret = 0;
/* So index is set to zero, too! */
@@ -1649,17 +1319,6 @@
}
}
- i = tab->index;
-
- /* Optimizations to save entries */
- gfar_cluster_filer(tab);
- gfar_optimize_filer_masks(tab);
-
- pr_debug("\tSummary:\n"
- "\tData on hardware: %d\n"
- "\tCompression rate: %d%%\n",
- tab->index, 100 - (100 * tab->index) / i);
-
/* Write everything to hardware */
ret = gfar_write_filer_table(priv, tab);
if (ret == -EBUSY) {
@@ -1725,13 +1384,14 @@
}
process:
+ priv->rx_list.count++;
ret = gfar_process_filer_changes(priv);
if (ret)
goto clean_list;
- priv->rx_list.count++;
return ret;
clean_list:
+ priv->rx_list.count--;
list_del(&temp->list);
clean_mem:
kfree(temp);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_main.c b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
index 982fdcd..b5b2925 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_main.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_main.c
@@ -216,7 +216,7 @@
static inline bool fm10k_page_is_reserved(struct page *page)
{
- return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc;
+ return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
}
static bool fm10k_can_reuse_rx_page(struct fm10k_rx_buffer *rx_buffer,
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 2f70a9b..830466c 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -6566,7 +6566,7 @@
static inline bool igb_page_is_reserved(struct page *page)
{
- return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc;
+ return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
}
static bool igb_can_reuse_rx_page(struct igb_rx_buffer *rx_buffer,
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 9aa6104..ae21e0b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1832,7 +1832,7 @@
static inline bool ixgbe_page_is_reserved(struct page *page)
{
- return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc;
+ return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
}
/**
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index e71cdde..1d7b00b 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -765,7 +765,7 @@
static inline bool ixgbevf_page_is_reserved(struct page *page)
{
- return (page_to_nid(page) != numa_mem_id()) || page->pfmemalloc;
+ return (page_to_nid(page) != numa_mem_id()) || page_is_pfmemalloc(page);
}
/**
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index 370e20ed..62e48bc 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1462,7 +1462,7 @@
struct mvneta_rx_queue *rxq)
{
struct net_device *dev = pp->dev;
- int rx_done, rx_filled;
+ int rx_done;
u32 rcvd_pkts = 0;
u32 rcvd_bytes = 0;
@@ -1473,7 +1473,6 @@
rx_todo = rx_done;
rx_done = 0;
- rx_filled = 0;
/* Fairness NAPI loop */
while (rx_done < rx_todo) {
@@ -1484,7 +1483,6 @@
int rx_bytes, err;
rx_done++;
- rx_filled++;
rx_status = rx_desc->status;
rx_bytes = rx_desc->data_size - (ETH_FCS_LEN + MVNETA_MH_SIZE);
data = (unsigned char *)rx_desc->buf_cookie;
@@ -1524,6 +1522,14 @@
continue;
}
+ /* Refill processing */
+ err = mvneta_rx_refill(pp, rx_desc);
+ if (err) {
+ netdev_err(dev, "Linux processing - Can't refill\n");
+ rxq->missed++;
+ goto err_drop_frame;
+ }
+
skb = build_skb(data, pp->frag_size > PAGE_SIZE ? 0 : pp->frag_size);
if (!skb)
goto err_drop_frame;
@@ -1543,14 +1549,6 @@
mvneta_rx_csum(pp, rx_status, skb);
napi_gro_receive(&pp->napi, skb);
-
- /* Refill processing */
- err = mvneta_rx_refill(pp, rx_desc);
- if (err) {
- netdev_err(dev, "Linux processing - Can't refill\n");
- rxq->missed++;
- rx_filled--;
- }
}
if (rcvd_pkts) {
@@ -1563,7 +1561,7 @@
}
/* Update rxq management counters */
- mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_filled);
+ mvneta_rxq_desc_num_update(pp, rxq, rx_done, rx_done);
return rx_done;
}
diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c
index 3e8b1bf..d9884fd 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -27,6 +27,8 @@
#include <linux/of_address.h>
#include <linux/phy.h>
#include <linux/clk.h>
+#include <linux/hrtimer.h>
+#include <linux/ktime.h>
#include <uapi/linux/ppp_defs.h>
#include <net/ip.h>
#include <net/ipv6.h>
@@ -299,6 +301,7 @@
/* Coalescing */
#define MVPP2_TXDONE_COAL_PKTS_THRESH 15
+#define MVPP2_TXDONE_HRTIMER_PERIOD_NS 1000000UL
#define MVPP2_RX_COAL_PKTS 32
#define MVPP2_RX_COAL_USEC 100
@@ -660,6 +663,14 @@
u64 tx_bytes;
};
+/* Per-CPU port control */
+struct mvpp2_port_pcpu {
+ struct hrtimer tx_done_timer;
+ bool timer_scheduled;
+ /* Tasklet for egress finalization */
+ struct tasklet_struct tx_done_tasklet;
+};
+
struct mvpp2_port {
u8 id;
@@ -679,6 +690,9 @@
u32 pending_cause_rx;
struct napi_struct napi;
+ /* Per-CPU port control */
+ struct mvpp2_port_pcpu __percpu *pcpu;
+
/* Flags */
unsigned long flags;
@@ -776,6 +790,9 @@
/* Array of transmitted skb */
struct sk_buff **tx_skb;
+ /* Array of transmitted buffers' physical addresses */
+ dma_addr_t *tx_buffs;
+
/* Index of last TX DMA descriptor that was inserted */
int txq_put_index;
@@ -913,8 +930,6 @@
/* Occupied buffers indicator */
atomic_t in_use;
int in_use_thresh;
-
- spinlock_t lock;
};
struct mvpp2_buff_hdr {
@@ -963,9 +978,13 @@
}
static void mvpp2_txq_inc_put(struct mvpp2_txq_pcpu *txq_pcpu,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ struct mvpp2_tx_desc *tx_desc)
{
txq_pcpu->tx_skb[txq_pcpu->txq_put_index] = skb;
+ if (skb)
+ txq_pcpu->tx_buffs[txq_pcpu->txq_put_index] =
+ tx_desc->buf_phys_addr;
txq_pcpu->txq_put_index++;
if (txq_pcpu->txq_put_index == txq_pcpu->size)
txq_pcpu->txq_put_index = 0;
@@ -3376,7 +3395,6 @@
bm_pool->pkt_size = 0;
bm_pool->buf_num = 0;
atomic_set(&bm_pool->in_use, 0);
- spin_lock_init(&bm_pool->lock);
return 0;
}
@@ -3647,7 +3665,6 @@
mvpp2_bm_pool_use(struct mvpp2_port *port, int pool, enum mvpp2_bm_type type,
int pkt_size)
{
- unsigned long flags = 0;
struct mvpp2_bm_pool *new_pool = &port->priv->bm_pools[pool];
int num;
@@ -3656,8 +3673,6 @@
return NULL;
}
- spin_lock_irqsave(&new_pool->lock, flags);
-
if (new_pool->type == MVPP2_BM_FREE)
new_pool->type = type;
@@ -3686,8 +3701,6 @@
if (num != pkts_num) {
WARN(1, "pool %d: %d of %d allocated\n",
new_pool->id, num, pkts_num);
- /* We need to undo the bufs_add() allocations */
- spin_unlock_irqrestore(&new_pool->lock, flags);
return NULL;
}
}
@@ -3695,15 +3708,12 @@
mvpp2_bm_pool_bufsize_set(port->priv, new_pool,
MVPP2_RX_BUF_SIZE(new_pool->pkt_size));
- spin_unlock_irqrestore(&new_pool->lock, flags);
-
return new_pool;
}
/* Initialize pools for swf */
static int mvpp2_swf_bm_pool_init(struct mvpp2_port *port)
{
- unsigned long flags = 0;
int rxq;
if (!port->pool_long) {
@@ -3714,9 +3724,7 @@
if (!port->pool_long)
return -ENOMEM;
- spin_lock_irqsave(&port->pool_long->lock, flags);
port->pool_long->port_map |= (1 << port->id);
- spin_unlock_irqrestore(&port->pool_long->lock, flags);
for (rxq = 0; rxq < rxq_number; rxq++)
mvpp2_rxq_long_pool_set(port, rxq, port->pool_long->id);
@@ -3730,9 +3738,7 @@
if (!port->pool_short)
return -ENOMEM;
- spin_lock_irqsave(&port->pool_short->lock, flags);
port->pool_short->port_map |= (1 << port->id);
- spin_unlock_irqrestore(&port->pool_short->lock, flags);
for (rxq = 0; rxq < rxq_number; rxq++)
mvpp2_rxq_short_pool_set(port, rxq,
@@ -3806,7 +3812,6 @@
mvpp2_write(port->priv, MVPP2_ISR_RX_TX_MASK_REG(port->id),
(MVPP2_CAUSE_MISC_SUM_MASK |
- MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK |
MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK));
}
@@ -4382,23 +4387,6 @@
rxq->time_coal = usec;
}
-/* Set threshold for TX_DONE pkts coalescing */
-static void mvpp2_tx_done_pkts_coal_set(void *arg)
-{
- struct mvpp2_port *port = arg;
- int queue;
- u32 val;
-
- for (queue = 0; queue < txq_number; queue++) {
- struct mvpp2_tx_queue *txq = port->txqs[queue];
-
- val = (txq->done_pkts_coal << MVPP2_TRANSMITTED_THRESH_OFFSET) &
- MVPP2_TRANSMITTED_THRESH_MASK;
- mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id);
- mvpp2_write(port->priv, MVPP2_TXQ_THRESH_REG, val);
- }
-}
-
/* Free Tx queue skbuffs */
static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
struct mvpp2_tx_queue *txq,
@@ -4407,8 +4395,8 @@
int i;
for (i = 0; i < num; i++) {
- struct mvpp2_tx_desc *tx_desc = txq->descs +
- txq_pcpu->txq_get_index;
+ dma_addr_t buf_phys_addr =
+ txq_pcpu->tx_buffs[txq_pcpu->txq_get_index];
struct sk_buff *skb = txq_pcpu->tx_skb[txq_pcpu->txq_get_index];
mvpp2_txq_inc_get(txq_pcpu);
@@ -4416,8 +4404,8 @@
if (!skb)
continue;
- dma_unmap_single(port->dev->dev.parent, tx_desc->buf_phys_addr,
- tx_desc->data_size, DMA_TO_DEVICE);
+ dma_unmap_single(port->dev->dev.parent, buf_phys_addr,
+ skb_headlen(skb), DMA_TO_DEVICE);
dev_kfree_skb_any(skb);
}
}
@@ -4433,7 +4421,7 @@
static inline struct mvpp2_tx_queue *mvpp2_get_tx_queue(struct mvpp2_port *port,
u32 cause)
{
- int queue = fls(cause >> 16) - 1;
+ int queue = fls(cause) - 1;
return port->txqs[queue];
}
@@ -4460,6 +4448,29 @@
netif_tx_wake_queue(nq);
}
+static unsigned int mvpp2_tx_done(struct mvpp2_port *port, u32 cause)
+{
+ struct mvpp2_tx_queue *txq;
+ struct mvpp2_txq_pcpu *txq_pcpu;
+ unsigned int tx_todo = 0;
+
+ while (cause) {
+ txq = mvpp2_get_tx_queue(port, cause);
+ if (!txq)
+ break;
+
+ txq_pcpu = this_cpu_ptr(txq->pcpu);
+
+ if (txq_pcpu->count) {
+ mvpp2_txq_done(port, txq, txq_pcpu);
+ tx_todo += txq_pcpu->count;
+ }
+
+ cause &= ~(1 << txq->log_id);
+ }
+ return tx_todo;
+}
+
/* Rx/Tx queue initialization/cleanup methods */
/* Allocate and initialize descriptors for aggr TXQ */
@@ -4649,12 +4660,13 @@
txq_pcpu->tx_skb = kmalloc(txq_pcpu->size *
sizeof(*txq_pcpu->tx_skb),
GFP_KERNEL);
- if (!txq_pcpu->tx_skb) {
- dma_free_coherent(port->dev->dev.parent,
- txq->size * MVPP2_DESC_ALIGNED_SIZE,
- txq->descs, txq->descs_phys);
- return -ENOMEM;
- }
+ if (!txq_pcpu->tx_skb)
+ goto error;
+
+ txq_pcpu->tx_buffs = kmalloc(txq_pcpu->size *
+ sizeof(dma_addr_t), GFP_KERNEL);
+ if (!txq_pcpu->tx_buffs)
+ goto error;
txq_pcpu->count = 0;
txq_pcpu->reserved_num = 0;
@@ -4663,6 +4675,19 @@
}
return 0;
+
+error:
+ for_each_present_cpu(cpu) {
+ txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
+ kfree(txq_pcpu->tx_skb);
+ kfree(txq_pcpu->tx_buffs);
+ }
+
+ dma_free_coherent(port->dev->dev.parent,
+ txq->size * MVPP2_DESC_ALIGNED_SIZE,
+ txq->descs, txq->descs_phys);
+
+ return -ENOMEM;
}
/* Free allocated TXQ resources */
@@ -4675,6 +4700,7 @@
for_each_present_cpu(cpu) {
txq_pcpu = per_cpu_ptr(txq->pcpu, cpu);
kfree(txq_pcpu->tx_skb);
+ kfree(txq_pcpu->tx_buffs);
}
if (txq->descs)
@@ -4805,7 +4831,6 @@
goto err_cleanup;
}
- on_each_cpu(mvpp2_tx_done_pkts_coal_set, port, 1);
on_each_cpu(mvpp2_txq_sent_counter_clear, port, 1);
return 0;
@@ -4887,6 +4912,49 @@
}
}
+static void mvpp2_timer_set(struct mvpp2_port_pcpu *port_pcpu)
+{
+ ktime_t interval;
+
+ if (!port_pcpu->timer_scheduled) {
+ port_pcpu->timer_scheduled = true;
+ interval = ktime_set(0, MVPP2_TXDONE_HRTIMER_PERIOD_NS);
+ hrtimer_start(&port_pcpu->tx_done_timer, interval,
+ HRTIMER_MODE_REL_PINNED);
+ }
+}
+
+static void mvpp2_tx_proc_cb(unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_port_pcpu *port_pcpu = this_cpu_ptr(port->pcpu);
+ unsigned int tx_todo, cause;
+
+ if (!netif_running(dev))
+ return;
+ port_pcpu->timer_scheduled = false;
+
+ /* Process all the Tx queues */
+ cause = (1 << txq_number) - 1;
+ tx_todo = mvpp2_tx_done(port, cause);
+
+ /* Set the timer in case not all the packets were processed */
+ if (tx_todo)
+ mvpp2_timer_set(port_pcpu);
+}
+
+static enum hrtimer_restart mvpp2_hr_timer_cb(struct hrtimer *timer)
+{
+ struct mvpp2_port_pcpu *port_pcpu = container_of(timer,
+ struct mvpp2_port_pcpu,
+ tx_done_timer);
+
+ tasklet_schedule(&port_pcpu->tx_done_tasklet);
+
+ return HRTIMER_NORESTART;
+}
+
/* Main RX/TX processing routines */
/* Display more error info */
@@ -5144,11 +5212,11 @@
if (i == (skb_shinfo(skb)->nr_frags - 1)) {
/* Last descriptor */
tx_desc->command = MVPP2_TXD_L_DESC;
- mvpp2_txq_inc_put(txq_pcpu, skb);
+ mvpp2_txq_inc_put(txq_pcpu, skb, tx_desc);
} else {
/* Descriptor in the middle: Not First, Not Last */
tx_desc->command = 0;
- mvpp2_txq_inc_put(txq_pcpu, NULL);
+ mvpp2_txq_inc_put(txq_pcpu, NULL, tx_desc);
}
}
@@ -5214,12 +5282,12 @@
/* First and Last descriptor */
tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_L_DESC;
tx_desc->command = tx_cmd;
- mvpp2_txq_inc_put(txq_pcpu, skb);
+ mvpp2_txq_inc_put(txq_pcpu, skb, tx_desc);
} else {
/* First but not Last */
tx_cmd |= MVPP2_TXD_F_DESC | MVPP2_TXD_PADDING_DISABLE;
tx_desc->command = tx_cmd;
- mvpp2_txq_inc_put(txq_pcpu, NULL);
+ mvpp2_txq_inc_put(txq_pcpu, NULL, tx_desc);
/* Continue with other skb fragments */
if (mvpp2_tx_frag_process(port, skb, aggr_txq, txq)) {
@@ -5255,6 +5323,17 @@
dev_kfree_skb_any(skb);
}
+ /* Finalize TX processing */
+ if (txq_pcpu->count >= txq->done_pkts_coal)
+ mvpp2_txq_done(port, txq, txq_pcpu);
+
+ /* Set the timer in case not all frags were processed */
+ if (txq_pcpu->count <= frags && txq_pcpu->count > 0) {
+ struct mvpp2_port_pcpu *port_pcpu = this_cpu_ptr(port->pcpu);
+
+ mvpp2_timer_set(port_pcpu);
+ }
+
return NETDEV_TX_OK;
}
@@ -5268,10 +5347,11 @@
netdev_err(dev, "tx fifo underrun error\n");
}
-static void mvpp2_txq_done_percpu(void *arg)
+static int mvpp2_poll(struct napi_struct *napi, int budget)
{
- struct mvpp2_port *port = arg;
- u32 cause_rx_tx, cause_tx, cause_misc;
+ u32 cause_rx_tx, cause_rx, cause_misc;
+ int rx_done = 0;
+ struct mvpp2_port *port = netdev_priv(napi->dev);
/* Rx/Tx cause register
*
@@ -5285,7 +5365,7 @@
*/
cause_rx_tx = mvpp2_read(port->priv,
MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
- cause_tx = cause_rx_tx & MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
+ cause_rx_tx &= ~MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
cause_misc = cause_rx_tx & MVPP2_CAUSE_MISC_SUM_MASK;
if (cause_misc) {
@@ -5297,26 +5377,6 @@
cause_rx_tx & ~MVPP2_CAUSE_MISC_SUM_MASK);
}
- /* Release TX descriptors */
- if (cause_tx) {
- struct mvpp2_tx_queue *txq = mvpp2_get_tx_queue(port, cause_tx);
- struct mvpp2_txq_pcpu *txq_pcpu = this_cpu_ptr(txq->pcpu);
-
- if (txq_pcpu->count)
- mvpp2_txq_done(port, txq, txq_pcpu);
- }
-}
-
-static int mvpp2_poll(struct napi_struct *napi, int budget)
-{
- u32 cause_rx_tx, cause_rx;
- int rx_done = 0;
- struct mvpp2_port *port = netdev_priv(napi->dev);
-
- on_each_cpu(mvpp2_txq_done_percpu, port, 1);
-
- cause_rx_tx = mvpp2_read(port->priv,
- MVPP2_ISR_RX_TX_CAUSE_REG(port->id));
cause_rx = cause_rx_tx & MVPP2_CAUSE_RXQ_OCCUP_DESC_ALL_MASK;
/* Process RX packets */
@@ -5561,6 +5621,8 @@
static int mvpp2_stop(struct net_device *dev)
{
struct mvpp2_port *port = netdev_priv(dev);
+ struct mvpp2_port_pcpu *port_pcpu;
+ int cpu;
mvpp2_stop_dev(port);
mvpp2_phy_disconnect(port);
@@ -5569,6 +5631,13 @@
on_each_cpu(mvpp2_interrupts_mask, port, 1);
free_irq(port->irq, port);
+ for_each_present_cpu(cpu) {
+ port_pcpu = per_cpu_ptr(port->pcpu, cpu);
+
+ hrtimer_cancel(&port_pcpu->tx_done_timer);
+ port_pcpu->timer_scheduled = false;
+ tasklet_kill(&port_pcpu->tx_done_tasklet);
+ }
mvpp2_cleanup_rxqs(port);
mvpp2_cleanup_txqs(port);
@@ -5784,7 +5853,6 @@
txq->done_pkts_coal = c->tx_max_coalesced_frames;
}
- on_each_cpu(mvpp2_tx_done_pkts_coal_set, port, 1);
return 0;
}
@@ -6035,6 +6103,7 @@
{
struct device_node *phy_node;
struct mvpp2_port *port;
+ struct mvpp2_port_pcpu *port_pcpu;
struct net_device *dev;
struct resource *res;
const char *dt_mac_addr;
@@ -6044,7 +6113,7 @@
int features;
int phy_mode;
int priv_common_regs_num = 2;
- int err, i;
+ int err, i, cpu;
dev = alloc_etherdev_mqs(sizeof(struct mvpp2_port), txq_number,
rxq_number);
@@ -6135,6 +6204,24 @@
}
mvpp2_port_power_up(port);
+ port->pcpu = alloc_percpu(struct mvpp2_port_pcpu);
+ if (!port->pcpu) {
+ err = -ENOMEM;
+ goto err_free_txq_pcpu;
+ }
+
+ for_each_present_cpu(cpu) {
+ port_pcpu = per_cpu_ptr(port->pcpu, cpu);
+
+ hrtimer_init(&port_pcpu->tx_done_timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL_PINNED);
+ port_pcpu->tx_done_timer.function = mvpp2_hr_timer_cb;
+ port_pcpu->timer_scheduled = false;
+
+ tasklet_init(&port_pcpu->tx_done_tasklet, mvpp2_tx_proc_cb,
+ (unsigned long)dev);
+ }
+
netif_napi_add(dev, &port->napi, mvpp2_poll, NAPI_POLL_WEIGHT);
features = NETIF_F_SG | NETIF_F_IP_CSUM;
dev->features = features | NETIF_F_RXCSUM;
@@ -6144,7 +6231,7 @@
err = register_netdev(dev);
if (err < 0) {
dev_err(&pdev->dev, "failed to register netdev\n");
- goto err_free_txq_pcpu;
+ goto err_free_port_pcpu;
}
netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr);
@@ -6153,6 +6240,8 @@
priv->port_list[id] = port;
return 0;
+err_free_port_pcpu:
+ free_percpu(port->pcpu);
err_free_txq_pcpu:
for (i = 0; i < txq_number; i++)
free_percpu(port->txqs[i]->pcpu);
@@ -6171,6 +6260,7 @@
int i;
unregister_netdev(port->dev);
+ free_percpu(port->pcpu);
free_percpu(port->stats);
for (i = 0; i < txq_number; i++)
free_percpu(port->txqs[i]->pcpu);
diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c
index 8204013..0a32020 100644
--- a/drivers/net/ethernet/mellanox/mlx4/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c
@@ -686,6 +686,7 @@
{
struct mlx4_cmd *cmd = &mlx4_priv(dev)->cmd;
struct mlx4_cmd_context *context;
+ long ret_wait;
int err = 0;
down(&cmd->event_sem);
@@ -711,8 +712,20 @@
if (err)
goto out_reset;
- if (!wait_for_completion_timeout(&context->done,
- msecs_to_jiffies(timeout))) {
+ if (op == MLX4_CMD_SENSE_PORT) {
+ ret_wait =
+ wait_for_completion_interruptible_timeout(&context->done,
+ msecs_to_jiffies(timeout));
+ if (ret_wait < 0) {
+ context->fw_status = 0;
+ context->out_param = 0;
+ context->result = 0;
+ }
+ } else {
+ ret_wait = (long)wait_for_completion_timeout(&context->done,
+ msecs_to_jiffies(timeout));
+ }
+ if (!ret_wait) {
mlx4_warn(dev, "command 0x%x timed out (go bit not cleared)\n",
op);
if (op == MLX4_CMD_NOP) {
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_rx.c b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
index 7a4f20b..9c145dd 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_rx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_rx.c
@@ -246,7 +246,6 @@
static inline bool mlx4_en_is_ring_empty(struct mlx4_en_rx_ring *ring)
{
- BUG_ON((u32)(ring->prod - ring->cons) > ring->actual_size);
return ring->prod == ring->cons;
}
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index aae13ad..8e81e53 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -601,7 +601,7 @@
continue;
mlx4_dbg(dev, "%s: Sending MLX4_PORT_CHANGE_SUBTYPE_DOWN to slave: %d, port:%d\n",
__func__, i, port);
- s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
+ s_info = &priv->mfunc.master.vf_oper[i].vport[port].state;
if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) {
eqe->event.port_change.port =
cpu_to_be32(
@@ -640,7 +640,7 @@
continue;
if (i == mlx4_master_func_num(dev))
continue;
- s_info = &priv->mfunc.master.vf_oper[slave].vport[port].state;
+ s_info = &priv->mfunc.master.vf_oper[i].vport[port].state;
if (IFLA_VF_LINK_STATE_AUTO == s_info->link_state) {
eqe->event.port_change.port =
cpu_to_be32(
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 12fbfcb..29c2a01 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -2273,6 +2273,11 @@
} else if (err == -ENOENT) {
err = 0;
continue;
+ } else if (mlx4_is_slave(dev) && err == -EINVAL) {
+ priv->def_counter[port] = MLX4_SINK_COUNTER_INDEX(dev);
+ mlx4_warn(dev, "can't allocate counter from old PF driver, using index %d\n",
+ MLX4_SINK_COUNTER_INDEX(dev));
+ err = 0;
} else {
mlx4_err(dev, "%s: failed to allocate default counter port %d err %d\n",
__func__, port + 1, err);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index afad529..06e3e1e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -391,6 +391,8 @@
/* disable cmdif checksum */
MLX5_SET(cmd_hca_cap, set_hca_cap, cmdif_checksum, 0);
+ MLX5_SET(cmd_hca_cap, set_hca_cap, log_uar_page_sz, PAGE_SHIFT - 12);
+
err = set_caps(dev, set_ctx, set_sz);
query_ex:
diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c
index f78909a..09d2e16 100644
--- a/drivers/net/ethernet/micrel/ks8842.c
+++ b/drivers/net/ethernet/micrel/ks8842.c
@@ -952,9 +952,8 @@
sg_dma_address(&tx_ctl->sg) = dma_map_single(adapter->dev,
tx_ctl->buf, DMA_BUFFER_SIZE, DMA_TO_DEVICE);
- err = dma_mapping_error(adapter->dev,
- sg_dma_address(&tx_ctl->sg));
- if (err) {
+ if (dma_mapping_error(adapter->dev, sg_dma_address(&tx_ctl->sg))) {
+ err = -ENOMEM;
sg_dma_address(&tx_ctl->sg) = 0;
goto err;
}
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
index 33669c2..753ea8b 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c
@@ -1415,7 +1415,7 @@
if (fw->size & 0xF) {
addr = dest + size;
for (i = 0; i < (fw->size & 0xF); i++)
- data[i] = temp[size + i];
+ data[i] = ((u8 *)temp)[size + i];
for (; i < 16; i++)
data[i] = 0;
ret = qlcnic_ms_mem_write128(adapter, addr,
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 3df51fa..f790f61 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -4875,10 +4875,12 @@
case RTL_GIGA_MAC_VER_46:
case RTL_GIGA_MAC_VER_47:
case RTL_GIGA_MAC_VER_48:
+ RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
+ break;
case RTL_GIGA_MAC_VER_49:
case RTL_GIGA_MAC_VER_50:
case RTL_GIGA_MAC_VER_51:
- RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF);
+ RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
break;
default:
RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST);
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index fd97457..78849dd 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -228,9 +228,7 @@
struct ravb_desc *desc = NULL;
int rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q];
int tx_ring_size = sizeof(*tx_desc) * priv->num_tx_ring[q];
- struct sk_buff *skb;
dma_addr_t dma_addr;
- void *buffer;
int i;
priv->cur_rx[q] = 0;
@@ -241,41 +239,28 @@
memset(priv->rx_ring[q], 0, rx_ring_size);
/* Build RX ring buffer */
for (i = 0; i < priv->num_rx_ring[q]; i++) {
- priv->rx_skb[q][i] = NULL;
- skb = netdev_alloc_skb(ndev, PKT_BUF_SZ + RAVB_ALIGN - 1);
- if (!skb)
- break;
- ravb_set_buffer_align(skb);
/* RX descriptor */
rx_desc = &priv->rx_ring[q][i];
/* The size of the buffer should be on 16-byte boundary. */
rx_desc->ds_cc = cpu_to_le16(ALIGN(PKT_BUF_SZ, 16));
- dma_addr = dma_map_single(&ndev->dev, skb->data,
+ dma_addr = dma_map_single(&ndev->dev, priv->rx_skb[q][i]->data,
ALIGN(PKT_BUF_SZ, 16),
DMA_FROM_DEVICE);
- if (dma_mapping_error(&ndev->dev, dma_addr)) {
- dev_kfree_skb(skb);
- break;
- }
- priv->rx_skb[q][i] = skb;
+ /* We just set the data size to 0 for a failed mapping which
+ * should prevent DMA from happening...
+ */
+ if (dma_mapping_error(&ndev->dev, dma_addr))
+ rx_desc->ds_cc = cpu_to_le16(0);
rx_desc->dptr = cpu_to_le32(dma_addr);
rx_desc->die_dt = DT_FEMPTY;
}
rx_desc = &priv->rx_ring[q][i];
rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]);
rx_desc->die_dt = DT_LINKFIX; /* type */
- priv->dirty_rx[q] = (u32)(i - priv->num_rx_ring[q]);
memset(priv->tx_ring[q], 0, tx_ring_size);
/* Build TX ring buffer */
for (i = 0; i < priv->num_tx_ring[q]; i++) {
- priv->tx_skb[q][i] = NULL;
- priv->tx_buffers[q][i] = NULL;
- buffer = kmalloc(PKT_BUF_SZ + RAVB_ALIGN - 1, GFP_KERNEL);
- if (!buffer)
- break;
- /* Aligned TX buffer */
- priv->tx_buffers[q][i] = buffer;
tx_desc = &priv->tx_ring[q][i];
tx_desc->die_dt = DT_EEMPTY;
}
@@ -298,7 +283,10 @@
static int ravb_ring_init(struct net_device *ndev, int q)
{
struct ravb_private *priv = netdev_priv(ndev);
+ struct sk_buff *skb;
int ring_size;
+ void *buffer;
+ int i;
/* Allocate RX and TX skb rings */
priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q],
@@ -308,12 +296,28 @@
if (!priv->rx_skb[q] || !priv->tx_skb[q])
goto error;
+ for (i = 0; i < priv->num_rx_ring[q]; i++) {
+ skb = netdev_alloc_skb(ndev, PKT_BUF_SZ + RAVB_ALIGN - 1);
+ if (!skb)
+ goto error;
+ ravb_set_buffer_align(skb);
+ priv->rx_skb[q][i] = skb;
+ }
+
/* Allocate rings for the aligned buffers */
priv->tx_buffers[q] = kcalloc(priv->num_tx_ring[q],
sizeof(*priv->tx_buffers[q]), GFP_KERNEL);
if (!priv->tx_buffers[q])
goto error;
+ for (i = 0; i < priv->num_tx_ring[q]; i++) {
+ buffer = kmalloc(PKT_BUF_SZ + RAVB_ALIGN - 1, GFP_KERNEL);
+ if (!buffer)
+ goto error;
+ /* Aligned TX buffer */
+ priv->tx_buffers[q][i] = buffer;
+ }
+
/* Allocate all RX descriptors. */
ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1);
priv->rx_ring[q] = dma_alloc_coherent(NULL, ring_size,
@@ -524,6 +528,10 @@
if (--boguscnt < 0)
break;
+ /* We use 0-byte descriptors to mark the DMA mapping errors */
+ if (!pkt_len)
+ continue;
+
if (desc_status & MSC_MC)
stats->multicast++;
@@ -543,10 +551,9 @@
skb = priv->rx_skb[q][entry];
priv->rx_skb[q][entry] = NULL;
- dma_sync_single_for_cpu(&ndev->dev,
- le32_to_cpu(desc->dptr),
- ALIGN(PKT_BUF_SZ, 16),
- DMA_FROM_DEVICE);
+ dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr),
+ ALIGN(PKT_BUF_SZ, 16),
+ DMA_FROM_DEVICE);
get_ts &= (q == RAVB_NC) ?
RAVB_RXTSTAMP_TYPE_V2_L2_EVENT :
~RAVB_RXTSTAMP_TYPE_V2_L2_EVENT;
@@ -584,17 +591,15 @@
if (!skb)
break; /* Better luck next round. */
ravb_set_buffer_align(skb);
- dma_unmap_single(&ndev->dev, le32_to_cpu(desc->dptr),
- ALIGN(PKT_BUF_SZ, 16),
- DMA_FROM_DEVICE);
dma_addr = dma_map_single(&ndev->dev, skb->data,
le16_to_cpu(desc->ds_cc),
DMA_FROM_DEVICE);
skb_checksum_none_assert(skb);
- if (dma_mapping_error(&ndev->dev, dma_addr)) {
- dev_kfree_skb_any(skb);
- break;
- }
+ /* We just set the data size to 0 for a failed mapping
+ * which should prevent DMA from happening...
+ */
+ if (dma_mapping_error(&ndev->dev, dma_addr))
+ desc->ds_cc = cpu_to_le16(0);
desc->dptr = cpu_to_le32(dma_addr);
priv->rx_skb[q][entry] = skb;
}
@@ -1279,7 +1284,6 @@
u32 dma_addr;
void *buffer;
u32 entry;
- u32 tccr;
spin_lock_irqsave(&priv->lock, flags);
if (priv->cur_tx[q] - priv->dirty_tx[q] >= priv->num_tx_ring[q]) {
@@ -1328,9 +1332,7 @@
dma_wmb();
desc->die_dt = DT_FSINGLE;
- tccr = ravb_read(ndev, TCCR);
- if (!(tccr & (TCCR_TSRQ0 << q)))
- ravb_write(ndev, tccr | (TCCR_TSRQ0 << q), TCCR);
+ ravb_write(ndev, ravb_read(ndev, TCCR) | (TCCR_TSRQ0 << q), TCCR);
priv->cur_tx[q]++;
if (priv->cur_tx[q] - priv->dirty_tx[q] >= priv->num_tx_ring[q] &&
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index 2d8578cade..2e7f9a2 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -4821,6 +4821,7 @@
rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE,
ROCKER_OP_FLAG_REMOVE);
unregister_netdev(rocker_port->dev);
+ free_netdev(rocker_port->dev);
}
kfree(rocker->ports);
}
diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c
index 605cc89..b1a4ea2 100644
--- a/drivers/net/ethernet/sfc/ef10.c
+++ b/drivers/net/ethernet/sfc/ef10.c
@@ -1282,7 +1282,12 @@
}
}
- if (core_stats) {
+ if (!core_stats)
+ return stats_count;
+
+ if (nic_data->datapath_caps &
+ 1 << MC_CMD_GET_CAPABILITIES_OUT_EVB_LBN) {
+ /* Use vadaptor stats. */
core_stats->rx_packets = stats[EF10_STAT_rx_unicast] +
stats[EF10_STAT_rx_multicast] +
stats[EF10_STAT_rx_broadcast];
@@ -1302,6 +1307,26 @@
core_stats->rx_fifo_errors = stats[EF10_STAT_rx_overflow];
core_stats->rx_errors = core_stats->rx_crc_errors;
core_stats->tx_errors = stats[EF10_STAT_tx_bad];
+ } else {
+ /* Use port stats. */
+ core_stats->rx_packets = stats[EF10_STAT_port_rx_packets];
+ core_stats->tx_packets = stats[EF10_STAT_port_tx_packets];
+ core_stats->rx_bytes = stats[EF10_STAT_port_rx_bytes];
+ core_stats->tx_bytes = stats[EF10_STAT_port_tx_bytes];
+ core_stats->rx_dropped = stats[EF10_STAT_port_rx_nodesc_drops] +
+ stats[GENERIC_STAT_rx_nodesc_trunc] +
+ stats[GENERIC_STAT_rx_noskb_drops];
+ core_stats->multicast = stats[EF10_STAT_port_rx_multicast];
+ core_stats->rx_length_errors =
+ stats[EF10_STAT_port_rx_gtjumbo] +
+ stats[EF10_STAT_port_rx_length_error];
+ core_stats->rx_crc_errors = stats[EF10_STAT_port_rx_bad];
+ core_stats->rx_frame_errors =
+ stats[EF10_STAT_port_rx_align_error];
+ core_stats->rx_fifo_errors = stats[EF10_STAT_port_rx_overflow];
+ core_stats->rx_errors = (core_stats->rx_length_errors +
+ core_stats->rx_crc_errors +
+ core_stats->rx_frame_errors);
}
return stats_count;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
index 7e3129e..f0e4bb4 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
@@ -42,7 +42,7 @@
#define NSS_COMMON_CLK_DIV_MASK 0x7f
#define NSS_COMMON_CLK_SRC_CTRL 0x14
-#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x) (1 << x)
+#define NSS_COMMON_CLK_SRC_CTRL_OFFSET(x) (x)
/* Mode is coded on 1 bit but is different depending on the MAC ID:
* MAC0: QSGMII=0 RGMII=1
* MAC1: QSGMII=0 SGMII=0 RGMII=1
@@ -291,7 +291,7 @@
/* Configure the clock src according to the mode */
regmap_read(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, &val);
- val &= ~NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id);
+ val &= ~(1 << NSS_COMMON_CLK_SRC_CTRL_OFFSET(gmac->id));
switch (gmac->phy_mode) {
case PHY_INTERFACE_MODE_RGMII:
val |= NSS_COMMON_CLK_SRC_CTRL_RGMII(gmac->id) <<
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 50f7a7a..864b476 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -2843,7 +2843,7 @@
if (res->mac)
memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
- dev_set_drvdata(device, priv);
+ dev_set_drvdata(device, priv->dev);
/* Verify driver arguments */
stmmac_verify_args();
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index f3918c7..bcdc895 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -413,3 +413,7 @@
SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops, stmmac_pltfr_suspend,
stmmac_pltfr_resume);
EXPORT_SYMBOL_GPL(stmmac_pltfr_pm_ops);
+
+MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet platform support");
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index 0c5842a..ab6051a 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -6658,10 +6658,8 @@
struct sk_buff *skb_new;
skb_new = skb_realloc_headroom(skb, len);
- if (!skb_new) {
- rp->tx_errors++;
+ if (!skb_new)
goto out_drop;
- }
kfree_skb(skb);
skb = skb_new;
} else
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index f335bf1..d155bf2 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -793,9 +793,7 @@
static int cpsw_poll(struct napi_struct *napi, int budget)
{
struct cpsw_priv *priv = napi_to_priv(napi);
- int num_tx, num_rx;
-
- num_tx = cpdma_chan_process(priv->txch, 128);
+ int num_rx;
num_rx = cpdma_chan_process(priv->rxch, budget);
if (num_rx < budget) {
@@ -810,9 +808,8 @@
}
}
- if (num_rx || num_tx)
- cpsw_dbg(priv, intr, "poll %d rx, %d tx pkts\n",
- num_rx, num_tx);
+ if (num_rx)
+ cpsw_dbg(priv, intr, "poll %d rx pkts\n", num_rx);
return num_rx;
}
diff --git a/drivers/net/ethernet/ti/netcp.h b/drivers/net/ethernet/ti/netcp.h
index bbacf5c..bb1bb72 100644
--- a/drivers/net/ethernet/ti/netcp.h
+++ b/drivers/net/ethernet/ti/netcp.h
@@ -85,7 +85,6 @@
struct list_head rxhook_list_head;
unsigned int rx_queue_id;
void *rx_fdq[KNAV_DMA_FDQ_PER_CHAN];
- u32 rx_buffer_sizes[KNAV_DMA_FDQ_PER_CHAN];
struct napi_struct rx_napi;
struct napi_struct tx_napi;
@@ -223,6 +222,7 @@
/* SGMII functions */
int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port);
+bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set);
int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port);
int netcp_sgmii_config(void __iomem *sgmii_ofs, int port, u32 interface);
diff --git a/drivers/net/ethernet/ti/netcp_core.c b/drivers/net/ethernet/ti/netcp_core.c
index 5ec4ed3..4755838 100644
--- a/drivers/net/ethernet/ti/netcp_core.c
+++ b/drivers/net/ethernet/ti/netcp_core.c
@@ -34,6 +34,7 @@
#define NETCP_SOP_OFFSET (NET_IP_ALIGN + NET_SKB_PAD)
#define NETCP_NAPI_WEIGHT 64
#define NETCP_TX_TIMEOUT (5 * HZ)
+#define NETCP_PACKET_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN)
#define NETCP_MIN_PACKET_SIZE ETH_ZLEN
#define NETCP_MAX_MCAST_ADDR 16
@@ -804,30 +805,28 @@
if (likely(fdq == 0)) {
unsigned int primary_buf_len;
/* Allocate a primary receive queue entry */
- buf_len = netcp->rx_buffer_sizes[0] + NETCP_SOP_OFFSET;
+ buf_len = NETCP_PACKET_SIZE + NETCP_SOP_OFFSET;
primary_buf_len = SKB_DATA_ALIGN(buf_len) +
SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
- if (primary_buf_len <= PAGE_SIZE) {
- bufptr = netdev_alloc_frag(primary_buf_len);
- pad[1] = primary_buf_len;
- } else {
- bufptr = kmalloc(primary_buf_len, GFP_ATOMIC |
- GFP_DMA32 | __GFP_COLD);
- pad[1] = 0;
- }
+ bufptr = netdev_alloc_frag(primary_buf_len);
+ pad[1] = primary_buf_len;
if (unlikely(!bufptr)) {
- dev_warn_ratelimited(netcp->ndev_dev, "Primary RX buffer alloc failed\n");
+ dev_warn_ratelimited(netcp->ndev_dev,
+ "Primary RX buffer alloc failed\n");
goto fail;
}
dma = dma_map_single(netcp->dev, bufptr, buf_len,
DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(netcp->dev, dma)))
+ goto fail;
+
pad[0] = (u32)bufptr;
} else {
/* Allocate a secondary receive queue entry */
- page = alloc_page(GFP_ATOMIC | GFP_DMA32 | __GFP_COLD);
+ page = alloc_page(GFP_ATOMIC | GFP_DMA | __GFP_COLD);
if (unlikely(!page)) {
dev_warn_ratelimited(netcp->ndev_dev, "Secondary page alloc failed\n");
goto fail;
@@ -1010,7 +1009,7 @@
/* Map the linear buffer */
dma_addr = dma_map_single(dev, skb->data, pkt_len, DMA_TO_DEVICE);
- if (unlikely(!dma_addr)) {
+ if (unlikely(dma_mapping_error(dev, dma_addr))) {
dev_err(netcp->ndev_dev, "Failed to map skb buffer\n");
return NULL;
}
@@ -1546,8 +1545,8 @@
knav_queue_disable_notify(netcp->rx_queue);
/* open Rx FDQs */
- for (i = 0; i < KNAV_DMA_FDQ_PER_CHAN &&
- netcp->rx_queue_depths[i] && netcp->rx_buffer_sizes[i]; ++i) {
+ for (i = 0; i < KNAV_DMA_FDQ_PER_CHAN && netcp->rx_queue_depths[i];
+ ++i) {
snprintf(name, sizeof(name), "rx-fdq-%s-%d", ndev->name, i);
netcp->rx_fdq[i] = knav_queue_open(name, KNAV_QUEUE_GP, 0);
if (IS_ERR_OR_NULL(netcp->rx_fdq[i])) {
@@ -1617,11 +1616,11 @@
}
mutex_unlock(&netcp_modules_lock);
- netcp_rxpool_refill(netcp);
napi_enable(&netcp->rx_napi);
napi_enable(&netcp->tx_napi);
knav_queue_enable_notify(netcp->tx_compl_q);
knav_queue_enable_notify(netcp->rx_queue);
+ netcp_rxpool_refill(netcp);
netif_tx_wake_all_queues(ndev);
dev_dbg(netcp->ndev_dev, "netcp device %s opened\n", ndev->name);
return 0;
@@ -1941,14 +1940,6 @@
netcp->rx_queue_depths[0] = 128;
}
- ret = of_property_read_u32_array(node_interface, "rx-buffer-size",
- netcp->rx_buffer_sizes,
- KNAV_DMA_FDQ_PER_CHAN);
- if (ret) {
- dev_err(dev, "missing \"rx-buffer-size\" parameter\n");
- netcp->rx_buffer_sizes[0] = 1536;
- }
-
ret = of_property_read_u32_array(node_interface, "rx-pool", temp, 2);
if (ret < 0) {
dev_err(dev, "missing \"rx-pool\" parameter\n");
@@ -2112,6 +2103,7 @@
static int netcp_remove(struct platform_device *pdev)
{
struct netcp_device *netcp_device = platform_get_drvdata(pdev);
+ struct netcp_intf *netcp_intf, *netcp_tmp;
struct netcp_inst_modpriv *inst_modpriv, *tmp;
struct netcp_module *module;
@@ -2123,10 +2115,17 @@
list_del(&inst_modpriv->inst_list);
kfree(inst_modpriv);
}
- WARN(!list_empty(&netcp_device->interface_head), "%s interface list not empty!\n",
- pdev->name);
- devm_kfree(&pdev->dev, netcp_device);
+ /* now that all modules are removed, clean up the interfaces */
+ list_for_each_entry_safe(netcp_intf, netcp_tmp,
+ &netcp_device->interface_head,
+ interface_list) {
+ netcp_delete_interface(netcp_device, netcp_intf->ndev);
+ }
+
+ WARN(!list_empty(&netcp_device->interface_head),
+ "%s interface list not empty!\n", pdev->name);
+
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
platform_set_drvdata(pdev, NULL);
diff --git a/drivers/net/ethernet/ti/netcp_ethss.c b/drivers/net/ethernet/ti/netcp_ethss.c
index 9b7e0a3..1974a8a 100644
--- a/drivers/net/ethernet/ti/netcp_ethss.c
+++ b/drivers/net/ethernet/ti/netcp_ethss.c
@@ -1901,11 +1901,28 @@
writel(slave->mac_control, GBE_REG_ADDR(slave, emac_regs, mac_control));
}
+static void gbe_sgmii_rtreset(struct gbe_priv *priv,
+ struct gbe_slave *slave, bool set)
+{
+ void __iomem *sgmii_port_regs;
+
+ if (SLAVE_LINK_IS_XGMII(slave))
+ return;
+
+ if ((priv->ss_version == GBE_SS_VERSION_14) && (slave->slave_num >= 2))
+ sgmii_port_regs = priv->sgmii_port34_regs;
+ else
+ sgmii_port_regs = priv->sgmii_port_regs;
+
+ netcp_sgmii_rtreset(sgmii_port_regs, slave->slave_num, set);
+}
+
static void gbe_slave_stop(struct gbe_intf *intf)
{
struct gbe_priv *gbe_dev = intf->gbe_dev;
struct gbe_slave *slave = intf->slave;
+ gbe_sgmii_rtreset(gbe_dev, slave, true);
gbe_port_reset(slave);
/* Disable forwarding */
cpsw_ale_control_set(gbe_dev->ale, slave->port_num,
@@ -1947,6 +1964,7 @@
gbe_sgmii_config(priv, slave);
gbe_port_reset(slave);
+ gbe_sgmii_rtreset(priv, slave, false);
gbe_port_config(priv, slave, priv->rx_packet_max);
gbe_set_slave_mac(slave, gbe_intf);
/* enable forwarding */
@@ -2490,10 +2508,9 @@
{
struct gbe_slave *slave;
- for (;;) {
+ while (!list_empty(&gbe_dev->secondary_slaves)) {
slave = first_sec_slave(gbe_dev);
- if (!slave)
- break;
+
if (slave->phy)
phy_disconnect(slave->phy);
list_del(&slave->slave_list);
@@ -2839,14 +2856,13 @@
&gbe_dev->dma_chan_name);
if (ret < 0) {
dev_err(dev, "missing \"tx-channel\" parameter\n");
- ret = -ENODEV;
- goto quit;
+ return -EINVAL;
}
if (!strcmp(node->name, "gbe")) {
ret = get_gbe_resource_version(gbe_dev, node);
if (ret)
- goto quit;
+ return ret;
dev_dbg(dev, "ss_version: 0x%08x\n", gbe_dev->ss_version);
@@ -2857,22 +2873,20 @@
else
ret = -ENODEV;
- if (ret)
- goto quit;
} else if (!strcmp(node->name, "xgbe")) {
ret = set_xgbe_ethss10_priv(gbe_dev, node);
if (ret)
- goto quit;
+ return ret;
ret = netcp_xgbe_serdes_init(gbe_dev->xgbe_serdes_regs,
gbe_dev->ss_regs);
- if (ret)
- goto quit;
} else {
dev_err(dev, "unknown GBE node(%s)\n", node->name);
ret = -ENODEV;
- goto quit;
}
+ if (ret)
+ return ret;
+
interfaces = of_get_child_by_name(node, "interfaces");
if (!interfaces)
dev_err(dev, "could not find interfaces\n");
@@ -2880,11 +2894,11 @@
ret = netcp_txpipe_init(&gbe_dev->tx_pipe, netcp_device,
gbe_dev->dma_chan_name, gbe_dev->tx_queue_id);
if (ret)
- goto quit;
+ return ret;
ret = netcp_txpipe_open(&gbe_dev->tx_pipe);
if (ret)
- goto quit;
+ return ret;
/* Create network interfaces */
INIT_LIST_HEAD(&gbe_dev->gbe_intf_head);
@@ -2899,6 +2913,7 @@
if (gbe_dev->num_slaves >= gbe_dev->max_num_slaves)
break;
}
+ of_node_put(interfaces);
if (!gbe_dev->num_slaves)
dev_warn(dev, "No network interface configured\n");
@@ -2911,9 +2926,10 @@
of_node_put(secondary_ports);
if (!gbe_dev->num_slaves) {
- dev_err(dev, "No network interface or secondary ports configured\n");
+ dev_err(dev,
+ "No network interface or secondary ports configured\n");
ret = -ENODEV;
- goto quit;
+ goto free_sec_ports;
}
memset(&ale_params, 0, sizeof(ale_params));
@@ -2927,7 +2943,7 @@
if (!gbe_dev->ale) {
dev_err(gbe_dev->dev, "error initializing ale engine\n");
ret = -ENODEV;
- goto quit;
+ goto free_sec_ports;
} else {
dev_dbg(gbe_dev->dev, "Created a gbe ale engine\n");
}
@@ -2943,14 +2959,8 @@
*inst_priv = gbe_dev;
return 0;
-quit:
- if (gbe_dev->hw_stats)
- devm_kfree(dev, gbe_dev->hw_stats);
- cpsw_ale_destroy(gbe_dev->ale);
- if (gbe_dev->ss_regs)
- devm_iounmap(dev, gbe_dev->ss_regs);
- of_node_put(interfaces);
- devm_kfree(dev, gbe_dev);
+free_sec_ports:
+ free_secondary_ports(gbe_dev);
return ret;
}
@@ -3023,12 +3033,9 @@
free_secondary_ports(gbe_dev);
if (!list_empty(&gbe_dev->gbe_intf_head))
- dev_alert(gbe_dev->dev, "unreleased ethss interfaces present\n");
+ dev_alert(gbe_dev->dev,
+ "unreleased ethss interfaces present\n");
- devm_kfree(gbe_dev->dev, gbe_dev->hw_stats);
- devm_iounmap(gbe_dev->dev, gbe_dev->ss_regs);
- memset(gbe_dev, 0x00, sizeof(*gbe_dev));
- devm_kfree(gbe_dev->dev, gbe_dev);
return 0;
}
diff --git a/drivers/net/ethernet/ti/netcp_sgmii.c b/drivers/net/ethernet/ti/netcp_sgmii.c
index dbeb142..5d8419f 100644
--- a/drivers/net/ethernet/ti/netcp_sgmii.c
+++ b/drivers/net/ethernet/ti/netcp_sgmii.c
@@ -18,6 +18,9 @@
#include "netcp.h"
+#define SGMII_SRESET_RESET BIT(0)
+#define SGMII_SRESET_RTRESET BIT(1)
+
#define SGMII_REG_STATUS_LOCK BIT(4)
#define SGMII_REG_STATUS_LINK BIT(0)
#define SGMII_REG_STATUS_AUTONEG BIT(2)
@@ -51,12 +54,35 @@
int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port)
{
/* Soft reset */
- sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port), 0x1);
- while (sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) != 0x0)
+ sgmii_write_reg_bit(sgmii_ofs, SGMII_SRESET_REG(port),
+ SGMII_SRESET_RESET);
+
+ while ((sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port)) &
+ SGMII_SRESET_RESET) != 0x0)
;
+
return 0;
}
+/* port is 0 based */
+bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set)
+{
+ u32 reg;
+ bool oldval;
+
+ /* Initiate a soft reset */
+ reg = sgmii_read_reg(sgmii_ofs, SGMII_SRESET_REG(port));
+ oldval = (reg & SGMII_SRESET_RTRESET) != 0x0;
+ if (set)
+ reg |= SGMII_SRESET_RTRESET;
+ else
+ reg &= ~SGMII_SRESET_RTRESET;
+ sgmii_write_reg(sgmii_ofs, SGMII_SRESET_REG(port), reg);
+ wmb();
+
+ return oldval;
+}
+
int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port)
{
u32 status = 0, link = 0;
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index 2ffbf13..216bfd3 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -728,11 +728,12 @@
dev->type = ARPHRD_AX25;
/* Perform the low-level AX25 initialization. */
- if ((err = ax_open(ax->dev))) {
+ err = ax_open(ax->dev);
+ if (err)
goto out_free_netdev;
- }
- if (register_netdev(dev))
+ err = register_netdev(dev);
+ if (err)
goto out_free_buffers;
/* after register_netdev() - because else printk smashes the kernel */
diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h
index 953a974..9542b7b 100644
--- a/drivers/net/ipvlan/ipvlan.h
+++ b/drivers/net/ipvlan/ipvlan.h
@@ -67,8 +67,6 @@
struct ipvl_port *port;
struct net_device *phy_dev;
struct list_head addrs;
- int ipv4cnt;
- int ipv6cnt;
struct ipvl_pcpu_stats __percpu *pcpu_stats;
DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE);
netdev_features_t sfeatures;
@@ -106,6 +104,11 @@
return rcu_dereference(d->rx_handler_data);
}
+static inline struct ipvl_port *ipvlan_port_get_rcu_bh(const struct net_device *d)
+{
+ return rcu_dereference_bh(d->rx_handler_data);
+}
+
static inline struct ipvl_port *ipvlan_port_get_rtnl(const struct net_device *d)
{
return rtnl_dereference(d->rx_handler_data);
@@ -124,5 +127,5 @@
bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6);
struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port,
const void *iaddr, bool is_v6);
-void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync);
+void ipvlan_ht_addr_del(struct ipvl_addr *addr);
#endif /* __IPVLAN_H */
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c
index 8afbeda..207f62e 100644
--- a/drivers/net/ipvlan/ipvlan_core.c
+++ b/drivers/net/ipvlan/ipvlan_core.c
@@ -85,11 +85,9 @@
hlist_add_head_rcu(&addr->hlnode, &port->hlhead[hash]);
}
-void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync)
+void ipvlan_ht_addr_del(struct ipvl_addr *addr)
{
hlist_del_init_rcu(&addr->hlnode);
- if (sync)
- synchronize_rcu();
}
struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
@@ -531,7 +529,7 @@
int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ipvl_dev *ipvlan = netdev_priv(dev);
- struct ipvl_port *port = ipvlan_port_get_rcu(ipvlan->phy_dev);
+ struct ipvl_port *port = ipvlan_port_get_rcu_bh(ipvlan->phy_dev);
if (!port)
goto out;
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c
index 1acc283..20b58bd 100644
--- a/drivers/net/ipvlan/ipvlan_main.c
+++ b/drivers/net/ipvlan/ipvlan_main.c
@@ -153,10 +153,9 @@
else
dev->flags &= ~IFF_NOARP;
- if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) {
- list_for_each_entry(addr, &ipvlan->addrs, anode)
- ipvlan_ht_addr_add(ipvlan, addr);
- }
+ list_for_each_entry(addr, &ipvlan->addrs, anode)
+ ipvlan_ht_addr_add(ipvlan, addr);
+
return dev_uc_add(phy_dev, phy_dev->dev_addr);
}
@@ -171,10 +170,9 @@
dev_uc_del(phy_dev, phy_dev->dev_addr);
- if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) {
- list_for_each_entry(addr, &ipvlan->addrs, anode)
- ipvlan_ht_addr_del(addr, !dev->dismantle);
- }
+ list_for_each_entry(addr, &ipvlan->addrs, anode)
+ ipvlan_ht_addr_del(addr);
+
return 0;
}
@@ -471,8 +469,6 @@
ipvlan->port = port;
ipvlan->sfeatures = IPVLAN_FEATURES;
INIT_LIST_HEAD(&ipvlan->addrs);
- ipvlan->ipv4cnt = 0;
- ipvlan->ipv6cnt = 0;
/* TODO Probably put random address here to be presented to the
* world but keep using the physical-dev address for the outgoing
@@ -508,12 +504,12 @@
struct ipvl_dev *ipvlan = netdev_priv(dev);
struct ipvl_addr *addr, *next;
- if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) {
- list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) {
- ipvlan_ht_addr_del(addr, !dev->dismantle);
- list_del(&addr->anode);
- }
+ list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) {
+ ipvlan_ht_addr_del(addr);
+ list_del(&addr->anode);
+ kfree_rcu(addr, rcu);
}
+
list_del_rcu(&ipvlan->pnode);
unregister_netdevice_queue(dev, head);
netdev_upper_dev_unlink(ipvlan->phy_dev, dev);
@@ -627,7 +623,7 @@
memcpy(&addr->ip6addr, ip6_addr, sizeof(struct in6_addr));
addr->atype = IPVL_IPV6;
list_add_tail(&addr->anode, &ipvlan->addrs);
- ipvlan->ipv6cnt++;
+
/* If the interface is not up, the address will be added to the hash
* list by ipvlan_open.
*/
@@ -645,10 +641,8 @@
if (!addr)
return;
- ipvlan_ht_addr_del(addr, true);
+ ipvlan_ht_addr_del(addr);
list_del(&addr->anode);
- ipvlan->ipv6cnt--;
- WARN_ON(ipvlan->ipv6cnt < 0);
kfree_rcu(addr, rcu);
return;
@@ -661,6 +655,10 @@
struct net_device *dev = (struct net_device *)if6->idev->dev;
struct ipvl_dev *ipvlan = netdev_priv(dev);
+ /* FIXME IPv6 autoconf calls us from bh without RTNL */
+ if (in_softirq())
+ return NOTIFY_DONE;
+
if (!netif_is_ipvlan(dev))
return NOTIFY_DONE;
@@ -699,7 +697,7 @@
memcpy(&addr->ip4addr, ip4_addr, sizeof(struct in_addr));
addr->atype = IPVL_IPV4;
list_add_tail(&addr->anode, &ipvlan->addrs);
- ipvlan->ipv4cnt++;
+
/* If the interface is not up, the address will be added to the hash
* list by ipvlan_open.
*/
@@ -717,10 +715,8 @@
if (!addr)
return;
- ipvlan_ht_addr_del(addr, true);
+ ipvlan_ht_addr_del(addr);
list_del(&addr->anode);
- ipvlan->ipv4cnt--;
- WARN_ON(ipvlan->ipv4cnt < 0);
kfree_rcu(addr, rcu);
return;
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c
index 3b933bb..edd7734 100644
--- a/drivers/net/macvtap.c
+++ b/drivers/net/macvtap.c
@@ -719,6 +719,7 @@
struct virtio_net_hdr vnet_hdr = { 0 };
int vnet_hdr_len = 0;
int copylen = 0;
+ int depth;
bool zerocopy = false;
size_t linear;
ssize_t n;
@@ -804,6 +805,12 @@
skb_probe_transport_header(skb, ETH_HLEN);
+ /* Move network header to the right position for VLAN tagged packets */
+ if ((skb->protocol == htons(ETH_P_8021Q) ||
+ skb->protocol == htons(ETH_P_8021AD)) &&
+ __vlan_get_protocol(skb, skb->protocol, &depth) != 0)
+ skb_set_network_header(skb, depth);
+
rcu_read_lock();
vlan = rcu_dereference(q->vlan);
/* copy skb_ubuf_info for callback when skb has no error */
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index 3cc316cb..d8757bf 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -102,6 +102,12 @@
netdev_dbg(ndev, "%s: %d byte payload received\n", __func__, len);
+ if (len < 0) {
+ ndev->stats.rx_errors++;
+ ndev->stats.rx_length_errors++;
+ goto enqueue_again;
+ }
+
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, ndev);
skb->ip_summed = CHECKSUM_NONE;
@@ -121,6 +127,7 @@
return;
}
+enqueue_again:
rc = ntb_transport_rx_enqueue(qp, skb, skb->data, ndev->mtu + ETH_HLEN);
if (rc) {
dev_kfree_skb(skb);
@@ -184,7 +191,7 @@
rc = ntb_transport_rx_enqueue(dev->qp, skb, skb->data,
ndev->mtu + ETH_HLEN);
- if (rc == -EINVAL) {
+ if (rc) {
dev_kfree_skb(skb);
goto err;
}
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index c7a12e2..8a3bf54 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -164,7 +164,7 @@
return ret;
}
- if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) ||
+ if ((phydev->interface >= PHY_INTERFACE_MODE_RGMII_ID) &&
(phydev->interface <= PHY_INTERFACE_MODE_RGMII_RXID)) {
val = phy_read_mmd_indirect(phydev, DP83867_RGMIICTL,
DP83867_DEVADDR, phydev->addr);
diff --git a/drivers/net/phy/fixed_phy.c b/drivers/net/phy/fixed_phy.c
index 1960b46..d7a6524 100644
--- a/drivers/net/phy/fixed_phy.c
+++ b/drivers/net/phy/fixed_phy.c
@@ -290,6 +290,15 @@
return ERR_PTR(-EINVAL);
}
+ /* propagate the fixed link values to struct phy_device */
+ phy->link = status->link;
+ if (status->link) {
+ phy->speed = status->speed;
+ phy->duplex = status->duplex;
+ phy->pause = status->pause;
+ phy->asym_pause = status->asym_pause;
+ }
+
of_node_get(np);
phy->dev.of_node = np;
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 095ef3f..46a14cb 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -421,6 +421,8 @@
{
struct phy_device *phydev = to_phy_device(dev);
struct phy_driver *phydrv = to_phy_driver(drv);
+ const int num_ids = ARRAY_SIZE(phydev->c45_ids.device_ids);
+ int i;
if (of_driver_match_device(dev, drv))
return 1;
@@ -428,8 +430,21 @@
if (phydrv->match_phy_device)
return phydrv->match_phy_device(phydev);
- return (phydrv->phy_id & phydrv->phy_id_mask) ==
- (phydev->phy_id & phydrv->phy_id_mask);
+ if (phydev->is_c45) {
+ for (i = 1; i < num_ids; i++) {
+ if (!(phydev->c45_ids.devices_in_package & (1 << i)))
+ continue;
+
+ if ((phydrv->phy_id & phydrv->phy_id_mask) ==
+ (phydev->c45_ids.device_ids[i] &
+ phydrv->phy_id_mask))
+ return 1;
+ }
+ return 0;
+ } else {
+ return (phydrv->phy_id & phydrv->phy_id_mask) ==
+ (phydev->phy_id & phydrv->phy_id_mask);
+ }
}
#ifdef CONFIG_PM
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index b2197b5..34fe339 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -811,6 +811,7 @@
bool needs_aneg = false, do_suspend = false;
enum phy_state old_state;
int err = 0;
+ int old_link;
mutex_lock(&phydev->lock);
@@ -896,11 +897,18 @@
phydev->adjust_link(phydev->attached_dev);
break;
case PHY_RUNNING:
- /* Only register a CHANGE if we are
- * polling or ignoring interrupts
+ /* Only register a CHANGE if we are polling or ignoring
+ * interrupts and link changed since latest checking.
*/
- if (!phy_interrupt_is_valid(phydev))
- phydev->state = PHY_CHANGELINK;
+ if (!phy_interrupt_is_valid(phydev)) {
+ old_link = phydev->link;
+ err = phy_read_status(phydev);
+ if (err)
+ break;
+
+ if (old_link != phydev->link)
+ phydev->state = PHY_CHANGELINK;
+ }
break;
case PHY_CHANGELINK:
err = phy_read_status(phydev);
@@ -1030,10 +1038,14 @@
int value = -1;
if (phydrv->read_mmd_indirect == NULL) {
- mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+ struct mii_bus *bus = phydev->bus;
+
+ mutex_lock(&bus->mdio_lock);
+ mmd_phy_indirect(bus, prtad, devad, addr);
/* Read the content of the MMD's selected register */
- value = phydev->bus->read(phydev->bus, addr, MII_MMD_DATA);
+ value = bus->read(bus, addr, MII_MMD_DATA);
+ mutex_unlock(&bus->mdio_lock);
} else {
value = phydrv->read_mmd_indirect(phydev, prtad, devad, addr);
}
@@ -1063,10 +1075,14 @@
struct phy_driver *phydrv = phydev->drv;
if (phydrv->write_mmd_indirect == NULL) {
- mmd_phy_indirect(phydev->bus, prtad, devad, addr);
+ struct mii_bus *bus = phydev->bus;
+
+ mutex_lock(&bus->mdio_lock);
+ mmd_phy_indirect(bus, prtad, devad, addr);
/* Write the data into MMD's selected register */
- phydev->bus->write(phydev->bus, addr, MII_MMD_DATA, data);
+ bus->write(bus, addr, MII_MMD_DATA, data);
+ mutex_unlock(&bus->mdio_lock);
} else {
phydrv->write_mmd_indirect(phydev, prtad, devad, addr, data);
}
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 0302483..55f0178 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -176,7 +176,7 @@
if (c45_ids)
dev->c45_ids = *c45_ids;
dev->bus = bus;
- dev->dev.parent = bus->parent;
+ dev->dev.parent = &bus->dev;
dev->dev.bus = &mdio_bus_type;
dev->irq = bus->irq != NULL ? bus->irq[addr] : PHY_POLL;
dev_set_name(&dev->dev, PHY_ID_FMT, bus->id, addr);
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index c0f6479e..70b0895 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -91,19 +91,18 @@
}
/*
- * The LAN8710/LAN8720 requires a minimum of 2 link pulses within 64ms of each
- * other in order to set the ENERGYON bit and exit EDPD mode. If a link partner
- * does send the pulses within this interval, the PHY will remained powered
- * down.
- *
- * This workaround will manually toggle the PHY on/off upon calls to read_status
- * in order to generate link test pulses if the link is down. If a link partner
- * is present, it will respond to the pulses, which will cause the ENERGYON bit
- * to be set and will cause the EDPD mode to be exited.
+ * The LAN87xx suffers from rare absence of the ENERGYON-bit when Ethernet cable
+ * plugs in while LAN87xx is in Energy Detect Power-Down mode. This leads to
+ * unstable detection of plugging in Ethernet cable.
+ * This workaround disables Energy Detect Power-Down mode and waiting for
+ * response on link pulses to detect presence of plugged Ethernet cable.
+ * The Energy Detect Power-Down mode is enabled again in the end of procedure to
+ * save approximately 220 mW of power if cable is unplugged.
*/
static int lan87xx_read_status(struct phy_device *phydev)
{
int err = genphy_read_status(phydev);
+ int i;
if (!phydev->link) {
/* Disable EDPD to wake up PHY */
@@ -116,8 +115,16 @@
if (rc < 0)
return rc;
- /* Sleep 64 ms to allow ~5 link test pulses to be sent */
- msleep(64);
+ /* Wait max 640 ms to detect energy */
+ for (i = 0; i < 64; i++) {
+ /* Sleep to allow link test pulses to be sent */
+ msleep(10);
+ rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+ if (rc < 0)
+ return rc;
+ if (rc & MII_LAN83C185_ENERGYON)
+ break;
+ }
/* Re-enable EDPD */
rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
@@ -191,7 +198,7 @@
/* basic functions */
.config_aneg = genphy_config_aneg,
- .read_status = genphy_read_status,
+ .read_status = lan87xx_read_status,
.config_init = smsc_phy_config_init,
.soft_reset = smsc_phy_reset,
diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c
index 9d15566..fa8f504 100644
--- a/drivers/net/ppp/ppp_generic.c
+++ b/drivers/net/ppp/ppp_generic.c
@@ -269,9 +269,9 @@
static void ppp_ccp_closed(struct ppp *ppp);
static struct compressor *find_compressor(int type);
static void ppp_get_stats(struct ppp *ppp, struct ppp_stats *st);
-static struct ppp *ppp_create_interface(struct net *net, int unit, int *retp);
+static struct ppp *ppp_create_interface(struct net *net, int unit,
+ struct file *file, int *retp);
static void init_ppp_file(struct ppp_file *pf, int kind);
-static void ppp_shutdown_interface(struct ppp *ppp);
static void ppp_destroy_interface(struct ppp *ppp);
static struct ppp *ppp_find_unit(struct ppp_net *pn, int unit);
static struct channel *ppp_find_channel(struct ppp_net *pn, int unit);
@@ -392,8 +392,10 @@
file->private_data = NULL;
if (pf->kind == INTERFACE) {
ppp = PF_TO_PPP(pf);
+ rtnl_lock();
if (file == ppp->owner)
- ppp_shutdown_interface(ppp);
+ unregister_netdevice(ppp->dev);
+ rtnl_unlock();
}
if (atomic_dec_and_test(&pf->refcnt)) {
switch (pf->kind) {
@@ -593,8 +595,10 @@
mutex_lock(&ppp_mutex);
if (pf->kind == INTERFACE) {
ppp = PF_TO_PPP(pf);
+ rtnl_lock();
if (file == ppp->owner)
- ppp_shutdown_interface(ppp);
+ unregister_netdevice(ppp->dev);
+ rtnl_unlock();
}
if (atomic_long_read(&file->f_count) < 2) {
ppp_release(NULL, file);
@@ -838,11 +842,10 @@
/* Create a new ppp unit */
if (get_user(unit, p))
break;
- ppp = ppp_create_interface(net, unit, &err);
+ ppp = ppp_create_interface(net, unit, file, &err);
if (!ppp)
break;
file->private_data = &ppp->file;
- ppp->owner = file;
err = -EFAULT;
if (put_user(ppp->file.index, p))
break;
@@ -916,6 +919,16 @@
static __net_exit void ppp_exit_net(struct net *net)
{
struct ppp_net *pn = net_generic(net, ppp_net_id);
+ struct ppp *ppp;
+ LIST_HEAD(list);
+ int id;
+
+ rtnl_lock();
+ idr_for_each_entry(&pn->units_idr, ppp, id)
+ unregister_netdevice_queue(ppp->dev, &list);
+
+ unregister_netdevice_many(&list);
+ rtnl_unlock();
idr_destroy(&pn->units_idr);
}
@@ -1088,8 +1101,28 @@
return 0;
}
+static void ppp_dev_uninit(struct net_device *dev)
+{
+ struct ppp *ppp = netdev_priv(dev);
+ struct ppp_net *pn = ppp_pernet(ppp->ppp_net);
+
+ ppp_lock(ppp);
+ ppp->closing = 1;
+ ppp_unlock(ppp);
+
+ mutex_lock(&pn->all_ppp_mutex);
+ unit_put(&pn->units_idr, ppp->file.index);
+ mutex_unlock(&pn->all_ppp_mutex);
+
+ ppp->owner = NULL;
+
+ ppp->file.dead = 1;
+ wake_up_interruptible(&ppp->file.rwait);
+}
+
static const struct net_device_ops ppp_netdev_ops = {
.ndo_init = ppp_dev_init,
+ .ndo_uninit = ppp_dev_uninit,
.ndo_start_xmit = ppp_start_xmit,
.ndo_do_ioctl = ppp_net_ioctl,
.ndo_get_stats64 = ppp_get_stats64,
@@ -2667,8 +2700,8 @@
* or if there is already a unit with the requested number.
* unit == -1 means allocate a new number.
*/
-static struct ppp *
-ppp_create_interface(struct net *net, int unit, int *retp)
+static struct ppp *ppp_create_interface(struct net *net, int unit,
+ struct file *file, int *retp)
{
struct ppp *ppp;
struct ppp_net *pn;
@@ -2688,6 +2721,7 @@
ppp->mru = PPP_MRU;
init_ppp_file(&ppp->file, INTERFACE);
ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */
+ ppp->owner = file;
for (i = 0; i < NUM_NP; ++i)
ppp->npmode[i] = NPMODE_PASS;
INIT_LIST_HEAD(&ppp->channels);
@@ -2776,34 +2810,6 @@
}
/*
- * Take down a ppp interface unit - called when the owning file
- * (the one that created the unit) is closed or detached.
- */
-static void ppp_shutdown_interface(struct ppp *ppp)
-{
- struct ppp_net *pn;
-
- pn = ppp_pernet(ppp->ppp_net);
- mutex_lock(&pn->all_ppp_mutex);
-
- /* This will call dev_close() for us. */
- ppp_lock(ppp);
- if (!ppp->closing) {
- ppp->closing = 1;
- ppp_unlock(ppp);
- unregister_netdev(ppp->dev);
- unit_put(&pn->units_idr, ppp->file.index);
- } else
- ppp_unlock(ppp);
-
- ppp->file.dead = 1;
- ppp->owner = NULL;
- wake_up_interruptible(&ppp->file.rwait);
-
- mutex_unlock(&pn->all_ppp_mutex);
-}
-
-/*
* Free the memory used by a ppp unit. This is only called once
* there are no channels connected to the unit and no file structs
* that reference the unit.
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index dac7a0d..01f08a7 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -396,7 +396,7 @@
return 0;
}
-static int rionet_remove_dev(struct device *dev, struct subsys_interface *sif)
+static void rionet_remove_dev(struct device *dev, struct subsys_interface *sif)
{
struct rio_dev *rdev = to_rio_dev(dev);
unsigned char netid = rdev->net->hport->id;
@@ -416,8 +416,6 @@
}
}
}
-
- return 0;
}
static void rionet_get_drvinfo(struct net_device *ndev,
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index f603f36..64a60af 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -757,6 +757,7 @@
{QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */
{QMI_FIXED_INTF(0x1199, 0x901f, 8)}, /* Sierra Wireless EM7355 */
{QMI_FIXED_INTF(0x1199, 0x9041, 8)}, /* Sierra Wireless MC7305/MC7355 */
+ {QMI_FIXED_INTF(0x1199, 0x9041, 10)}, /* Sierra Wireless MC7305/MC7355 */
{QMI_FIXED_INTF(0x1199, 0x9051, 8)}, /* Netgear AirCard 340U */
{QMI_FIXED_INTF(0x1199, 0x9053, 8)}, /* Sierra Wireless Modem */
{QMI_FIXED_INTF(0x1199, 0x9054, 8)}, /* Sierra Wireless Modem */
@@ -784,6 +785,7 @@
{QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
{QMI_FIXED_INTF(0x413c, 0x81a8, 8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
{QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
+ {QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
{QMI_FIXED_INTF(0x03f0, 0x581d, 4)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
/* 4. Gobi 1000 devices */
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 7f6419e..ad8cbc6 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -27,7 +27,7 @@
#include <linux/usb/cdc.h>
/* Version Information */
-#define DRIVER_VERSION "v1.08.0 (2015/01/13)"
+#define DRIVER_VERSION "v1.08.1 (2015/07/28)"
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
#define DRIVER_DESC "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
#define MODULENAME "r8152"
@@ -1902,11 +1902,10 @@
static void rtl8152_tx_timeout(struct net_device *netdev)
{
struct r8152 *tp = netdev_priv(netdev);
- int i;
netif_warn(tp, tx_err, netdev, "Tx timeout\n");
- for (i = 0; i < RTL8152_MAX_TX; i++)
- usb_unlink_urb(tp->tx_info[i].urb);
+
+ usb_queue_reset_device(tp->intf);
}
static void rtl8152_set_rx_mode(struct net_device *netdev)
@@ -2075,7 +2074,6 @@
{
int i, ret = 0;
- napi_disable(&tp->napi);
INIT_LIST_HEAD(&tp->rx_done);
for (i = 0; i < RTL8152_MAX_RX; i++) {
INIT_LIST_HEAD(&tp->rx_info[i].list);
@@ -2083,7 +2081,6 @@
if (ret)
break;
}
- napi_enable(&tp->napi);
if (ret && ++i < RTL8152_MAX_RX) {
struct list_head rx_queue;
@@ -2166,6 +2163,7 @@
if (test_bit(RTL8152_UNPLUG, &tp->flags))
return -ENODEV;
+ usb_disable_lpm(tp->udev);
set_tx_qlen(tp);
rtl_set_eee_plus(tp);
r8153_set_rx_early_timeout(tp);
@@ -2337,11 +2335,61 @@
device_set_wakeup_enable(&tp->udev->dev, false);
}
+static void r8153_u1u2en(struct r8152 *tp, bool enable)
+{
+ u8 u1u2[8];
+
+ if (enable)
+ memset(u1u2, 0xff, sizeof(u1u2));
+ else
+ memset(u1u2, 0x00, sizeof(u1u2));
+
+ usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2);
+}
+
+static void r8153_u2p3en(struct r8152 *tp, bool enable)
+{
+ u32 ocp_data;
+
+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL);
+ if (enable && tp->version != RTL_VER_03 && tp->version != RTL_VER_04)
+ ocp_data |= U2P3_ENABLE;
+ else
+ ocp_data &= ~U2P3_ENABLE;
+ ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
+}
+
+static void r8153_power_cut_en(struct r8152 *tp, bool enable)
+{
+ u32 ocp_data;
+
+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT);
+ if (enable)
+ ocp_data |= PWR_EN | PHASE2_EN;
+ else
+ ocp_data &= ~(PWR_EN | PHASE2_EN);
+ ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
+
+ ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
+ ocp_data &= ~PCUT_STATUS;
+ ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
+}
+
+static bool rtl_can_wakeup(struct r8152 *tp)
+{
+ struct usb_device *udev = tp->udev;
+
+ return (udev->actconfig->desc.bmAttributes & USB_CONFIG_ATT_WAKEUP);
+}
+
static void rtl_runtime_suspend_enable(struct r8152 *tp, bool enable)
{
if (enable) {
u32 ocp_data;
+ r8153_u1u2en(tp, false);
+ r8153_u2p3en(tp, false);
+
__rtl_set_wol(tp, WAKE_ANY);
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_CONFIG);
@@ -2353,6 +2401,8 @@
ocp_write_byte(tp, MCU_TYPE_PLA, PLA_CRWECR, CRWECR_NORAML);
} else {
__rtl_set_wol(tp, tp->saved_wolopts);
+ r8153_u2p3en(tp, true);
+ r8153_u1u2en(tp, true);
}
}
@@ -2599,46 +2649,6 @@
set_bit(PHY_RESET, &tp->flags);
}
-static void r8153_u1u2en(struct r8152 *tp, bool enable)
-{
- u8 u1u2[8];
-
- if (enable)
- memset(u1u2, 0xff, sizeof(u1u2));
- else
- memset(u1u2, 0x00, sizeof(u1u2));
-
- usb_ocp_write(tp, USB_TOLERANCE, BYTE_EN_SIX_BYTES, sizeof(u1u2), u1u2);
-}
-
-static void r8153_u2p3en(struct r8152 *tp, bool enable)
-{
- u32 ocp_data;
-
- ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL);
- if (enable)
- ocp_data |= U2P3_ENABLE;
- else
- ocp_data &= ~U2P3_ENABLE;
- ocp_write_word(tp, MCU_TYPE_USB, USB_U2P3_CTRL, ocp_data);
-}
-
-static void r8153_power_cut_en(struct r8152 *tp, bool enable)
-{
- u32 ocp_data;
-
- ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_POWER_CUT);
- if (enable)
- ocp_data |= PWR_EN | PHASE2_EN;
- else
- ocp_data &= ~(PWR_EN | PHASE2_EN);
- ocp_write_word(tp, MCU_TYPE_USB, USB_POWER_CUT, ocp_data);
-
- ocp_data = ocp_read_word(tp, MCU_TYPE_USB, USB_MISC_0);
- ocp_data &= ~PCUT_STATUS;
- ocp_write_word(tp, MCU_TYPE_USB, USB_MISC_0, ocp_data);
-}
-
static void r8153_first_init(struct r8152 *tp)
{
u32 ocp_data;
@@ -2781,6 +2791,7 @@
r8153_disable_aldps(tp);
rtl_disable(tp);
r8153_enable_aldps(tp);
+ usb_enable_lpm(tp->udev);
}
static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex)
@@ -2901,9 +2912,13 @@
if (test_bit(RTL8152_UNPLUG, &tp->flags))
return;
+ r8153_u1u2en(tp, false);
r8153_disable_aldps(tp);
r8153_first_init(tp);
r8153_enable_aldps(tp);
+ r8153_u2p3en(tp, true);
+ r8153_u1u2en(tp, true);
+ usb_enable_lpm(tp->udev);
}
static void rtl8153_down(struct r8152 *tp)
@@ -2914,6 +2929,7 @@
}
r8153_u1u2en(tp, false);
+ r8153_u2p3en(tp, false);
r8153_power_cut_en(tp, false);
r8153_disable_aldps(tp);
r8153_enter_oob(tp);
@@ -2932,8 +2948,10 @@
if (!netif_carrier_ok(netdev)) {
tp->rtl_ops.enable(tp);
set_bit(RTL8152_SET_RX_MODE, &tp->flags);
+ napi_disable(&tp->napi);
netif_carrier_on(netdev);
rtl_start_rx(tp);
+ napi_enable(&tp->napi);
}
} else {
if (netif_carrier_ok(netdev)) {
@@ -3252,6 +3270,7 @@
msleep(20);
}
+ usb_disable_lpm(tp->udev);
r8153_u2p3en(tp, false);
if (tp->version == RTL_VER_04) {
@@ -3319,6 +3338,59 @@
r8153_enable_aldps(tp);
r8152b_enable_fc(tp);
rtl_tally_reset(tp);
+ r8153_u2p3en(tp, true);
+}
+
+static int rtl8152_pre_reset(struct usb_interface *intf)
+{
+ struct r8152 *tp = usb_get_intfdata(intf);
+ struct net_device *netdev;
+
+ if (!tp)
+ return 0;
+
+ netdev = tp->netdev;
+ if (!netif_running(netdev))
+ return 0;
+
+ napi_disable(&tp->napi);
+ clear_bit(WORK_ENABLE, &tp->flags);
+ usb_kill_urb(tp->intr_urb);
+ cancel_delayed_work_sync(&tp->schedule);
+ if (netif_carrier_ok(netdev)) {
+ netif_stop_queue(netdev);
+ mutex_lock(&tp->control);
+ tp->rtl_ops.disable(tp);
+ mutex_unlock(&tp->control);
+ }
+
+ return 0;
+}
+
+static int rtl8152_post_reset(struct usb_interface *intf)
+{
+ struct r8152 *tp = usb_get_intfdata(intf);
+ struct net_device *netdev;
+
+ if (!tp)
+ return 0;
+
+ netdev = tp->netdev;
+ if (!netif_running(netdev))
+ return 0;
+
+ set_bit(WORK_ENABLE, &tp->flags);
+ if (netif_carrier_ok(netdev)) {
+ mutex_lock(&tp->control);
+ tp->rtl_ops.enable(tp);
+ rtl8152_set_rx_mode(netdev);
+ mutex_unlock(&tp->control);
+ netif_wake_queue(netdev);
+ }
+
+ napi_enable(&tp->napi);
+
+ return 0;
}
static int rtl8152_suspend(struct usb_interface *intf, pm_message_t message)
@@ -3374,9 +3446,11 @@
if (test_bit(SELECTIVE_SUSPEND, &tp->flags)) {
rtl_runtime_suspend_enable(tp, false);
clear_bit(SELECTIVE_SUSPEND, &tp->flags);
+ napi_disable(&tp->napi);
set_bit(WORK_ENABLE, &tp->flags);
if (netif_carrier_ok(tp->netdev))
rtl_start_rx(tp);
+ napi_enable(&tp->napi);
} else {
tp->rtl_ops.up(tp);
rtl8152_set_speed(tp, AUTONEG_ENABLE,
@@ -3403,12 +3477,15 @@
if (usb_autopm_get_interface(tp->intf) < 0)
return;
- mutex_lock(&tp->control);
-
- wol->supported = WAKE_ANY;
- wol->wolopts = __rtl_get_wol(tp);
-
- mutex_unlock(&tp->control);
+ if (!rtl_can_wakeup(tp)) {
+ wol->supported = 0;
+ wol->wolopts = 0;
+ } else {
+ mutex_lock(&tp->control);
+ wol->supported = WAKE_ANY;
+ wol->wolopts = __rtl_get_wol(tp);
+ mutex_unlock(&tp->control);
+ }
usb_autopm_put_interface(tp->intf);
}
@@ -3418,6 +3495,9 @@
struct r8152 *tp = netdev_priv(dev);
int ret;
+ if (!rtl_can_wakeup(tp))
+ return -EOPNOTSUPP;
+
ret = usb_autopm_get_interface(tp->intf);
if (ret < 0)
goto out_set_wol;
@@ -4059,6 +4139,9 @@
goto out1;
}
+ if (!rtl_can_wakeup(tp))
+ __rtl_set_wol(tp, 0);
+
tp->saved_wolopts = __rtl_get_wol(tp);
if (tp->saved_wolopts)
device_set_wakeup_enable(&udev->dev, true);
@@ -4132,6 +4215,8 @@
.suspend = rtl8152_suspend,
.resume = rtl8152_resume,
.reset_resume = rtl8152_resume,
+ .pre_reset = rtl8152_pre_reset,
+ .post_reset = rtl8152_post_reset,
.supports_autosuspend = 1,
.disable_hub_initiated_lpm = 1,
};
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 3c86b10..e049857 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -778,7 +778,7 @@
{
struct usbnet *dev = netdev_priv(net);
struct driver_info *info = dev->driver_info;
- int retval, pm;
+ int retval, pm, mpn;
clear_bit(EVENT_DEV_OPEN, &dev->flags);
netif_stop_queue (net);
@@ -809,6 +809,8 @@
usbnet_purge_paused_rxq(dev);
+ mpn = !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags);
+
/* deferred work (task, timer, softirq) must also stop.
* can't flush_scheduled_work() until we drop rtnl (later),
* else workers could deadlock; so make workers a NOP.
@@ -819,8 +821,7 @@
if (!pm)
usb_autopm_put_interface(dev->intf);
- if (info->manage_power &&
- !test_and_clear_bit(EVENT_NO_RUNTIME_PM, &dev->flags))
+ if (info->manage_power && mpn)
info->manage_power(dev, 0);
else
usb_autopm_put_interface(dev->intf);
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 63c7810..237f8e5 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1756,9 +1756,9 @@
/* Do we support "hardware" checksums? */
if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) {
/* This opens up the world of extra features. */
- dev->hw_features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+ dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG;
if (csum)
- dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+ dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG;
if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO
@@ -1828,7 +1828,8 @@
else
vi->hdr_len = sizeof(struct virtio_net_hdr);
- if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT))
+ if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT) ||
+ virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
vi->any_header_sg = true;
if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ))
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 34c519e..5bc4b1e 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2216,6 +2216,8 @@
if (vxlan_addr_multicast(&vxlan->default_dst.remote_ip)) {
ret = vxlan_igmp_join(vxlan);
+ if (ret == -EADDRINUSE)
+ ret = 0;
if (ret) {
vxlan_sock_release(vs);
return ret;
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 7193b73..848ea6a 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -589,7 +589,8 @@
chan->netdev->base_addr = chan->cosa->datareg;
chan->netdev->irq = chan->cosa->irq;
chan->netdev->dma = chan->cosa->dma;
- if (register_hdlc_device(chan->netdev)) {
+ err = register_hdlc_device(chan->netdev);
+ if (err) {
netdev_warn(chan->netdev,
"register_hdlc_device() failed\n");
free_netdev(chan->netdev);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 5e15e8e..a31a680 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -279,6 +279,7 @@
return;
case AR9300_DEVID_QCA956X:
ah->hw_version.macVersion = AR_SREV_VERSION_9561;
+ return;
}
val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 25d1cbd..b2f0d24 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -3728,7 +3728,7 @@
switch (phy->rev) {
case 6:
case 5:
- if (sprom->fem.ghz5.extpa_gain == 3)
+ if (sprom->fem.ghz2.extpa_gain == 3)
return b43_ntab_tx_gain_epa_rev3_hi_pwr_2g;
/* fall through */
case 4:
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index d560648..d45dc02 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -438,6 +438,12 @@
#define RX_QUEUE_MASK 255
#define RX_QUEUE_SIZE_LOG 8
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 64
+#define RX_LOW_WATERMARK 8
+
/**
* struct iwl_rb_status - reserve buffer status
* host memory mapped FH registers
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 80fefe7..3b8e85e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -540,13 +540,11 @@
hw_addr = (const u8 *)(mac_override +
MAC_ADDRESS_OVERRIDE_FAMILY_8000);
- /* The byte order is little endian 16 bit, meaning 214365 */
- data->hw_addr[0] = hw_addr[1];
- data->hw_addr[1] = hw_addr[0];
- data->hw_addr[2] = hw_addr[3];
- data->hw_addr[3] = hw_addr[2];
- data->hw_addr[4] = hw_addr[5];
- data->hw_addr[5] = hw_addr[4];
+ /*
+ * Store the MAC address from MAO section.
+ * No byte swapping is required in MAO section
+ */
+ memcpy(data->hw_addr, hw_addr, ETH_ALEN);
/*
* Force the use of the OTP MAC address in case of reserved MAC
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 5e4cbdb..737774a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -660,7 +660,8 @@
* iwl_umac_scan_flags
*@IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request
* can be preempted by other scan requests with higher priority.
- * The low priority scan is aborted.
+ * The low priority scan will be resumed when the higher proirity scan is
+ * completed.
*@IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver
* when scan starts.
*/
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 5de1449..5514ad6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -1023,7 +1023,7 @@
cmd->scan_priority =
iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
- if (iwl_mvm_scan_total_iterations(params) == 0)
+ if (iwl_mvm_scan_total_iterations(params) == 1)
cmd->ooc_priority =
iwl_mvm_scan_priority(mvm, IWL_SCAN_PRIORITY_EXT_6);
else
@@ -1109,6 +1109,9 @@
cmd->uid = cpu_to_le32(uid);
cmd->general_flags = cpu_to_le32(iwl_mvm_scan_umac_flags(mvm, params));
+ if (type == IWL_MVM_SCAN_SCHED)
+ cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
+
if (iwl_mvm_scan_use_ebs(mvm, vif, n_iterations))
cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index d68dc69..26f076e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -1401,6 +1401,7 @@
bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
u8 sta_id;
int ret;
+ static const u8 __maybe_unused zero_addr[ETH_ALEN] = {0};
lockdep_assert_held(&mvm->mutex);
@@ -1467,7 +1468,7 @@
end:
IWL_DEBUG_WEP(mvm, "key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n",
keyconf->cipher, keyconf->keylen, keyconf->keyidx,
- sta->addr, ret);
+ sta ? sta->addr : zero_addr, ret);
return ret;
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index d24b6a8..e472729 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -86,7 +86,7 @@
{
lockdep_assert_held(&mvm->time_event_lock);
- if (te_data->id == TE_MAX)
+ if (!te_data->vif)
return;
list_del(&te_data->list);
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 7ba7a118..8911686 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -252,7 +252,7 @@
if (info->band == IEEE80211_BAND_2GHZ &&
!iwl_mvm_bt_coex_is_shared_ant_avail(mvm))
- rate_flags = BIT(mvm->cfg->non_shared_ant) << RATE_MCS_ANT_POS;
+ rate_flags = mvm->cfg->non_shared_ant << RATE_MCS_ANT_POS;
else
rate_flags =
BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 2ed1e4d..9f65c1c 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -368,12 +368,14 @@
/* 3165 Series */
{IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)},
{IWL_PCI_DEVICE(0x3165, 0x4012, iwl3165_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x3166, 0x4212, iwl3165_2ac_cfg)},
{IWL_PCI_DEVICE(0x3165, 0x4410, iwl3165_2ac_cfg)},
{IWL_PCI_DEVICE(0x3165, 0x4510, iwl3165_2ac_cfg)},
{IWL_PCI_DEVICE(0x3165, 0x4110, iwl3165_2ac_cfg)},
{IWL_PCI_DEVICE(0x3166, 0x4310, iwl3165_2ac_cfg)},
{IWL_PCI_DEVICE(0x3166, 0x4210, iwl3165_2ac_cfg)},
{IWL_PCI_DEVICE(0x3165, 0x8010, iwl3165_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x3165, 0x8110, iwl3165_2ac_cfg)},
/* 7265 Series */
{IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)},
@@ -426,9 +428,8 @@
{IWL_PCI_DEVICE(0x24F4, 0x1130, iwl8260_2ac_cfg)},
{IWL_PCI_DEVICE(0x24F4, 0x1030, iwl8260_2ac_cfg)},
{IWL_PCI_DEVICE(0x24F3, 0xC010, iwl8260_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x24F3, 0xC110, iwl8260_2ac_cfg)},
{IWL_PCI_DEVICE(0x24F3, 0xD010, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F4, 0xC030, iwl8260_2ac_cfg)},
- {IWL_PCI_DEVICE(0x24F4, 0xD030, iwl8260_2ac_cfg)},
{IWL_PCI_DEVICE(0x24F3, 0xC050, iwl8260_2ac_cfg)},
{IWL_PCI_DEVICE(0x24F3, 0xD050, iwl8260_2ac_cfg)},
{IWL_PCI_DEVICE(0x24F3, 0x8010, iwl8260_2ac_cfg)},
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 31f72a6..376b84e 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -44,15 +44,6 @@
#include "iwl-io.h"
#include "iwl-op-mode.h"
-/*
- * RX related structures and functions
- */
-#define RX_NUM_QUEUES 1
-#define RX_POST_REQ_ALLOC 2
-#define RX_CLAIM_REQ_ALLOC 8
-#define RX_POOL_SIZE ((RX_CLAIM_REQ_ALLOC - RX_POST_REQ_ALLOC) * RX_NUM_QUEUES)
-#define RX_LOW_WATERMARK 8
-
struct iwl_host_cmd;
/*This file includes the declaration that are internal to the
@@ -86,29 +77,29 @@
* struct iwl_rxq - Rx queue
* @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
* @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
+ * @pool:
+ * @queue:
* @read: Shared index to newest available Rx buffer
* @write: Shared index to oldest written Rx packet
* @free_count: Number of pre-allocated buffers in rx_free
- * @used_count: Number of RBDs handled to allocator to use for allocation
* @write_actual:
- * @rx_free: list of RBDs with allocated RB ready for use
- * @rx_used: list of RBDs with no RB attached
+ * @rx_free: list of free SKBs for use
+ * @rx_used: List of Rx buffers with no SKB
* @need_update: flag to indicate we need to update read/write index
* @rb_stts: driver's pointer to receive buffer status
* @rb_stts_dma: bus address of receive buffer status
* @lock:
- * @pool: initial pool of iwl_rx_mem_buffer for the queue
- * @queue: actual rx queue
*
* NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
*/
struct iwl_rxq {
__le32 *bd;
dma_addr_t bd_dma;
+ struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+ struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
u32 read;
u32 write;
u32 free_count;
- u32 used_count;
u32 write_actual;
struct list_head rx_free;
struct list_head rx_used;
@@ -116,32 +107,6 @@
struct iwl_rb_status *rb_stts;
dma_addr_t rb_stts_dma;
spinlock_t lock;
- struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE];
- struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
-};
-
-/**
- * struct iwl_rb_allocator - Rx allocator
- * @pool: initial pool of allocator
- * @req_pending: number of requests the allcator had not processed yet
- * @req_ready: number of requests honored and ready for claiming
- * @rbd_allocated: RBDs with pages allocated and ready to be handled to
- * the queue. This is a list of &struct iwl_rx_mem_buffer
- * @rbd_empty: RBDs with no page attached for allocator use. This is a list
- * of &struct iwl_rx_mem_buffer
- * @lock: protects the rbd_allocated and rbd_empty lists
- * @alloc_wq: work queue for background calls
- * @rx_alloc: work struct for background calls
- */
-struct iwl_rb_allocator {
- struct iwl_rx_mem_buffer pool[RX_POOL_SIZE];
- atomic_t req_pending;
- atomic_t req_ready;
- struct list_head rbd_allocated;
- struct list_head rbd_empty;
- spinlock_t lock;
- struct workqueue_struct *alloc_wq;
- struct work_struct rx_alloc;
};
struct iwl_dma_ptr {
@@ -285,7 +250,7 @@
/**
* struct iwl_trans_pcie - PCIe transport specific data
* @rxq: all the RX queue data
- * @rba: allocator for RX replenishing
+ * @rx_replenish: work that will be called when buffers need to be allocated
* @drv - pointer to iwl_drv
* @trans: pointer to the generic transport area
* @scd_base_addr: scheduler sram base address in SRAM
@@ -308,7 +273,7 @@
*/
struct iwl_trans_pcie {
struct iwl_rxq rxq;
- struct iwl_rb_allocator rba;
+ struct work_struct rx_replenish;
struct iwl_trans *trans;
struct iwl_drv *drv;
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index a3fbaa0..adad8d0 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
@@ -74,29 +74,16 @@
* resets the Rx queue buffers with new memory.
*
* The management in the driver is as follows:
- * + A list of pre-allocated RBDs is stored in iwl->rxq->rx_free.
- * When the interrupt handler is called, the request is processed.
- * The page is either stolen - transferred to the upper layer
- * or reused - added immediately to the iwl->rxq->rx_free list.
- * + When the page is stolen - the driver updates the matching queue's used
- * count, detaches the RBD and transfers it to the queue used list.
- * When there are two used RBDs - they are transferred to the allocator empty
- * list. Work is then scheduled for the allocator to start allocating
- * eight buffers.
- * When there are another 6 used RBDs - they are transferred to the allocator
- * empty list and the driver tries to claim the pre-allocated buffers and
- * add them to iwl->rxq->rx_free. If it fails - it continues to claim them
- * until ready.
- * When there are 8+ buffers in the free list - either from allocation or from
- * 8 reused unstolen pages - restock is called to update the FW and indexes.
- * + In order to make sure the allocator always has RBDs to use for allocation
- * the allocator has initial pool in the size of num_queues*(8-2) - the
- * maximum missing RBDs per allocation request (request posted with 2
- * empty RBDs, there is no guarantee when the other 6 RBDs are supplied).
- * The queues supplies the recycle of the rest of the RBDs.
+ * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When
+ * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ * to replenish the iwl->rxq->rx_free.
+ * + In iwl_pcie_rx_replenish (scheduled) if 'processed' != 'read' then the
+ * iwl->rxq is replenished and the READ INDEX is updated (updating the
+ * 'processed' and 'read' driver indexes as well)
* + A received packet is processed and handed to the kernel network stack,
* detached from the iwl->rxq. The driver 'processed' index is updated.
- * + If there are no allocated buffers in iwl->rxq->rx_free,
+ * + The Host/Firmware iwl->rxq is replenished at irq thread time from the
+ * rx_free list. If there are no allocated buffers in iwl->rxq->rx_free,
* the READ INDEX is not incremented and iwl->status(RX_STALLED) is set.
* If there were enough free buffers and RX_STALLED is set it is cleared.
*
@@ -105,32 +92,18 @@
*
* iwl_rxq_alloc() Allocates rx_free
* iwl_pcie_rx_replenish() Replenishes rx_free list from rx_used, and calls
- * iwl_pcie_rxq_restock.
- * Used only during initialization.
+ * iwl_pcie_rxq_restock
* iwl_pcie_rxq_restock() Moves available buffers from rx_free into Rx
* queue, updates firmware pointers, and updates
- * the WRITE index.
- * iwl_pcie_rx_allocator() Background work for allocating pages.
+ * the WRITE index. If insufficient rx_free buffers
+ * are available, schedules iwl_pcie_rx_replenish
*
* -- enable interrupts --
* ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the
* READ INDEX, detaching the SKB from the pool.
* Moves the packet buffer from queue to rx_used.
- * Posts and claims requests to the allocator.
* Calls iwl_pcie_rxq_restock to refill any empty
* slots.
- *
- * RBD life-cycle:
- *
- * Init:
- * rxq.pool -> rxq.rx_used -> rxq.rx_free -> rxq.queue
- *
- * Regular Receive interrupt:
- * Page Stolen:
- * rxq.queue -> rxq.rx_used -> allocator.rbd_empty ->
- * allocator.rbd_allocated -> rxq.rx_free -> rxq.queue
- * Page not Stolen:
- * rxq.queue -> rxq.rx_free -> rxq.queue
* ...
*
*/
@@ -267,6 +240,10 @@
rxq->free_count--;
}
spin_unlock(&rxq->lock);
+ /* If the pre-allocated buffer pool is dropping low, schedule to
+ * refill it */
+ if (rxq->free_count <= RX_LOW_WATERMARK)
+ schedule_work(&trans_pcie->rx_replenish);
/* If we've added more space for the firmware to place data, tell it.
* Increment device's write pointer in multiples of 8. */
@@ -278,44 +255,6 @@
}
/*
- * iwl_pcie_rx_alloc_page - allocates and returns a page.
- *
- */
-static struct page *iwl_pcie_rx_alloc_page(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rxq *rxq = &trans_pcie->rxq;
- struct page *page;
- gfp_t gfp_mask = GFP_KERNEL;
-
- if (rxq->free_count > RX_LOW_WATERMARK)
- gfp_mask |= __GFP_NOWARN;
-
- if (trans_pcie->rx_page_order > 0)
- gfp_mask |= __GFP_COMP;
-
- /* Alloc a new receive buffer */
- page = alloc_pages(gfp_mask, trans_pcie->rx_page_order);
- if (!page) {
- if (net_ratelimit())
- IWL_DEBUG_INFO(trans, "alloc_pages failed, order: %d\n",
- trans_pcie->rx_page_order);
- /* Issue an error if the hardware has consumed more than half
- * of its free buffer list and we don't have enough
- * pre-allocated buffers.
-` */
- if (rxq->free_count <= RX_LOW_WATERMARK &&
- iwl_rxq_space(rxq) > (RX_QUEUE_SIZE / 2) &&
- net_ratelimit())
- IWL_CRIT(trans,
- "Failed to alloc_pages with GFP_KERNEL. Only %u free buffers remaining.\n",
- rxq->free_count);
- return NULL;
- }
- return page;
-}
-
-/*
* iwl_pcie_rxq_alloc_rbs - allocate a page for each used RBD
*
* A used RBD is an Rx buffer that has been given to the stack. To use it again
@@ -324,12 +263,13 @@
* iwl_pcie_rxq_restock. The latter function will update the HW to use the newly
* allocated buffers.
*/
-static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans)
+static void iwl_pcie_rxq_alloc_rbs(struct iwl_trans *trans, gfp_t priority)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rxq *rxq = &trans_pcie->rxq;
struct iwl_rx_mem_buffer *rxb;
struct page *page;
+ gfp_t gfp_mask = priority;
while (1) {
spin_lock(&rxq->lock);
@@ -339,10 +279,32 @@
}
spin_unlock(&rxq->lock);
+ if (rxq->free_count > RX_LOW_WATERMARK)
+ gfp_mask |= __GFP_NOWARN;
+
+ if (trans_pcie->rx_page_order > 0)
+ gfp_mask |= __GFP_COMP;
+
/* Alloc a new receive buffer */
- page = iwl_pcie_rx_alloc_page(trans);
- if (!page)
+ page = alloc_pages(gfp_mask, trans_pcie->rx_page_order);
+ if (!page) {
+ if (net_ratelimit())
+ IWL_DEBUG_INFO(trans, "alloc_pages failed, "
+ "order: %d\n",
+ trans_pcie->rx_page_order);
+
+ if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+ net_ratelimit())
+ IWL_CRIT(trans, "Failed to alloc_pages with %s."
+ "Only %u free buffers remaining.\n",
+ priority == GFP_ATOMIC ?
+ "GFP_ATOMIC" : "GFP_KERNEL",
+ rxq->free_count);
+ /* We don't reschedule replenish work here -- we will
+ * call the restock method and if it still needs
+ * more buffers it will schedule replenish */
return;
+ }
spin_lock(&rxq->lock);
@@ -393,7 +355,7 @@
lockdep_assert_held(&rxq->lock);
- for (i = 0; i < RX_QUEUE_SIZE; i++) {
+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
if (!rxq->pool[i].page)
continue;
dma_unmap_page(trans->dev, rxq->pool[i].page_dma,
@@ -410,144 +372,32 @@
* When moving to rx_free an page is allocated for the slot.
*
* Also restock the Rx queue via iwl_pcie_rxq_restock.
- * This is called only during initialization
+ * This is called as a scheduled work item (except for during initialization)
*/
-static void iwl_pcie_rx_replenish(struct iwl_trans *trans)
+static void iwl_pcie_rx_replenish(struct iwl_trans *trans, gfp_t gfp)
{
- iwl_pcie_rxq_alloc_rbs(trans);
+ iwl_pcie_rxq_alloc_rbs(trans, gfp);
iwl_pcie_rxq_restock(trans);
}
-/*
- * iwl_pcie_rx_allocator - Allocates pages in the background for RX queues
- *
- * Allocates for each received request 8 pages
- * Called as a scheduled work item.
- */
-static void iwl_pcie_rx_allocator(struct iwl_trans *trans)
+static void iwl_pcie_rx_replenish_work(struct work_struct *data)
{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rb_allocator *rba = &trans_pcie->rba;
-
- while (atomic_read(&rba->req_pending)) {
- int i;
- struct list_head local_empty;
- struct list_head local_allocated;
-
- INIT_LIST_HEAD(&local_allocated);
- spin_lock(&rba->lock);
- /* swap out the entire rba->rbd_empty to a local list */
- list_replace_init(&rba->rbd_empty, &local_empty);
- spin_unlock(&rba->lock);
-
- for (i = 0; i < RX_CLAIM_REQ_ALLOC;) {
- struct iwl_rx_mem_buffer *rxb;
- struct page *page;
-
- /* List should never be empty - each reused RBD is
- * returned to the list, and initial pool covers any
- * possible gap between the time the page is allocated
- * to the time the RBD is added.
- */
- BUG_ON(list_empty(&local_empty));
- /* Get the first rxb from the rbd list */
- rxb = list_first_entry(&local_empty,
- struct iwl_rx_mem_buffer, list);
- BUG_ON(rxb->page);
-
- /* Alloc a new receive buffer */
- page = iwl_pcie_rx_alloc_page(trans);
- if (!page)
- continue;
- rxb->page = page;
-
- /* Get physical address of the RB */
- rxb->page_dma = dma_map_page(trans->dev, page, 0,
- PAGE_SIZE << trans_pcie->rx_page_order,
- DMA_FROM_DEVICE);
- if (dma_mapping_error(trans->dev, rxb->page_dma)) {
- rxb->page = NULL;
- __free_pages(page, trans_pcie->rx_page_order);
- continue;
- }
- /* dma address must be no more than 36 bits */
- BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
- /* and also 256 byte aligned! */
- BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
-
- /* move the allocated entry to the out list */
- list_move(&rxb->list, &local_allocated);
- i++;
- }
-
- spin_lock(&rba->lock);
- /* add the allocated rbds to the allocator allocated list */
- list_splice_tail(&local_allocated, &rba->rbd_allocated);
- /* add the unused rbds back to the allocator empty list */
- list_splice_tail(&local_empty, &rba->rbd_empty);
- spin_unlock(&rba->lock);
-
- atomic_dec(&rba->req_pending);
- atomic_inc(&rba->req_ready);
- }
-}
-
-/*
- * iwl_pcie_rx_allocator_get - Returns the pre-allocated pages
-.*
-.* Called by queue when the queue posted allocation request and
- * has freed 8 RBDs in order to restock itself.
- */
-static int iwl_pcie_rx_allocator_get(struct iwl_trans *trans,
- struct iwl_rx_mem_buffer
- *out[RX_CLAIM_REQ_ALLOC])
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rb_allocator *rba = &trans_pcie->rba;
- int i;
-
- if (atomic_dec_return(&rba->req_ready) < 0) {
- atomic_inc(&rba->req_ready);
- IWL_DEBUG_RX(trans,
- "Allocation request not ready, pending requests = %d\n",
- atomic_read(&rba->req_pending));
- return -ENOMEM;
- }
-
- spin_lock(&rba->lock);
- for (i = 0; i < RX_CLAIM_REQ_ALLOC; i++) {
- /* Get next free Rx buffer, remove it from free list */
- out[i] = list_first_entry(&rba->rbd_allocated,
- struct iwl_rx_mem_buffer, list);
- list_del(&out[i]->list);
- }
- spin_unlock(&rba->lock);
-
- return 0;
-}
-
-static void iwl_pcie_rx_allocator_work(struct work_struct *data)
-{
- struct iwl_rb_allocator *rba_p =
- container_of(data, struct iwl_rb_allocator, rx_alloc);
struct iwl_trans_pcie *trans_pcie =
- container_of(rba_p, struct iwl_trans_pcie, rba);
+ container_of(data, struct iwl_trans_pcie, rx_replenish);
- iwl_pcie_rx_allocator(trans_pcie->trans);
+ iwl_pcie_rx_replenish(trans_pcie->trans, GFP_KERNEL);
}
static int iwl_pcie_rx_alloc(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rxq *rxq = &trans_pcie->rxq;
- struct iwl_rb_allocator *rba = &trans_pcie->rba;
struct device *dev = trans->dev;
memset(&trans_pcie->rxq, 0, sizeof(trans_pcie->rxq));
spin_lock_init(&rxq->lock);
- spin_lock_init(&rba->lock);
if (WARN_ON(rxq->bd || rxq->rb_stts))
return -EINVAL;
@@ -637,49 +487,15 @@
INIT_LIST_HEAD(&rxq->rx_free);
INIT_LIST_HEAD(&rxq->rx_used);
rxq->free_count = 0;
- rxq->used_count = 0;
- for (i = 0; i < RX_QUEUE_SIZE; i++)
+ for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
list_add(&rxq->pool[i].list, &rxq->rx_used);
}
-static void iwl_pcie_rx_init_rba(struct iwl_rb_allocator *rba)
-{
- int i;
-
- lockdep_assert_held(&rba->lock);
-
- INIT_LIST_HEAD(&rba->rbd_allocated);
- INIT_LIST_HEAD(&rba->rbd_empty);
-
- for (i = 0; i < RX_POOL_SIZE; i++)
- list_add(&rba->pool[i].list, &rba->rbd_empty);
-}
-
-static void iwl_pcie_rx_free_rba(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rb_allocator *rba = &trans_pcie->rba;
- int i;
-
- lockdep_assert_held(&rba->lock);
-
- for (i = 0; i < RX_POOL_SIZE; i++) {
- if (!rba->pool[i].page)
- continue;
- dma_unmap_page(trans->dev, rba->pool[i].page_dma,
- PAGE_SIZE << trans_pcie->rx_page_order,
- DMA_FROM_DEVICE);
- __free_pages(rba->pool[i].page, trans_pcie->rx_page_order);
- rba->pool[i].page = NULL;
- }
-}
-
int iwl_pcie_rx_init(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rxq *rxq = &trans_pcie->rxq;
- struct iwl_rb_allocator *rba = &trans_pcie->rba;
int i, err;
if (!rxq->bd) {
@@ -687,21 +503,11 @@
if (err)
return err;
}
- if (!rba->alloc_wq)
- rba->alloc_wq = alloc_workqueue("rb_allocator",
- WQ_HIGHPRI | WQ_UNBOUND, 1);
- INIT_WORK(&rba->rx_alloc, iwl_pcie_rx_allocator_work);
-
- spin_lock(&rba->lock);
- atomic_set(&rba->req_pending, 0);
- atomic_set(&rba->req_ready, 0);
- /* free all first - we might be reconfigured for a different size */
- iwl_pcie_rx_free_rba(trans);
- iwl_pcie_rx_init_rba(rba);
- spin_unlock(&rba->lock);
spin_lock(&rxq->lock);
+ INIT_WORK(&trans_pcie->rx_replenish, iwl_pcie_rx_replenish_work);
+
/* free all first - we might be reconfigured for a different size */
iwl_pcie_rxq_free_rbs(trans);
iwl_pcie_rx_init_rxb_lists(rxq);
@@ -716,7 +522,7 @@
memset(rxq->rb_stts, 0, sizeof(*rxq->rb_stts));
spin_unlock(&rxq->lock);
- iwl_pcie_rx_replenish(trans);
+ iwl_pcie_rx_replenish(trans, GFP_KERNEL);
iwl_pcie_rx_hw_init(trans, rxq);
@@ -731,7 +537,6 @@
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rxq *rxq = &trans_pcie->rxq;
- struct iwl_rb_allocator *rba = &trans_pcie->rba;
/*if rxq->bd is NULL, it means that nothing has been allocated,
* exit now */
@@ -740,15 +545,7 @@
return;
}
- cancel_work_sync(&rba->rx_alloc);
- if (rba->alloc_wq) {
- destroy_workqueue(rba->alloc_wq);
- rba->alloc_wq = NULL;
- }
-
- spin_lock(&rba->lock);
- iwl_pcie_rx_free_rba(trans);
- spin_unlock(&rba->lock);
+ cancel_work_sync(&trans_pcie->rx_replenish);
spin_lock(&rxq->lock);
iwl_pcie_rxq_free_rbs(trans);
@@ -769,43 +566,6 @@
rxq->rb_stts = NULL;
}
-/*
- * iwl_pcie_rx_reuse_rbd - Recycle used RBDs
- *
- * Called when a RBD can be reused. The RBD is transferred to the allocator.
- * When there are 2 empty RBDs - a request for allocation is posted
- */
-static void iwl_pcie_rx_reuse_rbd(struct iwl_trans *trans,
- struct iwl_rx_mem_buffer *rxb,
- struct iwl_rxq *rxq)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct iwl_rb_allocator *rba = &trans_pcie->rba;
-
- /* Count the used RBDs */
- rxq->used_count++;
-
- /* Move the RBD to the used list, will be moved to allocator in batches
- * before claiming or posting a request*/
- list_add_tail(&rxb->list, &rxq->rx_used);
-
- /* If we have RX_POST_REQ_ALLOC new released rx buffers -
- * issue a request for allocator. Modulo RX_CLAIM_REQ_ALLOC is
- * used for the case we failed to claim RX_CLAIM_REQ_ALLOC,
- * after but we still need to post another request.
- */
- if ((rxq->used_count % RX_CLAIM_REQ_ALLOC) == RX_POST_REQ_ALLOC) {
- /* Move the 2 RBDs to the allocator ownership.
- Allocator has another 6 from pool for the request completion*/
- spin_lock(&rba->lock);
- list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty);
- spin_unlock(&rba->lock);
-
- atomic_inc(&rba->req_pending);
- queue_work(rba->alloc_wq, &rba->rx_alloc);
- }
-}
-
static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
struct iwl_rx_mem_buffer *rxb)
{
@@ -928,13 +688,13 @@
*/
__free_pages(rxb->page, trans_pcie->rx_page_order);
rxb->page = NULL;
- iwl_pcie_rx_reuse_rbd(trans, rxb, rxq);
+ list_add_tail(&rxb->list, &rxq->rx_used);
} else {
list_add_tail(&rxb->list, &rxq->rx_free);
rxq->free_count++;
}
} else
- iwl_pcie_rx_reuse_rbd(trans, rxb, rxq);
+ list_add_tail(&rxb->list, &rxq->rx_used);
}
/*
@@ -944,7 +704,10 @@
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_rxq *rxq = &trans_pcie->rxq;
- u32 r, i, j;
+ u32 r, i;
+ u8 fill_rx = 0;
+ u32 count = 8;
+ int total_empty;
restart:
spin_lock(&rxq->lock);
@@ -957,6 +720,14 @@
if (i == r)
IWL_DEBUG_RX(trans, "HW = SW = %d\n", r);
+ /* calculate total frames need to be restock after handling RX */
+ total_empty = r - rxq->write_actual;
+ if (total_empty < 0)
+ total_empty += RX_QUEUE_SIZE;
+
+ if (total_empty > (RX_QUEUE_SIZE / 2))
+ fill_rx = 1;
+
while (i != r) {
struct iwl_rx_mem_buffer *rxb;
@@ -968,48 +739,29 @@
iwl_pcie_rx_handle_rb(trans, rxb);
i = (i + 1) & RX_QUEUE_MASK;
-
- /* If we have RX_CLAIM_REQ_ALLOC released rx buffers -
- * try to claim the pre-allocated buffers from the allocator */
- if (rxq->used_count >= RX_CLAIM_REQ_ALLOC) {
- struct iwl_rb_allocator *rba = &trans_pcie->rba;
- struct iwl_rx_mem_buffer *out[RX_CLAIM_REQ_ALLOC];
-
- /* Add the remaining 6 empty RBDs for allocator use */
- spin_lock(&rba->lock);
- list_splice_tail_init(&rxq->rx_used, &rba->rbd_empty);
- spin_unlock(&rba->lock);
-
- /* If not ready - continue, will try to reclaim later.
- * No need to reschedule work - allocator exits only on
- * success */
- if (!iwl_pcie_rx_allocator_get(trans, out)) {
- /* If success - then RX_CLAIM_REQ_ALLOC
- * buffers were retrieved and should be added
- * to free list */
- rxq->used_count -= RX_CLAIM_REQ_ALLOC;
- for (j = 0; j < RX_CLAIM_REQ_ALLOC; j++) {
- list_add_tail(&out[j]->list,
- &rxq->rx_free);
- rxq->free_count++;
- }
+ /* If there are a lot of unused frames,
+ * restock the Rx queue so ucode wont assert. */
+ if (fill_rx) {
+ count++;
+ if (count >= 8) {
+ rxq->read = i;
+ spin_unlock(&rxq->lock);
+ iwl_pcie_rx_replenish(trans, GFP_ATOMIC);
+ count = 0;
+ goto restart;
}
}
- /* handle restock for two cases:
- * - we just pulled buffers from the allocator
- * - we have 8+ unstolen pages accumulated */
- if (rxq->free_count >= RX_CLAIM_REQ_ALLOC) {
- rxq->read = i;
- spin_unlock(&rxq->lock);
- iwl_pcie_rxq_restock(trans);
- goto restart;
- }
}
/* Backtrack one entry */
rxq->read = i;
spin_unlock(&rxq->lock);
+ if (fill_rx)
+ iwl_pcie_rx_replenish(trans, GFP_ATOMIC);
+ else
+ iwl_pcie_rxq_restock(trans);
+
if (trans_pcie->napi.poll)
napi_gro_flush(&trans_pcie->napi, false);
}
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 43ae658..9e144e7 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -182,7 +182,7 @@
static void iwl_pcie_set_pwr(struct iwl_trans *trans, bool vaux)
{
- if (!trans->cfg->apmg_not_supported)
+ if (trans->cfg->apmg_not_supported)
return;
if (vaux && pci_pme_capable(to_pci_dev(trans->dev), PCI_D3cold))
@@ -478,10 +478,16 @@
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000)
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
APMG_PCIDEV_STT_VAL_WAKE_ME);
- else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
+ else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
+ iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+ CSR_RESET_LINK_PWR_MGMT_DISABLED);
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
CSR_HW_IF_CONFIG_REG_PREPARE |
CSR_HW_IF_CONFIG_REG_ENABLE_PME);
+ mdelay(1);
+ iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+ CSR_RESET_LINK_PWR_MGMT_DISABLED);
+ }
mdelay(5);
}
@@ -575,6 +581,10 @@
if (ret >= 0)
return 0;
+ iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+ CSR_RESET_LINK_PWR_MGMT_DISABLED);
+ msleep(1);
+
for (iter = 0; iter < 10; iter++) {
/* If HW is not ready, prepare the conditions to check again */
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
@@ -582,8 +592,10 @@
do {
ret = iwl_pcie_set_hw_ready(trans);
- if (ret >= 0)
- return 0;
+ if (ret >= 0) {
+ ret = 0;
+ goto out;
+ }
usleep_range(200, 1000);
t += 200;
@@ -593,6 +605,10 @@
IWL_ERR(trans, "Couldn't prepare the card\n");
+out:
+ iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
+ CSR_RESET_LINK_PWR_MGMT_DISABLED);
+
return ret;
}
@@ -2459,7 +2475,7 @@
struct iwl_trans_pcie *trans_pcie;
struct iwl_trans *trans;
u16 pci_cmd;
- int err;
+ int ret;
trans = iwl_trans_alloc(sizeof(struct iwl_trans_pcie),
&pdev->dev, cfg, &trans_ops_pcie, 0);
@@ -2474,8 +2490,8 @@
spin_lock_init(&trans_pcie->ref_lock);
init_waitqueue_head(&trans_pcie->ucode_write_waitq);
- err = pci_enable_device(pdev);
- if (err)
+ ret = pci_enable_device(pdev);
+ if (ret)
goto out_no_pci;
if (!cfg->base_params->pcie_l1_allowed) {
@@ -2491,23 +2507,23 @@
pci_set_master(pdev);
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
- if (!err)
- err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
- if (err) {
- err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (!err)
- err = pci_set_consistent_dma_mask(pdev,
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
+ if (!ret)
+ ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
+ if (ret) {
+ ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (!ret)
+ ret = pci_set_consistent_dma_mask(pdev,
DMA_BIT_MASK(32));
/* both attempts failed: */
- if (err) {
+ if (ret) {
dev_err(&pdev->dev, "No suitable DMA available\n");
goto out_pci_disable_device;
}
}
- err = pci_request_regions(pdev, DRV_NAME);
- if (err) {
+ ret = pci_request_regions(pdev, DRV_NAME);
+ if (ret) {
dev_err(&pdev->dev, "pci_request_regions failed\n");
goto out_pci_disable_device;
}
@@ -2515,7 +2531,7 @@
trans_pcie->hw_base = pci_ioremap_bar(pdev, 0);
if (!trans_pcie->hw_base) {
dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
- err = -ENODEV;
+ ret = -ENODEV;
goto out_pci_release_regions;
}
@@ -2527,9 +2543,9 @@
trans_pcie->pci_dev = pdev;
iwl_disable_interrupts(trans);
- err = pci_enable_msi(pdev);
- if (err) {
- dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err);
+ ret = pci_enable_msi(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", ret);
/* enable rfkill interrupt: hw bug w/a */
pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
@@ -2547,11 +2563,16 @@
*/
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
unsigned long flags;
- int ret;
trans->hw_rev = (trans->hw_rev & 0xfff0) |
(CSR_HW_REV_STEP(trans->hw_rev << 2) << 2);
+ ret = iwl_pcie_prepare_card_hw(trans);
+ if (ret) {
+ IWL_WARN(trans, "Exit HW not ready\n");
+ goto out_pci_disable_msi;
+ }
+
/*
* in-order to recognize C step driver should read chip version
* id located at the AUX bus MISC address space.
@@ -2591,13 +2612,14 @@
/* Initialize the wait queue for commands */
init_waitqueue_head(&trans_pcie->wait_command_queue);
- if (iwl_pcie_alloc_ict(trans))
+ ret = iwl_pcie_alloc_ict(trans);
+ if (ret)
goto out_pci_disable_msi;
- err = request_threaded_irq(pdev->irq, iwl_pcie_isr,
+ ret = request_threaded_irq(pdev->irq, iwl_pcie_isr,
iwl_pcie_irq_handler,
IRQF_SHARED, DRV_NAME, trans);
- if (err) {
+ if (ret) {
IWL_ERR(trans, "Error allocating IRQ %d\n", pdev->irq);
goto out_free_ict;
}
@@ -2617,5 +2639,5 @@
pci_disable_device(pdev);
out_no_pci:
iwl_trans_free(trans);
- return ERR_PTR(err);
+ return ERR_PTR(ret);
}
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 2b86c21..607acb5 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -1875,8 +1875,19 @@
/* start timer if queue currently empty */
if (q->read_ptr == q->write_ptr) {
- if (txq->wd_timeout)
- mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout);
+ if (txq->wd_timeout) {
+ /*
+ * If the TXQ is active, then set the timer, if not,
+ * set the timer in remainder so that the timer will
+ * be armed with the right value when the station will
+ * wake up.
+ */
+ if (!txq->frozen)
+ mod_timer(&txq->stuck_timer,
+ jiffies + txq->wd_timeout);
+ else
+ txq->frozen_expiry_remainder = txq->wd_timeout;
+ }
IWL_DEBUG_RPM(trans, "Q: %d first tx - take ref\n", q->id);
iwl_trans_pcie_ref(trans);
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
index b6cc9ff..1c6788ae 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio_ops.c
@@ -172,6 +172,7 @@
(struct rsi_91x_sdiodev *)adapter->rsi_dev;
u32 len;
u32 num_blocks;
+ const u8 *fw;
const struct firmware *fw_entry = NULL;
u32 block_size = dev->tx_blk_size;
int status = 0;
@@ -200,6 +201,10 @@
return status;
}
+ /* Copy firmware into DMA-accessible memory */
+ fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+ if (!fw)
+ return -ENOMEM;
len = fw_entry->size;
if (len % 4)
@@ -210,7 +215,8 @@
rsi_dbg(INIT_ZONE, "%s: Instruction size:%d\n", __func__, len);
rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
- status = rsi_copy_to_card(common, fw_entry->data, len, num_blocks);
+ status = rsi_copy_to_card(common, fw, len, num_blocks);
+ kfree(fw);
release_firmware(fw_entry);
return status;
}
diff --git a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
index 1106ce7..30c2cf7 100644
--- a/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
+++ b/drivers/net/wireless/rsi/rsi_91x_usb_ops.c
@@ -146,7 +146,10 @@
return status;
}
+ /* Copy firmware into DMA-accessible memory */
fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
+ if (!fw)
+ return -ENOMEM;
len = fw_entry->size;
if (len % 4)
@@ -158,6 +161,7 @@
rsi_dbg(INIT_ZONE, "%s: num blocks: %d\n", __func__, num_blocks);
status = rsi_copy_to_card(common, fw, len, num_blocks);
+ kfree(fw);
release_firmware(fw_entry);
return status;
}
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index 3b3a88b..585d088 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -1015,9 +1015,12 @@
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
+ struct rtl_tcb_desc tcb_desc;
- if (skb)
- rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, NULL);
+ if (skb) {
+ memset(&tcb_desc, 0, sizeof(struct rtl_tcb_desc));
+ rtlpriv->intf_ops->adapter_tx(hw, NULL, skb, &tcb_desc);
+ }
}
static void rtl_op_bss_info_changed(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
index 1017f02..7bf88d9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
@@ -385,6 +385,7 @@
module_param_named(ips, rtl8723be_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl8723be_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl8723be_mod_params.fwctrl_lps, bool, 0444);
+module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444);
module_param_named(disable_watchdog, rtl8723be_mod_params.disable_watchdog,
bool, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 1a83e19..28577a3 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -61,6 +61,12 @@
void xenvif_skb_zerocopy_complete(struct xenvif_queue *queue)
{
atomic_dec(&queue->inflight_packets);
+
+ /* Wake the dealloc thread _after_ decrementing inflight_packets so
+ * that if kthread_stop() has already been called, the dealloc thread
+ * does not wait forever with nothing to wake it.
+ */
+ wake_up(&queue->dealloc_wq);
}
int xenvif_schedulable(struct xenvif *vif)
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c
index 880d0d6..3f44b52 100644
--- a/drivers/net/xen-netback/netback.c
+++ b/drivers/net/xen-netback/netback.c
@@ -810,23 +810,17 @@
static struct gnttab_map_grant_ref *xenvif_get_requests(struct xenvif_queue *queue,
struct sk_buff *skb,
struct xen_netif_tx_request *txp,
- struct gnttab_map_grant_ref *gop)
+ struct gnttab_map_grant_ref *gop,
+ unsigned int frag_overflow,
+ struct sk_buff *nskb)
{
struct skb_shared_info *shinfo = skb_shinfo(skb);
skb_frag_t *frags = shinfo->frags;
u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx;
int start;
pending_ring_idx_t index;
- unsigned int nr_slots, frag_overflow = 0;
+ unsigned int nr_slots;
- /* At this point shinfo->nr_frags is in fact the number of
- * slots, which can be as large as XEN_NETBK_LEGACY_SLOTS_MAX.
- */
- if (shinfo->nr_frags > MAX_SKB_FRAGS) {
- frag_overflow = shinfo->nr_frags - MAX_SKB_FRAGS;
- BUG_ON(frag_overflow > MAX_SKB_FRAGS);
- shinfo->nr_frags = MAX_SKB_FRAGS;
- }
nr_slots = shinfo->nr_frags;
/* Skip first skb fragment if it is on same page as header fragment. */
@@ -841,13 +835,6 @@
}
if (frag_overflow) {
- struct sk_buff *nskb = xenvif_alloc_skb(0);
- if (unlikely(nskb == NULL)) {
- if (net_ratelimit())
- netdev_err(queue->vif->dev,
- "Can't allocate the frag_list skb.\n");
- return NULL;
- }
shinfo = skb_shinfo(nskb);
frags = shinfo->frags;
@@ -1175,9 +1162,10 @@
unsigned *copy_ops,
unsigned *map_ops)
{
- struct gnttab_map_grant_ref *gop = queue->tx_map_ops, *request_gop;
- struct sk_buff *skb;
+ struct gnttab_map_grant_ref *gop = queue->tx_map_ops;
+ struct sk_buff *skb, *nskb;
int ret;
+ unsigned int frag_overflow;
while (skb_queue_len(&queue->tx_queue) < budget) {
struct xen_netif_tx_request txreq;
@@ -1265,6 +1253,29 @@
break;
}
+ skb_shinfo(skb)->nr_frags = ret;
+ if (data_len < txreq.size)
+ skb_shinfo(skb)->nr_frags++;
+ /* At this point shinfo->nr_frags is in fact the number of
+ * slots, which can be as large as XEN_NETBK_LEGACY_SLOTS_MAX.
+ */
+ frag_overflow = 0;
+ nskb = NULL;
+ if (skb_shinfo(skb)->nr_frags > MAX_SKB_FRAGS) {
+ frag_overflow = skb_shinfo(skb)->nr_frags - MAX_SKB_FRAGS;
+ BUG_ON(frag_overflow > MAX_SKB_FRAGS);
+ skb_shinfo(skb)->nr_frags = MAX_SKB_FRAGS;
+ nskb = xenvif_alloc_skb(0);
+ if (unlikely(nskb == NULL)) {
+ kfree_skb(skb);
+ xenvif_tx_err(queue, &txreq, idx);
+ if (net_ratelimit())
+ netdev_err(queue->vif->dev,
+ "Can't allocate the frag_list skb.\n");
+ break;
+ }
+ }
+
if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
struct xen_netif_extra_info *gso;
gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
@@ -1272,6 +1283,7 @@
if (xenvif_set_skb_gso(queue->vif, skb, gso)) {
/* Failure in xenvif_set_skb_gso is fatal. */
kfree_skb(skb);
+ kfree_skb(nskb);
break;
}
}
@@ -1294,9 +1306,7 @@
(*copy_ops)++;
- skb_shinfo(skb)->nr_frags = ret;
if (data_len < txreq.size) {
- skb_shinfo(skb)->nr_frags++;
frag_set_pending_idx(&skb_shinfo(skb)->frags[0],
pending_idx);
xenvif_tx_create_map_op(queue, pending_idx, &txreq, gop);
@@ -1310,13 +1320,8 @@
queue->pending_cons++;
- request_gop = xenvif_get_requests(queue, skb, txfrags, gop);
- if (request_gop == NULL) {
- kfree_skb(skb);
- xenvif_tx_err(queue, &txreq, idx);
- break;
- }
- gop = request_gop;
+ gop = xenvif_get_requests(queue, skb, txfrags, gop,
+ frag_overflow, nskb);
__skb_queue_tail(&queue->tx_queue, skb);
@@ -1536,7 +1541,6 @@
smp_wmb();
queue->dealloc_prod++;
} while (ubuf);
- wake_up(&queue->dealloc_wq);
spin_unlock_irqrestore(&queue->callback_lock, flags);
if (likely(zerocopy_success))
@@ -1566,13 +1570,13 @@
smp_rmb();
while (dc != dp) {
- BUG_ON(gop - queue->tx_unmap_ops > MAX_PENDING_REQS);
+ BUG_ON(gop - queue->tx_unmap_ops >= MAX_PENDING_REQS);
pending_idx =
queue->dealloc_ring[pending_index(dc++)];
- pending_idx_release[gop-queue->tx_unmap_ops] =
+ pending_idx_release[gop - queue->tx_unmap_ops] =
pending_idx;
- queue->pages_to_unmap[gop-queue->tx_unmap_ops] =
+ queue->pages_to_unmap[gop - queue->tx_unmap_ops] =
queue->mmap_pages[pending_idx];
gnttab_set_unmap_op(gop,
idx_to_kaddr(queue, pending_idx),
diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c
index 2b77ccf..754a9bb 100644
--- a/drivers/nfc/mei_phy.c
+++ b/drivers/nfc/mei_phy.c
@@ -355,7 +355,8 @@
goto err;
}
- r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy);
+ r = mei_cl_register_event_cb(phy->device, BIT(MEI_CL_EVENT_RX),
+ nfc_mei_event_cb, phy);
if (r) {
pr_err("Event cb registration failed %d\n", r);
goto err;
diff --git a/drivers/ntb/ntb.c b/drivers/ntb/ntb.c
index 23435f2..2e25307 100644
--- a/drivers/ntb/ntb.c
+++ b/drivers/ntb/ntb.c
@@ -114,7 +114,7 @@
ntb->dev.bus = &ntb_bus;
ntb->dev.parent = &ntb->pdev->dev;
ntb->dev.release = ntb_dev_release;
- dev_set_name(&ntb->dev, pci_name(ntb->pdev));
+ dev_set_name(&ntb->dev, "%s", pci_name(ntb->pdev));
ntb->ctx = NULL;
ntb->ctx_ops = NULL;
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index efe3ad4..1c6386d 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -142,10 +142,11 @@
void (*rx_handler)(struct ntb_transport_qp *qp, void *qp_data,
void *data, int len);
+ struct list_head rx_post_q;
struct list_head rx_pend_q;
struct list_head rx_free_q;
- spinlock_t ntb_rx_pend_q_lock;
- spinlock_t ntb_rx_free_q_lock;
+ /* ntb_rx_q_lock: synchronize access to rx_XXXX_q */
+ spinlock_t ntb_rx_q_lock;
void *rx_buff;
unsigned int rx_index;
unsigned int rx_max_entry;
@@ -211,6 +212,8 @@
bool link_is_up;
struct delayed_work link_work;
struct work_struct link_cleanup;
+
+ struct dentry *debugfs_node_dir;
};
enum {
@@ -436,13 +439,17 @@
char *buf;
ssize_t ret, out_offset, out_count;
+ qp = filp->private_data;
+
+ if (!qp || !qp->link_is_up)
+ return 0;
+
out_count = 1000;
buf = kmalloc(out_count, GFP_KERNEL);
if (!buf)
return -ENOMEM;
- qp = filp->private_data;
out_offset = 0;
out_offset += snprintf(buf + out_offset, out_count - out_offset,
"NTB QP stats\n");
@@ -534,6 +541,27 @@
return entry;
}
+static struct ntb_queue_entry *ntb_list_mv(spinlock_t *lock,
+ struct list_head *list,
+ struct list_head *to_list)
+{
+ struct ntb_queue_entry *entry;
+ unsigned long flags;
+
+ spin_lock_irqsave(lock, flags);
+
+ if (list_empty(list)) {
+ entry = NULL;
+ } else {
+ entry = list_first_entry(list, struct ntb_queue_entry, entry);
+ list_move_tail(&entry->entry, to_list);
+ }
+
+ spin_unlock_irqrestore(lock, flags);
+
+ return entry;
+}
+
static int ntb_transport_setup_qp_mw(struct ntb_transport_ctx *nt,
unsigned int qp_num)
{
@@ -601,13 +629,16 @@
}
static int ntb_set_mw(struct ntb_transport_ctx *nt, int num_mw,
- unsigned int size)
+ resource_size_t size)
{
struct ntb_transport_mw *mw = &nt->mw_vec[num_mw];
struct pci_dev *pdev = nt->ndev->pdev;
- unsigned int xlat_size, buff_size;
+ size_t xlat_size, buff_size;
int rc;
+ if (!size)
+ return -EINVAL;
+
xlat_size = round_up(size, mw->xlat_align_size);
buff_size = round_up(size, mw->xlat_align);
@@ -627,7 +658,7 @@
if (!mw->virt_addr) {
mw->xlat_size = 0;
mw->buff_size = 0;
- dev_err(&pdev->dev, "Unable to alloc MW buff of size %d\n",
+ dev_err(&pdev->dev, "Unable to alloc MW buff of size %zu\n",
buff_size);
return -ENOMEM;
}
@@ -867,6 +898,8 @@
if (qp->event_handler)
qp->event_handler(qp->cb_data, qp->link_is_up);
+
+ tasklet_schedule(&qp->rxc_db_work);
} else if (nt->link_is_up)
schedule_delayed_work(&qp->link_work,
msecs_to_jiffies(NTB_LINK_DOWN_TIMEOUT));
@@ -923,12 +956,12 @@
qp->tx_max_frame = min(transport_mtu, tx_size / 2);
qp->tx_max_entry = tx_size / qp->tx_max_frame;
- if (nt_debugfs_dir) {
+ if (nt->debugfs_node_dir) {
char debugfs_name[4];
snprintf(debugfs_name, 4, "qp%d", qp_num);
qp->debugfs_dir = debugfs_create_dir(debugfs_name,
- nt_debugfs_dir);
+ nt->debugfs_node_dir);
qp->debugfs_stats = debugfs_create_file("stats", S_IRUSR,
qp->debugfs_dir, qp,
@@ -941,10 +974,10 @@
INIT_DELAYED_WORK(&qp->link_work, ntb_qp_link_work);
INIT_WORK(&qp->link_cleanup, ntb_qp_link_cleanup_work);
- spin_lock_init(&qp->ntb_rx_pend_q_lock);
- spin_lock_init(&qp->ntb_rx_free_q_lock);
+ spin_lock_init(&qp->ntb_rx_q_lock);
spin_lock_init(&qp->ntb_tx_free_q_lock);
+ INIT_LIST_HEAD(&qp->rx_post_q);
INIT_LIST_HEAD(&qp->rx_pend_q);
INIT_LIST_HEAD(&qp->rx_free_q);
INIT_LIST_HEAD(&qp->tx_free_q);
@@ -1031,6 +1064,12 @@
goto err2;
}
+ if (nt_debugfs_dir) {
+ nt->debugfs_node_dir =
+ debugfs_create_dir(pci_name(ndev->pdev),
+ nt_debugfs_dir);
+ }
+
for (i = 0; i < qp_count; i++) {
rc = ntb_transport_init_queue(nt, i);
if (rc)
@@ -1107,22 +1146,47 @@
kfree(nt);
}
+static void ntb_complete_rxc(struct ntb_transport_qp *qp)
+{
+ struct ntb_queue_entry *entry;
+ void *cb_data;
+ unsigned int len;
+ unsigned long irqflags;
+
+ spin_lock_irqsave(&qp->ntb_rx_q_lock, irqflags);
+
+ while (!list_empty(&qp->rx_post_q)) {
+ entry = list_first_entry(&qp->rx_post_q,
+ struct ntb_queue_entry, entry);
+ if (!(entry->flags & DESC_DONE_FLAG))
+ break;
+
+ entry->rx_hdr->flags = 0;
+ iowrite32(entry->index, &qp->rx_info->entry);
+
+ cb_data = entry->cb_data;
+ len = entry->len;
+
+ list_move_tail(&entry->entry, &qp->rx_free_q);
+
+ spin_unlock_irqrestore(&qp->ntb_rx_q_lock, irqflags);
+
+ if (qp->rx_handler && qp->client_ready)
+ qp->rx_handler(qp, qp->cb_data, cb_data, len);
+
+ spin_lock_irqsave(&qp->ntb_rx_q_lock, irqflags);
+ }
+
+ spin_unlock_irqrestore(&qp->ntb_rx_q_lock, irqflags);
+}
+
static void ntb_rx_copy_callback(void *data)
{
struct ntb_queue_entry *entry = data;
- struct ntb_transport_qp *qp = entry->qp;
- void *cb_data = entry->cb_data;
- unsigned int len = entry->len;
- struct ntb_payload_header *hdr = entry->rx_hdr;
- hdr->flags = 0;
+ entry->flags |= DESC_DONE_FLAG;
- iowrite32(entry->index, &qp->rx_info->entry);
-
- ntb_list_add(&qp->ntb_rx_free_q_lock, &entry->entry, &qp->rx_free_q);
-
- if (qp->rx_handler && qp->client_ready)
- qp->rx_handler(qp, qp->cb_data, cb_data, len);
+ ntb_complete_rxc(entry->qp);
}
static void ntb_memcpy_rx(struct ntb_queue_entry *entry, void *offset)
@@ -1138,19 +1202,18 @@
ntb_rx_copy_callback(entry);
}
-static void ntb_async_rx(struct ntb_queue_entry *entry, void *offset,
- size_t len)
+static void ntb_async_rx(struct ntb_queue_entry *entry, void *offset)
{
struct dma_async_tx_descriptor *txd;
struct ntb_transport_qp *qp = entry->qp;
struct dma_chan *chan = qp->dma_chan;
struct dma_device *device;
- size_t pay_off, buff_off;
+ size_t pay_off, buff_off, len;
struct dmaengine_unmap_data *unmap;
dma_cookie_t cookie;
void *buf = entry->buf;
- entry->len = len;
+ len = entry->len;
if (!chan)
goto err;
@@ -1226,7 +1289,6 @@
struct ntb_payload_header *hdr;
struct ntb_queue_entry *entry;
void *offset;
- int rc;
offset = qp->rx_buff + qp->rx_max_frame * qp->rx_index;
hdr = offset + qp->rx_max_frame - sizeof(struct ntb_payload_header);
@@ -1255,65 +1317,43 @@
return -EIO;
}
- entry = ntb_list_rm(&qp->ntb_rx_pend_q_lock, &qp->rx_pend_q);
+ entry = ntb_list_mv(&qp->ntb_rx_q_lock, &qp->rx_pend_q, &qp->rx_post_q);
if (!entry) {
dev_dbg(&qp->ndev->pdev->dev, "no receive buffer\n");
qp->rx_err_no_buf++;
-
- rc = -ENOMEM;
- goto err;
+ return -EAGAIN;
}
+ entry->rx_hdr = hdr;
+ entry->index = qp->rx_index;
+
if (hdr->len > entry->len) {
dev_dbg(&qp->ndev->pdev->dev,
"receive buffer overflow! Wanted %d got %d\n",
hdr->len, entry->len);
qp->rx_err_oflow++;
- rc = -EIO;
- goto err;
+ entry->len = -EIO;
+ entry->flags |= DESC_DONE_FLAG;
+
+ ntb_complete_rxc(qp);
+ } else {
+ dev_dbg(&qp->ndev->pdev->dev,
+ "RX OK index %u ver %u size %d into buf size %d\n",
+ qp->rx_index, hdr->ver, hdr->len, entry->len);
+
+ qp->rx_bytes += hdr->len;
+ qp->rx_pkts++;
+
+ entry->len = hdr->len;
+
+ ntb_async_rx(entry, offset);
}
- dev_dbg(&qp->ndev->pdev->dev,
- "RX OK index %u ver %u size %d into buf size %d\n",
- qp->rx_index, hdr->ver, hdr->len, entry->len);
-
- qp->rx_bytes += hdr->len;
- qp->rx_pkts++;
-
- entry->index = qp->rx_index;
- entry->rx_hdr = hdr;
-
- ntb_async_rx(entry, offset, hdr->len);
-
qp->rx_index++;
qp->rx_index %= qp->rx_max_entry;
return 0;
-
-err:
- /* FIXME: if this syncrhonous update of the rx_index gets ahead of
- * asyncrhonous ntb_rx_copy_callback of previous entry, there are three
- * scenarios:
- *
- * 1) The peer might miss this update, but observe the update
- * from the memcpy completion callback. In this case, the buffer will
- * not be freed on the peer to be reused for a different packet. The
- * successful rx of a later packet would clear the condition, but the
- * condition could persist if several rx fail in a row.
- *
- * 2) The peer may observe this update before the asyncrhonous copy of
- * prior packets is completed. The peer may overwrite the buffers of
- * the prior packets before they are copied.
- *
- * 3) Both: the peer may observe the update, and then observe the index
- * decrement by the asynchronous completion callback. Who knows what
- * badness that will cause.
- */
- hdr->flags = 0;
- iowrite32(qp->rx_index, &qp->rx_info->entry);
-
- return rc;
}
static void ntb_transport_rxc_db(unsigned long data)
@@ -1333,7 +1373,7 @@
break;
}
- if (qp->dma_chan)
+ if (i && qp->dma_chan)
dma_async_issue_pending(qp->dma_chan);
if (i == qp->rx_max_entry) {
@@ -1609,7 +1649,7 @@
goto err1;
entry->qp = qp;
- ntb_list_add(&qp->ntb_rx_free_q_lock, &entry->entry,
+ ntb_list_add(&qp->ntb_rx_q_lock, &entry->entry,
&qp->rx_free_q);
}
@@ -1634,7 +1674,7 @@
while ((entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q)))
kfree(entry);
err1:
- while ((entry = ntb_list_rm(&qp->ntb_rx_free_q_lock, &qp->rx_free_q)))
+ while ((entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_free_q)))
kfree(entry);
if (qp->dma_chan)
dma_release_channel(qp->dma_chan);
@@ -1652,7 +1692,6 @@
*/
void ntb_transport_free_queue(struct ntb_transport_qp *qp)
{
- struct ntb_transport_ctx *nt = qp->transport;
struct pci_dev *pdev;
struct ntb_queue_entry *entry;
u64 qp_bit;
@@ -1689,18 +1728,23 @@
qp->tx_handler = NULL;
qp->event_handler = NULL;
- while ((entry = ntb_list_rm(&qp->ntb_rx_free_q_lock, &qp->rx_free_q)))
+ while ((entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_free_q)))
kfree(entry);
- while ((entry = ntb_list_rm(&qp->ntb_rx_pend_q_lock, &qp->rx_pend_q))) {
- dev_warn(&pdev->dev, "Freeing item from a non-empty queue\n");
+ while ((entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_pend_q))) {
+ dev_warn(&pdev->dev, "Freeing item from non-empty rx_pend_q\n");
+ kfree(entry);
+ }
+
+ while ((entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_post_q))) {
+ dev_warn(&pdev->dev, "Freeing item from non-empty rx_post_q\n");
kfree(entry);
}
while ((entry = ntb_list_rm(&qp->ntb_tx_free_q_lock, &qp->tx_free_q)))
kfree(entry);
- nt->qp_bitmap_free |= qp_bit;
+ qp->transport->qp_bitmap_free |= qp_bit;
dev_info(&pdev->dev, "NTB Transport QP %d freed\n", qp->qp_num);
}
@@ -1724,14 +1768,14 @@
if (!qp || qp->client_ready)
return NULL;
- entry = ntb_list_rm(&qp->ntb_rx_pend_q_lock, &qp->rx_pend_q);
+ entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_pend_q);
if (!entry)
return NULL;
buf = entry->cb_data;
*len = entry->len;
- ntb_list_add(&qp->ntb_rx_free_q_lock, &entry->entry, &qp->rx_free_q);
+ ntb_list_add(&qp->ntb_rx_q_lock, &entry->entry, &qp->rx_free_q);
return buf;
}
@@ -1757,15 +1801,18 @@
if (!qp)
return -EINVAL;
- entry = ntb_list_rm(&qp->ntb_rx_free_q_lock, &qp->rx_free_q);
+ entry = ntb_list_rm(&qp->ntb_rx_q_lock, &qp->rx_free_q);
if (!entry)
return -ENOMEM;
entry->cb_data = cb;
entry->buf = data;
entry->len = len;
+ entry->flags = 0;
- ntb_list_add(&qp->ntb_rx_pend_q_lock, &entry->entry, &qp->rx_pend_q);
+ ntb_list_add(&qp->ntb_rx_q_lock, &entry->entry, &qp->rx_pend_q);
+
+ tasklet_schedule(&qp->rxc_db_work);
return 0;
}
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index a523342..7384455 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -458,10 +458,15 @@
nvdimm_bus_unlock(dev);
}
if (is_nd_btt(dev) && probe) {
+ struct nd_btt *nd_btt = to_nd_btt(dev);
+
nd_region = to_nd_region(dev->parent);
nvdimm_bus_lock(dev);
if (nd_region->btt_seed == dev)
nd_region_create_btt_seed(nd_region);
+ if (nd_region->ns_seed == &nd_btt->ndns->dev &&
+ is_nd_blk(dev->parent))
+ nd_region_create_blk_seed(nd_region);
nvdimm_bus_unlock(dev);
}
}
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
new file mode 100644
index 0000000..8db2978
--- /dev/null
+++ b/drivers/nvmem/Kconfig
@@ -0,0 +1,39 @@
+menuconfig NVMEM
+ tristate "NVMEM Support"
+ select REGMAP
+ help
+ Support for NVMEM(Non Volatile Memory) devices like EEPROM, EFUSES...
+
+ This framework is designed to provide a generic interface to NVMEM
+ from both the Linux Kernel and the userspace.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_core.
+
+ If unsure, say no.
+
+if NVMEM
+
+config QCOM_QFPROM
+ tristate "QCOM QFPROM Support"
+ depends on ARCH_QCOM || COMPILE_TEST
+ select REGMAP_MMIO
+ help
+ Say y here to enable QFPROM support. The QFPROM provides access
+ functions for QFPROM data to rest of the drivers via nvmem interface.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_qfprom.
+
+config NVMEM_SUNXI_SID
+ tristate "Allwinner SoCs SID support"
+ depends on ARCH_SUNXI
+ select REGMAP_MMIO
+ help
+ This is a driver for the 'security ID' available on various Allwinner
+ devices.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem_sunxi_sid.
+
+endif
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
new file mode 100644
index 0000000..4328b93
--- /dev/null
+++ b/drivers/nvmem/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for nvmem drivers.
+#
+
+obj-$(CONFIG_NVMEM) += nvmem_core.o
+nvmem_core-y := core.o
+
+# Devices
+obj-$(CONFIG_QCOM_QFPROM) += nvmem_qfprom.o
+nvmem_qfprom-y := qfprom.o
+obj-$(CONFIG_NVMEM_SUNXI_SID) += nvmem_sunxi_sid.o
+nvmem_sunxi_sid-y := sunxi_sid.o
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
new file mode 100644
index 0000000..d3c6676
--- /dev/null
+++ b/drivers/nvmem/core.c
@@ -0,0 +1,1083 @@
+/*
+ * nvmem framework core.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+struct nvmem_device {
+ const char *name;
+ struct regmap *regmap;
+ struct module *owner;
+ struct device dev;
+ int stride;
+ int word_size;
+ int ncells;
+ int id;
+ int users;
+ size_t size;
+ bool read_only;
+};
+
+struct nvmem_cell {
+ const char *name;
+ int offset;
+ int bytes;
+ int bit_offset;
+ int nbits;
+ struct nvmem_device *nvmem;
+ struct list_head node;
+};
+
+static DEFINE_MUTEX(nvmem_mutex);
+static DEFINE_IDA(nvmem_ida);
+
+static LIST_HEAD(nvmem_cells);
+static DEFINE_MUTEX(nvmem_cells_mutex);
+
+#define to_nvmem_device(d) container_of(d, struct nvmem_device, dev)
+
+static ssize_t bin_attr_nvmem_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t pos, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct nvmem_device *nvmem = to_nvmem_device(dev);
+ int rc;
+
+ /* Stop the user from reading */
+ if (pos > nvmem->size)
+ return 0;
+
+ if (pos + count > nvmem->size)
+ count = nvmem->size - pos;
+
+ count = round_down(count, nvmem->word_size);
+
+ rc = regmap_raw_read(nvmem->regmap, pos, buf, count);
+
+ if (IS_ERR_VALUE(rc))
+ return rc;
+
+ return count;
+}
+
+static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t pos, size_t count)
+{
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct nvmem_device *nvmem = to_nvmem_device(dev);
+ int rc;
+
+ /* Stop the user from writing */
+ if (pos > nvmem->size)
+ return 0;
+
+ if (pos + count > nvmem->size)
+ count = nvmem->size - pos;
+
+ count = round_down(count, nvmem->word_size);
+
+ rc = regmap_raw_write(nvmem->regmap, pos, buf, count);
+
+ if (IS_ERR_VALUE(rc))
+ return rc;
+
+ return count;
+}
+
+/* default read/write permissions */
+static struct bin_attribute bin_attr_rw_nvmem = {
+ .attr = {
+ .name = "nvmem",
+ .mode = S_IWUSR | S_IRUGO,
+ },
+ .read = bin_attr_nvmem_read,
+ .write = bin_attr_nvmem_write,
+};
+
+static struct bin_attribute *nvmem_bin_rw_attributes[] = {
+ &bin_attr_rw_nvmem,
+ NULL,
+};
+
+static const struct attribute_group nvmem_bin_rw_group = {
+ .bin_attrs = nvmem_bin_rw_attributes,
+};
+
+static const struct attribute_group *nvmem_rw_dev_groups[] = {
+ &nvmem_bin_rw_group,
+ NULL,
+};
+
+/* read only permission */
+static struct bin_attribute bin_attr_ro_nvmem = {
+ .attr = {
+ .name = "nvmem",
+ .mode = S_IRUGO,
+ },
+ .read = bin_attr_nvmem_read,
+};
+
+static struct bin_attribute *nvmem_bin_ro_attributes[] = {
+ &bin_attr_ro_nvmem,
+ NULL,
+};
+
+static const struct attribute_group nvmem_bin_ro_group = {
+ .bin_attrs = nvmem_bin_ro_attributes,
+};
+
+static const struct attribute_group *nvmem_ro_dev_groups[] = {
+ &nvmem_bin_ro_group,
+ NULL,
+};
+
+static void nvmem_release(struct device *dev)
+{
+ struct nvmem_device *nvmem = to_nvmem_device(dev);
+
+ ida_simple_remove(&nvmem_ida, nvmem->id);
+ kfree(nvmem);
+}
+
+static const struct device_type nvmem_provider_type = {
+ .release = nvmem_release,
+};
+
+static struct bus_type nvmem_bus_type = {
+ .name = "nvmem",
+};
+
+static int of_nvmem_match(struct device *dev, void *nvmem_np)
+{
+ return dev->of_node == nvmem_np;
+}
+
+static struct nvmem_device *of_nvmem_find(struct device_node *nvmem_np)
+{
+ struct device *d;
+
+ if (!nvmem_np)
+ return NULL;
+
+ d = bus_find_device(&nvmem_bus_type, NULL, nvmem_np, of_nvmem_match);
+
+ if (!d)
+ return NULL;
+
+ return to_nvmem_device(d);
+}
+
+static struct nvmem_cell *nvmem_find_cell(const char *cell_id)
+{
+ struct nvmem_cell *p;
+
+ list_for_each_entry(p, &nvmem_cells, node)
+ if (p && !strcmp(p->name, cell_id))
+ return p;
+
+ return NULL;
+}
+
+static void nvmem_cell_drop(struct nvmem_cell *cell)
+{
+ mutex_lock(&nvmem_cells_mutex);
+ list_del(&cell->node);
+ mutex_unlock(&nvmem_cells_mutex);
+ kfree(cell);
+}
+
+static void nvmem_device_remove_all_cells(const struct nvmem_device *nvmem)
+{
+ struct nvmem_cell *cell;
+ struct list_head *p, *n;
+
+ list_for_each_safe(p, n, &nvmem_cells) {
+ cell = list_entry(p, struct nvmem_cell, node);
+ if (cell->nvmem == nvmem)
+ nvmem_cell_drop(cell);
+ }
+}
+
+static void nvmem_cell_add(struct nvmem_cell *cell)
+{
+ mutex_lock(&nvmem_cells_mutex);
+ list_add_tail(&cell->node, &nvmem_cells);
+ mutex_unlock(&nvmem_cells_mutex);
+}
+
+static int nvmem_cell_info_to_nvmem_cell(struct nvmem_device *nvmem,
+ const struct nvmem_cell_info *info,
+ struct nvmem_cell *cell)
+{
+ cell->nvmem = nvmem;
+ cell->offset = info->offset;
+ cell->bytes = info->bytes;
+ cell->name = info->name;
+
+ cell->bit_offset = info->bit_offset;
+ cell->nbits = info->nbits;
+
+ if (cell->nbits)
+ cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+ BITS_PER_BYTE);
+
+ if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+ dev_err(&nvmem->dev,
+ "cell %s unaligned to nvmem stride %d\n",
+ cell->name, nvmem->stride);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int nvmem_add_cells(struct nvmem_device *nvmem,
+ const struct nvmem_config *cfg)
+{
+ struct nvmem_cell **cells;
+ const struct nvmem_cell_info *info = cfg->cells;
+ int i, rval;
+
+ cells = kcalloc(cfg->ncells, sizeof(*cells), GFP_KERNEL);
+ if (!cells)
+ return -ENOMEM;
+
+ for (i = 0; i < cfg->ncells; i++) {
+ cells[i] = kzalloc(sizeof(**cells), GFP_KERNEL);
+ if (!cells[i]) {
+ rval = -ENOMEM;
+ goto err;
+ }
+
+ rval = nvmem_cell_info_to_nvmem_cell(nvmem, &info[i], cells[i]);
+ if (IS_ERR_VALUE(rval)) {
+ kfree(cells[i]);
+ goto err;
+ }
+
+ nvmem_cell_add(cells[i]);
+ }
+
+ nvmem->ncells = cfg->ncells;
+ /* remove tmp array */
+ kfree(cells);
+
+ return 0;
+err:
+ while (--i)
+ nvmem_cell_drop(cells[i]);
+
+ return rval;
+}
+
+/**
+ * nvmem_register() - Register a nvmem device for given nvmem_config.
+ * Also creates an binary entry in /sys/bus/nvmem/devices/dev-name/nvmem
+ *
+ * @config: nvmem device configuration with which nvmem device is created.
+ *
+ * Return: Will be an ERR_PTR() on error or a valid pointer to nvmem_device
+ * on success.
+ */
+
+struct nvmem_device *nvmem_register(const struct nvmem_config *config)
+{
+ struct nvmem_device *nvmem;
+ struct device_node *np;
+ struct regmap *rm;
+ int rval;
+
+ if (!config->dev)
+ return ERR_PTR(-EINVAL);
+
+ rm = dev_get_regmap(config->dev, NULL);
+ if (!rm) {
+ dev_err(config->dev, "Regmap not found\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ nvmem = kzalloc(sizeof(*nvmem), GFP_KERNEL);
+ if (!nvmem)
+ return ERR_PTR(-ENOMEM);
+
+ rval = ida_simple_get(&nvmem_ida, 0, 0, GFP_KERNEL);
+ if (rval < 0) {
+ kfree(nvmem);
+ return ERR_PTR(rval);
+ }
+
+ nvmem->id = rval;
+ nvmem->regmap = rm;
+ nvmem->owner = config->owner;
+ nvmem->stride = regmap_get_reg_stride(rm);
+ nvmem->word_size = regmap_get_val_bytes(rm);
+ nvmem->size = regmap_get_max_register(rm) + nvmem->stride;
+ nvmem->dev.type = &nvmem_provider_type;
+ nvmem->dev.bus = &nvmem_bus_type;
+ nvmem->dev.parent = config->dev;
+ np = config->dev->of_node;
+ nvmem->dev.of_node = np;
+ dev_set_name(&nvmem->dev, "%s%d",
+ config->name ? : "nvmem", config->id);
+
+ nvmem->read_only = of_property_read_bool(np, "read-only") |
+ config->read_only;
+
+ nvmem->dev.groups = nvmem->read_only ? nvmem_ro_dev_groups :
+ nvmem_rw_dev_groups;
+
+ device_initialize(&nvmem->dev);
+
+ dev_dbg(&nvmem->dev, "Registering nvmem device %s\n", config->name);
+
+ rval = device_add(&nvmem->dev);
+ if (rval) {
+ ida_simple_remove(&nvmem_ida, nvmem->id);
+ kfree(nvmem);
+ return ERR_PTR(rval);
+ }
+
+ if (config->cells)
+ nvmem_add_cells(nvmem, config);
+
+ return nvmem;
+}
+EXPORT_SYMBOL_GPL(nvmem_register);
+
+/**
+ * nvmem_unregister() - Unregister previously registered nvmem device
+ *
+ * @nvmem: Pointer to previously registered nvmem device.
+ *
+ * Return: Will be an negative on error or a zero on success.
+ */
+int nvmem_unregister(struct nvmem_device *nvmem)
+{
+ mutex_lock(&nvmem_mutex);
+ if (nvmem->users) {
+ mutex_unlock(&nvmem_mutex);
+ return -EBUSY;
+ }
+ mutex_unlock(&nvmem_mutex);
+
+ nvmem_device_remove_all_cells(nvmem);
+ device_del(&nvmem->dev);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvmem_unregister);
+
+static struct nvmem_device *__nvmem_device_get(struct device_node *np,
+ struct nvmem_cell **cellp,
+ const char *cell_id)
+{
+ struct nvmem_device *nvmem = NULL;
+
+ mutex_lock(&nvmem_mutex);
+
+ if (np) {
+ nvmem = of_nvmem_find(np);
+ if (!nvmem) {
+ mutex_unlock(&nvmem_mutex);
+ return ERR_PTR(-EPROBE_DEFER);
+ }
+ } else {
+ struct nvmem_cell *cell = nvmem_find_cell(cell_id);
+
+ if (cell) {
+ nvmem = cell->nvmem;
+ *cellp = cell;
+ }
+
+ if (!nvmem) {
+ mutex_unlock(&nvmem_mutex);
+ return ERR_PTR(-ENOENT);
+ }
+ }
+
+ nvmem->users++;
+ mutex_unlock(&nvmem_mutex);
+
+ if (!try_module_get(nvmem->owner)) {
+ dev_err(&nvmem->dev,
+ "could not increase module refcount for cell %s\n",
+ nvmem->name);
+
+ mutex_lock(&nvmem_mutex);
+ nvmem->users--;
+ mutex_unlock(&nvmem_mutex);
+
+ return ERR_PTR(-EINVAL);
+ }
+
+ return nvmem;
+}
+
+static void __nvmem_device_put(struct nvmem_device *nvmem)
+{
+ module_put(nvmem->owner);
+ mutex_lock(&nvmem_mutex);
+ nvmem->users--;
+ mutex_unlock(&nvmem_mutex);
+}
+
+static int nvmem_match(struct device *dev, void *data)
+{
+ return !strcmp(dev_name(dev), data);
+}
+
+static struct nvmem_device *nvmem_find(const char *name)
+{
+ struct device *d;
+
+ d = bus_find_device(&nvmem_bus_type, NULL, (void *)name, nvmem_match);
+
+ if (!d)
+ return NULL;
+
+ return to_nvmem_device(d);
+}
+
+#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
+/**
+ * of_nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev node: Device tree node that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
+ * on success.
+ */
+struct nvmem_device *of_nvmem_device_get(struct device_node *np, const char *id)
+{
+
+ struct device_node *nvmem_np;
+ int index;
+
+ index = of_property_match_string(np, "nvmem-names", id);
+
+ nvmem_np = of_parse_phandle(np, "nvmem", index);
+ if (!nvmem_np)
+ return ERR_PTR(-EINVAL);
+
+ return __nvmem_device_get(nvmem_np, NULL, NULL);
+}
+EXPORT_SYMBOL_GPL(of_nvmem_device_get);
+#endif
+
+/**
+ * nvmem_device_get() - Get nvmem device from a given id
+ *
+ * @dev : Device that uses the nvmem device
+ * @id: nvmem name from nvmem-names property.
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_device
+ * on success.
+ */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *dev_name)
+{
+ if (dev->of_node) { /* try dt first */
+ struct nvmem_device *nvmem;
+
+ nvmem = of_nvmem_device_get(dev->of_node, dev_name);
+
+ if (!IS_ERR(nvmem) || PTR_ERR(nvmem) == -EPROBE_DEFER)
+ return nvmem;
+
+ }
+
+ return nvmem_find(dev_name);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_get);
+
+static int devm_nvmem_device_match(struct device *dev, void *res, void *data)
+{
+ struct nvmem_device **nvmem = res;
+
+ if (WARN_ON(!nvmem || !*nvmem))
+ return 0;
+
+ return *nvmem == data;
+}
+
+static void devm_nvmem_device_release(struct device *dev, void *res)
+{
+ nvmem_device_put(*(struct nvmem_device **)res);
+}
+
+/**
+ * devm_nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
+ * that needs to be released.
+ */
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
+{
+ int ret;
+
+ ret = devres_release(dev, devm_nvmem_device_release,
+ devm_nvmem_device_match, nvmem);
+
+ WARN_ON(ret);
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
+
+/**
+ * nvmem_device_put() - put alredy got nvmem device
+ *
+ * @nvmem: pointer to nvmem device that needs to be released.
+ */
+void nvmem_device_put(struct nvmem_device *nvmem)
+{
+ __nvmem_device_put(nvmem);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_put);
+
+/**
+ * devm_nvmem_device_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem name in nvmems property.
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a struct nvmem_cell
+ * on success. The nvmem_cell will be freed by the automatically once the
+ * device is freed.
+ */
+struct nvmem_device *devm_nvmem_device_get(struct device *dev, const char *id)
+{
+ struct nvmem_device **ptr, *nvmem;
+
+ ptr = devres_alloc(devm_nvmem_device_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ nvmem = nvmem_device_get(dev, id);
+ if (!IS_ERR(nvmem)) {
+ *ptr = nvmem;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return nvmem;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_device_get);
+
+static struct nvmem_cell *nvmem_cell_get_from_list(const char *cell_id)
+{
+ struct nvmem_cell *cell = NULL;
+ struct nvmem_device *nvmem;
+
+ nvmem = __nvmem_device_get(NULL, &cell, cell_id);
+ if (IS_ERR(nvmem))
+ return ERR_CAST(nvmem);
+
+ return cell;
+}
+
+#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
+/**
+ * of_nvmem_cell_get() - Get a nvmem cell from given device node and cell id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name from nvmem-cell-names property.
+ *
+ * Return: Will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell. The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+ const char *name)
+{
+ struct device_node *cell_np, *nvmem_np;
+ struct nvmem_cell *cell;
+ struct nvmem_device *nvmem;
+ const __be32 *addr;
+ int rval, len, index;
+
+ index = of_property_match_string(np, "nvmem-cell-names", name);
+
+ cell_np = of_parse_phandle(np, "nvmem-cells", index);
+ if (!cell_np)
+ return ERR_PTR(-EINVAL);
+
+ nvmem_np = of_get_next_parent(cell_np);
+ if (!nvmem_np)
+ return ERR_PTR(-EINVAL);
+
+ nvmem = __nvmem_device_get(nvmem_np, NULL, NULL);
+ if (IS_ERR(nvmem))
+ return ERR_CAST(nvmem);
+
+ addr = of_get_property(cell_np, "reg", &len);
+ if (!addr || (len < 2 * sizeof(u32))) {
+ dev_err(&nvmem->dev, "nvmem: invalid reg on %s\n",
+ cell_np->full_name);
+ rval = -EINVAL;
+ goto err_mem;
+ }
+
+ cell = kzalloc(sizeof(*cell), GFP_KERNEL);
+ if (!cell) {
+ rval = -ENOMEM;
+ goto err_mem;
+ }
+
+ cell->nvmem = nvmem;
+ cell->offset = be32_to_cpup(addr++);
+ cell->bytes = be32_to_cpup(addr);
+ cell->name = cell_np->name;
+
+ addr = of_get_property(cell_np, "bits", &len);
+ if (addr && len == (2 * sizeof(u32))) {
+ cell->bit_offset = be32_to_cpup(addr++);
+ cell->nbits = be32_to_cpup(addr);
+ }
+
+ if (cell->nbits)
+ cell->bytes = DIV_ROUND_UP(cell->nbits + cell->bit_offset,
+ BITS_PER_BYTE);
+
+ if (!IS_ALIGNED(cell->offset, nvmem->stride)) {
+ dev_err(&nvmem->dev,
+ "cell %s unaligned to nvmem stride %d\n",
+ cell->name, nvmem->stride);
+ rval = -EINVAL;
+ goto err_sanity;
+ }
+
+ nvmem_cell_add(cell);
+
+ return cell;
+
+err_sanity:
+ kfree(cell);
+
+err_mem:
+ __nvmem_device_put(nvmem);
+
+ return ERR_PTR(rval);
+}
+EXPORT_SYMBOL_GPL(of_nvmem_cell_get);
+#endif
+
+/**
+ * nvmem_cell_get() - Get nvmem cell of device form a given cell name
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem cell name to get.
+ *
+ * Return: Will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell. The nvmem_cell will be freed by the
+ * nvmem_cell_put().
+ */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *cell_id)
+{
+ struct nvmem_cell *cell;
+
+ if (dev->of_node) { /* try dt first */
+ cell = of_nvmem_cell_get(dev->of_node, cell_id);
+ if (!IS_ERR(cell) || PTR_ERR(cell) == -EPROBE_DEFER)
+ return cell;
+ }
+
+ return nvmem_cell_get_from_list(cell_id);
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_get);
+
+static void devm_nvmem_cell_release(struct device *dev, void *res)
+{
+ nvmem_cell_put(*(struct nvmem_cell **)res);
+}
+
+/**
+ * devm_nvmem_cell_get() - Get nvmem cell of device form a given id
+ *
+ * @dev node: Device tree node that uses the nvmem cell
+ * @id: nvmem id in nvmem-names property.
+ *
+ * Return: Will be an ERR_PTR() on error or a valid pointer
+ * to a struct nvmem_cell. The nvmem_cell will be freed by the
+ * automatically once the device is freed.
+ */
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *id)
+{
+ struct nvmem_cell **ptr, *cell;
+
+ ptr = devres_alloc(devm_nvmem_cell_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ cell = nvmem_cell_get(dev, id);
+ if (!IS_ERR(cell)) {
+ *ptr = cell;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return cell;
+}
+EXPORT_SYMBOL_GPL(devm_nvmem_cell_get);
+
+static int devm_nvmem_cell_match(struct device *dev, void *res, void *data)
+{
+ struct nvmem_cell **c = res;
+
+ if (WARN_ON(!c || !*c))
+ return 0;
+
+ return *c == data;
+}
+
+/**
+ * devm_nvmem_cell_put() - Release previously allocated nvmem cell
+ * from devm_nvmem_cell_get.
+ *
+ * @cell: Previously allocated nvmem cell by devm_nvmem_cell_get()
+ */
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell)
+{
+ int ret;
+
+ ret = devres_release(dev, devm_nvmem_cell_release,
+ devm_nvmem_cell_match, cell);
+
+ WARN_ON(ret);
+}
+EXPORT_SYMBOL(devm_nvmem_cell_put);
+
+/**
+ * nvmem_cell_put() - Release previously allocated nvmem cell.
+ *
+ * @cell: Previously allocated nvmem cell by nvmem_cell_get()
+ */
+void nvmem_cell_put(struct nvmem_cell *cell)
+{
+ struct nvmem_device *nvmem = cell->nvmem;
+
+ __nvmem_device_put(nvmem);
+ nvmem_cell_drop(cell);
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_put);
+
+static inline void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell,
+ void *buf)
+{
+ u8 *p, *b;
+ int i, bit_offset = cell->bit_offset;
+
+ p = b = buf;
+ if (bit_offset) {
+ /* First shift */
+ *b++ >>= bit_offset;
+
+ /* setup rest of the bytes if any */
+ for (i = 1; i < cell->bytes; i++) {
+ /* Get bits from next byte and shift them towards msb */
+ *p |= *b << (BITS_PER_BYTE - bit_offset);
+
+ p = b;
+ *b++ >>= bit_offset;
+ }
+
+ /* result fits in less bytes */
+ if (cell->bytes != DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE))
+ *p-- = 0;
+ }
+ /* clear msb bits if any leftover in the last byte */
+ *p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0);
+}
+
+static int __nvmem_cell_read(struct nvmem_device *nvmem,
+ struct nvmem_cell *cell,
+ void *buf, size_t *len)
+{
+ int rc;
+
+ rc = regmap_raw_read(nvmem->regmap, cell->offset, buf, cell->bytes);
+
+ if (IS_ERR_VALUE(rc))
+ return rc;
+
+ /* shift bits in-place */
+ if (cell->bit_offset || cell->bit_offset)
+ nvmem_shift_read_buffer_in_place(cell, buf);
+
+ *len = cell->bytes;
+
+ return 0;
+}
+
+/**
+ * nvmem_cell_read() - Read a given nvmem cell
+ *
+ * @cell: nvmem cell to be read.
+ * @len: pointer to length of cell which will be populated on successful read.
+ *
+ * Return: ERR_PTR() on error or a valid pointer to a char * buffer on success.
+ * The buffer should be freed by the consumer with a kfree().
+ */
+void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
+{
+ struct nvmem_device *nvmem = cell->nvmem;
+ u8 *buf;
+ int rc;
+
+ if (!nvmem || !nvmem->regmap)
+ return ERR_PTR(-EINVAL);
+
+ buf = kzalloc(cell->bytes, GFP_KERNEL);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+ rc = __nvmem_cell_read(nvmem, cell, buf, len);
+ if (IS_ERR_VALUE(rc)) {
+ kfree(buf);
+ return ERR_PTR(rc);
+ }
+
+ return buf;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_read);
+
+static inline void *nvmem_cell_prepare_write_buffer(struct nvmem_cell *cell,
+ u8 *_buf, int len)
+{
+ struct nvmem_device *nvmem = cell->nvmem;
+ int i, rc, nbits, bit_offset = cell->bit_offset;
+ u8 v, *p, *buf, *b, pbyte, pbits;
+
+ nbits = cell->nbits;
+ buf = kzalloc(cell->bytes, GFP_KERNEL);
+ if (!buf)
+ return ERR_PTR(-ENOMEM);
+
+ memcpy(buf, _buf, len);
+ p = b = buf;
+
+ if (bit_offset) {
+ pbyte = *b;
+ *b <<= bit_offset;
+
+ /* setup the first byte with lsb bits from nvmem */
+ rc = regmap_raw_read(nvmem->regmap, cell->offset, &v, 1);
+ *b++ |= GENMASK(bit_offset - 1, 0) & v;
+
+ /* setup rest of the byte if any */
+ for (i = 1; i < cell->bytes; i++) {
+ /* Get last byte bits and shift them towards lsb */
+ pbits = pbyte >> (BITS_PER_BYTE - 1 - bit_offset);
+ pbyte = *b;
+ p = b;
+ *b <<= bit_offset;
+ *b++ |= pbits;
+ }
+ }
+
+ /* if it's not end on byte boundary */
+ if ((nbits + bit_offset) % BITS_PER_BYTE) {
+ /* setup the last byte with msb bits from nvmem */
+ rc = regmap_raw_read(nvmem->regmap,
+ cell->offset + cell->bytes - 1, &v, 1);
+ *p |= GENMASK(7, (nbits + bit_offset) % BITS_PER_BYTE) & v;
+
+ }
+
+ return buf;
+}
+
+/**
+ * nvmem_cell_write() - Write to a given nvmem cell
+ *
+ * @cell: nvmem cell to be written.
+ * @buf: Buffer to be written.
+ * @len: length of buffer to be written to nvmem cell.
+ *
+ * Return: length of bytes written or negative on failure.
+ */
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len)
+{
+ struct nvmem_device *nvmem = cell->nvmem;
+ int rc;
+
+ if (!nvmem || !nvmem->regmap || nvmem->read_only ||
+ (cell->bit_offset == 0 && len != cell->bytes))
+ return -EINVAL;
+
+ if (cell->bit_offset || cell->nbits) {
+ buf = nvmem_cell_prepare_write_buffer(cell, buf, len);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+ }
+
+ rc = regmap_raw_write(nvmem->regmap, cell->offset, buf, cell->bytes);
+
+ /* free the tmp buffer */
+ if (cell->bit_offset)
+ kfree(buf);
+
+ if (IS_ERR_VALUE(rc))
+ return rc;
+
+ return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_write);
+
+/**
+ * nvmem_device_cell_read() - Read a given nvmem device and cell
+ *
+ * @nvmem: nvmem device to read from.
+ * @info: nvmem cell info to be read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * Return: length of successful bytes read on success and negative
+ * error code on error.
+ */
+ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf)
+{
+ struct nvmem_cell cell;
+ int rc;
+ ssize_t len;
+
+ if (!nvmem || !nvmem->regmap)
+ return -EINVAL;
+
+ rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+ if (IS_ERR_VALUE(rc))
+ return rc;
+
+ rc = __nvmem_cell_read(nvmem, &cell, buf, &len);
+ if (IS_ERR_VALUE(rc))
+ return rc;
+
+ return len;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_read);
+
+/**
+ * nvmem_device_cell_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @info: nvmem cell info to be written
+ * @buf: buffer to be written to cell.
+ *
+ * Return: length of bytes written or negative error code on failure.
+ * */
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf)
+{
+ struct nvmem_cell cell;
+ int rc;
+
+ if (!nvmem || !nvmem->regmap)
+ return -EINVAL;
+
+ rc = nvmem_cell_info_to_nvmem_cell(nvmem, info, &cell);
+ if (IS_ERR_VALUE(rc))
+ return rc;
+
+ return nvmem_cell_write(&cell, buf, cell.bytes);
+}
+EXPORT_SYMBOL_GPL(nvmem_device_cell_write);
+
+/**
+ * nvmem_device_read() - Read from a given nvmem device
+ *
+ * @nvmem: nvmem device to read from.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to read.
+ * @buf: buffer pointer which will be populated on successful read.
+ *
+ * Return: length of successful bytes read on success and negative
+ * error code on error.
+ */
+int nvmem_device_read(struct nvmem_device *nvmem,
+ unsigned int offset,
+ size_t bytes, void *buf)
+{
+ int rc;
+
+ if (!nvmem || !nvmem->regmap)
+ return -EINVAL;
+
+ rc = regmap_raw_read(nvmem->regmap, offset, buf, bytes);
+
+ if (IS_ERR_VALUE(rc))
+ return rc;
+
+ return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_read);
+
+/**
+ * nvmem_device_write() - Write cell to a given nvmem device
+ *
+ * @nvmem: nvmem device to be written to.
+ * @offset: offset in nvmem device.
+ * @bytes: number of bytes to write.
+ * @buf: buffer to be written.
+ *
+ * Return: length of bytes written or negative error code on failure.
+ * */
+int nvmem_device_write(struct nvmem_device *nvmem,
+ unsigned int offset,
+ size_t bytes, void *buf)
+{
+ int rc;
+
+ if (!nvmem || !nvmem->regmap)
+ return -EINVAL;
+
+ rc = regmap_raw_write(nvmem->regmap, offset, buf, bytes);
+
+ if (IS_ERR_VALUE(rc))
+ return rc;
+
+
+ return bytes;
+}
+EXPORT_SYMBOL_GPL(nvmem_device_write);
+
+static int __init nvmem_init(void)
+{
+ return bus_register(&nvmem_bus_type);
+}
+
+static void __exit nvmem_exit(void)
+{
+ bus_unregister(&nvmem_bus_type);
+}
+
+subsys_initcall(nvmem_init);
+module_exit(nvmem_exit);
+
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org");
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com");
+MODULE_DESCRIPTION("nvmem Driver Core");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvmem/qfprom.c b/drivers/nvmem/qfprom.c
new file mode 100644
index 0000000..afb67e7
--- /dev/null
+++ b/drivers/nvmem/qfprom.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+static struct regmap_config qfprom_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .reg_stride = 1,
+};
+
+static struct nvmem_config econfig = {
+ .name = "qfprom",
+ .owner = THIS_MODULE,
+};
+
+static int qfprom_remove(struct platform_device *pdev)
+{
+ struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+ return nvmem_unregister(nvmem);
+}
+
+static int qfprom_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct nvmem_device *nvmem;
+ struct regmap *regmap;
+ void __iomem *base;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ qfprom_regmap_config.max_register = resource_size(res) - 1;
+
+ regmap = devm_regmap_init_mmio(dev, base, &qfprom_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "regmap init failed\n");
+ return PTR_ERR(regmap);
+ }
+ econfig.dev = dev;
+ nvmem = nvmem_register(&econfig);
+ if (IS_ERR(nvmem))
+ return PTR_ERR(nvmem);
+
+ platform_set_drvdata(pdev, nvmem);
+
+ return 0;
+}
+
+static const struct of_device_id qfprom_of_match[] = {
+ { .compatible = "qcom,qfprom",},
+ {/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, qfprom_of_match);
+
+static struct platform_driver qfprom_driver = {
+ .probe = qfprom_probe,
+ .remove = qfprom_remove,
+ .driver = {
+ .name = "qcom,qfprom",
+ .of_match_table = qfprom_of_match,
+ },
+};
+module_platform_driver(qfprom_driver);
+MODULE_AUTHOR("Srinivas Kandagatla <srinivas.kandagatla@linaro.org>");
+MODULE_DESCRIPTION("Qualcomm QFPROM driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c
new file mode 100644
index 0000000..14777dd
--- /dev/null
+++ b/drivers/nvmem/sunxi_sid.c
@@ -0,0 +1,171 @@
+/*
+ * Allwinner sunXi SoCs Security ID support.
+ *
+ * Copyright (c) 2013 Oliver Schinagl <oliver@schinagl.nl>
+ * Copyright (C) 2014 Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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/device.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/nvmem-provider.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+
+static struct nvmem_config econfig = {
+ .name = "sunxi-sid",
+ .read_only = true,
+ .owner = THIS_MODULE,
+};
+
+struct sunxi_sid {
+ void __iomem *base;
+};
+
+/* We read the entire key, due to a 32 bit read alignment requirement. Since we
+ * want to return the requested byte, this results in somewhat slower code and
+ * uses 4 times more reads as needed but keeps code simpler. Since the SID is
+ * only very rarely probed, this is not really an issue.
+ */
+static u8 sunxi_sid_read_byte(const struct sunxi_sid *sid,
+ const unsigned int offset)
+{
+ u32 sid_key;
+
+ sid_key = ioread32be(sid->base + round_down(offset, 4));
+ sid_key >>= (offset % 4) * 8;
+
+ return sid_key; /* Only return the last byte */
+}
+
+static int sunxi_sid_read(void *context,
+ const void *reg, size_t reg_size,
+ void *val, size_t val_size)
+{
+ struct sunxi_sid *sid = context;
+ unsigned int offset = *(u32 *)reg;
+ u8 *buf = val;
+
+ while (val_size) {
+ *buf++ = sunxi_sid_read_byte(sid, offset);
+ val_size--;
+ offset++;
+ }
+
+ return 0;
+}
+
+static int sunxi_sid_write(void *context, const void *data, size_t count)
+{
+ /* Unimplemented, dummy to keep regmap core happy */
+ return 0;
+}
+
+static struct regmap_bus sunxi_sid_bus = {
+ .read = sunxi_sid_read,
+ .write = sunxi_sid_write,
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+static bool sunxi_sid_writeable_reg(struct device *dev, unsigned int reg)
+{
+ return false;
+}
+
+static struct regmap_config sunxi_sid_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 8,
+ .reg_stride = 1,
+ .writeable_reg = sunxi_sid_writeable_reg,
+};
+
+static int sunxi_sid_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct nvmem_device *nvmem;
+ struct regmap *regmap;
+ struct sunxi_sid *sid;
+ int i, size;
+ char *randomness;
+
+ sid = devm_kzalloc(dev, sizeof(*sid), GFP_KERNEL);
+ if (!sid)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ sid->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(sid->base))
+ return PTR_ERR(sid->base);
+
+ size = resource_size(res) - 1;
+ sunxi_sid_regmap_config.max_register = size;
+
+ regmap = devm_regmap_init(dev, &sunxi_sid_bus, sid,
+ &sunxi_sid_regmap_config);
+ if (IS_ERR(regmap)) {
+ dev_err(dev, "regmap init failed\n");
+ return PTR_ERR(regmap);
+ }
+
+ econfig.dev = dev;
+ nvmem = nvmem_register(&econfig);
+ if (IS_ERR(nvmem))
+ return PTR_ERR(nvmem);
+
+ randomness = kzalloc(sizeof(u8) * size, GFP_KERNEL);
+ for (i = 0; i < size; i++)
+ randomness[i] = sunxi_sid_read_byte(sid, i);
+
+ add_device_randomness(randomness, size);
+ kfree(randomness);
+
+ platform_set_drvdata(pdev, nvmem);
+
+ return 0;
+}
+
+static int sunxi_sid_remove(struct platform_device *pdev)
+{
+ struct nvmem_device *nvmem = platform_get_drvdata(pdev);
+
+ return nvmem_unregister(nvmem);
+}
+
+static const struct of_device_id sunxi_sid_of_match[] = {
+ { .compatible = "allwinner,sun4i-a10-sid" },
+ { .compatible = "allwinner,sun7i-a20-sid" },
+ {/* sentinel */},
+};
+MODULE_DEVICE_TABLE(of, sunxi_sid_of_match);
+
+static struct platform_driver sunxi_sid_driver = {
+ .probe = sunxi_sid_probe,
+ .remove = sunxi_sid_remove,
+ .driver = {
+ .name = "eeprom-sunxi-sid",
+ .of_match_table = sunxi_sid_of_match,
+ },
+};
+module_platform_driver(sunxi_sid_driver);
+
+MODULE_AUTHOR("Oliver Schinagl <oliver@schinagl.nl>");
+MODULE_DESCRIPTION("Allwinner sunxi security id driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 8df1b17..59bb855 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -47,7 +47,7 @@
config OF_ADDRESS
def_bool y
- depends on !SPARC
+ depends on !SPARC && HAS_IOMEM
select OF_ADDRESS_PCI if PCI
config OF_ADDRESS_PCI
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 1801634..9f71770b6 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -979,7 +979,6 @@
.remove = unittest_remove,
.driver = {
.name = "unittest",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(unittest_match),
},
};
@@ -1666,7 +1665,6 @@
static struct i2c_driver unittest_i2c_dev_driver = {
.driver = {
.name = "unittest-i2c-dev",
- .owner = THIS_MODULE,
},
.probe = unittest_i2c_dev_probe,
.remove = unittest_i2c_dev_remove,
@@ -1761,7 +1759,6 @@
static struct i2c_driver unittest_i2c_mux_driver = {
.driver = {
.name = "unittest-i2c-mux",
- .owner = THIS_MODULE,
},
.probe = unittest_i2c_mux_probe,
.remove = unittest_i2c_mux_remove,
diff --git a/drivers/parport/share.c b/drivers/parport/share.c
index 8067f54..5ce5ef2 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -891,8 +891,10 @@
par_dev->dev.release = free_pardevice;
par_dev->devmodel = true;
ret = device_register(&par_dev->dev);
- if (ret)
- goto err_put_dev;
+ if (ret) {
+ put_device(&par_dev->dev);
+ goto err_put_port;
+ }
/* Chain this onto the list */
par_dev->prev = NULL;
@@ -907,7 +909,8 @@
spin_unlock(&port->physport->pardevice_lock);
pr_debug("%s: cannot grant exclusive access for device %s\n",
port->name, name);
- goto err_put_dev;
+ device_unregister(&par_dev->dev);
+ goto err_put_port;
}
port->flags |= PARPORT_FLAG_EXCL;
}
@@ -938,8 +941,6 @@
return par_dev;
-err_put_dev:
- put_device(&par_dev->dev);
err_free_devname:
kfree(devname);
err_free_par_dev:
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 73de4ef..944f500 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -2,7 +2,7 @@
# PCI configuration
#
config PCI_BUS_ADDR_T_64BIT
- def_bool y if (ARCH_DMA_ADDR_T_64BIT || 64BIT)
+ def_bool y if (ARCH_DMA_ADDR_T_64BIT || (64BIT && !PARISC))
depends on PCI
config PCI_MSI
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index cefd636..f6ae0d0 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -997,7 +997,12 @@
else if (type == PCI_EXP_TYPE_UPSTREAM ||
type == PCI_EXP_TYPE_DOWNSTREAM) {
parent = pci_upstream_bridge(pdev);
- if (!parent->has_secondary_link)
+
+ /*
+ * Usually there's an upstream device (Root Port or Switch
+ * Downstream Port), but we can't assume one exists.
+ */
+ if (parent && !parent->has_secondary_link)
pdev->has_secondary_link = 1;
}
}
@@ -1103,7 +1108,7 @@
#define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
-static void pci_msi_setup_pci_dev(struct pci_dev *dev)
+void pci_msi_setup_pci_dev(struct pci_dev *dev)
{
/*
* Disable the MSI hardware to avoid screaming interrupts
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index c0e6ede..47da573 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -54,8 +54,20 @@
Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung S5P
and EXYNOS SoCs.
+config PHY_LPC18XX_USB_OTG
+ tristate "NXP LPC18xx/43xx SoC USB OTG PHY driver"
+ depends on OF && (ARCH_LPC18XX || COMPILE_TEST)
+ depends on MFD_SYSCON
+ select GENERIC_PHY
+ help
+ Enable this to support NXP LPC18xx/43xx internal USB OTG PHY.
+
+ This driver is need for USB0 support on LPC18xx/43xx and takes
+ care of enabling and clock setup.
+
config PHY_PXA_28NM_HSIC
tristate "Marvell USB HSIC 28nm PHY Driver"
+ depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support Marvell USB HSIC PHY driver for Marvell
@@ -66,6 +78,7 @@
config PHY_PXA_28NM_USB2
tristate "Marvell USB 2.0 28nm PHY Driver"
+ depends on HAS_IOMEM
select GENERIC_PHY
help
Enable this to support Marvell USB 2.0 PHY driver for Marvell
@@ -197,6 +210,8 @@
tristate "Allwinner sunxi SoC USB PHY driver"
depends on ARCH_SUNXI && HAS_IOMEM && OF
depends on RESET_CONTROLLER
+ depends on EXTCON
+ depends on POWER_SUPPLY
select GENERIC_PHY
help
Enable this to support the transceiver that is part of Allwinner
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index f344e1b..a5b18c1 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -10,6 +10,7 @@
obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
+obj-$(CONFIG_PHY_LPC18XX_USB_OTG) += phy-lpc18xx-usb-otg.o
obj-$(CONFIG_PHY_PXA_28NM_USB2) += phy-pxa-28nm-usb2.o
obj-$(CONFIG_PHY_PXA_28NM_HSIC) += phy-pxa-28nm-hsic.o
obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o
diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/phy-armada375-usb2.c
index 8ccc395..1a3db28 100644
--- a/drivers/phy/phy-armada375-usb2.c
+++ b/drivers/phy/phy-armada375-usb2.c
@@ -51,7 +51,7 @@
return 0;
}
-static struct phy_ops armada375_usb_phy_ops = {
+static const struct phy_ops armada375_usb_phy_ops = {
.init = armada375_usb_phy_init,
.owner = THIS_MODULE,
};
@@ -149,7 +149,6 @@
.driver = {
.of_match_table = of_usb_cluster_table,
.name = "armada-375-usb-cluster",
- .owner = THIS_MODULE,
}
};
module_platform_driver(armada375_usb_phy_driver);
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c
index ef2dc1a..7b67fe4 100644
--- a/drivers/phy/phy-bcm-kona-usb2.c
+++ b/drivers/phy/phy-bcm-kona-usb2.c
@@ -91,7 +91,7 @@
return 0;
}
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
.init = bcm_kona_usb_phy_init,
.power_on = bcm_kona_usb_phy_power_on,
.power_off = bcm_kona_usb_phy_power_off,
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
index 6f3e06d..0062027 100644
--- a/drivers/phy/phy-berlin-sata.c
+++ b/drivers/phy/phy-berlin-sata.c
@@ -176,7 +176,7 @@
return priv->phys[i]->phy;
}
-static struct phy_ops phy_berlin_sata_ops = {
+static const struct phy_ops phy_berlin_sata_ops = {
.power_on = phy_berlin_sata_power_on,
.power_off = phy_berlin_sata_power_off,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c
index c6fc95b..797ba17 100644
--- a/drivers/phy/phy-berlin-usb.c
+++ b/drivers/phy/phy-berlin-usb.c
@@ -105,9 +105,9 @@
static const u32 phy_berlin_pll_dividers[] = {
/* Berlin 2 */
- CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
- /* Berlin 2CD */
CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55),
+ /* Berlin 2CD/Q */
+ CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
};
struct phy_berlin_usb_priv {
@@ -147,12 +147,12 @@
return 0;
}
-static struct phy_ops phy_berlin_usb_ops = {
+static const struct phy_ops phy_berlin_usb_ops = {
.power_on = phy_berlin_usb_power_on,
.owner = THIS_MODULE,
};
-static const struct of_device_id phy_berlin_sata_of_match[] = {
+static const struct of_device_id phy_berlin_usb_of_match[] = {
{
.compatible = "marvell,berlin2-usb-phy",
.data = &phy_berlin_pll_dividers[0],
@@ -163,12 +163,12 @@
},
{ },
};
-MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
+MODULE_DEVICE_TABLE(of, phy_berlin_usb_of_match);
static int phy_berlin_usb_probe(struct platform_device *pdev)
{
const struct of_device_id *match =
- of_match_device(phy_berlin_sata_of_match, &pdev->dev);
+ of_match_device(phy_berlin_usb_of_match, &pdev->dev);
struct phy_berlin_usb_priv *priv;
struct resource *res;
struct phy *phy;
@@ -207,9 +207,8 @@
.probe = phy_berlin_usb_probe,
.driver = {
.name = "phy-berlin-usb",
- .owner = THIS_MODULE,
- .of_match_table = phy_berlin_sata_of_match,
- },
+ .of_match_table = phy_berlin_usb_of_match,
+ },
};
module_platform_driver(phy_berlin_usb_driver);
diff --git a/drivers/phy/phy-brcmstb-sata.c b/drivers/phy/phy-brcmstb-sata.c
index b7e303d..8a2cb16 100644
--- a/drivers/phy/phy-brcmstb-sata.c
+++ b/drivers/phy/phy-brcmstb-sata.c
@@ -122,7 +122,7 @@
return 0;
}
-static struct phy_ops phy_ops_28nm = {
+static const struct phy_ops phy_ops_28nm = {
.init = brcm_sata_phy_init,
.owner = THIS_MODULE,
};
diff --git a/drivers/phy/phy-dm816x-usb.c b/drivers/phy/phy-dm816x-usb.c
index 7b42555..b4bbef6 100644
--- a/drivers/phy/phy-dm816x-usb.c
+++ b/drivers/phy/phy-dm816x-usb.c
@@ -113,7 +113,7 @@
return 0;
}
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
.init = dm816x_usb_phy_init,
.owner = THIS_MODULE,
};
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
index 179cbf9..34b0615 100644
--- a/drivers/phy/phy-exynos-dp-video.c
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -48,7 +48,7 @@
EXYNOS5_PHY_ENABLE, 0);
}
-static struct phy_ops exynos_dp_video_phy_ops = {
+static const struct phy_ops exynos_dp_video_phy_ops = {
.power_on = exynos_dp_video_phy_power_on,
.power_off = exynos_dp_video_phy_power_off,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index df7519a..2a54cab 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -124,7 +124,7 @@
return state->phys[args->args[0]].phy;
}
-static struct phy_ops exynos_mipi_video_phy_ops = {
+static const struct phy_ops exynos_mipi_video_phy_ops = {
.power_on = exynos_mipi_video_phy_power_on,
.power_off = exynos_mipi_video_phy_power_off,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index d72ef15..20696f5 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -537,7 +537,7 @@
return phy_drd->phys[args->args[0]].phy;
}
-static struct phy_ops exynos5_usbdrd_phy_ops = {
+static const struct phy_ops exynos5_usbdrd_phy_ops = {
.init = exynos5_usbdrd_phy_init,
.exit = exynos5_usbdrd_phy_exit,
.power_on = exynos5_usbdrd_phy_power_on,
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c
index bc858cc..60e13af 100644
--- a/drivers/phy/phy-exynos5250-sata.c
+++ b/drivers/phy/phy-exynos5250-sata.c
@@ -154,7 +154,7 @@
return ret;
}
-static struct phy_ops exynos_sata_phy_ops = {
+static const struct phy_ops exynos_sata_phy_ops = {
.init = exynos_sata_phy_init,
.power_on = exynos_sata_phy_power_on,
.power_off = exynos_sata_phy_power_off,
diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c
index d6b2265..e5ab3aa 100644
--- a/drivers/phy/phy-hix5hd2-sata.c
+++ b/drivers/phy/phy-hix5hd2-sata.c
@@ -129,7 +129,7 @@
return 0;
}
-static struct phy_ops hix5hd2_sata_phy_ops = {
+static const struct phy_ops hix5hd2_sata_phy_ops = {
.init = hix5hd2_sata_phy_init,
.owner = THIS_MODULE,
};
diff --git a/drivers/phy/phy-lpc18xx-usb-otg.c b/drivers/phy/phy-lpc18xx-usb-otg.c
new file mode 100644
index 0000000..3b7a71e
--- /dev/null
+++ b/drivers/phy/phy-lpc18xx-usb-otg.c
@@ -0,0 +1,143 @@
+/*
+ * PHY driver for NXP LPC18xx/43xx internal USB OTG PHY
+ *
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+/* USB OTG PHY register offset and bit in CREG */
+#define LPC18XX_CREG_CREG0 0x004
+#define LPC18XX_CREG_CREG0_USB0PHY BIT(5)
+
+struct lpc18xx_usb_otg_phy {
+ struct phy *phy;
+ struct clk *clk;
+ struct regmap *reg;
+};
+
+static int lpc18xx_usb_otg_phy_init(struct phy *phy)
+{
+ struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+ int ret;
+
+ /* The PHY must be clocked at 480 MHz */
+ ret = clk_set_rate(lpc->clk, 480000000);
+ if (ret)
+ return ret;
+
+ return clk_prepare(lpc->clk);
+}
+
+static int lpc18xx_usb_otg_phy_exit(struct phy *phy)
+{
+ struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+
+ clk_unprepare(lpc->clk);
+
+ return 0;
+}
+
+static int lpc18xx_usb_otg_phy_power_on(struct phy *phy)
+{
+ struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+ int ret;
+
+ ret = clk_enable(lpc->clk);
+ if (ret)
+ return ret;
+
+ /* The bit in CREG is cleared to enable the PHY */
+ return regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0,
+ LPC18XX_CREG_CREG0_USB0PHY, 0);
+}
+
+static int lpc18xx_usb_otg_phy_power_off(struct phy *phy)
+{
+ struct lpc18xx_usb_otg_phy *lpc = phy_get_drvdata(phy);
+ int ret;
+
+ ret = regmap_update_bits(lpc->reg, LPC18XX_CREG_CREG0,
+ LPC18XX_CREG_CREG0_USB0PHY,
+ LPC18XX_CREG_CREG0_USB0PHY);
+ if (ret)
+ return ret;
+
+ clk_disable(lpc->clk);
+
+ return 0;
+}
+
+static const struct phy_ops lpc18xx_usb_otg_phy_ops = {
+ .init = lpc18xx_usb_otg_phy_init,
+ .exit = lpc18xx_usb_otg_phy_exit,
+ .power_on = lpc18xx_usb_otg_phy_power_on,
+ .power_off = lpc18xx_usb_otg_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int lpc18xx_usb_otg_phy_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct lpc18xx_usb_otg_phy *lpc;
+
+ lpc = devm_kzalloc(&pdev->dev, sizeof(*lpc), GFP_KERNEL);
+ if (!lpc)
+ return -ENOMEM;
+
+ lpc->reg = syscon_node_to_regmap(pdev->dev.of_node->parent);
+ if (IS_ERR(lpc->reg)) {
+ dev_err(&pdev->dev, "failed to get syscon\n");
+ return PTR_ERR(lpc->reg);
+ }
+
+ lpc->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(lpc->clk)) {
+ dev_err(&pdev->dev, "failed to get clock\n");
+ return PTR_ERR(lpc->clk);
+ }
+
+ lpc->phy = devm_phy_create(&pdev->dev, NULL, &lpc18xx_usb_otg_phy_ops);
+ if (IS_ERR(lpc->phy)) {
+ dev_err(&pdev->dev, "failed to create PHY\n");
+ return PTR_ERR(lpc->phy);
+ }
+
+ phy_set_drvdata(lpc->phy, lpc);
+
+ phy_provider = devm_of_phy_provider_register(&pdev->dev,
+ of_phy_simple_xlate);
+
+ return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id lpc18xx_usb_otg_phy_match[] = {
+ { .compatible = "nxp,lpc1850-usb-otg-phy" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lpc18xx_usb_otg_phy_match);
+
+static struct platform_driver lpc18xx_usb_otg_phy_driver = {
+ .probe = lpc18xx_usb_otg_phy_probe,
+ .driver = {
+ .name = "lpc18xx-usb-otg-phy",
+ .of_match_table = lpc18xx_usb_otg_phy_match,
+ },
+};
+module_platform_driver(lpc18xx_usb_otg_phy_driver);
+
+MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
+MODULE_DESCRIPTION("NXP LPC18xx/43xx USB OTG PHY driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
index 5e257ef..c47b56b 100644
--- a/drivers/phy/phy-miphy28lp.c
+++ b/drivers/phy/phy-miphy28lp.c
@@ -1132,7 +1132,7 @@
return miphy_phy->phy;
}
-static struct phy_ops miphy28lp_ops = {
+static const struct phy_ops miphy28lp_ops = {
.init = miphy28lp_init,
.owner = THIS_MODULE,
};
@@ -1268,7 +1268,6 @@
.probe = miphy28lp_probe,
.driver = {
.name = "miphy28lp-phy",
- .owner = THIS_MODULE,
.of_match_table = miphy28lp_of_match,
}
};
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
index 0ff354d..00a686a 100644
--- a/drivers/phy/phy-miphy365x.c
+++ b/drivers/phy/phy-miphy365x.c
@@ -510,7 +510,7 @@
return miphy_phy->phy;
}
-static struct phy_ops miphy365x_ops = {
+static const struct phy_ops miphy365x_ops = {
.init = miphy365x_init,
.owner = THIS_MODULE,
};
diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c
index 03b94f9..768ce92 100644
--- a/drivers/phy/phy-mvebu-sata.c
+++ b/drivers/phy/phy-mvebu-sata.c
@@ -75,7 +75,7 @@
return 0;
}
-static struct phy_ops phy_mvebu_sata_ops = {
+static const struct phy_ops phy_mvebu_sata_ops = {
.power_on = phy_mvebu_sata_power_on,
.power_off = phy_mvebu_sata_power_off,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index c1a4686..0fe8058 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -137,7 +137,7 @@
return 0;
}
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
.init = omap_usb_init,
.power_on = omap_usb_power_on,
.power_off = omap_usb_power_off,
diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c
index 4b243f7..69ce2af 100644
--- a/drivers/phy/phy-qcom-apq8064-sata.c
+++ b/drivers/phy/phy-qcom-apq8064-sata.c
@@ -204,7 +204,7 @@
return 0;
}
-static struct phy_ops qcom_apq8064_sata_phy_ops = {
+static const struct phy_ops qcom_apq8064_sata_phy_ops = {
.init = qcom_apq8064_sata_phy_init,
.exit = qcom_apq8064_sata_phy_exit,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c
index 6f2fe26..0ad127c 100644
--- a/drivers/phy/phy-qcom-ipq806x-sata.c
+++ b/drivers/phy/phy-qcom-ipq806x-sata.c
@@ -126,7 +126,7 @@
return 0;
}
-static struct phy_ops qcom_ipq806x_sata_phy_ops = {
+static const struct phy_ops qcom_ipq806x_sata_phy_ops = {
.init = qcom_ipq806x_sata_phy_init,
.exit = qcom_ipq806x_sata_phy_exit,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
index 591a391..2bd5ce4 100644
--- a/drivers/phy/phy-qcom-ufs-i.h
+++ b/drivers/phy/phy-qcom-ufs-i.h
@@ -150,7 +150,7 @@
struct ufs_qcom_phy *ufs_qcom_phy);
struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
struct ufs_qcom_phy *common_cfg,
- struct phy_ops *ufs_qcom_phy_gen_ops,
+ const struct phy_ops *ufs_qcom_phy_gen_ops,
struct ufs_qcom_phy_specific_ops *phy_spec_ops);
int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A,
diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c
index f5fc50a..56631e7 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c
+++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c
@@ -115,7 +115,7 @@
return err;
}
-static struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
+static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
.init = ufs_qcom_phy_qmp_14nm_init,
.exit = ufs_qcom_phy_exit,
.power_on = ufs_qcom_phy_power_on,
@@ -191,7 +191,6 @@
.driver = {
.of_match_table = ufs_qcom_phy_qmp_14nm_of_match,
.name = "ufs_qcom_phy_qmp_14nm",
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
index 8332f96..b16ea77 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c
+++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c
@@ -171,7 +171,7 @@
return err;
}
-static struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = {
+static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = {
.init = ufs_qcom_phy_qmp_20nm_init,
.exit = ufs_qcom_phy_exit,
.power_on = ufs_qcom_phy_power_on,
@@ -247,7 +247,6 @@
.driver = {
.of_match_table = ufs_qcom_phy_qmp_20nm_of_match,
.name = "ufs_qcom_phy_qmp_20nm",
- .owner = THIS_MODULE,
},
};
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
index f9c618f..49a1ed0 100644
--- a/drivers/phy/phy-qcom-ufs.c
+++ b/drivers/phy/phy-qcom-ufs.c
@@ -77,7 +77,7 @@
struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
struct ufs_qcom_phy *common_cfg,
- struct phy_ops *ufs_qcom_phy_gen_ops,
+ const struct phy_ops *ufs_qcom_phy_gen_ops,
struct ufs_qcom_phy_specific_ops *phy_spec_ops)
{
int err;
diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c
index 39d9b29..6e0d9fa 100644
--- a/drivers/phy/phy-rcar-gen2.c
+++ b/drivers/phy/phy-rcar-gen2.c
@@ -184,7 +184,7 @@
return 0;
}
-static struct phy_ops rcar_gen2_phy_ops = {
+static const struct phy_ops rcar_gen2_phy_ops = {
.init = rcar_gen2_phy_init,
.exit = rcar_gen2_phy_exit,
.power_on = rcar_gen2_phy_power_on,
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
index 7d4c336..5a5c073 100644
--- a/drivers/phy/phy-rockchip-usb.c
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -84,7 +84,7 @@
return 0;
}
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
.power_on = rockchip_usb_phy_power_on,
.power_off = rockchip_usb_phy_power_off,
.owner = THIS_MODULE,
@@ -146,7 +146,6 @@
.probe = rockchip_usb_phy_probe,
.driver = {
.name = "rockchip-usb-phy",
- .owner = THIS_MODULE,
.of_match_table = rockchip_usb_phy_dt_ids,
},
};
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index 55b6994..f278a9c 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -71,7 +71,7 @@
return 0;
}
-static struct phy_ops samsung_usb2_phy_ops = {
+static const struct phy_ops samsung_usb2_phy_ops = {
.power_on = samsung_usb2_phy_power_on,
.power_off = samsung_usb2_phy_power_off,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/phy-spear1310-miphy.c
index 45d0005..ed67e98 100644
--- a/drivers/phy/phy-spear1310-miphy.c
+++ b/drivers/phy/phy-spear1310-miphy.c
@@ -179,7 +179,7 @@
};
MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match);
-static struct phy_ops spear1310_miphy_ops = {
+static const struct phy_ops spear1310_miphy_ops = {
.init = spear1310_miphy_init,
.exit = spear1310_miphy_exit,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/phy-spear1340-miphy.c
index 494240d..97280c0 100644
--- a/drivers/phy/phy-spear1340-miphy.c
+++ b/drivers/phy/phy-spear1340-miphy.c
@@ -189,7 +189,7 @@
};
MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match);
-static struct phy_ops spear1340_miphy_ops = {
+static const struct phy_ops spear1340_miphy_ops = {
.init = spear1340_miphy_init,
.exit = spear1340_miphy_exit,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c
index c093b47..0ac7463 100644
--- a/drivers/phy/phy-stih41x-usb.c
+++ b/drivers/phy/phy-stih41x-usb.c
@@ -112,7 +112,7 @@
return 0;
}
-static struct phy_ops stih41x_usb_phy_ops = {
+static const struct phy_ops stih41x_usb_phy_ops = {
.init = stih41x_usb_phy_init,
.power_on = stih41x_usb_phy_power_on,
.power_off = stih41x_usb_phy_power_off,
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index e17c539..731b395 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -1,7 +1,7 @@
/*
* Allwinner sun4i USB phy driver
*
- * Copyright (C) 2014 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (C) 2014-2015 Hans de Goede <hdegoede@redhat.com>
*
* Based on code from
* Allwinner Technology Co., Ltd. <www.allwinnertech.com>
@@ -22,23 +22,30 @@
*/
#include <linux/clk.h>
+#include <linux/delay.h>
#include <linux/err.h>
+#include <linux/extcon.h>
#include <linux/io.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_gpio.h>
#include <linux/phy/phy.h>
#include <linux/phy/phy-sun4i-usb.h>
#include <linux/platform_device.h>
+#include <linux/power_supply.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
+#include <linux/workqueue.h>
#define REG_ISCR 0x00
-#define REG_PHYCTL 0x04
+#define REG_PHYCTL_A10 0x04
#define REG_PHYBIST 0x08
#define REG_PHYTUNE 0x0c
+#define REG_PHYCTL_A33 0x10
#define PHYCTL_DATA BIT(7)
@@ -47,6 +54,17 @@
#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8)
#define SUNXI_ULPI_BYPASS_EN BIT(0)
+/* ISCR, Interface Status and Control bits */
+#define ISCR_ID_PULLUP_EN (1 << 17)
+#define ISCR_DPDM_PULLUP_EN (1 << 16)
+/* sunxi has the phy id/vbus pins not connected, so we use the force bits */
+#define ISCR_FORCE_ID_MASK (3 << 14)
+#define ISCR_FORCE_ID_LOW (2 << 14)
+#define ISCR_FORCE_ID_HIGH (3 << 14)
+#define ISCR_FORCE_VBUS_MASK (3 << 12)
+#define ISCR_FORCE_VBUS_LOW (2 << 12)
+#define ISCR_FORCE_VBUS_HIGH (3 << 12)
+
/* Common Control Bits for Both PHYs */
#define PHY_PLL_BW 0x03
#define PHY_RES45_CAL_EN 0x0c
@@ -63,60 +81,124 @@
#define MAX_PHYS 3
+/*
+ * Note do not raise the debounce time, we must report Vusb high within 100ms
+ * otherwise we get Vbus errors
+ */
+#define DEBOUNCE_TIME msecs_to_jiffies(50)
+#define POLL_TIME msecs_to_jiffies(250)
+
struct sun4i_usb_phy_data {
void __iomem *base;
struct mutex mutex;
int num_phys;
u32 disc_thresh;
+ bool has_a33_phyctl;
struct sun4i_usb_phy {
struct phy *phy;
void __iomem *pmu;
struct regulator *vbus;
struct reset_control *reset;
struct clk *clk;
+ bool regulator_on;
int index;
} phys[MAX_PHYS];
+ /* phy0 / otg related variables */
+ struct extcon_dev *extcon;
+ bool phy0_init;
+ bool phy0_poll;
+ struct gpio_desc *id_det_gpio;
+ struct gpio_desc *vbus_det_gpio;
+ struct power_supply *vbus_power_supply;
+ struct notifier_block vbus_power_nb;
+ bool vbus_power_nb_registered;
+ int id_det_irq;
+ int vbus_det_irq;
+ int id_det;
+ int vbus_det;
+ struct delayed_work detect;
};
#define to_sun4i_usb_phy_data(phy) \
container_of((phy), struct sun4i_usb_phy_data, phys[(phy)->index])
+static void sun4i_usb_phy0_update_iscr(struct phy *_phy, u32 clr, u32 set)
+{
+ struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+ u32 iscr;
+
+ iscr = readl(data->base + REG_ISCR);
+ iscr &= ~clr;
+ iscr |= set;
+ writel(iscr, data->base + REG_ISCR);
+}
+
+static void sun4i_usb_phy0_set_id_detect(struct phy *phy, u32 val)
+{
+ if (val)
+ val = ISCR_FORCE_ID_HIGH;
+ else
+ val = ISCR_FORCE_ID_LOW;
+
+ sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_ID_MASK, val);
+}
+
+static void sun4i_usb_phy0_set_vbus_detect(struct phy *phy, u32 val)
+{
+ if (val)
+ val = ISCR_FORCE_VBUS_HIGH;
+ else
+ val = ISCR_FORCE_VBUS_LOW;
+
+ sun4i_usb_phy0_update_iscr(phy, ISCR_FORCE_VBUS_MASK, val);
+}
+
static void sun4i_usb_phy_write(struct sun4i_usb_phy *phy, u32 addr, u32 data,
int len)
{
struct sun4i_usb_phy_data *phy_data = to_sun4i_usb_phy_data(phy);
u32 temp, usbc_bit = BIT(phy->index * 2);
+ void *phyctl;
int i;
mutex_lock(&phy_data->mutex);
+ if (phy_data->has_a33_phyctl) {
+ phyctl = phy_data->base + REG_PHYCTL_A33;
+ /* A33 needs us to set phyctl to 0 explicitly */
+ writel(0, phyctl);
+ } else {
+ phyctl = phy_data->base + REG_PHYCTL_A10;
+ }
+
for (i = 0; i < len; i++) {
- temp = readl(phy_data->base + REG_PHYCTL);
+ temp = readl(phyctl);
/* clear the address portion */
temp &= ~(0xff << 8);
/* set the address */
temp |= ((addr + i) << 8);
- writel(temp, phy_data->base + REG_PHYCTL);
+ writel(temp, phyctl);
/* set the data bit and clear usbc bit*/
- temp = readb(phy_data->base + REG_PHYCTL);
+ temp = readb(phyctl);
if (data & 0x1)
temp |= PHYCTL_DATA;
else
temp &= ~PHYCTL_DATA;
temp &= ~usbc_bit;
- writeb(temp, phy_data->base + REG_PHYCTL);
+ writeb(temp, phyctl);
/* pulse usbc_bit */
- temp = readb(phy_data->base + REG_PHYCTL);
+ temp = readb(phyctl);
temp |= usbc_bit;
- writeb(temp, phy_data->base + REG_PHYCTL);
+ writeb(temp, phyctl);
- temp = readb(phy_data->base + REG_PHYCTL);
+ temp = readb(phyctl);
temp &= ~usbc_bit;
- writeb(temp, phy_data->base + REG_PHYCTL);
+ writeb(temp, phyctl);
data >>= 1;
}
@@ -171,12 +253,39 @@
sun4i_usb_phy_passby(phy, 1);
+ if (phy->index == 0) {
+ data->phy0_init = true;
+
+ /* Enable pull-ups */
+ sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_DPDM_PULLUP_EN);
+ sun4i_usb_phy0_update_iscr(_phy, 0, ISCR_ID_PULLUP_EN);
+
+ if (data->id_det_gpio) {
+ /* OTG mode, force ISCR and cable state updates */
+ data->id_det = -1;
+ data->vbus_det = -1;
+ queue_delayed_work(system_wq, &data->detect, 0);
+ } else {
+ /* Host only mode */
+ sun4i_usb_phy0_set_id_detect(_phy, 0);
+ sun4i_usb_phy0_set_vbus_detect(_phy, 1);
+ }
+ }
+
return 0;
}
static int sun4i_usb_phy_exit(struct phy *_phy)
{
struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+
+ if (phy->index == 0) {
+ /* Disable pull-ups */
+ sun4i_usb_phy0_update_iscr(_phy, ISCR_DPDM_PULLUP_EN, 0);
+ sun4i_usb_phy0_update_iscr(_phy, ISCR_ID_PULLUP_EN, 0);
+ data->phy0_init = false;
+ }
sun4i_usb_phy_passby(phy, 0);
reset_control_assert(phy->reset);
@@ -185,23 +294,74 @@
return 0;
}
+static int sun4i_usb_phy0_get_vbus_det(struct sun4i_usb_phy_data *data)
+{
+ if (data->vbus_det_gpio)
+ return gpiod_get_value_cansleep(data->vbus_det_gpio);
+
+ if (data->vbus_power_supply) {
+ union power_supply_propval val;
+ int r;
+
+ r = power_supply_get_property(data->vbus_power_supply,
+ POWER_SUPPLY_PROP_PRESENT, &val);
+ if (r == 0)
+ return val.intval;
+ }
+
+ /* Fallback: report vbus as high */
+ return 1;
+}
+
+static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data)
+{
+ return data->vbus_det_gpio || data->vbus_power_supply;
+}
+
static int sun4i_usb_phy_power_on(struct phy *_phy)
{
struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
- int ret = 0;
+ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
+ int ret;
- if (phy->vbus)
- ret = regulator_enable(phy->vbus);
+ if (!phy->vbus || phy->regulator_on)
+ return 0;
- return ret;
+ /* For phy0 only turn on Vbus if we don't have an ext. Vbus */
+ if (phy->index == 0 && sun4i_usb_phy0_have_vbus_det(data) &&
+ data->vbus_det)
+ return 0;
+
+ ret = regulator_enable(phy->vbus);
+ if (ret)
+ return ret;
+
+ phy->regulator_on = true;
+
+ /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */
+ if (phy->index == 0 && data->vbus_det_gpio && data->phy0_poll)
+ mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+ return 0;
}
static int sun4i_usb_phy_power_off(struct phy *_phy)
{
struct sun4i_usb_phy *phy = phy_get_drvdata(_phy);
+ struct sun4i_usb_phy_data *data = to_sun4i_usb_phy_data(phy);
- if (phy->vbus)
- regulator_disable(phy->vbus);
+ if (!phy->vbus || !phy->regulator_on)
+ return 0;
+
+ regulator_disable(phy->vbus);
+ phy->regulator_on = false;
+
+ /*
+ * phy0 vbus typically slowly discharges, sometimes this causes the
+ * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan.
+ */
+ if (phy->index == 0 && data->vbus_det_gpio && !data->phy0_poll)
+ mod_delayed_work(system_wq, &data->detect, POLL_TIME);
return 0;
}
@@ -212,8 +372,9 @@
sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2);
}
+EXPORT_SYMBOL_GPL(sun4i_usb_phy_set_squelch_detect);
-static struct phy_ops sun4i_usb_phy_ops = {
+static const struct phy_ops sun4i_usb_phy_ops = {
.init = sun4i_usb_phy_init,
.exit = sun4i_usb_phy_exit,
.power_on = sun4i_usb_phy_power_on,
@@ -221,6 +382,95 @@
.owner = THIS_MODULE,
};
+static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work)
+{
+ struct sun4i_usb_phy_data *data =
+ container_of(work, struct sun4i_usb_phy_data, detect.work);
+ struct phy *phy0 = data->phys[0].phy;
+ int id_det, vbus_det, id_notify = 0, vbus_notify = 0;
+
+ id_det = gpiod_get_value_cansleep(data->id_det_gpio);
+ vbus_det = sun4i_usb_phy0_get_vbus_det(data);
+
+ mutex_lock(&phy0->mutex);
+
+ if (!data->phy0_init) {
+ mutex_unlock(&phy0->mutex);
+ return;
+ }
+
+ if (id_det != data->id_det) {
+ /*
+ * When a host cable (id == 0) gets plugged in on systems
+ * without vbus detection report vbus low for long enough for
+ * the musb-ip to end the current device session.
+ */
+ if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 0) {
+ sun4i_usb_phy0_set_vbus_detect(phy0, 0);
+ msleep(200);
+ sun4i_usb_phy0_set_vbus_detect(phy0, 1);
+ }
+ sun4i_usb_phy0_set_id_detect(phy0, id_det);
+ data->id_det = id_det;
+ id_notify = 1;
+ }
+
+ if (vbus_det != data->vbus_det) {
+ sun4i_usb_phy0_set_vbus_detect(phy0, vbus_det);
+ data->vbus_det = vbus_det;
+ vbus_notify = 1;
+ }
+
+ mutex_unlock(&phy0->mutex);
+
+ if (id_notify) {
+ extcon_set_cable_state_(data->extcon, EXTCON_USB_HOST,
+ !id_det);
+ /*
+ * When a host cable gets unplugged (id == 1) on systems
+ * without vbus detection report vbus low for long enough to
+ * the musb-ip to end the current host session.
+ */
+ if (!sun4i_usb_phy0_have_vbus_det(data) && id_det == 1) {
+ mutex_lock(&phy0->mutex);
+ sun4i_usb_phy0_set_vbus_detect(phy0, 0);
+ msleep(1000);
+ sun4i_usb_phy0_set_vbus_detect(phy0, 1);
+ mutex_unlock(&phy0->mutex);
+ }
+ }
+
+ if (vbus_notify)
+ extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det);
+
+ if (data->phy0_poll)
+ queue_delayed_work(system_wq, &data->detect, POLL_TIME);
+}
+
+static irqreturn_t sun4i_usb_phy0_id_vbus_det_irq(int irq, void *dev_id)
+{
+ struct sun4i_usb_phy_data *data = dev_id;
+
+ /* vbus or id changed, let the pins settle and then scan them */
+ mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+ return IRQ_HANDLED;
+}
+
+static int sun4i_usb_phy0_vbus_notify(struct notifier_block *nb,
+ unsigned long val, void *v)
+{
+ struct sun4i_usb_phy_data *data =
+ container_of(nb, struct sun4i_usb_phy_data, vbus_power_nb);
+ struct power_supply *psy = v;
+
+ /* Properties on the vbus_power_supply changed, scan vbus_det */
+ if (val == PSY_EVENT_PROP_CHANGED && psy == data->vbus_power_supply)
+ mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME);
+
+ return NOTIFY_OK;
+}
+
static struct phy *sun4i_usb_phy_xlate(struct device *dev,
struct of_phandle_args *args)
{
@@ -232,6 +482,29 @@
return data->phys[args->args[0]].phy;
}
+static int sun4i_usb_phy_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
+
+ if (data->vbus_power_nb_registered)
+ power_supply_unreg_notifier(&data->vbus_power_nb);
+ if (data->id_det_irq >= 0)
+ devm_free_irq(dev, data->id_det_irq, data);
+ if (data->vbus_det_irq >= 0)
+ devm_free_irq(dev, data->vbus_det_irq, data);
+
+ cancel_delayed_work_sync(&data->detect);
+
+ return 0;
+}
+
+static const unsigned int sun4i_usb_phy0_cable[] = {
+ EXTCON_USB,
+ EXTCON_USB_HOST,
+ EXTCON_NONE,
+};
+
static int sun4i_usb_phy_probe(struct platform_device *pdev)
{
struct sun4i_usb_phy_data *data;
@@ -240,35 +513,87 @@
struct phy_provider *phy_provider;
bool dedicated_clocks;
struct resource *res;
- int i;
+ int i, ret;
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
mutex_init(&data->mutex);
+ INIT_DELAYED_WORK(&data->detect, sun4i_usb_phy0_id_vbus_det_scan);
+ dev_set_drvdata(dev, data);
- if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy"))
+ if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") ||
+ of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") ||
+ of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
data->num_phys = 2;
else
data->num_phys = 3;
- if (of_device_is_compatible(np, "allwinner,sun4i-a10-usb-phy") ||
- of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
- data->disc_thresh = 3;
- else
+ if (of_device_is_compatible(np, "allwinner,sun5i-a13-usb-phy") ||
+ of_device_is_compatible(np, "allwinner,sun7i-a20-usb-phy"))
data->disc_thresh = 2;
+ else
+ data->disc_thresh = 3;
- if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy"))
+ if (of_device_is_compatible(np, "allwinner,sun6i-a31-usb-phy") ||
+ of_device_is_compatible(np, "allwinner,sun8i-a23-usb-phy") ||
+ of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
dedicated_clocks = true;
else
dedicated_clocks = false;
+ if (of_device_is_compatible(np, "allwinner,sun8i-a33-usb-phy"))
+ data->has_a33_phyctl = true;
+
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl");
data->base = devm_ioremap_resource(dev, res);
if (IS_ERR(data->base))
return PTR_ERR(data->base);
+ data->id_det_gpio = devm_gpiod_get(dev, "usb0_id_det", GPIOD_IN);
+ if (IS_ERR(data->id_det_gpio)) {
+ if (PTR_ERR(data->id_det_gpio) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ data->id_det_gpio = NULL;
+ }
+
+ data->vbus_det_gpio = devm_gpiod_get(dev, "usb0_vbus_det", GPIOD_IN);
+ if (IS_ERR(data->vbus_det_gpio)) {
+ if (PTR_ERR(data->vbus_det_gpio) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ data->vbus_det_gpio = NULL;
+ }
+
+ if (of_find_property(np, "usb0_vbus_power-supply", NULL)) {
+ data->vbus_power_supply = devm_power_supply_get_by_phandle(dev,
+ "usb0_vbus_power-supply");
+ if (IS_ERR(data->vbus_power_supply))
+ return PTR_ERR(data->vbus_power_supply);
+
+ if (!data->vbus_power_supply)
+ return -EPROBE_DEFER;
+ }
+
+ /* vbus_det without id_det makes no sense, and is not supported */
+ if (sun4i_usb_phy0_have_vbus_det(data) && !data->id_det_gpio) {
+ dev_err(dev, "usb0_id_det missing or invalid\n");
+ return -ENODEV;
+ }
+
+ if (data->id_det_gpio) {
+ data->extcon = devm_extcon_dev_allocate(dev,
+ sun4i_usb_phy0_cable);
+ if (IS_ERR(data->extcon))
+ return PTR_ERR(data->extcon);
+
+ ret = devm_extcon_dev_register(dev, data->extcon);
+ if (ret) {
+ dev_err(dev, "failed to register extcon: %d\n", ret);
+ return ret;
+ }
+ }
+
for (i = 0; i < data->num_phys; i++) {
struct sun4i_usb_phy *phy = data->phys + i;
char name[16];
@@ -318,10 +643,54 @@
phy_set_drvdata(phy->phy, &data->phys[i]);
}
- dev_set_drvdata(dev, data);
- phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
+ data->id_det_irq = gpiod_to_irq(data->id_det_gpio);
+ data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio);
+ if ((data->id_det_gpio && data->id_det_irq < 0) ||
+ (data->vbus_det_gpio && data->vbus_det_irq < 0))
+ data->phy0_poll = true;
- return PTR_ERR_OR_ZERO(phy_provider);
+ if (data->id_det_irq >= 0) {
+ ret = devm_request_irq(dev, data->id_det_irq,
+ sun4i_usb_phy0_id_vbus_det_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "usb0-id-det", data);
+ if (ret) {
+ dev_err(dev, "Err requesting id-det-irq: %d\n", ret);
+ return ret;
+ }
+ }
+
+ if (data->vbus_det_irq >= 0) {
+ ret = devm_request_irq(dev, data->vbus_det_irq,
+ sun4i_usb_phy0_id_vbus_det_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "usb0-vbus-det", data);
+ if (ret) {
+ dev_err(dev, "Err requesting vbus-det-irq: %d\n", ret);
+ data->vbus_det_irq = -1;
+ sun4i_usb_phy_remove(pdev); /* Stop detect work */
+ return ret;
+ }
+ }
+
+ if (data->vbus_power_supply) {
+ data->vbus_power_nb.notifier_call = sun4i_usb_phy0_vbus_notify;
+ data->vbus_power_nb.priority = 0;
+ ret = power_supply_reg_notifier(&data->vbus_power_nb);
+ if (ret) {
+ sun4i_usb_phy_remove(pdev); /* Stop detect work */
+ return ret;
+ }
+ data->vbus_power_nb_registered = true;
+ }
+
+ phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_phy_xlate);
+ if (IS_ERR(phy_provider)) {
+ sun4i_usb_phy_remove(pdev); /* Stop detect work */
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
}
static const struct of_device_id sun4i_usb_phy_of_match[] = {
@@ -329,12 +698,15 @@
{ .compatible = "allwinner,sun5i-a13-usb-phy" },
{ .compatible = "allwinner,sun6i-a31-usb-phy" },
{ .compatible = "allwinner,sun7i-a20-usb-phy" },
+ { .compatible = "allwinner,sun8i-a23-usb-phy" },
+ { .compatible = "allwinner,sun8i-a33-usb-phy" },
{ },
};
MODULE_DEVICE_TABLE(of, sun4i_usb_phy_of_match);
static struct platform_driver sun4i_usb_phy_driver = {
.probe = sun4i_usb_phy_probe,
+ .remove = sun4i_usb_phy_remove,
.driver = {
.of_match_table = sun4i_usb_phy_of_match,
.name = "sun4i-usb-phy",
diff --git a/drivers/phy/phy-sun9i-usb.c b/drivers/phy/phy-sun9i-usb.c
index 0095914..ac4f31a 100644
--- a/drivers/phy/phy-sun9i-usb.c
+++ b/drivers/phy/phy-sun9i-usb.c
@@ -114,7 +114,7 @@
return 0;
}
-static struct phy_ops sun9i_usb_phy_ops = {
+static const struct phy_ops sun9i_usb_phy_ops = {
.init = sun9i_usb_phy_init,
.exit = sun9i_usb_phy_exit,
.owner = THIS_MODULE,
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 53f295c..93bc112 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -28,7 +28,8 @@
#include <linux/delay.h>
#include <linux/phy/omap_control_phy.h>
#include <linux/of_platform.h>
-#include <linux/spinlock.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
#define PLL_STATUS 0x00000004
#define PLL_GO 0x00000008
@@ -53,6 +54,8 @@
#define PLL_LOCK 0x2
#define PLL_IDLE 0x1
+#define SATA_PLL_SOFT_RESET BIT(18)
+
/*
* This is an Empirical value that works, need to confirm the actual
* value required for the PIPE3PHY_PLL_CONFIGURATION2.PLL_IDLE status
@@ -83,10 +86,9 @@
struct clk *refclk;
struct clk *div_clk;
struct pipe3_dpll_map *dpll_map;
- bool enabled;
- spinlock_t lock; /* serialize clock enable/disable */
- /* the below flag is needed specifically for SATA */
- bool refclk_enabled;
+ struct regmap *dpll_reset_syscon; /* ctrl. reg. acces */
+ unsigned int dpll_reset_reg; /* reg. index within syscon */
+ bool sata_refclk_enabled;
};
static struct pipe3_dpll_map dpll_map_usb[] = {
@@ -137,6 +139,9 @@
return NULL;
}
+static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy);
+static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy);
+
static int ti_pipe3_power_off(struct phy *x)
{
struct ti_pipe3 *phy = phy_get_drvdata(x);
@@ -217,6 +222,7 @@
u32 val;
int ret = 0;
+ ti_pipe3_enable_clocks(phy);
/*
* Set pcie_pcs register to 0x96 for proper functioning of phy
* as recommended in AM572x TRM SPRUHZ6, section 18.5.2.2, table
@@ -250,36 +256,49 @@
u32 val;
unsigned long timeout;
- /* SATA DPLL can't be powered down due to Errata i783 and PCIe
- * does not have internal DPLL
+ /* If dpll_reset_syscon is not present we wont power down SATA DPLL
+ * due to Errata i783
*/
- if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") ||
- of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
+ if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") &&
+ !phy->dpll_reset_syscon)
return 0;
- /* Put DPLL in IDLE mode */
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
- val |= PLL_IDLE;
- ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+ /* PCIe doesn't have internal DPLL */
+ if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
+ /* Put DPLL in IDLE mode */
+ val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+ val |= PLL_IDLE;
+ ti_pipe3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
- /* wait for LDO and Oscillator to power down */
- timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
- do {
- cpu_relax();
- val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
- if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
- break;
- } while (!time_after(jiffies, timeout));
+ /* wait for LDO and Oscillator to power down */
+ timeout = jiffies + msecs_to_jiffies(PLL_IDLE_TIME);
+ do {
+ cpu_relax();
+ val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_STATUS);
+ if ((val & PLL_TICOPWDN) && (val & PLL_LDOPWDN))
+ break;
+ } while (!time_after(jiffies, timeout));
- if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
- dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
- val);
- return -EBUSY;
+ if (!(val & PLL_TICOPWDN) || !(val & PLL_LDOPWDN)) {
+ dev_err(phy->dev, "Failed to power down: PLL_STATUS 0x%x\n",
+ val);
+ return -EBUSY;
+ }
}
+ /* i783: SATA needs control bit toggle after PLL unlock */
+ if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata")) {
+ regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg,
+ SATA_PLL_SOFT_RESET, SATA_PLL_SOFT_RESET);
+ regmap_update_bits(phy->dpll_reset_syscon, phy->dpll_reset_reg,
+ SATA_PLL_SOFT_RESET, 0);
+ }
+
+ ti_pipe3_disable_clocks(phy);
+
return 0;
}
-static struct phy_ops ops = {
+static const struct phy_ops ops = {
.init = ti_pipe3_init,
.exit = ti_pipe3_exit,
.power_on = ti_pipe3_power_on,
@@ -306,7 +325,6 @@
return -ENOMEM;
phy->dev = &pdev->dev;
- spin_lock_init(&phy->lock);
if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
match = of_match_device(ti_pipe3_id_table, &pdev->dev);
@@ -350,6 +368,21 @@
}
} else {
phy->wkupclk = ERR_PTR(-ENODEV);
+ phy->dpll_reset_syscon = syscon_regmap_lookup_by_phandle(node,
+ "syscon-pllreset");
+ if (IS_ERR(phy->dpll_reset_syscon)) {
+ dev_info(&pdev->dev,
+ "can't get syscon-pllreset, sata dpll won't idle\n");
+ phy->dpll_reset_syscon = NULL;
+ } else {
+ if (of_property_read_u32_index(node,
+ "syscon-pllreset", 1,
+ &phy->dpll_reset_reg)) {
+ dev_err(&pdev->dev,
+ "couldn't get pllreset reg. offset\n");
+ return -EINVAL;
+ }
+ }
}
if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
@@ -403,6 +436,16 @@
platform_set_drvdata(pdev, phy);
pm_runtime_enable(phy->dev);
+ /*
+ * Prevent auto-disable of refclk for SATA PHY due to Errata i783
+ */
+ if (of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
+ if (!IS_ERR(phy->refclk)) {
+ clk_prepare_enable(phy->refclk);
+ phy->sata_refclk_enabled = true;
+ }
+ }
+
generic_phy = devm_phy_create(phy->dev, NULL, &ops);
if (IS_ERR(generic_phy))
return PTR_ERR(generic_phy);
@@ -413,63 +456,33 @@
if (IS_ERR(phy_provider))
return PTR_ERR(phy_provider);
- pm_runtime_get(&pdev->dev);
-
return 0;
}
static int ti_pipe3_remove(struct platform_device *pdev)
{
- if (!pm_runtime_suspended(&pdev->dev))
- pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
return 0;
}
-#ifdef CONFIG_PM
-static int ti_pipe3_enable_refclk(struct ti_pipe3 *phy)
+static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
{
- if (!IS_ERR(phy->refclk) && !phy->refclk_enabled) {
- int ret;
+ int ret = 0;
+ if (!IS_ERR(phy->refclk)) {
ret = clk_prepare_enable(phy->refclk);
if (ret) {
dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
return ret;
}
- phy->refclk_enabled = true;
}
- return 0;
-}
-
-static void ti_pipe3_disable_refclk(struct ti_pipe3 *phy)
-{
- if (!IS_ERR(phy->refclk))
- clk_disable_unprepare(phy->refclk);
-
- phy->refclk_enabled = false;
-}
-
-static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
-{
- int ret = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&phy->lock, flags);
- if (phy->enabled)
- goto err1;
-
- ret = ti_pipe3_enable_refclk(phy);
- if (ret)
- goto err1;
-
if (!IS_ERR(phy->wkupclk)) {
ret = clk_prepare_enable(phy->wkupclk);
if (ret) {
dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
- goto err2;
+ goto disable_refclk;
}
}
@@ -477,96 +490,43 @@
ret = clk_prepare_enable(phy->div_clk);
if (ret) {
dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
- goto err3;
+ goto disable_wkupclk;
}
}
- phy->enabled = true;
- spin_unlock_irqrestore(&phy->lock, flags);
return 0;
-err3:
+disable_wkupclk:
if (!IS_ERR(phy->wkupclk))
clk_disable_unprepare(phy->wkupclk);
-err2:
+disable_refclk:
if (!IS_ERR(phy->refclk))
clk_disable_unprepare(phy->refclk);
- ti_pipe3_disable_refclk(phy);
-err1:
- spin_unlock_irqrestore(&phy->lock, flags);
return ret;
}
static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy)
{
- unsigned long flags;
-
- spin_lock_irqsave(&phy->lock, flags);
- if (!phy->enabled) {
- spin_unlock_irqrestore(&phy->lock, flags);
- return;
- }
-
if (!IS_ERR(phy->wkupclk))
clk_disable_unprepare(phy->wkupclk);
- /* Don't disable refclk for SATA PHY due to Errata i783 */
- if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
- ti_pipe3_disable_refclk(phy);
+ if (!IS_ERR(phy->refclk)) {
+ clk_disable_unprepare(phy->refclk);
+ /*
+ * SATA refclk needs an additional disable as we left it
+ * on in probe to avoid Errata i783
+ */
+ if (phy->sata_refclk_enabled) {
+ clk_disable_unprepare(phy->refclk);
+ phy->sata_refclk_enabled = false;
+ }
+ }
+
if (!IS_ERR(phy->div_clk))
clk_disable_unprepare(phy->div_clk);
- phy->enabled = false;
- spin_unlock_irqrestore(&phy->lock, flags);
}
-static int ti_pipe3_runtime_suspend(struct device *dev)
-{
- struct ti_pipe3 *phy = dev_get_drvdata(dev);
-
- ti_pipe3_disable_clocks(phy);
- return 0;
-}
-
-static int ti_pipe3_runtime_resume(struct device *dev)
-{
- struct ti_pipe3 *phy = dev_get_drvdata(dev);
- int ret = 0;
-
- ret = ti_pipe3_enable_clocks(phy);
- return ret;
-}
-
-static int ti_pipe3_suspend(struct device *dev)
-{
- struct ti_pipe3 *phy = dev_get_drvdata(dev);
-
- ti_pipe3_disable_clocks(phy);
- return 0;
-}
-
-static int ti_pipe3_resume(struct device *dev)
-{
- struct ti_pipe3 *phy = dev_get_drvdata(dev);
- int ret;
-
- ret = ti_pipe3_enable_clocks(phy);
- if (ret)
- return ret;
-
- pm_runtime_disable(dev);
- pm_runtime_set_active(dev);
- pm_runtime_enable(dev);
- return 0;
-}
-#endif
-
-static const struct dev_pm_ops ti_pipe3_pm_ops = {
- SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend,
- ti_pipe3_runtime_resume, NULL)
- SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume)
-};
-
static const struct of_device_id ti_pipe3_id_table[] = {
{
.compatible = "ti,phy-usb3",
@@ -592,7 +552,6 @@
.remove = ti_pipe3_remove,
.driver = {
.name = "ti-pipe3",
- .pm = &ti_pipe3_pm_ops,
.of_match_table = ti_pipe3_id_table,
},
};
diff --git a/drivers/phy/phy-tusb1210.c b/drivers/phy/phy-tusb1210.c
index 07efdd3..2535d79 100644
--- a/drivers/phy/phy-tusb1210.c
+++ b/drivers/phy/phy-tusb1210.c
@@ -53,7 +53,7 @@
return 0;
}
-static struct phy_ops phy_ops = {
+static const struct phy_ops phy_ops = {
.power_on = tusb1210_power_on,
.power_off = tusb1210_power_off,
.owner = THIS_MODULE,
diff --git a/drivers/phy/ulpi_phy.h b/drivers/phy/ulpi_phy.h
index ac49fb6..f2ebe49 100644
--- a/drivers/phy/ulpi_phy.h
+++ b/drivers/phy/ulpi_phy.h
@@ -5,7 +5,7 @@
* and it's controller, which is always the parent.
*/
static inline struct phy
-*ulpi_phy_create(struct ulpi *ulpi, struct phy_ops *ops)
+*ulpi_phy_create(struct ulpi *ulpi, const struct phy_ops *ops)
{
struct phy *phy;
int ret;
diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
index efcf2a2..6177315 100644
--- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c
+++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c
@@ -473,6 +473,8 @@
spin_lock_irqsave(&pc->irq_lock[bank], flags);
bcm2835_gpio_irq_config(pc, gpio, false);
+ /* Clear events that were latched prior to clearing event sources */
+ bcm2835_gpio_set_bit(pc, GPEDS0, gpio);
clear_bit(offset, &pc->enabled_irq_map[bank]);
spin_unlock_irqrestore(&pc->irq_lock[bank], flags);
}
diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c
index 5fd4437..88a7fac 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c
@@ -403,14 +403,13 @@
unsigned num_configs)
{
struct imx1_pinctrl *ipctl = pinctrl_dev_get_drvdata(pctldev);
- const struct imx1_pinctrl_soc_info *info = ipctl->info;
int i;
for (i = 0; i != num_configs; ++i) {
imx1_write_bit(ipctl, pin_id, configs[i] & 0x01, MX1_PUEN);
dev_dbg(ipctl->dev, "pinconf set pullup pin %s\n",
- info->pins[pin_id].name);
+ pin_desc_get(pctldev, pin_id)->name);
}
return 0;
diff --git a/drivers/pinctrl/nomadik/pinctrl-abx500.c b/drivers/pinctrl/nomadik/pinctrl-abx500.c
index 557d0f2..97681fa 100644
--- a/drivers/pinctrl/nomadik/pinctrl-abx500.c
+++ b/drivers/pinctrl/nomadik/pinctrl-abx500.c
@@ -787,7 +787,6 @@
.set_mux = abx500_pmx_set,
.gpio_request_enable = abx500_gpio_request_enable,
.gpio_disable_free = abx500_gpio_disable_free,
- .strict = true,
};
static int abx500_get_groups_cnt(struct pinctrl_dev *pctldev)
diff --git a/drivers/pinctrl/pinctrl-lpc18xx.c b/drivers/pinctrl/pinctrl-lpc18xx.c
index ef0b697..347c763 100644
--- a/drivers/pinctrl/pinctrl-lpc18xx.c
+++ b/drivers/pinctrl/pinctrl-lpc18xx.c
@@ -823,7 +823,7 @@
break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
- if (param)
+ if (param_val)
*reg &= ~(LPC18XX_SCU_I2C0_ZIF << shift);
else
*reg |= (LPC18XX_SCU_I2C0_ZIF << shift);
@@ -876,7 +876,7 @@
break;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
- if (param)
+ if (param_val)
*reg &= ~LPC18XX_SCU_PIN_ZIF;
else
*reg |= LPC18XX_SCU_PIN_ZIF;
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index b2de09d..0b8d480 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -1760,7 +1760,8 @@
int res;
res = request_irq(pcs_soc->irq, pcs_irq_handler,
- IRQF_SHARED | IRQF_NO_SUSPEND,
+ IRQF_SHARED | IRQF_NO_SUSPEND |
+ IRQF_NO_THREAD,
name, pcs_soc);
if (res) {
pcs_soc->irq = -1;
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c
index 3dd5a3b..c760bf4 100644
--- a/drivers/pinctrl/samsung/pinctrl-samsung.c
+++ b/drivers/pinctrl/samsung/pinctrl-samsung.c
@@ -33,11 +33,6 @@
#include "../core.h"
#include "pinctrl-samsung.h"
-#define GROUP_SUFFIX "-grp"
-#define GSUFFIX_LEN sizeof(GROUP_SUFFIX)
-#define FUNCTION_SUFFIX "-mux"
-#define FSUFFIX_LEN sizeof(FUNCTION_SUFFIX)
-
/* list of all possible config options supported */
static struct pin_config {
const char *property;
diff --git a/drivers/pinctrl/sh-pfc/sh_pfc.h b/drivers/pinctrl/sh-pfc/sh_pfc.h
index c7508d5..0874cfe 100644
--- a/drivers/pinctrl/sh-pfc/sh_pfc.h
+++ b/drivers/pinctrl/sh-pfc/sh_pfc.h
@@ -224,7 +224,7 @@
/* PINMUX_GPIO_GP_ALL - Expand to a list of sh_pfc_pin entries */
#define _GP_GPIO(bank, _pin, _name, sfx) \
- [(bank * 32) + _pin] = { \
+ { \
.pin = (bank * 32) + _pin, \
.name = __stringify(_name), \
.enum_id = _name##_DATA, \
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index cb13299..3271cd1 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -4,7 +4,6 @@
menuconfig CHROME_PLATFORMS
bool "Platform support for Chrome hardware"
- depends on X86 || ARM
---help---
Say Y here to get to see options for platform support for
various Chromebooks and Chromeboxes. This option alone does
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c
index 832932b..7fd4f51 100644
--- a/drivers/regulator/88pm800.c
+++ b/drivers/regulator/88pm800.c
@@ -130,7 +130,7 @@
.owner = THIS_MODULE, \
.n_voltages = ARRAY_SIZE(ldo_volt_table), \
.vsel_reg = PM800_##vreg##_VOUT, \
- .vsel_mask = 0x1f, \
+ .vsel_mask = 0xf, \
.enable_reg = PM800_##ereg, \
.enable_mask = 1 << (ebit), \
.volt_table = ldo_volt_table, \
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index c9f7201..78387a6 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -109,6 +109,7 @@
static struct regulator *create_regulator(struct regulator_dev *rdev,
struct device *dev,
const char *supply_name);
+static void _regulator_put(struct regulator *regulator);
static const char *rdev_get_name(struct regulator_dev *rdev)
{
@@ -1105,6 +1106,9 @@
rdev_info(rdev, "supplied by %s\n", rdev_get_name(supply_rdev));
+ if (!try_module_get(supply_rdev->owner))
+ return -ENODEV;
+
rdev->supply = create_regulator(supply_rdev, &rdev->dev, "SUPPLY");
if (rdev->supply == NULL) {
err = -ENOMEM;
@@ -1381,9 +1385,13 @@
}
if (!r) {
- dev_err(dev, "Failed to resolve %s-supply for %s\n",
- rdev->supply_name, rdev->desc->name);
- return -EPROBE_DEFER;
+ if (have_full_constraints()) {
+ r = dummy_regulator_rdev;
+ } else {
+ dev_err(dev, "Failed to resolve %s-supply for %s\n",
+ rdev->supply_name, rdev->desc->name);
+ return -EPROBE_DEFER;
+ }
}
/* Recursively resolve the supply of the supply */
@@ -1398,8 +1406,11 @@
/* Cascade always-on state to supply */
if (_regulator_is_enabled(rdev)) {
ret = regulator_enable(rdev->supply);
- if (ret < 0)
+ if (ret < 0) {
+ if (rdev->supply)
+ _regulator_put(rdev->supply);
return ret;
+ }
}
return 0;
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
index 6f2bdad..e94ddcf 100644
--- a/drivers/regulator/max8973-regulator.c
+++ b/drivers/regulator/max8973-regulator.c
@@ -450,7 +450,7 @@
pdata->control_flags |= MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE;
if (of_property_read_bool(np, "maxim,enable-bias-control"))
- pdata->control_flags |= MAX8973_BIAS_ENABLE;
+ pdata->control_flags |= MAX8973_CONTROL_BIAS_ENABLE;
return pdata;
}
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index 326ffb5..72fc3c3 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -34,6 +34,8 @@
#include <linux/mfd/samsung/s2mps14.h>
#include <linux/mfd/samsung/s2mpu02.h>
+/* The highest number of possible regulators for supported devices. */
+#define S2MPS_REGULATOR_MAX S2MPS13_REGULATOR_MAX
struct s2mps11_info {
unsigned int rdev_num;
int ramp_delay2;
@@ -49,7 +51,7 @@
* One bit for each S2MPS13/S2MPS14/S2MPU02 regulator whether
* the suspend mode was enabled.
*/
- unsigned long long s2mps14_suspend_state:50;
+ DECLARE_BITMAP(suspend_state, S2MPS_REGULATOR_MAX);
/* Array of size rdev_num with GPIO-s for external sleep control */
int *ext_control_gpio;
@@ -500,7 +502,7 @@
switch (s2mps11->dev_type) {
case S2MPS13X:
case S2MPS14X:
- if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+ if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state))
val = S2MPS14_ENABLE_SUSPEND;
else if (gpio_is_valid(s2mps11->ext_control_gpio[rdev_get_id(rdev)]))
val = S2MPS14_ENABLE_EXT_CONTROL;
@@ -508,7 +510,7 @@
val = rdev->desc->enable_mask;
break;
case S2MPU02:
- if (s2mps11->s2mps14_suspend_state & (1 << rdev_get_id(rdev)))
+ if (test_bit(rdev_get_id(rdev), s2mps11->suspend_state))
val = S2MPU02_ENABLE_SUSPEND;
else
val = rdev->desc->enable_mask;
@@ -562,7 +564,7 @@
if (ret < 0)
return ret;
- s2mps11->s2mps14_suspend_state |= (1 << rdev_get_id(rdev));
+ set_bit(rdev_get_id(rdev), s2mps11->suspend_state);
/*
* Don't enable suspend mode if regulator is already disabled because
* this would effectively for a short time turn on the regulator after
@@ -960,18 +962,22 @@
case S2MPS11X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps11_regulators);
regulators = s2mps11_regulators;
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
break;
case S2MPS13X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps13_regulators);
regulators = s2mps13_regulators;
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
break;
case S2MPS14X:
s2mps11->rdev_num = ARRAY_SIZE(s2mps14_regulators);
regulators = s2mps14_regulators;
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
break;
case S2MPU02:
s2mps11->rdev_num = ARRAY_SIZE(s2mpu02_regulators);
regulators = s2mpu02_regulators;
+ BUILD_BUG_ON(S2MPS_REGULATOR_MAX < s2mps11->rdev_num);
break;
default:
dev_err(&pdev->dev, "Invalid device type: %u\n",
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 167783f..72c9333 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -666,9 +666,8 @@
#ifdef CONFIG_RTC_DRV_DS1374_WDT
int res;
- res = misc_deregister(&ds1374_miscdev);
- if (!res)
- ds1374_miscdev.parent = NULL;
+ misc_deregister(&ds1374_miscdev);
+ ds1374_miscdev.parent = NULL;
unregister_reboot_notifier(&ds1374_wdt_notifier);
#endif
diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile
index 95bccfd..e5225ad 100644
--- a/drivers/s390/Makefile
+++ b/drivers/s390/Makefile
@@ -2,7 +2,7 @@
# Makefile for the S/390 specific device drivers
#
-obj-y += cio/ block/ char/ crypto/ net/ scsi/ kvm/
+obj-y += cio/ block/ char/ crypto/ net/ scsi/ virtio/
drivers-y += drivers/s390/built-in.o
diff --git a/drivers/s390/kvm/Makefile b/drivers/s390/virtio/Makefile
similarity index 100%
rename from drivers/s390/kvm/Makefile
rename to drivers/s390/virtio/Makefile
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/virtio/kvm_virtio.c
similarity index 100%
rename from drivers/s390/kvm/kvm_virtio.c
rename to drivers/s390/virtio/kvm_virtio.c
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c
similarity index 100%
rename from drivers/s390/kvm/virtio_ccw.c
rename to drivers/s390/virtio/virtio_ccw.c
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index 26270c3..ce129e5 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -39,7 +39,7 @@
#define DRV_NAME "fnic"
#define DRV_DESCRIPTION "Cisco FCoE HBA Driver"
-#define DRV_VERSION "1.6.0.17"
+#define DRV_VERSION "1.6.0.17a"
#define PFX DRV_NAME ": "
#define DFX DRV_NAME "%d: "
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 155b286..25436cd 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -425,6 +425,7 @@
unsigned long ptr;
struct fc_rport_priv *rdata;
spinlock_t *io_lock = NULL;
+ int io_lock_acquired = 0;
if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
return SCSI_MLQUEUE_HOST_BUSY;
@@ -518,6 +519,7 @@
spin_lock_irqsave(io_lock, flags);
/* initialize rest of io_req */
+ io_lock_acquired = 1;
io_req->port_id = rport->port_id;
io_req->start_time = jiffies;
CMD_STATE(sc) = FNIC_IOREQ_CMD_PENDING;
@@ -571,7 +573,7 @@
(((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));
/* if only we issued IO, will we have the io lock */
- if (CMD_FLAGS(sc) & FNIC_IO_INITIALIZED)
+ if (io_lock_acquired)
spin_unlock_irqrestore(io_lock, flags);
atomic_dec(&fnic->in_flight);
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 8827448..a9aa389 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -599,9 +599,10 @@
{
struct ipr_trace_entry *trace_entry;
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+ unsigned int trace_index;
- trace_entry = &ioa_cfg->trace[atomic_add_return
- (1, &ioa_cfg->trace_index)%IPR_NUM_TRACE_ENTRIES];
+ trace_index = atomic_add_return(1, &ioa_cfg->trace_index) & IPR_TRACE_INDEX_MASK;
+ trace_entry = &ioa_cfg->trace[trace_index];
trace_entry->time = jiffies;
trace_entry->op_code = ipr_cmd->ioarcb.cmd_pkt.cdb[0];
trace_entry->type = type;
@@ -1051,10 +1052,15 @@
static int ipr_get_hrrq_index(struct ipr_ioa_cfg *ioa_cfg)
{
+ unsigned int hrrq;
+
if (ioa_cfg->hrrq_num == 1)
- return 0;
- else
- return (atomic_add_return(1, &ioa_cfg->hrrq_index) % (ioa_cfg->hrrq_num - 1)) + 1;
+ hrrq = 0;
+ else {
+ hrrq = atomic_add_return(1, &ioa_cfg->hrrq_index);
+ hrrq = (hrrq % (ioa_cfg->hrrq_num - 1)) + 1;
+ }
+ return hrrq;
}
/**
@@ -6263,21 +6269,23 @@
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc);
- unsigned long hrrq_flags;
+ unsigned long lock_flags;
scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len));
if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) {
scsi_dma_unmap(scsi_cmd);
- spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags);
+ spin_lock_irqsave(ipr_cmd->hrrq->lock, lock_flags);
list_add_tail(&ipr_cmd->queue, &ipr_cmd->hrrq->hrrq_free_q);
scsi_cmd->scsi_done(scsi_cmd);
- spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags);
+ spin_unlock_irqrestore(ipr_cmd->hrrq->lock, lock_flags);
} else {
- spin_lock_irqsave(ipr_cmd->hrrq->lock, hrrq_flags);
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ spin_lock(&ipr_cmd->hrrq->_lock);
ipr_erp_start(ioa_cfg, ipr_cmd);
- spin_unlock_irqrestore(ipr_cmd->hrrq->lock, hrrq_flags);
+ spin_unlock(&ipr_cmd->hrrq->_lock);
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
}
}
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 73790a1..6b97ee4 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1486,6 +1486,7 @@
#define IPR_NUM_TRACE_INDEX_BITS 8
#define IPR_NUM_TRACE_ENTRIES (1 << IPR_NUM_TRACE_INDEX_BITS)
+#define IPR_TRACE_INDEX_MASK (IPR_NUM_TRACE_ENTRIES - 1)
#define IPR_TRACE_SIZE (sizeof(struct ipr_trace_entry) * IPR_NUM_TRACE_ENTRIES)
char trace_start[8];
#define IPR_TRACE_START_LABEL "trace"
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 1b3a094..30f9ef0 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -733,8 +733,6 @@
if (resp) {
resp(sp, fp, arg);
res = true;
- } else if (!IS_ERR(fp)) {
- fc_frame_free(fp);
}
spin_lock_bh(&ep->ex_lock);
@@ -1596,7 +1594,8 @@
* If new exch resp handler is valid then call that
* first.
*/
- fc_invoke_resp(ep, sp, fp);
+ if (!fc_invoke_resp(ep, sp, fp))
+ fc_frame_free(fp);
fc_exch_release(ep);
return;
@@ -1695,7 +1694,8 @@
fc_exch_hold(ep);
if (!rc)
fc_exch_delete(ep);
- fc_invoke_resp(ep, sp, fp);
+ if (!fc_invoke_resp(ep, sp, fp))
+ fc_frame_free(fp);
if (has_rec)
fc_exch_timer_set(ep, ep->r_a_tov);
fc_exch_release(ep);
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index c679594..2d5909c 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1039,11 +1039,26 @@
fc_fcp_pkt_hold(fsp);
spin_unlock_irqrestore(&si->scsi_queue_lock, flags);
- if (!fc_fcp_lock_pkt(fsp)) {
+ spin_lock_bh(&fsp->scsi_pkt_lock);
+ if (!(fsp->state & FC_SRB_COMPL)) {
+ fsp->state |= FC_SRB_COMPL;
+ /*
+ * TODO: dropping scsi_pkt_lock and then reacquiring
+ * again around fc_fcp_cleanup_cmd() is required,
+ * since fc_fcp_cleanup_cmd() calls into
+ * fc_seq_set_resp() and that func preempts cpu using
+ * schedule. May be schedule and related code should be
+ * removed instead of unlocking here to avoid scheduling
+ * while atomic bug.
+ */
+ spin_unlock_bh(&fsp->scsi_pkt_lock);
+
fc_fcp_cleanup_cmd(fsp, error);
+
+ spin_lock_bh(&fsp->scsi_pkt_lock);
fc_io_compl(fsp);
- fc_fcp_unlock_pkt(fsp);
}
+ spin_unlock_bh(&fsp->scsi_pkt_lock);
fc_fcp_pkt_release(fsp);
spin_lock_irqsave(&si->scsi_queue_lock, flags);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 8053f24..98d9bb6 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -2941,10 +2941,10 @@
{
struct iscsi_conn *conn = cls_conn->dd_data;
struct iscsi_session *session = conn->session;
- unsigned long flags;
del_timer_sync(&conn->transport_timer);
+ mutex_lock(&session->eh_mutex);
spin_lock_bh(&session->frwd_lock);
conn->c_stage = ISCSI_CONN_CLEANUP_WAIT;
if (session->leadconn == conn) {
@@ -2956,28 +2956,6 @@
}
spin_unlock_bh(&session->frwd_lock);
- /*
- * Block until all in-progress commands for this connection
- * time out or fail.
- */
- for (;;) {
- spin_lock_irqsave(session->host->host_lock, flags);
- if (!atomic_read(&session->host->host_busy)) { /* OK for ERL == 0 */
- spin_unlock_irqrestore(session->host->host_lock, flags);
- break;
- }
- spin_unlock_irqrestore(session->host->host_lock, flags);
- msleep_interruptible(500);
- iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): "
- "host_busy %d host_failed %d\n",
- atomic_read(&session->host->host_busy),
- session->host->host_failed);
- /*
- * force eh_abort() to unblock
- */
- wake_up(&conn->ehwait);
- }
-
/* flush queued up work because we free the connection below */
iscsi_suspend_tx(conn);
@@ -2994,6 +2972,7 @@
if (session->leadconn == conn)
session->leadconn = NULL;
spin_unlock_bh(&session->frwd_lock);
+ mutex_unlock(&session->eh_mutex);
iscsi_destroy_conn(cls_conn);
}
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 82b92c4..437254e 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -738,7 +738,7 @@
ql_log(ql_log_info, vha, 0x706f,
"Issuing MPI reset.\n");
- if (IS_QLA83XX(ha)) {
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
uint32_t idc_control;
qla83xx_idc_lock(vha, 0);
diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c
index 0e6ee3c..8b011ae 100644
--- a/drivers/scsi/qla2xxx/qla_dbg.c
+++ b/drivers/scsi/qla2xxx/qla_dbg.c
@@ -67,10 +67,10 @@
* | | | 0xd031-0xd0ff |
* | | | 0xd101-0xd1fe |
* | | | 0xd214-0xd2fe |
- * | Target Mode | 0xe079 | |
- * | Target Mode Management | 0xf072 | 0xf002 |
+ * | Target Mode | 0xe080 | |
+ * | Target Mode Management | 0xf096 | 0xf002 |
* | | | 0xf046-0xf049 |
- * | Target Mode Task Management | 0x1000b | |
+ * | Target Mode Task Management | 0x1000d | |
* ----------------------------------------------------------------------
*/
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index e86201d..9ad819e 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -274,6 +274,7 @@
#define RESPONSE_ENTRY_CNT_FX00 256 /* Number of response entries.*/
struct req_que;
+struct qla_tgt_sess;
/*
* (sd.h is not exported, hence local inclusion)
@@ -2026,6 +2027,7 @@
uint16_t port_id;
unsigned long retry_delay_timestamp;
+ struct qla_tgt_sess *tgt_session;
} fc_port_t;
#include "qla_mr.h"
@@ -3154,13 +3156,13 @@
/* Bit 21 of fw_attributes decides the MCTP capabilities */
#define IS_MCTP_CAPABLE(ha) (IS_QLA2031(ha) && \
((ha)->fw_attributes_ext[0] & BIT_0))
-#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha))
-#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha))
+#define IS_PI_UNINIT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
+#define IS_PI_IPGUARD_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_PI_DIFB_DIX0_CAPABLE(ha) (0)
-#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha))
+#define IS_PI_SPLIT_DET_CAPABLE_HBA(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_PI_SPLIT_DET_CAPABLE(ha) (IS_PI_SPLIT_DET_CAPABLE_HBA(ha) && \
(((ha)->fw_attributes_h << 16 | (ha)->fw_attributes) & BIT_22))
-#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha))
+#define IS_ATIO_MSIX_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
#define IS_TGT_MODE_CAPABLE(ha) (ha->tgt.atio_q_length)
#define IS_SHADOW_REG_CAPABLE(ha) (IS_QLA27XX(ha))
#define IS_DPORT_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha))
@@ -3579,6 +3581,16 @@
uint16_t fcoe_fcf_idx;
uint8_t fcoe_vn_port_mac[6];
+ /* list of commands waiting on workqueue */
+ struct list_head qla_cmd_list;
+ struct list_head qla_sess_op_cmd_list;
+ spinlock_t cmd_list_lock;
+
+ /* Counter to detect races between ELS and RSCN events */
+ atomic_t generation_tick;
+ /* Time when global fcport update has been scheduled */
+ int total_fcport_update_gen;
+
uint32_t vp_abort_cnt;
struct fc_vport *fc_vport; /* holds fc_vport * for each vport */
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 6640131..11f2f32 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -115,6 +115,8 @@
QLA_LOGIO_LOGIN_RETRIED : 0;
qla2x00_post_async_login_done_work(fcport->vha, fcport,
lio->u.logio.data);
+ } else if (sp->type == SRB_LOGOUT_CMD) {
+ qlt_logo_completion_handler(fcport, QLA_FUNCTION_TIMEOUT);
}
}
@@ -497,7 +499,10 @@
qla2x00_async_logout_done(struct scsi_qla_host *vha, fc_port_t *fcport,
uint16_t *data)
{
- qla2x00_mark_device_lost(vha, fcport, 1, 0);
+ /* Don't re-login in target mode */
+ if (!fcport->tgt_session)
+ qla2x00_mark_device_lost(vha, fcport, 1, 0);
+ qlt_logo_completion_handler(fcport, data[0]);
return;
}
@@ -1538,7 +1543,7 @@
mem_size = (ha->fw_memory_size - 0x11000 + 1) *
sizeof(uint16_t);
} else if (IS_FWI2_CAPABLE(ha)) {
- if (IS_QLA83XX(ha))
+ if (IS_QLA83XX(ha) || IS_QLA27XX(ha))
fixed_size = offsetof(struct qla83xx_fw_dump, ext_mem);
else if (IS_QLA81XX(ha))
fixed_size = offsetof(struct qla81xx_fw_dump, ext_mem);
@@ -1550,7 +1555,7 @@
mem_size = (ha->fw_memory_size - 0x100000 + 1) *
sizeof(uint32_t);
if (ha->mqenable) {
- if (!IS_QLA83XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
mq_size = sizeof(struct qla2xxx_mq_chain);
/*
* Allocate maximum buffer size for all queues.
@@ -2922,21 +2927,14 @@
{
fc_port_t *fcport = data;
struct fc_rport *rport;
- scsi_qla_host_t *vha = fcport->vha;
unsigned long flags;
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
rport = fcport->drport ? fcport->drport: fcport->rport;
fcport->drport = NULL;
spin_unlock_irqrestore(fcport->vha->host->host_lock, flags);
- if (rport) {
+ if (rport)
fc_remote_port_delete(rport);
- /*
- * Release the target mode FC NEXUS in qla_target.c code
- * if target mod is enabled.
- */
- qlt_fc_port_deleted(vha, fcport);
- }
}
/**
@@ -3303,6 +3301,7 @@
* Create target mode FC NEXUS in qla_target.c if target mode is
* enabled..
*/
+
qlt_fc_port_added(vha, fcport);
spin_lock_irqsave(fcport->vha->host->host_lock, flags);
@@ -3341,8 +3340,7 @@
if (IS_QLAFX00(vha->hw)) {
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
- qla2x00_reg_remote_port(vha, fcport);
- return;
+ goto reg_port;
}
fcport->login_retry = 0;
fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
@@ -3350,7 +3348,16 @@
qla2x00_set_fcport_state(fcport, FCS_ONLINE);
qla2x00_iidma_fcport(vha, fcport);
qla24xx_update_fcport_fcp_prio(vha, fcport);
- qla2x00_reg_remote_port(vha, fcport);
+
+reg_port:
+ if (qla_ini_mode_enabled(vha))
+ qla2x00_reg_remote_port(vha, fcport);
+ else {
+ /*
+ * Create target mode FC NEXUS in qla_target.c
+ */
+ qlt_fc_port_added(vha, fcport);
+ }
}
/*
@@ -3375,6 +3382,7 @@
LIST_HEAD(new_fcports);
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
+ int discovery_gen;
/* If FL port exists, then SNS is present */
if (IS_FWI2_CAPABLE(ha))
@@ -3445,6 +3453,14 @@
fcport->scan_state = QLA_FCPORT_SCAN;
}
+ /* Mark the time right before querying FW for connected ports.
+ * This process is long, asynchronous and by the time it's done,
+ * collected information might not be accurate anymore. E.g.
+ * disconnected port might have re-connected and a brand new
+ * session has been created. In this case session's generation
+ * will be newer than discovery_gen. */
+ qlt_do_generation_tick(vha, &discovery_gen);
+
rval = qla2x00_find_all_fabric_devs(vha, &new_fcports);
if (rval != QLA_SUCCESS)
break;
@@ -3460,20 +3476,44 @@
if ((fcport->flags & FCF_FABRIC_DEVICE) == 0)
continue;
- if (fcport->scan_state == QLA_FCPORT_SCAN &&
- atomic_read(&fcport->state) == FCS_ONLINE) {
- qla2x00_mark_device_lost(vha, fcport,
- ql2xplogiabsentdevice, 0);
- if (fcport->loop_id != FC_NO_LOOP_ID &&
- (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
- fcport->port_type != FCT_INITIATOR &&
- fcport->port_type != FCT_BROADCAST) {
- ha->isp_ops->fabric_logout(vha,
- fcport->loop_id,
- fcport->d_id.b.domain,
- fcport->d_id.b.area,
- fcport->d_id.b.al_pa);
- qla2x00_clear_loop_id(fcport);
+ if (fcport->scan_state == QLA_FCPORT_SCAN) {
+ if (qla_ini_mode_enabled(base_vha) &&
+ atomic_read(&fcport->state) == FCS_ONLINE) {
+ qla2x00_mark_device_lost(vha, fcport,
+ ql2xplogiabsentdevice, 0);
+ if (fcport->loop_id != FC_NO_LOOP_ID &&
+ (fcport->flags & FCF_FCP2_DEVICE) == 0 &&
+ fcport->port_type != FCT_INITIATOR &&
+ fcport->port_type != FCT_BROADCAST) {
+ ha->isp_ops->fabric_logout(vha,
+ fcport->loop_id,
+ fcport->d_id.b.domain,
+ fcport->d_id.b.area,
+ fcport->d_id.b.al_pa);
+ qla2x00_clear_loop_id(fcport);
+ }
+ } else if (!qla_ini_mode_enabled(base_vha)) {
+ /*
+ * In target mode, explicitly kill
+ * sessions and log out of devices
+ * that are gone, so that we don't
+ * end up with an initiator using the
+ * wrong ACL (if the fabric recycles
+ * an FC address and we have a stale
+ * session around) and so that we don't
+ * report initiators that are no longer
+ * on the fabric.
+ */
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf077,
+ "port gone, logging out/killing session: "
+ "%8phC state 0x%x flags 0x%x fc4_type 0x%x "
+ "scan_state %d\n",
+ fcport->port_name,
+ atomic_read(&fcport->state),
+ fcport->flags, fcport->fc4_type,
+ fcport->scan_state);
+ qlt_fc_port_deleted(vha, fcport,
+ discovery_gen);
}
}
}
@@ -3494,6 +3534,28 @@
(fcport->flags & FCF_LOGIN_NEEDED) == 0)
continue;
+ /*
+ * If we're not an initiator, skip looking for devices
+ * and logging in. There's no reason for us to do it,
+ * and it seems to actively cause problems in target
+ * mode if we race with the initiator logging into us
+ * (we might get the "port ID used" status back from
+ * our login command and log out the initiator, which
+ * seems to cause havoc).
+ */
+ if (!qla_ini_mode_enabled(base_vha)) {
+ if (fcport->scan_state == QLA_FCPORT_FOUND) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf078,
+ "port %8phC state 0x%x flags 0x%x fc4_type 0x%x "
+ "scan_state %d (initiator mode disabled; skipping "
+ "login)\n", fcport->port_name,
+ atomic_read(&fcport->state),
+ fcport->flags, fcport->fc4_type,
+ fcport->scan_state);
+ }
+ continue;
+ }
+
if (fcport->loop_id == FC_NO_LOOP_ID) {
fcport->loop_id = next_loopid;
rval = qla2x00_find_new_loop_id(
@@ -3520,16 +3582,38 @@
test_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags))
break;
- /* Find a new loop ID to use. */
- fcport->loop_id = next_loopid;
- rval = qla2x00_find_new_loop_id(base_vha, fcport);
- if (rval != QLA_SUCCESS) {
- /* Ran out of IDs to use */
- break;
- }
+ /*
+ * If we're not an initiator, skip looking for devices
+ * and logging in. There's no reason for us to do it,
+ * and it seems to actively cause problems in target
+ * mode if we race with the initiator logging into us
+ * (we might get the "port ID used" status back from
+ * our login command and log out the initiator, which
+ * seems to cause havoc).
+ */
+ if (qla_ini_mode_enabled(base_vha)) {
+ /* Find a new loop ID to use. */
+ fcport->loop_id = next_loopid;
+ rval = qla2x00_find_new_loop_id(base_vha,
+ fcport);
+ if (rval != QLA_SUCCESS) {
+ /* Ran out of IDs to use */
+ break;
+ }
- /* Login and update database */
- qla2x00_fabric_dev_login(vha, fcport, &next_loopid);
+ /* Login and update database */
+ qla2x00_fabric_dev_login(vha, fcport,
+ &next_loopid);
+ } else {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf079,
+ "new port %8phC state 0x%x flags 0x%x fc4_type "
+ "0x%x scan_state %d (initiator mode disabled; "
+ "skipping login)\n",
+ fcport->port_name,
+ atomic_read(&fcport->state),
+ fcport->flags, fcport->fc4_type,
+ fcport->scan_state);
+ }
list_move_tail(&fcport->list, &vha->vp_fcports);
}
@@ -3725,11 +3809,12 @@
fcport->fp_speed = new_fcport->fp_speed;
/*
- * If address the same and state FCS_ONLINE, nothing
- * changed.
+ * If address the same and state FCS_ONLINE
+ * (or in target mode), nothing changed.
*/
if (fcport->d_id.b24 == new_fcport->d_id.b24 &&
- atomic_read(&fcport->state) == FCS_ONLINE) {
+ (atomic_read(&fcport->state) == FCS_ONLINE ||
+ !qla_ini_mode_enabled(base_vha))) {
break;
}
@@ -3749,6 +3834,22 @@
* Log it out if still logged in and mark it for
* relogin later.
*/
+ if (!qla_ini_mode_enabled(base_vha)) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf080,
+ "port changed FC ID, %8phC"
+ " old %x:%x:%x (loop_id 0x%04x)-> new %x:%x:%x\n",
+ fcport->port_name,
+ fcport->d_id.b.domain,
+ fcport->d_id.b.area,
+ fcport->d_id.b.al_pa,
+ fcport->loop_id,
+ new_fcport->d_id.b.domain,
+ new_fcport->d_id.b.area,
+ new_fcport->d_id.b.al_pa);
+ fcport->d_id.b24 = new_fcport->d_id.b24;
+ break;
+ }
+
fcport->d_id.b24 = new_fcport->d_id.b24;
fcport->flags |= FCF_LOGIN_NEEDED;
if (fcport->loop_id != FC_NO_LOOP_ID &&
@@ -3768,6 +3869,7 @@
if (found)
continue;
/* If device was not in our fcports list, then add it. */
+ new_fcport->scan_state = QLA_FCPORT_FOUND;
list_add_tail(&new_fcport->list, new_fcports);
/* Allocate a new replacement fcport. */
@@ -4188,6 +4290,14 @@
atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
spin_unlock_irqrestore(&ha->vport_slock, flags);
qla2x00_rport_del(fcport);
+
+ /*
+ * Release the target mode FC NEXUS in
+ * qla_target.c, if target mod is enabled.
+ */
+ qlt_fc_port_deleted(vha, fcport,
+ base_vha->total_fcport_update_gen);
+
spin_lock_irqsave(&ha->vport_slock, flags);
}
}
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 36fbd4c..6f02b26 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -1943,6 +1943,9 @@
logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
logio->control_flags =
cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
+ if (!sp->fcport->tgt_session ||
+ !sp->fcport->tgt_session->keep_nport_handle)
+ logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
logio->port_id[0] = sp->fcport->d_id.b.al_pa;
logio->port_id[1] = sp->fcport->d_id.b.area;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index 02b1c1c..b2f713a 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -2415,7 +2415,8 @@
*orig_iocb_cnt = mcp->mb[10];
if (vha->hw->flags.npiv_supported && max_npiv_vports)
*max_npiv_vports = mcp->mb[11];
- if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw)) && max_fcfs)
+ if ((IS_QLA81XX(vha->hw) || IS_QLA83XX(vha->hw) ||
+ IS_QLA27XX(vha->hw)) && max_fcfs)
*max_fcfs = mcp->mb[12];
}
@@ -3898,7 +3899,7 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
if (!(rsp->options & BIT_0)) {
WRT_REG_DWORD(rsp->rsp_q_out, 0);
- if (!IS_QLA83XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
WRT_REG_DWORD(rsp->rsp_q_in, 0);
}
@@ -5345,7 +5346,7 @@
mbx_cmd_t *mcp = &mc;
struct qla_hw_data *ha = vha->hw;
- if (!IS_QLA83XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
return QLA_FUNCTION_FAILED;
ql_dbg(ql_dbg_mbx, vha, 0x1143, "Entered %s.\n", __func__);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index a28815b..8a5cac8 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2504,6 +2504,7 @@
ha->mbx_count = MAILBOX_REGISTER_COUNT;
req_length = REQUEST_ENTRY_CNT_24XX;
rsp_length = RESPONSE_ENTRY_CNT_2300;
+ ha->tgt.atio_q_length = ATIO_ENTRY_CNT_24XX;
ha->max_loop_id = SNS_LAST_LOOP_ID_2300;
ha->init_cb_size = sizeof(struct mid_init_cb_81xx);
ha->gid_list_info_size = 8;
@@ -3229,11 +3230,15 @@
spin_lock_irqsave(vha->host->host_lock, flags);
fcport->drport = rport;
spin_unlock_irqrestore(vha->host->host_lock, flags);
+ qlt_do_generation_tick(vha, &base_vha->total_fcport_update_gen);
set_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags);
qla2xxx_wake_dpc(base_vha);
} else {
- fc_remote_port_delete(rport);
- qlt_fc_port_deleted(vha, fcport);
+ int now;
+ if (rport)
+ fc_remote_port_delete(rport);
+ qlt_do_generation_tick(vha, &now);
+ qlt_fc_port_deleted(vha, fcport, now);
}
}
@@ -3763,8 +3768,11 @@
INIT_LIST_HEAD(&vha->vp_fcports);
INIT_LIST_HEAD(&vha->work_list);
INIT_LIST_HEAD(&vha->list);
+ INIT_LIST_HEAD(&vha->qla_cmd_list);
+ INIT_LIST_HEAD(&vha->qla_sess_op_cmd_list);
spin_lock_init(&vha->work_lock);
+ spin_lock_init(&vha->cmd_list_lock);
sprintf(vha->host_str, "%s_%ld", QLA2XXX_DRIVER_NAME, vha->host_no);
ql_dbg(ql_dbg_init, vha, 0x0041,
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 028e8c8..2feb5f3 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -1697,7 +1697,7 @@
{
uint32_t led_select_value = 0;
- if (!IS_QLA83XX(ha))
+ if (!IS_QLA83XX(ha) && !IS_QLA27XX(ha))
goto out;
if (ha->port_no == 0)
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index b749026..58651ec 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -113,6 +113,11 @@
static void qlt_alloc_qfull_cmd(struct scsi_qla_host *vha,
struct atio_from_isp *atio, uint16_t status, int qfull);
static void qlt_disable_vha(struct scsi_qla_host *vha);
+static void qlt_clear_tgt_db(struct qla_tgt *tgt);
+static void qlt_send_notify_ack(struct scsi_qla_host *vha,
+ struct imm_ntfy_from_isp *ntfy,
+ uint32_t add_flags, uint16_t resp_code, int resp_code_valid,
+ uint16_t srr_flags, uint16_t srr_reject_code, uint8_t srr_explan);
/*
* Global Variables
*/
@@ -122,6 +127,16 @@
static DEFINE_MUTEX(qla_tgt_mutex);
static LIST_HEAD(qla_tgt_glist);
+/* This API intentionally takes dest as a parameter, rather than returning
+ * int value to avoid caller forgetting to issue wmb() after the store */
+void qlt_do_generation_tick(struct scsi_qla_host *vha, int *dest)
+{
+ scsi_qla_host_t *base_vha = pci_get_drvdata(vha->hw->pdev);
+ *dest = atomic_inc_return(&base_vha->generation_tick);
+ /* memory barrier */
+ wmb();
+}
+
/* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list) */
static struct qla_tgt_sess *qlt_find_sess_by_port_name(
struct qla_tgt *tgt,
@@ -381,14 +396,73 @@
struct qla_tgt *tgt = sess->tgt;
struct scsi_qla_host *vha = sess->vha;
struct qla_hw_data *ha = vha->hw;
+ unsigned long flags;
+ bool logout_started = false;
+ fc_port_t fcport;
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf084,
+ "%s: se_sess %p / sess %p from port %8phC loop_id %#04x"
+ " s_id %02x:%02x:%02x logout %d keep %d plogi %d\n",
+ __func__, sess->se_sess, sess, sess->port_name, sess->loop_id,
+ sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+ sess->logout_on_delete, sess->keep_nport_handle,
+ sess->plogi_ack_needed);
BUG_ON(!tgt);
+
+ if (sess->logout_on_delete) {
+ int rc;
+
+ memset(&fcport, 0, sizeof(fcport));
+ fcport.loop_id = sess->loop_id;
+ fcport.d_id = sess->s_id;
+ memcpy(fcport.port_name, sess->port_name, WWN_SIZE);
+ fcport.vha = vha;
+ fcport.tgt_session = sess;
+
+ rc = qla2x00_post_async_logout_work(vha, &fcport, NULL);
+ if (rc != QLA_SUCCESS)
+ ql_log(ql_log_warn, vha, 0xf085,
+ "Schedule logo failed sess %p rc %d\n",
+ sess, rc);
+ else
+ logout_started = true;
+ }
+
/*
* Release the target session for FC Nexus from fabric module code.
*/
if (sess->se_sess != NULL)
ha->tgt.tgt_ops->free_session(sess);
+ if (logout_started) {
+ bool traced = false;
+
+ while (!ACCESS_ONCE(sess->logout_completed)) {
+ if (!traced) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf086,
+ "%s: waiting for sess %p logout\n",
+ __func__, sess);
+ traced = true;
+ }
+ msleep(100);
+ }
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf087,
+ "%s: sess %p logout completed\n",
+ __func__, sess);
+ }
+
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+
+ if (sess->plogi_ack_needed)
+ qlt_send_notify_ack(vha, &sess->tm_iocb,
+ 0, 0, 0, 0, 0, 0);
+
+ list_del(&sess->sess_list_entry);
+
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf001,
"Unregistration of sess %p finished\n", sess);
@@ -409,9 +483,9 @@
vha->hw->tgt.tgt_ops->clear_nacl_from_fcport_map(sess);
- list_del(&sess->sess_list_entry);
- if (sess->deleted)
- list_del(&sess->del_list_entry);
+ if (!list_empty(&sess->del_list_entry))
+ list_del_init(&sess->del_list_entry);
+ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
INIT_WORK(&sess->free_work, qlt_free_session_done);
schedule_work(&sess->free_work);
@@ -431,10 +505,10 @@
loop_id = le16_to_cpu(n->u.isp24.nport_handle);
if (loop_id == 0xFFFF) {
-#if 0 /* FIXME: Re-enable Global event handling.. */
/* Global event */
- atomic_inc(&ha->tgt.qla_tgt->tgt_global_resets_count);
- qlt_clear_tgt_db(ha->tgt.qla_tgt);
+ atomic_inc(&vha->vha_tgt.qla_tgt->tgt_global_resets_count);
+ qlt_clear_tgt_db(vha->vha_tgt.qla_tgt);
+#if 0 /* FIXME: do we need to choose a session here? */
if (!list_empty(&ha->tgt.qla_tgt->sess_list)) {
sess = list_entry(ha->tgt.qla_tgt->sess_list.next,
typeof(*sess), sess_list_entry);
@@ -489,27 +563,38 @@
struct qla_tgt *tgt = sess->tgt;
uint32_t dev_loss_tmo = tgt->ha->port_down_retry_count + 5;
- if (sess->deleted)
- return;
+ if (sess->deleted) {
+ /* Upgrade to unconditional deletion in case it was temporary */
+ if (immediate && sess->deleted == QLA_SESS_DELETION_PENDING)
+ list_del(&sess->del_list_entry);
+ else
+ return;
+ }
ql_dbg(ql_dbg_tgt, sess->vha, 0xe001,
"Scheduling sess %p for deletion\n", sess);
- list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
- sess->deleted = 1;
- if (immediate)
+ if (immediate) {
dev_loss_tmo = 0;
+ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
+ list_add(&sess->del_list_entry, &tgt->del_sess_list);
+ } else {
+ sess->deleted = QLA_SESS_DELETION_PENDING;
+ list_add_tail(&sess->del_list_entry, &tgt->del_sess_list);
+ }
sess->expires = jiffies + dev_loss_tmo * HZ;
ql_dbg(ql_dbg_tgt, sess->vha, 0xe048,
- "qla_target(%d): session for port %8phC (loop ID %d) scheduled for "
- "deletion in %u secs (expires: %lu) immed: %d\n",
- sess->vha->vp_idx, sess->port_name, sess->loop_id, dev_loss_tmo,
- sess->expires, immediate);
+ "qla_target(%d): session for port %8phC (loop ID %d s_id %02x:%02x:%02x)"
+ " scheduled for deletion in %u secs (expires: %lu) immed: %d, logout: %d, gen: %#x\n",
+ sess->vha->vp_idx, sess->port_name, sess->loop_id,
+ sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa,
+ dev_loss_tmo, sess->expires, immediate, sess->logout_on_delete,
+ sess->generation);
if (immediate)
- schedule_delayed_work(&tgt->sess_del_work, 0);
+ mod_delayed_work(system_wq, &tgt->sess_del_work, 0);
else
schedule_delayed_work(&tgt->sess_del_work,
sess->expires - jiffies);
@@ -578,9 +663,9 @@
/* ha->hardware_lock supposed to be held on entry */
static void qlt_undelete_sess(struct qla_tgt_sess *sess)
{
- BUG_ON(!sess->deleted);
+ BUG_ON(sess->deleted != QLA_SESS_DELETION_PENDING);
- list_del(&sess->del_list_entry);
+ list_del_init(&sess->del_list_entry);
sess->deleted = 0;
}
@@ -599,7 +684,9 @@
del_list_entry);
elapsed = jiffies;
if (time_after_eq(elapsed, sess->expires)) {
- qlt_undelete_sess(sess);
+ /* No turning back */
+ list_del_init(&sess->del_list_entry);
+ sess->deleted = QLA_SESS_DELETION_IN_PROGRESS;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf004,
"Timeout: sess %p about to be deleted\n",
@@ -643,6 +730,13 @@
fcport->d_id.b.al_pa, fcport->d_id.b.area,
fcport->loop_id);
+ /* Cannot undelete at this point */
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ spin_unlock_irqrestore(&ha->hardware_lock,
+ flags);
+ return NULL;
+ }
+
if (sess->deleted)
qlt_undelete_sess(sess);
@@ -652,6 +746,9 @@
if (sess->local && !local)
sess->local = 0;
+
+ qlt_do_generation_tick(vha, &sess->generation);
+
spin_unlock_irqrestore(&ha->hardware_lock, flags);
return sess;
@@ -673,6 +770,14 @@
sess->s_id = fcport->d_id;
sess->loop_id = fcport->loop_id;
sess->local = local;
+ INIT_LIST_HEAD(&sess->del_list_entry);
+
+ /* Under normal circumstances we want to logout from firmware when
+ * session eventually ends and release corresponding nport handle.
+ * In the exception cases (e.g. when new PLOGI is waiting) corresponding
+ * code will adjust these flags as necessary. */
+ sess->logout_on_delete = 1;
+ sess->keep_nport_handle = 0;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf006,
"Adding sess %p to tgt %p via ->check_initiator_node_acl()\n",
@@ -705,6 +810,7 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
list_add_tail(&sess->sess_list_entry, &vha->vha_tgt.qla_tgt->sess_list);
vha->vha_tgt.qla_tgt->sess_count++;
+ qlt_do_generation_tick(vha, &sess->generation);
spin_unlock_irqrestore(&ha->hardware_lock, flags);
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf04b,
@@ -718,7 +824,7 @@
}
/*
- * Called from drivers/scsi/qla2xxx/qla_init.c:qla2x00_reg_remote_port()
+ * Called from qla2x00_reg_remote_port()
*/
void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)
{
@@ -750,6 +856,10 @@
mutex_unlock(&vha->vha_tgt.tgt_mutex);
spin_lock_irqsave(&ha->hardware_lock, flags);
+ } else if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ /* Point of no return */
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ return;
} else {
kref_get(&sess->se_sess->sess_kref);
@@ -780,27 +890,36 @@
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
-void qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport)
+/*
+ * max_gen - specifies maximum session generation
+ * at which this deletion requestion is still valid
+ */
+void
+qlt_fc_port_deleted(struct scsi_qla_host *vha, fc_port_t *fcport, int max_gen)
{
- struct qla_hw_data *ha = vha->hw;
struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
struct qla_tgt_sess *sess;
- unsigned long flags;
if (!vha->hw->tgt.tgt_ops)
return;
- if (!tgt || (fcport->port_type != FCT_INITIATOR))
+ if (!tgt)
return;
- spin_lock_irqsave(&ha->hardware_lock, flags);
if (tgt->tgt_stop) {
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
return;
}
sess = qlt_find_sess_by_port_name(tgt, fcport->port_name);
if (!sess) {
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ return;
+ }
+
+ if (max_gen - sess->generation < 0) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf092,
+ "Ignoring stale deletion request for se_sess %p / sess %p"
+ " for port %8phC, req_gen %d, sess_gen %d\n",
+ sess->se_sess, sess, sess->port_name, max_gen,
+ sess->generation);
return;
}
@@ -808,7 +927,6 @@
sess->local = 1;
qlt_schedule_sess_for_deletion(sess, false);
- spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
static inline int test_tgt_sess_count(struct qla_tgt *tgt)
@@ -1175,6 +1293,70 @@
FCP_TMF_CMPL, true);
}
+static int abort_cmd_for_tag(struct scsi_qla_host *vha, uint32_t tag)
+{
+ struct qla_tgt_sess_op *op;
+ struct qla_tgt_cmd *cmd;
+
+ spin_lock(&vha->cmd_list_lock);
+
+ list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
+ if (tag == op->atio.u.isp24.exchange_addr) {
+ op->aborted = true;
+ spin_unlock(&vha->cmd_list_lock);
+ return 1;
+ }
+ }
+
+ list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
+ if (tag == cmd->atio.u.isp24.exchange_addr) {
+ cmd->state = QLA_TGT_STATE_ABORTED;
+ spin_unlock(&vha->cmd_list_lock);
+ return 1;
+ }
+ }
+
+ spin_unlock(&vha->cmd_list_lock);
+ return 0;
+}
+
+/* drop cmds for the given lun
+ * XXX only looks for cmds on the port through which lun reset was recieved
+ * XXX does not go through the list of other port (which may have cmds
+ * for the same lun)
+ */
+static void abort_cmds_for_lun(struct scsi_qla_host *vha,
+ uint32_t lun, uint8_t *s_id)
+{
+ struct qla_tgt_sess_op *op;
+ struct qla_tgt_cmd *cmd;
+ uint32_t key;
+
+ key = sid_to_key(s_id);
+ spin_lock(&vha->cmd_list_lock);
+ list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
+ uint32_t op_key;
+ uint32_t op_lun;
+
+ op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
+ op_lun = scsilun_to_int(
+ (struct scsi_lun *)&op->atio.u.isp24.fcp_cmnd.lun);
+ if (op_key == key && op_lun == lun)
+ op->aborted = true;
+ }
+ list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
+ uint32_t cmd_key;
+ uint32_t cmd_lun;
+
+ cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
+ cmd_lun = scsilun_to_int(
+ (struct scsi_lun *)&cmd->atio.u.isp24.fcp_cmnd.lun);
+ if (cmd_key == key && cmd_lun == lun)
+ cmd->state = QLA_TGT_STATE_ABORTED;
+ }
+ spin_unlock(&vha->cmd_list_lock);
+}
+
/* ha->hardware_lock supposed to be held on entry */
static int __qlt_24xx_handle_abts(struct scsi_qla_host *vha,
struct abts_recv_from_24xx *abts, struct qla_tgt_sess *sess)
@@ -1199,8 +1381,19 @@
}
spin_unlock(&se_sess->sess_cmd_lock);
- if (!found_lun)
- return -ENOENT;
+ /* cmd not in LIO lists, look in qla list */
+ if (!found_lun) {
+ if (abort_cmd_for_tag(vha, abts->exchange_addr_to_abort)) {
+ /* send TASK_ABORT response immediately */
+ qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_CMPL, false);
+ return 0;
+ } else {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf081,
+ "unable to find cmd in driver or LIO for tag 0x%x\n",
+ abts->exchange_addr_to_abort);
+ return -ENOENT;
+ }
+ }
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00f,
"qla_target(%d): task abort (tag=%d)\n",
@@ -1284,6 +1477,11 @@
return;
}
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ qlt_24xx_send_abts_resp(vha, abts, FCP_TMF_REJECTED, false);
+ return;
+ }
+
rc = __qlt_24xx_handle_abts(vha, abts, sess);
if (rc != 0) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf054,
@@ -1726,20 +1924,6 @@
struct qla_hw_data *ha = vha->hw;
struct se_cmd *se_cmd = &cmd->se_cmd;
- if (unlikely(cmd->aborted)) {
- ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
- "qla_target(%d): terminating exchange for aborted cmd=%p (se_cmd=%p, tag=%lld)",
- vha->vp_idx, cmd, se_cmd, se_cmd->tag);
-
- cmd->state = QLA_TGT_STATE_ABORTED;
- cmd->cmd_flags |= BIT_6;
-
- qlt_send_term_exchange(vha, cmd, &cmd->atio, 0);
-
- /* !! At this point cmd could be already freed !! */
- return QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED;
- }
-
prm->cmd = cmd;
prm->tgt = tgt;
prm->rq_result = scsi_status;
@@ -2301,6 +2485,19 @@
unsigned long flags = 0;
int res;
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ if (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ cmd->state = QLA_TGT_STATE_PROCESSED;
+ if (cmd->sess->logout_completed)
+ /* no need to terminate. FW already freed exchange. */
+ qlt_abort_cmd_on_host_reset(cmd->vha, cmd);
+ else
+ qlt_send_term_exchange(vha, cmd, &cmd->atio, 1);
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
memset(&prm, 0, sizeof(prm));
qlt_check_srr_debug(cmd, &xmit_type);
@@ -2313,9 +2510,6 @@
res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
&full_req_cnt);
if (unlikely(res != 0)) {
- if (res == QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED)
- return 0;
-
return res;
}
@@ -2345,9 +2539,10 @@
res = qlt_build_ctio_crc2_pkt(&prm, vha);
else
res = qlt_24xx_build_ctio_pkt(&prm, vha);
- if (unlikely(res != 0))
+ if (unlikely(res != 0)) {
+ vha->req->cnt += full_req_cnt;
goto out_unmap_unlock;
-
+ }
pkt = (struct ctio7_to_24xx *)prm.pkt;
@@ -2461,7 +2656,8 @@
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (qla2x00_reset_active(vha) || cmd->reset_count != ha->chip_reset) {
+ if (qla2x00_reset_active(vha) || (cmd->reset_count != ha->chip_reset) ||
+ (cmd->sess && cmd->sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)) {
/*
* Either a chip reset is active or this request was from
* previous life, just abort the processing.
@@ -2485,8 +2681,11 @@
else
res = qlt_24xx_build_ctio_pkt(&prm, vha);
- if (unlikely(res != 0))
+ if (unlikely(res != 0)) {
+ vha->req->cnt += prm.req_cnt;
goto out_unlock_free_unmap;
+ }
+
pkt = (struct ctio7_to_24xx *)prm.pkt;
pkt->u.status0.flags |= __constant_cpu_to_le16(CTIO7_FLAGS_DATA_OUT |
CTIO7_FLAGS_STATUS_MODE_0);
@@ -2651,6 +2850,89 @@
/* If hardware_lock held on entry, might drop it, then reaquire */
/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
+static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha,
+ struct imm_ntfy_from_isp *ntfy)
+{
+ struct nack_to_isp *nack;
+ struct qla_hw_data *ha = vha->hw;
+ request_t *pkt;
+ int ret = 0;
+
+ ql_dbg(ql_dbg_tgt_tmr, vha, 0xe01c,
+ "Sending TERM ELS CTIO (ha=%p)\n", ha);
+
+ pkt = (request_t *)qla2x00_alloc_iocbs_ready(vha, NULL);
+ if (pkt == NULL) {
+ ql_dbg(ql_dbg_tgt, vha, 0xe080,
+ "qla_target(%d): %s failed: unable to allocate "
+ "request packet\n", vha->vp_idx, __func__);
+ return -ENOMEM;
+ }
+
+ pkt->entry_type = NOTIFY_ACK_TYPE;
+ pkt->entry_count = 1;
+ pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
+
+ nack = (struct nack_to_isp *)pkt;
+ nack->ox_id = ntfy->ox_id;
+
+ nack->u.isp24.nport_handle = ntfy->u.isp24.nport_handle;
+ if (le16_to_cpu(ntfy->u.isp24.status) == IMM_NTFY_ELS) {
+ nack->u.isp24.flags = ntfy->u.isp24.flags &
+ __constant_cpu_to_le32(NOTIFY24XX_FLAGS_PUREX_IOCB);
+ }
+
+ /* terminate */
+ nack->u.isp24.flags |=
+ __constant_cpu_to_le16(NOTIFY_ACK_FLAGS_TERMINATE);
+
+ nack->u.isp24.srr_rx_id = ntfy->u.isp24.srr_rx_id;
+ nack->u.isp24.status = ntfy->u.isp24.status;
+ nack->u.isp24.status_subcode = ntfy->u.isp24.status_subcode;
+ nack->u.isp24.fw_handle = ntfy->u.isp24.fw_handle;
+ nack->u.isp24.exchange_address = ntfy->u.isp24.exchange_address;
+ nack->u.isp24.srr_rel_offs = ntfy->u.isp24.srr_rel_offs;
+ nack->u.isp24.srr_ui = ntfy->u.isp24.srr_ui;
+ nack->u.isp24.vp_index = ntfy->u.isp24.vp_index;
+
+ qla2x00_start_iocbs(vha, vha->req);
+ return ret;
+}
+
+static void qlt_send_term_imm_notif(struct scsi_qla_host *vha,
+ struct imm_ntfy_from_isp *imm, int ha_locked)
+{
+ unsigned long flags = 0;
+ int rc;
+
+ if (qlt_issue_marker(vha, ha_locked) < 0)
+ return;
+
+ if (ha_locked) {
+ rc = __qlt_send_term_imm_notif(vha, imm);
+
+#if 0 /* Todo */
+ if (rc == -ENOMEM)
+ qlt_alloc_qfull_cmd(vha, imm, 0, 0);
+#endif
+ goto done;
+ }
+
+ spin_lock_irqsave(&vha->hw->hardware_lock, flags);
+ rc = __qlt_send_term_imm_notif(vha, imm);
+
+#if 0 /* Todo */
+ if (rc == -ENOMEM)
+ qlt_alloc_qfull_cmd(vha, imm, 0, 0);
+#endif
+
+done:
+ if (!ha_locked)
+ spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+}
+
+/* If hardware_lock held on entry, might drop it, then reaquire */
+/* This function sends the appropriate CTIO to ISP 2xxx or 24xx */
static int __qlt_send_term_exchange(struct scsi_qla_host *vha,
struct qla_tgt_cmd *cmd,
struct atio_from_isp *atio)
@@ -2715,7 +2997,7 @@
static void qlt_send_term_exchange(struct scsi_qla_host *vha,
struct qla_tgt_cmd *cmd, struct atio_from_isp *atio, int ha_locked)
{
- unsigned long flags;
+ unsigned long flags = 0;
int rc;
if (qlt_issue_marker(vha, ha_locked) < 0)
@@ -2731,17 +3013,18 @@
rc = __qlt_send_term_exchange(vha, cmd, atio);
if (rc == -ENOMEM)
qlt_alloc_qfull_cmd(vha, atio, 0, 0);
- spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
done:
if (cmd && ((cmd->state != QLA_TGT_STATE_ABORTED) ||
!cmd->cmd_sent_to_fw)) {
- if (!ha_locked && !in_interrupt())
- msleep(250); /* just in case */
-
- qlt_unmap_sg(vha, cmd);
+ if (cmd->sg_mapped)
+ qlt_unmap_sg(vha, cmd);
vha->hw->tgt.tgt_ops->free_cmd(cmd);
}
+
+ if (!ha_locked)
+ spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
+
return;
}
@@ -2792,6 +3075,24 @@
}
+void qlt_abort_cmd(struct qla_tgt_cmd *cmd)
+{
+ struct qla_tgt *tgt = cmd->tgt;
+ struct scsi_qla_host *vha = tgt->vha;
+ struct se_cmd *se_cmd = &cmd->se_cmd;
+
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf014,
+ "qla_target(%d): terminating exchange for aborted cmd=%p "
+ "(se_cmd=%p, tag=%llu)", vha->vp_idx, cmd, &cmd->se_cmd,
+ se_cmd->tag);
+
+ cmd->state = QLA_TGT_STATE_ABORTED;
+ cmd->cmd_flags |= BIT_6;
+
+ qlt_send_term_exchange(vha, cmd, &cmd->atio, 0);
+}
+EXPORT_SYMBOL(qlt_abort_cmd);
+
void qlt_free_cmd(struct qla_tgt_cmd *cmd)
{
struct qla_tgt_sess *sess = cmd->sess;
@@ -3015,7 +3316,7 @@
dump_stack();
}
- cmd->cmd_flags |= BIT_12;
+ cmd->cmd_flags |= BIT_17;
ha->tgt.tgt_ops->free_cmd(cmd);
}
@@ -3177,7 +3478,7 @@
skip_term:
if (cmd->state == QLA_TGT_STATE_PROCESSED) {
- ;
+ cmd->cmd_flags |= BIT_12;
} else if (cmd->state == QLA_TGT_STATE_NEED_DATA) {
int rx_status = 0;
@@ -3191,9 +3492,11 @@
ha->tgt.tgt_ops->handle_data(cmd);
return;
} else if (cmd->state == QLA_TGT_STATE_ABORTED) {
+ cmd->cmd_flags |= BIT_18;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf01e,
"Aborted command %p (tag %lld) finished\n", cmd, se_cmd->tag);
} else {
+ cmd->cmd_flags |= BIT_19;
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf05c,
"qla_target(%d): A command in state (%d) should "
"not return a CTIO complete\n", vha->vp_idx, cmd->state);
@@ -3205,7 +3508,6 @@
dump_stack();
}
-
ha->tgt.tgt_ops->free_cmd(cmd);
}
@@ -3263,6 +3565,13 @@
if (tgt->tgt_stop)
goto out_term;
+ if (cmd->state == QLA_TGT_STATE_ABORTED) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf082,
+ "cmd with tag %u is aborted\n",
+ cmd->atio.u.isp24.exchange_addr);
+ goto out_term;
+ }
+
cdb = &atio->u.isp24.fcp_cmnd.cdb[0];
cmd->se_cmd.tag = atio->u.isp24.exchange_addr;
cmd->unpacked_lun = scsilun_to_int(
@@ -3316,6 +3625,12 @@
static void qlt_do_work(struct work_struct *work)
{
struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
+ scsi_qla_host_t *vha = cmd->vha;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
+ list_del(&cmd->cmd_list);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
__qlt_do_work(cmd);
}
@@ -3345,6 +3660,11 @@
cmd->loop_id = sess->loop_id;
cmd->conf_compl_supported = sess->conf_compl_supported;
+ cmd->cmd_flags = 0;
+ cmd->jiffies_at_alloc = get_jiffies_64();
+
+ cmd->reset_count = vha->hw->chip_reset;
+
return cmd;
}
@@ -3362,14 +3682,25 @@
unsigned long flags;
uint8_t *s_id = op->atio.u.isp24.fcp_hdr.s_id;
+ spin_lock_irqsave(&vha->cmd_list_lock, flags);
+ list_del(&op->cmd_list);
+ spin_unlock_irqrestore(&vha->cmd_list_lock, flags);
+
+ if (op->aborted) {
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf083,
+ "sess_op with tag %u is aborted\n",
+ op->atio.u.isp24.exchange_addr);
+ goto out_term;
+ }
+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf022,
- "qla_target(%d): Unable to find wwn login"
- " (s_id %x:%x:%x), trying to create it manually\n",
- vha->vp_idx, s_id[0], s_id[1], s_id[2]);
+ "qla_target(%d): Unable to find wwn login"
+ " (s_id %x:%x:%x), trying to create it manually\n",
+ vha->vp_idx, s_id[0], s_id[1], s_id[2]);
if (op->atio.u.raw.entry_count > 1) {
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf023,
- "Dropping multy entry atio %p\n", &op->atio);
+ "Dropping multy entry atio %p\n", &op->atio);
goto out_term;
}
@@ -3434,10 +3765,25 @@
memcpy(&op->atio, atio, sizeof(*atio));
op->vha = vha;
+
+ spin_lock(&vha->cmd_list_lock);
+ list_add_tail(&op->cmd_list, &vha->qla_sess_op_cmd_list);
+ spin_unlock(&vha->cmd_list_lock);
+
INIT_WORK(&op->work, qlt_create_sess_from_atio);
queue_work(qla_tgt_wq, &op->work);
return 0;
}
+
+ /* Another WWN used to have our s_id. Our PLOGI scheduled its
+ * session deletion, but it's still in sess_del_work wq */
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ ql_dbg(ql_dbg_io, vha, 0x3061,
+ "New command while old session %p is being deleted\n",
+ sess);
+ return -EFAULT;
+ }
+
/*
* Do kref_get() before returning + dropping qla_hw_data->hardware_lock.
*/
@@ -3451,13 +3797,13 @@
return -ENOMEM;
}
- cmd->cmd_flags = 0;
- cmd->jiffies_at_alloc = get_jiffies_64();
-
- cmd->reset_count = vha->hw->chip_reset;
-
cmd->cmd_in_wq = 1;
cmd->cmd_flags |= BIT_0;
+
+ spin_lock(&vha->cmd_list_lock);
+ list_add_tail(&cmd->cmd_list, &vha->qla_cmd_list);
+ spin_unlock(&vha->cmd_list_lock);
+
INIT_WORK(&cmd->work, qlt_do_work);
queue_work(qla_tgt_wq, &cmd->work);
return 0;
@@ -3471,6 +3817,7 @@
struct scsi_qla_host *vha = sess->vha;
struct qla_hw_data *ha = vha->hw;
struct qla_tgt_mgmt_cmd *mcmd;
+ struct atio_from_isp *a = (struct atio_from_isp *)iocb;
int res;
uint8_t tmr_func;
@@ -3511,6 +3858,7 @@
ql_dbg(ql_dbg_tgt_tmr, vha, 0x10002,
"qla_target(%d): LUN_RESET received\n", sess->vha->vp_idx);
tmr_func = TMR_LUN_RESET;
+ abort_cmds_for_lun(vha, lun, a->u.isp24.fcp_hdr.s_id);
break;
case QLA_TGT_CLEAR_TS:
@@ -3599,6 +3947,9 @@
sizeof(struct atio_from_isp));
}
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS)
+ return -EFAULT;
+
return qlt_issue_task_mgmt(sess, unpacked_lun, fn, iocb, 0);
}
@@ -3664,22 +4015,280 @@
return __qlt_abort_task(vha, iocb, sess);
}
+void qlt_logo_completion_handler(fc_port_t *fcport, int rc)
+{
+ if (fcport->tgt_session) {
+ if (rc != MBS_COMMAND_COMPLETE) {
+ ql_dbg(ql_dbg_tgt_mgt, fcport->vha, 0xf093,
+ "%s: se_sess %p / sess %p from"
+ " port %8phC loop_id %#04x s_id %02x:%02x:%02x"
+ " LOGO failed: %#x\n",
+ __func__,
+ fcport->tgt_session->se_sess,
+ fcport->tgt_session,
+ fcport->port_name, fcport->loop_id,
+ fcport->d_id.b.domain, fcport->d_id.b.area,
+ fcport->d_id.b.al_pa, rc);
+ }
+
+ fcport->tgt_session->logout_completed = 1;
+ }
+}
+
+static void qlt_swap_imm_ntfy_iocb(struct imm_ntfy_from_isp *a,
+ struct imm_ntfy_from_isp *b)
+{
+ struct imm_ntfy_from_isp tmp;
+ memcpy(&tmp, a, sizeof(struct imm_ntfy_from_isp));
+ memcpy(a, b, sizeof(struct imm_ntfy_from_isp));
+ memcpy(b, &tmp, sizeof(struct imm_ntfy_from_isp));
+}
+
+/*
+* ha->hardware_lock supposed to be held on entry (to protect tgt->sess_list)
+*
+* Schedules sessions with matching port_id/loop_id but different wwn for
+* deletion. Returns existing session with matching wwn if present.
+* Null otherwise.
+*/
+static struct qla_tgt_sess *
+qlt_find_sess_invalidate_other(struct qla_tgt *tgt, uint64_t wwn,
+ port_id_t port_id, uint16_t loop_id)
+{
+ struct qla_tgt_sess *sess = NULL, *other_sess;
+ uint64_t other_wwn;
+
+ list_for_each_entry(other_sess, &tgt->sess_list, sess_list_entry) {
+
+ other_wwn = wwn_to_u64(other_sess->port_name);
+
+ if (wwn == other_wwn) {
+ WARN_ON(sess);
+ sess = other_sess;
+ continue;
+ }
+
+ /* find other sess with nport_id collision */
+ if (port_id.b24 == other_sess->s_id.b24) {
+ if (loop_id != other_sess->loop_id) {
+ ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000c,
+ "Invalidating sess %p loop_id %d wwn %llx.\n",
+ other_sess, other_sess->loop_id, other_wwn);
+
+ /*
+ * logout_on_delete is set by default, but another
+ * session that has the same s_id/loop_id combo
+ * might have cleared it when requested this session
+ * deletion, so don't touch it
+ */
+ qlt_schedule_sess_for_deletion(other_sess, true);
+ } else {
+ /*
+ * Another wwn used to have our s_id/loop_id
+ * combo - kill the session, but don't log out
+ */
+ sess->logout_on_delete = 0;
+ qlt_schedule_sess_for_deletion(other_sess,
+ true);
+ }
+ continue;
+ }
+
+ /* find other sess with nport handle collision */
+ if (loop_id == other_sess->loop_id) {
+ ql_dbg(ql_dbg_tgt_tmr, tgt->vha, 0x1000d,
+ "Invalidating sess %p loop_id %d wwn %llx.\n",
+ other_sess, other_sess->loop_id, other_wwn);
+
+ /* Same loop_id but different s_id
+ * Ok to kill and logout */
+ qlt_schedule_sess_for_deletion(other_sess, true);
+ }
+ }
+
+ return sess;
+}
+
+/* Abort any commands for this s_id waiting on qla_tgt_wq workqueue */
+static int abort_cmds_for_s_id(struct scsi_qla_host *vha, port_id_t *s_id)
+{
+ struct qla_tgt_sess_op *op;
+ struct qla_tgt_cmd *cmd;
+ uint32_t key;
+ int count = 0;
+
+ key = (((u32)s_id->b.domain << 16) |
+ ((u32)s_id->b.area << 8) |
+ ((u32)s_id->b.al_pa));
+
+ spin_lock(&vha->cmd_list_lock);
+ list_for_each_entry(op, &vha->qla_sess_op_cmd_list, cmd_list) {
+ uint32_t op_key = sid_to_key(op->atio.u.isp24.fcp_hdr.s_id);
+ if (op_key == key) {
+ op->aborted = true;
+ count++;
+ }
+ }
+ list_for_each_entry(cmd, &vha->qla_cmd_list, cmd_list) {
+ uint32_t cmd_key = sid_to_key(cmd->atio.u.isp24.fcp_hdr.s_id);
+ if (cmd_key == key) {
+ cmd->state = QLA_TGT_STATE_ABORTED;
+ count++;
+ }
+ }
+ spin_unlock(&vha->cmd_list_lock);
+
+ return count;
+}
+
/*
* ha->hardware_lock supposed to be held on entry. Might drop it, then reaquire
*/
static int qlt_24xx_handle_els(struct scsi_qla_host *vha,
struct imm_ntfy_from_isp *iocb)
{
+ struct qla_tgt *tgt = vha->vha_tgt.qla_tgt;
+ struct qla_hw_data *ha = vha->hw;
+ struct qla_tgt_sess *sess = NULL;
+ uint64_t wwn;
+ port_id_t port_id;
+ uint16_t loop_id;
+ uint16_t wd3_lo;
int res = 0;
+ wwn = wwn_to_u64(iocb->u.isp24.port_name);
+
+ port_id.b.domain = iocb->u.isp24.port_id[2];
+ port_id.b.area = iocb->u.isp24.port_id[1];
+ port_id.b.al_pa = iocb->u.isp24.port_id[0];
+ port_id.b.rsvd_1 = 0;
+
+ loop_id = le16_to_cpu(iocb->u.isp24.nport_handle);
+
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf026,
"qla_target(%d): Port ID: 0x%3phC ELS opcode: 0x%02x\n",
vha->vp_idx, iocb->u.isp24.port_id, iocb->u.isp24.status_subcode);
+ /* res = 1 means ack at the end of thread
+ * res = 0 means ack async/later.
+ */
switch (iocb->u.isp24.status_subcode) {
case ELS_PLOGI:
- case ELS_FLOGI:
+
+ /* Mark all stale commands in qla_tgt_wq for deletion */
+ abort_cmds_for_s_id(vha, &port_id);
+
+ if (wwn)
+ sess = qlt_find_sess_invalidate_other(tgt, wwn,
+ port_id, loop_id);
+
+ if (!sess || IS_SW_RESV_ADDR(sess->s_id)) {
+ res = 1;
+ break;
+ }
+
+ if (sess->plogi_ack_needed) {
+ /*
+ * Initiator sent another PLOGI before last PLOGI could
+ * finish. Swap plogi iocbs and terminate old one
+ * without acking, new one will get acked when session
+ * deletion completes.
+ */
+ ql_log(ql_log_warn, sess->vha, 0xf094,
+ "sess %p received double plogi.\n", sess);
+
+ qlt_swap_imm_ntfy_iocb(iocb, &sess->tm_iocb);
+
+ qlt_send_term_imm_notif(vha, iocb, 1);
+
+ res = 0;
+ break;
+ }
+
+ res = 0;
+
+ /*
+ * Save immediate Notif IOCB for Ack when sess is done
+ * and being deleted.
+ */
+ memcpy(&sess->tm_iocb, iocb, sizeof(sess->tm_iocb));
+ sess->plogi_ack_needed = 1;
+
+ /*
+ * Under normal circumstances we want to release nport handle
+ * during LOGO process to avoid nport handle leaks inside FW.
+ * The exception is when LOGO is done while another PLOGI with
+ * the same nport handle is waiting as might be the case here.
+ * Note: there is always a possibily of a race where session
+ * deletion has already started for other reasons (e.g. ACL
+ * removal) and now PLOGI arrives:
+ * 1. if PLOGI arrived in FW after nport handle has been freed,
+ * FW must have assigned this PLOGI a new/same handle and we
+ * can proceed ACK'ing it as usual when session deletion
+ * completes.
+ * 2. if PLOGI arrived in FW before LOGO with LCF_FREE_NPORT
+ * bit reached it, the handle has now been released. We'll
+ * get an error when we ACK this PLOGI. Nothing will be sent
+ * back to initiator. Initiator should eventually retry
+ * PLOGI and situation will correct itself.
+ */
+ sess->keep_nport_handle = ((sess->loop_id == loop_id) &&
+ (sess->s_id.b24 == port_id.b24));
+ qlt_schedule_sess_for_deletion(sess, true);
+ break;
+
case ELS_PRLI:
+ wd3_lo = le16_to_cpu(iocb->u.isp24.u.prli.wd3_lo);
+
+ if (wwn)
+ sess = qlt_find_sess_invalidate_other(tgt, wwn, port_id,
+ loop_id);
+
+ if (sess != NULL) {
+ if (sess->deleted) {
+ /*
+ * Impatient initiator sent PRLI before last
+ * PLOGI could finish. Will force him to re-try,
+ * while last one finishes.
+ */
+ ql_log(ql_log_warn, sess->vha, 0xf095,
+ "sess %p PRLI received, before plogi ack.\n",
+ sess);
+ qlt_send_term_imm_notif(vha, iocb, 1);
+ res = 0;
+ break;
+ }
+
+ /*
+ * This shouldn't happen under normal circumstances,
+ * since we have deleted the old session during PLOGI
+ */
+ ql_dbg(ql_dbg_tgt_mgt, vha, 0xf096,
+ "PRLI (loop_id %#04x) for existing sess %p (loop_id %#04x)\n",
+ sess->loop_id, sess, iocb->u.isp24.nport_handle);
+
+ sess->local = 0;
+ sess->loop_id = loop_id;
+ sess->s_id = port_id;
+
+ if (wd3_lo & BIT_7)
+ sess->conf_compl_supported = 1;
+
+ }
+ res = 1; /* send notify ack */
+
+ /* Make session global (not used in fabric mode) */
+ if (ha->current_topology != ISP_CFG_F) {
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ } else {
+ /* todo: else - create sess here. */
+ res = 1; /* send notify ack */
+ }
+
+ break;
+
case ELS_LOGO:
case ELS_PRLO:
res = qlt_reset(vha, iocb, QLA_TGT_NEXUS_LOSS_SESS);
@@ -3697,6 +4306,7 @@
break;
}
+ case ELS_FLOGI: /* should never happen */
default:
ql_dbg(ql_dbg_tgt_mgt, vha, 0xf061,
"qla_target(%d): Unsupported ELS command %x "
@@ -5012,6 +5622,11 @@
if (!sess)
goto out_term;
} else {
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ sess = NULL;
+ goto out_term;
+ }
+
kref_get(&sess->se_sess->sess_kref);
}
@@ -5066,6 +5681,11 @@
if (!sess)
goto out_term;
} else {
+ if (sess->deleted == QLA_SESS_DELETION_IN_PROGRESS) {
+ sess = NULL;
+ goto out_term;
+ }
+
kref_get(&sess->se_sess->sess_kref);
}
@@ -5552,6 +6172,7 @@
/* Adjust ring index */
WRT_REG_DWORD(ISP_ATIO_Q_OUT(vha), ha->tgt.atio_ring_index);
+ RD_REG_DWORD_RELAXED(ISP_ATIO_Q_OUT(vha));
}
void
@@ -5793,7 +6414,7 @@
if (!QLA_TGT_MODE_ENABLED())
return;
- if (ha->mqenable || IS_QLA83XX(ha)) {
+ if (ha->mqenable || IS_QLA83XX(ha) || IS_QLA27XX(ha)) {
ISP_ATIO_Q_IN(base_vha) = &ha->mqiobase->isp25mq.atio_q_in;
ISP_ATIO_Q_OUT(base_vha) = &ha->mqiobase->isp25mq.atio_q_out;
} else {
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index 985d76d..bca584a 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -167,7 +167,24 @@
uint32_t srr_rel_offs;
uint16_t srr_ui;
uint16_t srr_ox_id;
- uint8_t reserved_4[19];
+ union {
+ struct {
+ uint8_t node_name[8];
+ } plogi; /* PLOGI/ADISC/PDISC */
+ struct {
+ /* PRLI word 3 bit 0-15 */
+ uint16_t wd3_lo;
+ uint8_t resv0[6];
+ } prli;
+ struct {
+ uint8_t port_id[3];
+ uint8_t resv1;
+ uint16_t nport_handle;
+ uint16_t resv2;
+ } req_els;
+ } u;
+ uint8_t port_name[8];
+ uint8_t resv3[3];
uint8_t vp_index;
uint32_t reserved_5;
uint8_t port_id[3];
@@ -234,6 +251,7 @@
uint8_t reserved[2];
uint16_t ox_id;
} __packed;
+#define NOTIFY_ACK_FLAGS_TERMINATE BIT_3
#define NOTIFY_ACK_SRR_FLAGS_ACCEPT 0
#define NOTIFY_ACK_SRR_FLAGS_REJECT 1
@@ -790,13 +808,6 @@
#define FC_TM_REJECT 4
#define FC_TM_FAILED 5
-/*
- * Error code of qlt_pre_xmit_response() meaning that cmd's exchange was
- * terminated, so no more actions is needed and success should be returned
- * to target.
- */
-#define QLA_TGT_PRE_XMIT_RESP_CMD_ABORTED 0x1717
-
#if (BITS_PER_LONG > 32) || defined(CONFIG_HIGHMEM64G)
#define pci_dma_lo32(a) (a & 0xffffffff)
#define pci_dma_hi32(a) ((((a) >> 16)>>16) & 0xffffffff)
@@ -874,6 +885,15 @@
struct scsi_qla_host *vha;
struct atio_from_isp atio;
struct work_struct work;
+ struct list_head cmd_list;
+ bool aborted;
+};
+
+enum qla_sess_deletion {
+ QLA_SESS_DELETION_NONE = 0,
+ QLA_SESS_DELETION_PENDING = 1, /* hopefully we can get rid of
+ * this one */
+ QLA_SESS_DELETION_IN_PROGRESS = 2,
};
/*
@@ -884,8 +904,15 @@
port_id_t s_id;
unsigned int conf_compl_supported:1;
- unsigned int deleted:1;
+ unsigned int deleted:2;
unsigned int local:1;
+ unsigned int logout_on_delete:1;
+ unsigned int plogi_ack_needed:1;
+ unsigned int keep_nport_handle:1;
+
+ unsigned char logout_completed;
+
+ int generation;
struct se_session *se_sess;
struct scsi_qla_host *vha;
@@ -897,6 +924,10 @@
uint8_t port_name[WWN_SIZE];
struct work_struct free_work;
+
+ union {
+ struct imm_ntfy_from_isp tm_iocb;
+ };
};
struct qla_tgt_cmd {
@@ -912,7 +943,6 @@
unsigned int conf_compl_supported:1;
unsigned int sg_mapped:1;
unsigned int free_sg:1;
- unsigned int aborted:1; /* Needed in case of SRR */
unsigned int write_data_transferred:1;
unsigned int ctx_dsd_alloced:1;
unsigned int q_full:1;
@@ -961,6 +991,9 @@
* BIT_14 - Back end data received/sent.
* BIT_15 - SRR prepare ctio
* BIT_16 - complete free
+ * BIT_17 - flush - qlt_abort_cmd_on_host_reset
+ * BIT_18 - completion w/abort status
+ * BIT_19 - completion w/unknown status
*/
uint32_t cmd_flags;
};
@@ -1026,6 +1059,10 @@
struct qla_tgt_cmd *cmd;
};
+/* Check for Switch reserved address */
+#define IS_SW_RESV_ADDR(_s_id) \
+ ((_s_id.b.domain == 0xff) && (_s_id.b.area == 0xfc))
+
#define QLA_TGT_XMIT_DATA 1
#define QLA_TGT_XMIT_STATUS 2
#define QLA_TGT_XMIT_ALL (QLA_TGT_XMIT_STATUS|QLA_TGT_XMIT_DATA)
@@ -1043,7 +1080,7 @@
extern void qlt_lport_deregister(struct scsi_qla_host *);
extern void qlt_unreg_sess(struct qla_tgt_sess *);
extern void qlt_fc_port_added(struct scsi_qla_host *, fc_port_t *);
-extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *);
+extern void qlt_fc_port_deleted(struct scsi_qla_host *, fc_port_t *, int);
extern int __init qlt_init(void);
extern void qlt_exit(void);
extern void qlt_update_vp_map(struct scsi_qla_host *, int);
@@ -1073,12 +1110,23 @@
ha->host->active_mode |= MODE_INITIATOR;
}
+static inline uint32_t sid_to_key(const uint8_t *s_id)
+{
+ uint32_t key;
+
+ key = (((unsigned long)s_id[0] << 16) |
+ ((unsigned long)s_id[1] << 8) |
+ (unsigned long)s_id[2]);
+ return key;
+}
+
/*
* Exported symbols from qla_target.c LLD logic used by qla2xxx code..
*/
extern void qlt_response_pkt_all_vps(struct scsi_qla_host *, response_t *);
extern int qlt_rdy_to_xfer(struct qla_tgt_cmd *);
extern int qlt_xmit_response(struct qla_tgt_cmd *, int, uint8_t);
+extern void qlt_abort_cmd(struct qla_tgt_cmd *);
extern void qlt_xmit_tm_rsp(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_mcmd(struct qla_tgt_mgmt_cmd *);
extern void qlt_free_cmd(struct qla_tgt_cmd *cmd);
@@ -1109,5 +1157,7 @@
extern irqreturn_t qla83xx_msix_atio_q(int, void *);
extern void qlt_83xx_iospace_config(struct qla_hw_data *);
extern int qlt_free_qfull_cmds(struct scsi_qla_host *);
+extern void qlt_logo_completion_handler(fc_port_t *, int);
+extern void qlt_do_generation_tick(struct scsi_qla_host *, int *);
#endif /* __QLA_TARGET_H */
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index d9a8c60..9224a06 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -374,7 +374,7 @@
{
struct qla_tgt_cmd *cmd = container_of(se_cmd,
struct qla_tgt_cmd, se_cmd);
-
+ cmd->cmd_flags |= BIT_3;
cmd->bufflen = se_cmd->data_length;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
@@ -405,7 +405,7 @@
se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) {
spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
wait_for_completion_timeout(&se_cmd->t_transport_stop_comp,
- 3000);
+ 3 * HZ);
return 0;
}
spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
@@ -541,12 +541,10 @@
cmd->cmd_flags |= BIT_4;
cmd->bufflen = se_cmd->data_length;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
- cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
cmd->sg_cnt = se_cmd->t_data_nents;
cmd->sg = se_cmd->t_data_sg;
cmd->offset = 0;
- cmd->cmd_flags |= BIT_3;
cmd->prot_sg_cnt = se_cmd->t_prot_nents;
cmd->prot_sg = se_cmd->t_prot_sg;
@@ -571,7 +569,6 @@
cmd->sg_cnt = 0;
cmd->offset = 0;
cmd->dma_data_direction = target_reverse_dma_direction(se_cmd);
- cmd->aborted = (se_cmd->transport_state & CMD_T_ABORTED);
if (cmd->cmd_flags & BIT_5) {
pr_crit("Bit_5 already set for cmd = %p.\n", cmd);
dump_stack();
@@ -636,14 +633,7 @@
{
struct qla_tgt_cmd *cmd = container_of(se_cmd,
struct qla_tgt_cmd, se_cmd);
- struct scsi_qla_host *vha = cmd->vha;
- struct qla_hw_data *ha = vha->hw;
-
- if (!cmd->sg_mapped)
- return;
-
- pci_unmap_sg(ha->pdev, cmd->sg, cmd->sg_cnt, cmd->dma_data_direction);
- cmd->sg_mapped = 0;
+ qlt_abort_cmd(cmd);
}
static void tcm_qla2xxx_clear_sess_lookup(struct tcm_qla2xxx_lport *,
@@ -1149,9 +1139,7 @@
return NULL;
}
- key = (((unsigned long)s_id[0] << 16) |
- ((unsigned long)s_id[1] << 8) |
- (unsigned long)s_id[2]);
+ key = sid_to_key(s_id);
pr_debug("find_sess_by_s_id: 0x%06x\n", key);
se_nacl = btree_lookup32(&lport->lport_fcport_map, key);
@@ -1186,9 +1174,7 @@
void *slot;
int rc;
- key = (((unsigned long)s_id[0] << 16) |
- ((unsigned long)s_id[1] << 8) |
- (unsigned long)s_id[2]);
+ key = sid_to_key(s_id);
pr_debug("set_sess_by_s_id: %06x\n", key);
slot = btree_lookup32(&lport->lport_fcport_map, key);
@@ -1544,6 +1530,10 @@
}
sess->conf_compl_supported = conf_compl_supported;
+
+ /* Reset logout parameters to default */
+ sess->logout_on_delete = 1;
+ sess->keep_nport_handle = 0;
}
/*
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 106884a..6457a8a 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -26,7 +26,6 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/jiffies.h>
-#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -944,7 +943,7 @@
scmd->sdb.length);
scmd->sdb.table.sgl = &ses->sense_sgl;
scmd->sc_data_direction = DMA_FROM_DEVICE;
- scmd->sdb.table.nents = 1;
+ scmd->sdb.table.nents = scmd->sdb.table.orig_nents = 1;
scmd->cmnd[0] = REQUEST_SENSE;
scmd->cmnd[4] = scmd->sdb.length;
scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]);
@@ -2523,33 +2522,3 @@
}
}
EXPORT_SYMBOL(scsi_build_sense_buffer);
-
-/**
- * scsi_set_sense_information - set the information field in a
- * formatted sense data buffer
- * @buf: Where to build sense data
- * @info: 64-bit information value to be set
- *
- **/
-void scsi_set_sense_information(u8 *buf, u64 info)
-{
- if ((buf[0] & 0x7f) == 0x72) {
- u8 *ucp, len;
-
- len = buf[7];
- ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0);
- if (!ucp) {
- buf[7] = len + 0xa;
- ucp = buf + 8 + len;
- }
- ucp[0] = 0;
- ucp[1] = 0xa;
- ucp[2] = 0x80; /* Valid bit */
- ucp[3] = 0;
- put_unaligned_be64(info, &ucp[4]);
- } else if ((buf[0] & 0x7f) == 0x70) {
- buf[0] |= 0x80;
- put_unaligned_be64(info, &buf[3]);
- }
-}
-EXPORT_SYMBOL(scsi_set_sense_information);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index b1a2631..448ebda 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -583,7 +583,7 @@
static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq)
{
- if (mq && sdb->table.nents <= SCSI_MAX_SG_SEGMENTS)
+ if (mq && sdb->table.orig_nents <= SCSI_MAX_SG_SEGMENTS)
return;
__sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free);
}
@@ -597,8 +597,8 @@
if (mq) {
if (nents <= SCSI_MAX_SG_SEGMENTS) {
- sdb->table.nents = nents;
- sg_init_table(sdb->table.sgl, sdb->table.nents);
+ sdb->table.nents = sdb->table.orig_nents = nents;
+ sg_init_table(sdb->table.sgl, nents);
return 0;
}
first_chunk = sdb->table.sgl;
diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index 9e43ae1..e4b7998 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -217,15 +217,15 @@
{
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
struct scsi_device *sdev = to_scsi_device(dev);
- int err;
+ int err = 0;
- err = blk_pre_runtime_suspend(sdev->request_queue);
- if (err)
- return err;
- if (pm && pm->runtime_suspend)
+ if (pm && pm->runtime_suspend) {
+ err = blk_pre_runtime_suspend(sdev->request_queue);
+ if (err)
+ return err;
err = pm->runtime_suspend(dev);
- blk_post_runtime_suspend(sdev->request_queue, err);
-
+ blk_post_runtime_suspend(sdev->request_queue, err);
+ }
return err;
}
@@ -248,11 +248,11 @@
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
int err = 0;
- blk_pre_runtime_resume(sdev->request_queue);
- if (pm && pm->runtime_resume)
+ if (pm && pm->runtime_resume) {
+ blk_pre_runtime_resume(sdev->request_queue);
err = pm->runtime_resume(dev);
- blk_post_runtime_resume(sdev->request_queue, err);
-
+ blk_post_runtime_resume(sdev->request_queue, err);
+ }
return err;
}
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 3b2fcb4..a20da8c 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2770,9 +2770,9 @@
max_xfer = sdkp->max_xfer_blocks;
max_xfer <<= ilog2(sdp->sector_size) - 9;
- max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue),
- max_xfer);
- blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer);
+ sdkp->disk->queue->limits.max_sectors =
+ min_not_zero(queue_max_hw_sectors(sdkp->disk->queue), max_xfer);
+
set_capacity(disk, sdkp->capacity);
sd_config_write_same(sdkp);
kfree(buffer);
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 285f775..7dbbb29 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -949,7 +949,7 @@
{
struct Scsi_Host *shost;
struct virtio_scsi *vscsi;
- int err, host_prot;
+ int err;
u32 sg_elems, num_targets;
u32 cmd_per_lun;
u32 num_queues;
@@ -1009,6 +1009,8 @@
#ifdef CONFIG_BLK_DEV_INTEGRITY
if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) {
+ int host_prot;
+
host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION |
SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION |
SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION;
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 0cae169..b0f30fb 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -612,7 +612,7 @@
config SPI_ZYNQMP_GQSPI
tristate "Xilinx ZynqMP GQSPI controller"
- depends on SPI_MASTER
+ depends on SPI_MASTER && HAS_DMA
help
Enables Xilinx GQSPI controller driver for Zynq UltraScale+ MPSoC.
diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c
index 788e2b1..acce90a 100644
--- a/drivers/spi/spi-img-spfi.c
+++ b/drivers/spi/spi-img-spfi.c
@@ -40,6 +40,7 @@
#define SPFI_CONTROL_SOFT_RESET BIT(11)
#define SPFI_CONTROL_SEND_DMA BIT(10)
#define SPFI_CONTROL_GET_DMA BIT(9)
+#define SPFI_CONTROL_SE BIT(8)
#define SPFI_CONTROL_TMODE_SHIFT 5
#define SPFI_CONTROL_TMODE_MASK 0x7
#define SPFI_CONTROL_TMODE_SINGLE 0
@@ -491,6 +492,7 @@
else if (xfer->tx_nbits == SPI_NBITS_QUAD &&
xfer->rx_nbits == SPI_NBITS_QUAD)
val |= SPFI_CONTROL_TMODE_QUAD << SPFI_CONTROL_TMODE_SHIFT;
+ val |= SPFI_CONTROL_SE;
spfi_writel(spfi, val, SPFI_CONTROL);
}
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index eb7d3a6..f9deb84 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -201,8 +201,9 @@
{
struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
- if (spi_imx->dma_is_inited && (transfer->len > spi_imx->rx_wml)
- && (transfer->len > spi_imx->tx_wml))
+ if (spi_imx->dma_is_inited
+ && transfer->len > spi_imx->rx_wml * sizeof(u32)
+ && transfer->len > spi_imx->tx_wml * sizeof(u32))
return true;
return false;
}
diff --git a/drivers/spi/spi-zynqmp-gqspi.c b/drivers/spi/spi-zynqmp-gqspi.c
index 87b20a5..f23f36e 100644
--- a/drivers/spi/spi-zynqmp-gqspi.c
+++ b/drivers/spi/spi-zynqmp-gqspi.c
@@ -214,6 +214,7 @@
case GQSPI_SELECT_FLASH_CS_BOTH:
instanceptr->genfifocs = GQSPI_GENFIFO_CS_LOWER |
GQSPI_GENFIFO_CS_UPPER;
+ break;
case GQSPI_SELECT_FLASH_CS_UPPER:
instanceptr->genfifocs = GQSPI_GENFIFO_CS_UPPER;
break;
diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
index dd616ff..c7de641 100644
--- a/drivers/spi/spidev.c
+++ b/drivers/spi/spidev.c
@@ -693,6 +693,7 @@
#ifdef CONFIG_OF
static const struct of_device_id spidev_dt_ids[] = {
{ .compatible = "rohm,dh2228fv" },
+ { .compatible = "lineartechnology,ltc2488" },
{},
};
MODULE_DEVICE_TABLE(of, spidev_dt_ids);
diff --git a/drivers/spmi/Kconfig b/drivers/spmi/Kconfig
index 982580a..0d3b70b 100644
--- a/drivers/spmi/Kconfig
+++ b/drivers/spmi/Kconfig
@@ -12,7 +12,7 @@
config SPMI_MSM_PMIC_ARB
tristate "Qualcomm MSM SPMI Controller (PMIC Arbiter)"
- depends on IRQ_DOMAIN
+ select IRQ_DOMAIN
depends on ARCH_QCOM || COMPILE_TEST
depends on HAS_IOMEM
default ARCH_QCOM
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index d7119db..a4d8c04 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -575,6 +575,22 @@
return 0;
}
+static int qpnpint_get_irqchip_state(struct irq_data *d,
+ enum irqchip_irq_state which,
+ bool *state)
+{
+ u8 irq = d->hwirq >> 8;
+ u8 status = 0;
+
+ if (which != IRQCHIP_STATE_LINE_LEVEL)
+ return -EINVAL;
+
+ qpnpint_spmi_read(d, QPNPINT_REG_RT_STS, &status, 1);
+ *state = !!(status & BIT(irq));
+
+ return 0;
+}
+
static struct irq_chip pmic_arb_irqchip = {
.name = "pmic_arb",
.irq_enable = qpnpint_irq_enable,
@@ -582,6 +598,7 @@
.irq_mask = qpnpint_irq_mask,
.irq_unmask = qpnpint_irq_unmask,
.irq_set_type = qpnpint_irq_set_type,
+ .irq_get_irqchip_state = qpnpint_get_irqchip_state,
.flags = IRQCHIP_MASK_ON_SUSPEND
| IRQCHIP_SKIP_SET_WAKE,
};
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index 9493843..11467e1 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -22,6 +22,8 @@
#include <linux/pm_runtime.h>
#include <dt-bindings/spmi/spmi.h>
+#define CREATE_TRACE_POINTS
+#include <trace/events/spmi.h>
static DEFINE_IDA(ctrl_ida);
@@ -96,28 +98,42 @@
static inline int
spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid)
{
+ int ret;
+
if (!ctrl || !ctrl->cmd || ctrl->dev.type != &spmi_ctrl_type)
return -EINVAL;
- return ctrl->cmd(ctrl, opcode, sid);
+ ret = ctrl->cmd(ctrl, opcode, sid);
+ trace_spmi_cmd(opcode, sid, ret);
+ return ret;
}
static inline int spmi_read_cmd(struct spmi_controller *ctrl, u8 opcode,
u8 sid, u16 addr, u8 *buf, size_t len)
{
+ int ret;
+
if (!ctrl || !ctrl->read_cmd || ctrl->dev.type != &spmi_ctrl_type)
return -EINVAL;
- return ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len);
+ trace_spmi_read_begin(opcode, sid, addr);
+ ret = ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len);
+ trace_spmi_read_end(opcode, sid, addr, ret, len, buf);
+ return ret;
}
static inline int spmi_write_cmd(struct spmi_controller *ctrl, u8 opcode,
u8 sid, u16 addr, const u8 *buf, size_t len)
{
+ int ret;
+
if (!ctrl || !ctrl->write_cmd || ctrl->dev.type != &spmi_ctrl_type)
return -EINVAL;
- return ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len);
+ trace_spmi_write_begin(opcode, sid, addr, len, buf);
+ ret = ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len);
+ trace_spmi_write_end(opcode, sid, addr, ret);
+ return ret;
}
/**
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 7f6cae5..e29293c 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -56,8 +56,6 @@
source "drivers/staging/iio/Kconfig"
-source "drivers/staging/sm7xxfb/Kconfig"
-
source "drivers/staging/sm750fb/Kconfig"
source "drivers/staging/xgifb/Kconfig"
@@ -78,8 +76,6 @@
source "drivers/staging/board/Kconfig"
-source "drivers/staging/ozwpan/Kconfig"
-
source "drivers/staging/gdm72xx/Kconfig"
source "drivers/staging/gdm724x/Kconfig"
@@ -112,4 +108,6 @@
source "drivers/staging/wilc1000/Kconfig"
+source "drivers/staging/most/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 347f647..50824dd 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -22,7 +22,6 @@
obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_VME_BUS) += vme/
obj-$(CONFIG_IIO) += iio/
-obj-$(CONFIG_FB_SM7XX) += sm7xxfb/
obj-$(CONFIG_FB_SM750) += sm750fb/
obj-$(CONFIG_FB_XGI) += xgifb/
obj-$(CONFIG_USB_EMXX) += emxx_udc/
@@ -32,7 +31,6 @@
obj-$(CONFIG_MFD_NVEC) += nvec/
obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_STAGING_BOARD) += board/
-obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/
obj-$(CONFIG_WIMAX_GDM72XX) += gdm72xx/
obj-$(CONFIG_LTE_GDM724X) += gdm724x/
obj-$(CONFIG_FIREWIRE_SERIAL) += fwserial/
@@ -48,3 +46,4 @@
obj-$(CONFIG_FB_TFT) += fbtft/
obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
obj-$(CONFIG_WILC1000) += wilc1000/
+obj-$(CONFIG_MOST) += most/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 24d657b..6830712 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -20,7 +20,8 @@
config ANDROID_TIMED_GPIO
tristate "Android timed gpio driver"
- depends on GPIOLIB && ANDROID_TIMED_OUTPUT
+ depends on GPIOLIB || COMPILE_TEST
+ depends on ANDROID_TIMED_OUTPUT
default n
---help---
Unlike generic gpio is to allow programs to access and manipulate gpio
diff --git a/drivers/staging/android/TODO b/drivers/staging/android/TODO
index 06954cd..20288fc 100644
--- a/drivers/staging/android/TODO
+++ b/drivers/staging/android/TODO
@@ -2,16 +2,8 @@
- checkpatch.pl cleanups
- sparse fixes
- rename files to be not so "generic"
- - make sure things build as modules properly
- add proper arch dependencies as needed
- audit userspace interfaces to make sure they are sane
- - kuid_t should never be exposed to user space as it is
- kernel internal type. Data structure for this kuid_t is:
- typedef struct {
- uid_t val;
- } kuid_t;
- - This bug is introduced by Xiong Zhou in the patch bd471258f2e09
- - ("staging: android: logger: use kuid_t instead of uid_t")
Please send patches to Greg Kroah-Hartman <greg@kroah.com> and Cc:
-Brian Swetland <swetland@google.com>
+Arve Hjønnevåg <arve@android.com> and Riley Andrews <riandrews@android.com>
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index c5c037c..60200a3 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -388,7 +388,7 @@
/* ... and allocate the backing shmem file */
vmfile = shmem_file_setup(name, asma->size, vma->vm_flags);
- if (unlikely(IS_ERR(vmfile))) {
+ if (IS_ERR(vmfile)) {
ret = PTR_ERR(vmfile);
goto out;
}
@@ -660,7 +660,7 @@
if (page_range_subsumed_by_range(range, pgstart, pgend))
return 0;
if (page_range_in_range(range, pgstart, pgend)) {
- pgstart = min_t(size_t, range->pgstart, pgstart),
+ pgstart = min_t(size_t, range->pgstart, pgstart);
pgend = max_t(size_t, range->pgend, pgend);
purged |= range->purged;
range_del(range);
@@ -863,14 +863,9 @@
static void __exit ashmem_exit(void)
{
- int ret;
-
unregister_shrinker(&ashmem_shrinker);
- ret = misc_deregister(&ashmem_misc);
- if (unlikely(ret))
- pr_err("failed to unregister misc device!\n");
-
+ misc_deregister(&ashmem_misc);
kmem_cache_destroy(ashmem_range_cachep);
kmem_cache_destroy(ashmem_area_cachep);
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 6f48112..eec878e 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -1103,10 +1103,10 @@
struct dma_buf *ion_share_dma_buf(struct ion_client *client,
struct ion_handle *handle)
{
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct ion_buffer *buffer;
struct dma_buf *dmabuf;
bool valid_handle;
- DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
mutex_lock(&client->lock);
valid_handle = ion_handle_validate(client, handle);
@@ -1466,7 +1466,6 @@
.release = single_release,
};
-#ifdef DEBUG_HEAP_SHRINKER
static int debug_shrink_set(void *data, u64 val)
{
struct ion_heap *heap = data;
@@ -1474,15 +1473,14 @@
int objs;
sc.gfp_mask = -1;
- sc.nr_to_scan = 0;
+ sc.nr_to_scan = val;
- if (!val)
- return 0;
+ if (!val) {
+ objs = heap->shrinker.count_objects(&heap->shrinker, &sc);
+ sc.nr_to_scan = objs;
+ }
- objs = heap->shrinker.shrink(&heap->shrinker, &sc);
- sc.nr_to_scan = objs;
-
- heap->shrinker.shrink(&heap->shrinker, &sc);
+ heap->shrinker.scan_objects(&heap->shrinker, &sc);
return 0;
}
@@ -1495,14 +1493,13 @@
sc.gfp_mask = -1;
sc.nr_to_scan = 0;
- objs = heap->shrinker.shrink(&heap->shrinker, &sc);
+ objs = heap->shrinker.count_objects(&heap->shrinker, &sc);
*val = objs;
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(debug_shrink_fops, debug_shrink_get,
debug_shrink_set, "%llu\n");
-#endif
void ion_device_add_heap(struct ion_device *dev, struct ion_heap *heap)
{
@@ -1540,8 +1537,7 @@
path, heap->name);
}
-#ifdef DEBUG_HEAP_SHRINKER
- if (heap->shrinker.shrink) {
+ if (heap->shrinker.count_objects && heap->shrinker.scan_objects) {
char debug_name[64];
snprintf(debug_name, 64, "%s_shrink", heap->name);
@@ -1556,7 +1552,7 @@
path, debug_name);
}
}
-#endif
+
up_write(&dev->lock);
}
diff --git a/drivers/staging/android/ion/ion_chunk_heap.c b/drivers/staging/android/ion/ion_chunk_heap.c
index 5474615..0813163 100644
--- a/drivers/staging/android/ion/ion_chunk_heap.c
+++ b/drivers/staging/android/ion/ion_chunk_heap.c
@@ -173,8 +173,8 @@
chunk_heap->heap.ops = &chunk_heap_ops;
chunk_heap->heap.type = ION_HEAP_TYPE_CHUNK;
chunk_heap->heap.flags = ION_HEAP_FLAG_DEFER_FREE;
- pr_debug("%s: base %lu size %zu align %ld\n", __func__, chunk_heap->base,
- heap_data->size, heap_data->align);
+ pr_debug("%s: base %lu size %zu align %ld\n", __func__,
+ chunk_heap->base, heap_data->size, heap_data->align);
return &chunk_heap->heap;
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index f4211f1..0b2448c 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -73,8 +73,8 @@
if (!info->table)
goto free_mem;
- if (dma_common_get_sgtable
- (dev, info->table, info->cpu_addr, info->handle, len))
+ if (dma_get_sgtable(dev, info->table, info->cpu_addr, info->handle,
+ len))
goto free_table;
/* keep this for memory release */
buffer->priv_virt = info;
diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c
index 4b88f11..19ad3ab 100644
--- a/drivers/staging/android/ion/ion_page_pool.c
+++ b/drivers/staging/android/ion/ion_page_pool.c
@@ -116,7 +116,7 @@
int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
int nr_to_scan)
{
- int freed;
+ int freed = 0;
bool high;
if (current_is_kswapd())
@@ -127,7 +127,7 @@
if (nr_to_scan == 0)
return ion_page_pool_total(pool, high);
- for (freed = 0; freed < nr_to_scan; freed++) {
+ while (freed < nr_to_scan) {
struct page *page;
mutex_lock(&pool->mutex);
@@ -141,6 +141,7 @@
}
mutex_unlock(&pool->mutex);
ion_page_pool_free_pages(pool, page);
+ freed += (1 << pool->order);
}
return freed;
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index da2a63c..7a7a9a0 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -212,14 +212,26 @@
{
struct ion_system_heap *sys_heap;
int nr_total = 0;
- int i;
+ int i, nr_freed;
+ int only_scan = 0;
sys_heap = container_of(heap, struct ion_system_heap, heap);
+ if (!nr_to_scan)
+ only_scan = 1;
+
for (i = 0; i < num_orders; i++) {
struct ion_page_pool *pool = sys_heap->pools[i];
- nr_total += ion_page_pool_shrink(pool, gfp_mask, nr_to_scan);
+ nr_freed = ion_page_pool_shrink(pool, gfp_mask, nr_to_scan);
+ nr_total += nr_freed;
+
+ if (!only_scan) {
+ nr_to_scan -= nr_freed;
+ /* shrink completed */
+ if (nr_to_scan <= 0)
+ break;
+ }
}
return nr_total;
diff --git a/drivers/staging/android/ion/ion_test.c b/drivers/staging/android/ion/ion_test.c
index 7d6e6b6b..b8dcf5a 100644
--- a/drivers/staging/android/ion/ion_test.c
+++ b/drivers/staging/android/ion/ion_test.c
@@ -269,7 +269,8 @@
if (!testdev)
return -ENODATA;
- return misc_deregister(&testdev->misc);
+ misc_deregister(&testdev->misc);
+ return 0;
}
static struct platform_device *ion_test_pdev;
diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h
index a21b79f..61f8a3a 100644
--- a/drivers/staging/android/sync.h
+++ b/drivers/staging/android/sync.h
@@ -337,11 +337,11 @@
#ifdef CONFIG_DEBUG_FS
-extern void sync_timeline_debug_add(struct sync_timeline *obj);
-extern void sync_timeline_debug_remove(struct sync_timeline *obj);
-extern void sync_fence_debug_add(struct sync_fence *fence);
-extern void sync_fence_debug_remove(struct sync_fence *fence);
-extern void sync_dump(void);
+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_dump(void);
#else
# define sync_timeline_debug_add(obj)
diff --git a/drivers/staging/android/timed_gpio.c b/drivers/staging/android/timed_gpio.c
index 938a35c..ce11726 100644
--- a/drivers/staging/android/timed_gpio.c
+++ b/drivers/staging/android/timed_gpio.c
@@ -61,9 +61,9 @@
static void gpio_enable(struct timed_output_dev *dev, int value)
{
- struct timed_gpio_data *data =
+ struct timed_gpio_data *data =
container_of(dev, struct timed_gpio_data, dev);
- unsigned long flags;
+ unsigned long flags;
spin_lock_irqsave(&data->lock, flags);
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 7dee73d..57e71f9 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -2,7 +2,7 @@
tristate "Data acquisition support (comedi)"
depends on m
---help---
- Enable support a wide range of data acquisition devices
+ Enable support for a wide range of data acquisition devices
for Linux.
if COMEDI
diff --git a/drivers/staging/comedi/comedi_compat32.c b/drivers/staging/comedi/comedi_compat32.c
index 2584824..f356386 100644
--- a/drivers/staging/comedi/comedi_compat32.c
+++ b/drivers/staging/comedi/comedi_compat32.c
@@ -202,7 +202,8 @@
err |= __get_user(temp.uint, &cmd32->stop_arg);
err |= __put_user(temp.uint, &cmd->stop_arg);
err |= __get_user(temp.uptr, &cmd32->chanlist);
- err |= __put_user(compat_ptr(temp.uptr), &cmd->chanlist);
+ err |= __put_user((unsigned int __force *)compat_ptr(temp.uptr),
+ &cmd->chanlist);
err |= __get_user(temp.uint, &cmd32->chanlist_len);
err |= __put_user(temp.uint, &cmd->chanlist_len);
err |= __get_user(temp.uptr, &cmd32->data);
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 985d94b..fd54d09 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -215,7 +215,6 @@
struct comedi_subdevice *s;
unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
- BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS);
mutex_lock(&comedi_subdevice_minor_table_lock);
s = comedi_subdevice_minor_table[i];
if (s && s->device != dev)
@@ -228,7 +227,6 @@
{
struct comedi_device *dev;
- BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
mutex_lock(&comedi_board_minor_table_lock);
dev = comedi_dev_get(comedi_board_minor_table[minor]);
mutex_unlock(&comedi_board_minor_table_lock);
@@ -241,7 +239,6 @@
struct comedi_subdevice *s;
unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
- BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS);
mutex_lock(&comedi_subdevice_minor_table_lock);
s = comedi_subdevice_minor_table[i];
dev = comedi_dev_get(s ? s->device : NULL);
@@ -2599,14 +2596,14 @@
cfp->dev = dev;
mutex_lock(&dev->mutex);
- if (!dev->attached && !capable(CAP_NET_ADMIN)) {
- dev_dbg(dev->class_dev, "not attached and not CAP_NET_ADMIN\n");
+ if (!dev->attached && !capable(CAP_SYS_ADMIN)) {
+ dev_dbg(dev->class_dev, "not attached and not CAP_SYS_ADMIN\n");
rc = -ENODEV;
goto out;
}
if (dev->attached && dev->use_count == 0) {
if (!try_module_get(dev->driver->module)) {
- rc = -ENOSYS;
+ rc = -ENXIO;
goto out;
}
if (dev->open) {
@@ -2777,12 +2774,6 @@
return dev;
}
-static void comedi_free_board_minor(unsigned minor)
-{
- BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS);
- comedi_free_board_dev(comedi_clear_board_minor(minor));
-}
-
void comedi_release_hardware_device(struct device *hardware_device)
{
int minor;
@@ -2838,12 +2829,10 @@
if (!s)
return;
- if (s->minor < 0)
+ if (s->minor < COMEDI_NUM_BOARD_MINORS ||
+ s->minor >= COMEDI_NUM_MINORS)
return;
- BUG_ON(s->minor >= COMEDI_NUM_MINORS);
- BUG_ON(s->minor < COMEDI_NUM_BOARD_MINORS);
-
i = s->minor - COMEDI_NUM_BOARD_MINORS;
mutex_lock(&comedi_subdevice_minor_table_lock);
if (s == comedi_subdevice_minor_table[i])
@@ -2857,10 +2846,13 @@
static void comedi_cleanup_board_minors(void)
{
+ struct comedi_device *dev;
unsigned i;
- for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++)
- comedi_free_board_minor(i);
+ for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
+ dev = comedi_clear_board_minor(i);
+ comedi_free_board_dev(dev);
+ }
}
static int __init comedi_init(void)
@@ -2932,14 +2924,7 @@
static void __exit comedi_cleanup(void)
{
- int i;
-
comedi_cleanup_board_minors();
- for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i)
- BUG_ON(comedi_board_minor_table[i]);
- for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i)
- BUG_ON(comedi_subdevice_minor_table[i]);
-
class_destroy(comedi_class);
cdev_del(&comedi_cdev);
unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c
index ed0b60c..b03bc66 100644
--- a/drivers/staging/comedi/drivers.c
+++ b/drivers/staging/comedi/drivers.c
@@ -820,7 +820,7 @@
"driver '%s' does not support attach using comedi_config\n",
driv->driver_name);
module_put(driv->module);
- ret = -ENOSYS;
+ ret = -EIO;
goto out;
}
dev->driver = driv;
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
index fa99c8c..f0c0d58 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c
@@ -1,22 +1,3 @@
-/* Digital Input IRQ Function Selection */
-#define APCI1564_DI_INT_OR (0 << 1)
-#define APCI1564_DI_INT_AND (1 << 1)
-
-/* Digital Input Interrupt Enable Disable. */
-#define APCI1564_DI_INT_ENABLE 0x4
-#define APCI1564_DI_INT_DISABLE 0xfffffffb
-
-/* Digital Output Interrupt Enable Disable. */
-#define APCI1564_DO_VCC_INT_ENABLE 0x1
-#define APCI1564_DO_VCC_INT_DISABLE 0xfffffffe
-#define APCI1564_DO_CC_INT_ENABLE 0x2
-#define APCI1564_DO_CC_INT_DISABLE 0xfffffffd
-
-/* TIMER COUNTER WATCHDOG DEFINES */
-#define ADDIDATA_TIMER 0
-#define ADDIDATA_COUNTER 1
-#define ADDIDATA_WATCHDOG 2
-
static int apci1564_timer_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -27,15 +8,16 @@
devpriv->tsk_current = current;
- /* First Stop The Timer */
+ /* Stop the timer */
ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
- ctrl &= 0xfffff9fe;
- /* Stop The Timer */
+ ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+ ADDI_TCW_CTRL_ENA);
outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
if (data[1] == 1) {
/* Enable timer int & disable all the other int sources */
- outl(0x02, devpriv->timer + ADDI_TCW_CTRL_REG);
+ outl(ADDI_TCW_CTRL_IRQ_ENA,
+ devpriv->timer + ADDI_TCW_CTRL_REG);
outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
@@ -59,9 +41,11 @@
outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG);
ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
- ctrl &= 0xfff719e2;
- ctrl |= (2 << 13) | 0x10;
- /* mode 2 */
+ ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK |
+ ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+ ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
+ ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
+ ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA;
outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
return insn->n;
@@ -76,13 +60,13 @@
unsigned int ctrl;
ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
+ ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
switch (data[1]) {
case 0: /* Stop The Timer */
- ctrl &= 0xfffff9fe;
+ ctrl &= ~ADDI_TCW_CTRL_ENA;
break;
case 1: /* Enable the Timer */
- ctrl &= 0xfffff9ff;
- ctrl |= 0x1;
+ ctrl |= ADDI_TCW_CTRL_ENA;
break;
}
outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
@@ -98,7 +82,8 @@
struct apci1564_private *devpriv = dev->private;
/* Stores the status of the Timer */
- data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) & 0x1;
+ data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) &
+ ADDI_TCW_STATUS_OVERFLOW;
/* Stores the Actual value of the Timer */
data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG);
@@ -118,35 +103,34 @@
devpriv->tsk_current = current;
- /* First Stop The Counter */
- ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
- ctrl &= 0xfffff9fe;
/* Stop The Timer */
+ ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
+ ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+ ADDI_TCW_CTRL_ENA);
outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
/* Set the reload value */
outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
- /* Set the mode : */
- /* - Disable the hardware */
- /* - Disable the counter mode */
- /* - Disable the warning */
- /* - Disable the reset */
- /* - Disable the timer mode */
- /* - Enable the counter mode */
-
- ctrl &= 0xfffc19e2;
- ctrl |= 0x80000 | (data[4] << 16);
+ /* Set the mode */
+ ctrl &= ~(ADDI_TCW_CTRL_EXT_CLK_MASK | ADDI_TCW_CTRL_MODE_MASK |
+ ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
+ ADDI_TCW_CTRL_WARN_ENA);
+ ctrl |= ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE(data[4]);
outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
/* Enable or Disable Interrupt */
- ctrl &= 0xfffff9fd;
- ctrl |= (data[1] << 1);
+ if (data[1])
+ ctrl |= ADDI_TCW_CTRL_IRQ_ENA;
+ else
+ ctrl &= ~ADDI_TCW_CTRL_IRQ_ENA;
outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
/* Set the Up/Down selection */
- ctrl &= 0xfffbf9ff;
- ctrl |= (data[6] << 18);
+ if (data[6])
+ ctrl |= ADDI_TCW_CTRL_CNT_UP;
+ else
+ ctrl &= ~ADDI_TCW_CTRL_CNT_UP;
outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
return insn->n;
@@ -163,17 +147,16 @@
unsigned int ctrl;
ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
+ ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
switch (data[1]) {
case 0: /* Stops the Counter subdevice */
ctrl = 0;
break;
case 1: /* Start the Counter subdevice */
- ctrl &= 0xfffff9ff;
- ctrl |= 0x1;
+ ctrl |= ADDI_TCW_CTRL_ENA;
break;
case 2: /* Clears the Counter subdevice */
- ctrl &= 0xfffff9ff;
- ctrl |= 0x400;
+ ctrl |= ADDI_TCW_CTRL_GATE;
break;
}
outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
@@ -195,10 +178,10 @@
data[0] = inl(iobase + ADDI_TCW_VAL_REG);
status = inl(iobase + ADDI_TCW_STATUS_REG);
- data[1] = (status >> 1) & 1; /* software trigger status */
- data[2] = (status >> 2) & 1; /* hardware trigger status */
- data[3] = (status >> 3) & 1; /* software clear status */
- data[4] = (status >> 0) & 1; /* overflow status */
+ data[1] = (status & ADDI_TCW_STATUS_SOFT_TRIG) ? 1 : 0;
+ data[2] = (status & ADDI_TCW_STATUS_HARDWARE_TRIG) ? 1 : 0;
+ data[3] = (status & ADDI_TCW_STATUS_SOFT_CLR) ? 1 : 0;
+ data[4] = (status & ADDI_TCW_STATUS_OVERFLOW) ? 1 : 0;
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
index 1f2f781..3757074 100644
--- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
+++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci3501.c
@@ -22,54 +22,50 @@
unsigned int *data)
{
struct apci3501_private *devpriv = dev->private;
- unsigned int ul_Command1 = 0;
+ unsigned int ctrl;
+
+ if (data[0] != ADDIDATA_WATCHDOG &&
+ data[0] != ADDIDATA_TIMER)
+ return -EINVAL;
devpriv->tsk_Current = current;
- if (data[0] == ADDIDATA_WATCHDOG) {
- devpriv->b_TimerSelectMode = ADDIDATA_WATCHDOG;
- /* Disable the watchdog */
- outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
+ devpriv->timer_mode = data[0];
- if (data[1] == 1) {
- /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
- outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
- } else {
- /* disable Timer interrupt */
- outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
- }
-
- outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
- outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
-
- /* Set the mode (e2->e0) */
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG) | 0xFFF819E0UL;
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+ /* first, disable the watchdog or stop the timer */
+ if (devpriv->timer_mode == ADDIDATA_WATCHDOG) {
+ ctrl = 0;
+ } else {
+ ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+ ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+ ADDI_TCW_CTRL_ENA);
}
+ outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
- else if (data[0] == ADDIDATA_TIMER) {
- /* First Stop The Timer */
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
- devpriv->b_TimerSelectMode = ADDIDATA_TIMER;
- if (data[1] == 1) {
- /* Enable TIMER int & DISABLE ALL THE OTHER int SOURCES */
- outl(0x02, dev->iobase + APCI3501_TIMER_CTRL_REG);
- } else {
- /* disable Timer interrupt */
- outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
- }
+ /* enable/disable the timer interrupt */
+ ctrl = (data[1] == 1) ? ADDI_TCW_CTRL_IRQ_ENA : 0;
+ outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
- outl(data[2], dev->iobase + APCI3501_TIMER_TIMEBASE_REG);
- outl(data[3], dev->iobase + APCI3501_TIMER_RELOAD_REG);
+ outl(data[2], devpriv->tcw + ADDI_TCW_TIMEBASE_REG);
+ outl(data[3], devpriv->tcw + ADDI_TCW_RELOAD_REG);
+ ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+ if (devpriv->timer_mode == ADDIDATA_WATCHDOG) {
+ /* Set the mode (e2->e0) NOTE: this doesn't look correct */
+ ctrl |= ~(ADDI_TCW_CTRL_CNT_UP | ADDI_TCW_CTRL_EXT_CLK_MASK |
+ ADDI_TCW_CTRL_MODE_MASK | ADDI_TCW_CTRL_GATE |
+ ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_TIMER_ENA |
+ ADDI_TCW_CTRL_RESET_ENA | ADDI_TCW_CTRL_WARN_ENA |
+ ADDI_TCW_CTRL_IRQ_ENA | ADDI_TCW_CTRL_ENA);
+ } else {
/* mode 2 */
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 =
- (ul_Command1 & 0xFFF719E2UL) | 2UL << 13UL | 0x10UL;
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+ ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK |
+ ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+ ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
+ ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
+ ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA;
}
+ outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
return insn->n;
}
@@ -92,49 +88,27 @@
unsigned int *data)
{
struct apci3501_private *devpriv = dev->private;
- unsigned int ul_Command1 = 0;
+ unsigned int ctrl;
- if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
+ if (devpriv->timer_mode == ADDIDATA_WATCHDOG ||
+ devpriv->timer_mode == ADDIDATA_TIMER) {
+ ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+ ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
- if (data[1] == 1) {
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
- /* Enable the Watchdog */
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
- } else if (data[1] == 0) { /* Stop The Watchdog */
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- outl(0x0, dev->iobase + APCI3501_TIMER_CTRL_REG);
- } else if (data[1] == 2) {
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+ if (data[1] == 1) { /* enable */
+ ctrl |= ADDI_TCW_CTRL_ENA;
+ } else if (data[1] == 0) { /* stop */
+ if (devpriv->timer_mode == ADDIDATA_WATCHDOG)
+ ctrl = 0;
+ else
+ ctrl &= ~ADDI_TCW_CTRL_ENA;
+ } else if (data[1] == 2) { /* trigger */
+ ctrl |= ADDI_TCW_CTRL_TRIG;
}
+ outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
}
- if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
- if (data[1] == 1) {
-
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x1UL;
- /* Enable the Timer */
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
- } else if (data[1] == 0) {
- /* Stop The Timer */
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 = ul_Command1 & 0xFFFFF9FEUL;
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
- }
-
- else if (data[1] == 2) {
- /* Trigger the Timer */
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 = (ul_Command1 & 0xFFFFF9FFUL) | 0x200UL;
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
- }
- }
-
- inl(dev->iobase + APCI3501_TIMER_STATUS_REG);
+ inl(devpriv->tcw + ADDI_TCW_STATUS_REG);
return insn->n;
}
@@ -155,19 +129,13 @@
{
struct apci3501_private *devpriv = dev->private;
- if (devpriv->b_TimerSelectMode == ADDIDATA_WATCHDOG) {
- data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
- data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
- }
+ if (devpriv->timer_mode != ADDIDATA_TIMER &&
+ devpriv->timer_mode != ADDIDATA_WATCHDOG)
+ return -EINVAL;
- else if (devpriv->b_TimerSelectMode == ADDIDATA_TIMER) {
- data[0] = inl(dev->iobase + APCI3501_TIMER_STATUS_REG) & 0x1;
- data[1] = inl(dev->iobase + APCI3501_TIMER_SYNC_REG);
- }
+ data[0] = inl(devpriv->tcw + ADDI_TCW_STATUS_REG) &
+ ADDI_TCW_STATUS_OVERFLOW;
+ data[1] = inl(devpriv->tcw + ADDI_TCW_VAL_REG);
- else if ((devpriv->b_TimerSelectMode != ADDIDATA_TIMER)
- && (devpriv->b_TimerSelectMode != ADDIDATA_WATCHDOG)) {
- dev_err(dev->class_dev, "Invalid subdevice.\n");
- }
return insn->n;
}
diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c
index 33e58b9..f1ccfbd 100644
--- a/drivers/staging/comedi/drivers/addi_apci_1564.c
+++ b/drivers/staging/comedi/drivers/addi_apci_1564.c
@@ -44,12 +44,12 @@
* 0x48 - 0x64 Timer 12-Bit
*/
#define APCI1564_EEPROM_REG 0x00
-#define APCI1564_EEPROM_VCC_STATUS (1 << 8)
+#define APCI1564_EEPROM_VCC_STATUS BIT(8)
#define APCI1564_EEPROM_TO_REV(x) (((x) >> 4) & 0xf)
-#define APCI1564_EEPROM_DI (1 << 3)
-#define APCI1564_EEPROM_DO (1 << 2)
-#define APCI1564_EEPROM_CS (1 << 1)
-#define APCI1564_EEPROM_CLK (1 << 0)
+#define APCI1564_EEPROM_DI BIT(3)
+#define APCI1564_EEPROM_DO BIT(2)
+#define APCI1564_EEPROM_CS BIT(1)
+#define APCI1564_EEPROM_CLK BIT(0)
#define APCI1564_REV1_TIMER_IOBASE 0x04
#define APCI1564_REV2_MAIN_IOBASE 0x04
#define APCI1564_REV2_TIMER_IOBASE 0x48
@@ -79,10 +79,17 @@
#define APCI1564_DI_INT_MODE2_REG 0x08
#define APCI1564_DI_INT_STATUS_REG 0x0c
#define APCI1564_DI_IRQ_REG 0x10
+#define APCI1564_DI_IRQ_ENA BIT(2)
+#define APCI1564_DI_IRQ_MODE BIT(1) /* 1=AND, 0=OR */
#define APCI1564_DO_REG 0x14
#define APCI1564_DO_INT_CTRL_REG 0x18
+#define APCI1564_DO_INT_CTRL_CC_INT_ENA BIT(1)
+#define APCI1564_DO_INT_CTRL_VCC_INT_ENA BIT(0)
#define APCI1564_DO_INT_STATUS_REG 0x1c
+#define APCI1564_DO_INT_STATUS_CC BIT(1)
+#define APCI1564_DO_INT_STATUS_VCC BIT(0)
#define APCI1564_DO_IRQ_REG 0x20
+#define APCI1564_DO_IRQ_INTR BIT(0)
#define APCI1564_WDOG_REG 0x24
#define APCI1564_WDOG_RELOAD_REG 0x28
#define APCI1564_WDOG_TIMEBASE_REG 0x2c
@@ -159,9 +166,9 @@
unsigned int chan;
status = inl(dev->iobase + APCI1564_DI_IRQ_REG);
- if (status & APCI1564_DI_INT_ENABLE) {
+ if (status & APCI1564_DI_IRQ_ENA) {
/* disable the interrupt */
- outl(status & APCI1564_DI_INT_DISABLE,
+ outl(status & ~APCI1564_DI_IRQ_ENA,
dev->iobase + APCI1564_DI_IRQ_REG);
s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG) &
@@ -300,11 +307,9 @@
outl(0x0, dev->iobase + APCI1564_DI_INT_MODE2_REG);
break;
case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
- if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE |
- APCI1564_DI_INT_OR)) {
+ if (devpriv->ctrl != APCI1564_DI_IRQ_ENA) {
/* switching to 'OR' mode */
- devpriv->ctrl = APCI1564_DI_INT_ENABLE |
- APCI1564_DI_INT_OR;
+ devpriv->ctrl = APCI1564_DI_IRQ_ENA;
/* wipe old channels */
devpriv->mode1 = 0;
devpriv->mode2 = 0;
@@ -318,11 +323,11 @@
devpriv->mode2 |= data[5] << shift;
break;
case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
- if (devpriv->ctrl != (APCI1564_DI_INT_ENABLE |
- APCI1564_DI_INT_AND)) {
+ if (devpriv->ctrl != (APCI1564_DI_IRQ_ENA |
+ APCI1564_DI_IRQ_MODE)) {
/* switching to 'AND' mode */
- devpriv->ctrl = APCI1564_DI_INT_ENABLE |
- APCI1564_DI_INT_AND;
+ devpriv->ctrl = APCI1564_DI_IRQ_ENA |
+ APCI1564_DI_IRQ_MODE;
/* wipe old channels */
devpriv->mode1 = 0;
devpriv->mode2 = 0;
diff --git a/drivers/staging/comedi/drivers/addi_apci_3501.c b/drivers/staging/comedi/drivers/addi_apci_3501.c
index 73786a3..40ff914 100644
--- a/drivers/staging/comedi/drivers/addi_apci_3501.c
+++ b/drivers/staging/comedi/drivers/addi_apci_3501.c
@@ -27,27 +27,21 @@
#include <linux/sched.h>
#include "../comedi_pci.h"
+#include "addi_tcw.h"
#include "amcc_s5933.h"
/*
* PCI bar 1 register I/O map
*/
#define APCI3501_AO_CTRL_STATUS_REG 0x00
-#define APCI3501_AO_CTRL_BIPOLAR (1 << 0)
-#define APCI3501_AO_STATUS_READY (1 << 8)
+#define APCI3501_AO_CTRL_BIPOLAR BIT(0)
+#define APCI3501_AO_STATUS_READY BIT(8)
#define APCI3501_AO_DATA_REG 0x04
#define APCI3501_AO_DATA_CHAN(x) ((x) << 0)
#define APCI3501_AO_DATA_VAL(x) ((x) << 8)
-#define APCI3501_AO_DATA_BIPOLAR (1 << 31)
+#define APCI3501_AO_DATA_BIPOLAR BIT(31)
#define APCI3501_AO_TRIG_SCS_REG 0x08
-#define APCI3501_TIMER_SYNC_REG 0x20
-#define APCI3501_TIMER_RELOAD_REG 0x24
-#define APCI3501_TIMER_TIMEBASE_REG 0x28
-#define APCI3501_TIMER_CTRL_REG 0x2c
-#define APCI3501_TIMER_STATUS_REG 0x30
-#define APCI3501_TIMER_IRQ_REG 0x34
-#define APCI3501_TIMER_WARN_RELOAD_REG 0x38
-#define APCI3501_TIMER_WARN_TIMEBASE_REG 0x3c
+#define APCI3501_TIMER_BASE 0x20
#define APCI3501_DO_REG 0x40
#define APCI3501_DI_REG 0x50
@@ -72,9 +66,10 @@
#define EEPROM_TIMER_WATCHDOG_COUNTER 10
struct apci3501_private {
- int i_IobaseAmcc;
+ unsigned long amcc;
+ unsigned long tcw;
struct task_struct *tsk_Current;
- unsigned char b_TimerSelectMode;
+ unsigned char timer_mode;
};
static struct comedi_lrange apci3501_ao_range = {
@@ -222,11 +217,10 @@
static int apci3501_eeprom_get_ao_n_chan(struct comedi_device *dev)
{
struct apci3501_private *devpriv = dev->private;
- unsigned long iobase = devpriv->i_IobaseAmcc;
unsigned char nfuncs;
int i;
- nfuncs = apci3501_eeprom_readw(iobase, 10) & 0xff;
+ nfuncs = apci3501_eeprom_readw(devpriv->amcc, 10) & 0xff;
/* Read functionality details */
for (i = 0; i < nfuncs; i++) {
@@ -235,11 +229,11 @@
unsigned char func;
unsigned short val;
- func = apci3501_eeprom_readw(iobase, 12 + offset) & 0x3f;
- addr = apci3501_eeprom_readw(iobase, 14 + offset);
+ func = apci3501_eeprom_readw(devpriv->amcc, 12 + offset) & 0x3f;
+ addr = apci3501_eeprom_readw(devpriv->amcc, 14 + offset);
if (func == EEPROM_ANALOGOUTPUT) {
- val = apci3501_eeprom_readw(iobase, addr + 10);
+ val = apci3501_eeprom_readw(devpriv->amcc, addr + 10);
return (val >> 4) & 0x3ff;
}
}
@@ -254,7 +248,7 @@
struct apci3501_private *devpriv = dev->private;
unsigned short addr = CR_CHAN(insn->chanspec);
- data[0] = apci3501_eeprom_readw(devpriv->i_IobaseAmcc, 2 * addr);
+ data[0] = apci3501_eeprom_readw(devpriv->amcc, 2 * addr);
return insn->n;
}
@@ -263,26 +257,29 @@
{
struct comedi_device *dev = d;
struct apci3501_private *devpriv = dev->private;
- unsigned int ui_Timer_AOWatchdog;
- unsigned long ul_Command1;
+ unsigned int status;
+ unsigned int ctrl;
/* Disable Interrupt */
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 = ul_Command1 & 0xFFFFF9FDul;
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
+ ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+ ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+ ADDI_TCW_CTRL_IRQ_ENA);
+ outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
- ui_Timer_AOWatchdog = inl(dev->iobase + APCI3501_TIMER_IRQ_REG) & 0x1;
- if ((!ui_Timer_AOWatchdog)) {
+ status = inl(devpriv->tcw + ADDI_TCW_IRQ_REG);
+ if (!(status & ADDI_TCW_IRQ)) {
dev_err(dev->class_dev, "IRQ from unknown source\n");
return IRQ_NONE;
}
/* Enable Interrupt Send a signal to from kernel to user space */
send_sig(SIGIO, devpriv->tsk_Current, 0);
- ul_Command1 = inl(dev->iobase + APCI3501_TIMER_CTRL_REG);
- ul_Command1 = (ul_Command1 & 0xFFFFF9FDul) | 1 << 1;
- outl(ul_Command1, dev->iobase + APCI3501_TIMER_CTRL_REG);
- inl(dev->iobase + APCI3501_TIMER_STATUS_REG);
+ ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
+ ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
+ ADDI_TCW_CTRL_IRQ_ENA);
+ ctrl |= ADDI_TCW_CTRL_IRQ_ENA;
+ outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
+ inl(devpriv->tcw + ADDI_TCW_STATUS_REG);
return IRQ_HANDLED;
}
@@ -334,8 +331,9 @@
if (ret)
return ret;
+ devpriv->amcc = pci_resource_start(pcidev, 0);
dev->iobase = pci_resource_start(pcidev, 1);
- devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
+ devpriv->tcw = dev->iobase + APCI3501_TIMER_BASE;
ao_n_chan = apci3501_eeprom_get_ao_n_chan(dev);
diff --git a/drivers/staging/comedi/drivers/addi_tcw.h b/drivers/staging/comedi/drivers/addi_tcw.h
index 8794d4c..db6d5a4 100644
--- a/drivers/staging/comedi/drivers/addi_tcw.h
+++ b/drivers/staging/comedi/drivers/addi_tcw.h
@@ -10,44 +10,51 @@
#define ADDI_TCW_VAL_REG 0x00
#define ADDI_TCW_SYNC_REG 0x00
-#define ADDI_TCW_SYNC_CTR_TRIG (1 << 8)
-#define ADDI_TCW_SYNC_CTR_DIS (1 << 7)
-#define ADDI_TCW_SYNC_CTR_ENA (1 << 6)
-#define ADDI_TCW_SYNC_TIMER_TRIG (1 << 5)
-#define ADDI_TCW_SYNC_TIMER_DIS (1 << 4)
-#define ADDI_TCW_SYNC_TIMER_ENA (1 << 3)
-#define ADDI_TCW_SYNC_WDOG_TRIG (1 << 2)
-#define ADDI_TCW_SYNC_WDOG_DIS (1 << 1)
-#define ADDI_TCW_SYNC_WDOG_ENA (1 << 0)
+#define ADDI_TCW_SYNC_CTR_TRIG BIT(8)
+#define ADDI_TCW_SYNC_CTR_DIS BIT(7)
+#define ADDI_TCW_SYNC_CTR_ENA BIT(6)
+#define ADDI_TCW_SYNC_TIMER_TRIG BIT(5)
+#define ADDI_TCW_SYNC_TIMER_DIS BIT(4)
+#define ADDI_TCW_SYNC_TIMER_ENA BIT(3)
+#define ADDI_TCW_SYNC_WDOG_TRIG BIT(2)
+#define ADDI_TCW_SYNC_WDOG_DIS BIT(1)
+#define ADDI_TCW_SYNC_WDOG_ENA BIT(0)
#define ADDI_TCW_RELOAD_REG 0x04
#define ADDI_TCW_TIMEBASE_REG 0x08
#define ADDI_TCW_CTRL_REG 0x0c
-#define ADDI_TCW_CTRL_EXT_CLK_STATUS (1 << 21)
-#define ADDI_TCW_CTRL_CASCADE (1 << 20)
-#define ADDI_TCW_CTRL_CNTR_ENA (1 << 19)
-#define ADDI_TCW_CTRL_CNT_UP (1 << 18)
-#define ADDI_TCW_CTRL_EXT_CLK(x) ((x) << 16)
-#define ADDI_TCW_CTRL_OUT(x) ((x) << 11)
-#define ADDI_TCW_CTRL_GATE (1 << 10)
-#define ADDI_TCW_CTRL_TRIG (1 << 9)
-#define ADDI_TCW_CTRL_EXT_GATE(x) ((x) << 7)
-#define ADDI_TCW_CTRL_EXT_TRIG(x) ((x) << 5)
-#define ADDI_TCW_CTRL_TIMER_ENA (1 << 4)
-#define ADDI_TCW_CTRL_RESET_ENA (1 << 3)
-#define ADDI_TCW_CTRL_WARN_ENA (1 << 2)
-#define ADDI_TCW_CTRL_IRQ_ENA (1 << 1)
-#define ADDI_TCW_CTRL_ENA (1 << 0)
+#define ADDI_TCW_CTRL_EXT_CLK_STATUS BIT(21)
+#define ADDI_TCW_CTRL_CASCADE BIT(20)
+#define ADDI_TCW_CTRL_CNTR_ENA BIT(19)
+#define ADDI_TCW_CTRL_CNT_UP BIT(18)
+#define ADDI_TCW_CTRL_EXT_CLK(x) (((x) & 3) << 16)
+#define ADDI_TCW_CTRL_EXT_CLK_MASK ADDI_TCW_CTRL_EXT_CLK(3)
+#define ADDI_TCW_CTRL_MODE(x) (((x) & 7) << 13)
+#define ADDI_TCW_CTRL_MODE_MASK ADDI_TCW_CTRL_MODE(7)
+#define ADDI_TCW_CTRL_OUT(x) (((x) & 3) << 11)
+#define ADDI_TCW_CTRL_OUT_MASK ADDI_TCW_CTRL_OUT(3)
+#define ADDI_TCW_CTRL_GATE BIT(10)
+#define ADDI_TCW_CTRL_TRIG BIT(9)
+#define ADDI_TCW_CTRL_EXT_GATE(x) (((x) & 3) << 7)
+#define ADDI_TCW_CTRL_EXT_GATE_MASK ADDI_TCW_CTRL_EXT_GATE(3)
+#define ADDI_TCW_CTRL_EXT_TRIG(x) (((x) & 3) << 5)
+#define ADDI_TCW_CTRL_EXT_TRIG_MASK ADDI_TCW_CTRL_EXT_TRIG(3)
+#define ADDI_TCW_CTRL_TIMER_ENA BIT(4)
+#define ADDI_TCW_CTRL_RESET_ENA BIT(3)
+#define ADDI_TCW_CTRL_WARN_ENA BIT(2)
+#define ADDI_TCW_CTRL_IRQ_ENA BIT(1)
+#define ADDI_TCW_CTRL_ENA BIT(0)
#define ADDI_TCW_STATUS_REG 0x10
-#define ADDI_TCW_STATUS_SOFT_CLR (1 << 3)
-#define ADDI_TCW_STATUS_SOFT_TRIG (1 << 1)
-#define ADDI_TCW_STATUS_OVERFLOW (1 << 0)
+#define ADDI_TCW_STATUS_SOFT_CLR BIT(3)
+#define ADDI_TCW_STATUS_HARDWARE_TRIG BIT(2)
+#define ADDI_TCW_STATUS_SOFT_TRIG BIT(1)
+#define ADDI_TCW_STATUS_OVERFLOW BIT(0)
#define ADDI_TCW_IRQ_REG 0x14
-#define ADDI_TCW_IRQ (1 << 0)
+#define ADDI_TCW_IRQ BIT(0)
#define ADDI_TCW_WARN_TIMEVAL_REG 0x18
diff --git a/drivers/staging/comedi/drivers/adl_pci7x3x.c b/drivers/staging/comedi/drivers/adl_pci7x3x.c
index 934af3f..b0fc027 100644
--- a/drivers/staging/comedi/drivers/adl_pci7x3x.c
+++ b/drivers/staging/comedi/drivers/adl_pci7x3x.c
@@ -120,8 +120,20 @@
{
unsigned long reg = (unsigned long)s->private;
- if (comedi_dio_update_state(s, data))
- outl(s->state, dev->iobase + reg);
+ if (comedi_dio_update_state(s, data)) {
+ unsigned int val = s->state;
+
+ if (s->n_chan == 16) {
+ /*
+ * It seems the PCI-7230 needs the 16-bit DO state
+ * to be shifted left by 16 bits before being written
+ * to the 32-bit register. Set the value in both
+ * halves of the register to be sure.
+ */
+ val |= val << 16;
+ }
+ outl(val, dev->iobase + reg);
+ }
data[1] = s->state;
diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c
index 4ebf5aa..47e3839 100644
--- a/drivers/staging/comedi/drivers/cb_pcimdas.c
+++ b/drivers/staging/comedi/drivers/cb_pcimdas.c
@@ -141,11 +141,13 @@
* jumper-settable on the board. The settings are not software-readable.
*/
static const struct comedi_lrange cb_pcimdas_ao_range = {
- 4, {
+ 6, {
BIP_RANGE(10),
BIP_RANGE(5),
UNI_RANGE(10),
- UNI_RANGE(5)
+ UNI_RANGE(5),
+ RANGE_ext(-1, 1),
+ RANGE_ext(0, 1)
}
};
diff --git a/drivers/staging/comedi/drivers/dac02.c b/drivers/staging/comedi/drivers/dac02.c
index a6798ad..a562df4 100644
--- a/drivers/staging/comedi/drivers/dac02.c
+++ b/drivers/staging/comedi/drivers/dac02.c
@@ -130,11 +130,7 @@
s->range_table = &das02_ao_ranges;
s->insn_write = dac02_ao_insn_write;
- ret = comedi_alloc_subdev_readback(s);
- if (ret)
- return ret;
-
- return 0;
+ return comedi_alloc_subdev_readback(s);
}
static struct comedi_driver dac02_driver = {
diff --git a/drivers/staging/comedi/drivers/das08_cs.c b/drivers/staging/comedi/drivers/das08_cs.c
index 93fab68..9c02b17 100644
--- a/drivers/staging/comedi/drivers/das08_cs.c
+++ b/drivers/staging/comedi/drivers/das08_cs.c
@@ -108,7 +108,7 @@
};
module_comedi_pcmcia_driver(driver_das08_cs, das08_cs_driver);
-MODULE_AUTHOR("David A. Schleef <ds@schleef.org>, "
- "Frank Mori Hess <fmhess@users.sourceforge.net>");
+MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
+MODULE_AUTHOR("Frank Mori Hess <fmhess@users.sourceforge.net>");
MODULE_DESCRIPTION("Comedi driver for ComputerBoards DAS-08 PCMCIA boards");
MODULE_LICENSE("GPL");
diff --git a/drivers/staging/comedi/drivers/das16.c b/drivers/staging/comedi/drivers/das16.c
index d7cf4b1..056bca9 100644
--- a/drivers/staging/comedi/drivers/das16.c
+++ b/drivers/staging/comedi/drivers/das16.c
@@ -1032,8 +1032,7 @@
/* check that clock setting is valid */
if (it->options[3]) {
- if (it->options[3] != 0 &&
- it->options[3] != 1 && it->options[3] != 10) {
+ if (it->options[3] != 1 && it->options[3] != 10) {
dev_err(dev->class_dev,
"Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
return -EINVAL;
diff --git a/drivers/staging/comedi/drivers/das16m1.c b/drivers/staging/comedi/drivers/das16m1.c
index a18a887..3a37373 100644
--- a/drivers/staging/comedi/drivers/das16m1.c
+++ b/drivers/staging/comedi/drivers/das16m1.c
@@ -69,18 +69,18 @@
"cio-das16/m1"
- 0 a/d bits 0-3, mux start 12 bit
- 1 a/d bits 4-11 unused
- 2 status control
- 3 di 4 bit do 4 bit
- 4 unused clear interrupt
- 5 interrupt, pacer
- 6 channel/gain queue address
- 7 channel/gain queue data
- 89ab 8254
- cdef 8254
- 400 8255
- 404-407 8254
+ 0 a/d bits 0-3, mux start 12 bit
+ 1 a/d bits 4-11 unused
+ 2 status control
+ 3 di 4 bit do 4 bit
+ 4 unused clear interrupt
+ 5 interrupt, pacer
+ 6 channel/gain queue address
+ 7 channel/gain queue data
+ 89ab 8254
+ cdef 8254
+ 400 8255
+ 404-407 8254
*/
@@ -411,15 +411,18 @@
hw_counter = comedi_8254_read(devpriv->counter, 1);
/* make sure hardware counter reading is not bogus due to initial value
* not having been loaded yet */
- if (devpriv->adc_count == 0 && hw_counter == devpriv->initial_hw_count) {
+ if (devpriv->adc_count == 0 &&
+ hw_counter == devpriv->initial_hw_count) {
num_samples = 0;
} else {
- /* The calculation of num_samples looks odd, but it uses the following facts.
- * 16 bit hardware counter is initialized with value of zero (which really
- * means 0x1000). The counter decrements by one on each conversion
- * (when the counter decrements from zero it goes to 0xffff). num_samples
- * is a 16 bit variable, so it will roll over in a similar fashion to the
- * hardware counter. Work it out, and this is what you get. */
+ /* The calculation of num_samples looks odd, but it uses the
+ * following facts. 16 bit hardware counter is initialized with
+ * value of zero (which really means 0x1000). The counter
+ * decrements by one on each conversion (when the counter
+ * decrements from zero it goes to 0xffff). num_samples is a
+ * 16 bit variable, so it will roll over in a similar fashion
+ * to the hardware counter. Work it out, and this is what you
+ * get. */
num_samples = -hw_counter - devpriv->adc_count;
}
/* check if we only need some of the points */
diff --git a/drivers/staging/comedi/drivers/das1800.c b/drivers/staging/comedi/drivers/das1800.c
index bfa4262..94078118 100644
--- a/drivers/staging/comedi/drivers/das1800.c
+++ b/drivers/staging/comedi/drivers/das1800.c
@@ -1266,6 +1266,7 @@
if (index == das1801hc || index == das1802hc)
return board;
index = das1801hc;
+ break;
default:
dev_err(dev->class_dev,
"Board model: probe returned 0x%x (unknown, please report)\n",
diff --git a/drivers/staging/comedi/drivers/dmm32at.c b/drivers/staging/comedi/drivers/dmm32at.c
index bb2883c..958c0d4 100644
--- a/drivers/staging/comedi/drivers/dmm32at.c
+++ b/drivers/staging/comedi/drivers/dmm32at.c
@@ -607,11 +607,7 @@
/* Digital I/O subdevice */
s = &dev->subdevices[2];
- ret = subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE);
- if (ret)
- return ret;
-
- return 0;
+ return subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE);
}
static struct comedi_driver dmm32at_driver = {
diff --git a/drivers/staging/comedi/drivers/fl512.c b/drivers/staging/comedi/drivers/fl512.c
index e1f4932..55cae61 100644
--- a/drivers/staging/comedi/drivers/fl512.c
+++ b/drivers/staging/comedi/drivers/fl512.c
@@ -136,11 +136,7 @@
s->range_table = &range_fl512;
s->insn_write = fl512_ao_insn_write;
- ret = comedi_alloc_subdev_readback(s);
- if (ret)
- return ret;
-
- return 0;
+ return comedi_alloc_subdev_readback(s);
}
static struct comedi_driver fl512_driver = {
diff --git a/drivers/staging/comedi/drivers/me4000.c b/drivers/staging/comedi/drivers/me4000.c
index a8f3ca4..15a5320 100644
--- a/drivers/staging/comedi/drivers/me4000.c
+++ b/drivers/staging/comedi/drivers/me4000.c
@@ -1,43 +1,41 @@
/*
- comedi/drivers/me4000.c
- Source code for the Meilhaus ME-4000 board family.
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
- 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.
+ * me4000.c
+ * Source code for the Meilhaus ME-4000 board family.
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*/
+
/*
-Driver: me4000
-Description: Meilhaus ME-4000 series boards
-Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i, ME-4680is
-Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
-Updated: Mon, 18 Mar 2002 15:34:01 -0800
-Status: broken (no support for loading firmware)
-
-Supports:
-
- - Analog Input
- - Analog Output
- - Digital I/O
- - Counter
-
-Configuration Options: not applicable, uses PCI auto config
-
-The firmware required by these boards is available in the
-comedi_nonfree_firmware tarball available from
-http://www.comedi.org. However, the driver's support for
-loading the firmware through comedi_config is currently
-broken.
-
+ * Driver: me4000
+ * Description: Meilhaus ME-4000 series boards
+ * Devices: [Meilhaus] ME-4650 (me4000), ME-4670i, ME-4680, ME-4680i,
+ * ME-4680is
+ * Author: gg (Guenter Gebhardt <g.gebhardt@meilhaus.com>)
+ * Updated: Mon, 18 Mar 2002 15:34:01 -0800
+ * Status: untested
+ *
+ * Supports:
+ * - Analog Input
+ * - Analog Output
+ * - Digital I/O
+ * - Counter
+ *
+ * Configuration Options: not applicable, uses PCI auto config
+ *
+ * The firmware required by these boards is available in the
+ * comedi_nonfree_firmware tarball available from
+ * http://www.comedi.org.
*/
#include <linux/module.h>
@@ -57,66 +55,61 @@
#define ME4000_AO_CHAN(x) ((x) * 0x18)
#define ME4000_AO_CTRL_REG(x) (0x00 + ME4000_AO_CHAN(x))
-#define ME4000_AO_CTRL_BIT_MODE_0 (1 << 0)
-#define ME4000_AO_CTRL_BIT_MODE_1 (1 << 1)
-#define ME4000_AO_CTRL_MASK_MODE (3 << 0)
-#define ME4000_AO_CTRL_BIT_STOP (1 << 2)
-#define ME4000_AO_CTRL_BIT_ENABLE_FIFO (1 << 3)
-#define ME4000_AO_CTRL_BIT_ENABLE_EX_TRIG (1 << 4)
-#define ME4000_AO_CTRL_BIT_EX_TRIG_EDGE (1 << 5)
-#define ME4000_AO_CTRL_BIT_IMMEDIATE_STOP (1 << 7)
-#define ME4000_AO_CTRL_BIT_ENABLE_DO (1 << 8)
-#define ME4000_AO_CTRL_BIT_ENABLE_IRQ (1 << 9)
-#define ME4000_AO_CTRL_BIT_RESET_IRQ (1 << 10)
+#define ME4000_AO_CTRL_MODE_0 BIT(0)
+#define ME4000_AO_CTRL_MODE_1 BIT(1)
+#define ME4000_AO_CTRL_STOP BIT(2)
+#define ME4000_AO_CTRL_ENABLE_FIFO BIT(3)
+#define ME4000_AO_CTRL_ENABLE_EX_TRIG BIT(4)
+#define ME4000_AO_CTRL_EX_TRIG_EDGE BIT(5)
+#define ME4000_AO_CTRL_IMMEDIATE_STOP BIT(7)
+#define ME4000_AO_CTRL_ENABLE_DO BIT(8)
+#define ME4000_AO_CTRL_ENABLE_IRQ BIT(9)
+#define ME4000_AO_CTRL_RESET_IRQ BIT(10)
#define ME4000_AO_STATUS_REG(x) (0x04 + ME4000_AO_CHAN(x))
-#define ME4000_AO_STATUS_BIT_FSM (1 << 0)
-#define ME4000_AO_STATUS_BIT_FF (1 << 1)
-#define ME4000_AO_STATUS_BIT_HF (1 << 2)
-#define ME4000_AO_STATUS_BIT_EF (1 << 3)
+#define ME4000_AO_STATUS_FSM BIT(0)
+#define ME4000_AO_STATUS_FF BIT(1)
+#define ME4000_AO_STATUS_HF BIT(2)
+#define ME4000_AO_STATUS_EF BIT(3)
#define ME4000_AO_FIFO_REG(x) (0x08 + ME4000_AO_CHAN(x))
#define ME4000_AO_SINGLE_REG(x) (0x0c + ME4000_AO_CHAN(x))
#define ME4000_AO_TIMER_REG(x) (0x10 + ME4000_AO_CHAN(x))
#define ME4000_AI_CTRL_REG 0x74
#define ME4000_AI_STATUS_REG 0x74
-#define ME4000_AI_CTRL_BIT_MODE_0 (1 << 0)
-#define ME4000_AI_CTRL_BIT_MODE_1 (1 << 1)
-#define ME4000_AI_CTRL_BIT_MODE_2 (1 << 2)
-#define ME4000_AI_CTRL_BIT_SAMPLE_HOLD (1 << 3)
-#define ME4000_AI_CTRL_BIT_IMMEDIATE_STOP (1 << 4)
-#define ME4000_AI_CTRL_BIT_STOP (1 << 5)
-#define ME4000_AI_CTRL_BIT_CHANNEL_FIFO (1 << 6)
-#define ME4000_AI_CTRL_BIT_DATA_FIFO (1 << 7)
-#define ME4000_AI_CTRL_BIT_FULLSCALE (1 << 8)
-#define ME4000_AI_CTRL_BIT_OFFSET (1 << 9)
-#define ME4000_AI_CTRL_BIT_EX_TRIG_ANALOG (1 << 10)
-#define ME4000_AI_CTRL_BIT_EX_TRIG (1 << 11)
-#define ME4000_AI_CTRL_BIT_EX_TRIG_FALLING (1 << 12)
-#define ME4000_AI_CTRL_BIT_EX_IRQ (1 << 13)
-#define ME4000_AI_CTRL_BIT_EX_IRQ_RESET (1 << 14)
-#define ME4000_AI_CTRL_BIT_LE_IRQ (1 << 15)
-#define ME4000_AI_CTRL_BIT_LE_IRQ_RESET (1 << 16)
-#define ME4000_AI_CTRL_BIT_HF_IRQ (1 << 17)
-#define ME4000_AI_CTRL_BIT_HF_IRQ_RESET (1 << 18)
-#define ME4000_AI_CTRL_BIT_SC_IRQ (1 << 19)
-#define ME4000_AI_CTRL_BIT_SC_IRQ_RESET (1 << 20)
-#define ME4000_AI_CTRL_BIT_SC_RELOAD (1 << 21)
-#define ME4000_AI_STATUS_BIT_EF_CHANNEL (1 << 22)
-#define ME4000_AI_STATUS_BIT_HF_CHANNEL (1 << 23)
-#define ME4000_AI_STATUS_BIT_FF_CHANNEL (1 << 24)
-#define ME4000_AI_STATUS_BIT_EF_DATA (1 << 25)
-#define ME4000_AI_STATUS_BIT_HF_DATA (1 << 26)
-#define ME4000_AI_STATUS_BIT_FF_DATA (1 << 27)
-#define ME4000_AI_STATUS_BIT_LE (1 << 28)
-#define ME4000_AI_STATUS_BIT_FSM (1 << 29)
-#define ME4000_AI_CTRL_BIT_EX_TRIG_BOTH (1 << 31)
+#define ME4000_AI_CTRL_MODE_0 BIT(0)
+#define ME4000_AI_CTRL_MODE_1 BIT(1)
+#define ME4000_AI_CTRL_MODE_2 BIT(2)
+#define ME4000_AI_CTRL_SAMPLE_HOLD BIT(3)
+#define ME4000_AI_CTRL_IMMEDIATE_STOP BIT(4)
+#define ME4000_AI_CTRL_STOP BIT(5)
+#define ME4000_AI_CTRL_CHANNEL_FIFO BIT(6)
+#define ME4000_AI_CTRL_DATA_FIFO BIT(7)
+#define ME4000_AI_CTRL_FULLSCALE BIT(8)
+#define ME4000_AI_CTRL_OFFSET BIT(9)
+#define ME4000_AI_CTRL_EX_TRIG_ANALOG BIT(10)
+#define ME4000_AI_CTRL_EX_TRIG BIT(11)
+#define ME4000_AI_CTRL_EX_TRIG_FALLING BIT(12)
+#define ME4000_AI_CTRL_EX_IRQ BIT(13)
+#define ME4000_AI_CTRL_EX_IRQ_RESET BIT(14)
+#define ME4000_AI_CTRL_LE_IRQ BIT(15)
+#define ME4000_AI_CTRL_LE_IRQ_RESET BIT(16)
+#define ME4000_AI_CTRL_HF_IRQ BIT(17)
+#define ME4000_AI_CTRL_HF_IRQ_RESET BIT(18)
+#define ME4000_AI_CTRL_SC_IRQ BIT(19)
+#define ME4000_AI_CTRL_SC_IRQ_RESET BIT(20)
+#define ME4000_AI_CTRL_SC_RELOAD BIT(21)
+#define ME4000_AI_STATUS_EF_CHANNEL BIT(22)
+#define ME4000_AI_STATUS_HF_CHANNEL BIT(23)
+#define ME4000_AI_STATUS_FF_CHANNEL BIT(24)
+#define ME4000_AI_STATUS_EF_DATA BIT(25)
+#define ME4000_AI_STATUS_HF_DATA BIT(26)
+#define ME4000_AI_STATUS_FF_DATA BIT(27)
+#define ME4000_AI_STATUS_LE BIT(28)
+#define ME4000_AI_STATUS_FSM BIT(29)
+#define ME4000_AI_CTRL_EX_TRIG_BOTH BIT(31)
#define ME4000_AI_CHANNEL_LIST_REG 0x78
-#define ME4000_AI_LIST_INPUT_SINGLE_ENDED (0 << 5)
-#define ME4000_AI_LIST_INPUT_DIFFERENTIAL (1 << 5)
-#define ME4000_AI_LIST_RANGE_BIPOLAR_10 (0 << 6)
-#define ME4000_AI_LIST_RANGE_BIPOLAR_2_5 (1 << 6)
-#define ME4000_AI_LIST_RANGE_UNIPOLAR_10 (2 << 6)
-#define ME4000_AI_LIST_RANGE_UNIPOLAR_2_5 (3 << 6)
-#define ME4000_AI_LIST_LAST_ENTRY (1 << 8)
+#define ME4000_AI_LIST_INPUT_DIFFERENTIAL BIT(5)
+#define ME4000_AI_LIST_RANGE(x) ((3 - ((x) & 3)) << 6)
+#define ME4000_AI_LIST_LAST_ENTRY BIT(8)
#define ME4000_AI_DATA_REG 0x7c
#define ME4000_AI_CHAN_TIMER_REG 0x80
#define ME4000_AI_CHAN_PRE_TIMER_REG 0x84
@@ -126,14 +119,14 @@
#define ME4000_AI_SCAN_PRE_TIMER_HIGH_REG 0x94
#define ME4000_AI_START_REG 0x98
#define ME4000_IRQ_STATUS_REG 0x9c
-#define ME4000_IRQ_STATUS_BIT_EX (1 << 0)
-#define ME4000_IRQ_STATUS_BIT_LE (1 << 1)
-#define ME4000_IRQ_STATUS_BIT_AI_HF (1 << 2)
-#define ME4000_IRQ_STATUS_BIT_AO_0_HF (1 << 3)
-#define ME4000_IRQ_STATUS_BIT_AO_1_HF (1 << 4)
-#define ME4000_IRQ_STATUS_BIT_AO_2_HF (1 << 5)
-#define ME4000_IRQ_STATUS_BIT_AO_3_HF (1 << 6)
-#define ME4000_IRQ_STATUS_BIT_SC (1 << 7)
+#define ME4000_IRQ_STATUS_EX BIT(0)
+#define ME4000_IRQ_STATUS_LE BIT(1)
+#define ME4000_IRQ_STATUS_AI_HF BIT(2)
+#define ME4000_IRQ_STATUS_AO_0_HF BIT(3)
+#define ME4000_IRQ_STATUS_AO_1_HF BIT(4)
+#define ME4000_IRQ_STATUS_AO_2_HF BIT(5)
+#define ME4000_IRQ_STATUS_AO_3_HF BIT(6)
+#define ME4000_IRQ_STATUS_SC BIT(7)
#define ME4000_DIO_PORT_0_REG 0xa0
#define ME4000_DIO_PORT_1_REG 0xa4
#define ME4000_DIO_PORT_2_REG 0xa8
@@ -141,20 +134,20 @@
#define ME4000_DIO_DIR_REG 0xb0
#define ME4000_AO_LOADSETREG_XX 0xb4
#define ME4000_DIO_CTRL_REG 0xb8
-#define ME4000_DIO_CTRL_BIT_MODE_0 (1 << 0)
-#define ME4000_DIO_CTRL_BIT_MODE_1 (1 << 1)
-#define ME4000_DIO_CTRL_BIT_MODE_2 (1 << 2)
-#define ME4000_DIO_CTRL_BIT_MODE_3 (1 << 3)
-#define ME4000_DIO_CTRL_BIT_MODE_4 (1 << 4)
-#define ME4000_DIO_CTRL_BIT_MODE_5 (1 << 5)
-#define ME4000_DIO_CTRL_BIT_MODE_6 (1 << 6)
-#define ME4000_DIO_CTRL_BIT_MODE_7 (1 << 7)
-#define ME4000_DIO_CTRL_BIT_FUNCTION_0 (1 << 8)
-#define ME4000_DIO_CTRL_BIT_FUNCTION_1 (1 << 9)
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_0 (1 << 10)
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_1 (1 << 11)
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_2 (1 << 12)
-#define ME4000_DIO_CTRL_BIT_FIFO_HIGH_3 (1 << 13)
+#define ME4000_DIO_CTRL_MODE_0 BIT(0)
+#define ME4000_DIO_CTRL_MODE_1 BIT(1)
+#define ME4000_DIO_CTRL_MODE_2 BIT(2)
+#define ME4000_DIO_CTRL_MODE_3 BIT(3)
+#define ME4000_DIO_CTRL_MODE_4 BIT(4)
+#define ME4000_DIO_CTRL_MODE_5 BIT(5)
+#define ME4000_DIO_CTRL_MODE_6 BIT(6)
+#define ME4000_DIO_CTRL_MODE_7 BIT(7)
+#define ME4000_DIO_CTRL_FUNCTION_0 BIT(8)
+#define ME4000_DIO_CTRL_FUNCTION_1 BIT(9)
+#define ME4000_DIO_CTRL_FIFO_HIGH_0 BIT(10)
+#define ME4000_DIO_CTRL_FIFO_HIGH_1 BIT(11)
+#define ME4000_DIO_CTRL_FIFO_HIGH_2 BIT(12)
+#define ME4000_DIO_CTRL_FIFO_HIGH_3 BIT(13)
#define ME4000_AO_DEMUX_ADJUST_REG 0xbc
#define ME4000_AO_DEMUX_ADJUST_VALUE 0x4c
#define ME4000_AI_SAMPLE_COUNTER_REG 0xc0
@@ -166,8 +159,12 @@
#define ME4000_AI_CHANNEL_LIST_COUNT 1024
-struct me4000_info {
+struct me4000_private {
unsigned long plx_regbase;
+ unsigned int ai_ctrl_mode;
+ unsigned int ai_init_ticks;
+ unsigned int ai_scan_ticks;
+ unsigned int ai_chan_ticks;
};
enum me4000_boardid {
@@ -188,134 +185,126 @@
struct me4000_board {
const char *name;
- int ao_nchan;
- int ao_fifo;
int ai_nchan;
- int ai_diff_nchan;
- int ai_sh_nchan;
- int ex_trig_analog;
- int dio_nchan;
- int has_counter;
+ unsigned int can_do_diff_ai:1;
+ unsigned int can_do_sh_ai:1; /* sample & hold (8 channels) */
+ unsigned int ex_trig_analog:1;
+ unsigned int has_ao:1;
+ unsigned int has_ao_fifo:1;
+ unsigned int has_counter:1;
};
static const struct me4000_board me4000_boards[] = {
[BOARD_ME4650] = {
.name = "ME-4650",
.ai_nchan = 16,
- .dio_nchan = 32,
},
[BOARD_ME4660] = {
.name = "ME-4660",
.ai_nchan = 32,
- .ai_diff_nchan = 16,
- .dio_nchan = 32,
+ .can_do_diff_ai = 1,
.has_counter = 1,
},
[BOARD_ME4660I] = {
.name = "ME-4660i",
.ai_nchan = 32,
- .ai_diff_nchan = 16,
- .dio_nchan = 32,
+ .can_do_diff_ai = 1,
.has_counter = 1,
},
[BOARD_ME4660S] = {
.name = "ME-4660s",
.ai_nchan = 32,
- .ai_diff_nchan = 16,
- .ai_sh_nchan = 8,
- .dio_nchan = 32,
+ .can_do_diff_ai = 1,
+ .can_do_sh_ai = 1,
.has_counter = 1,
},
[BOARD_ME4660IS] = {
.name = "ME-4660is",
.ai_nchan = 32,
- .ai_diff_nchan = 16,
- .ai_sh_nchan = 8,
- .dio_nchan = 32,
+ .can_do_diff_ai = 1,
+ .can_do_sh_ai = 1,
.has_counter = 1,
},
[BOARD_ME4670] = {
.name = "ME-4670",
- .ao_nchan = 4,
.ai_nchan = 32,
- .ai_diff_nchan = 16,
+ .can_do_diff_ai = 1,
.ex_trig_analog = 1,
- .dio_nchan = 32,
+ .has_ao = 1,
.has_counter = 1,
},
[BOARD_ME4670I] = {
.name = "ME-4670i",
- .ao_nchan = 4,
.ai_nchan = 32,
- .ai_diff_nchan = 16,
+ .can_do_diff_ai = 1,
.ex_trig_analog = 1,
- .dio_nchan = 32,
+ .has_ao = 1,
.has_counter = 1,
},
[BOARD_ME4670S] = {
.name = "ME-4670s",
- .ao_nchan = 4,
.ai_nchan = 32,
- .ai_diff_nchan = 16,
- .ai_sh_nchan = 8,
+ .can_do_diff_ai = 1,
+ .can_do_sh_ai = 1,
.ex_trig_analog = 1,
- .dio_nchan = 32,
+ .has_ao = 1,
.has_counter = 1,
},
[BOARD_ME4670IS] = {
.name = "ME-4670is",
- .ao_nchan = 4,
.ai_nchan = 32,
- .ai_diff_nchan = 16,
- .ai_sh_nchan = 8,
+ .can_do_diff_ai = 1,
+ .can_do_sh_ai = 1,
.ex_trig_analog = 1,
- .dio_nchan = 32,
+ .has_ao = 1,
.has_counter = 1,
},
[BOARD_ME4680] = {
.name = "ME-4680",
- .ao_nchan = 4,
- .ao_fifo = 4,
.ai_nchan = 32,
- .ai_diff_nchan = 16,
+ .can_do_diff_ai = 1,
.ex_trig_analog = 1,
- .dio_nchan = 32,
+ .has_ao = 1,
+ .has_ao_fifo = 1,
.has_counter = 1,
},
[BOARD_ME4680I] = {
.name = "ME-4680i",
- .ao_nchan = 4,
- .ao_fifo = 4,
.ai_nchan = 32,
- .ai_diff_nchan = 16,
+ .can_do_diff_ai = 1,
.ex_trig_analog = 1,
- .dio_nchan = 32,
+ .has_ao = 1,
+ .has_ao_fifo = 1,
.has_counter = 1,
},
[BOARD_ME4680S] = {
.name = "ME-4680s",
- .ao_nchan = 4,
- .ao_fifo = 4,
.ai_nchan = 32,
- .ai_diff_nchan = 16,
- .ai_sh_nchan = 8,
+ .can_do_diff_ai = 1,
+ .can_do_sh_ai = 1,
.ex_trig_analog = 1,
- .dio_nchan = 32,
+ .has_ao = 1,
+ .has_ao_fifo = 1,
.has_counter = 1,
},
[BOARD_ME4680IS] = {
.name = "ME-4680is",
- .ao_nchan = 4,
- .ao_fifo = 4,
.ai_nchan = 32,
- .ai_diff_nchan = 16,
- .ai_sh_nchan = 8,
+ .can_do_diff_ai = 1,
+ .can_do_sh_ai = 1,
.ex_trig_analog = 1,
- .dio_nchan = 32,
+ .has_ao = 1,
+ .has_ao_fifo = 1,
.has_counter = 1,
},
};
+/*
+ * NOTE: the ranges here are inverted compared to the values
+ * written to the ME4000_AI_CHANNEL_LIST_REG,
+ *
+ * The ME4000_AI_LIST_RANGE() macro handles the inversion.
+ */
static const struct comedi_lrange me4000_ai_range = {
4, {
UNI_RANGE(2.5),
@@ -330,7 +319,7 @@
unsigned long context)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- struct me4000_info *info = dev->private;
+ struct me4000_private *devpriv = dev->private;
unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
unsigned int file_length;
unsigned int val;
@@ -343,42 +332,42 @@
* Set PLX local interrupt 2 polarity to high.
* Interrupt is thrown by init pin of xilinx.
*/
- outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR);
+ outl(PLX9052_INTCSR_LI2POL, devpriv->plx_regbase + PLX9052_INTCSR);
/* Set /CS and /WRITE of the Xilinx */
- val = inl(info->plx_regbase + PLX9052_CNTRL);
+ val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
val |= PLX9052_CNTRL_UIO2_DATA;
- outl(val, info->plx_regbase + PLX9052_CNTRL);
+ outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
/* Init Xilinx with CS1 */
inb(xilinx_iobase + 0xC8);
/* Wait until /INIT pin is set */
- udelay(20);
- val = inl(info->plx_regbase + PLX9052_INTCSR);
+ usleep_range(20, 1000);
+ val = inl(devpriv->plx_regbase + PLX9052_INTCSR);
if (!(val & PLX9052_INTCSR_LI2STAT)) {
dev_err(dev->class_dev, "Can't init Xilinx\n");
return -EIO;
}
/* Reset /CS and /WRITE of the Xilinx */
- val = inl(info->plx_regbase + PLX9052_CNTRL);
+ val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
val &= ~PLX9052_CNTRL_UIO2_DATA;
- outl(val, info->plx_regbase + PLX9052_CNTRL);
+ outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
/* Download Xilinx firmware */
file_length = (((unsigned int)data[0] & 0xff) << 24) +
(((unsigned int)data[1] & 0xff) << 16) +
(((unsigned int)data[2] & 0xff) << 8) +
((unsigned int)data[3] & 0xff);
- udelay(10);
+ usleep_range(10, 1000);
for (i = 0; i < file_length; i++) {
outb(data[16 + i], xilinx_iobase);
- udelay(10);
+ usleep_range(10, 1000);
/* Check if BUSY flag is low */
- val = inl(info->plx_regbase + PLX9052_CNTRL);
+ val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
if (val & PLX9052_CNTRL_UIO1_DATA) {
dev_err(dev->class_dev,
"Xilinx is still busy (i = %d)\n", i);
@@ -387,7 +376,7 @@
}
/* If done flag is high download was successful */
- val = inl(info->plx_regbase + PLX9052_CNTRL);
+ val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
if (!(val & PLX9052_CNTRL_UIO0_DATA)) {
dev_err(dev->class_dev, "DONE flag is not set\n");
dev_err(dev->class_dev, "Download not successful\n");
@@ -395,44 +384,53 @@
}
/* Set /CS and /WRITE */
- val = inl(info->plx_regbase + PLX9052_CNTRL);
+ val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
val |= PLX9052_CNTRL_UIO2_DATA;
- outl(val, info->plx_regbase + PLX9052_CNTRL);
+ outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
return 0;
}
+static void me4000_ai_reset(struct comedi_device *dev)
+{
+ unsigned int ctrl;
+
+ /* Stop any running conversion */
+ ctrl = inl(dev->iobase + ME4000_AI_CTRL_REG);
+ ctrl |= ME4000_AI_CTRL_STOP | ME4000_AI_CTRL_IMMEDIATE_STOP;
+ outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG);
+
+ /* Clear the control register */
+ outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
+}
+
static void me4000_reset(struct comedi_device *dev)
{
- struct me4000_info *info = dev->private;
+ struct me4000_private *devpriv = dev->private;
unsigned int val;
int chan;
- /* Make a hardware reset */
- val = inl(info->plx_regbase + PLX9052_CNTRL);
+ /* Disable interrupts on the PLX */
+ outl(0, devpriv->plx_regbase + PLX9052_INTCSR);
+
+ /* Software reset the PLX */
+ val = inl(devpriv->plx_regbase + PLX9052_CNTRL);
val |= PLX9052_CNTRL_PCI_RESET;
- outl(val, info->plx_regbase + PLX9052_CNTRL);
+ outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
val &= ~PLX9052_CNTRL_PCI_RESET;
- outl(val, info->plx_regbase + PLX9052_CNTRL);
+ outl(val, devpriv->plx_regbase + PLX9052_CNTRL);
/* 0x8000 to the DACs means an output voltage of 0V */
for (chan = 0; chan < 4; chan++)
outl(0x8000, dev->iobase + ME4000_AO_SINGLE_REG(chan));
- /* Set both stop bits in the analog input control register */
- outl(ME4000_AI_CTRL_BIT_IMMEDIATE_STOP | ME4000_AI_CTRL_BIT_STOP,
- dev->iobase + ME4000_AI_CTRL_REG);
+ me4000_ai_reset(dev);
/* Set both stop bits in the analog output control register */
- val = ME4000_AO_CTRL_BIT_IMMEDIATE_STOP | ME4000_AO_CTRL_BIT_STOP;
+ val = ME4000_AO_CTRL_IMMEDIATE_STOP | ME4000_AO_CTRL_STOP;
for (chan = 0; chan < 4; chan++)
outl(val, dev->iobase + ME4000_AO_CTRL_REG(chan));
- /* Enable interrupts on the PLX */
- outl(PLX9052_INTCSR_LI1ENAB |
- PLX9052_INTCSR_LI1POL |
- PLX9052_INTCSR_PCIENAB, info->plx_regbase + PLX9052_INTCSR);
-
/* Set the adustment register for AO demux */
outl(ME4000_AO_DEMUX_ADJUST_VALUE,
dev->iobase + ME4000_AO_DEMUX_ADJUST_REG);
@@ -445,96 +443,68 @@
outl(0x1, dev->iobase + ME4000_DIO_CTRL_REG);
}
-/*=============================================================================
- Analog input section
- ===========================================================================*/
+static unsigned int me4000_ai_get_sample(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ unsigned int val;
+
+ /* read two's complement value and munge to offset binary */
+ val = inl(dev->iobase + ME4000_AI_DATA_REG);
+ return comedi_offset_munge(s, val);
+}
+
+static int me4000_ai_eoc(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned long context)
+{
+ unsigned int status;
+
+ status = inl(dev->iobase + ME4000_AI_STATUS_REG);
+ if (status & ME4000_AI_STATUS_EF_DATA)
+ return 0;
+ return -EBUSY;
+}
static int me4000_ai_insn_read(struct comedi_device *dev,
- struct comedi_subdevice *subdevice,
- struct comedi_insn *insn, unsigned int *data)
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
{
- const struct me4000_board *board = dev->board_ptr;
- int chan = CR_CHAN(insn->chanspec);
- int rang = CR_RANGE(insn->chanspec);
- int aref = CR_AREF(insn->chanspec);
+ unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int range = CR_RANGE(insn->chanspec);
+ unsigned int aref = CR_AREF(insn->chanspec);
+ unsigned int entry;
+ int ret = 0;
+ int i;
- unsigned int entry = 0;
- unsigned int tmp;
- unsigned int lval;
-
- if (insn->n == 0) {
- return 0;
- } else if (insn->n > 1) {
- dev_err(dev->class_dev, "Invalid instruction length %d\n",
- insn->n);
- return -EINVAL;
- }
-
- switch (rang) {
- case 0:
- entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
- break;
- case 1:
- entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
- break;
- case 2:
- entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
- break;
- case 3:
- entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
- break;
- default:
- dev_err(dev->class_dev, "Invalid range specified\n");
- return -EINVAL;
- }
-
- switch (aref) {
- case AREF_GROUND:
- case AREF_COMMON:
- if (chan >= board->ai_nchan) {
+ entry = chan | ME4000_AI_LIST_RANGE(range);
+ if (aref == AREF_DIFF) {
+ if (!(s->subdev_flags & SDF_DIFF)) {
dev_err(dev->class_dev,
- "Analog input is not available\n");
+ "Differential inputs are not available\n");
return -EINVAL;
}
- entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED | chan;
- break;
- case AREF_DIFF:
- if (rang == 0 || rang == 1) {
+ if (!comedi_range_is_bipolar(s, range)) {
dev_err(dev->class_dev,
"Range must be bipolar when aref = diff\n");
return -EINVAL;
}
- if (chan >= board->ai_diff_nchan) {
+ if (chan >= (s->n_chan / 2)) {
dev_err(dev->class_dev,
"Analog input is not available\n");
return -EINVAL;
}
- entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL | chan;
- break;
- default:
- dev_err(dev->class_dev, "Invalid aref specified\n");
- return -EINVAL;
+ entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
}
entry |= ME4000_AI_LIST_LAST_ENTRY;
- /* Clear channel list, data fifo and both stop bits */
- tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
- tmp &= ~(ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
- ME4000_AI_CTRL_BIT_DATA_FIFO |
- ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
- /* Set the acquisition mode to single */
- tmp &= ~(ME4000_AI_CTRL_BIT_MODE_0 | ME4000_AI_CTRL_BIT_MODE_1 |
- ME4000_AI_CTRL_BIT_MODE_2);
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
- /* Enable channel list and data fifo */
- tmp |= ME4000_AI_CTRL_BIT_CHANNEL_FIFO | ME4000_AI_CTRL_BIT_DATA_FIFO;
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
+ /* Enable channel list and data fifo for single acquisition mode */
+ outl(ME4000_AI_CTRL_CHANNEL_FIFO | ME4000_AI_CTRL_DATA_FIFO,
+ dev->iobase + ME4000_AI_CTRL_REG);
/* Generate channel list entry */
outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
@@ -543,36 +513,29 @@
outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
outl(ME4000_AI_MIN_TICKS, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
- /* Start conversion by dummy read */
- inl(dev->iobase + ME4000_AI_START_REG);
+ for (i = 0; i < insn->n; i++) {
+ unsigned int val;
- /* Wait until ready */
- udelay(10);
- if (!(inl(dev->iobase + ME4000_AI_STATUS_REG) &
- ME4000_AI_STATUS_BIT_EF_DATA)) {
- dev_err(dev->class_dev, "Value not available after wait\n");
- return -EIO;
+ /* start conversion by dummy read */
+ inl(dev->iobase + ME4000_AI_START_REG);
+
+ ret = comedi_timeout(dev, s, insn, me4000_ai_eoc, 0);
+ if (ret)
+ break;
+
+ val = me4000_ai_get_sample(dev, s);
+ data[i] = comedi_offset_munge(s, val);
}
- /* Read value from data fifo */
- lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
- data[0] = lval ^ 0x8000;
+ me4000_ai_reset(dev);
- return 1;
+ return ret ? ret : insn->n;
}
static int me4000_ai_cancel(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- unsigned int tmp;
-
- /* Stop any running conversion */
- tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
- tmp &= ~(ME4000_AI_CTRL_BIT_STOP | ME4000_AI_CTRL_BIT_IMMEDIATE_STOP);
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
- /* Clear the control register */
- outl(0x0, dev->iobase + ME4000_AI_CTRL_REG);
+ me4000_ai_reset(dev);
return 0;
}
@@ -581,8 +544,6 @@
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
- const struct me4000_board *board = dev->board_ptr;
- unsigned int max_diff_chan = board->ai_diff_nchan;
unsigned int aref0 = CR_AREF(cmd->chanlist[0]);
int i;
@@ -598,7 +559,13 @@
}
if (aref == AREF_DIFF) {
- if (chan >= max_diff_chan) {
+ if (!(s->subdev_flags & SDF_DIFF)) {
+ dev_err(dev->class_dev,
+ "Differential inputs are not available\n");
+ return -EINVAL;
+ }
+
+ if (chan >= (s->n_chan / 2)) {
dev_dbg(dev->class_dev,
"Channel number to high\n");
return -EINVAL;
@@ -615,202 +582,127 @@
return 0;
}
-static int ai_round_cmd_args(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd,
- unsigned int *init_ticks,
- unsigned int *scan_ticks, unsigned int *chan_ticks)
+static void me4000_ai_round_cmd_args(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
{
+ struct me4000_private *devpriv = dev->private;
int rest;
- *init_ticks = 0;
- *scan_ticks = 0;
- *chan_ticks = 0;
+ devpriv->ai_init_ticks = 0;
+ devpriv->ai_scan_ticks = 0;
+ devpriv->ai_chan_ticks = 0;
if (cmd->start_arg) {
- *init_ticks = (cmd->start_arg * 33) / 1000;
+ devpriv->ai_init_ticks = (cmd->start_arg * 33) / 1000;
rest = (cmd->start_arg * 33) % 1000;
if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
if (rest > 33)
- (*init_ticks)++;
+ devpriv->ai_init_ticks++;
} else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
if (rest)
- (*init_ticks)++;
+ devpriv->ai_init_ticks++;
}
}
if (cmd->scan_begin_arg) {
- *scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
+ devpriv->ai_scan_ticks = (cmd->scan_begin_arg * 33) / 1000;
rest = (cmd->scan_begin_arg * 33) % 1000;
if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
if (rest > 33)
- (*scan_ticks)++;
+ devpriv->ai_scan_ticks++;
} else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
if (rest)
- (*scan_ticks)++;
+ devpriv->ai_scan_ticks++;
}
}
if (cmd->convert_arg) {
- *chan_ticks = (cmd->convert_arg * 33) / 1000;
+ devpriv->ai_chan_ticks = (cmd->convert_arg * 33) / 1000;
rest = (cmd->convert_arg * 33) % 1000;
if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_NEAREST) {
if (rest > 33)
- (*chan_ticks)++;
+ devpriv->ai_chan_ticks++;
} else if ((cmd->flags & CMDF_ROUND_MASK) == CMDF_ROUND_UP) {
if (rest)
- (*chan_ticks)++;
+ devpriv->ai_chan_ticks++;
}
}
-
- return 0;
}
-static void ai_write_timer(struct comedi_device *dev,
- unsigned int init_ticks,
- unsigned int scan_ticks, unsigned int chan_ticks)
+static void me4000_ai_write_chanlist(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
{
- outl(init_ticks - 1, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
- outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
-
- if (scan_ticks) {
- outl(scan_ticks - 1, dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
- outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
- }
-
- outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
- outl(chan_ticks - 1, dev->iobase + ME4000_AI_CHAN_TIMER_REG);
-}
-
-static int ai_write_chanlist(struct comedi_device *dev,
- struct comedi_subdevice *s, struct comedi_cmd *cmd)
-{
- unsigned int entry;
- unsigned int chan;
- unsigned int rang;
- unsigned int aref;
int i;
for (i = 0; i < cmd->chanlist_len; i++) {
- chan = CR_CHAN(cmd->chanlist[i]);
- rang = CR_RANGE(cmd->chanlist[i]);
- aref = CR_AREF(cmd->chanlist[i]);
+ unsigned int chan = CR_CHAN(cmd->chanlist[i]);
+ unsigned int range = CR_RANGE(cmd->chanlist[i]);
+ unsigned int aref = CR_AREF(cmd->chanlist[i]);
+ unsigned int entry;
- entry = chan;
-
- if (rang == 0)
- entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_2_5;
- else if (rang == 1)
- entry |= ME4000_AI_LIST_RANGE_UNIPOLAR_10;
- else if (rang == 2)
- entry |= ME4000_AI_LIST_RANGE_BIPOLAR_2_5;
- else
- entry |= ME4000_AI_LIST_RANGE_BIPOLAR_10;
+ entry = chan | ME4000_AI_LIST_RANGE(range);
if (aref == AREF_DIFF)
entry |= ME4000_AI_LIST_INPUT_DIFFERENTIAL;
- else
- entry |= ME4000_AI_LIST_INPUT_SINGLE_ENDED;
+
+ if (i == (cmd->chanlist_len - 1))
+ entry |= ME4000_AI_LIST_LAST_ENTRY;
outl(entry, dev->iobase + ME4000_AI_CHANNEL_LIST_REG);
}
-
- return 0;
-}
-
-static int ai_prepare(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_cmd *cmd,
- unsigned int init_ticks,
- unsigned int scan_ticks, unsigned int chan_ticks)
-{
- unsigned int tmp = 0;
-
- /* Write timer arguments */
- ai_write_timer(dev, init_ticks, scan_ticks, chan_ticks);
-
- /* Reset control register */
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
- /* Start sources */
- if ((cmd->start_src == TRIG_EXT &&
- cmd->scan_begin_src == TRIG_TIMER &&
- cmd->convert_src == TRIG_TIMER) ||
- (cmd->start_src == TRIG_EXT &&
- cmd->scan_begin_src == TRIG_FOLLOW &&
- cmd->convert_src == TRIG_TIMER)) {
- tmp = ME4000_AI_CTRL_BIT_MODE_1 |
- ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
- ME4000_AI_CTRL_BIT_DATA_FIFO;
- } else if (cmd->start_src == TRIG_EXT &&
- cmd->scan_begin_src == TRIG_EXT &&
- cmd->convert_src == TRIG_TIMER) {
- tmp = ME4000_AI_CTRL_BIT_MODE_2 |
- ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
- ME4000_AI_CTRL_BIT_DATA_FIFO;
- } else if (cmd->start_src == TRIG_EXT &&
- cmd->scan_begin_src == TRIG_EXT &&
- cmd->convert_src == TRIG_EXT) {
- tmp = ME4000_AI_CTRL_BIT_MODE_0 |
- ME4000_AI_CTRL_BIT_MODE_1 |
- ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
- ME4000_AI_CTRL_BIT_DATA_FIFO;
- } else {
- tmp = ME4000_AI_CTRL_BIT_MODE_0 |
- ME4000_AI_CTRL_BIT_CHANNEL_FIFO |
- ME4000_AI_CTRL_BIT_DATA_FIFO;
- }
-
- /* Stop triggers */
- if (cmd->stop_src == TRIG_COUNT) {
- outl(cmd->chanlist_len * cmd->stop_arg,
- dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
- tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
- } else if (cmd->stop_src == TRIG_NONE &&
- cmd->scan_end_src == TRIG_COUNT) {
- outl(cmd->scan_end_arg,
- dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
- tmp |= ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ;
- } else {
- tmp |= ME4000_AI_CTRL_BIT_HF_IRQ;
- }
-
- /* Write the setup to the control register */
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
- /* Write the channel list */
- ai_write_chanlist(dev, s, cmd);
-
- return 0;
}
static int me4000_ai_do_cmd(struct comedi_device *dev,
struct comedi_subdevice *s)
{
- int err;
- unsigned int init_ticks = 0;
- unsigned int scan_ticks = 0;
- unsigned int chan_ticks = 0;
+ struct me4000_private *devpriv = dev->private;
struct comedi_cmd *cmd = &s->async->cmd;
+ unsigned int ctrl;
- /* Reset the analog input */
- err = me4000_ai_cancel(dev, s);
- if (err)
- return err;
+ /* Write timer arguments */
+ outl(devpriv->ai_init_ticks - 1,
+ dev->iobase + ME4000_AI_SCAN_PRE_TIMER_LOW_REG);
+ outl(0x0, dev->iobase + ME4000_AI_SCAN_PRE_TIMER_HIGH_REG);
- /* Round the timer arguments */
- err = ai_round_cmd_args(dev,
- s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
- if (err)
- return err;
+ if (devpriv->ai_scan_ticks) {
+ outl(devpriv->ai_scan_ticks - 1,
+ dev->iobase + ME4000_AI_SCAN_TIMER_LOW_REG);
+ outl(0x0, dev->iobase + ME4000_AI_SCAN_TIMER_HIGH_REG);
+ }
- /* Prepare the AI for acquisition */
- err = ai_prepare(dev, s, cmd, init_ticks, scan_ticks, chan_ticks);
- if (err)
- return err;
+ outl(devpriv->ai_chan_ticks - 1,
+ dev->iobase + ME4000_AI_CHAN_PRE_TIMER_REG);
+ outl(devpriv->ai_chan_ticks - 1,
+ dev->iobase + ME4000_AI_CHAN_TIMER_REG);
+
+ /* Start sources */
+ ctrl = devpriv->ai_ctrl_mode |
+ ME4000_AI_CTRL_CHANNEL_FIFO |
+ ME4000_AI_CTRL_DATA_FIFO;
+
+ /* Stop triggers */
+ if (cmd->stop_src == TRIG_COUNT) {
+ outl(cmd->chanlist_len * cmd->stop_arg,
+ dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
+ ctrl |= ME4000_AI_CTRL_SC_IRQ;
+ } else if (cmd->stop_src == TRIG_NONE &&
+ cmd->scan_end_src == TRIG_COUNT) {
+ outl(cmd->scan_end_arg,
+ dev->iobase + ME4000_AI_SAMPLE_COUNTER_REG);
+ ctrl |= ME4000_AI_CTRL_SC_IRQ;
+ }
+ ctrl |= ME4000_AI_CTRL_HF_IRQ;
+
+ /* Write the setup to the control register */
+ outl(ctrl, dev->iobase + ME4000_AI_CTRL_REG);
+
+ /* Write the channel list */
+ me4000_ai_write_chanlist(dev, s, cmd);
/* Start acquistion by dummy read */
inl(dev->iobase + ME4000_AI_START_REG);
@@ -822,14 +714,9 @@
struct comedi_subdevice *s,
struct comedi_cmd *cmd)
{
- unsigned int init_ticks;
- unsigned int chan_ticks;
- unsigned int scan_ticks;
+ struct me4000_private *devpriv = dev->private;
int err = 0;
- /* Round the timer arguments */
- ai_round_cmd_args(dev, s, cmd, &init_ticks, &scan_ticks, &chan_ticks);
-
/* Step 1 : check if triggers are trivially valid */
err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
@@ -857,21 +744,28 @@
if (cmd->start_src == TRIG_NOW &&
cmd->scan_begin_src == TRIG_TIMER &&
cmd->convert_src == TRIG_TIMER) {
+ devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0;
} else if (cmd->start_src == TRIG_NOW &&
cmd->scan_begin_src == TRIG_FOLLOW &&
cmd->convert_src == TRIG_TIMER) {
+ devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0;
} else if (cmd->start_src == TRIG_EXT &&
cmd->scan_begin_src == TRIG_TIMER &&
cmd->convert_src == TRIG_TIMER) {
+ devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1;
} else if (cmd->start_src == TRIG_EXT &&
cmd->scan_begin_src == TRIG_FOLLOW &&
cmd->convert_src == TRIG_TIMER) {
+ devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_1;
} else if (cmd->start_src == TRIG_EXT &&
cmd->scan_begin_src == TRIG_EXT &&
cmd->convert_src == TRIG_TIMER) {
+ devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_2;
} else if (cmd->start_src == TRIG_EXT &&
cmd->scan_begin_src == TRIG_EXT &&
cmd->convert_src == TRIG_EXT) {
+ devpriv->ai_ctrl_mode = ME4000_AI_CTRL_MODE_0 |
+ ME4000_AI_CTRL_MODE_1;
} else {
err |= -EINVAL;
}
@@ -887,15 +781,19 @@
cmd->chanlist_len = 1;
err |= -EINVAL;
}
- if (init_ticks < 66) {
+
+ /* Round the timer arguments */
+ me4000_ai_round_cmd_args(dev, s, cmd);
+
+ if (devpriv->ai_init_ticks < 66) {
cmd->start_arg = 2000;
err |= -EINVAL;
}
- if (scan_ticks && scan_ticks < 67) {
+ if (devpriv->ai_scan_ticks && devpriv->ai_scan_ticks < 67) {
cmd->scan_begin_arg = 2031;
err |= -EINVAL;
}
- if (chan_ticks < 66) {
+ if (devpriv->ai_chan_ticks < 66) {
cmd->convert_arg = 2000;
err |= -EINVAL;
}
@@ -915,17 +813,18 @@
cmd->scan_begin_src == TRIG_TIMER &&
cmd->convert_src == TRIG_TIMER) {
/* Check timer arguments */
- if (init_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
- if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
}
- if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
+ if (devpriv->ai_scan_ticks <=
+ cmd->chanlist_len * devpriv->ai_chan_ticks) {
dev_err(dev->class_dev, "Invalid scan end arg\n");
/* At least one tick more */
@@ -936,12 +835,12 @@
cmd->scan_begin_src == TRIG_FOLLOW &&
cmd->convert_src == TRIG_TIMER) {
/* Check timer arguments */
- if (init_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
- if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
@@ -950,17 +849,18 @@
cmd->scan_begin_src == TRIG_TIMER &&
cmd->convert_src == TRIG_TIMER) {
/* Check timer arguments */
- if (init_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
- if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
}
- if (scan_ticks <= cmd->chanlist_len * chan_ticks) {
+ if (devpriv->ai_scan_ticks <=
+ cmd->chanlist_len * devpriv->ai_chan_ticks) {
dev_err(dev->class_dev, "Invalid scan end arg\n");
/* At least one tick more */
@@ -971,12 +871,12 @@
cmd->scan_begin_src == TRIG_FOLLOW &&
cmd->convert_src == TRIG_TIMER) {
/* Check timer arguments */
- if (init_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
- if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
@@ -985,12 +885,12 @@
cmd->scan_begin_src == TRIG_EXT &&
cmd->convert_src == TRIG_TIMER) {
/* Check timer arguments */
- if (init_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
}
- if (chan_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_chan_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid convert arg\n");
cmd->convert_arg = 2000; /* 66 ticks at least */
err++;
@@ -999,7 +899,7 @@
cmd->scan_begin_src == TRIG_EXT &&
cmd->convert_src == TRIG_EXT) {
/* Check timer arguments */
- if (init_ticks < ME4000_AI_MIN_TICKS) {
+ if (devpriv->ai_init_ticks < ME4000_AI_MIN_TICKS) {
dev_err(dev->class_dev, "Invalid start arg\n");
cmd->start_arg = 2000; /* 66 ticks at least */
err++;
@@ -1039,103 +939,57 @@
return IRQ_NONE;
if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
- ME4000_IRQ_STATUS_BIT_AI_HF) {
+ ME4000_IRQ_STATUS_AI_HF) {
/* Read status register to find out what happened */
- tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
+ tmp = inl(dev->iobase + ME4000_AI_STATUS_REG);
- if (!(tmp & ME4000_AI_STATUS_BIT_FF_DATA) &&
- !(tmp & ME4000_AI_STATUS_BIT_HF_DATA) &&
- (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
- c = ME4000_AI_FIFO_COUNT;
-
- /*
- * FIFO overflow, so stop conversion
- * and disable all interrupts
- */
- tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
- tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
- ME4000_AI_CTRL_BIT_SC_IRQ);
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
- s->async->events |= COMEDI_CB_ERROR;
-
+ if (!(tmp & ME4000_AI_STATUS_FF_DATA) &&
+ !(tmp & ME4000_AI_STATUS_HF_DATA) &&
+ (tmp & ME4000_AI_STATUS_EF_DATA)) {
dev_err(dev->class_dev, "FIFO overflow\n");
- } else if ((tmp & ME4000_AI_STATUS_BIT_FF_DATA)
- && !(tmp & ME4000_AI_STATUS_BIT_HF_DATA)
- && (tmp & ME4000_AI_STATUS_BIT_EF_DATA)) {
+ s->async->events |= COMEDI_CB_ERROR;
+ c = ME4000_AI_FIFO_COUNT;
+ } else if ((tmp & ME4000_AI_STATUS_FF_DATA) &&
+ !(tmp & ME4000_AI_STATUS_HF_DATA) &&
+ (tmp & ME4000_AI_STATUS_EF_DATA)) {
c = ME4000_AI_FIFO_COUNT / 2;
} else {
- dev_err(dev->class_dev,
- "Can't determine state of fifo\n");
- c = 0;
-
- /*
- * Undefined state, so stop conversion
- * and disable all interrupts
- */
- tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
- tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
- ME4000_AI_CTRL_BIT_SC_IRQ);
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
- s->async->events |= COMEDI_CB_ERROR;
-
dev_err(dev->class_dev, "Undefined FIFO state\n");
+ s->async->events |= COMEDI_CB_ERROR;
+ c = 0;
}
for (i = 0; i < c; i++) {
- /* Read value from data fifo */
- lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
- lval ^= 0x8000;
-
- if (!comedi_buf_write_samples(s, &lval, 1)) {
- /*
- * Buffer overflow, so stop conversion
- * and disable all interrupts
- */
- tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
- tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ |
- ME4000_AI_CTRL_BIT_SC_IRQ);
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
- break;
- }
- }
-
- /* Work is done, so reset the interrupt */
- tmp |= ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
- tmp &= ~ME4000_AI_CTRL_BIT_HF_IRQ_RESET;
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
- }
-
- if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
- ME4000_IRQ_STATUS_BIT_SC) {
- s->async->events |= COMEDI_CB_EOA;
-
- /*
- * Acquisition is complete, so stop
- * conversion and disable all interrupts
- */
- tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
- tmp |= ME4000_AI_CTRL_BIT_IMMEDIATE_STOP;
- tmp &= ~(ME4000_AI_CTRL_BIT_HF_IRQ | ME4000_AI_CTRL_BIT_SC_IRQ);
- outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
-
- /* Poll data until fifo empty */
- while (inl(dev->iobase + ME4000_AI_CTRL_REG) &
- ME4000_AI_STATUS_BIT_EF_DATA) {
- /* Read value from data fifo */
- lval = inl(dev->iobase + ME4000_AI_DATA_REG) & 0xFFFF;
- lval ^= 0x8000;
-
+ lval = me4000_ai_get_sample(dev, s);
if (!comedi_buf_write_samples(s, &lval, 1))
break;
}
/* Work is done, so reset the interrupt */
- tmp |= ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
+ tmp |= ME4000_AI_CTRL_HF_IRQ_RESET;
outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
- tmp &= ~ME4000_AI_CTRL_BIT_SC_IRQ_RESET;
+ tmp &= ~ME4000_AI_CTRL_HF_IRQ_RESET;
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
+ }
+
+ if (inl(dev->iobase + ME4000_IRQ_STATUS_REG) &
+ ME4000_IRQ_STATUS_SC) {
+ /* Acquisition is complete */
+ s->async->events |= COMEDI_CB_EOA;
+
+ /* Poll data until fifo empty */
+ while (inl(dev->iobase + ME4000_AI_STATUS_REG) &
+ ME4000_AI_STATUS_EF_DATA) {
+ lval = me4000_ai_get_sample(dev, s);
+ if (!comedi_buf_write_samples(s, &lval, 1))
+ break;
+ }
+
+ /* Work is done, so reset the interrupt */
+ tmp = inl(dev->iobase + ME4000_AI_CTRL_REG);
+ tmp |= ME4000_AI_CTRL_SC_IRQ_RESET;
+ outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
+ tmp &= ~ME4000_AI_CTRL_SC_IRQ_RESET;
outl(tmp, dev->iobase + ME4000_AI_CTRL_REG);
}
@@ -1149,12 +1003,12 @@
struct comedi_insn *insn,
unsigned int *data)
{
- int chan = CR_CHAN(insn->chanspec);
+ unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int tmp;
/* Stop any running conversion */
tmp = inl(dev->iobase + ME4000_AO_CTRL_REG(chan));
- tmp |= ME4000_AO_CTRL_BIT_IMMEDIATE_STOP;
+ tmp |= ME4000_AO_CTRL_IMMEDIATE_STOP;
outl(tmp, dev->iobase + ME4000_AO_CTRL_REG(chan));
/* Clear control register and set to single mode */
@@ -1217,18 +1071,18 @@
return ret;
tmp = inl(dev->iobase + ME4000_DIO_CTRL_REG);
- tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_0 | ME4000_DIO_CTRL_BIT_MODE_1 |
- ME4000_DIO_CTRL_BIT_MODE_2 | ME4000_DIO_CTRL_BIT_MODE_3 |
- ME4000_DIO_CTRL_BIT_MODE_4 | ME4000_DIO_CTRL_BIT_MODE_5 |
- ME4000_DIO_CTRL_BIT_MODE_6 | ME4000_DIO_CTRL_BIT_MODE_7);
+ tmp &= ~(ME4000_DIO_CTRL_MODE_0 | ME4000_DIO_CTRL_MODE_1 |
+ ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3 |
+ ME4000_DIO_CTRL_MODE_4 | ME4000_DIO_CTRL_MODE_5 |
+ ME4000_DIO_CTRL_MODE_6 | ME4000_DIO_CTRL_MODE_7);
if (s->io_bits & 0x000000ff)
- tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
+ tmp |= ME4000_DIO_CTRL_MODE_0;
if (s->io_bits & 0x0000ff00)
- tmp |= ME4000_DIO_CTRL_BIT_MODE_2;
+ tmp |= ME4000_DIO_CTRL_MODE_2;
if (s->io_bits & 0x00ff0000)
- tmp |= ME4000_DIO_CTRL_BIT_MODE_4;
+ tmp |= ME4000_DIO_CTRL_MODE_4;
if (s->io_bits & 0xff000000)
- tmp |= ME4000_DIO_CTRL_BIT_MODE_6;
+ tmp |= ME4000_DIO_CTRL_MODE_6;
/*
* Check for optoisolated ME-4000 version.
@@ -1238,9 +1092,8 @@
if (inl(dev->iobase + ME4000_DIO_DIR_REG)) {
s->io_bits |= 0x000000ff;
s->io_bits &= ~0x0000ff00;
- tmp |= ME4000_DIO_CTRL_BIT_MODE_0;
- tmp &= ~(ME4000_DIO_CTRL_BIT_MODE_2 |
- ME4000_DIO_CTRL_BIT_MODE_3);
+ tmp |= ME4000_DIO_CTRL_MODE_0;
+ tmp &= ~(ME4000_DIO_CTRL_MODE_2 | ME4000_DIO_CTRL_MODE_3);
}
outl(tmp, dev->iobase + ME4000_DIO_CTRL_REG);
@@ -1253,7 +1106,7 @@
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
const struct me4000_board *board = NULL;
- struct me4000_info *info;
+ struct me4000_private *devpriv;
struct comedi_subdevice *s;
int result;
@@ -1264,17 +1117,17 @@
dev->board_ptr = board;
dev->board_name = board->name;
- info = comedi_alloc_devpriv(dev, sizeof(*info));
- if (!info)
+ devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
+ if (!devpriv)
return -ENOMEM;
result = comedi_pci_enable(dev);
if (result)
return result;
- info->plx_regbase = pci_resource_start(pcidev, 1);
+ devpriv->plx_regbase = pci_resource_start(pcidev, 1);
dev->iobase = pci_resource_start(pcidev, 2);
- if (!info->plx_regbase || !dev->iobase)
+ if (!devpriv->plx_regbase || !dev->iobase)
return -ENODEV;
result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE,
@@ -1287,79 +1140,66 @@
if (pcidev->irq > 0) {
result = request_irq(pcidev->irq, me4000_ai_isr, IRQF_SHARED,
dev->board_name, dev);
- if (result == 0)
+ if (result == 0) {
dev->irq = pcidev->irq;
+
+ /* Enable interrupts on the PLX */
+ outl(PLX9052_INTCSR_LI1ENAB | PLX9052_INTCSR_LI1POL |
+ PLX9052_INTCSR_PCIENAB,
+ devpriv->plx_regbase + PLX9052_INTCSR);
+ }
}
result = comedi_alloc_subdevices(dev, 4);
if (result)
return result;
- /*=========================================================================
- Analog input subdevice
- ========================================================================*/
-
+ /* Analog Input subdevice */
s = &dev->subdevices[0];
+ s->type = COMEDI_SUBD_AI;
+ s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND;
+ if (board->can_do_diff_ai)
+ s->subdev_flags |= SDF_DIFF;
+ s->n_chan = board->ai_nchan;
+ s->maxdata = 0xffff;
+ s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
+ s->range_table = &me4000_ai_range;
+ s->insn_read = me4000_ai_insn_read;
- if (board->ai_nchan) {
- s->type = COMEDI_SUBD_AI;
- s->subdev_flags =
- SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
- s->n_chan = board->ai_nchan;
- s->maxdata = 0xFFFF; /* 16 bit ADC */
- s->len_chanlist = ME4000_AI_CHANNEL_LIST_COUNT;
- s->range_table = &me4000_ai_range;
- s->insn_read = me4000_ai_insn_read;
-
- if (dev->irq) {
- dev->read_subdev = s;
- s->subdev_flags |= SDF_CMD_READ;
- s->cancel = me4000_ai_cancel;
- s->do_cmdtest = me4000_ai_do_cmd_test;
- s->do_cmd = me4000_ai_do_cmd;
- }
- } else {
- s->type = COMEDI_SUBD_UNUSED;
+ if (dev->irq) {
+ dev->read_subdev = s;
+ s->subdev_flags |= SDF_CMD_READ;
+ s->cancel = me4000_ai_cancel;
+ s->do_cmdtest = me4000_ai_do_cmd_test;
+ s->do_cmd = me4000_ai_do_cmd;
}
- /*=========================================================================
- Analog output subdevice
- ========================================================================*/
-
+ /* Analog Output subdevice */
s = &dev->subdevices[1];
-
- if (board->ao_nchan) {
- s->type = COMEDI_SUBD_AO;
- s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND;
- s->n_chan = board->ao_nchan;
- s->maxdata = 0xFFFF; /* 16 bit DAC */
- s->range_table = &range_bipolar10;
- s->insn_write = me4000_ao_insn_write;
+ if (board->has_ao) {
+ s->type = COMEDI_SUBD_AO;
+ s->subdev_flags = SDF_WRITABLE | SDF_COMMON | SDF_GROUND;
+ s->n_chan = 4;
+ s->maxdata = 0xffff;
+ s->range_table = &range_bipolar10;
+ s->insn_write = me4000_ao_insn_write;
result = comedi_alloc_subdev_readback(s);
if (result)
return result;
} else {
- s->type = COMEDI_SUBD_UNUSED;
+ s->type = COMEDI_SUBD_UNUSED;
}
- /*=========================================================================
- Digital I/O subdevice
- ========================================================================*/
-
+ /* Digital I/O subdevice */
s = &dev->subdevices[2];
-
- if (board->dio_nchan) {
- s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
- s->n_chan = board->dio_nchan;
- s->maxdata = 1;
- s->range_table = &range_digital;
- s->insn_bits = me4000_dio_insn_bits;
- s->insn_config = me4000_dio_insn_config;
- } else {
- s->type = COMEDI_SUBD_UNUSED;
- }
+ s->type = COMEDI_SUBD_DIO;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
+ s->n_chan = 32;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = me4000_dio_insn_bits;
+ s->insn_config = me4000_dio_insn_config;
/*
* Check for optoisolated ME-4000 version. If one the first
@@ -1367,7 +1207,7 @@
*/
if (!inl(dev->iobase + ME4000_DIO_DIR_REG)) {
s->io_bits |= 0xFF;
- outl(ME4000_DIO_CTRL_BIT_MODE_0,
+ outl(ME4000_DIO_CTRL_MODE_0,
dev->iobase + ME4000_DIO_DIR_REG);
}
@@ -1393,8 +1233,12 @@
static void me4000_detach(struct comedi_device *dev)
{
- if (dev->iobase)
- me4000_reset(dev);
+ if (dev->irq) {
+ struct me4000_private *devpriv = dev->private;
+
+ /* Disable interrupts on the PLX */
+ outl(0, devpriv->plx_regbase + PLX9052_INTCSR);
+ }
comedi_pci_detach(dev);
}
@@ -1438,6 +1282,6 @@
module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for Meilhaus ME-4000 series boards");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(ME4000_FIRMWARE);
diff --git a/drivers/staging/comedi/drivers/ni_daq_dio24.c b/drivers/staging/comedi/drivers/ni_daq_dio24.c
index a208cb3..d9de83a 100644
--- a/drivers/staging/comedi/drivers/ni_daq_dio24.c
+++ b/drivers/staging/comedi/drivers/ni_daq_dio24.c
@@ -55,11 +55,7 @@
/* 8255 dio */
s = &dev->subdevices[0];
- ret = subdev_8255_init(dev, s, NULL, 0x00);
- if (ret)
- return ret;
-
- return 0;
+ return subdev_8255_init(dev, s, NULL, 0x00);
}
static struct comedi_driver driver_dio24 = {
diff --git a/drivers/staging/comedi/drivers/ni_usb6501.c b/drivers/staging/comedi/drivers/ni_usb6501.c
index 5f649f8..88de8da 100644
--- a/drivers/staging/comedi/drivers/ni_usb6501.c
+++ b/drivers/staging/comedi/drivers/ni_usb6501.c
@@ -172,7 +172,7 @@
};
static int ni6501_port_command(struct comedi_device *dev, int command,
- const u8 *port, u8 *bitmap)
+ unsigned int val, u8 *bitmap)
{
struct usb_device *usb = comedi_to_usb_dev(dev);
struct ni6501_private *devpriv = dev->private;
@@ -190,22 +190,22 @@
request_size = sizeof(READ_PORT_REQUEST);
response_size = sizeof(READ_PORT_RESPONSE);
memcpy(tx, READ_PORT_REQUEST, request_size);
- tx[14] = port[0];
+ tx[14] = val & 0xff;
break;
case WRITE_PORT:
request_size = sizeof(WRITE_PORT_REQUEST);
response_size = sizeof(GENERIC_RESPONSE);
memcpy(tx, WRITE_PORT_REQUEST, request_size);
- tx[14] = port[0];
- tx[17] = bitmap[0];
+ tx[14] = val & 0xff;
+ tx[17] = *bitmap;
break;
case SET_PORT_DIR:
request_size = sizeof(SET_PORT_DIR_REQUEST);
response_size = sizeof(GENERIC_RESPONSE);
memcpy(tx, SET_PORT_DIR_REQUEST, request_size);
- tx[14] = port[0];
- tx[15] = port[1];
- tx[16] = port[2];
+ tx[14] = val & 0xff;
+ tx[15] = (val >> 8) & 0xff;
+ tx[16] = (val >> 16) & 0xff;
break;
default:
ret = -EINVAL;
@@ -235,7 +235,7 @@
/* Check if results are valid */
if (command == READ_PORT) {
- bitmap[0] = devpriv->usb_rx_buf[14];
+ *bitmap = devpriv->usb_rx_buf[14];
/* mask bitmap for comparing */
devpriv->usb_rx_buf[14] = 0x00;
@@ -349,17 +349,12 @@
unsigned int *data)
{
int ret;
- u8 port[3];
ret = comedi_dio_insn_config(dev, s, insn, data, 0);
if (ret)
return ret;
- port[0] = (s->io_bits) & 0xff;
- port[1] = (s->io_bits >> 8) & 0xff;
- port[2] = (s->io_bits >> 16) & 0xff;
-
- ret = ni6501_port_command(dev, SET_PORT_DIR, port, NULL);
+ ret = ni6501_port_command(dev, SET_PORT_DIR, s->io_bits, NULL);
if (ret)
return ret;
@@ -382,7 +377,7 @@
if (mask & (0xFF << port * 8)) {
bitmap = (s->state >> port * 8) & 0xFF;
ret = ni6501_port_command(dev, WRITE_PORT,
- &port, &bitmap);
+ port, &bitmap);
if (ret)
return ret;
}
@@ -391,7 +386,7 @@
data[1] = 0;
for (port = 0; port < 3; port++) {
- ret = ni6501_port_command(dev, READ_PORT, &port, &bitmap);
+ ret = ni6501_port_command(dev, READ_PORT, port, &bitmap);
if (ret)
return ret;
data[1] |= bitmap << port * 8;
diff --git a/drivers/staging/comedi/drivers/pcl816.c b/drivers/staging/comedi/drivers/pcl816.c
index 781b321..a353d1b 100644
--- a/drivers/staging/comedi/drivers/pcl816.c
+++ b/drivers/staging/comedi/drivers/pcl816.c
@@ -305,7 +305,7 @@
chansegment[0] = chanlist[0];
for (i = 1, seglen = 1; i < chanlen; i++, seglen++) {
/* we detect loop, this must by finish */
- if (chanlist[0] == chanlist[i])
+ if (chanlist[0] == chanlist[i])
break;
nowmustbechan =
(CR_CHAN(chansegment[i - 1]) + 1) % chanlen;
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c
index 781918d..35f0f67 100644
--- a/drivers/staging/comedi/drivers/s626.c
+++ b/drivers/staging/comedi/drivers/s626.c
@@ -2852,11 +2852,7 @@
s->insn_read = s626_enc_insn_read;
s->insn_write = s626_enc_insn_write;
- ret = s626_initialize(dev);
- if (ret)
- return ret;
-
- return 0;
+ return s626_initialize(dev);
}
static void s626_detach(struct comedi_device *dev)
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index 83da162..5f19374 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/slab.h>
+#include <linux/ktime.h>
#include <linux/termios.h>
#include <asm/ioctls.h>
@@ -121,9 +122,9 @@
static void serial2002_tty_read_poll_wait(struct file *f, int timeout)
{
struct poll_wqueues table;
- struct timeval start, now;
+ ktime_t start, now;
- do_gettimeofday(&start);
+ start = ktime_get();
poll_initwait(&table);
while (1) {
long elapsed;
@@ -134,9 +135,8 @@
POLLHUP | POLLERR)) {
break;
}
- do_gettimeofday(&now);
- elapsed = 1000000 * (now.tv_sec - start.tv_sec) +
- now.tv_usec - start.tv_usec;
+ now = ktime_get();
+ elapsed = ktime_us_delta(now, start);
if (elapsed > timeout)
break;
set_current_state(TASK_INTERRUPTIBLE);
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c
index eaa9add..649cf47 100644
--- a/drivers/staging/comedi/drivers/usbduxsigma.c
+++ b/drivers/staging/comedi/drivers/usbduxsigma.c
@@ -1,6 +1,6 @@
/*
* usbduxsigma.c
- * Copyright (C) 2011-2014 Bernd Porr, mail@berndporr.me.uk
+ * Copyright (C) 2011-2015 Bernd Porr, mail@berndporr.me.uk
*
* 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
@@ -18,7 +18,7 @@
* Description: University of Stirling USB DAQ & INCITE Technology Limited
* Devices: [ITL] USB-DUX-SIGMA (usbduxsigma)
* Author: Bernd Porr <mail@berndporr.me.uk>
- * Updated: 10 Oct 2014
+ * Updated: 20 July 2015
* Status: stable
*/
@@ -39,6 +39,7 @@
* 0.4: fixed D/A voltage range
* 0.5: various bug fixes, health check at startup
* 0.6: corrected wrong input range
+ * 0.7: rewrite code that urb->interval is always 1
*/
#include <linux/kernel.h>
@@ -122,7 +123,7 @@
#define RETRIES 10
/* bulk transfer commands to usbduxsigma */
-#define USBBUXSIGMA_AD_CMD 0
+#define USBBUXSIGMA_AD_CMD 9
#define USBDUXSIGMA_DA_CMD 1
#define USBDUXSIGMA_DIO_CFG_CMD 2
#define USBDUXSIGMA_DIO_BITS_CMD 3
@@ -217,24 +218,28 @@
int ret;
int i;
- devpriv->ai_counter--;
- if (devpriv->ai_counter == 0) {
- devpriv->ai_counter = devpriv->ai_timer;
+ if ((urb->actual_length > 0) && (urb->status != -EXDEV)) {
+ devpriv->ai_counter--;
+ if (devpriv->ai_counter == 0) {
+ devpriv->ai_counter = devpriv->ai_timer;
- /* get the data from the USB bus and hand it over to comedi */
- for (i = 0; i < cmd->chanlist_len; i++) {
- /* transfer data, note first byte is the DIO state */
- val = be32_to_cpu(devpriv->in_buf[i+1]);
- val &= 0x00ffffff; /* strip status byte */
- val ^= 0x00800000; /* convert to unsigned */
+ /* get the data from the USB bus
+ and hand it over to comedi */
+ for (i = 0; i < cmd->chanlist_len; i++) {
+ /* transfer data,
+ note first byte is the DIO state */
+ val = be32_to_cpu(devpriv->in_buf[i+1]);
+ val &= 0x00ffffff; /* strip status byte */
+ val ^= 0x00800000; /* convert to unsigned */
- if (!comedi_buf_write_samples(s, &val, 1))
- return;
+ if (!comedi_buf_write_samples(s, &val, 1))
+ return;
+ }
+
+ if (cmd->stop_src == TRIG_COUNT &&
+ async->scans_done >= cmd->stop_arg)
+ async->events |= COMEDI_CB_EOA;
}
-
- if (cmd->stop_src == TRIG_COUNT &&
- async->scans_done >= cmd->stop_arg)
- async->events |= COMEDI_CB_EOA;
}
/* if command is still running, resubmit urb */
@@ -374,10 +379,7 @@
urb->transfer_buffer_length = SIZEOUTBUF;
urb->dev = comedi_to_usb_dev(dev);
urb->status = 0;
- if (devpriv->high_speed)
- urb->interval = 8; /* uframes */
- else
- urb->interval = 1; /* frames */
+ urb->interval = 1; /* (u)frames */
urb->number_of_packets = 1;
urb->iso_frame_desc[0].offset = 0;
urb->iso_frame_desc[0].length = SIZEOUTBUF;
@@ -441,7 +443,6 @@
int input_urb)
{
struct usb_device *usb = comedi_to_usb_dev(dev);
- struct usbduxsigma_private *devpriv = dev->private;
struct urb *urb;
int ret;
int i;
@@ -452,7 +453,7 @@
/* in case of a resubmission after an unlink... */
if (input_urb)
- urb->interval = devpriv->ai_interval;
+ urb->interval = 1;
urb->context = dev;
urb->dev = usb;
urb->status = 0;
@@ -481,6 +482,7 @@
struct usbduxsigma_private *devpriv = dev->private;
int high_speed = devpriv->high_speed;
int interval = usbduxsigma_chans_to_interval(cmd->chanlist_len);
+ unsigned int tmp;
int err = 0;
/* Step 1 : check if triggers are trivially valid */
@@ -508,35 +510,20 @@
err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
- if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
- err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-
- if (cmd->scan_begin_src == TRIG_TIMER) {
- unsigned int tmp;
-
- if (high_speed) {
- /*
- * In high speed mode microframes are possible.
- * However, during one microframe we can roughly
- * sample two channels. Thus, the more channels
- * are in the channel list the more time we need.
- */
- err |= comedi_check_trigger_arg_min(&cmd->
- scan_begin_arg,
- (1000000 / 8 *
- interval));
-
- tmp = (cmd->scan_begin_arg / 125000) * 125000;
- } else {
- /* full speed */
- /* 1kHz scans every USB frame */
- err |= comedi_check_trigger_arg_min(&cmd->
- scan_begin_arg,
- 1000000);
-
- tmp = (cmd->scan_begin_arg / 1000000) * 1000000;
- }
- err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
+ if (high_speed) {
+ /*
+ * In high speed mode microframes are possible.
+ * However, during one microframe we can roughly
+ * sample two channels. Thus, the more channels
+ * are in the channel list the more time we need.
+ */
+ err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+ (125000 * interval));
+ } else {
+ /* full speed */
+ /* 1kHz scans every USB frame */
+ err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
+ 1000000);
}
err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
@@ -552,21 +539,8 @@
/* Step 4: fix up any arguments */
- if (high_speed) {
- /*
- * every 2 channels get a time window of 125us. Thus, if we
- * sample all 16 channels we need 1ms. If we sample only one
- * channel we need only 125us
- */
- devpriv->ai_interval = interval;
- devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
- } else {
- /* interval always 1ms */
- devpriv->ai_interval = 1;
- devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
- }
- if (devpriv->ai_timer < 1)
- err |= -EINVAL;
+ tmp = rounddown(cmd->scan_begin_arg, high_speed ? 125000 : 1000000);
+ err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
if (err)
return 4;
@@ -668,19 +642,36 @@
down(&devpriv->sem);
+ if (devpriv->high_speed) {
+ /*
+ * every 2 channels get a time window of 125us. Thus, if we
+ * sample all 16 channels we need 1ms. If we sample only one
+ * channel we need only 125us
+ */
+ unsigned int interval = usbduxsigma_chans_to_interval(len);
+
+ devpriv->ai_interval = interval;
+ devpriv->ai_timer = cmd->scan_begin_arg / (125000 * interval);
+ } else {
+ /* interval always 1ms */
+ devpriv->ai_interval = 1;
+ devpriv->ai_timer = cmd->scan_begin_arg / 1000000;
+ }
+
for (i = 0; i < len; i++) {
unsigned int chan = CR_CHAN(cmd->chanlist[i]);
create_adc_command(chan, &muxsg0, &muxsg1);
}
- devpriv->dux_commands[1] = len; /* num channels per time step */
- devpriv->dux_commands[2] = 0x12; /* CONFIG0 */
- devpriv->dux_commands[3] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
- devpriv->dux_commands[4] = 0x00; /* CONFIG3: diff. channels off */
- devpriv->dux_commands[5] = muxsg0;
- devpriv->dux_commands[6] = muxsg1;
- devpriv->dux_commands[7] = sysred;
+ devpriv->dux_commands[1] = devpriv->ai_interval;
+ devpriv->dux_commands[2] = len; /* num channels per time step */
+ devpriv->dux_commands[3] = 0x12; /* CONFIG0 */
+ devpriv->dux_commands[4] = 0x03; /* CONFIG1: 23kHz sample, delay 0us */
+ devpriv->dux_commands[5] = 0x00; /* CONFIG3: diff. channels off */
+ devpriv->dux_commands[6] = muxsg0;
+ devpriv->dux_commands[7] = muxsg1;
+ devpriv->dux_commands[8] = sysred;
ret = usbbuxsigma_send_cmd(dev, USBBUXSIGMA_AD_CMD);
if (ret < 0) {
@@ -848,29 +839,22 @@
struct comedi_cmd *cmd)
{
struct usbduxsigma_private *devpriv = dev->private;
+ unsigned int tmp;
int err = 0;
- int high_speed;
- unsigned int flags;
-
- /* high speed conversions are not used yet */
- high_speed = 0; /* (devpriv->high_speed) */
/* Step 1 : check if triggers are trivially valid */
err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
- if (high_speed) {
- /*
- * start immediately a new scan
- * the sampling rate is set by the coversion rate
- */
- flags = TRIG_FOLLOW;
- } else {
- /* start a new scan (output at once) with a timer */
- flags = TRIG_TIMER;
- }
- err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags);
-
+ /*
+ * For now, always use "scan" timing with all channels updated at once
+ * (cmd->scan_begin_src == TRIG_TIMER, cmd->convert_src == TRIG_NOW).
+ *
+ * In a future version, "convert" timing with channels updated
+ * indivually may be supported in high speed mode
+ * (cmd->scan_begin_src == TRIG_FOLLOW, cmd->convert_src == TRIG_TIMER).
+ */
+ err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
@@ -894,17 +878,7 @@
err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
- if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
- err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
-
- if (cmd->scan_begin_src == TRIG_TIMER) {
- err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
- 1000000);
- }
-
- /* not used now, is for later use */
- if (cmd->convert_src == TRIG_TIMER)
- err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 125000);
+ err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, 1000000);
err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
cmd->chanlist_len);
@@ -919,19 +893,8 @@
/* Step 4: fix up any arguments */
- /* we count in timer steps */
- if (high_speed) {
- /* timing of the conversion itself: every 125 us */
- devpriv->ao_timer = cmd->convert_arg / 125000;
- } else {
- /*
- * timing of the scan: every 1ms
- * we get all channels at once
- */
- devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
- }
- if (devpriv->ao_timer < 1)
- err |= -EINVAL;
+ tmp = rounddown(cmd->scan_begin_arg, 1000000);
+ err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, tmp);
if (err)
return 4;
@@ -948,6 +911,14 @@
down(&devpriv->sem);
+ /*
+ * For now, only "scan" timing is supported. A future version may
+ * support "convert" timing in high speed mode.
+ *
+ * Timing of the scan: every 1ms all channels updated at once.
+ */
+ devpriv->ao_timer = cmd->scan_begin_arg / 1000000;
+
devpriv->ao_counter = devpriv->ao_timer;
if (cmd->start_src == TRIG_NOW) {
@@ -1427,10 +1398,7 @@
urb->transfer_buffer_length = SIZEOUTBUF;
urb->iso_frame_desc[0].offset = 0;
urb->iso_frame_desc[0].length = SIZEOUTBUF;
- if (devpriv->high_speed)
- urb->interval = 8; /* uframes */
- else
- urb->interval = 1; /* frames */
+ urb->interval = 1; /* (u)frames */
}
if (devpriv->pwm_buf_sz) {
@@ -1653,7 +1621,7 @@
};
module_comedi_usb_driver(usbduxsigma_driver, usbduxsigma_usb_driver);
-MODULE_AUTHOR("Bernd Porr, BerndPorr@f2s.com");
-MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com");
+MODULE_AUTHOR("Bernd Porr, mail@berndporr.me.uk");
+MODULE_DESCRIPTION("Stirling/ITL USB-DUX SIGMA -- mail@berndporr.me.uk");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(FIRMWARE);
diff --git a/drivers/staging/comedi/range.c b/drivers/staging/comedi/range.c
index 6a393b2..ce3a58a 100644
--- a/drivers/staging/comedi/range.c
+++ b/drivers/staging/comedi/range.c
@@ -102,7 +102,18 @@
* @s: comedi_subdevice struct
* @n: number of elements in the chanlist
* @chanlist: the chanlist to validate
-*/
+ *
+ * Each element consists of a channel number, a range index, an analog
+ * reference type and some flags, all packed into an unsigned int.
+ *
+ * This checks that the channel number and range index are supported by
+ * the comedi subdevice. It does not check whether the analog reference
+ * type and the flags are supported. Drivers that care should check those
+ * themselves.
+ *
+ * Return: %0 if all @chanlist elements are valid (success),
+ * %-EINVAL if one or more elements are invalid.
+ */
int comedi_check_chanlist(struct comedi_subdevice *s, int n,
unsigned int *chanlist)
{
diff --git a/drivers/staging/dgap/dgap.c b/drivers/staging/dgap/dgap.c
index 26b0446..9112dd2 100644
--- a/drivers/staging/dgap/dgap.c
+++ b/drivers/staging/dgap/dgap.c
@@ -4953,9 +4953,8 @@
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
spin_unlock_irqrestore(&bd->bd_lock, lock_flags);
- rc = put_user(C_CLOCAL(tty) ? 1 : 0,
+ return put_user(C_CLOCAL(tty) ? 1 : 0,
(unsigned long __user *) arg);
- return rc;
case TIOCSSOFTCAR:
spin_unlock_irqrestore(&ch->ch_lock, lock_flags2);
@@ -7004,25 +7003,29 @@
kfree(brd);
}
-static void dgap_remove_one(struct pci_dev *dev)
+static void dgap_stop(bool removesys, struct pci_driver *drv)
{
- unsigned int i;
- ulong lock_flags;
- struct pci_driver *drv = to_pci_driver(dev->dev.driver);
+ unsigned long lock_flags;
spin_lock_irqsave(&dgap_poll_lock, lock_flags);
dgap_poll_stop = 1;
spin_unlock_irqrestore(&dgap_poll_lock, lock_flags);
- /* Turn off poller right away. */
del_timer_sync(&dgap_poll_timer);
-
- dgap_remove_driver_sysfiles(drv);
+ 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]);
@@ -7096,21 +7099,6 @@
return rc;
}
-static void dgap_stop(void)
-{
- 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);
-
- device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
- class_destroy(dgap_class);
- unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
-}
-
/************************************************************************
*
* Driver load/unload functions
@@ -7133,8 +7121,10 @@
return rc;
rc = pci_register_driver(&dgap_driver);
- if (rc)
- goto err_stop;
+ if (rc) {
+ dgap_stop(false, NULL);
+ return rc;
+ }
rc = dgap_create_driver_sysfiles(&dgap_driver);
if (rc)
@@ -7146,9 +7136,6 @@
err_unregister:
pci_unregister_driver(&dgap_driver);
-err_stop:
- dgap_stop();
-
return rc;
}
diff --git a/drivers/staging/dgnc/dgnc_driver.h b/drivers/staging/dgnc/dgnc_driver.h
index d04671f..06ece51 100644
--- a/drivers/staging/dgnc/dgnc_driver.h
+++ b/drivers/staging/dgnc/dgnc_driver.h
@@ -21,9 +21,9 @@
#ifndef __DGNC_DRIVER_H
#define __DGNC_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 */
+#include <linux/types.h>
+#include <linux/tty.h>
+#include <linux/interrupt.h>
#include "digi.h" /* Digi specific ioctl header */
#include "dgnc_sysfs.h" /* Support for SYSFS */
diff --git a/drivers/staging/dgnc/dgnc_sysfs.h b/drivers/staging/dgnc/dgnc_sysfs.h
index be0f90a..7be7d55 100644
--- a/drivers/staging/dgnc/dgnc_sysfs.h
+++ b/drivers/staging/dgnc/dgnc_sysfs.h
@@ -25,16 +25,16 @@
struct pci_driver;
struct class_device;
-extern void dgnc_create_ports_sysfiles(struct dgnc_board *bd);
-extern void dgnc_remove_ports_sysfiles(struct dgnc_board *bd);
+void dgnc_create_ports_sysfiles(struct dgnc_board *bd);
+void dgnc_remove_ports_sysfiles(struct dgnc_board *bd);
-extern void dgnc_create_driver_sysfiles(struct pci_driver *);
-extern void dgnc_remove_driver_sysfiles(struct pci_driver *);
+void dgnc_create_driver_sysfiles(struct pci_driver *);
+void dgnc_remove_driver_sysfiles(struct pci_driver *);
-extern int dgnc_tty_class_init(void);
-extern int dgnc_tty_class_destroy(void);
+int dgnc_tty_class_init(void);
+int dgnc_tty_class_destroy(void);
-extern void dgnc_create_tty_sysfs(struct un_t *un, struct device *c);
-extern void dgnc_remove_tty_sysfs(struct device *c);
+void dgnc_create_tty_sysfs(struct un_t *un, struct device *c);
+void dgnc_remove_tty_sysfs(struct device *c);
#endif
diff --git a/drivers/staging/emxx_udc/emxx_udc.c b/drivers/staging/emxx_udc/emxx_udc.c
index 4178d96..b6b76ff 100644
--- a/drivers/staging/emxx_udc/emxx_udc.c
+++ b/drivers/staging/emxx_udc/emxx_udc.c
@@ -3153,36 +3153,46 @@
.ioctl = nbu2ss_gad_ioctl,
};
-static const char g_ep0_name[] = "ep0";
-static const char g_ep1_name[] = "ep1-bulk";
-static const char g_ep2_name[] = "ep2-bulk";
-static const char g_ep3_name[] = "ep3in-int";
-static const char g_ep4_name[] = "ep4-iso";
-static const char g_ep5_name[] = "ep5-iso";
-static const char g_ep6_name[] = "ep6-bulk";
-static const char g_ep7_name[] = "ep7-bulk";
-static const char g_ep8_name[] = "ep8in-int";
-static const char g_ep9_name[] = "ep9-iso";
-static const char g_epa_name[] = "epa-iso";
-static const char g_epb_name[] = "epb-bulk";
-static const char g_epc_name[] = "epc-nulk";
-static const char g_epd_name[] = "epdin-int";
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[NUM_ENDPOINTS] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
-static const char *gp_ep_name[NUM_ENDPOINTS] = {
- g_ep0_name,
- g_ep1_name,
- g_ep2_name,
- g_ep3_name,
- g_ep4_name,
- g_ep5_name,
- g_ep6_name,
- g_ep7_name,
- g_ep8_name,
- g_ep9_name,
- g_epa_name,
- g_epb_name,
- g_epc_name,
- g_epd_name,
+ EP_INFO("ep0",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep2-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep3in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep5-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep6-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep7-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep8in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep9-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("epa-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("epb-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("epc-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("epdin-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+
+#undef EP_INFO
};
/*-------------------------------------------------------------------------*/
@@ -3200,10 +3210,12 @@
ep->desc = NULL;
ep->ep.driver_data = NULL;
- ep->ep.name = gp_ep_name[i];
+ ep->ep.name = ep_info[i].name;
+ ep->ep.caps = ep_info[i].caps;
ep->ep.ops = &nbu2ss_ep_ops;
- ep->ep.maxpacket = (i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE);
+ usb_ep_set_maxpacket_limit(&ep->ep,
+ i == 0 ? EP0_PACKETSIZE : EP_PACKETSIZE);
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
INIT_LIST_HEAD(&ep->queue);
diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig
index d401878..d473010 100644
--- a/drivers/staging/fbtft/Kconfig
+++ b/drivers/staging/fbtft/Kconfig
@@ -1,6 +1,7 @@
menuconfig FB_TFT
tristate "Support for small TFT LCD display modules"
- depends on FB && SPI && GPIOLIB
+ depends on FB && SPI
+ depends on GPIOLIB || COMPILE_TEST
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
@@ -152,6 +153,12 @@
help
Generic Framebuffer support for TLS8204
+config FB_TFT_UC1611
+ tristate "FB driver for the UC1611 LCD controller"
+ depends on FB_TFT
+ help
+ Generic Framebuffer support for UC1611
+
config FB_TFT_UC1701
tristate "FB driver for the UC1701 LCD Controller"
depends on FB_TFT
diff --git a/drivers/staging/fbtft/Makefile b/drivers/staging/fbtft/Makefile
index 554b526..b26efdc 100644
--- a/drivers/staging/fbtft/Makefile
+++ b/drivers/staging/fbtft/Makefile
@@ -27,6 +27,7 @@
obj-$(CONFIG_FB_TFT_ST7735R) += fb_st7735r.o
obj-$(CONFIG_FB_TFT_TINYLCD) += fb_tinylcd.o
obj-$(CONFIG_FB_TFT_TLS8204) += fb_tls8204.o
+obj-$(CONFIG_FB_TFT_UC1611) += fb_uc1611.o
obj-$(CONFIG_FB_TFT_UC1701) += fb_uc1701.o
obj-$(CONFIG_FB_TFT_UPD161704) += fb_upd161704.o
obj-$(CONFIG_FB_TFT_WATTEROTT) += fb_watterott.o
diff --git a/drivers/staging/fbtft/fb_uc1611.c b/drivers/staging/fbtft/fb_uc1611.c
new file mode 100644
index 0000000..32f3a9d
--- /dev/null
+++ b/drivers/staging/fbtft/fb_uc1611.c
@@ -0,0 +1,350 @@
+/*
+ * FB driver for the UltraChip UC1611 LCD controller
+ *
+ * The display is 4-bit grayscale (16 shades) 240x160.
+ *
+ * Copyright (C) 2015 Henri Chain
+ *
+ * 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/spi/spi.h>
+#include <linux/delay.h>
+
+#include "fbtft.h"
+
+#define DRVNAME "fb_uc1611"
+#define WIDTH 240
+#define HEIGHT 160
+#define BPP 8
+#define FPS 40
+
+/*
+ * LCD voltage is a combination of ratio, gain, pot and temp
+ *
+ * V_LCD = V_BIAS * ratio
+ * V_LCD = (C_V0 + C_PM × pot) * (1 + (T - 25) * temp)
+ * C_V0 and C_PM depend on ratio and gain
+ * T is ambient temperature
+ */
+
+/* BR -> actual ratio: 0-3 -> 5, 10, 11, 13 */
+static unsigned ratio = 2;
+module_param(ratio, uint, 0);
+MODULE_PARM_DESC(ratio, "BR[1:0] Bias voltage ratio: 0-3 (default: 2)");
+
+static unsigned gain = 3;
+module_param(gain, uint, 0);
+MODULE_PARM_DESC(gain, "GN[1:0] Bias voltage gain: 0-3 (default: 3)");
+
+static unsigned pot = 16;
+module_param(pot, uint, 0);
+MODULE_PARM_DESC(pot, "PM[6:0] Bias voltage pot.: 0-63 (default: 16)");
+
+/* TC -> % compensation per deg C: 0-3 -> -.05, -.10, -.015, -.20 */
+static unsigned temp;
+module_param(temp, uint, 0);
+MODULE_PARM_DESC(temp, "TC[1:0] Temperature compensation: 0-3 (default: 0)");
+
+/* PC[1:0] -> LCD capacitance: 0-3 -> <20nF, 20-28 nF, 29-40 nF, 40-56 nF */
+static unsigned load = 1;
+module_param(load, uint, 0);
+MODULE_PARM_DESC(load, "PC[1:0] Panel Loading: 0-3 (default: 1)");
+
+/* PC[3:2] -> V_LCD: 0, 1, 3 -> ext., int. with ratio = 5, int. standard */
+static unsigned pump = 3;
+module_param(pump, uint, 0);
+MODULE_PARM_DESC(pump, "PC[3:2] Pump control: 0,1,3 (default: 3)");
+
+static int init_display(struct fbtft_par *par)
+{
+ int ret;
+
+ fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
+
+ /* Set CS active high */
+ par->spi->mode |= SPI_CS_HIGH;
+ ret = par->spi->master->setup(par->spi);
+ if (ret) {
+ dev_err(par->info->device, "Could not set SPI_CS_HIGH\n");
+ return ret;
+ }
+
+ /* Reset controller */
+ write_reg(par, 0xE2);
+
+ /* Set bias ratio */
+ write_reg(par, 0xE8 | (ratio & 0x03));
+
+ /* Set bias gain and potentiometer */
+ write_reg(par, 0x81);
+ write_reg(par, (gain & 0x03) << 6 | (pot & 0x3F));
+
+ /* Set temperature compensation */
+ write_reg(par, 0x24 | (temp & 0x03));
+
+ /* Set panel loading */
+ write_reg(par, 0x28 | (load & 0x03));
+
+ /* Set pump control */
+ write_reg(par, 0x2C | (pump & 0x03));
+
+ /* Set inverse display */
+ write_reg(par, 0xA6 | (0x01 & 0x01));
+
+ /* Set 4-bit grayscale mode */
+ write_reg(par, 0xD0 | (0x02 & 0x03));
+
+ /* Set Display enable */
+ write_reg(par, 0xA8 | 0x07);
+
+ return 0;
+}
+
+static void set_addr_win(struct fbtft_par *par, int xs, int ys, int xe, int ye)
+{
+ fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par,
+ "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n",
+ __func__, xs, ys, xe, ye);
+
+ switch (par->info->var.rotate) {
+ case 90:
+ case 270:
+ /* Set column address */
+ write_reg(par, ys & 0x0F);
+ write_reg(par, 0x10 | (ys >> 4));
+
+ /* Set page address (divide xs by 2) (not used by driver) */
+ write_reg(par, 0x60 | ((xs >> 1) & 0x0F));
+ write_reg(par, 0x70 | (xs >> 5));
+ break;
+ default:
+ /* Set column address (not used by driver) */
+ write_reg(par, xs & 0x0F);
+ write_reg(par, 0x10 | (xs >> 4));
+
+ /* Set page address (divide ys by 2) */
+ write_reg(par, 0x60 | ((ys >> 1) & 0x0F));
+ write_reg(par, 0x70 | (ys >> 5));
+ break;
+ }
+}
+
+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, 0xA8 | 0x00);
+ else
+ write_reg(par, 0xA8 | 0x07);
+ return 0;
+}
+
+static int set_var(struct fbtft_par *par)
+{
+ fbtft_par_dbg(DEBUG_INIT_DISPLAY, par, "%s()\n", __func__);
+
+ /* par->info->fix.visual = FB_VISUAL_PSEUDOCOLOR; */
+ par->info->var.grayscale = 1;
+ par->info->var.red.offset = 0;
+ par->info->var.red.length = 8;
+ par->info->var.green.offset = 0;
+ par->info->var.green.length = 8;
+ par->info->var.blue.offset = 0;
+ par->info->var.blue.length = 8;
+ par->info->var.transp.offset = 0;
+ par->info->var.transp.length = 0;
+
+ switch (par->info->var.rotate) {
+ case 90:
+ /* Set RAM address control */
+ write_reg(par, 0x88
+ | (0x0 & 0x1) << 2 /* Increment positively */
+ | (0x1 & 0x1) << 1 /* Increment page first */
+ | (0x1 & 0x1)); /* Wrap around (default) */
+
+ /* Set LCD mapping */
+ write_reg(par, 0xC0
+ | (0x0 & 0x1) << 2 /* Mirror Y OFF */
+ | (0x0 & 0x1) << 1 /* Mirror X OFF */
+ | (0x0 & 0x1)); /* MS nibble last (default) */
+ break;
+ case 180:
+ /* Set RAM address control */
+ write_reg(par, 0x88
+ | (0x0 & 0x1) << 2 /* Increment positively */
+ | (0x0 & 0x1) << 1 /* Increment column first */
+ | (0x1 & 0x1)); /* Wrap around (default) */
+
+ /* Set LCD mapping */
+ write_reg(par, 0xC0
+ | (0x1 & 0x1) << 2 /* Mirror Y ON */
+ | (0x0 & 0x1) << 1 /* Mirror X OFF */
+ | (0x0 & 0x1)); /* MS nibble last (default) */
+ break;
+ case 270:
+ /* Set RAM address control */
+ write_reg(par, 0x88
+ | (0x0 & 0x1) << 2 /* Increment positively */
+ | (0x1 & 0x1) << 1 /* Increment page first */
+ | (0x1 & 0x1)); /* Wrap around (default) */
+
+ /* Set LCD mapping */
+ write_reg(par, 0xC0
+ | (0x1 & 0x1) << 2 /* Mirror Y ON */
+ | (0x1 & 0x1) << 1 /* Mirror X ON */
+ | (0x0 & 0x1)); /* MS nibble last (default) */
+ break;
+ default:
+ /* Set RAM address control */
+ write_reg(par, 0x88
+ | (0x0 & 0x1) << 2 /* Increment positively */
+ | (0x0 & 0x1) << 1 /* Increment column first */
+ | (0x1 & 0x1)); /* Wrap around (default) */
+
+ /* Set LCD mapping */
+ write_reg(par, 0xC0
+ | (0x0 & 0x1) << 2 /* Mirror Y OFF */
+ | (0x1 & 0x1) << 1 /* Mirror X ON */
+ | (0x0 & 0x1)); /* MS nibble last (default) */
+ break;
+ }
+
+ return 0;
+}
+
+static int write_vmem(struct fbtft_par *par, size_t offset, size_t len)
+{
+ u8 *vmem8 = (u8 *)(par->info->screen_base);
+ u8 *buf8 = (u8 *)(par->txbuf.buf);
+ u16 *buf16 = (u16 *)(par->txbuf.buf);
+ int line_length = par->info->fix.line_length;
+ int y_start = (offset / line_length);
+ int y_end = (offset + len - 1) / line_length;
+ int x, y, i;
+ int ret = 0;
+
+ fbtft_par_dbg(DEBUG_WRITE_VMEM, par, "%s()\n", __func__);
+
+ switch (par->pdata->display.buswidth) {
+ case 8:
+ switch (par->info->var.rotate) {
+ case 90:
+ case 270:
+ i = y_start * line_length;
+ for (y = y_start; y <= y_end; y++) {
+ for (x = 0; x < line_length; x += 2) {
+ *buf8 = vmem8[i] >> 4;
+ *buf8 |= vmem8[i + 1] & 0xF0;
+ buf8++;
+ i += 2;
+ }
+ }
+ break;
+ default:
+ /* Must be even because pages are two lines */
+ y_start &= 0xFE;
+ i = y_start * line_length;
+ for (y = y_start; y <= y_end; y += 2) {
+ for (x = 0; x < line_length; x++) {
+ *buf8 = vmem8[i] >> 4;
+ *buf8 |= vmem8[i + line_length] & 0xF0;
+ buf8++;
+ i++;
+ }
+ i += line_length;
+ }
+ break;
+ }
+ gpio_set_value(par->gpio.dc, 1);
+
+ /* Write data */
+ ret = par->fbtftops.write(par, par->txbuf.buf, len / 2);
+ break;
+ case 9:
+ switch (par->info->var.rotate) {
+ case 90:
+ case 270:
+ i = y_start * line_length;
+ for (y = y_start; y <= y_end; y++) {
+ for (x = 0; x < line_length; x += 2) {
+ *buf16 = 0x100;
+ *buf16 |= vmem8[i] >> 4;
+ *buf16 |= vmem8[i + 1] & 0xF0;
+ buf16++;
+ i += 2;
+ }
+ }
+ break;
+ default:
+ /* Must be even because pages are two lines */
+ y_start &= 0xFE;
+ i = y_start * line_length;
+ for (y = y_start; y <= y_end; y += 2) {
+ for (x = 0; x < line_length; x++) {
+ *buf16 = 0x100;
+ *buf16 |= vmem8[i] >> 4;
+ *buf16 |= vmem8[i + line_length] & 0xF0;
+ buf16++;
+ i++;
+ }
+ i += line_length;
+ }
+ break;
+ }
+
+ /* Write data */
+ ret = par->fbtftops.write(par, par->txbuf.buf, len);
+ break;
+ default:
+ dev_err(par->info->device, "unsupported buswidth %d\n",
+ par->pdata->display.buswidth);
+ }
+
+ if (ret < 0)
+ dev_err(par->info->device, "write failed and returned: %d\n",
+ ret);
+
+ return ret;
+}
+
+static struct fbtft_display display = {
+ .txbuflen = -1,
+ .regwidth = 8,
+ .width = WIDTH,
+ .height = HEIGHT,
+ .bpp = BPP,
+ .fps = FPS,
+ .fbtftops = {
+ .write_vmem = write_vmem,
+ .init_display = init_display,
+ .set_addr_win = set_addr_win,
+ .set_var = set_var,
+ .blank = blank,
+ },
+};
+
+FBTFT_REGISTER_DRIVER(DRVNAME, "ultrachip,uc1611", &display);
+
+MODULE_ALIAS("spi:" DRVNAME);
+MODULE_ALIAS("platform:" DRVNAME);
+MODULE_ALIAS("spi:uc1611");
+MODULE_ALIAS("platform:uc1611");
+
+MODULE_DESCRIPTION("FB driver for the UC1611 LCD controller");
+MODULE_AUTHOR("Henri Chain");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c
index 9cc8141..23392eb 100644
--- a/drivers/staging/fbtft/fbtft-core.c
+++ b/drivers/staging/fbtft/fbtft-core.c
@@ -677,13 +677,13 @@
*
*/
struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
- struct device *dev)
+ struct device *dev,
+ struct fbtft_platform_data *pdata)
{
struct fb_info *info;
struct fbtft_par *par;
struct fb_ops *fbops = NULL;
struct fb_deferred_io *fbdefio = NULL;
- struct fbtft_platform_data *pdata = dev->platform_data;
u8 *vmem = NULL;
void *txbuf = NULL;
void *buf = NULL;
@@ -828,7 +828,7 @@
par = info->par;
par->info = info;
- par->pdata = dev->platform_data;
+ par->pdata = pdata;
par->debug = display->debug;
par->buf = buf;
spin_lock_init(&par->dirty_lock);
@@ -1076,6 +1076,11 @@
p = of_prop_next_u32(prop, NULL, &val);
if (!p)
return -EINVAL;
+
+ par->fbtftops.reset(par);
+ if (par->gpio.cs != -1)
+ gpio_set_value(par->gpio.cs, 0); /* Activate chip */
+
while (p) {
if (val & FBTFT_OF_INIT_CMD) {
val &= 0xFFFF;
@@ -1260,12 +1265,11 @@
*/
static int fbtft_verify_gpios(struct fbtft_par *par)
{
- struct fbtft_platform_data *pdata;
+ struct fbtft_platform_data *pdata = par->pdata;
int i;
fbtft_par_dbg(DEBUG_VERIFY_GPIOS, par, "%s()\n", __func__);
- pdata = par->info->device->platform_data;
if (pdata->display.buswidth != 9 && par->startbyte == 0 &&
par->gpio.dc < 0) {
dev_err(par->info->device,
@@ -1383,10 +1387,9 @@
pdata = fbtft_probe_dt(dev);
if (IS_ERR(pdata))
return PTR_ERR(pdata);
- dev->platform_data = pdata;
}
- info = fbtft_framebuffer_alloc(display, dev);
+ info = fbtft_framebuffer_alloc(display, dev, pdata);
if (!info)
return -ENOMEM;
diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h
index 7d817eb..7e9a506 100644
--- a/drivers/staging/fbtft/fbtft.h
+++ b/drivers/staging/fbtft/fbtft.h
@@ -262,39 +262,38 @@
par->fbtftops.write_register(par, NUMARGS(__VA_ARGS__), __VA_ARGS__)
/* fbtft-core.c */
-extern void fbtft_dbg_hex(const struct device *dev,
- int groupsize, void *buf, size_t len, const char *fmt, ...);
-extern struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
- struct device *dev);
-extern void fbtft_framebuffer_release(struct fb_info *info);
-extern int fbtft_register_framebuffer(struct fb_info *fb_info);
-extern int fbtft_unregister_framebuffer(struct fb_info *fb_info);
-extern void fbtft_register_backlight(struct fbtft_par *par);
-extern void fbtft_unregister_backlight(struct fbtft_par *par);
-extern int fbtft_init_display(struct fbtft_par *par);
-extern int fbtft_probe_common(struct fbtft_display *display,
- struct spi_device *sdev, struct platform_device *pdev);
-extern int fbtft_remove_common(struct device *dev, struct fb_info *info);
+void fbtft_dbg_hex(const struct device *dev, int groupsize,
+ void *buf, size_t len, const char *fmt, ...);
+struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
+ struct device *dev,
+ struct fbtft_platform_data *pdata);
+void fbtft_framebuffer_release(struct fb_info *info);
+int fbtft_register_framebuffer(struct fb_info *fb_info);
+int fbtft_unregister_framebuffer(struct fb_info *fb_info);
+void fbtft_register_backlight(struct fbtft_par *par);
+void fbtft_unregister_backlight(struct fbtft_par *par);
+int fbtft_init_display(struct fbtft_par *par);
+int fbtft_probe_common(struct fbtft_display *display, struct spi_device *sdev,
+ struct platform_device *pdev);
+int fbtft_remove_common(struct device *dev, struct fb_info *info);
/* fbtft-io.c */
-extern int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len);
-extern int fbtft_write_spi_emulate_9(struct fbtft_par *par,
- void *buf, size_t len);
-extern int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len);
-extern int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len);
-extern int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len);
-extern int fbtft_write_gpio16_wr_latched(struct fbtft_par *par,
- void *buf, size_t len);
+int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_write_spi_emulate_9(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_read_spi(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len);
+int fbtft_write_gpio16_wr_latched(struct fbtft_par *par, void *buf, size_t len);
/* fbtft-bus.c */
-extern int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len);
-extern int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len);
-extern int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len);
-extern int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len);
-extern void fbtft_write_reg8_bus8(struct fbtft_par *par, int len, ...);
-extern void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...);
-extern void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...);
-extern void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...);
+int fbtft_write_vmem8_bus8(struct fbtft_par *par, size_t offset, size_t len);
+int fbtft_write_vmem16_bus16(struct fbtft_par *par, size_t offset, size_t len);
+int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len);
+int fbtft_write_vmem16_bus9(struct fbtft_par *par, size_t offset, size_t len);
+void fbtft_write_reg8_bus8(struct fbtft_par *par, int len, ...);
+void fbtft_write_reg8_bus9(struct fbtft_par *par, int len, ...);
+void fbtft_write_reg16_bus8(struct fbtft_par *par, int len, ...);
+void fbtft_write_reg16_bus16(struct fbtft_par *par, int len, ...);
#define FBTFT_REGISTER_DRIVER(_name, _compatible, _display) \
diff --git a/drivers/staging/fbtft/fbtft_device.c b/drivers/staging/fbtft/fbtft_device.c
index 211d504..fa916e8 100644
--- a/drivers/staging/fbtft/fbtft_device.c
+++ b/drivers/staging/fbtft/fbtft_device.c
@@ -397,6 +397,37 @@
}
}
}, {
+ .name = "ew24ha0",
+ .spi = &(struct spi_board_info) {
+ .modalias = "fb_uc1611",
+ .max_speed_hz = 32000000,
+ .mode = SPI_MODE_3,
+ .platform_data = &(struct fbtft_platform_data) {
+ .display = {
+ .buswidth = 8,
+ },
+ .gpios = (const struct fbtft_gpio []) {
+ { "dc", 24 },
+ {},
+ },
+ }
+ }
+ }, {
+ .name = "ew24ha0_9bit",
+ .spi = &(struct spi_board_info) {
+ .modalias = "fb_uc1611",
+ .max_speed_hz = 32000000,
+ .mode = SPI_MODE_3,
+ .platform_data = &(struct fbtft_platform_data) {
+ .display = {
+ .buswidth = 9,
+ },
+ .gpios = (const struct fbtft_gpio []) {
+ {},
+ },
+ }
+ }
+ }, {
.name = "flexfb",
.spi = &(struct spi_board_info) {
.modalias = "flexfb",
diff --git a/drivers/staging/fbtft/flexfb.c b/drivers/staging/fbtft/flexfb.c
index 2c4ce07..c763efc 100644
--- a/drivers/staging/fbtft/flexfb.c
+++ b/drivers/staging/fbtft/flexfb.c
@@ -12,10 +12,6 @@
* 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/module.h>
@@ -30,7 +26,6 @@
#define DRVNAME "flexfb"
-
static char *chip;
module_param(chip, charp, 0);
MODULE_PARM_DESC(chip, "LCD controller");
@@ -68,7 +63,6 @@
module_param(latched, bool, 0);
MODULE_PARM_DESC(latched, "Use with latched 16-bit databus");
-
static int *initp;
static int initp_num;
@@ -132,14 +126,115 @@
-1, 0xab, 0x01, -1, 0xb1, 0x32, -1, 0xb4, 0xa0, 0xb5, 0x55, -1, 0xbb, 0x17, -1, 0xbe, 0x05,
-1, 0xc1, 0xc8, 0x80, 0xc8, -1, 0xc7, 0x0f, -1, 0xb6, 0x01, -1, 0xa6, -1, 0xaf, -3 };
+/**
+ * struct flexfb_lcd_controller - Describes the LCD controller properties
+ * @name: Model name of the chip
+ * @width: Width of display in pixels
+ * @height: Height of display in pixels
+ * @setaddrwin: Which set_addr_win() implementation to use
+ * @regwidth: LCD Controller Register width in bits
+ * @init_seq: LCD initialization sequence
+ * @init_seq_sz: Size of LCD initialization sequence
+ */
+struct flexfb_lcd_controller {
+ const char *name;
+ unsigned int width;
+ unsigned int height;
+ unsigned int setaddrwin;
+ unsigned int regwidth;
+ int *init_seq;
+ int init_seq_sz;
+};
+
+static const struct flexfb_lcd_controller flexfb_chip_table[] = {
+ {
+ .name = "st7735r",
+ .width = 120,
+ .height = 160,
+ .init_seq = st7735r_init,
+ .init_seq_sz = ARRAY_SIZE(st7735r_init),
+ },
+ {
+ .name = "hx8340bn",
+ .width = 176,
+ .height = 220,
+ .init_seq = hx8340bn_init,
+ .init_seq_sz = ARRAY_SIZE(hx8340bn_init),
+ },
+ {
+ .name = "ili9225",
+ .width = 176,
+ .height = 220,
+ .regwidth = 16,
+ .init_seq = ili9225_init,
+ .init_seq_sz = ARRAY_SIZE(ili9225_init),
+ },
+ {
+ .name = "ili9225",
+ .width = 176,
+ .height = 220,
+ .regwidth = 16,
+ .init_seq = ili9225_init,
+ .init_seq_sz = ARRAY_SIZE(ili9225_init),
+ },
+ {
+ .name = "ili9225",
+ .width = 176,
+ .height = 220,
+ .regwidth = 16,
+ .init_seq = ili9225_init,
+ .init_seq_sz = ARRAY_SIZE(ili9225_init),
+ },
+ {
+ .name = "ili9320",
+ .width = 240,
+ .height = 320,
+ .setaddrwin = 1,
+ .regwidth = 16,
+ .init_seq = ili9320_init,
+ .init_seq_sz = ARRAY_SIZE(ili9320_init),
+ },
+ {
+ .name = "ili9325",
+ .width = 240,
+ .height = 320,
+ .setaddrwin = 1,
+ .regwidth = 16,
+ .init_seq = ili9325_init,
+ .init_seq_sz = ARRAY_SIZE(ili9325_init),
+ },
+ {
+ .name = "ili9341",
+ .width = 240,
+ .height = 320,
+ .init_seq = ili9341_init,
+ .init_seq_sz = ARRAY_SIZE(ili9341_init),
+ },
+ {
+ .name = "ssd1289",
+ .width = 240,
+ .height = 320,
+ .setaddrwin = 2,
+ .regwidth = 16,
+ .init_seq = ssd1289_init,
+ .init_seq_sz = ARRAY_SIZE(ssd1289_init),
+ },
+ {
+ .name = "ssd1351",
+ .width = 128,
+ .height = 128,
+ .setaddrwin = 3,
+ .init_seq = ssd1351_init,
+ .init_seq_sz = ARRAY_SIZE(ssd1351_init),
+ },
+};
/* ili9320, ili9325 */
static void flexfb_set_addr_win_1(struct fbtft_par *par,
int xs, int ys, int xe, int ye)
{
- fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par,
- "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n",
- __func__, xs, ys, xe, ye);
+ fbtft_par_dbg(DEBUG_SET_ADDR_WIN, par, "%s(xs=%d, ys=%d, xe=%d, ye=%d)\n",
+ __func__, xs, ys, xe, ye);
switch (par->info->var.rotate) {
/* R20h = Horizontal GRAM Start Address */
/* R21h = Vertical GRAM Start Address */
@@ -242,7 +337,7 @@
return -EINVAL;
}
if (latched)
- num_db = buswidth/2;
+ num_db = buswidth / 2;
for (i = 0; i < num_db; i++) {
if (par->gpio.db[i] < 0) {
dev_err(par->info->device,
@@ -255,8 +350,38 @@
return 0;
}
+static void flexfb_chip_load_param(const struct flexfb_lcd_controller *chip)
+{
+ if (!width)
+ width = chip->width;
+ if (!height)
+ height = chip->height;
+ setaddrwin = chip->setaddrwin;
+ if (chip->regwidth)
+ regwidth = chip->regwidth;
+ if (!init_num) {
+ initp = chip->init_seq;
+ initp_num = chip->init_seq_sz;
+ }
+}
+
static struct fbtft_display flex_display = { };
+static int flexfb_chip_init(const struct device *dev)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(flexfb_chip_table); i++)
+ if (!strcmp(chip, flexfb_chip_table[i].name)) {
+ flexfb_chip_load_param(&flexfb_chip_table[i]);
+ return 0;
+ }
+
+ dev_err(dev, "chip=%s is not supported\n", chip);
+
+ return -EINVAL;
+}
+
static int flexfb_probe_common(struct spi_device *sdev,
struct platform_device *pdev)
{
@@ -277,110 +402,9 @@
sdev ? "'SPI device'" : "'Platform device'");
if (chip) {
-
- if (!strcmp(chip, "st7735r")) {
- if (!width)
- width = 128;
- if (!height)
- height = 160;
- if (init_num == 0) {
- initp = st7735r_init;
- initp_num = ARRAY_SIZE(st7735r_init);
- }
-
-
- } else if (!strcmp(chip, "hx8340bn")) {
- if (!width)
- width = 176;
- if (!height)
- height = 220;
- setaddrwin = 0;
- if (init_num == 0) {
- initp = hx8340bn_init;
- initp_num = ARRAY_SIZE(hx8340bn_init);
- }
-
-
- } else if (!strcmp(chip, "ili9225")) {
- if (!width)
- width = 176;
- if (!height)
- height = 220;
- setaddrwin = 0;
- regwidth = 16;
- if (init_num == 0) {
- initp = ili9225_init;
- initp_num = ARRAY_SIZE(ili9225_init);
- }
-
-
-
- } else if (!strcmp(chip, "ili9320")) {
- if (!width)
- width = 240;
- if (!height)
- height = 320;
- setaddrwin = 1;
- regwidth = 16;
- if (init_num == 0) {
- initp = ili9320_init;
- initp_num = ARRAY_SIZE(ili9320_init);
- }
-
-
- } else if (!strcmp(chip, "ili9325")) {
- if (!width)
- width = 240;
- if (!height)
- height = 320;
- setaddrwin = 1;
- regwidth = 16;
- if (init_num == 0) {
- initp = ili9325_init;
- initp_num = ARRAY_SIZE(ili9325_init);
- }
-
- } else if (!strcmp(chip, "ili9341")) {
- if (!width)
- width = 240;
- if (!height)
- height = 320;
- setaddrwin = 0;
- regwidth = 8;
- if (init_num == 0) {
- initp = ili9341_init;
- initp_num = ARRAY_SIZE(ili9341_init);
- }
-
-
- } else if (!strcmp(chip, "ssd1289")) {
- if (!width)
- width = 240;
- if (!height)
- height = 320;
- setaddrwin = 2;
- regwidth = 16;
- if (init_num == 0) {
- initp = ssd1289_init;
- initp_num = ARRAY_SIZE(ssd1289_init);
- }
-
-
-
- } else if (!strcmp(chip, "ssd1351")) {
- if (!width)
- width = 128;
- if (!height)
- height = 128;
- setaddrwin = 3;
- if (init_num == 0) {
- initp = ssd1351_init;
- initp_num = ARRAY_SIZE(ssd1351_init);
- }
- } else {
- dev_err(dev, "chip=%s is not supported\n", chip);
- return -EINVAL;
- }
+ ret = flexfb_chip_init(dev);
+ if (ret)
+ return ret;
}
if (width == 0 || height == 0) {
@@ -395,7 +419,7 @@
fbtft_init_dbg(dev, "regwidth = %d\n", regwidth);
fbtft_init_dbg(dev, "buswidth = %d\n", buswidth);
- info = fbtft_framebuffer_alloc(&flex_display, dev);
+ info = fbtft_framebuffer_alloc(&flex_display, dev, dev->platform_data);
if (!info)
return -ENOMEM;
@@ -527,8 +551,8 @@
return -EINVAL;
par = info->par;
if (par)
- fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par,
- "%s()\n", __func__);
+ fbtft_par_dbg(DEBUG_DRIVER_INIT_FUNCTIONS, par, "%s()\n",
+ __func__);
fbtft_unregister_framebuffer(info);
fbtft_framebuffer_release(info);
diff --git a/drivers/staging/fsl-mc/README.txt b/drivers/staging/fsl-mc/README.txt
new file mode 100644
index 0000000..8214102
--- /dev/null
+++ b/drivers/staging/fsl-mc/README.txt
@@ -0,0 +1,364 @@
+Copyright (C) 2015 Freescale Semiconductor Inc.
+
+DPAA2 (Data Path Acceleration Architecture Gen2)
+------------------------------------------------
+
+This document provides an overview of the Freescale DPAA2 architecture
+and how it is integrated into the Linux kernel.
+
+Contents summary
+ -DPAA2 overview
+ -Overview of DPAA2 objects
+ -DPAA2 Linux driver architecture overview
+ -bus driver
+ -dprc driver
+ -allocator
+ -dpio driver
+ -Ethernet
+ -mac
+
+DPAA2 Overview
+--------------
+
+DPAA2 is a hardware architecture designed for high-speeed network
+packet processing. DPAA2 consists of sophisticated mechanisms for
+processing Ethernet packets, queue management, buffer management,
+autonomous L2 switching, virtual Ethernet bridging, and accelerator
+(e.g. crypto) sharing.
+
+A DPAA2 hardware component called the Management Complex (or MC) manages the
+DPAA2 hardware resources. The MC provides an object-based abstraction for
+software drivers to use the DPAA2 hardware.
+
+The MC uses DPAA2 hardware resources such as queues, buffer pools, and
+network ports to create functional objects/devices such as network
+interfaces, an L2 switch, or accelerator instances.
+
+The MC provides memory-mapped I/O command interfaces (MC portals)
+which DPAA2 software drivers use to operate on DPAA2 objects:
+
+ +--------------------------------------+
+ | OS |
+ | DPAA2 drivers |
+ | | |
+ +-----------------------------|--------+
+ |
+ | (create,discover,connect
+ | config,use,destroy)
+ |
+ DPAA2 |
+ +------------------------| mc portal |-+
+ | | |
+ | +- - - - - - - - - - - - -V- - -+ |
+ | | | |
+ | | Management Complex (MC) | |
+ | | | |
+ | +- - - - - - - - - - - - - - - -+ |
+ | |
+ | Hardware Hardware |
+ | Resources Objects |
+ | --------- ------- |
+ | -queues -DPRC |
+ | -buffer pools -DPMCP |
+ | -Eth MACs/ports -DPIO |
+ | -network interface -DPNI |
+ | profiles -DPMAC |
+ | -queue portals -DPBP |
+ | -MC portals ... |
+ | ... |
+ | |
+ +--------------------------------------+
+
+The MC mediates operations such as create, discover,
+connect, configuration, and destroy. Fast-path operations
+on data, such as packet transmit/receive, are not mediated by
+the MC and are done directly using memory mapped regions in
+DPIO objects.
+
+Overview of DPAA2 Objects
+-------------------------
+The section provides a brief overview of some key objects
+in the DPAA2 hardware. A simple scenario is described illustrating
+the objects involved in creating a network interfaces.
+
+-DPRC (Datapath Resource Container)
+
+ A DPRC is an container object that holds all the other
+ types of DPAA2 objects. In the example diagram below there
+ are 8 objects of 5 types (DPMCP, DPIO, DPBP, DPNI, and DPMAC)
+ in the container.
+
+ +---------------------------------------------------------+
+ | DPRC |
+ | |
+ | +-------+ +-------+ +-------+ +-------+ +-------+ |
+ | | DPMCP | | DPIO | | DPBP | | DPNI | | DPMAC | |
+ | +-------+ +-------+ +-------+ +---+---+ +---+---+ |
+ | | DPMCP | | DPIO | |
+ | +-------+ +-------+ |
+ | | DPMCP | |
+ | +-------+ |
+ | |
+ +---------------------------------------------------------+
+
+ From the point of view of an OS, a DPRC is bus-like. Like
+ a plug-and-play bus, such as PCI, DPRC commands can be used to
+ enumerate the contents of the DPRC, discover the hardware
+ objects present (including mappable regions and interrupts).
+
+ dprc.1 (bus)
+ |
+ +--+--------+-------+-------+-------+
+ | | | | |
+ dpmcp.1 dpio.1 dpbp.1 dpni.1 dpmac.1
+ dpmcp.2 dpio.2
+ dpmcp.3
+
+ Hardware objects can be created and destroyed dynamically, providing
+ the ability to hot plug/unplug objects in and out of the DPRC.
+
+ A DPRC has a mappable mmio region (an MC portal) that can be used
+ to send MC commands. It has an interrupt for status events (like
+ hotplug).
+
+ All objects in a container share the same hardware "isolation context".
+ This means that with respect to an IOMMU the isolation granularity
+ is at the DPRC (container) level, not at the individual object
+ level.
+
+ DPRCs can be defined statically and populated with objects
+ via a config file passed to the MC when firmware starts
+ it. There is also a Linux user space tool called "restool"
+ that can be used to create/destroy containers and objects
+ dynamically.
+
+-DPAA2 Objects for an Ethernet Network Interface
+
+ A typical Ethernet NIC is monolithic-- the NIC device contains TX/RX
+ queuing mechanisms, configuration mechanisms, buffer management,
+ physical ports, and interrupts. DPAA2 uses a more granular approach
+ utilizing multiple hardware objects. Each object has specialized
+ functions, and are used together by software to provide Ethernet network
+ interface functionality. This approach provides efficient use of finite
+ hardware resources, flexibility, and performance advantages.
+
+ The diagram below shows the objects needed for a simple
+ network interface configuration on a system with 2 CPUs.
+
+ +---+---+ +---+---+
+ CPU0 CPU1
+ +---+---+ +---+---+
+ | |
+ +---+---+ +---+---+
+ DPIO DPIO
+ +---+---+ +---+---+
+ \ /
+ \ /
+ \ /
+ +---+---+
+ DPNI --- DPBP,DPMCP
+ +---+---+
+ |
+ |
+ +---+---+
+ DPMAC
+ +---+---+
+ |
+ port/PHY
+
+ Below the objects are described. For each object a brief description
+ is provided along with a summary of the kinds of operations the object
+ supports and a summary of key resources of the object (mmio regions
+ and irqs).
+
+ -DPMAC (Datapath Ethernet MAC): represents an Ethernet MAC, a
+ hardware device that connects to an Ethernet PHY and allows
+ physical transmission and reception of Ethernet frames.
+ -mmio regions: none
+ -irqs: dpni link change
+ -commands: set link up/down, link config, get stats,
+ irq config, enable, reset
+
+ -DPNI (Datapath Network Interface): contains TX/RX queues,
+ network interface configuration, and rx buffer pool configuration
+ mechanisms.
+ -mmio regions: none
+ -irqs: link state
+ -commands: port config, offload config, queue config,
+ parse/classify config, irq config, enable, reset
+
+ -DPIO (Datapath I/O): provides interfaces to enqueue and dequeue
+ packets and do hardware buffer pool management operations. For
+ optimum performance there is typically DPIO per CPU. This allows
+ each CPU to perform simultaneous enqueue/dequeue operations.
+ -mmio regions: queue operations, buffer mgmt
+ -irqs: data availability, congestion notification, buffer
+ pool depletion
+ -commands: irq config, enable, reset
+
+ -DPBP (Datapath Buffer Pool): represents a hardware buffer
+ pool.
+ -mmio regions: none
+ -irqs: none
+ -commands: enable, reset
+
+ -DPMCP (Datapath MC Portal): provides an MC command portal.
+ Used by drivers to send commands to the MC to manage
+ objects.
+ -mmio regions: MC command portal
+ -irqs: command completion
+ -commands: irq config, enable, reset
+
+ Object Connections
+ ------------------
+ Some objects have explicit relationships that must
+ be configured:
+
+ -DPNI <--> DPMAC
+ -DPNI <--> DPNI
+ -DPNI <--> L2-switch-port
+ A DPNI must be connected to something such as a DPMAC,
+ another DPNI, or L2 switch port. The DPNI connection
+ is made via a DPRC command.
+
+ +-------+ +-------+
+ | DPNI | | DPMAC |
+ +---+---+ +---+---+
+ | |
+ +==========+
+
+ -DPNI <--> DPBP
+ A network interface requires a 'buffer pool' (DPBP
+ object) which provides a list of pointers to memory
+ where received Ethernet data is to be copied. The
+ Ethernet driver configures the DPBPs associated with
+ the network interface.
+
+ Interrupts
+ ----------
+ All interrupts generated by DPAA2 objects are message
+ interrupts. At the hardware level message interrupts
+ generated by devices will normally have 3 components--
+ 1) a non-spoofable 'device-id' expressed on the hardware
+ bus, 2) an address, 3) a data value.
+
+ In the case of DPAA2 devices/objects, all objects in the
+ same container/DPRC share the same 'device-id'.
+ For ARM-based SoC this is the same as the stream ID.
+
+
+DPAA2 Linux Driver Overview
+---------------------------
+
+This section provides an overview of the Linux kernel drivers for
+DPAA2-- 1) the bus driver and associated "DPAA2 infrastructure"
+drivers and 2) functional object drivers (such as Ethernet).
+
+As described previously, a DPRC is a container that holds the other
+types of DPAA2 objects. It is functionally similar to a plug-and-play
+bus controller.
+
+Each object in the DPRC is a Linux "device" and is bound to a driver.
+The diagram below shows the Linux drivers involved in a networking
+scenario and the objects bound to each driver. A brief description
+of each driver follows.
+
+ +------------+
+ | OS Network |
+ | Stack |
+ +------------+ +------------+
+ | Allocator |. . . . . . . | Ethernet |
+ |(dpmcp,dpbp)| | (dpni) |
+ +-.----------+ +---+---+----+
+ . . ^ |
+ . . <data avail, | |<enqueue,
+ . . tx confirm> | | dequeue>
+ +-------------+ . | |
+ | DPRC driver | . +---+---V----+ +---------+
+ | (dprc) | . . . . . .| DPIO driver| | MAC |
+ +----------+--+ | (dpio) | | (dpmac) |
+ | +------+-----+ +-----+---+
+ |<dev add/remove> | |
+ | | |
+ +----+--------------+ | +--+---+
+ | mc-bus driver | | | PHY |
+ | | | |driver|
+ | /fsl-mc@80c000000 | | +--+---+
+ +-------------------+ | |
+ | |
+ ================================ HARDWARE =========|=================|======
+ DPIO |
+ | |
+ DPNI---DPBP |
+ | |
+ DPMAC |
+ | |
+ PHY ---------------+
+ ===================================================|========================
+
+A brief description of each driver is provided below.
+
+ mc-bus driver
+ -------------
+ The mc-bus driver is a platform driver and is probed from an
+ "/fsl-mc@xxxx" node in the device tree passed in by boot firmware.
+ It is responsible for bootstrapping the DPAA2 kernel infrastructure.
+ Key functions include:
+ -registering a new bus type named "fsl-mc" with the kernel,
+ and implementing bus call-backs (e.g. match/uevent/dev_groups)
+ -implemeting APIs for DPAA2 driver registration and for device
+ add/remove
+ -creates an MSI irq domain
+ -do a device add of the 'root' DPRC device, which is needed
+ to bootstrap things
+
+ DPRC driver
+ -----------
+ The dprc-driver is bound DPRC objects and does runtime management
+ of a bus instance. It performs the initial bus scan of the DPRC
+ and handles interrupts for container events such as hot plug.
+
+ Allocator
+ ----------
+ Certain objects such as DPMCP and DPBP are generic and fungible,
+ and are intended to be used by other drivers. For example,
+ the DPAA2 Ethernet driver needs:
+ -DPMCPs to send MC commands, to configure network interfaces
+ -DPBPs for network buffer pools
+
+ The allocator driver registers for these allocatable object types
+ and those objects are bound to the allocator when the bus is probed.
+ The allocator maintains a pool of objects that are available for
+ allocation by other DPAA2 drivers.
+
+ DPIO driver
+ -----------
+ The DPIO driver is bound to DPIO objects and provides services that allow
+ other drivers such as the Ethernet driver to receive and transmit data.
+ Key services include:
+ -data availability notifications
+ -hardware queuing operations (enqueue and dequeue of data)
+ -hardware buffer pool management
+
+ There is typically one DPIO object per physical CPU for optimum
+ performance, allowing each CPU to simultaneously enqueue
+ and dequeue data.
+
+ The DPIO driver operates on behalf of all DPAA2 drivers
+ active in the kernel-- Ethernet, crypto, compression,
+ etc.
+
+ Ethernet
+ --------
+ The Ethernet driver is bound to a DPNI and implements the kernel
+ interfaces needed to connect the DPAA2 network interface to
+ the network stack.
+
+ Each DPNI corresponds to a Linux network interface.
+
+ MAC driver
+ ----------
+ An Ethernet PHY is an off-chip, board specific component and is managed
+ by the appropriate PHY driver via an mdio bus. The MAC driver
+ plays a role of being a proxy between the PHY driver and the
+ MC. It does this proxy via the MC commands to a DPMAC object.
diff --git a/drivers/staging/fsl-mc/TODO b/drivers/staging/fsl-mc/TODO
index d78288b..3894368 100644
--- a/drivers/staging/fsl-mc/TODO
+++ b/drivers/staging/fsl-mc/TODO
@@ -1,13 +1,31 @@
-* Add README file (with ASCII art) describing relationships between
- DPAA2 objects and how combine them to make a NIC, an LS2 switch, etc.
- Also, define all acronyms used.
-
* Decide if multiple root fsl-mc buses will be supported per Linux instance,
and if so add support for this.
* Add at least one device driver for a DPAA2 object (child device of the
- fsl-mc bus).
+ fsl-mc bus). Most likely candidate for this is adding DPAA2 Ethernet
+ driver support, which depends on drivers for several objects: DPNI,
+ DPIO, DPMAC. Other pre-requisites include:
+
+ * interrupt support. for meaningful driver support we need
+ interrupts, and thus need message interrupt support by the bus
+ driver.
+ -Note: this has dependencies on generic MSI support work
+ in process upstream, see [1] and [2].
+
+ * Management Complex (MC) command serialization. locking mechanisms
+ are needed by drivers to serialize commands sent to the MC, including
+ from atomic context.
+
+ * MC firmware uprev. The MC firmware upon which the fsl-mc
+ bus driver and DPAA2 object drivers are based is continuing
+ to evolve, so minor updates are needed to keep in sync with binary
+ interface changes to the MC.
+
+* Cleanup
Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
german.rivera@freescale.com, devel@driverdev.osuosl.org,
linux-kernel@vger.kernel.org
+
+[1] https://lkml.org/lkml/2015/7/9/93
+[2] https://lkml.org/lkml/2015/7/7/712
diff --git a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
index 5992670..e1861cf 100644
--- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
+++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000.h
@@ -42,17 +42,16 @@
struct pcmcia_device;
struct net_device;
-extern struct net_device *init_ft1000_card(struct pcmcia_device *link,
- void *ft1000_reset);
-extern void stop_ft1000_card(struct net_device *dev);
-extern int card_download(struct net_device *dev, const u8 *pFileStart,
- size_t FileLength);
+struct net_device *init_ft1000_card(struct pcmcia_device *link,
+ void *ft1000_reset);
+void stop_ft1000_card(struct net_device *dev);
+int card_download(struct net_device *dev, const u8 *pFileStart,
+ size_t FileLength);
-extern u16 ft1000_read_dpram(struct net_device *dev, int offset);
-extern void card_bootload(struct net_device *dev);
-extern u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset,
- int Index);
-extern u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset);
+u16 ft1000_read_dpram(struct net_device *dev, int offset);
+void card_bootload(struct net_device *dev);
+u16 ft1000_read_dpram_mag_16(struct net_device *dev, int offset, int Index);
+u32 ft1000_read_dpram_mag_32(struct net_device *dev, int offset);
void ft1000_write_dpram_mag_32(struct net_device *dev, int offset, u32 value);
/* Read the value of a given ASIC register. */
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
index 409266b..f241a3a 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_debug.c
@@ -260,7 +260,8 @@
/* Make sure we free any memory reserve for slow Queue */
for (i = 0; i < MAX_NUM_APP; i++) {
while (list_empty(&dev->app_info[i].app_sqlist) == 0) {
- pdpram_blk = list_entry(dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
+ pdpram_blk = list_entry(dev->app_info[i].app_sqlist.next,
+ struct dpram_blk, list);
list_del(&pdpram_blk->list);
ft1000_free_buffer(pdpram_blk, &freercvpool);
@@ -415,12 +416,19 @@
struct timeval tv;
struct IOCTL_GET_VER get_ver_data;
struct IOCTL_GET_DSP_STAT get_stat_data;
- u8 ConnectionMsg[] = {0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
- 0x00, 0x01, 0x00, 0x00};
+ u8 ConnectionMsg[] = {
+ 0x00, 0x44, 0x10, 0x20, 0x80, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x93, 0x64,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x0a,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x37, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f, 0x00,
+ 0x00, 0x01, 0x00, 0x00
+ };
unsigned short ledStat = 0;
unsigned short conStat = 0;
@@ -495,10 +503,12 @@
memcpy(get_stat_data.eui64, info->eui64, EUISZ);
if (info->ProgConStat != 0xFF) {
- ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED, (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
+ ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_LED,
+ (u8 *)&ledStat, FT1000_MAG_DSP_LED_INDX);
get_stat_data.LedStat = ntohs(ledStat);
pr_debug("LedStat = 0x%x\n", get_stat_data.LedStat);
- ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE, (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
+ ft1000_read_dpram16(ft1000dev, FT1000_MAG_DSP_CON_STATE,
+ (u8 *)&conStat, FT1000_MAG_DSP_CON_STATE_INDX);
get_stat_data.ConStat = ntohs(conStat);
pr_debug("ConStat = 0x%x\n", get_stat_data.ConStat);
} else {
@@ -689,7 +699,8 @@
if (list_empty(&ft1000dev->app_info[i].app_sqlist) == 0) {
/* pr_debug("Message detected in slow queue\n"); */
spin_lock_irqsave(&free_buff_lock, flags);
- pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next, struct dpram_blk, list);
+ pdpram_blk = list_entry(ft1000dev->app_info[i].app_sqlist.next,
+ struct dpram_blk, list);
list_del(&pdpram_blk->list);
ft1000dev->app_info[i].NumOfMsg--;
/* pr_debug("NumOfMsg for app %d = %d\n", i, ft1000dev->app_info[i].NumOfMsg); */
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
index 5def347..297b7ae 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_download.c
@@ -95,7 +95,6 @@
long nDspImages; /* Number of DSP images in file. */
};
-#pragma pack(1)
struct dsp_image_info {
long coff_date; /* Date/time when DSP Coff image was built. */
long begin_offset; /* Offset in file where image begins. */
@@ -105,7 +104,7 @@
long version; /* Embedded version # of DSP code. */
unsigned short checksum; /* DSP File checksum */
unsigned short pad1;
-};
+} __packed;
/* checks if the doorbell register is cleared */
@@ -180,7 +179,8 @@
}
status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_HANDSHAKE_LOC, (u8 *)&handshake, 1);
+ DWNLD_MAG1_HANDSHAKE_LOC,
+ (u8 *)&handshake, 1);
handshake = ntohs(handshake);
if (status)
@@ -281,12 +281,14 @@
if (ft1000dev->bootmode == 1) {
status = fix_ft1000_read_dpram32(ft1000dev,
- DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
+ DWNLD_MAG1_TYPE_LOC,
+ (u8 *)&tempx);
tempx = ntohl(tempx);
} else {
tempx = 0;
status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_TYPE_LOC, (u8 *)&tempword, 1);
+ DWNLD_MAG1_TYPE_LOC,
+ (u8 *)&tempword, 1);
tempx |= (tempword << 16);
tempx = ntohl(tempx);
}
@@ -304,7 +306,8 @@
if (ft1000dev->bootmode == 1) {
status = fix_ft1000_read_dpram32(ft1000dev,
- DWNLD_MAG1_TYPE_LOC, (u8 *)&tempx);
+ DWNLD_MAG1_TYPE_LOC,
+ (u8 *)&tempx);
tempx = ntohl(tempx);
} else {
if (ft1000dev->usbboot == 2) {
@@ -332,14 +335,17 @@
if (ft1000dev->bootmode == 1) {
status = fix_ft1000_read_dpram32(ft1000dev,
- DWNLD_MAG1_SIZE_LOC, (u8 *)&value);
+ DWNLD_MAG1_SIZE_LOC,
+ (u8 *)&value);
value = ntohl(value);
} else {
status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 0);
+ DWNLD_MAG1_SIZE_LOC,
+ (u8 *)&tempword, 0);
value = tempword;
status = ft1000_read_dpram16(ft1000dev,
- DWNLD_MAG1_SIZE_LOC, (u8 *)&tempword, 1);
+ DWNLD_MAG1_SIZE_LOC,
+ (u8 *)&tempword, 1);
value |= (tempword << 16);
value = ntohl(value);
}
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
index e6b5976..9620970 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_hw.c
@@ -842,7 +842,6 @@
skb = dev_alloc_skb(len + 12 + 2);
if (skb == NULL) {
- pr_debug("No Network buffers available\n");
info->stats.rx_errors++;
ft1000_submit_rx_urb(info);
return -1;
diff --git a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
index fea60d5..9b5050f 100644
--- a/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
+++ b/drivers/staging/ft1000/ft1000-usb/ft1000_usb.h
@@ -134,8 +134,8 @@
int ft1000_create_dev(struct ft1000_usb *dev);
void ft1000_destroy_dev(struct net_device *dev);
-extern int card_send_command(struct ft1000_usb *ft1000dev,
- void *ptempbuffer, int size);
+int card_send_command(struct ft1000_usb *ft1000dev,
+ void *ptempbuffer, int size);
struct dpram_blk *ft1000_get_buffer(struct list_head *bufflist);
void ft1000_free_buffer(struct dpram_blk *pdpram_blk, struct list_head *plist);
diff --git a/drivers/staging/gdm72xx/usb_ids.h b/drivers/staging/gdm72xx/usb_ids.h
index 8ce544d..7afb9ba 100644
--- a/drivers/staging/gdm72xx/usb_ids.h
+++ b/drivers/staging/gdm72xx/usb_ids.h
@@ -32,7 +32,9 @@
#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)}
#define USB_DEVICE_CDC_DATA(vid, pid) \
@@ -40,6 +42,7 @@
static const struct usb_device_id id_table[] = {
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),
@@ -58,6 +61,7 @@
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),
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index d7c5223..3f7715c 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -1,5 +1,5 @@
/*
- * Freescale i.MX28 LRADC driver
+ * Freescale MXS LRADC driver
*
* Copyright (c) 2012 DENX Software Engineering, GmbH.
* Marek Vasut <marex@denx.de>
@@ -15,34 +15,30 @@
* GNU General Public License for more details.
*/
-#include <linux/err.h>
-#include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/of_device.h>
-#include <linux/sysfs.h>
-#include <linux/list.h>
-#include <linux/io.h>
-#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-#include <linux/wait.h>
-#include <linux/sched.h>
+#include <linux/slab.h>
#include <linux/stmp_device.h>
-#include <linux/bitops.h>
-#include <linux/completion.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/clk.h>
+#include <linux/sysfs.h>
-#include <linux/iio/iio.h>
-#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/sysfs.h>
#define DRIVER_NAME "mxs-lradc"
@@ -65,14 +61,14 @@
* Once the pen touches the touchscreen, the touchscreen switches from
* IRQ-driven mode to polling mode to prevent interrupt storm. The polling
* is realized by worker thread, which is called every 20 or so milliseconds.
- * This gives the touchscreen enough fluence and does not strain the system
+ * This gives the touchscreen enough fluency and does not strain the system
* too much.
*/
#define LRADC_TS_SAMPLE_DELAY_MS 5
/*
* The LRADC reads the following amount of samples from each touchscreen
- * channel and the driver then computes avarage of these.
+ * channel and the driver then computes average of these.
*/
#define LRADC_TS_SAMPLE_AMOUNT 4
@@ -238,7 +234,7 @@
* CH5 -- Touch screen YNLR
* CH6 -- Touch screen WIPER (5-wire only)
*
- * The bitfields below represents which parts of the LRADC block are
+ * The bit fields below represents which parts of the LRADC block are
* switched into special mode of operation. These channels can not
* be sampled as regular LRADC channels. The driver will refuse any
* attempt to sample these channels.
@@ -252,7 +248,7 @@
struct input_dev *ts_input;
enum mxs_lradc_id soc;
- enum lradc_ts_plate cur_plate; /* statemachine */
+ enum lradc_ts_plate cur_plate; /* state machine */
bool ts_valid;
unsigned ts_x_pos;
unsigned ts_y_pos;
@@ -812,7 +808,7 @@
int ret;
/*
- * See if there is no buffered operation in progess. If there is, simply
+ * See if there is no buffered operation in progress. If there is, simply
* bail out. This can be improved to support both buffered and raw IO at
* the same time, yet the code becomes horribly complicated. Therefore I
* applied KISS principle here.
@@ -1369,7 +1365,7 @@
* Driver initialization
*/
-#define MXS_ADC_CHAN(idx, chan_type) { \
+#define MXS_ADC_CHAN(idx, chan_type, name) { \
.type = (chan_type), \
.indexed = 1, \
.scan_index = (idx), \
@@ -1382,17 +1378,18 @@
.realbits = LRADC_RESOLUTION, \
.storagebits = 32, \
}, \
+ .datasheet_name = (name), \
}
-static const struct iio_chan_spec mxs_lradc_chan_spec[] = {
- MXS_ADC_CHAN(0, IIO_VOLTAGE),
- MXS_ADC_CHAN(1, IIO_VOLTAGE),
- MXS_ADC_CHAN(2, IIO_VOLTAGE),
- MXS_ADC_CHAN(3, IIO_VOLTAGE),
- MXS_ADC_CHAN(4, IIO_VOLTAGE),
- MXS_ADC_CHAN(5, IIO_VOLTAGE),
- MXS_ADC_CHAN(6, IIO_VOLTAGE),
- MXS_ADC_CHAN(7, IIO_VOLTAGE), /* VBATT */
+static const struct iio_chan_spec mx23_lradc_chan_spec[] = {
+ MXS_ADC_CHAN(0, IIO_VOLTAGE, "LRADC0"),
+ MXS_ADC_CHAN(1, IIO_VOLTAGE, "LRADC1"),
+ MXS_ADC_CHAN(2, IIO_VOLTAGE, "LRADC2"),
+ MXS_ADC_CHAN(3, IIO_VOLTAGE, "LRADC3"),
+ MXS_ADC_CHAN(4, IIO_VOLTAGE, "LRADC4"),
+ MXS_ADC_CHAN(5, IIO_VOLTAGE, "LRADC5"),
+ MXS_ADC_CHAN(6, IIO_VOLTAGE, "VDDIO"),
+ MXS_ADC_CHAN(7, IIO_VOLTAGE, "VBATT"),
/* Combined Temperature sensors */
{
.type = IIO_TEMP,
@@ -1403,6 +1400,7 @@
BIT(IIO_CHAN_INFO_SCALE),
.channel = 8,
.scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
+ .datasheet_name = "TEMP_DIE",
},
/* Hidden channel to keep indexes */
{
@@ -1411,12 +1409,48 @@
.scan_index = -1,
.channel = 9,
},
- MXS_ADC_CHAN(10, IIO_VOLTAGE), /* VDDIO */
- MXS_ADC_CHAN(11, IIO_VOLTAGE), /* VTH */
- MXS_ADC_CHAN(12, IIO_VOLTAGE), /* VDDA */
- MXS_ADC_CHAN(13, IIO_VOLTAGE), /* VDDD */
- MXS_ADC_CHAN(14, IIO_VOLTAGE), /* VBG */
- MXS_ADC_CHAN(15, IIO_VOLTAGE), /* VDD5V */
+ MXS_ADC_CHAN(10, IIO_VOLTAGE, NULL),
+ MXS_ADC_CHAN(11, IIO_VOLTAGE, NULL),
+ MXS_ADC_CHAN(12, IIO_VOLTAGE, "USB_DP"),
+ MXS_ADC_CHAN(13, IIO_VOLTAGE, "USB_DN"),
+ MXS_ADC_CHAN(14, IIO_VOLTAGE, "VBG"),
+ MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"),
+};
+
+static const struct iio_chan_spec mx28_lradc_chan_spec[] = {
+ MXS_ADC_CHAN(0, IIO_VOLTAGE, "LRADC0"),
+ MXS_ADC_CHAN(1, IIO_VOLTAGE, "LRADC1"),
+ MXS_ADC_CHAN(2, IIO_VOLTAGE, "LRADC2"),
+ MXS_ADC_CHAN(3, IIO_VOLTAGE, "LRADC3"),
+ MXS_ADC_CHAN(4, IIO_VOLTAGE, "LRADC4"),
+ MXS_ADC_CHAN(5, IIO_VOLTAGE, "LRADC5"),
+ MXS_ADC_CHAN(6, IIO_VOLTAGE, "LRADC6"),
+ MXS_ADC_CHAN(7, IIO_VOLTAGE, "VBATT"),
+ /* Combined Temperature sensors */
+ {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .scan_index = 8,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_OFFSET) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .channel = 8,
+ .scan_type = {.sign = 'u', .realbits = 18, .storagebits = 32,},
+ .datasheet_name = "TEMP_DIE",
+ },
+ /* Hidden channel to keep indexes */
+ {
+ .type = IIO_TEMP,
+ .indexed = 1,
+ .scan_index = -1,
+ .channel = 9,
+ },
+ MXS_ADC_CHAN(10, IIO_VOLTAGE, "VDDIO"),
+ MXS_ADC_CHAN(11, IIO_VOLTAGE, "VTH"),
+ MXS_ADC_CHAN(12, IIO_VOLTAGE, "VDDA"),
+ MXS_ADC_CHAN(13, IIO_VOLTAGE, "VDDD"),
+ MXS_ADC_CHAN(14, IIO_VOLTAGE, "VBG"),
+ MXS_ADC_CHAN(15, IIO_VOLTAGE, "VDD5V"),
};
static int mxs_lradc_hw_init(struct mxs_lradc *lradc)
@@ -1612,10 +1646,16 @@
iio->dev.parent = &pdev->dev;
iio->info = &mxs_lradc_iio_info;
iio->modes = INDIO_DIRECT_MODE;
- iio->channels = mxs_lradc_chan_spec;
- iio->num_channels = ARRAY_SIZE(mxs_lradc_chan_spec);
iio->masklength = LRADC_MAX_TOTAL_CHANS;
+ if (lradc->soc == IMX23_LRADC) {
+ iio->channels = mx23_lradc_chan_spec;
+ iio->num_channels = ARRAY_SIZE(mx23_lradc_chan_spec);
+ } else {
+ iio->channels = mx28_lradc_chan_spec;
+ iio->num_channels = ARRAY_SIZE(mx28_lradc_chan_spec);
+ }
+
ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time,
&mxs_lradc_trigger_handler,
&mxs_lradc_buffer_ops);
@@ -1707,6 +1747,6 @@
module_platform_driver(mxs_lradc_driver);
MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
-MODULE_DESCRIPTION("Freescale i.MX28 LRADC driver");
+MODULE_DESCRIPTION("Freescale MXS LRADC driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/staging/iio/addac/adt7316-i2c.c b/drivers/staging/iio/addac/adt7316-i2c.c
index 75ddd4f..78fe0b5 100644
--- a/drivers/staging/iio/addac/adt7316-i2c.c
+++ b/drivers/staging/iio/addac/adt7316-i2c.c
@@ -124,7 +124,6 @@
.driver = {
.name = "adt7316",
.pm = ADT7316_PM_OPS,
- .owner = THIS_MODULE,
},
.probe = adt7316_i2c_probe,
.id_table = adt7316_i2c_id,
diff --git a/drivers/staging/iio/iio_dummy_evgen.c b/drivers/staging/iio/iio_dummy_evgen.c
index c54d5b5..6d38854 100644
--- a/drivers/staging/iio/iio_dummy_evgen.c
+++ b/drivers/staging/iio/iio_dummy_evgen.c
@@ -214,6 +214,7 @@
.groups = iio_evgen_groups,
.release = &iio_evgen_release,
};
+
static __init int iio_dummy_evgen_init(void)
{
int ret = iio_dummy_evgen_create();
diff --git a/drivers/staging/iio/iio_simple_dummy.c b/drivers/staging/iio/iio_simple_dummy.c
index 1629a8a..381f90f 100644
--- a/drivers/staging/iio/iio_simple_dummy.c
+++ b/drivers/staging/iio/iio_simple_dummy.c
@@ -611,7 +611,6 @@
*/
iio_dummy_devs[index] = indio_dev;
-
/*
* Set the device name.
*
@@ -675,7 +674,6 @@
*/
struct iio_dev *indio_dev = iio_dummy_devs[index];
-
/* Unregister the device */
iio_device_unregister(indio_dev);
diff --git a/drivers/staging/iio/iio_simple_dummy.h b/drivers/staging/iio/iio_simple_dummy.h
index e877a99..8d00224 100644
--- a/drivers/staging/iio/iio_simple_dummy.h
+++ b/drivers/staging/iio/iio_simple_dummy.h
@@ -119,6 +119,7 @@
{
return 0;
};
+
static inline
void iio_simple_dummy_unconfigure_buffer(struct iio_dev *indio_dev)
{};
diff --git a/drivers/staging/iio/iio_simple_dummy_buffer.c b/drivers/staging/iio/iio_simple_dummy_buffer.c
index a651b89..00ed774 100644
--- a/drivers/staging/iio/iio_simple_dummy_buffer.c
+++ b/drivers/staging/iio/iio_simple_dummy_buffer.c
@@ -32,6 +32,7 @@
[diffvoltage3m4] = -2,
[accelx] = 344,
};
+
/**
* iio_simple_dummy_trigger_h() - the trigger handler function
* @irq: the interrupt number
@@ -178,7 +179,6 @@
iio_kfifo_free(indio_dev->buffer);
error_ret:
return ret;
-
}
/**
diff --git a/drivers/staging/iio/iio_simple_dummy_events.c b/drivers/staging/iio/iio_simple_dummy_events.c
index ecc563c..73108ba 100644
--- a/drivers/staging/iio/iio_simple_dummy_events.c
+++ b/drivers/staging/iio/iio_simple_dummy_events.c
@@ -120,7 +120,7 @@
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- enum iio_event_info info,
+ enum iio_event_info info,
int *val, int *val2)
{
struct iio_dummy_state *st = iio_priv(indio_dev);
@@ -143,7 +143,7 @@
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- enum iio_event_info info,
+ enum iio_event_info info,
int val, int val2)
{
struct iio_dummy_state *st = iio_priv(indio_dev);
diff --git a/drivers/staging/iio/light/isl29018.c b/drivers/staging/iio/light/isl29018.c
index e646c5d..019ba52 100644
--- a/drivers/staging/iio/light/isl29018.c
+++ b/drivers/staging/iio/light/isl29018.c
@@ -838,7 +838,6 @@
.name = "isl29018",
.acpi_match_table = ACPI_PTR(isl29018_acpi_match),
.pm = ISL29018_PM_OPS,
- .owner = THIS_MODULE,
.of_match_table = isl29018_of_match,
},
.probe = isl29018_probe,
diff --git a/drivers/staging/iio/light/isl29028.c b/drivers/staging/iio/light/isl29028.c
index e5b2fdc..cd6f272 100644
--- a/drivers/staging/iio/light/isl29028.c
+++ b/drivers/staging/iio/light/isl29028.c
@@ -547,7 +547,6 @@
.class = I2C_CLASS_HWMON,
.driver = {
.name = "isl29028",
- .owner = THIS_MODULE,
.of_match_table = isl29028_of_match,
},
.probe = isl29028_probe,
diff --git a/drivers/staging/iio/meter/ade7854.h b/drivers/staging/iio/meter/ade7854.h
index 52ca541..52f4195 100644
--- a/drivers/staging/iio/meter/ade7854.h
+++ b/drivers/staging/iio/meter/ade7854.h
@@ -168,7 +168,7 @@
};
-extern int ade7854_probe(struct iio_dev *indio_dev, struct device *dev);
-extern int ade7854_remove(struct iio_dev *indio_dev);
+int ade7854_probe(struct iio_dev *indio_dev, struct device *dev);
+int ade7854_remove(struct iio_dev *indio_dev);
#endif
diff --git a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
index 3c1c8c6..9fe48ef 100644
--- a/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
+++ b/drivers/staging/iio/trigger/iio-trig-bfin-timer.c
@@ -79,7 +79,8 @@
}
static ssize_t iio_bfin_tmr_frequency_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
+ struct device_attribute *attr,
+ const char *buf, size_t count)
{
struct iio_trigger *trig = to_iio_trigger(dev);
struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
@@ -116,8 +117,8 @@
}
static ssize_t iio_bfin_tmr_frequency_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
+ struct device_attribute *attr,
+ char *buf)
{
struct iio_trigger *trig = to_iio_trigger(dev);
struct bfin_tmr_state *st = iio_trigger_get_drvdata(trig);
diff --git a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
index 0c1976d..2db8857 100644
--- a/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
+++ b/drivers/staging/iio/trigger/iio-trig-periodic-rtc.c
@@ -37,7 +37,7 @@
if (trig_info->frequency == 0 && state)
return -EINVAL;
dev_dbg(&trig_info->rtc->dev, "trigger frequency is %u\n",
- trig_info->frequency);
+ trig_info->frequency);
ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, state);
if (ret == 0)
trig_info->state = state;
@@ -74,8 +74,9 @@
if (ret == 0 && trig_info->state && trig_info->frequency == 0)
ret = rtc_irq_set_state(trig_info->rtc,
&trig_info->task, 1);
- } else
+ } else {
ret = rtc_irq_set_state(trig_info->rtc, &trig_info->task, 0);
+ }
if (ret)
goto error_ret;
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs.h b/drivers/staging/lustre/include/linux/libcfs/libcfs.h
index 5dd9cdf..01961d9 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs.h
@@ -134,7 +134,7 @@
/* container_of depends on "likely" which is defined in libcfs_private.h */
static inline void *__container_of(void *ptr, unsigned long shift)
{
- if (unlikely(IS_ERR(ptr) || ptr == NULL))
+ if (IS_ERR_OR_NULL(ptr))
return ptr;
return (char *)ptr - shift;
}
@@ -148,4 +148,17 @@
void *libcfs_kvzalloc_cpt(struct cfs_cpt_table *cptab, int cpt, size_t size,
gfp_t flags);
+extern struct miscdevice libcfs_dev;
+/**
+ * The path of debug log dump upcall script.
+ */
+extern char lnet_upcall[1024];
+extern char lnet_debug_log_upcall[1024];
+
+extern void libcfs_init_nidstrings(void);
+
+extern struct cfs_psdev_ops libcfs_psdev_ops;
+
+extern struct cfs_wi_sched *cfs_sched_rehash;
+
#endif /* _LIBCFS_H */
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
index 8251ac9..a3aa644 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_debug.h
@@ -50,7 +50,6 @@
extern unsigned int libcfs_debug;
extern unsigned int libcfs_printk;
extern unsigned int libcfs_console_ratelimit;
-extern unsigned int libcfs_watchdog_ratelimit;
extern unsigned int libcfs_console_max_delay;
extern unsigned int libcfs_console_min_delay;
extern unsigned int libcfs_console_backoff;
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h
index eea55d9..aa69c6a 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_fail.h
@@ -79,14 +79,16 @@
{
int ret = 0;
- if (unlikely(CFS_FAIL_PRECHECK(id) &&
- (ret = __cfs_fail_check_set(id, value, set)))) {
- if (quiet) {
- CDEBUG(D_INFO, "*** cfs_fail_loc=%x, val=%u***\n",
- id, value);
- } else {
- LCONSOLE_INFO("*** cfs_fail_loc=%x, val=%u***\n",
- id, value);
+ if (unlikely(CFS_FAIL_PRECHECK(id))) {
+ ret = __cfs_fail_check_set(id, value, set);
+ if (ret) {
+ if (quiet) {
+ CDEBUG(D_INFO, "*** cfs_fail_loc=%x, val=%u***\n",
+ id, value);
+ } else {
+ LCONSOLE_INFO("*** cfs_fail_loc=%x, val=%u***\n",
+ id, value);
+ }
}
}
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
index ed37d26..9544860 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_private.h
@@ -87,24 +87,6 @@
lbug_with_loc(&msgdata); \
} while (0)
-extern atomic_t libcfs_kmemory;
-/*
- * Memory
- */
-
-# define libcfs_kmem_inc(ptr, size) \
-do { \
- atomic_add(size, &libcfs_kmemory); \
-} while (0)
-
-# define libcfs_kmem_dec(ptr, size) \
-do { \
- atomic_sub(size, &libcfs_kmemory); \
-} while (0)
-
-# define libcfs_kmem_read() \
- atomic_read(&libcfs_kmemory)
-
#ifndef LIBCFS_VMALLOC_SIZE
#define LIBCFS_VMALLOC_SIZE (2 << PAGE_CACHE_SHIFT) /* 2 pages */
#endif
@@ -121,14 +103,9 @@
if (unlikely((ptr) == NULL)) { \
CERROR("LNET: out of memory at %s:%d (tried to alloc '" \
#ptr "' = %d)\n", __FILE__, __LINE__, (int)(size)); \
- CERROR("LNET: %d total bytes allocated by lnet\n", \
- libcfs_kmem_read()); \
} else { \
memset((ptr), 0, (size)); \
- libcfs_kmem_inc((ptr), (size)); \
- CDEBUG(D_MALLOC, "alloc '" #ptr "': %d at %p (tot %d).\n", \
- (int)(size), (ptr), libcfs_kmem_read()); \
- } \
+ } \
} while (0)
/**
@@ -180,9 +157,6 @@
"%s:%d\n", s, __FILE__, __LINE__); \
break; \
} \
- libcfs_kmem_dec((ptr), s); \
- CDEBUG(D_MALLOC, "kfreed '" #ptr "': %d at %p (tot %d).\n", \
- s, (ptr), libcfs_kmem_read()); \
if (unlikely(s > LIBCFS_VMALLOC_SIZE)) \
vfree(ptr); \
else \
diff --git a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h
index 509dc1e..478e958 100644
--- a/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h
+++ b/drivers/staging/lustre/include/linux/libcfs/libcfs_string.h
@@ -102,6 +102,4 @@
int cfs_ip_addr_match(__u32 addr, struct list_head *list);
void cfs_ip_addr_free(struct list_head *list);
-#define strtoul(str, endp, base) simple_strtoul(str, endp, base)
-
#endif
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
index 4eb24a1..c29d2ce 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.c
@@ -1390,7 +1390,7 @@
.max_pages_per_fmr = LNET_MAX_PAYLOAD/PAGE_SIZE,
.page_shift = PAGE_SHIFT,
.access = (IB_ACCESS_LOCAL_WRITE |
- IB_ACCESS_REMOTE_WRITE),
+ IB_ACCESS_REMOTE_WRITE),
.pool_size = fps->fps_pool_size,
.dirty_watermark = fps->fps_flush_trigger,
.flush_function = NULL,
@@ -1789,140 +1789,6 @@
goto again;
}
-void kiblnd_pmr_pool_unmap(kib_phys_mr_t *pmr)
-{
- kib_pmr_pool_t *ppo = pmr->pmr_pool;
- struct ib_mr *mr = pmr->pmr_mr;
-
- pmr->pmr_mr = NULL;
- kiblnd_pool_free_node(&ppo->ppo_pool, &pmr->pmr_list);
- if (mr != NULL)
- ib_dereg_mr(mr);
-}
-
-int kiblnd_pmr_pool_map(kib_pmr_poolset_t *pps, kib_hca_dev_t *hdev,
- kib_rdma_desc_t *rd, __u64 *iova, kib_phys_mr_t **pp_pmr)
-{
- kib_phys_mr_t *pmr;
- struct list_head *node;
- int rc;
- int i;
-
- node = kiblnd_pool_alloc_node(&pps->pps_poolset);
- if (node == NULL) {
- CERROR("Failed to allocate PMR descriptor\n");
- return -ENOMEM;
- }
-
- pmr = container_of(node, kib_phys_mr_t, pmr_list);
- if (pmr->pmr_pool->ppo_hdev != hdev) {
- kiblnd_pool_free_node(&pmr->pmr_pool->ppo_pool, node);
- return -EAGAIN;
- }
-
- for (i = 0; i < rd->rd_nfrags; i++) {
- pmr->pmr_ipb[i].addr = rd->rd_frags[i].rf_addr;
- pmr->pmr_ipb[i].size = rd->rd_frags[i].rf_nob;
- }
-
- pmr->pmr_mr = ib_reg_phys_mr(hdev->ibh_pd,
- pmr->pmr_ipb, rd->rd_nfrags,
- IB_ACCESS_LOCAL_WRITE |
- IB_ACCESS_REMOTE_WRITE,
- iova);
- if (!IS_ERR(pmr->pmr_mr)) {
- pmr->pmr_iova = *iova;
- *pp_pmr = pmr;
- return 0;
- }
-
- rc = PTR_ERR(pmr->pmr_mr);
- CERROR("Failed ib_reg_phys_mr: %d\n", rc);
-
- pmr->pmr_mr = NULL;
- kiblnd_pool_free_node(&pmr->pmr_pool->ppo_pool, node);
-
- return rc;
-}
-
-static void kiblnd_destroy_pmr_pool(kib_pool_t *pool)
-{
- kib_pmr_pool_t *ppo = container_of(pool, kib_pmr_pool_t, ppo_pool);
- kib_phys_mr_t *pmr;
- kib_phys_mr_t *tmp;
-
- LASSERT(pool->po_allocated == 0);
-
- list_for_each_entry_safe(pmr, tmp, &pool->po_free_list, pmr_list) {
- LASSERT(pmr->pmr_mr == NULL);
- list_del(&pmr->pmr_list);
-
- if (pmr->pmr_ipb != NULL) {
- LIBCFS_FREE(pmr->pmr_ipb,
- IBLND_MAX_RDMA_FRAGS *
- sizeof(struct ib_phys_buf));
- }
-
- LIBCFS_FREE(pmr, sizeof(kib_phys_mr_t));
- }
-
- kiblnd_fini_pool(pool);
- if (ppo->ppo_hdev != NULL)
- kiblnd_hdev_decref(ppo->ppo_hdev);
-
- LIBCFS_FREE(ppo, sizeof(kib_pmr_pool_t));
-}
-
-static inline int kiblnd_pmr_pool_size(int ncpts)
-{
- int size = *kiblnd_tunables.kib_pmr_pool_size / ncpts;
-
- return max(IBLND_PMR_POOL, size);
-}
-
-static int kiblnd_create_pmr_pool(kib_poolset_t *ps, int size,
- kib_pool_t **pp_po)
-{
- struct kib_pmr_pool *ppo;
- struct kib_pool *pool;
- kib_phys_mr_t *pmr;
- int i;
-
- LIBCFS_CPT_ALLOC(ppo, lnet_cpt_table(),
- ps->ps_cpt, sizeof(kib_pmr_pool_t));
- if (ppo == NULL) {
- CERROR("Failed to allocate PMR pool\n");
- return -ENOMEM;
- }
-
- pool = &ppo->ppo_pool;
- kiblnd_init_pool(ps, pool, size);
-
- for (i = 0; i < size; i++) {
- LIBCFS_CPT_ALLOC(pmr, lnet_cpt_table(),
- ps->ps_cpt, sizeof(kib_phys_mr_t));
- if (pmr == NULL)
- break;
-
- pmr->pmr_pool = ppo;
- LIBCFS_CPT_ALLOC(pmr->pmr_ipb, lnet_cpt_table(), ps->ps_cpt,
- IBLND_MAX_RDMA_FRAGS * sizeof(*pmr->pmr_ipb));
- if (pmr->pmr_ipb == NULL)
- break;
-
- list_add(&pmr->pmr_list, &pool->po_free_list);
- }
-
- if (i < size) {
- ps->ps_pool_destroy(pool);
- return -ENOMEM;
- }
-
- ppo->ppo_hdev = kiblnd_current_hdev(ps->ps_net->ibn_dev);
- *pp_po = pool;
- return 0;
-}
-
static void kiblnd_destroy_tx_pool(kib_pool_t *pool)
{
kib_tx_pool_t *tpo = container_of(pool, kib_tx_pool_t, tpo_pool);
@@ -2078,7 +1944,6 @@
cfs_cpt_for_each(i, lnet_cpt_table()) {
kib_tx_poolset_t *tps;
kib_fmr_poolset_t *fps;
- kib_pmr_poolset_t *pps;
if (net->ibn_tx_ps != NULL) {
tps = net->ibn_tx_ps[i];
@@ -2089,11 +1954,6 @@
fps = net->ibn_fmr_ps[i];
kiblnd_fini_fmr_poolset(fps);
}
-
- if (net->ibn_pmr_ps != NULL) {
- pps = net->ibn_pmr_ps[i];
- kiblnd_fini_poolset(&pps->pps_poolset);
- }
}
if (net->ibn_tx_ps != NULL) {
@@ -2105,18 +1965,13 @@
cfs_percpt_free(net->ibn_fmr_ps);
net->ibn_fmr_ps = NULL;
}
-
- if (net->ibn_pmr_ps != NULL) {
- cfs_percpt_free(net->ibn_pmr_ps);
- net->ibn_pmr_ps = NULL;
- }
}
static int kiblnd_net_init_pools(kib_net_t *net, __u32 *cpts, int ncpts)
{
unsigned long flags;
int cpt;
- int rc;
+ int rc = 0;
int i;
read_lock_irqsave(&kiblnd_data.kib_global_lock, flags);
@@ -2137,12 +1992,16 @@
goto failed;
}
- /* TX pool must be created later than FMR/PMR, see LU-2268
- * for details */
+ /*
+ * TX pool must be created later than FMR, see LU-2268
+ * for details
+ */
LASSERT(net->ibn_tx_ps == NULL);
- /* premapping can fail if ibd_nmr > 1, so we always create
- * FMR/PMR pool and map-on-demand if premapping failed */
+ /*
+ * premapping can fail if ibd_nmr > 1, so we always create
+ * FMR pool and map-on-demand if premapping failed
+ */
net->ibn_fmr_ps = cfs_percpt_alloc(lnet_cpt_table(),
sizeof(kib_fmr_poolset_t));
@@ -2158,7 +2017,7 @@
kiblnd_fmr_pool_size(ncpts),
kiblnd_fmr_flush_trigger(ncpts));
if (rc == -ENOSYS && i == 0) /* no FMR */
- break; /* create PMR pool */
+ break;
if (rc != 0) { /* a real error */
CERROR("Can't initialize FMR pool for CPT %d: %d\n",
@@ -2175,38 +2034,8 @@
cfs_percpt_free(net->ibn_fmr_ps);
net->ibn_fmr_ps = NULL;
- CWARN("Device does not support FMR, failing back to PMR\n");
-
- if (*kiblnd_tunables.kib_pmr_pool_size <
- *kiblnd_tunables.kib_ntx / 4) {
- CERROR("Can't set pmr pool size (%d) < ntx / 4(%d)\n",
- *kiblnd_tunables.kib_pmr_pool_size,
- *kiblnd_tunables.kib_ntx / 4);
- rc = -EINVAL;
- goto failed;
- }
-
- net->ibn_pmr_ps = cfs_percpt_alloc(lnet_cpt_table(),
- sizeof(kib_pmr_poolset_t));
- if (net->ibn_pmr_ps == NULL) {
- CERROR("Failed to allocate PMR pool array\n");
- rc = -ENOMEM;
- goto failed;
- }
-
- for (i = 0; i < ncpts; i++) {
- cpt = (cpts == NULL) ? i : cpts[i];
- rc = kiblnd_init_poolset(&net->ibn_pmr_ps[cpt]->pps_poolset,
- cpt, net, "PMR",
- kiblnd_pmr_pool_size(ncpts),
- kiblnd_create_pmr_pool,
- kiblnd_destroy_pmr_pool, NULL, NULL);
- if (rc != 0) {
- CERROR("Can't initialize PMR pool for CPT %d: %d\n",
- cpt, rc);
+ CWARN("Device does not support FMR\n");
goto failed;
- }
- }
create_tx_pool:
net->ibn_tx_ps = cfs_percpt_alloc(lnet_cpt_table(),
@@ -2318,17 +2147,13 @@
static int kiblnd_hdev_setup_mrs(kib_hca_dev_t *hdev)
{
struct ib_mr *mr;
- int i;
int rc;
- __u64 mm_size;
- __u64 mr_size;
int acflags = IB_ACCESS_LOCAL_WRITE | IB_ACCESS_REMOTE_WRITE;
rc = kiblnd_hdev_get_attr(hdev);
if (rc != 0)
return rc;
- if (hdev->ibh_mr_shift == 64) {
LIBCFS_ALLOC(hdev->ibh_mrs, 1 * sizeof(*hdev->ibh_mrs));
if (hdev->ibh_mrs == NULL) {
CERROR("Failed to allocate MRs table\n");
@@ -2347,53 +2172,6 @@
hdev->ibh_mrs[0] = mr;
- goto out;
- }
-
- mr_size = 1ULL << hdev->ibh_mr_shift;
- mm_size = (unsigned long)high_memory - PAGE_OFFSET;
-
- hdev->ibh_nmrs = (int)((mm_size + mr_size - 1) >> hdev->ibh_mr_shift);
-
- if (hdev->ibh_mr_shift < 32 || hdev->ibh_nmrs > 1024) {
- /* it's 4T..., assume we will re-code at that time */
- CERROR("Can't support memory size: x%#llx with MR size: x%#llx\n",
- mm_size, mr_size);
- return -EINVAL;
- }
-
- /* create an array of MRs to cover all memory */
- LIBCFS_ALLOC(hdev->ibh_mrs, sizeof(*hdev->ibh_mrs) * hdev->ibh_nmrs);
- if (hdev->ibh_mrs == NULL) {
- CERROR("Failed to allocate MRs' table\n");
- return -ENOMEM;
- }
-
- for (i = 0; i < hdev->ibh_nmrs; i++) {
- struct ib_phys_buf ipb;
- __u64 iova;
-
- ipb.size = hdev->ibh_mr_size;
- ipb.addr = i * mr_size;
- iova = ipb.addr;
-
- mr = ib_reg_phys_mr(hdev->ibh_pd, &ipb, 1, acflags, &iova);
- if (IS_ERR(mr)) {
- CERROR("Failed ib_reg_phys_mr addr %#llx size %#llx : %ld\n",
- ipb.addr, ipb.size, PTR_ERR(mr));
- kiblnd_hdev_cleanup_mrs(hdev);
- return PTR_ERR(mr);
- }
-
- LASSERT(iova == ipb.addr);
-
- hdev->ibh_mrs[i] = mr;
- }
-
-out:
- if (hdev->ibh_mr_size != ~0ULL || hdev->ibh_nmrs != 1)
- LCONSOLE_INFO("Register global MR array, MR size: %#llx, array size: %d\n",
- hdev->ibh_mr_size, hdev->ibh_nmrs);
return 0;
}
@@ -2564,14 +2342,9 @@
kiblnd_fail_poolset(&net->ibn_tx_ps[i]->tps_poolset,
&zombie_tpo);
- if (net->ibn_fmr_ps != NULL) {
+ if (net->ibn_fmr_ps)
kiblnd_fail_fmr_poolset(net->ibn_fmr_ps[i],
&zombie_fpo);
-
- } else if (net->ibn_pmr_ps != NULL) {
- kiblnd_fail_poolset(&net->ibn_pmr_ps[i]->
- pps_poolset, &zombie_ppo);
- }
}
}
@@ -2667,9 +2440,6 @@
LASSERT(list_empty(&kiblnd_data.kib_devs));
- CDEBUG(D_MALLOC, "before LND base cleanup: kmem %d\n",
- atomic_read(&libcfs_kmemory));
-
switch (kiblnd_data.kib_init) {
default:
LBUG();
@@ -2720,9 +2490,6 @@
if (kiblnd_data.kib_scheds != NULL)
cfs_percpt_free(kiblnd_data.kib_scheds);
- CDEBUG(D_MALLOC, "after LND base cleanup: kmem %d\n",
- atomic_read(&libcfs_kmemory));
-
kiblnd_data.kib_init = IBLND_INIT_NOTHING;
module_put(THIS_MODULE);
}
@@ -2739,9 +2506,6 @@
if (net == NULL)
goto out;
- CDEBUG(D_MALLOC, "before LND net cleanup: kmem %d\n",
- atomic_read(&libcfs_kmemory));
-
write_lock_irqsave(g_lock, flags);
net->ibn_shutdown = 1;
write_unlock_irqrestore(g_lock, flags);
@@ -2786,9 +2550,6 @@
break;
}
- CDEBUG(D_MALLOC, "after LND net cleanup: kmem %d\n",
- atomic_read(&libcfs_kmemory));
-
net->ibn_init = IBLND_INIT_NOTHING;
ni->ni_data = NULL;
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
index f5d1d9f..f4b6c33 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd.h
@@ -48,7 +48,7 @@
#include <linux/uio.h>
#include <linux/uaccess.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/fs.h>
#include <linux/file.h>
@@ -104,7 +104,6 @@
int *kib_map_on_demand; /* map-on-demand if RD has more
* fragments than this value, 0
* disable map-on-demand */
- int *kib_pmr_pool_size; /* # physical MR in pool */
int *kib_fmr_pool_size; /* # FMRs in pool */
int *kib_fmr_flush_trigger; /* When to trigger FMR flush */
int *kib_fmr_cache; /* enable FMR pool cache? */
@@ -120,7 +119,7 @@
#define IBLND_CREDIT_HIGHWATER_V1 7 /* V1 only : when eagerly to return credits */
#define IBLND_CREDITS_DEFAULT 8 /* default # of peer credits */
-#define IBLND_CREDITS_MAX ((typeof(((kib_msg_t*) 0)->ibm_credits)) - 1) /* Max # of peer credits */
+#define IBLND_CREDITS_MAX ((typeof(((kib_msg_t *) 0)->ibm_credits)) - 1) /* Max # of peer credits */
#define IBLND_MSG_QUEUE_SIZE(v) ((v) == IBLND_MSG_VERSION_1 ? \
IBLND_MSG_QUEUE_SIZE_V1 : \
@@ -163,7 +162,6 @@
/* Pools (shared by connections on each CPT) */
/* These pools can grow at runtime, so don't need give a very large value */
#define IBLND_TX_POOL 256
-#define IBLND_PMR_POOL 256
#define IBLND_FMR_POOL 256
#define IBLND_FMR_POOL_FLUSH 192
@@ -232,17 +230,6 @@
struct page *ibp_pages[0]; /* page array */
} kib_pages_t;
-struct kib_pmr_pool;
-
-typedef struct {
- struct list_head pmr_list; /* chain node */
- struct ib_phys_buf *pmr_ipb; /* physical buffer */
- struct ib_mr *pmr_mr; /* IB MR */
- struct kib_pmr_pool *pmr_pool; /* owner of this MR */
- __u64 pmr_iova; /* Virtual I/O address */
- int pmr_refcount; /* reference count */
-} kib_phys_mr_t;
-
struct kib_pool;
struct kib_poolset;
@@ -299,15 +286,6 @@
} kib_tx_pool_t;
typedef struct {
- kib_poolset_t pps_poolset; /* pool-set */
-} kib_pmr_poolset_t;
-
-typedef struct kib_pmr_pool {
- struct kib_hca_dev *ppo_hdev; /* device for this pool */
- kib_pool_t ppo_pool; /* pool */
-} kib_pmr_pool_t;
-
-typedef struct {
spinlock_t fps_lock; /* serialize */
struct kib_net *fps_net; /* IB network */
struct list_head fps_pool_list; /* FMR pool list */
@@ -347,7 +325,6 @@
kib_tx_poolset_t **ibn_tx_ps; /* tx pool-set */
kib_fmr_poolset_t **ibn_fmr_ps; /* fmr pool-set */
- kib_pmr_poolset_t **ibn_pmr_ps; /* pmr pool-set */
kib_dev_t *ibn_dev; /* underlying IB device */
} kib_net_t;
@@ -519,7 +496,7 @@
enum ib_wc_status rx_status; /* completion status */
kib_msg_t *rx_msg; /* message buffer (host vaddr) */
__u64 rx_msgaddr; /* message buffer (I/O addr) */
- DECLARE_PCI_UNMAP_ADDR (rx_msgunmap); /* for dma_unmap_single() */
+ DECLARE_PCI_UNMAP_ADDR(rx_msgunmap); /* for dma_unmap_single() */
struct ib_recv_wr rx_wrq; /* receive work item... */
struct ib_sge rx_sge; /* ...and its memory */
} kib_rx_t;
@@ -546,7 +523,7 @@
* completion */
kib_msg_t *tx_msg; /* message buffer (host vaddr) */
__u64 tx_msgaddr; /* message buffer (I/O addr) */
- DECLARE_PCI_UNMAP_ADDR (tx_msgunmap); /* for dma_unmap_single() */
+ DECLARE_PCI_UNMAP_ADDR(tx_msgunmap); /* for dma_unmap_single() */
int tx_nwrq; /* # send work items */
struct ib_send_wr *tx_wrq; /* send work items... */
struct ib_sge *tx_sge; /* ...and their memory */
@@ -554,10 +531,7 @@
int tx_nfrags; /* # entries in... */
struct scatterlist *tx_frags; /* dma_map_sg descriptor */
__u64 *tx_pages; /* rdma phys page addrs */
- union {
- kib_phys_mr_t *pmr; /* MR for physical buffer */
- kib_fmr_t fmr; /* FMR */
- } tx_u;
+ kib_fmr_t fmr; /* FMR */
int tx_dmadir; /* dma direction */
} kib_tx_t;
@@ -642,19 +616,19 @@
extern kib_data_t kiblnd_data;
-extern void kiblnd_hdev_destroy(kib_hca_dev_t *hdev);
+void kiblnd_hdev_destroy(kib_hca_dev_t *hdev);
static inline void
kiblnd_hdev_addref_locked(kib_hca_dev_t *hdev)
{
- LASSERT (atomic_read(&hdev->ibh_ref) > 0);
+ LASSERT(atomic_read(&hdev->ibh_ref) > 0);
atomic_inc(&hdev->ibh_ref);
}
static inline void
kiblnd_hdev_decref(kib_hca_dev_t *hdev)
{
- LASSERT (atomic_read(&hdev->ibh_ref) > 0);
+ LASSERT(atomic_read(&hdev->ibh_ref) > 0);
if (atomic_dec_and_test(&hdev->ibh_ref))
kiblnd_hdev_destroy(hdev);
}
@@ -701,7 +675,7 @@
do { \
CDEBUG(D_NET, "peer[%p] -> %s (%d)++\n", \
(peer), libcfs_nid2str((peer)->ibp_nid), \
- atomic_read (&(peer)->ibp_refcount)); \
+ atomic_read(&(peer)->ibp_refcount)); \
atomic_inc(&(peer)->ibp_refcount); \
} while (0)
@@ -709,32 +683,32 @@
do { \
CDEBUG(D_NET, "peer[%p] -> %s (%d)--\n", \
(peer), libcfs_nid2str((peer)->ibp_nid), \
- atomic_read (&(peer)->ibp_refcount)); \
+ atomic_read(&(peer)->ibp_refcount)); \
LASSERT_ATOMIC_POS(&(peer)->ibp_refcount); \
if (atomic_dec_and_test(&(peer)->ibp_refcount)) \
kiblnd_destroy_peer(peer); \
} while (0)
static inline struct list_head *
-kiblnd_nid2peerlist (lnet_nid_t nid)
+kiblnd_nid2peerlist(lnet_nid_t nid)
{
unsigned int hash =
((unsigned int)nid) % kiblnd_data.kib_peer_hash_size;
- return (&kiblnd_data.kib_peers [hash]);
+ return &kiblnd_data.kib_peers[hash];
}
static inline int
-kiblnd_peer_active (kib_peer_t *peer)
+kiblnd_peer_active(kib_peer_t *peer)
{
/* Am I in the peer hash table? */
- return (!list_empty(&peer->ibp_list));
+ return !list_empty(&peer->ibp_list);
}
static inline kib_conn_t *
-kiblnd_get_conn_locked (kib_peer_t *peer)
+kiblnd_get_conn_locked(kib_peer_t *peer)
{
- LASSERT (!list_empty(&peer->ibp_conns));
+ LASSERT(!list_empty(&peer->ibp_conns));
/* just return the first connection */
return list_entry(peer->ibp_conns.next, kib_conn_t, ibc_list);
@@ -751,7 +725,7 @@
static inline int
kiblnd_need_noop(kib_conn_t *conn)
{
- LASSERT (conn->ibc_state >= IBLND_CONN_ESTABLISHED);
+ LASSERT(conn->ibc_state >= IBLND_CONN_ESTABLISHED);
if (conn->ibc_outstanding_credits <
IBLND_CREDITS_HIGHWATER(conn->ibc_version) &&
@@ -788,7 +762,7 @@
}
static inline const char *
-kiblnd_queue2str (kib_conn_t *conn, struct list_head *q)
+kiblnd_queue2str(kib_conn_t *conn, struct list_head *q)
{
if (q == &conn->ibc_tx_queue)
return "tx_queue";
@@ -815,43 +789,43 @@
#define IBLND_WID_MASK 3UL
static inline __u64
-kiblnd_ptr2wreqid (void *ptr, int type)
+kiblnd_ptr2wreqid(void *ptr, int type)
{
unsigned long lptr = (unsigned long)ptr;
- LASSERT ((lptr & IBLND_WID_MASK) == 0);
- LASSERT ((type & ~IBLND_WID_MASK) == 0);
+ LASSERT((lptr & IBLND_WID_MASK) == 0);
+ LASSERT((type & ~IBLND_WID_MASK) == 0);
return (__u64)(lptr | type);
}
static inline void *
-kiblnd_wreqid2ptr (__u64 wreqid)
+kiblnd_wreqid2ptr(__u64 wreqid)
{
return (void *)(((unsigned long)wreqid) & ~IBLND_WID_MASK);
}
static inline int
-kiblnd_wreqid2type (__u64 wreqid)
+kiblnd_wreqid2type(__u64 wreqid)
{
- return (wreqid & IBLND_WID_MASK);
+ return wreqid & IBLND_WID_MASK;
}
static inline void
-kiblnd_set_conn_state (kib_conn_t *conn, int state)
+kiblnd_set_conn_state(kib_conn_t *conn, int state)
{
conn->ibc_state = state;
mb();
}
static inline void
-kiblnd_init_msg (kib_msg_t *msg, int type, int body_nob)
+kiblnd_init_msg(kib_msg_t *msg, int type, int body_nob)
{
msg->ibm_type = type;
msg->ibm_nob = offsetof(kib_msg_t, ibm_u) + body_nob;
}
static inline int
-kiblnd_rd_size (kib_rdma_desc_t *rd)
+kiblnd_rd_size(kib_rdma_desc_t *rd)
{
int i;
int size;
@@ -887,7 +861,7 @@
rd->rd_frags[index].rf_addr += nob;
rd->rd_frags[index].rf_nob -= nob;
} else {
- index ++;
+ index++;
}
return index;
@@ -896,8 +870,8 @@
static inline int
kiblnd_rd_msg_size(kib_rdma_desc_t *rd, int msgtype, int n)
{
- LASSERT (msgtype == IBLND_MSG_GET_REQ ||
- msgtype == IBLND_MSG_PUT_ACK);
+ LASSERT(msgtype == IBLND_MSG_GET_REQ ||
+ msgtype == IBLND_MSG_PUT_ACK);
return msgtype == IBLND_MSG_GET_REQ ?
offsetof(kib_get_msg_t, ibgm_rd.rd_frags[n]) :
@@ -978,57 +952,53 @@
int npages, __u64 iov, kib_fmr_t *fmr);
void kiblnd_fmr_pool_unmap(kib_fmr_t *fmr, int status);
-int kiblnd_pmr_pool_map(kib_pmr_poolset_t *pps, kib_hca_dev_t *hdev,
- kib_rdma_desc_t *rd, __u64 *iova, kib_phys_mr_t **pp_pmr);
-void kiblnd_pmr_pool_unmap(kib_phys_mr_t *pmr);
-
-int kiblnd_startup (lnet_ni_t *ni);
-void kiblnd_shutdown (lnet_ni_t *ni);
-int kiblnd_ctl (lnet_ni_t *ni, unsigned int cmd, void *arg);
-void kiblnd_query (struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
+int kiblnd_startup(lnet_ni_t *ni);
+void kiblnd_shutdown(lnet_ni_t *ni);
+int kiblnd_ctl(lnet_ni_t *ni, unsigned int cmd, void *arg);
+void kiblnd_query(struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
int kiblnd_tunables_init(void);
void kiblnd_tunables_fini(void);
-int kiblnd_connd (void *arg);
+int kiblnd_connd(void *arg);
int kiblnd_scheduler(void *arg);
int kiblnd_thread_start(int (*fn)(void *arg), void *arg, char *name);
-int kiblnd_failover_thread (void *arg);
+int kiblnd_failover_thread(void *arg);
int kiblnd_alloc_pages(kib_pages_t **pp, int cpt, int npages);
-void kiblnd_free_pages (kib_pages_t *p);
+void kiblnd_free_pages(kib_pages_t *p);
int kiblnd_cm_callback(struct rdma_cm_id *cmid,
struct rdma_cm_event *event);
int kiblnd_translate_mtu(int value);
int kiblnd_dev_failover(kib_dev_t *dev);
-int kiblnd_create_peer (lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid);
-void kiblnd_destroy_peer (kib_peer_t *peer);
-void kiblnd_destroy_dev (kib_dev_t *dev);
-void kiblnd_unlink_peer_locked (kib_peer_t *peer);
-void kiblnd_peer_alive (kib_peer_t *peer);
-kib_peer_t *kiblnd_find_peer_locked (lnet_nid_t nid);
-void kiblnd_peer_connect_failed (kib_peer_t *peer, int active, int error);
-int kiblnd_close_stale_conns_locked (kib_peer_t *peer,
+int kiblnd_create_peer(lnet_ni_t *ni, kib_peer_t **peerp, lnet_nid_t nid);
+void kiblnd_destroy_peer(kib_peer_t *peer);
+void kiblnd_destroy_dev(kib_dev_t *dev);
+void kiblnd_unlink_peer_locked(kib_peer_t *peer);
+void kiblnd_peer_alive(kib_peer_t *peer);
+kib_peer_t *kiblnd_find_peer_locked(lnet_nid_t nid);
+void kiblnd_peer_connect_failed(kib_peer_t *peer, int active, int error);
+int kiblnd_close_stale_conns_locked(kib_peer_t *peer,
int version, __u64 incarnation);
-int kiblnd_close_peer_conns_locked (kib_peer_t *peer, int why);
+int kiblnd_close_peer_conns_locked(kib_peer_t *peer, int why);
void kiblnd_connreq_done(kib_conn_t *conn, int status);
-kib_conn_t *kiblnd_create_conn (kib_peer_t *peer, struct rdma_cm_id *cmid,
+kib_conn_t *kiblnd_create_conn(kib_peer_t *peer, struct rdma_cm_id *cmid,
int state, int version);
-void kiblnd_destroy_conn (kib_conn_t *conn);
-void kiblnd_close_conn (kib_conn_t *conn, int error);
-void kiblnd_close_conn_locked (kib_conn_t *conn, int error);
+void kiblnd_destroy_conn(kib_conn_t *conn);
+void kiblnd_close_conn(kib_conn_t *conn, int error);
+void kiblnd_close_conn_locked(kib_conn_t *conn, int error);
-int kiblnd_init_rdma (kib_conn_t *conn, kib_tx_t *tx, int type,
+int kiblnd_init_rdma(kib_conn_t *conn, kib_tx_t *tx, int type,
int nob, kib_rdma_desc_t *dstrd, __u64 dstcookie);
-void kiblnd_launch_tx (lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid);
-void kiblnd_queue_tx_locked (kib_tx_t *tx, kib_conn_t *conn);
-void kiblnd_queue_tx (kib_tx_t *tx, kib_conn_t *conn);
-void kiblnd_init_tx_msg (lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob);
-void kiblnd_txlist_done (lnet_ni_t *ni, struct list_head *txlist,
+void kiblnd_launch_tx(lnet_ni_t *ni, kib_tx_t *tx, lnet_nid_t nid);
+void kiblnd_queue_tx_locked(kib_tx_t *tx, kib_conn_t *conn);
+void kiblnd_queue_tx(kib_tx_t *tx, kib_conn_t *conn);
+void kiblnd_init_tx_msg(lnet_ni_t *ni, kib_tx_t *tx, int type, int body_nob);
+void kiblnd_txlist_done(lnet_ni_t *ni, struct list_head *txlist,
int status);
void kiblnd_check_sends (kib_conn_t *conn);
@@ -1036,10 +1006,10 @@
void kiblnd_cq_event(struct ib_event *event, void *arg);
void kiblnd_cq_completion(struct ib_cq *cq, void *arg);
-void kiblnd_pack_msg (lnet_ni_t *ni, kib_msg_t *msg, int version,
+void kiblnd_pack_msg(lnet_ni_t *ni, kib_msg_t *msg, int version,
int credits, lnet_nid_t dstnid, __u64 dststamp);
int kiblnd_unpack_msg(kib_msg_t *msg, int nob);
-int kiblnd_post_rx (kib_rx_t *rx, int credit);
+int kiblnd_post_rx(kib_rx_t *rx, int credit);
int kiblnd_send(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg);
int kiblnd_recv(lnet_ni_t *ni, void *private, lnet_msg_t *lntmsg, int delayed,
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
index 477aa8b..a23a6d9 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_cb.c
@@ -121,7 +121,6 @@
LASSERT(tx->tx_conn == NULL);
LASSERT(tx->tx_lntmsg[0] == NULL);
LASSERT(tx->tx_lntmsg[1] == NULL);
- LASSERT(tx->tx_u.pmr == NULL);
LASSERT(tx->tx_nfrags == 0);
return tx;
@@ -575,7 +574,7 @@
cpt = tx->tx_pool->tpo_pool.po_owner->ps_cpt;
fps = net->ibn_fmr_ps[cpt];
- rc = kiblnd_fmr_pool_map(fps, pages, npages, 0, &tx->tx_u.fmr);
+ rc = kiblnd_fmr_pool_map(fps, pages, npages, 0, &tx->fmr);
if (rc != 0) {
CERROR("Can't map %d pages: %d\n", npages, rc);
return rc;
@@ -583,8 +582,8 @@
/* If rd is not tx_rd, it's going to get sent to a peer, who will need
* the rkey */
- rd->rd_key = (rd != tx->tx_rd) ? tx->tx_u.fmr.fmr_pfmr->fmr->rkey :
- tx->tx_u.fmr.fmr_pfmr->fmr->lkey;
+ rd->rd_key = (rd != tx->tx_rd) ? tx->fmr.fmr_pfmr->fmr->rkey :
+ tx->fmr.fmr_pfmr->fmr->lkey;
rd->rd_frags[0].rf_addr &= ~hdev->ibh_page_mask;
rd->rd_frags[0].rf_nob = nob;
rd->rd_nfrags = 1;
@@ -592,42 +591,6 @@
return 0;
}
-static int
-kiblnd_pmr_map_tx(kib_net_t *net, kib_tx_t *tx, kib_rdma_desc_t *rd, int nob)
-{
- kib_hca_dev_t *hdev;
- kib_pmr_poolset_t *pps;
- __u64 iova;
- int cpt;
- int rc;
-
- LASSERT(tx->tx_pool != NULL);
- LASSERT(tx->tx_pool->tpo_pool.po_owner != NULL);
-
- hdev = tx->tx_pool->tpo_hdev;
-
- iova = rd->rd_frags[0].rf_addr & ~hdev->ibh_page_mask;
-
- cpt = tx->tx_pool->tpo_pool.po_owner->ps_cpt;
-
- pps = net->ibn_pmr_ps[cpt];
- rc = kiblnd_pmr_pool_map(pps, hdev, rd, &iova, &tx->tx_u.pmr);
- if (rc != 0) {
- CERROR("Failed to create MR by phybuf: %d\n", rc);
- return rc;
- }
-
- /* If rd is not tx_rd, it's going to get sent to a peer, who will need
- * the rkey */
- rd->rd_key = (rd != tx->tx_rd) ? tx->tx_u.pmr->pmr_mr->rkey :
- tx->tx_u.pmr->pmr_mr->lkey;
- rd->rd_nfrags = 1;
- rd->rd_frags[0].rf_addr = iova;
- rd->rd_frags[0].rf_nob = nob;
-
- return 0;
-}
-
void
kiblnd_unmap_tx(lnet_ni_t *ni, kib_tx_t *tx)
{
@@ -635,13 +598,9 @@
LASSERT(net != NULL);
- if (net->ibn_fmr_ps != NULL && tx->tx_u.fmr.fmr_pfmr != NULL) {
- kiblnd_fmr_pool_unmap(&tx->tx_u.fmr, tx->tx_status);
- tx->tx_u.fmr.fmr_pfmr = NULL;
-
- } else if (net->ibn_pmr_ps != NULL && tx->tx_u.pmr != NULL) {
- kiblnd_pmr_pool_unmap(tx->tx_u.pmr);
- tx->tx_u.pmr = NULL;
+ if (net->ibn_fmr_ps && tx->fmr.fmr_pfmr) {
+ kiblnd_fmr_pool_unmap(&tx->fmr, tx->tx_status);
+ tx->fmr.fmr_pfmr = NULL;
}
if (tx->tx_nfrags != 0) {
@@ -687,8 +646,6 @@
if (net->ibn_fmr_ps != NULL)
return kiblnd_fmr_map_tx(net, tx, rd, nob);
- else if (net->ibn_pmr_ps != NULL)
- return kiblnd_pmr_map_tx(net, tx, rd, nob);
return -EINVAL;
}
@@ -3133,8 +3090,7 @@
dropped_lock = 0;
if (!list_empty(&kiblnd_data.kib_connd_zombies)) {
- conn = list_entry(kiblnd_data. \
- kib_connd_zombies.next,
+ conn = list_entry(kiblnd_data.kib_connd_zombies.next,
kib_conn_t, ibc_list);
list_del(&conn->ibc_list);
diff --git a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c
index b0e0036..b3d1b5d 100644
--- a/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c
+++ b/drivers/staging/lustre/lnet/klnds/o2iblnd/o2iblnd_modparams.c
@@ -126,11 +126,6 @@
module_param(fmr_cache, int, 0444);
MODULE_PARM_DESC(fmr_cache, "non-zero to enable FMR caching");
-/* NB: this value is shared by all CPTs, it can grow at runtime */
-static int pmr_pool_size = 512;
-module_param(pmr_pool_size, int, 0444);
-MODULE_PARM_DESC(pmr_pool_size, "size of MR cache pmr pool on each CPT");
-
/*
* 0: disable failover
* 1: enable failover if necessary
@@ -170,7 +165,6 @@
.kib_fmr_pool_size = &fmr_pool_size,
.kib_fmr_flush_trigger = &fmr_flush_trigger,
.kib_fmr_cache = &fmr_cache,
- .kib_pmr_pool_size = &pmr_pool_size,
.kib_require_priv_port = &require_privileged_port,
.kib_use_priv_port = &use_privileged_port,
.kib_nscheds = &nscheds
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
index 4128a92..d8bfcad 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.c
@@ -2252,8 +2252,6 @@
int i;
int j;
- CDEBUG(D_MALLOC, "before NAL cleanup: kmem %d\n",
- atomic_read(&libcfs_kmemory));
LASSERT(ksocknal_data.ksnd_nnets == 0);
switch (ksocknal_data.ksnd_init) {
@@ -2331,9 +2329,6 @@
break;
}
- CDEBUG(D_MALLOC, "after NAL cleanup: kmem %d\n",
- atomic_read(&libcfs_kmemory));
-
module_put(THIS_MODULE);
}
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h
index 8a9d4a0..a0fcbc3 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd.h
@@ -46,6 +46,7 @@
#include <linux/sysctl.h>
#include <linux/uio.h>
#include <linux/unistd.h>
+#include <asm/irq.h>
#include <net/sock.h>
#include <net/tcp.h>
@@ -519,8 +520,8 @@
atomic_inc(&conn->ksnc_conn_refcount);
}
-extern void ksocknal_queue_zombie_conn(ksock_conn_t *conn);
-extern void ksocknal_finalize_zcreq(ksock_conn_t *conn);
+void ksocknal_queue_zombie_conn(ksock_conn_t *conn);
+void ksocknal_finalize_zcreq(ksock_conn_t *conn);
static inline void
ksocknal_conn_decref(ksock_conn_t *conn)
@@ -565,8 +566,8 @@
atomic_inc(&tx->tx_refcount);
}
-extern void ksocknal_tx_prep(ksock_conn_t *, ksock_tx_t *tx);
-extern void ksocknal_tx_done(lnet_ni_t *ni, ksock_tx_t *tx);
+void ksocknal_tx_prep(ksock_conn_t *, ksock_tx_t *tx);
+void ksocknal_tx_done(lnet_ni_t *ni, ksock_tx_t *tx);
static inline void
ksocknal_tx_decref(ksock_tx_t *tx)
@@ -583,7 +584,7 @@
atomic_inc(&route->ksnr_refcount);
}
-extern void ksocknal_destroy_route(ksock_route_t *route);
+void ksocknal_destroy_route(ksock_route_t *route);
static inline void
ksocknal_route_decref(ksock_route_t *route)
@@ -600,7 +601,7 @@
atomic_inc(&peer->ksnp_refcount);
}
-extern void ksocknal_destroy_peer(ksock_peer_t *peer);
+void ksocknal_destroy_peer(ksock_peer_t *peer);
static inline void
ksocknal_peer_decref(ksock_peer_t *peer)
@@ -620,70 +621,69 @@
unsigned int offset, unsigned int mlen, unsigned int rlen);
int ksocknal_accept(lnet_ni_t *ni, struct socket *sock);
-extern int ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip, int port);
-extern ksock_peer_t *ksocknal_find_peer_locked(lnet_ni_t *ni, lnet_process_id_t id);
-extern ksock_peer_t *ksocknal_find_peer(lnet_ni_t *ni, lnet_process_id_t id);
-extern void ksocknal_peer_failed(ksock_peer_t *peer);
-extern int ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route,
- struct socket *sock, int type);
-extern void ksocknal_close_conn_locked(ksock_conn_t *conn, int why);
-extern void ksocknal_terminate_conn(ksock_conn_t *conn);
-extern void ksocknal_destroy_conn(ksock_conn_t *conn);
-extern int ksocknal_close_peer_conns_locked(ksock_peer_t *peer,
- __u32 ipaddr, int why);
-extern int ksocknal_close_conn_and_siblings(ksock_conn_t *conn, int why);
-extern int ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr);
-extern ksock_conn_t *ksocknal_find_conn_locked(ksock_peer_t *peer,
- ksock_tx_t *tx, int nonblk);
+int ksocknal_add_peer(lnet_ni_t *ni, lnet_process_id_t id, __u32 ip, int port);
+ksock_peer_t *ksocknal_find_peer_locked(lnet_ni_t *ni, lnet_process_id_t id);
+ksock_peer_t *ksocknal_find_peer(lnet_ni_t *ni, lnet_process_id_t id);
+void ksocknal_peer_failed(ksock_peer_t *peer);
+int ksocknal_create_conn(lnet_ni_t *ni, ksock_route_t *route,
+ struct socket *sock, int type);
+void ksocknal_close_conn_locked(ksock_conn_t *conn, int why);
+void ksocknal_terminate_conn(ksock_conn_t *conn);
+void ksocknal_destroy_conn(ksock_conn_t *conn);
+int ksocknal_close_peer_conns_locked(ksock_peer_t *peer,
+ __u32 ipaddr, int why);
+int ksocknal_close_conn_and_siblings(ksock_conn_t *conn, int why);
+int ksocknal_close_matching_conns(lnet_process_id_t id, __u32 ipaddr);
+ksock_conn_t *ksocknal_find_conn_locked(ksock_peer_t *peer,
+ ksock_tx_t *tx, int nonblk);
-extern int ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx,
- lnet_process_id_t id);
-extern ksock_tx_t *ksocknal_alloc_tx(int type, int size);
-extern void ksocknal_free_tx(ksock_tx_t *tx);
-extern ksock_tx_t *ksocknal_alloc_tx_noop(__u64 cookie, int nonblk);
-extern void ksocknal_next_tx_carrier(ksock_conn_t *conn);
-extern void ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn);
-extern void ksocknal_txlist_done(lnet_ni_t *ni, struct list_head *txlist,
- int error);
-extern void ksocknal_notify(lnet_ni_t *ni, lnet_nid_t gw_nid, int alive);
-extern void ksocknal_query(struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
-extern int ksocknal_thread_start(int (*fn)(void *arg), void *arg, char *name);
-extern void ksocknal_thread_fini(void);
-extern void ksocknal_launch_all_connections_locked(ksock_peer_t *peer);
-extern ksock_route_t *ksocknal_find_connectable_route_locked(ksock_peer_t *peer);
-extern ksock_route_t *ksocknal_find_connecting_route_locked(ksock_peer_t *peer);
-extern int ksocknal_new_packet(ksock_conn_t *conn, int skip);
-extern int ksocknal_scheduler(void *arg);
-extern int ksocknal_connd(void *arg);
-extern int ksocknal_reaper(void *arg);
-extern int ksocknal_send_hello(lnet_ni_t *ni, ksock_conn_t *conn,
- lnet_nid_t peer_nid, ksock_hello_msg_t *hello);
-extern int ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn,
- ksock_hello_msg_t *hello, lnet_process_id_t *id,
- __u64 *incarnation);
-extern void ksocknal_read_callback(ksock_conn_t *conn);
-extern void ksocknal_write_callback(ksock_conn_t *conn);
+int ksocknal_launch_packet(lnet_ni_t *ni, ksock_tx_t *tx,
+ lnet_process_id_t id);
+ksock_tx_t *ksocknal_alloc_tx(int type, int size);
+void ksocknal_free_tx(ksock_tx_t *tx);
+ksock_tx_t *ksocknal_alloc_tx_noop(__u64 cookie, int nonblk);
+void ksocknal_next_tx_carrier(ksock_conn_t *conn);
+void ksocknal_queue_tx_locked(ksock_tx_t *tx, ksock_conn_t *conn);
+void ksocknal_txlist_done(lnet_ni_t *ni, struct list_head *txlist, int error);
+void ksocknal_notify(lnet_ni_t *ni, lnet_nid_t gw_nid, int alive);
+void ksocknal_query(struct lnet_ni *ni, lnet_nid_t nid, unsigned long *when);
+int ksocknal_thread_start(int (*fn)(void *arg), void *arg, char *name);
+void ksocknal_thread_fini(void);
+void ksocknal_launch_all_connections_locked(ksock_peer_t *peer);
+ksock_route_t *ksocknal_find_connectable_route_locked(ksock_peer_t *peer);
+ksock_route_t *ksocknal_find_connecting_route_locked(ksock_peer_t *peer);
+int ksocknal_new_packet(ksock_conn_t *conn, int skip);
+int ksocknal_scheduler(void *arg);
+int ksocknal_connd(void *arg);
+int ksocknal_reaper(void *arg);
+int ksocknal_send_hello(lnet_ni_t *ni, ksock_conn_t *conn,
+ lnet_nid_t peer_nid, ksock_hello_msg_t *hello);
+int ksocknal_recv_hello(lnet_ni_t *ni, ksock_conn_t *conn,
+ ksock_hello_msg_t *hello, lnet_process_id_t *id,
+ __u64 *incarnation);
+void ksocknal_read_callback(ksock_conn_t *conn);
+void ksocknal_write_callback(ksock_conn_t *conn);
-extern int ksocknal_lib_zc_capable(ksock_conn_t *conn);
-extern void ksocknal_lib_save_callback(struct socket *sock, ksock_conn_t *conn);
-extern void ksocknal_lib_set_callback(struct socket *sock, ksock_conn_t *conn);
-extern void ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn);
-extern void ksocknal_lib_push_conn(ksock_conn_t *conn);
-extern int ksocknal_lib_get_conn_addrs(ksock_conn_t *conn);
-extern int ksocknal_lib_setup_sock(struct socket *so);
-extern int ksocknal_lib_send_iov(ksock_conn_t *conn, ksock_tx_t *tx);
-extern int ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx);
-extern void ksocknal_lib_eager_ack(ksock_conn_t *conn);
-extern int ksocknal_lib_recv_iov(ksock_conn_t *conn);
-extern int ksocknal_lib_recv_kiov(ksock_conn_t *conn);
-extern int ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem,
- int *rxmem, int *nagle);
+int ksocknal_lib_zc_capable(ksock_conn_t *conn);
+void ksocknal_lib_save_callback(struct socket *sock, ksock_conn_t *conn);
+void ksocknal_lib_set_callback(struct socket *sock, ksock_conn_t *conn);
+void ksocknal_lib_reset_callback(struct socket *sock, ksock_conn_t *conn);
+void ksocknal_lib_push_conn(ksock_conn_t *conn);
+int ksocknal_lib_get_conn_addrs(ksock_conn_t *conn);
+int ksocknal_lib_setup_sock(struct socket *so);
+int ksocknal_lib_send_iov(ksock_conn_t *conn, ksock_tx_t *tx);
+int ksocknal_lib_send_kiov(ksock_conn_t *conn, ksock_tx_t *tx);
+void ksocknal_lib_eager_ack(ksock_conn_t *conn);
+int ksocknal_lib_recv_iov(ksock_conn_t *conn);
+int ksocknal_lib_recv_kiov(ksock_conn_t *conn);
+int ksocknal_lib_get_conn_tunables(ksock_conn_t *conn, int *txmem,
+ int *rxmem, int *nagle);
-extern int ksocknal_tunables_init(void);
+int ksocknal_tunables_init(void);
-extern void ksocknal_lib_csum_tx(ksock_tx_t *tx);
+void ksocknal_lib_csum_tx(ksock_tx_t *tx);
-extern int ksocknal_lib_memory_pressure(ksock_conn_t *conn);
-extern int ksocknal_lib_bind_thread_to_cpu(int id);
+int ksocknal_lib_memory_pressure(ksock_conn_t *conn);
+int ksocknal_lib_bind_thread_to_cpu(int id);
#endif /* _SOCKLND_SOCKLND_H_ */
diff --git a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
index fe2a83a..0d5aac6 100644
--- a/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
+++ b/drivers/staging/lustre/lnet/klnds/socklnd/socklnd_cb.c
@@ -526,8 +526,7 @@
counter++; /* exponential backoff warnings */
if ((counter & (-counter)) == counter)
- CWARN("%u ENOMEM tx %p (%u allocated)\n",
- counter, conn, atomic_read(&libcfs_kmemory));
+ CWARN("%u ENOMEM tx %p\n", counter, conn);
/* Queue on ksnd_enomem_conns for retry after a timeout */
spin_lock_bh(&ksocknal_data.ksnd_reaper_lock);
diff --git a/drivers/staging/lustre/lnet/lnet/router_proc.c b/drivers/staging/lustre/lnet/lnet/router_proc.c
index ee902dc..40f418b 100644
--- a/drivers/staging/lustre/lnet/lnet/router_proc.c
+++ b/drivers/staging/lustre/lnet/lnet/router_proc.c
@@ -32,17 +32,6 @@
static struct ctl_table_header *lnet_table_header;
-#define CTL_LNET (0x100)
-enum {
- PSDEV_LNET_STATS = 100,
- PSDEV_LNET_ROUTES,
- PSDEV_LNET_ROUTERS,
- PSDEV_LNET_PEERS,
- PSDEV_LNET_BUFFERS,
- PSDEV_LNET_NIS,
- PSDEV_LNET_PTL_ROTOR,
-};
-
#define LNET_LOFFT_BITS (sizeof(loff_t) * 8)
/*
* NB: max allowed LNET_CPT_BITS is 8 on 64-bit system and 2 on 32-bit system
diff --git a/drivers/staging/lustre/lnet/selftest/console.h b/drivers/staging/lustre/lnet/selftest/console.h
index c4cf0ae..cdce2dd 100644
--- a/drivers/staging/lustre/lnet/selftest/console.h
+++ b/drivers/staging/lustre/lnet/selftest/console.h
@@ -187,51 +187,49 @@
int lstcon_console_init(void);
int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_data *data);
int lstcon_console_fini(void);
-extern int lstcon_session_match(lst_sid_t sid);
-extern int lstcon_session_new(char *name, int key, unsigned version,
- int timeout, int flags, lst_sid_t *sid_up);
-extern int lstcon_session_info(lst_sid_t *sid_up, int *key, unsigned *verp,
- lstcon_ndlist_ent_t *entp, char *name_up, int len);
-extern int lstcon_session_end(void);
-extern int lstcon_session_debug(int timeout, struct list_head *result_up);
-extern int lstcon_session_feats_check(unsigned feats);
-extern int lstcon_batch_debug(int timeout, char *name,
- int client, struct list_head *result_up);
-extern int lstcon_group_debug(int timeout, char *name,
- struct list_head *result_up);
-extern int lstcon_nodes_debug(int timeout, int nnd, lnet_process_id_t *nds_up,
- struct list_head *result_up);
-extern int lstcon_group_add(char *name);
-extern int lstcon_group_del(char *name);
-extern int lstcon_group_clean(char *name, int args);
-extern int lstcon_group_refresh(char *name, struct list_head *result_up);
-extern int lstcon_nodes_add(char *name, int nnd, lnet_process_id_t *nds_up,
- unsigned *featp, struct list_head *result_up);
-extern int lstcon_nodes_remove(char *name, int nnd, lnet_process_id_t *nds_up,
- struct list_head *result_up);
-extern int lstcon_group_info(char *name, lstcon_ndlist_ent_t *gent_up,
- int *index_p, int *ndent_p, lstcon_node_ent_t *ndents_up);
-extern int lstcon_group_list(int idx, int len, char *name_up);
-extern int lstcon_batch_add(char *name);
-extern int lstcon_batch_run(char *name, int timeout,
+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 lstcon_session_end(void);
+int lstcon_session_debug(int timeout, struct list_head *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 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);
+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_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_test_batch_query(char *name, int testidx,
+ int client, int timeout,
struct list_head *result_up);
-extern int lstcon_batch_stop(char *name, int force,
- struct list_head *result_up);
-extern int lstcon_test_batch_query(char *name, int testidx,
- int client, int timeout,
- struct list_head *result_up);
-extern int lstcon_batch_del(char *name);
-extern int lstcon_batch_list(int idx, int namelen, char *name_up);
-extern 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);
-extern int lstcon_group_stat(char *grp_name, int timeout,
- struct list_head *result_up);
-extern int lstcon_nodes_stat(int count, lnet_process_id_t *ids_up,
- int timeout, struct list_head *result_up);
-extern 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);
+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 server, int testidx, int *index_p,
+ int *ndent_p, lstcon_node_ent_t *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);
+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);
#endif
diff --git a/drivers/staging/lustre/lnet/selftest/framework.c b/drivers/staging/lustre/lnet/selftest/framework.c
index 7c5185a..257de35 100644
--- a/drivers/staging/lustre/lnet/selftest/framework.c
+++ b/drivers/staging/lustre/lnet/selftest/framework.c
@@ -203,7 +203,8 @@
sfw_batch_t *tsb;
sfw_test_case_t *tsc;
- if (sn == NULL) return;
+ if (sn == NULL)
+ return;
LASSERT(!sn->sn_timer_active);
@@ -613,7 +614,8 @@
srpc_client_rpc_t *rpc;
sfw_test_unit_t *tsu;
- if (!tsi->tsi_is_client) goto clean;
+ if (!tsi->tsi_is_client)
+ goto clean;
tsi->tsi_ops->tso_fini(tsi);
@@ -1700,7 +1702,8 @@
for (i = 0; ; i++) {
sv = &sfw_services[i];
- if (sv->sv_name == NULL) break;
+ if (sv->sv_name == NULL)
+ break;
sv->sv_bulk_ready = NULL;
sv->sv_handler = sfw_handle_server_rpc;
@@ -1717,7 +1720,8 @@
}
/* about to sfw_shutdown, no need to add buffer */
- if (error) continue;
+ if (error)
+ continue;
rc = srpc_service_add_buffers(sv, sv->sv_wi_total);
if (rc != 0) {
diff --git a/drivers/staging/lustre/lustre/fid/fid_request.c b/drivers/staging/lustre/lustre/fid/fid_request.c
index 1362783..a16d577 100644
--- a/drivers/staging/lustre/lustre/fid/fid_request.c
+++ b/drivers/staging/lustre/lustre/fid/fid_request.c
@@ -498,11 +498,11 @@
int rc;
cli->cl_seq = kzalloc(sizeof(*cli->cl_seq), GFP_NOFS);
- if (cli->cl_seq == NULL)
+ if (!cli->cl_seq)
return -ENOMEM;
prefix = kzalloc(MAX_OBD_NAME + 5, GFP_NOFS);
- if (prefix == NULL) {
+ if (!prefix) {
rc = -ENOMEM;
goto out_free_seq;
}
diff --git a/drivers/staging/lustre/lustre/fld/fld_cache.c b/drivers/staging/lustre/lustre/fld/fld_cache.c
index ec2fc43..1b1066b 100644
--- a/drivers/staging/lustre/lustre/fld/fld_cache.c
+++ b/drivers/staging/lustre/lustre/fld/fld_cache.c
@@ -70,7 +70,7 @@
LASSERT(cache_threshold < cache_size);
cache = kzalloc(sizeof(*cache), GFP_NOFS);
- if (cache == NULL)
+ if (!cache)
return ERR_PTR(-ENOMEM);
INIT_LIST_HEAD(&cache->fci_entries_head);
diff --git a/drivers/staging/lustre/lustre/fld/fld_request.c b/drivers/staging/lustre/lustre/fld/fld_request.c
index c3b47f2..1e450bf 100644
--- a/drivers/staging/lustre/lustre/fld/fld_request.c
+++ b/drivers/staging/lustre/lustre/fld/fld_request.c
@@ -222,7 +222,7 @@
fld->lcf_name, name, tar->ft_idx);
target = kzalloc(sizeof(*target), GFP_NOFS);
- if (target == NULL)
+ if (!target)
return -ENOMEM;
spin_lock(&fld->lcf_lock);
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
index 513c81f..6b14406 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_compat25.h
@@ -64,98 +64,6 @@
#define LTIME_S(time) (time.tv_sec)
-/* inode_dio_wait(i) use as-is for write lock */
-# define inode_dio_write_done(i) do {} while (0) /* for write unlock */
-# define inode_dio_read(i) atomic_inc(&(i)->i_dio_count)
-/* inode_dio_done(i) use as-is for read unlock */
-
-
-#ifndef FS_HAS_FIEMAP
-#define FS_HAS_FIEMAP (0)
-#endif
-
-#define ll_vfs_rmdir(dir, entry, mnt) vfs_rmdir(dir, entry)
-#define ll_vfs_mkdir(inode, dir, mnt, mode) vfs_mkdir(inode, dir, mode)
-#define ll_vfs_link(old, mnt, dir, new, mnt1) vfs_link(old, dir, new)
-#define ll_vfs_unlink(inode, entry, mnt) vfs_unlink(inode, entry)
-#define ll_vfs_mknod(dir, entry, mnt, mode, dev) \
- vfs_mknod(dir, entry, mode, dev)
-#define ll_security_inode_unlink(dir, entry, mnt) \
- security_inode_unlink(dir, entry)
-#define ll_vfs_rename(old, old_dir, mnt, new, new_dir, mnt1) \
- vfs_rename(old, old_dir, new, new_dir, NULL, 0)
-
-#define cfs_bio_io_error(a, b) bio_io_error((a))
-#define cfs_bio_endio(a, b, c) bio_endio((a), (c))
-
-#define cfs_path_put(nd) path_put(&(nd)->path)
-
-
-#ifndef SLAB_DESTROY_BY_RCU
-#define SLAB_DESTROY_BY_RCU 0
-#endif
-
-
-
-static inline int
-ll_quota_on(struct super_block *sb, int off, int ver, char *name, int remount)
-{
- int rc;
-
- if (sb->s_qcop->quota_on) {
- struct path path;
-
- rc = kern_path(name, LOOKUP_FOLLOW, &path);
- if (!rc)
- return rc;
- rc = sb->s_qcop->quota_on(sb, off, ver
- , &path
- );
- path_put(&path);
- return rc;
- } else
- return -ENOSYS;
-}
-
-static inline int ll_quota_off(struct super_block *sb, int off, int remount)
-{
- if (sb->s_qcop->quota_off) {
- return sb->s_qcop->quota_off(sb, off
- );
- } else
- return -ENOSYS;
-}
-
-
-# define ll_vfs_dq_init dquot_initialize
-# define ll_vfs_dq_drop dquot_drop
-# define ll_vfs_dq_transfer dquot_transfer
-# define ll_vfs_dq_off(sb, remount) dquot_suspend(sb, -1)
-
-
-
-
-
-#define queue_max_phys_segments(rq) queue_max_segments(rq)
-#define queue_max_hw_segments(rq) queue_max_segments(rq)
-
-
-#define ll_d_hlist_node hlist_node
-#define ll_d_hlist_empty(list) hlist_empty(list)
-#define ll_d_hlist_entry(ptr, type, name) hlist_entry(ptr.first, type, name)
-#define ll_d_hlist_for_each(tmp, i_dentry) hlist_for_each(tmp, i_dentry)
-#define ll_d_hlist_for_each_entry(dentry, p, i_dentry, alias) \
- p = NULL; hlist_for_each_entry(dentry, i_dentry, alias)
-
-
-#define bio_hw_segments(q, bio) 0
-
-
-#define ll_pagevec_init(pv, cold) do {} while (0)
-#define ll_pagevec_add(pv, pg) (0)
-#define ll_pagevec_lru_add_file(pv) do {} while (0)
-
-
#ifndef QUOTA_OK
# define QUOTA_OK 0
#endif
@@ -163,17 +71,6 @@
# define NO_QUOTA (-EDQUOT)
#endif
-#ifndef SEEK_DATA
-#define SEEK_DATA 3 /* seek to the next data */
-#endif
-#ifndef SEEK_HOLE
-#define SEEK_HOLE 4 /* seek to the next hole */
-#endif
-
-#ifndef FMODE_UNSIGNED_OFFSET
-#define FMODE_UNSIGNED_OFFSET ((__force fmode_t)0x2000)
-#endif
-
#if !defined(_ASM_GENERIC_BITOPS_EXT2_NON_ATOMIC_H_) && !defined(ext2_set_bit)
# define ext2_set_bit __test_and_set_bit_le
# define ext2_clear_bit __test_and_clear_bit_le
@@ -182,20 +79,4 @@
# define ext2_find_next_zero_bit find_next_zero_bit_le
#endif
-#ifdef ATTR_TIMES_SET
-# define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
-#else
-# define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET)
-#endif
-
-
-#include <linux/version.h>
-#include <linux/fs.h>
-
-# define ll_umode_t umode_t
-
-#include <linux/dcache.h>
-
-# define ll_dirty_inode(inode, flag) (inode)->i_sb->s_op->dirty_inode((inode), flag)
-
#endif /* _COMPAT25_H */
diff --git a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h b/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h
index 1456278..ebe8d68 100644
--- a/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h
+++ b/drivers/staging/lustre/lustre/include/linux/lustre_patchless_compat.h
@@ -60,18 +60,6 @@
ll_delete_from_page_cache(page);
}
-#ifdef ATTR_OPEN
-# define ATTR_FROM_OPEN ATTR_OPEN
-#else
-# ifndef ATTR_FROM_OPEN
-# define ATTR_FROM_OPEN 0
-# endif
-#endif /* ATTR_OPEN */
-
-#ifndef ATTR_RAW
-#define ATTR_RAW 0
-#endif
-
#ifndef ATTR_CTIME_SET
/*
* set ATTR_CTIME_SET to a high value to avoid any risk of collision with other
diff --git a/drivers/staging/lustre/lustre/include/lprocfs_status.h b/drivers/staging/lustre/lustre/include/lprocfs_status.h
index 8ede2a0..fd3c4df 100644
--- a/drivers/staging/lustre/lustre/include/lprocfs_status.h
+++ b/drivers/staging/lustre/lustre/include/lprocfs_status.h
@@ -375,12 +375,11 @@
#define JOBSTATS_PROCNAME_UID "procname_uid"
#define JOBSTATS_NODELOCAL "nodelocal"
-extern int lprocfs_write_frac_helper(const char __user *buffer,
- unsigned long count, int *val, int mult);
-extern int lprocfs_read_frac_helper(char *buffer, unsigned long count,
- long val, int mult);
-extern int lprocfs_stats_alloc_one(struct lprocfs_stats *stats,
- unsigned int cpuid);
+int lprocfs_write_frac_helper(const char __user *buffer,
+ unsigned long count, int *val, int mult);
+int lprocfs_read_frac_helper(char *buffer, unsigned long count,
+ long val, int mult);
+int lprocfs_stats_alloc_one(struct lprocfs_stats *stats, unsigned int cpuid);
/*
* \return value
* < 0 : on error (only possible for opc as LPROCFS_GET_SMP_ID)
@@ -497,20 +496,18 @@
* count itself to reside within a single cache line.
*/
-extern void lprocfs_counter_add(struct lprocfs_stats *stats, int idx,
- long amount);
-extern void lprocfs_counter_sub(struct lprocfs_stats *stats, int idx,
- long amount);
+void lprocfs_counter_add(struct lprocfs_stats *stats, int idx, long amount);
+void lprocfs_counter_sub(struct lprocfs_stats *stats, int idx, long amount);
#define lprocfs_counter_incr(stats, idx) \
lprocfs_counter_add(stats, idx, 1)
#define lprocfs_counter_decr(stats, idx) \
lprocfs_counter_sub(stats, idx, 1)
-extern __s64 lprocfs_read_helper(struct lprocfs_counter *lc,
- struct lprocfs_counter_header *header,
- enum lprocfs_stats_flags flags,
- enum lprocfs_fields_flags field);
+__s64 lprocfs_read_helper(struct lprocfs_counter *lc,
+ struct lprocfs_counter_header *header,
+ enum lprocfs_stats_flags flags,
+ enum lprocfs_fields_flags field);
static inline __u64 lprocfs_stats_collector(struct lprocfs_stats *stats,
int idx,
enum lprocfs_fields_flags field)
@@ -537,107 +534,103 @@
extern struct lprocfs_stats *
lprocfs_alloc_stats(unsigned int num, enum lprocfs_stats_flags flags);
-extern void lprocfs_clear_stats(struct lprocfs_stats *stats);
-extern void lprocfs_free_stats(struct lprocfs_stats **stats);
-extern void lprocfs_init_ops_stats(int num_private_stats,
- struct lprocfs_stats *stats);
-extern void lprocfs_init_mps_stats(int num_private_stats,
- struct lprocfs_stats *stats);
-extern void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats);
-extern int lprocfs_alloc_obd_stats(struct obd_device *obddev,
- unsigned int num_private_stats);
-extern int lprocfs_alloc_md_stats(struct obd_device *obddev,
- unsigned int num_private_stats);
-extern void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
- unsigned conf, const char *name,
- const char *units);
-extern void lprocfs_free_obd_stats(struct obd_device *obddev);
-extern void lprocfs_free_md_stats(struct obd_device *obddev);
+void lprocfs_clear_stats(struct lprocfs_stats *stats);
+void lprocfs_free_stats(struct lprocfs_stats **stats);
+void lprocfs_init_ops_stats(int num_private_stats, struct lprocfs_stats *stats);
+void lprocfs_init_mps_stats(int num_private_stats, struct lprocfs_stats *stats);
+void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats);
+int lprocfs_alloc_obd_stats(struct obd_device *obddev,
+ unsigned int num_private_stats);
+int lprocfs_alloc_md_stats(struct obd_device *obddev,
+ unsigned int num_private_stats);
+void lprocfs_counter_init(struct lprocfs_stats *stats, int index,
+ unsigned conf, const char *name, const char *units);
+void lprocfs_free_obd_stats(struct obd_device *obddev);
+void lprocfs_free_md_stats(struct obd_device *obddev);
struct obd_export;
-extern int lprocfs_exp_cleanup(struct obd_export *exp);
-extern struct dentry *ldebugfs_add_simple(struct dentry *root,
- char *name,
- void *data,
- struct file_operations *fops);
-extern struct dentry *
+int lprocfs_exp_cleanup(struct obd_export *exp);
+struct dentry *ldebugfs_add_simple(struct dentry *root,
+ char *name,
+ void *data,
+ struct file_operations *fops);
+struct dentry *
ldebugfs_add_symlink(const char *name, struct dentry *parent,
- const char *format, ...);
+ const char *format, ...);
-extern int ldebugfs_register_stats(struct dentry *parent,
- const char *name,
- struct lprocfs_stats *stats);
+int ldebugfs_register_stats(struct dentry *parent,
+ const char *name,
+ struct lprocfs_stats *stats);
/* lprocfs_status.c */
-extern int ldebugfs_add_vars(struct dentry *parent,
- struct lprocfs_vars *var,
- void *data);
+int ldebugfs_add_vars(struct dentry *parent,
+ struct lprocfs_vars *var,
+ void *data);
-extern struct dentry *ldebugfs_register(const char *name,
- struct dentry *parent,
- struct lprocfs_vars *list,
- void *data);
+struct dentry *ldebugfs_register(const char *name,
+ struct dentry *parent,
+ struct lprocfs_vars *list,
+ void *data);
-extern void ldebugfs_remove(struct dentry **entryp);
+void ldebugfs_remove(struct dentry **entryp);
-extern int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list,
- struct attribute_group *attrs);
-extern int lprocfs_obd_cleanup(struct obd_device *obd);
+int lprocfs_obd_setup(struct obd_device *obd, struct lprocfs_vars *list,
+ struct attribute_group *attrs);
+int lprocfs_obd_cleanup(struct obd_device *obd);
-extern int ldebugfs_seq_create(struct dentry *parent,
- const char *name,
- umode_t mode,
- const struct file_operations *seq_fops,
- void *data);
-extern int ldebugfs_obd_seq_create(struct obd_device *dev,
- const char *name,
- umode_t mode,
- const struct file_operations *seq_fops,
- void *data);
+int ldebugfs_seq_create(struct dentry *parent,
+ const char *name,
+ umode_t mode,
+ const struct file_operations *seq_fops,
+ void *data);
+int ldebugfs_obd_seq_create(struct obd_device *dev,
+ const char *name,
+ umode_t mode,
+ const struct file_operations *seq_fops,
+ void *data);
/* Generic callbacks */
-extern int lprocfs_rd_u64(struct seq_file *m, void *data);
-extern int lprocfs_rd_atomic(struct seq_file *m, void *data);
-extern int lprocfs_wr_atomic(struct file *file, const char __user *buffer,
- unsigned long count, void *data);
-extern int lprocfs_rd_uint(struct seq_file *m, void *data);
-extern int lprocfs_wr_uint(struct file *file, const char __user *buffer,
- unsigned long count, void *data);
-extern int lprocfs_rd_name(struct seq_file *m, void *data);
-extern int lprocfs_rd_server_uuid(struct seq_file *m, void *data);
-extern int lprocfs_rd_conn_uuid(struct seq_file *m, void *data);
-extern int lprocfs_rd_import(struct seq_file *m, void *data);
-extern int lprocfs_rd_state(struct seq_file *m, void *data);
-extern int lprocfs_rd_connect_flags(struct seq_file *m, void *data);
+int lprocfs_rd_u64(struct seq_file *m, void *data);
+int lprocfs_rd_atomic(struct seq_file *m, void *data);
+int lprocfs_wr_atomic(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+int lprocfs_rd_uint(struct seq_file *m, void *data);
+int lprocfs_wr_uint(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+int lprocfs_rd_name(struct seq_file *m, void *data);
+int lprocfs_rd_server_uuid(struct seq_file *m, void *data);
+int lprocfs_rd_conn_uuid(struct seq_file *m, void *data);
+int lprocfs_rd_import(struct seq_file *m, void *data);
+int lprocfs_rd_state(struct seq_file *m, void *data);
+int lprocfs_rd_connect_flags(struct seq_file *m, void *data);
struct adaptive_timeout;
-extern int lprocfs_at_hist_helper(struct seq_file *m,
- struct adaptive_timeout *at);
-extern int lprocfs_rd_timeouts(struct seq_file *m, void *data);
-extern int lprocfs_wr_timeouts(struct file *file, const char __user *buffer,
- unsigned long count, void *data);
-extern int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
+int lprocfs_at_hist_helper(struct seq_file *m, struct adaptive_timeout *at);
+int lprocfs_rd_timeouts(struct seq_file *m, void *data);
+int lprocfs_wr_timeouts(struct file *file, const char __user *buffer,
+ unsigned long count, void *data);
+int lprocfs_wr_evict_client(struct file *file, const char __user *buffer,
size_t count, loff_t *off);
-extern int lprocfs_wr_ping(struct file *file, const char __user *buffer,
- size_t count, loff_t *off);
-extern int lprocfs_wr_import(struct file *file, const char __user *buffer,
+int lprocfs_wr_ping(struct file *file, const char __user *buffer,
+ size_t count, loff_t *off);
+int lprocfs_wr_import(struct file *file, const char __user *buffer,
size_t count, loff_t *off);
-extern int lprocfs_rd_pinger_recov(struct seq_file *m, void *n);
-extern int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer,
- size_t count, loff_t *off);
+int lprocfs_rd_pinger_recov(struct seq_file *m, void *n);
+int lprocfs_wr_pinger_recov(struct file *file, const char __user *buffer,
+ size_t count, loff_t *off);
/* Statfs helpers */
-extern int lprocfs_write_helper(const char __user *buffer, unsigned long count,
- int *val);
-extern int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult);
-extern int lprocfs_write_u64_helper(const char __user *buffer,
- unsigned long count, __u64 *val);
-extern int lprocfs_write_frac_u64_helper(const char *buffer,
- unsigned long count,
- __u64 *val, int mult);
-extern char *lprocfs_find_named_value(const char *buffer, const char *name,
- size_t *count);
+int lprocfs_write_helper(const char __user *buffer, unsigned long count,
+ int *val);
+int lprocfs_seq_read_frac_helper(struct seq_file *m, long val, int mult);
+int lprocfs_write_u64_helper(const char __user *buffer,
+ unsigned long count, __u64 *val);
+int lprocfs_write_frac_u64_helper(const char *buffer,
+ unsigned long count,
+ __u64 *val, int mult);
+char *lprocfs_find_named_value(const char *buffer, const char *name,
+ size_t *count);
void lprocfs_oh_tally(struct obd_histogram *oh, unsigned int value);
void lprocfs_oh_tally_log2(struct obd_histogram *oh, unsigned int value);
void lprocfs_oh_clear(struct obd_histogram *oh);
@@ -646,8 +639,8 @@
void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx,
struct lprocfs_counter *cnt);
-extern int lprocfs_single_release(struct inode *, struct file *);
-extern int lprocfs_seq_release(struct inode *, struct file *);
+int lprocfs_single_release(struct inode *, struct file *);
+int lprocfs_seq_release(struct inode *, struct file *);
/* You must use these macros when you want to refer to
* the import in a client obd_device for a lprocfs entry */
@@ -746,7 +739,7 @@
/* lproc_ptlrpc.c */
struct ptlrpc_request;
-extern void target_print_req(void *seq_file, struct ptlrpc_request *req);
+void target_print_req(void *seq_file, struct ptlrpc_request *req);
/* lproc_status.c */
int lprocfs_obd_rd_max_pages_per_rpc(struct seq_file *m, void *data);
@@ -754,62 +747,62 @@
size_t count, loff_t *off);
/* all quota proc functions */
-extern int lprocfs_quota_rd_bunit(char *page, char **start,
- loff_t off, int count,
- int *eof, void *data);
-extern int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_btune(char *page, char **start,
- loff_t off, int count,
- int *eof, void *data);
-extern int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_iunit(char *page, char **start,
- loff_t off, int count,
- int *eof, void *data);
-extern int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_itune(char *page, char **start,
- loff_t off, int count,
- int *eof, void *data);
-extern int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_type(char *page, char **start, loff_t off, int count,
- int *eof, void *data);
-extern int lprocfs_quota_wr_type(struct file *file, const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_switch_seconds(char *page, char **start, loff_t off,
- int count, int *eof, void *data);
-extern int lprocfs_quota_wr_switch_seconds(struct file *file,
- const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_sync_blk(char *page, char **start, loff_t off,
+int lprocfs_quota_rd_bunit(char *page, char **start,
+ loff_t off, int count,
+ int *eof, void *data);
+int lprocfs_quota_wr_bunit(struct file *file, const char *buffer,
+ unsigned long count, void *data);
+int lprocfs_quota_rd_btune(char *page, char **start,
+ loff_t off, int count,
+ int *eof, void *data);
+int lprocfs_quota_wr_btune(struct file *file, const char *buffer,
+ unsigned long count, void *data);
+int lprocfs_quota_rd_iunit(char *page, char **start,
+ loff_t off, int count,
+ int *eof, void *data);
+int lprocfs_quota_wr_iunit(struct file *file, const char *buffer,
+ unsigned long count, void *data);
+int lprocfs_quota_rd_itune(char *page, char **start,
+ loff_t off, int count,
+ int *eof, void *data);
+int lprocfs_quota_wr_itune(struct file *file, const char *buffer,
+ unsigned long count, void *data);
+int lprocfs_quota_rd_type(char *page, char **start, loff_t off, int count,
+ int *eof, void *data);
+int lprocfs_quota_wr_type(struct file *file, const char *buffer,
+ unsigned long count, void *data);
+int lprocfs_quota_rd_switch_seconds(char *page, char **start, loff_t off,
+ int count, int *eof, void *data);
+int lprocfs_quota_wr_switch_seconds(struct file *file,
+ const char *buffer,
+ unsigned long count, void *data);
+int lprocfs_quota_rd_sync_blk(char *page, char **start, loff_t off,
+ int count, int *eof, void *data);
+int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
+ unsigned long count, void *data);
+int lprocfs_quota_rd_switch_qs(char *page, char **start, loff_t off,
+ int count, int *eof, void *data);
+int lprocfs_quota_wr_switch_qs(struct file *file,
+ const char *buffer, unsigned long count,
+ void *data);
+int lprocfs_quota_rd_boundary_factor(char *page, char **start, loff_t off,
int count, int *eof, void *data);
-extern int lprocfs_quota_wr_sync_blk(struct file *file, const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_switch_qs(char *page, char **start, loff_t off,
- int count, int *eof, void *data);
-extern int lprocfs_quota_wr_switch_qs(struct file *file,
- const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_boundary_factor(char *page, char **start, loff_t off,
- int count, int *eof, void *data);
-extern int lprocfs_quota_wr_boundary_factor(struct file *file,
- const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_least_bunit(char *page, char **start, loff_t off,
- int count, int *eof, void *data);
-extern int lprocfs_quota_wr_least_bunit(struct file *file,
- const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_least_iunit(char *page, char **start, loff_t off,
- int count, int *eof, void *data);
-extern int lprocfs_quota_wr_least_iunit(struct file *file,
- const char *buffer,
- unsigned long count, void *data);
-extern int lprocfs_quota_rd_qs_factor(char *page, char **start, loff_t off,
- int count, int *eof, void *data);
-extern int lprocfs_quota_wr_qs_factor(struct file *file,
- const char *buffer,
- unsigned long count, void *data);
+int lprocfs_quota_wr_boundary_factor(struct file *file,
+ const char *buffer, unsigned long count,
+ void *data);
+int lprocfs_quota_rd_least_bunit(char *page, char **start, loff_t off,
+ int count, int *eof, void *data);
+int lprocfs_quota_wr_least_bunit(struct file *file,
+ const char *buffer, unsigned long count,
+ void *data);
+int lprocfs_quota_rd_least_iunit(char *page, char **start, loff_t off,
+ int count, int *eof, void *data);
+int lprocfs_quota_wr_least_iunit(struct file *file,
+ const char *buffer, unsigned long count,
+ void *data);
+int lprocfs_quota_rd_qs_factor(char *page, char **start, loff_t off,
+ int count, int *eof, void *data);
+int lprocfs_quota_wr_qs_factor(struct file *file,
+ const char *buffer, unsigned long count,
+ void *data);
#endif /* LPROCFS_SNMP_H */
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
index 4d72d6e..ac78dbc 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_idl.h
@@ -747,7 +747,7 @@
return fid_seq(fid);
}
-extern void lustre_swab_ost_id(struct ost_id *oid);
+void lustre_swab_ost_id(struct ost_id *oid);
/**
* Get inode generation from a igif.
@@ -814,8 +814,8 @@
return fid_seq(fid) == 0 && fid_oid(fid) == 0;
}
-extern void lustre_swab_lu_fid(struct lu_fid *fid);
-extern void lustre_swab_lu_seq_range(struct lu_seq_range *range);
+void lustre_swab_lu_fid(struct lu_fid *fid);
+void lustre_swab_lu_seq_range(struct lu_seq_range *range);
static inline int lu_fid_eq(const struct lu_fid *f0, const struct lu_fid *f1)
{
@@ -1131,7 +1131,7 @@
__u64 pb_padding[4];
};
-extern void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
+void lustre_swab_ptlrpc_body(struct ptlrpc_body *pb);
/* message body offset for lustre_msg_v2 */
/* ptlrpc body offset in all request/reply messages */
@@ -1395,7 +1395,7 @@
* reserve the flag for future use. */
-extern void lustre_swab_connect(struct obd_connect_data *ocd);
+void lustre_swab_connect(struct obd_connect_data *ocd);
/*
* Supported checksum algorithms. Up to 32 checksum types are supported.
@@ -1737,10 +1737,10 @@
__u64 hss_clearmask;
};
-extern void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
-extern void lustre_swab_hsm_state_set(struct hsm_state_set *hss);
+void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
+void lustre_swab_hsm_state_set(struct hsm_state_set *hss);
-extern void lustre_swab_obd_statfs (struct obd_statfs *os);
+void lustre_swab_obd_statfs(struct obd_statfs *os);
/* ost_body.data values for OST_BRW */
@@ -1780,7 +1780,7 @@
#define ioobj_max_brw_set(ioo, num) \
do { (ioo)->ioo_max_brw = ((num) - 1) << IOOBJ_MAX_BRW_BITS; } while (0)
-extern void lustre_swab_obd_ioobj (struct obd_ioobj *ioo);
+void lustre_swab_obd_ioobj(struct obd_ioobj *ioo);
/* multiple of 8 bytes => can array */
struct niobuf_remote {
@@ -1789,7 +1789,7 @@
__u32 flags;
};
-extern void lustre_swab_niobuf_remote (struct niobuf_remote *nbr);
+void lustre_swab_niobuf_remote(struct niobuf_remote *nbr);
/* lock value block communicated between the filter and llite */
@@ -1811,7 +1811,7 @@
__u64 lvb_blocks;
};
-extern void lustre_swab_ost_lvb_v1(struct ost_lvb_v1 *lvb);
+void lustre_swab_ost_lvb_v1(struct ost_lvb_v1 *lvb);
struct ost_lvb {
__u64 lvb_size;
@@ -1825,7 +1825,7 @@
__u32 lvb_padding;
};
-extern void lustre_swab_ost_lvb(struct ost_lvb *lvb);
+void lustre_swab_ost_lvb(struct ost_lvb *lvb);
/*
* lquota data structures
@@ -1864,7 +1864,7 @@
struct obd_dqblk qc_dqblk;
};
-extern void lustre_swab_obd_quotactl(struct obd_quotactl *q);
+void lustre_swab_obd_quotactl(struct obd_quotactl *q);
#define Q_QUOTACHECK 0x800100 /* deprecated as of 2.4 */
#define Q_INITQUOTA 0x800101 /* deprecated as of 2.4 */
@@ -1913,7 +1913,7 @@
#define QUOTA_DQACQ_FL_REL 0x4 /* release quota */
#define QUOTA_DQACQ_FL_REPORT 0x8 /* report usage */
-extern void lustre_swab_quota_body(struct quota_body *b);
+void lustre_swab_quota_body(struct quota_body *b);
/* Quota types currently supported */
enum {
@@ -1993,7 +1993,7 @@
__u64 lvb_pad1;
};
-extern void lustre_swab_lquota_lvb(struct lquota_lvb *lvb);
+void lustre_swab_lquota_lvb(struct lquota_lvb *lvb);
/* LVB used with global quota lock */
#define lvb_glb_ver lvb_id_may_rel /* current version of the global index */
@@ -2072,7 +2072,7 @@
REINT_MAX
} mds_reint_t, mdt_reint_t;
-extern void lustre_swab_generic_32s (__u32 *val);
+void lustre_swab_generic_32s(__u32 *val);
/* the disposition of the intent outlines what was executed */
#define DISP_IT_EXECD 0x00000001
@@ -2112,7 +2112,7 @@
/* This FULL lock is useful to take on unlink sort of operations */
#define MDS_INODELOCK_FULL ((1<<(MDS_INODELOCK_MAXSHIFT+1))-1)
-extern void lustre_swab_ll_fid (struct ll_fid *fid);
+void lustre_swab_ll_fid(struct ll_fid *fid);
/* NOTE: until Lustre 1.8.7/2.1.1 the fid_ver() was packed into name[2],
* but was moved into name[1] along with the OID to avoid consuming the
@@ -2231,7 +2231,7 @@
__u64 padding_10;
}; /* 216 */
-extern void lustre_swab_mdt_body (struct mdt_body *b);
+void lustre_swab_mdt_body(struct mdt_body *b);
struct mdt_ioepoch {
struct lustre_handle handle;
@@ -2240,7 +2240,7 @@
__u32 padding;
};
-extern void lustre_swab_mdt_ioepoch (struct mdt_ioepoch *b);
+void lustre_swab_mdt_ioepoch(struct mdt_ioepoch *b);
/* permissions for md_perm.mp_perm */
enum {
@@ -2264,7 +2264,7 @@
__u32 rp_padding;
};
-extern void lustre_swab_mdt_remote_perm(struct mdt_remote_perm *p);
+void lustre_swab_mdt_remote_perm(struct mdt_remote_perm *p);
struct mdt_rec_setattr {
__u32 sa_opcode;
@@ -2294,7 +2294,7 @@
__u32 sa_padding_5;
};
-extern void lustre_swab_mdt_rec_setattr (struct mdt_rec_setattr *sa);
+void lustre_swab_mdt_rec_setattr(struct mdt_rec_setattr *sa);
/*
* Attribute flags used in mdt_rec_setattr::sa_valid.
@@ -2584,7 +2584,7 @@
__u32 rr_padding_4; /* also fix lustre_swab_mdt_rec_reint */
};
-extern void lustre_swab_mdt_rec_reint(struct mdt_rec_reint *rr);
+void lustre_swab_mdt_rec_reint(struct mdt_rec_reint *rr);
struct lmv_desc {
__u32 ld_tgt_count; /* how many MDS's */
@@ -2600,7 +2600,7 @@
struct obd_uuid ld_uuid;
};
-extern void lustre_swab_lmv_desc (struct lmv_desc *ld);
+void lustre_swab_lmv_desc(struct lmv_desc *ld);
/* TODO: lmv_stripe_md should contain mds capabilities for all slave fids */
struct lmv_stripe_md {
@@ -2612,7 +2612,7 @@
struct lu_fid mea_ids[0];
};
-extern void lustre_swab_lmv_stripe_md(struct lmv_stripe_md *mea);
+void lustre_swab_lmv_stripe_md(struct lmv_stripe_md *mea);
/* lmv structures */
#define MEA_MAGIC_LAST_CHAR 0xb2221ca1
@@ -2670,7 +2670,7 @@
#define ld_magic ld_active_tgt_count /* for swabbing from llogs */
-extern void lustre_swab_lov_desc (struct lov_desc *ld);
+void lustre_swab_lov_desc(struct lov_desc *ld);
/*
* LDLM requests:
@@ -2697,7 +2697,7 @@
#define PLDLMRES(res) (res)->lr_name.name[0], (res)->lr_name.name[1], \
(res)->lr_name.name[2], (res)->lr_name.name[3]
-extern void lustre_swab_ldlm_res_id (struct ldlm_res_id *id);
+void lustre_swab_ldlm_res_id(struct ldlm_res_id *id);
static inline int ldlm_res_eq(const struct ldlm_res_id *res0,
const struct ldlm_res_id *res1)
@@ -2774,19 +2774,19 @@
struct ldlm_inodebits l_inodebits;
} ldlm_wire_policy_data_t;
-extern void lustre_swab_ldlm_policy_data (ldlm_wire_policy_data_t *d);
+void lustre_swab_ldlm_policy_data(ldlm_wire_policy_data_t *d);
union ldlm_gl_desc {
struct ldlm_gl_lquota_desc lquota_desc;
};
-extern void lustre_swab_gl_desc(union ldlm_gl_desc *);
+void lustre_swab_gl_desc(union ldlm_gl_desc *);
struct ldlm_intent {
__u64 opc;
};
-extern void lustre_swab_ldlm_intent (struct ldlm_intent *i);
+void lustre_swab_ldlm_intent(struct ldlm_intent *i);
struct ldlm_resource_desc {
ldlm_type_t lr_type;
@@ -2794,7 +2794,7 @@
struct ldlm_res_id lr_name;
};
-extern void lustre_swab_ldlm_resource_desc (struct ldlm_resource_desc *r);
+void lustre_swab_ldlm_resource_desc(struct ldlm_resource_desc *r);
struct ldlm_lock_desc {
struct ldlm_resource_desc l_resource;
@@ -2803,7 +2803,7 @@
ldlm_wire_policy_data_t l_policy_data;
};
-extern void lustre_swab_ldlm_lock_desc (struct ldlm_lock_desc *l);
+void lustre_swab_ldlm_lock_desc(struct ldlm_lock_desc *l);
#define LDLM_LOCKREQ_HANDLES 2
#define LDLM_ENQUEUE_CANCEL_OFF 1
@@ -2815,7 +2815,7 @@
struct lustre_handle lock_handle[LDLM_LOCKREQ_HANDLES];
};
-extern void lustre_swab_ldlm_request (struct ldlm_request *rq);
+void lustre_swab_ldlm_request(struct ldlm_request *rq);
/* If LDLM_ENQUEUE, 1 slot is already occupied, 1 is available.
* Otherwise, 2 are available. */
@@ -2837,7 +2837,7 @@
__u64 lock_policy_res2;
};
-extern void lustre_swab_ldlm_reply (struct ldlm_reply *r);
+void lustre_swab_ldlm_reply(struct ldlm_reply *r);
#define ldlm_flags_to_wire(flags) ((__u32)(flags))
#define ldlm_flags_from_wire(flags) ((__u64)(flags))
@@ -2881,7 +2881,8 @@
__u64 mti_nids[MTI_NIDS_MAX]; /* host nids (lnet_nid_t)*/
char mti_params[MTI_PARAM_MAXLEN];
};
-extern void lustre_swab_mgs_target_info(struct mgs_target_info *oinfo);
+
+void lustre_swab_mgs_target_info(struct mgs_target_info *oinfo);
struct mgs_nidtbl_entry {
__u64 mne_version; /* table version of this entry */
@@ -2896,7 +2897,8 @@
lnet_nid_t nids[0]; /* variable size buffer for NIDs. */
} u;
};
-extern void lustre_swab_mgs_nidtbl_entry(struct mgs_nidtbl_entry *oinfo);
+
+void lustre_swab_mgs_nidtbl_entry(struct mgs_nidtbl_entry *oinfo);
struct mgs_config_body {
char mcb_name[MTI_NAME_MAXLEN]; /* logname */
@@ -2906,13 +2908,15 @@
__u8 mcb_bits; /* bits unit size of config log */
__u32 mcb_units; /* # of units for bulk transfer */
};
-extern void lustre_swab_mgs_config_body(struct mgs_config_body *body);
+
+void lustre_swab_mgs_config_body(struct mgs_config_body *body);
struct mgs_config_res {
__u64 mcr_offset; /* index of last config log */
__u64 mcr_size; /* size of the log */
};
-extern void lustre_swab_mgs_config_res(struct mgs_config_res *body);
+
+void lustre_swab_mgs_config_res(struct mgs_config_res *body);
/* Config marker flags (in config log) */
#define CM_START 0x01
@@ -2933,8 +2937,7 @@
char cm_comment[MTI_NAME_MAXLEN];
};
-extern void lustre_swab_cfg_marker(struct cfg_marker *marker,
- int swab, int size);
+void lustre_swab_cfg_marker(struct cfg_marker *marker, int swab, int size);
/*
* Opcodes for multiple servers.
@@ -3334,7 +3337,7 @@
}
}
-extern void lustre_swab_obdo (struct obdo *o);
+void lustre_swab_obdo(struct obdo *o);
/* request structure for OST's */
struct ost_body {
@@ -3348,25 +3351,25 @@
struct ll_user_fiemap fiemap;
};
-extern void lustre_swab_ost_body (struct ost_body *b);
-extern void lustre_swab_ost_last_id(__u64 *id);
-extern void lustre_swab_fiemap(struct ll_user_fiemap *fiemap);
+void lustre_swab_ost_body(struct ost_body *b);
+void lustre_swab_ost_last_id(__u64 *id);
+void lustre_swab_fiemap(struct ll_user_fiemap *fiemap);
-extern void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum);
-extern void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum);
-extern void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod,
- int stripe_count);
-extern void lustre_swab_lov_mds_md(struct lov_mds_md *lmm);
+void lustre_swab_lov_user_md_v1(struct lov_user_md_v1 *lum);
+void lustre_swab_lov_user_md_v3(struct lov_user_md_v3 *lum);
+void lustre_swab_lov_user_md_objects(struct lov_user_ost_data *lod,
+ int stripe_count);
+void lustre_swab_lov_mds_md(struct lov_mds_md *lmm);
/* llog_swab.c */
-extern void lustre_swab_llogd_body (struct llogd_body *d);
-extern void lustre_swab_llog_hdr (struct llog_log_hdr *h);
-extern void lustre_swab_llogd_conn_body (struct llogd_conn_body *d);
-extern void lustre_swab_llog_rec(struct llog_rec_hdr *rec);
-extern void lustre_swab_llog_id(struct llog_logid *lid);
+void lustre_swab_llogd_body(struct llogd_body *d);
+void lustre_swab_llog_hdr(struct llog_log_hdr *h);
+void lustre_swab_llogd_conn_body(struct llogd_conn_body *d);
+void lustre_swab_llog_rec(struct llog_rec_hdr *rec);
+void lustre_swab_llog_id(struct llog_logid *lid);
struct lustre_cfg;
-extern void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg);
+void lustre_swab_lustre_cfg(struct lustre_cfg *lcfg);
/* Functions for dumping PTLRPC fields */
void dump_rniobuf(struct niobuf_remote *rnb);
@@ -3418,7 +3421,8 @@
__u64 ii_pad2;
__u64 ii_pad3;
};
-extern void lustre_swab_idx_info(struct idx_info *ii);
+
+void lustre_swab_idx_info(struct idx_info *ii);
#define II_END_OFF MDS_DIR_END_OFF /* all entries have been read */
@@ -3450,7 +3454,8 @@
* For the time being, we only support fixed-size key & record. */
char lip_entries[0];
};
-extern void lustre_swab_lip_header(struct lu_idxpage *lip);
+
+void lustre_swab_lip_header(struct lu_idxpage *lip);
#define LIP_HDR_SIZE (offsetof(struct lu_idxpage, lip_entries))
@@ -3490,7 +3495,7 @@
__u8 lc_hmac[CAPA_HMAC_MAX_LEN]; /** HMAC */
} __attribute__((packed));
-extern void lustre_swab_lustre_capa(struct lustre_capa *c);
+void lustre_swab_lustre_capa(struct lustre_capa *c);
/** lustre_capa::lc_opc */
enum {
@@ -3548,7 +3553,7 @@
__u8 lk_key[CAPA_HMAC_KEY_MAX_LEN]; /**< key */
} __attribute__((packed));
-extern void lustre_swab_lustre_capa_key(struct lustre_capa_key *k);
+void lustre_swab_lustre_capa_key(struct lustre_capa_key *k);
/** The link ea holds 1 \a link_ea_entry for each hardlink */
#define LINK_EA_MAGIC 0x11EAF1DFUL
@@ -3620,12 +3625,12 @@
__u64 hpk_padding2;
} __attribute__((packed));
-extern void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
-extern void lustre_swab_hsm_current_action(struct hsm_current_action *action);
-extern void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk);
-extern void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
-extern void lustre_swab_hsm_user_item(struct hsm_user_item *hui);
-extern void lustre_swab_hsm_request(struct hsm_request *hr);
+void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
+void lustre_swab_hsm_current_action(struct hsm_current_action *action);
+void lustre_swab_hsm_progress_kernel(struct hsm_progress_kernel *hpk);
+void lustre_swab_hsm_user_state(struct hsm_user_state *hus);
+void lustre_swab_hsm_user_item(struct hsm_user_item *hui);
+void lustre_swab_hsm_request(struct hsm_request *hr);
/**
* These are object update opcode under UPDATE_OBJ, which is currently
diff --git a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
index e095ada..9b1bb23 100644
--- a/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
+++ b/drivers/staging/lustre/lustre/include/lustre/lustre_user.h
@@ -406,7 +406,7 @@
stripes * sizeof(struct lmv_user_mds_data);
}
-extern void lustre_swab_lmv_user_md(struct lmv_user_md *lum);
+void lustre_swab_lmv_user_md(struct lmv_user_md *lum);
struct ll_recreate_obj {
__u64 lrc_id;
diff --git a/drivers/staging/lustre/lustre/include/lustre_dlm.h b/drivers/staging/lustre/lustre/include/lustre_dlm.h
index f6f4c03..3552546 100644
--- a/drivers/staging/lustre/lustre/include/lustre_dlm.h
+++ b/drivers/staging/lustre/lustre/include/lustre_dlm.h
@@ -1017,7 +1017,7 @@
extern char *ldlm_lockname[];
extern char *ldlm_typename[];
-extern char *ldlm_it2str(int it);
+char *ldlm_it2str(int it);
/**
* Just a fancy CDEBUG call with log level preset to LDLM_DEBUG.
diff --git a/drivers/staging/lustre/lustre/include/lustre_export.h b/drivers/staging/lustre/lustre/include/lustre_export.h
index 3b992b4..5189fad 100644
--- a/drivers/staging/lustre/lustre/include/lustre_export.h
+++ b/drivers/staging/lustre/lustre/include/lustre_export.h
@@ -368,8 +368,8 @@
return ocd->ocd_connect_flags & OBD_CONNECT_DISP_STRIPE;
}
-extern struct obd_export *class_conn2export(struct lustre_handle *conn);
-extern struct obd_device *class_conn2obd(struct lustre_handle *conn);
+struct obd_export *class_conn2export(struct lustre_handle *conn);
+struct obd_device *class_conn2obd(struct lustre_handle *conn);
/** @} export */
diff --git a/drivers/staging/lustre/lustre/include/lustre_import.h b/drivers/staging/lustre/lustre/include/lustre_import.h
index dcc8076..5a38f3d 100644
--- a/drivers/staging/lustre/lustre/include/lustre_import.h
+++ b/drivers/staging/lustre/lustre/include/lustre_import.h
@@ -375,8 +375,8 @@
/* genops.c */
struct obd_export;
-extern struct obd_import *class_exp2cliimp(struct obd_export *);
-extern struct obd_import *class_conn2cliimp(struct lustre_handle *);
+struct obd_import *class_exp2cliimp(struct obd_export *);
+struct obd_import *class_conn2cliimp(struct lustre_handle *);
/** @} import */
diff --git a/drivers/staging/lustre/lustre/include/lustre_net.h b/drivers/staging/lustre/lustre/include/lustre_net.h
index 77a7de9..48ad60b 100644
--- a/drivers/staging/lustre/lustre/include/lustre_net.h
+++ b/drivers/staging/lustre/lustre/include/lustre_net.h
@@ -2183,7 +2183,7 @@
*/
struct ptlrpc_request_set *pc_set;
/**
- * Thread name used in cfs_daemonize()
+ * Thread name used in kthread_run()
*/
char pc_name[16];
/**
@@ -2277,18 +2277,18 @@
/* ptlrpc/events.c */
extern lnet_handle_eq_t ptlrpc_eq_h;
-extern int ptlrpc_uuid_to_peer(struct obd_uuid *uuid,
- lnet_process_id_t *peer, lnet_nid_t *self);
+int ptlrpc_uuid_to_peer(struct obd_uuid *uuid,
+ lnet_process_id_t *peer, lnet_nid_t *self);
/**
* These callbacks are invoked by LNet when something happened to
* underlying buffer
* @{
*/
-extern void request_out_callback(lnet_event_t *ev);
-extern void reply_in_callback(lnet_event_t *ev);
-extern void client_bulk_callback(lnet_event_t *ev);
-extern void request_in_callback(lnet_event_t *ev);
-extern void reply_out_callback(lnet_event_t *ev);
+void request_out_callback(lnet_event_t *ev);
+void reply_in_callback(lnet_event_t *ev);
+void client_bulk_callback(lnet_event_t *ev);
+void request_in_callback(lnet_event_t *ev);
+void reply_out_callback(lnet_event_t *ev);
/** @} */
/* ptlrpc/connection.c */
@@ -2299,7 +2299,7 @@
struct ptlrpc_connection *ptlrpc_connection_addref(struct ptlrpc_connection *);
int ptlrpc_connection_init(void);
void ptlrpc_connection_fini(void);
-extern lnet_pid_t ptl_get_pid(void);
+lnet_pid_t ptl_get_pid(void);
/* ptlrpc/niobuf.c */
/**
diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h
index 55452e5..9ad8c26 100644
--- a/drivers/staging/lustre/lustre/include/obd.h
+++ b/drivers/staging/lustre/lustre/include/obd.h
@@ -1472,7 +1472,7 @@
}
/* we have an idx, read it */
start = name + LUSTRE_VOLATILE_HDR_LEN + 1;
- *idx = strtoul(start, &end, 0);
+ *idx = simple_strtoul(start, &end, 0);
/* error cases:
* no digit, no trailing :, negative value
*/
diff --git a/drivers/staging/lustre/lustre/include/obd_class.h b/drivers/staging/lustre/lustre/include/obd_class.h
index 36ed781..87bb2ce 100644
--- a/drivers/staging/lustre/lustre/include/obd_class.h
+++ b/drivers/staging/lustre/lustre/include/obd_class.h
@@ -64,10 +64,10 @@
extern rwlock_t obd_dev_lock;
/* OBD Operations Declarations */
-extern struct obd_device *class_conn2obd(struct lustre_handle *);
-extern struct obd_device *class_exp2obd(struct obd_export *);
-extern int class_handle_ioctl(unsigned int cmd, unsigned long arg);
-extern int lustre_get_jobid(char *jobid);
+struct obd_device *class_conn2obd(struct lustre_handle *);
+struct obd_device *class_exp2obd(struct obd_export *);
+int class_handle_ioctl(unsigned int cmd, unsigned long arg);
+int lustre_get_jobid(char *jobid);
struct lu_device_type;
@@ -139,7 +139,7 @@
int class_add_uuid(const char *uuid, __u64 nid);
/*obdecho*/
-extern void lprocfs_echo_init_vars(struct lprocfs_static_vars *lvars);
+void lprocfs_echo_init_vars(struct lprocfs_static_vars *lvars);
#define CFG_F_START 0x01 /* Set when we start updating from a log */
#define CFG_F_MARKER 0x02 /* We are within a maker */
@@ -1823,8 +1823,8 @@
/* OBD Metadata Support */
-extern int obd_init_caches(void);
-extern void obd_cleanup_caches(void);
+int obd_init_caches(void);
+void obd_cleanup_caches(void);
/* support routines */
extern struct kmem_cache *obdo_cachep;
@@ -1869,8 +1869,7 @@
/* obd_mount.c */
/* sysctl.c */
-extern void obd_sysctl_init (void);
-extern void obd_sysctl_clean (void);
+int obd_sysctl_init(void);
/* uuid.c */
typedef __u8 class_uuid_t[16];
diff --git a/drivers/staging/lustre/lustre/include/obd_support.h b/drivers/staging/lustre/lustre/include/obd_support.h
index 73e2d48..18aec79 100644
--- a/drivers/staging/lustre/lustre/include/obd_support.h
+++ b/drivers/staging/lustre/lustre/include/obd_support.h
@@ -56,9 +56,7 @@
/* obd_timeout should only be used for recovery, not for
networking / disk / timings affected by load (use Adaptive Timeouts) */
extern unsigned int obd_timeout; /* seconds */
-extern unsigned int ldlm_timeout; /* seconds */
extern unsigned int obd_timeout_set;
-extern unsigned int ldlm_timeout_set;
extern unsigned int at_min;
extern unsigned int at_max;
extern unsigned int at_history;
@@ -105,8 +103,6 @@
/* Timeout definitions */
#define OBD_TIMEOUT_DEFAULT 100
-#define LDLM_TIMEOUT_DEFAULT 20
-#define MDS_LDLM_TIMEOUT_DEFAULT 6
/* Time to wait for all clients to reconnect during recovery (hard limit) */
#define OBD_RECOVERY_TIME_HARD (obd_timeout * 9)
/* Time to wait for all clients to reconnect during recovery (soft limit) */
@@ -505,9 +501,7 @@
#define OBD_FAIL_ONCE CFS_FAIL_ONCE
#define OBD_FAILED CFS_FAILED
-extern atomic_t libcfs_kmemory;
-
-extern void obd_update_maxusage(void);
+void obd_update_maxusage(void);
#define obd_memory_add(size) \
lprocfs_counter_add(obd_memory, OBD_MEMORY_STAT, (long)(size))
@@ -526,8 +520,8 @@
lprocfs_stats_collector(obd_memory, OBD_MEMORY_PAGES_STAT, \
LPROCFS_FIELDS_FLAGS_SUM)
-extern __u64 obd_memory_max(void);
-extern __u64 obd_pages_max(void);
+__u64 obd_memory_max(void);
+__u64 obd_pages_max(void);
#define OBD_DEBUG_MEMUSAGE (1)
@@ -622,8 +616,8 @@
if (unlikely((ptr) == NULL)) { \
CERROR("vmalloc of '" #ptr "' (%d bytes) failed\n", \
(int)(size)); \
- CERROR("%llu total bytes allocated by Lustre, %d by LNET\n", \
- obd_memory_sum(), atomic_read(&libcfs_kmemory)); \
+ CERROR("%llu total bytes allocated by Lustre\n", \
+ obd_memory_sum()); \
} else { \
OBD_ALLOC_POST(ptr, size, "vmalloced"); \
} \
@@ -769,12 +763,10 @@
"failed\n", (int)1, \
(__u64)(1 << PAGE_CACHE_SHIFT)); \
CERROR("%llu total bytes and %llu total pages " \
- "(%llu bytes) allocated by Lustre, " \
- "%d total bytes by LNET\n", \
+ "(%llu bytes) allocated by Lustre\n", \
obd_memory_sum(), \
obd_pages_sum() << PAGE_CACHE_SHIFT, \
- obd_pages_sum(), \
- atomic_read(&libcfs_kmemory)); \
+ obd_pages_sum()); \
} else { \
obd_pages_add(0); \
CDEBUG(D_MALLOC, "alloc_pages '" #ptr "': %d page(s) / " \
diff --git a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
index e0c1cca..9053f81 100644
--- a/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
+++ b/drivers/staging/lustre/lustre/lclient/lcommon_cl.c
@@ -203,7 +203,7 @@
int rc;
vdv = kzalloc(sizeof(*vdv), GFP_NOFS);
- if (vdv == NULL)
+ if (!vdv)
return ERR_PTR(-ENOMEM);
lud = &vdv->cdv_cl.cd_lu_dev;
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
index 6601e6b..fa4b7c7 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_internal.h
@@ -209,7 +209,7 @@
/* interval tree, for LDLM_EXTENT. */
extern struct kmem_cache *ldlm_interval_slab; /* slab cache for ldlm_interval */
-extern void ldlm_interval_attach(struct ldlm_interval *n, struct ldlm_lock *l);
+void ldlm_interval_attach(struct ldlm_interval *n, struct ldlm_lock *l);
struct ldlm_interval *ldlm_interval_detach(struct ldlm_lock *l);
struct ldlm_interval *ldlm_interval_alloc(struct ldlm_lock *lock);
void ldlm_interval_free(struct ldlm_interval *node);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
index 764f986..badd227 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lib.c
@@ -656,7 +656,8 @@
}
EXPORT_SYMBOL(target_pack_pool_reply);
-int target_send_reply_msg(struct ptlrpc_request *req, int rc, int fail_id)
+static int
+target_send_reply_msg(struct ptlrpc_request *req, int rc, int fail_id)
{
if (OBD_FAIL_CHECK_ORSET(fail_id & ~OBD_FAIL_ONCE, OBD_FAIL_ONCE)) {
DEBUG_REQ(D_ERROR, req, "dropping reply");
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
index bb2246d..cd340fc 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lock.c
@@ -1528,7 +1528,7 @@
if (lvb_len) {
lock->l_lvb_len = lvb_len;
lock->l_lvb_data = kzalloc(lvb_len, GFP_NOFS);
- if (lock->l_lvb_data == NULL)
+ if (!lock->l_lvb_data)
goto out;
}
@@ -1813,7 +1813,7 @@
return 0;
arg = kzalloc(sizeof(*arg), GFP_NOFS);
- if (arg == NULL)
+ if (!arg)
return -ENOMEM;
atomic_set(&arg->restart, 0);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
index b7b6ca1..ac79db9 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
@@ -76,15 +76,6 @@
return cfs_time_seconds((int)cfs_duration_sec(cfs_time_sub(timeout, 0)) + 1);
}
-/* timeout for initial callback (AST) reply (bz10399) */
-static inline unsigned int ldlm_get_rq_timeout(void)
-{
- /* Non-AT value */
- unsigned int timeout = min(ldlm_timeout, obd_timeout / 3);
-
- return timeout < 1 ? 1 : timeout;
-}
-
#define ELT_STOPPED 0
#define ELT_READY 1
#define ELT_TERMINATE 2
@@ -225,7 +216,7 @@
void *lvb_data;
lvb_data = kzalloc(lvb_len, GFP_NOFS);
- if (lvb_data == NULL) {
+ if (!lvb_data) {
LDLM_ERROR(lock, "No memory: %d.\n", lvb_len);
rc = -ENOMEM;
goto out;
@@ -453,7 +444,7 @@
struct ldlm_bl_work_item *blwi;
blwi = kzalloc(sizeof(*blwi), GFP_NOFS);
- if (blwi == NULL)
+ if (!blwi)
return -ENOMEM;
init_blwi(blwi, ns, ld, cancels, count, lock, cancel_flags);
@@ -1053,7 +1044,7 @@
return -EALREADY;
ldlm_state = kzalloc(sizeof(*ldlm_state), GFP_NOFS);
- if (ldlm_state == NULL)
+ if (!ldlm_state)
return -ENOMEM;
ldlm_kobj = kobject_create_and_add("ldlm", lustre_kobj);
@@ -1123,7 +1114,7 @@
blp = kzalloc(sizeof(*blp), GFP_NOFS);
- if (blp == NULL) {
+ if (!blp) {
rc = -ENOMEM;
goto out;
}
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
index 1605b9c..c234acb 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_pool.c
@@ -1422,7 +1422,7 @@
return -EALREADY;
ldlm_pools_thread = kzalloc(sizeof(*ldlm_pools_thread), GFP_NOFS);
- if (ldlm_pools_thread == NULL)
+ if (!ldlm_pools_thread)
return -ENOMEM;
init_completion(&ldlm_pools_comp);
@@ -1486,8 +1486,10 @@
void ldlm_pools_fini(void)
{
- unregister_shrinker(&ldlm_pools_srv_shrinker);
- unregister_shrinker(&ldlm_pools_cli_shrinker);
+ if (ldlm_pools_thread) {
+ unregister_shrinker(&ldlm_pools_srv_shrinker);
+ unregister_shrinker(&ldlm_pools_cli_shrinker);
+ }
ldlm_pools_thread_stop();
}
EXPORT_SYMBOL(ldlm_pools_fini);
diff --git a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
index cdb6366..4bb3173 100644
--- a/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
+++ b/drivers/staging/lustre/lustre/ldlm/ldlm_resource.c
@@ -939,6 +939,7 @@
ldlm_pool_fini(&ns->ns_pool);
ldlm_namespace_debugfs_unregister(ns);
+ ldlm_namespace_sysfs_unregister(ns);
cfs_hash_putref(ns->ns_rs_hash);
/* Namespace \a ns should be not on list at this time, otherwise
* this will cause issues related to using freed \a ns in poold
diff --git a/drivers/staging/lustre/lustre/libcfs/debug.c b/drivers/staging/lustre/lustre/libcfs/debug.c
index 021c92f..e93f556 100644
--- a/drivers/staging/lustre/lustre/libcfs/debug.c
+++ b/drivers/staging/lustre/lustre/libcfs/debug.c
@@ -57,8 +57,42 @@
MODULE_PARM_DESC(libcfs_debug, "Lustre kernel debug mask");
EXPORT_SYMBOL(libcfs_debug);
+static int libcfs_param_debug_mb_set(const char *val,
+ const struct kernel_param *kp)
+{
+ int rc;
+ unsigned num;
+
+ rc = kstrtouint(val, 0, &num);
+ if (rc < 0)
+ return rc;
+
+ if (!*((unsigned int *)kp->arg)) {
+ *((unsigned int *)kp->arg) = num;
+ return 0;
+ }
+
+ rc = cfs_trace_set_debug_mb(num);
+
+ if (!rc)
+ *((unsigned int *)kp->arg) = cfs_trace_get_debug_mb();
+
+ return rc;
+}
+
+/* While debug_mb setting look like unsigned int, in fact
+ * it needs quite a bunch of extra processing, so we define special
+ * debugmb parameter type with corresponding methods to handle this case */
+static struct kernel_param_ops param_ops_debugmb = {
+ .set = libcfs_param_debug_mb_set,
+ .get = param_get_uint,
+};
+
+#define param_check_debugmb(name, p) \
+ __param_check(name, p, unsigned int)
+
static unsigned int libcfs_debug_mb;
-module_param(libcfs_debug_mb, uint, 0644);
+module_param(libcfs_debug_mb, debugmb, 0644);
MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size.");
EXPORT_SYMBOL(libcfs_debug_mb);
@@ -72,18 +106,106 @@
MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)");
EXPORT_SYMBOL(libcfs_console_ratelimit);
-unsigned int libcfs_console_max_delay;
-module_param(libcfs_console_max_delay, uint, 0644);
-MODULE_PARM_DESC(libcfs_console_max_delay, "Lustre kernel debug console max delay (jiffies)");
-EXPORT_SYMBOL(libcfs_console_max_delay);
+static int param_set_delay_minmax(const char *val,
+ const struct kernel_param *kp,
+ long min, long max)
+{
+ long d;
+ int sec;
+ int rc;
+ rc = kstrtoint(val, 0, &sec);
+ if (rc)
+ return -EINVAL;
+
+ d = cfs_time_seconds(sec) / 100;
+ if (d < min || d > max)
+ return -EINVAL;
+
+ *((unsigned int *)kp->arg) = d;
+
+ return 0;
+}
+
+static int param_get_delay(char *buffer, const struct kernel_param *kp)
+{
+ unsigned int d = *(unsigned int *)kp->arg;
+
+ return sprintf(buffer, "%u", (unsigned int)cfs_duration_sec(d * 100));
+}
+
+unsigned int libcfs_console_max_delay;
+EXPORT_SYMBOL(libcfs_console_max_delay);
unsigned int libcfs_console_min_delay;
-module_param(libcfs_console_min_delay, uint, 0644);
-MODULE_PARM_DESC(libcfs_console_min_delay, "Lustre kernel debug console min delay (jiffies)");
EXPORT_SYMBOL(libcfs_console_min_delay);
+static int param_set_console_max_delay(const char *val,
+ const struct kernel_param *kp)
+{
+ return param_set_delay_minmax(val, kp,
+ libcfs_console_min_delay, INT_MAX);
+}
+
+static struct kernel_param_ops param_ops_console_max_delay = {
+ .set = param_set_console_max_delay,
+ .get = param_get_delay,
+};
+
+#define param_check_console_max_delay(name, p) \
+ __param_check(name, p, unsigned int)
+
+module_param(libcfs_console_max_delay, console_max_delay, 0644);
+MODULE_PARM_DESC(libcfs_console_max_delay, "Lustre kernel debug console max delay (jiffies)");
+
+static int param_set_console_min_delay(const char *val,
+ const struct kernel_param *kp)
+{
+ return param_set_delay_minmax(val, kp,
+ 1, libcfs_console_max_delay);
+}
+
+static struct kernel_param_ops param_ops_console_min_delay = {
+ .set = param_set_console_min_delay,
+ .get = param_get_delay,
+};
+
+#define param_check_console_min_delay(name, p) \
+ __param_check(name, p, unsigned int)
+
+module_param(libcfs_console_min_delay, console_min_delay, 0644);
+MODULE_PARM_DESC(libcfs_console_min_delay, "Lustre kernel debug console min delay (jiffies)");
+
+static int param_set_uint_minmax(const char *val,
+ const struct kernel_param *kp,
+ unsigned int min, unsigned int max)
+{
+ unsigned int num;
+ int ret;
+
+ if (!val)
+ return -EINVAL;
+ ret = kstrtouint(val, 0, &num);
+ if (ret < 0 || num < min || num > max)
+ return -EINVAL;
+ *((unsigned int *)kp->arg) = num;
+ return 0;
+}
+
+static int param_set_uintpos(const char *val, const struct kernel_param *kp)
+{
+ return param_set_uint_minmax(val, kp, 1, -1);
+}
+
+static struct kernel_param_ops param_ops_uintpos = {
+ .set = param_set_uintpos,
+ .get = param_get_uint,
+};
+
+#define param_check_uintpos(name, p) \
+ __param_check(name, p, unsigned int)
+
unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF;
-module_param(libcfs_console_backoff, uint, 0644);
+module_param(libcfs_console_backoff, uintpos, 0644);
MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor");
EXPORT_SYMBOL(libcfs_console_backoff);
@@ -93,23 +215,14 @@
unsigned int libcfs_stack = 3 * THREAD_SIZE / 4;
EXPORT_SYMBOL(libcfs_stack);
-static unsigned int portal_enter_debugger;
-EXPORT_SYMBOL(portal_enter_debugger);
-
unsigned int libcfs_catastrophe;
EXPORT_SYMBOL(libcfs_catastrophe);
-unsigned int libcfs_watchdog_ratelimit = 300;
-EXPORT_SYMBOL(libcfs_watchdog_ratelimit);
-
unsigned int libcfs_panic_on_lbug = 1;
module_param(libcfs_panic_on_lbug, uint, 0644);
MODULE_PARM_DESC(libcfs_panic_on_lbug, "Lustre kernel panic on LBUG");
EXPORT_SYMBOL(libcfs_panic_on_lbug);
-atomic_t libcfs_kmemory = ATOMIC_INIT(0);
-EXPORT_SYMBOL(libcfs_kmemory);
-
static wait_queue_head_t debug_ctlwq;
char libcfs_debug_file_path_arr[PATH_MAX] = LIBCFS_DEBUG_FILE_PATH_DEFAULT;
@@ -414,8 +527,10 @@
}
rc = cfs_tracefile_init(max);
- if (rc == 0)
+ if (rc == 0) {
libcfs_register_panic_notifier();
+ libcfs_debug_mb = cfs_trace_get_debug_mb();
+ }
return rc;
}
diff --git a/drivers/staging/lustre/lustre/libcfs/fail.c b/drivers/staging/lustre/lustre/libcfs/fail.c
index 7b7fc21..42d615f 100644
--- a/drivers/staging/lustre/lustre/libcfs/fail.c
+++ b/drivers/staging/lustre/lustre/libcfs/fail.c
@@ -123,7 +123,7 @@
int __cfs_fail_timeout_set(__u32 id, __u32 value, int ms, int set)
{
- int ret = 0;
+ int ret;
ret = __cfs_fail_check_set(id, value, set);
if (ret) {
diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c
index 31a5581..933525c 100644
--- a/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c
+++ b/drivers/staging/lustre/lustre/libcfs/libcfs_cpu.c
@@ -78,7 +78,7 @@
int
cfs_cpt_table_print(struct cfs_cpt_table *cptab, char *buf, int len)
{
- int rc = 0;
+ int rc;
rc = snprintf(buf, len, "%d\t: %d\n", 0, 0);
len -= rc;
diff --git a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
index 76d4392..efe5e66 100644
--- a/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
+++ b/drivers/staging/lustre/lustre/libcfs/libcfs_string.c
@@ -231,7 +231,7 @@
char *endp;
str = cfs_trimwhite(str);
- *num = strtoul(str, &endp, 0);
+ *num = simple_strtoul(str, &endp, 0);
if (endp == str)
return 0;
@@ -400,7 +400,7 @@
struct cfs_range_expr *expr;
expr = list_entry(expr_list->el_exprs.next,
- struct cfs_range_expr, re_link),
+ struct cfs_range_expr, re_link);
list_del(&expr->re_link);
LIBCFS_FREE(expr, sizeof(*expr));
}
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c
index aa3fffe..fbbc8a7 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-crypto.c
@@ -114,7 +114,7 @@
crypto_free_hash(hdesc.tfm);
return -ENOSPC;
}
- sg_init_one(&sl, (void *)buf, buf_len);
+ sg_init_one(&sl, buf, buf_len);
hdesc.flags = 0;
err = crypto_hash_digest(&hdesc, &sl, sl.length, hash);
@@ -165,7 +165,7 @@
{
struct scatterlist sl;
- sg_init_one(&sl, (void *)buf, buf_len);
+ sg_init_one(&sl, buf, buf_len);
return crypto_hash_update((struct hash_desc *)hdesc, &sl, sl.length);
}
diff --git a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
index e962f89..64a984b 100644
--- a/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
+++ b/drivers/staging/lustre/lustre/libcfs/linux/linux-module.c
@@ -49,7 +49,7 @@
hdr = (struct libcfs_ioctl_hdr *)buf;
data = (struct libcfs_ioctl_data *)buf;
- if (copy_from_user(buf, (void *)arg, sizeof(*hdr)))
+ if (copy_from_user(buf, arg, sizeof(*hdr)))
return -EFAULT;
if (hdr->ioc_version != LIBCFS_IOCTL_VERSION) {
@@ -69,7 +69,7 @@
}
orig_len = hdr->ioc_len;
- if (copy_from_user(buf, (void *)arg, hdr->ioc_len))
+ if (copy_from_user(buf, arg, hdr->ioc_len))
return -EFAULT;
if (orig_len != data->ioc_len)
return -EINVAL;
@@ -96,8 +96,6 @@
return 0;
}
-extern struct cfs_psdev_ops libcfs_psdev_ops;
-
static int
libcfs_psdev_open(struct inode *inode, struct file *file)
{
diff --git a/drivers/staging/lustre/lustre/libcfs/module.c b/drivers/staging/lustre/lustre/libcfs/module.c
index e60b2e9..806f974 100644
--- a/drivers/staging/lustre/lustre/libcfs/module.c
+++ b/drivers/staging/lustre/lustre/libcfs/module.c
@@ -50,6 +50,7 @@
#include <linux/list.h>
#include <linux/sysctl.h>
+#include <linux/debugfs.h>
# define DEBUG_SUBSYSTEM S_LNET
@@ -65,48 +66,12 @@
MODULE_DESCRIPTION("Portals v3.1");
MODULE_LICENSE("GPL");
-extern struct miscdevice libcfs_dev;
-extern struct cfs_wi_sched *cfs_sched_rehash;
-extern void libcfs_init_nidstrings(void);
+static void insert_debugfs(void);
+static void remove_debugfs(void);
-static int insert_proc(void);
-static void remove_proc(void);
+static struct dentry *lnet_debugfs_root;
-static struct ctl_table_header *lnet_table_header;
-extern char lnet_upcall[1024];
-/**
- * The path of debug log dump upcall script.
- */
-extern char lnet_debug_log_upcall[1024];
-
-#define CTL_LNET (0x100)
-
-enum {
- PSDEV_DEBUG = 1, /* control debugging */
- PSDEV_SUBSYSTEM_DEBUG, /* control debugging */
- PSDEV_PRINTK, /* force all messages to console */
- PSDEV_CONSOLE_RATELIMIT, /* ratelimit console messages */
- PSDEV_CONSOLE_MAX_DELAY_CS, /* maximum delay over which we skip messages */
- PSDEV_CONSOLE_MIN_DELAY_CS, /* initial delay over which we skip messages */
- PSDEV_CONSOLE_BACKOFF, /* delay increase factor */
- PSDEV_DEBUG_PATH, /* crashdump log location */
- PSDEV_DEBUG_DUMP_PATH, /* crashdump tracelog location */
- PSDEV_CPT_TABLE, /* information about cpu partitions */
- PSDEV_LNET_UPCALL, /* User mode upcall script */
- PSDEV_LNET_MEMUSED, /* bytes currently PORTAL_ALLOCated */
- PSDEV_LNET_CATASTROPHE, /* if we have LBUGged or panic'd */
- PSDEV_LNET_PANIC_ON_LBUG, /* flag to panic on LBUG */
- PSDEV_LNET_DUMP_KERNEL, /* snapshot kernel debug buffer to file */
- PSDEV_LNET_DAEMON_FILE, /* spool kernel debug buffer to file */
- PSDEV_LNET_DEBUG_MB, /* size of debug buffer */
- PSDEV_LNET_DEBUG_LOG_UPCALL, /* debug log upcall script */
- PSDEV_LNET_WATCHDOG_RATELIMIT, /* ratelimit watchdog messages */
- PSDEV_LNET_FORCE_LBUG, /* hook to force an LBUG */
- PSDEV_LNET_FAIL_LOC, /* control test failures instrumentation */
- PSDEV_LNET_FAIL_VAL, /* userdata for fail loc */
-};
-
-static void kportal_memhog_free (struct libcfs_device_userstate *ldu)
+static void kportal_memhog_free(struct libcfs_device_userstate *ldu)
{
struct page **level0p = &ldu->ldu_memhog_root_page;
struct page **level1p;
@@ -146,7 +111,7 @@
*level0p = NULL;
}
- LASSERT (ldu->ldu_memhog_pages == 0);
+ LASSERT(ldu->ldu_memhog_pages == 0);
}
static int kportal_memhog_alloc(struct libcfs_device_userstate *ldu, int npages,
@@ -158,8 +123,8 @@
int count1;
int count2;
- LASSERT (ldu->ldu_memhog_pages == 0);
- LASSERT (ldu->ldu_memhog_root_page == NULL);
+ LASSERT(ldu->ldu_memhog_pages == 0);
+ LASSERT(ldu->ldu_memhog_root_page == NULL);
if (npages < 0)
return -EINVAL;
@@ -338,7 +303,7 @@
if (err != -EINVAL) {
if (err == 0)
err = libcfs_ioctl_popdata(arg,
- data, sizeof (*data));
+ data, sizeof(*data));
break;
}
}
@@ -361,7 +326,7 @@
return -ENOMEM;
/* 'cmd' and permissions get checked in our arch-specific caller */
- if (libcfs_ioctl_getdata(buf, buf + 800, (void *)arg)) {
+ if (libcfs_ioctl_getdata(buf, buf + 800, arg)) {
CERROR("PORTALS ioctl: data error\n");
err = -EINVAL;
goto out;
@@ -428,17 +393,10 @@
goto cleanup_wi;
}
+ insert_debugfs();
- rc = insert_proc();
- if (rc) {
- CERROR("insert_proc: error %d\n", rc);
- goto cleanup_crypto;
- }
-
- CDEBUG (D_OTHER, "portals setup OK\n");
+ CDEBUG(D_OTHER, "portals setup OK\n");
return 0;
- cleanup_crypto:
- cfs_crypto_unregister();
cleanup_wi:
cfs_wi_shutdown();
cleanup_deregister:
@@ -454,10 +412,7 @@
{
int rc;
- remove_proc();
-
- CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
- atomic_read(&libcfs_kmemory));
+ remove_debugfs();
if (cfs_sched_rehash != NULL) {
cfs_wi_sched_destroy(cfs_sched_rehash);
@@ -467,16 +422,10 @@
cfs_crypto_unregister();
cfs_wi_shutdown();
- rc = misc_deregister(&libcfs_dev);
- if (rc)
- CERROR("misc_deregister error %d\n", rc);
+ misc_deregister(&libcfs_dev);
cfs_cpu_fini();
- if (atomic_read(&libcfs_kmemory) != 0)
- CERROR("Portals memory leaked: %d bytes\n",
- atomic_read(&libcfs_kmemory));
-
rc = libcfs_debug_cleanup();
if (rc)
pr_err("LustreError: libcfs_debug_cleanup: %d\n", rc);
@@ -551,9 +500,6 @@
__proc_dobitmasks);
}
-static int min_watchdog_ratelimit; /* disable ratelimiting */
-static int max_watchdog_ratelimit = (24*60*60); /* limit to once per day */
-
static int __proc_dump_kernel(void *data, int write,
loff_t pos, void __user *buffer, int nob)
{
@@ -593,125 +539,6 @@
__proc_daemon_file);
}
-static int __proc_debug_mb(void *data, int write,
- loff_t pos, void __user *buffer, int nob)
-{
- if (!write) {
- char tmpstr[32];
- int len = snprintf(tmpstr, sizeof(tmpstr), "%d",
- cfs_trace_get_debug_mb());
-
- if (pos >= len)
- return 0;
-
- return cfs_trace_copyout_string(buffer, nob, tmpstr + pos,
- "\n");
- }
-
- return cfs_trace_set_debug_mb_usrstr(buffer, nob);
-}
-
-static int proc_debug_mb(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- return proc_call_handler(table->data, write, ppos, buffer, lenp,
- __proc_debug_mb);
-}
-
-static int proc_console_max_delay_cs(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp,
- loff_t *ppos)
-{
- int rc, max_delay_cs;
- struct ctl_table dummy = *table;
- long d;
-
- dummy.data = &max_delay_cs;
- dummy.proc_handler = &proc_dointvec;
-
- if (!write) { /* read */
- max_delay_cs = cfs_duration_sec(libcfs_console_max_delay * 100);
- rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
- return rc;
- }
-
- /* write */
- max_delay_cs = 0;
- rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
- if (rc < 0)
- return rc;
- if (max_delay_cs <= 0)
- return -EINVAL;
-
- d = cfs_time_seconds(max_delay_cs) / 100;
- if (d == 0 || d < libcfs_console_min_delay)
- return -EINVAL;
- libcfs_console_max_delay = d;
-
- return rc;
-}
-
-static int proc_console_min_delay_cs(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp,
- loff_t *ppos)
-{
- int rc, min_delay_cs;
- struct ctl_table dummy = *table;
- long d;
-
- dummy.data = &min_delay_cs;
- dummy.proc_handler = &proc_dointvec;
-
- if (!write) { /* read */
- min_delay_cs = cfs_duration_sec(libcfs_console_min_delay * 100);
- rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
- return rc;
- }
-
- /* write */
- min_delay_cs = 0;
- rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
- if (rc < 0)
- return rc;
- if (min_delay_cs <= 0)
- return -EINVAL;
-
- d = cfs_time_seconds(min_delay_cs) / 100;
- if (d == 0 || d > libcfs_console_max_delay)
- return -EINVAL;
- libcfs_console_min_delay = d;
-
- return rc;
-}
-
-static int proc_console_backoff(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- int rc, backoff;
- struct ctl_table dummy = *table;
-
- dummy.data = &backoff;
- dummy.proc_handler = &proc_dointvec;
-
- if (!write) { /* read */
- backoff = libcfs_console_backoff;
- rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
- return rc;
- }
-
- /* write */
- backoff = 0;
- rc = proc_dointvec(&dummy, write, buffer, lenp, ppos);
- if (rc < 0)
- return rc;
- if (backoff <= 0)
- return -EINVAL;
-
- libcfs_console_backoff = backoff;
-
- return rc;
-}
-
static int libcfs_force_lbug(struct ctl_table *table, int write,
void __user *buffer,
size_t *lenp, loff_t *ppos)
@@ -809,40 +636,6 @@
.proc_handler = &proc_dobitmasks,
},
{
- .procname = "console_ratelimit",
- .data = &libcfs_console_ratelimit,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .procname = "console_max_delay_centisecs",
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_console_max_delay_cs
- },
- {
- .procname = "console_min_delay_centisecs",
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_console_min_delay_cs
- },
- {
- .procname = "console_backoff",
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_console_backoff
- },
-
- {
- .procname = "debug_path",
- .data = libcfs_debug_file_path_arr,
- .maxlen = sizeof(libcfs_debug_file_path_arr),
- .mode = 0644,
- .proc_handler = &proc_dostring,
- },
-
- {
.procname = "cpu_partition_table",
.maxlen = 128,
.mode = 0444,
@@ -864,13 +657,6 @@
.proc_handler = &proc_dostring,
},
{
- .procname = "lnet_memused",
- .data = (int *)&libcfs_kmemory.counter,
- .maxlen = sizeof(int),
- .mode = 0444,
- .proc_handler = &proc_dointvec,
- },
- {
.procname = "catastrophe",
.data = &libcfs_catastrophe,
.maxlen = sizeof(int),
@@ -878,13 +664,6 @@
.proc_handler = &proc_dointvec,
},
{
- .procname = "panic_on_lbug",
- .data = &libcfs_panic_on_lbug,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
.procname = "dump_kernel",
.maxlen = 256,
.mode = 0200,
@@ -897,20 +676,6 @@
.proc_handler = &proc_daemon_file,
},
{
- .procname = "debug_mb",
- .mode = 0644,
- .proc_handler = &proc_debug_mb,
- },
- {
- .procname = "watchdog_ratelimit",
- .data = &libcfs_watchdog_ratelimit,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec_minmax,
- .extra1 = &min_watchdog_ratelimit,
- .extra2 = &max_watchdog_ratelimit,
- },
- {
.procname = "force_lbug",
.data = NULL,
.maxlen = 0,
@@ -935,31 +700,93 @@
}
};
-static struct ctl_table top_table[] = {
- {
- .procname = "lnet",
- .mode = 0555,
- .data = NULL,
- .maxlen = 0,
- .child = lnet_table,
- },
- {
- }
+struct lnet_debugfs_symlink_def {
+ char *name;
+ char *target;
};
-static int insert_proc(void)
+static const struct lnet_debugfs_symlink_def lnet_debugfs_symlinks[] = {
+ { "console_ratelimit",
+ "/sys/module/libcfs/parameters/libcfs_console_ratelimit"},
+ { "debug_path",
+ "/sys/module/libcfs/parameters/libcfs_debug_file_path"},
+ { "panic_on_lbug",
+ "/sys/module/libcfs/parameters/libcfs_panic_on_lbug"},
+ { "libcfs_console_backoff",
+ "/sys/module/libcfs/parameters/libcfs_console_backoff"},
+ { "debug_mb",
+ "/sys/module/libcfs/parameters/libcfs_debug_mb"},
+ { "console_min_delay_centisecs",
+ "/sys/module/libcfs/parameters/libcfs_console_min_delay"},
+ { "console_max_delay_centisecs",
+ "/sys/module/libcfs/parameters/libcfs_console_max_delay"},
+ {},
+};
+
+static ssize_t lnet_debugfs_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *ppos)
{
- if (lnet_table_header == NULL)
- lnet_table_header = register_sysctl_table(top_table);
- return 0;
+ struct ctl_table *table = filp->private_data;
+ int error;
+
+ error = table->proc_handler(table, 0, (void __user *)buf, &count, ppos);
+ if (!error)
+ error = count;
+
+ return error;
}
-static void remove_proc(void)
+static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *ppos)
{
- if (lnet_table_header != NULL)
- unregister_sysctl_table(lnet_table_header);
+ struct ctl_table *table = filp->private_data;
+ int error;
- lnet_table_header = NULL;
+ error = table->proc_handler(table, 1, (void __user *)buf, &count, ppos);
+ if (!error)
+ error = count;
+
+ return error;
+}
+
+static const struct file_operations lnet_debugfs_file_operations = {
+ .open = simple_open,
+ .read = lnet_debugfs_read,
+ .write = lnet_debugfs_write,
+ .llseek = default_llseek,
+};
+
+static void insert_debugfs(void)
+{
+ struct ctl_table *table;
+ struct dentry *entry;
+ const struct lnet_debugfs_symlink_def *symlinks;
+
+ if (lnet_debugfs_root == NULL)
+ lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
+
+ /* Even if we cannot create, just ignore it altogether) */
+ if (IS_ERR_OR_NULL(lnet_debugfs_root))
+ return;
+
+ for (table = lnet_table; table->procname; table++)
+ entry = debugfs_create_file(table->procname, table->mode,
+ lnet_debugfs_root, table,
+ &lnet_debugfs_file_operations);
+
+ for (symlinks = lnet_debugfs_symlinks; symlinks->name; symlinks++)
+ entry = debugfs_create_symlink(symlinks->name,
+ lnet_debugfs_root,
+ symlinks->target);
+
+}
+
+static void remove_debugfs(void)
+{
+ if (lnet_debugfs_root != NULL)
+ debugfs_remove_recursive(lnet_debugfs_root);
+
+ lnet_debugfs_root = NULL;
}
MODULE_VERSION("1.0.0");
diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.c b/drivers/staging/lustre/lustre/libcfs/tracefile.c
index 6ee2adc..effa2af 100644
--- a/drivers/staging/lustre/lustre/libcfs/tracefile.c
+++ b/drivers/staging/lustre/lustre/libcfs/tracefile.c
@@ -937,18 +937,6 @@
return 0;
}
-int cfs_trace_set_debug_mb_usrstr(void __user *usr_str, int usr_str_nob)
-{
- char str[32];
- int rc;
-
- rc = cfs_trace_copyin_string(str, sizeof(str), usr_str, usr_str_nob);
- if (rc < 0)
- return rc;
-
- return cfs_trace_set_debug_mb(simple_strtoul(str, NULL, 0));
-}
-
int cfs_trace_get_debug_mb(void)
{
int i;
diff --git a/drivers/staging/lustre/lustre/libcfs/tracefile.h b/drivers/staging/lustre/lustre/libcfs/tracefile.h
index 0601476..e931f6d 100644
--- a/drivers/staging/lustre/lustre/libcfs/tracefile.h
+++ b/drivers/staging/lustre/lustre/libcfs/tracefile.h
@@ -47,7 +47,7 @@
extern char cfs_tracefile[TRACEFILE_NAME_SIZE];
extern long long cfs_tracefile_size;
-extern void libcfs_run_debug_log_upcall(char *file);
+void libcfs_run_debug_log_upcall(char *file);
int cfs_tracefile_init_arch(void);
void cfs_tracefile_fini_arch(void);
@@ -77,14 +77,13 @@
int cfs_trace_daemon_command(char *str);
int cfs_trace_daemon_command_usrstr(void __user *usr_str, int usr_str_nob);
int cfs_trace_set_debug_mb(int mb);
-int cfs_trace_set_debug_mb_usrstr(void __user *usr_str, int usr_str_nob);
int cfs_trace_get_debug_mb(void);
-extern void libcfs_debug_dumplog_internal(void *arg);
-extern void libcfs_register_panic_notifier(void);
-extern void libcfs_unregister_panic_notifier(void);
+void libcfs_debug_dumplog_internal(void *arg);
+void libcfs_register_panic_notifier(void);
+void libcfs_unregister_panic_notifier(void);
extern int libcfs_panic_in_progress;
-extern int cfs_trace_max_debug_mb(void);
+int cfs_trace_max_debug_mb(void);
#define TCD_MAX_PAGES (5 << (20 - PAGE_CACHE_SHIFT))
#define TCD_STOCK_PAGES (TCD_MAX_PAGES)
@@ -253,15 +252,15 @@
unsigned short type;
};
-extern void cfs_set_ptldebug_header(struct ptldebug_header *header,
- struct libcfs_debug_msg_data *m,
- unsigned long stack);
-extern void cfs_print_to_console(struct ptldebug_header *hdr, int mask,
- const char *buf, int len, const char *file,
- const char *fn);
+void cfs_set_ptldebug_header(struct ptldebug_header *header,
+ struct libcfs_debug_msg_data *m,
+ unsigned long stack);
+void cfs_print_to_console(struct ptldebug_header *hdr, int mask,
+ const char *buf, int len, const char *file,
+ const char *fn);
-extern int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking);
-extern void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking);
+int cfs_trace_lock_tcd(struct cfs_trace_cpu_data *tcd, int walking);
+void cfs_trace_unlock_tcd(struct cfs_trace_cpu_data *tcd, int walking);
/**
* trace_buf_type_t, trace_buf_idx_get() and trace_console_buffers[][]
@@ -271,7 +270,7 @@
*/
extern char *cfs_trace_console_buffers[NR_CPUS][CFS_TCD_TYPE_MAX];
-extern cfs_trace_buf_type_t cfs_trace_buf_idx_get(void);
+cfs_trace_buf_type_t cfs_trace_buf_idx_get(void);
static inline char *
cfs_trace_get_console_buffer(void)
@@ -314,8 +313,8 @@
int cfs_tcd_owns_tage(struct cfs_trace_cpu_data *tcd,
struct cfs_trace_page *tage);
-extern void cfs_trace_assertion_failed(const char *str,
- struct libcfs_debug_msg_data *m);
+void cfs_trace_assertion_failed(const char *str,
+ struct libcfs_debug_msg_data *m);
/* ASSERTION that is safe to use within the debug system */
#define __LASSERT(cond) \
diff --git a/drivers/staging/lustre/lustre/llite/dcache.c b/drivers/staging/lustre/lustre/llite/dcache.c
index 7b008a6..b866859 100644
--- a/drivers/staging/lustre/lustre/llite/dcache.c
+++ b/drivers/staging/lustre/lustre/llite/dcache.c
@@ -250,7 +250,6 @@
void ll_invalidate_aliases(struct inode *inode)
{
struct dentry *dentry;
- struct ll_d_hlist_node *p;
LASSERT(inode != NULL);
@@ -258,7 +257,7 @@
inode->i_ino, inode->i_generation, inode);
ll_lock_dcache(inode);
- ll_d_hlist_for_each_entry(dentry, p, &inode->i_dentry, d_u.d_alias) {
+ hlist_for_each_entry(dentry, &inode->i_dentry, d_u.d_alias) {
CDEBUG(D_DENTRY, "dentry in drop %pd (%p) parent %p inode %p flags %d\n",
dentry, dentry, dentry->d_parent,
d_inode(dentry), dentry->d_flags);
diff --git a/drivers/staging/lustre/lustre/llite/dir.c b/drivers/staging/lustre/lustre/llite/dir.c
index 3d746a9..769b611 100644
--- a/drivers/staging/lustre/lustre/llite/dir.c
+++ b/drivers/staging/lustre/lustre/llite/dir.c
@@ -203,7 +203,6 @@
CDEBUG(D_VFSTRACE, "read %d/%d pages\n", nrdpgs, npages);
- ll_pagevec_init(&lru_pvec, 0);
for (i = 1; i < npages; i++) {
unsigned long offset;
int ret;
@@ -228,15 +227,12 @@
GFP_KERNEL);
if (ret == 0) {
unlock_page(page);
- if (ll_pagevec_add(&lru_pvec, page) == 0)
- ll_pagevec_lru_add_file(&lru_pvec);
} else {
CDEBUG(D_VFSTRACE, "page %lu add to page cache failed: %d\n",
offset, ret);
}
page_cache_release(page);
}
- ll_pagevec_lru_add_file(&lru_pvec);
if (page_pool != &page0)
kfree(page_pool);
diff --git a/drivers/staging/lustre/lustre/llite/file.c b/drivers/staging/lustre/lustre/llite/file.c
index 3075db2..dcd0c6d 100644
--- a/drivers/staging/lustre/lustre/llite/file.c
+++ b/drivers/staging/lustre/lustre/llite/file.c
@@ -702,8 +702,7 @@
out_openerr:
if (opendir_set != 0)
ll_stop_statahead(inode, lli->lli_opendir_key);
- if (fd != NULL)
- ll_file_data_put(fd);
+ ll_file_data_put(fd);
} else {
ll_stats_ops_tally(ll_i2sbi(inode), LPROC_LL_OPEN, 1);
}
@@ -3005,7 +3004,7 @@
struct inode *inode = d_inode(de);
struct ll_sb_info *sbi = ll_i2sbi(inode);
struct ll_inode_info *lli = ll_i2info(inode);
- int res = 0;
+ int res;
res = ll_inode_revalidate(de, MDS_INODELOCK_UPDATE |
MDS_INODELOCK_LOOKUP);
diff --git a/drivers/staging/lustre/lustre/llite/llite_capa.c b/drivers/staging/lustre/lustre/llite/llite_capa.c
index a626871..24590ae 100644
--- a/drivers/staging/lustre/lustre/llite/llite_capa.c
+++ b/drivers/staging/lustre/lustre/llite/llite_capa.c
@@ -70,7 +70,8 @@
static int ll_update_capa(struct obd_capa *ocapa, struct lustre_capa *capa);
-static inline void update_capa_timer(struct obd_capa *ocapa, unsigned long expiry)
+static inline void update_capa_timer(struct obd_capa *ocapa,
+ unsigned long expiry)
{
if (time_before(expiry, ll_capa_timer.expires) ||
!timer_pending(&ll_capa_timer)) {
@@ -102,13 +103,13 @@
spin_lock(&capa_lock);
if (!list_empty(ll_capa_list)) {
ocapa = list_entry(ll_capa_list->next, struct obd_capa,
- c_list);
+ c_list);
expired = capa_is_to_expire(ocapa);
if (!expired)
update_capa_timer(ocapa, capa_renewal_time(ocapa));
} else if (!list_empty(&ll_idle_capas)) {
ocapa = list_entry(ll_idle_capas.next, struct obd_capa,
- c_list);
+ c_list);
expired = capa_is_expired(ocapa);
if (!expired)
update_capa_timer(ocapa, ocapa->c_expiry);
@@ -165,7 +166,8 @@
/* three places where client capa is deleted:
* 1. capa_thread_main(), main place to delete expired capa.
* 2. ll_clear_inode_capas() in ll_clear_inode().
- * 3. ll_truncate_free_capa() delete truncate capa explicitly in ll_setattr_ost().
+ * 3. ll_truncate_free_capa() delete truncate capa explicitly in
+ * ll_setattr_ost().
*/
static int capa_thread_main(void *unused)
{
@@ -206,7 +208,8 @@
* lock.
*/
/* ibits may be changed by ll_have_md_lock() so we have
- * to set it each time */
+ * to set it each time
+ */
ibits = MDS_INODELOCK_LOOKUP;
if (capa_for_mds(&ocapa->c_capa) &&
!S_ISDIR(ocapa->u.cli.inode->i_mode) &&
@@ -225,14 +228,15 @@
if (capa_for_oss(&ocapa->c_capa) &&
obd_capa_open_count(ocapa) == 0) {
/* oss capa with open count == 0 won't renew,
- * move to idle list */
+ * move to idle list
+ */
sort_add_capa(ocapa, &ll_idle_capas);
continue;
}
/* NB iput() is in ll_update_capa() */
inode = igrab(ocapa->u.cli.inode);
- if (inode == NULL) {
+ if (!inode) {
DEBUG_CAPA(D_ERROR, &ocapa->c_capa,
"igrab failed for");
continue;
@@ -255,7 +259,7 @@
update_capa_timer(next, capa_renewal_time(next));
list_for_each_entry_safe(ocapa, tmp, &ll_idle_capas,
- c_list) {
+ c_list) {
if (!capa_is_expired(ocapa)) {
if (!next)
update_capa_timer(ocapa,
@@ -299,11 +303,11 @@
task = kthread_run(capa_thread_main, NULL, "ll_capa");
if (IS_ERR(task)) {
CERROR("cannot start expired capa thread: rc %ld\n",
- PTR_ERR(task));
+ PTR_ERR(task));
return PTR_ERR(task);
}
wait_event(ll_capa_thread.t_ctl_waitq,
- thread_is_running(&ll_capa_thread));
+ thread_is_running(&ll_capa_thread));
return 0;
}
@@ -313,7 +317,7 @@
thread_set_flags(&ll_capa_thread, SVC_STOPPING);
wake_up(&ll_capa_thread.t_ctl_waitq);
wait_event(ll_capa_thread.t_ctl_waitq,
- thread_is_stopped(&ll_capa_thread));
+ thread_is_stopped(&ll_capa_thread));
}
struct obd_capa *ll_osscapa_get(struct inode *inode, __u64 opc)
@@ -360,7 +364,7 @@
ocapa = NULL;
if (atomic_read(&ll_capa_debug)) {
- CERROR("no capability for "DFID" opc %#llx\n",
+ CERROR("no capability for " DFID " opc %#llx\n",
PFID(&lli->lli_fid), opc);
atomic_set(&ll_capa_debug, 0);
}
@@ -376,7 +380,7 @@
struct ll_inode_info *lli = ll_i2info(inode);
struct obd_capa *ocapa;
- LASSERT(inode != NULL);
+ LASSERT(inode);
if ((ll_i2sbi(inode)->ll_flags & LL_SBI_MDS_CAPA) == 0)
return NULL;
@@ -385,7 +389,7 @@
ocapa = capa_get(lli->lli_mds_capa);
spin_unlock(&capa_lock);
if (!ocapa && atomic_read(&ll_capa_debug)) {
- CERROR("no mds capability for "DFID"\n", PFID(&lli->lli_fid));
+ CERROR("no mds capability for " DFID "\n", PFID(&lli->lli_fid));
atomic_set(&ll_capa_debug, 0);
}
@@ -447,7 +451,8 @@
struct list_head *next = NULL;
/* capa is sorted in lli_oss_capas so lookup can always find the
- * latest one */
+ * latest one
+ */
list_for_each_entry(tmp, &lli->lli_oss_capas, u.cli.lli_list) {
if (cfs_time_after(ocapa->c_expiry, tmp->c_expiry)) {
next = &tmp->u.cli.lli_list;
@@ -537,7 +542,8 @@
ll_capa_renewal_failed++;
/* failed capa won't be renewed any longer, but if -EIO,
- * client might be doing recovery, retry in 2 min. */
+ * client might be doing recovery, retry in 2 min.
+ */
if (rc == -EIO && !capa_is_expired(ocapa)) {
delay_capa_renew(ocapa, 120);
DEBUG_CAPA(D_ERROR, &ocapa->c_capa,
@@ -638,7 +644,7 @@
ll_delete_capa(ocapa);
list_for_each_entry_safe(ocapa, tmp, &lli->lli_oss_capas,
- u.cli.lli_list)
+ u.cli.lli_list)
ll_delete_capa(ocapa);
spin_unlock(&capa_lock);
}
diff --git a/drivers/staging/lustre/lustre/llite/llite_internal.h b/drivers/staging/lustre/lustre/llite/llite_internal.h
index f097d4d..ec8fff4 100644
--- a/drivers/staging/lustre/lustre/llite/llite_internal.h
+++ b/drivers/staging/lustre/lustre/llite/llite_internal.h
@@ -456,7 +456,6 @@
};
struct ll_sb_info {
- struct list_head ll_list;
/* this protects pglist and ra_info. It isn't safe to
* grab from interrupt contexts */
spinlock_t ll_lock;
@@ -711,11 +710,11 @@
extern struct file_operations ll_file_operations_flock;
extern struct file_operations ll_file_operations_noflock;
extern struct inode_operations ll_file_inode_operations;
-extern int ll_have_md_lock(struct inode *inode, __u64 *bits,
- ldlm_mode_t l_req_mode);
-extern ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits,
- struct lustre_handle *lockh, __u64 flags,
- ldlm_mode_t mode);
+int ll_have_md_lock(struct inode *inode, __u64 *bits,
+ ldlm_mode_t l_req_mode);
+ldlm_mode_t ll_take_md_lock(struct inode *inode, __u64 bits,
+ struct lustre_handle *lockh, __u64 flags,
+ ldlm_mode_t mode);
int ll_file_open(struct inode *inode, struct file *file);
int ll_file_release(struct inode *inode, struct file *file);
int ll_glimpse_ioctl(struct ll_sb_info *sbi,
@@ -1376,9 +1375,9 @@
ll_stats_ops_tally(ll_s2sbi(cl2ccc_dev(dev)->cdv_sb), opc, rc);
}
-extern ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
- int rw, struct inode *inode,
- struct ll_dio_pages *pv);
+ssize_t ll_direct_rw_pages(const struct lu_env *env, struct cl_io *io,
+ int rw, struct inode *inode,
+ struct ll_dio_pages *pv);
static inline int ll_file_nolock(const struct file *file)
{
diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c
index 2513988..b4ed6c8 100644
--- a/drivers/staging/lustre/lustre/llite/llite_lib.c
+++ b/drivers/staging/lustre/lustre/llite/llite_lib.c
@@ -60,9 +60,6 @@
struct dentry *llite_root;
struct kset *llite_kset;
-static LIST_HEAD(ll_super_blocks);
-static DEFINE_SPINLOCK(ll_sb_lock);
-
#ifndef log2
#define log2(n) ffz(~(n))
#endif
@@ -112,10 +109,6 @@
class_uuid_unparse(uuid, &sbi->ll_sb_uuid);
CDEBUG(D_CONFIG, "generated uuid: %s\n", sbi->ll_sb_uuid.uuid);
- spin_lock(&ll_sb_lock);
- list_add_tail(&sbi->ll_list, &ll_super_blocks);
- spin_unlock(&ll_sb_lock);
-
sbi->ll_flags |= LL_SBI_VERBOSE;
sbi->ll_flags |= LL_SBI_CHECKSUM;
@@ -144,12 +137,7 @@
{
struct ll_sb_info *sbi = ll_s2sbi(sb);
- if (sbi != NULL) {
- spin_lock(&ll_sb_lock);
- list_del(&sbi->ll_list);
- spin_unlock(&ll_sb_lock);
- kfree(sbi);
- }
+ kfree(sbi);
}
static int client_common_fill_super(struct super_block *sb, char *md, char *dt,
@@ -1114,7 +1102,7 @@
if (lli->lli_mds_read_och)
ll_md_real_close(inode, FMODE_READ);
- if (S_ISLNK(inode->i_mode) && lli->lli_symlink_name) {
+ if (S_ISLNK(inode->i_mode)) {
kfree(lli->lli_symlink_name);
lli->lli_symlink_name = NULL;
}
@@ -1150,6 +1138,8 @@
lli->lli_has_smd = false;
}
+#define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)
+
static int ll_md_setattr(struct dentry *dentry, struct md_op_data *op_data,
struct md_open_data **mod)
{
@@ -1354,11 +1344,8 @@
if (!op_data)
return -ENOMEM;
- if (!S_ISDIR(inode->i_mode)) {
- if (attr->ia_valid & ATTR_SIZE)
- inode_dio_write_done(inode);
+ if (!S_ISDIR(inode->i_mode))
mutex_unlock(&inode->i_mutex);
- }
memcpy(&op_data->op_attr, attr, sizeof(*attr));
diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c
index cc00fd1..06f5e51 100644
--- a/drivers/staging/lustre/lustre/llite/lloop.c
+++ b/drivers/staging/lustre/lustre/llite/lloop.c
@@ -162,7 +162,7 @@
static struct lloop_device *loop_dev;
static struct gendisk **disks;
static struct mutex lloop_mutex;
-static void *ll_iocontrol_magic = NULL;
+static void *ll_iocontrol_magic;
static loff_t get_loop_size(struct lloop_device *lo, struct file *file)
{
@@ -365,7 +365,7 @@
loop_add_bio(lo, old_bio);
return;
err:
- cfs_bio_io_error(old_bio, old_bio->bi_iter.bi_size);
+ bio_io_error(old_bio);
}
@@ -376,7 +376,7 @@
while (bio) {
struct bio *tmp = bio->bi_next;
bio->bi_next = NULL;
- cfs_bio_endio(bio, bio->bi_iter.bi_size, ret);
+ bio_endio(bio, ret);
bio = tmp;
}
}
diff --git a/drivers/staging/lustre/lustre/llite/namei.c b/drivers/staging/lustre/lustre/llite/namei.c
index 72ce6e7..05e7dc8 100644
--- a/drivers/staging/lustre/lustre/llite/namei.c
+++ b/drivers/staging/lustre/lustre/llite/namei.c
@@ -144,10 +144,9 @@
static void ll_invalidate_negative_children(struct inode *dir)
{
struct dentry *dentry, *tmp_subdir;
- struct ll_d_hlist_node *p;
ll_lock_dcache(dir);
- ll_d_hlist_for_each_entry(dentry, p, &dir->i_dentry, d_u.d_alias) {
+ hlist_for_each_entry(dentry, &dir->i_dentry, d_u.d_alias) {
spin_lock(&dentry->d_lock);
if (!list_empty(&dentry->d_subdirs)) {
struct dentry *child;
@@ -334,15 +333,14 @@
static struct dentry *ll_find_alias(struct inode *inode, struct dentry *dentry)
{
struct dentry *alias, *discon_alias, *invalid_alias;
- struct ll_d_hlist_node *p;
- if (ll_d_hlist_empty(&inode->i_dentry))
+ if (hlist_empty(&inode->i_dentry))
return NULL;
discon_alias = invalid_alias = NULL;
ll_lock_dcache(inode);
- ll_d_hlist_for_each_entry(alias, p, &inode->i_dentry, d_u.d_alias) {
+ hlist_for_each_entry(alias, &inode->i_dentry, d_u.d_alias) {
LASSERT(alias != dentry);
spin_lock(&alias->d_lock);
@@ -690,7 +688,7 @@
goto out;
}
- LASSERT(ll_d_hlist_empty(&inode->i_dentry));
+ LASSERT(hlist_empty(&inode->i_dentry));
/* We asked for a lock on the directory, but were granted a
* lock on the inode. Since we finally have an inode pointer,
@@ -1008,7 +1006,7 @@
return rc;
}
-static int ll_mkdir(struct inode *dir, struct dentry *dentry, ll_umode_t mode)
+static int ll_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
{
int err;
diff --git a/drivers/staging/lustre/lustre/llite/remote_perm.c b/drivers/staging/lustre/lustre/llite/remote_perm.c
index a581826..39022ea 100644
--- a/drivers/staging/lustre/lustre/llite/remote_perm.c
+++ b/drivers/staging/lustre/lustre/llite/remote_perm.c
@@ -54,8 +54,8 @@
#include "../include/lustre_param.h"
#include "llite_internal.h"
-struct kmem_cache *ll_remote_perm_cachep = NULL;
-struct kmem_cache *ll_rmtperm_hash_cachep = NULL;
+struct kmem_cache *ll_remote_perm_cachep;
+struct kmem_cache *ll_rmtperm_hash_cachep;
static inline struct ll_remote_perm *alloc_ll_remote_perm(void)
{
@@ -104,8 +104,7 @@
return;
for (i = 0; i < REMOTE_PERM_HASHSIZE; i++)
- hlist_for_each_entry_safe(lrp, next, hash + i,
- lrp_list)
+ hlist_for_each_entry_safe(lrp, next, hash + i, lrp_list)
free_ll_remote_perm(lrp);
OBD_SLAB_FREE(hash, ll_rmtperm_hash_cachep,
REMOTE_PERM_HASHSIZE * sizeof(*hash));
@@ -117,7 +116,8 @@
}
/* NB: setxid permission is not checked here, instead it's done on
- * MDT when client get remote permission. */
+ * MDT when client get remote permission.
+ */
static int do_check_remote_perm(struct ll_inode_info *lli, int mask)
{
struct hlist_head *head;
@@ -184,7 +184,7 @@
if (!lli->lli_remote_perms) {
perm_hash = alloc_rmtperm_hash();
- if (perm_hash == NULL) {
+ if (!perm_hash) {
CERROR("alloc lli_remote_perms failed!\n");
return -ENOMEM;
}
@@ -287,7 +287,7 @@
perm = req_capsule_server_swab_get(&req->rq_pill, &RMF_ACL,
lustre_swab_mdt_remote_perm);
- if (unlikely(perm == NULL)) {
+ if (unlikely(!perm)) {
mutex_unlock(&lli->lli_rmtperm_mutex);
rc = -EPROTO;
break;
@@ -321,8 +321,7 @@
spin_lock(&lli->lli_lock);
for (i = 0; i < REMOTE_PERM_HASHSIZE; i++) {
- hlist_for_each_entry_safe(lrp, node, next, hash + i,
- lrp_list)
+ hlist_for_each_entry_safe(lrp, node, next, hash + i, lrp_list)
free_ll_remote_perm(lrp);
}
diff --git a/drivers/staging/lustre/lustre/llite/vvp_io.c b/drivers/staging/lustre/lustre/llite/vvp_io.c
index 91bba79..a659962 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_io.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_io.c
@@ -455,12 +455,11 @@
struct cl_io *io = ios->cis_io;
struct inode *inode = ccc_object_inode(io->ci_obj);
- if (cl_io_is_trunc(io)) {
+ if (cl_io_is_trunc(io))
/* Truncate in memory pages - they must be clean pages
* because osc has already notified to destroy osc_extents. */
vvp_do_vmtruncate(inode, io->u.ci_setattr.sa_attr.lvb_size);
- inode_dio_write_done(inode);
- }
+
mutex_unlock(&inode->i_mutex);
}
diff --git a/drivers/staging/lustre/lustre/llite/vvp_page.c b/drivers/staging/lustre/lustre/llite/vvp_page.c
index 954ed08..a3cf5ad 100644
--- a/drivers/staging/lustre/lustre/llite/vvp_page.c
+++ b/drivers/staging/lustre/lustre/llite/vvp_page.c
@@ -227,11 +227,16 @@
struct cl_io *unused)
{
struct page *vmpage = cl2vm_page(slice);
+ struct cl_page *pg = slice->cpl_page;
LASSERT(PageLocked(vmpage));
LASSERT(!PageDirty(vmpage));
- set_page_writeback(vmpage);
+ /* ll_writepage path is not a sync write, so need to set page writeback
+ * flag */
+ if (!pg->cp_sync_io)
+ set_page_writeback(vmpage);
+
vvp_write_pending(cl2ccc(slice->cpl_obj), cl2ccc_page(slice));
return 0;
@@ -298,9 +303,6 @@
struct cl_page *pg = slice->cpl_page;
struct page *vmpage = cp->cpg_page;
- LASSERT(ergo(pg->cp_sync_io != NULL, PageLocked(vmpage)));
- LASSERT(PageWriteback(vmpage));
-
CL_PAGE_HEADER(D_PAGE, env, pg, "completing WRITE with %d\n", ioret);
/*
@@ -316,14 +318,19 @@
cp->cpg_write_queued = 0;
vvp_write_complete(cl2ccc(slice->cpl_obj), cp);
- /*
- * Only mark the page error only when it's an async write because
- * applications won't wait for IO to finish.
- */
- if (pg->cp_sync_io == NULL)
+ if (pg->cp_sync_io != NULL) {
+ LASSERT(PageLocked(vmpage));
+ LASSERT(!PageWriteback(vmpage));
+ } else {
+ LASSERT(PageWriteback(vmpage));
+ /*
+ * Only mark the page error only when it's an async write
+ * because applications won't wait for IO to finish.
+ */
vvp_vmpage_error(ccc_object_inode(pg->cp_obj), vmpage, ioret);
- end_page_writeback(vmpage);
+ end_page_writeback(vmpage);
+ }
}
/**
diff --git a/drivers/staging/lustre/lustre/llite/xattr_cache.c b/drivers/staging/lustre/lustre/llite/xattr_cache.c
index 6956dec..9e763ce 100644
--- a/drivers/staging/lustre/lustre/llite/xattr_cache.c
+++ b/drivers/staging/lustre/lustre/llite/xattr_cache.c
@@ -357,7 +357,7 @@
struct ll_inode_info *lli = ll_i2info(inode);
struct mdt_body *body;
__u32 *xsizes;
- int rc = 0, i;
+ int rc, i;
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_intent.c b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
index cb35f63..eebe45b 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_intent.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_intent.c
@@ -100,7 +100,7 @@
}
op_data = kzalloc(sizeof(*op_data), GFP_NOFS);
- if (op_data == NULL) {
+ if (!op_data) {
rc = -ENOMEM;
goto out;
}
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
index ac5053c..c9e0536e 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
@@ -716,7 +716,7 @@
if (remote_gf == NULL) {
remote_gf_size = sizeof(*remote_gf) + PATH_MAX;
remote_gf = kzalloc(remote_gf_size, GFP_NOFS);
- if (remote_gf == NULL) {
+ if (!remote_gf) {
rc = -ENOMEM;
goto out_fid2path;
}
@@ -1398,7 +1398,7 @@
return rc;
temp = kzalloc(sizeof(*temp), GFP_NOFS);
- if (temp == NULL)
+ if (!temp)
return -ENOMEM;
for (i = 0; i < lmv->desc.ld_tgt_count; i++) {
@@ -1730,7 +1730,7 @@
}
rdata = kzalloc(sizeof(*rdata), GFP_NOFS);
- if (rdata == NULL) {
+ if (!rdata) {
rc = -ENOMEM;
goto out;
}
@@ -1993,7 +1993,7 @@
struct obd_device *obd = exp->exp_obd;
struct lmv_obd *lmv = &obd->u.lmv;
struct lmv_tgt_desc *tgt;
- int rc = 0;
+ int rc;
rc = lmv_check_connect(obd);
if (rc)
diff --git a/drivers/staging/lustre/lustre/lov/lov_dev.c b/drivers/staging/lustre/lustre/lov/lov_dev.c
index 504b24a..8c3bbe5 100644
--- a/drivers/staging/lustre/lustre/lov/lov_dev.c
+++ b/drivers/staging/lustre/lustre/lov/lov_dev.c
@@ -478,7 +478,7 @@
int rc;
ld = kzalloc(sizeof(*ld), GFP_NOFS);
- if (ld == NULL)
+ if (!ld)
return ERR_PTR(-ENOMEM);
cl_device_init(&ld->ld_cl, t);
diff --git a/drivers/staging/lustre/lustre/lov/lov_io.c b/drivers/staging/lustre/lustre/lov/lov_io.c
index 11c1081..bf36291 100644
--- a/drivers/staging/lustre/lustre/lov/lov_io.c
+++ b/drivers/staging/lustre/lustre/lov/lov_io.c
@@ -181,7 +181,7 @@
} else {
sub->sub_io = kzalloc(sizeof(*sub->sub_io),
GFP_NOFS);
- if (sub->sub_io == NULL)
+ if (!sub->sub_io)
result = -ENOMEM;
}
}
diff --git a/drivers/staging/lustre/lustre/lov/lov_merge.c b/drivers/staging/lustre/lustre/lov/lov_merge.c
index b7e7bfa..dd1cf3d 100644
--- a/drivers/staging/lustre/lustre/lov/lov_merge.c
+++ b/drivers/staging/lustre/lustre/lov/lov_merge.c
@@ -123,6 +123,7 @@
if (shrink) {
for (; stripe < lsm->lsm_stripe_count; stripe++) {
struct lov_oinfo *loi = lsm->lsm_oinfo[stripe];
+
kms = lov_size_to_stripe(lsm, size, stripe);
CDEBUG(D_INODE,
"stripe %d KMS %sing %llu->%llu\n",
diff --git a/drivers/staging/lustre/lustre/lov/lov_obd.c b/drivers/staging/lustre/lustre/lov/lov_obd.c
index 96c55ac..c5c67d9 100644
--- a/drivers/staging/lustre/lustre/lov/lov_obd.c
+++ b/drivers/staging/lustre/lustre/lov/lov_obd.c
@@ -107,6 +107,10 @@
/* Disconnect */
__lov_del_obd(obd, tgt);
}
+
+ if (lov->lov_tgts_kobj)
+ kobject_put(lov->lov_tgts_kobj);
+
} else {
mutex_unlock(&lov->lov_lock);
}
@@ -322,9 +326,6 @@
}
}
- if (lov->lov_tgts_kobj)
- kobject_put(lov->lov_tgts_kobj);
-
obd_putref(obd);
out:
@@ -976,7 +977,7 @@
src_oa->o_flags & OBD_FL_RECREATE_OBJS);
obj_mdp = kzalloc(sizeof(*obj_mdp), GFP_NOFS);
- if (obj_mdp == NULL)
+ if (!obj_mdp)
return -ENOMEM;
ost_idx = src_oa->o_nlink;
@@ -1439,7 +1440,7 @@
__u32 *genp;
len = 0;
- if (obd_ioctl_getdata(&buf, &len, (void *)uarg))
+ if (obd_ioctl_getdata(&buf, &len, uarg))
return -EINVAL;
data = (struct obd_ioctl_data *)buf;
@@ -1472,7 +1473,7 @@
*genp = lov->lov_tgts[i]->ltd_gen;
}
- if (copy_to_user((void *)uarg, buf, len))
+ if (copy_to_user(uarg, buf, len))
rc = -EFAULT;
obd_ioctl_freedata(buf, len);
break;
diff --git a/drivers/staging/lustre/lustre/lov/lov_pool.c b/drivers/staging/lustre/lustre/lov/lov_pool.c
index 1e4d3fb..c59b140 100644
--- a/drivers/staging/lustre/lustre/lov/lov_pool.c
+++ b/drivers/staging/lustre/lustre/lov/lov_pool.c
@@ -431,7 +431,7 @@
return -ENAMETOOLONG;
new_pool = kzalloc(sizeof(*new_pool), GFP_NOFS);
- if (new_pool == NULL)
+ if (!new_pool)
return -ENOMEM;
strncpy(new_pool->pool_name, poolname, LOV_MAXPOOLNAME);
diff --git a/drivers/staging/lustre/lustre/lov/lov_request.c b/drivers/staging/lustre/lustre/lov/lov_request.c
index f4de8b8..416e42e 100644
--- a/drivers/staging/lustre/lustre/lov/lov_request.c
+++ b/drivers/staging/lustre/lustre/lov/lov_request.c
@@ -275,7 +275,7 @@
int rc = 0, i;
set = kzalloc(sizeof(*set), GFP_NOFS);
- if (set == NULL)
+ if (!set)
return -ENOMEM;
lov_init_set(set);
@@ -301,7 +301,7 @@
}
req = kzalloc(sizeof(*req), GFP_NOFS);
- if (req == NULL) {
+ if (!req) {
rc = -ENOMEM;
goto out_set;
}
@@ -358,7 +358,7 @@
int rc = 0, i;
set = kzalloc(sizeof(*set), GFP_NOFS);
- if (set == NULL)
+ if (!set)
return -ENOMEM;
lov_init_set(set);
@@ -384,7 +384,7 @@
}
req = kzalloc(sizeof(*req), GFP_NOFS);
- if (req == NULL) {
+ if (!req) {
rc = -ENOMEM;
goto out_set;
}
@@ -477,7 +477,7 @@
int rc = 0, i;
set = kzalloc(sizeof(*set), GFP_NOFS);
- if (set == NULL)
+ if (!set)
return -ENOMEM;
lov_init_set(set);
@@ -500,7 +500,7 @@
}
req = kzalloc(sizeof(*req), GFP_NOFS);
- if (req == NULL) {
+ if (!req) {
rc = -ENOMEM;
goto out_set;
}
@@ -704,7 +704,7 @@
int rc = 0, i;
set = kzalloc(sizeof(*set), GFP_NOFS);
- if (set == NULL)
+ if (!set)
return -ENOMEM;
lov_init_set(set);
@@ -730,14 +730,14 @@
}
req = kzalloc(sizeof(*req), GFP_NOFS);
- if (req == NULL) {
+ if (!req) {
rc = -ENOMEM;
goto out_set;
}
req->rq_oi.oi_osfs = kzalloc(sizeof(*req->rq_oi.oi_osfs),
GFP_NOFS);
- if (req->rq_oi.oi_osfs == NULL) {
+ if (!req->rq_oi.oi_osfs) {
kfree(req);
rc = -ENOMEM;
goto out_set;
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_lib.c b/drivers/staging/lustre/lustre/mdc/mdc_lib.c
index d3234cb..1a850ea 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_lib.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_lib.c
@@ -286,7 +286,7 @@
sa_valid |= MDS_ATTR_KILL_SGID;
if (ia_valid & ATTR_CTIME_SET)
sa_valid |= MDS_ATTR_CTIME_SET;
- if (ia_valid & ATTR_FROM_OPEN)
+ if (ia_valid & ATTR_OPEN)
sa_valid |= MDS_ATTR_FROM_OPEN;
if (ia_valid & ATTR_BLOCKS)
sa_valid |= MDS_ATTR_BLOCKS;
diff --git a/drivers/staging/lustre/lustre/mdc/mdc_request.c b/drivers/staging/lustre/lustre/mdc/mdc_request.c
index 7f208a6..204d512 100644
--- a/drivers/staging/lustre/lustre/mdc/mdc_request.c
+++ b/drivers/staging/lustre/lustre/mdc/mdc_request.c
@@ -1202,7 +1202,7 @@
/* Key is KEY_FID2PATH + getinfo_fid2path description */
keylen = cfs_size_round(sizeof(KEY_FID2PATH)) + sizeof(*gf);
key = kzalloc(keylen, GFP_NOFS);
- if (key == NULL)
+ if (!key)
return -ENOMEM;
memcpy(key, KEY_FID2PATH, sizeof(KEY_FID2PATH));
memcpy(key + cfs_size_round(sizeof(KEY_FID2PATH)), gf, sizeof(*gf));
@@ -1605,7 +1605,7 @@
cs->cs_fp, cs->cs_startrec);
cs->cs_buf = kzalloc(KUC_CHANGELOG_MSG_MAXSIZE, GFP_NOFS);
- if (cs->cs_buf == NULL) {
+ if (!cs->cs_buf) {
rc = -ENOMEM;
goto out;
}
@@ -1934,7 +1934,7 @@
struct obd_quotactl *oqctl;
oqctl = kzalloc(sizeof(*oqctl), GFP_NOFS);
- if (oqctl == NULL) {
+ if (!oqctl) {
rc = -ENOMEM;
goto out;
}
diff --git a/drivers/staging/lustre/lustre/mgc/mgc_request.c b/drivers/staging/lustre/lustre/mgc/mgc_request.c
index 174dfc3..019ee2f 100644
--- a/drivers/staging/lustre/lustre/mgc/mgc_request.c
+++ b/drivers/staging/lustre/lustre/mgc/mgc_request.c
@@ -1128,7 +1128,7 @@
LASSERT(cfg->cfg_sb == cfg->cfg_instance);
inst = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
- if (inst == NULL)
+ if (!inst)
return -ENOMEM;
if (!IS_SERVER(lsi)) {
@@ -1232,7 +1232,7 @@
pos += sprintf(obdname + pos, "-%s%04x",
is_ost ? "OST" : "MDT", entry->mne_index);
- cname = is_ost ? "osc" : "mdc",
+ cname = is_ost ? "osc" : "mdc";
pos += sprintf(obdname + pos, "-%s-%s", cname, inst);
lustre_cfg_bufs_reset(&bufs, obdname);
@@ -1493,7 +1493,7 @@
lsi = s2lsi(cld->cld_cfg.cfg_sb);
env = kzalloc(sizeof(*env), GFP_NOFS);
- if (env == NULL)
+ if (!env)
return -ENOMEM;
rc = lu_env_init(env, LCT_MG_THREAD);
diff --git a/drivers/staging/lustre/lustre/obdclass/acl.c b/drivers/staging/lustre/lustre/obdclass/acl.c
index bc3fc47..933456c 100644
--- a/drivers/staging/lustre/lustre/obdclass/acl.c
+++ b/drivers/staging/lustre/lustre/obdclass/acl.c
@@ -104,11 +104,10 @@
if (unlikely(old_count <= new_count))
return old_size;
- new = kzalloc(new_size, GFP_NOFS);
+ new = kmemdup(*header, new_size, GFP_NOFS);
if (unlikely(new == NULL))
return -ENOMEM;
- memcpy(new, *header, new_size);
kfree(*header);
*header = new;
return new_size;
@@ -125,11 +124,10 @@
if (unlikely(old_count <= ext_count))
return 0;
- new = kzalloc(ext_size, GFP_NOFS);
+ new = kmemdup(*header, ext_size, GFP_NOFS);
if (unlikely(new == NULL))
return -ENOMEM;
- memcpy(new, *header, ext_size);
kfree(*header);
*header = new;
return 0;
diff --git a/drivers/staging/lustre/lustre/obdclass/cl_page.c b/drivers/staging/lustre/lustre/obdclass/cl_page.c
index a7f3032..d5fb81f 100644
--- a/drivers/staging/lustre/lustre/obdclass/cl_page.c
+++ b/drivers/staging/lustre/lustre/obdclass/cl_page.c
@@ -51,13 +51,13 @@
static void cl_page_delete0(const struct lu_env *env, struct cl_page *pg,
int radix);
-# define PASSERT(env, page, expr) \
- do { \
- if (unlikely(!(expr))) { \
- CL_PAGE_DEBUG(D_ERROR, (env), (page), #expr "\n"); \
- LASSERT(0); \
- } \
- } while (0)
+# define PASSERT(env, page, expr) \
+ do { \
+ if (unlikely(!(expr))) { \
+ CL_PAGE_DEBUG(D_ERROR, (env), (page), #expr "\n"); \
+ LASSERT(0); \
+ } \
+ } while (0)
# define PINVRNT(env, page, exp) \
((void)sizeof(env), (void)sizeof(page), (void)sizeof !!(exp))
@@ -169,6 +169,7 @@
while ((nr = radix_tree_gang_lookup(&hdr->coh_tree, (void **)pvec,
idx, CLT_PVEC_SIZE)) > 0) {
int end_of_region = 0;
+
idx = pvec[nr - 1]->cp_index + 1;
for (i = 0, j = 0; i < nr; ++i) {
page = pvec[i];
@@ -286,6 +287,7 @@
GFP_NOFS);
if (page != NULL) {
int result = 0;
+
atomic_set(&page->cp_ref, 1);
if (type == CPT_CACHEABLE) /* for radix tree */
atomic_inc(&page->cp_ref);
@@ -352,8 +354,10 @@
idx, PFID(&hdr->coh_lu.loh_fid), vmpage, vmpage->private, type);
/* fast path. */
if (type == CPT_CACHEABLE) {
- /* vmpage lock is used to protect the child/parent
- * relationship */
+ /*
+ * vmpage lock is used to protect the child/parent
+ * relationship
+ */
KLASSERT(PageLocked(vmpage));
/*
* cl_vmpage_page() can be called here without any locks as
@@ -372,9 +376,8 @@
idx) == page));
}
- if (page != NULL) {
+ if (page != NULL)
return page;
- }
/* allocate and initialize cl_page */
page = cl_page_alloc(env, o, idx, vmpage, type);
@@ -1189,9 +1192,6 @@
if (result == 0)
cl_page_io_start(env, pg, crt);
- KLASSERT(ergo(crt == CRT_WRITE && pg->cp_type == CPT_CACHEABLE,
- equi(result == 0,
- PageWriteback(cl_page_vmpage(env, pg)))));
CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", crt, result);
return result;
}
@@ -1425,7 +1425,7 @@
CL_PAGE_HEADER(D_TRACE, env, pg, "%d %d\n", from, to);
CL_PAGE_INVOID(env, pg, CL_PAGE_OP(cpo_clip),
(const struct lu_env *,
- const struct cl_page_slice *,int, int),
+ const struct cl_page_slice *, int, int),
from, to);
}
EXPORT_SYMBOL(cl_page_clip);
diff --git a/drivers/staging/lustre/lustre/obdclass/class_obd.c b/drivers/staging/lustre/lustre/obdclass/class_obd.c
index 1bc3756..2c705d7 100644
--- a/drivers/staging/lustre/lustre/obdclass/class_obd.c
+++ b/drivers/staging/lustre/lustre/obdclass/class_obd.c
@@ -78,12 +78,8 @@
EXPORT_SYMBOL(obd_dirty_pages);
unsigned int obd_timeout = OBD_TIMEOUT_DEFAULT; /* seconds */
EXPORT_SYMBOL(obd_timeout);
-unsigned int ldlm_timeout = LDLM_TIMEOUT_DEFAULT; /* seconds */
-EXPORT_SYMBOL(ldlm_timeout);
unsigned int obd_timeout_set;
EXPORT_SYMBOL(obd_timeout_set);
-unsigned int ldlm_timeout_set;
-EXPORT_SYMBOL(ldlm_timeout_set);
/* Adaptive timeout defs here instead of ptlrpc module for /proc/sys/ access */
unsigned int at_min = 0;
EXPORT_SYMBOL(at_min);
@@ -144,11 +140,11 @@
CERROR("%s%salloc of %s (%llu bytes) failed at %s:%d\n",
ptr ? "force " :"", type, name, (__u64)size, file,
line);
- CERROR("%llu total bytes and %llu total pages (%llu bytes) allocated by Lustre, %d total bytes by LNET\n",
+ CERROR("%llu total bytes and %llu total pages"
+ " (%llu bytes) allocated by Lustre\n",
obd_memory_sum(),
obd_pages_sum() << PAGE_CACHE_SHIFT,
- obd_pages_sum(),
- atomic_read(&libcfs_kmemory));
+ obd_pages_sum());
return 1;
}
return 0;
@@ -232,7 +228,7 @@
goto out;
}
lcfg = kzalloc(data->ioc_plen1, GFP_NOFS);
- if (lcfg == NULL) {
+ if (!lcfg) {
err = -ENOMEM;
goto out;
}
@@ -571,12 +567,14 @@
if (err)
return err;
- obd_sysctl_init();
-
err = class_procfs_init();
if (err)
return err;
+ err = obd_sysctl_init();
+ if (err)
+ return err;
+
err = lu_global_init();
if (err)
return err;
@@ -661,7 +659,6 @@
lu_global_fini();
obd_cleanup_caches();
- obd_sysctl_clean();
class_procfs_clean();
diff --git a/drivers/staging/lustre/lustre/obdclass/debug.c b/drivers/staging/lustre/lustre/obdclass/debug.c
index 9c934e6..c61add4 100644
--- a/drivers/staging/lustre/lustre/obdclass/debug.c
+++ b/drivers/staging/lustre/lustre/obdclass/debug.c
@@ -40,7 +40,7 @@
#define DEBUG_SUBSYSTEM D_OTHER
-#include <linux/unaligned/access_ok.h>
+#include <asm/unaligned.h>
#include "../include/obd_support.h"
#include "../include/lustre_debug.h"
diff --git a/drivers/staging/lustre/lustre/obdclass/genops.c b/drivers/staging/lustre/lustre/obdclass/genops.c
index 978c3c5..0ca73094 100644
--- a/drivers/staging/lustre/lustre/obdclass/genops.c
+++ b/drivers/staging/lustre/lustre/obdclass/genops.c
@@ -45,7 +45,7 @@
spinlock_t obd_types_lock;
-struct kmem_cache *obd_device_cachep;
+static struct kmem_cache *obd_device_cachep;
struct kmem_cache *obdo_cachep;
EXPORT_SYMBOL(obdo_cachep);
static struct kmem_cache *import_cachep;
@@ -71,9 +71,8 @@
struct obd_device *obd;
OBD_SLAB_ALLOC_PTR_GFP(obd, obd_device_cachep, GFP_NOFS);
- if (obd != NULL) {
+ if (obd != NULL)
obd->obd_magic = OBD_DEVICE_MAGIC;
- }
return obd;
}
@@ -172,7 +171,7 @@
rc = -ENOMEM;
type = kzalloc(sizeof(*type), GFP_NOFS);
- if (type == NULL)
+ if (!type)
return rc;
type->typ_dt_ops = kzalloc(sizeof(*type->typ_dt_ops), GFP_NOFS);
@@ -294,7 +293,7 @@
}
type = class_get_type(type_name);
- if (type == NULL){
+ if (type == NULL) {
CERROR("OBD: unknown type: %s\n", type_name);
return ERR_PTR(-ENODEV);
}
@@ -999,7 +998,8 @@
}
EXPORT_SYMBOL(class_import_put);
-static void init_imp_at(struct imp_at *at) {
+static void init_imp_at(struct imp_at *at)
+{
int i;
at_init(&at->iat_net_latency, 0, 0);
for (i = 0; i < IMP_AT_MAX_PORTALS; i++) {
@@ -1016,7 +1016,7 @@
struct obd_import *imp;
imp = kzalloc(sizeof(*imp), GFP_NOFS);
- if (imp == NULL)
+ if (!imp)
return NULL;
INIT_LIST_HEAD(&imp->imp_pinger_chain);
@@ -1642,7 +1642,8 @@
/**
* Add export to the obd_zombie thread and notify it.
*/
-static void obd_zombie_export_add(struct obd_export *exp) {
+static void obd_zombie_export_add(struct obd_export *exp)
+{
spin_lock(&exp->exp_obd->obd_dev_lock);
LASSERT(!list_empty(&exp->exp_obd_chain));
list_del_init(&exp->exp_obd_chain);
@@ -1658,7 +1659,8 @@
/**
* Add import to the obd_zombie thread and notify it.
*/
-static void obd_zombie_import_add(struct obd_import *imp) {
+static void obd_zombie_import_add(struct obd_import *imp)
+{
LASSERT(imp->imp_sec == NULL);
LASSERT(imp->imp_rq_pool == NULL);
spin_lock(&obd_zombie_impexp_lock);
@@ -1819,7 +1821,7 @@
int len = kuc_len(payload_len);
lh = kzalloc(len, GFP_NOFS);
- if (lh == NULL)
+ if (!lh)
return ERR_PTR(-ENOMEM);
lh->kuc_magic = KUC_MAGIC;
diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
index 84f75dc..6218ef3 100644
--- a/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
+++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-module.c
@@ -385,7 +385,7 @@
return 0;
}
-struct seq_operations obd_device_list_sops = {
+static const struct seq_operations obd_device_list_sops = {
.start = obd_device_list_seq_start,
.stop = obd_device_list_seq_stop,
.next = obd_device_list_seq_next,
@@ -406,7 +406,7 @@
return 0;
}
-struct file_operations obd_device_list_fops = {
+static const struct file_operations obd_device_list_fops = {
.owner = THIS_MODULE,
.open = obd_device_list_open,
.read = seq_read,
@@ -423,7 +423,7 @@
int class_procfs_init(void)
{
- int rc = 0;
+ int rc = -ENOMEM;
struct dentry *file;
lustre_kobj = kobject_create_and_add("lustre", fs_kobj);
diff --git a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
index 54f0a81..1515163 100644
--- a/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
+++ b/drivers/staging/lustre/lustre/obdclass/linux/linux-sysctl.c
@@ -50,331 +50,119 @@
#include "../../include/obd_support.h"
#include "../../include/lprocfs_status.h"
-#ifdef CONFIG_SYSCTL
-static struct ctl_table_header *obd_table_header;
-#endif
+struct static_lustre_uintvalue_attr {
+ struct {
+ struct attribute attr;
+ ssize_t (*show)(struct kobject *kobj, struct attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t len);
+ } u;
+ int *value;
+};
-#ifdef CONFIG_SYSCTL
-static int proc_set_timeout(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos)
+static ssize_t static_uintvalue_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct static_lustre_uintvalue_attr *lattr = (void *)attr;
+
+ return sprintf(buf, "%d\n", *lattr->value);
+}
+
+static ssize_t static_uintvalue_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct static_lustre_uintvalue_attr *lattr = (void *)attr;
+ int rc;
+ unsigned int val;
+
+ rc = kstrtouint(buffer, 10, &val);
+ if (rc)
+ return rc;
+
+ *lattr->value = val;
+
+ return count;
+}
+
+#define LUSTRE_STATIC_UINT_ATTR(name, value) \
+static struct static_lustre_uintvalue_attr lustre_sattr_##name = \
+ {__ATTR(name, 0644, \
+ static_uintvalue_show, \
+ static_uintvalue_store),\
+ value }
+
+LUSTRE_STATIC_UINT_ATTR(timeout, &obd_timeout);
+
+static ssize_t max_dirty_mb_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ return sprintf(buf, "%ul\n",
+ obd_max_dirty_pages / (1 << (20 - PAGE_CACHE_SHIFT)));
+}
+
+static ssize_t max_dirty_mb_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
{
int rc;
+ unsigned long val;
- rc = proc_dointvec(table, write, buffer, lenp, ppos);
- if (ldlm_timeout >= obd_timeout)
- ldlm_timeout = max(obd_timeout / 3, 1U);
- return rc;
-}
+ rc = kstrtoul(buffer, 10, &val);
+ if (rc)
+ return rc;
-static int proc_memory_alloc(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- char buf[22];
- int len;
+ val *= 1 << (20 - PAGE_CACHE_SHIFT); /* convert to pages */
- if (!*lenp || (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
- if (write)
+ if (val > ((totalram_pages / 10) * 9)) {
+ /* Somebody wants to assign too much memory to dirty pages */
return -EINVAL;
-
- len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_sum());
- if (len > *lenp)
- len = *lenp;
- buf[len] = '\0';
- if (copy_to_user(buffer, buf, len))
- return -EFAULT;
- *lenp = len;
- *ppos += *lenp;
- return 0;
-}
-
-static int proc_pages_alloc(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- char buf[22];
- int len;
-
- if (!*lenp || (*ppos && !write)) {
- *lenp = 0;
- return 0;
}
- if (write)
+
+ if (val < 4 << (20 - PAGE_CACHE_SHIFT)) {
+ /* Less than 4 Mb for dirty cache is also bad */
return -EINVAL;
+ }
- len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_sum());
- if (len > *lenp)
- len = *lenp;
- buf[len] = '\0';
- if (copy_to_user(buffer, buf, len))
- return -EFAULT;
- *lenp = len;
- *ppos += *lenp;
- return 0;
+ obd_max_dirty_pages = val;
+
+ return count;
}
+LUSTRE_RW_ATTR(max_dirty_mb);
-static int proc_mem_max(struct ctl_table *table, int write, void __user *buffer,
- size_t *lenp, loff_t *ppos)
-{
- char buf[22];
- int len;
+LUSTRE_STATIC_UINT_ATTR(debug_peer_on_timeout, &obd_debug_peer_on_timeout);
+LUSTRE_STATIC_UINT_ATTR(dump_on_timeout, &obd_dump_on_timeout);
+LUSTRE_STATIC_UINT_ATTR(dump_on_eviction, &obd_dump_on_eviction);
+LUSTRE_STATIC_UINT_ATTR(at_min, &at_min);
+LUSTRE_STATIC_UINT_ATTR(at_max, &at_max);
+LUSTRE_STATIC_UINT_ATTR(at_extra, &at_extra);
+LUSTRE_STATIC_UINT_ATTR(at_early_margin, &at_early_margin);
+LUSTRE_STATIC_UINT_ATTR(at_history, &at_history);
- if (!*lenp || (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
- if (write)
- return -EINVAL;
-
- len = snprintf(buf, sizeof(buf), "%llu\n", obd_memory_max());
- if (len > *lenp)
- len = *lenp;
- buf[len] = '\0';
- if (copy_to_user(buffer, buf, len))
- return -EFAULT;
- *lenp = len;
- *ppos += *lenp;
- return 0;
-}
-
-static int proc_pages_max(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- char buf[22];
- int len;
-
- if (!*lenp || (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
- if (write)
- return -EINVAL;
-
- len = snprintf(buf, sizeof(buf), "%llu\n", obd_pages_max());
- if (len > *lenp)
- len = *lenp;
- buf[len] = '\0';
- if (copy_to_user(buffer, buf, len))
- return -EFAULT;
- *lenp = len;
- *ppos += *lenp;
- return 0;
-}
-
-static int proc_max_dirty_pages_in_mb(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- int rc = 0;
-
- if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
- if (write) {
- rc = lprocfs_write_frac_helper(buffer, *lenp,
- (unsigned int *)table->data,
- 1 << (20 - PAGE_CACHE_SHIFT));
- /* Don't allow them to let dirty pages exceed 90% of system
- * memory and set a hard minimum of 4MB. */
- if (obd_max_dirty_pages > ((totalram_pages / 10) * 9)) {
- CERROR("Refusing to set max dirty pages to %u, which is more than 90%% of available RAM; setting to %lu\n",
- obd_max_dirty_pages,
- ((totalram_pages / 10) * 9));
- obd_max_dirty_pages = (totalram_pages / 10) * 9;
- } else if (obd_max_dirty_pages < 4 << (20 - PAGE_CACHE_SHIFT)) {
- obd_max_dirty_pages = 4 << (20 - PAGE_CACHE_SHIFT);
- }
- } else {
- char buf[21];
- int len;
-
- len = lprocfs_read_frac_helper(buf, sizeof(buf),
- *(unsigned int *)table->data,
- 1 << (20 - PAGE_CACHE_SHIFT));
- if (len > *lenp)
- len = *lenp;
- buf[len] = '\0';
- if (copy_to_user(buffer, buf, len))
- return -EFAULT;
- *lenp = len;
- }
- *ppos += *lenp;
- return rc;
-}
-
-static int proc_alloc_fail_rate(struct ctl_table *table, int write,
- void __user *buffer, size_t *lenp, loff_t *ppos)
-{
- int rc = 0;
-
- if (!table->data || !table->maxlen || !*lenp || (*ppos && !write)) {
- *lenp = 0;
- return 0;
- }
- if (write) {
- rc = lprocfs_write_frac_helper(buffer, *lenp,
- (unsigned int *)table->data,
- OBD_ALLOC_FAIL_MULT);
- } else {
- char buf[21];
- int len;
-
- len = lprocfs_read_frac_helper(buf, 21,
- *(unsigned int *)table->data,
- OBD_ALLOC_FAIL_MULT);
- if (len > *lenp)
- len = *lenp;
- buf[len] = '\0';
- if (copy_to_user(buffer, buf, len))
- return -EFAULT;
- *lenp = len;
- }
- *ppos += *lenp;
- return rc;
-}
-
-static struct ctl_table obd_table[] = {
- {
- .procname = "timeout",
- .data = &obd_timeout,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_set_timeout
- },
- {
- .procname = "debug_peer_on_timeout",
- .data = &obd_debug_peer_on_timeout,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .procname = "dump_on_timeout",
- .data = &obd_dump_on_timeout,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .procname = "dump_on_eviction",
- .data = &obd_dump_on_eviction,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec
- },
- {
- .procname = "memused",
- .data = NULL,
- .maxlen = 0,
- .mode = 0444,
- .proc_handler = &proc_memory_alloc
- },
- {
- .procname = "pagesused",
- .data = NULL,
- .maxlen = 0,
- .mode = 0444,
- .proc_handler = &proc_pages_alloc
- },
- {
- .procname = "memused_max",
- .data = NULL,
- .maxlen = 0,
- .mode = 0444,
- .proc_handler = &proc_mem_max
- },
- {
- .procname = "pagesused_max",
- .data = NULL,
- .maxlen = 0,
- .mode = 0444,
- .proc_handler = &proc_pages_max
- },
- {
- .procname = "ldlm_timeout",
- .data = &ldlm_timeout,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_set_timeout
- },
- {
- .procname = "alloc_fail_rate",
- .data = &obd_alloc_fail_rate,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_alloc_fail_rate
- },
- {
- .procname = "max_dirty_mb",
- .data = &obd_max_dirty_pages,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_max_dirty_pages_in_mb
- },
- {
- .procname = "at_min",
- .data = &at_min,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .procname = "at_max",
- .data = &at_max,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .procname = "at_extra",
- .data = &at_extra,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .procname = "at_early_margin",
- .data = &at_early_margin,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {
- .procname = "at_history",
- .data = &at_history,
- .maxlen = sizeof(int),
- .mode = 0644,
- .proc_handler = &proc_dointvec,
- },
- {}
+static struct attribute *lustre_attrs[] = {
+ &lustre_sattr_timeout.u.attr,
+ &lustre_attr_max_dirty_mb.attr,
+ &lustre_sattr_debug_peer_on_timeout.u.attr,
+ &lustre_sattr_dump_on_timeout.u.attr,
+ &lustre_sattr_dump_on_eviction.u.attr,
+ &lustre_sattr_at_min.u.attr,
+ &lustre_sattr_at_max.u.attr,
+ &lustre_sattr_at_extra.u.attr,
+ &lustre_sattr_at_early_margin.u.attr,
+ &lustre_sattr_at_history.u.attr,
+ NULL,
};
-static struct ctl_table parent_table[] = {
- {
- .procname = "lustre",
- .data = NULL,
- .maxlen = 0,
- .mode = 0555,
- .child = obd_table
- },
- {}
+static struct attribute_group lustre_attr_group = {
+ .attrs = lustre_attrs,
};
-#endif
-void obd_sysctl_init(void)
+int obd_sysctl_init(void)
{
-#ifdef CONFIG_SYSCTL
- if (!obd_table_header)
- obd_table_header = register_sysctl_table(parent_table);
-#endif
+ return sysfs_create_group(lustre_kobj, &lustre_attr_group);
}
void obd_sysctl_clean(void)
{
-#ifdef CONFIG_SYSCTL
- if (obd_table_header)
- unregister_sysctl_table(obd_table_header);
- obd_table_header = NULL;
-#endif
}
diff --git a/drivers/staging/lustre/lustre/obdclass/llog.c b/drivers/staging/lustre/lustre/obdclass/llog.c
index 4fa52d1..facc835 100644
--- a/drivers/staging/lustre/lustre/obdclass/llog.c
+++ b/drivers/staging/lustre/lustre/obdclass/llog.c
@@ -61,7 +61,7 @@
struct llog_handle *loghandle;
loghandle = kzalloc(sizeof(*loghandle), GFP_NOFS);
- if (loghandle == NULL)
+ if (!loghandle)
return NULL;
init_rwsem(&loghandle->lgh_lock);
@@ -208,7 +208,7 @@
LASSERT(handle->lgh_hdr == NULL);
llh = kzalloc(sizeof(*llh), GFP_NOFS);
- if (llh == NULL)
+ if (!llh)
return -ENOMEM;
handle->lgh_hdr = llh;
/* first assign flags to use llog_client_ops */
@@ -435,7 +435,7 @@
int rc;
lpi = kzalloc(sizeof(*lpi), GFP_NOFS);
- if (lpi == NULL) {
+ if (!lpi) {
CERROR("cannot alloc pointer\n");
return -ENOMEM;
}
@@ -907,7 +907,7 @@
char *name)
{
struct llog_handle *llh;
- int rc = 0;
+ int rc;
rc = llog_open(env, ctxt, &llh, NULL, name, LLOG_OPEN_EXISTS);
if (rc < 0) {
diff --git a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
index 17e7c18..08d1f0e 100644
--- a/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
+++ b/drivers/staging/lustre/lustre/obdclass/lprocfs_status.c
@@ -275,7 +275,7 @@
return NULL;
dest = kzalloc(MAX_STRING_SIZE + 1, GFP_KERNEL);
- if (dest == NULL)
+ if (!dest)
return NULL;
va_start(ap, format);
@@ -329,7 +329,7 @@
void ldebugfs_remove(struct dentry **entryp)
{
- debugfs_remove(*entryp);
+ debugfs_remove_recursive(*entryp);
*entryp = NULL;
}
EXPORT_SYMBOL(ldebugfs_remove);
diff --git a/drivers/staging/lustre/lustre/obdclass/lu_object.c b/drivers/staging/lustre/lustre/obdclass/lu_object.c
index 4d9b633..8e47232 100644
--- a/drivers/staging/lustre/lustre/obdclass/lu_object.c
+++ b/drivers/staging/lustre/lustre/obdclass/lu_object.c
@@ -602,7 +602,7 @@
struct lu_site_bkt_data *bkt;
o = lu_object_alloc(env, dev, f, conf);
- if (unlikely(IS_ERR(o)))
+ if (IS_ERR(o))
return o;
hs = dev->ld_site->ls_obj_hash;
@@ -666,7 +666,7 @@
* operations, including fld queries, inode loading, etc.
*/
o = lu_object_alloc(env, dev, f, conf);
- if (unlikely(IS_ERR(o)))
+ if (IS_ERR(o))
return o;
LASSERT(lu_fid_eq(lu_object_fid(o), f));
@@ -674,7 +674,7 @@
cfs_hash_bd_lock(hs, &bd, 1);
shadow = htable_lookup(s, &bd, f, waiter, &version);
- if (likely(IS_ERR(shadow) && PTR_ERR(shadow) == -ENOENT)) {
+ if (likely(PTR_ERR(shadow) == -ENOENT)) {
struct lu_site_bkt_data *bkt;
bkt = cfs_hash_bd_extra_get(hs, &bd);
@@ -1558,7 +1558,7 @@
LINVRNT(key->lct_index == i);
value = key->lct_init(ctx, key);
- if (unlikely(IS_ERR(value)))
+ if (IS_ERR(value))
return PTR_ERR(value);
if (!(ctx->lc_tags & LCT_NOREF))
diff --git a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c
index 5cc6435..d6184f8 100644
--- a/drivers/staging/lustre/lustre/obdclass/lustre_peer.c
+++ b/drivers/staging/lustre/lustre/obdclass/lustre_peer.c
@@ -105,7 +105,7 @@
return -EOVERFLOW;
data = kzalloc(sizeof(*data), GFP_NOFS);
- if (data == NULL)
+ if (!data)
return -ENOMEM;
obd_str2uuid(&data->un_uuid, uuid);
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_config.c b/drivers/staging/lustre/lustre/obdclass/obd_config.c
index fbdb748..93805ac 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_config.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_config.c
@@ -835,7 +835,7 @@
CDEBUG(D_CONFIG, "Add profile %s\n", prof);
lprof = kzalloc(sizeof(*lprof), GFP_NOFS);
- if (lprof == NULL)
+ if (!lprof)
return -ENOMEM;
INIT_LIST_HEAD(&lprof->lp_list);
@@ -979,7 +979,7 @@
new_len = LUSTRE_CFG_BUFLEN(cfg, 1) + strlen(new_name) - name_len;
new_param = kzalloc(new_len, GFP_NOFS);
- if (new_param == NULL)
+ if (!new_param)
return ERR_PTR(-ENOMEM);
strcpy(new_param, new_name);
@@ -987,7 +987,7 @@
strcat(new_param, value);
bufs = kzalloc(sizeof(*bufs), GFP_NOFS);
- if (bufs == NULL) {
+ if (!bufs) {
kfree(new_param);
return ERR_PTR(-ENOMEM);
}
@@ -1123,12 +1123,7 @@
goto out;
}
case LCFG_SET_LDLM_TIMEOUT: {
- CDEBUG(D_IOCTL, "changing lustre ldlm_timeout from %d to %d\n",
- ldlm_timeout, lcfg->lcfg_num);
- ldlm_timeout = max(lcfg->lcfg_num, 1U);
- if (ldlm_timeout >= obd_timeout)
- ldlm_timeout = max(obd_timeout / 3, 1U);
- ldlm_timeout_set = 1;
+ /* ldlm_timeout is not used on the client */
err = 0;
goto out;
}
@@ -1461,7 +1456,7 @@
inst_len = LUSTRE_CFG_BUFLEN(lcfg, 0) +
sizeof(clli->cfg_instance) * 2 + 4;
inst_name = kzalloc(inst_len, GFP_NOFS);
- if (inst_name == NULL) {
+ if (!inst_name) {
rc = -ENOMEM;
goto out;
}
@@ -1639,7 +1634,7 @@
int rc = 0;
outstr = kzalloc(256, GFP_NOFS);
- if (outstr == NULL)
+ if (!outstr)
return -ENOMEM;
if (rec->lrh_type == OBD_CFG_REC) {
diff --git a/drivers/staging/lustre/lustre/obdclass/obd_mount.c b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
index ce4a71f..7c5bab3 100644
--- a/drivers/staging/lustre/lustre/obdclass/obd_mount.c
+++ b/drivers/staging/lustre/lustre/obdclass/obd_mount.c
@@ -85,7 +85,7 @@
LASSERT(cfg);
bufs = kzalloc(sizeof(*bufs), GFP_NOFS);
- if (bufs == NULL)
+ if (!bufs)
return -ENOMEM;
/* mgc_process_config */
@@ -247,18 +247,18 @@
mutex_lock(&mgc_start_lock);
len = strlen(LUSTRE_MGC_OBDNAME) + strlen(libcfs_nid2str(nid)) + 1;
- mgcname = kzalloc(len, GFP_NOFS);
- niduuid = kzalloc(len + 2, GFP_NOFS);
+ mgcname = kasprintf(GFP_NOFS,
+ "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid));
+ niduuid = kasprintf(GFP_NOFS, "%s_%x", mgcname, i);
if (!mgcname || !niduuid) {
rc = -ENOMEM;
goto out_free;
}
- sprintf(mgcname, "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid));
mgssec = lsi->lsi_lmd->lmd_mgssec ? lsi->lsi_lmd->lmd_mgssec : "";
data = kzalloc(sizeof(*data), GFP_NOFS);
- if (data == NULL) {
+ if (!data) {
rc = -ENOMEM;
goto out_free;
}
@@ -326,7 +326,6 @@
/* Add the primary nids for the MGS */
i = 0;
- sprintf(niduuid, "%s_%x", mgcname, i);
if (IS_SERVER(lsi)) {
ptr = lsi->lsi_lmd->lmd_mgs;
if (IS_MGS(lsi)) {
@@ -885,7 +884,7 @@
length = tail - ptr;
lmd->lmd_mgssec = kzalloc(length + 1, GFP_NOFS);
- if (lmd->lmd_mgssec == NULL)
+ if (!lmd->lmd_mgssec)
return -ENOMEM;
memcpy(lmd->lmd_mgssec, ptr, length);
@@ -911,7 +910,7 @@
length = tail - ptr;
*handle = kzalloc(length + 1, GFP_NOFS);
- if (*handle == NULL)
+ if (!*handle)
return -ENOMEM;
memcpy(*handle, ptr, length);
@@ -941,7 +940,7 @@
oldlen = strlen(lmd->lmd_mgs) + 1;
mgsnid = kzalloc(oldlen + length + 1, GFP_NOFS);
- if (mgsnid == NULL)
+ if (!mgsnid)
return -ENOMEM;
if (lmd->lmd_mgs != NULL) {
@@ -983,7 +982,7 @@
lmd->lmd_magic = LMD_MAGIC;
lmd->lmd_params = kzalloc(4096, GFP_NOFS);
- if (lmd->lmd_params == NULL)
+ if (!lmd->lmd_params)
return -ENOMEM;
lmd->lmd_params[0] = '\0';
@@ -1120,10 +1119,9 @@
/* Remove leading /s from fsname */
while (*++s1 == '/') ;
/* Freed in lustre_free_lsi */
- lmd->lmd_profile = kzalloc(strlen(s1) + 8, GFP_NOFS);
+ lmd->lmd_profile = kasprintf(GFP_NOFS, "%s-client", s1);
if (!lmd->lmd_profile)
return -ENOMEM;
- sprintf(lmd->lmd_profile, "%s-client", s1);
}
/* Freed in lustre_free_lsi */
@@ -1281,7 +1279,7 @@
.mount = lustre_mount,
.kill_sb = lustre_kill_super,
.fs_flags = FS_BINARY_MOUNTDATA | FS_REQUIRES_DEV |
- FS_HAS_FIEMAP | FS_RENAME_DOES_D_MOVE,
+ FS_RENAME_DOES_D_MOVE,
};
MODULE_ALIAS_FS("lustre");
diff --git a/drivers/staging/lustre/lustre/obdclass/uuid.c b/drivers/staging/lustre/lustre/obdclass/uuid.c
index ff0a01b..b0b0157 100644
--- a/drivers/staging/lustre/lustre/obdclass/uuid.c
+++ b/drivers/staging/lustre/lustre/obdclass/uuid.c
@@ -43,40 +43,8 @@
#include "../include/obd_support.h"
#include "../include/obd_class.h"
-
-static inline __u32 consume(int nob, __u8 **ptr)
-{
- __u32 value;
-
- LASSERT(nob <= sizeof(value));
-
- for (value = 0; nob > 0; --nob)
- value = (value << 8) | *((*ptr)++);
- return value;
-}
-
-#define CONSUME(val, ptr) (val) = consume(sizeof(val), (ptr))
-
-static void uuid_unpack(class_uuid_t in, __u16 *uu, int nr)
-{
- __u8 *ptr = in;
-
- LASSERT(nr * sizeof(*uu) == sizeof(class_uuid_t));
-
- while (nr-- > 0)
- CONSUME(uu[nr], &ptr);
-}
-
void class_uuid_unparse(class_uuid_t uu, struct obd_uuid *out)
{
- /* uu as an array of __u16's */
- __u16 uuid[sizeof(class_uuid_t) / sizeof(__u16)];
-
- CLASSERT(ARRAY_SIZE(uuid) == 8);
-
- uuid_unpack(uu, uuid, ARRAY_SIZE(uuid));
- sprintf(out->uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x",
- uuid[0], uuid[1], uuid[2], uuid[3],
- uuid[4], uuid[5], uuid[6], uuid[7]);
+ sprintf(out->uuid, "%pU", uu);
}
EXPORT_SYMBOL(class_uuid_unparse);
diff --git a/drivers/staging/lustre/lustre/obdecho/echo_client.c b/drivers/staging/lustre/lustre/obdecho/echo_client.c
index 0222fd2..27bd170 100644
--- a/drivers/staging/lustre/lustre/obdecho/echo_client.c
+++ b/drivers/staging/lustre/lustre/obdecho/echo_client.c
@@ -480,11 +480,11 @@
LASSERT(*lsmp == NULL);
*lsmp = kzalloc(lsm_size, GFP_NOFS);
- if (*lsmp == NULL)
+ if (!*lsmp)
return -ENOMEM;
(*lsmp)->lsm_oinfo[0] = kzalloc(sizeof(struct lov_oinfo), GFP_NOFS);
- if ((*lsmp)->lsm_oinfo[0] == NULL) {
+ if (!(*lsmp)->lsm_oinfo[0]) {
kfree(*lsmp);
return -ENOMEM;
}
@@ -701,7 +701,7 @@
int cleanup = 0;
ed = kzalloc(sizeof(*ed), GFP_NOFS);
- if (ed == NULL) {
+ if (!ed) {
rc = -ENOMEM;
goto out;
}
@@ -1878,7 +1878,7 @@
return rc;
env = kzalloc(sizeof(*env), GFP_NOFS);
- if (env == NULL)
+ if (!env)
return -ENOMEM;
rc = lu_env_init(env, LCT_DT_THREAD);
@@ -2049,7 +2049,7 @@
ec->ec_nstripes = 0;
ocd = kzalloc(sizeof(*ocd), GFP_NOFS);
- if (ocd == NULL) {
+ if (!ocd) {
CERROR("Can't alloc ocd connecting to %s\n",
lustre_cfg_string(lcfg, 1));
return -ENOMEM;
@@ -2139,7 +2139,7 @@
.o_disconnect = echo_client_disconnect
};
-int echo_client_init(void)
+static int echo_client_init(void)
{
int rc;
@@ -2154,7 +2154,7 @@
return rc;
}
-void echo_client_exit(void)
+static void echo_client_exit(void)
{
class_unregister_type(LUSTRE_ECHO_CLIENT_NAME);
lu_kmem_fini(echo_caches);
diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
index 5592d32..c72035e 100644
--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
+++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
@@ -1837,12 +1837,6 @@
oap2 = list_first_entry(&tmp->oe_pages, struct osc_async_page,
oap_pending_item);
EASSERT(tmp->oe_owner == current, tmp);
-#if 0
- if (overlapped(tmp, ext)) {
- OSC_EXTENT_DUMP(D_ERROR, tmp, "overlapped %p.\n", ext);
- EASSERT(0, ext);
- }
-#endif
if (oap2cl_page(oap)->cp_type != oap2cl_page(oap2)->cp_type) {
CDEBUG(D_CACHE, "Do not permit different type of IO"
" for a same RPC\n");
diff --git a/drivers/staging/lustre/lustre/osc/osc_dev.c b/drivers/staging/lustre/lustre/osc/osc_dev.c
index 9222c9f..91fdec4 100644
--- a/drivers/staging/lustre/lustre/osc/osc_dev.c
+++ b/drivers/staging/lustre/lustre/osc/osc_dev.c
@@ -218,7 +218,7 @@
int rc;
od = kzalloc(sizeof(*od), GFP_NOFS);
- if (od == NULL)
+ if (!od)
return ERR_PTR(-ENOMEM);
cl_device_init(&od->od_cl, t);
diff --git a/drivers/staging/lustre/lustre/osc/osc_page.c b/drivers/staging/lustre/lustre/osc/osc_page.c
index 43dfa73..f9cf5ce 100644
--- a/drivers/staging/lustre/lustre/osc/osc_page.c
+++ b/drivers/staging/lustre/lustre/osc/osc_page.c
@@ -471,7 +471,7 @@
struct cl_io *io)
{
struct osc_page *opg = cl2osc_page(slice);
- int rc = 0;
+ int rc;
rc = osc_flush_async_page(env, io, opg);
return rc;
diff --git a/drivers/staging/lustre/lustre/osc/osc_request.c b/drivers/staging/lustre/lustre/osc/osc_request.c
index f84b4c7..12113df 100644
--- a/drivers/staging/lustre/lustre/osc/osc_request.c
+++ b/drivers/staging/lustre/lustre/osc/osc_request.c
@@ -119,7 +119,7 @@
if (*lmmp == NULL) {
*lmmp = kzalloc(lmm_size, GFP_NOFS);
- if (*lmmp == NULL)
+ if (!*lmmp)
return -ENOMEM;
}
@@ -1909,7 +1909,7 @@
mpflag = cfs_memory_pressure_get_and_set();
crattr = kzalloc(sizeof(*crattr), GFP_NOFS);
- if (crattr == NULL) {
+ if (!crattr) {
rc = -ENOMEM;
goto out;
}
@@ -2665,7 +2665,7 @@
buf = NULL;
len = 0;
- if (obd_ioctl_getdata(&buf, &len, (void *)uarg)) {
+ if (obd_ioctl_getdata(&buf, &len, uarg)) {
err = -EINVAL;
goto out;
}
@@ -2695,7 +2695,7 @@
memcpy(data->ioc_inlbuf2, &obd->obd_uuid, sizeof(uuid));
- err = copy_to_user((void *)uarg, buf, len);
+ err = copy_to_user(uarg, buf, len);
if (err)
err = -EFAULT;
obd_ioctl_freedata(buf, len);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/client.c b/drivers/staging/lustre/lustre/ptlrpc/client.c
index a12cd66..c83a34a 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/client.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/client.c
@@ -971,7 +971,7 @@
struct ptlrpc_set_cbdata *cbdata;
cbdata = kzalloc(sizeof(*cbdata), GFP_NOFS);
- if (cbdata == NULL)
+ if (!cbdata)
return -ENOMEM;
cbdata->psc_interpret = fn;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/events.c b/drivers/staging/lustre/lustre/ptlrpc/events.c
index 8cb1929..c8ef9e5 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/events.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/events.c
@@ -485,7 +485,7 @@
return rc;
}
-void ptlrpc_ni_fini(void)
+static void ptlrpc_ni_fini(void)
{
wait_queue_head_t waitq;
struct l_wait_info lwi;
@@ -529,7 +529,7 @@
return pid;
}
-int ptlrpc_ni_init(void)
+static int ptlrpc_ni_init(void)
{
int rc;
lnet_pid_t pid;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/import.c b/drivers/staging/lustre/lustre/ptlrpc/import.c
index c9b8481..1eae389 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/import.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/import.c
@@ -555,14 +555,12 @@
imp_conn->oic_last_attempt = cfs_time_current_64();
/* switch connection, don't mind if it's same as the current one */
- if (imp->imp_connection)
- ptlrpc_connection_put(imp->imp_connection);
+ ptlrpc_connection_put(imp->imp_connection);
imp->imp_connection = ptlrpc_connection_addref(imp_conn->oic_conn);
dlmexp = class_conn2export(&imp->imp_dlm_handle);
LASSERT(dlmexp != NULL);
- if (dlmexp->exp_connection)
- ptlrpc_connection_put(dlmexp->exp_connection);
+ ptlrpc_connection_put(dlmexp->exp_connection);
dlmexp->exp_connection = ptlrpc_connection_addref(imp_conn->oic_conn);
class_export_put(dlmexp);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
index aaaabbf..53f9af1 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/lproc_ptlrpc.c
@@ -652,7 +652,7 @@
return -EINVAL;
cmd = kzalloc(LPROCFS_NRS_WR_MAX_CMD, GFP_NOFS);
- if (cmd == NULL)
+ if (!cmd)
return -ENOMEM;
/**
* strsep() modifies its argument, so keep a copy
@@ -819,7 +819,7 @@
}
srhi = kzalloc(sizeof(*srhi), GFP_NOFS);
- if (srhi == NULL)
+ if (!srhi)
return NULL;
srhi->srhi_seq = 0;
@@ -1219,7 +1219,7 @@
char *tmpbuf;
kbuf = kzalloc(BUFLEN, GFP_NOFS);
- if (kbuf == NULL)
+ if (!kbuf)
return -ENOMEM;
/*
@@ -1303,7 +1303,7 @@
return -EINVAL;
kbuf = kzalloc(count + 1, GFP_NOFS);
- if (kbuf == NULL)
+ if (!kbuf)
return -ENOMEM;
if (copy_from_user(kbuf, buffer, count)) {
diff --git a/drivers/staging/lustre/lustre/ptlrpc/nrs.c b/drivers/staging/lustre/lustre/ptlrpc/nrs.c
index 9516aca..d37cdd5 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/nrs.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/nrs.c
@@ -1156,7 +1156,7 @@
}
desc = kzalloc(sizeof(*desc), GFP_NOFS);
- if (desc == NULL) {
+ if (!desc) {
rc = -ENOMEM;
goto fail;
}
diff --git a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
index 2787bfd..84937ad 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/pack_generic.c
@@ -52,6 +52,8 @@
#include "../include/obd_cksum.h"
#include "../include/lustre/ll_fiemap.h"
+#include "ptlrpc_internal.h"
+
static inline int lustre_msg_hdr_size_v2(int count)
{
return cfs_size_round(offsetof(struct lustre_msg_v2,
diff --git a/drivers/staging/lustre/lustre/ptlrpc/pinger.c b/drivers/staging/lustre/lustre/ptlrpc/pinger.c
index d05c37c..f8edb79 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/pinger.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/pinger.c
@@ -318,8 +318,6 @@
strcpy(pinger_thread.t_name, "ll_ping");
- /* CLONE_VM and CLONE_FILES just avoid a needless copy, because we
- * just drop the VM and FILES in cfs_daemonize_ctxt() right away. */
rc = PTR_ERR(kthread_run(ptlrpc_pinger_main, &pinger_thread,
"%s", pinger_thread.t_name));
if (IS_ERR_VALUE(rc)) {
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
index 5268887..ae99180 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpc_module.c
@@ -51,7 +51,7 @@
extern struct mutex pinger_mutex;
extern struct mutex ptlrpcd_mutex;
-__init int ptlrpc_init(void)
+static int __init ptlrpc_init(void)
{
int rc, cleanup_phase = 0;
diff --git a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
index e591cff..17cc81d 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/ptlrpcd.c
@@ -739,7 +739,7 @@
size = offsetof(struct ptlrpcd, pd_threads[nthreads]);
ptlrpcds = kzalloc(size, GFP_NOFS);
- if (ptlrpcds == NULL) {
+ if (!ptlrpcds) {
rc = -ENOMEM;
goto out;
}
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
index 69d73c4..2ee3e8b 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_bulk.c
@@ -415,7 +415,7 @@
for (i = 0; i < npools; i++) {
pools[i] = kzalloc(PAGE_CACHE_SIZE, GFP_NOFS);
- if (pools[i] == NULL)
+ if (!pools[i])
goto out_pools;
for (j = 0; j < PAGES_PER_POOL && alloced < npages; j++) {
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
index 31da43e..e7f2f33 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_config.c
@@ -564,7 +564,7 @@
return NULL;
conf = kzalloc(sizeof(*conf), GFP_NOFS);
- if (conf == NULL)
+ if (!conf)
return NULL;
strcpy(conf->sc_fsname, fsname);
diff --git a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
index 53ce0d1..a243db6 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/sec_plain.c
@@ -444,7 +444,7 @@
LASSERT(SPTLRPC_FLVR_POLICY(sf->sf_rpc) == SPTLRPC_POLICY_PLAIN);
plsec = kzalloc(sizeof(*plsec), GFP_NOFS);
- if (plsec == NULL)
+ if (!plsec)
return NULL;
/*
diff --git a/drivers/staging/lustre/lustre/ptlrpc/service.c b/drivers/staging/lustre/lustre/ptlrpc/service.c
index 9117f1c..003344c 100644
--- a/drivers/staging/lustre/lustre/ptlrpc/service.c
+++ b/drivers/staging/lustre/lustre/ptlrpc/service.c
@@ -43,7 +43,7 @@
#include "ptlrpc_internal.h"
/* The following are visible and mutable through /sys/module/ptlrpc */
-int test_req_buffer_pressure = 0;
+int test_req_buffer_pressure;
module_param(test_req_buffer_pressure, int, 0444);
MODULE_PARM_DESC(test_req_buffer_pressure, "set non-zero to put pressure on request buffer pools");
module_param(at_min, int, 0644);
@@ -69,7 +69,7 @@
/** Used to protect the \e ptlrpc_all_services list */
struct mutex ptlrpc_all_services_mutex;
-struct ptlrpc_request_buffer_desc *
+static struct ptlrpc_request_buffer_desc *
ptlrpc_alloc_rqbd(struct ptlrpc_service_part *svcpt)
{
struct ptlrpc_service *svc = svcpt->scp_service;
@@ -101,7 +101,7 @@
return rqbd;
}
-void
+static void
ptlrpc_free_rqbd(struct ptlrpc_request_buffer_desc *rqbd)
{
struct ptlrpc_service_part *svcpt = rqbd->rqbd_svcpt;
@@ -118,7 +118,7 @@
kfree(rqbd);
}
-int
+static int
ptlrpc_grow_req_bufs(struct ptlrpc_service_part *svcpt, int post)
{
struct ptlrpc_service *svc = svcpt->scp_service;
@@ -732,7 +732,7 @@
service = kzalloc(offsetof(struct ptlrpc_service, srv_parts[ncpts]),
GFP_NOFS);
- if (service == NULL) {
+ if (!service) {
kfree(cpts);
return ERR_PTR(-ENOMEM);
}
@@ -2298,7 +2298,7 @@
}
env = kzalloc(sizeof(*env), GFP_NOFS);
- if (env == NULL) {
+ if (!env) {
rc = -ENOMEM;
goto out_srv_fini;
}
@@ -2826,9 +2826,7 @@
ptlrpc_stop_hr_threads();
cfs_percpt_for_each(hrp, i, ptlrpc_hr.hr_partitions) {
- if (hrp->hrp_thrs != NULL) {
- kfree(hrp->hrp_thrs);
- }
+ kfree(hrp->hrp_thrs);
}
cfs_percpt_free(ptlrpc_hr.hr_partitions);
@@ -3054,7 +3052,7 @@
* Right now, it just checks to make sure that requests aren't languishing
* in the queue. We'll use this health check to govern whether a node needs
* to be shot, so it's intentionally non-aggressive. */
-int ptlrpc_svcpt_health_check(struct ptlrpc_service_part *svcpt)
+static int ptlrpc_svcpt_health_check(struct ptlrpc_service_part *svcpt)
{
struct ptlrpc_request *request = NULL;
struct timeval right_now;
diff --git a/drivers/staging/lustre/sysfs-fs-lustre b/drivers/staging/lustre/sysfs-fs-lustre
index 1e302e8..873e2cf 100644
--- a/drivers/staging/lustre/sysfs-fs-lustre
+++ b/drivers/staging/lustre/sysfs-fs-lustre
@@ -40,6 +40,109 @@
e.g. dd.1253
nodelocal - use jobid_name value from above.
+What: /sys/fs/lustre/timeout
+Date: June 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Controls "lustre timeout" variable, also known as obd_timeout
+ in some old manual. In the past obd_timeout was of paramount
+ importance as the timeout value used everywhere and where
+ other timeouts were derived from. These days it's much less
+ important as network timeouts are mostly determined by
+ AT (adaptive timeouts).
+ Unit: seconds, default: 100
+
+What: /sys/fs/lustre/max_dirty_mb
+Date: June 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Controls total number of dirty cache (in megabytes) allowed
+ across all mounted lustre filesystems.
+ Since writeout of dirty pages in Lustre is somewhat expensive,
+ when you allow to many dirty pages, this might lead to
+ performance degradations as kernel tries to desperately
+ find some pages to free/writeout.
+ Default 1/2 RAM. Min value 4, max value 9/10 of RAM.
+
+What: /sys/fs/lustre/debug_peer_on_timeout
+Date: June 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Control if lnet debug information should be printed when
+ an RPC timeout occurs.
+ 0 disabled (default)
+ 1 enabled
+
+What: /sys/fs/lustre/dump_on_timeout
+Date: June 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Controls if Lustre debug log should be dumped when an RPC
+ timeout occurs. This is useful if yout debug buffer typically
+ rolls over by the time you notice RPC timeouts.
+
+What: /sys/fs/lustre/dump_on_eviction
+Date: June 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Controls if Lustre debug log should be dumped when an this
+ client is evicted from one of the servers.
+ This is useful if yout debug buffer typically rolls over
+ by the time you notice the eviction event.
+
+What: /sys/fs/lustre/at_min
+Date: July 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Controls minimum adaptive timeout in seconds. If you encounter
+ a case where clients timeout due to server-reported processing
+ time being too short, you might consider increasing this value.
+ One common case of this if the underlying network has
+ unpredictable long delays.
+ Default: 0
+
+What: /sys/fs/lustre/at_max
+Date: July 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Controls maximum adaptive timeout in seconds. If at_max timeout
+ is reached for an RPC, the RPC will time out.
+ Some genuinuely slow network hardware might warrant increasing
+ this value.
+ Setting this value to 0 disables Adaptive Timeouts
+ functionality and old-style obd_timeout value is then used.
+ Default: 600
+
+What: /sys/fs/lustre/at_extra
+Date: July 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Controls how much extra time to request for unfinished requests
+ in processing in seconds. Normally a server-side parameter, it
+ is also used on the client for responses to various LDLM ASTs
+ that are handled with a special server thread on the client.
+ This is a way for the servers to ask the clients not to time
+ out the request that reached current servicing time estimate
+ yet and give it some more time.
+ Default: 30
+
+What: /sys/fs/lustre/at_early_margin
+Date: July 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Controls when to send the early reply for requests that are
+ about to timeout as an offset to the estimated service time in
+ seconds..
+ Default: 5
+
+What: /sys/fs/lustre/at_history
+Date: July 2015
+Contact: "Oleg Drokin" <oleg.drokin@intel.com>
+Description:
+ Controls for how many seconds to remember slowest events
+ encountered by adaptive timeouts code.
+ Default: 600
+
What: /sys/fs/lustre/llite/<fsname>-<uuid>/blocksize
Date: May 2015
Contact: "Oleg Drokin" <oleg.drokin@intel.com>
diff --git a/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt
new file mode 100644
index 0000000..380c137
--- /dev/null
+++ b/drivers/staging/most/Documentation/ABI/sysfs-class-most.txt
@@ -0,0 +1,181 @@
+What: /sys/class/most/mostcore/aims
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ List of AIMs that have been loaded.
+Users:
+
+What: /sys/class/most/mostcore/aims/<aim>/add_link
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ This is used to establish a connection of a channel and the
+ current AIM.
+Users:
+
+What: /sys/class/most/mostcore/aims/<aim>/remove_link
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ This is used to remove a connected channel from the
+ current AIM.
+Users:
+
+What: /sys/class/most/mostcore/devices
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ List of attached MOST interfaces.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/description
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ Provides information about the interface type and the physical
+ location of the device. Hardware attached via USB, for instance,
+ might return <usb_device 1-1.1:1.0>
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/interface
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ Indicates the type of peripherial interface the current device
+ uses.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ For every channel of the device a directory is created, whose
+ name is dictated by the HDM. This enables an application to
+ collect information about the channel's capabilities and
+ configure it.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/available_datatypes
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ Indicates the data types the current channel can transport.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/available_directions
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ Indicates the directions the current channel is capable of.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/number_of_packet_buffers
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ Indicates the number of packet buffers the current channel can
+ handle.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/number_of_stream_buffers
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ Indicates the number of streaming buffers the current channel can
+ handle.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/size_of_packet_buffer
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ Indicates the size of a packet buffer the current channel can
+ handle.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/size_of_stream_buffer
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ Indicates the size of a streaming buffer the current channel can
+ handle.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_number_of_buffers
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ This is to configure the number of buffers of the current channel.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_buffer_size
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ This is to configure the size of a buffer of the current channel.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_direction
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ This is to configure the direction of the current channel.
+ The following strings will be accepted:
+ 'dir_tx',
+ 'dir_rx'
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_datatype
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ This is to configure the data type of the current channel.
+ The following strings will be accepted:
+ 'control',
+ 'async',
+ 'sync',
+ 'isoc_avp'
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_subbuffer_size
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ This is to configure the subbuffer size of the current channel.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/set_packets_per_xact
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ This is to configure the number of packets per transaction of
+ the current channel. This is only needed network interface
+ controller is attached via USB.
+Users:
+
+What: /sys/class/most/mostcore/devices/<mdev>/<channel>/channel_starving
+Date: June 2015
+KernelVersion: 4.3
+Contact: Christian Gromm <christian.gromm@microchip.com>
+Description:
+ Indicates whether current channel ran out of buffers.
+Users:
diff --git a/drivers/staging/most/Documentation/driver_usage.txt b/drivers/staging/most/Documentation/driver_usage.txt
new file mode 100644
index 0000000..a4dc0c3
--- /dev/null
+++ b/drivers/staging/most/Documentation/driver_usage.txt
@@ -0,0 +1,180 @@
+
+ Section 1 Overview
+
+The Media Oriented Systems Transport (MOST) driver gives Linux applications
+access a MOST network: The Automotive Information Backbone and the de-facto
+standard for high-bandwidth automotive multimedia networking.
+
+MOST defines the protocol, hardware and software layers necessary to allow
+for the efficient and low-cost transport of control, real-time and packet
+data using a single medium (physical layer). Media currently in use are
+fiber optics, unshielded twisted pair cables (UTP) and coax cables. MOST
+also supports various speed grades up to 150 Mbps.
+For more information on MOST, visit the MOST Cooperation website:
+www.mostcooperation.com.
+
+Cars continue to evolve into sophisticated consumer electronics platforms,
+increasing the demand for reliable and simple solutions to support audio,
+video and data communications. MOST can be used to connect multiple
+consumer devices via optical or electrical physical layers directly to one
+another or in a network configuration. As a synchronous network, MOST
+provides excellent Quality of Service and seamless connectivity for
+audio/video streaming. Therefore, the driver perfectly fits to the mission
+of Automotive Grade Linux to create open source software solutions for
+automotive applications.
+
+The driver consists basically of three layers. The hardware layer, the
+core layer and the application layer. The core layer consists of the core
+module only. This module handles the communication flow through all three
+layers, the configuration of the driver, the configuration interface
+representation in sysfs, and the buffer management.
+For each of the other two layers a selection of modules is provided. These
+modules can arbitrarily be combined to meet the needs of the desired
+system architecture. A module of the hardware layer is referred to as an
+HDM (hardware dependent module). Each module of this layer handles exactly
+one of the peripheral interfaces of a network interface controller (e.g.
+USB, MediaLB, I2C). A module of the application layer is referred to as an
+AIM (application interfacing module). The modules of this layer give access
+to MOST via one the following ways: character devices, ALSA, Networking or
+V4L2.
+
+To physically access MOST, an Intelligent Network Interface Controller
+(INIC) is needed. For more information on available controllers visit:
+www.microchip.com
+
+
+
+ Section 1.1 Hardware Layer
+
+The hardware layer contains so called hardware dependent modules (HDM). For each
+peripheral interface the hardware supports the driver has a suitable module
+that handles the interface.
+
+The HDMs encapsulate the peripheral interface specific knowledge of the driver
+and provides an easy way of extending the number of supported interfaces.
+Currently the following HDMs are available:
+
+ 1) MediaLB (DIM2)
+ Host wants to communicate with hardware via MediaLB.
+
+ 2) I2C
+ Host wants to communicate with the hardware via I2C.
+
+ 3) USB
+ Host wants to communicate with the hardware via USB.
+
+
+ Section 1.2 Core Layer
+
+The core layer contains the mostcore module only, which processes the driver
+configuration via sysfs, buffer management and data forwarding.
+
+
+
+ Section 1.2 Application Layer
+
+The application layer contains so called application interfacing modules (AIM).
+Depending on how the driver should interface to the application, one or more
+suitable modules can be selected.
+
+The AIMs encapsulate the application interface specific knowledge of the driver
+and provides access to user space or other kernel subsystems.
+Currently the following AIMs are available
+
+ 1) Character Device
+ Applications can access the driver by means of character devices.
+
+ 2) Networking
+ Standard networking applications (e.g. iperf) can by used to access
+ the driver via the networking subsystem.
+
+ 3) Video4Linux (v4l2)
+ Standard video applications (e.g. VLC) can by used to access the
+ driver via the V4L subsystem.
+
+ 4) Advanced Linux Sound Architecture (ALSA)
+ Standard sound applications (e.g. aplay, arecord, audacity) can by
+ used to access the driver via the ALSA subsystem.
+
+
+
+ Section 2 Configuration
+
+See ABI/sysfs-class-most.txt
+
+
+
+ Section 3 USB Padding
+
+When transceiving synchronous or isochronous data, the number of packets per USB
+transaction and the sub-buffer size need to be configured. These values
+are needed for the driver to process buffer padding, as expected by hardware,
+which is for performance optimization purposes of the USB transmission.
+
+When transmitting synchronous data the allocated channel width needs to be
+written to 'set_subbuffer_size'. Additionally, the number of MOST frames that
+should travel to the host within one USB transaction need to be written to
+'packets_per_xact'.
+
+Internally the synchronous threshold is calculated as follows:
+
+ frame_size = set_subbuffer_size * packets_per_xact
+
+In case 'packets_per_xact' is set to 0xFF the maximum number of packets,
+allocated within one MOST frame, is calculated that fit into _one_ 512 byte
+USB full packet.
+
+ frame_size = floor(MTU_USB / bandwidth_sync) * bandwidth_sync
+
+This frame_size is the number of synchronous data within an USB transaction,
+which renders MTU_USB - frame_size bytes for padding.
+
+When transmitting isochronous AVP data the desired packet size needs to be
+written to 'set_subbuffer_size' and hardware will always expect two isochronous
+packets within one USB transaction. This renders
+
+ MTU_USB - (2 * set_subbuffer_size)
+
+bytes for padding.
+
+Note that at least 2 times set_subbuffer_size bytes for isochronous data or
+set_subbuffer_size times packts_per_xact bytes for synchronous data need to be
+put in the transmission buffer and passed to the driver.
+
+Since HDMs are allowed to change a chosen configuration to best fit its
+constraints, it is recommended to always double check the configuration and read
+back the previously written files.
+
+
+
+ Section 4 Routing Channels
+
+To connect a channel that has been configured as outlined above to an AIM and
+make it accessible to user space applications, the attribute file 'add_link' is
+used. To actually bind a channel to the AIM a string needs to be written to the
+file that complies with the following syntax:
+
+ "most_device:channel_name:link_name[.param]"
+
+The example above links the channel "channel_name" of the device "most_device"
+to the AIM. In case the AIM interfaces the VFS this would also create a device
+node "link_name" in the /dev directory. The parameter "param" is an AIM dependent
+string, which can be omitted in case the used AIM does not make any use of it.
+
+Cdev AIM example:
+ $ echo "mdev0:ep_81:my_rx_channel" >add_link
+ $ echo "mdev0:ep_81" >add_link
+
+
+Sound/ALSA AIM example:
+
+The sound/ALSA AIM needs an additional parameter to determine the audio resolution
+that is going to be used. The following strings can be used:
+
+ - "1x8" (Mono)
+ - "2x16" (16-bit stereo)
+ - "2x24" (24-bit stereo)
+ - "2x32" (32-bit stereo)
+
+ $ echo "mdev0:ep_81:audio_rx.2x16" >add_link
+ $ echo "mdev0:ep_81" >add_link
diff --git a/drivers/staging/most/Kconfig b/drivers/staging/most/Kconfig
new file mode 100644
index 0000000..d50de03
--- /dev/null
+++ b/drivers/staging/most/Kconfig
@@ -0,0 +1,30 @@
+menuconfig MOST
+ tristate "MOST driver"
+ select MOSTCORE
+ default n
+ ---help---
+ This option allows you to enable support for MOST Network transceivers.
+
+ If in doubt, say N here.
+
+
+
+if MOST
+
+source "drivers/staging/most/mostcore/Kconfig"
+
+source "drivers/staging/most/aim-cdev/Kconfig"
+
+source "drivers/staging/most/aim-network/Kconfig"
+
+source "drivers/staging/most/aim-sound/Kconfig"
+
+source "drivers/staging/most/aim-v4l2/Kconfig"
+
+source "drivers/staging/most/hdm-dim2/Kconfig"
+
+source "drivers/staging/most/hdm-i2c/Kconfig"
+
+source "drivers/staging/most/hdm-usb/Kconfig"
+
+endif
diff --git a/drivers/staging/most/Makefile b/drivers/staging/most/Makefile
new file mode 100644
index 0000000..9ee981c
--- /dev/null
+++ b/drivers/staging/most/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_MOSTCORE) += mostcore/
+obj-$(CONFIG_AIM_CDEV) += aim-cdev/
+obj-$(CONFIG_AIM_NETWORK) += aim-network/
+obj-$(CONFIG_AIM_SOUND) += aim-sound/
+obj-$(CONFIG_AIM_V4L2) += aim-v4l2/
+obj-$(CONFIG_HDM_DIM2) += hdm-dim2/
+obj-$(CONFIG_HDM_I2C) += hdm-i2c/
+obj-$(CONFIG_HDM_USB) += hdm-usb/
diff --git a/drivers/staging/most/TODO b/drivers/staging/most/TODO
new file mode 100644
index 0000000..4fa11a9
--- /dev/null
+++ b/drivers/staging/most/TODO
@@ -0,0 +1,8 @@
+* Get through code review with Greg Kroah-Hartman
+
+Contact:
+To:
+Christian Gromm <christian.gromm@microchip.com>
+Cc:
+Michael Fabry <Michael.Fabry@microchip.com>
+Christian Gromm <chris@engineersdelight.de>
diff --git a/drivers/staging/most/aim-cdev/Kconfig b/drivers/staging/most/aim-cdev/Kconfig
new file mode 100644
index 0000000..3c59f1b
--- /dev/null
+++ b/drivers/staging/most/aim-cdev/Kconfig
@@ -0,0 +1,12 @@
+#
+# MOST Cdev configuration
+#
+
+config AIM_CDEV
+ tristate "Cdev AIM"
+
+ ---help---
+ Say Y here if you want to commumicate via character devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called aim_cdev.
\ No newline at end of file
diff --git a/drivers/staging/most/aim-cdev/Makefile b/drivers/staging/most/aim-cdev/Makefile
new file mode 100644
index 0000000..0bcc6c6
--- /dev/null
+++ b/drivers/staging/most/aim-cdev/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_AIM_CDEV) += aim_cdev.o
+
+aim_cdev-objs := cdev.o
+ccflags-y += -Idrivers/staging/most/mostcore/
\ No newline at end of file
diff --git a/drivers/staging/most/aim-cdev/cdev.c b/drivers/staging/most/aim-cdev/cdev.c
new file mode 100644
index 0000000..0a13d8d
--- /dev/null
+++ b/drivers/staging/most/aim-cdev/cdev.c
@@ -0,0 +1,528 @@
+/*
+ * cdev.c - Application interfacing module for character devices
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/cdev.h>
+#include <linux/kfifo.h>
+#include <linux/uaccess.h>
+#include <linux/idr.h>
+#include "mostcore.h"
+
+static dev_t aim_devno;
+static struct class *aim_class;
+static struct ida minor_id;
+static unsigned int major;
+
+struct aim_channel {
+ wait_queue_head_t wq;
+ struct cdev cdev;
+ struct device *dev;
+ struct mutex io_mutex;
+ struct most_interface *iface;
+ struct most_channel_config *cfg;
+ unsigned int channel_id;
+ dev_t devno;
+ bool keep_mbo;
+ unsigned int mbo_offs;
+ struct mbo *stacked_mbo;
+ DECLARE_KFIFO_PTR(fifo, typeof(struct mbo *));
+ atomic_t access_ref;
+ struct list_head list;
+};
+#define to_channel(d) container_of(d, struct aim_channel, cdev)
+static struct list_head channel_list;
+static spinlock_t ch_list_lock;
+
+
+static struct aim_channel *get_channel(struct most_interface *iface, int id)
+{
+ struct aim_channel *channel, *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)) {
+ found_channel = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&ch_list_lock, flags);
+ if (!found_channel)
+ return NULL;
+ return channel;
+}
+
+/**
+ * aim_open - implements the syscall to open the device
+ * @inode: inode pointer
+ * @filp: file pointer
+ *
+ * This stores the channel pointer in the private data field of
+ * the file structure and activates the channel within the core.
+ */
+static int aim_open(struct inode *inode, struct file *filp)
+{
+ struct aim_channel *channel;
+ int ret;
+
+ channel = to_channel(inode->i_cdev);
+ filp->private_data = channel;
+
+ if (((channel->cfg->direction == MOST_CH_RX) &&
+ ((filp->f_flags & O_ACCMODE) != O_RDONLY))
+ || ((channel->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)) {
+ pr_info("WARN: Device is busy\n");
+ atomic_dec(&channel->access_ref);
+ return -EBUSY;
+ }
+
+ ret = most_start_channel(channel->iface, channel->channel_id);
+ if (ret)
+ atomic_dec(&channel->access_ref);
+ return ret;
+}
+
+/**
+ * aim_close - implements the syscall to close the device
+ * @inode: inode pointer
+ * @filp: file pointer
+ *
+ * This stops the channel within the core.
+ */
+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;
+ }
+ mutex_unlock(&channel->io_mutex);
+
+ while (0 != kfifo_out((struct kfifo *)&channel->fifo, &mbo, 1))
+ most_put_mbo(mbo);
+ if (channel->keep_mbo == true)
+ most_put_mbo(channel->stacked_mbo);
+ ret = most_stop_channel(channel->iface, channel->channel_id);
+ atomic_dec(&channel->access_ref);
+ wake_up_interruptible(&channel->wq);
+ return ret;
+}
+
+/**
+ * aim_write - implements the syscall to write to the device
+ * @filp: file pointer
+ * @buf: pointer to user buffer
+ * @count: number of bytes to write
+ * @offset: offset from where to start writing
+ */
+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);
+
+ mbo = most_get_mbo(channel->iface, channel->channel_id);
+
+ if (!mbo && channel->dev) {
+ if ((filp->f_flags & O_NONBLOCK))
+ return -EAGAIN;
+ if (wait_event_interruptible(
+ channel->wq,
+ (mbo = most_get_mbo(channel->iface,
+ channel->channel_id)) ||
+ (channel->dev == NULL)))
+ return -ERESTARTSYS;
+ }
+
+ mutex_lock(&channel->io_mutex);
+ if (unlikely(!channel->dev)) {
+ mutex_unlock(&channel->io_mutex);
+ err = -EPIPE;
+ goto error;
+ }
+ mutex_unlock(&channel->io_mutex);
+
+ max_len = channel->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;
+ }
+
+ 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 (mbo)
+ most_put_mbo(mbo);
+ return err;
+}
+
+/**
+ * aim_read - implements the syscall to read from the device
+ * @filp: file pointer
+ * @buf: pointer to user buffer
+ * @count: number of bytes to read
+ * @offset: offset from where to start reading
+ */
+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;
+ struct mbo *mbo;
+ struct aim_channel *channel = filp->private_data;
+
+ if (channel->keep_mbo == true) {
+ mbo = channel->stacked_mbo;
+ channel->keep_mbo = false;
+ goto start_copy;
+ }
+ while ((0 == kfifo_out(&channel->fifo, &mbo, 1))
+ && (channel->dev != NULL)) {
+ if (filp->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ if (wait_event_interruptible(channel->wq,
+ (!kfifo_is_empty(&channel->fifo) ||
+ (channel->dev == NULL))))
+ return -ERESTARTSYS;
+ }
+
+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);
+ return -EIO;
+ }
+
+ if (count < mbo->processed_length)
+ channel->keep_mbo = true;
+
+ proc_len = min((int)count,
+ (int)(mbo->processed_length - channel->mbo_offs));
+
+ not_copied = copy_to_user(buf,
+ mbo->virt_address + channel->mbo_offs,
+ proc_len);
+
+ retval = not_copied ? proc_len - not_copied : proc_len;
+
+ if (channel->keep_mbo == true) {
+ channel->mbo_offs = retval;
+ channel->stacked_mbo = mbo;
+ } else {
+ most_put_mbo(mbo);
+ channel->mbo_offs = 0;
+ }
+ mutex_unlock(&channel->io_mutex);
+ return retval;
+}
+
+/**
+ * Initialization of struct file_operations
+ */
+static const struct file_operations channel_fops = {
+ .owner = THIS_MODULE,
+ .read = aim_read,
+ .write = aim_write,
+ .open = aim_open,
+ .release = aim_close,
+};
+
+/**
+ * aim_disconnect_channel - disconnect a channel
+ * @iface: pointer to interface instance
+ * @channel_id: channel index
+ *
+ * This frees allocated memory and removes the cdev that represents this
+ * channel in user space.
+ */
+static int aim_disconnect_channel(struct most_interface *iface, int channel_id)
+{
+ struct aim_channel *channel;
+ unsigned long flags;
+
+ if (!iface) {
+ pr_info("Bad interface pointer\n");
+ return -EINVAL;
+ }
+
+ channel = get_channel(iface, channel_id);
+ if (channel == NULL)
+ 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);
+ } else {
+ wake_up_interruptible(&channel->wq);
+ }
+ return 0;
+}
+
+/**
+ * aim_rx_completion - completion handler for rx channels
+ * @mbo: pointer to buffer object that has completed
+ *
+ * This searches for the channel linked to this MBO and stores it in the local
+ * fifo buffer.
+ */
+static int aim_rx_completion(struct mbo *mbo)
+{
+ struct aim_channel *channel;
+
+ if (!mbo)
+ return -EINVAL;
+
+ channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
+ if (channel == NULL)
+ return -ENXIO;
+
+ kfifo_in(&channel->fifo, &mbo, 1);
+#ifdef DEBUG_MESG
+ if (kfifo_is_full(&channel->fifo))
+ pr_info("WARN: Fifo is full\n");
+#endif
+ wake_up_interruptible(&channel->wq);
+ return 0;
+}
+
+/**
+ * aim_tx_completion - completion handler for tx channels
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ *
+ * This wakes sleeping processes in the wait-queue.
+ */
+static int aim_tx_completion(struct most_interface *iface, int channel_id)
+{
+ struct aim_channel *channel;
+
+ if (!iface) {
+ pr_info("Bad interface pointer\n");
+ return -EINVAL;
+ }
+ if ((channel_id < 0) || (channel_id >= iface->num_channels)) {
+ pr_info("Channel ID out of range\n");
+ return -EINVAL;
+ }
+
+ channel = get_channel(iface, channel_id);
+ if (channel == NULL)
+ return -ENXIO;
+ wake_up_interruptible(&channel->wq);
+ return 0;
+}
+
+static struct most_aim cdev_aim;
+
+/**
+ * aim_probe - probe function of the driver module
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ * @cfg: pointer to actual channel configuration
+ * @parent: pointer to kobject (needed for sysfs hook-up)
+ * @name: name of the device to be created
+ *
+ * This allocates achannel object and creates the device node in /dev
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int aim_probe(struct most_interface *iface, int channel_id,
+ struct most_channel_config *cfg,
+ struct kobject *parent, char *name)
+{
+ struct aim_channel *channel;
+ unsigned long cl_flags;
+ int retval;
+ int current_minor;
+
+ if ((!iface) || (!cfg) || (!parent) || (!name)) {
+ pr_info("Probing AIM with bad arguments");
+ return -EINVAL;
+ }
+ channel = get_channel(iface, channel_id);
+ if (channel)
+ 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) {
+ pr_info("failed to alloc channel object\n");
+ 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);
+ if (retval) {
+ pr_info("failed to alloc channel kfifo");
+ goto error_alloc_kfifo;
+ }
+ init_waitqueue_head(&channel->wq);
+ mutex_init(&channel->io_mutex);
+ spin_lock_irqsave(&ch_list_lock, cl_flags);
+ list_add_tail(&channel->list, &channel_list);
+ spin_unlock_irqrestore(&ch_list_lock, cl_flags);
+ channel->dev = device_create(aim_class,
+ NULL,
+ channel->devno,
+ NULL,
+ "%s", name);
+
+ retval = IS_ERR(channel->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);
+ return 0;
+
+error_create_device:
+ kfifo_free(&channel->fifo);
+ list_del(&channel->list);
+error_alloc_kfifo:
+ cdev_del(&channel->cdev);
+ kfree(channel);
+error_alloc_channel:
+ ida_simple_remove(&minor_id, current_minor);
+ return retval;
+}
+
+static struct most_aim cdev_aim = {
+ .name = "cdev",
+ .probe_channel = aim_probe,
+ .disconnect_channel = aim_disconnect_channel,
+ .rx_completion = aim_rx_completion,
+ .tx_completion = aim_tx_completion,
+};
+
+static int __init mod_init(void)
+{
+ pr_info("init()\n");
+
+ INIT_LIST_HEAD(&channel_list);
+ spin_lock_init(&ch_list_lock);
+ ida_init(&minor_id);
+
+ if (alloc_chrdev_region(&aim_devno, 0, 50, "cdev") < 0)
+ return -EIO;
+ major = MAJOR(aim_devno);
+
+ aim_class = class_create(THIS_MODULE, "most_cdev_aim");
+ if (IS_ERR(aim_class)) {
+ pr_err("no udev support\n");
+ goto free_cdev;
+ }
+
+ if (most_register_aim(&cdev_aim))
+ goto dest_class;
+ return 0;
+
+dest_class:
+ class_destroy(aim_class);
+free_cdev:
+ unregister_chrdev_region(aim_devno, 1);
+ return -EIO;
+}
+
+static void __exit mod_exit(void)
+{
+ struct aim_channel *channel, *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);
+ }
+ class_destroy(aim_class);
+ unregister_chrdev_region(aim_devno, 1);
+ ida_destroy(&minor_id);
+}
+
+module_init(mod_init);
+module_exit(mod_exit);
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("character device AIM for mostcore");
diff --git a/drivers/staging/most/aim-network/Kconfig b/drivers/staging/most/aim-network/Kconfig
new file mode 100644
index 0000000..4c66b24
--- /dev/null
+++ b/drivers/staging/most/aim-network/Kconfig
@@ -0,0 +1,13 @@
+#
+# MOST Networking configuration
+#
+
+config AIM_NETWORK
+ tristate "Networking AIM"
+ depends on NET
+
+ ---help---
+ Say Y here if you want to commumicate via a networking device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called aim_network.
diff --git a/drivers/staging/most/aim-network/Makefile b/drivers/staging/most/aim-network/Makefile
new file mode 100644
index 0000000..840c1dd
--- /dev/null
+++ b/drivers/staging/most/aim-network/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_AIM_NETWORK) += aim_network.o
+
+aim_network-objs := networking.o
+ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-network/networking.c b/drivers/staging/most/aim-network/networking.c
new file mode 100644
index 0000000..c8ab239
--- /dev/null
+++ b/drivers/staging/most/aim-network/networking.c
@@ -0,0 +1,567 @@
+/*
+ * Networking AIM - Networking Application Interface Module for MostCore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include "mostcore.h"
+#include "networking.h"
+
+
+#define MEP_HDR_LEN 8
+#define MDP_HDR_LEN 16
+#define MAMAC_DATA_LEN (1024 - MDP_HDR_LEN)
+
+#define PMHL 5
+
+#define PMS_TELID_UNSEGM_MAMAC 0x0A
+#define PMS_FIFONO_MDP 0x01
+#define PMS_FIFONO_MEP 0x04
+#define PMS_MSGTYPE_DATA 0x04
+#define PMS_DEF_PRIO 0
+#define MEP_DEF_RETRY 15
+
+#define PMS_FIFONO_MASK 0x07
+#define PMS_FIFONO_SHIFT 3
+#define PMS_RETRY_SHIFT 4
+#define PMS_TELID_MASK 0x0F
+#define PMS_TELID_SHIFT 4
+
+#define HB(value) ((u8)((u16)(value) >> 8))
+#define LB(value) ((u8)(value))
+
+
+
+#define EXTRACT_BIT_SET(bitset_name, value) \
+ (((value) >> bitset_name##_SHIFT) & bitset_name##_MASK)
+
+#define PMS_IS_MEP(buf, len) \
+ ((len) > MEP_HDR_LEN && \
+ EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MEP)
+
+#define PMS_IS_MAMAC(buf, len) \
+ ((len) > MDP_HDR_LEN && \
+ EXTRACT_BIT_SET(PMS_FIFONO, (buf)[3]) == PMS_FIFONO_MDP && \
+ EXTRACT_BIT_SET(PMS_TELID, (buf)[14]) == PMS_TELID_UNSEGM_MAMAC)
+
+struct net_dev_channel {
+ bool linked;
+ int ch_id;
+};
+
+struct net_dev_context {
+ struct most_interface *iface;
+ bool channels_opened;
+ bool is_mamac;
+ unsigned char link_stat;
+ struct net_device *dev;
+ struct net_dev_channel rx;
+ struct net_dev_channel tx;
+ struct list_head list;
+};
+
+static struct list_head net_devices = LIST_HEAD_INIT(net_devices);
+static struct spinlock list_lock;
+static struct most_aim aim;
+
+
+static int skb_to_mamac(const struct sk_buff *skb, struct mbo *mbo)
+{
+ u8 *buff = mbo->virt_address;
+ const u8 broadcast[] = { 0x03, 0xFF };
+ const u8 *dest_addr = skb->data + 4;
+ const u8 *eth_type = skb->data + 12;
+ unsigned int payload_len = skb->len - ETH_HLEN;
+ unsigned int mdp_len = payload_len + MDP_HDR_LEN;
+
+ if (mbo->buffer_length < mdp_len) {
+ pr_err("drop: too small buffer! (%d for %d)\n",
+ mbo->buffer_length, mdp_len);
+ return -EINVAL;
+ }
+
+ if (skb->len < ETH_HLEN) {
+ pr_err("drop: too small packet! (%d)\n", skb->len);
+ return -EINVAL;
+ }
+
+ if (dest_addr[0] == 0xFF && dest_addr[1] == 0xFF)
+ dest_addr = broadcast;
+
+ *buff++ = HB(mdp_len - 2);
+ *buff++ = LB(mdp_len - 2);
+
+ *buff++ = PMHL;
+ *buff++ = (PMS_FIFONO_MDP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
+ *buff++ = PMS_DEF_PRIO;
+ *buff++ = dest_addr[0];
+ *buff++ = dest_addr[1];
+ *buff++ = 0x00;
+
+ *buff++ = HB(payload_len + 6);
+ *buff++ = LB(payload_len + 6);
+
+ /* end of FPH here */
+
+ *buff++ = eth_type[0];
+ *buff++ = eth_type[1];
+ *buff++ = 0;
+ *buff++ = 0;
+
+ *buff++ = PMS_TELID_UNSEGM_MAMAC << 4 | HB(payload_len);
+ *buff++ = LB(payload_len);
+
+ memcpy(buff, skb->data + ETH_HLEN, payload_len);
+ mbo->buffer_length = mdp_len;
+ return 0;
+}
+
+static int skb_to_mep(const struct sk_buff *skb, struct mbo *mbo)
+{
+ u8 *buff = mbo->virt_address;
+ unsigned int mep_len = skb->len + MEP_HDR_LEN;
+
+ if (mbo->buffer_length < mep_len) {
+ pr_err("drop: too small buffer! (%d for %d)\n",
+ mbo->buffer_length, mep_len);
+ return -EINVAL;
+ }
+
+ *buff++ = HB(mep_len - 2);
+ *buff++ = LB(mep_len - 2);
+
+ *buff++ = PMHL;
+ *buff++ = (PMS_FIFONO_MEP << PMS_FIFONO_SHIFT) | PMS_MSGTYPE_DATA;
+ *buff++ = (MEP_DEF_RETRY << PMS_RETRY_SHIFT) | PMS_DEF_PRIO;
+ *buff++ = 0;
+ *buff++ = 0;
+ *buff++ = 0;
+
+ memcpy(buff, skb->data, skb->len);
+ mbo->buffer_length = mep_len;
+ return 0;
+}
+
+static int most_nd_set_mac_address(struct net_device *dev, void *p)
+{
+ struct net_dev_context *nd = dev->ml_priv;
+ int err = eth_mac_addr(dev, p);
+
+ if (err)
+ return err;
+
+ BUG_ON(nd->dev != dev);
+
+ nd->is_mamac =
+ (dev->dev_addr[0] == 0 && dev->dev_addr[1] == 0 &&
+ dev->dev_addr[2] == 0 && dev->dev_addr[3] == 0);
+
+ /*
+ * Set default MTU for the given packet type.
+ * It is still possible to change MTU using ip tools afterwards.
+ */
+ dev->mtu = nd->is_mamac ? MAMAC_DATA_LEN : ETH_DATA_LEN;
+
+ return 0;
+}
+
+static int most_nd_open(struct net_device *dev)
+{
+ struct net_dev_context *nd = dev->ml_priv;
+
+ pr_info("open net device %s\n", dev->name);
+
+ BUG_ON(nd->dev != dev);
+
+ if (nd->channels_opened)
+ return -EFAULT;
+
+ BUG_ON(!nd->tx.linked || !nd->rx.linked);
+
+ if (most_start_channel(nd->iface, nd->rx.ch_id)) {
+ pr_err("most_start_channel() failed\n");
+ return -EBUSY;
+ }
+
+ if (most_start_channel(nd->iface, nd->tx.ch_id)) {
+ pr_err("most_start_channel() failed\n");
+ most_stop_channel(nd->iface, nd->rx.ch_id);
+ return -EBUSY;
+ }
+
+ nd->channels_opened = true;
+
+ if (nd->is_mamac) {
+ nd->link_stat = 1;
+ netif_wake_queue(dev);
+ } else {
+ nd->iface->request_netinfo(nd->iface, nd->tx.ch_id);
+ }
+
+ return 0;
+}
+
+static int most_nd_stop(struct net_device *dev)
+{
+ struct net_dev_context *nd = dev->ml_priv;
+
+ pr_info("stop net device %s\n", dev->name);
+
+ BUG_ON(nd->dev != dev);
+ netif_stop_queue(dev);
+
+ if (nd->channels_opened) {
+ most_stop_channel(nd->iface, nd->rx.ch_id);
+ most_stop_channel(nd->iface, nd->tx.ch_id);
+ nd->channels_opened = false;
+ }
+
+ return 0;
+}
+
+static netdev_tx_t most_nd_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct net_dev_context *nd = dev->ml_priv;
+ struct mbo *mbo;
+ int ret;
+
+ BUG_ON(nd->dev != dev);
+
+ mbo = most_get_mbo(nd->iface, nd->tx.ch_id);
+
+ if (!mbo) {
+ netif_stop_queue(dev);
+ dev->stats.tx_fifo_errors++;
+ return NETDEV_TX_BUSY;
+ }
+
+ if (nd->is_mamac)
+ ret = skb_to_mamac(skb, mbo);
+ else
+ ret = skb_to_mep(skb, mbo);
+
+ if (ret) {
+ most_put_mbo(mbo);
+ dev->stats.tx_dropped++;
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ most_submit_mbo(mbo);
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+static const struct net_device_ops most_nd_ops = {
+ .ndo_open = most_nd_open,
+ .ndo_stop = most_nd_stop,
+ .ndo_start_xmit = most_nd_start_xmit,
+ .ndo_set_mac_address = most_nd_set_mac_address,
+};
+
+static void most_nd_setup(struct net_device *dev)
+{
+ pr_info("setup net device %s\n", dev->name);
+ ether_setup(dev);
+ dev->netdev_ops = &most_nd_ops;
+}
+
+static void most_net_rm_netdev_safe(struct net_dev_context *nd)
+{
+ if (!nd->dev)
+ return;
+
+ pr_info("remove net device %p\n", nd->dev);
+
+ unregister_netdev(nd->dev);
+ free_netdev(nd->dev);
+ nd->dev = 0;
+}
+
+static struct net_dev_context *get_net_dev_context(
+ struct most_interface *iface)
+{
+ struct net_dev_context *nd, *tmp;
+
+ spin_lock(&list_lock);
+ list_for_each_entry_safe(nd, tmp, &net_devices, list) {
+ if (nd->iface == iface) {
+ spin_unlock(&list_lock);
+ return nd;
+ }
+ }
+ spin_unlock(&list_lock);
+ return NULL;
+}
+
+static int aim_probe_channel(struct most_interface *iface, int channel_idx,
+ struct most_channel_config *ccfg,
+ struct kobject *parent, char *name)
+{
+ struct net_dev_context *nd;
+ struct net_dev_channel *ch;
+
+ if (!iface)
+ return -EINVAL;
+
+ if (ccfg->data_type != MOST_CH_ASYNC)
+ return -EINVAL;
+
+ nd = get_net_dev_context(iface);
+
+ if (!nd) {
+ nd = kzalloc(sizeof(*nd), GFP_KERNEL);
+ if (!nd)
+ return -ENOMEM;
+
+ nd->iface = iface;
+
+ spin_lock(&list_lock);
+ list_add(&nd->list, &net_devices);
+ spin_unlock(&list_lock);
+ }
+
+ ch = ccfg->direction == MOST_CH_TX ? &nd->tx : &nd->rx;
+ if (ch->linked) {
+ pr_err("only one channel per instance & direction allowed\n");
+ return -EINVAL;
+ }
+
+ if (nd->tx.linked || nd->rx.linked) {
+ struct net_device *dev =
+ alloc_netdev(0, "meth%d", NET_NAME_UNKNOWN, most_nd_setup);
+
+ if (!dev) {
+ pr_err("no memory for net_device\n");
+ return -ENOMEM;
+ }
+
+ nd->dev = dev;
+
+ dev->ml_priv = nd;
+ if (register_netdev(dev)) {
+ pr_err("registering net device failed\n");
+ free_netdev(dev);
+ return -EINVAL;
+ }
+ }
+
+ ch->ch_id = channel_idx;
+ ch->linked = true;
+
+ return 0;
+}
+
+static int aim_disconnect_channel(struct most_interface *iface,
+ int channel_idx)
+{
+ struct net_dev_context *nd;
+ struct net_dev_channel *ch;
+
+ nd = get_net_dev_context(iface);
+ if (!nd)
+ return -EINVAL;
+
+ if (nd->rx.linked && channel_idx == nd->rx.ch_id)
+ ch = &nd->rx;
+ else if (nd->tx.linked && channel_idx == nd->tx.ch_id)
+ ch = &nd->tx;
+ else
+ return -EINVAL;
+
+ ch->linked = false;
+
+ /*
+ * do not call most_stop_channel() here, because channels are
+ * going to be closed in ndo_stop() after unregister_netdev()
+ */
+ most_net_rm_netdev_safe(nd);
+
+ if (!nd->rx.linked && !nd->tx.linked) {
+ spin_lock(&list_lock);
+ list_del(&nd->list);
+ spin_unlock(&list_lock);
+ kfree(nd);
+ }
+
+ return 0;
+}
+
+static int aim_resume_tx_channel(struct most_interface *iface,
+ int channel_idx)
+{
+ struct net_dev_context *nd;
+
+ nd = get_net_dev_context(iface);
+ if (!nd || !nd->channels_opened || nd->tx.ch_id != channel_idx)
+ return 0;
+
+ if (!nd->dev)
+ return 0;
+
+ netif_wake_queue(nd->dev);
+ return 0;
+}
+
+static int aim_rx_data(struct mbo *mbo)
+{
+ const u32 zero = 0;
+ struct net_dev_context *nd;
+ char *buf = mbo->virt_address;
+ uint32_t len = mbo->processed_length;
+ struct sk_buff *skb;
+ struct net_device *dev;
+
+ nd = get_net_dev_context(mbo->ifp);
+ if (!nd || !nd->channels_opened || nd->rx.ch_id != mbo->hdm_channel_id)
+ return -EIO;
+
+ dev = nd->dev;
+ if (!dev) {
+ pr_err_once("drop packet: missing net_device\n");
+ return -EIO;
+ }
+
+ if (nd->is_mamac) {
+ if (!PMS_IS_MAMAC(buf, len))
+ return -EIO;
+
+ skb = dev_alloc_skb(len - MDP_HDR_LEN + 2 * ETH_ALEN + 2);
+ } else {
+ if (!PMS_IS_MEP(buf, len))
+ return -EIO;
+
+ skb = dev_alloc_skb(len - MEP_HDR_LEN);
+ }
+
+ if (!skb) {
+ dev->stats.rx_dropped++;
+ pr_err_once("drop packet: no memory for skb\n");
+ goto out;
+ }
+
+ skb->dev = dev;
+
+ if (nd->is_mamac) {
+ /* dest */
+ memcpy(skb_put(skb, ETH_ALEN), dev->dev_addr, ETH_ALEN);
+
+ /* src */
+ memcpy(skb_put(skb, 4), &zero, 4);
+ memcpy(skb_put(skb, 2), buf + 5, 2);
+
+ /* eth type */
+ memcpy(skb_put(skb, 2), buf + 10, 2);
+
+ buf += MDP_HDR_LEN;
+ len -= MDP_HDR_LEN;
+ } else {
+ buf += MEP_HDR_LEN;
+ len -= MEP_HDR_LEN;
+ }
+
+ 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);
+
+out:
+ most_put_mbo(mbo);
+ return 0;
+}
+
+static int __init most_net_init(void)
+{
+ pr_info("most_net_init()\n");
+ spin_lock_init(&list_lock);
+ aim.name = "networking";
+ aim.probe_channel = aim_probe_channel;
+ aim.disconnect_channel = aim_disconnect_channel;
+ aim.tx_completion = aim_resume_tx_channel;
+ aim.rx_completion = aim_rx_data;
+ return most_register_aim(&aim);
+}
+
+static void __exit most_net_exit(void)
+{
+ struct net_dev_context *nd, *tmp;
+
+ spin_lock(&list_lock);
+ list_for_each_entry_safe(nd, tmp, &net_devices, list) {
+ list_del(&nd->list);
+ spin_unlock(&list_lock);
+ /*
+ * do not call most_stop_channel() here, because channels are
+ * going to be closed in ndo_stop() after unregister_netdev()
+ */
+ most_net_rm_netdev_safe(nd);
+ kfree(nd);
+ spin_lock(&list_lock);
+ }
+ spin_unlock(&list_lock);
+
+ most_deregister_aim(&aim);
+ pr_info("most_net_exit()\n");
+}
+
+/**
+ * most_deliver_netinfo - callback for HDM to be informed about HW's MAC
+ * @param iface - most interface instance
+ * @param link_stat - link status
+ * @param mac_addr - MAC address
+ */
+void most_deliver_netinfo(struct most_interface *iface,
+ unsigned char link_stat, unsigned char *mac_addr)
+{
+ struct net_dev_context *nd;
+ struct net_device *dev;
+
+ pr_info("Received netinfo from %s\n", iface->description);
+
+ nd = get_net_dev_context(iface);
+ if (!nd)
+ return;
+
+ dev = nd->dev;
+ if (!dev)
+ return;
+
+ if (mac_addr)
+ memcpy(dev->dev_addr, mac_addr, ETH_ALEN);
+
+ if (nd->link_stat != link_stat) {
+ nd->link_stat = link_stat;
+ if (nd->link_stat)
+ netif_wake_queue(dev);
+ else
+ netif_stop_queue(dev);
+ }
+}
+EXPORT_SYMBOL(most_deliver_netinfo);
+
+module_init(most_net_init);
+module_exit(most_net_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("Networking Application Interface Module for MostCore");
diff --git a/drivers/staging/most/aim-network/networking.h b/drivers/staging/most/aim-network/networking.h
new file mode 100644
index 0000000..1b8b434
--- /dev/null
+++ b/drivers/staging/most/aim-network/networking.h
@@ -0,0 +1,23 @@
+/*
+ * Networking AIM - Networking Application Interface Module for MostCore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+#ifndef _NETWORKING_H_
+#define _NETWORKING_H_
+
+#include "mostcore.h"
+
+
+void most_deliver_netinfo(struct most_interface *iface,
+ unsigned char link_stat, unsigned char *mac_addr);
+
+
+#endif
diff --git a/drivers/staging/most/aim-sound/Kconfig b/drivers/staging/most/aim-sound/Kconfig
new file mode 100644
index 0000000..3194c21
--- /dev/null
+++ b/drivers/staging/most/aim-sound/Kconfig
@@ -0,0 +1,13 @@
+#
+# MOST ALSA configuration
+#
+
+config AIM_SOUND
+ tristate "ALSA AIM"
+ depends on SND
+ select SND_PCM
+ ---help---
+ Say Y here if you want to commumicate via ALSA/sound devices.
+
+ To compile this driver as a module, choose M here: the
+ module will be called aim_sound.
diff --git a/drivers/staging/most/aim-sound/Makefile b/drivers/staging/most/aim-sound/Makefile
new file mode 100644
index 0000000..beba958
--- /dev/null
+++ b/drivers/staging/most/aim-sound/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_AIM_SOUND) += aim_sound.o
+
+aim_sound-objs := sound.o
+ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/aim-sound/sound.c b/drivers/staging/most/aim-sound/sound.c
new file mode 100644
index 0000000..860302e
--- /dev/null
+++ b/drivers/staging/most/aim-sound/sound.c
@@ -0,0 +1,758 @@
+/*
+ * sound.c - Audio Application Interface Module for Mostcore
+ *
+ * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <mostcore.h>
+
+#define DRIVER_NAME "sound"
+
+static struct list_head dev_list;
+
+/**
+ * struct channel - private structure to keep channel specific data
+ * @substream: stores the substream structure
+ * @iface: interface for which the channel belongs to
+ * @cfg: channel configuration
+ * @card: registered sound card
+ * @list: list for private use
+ * @id: channel index
+ * @period_pos: current period position (ring buffer)
+ * @buffer_pos: current buffer position (ring buffer)
+ * @is_stream_running: identifies whether a stream is running or not
+ * @opened: set when the stream is opened
+ * @playback_task: playback thread
+ * @playback_waitq: waitq used by playback thread
+ */
+struct channel {
+ struct snd_pcm_substream *substream;
+ struct most_interface *iface;
+ struct most_channel_config *cfg;
+ struct snd_card *card;
+ struct list_head list;
+ int id;
+ unsigned int period_pos;
+ unsigned int buffer_pos;
+ bool is_stream_running;
+
+ struct task_struct *playback_task;
+ wait_queue_head_t playback_waitq;
+
+ void (*copy_fn)(void *alsa, void *most, unsigned int bytes);
+};
+
+#define MOST_PCM_INFO (SNDRV_PCM_INFO_MMAP | \
+ SNDRV_PCM_INFO_MMAP_VALID | \
+ SNDRV_PCM_INFO_BATCH | \
+ SNDRV_PCM_INFO_INTERLEAVED | \
+ SNDRV_PCM_INFO_BLOCK_TRANSFER)
+
+/**
+ * Initialization of struct snd_pcm_hardware
+ */
+static struct snd_pcm_hardware pcm_hardware_template = {
+ .info = MOST_PCM_INFO,
+ .rates = SNDRV_PCM_RATE_48000,
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 8,
+};
+
+#define swap16(val) ( \
+ (((u16)(val) << 8) & (u16)0xFF00) | \
+ (((u16)(val) >> 8) & (u16)0x00FF))
+
+#define swap32(val) ( \
+ (((u32)(val) << 24) & (u32)0xFF000000) | \
+ (((u32)(val) << 8) & (u32)0x00FF0000) | \
+ (((u32)(val) >> 8) & (u32)0x0000FF00) | \
+ (((u32)(val) >> 24) & (u32)0x000000FF))
+
+static void swap_copy16(u16 *dest, const u16 *source, unsigned int bytes)
+{
+ unsigned int i = 0;
+
+ while (i < (bytes / 2)) {
+ dest[i] = swap16(source[i]);
+ i++;
+ }
+}
+
+static void swap_copy24(u8 *dest, const u8 *source, unsigned int bytes)
+{
+ unsigned int i = 0;
+
+ while (i < bytes - 2) {
+ dest[i] = source[i + 2];
+ dest[i + 1] = source[i + 1];
+ dest[i + 2] = source[i];
+ i += 3;
+ }
+}
+
+static void swap_copy32(u32 *dest, const u32 *source, unsigned int bytes)
+{
+ unsigned int i = 0;
+
+ while (i < bytes / 4) {
+ dest[i] = swap32(source[i]);
+ i++;
+ }
+}
+
+static void alsa_to_most_memcpy(void *alsa, void *most, unsigned int bytes)
+{
+ memcpy(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy16(void *alsa, void *most, unsigned int bytes)
+{
+ swap_copy16(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy24(void *alsa, void *most, unsigned int bytes)
+{
+ swap_copy24(most, alsa, bytes);
+}
+
+static void alsa_to_most_copy32(void *alsa, void *most, unsigned int bytes)
+{
+ swap_copy32(most, alsa, bytes);
+}
+
+static void most_to_alsa_memcpy(void *alsa, void *most, unsigned int bytes)
+{
+ memcpy(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy16(void *alsa, void *most, unsigned int bytes)
+{
+ swap_copy16(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy24(void *alsa, void *most, unsigned int bytes)
+{
+ swap_copy24(alsa, most, bytes);
+}
+
+static void most_to_alsa_copy32(void *alsa, void *most, unsigned int bytes)
+{
+ swap_copy32(alsa, most, bytes);
+}
+
+/**
+ * get_channel - get pointer to channel
+ * @iface: interface structure
+ * @channel_id: channel ID
+ *
+ * This traverses the channel list and returns the channel matching the
+ * ID and interface.
+ *
+ * Returns pointer to channel on success or NULL otherwise.
+ */
+static struct channel *get_channel(struct most_interface *iface,
+ int channel_id)
+{
+ struct channel *channel, *tmp;
+
+ list_for_each_entry_safe(channel, tmp, &dev_list, list) {
+ if ((channel->iface == iface) && (channel->id == channel_id))
+ return channel;
+ }
+
+ return NULL;
+}
+
+/**
+ * copy_data - implements data copying function
+ * @channel: channel
+ * @mbo: MBO from core
+ *
+ * Copy data from/to ring buffer to/from MBO and update the buffer position
+ */
+static bool copy_data(struct channel *channel, struct mbo *mbo)
+{
+ struct snd_pcm_runtime *const runtime = channel->substream->runtime;
+ unsigned int const frame_bytes = channel->cfg->subbuffer_size;
+ unsigned int const buffer_size = runtime->buffer_size;
+ unsigned int frames;
+ unsigned int fr0;
+
+ if (channel->cfg->direction & MOST_CH_RX)
+ frames = mbo->processed_length / frame_bytes;
+ else
+ frames = mbo->buffer_length / frame_bytes;
+ fr0 = min(buffer_size - channel->buffer_pos, frames);
+
+ channel->copy_fn(runtime->dma_area + channel->buffer_pos * frame_bytes,
+ mbo->virt_address,
+ fr0 * frame_bytes);
+
+ if (frames > fr0) {
+ /* wrap around at end of ring buffer */
+ channel->copy_fn(runtime->dma_area,
+ mbo->virt_address + fr0 * frame_bytes,
+ (frames - fr0) * frame_bytes);
+ }
+
+ channel->buffer_pos += frames;
+ if (channel->buffer_pos >= buffer_size)
+ channel->buffer_pos -= buffer_size;
+ channel->period_pos += frames;
+ if (channel->period_pos >= runtime->period_size) {
+ channel->period_pos -= runtime->period_size;
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * playback_thread - function implements the playback thread
+ * @data: private data
+ *
+ * Thread which does the playback functionality in a loop. It waits for a free
+ * MBO from mostcore for a particular channel and copy the data from ring buffer
+ * to MBO. Submit the MBO back to mostcore, after copying the data.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int playback_thread(void *data)
+{
+ struct channel *const channel = data;
+
+ pr_info("playback thread started\n");
+
+ while (!kthread_should_stop()) {
+ struct mbo *mbo = NULL;
+ bool period_elapsed = false;
+ int ret;
+
+ wait_event_interruptible(
+ channel->playback_waitq,
+ kthread_should_stop() ||
+ (mbo = most_get_mbo(channel->iface, channel->id)));
+
+ if (!mbo)
+ continue;
+
+ if (channel->is_stream_running)
+ period_elapsed = copy_data(channel, mbo);
+ else
+ memset(mbo->virt_address, 0, mbo->buffer_length);
+
+ ret = most_submit_mbo(mbo);
+ if (ret)
+ channel->is_stream_running = false;
+
+ if (period_elapsed)
+ snd_pcm_period_elapsed(channel->substream);
+ }
+
+ return 0;
+}
+
+/**
+ * pcm_open - implements open callback function for PCM middle layer
+ * @substream: pointer to ALSA PCM substream
+ *
+ * This is called when a PCM substream is opened. At least, the function should
+ * initialize the runtime->hw record.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_open(struct snd_pcm_substream *substream)
+{
+ struct channel *channel = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct most_channel_config *cfg = channel->cfg;
+
+ pr_info("pcm_open(), %s\n", substream->name);
+
+ channel->substream = substream;
+
+ if (cfg->direction == MOST_CH_TX) {
+ init_waitqueue_head(&channel->playback_waitq);
+ channel->playback_task = kthread_run(&playback_thread, channel,
+ "most_audio_playback");
+ if (IS_ERR(channel->playback_task))
+ return PTR_ERR(channel->playback_task);
+ }
+
+ if (most_start_channel(channel->iface, channel->id)) {
+ pr_err("most_start_channel() failed!\n");
+ if (cfg->direction == MOST_CH_TX)
+ kthread_stop(channel->playback_task);
+ return -EBUSY;
+ }
+
+ runtime->hw = pcm_hardware_template;
+ runtime->hw.buffer_bytes_max = cfg->num_buffers * cfg->buffer_size;
+ runtime->hw.period_bytes_min = cfg->buffer_size;
+ runtime->hw.period_bytes_max = cfg->buffer_size;
+ runtime->hw.periods_min = 1;
+ runtime->hw.periods_max = cfg->num_buffers;
+
+ return 0;
+}
+
+/**
+ * pcm_close - implements close callback function for PCM middle layer
+ * @substream: sub-stream pointer
+ *
+ * Obviously, this is called when a PCM substream is closed. Any private
+ * instance for a PCM substream allocated in the open callback will be
+ * released here.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_close(struct snd_pcm_substream *substream)
+{
+ struct channel *channel = substream->private_data;
+
+ pr_info("pcm_close(), %s\n", substream->name);
+
+ if (channel->cfg->direction == MOST_CH_TX)
+ kthread_stop(channel->playback_task);
+ most_stop_channel(channel->iface, channel->id);
+
+ return 0;
+}
+
+/**
+ * pcm_hw_params - implements hw_params callback function for PCM middle layer
+ * @substream: sub-stream pointer
+ * @hw_params: contains the hardware parameters set by the application
+ *
+ * This is called when the hardware parameters is set by the application, that
+ * is, once when the buffer size, the period size, the format, etc. are defined
+ * for the PCM substream. Many hardware setups should be done is this callback,
+ * including the allocation of buffers.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ pr_info("pcm_hw_params()\n");
+
+ return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+ params_buffer_bytes(hw_params));
+}
+
+/**
+ * pcm_hw_free - implements hw_free callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This is called to release the resources allocated via hw_params.
+ * This function will be always called before the close callback is called.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ pr_info("pcm_hw_free()\n");
+
+ return snd_pcm_lib_free_vmalloc_buffer(substream);
+}
+
+/**
+ * pcm_prepare - implements prepare callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This callback is called when the PCM is "prepared". Format rate, sample rate,
+ * etc., can be set here. This callback can be called many times at each setup.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct channel *channel = substream->private_data;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct most_channel_config *cfg = channel->cfg;
+ int width = snd_pcm_format_physical_width(runtime->format);
+
+ channel->copy_fn = NULL;
+
+ if (cfg->direction == MOST_CH_TX) {
+ if (snd_pcm_format_big_endian(runtime->format) || width == 8)
+ channel->copy_fn = alsa_to_most_memcpy;
+ else if (width == 16)
+ channel->copy_fn = alsa_to_most_copy16;
+ else if (width == 24)
+ channel->copy_fn = alsa_to_most_copy24;
+ else if (width == 32)
+ channel->copy_fn = alsa_to_most_copy32;
+ } else {
+ if (snd_pcm_format_big_endian(runtime->format) || width == 8)
+ channel->copy_fn = most_to_alsa_memcpy;
+ else if (width == 16)
+ channel->copy_fn = most_to_alsa_copy16;
+ else if (width == 24)
+ channel->copy_fn = most_to_alsa_copy24;
+ else if (width == 32)
+ channel->copy_fn = most_to_alsa_copy32;
+ }
+
+ if (!channel->copy_fn) {
+ pr_err("unsupported format\n");
+ return -EINVAL;
+ }
+
+ channel->period_pos = 0;
+ channel->buffer_pos = 0;
+
+ return 0;
+}
+
+/**
+ * pcm_trigger - implements trigger callback function for PCM middle layer
+ * @substream: substream pointer
+ * @cmd: action to perform
+ *
+ * This is called when the PCM is started, stopped or paused. The action will be
+ * specified in the second argument, SNDRV_PCM_TRIGGER_XXX
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct channel *channel = substream->private_data;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ channel->is_stream_running = true;
+ return 0;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ channel->is_stream_running = false;
+ return 0;
+
+ default:
+ pr_info("pcm_trigger(), invalid\n");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/**
+ * pcm_pointer - implements pointer callback function for PCM middle layer
+ * @substream: substream pointer
+ *
+ * This callback is called when the PCM middle layer inquires the current
+ * hardware position on the buffer. The position must be returned in frames,
+ * ranging from 0 to buffer_size-1.
+ */
+static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct channel *channel = substream->private_data;
+
+ return channel->buffer_pos;
+}
+
+/**
+ * Initialization of struct snd_pcm_ops
+ */
+static struct snd_pcm_ops pcm_ops = {
+ .open = pcm_open,
+ .close = pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = pcm_hw_params,
+ .hw_free = pcm_hw_free,
+ .prepare = pcm_prepare,
+ .trigger = pcm_trigger,
+ .pointer = pcm_pointer,
+ .page = snd_pcm_lib_get_vmalloc_page,
+ .mmap = snd_pcm_lib_mmap_vmalloc,
+};
+
+
+int split_arg_list(char *buf, char **card_name, char **pcm_format)
+{
+ *card_name = strsep(&buf, ".");
+ if (!*card_name)
+ return -EIO;
+ *pcm_format = strsep(&buf, ".\n");
+ if (!*pcm_format)
+ return -EIO;
+ return 0;
+}
+
+int audio_set_pcm_format(char *pcm_format, struct most_channel_config *cfg)
+{
+ if (!strcmp(pcm_format, "1x8")) {
+ if (cfg->subbuffer_size != 1)
+ goto error;
+ pr_info("PCM format is 8-bit mono\n");
+ pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S8;
+ } else if (!strcmp(pcm_format, "2x16")) {
+ if (cfg->subbuffer_size != 4)
+ goto error;
+ pr_info("PCM format is 16-bit stereo\n");
+ pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S16_BE;
+ } else if (!strcmp(pcm_format, "2x24")) {
+ if (cfg->subbuffer_size != 6)
+ goto error;
+ pr_info("PCM format is 24-bit stereo\n");
+ pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S24_3LE |
+ SNDRV_PCM_FMTBIT_S24_3BE;
+ } else if (!strcmp(pcm_format, "2x32")) {
+ if (cfg->subbuffer_size != 8)
+ goto error;
+ pr_info("PCM format is 32-bit stereo\n");
+ pcm_hardware_template.formats = SNDRV_PCM_FMTBIT_S32_LE |
+ SNDRV_PCM_FMTBIT_S32_BE;
+ } else {
+ pr_err("PCM format %s not supported\n", pcm_format);
+ return -EIO;
+ }
+ return 0;
+error:
+ pr_err("Audio resolution doesn't fit subbuffer size\n");
+ return -EINVAL;
+}
+
+/**
+ * audio_probe_channel - probe function of the driver module
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ * @cfg: pointer to actual channel configuration
+ * @parent: pointer to kobject (needed for sysfs hook-up)
+ * @arg_list: string that provides the name of the device to be created in /dev
+ * plus the desired audio resolution
+ *
+ * Creates sound card, pcm device, sets pcm ops and registers sound card.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_probe_channel(struct most_interface *iface, int channel_id,
+ struct most_channel_config *cfg,
+ struct kobject *parent, char *arg_list)
+{
+ struct channel *channel;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ int playback_count = 0;
+ int capture_count = 0;
+ int ret;
+ int direction;
+ char *card_name;
+ char *pcm_format;
+
+ pr_info("sound_probe_channel()\n");
+
+ if (!iface)
+ return -EINVAL;
+
+ if (cfg->data_type != MOST_CH_SYNC) {
+ pr_err("Incompatible channel type\n");
+ return -EINVAL;
+ }
+
+ if (get_channel(iface, channel_id)) {
+ pr_err("channel (%s:%d) is already linked\n",
+ iface->description, channel_id);
+ return -EINVAL;
+ }
+
+ if (cfg->direction == MOST_CH_TX) {
+ playback_count = 1;
+ direction = SNDRV_PCM_STREAM_PLAYBACK;
+ } else {
+ capture_count = 1;
+ direction = SNDRV_PCM_STREAM_CAPTURE;
+ }
+
+ ret = split_arg_list(arg_list, &card_name, &pcm_format);
+ if (ret < 0) {
+ pr_info("PCM format missing\n");
+ return ret;
+ }
+ if (audio_set_pcm_format(pcm_format, cfg))
+ return ret;
+
+ ret = snd_card_new(NULL, -1, card_name, THIS_MODULE,
+ sizeof(*channel), &card);
+ if (ret < 0)
+ return ret;
+
+ channel = card->private_data;
+ channel->card = card;
+ channel->cfg = cfg;
+ channel->iface = iface;
+ channel->id = channel_id;
+
+ snprintf(card->driver, sizeof(card->driver), "%s", DRIVER_NAME);
+ snprintf(card->shortname, sizeof(card->shortname), "MOST:%d",
+ card->number);
+ snprintf(card->longname, sizeof(card->longname), "%s at %s, ch %d",
+ card->shortname, iface->description, channel_id);
+
+ ret = snd_pcm_new(card, card_name, 0, playback_count,
+ capture_count, &pcm);
+ if (ret < 0)
+ goto err_free_card;
+
+ pcm->private_data = channel;
+
+ snd_pcm_set_ops(pcm, direction, &pcm_ops);
+
+ ret = snd_card_register(card);
+ if (ret < 0)
+ goto err_free_card;
+
+ list_add_tail(&channel->list, &dev_list);
+
+ return 0;
+
+err_free_card:
+ snd_card_free(card);
+ return ret;
+}
+
+/**
+ * audio_disconnect_channel - function to disconnect a channel
+ * @iface: pointer to interface instance
+ * @channel_id: channel index
+ *
+ * This frees allocated memory and removes the sound card from ALSA
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_disconnect_channel(struct most_interface *iface,
+ int channel_id)
+{
+ struct channel *channel;
+
+ pr_info("sound_disconnect_channel()\n");
+
+ channel = get_channel(iface, channel_id);
+ if (!channel) {
+ pr_err("sound_disconnect_channel(), invalid channel %d\n",
+ channel_id);
+ return -EINVAL;
+ }
+
+ list_del(&channel->list);
+ snd_card_free(channel->card);
+
+ return 0;
+}
+
+/**
+ * audio_rx_completion - completion handler for rx channels
+ * @mbo: pointer to buffer object that has completed
+ *
+ * This searches for the channel this MBO belongs to and copy the data from MBO
+ * to ring buffer
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_rx_completion(struct mbo *mbo)
+{
+ struct channel *channel = get_channel(mbo->ifp, mbo->hdm_channel_id);
+ bool period_elapsed = false;
+
+ if (!channel) {
+ pr_err("sound_rx_completion(), invalid channel %d\n",
+ mbo->hdm_channel_id);
+ return -EINVAL;
+ }
+
+ if (channel->is_stream_running)
+ period_elapsed = copy_data(channel, mbo);
+
+ most_put_mbo(mbo);
+
+ if (period_elapsed)
+ snd_pcm_period_elapsed(channel->substream);
+
+ return 0;
+}
+
+/**
+ * audio_tx_completion - completion handler for tx channels
+ * @iface: pointer to interface instance
+ * @channel_id: channel index/ID
+ *
+ * This searches the channel that belongs to this combination of interface
+ * pointer and channel ID and wakes a process sitting in the wait queue of
+ * this channel.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int audio_tx_completion(struct most_interface *iface, int channel_id)
+{
+ struct channel *channel = get_channel(iface, channel_id);
+
+ if (!channel) {
+ pr_err("sound_tx_completion(), invalid channel %d\n",
+ channel_id);
+ return -EINVAL;
+ }
+
+ wake_up_interruptible(&channel->playback_waitq);
+
+ return 0;
+}
+
+/**
+ * Initialization of the struct most_aim
+ */
+static struct most_aim audio_aim = {
+ .name = DRIVER_NAME,
+ .probe_channel = audio_probe_channel,
+ .disconnect_channel = audio_disconnect_channel,
+ .rx_completion = audio_rx_completion,
+ .tx_completion = audio_tx_completion,
+};
+
+static int __init audio_init(void)
+{
+ pr_info("init()\n");
+
+ INIT_LIST_HEAD(&dev_list);
+
+ return most_register_aim(&audio_aim);
+}
+
+static void __exit audio_exit(void)
+{
+ struct channel *channel, *tmp;
+
+ pr_info("exit()\n");
+
+ list_for_each_entry_safe(channel, tmp, &dev_list, list) {
+ list_del(&channel->list);
+ snd_card_free(channel->card);
+ }
+
+ most_deregister_aim(&audio_aim);
+}
+
+module_init(audio_init);
+module_exit(audio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("Audio Application Interface Module for MostCore");
diff --git a/drivers/staging/most/aim-v4l2/Kconfig b/drivers/staging/most/aim-v4l2/Kconfig
new file mode 100644
index 0000000..d70eaaf
--- /dev/null
+++ b/drivers/staging/most/aim-v4l2/Kconfig
@@ -0,0 +1,12 @@
+#
+# MOST V4L2 configuration
+#
+
+config AIM_V4L2
+ tristate "V4L2 AIM"
+ depends on VIDEO_V4L2
+ ---help---
+ Say Y here if you want to commumicate via Video 4 Linux.
+
+ To compile this driver as a module, choose M here: the
+ module will be called aim_v4l2.
\ No newline at end of file
diff --git a/drivers/staging/most/aim-v4l2/Makefile b/drivers/staging/most/aim-v4l2/Makefile
new file mode 100644
index 0000000..28aa948
--- /dev/null
+++ b/drivers/staging/most/aim-v4l2/Makefile
@@ -0,0 +1,6 @@
+obj-$(CONFIG_AIM_V4L2) += aim_v4l2.o
+
+aim_v4l2-objs := video.o
+
+ccflags-y += -Idrivers/staging/most/mostcore/
+ccflags-y += -Idrivers/media/video
diff --git a/drivers/staging/most/aim-v4l2/video.c b/drivers/staging/most/aim-v4l2/video.c
new file mode 100644
index 0000000..d968791
--- /dev/null
+++ b/drivers/staging/most/aim-v4l2/video.c
@@ -0,0 +1,635 @@
+/*
+ * V4L2 AIM - V4L2 Application Interface Module for MostCore
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/suspend.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+
+#include "mostcore.h"
+
+
+#define V4L2_AIM_MAX_INPUT 1
+
+
+struct most_video_dev {
+ struct most_interface *iface;
+ int ch_idx;
+ struct list_head list;
+ bool mute;
+
+ struct list_head pending_mbos;
+ spinlock_t list_lock;
+
+ struct v4l2_device v4l2_dev;
+ atomic_t access_ref;
+ struct video_device *vdev;
+ unsigned int ctrl_input;
+
+ struct mutex lock;
+
+ wait_queue_head_t wait_data;
+};
+
+struct aim_fh {
+ /* must be the first field of this struct! */
+ struct v4l2_fh fh;
+ struct most_video_dev *mdev;
+ u32 offs;
+};
+
+
+static struct list_head video_devices = LIST_HEAD_INIT(video_devices);
+static struct spinlock list_lock;
+static struct most_aim aim_info;
+
+
+static inline bool data_ready(struct most_video_dev *mdev)
+{
+ return !list_empty(&mdev->pending_mbos);
+}
+
+static inline struct mbo *get_top_mbo(struct most_video_dev *mdev)
+{
+ return list_first_entry(&mdev->pending_mbos, struct mbo, list);
+}
+
+
+static int aim_vdev_open(struct file *filp)
+{
+ int ret;
+ struct video_device *vdev = video_devdata(filp);
+ struct most_video_dev *mdev = video_drvdata(filp);
+ struct aim_fh *fh;
+
+ pr_info("aim_vdev_open()\n");
+
+ switch (vdev->vfl_type) {
+ case VFL_TYPE_GRABBER:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ fh = kzalloc(sizeof(struct aim_fh), GFP_KERNEL);
+ if (!fh)
+ return -ENOMEM;
+
+ if (!atomic_inc_and_test(&mdev->access_ref)) {
+ pr_err("too many clients\n");
+ ret = -EBUSY;
+ goto err_dec;
+ }
+
+ fh->mdev = mdev;
+ v4l2_fh_init(&fh->fh, vdev);
+ filp->private_data = fh;
+
+ v4l2_fh_add(&fh->fh);
+
+ ret = most_start_channel(mdev->iface, mdev->ch_idx);
+ if (ret) {
+ pr_err("most_start_channel() failed\n");
+ goto err_rm;
+ }
+
+ return 0;
+
+err_rm:
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
+
+err_dec:
+ atomic_dec(&mdev->access_ref);
+ kfree(fh);
+ return ret;
+}
+
+static int aim_vdev_close(struct file *filp)
+{
+ struct aim_fh *fh = filp->private_data;
+ struct most_video_dev *mdev = fh->mdev;
+ struct mbo *mbo, *tmp;
+
+ pr_info("aim_vdev_close()\n");
+
+ /*
+ * We need to put MBOs back before we call most_stop_channel()
+ * to deallocate MBOs.
+ * From the other hand mostcore still calling rx_completion()
+ * to deliver MBOs until most_stop_channel() is called.
+ * Use mute to work around this issue.
+ * This must be implemented in core.
+ */
+
+ spin_lock(&mdev->list_lock);
+ mdev->mute = true;
+ list_for_each_entry_safe(mbo, tmp, &mdev->pending_mbos, list) {
+ list_del(&mbo->list);
+ spin_unlock(&mdev->list_lock);
+ most_put_mbo(mbo);
+ spin_lock(&mdev->list_lock);
+ }
+ spin_unlock(&mdev->list_lock);
+ most_stop_channel(mdev->iface, mdev->ch_idx);
+ mdev->mute = false;
+
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
+
+ atomic_dec(&mdev->access_ref);
+ kfree(fh);
+ return 0;
+}
+
+static ssize_t aim_vdev_read(struct file *filp, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ struct aim_fh *fh = filp->private_data;
+ struct most_video_dev *mdev = fh->mdev;
+ int ret = 0;
+
+ if (*pos)
+ return -ESPIPE;
+
+ if (!mdev)
+ return -ENODEV;
+
+ /* wait for the first buffer */
+ if (!(filp->f_flags & O_NONBLOCK)) {
+ if (wait_event_interruptible(mdev->wait_data, data_ready(mdev)))
+ return -ERESTARTSYS;
+ }
+
+ if (!data_ready(mdev))
+ return -EAGAIN;
+
+ while (count > 0 && data_ready(mdev)) {
+ struct mbo *const mbo = get_top_mbo(mdev);
+ int const rem = mbo->processed_length - fh->offs;
+ int const cnt = rem < count ? rem : count;
+
+ if (copy_to_user(buf, mbo->virt_address + fh->offs, cnt)) {
+ pr_err("read: copy_to_user failed\n");
+ if (!ret)
+ ret = -EFAULT;
+ return ret;
+ }
+
+ fh->offs += cnt;
+ count -= cnt;
+ buf += cnt;
+ ret += cnt;
+
+ if (cnt >= rem) {
+ fh->offs = 0;
+ spin_lock(&mdev->list_lock);
+ list_del(&mbo->list);
+ spin_unlock(&mdev->list_lock);
+ most_put_mbo(mbo);
+ }
+ }
+ return ret;
+}
+
+static unsigned int aim_vdev_poll(struct file *filp, poll_table *wait)
+{
+ struct aim_fh *fh = filp->private_data;
+ struct most_video_dev *mdev = fh->mdev;
+ unsigned int mask = 0;
+
+ /* only wait if no data is available */
+ if (!data_ready(mdev))
+ poll_wait(filp, &mdev->wait_data, wait);
+ if (data_ready(mdev))
+ mask |= POLLIN | POLLRDNORM;
+
+ return mask;
+}
+
+static void aim_set_format_struct(struct v4l2_format *f)
+{
+ f->fmt.pix.width = 8;
+ f->fmt.pix.height = 8;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+ f->fmt.pix.bytesperline = 0;
+ f->fmt.pix.sizeimage = 188 * 2;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+ f->fmt.pix.field = V4L2_FIELD_NONE;
+ f->fmt.pix.priv = 0;
+}
+
+static int aim_set_format(struct most_video_dev *mdev, unsigned int cmd,
+ struct v4l2_format *format)
+{
+#if 0
+ u32 const pixfmt = format->fmt.pix.pixelformat;
+ const char *fmt;
+
+ if (pixfmt != V4L2_PIX_FMT_MPEG) {
+ if (cmd == VIDIOC_TRY_FMT)
+ fmt = KERN_ERR "try %c%c%c%c failed\n";
+ else
+ fmt = KERN_ERR "set %c%c%c%c failed\n";
+ } else {
+ if (cmd == VIDIOC_TRY_FMT)
+ fmt = KERN_ERR "try %c%c%c%c\n";
+ else
+ fmt = KERN_ERR "set %c%c%c%c\n";
+ }
+ printk(fmt,
+ (pixfmt) & 255,
+ (pixfmt >> 8) & 255,
+ (pixfmt >> 16) & 255,
+ (pixfmt >> 24) & 255);
+#endif
+
+ if (format->fmt.pix.pixelformat != V4L2_PIX_FMT_MPEG)
+ return -EINVAL;
+
+ if (cmd == VIDIOC_TRY_FMT)
+ return 0;
+
+ aim_set_format_struct(format);
+
+ return 0;
+}
+
+
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *cap)
+{
+ struct aim_fh *fh = priv;
+ struct most_video_dev *mdev = fh->mdev;
+
+ pr_info("vidioc_querycap()\n");
+
+ strlcpy(cap->driver, "v4l2_most_aim", sizeof(cap->driver));
+ strlcpy(cap->card, "my_card", sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info),
+ "%s", mdev->iface->description);
+
+ cap->capabilities =
+ V4L2_CAP_READWRITE |
+ V4L2_CAP_TUNER |
+ V4L2_CAP_VIDEO_CAPTURE;
+ return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ pr_info("vidioc_enum_fmt_vid_cap() %d\n", f->index);
+
+ if (f->index)
+ return -EINVAL;
+
+ strcpy(f->description, "MPEG");
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ f->flags = V4L2_FMT_FLAG_COMPRESSED;
+ f->pixelformat = V4L2_PIX_FMT_MPEG;
+
+ return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ pr_info("vidioc_g_fmt_vid_cap()\n");
+
+ aim_set_format_struct(f);
+ return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct aim_fh *fh = priv;
+ struct most_video_dev *mdev = fh->mdev;
+
+ return aim_set_format(mdev, VIDIOC_TRY_FMT, f);
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct aim_fh *fh = priv;
+ struct most_video_dev *mdev = fh->mdev;
+
+ return aim_set_format(mdev, VIDIOC_S_FMT, f);
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+ pr_info("vidioc_g_std()\n");
+
+ *norm = V4L2_STD_UNKNOWN;
+ return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *priv,
+ struct v4l2_input *input)
+{
+ struct aim_fh *fh = priv;
+ struct most_video_dev *mdev = fh->mdev;
+
+ if (input->index >= V4L2_AIM_MAX_INPUT)
+ return -EINVAL;
+
+ strcpy(input->name, "MOST Video");
+ input->type |= V4L2_INPUT_TYPE_CAMERA;
+ input->audioset = 0;
+
+ input->std = mdev->vdev->tvnorms;
+
+ return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+ struct aim_fh *fh = priv;
+ struct most_video_dev *mdev = fh->mdev;
+ *i = mdev->ctrl_input;
+ return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int index)
+{
+ struct aim_fh *fh = priv;
+ struct most_video_dev *mdev = fh->mdev;
+
+ pr_info("vidioc_s_input(%d)\n", index);
+
+ if (index >= V4L2_AIM_MAX_INPUT)
+ return -EINVAL;
+ mdev->ctrl_input = index;
+ return 0;
+}
+
+static struct v4l2_file_operations aim_fops = {
+ .owner = THIS_MODULE,
+ .open = aim_vdev_open,
+ .release = aim_vdev_close,
+ .read = aim_vdev_read,
+ .poll = aim_vdev_poll,
+ .unlocked_ioctl = video_ioctl2,
+};
+
+static const struct v4l2_ioctl_ops video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
+ .vidioc_g_std = vidioc_g_std,
+ .vidioc_enum_input = vidioc_enum_input,
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+};
+
+static const struct video_device aim_videodev_template = {
+ .fops = &aim_fops,
+ .release = video_device_release,
+ .ioctl_ops = &video_ioctl_ops,
+ .tvnorms = V4L2_STD_UNKNOWN,
+};
+
+/**************************************************************************/
+
+static struct most_video_dev *get_aim_dev(
+ struct most_interface *iface, int channel_idx)
+{
+ struct most_video_dev *mdev, *tmp;
+
+ spin_lock(&list_lock);
+ list_for_each_entry_safe(mdev, tmp, &video_devices, list) {
+ if (mdev->iface == iface && mdev->ch_idx == channel_idx) {
+ spin_unlock(&list_lock);
+ return mdev;
+ }
+ }
+ spin_unlock(&list_lock);
+ return 0;
+}
+
+static int aim_rx_data(struct mbo *mbo)
+{
+ struct most_video_dev *mdev =
+ get_aim_dev(mbo->ifp, mbo->hdm_channel_id);
+
+ if (!mdev)
+ return -EIO;
+
+ spin_lock(&mdev->list_lock);
+ if (unlikely(mdev->mute)) {
+ spin_unlock(&mdev->list_lock);
+ return -EIO;
+ }
+
+ list_add_tail(&mbo->list, &mdev->pending_mbos);
+ spin_unlock(&mdev->list_lock);
+ wake_up_interruptible(&mdev->wait_data);
+ return 0;
+}
+
+static int aim_register_videodev(struct most_video_dev *mdev)
+{
+ int retval = -ENOMEM;
+ int ret;
+
+ pr_info("aim_register_videodev()\n");
+
+ init_waitqueue_head(&mdev->wait_data);
+
+ /* allocate and fill v4l2 video struct */
+ mdev->vdev = video_device_alloc();
+ if (!mdev->vdev)
+ return -ENOMEM;
+
+ /* Fill the video capture device struct */
+ *mdev->vdev = aim_videodev_template;
+ mdev->vdev->v4l2_dev = &mdev->v4l2_dev;
+ mdev->vdev->lock = &mdev->lock;
+ strcpy(mdev->vdev->name, "most v4l2 aim video");
+
+ /* Register the v4l2 device */
+ video_set_drvdata(mdev->vdev, mdev);
+ retval = video_register_device(mdev->vdev, VFL_TYPE_GRABBER, -1);
+ if (retval != 0) {
+ pr_err("video_register_device failed (%d)\n", retval);
+ ret = -ENODEV;
+ goto err_vbi_dev;
+ }
+
+ return 0;
+
+err_vbi_dev:
+ video_device_release(mdev->vdev);
+ return ret;
+}
+
+static void aim_unregister_videodev(struct most_video_dev *mdev)
+{
+ pr_info("aim_unregister_videodev()\n");
+
+ video_unregister_device(mdev->vdev);
+}
+
+
+static void aim_v4l2_dev_release(struct v4l2_device *v4l2_dev)
+{
+ struct most_video_dev *mdev =
+ container_of(v4l2_dev, struct most_video_dev, v4l2_dev);
+
+ v4l2_device_unregister(v4l2_dev);
+ kfree(mdev);
+}
+
+static int aim_probe_channel(struct most_interface *iface, int channel_idx,
+ struct most_channel_config *ccfg,
+ struct kobject *parent, char *name)
+{
+ int ret;
+ struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
+
+ pr_info("aim_probe_channel()\n");
+
+ if (mdev) {
+ pr_err("channel already linked\n");
+ return -EEXIST;
+ }
+
+ if (ccfg->direction != MOST_CH_RX) {
+ pr_err("wrong direction, expect rx\n");
+ return -EINVAL;
+ }
+
+ if (ccfg->data_type != MOST_CH_SYNC &&
+ ccfg->data_type != MOST_CH_ISOC_AVP) {
+ pr_err("wrong channel type, expect sync or isoc_avp\n");
+ return -EINVAL;
+ }
+
+ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ if (!mdev)
+ return -ENOMEM;
+
+ mutex_init(&mdev->lock);
+ atomic_set(&mdev->access_ref, -1);
+ spin_lock_init(&mdev->list_lock);
+ INIT_LIST_HEAD(&mdev->pending_mbos);
+ mdev->iface = iface;
+ mdev->ch_idx = channel_idx;
+ mdev->v4l2_dev.release = aim_v4l2_dev_release;
+
+ /* Create the v4l2_device */
+ strlcpy(mdev->v4l2_dev.name, "most_video_device",
+ sizeof(mdev->v4l2_dev.name));
+ ret = v4l2_device_register(NULL, &mdev->v4l2_dev);
+ if (ret) {
+ pr_err("v4l2_device_register() failed\n");
+ kfree(mdev);
+ return ret;
+ }
+
+ ret = aim_register_videodev(mdev);
+ if (ret)
+ goto err_unreg;
+
+ spin_lock(&list_lock);
+ list_add(&mdev->list, &video_devices);
+ spin_unlock(&list_lock);
+ return 0;
+
+err_unreg:
+ v4l2_device_disconnect(&mdev->v4l2_dev);
+ v4l2_device_put(&mdev->v4l2_dev);
+ return ret;
+}
+
+static int aim_disconnect_channel(struct most_interface *iface,
+ int channel_idx)
+{
+ struct most_video_dev *mdev = get_aim_dev(iface, channel_idx);
+
+ pr_info("aim_disconnect_channel()\n");
+
+ if (!mdev) {
+ pr_err("no such channel is linked\n");
+ return -ENOENT;
+ }
+
+ spin_lock(&list_lock);
+ list_del(&mdev->list);
+ spin_unlock(&list_lock);
+
+ aim_unregister_videodev(mdev);
+ v4l2_device_disconnect(&mdev->v4l2_dev);
+ v4l2_device_put(&mdev->v4l2_dev);
+ return 0;
+}
+
+static int __init aim_init(void)
+{
+ spin_lock_init(&list_lock);
+
+ aim_info.name = "v4l";
+ aim_info.probe_channel = aim_probe_channel;
+ aim_info.disconnect_channel = aim_disconnect_channel;
+ aim_info.rx_completion = aim_rx_data;
+ return most_register_aim(&aim_info);
+}
+
+static void __exit aim_exit(void)
+{
+ struct most_video_dev *mdev, *tmp;
+
+ /*
+ * As the mostcore currently doesn't call disconnect_channel()
+ * for linked channels while we call most_deregister_aim()
+ * we simulate this call here.
+ * This must be fixed in core.
+ */
+ spin_lock(&list_lock);
+ list_for_each_entry_safe(mdev, tmp, &video_devices, list) {
+ list_del(&mdev->list);
+ spin_unlock(&list_lock);
+
+ aim_unregister_videodev(mdev);
+ v4l2_device_disconnect(&mdev->v4l2_dev);
+ v4l2_device_put(&mdev->v4l2_dev);
+ spin_lock(&list_lock);
+ }
+ spin_unlock(&list_lock);
+
+ most_deregister_aim(&aim_info);
+ BUG_ON(!list_empty(&video_devices));
+}
+
+module_init(aim_init);
+module_exit(aim_exit);
+
+MODULE_DESCRIPTION("V4L2 Application Interface Module for MostCore");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-dim2/Kconfig b/drivers/staging/most/hdm-dim2/Kconfig
new file mode 100644
index 0000000..1d4ad1d
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/Kconfig
@@ -0,0 +1,16 @@
+#
+# MediaLB configuration
+#
+
+config HDM_DIM2
+ tristate "DIM2 HDM"
+ depends on AIM_NETWORK
+
+ ---help---
+ Say Y here if you want to connect via MediaLB to network transceiver.
+ This device driver is platform dependent and needs an addtional
+ platform driver to be installed. For more information contact
+ maintainer of this driver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hdm_dim2.
diff --git a/drivers/staging/most/hdm-dim2/Makefile b/drivers/staging/most/hdm-dim2/Makefile
new file mode 100644
index 0000000..6bbee87
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_HDM_DIM2) += hdm_dim2.o
+
+hdm_dim2-objs := dim2_hdm.o dim2_hal.o dim2_sysfs.o
+ccflags-y += -Idrivers/staging/most/mostcore/
+ccflags-y += -Idrivers/staging/most/aim-network/
diff --git a/drivers/staging/most/hdm-dim2/dim2_errors.h b/drivers/staging/most/hdm-dim2/dim2_errors.h
new file mode 100644
index 0000000..314f7de
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/dim2_errors.h
@@ -0,0 +1,67 @@
+/*
+ * dim2_errors.h - Definitions of errors for DIM2 HAL API
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef _MOST_DIM_ERRORS_H
+#define _MOST_DIM_ERRORS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * MOST DIM errors.
+ */
+enum dim_errors_t {
+ /** Not an error */
+ DIM_NO_ERROR = 0,
+
+ /** Bad base address for DIM2 IP */
+ DIM_INIT_ERR_DIM_ADDR = 0x10,
+
+ /**< Bad MediaLB clock */
+ DIM_INIT_ERR_MLB_CLOCK,
+
+ /** Bad channel address */
+ DIM_INIT_ERR_CHANNEL_ADDRESS,
+
+ /** Out of DBR memory */
+ DIM_INIT_ERR_OUT_OF_MEMORY,
+
+ /** DIM API is called while DIM is not initialized successfully */
+ DIM_ERR_DRIVER_NOT_INITIALIZED = 0x20,
+
+ /**
+ * Configuration does not respect hardware limitations
+ * for isochronous or synchronous channels
+ */
+ DIM_ERR_BAD_CONFIG,
+
+ /**
+ * Buffer size does not respect hardware limitations
+ * for isochronous or synchronous channels
+ */
+ DIM_ERR_BAD_BUFFER_SIZE,
+
+ DIM_ERR_UNDERFLOW,
+
+ DIM_ERR_OVERFLOW,
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _MOST_DIM_ERRORS_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.c b/drivers/staging/most/hdm-dim2/dim2_hal.c
new file mode 100644
index 0000000..a54cf2c
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/dim2_hal.c
@@ -0,0 +1,919 @@
+/*
+ * dim2_hal.c - DIM2 HAL implementation
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#include "dim2_hal.h"
+#include "dim2_errors.h"
+#include "dim2_reg.h"
+#include <linux/stddef.h>
+
+
+/*
+ * The number of frames per sub-buffer for synchronous channels.
+ * Allowed values: 1, 2, 4, 8, 16, 32, 64.
+ */
+#define FRAMES_PER_SUBBUFF 16
+
+/*
+ * Size factor for synchronous DBR buffer.
+ * Minimal value is 4*FRAMES_PER_SUBBUFF.
+ */
+#define SYNC_DBR_FACTOR (4u * (u16)FRAMES_PER_SUBBUFF)
+
+/*
+ * Size factor for isochronous DBR buffer.
+ * Minimal value is 3.
+ */
+#define ISOC_DBR_FACTOR 3u
+
+/*
+ * Number of 32-bit units for DBR map.
+ *
+ * 1: block size is 512, max allocation is 16K
+ * 2: block size is 256, max allocation is 8K
+ * 4: block size is 128, max allocation is 4K
+ * 8: block size is 64, max allocation is 2K
+ *
+ * Min allocated space is block size.
+ * Max possible allocated space is 32 blocks.
+ */
+#define DBR_MAP_SIZE 2
+
+
+/* -------------------------------------------------------------------------- */
+/* not configurable area */
+
+#define CDT 0x00
+#define ADT 0x40
+#define MLB_CAT 0x80
+#define AHB_CAT 0x88
+
+#define DBR_SIZE (16*1024) /* specified by IP */
+#define DBR_BLOCK_SIZE (DBR_SIZE / 32 / DBR_MAP_SIZE)
+
+
+/* -------------------------------------------------------------------------- */
+/* generic helper functions and macros */
+
+#define MLBC0_FCNT_VAL_MACRO(n) MLBC0_FCNT_VAL_ ## n ## FPSB
+#define MLBC0_FCNT_VAL(fpsb) MLBC0_FCNT_VAL_MACRO(fpsb)
+
+static inline u32 bit_mask(u8 position)
+{
+ return (u32)1 << position;
+}
+
+static inline bool dim_on_error(u8 error_id, const char *error_message)
+{
+ DIMCB_OnError(error_id, error_message);
+ return false;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* types and local variables */
+
+struct lld_global_vars_t {
+ bool dim_is_initialized;
+ bool mcm_is_initialized;
+ struct dim2_regs *dim2; /* DIM2 core base address */
+ u32 dbr_map[DBR_MAP_SIZE];
+};
+
+static struct lld_global_vars_t g = { false };
+
+
+/* -------------------------------------------------------------------------- */
+
+static int dbr_get_mask_size(u16 size)
+{
+ int i;
+
+ for (i = 0; i < 6; i++)
+ if (size <= (DBR_BLOCK_SIZE << i))
+ return 1 << i;
+ return 0;
+}
+
+/**
+ * Allocates DBR memory.
+ * @param size Allocating memory size.
+ * @return Offset in DBR memory by success or DBR_SIZE if out of memory.
+ */
+static int alloc_dbr(u16 size)
+{
+ int mask_size;
+ int i, block_idx = 0;
+
+ if (size <= 0)
+ return DBR_SIZE; /* out of memory */
+
+ mask_size = dbr_get_mask_size(size);
+ if (mask_size == 0)
+ return DBR_SIZE; /* out of memory */
+
+ for (i = 0; i < DBR_MAP_SIZE; i++) {
+ u32 const blocks = (size + DBR_BLOCK_SIZE - 1) / DBR_BLOCK_SIZE;
+ u32 mask = ~((~(u32)0) << blocks);
+
+ do {
+ if ((g.dbr_map[i] & mask) == 0) {
+ g.dbr_map[i] |= mask;
+ return block_idx * DBR_BLOCK_SIZE;
+ }
+ block_idx += mask_size;
+ /* do shift left with 2 steps for case mask_size == 32 */
+ mask <<= mask_size - 1;
+ } while ((mask <<= 1) != 0);
+ }
+
+ return DBR_SIZE; /* out of memory */
+}
+
+static void free_dbr(int offs, int size)
+{
+ int block_idx = offs / DBR_BLOCK_SIZE;
+ u32 const blocks = (size + DBR_BLOCK_SIZE - 1) / DBR_BLOCK_SIZE;
+ u32 mask = ~((~(u32)0) << blocks);
+
+ mask <<= block_idx % 32;
+ g.dbr_map[block_idx / 32] &= ~mask;
+}
+
+/* -------------------------------------------------------------------------- */
+
+static u32 dim2_read_ctr(u32 ctr_addr, u16 mdat_idx)
+{
+ DIMCB_IoWrite(&g.dim2->MADR, ctr_addr);
+
+ /* wait till transfer is completed */
+ while ((DIMCB_IoRead(&g.dim2->MCTL) & 1) != 1)
+ continue;
+
+ DIMCB_IoWrite(&g.dim2->MCTL, 0); /* clear transfer complete */
+
+ return DIMCB_IoRead((&g.dim2->MDAT0) + mdat_idx);
+}
+
+static void dim2_write_ctr_mask(u32 ctr_addr, const u32 *mask, const u32 *value)
+{
+ enum { MADR_WNR_BIT = 31 };
+
+ DIMCB_IoWrite(&g.dim2->MCTL, 0); /* clear transfer complete */
+
+ if (mask[0] != 0)
+ DIMCB_IoWrite(&g.dim2->MDAT0, value[0]);
+ if (mask[1] != 0)
+ DIMCB_IoWrite(&g.dim2->MDAT1, value[1]);
+ if (mask[2] != 0)
+ DIMCB_IoWrite(&g.dim2->MDAT2, value[2]);
+ if (mask[3] != 0)
+ DIMCB_IoWrite(&g.dim2->MDAT3, value[3]);
+
+ DIMCB_IoWrite(&g.dim2->MDWE0, mask[0]);
+ DIMCB_IoWrite(&g.dim2->MDWE1, mask[1]);
+ DIMCB_IoWrite(&g.dim2->MDWE2, mask[2]);
+ DIMCB_IoWrite(&g.dim2->MDWE3, mask[3]);
+
+ DIMCB_IoWrite(&g.dim2->MADR, bit_mask(MADR_WNR_BIT) | ctr_addr);
+
+ /* wait till transfer is completed */
+ while ((DIMCB_IoRead(&g.dim2->MCTL) & 1) != 1)
+ continue;
+
+ DIMCB_IoWrite(&g.dim2->MCTL, 0); /* clear transfer complete */
+}
+
+static inline void dim2_write_ctr(u32 ctr_addr, const u32 *value)
+{
+ u32 const mask[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+
+ dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static inline void dim2_clear_ctr(u32 ctr_addr)
+{
+ u32 const value[4] = { 0, 0, 0, 0 };
+
+ dim2_write_ctr(ctr_addr, value);
+}
+
+static void dim2_configure_cat(u8 cat_base, u8 ch_addr, u8 ch_type,
+ bool read_not_write, bool sync_mfe)
+{
+ u16 const cat =
+ (read_not_write << CAT_RNW_BIT) |
+ (ch_type << CAT_CT_SHIFT) |
+ (ch_addr << CAT_CL_SHIFT) |
+ (sync_mfe << CAT_MFE_BIT) |
+ (false << CAT_MT_BIT) |
+ (true << CAT_CE_BIT);
+ u8 const ctr_addr = cat_base + ch_addr / 8;
+ u8 const idx = (ch_addr % 8) / 2;
+ u8 const shift = (ch_addr % 2) * 16;
+ u32 mask[4] = { 0, 0, 0, 0 };
+ u32 value[4] = { 0, 0, 0, 0 };
+
+ mask[idx] = (u32)0xFFFF << shift;
+ value[idx] = cat << shift;
+ dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static void dim2_clear_cat(u8 cat_base, u8 ch_addr)
+{
+ u8 const ctr_addr = cat_base + ch_addr / 8;
+ u8 const idx = (ch_addr % 8) / 2;
+ u8 const shift = (ch_addr % 2) * 16;
+ u32 mask[4] = { 0, 0, 0, 0 };
+ u32 value[4] = { 0, 0, 0, 0 };
+
+ mask[idx] = (u32)0xFFFF << shift;
+ dim2_write_ctr_mask(ctr_addr, mask, value);
+}
+
+static void dim2_configure_cdt(u8 ch_addr, u16 dbr_address, u16 hw_buffer_size,
+ u16 packet_length)
+{
+ u32 cdt[4] = { 0, 0, 0, 0 };
+
+ if (packet_length)
+ cdt[1] = ((packet_length - 1) << CDT1_BS_ISOC_SHIFT);
+
+ cdt[3] =
+ ((hw_buffer_size - 1) << CDT3_BD_SHIFT) |
+ (dbr_address << CDT3_BA_SHIFT);
+ dim2_write_ctr(CDT + ch_addr, cdt);
+}
+
+static void dim2_clear_cdt(u8 ch_addr)
+{
+ u32 cdt[4] = { 0, 0, 0, 0 };
+
+ dim2_write_ctr(CDT + ch_addr, cdt);
+}
+
+static void dim2_configure_adt(u8 ch_addr)
+{
+ u32 adt[4] = { 0, 0, 0, 0 };
+
+ adt[0] =
+ (true << ADT0_CE_BIT) |
+ (true << ADT0_LE_BIT) |
+ (0 << ADT0_PG_BIT);
+
+ dim2_write_ctr(ADT + ch_addr, adt);
+}
+
+static void dim2_clear_adt(u8 ch_addr)
+{
+ u32 adt[4] = { 0, 0, 0, 0 };
+
+ dim2_write_ctr(ADT + ch_addr, adt);
+}
+
+static void dim2_start_ctrl_async(u8 ch_addr, u8 idx, u32 buf_addr,
+ u16 buffer_size)
+{
+ u8 const shift = idx * 16;
+
+ u32 mask[4] = { 0, 0, 0, 0 };
+ u32 adt[4] = { 0, 0, 0, 0 };
+
+ mask[1] =
+ bit_mask(ADT1_PS_BIT + shift) |
+ bit_mask(ADT1_RDY_BIT + shift) |
+ (ADT1_CTRL_ASYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
+ adt[1] =
+ (true << (ADT1_PS_BIT + shift)) |
+ (true << (ADT1_RDY_BIT + shift)) |
+ ((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
+
+ mask[idx + 2] = 0xFFFFFFFF;
+ adt[idx + 2] = buf_addr;
+
+ dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
+}
+
+static void dim2_start_isoc_sync(u8 ch_addr, u8 idx, u32 buf_addr,
+ u16 buffer_size)
+{
+ u8 const shift = idx * 16;
+
+ u32 mask[4] = { 0, 0, 0, 0 };
+ u32 adt[4] = { 0, 0, 0, 0 };
+
+ mask[1] =
+ bit_mask(ADT1_RDY_BIT + shift) |
+ (ADT1_ISOC_SYNC_BD_MASK << (ADT1_BD_SHIFT + shift));
+ adt[1] =
+ (true << (ADT1_RDY_BIT + shift)) |
+ ((buffer_size - 1) << (ADT1_BD_SHIFT + shift));
+
+ mask[idx + 2] = 0xFFFFFFFF;
+ adt[idx + 2] = buf_addr;
+
+ dim2_write_ctr_mask(ADT + ch_addr, mask, adt);
+}
+
+
+static void dim2_clear_ctram(void)
+{
+ u32 ctr_addr;
+
+ for (ctr_addr = 0; ctr_addr < 0x90; ctr_addr++)
+ dim2_clear_ctr(ctr_addr);
+}
+
+static void dim2_configure_channel(
+ u8 ch_addr, u8 type, u8 is_tx, u16 dbr_address, u16 hw_buffer_size,
+ u16 packet_length, bool sync_mfe)
+{
+ dim2_configure_cdt(ch_addr, dbr_address, hw_buffer_size, packet_length);
+ dim2_configure_cat(MLB_CAT, ch_addr, type, is_tx ? 1 : 0, sync_mfe);
+
+ dim2_configure_adt(ch_addr);
+ dim2_configure_cat(AHB_CAT, ch_addr, type, is_tx ? 0 : 1, sync_mfe);
+
+ /* unmask interrupt for used channel, enable mlb_sys_int[0] interrupt */
+ DIMCB_IoWrite(&g.dim2->ACMR0,
+ DIMCB_IoRead(&g.dim2->ACMR0) | bit_mask(ch_addr));
+}
+
+static void dim2_clear_channel(u8 ch_addr)
+{
+ /* mask interrupt for used channel, disable mlb_sys_int[0] interrupt */
+ DIMCB_IoWrite(&g.dim2->ACMR0,
+ DIMCB_IoRead(&g.dim2->ACMR0) & ~bit_mask(ch_addr));
+
+ dim2_clear_cat(AHB_CAT, ch_addr);
+ dim2_clear_adt(ch_addr);
+
+ dim2_clear_cat(MLB_CAT, ch_addr);
+ dim2_clear_cdt(ch_addr);
+}
+
+/* -------------------------------------------------------------------------- */
+/* channel state helpers */
+
+static void state_init(struct int_ch_state *state)
+{
+ state->request_counter = 0;
+ state->service_counter = 0;
+
+ state->idx1 = 0;
+ state->idx2 = 0;
+ state->level = 0;
+}
+
+/* -------------------------------------------------------------------------- */
+/* macro helper functions */
+
+static inline bool check_channel_address(u32 ch_address)
+{
+ return ch_address > 0 && (ch_address % 2) == 0 &&
+ (ch_address / 2) <= (u32)CAT_CL_MASK;
+}
+
+static inline bool check_packet_length(u32 packet_length)
+{
+ u16 const max_size = ((u16)CDT3_BD_ISOC_MASK + 1u) / ISOC_DBR_FACTOR;
+
+ if (packet_length <= 0)
+ return false; /* too small */
+
+ if (packet_length > max_size)
+ return false; /* too big */
+
+ if (packet_length - 1u > (u32)CDT1_BS_ISOC_MASK)
+ return false; /* too big */
+
+ return true;
+}
+
+static inline bool check_bytes_per_frame(u32 bytes_per_frame)
+{
+ u16 const max_size = ((u16)CDT3_BD_MASK + 1u) / SYNC_DBR_FACTOR;
+
+ if (bytes_per_frame <= 0)
+ return false; /* too small */
+
+ if (bytes_per_frame > max_size)
+ return false; /* too big */
+
+ return true;
+}
+
+static inline u16 norm_ctrl_async_buffer_size(u16 buf_size)
+{
+ u16 const max_size = (u16)ADT1_CTRL_ASYNC_BD_MASK + 1u;
+
+ if (buf_size > max_size)
+ return max_size;
+
+ return buf_size;
+}
+
+static inline u16 norm_isoc_buffer_size(u16 buf_size, u16 packet_length)
+{
+ u16 n;
+ u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
+
+ if (buf_size > max_size)
+ buf_size = max_size;
+
+ n = buf_size / packet_length;
+
+ if (n < 2u)
+ return 0; /* too small buffer for given packet_length */
+
+ return packet_length * n;
+}
+
+static inline u16 norm_sync_buffer_size(u16 buf_size, u16 bytes_per_frame)
+{
+ u16 n;
+ u16 const max_size = (u16)ADT1_ISOC_SYNC_BD_MASK + 1u;
+ u32 const unit = bytes_per_frame * (u16)FRAMES_PER_SUBBUFF;
+
+ if (buf_size > max_size)
+ buf_size = max_size;
+
+ n = buf_size / unit;
+
+ if (n < 1u)
+ return 0; /* too small buffer for given bytes_per_frame */
+
+ return unit * n;
+}
+
+static void dim2_cleanup(void)
+{
+ /* disable MediaLB */
+ DIMCB_IoWrite(&g.dim2->MLBC0, false << MLBC0_MLBEN_BIT);
+
+ dim2_clear_ctram();
+
+ /* disable mlb_int interrupt */
+ DIMCB_IoWrite(&g.dim2->MIEN, 0);
+
+ /* clear status for all dma channels */
+ DIMCB_IoWrite(&g.dim2->ACSR0, 0xFFFFFFFF);
+ DIMCB_IoWrite(&g.dim2->ACSR1, 0xFFFFFFFF);
+
+ /* mask interrupts for all channels */
+ DIMCB_IoWrite(&g.dim2->ACMR0, 0);
+ DIMCB_IoWrite(&g.dim2->ACMR1, 0);
+}
+
+static void dim2_initialize(bool enable_6pin, u8 mlb_clock)
+{
+ dim2_cleanup();
+
+ /* configure and enable MediaLB */
+ DIMCB_IoWrite(&g.dim2->MLBC0,
+ enable_6pin << MLBC0_MLBPEN_BIT |
+ mlb_clock << MLBC0_MLBCLK_SHIFT |
+ MLBC0_FCNT_VAL(FRAMES_PER_SUBBUFF) << MLBC0_FCNT_SHIFT |
+ true << MLBC0_MLBEN_BIT);
+
+ /* activate all HBI channels */
+ DIMCB_IoWrite(&g.dim2->HCMR0, 0xFFFFFFFF);
+ DIMCB_IoWrite(&g.dim2->HCMR1, 0xFFFFFFFF);
+
+ /* enable HBI */
+ DIMCB_IoWrite(&g.dim2->HCTL, bit_mask(HCTL_EN_BIT));
+
+ /* configure DMA */
+ DIMCB_IoWrite(&g.dim2->ACTL,
+ ACTL_DMA_MODE_VAL_DMA_MODE_1 << ACTL_DMA_MODE_BIT |
+ true << ACTL_SCE_BIT);
+
+#if 0
+ DIMCB_IoWrite(&g.dim2->MIEN,
+ bit_mask(MIEN_CTX_BREAK_BIT) |
+ bit_mask(MIEN_CTX_PE_BIT) |
+ bit_mask(MIEN_CTX_DONE_BIT) |
+ bit_mask(MIEN_CRX_BREAK_BIT) |
+ bit_mask(MIEN_CRX_PE_BIT) |
+ bit_mask(MIEN_CRX_DONE_BIT) |
+ bit_mask(MIEN_ATX_BREAK_BIT) |
+ bit_mask(MIEN_ATX_PE_BIT) |
+ bit_mask(MIEN_ATX_DONE_BIT) |
+ bit_mask(MIEN_ARX_BREAK_BIT) |
+ bit_mask(MIEN_ARX_PE_BIT) |
+ bit_mask(MIEN_ARX_DONE_BIT));
+#endif
+}
+
+static bool dim2_is_mlb_locked(void)
+{
+ u32 const mask0 = bit_mask(MLBC0_MLBLK_BIT);
+ u32 const mask1 = bit_mask(MLBC1_CLKMERR_BIT) |
+ bit_mask(MLBC1_LOCKERR_BIT);
+ u32 const c1 = DIMCB_IoRead(&g.dim2->MLBC1);
+ u32 const nda_mask = (u32)MLBC1_NDA_MASK << MLBC1_NDA_SHIFT;
+
+ DIMCB_IoWrite(&g.dim2->MLBC1, c1 & nda_mask);
+ return (DIMCB_IoRead(&g.dim2->MLBC1) & mask1) == 0 &&
+ (DIMCB_IoRead(&g.dim2->MLBC0) & mask0) != 0;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* channel help routines */
+
+static inline bool service_channel(u8 ch_addr, u8 idx)
+{
+ u8 const shift = idx * 16;
+ u32 const adt1 = dim2_read_ctr(ADT + ch_addr, 1);
+
+ if (((adt1 >> (ADT1_DNE_BIT + shift)) & 1) == 0)
+ return false;
+
+ {
+ u32 mask[4] = { 0, 0, 0, 0 };
+ u32 adt_w[4] = { 0, 0, 0, 0 };
+
+ mask[1] =
+ bit_mask(ADT1_DNE_BIT + shift) |
+ bit_mask(ADT1_ERR_BIT + shift) |
+ bit_mask(ADT1_RDY_BIT + shift);
+ dim2_write_ctr_mask(ADT + ch_addr, mask, adt_w);
+ }
+
+ /* clear channel status bit */
+ DIMCB_IoWrite(&g.dim2->ACSR0, bit_mask(ch_addr));
+
+ return true;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* channel init routines */
+
+static void isoc_init(struct dim_channel *ch, u8 ch_addr, u16 packet_length)
+{
+ state_init(&ch->state);
+
+ ch->addr = ch_addr;
+
+ ch->packet_length = packet_length;
+ ch->bytes_per_frame = 0;
+ ch->done_sw_buffers_number = 0;
+}
+
+static void sync_init(struct dim_channel *ch, u8 ch_addr, u16 bytes_per_frame)
+{
+ state_init(&ch->state);
+
+ ch->addr = ch_addr;
+
+ ch->packet_length = 0;
+ ch->bytes_per_frame = bytes_per_frame;
+ ch->done_sw_buffers_number = 0;
+}
+
+static void channel_init(struct dim_channel *ch, u8 ch_addr)
+{
+ state_init(&ch->state);
+
+ ch->addr = ch_addr;
+
+ ch->packet_length = 0;
+ ch->bytes_per_frame = 0;
+ ch->done_sw_buffers_number = 0;
+}
+
+/* returns true if channel interrupt state is cleared */
+static bool channel_service_interrupt(struct dim_channel *ch)
+{
+ struct int_ch_state *const state = &ch->state;
+
+ if (!service_channel(ch->addr, state->idx2))
+ return false;
+
+ state->idx2 ^= 1;
+ state->request_counter++;
+ return true;
+}
+
+static bool channel_start(struct dim_channel *ch, u32 buf_addr, u16 buf_size)
+{
+ struct int_ch_state *const state = &ch->state;
+
+ if (buf_size <= 0)
+ return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE, "Bad buffer size");
+
+ if (ch->packet_length == 0 && ch->bytes_per_frame == 0 &&
+ buf_size != norm_ctrl_async_buffer_size(buf_size))
+ return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+ "Bad control/async buffer size");
+
+ if (ch->packet_length &&
+ buf_size != norm_isoc_buffer_size(buf_size, ch->packet_length))
+ return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+ "Bad isochronous buffer size");
+
+ if (ch->bytes_per_frame &&
+ buf_size != norm_sync_buffer_size(buf_size, ch->bytes_per_frame))
+ return dim_on_error(DIM_ERR_BAD_BUFFER_SIZE,
+ "Bad synchronous buffer size");
+
+ if (state->level >= 2u)
+ return dim_on_error(DIM_ERR_OVERFLOW, "Channel overflow");
+
+ ++state->level;
+
+ if (ch->packet_length || ch->bytes_per_frame)
+ dim2_start_isoc_sync(ch->addr, state->idx1, buf_addr, buf_size);
+ else
+ dim2_start_ctrl_async(ch->addr, state->idx1, buf_addr, buf_size);
+ state->idx1 ^= 1;
+
+ return true;
+}
+
+static u8 channel_service(struct dim_channel *ch)
+{
+ struct int_ch_state *const state = &ch->state;
+
+ if (state->service_counter != state->request_counter) {
+ state->service_counter++;
+ if (state->level == 0)
+ return DIM_ERR_UNDERFLOW;
+
+ --state->level;
+ ch->done_sw_buffers_number++;
+ }
+
+ return DIM_NO_ERROR;
+}
+
+static bool channel_detach_buffers(struct dim_channel *ch, u16 buffers_number)
+{
+ if (buffers_number > ch->done_sw_buffers_number)
+ return dim_on_error(DIM_ERR_UNDERFLOW, "Channel underflow");
+
+ ch->done_sw_buffers_number -= buffers_number;
+ return true;
+}
+
+
+/* -------------------------------------------------------------------------- */
+/* API */
+
+u8 DIM_Startup(void *dim_base_address, u32 mlb_clock)
+{
+ g.dim_is_initialized = false;
+
+ if (!dim_base_address)
+ return DIM_INIT_ERR_DIM_ADDR;
+
+ /* MediaLB clock: 0 - 256 fs, 1 - 512 fs, 2 - 1024 fs, 3 - 2048 fs */
+ /* MediaLB clock: 4 - 3072 fs, 5 - 4096 fs, 6 - 6144 fs, 7 - 8192 fs */
+ if (mlb_clock >= 8)
+ return DIM_INIT_ERR_MLB_CLOCK;
+
+ g.dim2 = dim_base_address;
+ g.dbr_map[0] = g.dbr_map[1] = 0;
+
+ dim2_initialize(mlb_clock >= 3, mlb_clock);
+
+ g.dim_is_initialized = true;
+
+ return DIM_NO_ERROR;
+}
+
+void DIM_Shutdown(void)
+{
+ g.dim_is_initialized = false;
+ dim2_cleanup();
+}
+
+bool DIM_GetLockState(void)
+{
+ return dim2_is_mlb_locked();
+}
+
+static u8 init_ctrl_async(struct dim_channel *ch, u8 type, u8 is_tx,
+ u16 ch_address, u16 hw_buffer_size)
+{
+ if (!g.dim_is_initialized || !ch)
+ return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+ if (!check_channel_address(ch_address))
+ return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+ ch->dbr_size = hw_buffer_size;
+ ch->dbr_addr = alloc_dbr(ch->dbr_size);
+ if (ch->dbr_addr >= DBR_SIZE)
+ return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+ channel_init(ch, ch_address / 2);
+
+ dim2_configure_channel(ch->addr, type, is_tx,
+ ch->dbr_addr, ch->dbr_size, 0, false);
+
+ return DIM_NO_ERROR;
+}
+
+u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size)
+{
+ return norm_ctrl_async_buffer_size(buf_size);
+}
+
+/**
+ * Retrieves maximal possible correct buffer size for isochronous data type
+ * conform to given packet length and not bigger than given buffer size.
+ *
+ * Returns non-zero correct buffer size or zero by error.
+ */
+u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length)
+{
+ if (!check_packet_length(packet_length))
+ return 0;
+
+ return norm_isoc_buffer_size(buf_size, packet_length);
+}
+
+/**
+ * Retrieves maximal possible correct buffer size for synchronous data type
+ * conform to given bytes per frame and not bigger than given buffer size.
+ *
+ * Returns non-zero correct buffer size or zero by error.
+ */
+u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame)
+{
+ if (!check_bytes_per_frame(bytes_per_frame))
+ return 0;
+
+ return norm_sync_buffer_size(buf_size, bytes_per_frame);
+}
+
+u8 DIM_InitControl(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 max_buffer_size)
+{
+ return init_ctrl_async(ch, CAT_CT_VAL_CONTROL, is_tx, ch_address,
+ max_buffer_size * 2);
+}
+
+u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 max_buffer_size)
+{
+ return init_ctrl_async(ch, CAT_CT_VAL_ASYNC, is_tx, ch_address,
+ max_buffer_size * 2);
+}
+
+u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 packet_length)
+{
+ if (!g.dim_is_initialized || !ch)
+ return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+ if (!check_channel_address(ch_address))
+ return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+ if (!check_packet_length(packet_length))
+ return DIM_ERR_BAD_CONFIG;
+
+ ch->dbr_size = packet_length * ISOC_DBR_FACTOR;
+ ch->dbr_addr = alloc_dbr(ch->dbr_size);
+ if (ch->dbr_addr >= DBR_SIZE)
+ return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+ isoc_init(ch, ch_address / 2, packet_length);
+
+ dim2_configure_channel(ch->addr, CAT_CT_VAL_ISOC, is_tx, ch->dbr_addr,
+ ch->dbr_size, packet_length, false);
+
+ return DIM_NO_ERROR;
+}
+
+u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 bytes_per_frame)
+{
+ if (!g.dim_is_initialized || !ch)
+ return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+ if (!check_channel_address(ch_address))
+ return DIM_INIT_ERR_CHANNEL_ADDRESS;
+
+ if (!check_bytes_per_frame(bytes_per_frame))
+ return DIM_ERR_BAD_CONFIG;
+
+ ch->dbr_size = bytes_per_frame * SYNC_DBR_FACTOR;
+ ch->dbr_addr = alloc_dbr(ch->dbr_size);
+ if (ch->dbr_addr >= DBR_SIZE)
+ return DIM_INIT_ERR_OUT_OF_MEMORY;
+
+ sync_init(ch, ch_address / 2, bytes_per_frame);
+
+ dim2_configure_channel(ch->addr, CAT_CT_VAL_SYNC, is_tx,
+ ch->dbr_addr, ch->dbr_size, 0, true);
+
+ return DIM_NO_ERROR;
+}
+
+u8 DIM_DestroyChannel(struct dim_channel *ch)
+{
+ if (!g.dim_is_initialized || !ch)
+ return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+ dim2_clear_channel(ch->addr);
+ if (ch->dbr_addr < DBR_SIZE)
+ free_dbr(ch->dbr_addr, ch->dbr_size);
+ ch->dbr_addr = DBR_SIZE;
+
+ return DIM_NO_ERROR;
+}
+
+void DIM_ServiceIrq(struct dim_channel *const *channels)
+{
+ bool state_changed;
+
+ if (!g.dim_is_initialized) {
+ dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED,
+ "DIM is not initialized");
+ return;
+ }
+
+ if (!channels) {
+ dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channels");
+ return;
+ }
+
+ /*
+ * Use while-loop and a flag to make sure the age is changed back at least once,
+ * otherwise the interrupt may never come if CPU generates interrupt on changing age.
+ *
+ * This cycle runs not more than number of channels, because service_interrupts
+ * routine doesn't start the channel again.
+ */
+ do {
+ struct dim_channel *const *ch = channels;
+
+ state_changed = false;
+
+ while (*ch) {
+ state_changed |= channel_service_interrupt(*ch);
+ ++ch;
+ }
+ } while (state_changed);
+
+ /* clear pending Interrupts */
+ DIMCB_IoWrite(&g.dim2->MS0, 0);
+ DIMCB_IoWrite(&g.dim2->MS1, 0);
+}
+
+u8 DIM_ServiceChannel(struct dim_channel *ch)
+{
+ if (!g.dim_is_initialized || !ch)
+ return DIM_ERR_DRIVER_NOT_INITIALIZED;
+
+ return channel_service(ch);
+}
+
+struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
+ struct dim_ch_state_t *state_ptr)
+{
+ if (!ch || !state_ptr)
+ return NULL;
+
+ state_ptr->ready = ch->state.level < 2;
+ state_ptr->done_buffers = ch->done_sw_buffers_number;
+
+ return state_ptr;
+}
+
+bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr, u16 buffer_size)
+{
+ if (!ch)
+ return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channel");
+
+ return channel_start(ch, buffer_addr, buffer_size);
+}
+
+bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number)
+{
+ if (!ch)
+ return dim_on_error(DIM_ERR_DRIVER_NOT_INITIALIZED, "Bad channel");
+
+ return channel_detach_buffers(ch, buffers_number);
+}
+
+u32 DIM_ReadRegister(u8 register_index)
+{
+ return DIMCB_IoRead((u32 *)g.dim2 + register_index);
+}
diff --git a/drivers/staging/most/hdm-dim2/dim2_hal.h b/drivers/staging/most/hdm-dim2/dim2_hal.h
new file mode 100644
index 0000000..8929af9
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/dim2_hal.h
@@ -0,0 +1,124 @@
+/*
+ * dim2_hal.h - DIM2 HAL interface
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef _DIM2_HAL_H
+#define _DIM2_HAL_H
+
+#include <linux/types.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The values below are specified in the hardware specification.
+ * So, they should not be changed until the hardware specification changes.
+ */
+enum mlb_clk_speed {
+ CLK_256FS = 0,
+ CLK_512FS = 1,
+ CLK_1024FS = 2,
+ CLK_2048FS = 3,
+ CLK_3072FS = 4,
+ CLK_4096FS = 5,
+ CLK_6144FS = 6,
+ CLK_8192FS = 7,
+};
+
+struct dim_ch_state_t {
+ bool ready; /* Shows readiness to enqueue next buffer */
+ u16 done_buffers; /* Number of completed buffers */
+};
+
+typedef int atomic_counter_t;
+
+struct int_ch_state {
+ /* changed only in interrupt context */
+ volatile atomic_counter_t request_counter;
+
+ /* changed only in task context */
+ volatile atomic_counter_t service_counter;
+
+ u8 idx1;
+ u8 idx2;
+ u8 level; /* [0..2], buffering level */
+};
+
+struct dim_channel {
+ struct int_ch_state state;
+ u8 addr;
+ u16 dbr_addr;
+ u16 dbr_size;
+ u16 packet_length; /*< Isochronous packet length in bytes. */
+ u16 bytes_per_frame; /*< Synchronous bytes per frame. */
+ u16 done_sw_buffers_number; /*< Done software buffers number. */
+};
+
+
+u8 DIM_Startup(void *dim_base_address, u32 mlb_clock);
+
+void DIM_Shutdown(void);
+
+bool DIM_GetLockState(void);
+
+u16 DIM_NormCtrlAsyncBufferSize(u16 buf_size);
+
+u16 DIM_NormIsocBufferSize(u16 buf_size, u16 packet_length);
+
+u16 DIM_NormSyncBufferSize(u16 buf_size, u16 bytes_per_frame);
+
+u8 DIM_InitControl(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 max_buffer_size);
+
+u8 DIM_InitAsync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 max_buffer_size);
+
+u8 DIM_InitIsoc(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 packet_length);
+
+u8 DIM_InitSync(struct dim_channel *ch, u8 is_tx, u16 ch_address,
+ u16 bytes_per_frame);
+
+u8 DIM_DestroyChannel(struct dim_channel *ch);
+
+void DIM_ServiceIrq(struct dim_channel *const *channels);
+
+u8 DIM_ServiceChannel(struct dim_channel *ch);
+
+struct dim_ch_state_t *DIM_GetChannelState(struct dim_channel *ch,
+ struct dim_ch_state_t *dim_ch_state_ptr);
+
+bool DIM_EnqueueBuffer(struct dim_channel *ch, u32 buffer_addr,
+ u16 buffer_size);
+
+bool DIM_DetachBuffers(struct dim_channel *ch, u16 buffers_number);
+
+u32 DIM_ReadRegister(u8 register_index);
+
+
+u32 DIMCB_IoRead(u32 *ptr32);
+
+void DIMCB_IoWrite(u32 *ptr32, u32 value);
+
+void DIMCB_OnError(u8 error_id, const char *error_message);
+
+void DIMCB_OnFail(const char *filename, int linenum);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DIM2_HAL_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.c b/drivers/staging/most/hdm-dim2/dim2_hdm.c
new file mode 100644
index 0000000..6a5a3a2
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/dim2_hdm.c
@@ -0,0 +1,964 @@
+/*
+ * dim2_hdm.c - MediaLB DIM2 Hardware Dependent Module
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+
+#include <mostcore.h>
+#include <networking.h>
+#include "dim2_hal.h"
+#include "dim2_hdm.h"
+#include "dim2_errors.h"
+#include "dim2_sysfs.h"
+
+#define DMA_CHANNELS (32 - 1) /* channel 0 is a system channel */
+
+#define MAX_BUFFERS_PACKET 32
+#define MAX_BUFFERS_STREAMING 32
+#define MAX_BUF_SIZE_PACKET 2048
+#define MAX_BUF_SIZE_STREAMING (8*1024)
+
+/* command line parameter to select clock speed */
+static char *clock_speed;
+module_param(clock_speed, charp, 0);
+MODULE_PARM_DESC(clock_speed, "MediaLB Clock Speed");
+
+/*
+ * #############################################################################
+ *
+ * The define below activates an utility function used by HAL-simu
+ * for calling DIM interrupt handler.
+ * It is used only for TEST PURPOSE and shall be commented before release.
+ *
+ * #############################################################################
+ */
+/* #define ENABLE_HDM_TEST */
+
+static DEFINE_SPINLOCK(dim_lock);
+
+static void dim2_tasklet_fn(unsigned long data);
+static DECLARE_TASKLET(dim2_tasklet, dim2_tasklet_fn, 0);
+
+/**
+ * struct hdm_channel - private structure to keep channel specific data
+ * @is_initialized: identifier to know whether the channel is initialized
+ * @ch: HAL specific channel data
+ * @pending_list: list to keep MBO's before starting transfer
+ * @started_list: list to keep MBO's after starting transfer
+ * @direction: channel direction (TX or RX)
+ * @data_type: channel data type
+ */
+struct hdm_channel {
+ char name[sizeof "caNNN"];
+ bool is_initialized;
+ struct dim_channel ch;
+ struct list_head pending_list; /* before DIM_EnqueueBuffer() */
+ struct list_head started_list; /* after DIM_EnqueueBuffer() */
+ enum most_channel_direction direction;
+ enum most_channel_data_type data_type;
+};
+
+/**
+ * struct dim2_hdm - private structure to keep interface specific data
+ * @hch: an array of channel specific data
+ * @most_iface: most interface structure
+ * @capabilities: an array of channel capability data
+ * @io_base: I/O register base address
+ * @irq_ahb0: dim2 AHB0 irq number
+ * @clk_speed: user selectable (through command line parameter) clock speed
+ * @netinfo_task: thread to deliver network status
+ * @netinfo_waitq: waitq for the thread to sleep
+ * @deliver_netinfo: to identify whether network status received
+ * @mac_addrs: INIC mac address
+ * @link_state: network link state
+ * @atx_idx: index of async tx channel
+ */
+struct dim2_hdm {
+ struct hdm_channel hch[DMA_CHANNELS];
+ struct most_channel_capability capabilities[DMA_CHANNELS];
+ struct most_interface most_iface;
+ char name[16 + sizeof "dim2-"];
+ void *io_base;
+ unsigned int irq_ahb0;
+ int clk_speed;
+ struct task_struct *netinfo_task;
+ wait_queue_head_t netinfo_waitq;
+ int deliver_netinfo;
+ unsigned char mac_addrs[6];
+ unsigned char link_state;
+ int atx_idx;
+ struct medialb_bus bus;
+};
+
+#define iface_to_hdm(iface) container_of(iface, struct dim2_hdm, most_iface)
+
+/* Macro to identify a network status message */
+#define PACKET_IS_NET_INFO(p) \
+ (((p)[1] == 0x18) && ((p)[2] == 0x05) && ((p)[3] == 0x0C) && \
+ ((p)[13] == 0x3C) && ((p)[14] == 0x00) && ((p)[15] == 0x0A))
+
+#if defined(ENABLE_HDM_TEST)
+static struct dim2_hdm *test_dev;
+#endif
+
+bool dim2_sysfs_get_state_cb(void)
+{
+ bool state;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dim_lock, flags);
+ state = DIM_GetLockState();
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+ return state;
+}
+
+/**
+ * DIMCB_IoRead - callback from HAL to read an I/O register
+ * @ptr32: register address
+ */
+u32 DIMCB_IoRead(u32 *ptr32)
+{
+ return __raw_readl(ptr32);
+}
+
+/**
+ * DIMCB_IoWrite - callback from HAL to write value to an I/O register
+ * @ptr32: register address
+ * @value: value to write
+ */
+void DIMCB_IoWrite(u32 *ptr32, u32 value)
+{
+ __raw_writel(value, ptr32);
+}
+
+/**
+ * DIMCB_OnError - callback from HAL to report miscommunication between
+ * HDM and HAL
+ * @error_id: Error ID
+ * @error_message: Error message. Some text in a free format
+ */
+void DIMCB_OnError(u8 error_id, const char *error_message)
+{
+ pr_err("DIMCB_OnError: error_id - %d, error_message - %s\n", error_id,
+ error_message);
+}
+
+/**
+ * DIMCB_OnFail - callback from HAL to report unrecoverable errors
+ * @filename: Source file where the error happened
+ * @linenum: Line number of the file where the error happened
+ */
+void DIMCB_OnFail(const char *filename, int linenum)
+{
+ pr_err("DIMCB_OnFail: file - %s, line no. - %d\n", filename, linenum);
+}
+
+/**
+ * startup_dim - initialize the dim2 interface
+ * @pdev: platform device
+ *
+ * Get the value of command line parameter "clock_speed" if given or use the
+ * default value, enable the clock and PLL, and initialize the dim2 interface.
+ */
+static int startup_dim(struct platform_device *pdev)
+{
+ struct dim2_hdm *dev = platform_get_drvdata(pdev);
+ struct dim2_platform_data *pdata = pdev->dev.platform_data;
+ u8 hal_ret;
+
+ dev->clk_speed = -1;
+
+ if (clock_speed) {
+ if (!strcmp(clock_speed, "256fs"))
+ dev->clk_speed = CLK_256FS;
+ else if (!strcmp(clock_speed, "512fs"))
+ dev->clk_speed = CLK_512FS;
+ else if (!strcmp(clock_speed, "1024fs"))
+ dev->clk_speed = CLK_1024FS;
+ else if (!strcmp(clock_speed, "2048fs"))
+ dev->clk_speed = CLK_2048FS;
+ else if (!strcmp(clock_speed, "3072fs"))
+ dev->clk_speed = CLK_3072FS;
+ else if (!strcmp(clock_speed, "4096fs"))
+ dev->clk_speed = CLK_4096FS;
+ else if (!strcmp(clock_speed, "6144fs"))
+ dev->clk_speed = CLK_6144FS;
+ else if (!strcmp(clock_speed, "8192fs"))
+ dev->clk_speed = CLK_8192FS;
+ }
+
+ if (dev->clk_speed == -1) {
+ pr_info("Bad or missing clock speed parameter,"
+ " using default value: 3072fs\n");
+ dev->clk_speed = CLK_3072FS;
+ } else
+ pr_info("Selected clock speed: %s\n", clock_speed);
+
+ if (pdata && pdata->init) {
+ int ret = pdata->init(pdata, dev->io_base, dev->clk_speed);
+
+ if (ret)
+ return ret;
+ }
+
+ hal_ret = DIM_Startup(dev->io_base, dev->clk_speed);
+ if (hal_ret != DIM_NO_ERROR) {
+ pr_err("DIM_Startup failed: %d\n", hal_ret);
+ if (pdata && pdata->destroy)
+ pdata->destroy(pdata);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/**
+ * try_start_dim_transfer - try to transfer a buffer on a channel
+ * @hdm_ch: channel specific data
+ *
+ * Transfer a buffer from pending_list if the channel is ready
+ */
+static int try_start_dim_transfer(struct hdm_channel *hdm_ch)
+{
+ u16 buf_size;
+ struct list_head *head = &hdm_ch->pending_list;
+ struct mbo *mbo;
+ unsigned long flags;
+ struct dim_ch_state_t st;
+
+ BUG_ON(hdm_ch == 0);
+ BUG_ON(!hdm_ch->is_initialized);
+
+ spin_lock_irqsave(&dim_lock, flags);
+ if (list_empty(head)) {
+ spin_unlock_irqrestore(&dim_lock, flags);
+ return -EAGAIN;
+ }
+
+ if (!DIM_GetChannelState(&hdm_ch->ch, &st)->ready) {
+ spin_unlock_irqrestore(&dim_lock, flags);
+ return -EAGAIN;
+ }
+
+ mbo = list_entry(head->next, struct mbo, list);
+ buf_size = mbo->buffer_length;
+
+ BUG_ON(mbo->bus_address == 0);
+ if (!DIM_EnqueueBuffer(&hdm_ch->ch, mbo->bus_address, buf_size)) {
+ list_del(head->next);
+ spin_unlock_irqrestore(&dim_lock, flags);
+ mbo->processed_length = 0;
+ mbo->status = MBO_E_INVAL;
+ mbo->complete(mbo);
+ return -EFAULT;
+ }
+
+ list_move_tail(head->next, &hdm_ch->started_list);
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+ return 0;
+}
+
+/**
+ * deliver_netinfo_thread - thread to deliver network status to mostcore
+ * @data: private data
+ *
+ * Wait for network status and deliver it to mostcore once it is received
+ */
+static int deliver_netinfo_thread(void *data)
+{
+ struct dim2_hdm *dev = (struct dim2_hdm *)data;
+
+ while (!kthread_should_stop()) {
+ wait_event_interruptible(dev->netinfo_waitq,
+ dev->deliver_netinfo ||
+ kthread_should_stop());
+
+ if (dev->deliver_netinfo) {
+ dev->deliver_netinfo--;
+ most_deliver_netinfo(&dev->most_iface, dev->link_state,
+ dev->mac_addrs);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * retrieve_netinfo - retrieve network status from received buffer
+ * @dev: private data
+ * @mbo: received MBO
+ *
+ * Parse the message in buffer and get node address, link state, MAC address.
+ * Wake up a thread to deliver this status to mostcore
+ */
+static void retrieve_netinfo(struct dim2_hdm *dev, struct mbo *mbo)
+{
+ u8 *data = mbo->virt_address;
+ u8 *mac = dev->mac_addrs;
+
+ pr_info("Node Address: 0x%03x\n", (u16)data[16] << 8 | data[17]);
+ dev->link_state = data[18];
+ pr_info("NIState: %d\n", dev->link_state);
+ memcpy(mac, data + 19, 6);
+ pr_info("MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+ dev->deliver_netinfo++;
+ wake_up_interruptible(&dev->netinfo_waitq);
+}
+
+/**
+ * service_done_flag - handle completed buffers
+ * @dev: private data
+ * @ch_idx: channel index
+ *
+ * Return back the completed buffers to mostcore, using completion callback
+ */
+static void service_done_flag(struct dim2_hdm *dev, int ch_idx)
+{
+ struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+ struct dim_ch_state_t st;
+ struct list_head *head;
+ struct mbo *mbo;
+ int done_buffers;
+ unsigned long flags;
+ u8 *data;
+
+ BUG_ON(hdm_ch == 0);
+ BUG_ON(!hdm_ch->is_initialized);
+
+ spin_lock_irqsave(&dim_lock, flags);
+
+ done_buffers = DIM_GetChannelState(&hdm_ch->ch, &st)->done_buffers;
+ if (!done_buffers) {
+ spin_unlock_irqrestore(&dim_lock, flags);
+ return;
+ }
+
+ if (!DIM_DetachBuffers(&hdm_ch->ch, done_buffers)) {
+ spin_unlock_irqrestore(&dim_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+ head = &hdm_ch->started_list;
+
+ while (done_buffers) {
+ spin_lock_irqsave(&dim_lock, flags);
+ if (list_empty(head)) {
+ spin_unlock_irqrestore(&dim_lock, flags);
+ pr_crit("hard error: started_mbo list is empty "
+ "whereas DIM2 has sent buffers\n");
+ break;
+ }
+
+ mbo = list_entry(head->next, struct mbo, list);
+ list_del(head->next);
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+ data = mbo->virt_address;
+
+ if (hdm_ch->data_type == MOST_CH_ASYNC &&
+ hdm_ch->direction == MOST_CH_RX &&
+ PACKET_IS_NET_INFO(data)) {
+
+ retrieve_netinfo(dev, mbo);
+
+ spin_lock_irqsave(&dim_lock, flags);
+ list_add_tail(&mbo->list, &hdm_ch->pending_list);
+ spin_unlock_irqrestore(&dim_lock, flags);
+ } else {
+ if (hdm_ch->data_type == MOST_CH_CONTROL ||
+ hdm_ch->data_type == MOST_CH_ASYNC) {
+
+ u32 const data_size =
+ (u32)data[0] * 256 + data[1] + 2;
+
+ mbo->processed_length =
+ min(data_size, (u32)mbo->buffer_length);
+ } else {
+ mbo->processed_length = mbo->buffer_length;
+ }
+ mbo->status = MBO_SUCCESS;
+ mbo->complete(mbo);
+ }
+
+ done_buffers--;
+ }
+}
+
+static struct dim_channel **get_active_channels(struct dim2_hdm *dev,
+ struct dim_channel **buffer)
+{
+ int idx = 0;
+ int ch_idx;
+
+ for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
+ if (dev->hch[ch_idx].is_initialized)
+ buffer[idx++] = &dev->hch[ch_idx].ch;
+ }
+ buffer[idx++] = 0;
+
+ return buffer;
+}
+
+/**
+ * dim2_tasklet_fn - tasklet function
+ * @data: private data
+ *
+ * Service each initialized channel, if needed
+ */
+static void dim2_tasklet_fn(unsigned long data)
+{
+ struct dim2_hdm *dev = (struct dim2_hdm *)data;
+ unsigned long flags;
+ int ch_idx;
+
+ for (ch_idx = 0; ch_idx < DMA_CHANNELS; ch_idx++) {
+ if (!dev->hch[ch_idx].is_initialized)
+ continue;
+
+ spin_lock_irqsave(&dim_lock, flags);
+ DIM_ServiceChannel(&(dev->hch[ch_idx].ch));
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+ service_done_flag(dev, ch_idx);
+ while (!try_start_dim_transfer(dev->hch + ch_idx))
+ continue;
+ }
+}
+
+/**
+ * dim2_ahb_isr - interrupt service routine
+ * @irq: irq number
+ * @_dev: private data
+ *
+ * Acknowledge the interrupt and schedule a tasklet to service channels.
+ * Return IRQ_HANDLED.
+ */
+static irqreturn_t dim2_ahb_isr(int irq, void *_dev)
+{
+ struct dim2_hdm *dev = (struct dim2_hdm *)_dev;
+ struct dim_channel *buffer[DMA_CHANNELS + 1];
+ unsigned long flags;
+
+ spin_lock_irqsave(&dim_lock, flags);
+ DIM_ServiceIrq(get_active_channels(dev, buffer));
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+#if !defined(ENABLE_HDM_TEST)
+ dim2_tasklet.data = (unsigned long)dev;
+ tasklet_schedule(&dim2_tasklet);
+#else
+ dim2_tasklet_fn((unsigned long)dev);
+#endif
+ return IRQ_HANDLED;
+}
+
+#if defined(ENABLE_HDM_TEST)
+
+/*
+ * Utility function used by HAL-simu for calling DIM interrupt handler.
+ * It is used only for TEST PURPOSE.
+ */
+void raise_dim_interrupt(void)
+{
+ (void)dim2_ahb_isr(0, test_dev);
+}
+#endif
+
+/**
+ * complete_all_mbos - complete MBO's in a list
+ * @head: list head
+ *
+ * Delete all the entries in list and return back MBO's to mostcore using
+ * completion call back.
+ */
+static void complete_all_mbos(struct list_head *head)
+{
+ unsigned long flags;
+ struct mbo *mbo;
+
+ for (;;) {
+ spin_lock_irqsave(&dim_lock, flags);
+ if (list_empty(head)) {
+ spin_unlock_irqrestore(&dim_lock, flags);
+ break;
+ }
+
+ mbo = list_entry(head->next, struct mbo, list);
+ list_del(head->next);
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+ mbo->processed_length = 0;
+ mbo->status = MBO_E_CLOSE;
+ mbo->complete(mbo);
+ }
+}
+
+/**
+ * configure_channel - initialize a channel
+ * @iface: interface the channel belongs to
+ * @channel: channel to be configured
+ * @channel_config: structure that holds the configuration information
+ *
+ * Receives configuration information from mostcore and initialize
+ * the corresponding channel. Return 0 on success, negative on failure.
+ */
+static int configure_channel(struct most_interface *most_iface, int ch_idx,
+ struct most_channel_config *ccfg)
+{
+ struct dim2_hdm *dev = iface_to_hdm(most_iface);
+ bool const is_tx = ccfg->direction == MOST_CH_TX;
+ u16 const sub_size = ccfg->subbuffer_size;
+ u16 const buf_size = ccfg->buffer_size;
+ u16 new_size;
+ unsigned long flags;
+ u8 hal_ret;
+ int const ch_addr = ch_idx * 2 + 2;
+ struct hdm_channel *const hdm_ch = dev->hch + ch_idx;
+
+ BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+ if (hdm_ch->is_initialized)
+ return -EPERM;
+
+ switch (ccfg->data_type) {
+ case MOST_CH_CONTROL:
+ new_size = DIM_NormCtrlAsyncBufferSize(buf_size);
+ if (new_size == 0) {
+ pr_err("%s: too small buffer size\n", hdm_ch->name);
+ return -EINVAL;
+ }
+ ccfg->buffer_size = new_size;
+ if (new_size != buf_size)
+ pr_warn("%s: fixed buffer size (%d -> %d)\n",
+ hdm_ch->name, buf_size, new_size);
+ spin_lock_irqsave(&dim_lock, flags);
+ hal_ret = DIM_InitControl(&hdm_ch->ch, is_tx, ch_addr, buf_size);
+ break;
+ case MOST_CH_ASYNC:
+ new_size = DIM_NormCtrlAsyncBufferSize(buf_size);
+ if (new_size == 0) {
+ pr_err("%s: too small buffer size\n", hdm_ch->name);
+ return -EINVAL;
+ }
+ ccfg->buffer_size = new_size;
+ if (new_size != buf_size)
+ pr_warn("%s: fixed buffer size (%d -> %d)\n",
+ hdm_ch->name, buf_size, new_size);
+ spin_lock_irqsave(&dim_lock, flags);
+ hal_ret = DIM_InitAsync(&hdm_ch->ch, is_tx, ch_addr, buf_size);
+ break;
+ case MOST_CH_ISOC_AVP:
+ new_size = DIM_NormIsocBufferSize(buf_size, sub_size);
+ if (new_size == 0) {
+ pr_err("%s: invalid sub-buffer size or "
+ "too small buffer size\n", hdm_ch->name);
+ return -EINVAL;
+ }
+ ccfg->buffer_size = new_size;
+ if (new_size != buf_size)
+ pr_warn("%s: fixed buffer size (%d -> %d)\n",
+ hdm_ch->name, buf_size, new_size);
+ spin_lock_irqsave(&dim_lock, flags);
+ hal_ret = DIM_InitIsoc(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+ break;
+ case MOST_CH_SYNC:
+ new_size = DIM_NormSyncBufferSize(buf_size, sub_size);
+ if (new_size == 0) {
+ pr_err("%s: invalid sub-buffer size or "
+ "too small buffer size\n", hdm_ch->name);
+ return -EINVAL;
+ }
+ ccfg->buffer_size = new_size;
+ if (new_size != buf_size)
+ pr_warn("%s: fixed buffer size (%d -> %d)\n",
+ hdm_ch->name, buf_size, new_size);
+ spin_lock_irqsave(&dim_lock, flags);
+ hal_ret = DIM_InitSync(&hdm_ch->ch, is_tx, ch_addr, sub_size);
+ break;
+ default:
+ pr_err("%s: configure failed, bad channel type: %d\n",
+ hdm_ch->name, ccfg->data_type);
+ return -EINVAL;
+ }
+
+ if (hal_ret != DIM_NO_ERROR) {
+ spin_unlock_irqrestore(&dim_lock, flags);
+ pr_err("%s: configure failed (%d), type: %d, is_tx: %d\n",
+ hdm_ch->name, hal_ret, ccfg->data_type, (int)is_tx);
+ return -ENODEV;
+ }
+
+ hdm_ch->data_type = ccfg->data_type;
+ hdm_ch->direction = ccfg->direction;
+ hdm_ch->is_initialized = true;
+
+ if (hdm_ch->data_type == MOST_CH_ASYNC &&
+ hdm_ch->direction == MOST_CH_TX &&
+ dev->atx_idx < 0)
+ dev->atx_idx = ch_idx;
+
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+ return 0;
+}
+
+/**
+ * enqueue - enqueue a buffer for data transfer
+ * @iface: intended interface
+ * @channel: ID of the channel the buffer is intended for
+ * @mbo: pointer to the buffer object
+ *
+ * Push the buffer into pending_list and try to transfer one buffer from
+ * pending_list. Return 0 on success, negative on failure.
+ */
+static int enqueue(struct most_interface *most_iface, int ch_idx,
+ struct mbo *mbo)
+{
+ struct dim2_hdm *dev = iface_to_hdm(most_iface);
+ struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+ unsigned long flags;
+
+ BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+ if (!hdm_ch->is_initialized)
+ return -EPERM;
+
+ if (mbo->bus_address == 0)
+ return -EFAULT;
+
+ spin_lock_irqsave(&dim_lock, flags);
+ list_add_tail(&mbo->list, &hdm_ch->pending_list);
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+ (void)try_start_dim_transfer(hdm_ch);
+
+ return 0;
+}
+
+/**
+ * request_netinfo - triggers retrieving of network info
+ * @iface: pointer to the interface
+ * @channel_id: corresponding channel ID
+ *
+ * Send a command to INIC which triggers retrieving of network info by means of
+ * "Message exchange over MDP/MEP". Return 0 on success, negative on failure.
+ */
+static void request_netinfo(struct most_interface *most_iface, int ch_idx)
+{
+ struct dim2_hdm *dev = iface_to_hdm(most_iface);
+ struct mbo *mbo;
+ u8 *data;
+
+ if (dev->atx_idx < 0) {
+ pr_err("Async Tx Not initialized\n");
+ return;
+ }
+
+ mbo = most_get_mbo(&dev->most_iface, dev->atx_idx);
+ if (!mbo)
+ return;
+
+ mbo->buffer_length = 5;
+
+ data = mbo->virt_address;
+
+ data[0] = 0x00; /* PML High byte */
+ data[1] = 0x03; /* PML Low byte */
+ data[2] = 0x02; /* PMHL */
+ data[3] = 0x08; /* FPH */
+ data[4] = 0x40; /* FMF (FIFO cmd msg - Triggers NAOverMDP) */
+
+ most_submit_mbo(mbo);
+}
+
+/**
+ * poison_channel - poison buffers of a channel
+ * @iface: pointer to the interface the channel to be poisoned belongs to
+ * @channel_id: corresponding channel ID
+ *
+ * Destroy a channel and complete all the buffers in both started_list &
+ * pending_list. Return 0 on success, negative on failure.
+ */
+static int poison_channel(struct most_interface *most_iface, int ch_idx)
+{
+ struct dim2_hdm *dev = iface_to_hdm(most_iface);
+ struct hdm_channel *hdm_ch = dev->hch + ch_idx;
+ unsigned long flags;
+ u8 hal_ret;
+ int ret = 0;
+
+ BUG_ON(ch_idx < 0 || ch_idx >= DMA_CHANNELS);
+
+ if (!hdm_ch->is_initialized)
+ return -EPERM;
+
+ spin_lock_irqsave(&dim_lock, flags);
+ hal_ret = DIM_DestroyChannel(&hdm_ch->ch);
+ hdm_ch->is_initialized = false;
+ if (ch_idx == dev->atx_idx)
+ dev->atx_idx = -1;
+ spin_unlock_irqrestore(&dim_lock, flags);
+ if (hal_ret != DIM_NO_ERROR) {
+ pr_err("HAL Failed to close channel %s\n", hdm_ch->name);
+ ret = -EFAULT;
+ }
+
+ complete_all_mbos(&hdm_ch->started_list);
+ complete_all_mbos(&hdm_ch->pending_list);
+
+ return ret;
+}
+
+/*
+ * dim2_probe - dim2 probe handler
+ * @pdev: platform device structure
+ *
+ * Register the dim2 interface with mostcore and initialize it.
+ * Return 0 on success, negative on failure.
+ */
+static int dim2_probe(struct platform_device *pdev)
+{
+ struct dim2_hdm *dev;
+ struct resource *res;
+ int ret, i;
+ struct kobject *kobj;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ dev->atx_idx = -1;
+
+ platform_set_drvdata(pdev, dev);
+#if defined(ENABLE_HDM_TEST)
+ test_dev = dev;
+#else
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ pr_err("no memory region defined\n");
+ ret = -ENOENT;
+ goto err_free_dev;
+ }
+
+ if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+ pr_err("failed to request mem region\n");
+ ret = -EBUSY;
+ goto err_free_dev;
+ }
+
+ dev->io_base = ioremap(res->start, resource_size(res));
+ if (!dev->io_base) {
+ pr_err("failed to ioremap\n");
+ ret = -ENOMEM;
+ goto err_release_mem;
+ }
+
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0) {
+ pr_err("failed to get irq\n");
+ goto err_unmap_io;
+ }
+ dev->irq_ahb0 = ret;
+
+ ret = request_irq(dev->irq_ahb0, dim2_ahb_isr, 0, "mlb_ahb0", dev);
+ if (ret) {
+ pr_err("failed to request IRQ: %d, err: %d\n", dev->irq_ahb0, ret);
+ goto err_unmap_io;
+ }
+#endif
+ init_waitqueue_head(&dev->netinfo_waitq);
+ dev->deliver_netinfo = 0;
+ dev->netinfo_task = kthread_run(&deliver_netinfo_thread, (void *)dev,
+ "dim2_netinfo");
+ if (IS_ERR(dev->netinfo_task)) {
+ ret = PTR_ERR(dev->netinfo_task);
+ goto err_free_irq;
+ }
+
+ for (i = 0; i < DMA_CHANNELS; i++) {
+ struct most_channel_capability *cap = dev->capabilities + i;
+ struct hdm_channel *hdm_ch = dev->hch + i;
+
+ INIT_LIST_HEAD(&hdm_ch->pending_list);
+ INIT_LIST_HEAD(&hdm_ch->started_list);
+ hdm_ch->is_initialized = false;
+ snprintf(hdm_ch->name, sizeof(hdm_ch->name), "ca%d", i * 2 + 2);
+
+ cap->name_suffix = hdm_ch->name;
+ cap->direction = MOST_CH_RX | MOST_CH_TX;
+ cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
+ MOST_CH_ISOC_AVP | MOST_CH_SYNC;
+ cap->num_buffers_packet = MAX_BUFFERS_PACKET;
+ cap->buffer_size_packet = MAX_BUF_SIZE_PACKET;
+ cap->num_buffers_streaming = MAX_BUFFERS_STREAMING;
+ cap->buffer_size_streaming = MAX_BUF_SIZE_STREAMING;
+ }
+
+ {
+ const char *fmt;
+
+ if (sizeof(res->start) == sizeof(long long))
+ fmt = "dim2-%016llx";
+ else if (sizeof(res->start) == sizeof(long))
+ fmt = "dim2-%016lx";
+ else
+ fmt = "dim2-%016x";
+
+ snprintf(dev->name, sizeof(dev->name), fmt, res->start);
+ }
+
+ dev->most_iface.interface = ITYPE_MEDIALB_DIM2;
+ dev->most_iface.description = dev->name;
+ dev->most_iface.num_channels = DMA_CHANNELS;
+ dev->most_iface.channel_vector = dev->capabilities;
+ dev->most_iface.configure = configure_channel;
+ dev->most_iface.enqueue = enqueue;
+ dev->most_iface.poison_channel = poison_channel;
+ dev->most_iface.request_netinfo = request_netinfo;
+
+ kobj = most_register_interface(&dev->most_iface);
+ if (IS_ERR(kobj)) {
+ ret = PTR_ERR(kobj);
+ pr_err("failed to register MOST interface\n");
+ goto err_stop_thread;
+ }
+
+ ret = dim2_sysfs_probe(&dev->bus, kobj);
+ if (ret)
+ goto err_unreg_iface;
+
+ ret = startup_dim(pdev);
+ if (ret) {
+ pr_err("failed to initialize DIM2\n");
+ goto err_destroy_bus;
+ }
+
+ return 0;
+
+err_destroy_bus:
+ dim2_sysfs_destroy(&dev->bus);
+err_unreg_iface:
+ most_deregister_interface(&dev->most_iface);
+err_stop_thread:
+ kthread_stop(dev->netinfo_task);
+err_free_irq:
+#if !defined(ENABLE_HDM_TEST)
+ free_irq(dev->irq_ahb0, dev);
+err_unmap_io:
+ iounmap(dev->io_base);
+err_release_mem:
+ release_mem_region(res->start, resource_size(res));
+err_free_dev:
+#endif
+ kfree(dev);
+
+ return ret;
+}
+
+/**
+ * dim2_remove - dim2 remove handler
+ * @pdev: platform device structure
+ *
+ * Unregister the interface from mostcore
+ */
+static int dim2_remove(struct platform_device *pdev)
+{
+ struct dim2_hdm *dev = platform_get_drvdata(pdev);
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct dim2_platform_data *pdata = pdev->dev.platform_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dim_lock, flags);
+ DIM_Shutdown();
+ spin_unlock_irqrestore(&dim_lock, flags);
+
+ if (pdata && pdata->destroy)
+ pdata->destroy(pdata);
+
+ dim2_sysfs_destroy(&dev->bus);
+ most_deregister_interface(&dev->most_iface);
+ kthread_stop(dev->netinfo_task);
+#if !defined(ENABLE_HDM_TEST)
+ free_irq(dev->irq_ahb0, dev);
+ iounmap(dev->io_base);
+ release_mem_region(res->start, resource_size(res));
+#endif
+ kfree(dev);
+ platform_set_drvdata(pdev, NULL);
+
+ /*
+ * break link to local platform_device_id struct
+ * to prevent crash by unload platform device module
+ */
+ pdev->id_entry = 0;
+
+ return 0;
+}
+
+static struct platform_device_id dim2_id[] = {
+ { "medialb_dim2" },
+ { }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(platform, dim2_id);
+
+static struct platform_driver dim2_driver = {
+ .probe = dim2_probe,
+ .remove = dim2_remove,
+ .id_table = dim2_id,
+ .driver = {
+ .name = "hdm_dim2",
+ .owner = THIS_MODULE,
+ },
+};
+
+/**
+ * dim2_hdm_init - Driver Registration Routine
+ */
+static int __init dim2_hdm_init(void)
+{
+ pr_info("dim2_hdm_init()\n");
+ return platform_driver_register(&dim2_driver);
+}
+
+/**
+ * dim2_hdm_exit - Driver Cleanup Routine
+ **/
+static void __exit dim2_hdm_exit(void)
+{
+ pr_info("dim2_hdm_exit()\n");
+ platform_driver_unregister(&dim2_driver);
+}
+
+module_init(dim2_hdm_init);
+module_exit(dim2_hdm_exit);
+
+MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("MediaLB DIM2 Hardware Dependent Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-dim2/dim2_hdm.h b/drivers/staging/most/hdm-dim2/dim2_hdm.h
new file mode 100644
index 0000000..6e68832
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/dim2_hdm.h
@@ -0,0 +1,26 @@
+/*
+ * dim2_hdm.h - MediaLB DIM2 HDM Header
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef DIM2_HDM_H
+#define DIM2_HDM_H
+
+struct device;
+
+/* platform dependent data for dim2 interface */
+struct dim2_platform_data {
+ int (*init)(struct dim2_platform_data *pd, void *io_base, int clk_speed);
+ void (*destroy)(struct dim2_platform_data *pd);
+ void *priv;
+};
+
+#endif /* DIM2_HDM_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_reg.h b/drivers/staging/most/hdm-dim2/dim2_reg.h
new file mode 100644
index 0000000..476f66f
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/dim2_reg.h
@@ -0,0 +1,176 @@
+/*
+ * dim2_reg.h - Definitions for registers of DIM2
+ * (MediaLB, Device Interface Macro IP, OS62420)
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#ifndef DIM2_OS62420_H
+#define DIM2_OS62420_H
+
+#include <linux/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+struct dim2_regs {
+ /* 0x00 */ u32 MLBC0;
+ /* 0x01 */ u32 rsvd0[1];
+ /* 0x02 */ u32 MLBPC0;
+ /* 0x03 */ u32 MS0;
+ /* 0x04 */ u32 rsvd1[1];
+ /* 0x05 */ u32 MS1;
+ /* 0x06 */ u32 rsvd2[2];
+ /* 0x08 */ u32 MSS;
+ /* 0x09 */ u32 MSD;
+ /* 0x0A */ u32 rsvd3[1];
+ /* 0x0B */ u32 MIEN;
+ /* 0x0C */ u32 rsvd4[1];
+ /* 0x0D */ u32 MLBPC2;
+ /* 0x0E */ u32 MLBPC1;
+ /* 0x0F */ u32 MLBC1;
+ /* 0x10 */ u32 rsvd5[0x10];
+ /* 0x20 */ u32 HCTL;
+ /* 0x21 */ u32 rsvd6[1];
+ /* 0x22 */ u32 HCMR0;
+ /* 0x23 */ u32 HCMR1;
+ /* 0x24 */ u32 HCER0;
+ /* 0x25 */ u32 HCER1;
+ /* 0x26 */ u32 HCBR0;
+ /* 0x27 */ u32 HCBR1;
+ /* 0x28 */ u32 rsvd7[8];
+ /* 0x30 */ u32 MDAT0;
+ /* 0x31 */ u32 MDAT1;
+ /* 0x32 */ u32 MDAT2;
+ /* 0x33 */ u32 MDAT3;
+ /* 0x34 */ u32 MDWE0;
+ /* 0x35 */ u32 MDWE1;
+ /* 0x36 */ u32 MDWE2;
+ /* 0x37 */ u32 MDWE3;
+ /* 0x38 */ u32 MCTL;
+ /* 0x39 */ u32 MADR;
+ /* 0x3A */ u32 rsvd8[0xB6];
+ /* 0xF0 */ u32 ACTL;
+ /* 0xF1 */ u32 rsvd9[3];
+ /* 0xF4 */ u32 ACSR0;
+ /* 0xF5 */ u32 ACSR1;
+ /* 0xF6 */ u32 ACMR0;
+ /* 0xF7 */ u32 ACMR1;
+};
+
+
+#define DIM2_MASK(n) (~((~(u32)0)<<(n)))
+
+enum {
+ MLBC0_MLBLK_BIT = 7,
+
+ MLBC0_MLBPEN_BIT = 5,
+
+ MLBC0_MLBCLK_SHIFT = 2,
+ MLBC0_MLBCLK_VAL_256FS = 0,
+ MLBC0_MLBCLK_VAL_512FS = 1,
+ MLBC0_MLBCLK_VAL_1024FS = 2,
+ MLBC0_MLBCLK_VAL_2048FS = 3,
+
+ MLBC0_FCNT_SHIFT = 15,
+ MLBC0_FCNT_MASK = 7,
+ MLBC0_FCNT_VAL_1FPSB = 0,
+ MLBC0_FCNT_VAL_2FPSB = 1,
+ MLBC0_FCNT_VAL_4FPSB = 2,
+ MLBC0_FCNT_VAL_8FPSB = 3,
+ MLBC0_FCNT_VAL_16FPSB = 4,
+ MLBC0_FCNT_VAL_32FPSB = 5,
+ MLBC0_FCNT_VAL_64FPSB = 6,
+
+ MLBC0_MLBEN_BIT = 0,
+
+ MIEN_CTX_BREAK_BIT = 29,
+ MIEN_CTX_PE_BIT = 28,
+ MIEN_CTX_DONE_BIT = 27,
+
+ MIEN_CRX_BREAK_BIT = 26,
+ MIEN_CRX_PE_BIT = 25,
+ MIEN_CRX_DONE_BIT = 24,
+
+ MIEN_ATX_BREAK_BIT = 22,
+ MIEN_ATX_PE_BIT = 21,
+ MIEN_ATX_DONE_BIT = 20,
+
+ MIEN_ARX_BREAK_BIT = 19,
+ MIEN_ARX_PE_BIT = 18,
+ MIEN_ARX_DONE_BIT = 17,
+
+ MIEN_SYNC_PE_BIT = 16,
+
+ MIEN_ISOC_BUFO_BIT = 1,
+ MIEN_ISOC_PE_BIT = 0,
+
+ MLBC1_NDA_SHIFT = 8,
+ MLBC1_NDA_MASK = 0xFF,
+
+ MLBC1_CLKMERR_BIT = 7,
+ MLBC1_LOCKERR_BIT = 6,
+
+ ACTL_DMA_MODE_BIT = 2,
+ ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0,
+ ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1,
+ ACTL_SCE_BIT = 0,
+
+ HCTL_EN_BIT = 15
+};
+
+enum {
+ CDT1_BS_ISOC_SHIFT = 0,
+ CDT1_BS_ISOC_MASK = DIM2_MASK(9),
+
+ CDT3_BD_SHIFT = 0,
+ CDT3_BD_MASK = DIM2_MASK(12),
+ CDT3_BD_ISOC_MASK = DIM2_MASK(13),
+ CDT3_BA_SHIFT = 16,
+
+ ADT0_CE_BIT = 15,
+ ADT0_LE_BIT = 14,
+ ADT0_PG_BIT = 13,
+
+ ADT1_RDY_BIT = 15,
+ ADT1_DNE_BIT = 14,
+ ADT1_ERR_BIT = 13,
+ ADT1_PS_BIT = 12,
+ ADT1_MEP_BIT = 11,
+ ADT1_BD_SHIFT = 0,
+ ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
+ ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),
+
+ CAT_MFE_BIT = 14,
+
+ CAT_MT_BIT = 13,
+
+ CAT_RNW_BIT = 12,
+
+ CAT_CE_BIT = 11,
+
+ CAT_CT_SHIFT = 8,
+ CAT_CT_VAL_SYNC = 0,
+ CAT_CT_VAL_CONTROL = 1,
+ CAT_CT_VAL_ASYNC = 2,
+ CAT_CT_VAL_ISOC = 3,
+
+ CAT_CL_SHIFT = 0,
+ CAT_CL_MASK = DIM2_MASK(6)
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DIM2_OS62420_H */
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.c b/drivers/staging/most/hdm-dim2/dim2_sysfs.c
new file mode 100644
index 0000000..8e331a2
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.c
@@ -0,0 +1,116 @@
+/*
+ * dim2_sysfs.c - MediaLB sysfs information
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include "dim2_sysfs.h"
+
+struct bus_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct medialb_bus *bus, char *buf);
+ ssize_t (*store)(struct medialb_bus *bus, const char *buf, size_t count);
+};
+
+static ssize_t state_show(struct medialb_bus *bus, char *buf)
+{
+ bool state = dim2_sysfs_get_state_cb();
+
+ return sprintf(buf, "%s\n", state ? "locked" : "");
+}
+
+static struct bus_attr state_attr = __ATTR_RO(state);
+
+static struct attribute *bus_default_attrs[] = {
+ &state_attr.attr,
+ NULL,
+};
+
+static struct attribute_group bus_attr_group = {
+ .attrs = bus_default_attrs,
+};
+
+static void bus_kobj_release(struct kobject *kobj)
+{
+}
+
+static ssize_t bus_kobj_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct medialb_bus *bus =
+ container_of(kobj, struct medialb_bus, kobj_group);
+ struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
+
+ if (!xattr->show)
+ return -EIO;
+
+ return xattr->show(bus, buf);
+}
+
+static ssize_t bus_kobj_attr_store(struct kobject *kobj, struct attribute *attr,
+ const char *buf, size_t count)
+{
+ ssize_t ret;
+ struct medialb_bus *bus =
+ container_of(kobj, struct medialb_bus, kobj_group);
+ struct bus_attr *xattr = container_of(attr, struct bus_attr, attr);
+
+ if (!xattr->store)
+ return -EIO;
+
+ ret = xattr->store(bus, buf, count);
+ return ret;
+}
+
+static struct sysfs_ops const bus_kobj_sysfs_ops = {
+ .show = bus_kobj_attr_show,
+ .store = bus_kobj_attr_store,
+};
+
+static struct kobj_type bus_ktype = {
+ .release = bus_kobj_release,
+ .sysfs_ops = &bus_kobj_sysfs_ops,
+};
+
+int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj)
+{
+ int err;
+
+ kobject_init(&bus->kobj_group, &bus_ktype);
+ err = kobject_add(&bus->kobj_group, parent_kobj, "bus");
+ if (err) {
+ pr_err("kobject_add() failed: %d\n", err);
+ goto err_kobject_add;
+ }
+
+ err = sysfs_create_group(&bus->kobj_group, &bus_attr_group);
+ if (err) {
+ pr_err("sysfs_create_group() failed: %d\n", err);
+ goto err_create_group;
+ }
+
+ return 0;
+
+err_create_group:
+ kobject_put(&bus->kobj_group);
+
+err_kobject_add:
+ return err;
+}
+
+void dim2_sysfs_destroy(struct medialb_bus *bus)
+{
+ kobject_put(&bus->kobj_group);
+}
diff --git a/drivers/staging/most/hdm-dim2/dim2_sysfs.h b/drivers/staging/most/hdm-dim2/dim2_sysfs.h
new file mode 100644
index 0000000..e719691
--- /dev/null
+++ b/drivers/staging/most/hdm-dim2/dim2_sysfs.h
@@ -0,0 +1,39 @@
+/*
+ * dim2_sysfs.h - MediaLB sysfs information
+ *
+ * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/* Author: Andrey Shvetsov <andrey.shvetsov@k2l.de> */
+
+#ifndef DIM2_SYSFS_H
+#define DIM2_SYSFS_H
+
+
+#include <linux/kobject.h>
+
+
+struct medialb_bus {
+ struct kobject kobj_group;
+};
+
+struct dim2_hdm;
+
+int dim2_sysfs_probe(struct medialb_bus *bus, struct kobject *parent_kobj);
+void dim2_sysfs_destroy(struct medialb_bus *bus);
+
+/*
+ * callback,
+ * must deliver MediaLB state as true if locked or false if unlocked
+ */
+bool dim2_sysfs_get_state_cb(void);
+
+
+#endif /* DIM2_SYSFS_H */
diff --git a/drivers/staging/most/hdm-i2c/Kconfig b/drivers/staging/most/hdm-i2c/Kconfig
new file mode 100644
index 0000000..6fd7983
--- /dev/null
+++ b/drivers/staging/most/hdm-i2c/Kconfig
@@ -0,0 +1,12 @@
+#
+# MOST I2C configuration
+#
+
+config HDM_I2C
+ tristate "I2C HDM"
+ depends on I2C
+ ---help---
+ Say Y here if you want to connect via I2C to network tranceiver.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hdm_i2c.
diff --git a/drivers/staging/most/hdm-i2c/Makefile b/drivers/staging/most/hdm-i2c/Makefile
new file mode 100644
index 0000000..03a4a59
--- /dev/null
+++ b/drivers/staging/most/hdm-i2c/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_HDM_I2C) += hdm_i2c.o
+
+ccflags-y += -Idrivers/staging/most/mostcore/
diff --git a/drivers/staging/most/hdm-i2c/hdm_i2c.c b/drivers/staging/most/hdm-i2c/hdm_i2c.c
new file mode 100644
index 0000000..029ded3
--- /dev/null
+++ b/drivers/staging/most/hdm-i2c/hdm_i2c.c
@@ -0,0 +1,451 @@
+/*
+ * hdm_i2c.c - Hardware Dependent Module for I2C Interface
+ *
+ * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+
+#include <mostcore.h>
+
+enum { CH_RX, CH_TX, NUM_CHANNELS };
+
+#define MAX_BUFFERS_CONTROL 32
+#define MAX_BUF_SIZE_CONTROL 256
+
+/**
+ * list_first_mbo - get the first mbo from a list
+ * @ptr: the list head to take the mbo from.
+ */
+#define list_first_mbo(ptr) \
+ list_first_entry(ptr, struct mbo, list)
+
+
+/* IRQ / Polling option */
+static bool polling_req;
+module_param(polling_req, bool, S_IRUGO);
+MODULE_PARM_DESC(polling_req, "Request Polling. Default = 0 (use irq)");
+
+/* Polling Rate */
+static int scan_rate = 100;
+module_param(scan_rate, int, 0644);
+MODULE_PARM_DESC(scan_rate, "Polling rate in times/sec. Default = 100");
+
+struct hdm_i2c {
+ bool is_open[NUM_CHANNELS];
+ bool polling_mode;
+ struct most_interface most_iface;
+ struct most_channel_capability capabilities[NUM_CHANNELS];
+ struct i2c_client *client;
+ struct rx {
+ struct delayed_work dwork;
+ wait_queue_head_t waitq;
+ struct list_head list;
+ struct mutex list_mutex;
+ } rx;
+ char name[64];
+};
+
+#define to_hdm(iface) container_of(iface, struct hdm_i2c, most_iface)
+
+/**
+ * configure_channel - called from MOST core to configure a channel
+ * @iface: interface the channel belongs to
+ * @channel: channel to be configured
+ * @channel_config: structure that holds the configuration information
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Receives configuration information from MOST core and initialize the
+ * corresponding channel.
+ */
+static int configure_channel(struct most_interface *most_iface,
+ int ch_idx,
+ struct most_channel_config *channel_config)
+{
+ struct hdm_i2c *dev = to_hdm(most_iface);
+
+ BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+ BUG_ON(dev->is_open[ch_idx]);
+
+ if (channel_config->data_type != MOST_CH_CONTROL) {
+ pr_err("bad data type for channel %d\n", ch_idx);
+ return -EPERM;
+ }
+
+ if (channel_config->direction != dev->capabilities[ch_idx].direction) {
+ pr_err("bad direction for channel %d\n", ch_idx);
+ return -EPERM;
+ }
+
+ if (channel_config->direction == MOST_CH_RX) {
+ if (dev->polling_mode)
+ schedule_delayed_work(&dev->rx.dwork,
+ msecs_to_jiffies(MSEC_PER_SEC / 4));
+ }
+ dev->is_open[ch_idx] = true;
+
+ return 0;
+}
+
+/**
+ * enqueue - called from MOST core to enqueue a buffer for data transfer
+ * @iface: intended interface
+ * @channel: ID of the channel the buffer is intended for
+ * @mbo: pointer to the buffer object
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Transmit the data over I2C if it is a "write" request or push the buffer into
+ * list if it is an "read" request
+ */
+static int enqueue(struct most_interface *most_iface,
+ int ch_idx, struct mbo *mbo)
+{
+ struct hdm_i2c *dev = to_hdm(most_iface);
+ int ret;
+
+ BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+ BUG_ON(!dev->is_open[ch_idx]);
+
+ if (ch_idx == CH_RX) {
+ /* RX */
+ mutex_lock(&dev->rx.list_mutex);
+ list_add_tail(&mbo->list, &dev->rx.list);
+ mutex_unlock(&dev->rx.list_mutex);
+ wake_up_interruptible(&dev->rx.waitq);
+ } else {
+ /* TX */
+ ret = i2c_master_send(dev->client, mbo->virt_address,
+ mbo->buffer_length);
+ if (ret <= 0) {
+ mbo->processed_length = 0;
+ mbo->status = MBO_E_INVAL;
+ } else {
+ mbo->processed_length = mbo->buffer_length;
+ mbo->status = MBO_SUCCESS;
+ }
+ mbo->complete(mbo);
+ }
+
+ return 0;
+}
+
+/**
+ * poison_channel - called from MOST core to poison buffers of a channel
+ * @iface: pointer to the interface the channel to be poisoned belongs to
+ * @channel_id: corresponding channel ID
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * If channel direction is RX, complete the buffers in list with
+ * status MBO_E_CLOSE
+ */
+static int poison_channel(struct most_interface *most_iface,
+ int ch_idx)
+{
+ struct hdm_i2c *dev = to_hdm(most_iface);
+ struct mbo *mbo;
+
+ BUG_ON(ch_idx < 0 || ch_idx >= NUM_CHANNELS);
+ BUG_ON(!dev->is_open[ch_idx]);
+
+ dev->is_open[ch_idx] = false;
+
+ if (ch_idx == CH_RX) {
+ mutex_lock(&dev->rx.list_mutex);
+ while (!list_empty(&dev->rx.list)) {
+ mbo = list_first_mbo(&dev->rx.list);
+ list_del(&mbo->list);
+ mutex_unlock(&dev->rx.list_mutex);
+
+ mbo->processed_length = 0;
+ mbo->status = MBO_E_CLOSE;
+ mbo->complete(mbo);
+
+ mutex_lock(&dev->rx.list_mutex);
+ }
+ mutex_unlock(&dev->rx.list_mutex);
+ wake_up_interruptible(&dev->rx.waitq);
+ }
+
+ return 0;
+}
+
+static void request_netinfo(struct most_interface *most_iface,
+ int ch_idx)
+{
+ pr_info("request_netinfo()\n");
+}
+
+static void do_rx_work(struct hdm_i2c *dev)
+{
+ struct mbo *mbo;
+ unsigned char msg[MAX_BUF_SIZE_CONTROL];
+ int ret, ch_idx = CH_RX;
+ uint16_t pml, data_size;
+
+ /* Read PML (2 bytes) */
+ ret = i2c_master_recv(dev->client, msg, 2);
+ if (ret <= 0) {
+ pr_err("Failed to receive PML\n");
+ return;
+ }
+
+ pml = (msg[0] << 8) | msg[1];
+ if (!pml)
+ return;
+
+ data_size = pml + 2;
+
+ /* Read the whole message, including PML */
+ ret = i2c_master_recv(dev->client, msg, data_size);
+ if (ret <= 0) {
+ pr_err("Failed to receive a Port Message\n");
+ return;
+ }
+
+ for (;;) {
+ /* Conditions to wait for: poisoned channel or free buffer
+ available for reading */
+ if (wait_event_interruptible(dev->rx.waitq,
+ !dev->is_open[ch_idx] ||
+ !list_empty(&dev->rx.list))) {
+ pr_err("wait_event_interruptible() failed\n");
+ return;
+ }
+
+ if (!dev->is_open[ch_idx])
+ return;
+
+ mutex_lock(&dev->rx.list_mutex);
+
+ /* list may be empty if poison or remove is called */
+ if (!list_empty(&dev->rx.list))
+ break;
+
+ mutex_unlock(&dev->rx.list_mutex);
+ }
+
+ mbo = list_first_mbo(&dev->rx.list);
+ list_del(&mbo->list);
+ mutex_unlock(&dev->rx.list_mutex);
+
+ mbo->processed_length = min(data_size, mbo->buffer_length);
+ memcpy(mbo->virt_address, msg, mbo->processed_length);
+ mbo->status = MBO_SUCCESS;
+ mbo->complete(mbo);
+}
+
+/**
+ * pending_rx_work - Read pending messages through I2C
+ * @work: definition of this work item
+ *
+ * Invoked by the Interrupt Service Routine, most_irq_handler()
+ */
+static void pending_rx_work(struct work_struct *work)
+{
+ struct hdm_i2c *dev = container_of(work, struct hdm_i2c, rx.dwork.work);
+
+ do_rx_work(dev);
+
+ if (dev->polling_mode) {
+ if (dev->is_open[CH_RX])
+ schedule_delayed_work(&dev->rx.dwork,
+ msecs_to_jiffies(MSEC_PER_SEC
+ / scan_rate));
+ } else
+ enable_irq(dev->client->irq);
+}
+
+/*
+ * most_irq_handler - Interrupt Service Routine
+ * @irq: irq number
+ * @_dev: private data
+ *
+ * Schedules a delayed work
+ *
+ * By default the interrupt line behavior is Active Low. Once an interrupt is
+ * generated by the device, until driver clears the interrupt (by reading
+ * the PMP message), device keeps the interrupt line in low state. Since i2c
+ * read is done in work queue, the interrupt line must be disabled temporarily
+ * to avoid ISR being called repeatedly. Re-enable the interrupt in workqueue,
+ * after reading the message.
+ *
+ * Note: If we use the interrupt line in Falling edge mode, there is a
+ * possibility to miss interrupts when ISR is getting executed.
+ *
+ */
+static irqreturn_t most_irq_handler(int irq, void *_dev)
+{
+ struct hdm_i2c *dev = _dev;
+
+ disable_irq_nosync(irq);
+
+ schedule_delayed_work(&dev->rx.dwork, 0);
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * i2c_probe - i2c probe handler
+ * @client: i2c client device structure
+ * @id: i2c client device id
+ *
+ * Return 0 on success, negative on failure.
+ *
+ * Register the i2c client device as a MOST interface
+ */
+static int i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+ struct hdm_i2c *dev;
+ int ret, i;
+ struct kobject *kobj;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ /* ID format: i2c-<bus>-<address> */
+ snprintf(dev->name, sizeof(dev->name), "i2c-%d-%04x",
+ client->adapter->nr, client->addr);
+
+ for (i = 0; i < NUM_CHANNELS; i++) {
+ dev->is_open[i] = false;
+ dev->capabilities[i].data_type = MOST_CH_CONTROL;
+ dev->capabilities[i].num_buffers_packet = MAX_BUFFERS_CONTROL;
+ dev->capabilities[i].buffer_size_packet = MAX_BUF_SIZE_CONTROL;
+ }
+ dev->capabilities[CH_RX].direction = MOST_CH_RX;
+ dev->capabilities[CH_RX].name_suffix = "rx";
+ dev->capabilities[CH_TX].direction = MOST_CH_TX;
+ dev->capabilities[CH_TX].name_suffix = "tx";
+
+ dev->most_iface.interface = ITYPE_I2C;
+ dev->most_iface.description = dev->name;
+ dev->most_iface.num_channels = NUM_CHANNELS;
+ dev->most_iface.channel_vector = dev->capabilities;
+ dev->most_iface.configure = configure_channel;
+ dev->most_iface.enqueue = enqueue;
+ dev->most_iface.poison_channel = poison_channel;
+ dev->most_iface.request_netinfo = request_netinfo;
+
+ INIT_LIST_HEAD(&dev->rx.list);
+ mutex_init(&dev->rx.list_mutex);
+ init_waitqueue_head(&dev->rx.waitq);
+
+ INIT_DELAYED_WORK(&dev->rx.dwork, pending_rx_work);
+
+ dev->client = client;
+ i2c_set_clientdata(client, dev);
+
+ kobj = most_register_interface(&dev->most_iface);
+ if (IS_ERR(kobj)) {
+ pr_err("Failed to register i2c as a MOST interface\n");
+ kfree(dev);
+ return PTR_ERR(kobj);
+ }
+
+ dev->polling_mode = polling_req || client->irq <= 0;
+ if (!dev->polling_mode) {
+ pr_info("Requesting IRQ: %d\n", client->irq);
+ ret = request_irq(client->irq, most_irq_handler, IRQF_SHARED,
+ client->name, dev);
+ if (ret) {
+ pr_info("IRQ request failed: %d, "
+ "falling back to polling\n", ret);
+ dev->polling_mode = true;
+ }
+ }
+
+ if (dev->polling_mode)
+ pr_info("Using polling at rate: %d times/sec\n", scan_rate);
+
+ return 0;
+}
+
+/*
+ * i2c_remove - i2c remove handler
+ * @client: i2c client device structure
+ *
+ * Return 0 on success.
+ *
+ * Unregister the i2c client device as a MOST interface
+ */
+static int i2c_remove(struct i2c_client *client)
+{
+ struct hdm_i2c *dev = i2c_get_clientdata(client);
+ int i;
+
+ if (!dev->polling_mode)
+ free_irq(client->irq, dev);
+
+ most_deregister_interface(&dev->most_iface);
+
+ for (i = 0 ; i < NUM_CHANNELS; i++)
+ if (dev->is_open[i])
+ poison_channel(&dev->most_iface, i);
+ cancel_delayed_work_sync(&dev->rx.dwork);
+ kfree(dev);
+
+ return 0;
+}
+
+static const struct i2c_device_id i2c_id[] = {
+ { "most_i2c", 0 },
+ { }, /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(i2c, i2c_id);
+
+static struct i2c_driver i2c_driver = {
+ .driver = {
+ .name = "hdm_i2c",
+ .owner = THIS_MODULE,
+ },
+ .probe = i2c_probe,
+ .remove = i2c_remove,
+ .id_table = i2c_id,
+};
+
+/**
+ * hdm_i2c_init - Driver Registration Routine
+ */
+static int __init hdm_i2c_init(void)
+{
+ pr_info("hdm_i2c_init()\n");
+
+ return i2c_add_driver(&i2c_driver);
+}
+
+/**
+ * hdm_i2c_exit - Driver Cleanup Routine
+ **/
+static void __exit hdm_i2c_exit(void)
+{
+ i2c_del_driver(&i2c_driver);
+ pr_info("hdm_i2c_exit()\n");
+}
+
+module_init(hdm_i2c_init);
+module_exit(hdm_i2c_exit);
+
+MODULE_AUTHOR("Jain Roy Ambi <JainRoy.Ambi@microchip.com>");
+MODULE_AUTHOR("Andrey Shvetsov <andrey.shvetsov@k2l.de>");
+MODULE_DESCRIPTION("I2C Hardware Dependent Module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/staging/most/hdm-usb/Kconfig b/drivers/staging/most/hdm-usb/Kconfig
new file mode 100644
index 0000000..a482c3f
--- /dev/null
+++ b/drivers/staging/most/hdm-usb/Kconfig
@@ -0,0 +1,14 @@
+#
+# MOST USB configuration
+#
+
+config HDM_USB
+ tristate "USB HDM"
+ depends on USB
+ select AIM_NETWORK
+ ---help---
+ Say Y here if you want to connect via USB to network tranceiver.
+ This device driver depends on the networking AIM.
+
+ To compile this driver as a module, choose M here: the
+ module will be called hdm_usb.
diff --git a/drivers/staging/most/hdm-usb/Makefile b/drivers/staging/most/hdm-usb/Makefile
new file mode 100644
index 0000000..6bbacb4
--- /dev/null
+++ b/drivers/staging/most/hdm-usb/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_HDM_USB) += hdm_usb.o
+
+ccflags-y += -Idrivers/staging/most/mostcore/
+ccflags-y += -Idrivers/staging/most/aim-network/
diff --git a/drivers/staging/most/hdm-usb/hdm_usb.c b/drivers/staging/most/hdm-usb/hdm_usb.c
new file mode 100644
index 0000000..305303f
--- /dev/null
+++ b/drivers/staging/most/hdm-usb/hdm_usb.c
@@ -0,0 +1,1454 @@
+/*
+ * hdm_usb.c - Hardware dependent module for USB
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/usb.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/sysfs.h>
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/uaccess.h>
+#include "mostcore.h"
+#include "networking.h"
+
+#define USB_MTU 512
+#define NO_ISOCHRONOUS_URB 0
+#define AV_PACKETS_PER_XACT 2
+#define BUF_CHAIN_SIZE 0xFFFF
+#define MAX_NUM_ENDPOINTS 30
+#define MAX_SUFFIX_LEN 10
+#define MAX_STRING_LEN 80
+#define MAX_BUF_SIZE 0xFFFF
+#define CEILING(x, y) (((x) + (y) - 1) / (y))
+
+#define USB_VENDOR_ID_SMSC 0x0424 /* VID: SMSC */
+#define USB_DEV_ID_BRDG 0xC001 /* PID: USB Bridge */
+#define USB_DEV_ID_INIC 0xCF18 /* PID: USB INIC */
+#define HW_RESYNC 0x0000
+/* DRCI Addresses */
+#define DRCI_REG_NI_STATE 0x0100
+#define DRCI_REG_PACKET_BW 0x0101
+#define DRCI_REG_NODE_ADDR 0x0102
+#define DRCI_REG_NODE_POS 0x0103
+#define DRCI_REG_MEP_FILTER 0x0140
+#define DRCI_REG_HASH_TBL0 0x0141
+#define DRCI_REG_HASH_TBL1 0x0142
+#define DRCI_REG_HASH_TBL2 0x0143
+#define DRCI_REG_HASH_TBL3 0x0144
+#define DRCI_REG_HW_ADDR_HI 0x0145
+#define DRCI_REG_HW_ADDR_MI 0x0146
+#define DRCI_REG_HW_ADDR_LO 0x0147
+#define DRCI_READ_REQ 0xA0
+#define DRCI_WRITE_REQ 0xA1
+
+/**
+ * struct buf_anchor - used to create a list of pending URBs
+ * @urb: pointer to USB request block
+ * @clear_work_obj:
+ * @list: linked list
+ * @urb_completion:
+ */
+struct buf_anchor {
+ struct urb *urb;
+ struct work_struct clear_work_obj;
+ struct list_head list;
+ struct completion urb_compl;
+};
+#define to_buf_anchor(w) container_of(w, struct buf_anchor, clear_work_obj)
+
+/**
+ * struct most_dci_obj - Direct Communication Interface
+ * @kobj:position in sysfs
+ * @usb_device: pointer to the usb device
+ */
+struct most_dci_obj {
+ struct kobject kobj;
+ struct usb_device *usb_device;
+};
+#define to_dci_obj(p) container_of(p, struct most_dci_obj, kobj)
+
+/**
+ * struct most_dev - holds all usb interface specific stuff
+ * @parent: parent object in sysfs
+ * @usb_device: pointer to usb device
+ * @iface: hardware interface
+ * @cap: channel capabilities
+ * @conf: channel configuration
+ * @dci: direct communication interface of hardware
+ * @hw_addr: MAC address of hardware
+ * @ep_address: endpoint address table
+ * @link_stat: link status of hardware
+ * @description: device description
+ * @suffix: suffix for channel name
+ * @anchor_list_lock: locks list access
+ * @padding_active: indicates channel uses padding
+ * @is_channel_healthy: health status table of each channel
+ * @anchor_list: list of anchored items
+ * @io_mutex: synchronize I/O with disconnect
+ * @link_stat_timer: timer for link status reports
+ * @poll_work_obj: work for polling link status
+ */
+struct most_dev {
+ struct kobject *parent;
+ struct usb_device *usb_device;
+ struct most_interface iface;
+ struct most_channel_capability *cap;
+ struct most_channel_config *conf;
+ struct most_dci_obj *dci;
+ u8 hw_addr[6];
+ u8 *ep_address;
+ u16 link_stat;
+ char description[MAX_STRING_LEN];
+ char suffix[MAX_NUM_ENDPOINTS][MAX_SUFFIX_LEN];
+ spinlock_t anchor_list_lock[MAX_NUM_ENDPOINTS];
+ bool padding_active[MAX_NUM_ENDPOINTS];
+ bool is_channel_healthy[MAX_NUM_ENDPOINTS];
+ struct list_head *anchor_list;
+ struct mutex io_mutex;
+ struct timer_list link_stat_timer;
+ struct work_struct poll_work_obj;
+};
+#define to_mdev(d) container_of(d, struct most_dev, iface)
+#define to_mdev_from_work(w) container_of(w, struct most_dev, poll_work_obj)
+
+static struct workqueue_struct *schedule_usb_work;
+static void wq_clear_halt(struct work_struct *wq_obj);
+static void wq_netinfo(struct work_struct *wq_obj);
+
+/**
+ * trigger_resync_vr - Vendor request to trigger HW re-sync mechanism
+ * @dev: usb device
+ *
+ */
+static void trigger_resync_vr(struct usb_device *dev)
+{
+ int retval;
+ u8 request_type = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_ENDPOINT;
+ int *data = kzalloc(sizeof(*data), GFP_KERNEL);
+
+ if (!data)
+ goto error;
+ *data = HW_RESYNC;
+ retval = usb_control_msg(dev,
+ usb_sndctrlpipe(dev, 0),
+ 0,
+ request_type,
+ 0,
+ 0,
+ data,
+ 0,
+ 5 * HZ);
+ kfree(data);
+ if (retval >= 0)
+ return;
+error:
+ dev_err(&dev->dev, "Vendor request \"stall\" failed\n");
+}
+
+/**
+ * drci_rd_reg - read a DCI register
+ * @dev: usb device
+ * @reg: register address
+ * @buf: buffer to store data
+ *
+ * This is reads data from INIC's direct register communication interface
+ */
+static inline int drci_rd_reg(struct usb_device *dev, u16 reg, void *buf)
+{
+ return usb_control_msg(dev,
+ usb_rcvctrlpipe(dev, 0),
+ DRCI_READ_REQ,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0000,
+ reg,
+ buf,
+ 2,
+ 5 * HZ);
+}
+
+/**
+ * drci_wr_reg - write a DCI register
+ * @dev: usb device
+ * @reg: register address
+ * @data: data to write
+ *
+ * This is writes data to INIC's direct register communication interface
+ */
+static inline int drci_wr_reg(struct usb_device *dev, u16 reg, u16 data)
+{
+ return usb_control_msg(dev,
+ usb_sndctrlpipe(dev, 0),
+ DRCI_WRITE_REQ,
+ USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ data,
+ reg,
+ NULL,
+ 0,
+ 5 * HZ);
+}
+
+/**
+ * free_anchored_buffers - free device's anchored items
+ * @mdev: the device
+ * @channel: channel ID
+ */
+static void free_anchored_buffers(struct most_dev *mdev, unsigned int channel)
+{
+ struct mbo *mbo;
+ struct buf_anchor *anchor, *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+ list_for_each_entry_safe(anchor, tmp, &mdev->anchor_list[channel], list) {
+ struct urb *urb = anchor->urb;
+
+ spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+ if (likely(urb)) {
+ mbo = urb->context;
+ if (!irqs_disabled()) {
+ usb_kill_urb(urb);
+ } else {
+ usb_unlink_urb(urb);
+ wait_for_completion(&anchor->urb_compl);
+ }
+ if ((mbo) && (mbo->complete)) {
+ mbo->status = MBO_E_CLOSE;
+ mbo->processed_length = 0;
+ mbo->complete(mbo);
+ }
+ usb_free_urb(urb);
+ }
+ spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+ list_del(&anchor->list);
+ kfree(anchor);
+ }
+ spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+}
+
+/**
+ * get_stream_frame_size - calculate frame size of current configuration
+ * @cfg: channel configuration
+ */
+static unsigned int get_stream_frame_size(struct most_channel_config *cfg)
+{
+ unsigned int frame_size = 0;
+ unsigned int sub_size = cfg->subbuffer_size;
+
+ if (!sub_size) {
+ pr_warn("Misconfig: Subbuffer size zero.\n");
+ return frame_size;
+ }
+ switch (cfg->data_type) {
+ case MOST_CH_ISOC_AVP:
+ frame_size = AV_PACKETS_PER_XACT * sub_size;
+ break;
+ case MOST_CH_SYNC:
+ if (cfg->packets_per_xact == 0) {
+ pr_warn("Misconfig: Packets per XACT zero\n");
+ frame_size = 0;
+ } else if (cfg->packets_per_xact == 0xFF)
+ frame_size = (USB_MTU / sub_size) * sub_size;
+ else
+ frame_size = cfg->packets_per_xact * sub_size;
+ break;
+ default:
+ pr_warn("Query frame size of non-streaming channel\n");
+ break;
+ }
+ return frame_size;
+}
+
+/**
+ * hdm_poison_channel - mark buffers of this channel as invalid
+ * @iface: pointer to the interface
+ * @channel: channel ID
+ *
+ * This unlinks all URBs submitted to the HCD,
+ * calls the associated completion function of the core and removes
+ * them from the list.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+static int hdm_poison_channel(struct most_interface *iface, int channel)
+{
+ struct most_dev *mdev;
+
+ mdev = to_mdev(iface);
+ if (unlikely(!iface)) {
+ dev_warn(&mdev->usb_device->dev, "Poison: Bad interface.\n");
+ return -EIO;
+ }
+ if (unlikely((channel < 0) || (channel >= iface->num_channels))) {
+ dev_warn(&mdev->usb_device->dev, "Channel ID out of range.\n");
+ return -ECHRNG;
+ }
+
+ mdev->is_channel_healthy[channel] = false;
+
+ mutex_lock(&mdev->io_mutex);
+ free_anchored_buffers(mdev, channel);
+ if (mdev->padding_active[channel] == true)
+ mdev->padding_active[channel] = false;
+
+ if (mdev->conf[channel].data_type == MOST_CH_ASYNC) {
+ del_timer_sync(&mdev->link_stat_timer);
+ cancel_work_sync(&mdev->poll_work_obj);
+ }
+ mutex_unlock(&mdev->io_mutex);
+ return 0;
+}
+
+/**
+ * hdm_add_padding - add padding bytes
+ * @mdev: most device
+ * @channel: channel ID
+ * @mbo: buffer object
+ *
+ * This inserts the INIC hardware specific padding bytes into a streaming
+ * channel's buffer
+ */
+static int hdm_add_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
+{
+ struct most_channel_config *conf = &mdev->conf[channel];
+ unsigned int j, num_frames, frame_size;
+ u16 rd_addr, wr_addr;
+
+ frame_size = get_stream_frame_size(conf);
+ if (!frame_size)
+ return -EIO;
+ num_frames = mbo->buffer_length / frame_size;
+
+ if (num_frames < 1) {
+ dev_err(&mdev->usb_device->dev,
+ "Missed minimal transfer unit.\n");
+ return -EIO;
+ }
+
+ for (j = 1; j < num_frames; j++) {
+ wr_addr = (num_frames - j) * USB_MTU;
+ rd_addr = (num_frames - j) * frame_size;
+ memmove(mbo->virt_address + wr_addr,
+ mbo->virt_address + rd_addr,
+ frame_size);
+ }
+ mbo->buffer_length = num_frames * USB_MTU;
+ return 0;
+}
+
+/**
+ * hdm_remove_padding - remove padding bytes
+ * @mdev: most device
+ * @channel: channel ID
+ * @mbo: buffer object
+ *
+ * This takes the INIC hardware specific padding bytes off a streaming
+ * channel's buffer.
+ */
+static int hdm_remove_padding(struct most_dev *mdev, int channel, struct mbo *mbo)
+{
+ unsigned int j, num_frames, frame_size;
+ struct most_channel_config *const conf = &mdev->conf[channel];
+
+ frame_size = get_stream_frame_size(conf);
+ if (!frame_size)
+ return -EIO;
+ num_frames = mbo->processed_length / USB_MTU;
+
+ for (j = 1; j < num_frames; j++)
+ memmove(mbo->virt_address + frame_size * j,
+ mbo->virt_address + USB_MTU * j,
+ frame_size);
+
+ mbo->processed_length = frame_size * num_frames;
+ return 0;
+}
+
+/**
+ * hdm_write_completion - completion function for submitted Tx URBs
+ * @urb: the URB that has been completed
+ *
+ * This checks the status of the completed URB. In case the URB has been
+ * unlinked before, it is immediately freed. On any other error the MBO
+ * transfer flag is set. On success it frees allocated resources and calls
+ * the completion function.
+ *
+ * Context: interrupt!
+ */
+static void hdm_write_completion(struct urb *urb)
+{
+ struct mbo *mbo;
+ struct buf_anchor *anchor;
+ struct most_dev *mdev;
+ struct device *dev;
+ unsigned int channel;
+ unsigned long flags;
+
+ mbo = urb->context;
+ anchor = mbo->priv;
+ mdev = to_mdev(mbo->ifp);
+ channel = mbo->hdm_channel_id;
+ dev = &mdev->usb_device->dev;
+
+ if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) ||
+ (mdev->is_channel_healthy[channel] == false)) {
+ complete(&anchor->urb_compl);
+ return;
+ }
+
+ if (unlikely(urb->status && !(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))) {
+ mbo->processed_length = 0;
+ switch (urb->status) {
+ case -EPIPE:
+ dev_warn(dev, "Broken OUT pipe detected\n");
+ most_stop_enqueue(&mdev->iface, channel);
+ mbo->status = MBO_E_INVAL;
+ usb_unlink_urb(urb);
+ INIT_WORK(&anchor->clear_work_obj, wq_clear_halt);
+ queue_work(schedule_usb_work, &anchor->clear_work_obj);
+ return;
+ case -ENODEV:
+ case -EPROTO:
+ mbo->status = MBO_E_CLOSE;
+ break;
+ default:
+ mbo->status = MBO_E_INVAL;
+ break;
+ }
+ } else {
+ mbo->status = MBO_SUCCESS;
+ mbo->processed_length = urb->actual_length;
+ }
+
+ spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+ list_del(&anchor->list);
+ spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+ kfree(anchor);
+
+ if (likely(mbo->complete))
+ mbo->complete(mbo);
+ usb_free_urb(urb);
+}
+
+/**
+ * hdm_read_completion - completion funciton for submitted Rx URBs
+ * @urb: the URB that has been completed
+ *
+ * This checks the status of the completed URB. In case the URB has been
+ * unlinked before it is immediately freed. On any other error the MBO transfer
+ * flag is set. On success it frees allocated resources, removes
+ * padding bytes -if necessary- and calls the completion function.
+ *
+ * Context: interrupt!
+ *
+ * **************************************************************************
+ * Error codes returned by in urb->status
+ * or in iso_frame_desc[n].status (for ISO)
+ * *************************************************************************
+ *
+ * USB device drivers may only test urb status values in completion handlers.
+ * This is because otherwise there would be a race between HCDs updating
+ * these values on one CPU, and device drivers testing them on another CPU.
+ *
+ * A transfer's actual_length may be positive even when an error has been
+ * reported. That's because transfers often involve several packets, so that
+ * one or more packets could finish before an error stops further endpoint I/O.
+ *
+ * For isochronous URBs, the urb status value is non-zero only if the URB is
+ * unlinked, the device is removed, the host controller is disabled or the total
+ * transferred length is less than the requested length and the URB_SHORT_NOT_OK
+ * flag is set. Completion handlers for isochronous URBs should only see
+ * urb->status set to zero, -ENOENT, -ECONNRESET, -ESHUTDOWN, or -EREMOTEIO.
+ * Individual frame descriptor status fields may report more status codes.
+ *
+ *
+ * 0 Transfer completed successfully
+ *
+ * -ENOENT URB was synchronously unlinked by usb_unlink_urb
+ *
+ * -EINPROGRESS URB still pending, no results yet
+ * (That is, if drivers see this it's a bug.)
+ *
+ * -EPROTO (*, **) a) bitstuff error
+ * b) no response packet received within the
+ * prescribed bus turn-around time
+ * c) unknown USB error
+ *
+ * -EILSEQ (*, **) a) CRC mismatch
+ * b) no response packet received within the
+ * prescribed bus turn-around time
+ * c) unknown USB error
+ *
+ * Note that often the controller hardware does not
+ * distinguish among cases a), b), and c), so a
+ * driver cannot tell whether there was a protocol
+ * error, a failure to respond (often caused by
+ * device disconnect), or some other fault.
+ *
+ * -ETIME (**) No response packet received within the prescribed
+ * bus turn-around time. This error may instead be
+ * reported as -EPROTO or -EILSEQ.
+ *
+ * -ETIMEDOUT Synchronous USB message functions use this code
+ * to indicate timeout expired before the transfer
+ * completed, and no other error was reported by HC.
+ *
+ * -EPIPE (**) Endpoint stalled. For non-control endpoints,
+ * reset this status with usb_clear_halt().
+ *
+ * -ECOMM During an IN transfer, the host controller
+ * received data from an endpoint faster than it
+ * could be written to system memory
+ *
+ * -ENOSR During an OUT transfer, the host controller
+ * could not retrieve data from system memory fast
+ * enough to keep up with the USB data rate
+ *
+ * -EOVERFLOW (*) The amount of data returned by the endpoint was
+ * greater than either the max packet size of the
+ * endpoint or the remaining buffer size. "Babble".
+ *
+ * -EREMOTEIO The data read from the endpoint did not fill the
+ * specified buffer, and URB_SHORT_NOT_OK was set in
+ * urb->transfer_flags.
+ *
+ * -ENODEV Device was removed. Often preceded by a burst of
+ * other errors, since the hub driver doesn't detect
+ * device removal events immediately.
+ *
+ * -EXDEV ISO transfer only partially completed
+ * (only set in iso_frame_desc[n].status, not urb->status)
+ *
+ * -EINVAL ISO madness, if this happens: Log off and go home
+ *
+ * -ECONNRESET URB was asynchronously unlinked by usb_unlink_urb
+ *
+ * -ESHUTDOWN The device or host controller has been disabled due
+ * to some problem that could not be worked around,
+ * such as a physical disconnect.
+ *
+ *
+ * (*) Error codes like -EPROTO, -EILSEQ and -EOVERFLOW normally indicate
+ * hardware problems such as bad devices (including firmware) or cables.
+ *
+ * (**) This is also one of several codes that different kinds of host
+ * controller use to indicate a transfer has failed because of device
+ * disconnect. In the interval before the hub driver starts disconnect
+ * processing, devices may receive such fault reports for every request.
+ *
+ * See <https://www.kernel.org/doc/Documentation/usb/error-codes.txt>
+ */
+static void hdm_read_completion(struct urb *urb)
+{
+ struct mbo *mbo;
+ struct buf_anchor *anchor;
+ struct most_dev *mdev;
+ struct device *dev;
+ unsigned long flags;
+ unsigned int channel;
+ struct most_channel_config *conf;
+
+ mbo = urb->context;
+ anchor = mbo->priv;
+ mdev = to_mdev(mbo->ifp);
+ channel = mbo->hdm_channel_id;
+ dev = &mdev->usb_device->dev;
+
+ if ((urb->status == -ENOENT) || (urb->status == -ECONNRESET) ||
+ (mdev->is_channel_healthy[channel] == false)) {
+ complete(&anchor->urb_compl);
+ return;
+ }
+
+ conf = &mdev->conf[channel];
+
+ if (unlikely(urb->status && !(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))) {
+ mbo->processed_length = 0;
+ switch (urb->status) {
+ case -EPIPE:
+ dev_warn(dev, "Broken IN pipe detected\n");
+ mbo->status = MBO_E_INVAL;
+ usb_unlink_urb(urb);
+ INIT_WORK(&anchor->clear_work_obj, wq_clear_halt);
+ queue_work(schedule_usb_work, &anchor->clear_work_obj);
+ return;
+ case -ENODEV:
+ case -EPROTO:
+ mbo->status = MBO_E_CLOSE;
+ break;
+ case -EOVERFLOW:
+ dev_warn(dev, "Babble on IN pipe detected\n");
+ default:
+ mbo->status = MBO_E_INVAL;
+ break;
+ }
+ } else {
+ mbo->processed_length = urb->actual_length;
+ if (mdev->padding_active[channel] == false) {
+ mbo->status = MBO_SUCCESS;
+ } else {
+ if (hdm_remove_padding(mdev, channel, mbo)) {
+ mbo->processed_length = 0;
+ mbo->status = MBO_E_INVAL;
+ } else {
+ mbo->status = MBO_SUCCESS;
+ }
+ }
+ }
+ spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+ list_del(&anchor->list);
+ spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+ kfree(anchor);
+
+ if (likely(mbo->complete))
+ mbo->complete(mbo);
+ usb_free_urb(urb);
+}
+
+/**
+ * hdm_enqueue - receive a buffer to be used for data transfer
+ * @iface: interface to enqueue to
+ * @channel: ID of the channel
+ * @mbo: pointer to the buffer object
+ *
+ * This allocates a new URB and fills it according to the channel
+ * that is being used for transmission of data. Before the URB is
+ * submitted it is stored in the private anchor list.
+ *
+ * Returns 0 on success. On any error the URB is freed and a error code
+ * is returned.
+ *
+ * Context: Could in _some_ cases be interrupt!
+ */
+static int hdm_enqueue(struct most_interface *iface, int channel, struct mbo *mbo)
+{
+ struct most_dev *mdev;
+ struct buf_anchor *anchor;
+ struct most_channel_config *conf;
+ struct device *dev;
+ int retval = 0;
+ struct urb *urb;
+ unsigned long flags;
+ unsigned long length;
+ void *virt_address;
+
+ if (unlikely(!iface || !mbo))
+ return -EIO;
+ if (unlikely(iface->num_channels <= channel) || (channel < 0))
+ return -ECHRNG;
+
+ mdev = to_mdev(iface);
+ conf = &mdev->conf[channel];
+ dev = &mdev->usb_device->dev;
+
+ if (!mdev->usb_device)
+ return -ENODEV;
+
+ urb = usb_alloc_urb(NO_ISOCHRONOUS_URB, GFP_ATOMIC);
+ if (!urb) {
+ dev_err(dev, "Failed to allocate URB\n");
+ return -ENOMEM;
+ }
+
+ anchor = kzalloc(sizeof(*anchor), GFP_ATOMIC);
+ if (!anchor) {
+ retval = -ENOMEM;
+ goto _error;
+ }
+
+ anchor->urb = urb;
+ init_completion(&anchor->urb_compl);
+ mbo->priv = anchor;
+
+ spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+ list_add_tail(&anchor->list, &mdev->anchor_list[channel]);
+ spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+
+ if ((mdev->padding_active[channel] == true) &&
+ (conf->direction & MOST_CH_TX))
+ if (hdm_add_padding(mdev, channel, mbo)) {
+ retval = -EIO;
+ goto _error_1;
+ }
+
+ urb->transfer_dma = mbo->bus_address;
+ virt_address = mbo->virt_address;
+ length = mbo->buffer_length;
+
+ if (conf->direction & MOST_CH_TX) {
+ usb_fill_bulk_urb(urb, mdev->usb_device,
+ usb_sndbulkpipe(mdev->usb_device,
+ mdev->ep_address[channel]),
+ virt_address,
+ length,
+ hdm_write_completion,
+ mbo);
+ if (conf->data_type != MOST_CH_ISOC_AVP)
+ urb->transfer_flags |= URB_ZERO_PACKET;
+ } else {
+ usb_fill_bulk_urb(urb, mdev->usb_device,
+ usb_rcvbulkpipe(mdev->usb_device,
+ mdev->ep_address[channel]),
+ virt_address,
+ length,
+ hdm_read_completion,
+ mbo);
+ }
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(dev, "URB submit failed with error %d.\n", retval);
+ goto _error_1;
+ }
+ return 0;
+
+_error_1:
+ spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+ list_del(&anchor->list);
+ spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+ kfree(anchor);
+_error:
+ usb_free_urb(urb);
+ return retval;
+}
+
+/**
+ * hdm_configure_channel - receive channel configuration from core
+ * @iface: interface
+ * @channel: channel ID
+ * @conf: structure that holds the configuration information
+ */
+static int hdm_configure_channel(struct most_interface *iface, int channel,
+ struct most_channel_config *conf)
+{
+ unsigned int num_frames;
+ unsigned int frame_size;
+ unsigned int temp_size;
+ unsigned int tail_space;
+ struct most_dev *mdev;
+ struct device *dev;
+
+ mdev = to_mdev(iface);
+ mdev->is_channel_healthy[channel] = true;
+ dev = &mdev->usb_device->dev;
+
+ if (unlikely(!iface || !conf)) {
+ dev_err(dev, "Bad interface or config pointer.\n");
+ return -EINVAL;
+ }
+ if (unlikely((channel < 0) || (channel >= iface->num_channels))) {
+ dev_err(dev, "Channel ID out of range.\n");
+ return -EINVAL;
+ }
+ if ((!conf->num_buffers) || (!conf->buffer_size)) {
+ dev_err(dev, "Misconfig: buffer size or #buffers zero.\n");
+ return -EINVAL;
+ }
+
+ if (!(conf->data_type == MOST_CH_SYNC) &&
+ !((conf->data_type == MOST_CH_ISOC_AVP) &&
+ (conf->packets_per_xact != 0xFF))) {
+ mdev->padding_active[channel] = false;
+ goto exit;
+ }
+
+ mdev->padding_active[channel] = true;
+ temp_size = conf->buffer_size;
+
+ if ((conf->data_type != MOST_CH_SYNC) &&
+ (conf->data_type != MOST_CH_ISOC_AVP)) {
+ dev_warn(dev, "Unsupported data type\n");
+ return -EINVAL;
+ }
+
+ frame_size = get_stream_frame_size(conf);
+ if ((frame_size == 0) || (frame_size > USB_MTU)) {
+ dev_warn(dev, "Misconfig: frame size wrong\n");
+ return -EINVAL;
+ }
+
+ if (conf->buffer_size % frame_size) {
+ u16 tmp_val;
+
+ tmp_val = conf->buffer_size / frame_size;
+ conf->buffer_size = tmp_val * frame_size;
+ dev_notice(dev,
+ "Channel %d - rouding buffer size to %d bytes, "
+ "channel config says %d bytes\n",
+ channel,
+ conf->buffer_size,
+ temp_size);
+ }
+
+ num_frames = conf->buffer_size / frame_size;
+ tail_space = num_frames * (USB_MTU - frame_size);
+ temp_size += tail_space;
+
+ /* calculate extra length to comply w/ HW padding */
+ conf->extra_len = (CEILING(temp_size, USB_MTU) * USB_MTU)
+ - conf->buffer_size;
+exit:
+ mdev->conf[channel] = *conf;
+ return 0;
+}
+
+/**
+ * hdm_update_netinfo - retrieve latest networking information
+ * @mdev: device interface
+ *
+ * This triggers the USB vendor requests to read the hardware address and
+ * the current link status of the attached device.
+ */
+static int hdm_update_netinfo(struct most_dev *mdev)
+{
+ struct device *dev = &mdev->usb_device->dev;
+ int i;
+ u16 link;
+ u8 addr[6];
+
+ if (!is_valid_ether_addr(mdev->hw_addr)) {
+ if (0 > drci_rd_reg(mdev->usb_device,
+ DRCI_REG_HW_ADDR_HI, addr)) {
+ dev_err(dev, "Vendor request \"hw_addr_hi\" failed\n");
+ return -1;
+ }
+ if (0 > drci_rd_reg(mdev->usb_device,
+ DRCI_REG_HW_ADDR_MI, addr + 2)) {
+ dev_err(dev, "Vendor request \"hw_addr_mid\" failed\n");
+ return -1;
+ }
+ if (0 > drci_rd_reg(mdev->usb_device,
+ DRCI_REG_HW_ADDR_LO, addr + 4)) {
+ dev_err(dev, "Vendor request \"hw_addr_low\" failed\n");
+ return -1;
+ }
+ mutex_lock(&mdev->io_mutex);
+ for (i = 0; i < 6; i++)
+ mdev->hw_addr[i] = addr[i];
+ mutex_unlock(&mdev->io_mutex);
+
+ }
+ if (0 > drci_rd_reg(mdev->usb_device, DRCI_REG_NI_STATE, &link)) {
+ dev_err(dev, "Vendor request \"link status\" failed\n");
+ return -1;
+ }
+ le16_to_cpus(&link);
+ mutex_lock(&mdev->io_mutex);
+ mdev->link_stat = link;
+ mutex_unlock(&mdev->io_mutex);
+ return 0;
+}
+
+/**
+ * hdm_request_netinfo - request network information
+ * @iface: pointer to interface
+ * @channel: channel ID
+ *
+ * This is used as trigger to set up the link status timer that
+ * polls for the NI state of the INIC every 2 seconds.
+ *
+ */
+static void hdm_request_netinfo(struct most_interface *iface, int channel)
+{
+ struct most_dev *mdev;
+
+ BUG_ON(!iface);
+ mdev = to_mdev(iface);
+ mdev->link_stat_timer.expires = jiffies + HZ;
+ mod_timer(&mdev->link_stat_timer, mdev->link_stat_timer.expires);
+}
+
+/**
+ * link_stat_timer_handler - add work to link_stat work queue
+ * @data: pointer to USB device instance
+ *
+ * The handler runs in interrupt context. That's why we need to defer the
+ * tasks to a work queue.
+ */
+static void link_stat_timer_handler(unsigned long data)
+{
+ struct most_dev *mdev = (struct most_dev *)data;
+
+ queue_work(schedule_usb_work, &mdev->poll_work_obj);
+ mdev->link_stat_timer.expires = jiffies + (2 * HZ);
+ add_timer(&mdev->link_stat_timer);
+}
+
+/**
+ * wq_netinfo - work queue function
+ * @wq_obj: object that holds data for our deferred work to do
+ *
+ * This retrieves the network interface status of the USB INIC
+ * and compares it with the current status. If the status has
+ * changed, it updates the status of the core.
+ */
+static void wq_netinfo(struct work_struct *wq_obj)
+{
+ struct most_dev *mdev;
+ int i, prev_link_stat;
+ u8 prev_hw_addr[6];
+
+ mdev = to_mdev_from_work(wq_obj);
+ prev_link_stat = mdev->link_stat;
+
+ for (i = 0; i < 6; i++)
+ prev_hw_addr[i] = mdev->hw_addr[i];
+
+ if (0 > hdm_update_netinfo(mdev))
+ return;
+ if ((prev_link_stat != mdev->link_stat) ||
+ (prev_hw_addr[0] != mdev->hw_addr[0]) ||
+ (prev_hw_addr[1] != mdev->hw_addr[1]) ||
+ (prev_hw_addr[2] != mdev->hw_addr[2]) ||
+ (prev_hw_addr[3] != mdev->hw_addr[3]) ||
+ (prev_hw_addr[4] != mdev->hw_addr[4]) ||
+ (prev_hw_addr[5] != mdev->hw_addr[5]))
+ most_deliver_netinfo(&mdev->iface, mdev->link_stat,
+ &mdev->hw_addr[0]);
+}
+
+/**
+ * wq_clear_halt - work queue function
+ * @wq_obj: work_struct object to execute
+ *
+ * This sends a clear_halt to the given USB pipe.
+ */
+static void wq_clear_halt(struct work_struct *wq_obj)
+{
+ struct buf_anchor *anchor;
+ struct most_dev *mdev;
+ struct mbo *mbo;
+ struct urb *urb;
+ unsigned int channel;
+ unsigned long flags;
+
+ anchor = to_buf_anchor(wq_obj);
+ urb = anchor->urb;
+ mbo = urb->context;
+ mdev = to_mdev(mbo->ifp);
+ channel = mbo->hdm_channel_id;
+
+ if (usb_clear_halt(urb->dev, urb->pipe))
+ dev_warn(&mdev->usb_device->dev, "Failed to reset endpoint.\n");
+
+ usb_free_urb(urb);
+ spin_lock_irqsave(&mdev->anchor_list_lock[channel], flags);
+ list_del(&anchor->list);
+ spin_unlock_irqrestore(&mdev->anchor_list_lock[channel], flags);
+
+ if (likely(mbo->complete))
+ mbo->complete(mbo);
+ if (mdev->conf[channel].direction & MOST_CH_TX)
+ most_resume_enqueue(&mdev->iface, channel);
+
+ kfree(anchor);
+}
+
+/**
+ * hdm_usb_fops - file operation table for USB driver
+ */
+static const struct file_operations hdm_usb_fops = {
+ .owner = THIS_MODULE,
+};
+
+/**
+ * usb_device_id - ID table for HCD device probing
+ */
+static struct usb_device_id usbid[] = {
+ { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_BRDG), },
+ { USB_DEVICE(USB_VENDOR_ID_SMSC, USB_DEV_ID_INIC), },
+ { } /* Terminating entry */
+};
+
+#define MOST_DCI_RO_ATTR(_name) \
+ struct most_dci_attribute most_dci_attr_##_name = \
+ __ATTR(_name, S_IRUGO, show_value, NULL)
+
+#define MOST_DCI_ATTR(_name) \
+ struct most_dci_attribute most_dci_attr_##_name = \
+ __ATTR(_name, S_IRUGO | S_IWUSR, show_value, store_value)
+
+/**
+ * struct most_dci_attribute - to access the attributes of a dci object
+ * @attr: attributes of a dci object
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_dci_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct most_dci_obj *d,
+ struct most_dci_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct most_dci_obj *d,
+ struct most_dci_attribute *attr,
+ const char *buf,
+ size_t count);
+};
+#define to_dci_attr(a) container_of(a, struct most_dci_attribute, attr)
+
+
+/**
+ * dci_attr_show - show function for dci object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t dci_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct most_dci_attribute *dci_attr = to_dci_attr(attr);
+ struct most_dci_obj *dci_obj = to_dci_obj(kobj);
+
+ if (!dci_attr->show)
+ return -EIO;
+
+ return dci_attr->show(dci_obj, dci_attr, buf);
+}
+
+/**
+ * dci_attr_store - store function for dci object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t dci_attr_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct most_dci_attribute *dci_attr = to_dci_attr(attr);
+ struct most_dci_obj *dci_obj = to_dci_obj(kobj);
+
+ if (!dci_attr->store)
+ return -EIO;
+
+ return dci_attr->store(dci_obj, dci_attr, buf, len);
+}
+
+static const struct sysfs_ops most_dci_sysfs_ops = {
+ .show = dci_attr_show,
+ .store = dci_attr_store,
+};
+
+/**
+ * most_dci_release - release function for dci object
+ * @kobj: pointer to kobject
+ *
+ * This frees the memory allocated for the dci object
+ */
+static void most_dci_release(struct kobject *kobj)
+{
+ struct most_dci_obj *dci_obj = to_dci_obj(kobj);
+
+ kfree(dci_obj);
+}
+
+static ssize_t show_value(struct most_dci_obj *dci_obj,
+ struct most_dci_attribute *attr, char *buf)
+{
+ u16 tmp_val;
+ u16 reg_addr;
+ int err;
+
+ if (!strcmp(attr->attr.name, "ni_state"))
+ reg_addr = DRCI_REG_NI_STATE;
+ else if (!strcmp(attr->attr.name, "packet_bandwidth"))
+ reg_addr = DRCI_REG_PACKET_BW;
+ else if (!strcmp(attr->attr.name, "node_address"))
+ reg_addr = DRCI_REG_NODE_ADDR;
+ else if (!strcmp(attr->attr.name, "node_position"))
+ reg_addr = DRCI_REG_NODE_POS;
+ else if (!strcmp(attr->attr.name, "mep_filter"))
+ reg_addr = DRCI_REG_MEP_FILTER;
+ else if (!strcmp(attr->attr.name, "mep_hash0"))
+ reg_addr = DRCI_REG_HASH_TBL0;
+ else if (!strcmp(attr->attr.name, "mep_hash1"))
+ reg_addr = DRCI_REG_HASH_TBL1;
+ else if (!strcmp(attr->attr.name, "mep_hash2"))
+ reg_addr = DRCI_REG_HASH_TBL2;
+ else if (!strcmp(attr->attr.name, "mep_hash3"))
+ reg_addr = DRCI_REG_HASH_TBL3;
+ else if (!strcmp(attr->attr.name, "mep_eui48_hi"))
+ reg_addr = DRCI_REG_HW_ADDR_HI;
+ else if (!strcmp(attr->attr.name, "mep_eui48_mi"))
+ reg_addr = DRCI_REG_HW_ADDR_MI;
+ else if (!strcmp(attr->attr.name, "mep_eui48_lo"))
+ reg_addr = DRCI_REG_HW_ADDR_LO;
+ else
+ return -EIO;
+
+ err = drci_rd_reg(dci_obj->usb_device, reg_addr, &tmp_val);
+ if (err < 0)
+ return err;
+
+ return snprintf(buf, PAGE_SIZE, "%04x\n", le16_to_cpu(tmp_val));
+}
+
+static ssize_t store_value(struct most_dci_obj *dci_obj,
+ struct most_dci_attribute *attr,
+ const char *buf, size_t count)
+{
+ u16 v16;
+ u16 reg_addr;
+ int err;
+
+ if (!strcmp(attr->attr.name, "mep_filter"))
+ reg_addr = DRCI_REG_MEP_FILTER;
+ else if (!strcmp(attr->attr.name, "mep_hash0"))
+ reg_addr = DRCI_REG_HASH_TBL0;
+ else if (!strcmp(attr->attr.name, "mep_hash1"))
+ reg_addr = DRCI_REG_HASH_TBL1;
+ else if (!strcmp(attr->attr.name, "mep_hash2"))
+ reg_addr = DRCI_REG_HASH_TBL2;
+ else if (!strcmp(attr->attr.name, "mep_hash3"))
+ reg_addr = DRCI_REG_HASH_TBL3;
+ else if (!strcmp(attr->attr.name, "mep_eui48_hi"))
+ reg_addr = DRCI_REG_HW_ADDR_HI;
+ else if (!strcmp(attr->attr.name, "mep_eui48_mi"))
+ reg_addr = DRCI_REG_HW_ADDR_MI;
+ else if (!strcmp(attr->attr.name, "mep_eui48_lo"))
+ reg_addr = DRCI_REG_HW_ADDR_LO;
+ else
+ return -EIO;
+
+ err = kstrtou16(buf, 16, &v16);
+ if (err)
+ return err;
+
+ err = drci_wr_reg(dci_obj->usb_device, reg_addr, cpu_to_le16(v16));
+ if (err < 0)
+ return err;
+
+ return count;
+}
+
+static MOST_DCI_RO_ATTR(ni_state);
+static MOST_DCI_RO_ATTR(packet_bandwidth);
+static MOST_DCI_RO_ATTR(node_address);
+static MOST_DCI_RO_ATTR(node_position);
+static MOST_DCI_ATTR(mep_filter);
+static MOST_DCI_ATTR(mep_hash0);
+static MOST_DCI_ATTR(mep_hash1);
+static MOST_DCI_ATTR(mep_hash2);
+static MOST_DCI_ATTR(mep_hash3);
+static MOST_DCI_ATTR(mep_eui48_hi);
+static MOST_DCI_ATTR(mep_eui48_mi);
+static MOST_DCI_ATTR(mep_eui48_lo);
+
+/**
+ * most_dci_def_attrs - array of default attribute files of the dci object
+ */
+static struct attribute *most_dci_def_attrs[] = {
+ &most_dci_attr_ni_state.attr,
+ &most_dci_attr_packet_bandwidth.attr,
+ &most_dci_attr_node_address.attr,
+ &most_dci_attr_node_position.attr,
+ &most_dci_attr_mep_filter.attr,
+ &most_dci_attr_mep_hash0.attr,
+ &most_dci_attr_mep_hash1.attr,
+ &most_dci_attr_mep_hash2.attr,
+ &most_dci_attr_mep_hash3.attr,
+ &most_dci_attr_mep_eui48_hi.attr,
+ &most_dci_attr_mep_eui48_mi.attr,
+ &most_dci_attr_mep_eui48_lo.attr,
+ NULL,
+};
+
+/**
+ * DCI ktype
+ */
+static struct kobj_type most_dci_ktype = {
+ .sysfs_ops = &most_dci_sysfs_ops,
+ .release = most_dci_release,
+ .default_attrs = most_dci_def_attrs,
+};
+
+/**
+ * create_most_dci_obj - allocates a dci object
+ * @parent: parent kobject
+ *
+ * This creates a dci object and registers it with sysfs.
+ * Returns a pointer to the object or NULL when something went wrong.
+ */
+static struct
+most_dci_obj *create_most_dci_obj(struct kobject *parent)
+{
+ struct most_dci_obj *most_dci;
+ int retval;
+
+ most_dci = kzalloc(sizeof(*most_dci), GFP_KERNEL);
+ if (!most_dci)
+ return NULL;
+
+ retval = kobject_init_and_add(&most_dci->kobj, &most_dci_ktype, parent,
+ "dci");
+ if (retval) {
+ kobject_put(&most_dci->kobj);
+ return NULL;
+ }
+ return most_dci;
+}
+
+/**
+ * destroy_most_dci_obj - DCI object release function
+ * @p: pointer to dci object
+ */
+static void destroy_most_dci_obj(struct most_dci_obj *p)
+{
+ kobject_put(&p->kobj);
+}
+
+/**
+ * hdm_probe - probe function of USB device driver
+ * @interface: Interface of the attached USB device
+ * @id: Pointer to the USB ID table.
+ *
+ * This allocates and initializes the device instance, adds the new
+ * entry to the internal list, scans the USB descriptors and registers
+ * the interface with the core.
+ * Additionally, the DCI objects are created and the hardware is sync'd.
+ *
+ * Return 0 on success. In case of an error a negative number is returned.
+ */
+static int
+hdm_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+ unsigned int i;
+ unsigned int num_endpoints;
+ struct most_channel_capability *tmp_cap;
+ struct most_dev *mdev;
+ struct usb_device *usb_dev;
+ struct device *dev;
+ struct usb_host_interface *usb_iface_desc;
+ struct usb_endpoint_descriptor *ep_desc;
+ int ret = 0;
+
+ usb_iface_desc = interface->cur_altsetting;
+ usb_dev = interface_to_usbdev(interface);
+ dev = &usb_dev->dev;
+ mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
+ if (!mdev)
+ goto exit_ENOMEM;
+
+ usb_set_intfdata(interface, mdev);
+ num_endpoints = usb_iface_desc->desc.bNumEndpoints;
+ mutex_init(&mdev->io_mutex);
+ INIT_WORK(&mdev->poll_work_obj, wq_netinfo);
+ init_timer(&mdev->link_stat_timer);
+
+ mdev->usb_device = usb_dev;
+ mdev->link_stat_timer.function = link_stat_timer_handler;
+ mdev->link_stat_timer.data = (unsigned long)mdev;
+ mdev->link_stat_timer.expires = jiffies + (2 * HZ);
+
+ mdev->iface.mod = hdm_usb_fops.owner;
+ mdev->iface.interface = ITYPE_USB;
+ mdev->iface.configure = hdm_configure_channel;
+ mdev->iface.request_netinfo = hdm_request_netinfo;
+ mdev->iface.enqueue = hdm_enqueue;
+ mdev->iface.poison_channel = hdm_poison_channel;
+ mdev->iface.description = mdev->description;
+ mdev->iface.num_channels = num_endpoints;
+
+ snprintf(mdev->description, sizeof(mdev->description),
+ "usb_device %d-%s:%d.%d",
+ usb_dev->bus->busnum,
+ usb_dev->devpath,
+ usb_dev->config->desc.bConfigurationValue,
+ usb_iface_desc->desc.bInterfaceNumber);
+
+ mdev->conf = kcalloc(num_endpoints, sizeof(*mdev->conf), GFP_KERNEL);
+ if (!mdev->conf)
+ goto exit_free;
+
+ mdev->cap = kcalloc(num_endpoints, sizeof(*mdev->cap), GFP_KERNEL);
+ if (!mdev->cap)
+ goto exit_free1;
+
+ mdev->iface.channel_vector = mdev->cap;
+ mdev->iface.priv = NULL;
+
+ mdev->ep_address =
+ kcalloc(num_endpoints, sizeof(*mdev->ep_address), GFP_KERNEL);
+ if (!mdev->ep_address)
+ goto exit_free2;
+
+ mdev->anchor_list =
+ kcalloc(num_endpoints, sizeof(*mdev->anchor_list), GFP_KERNEL);
+ if (!mdev->anchor_list)
+ goto exit_free3;
+
+ tmp_cap = mdev->cap;
+ for (i = 0; i < num_endpoints; i++) {
+ ep_desc = &usb_iface_desc->endpoint[i].desc;
+ mdev->ep_address[i] = ep_desc->bEndpointAddress;
+ mdev->padding_active[i] = false;
+ mdev->is_channel_healthy[i] = true;
+
+ snprintf(&mdev->suffix[i][0], MAX_SUFFIX_LEN, "ep%02x",
+ mdev->ep_address[i]);
+
+ tmp_cap->name_suffix = &mdev->suffix[i][0];
+ tmp_cap->buffer_size_packet = MAX_BUF_SIZE;
+ tmp_cap->buffer_size_streaming = MAX_BUF_SIZE;
+ tmp_cap->num_buffers_packet = BUF_CHAIN_SIZE;
+ tmp_cap->num_buffers_streaming = BUF_CHAIN_SIZE;
+ tmp_cap->data_type = MOST_CH_CONTROL | MOST_CH_ASYNC |
+ MOST_CH_ISOC_AVP | MOST_CH_SYNC;
+ if (ep_desc->bEndpointAddress & USB_DIR_IN)
+ tmp_cap->direction = MOST_CH_RX;
+ else
+ tmp_cap->direction = MOST_CH_TX;
+ tmp_cap++;
+ INIT_LIST_HEAD(&mdev->anchor_list[i]);
+ spin_lock_init(&mdev->anchor_list_lock[i]);
+ }
+ dev_notice(dev, "claimed gadget: Vendor=%4.4x ProdID=%4.4x Bus=%02x Device=%02x\n",
+ le16_to_cpu(usb_dev->descriptor.idVendor),
+ le16_to_cpu(usb_dev->descriptor.idProduct),
+ usb_dev->bus->busnum,
+ usb_dev->devnum);
+
+ dev_notice(dev, "device path: /sys/bus/usb/devices/%d-%s:%d.%d\n",
+ usb_dev->bus->busnum,
+ usb_dev->devpath,
+ usb_dev->config->desc.bConfigurationValue,
+ usb_iface_desc->desc.bInterfaceNumber);
+
+ mdev->parent = most_register_interface(&mdev->iface);
+ if (IS_ERR(mdev->parent)) {
+ ret = PTR_ERR(mdev->parent);
+ goto exit_free4;
+ }
+
+ mutex_lock(&mdev->io_mutex);
+ if (le16_to_cpu(usb_dev->descriptor.idProduct) == USB_DEV_ID_INIC) {
+ /* this increments the reference count of the instance
+ * object of the core
+ */
+ mdev->dci = create_most_dci_obj(mdev->parent);
+ if (!mdev->dci) {
+ mutex_unlock(&mdev->io_mutex);
+ most_deregister_interface(&mdev->iface);
+ ret = -ENOMEM;
+ goto exit_free4;
+ }
+
+ kobject_uevent(&mdev->dci->kobj, KOBJ_ADD);
+ mdev->dci->usb_device = mdev->usb_device;
+ trigger_resync_vr(usb_dev);
+ }
+ mutex_unlock(&mdev->io_mutex);
+ return 0;
+
+exit_free4:
+ kfree(mdev->anchor_list);
+exit_free3:
+ kfree(mdev->ep_address);
+exit_free2:
+ kfree(mdev->cap);
+exit_free1:
+ kfree(mdev->conf);
+exit_free:
+ kfree(mdev);
+exit_ENOMEM:
+ if (ret == 0 || ret == -ENOMEM) {
+ ret = -ENOMEM;
+ dev_err(dev, "out of memory\n");
+ }
+ return ret;
+}
+
+/**
+ * hdm_disconnect - disconnect function of USB device driver
+ * @interface: Interface of the attached USB device
+ *
+ * This deregisters the interface with the core, removes the kernel timer
+ * and frees resources.
+ *
+ * Context: hub kernel thread
+ */
+static void hdm_disconnect(struct usb_interface *interface)
+{
+ struct most_dev *mdev;
+
+ mdev = usb_get_intfdata(interface);
+ mutex_lock(&mdev->io_mutex);
+ usb_set_intfdata(interface, NULL);
+ mdev->usb_device = NULL;
+ mutex_unlock(&mdev->io_mutex);
+
+ del_timer_sync(&mdev->link_stat_timer);
+ cancel_work_sync(&mdev->poll_work_obj);
+
+ destroy_most_dci_obj(mdev->dci);
+ most_deregister_interface(&mdev->iface);
+
+ kfree(mdev->anchor_list);
+ kfree(mdev->cap);
+ kfree(mdev->conf);
+ kfree(mdev->ep_address);
+ kfree(mdev);
+}
+
+static struct usb_driver hdm_usb = {
+ .name = "hdm_usb",
+ .id_table = usbid,
+ .probe = hdm_probe,
+ .disconnect = hdm_disconnect,
+};
+
+static int __init hdm_usb_init(void)
+{
+ pr_info("hdm_usb_init()\n");
+ if (usb_register(&hdm_usb)) {
+ pr_err("could not register hdm_usb driver\n");
+ return -EIO;
+ }
+ schedule_usb_work = create_workqueue("hdmu_work");
+ if (schedule_usb_work == NULL) {
+ pr_err("could not create workqueue\n");
+ usb_deregister(&hdm_usb);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void __exit hdm_usb_exit(void)
+{
+ pr_info("hdm_usb_exit()\n");
+ destroy_workqueue(schedule_usb_work);
+ usb_deregister(&hdm_usb);
+}
+
+module_init(hdm_usb_init);
+module_exit(hdm_usb_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("HDM_4_USB");
diff --git a/drivers/staging/most/mostcore/Kconfig b/drivers/staging/most/mostcore/Kconfig
new file mode 100644
index 0000000..38abf1b
--- /dev/null
+++ b/drivers/staging/most/mostcore/Kconfig
@@ -0,0 +1,13 @@
+#
+# MOSTCore configuration
+#
+
+config MOSTCORE
+ tristate "MOST Core"
+
+ ---help---
+ Say Y here if you want to enable MOST support.
+ This device driver needs at least an additional AIM and HDM to work.
+
+ To compile this driver as a module, choose M here: the
+ module will be called mostcore.
diff --git a/drivers/staging/most/mostcore/Makefile b/drivers/staging/most/mostcore/Makefile
new file mode 100644
index 0000000..a078f01
--- /dev/null
+++ b/drivers/staging/most/mostcore/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MOSTCORE) += mostcore.o
+
+mostcore-objs := core.o
diff --git a/drivers/staging/most/mostcore/core.c b/drivers/staging/most/mostcore/core.c
new file mode 100644
index 0000000..7bb16db
--- /dev/null
+++ b/drivers/staging/most/mostcore/core.c
@@ -0,0 +1,1932 @@
+/*
+ * core.c - Implementation of core module of MOST Linux driver stack
+ *
+ * Copyright (C) 2013-2015 Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/poll.h>
+#include <linux/wait.h>
+#include <linux/kobject.h>
+#include <linux/mutex.h>
+#include <linux/completion.h>
+#include <linux/sysfs.h>
+#include <linux/kthread.h>
+#include <linux/dma-mapping.h>
+#include <linux/idr.h>
+#include "mostcore.h"
+
+#define MAX_CHANNELS 64
+#define STRING_SIZE 80
+
+static struct class *most_class;
+static struct device *class_glue_dir;
+static struct ida mdev_id;
+static int modref;
+
+struct most_c_obj {
+ struct kobject kobj;
+ struct completion cleanup;
+ atomic_t mbo_ref;
+ atomic_t mbo_nq_level;
+ uint16_t channel_id;
+ bool is_poisoned;
+ bool is_started;
+ int is_starving;
+ struct most_interface *iface;
+ struct most_inst_obj *inst;
+ struct most_channel_config cfg;
+ bool keep_mbo;
+ bool enqueue_halt;
+ struct list_head fifo;
+ spinlock_t fifo_lock;
+ struct list_head halt_fifo;
+ struct list_head list;
+ struct most_aim *first_aim;
+ struct most_aim *second_aim;
+ struct list_head trash_fifo;
+ struct task_struct *hdm_enqueue_task;
+ struct mutex stop_task_mutex;
+ wait_queue_head_t hdm_fifo_wq;
+};
+#define to_c_obj(d) container_of(d, struct most_c_obj, kobj)
+
+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 kobject kobj;
+ struct list_head list;
+};
+#define to_inst_obj(d) container_of(d, struct most_inst_obj, kobj)
+
+/**
+ * list_pop_mbo - retrieves the first MBO of the list and removes it
+ * @ptr: the list head to grab the MBO from.
+ */
+#define list_pop_mbo(ptr) \
+({ \
+ struct mbo *_mbo = list_first_entry(ptr, struct mbo, list); \
+ list_del(&_mbo->list); \
+ _mbo; \
+})
+
+static struct mutex deregister_mutex;
+
+/* ___ ___
+ * ___C H A N N E L___
+ */
+
+/**
+ * struct most_c_attr - to access the attributes of a channel object
+ * @attr: attributes of a channel
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_c_attr {
+ struct attribute attr;
+ ssize_t (*show)(struct most_c_obj *d,
+ struct most_c_attr *attr,
+ char *buf);
+ ssize_t (*store)(struct most_c_obj *d,
+ struct most_c_attr *attr,
+ const char *buf,
+ size_t count);
+};
+#define to_channel_attr(a) container_of(a, struct most_c_attr, attr)
+
+#define MOST_CHNL_ATTR(_name, _mode, _show, _store) \
+ struct most_c_attr most_chnl_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+/**
+ * channel_attr_show - show function of channel object
+ * @kobj: pointer to its kobject
+ * @attr: pointer to its attributes
+ * @buf: buffer
+ */
+static ssize_t channel_attr_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct most_c_attr *channel_attr = to_channel_attr(attr);
+ struct most_c_obj *c_obj = to_c_obj(kobj);
+
+ if (!channel_attr->show)
+ return -EIO;
+
+ return channel_attr->show(c_obj, channel_attr, buf);
+}
+
+/**
+ * channel_attr_store - store function of channel object
+ * @kobj: pointer to its kobject
+ * @attr: pointer to its attributes
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t channel_attr_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct most_c_attr *channel_attr = to_channel_attr(attr);
+ struct most_c_obj *c_obj = to_c_obj(kobj);
+
+ if (!channel_attr->store)
+ return -EIO;
+ return channel_attr->store(c_obj, channel_attr, buf, len);
+}
+
+static const struct sysfs_ops most_channel_sysfs_ops = {
+ .show = channel_attr_show,
+ .store = channel_attr_store,
+};
+
+/**
+ * most_free_mbo_coherent - free an MBO and its coherent buffer
+ * @mbo: buffer to be released
+ *
+ */
+static void most_free_mbo_coherent(struct mbo *mbo)
+{
+ struct most_c_obj *c = mbo->context;
+ u16 const coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
+
+ dma_free_coherent(NULL, coherent_buf_size, mbo->virt_address,
+ mbo->bus_address);
+ kfree(mbo);
+ if (atomic_sub_and_test(1, &c->mbo_ref))
+ complete(&c->cleanup);
+}
+
+/**
+ * flush_channel_fifos - clear the channel fifos
+ * @c: pointer to channel object
+ */
+static void flush_channel_fifos(struct most_c_obj *c)
+{
+ unsigned long flags, hf_flags;
+ struct mbo *mbo, *tmp;
+
+ if (list_empty(&c->fifo) && list_empty(&c->halt_fifo))
+ return;
+
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ list_for_each_entry_safe(mbo, tmp, &c->fifo, list) {
+ list_del(&mbo->list);
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+ if (likely(mbo))
+ most_free_mbo_coherent(mbo);
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ }
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+ spin_lock_irqsave(&c->fifo_lock, hf_flags);
+ list_for_each_entry_safe(mbo, tmp, &c->halt_fifo, list) {
+ list_del(&mbo->list);
+ spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
+ if (likely(mbo))
+ most_free_mbo_coherent(mbo);
+ spin_lock_irqsave(&c->fifo_lock, hf_flags);
+ }
+ spin_unlock_irqrestore(&c->fifo_lock, hf_flags);
+
+ if (unlikely((!list_empty(&c->fifo) || !list_empty(&c->halt_fifo))))
+ pr_info("WARN: fifo | trash fifo not empty\n");
+}
+
+/**
+ * flush_trash_fifo - clear the trash fifo
+ * @c: pointer to channel object
+ */
+static int flush_trash_fifo(struct most_c_obj *c)
+{
+ struct mbo *mbo, *tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ list_for_each_entry_safe(mbo, tmp, &c->trash_fifo, list) {
+ list_del(&mbo->list);
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+ most_free_mbo_coherent(mbo);
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ }
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+ return 0;
+}
+
+/**
+ * most_channel_release - release function of channel object
+ * @kobj: pointer to channel's kobject
+ */
+static void most_channel_release(struct kobject *kobj)
+{
+ struct most_c_obj *c = to_c_obj(kobj);
+
+ kfree(c);
+}
+
+static ssize_t show_available_directions(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ unsigned int i = c->channel_id;
+
+ strcpy(buf, "");
+ if (c->iface->channel_vector[i].direction & MOST_CH_RX)
+ strcat(buf, "dir_rx ");
+ if (c->iface->channel_vector[i].direction & MOST_CH_TX)
+ strcat(buf, "dir_tx ");
+ strcat(buf, "\n");
+ return strlen(buf) + 1;
+}
+
+static ssize_t show_available_datatypes(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ unsigned int i = c->channel_id;
+
+ strcpy(buf, "");
+ if (c->iface->channel_vector[i].data_type & MOST_CH_CONTROL)
+ strcat(buf, "control ");
+ if (c->iface->channel_vector[i].data_type & MOST_CH_ASYNC)
+ strcat(buf, "async ");
+ if (c->iface->channel_vector[i].data_type & MOST_CH_SYNC)
+ strcat(buf, "sync ");
+ if (c->iface->channel_vector[i].data_type & MOST_CH_ISOC_AVP)
+ strcat(buf, "isoc_avp ");
+ strcat(buf, "\n");
+ return strlen(buf) + 1;
+}
+
+static
+ssize_t show_number_of_packet_buffers(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ unsigned int i = c->channel_id;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ c->iface->channel_vector[i].num_buffers_packet);
+}
+
+static
+ssize_t show_number_of_stream_buffers(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ unsigned int i = c->channel_id;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ c->iface->channel_vector[i].num_buffers_streaming);
+}
+
+static
+ssize_t show_size_of_packet_buffer(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ unsigned int i = c->channel_id;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ c->iface->channel_vector[i].buffer_size_packet);
+}
+
+static
+ssize_t show_size_of_stream_buffer(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ unsigned int i = c->channel_id;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ c->iface->channel_vector[i].buffer_size_streaming);
+}
+
+static ssize_t show_channel_starving(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", c->is_starving);
+}
+
+
+#define create_show_channel_attribute(val) \
+ static MOST_CHNL_ATTR(val, S_IRUGO, show_##val, NULL)
+
+create_show_channel_attribute(available_directions);
+create_show_channel_attribute(available_datatypes);
+create_show_channel_attribute(number_of_packet_buffers);
+create_show_channel_attribute(number_of_stream_buffers);
+create_show_channel_attribute(size_of_stream_buffer);
+create_show_channel_attribute(size_of_packet_buffer);
+create_show_channel_attribute(channel_starving);
+
+static ssize_t show_set_number_of_buffers(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.num_buffers);
+}
+
+static ssize_t store_set_number_of_buffers(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = kstrtou16(buf, 0, &c->cfg.num_buffers);
+
+ if (ret)
+ return ret;
+ return count;
+}
+
+static ssize_t show_set_buffer_size(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.buffer_size);
+}
+
+static ssize_t store_set_buffer_size(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = kstrtou16(buf, 0, &c->cfg.buffer_size);
+
+ if (ret)
+ return ret;
+ return count;
+}
+
+static ssize_t show_set_direction(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ if (c->cfg.direction & MOST_CH_TX)
+ return snprintf(buf, PAGE_SIZE, "dir_tx\n");
+ else if (c->cfg.direction & MOST_CH_RX)
+ return snprintf(buf, PAGE_SIZE, "dir_rx\n");
+ return snprintf(buf, PAGE_SIZE, "unconfigured\n");
+}
+
+static ssize_t store_set_direction(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ const char *buf,
+ size_t count)
+{
+ if (!strcmp(buf, "dir_rx\n"))
+ c->cfg.direction = MOST_CH_RX;
+ else if (!strcmp(buf, "dir_tx\n"))
+ c->cfg.direction = MOST_CH_TX;
+ else {
+ pr_info("WARN: invalid attribute settings\n");
+ return -EINVAL;
+ }
+ return count;
+}
+
+static ssize_t show_set_datatype(struct most_c_obj *c,
+ 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");
+ return snprintf(buf, PAGE_SIZE, "unconfigured\n");
+}
+
+static ssize_t store_set_datatype(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ 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 {
+ pr_info("WARN: invalid attribute settings\n");
+ return -EINVAL;
+ }
+ return count;
+}
+
+static ssize_t show_set_subbuffer_size(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.subbuffer_size);
+}
+
+static ssize_t store_set_subbuffer_size(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = kstrtou16(buf, 0, &c->cfg.subbuffer_size);
+
+ if (ret)
+ return ret;
+ return count;
+}
+
+static ssize_t show_set_packets_per_xact(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", c->cfg.packets_per_xact);
+}
+
+static ssize_t store_set_packets_per_xact(struct most_c_obj *c,
+ struct most_c_attr *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = kstrtou16(buf, 0, &c->cfg.packets_per_xact);
+
+ if (ret)
+ return ret;
+ return count;
+}
+
+#define create_channel_attribute(value) \
+ static MOST_CHNL_ATTR(value, S_IRUGO | S_IWUSR, \
+ show_##value, \
+ store_##value)
+
+create_channel_attribute(set_buffer_size);
+create_channel_attribute(set_number_of_buffers);
+create_channel_attribute(set_direction);
+create_channel_attribute(set_datatype);
+create_channel_attribute(set_subbuffer_size);
+create_channel_attribute(set_packets_per_xact);
+
+
+/**
+ * most_channel_def_attrs - array of default attributes of channel object
+ */
+static struct attribute *most_channel_def_attrs[] = {
+ &most_chnl_attr_available_directions.attr,
+ &most_chnl_attr_available_datatypes.attr,
+ &most_chnl_attr_number_of_packet_buffers.attr,
+ &most_chnl_attr_number_of_stream_buffers.attr,
+ &most_chnl_attr_size_of_packet_buffer.attr,
+ &most_chnl_attr_size_of_stream_buffer.attr,
+ &most_chnl_attr_set_number_of_buffers.attr,
+ &most_chnl_attr_set_buffer_size.attr,
+ &most_chnl_attr_set_direction.attr,
+ &most_chnl_attr_set_datatype.attr,
+ &most_chnl_attr_set_subbuffer_size.attr,
+ &most_chnl_attr_set_packets_per_xact.attr,
+ &most_chnl_attr_channel_starving.attr,
+ NULL,
+};
+
+static struct kobj_type most_channel_ktype = {
+ .sysfs_ops = &most_channel_sysfs_ops,
+ .release = most_channel_release,
+ .default_attrs = most_channel_def_attrs,
+};
+
+static struct kset *most_channel_kset;
+
+/**
+ * create_most_c_obj - allocates a channel object
+ * @name: name of the channel object
+ * @parent: parent kobject
+ *
+ * This create a channel object and registers it with sysfs.
+ * Returns a pointer to the object or NULL when something went wrong.
+ */
+static struct most_c_obj *
+create_most_c_obj(const char *name, struct kobject *parent)
+{
+ struct most_c_obj *c;
+ int retval;
+
+ c = kzalloc(sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return NULL;
+ c->kobj.kset = most_channel_kset;
+ retval = kobject_init_and_add(&c->kobj, &most_channel_ktype, parent,
+ "%s", name);
+ if (retval) {
+ kobject_put(&c->kobj);
+ return NULL;
+ }
+ kobject_uevent(&c->kobj, KOBJ_ADD);
+ 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->first_aim)
+ c->first_aim->disconnect_channel(c->iface, c->channel_id);
+ if (c->second_aim)
+ c->second_aim->disconnect_channel(c->iface, c->channel_id);
+ c->first_aim = NULL;
+ c->second_aim = 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___
+ */
+#define MOST_INST_ATTR(_name, _mode, _show, _store) \
+ struct most_inst_attribute most_inst_attr_##_name = \
+ __ATTR(_name, _mode, _show, _store)
+
+static struct list_head instance_list;
+
+/**
+ * struct most_inst_attribute - to access the attributes of instance object
+ * @attr: attributes of an instance
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_inst_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct most_inst_obj *d,
+ struct most_inst_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct most_inst_obj *d,
+ struct most_inst_attribute *attr,
+ const char *buf,
+ size_t count);
+};
+#define to_instance_attr(a) \
+ container_of(a, struct most_inst_attribute, attr)
+
+/**
+ * instance_attr_show - show function for an instance object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t instance_attr_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct most_inst_attribute *instance_attr;
+ struct most_inst_obj *instance_obj;
+
+ instance_attr = to_instance_attr(attr);
+ instance_obj = to_inst_obj(kobj);
+
+ if (!instance_attr->show)
+ return -EIO;
+
+ return instance_attr->show(instance_obj, instance_attr, buf);
+}
+
+/**
+ * instance_attr_store - store function for an instance object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t instance_attr_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct most_inst_attribute *instance_attr;
+ struct most_inst_obj *instance_obj;
+
+ instance_attr = to_instance_attr(attr);
+ instance_obj = to_inst_obj(kobj);
+
+ if (!instance_attr->store)
+ return -EIO;
+
+ return instance_attr->store(instance_obj, instance_attr, buf, len);
+}
+
+static const struct sysfs_ops most_inst_sysfs_ops = {
+ .show = instance_attr_show,
+ .store = instance_attr_store,
+};
+
+/**
+ * most_inst_release - release function for instance object
+ * @kobj: pointer to instance's kobject
+ *
+ * This frees the allocated memory for the instance object
+ */
+static void most_inst_release(struct kobject *kobj)
+{
+ struct most_inst_obj *inst = to_inst_obj(kobj);
+
+ kfree(inst);
+}
+
+static ssize_t show_description(struct most_inst_obj *instance_obj,
+ struct most_inst_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n",
+ instance_obj->iface->description);
+}
+
+static ssize_t show_interface(struct most_inst_obj *instance_obj,
+ struct most_inst_attribute *attr,
+ char *buf)
+{
+ switch (instance_obj->iface->interface) {
+ case ITYPE_LOOPBACK:
+ return snprintf(buf, PAGE_SIZE, "loopback\n");
+ case ITYPE_I2C:
+ return snprintf(buf, PAGE_SIZE, "i2c\n");
+ case ITYPE_I2S:
+ return snprintf(buf, PAGE_SIZE, "i2s\n");
+ case ITYPE_TSI:
+ return snprintf(buf, PAGE_SIZE, "tsi\n");
+ case ITYPE_HBI:
+ return snprintf(buf, PAGE_SIZE, "hbi\n");
+ case ITYPE_MEDIALB_DIM:
+ return snprintf(buf, PAGE_SIZE, "mlb_dim\n");
+ case ITYPE_MEDIALB_DIM2:
+ return snprintf(buf, PAGE_SIZE, "mlb_dim2\n");
+ case ITYPE_USB:
+ return snprintf(buf, PAGE_SIZE, "usb\n");
+ case ITYPE_PCIE:
+ return snprintf(buf, PAGE_SIZE, "pcie\n");
+ }
+ return snprintf(buf, PAGE_SIZE, "unknown\n");
+}
+
+#define create_inst_attribute(value) \
+ static MOST_INST_ATTR(value, S_IRUGO, show_##value, NULL)
+
+create_inst_attribute(description);
+create_inst_attribute(interface);
+
+static struct attribute *most_inst_def_attrs[] = {
+ &most_inst_attr_description.attr,
+ &most_inst_attr_interface.attr,
+ NULL,
+};
+
+static struct kobj_type most_inst_ktype = {
+ .sysfs_ops = &most_inst_sysfs_ops,
+ .release = most_inst_release,
+ .default_attrs = most_inst_def_attrs,
+};
+
+static struct kset *most_inst_kset;
+
+
+/**
+ * create_most_inst_obj - creates an instance object
+ * @name: name of the object to be created
+ *
+ * This allocates memory for an instance structure, assigns the proper kset
+ * and registers it with sysfs.
+ *
+ * Returns a pointer to the instance object or NULL when something went wrong.
+ */
+static struct most_inst_obj *create_most_inst_obj(const char *name)
+{
+ struct most_inst_obj *inst;
+ int retval;
+
+ inst = kzalloc(sizeof(*inst), GFP_KERNEL);
+ if (!inst)
+ return NULL;
+ inst->kobj.kset = most_inst_kset;
+ retval = kobject_init_and_add(&inst->kobj, &most_inst_ktype, NULL,
+ "%s", name);
+ if (retval) {
+ kobject_put(&inst->kobj);
+ return NULL;
+ }
+ kobject_uevent(&inst->kobj, KOBJ_ADD);
+ return inst;
+}
+
+/**
+ * destroy_most_inst_obj - MOST instance release function
+ * @inst: pointer to the instance object
+ *
+ * This decrements the reference counter of the instance object.
+ * If the reference count turns zero, its release function is called
+ */
+static void destroy_most_inst_obj(struct most_inst_obj *inst)
+{
+ 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);
+ }
+ kobject_put(&inst->kobj);
+}
+
+/* ___ ___
+ * ___A I M___
+ */
+struct most_aim_obj {
+ struct kobject kobj;
+ struct list_head list;
+ struct most_aim *driver;
+ char add_link[STRING_SIZE];
+ char remove_link[STRING_SIZE];
+};
+#define to_aim_obj(d) container_of(d, struct most_aim_obj, kobj)
+
+static struct list_head aim_list;
+
+
+/**
+ * struct most_aim_attribute - to access the attributes of AIM object
+ * @attr: attributes of an AIM
+ * @show: pointer to the show function
+ * @store: pointer to the store function
+ */
+struct most_aim_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct most_aim_obj *d,
+ struct most_aim_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct most_aim_obj *d,
+ struct most_aim_attribute *attr,
+ const char *buf,
+ size_t count);
+};
+#define to_aim_attr(a) container_of(a, struct most_aim_attribute, attr)
+
+/**
+ * aim_attr_show - show function of an AIM object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ */
+static ssize_t aim_attr_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct most_aim_attribute *aim_attr;
+ struct most_aim_obj *aim_obj;
+
+ aim_attr = to_aim_attr(attr);
+ aim_obj = to_aim_obj(kobj);
+
+ if (!aim_attr->show)
+ return -EIO;
+
+ return aim_attr->show(aim_obj, aim_attr, buf);
+}
+
+/**
+ * aim_attr_store - store function of an AIM object
+ * @kobj: pointer to kobject
+ * @attr: pointer to attribute struct
+ * @buf: buffer
+ * @len: length of buffer
+ */
+static ssize_t aim_attr_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct most_aim_attribute *aim_attr;
+ struct most_aim_obj *aim_obj;
+
+ aim_attr = to_aim_attr(attr);
+ aim_obj = to_aim_obj(kobj);
+
+ if (!aim_attr->store)
+ return -EIO;
+ return aim_attr->store(aim_obj, aim_attr, buf, len);
+}
+
+static const struct sysfs_ops most_aim_sysfs_ops = {
+ .show = aim_attr_show,
+ .store = aim_attr_store,
+};
+
+/**
+ * most_aim_release - AIM release function
+ * @kobj: pointer to AIM's kobject
+ */
+static void most_aim_release(struct kobject *kobj)
+{
+ struct most_aim_obj *aim_obj = to_aim_obj(kobj);
+
+ kfree(aim_obj);
+}
+
+static ssize_t show_add_link(struct most_aim_obj *aim_obj,
+ struct most_aim_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", aim_obj->add_link);
+}
+
+/**
+ * split_string - parses and changes string in the buffer buf and
+ * splits it into two mandatory and one optional substrings.
+ *
+ * @buf: complete string from attribute 'add_channel'
+ * @a: address of pointer to 1st substring (=instance name)
+ * @b: address of pointer to 2nd substring (=channel name)
+ * @c: optional address of pointer to 3rd substring (=user defined name)
+ *
+ * Examples:
+ *
+ * Input: "mdev0:ch0@ep_81:my_channel\n" or
+ * "mdev0:ch0@ep_81:my_channel"
+ *
+ * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c -> "my_channel"
+ *
+ * Input: "mdev0:ch0@ep_81\n"
+ * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c -> ""
+ *
+ * Input: "mdev0:ch0@ep_81"
+ * Output: *a -> "mdev0", *b -> "ch0@ep_81", *c == NULL
+ */
+static int split_string(char *buf, char **a, char **b, char **c)
+{
+ *a = strsep(&buf, ":");
+ if (!*a)
+ return -EIO;
+
+ *b = strsep(&buf, ":\n");
+ if (!*b)
+ return -EIO;
+
+ if (c)
+ *c = strsep(&buf, ":\n");
+
+ return 0;
+}
+
+/**
+ * get_channel_by_name - get pointer to channel object
+ * @mdev: name of the device instance
+ * @mdev_ch: name of the respective channel
+ *
+ * This retrieves the pointer to a channel object.
+ */
+static struct
+most_c_obj *get_channel_by_name(char *mdev, char *mdev_ch)
+{
+ struct most_c_obj *c, *tmp;
+ struct most_inst_obj *i, *i_tmp;
+ int found = 0;
+
+ list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
+ if (!strcmp(kobject_name(&i->kobj), mdev)) {
+ found++;
+ break;
+ }
+ }
+ if (unlikely(!found))
+ return ERR_PTR(-EIO);
+
+ list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
+ if (!strcmp(kobject_name(&c->kobj), mdev_ch)) {
+ found++;
+ break;
+ }
+ }
+ if (unlikely(2 > found))
+ return ERR_PTR(-EIO);
+ return c;
+}
+
+/**
+ * store_add_link - store() function for add_link attribute
+ * @aim_obj: pointer to AIM object
+ * @attr: its attributes
+ * @buf: buffer
+ * @len: buffer length
+ *
+ * This parses the string given by buf and splits it into
+ * three substrings. Note: third substring is optional. In case a cdev
+ * AIM is loaded the optional 3rd substring will make up the name of
+ * device node in the /dev directory. If omitted, the device node will
+ * inherit the channel's name within sysfs.
+ *
+ * Searches for a pair of device and channel and probes the AIM
+ *
+ * Example:
+ * (1) echo -n -e "mdev0:ch0@ep_81:my_rxchannel\n" >add_link
+ * (2) echo -n -e "mdev0:ch0@ep_81\n" >add_link
+ *
+ * (1) would create the device node /dev/my_rxchannel
+ * (2) would create the device node /dev/mdev0-ch0@ep_81
+ */
+static ssize_t store_add_link(struct most_aim_obj *aim_obj,
+ struct most_aim_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct most_c_obj *c;
+ struct most_aim **aim_ptr;
+ char buffer[STRING_SIZE];
+ char *mdev;
+ char *mdev_ch;
+ char *mdev_devnod;
+ char devnod_buf[STRING_SIZE];
+ int ret;
+ size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
+
+ strlcpy(buffer, buf, max_len);
+ strlcpy(aim_obj->add_link, buf, max_len);
+
+ ret = split_string(buffer, &mdev, &mdev_ch, &mdev_devnod);
+ if (ret)
+ return ret;
+
+ if (!mdev_devnod || *mdev_devnod == 0) {
+ snprintf(devnod_buf, sizeof(devnod_buf), "%s-%s", mdev, mdev_ch);
+ mdev_devnod = devnod_buf;
+ }
+
+ c = get_channel_by_name(mdev, mdev_ch);
+ if (IS_ERR(c))
+ return -ENODEV;
+
+ if (!c->first_aim)
+ aim_ptr = &c->first_aim;
+ else if (!c->second_aim)
+ aim_ptr = &c->second_aim;
+ else
+ return -ENOSPC;
+
+ ret = aim_obj->driver->probe_channel(c->iface, c->channel_id,
+ &c->cfg, &c->kobj, mdev_devnod);
+ if (ret)
+ return ret;
+ *aim_ptr = aim_obj->driver;
+ return len;
+}
+
+static struct most_aim_attribute most_aim_attr_add_link =
+ __ATTR(add_link, S_IRUGO | S_IWUSR, show_add_link, store_add_link);
+
+static ssize_t show_remove_link(struct most_aim_obj *aim_obj,
+ struct most_aim_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", aim_obj->remove_link);
+}
+
+/**
+ * store_remove_link - store function for remove_link attribute
+ * @aim_obj: pointer to AIM object
+ * @attr: its attributes
+ * @buf: buffer
+ * @len: buffer length
+ *
+ * Example:
+ * echo -n -e "mdev0:ch0@ep_81\n" >remove_link
+ */
+static ssize_t store_remove_link(struct most_aim_obj *aim_obj,
+ struct most_aim_attribute *attr,
+ const char *buf,
+ size_t len)
+{
+ struct most_c_obj *c;
+ char buffer[STRING_SIZE];
+ char *mdev;
+ char *mdev_ch;
+ int ret;
+ size_t max_len = min_t(size_t, len + 1, STRING_SIZE);
+
+ strlcpy(buffer, buf, max_len);
+ strlcpy(aim_obj->remove_link, buf, max_len);
+ ret = split_string(buffer, &mdev, &mdev_ch, NULL);
+ if (ret)
+ return ret;
+
+ c = get_channel_by_name(mdev, mdev_ch);
+ if (IS_ERR(c))
+ return -ENODEV;
+
+ if (c->first_aim == aim_obj->driver)
+ c->first_aim = NULL;
+ if (c->second_aim == aim_obj->driver)
+ c->second_aim = NULL;
+ if (aim_obj->driver->disconnect_channel(c->iface, c->channel_id))
+ return -EIO;
+ return len;
+}
+
+static struct most_aim_attribute most_aim_attr_remove_link =
+ __ATTR(remove_link, S_IRUGO | S_IWUSR, show_remove_link, store_remove_link);
+
+static struct attribute *most_aim_def_attrs[] = {
+ &most_aim_attr_add_link.attr,
+ &most_aim_attr_remove_link.attr,
+ NULL,
+};
+
+static struct kobj_type most_aim_ktype = {
+ .sysfs_ops = &most_aim_sysfs_ops,
+ .release = most_aim_release,
+ .default_attrs = most_aim_def_attrs,
+};
+
+static struct kset *most_aim_kset;
+
+/**
+ * create_most_aim_obj - creates an AIM object
+ * @name: name of the AIM
+ *
+ * This creates an AIM object assigns the proper kset and registers
+ * it with sysfs.
+ * Returns a pointer to the object or NULL if something went wrong.
+ */
+static struct most_aim_obj *create_most_aim_obj(const char *name)
+{
+ struct most_aim_obj *most_aim;
+ int retval;
+
+ most_aim = kzalloc(sizeof(*most_aim), GFP_KERNEL);
+ if (!most_aim)
+ return NULL;
+ most_aim->kobj.kset = most_aim_kset;
+ retval = kobject_init_and_add(&most_aim->kobj, &most_aim_ktype,
+ NULL, "%s", name);
+ if (retval) {
+ kobject_put(&most_aim->kobj);
+ return NULL;
+ }
+ kobject_uevent(&most_aim->kobj, KOBJ_ADD);
+ return most_aim;
+}
+
+/**
+ * destroy_most_aim_obj - AIM release function
+ * @p: pointer to AIM object
+ *
+ * This decrements the reference counter of the AIM object. If the
+ * reference count turns zero, its release function will be called.
+ */
+static void destroy_most_aim_obj(struct most_aim_obj *p)
+{
+ kobject_put(&p->kobj);
+}
+
+
+/* ___ ___
+ * ___C O R E___
+ */
+
+/**
+ * Instantiation of the MOST bus
+ */
+static struct bus_type most_bus = {
+ .name = "most",
+};
+
+/**
+ * Instantiation of the core driver
+ */
+static struct device_driver mostcore = {
+ .name = "mostcore",
+ .bus = &most_bus,
+};
+
+static inline void trash_mbo(struct mbo *mbo)
+{
+ unsigned long flags;
+ struct most_c_obj *c = mbo->context;
+
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ list_add(&mbo->list, &c->trash_fifo);
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+}
+
+static struct mbo *get_hdm_mbo(struct most_c_obj *c)
+{
+ unsigned long flags;
+ struct mbo *mbo;
+
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ if (c->enqueue_halt || list_empty(&c->halt_fifo))
+ mbo = NULL;
+ else
+ mbo = list_pop_mbo(&c->halt_fifo);
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+ return mbo;
+}
+
+static void nq_hdm_mbo(struct mbo *mbo)
+{
+ unsigned long flags;
+ struct most_c_obj *c = mbo->context;
+
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ list_add_tail(&mbo->list, &c->halt_fifo);
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+ wake_up_interruptible(&c->hdm_fifo_wq);
+}
+
+static int hdm_enqueue_thread(void *data)
+{
+ struct most_c_obj *c = data;
+ struct mbo *mbo;
+ typeof(c->iface->enqueue) enqueue = c->iface->enqueue;
+
+ while (likely(!kthread_should_stop())) {
+ wait_event_interruptible(c->hdm_fifo_wq,
+ (mbo = get_hdm_mbo(c))
+ || kthread_should_stop());
+
+ if (unlikely(!mbo))
+ continue;
+
+ if (c->cfg.direction == MOST_CH_RX)
+ mbo->buffer_length = c->cfg.buffer_size;
+
+ if (unlikely(enqueue(mbo->ifp, mbo->hdm_channel_id, mbo))) {
+ pr_err("hdm enqueue failed\n");
+ nq_hdm_mbo(mbo);
+ c->hdm_enqueue_task = NULL;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+static int run_enqueue_thread(struct most_c_obj *c, int channel_id)
+{
+ struct task_struct *task =
+ kthread_run(&hdm_enqueue_thread, c, "hdm_fifo_%d", channel_id);
+
+ if (IS_ERR(task))
+ return PTR_ERR(task);
+
+ c->hdm_enqueue_task = task;
+ return 0;
+}
+
+/**
+ * arm_mbo - recycle MBO for further usage
+ * @mbo: buffer object
+ *
+ * This puts an MBO back to the list to have it ready for up coming
+ * tx transactions.
+ *
+ * In case the MBO belongs to a channel that recently has been
+ * poisoned, the MBO is scheduled to be trashed.
+ * Calls the completion handler of an attached AIM.
+ */
+static void arm_mbo(struct mbo *mbo)
+{
+ unsigned long flags;
+ struct most_c_obj *c;
+
+ BUG_ON((!mbo) || (!mbo->context));
+ c = mbo->context;
+
+ if (c->is_poisoned) {
+ trash_mbo(mbo);
+ return;
+ }
+
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ list_add_tail(&mbo->list, &c->fifo);
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+
+ if (c->second_aim && c->second_aim->tx_completion)
+ c->second_aim->tx_completion(c->iface, c->channel_id);
+ if (c->first_aim && c->first_aim->tx_completion)
+ c->first_aim->tx_completion(c->iface, c->channel_id);
+}
+
+/**
+ * arm_mbo_chain - helper function that arms an MBO chain for the HDM
+ * @c: pointer to interface channel
+ * @dir: direction of the channel
+ * @compl: pointer to completion function
+ *
+ * This allocates buffer objects including the containing DMA coherent
+ * buffer and puts them in the fifo.
+ * Buffers of Rx channels are put in the kthread fifo, hence immediately
+ * submitted to the HDM.
+ *
+ * Returns the number of allocated and enqueued MBOs.
+ */
+static int arm_mbo_chain(struct most_c_obj *c, int dir,
+ void (*compl)(struct mbo *))
+{
+ unsigned int i;
+ int retval;
+ struct mbo *mbo;
+ u32 coherent_buf_size = c->cfg.buffer_size + c->cfg.extra_len;
+
+ atomic_set(&c->mbo_nq_level, 0);
+
+ for (i = 0; i < c->cfg.num_buffers; i++) {
+ mbo = kzalloc(sizeof(*mbo), GFP_KERNEL);
+ if (!mbo) {
+ pr_info("WARN: Allocation of MBO failed.\n");
+ retval = i;
+ goto _exit;
+ }
+ mbo->context = c;
+ mbo->ifp = c->iface;
+ mbo->hdm_channel_id = c->channel_id;
+ mbo->virt_address = dma_alloc_coherent(NULL,
+ coherent_buf_size,
+ &mbo->bus_address,
+ GFP_KERNEL);
+ if (!mbo->virt_address) {
+ pr_info("WARN: No DMA coherent buffer.\n");
+ retval = i;
+ goto _error1;
+ }
+ mbo->complete = compl;
+ if (dir == MOST_CH_RX) {
+ nq_hdm_mbo(mbo);
+ atomic_inc(&c->mbo_nq_level);
+ } else {
+ arm_mbo(mbo);
+ }
+ }
+ return i;
+
+_error1:
+ kfree(mbo);
+_exit:
+ return retval;
+}
+
+/**
+ * most_submit_mbo - submits an MBO to fifo
+ * @mbo: pointer to the MBO
+ *
+ */
+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;
+}
+EXPORT_SYMBOL_GPL(most_submit_mbo);
+
+/**
+ * most_write_completion - write completion handler
+ * @mbo: pointer to MBO
+ *
+ * This recycles the MBO for further usage. In case the channel has been
+ * poisoned, the MBO is scheduled to be trashed.
+ */
+static void most_write_completion(struct mbo *mbo)
+{
+ struct most_c_obj *c;
+
+ BUG_ON((!mbo) || (!mbo->context));
+
+ c = mbo->context;
+ if (mbo->status == MBO_E_INVAL)
+ pr_info("WARN: Tx MBO status: invalid\n");
+ if (unlikely((c->is_poisoned == true) || (mbo->status == MBO_E_CLOSE)))
+ trash_mbo(mbo);
+ else
+ arm_mbo(mbo);
+}
+
+/**
+ * get_channel_by_iface - get pointer to channel object
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ *
+ * This retrieves a pointer to a channel of the given interface and channel ID.
+ */
+static struct
+most_c_obj *get_channel_by_iface(struct most_interface *iface, int id)
+{
+ struct most_inst_obj *i;
+
+ if (unlikely(!iface)) {
+ pr_err("Bad interface\n");
+ return NULL;
+ }
+ if (unlikely((id < 0) || (id >= iface->num_channels))) {
+ pr_err("Channel index (%d) out of range\n", id);
+ return NULL;
+ }
+ i = iface->priv;
+ if (unlikely(!i)) {
+ pr_err("interface is not registered\n");
+ return NULL;
+ }
+ return i->channel[id];
+}
+
+/**
+ * most_get_mbo - get pointer to an MBO of pool
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ *
+ * This attempts to get a free buffer out of the channel fifo.
+ * Returns a pointer to MBO on success or NULL otherwise.
+ */
+struct mbo *most_get_mbo(struct most_interface *iface, int id)
+{
+ struct mbo *mbo;
+ struct most_c_obj *c;
+ unsigned long flags;
+
+ c = get_channel_by_iface(iface, id);
+ if (unlikely(!c))
+ return NULL;
+ spin_lock_irqsave(&c->fifo_lock, flags);
+ if (list_empty(&c->fifo)) {
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+ return NULL;
+ }
+ mbo = list_pop_mbo(&c->fifo);
+ spin_unlock_irqrestore(&c->fifo_lock, flags);
+ mbo->buffer_length = c->cfg.buffer_size;
+ return mbo;
+}
+EXPORT_SYMBOL_GPL(most_get_mbo);
+
+
+/**
+ * most_put_mbo - return buffer to pool
+ * @mbo: buffer object
+ */
+void most_put_mbo(struct mbo *mbo)
+{
+ struct most_c_obj *c;
+ struct most_inst_obj *i;
+
+ c = mbo->context;
+ i = c->inst;
+
+ 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;
+ }
+ nq_hdm_mbo(mbo);
+ atomic_inc(&c->mbo_nq_level);
+}
+EXPORT_SYMBOL_GPL(most_put_mbo);
+
+/**
+ * most_read_completion - read completion handler
+ * @mbo: pointer to MBO
+ *
+ * This function is called by the HDM when data has been received from the
+ * hardware and copied to the buffer of the MBO.
+ *
+ * In case the channel has been poisoned it puts the buffer in the trash queue.
+ * Otherwise, it passes the buffer to an AIM for further processing.
+ */
+static void most_read_completion(struct mbo *mbo)
+{
+ struct most_c_obj *c;
+
+ c = mbo->context;
+ if (unlikely((c->is_poisoned == true) || (mbo->status == MBO_E_CLOSE)))
+ goto release_mbo;
+
+ if (mbo->status == MBO_E_INVAL) {
+ nq_hdm_mbo(mbo);
+ atomic_inc(&c->mbo_nq_level);
+ return;
+ }
+
+ if (atomic_sub_and_test(1, &c->mbo_nq_level)) {
+ pr_info("WARN: rx device out of buffers\n");
+ c->is_starving = 1;
+ }
+
+ if (c->first_aim && c->first_aim->rx_completion &&
+ c->first_aim->rx_completion(mbo) == 0)
+ return;
+ if (c->second_aim && c->second_aim->rx_completion &&
+ c->second_aim->rx_completion(mbo) == 0)
+ return;
+ pr_info("WARN: no driver linked with this channel\n");
+ mbo->status = MBO_E_CLOSE;
+release_mbo:
+ trash_mbo(mbo);
+}
+
+/**
+ * most_start_channel - prepares a channel for communication
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ *
+ * This prepares the channel for usage. Cross-checks whether the
+ * channel's been properly configured.
+ *
+ * Returns 0 on success or error code otherwise.
+ */
+int most_start_channel(struct most_interface *iface, int id)
+{
+ int num_buffer;
+ int ret;
+ struct most_c_obj *c = get_channel_by_iface(iface, id);
+
+ if (unlikely(!c))
+ return -EINVAL;
+
+ if (c->is_started)
+ return -EBUSY;
+
+ if (!try_module_get(iface->mod)) {
+ pr_info("failed to acquire HDM lock\n");
+ return -ENOLCK;
+ }
+ modref++;
+
+ c->cfg.extra_len = 0;
+ if (c->iface->configure(c->iface, c->channel_id, &c->cfg)) {
+ pr_info("channel configuration failed. Go check settings...\n");
+ ret = -EINVAL;
+ goto error;
+ }
+
+ init_waitqueue_head(&c->hdm_fifo_wq);
+
+ if (c->cfg.direction == MOST_CH_RX)
+ num_buffer = arm_mbo_chain(c, c->cfg.direction,
+ most_read_completion);
+ else
+ num_buffer = arm_mbo_chain(c, c->cfg.direction,
+ most_write_completion);
+ if (unlikely(0 == num_buffer)) {
+ pr_info("failed to allocate memory\n");
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ ret = run_enqueue_thread(c, id);
+ if (ret)
+ goto error;
+
+ c->is_started = true;
+ c->is_starving = 0;
+ atomic_set(&c->mbo_ref, num_buffer);
+ return 0;
+error:
+ if (iface->mod)
+ module_put(iface->mod);
+ modref--;
+ return ret;
+}
+EXPORT_SYMBOL_GPL(most_start_channel);
+
+/**
+ * most_stop_channel - stops a running channel
+ * @iface: pointer to interface instance
+ * @id: channel ID
+ */
+int most_stop_channel(struct most_interface *iface, int id)
+{
+ struct most_c_obj *c;
+
+ if (unlikely((!iface) || (id >= iface->num_channels) || (id < 0))) {
+ pr_err("Bad interface or index out of range\n");
+ return -EINVAL;
+ }
+ c = get_channel_by_iface(iface, id);
+ if (unlikely(!c))
+ return -EINVAL;
+
+ if (!c->is_started)
+ return 0;
+
+ /* FIXME: we need to know calling AIM to reset only one link */
+ c->first_aim = NULL;
+ c->second_aim = NULL;
+ /* do not go into recursion calling aim->disconnect_channel */
+
+ 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);
+ return -ENODEV;
+ }
+ mutex_unlock(&deregister_mutex);
+
+ if (iface->mod && modref) {
+ module_put(iface->mod);
+ modref--;
+ }
+
+ c->is_poisoned = true;
+ if (c->iface->poison_channel(c->iface, c->channel_id)) {
+ pr_err("Cannot stop channel %d of mdev %s\n", c->channel_id,
+ c->iface->description);
+ return -EAGAIN;
+ }
+ flush_trash_fifo(c);
+ flush_channel_fifos(c);
+
+#ifdef CMPL_INTERRUPTIBLE
+ if (wait_for_completion_interruptible(&c->cleanup)) {
+ pr_info("Interrupted while clean up ch %d\n", c->channel_id);
+ return -EINTR;
+ }
+#else
+ wait_for_completion(&c->cleanup);
+#endif
+ c->is_poisoned = false;
+ c->is_started = false;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(most_stop_channel);
+
+/**
+ * most_register_aim - registers an AIM (driver) with the core
+ * @aim: instance of AIM to be registered
+ */
+int most_register_aim(struct most_aim *aim)
+{
+ struct most_aim_obj *aim_obj;
+
+ if (!aim) {
+ pr_err("Bad driver\n");
+ return -EINVAL;
+ }
+ aim_obj = create_most_aim_obj(aim->name);
+ if (!aim_obj) {
+ pr_info("failed to alloc driver object\n");
+ return -ENOMEM;
+ }
+ aim_obj->driver = aim;
+ aim->context = aim_obj;
+ pr_info("registered new application interfacing module %s\n",
+ aim->name);
+ list_add_tail(&aim_obj->list, &aim_list);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(most_register_aim);
+
+/**
+ * most_deregister_aim - deregisters an AIM (driver) with the core
+ * @aim: AIM to be removed
+ */
+int most_deregister_aim(struct most_aim *aim)
+{
+ struct most_aim_obj *aim_obj;
+ struct most_c_obj *c, *tmp;
+ struct most_inst_obj *i, *i_tmp;
+
+ if (!aim) {
+ pr_err("Bad driver\n");
+ return -EINVAL;
+ }
+
+ aim_obj = aim->context;
+ if (!aim_obj) {
+ pr_info("driver not registered.\n");
+ return -EINVAL;
+ }
+ list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
+ list_for_each_entry_safe(c, tmp, &i->channel_list, list) {
+ if (c->first_aim == aim || c->second_aim == aim)
+ aim->disconnect_channel(
+ c->iface, c->channel_id);
+ if (c->first_aim == aim)
+ c->first_aim = NULL;
+ if (c->second_aim == aim)
+ c->second_aim = NULL;
+ }
+ }
+ list_del(&aim_obj->list);
+ destroy_most_aim_obj(aim_obj);
+ pr_info("deregistering application interfacing module %s\n", aim->name);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(most_deregister_aim);
+
+/**
+ * most_register_interface - registers an interface with core
+ * @iface: pointer to the instance of the interface description.
+ *
+ * Allocates and initializes a new interface instance and all of its channels.
+ * Returns a pointer to kobject or an error pointer.
+ */
+struct kobject *most_register_interface(struct most_interface *iface)
+{
+ unsigned int i;
+ int id;
+ char name[STRING_SIZE];
+ char channel_name[STRING_SIZE];
+ struct most_c_obj *c;
+ struct most_inst_obj *inst;
+
+ if (!iface || !iface->enqueue || !iface->configure ||
+ !iface->poison_channel || (iface->num_channels > MAX_CHANNELS)) {
+ pr_err("Bad interface or channel overflow\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ id = ida_simple_get(&mdev_id, 0, 0, GFP_KERNEL);
+ if (id < 0) {
+ pr_info("Failed to alloc mdev ID\n");
+ return ERR_PTR(id);
+ }
+ snprintf(name, STRING_SIZE, "mdev%d", id);
+
+ inst = create_most_inst_obj(name);
+ if (!inst) {
+ pr_info("Failed to allocate interface instance\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ iface->priv = inst;
+ 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++) {
+ const char *name_suffix = iface->channel_vector[i].name_suffix;
+
+ if (!name_suffix)
+ snprintf(channel_name, STRING_SIZE, "ch%d", i);
+ else if (name_suffix[0] == '@')
+ snprintf(channel_name, STRING_SIZE, "ch%d%s", i,
+ name_suffix);
+ else
+ snprintf(channel_name, STRING_SIZE, "%s", name_suffix);
+
+ /* this increments the reference count of this instance */
+ c = create_most_c_obj(channel_name, &inst->kobj);
+ if (!c)
+ goto free_instance;
+ inst->channel[i] = c;
+ c->is_starving = 0;
+ c->iface = iface;
+ c->inst = inst;
+ c->channel_id = i;
+ c->keep_mbo = false;
+ c->enqueue_halt = false;
+ c->is_poisoned = false;
+ c->is_started = false;
+ c->cfg.direction = 0;
+ c->cfg.data_type = 0;
+ c->cfg.num_buffers = 0;
+ c->cfg.buffer_size = 0;
+ c->cfg.subbuffer_size = 0;
+ c->cfg.packets_per_xact = 0;
+ spin_lock_init(&c->fifo_lock);
+ INIT_LIST_HEAD(&c->fifo);
+ INIT_LIST_HEAD(&c->trash_fifo);
+ INIT_LIST_HEAD(&c->halt_fifo);
+ init_completion(&c->cleanup);
+ atomic_set(&c->mbo_ref, 0);
+ mutex_init(&c->stop_task_mutex);
+ list_add_tail(&c->list, &inst->channel_list);
+ }
+ pr_info("registered new MOST device mdev%d (%s)\n",
+ inst->dev_id, iface->description);
+ return &inst->kobj;
+
+free_instance:
+ pr_info("Failed allocate channel(s)\n");
+ list_del(&inst->list);
+ destroy_most_inst_obj(inst);
+ return ERR_PTR(-ENOMEM);
+}
+EXPORT_SYMBOL_GPL(most_register_interface);
+
+/**
+ * most_deregister_interface - deregisters an interface with core
+ * @iface: pointer to the interface instance description.
+ *
+ * Before removing an interface instance from the list, all running
+ * channels are stopped and poisoned.
+ */
+void most_deregister_interface(struct most_interface *iface)
+{
+ 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->is_started)
+ 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);
+ }
+ ida_simple_remove(&mdev_id, i->dev_id);
+ list_del(&i->list);
+ destroy_most_inst_obj(i);
+}
+EXPORT_SYMBOL_GPL(most_deregister_interface);
+
+/**
+ * most_stop_enqueue - prevents core from enqueueing MBOs
+ * @iface: pointer to interface
+ * @id: channel id
+ *
+ * This is called by an HDM that _cannot_ attend to its duties and
+ * is imminent to get run over by the core. The core is not going to
+ * enqueue any further packets unless the flagging HDM calls
+ * most_resume enqueue().
+ */
+void most_stop_enqueue(struct most_interface *iface, int id)
+{
+ struct most_c_obj *c = get_channel_by_iface(iface, id);
+
+ if (likely(c))
+ c->enqueue_halt = true;
+}
+EXPORT_SYMBOL_GPL(most_stop_enqueue);
+
+/**
+ * most_resume_enqueue - allow core to enqueue MBOs again
+ * @iface: pointer to interface
+ * @id: channel id
+ *
+ * This clears the enqueue halt flag and enqueues all MBOs currently
+ * sitting in the wait fifo.
+ */
+void most_resume_enqueue(struct most_interface *iface, int id)
+{
+ struct most_c_obj *c = get_channel_by_iface(iface, id);
+
+ if (unlikely(!c))
+ return;
+ c->enqueue_halt = false;
+
+ wake_up_interruptible(&c->hdm_fifo_wq);
+}
+EXPORT_SYMBOL_GPL(most_resume_enqueue);
+
+static int __init most_init(void)
+{
+ 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)) {
+ pr_info("Cannot register most bus\n");
+ goto exit;
+ }
+
+ most_class = class_create(THIS_MODULE, "most");
+ if (IS_ERR(most_class)) {
+ pr_info("No udev support.\n");
+ goto exit_bus;
+ }
+ if (driver_register(&mostcore)) {
+ pr_info("Cannot register core driver\n");
+ goto exit_class;
+ }
+
+ class_glue_dir =
+ device_create(most_class, NULL, 0, NULL, "mostcore");
+ if (!class_glue_dir)
+ goto exit_driver;
+
+ most_aim_kset =
+ kset_create_and_add("aims", NULL, &class_glue_dir->kobj);
+ if (!most_aim_kset)
+ goto exit_class_container;
+
+ most_inst_kset =
+ kset_create_and_add("devices", NULL, &class_glue_dir->kobj);
+ if (!most_inst_kset)
+ goto exit_driver_kset;
+
+ return 0;
+
+exit_driver_kset:
+ kset_unregister(most_aim_kset);
+exit_class_container:
+ device_destroy(most_class, 0);
+exit_driver:
+ driver_unregister(&mostcore);
+exit_class:
+ class_destroy(most_class);
+exit_bus:
+ bus_unregister(&most_bus);
+exit:
+ return -ENOMEM;
+}
+
+static void __exit most_exit(void)
+{
+ struct most_inst_obj *i, *i_tmp;
+ struct most_aim_obj *d, *d_tmp;
+
+ pr_info("exit core module\n");
+ list_for_each_entry_safe(d, d_tmp, &aim_list, list) {
+ destroy_most_aim_obj(d);
+ }
+
+ list_for_each_entry_safe(i, i_tmp, &instance_list, list) {
+ list_del(&i->list);
+ destroy_most_inst_obj(i);
+ }
+ kset_unregister(most_inst_kset);
+ kset_unregister(most_aim_kset);
+ device_destroy(most_class, 0);
+ driver_unregister(&mostcore);
+ class_destroy(most_class);
+ bus_unregister(&most_bus);
+ ida_destroy(&mdev_id);
+}
+
+module_init(most_init);
+module_exit(most_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Gromm <christian.gromm@microchip.com>");
+MODULE_DESCRIPTION("Core module of stacked MOST Linux driver");
diff --git a/drivers/staging/most/mostcore/mostcore.h b/drivers/staging/most/mostcore/mostcore.h
new file mode 100644
index 0000000..299c7d5
--- /dev/null
+++ b/drivers/staging/most/mostcore/mostcore.h
@@ -0,0 +1,316 @@
+/*
+ * mostcore.h - Interface between MostCore,
+ * Hardware Dependent Module (HDM) and Application Interface Module (AIM).
+ *
+ * Copyright (C) 2013-2015, Microchip Technology Germany II GmbH & Co. KG
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * This file is licensed under GPLv2.
+ */
+
+/*
+ * Authors:
+ * Andrey Shvetsov <andrey.shvetsov@k2l.de>
+ * Christian Gromm <christian.gromm@microchip.com>
+ * Sebastian Graf
+ */
+
+#ifndef __MOST_CORE_H__
+#define __MOST_CORE_H__
+
+#include <linux/types.h>
+
+struct kobject;
+struct module;
+
+/**
+ * Interface type
+ */
+enum most_interface_type {
+ ITYPE_LOOPBACK = 1,
+ ITYPE_I2C,
+ ITYPE_I2S,
+ ITYPE_TSI,
+ ITYPE_HBI,
+ ITYPE_MEDIALB_DIM,
+ ITYPE_MEDIALB_DIM2,
+ ITYPE_USB,
+ ITYPE_PCIE
+};
+
+/**
+ * Channel direction.
+ */
+enum most_channel_direction {
+ MOST_CH_RX = 1 << 0,
+ MOST_CH_TX = 1 << 1,
+};
+
+/**
+ * Channel data type.
+ */
+enum most_channel_data_type {
+ MOST_CH_CONTROL = 1 << 0,
+ MOST_CH_ASYNC = 1 << 1,
+ MOST_CH_ISOC_AVP = 1 << 2,
+ MOST_CH_SYNC = 1 << 5,
+};
+
+
+enum mbo_status_flags {
+ /* MBO was processed successfully (data was send or received )*/
+ MBO_SUCCESS = 0,
+ /* The MBO contains wrong or missing information. */
+ MBO_E_INVAL,
+ /* MBO was completed as HDM Channel will be closed */
+ MBO_E_CLOSE,
+};
+
+/**
+ * struct most_channel_capability - Channel capability
+ * @direction: Supported channel directions.
+ * The value is bitwise OR-combination of the values from the
+ * enumeration most_channel_direction. Zero is allowed value and means
+ * "channel may not be used".
+ * @data_type: Supported channel data types.
+ * The value is bitwise OR-combination of the values from the
+ * enumeration most_channel_data_type. Zero is allowed value and means
+ * "channel may not be used".
+ * @num_buffer_packet: Maximum number of buffers supported by this channel
+ * for packet data types (Async,Control,QoS)
+ * @buffer_size_packet: Maximum buffer size supported by this channel
+ * for packet data types (Async,Control,QoS)
+ * @num_buffer_streaming: Maximum number of buffers supported by this channel
+ * for streaming data types (Sync,AV Packetized)
+ * @buffer_size_streaming: Maximum buffer size supported by this channel
+ * for streaming data types (Sync,AV Packetized)
+ * @name_suffix: Optional suffix providean by an HDM that is attached to the
+ * regular channel name.
+ *
+ * Describes the capabilities of a MostCore channel like supported Data Types
+ * and directions. This information is provided by an HDM for the MostCore.
+ *
+ * The Core creates read only sysfs attribute files in
+ * /sys/devices/virtual/most/mostcore/devices/mdev-#/mdev#-ch#/ with the
+ * following attributes:
+ * -available_directions
+ * -available_datatypes
+ * -number_of_packet_buffers
+ * -number_of_stream_buffers
+ * -size_of_packet_buffer
+ * -size_of_stream_buffer
+ * where content of each file is a string with all supported properties of this
+ * very channel attribute.
+ */
+struct most_channel_capability {
+ u16 direction;
+ u16 data_type;
+ u16 num_buffers_packet;
+ u16 buffer_size_packet;
+ u16 num_buffers_streaming;
+ u16 buffer_size_streaming;
+ char *name_suffix;
+};
+
+/**
+ * struct most_channel_config - stores channel configuration
+ * @direction: direction of the channel
+ * @data_type: data type travelling over this channel
+ * @num_buffers: number of buffers
+ * @buffer_size: size of a buffer for AIM.
+ * Buffer size may be cutted down by HDM in a configure callback
+ * to match to a given interface and channel type.
+ * @extra_len: additional buffer space for internal HDM purposes like padding.
+ * May be set by HDM in a configure callback if needed.
+ * @subbuffer_size: size of a subbuffer
+ * @packets_per_xact: number of MOST frames that are packet inside one USB
+ * packet. This is USB specific
+ *
+ * Describes the configuration for a MostCore channel. This information is
+ * provided from the MostCore to a HDM (like the Medusa PCIe Interface) as a
+ * parameter of the "configure" function call.
+ */
+struct most_channel_config {
+ enum most_channel_direction direction;
+ enum most_channel_data_type data_type;
+ u16 num_buffers;
+ u16 buffer_size;
+ u16 extra_len;
+ u16 subbuffer_size;
+ u16 packets_per_xact;
+};
+
+/*
+ * struct mbo - MOST Buffer Object.
+ * @context: context for core completion handler
+ * @priv: private data for HDM
+ *
+ * public: documented fields that are used for the communications
+ * between MostCore and HDMs
+ *
+ * @list: list head for use by the mbo's current owner
+ * @ifp: (in) associated interface instance
+ * @hdm_channel_id: (in) HDM channel instance
+ * @virt_address: (in) kernel virtual address of the buffer
+ * @bus_address: (in) bus address of the buffer
+ * @buffer_length: (in) buffer payload length
+ * @processed_length: (out) processed length
+ * @status: (out) transfer status
+ * @complete: (in) completion routine
+ *
+ * The MostCore allocates and initializes the MBO.
+ *
+ * The HDM receives MBO for transfer from MostCore with the call to enqueue().
+ * The HDM copies the data to- or from the buffer depending on configured
+ * channel direction, set "processed_length" and "status" and completes
+ * the transfer procedure by calling the completion routine.
+ *
+ * At the end the MostCore deallocates the MBO or recycles it for further
+ * transfers for the same or different HDM.
+ *
+ * Directions of usage:
+ * The core driver should never access any MBO fields (even if marked
+ * as "public") while the MBO is owned by an HDM. The ownership starts with
+ * the call of enqueue() and ends with the call of its complete() routine.
+ *
+ * II.
+ * Every HDM attached to the core driver _must_ ensure that it returns any MBO
+ * it owns (due to a previous call to enqueue() by the core driver) before it
+ * de-registers an interface or gets unloaded from the kernel. If this direction
+ * is violated memory leaks will occur, since the core driver does _not_ track
+ * MBOs it is currently not in control of.
+ *
+ */
+struct mbo {
+ void *context;
+ void *priv;
+ struct list_head list;
+ struct most_interface *ifp;
+ u16 hdm_channel_id;
+ void *virt_address;
+ dma_addr_t bus_address;
+ u16 buffer_length;
+ u16 processed_length;
+ enum mbo_status_flags status;
+ void (*complete)(struct mbo *);
+};
+
+/**
+ * Interface instance description.
+ *
+ * Describes one instance of an interface like Medusa PCIe or Vantage USB.
+ * This structure is allocated and initialized in the HDM. MostCore may not
+ * modify this structure.
+ *
+ * @interface Interface type. \sa most_interface_type.
+ * @description PRELIMINARY.
+ * Unique description of the device instance from point of view of the
+ * interface in free text form (ASCII).
+ * It may be a hexadecimal presentation of the memory address for the MediaLB
+ * IP or USB device ID with USB properties for USB interface, etc.
+ * @num_channels Number of channels and size of the channel_vector.
+ * @channel_vector Properties of the channels.
+ * Array index represents channel ID by the driver.
+ * @configure Callback to change data type for the channel of the
+ * interface instance. May be zero if the instance of the interface is not
+ * configurable. Parameter channel_config describes direction and data
+ * type for the channel, configured by the higher level. The content of
+ * @enqueue Delivers MBO to the HDM for processing.
+ * After HDM completes Rx- or Tx- operation the processed MBO shall
+ * be returned back to the MostCore using completion routine.
+ * The reason to get the MBO delivered from the MostCore after the channel
+ * is poisoned is the re-opening of the channel by the application.
+ * In this case the HDM shall hold MBOs and service the channel as usual.
+ * The HDM must be able to hold at least one MBO for each channel.
+ * The callback returns a negative value on error, otherwise 0.
+ * @poison_channel Informs HDM about closing the channel. The HDM shall
+ * cancel all transfers and synchronously or asynchronously return
+ * all enqueued for this channel MBOs using the completion routine.
+ * The callback returns a negative value on error, otherwise 0.
+ * @request_netinfo: triggers retrieving of network info from the HDM by
+ * means of "Message exchange over MDP/MEP"
+ * @priv Private field used by mostcore to store context information.
+ */
+struct most_interface {
+ struct module *mod;
+ enum most_interface_type interface;
+ const char *description;
+ int num_channels;
+ struct most_channel_capability *channel_vector;
+ int (*configure)(struct most_interface *iface, int channel_idx,
+ struct most_channel_config *channel_config);
+ int (*enqueue)(struct most_interface *iface, int channel_idx,
+ struct mbo *mbo);
+ int (*poison_channel)(struct most_interface *iface, int channel_idx);
+ void (*request_netinfo)(struct most_interface *iface, int channel_idx);
+ void *priv;
+};
+
+/**
+ * struct most_aim - identifies MOST device driver to mostcore
+ * @name: Driver name
+ * @probe_channel: function for core to notify driver about channel connection
+ * @disconnect_channel: notification that a certain channel isn't available anymore
+ * @rx_completion: completion handler for received packets
+ * @tx_completion: completion handler for transmitted packets
+ * @context: context pointer to be used by mostcore
+ */
+struct most_aim {
+ const char *name;
+ int (*probe_channel)(struct most_interface *iface, int channel_idx,
+ struct most_channel_config *cfg,
+ struct kobject *parent, char *name);
+ int (*disconnect_channel)(struct most_interface *iface,
+ int channel_idx);
+ int (*rx_completion)(struct mbo *mbo);
+ int (*tx_completion)(struct most_interface *iface, int channel_idx);
+ void *context;
+};
+
+/**
+ * most_register_interface - Registers instance of the interface.
+ * @iface: Pointer to the interface instance description.
+ *
+ * Returns a pointer to the kobject of the generated instance.
+ *
+ * Note: HDM has to ensure that any reference held on the kobj is
+ * released before deregistering the interface.
+ */
+struct kobject *most_register_interface(struct most_interface *iface);
+
+/**
+ * Deregisters instance of the interface.
+ * @intf_instance Pointer to the interface instance description.
+ */
+void most_deregister_interface(struct most_interface *iface);
+int most_submit_mbo(struct mbo *mbo);
+
+/**
+ * most_stop_enqueue - prevents core from enqueing MBOs
+ * @iface: pointer to interface
+ * @channel_idx: channel index
+ */
+void most_stop_enqueue(struct most_interface *iface, int channel_idx);
+
+/**
+ * most_resume_enqueue - allow core to enqueue MBOs again
+ * @iface: pointer to interface
+ * @channel_idx: channel index
+ *
+ * This clears the enqueue halt flag and enqueues all MBOs currently
+ * in wait fifo.
+ */
+void most_resume_enqueue(struct most_interface *iface, int channel_idx);
+int most_register_aim(struct most_aim *aim);
+int most_deregister_aim(struct most_aim *aim);
+struct mbo *most_get_mbo(struct most_interface *iface, int channel_idx);
+void most_put_mbo(struct mbo *mbo);
+int most_start_channel(struct most_interface *iface, int channel_idx);
+int most_stop_channel(struct most_interface *iface, int channel_idx);
+
+
+#endif /* MOST_CORE_H_ */
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c
index 7285c64..ad30ce4 100644
--- a/drivers/staging/mt29f_spinand/mt29f_spinand.c
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c
@@ -948,7 +948,6 @@
static struct spi_driver spinand_driver = {
.driver = {
.name = "mt29f",
- .bus = &spi_bus_type,
.owner = THIS_MODULE,
.of_match_table = spinand_dt,
},
diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.h b/drivers/staging/mt29f_spinand/mt29f_spinand.h
index 7f2c24d..6c8e413 100644
--- a/drivers/staging/mt29f_spinand/mt29f_spinand.h
+++ b/drivers/staging/mt29f_spinand/mt29f_spinand.h
@@ -101,7 +101,7 @@
u8 *rx_buf; /* Rx buf */
};
-extern int spinand_mtd(struct mtd_info *mtd);
-extern void spinand_mtd_release(struct mtd_info *mtd);
+int spinand_mtd(struct mtd_info *mtd);
+void spinand_mtd_release(struct mtd_info *mtd);
#endif /* __LINUX_MTD_SPI_NAND_H */
diff --git a/drivers/staging/netlogic/platform_net.c b/drivers/staging/netlogic/platform_net.c
index 77c3c35..e914147 100644
--- a/drivers/staging/netlogic/platform_net.c
+++ b/drivers/staging/netlogic/platform_net.c
@@ -163,7 +163,7 @@
switch (nlm_prom_info.board_major_version) {
case 12:
/* first block RGMII or XAUI, use RGMII */
- ndata0.phy_interface = PHY_INTERFACE_MODE_RGMII,
+ ndata0.phy_interface = PHY_INTERFACE_MODE_RGMII;
ndata0.tx_stnid[0] = FMN_STNID_GMAC0_TX0;
ndata0.phy_addr[0] = 0;
diff --git a/drivers/staging/netlogic/xlr_net.h b/drivers/staging/netlogic/xlr_net.h
index 13e03f0..2f65ec5 100644
--- a/drivers/staging/netlogic/xlr_net.h
+++ b/drivers/staging/netlogic/xlr_net.h
@@ -1102,4 +1102,4 @@
u64 *class_3_spill;
};
-extern void xlr_set_gmac_speed(struct xlr_net_priv *priv);
+void xlr_set_gmac_speed(struct xlr_net_priv *priv);
diff --git a/drivers/staging/nvec/nvec.h b/drivers/staging/nvec/nvec.h
index e271375..2ec9de9 100644
--- a/drivers/staging/nvec/nvec.h
+++ b/drivers/staging/nvec/nvec.h
@@ -165,19 +165,18 @@
int state;
};
-extern int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
- short size);
+int nvec_write_async(struct nvec_chip *nvec, const unsigned char *data,
+ short size);
-extern struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec,
- const unsigned char *data, short size);
+struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec,
+ const unsigned char *data, short size);
-extern int nvec_register_notifier(struct nvec_chip *nvec,
- struct notifier_block *nb,
- unsigned int events);
+int nvec_register_notifier(struct nvec_chip *nvec,
+ struct notifier_block *nb,
+ unsigned int events);
-extern int nvec_unregister_notifier(struct nvec_chip *dev,
- struct notifier_block *nb);
+int nvec_unregister_notifier(struct nvec_chip *dev, struct notifier_block *nb);
-extern void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg);
+void nvec_msg_free(struct nvec_chip *nvec, struct nvec_msg *msg);
#endif
diff --git a/drivers/staging/octeon/ethernet-mdio.h b/drivers/staging/octeon/ethernet-mdio.h
index a530b55..5ed8483 100644
--- a/drivers/staging/octeon/ethernet-mdio.h
+++ b/drivers/staging/octeon/ethernet-mdio.h
@@ -25,7 +25,7 @@
extern const struct ethtool_ops cvm_oct_ethtool_ops;
-extern void octeon_mdiobus_force_mod_depencency(void);
+void octeon_mdiobus_force_mod_depencency(void);
int cvm_oct_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
int cvm_oct_phy_setup_device(struct net_device *dev);
diff --git a/drivers/staging/octeon/ethernet-rgmii.c b/drivers/staging/octeon/ethernet-rgmii.c
index beb7aac..51dcb61 100644
--- a/drivers/staging/octeon/ethernet-rgmii.c
+++ b/drivers/staging/octeon/ethernet-rgmii.c
@@ -118,9 +118,10 @@
}
/* Since the 10Mbps preamble workaround is allowed we need to enable
- preamble checking, FCS stripping, and clear error bits on
- every speed change. If errors occur during 10Mbps operation
- the above code will change this stuff */
+ * preamble checking, FCS stripping, and clear error bits on
+ * every speed change. If errors occur during 10Mbps operation
+ * the above code will change this stuff
+ */
cvm_oct_set_hw_preamble(priv, true);
if (priv->phydev == NULL) {
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index 7c1c1b0..e2df041 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -396,10 +396,12 @@
/* Check if we can use the hardware checksumming */
if ((skb->protocol == htons(ETH_P_IP)) &&
- (ip_hdr(skb)->version == 4) && (ip_hdr(skb)->ihl == 5) &&
- ((ip_hdr(skb)->frag_off == 0) || (ip_hdr(skb)->frag_off == htons(1 << 14)))
- && ((ip_hdr(skb)->protocol == IPPROTO_TCP)
- || (ip_hdr(skb)->protocol == IPPROTO_UDP))) {
+ (ip_hdr(skb)->version == 4) &&
+ (ip_hdr(skb)->ihl == 5) &&
+ ((ip_hdr(skb)->frag_off == 0) ||
+ (ip_hdr(skb)->frag_off == htons(1 << 14))) &&
+ ((ip_hdr(skb)->protocol == IPPROTO_TCP) ||
+ (ip_hdr(skb)->protocol == IPPROTO_UDP))) {
/* Use hardware checksum calc */
pko_command.s.ipoffp1 = sizeof(struct ethhdr) + 1;
}
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index f9dba23..0718b35 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -157,6 +157,7 @@
#ifdef __LITTLE_ENDIAN
{
union cvmx_ipd_ctl_status ipd_ctl_status;
+
ipd_ctl_status.u64 = cvmx_read_csr(CVMX_IPD_CTL_STATUS);
ipd_ctl_status.s.pkt_lend = 1;
ipd_ctl_status.s.wqe_lend = 1;
diff --git a/drivers/staging/octeon/octeon-ethernet.h b/drivers/staging/octeon/octeon-ethernet.h
index e9d3e9a..a242c70 100644
--- a/drivers/staging/octeon/octeon-ethernet.h
+++ b/drivers/staging/octeon/octeon-ethernet.h
@@ -53,20 +53,20 @@
int cvm_oct_free_work(void *work_queue_entry);
-extern int cvm_oct_rgmii_init(struct net_device *dev);
-extern void cvm_oct_rgmii_uninit(struct net_device *dev);
-extern int cvm_oct_rgmii_open(struct net_device *dev);
+int cvm_oct_rgmii_init(struct net_device *dev);
+void cvm_oct_rgmii_uninit(struct net_device *dev);
+int cvm_oct_rgmii_open(struct net_device *dev);
-extern int cvm_oct_sgmii_init(struct net_device *dev);
-extern int cvm_oct_sgmii_open(struct net_device *dev);
+int cvm_oct_sgmii_init(struct net_device *dev);
+int cvm_oct_sgmii_open(struct net_device *dev);
-extern int cvm_oct_spi_init(struct net_device *dev);
-extern void cvm_oct_spi_uninit(struct net_device *dev);
-extern int cvm_oct_xaui_init(struct net_device *dev);
-extern int cvm_oct_xaui_open(struct net_device *dev);
+int cvm_oct_spi_init(struct net_device *dev);
+void cvm_oct_spi_uninit(struct net_device *dev);
+int cvm_oct_xaui_init(struct net_device *dev);
+int cvm_oct_xaui_open(struct net_device *dev);
-extern int cvm_oct_common_init(struct net_device *dev);
-extern void cvm_oct_common_uninit(struct net_device *dev);
+int cvm_oct_common_init(struct net_device *dev);
+void cvm_oct_common_uninit(struct net_device *dev);
void cvm_oct_adjust_link(struct net_device *dev);
int cvm_oct_common_stop(struct net_device *dev);
int cvm_oct_common_open(struct net_device *dev,
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h
index aec9895..d06e19d 100644
--- a/drivers/staging/olpc_dcon/olpc_dcon.h
+++ b/drivers/staging/olpc_dcon/olpc_dcon.h
@@ -98,7 +98,7 @@
#include <linux/interrupt.h>
-extern irqreturn_t dcon_interrupt(int irq, void *id);
+irqreturn_t dcon_interrupt(int irq, void *id);
#ifdef CONFIG_FB_OLPC_DCON_1
extern struct dcon_platform_data dcon_pdata_xo_1;
diff --git a/drivers/staging/ozwpan/Kconfig b/drivers/staging/ozwpan/Kconfig
deleted file mode 100644
index 7904cae..0000000
--- a/drivers/staging/ozwpan/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-config USB_WPAN_HCD
- tristate "USB over WiFi Host Controller"
- depends on USB && NET
- help
- A driver for USB Host Controllers that are compatible with
- Ozmo Devices USB over WiFi technology.
-
- To compile this driver a module, choose M here: the module
- will be called "ozwpan".
diff --git a/drivers/staging/ozwpan/Makefile b/drivers/staging/ozwpan/Makefile
deleted file mode 100644
index 29529c1..0000000
--- a/drivers/staging/ozwpan/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-# -----------------------------------------------------------------------------
-# Copyright (c) 2011 Ozmo Inc
-# Released under the GNU General Public License Version 2 (GPLv2).
-# -----------------------------------------------------------------------------
-
-obj-$(CONFIG_USB_WPAN_HCD) += ozwpan.o
-ozwpan-y := \
- ozmain.o \
- ozpd.o \
- ozusbsvc.o \
- ozusbsvc1.o \
- ozhcd.o \
- ozeltbuf.o \
- ozproto.o \
- ozcdev.o \
- ozurbparanoia.o
diff --git a/drivers/staging/ozwpan/README b/drivers/staging/ozwpan/README
deleted file mode 100644
index 7c055ec..0000000
--- a/drivers/staging/ozwpan/README
+++ /dev/null
@@ -1,25 +0,0 @@
-OZWPAN USB Host Controller Driver
----------------------------------
-This driver is a USB HCD driver that does not have an associated a physical
-device but instead uses Wi-Fi to communicate with the wireless peripheral.
-The USB requests are converted into a layer 2 network protocol and transmitted
-on the network using an ethertype (0x892e) regestered to Ozmo Device Inc.
-This driver is compatible with existing wireless devices that use Ozmo Devices
-technology.
-
-To operate the driver must be bound to a suitable network interface. This can
-be done when the module is loaded (specifying the name of the network interface
-as a parameter - e.g. 'insmod ozwpan g_net_dev=go0') or can be bound after
-loading using an ioctl call. See the ozappif.h file and the ioctls
-OZ_IOCTL_ADD_BINDING and OZ_IOCTL_REMOVE_BINDING.
-
-The devices connect to the host use Wi-Fi Direct so a network card that supports
-Wi-Fi direct is required. A recent version (0.8.x or later) version of the
-wpa_supplicant can be used to setup the network interface to create a persistent
-autonomous group (for older pre-WFD peripherals) or put in a listen state to
-allow group negotiation to occur for more recent devices that support WFD.
-
-The protocol used over the network does not directly mimic the USB bus
-transactions as this would be rather busy and inefficient. Instead the chapter 9
-requests are converted into a request/response pair of messages. (See
-ozprotocol.h for data structures used in the protocol).
diff --git a/drivers/staging/ozwpan/TODO b/drivers/staging/ozwpan/TODO
deleted file mode 100644
index f32c1c0..0000000
--- a/drivers/staging/ozwpan/TODO
+++ /dev/null
@@ -1,14 +0,0 @@
-TODO:
- - Convert event tracing code to in-kernel tracing infrastructure
- - Check for remaining ioctl & check if that can be converted into
- sysfs entries
- - Convert debug prints to appropriate dev_debug or something better
- - Modify Kconfig to add CONFIG option for enabling/disabling event
- tracing.
- - check USB HCD implementation is complete and correct.
- - code review by USB developer community.
- - testing with as many devices as possible.
-
-Please send any patches for this driver to
-Shigekatsu Tateno <shigekatsu.tateno@atmel.com>
-and Greg Kroah-Hartman <gregkh@linuxfoundation.org>.
diff --git a/drivers/staging/ozwpan/ozappif.h b/drivers/staging/ozwpan/ozappif.h
deleted file mode 100644
index ea1b271..0000000
--- a/drivers/staging/ozwpan/ozappif.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZAPPIF_H
-#define _OZAPPIF_H
-
-#define OZ_IOCTL_MAGIC 0xf4
-
-struct oz_mac_addr {
- __u8 a[6];
-};
-
-#define OZ_MAX_PDS 8
-
-struct oz_pd_list {
- __u32 count;
- struct oz_mac_addr addr[OZ_MAX_PDS];
-};
-
-#define OZ_MAX_BINDING_LEN 32
-
-struct oz_binding_info {
- char name[OZ_MAX_BINDING_LEN];
-};
-
-#define OZ_IOCTL_GET_PD_LIST _IOR(OZ_IOCTL_MAGIC, 0, struct oz_pd_list)
-#define OZ_IOCTL_SET_ACTIVE_PD _IOW(OZ_IOCTL_MAGIC, 1, struct oz_mac_addr)
-#define OZ_IOCTL_GET_ACTIVE_PD _IOR(OZ_IOCTL_MAGIC, 2, struct oz_mac_addr)
-#define OZ_IOCTL_ADD_BINDING _IOW(OZ_IOCTL_MAGIC, 3, struct oz_binding_info)
-#define OZ_IOCTL_REMOVE_BINDING _IOW(OZ_IOCTL_MAGIC, 4, struct oz_binding_info)
-#define OZ_IOCTL_MAX 5
-
-
-#endif /* _OZAPPIF_H */
diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c
deleted file mode 100644
index da0e1fd..0000000
--- a/drivers/staging/ozwpan/ozcdev.c
+++ /dev/null
@@ -1,554 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#include <linux/module.h>
-#include <linux/fs.h>
-#include <linux/cdev.h>
-#include <linux/uaccess.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozappif.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozcdev.h"
-
-#define OZ_RD_BUF_SZ 256
-struct oz_cdev {
- dev_t devnum;
- struct cdev cdev;
- wait_queue_head_t rdq;
- spinlock_t lock;
- u8 active_addr[ETH_ALEN];
- struct oz_pd *active_pd;
-};
-
-/* Per PD context for the serial service stored in the PD. */
-struct oz_serial_ctx {
- atomic_t ref_count;
- u8 tx_seq_num;
- u8 rx_seq_num;
- u8 rd_buf[OZ_RD_BUF_SZ];
- int rd_in;
- int rd_out;
-};
-
-static struct oz_cdev g_cdev;
-static struct class *g_oz_class;
-
-/*
- * Context: process and softirq
- */
-static struct oz_serial_ctx *oz_cdev_claim_ctx(struct oz_pd *pd)
-{
- struct oz_serial_ctx *ctx;
-
- spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
- ctx = (struct oz_serial_ctx *) pd->app_ctx[OZ_APPID_SERIAL];
- if (ctx)
- atomic_inc(&ctx->ref_count);
- spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
- return ctx;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_cdev_release_ctx(struct oz_serial_ctx *ctx)
-{
- if (atomic_dec_and_test(&ctx->ref_count)) {
- oz_dbg(ON, "Dealloc serial context\n");
- kfree(ctx);
- }
-}
-
-/*
- * Context: process
- */
-static int oz_cdev_open(struct inode *inode, struct file *filp)
-{
- struct oz_cdev *dev = container_of(inode->i_cdev, struct oz_cdev, cdev);
-
- oz_dbg(ON, "major = %d minor = %d\n", imajor(inode), iminor(inode));
-
- filp->private_data = dev;
- return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_cdev_release(struct inode *inode, struct file *filp)
-{
- return 0;
-}
-
-/*
- * Context: process
- */
-static ssize_t oz_cdev_read(struct file *filp, char __user *buf, size_t count,
- loff_t *fpos)
-{
- int n;
- int ix;
-
- struct oz_pd *pd;
- struct oz_serial_ctx *ctx;
-
- spin_lock_bh(&g_cdev.lock);
- pd = g_cdev.active_pd;
- if (pd)
- oz_pd_get(pd);
- spin_unlock_bh(&g_cdev.lock);
- if (pd == NULL)
- return -1;
- ctx = oz_cdev_claim_ctx(pd);
- if (ctx == NULL)
- goto out2;
- n = ctx->rd_in - ctx->rd_out;
- if (n < 0)
- n += OZ_RD_BUF_SZ;
- if (count > n)
- count = n;
- ix = ctx->rd_out;
- n = OZ_RD_BUF_SZ - ix;
- if (n > count)
- n = count;
- if (copy_to_user(buf, &ctx->rd_buf[ix], n)) {
- count = 0;
- goto out1;
- }
- ix += n;
- if (ix == OZ_RD_BUF_SZ)
- ix = 0;
- if (n < count) {
- if (copy_to_user(&buf[n], ctx->rd_buf, count-n)) {
- count = 0;
- goto out1;
- }
- ix = count-n;
- }
- ctx->rd_out = ix;
-out1:
- oz_cdev_release_ctx(ctx);
-out2:
- oz_pd_put(pd);
- return count;
-}
-
-/*
- * Context: process
- */
-static ssize_t oz_cdev_write(struct file *filp, const char __user *buf,
- size_t count, loff_t *fpos)
-{
- struct oz_pd *pd;
- struct oz_elt_buf *eb;
- struct oz_elt_info *ei;
- struct oz_elt *elt;
- struct oz_app_hdr *app_hdr;
- struct oz_serial_ctx *ctx;
-
- if (count > sizeof(ei->data) - sizeof(*elt) - sizeof(*app_hdr))
- return -EINVAL;
-
- spin_lock_bh(&g_cdev.lock);
- pd = g_cdev.active_pd;
- if (pd)
- oz_pd_get(pd);
- spin_unlock_bh(&g_cdev.lock);
- if (pd == NULL)
- return -ENXIO;
- if (!(pd->state & OZ_PD_S_CONNECTED))
- return -EAGAIN;
- eb = &pd->elt_buff;
- ei = oz_elt_info_alloc(eb);
- if (ei == NULL) {
- count = 0;
- goto out;
- }
- elt = (struct oz_elt *)ei->data;
- app_hdr = (struct oz_app_hdr *)(elt+1);
- elt->length = sizeof(struct oz_app_hdr) + count;
- elt->type = OZ_ELT_APP_DATA;
- ei->app_id = OZ_APPID_SERIAL;
- ei->length = elt->length + sizeof(struct oz_elt);
- app_hdr->app_id = OZ_APPID_SERIAL;
- if (copy_from_user(app_hdr+1, buf, count))
- goto out;
- spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
- ctx = (struct oz_serial_ctx *) pd->app_ctx[OZ_APPID_SERIAL];
- if (ctx) {
- app_hdr->elt_seq_num = ctx->tx_seq_num++;
- if (ctx->tx_seq_num == 0)
- ctx->tx_seq_num = 1;
- spin_lock(&eb->lock);
- if (oz_queue_elt_info(eb, 0, 0, ei) == 0)
- ei = NULL;
- spin_unlock(&eb->lock);
- }
- spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
-out:
- if (ei) {
- count = 0;
- spin_lock_bh(&eb->lock);
- oz_elt_info_free(eb, ei);
- spin_unlock_bh(&eb->lock);
- }
- oz_pd_put(pd);
- return count;
-}
-
-/*
- * Context: process
- */
-static int oz_set_active_pd(const u8 *addr)
-{
- int rc = 0;
- struct oz_pd *pd;
- struct oz_pd *old_pd;
-
- pd = oz_pd_find(addr);
- if (pd) {
- spin_lock_bh(&g_cdev.lock);
- ether_addr_copy(g_cdev.active_addr, addr);
- old_pd = g_cdev.active_pd;
- g_cdev.active_pd = pd;
- spin_unlock_bh(&g_cdev.lock);
- if (old_pd)
- oz_pd_put(old_pd);
- } else {
- if (is_zero_ether_addr(addr)) {
- spin_lock_bh(&g_cdev.lock);
- pd = g_cdev.active_pd;
- g_cdev.active_pd = NULL;
- memset(g_cdev.active_addr, 0,
- sizeof(g_cdev.active_addr));
- spin_unlock_bh(&g_cdev.lock);
- if (pd)
- oz_pd_put(pd);
- } else {
- rc = -1;
- }
- }
- return rc;
-}
-
-/*
- * Context: process
- */
-static long oz_cdev_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg)
-{
- int rc = 0;
-
- if (_IOC_TYPE(cmd) != OZ_IOCTL_MAGIC)
- return -ENOTTY;
- if (_IOC_NR(cmd) > OZ_IOCTL_MAX)
- return -ENOTTY;
- if (_IOC_DIR(cmd) & _IOC_READ)
- rc = !access_ok(VERIFY_WRITE, (void __user *)arg,
- _IOC_SIZE(cmd));
- else if (_IOC_DIR(cmd) & _IOC_WRITE)
- rc = !access_ok(VERIFY_READ, (void __user *)arg,
- _IOC_SIZE(cmd));
- if (rc)
- return -EFAULT;
- switch (cmd) {
- case OZ_IOCTL_GET_PD_LIST: {
- struct oz_pd_list list;
-
- oz_dbg(ON, "OZ_IOCTL_GET_PD_LIST\n");
- memset(&list, 0, sizeof(list));
- list.count = oz_get_pd_list(list.addr, OZ_MAX_PDS);
- if (copy_to_user((void __user *)arg, &list,
- sizeof(list)))
- return -EFAULT;
- }
- break;
- case OZ_IOCTL_SET_ACTIVE_PD: {
- u8 addr[ETH_ALEN];
-
- oz_dbg(ON, "OZ_IOCTL_SET_ACTIVE_PD\n");
- if (copy_from_user(addr, (void __user *)arg, ETH_ALEN))
- return -EFAULT;
- rc = oz_set_active_pd(addr);
- }
- break;
- case OZ_IOCTL_GET_ACTIVE_PD: {
- u8 addr[ETH_ALEN];
-
- oz_dbg(ON, "OZ_IOCTL_GET_ACTIVE_PD\n");
- spin_lock_bh(&g_cdev.lock);
- ether_addr_copy(addr, g_cdev.active_addr);
- spin_unlock_bh(&g_cdev.lock);
- if (copy_to_user((void __user *)arg, addr, ETH_ALEN))
- return -EFAULT;
- }
- break;
- case OZ_IOCTL_ADD_BINDING:
- case OZ_IOCTL_REMOVE_BINDING: {
- struct oz_binding_info b;
-
- if (copy_from_user(&b, (void __user *)arg,
- sizeof(struct oz_binding_info))) {
- return -EFAULT;
- }
- /* Make sure name is null terminated. */
- b.name[OZ_MAX_BINDING_LEN-1] = 0;
- if (cmd == OZ_IOCTL_ADD_BINDING)
- oz_binding_add(b.name);
- else
- oz_binding_remove(b.name);
- }
- break;
- }
- return rc;
-}
-
-/*
- * Context: process
- */
-static unsigned int oz_cdev_poll(struct file *filp, poll_table *wait)
-{
- unsigned int ret = 0;
- struct oz_cdev *dev = filp->private_data;
-
- oz_dbg(ON, "Poll called wait = %p\n", wait);
- spin_lock_bh(&dev->lock);
- if (dev->active_pd) {
- struct oz_serial_ctx *ctx = oz_cdev_claim_ctx(dev->active_pd);
-
- if (ctx) {
- if (ctx->rd_in != ctx->rd_out)
- ret |= POLLIN | POLLRDNORM;
- oz_cdev_release_ctx(ctx);
- }
- }
- spin_unlock_bh(&dev->lock);
- if (wait)
- poll_wait(filp, &dev->rdq, wait);
- return ret;
-}
-
-/*
- */
-static const struct file_operations oz_fops = {
- .owner = THIS_MODULE,
- .open = oz_cdev_open,
- .release = oz_cdev_release,
- .read = oz_cdev_read,
- .write = oz_cdev_write,
- .unlocked_ioctl = oz_cdev_ioctl,
- .poll = oz_cdev_poll
-};
-
-/*
- * Context: process
- */
-int oz_cdev_register(void)
-{
- int err;
- struct device *dev;
-
- memset(&g_cdev, 0, sizeof(g_cdev));
- err = alloc_chrdev_region(&g_cdev.devnum, 0, 1, "ozwpan");
- if (err < 0)
- return err;
- oz_dbg(ON, "Alloc dev number %d:%d\n",
- MAJOR(g_cdev.devnum), MINOR(g_cdev.devnum));
- cdev_init(&g_cdev.cdev, &oz_fops);
- g_cdev.cdev.owner = THIS_MODULE;
- spin_lock_init(&g_cdev.lock);
- init_waitqueue_head(&g_cdev.rdq);
- err = cdev_add(&g_cdev.cdev, g_cdev.devnum, 1);
- if (err < 0) {
- oz_dbg(ON, "Failed to add cdev\n");
- goto unregister;
- }
- g_oz_class = class_create(THIS_MODULE, "ozmo_wpan");
- if (IS_ERR(g_oz_class)) {
- oz_dbg(ON, "Failed to register ozmo_wpan class\n");
- err = PTR_ERR(g_oz_class);
- goto delete;
- }
- dev = device_create(g_oz_class, NULL, g_cdev.devnum, NULL, "ozwpan");
- if (IS_ERR(dev)) {
- oz_dbg(ON, "Failed to create sysfs entry for cdev\n");
- err = PTR_ERR(dev);
- goto delete;
- }
- return 0;
-
-delete:
- cdev_del(&g_cdev.cdev);
-unregister:
- unregister_chrdev_region(g_cdev.devnum, 1);
- return err;
-}
-
-/*
- * Context: process
- */
-int oz_cdev_deregister(void)
-{
- cdev_del(&g_cdev.cdev);
- unregister_chrdev_region(g_cdev.devnum, 1);
- if (g_oz_class) {
- device_destroy(g_oz_class, g_cdev.devnum);
- class_destroy(g_oz_class);
- }
- return 0;
-}
-
-/*
- * Context: process
- */
-int oz_cdev_init(void)
-{
- oz_app_enable(OZ_APPID_SERIAL, 1);
- return 0;
-}
-
-/*
- * Context: process
- */
-void oz_cdev_term(void)
-{
- oz_app_enable(OZ_APPID_SERIAL, 0);
-}
-
-/*
- * Context: softirq-serialized
- */
-int oz_cdev_start(struct oz_pd *pd, int resume)
-{
- struct oz_serial_ctx *ctx;
- struct oz_serial_ctx *old_ctx;
-
- if (resume) {
- oz_dbg(ON, "Serial service resumed\n");
- return 0;
- }
- ctx = kzalloc(sizeof(struct oz_serial_ctx), GFP_ATOMIC);
- if (ctx == NULL)
- return -ENOMEM;
- atomic_set(&ctx->ref_count, 1);
- ctx->tx_seq_num = 1;
- spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
- old_ctx = pd->app_ctx[OZ_APPID_SERIAL];
- if (old_ctx) {
- spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
- kfree(ctx);
- } else {
- pd->app_ctx[OZ_APPID_SERIAL] = ctx;
- spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
- }
- spin_lock(&g_cdev.lock);
- if ((g_cdev.active_pd == NULL) &&
- ether_addr_equal(pd->mac_addr, g_cdev.active_addr)) {
- oz_pd_get(pd);
- g_cdev.active_pd = pd;
- oz_dbg(ON, "Active PD arrived\n");
- }
- spin_unlock(&g_cdev.lock);
- oz_dbg(ON, "Serial service started\n");
- return 0;
-}
-
-/*
- * Context: softirq or process
- */
-void oz_cdev_stop(struct oz_pd *pd, int pause)
-{
- struct oz_serial_ctx *ctx;
-
- if (pause) {
- oz_dbg(ON, "Serial service paused\n");
- return;
- }
- spin_lock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
- ctx = (struct oz_serial_ctx *) pd->app_ctx[OZ_APPID_SERIAL];
- pd->app_ctx[OZ_APPID_SERIAL] = NULL;
- spin_unlock_bh(&pd->app_lock[OZ_APPID_SERIAL]);
- if (ctx)
- oz_cdev_release_ctx(ctx);
- spin_lock(&g_cdev.lock);
- if (pd == g_cdev.active_pd)
- g_cdev.active_pd = NULL;
- else
- pd = NULL;
- spin_unlock(&g_cdev.lock);
- if (pd) {
- oz_pd_put(pd);
- oz_dbg(ON, "Active PD departed\n");
- }
- oz_dbg(ON, "Serial service stopped\n");
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt)
-{
- struct oz_serial_ctx *ctx;
- struct oz_app_hdr *app_hdr;
- u8 *data;
- int len;
- int space;
- int copy_sz;
- int ix;
-
- ctx = oz_cdev_claim_ctx(pd);
- if (ctx == NULL) {
- oz_dbg(ON, "Cannot claim serial context\n");
- return;
- }
-
- app_hdr = (struct oz_app_hdr *)(elt+1);
- /* If sequence number is non-zero then check it is not a duplicate.
- */
- if (app_hdr->elt_seq_num != 0) {
- if (((ctx->rx_seq_num - app_hdr->elt_seq_num) & 0x80) == 0) {
- /* Reject duplicate element. */
- oz_dbg(ON, "Duplicate element:%02x %02x\n",
- app_hdr->elt_seq_num, ctx->rx_seq_num);
- goto out;
- }
- }
- ctx->rx_seq_num = app_hdr->elt_seq_num;
- len = elt->length - sizeof(struct oz_app_hdr);
- data = ((u8 *)(elt+1)) + sizeof(struct oz_app_hdr);
- if (len <= 0)
- goto out;
- space = ctx->rd_out - ctx->rd_in - 1;
- if (space < 0)
- space += OZ_RD_BUF_SZ;
- if (len > space) {
- oz_dbg(ON, "Not enough space:%d %d\n", len, space);
- len = space;
- }
- ix = ctx->rd_in;
- copy_sz = OZ_RD_BUF_SZ - ix;
- if (copy_sz > len)
- copy_sz = len;
- memcpy(&ctx->rd_buf[ix], data, copy_sz);
- len -= copy_sz;
- ix += copy_sz;
- if (ix == OZ_RD_BUF_SZ)
- ix = 0;
- if (len) {
- memcpy(ctx->rd_buf, data+copy_sz, len);
- ix = len;
- }
- ctx->rd_in = ix;
- wake_up(&g_cdev.rdq);
-out:
- oz_cdev_release_ctx(ctx);
-}
diff --git a/drivers/staging/ozwpan/ozcdev.h b/drivers/staging/ozwpan/ozcdev.h
deleted file mode 100644
index dd11935..0000000
--- a/drivers/staging/ozwpan/ozcdev.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZCDEV_H
-#define _OZCDEV_H
-
-int oz_cdev_register(void);
-int oz_cdev_deregister(void);
-int oz_cdev_init(void);
-void oz_cdev_term(void);
-int oz_cdev_start(struct oz_pd *pd, int resume);
-void oz_cdev_stop(struct oz_pd *pd, int pause);
-void oz_cdev_rx(struct oz_pd *pd, struct oz_elt *elt);
-
-#endif /* _OZCDEV_H */
diff --git a/drivers/staging/ozwpan/ozdbg.h b/drivers/staging/ozwpan/ozdbg.h
deleted file mode 100644
index b86a2b7..0000000
--- a/drivers/staging/ozwpan/ozdbg.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * ---------------------------------------------------------------------------*/
-
-#ifndef _OZDBG_H
-#define _OZDBG_H
-
-#define OZ_WANT_DBG 0
-#define OZ_WANT_VERBOSE_DBG 1
-
-#define OZ_DBG_ON 0x0
-#define OZ_DBG_STREAM 0x1
-#define OZ_DBG_URB 0x2
-#define OZ_DBG_CTRL_DETAIL 0x4
-#define OZ_DBG_HUB 0x8
-#define OZ_DBG_RX_FRAMES 0x10
-#define OZ_DBG_TX_FRAMES 0x20
-
-#define OZ_DEFAULT_DBG_MASK \
- ( \
- /* OZ_DBG_STREAM | */ \
- /* OZ_DBG_URB | */ \
- /* OZ_DBG_CTRL_DETAIL | */ \
- OZ_DBG_HUB | \
- /* OZ_DBG_RX_FRAMES | */ \
- /* OZ_DBG_TX_FRAMES | */ \
- 0)
-
-extern unsigned int oz_dbg_mask;
-
-#define oz_want_dbg(mask) \
- ((OZ_WANT_DBG && (OZ_DBG_##mask == OZ_DBG_ON)) || \
- (OZ_WANT_VERBOSE_DBG && (OZ_DBG_##mask & oz_dbg_mask)))
-
-#define oz_dbg(mask, fmt, ...) \
-do { \
- if (oz_want_dbg(mask)) \
- pr_debug(fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define oz_cdev_dbg(cdev, mask, fmt, ...) \
-do { \
- if (oz_want_dbg(mask)) \
- netdev_dbg((cdev)->dev, fmt, ##__VA_ARGS__); \
-} while (0)
-
-#define oz_pd_dbg(pd, mask, fmt, ...) \
-do { \
- if (oz_want_dbg(mask)) \
- pr_debug(fmt, ##__VA_ARGS__); \
-} while (0)
-
-#endif /* _OZDBG_H */
diff --git a/drivers/staging/ozwpan/ozeltbuf.c b/drivers/staging/ozwpan/ozeltbuf.c
deleted file mode 100644
index 01b25da..0000000
--- a/drivers/staging/ozwpan/ozeltbuf.c
+++ /dev/null
@@ -1,252 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-
-/*
- * Context: softirq-serialized
- */
-void oz_elt_buf_init(struct oz_elt_buf *buf)
-{
- memset(buf, 0, sizeof(struct oz_elt_buf));
- INIT_LIST_HEAD(&buf->stream_list);
- INIT_LIST_HEAD(&buf->order_list);
- INIT_LIST_HEAD(&buf->isoc_list);
- spin_lock_init(&buf->lock);
-}
-
-/*
- * Context: softirq or process
- */
-void oz_elt_buf_term(struct oz_elt_buf *buf)
-{
- struct oz_elt_info *ei, *n;
-
- list_for_each_entry_safe(ei, n, &buf->isoc_list, link_order)
- kfree(ei);
- list_for_each_entry_safe(ei, n, &buf->order_list, link_order)
- kfree(ei);
-}
-
-/*
- * Context: softirq or process
- */
-struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf)
-{
- struct oz_elt_info *ei;
-
- ei = kmem_cache_zalloc(oz_elt_info_cache, GFP_ATOMIC);
- if (ei) {
- INIT_LIST_HEAD(&ei->link);
- INIT_LIST_HEAD(&ei->link_order);
- }
- return ei;
-}
-
-/*
- * Precondition: oz_elt_buf.lock must be held.
- * Context: softirq or process
- */
-void oz_elt_info_free(struct oz_elt_buf *buf, struct oz_elt_info *ei)
-{
- if (ei)
- kmem_cache_free(oz_elt_info_cache, ei);
-}
-
-/*------------------------------------------------------------------------------
- * Context: softirq
- */
-void oz_elt_info_free_chain(struct oz_elt_buf *buf, struct list_head *list)
-{
- struct oz_elt_info *ei, *n;
-
- spin_lock_bh(&buf->lock);
- list_for_each_entry_safe(ei, n, list->next, link)
- oz_elt_info_free(buf, ei);
- spin_unlock_bh(&buf->lock);
-}
-
-int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count)
-{
- struct oz_elt_stream *st;
-
- oz_dbg(ON, "%s: (0x%x)\n", __func__, id);
-
- st = kzalloc(sizeof(struct oz_elt_stream), GFP_ATOMIC);
- if (st == NULL)
- return -ENOMEM;
- atomic_set(&st->ref_count, 1);
- st->id = id;
- st->max_buf_count = max_buf_count;
- INIT_LIST_HEAD(&st->elt_list);
- spin_lock_bh(&buf->lock);
- list_add_tail(&st->link, &buf->stream_list);
- spin_unlock_bh(&buf->lock);
- return 0;
-}
-
-int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id)
-{
- struct list_head *e, *n;
- struct oz_elt_stream *st = NULL;
-
- oz_dbg(ON, "%s: (0x%x)\n", __func__, id);
- spin_lock_bh(&buf->lock);
- list_for_each(e, &buf->stream_list) {
- st = list_entry(e, struct oz_elt_stream, link);
- if (st->id == id) {
- list_del(e);
- break;
- }
- st = NULL;
- }
- if (!st) {
- spin_unlock_bh(&buf->lock);
- return -1;
- }
- list_for_each_safe(e, n, &st->elt_list) {
- struct oz_elt_info *ei =
- list_entry(e, struct oz_elt_info, link);
- list_del_init(&ei->link);
- list_del_init(&ei->link_order);
- st->buf_count -= ei->length;
- oz_dbg(STREAM, "Stream down: %d %d %d\n",
- st->buf_count, ei->length, atomic_read(&st->ref_count));
- oz_elt_stream_put(st);
- oz_elt_info_free(buf, ei);
- }
- spin_unlock_bh(&buf->lock);
- oz_elt_stream_put(st);
- return 0;
-}
-
-void oz_elt_stream_get(struct oz_elt_stream *st)
-{
- atomic_inc(&st->ref_count);
-}
-
-void oz_elt_stream_put(struct oz_elt_stream *st)
-{
- if (atomic_dec_and_test(&st->ref_count)) {
- oz_dbg(ON, "Stream destroyed\n");
- kfree(st);
- }
-}
-
-/*
- * Precondition: Element buffer lock must be held.
- * If this function fails the caller is responsible for deallocating the elt
- * info structure.
- */
-int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id,
- struct oz_elt_info *ei)
-{
- struct oz_elt_stream *st = NULL;
- struct list_head *e;
-
- if (id) {
- list_for_each(e, &buf->stream_list) {
- st = list_entry(e, struct oz_elt_stream, link);
- if (st->id == id)
- break;
- }
- if (e == &buf->stream_list) {
- /* Stream specified but stream not known so fail.
- * Caller deallocates element info. */
- return -1;
- }
- }
- if (st) {
- /* If this is an ISOC fixed element that needs a frame number
- * then insert that now. Earlier we stored the unit count in
- * this field.
- */
- struct oz_isoc_fixed *body = (struct oz_isoc_fixed *)
- &ei->data[sizeof(struct oz_elt)];
- if ((body->app_id == OZ_APPID_USB) && (body->type
- == OZ_USB_ENDPOINT_DATA) &&
- (body->format == OZ_DATA_F_ISOC_FIXED)) {
- u8 unit_count = body->frame_number;
-
- body->frame_number = st->frame_number;
- st->frame_number += unit_count;
- }
- /* Claim stream and update accounts */
- oz_elt_stream_get(st);
- ei->stream = st;
- st->buf_count += ei->length;
- /* Add to list in stream. */
- list_add_tail(&ei->link, &st->elt_list);
- oz_dbg(STREAM, "Stream up: %d %d\n", st->buf_count, ei->length);
- /* Check if we have too much buffered for this stream. If so
- * start dropping elements until we are back in bounds.
- */
- while ((st->buf_count > st->max_buf_count) &&
- !list_empty(&st->elt_list)) {
- struct oz_elt_info *ei2 =
- list_first_entry(&st->elt_list,
- struct oz_elt_info, link);
- list_del_init(&ei2->link);
- list_del_init(&ei2->link_order);
- st->buf_count -= ei2->length;
- oz_elt_info_free(buf, ei2);
- oz_elt_stream_put(st);
- }
- }
- list_add_tail(&ei->link_order, isoc ?
- &buf->isoc_list : &buf->order_list);
- return 0;
-}
-
-int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len,
- unsigned max_len, struct list_head *list)
-{
- int count = 0;
- struct list_head *el;
- struct oz_elt_info *ei, *n;
-
- spin_lock_bh(&buf->lock);
- if (isoc)
- el = &buf->isoc_list;
- else
- el = &buf->order_list;
-
- list_for_each_entry_safe(ei, n, el, link_order) {
- if ((*len + ei->length) <= max_len) {
- struct oz_app_hdr *app_hdr = (struct oz_app_hdr *)
- &ei->data[sizeof(struct oz_elt)];
- app_hdr->elt_seq_num = buf->tx_seq_num[ei->app_id]++;
- if (buf->tx_seq_num[ei->app_id] == 0)
- buf->tx_seq_num[ei->app_id] = 1;
- *len += ei->length;
- list_del(&ei->link);
- list_del(&ei->link_order);
- if (ei->stream) {
- ei->stream->buf_count -= ei->length;
- oz_dbg(STREAM, "Stream down: %d %d\n",
- ei->stream->buf_count, ei->length);
- oz_elt_stream_put(ei->stream);
- ei->stream = NULL;
- }
- INIT_LIST_HEAD(&ei->link_order);
- list_add_tail(&ei->link, list);
- count++;
- } else {
- break;
- }
- }
- spin_unlock_bh(&buf->lock);
- return count;
-}
-
-int oz_are_elts_available(struct oz_elt_buf *buf)
-{
- return !list_empty(&buf->order_list);
-}
diff --git a/drivers/staging/ozwpan/ozeltbuf.h b/drivers/staging/ozwpan/ozeltbuf.h
deleted file mode 100644
index f09f5fe..0000000
--- a/drivers/staging/ozwpan/ozeltbuf.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZELTBUF_H
-#define _OZELTBUF_H
-
-#include "ozprotocol.h"
-
-/*-----------------------------------------------------------------------------
- */
-struct oz_pd;
-typedef void (*oz_elt_callback_t)(struct oz_pd *pd, long context);
-
-struct oz_elt_stream {
- struct list_head link;
- struct list_head elt_list;
- atomic_t ref_count;
- unsigned buf_count;
- unsigned max_buf_count;
- u8 frame_number;
- u8 id;
-};
-
-#define OZ_MAX_ELT_PAYLOAD 255
-struct oz_elt_info {
- struct list_head link;
- struct list_head link_order;
- u8 flags;
- u8 app_id;
- oz_elt_callback_t callback;
- long context;
- struct oz_elt_stream *stream;
- u8 data[sizeof(struct oz_elt) + OZ_MAX_ELT_PAYLOAD];
- int length;
-};
-/* Flags values */
-#define OZ_EI_F_MARKED 0x1
-
-struct oz_elt_buf {
- spinlock_t lock;
- struct list_head stream_list;
- struct list_head order_list;
- struct list_head isoc_list;
- u8 tx_seq_num[OZ_NB_APPS];
-};
-
-void oz_elt_buf_init(struct oz_elt_buf *buf);
-void oz_elt_buf_term(struct oz_elt_buf *buf);
-struct oz_elt_info *oz_elt_info_alloc(struct oz_elt_buf *buf);
-void oz_elt_info_free(struct oz_elt_buf *buf, struct oz_elt_info *ei);
-void oz_elt_info_free_chain(struct oz_elt_buf *buf, struct list_head *list);
-int oz_elt_stream_create(struct oz_elt_buf *buf, u8 id, int max_buf_count);
-int oz_elt_stream_delete(struct oz_elt_buf *buf, u8 id);
-void oz_elt_stream_get(struct oz_elt_stream *st);
-void oz_elt_stream_put(struct oz_elt_stream *st);
-int oz_queue_elt_info(struct oz_elt_buf *buf, u8 isoc, u8 id,
- struct oz_elt_info *ei);
-int oz_select_elts_for_tx(struct oz_elt_buf *buf, u8 isoc, unsigned *len,
- unsigned max_len, struct list_head *list);
-int oz_are_elts_available(struct oz_elt_buf *buf);
-
-#endif /* _OZELTBUF_H */
-
diff --git a/drivers/staging/ozwpan/ozhcd.c b/drivers/staging/ozwpan/ozhcd.c
deleted file mode 100644
index 784b5ec..0000000
--- a/drivers/staging/ozwpan/ozhcd.c
+++ /dev/null
@@ -1,2301 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- *
- * This file provides the implementation of a USB host controller device that
- * does not have any associated hardware. Instead the virtual device is
- * connected to the WiFi network and emulates the operation of a USB hcd by
- * receiving and sending network frames.
- * Note:
- * We take great pains to reduce the amount of code where interrupts need to be
- * disabled and in this respect we are different from standard HCD's. In
- * particular we don't want in_irq() code bleeding over to the protocol side of
- * the driver.
- * The troublesome functions are the urb enqueue and dequeue functions both of
- * which can be called in_irq(). So for these functions we put the urbs into a
- * queue and request a tasklet to process them. This means that a spinlock with
- * interrupts disabled must be held for insertion and removal but most code is
- * is in tasklet or soft irq context. The lock that protects this list is called
- * the tasklet lock and serves the purpose of the 'HCD lock' which must be held
- * when calling the following functions.
- * usb_hcd_link_urb_to_ep()
- * usb_hcd_unlink_urb_from_ep()
- * usb_hcd_flush_endpoint()
- * usb_hcd_check_unlink_urb()
- * -----------------------------------------------------------------------------
- */
-#include <linux/platform_device.h>
-#include <linux/usb.h>
-#include <linux/slab.h>
-#include <linux/export.h>
-#include "linux/usb/hcd.h"
-#include <asm/unaligned.h>
-#include "ozdbg.h"
-#include "ozusbif.h"
-#include "ozurbparanoia.h"
-#include "ozhcd.h"
-
-/*
- * Number of units of buffering to capture for an isochronous IN endpoint before
- * allowing data to be indicated up.
- */
-#define OZ_IN_BUFFERING_UNITS 100
-
-/* Name of our platform device.
- */
-#define OZ_PLAT_DEV_NAME "ozwpan"
-
-/*EP0 timeout before ep0 request is again added to TX queue. (13*8 = 98mSec)
- */
-#define EP0_TIMEOUT_COUNTER 13
-
-/* Debounce time HCD driver should wait before unregistering.
- */
-#define OZ_HUB_DEBOUNCE_TIMEOUT 1500
-
-/*
- * Used to link urbs together and also store some status information for each
- * urb.
- * A cache of these are kept in a pool to reduce number of calls to kmalloc.
- */
-struct oz_urb_link {
- struct list_head link;
- struct urb *urb;
- struct oz_port *port;
- u8 req_id;
- u8 ep_num;
- unsigned submit_counter;
-};
-
-static struct kmem_cache *oz_urb_link_cache;
-
-/* Holds state information about a USB endpoint.
- */
-#define OZ_EP_BUFFER_SIZE_ISOC (1024 * 24)
-#define OZ_EP_BUFFER_SIZE_INT 512
-struct oz_endpoint {
- struct list_head urb_list; /* List of oz_urb_link items. */
- struct list_head link; /* For isoc ep, links in to isoc
- lists of oz_port. */
- struct timespec timestamp;
- int credit;
- int credit_ceiling;
- u8 ep_num;
- u8 attrib;
- u8 *buffer;
- int buffer_size;
- int in_ix;
- int out_ix;
- int buffered_units;
- unsigned flags;
- int start_frame;
-};
-
-/* Bits in the flags field. */
-#define OZ_F_EP_BUFFERING 0x1
-#define OZ_F_EP_HAVE_STREAM 0x2
-
-/* Holds state information about a USB interface.
- */
-struct oz_interface {
- unsigned ep_mask;
- u8 alt;
-};
-
-/* Holds state information about an hcd port.
- */
-#define OZ_NB_ENDPOINTS 16
-struct oz_port {
- unsigned flags;
- unsigned status;
- void *hpd;
- struct oz_hcd *ozhcd;
- spinlock_t port_lock;
- u8 bus_addr;
- u8 next_req_id;
- u8 config_num;
- int num_iface;
- struct oz_interface *iface;
- struct oz_endpoint *out_ep[OZ_NB_ENDPOINTS];
- struct oz_endpoint *in_ep[OZ_NB_ENDPOINTS];
- struct list_head isoc_out_ep;
- struct list_head isoc_in_ep;
-};
-
-#define OZ_PORT_F_PRESENT 0x1
-#define OZ_PORT_F_CHANGED 0x2
-#define OZ_PORT_F_DYING 0x4
-
-/* Data structure in the private context area of struct usb_hcd.
- */
-#define OZ_NB_PORTS 8
-struct oz_hcd {
- spinlock_t hcd_lock;
- struct list_head urb_pending_list;
- struct list_head urb_cancel_list;
- struct list_head orphanage;
- int conn_port; /* Port that is currently connecting, -1 if none.*/
- struct oz_port ports[OZ_NB_PORTS];
- uint flags;
- struct usb_hcd *hcd;
-};
-
-/* Bits in flags field.
- */
-#define OZ_HDC_F_SUSPENDED 0x1
-
-/*
- * Static function prototypes.
- */
-static int oz_hcd_start(struct usb_hcd *hcd);
-static void oz_hcd_stop(struct usb_hcd *hcd);
-static void oz_hcd_shutdown(struct usb_hcd *hcd);
-static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
- gfp_t mem_flags);
-static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status);
-static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
- struct usb_host_endpoint *ep);
-static void oz_hcd_endpoint_reset(struct usb_hcd *hcd,
- struct usb_host_endpoint *ep);
-static int oz_hcd_get_frame_number(struct usb_hcd *hcd);
-static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf);
-static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
- u16 windex, char *buf, u16 wlength);
-static int oz_hcd_bus_suspend(struct usb_hcd *hcd);
-static int oz_hcd_bus_resume(struct usb_hcd *hcd);
-static int oz_plat_probe(struct platform_device *dev);
-static int oz_plat_remove(struct platform_device *dev);
-static void oz_plat_shutdown(struct platform_device *dev);
-static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg);
-static int oz_plat_resume(struct platform_device *dev);
-static void oz_urb_process_tasklet(unsigned long unused);
-static int oz_build_endpoints_for_config(struct usb_hcd *hcd,
- struct oz_port *port, struct usb_host_config *config,
- gfp_t mem_flags);
-static void oz_clean_endpoints_for_config(struct usb_hcd *hcd,
- struct oz_port *port);
-static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
- struct oz_port *port,
- struct usb_host_interface *intf, gfp_t mem_flags);
-static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd,
- struct oz_port *port, int if_ix);
-static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
- gfp_t mem_flags);
-static struct oz_urb_link *oz_remove_urb(struct oz_endpoint *ep,
- struct urb *urb);
-static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status);
-
-/*
- * Static external variables.
- */
-static struct platform_device *g_plat_dev;
-static struct oz_hcd *g_ozhcd;
-static DEFINE_SPINLOCK(g_hcdlock); /* Guards g_ozhcd. */
-static const char g_hcd_name[] = "Ozmo WPAN";
-static DEFINE_SPINLOCK(g_tasklet_lock);
-static struct tasklet_struct g_urb_process_tasklet;
-static struct tasklet_struct g_urb_cancel_tasklet;
-static atomic_t g_pending_urbs = ATOMIC_INIT(0);
-static atomic_t g_usb_frame_number = ATOMIC_INIT(0);
-static const struct hc_driver g_oz_hc_drv = {
- .description = g_hcd_name,
- .product_desc = "Ozmo Devices WPAN",
- .hcd_priv_size = sizeof(struct oz_hcd),
- .flags = HCD_USB11,
- .start = oz_hcd_start,
- .stop = oz_hcd_stop,
- .shutdown = oz_hcd_shutdown,
- .urb_enqueue = oz_hcd_urb_enqueue,
- .urb_dequeue = oz_hcd_urb_dequeue,
- .endpoint_disable = oz_hcd_endpoint_disable,
- .endpoint_reset = oz_hcd_endpoint_reset,
- .get_frame_number = oz_hcd_get_frame_number,
- .hub_status_data = oz_hcd_hub_status_data,
- .hub_control = oz_hcd_hub_control,
- .bus_suspend = oz_hcd_bus_suspend,
- .bus_resume = oz_hcd_bus_resume,
-};
-
-static struct platform_driver g_oz_plat_drv = {
- .probe = oz_plat_probe,
- .remove = oz_plat_remove,
- .shutdown = oz_plat_shutdown,
- .suspend = oz_plat_suspend,
- .resume = oz_plat_resume,
- .driver = {
- .name = OZ_PLAT_DEV_NAME,
- },
-};
-
-/*
- * Gets our private context area (which is of type struct oz_hcd) from the
- * usb_hcd structure.
- * Context: any
- */
-static inline struct oz_hcd *oz_hcd_private(struct usb_hcd *hcd)
-{
- return (struct oz_hcd *)hcd->hcd_priv;
-}
-
-/*
- * Searches list of ports to find the index of the one with a specified USB
- * bus address. If none of the ports has the bus address then the connection
- * port is returned, if there is one or -1 otherwise.
- * Context: any
- */
-static int oz_get_port_from_addr(struct oz_hcd *ozhcd, u8 bus_addr)
-{
- int i;
-
- for (i = 0; i < OZ_NB_PORTS; i++) {
- if (ozhcd->ports[i].bus_addr == bus_addr)
- return i;
- }
- return ozhcd->conn_port;
-}
-
-/*
- * Context: any
- */
-static struct oz_urb_link *oz_alloc_urb_link(void)
-{
- return kmem_cache_alloc(oz_urb_link_cache, GFP_ATOMIC);
-}
-
-/*
- * Context: any
- */
-static void oz_free_urb_link(struct oz_urb_link *urbl)
-{
- if (!urbl)
- return;
-
- kmem_cache_free(oz_urb_link_cache, urbl);
-}
-
-/*
- * Allocates endpoint structure and optionally a buffer. If a buffer is
- * allocated it immediately follows the endpoint structure.
- * Context: softirq
- */
-static struct oz_endpoint *oz_ep_alloc(int buffer_size, gfp_t mem_flags)
-{
- struct oz_endpoint *ep;
-
- ep = kzalloc(sizeof(struct oz_endpoint)+buffer_size, mem_flags);
- if (!ep)
- return NULL;
-
- INIT_LIST_HEAD(&ep->urb_list);
- INIT_LIST_HEAD(&ep->link);
- ep->credit = -1;
- if (buffer_size) {
- ep->buffer_size = buffer_size;
- ep->buffer = (u8 *)(ep+1);
- }
-
- return ep;
-}
-
-/*
- * Pre-condition: Must be called with g_tasklet_lock held and interrupts
- * disabled.
- * Context: softirq or process
- */
-static struct oz_urb_link *oz_uncancel_urb(struct oz_hcd *ozhcd,
- struct urb *urb)
-{
- struct oz_urb_link *urbl;
-
- list_for_each_entry(urbl, &ozhcd->urb_cancel_list, link) {
- if (urb == urbl->urb) {
- list_del_init(&urbl->link);
- return urbl;
- }
- }
- return NULL;
-}
-
-/*
- * This is called when we have finished processing an urb. It unlinks it from
- * the ep and returns it to the core.
- * Context: softirq or process
- */
-static void oz_complete_urb(struct usb_hcd *hcd, struct urb *urb,
- int status)
-{
- struct oz_hcd *ozhcd = oz_hcd_private(hcd);
- unsigned long irq_state;
- struct oz_urb_link *cancel_urbl;
-
- spin_lock_irqsave(&g_tasklet_lock, irq_state);
- usb_hcd_unlink_urb_from_ep(hcd, urb);
- /* Clear hcpriv which will prevent it being put in the cancel list
- * in the event that an attempt is made to cancel it.
- */
- urb->hcpriv = NULL;
- /* Walk the cancel list in case the urb is already sitting there.
- * Since we process the cancel list in a tasklet rather than in
- * the dequeue function this could happen.
- */
- cancel_urbl = oz_uncancel_urb(ozhcd, urb);
- /* Note: we release lock but do not enable local irqs.
- * It appears that usb_hcd_giveback_urb() expects irqs to be disabled,
- * or at least other host controllers disable interrupts at this point
- * so we do the same. We must, however, release the lock otherwise a
- * deadlock will occur if an urb is submitted to our driver in the urb
- * completion function. Because we disable interrupts it is possible
- * that the urb_enqueue function can be called with them disabled.
- */
- spin_unlock(&g_tasklet_lock);
- if (oz_forget_urb(urb)) {
- oz_dbg(ON, "ERROR Unknown URB %p\n", urb);
- } else {
- atomic_dec(&g_pending_urbs);
- usb_hcd_giveback_urb(hcd, urb, status);
- }
- spin_lock(&g_tasklet_lock);
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- oz_free_urb_link(cancel_urbl);
-}
-
-/*
- * Deallocates an endpoint including deallocating any associated stream and
- * returning any queued urbs to the core.
- * Context: softirq
- */
-static void oz_ep_free(struct oz_port *port, struct oz_endpoint *ep)
-{
- if (port) {
- LIST_HEAD(list);
- struct oz_hcd *ozhcd = port->ozhcd;
-
- if (ep->flags & OZ_F_EP_HAVE_STREAM)
- oz_usb_stream_delete(port->hpd, ep->ep_num);
- /* Transfer URBs to the orphanage while we hold the lock. */
- spin_lock_bh(&ozhcd->hcd_lock);
- /* Note: this works even if ep->urb_list is empty.*/
- list_replace_init(&ep->urb_list, &list);
- /* Put the URBs in the orphanage. */
- list_splice_tail(&list, &ozhcd->orphanage);
- spin_unlock_bh(&ozhcd->hcd_lock);
- }
- oz_dbg(ON, "Freeing endpoint memory\n");
- kfree(ep);
-}
-
-/*
- * Context: softirq
- */
-static void oz_complete_buffered_urb(struct oz_port *port,
- struct oz_endpoint *ep,
- struct urb *urb)
-{
- int data_len, available_space, copy_len;
-
- data_len = ep->buffer[ep->out_ix];
- if (data_len <= urb->transfer_buffer_length)
- available_space = data_len;
- else
- available_space = urb->transfer_buffer_length;
-
- if (++ep->out_ix == ep->buffer_size)
- ep->out_ix = 0;
- copy_len = ep->buffer_size - ep->out_ix;
- if (copy_len >= available_space)
- copy_len = available_space;
- memcpy(urb->transfer_buffer, &ep->buffer[ep->out_ix], copy_len);
-
- if (copy_len < available_space) {
- memcpy((urb->transfer_buffer + copy_len), ep->buffer,
- (available_space - copy_len));
- ep->out_ix = available_space - copy_len;
- } else {
- ep->out_ix += copy_len;
- }
- urb->actual_length = available_space;
- if (ep->out_ix == ep->buffer_size)
- ep->out_ix = 0;
-
- ep->buffered_units--;
- oz_dbg(ON, "Trying to give back buffered frame of size=%d\n",
- available_space);
- oz_complete_urb(port->ozhcd->hcd, urb, 0);
-}
-
-/*
- * Context: softirq
- */
-static int oz_enqueue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
- struct urb *urb, u8 req_id)
-{
- struct oz_urb_link *urbl;
- struct oz_endpoint *ep = NULL;
- int err = 0;
-
- if (ep_addr >= OZ_NB_ENDPOINTS) {
- oz_dbg(ON, "%s: Invalid endpoint number\n", __func__);
- return -EINVAL;
- }
- urbl = oz_alloc_urb_link();
- if (!urbl)
- return -ENOMEM;
- urbl->submit_counter = 0;
- urbl->urb = urb;
- urbl->req_id = req_id;
- urbl->ep_num = ep_addr;
- /* Hold lock while we insert the URB into the list within the
- * endpoint structure.
- */
- spin_lock_bh(&port->ozhcd->hcd_lock);
- /* If the urb has been unlinked while out of any list then
- * complete it now.
- */
- if (urb->unlinked) {
- spin_unlock_bh(&port->ozhcd->hcd_lock);
- oz_dbg(ON, "urb %p unlinked so complete immediately\n", urb);
- oz_complete_urb(port->ozhcd->hcd, urb, 0);
- oz_free_urb_link(urbl);
- return 0;
- }
-
- if (in_dir)
- ep = port->in_ep[ep_addr];
- else
- ep = port->out_ep[ep_addr];
- if (!ep) {
- err = -ENOMEM;
- goto out;
- }
-
- /*For interrupt endpoint check for buffered data
- * & complete urb
- */
- if (((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
- && ep->buffered_units > 0) {
- oz_free_urb_link(urbl);
- spin_unlock_bh(&port->ozhcd->hcd_lock);
- oz_complete_buffered_urb(port, ep, urb);
- return 0;
- }
-
- if (port->hpd) {
- list_add_tail(&urbl->link, &ep->urb_list);
- if (!in_dir && ep_addr && (ep->credit < 0)) {
- getrawmonotonic(&ep->timestamp);
- ep->credit = 0;
- }
- } else {
- err = -EPIPE;
- }
-out:
- spin_unlock_bh(&port->ozhcd->hcd_lock);
- if (err)
- oz_free_urb_link(urbl);
- return err;
-}
-
-/*
- * Removes an urb from the queue in the endpoint.
- * Returns 0 if it is found and -EIDRM otherwise.
- * Context: softirq
- */
-static int oz_dequeue_ep_urb(struct oz_port *port, u8 ep_addr, int in_dir,
- struct urb *urb)
-{
- struct oz_urb_link *urbl = NULL;
- struct oz_endpoint *ep;
-
- spin_lock_bh(&port->ozhcd->hcd_lock);
- if (in_dir)
- ep = port->in_ep[ep_addr];
- else
- ep = port->out_ep[ep_addr];
- if (ep) {
- struct list_head *e;
-
- list_for_each(e, &ep->urb_list) {
- urbl = list_entry(e, struct oz_urb_link, link);
- if (urbl->urb == urb) {
- list_del_init(e);
- break;
- }
- urbl = NULL;
- }
- }
- spin_unlock_bh(&port->ozhcd->hcd_lock);
- oz_free_urb_link(urbl);
- return urbl ? 0 : -EIDRM;
-}
-
-/*
- * Finds an urb given its request id.
- * Context: softirq
- */
-static struct urb *oz_find_urb_by_id(struct oz_port *port, int ep_ix,
- u8 req_id)
-{
- struct oz_hcd *ozhcd = port->ozhcd;
- struct urb *urb = NULL;
- struct oz_urb_link *urbl;
- struct oz_endpoint *ep;
-
- spin_lock_bh(&ozhcd->hcd_lock);
- ep = port->out_ep[ep_ix];
- if (ep) {
- struct list_head *e;
-
- list_for_each(e, &ep->urb_list) {
- urbl = list_entry(e, struct oz_urb_link, link);
- if (urbl->req_id == req_id) {
- urb = urbl->urb;
- list_del_init(e);
- break;
- }
- }
- }
- spin_unlock_bh(&ozhcd->hcd_lock);
- /* If urb is non-zero then we we must have an urb link to delete.
- */
- if (urb)
- oz_free_urb_link(urbl);
- return urb;
-}
-
-/*
- * Pre-condition: Port lock must be held.
- * Context: softirq
- */
-static void oz_acquire_port(struct oz_port *port, void *hpd)
-{
- INIT_LIST_HEAD(&port->isoc_out_ep);
- INIT_LIST_HEAD(&port->isoc_in_ep);
- port->flags |= OZ_PORT_F_PRESENT | OZ_PORT_F_CHANGED;
- port->status |= USB_PORT_STAT_CONNECTION |
- (USB_PORT_STAT_C_CONNECTION << 16);
- oz_usb_get(hpd);
- port->hpd = hpd;
-}
-
-/*
- * Context: softirq
- */
-static struct oz_hcd *oz_hcd_claim(void)
-{
- struct oz_hcd *ozhcd;
-
- spin_lock_bh(&g_hcdlock);
- ozhcd = g_ozhcd;
- if (ozhcd)
- usb_get_hcd(ozhcd->hcd);
- spin_unlock_bh(&g_hcdlock);
- return ozhcd;
-}
-
-/*
- * Context: softirq
- */
-static inline void oz_hcd_put(struct oz_hcd *ozhcd)
-{
- if (ozhcd)
- usb_put_hcd(ozhcd->hcd);
-}
-
-/*
- * This is called by the protocol handler to notify that a PD has arrived.
- * We allocate a port to associate with the PD and create a structure for
- * endpoint 0. This port is made the connection port.
- * In the event that one of the other port is already a connection port then
- * we fail.
- * TODO We should be able to do better than fail and should be able remember
- * that this port needs configuring and make it the connection port once the
- * current connection port has been assigned an address. Collisions here are
- * probably very rare indeed.
- * Context: softirq
- */
-struct oz_port *oz_hcd_pd_arrived(void *hpd)
-{
- int i;
- struct oz_port *hport;
- struct oz_hcd *ozhcd;
- struct oz_endpoint *ep;
-
- ozhcd = oz_hcd_claim();
- if (!ozhcd)
- return NULL;
- /* Allocate an endpoint object in advance (before holding hcd lock) to
- * use for out endpoint 0.
- */
- ep = oz_ep_alloc(0, GFP_ATOMIC);
- if (!ep)
- goto err_put;
-
- spin_lock_bh(&ozhcd->hcd_lock);
- if (ozhcd->conn_port >= 0)
- goto err_unlock;
-
- for (i = 0; i < OZ_NB_PORTS; i++) {
- struct oz_port *port = &ozhcd->ports[i];
-
- spin_lock(&port->port_lock);
- if (!(port->flags & (OZ_PORT_F_PRESENT | OZ_PORT_F_CHANGED))) {
- oz_acquire_port(port, hpd);
- spin_unlock(&port->port_lock);
- break;
- }
- spin_unlock(&port->port_lock);
- }
- if (i == OZ_NB_PORTS)
- goto err_unlock;
-
- ozhcd->conn_port = i;
- hport = &ozhcd->ports[i];
- hport->out_ep[0] = ep;
- spin_unlock_bh(&ozhcd->hcd_lock);
- if (ozhcd->flags & OZ_HDC_F_SUSPENDED)
- usb_hcd_resume_root_hub(ozhcd->hcd);
- usb_hcd_poll_rh_status(ozhcd->hcd);
- oz_hcd_put(ozhcd);
-
- return hport;
-
-err_unlock:
- spin_unlock_bh(&ozhcd->hcd_lock);
- oz_ep_free(NULL, ep);
-err_put:
- oz_hcd_put(ozhcd);
- return NULL;
-}
-
-/*
- * This is called by the protocol handler to notify that the PD has gone away.
- * We need to deallocate all resources and then request that the root hub is
- * polled. We release the reference we hold on the PD.
- * Context: softirq
- */
-void oz_hcd_pd_departed(struct oz_port *port)
-{
- struct oz_hcd *ozhcd;
- void *hpd;
- struct oz_endpoint *ep = NULL;
-
- if (port == NULL) {
- oz_dbg(ON, "%s: port = 0\n", __func__);
- return;
- }
- ozhcd = port->ozhcd;
- if (ozhcd == NULL)
- return;
- /* Check if this is the connection port - if so clear it.
- */
- spin_lock_bh(&ozhcd->hcd_lock);
- if ((ozhcd->conn_port >= 0) &&
- (port == &ozhcd->ports[ozhcd->conn_port])) {
- oz_dbg(ON, "Clearing conn_port\n");
- ozhcd->conn_port = -1;
- }
- spin_lock(&port->port_lock);
- port->flags |= OZ_PORT_F_DYING;
- spin_unlock(&port->port_lock);
- spin_unlock_bh(&ozhcd->hcd_lock);
-
- oz_clean_endpoints_for_config(ozhcd->hcd, port);
- spin_lock_bh(&port->port_lock);
- hpd = port->hpd;
- port->hpd = NULL;
- port->bus_addr = 0xff;
- port->config_num = 0;
- port->flags &= ~(OZ_PORT_F_PRESENT | OZ_PORT_F_DYING);
- port->flags |= OZ_PORT_F_CHANGED;
- port->status &= ~(USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE);
- port->status |= (USB_PORT_STAT_C_CONNECTION << 16);
- /* If there is an endpont 0 then clear the pointer while we hold
- * the spinlock be we deallocate it after releasing the lock.
- */
- if (port->out_ep[0]) {
- ep = port->out_ep[0];
- port->out_ep[0] = NULL;
- }
- spin_unlock_bh(&port->port_lock);
- if (ep)
- oz_ep_free(port, ep);
- usb_hcd_poll_rh_status(ozhcd->hcd);
- oz_usb_put(hpd);
-}
-
-/*
- * Context: softirq
- */
-void oz_hcd_pd_reset(void *hpd, void *hport)
-{
- /* Cleanup the current configuration and report reset to the core.
- */
- struct oz_port *port = hport;
- struct oz_hcd *ozhcd = port->ozhcd;
-
- oz_dbg(ON, "PD Reset\n");
- spin_lock_bh(&port->port_lock);
- port->flags |= OZ_PORT_F_CHANGED;
- port->status |= USB_PORT_STAT_RESET;
- port->status |= (USB_PORT_STAT_C_RESET << 16);
- spin_unlock_bh(&port->port_lock);
- oz_clean_endpoints_for_config(ozhcd->hcd, port);
- usb_hcd_poll_rh_status(ozhcd->hcd);
-}
-
-/*
- * Context: softirq
- */
-void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status, const u8 *desc,
- u8 length, u16 offset, u16 total_size)
-{
- struct oz_port *port = hport;
- struct urb *urb;
- int err = 0;
-
- oz_dbg(ON, "oz_hcd_get_desc_cnf length = %d offs = %d tot_size = %d\n",
- length, offset, total_size);
- urb = oz_find_urb_by_id(port, 0, req_id);
- if (!urb)
- return;
- if (status == 0) {
- unsigned int copy_len;
- unsigned int required_size = urb->transfer_buffer_length;
-
- if (required_size > total_size)
- required_size = total_size;
- copy_len = required_size-offset;
- if (length <= copy_len)
- copy_len = length;
- memcpy(urb->transfer_buffer+offset, desc, copy_len);
- offset += copy_len;
- if (offset < required_size) {
- struct usb_ctrlrequest *setup =
- (struct usb_ctrlrequest *)urb->setup_packet;
- unsigned wvalue = le16_to_cpu(setup->wValue);
-
- if (oz_enqueue_ep_urb(port, 0, 0, urb, req_id))
- err = -ENOMEM;
- else if (oz_usb_get_desc_req(port->hpd, req_id,
- setup->bRequestType, (u8)(wvalue>>8),
- (u8)wvalue, setup->wIndex, offset,
- required_size-offset)) {
- oz_dequeue_ep_urb(port, 0, 0, urb);
- err = -ENOMEM;
- }
- if (err == 0)
- return;
- }
- }
- urb->actual_length = total_size;
- oz_complete_urb(port->ozhcd->hcd, urb, 0);
-}
-
-/*
- * Context: softirq
- */
-static void oz_display_conf_type(u8 t)
-{
- switch (t) {
- case USB_REQ_GET_STATUS:
- oz_dbg(ON, "USB_REQ_GET_STATUS - cnf\n");
- break;
- case USB_REQ_CLEAR_FEATURE:
- oz_dbg(ON, "USB_REQ_CLEAR_FEATURE - cnf\n");
- break;
- case USB_REQ_SET_FEATURE:
- oz_dbg(ON, "USB_REQ_SET_FEATURE - cnf\n");
- break;
- case USB_REQ_SET_ADDRESS:
- oz_dbg(ON, "USB_REQ_SET_ADDRESS - cnf\n");
- break;
- case USB_REQ_GET_DESCRIPTOR:
- oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n");
- break;
- case USB_REQ_SET_DESCRIPTOR:
- oz_dbg(ON, "USB_REQ_SET_DESCRIPTOR - cnf\n");
- break;
- case USB_REQ_GET_CONFIGURATION:
- oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - cnf\n");
- break;
- case USB_REQ_SET_CONFIGURATION:
- oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - cnf\n");
- break;
- case USB_REQ_GET_INTERFACE:
- oz_dbg(ON, "USB_REQ_GET_INTERFACE - cnf\n");
- break;
- case USB_REQ_SET_INTERFACE:
- oz_dbg(ON, "USB_REQ_SET_INTERFACE - cnf\n");
- break;
- case USB_REQ_SYNCH_FRAME:
- oz_dbg(ON, "USB_REQ_SYNCH_FRAME - cnf\n");
- break;
- }
-}
-
-/*
- * Context: softirq
- */
-static void oz_hcd_complete_set_config(struct oz_port *port, struct urb *urb,
- u8 rcode, u8 config_num)
-{
- int rc = 0;
- struct usb_hcd *hcd = port->ozhcd->hcd;
-
- if (rcode == 0) {
- port->config_num = config_num;
- oz_clean_endpoints_for_config(hcd, port);
- if (oz_build_endpoints_for_config(hcd, port,
- &urb->dev->config[port->config_num-1], GFP_ATOMIC)) {
- rc = -ENOMEM;
- }
- } else {
- rc = -ENOMEM;
- }
- oz_complete_urb(hcd, urb, rc);
-}
-
-/*
- * Context: softirq
- */
-static void oz_hcd_complete_set_interface(struct oz_port *port, struct urb *urb,
- u8 rcode, u8 if_num, u8 alt)
-{
- struct usb_hcd *hcd = port->ozhcd->hcd;
- int rc = 0;
-
- if ((rcode == 0) && (port->config_num > 0)) {
- struct usb_host_config *config;
- struct usb_host_interface *intf;
-
- oz_dbg(ON, "Set interface %d alt %d\n", if_num, alt);
- oz_clean_endpoints_for_interface(hcd, port, if_num);
- config = &urb->dev->config[port->config_num-1];
- intf = &config->intf_cache[if_num]->altsetting[alt];
- if (oz_build_endpoints_for_interface(hcd, port, intf,
- GFP_ATOMIC))
- rc = -ENOMEM;
- else
- port->iface[if_num].alt = alt;
- } else {
- rc = -ENOMEM;
- }
- oz_complete_urb(hcd, urb, rc);
-}
-
-/*
- * Context: softirq
- */
-void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode, const u8 *data,
- int data_len)
-{
- struct oz_port *port = hport;
- struct urb *urb;
- struct usb_ctrlrequest *setup;
- struct usb_hcd *hcd = port->ozhcd->hcd;
- unsigned windex;
- unsigned wvalue;
-
- oz_dbg(ON, "oz_hcd_control_cnf rcode=%u len=%d\n", rcode, data_len);
- urb = oz_find_urb_by_id(port, 0, req_id);
- if (!urb) {
- oz_dbg(ON, "URB not found\n");
- return;
- }
- setup = (struct usb_ctrlrequest *)urb->setup_packet;
- windex = le16_to_cpu(setup->wIndex);
- wvalue = le16_to_cpu(setup->wValue);
- if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
- /* Standard requests */
- oz_display_conf_type(setup->bRequest);
- switch (setup->bRequest) {
- case USB_REQ_SET_CONFIGURATION:
- oz_hcd_complete_set_config(port, urb, rcode,
- (u8)wvalue);
- break;
- case USB_REQ_SET_INTERFACE:
- oz_hcd_complete_set_interface(port, urb, rcode,
- (u8)windex, (u8)wvalue);
- break;
- default:
- oz_complete_urb(hcd, urb, 0);
- }
-
- } else {
- int copy_len;
-
- oz_dbg(ON, "VENDOR-CLASS - cnf\n");
- if (data_len) {
- if (data_len <= urb->transfer_buffer_length)
- copy_len = data_len;
- else
- copy_len = urb->transfer_buffer_length;
- memcpy(urb->transfer_buffer, data, copy_len);
- urb->actual_length = copy_len;
- }
- oz_complete_urb(hcd, urb, 0);
- }
-}
-
-/*
- * Context: softirq-serialized
- */
-static int oz_hcd_buffer_data(struct oz_endpoint *ep, const u8 *data,
- int data_len)
-{
- int space;
- int copy_len;
-
- if (!ep->buffer)
- return -1;
- space = ep->out_ix-ep->in_ix-1;
- if (space < 0)
- space += ep->buffer_size;
- if (space < (data_len+1)) {
- oz_dbg(ON, "Buffer full\n");
- return -1;
- }
- ep->buffer[ep->in_ix] = (u8)data_len;
- if (++ep->in_ix == ep->buffer_size)
- ep->in_ix = 0;
- copy_len = ep->buffer_size - ep->in_ix;
- if (copy_len > data_len)
- copy_len = data_len;
- memcpy(&ep->buffer[ep->in_ix], data, copy_len);
-
- if (copy_len < data_len) {
- memcpy(ep->buffer, data+copy_len, data_len-copy_len);
- ep->in_ix = data_len-copy_len;
- } else {
- ep->in_ix += copy_len;
- }
- if (ep->in_ix == ep->buffer_size)
- ep->in_ix = 0;
- ep->buffered_units++;
- return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len)
-{
- struct oz_port *port = (struct oz_port *)hport;
- struct oz_endpoint *ep;
- struct oz_hcd *ozhcd = port->ozhcd;
-
- spin_lock_bh(&ozhcd->hcd_lock);
- ep = port->in_ep[endpoint & USB_ENDPOINT_NUMBER_MASK];
- if (ep == NULL)
- goto done;
- switch (ep->attrib & USB_ENDPOINT_XFERTYPE_MASK) {
- case USB_ENDPOINT_XFER_INT:
- case USB_ENDPOINT_XFER_BULK:
- if (!list_empty(&ep->urb_list)) {
- struct oz_urb_link *urbl =
- list_first_entry(&ep->urb_list,
- struct oz_urb_link, link);
- struct urb *urb;
- int copy_len;
-
- list_del_init(&urbl->link);
- spin_unlock_bh(&ozhcd->hcd_lock);
- urb = urbl->urb;
- oz_free_urb_link(urbl);
- if (data_len <= urb->transfer_buffer_length)
- copy_len = data_len;
- else
- copy_len = urb->transfer_buffer_length;
- memcpy(urb->transfer_buffer, data, copy_len);
- urb->actual_length = copy_len;
- oz_complete_urb(port->ozhcd->hcd, urb, 0);
- return;
- }
- oz_dbg(ON, "buffering frame as URB is not available\n");
- oz_hcd_buffer_data(ep, data, data_len);
- break;
- case USB_ENDPOINT_XFER_ISOC:
- oz_hcd_buffer_data(ep, data, data_len);
- break;
- }
-done:
- spin_unlock_bh(&ozhcd->hcd_lock);
-}
-
-/*
- * Context: unknown
- */
-static inline int oz_usb_get_frame_number(void)
-{
- return atomic_inc_return(&g_usb_frame_number);
-}
-
-/*
- * Context: softirq
- */
-int oz_hcd_heartbeat(void *hport)
-{
- int rc = 0;
- struct oz_port *port = hport;
- struct oz_hcd *ozhcd = port->ozhcd;
- struct oz_urb_link *urbl, *n;
- LIST_HEAD(xfr_list);
- struct urb *urb;
- struct oz_endpoint *ep;
- struct timespec ts, delta;
-
- getrawmonotonic(&ts);
- /* Check the OUT isoc endpoints to see if any URB data can be sent.
- */
- spin_lock_bh(&ozhcd->hcd_lock);
- list_for_each_entry(ep, &port->isoc_out_ep, link) {
- if (ep->credit < 0)
- continue;
- delta = timespec_sub(ts, ep->timestamp);
- ep->credit += div_u64(timespec_to_ns(&delta), NSEC_PER_MSEC);
- if (ep->credit > ep->credit_ceiling)
- ep->credit = ep->credit_ceiling;
- ep->timestamp = ts;
- while (ep->credit && !list_empty(&ep->urb_list)) {
- urbl = list_first_entry(&ep->urb_list,
- struct oz_urb_link, link);
- urb = urbl->urb;
- if ((ep->credit + 1) < urb->number_of_packets)
- break;
- ep->credit -= urb->number_of_packets;
- if (ep->credit < 0)
- ep->credit = 0;
- list_move_tail(&urbl->link, &xfr_list);
- }
- }
- spin_unlock_bh(&ozhcd->hcd_lock);
- /* Send to PD and complete URBs.
- */
- list_for_each_entry_safe(urbl, n, &xfr_list, link) {
- urb = urbl->urb;
- list_del_init(&urbl->link);
- urb->error_count = 0;
- urb->start_frame = oz_usb_get_frame_number();
- oz_usb_send_isoc(port->hpd, urbl->ep_num, urb);
- oz_free_urb_link(urbl);
- oz_complete_urb(port->ozhcd->hcd, urb, 0);
- }
- /* Check the IN isoc endpoints to see if any URBs can be completed.
- */
- spin_lock_bh(&ozhcd->hcd_lock);
- list_for_each_entry(ep, &port->isoc_in_ep, link) {
- if (ep->flags & OZ_F_EP_BUFFERING) {
- if (ep->buffered_units >= OZ_IN_BUFFERING_UNITS) {
- ep->flags &= ~OZ_F_EP_BUFFERING;
- ep->credit = 0;
- ep->timestamp = ts;
- ep->start_frame = 0;
- }
- continue;
- }
- delta = timespec_sub(ts, ep->timestamp);
- ep->credit += div_u64(timespec_to_ns(&delta), NSEC_PER_MSEC);
- ep->timestamp = ts;
- list_for_each_entry_safe(urbl, n, &ep->urb_list, link) {
- struct urb *urb = urbl->urb;
- int len = 0;
- int copy_len;
- int i;
-
- if (ep->credit < urb->number_of_packets)
- break;
- if (ep->buffered_units < urb->number_of_packets)
- break;
- urb->actual_length = 0;
- for (i = 0; i < urb->number_of_packets; i++) {
- len = ep->buffer[ep->out_ix];
- if (++ep->out_ix == ep->buffer_size)
- ep->out_ix = 0;
- copy_len = ep->buffer_size - ep->out_ix;
- if (copy_len > len)
- copy_len = len;
- memcpy(urb->transfer_buffer,
- &ep->buffer[ep->out_ix], copy_len);
- if (copy_len < len) {
- memcpy(urb->transfer_buffer+copy_len,
- ep->buffer, len-copy_len);
- ep->out_ix = len-copy_len;
- } else
- ep->out_ix += copy_len;
- if (ep->out_ix == ep->buffer_size)
- ep->out_ix = 0;
- urb->iso_frame_desc[i].offset =
- urb->actual_length;
- urb->actual_length += len;
- urb->iso_frame_desc[i].actual_length = len;
- urb->iso_frame_desc[i].status = 0;
- }
- ep->buffered_units -= urb->number_of_packets;
- urb->error_count = 0;
- urb->start_frame = ep->start_frame;
- ep->start_frame += urb->number_of_packets;
- list_move_tail(&urbl->link, &xfr_list);
- ep->credit -= urb->number_of_packets;
- }
- }
- if (!list_empty(&port->isoc_out_ep) || !list_empty(&port->isoc_in_ep))
- rc = 1;
- spin_unlock_bh(&ozhcd->hcd_lock);
- /* Complete the filled URBs.
- */
- list_for_each_entry_safe(urbl, n, &xfr_list, link) {
- urb = urbl->urb;
- list_del_init(&urbl->link);
- oz_free_urb_link(urbl);
- oz_complete_urb(port->ozhcd->hcd, urb, 0);
- }
- /* Check if there are any ep0 requests that have timed out.
- * If so resent to PD.
- */
- ep = port->out_ep[0];
- if (ep) {
- spin_lock_bh(&ozhcd->hcd_lock);
- list_for_each_entry_safe(urbl, n, &ep->urb_list, link) {
- if (urbl->submit_counter > EP0_TIMEOUT_COUNTER) {
- oz_dbg(ON, "Request 0x%p timeout\n", urbl->urb);
- list_move_tail(&urbl->link, &xfr_list);
- urbl->submit_counter = 0;
- } else {
- urbl->submit_counter++;
- }
- }
- if (!list_empty(&ep->urb_list))
- rc = 1;
- spin_unlock_bh(&ozhcd->hcd_lock);
- list_for_each_entry_safe(urbl, n, &xfr_list, link) {
- oz_dbg(ON, "Resending request to PD\n");
- oz_process_ep0_urb(ozhcd, urbl->urb, GFP_ATOMIC);
- oz_free_urb_link(urbl);
- }
- }
- return rc;
-}
-
-/*
- * Context: softirq
- */
-static int oz_build_endpoints_for_interface(struct usb_hcd *hcd,
- struct oz_port *port,
- struct usb_host_interface *intf, gfp_t mem_flags)
-{
- struct oz_hcd *ozhcd = port->ozhcd;
- int i;
- int if_ix = intf->desc.bInterfaceNumber;
- int request_heartbeat = 0;
-
- oz_dbg(ON, "interface[%d] = %p\n", if_ix, intf);
- if (if_ix >= port->num_iface || port->iface == NULL)
- return -ENOMEM;
- for (i = 0; i < intf->desc.bNumEndpoints; i++) {
- struct usb_host_endpoint *hep = &intf->endpoint[i];
- u8 ep_addr = hep->desc.bEndpointAddress;
- u8 ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
- struct oz_endpoint *ep;
- int buffer_size = 0;
-
- oz_dbg(ON, "%d bEndpointAddress = %x\n", i, ep_addr);
- if (ep_addr & USB_ENDPOINT_DIR_MASK) {
- switch (hep->desc.bmAttributes &
- USB_ENDPOINT_XFERTYPE_MASK) {
- case USB_ENDPOINT_XFER_ISOC:
- buffer_size = OZ_EP_BUFFER_SIZE_ISOC;
- break;
- case USB_ENDPOINT_XFER_INT:
- buffer_size = OZ_EP_BUFFER_SIZE_INT;
- break;
- }
- }
-
- ep = oz_ep_alloc(buffer_size, mem_flags);
- if (!ep) {
- oz_clean_endpoints_for_interface(hcd, port, if_ix);
- return -ENOMEM;
- }
- ep->attrib = hep->desc.bmAttributes;
- ep->ep_num = ep_num;
- if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_ISOC) {
- oz_dbg(ON, "wMaxPacketSize = %d\n",
- usb_endpoint_maxp(&hep->desc));
- ep->credit_ceiling = 200;
- if (ep_addr & USB_ENDPOINT_DIR_MASK) {
- ep->flags |= OZ_F_EP_BUFFERING;
- } else {
- ep->flags |= OZ_F_EP_HAVE_STREAM;
- if (oz_usb_stream_create(port->hpd, ep_num))
- ep->flags &= ~OZ_F_EP_HAVE_STREAM;
- }
- }
- spin_lock_bh(&ozhcd->hcd_lock);
- if (ep_addr & USB_ENDPOINT_DIR_MASK) {
- port->in_ep[ep_num] = ep;
- port->iface[if_ix].ep_mask |=
- (1<<(ep_num+OZ_NB_ENDPOINTS));
- if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_ISOC) {
- list_add_tail(&ep->link, &port->isoc_in_ep);
- request_heartbeat = 1;
- }
- } else {
- port->out_ep[ep_num] = ep;
- port->iface[if_ix].ep_mask |= (1<<ep_num);
- if ((ep->attrib & USB_ENDPOINT_XFERTYPE_MASK)
- == USB_ENDPOINT_XFER_ISOC) {
- list_add_tail(&ep->link, &port->isoc_out_ep);
- request_heartbeat = 1;
- }
- }
- spin_unlock_bh(&ozhcd->hcd_lock);
- if (request_heartbeat && port->hpd)
- oz_usb_request_heartbeat(port->hpd);
- }
- return 0;
-}
-
-/*
- * Context: softirq
- */
-static void oz_clean_endpoints_for_interface(struct usb_hcd *hcd,
- struct oz_port *port, int if_ix)
-{
- struct oz_hcd *ozhcd = port->ozhcd;
- unsigned mask;
- int i;
- LIST_HEAD(ep_list);
- struct oz_endpoint *ep, *n;
-
- oz_dbg(ON, "Deleting endpoints for interface %d\n", if_ix);
- if (if_ix >= port->num_iface)
- return;
- spin_lock_bh(&ozhcd->hcd_lock);
- mask = port->iface[if_ix].ep_mask;
- port->iface[if_ix].ep_mask = 0;
- for (i = 0; i < OZ_NB_ENDPOINTS; i++) {
- struct list_head *e;
- /* Gather OUT endpoints.
- */
- if ((mask & (1<<i)) && port->out_ep[i]) {
- e = &port->out_ep[i]->link;
- port->out_ep[i] = NULL;
- /* Remove from isoc list if present.
- */
- list_move_tail(e, &ep_list);
- }
- /* Gather IN endpoints.
- */
- if ((mask & (1<<(i+OZ_NB_ENDPOINTS))) && port->in_ep[i]) {
- e = &port->in_ep[i]->link;
- port->in_ep[i] = NULL;
- list_move_tail(e, &ep_list);
- }
- }
- spin_unlock_bh(&ozhcd->hcd_lock);
- list_for_each_entry_safe(ep, n, &ep_list, link) {
- list_del_init(&ep->link);
- oz_ep_free(port, ep);
- }
-}
-
-/*
- * Context: softirq
- */
-static int oz_build_endpoints_for_config(struct usb_hcd *hcd,
- struct oz_port *port, struct usb_host_config *config,
- gfp_t mem_flags)
-{
- struct oz_hcd *ozhcd = port->ozhcd;
- int i;
- int num_iface = config->desc.bNumInterfaces;
-
- if (num_iface) {
- struct oz_interface *iface;
-
- iface = kmalloc_array(num_iface, sizeof(struct oz_interface),
- mem_flags | __GFP_ZERO);
- if (!iface)
- return -ENOMEM;
- spin_lock_bh(&ozhcd->hcd_lock);
- port->iface = iface;
- port->num_iface = num_iface;
- spin_unlock_bh(&ozhcd->hcd_lock);
- }
- for (i = 0; i < num_iface; i++) {
- struct usb_host_interface *intf =
- &config->intf_cache[i]->altsetting[0];
- if (oz_build_endpoints_for_interface(hcd, port, intf,
- mem_flags))
- goto fail;
- }
- return 0;
-fail:
- oz_clean_endpoints_for_config(hcd, port);
- return -1;
-}
-
-/*
- * Context: softirq
- */
-static void oz_clean_endpoints_for_config(struct usb_hcd *hcd,
- struct oz_port *port)
-{
- struct oz_hcd *ozhcd = port->ozhcd;
- int i;
-
- oz_dbg(ON, "Deleting endpoints for configuration\n");
- for (i = 0; i < port->num_iface; i++)
- oz_clean_endpoints_for_interface(hcd, port, i);
- spin_lock_bh(&ozhcd->hcd_lock);
- if (port->iface) {
- oz_dbg(ON, "Freeing interfaces object\n");
- kfree(port->iface);
- port->iface = NULL;
- }
- port->num_iface = 0;
- spin_unlock_bh(&ozhcd->hcd_lock);
-}
-
-/*
- * Context: tasklet
- */
-static void *oz_claim_hpd(struct oz_port *port)
-{
- void *hpd;
- struct oz_hcd *ozhcd = port->ozhcd;
-
- spin_lock_bh(&ozhcd->hcd_lock);
- hpd = port->hpd;
- if (hpd)
- oz_usb_get(hpd);
- spin_unlock_bh(&ozhcd->hcd_lock);
- return hpd;
-}
-
-/*
- * Context: tasklet
- */
-static void oz_process_ep0_urb(struct oz_hcd *ozhcd, struct urb *urb,
- gfp_t mem_flags)
-{
- struct usb_ctrlrequest *setup;
- unsigned windex;
- unsigned wvalue;
- unsigned wlength;
- void *hpd;
- u8 req_id;
- int rc = 0;
- unsigned complete = 0;
-
- int port_ix = -1;
- struct oz_port *port = NULL;
-
- oz_dbg(URB, "[%s]:(%p)\n", __func__, urb);
- port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
- if (port_ix < 0) {
- rc = -EPIPE;
- goto out;
- }
- port = &ozhcd->ports[port_ix];
- if (((port->flags & OZ_PORT_F_PRESENT) == 0)
- || (port->flags & OZ_PORT_F_DYING)) {
- oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n",
- port_ix, urb->dev->devnum);
- rc = -EPIPE;
- goto out;
- }
- /* Store port in private context data.
- */
- urb->hcpriv = port;
- setup = (struct usb_ctrlrequest *)urb->setup_packet;
- windex = le16_to_cpu(setup->wIndex);
- wvalue = le16_to_cpu(setup->wValue);
- wlength = le16_to_cpu(setup->wLength);
- oz_dbg(CTRL_DETAIL, "bRequestType = %x\n", setup->bRequestType);
- oz_dbg(CTRL_DETAIL, "bRequest = %x\n", setup->bRequest);
- oz_dbg(CTRL_DETAIL, "wValue = %x\n", wvalue);
- oz_dbg(CTRL_DETAIL, "wIndex = %x\n", windex);
- oz_dbg(CTRL_DETAIL, "wLength = %x\n", wlength);
-
- req_id = port->next_req_id++;
- hpd = oz_claim_hpd(port);
- if (hpd == NULL) {
- oz_dbg(ON, "Cannot claim port\n");
- rc = -EPIPE;
- goto out;
- }
-
- if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
- /* Standard requests
- */
- switch (setup->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - req\n");
- break;
- case USB_REQ_SET_ADDRESS:
- oz_dbg(ON, "USB_REQ_SET_ADDRESS - req\n");
- oz_dbg(ON, "Port %d address is 0x%x\n",
- ozhcd->conn_port,
- (u8)le16_to_cpu(setup->wValue));
- spin_lock_bh(&ozhcd->hcd_lock);
- if (ozhcd->conn_port >= 0) {
- ozhcd->ports[ozhcd->conn_port].bus_addr =
- (u8)le16_to_cpu(setup->wValue);
- oz_dbg(ON, "Clearing conn_port\n");
- ozhcd->conn_port = -1;
- }
- spin_unlock_bh(&ozhcd->hcd_lock);
- complete = 1;
- break;
- case USB_REQ_SET_CONFIGURATION:
- oz_dbg(ON, "USB_REQ_SET_CONFIGURATION - req\n");
- break;
- case USB_REQ_GET_CONFIGURATION:
- /* We short circuit this case and reply directly since
- * we have the selected configuration number cached.
- */
- oz_dbg(ON, "USB_REQ_GET_CONFIGURATION - reply now\n");
- if (urb->transfer_buffer_length >= 1) {
- urb->actual_length = 1;
- *((u8 *)urb->transfer_buffer) =
- port->config_num;
- complete = 1;
- } else {
- rc = -EPIPE;
- }
- break;
- case USB_REQ_GET_INTERFACE:
- /* We short circuit this case and reply directly since
- * we have the selected interface alternative cached.
- */
- oz_dbg(ON, "USB_REQ_GET_INTERFACE - reply now\n");
- if (urb->transfer_buffer_length >= 1) {
- urb->actual_length = 1;
- *((u8 *)urb->transfer_buffer) =
- port->iface[(u8)windex].alt;
- oz_dbg(ON, "interface = %d alt = %d\n",
- windex, port->iface[(u8)windex].alt);
- complete = 1;
- } else {
- rc = -EPIPE;
- }
- break;
- case USB_REQ_SET_INTERFACE:
- oz_dbg(ON, "USB_REQ_SET_INTERFACE - req\n");
- break;
- }
- }
- if (!rc && !complete) {
- int data_len = 0;
-
- if ((setup->bRequestType & USB_DIR_IN) == 0)
- data_len = wlength;
- urb->actual_length = data_len;
- if (oz_usb_control_req(port->hpd, req_id, setup,
- urb->transfer_buffer, data_len)) {
- rc = -ENOMEM;
- } else {
- /* Note: we are queuing the request after we have
- * submitted it to be transmitted. If the request were
- * to complete before we queued it then it would not
- * be found in the queue. It seems impossible for
- * this to happen but if it did the request would
- * be resubmitted so the problem would hopefully
- * resolve itself. Putting the request into the
- * queue before it has been sent is worse since the
- * urb could be cancelled while we are using it
- * to build the request.
- */
- if (oz_enqueue_ep_urb(port, 0, 0, urb, req_id))
- rc = -ENOMEM;
- }
- }
- oz_usb_put(hpd);
-out:
- if (rc || complete) {
- oz_dbg(ON, "Completing request locally\n");
- oz_complete_urb(ozhcd->hcd, urb, rc);
- } else {
- oz_usb_request_heartbeat(port->hpd);
- }
-}
-
-/*
- * Context: tasklet
- */
-static int oz_urb_process(struct oz_hcd *ozhcd, struct urb *urb)
-{
- int rc = 0;
- struct oz_port *port = urb->hcpriv;
- u8 ep_addr;
-
- /* When we are paranoid we keep a list of urbs which we check against
- * before handing one back. This is just for debugging during
- * development and should be turned off in the released driver.
- */
- oz_remember_urb(urb);
- /* Check buffer is valid.
- */
- if (!urb->transfer_buffer && urb->transfer_buffer_length)
- return -EINVAL;
- /* Check if there is a device at the port - refuse if not.
- */
- if ((port->flags & OZ_PORT_F_PRESENT) == 0)
- return -EPIPE;
- ep_addr = usb_pipeendpoint(urb->pipe);
- if (ep_addr) {
- /* If the request is not for EP0 then queue it.
- */
- if (oz_enqueue_ep_urb(port, ep_addr, usb_pipein(urb->pipe),
- urb, 0))
- rc = -EPIPE;
- } else {
- oz_process_ep0_urb(ozhcd, urb, GFP_ATOMIC);
- }
- return rc;
-}
-
-/*
- * Context: tasklet
- */
-static void oz_urb_process_tasklet(unsigned long unused)
-{
- unsigned long irq_state;
- struct urb *urb;
- struct oz_hcd *ozhcd = oz_hcd_claim();
- struct oz_urb_link *urbl, *n;
- int rc = 0;
-
- if (ozhcd == NULL)
- return;
- /* This is called from a tasklet so is in softirq context but the urb
- * list is filled from any context so we need to lock
- * appropriately while removing urbs.
- */
- spin_lock_irqsave(&g_tasklet_lock, irq_state);
- list_for_each_entry_safe(urbl, n, &ozhcd->urb_pending_list, link) {
- list_del_init(&urbl->link);
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- urb = urbl->urb;
- oz_free_urb_link(urbl);
- rc = oz_urb_process(ozhcd, urb);
- if (rc)
- oz_complete_urb(ozhcd->hcd, urb, rc);
- spin_lock_irqsave(&g_tasklet_lock, irq_state);
- }
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- oz_hcd_put(ozhcd);
-}
-
-/*
- * This function searches for the urb in any of the lists it could be in.
- * If it is found it is removed from the list and completed. If the urb is
- * being processed then it won't be in a list so won't be found. However, the
- * call to usb_hcd_check_unlink_urb() will set the value of the unlinked field
- * to a non-zero value. When an attempt is made to put the urb back in a list
- * the unlinked field will be checked and the urb will then be completed.
- * Context: tasklet
- */
-static void oz_urb_cancel(struct oz_port *port, u8 ep_num, struct urb *urb)
-{
- struct oz_urb_link *urbl = NULL;
- struct list_head *e;
- struct oz_hcd *ozhcd;
- unsigned long irq_state;
- u8 ix;
-
- if (port == NULL) {
- oz_dbg(ON, "%s: ERROR: (%p) port is null\n", __func__, urb);
- return;
- }
- ozhcd = port->ozhcd;
- if (ozhcd == NULL) {
- oz_dbg(ON, "%s; ERROR: (%p) ozhcd is null\n", __func__, urb);
- return;
- }
-
- /* Look in the tasklet queue.
- */
- spin_lock_irqsave(&g_tasklet_lock, irq_state);
- list_for_each(e, &ozhcd->urb_cancel_list) {
- urbl = list_entry(e, struct oz_urb_link, link);
- if (urb == urbl->urb) {
- list_del_init(e);
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- goto out2;
- }
- }
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- urbl = NULL;
-
- /* Look in the orphanage.
- */
- spin_lock_irqsave(&ozhcd->hcd_lock, irq_state);
- list_for_each(e, &ozhcd->orphanage) {
- urbl = list_entry(e, struct oz_urb_link, link);
- if (urbl->urb == urb) {
- list_del(e);
- oz_dbg(ON, "Found urb in orphanage\n");
- goto out;
- }
- }
- ix = (ep_num & 0xf);
- urbl = NULL;
- if ((ep_num & USB_DIR_IN) && ix)
- urbl = oz_remove_urb(port->in_ep[ix], urb);
- else
- urbl = oz_remove_urb(port->out_ep[ix], urb);
-out:
- spin_unlock_irqrestore(&ozhcd->hcd_lock, irq_state);
-out2:
- if (urbl) {
- urb->actual_length = 0;
- oz_free_urb_link(urbl);
- oz_complete_urb(ozhcd->hcd, urb, -EPIPE);
- }
-}
-
-/*
- * Context: tasklet
- */
-static void oz_urb_cancel_tasklet(unsigned long unused)
-{
- unsigned long irq_state;
- struct urb *urb;
- struct oz_urb_link *urbl, *n;
- struct oz_hcd *ozhcd = oz_hcd_claim();
-
- if (ozhcd == NULL)
- return;
- spin_lock_irqsave(&g_tasklet_lock, irq_state);
- list_for_each_entry_safe(urbl, n, &ozhcd->urb_cancel_list, link) {
- list_del_init(&urbl->link);
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- urb = urbl->urb;
- if (urb->unlinked)
- oz_urb_cancel(urbl->port, urbl->ep_num, urb);
- oz_free_urb_link(urbl);
- spin_lock_irqsave(&g_tasklet_lock, irq_state);
- }
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- oz_hcd_put(ozhcd);
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_clear_orphanage(struct oz_hcd *ozhcd, int status)
-{
- if (ozhcd) {
- struct oz_urb_link *urbl, *n;
-
- list_for_each_entry_safe(urbl, n, &ozhcd->orphanage, link) {
- list_del(&urbl->link);
- oz_complete_urb(ozhcd->hcd, urbl->urb, status);
- oz_free_urb_link(urbl);
- }
- }
-}
-
-/*
- * Context: unknown
- */
-static int oz_hcd_start(struct usb_hcd *hcd)
-{
- hcd->power_budget = 200;
- hcd->state = HC_STATE_RUNNING;
- hcd->uses_new_polling = 1;
- return 0;
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_stop(struct usb_hcd *hcd)
-{
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_shutdown(struct usb_hcd *hcd)
-{
-}
-
-/*
- * Called to queue an urb for the device.
- * This function should return a non-zero error code if it fails the urb but
- * should not call usb_hcd_giveback_urb().
- * Context: any
- */
-static int oz_hcd_urb_enqueue(struct usb_hcd *hcd, struct urb *urb,
- gfp_t mem_flags)
-{
- struct oz_hcd *ozhcd = oz_hcd_private(hcd);
- int rc;
- int port_ix;
- struct oz_port *port;
- unsigned long irq_state;
- struct oz_urb_link *urbl;
-
- oz_dbg(URB, "%s: (%p)\n", __func__, urb);
- if (unlikely(ozhcd == NULL)) {
- oz_dbg(URB, "Refused urb(%p) not ozhcd\n", urb);
- return -EPIPE;
- }
- if (unlikely(hcd->state != HC_STATE_RUNNING)) {
- oz_dbg(URB, "Refused urb(%p) not running\n", urb);
- return -EPIPE;
- }
- port_ix = oz_get_port_from_addr(ozhcd, urb->dev->devnum);
- if (port_ix < 0)
- return -EPIPE;
- port = &ozhcd->ports[port_ix];
- if (port == NULL)
- return -EPIPE;
- if (!(port->flags & OZ_PORT_F_PRESENT) ||
- (port->flags & OZ_PORT_F_CHANGED)) {
- oz_dbg(ON, "Refusing URB port_ix = %d devnum = %d\n",
- port_ix, urb->dev->devnum);
- return -EPIPE;
- }
- urb->hcpriv = port;
- /* Put request in queue for processing by tasklet.
- */
- urbl = oz_alloc_urb_link();
- if (unlikely(urbl == NULL))
- return -ENOMEM;
- urbl->urb = urb;
- spin_lock_irqsave(&g_tasklet_lock, irq_state);
- rc = usb_hcd_link_urb_to_ep(hcd, urb);
- if (unlikely(rc)) {
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- oz_free_urb_link(urbl);
- return rc;
- }
- list_add_tail(&urbl->link, &ozhcd->urb_pending_list);
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- tasklet_schedule(&g_urb_process_tasklet);
- atomic_inc(&g_pending_urbs);
- return 0;
-}
-
-/*
- * Context: tasklet
- */
-static struct oz_urb_link *oz_remove_urb(struct oz_endpoint *ep,
- struct urb *urb)
-{
- struct oz_urb_link *urbl;
-
- if (unlikely(ep == NULL))
- return NULL;
-
- list_for_each_entry(urbl, &ep->urb_list, link) {
- if (urbl->urb == urb) {
- list_del_init(&urbl->link);
- if (usb_pipeisoc(urb->pipe)) {
- ep->credit -= urb->number_of_packets;
- if (ep->credit < 0)
- ep->credit = 0;
- }
- return urbl;
- }
- }
- return NULL;
-}
-
-/*
- * Called to dequeue a previously submitted urb for the device.
- * Context: any
- */
-static int oz_hcd_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
-{
- struct oz_hcd *ozhcd = oz_hcd_private(hcd);
- struct oz_urb_link *urbl;
- int rc;
- unsigned long irq_state;
-
- oz_dbg(URB, "%s: (%p)\n", __func__, urb);
- urbl = oz_alloc_urb_link();
- if (unlikely(urbl == NULL))
- return -ENOMEM;
- spin_lock_irqsave(&g_tasklet_lock, irq_state);
- /* The following function checks the urb is still in the queue
- * maintained by the core and that the unlinked field is zero.
- * If both are true the function sets the unlinked field and returns
- * zero. Otherwise it returns an error.
- */
- rc = usb_hcd_check_unlink_urb(hcd, urb, status);
- /* We have to check we haven't completed the urb or are about
- * to complete it. When we do we set hcpriv to 0 so if this has
- * already happened we don't put the urb in the cancel queue.
- */
- if ((rc == 0) && urb->hcpriv) {
- urbl->urb = urb;
- urbl->port = (struct oz_port *)urb->hcpriv;
- urbl->ep_num = usb_pipeendpoint(urb->pipe);
- if (usb_pipein(urb->pipe))
- urbl->ep_num |= USB_DIR_IN;
- list_add_tail(&urbl->link, &ozhcd->urb_cancel_list);
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- tasklet_schedule(&g_urb_cancel_tasklet);
- } else {
- spin_unlock_irqrestore(&g_tasklet_lock, irq_state);
- oz_free_urb_link(urbl);
- }
- return rc;
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_endpoint_disable(struct usb_hcd *hcd,
- struct usb_host_endpoint *ep)
-{
-}
-
-/*
- * Context: unknown
- */
-static void oz_hcd_endpoint_reset(struct usb_hcd *hcd,
- struct usb_host_endpoint *ep)
-{
-}
-
-/*
- * Context: unknown
- */
-static int oz_hcd_get_frame_number(struct usb_hcd *hcd)
-{
- oz_dbg(ON, "oz_hcd_get_frame_number\n");
- return oz_usb_get_frame_number();
-}
-
-/*
- * Context: softirq
- * This is called as a consquence of us calling usb_hcd_poll_rh_status() and we
- * always do that in softirq context.
- */
-static int oz_hcd_hub_status_data(struct usb_hcd *hcd, char *buf)
-{
- struct oz_hcd *ozhcd = oz_hcd_private(hcd);
- int i;
-
- buf[0] = 0;
- buf[1] = 0;
-
- spin_lock_bh(&ozhcd->hcd_lock);
- for (i = 0; i < OZ_NB_PORTS; i++) {
- if (ozhcd->ports[i].flags & OZ_PORT_F_CHANGED) {
- oz_dbg(HUB, "Port %d changed\n", i);
- ozhcd->ports[i].flags &= ~OZ_PORT_F_CHANGED;
- if (i < 7)
- buf[0] |= 1 << (i + 1);
- else
- buf[1] |= 1 << (i - 7);
- }
- }
- spin_unlock_bh(&ozhcd->hcd_lock);
- if (buf[0] != 0 || buf[1] != 0)
- return 2;
- return 0;
-}
-
-/*
- * Context: process
- */
-static void oz_get_hub_descriptor(struct usb_hcd *hcd,
- struct usb_hub_descriptor *desc)
-{
- memset(desc, 0, sizeof(*desc));
- desc->bDescriptorType = 0x29;
- desc->bDescLength = 9;
- desc->wHubCharacteristics = cpu_to_le16(0x0001);
- desc->bNbrPorts = OZ_NB_PORTS;
-}
-
-/*
- * Context: process
- */
-static int oz_set_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
-{
- struct oz_port *port;
- u8 port_id = (u8)windex;
- struct oz_hcd *ozhcd = oz_hcd_private(hcd);
- unsigned set_bits = 0;
- unsigned clear_bits = 0;
-
- if ((port_id < 1) || (port_id > OZ_NB_PORTS))
- return -EPIPE;
- port = &ozhcd->ports[port_id-1];
- switch (wvalue) {
- case USB_PORT_FEAT_CONNECTION:
- oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n");
- break;
- case USB_PORT_FEAT_ENABLE:
- oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n");
- break;
- case USB_PORT_FEAT_SUSPEND:
- oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n");
- break;
- case USB_PORT_FEAT_OVER_CURRENT:
- oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
- break;
- case USB_PORT_FEAT_RESET:
- oz_dbg(HUB, "USB_PORT_FEAT_RESET\n");
- set_bits = USB_PORT_STAT_ENABLE | (USB_PORT_STAT_C_RESET<<16);
- clear_bits = USB_PORT_STAT_RESET;
- ozhcd->ports[port_id-1].bus_addr = 0;
- break;
- case USB_PORT_FEAT_POWER:
- oz_dbg(HUB, "USB_PORT_FEAT_POWER\n");
- set_bits |= USB_PORT_STAT_POWER;
- break;
- case USB_PORT_FEAT_LOWSPEED:
- oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n");
- break;
- case USB_PORT_FEAT_C_CONNECTION:
- oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n");
- break;
- case USB_PORT_FEAT_C_ENABLE:
- oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n");
- break;
- case USB_PORT_FEAT_C_SUSPEND:
- oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n");
- break;
- case USB_PORT_FEAT_C_OVER_CURRENT:
- oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
- break;
- case USB_PORT_FEAT_C_RESET:
- oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n");
- break;
- case USB_PORT_FEAT_TEST:
- oz_dbg(HUB, "USB_PORT_FEAT_TEST\n");
- break;
- case USB_PORT_FEAT_INDICATOR:
- oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n");
- break;
- default:
- oz_dbg(HUB, "Other %d\n", wvalue);
- break;
- }
- if (set_bits || clear_bits) {
- spin_lock_bh(&port->port_lock);
- port->status &= ~clear_bits;
- port->status |= set_bits;
- spin_unlock_bh(&port->port_lock);
- }
- oz_dbg(HUB, "Port[%d] status = 0x%x\n", port_id, port->status);
- return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_clear_port_feature(struct usb_hcd *hcd, u16 wvalue, u16 windex)
-{
- struct oz_port *port;
- u8 port_id = (u8)windex;
- struct oz_hcd *ozhcd = oz_hcd_private(hcd);
- unsigned clear_bits = 0;
-
- if ((port_id < 1) || (port_id > OZ_NB_PORTS))
- return -EPIPE;
- port = &ozhcd->ports[port_id-1];
- switch (wvalue) {
- case USB_PORT_FEAT_CONNECTION:
- oz_dbg(HUB, "USB_PORT_FEAT_CONNECTION\n");
- break;
- case USB_PORT_FEAT_ENABLE:
- oz_dbg(HUB, "USB_PORT_FEAT_ENABLE\n");
- clear_bits = USB_PORT_STAT_ENABLE;
- break;
- case USB_PORT_FEAT_SUSPEND:
- oz_dbg(HUB, "USB_PORT_FEAT_SUSPEND\n");
- break;
- case USB_PORT_FEAT_OVER_CURRENT:
- oz_dbg(HUB, "USB_PORT_FEAT_OVER_CURRENT\n");
- break;
- case USB_PORT_FEAT_RESET:
- oz_dbg(HUB, "USB_PORT_FEAT_RESET\n");
- break;
- case USB_PORT_FEAT_POWER:
- oz_dbg(HUB, "USB_PORT_FEAT_POWER\n");
- clear_bits |= USB_PORT_STAT_POWER;
- break;
- case USB_PORT_FEAT_LOWSPEED:
- oz_dbg(HUB, "USB_PORT_FEAT_LOWSPEED\n");
- break;
- case USB_PORT_FEAT_C_CONNECTION:
- oz_dbg(HUB, "USB_PORT_FEAT_C_CONNECTION\n");
- clear_bits = USB_PORT_STAT_C_CONNECTION << 16;
- break;
- case USB_PORT_FEAT_C_ENABLE:
- oz_dbg(HUB, "USB_PORT_FEAT_C_ENABLE\n");
- clear_bits = USB_PORT_STAT_C_ENABLE << 16;
- break;
- case USB_PORT_FEAT_C_SUSPEND:
- oz_dbg(HUB, "USB_PORT_FEAT_C_SUSPEND\n");
- break;
- case USB_PORT_FEAT_C_OVER_CURRENT:
- oz_dbg(HUB, "USB_PORT_FEAT_C_OVER_CURRENT\n");
- break;
- case USB_PORT_FEAT_C_RESET:
- oz_dbg(HUB, "USB_PORT_FEAT_C_RESET\n");
- clear_bits = USB_PORT_FEAT_C_RESET << 16;
- break;
- case USB_PORT_FEAT_TEST:
- oz_dbg(HUB, "USB_PORT_FEAT_TEST\n");
- break;
- case USB_PORT_FEAT_INDICATOR:
- oz_dbg(HUB, "USB_PORT_FEAT_INDICATOR\n");
- break;
- default:
- oz_dbg(HUB, "Other %d\n", wvalue);
- break;
- }
- if (clear_bits) {
- spin_lock_bh(&port->port_lock);
- port->status &= ~clear_bits;
- spin_unlock_bh(&port->port_lock);
- }
- oz_dbg(HUB, "Port[%d] status = 0x%x\n",
- port_id, ozhcd->ports[port_id-1].status);
- return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_get_port_status(struct usb_hcd *hcd, u16 windex, char *buf)
-{
- struct oz_hcd *ozhcd;
- u32 status;
-
- if ((windex < 1) || (windex > OZ_NB_PORTS))
- return -EPIPE;
- ozhcd = oz_hcd_private(hcd);
- oz_dbg(HUB, "GetPortStatus windex = %d\n", windex);
- status = ozhcd->ports[windex-1].status;
- put_unaligned(cpu_to_le32(status), (__le32 *)buf);
- oz_dbg(HUB, "Port[%d] status = %x\n", windex, status);
- return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_hcd_hub_control(struct usb_hcd *hcd, u16 req_type, u16 wvalue,
- u16 windex, char *buf, u16 wlength)
-{
- int err = 0;
-
- switch (req_type) {
- case ClearHubFeature:
- oz_dbg(HUB, "ClearHubFeature: %d\n", req_type);
- break;
- case ClearPortFeature:
- err = oz_clear_port_feature(hcd, wvalue, windex);
- break;
- case GetHubDescriptor:
- oz_get_hub_descriptor(hcd, (struct usb_hub_descriptor *)buf);
- break;
- case GetHubStatus:
- oz_dbg(HUB, "GetHubStatus: req_type = 0x%x\n", req_type);
- put_unaligned(cpu_to_le32(0), (__le32 *)buf);
- break;
- case GetPortStatus:
- err = oz_get_port_status(hcd, windex, buf);
- break;
- case SetHubFeature:
- oz_dbg(HUB, "SetHubFeature: %d\n", req_type);
- break;
- case SetPortFeature:
- err = oz_set_port_feature(hcd, wvalue, windex);
- break;
- default:
- oz_dbg(HUB, "Other: %d\n", req_type);
- break;
- }
- return err;
-}
-
-/*
- * Context: process
- */
-static int oz_hcd_bus_suspend(struct usb_hcd *hcd)
-{
- struct oz_hcd *ozhcd;
-
- ozhcd = oz_hcd_private(hcd);
- spin_lock_bh(&ozhcd->hcd_lock);
- hcd->state = HC_STATE_SUSPENDED;
- ozhcd->flags |= OZ_HDC_F_SUSPENDED;
- spin_unlock_bh(&ozhcd->hcd_lock);
- return 0;
-}
-
-/*
- * Context: process
- */
-static int oz_hcd_bus_resume(struct usb_hcd *hcd)
-{
- struct oz_hcd *ozhcd;
-
- ozhcd = oz_hcd_private(hcd);
- spin_lock_bh(&ozhcd->hcd_lock);
- ozhcd->flags &= ~OZ_HDC_F_SUSPENDED;
- hcd->state = HC_STATE_RUNNING;
- spin_unlock_bh(&ozhcd->hcd_lock);
- return 0;
-}
-
-static void oz_plat_shutdown(struct platform_device *dev)
-{
-}
-
-/*
- * Context: process
- */
-static int oz_plat_probe(struct platform_device *dev)
-{
- int i;
- int err;
- struct usb_hcd *hcd;
- struct oz_hcd *ozhcd;
-
- hcd = usb_create_hcd(&g_oz_hc_drv, &dev->dev, dev_name(&dev->dev));
- if (hcd == NULL) {
- oz_dbg(ON, "Failed to created hcd object OK\n");
- return -ENOMEM;
- }
- ozhcd = oz_hcd_private(hcd);
- memset(ozhcd, 0, sizeof(*ozhcd));
- INIT_LIST_HEAD(&ozhcd->urb_pending_list);
- INIT_LIST_HEAD(&ozhcd->urb_cancel_list);
- INIT_LIST_HEAD(&ozhcd->orphanage);
- ozhcd->hcd = hcd;
- ozhcd->conn_port = -1;
- spin_lock_init(&ozhcd->hcd_lock);
- for (i = 0; i < OZ_NB_PORTS; i++) {
- struct oz_port *port = &ozhcd->ports[i];
-
- port->ozhcd = ozhcd;
- port->flags = 0;
- port->status = 0;
- port->bus_addr = 0xff;
- spin_lock_init(&port->port_lock);
- }
- err = usb_add_hcd(hcd, 0, 0);
- if (err) {
- oz_dbg(ON, "Failed to add hcd object OK\n");
- usb_put_hcd(hcd);
- return -1;
- }
- device_wakeup_enable(hcd->self.controller);
-
- spin_lock_bh(&g_hcdlock);
- g_ozhcd = ozhcd;
- spin_unlock_bh(&g_hcdlock);
- return 0;
-}
-
-/*
- * Context: unknown
- */
-static int oz_plat_remove(struct platform_device *dev)
-{
- struct usb_hcd *hcd = platform_get_drvdata(dev);
- struct oz_hcd *ozhcd;
-
- if (hcd == NULL)
- return -1;
- ozhcd = oz_hcd_private(hcd);
- spin_lock_bh(&g_hcdlock);
- if (ozhcd == g_ozhcd)
- g_ozhcd = NULL;
- spin_unlock_bh(&g_hcdlock);
- oz_dbg(ON, "Clearing orphanage\n");
- oz_hcd_clear_orphanage(ozhcd, -EPIPE);
- oz_dbg(ON, "Removing hcd\n");
- usb_remove_hcd(hcd);
- usb_put_hcd(hcd);
- return 0;
-}
-
-/*
- * Context: unknown
- */
-static int oz_plat_suspend(struct platform_device *dev, pm_message_t msg)
-{
- return 0;
-}
-
-
-/*
- * Context: unknown
- */
-static int oz_plat_resume(struct platform_device *dev)
-{
- return 0;
-}
-
-/*
- * Context: process
- */
-int oz_hcd_init(void)
-{
- int err;
-
- if (usb_disabled())
- return -ENODEV;
-
- oz_urb_link_cache = KMEM_CACHE(oz_urb_link, 0);
- if (!oz_urb_link_cache)
- return -ENOMEM;
-
- tasklet_init(&g_urb_process_tasklet, oz_urb_process_tasklet, 0);
- tasklet_init(&g_urb_cancel_tasklet, oz_urb_cancel_tasklet, 0);
- err = platform_driver_register(&g_oz_plat_drv);
- oz_dbg(ON, "platform_driver_register() returned %d\n", err);
- if (err)
- goto error;
- g_plat_dev = platform_device_alloc(OZ_PLAT_DEV_NAME, -1);
- if (g_plat_dev == NULL) {
- err = -ENOMEM;
- goto error1;
- }
- oz_dbg(ON, "platform_device_alloc() succeeded\n");
- err = platform_device_add(g_plat_dev);
- if (err)
- goto error2;
- oz_dbg(ON, "platform_device_add() succeeded\n");
- return 0;
-error2:
- platform_device_put(g_plat_dev);
-error1:
- platform_driver_unregister(&g_oz_plat_drv);
-error:
- tasklet_disable(&g_urb_process_tasklet);
- tasklet_disable(&g_urb_cancel_tasklet);
- oz_dbg(ON, "oz_hcd_init() failed %d\n", err);
- return err;
-}
-
-/*
- * Context: process
- */
-void oz_hcd_term(void)
-{
- msleep(OZ_HUB_DEBOUNCE_TIMEOUT);
- tasklet_kill(&g_urb_process_tasklet);
- tasklet_kill(&g_urb_cancel_tasklet);
- platform_device_unregister(g_plat_dev);
- platform_driver_unregister(&g_oz_plat_drv);
- oz_dbg(ON, "Pending urbs:%d\n", atomic_read(&g_pending_urbs));
- kmem_cache_destroy(oz_urb_link_cache);
-}
diff --git a/drivers/staging/ozwpan/ozhcd.h b/drivers/staging/ozwpan/ozhcd.h
deleted file mode 100644
index 55e97b1..0000000
--- a/drivers/staging/ozwpan/ozhcd.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * ---------------------------------------------------------------------------*/
-#ifndef _OZHCD_H
-#define _OZHCD_H
-
-int oz_hcd_init(void);
-void oz_hcd_term(void);
-struct oz_port *oz_hcd_pd_arrived(void *ctx);
-void oz_hcd_pd_departed(struct oz_port *hport);
-void oz_hcd_pd_reset(void *hpd, void *hport);
-
-#endif /* _OZHCD_H */
-
diff --git a/drivers/staging/ozwpan/ozmain.c b/drivers/staging/ozwpan/ozmain.c
deleted file mode 100644
index 74ef348..0000000
--- a/drivers/staging/ozwpan/ozmain.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/errno.h>
-#include <linux/ieee80211.h>
-#include "ozdbg.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozcdev.h"
-
-unsigned int oz_dbg_mask = OZ_DEFAULT_DBG_MASK;
-
-/*
- * The name of the 802.11 mac device. Empty string is the default value but a
- * value can be supplied as a parameter to the module. An empty string means
- * bind to nothing. '*' means bind to all netcards - this includes non-802.11
- * netcards. Bindings can be added later using an IOCTL.
- */
-static char *g_net_dev = "";
-module_param(g_net_dev, charp, S_IRUGO);
-MODULE_PARM_DESC(g_net_dev, "The device(s) to bind to; "
- "'*' means all, '' (empty string; default) means none.");
-
-/*
- * Context: process
- */
-static int __init ozwpan_init(void)
-{
- int err;
-
- err = oz_cdev_register();
- if (err)
- return err;
- err = oz_protocol_init(g_net_dev);
- if (err)
- goto err_protocol;
- oz_app_enable(OZ_APPID_USB, 1);
- oz_apps_init();
- return 0;
-
-err_protocol:
- oz_cdev_deregister();
- return err;
-}
-
-/*
- * Context: process
- */
-static void __exit ozwpan_exit(void)
-{
- oz_protocol_term();
- oz_apps_term();
- oz_cdev_deregister();
-}
-
-module_init(ozwpan_init);
-module_exit(ozwpan_exit);
-
-MODULE_AUTHOR("Chris Kelly");
-MODULE_DESCRIPTION("Ozmo Devices USB over WiFi hcd driver");
-MODULE_VERSION("1.0.13");
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/staging/ozwpan/ozpd.c b/drivers/staging/ozwpan/ozpd.c
deleted file mode 100644
index 021d74a..0000000
--- a/drivers/staging/ozwpan/ozpd.c
+++ /dev/null
@@ -1,886 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/errno.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozcdev.h"
-#include "ozusbsvc.h"
-#include <asm/unaligned.h>
-#include <linux/uaccess.h>
-#include <net/psnap.h>
-
-static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd);
-static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f);
-static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f);
-static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f);
-static int oz_send_isoc_frame(struct oz_pd *pd);
-static void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f);
-static void oz_isoc_stream_free(struct oz_isoc_stream *st);
-static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data);
-static void oz_isoc_destructor(struct sk_buff *skb);
-
-/*
- * Counts the uncompleted isoc frames submitted to netcard.
- */
-static atomic_t g_submitted_isoc = ATOMIC_INIT(0);
-
-/* Application handler functions.
- */
-static const struct oz_app_if g_app_if[OZ_NB_APPS] = {
- [OZ_APPID_USB] = {
- .init = oz_usb_init,
- .term = oz_usb_term,
- .start = oz_usb_start,
- .stop = oz_usb_stop,
- .rx = oz_usb_rx,
- .heartbeat = oz_usb_heartbeat,
- .farewell = oz_usb_farewell,
- },
- [OZ_APPID_SERIAL] = {
- .init = oz_cdev_init,
- .term = oz_cdev_term,
- .start = oz_cdev_start,
- .stop = oz_cdev_stop,
- .rx = oz_cdev_rx,
- },
-};
-
-
-/*
- * Context: softirq or process
- */
-void oz_pd_set_state(struct oz_pd *pd, unsigned state)
-{
- pd->state = state;
- switch (state) {
- case OZ_PD_S_IDLE:
- oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_IDLE\n");
- break;
- case OZ_PD_S_CONNECTED:
- oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_CONNECTED\n");
- break;
- case OZ_PD_S_STOPPED:
- oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_STOPPED\n");
- break;
- case OZ_PD_S_SLEEP:
- oz_pd_dbg(pd, ON, "PD State: OZ_PD_S_SLEEP\n");
- break;
- }
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_get(struct oz_pd *pd)
-{
- atomic_inc(&pd->ref_count);
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_put(struct oz_pd *pd)
-{
- if (atomic_dec_and_test(&pd->ref_count))
- oz_pd_destroy(pd);
-}
-
-/*
- * Context: softirq-serialized
- */
-struct oz_pd *oz_pd_alloc(const u8 *mac_addr)
-{
- struct oz_pd *pd;
- int i;
-
- pd = kzalloc(sizeof(struct oz_pd), GFP_ATOMIC);
- if (!pd)
- return NULL;
-
- atomic_set(&pd->ref_count, 2);
- for (i = 0; i < OZ_NB_APPS; i++)
- spin_lock_init(&pd->app_lock[i]);
- pd->last_rx_pkt_num = 0xffffffff;
- oz_pd_set_state(pd, OZ_PD_S_IDLE);
- pd->max_tx_size = OZ_MAX_TX_SIZE;
- ether_addr_copy(pd->mac_addr, mac_addr);
- oz_elt_buf_init(&pd->elt_buff);
- spin_lock_init(&pd->tx_frame_lock);
- INIT_LIST_HEAD(&pd->tx_queue);
- INIT_LIST_HEAD(&pd->farewell_list);
- pd->last_sent_frame = &pd->tx_queue;
- spin_lock_init(&pd->stream_lock);
- INIT_LIST_HEAD(&pd->stream_list);
- tasklet_init(&pd->heartbeat_tasklet, oz_pd_heartbeat_handler,
- (unsigned long)pd);
- tasklet_init(&pd->timeout_tasklet, oz_pd_timeout_handler,
- (unsigned long)pd);
- hrtimer_init(&pd->heartbeat, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- hrtimer_init(&pd->timeout, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- pd->heartbeat.function = oz_pd_heartbeat_event;
- pd->timeout.function = oz_pd_timeout_event;
-
- return pd;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_pd_free(struct work_struct *work)
-{
- struct list_head *e, *n;
- struct oz_pd *pd;
-
- oz_pd_dbg(pd, ON, "Destroying PD\n");
- pd = container_of(work, struct oz_pd, workitem);
- /*Disable timer tasklets*/
- tasklet_kill(&pd->heartbeat_tasklet);
- tasklet_kill(&pd->timeout_tasklet);
-
- /* Free streams, queued tx frames and farewells. */
-
- list_for_each_safe(e, n, &pd->stream_list)
- oz_isoc_stream_free(list_entry(e, struct oz_isoc_stream, link));
-
- list_for_each_safe(e, n, &pd->tx_queue) {
- struct oz_tx_frame *f = list_entry(e, struct oz_tx_frame, link);
-
- if (f->skb != NULL)
- kfree_skb(f->skb);
- oz_retire_frame(pd, f);
- }
-
- oz_elt_buf_term(&pd->elt_buff);
-
- list_for_each_safe(e, n, &pd->farewell_list)
- kfree(list_entry(e, struct oz_farewell, link));
-
- if (pd->net_dev)
- dev_put(pd->net_dev);
- kfree(pd);
-}
-
-/*
- * Context: softirq or Process
- */
-void oz_pd_destroy(struct oz_pd *pd)
-{
- if (hrtimer_active(&pd->timeout))
- hrtimer_cancel(&pd->timeout);
- if (hrtimer_active(&pd->heartbeat))
- hrtimer_cancel(&pd->heartbeat);
-
- INIT_WORK(&pd->workitem, oz_pd_free);
- if (!schedule_work(&pd->workitem))
- oz_pd_dbg(pd, ON, "failed to schedule workitem\n");
-}
-
-/*
- * Context: softirq-serialized
- */
-int oz_services_start(struct oz_pd *pd, u16 apps, int resume)
-{
- int i, rc = 0;
-
- oz_pd_dbg(pd, ON, "%s: (0x%x) resume(%d)\n", __func__, apps, resume);
- for (i = 0; i < OZ_NB_APPS; i++) {
- if (g_app_if[i].start && (apps & (1 << i))) {
- if (g_app_if[i].start(pd, resume)) {
- rc = -1;
- oz_pd_dbg(pd, ON,
- "Unable to start service %d\n", i);
- break;
- }
- spin_lock_bh(&g_polling_lock);
- pd->total_apps |= (1 << i);
- if (resume)
- pd->paused_apps &= ~(1 << i);
- spin_unlock_bh(&g_polling_lock);
- }
- }
- return rc;
-}
-
-/*
- * Context: softirq or process
- */
-void oz_services_stop(struct oz_pd *pd, u16 apps, int pause)
-{
- int i;
-
- oz_pd_dbg(pd, ON, "%s: (0x%x) pause(%d)\n", __func__, apps, pause);
- for (i = 0; i < OZ_NB_APPS; i++) {
- if (g_app_if[i].stop && (apps & (1 << i))) {
- spin_lock_bh(&g_polling_lock);
- if (pause) {
- pd->paused_apps |= (1 << i);
- } else {
- pd->total_apps &= ~(1 << i);
- pd->paused_apps &= ~(1 << i);
- }
- spin_unlock_bh(&g_polling_lock);
- g_app_if[i].stop(pd, pause);
- }
- }
-}
-
-/*
- * Context: softirq
- */
-void oz_pd_heartbeat(struct oz_pd *pd, u16 apps)
-{
- int i, more = 0;
-
- for (i = 0; i < OZ_NB_APPS; i++) {
- if (g_app_if[i].heartbeat && (apps & (1 << i))) {
- if (g_app_if[i].heartbeat(pd))
- more = 1;
- }
- }
- if ((!more) && (hrtimer_active(&pd->heartbeat)))
- hrtimer_cancel(&pd->heartbeat);
- if (pd->mode & OZ_F_ISOC_ANYTIME) {
- int count = 8;
-
- while (count-- && (oz_send_isoc_frame(pd) >= 0))
- ;
- }
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_stop(struct oz_pd *pd)
-{
- u16 stop_apps;
-
- oz_dbg(ON, "oz_pd_stop() State = 0x%x\n", pd->state);
- oz_pd_indicate_farewells(pd);
- spin_lock_bh(&g_polling_lock);
- stop_apps = pd->total_apps;
- pd->total_apps = 0;
- pd->paused_apps = 0;
- spin_unlock_bh(&g_polling_lock);
- oz_services_stop(pd, stop_apps, 0);
- spin_lock_bh(&g_polling_lock);
- oz_pd_set_state(pd, OZ_PD_S_STOPPED);
- /* Remove from PD list.*/
- list_del(&pd->link);
- spin_unlock_bh(&g_polling_lock);
- oz_dbg(ON, "pd ref count = %d\n", atomic_read(&pd->ref_count));
- oz_pd_put(pd);
-}
-
-/*
- * Context: softirq
- */
-int oz_pd_sleep(struct oz_pd *pd)
-{
- int do_stop = 0;
- u16 stop_apps;
-
- spin_lock_bh(&g_polling_lock);
- if (pd->state & (OZ_PD_S_SLEEP | OZ_PD_S_STOPPED)) {
- spin_unlock_bh(&g_polling_lock);
- return 0;
- }
- if (pd->keep_alive && pd->session_id)
- oz_pd_set_state(pd, OZ_PD_S_SLEEP);
- else
- do_stop = 1;
-
- stop_apps = pd->total_apps;
- spin_unlock_bh(&g_polling_lock);
- if (do_stop) {
- oz_pd_stop(pd);
- } else {
- oz_services_stop(pd, stop_apps, 1);
- oz_timer_add(pd, OZ_TIMER_STOP, pd->keep_alive);
- }
- return do_stop;
-}
-
-/*
- * Context: softirq
- */
-static struct oz_tx_frame *oz_tx_frame_alloc(struct oz_pd *pd)
-{
- struct oz_tx_frame *f;
-
- f = kmem_cache_alloc(oz_tx_frame_cache, GFP_ATOMIC);
- if (f) {
- f->total_size = sizeof(struct oz_hdr);
- INIT_LIST_HEAD(&f->link);
- INIT_LIST_HEAD(&f->elt_list);
- }
- return f;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_tx_isoc_free(struct oz_pd *pd, struct oz_tx_frame *f)
-{
- pd->nb_queued_isoc_frames--;
- list_del_init(&f->link);
-
- kmem_cache_free(oz_tx_frame_cache, f);
-
- oz_dbg(TX_FRAMES, "Releasing ISOC Frame isoc_nb= %d\n",
- pd->nb_queued_isoc_frames);
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_tx_frame_free(struct oz_pd *pd, struct oz_tx_frame *f)
-{
- kmem_cache_free(oz_tx_frame_cache, f);
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_set_more_bit(struct sk_buff *skb)
-{
- struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
-
- oz_hdr->control |= OZ_F_MORE_DATA;
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_set_last_pkt_nb(struct oz_pd *pd, struct sk_buff *skb)
-{
- struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
-
- oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK;
-}
-
-/*
- * Context: softirq
- */
-int oz_prepare_frame(struct oz_pd *pd, int empty)
-{
- struct oz_tx_frame *f;
-
- if ((pd->mode & OZ_MODE_MASK) != OZ_MODE_TRIGGERED)
- return -1;
- if (pd->nb_queued_frames >= OZ_MAX_QUEUED_FRAMES)
- return -1;
- if (!empty && !oz_are_elts_available(&pd->elt_buff))
- return -1;
- f = oz_tx_frame_alloc(pd);
- if (f == NULL)
- return -1;
- f->skb = NULL;
- f->hdr.control =
- (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ACK_REQUESTED;
- ++pd->last_tx_pkt_num;
- put_unaligned(cpu_to_le32(pd->last_tx_pkt_num), &f->hdr.pkt_num);
- if (empty == 0) {
- oz_select_elts_for_tx(&pd->elt_buff, 0, &f->total_size,
- pd->max_tx_size, &f->elt_list);
- }
- spin_lock(&pd->tx_frame_lock);
- list_add_tail(&f->link, &pd->tx_queue);
- pd->nb_queued_frames++;
- spin_unlock(&pd->tx_frame_lock);
- return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-static struct sk_buff *oz_build_frame(struct oz_pd *pd, struct oz_tx_frame *f)
-{
- struct sk_buff *skb;
- struct net_device *dev = pd->net_dev;
- struct oz_hdr *oz_hdr;
- struct oz_elt *elt;
- struct oz_elt_info *ei;
-
- /* Allocate skb with enough space for the lower layers as well
- * as the space we need.
- */
- skb = alloc_skb(f->total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
- if (skb == NULL)
- return NULL;
- /* Reserve the head room for lower layers.
- */
- skb_reserve(skb, LL_RESERVED_SPACE(dev));
- skb_reset_network_header(skb);
- skb->dev = dev;
- skb->protocol = htons(OZ_ETHERTYPE);
- if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr,
- dev->dev_addr, skb->len) < 0)
- goto fail;
- /* Push the tail to the end of the area we are going to copy to.
- */
- oz_hdr = (struct oz_hdr *)skb_put(skb, f->total_size);
- f->hdr.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK;
- memcpy(oz_hdr, &f->hdr, sizeof(struct oz_hdr));
- /* Copy the elements into the frame body.
- */
- elt = (struct oz_elt *)(oz_hdr+1);
- list_for_each_entry(ei, &f->elt_list, link) {
- memcpy(elt, ei->data, ei->length);
- elt = oz_next_elt(elt);
- }
- return skb;
-fail:
- kfree_skb(skb);
- return NULL;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_retire_frame(struct oz_pd *pd, struct oz_tx_frame *f)
-{
- struct oz_elt_info *ei, *n;
-
- list_for_each_entry_safe(ei, n, &f->elt_list, link) {
- list_del_init(&ei->link);
- if (ei->callback)
- ei->callback(pd, ei->context);
- spin_lock_bh(&pd->elt_buff.lock);
- oz_elt_info_free(&pd->elt_buff, ei);
- spin_unlock_bh(&pd->elt_buff.lock);
- }
- oz_tx_frame_free(pd, f);
-}
-
-/*
- * Context: softirq-serialized
- */
-static int oz_send_next_queued_frame(struct oz_pd *pd, int more_data)
-{
- struct sk_buff *skb;
- struct oz_tx_frame *f;
- struct list_head *e;
-
- spin_lock(&pd->tx_frame_lock);
- e = pd->last_sent_frame->next;
- if (e == &pd->tx_queue) {
- spin_unlock(&pd->tx_frame_lock);
- return -1;
- }
- f = list_entry(e, struct oz_tx_frame, link);
-
- if (f->skb != NULL) {
- skb = f->skb;
- oz_tx_isoc_free(pd, f);
- spin_unlock(&pd->tx_frame_lock);
- if (more_data)
- oz_set_more_bit(skb);
- oz_set_last_pkt_nb(pd, skb);
- if ((int)atomic_read(&g_submitted_isoc) <
- OZ_MAX_SUBMITTED_ISOC) {
- if (dev_queue_xmit(skb) < 0) {
- oz_dbg(TX_FRAMES, "Dropping ISOC Frame\n");
- return -1;
- }
- atomic_inc(&g_submitted_isoc);
- oz_dbg(TX_FRAMES, "Sending ISOC Frame, nb_isoc= %d\n",
- pd->nb_queued_isoc_frames);
- return 0;
- }
- kfree_skb(skb);
- oz_dbg(TX_FRAMES, "Dropping ISOC Frame>\n");
- return -1;
- }
-
- pd->last_sent_frame = e;
- skb = oz_build_frame(pd, f);
- spin_unlock(&pd->tx_frame_lock);
- if (!skb)
- return -1;
- if (more_data)
- oz_set_more_bit(skb);
- oz_dbg(TX_FRAMES, "TX frame PN=0x%x\n", f->hdr.pkt_num);
- if (dev_queue_xmit(skb) < 0)
- return -1;
-
- return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_send_queued_frames(struct oz_pd *pd, int backlog)
-{
- while (oz_prepare_frame(pd, 0) >= 0)
- backlog++;
-
- switch (pd->mode & (OZ_F_ISOC_NO_ELTS | OZ_F_ISOC_ANYTIME)) {
-
- case OZ_F_ISOC_NO_ELTS: {
- backlog += pd->nb_queued_isoc_frames;
- if (backlog <= 0)
- goto out;
- if (backlog > OZ_MAX_SUBMITTED_ISOC)
- backlog = OZ_MAX_SUBMITTED_ISOC;
- break;
- }
- case OZ_NO_ELTS_ANYTIME: {
- if ((backlog <= 0) && (pd->isoc_sent == 0))
- goto out;
- break;
- }
- default: {
- if (backlog <= 0)
- goto out;
- break;
- }
- }
- while (backlog--) {
- if (oz_send_next_queued_frame(pd, backlog) < 0)
- break;
- }
- return;
-
-out: oz_prepare_frame(pd, 1);
- oz_send_next_queued_frame(pd, 0);
-}
-
-/*
- * Context: softirq
- */
-static int oz_send_isoc_frame(struct oz_pd *pd)
-{
- struct sk_buff *skb;
- struct net_device *dev = pd->net_dev;
- struct oz_hdr *oz_hdr;
- struct oz_elt *elt;
- struct oz_elt_info *ei;
- LIST_HEAD(list);
- int total_size = sizeof(struct oz_hdr);
-
- oz_select_elts_for_tx(&pd->elt_buff, 1, &total_size,
- pd->max_tx_size, &list);
- if (list_empty(&list))
- return 0;
- skb = alloc_skb(total_size + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
- if (skb == NULL) {
- oz_dbg(ON, "Cannot alloc skb\n");
- oz_elt_info_free_chain(&pd->elt_buff, &list);
- return -1;
- }
- skb_reserve(skb, LL_RESERVED_SPACE(dev));
- skb_reset_network_header(skb);
- skb->dev = dev;
- skb->protocol = htons(OZ_ETHERTYPE);
- if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr,
- dev->dev_addr, skb->len) < 0) {
- kfree_skb(skb);
- return -1;
- }
- oz_hdr = (struct oz_hdr *)skb_put(skb, total_size);
- oz_hdr->control = (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC;
- oz_hdr->last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK;
- elt = (struct oz_elt *)(oz_hdr+1);
-
- list_for_each_entry(ei, &list, link) {
- memcpy(elt, ei->data, ei->length);
- elt = oz_next_elt(elt);
- }
- dev_queue_xmit(skb);
- oz_elt_info_free_chain(&pd->elt_buff, &list);
- return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn)
-{
- struct oz_tx_frame *f, *tmp = NULL;
- u8 diff;
- u32 pkt_num;
-
- LIST_HEAD(list);
-
- spin_lock(&pd->tx_frame_lock);
- list_for_each_entry(f, &pd->tx_queue, link) {
- pkt_num = le32_to_cpu(get_unaligned(&f->hdr.pkt_num));
- diff = (lpn - (pkt_num & OZ_LAST_PN_MASK)) & OZ_LAST_PN_MASK;
- if ((diff > OZ_LAST_PN_HALF_CYCLE) || (pkt_num == 0))
- break;
- oz_dbg(TX_FRAMES, "Releasing pkt_num= %u, nb= %d\n",
- pkt_num, pd->nb_queued_frames);
- tmp = f;
- pd->nb_queued_frames--;
- }
- if (tmp)
- list_cut_position(&list, &pd->tx_queue, &tmp->link);
- pd->last_sent_frame = &pd->tx_queue;
- spin_unlock(&pd->tx_frame_lock);
-
- list_for_each_entry_safe(f, tmp, &list, link)
- oz_retire_frame(pd, f);
-}
-
-/*
- * Precondition: stream_lock must be held.
- * Context: softirq
- */
-static struct oz_isoc_stream *pd_stream_find(struct oz_pd *pd, u8 ep_num)
-{
- struct oz_isoc_stream *st;
-
- list_for_each_entry(st, &pd->stream_list, link) {
- if (st->ep_num == ep_num)
- return st;
- }
- return NULL;
-}
-
-/*
- * Context: softirq
- */
-int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num)
-{
- struct oz_isoc_stream *st;
-
- st = kzalloc(sizeof(struct oz_isoc_stream), GFP_ATOMIC);
- if (!st)
- return -ENOMEM;
- st->ep_num = ep_num;
- spin_lock_bh(&pd->stream_lock);
- if (!pd_stream_find(pd, ep_num)) {
- list_add(&st->link, &pd->stream_list);
- st = NULL;
- }
- spin_unlock_bh(&pd->stream_lock);
- kfree(st);
- return 0;
-}
-
-/*
- * Context: softirq or process
- */
-static void oz_isoc_stream_free(struct oz_isoc_stream *st)
-{
- kfree_skb(st->skb);
- kfree(st);
-}
-
-/*
- * Context: softirq
- */
-int oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num)
-{
- struct oz_isoc_stream *st;
-
- spin_lock_bh(&pd->stream_lock);
- st = pd_stream_find(pd, ep_num);
- if (st)
- list_del(&st->link);
- spin_unlock_bh(&pd->stream_lock);
- if (st)
- oz_isoc_stream_free(st);
- return 0;
-}
-
-/*
- * Context: any
- */
-static void oz_isoc_destructor(struct sk_buff *skb)
-{
- atomic_dec(&g_submitted_isoc);
-}
-
-/*
- * Context: softirq
- */
-int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len)
-{
- struct net_device *dev = pd->net_dev;
- struct oz_isoc_stream *st;
- u8 nb_units = 0;
- struct sk_buff *skb = NULL;
- struct oz_hdr *oz_hdr = NULL;
- int size = 0;
-
- spin_lock_bh(&pd->stream_lock);
- st = pd_stream_find(pd, ep_num);
- if (st) {
- skb = st->skb;
- st->skb = NULL;
- nb_units = st->nb_units;
- st->nb_units = 0;
- oz_hdr = st->oz_hdr;
- size = st->size;
- }
- spin_unlock_bh(&pd->stream_lock);
- if (!st)
- return 0;
- if (!skb) {
- /* Allocate enough space for max size frame. */
- skb = alloc_skb(pd->max_tx_size + OZ_ALLOCATED_SPACE(dev),
- GFP_ATOMIC);
- if (skb == NULL)
- return 0;
- /* Reserve the head room for lower layers. */
- skb_reserve(skb, LL_RESERVED_SPACE(dev));
- skb_reset_network_header(skb);
- skb->dev = dev;
- skb->protocol = htons(OZ_ETHERTYPE);
- /* For audio packet set priority to AC_VO */
- skb->priority = 0x7;
- size = sizeof(struct oz_hdr) + sizeof(struct oz_isoc_large);
- oz_hdr = (struct oz_hdr *)skb_put(skb, size);
- }
- memcpy(skb_put(skb, len), data, len);
- size += len;
- if (++nb_units < pd->ms_per_isoc) {
- spin_lock_bh(&pd->stream_lock);
- st->skb = skb;
- st->nb_units = nb_units;
- st->oz_hdr = oz_hdr;
- st->size = size;
- spin_unlock_bh(&pd->stream_lock);
- } else {
- struct oz_hdr oz;
- struct oz_isoc_large iso;
-
- spin_lock_bh(&pd->stream_lock);
- iso.frame_number = st->frame_num;
- st->frame_num += nb_units;
- spin_unlock_bh(&pd->stream_lock);
- oz.control =
- (OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT) | OZ_F_ISOC;
- oz.last_pkt_num = pd->trigger_pkt_num & OZ_LAST_PN_MASK;
- oz.pkt_num = 0;
- iso.endpoint = ep_num;
- iso.format = OZ_DATA_F_ISOC_LARGE;
- iso.ms_data = nb_units;
- memcpy(oz_hdr, &oz, sizeof(oz));
- memcpy(oz_hdr+1, &iso, sizeof(iso));
- if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr,
- dev->dev_addr, skb->len) < 0)
- goto out;
-
- skb->destructor = oz_isoc_destructor;
- /*Queue for Xmit if mode is not ANYTIME*/
- if (!(pd->mode & OZ_F_ISOC_ANYTIME)) {
- struct oz_tx_frame *isoc_unit = NULL;
- int nb = pd->nb_queued_isoc_frames;
-
- if (nb >= pd->isoc_latency) {
- struct oz_tx_frame *f;
-
- oz_dbg(TX_FRAMES, "Dropping ISOC Unit nb= %d\n",
- nb);
- spin_lock(&pd->tx_frame_lock);
- list_for_each_entry(f, &pd->tx_queue, link) {
- if (f->skb != NULL) {
- oz_tx_isoc_free(pd, f);
- break;
- }
- }
- spin_unlock(&pd->tx_frame_lock);
- }
- isoc_unit = oz_tx_frame_alloc(pd);
- if (isoc_unit == NULL)
- goto out;
- isoc_unit->hdr = oz;
- isoc_unit->skb = skb;
- spin_lock_bh(&pd->tx_frame_lock);
- list_add_tail(&isoc_unit->link, &pd->tx_queue);
- pd->nb_queued_isoc_frames++;
- spin_unlock_bh(&pd->tx_frame_lock);
- oz_dbg(TX_FRAMES,
- "Added ISOC Frame to Tx Queue isoc_nb= %d, nb= %d\n",
- pd->nb_queued_isoc_frames, pd->nb_queued_frames);
- return 0;
- }
-
- /*In ANYTIME mode Xmit unit immediately*/
- if (atomic_read(&g_submitted_isoc) < OZ_MAX_SUBMITTED_ISOC) {
- atomic_inc(&g_submitted_isoc);
- if (dev_queue_xmit(skb) < 0)
- return -1;
- return 0;
- }
-
-out: kfree_skb(skb);
- return -1;
-
- }
- return 0;
-}
-
-/*
- * Context: process
- */
-void oz_apps_init(void)
-{
- int i;
-
- for (i = 0; i < OZ_NB_APPS; i++) {
- if (g_app_if[i].init)
- g_app_if[i].init();
- }
-}
-
-/*
- * Context: process
- */
-void oz_apps_term(void)
-{
- int i;
-
- /* Terminate all the apps. */
- for (i = 0; i < OZ_NB_APPS; i++) {
- if (g_app_if[i].term)
- g_app_if[i].term();
- }
-}
-
-/*
- * Context: softirq-serialized
- */
-void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt)
-{
- if (app_id < OZ_NB_APPS && g_app_if[app_id].rx)
- g_app_if[app_id].rx(pd, elt);
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_indicate_farewells(struct oz_pd *pd)
-{
- struct oz_farewell *f;
- const struct oz_app_if *ai = &g_app_if[OZ_APPID_USB];
-
- while (1) {
- spin_lock_bh(&g_polling_lock);
- if (list_empty(&pd->farewell_list)) {
- spin_unlock_bh(&g_polling_lock);
- break;
- }
- f = list_first_entry(&pd->farewell_list,
- struct oz_farewell, link);
- list_del(&f->link);
- spin_unlock_bh(&g_polling_lock);
- if (ai->farewell)
- ai->farewell(pd, f->ep_num, f->report, f->len);
- kfree(f);
- }
-}
diff --git a/drivers/staging/ozwpan/ozpd.h b/drivers/staging/ozwpan/ozpd.h
deleted file mode 100644
index 212fab0..0000000
--- a/drivers/staging/ozwpan/ozpd.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZPD_H_
-#define _OZPD_H_
-
-#include <linux/interrupt.h>
-#include "ozeltbuf.h"
-
-/* PD state
- */
-#define OZ_PD_S_IDLE 0x1
-#define OZ_PD_S_CONNECTED 0x2
-#define OZ_PD_S_SLEEP 0x4
-#define OZ_PD_S_STOPPED 0x8
-
-/* Timer event types.
- */
-#define OZ_TIMER_TOUT 1
-#define OZ_TIMER_HEARTBEAT 2
-#define OZ_TIMER_STOP 3
-
-/*
- *External spinlock variable
- */
-extern spinlock_t g_polling_lock;
-
-/* Data structure that hold information on a frame for transmisson. This is
- * built when the frame is first transmitted and is used to rebuild the frame
- * if a re-transmission is required.
- */
-struct oz_tx_frame {
- struct list_head link;
- struct list_head elt_list;
- struct oz_hdr hdr;
- struct sk_buff *skb;
- int total_size;
-};
-
-struct oz_isoc_stream {
- struct list_head link;
- u8 ep_num;
- u8 frame_num;
- u8 nb_units;
- int size;
- struct sk_buff *skb;
- struct oz_hdr *oz_hdr;
-};
-
-struct oz_farewell {
- struct list_head link;
- u8 ep_num;
- u8 index;
- u8 len;
- u8 report[0];
-};
-
-/* Data structure that holds information on a specific peripheral device (PD).
- */
-struct oz_pd {
- struct list_head link;
- atomic_t ref_count;
- u8 mac_addr[ETH_ALEN];
- unsigned state;
- unsigned state_flags;
- unsigned send_flags;
- u16 total_apps;
- u16 paused_apps;
- u8 session_id;
- u8 param_rsp_status;
- u8 pd_info;
- u8 isoc_sent;
- u32 last_rx_pkt_num;
- u32 last_tx_pkt_num;
- struct timespec last_rx_timestamp;
- u32 trigger_pkt_num;
- unsigned long pulse_time;
- unsigned long pulse_period;
- unsigned long presleep;
- unsigned long keep_alive;
- struct oz_elt_buf elt_buff;
- void *app_ctx[OZ_NB_APPS];
- spinlock_t app_lock[OZ_NB_APPS];
- int max_tx_size;
- u8 mode;
- u8 ms_per_isoc;
- unsigned isoc_latency;
- unsigned max_stream_buffering;
- int nb_queued_frames;
- int nb_queued_isoc_frames;
- spinlock_t tx_frame_lock;
- struct list_head *last_sent_frame;
- struct list_head tx_queue;
- struct list_head farewell_list;
- spinlock_t stream_lock;
- struct list_head stream_list;
- struct net_device *net_dev;
- struct hrtimer heartbeat;
- struct hrtimer timeout;
- u8 timeout_type;
- struct tasklet_struct heartbeat_tasklet;
- struct tasklet_struct timeout_tasklet;
- struct work_struct workitem;
-};
-
-#define OZ_MAX_QUEUED_FRAMES 4
-
-struct oz_pd *oz_pd_alloc(const u8 *mac_addr);
-void oz_pd_destroy(struct oz_pd *pd);
-void oz_pd_get(struct oz_pd *pd);
-void oz_pd_put(struct oz_pd *pd);
-void oz_pd_set_state(struct oz_pd *pd, unsigned state);
-void oz_pd_indicate_farewells(struct oz_pd *pd);
-int oz_pd_sleep(struct oz_pd *pd);
-void oz_pd_stop(struct oz_pd *pd);
-void oz_pd_heartbeat(struct oz_pd *pd, u16 apps);
-int oz_services_start(struct oz_pd *pd, u16 apps, int resume);
-void oz_services_stop(struct oz_pd *pd, u16 apps, int pause);
-int oz_prepare_frame(struct oz_pd *pd, int empty);
-void oz_send_queued_frames(struct oz_pd *pd, int backlog);
-void oz_retire_tx_frames(struct oz_pd *pd, u8 lpn);
-int oz_isoc_stream_create(struct oz_pd *pd, u8 ep_num);
-int oz_isoc_stream_delete(struct oz_pd *pd, u8 ep_num);
-int oz_send_isoc_unit(struct oz_pd *pd, u8 ep_num, const u8 *data, int len);
-void oz_handle_app_elt(struct oz_pd *pd, u8 app_id, struct oz_elt *elt);
-void oz_apps_init(void);
-void oz_apps_term(void);
-
-extern struct kmem_cache *oz_elt_info_cache;
-extern struct kmem_cache *oz_tx_frame_cache;
-
-#endif /* Sentry */
diff --git a/drivers/staging/ozwpan/ozproto.c b/drivers/staging/ozwpan/ozproto.c
deleted file mode 100644
index 1ba24a2..0000000
--- a/drivers/staging/ozwpan/ozproto.c
+++ /dev/null
@@ -1,813 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/errno.h>
-#include <linux/ieee80211.h>
-#include <linux/slab.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozusbsvc.h"
-
-#include "ozappif.h"
-#include <asm/unaligned.h>
-#include <linux/uaccess.h>
-#include <net/psnap.h>
-
-#define OZ_CF_CONN_SUCCESS 1
-#define OZ_CF_CONN_FAILURE 2
-
-#define OZ_DO_STOP 1
-#define OZ_DO_SLEEP 2
-
-struct oz_binding {
- struct packet_type ptype;
- char name[OZ_MAX_BINDING_LEN];
- struct list_head link;
-};
-
-/*
- * External variable
- */
-
-DEFINE_SPINLOCK(g_polling_lock);
-/*
- * Static external variables.
- */
-static LIST_HEAD(g_pd_list);
-static LIST_HEAD(g_binding);
-static DEFINE_SPINLOCK(g_binding_lock);
-static struct sk_buff_head g_rx_queue;
-static u8 g_session_id;
-static u16 g_apps = 0x1;
-static int g_processing_rx;
-
-struct kmem_cache *oz_elt_info_cache;
-struct kmem_cache *oz_tx_frame_cache;
-
-/*
- * Context: softirq-serialized
- */
-static u8 oz_get_new_session_id(u8 exclude)
-{
- if (++g_session_id == 0)
- g_session_id = 1;
- if (g_session_id == exclude) {
- if (++g_session_id == 0)
- g_session_id = 1;
- }
- return g_session_id;
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_send_conn_rsp(struct oz_pd *pd, u8 status)
-{
- struct sk_buff *skb;
- struct net_device *dev = pd->net_dev;
- struct oz_hdr *oz_hdr;
- struct oz_elt *elt;
- struct oz_elt_connect_rsp *body;
-
- int sz = sizeof(struct oz_hdr) + sizeof(struct oz_elt) +
- sizeof(struct oz_elt_connect_rsp);
- skb = alloc_skb(sz + OZ_ALLOCATED_SPACE(dev), GFP_ATOMIC);
- if (skb == NULL)
- return;
- skb_reserve(skb, LL_RESERVED_SPACE(dev));
- skb_reset_network_header(skb);
- oz_hdr = (struct oz_hdr *)skb_put(skb, sz);
- elt = (struct oz_elt *)(oz_hdr+1);
- body = (struct oz_elt_connect_rsp *)(elt+1);
- skb->dev = dev;
- skb->protocol = htons(OZ_ETHERTYPE);
- /* Fill in device header */
- if (dev_hard_header(skb, dev, OZ_ETHERTYPE, pd->mac_addr,
- dev->dev_addr, skb->len) < 0) {
- kfree_skb(skb);
- return;
- }
- oz_hdr->control = OZ_PROTOCOL_VERSION<<OZ_VERSION_SHIFT;
- oz_hdr->last_pkt_num = 0;
- put_unaligned(0, &oz_hdr->pkt_num);
- elt->type = OZ_ELT_CONNECT_RSP;
- elt->length = sizeof(struct oz_elt_connect_rsp);
- memset(body, 0, sizeof(struct oz_elt_connect_rsp));
- body->status = status;
- if (status == 0) {
- body->mode = pd->mode;
- body->session_id = pd->session_id;
- put_unaligned(cpu_to_le16(pd->total_apps), &body->apps);
- }
- oz_dbg(ON, "TX: OZ_ELT_CONNECT_RSP %d", status);
- dev_queue_xmit(skb);
-}
-
-/*
- * Context: softirq-serialized
- */
-static void pd_set_keepalive(struct oz_pd *pd, u8 kalive)
-{
- unsigned long keep_alive = kalive & OZ_KALIVE_VALUE_MASK;
-
- switch (kalive & OZ_KALIVE_TYPE_MASK) {
- case OZ_KALIVE_SPECIAL:
- pd->keep_alive = keep_alive * 1000*60*60*24*20;
- break;
- case OZ_KALIVE_SECS:
- pd->keep_alive = keep_alive*1000;
- break;
- case OZ_KALIVE_MINS:
- pd->keep_alive = keep_alive*1000*60;
- break;
- case OZ_KALIVE_HOURS:
- pd->keep_alive = keep_alive*1000*60*60;
- break;
- default:
- pd->keep_alive = 0;
- }
- oz_dbg(ON, "Keepalive = %lu mSec\n", pd->keep_alive);
-}
-
-/*
- * Context: softirq-serialized
- */
-static void pd_set_presleep(struct oz_pd *pd, u8 presleep, u8 start_timer)
-{
- if (presleep)
- pd->presleep = presleep*100;
- else
- pd->presleep = OZ_PRESLEEP_TOUT;
- if (start_timer) {
- spin_unlock(&g_polling_lock);
- oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep);
- spin_lock(&g_polling_lock);
- }
- oz_dbg(ON, "Presleep time = %lu mSec\n", pd->presleep);
-}
-
-/*
- * Context: softirq-serialized
- */
-static struct oz_pd *oz_connect_req(struct oz_pd *cur_pd, struct oz_elt *elt,
- const u8 *pd_addr, struct net_device *net_dev)
-{
- struct oz_pd *pd;
- struct oz_elt_connect_req *body =
- (struct oz_elt_connect_req *)(elt+1);
- u8 rsp_status = OZ_STATUS_SUCCESS;
- u8 stop_needed = 0;
- u16 new_apps = g_apps;
- struct net_device *old_net_dev = NULL;
- struct oz_pd *free_pd = NULL;
-
- if (cur_pd) {
- pd = cur_pd;
- spin_lock_bh(&g_polling_lock);
- } else {
- struct oz_pd *pd2 = NULL;
- struct list_head *e;
-
- pd = oz_pd_alloc(pd_addr);
- if (pd == NULL)
- return NULL;
- getnstimeofday(&pd->last_rx_timestamp);
- spin_lock_bh(&g_polling_lock);
- list_for_each(e, &g_pd_list) {
- pd2 = list_entry(e, struct oz_pd, link);
- if (ether_addr_equal(pd2->mac_addr, pd_addr)) {
- free_pd = pd;
- pd = pd2;
- break;
- }
- }
- if (pd != pd2)
- list_add_tail(&pd->link, &g_pd_list);
- }
- if (pd == NULL) {
- spin_unlock_bh(&g_polling_lock);
- return NULL;
- }
- if (pd->net_dev != net_dev) {
- old_net_dev = pd->net_dev;
- dev_hold(net_dev);
- pd->net_dev = net_dev;
- }
- oz_dbg(ON, "Host vendor: %d\n", body->host_vendor);
- pd->max_tx_size = OZ_MAX_TX_SIZE;
- pd->mode = body->mode;
- pd->pd_info = body->pd_info;
- if (pd->mode & OZ_F_ISOC_NO_ELTS) {
- pd->ms_per_isoc = body->ms_per_isoc;
- if (!pd->ms_per_isoc)
- pd->ms_per_isoc = 4;
-
- switch (body->ms_isoc_latency & OZ_LATENCY_MASK) {
- case OZ_ONE_MS_LATENCY:
- pd->isoc_latency = (body->ms_isoc_latency &
- ~OZ_LATENCY_MASK) / pd->ms_per_isoc;
- break;
- case OZ_TEN_MS_LATENCY:
- pd->isoc_latency = ((body->ms_isoc_latency &
- ~OZ_LATENCY_MASK) * 10) / pd->ms_per_isoc;
- break;
- default:
- pd->isoc_latency = OZ_MAX_TX_QUEUE_ISOC;
- }
- }
- if (body->max_len_div16)
- pd->max_tx_size = ((u16)body->max_len_div16)<<4;
- oz_dbg(ON, "Max frame:%u Ms per isoc:%u\n",
- pd->max_tx_size, pd->ms_per_isoc);
- pd->max_stream_buffering = 3*1024;
- pd->pulse_period = OZ_QUANTUM;
- pd_set_presleep(pd, body->presleep, 0);
- pd_set_keepalive(pd, body->keep_alive);
-
- new_apps &= le16_to_cpu(get_unaligned(&body->apps));
- if ((new_apps & 0x1) && (body->session_id)) {
- if (pd->session_id) {
- if (pd->session_id != body->session_id) {
- rsp_status = OZ_STATUS_SESSION_MISMATCH;
- goto done;
- }
- } else {
- new_apps &= ~0x1; /* Resume not permitted */
- pd->session_id =
- oz_get_new_session_id(body->session_id);
- }
- } else {
- if (pd->session_id && !body->session_id) {
- rsp_status = OZ_STATUS_SESSION_TEARDOWN;
- stop_needed = 1;
- } else {
- new_apps &= ~0x1; /* Resume not permitted */
- pd->session_id =
- oz_get_new_session_id(body->session_id);
- }
- }
-done:
- if (rsp_status == OZ_STATUS_SUCCESS) {
- u16 start_apps = new_apps & ~pd->total_apps & ~0x1;
- u16 stop_apps = pd->total_apps & ~new_apps & ~0x1;
- u16 resume_apps = new_apps & pd->paused_apps & ~0x1;
-
- spin_unlock_bh(&g_polling_lock);
- oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
- oz_dbg(ON, "new_apps=0x%x total_apps=0x%x paused_apps=0x%x\n",
- new_apps, pd->total_apps, pd->paused_apps);
- if (start_apps) {
- if (oz_services_start(pd, start_apps, 0))
- rsp_status = OZ_STATUS_TOO_MANY_PDS;
- }
- if (resume_apps)
- if (oz_services_start(pd, resume_apps, 1))
- rsp_status = OZ_STATUS_TOO_MANY_PDS;
- if (stop_apps)
- oz_services_stop(pd, stop_apps, 0);
- oz_pd_request_heartbeat(pd);
- } else {
- spin_unlock_bh(&g_polling_lock);
- }
- oz_send_conn_rsp(pd, rsp_status);
- if (rsp_status != OZ_STATUS_SUCCESS) {
- if (stop_needed)
- oz_pd_stop(pd);
- oz_pd_put(pd);
- pd = NULL;
- }
- if (old_net_dev)
- dev_put(old_net_dev);
- if (free_pd)
- oz_pd_destroy(free_pd);
- return pd;
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_add_farewell(struct oz_pd *pd, u8 ep_num, u8 index,
- const u8 *report, u8 len)
-{
- struct oz_farewell *f;
- struct oz_farewell *f2;
- int found = 0;
-
- f = kmalloc(sizeof(struct oz_farewell) + len, GFP_ATOMIC);
- if (!f)
- return;
- f->ep_num = ep_num;
- f->index = index;
- f->len = len;
- memcpy(f->report, report, len);
- oz_dbg(ON, "RX: Adding farewell report\n");
- spin_lock(&g_polling_lock);
- list_for_each_entry(f2, &pd->farewell_list, link) {
- if ((f2->ep_num == ep_num) && (f2->index == index)) {
- found = 1;
- list_del(&f2->link);
- break;
- }
- }
- list_add_tail(&f->link, &pd->farewell_list);
- spin_unlock(&g_polling_lock);
- if (found)
- kfree(f2);
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_rx_frame(struct sk_buff *skb)
-{
- u8 *mac_hdr;
- u8 *src_addr;
- struct oz_elt *elt;
- int length;
- struct oz_pd *pd = NULL;
- struct oz_hdr *oz_hdr = (struct oz_hdr *)skb_network_header(skb);
- struct timespec current_time;
- int dup = 0;
- u32 pkt_num;
-
- oz_dbg(RX_FRAMES, "RX frame PN=0x%x LPN=0x%x control=0x%x\n",
- oz_hdr->pkt_num, oz_hdr->last_pkt_num, oz_hdr->control);
- mac_hdr = skb_mac_header(skb);
- src_addr = &mac_hdr[ETH_ALEN];
- length = skb->len;
-
- /* Check the version field */
- if (oz_get_prot_ver(oz_hdr->control) != OZ_PROTOCOL_VERSION) {
- oz_dbg(ON, "Incorrect protocol version: %d\n",
- oz_get_prot_ver(oz_hdr->control));
- goto done;
- }
-
- pkt_num = le32_to_cpu(get_unaligned(&oz_hdr->pkt_num));
-
- pd = oz_pd_find(src_addr);
- if (pd) {
- if (!(pd->state & OZ_PD_S_CONNECTED))
- oz_pd_set_state(pd, OZ_PD_S_CONNECTED);
- getnstimeofday(¤t_time);
- if ((current_time.tv_sec != pd->last_rx_timestamp.tv_sec) ||
- (pd->presleep < MSEC_PER_SEC)) {
- oz_timer_add(pd, OZ_TIMER_TOUT, pd->presleep);
- pd->last_rx_timestamp = current_time;
- }
- if (pkt_num != pd->last_rx_pkt_num) {
- pd->last_rx_pkt_num = pkt_num;
- } else {
- dup = 1;
- oz_dbg(ON, "Duplicate frame\n");
- }
- }
-
- if (pd && !dup && ((pd->mode & OZ_MODE_MASK) == OZ_MODE_TRIGGERED)) {
- oz_dbg(RX_FRAMES, "Received TRIGGER Frame\n");
- pd->last_sent_frame = &pd->tx_queue;
- if (oz_hdr->control & OZ_F_ACK) {
- /* Retire completed frames */
- oz_retire_tx_frames(pd, oz_hdr->last_pkt_num);
- }
- if ((oz_hdr->control & OZ_F_ACK_REQUESTED) &&
- (pd->state == OZ_PD_S_CONNECTED)) {
- int backlog = pd->nb_queued_frames;
-
- pd->trigger_pkt_num = pkt_num;
- /* Send queued frames */
- oz_send_queued_frames(pd, backlog);
- }
- }
-
- length -= sizeof(struct oz_hdr);
- elt = (struct oz_elt *)((u8 *)oz_hdr + sizeof(struct oz_hdr));
-
- while (length >= sizeof(struct oz_elt)) {
- length -= sizeof(struct oz_elt) + elt->length;
- if (length < 0)
- break;
- switch (elt->type) {
- case OZ_ELT_CONNECT_REQ:
- oz_dbg(ON, "RX: OZ_ELT_CONNECT_REQ\n");
- pd = oz_connect_req(pd, elt, src_addr, skb->dev);
- break;
- case OZ_ELT_DISCONNECT:
- oz_dbg(ON, "RX: OZ_ELT_DISCONNECT\n");
- if (pd)
- oz_pd_sleep(pd);
- break;
- case OZ_ELT_UPDATE_PARAM_REQ: {
- struct oz_elt_update_param *body =
- (struct oz_elt_update_param *)(elt + 1);
- oz_dbg(ON, "RX: OZ_ELT_UPDATE_PARAM_REQ\n");
- if (pd && (pd->state & OZ_PD_S_CONNECTED)) {
- spin_lock(&g_polling_lock);
- pd_set_keepalive(pd, body->keepalive);
- pd_set_presleep(pd, body->presleep, 1);
- spin_unlock(&g_polling_lock);
- }
- }
- break;
- case OZ_ELT_FAREWELL_REQ: {
- struct oz_elt_farewell *body =
- (struct oz_elt_farewell *)(elt + 1);
- oz_dbg(ON, "RX: OZ_ELT_FAREWELL_REQ\n");
- oz_add_farewell(pd, body->ep_num,
- body->index, body->report,
- elt->length + 1 - sizeof(*body));
- }
- break;
- case OZ_ELT_APP_DATA:
- if (pd && (pd->state & OZ_PD_S_CONNECTED)) {
- struct oz_app_hdr *app_hdr =
- (struct oz_app_hdr *)(elt+1);
- if (dup)
- break;
- oz_handle_app_elt(pd, app_hdr->app_id, elt);
- }
- break;
- default:
- oz_dbg(ON, "RX: Unknown elt %02x\n", elt->type);
- }
- elt = oz_next_elt(elt);
- }
-done:
- if (pd)
- oz_pd_put(pd);
- consume_skb(skb);
-}
-
-/*
- * Context: process
- */
-void oz_protocol_term(void)
-{
- struct oz_binding *b, *t;
-
- /* Walk the list of bindings and remove each one.
- */
- spin_lock_bh(&g_binding_lock);
- list_for_each_entry_safe(b, t, &g_binding, link) {
- list_del(&b->link);
- spin_unlock_bh(&g_binding_lock);
- dev_remove_pack(&b->ptype);
- if (b->ptype.dev)
- dev_put(b->ptype.dev);
- kfree(b);
- spin_lock_bh(&g_binding_lock);
- }
- spin_unlock_bh(&g_binding_lock);
- /* Walk the list of PDs and stop each one. This causes the PD to be
- * removed from the list so we can just pull each one from the head
- * of the list.
- */
- spin_lock_bh(&g_polling_lock);
- while (!list_empty(&g_pd_list)) {
- struct oz_pd *pd =
- list_first_entry(&g_pd_list, struct oz_pd, link);
- oz_pd_get(pd);
- spin_unlock_bh(&g_polling_lock);
- oz_pd_stop(pd);
- oz_pd_put(pd);
- spin_lock_bh(&g_polling_lock);
- }
- spin_unlock_bh(&g_polling_lock);
- oz_dbg(ON, "Protocol stopped\n");
-
- kmem_cache_destroy(oz_tx_frame_cache);
- kmem_cache_destroy(oz_elt_info_cache);
-}
-
-/*
- * Context: softirq
- */
-void oz_pd_heartbeat_handler(unsigned long data)
-{
- struct oz_pd *pd = (struct oz_pd *)data;
- u16 apps = 0;
-
- spin_lock_bh(&g_polling_lock);
- if (pd->state & OZ_PD_S_CONNECTED)
- apps = pd->total_apps;
- spin_unlock_bh(&g_polling_lock);
- if (apps)
- oz_pd_heartbeat(pd, apps);
- oz_pd_put(pd);
-}
-
-/*
- * Context: softirq
- */
-void oz_pd_timeout_handler(unsigned long data)
-{
- int type;
- struct oz_pd *pd = (struct oz_pd *)data;
-
- spin_lock_bh(&g_polling_lock);
- type = pd->timeout_type;
- spin_unlock_bh(&g_polling_lock);
- switch (type) {
- case OZ_TIMER_TOUT:
- oz_pd_sleep(pd);
- break;
- case OZ_TIMER_STOP:
- oz_pd_stop(pd);
- break;
- }
- oz_pd_put(pd);
-}
-
-/*
- * Context: Interrupt
- */
-enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer)
-{
- struct oz_pd *pd;
-
- pd = container_of(timer, struct oz_pd, heartbeat);
- hrtimer_forward_now(timer, ktime_set(pd->pulse_period /
- MSEC_PER_SEC, (pd->pulse_period % MSEC_PER_SEC) * NSEC_PER_MSEC));
- oz_pd_get(pd);
- tasklet_schedule(&pd->heartbeat_tasklet);
- return HRTIMER_RESTART;
-}
-
-/*
- * Context: Interrupt
- */
-enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer)
-{
- struct oz_pd *pd;
-
- pd = container_of(timer, struct oz_pd, timeout);
- oz_pd_get(pd);
- tasklet_schedule(&pd->timeout_tasklet);
- return HRTIMER_NORESTART;
-}
-
-/*
- * Context: softirq or process
- */
-void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time)
-{
- spin_lock_bh(&g_polling_lock);
- switch (type) {
- case OZ_TIMER_TOUT:
- case OZ_TIMER_STOP:
- if (hrtimer_active(&pd->timeout)) {
- hrtimer_set_expires(&pd->timeout, ktime_set(due_time /
- MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
- NSEC_PER_MSEC));
- hrtimer_start_expires(&pd->timeout, HRTIMER_MODE_REL);
- } else {
- hrtimer_start(&pd->timeout, ktime_set(due_time /
- MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
- NSEC_PER_MSEC), HRTIMER_MODE_REL);
- }
- pd->timeout_type = type;
- break;
- case OZ_TIMER_HEARTBEAT:
- if (!hrtimer_active(&pd->heartbeat))
- hrtimer_start(&pd->heartbeat, ktime_set(due_time /
- MSEC_PER_SEC, (due_time % MSEC_PER_SEC) *
- NSEC_PER_MSEC), HRTIMER_MODE_REL);
- break;
- }
- spin_unlock_bh(&g_polling_lock);
-}
-
-/*
- * Context: softirq or process
- */
-void oz_pd_request_heartbeat(struct oz_pd *pd)
-{
- oz_timer_add(pd, OZ_TIMER_HEARTBEAT, pd->pulse_period > 0 ?
- pd->pulse_period : OZ_QUANTUM);
-}
-
-/*
- * Context: softirq or process
- */
-struct oz_pd *oz_pd_find(const u8 *mac_addr)
-{
- struct oz_pd *pd;
-
- spin_lock_bh(&g_polling_lock);
- list_for_each_entry(pd, &g_pd_list, link) {
- if (ether_addr_equal(pd->mac_addr, mac_addr)) {
- oz_pd_get(pd);
- spin_unlock_bh(&g_polling_lock);
- return pd;
- }
- }
- spin_unlock_bh(&g_polling_lock);
- return NULL;
-}
-
-/*
- * Context: process
- */
-void oz_app_enable(int app_id, int enable)
-{
- if (app_id < OZ_NB_APPS) {
- spin_lock_bh(&g_polling_lock);
- if (enable)
- g_apps |= (1<<app_id);
- else
- g_apps &= ~(1<<app_id);
- spin_unlock_bh(&g_polling_lock);
- }
-}
-
-/*
- * Context: softirq
- */
-static int oz_pkt_recv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *pt, struct net_device *orig_dev)
-{
- skb = skb_share_check(skb, GFP_ATOMIC);
- if (skb == NULL)
- return 0;
- spin_lock_bh(&g_rx_queue.lock);
- if (g_processing_rx) {
- /* We already hold the lock so use __ variant.
- */
- __skb_queue_head(&g_rx_queue, skb);
- spin_unlock_bh(&g_rx_queue.lock);
- } else {
- g_processing_rx = 1;
- do {
-
- spin_unlock_bh(&g_rx_queue.lock);
- oz_rx_frame(skb);
- spin_lock_bh(&g_rx_queue.lock);
- if (skb_queue_empty(&g_rx_queue)) {
- g_processing_rx = 0;
- spin_unlock_bh(&g_rx_queue.lock);
- break;
- }
- /* We already hold the lock so use __ variant.
- */
- skb = __skb_dequeue(&g_rx_queue);
- } while (1);
- }
- return 0;
-}
-
-/*
- * Context: process
- */
-void oz_binding_add(const char *net_dev)
-{
- struct oz_binding *binding;
-
- binding = kzalloc(sizeof(struct oz_binding), GFP_KERNEL);
- if (!binding)
- return;
-
- binding->ptype.type = htons(OZ_ETHERTYPE);
- binding->ptype.func = oz_pkt_recv;
- if (net_dev && *net_dev) {
- memcpy(binding->name, net_dev, OZ_MAX_BINDING_LEN);
- oz_dbg(ON, "Adding binding: %s\n", net_dev);
- binding->ptype.dev = dev_get_by_name(&init_net, net_dev);
- if (binding->ptype.dev == NULL) {
- oz_dbg(ON, "Netdev %s not found\n", net_dev);
- kfree(binding);
- return;
- }
- }
- dev_add_pack(&binding->ptype);
- spin_lock_bh(&g_binding_lock);
- list_add_tail(&binding->link, &g_binding);
- spin_unlock_bh(&g_binding_lock);
-}
-
-/*
- * Context: process
- */
-static void pd_stop_all_for_device(struct net_device *net_dev)
-{
- LIST_HEAD(h);
- struct oz_pd *pd;
- struct oz_pd *n;
-
- spin_lock_bh(&g_polling_lock);
- list_for_each_entry_safe(pd, n, &g_pd_list, link) {
- if (pd->net_dev == net_dev) {
- list_move(&pd->link, &h);
- oz_pd_get(pd);
- }
- }
- spin_unlock_bh(&g_polling_lock);
- while (!list_empty(&h)) {
- pd = list_first_entry(&h, struct oz_pd, link);
- oz_pd_stop(pd);
- oz_pd_put(pd);
- }
-}
-
-/*
- * Context: process
- */
-void oz_binding_remove(const char *net_dev)
-{
- struct oz_binding *binding;
- int found = 0;
-
- oz_dbg(ON, "Removing binding: %s\n", net_dev);
- spin_lock_bh(&g_binding_lock);
- list_for_each_entry(binding, &g_binding, link) {
- if (strncmp(binding->name, net_dev, OZ_MAX_BINDING_LEN) == 0) {
- oz_dbg(ON, "Binding '%s' found\n", net_dev);
- found = 1;
- break;
- }
- }
- spin_unlock_bh(&g_binding_lock);
- if (found) {
- dev_remove_pack(&binding->ptype);
- if (binding->ptype.dev) {
- dev_put(binding->ptype.dev);
- pd_stop_all_for_device(binding->ptype.dev);
- }
- list_del(&binding->link);
- kfree(binding);
- }
-}
-
-/*
- * Context: process
- */
-static char *oz_get_next_device_name(char *s, char *dname, int max_size)
-{
- while (*s == ',')
- s++;
- while (*s && (*s != ',') && max_size > 1) {
- *dname++ = *s++;
- max_size--;
- }
- *dname = 0;
- return s;
-}
-
-/*
- * Context: process
- */
-int oz_protocol_init(char *devs)
-{
- oz_elt_info_cache = KMEM_CACHE(oz_elt_info, 0);
- if (!oz_elt_info_cache)
- return -ENOMEM;
-
- oz_tx_frame_cache = KMEM_CACHE(oz_tx_frame, 0);
- if (!oz_tx_frame_cache) {
- kmem_cache_destroy(oz_elt_info_cache);
- return -ENOMEM;
- }
-
- skb_queue_head_init(&g_rx_queue);
- if (devs[0] == '*') {
- oz_binding_add(NULL);
- } else {
- char d[32];
-
- while (*devs) {
- devs = oz_get_next_device_name(devs, d, sizeof(d));
- if (d[0])
- oz_binding_add(d);
- }
- }
- return 0;
-}
-
-/*
- * Context: process
- */
-int oz_get_pd_list(struct oz_mac_addr *addr, int max_count)
-{
- struct oz_pd *pd;
- int count = 0;
-
- spin_lock_bh(&g_polling_lock);
- list_for_each_entry(pd, &g_pd_list, link) {
- if (count >= max_count)
- break;
- ether_addr_copy((u8 *)&addr[count++], pd->mac_addr);
- }
- spin_unlock_bh(&g_polling_lock);
- return count;
-}
-
diff --git a/drivers/staging/ozwpan/ozproto.h b/drivers/staging/ozwpan/ozproto.h
deleted file mode 100644
index 30c2db9..0000000
--- a/drivers/staging/ozwpan/ozproto.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZPROTO_H
-#define _OZPROTO_H
-
-#include <asm/byteorder.h>
-#include "ozdbg.h"
-#include "ozappif.h"
-
-#define OZ_ALLOCATED_SPACE(__x) (LL_RESERVED_SPACE(__x)+(__x)->needed_tailroom)
-
-/* Quantum in MS */
-#define OZ_QUANTUM 8
-/* Default timeouts.
- */
-#define OZ_PRESLEEP_TOUT 11
-
-/* Maximun sizes of tx frames. */
-#define OZ_MAX_TX_SIZE 760
-
-/* Maximum number of uncompleted isoc frames that can be pending in network. */
-#define OZ_MAX_SUBMITTED_ISOC 16
-
-/* Maximum number of uncompleted isoc frames that can be pending in Tx Queue. */
-#define OZ_MAX_TX_QUEUE_ISOC 32
-
-/* Application handler functions.
- */
-struct oz_app_if {
- int (*init)(void);
- void (*term)(void);
- int (*start)(struct oz_pd *pd, int resume);
- void (*stop)(struct oz_pd *pd, int pause);
- void (*rx)(struct oz_pd *pd, struct oz_elt *elt);
- int (*heartbeat)(struct oz_pd *pd);
- void (*farewell)(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len);
-};
-
-int oz_protocol_init(char *devs);
-void oz_protocol_term(void);
-int oz_get_pd_list(struct oz_mac_addr *addr, int max_count);
-void oz_app_enable(int app_id, int enable);
-struct oz_pd *oz_pd_find(const u8 *mac_addr);
-void oz_binding_add(const char *net_dev);
-void oz_binding_remove(const char *net_dev);
-void oz_timer_add(struct oz_pd *pd, int type, unsigned long due_time);
-void oz_timer_delete(struct oz_pd *pd, int type);
-void oz_pd_request_heartbeat(struct oz_pd *pd);
-void oz_pd_heartbeat_handler(unsigned long data);
-void oz_pd_timeout_handler(unsigned long data);
-enum hrtimer_restart oz_pd_heartbeat_event(struct hrtimer *timer);
-enum hrtimer_restart oz_pd_timeout_event(struct hrtimer *timer);
-int oz_get_pd_status_list(char *pd_list, int max_count);
-int oz_get_binding_list(char *buf, int max_if);
-
-extern struct kmem_cache *oz_elt_info_cache;
-extern struct kmem_cache *oz_tx_frame_cache;
-
-#endif /* _OZPROTO_H */
diff --git a/drivers/staging/ozwpan/ozprotocol.h b/drivers/staging/ozwpan/ozprotocol.h
deleted file mode 100644
index 4642072..0000000
--- a/drivers/staging/ozwpan/ozprotocol.h
+++ /dev/null
@@ -1,375 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZPROTOCOL_H
-#define _OZPROTOCOL_H
-
-#define PACKED __packed
-
-#define OZ_ETHERTYPE 0x892e
-
-/* Status codes
- */
-#define OZ_STATUS_SUCCESS 0
-#define OZ_STATUS_INVALID_PARAM 1
-#define OZ_STATUS_TOO_MANY_PDS 2
-#define OZ_STATUS_NOT_ALLOWED 4
-#define OZ_STATUS_SESSION_MISMATCH 5
-#define OZ_STATUS_SESSION_TEARDOWN 6
-
-/* This is the generic element header.
- Every element starts with this.
- */
-struct oz_elt {
- u8 type;
- u8 length;
-} PACKED;
-
-#define oz_next_elt(__elt) \
- (struct oz_elt *)((u8 *)((__elt) + 1) + (__elt)->length)
-
-/* Protocol element IDs.
- */
-#define OZ_ELT_CONNECT_REQ 0x06
-#define OZ_ELT_CONNECT_RSP 0x07
-#define OZ_ELT_DISCONNECT 0x08
-#define OZ_ELT_UPDATE_PARAM_REQ 0x11
-#define OZ_ELT_FAREWELL_REQ 0x12
-#define OZ_ELT_APP_DATA 0x31
-
-/* This is the Ozmo header which is the first Ozmo specific part
- * of a frame and comes after the MAC header.
- */
-struct oz_hdr {
- u8 control;
- u8 last_pkt_num;
- u32 pkt_num;
-} PACKED;
-
-#define OZ_PROTOCOL_VERSION 0x1
-/* Bits in the control field. */
-#define OZ_VERSION_MASK 0xc
-#define OZ_VERSION_SHIFT 2
-#define OZ_F_ACK 0x10
-#define OZ_F_ISOC 0x20
-#define OZ_F_MORE_DATA 0x40
-#define OZ_F_ACK_REQUESTED 0x80
-
-#define oz_get_prot_ver(__x) (((__x) & OZ_VERSION_MASK) >> OZ_VERSION_SHIFT)
-
-/* Used to select the bits of packet number to put in the last_pkt_num.
- */
-#define OZ_LAST_PN_MASK 0x00ff
-
-#define OZ_LAST_PN_HALF_CYCLE 127
-
-#define OZ_LATENCY_MASK 0xc0
-#define OZ_ONE_MS_LATENCY 0x40
-#define OZ_TEN_MS_LATENCY 0x80
-
-/* Connect request data structure.
- */
-struct oz_elt_connect_req {
- u8 mode;
- u8 resv1[16];
- u8 pd_info;
- u8 session_id;
- u8 presleep;
- u8 ms_isoc_latency;
- u8 host_vendor;
- u8 keep_alive;
- u16 apps;
- u8 max_len_div16;
- u8 ms_per_isoc;
- u8 resv3[2];
-} PACKED;
-
-/* mode field bits.
- */
-#define OZ_MODE_POLLED 0x0
-#define OZ_MODE_TRIGGERED 0x1
-#define OZ_MODE_MASK 0xf
-#define OZ_F_ISOC_NO_ELTS 0x40
-#define OZ_F_ISOC_ANYTIME 0x80
-#define OZ_NO_ELTS_ANYTIME 0xc0
-
-/* Keep alive field.
- */
-#define OZ_KALIVE_TYPE_MASK 0xc0
-#define OZ_KALIVE_VALUE_MASK 0x3f
-#define OZ_KALIVE_SPECIAL 0x00
-#define OZ_KALIVE_SECS 0x40
-#define OZ_KALIVE_MINS 0x80
-#define OZ_KALIVE_HOURS 0xc0
-
-/* Connect response data structure.
- */
-struct oz_elt_connect_rsp {
- u8 mode;
- u8 status;
- u8 resv1[3];
- u8 session_id;
- u16 apps;
- u32 resv2;
-} PACKED;
-
-struct oz_elt_farewell {
- u8 ep_num;
- u8 index;
- u8 report[1];
-} PACKED;
-
-struct oz_elt_update_param {
- u8 resv1[16];
- u8 presleep;
- u8 resv2;
- u8 host_vendor;
- u8 keepalive;
-} PACKED;
-
-/* Header common to all application elements.
- */
-struct oz_app_hdr {
- u8 app_id;
- u8 elt_seq_num;
-} PACKED;
-
-/* Values for app_id.
- */
-#define OZ_APPID_USB 0x1
-#define OZ_APPID_SERIAL 0x4
-#define OZ_APPID_MAX OZ_APPID_SERIAL
-#define OZ_NB_APPS (OZ_APPID_MAX+1)
-
-/* USB header common to all elements for the USB application.
- * This header extends the oz_app_hdr and comes directly after
- * the element header in a USB application.
- */
-struct oz_usb_hdr {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
-} PACKED;
-
-
-
-/* USB requests element subtypes (type field of hs_usb_hdr).
- */
-#define OZ_GET_DESC_REQ 1
-#define OZ_GET_DESC_RSP 2
-#define OZ_SET_CONFIG_REQ 3
-#define OZ_SET_CONFIG_RSP 4
-#define OZ_SET_INTERFACE_REQ 5
-#define OZ_SET_INTERFACE_RSP 6
-#define OZ_VENDOR_CLASS_REQ 7
-#define OZ_VENDOR_CLASS_RSP 8
-#define OZ_GET_STATUS_REQ 9
-#define OZ_GET_STATUS_RSP 10
-#define OZ_CLEAR_FEATURE_REQ 11
-#define OZ_CLEAR_FEATURE_RSP 12
-#define OZ_SET_FEATURE_REQ 13
-#define OZ_SET_FEATURE_RSP 14
-#define OZ_GET_CONFIGURATION_REQ 15
-#define OZ_GET_CONFIGURATION_RSP 16
-#define OZ_GET_INTERFACE_REQ 17
-#define OZ_GET_INTERFACE_RSP 18
-#define OZ_SYNCH_FRAME_REQ 19
-#define OZ_SYNCH_FRAME_RSP 20
-#define OZ_USB_ENDPOINT_DATA 23
-
-#define OZ_REQD_D2H 0x80
-
-struct oz_get_desc_req {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u16 offset;
- u16 size;
- u8 req_type;
- u8 desc_type;
- __le16 w_index;
- u8 index;
-} PACKED;
-
-/* Values for desc_type field.
-*/
-#define OZ_DESC_DEVICE 0x01
-#define OZ_DESC_CONFIG 0x02
-#define OZ_DESC_STRING 0x03
-
-/* Values for req_type field.
- */
-#define OZ_RECP_MASK 0x1F
-#define OZ_RECP_DEVICE 0x00
-#define OZ_RECP_INTERFACE 0x01
-#define OZ_RECP_ENDPOINT 0x02
-
-#define OZ_REQT_MASK 0x60
-#define OZ_REQT_STD 0x00
-#define OZ_REQT_CLASS 0x20
-#define OZ_REQT_VENDOR 0x40
-
-struct oz_get_desc_rsp {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- __le16 offset;
- __le16 total_size;
- u8 rcode;
- u8 data[1];
-} PACKED;
-
-struct oz_feature_req {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 recipient;
- u8 index;
- u16 feature;
-} PACKED;
-
-struct oz_feature_rsp {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 rcode;
-} PACKED;
-
-struct oz_set_config_req {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 index;
-} PACKED;
-
-struct oz_set_config_rsp {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 rcode;
-} PACKED;
-
-struct oz_set_interface_req {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 index;
- u8 alternative;
-} PACKED;
-
-struct oz_set_interface_rsp {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 rcode;
-} PACKED;
-
-struct oz_get_interface_req {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 index;
-} PACKED;
-
-struct oz_get_interface_rsp {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 rcode;
- u8 alternative;
-} PACKED;
-
-struct oz_vendor_class_req {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 req_type;
- u8 request;
- u16 value;
- u16 index;
- u8 data[1];
-} PACKED;
-
-struct oz_vendor_class_rsp {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 req_id;
- u8 rcode;
- u8 data[1];
-} PACKED;
-
-struct oz_data {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 endpoint;
- u8 format;
-} PACKED;
-
-struct oz_isoc_fixed {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 endpoint;
- u8 format;
- u8 unit_size;
- u8 frame_number;
- u8 data[1];
-} PACKED;
-
-struct oz_multiple_fixed {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 endpoint;
- u8 format;
- u8 unit_size;
- u8 data[1];
-} PACKED;
-
-struct oz_fragmented {
- u8 app_id;
- u8 elt_seq_num;
- u8 type;
- u8 endpoint;
- u8 format;
- u16 total_size;
- u16 offset;
- u8 data[1];
-} PACKED;
-
-/* Note: the following does not get packaged in an element in the same way
- * that other data formats are packaged. Instead the data is put in a frame
- * directly after the oz_header and is the only permitted data in such a
- * frame. The length of the data is directly determined from the frame size.
- */
-struct oz_isoc_large {
- u8 endpoint;
- u8 format;
- u8 ms_data;
- u8 frame_number;
-} PACKED;
-
-#define OZ_DATA_F_TYPE_MASK 0xF
-#define OZ_DATA_F_MULTIPLE_FIXED 0x1
-#define OZ_DATA_F_MULTIPLE_VAR 0x2
-#define OZ_DATA_F_ISOC_FIXED 0x3
-#define OZ_DATA_F_ISOC_VAR 0x4
-#define OZ_DATA_F_FRAGMENTED 0x5
-#define OZ_DATA_F_ISOC_LARGE 0x7
-
-#endif /* _OZPROTOCOL_H */
diff --git a/drivers/staging/ozwpan/ozurbparanoia.c b/drivers/staging/ozwpan/ozurbparanoia.c
deleted file mode 100644
index cf6278a..0000000
--- a/drivers/staging/ozwpan/ozurbparanoia.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#include <linux/usb.h>
-#include "ozdbg.h"
-
-#ifdef WANT_URB_PARANOIA
-
-#include "ozurbparanoia.h"
-
-#define OZ_MAX_URBS 1000
-struct urb *g_urb_memory[OZ_MAX_URBS];
-int g_nb_urbs;
-DEFINE_SPINLOCK(g_urb_mem_lock);
-
-void oz_remember_urb(struct urb *urb)
-{
- unsigned long irq_state;
-
- spin_lock_irqsave(&g_urb_mem_lock, irq_state);
- if (g_nb_urbs < OZ_MAX_URBS) {
- g_urb_memory[g_nb_urbs++] = urb;
- oz_dbg(ON, "urb up = %d %p\n", g_nb_urbs, urb);
- } else {
- oz_dbg(ON, "ERROR urb buffer full\n");
- }
- spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
-}
-
-/*
- */
-int oz_forget_urb(struct urb *urb)
-{
- unsigned long irq_state;
- int i;
- int rc = -1;
-
- spin_lock_irqsave(&g_urb_mem_lock, irq_state);
- for (i = 0; i < g_nb_urbs; i++) {
- if (g_urb_memory[i] == urb) {
- rc = 0;
- if (--g_nb_urbs > i)
- memcpy(&g_urb_memory[i], &g_urb_memory[i+1],
- (g_nb_urbs - i) * sizeof(struct urb *));
- oz_dbg(ON, "urb down = %d %p\n", g_nb_urbs, urb);
- }
- }
- spin_unlock_irqrestore(&g_urb_mem_lock, irq_state);
- return rc;
-}
-#endif /* #ifdef WANT_URB_PARANOIA */
-
diff --git a/drivers/staging/ozwpan/ozurbparanoia.h b/drivers/staging/ozwpan/ozurbparanoia.h
deleted file mode 100644
index 5080ea7..0000000
--- a/drivers/staging/ozwpan/ozurbparanoia.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _OZURBPARANOIA_H
-#define _OZURBPARANOIA_H
-/* -----------------------------------------------------------------------------
- * Released under the GNU General Public License Version 2 (GPLv2).
- * Copyright (c) 2011 Ozmo Inc
- * -----------------------------------------------------------------------------
- */
-
-#ifdef WANT_URB_PARANOIA
-void oz_remember_urb(struct urb *urb);
-int oz_forget_urb(struct urb *urb);
-#else
-static inline void oz_remember_urb(struct urb *urb) {}
-static inline int oz_forget_urb(struct urb *urb) { return 0; }
-#endif /* WANT_URB_PARANOIA */
-
-
-#endif /* _OZURBPARANOIA_H */
-
diff --git a/drivers/staging/ozwpan/ozusbif.h b/drivers/staging/ozwpan/ozusbif.h
deleted file mode 100644
index d2a6085..0000000
--- a/drivers/staging/ozwpan/ozusbif.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZUSBIF_H
-#define _OZUSBIF_H
-
-#include <linux/usb.h>
-
-/* Reference counting functions.
- */
-void oz_usb_get(void *hpd);
-void oz_usb_put(void *hpd);
-
-/* Stream functions.
- */
-int oz_usb_stream_create(void *hpd, u8 ep_num);
-int oz_usb_stream_delete(void *hpd, u8 ep_num);
-
-/* Request functions.
- */
-int oz_usb_control_req(void *hpd, u8 req_id, struct usb_ctrlrequest *setup,
- const u8 *data, int data_len);
-int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type,
- u8 index, __le16 windex, int offset, int len);
-int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb);
-void oz_usb_request_heartbeat(void *hpd);
-
-/* Confirmation functions.
- */
-void oz_hcd_get_desc_cnf(void *hport, u8 req_id, u8 status,
- const u8 *desc, u8 length, u16 offset, u16 total_size);
-void oz_hcd_control_cnf(void *hport, u8 req_id, u8 rcode,
- const u8 *data, int data_len);
-
-/* Indication functions.
- */
-void oz_hcd_data_ind(void *hport, u8 endpoint, const u8 *data, int data_len);
-
-int oz_hcd_heartbeat(void *hport);
-
-#endif /* _OZUSBIF_H */
diff --git a/drivers/staging/ozwpan/ozusbsvc.c b/drivers/staging/ozwpan/ozusbsvc.c
deleted file mode 100644
index bf15dc3..0000000
--- a/drivers/staging/ozwpan/ozusbsvc.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- *
- * This file provides protocol independent part of the implementation of the USB
- * service for a PD.
- * The implementation of this service is split into two parts the first of which
- * is protocol independent and the second contains protocol specific details.
- * This split is to allow alternative protocols to be defined.
- * The implementation of this service uses ozhcd.c to implement a USB HCD.
- * -----------------------------------------------------------------------------
- */
-
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/errno.h>
-#include <linux/input.h>
-#include <asm/unaligned.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozusbif.h"
-#include "ozhcd.h"
-#include "ozusbsvc.h"
-
-/*
- * This is called once when the driver is loaded to initialise the USB service.
- * Context: process
- */
-int oz_usb_init(void)
-{
- return oz_hcd_init();
-}
-
-/*
- * This is called once when the driver is unloaded to terminate the USB service.
- * Context: process
- */
-void oz_usb_term(void)
-{
- oz_hcd_term();
-}
-
-/*
- * This is called when the USB service is started or resumed for a PD.
- * Context: softirq
- */
-int oz_usb_start(struct oz_pd *pd, int resume)
-{
- int rc = 0;
- struct oz_usb_ctx *usb_ctx;
- struct oz_usb_ctx *old_ctx;
-
- if (resume) {
- oz_dbg(ON, "USB service resumed\n");
- return 0;
- }
- oz_dbg(ON, "USB service started\n");
- /* Create a USB context in case we need one. If we find the PD already
- * has a USB context then we will destroy it.
- */
- usb_ctx = kzalloc(sizeof(struct oz_usb_ctx), GFP_ATOMIC);
- if (usb_ctx == NULL)
- return -ENOMEM;
- atomic_set(&usb_ctx->ref_count, 1);
- usb_ctx->pd = pd;
- usb_ctx->stopped = 0;
- /* Install the USB context if the PD doesn't already have one.
- * If it does already have one then destroy the one we have just
- * created.
- */
- spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
- old_ctx = pd->app_ctx[OZ_APPID_USB];
- if (old_ctx == NULL)
- pd->app_ctx[OZ_APPID_USB] = usb_ctx;
- oz_usb_get(pd->app_ctx[OZ_APPID_USB]);
- spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
- if (old_ctx) {
- oz_dbg(ON, "Already have USB context\n");
- kfree(usb_ctx);
- usb_ctx = old_ctx;
- } else if (usb_ctx) {
- /* Take a reference to the PD. This will be released when
- * the USB context is destroyed.
- */
- oz_pd_get(pd);
- }
- /* If we already had a USB context and had obtained a port from
- * the USB HCD then just reset the port. If we didn't have a port
- * then report the arrival to the USB HCD so we get one.
- */
- if (usb_ctx->hport) {
- oz_hcd_pd_reset(usb_ctx, usb_ctx->hport);
- } else {
- usb_ctx->hport = oz_hcd_pd_arrived(usb_ctx);
- if (usb_ctx->hport == NULL) {
- oz_dbg(ON, "USB hub returned null port\n");
- spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
- pd->app_ctx[OZ_APPID_USB] = NULL;
- spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
- oz_usb_put(usb_ctx);
- rc = -1;
- }
- }
- oz_usb_put(usb_ctx);
- return rc;
-}
-
-/*
- * This is called when the USB service is stopped or paused for a PD.
- * Context: softirq or process
- */
-void oz_usb_stop(struct oz_pd *pd, int pause)
-{
- struct oz_usb_ctx *usb_ctx;
-
- if (pause) {
- oz_dbg(ON, "USB service paused\n");
- return;
- }
- spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
- usb_ctx = (struct oz_usb_ctx *) pd->app_ctx[OZ_APPID_USB];
- pd->app_ctx[OZ_APPID_USB] = NULL;
- spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
- if (usb_ctx) {
- struct timespec ts, now;
-
- getnstimeofday(&ts);
- oz_dbg(ON, "USB service stopping...\n");
- usb_ctx->stopped = 1;
- /* At this point the reference count on the usb context should
- * be 2 - one from when we created it and one from the hcd
- * which claims a reference. Since stopped = 1 no one else
- * should get in but someone may already be in. So wait
- * until they leave but timeout after 1 second.
- */
- while ((atomic_read(&usb_ctx->ref_count) > 2)) {
- getnstimeofday(&now);
- /*Approx 1 Sec. this is not perfect calculation*/
- if (now.tv_sec != ts.tv_sec)
- break;
- }
- oz_dbg(ON, "USB service stopped\n");
- oz_hcd_pd_departed(usb_ctx->hport);
- /* Release the reference taken in oz_usb_start.
- */
- oz_usb_put(usb_ctx);
- }
-}
-
-/*
- * This increments the reference count of the context area for a specific PD.
- * This ensures this context area does not disappear while still in use.
- * Context: softirq
- */
-void oz_usb_get(void *hpd)
-{
- struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
-
- atomic_inc(&usb_ctx->ref_count);
-}
-
-/*
- * This decrements the reference count of the context area for a specific PD
- * and destroys the context area if the reference count becomes zero.
- * Context: irq or process
- */
-void oz_usb_put(void *hpd)
-{
- struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
-
- if (atomic_dec_and_test(&usb_ctx->ref_count)) {
- oz_dbg(ON, "Dealloc USB context\n");
- oz_pd_put(usb_ctx->pd);
- kfree(usb_ctx);
- }
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_heartbeat(struct oz_pd *pd)
-{
- struct oz_usb_ctx *usb_ctx;
- int rc = 0;
-
- spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
- usb_ctx = (struct oz_usb_ctx *) pd->app_ctx[OZ_APPID_USB];
- if (usb_ctx)
- oz_usb_get(usb_ctx);
- spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
- if (usb_ctx == NULL)
- return rc;
- if (usb_ctx->stopped)
- goto done;
- if (usb_ctx->hport)
- if (oz_hcd_heartbeat(usb_ctx->hport))
- rc = 1;
-done:
- oz_usb_put(usb_ctx);
- return rc;
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_stream_create(void *hpd, u8 ep_num)
-{
- struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
- struct oz_pd *pd = usb_ctx->pd;
-
- oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num);
- if (pd->mode & OZ_F_ISOC_NO_ELTS) {
- oz_isoc_stream_create(pd, ep_num);
- } else {
- oz_pd_get(pd);
- if (oz_elt_stream_create(&pd->elt_buff, ep_num,
- 4*pd->max_tx_size)) {
- oz_pd_put(pd);
- return -1;
- }
- }
- return 0;
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_stream_delete(void *hpd, u8 ep_num)
-{
- struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
-
- if (usb_ctx) {
- struct oz_pd *pd = usb_ctx->pd;
-
- if (pd) {
- oz_dbg(ON, "%s: (0x%x)\n", __func__, ep_num);
- if (pd->mode & OZ_F_ISOC_NO_ELTS) {
- oz_isoc_stream_delete(pd, ep_num);
- } else {
- if (oz_elt_stream_delete(&pd->elt_buff, ep_num))
- return -1;
- oz_pd_put(pd);
- }
- }
- }
- return 0;
-}
-
-/*
- * Context: softirq or process
- */
-void oz_usb_request_heartbeat(void *hpd)
-{
- struct oz_usb_ctx *usb_ctx = (struct oz_usb_ctx *)hpd;
-
- if (usb_ctx && usb_ctx->pd)
- oz_pd_request_heartbeat(usb_ctx->pd);
-}
diff --git a/drivers/staging/ozwpan/ozusbsvc.h b/drivers/staging/ozwpan/ozusbsvc.h
deleted file mode 100644
index 58e05a5..0000000
--- a/drivers/staging/ozwpan/ozusbsvc.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- * -----------------------------------------------------------------------------
- */
-#ifndef _OZUSBSVC_H
-#define _OZUSBSVC_H
-
-/*------------------------------------------------------------------------------
- * Per PD context info stored in application context area of PD.
- * This object is reference counted to ensure it doesn't disappear while
- * still in use.
- */
-struct oz_usb_ctx {
- atomic_t ref_count;
- u8 tx_seq_num;
- u8 rx_seq_num;
- struct oz_pd *pd;
- void *hport;
- int stopped;
-};
-
-int oz_usb_init(void);
-void oz_usb_term(void);
-int oz_usb_start(struct oz_pd *pd, int resume);
-void oz_usb_stop(struct oz_pd *pd, int pause);
-void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt);
-int oz_usb_heartbeat(struct oz_pd *pd);
-void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len);
-
-#endif /* _OZUSBSVC_H */
-
diff --git a/drivers/staging/ozwpan/ozusbsvc1.c b/drivers/staging/ozwpan/ozusbsvc1.c
deleted file mode 100644
index 301fee8..0000000
--- a/drivers/staging/ozwpan/ozusbsvc1.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/* -----------------------------------------------------------------------------
- * Copyright (c) 2011 Ozmo Inc
- * Released under the GNU General Public License Version 2 (GPLv2).
- *
- * This file implements the protocol specific parts of the USB service for a PD.
- * -----------------------------------------------------------------------------
- */
-#include <linux/module.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
-#include <linux/netdevice.h>
-#include <linux/errno.h>
-#include <linux/input.h>
-#include <asm/unaligned.h>
-#include "ozdbg.h"
-#include "ozprotocol.h"
-#include "ozeltbuf.h"
-#include "ozpd.h"
-#include "ozproto.h"
-#include "ozusbif.h"
-#include "ozhcd.h"
-#include "ozusbsvc.h"
-
-#define MAX_ISOC_FIXED_DATA (253-sizeof(struct oz_isoc_fixed))
-
-/*
- * Context: softirq
- */
-static int oz_usb_submit_elt(struct oz_elt_buf *eb, struct oz_elt_info *ei,
- struct oz_usb_ctx *usb_ctx, u8 strid, u8 isoc)
-{
- int ret;
- struct oz_elt *elt = (struct oz_elt *)ei->data;
- struct oz_app_hdr *app_hdr = (struct oz_app_hdr *)(elt+1);
-
- elt->type = OZ_ELT_APP_DATA;
- ei->app_id = OZ_APPID_USB;
- ei->length = elt->length + sizeof(struct oz_elt);
- app_hdr->app_id = OZ_APPID_USB;
- spin_lock_bh(&eb->lock);
- if (isoc == 0) {
- app_hdr->elt_seq_num = usb_ctx->tx_seq_num++;
- if (usb_ctx->tx_seq_num == 0)
- usb_ctx->tx_seq_num = 1;
- }
- ret = oz_queue_elt_info(eb, isoc, strid, ei);
- if (ret)
- oz_elt_info_free(eb, ei);
- spin_unlock_bh(&eb->lock);
- return ret;
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_get_desc_req(void *hpd, u8 req_id, u8 req_type, u8 desc_type,
- u8 index, __le16 windex, int offset, int len)
-{
- struct oz_usb_ctx *usb_ctx = hpd;
- struct oz_pd *pd = usb_ctx->pd;
- struct oz_elt *elt;
- struct oz_get_desc_req *body;
- struct oz_elt_buf *eb = &pd->elt_buff;
- struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
-
- oz_dbg(ON, " req_type = 0x%x\n", req_type);
- oz_dbg(ON, " desc_type = 0x%x\n", desc_type);
- oz_dbg(ON, " index = 0x%x\n", index);
- oz_dbg(ON, " windex = 0x%x\n", windex);
- oz_dbg(ON, " offset = 0x%x\n", offset);
- oz_dbg(ON, " len = 0x%x\n", len);
- if (len > 200)
- len = 200;
- if (ei == NULL)
- return -1;
- elt = (struct oz_elt *)ei->data;
- elt->length = sizeof(struct oz_get_desc_req);
- body = (struct oz_get_desc_req *)(elt+1);
- body->type = OZ_GET_DESC_REQ;
- body->req_id = req_id;
- put_unaligned(cpu_to_le16(offset), &body->offset);
- put_unaligned(cpu_to_le16(len), &body->size);
- body->req_type = req_type;
- body->desc_type = desc_type;
- body->w_index = windex;
- body->index = index;
- return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-static int oz_usb_set_config_req(void *hpd, u8 req_id, u8 index)
-{
- struct oz_usb_ctx *usb_ctx = hpd;
- struct oz_pd *pd = usb_ctx->pd;
- struct oz_elt *elt;
- struct oz_elt_buf *eb = &pd->elt_buff;
- struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
- struct oz_set_config_req *body;
-
- if (ei == NULL)
- return -1;
- elt = (struct oz_elt *)ei->data;
- elt->length = sizeof(struct oz_set_config_req);
- body = (struct oz_set_config_req *)(elt+1);
- body->type = OZ_SET_CONFIG_REQ;
- body->req_id = req_id;
- body->index = index;
- return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-static int oz_usb_set_interface_req(void *hpd, u8 req_id, u8 index, u8 alt)
-{
- struct oz_usb_ctx *usb_ctx = hpd;
- struct oz_pd *pd = usb_ctx->pd;
- struct oz_elt *elt;
- struct oz_elt_buf *eb = &pd->elt_buff;
- struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
- struct oz_set_interface_req *body;
-
- if (ei == NULL)
- return -1;
- elt = (struct oz_elt *)ei->data;
- elt->length = sizeof(struct oz_set_interface_req);
- body = (struct oz_set_interface_req *)(elt+1);
- body->type = OZ_SET_INTERFACE_REQ;
- body->req_id = req_id;
- body->index = index;
- body->alternative = alt;
- return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-static int oz_usb_set_clear_feature_req(void *hpd, u8 req_id, u8 type,
- u8 recipient, u8 index, __le16 feature)
-{
- struct oz_usb_ctx *usb_ctx = hpd;
- struct oz_pd *pd = usb_ctx->pd;
- struct oz_elt *elt;
- struct oz_elt_buf *eb = &pd->elt_buff;
- struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
- struct oz_feature_req *body;
-
- if (ei == NULL)
- return -1;
- elt = (struct oz_elt *)ei->data;
- elt->length = sizeof(struct oz_feature_req);
- body = (struct oz_feature_req *)(elt+1);
- body->type = type;
- body->req_id = req_id;
- body->recipient = recipient;
- body->index = index;
- put_unaligned(feature, &body->feature);
- return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-static int oz_usb_vendor_class_req(void *hpd, u8 req_id, u8 req_type,
- u8 request, __le16 value, __le16 index, const u8 *data, int data_len)
-{
- struct oz_usb_ctx *usb_ctx = hpd;
- struct oz_pd *pd = usb_ctx->pd;
- struct oz_elt *elt;
- struct oz_elt_buf *eb = &pd->elt_buff;
- struct oz_elt_info *ei = oz_elt_info_alloc(&pd->elt_buff);
- struct oz_vendor_class_req *body;
-
- if (ei == NULL)
- return -1;
- elt = (struct oz_elt *)ei->data;
- elt->length = sizeof(struct oz_vendor_class_req) - 1 + data_len;
- body = (struct oz_vendor_class_req *)(elt+1);
- body->type = OZ_VENDOR_CLASS_REQ;
- body->req_id = req_id;
- body->req_type = req_type;
- body->request = request;
- put_unaligned(value, &body->value);
- put_unaligned(index, &body->index);
- if (data_len)
- memcpy(body->data, data, data_len);
- return oz_usb_submit_elt(eb, ei, usb_ctx, 0, 0);
-}
-
-/*
- * Context: tasklet
- */
-int oz_usb_control_req(void *hpd, u8 req_id, struct usb_ctrlrequest *setup,
- const u8 *data, int data_len)
-{
- unsigned wvalue = le16_to_cpu(setup->wValue);
- unsigned windex = le16_to_cpu(setup->wIndex);
- unsigned wlength = le16_to_cpu(setup->wLength);
- int rc = 0;
-
- if ((setup->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
- switch (setup->bRequest) {
- case USB_REQ_GET_DESCRIPTOR:
- rc = oz_usb_get_desc_req(hpd, req_id,
- setup->bRequestType, (u8)(wvalue>>8),
- (u8)wvalue, setup->wIndex, 0, wlength);
- break;
- case USB_REQ_SET_CONFIGURATION:
- rc = oz_usb_set_config_req(hpd, req_id, (u8)wvalue);
- break;
- case USB_REQ_SET_INTERFACE: {
- u8 if_num = (u8)windex;
- u8 alt = (u8)wvalue;
-
- rc = oz_usb_set_interface_req(hpd, req_id,
- if_num, alt);
- }
- break;
- case USB_REQ_SET_FEATURE:
- rc = oz_usb_set_clear_feature_req(hpd, req_id,
- OZ_SET_FEATURE_REQ,
- setup->bRequestType & 0xf, (u8)windex,
- setup->wValue);
- break;
- case USB_REQ_CLEAR_FEATURE:
- rc = oz_usb_set_clear_feature_req(hpd, req_id,
- OZ_CLEAR_FEATURE_REQ,
- setup->bRequestType & 0xf,
- (u8)windex, setup->wValue);
- break;
- }
- } else {
- rc = oz_usb_vendor_class_req(hpd, req_id, setup->bRequestType,
- setup->bRequest, setup->wValue, setup->wIndex,
- data, data_len);
- }
- return rc;
-}
-
-/*
- * Context: softirq
- */
-int oz_usb_send_isoc(void *hpd, u8 ep_num, struct urb *urb)
-{
- struct oz_usb_ctx *usb_ctx = hpd;
- struct oz_pd *pd = usb_ctx->pd;
- struct oz_elt_buf *eb;
- int i;
- int hdr_size;
- u8 *data;
- struct usb_iso_packet_descriptor *desc;
-
- if (pd->mode & OZ_F_ISOC_NO_ELTS) {
- for (i = 0; i < urb->number_of_packets; i++) {
- u8 *data;
-
- desc = &urb->iso_frame_desc[i];
- data = ((u8 *)urb->transfer_buffer)+desc->offset;
- oz_send_isoc_unit(pd, ep_num, data, desc->length);
- }
- return 0;
- }
-
- hdr_size = sizeof(struct oz_isoc_fixed) - 1;
- eb = &pd->elt_buff;
- i = 0;
- while (i < urb->number_of_packets) {
- struct oz_elt_info *ei = oz_elt_info_alloc(eb);
- struct oz_elt *elt;
- struct oz_isoc_fixed *body;
- int unit_count;
- int unit_size;
- int rem;
-
- if (ei == NULL)
- return -1;
- rem = MAX_ISOC_FIXED_DATA;
- elt = (struct oz_elt *)ei->data;
- body = (struct oz_isoc_fixed *)(elt + 1);
- body->type = OZ_USB_ENDPOINT_DATA;
- body->endpoint = ep_num;
- body->format = OZ_DATA_F_ISOC_FIXED;
- unit_size = urb->iso_frame_desc[i].length;
- body->unit_size = (u8)unit_size;
- data = ((u8 *)(elt+1)) + hdr_size;
- unit_count = 0;
- while (i < urb->number_of_packets) {
- desc = &urb->iso_frame_desc[i];
- if ((unit_size == desc->length) &&
- (desc->length <= rem)) {
- memcpy(data, ((u8 *)urb->transfer_buffer) +
- desc->offset, unit_size);
- data += unit_size;
- rem -= unit_size;
- unit_count++;
- desc->status = 0;
- desc->actual_length = desc->length;
- i++;
- } else {
- break;
- }
- }
- elt->length = hdr_size + MAX_ISOC_FIXED_DATA - rem;
- /* Store the number of units in body->frame_number for the
- * moment. This field will be correctly determined before
- * the element is sent. */
- body->frame_number = (u8)unit_count;
- oz_usb_submit_elt(eb, ei, usb_ctx, ep_num,
- pd->mode & OZ_F_ISOC_ANYTIME);
- }
- return 0;
-}
-
-/*
- * Context: softirq-serialized
- */
-static void oz_usb_handle_ep_data(struct oz_usb_ctx *usb_ctx,
- struct oz_usb_hdr *usb_hdr, int len)
-{
- struct oz_data *data_hdr = (struct oz_data *)usb_hdr;
-
- switch (data_hdr->format) {
- case OZ_DATA_F_MULTIPLE_FIXED: {
- struct oz_multiple_fixed *body =
- (struct oz_multiple_fixed *)data_hdr;
- u8 *data = body->data;
- unsigned int n;
- if (!body->unit_size ||
- len < sizeof(struct oz_multiple_fixed) - 1)
- break;
- n = (len - (sizeof(struct oz_multiple_fixed) - 1))
- / body->unit_size;
- while (n--) {
- oz_hcd_data_ind(usb_ctx->hport, body->endpoint,
- data, body->unit_size);
- data += body->unit_size;
- }
- }
- break;
- case OZ_DATA_F_ISOC_FIXED: {
- struct oz_isoc_fixed *body =
- (struct oz_isoc_fixed *)data_hdr;
- int data_len;
- int unit_size = body->unit_size;
- u8 *data = body->data;
- int count;
- int i;
-
- if (len < sizeof(struct oz_isoc_fixed) - 1)
- break;
- data_len = len - (sizeof(struct oz_isoc_fixed) - 1);
-
- if (!unit_size)
- break;
- count = data_len/unit_size;
- for (i = 0; i < count; i++) {
- oz_hcd_data_ind(usb_ctx->hport,
- body->endpoint, data, unit_size);
- data += unit_size;
- }
- }
- break;
- }
-
-}
-
-/*
- * This is called when the PD has received a USB element. The type of element
- * is determined and is then passed to an appropriate handler function.
- * Context: softirq-serialized
- */
-void oz_usb_rx(struct oz_pd *pd, struct oz_elt *elt)
-{
- struct oz_usb_hdr *usb_hdr = (struct oz_usb_hdr *)(elt + 1);
- struct oz_usb_ctx *usb_ctx;
-
- spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
- usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB];
- if (usb_ctx)
- oz_usb_get(usb_ctx);
- spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
- if (usb_ctx == NULL)
- return; /* Context has gone so nothing to do. */
- if (usb_ctx->stopped)
- goto done;
- /* If sequence number is non-zero then check it is not a duplicate.
- * Zero sequence numbers are always accepted.
- */
- if (usb_hdr->elt_seq_num != 0) {
- if (((usb_ctx->rx_seq_num - usb_hdr->elt_seq_num) & 0x80) == 0)
- /* Reject duplicate element. */
- goto done;
- }
- usb_ctx->rx_seq_num = usb_hdr->elt_seq_num;
- switch (usb_hdr->type) {
- case OZ_GET_DESC_RSP: {
- struct oz_get_desc_rsp *body =
- (struct oz_get_desc_rsp *)usb_hdr;
- u16 offs, total_size;
- u8 data_len;
-
- if (elt->length < sizeof(struct oz_get_desc_rsp) - 1)
- break;
- data_len = elt->length -
- (sizeof(struct oz_get_desc_rsp) - 1);
- offs = le16_to_cpu(get_unaligned(&body->offset));
- total_size =
- le16_to_cpu(get_unaligned(&body->total_size));
- oz_dbg(ON, "USB_REQ_GET_DESCRIPTOR - cnf\n");
- oz_hcd_get_desc_cnf(usb_ctx->hport, body->req_id,
- body->rcode, body->data,
- data_len, offs, total_size);
- }
- break;
- case OZ_SET_CONFIG_RSP: {
- struct oz_set_config_rsp *body =
- (struct oz_set_config_rsp *)usb_hdr;
- oz_hcd_control_cnf(usb_ctx->hport, body->req_id,
- body->rcode, NULL, 0);
- }
- break;
- case OZ_SET_INTERFACE_RSP: {
- struct oz_set_interface_rsp *body =
- (struct oz_set_interface_rsp *)usb_hdr;
- oz_hcd_control_cnf(usb_ctx->hport,
- body->req_id, body->rcode, NULL, 0);
- }
- break;
- case OZ_VENDOR_CLASS_RSP: {
- struct oz_vendor_class_rsp *body =
- (struct oz_vendor_class_rsp *)usb_hdr;
-
- if (elt->length <
- sizeof(struct oz_vendor_class_rsp) - 1)
- break;
-
- oz_hcd_control_cnf(usb_ctx->hport, body->req_id,
- body->rcode, body->data, elt->length-
- sizeof(struct oz_vendor_class_rsp)+1);
- }
- break;
- case OZ_USB_ENDPOINT_DATA:
- oz_usb_handle_ep_data(usb_ctx, usb_hdr, elt->length);
- break;
- }
-done:
- oz_usb_put(usb_ctx);
-}
-
-/*
- * Context: softirq, process
- */
-void oz_usb_farewell(struct oz_pd *pd, u8 ep_num, u8 *data, u8 len)
-{
- struct oz_usb_ctx *usb_ctx;
-
- spin_lock_bh(&pd->app_lock[OZ_APPID_USB]);
- usb_ctx = (struct oz_usb_ctx *)pd->app_ctx[OZ_APPID_USB];
- if (usb_ctx)
- oz_usb_get(usb_ctx);
- spin_unlock_bh(&pd->app_lock[OZ_APPID_USB]);
- if (usb_ctx == NULL)
- return; /* Context has gone so nothing to do. */
- if (!usb_ctx->stopped) {
- oz_dbg(ON, "Farewell indicated ep = 0x%x\n", ep_num);
- oz_hcd_data_ind(usb_ctx->hport, ep_num, data, len);
- }
- oz_usb_put(usb_ctx);
-}
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index bda208d..3e9ee7e 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -781,14 +781,18 @@
schedule_timeout_interruptible(msecs_to_jiffies(ms));
}
-/* send a serial byte to the LCD panel. The caller is responsible for locking
- if needed. */
+/*
+ * send a serial byte to the LCD panel. The caller is responsible for locking
+ * if needed.
+ */
static void lcd_send_serial(int byte)
{
int bit;
- /* the data bit is set on D0, and the clock on STROBE.
- * LCD reads D0 on STROBE's rising edge. */
+ /*
+ * the data bit is set on D0, and the clock on STROBE.
+ * LCD reads D0 on STROBE's rising edge.
+ */
for (bit = 0; bit < 8; bit++) {
bits.cl = BIT_CLR; /* CLK low */
panel_set_bits();
diff --git a/drivers/staging/rtl8188eu/core/rtw_ap.c b/drivers/staging/rtl8188eu/core/rtw_ap.c
index 581af88..5c45f8a 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ap.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ap.c
@@ -379,7 +379,8 @@
if (pmlmeext->active_keep_alive_check) {
int stainfo_offset;
- stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
+ stainfo_offset =
+ rtw_stainfo_offset(pstapriv, psta);
if (stainfo_offset_valid(stainfo_offset))
chk_alive_list[chk_alive_num++] = stainfo_offset;
continue;
@@ -1584,7 +1585,7 @@
}
}
- if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT)) {
+ if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) {
if (!psta->no_short_slot_time_set) {
psta->no_short_slot_time_set = 1;
diff --git a/drivers/staging/rtl8188eu/core/rtw_debug.c b/drivers/staging/rtl8188eu/core/rtw_debug.c
index bc3fe10..993c7db 100644
--- a/drivers/staging/rtl8188eu/core/rtw_debug.c
+++ b/drivers/staging/rtl8188eu/core/rtw_debug.c
@@ -219,6 +219,7 @@
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
int len = 0;
+
len += snprintf(page + len, count - len, "ht_option=%d\n", pmlmepriv->htpriv.ht_option);
*eof = 1;
return len;
@@ -588,6 +589,7 @@
if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {
int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength);
+
is_signal_dbg = is_signal_dbg == 0 ? 0 : 1;
if (is_signal_dbg && num != 2)
return count;
@@ -917,7 +919,7 @@
/* 5G */
if (pmlmeext->channel_set[i].ChannelNum >= 36 &&
pmlmeext->channel_set[i].ChannelNum < 140) {
- /* Find primary channel */
+ /* Find primary channel */
if (((pmlmeext->channel_set[i].ChannelNum - 36) % 8 == 0) &&
(pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
index_5G = i;
@@ -927,7 +929,7 @@
if (pmlmeext->channel_set[i].ChannelNum >= 149 &&
pmlmeext->channel_set[i].ChannelNum < 165) {
- /* find primary channel */
+ /* find primary channel */
if (((pmlmeext->channel_set[i].ChannelNum - 149) % 8 == 0) &&
(pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count)) {
index_5G = i;
diff --git a/drivers/staging/rtl8188eu/core/rtw_efuse.c b/drivers/staging/rtl8188eu/core/rtw_efuse.c
index dbaba2c..7b99ea9 100644
--- a/drivers/staging/rtl8188eu/core/rtw_efuse.c
+++ b/drivers/staging/rtl8188eu/core/rtw_efuse.c
@@ -551,7 +551,7 @@
bContinual = false;
}
} else if (ReadState & PG_STATE_DATA) {
- /* Data section Read ------------- */
+ /* Data section Read ------------- */
efuse_WordEnableDataRead(hworden, tmpdata, data);
efuse_addr = efuse_addr + (word_cnts*2)+1;
ReadState = PG_STATE_HEADER;
diff --git a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
index 11b780d..c3c5828 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ieee80211.c
@@ -19,6 +19,8 @@
******************************************************************************/
#define _IEEE80211_C
+#include <linux/ieee80211.h>
+
#include <drv_types.h>
#include <osdep_intf.h>
#include <ieee80211.h>
@@ -1042,7 +1044,7 @@
elems->timeout_int = pos;
elems->timeout_int_len = elen;
break;
- case WLAN_EID_HT_CAP:
+ case WLAN_EID_HT_CAPABILITY:
elems->ht_capabilities = pos;
elems->ht_capabilities_len = elen;
break;
diff --git a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
index 8c05cb0..22f5b45 100644
--- a/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
+++ b/drivers/staging/rtl8188eu/core/rtw_ioctl_set.c
@@ -183,7 +183,7 @@
if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
rtw_indicate_disconnect(padapter);
- rtw_free_assoc_resources(padapter, 1);
+ rtw_free_assoc_resources(padapter);
if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
@@ -271,7 +271,7 @@
if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
rtw_indicate_disconnect(padapter);
- rtw_free_assoc_resources(padapter, 1);
+ rtw_free_assoc_resources(padapter);
if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
@@ -293,7 +293,7 @@
if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
rtw_indicate_disconnect(padapter);
- rtw_free_assoc_resources(padapter, 1);
+ rtw_free_assoc_resources(padapter);
if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) {
_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
@@ -366,7 +366,7 @@
if ((check_fwstate(pmlmepriv, _FW_LINKED)) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)))
- rtw_free_assoc_resources(padapter, 1);
+ rtw_free_assoc_resources(padapter);
if ((*pold_state == Ndis802_11Infrastructure) || (*pold_state == Ndis802_11IBSS)) {
if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
@@ -415,7 +415,7 @@
rtw_disassoc_cmd(padapter, 0, true);
rtw_indicate_disconnect(padapter);
- rtw_free_assoc_resources(padapter, 1);
+ rtw_free_assoc_resources(padapter);
rtw_pwr_wakeup(padapter);
}
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme.c b/drivers/staging/rtl8188eu/core/rtw_mlme.c
index 0558451..2b917a1 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme.c
@@ -19,6 +19,7 @@
******************************************************************************/
#define _RTW_MLME_C_
+#include <linux/ieee80211.h>
#include <osdep_service.h>
#include <drv_types.h>
@@ -160,7 +161,7 @@
return pnetwork;
}
-static void _rtw_free_network(struct mlme_priv *pmlmepriv , struct wlan_network *pnetwork, u8 isfreeall)
+static void _rtw_free_network(struct mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
{
u32 curr_time, delta_time;
u32 lifetime = SCANQUEUE_LIFETIME;
@@ -352,8 +353,8 @@
((!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength)) == true) &&
((s_cap & WLAN_CAPABILITY_IBSS) ==
(d_cap & WLAN_CAPABILITY_IBSS)) &&
- ((s_cap & WLAN_CAPABILITY_BSS) ==
- (d_cap & WLAN_CAPABILITY_BSS)));
+ ((s_cap & WLAN_CAPABILITY_ESS) ==
+ (d_cap & WLAN_CAPABILITY_ESS)));
}
struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
@@ -581,7 +582,7 @@
}
/* TODO: Perry: For Power Management */
-void rtw_atimdone_event_callback(struct adapter *adapter , u8 *pbuf)
+void rtw_atimdone_event_callback(struct adapter *adapter, u8 *pbuf)
{
RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_evet\n"));
return;
@@ -614,7 +615,7 @@
spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->MacAddress);
if (ibss_wlan) {
- memcpy(ibss_wlan->network.IEs , pnetwork->IEs, 8);
+ memcpy(ibss_wlan->network.IEs, pnetwork->IEs, 8);
spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
goto exit;
}
@@ -692,8 +693,8 @@
pmlmepriv->to_join = false;
s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
if (_SUCCESS == s_ret) {
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
+ mod_timer(&pmlmepriv->assoc_timer,
+ jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
} else if (s_ret == 2) { /* there is no need to wait for join */
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
rtw_indicate_connect(adapter);
@@ -703,7 +704,7 @@
if (--pmlmepriv->to_roaming == 0 ||
_SUCCESS != rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) {
pmlmepriv->to_roaming = 0;
- rtw_free_assoc_resources(adapter, 1);
+ rtw_free_assoc_resources(adapter);
rtw_indicate_disconnect(adapter);
} else {
pmlmepriv->to_join = true;
@@ -757,7 +758,19 @@
/*
*rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
*/
-void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
+void rtw_free_assoc_resources(struct adapter *adapter)
+{
+ struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+ spin_lock_bh(&pmlmepriv->scanned_queue.lock);
+ rtw_free_assoc_resources_locked(adapter);
+ spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
+}
+
+/*
+*rtw_free_assoc_resources_locked: the caller has to lock pmlmepriv->lock
+*/
+void rtw_free_assoc_resources_locked(struct adapter *adapter)
{
struct wlan_network *pwlan = NULL;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
@@ -792,8 +805,6 @@
rtw_init_bcmc_stainfo(adapter);
}
- if (lock_scanned_queue)
- spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
if (pwlan)
@@ -804,8 +815,6 @@
if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1)))
rtw_free_network_nolock(pmlmepriv, pwlan);
- if (lock_scanned_queue)
- spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
pmlmepriv->key_mask = 0;
}
@@ -1301,7 +1310,7 @@
rtw_free_uc_swdec_pending_queue(adapter);
- rtw_free_assoc_resources(adapter, 1);
+ rtw_free_assoc_resources(adapter);
rtw_indicate_disconnect(adapter);
spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
/* remove the network entry in scanned_queue */
@@ -1382,7 +1391,7 @@
DBG_88E("%s try another roaming\n", __func__);
do_join_r = rtw_do_join(adapter);
if (_SUCCESS != do_join_r) {
- DBG_88E("%s roaming do_join return %d\n", __func__ , do_join_r);
+ DBG_88E("%s roaming do_join return %d\n", __func__, do_join_r);
continue;
}
break;
@@ -1556,7 +1565,7 @@
rtw_disassoc_cmd(adapter, 0, true);
rtw_indicate_disconnect(adapter);
- rtw_free_assoc_resources(adapter, 0);
+ rtw_free_assoc_resources_locked(adapter);
}
rtw_hal_get_def_var(adapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(supp_ant_div));
@@ -1997,7 +2006,7 @@
p = rtw_get_ie(in_ie+12, _HT_ADD_INFO_IE_, &ielen, in_len-12);
if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
out_len = *pout_len;
- rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2 , pout_len);
+ rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2, pout_len);
}
}
return phtpriv->ht_option;
diff --git a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
index a0b8f66..935b48e 100644
--- a/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8188eu/core/rtw_mlme_ext.c
@@ -1096,7 +1096,7 @@
/* Check if the AP's supported rates are also supported by STA. */
for (j = 0; j < sta_bssrate_len; j++) {
- /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
+ /* Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP */
if ((pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK)
== (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK))
break;
@@ -2932,7 +2932,7 @@
if (seq == 2) {
if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared) {
- /* legendary shared system */
+ /* legendary shared system */
p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
@@ -3367,7 +3367,7 @@
spin_unlock_bh(&pstapriv->asoc_list_lock);
/* now the station is qualified to join our BSS... */
- if (pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
+ if ((pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_ == status)) {
/* 1 bss_cap_update & sta_info_update */
bss_cap_update_on_sta_join(padapter, pstat);
sta_info_update(padapter, pstat);
@@ -4155,8 +4155,8 @@
u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
u8 *pframe = precv_frame->rx_data;
- if (ptable->func) {
- /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
+ if (ptable->func) {
+ /* receive the frames that ra(a1) is my address or ra(a1) is bc address. */
if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN) &&
memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
return;
diff --git a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
index ec0a8a4..9765946 100644
--- a/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8188eu/core/rtw_pwrctrl.c
@@ -70,7 +70,7 @@
}
}
/* s2-3. */
- rtw_free_assoc_resources(padapter, 1);
+ rtw_free_assoc_resources(padapter);
/* s2-4. */
rtw_free_network_queue(padapter, true);
@@ -549,12 +549,6 @@
(unsigned long)padapter);
}
-inline void rtw_set_ips_deny(struct adapter *padapter, u32 ms)
-{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
- pwrpriv->ips_deny_time = jiffies + msecs_to_jiffies(ms);
-}
-
/*
* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
* @adapter: pointer to struct adapter structure
diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c
index 8501eb8..44eeb03 100644
--- a/drivers/staging/rtl8188eu/core/rtw_recv.c
+++ b/drivers/staging/rtl8188eu/core/rtw_recv.c
@@ -74,10 +74,8 @@
precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(struct recv_frame) + RXFRAME_ALIGN_SZ);
- if (precvpriv->pallocated_frame_buf == NULL) {
- res = _FAIL;
- goto exit;
- }
+ if (!precvpriv->pallocated_frame_buf)
+ return _FAIL;
precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ);
@@ -89,7 +87,7 @@
list_add_tail(&(precvframe->list),
&(precvpriv->free_recv_queue.queue));
- res = rtw_os_recv_resource_alloc(padapter, precvframe);
+ rtw_os_recv_resource_alloc(precvframe);
precvframe->len = 0;
@@ -107,8 +105,6 @@
precvpriv->signal_stat_sampling_interval = 1000; /* ms */
rtw_set_signal_stat_timer(precvpriv);
-exit:
-
return res;
}
@@ -117,7 +113,6 @@
{
struct adapter *padapter = precvpriv->adapter;
-
rtw_free_uc_swdec_pending_queue(padapter);
if (precvpriv->pallocated_frame_buf) {
@@ -153,7 +148,6 @@
}
}
-
return (struct recv_frame *)hdr;
}
@@ -170,14 +164,6 @@
return precvframe;
}
-void rtw_init_recvframe(struct recv_frame *precvframe, struct recv_priv *precvpriv)
-{
- /* Perry: This can be removed */
- INIT_LIST_HEAD(&precvframe->list);
-
- precvframe->len = 0;
-}
-
int rtw_free_recvframe(struct recv_frame *precvframe,
struct __queue *pfree_recv_queue)
{
@@ -208,7 +194,6 @@
spin_unlock_bh(&pfree_recv_queue->lock);
-
return _SUCCESS;
}
@@ -217,7 +202,6 @@
struct adapter *padapter = precvframe->adapter;
struct recv_priv *precvpriv = &padapter->recvpriv;
-
list_del_init(&(precvframe->list));
list_add_tail(&(precvframe->list), get_list_head(queue));
@@ -226,7 +210,6 @@
precvpriv->free_recvframe_cnt++;
}
-
return _SUCCESS;
}
@@ -421,7 +404,6 @@
exit:
-
return res;
}
@@ -483,7 +465,6 @@
return_packet = NULL;
}
-
return return_packet;
}
@@ -502,7 +483,6 @@
struct rx_pkt_attrib *pattrib;
__be16 be_tmp;
-
pstapriv = &adapter->stapriv;
auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
@@ -561,7 +541,6 @@
prtnframe = precv_frame;
}
-
return prtnframe;
}
@@ -573,7 +552,6 @@
u16 seq_ctrl = ((precv_frame->attrib.seq_num&0xffff) << 4) |
(precv_frame->attrib.frag_num & 0xf);
-
if (tid > 15) {
RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, (tid>15)! seq_ctrl=0x%x, tid=0x%x\n", seq_ctrl, tid));
@@ -590,7 +568,6 @@
prxcache->tid_rxseq[tid] = seq_ctrl;
-
return _SUCCESS;
}
@@ -727,7 +704,6 @@
u8 *sta_addr = NULL;
int bmcast = IS_MCAST(pattrib->dst);
-
if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
/* filter packets that SA is myself or multicast or broadcast */
@@ -815,7 +791,6 @@
u8 *myhwaddr = myid(&adapter->eeprompriv);
int bmcast = IS_MCAST(pattrib->dst);
-
if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) &&
(check_fwstate(pmlmepriv, _FW_LINKED) == true ||
check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) {
@@ -907,7 +882,6 @@
exit:
-
return ret;
}
@@ -922,7 +896,6 @@
unsigned char *mybssid = get_bssid(pmlmepriv);
int ret = _SUCCESS;
-
if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
/* For AP mode, RA = BSSID, TX = STA(SRC_ADDR), A3 = DST_ADDR */
if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
@@ -967,7 +940,6 @@
exit:
-
return ret;
}
@@ -1149,7 +1121,6 @@
struct security_priv *psecuritypriv = &adapter->securitypriv;
int ret = _SUCCESS;
-
bretry = GetRetry(ptr);
pda = get_da(ptr);
psa = get_sa(ptr);
@@ -1253,7 +1224,6 @@
exit:
-
return ret;
}
@@ -1273,7 +1243,6 @@
u8 ver = (unsigned char)(*ptr)&0x3;
struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
-
if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
int ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, rtw_get_oper_ch(adapter));
if (ch_set_idx >= 0)
@@ -1362,7 +1331,6 @@
exit:
-
return retval;
}
@@ -1445,7 +1413,6 @@
struct recv_frame *prframe, *pnextrframe;
struct __queue *pfree_recv_queue;
-
curfragnum = 0;
pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
@@ -1510,7 +1477,6 @@
RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Performance defrag!!!!!\n"));
-
return prframe;
}
@@ -1528,7 +1494,6 @@
struct recv_frame *prtnframe = NULL;
struct __queue *pfree_recv_queue, *pdefrag_q;
-
pstapriv = &padapter->stapriv;
pfhdr = precv_frame;
@@ -1612,7 +1577,6 @@
}
}
-
return prtnframe;
}
@@ -2116,7 +2080,6 @@
struct recv_priv *precvpriv;
s32 ret = _SUCCESS;
-
padapter = precvframe->adapter;
precvpriv = &padapter->recvpriv;
@@ -2129,7 +2092,6 @@
precvpriv->rx_pkts++;
-
return ret;
_recv_entry_drop:
diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c b/drivers/staging/rtl8188eu/core/rtw_security.c
index d870a5c..22839d5 100644
--- a/drivers/staging/rtl8188eu/core/rtw_security.c
+++ b/drivers/staging/rtl8188eu/core/rtw_security.c
@@ -1330,7 +1330,7 @@
bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
for (j = 0; j < 16; j++)
- pframe[payload_index++] = chain_buffer[j];
+ pframe[payload_index++] = chain_buffer[j];
}
if (payload_remainder > 0) { /* If there is a short final block, then pad it,*/
diff --git a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
index 32300df..077b39a 100644
--- a/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8188eu/core/rtw_wlan_util.c
@@ -19,6 +19,8 @@
******************************************************************************/
#define _RTW_WLAN_UTIL_C_
+#include <linux/ieee80211.h>
+
#include <osdep_service.h>
#include <drv_types.h>
#include <wifi.h>
diff --git a/drivers/staging/rtl8188eu/core/rtw_xmit.c b/drivers/staging/rtl8188eu/core/rtw_xmit.c
index fda169d..5dc0b90 100644
--- a/drivers/staging/rtl8188eu/core/rtw_xmit.c
+++ b/drivers/staging/rtl8188eu/core/rtw_xmit.c
@@ -868,7 +868,7 @@
/* check if enable ampdu */
if (pattrib->ht_en && psta->htpriv.ampdu_enable) {
if (psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority))
- pattrib->ampdu_en = true;
+ pattrib->ampdu_en = true;
}
/* re-check if enable ampdu by BA_starting_seqctrl */
@@ -1026,22 +1026,22 @@
/* adding icv, if necessary... */
if (pattrib->iv_len) {
switch (pattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
- break;
- case _TKIP_:
- if (bmcst)
- TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
- else
- TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
- break;
- case _AES_:
- if (bmcst)
- AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
- else
- AES_IV(pattrib->iv, psta->dot11txpn, 0);
- break;
+ case _WEP40_:
+ case _WEP104_:
+ WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+ break;
+ case _TKIP_:
+ if (bmcst)
+ TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+ else
+ TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
+ break;
+ case _AES_:
+ if (bmcst)
+ AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+ else
+ AES_IV(pattrib->iv, psta->dot11txpn, 0);
+ break;
}
memcpy(pframe, pattrib->iv, pattrib->iv_len);
@@ -1769,7 +1769,7 @@
int bmcst = IS_MCAST(pattrib->ra);
if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == false)
- return ret;
+ return ret;
if (pattrib->psta)
psta = pattrib->psta;
diff --git a/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c b/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c
index 15a1765..2633a13 100644
--- a/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c
+++ b/drivers/staging/rtl8188eu/hal/Hal8188ERateAdaptive.c
@@ -659,11 +659,11 @@
{
struct odm_ra_info *pRaInfo = NULL;
+ if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
+ return;
ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_LOUD,
("macid =%d RateID = 0x%x RateMask = 0x%x SGIEnable =%d\n",
macid, RateID, RateMask, SGIEnable));
- if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
- return;
pRaInfo = &(dm_odm->RAInfo[macid]);
pRaInfo->RateID = RateID;
@@ -676,10 +676,10 @@
{
struct odm_ra_info *pRaInfo = NULL;
- ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
- (" macid =%d Rssi =%d\n", macid, Rssi));
if ((NULL == dm_odm) || (macid >= ASSOCIATE_ENTRY_NUM))
return;
+ ODM_RT_TRACE(dm_odm, ODM_COMP_RATE_ADAPTIVE, ODM_DBG_TRACE,
+ (" macid =%d Rssi =%d\n", macid, Rssi));
pRaInfo = &(dm_odm->RAInfo[macid]);
pRaInfo->RssiStaRA = Rssi;
diff --git a/drivers/staging/rtl8188eu/hal/bb_cfg.c b/drivers/staging/rtl8188eu/hal/bb_cfg.c
index 8eb2b39..9c7e626 100644
--- a/drivers/staging/rtl8188eu/hal/bb_cfg.c
+++ b/drivers/staging/rtl8188eu/hal/bb_cfg.c
@@ -24,9 +24,9 @@
#define read_next_pair(array, v1, v2, i) \
do { \
- i += 2; \
- v1 = array[i]; \
- v2 = array[i+1]; \
+ i += 2; \
+ v1 = array[i]; \
+ v2 = array[i+1]; \
} while (0)
diff --git a/drivers/staging/rtl8188eu/hal/hal_com.c b/drivers/staging/rtl8188eu/hal/hal_com.c
index 170e3de..38e9fdc 100644
--- a/drivers/staging/rtl8188eu/hal/hal_com.c
+++ b/drivers/staging/rtl8188eu/hal/hal_com.c
@@ -31,18 +31,7 @@
uint cnt = 0;
char buf[128];
- if (IS_81XXC(chip_vers)) {
- cnt += sprintf((buf+cnt), "Chip Version Info: %s_",
- IS_92C_SERIAL(chip_vers) ?
- "CHIP_8192C" : "CHIP_8188C");
- } else if (IS_92D(chip_vers)) {
- cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8192D_");
- } else if (IS_8723_SERIES(chip_vers)) {
- cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8723A_");
- } else if (IS_8188E(chip_vers)) {
- cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8188E_");
- }
-
+ cnt += sprintf((buf+cnt), "Chip Version Info: CHIP_8188E_");
cnt += sprintf((buf+cnt), "%s_", IS_NORMAL_CHIP(chip_vers) ?
"Normal_Chip" : "Test_Chip");
cnt += sprintf((buf+cnt), "%s_", IS_CHIP_VENDOR_TSMC(chip_vers) ?
@@ -60,18 +49,8 @@
else
cnt += sprintf((buf+cnt), "UNKNOWN_CUT(%d)_",
chip_vers.CUTVersion);
-
- if (IS_1T1R(chip_vers))
- cnt += sprintf((buf+cnt), "1T1R_");
- else if (IS_1T2R(chip_vers))
- cnt += sprintf((buf+cnt), "1T2R_");
- else if (IS_2T2R(chip_vers))
- cnt += sprintf((buf+cnt), "2T2R_");
- else
- cnt += sprintf((buf+cnt), "UNKNOWN_RFTYPE(%d)_",
- chip_vers.RFType);
-
- cnt += sprintf((buf+cnt), "RomVer(%d)\n", chip_vers.ROMVer);
+ cnt += sprintf((buf+cnt), "1T1R_");
+ cnt += sprintf((buf+cnt), "RomVer(0)\n");
pr_info("%s", buf);
}
diff --git a/drivers/staging/rtl8188eu/hal/hal_intf.c b/drivers/staging/rtl8188eu/hal/hal_intf.c
index 5edb5c4..85c17ef 100644
--- a/drivers/staging/rtl8188eu/hal/hal_intf.c
+++ b/drivers/staging/rtl8188eu/hal/hal_intf.c
@@ -131,14 +131,6 @@
adapt->HalFunc.GetHwRegHandler(adapt, variable, val);
}
-u8 rtw_hal_set_def_var(struct adapter *adapt, enum hal_def_variable var,
- void *val)
-{
- if (adapt->HalFunc.SetHalDefVarHandler)
- return adapt->HalFunc.SetHalDefVarHandler(adapt, var, val);
- return _FAIL;
-}
-
u8 rtw_hal_get_def_var(struct adapter *adapt,
enum hal_def_variable var, void *val)
{
@@ -156,22 +148,6 @@
val1, set);
}
-void rtw_hal_enable_interrupt(struct adapter *adapt)
-{
- if (adapt->HalFunc.enable_interrupt)
- adapt->HalFunc.enable_interrupt(adapt);
- else
- DBG_88E("%s: HalFunc.enable_interrupt is NULL!\n", __func__);
-}
-
-void rtw_hal_disable_interrupt(struct adapter *adapt)
-{
- if (adapt->HalFunc.disable_interrupt)
- adapt->HalFunc.disable_interrupt(adapt);
- else
- DBG_88E("%s: HalFunc.disable_interrupt is NULL!\n", __func__);
-}
-
u32 rtw_hal_inirp_init(struct adapter *adapt)
{
u32 rst = _FAIL;
@@ -269,14 +245,6 @@
return data;
}
-void rtw_hal_write_rfreg(struct adapter *adapt, enum rf_radio_path rfpath,
- u32 regaddr, u32 bitmask, u32 data)
-{
- if (adapt->HalFunc.write_rfreg)
- adapt->HalFunc.write_rfreg(adapt, rfpath, regaddr,
- bitmask, data);
-}
-
void rtw_hal_set_bwmode(struct adapter *adapt,
enum ht_channel_width bandwidth, u8 offset)
{
diff --git a/drivers/staging/rtl8188eu/hal/odm.c b/drivers/staging/rtl8188eu/hal/odm.c
index 28b5e7b..710fdc3 100644
--- a/drivers/staging/rtl8188eu/hal/odm.c
+++ b/drivers/staging/rtl8188eu/hal/odm.c
@@ -1170,13 +1170,10 @@
}
for (i = 0; i < sta_cnt; i++) {
- if (PWDB_rssi[i] != (0)) {
- if (pHalData->fw_ractrl) {
- /* Report every sta's RSSI to FW */
- } else {
- ODM_RA_SetRSSI_8188E(
- &(pHalData->odmpriv), (PWDB_rssi[i]&0xFF), (u8)((PWDB_rssi[i]>>16) & 0xFF));
- }
+ if (PWDB_rssi[i] != 0) {
+ ODM_RA_SetRSSI_8188E(&pHalData->odmpriv,
+ PWDB_rssi[i] & 0xFF,
+ (PWDB_rssi[i] >> 16) & 0xFF);
}
}
diff --git a/drivers/staging/rtl8188eu/hal/rf.c b/drivers/staging/rtl8188eu/hal/rf.c
index 0970927..38845d1 100644
--- a/drivers/staging/rtl8188eu/hal/rf.c
+++ b/drivers/staging/rtl8188eu/hal/rf.c
@@ -102,7 +102,7 @@
}
}
rtl88eu_dm_txpower_track_adjust(&hal_data->odmpriv, 1, &direction,
- &pwrtrac_value);
+ &pwrtrac_value);
if (direction == 1) {
/* Increase TX power */
diff --git a/drivers/staging/rtl8188eu/hal/rf_cfg.c b/drivers/staging/rtl8188eu/hal/rf_cfg.c
index 455ecdc..954cade 100644
--- a/drivers/staging/rtl8188eu/hal/rf_cfg.c
+++ b/drivers/staging/rtl8188eu/hal/rf_cfg.c
@@ -295,7 +295,7 @@
break;
}
- if (rtstatus != true)
+ if (!rtstatus)
return false;
}
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
index 86347f2..0a62bfa 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_cmd.c
@@ -127,27 +127,6 @@
return ret;
}
-u8 rtl8188e_set_raid_cmd(struct adapter *adapt, u32 mask)
-{
- u8 buf[3];
- u8 res = _SUCCESS;
- struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
-
- if (haldata->fw_ractrl) {
-
- memset(buf, 0, 3);
- put_unaligned_le32(mask, buf);
-
- FillH2CCmd_88E(adapt, H2C_DM_MACID_CFG, 3, buf);
- } else {
- DBG_88E("==>%s fw dont support RA\n", __func__);
- res = _FAIL;
- }
-
-
- return res;
-}
-
/* bitmap[0:27] = tx_rate_bitmap */
/* bitmap[28:31]= Rate Adaptive id */
/* arg[0:4] = macid */
diff --git a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
index 7904d22..a6295ca 100644
--- a/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
+++ b/drivers/staging/rtl8188eu/hal/rtl8188e_hal_init.c
@@ -128,7 +128,7 @@
padapter->HalData = NULL;
}
-static struct HAL_VERSION ReadChipVersion8188E(struct adapter *padapter)
+static void ReadChipVersion8188E(struct adapter *padapter)
{
u32 value32;
struct HAL_VERSION ChipVersion;
@@ -137,41 +137,17 @@
pHalData = GET_HAL_DATA(padapter);
value32 = usb_read32(padapter, REG_SYS_CFG);
- ChipVersion.ICType = CHIP_8188E;
ChipVersion.ChipType = ((value32 & RTL_ID) ? TEST_CHIP : NORMAL_CHIP);
-
- ChipVersion.RFType = RF_TYPE_1T1R;
ChipVersion.VendorType = ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : CHIP_VENDOR_TSMC);
ChipVersion.CUTVersion = (value32 & CHIP_VER_RTL_MASK)>>CHIP_VER_RTL_SHIFT; /* IC version (CUT) */
- /* For regulator mode. by tynli. 2011.01.14 */
- pHalData->RegulatorMode = ((value32 & TRP_BT_EN) ? RT_LDO_REGULATOR : RT_SWITCHING_REGULATOR);
-
- ChipVersion.ROMVer = 0; /* ROM code version. */
-
dump_chip_info(ChipVersion);
pHalData->VersionID = ChipVersion;
-
- if (IS_1T2R(ChipVersion)) {
- pHalData->rf_type = RF_1T2R;
- pHalData->NumTotalRFPath = 2;
- } else if (IS_2T2R(ChipVersion)) {
- pHalData->rf_type = RF_2T2R;
- pHalData->NumTotalRFPath = 2;
- } else{
- pHalData->rf_type = RF_1T1R;
- pHalData->NumTotalRFPath = 1;
- }
+ pHalData->rf_type = RF_1T1R;
+ pHalData->NumTotalRFPath = 1;
MSG_88E("RF_Type is %x!!\n", pHalData->rf_type);
-
- return ChipVersion;
-}
-
-static void rtl8188e_read_chip_version(struct adapter *padapter)
-{
- ReadChipVersion8188E(padapter);
}
static void rtl8188e_SetHalODMVar(struct adapter *Adapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
@@ -220,7 +196,7 @@
pHalFunc->dm_init = &rtl8188e_init_dm_priv;
- pHalFunc->read_chip_version = &rtl8188e_read_chip_version;
+ pHalFunc->read_chip_version = &ReadChipVersion8188E;
pHalFunc->set_bwmode_handler = &phy_set_bw_mode;
pHalFunc->set_channel_handler = &phy_sw_chnl;
@@ -232,7 +208,6 @@
pHalFunc->AntDivBeforeLinkHandler = &AntDivBeforeLink8188E;
pHalFunc->AntDivCompareHandler = &AntDivCompare8188E;
pHalFunc->read_rfreg = &phy_query_rf_reg;
- pHalFunc->write_rfreg = &phy_set_rf_reg;
pHalFunc->sreset_init_value = &sreset_init_value;
pHalFunc->sreset_get_wifi_status = &sreset_get_wifi_status;
diff --git a/drivers/staging/rtl8188eu/hal/usb_halinit.c b/drivers/staging/rtl8188eu/hal/usb_halinit.c
index 8726222..1ef878f 100644
--- a/drivers/staging/rtl8188eu/hal/usb_halinit.c
+++ b/drivers/staging/rtl8188eu/hal/usb_halinit.c
@@ -743,19 +743,16 @@
if (Adapter->registrypriv.mp_mode == 1) {
_InitRxSetting(Adapter);
Adapter->bFWReady = false;
- haldata->fw_ractrl = false;
} else {
status = rtl88eu_download_fw(Adapter);
if (status) {
DBG_88E("%s: Download Firmware failed!!\n", __func__);
Adapter->bFWReady = false;
- haldata->fw_ractrl = false;
return status;
} else {
RT_TRACE(_module_hci_hal_init_c_, _drv_info_, ("Initializeadapt8192CSdio(): Download Firmware Success!!\n"));
Adapter->bFWReady = true;
- haldata->fw_ractrl = false;
}
}
rtl8188e_InitializeFirmwareVars(Adapter);
@@ -1703,7 +1700,7 @@
/* Forece leave RF low power mode for 1T1R to prevent conficting setting in Fw power */
/* saving sequence. 2010.06.07. Added by tynli. Suggested by SD3 yschang. */
- if ((psmode != PS_MODE_ACTIVE) && (!IS_92C_SERIAL(haldata->VersionID)))
+ if (psmode != PS_MODE_ACTIVE)
ODM_RF_Saving(podmpriv, true);
rtl8188e_set_FwPwrMode_cmd(Adapter, psmode);
}
@@ -1961,75 +1958,6 @@
return bResult;
}
-/* */
-/* Description: */
-/* Change default setting of specified variable. */
-/* */
-static u8 SetHalDefVar8188EUsb(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue)
-{
- struct hal_data_8188e *haldata = GET_HAL_DATA(Adapter);
- u8 bResult = _SUCCESS;
-
- switch (eVariable) {
- case HAL_DEF_DBG_DM_FUNC:
- {
- u8 dm_func = *((u8 *)pValue);
- struct odm_dm_struct *podmpriv = &haldata->odmpriv;
-
- if (dm_func == 0) { /* disable all dynamic func */
- podmpriv->SupportAbility = DYNAMIC_FUNC_DISABLE;
- DBG_88E("==> Disable all dynamic function...\n");
- } else if (dm_func == 1) {/* disable DIG */
- podmpriv->SupportAbility &= (~DYNAMIC_BB_DIG);
- DBG_88E("==> Disable DIG...\n");
- } else if (dm_func == 2) {/* disable High power */
- podmpriv->SupportAbility &= (~DYNAMIC_BB_DYNAMIC_TXPWR);
- } else if (dm_func == 3) {/* disable tx power tracking */
- podmpriv->SupportAbility &= (~DYNAMIC_RF_CALIBRATION);
- DBG_88E("==> Disable tx power tracking...\n");
- } else if (dm_func == 5) {/* disable antenna diversity */
- podmpriv->SupportAbility &= (~DYNAMIC_BB_ANT_DIV);
- } else if (dm_func == 6) {/* turn on all dynamic func */
- if (!(podmpriv->SupportAbility & DYNAMIC_BB_DIG)) {
- struct rtw_dig *pDigTable = &podmpriv->DM_DigTable;
- pDigTable->CurIGValue = usb_read8(Adapter, 0xc50);
- }
- podmpriv->SupportAbility = DYNAMIC_ALL_FUNC_ENABLE;
- DBG_88E("==> Turn on all dynamic function...\n");
- }
- }
- break;
- case HAL_DEF_DBG_DUMP_RXPKT:
- haldata->bDumpRxPkt = *((u8 *)pValue);
- break;
- case HAL_DEF_DBG_DUMP_TXPKT:
- haldata->bDumpTxPkt = *((u8 *)pValue);
- break;
- case HW_DEF_FA_CNT_DUMP:
- {
- u8 bRSSIDump = *((u8 *)pValue);
- struct odm_dm_struct *dm_ocm = &(haldata->odmpriv);
- if (bRSSIDump)
- dm_ocm->DebugComponents = ODM_COMP_DIG|ODM_COMP_FA_CNT;
- else
- dm_ocm->DebugComponents = 0;
- }
- break;
- case HW_DEF_ODM_DBG_FLAG:
- {
- u64 DebugComponents = *((u64 *)pValue);
- struct odm_dm_struct *dm_ocm = &(haldata->odmpriv);
- dm_ocm->DebugComponents = DebugComponents;
- }
- break;
- default:
- bResult = _FAIL;
- break;
- }
-
- return bResult;
-}
-
static void UpdateHalRAMask8188EUsb(struct adapter *adapt, u32 mac_id, u8 rssi_level)
{
u8 init_rate = 0;
@@ -2085,28 +2013,9 @@
init_rate = get_highest_rate_idx(mask)&0x3f;
- if (haldata->fw_ractrl) {
- u8 arg;
+ ODM_RA_UpdateRateInfo_8188E(&haldata->odmpriv, mac_id,
+ raid, mask, shortGIrate);
- arg = mac_id & 0x1f;/* MACID */
- arg |= BIT(7);
- if (shortGIrate)
- arg |= BIT(5);
- mask |= ((raid << 28) & 0xf0000000);
- DBG_88E("update raid entry, mask=0x%x, arg=0x%x\n", mask, arg);
- psta->ra_mask = mask;
- mask |= ((raid << 28) & 0xf0000000);
-
- /* to do ,for 8188E-SMIC */
- rtl8188e_set_raid_cmd(adapt, mask);
- } else {
- ODM_RA_UpdateRateInfo_8188E(&(haldata->odmpriv),
- mac_id,
- raid,
- mask,
- shortGIrate
- );
- }
/* set ra_id */
psta->raid = raid;
psta->init_rate = init_rate;
@@ -2156,7 +2065,6 @@
pwrctrlpriv = &adapt->pwrctrlpriv;
/* init default value */
- haldata->fw_ractrl = false;
if (!pwrctrlpriv->bkeepfwalive)
haldata->LastHMEBoxNum = 0;
@@ -2200,7 +2108,6 @@
halfunc->SetHwRegHandler = &SetHwReg8188EU;
halfunc->GetHwRegHandler = &GetHwReg8188EU;
halfunc->GetHalDefVarHandler = &GetHalDefVar8188EUsb;
- halfunc->SetHalDefVarHandler = &SetHalDefVar8188EUsb;
halfunc->UpdateRAMaskHandler = &UpdateHalRAMask8188EUsb;
halfunc->SetBeaconRelatedRegistersHandler = &SetBeaconRelatedRegisters8188EUsb;
diff --git a/drivers/staging/rtl8188eu/include/HalVerDef.h b/drivers/staging/rtl8188eu/include/HalVerDef.h
index 97047cf..56b4ff0 100644
--- a/drivers/staging/rtl8188eu/include/HalVerDef.h
+++ b/drivers/staging/rtl8188eu/include/HalVerDef.h
@@ -20,20 +20,6 @@
#ifndef __HAL_VERSION_DEF_H__
#define __HAL_VERSION_DEF_H__
-enum HAL_IC_TYPE {
- CHIP_8192S = 0,
- CHIP_8188C = 1,
- CHIP_8192C = 2,
- CHIP_8192D = 3,
- CHIP_8723A = 4,
- CHIP_8188E = 5,
- CHIP_8881A = 6,
- CHIP_8812A = 7,
- CHIP_8821A = 8,
- CHIP_8723B = 9,
- CHIP_8192E = 10,
-};
-
enum HAL_CHIP_TYPE {
TEST_CHIP = 0,
NORMAL_CHIP = 1,
@@ -55,48 +41,20 @@
CHIP_VENDOR_UMC = 1,
};
-enum HAL_RF_TYPE {
- RF_TYPE_1T1R = 0,
- RF_TYPE_1T2R = 1,
- RF_TYPE_2T2R = 2,
- RF_TYPE_2T3R = 3,
- RF_TYPE_2T4R = 4,
- RF_TYPE_3T3R = 5,
- RF_TYPE_3T4R = 6,
- RF_TYPE_4T4R = 7,
-};
-
struct HAL_VERSION {
- enum HAL_IC_TYPE ICType;
enum HAL_CHIP_TYPE ChipType;
enum HAL_CUT_VERSION CUTVersion;
enum HAL_VENDOR VendorType;
- enum HAL_RF_TYPE RFType;
- u8 ROMVer;
};
/* Get element */
-#define GET_CVID_IC_TYPE(version) (((version).ICType))
#define GET_CVID_CHIP_TYPE(version) (((version).ChipType))
-#define GET_CVID_RF_TYPE(version) (((version).RFType))
#define GET_CVID_MANUFACTUER(version) (((version).VendorType))
#define GET_CVID_CUT_VERSION(version) (((version).CUTVersion))
-#define GET_CVID_ROM_VERSION(version) (((version).ROMVer) & ROM_VERSION_MASK)
/* Common Macro. -- */
/* HAL_VERSION VersionID */
-/* HAL_IC_TYPE_E */
-#define IS_81XXC(version) \
- (((GET_CVID_IC_TYPE(version) == CHIP_8192C) || \
- (GET_CVID_IC_TYPE(version) == CHIP_8188C)) ? true : false)
-#define IS_8723_SERIES(version) \
- ((GET_CVID_IC_TYPE(version) == CHIP_8723A) ? true : false)
-#define IS_92D(version) \
- ((GET_CVID_IC_TYPE(version) == CHIP_8192D) ? true : false)
-#define IS_8188E(version) \
- ((GET_CVID_IC_TYPE(version) == CHIP_8188E) ? true : false)
-
/* HAL_CHIP_TYPE_E */
#define IS_TEST_CHIP(version) \
((GET_CVID_CHIP_TYPE(version) == TEST_CHIP) ? true : false)
@@ -122,46 +80,4 @@
#define IS_CHIP_VENDOR_UMC(version) \
((GET_CVID_MANUFACTUER(version) == CHIP_VENDOR_UMC) ? true : false)
-/* HAL_RF_TYPE_E */
-#define IS_1T1R(version) \
- ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T1R) ? true : false)
-#define IS_1T2R(version) \
- ((GET_CVID_RF_TYPE(version) == RF_TYPE_1T2R) ? true : false)
-#define IS_2T2R(version) \
- ((GET_CVID_RF_TYPE(version) == RF_TYPE_2T2R) ? true : false)
-
-/* Chip version Macro. -- */
-#define IS_81XXC_TEST_CHIP(version) \
- ((IS_81XXC(version) && (!IS_NORMAL_CHIP(version))) ? true : false)
-
-#define IS_92C_SERIAL(version) \
- ((IS_81XXC(version) && IS_2T2R(version)) ? true : false)
-#define IS_81xxC_VENDOR_UMC_A_CUT(version) \
- (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
- (IS_A_CUT(version) ? true : false) : false) : false)
-#define IS_81xxC_VENDOR_UMC_B_CUT(version) \
- (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
- (IS_B_CUT(version) ? true : false) : false) : false)
-#define IS_81xxC_VENDOR_UMC_C_CUT(version) \
- (IS_81XXC(version) ? (IS_CHIP_VENDOR_UMC(version) ? \
- (IS_C_CUT(version) ? true : false) : false) : false)
-
-#define IS_NORMAL_CHIP92D(version) \
- ((IS_92D(version)) ? \
- ((GET_CVID_CHIP_TYPE(version) == NORMAL_CHIP) ? true : false) : false)
-
-#define IS_92D_SINGLEPHY(version) \
- ((IS_92D(version)) ? (IS_2T2R(version) ? true : false) : false)
-#define IS_92D_C_CUT(version) \
- ((IS_92D(version)) ? (IS_C_CUT(version) ? true : false) : false)
-#define IS_92D_D_CUT(version) \
- ((IS_92D(version)) ? (IS_D_CUT(version) ? true : false) : false)
-#define IS_92D_E_CUT(version) \
- ((IS_92D(version)) ? (IS_E_CUT(version) ? true : false) : false)
-
-#define IS_8723A_A_CUT(version) \
- ((IS_8723_SERIES(version)) ? (IS_A_CUT(version) ? true : false) : false)
-#define IS_8723A_B_CUT(version) \
- ((IS_8723_SERIES(version)) ? (IS_B_CUT(version) ? true : false) : false)
-
#endif
diff --git a/drivers/staging/rtl8188eu/include/hal_intf.h b/drivers/staging/rtl8188eu/include/hal_intf.h
index 3b476d8..e73c634 100644
--- a/drivers/staging/rtl8188eu/include/hal_intf.h
+++ b/drivers/staging/rtl8188eu/include/hal_intf.h
@@ -171,8 +171,6 @@
void (*read_adapter_info)(struct adapter *padapter);
- void (*enable_interrupt)(struct adapter *padapter);
- void (*disable_interrupt)(struct adapter *padapter);
s32 (*interrupt_handler)(struct adapter *padapter);
void (*set_bwmode_handler)(struct adapter *padapter,
@@ -190,9 +188,6 @@
u8 (*GetHalDefVarHandler)(struct adapter *padapter,
enum hal_def_variable eVariable,
void *pValue);
- u8 (*SetHalDefVarHandler)(struct adapter *padapter,
- enum hal_def_variable eVariable,
- void *pValue);
void (*SetHalODMVarHandler)(struct adapter *padapter,
enum hal_odm_variable eVariable,
@@ -216,9 +211,6 @@
u32 (*read_rfreg)(struct adapter *padapter,
enum rf_radio_path eRFPath, u32 RegAddr,
u32 BitMask);
- void (*write_rfreg)(struct adapter *padapter,
- enum rf_radio_path eRFPath, u32 RegAddr,
- u32 BitMask, u32 Data);
void (*sreset_init_value)(struct adapter *padapter);
u8 (*sreset_get_wifi_status)(struct adapter *padapter);
@@ -267,8 +259,6 @@
void rtw_hal_read_chip_info(struct adapter *padapter);
void rtw_hal_read_chip_version(struct adapter *padapter);
-u8 rtw_hal_set_def_var(struct adapter *padapter,
- enum hal_def_variable eVariable, void *pValue);
u8 rtw_hal_get_def_var(struct adapter *padapter,
enum hal_def_variable eVariable, void *pValue);
@@ -276,9 +266,6 @@
enum hal_odm_variable eVariable, void *pValue1,
bool bSet);
-void rtw_hal_enable_interrupt(struct adapter *padapter);
-void rtw_hal_disable_interrupt(struct adapter *padapter);
-
u32 rtw_hal_inirp_init(struct adapter *padapter);
u32 rtw_hal_inirp_deinit(struct adapter *padapter);
@@ -300,9 +287,6 @@
u32 rtw_hal_read_rfreg(struct adapter *padapter, enum rf_radio_path eRFPath,
u32 RegAddr, u32 BitMask);
-void rtw_hal_write_rfreg(struct adapter *padapter,
- enum rf_radio_path eRFPath, u32 RegAddr,
- u32 BitMask, u32 Data);
void rtw_hal_set_bwmode(struct adapter *padapter,
enum ht_channel_width Bandwidth, u8 Offset);
diff --git a/drivers/staging/rtl8188eu/include/ieee80211.h b/drivers/staging/rtl8188eu/include/ieee80211.h
index b129ad1..6400f75 100644
--- a/drivers/staging/rtl8188eu/include/ieee80211.h
+++ b/drivers/staging/rtl8188eu/include/ieee80211.h
@@ -477,63 +477,9 @@
#define WLAN_GET_SEQ_FRAG(seq) ((seq) & RTW_IEEE80211_SCTL_FRAG)
#define WLAN_GET_SEQ_SEQ(seq) ((seq) & RTW_IEEE80211_SCTL_SEQ)
-/* Authentication algorithms */
-#define WLAN_AUTH_OPEN 0
-#define WLAN_AUTH_SHARED_KEY 1
-
-#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)
-
/* Non standard? Not in <linux/ieee80211.h> */
#define WLAN_REASON_EXPIRATION_CHK 65535
-/* Information Element IDs */
-#define WLAN_EID_SSID 0
-#define WLAN_EID_SUPP_RATES 1
-#define WLAN_EID_FH_PARAMS 2
-#define WLAN_EID_DS_PARAMS 3
-#define WLAN_EID_CF_PARAMS 4
-#define WLAN_EID_TIM 5
-#define WLAN_EID_IBSS_PARAMS 6
-#define WLAN_EID_CHALLENGE 16
-/* EIDs defined by IEEE 802.11h - START */
-#define WLAN_EID_PWR_CONSTRAINT 32
-#define WLAN_EID_PWR_CAPABILITY 33
-#define WLAN_EID_TPC_REQUEST 34
-#define WLAN_EID_TPC_REPORT 35
-#define WLAN_EID_SUPPORTED_CHANNELS 36
-#define WLAN_EID_CHANNEL_SWITCH 37
-#define WLAN_EID_MEASURE_REQUEST 38
-#define WLAN_EID_MEASURE_REPORT 39
-#define WLAN_EID_QUITE 40
-#define WLAN_EID_IBSS_DFS 41
-/* EIDs defined by IEEE 802.11h - END */
-#define WLAN_EID_ERP_INFO 42
-#define WLAN_EID_HT_CAP 45
-#define WLAN_EID_RSN 48
-#define WLAN_EID_EXT_SUPP_RATES 50
-#define WLAN_EID_MOBILITY_DOMAIN 54
-#define WLAN_EID_FAST_BSS_TRANSITION 55
-#define WLAN_EID_TIMEOUT_INTERVAL 56
-#define WLAN_EID_RIC_DATA 57
-#define WLAN_EID_HT_OPERATION 61
-#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62
-#define WLAN_EID_20_40_BSS_COEXISTENCE 72
-#define WLAN_EID_20_40_BSS_INTOLERANT 73
-#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74
-#define WLAN_EID_MMIE 76
-#define WLAN_EID_VENDOR_SPECIFIC 221
-#define WLAN_EID_GENERIC (WLAN_EID_VENDOR_SPECIFIC)
-
#define IEEE80211_MGMT_HDR_LEN 24
#define IEEE80211_DATA_HDR3_LEN 24
#define IEEE80211_DATA_HDR4_LEN 30
diff --git a/drivers/staging/rtl8188eu/include/osdep_service.h b/drivers/staging/rtl8188eu/include/osdep_service.h
index 00472e0..cf9ca68 100644
--- a/drivers/staging/rtl8188eu/include/osdep_service.h
+++ b/drivers/staging/rtl8188eu/include/osdep_service.h
@@ -123,7 +123,7 @@
#define BIT35 0x0800000000
#define BIT36 0x1000000000
-extern int RTW_STATUS_CODE(int error_code);
+int RTW_STATUS_CODE(int error_code);
#define rtw_update_mem_stat(flag, sz) do {} while (0)
u8 *_rtw_malloc(u32 sz);
diff --git a/drivers/staging/rtl8188eu/include/recv_osdep.h b/drivers/staging/rtl8188eu/include/recv_osdep.h
index 0809963..fdeb603 100644
--- a/drivers/staging/rtl8188eu/include/recv_osdep.h
+++ b/drivers/staging/rtl8188eu/include/recv_osdep.h
@@ -38,8 +38,7 @@
int rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter);
void rtw_free_recv_priv(struct recv_priv *precvpriv);
-int rtw_os_recv_resource_alloc(struct adapter *adapt,
- struct recv_frame *recvfr);
+void rtw_os_recv_resource_alloc(struct recv_frame *recvfr);
int rtw_os_recvbuf_resource_alloc(struct adapter *adapt, struct recv_buf *buf);
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h
index 42b1f22..f813ce0 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_cmd.h
@@ -107,7 +107,6 @@
/* host message to firmware cmd */
void rtl8188e_set_FwPwrMode_cmd(struct adapter *padapter, u8 Mode);
void rtl8188e_set_FwJoinBssReport_cmd(struct adapter *padapter, u8 mstatus);
-u8 rtl8188e_set_raid_cmd(struct adapter *padapter, u32 mask);
void rtl8188e_Add_RateATid(struct adapter *padapter, u32 bitmap, u8 arg,
u8 rssi_level);
diff --git a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
index 7d8e022..cbad364 100644
--- a/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
+++ b/drivers/staging/rtl8188eu/include/rtl8188e_hal.h
@@ -188,15 +188,8 @@
#define EFUSE_PROTECT_BYTES_BANK 16
-/* For RTL8723 regulator mode. */
-enum rt_regulator_mode {
- RT_SWITCHING_REGULATOR = 0,
- RT_LDO_REGULATOR = 1,
-};
-
struct hal_data_8188e {
struct HAL_VERSION VersionID;
- enum rt_regulator_mode RegulatorMode; /* switching regulator or LDO */
u16 CustomerID;
u8 *pfirmware;
u32 fwsize;
@@ -301,7 +294,6 @@
/* for host message to fw */
u8 LastHMEBoxNum;
- u8 fw_ractrl;
u8 RegTxPause;
/* Beacon function related global variable. */
u32 RegBcnCtrlVal;
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme.h b/drivers/staging/rtl8188eu/include/rtw_mlme.h
index 8c7e8a3..4c99257 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mlme.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme.h
@@ -535,7 +535,8 @@
struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr);
struct wlan_network *rtw_get_oldest_wlan_network(struct __queue *scanned_queue);
-void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue);
+void rtw_free_assoc_resources(struct adapter *adapter);
+void rtw_free_assoc_resources_locked(struct adapter *adapter);
void rtw_indicate_disconnect(struct adapter *adapter);
void rtw_indicate_connect(struct adapter *adapter);
void rtw_indicate_scan_done(struct adapter *padapter, bool aborted);
diff --git a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
index 2417809..9093a5f 100644
--- a/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
+++ b/drivers/staging/rtl8188eu/include/rtw_mlme_ext.h
@@ -457,9 +457,9 @@
int init_mlme_ext_priv(struct adapter *adapter);
int init_hw_mlme_ext(struct adapter *padapter);
void free_mlme_ext_priv(struct mlme_ext_priv *pmlmeext);
-extern void init_mlme_ext_timer(struct adapter *padapter);
-extern void init_addba_retry_timer(struct adapter *adapt, struct sta_info *sta);
-extern struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv);
+void init_mlme_ext_timer(struct adapter *padapter);
+void init_addba_retry_timer(struct adapter *adapt, struct sta_info *sta);
+struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv);
unsigned char networktype_to_raid(unsigned char network_type);
u8 judge_network_type(struct adapter *padapter, unsigned char *rate, int len);
@@ -554,7 +554,7 @@
int cam_idx);
void beacon_timing_control(struct adapter *padapter);
-extern u8 set_tx_beacon_cmd(struct adapter *padapter);
+u8 set_tx_beacon_cmd(struct adapter *padapter);
unsigned int setup_beacon_frame(struct adapter *padapter,
unsigned char *beacon_frame);
void update_mgnt_tx_rate(struct adapter *padapter, u8 rate);
diff --git a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
index aa1fd87..a493d4c 100644
--- a/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
+++ b/drivers/staging/rtl8188eu/include/rtw_pwrctrl.h
@@ -257,7 +257,6 @@
void LPS_Enter(struct adapter *adapter);
void LPS_Leave(struct adapter *adapter);
-void rtw_set_ips_deny(struct adapter *adapter, u32 ms);
int _rtw_pwr_wakeup(struct adapter *adapter, u32 ips_defer_ms,
const char *caller);
#define rtw_pwr_wakeup(adapter) \
diff --git a/drivers/staging/rtl8188eu/include/sta_info.h b/drivers/staging/rtl8188eu/include/sta_info.h
index 9612490..d4e7832 100644
--- a/drivers/staging/rtl8188eu/include/sta_info.h
+++ b/drivers/staging/rtl8188eu/include/sta_info.h
@@ -113,7 +113,6 @@
u8 raid;
u8 init_rate;
- u32 ra_mask;
u8 wireless_mode; /* NETWORK_TYPE */
struct stainfo_stats sta_stats;
@@ -351,19 +350,19 @@
return x;
}
-extern u32 _rtw_init_sta_priv(struct sta_priv *pstapriv);
-extern u32 _rtw_free_sta_priv(struct sta_priv *pstapriv);
+u32 _rtw_init_sta_priv(struct sta_priv *pstapriv);
+u32 _rtw_free_sta_priv(struct sta_priv *pstapriv);
#define stainfo_offset_valid(offset) (offset < NUM_STA && offset >= 0)
int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta);
struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int off);
-extern struct sta_info *rtw_alloc_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
-extern u32 rtw_free_stainfo(struct adapter *adapt, struct sta_info *psta);
-extern void rtw_free_all_stainfo(struct adapter *adapt);
-extern struct sta_info *rtw_get_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
-extern u32 rtw_init_bcmc_stainfo(struct adapter *adapt);
-extern struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter);
-extern u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr);
+struct sta_info *rtw_alloc_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
+u32 rtw_free_stainfo(struct adapter *adapt, struct sta_info *psta);
+void rtw_free_all_stainfo(struct adapter *adapt);
+struct sta_info *rtw_get_stainfo(struct sta_priv *stapriv, u8 *hwaddr);
+u32 rtw_init_bcmc_stainfo(struct adapter *adapt);
+struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter);
+u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr);
#endif /* _STA_INFO_H_ */
diff --git a/drivers/staging/rtl8188eu/include/wifi.h b/drivers/staging/rtl8188eu/include/wifi.h
index a08a2e0..dba8af1 100644
--- a/drivers/staging/rtl8188eu/include/wifi.h
+++ b/drivers/staging/rtl8188eu/include/wifi.h
@@ -649,13 +649,6 @@
#define IEEE80211_MAX_AMPDU_BUF 0x40
-/* Spatial Multiplexing Power Save Modes */
-#define WLAN_HT_CAP_SM_PS_STATIC 0
-#define WLAN_HT_CAP_SM_PS_DYNAMIC 1
-#define WLAN_HT_CAP_SM_PS_INVALID 2
-#define WLAN_HT_CAP_SM_PS_DISABLED 3
-
-
#define OP_MODE_PURE 0
#define OP_MODE_MAY_BE_LEGACY_STAS 1
#define OP_MODE_20MHZ_HT_STA_ASSOCED 2
diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
index 38dba14..9695749 100644
--- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c
@@ -179,8 +179,8 @@
cap = le16_to_cpu(le_tmp);
- if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_BSS)) {
- if (cap & WLAN_CAPABILITY_BSS)
+ if (!WLAN_CAPABILITY_IS_STA_BSS(cap)) {
+ if (cap & WLAN_CAPABILITY_ESS)
iwe.u.mode = IW_MODE_MASTER;
else
iwe.u.mode = IW_MODE_ADHOC;
@@ -1871,7 +1871,7 @@
rtw_disassoc_cmd(padapter, 500, false);
DBG_88E("%s...call rtw_indicate_disconnect\n ", __func__);
rtw_indicate_disconnect(padapter);
- rtw_free_assoc_resources(padapter, 1);
+ rtw_free_assoc_resources(padapter);
}
ret = wpa_set_auth_algs(dev, (u32)param->value);
break;
@@ -2485,16 +2485,13 @@
static int rtw_hostapd_sta_flush(struct net_device *dev)
{
- int ret = 0;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
DBG_88E("%s\n", __func__);
flush_all_cam_entry(padapter); /* clear CAM */
- ret = rtw_sta_flush(padapter);
-
- return ret;
+ return rtw_sta_flush(padapter);
}
static int rtw_add_sta(struct net_device *dev, struct ieee_param *param)
@@ -2666,7 +2663,8 @@
psta = rtw_get_stainfo(pstapriv, param->sta_addr);
if (psta) {
- if ((psta->wpa_ie[0] == WLAN_EID_RSN) || (psta->wpa_ie[0] == WLAN_EID_GENERIC)) {
+ if (psta->wpa_ie[0] == WLAN_EID_RSN ||
+ psta->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
int wpa_ie_len;
int copy_len;
@@ -2809,7 +2807,6 @@
static int rtw_ioctl_acl_remove_sta(struct net_device *dev, struct ieee_param *param, int len)
{
- int ret = 0;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
@@ -2820,13 +2817,11 @@
param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
return -EINVAL;
- ret = rtw_acl_remove_sta(padapter, param->sta_addr);
- return ret;
+ return rtw_acl_remove_sta(padapter, param->sta_addr);
}
static int rtw_ioctl_acl_add_sta(struct net_device *dev, struct ieee_param *param, int len)
{
- int ret = 0;
struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev);
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
@@ -2837,8 +2832,7 @@
param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff)
return -EINVAL;
- ret = rtw_acl_add_sta(padapter, param->sta_addr);
- return ret;
+ return rtw_acl_add_sta(padapter, param->sta_addr);
}
static int rtw_ioctl_set_macaddr_acl(struct net_device *dev, struct ieee_param *param, int len)
diff --git a/drivers/staging/rtl8188eu/os_dep/os_intfs.c b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
index a14e79f..2361bce 100644
--- a/drivers/staging/rtl8188eu/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8188eu/os_dep/os_intfs.c
@@ -1175,7 +1175,7 @@
/* s2-2. indicate disconnect to os */
rtw_indicate_disconnect(padapter);
/* s2-3. */
- rtw_free_assoc_resources(padapter, 1);
+ rtw_free_assoc_resources(padapter);
/* s2-4. */
rtw_free_network_queue(padapter, true);
/* Close LED */
diff --git a/drivers/staging/rtl8188eu/os_dep/recv_linux.c b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
index 0570132..3ebb8b2 100644
--- a/drivers/staging/rtl8188eu/os_dep/recv_linux.c
+++ b/drivers/staging/rtl8188eu/os_dep/recv_linux.c
@@ -17,8 +17,6 @@
*
*
******************************************************************************/
-#define _RECV_OSDEP_C_
-
#include <osdep_service.h>
#include <drv_types.h>
@@ -29,26 +27,22 @@
#include <usb_ops_linux.h>
/* alloc os related resource in struct recv_frame */
-int rtw_os_recv_resource_alloc(struct adapter *padapter,
- struct recv_frame *precvframe)
+void rtw_os_recv_resource_alloc(struct recv_frame *precvframe)
{
precvframe->pkt_newalloc = NULL;
precvframe->pkt = NULL;
- return _SUCCESS;
}
/* alloc os related resource in struct recv_buf */
int rtw_os_recvbuf_resource_alloc(struct adapter *padapter,
struct recv_buf *precvbuf)
{
- int res = _SUCCESS;
-
- precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
- if (precvbuf->purb == NULL)
- res = _FAIL;
precvbuf->pskb = NULL;
precvbuf->reuse = false;
- return res;
+ precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!precvbuf->purb)
+ return _FAIL;
+ return _SUCCESS;
}
void rtw_handle_tkip_mic_err(struct adapter *padapter, u8 bgroup)
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index d0d4335..33bfe05 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -17,8 +17,8 @@
*
*
******************************************************************************/
-#define _HCI_INTF_C_
+#define pr_fmt(fmt) "R8188EU: " fmt
#include <osdep_service.h>
#include <drv_types.h>
#include <recv_osdep.h>
@@ -55,7 +55,6 @@
static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
{
int i;
- int status = _FAIL;
struct dvobj_priv *pdvobjpriv;
struct usb_host_config *phost_conf;
struct usb_config_descriptor *pconf_desc;
@@ -64,10 +63,9 @@
struct usb_endpoint_descriptor *pendp_desc;
struct usb_device *pusbd;
-
pdvobjpriv = kzalloc(sizeof(*pdvobjpriv), GFP_KERNEL);
if (pdvobjpriv == NULL)
- goto exit;
+ return NULL;
pdvobjpriv->pusbintf = usb_intf;
pusbd = interface_to_usbdev(usb_intf);
@@ -115,20 +113,13 @@
mutex_init(&pdvobjpriv->usb_vendor_req_mutex);
pdvobjpriv->usb_vendor_req_buf = kzalloc(MAX_USB_IO_CTL_SIZE, GFP_KERNEL);
- if (!pdvobjpriv->usb_vendor_req_buf)
- goto free_dvobj;
-
- usb_get_dev(pusbd);
-
- status = _SUCCESS;
-
-free_dvobj:
- if (status != _SUCCESS && pdvobjpriv) {
+ if (!pdvobjpriv->usb_vendor_req_buf) {
usb_set_intfdata(usb_intf, NULL);
kfree(pdvobjpriv);
- pdvobjpriv = NULL;
+ return NULL;
}
-exit:
+ usb_get_dev(pusbd);
+
return pdvobjpriv;
}
@@ -136,7 +127,6 @@
{
struct dvobj_priv *dvobj = usb_get_intfdata(usb_intf);
-
usb_set_intfdata(usb_intf, NULL);
if (dvobj) {
/* Modify condition for 92DU DMDP 2010.11.18, by Thomas */
@@ -150,7 +140,7 @@
* on sitesurvey for the first time when
* device is up . Reset usb port for sitesurvey
* fail issue. */
- DBG_88E("usb attached..., try to reset usb device\n");
+ pr_debug("usb attached..., try to reset usb device\n");
usb_reset_device(interface_to_usbdev(usb_intf));
}
}
@@ -201,7 +191,7 @@
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_dev_unload\n"));
if (padapter->bup) {
- DBG_88E("===> rtw_dev_unload\n");
+ pr_debug("===> rtw_dev_unload\n");
padapter->bDriverStopped = true;
if (padapter->xmitpriv.ack_tx)
rtw_ack_tx_done(&padapter->xmitpriv, RTW_SCTX_DONE_DRV_STOP);
@@ -224,7 +214,7 @@
("r871x_dev_unload():padapter->bup == false\n"));
}
- DBG_88E("<=== rtw_dev_unload\n");
+ pr_debug("<=== rtw_dev_unload\n");
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-rtw_dev_unload\n"));
}
@@ -236,16 +226,13 @@
struct net_device *pnetdev = padapter->pnetdev;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
- int ret = 0;
u32 start_time = jiffies;
-
- DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+ pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
if ((!padapter->bup) || (padapter->bDriverStopped) ||
(padapter->bSurpriseRemoved)) {
- DBG_88E("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
+ pr_debug("padapter->bup=%d bDriverStopped=%d bSurpriseRemoved = %d\n",
padapter->bup, padapter->bDriverStopped,
padapter->bSurpriseRemoved);
goto exit;
@@ -267,7 +254,7 @@
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
check_fwstate(pmlmepriv, _FW_LINKED)) {
- DBG_88E("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
+ pr_debug("%s:%d %s(%pM), length:%d assoc_ssid.length:%d\n",
__func__, __LINE__,
pmlmepriv->cur_network.network.Ssid.Ssid,
pmlmepriv->cur_network.network.MacAddress,
@@ -279,7 +266,7 @@
/* s2-2. indicate disconnect to os */
rtw_indicate_disconnect(padapter);
/* s2-3. */
- rtw_free_assoc_resources(padapter, 1);
+ rtw_free_assoc_resources(padapter);
/* s2-4. */
rtw_free_network_queue(padapter, true);
@@ -293,10 +280,10 @@
rtw_indicate_disconnect(padapter);
exit:
- DBG_88E("<=== %s return %d.............. in %dms\n", __func__
- , ret, rtw_get_passing_time_ms(start_time));
+ pr_debug("<=== %s .............. in %dms\n", __func__,
+ rtw_get_passing_time_ms(start_time));
- return ret;
+ return 0;
}
static int rtw_resume_process(struct adapter *padapter)
@@ -306,7 +293,7 @@
int ret = -1;
u32 start_time = jiffies;
- DBG_88E("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
+ pr_debug("==> %s (%s:%d)\n", __func__, current->comm, current->pid);
if (padapter) {
pnetdev = padapter->pnetdev;
@@ -319,7 +306,7 @@
rtw_reset_drv_sw(padapter);
pwrpriv->bkeepfwalive = false;
- DBG_88E("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
+ pr_debug("bkeepfwalive(%x)\n", pwrpriv->bkeepfwalive);
if (pm_netdev_open(pnetdev, true) != 0)
goto exit;
@@ -334,10 +321,9 @@
exit:
if (pwrpriv)
pwrpriv->bInSuspend = false;
- DBG_88E("<=== %s return %d.............. in %dms\n", __func__,
+ pr_debug("<=== %s return %d.............. in %dms\n", __func__,
ret, rtw_get_passing_time_ms(start_time));
-
return ret;
}
@@ -407,8 +393,8 @@
dvobj->pusbdev->do_remote_wakeup = 1;
pusb_intf->needs_remote_wakeup = 1;
device_init_wakeup(&pusb_intf->dev, 1);
- DBG_88E("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
- DBG_88E("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
+ pr_debug("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~~~~\n");
+ pr_debug("\n padapter->pwrctrlpriv.bSupportRemoteWakeup~~~[%d]~~~\n",
device_may_wakeup(&pusb_intf->dev));
}
#endif
@@ -416,13 +402,13 @@
/* 2012-07-11 Move here to prevent the 8723AS-VAU BT auto
* suspend influence */
if (usb_autopm_get_interface(pusb_intf) < 0)
- DBG_88E("can't get autopm:\n");
+ pr_debug("can't get autopm:\n");
/* alloc dev name after read efuse. */
rtw_init_netdev_name(pnetdev, padapter->registrypriv.ifname);
rtw_macaddr_cfg(padapter->eeprompriv.mac_addr);
memcpy(pnetdev->dev_addr, padapter->eeprompriv.mac_addr, ETH_ALEN);
- DBG_88E("MAC Address from pnetdev->dev_addr = %pM\n",
+ pr_debug("MAC Address from pnetdev->dev_addr = %pM\n",
pnetdev->dev_addr);
/* step 6. Tell the network stack we exist */
@@ -431,7 +417,7 @@
goto free_hal_data;
}
- DBG_88E("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
+ pr_debug("bDriverStopped:%d, bSurpriseRemoved:%d, bup:%d, hw_init_completed:%d\n"
, padapter->bDriverStopped
, padapter->bSurpriseRemoved
, padapter->bup
@@ -475,7 +461,7 @@
rtw_cancel_all_timer(if1);
rtw_dev_unload(if1);
- DBG_88E("+r871xu_dev_remove, hw_init_completed=%d\n",
+ pr_debug("+r871xu_dev_remove, hw_init_completed=%d\n",
if1->hw_init_completed);
rtw_free_drv_sw(if1);
if (pnetdev)
@@ -485,7 +471,6 @@
static int rtw_drv_init(struct usb_interface *pusb_intf, const struct usb_device_id *pdid)
{
struct adapter *if1 = NULL;
- int status = _FAIL;
struct dvobj_priv *dvobj;
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+rtw_drv_init\n"));
@@ -500,19 +485,18 @@
if1 = rtw_usb_if1_init(dvobj, pusb_intf, pdid);
if (if1 == NULL) {
- DBG_88E("rtw_init_primarystruct adapter Failed!\n");
+ pr_debug("rtw_init_primarystruct adapter Failed!\n");
goto free_dvobj;
}
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-871x_drv - drv_init, success!\n"));
- status = _SUCCESS;
+ return 0;
free_dvobj:
- if (status != _SUCCESS)
- usb_dvobj_deinit(pusb_intf);
+ usb_dvobj_deinit(pusb_intf);
exit:
- return status == _SUCCESS ? 0 : -ENODEV;
+ return -ENODEV;
}
/*
@@ -524,8 +508,7 @@
struct dvobj_priv *dvobj = usb_get_intfdata(pusb_intf);
struct adapter *padapter = dvobj->if1;
-
- DBG_88E("+rtw_dev_remove\n");
+ pr_debug("+rtw_dev_remove\n");
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("+dev_remove()\n"));
if (!pusb_intf->unregistering)
@@ -541,7 +524,7 @@
usb_dvobj_deinit(pusb_intf);
RT_TRACE(_module_hci_intfs_c_, _drv_err_, ("-dev_remove()\n"));
- DBG_88E("-r871xu_dev_remove, done\n");
+ pr_debug("-r871xu_dev_remove, done\n");
}
static struct usb_driver rtl8188e_usb_drv = {
diff --git a/drivers/staging/rtl8192e/dot11d.c b/drivers/staging/rtl8192e/dot11d.c
index ef9da86..fcf9b3b 100644
--- a/drivers/staging/rtl8192e/dot11d.c
+++ b/drivers/staging/rtl8192e/dot11d.c
@@ -160,21 +160,6 @@
pDot11dInfo->State = DOT11D_STATE_LEARNED;
}
-u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel)
-{
- struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
- u8 MaxTxPwrInDbm = 255;
-
- if (MAX_CHANNEL_NUMBER < Channel) {
- netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
- return MaxTxPwrInDbm;
- }
- if (pDot11dInfo->channel_map[Channel])
- MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
-
- return MaxTxPwrInDbm;
-}
-
void DOT11D_ScanComplete(struct rtllib_device *dev)
{
struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
@@ -190,27 +175,3 @@
break;
}
}
-
-int ToLegalChannel(struct rtllib_device *dev, u8 channel)
-{
- struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
- u8 default_chn = 0;
- u32 i;
-
- for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
- if (pDot11dInfo->channel_map[i] > 0) {
- default_chn = i;
- break;
- }
- }
-
- if (MAX_CHANNEL_NUMBER < channel) {
- netdev_err(dev->dev, "%s(): Invalid Channel\n", __func__);
- return default_chn;
- }
-
- if (pDot11dInfo->channel_map[channel] > 0)
- return channel;
-
- return default_chn;
-}
diff --git a/drivers/staging/rtl8192e/dot11d.h b/drivers/staging/rtl8192e/dot11d.h
index 69e0f8f..129ebed 100644
--- a/drivers/staging/rtl8192e/dot11d.h
+++ b/drivers/staging/rtl8192e/dot11d.h
@@ -79,7 +79,6 @@
#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) \
cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa)
-#define CIE_WATCHDOG_TH 1
#define GET_CIE_WATCHDOG(__pIeeeDev) \
(GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog)
static inline void RESET_CIE_WATCHDOG(struct rtllib_device *__pIeeeDev)
@@ -88,16 +87,11 @@
}
#define UPDATE_CIE_WATCHDOG(__pIeeeDev) (++GET_CIE_WATCHDOG(__pIeeeDev))
-#define IS_DOT11D_STATE_DONE(__pIeeeDev) \
- (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE)
-
void dot11d_init(struct rtllib_device *dev);
void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee);
void Dot11d_Reset(struct rtllib_device *dev);
void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr,
u16 CoutryIeLen, u8 *pCoutryIe);
-u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel);
void DOT11D_ScanComplete(struct rtllib_device *dev);
-int ToLegalChannel(struct rtllib_device *dev, u8 channel);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
index d0b0830..dba4584 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_def.h
@@ -26,8 +26,6 @@
#define MAX_SILENT_RESET_RX_SLOT_NUM 10
#define RX_MPDU_QUEUE 0
-#define RX_CMD_QUEUE 1
-
enum rtl819x_loopback {
RTL819X_NO_LOOPBACK = 0,
@@ -36,11 +34,6 @@
RTL819X_CCK_LOOPBACK = 3,
};
-
-#define RESET_DELAY_8185 20
-
-#define RT_IBSS_INT_MASKS (IMR_BcnInt | IMR_BcnInt | IMR_TBDOK | IMR_TBDER)
-
#define DESC90_RATE1M 0x00
#define DESC90_RATE2M 0x01
#define DESC90_RATE5_5M 0x02
@@ -74,17 +67,6 @@
#define SHORT_SLOT_TIME 9
#define NON_SHORT_SLOT_TIME 20
-
-#define MAX_LINES_HWCONFIG_TXT 1000
-#define MAX_BYTES_LINE_HWCONFIG_TXT 128
-
-#define SW_THREE_WIRE 0
-#define HW_THREE_WIRE 2
-
-#define BT_DEMO_BOARD 0
-#define BT_QA_BOARD 1
-#define BT_FPGA 2
-
#define RX_SMOOTH 20
#define QSLT_BK 0x1
@@ -96,25 +78,14 @@
#define QSLT_MGNT 0x12
#define QSLT_CMD 0x13
-#define NUM_OF_FIRMWARE_QUEUE 10
-#define NUM_OF_PAGES_IN_FW 0x100
#define NUM_OF_PAGE_IN_FW_QUEUE_BK 0x007
#define NUM_OF_PAGE_IN_FW_QUEUE_BE 0x0aa
#define NUM_OF_PAGE_IN_FW_QUEUE_VI 0x024
#define NUM_OF_PAGE_IN_FW_QUEUE_VO 0x007
-#define NUM_OF_PAGE_IN_FW_QUEUE_HCCA 0
-#define NUM_OF_PAGE_IN_FW_QUEUE_CMD 0x2
#define NUM_OF_PAGE_IN_FW_QUEUE_MGNT 0x10
-#define NUM_OF_PAGE_IN_FW_QUEUE_HIGH 0
#define NUM_OF_PAGE_IN_FW_QUEUE_BCN 0x4
#define NUM_OF_PAGE_IN_FW_QUEUE_PUB 0xd
-#define NUM_OF_PAGE_IN_FW_QUEUE_BK_DTM 0x026
-#define NUM_OF_PAGE_IN_FW_QUEUE_BE_DTM 0x048
-#define NUM_OF_PAGE_IN_FW_QUEUE_VI_DTM 0x048
-#define NUM_OF_PAGE_IN_FW_QUEUE_VO_DTM 0x026
-#define NUM_OF_PAGE_IN_FW_QUEUE_PUB_DTM 0x00
-
#define APPLIED_RESERVED_QUEUE_IN_FW 0x80000000
#define RSVD_FW_QUEUE_PAGE_BK_SHIFT 0x00
#define RSVD_FW_QUEUE_PAGE_BE_SHIFT 0x08
@@ -197,23 +168,6 @@
};
-
-#define TX_DESC_SIZE 32
-
-#define TX_DESC_CMD_SIZE 32
-
-
-#define TX_STATUS_DESC_SIZE 32
-
-#define TX_FWINFO_SIZE 8
-
-
-#define RX_DESC_SIZE 16
-
-#define RX_STATUS_DESC_SIZE 16
-
-#define RX_DRIVER_INFO_SIZE 8
-
struct log_int_8190 {
u32 nIMR_COMDOK;
u32 nIMR_MGNTDOK;
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
index facc6f1..c8f25ad 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.c
@@ -22,55 +22,38 @@
#include "r8192E_phy.h"
#include "r8190P_rtl8256.h"
-void PHY_SetRF8256Bandwidth(struct net_device *dev,
- enum ht_channel_width Bandwidth)
+void rtl92e_set_bandwidth(struct net_device *dev,
+ enum ht_channel_width Bandwidth)
{
u8 eRFPath;
struct r8192_priv *priv = rtllib_priv(dev);
+ if (priv->card_8192_version != VERSION_8190_BD &&
+ priv->card_8192_version != VERSION_8190_BE) {
+ netdev_warn(dev, "%s(): Unknown HW version.\n", __func__);
+ return;
+ }
+
for (eRFPath = 0; eRFPath < priv->NumTotalRFPath; eRFPath++) {
- if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+ if (!rtl92e_is_legal_rf_path(dev, eRFPath))
continue;
switch (Bandwidth) {
case HT_CHANNEL_WIDTH_20:
- if (priv->card_8192_version == VERSION_8190_BD ||
- priv->card_8192_version == VERSION_8190_BE) {
- rtl8192_phy_SetRFReg(dev,
- (enum rf90_radio_path)eRFPath,
- 0x0b, bMask12Bits, 0x100);
- rtl8192_phy_SetRFReg(dev,
- (enum rf90_radio_path)eRFPath,
- 0x2c, bMask12Bits, 0x3d7);
- rtl8192_phy_SetRFReg(dev,
- (enum rf90_radio_path)eRFPath,
- 0x0e, bMask12Bits, 0x021);
-
- } else {
- netdev_warn(dev, "%s(): Unknown HW version.\n",
- __func__);
- }
-
+ rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+ 0x0b, bMask12Bits, 0x100);
+ rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+ 0x2c, bMask12Bits, 0x3d7);
+ rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+ 0x0e, bMask12Bits, 0x021);
break;
case HT_CHANNEL_WIDTH_20_40:
- if (priv->card_8192_version == VERSION_8190_BD ||
- priv->card_8192_version == VERSION_8190_BE) {
- rtl8192_phy_SetRFReg(dev,
- (enum rf90_radio_path)eRFPath,
- 0x0b, bMask12Bits, 0x300);
- rtl8192_phy_SetRFReg(dev,
- (enum rf90_radio_path)eRFPath,
- 0x2c, bMask12Bits, 0x3ff);
- rtl8192_phy_SetRFReg(dev,
- (enum rf90_radio_path)eRFPath,
- 0x0e, bMask12Bits, 0x0e1);
-
- } else {
- netdev_warn(dev, "%s(): Unknown HW version.\n",
- __func__);
- }
-
-
+ rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+ 0x0b, bMask12Bits, 0x300);
+ rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+ 0x2c, bMask12Bits, 0x3ff);
+ rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath,
+ 0x0e, bMask12Bits, 0x0e1);
break;
default:
netdev_err(dev, "%s(): Unknown bandwidth: %#X\n",
@@ -81,15 +64,7 @@
}
}
-bool PHY_RF8256_Config(struct net_device *dev)
-{
- struct r8192_priv *priv = rtllib_priv(dev);
-
- priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
- return phy_RF8256_Config_ParaFile(dev);
-}
-
-bool phy_RF8256_Config_ParaFile(struct net_device *dev)
+bool rtl92e_config_rf(struct net_device *dev)
{
u32 u4RegValue = 0;
u8 eRFPath;
@@ -102,9 +77,11 @@
u8 ConstRetryTimes = 5, RetryTimes = 5;
u8 ret = 0;
+ priv->NumTotalRFPath = RTL819X_TOTAL_RF_PATH;
+
for (eRFPath = (enum rf90_radio_path)RF90_PATH_A;
eRFPath < priv->NumTotalRFPath; eRFPath++) {
- if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+ if (!rtl92e_is_legal_rf_path(dev, eRFPath))
continue;
pPhyReg = &priv->PHYRegDef[eRFPath];
@@ -113,114 +90,63 @@
switch (eRFPath) {
case RF90_PATH_A:
case RF90_PATH_C:
- u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs,
- bRFSI_RFENV);
+ u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs,
+ bRFSI_RFENV);
break;
case RF90_PATH_B:
case RF90_PATH_D:
- u4RegValue = rtl8192_QueryBBReg(dev, pPhyReg->rfintfs,
- bRFSI_RFENV<<16);
+ u4RegValue = rtl92e_get_bb_reg(dev, pPhyReg->rfintfs,
+ bRFSI_RFENV<<16);
break;
}
- rtl8192_setBBreg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfintfe, bRFSI_RFENV<<16, 0x1);
- rtl8192_setBBreg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfintfo, bRFSI_RFENV, 0x1);
- rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,
- b3WireAddressLength, 0x0);
- rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2,
- b3WireDataLength, 0x0);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2,
+ b3WireAddressLength, 0x0);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2,
+ b3WireDataLength, 0x0);
- rtl8192_phy_SetRFReg(dev, (enum rf90_radio_path) eRFPath, 0x0,
- bMask12Bits, 0xbf);
+ rtl92e_set_rf_reg(dev, (enum rf90_radio_path)eRFPath, 0x0,
+ bMask12Bits, 0xbf);
- rtStatus = rtl8192_phy_checkBBAndRF(dev, HW90_BLOCK_RF,
- (enum rf90_radio_path)eRFPath);
+ rtStatus = rtl92e_check_bb_and_rf(dev, HW90_BLOCK_RF,
+ (enum rf90_radio_path)eRFPath);
if (!rtStatus) {
netdev_err(dev, "%s(): Failed to check RF Path %d.\n",
__func__, eRFPath);
- goto phy_RF8256_Config_ParaFile_Fail;
+ goto fail;
}
RetryTimes = ConstRetryTimes;
RF3_Final_Value = 0;
- switch (eRFPath) {
- case RF90_PATH_A:
- while (RF3_Final_Value != RegValueToBeCheck &&
- RetryTimes != 0) {
- ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
+ while (RF3_Final_Value != RegValueToBeCheck &&
+ RetryTimes != 0) {
+ ret = rtl92e_config_rf_path(dev,
(enum rf90_radio_path)eRFPath);
- RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
- (enum rf90_radio_path)eRFPath,
- RegOffSetToBeCheck,
- bMask12Bits);
- RT_TRACE(COMP_RF,
- "RF %d %d register final value: %x\n",
- eRFPath, RegOffSetToBeCheck,
- RF3_Final_Value);
- RetryTimes--;
- }
- break;
- case RF90_PATH_B:
- while (RF3_Final_Value != RegValueToBeCheck &&
- RetryTimes != 0) {
- ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
- (enum rf90_radio_path)eRFPath);
- RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
- (enum rf90_radio_path)eRFPath,
- RegOffSetToBeCheck,
- bMask12Bits);
- RT_TRACE(COMP_RF,
- "RF %d %d register final value: %x\n",
- eRFPath, RegOffSetToBeCheck,
- RF3_Final_Value);
- RetryTimes--;
- }
- break;
- case RF90_PATH_C:
- while (RF3_Final_Value != RegValueToBeCheck &&
- RetryTimes != 0) {
- ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
- (enum rf90_radio_path)eRFPath);
- RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
+ RF3_Final_Value = rtl92e_get_rf_reg(dev,
(enum rf90_radio_path)eRFPath,
RegOffSetToBeCheck,
bMask12Bits);
- RT_TRACE(COMP_RF,
- "RF %d %d register final value: %x\n",
- eRFPath, RegOffSetToBeCheck,
- RF3_Final_Value);
- RetryTimes--;
- }
- break;
- case RF90_PATH_D:
- while (RF3_Final_Value != RegValueToBeCheck &&
- RetryTimes != 0) {
- ret = rtl8192_phy_ConfigRFWithHeaderFile(dev,
- (enum rf90_radio_path)eRFPath);
- RF3_Final_Value = rtl8192_phy_QueryRFReg(dev,
- (enum rf90_radio_path)eRFPath,
- RegOffSetToBeCheck, bMask12Bits);
- RT_TRACE(COMP_RF,
- "RF %d %d register final value: %x\n",
- eRFPath, RegOffSetToBeCheck,
- RF3_Final_Value);
- RetryTimes--;
- }
- break;
+ RT_TRACE(COMP_RF,
+ "RF %d %d register final value: %x\n",
+ eRFPath, RegOffSetToBeCheck,
+ RF3_Final_Value);
+ RetryTimes--;
}
switch (eRFPath) {
case RF90_PATH_A:
case RF90_PATH_C:
- rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV,
- u4RegValue);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfintfs, bRFSI_RFENV,
+ u4RegValue);
break;
case RF90_PATH_B:
case RF90_PATH_D:
- rtl8192_setBBreg(dev, pPhyReg->rfintfs, bRFSI_RFENV<<16,
- u4RegValue);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfintfs,
+ bRFSI_RFENV<<16, u4RegValue);
break;
}
@@ -228,7 +154,7 @@
netdev_err(dev,
"%s(): Failed to initialize RF Path %d.\n",
__func__, eRFPath);
- goto phy_RF8256_Config_ParaFile_Fail;
+ goto fail;
}
}
@@ -236,11 +162,11 @@
RT_TRACE(COMP_PHY, "PHY Initialization Success\n");
return true;
-phy_RF8256_Config_ParaFile_Fail:
+fail:
return false;
}
-void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel)
+void rtl92e_set_cck_tx_power(struct net_device *dev, u8 powerlevel)
{
u32 TxAGC = 0;
struct r8192_priv *priv = rtllib_priv(dev);
@@ -254,11 +180,11 @@
}
if (TxAGC > 0x24)
TxAGC = 0x24;
- rtl8192_setBBreg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
+ rtl92e_set_bb_reg(dev, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
}
-void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel)
+void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel)
{
struct r8192_priv *priv = rtllib_priv(dev);
u32 writeVal, powerBase0, powerBase1, writeVal_tmp;
@@ -300,7 +226,7 @@
else
writeVal = (byte3 << 24) | (byte2 << 16) |
(byte1 << 8) | byte0;
- rtl8192_setBBreg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
+ rtl92e_set_bb_reg(dev, RegOffset[index], 0x7f7f7f7f, writeVal);
}
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h
index 64e831d..3e4363f 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8190P_rtl8256.h
@@ -21,11 +21,10 @@
#define RTL8225H
#define RTL819X_TOTAL_RF_PATH 2
-extern void PHY_SetRF8256Bandwidth(struct net_device *dev,
- enum ht_channel_width Bandwidth);
-extern bool PHY_RF8256_Config(struct net_device *dev);
-extern bool phy_RF8256_Config_ParaFile(struct net_device *dev);
-extern void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel);
-extern void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
+void rtl92e_set_bandwidth(struct net_device *dev,
+ enum ht_channel_width Bandwidth);
+bool rtl92e_config_rf(struct net_device *dev);
+void rtl92e_set_cck_tx_power(struct net_device *dev, u8 powerlevel);
+void rtl92e_set_ofdm_tx_power(struct net_device *dev, u8 powerlevel);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
index ebd08a1..9ddabf5 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.c
@@ -21,11 +21,8 @@
#include "r8192E_hw.h"
#include "r8192E_cmdpkt.h"
-bool cmpk_message_handle_tx(
- struct net_device *dev,
- u8 *code_virtual_address,
- u32 packettype,
- u32 buffer_len)
+bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *code_virtual_address,
+ u32 packettype, u32 buffer_len)
{
bool rt_status = true;
@@ -41,7 +38,7 @@
struct tx_fwinfo_8190pci *pTxFwInfo = NULL;
RT_TRACE(COMP_CMDPKT, "%s(),buffer_len is %d\n", __func__, buffer_len);
- firmware_init_param(dev);
+ rtl92e_init_fw_param(dev);
frag_threshold = pfirmware->cmdpacket_frag_thresold;
do {
@@ -84,7 +81,7 @@
} while (frag_offset < buffer_len);
- write_nic_byte(dev, TPPoll, TPPoll_CQ);
+ rtl92e_writeb(dev, TPPoll, TPPoll_CQ);
Failed:
return rt_status;
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
index f714d51..2a8b165c 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_cmdpkt.h
@@ -19,7 +19,6 @@
#ifndef R819XUSB_CMDPKT_H
#define R819XUSB_CMDPKT_H
-extern bool cmpk_message_handle_tx(struct net_device *dev,
- u8 *codevirtualaddress, u32 packettype,
- u32 buffer_len);
+bool rtl92e_send_cmd_pkt(struct net_device *dev, u8 *codevirtualaddress,
+ u32 packettype, u32 buffer_len);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index f6661bb..c28cabc 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -33,7 +33,7 @@
static int WDCAPARA_ADD[] = {EDCAPARA_BE, EDCAPARA_BK, EDCAPARA_VI,
EDCAPARA_VO};
-void rtl8192e_start_beacon(struct net_device *dev)
+void rtl92e_start_beacon(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
struct rtllib_network *net = &priv->rtllib->current_network;
@@ -41,21 +41,20 @@
u16 BcnCW = 6;
u16 BcnIFS = 0xf;
- DMESG("Enabling beacon TX");
- rtl8192_irq_disable(dev);
+ rtl92e_irq_disable(dev);
- write_nic_word(dev, ATIMWND, 2);
+ rtl92e_writew(dev, ATIMWND, 2);
- write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
- write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
- write_nic_word(dev, BCN_DMATIME, 256);
+ rtl92e_writew(dev, BCN_INTERVAL, net->beacon_interval);
+ rtl92e_writew(dev, BCN_DRV_EARLY_INT, 10);
+ rtl92e_writew(dev, BCN_DMATIME, 256);
- write_nic_byte(dev, BCN_ERR_THRESH, 100);
+ rtl92e_writeb(dev, BCN_ERR_THRESH, 100);
BcnTimeCfg |= BcnCW<<BCN_TCFG_CW_SHIFT;
BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
- write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
- rtl8192_irq_enable(dev);
+ rtl92e_writew(dev, BCN_TCFG, BcnTimeCfg);
+ rtl92e_irq_enable(dev);
}
static void rtl8192e_update_msr(struct net_device *dev)
@@ -64,7 +63,7 @@
u8 msr;
enum led_ctl_mode LedAction = LED_CTL_NO_LINK;
- msr = read_nic_byte(dev, MSR);
+ msr = rtl92e_readb(dev, MSR);
msr &= ~MSR_LINK_MASK;
switch (priv->rtllib->iw_mode) {
@@ -91,26 +90,26 @@
break;
}
- write_nic_byte(dev, MSR, msr);
+ rtl92e_writeb(dev, MSR, msr);
if (priv->rtllib->LedControlHandler)
priv->rtllib->LedControlHandler(dev, LedAction);
}
-void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val)
+void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val)
{
struct r8192_priv *priv = rtllib_priv(dev);
switch (variable) {
case HW_VAR_BSSID:
- write_nic_dword(dev, BSSIDR, ((u32 *)(val))[0]);
- write_nic_word(dev, BSSIDR+2, ((u16 *)(val+2))[0]);
+ rtl92e_writel(dev, BSSIDR, ((u32 *)(val))[0]);
+ rtl92e_writew(dev, BSSIDR+2, ((u16 *)(val+2))[0]);
break;
case HW_VAR_MEDIA_STATUS:
{
enum rt_op_mode OpMode = *((enum rt_op_mode *)(val));
enum led_ctl_mode LedAction = LED_CTL_NO_LINK;
- u8 btMsr = read_nic_byte(dev, MSR);
+ u8 btMsr = rtl92e_readb(dev, MSR);
btMsr &= 0xfc;
@@ -134,7 +133,7 @@
break;
}
- write_nic_byte(dev, MSR, btMsr);
+ rtl92e_writeb(dev, MSR, btMsr);
}
break;
@@ -144,7 +143,7 @@
u32 RegRCR, Type;
Type = ((u8 *)(val))[0];
- RegRCR = read_nic_dword(dev, RCR);
+ RegRCR = rtl92e_readl(dev, RCR);
priv->ReceiveConfig = RegRCR;
if (Type == true)
@@ -152,7 +151,7 @@
else if (Type == false)
RegRCR &= (~RCR_CBSSID);
- write_nic_dword(dev, RCR, RegRCR);
+ rtl92e_writel(dev, RCR, RegRCR);
priv->ReceiveConfig = RegRCR;
}
@@ -161,7 +160,7 @@
case HW_VAR_SLOT_TIME:
priv->slot_time = val[0];
- write_nic_byte(dev, SLOT_TIME, val[0]);
+ rtl92e_writeb(dev, SLOT_TIME, val[0]);
break;
@@ -173,12 +172,12 @@
regTmp = priv->basic_rate;
if (priv->short_preamble)
regTmp |= BRSR_AckShortPmb;
- write_nic_dword(dev, RRSR, regTmp);
+ rtl92e_writel(dev, RRSR, regTmp);
break;
}
case HW_VAR_CPU_RST:
- write_nic_dword(dev, CPU_GEN, ((u32 *)(val))[0]);
+ rtl92e_writel(dev, CPU_GEN, ((u32 *)(val))[0]);
break;
case HW_VAR_AC_PARAM:
@@ -194,7 +193,7 @@
u1bAIFS = qop->aifs[pAcParam] *
((mode&(IEEE_G|IEEE_N_24G)) ? 9 : 20) + aSifsTime;
- dm_init_edca_turbo(dev);
+ rtl92e_dm_init_edca_turbo(dev);
u4bAcParam = (le16_to_cpu(qop->tx_op_limit[pAcParam]) <<
AC_PARAM_TXOP_LIMIT_OFFSET) |
@@ -208,19 +207,19 @@
__func__, eACI, u4bAcParam);
switch (eACI) {
case AC1_BK:
- write_nic_dword(dev, EDCAPARA_BK, u4bAcParam);
+ rtl92e_writel(dev, EDCAPARA_BK, u4bAcParam);
break;
case AC0_BE:
- write_nic_dword(dev, EDCAPARA_BE, u4bAcParam);
+ rtl92e_writel(dev, EDCAPARA_BE, u4bAcParam);
break;
case AC2_VI:
- write_nic_dword(dev, EDCAPARA_VI, u4bAcParam);
+ rtl92e_writel(dev, EDCAPARA_VI, u4bAcParam);
break;
case AC3_VO:
- write_nic_dword(dev, EDCAPARA_VO, u4bAcParam);
+ rtl92e_writel(dev, EDCAPARA_VO, u4bAcParam);
break;
default:
@@ -242,7 +241,7 @@
union aci_aifsn *pAciAifsn = (union aci_aifsn *) &
(qos_parameters->aifs[0]);
u8 acm = pAciAifsn->f.acm;
- u8 AcmCtrl = read_nic_byte(dev, AcmHwCtrl);
+ u8 AcmCtrl = rtl92e_readb(dev, AcmHwCtrl);
RT_TRACE(COMP_DBG, "===========>%s():HW_VAR_ACM_CTRL:%x\n",
__func__, eACI);
@@ -290,20 +289,20 @@
RT_TRACE(COMP_QOS,
"SetHwReg8190pci(): [HW_VAR_ACM_CTRL] Write 0x%X\n",
AcmCtrl);
- write_nic_byte(dev, AcmHwCtrl, AcmCtrl);
+ rtl92e_writeb(dev, AcmHwCtrl, AcmCtrl);
break;
}
case HW_VAR_SIFS:
- write_nic_byte(dev, SIFS, val[0]);
- write_nic_byte(dev, SIFS+1, val[0]);
+ rtl92e_writeb(dev, SIFS, val[0]);
+ rtl92e_writeb(dev, SIFS+1, val[0]);
break;
case HW_VAR_RF_TIMING:
{
u8 Rf_Timing = *((u8 *)val);
- write_nic_byte(dev, rFPGA0_RFTiming1, Rf_Timing);
+ rtl92e_writeb(dev, rFPGA0_RFTiming1, Rf_Timing);
break;
}
@@ -324,7 +323,7 @@
RT_TRACE(COMP_INIT, "====> rtl8192_read_eeprom_info\n");
- EEPROMId = eprom_read(dev, 0);
+ EEPROMId = rtl92e_eeprom_read(dev, 0);
if (EEPROMId != RTL8190_EEPROM_ID) {
netdev_err(dev, "%s(): Invalid EEPROM ID: %x\n", __func__,
EEPROMId);
@@ -334,12 +333,14 @@
}
if (!priv->AutoloadFailFlag) {
- priv->eeprom_vid = eprom_read(dev, EEPROM_VID >> 1);
- priv->eeprom_did = eprom_read(dev, EEPROM_DID >> 1);
+ priv->eeprom_vid = rtl92e_eeprom_read(dev, EEPROM_VID >> 1);
+ priv->eeprom_did = rtl92e_eeprom_read(dev, EEPROM_DID >> 1);
- usValue = eprom_read(dev, (u16)(EEPROM_Customer_ID>>1)) >> 8;
+ usValue = rtl92e_eeprom_read(dev,
+ (u16)(EEPROM_Customer_ID>>1)) >> 8;
priv->eeprom_CustomerID = (u8)(usValue & 0xff);
- usValue = eprom_read(dev, EEPROM_ICVersion_ChannelPlan>>1);
+ usValue = rtl92e_eeprom_read(dev,
+ EEPROM_ICVersion_ChannelPlan>>1);
priv->eeprom_ChannelPlan = usValue&0xff;
IC_Version = (usValue & 0xff00)>>8;
@@ -377,7 +378,7 @@
if (!priv->AutoloadFailFlag) {
for (i = 0; i < 6; i += 2) {
- usValue = eprom_read(dev,
+ usValue = rtl92e_eeprom_read(dev,
(u16)((EEPROM_NODE_ADDRESS_BYTE_0 + i) >> 1));
*(u16 *)(&dev->dev_addr[i]) = usValue;
}
@@ -397,8 +398,8 @@
if (priv->card_8192_version > VERSION_8190_BD) {
if (!priv->AutoloadFailFlag) {
- tempval = (eprom_read(dev, (EEPROM_RFInd_PowerDiff >>
- 1))) & 0xff;
+ tempval = (rtl92e_eeprom_read(dev,
+ (EEPROM_RFInd_PowerDiff >> 1))) & 0xff;
priv->EEPROMLegacyHTTxPowerDiff = tempval & 0xf;
if (tempval&0x80)
@@ -412,7 +413,7 @@
priv->EEPROMLegacyHTTxPowerDiff);
if (!priv->AutoloadFailFlag)
- priv->EEPROMThermalMeter = (u8)(((eprom_read(dev,
+ priv->EEPROMThermalMeter = (u8)(((rtl92e_eeprom_read(dev,
(EEPROM_ThermalMeter>>1))) &
0xff00)>>8);
else
@@ -423,7 +424,7 @@
if (priv->epromtype == EEPROM_93C46) {
if (!priv->AutoloadFailFlag) {
- usValue = eprom_read(dev,
+ usValue = rtl92e_eeprom_read(dev,
EEPROM_TxPwDiff_CrystalCap >> 1);
priv->EEPROMAntPwDiff = (usValue&0x0fff);
priv->EEPROMCrystalCap = (u8)((usValue & 0xf000)
@@ -441,7 +442,7 @@
for (i = 0; i < 14; i += 2) {
if (!priv->AutoloadFailFlag)
- usValue = eprom_read(dev,
+ usValue = rtl92e_eeprom_read(dev,
(u16)((EEPROM_TxPwIndex_CCK +
i) >> 1));
else
@@ -457,7 +458,7 @@
}
for (i = 0; i < 14; i += 2) {
if (!priv->AutoloadFailFlag)
- usValue = eprom_read(dev,
+ usValue = rtl92e_eeprom_read(dev,
(u16)((EEPROM_TxPwIndex_OFDM_24G
+ i) >> 1));
else
@@ -561,7 +562,7 @@
RT_TRACE(COMP_INIT, "\n2T4R config\n");
}
- init_rate_adaptive(dev);
+ rtl92e_init_adaptive_rate(dev);
priv->rf_chip = RF_8256;
@@ -626,13 +627,13 @@
RT_TRACE(COMP_TRACE, "<==== ReadAdapterInfo\n");
}
-void rtl8192_get_eeprom_size(struct net_device *dev)
+void rtl92e_get_eeprom_size(struct net_device *dev)
{
u16 curCR;
struct r8192_priv *priv = rtllib_priv(dev);
RT_TRACE(COMP_INIT, "===========>%s()\n", __func__);
- curCR = read_nic_dword(dev, EPROM_CMD);
+ curCR = rtl92e_readl(dev, EPROM_CMD);
RT_TRACE(COMP_INIT, "read from Reg Cmd9346CR(%x):%x\n", EPROM_CMD,
curCR);
priv->epromtype = (curCR & EPROM_CMD_9356SEL) ? EEPROM_93C56 :
@@ -684,26 +685,26 @@
break;
}
- write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+ rtl92e_writeb(dev, BW_OPMODE, regBwOpMode);
{
u32 ratr_value = 0;
ratr_value = regRATR;
if (priv->rf_type == RF_1T2R)
ratr_value &= ~(RATE_ALL_OFDM_2SS);
- write_nic_dword(dev, RATR0, ratr_value);
- write_nic_byte(dev, UFWP, 1);
+ rtl92e_writel(dev, RATR0, ratr_value);
+ rtl92e_writeb(dev, UFWP, 1);
}
- regTmp = read_nic_byte(dev, 0x313);
+ regTmp = rtl92e_readb(dev, 0x313);
regRRSR = ((regTmp) << 24) | (regRRSR & 0x00ffffff);
- write_nic_dword(dev, RRSR, regRRSR);
+ rtl92e_writel(dev, RRSR, regRRSR);
- write_nic_word(dev, RETRY_LIMIT,
- priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
- priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
+ rtl92e_writew(dev, RETRY_LIMIT,
+ priv->ShortRetryLimit << RETRY_LIMIT_SHORT_SHIFT |
+ priv->LongRetryLimit << RETRY_LIMIT_LONG_SHIFT);
}
-bool rtl8192_adapter_start(struct net_device *dev)
+bool rtl92e_start_adapter(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
u32 ulRegRead;
@@ -719,10 +720,10 @@
priv->being_init_adapter = true;
start:
- rtl8192_pci_resetdescring(dev);
+ rtl92e_reset_desc_ring(dev);
priv->Rf_Mode = RF_OP_By_SW_3wire;
if (priv->ResetProgress == RESET_TYPE_NORESET) {
- write_nic_byte(dev, ANAPAR, 0x37);
+ rtl92e_writeb(dev, ANAPAR, 0x37);
mdelay(500);
}
priv->pFirmware->firmware_status = FW_STATUS_0_INIT;
@@ -730,7 +731,7 @@
if (priv->RegRfOff)
priv->rtllib->eRFPowerState = eRfOff;
- ulRegRead = read_nic_dword(dev, CPU_GEN);
+ ulRegRead = rtl92e_readl(dev, CPU_GEN);
if (priv->pFirmware->firmware_status == FW_STATUS_0_INIT)
ulRegRead |= CPU_GEN_SYSTEM_RESET;
else if (priv->pFirmware->firmware_status == FW_STATUS_5_READY)
@@ -739,19 +740,19 @@
netdev_err(dev, "%s(): undefined firmware state: %d.\n",
__func__, priv->pFirmware->firmware_status);
- write_nic_dword(dev, CPU_GEN, ulRegRead);
+ rtl92e_writel(dev, CPU_GEN, ulRegRead);
- ICVersion = read_nic_byte(dev, IC_VERRSION);
+ ICVersion = rtl92e_readb(dev, IC_VERRSION);
if (ICVersion >= 0x4) {
- SwitchingRegulatorOutput = read_nic_byte(dev, SWREGULATOR);
+ SwitchingRegulatorOutput = rtl92e_readb(dev, SWREGULATOR);
if (SwitchingRegulatorOutput != 0xb8) {
- write_nic_byte(dev, SWREGULATOR, 0xa8);
+ rtl92e_writeb(dev, SWREGULATOR, 0xa8);
mdelay(1);
- write_nic_byte(dev, SWREGULATOR, 0xb8);
+ rtl92e_writeb(dev, SWREGULATOR, 0xb8);
}
}
RT_TRACE(COMP_INIT, "BB Config Start!\n");
- rtStatus = rtl8192_BBConfig(dev);
+ rtStatus = rtl92e_config_bb(dev);
if (!rtStatus) {
netdev_warn(dev, "%s(): Failed to configure BB\n", __func__);
return rtStatus;
@@ -760,7 +761,7 @@
priv->LoopbackMode = RTL819X_NO_LOOPBACK;
if (priv->ResetProgress == RESET_TYPE_NORESET) {
- ulRegRead = read_nic_dword(dev, CPU_GEN);
+ ulRegRead = rtl92e_readl(dev, CPU_GEN);
if (priv->LoopbackMode == RTL819X_NO_LOOPBACK)
ulRegRead = ((ulRegRead & CPU_GEN_NO_LOOPBACK_MSK) |
CPU_GEN_NO_LOOPBACK_SET);
@@ -770,73 +771,73 @@
netdev_err(dev, "%s: Invalid loopback mode setting.\n",
__func__);
- write_nic_dword(dev, CPU_GEN, ulRegRead);
+ rtl92e_writel(dev, CPU_GEN, ulRegRead);
udelay(500);
}
rtl8192_hwconfig(dev);
- write_nic_byte(dev, CMDR, CR_RE | CR_TE);
+ rtl92e_writeb(dev, CMDR, CR_RE | CR_TE);
- write_nic_byte(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |
- (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT)));
- write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
- write_nic_word(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
- write_nic_dword(dev, RCR, priv->ReceiveConfig);
+ rtl92e_writeb(dev, PCIF, ((MXDMA2_NoLimit<<MXDMA2_RX_SHIFT) |
+ (MXDMA2_NoLimit<<MXDMA2_TX_SHIFT)));
+ rtl92e_writel(dev, MAC0, ((u32 *)dev->dev_addr)[0]);
+ rtl92e_writew(dev, MAC4, ((u16 *)(dev->dev_addr + 4))[0]);
+ rtl92e_writel(dev, RCR, priv->ReceiveConfig);
- write_nic_dword(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK <<
- RSVD_FW_QUEUE_PAGE_BK_SHIFT |
- NUM_OF_PAGE_IN_FW_QUEUE_BE <<
- RSVD_FW_QUEUE_PAGE_BE_SHIFT |
- NUM_OF_PAGE_IN_FW_QUEUE_VI <<
- RSVD_FW_QUEUE_PAGE_VI_SHIFT |
- NUM_OF_PAGE_IN_FW_QUEUE_VO <<
- RSVD_FW_QUEUE_PAGE_VO_SHIFT);
- write_nic_dword(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT <<
- RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
- write_nic_dword(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW |
- NUM_OF_PAGE_IN_FW_QUEUE_BCN <<
- RSVD_FW_QUEUE_PAGE_BCN_SHIFT|
- NUM_OF_PAGE_IN_FW_QUEUE_PUB <<
- RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
+ rtl92e_writel(dev, RQPN1, NUM_OF_PAGE_IN_FW_QUEUE_BK <<
+ RSVD_FW_QUEUE_PAGE_BK_SHIFT |
+ NUM_OF_PAGE_IN_FW_QUEUE_BE <<
+ RSVD_FW_QUEUE_PAGE_BE_SHIFT |
+ NUM_OF_PAGE_IN_FW_QUEUE_VI <<
+ RSVD_FW_QUEUE_PAGE_VI_SHIFT |
+ NUM_OF_PAGE_IN_FW_QUEUE_VO <<
+ RSVD_FW_QUEUE_PAGE_VO_SHIFT);
+ rtl92e_writel(dev, RQPN2, NUM_OF_PAGE_IN_FW_QUEUE_MGNT <<
+ RSVD_FW_QUEUE_PAGE_MGNT_SHIFT);
+ rtl92e_writel(dev, RQPN3, APPLIED_RESERVED_QUEUE_IN_FW |
+ NUM_OF_PAGE_IN_FW_QUEUE_BCN <<
+ RSVD_FW_QUEUE_PAGE_BCN_SHIFT|
+ NUM_OF_PAGE_IN_FW_QUEUE_PUB <<
+ RSVD_FW_QUEUE_PAGE_PUB_SHIFT);
- rtl8192_tx_enable(dev);
- rtl8192_rx_enable(dev);
- ulRegRead = (0xFFF00000 & read_nic_dword(dev, RRSR)) |
+ rtl92e_tx_enable(dev);
+ rtl92e_rx_enable(dev);
+ ulRegRead = (0xFFF00000 & rtl92e_readl(dev, RRSR)) |
RATE_ALL_OFDM_AG | RATE_ALL_CCK;
- write_nic_dword(dev, RRSR, ulRegRead);
- write_nic_dword(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
+ rtl92e_writel(dev, RRSR, ulRegRead);
+ rtl92e_writel(dev, RATR0+4*7, (RATE_ALL_OFDM_AG | RATE_ALL_CCK));
- write_nic_byte(dev, ACK_TIMEOUT, 0x30);
+ rtl92e_writeb(dev, ACK_TIMEOUT, 0x30);
if (priv->ResetProgress == RESET_TYPE_NORESET)
- rtl8192_SetWirelessMode(dev, priv->rtllib->mode);
- CamResetAllEntry(dev);
+ rtl92e_set_wireless_mode(dev, priv->rtllib->mode);
+ rtl92e_cam_reset(dev);
{
u8 SECR_value = 0x0;
SECR_value |= SCR_TxEncEnable;
SECR_value |= SCR_RxDecEnable;
SECR_value |= SCR_NoSKMC;
- write_nic_byte(dev, SECR, SECR_value);
+ rtl92e_writeb(dev, SECR, SECR_value);
}
- write_nic_word(dev, ATIMWND, 2);
- write_nic_word(dev, BCN_INTERVAL, 100);
+ rtl92e_writew(dev, ATIMWND, 2);
+ rtl92e_writew(dev, BCN_INTERVAL, 100);
{
int i;
for (i = 0; i < QOS_QUEUE_NUM; i++)
- write_nic_dword(dev, WDCAPARA_ADD[i], 0x005e4332);
+ rtl92e_writel(dev, WDCAPARA_ADD[i], 0x005e4332);
}
- write_nic_byte(dev, 0xbe, 0xc0);
+ rtl92e_writeb(dev, 0xbe, 0xc0);
- rtl8192_phy_configmac(dev);
+ rtl92e_config_mac(dev);
if (priv->card_8192_version > (u8) VERSION_8190_BD) {
- rtl8192_phy_getTxPower(dev);
- rtl8192_phy_setTxPower(dev, priv->chan);
+ rtl92e_get_tx_power(dev);
+ rtl92e_set_tx_power(dev, priv->chan);
}
- tmpvalue = read_nic_byte(dev, IC_VERRSION);
+ tmpvalue = rtl92e_readb(dev, IC_VERRSION);
priv->IC_Cut = tmpvalue;
RT_TRACE(COMP_INIT, "priv->IC_Cut= 0x%x\n", priv->IC_Cut);
if (priv->IC_Cut >= IC_VersionCut_D) {
@@ -851,7 +852,7 @@
}
RT_TRACE(COMP_INIT, "Load Firmware!\n");
- bfirmwareok = init_firmware(dev);
+ bfirmwareok = rtl92e_init_fw(dev);
if (!bfirmwareok) {
if (retry_times < 10) {
retry_times++;
@@ -864,37 +865,34 @@
RT_TRACE(COMP_INIT, "Load Firmware finished!\n");
if (priv->ResetProgress == RESET_TYPE_NORESET) {
RT_TRACE(COMP_INIT, "RF Config Started!\n");
- rtStatus = rtl8192_phy_RFConfig(dev);
+ rtStatus = rtl92e_config_phy(dev);
if (!rtStatus) {
netdev_info(dev, "RF Config failed\n");
return rtStatus;
}
RT_TRACE(COMP_INIT, "RF Config Finished!\n");
}
- rtl8192_phy_updateInitGain(dev);
- rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
- rtl8192_setBBreg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
+ rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn, 0x1);
+ rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bOFDMEn, 0x1);
- write_nic_byte(dev, 0x87, 0x0);
+ rtl92e_writeb(dev, 0x87, 0x0);
if (priv->RegRfOff) {
RT_TRACE((COMP_INIT | COMP_RF | COMP_POWER),
"%s(): Turn off RF for RegRfOff ----------\n",
__func__);
- MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_SW, true);
+ rtl92e_set_rf_state(dev, eRfOff, RF_CHANGE_BY_SW);
} else if (priv->rtllib->RfOffReason > RF_CHANGE_BY_PS) {
RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER),
"%s(): Turn off RF for RfOffReason(%d) ----------\n",
__func__, priv->rtllib->RfOffReason);
- MgntActSet_RF_State(dev, eRfOff, priv->rtllib->RfOffReason,
- true);
+ rtl92e_set_rf_state(dev, eRfOff, priv->rtllib->RfOffReason);
} else if (priv->rtllib->RfOffReason >= RF_CHANGE_BY_IPS) {
RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER),
"%s(): Turn off RF for RfOffReason(%d) ----------\n",
__func__, priv->rtllib->RfOffReason);
- MgntActSet_RF_State(dev, eRfOff, priv->rtllib->RfOffReason,
- true);
+ rtl92e_set_rf_state(dev, eRfOff, priv->rtllib->RfOffReason);
} else {
RT_TRACE((COMP_INIT|COMP_RF|COMP_POWER), "%s(): RF-ON\n",
__func__);
@@ -908,13 +906,13 @@
priv->Rf_Mode = RF_OP_By_SW_3wire;
if (priv->ResetProgress == RESET_TYPE_NORESET) {
- dm_initialize_txpower_tracking(dev);
+ rtl92e_dm_init_txpower_tracking(dev);
if (priv->IC_Cut >= IC_VersionCut_D) {
- tmpRegA = rtl8192_QueryBBReg(dev,
- rOFDM0_XATxIQImbalance, bMaskDWord);
- tmpRegC = rtl8192_QueryBBReg(dev,
- rOFDM0_XCTxIQImbalance, bMaskDWord);
+ tmpRegA = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord);
+ tmpRegC = rtl92e_get_bb_reg(dev, rOFDM0_XCTxIQImbalance,
+ bMaskDWord);
for (i = 0; i < TxBBGainTableLength; i++) {
if (tmpRegA == dm_tx_bb_gain[i]) {
priv->rfa_txpowertrackingindex = (u8)i;
@@ -926,8 +924,8 @@
}
}
- TempCCk = rtl8192_QueryBBReg(dev,
- rCCK0_TxFilter1, bMaskByte2);
+ TempCCk = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1,
+ bMaskByte2);
for (i = 0; i < CCKTxBBGainTableLength; i++) {
if (TempCCk == dm_cck_tx_bb_gain[i][0]) {
@@ -954,7 +952,7 @@
priv->btxpower_tracking = false;
}
}
- rtl8192_irq_enable(dev);
+ rtl92e_irq_enable(dev);
end:
priv->being_init_adapter = false;
return rtStatus;
@@ -969,27 +967,27 @@
u16 rate_config = 0;
net = &priv->rtllib->current_network;
- rtl8192_config_rate(dev, &rate_config);
+ rtl92e_config_rate(dev, &rate_config);
priv->dot11CurrentPreambleMode = PREAMBLE_AUTO;
priv->basic_rate = rate_config &= 0x15f;
- write_nic_dword(dev, BSSIDR, ((u32 *)net->bssid)[0]);
- write_nic_word(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
+ rtl92e_writel(dev, BSSIDR, ((u32 *)net->bssid)[0]);
+ rtl92e_writew(dev, BSSIDR+4, ((u16 *)net->bssid)[2]);
if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
- write_nic_word(dev, ATIMWND, 2);
- write_nic_word(dev, BCN_DMATIME, 256);
- write_nic_word(dev, BCN_INTERVAL, net->beacon_interval);
- write_nic_word(dev, BCN_DRV_EARLY_INT, 10);
- write_nic_byte(dev, BCN_ERR_THRESH, 100);
+ rtl92e_writew(dev, ATIMWND, 2);
+ rtl92e_writew(dev, BCN_DMATIME, 256);
+ rtl92e_writew(dev, BCN_INTERVAL, net->beacon_interval);
+ rtl92e_writew(dev, BCN_DRV_EARLY_INT, 10);
+ rtl92e_writeb(dev, BCN_ERR_THRESH, 100);
BcnTimeCfg |= (BcnCW<<BCN_TCFG_CW_SHIFT);
BcnTimeCfg |= BcnIFS<<BCN_TCFG_IFS;
- write_nic_word(dev, BCN_TCFG, BcnTimeCfg);
+ rtl92e_writew(dev, BCN_TCFG, BcnTimeCfg);
}
}
-void rtl8192_link_change(struct net_device *dev)
+void rtl92e_link_change(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_device *ieee = priv->rtllib;
@@ -1002,16 +1000,16 @@
priv->ops->update_ratr_table(dev);
if ((KEY_TYPE_WEP40 == ieee->pairwise_key_type) ||
(KEY_TYPE_WEP104 == ieee->pairwise_key_type))
- EnableHWSecurityConfig8192(dev);
+ rtl92e_enable_hw_security_config(dev);
} else {
- write_nic_byte(dev, 0x173, 0);
+ rtl92e_writeb(dev, 0x173, 0);
}
rtl8192e_update_msr(dev);
if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
u32 reg = 0;
- reg = read_nic_dword(dev, RCR);
+ reg = rtl92e_readl(dev, RCR);
if (priv->rtllib->state == RTLLIB_LINKED) {
if (ieee->IntelPromiscuousModeInfo.bPromiscuousOn)
;
@@ -1020,12 +1018,12 @@
} else
priv->ReceiveConfig = reg &= ~RCR_CBSSID;
- write_nic_dword(dev, RCR, reg);
+ rtl92e_writel(dev, RCR, reg);
}
}
-void rtl8192_AllowAllDestAddr(struct net_device *dev,
- bool bAllowAllDA, bool WriteIntoReg)
+void rtl92e_set_monitor_mode(struct net_device *dev, bool bAllowAllDA,
+ bool WriteIntoReg)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1035,7 +1033,7 @@
priv->ReceiveConfig &= ~RCR_AAP;
if (WriteIntoReg)
- write_nic_dword(dev, RCR, priv->ReceiveConfig);
+ rtl92e_writel(dev, RCR, priv->ReceiveConfig);
}
static u8 MRateToHwRate8190Pci(u8 rate)
@@ -1177,8 +1175,20 @@
return QueueSelect;
}
-void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc,
- struct cb_desc *cb_desc, struct sk_buff *skb)
+static u8 rtl8192_QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc)
+{
+ u8 tmp_Short;
+
+ tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) :
+ ((tcb_desc->bUseShortPreamble) ? 1 : 0);
+ if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
+ tmp_Short = 0;
+
+ return tmp_Short;
+}
+
+void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
+ struct cb_desc *cb_desc, struct sk_buff *skb)
{
struct r8192_priv *priv = rtllib_priv(dev);
dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
@@ -1286,9 +1296,8 @@
pdesc->TxBuffAddr = mapping;
}
-void rtl8192_tx_fill_cmd_desc(struct net_device *dev,
- struct tx_desc_cmd *entry,
- struct cb_desc *cb_desc, struct sk_buff *skb)
+void rtl92e_fill_tx_cmd_desc(struct net_device *dev, struct tx_desc_cmd *entry,
+ struct cb_desc *cb_desc, struct sk_buff *skb)
{
struct r8192_priv *priv = rtllib_priv(dev);
dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
@@ -1506,8 +1515,9 @@
pstats->bPacketBeacon = precord_stats->bPacketBeacon = bPacketBeacon;
pstats->bToSelfBA = precord_stats->bToSelfBA = bToSelfBA;
if (check_reg824 == 0) {
- reg824_bit9 = rtl8192_QueryBBReg(priv->rtllib->dev,
- rFPGA0_XA_HSSIParameter2, 0x200);
+ reg824_bit9 = rtl92e_get_bb_reg(priv->rtllib->dev,
+ rFPGA0_XA_HSSIParameter2,
+ 0x200);
check_reg824 = 1;
}
@@ -1575,7 +1585,7 @@
}
}
- pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
+ pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all);
pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
pstats->RecvSignalPower = rx_pwr_all;
@@ -1615,7 +1625,7 @@
rx_snrX /= 2;
priv->stats.rxSNRdB[i] = (long)rx_snrX;
- RSSI = rtl819x_query_rxpwrpercentage(rx_pwr[i]);
+ RSSI = rtl92e_rx_db_to_percent(rx_pwr[i]);
if (priv->brfpath_rxenable[i])
total_rssi += RSSI;
@@ -1628,7 +1638,7 @@
rx_pwr_all = (((pofdm_buf->pwdb_all) >> 1) & 0x7f) - 106;
- pwdb_all = rtl819x_query_rxpwrpercentage(rx_pwr_all);
+ pwdb_all = rtl92e_rx_db_to_percent(rx_pwr_all);
pstats->RxPWDBAll = precord_stats->RxPWDBAll = pwdb_all;
pstats->RxPower = precord_stats->RxPower = rx_pwr_all;
@@ -1645,7 +1655,7 @@
rx_evmX /= 2;
- evm = rtl819x_evm_dbtopercentage(rx_evmX);
+ evm = rtl92e_evm_db_to_percent(rx_evmX);
if (bpacket_match_bssid) {
if (i == 0) {
pstats->SignalQuality = (u8)(evm &
@@ -1721,8 +1731,8 @@
slide_rssi_index = 0;
tmp_val = priv->stats.slide_rssi_total/slide_rssi_statistics;
- priv->stats.signal_strength = rtl819x_translate_todbm(priv,
- (u8)tmp_val);
+ priv->stats.signal_strength = rtl92e_translate_to_dbm(priv,
+ (u8)tmp_val);
curr_st->rssi = priv->stats.signal_strength;
if (!prev_st->bPacketMatchBSSID) {
if (!prev_st->bToSelfBA)
@@ -1732,13 +1742,10 @@
if (!bcheck)
return;
- rtl819x_process_cck_rxpathsel(priv, prev_st);
-
priv->stats.num_process_phyinfo++;
if (!prev_st->bIsCCK && prev_st->bPacketToSelf) {
for (rfpath = RF90_PATH_A; rfpath < RF90_PATH_C; rfpath++) {
- if (!rtl8192_phy_CheckIsLegalRFPath(priv->rtllib->dev,
- rfpath))
+ if (!rtl92e_is_legal_rf_path(priv->rtllib->dev, rfpath))
continue;
RT_TRACE(COMP_DBG,
"Jacken -> pPreviousstats->RxMIMOSignalStrength[rfpath] = %d\n",
@@ -1813,7 +1820,7 @@
(RX_SMOOTH-1)) +
(prev_st->RxPWDBAll)) / (RX_SMOOTH);
}
- rtl819x_update_rxsignalstatistics8190pci(priv, prev_st);
+ rtl92e_update_rx_statistics(priv, prev_st);
}
if (prev_st->SignalQuality != 0) {
@@ -1900,7 +1907,7 @@
rtl8192_query_rxphystatus(priv, pstats, pdesc, pdrvinfo,
&previous_stats, bpacket_match_bssid,
bpacket_toself, bPacketBeacon, bToSelfBA);
- rtl8192_record_rxdesc_forlateruse(pstats, &previous_stats);
+ rtl92e_copy_mpdu_stats(pstats, &previous_stats);
}
static void rtl8192_UpdateReceivedRateHistogramStatistics(
@@ -2016,10 +2023,8 @@
priv->stats.received_rate_histogram[rcvType][rateIndex]++;
}
-bool rtl8192_rx_query_status_desc(struct net_device *dev,
- struct rtllib_rx_stats *stats,
- struct rx_desc *pdesc,
- struct sk_buff *skb)
+bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats,
+ struct rx_desc *pdesc, struct sk_buff *skb)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rx_fwinfo *pDrvInfo = NULL;
@@ -2063,9 +2068,9 @@
(pDrvInfo->FirstAGGR == 1);
stats->TimeStampLow = pDrvInfo->TSFL;
- stats->TimeStampHigh = read_nic_dword(dev, TSFR+4);
+ stats->TimeStampHigh = rtl92e_readl(dev, TSFR+4);
- rtl819x_UpdateRxPktTimeStamp(dev, stats);
+ rtl92e_update_rx_pkt_timestamp(dev, stats);
if ((stats->RxBufShift + stats->RxDrvInfoSize) > 0)
stats->bShift = 1;
@@ -2089,7 +2094,7 @@
return true;
}
-void rtl8192_halt_adapter(struct net_device *dev, bool reset)
+void rtl92e_stop_adapter(struct net_device *dev, bool reset)
{
struct r8192_priv *priv = rtllib_priv(dev);
int i;
@@ -2102,7 +2107,7 @@
if (!priv->rtllib->bSupportRemoteWakeUp) {
u1bTmp = 0x0;
- write_nic_byte(dev, CMDR, u1bTmp);
+ rtl92e_writeb(dev, CMDR, u1bTmp);
}
mdelay(20);
@@ -2113,18 +2118,18 @@
priv->bHwRfOffAction = 2;
if (!priv->rtllib->bSupportRemoteWakeUp) {
- PHY_SetRtl8192eRfOff(dev);
- ulRegRead = read_nic_dword(dev, CPU_GEN);
+ rtl92e_set_rf_off(dev);
+ ulRegRead = rtl92e_readl(dev, CPU_GEN);
ulRegRead |= CPU_GEN_SYSTEM_RESET;
- write_nic_dword(dev, CPU_GEN, ulRegRead);
+ rtl92e_writel(dev, CPU_GEN, ulRegRead);
} else {
- write_nic_dword(dev, WFCRC0, 0xffffffff);
- write_nic_dword(dev, WFCRC1, 0xffffffff);
- write_nic_dword(dev, WFCRC2, 0xffffffff);
+ rtl92e_writel(dev, WFCRC0, 0xffffffff);
+ rtl92e_writel(dev, WFCRC1, 0xffffffff);
+ rtl92e_writel(dev, WFCRC2, 0xffffffff);
- write_nic_byte(dev, PMR, 0x5);
- write_nic_byte(dev, MacBlkCtrl, 0xa);
+ rtl92e_writeb(dev, PMR, 0x5);
+ rtl92e_writeb(dev, MacBlkCtrl, 0xa);
}
}
@@ -2136,7 +2141,7 @@
skb_queue_purge(&priv->skb_queue);
}
-void rtl8192_update_ratr_table(struct net_device *dev)
+void rtl92e_update_ratr_table(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_device *ieee = priv->rtllib;
@@ -2145,7 +2150,7 @@
u16 rate_config = 0;
u8 rate_index = 0;
- rtl8192_config_rate(dev, &rate_config);
+ rtl92e_config_rate(dev, &rate_config);
ratr_value = rate_config | *pMcsRate << 12;
switch (ieee->mode) {
case IEEE_A:
@@ -2179,12 +2184,12 @@
else if (!ieee->pHTInfo->bCurTxBW40MHz &&
ieee->pHTInfo->bCurShortGI20MHz)
ratr_value |= 0x80000000;
- write_nic_dword(dev, RATR0+rate_index*4, ratr_value);
- write_nic_byte(dev, UFWP, 1);
+ rtl92e_writel(dev, RATR0+rate_index*4, ratr_value);
+ rtl92e_writeb(dev, UFWP, 1);
}
void
-rtl8192_InitializeVariables(struct net_device *dev)
+rtl92e_init_variables(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -2218,66 +2223,65 @@
priv->bfirst_after_down = false;
}
-void rtl8192_EnableInterrupt(struct net_device *dev)
+void rtl92e_enable_irq(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
priv->irq_enabled = 1;
- write_nic_dword(dev, INTA_MASK, priv->irq_mask[0]);
+ rtl92e_writel(dev, INTA_MASK, priv->irq_mask[0]);
}
-void rtl8192_DisableInterrupt(struct net_device *dev)
+void rtl92e_disable_irq(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
- write_nic_dword(dev, INTA_MASK, 0);
+ rtl92e_writel(dev, INTA_MASK, 0);
priv->irq_enabled = 0;
}
-void rtl8192_ClearInterrupt(struct net_device *dev)
+void rtl92e_clear_irq(struct net_device *dev)
{
u32 tmp = 0;
- tmp = read_nic_dword(dev, ISR);
- write_nic_dword(dev, ISR, tmp);
+ tmp = rtl92e_readl(dev, ISR);
+ rtl92e_writel(dev, ISR, tmp);
}
-void rtl8192_enable_rx(struct net_device *dev)
+void rtl92e_enable_rx(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
- write_nic_dword(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]);
+ rtl92e_writel(dev, RDQDA, priv->rx_ring_dma[RX_MPDU_QUEUE]);
}
static const u32 TX_DESC_BASE[] = {
BKQDA, BEQDA, VIQDA, VOQDA, HCCAQDA, CQDA, MQDA, HQDA, BQDA
};
-void rtl8192_enable_tx(struct net_device *dev)
+void rtl92e_enable_tx(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
u32 i;
for (i = 0; i < MAX_TX_QUEUE_COUNT; i++)
- write_nic_dword(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma);
+ rtl92e_writel(dev, TX_DESC_BASE[i], priv->tx_ring[i].dma);
}
-void rtl8192_interrupt_recognized(struct net_device *dev, u32 *p_inta,
- u32 *p_intb)
+void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta, u32 *p_intb)
{
- *p_inta = read_nic_dword(dev, ISR);
- write_nic_dword(dev, ISR, *p_inta);
+ *p_inta = rtl92e_readl(dev, ISR);
+ rtl92e_writel(dev, ISR, *p_inta);
}
-bool rtl8192_HalRxCheckStuck(struct net_device *dev)
+bool rtl92e_is_rx_stuck(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
- u16 RegRxCounter = read_nic_word(dev, 0x130);
+ u16 RegRxCounter = rtl92e_readw(dev, 0x130);
bool bStuck = false;
static u8 rx_chk_cnt;
u32 SlotIndex = 0, TotalRxStuckCount = 0;
@@ -2338,11 +2342,11 @@
return bStuck;
}
-bool rtl8192_HalTxCheckStuck(struct net_device *dev)
+bool rtl92e_is_tx_stuck(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
bool bStuck = false;
- u16 RegTxCounter = read_nic_word(dev, 0x128);
+ u16 RegTxCounter = rtl92e_readw(dev, 0x128);
RT_TRACE(COMP_RESET, "%s():RegTxCounter is %d,TxCounter is %d\n",
__func__, RegTxCounter, priv->TxCounter);
@@ -2355,7 +2359,7 @@
return bStuck;
}
-bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev)
+bool rtl92e_get_nmode_support_by_sec(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_device *ieee = priv->rtllib;
@@ -2369,34 +2373,10 @@
}
}
-bool rtl8192_GetHalfNmodeSupportByAPs(struct net_device *dev)
+bool rtl92e_is_halfn_supported_by_ap(struct net_device *dev)
{
- bool Reval;
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_device *ieee = priv->rtllib;
- if (ieee->bHalfWirelessN24GMode == true)
- Reval = true;
- else
- Reval = false;
-
- return Reval;
-}
-
-u8 rtl8192_QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc)
-{
- u8 tmp_Short;
-
- tmp_Short = (TxHT == 1) ? ((tcb_desc->bUseShortGI) ? 1 : 0) :
- ((tcb_desc->bUseShortPreamble) ? 1 : 0);
- if (TxHT == 1 && TxRate != DESC90_RATEMCS15)
- tmp_Short = 0;
-
- return tmp_Short;
-}
-
-void ActUpdateChannelAccessSetting(struct net_device *dev,
- enum wireless_mode WirelessMode,
- struct channel_access_setting *ChnlAccessSetting)
-{
+ return ieee->bHalfWirelessN24GMode;
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h
index dbe0e1c..6bd6b3a 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.h
@@ -27,36 +27,30 @@
#include "r8190P_def.h"
-u8 rtl8192_QueryIsShort(u8 TxHT, u8 TxRate, struct cb_desc *tcb_desc);
-bool rtl8192_GetHalfNmodeSupportByAPs(struct net_device *dev);
-bool rtl8192_GetNmodeSupportBySecCfg(struct net_device *dev);
-bool rtl8192_HalTxCheckStuck(struct net_device *dev);
-bool rtl8192_HalRxCheckStuck(struct net_device *dev);
-void rtl8192_interrupt_recognized(struct net_device *dev, u32 *p_inta,
- u32 *p_intb);
-void rtl8192_enable_rx(struct net_device *dev);
-void rtl8192_enable_tx(struct net_device *dev);
-void rtl8192_EnableInterrupt(struct net_device *dev);
-void rtl8192_DisableInterrupt(struct net_device *dev);
-void rtl8192_ClearInterrupt(struct net_device *dev);
-void rtl8192_InitializeVariables(struct net_device *dev);
-void rtl8192e_start_beacon(struct net_device *dev);
-void rtl8192e_SetHwReg(struct net_device *dev, u8 variable, u8 *val);
-void rtl8192_get_eeprom_size(struct net_device *dev);
-bool rtl8192_adapter_start(struct net_device *dev);
-void rtl8192_link_change(struct net_device *dev);
-void rtl8192_AllowAllDestAddr(struct net_device *dev, bool bAllowAllDA,
- bool WriteIntoReg);
-void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc,
- struct cb_desc *cb_desc,
- struct sk_buff *skb);
-void rtl8192_tx_fill_cmd_desc(struct net_device *dev,
- struct tx_desc_cmd *entry,
- struct cb_desc *cb_desc, struct sk_buff *skb);
-bool rtl8192_rx_query_status_desc(struct net_device *dev,
- struct rtllib_rx_stats *stats,
- struct rx_desc *pdesc,
- struct sk_buff *skb);
-void rtl8192_halt_adapter(struct net_device *dev, bool reset);
-void rtl8192_update_ratr_table(struct net_device *dev);
+bool rtl92e_is_halfn_supported_by_ap(struct net_device *dev);
+bool rtl92e_get_nmode_support_by_sec(struct net_device *dev);
+bool rtl92e_is_tx_stuck(struct net_device *dev);
+bool rtl92e_is_rx_stuck(struct net_device *dev);
+void rtl92e_ack_irq(struct net_device *dev, u32 *p_inta, u32 *p_intb);
+void rtl92e_enable_rx(struct net_device *dev);
+void rtl92e_enable_tx(struct net_device *dev);
+void rtl92e_enable_irq(struct net_device *dev);
+void rtl92e_disable_irq(struct net_device *dev);
+void rtl92e_clear_irq(struct net_device *dev);
+void rtl92e_init_variables(struct net_device *dev);
+void rtl92e_start_beacon(struct net_device *dev);
+void rtl92e_set_reg(struct net_device *dev, u8 variable, u8 *val);
+void rtl92e_get_eeprom_size(struct net_device *dev);
+bool rtl92e_start_adapter(struct net_device *dev);
+void rtl92e_link_change(struct net_device *dev);
+void rtl92e_set_monitor_mode(struct net_device *dev, bool bAllowAllDA,
+ bool WriteIntoReg);
+void rtl92e_fill_tx_desc(struct net_device *dev, struct tx_desc *pdesc,
+ struct cb_desc *cb_desc, struct sk_buff *skb);
+void rtl92e_fill_tx_cmd_desc(struct net_device *dev, struct tx_desc_cmd *entry,
+ struct cb_desc *cb_desc, struct sk_buff *skb);
+bool rtl92e_get_rx_stats(struct net_device *dev, struct rtllib_rx_stats *stats,
+ struct rx_desc *pdesc, struct sk_buff *skb);
+void rtl92e_stop_adapter(struct net_device *dev, bool reset);
+void rtl92e_update_ratr_table(struct net_device *dev);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
index 17d2a15..5c527c4 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
@@ -23,7 +23,7 @@
#include "r8192E_firmware.h"
#include <linux/firmware.h>
-void firmware_init_param(struct net_device *dev)
+void rtl92e_init_fw_param(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rt_firmware *pfirmware = priv->pFirmware;
@@ -46,7 +46,7 @@
struct cb_desc *tcb_desc;
u8 bLastIniPkt;
- firmware_init_param(dev);
+ rtl92e_init_fw_param(dev);
frag_threshold = pfirmware->cmdpacket_frag_thresold;
do {
if ((buffer_len - frag_offset) > frag_threshold) {
@@ -96,7 +96,7 @@
} while (frag_offset < buffer_len);
- write_nic_byte(dev, TPPoll, TPPoll_CQ);
+ rtl92e_writeb(dev, TPPoll, TPPoll_CQ);
return true;
}
@@ -109,7 +109,7 @@
timeout = jiffies + msecs_to_jiffies(200);
while (time_before(jiffies, timeout)) {
- CPU_status = read_nic_dword(dev, CPU_GEN);
+ CPU_status = rtl92e_readl(dev, CPU_GEN);
if (CPU_status & CPU_GEN_PUT_CODE_OK)
break;
mdelay(2);
@@ -122,14 +122,14 @@
RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
}
- CPU_status = read_nic_dword(dev, CPU_GEN);
- write_nic_byte(dev, CPU_GEN,
- (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
+ CPU_status = rtl92e_readl(dev, CPU_GEN);
+ rtl92e_writeb(dev, CPU_GEN,
+ (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
mdelay(1);
timeout = jiffies + msecs_to_jiffies(200);
while (time_before(jiffies, timeout)) {
- CPU_status = read_nic_dword(dev, CPU_GEN);
+ CPU_status = rtl92e_readl(dev, CPU_GEN);
if (CPU_status&CPU_GEN_BOOT_RDY)
break;
mdelay(2);
@@ -158,7 +158,7 @@
timeout = jiffies + msecs_to_jiffies(20);
while (time_before(jiffies, timeout)) {
- CPU_status = read_nic_dword(dev, CPU_GEN);
+ CPU_status = rtl92e_readl(dev, CPU_GEN);
if (CPU_status&CPU_GEN_FIRM_RDY)
break;
mdelay(2);
@@ -223,7 +223,7 @@
return rt_status;
}
-bool init_firmware(struct net_device *dev)
+bool rtl92e_init_fw(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
bool rt_status = true;
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
index d79e542..fa760f7 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.h
@@ -19,8 +19,6 @@
#ifndef __INC_FIRMWARE_H
#define __INC_FIRMWARE_H
-#define RTL8190_CPU_START_OFFSET 0x80
-
#define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4*(v/4) - 8)
#define RTL8192E_BOOT_IMG_FW "RTL8192E/boot.img"
@@ -61,7 +59,7 @@
u16 firmware_buf_size[MAX_FW_INIT_STEP];
};
-bool init_firmware(struct net_device *dev);
-extern void firmware_init_param(struct net_device *dev);
+bool rtl92e_init_fw(struct net_device *dev);
+void rtl92e_init_fw_param(struct net_device *dev);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
index 43c3fb8..c81832d 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_hw.h
@@ -119,10 +119,10 @@
#define EPROM_CMD_NORMAL 0
#define EPROM_CMD_LOAD 1
#define EPROM_CMD_PROGRAM 2
-#define EPROM_CS_SHIFT 3
-#define EPROM_CK_SHIFT 2
-#define EPROM_W_SHIFT 1
-#define EPROM_R_SHIFT 0
+#define EPROM_CS_BIT 3
+#define EPROM_CK_BIT 2
+#define EPROM_W_BIT 1
+#define EPROM_R_BIT 0
AFR = 0x010,
#define AFR_CardBEn (1<<0)
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
index fba7654..3a15a0f 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.c
@@ -64,7 +64,7 @@
return i;
}
-u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath)
+u8 rtl92e_is_legal_rf_path(struct net_device *dev, u32 eRFPath)
{
u8 ret = 1;
struct r8192_priv *priv = rtllib_priv(dev);
@@ -80,27 +80,27 @@
return ret;
}
-void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask,
- u32 dwData)
+void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask,
+ u32 dwData)
{
u32 OriginalValue, BitShift, NewValue;
if (dwBitMask != bMaskDWord) {
- OriginalValue = read_nic_dword(dev, dwRegAddr);
+ OriginalValue = rtl92e_readl(dev, dwRegAddr);
BitShift = rtl8192_CalculateBitShift(dwBitMask);
NewValue = (((OriginalValue) & (~dwBitMask)) |
(dwData << BitShift));
- write_nic_dword(dev, dwRegAddr, NewValue);
+ rtl92e_writel(dev, dwRegAddr, NewValue);
} else
- write_nic_dword(dev, dwRegAddr, dwData);
+ rtl92e_writel(dev, dwRegAddr, dwData);
}
-u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask)
+u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask)
{
u32 Ret = 0, OriginalValue, BitShift;
- OriginalValue = read_nic_dword(dev, dwRegAddr);
+ OriginalValue = rtl92e_readl(dev, dwRegAddr);
BitShift = rtl8192_CalculateBitShift(dwBitMask);
Ret = (OriginalValue & dwBitMask) >> BitShift;
@@ -117,19 +117,19 @@
Offset &= 0x3f;
if (priv->rf_chip == RF_8256) {
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
if (Offset >= 31) {
priv->RfReg0Value[eRFPath] |= 0x140;
- rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
- bMaskDWord,
- (priv->RfReg0Value[eRFPath]<<16));
+ rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath]<<16));
NewOffset = Offset - 30;
} else if (Offset >= 16) {
priv->RfReg0Value[eRFPath] |= 0x100;
priv->RfReg0Value[eRFPath] &= (~0x40);
- rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
- bMaskDWord,
- (priv->RfReg0Value[eRFPath]<<16));
+ rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath]<<16));
NewOffset = Offset - 15;
} else
@@ -139,23 +139,23 @@
"check RF type here, need to be 8256\n");
NewOffset = Offset;
}
- rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress,
- NewOffset);
- rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x0);
- rtl8192_setBBreg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadAddress,
+ NewOffset);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x0);
+ rtl92e_set_bb_reg(dev, pPhyReg->rfHSSIPara2, bLSSIReadEdge, 0x1);
mdelay(1);
- ret = rtl8192_QueryBBReg(dev, pPhyReg->rfLSSIReadBack,
- bLSSIReadBackData);
+ ret = rtl92e_get_bb_reg(dev, pPhyReg->rfLSSIReadBack,
+ bLSSIReadBackData);
if (priv->rf_chip == RF_8256) {
priv->RfReg0Value[eRFPath] &= 0xebf;
- rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord,
- (priv->RfReg0Value[eRFPath] << 16));
+ rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, bMaskDWord,
+ (priv->RfReg0Value[eRFPath] << 16));
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
}
@@ -173,20 +173,20 @@
Offset &= 0x3f;
if (priv->rf_chip == RF_8256) {
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0xf00, 0x0);
if (Offset >= 31) {
priv->RfReg0Value[eRFPath] |= 0x140;
- rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
- bMaskDWord,
- (priv->RfReg0Value[eRFPath] << 16));
+ rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath] << 16));
NewOffset = Offset - 30;
} else if (Offset >= 16) {
priv->RfReg0Value[eRFPath] |= 0x100;
priv->RfReg0Value[eRFPath] &= (~0x40);
- rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset,
- bMaskDWord,
- (priv->RfReg0Value[eRFPath] << 16));
+ rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath] << 16));
NewOffset = Offset - 15;
} else
NewOffset = Offset;
@@ -198,7 +198,7 @@
DataAndAddr = (Data<<16) | (NewOffset&0x3f);
- rtl8192_setBBreg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
+ rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset, bMaskDWord, DataAndAddr);
if (Offset == 0x0)
priv->RfReg0Value[eRFPath] = Data;
@@ -206,23 +206,21 @@
if (priv->rf_chip == RF_8256) {
if (Offset != 0) {
priv->RfReg0Value[eRFPath] &= 0xebf;
- rtl8192_setBBreg(
- dev,
- pPhyReg->rf3wireOffset,
- bMaskDWord,
- (priv->RfReg0Value[eRFPath] << 16));
+ rtl92e_set_bb_reg(dev, pPhyReg->rf3wireOffset,
+ bMaskDWord,
+ (priv->RfReg0Value[eRFPath] << 16));
}
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x3);
}
}
-void rtl8192_phy_SetRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
- u32 RegAddr, u32 BitMask, u32 Data)
+void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask, u32 Data)
{
struct r8192_priv *priv = rtllib_priv(dev);
u32 Original_Value, BitShift, New_Value;
- if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+ if (!rtl92e_is_legal_rf_path(dev, eRFPath))
return;
if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter)
return;
@@ -256,13 +254,13 @@
}
}
-u32 rtl8192_phy_QueryRFReg(struct net_device *dev, enum rf90_radio_path eRFPath,
- u32 RegAddr, u32 BitMask)
+u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask)
{
u32 Original_Value, Readback_Value, BitShift;
struct r8192_priv *priv = rtllib_priv(dev);
- if (!rtl8192_phy_CheckIsLegalRFPath(dev, eRFPath))
+ if (!rtl92e_is_legal_rf_path(dev, eRFPath))
return 0;
if (priv->rtllib->eRFPowerState != eRfOn && !priv->being_init_adapter)
return 0;
@@ -289,20 +287,20 @@
Data |= ((Offset & 0xFF) << 12);
Data |= ((eRFPath & 0x3) << 20);
Data |= 0x80000000;
- while (read_nic_dword(dev, QPNR)&0x80000000) {
+ while (rtl92e_readl(dev, QPNR) & 0x80000000) {
if (time++ < 100)
udelay(10);
else
break;
}
- write_nic_dword(dev, QPNR, Data);
- while (read_nic_dword(dev, QPNR) & 0x80000000) {
+ rtl92e_writel(dev, QPNR, Data);
+ while (rtl92e_readl(dev, QPNR) & 0x80000000) {
if (time++ < 100)
udelay(10);
else
return 0;
}
- return read_nic_dword(dev, RF_DATA);
+ return rtl92e_readl(dev, RF_DATA);
}
@@ -317,18 +315,18 @@
Data |= 0x400000;
Data |= 0x80000000;
- while (read_nic_dword(dev, QPNR) & 0x80000000) {
+ while (rtl92e_readl(dev, QPNR) & 0x80000000) {
if (time++ < 100)
udelay(10);
else
break;
}
- write_nic_dword(dev, QPNR, Data);
+ rtl92e_writel(dev, QPNR, Data);
}
-void rtl8192_phy_configmac(struct net_device *dev)
+void rtl92e_config_mac(struct net_device *dev)
{
u32 dwArrayLen = 0, i = 0;
u32 *pdwArray = NULL;
@@ -350,14 +348,14 @@
pdwArray[i], pdwArray[i+1], pdwArray[i+2]);
if (pdwArray[i] == 0x318)
pdwArray[i+2] = 0x00000800;
- rtl8192_setBBreg(dev, pdwArray[i], pdwArray[i+1],
- pdwArray[i+2]);
+ rtl92e_set_bb_reg(dev, pdwArray[i], pdwArray[i+1],
+ pdwArray[i+2]);
}
return;
}
-void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType)
+static void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType)
{
int i;
u32 *Rtl819XPHY_REGArray_Table = NULL;
@@ -377,9 +375,9 @@
if (ConfigType == BaseBand_Config_PHY_REG) {
for (i = 0; i < PHY_REGArrayLen; i += 2) {
- rtl8192_setBBreg(dev, Rtl819XPHY_REGArray_Table[i],
- bMaskDWord,
- Rtl819XPHY_REGArray_Table[i+1]);
+ rtl92e_set_bb_reg(dev, Rtl819XPHY_REGArray_Table[i],
+ bMaskDWord,
+ Rtl819XPHY_REGArray_Table[i+1]);
RT_TRACE(COMP_DBG,
"i: %x, The Rtl819xUsbPHY_REGArray[0] is %x Rtl819xUsbPHY_REGArray[1] is %x\n",
i, Rtl819XPHY_REGArray_Table[i],
@@ -387,9 +385,9 @@
}
} else if (ConfigType == BaseBand_Config_AGC_TAB) {
for (i = 0; i < AGCTAB_ArrayLen; i += 2) {
- rtl8192_setBBreg(dev, Rtl819XAGCTAB_Array_Table[i],
- bMaskDWord,
- Rtl819XAGCTAB_Array_Table[i+1]);
+ rtl92e_set_bb_reg(dev, Rtl819XAGCTAB_Array_Table[i],
+ bMaskDWord,
+ Rtl819XAGCTAB_Array_Table[i+1]);
RT_TRACE(COMP_DBG,
"i:%x, The rtl819XAGCTAB_Array[0] is %x rtl819XAGCTAB_Array[1] is %x\n",
i, Rtl819XAGCTAB_Array_Table[i],
@@ -489,9 +487,8 @@
}
-bool rtl8192_phy_checkBBAndRF(struct net_device *dev,
- enum hw90_block CheckBlock,
- enum rf90_radio_path eRFPath)
+bool rtl92e_check_bb_and_rf(struct net_device *dev, enum hw90_block CheckBlock,
+ enum rf90_radio_path eRFPath)
{
bool ret = true;
u32 i, CheckTimes = 4, dwRegRead = 0;
@@ -515,20 +512,20 @@
switch (CheckBlock) {
case HW90_BLOCK_PHY0:
case HW90_BLOCK_PHY1:
- write_nic_dword(dev, WriteAddr[CheckBlock],
- WriteData[i]);
- dwRegRead = read_nic_dword(dev, WriteAddr[CheckBlock]);
+ rtl92e_writel(dev, WriteAddr[CheckBlock],
+ WriteData[i]);
+ dwRegRead = rtl92e_readl(dev, WriteAddr[CheckBlock]);
break;
case HW90_BLOCK_RF:
WriteData[i] &= 0xfff;
- rtl8192_phy_SetRFReg(dev, eRFPath,
- WriteAddr[HW90_BLOCK_RF],
- bMask12Bits, WriteData[i]);
+ rtl92e_set_rf_reg(dev, eRFPath,
+ WriteAddr[HW90_BLOCK_RF],
+ bMask12Bits, WriteData[i]);
mdelay(10);
- dwRegRead = rtl8192_phy_QueryRFReg(dev, eRFPath,
- WriteAddr[HW90_BLOCK_RF],
- bMaskDWord);
+ dwRegRead = rtl92e_get_rf_reg(dev, eRFPath,
+ WriteAddr[HW90_BLOCK_RF],
+ bMaskDWord);
mdelay(10);
break;
@@ -555,29 +552,29 @@
u8 bRegValue = 0, eCheckItem = 0;
u32 dwRegValue = 0;
- bRegValue = read_nic_byte(dev, BB_GLOBAL_RESET);
- write_nic_byte(dev, BB_GLOBAL_RESET, (bRegValue|BB_GLOBAL_RESET_BIT));
+ bRegValue = rtl92e_readb(dev, BB_GLOBAL_RESET);
+ rtl92e_writeb(dev, BB_GLOBAL_RESET, (bRegValue|BB_GLOBAL_RESET_BIT));
- dwRegValue = read_nic_dword(dev, CPU_GEN);
- write_nic_dword(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST)));
+ dwRegValue = rtl92e_readl(dev, CPU_GEN);
+ rtl92e_writel(dev, CPU_GEN, (dwRegValue&(~CPU_GEN_BB_RST)));
for (eCheckItem = (enum hw90_block)HW90_BLOCK_PHY0;
eCheckItem <= HW90_BLOCK_PHY1; eCheckItem++) {
- rtStatus = rtl8192_phy_checkBBAndRF(dev,
- (enum hw90_block)eCheckItem,
- (enum rf90_radio_path)0);
+ rtStatus = rtl92e_check_bb_and_rf(dev,
+ (enum hw90_block)eCheckItem,
+ (enum rf90_radio_path)0);
if (!rtStatus) {
RT_TRACE((COMP_ERR | COMP_PHY),
- "PHY_RF8256_Config():Check PHY%d Fail!!\n",
+ "rtl92e_config_rf():Check PHY%d Fail!!\n",
eCheckItem-1);
return rtStatus;
}
}
- rtl8192_setBBreg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bCCKEn|bOFDMEn, 0x0);
rtl8192_phyConfigBB(dev, BaseBand_Config_PHY_REG);
- dwRegValue = read_nic_dword(dev, CPU_GEN);
- write_nic_dword(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST));
+ dwRegValue = rtl92e_readl(dev, CPU_GEN);
+ rtl92e_writel(dev, CPU_GEN, (dwRegValue|CPU_GEN_BB_RST));
rtl8192_phyConfigBB(dev, BaseBand_Config_AGC_TAB);
@@ -588,57 +585,57 @@
priv->AntennaTxPwDiff[0]);
else
dwRegValue = 0x0;
- rtl8192_setBBreg(dev, rFPGA0_TxGainStage,
- (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue);
+ rtl92e_set_bb_reg(dev, rFPGA0_TxGainStage,
+ (bXBTxAGC|bXCTxAGC|bXDTxAGC), dwRegValue);
dwRegValue = priv->CrystalCap;
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, bXtalCap92x,
- dwRegValue);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, bXtalCap92x,
+ dwRegValue);
}
return rtStatus;
}
-bool rtl8192_BBConfig(struct net_device *dev)
+bool rtl92e_config_bb(struct net_device *dev)
{
rtl8192_InitBBRFRegDef(dev);
return rtl8192_BB_Config_ParaFile(dev);
}
-void rtl8192_phy_getTxPower(struct net_device *dev)
+void rtl92e_get_tx_power(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
priv->MCSTxPowerLevelOriginalOffset[0] =
- read_nic_dword(dev, rTxAGC_Rate18_06);
+ rtl92e_readl(dev, rTxAGC_Rate18_06);
priv->MCSTxPowerLevelOriginalOffset[1] =
- read_nic_dword(dev, rTxAGC_Rate54_24);
+ rtl92e_readl(dev, rTxAGC_Rate54_24);
priv->MCSTxPowerLevelOriginalOffset[2] =
- read_nic_dword(dev, rTxAGC_Mcs03_Mcs00);
+ rtl92e_readl(dev, rTxAGC_Mcs03_Mcs00);
priv->MCSTxPowerLevelOriginalOffset[3] =
- read_nic_dword(dev, rTxAGC_Mcs07_Mcs04);
+ rtl92e_readl(dev, rTxAGC_Mcs07_Mcs04);
priv->MCSTxPowerLevelOriginalOffset[4] =
- read_nic_dword(dev, rTxAGC_Mcs11_Mcs08);
+ rtl92e_readl(dev, rTxAGC_Mcs11_Mcs08);
priv->MCSTxPowerLevelOriginalOffset[5] =
- read_nic_dword(dev, rTxAGC_Mcs15_Mcs12);
+ rtl92e_readl(dev, rTxAGC_Mcs15_Mcs12);
- priv->DefaultInitialGain[0] = read_nic_byte(dev, rOFDM0_XAAGCCore1);
- priv->DefaultInitialGain[1] = read_nic_byte(dev, rOFDM0_XBAGCCore1);
- priv->DefaultInitialGain[2] = read_nic_byte(dev, rOFDM0_XCAGCCore1);
- priv->DefaultInitialGain[3] = read_nic_byte(dev, rOFDM0_XDAGCCore1);
+ priv->DefaultInitialGain[0] = rtl92e_readb(dev, rOFDM0_XAAGCCore1);
+ priv->DefaultInitialGain[1] = rtl92e_readb(dev, rOFDM0_XBAGCCore1);
+ priv->DefaultInitialGain[2] = rtl92e_readb(dev, rOFDM0_XCAGCCore1);
+ priv->DefaultInitialGain[3] = rtl92e_readb(dev, rOFDM0_XDAGCCore1);
RT_TRACE(COMP_INIT,
"Default initial gain (c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n",
priv->DefaultInitialGain[0], priv->DefaultInitialGain[1],
priv->DefaultInitialGain[2], priv->DefaultInitialGain[3]);
- priv->framesync = read_nic_byte(dev, rOFDM0_RxDetector3);
- priv->framesyncC34 = read_nic_dword(dev, rOFDM0_RxDetector2);
+ priv->framesync = rtl92e_readb(dev, rOFDM0_RxDetector3);
+ priv->framesyncC34 = rtl92e_readl(dev, rOFDM0_RxDetector2);
RT_TRACE(COMP_INIT, "Default framesync (0x%x) = 0x%x\n",
rOFDM0_RxDetector3, priv->framesync);
- priv->SifsTime = read_nic_word(dev, SIFS);
+ priv->SifsTime = rtl92e_readw(dev, SIFS);
}
-void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel)
+void rtl92e_set_tx_power(struct net_device *dev, u8 channel)
{
struct r8192_priv *priv = rtllib_priv(dev);
u8 powerlevel = 0, powerlevelOFDM24G = 0;
@@ -671,16 +668,17 @@
priv->AntennaTxPwDiff[1]<<4 |
priv->AntennaTxPwDiff[0]);
- rtl8192_setBBreg(dev, rFPGA0_TxGainStage,
- (bXBTxAGC|bXCTxAGC|bXDTxAGC), u4RegValue);
+ rtl92e_set_bb_reg(dev, rFPGA0_TxGainStage,
+ (bXBTxAGC|bXCTxAGC|bXDTxAGC),
+ u4RegValue);
}
}
switch (priv->rf_chip) {
case RF_8225:
break;
case RF_8256:
- PHY_SetRF8256CCKTxPower(dev, powerlevel);
- PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G);
+ rtl92e_set_cck_tx_power(dev, powerlevel);
+ rtl92e_set_ofdm_tx_power(dev, powerlevelOFDM24G);
break;
case RF_8258:
break;
@@ -690,7 +688,7 @@
}
}
-bool rtl8192_phy_RFConfig(struct net_device *dev)
+bool rtl92e_config_phy(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
bool rtStatus = true;
@@ -699,7 +697,7 @@
case RF_8225:
break;
case RF_8256:
- rtStatus = PHY_RF8256_Config(dev);
+ rtStatus = rtl92e_config_rf(dev);
break;
case RF_8258:
@@ -714,12 +712,7 @@
return rtStatus;
}
-void rtl8192_phy_updateInitGain(struct net_device *dev)
-{
-}
-
-u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
- enum rf90_radio_path eRFPath)
+u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath)
{
int i;
@@ -731,10 +724,9 @@
msleep(100);
continue;
}
- rtl8192_phy_SetRFReg(dev, eRFPath,
- Rtl819XRadioA_Array[i],
- bMask12Bits,
- Rtl819XRadioA_Array[i+1]);
+ rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioA_Array[i],
+ bMask12Bits,
+ Rtl819XRadioA_Array[i+1]);
}
break;
@@ -744,10 +736,9 @@
msleep(100);
continue;
}
- rtl8192_phy_SetRFReg(dev, eRFPath,
- Rtl819XRadioB_Array[i],
- bMask12Bits,
- Rtl819XRadioB_Array[i+1]);
+ rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioB_Array[i],
+ bMask12Bits,
+ Rtl819XRadioB_Array[i+1]);
}
break;
@@ -757,10 +748,9 @@
msleep(100);
continue;
}
- rtl8192_phy_SetRFReg(dev, eRFPath,
- Rtl819XRadioC_Array[i],
- bMask12Bits,
- Rtl819XRadioC_Array[i+1]);
+ rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioC_Array[i],
+ bMask12Bits,
+ Rtl819XRadioC_Array[i+1]);
}
break;
@@ -770,9 +760,9 @@
msleep(100);
continue;
}
- rtl8192_phy_SetRFReg(dev, eRFPath,
- Rtl819XRadioD_Array[i], bMask12Bits,
- Rtl819XRadioD_Array[i+1]);
+ rtl92e_set_rf_reg(dev, eRFPath, Rtl819XRadioD_Array[i],
+ bMask12Bits,
+ Rtl819XRadioD_Array[i+1]);
}
break;
@@ -794,8 +784,8 @@
break;
case RF_8256:
- PHY_SetRF8256CCKTxPower(dev, powerlevel);
- PHY_SetRF8256OFDMTxPower(dev, powerlevelOFDM24G);
+ rtl92e_set_cck_tx_power(dev, powerlevel);
+ rtl92e_set_ofdm_tx_power(dev, powerlevelOFDM24G);
break;
case RF_8258:
@@ -941,21 +931,21 @@
rtl8192_SetTxPowerLevel(dev, channel);
break;
case CmdID_WritePortUlong:
- write_nic_dword(dev, CurrentCmd->Para1,
- CurrentCmd->Para2);
+ rtl92e_writel(dev, CurrentCmd->Para1,
+ CurrentCmd->Para2);
break;
case CmdID_WritePortUshort:
- write_nic_word(dev, CurrentCmd->Para1,
- (u16)CurrentCmd->Para2);
+ rtl92e_writew(dev, CurrentCmd->Para1,
+ (u16)CurrentCmd->Para2);
break;
case CmdID_WritePortUchar:
- write_nic_byte(dev, CurrentCmd->Para1,
- (u8)CurrentCmd->Para2);
+ rtl92e_writeb(dev, CurrentCmd->Para1,
+ (u8)CurrentCmd->Para2);
break;
case CmdID_RF_WriteReg:
for (eRFPath = 0; eRFPath <
priv->NumTotalRFPath; eRFPath++)
- rtl8192_phy_SetRFReg(dev,
+ rtl92e_set_rf_reg(dev,
(enum rf90_radio_path)eRFPath,
CurrentCmd->Para1, bMask12Bits,
CurrentCmd->Para2<<7);
@@ -986,7 +976,7 @@
break;
}
}
-void rtl8192_SwChnl_WorkItem(struct net_device *dev)
+static void rtl8192_SwChnl_WorkItem(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1001,7 +991,7 @@
RT_TRACE(COMP_TRACE, "<== SwChnlCallback819xUsbWorkItem()\n");
}
-u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel)
+u8 rtl92e_set_channel(struct net_device *dev, u8 channel)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1082,13 +1072,13 @@
if (priv->rtllib->current_network.channel == 14 &&
!priv->bcck_in_ch14) {
priv->bcck_in_ch14 = true;
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
} else if (priv->rtllib->current_network.channel !=
14 && priv->bcck_in_ch14) {
priv->bcck_in_ch14 = false;
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
} else {
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
}
break;
@@ -1110,13 +1100,13 @@
if (priv->rtllib->current_network.channel == 14 &&
!priv->bcck_in_ch14) {
priv->bcck_in_ch14 = true;
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
} else if (priv->rtllib->current_network.channel != 14
&& priv->bcck_in_ch14) {
priv->bcck_in_ch14 = false;
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
} else {
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
}
break;
}
@@ -1150,7 +1140,7 @@
priv->CCK_index);
break;
}
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
}
static void CCK_Tx_Power_Track_BW_Switch(struct net_device *dev)
@@ -1163,7 +1153,7 @@
CCK_Tx_Power_Track_BW_Switch_ThermalMeter(dev);
}
-void rtl8192_SetBWModeWorkItem(struct net_device *dev)
+static void rtl8192_SetBWModeWorkItem(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1183,17 +1173,17 @@
netdev_err(dev, "%s(): Driver is not initialized\n", __func__);
return;
}
- regBwOpMode = read_nic_byte(dev, BW_OPMODE);
+ regBwOpMode = rtl92e_readb(dev, BW_OPMODE);
switch (priv->CurrentChannelBW) {
case HT_CHANNEL_WIDTH_20:
regBwOpMode |= BW_OPMODE_20MHZ;
- write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+ rtl92e_writeb(dev, BW_OPMODE, regBwOpMode);
break;
case HT_CHANNEL_WIDTH_20_40:
regBwOpMode &= ~BW_OPMODE_20MHZ;
- write_nic_byte(dev, BW_OPMODE, regBwOpMode);
+ rtl92e_writeb(dev, BW_OPMODE, regBwOpMode);
break;
default:
@@ -1204,38 +1194,38 @@
switch (priv->CurrentChannelBW) {
case HT_CHANNEL_WIDTH_20:
- rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x0);
- rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bRFMOD, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA1_RFMOD, bRFMOD, 0x0);
if (!priv->btxpower_tracking) {
- write_nic_dword(dev, rCCK0_TxFilter1, 0x1a1b0000);
- write_nic_dword(dev, rCCK0_TxFilter2, 0x090e1317);
- write_nic_dword(dev, rCCK0_DebugPort, 0x00000204);
+ rtl92e_writel(dev, rCCK0_TxFilter1, 0x1a1b0000);
+ rtl92e_writel(dev, rCCK0_TxFilter2, 0x090e1317);
+ rtl92e_writel(dev, rCCK0_DebugPort, 0x00000204);
} else {
CCK_Tx_Power_Track_BW_Switch(dev);
}
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x00100000, 1);
break;
case HT_CHANNEL_WIDTH_20_40:
- rtl8192_setBBreg(dev, rFPGA0_RFMOD, bRFMOD, 0x1);
- rtl8192_setBBreg(dev, rFPGA1_RFMOD, bRFMOD, 0x1);
+ rtl92e_set_bb_reg(dev, rFPGA0_RFMOD, bRFMOD, 0x1);
+ rtl92e_set_bb_reg(dev, rFPGA1_RFMOD, bRFMOD, 0x1);
if (!priv->btxpower_tracking) {
- write_nic_dword(dev, rCCK0_TxFilter1, 0x35360000);
- write_nic_dword(dev, rCCK0_TxFilter2, 0x121c252e);
- write_nic_dword(dev, rCCK0_DebugPort, 0x00000409);
+ rtl92e_writel(dev, rCCK0_TxFilter1, 0x35360000);
+ rtl92e_writel(dev, rCCK0_TxFilter2, 0x121c252e);
+ rtl92e_writel(dev, rCCK0_DebugPort, 0x00000409);
} else {
CCK_Tx_Power_Track_BW_Switch(dev);
}
- rtl8192_setBBreg(dev, rCCK0_System, bCCKSideBand,
- (priv->nCur40MhzPrimeSC>>1));
- rtl8192_setBBreg(dev, rOFDM1_LSTF, 0xC00,
- priv->nCur40MhzPrimeSC);
+ rtl92e_set_bb_reg(dev, rCCK0_System, bCCKSideBand,
+ (priv->nCur40MhzPrimeSC>>1));
+ rtl92e_set_bb_reg(dev, rOFDM1_LSTF, 0xC00,
+ priv->nCur40MhzPrimeSC);
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x00100000, 0);
break;
default:
netdev_err(dev, "%s(): unknown Bandwidth: %#X\n", __func__,
@@ -1249,7 +1239,7 @@
break;
case RF_8256:
- PHY_SetRF8256Bandwidth(dev, priv->CurrentChannelBW);
+ rtl92e_set_bandwidth(dev, priv->CurrentChannelBW);
break;
case RF_8258:
@@ -1270,8 +1260,8 @@
RT_TRACE(COMP_SWBW, "<==SetBWMode819xUsb()");
}
-void rtl8192_SetBWMode(struct net_device *dev, enum ht_channel_width Bandwidth,
- enum ht_extchnl_offset Offset)
+void rtl92e_set_bw_mode(struct net_device *dev, enum ht_channel_width Bandwidth,
+ enum ht_extchnl_offset Offset)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1295,7 +1285,7 @@
}
-void InitialGain819xPci(struct net_device *dev, u8 Operation)
+void rtl92e_init_gain(struct net_device *dev, u8 Operation)
{
#define SCAN_RX_INITIAL_GAIN 0x17
#define POWER_DETECTION_TH 0x08
@@ -1312,21 +1302,21 @@
BitMask = bMaskByte0;
if (dm_digtable.dig_algorithm ==
DIG_ALGO_BY_FALSE_ALARM)
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
priv->initgain_backup.xaagccore1 =
- (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1,
- BitMask);
+ (u8)rtl92e_get_bb_reg(dev, rOFDM0_XAAGCCore1,
+ BitMask);
priv->initgain_backup.xbagccore1 =
- (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1,
- BitMask);
+ (u8)rtl92e_get_bb_reg(dev, rOFDM0_XBAGCCore1,
+ BitMask);
priv->initgain_backup.xcagccore1 =
- (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1,
- BitMask);
+ (u8)rtl92e_get_bb_reg(dev, rOFDM0_XCAGCCore1,
+ BitMask);
priv->initgain_backup.xdagccore1 =
- (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1,
- BitMask);
+ (u8)rtl92e_get_bb_reg(dev, rOFDM0_XDAGCCore1,
+ BitMask);
BitMask = bMaskByte2;
- priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev,
+ priv->initgain_backup.cca = (u8)rtl92e_get_bb_reg(dev,
rCCK0_CCA, BitMask);
RT_TRACE(COMP_SCAN,
@@ -1347,13 +1337,13 @@
RT_TRACE(COMP_SCAN, "Write scan initial gain = 0x%x\n",
initial_gain);
- write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
- write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
- write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
- write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
+ rtl92e_writeb(dev, rOFDM0_XAAGCCore1, initial_gain);
+ rtl92e_writeb(dev, rOFDM0_XBAGCCore1, initial_gain);
+ rtl92e_writeb(dev, rOFDM0_XCAGCCore1, initial_gain);
+ rtl92e_writeb(dev, rOFDM0_XDAGCCore1, initial_gain);
RT_TRACE(COMP_SCAN, "Write scan 0xa0a = 0x%x\n",
POWER_DETECTION_TH);
- write_nic_byte(dev, 0xa0a, POWER_DETECTION_TH);
+ rtl92e_writeb(dev, 0xa0a, POWER_DETECTION_TH);
break;
case IG_Restore:
RT_TRACE(COMP_SCAN,
@@ -1361,18 +1351,18 @@
BitMask = 0x7f;
if (dm_digtable.dig_algorithm ==
DIG_ALGO_BY_FALSE_ALARM)
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
- rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, BitMask,
+ rtl92e_set_bb_reg(dev, rOFDM0_XAAGCCore1, BitMask,
(u32)priv->initgain_backup.xaagccore1);
- rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, BitMask,
+ rtl92e_set_bb_reg(dev, rOFDM0_XBAGCCore1, BitMask,
(u32)priv->initgain_backup.xbagccore1);
- rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, BitMask,
+ rtl92e_set_bb_reg(dev, rOFDM0_XCAGCCore1, BitMask,
(u32)priv->initgain_backup.xcagccore1);
- rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, BitMask,
+ rtl92e_set_bb_reg(dev, rOFDM0_XDAGCCore1, BitMask,
(u32)priv->initgain_backup.xdagccore1);
BitMask = bMaskByte2;
- rtl8192_setBBreg(dev, rCCK0_CCA, BitMask,
+ rtl92e_set_bb_reg(dev, rCCK0_CCA, BitMask,
(u32)priv->initgain_backup.cca);
RT_TRACE(COMP_SCAN,
@@ -1391,12 +1381,12 @@
"Scan BBInitialGainRestore 0xa0a is %x\n",
priv->initgain_backup.cca);
- rtl8192_phy_setTxPower(dev,
+ rtl92e_set_tx_power(dev,
priv->rtllib->current_network.channel);
if (dm_digtable.dig_algorithm ==
DIG_ALGO_BY_FALSE_ALARM)
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1);
break;
default:
RT_TRACE(COMP_SCAN, "Unknown IG Operation.\n");
@@ -1405,17 +1395,17 @@
}
}
-void PHY_SetRtl8192eRfOff(struct net_device *dev)
+void rtl92e_set_rf_off(struct net_device *dev)
{
- rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
- rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
- rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
- write_nic_byte(dev, ANAPAR_FOR_8192PciE, 0x07);
+ rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE, BIT4, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4, 0x300, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x18, 0x0);
+ rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable, 0xf, 0x0);
+ rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable, 0xf, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x60, 0x0);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1, 0x4, 0x0);
+ rtl92e_writeb(dev, ANAPAR_FOR_8192PciE, 0x07);
}
@@ -1447,7 +1437,7 @@
do {
InitilizeCount--;
priv->RegRfOff = false;
- rtstatus = NicIFEnableNIC(dev);
+ rtstatus = rtl92e_enable_nic(dev);
} while (!rtstatus && (InitilizeCount > 0));
if (!rtstatus) {
@@ -1461,24 +1451,24 @@
RT_CLEAR_PS_LEVEL(pPSC,
RT_RF_OFF_LEVL_HALT_NIC);
} else {
- write_nic_byte(dev, ANAPAR, 0x37);
+ rtl92e_writeb(dev, ANAPAR, 0x37);
mdelay(1);
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1,
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1,
0x4, 0x1);
priv->bHwRfOffAction = 0;
- rtl8192_setBBreg(dev, rFPGA0_XA_RFInterfaceOE,
- BIT4, 0x1);
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter4,
- 0x300, 0x3);
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1,
- 0x18, 0x3);
- rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable, 0x3,
- 0x3);
- rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable, 0x3,
- 0x3);
- rtl8192_setBBreg(dev, rFPGA0_AnalogParameter1,
- 0x60, 0x3);
+ rtl92e_set_bb_reg(dev, rFPGA0_XA_RFInterfaceOE,
+ BIT4, 0x1);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter4,
+ 0x300, 0x3);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1,
+ 0x18, 0x3);
+ rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable,
+ 0x3, 0x3);
+ rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable,
+ 0x3, 0x3);
+ rtl92e_set_bb_reg(dev, rFPGA0_AnalogParameter1,
+ 0x60, 0x3);
}
@@ -1511,7 +1501,7 @@
break;
}
}
- PHY_SetRtl8192eRfOff(dev);
+ rtl92e_set_rf_off(dev);
break;
case eRfOff:
@@ -1543,11 +1533,11 @@
if (pPSC->RegRfPsLevel & RT_RF_OFF_LEVL_HALT_NIC &&
!RT_IN_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC)) {
- NicIFDisableNIC(dev);
+ rtl92e_disable_nic(dev);
RT_SET_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
} else if (!(pPSC->RegRfPsLevel &
RT_RF_OFF_LEVL_HALT_NIC)) {
- PHY_SetRtl8192eRfOff(dev);
+ rtl92e_set_rf_off(dev);
}
break;
@@ -1586,32 +1576,34 @@
return bResult;
}
-bool SetRFPowerState(struct net_device *dev,
- enum rt_rf_power_state eRFPowerState)
+bool rtl92e_set_rf_power_state(struct net_device *dev,
+ enum rt_rf_power_state eRFPowerState)
{
struct r8192_priv *priv = rtllib_priv(dev);
bool bResult = false;
- RT_TRACE(COMP_PS, "---------> SetRFPowerState(): eRFPowerState(%d)\n",
+ RT_TRACE(COMP_PS,
+ "---------> rtl92e_set_rf_power_state(): eRFPowerState(%d)\n",
eRFPowerState);
if (eRFPowerState == priv->rtllib->eRFPowerState &&
priv->bHwRfOffAction == 0) {
RT_TRACE(COMP_PS,
- "<--------- SetRFPowerState(): discard the request for eRFPowerState(%d) is the same.\n",
+ "<--------- rtl92e_set_rf_power_state(): discard the request for eRFPowerState(%d) is the same.\n",
eRFPowerState);
return bResult;
}
bResult = SetRFPowerState8190(dev, eRFPowerState);
- RT_TRACE(COMP_PS, "<--------- SetRFPowerState(): bResult(%d)\n",
+ RT_TRACE(COMP_PS,
+ "<--------- rtl92e_set_rf_power_state(): bResult(%d)\n",
bResult);
return bResult;
}
-void PHY_ScanOperationBackup8192(struct net_device *dev, u8 Operation)
+void rtl92e_scan_op_backup(struct net_device *dev, u8 Operation)
{
struct r8192_priv *priv = rtllib_priv(dev);
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h
index 18bc582..96015d3 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_phy.h
@@ -67,48 +67,36 @@
#define bMaskLWord 0x0000ffff
#define bMaskDWord 0xffffffff
-extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev,
- u32 eRFPath);
-extern void rtl8192_setBBreg(struct net_device *dev, u32 dwRegAddr,
- u32 dwBitMask, u32 dwData);
-extern u32 rtl8192_QueryBBReg(struct net_device *dev, u32 dwRegAddr,
- u32 dwBitMask);
-extern void rtl8192_phy_SetRFReg(struct net_device *dev,
- enum rf90_radio_path eRFPath,
- u32 RegAddr, u32 BitMask, u32 Data);
-extern u32 rtl8192_phy_QueryRFReg(struct net_device *dev,
- enum rf90_radio_path eRFPath,
- u32 RegAddr, u32 BitMask);
-extern void rtl8192_phy_configmac(struct net_device *dev);
-extern void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
-extern bool rtl8192_phy_checkBBAndRF(struct net_device *dev,
- enum hw90_block CheckBlock,
- enum rf90_radio_path eRFPath);
-extern bool rtl8192_BBConfig(struct net_device *dev);
-extern void rtl8192_phy_getTxPower(struct net_device *dev);
-extern void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
-extern bool rtl8192_phy_RFConfig(struct net_device *dev);
-extern void rtl8192_phy_updateInitGain(struct net_device *dev);
-extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
- enum rf90_radio_path eRFPath);
+u8 rtl92e_is_legal_rf_path(struct net_device *dev, u32 eRFPath);
+void rtl92e_set_bb_reg(struct net_device *dev, u32 dwRegAddr,
+ u32 dwBitMask, u32 dwData);
+u32 rtl92e_get_bb_reg(struct net_device *dev, u32 dwRegAddr, u32 dwBitMask);
+void rtl92e_set_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask, u32 Data);
+u32 rtl92e_get_rf_reg(struct net_device *dev, enum rf90_radio_path eRFPath,
+ u32 RegAddr, u32 BitMask);
+void rtl92e_config_mac(struct net_device *dev);
+bool rtl92e_check_bb_and_rf(struct net_device *dev,
+ enum hw90_block CheckBlock,
+ enum rf90_radio_path eRFPath);
+bool rtl92e_config_bb(struct net_device *dev);
+void rtl92e_get_tx_power(struct net_device *dev);
+void rtl92e_set_tx_power(struct net_device *dev, u8 channel);
+bool rtl92e_config_phy(struct net_device *dev);
+u8 rtl92e_config_rf_path(struct net_device *dev, enum rf90_radio_path eRFPath);
-extern u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
-extern void rtl8192_SetBWMode(struct net_device *dev,
- enum ht_channel_width Bandwidth,
- enum ht_extchnl_offset Offset);
-extern void rtl8192_SwChnl_WorkItem(struct net_device *dev);
-extern void rtl8192_SetBWModeWorkItem(struct net_device *dev);
-extern void InitialGain819xPci(struct net_device *dev, u8 Operation);
+u8 rtl92e_set_channel(struct net_device *dev, u8 channel);
+void rtl92e_set_bw_mode(struct net_device *dev,
+ enum ht_channel_width Bandwidth,
+ enum ht_extchnl_offset Offset);
+void rtl92e_init_gain(struct net_device *dev, u8 Operation);
-extern void PHY_SetRtl8192eRfOff(struct net_device *dev);
+void rtl92e_set_rf_off(struct net_device *dev);
-bool
-SetRFPowerState(
- struct net_device *dev,
- enum rt_rf_power_state eRFPowerState
- );
-#define PHY_SetRFPowerState SetRFPowerState
+bool rtl92e_set_rf_power_state(struct net_device *dev,
+ enum rt_rf_power_state eRFPowerState);
+#define PHY_SetRFPowerState rtl92e_set_rf_power_state
-extern void PHY_ScanOperationBackup8192(struct net_device *dev, u8 Operation);
+void rtl92e_scan_op_backup(struct net_device *dev, u8 Operation);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
index f246222..29dd93a 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.c
@@ -28,15 +28,15 @@
#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
#include "r8192E_cmdpkt.h"
-void CamResetAllEntry(struct net_device *dev)
+void rtl92e_cam_reset(struct net_device *dev)
{
u32 ulcommand = 0;
ulcommand |= BIT31|BIT30;
- write_nic_dword(dev, RWCAM, ulcommand);
+ rtl92e_writel(dev, RWCAM, ulcommand);
}
-void EnableHWSecurityConfig8192(struct net_device *dev)
+void rtl92e_enable_hw_security_config(struct net_device *dev)
{
u8 SECR_value = 0x0;
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -65,11 +65,12 @@
RT_TRACE(COMP_SEC, "%s:, hwsec:%d, pairwise_key:%d, SECR_value:%x\n",
__func__, ieee->hwsec_active, ieee->pairwise_key_type,
SECR_value);
- write_nic_byte(dev, SECR, SECR_value);
+ rtl92e_writeb(dev, SECR, SECR_value);
}
-void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
- const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh)
+void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
+ u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
+ u32 *KeyContent, u8 is_mesh)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_device *ieee = priv->rtllib;
@@ -77,6 +78,10 @@
RT_TRACE(COMP_DBG,
"===========>%s():EntryNo is %d,KeyIndex is %d,KeyType is %d,is_mesh is %d\n",
__func__, EntryNo, KeyIndex, KeyType, is_mesh);
+
+ if (EntryNo >= TOTAL_CAM_ENTRY)
+ return;
+
if (!is_mesh) {
ieee->swcamtable[EntryNo].bused = true;
ieee->swcamtable[EntryNo].key_index = KeyIndex;
@@ -87,8 +92,9 @@
}
}
-void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
- const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent)
+void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
+ u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
+ u32 *KeyContent)
{
u32 TargetCommand = 0;
u32 TargetContent = 0;
@@ -106,16 +112,18 @@
return;
}
down(&priv->rtllib->ips_sem);
- IPSLeave(dev);
+ rtl92e_ips_leave(dev);
up(&priv->rtllib->ips_sem);
}
}
priv->rtllib->is_set_key = true;
- if (EntryNo >= TOTAL_CAM_ENTRY)
+ if (EntryNo >= TOTAL_CAM_ENTRY) {
netdev_info(dev, "%s(): Invalid CAM entry\n", __func__);
+ return;
+ }
RT_TRACE(COMP_SEC,
- "====>to setKey(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
+ "====>to rtl92e_set_key(), dev:%p, EntryNo:%d, KeyIndex:%d,KeyType:%d, MacAddr %pM\n",
dev, EntryNo, KeyIndex, KeyType, MacAddr);
if (DefaultKey)
@@ -133,20 +141,20 @@
(u32)(*(MacAddr+1)) << 24 |
(u32)usConfig;
- write_nic_dword(dev, WCAMI, TargetContent);
- write_nic_dword(dev, RWCAM, TargetCommand);
+ rtl92e_writel(dev, WCAMI, TargetContent);
+ rtl92e_writel(dev, RWCAM, TargetCommand);
} else if (i == 1) {
TargetContent = (u32)(*(MacAddr+2)) |
(u32)(*(MacAddr+3)) << 8 |
(u32)(*(MacAddr+4)) << 16 |
(u32)(*(MacAddr+5)) << 24;
- write_nic_dword(dev, WCAMI, TargetContent);
- write_nic_dword(dev, RWCAM, TargetCommand);
+ rtl92e_writel(dev, WCAMI, TargetContent);
+ rtl92e_writel(dev, RWCAM, TargetCommand);
} else {
if (KeyContent != NULL) {
- write_nic_dword(dev, WCAMI,
- (u32)(*(KeyContent+i-2)));
- write_nic_dword(dev, RWCAM, TargetCommand);
+ rtl92e_writel(dev, WCAMI,
+ (u32)(*(KeyContent+i-2)));
+ rtl92e_writel(dev, RWCAM, TargetCommand);
udelay(100);
}
}
@@ -154,7 +162,7 @@
RT_TRACE(COMP_SEC, "=========>after set key, usconfig:%x\n", usConfig);
}
-void CamRestoreAllEntry(struct net_device *dev)
+void rtl92e_cam_restore(struct net_device *dev)
{
u8 EntryId = 0;
struct r8192_priv *priv = rtllib_priv(dev);
@@ -170,7 +178,7 @@
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
- RT_TRACE(COMP_SEC, "CamRestoreAllEntry:\n");
+ RT_TRACE(COMP_SEC, "rtl92e_cam_restore:\n");
if ((priv->rtllib->pairwise_key_type == KEY_TYPE_WEP40) ||
@@ -179,36 +187,41 @@
for (EntryId = 0; EntryId < 4; EntryId++) {
MacAddr = CAM_CONST_ADDR[EntryId];
if (priv->rtllib->swcamtable[EntryId].bused) {
- setKey(dev, EntryId, EntryId,
- priv->rtllib->pairwise_key_type, MacAddr,
- 0, (u32 *)(&priv->rtllib->swcamtable
- [EntryId].key_buf[0]));
+ rtl92e_set_key(dev, EntryId, EntryId,
+ priv->rtllib->pairwise_key_type,
+ MacAddr, 0,
+ (u32 *)(&priv->rtllib->swcamtable
+ [EntryId].key_buf[0]));
}
}
} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_TKIP) {
if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
- setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
- (u8 *)dev->dev_addr, 0,
- (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
+ rtl92e_set_key(dev, 4, 0,
+ priv->rtllib->pairwise_key_type,
+ (u8 *)dev->dev_addr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[4].
+ key_buf[0]));
} else {
- setKey(dev, 4, 0, priv->rtllib->pairwise_key_type,
- MacAddr, 0,
- (u32 *)(&priv->rtllib->swcamtable[4].key_buf[0]));
+ rtl92e_set_key(dev, 4, 0,
+ priv->rtllib->pairwise_key_type,
+ MacAddr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[4].
+ key_buf[0]));
}
} else if (priv->rtllib->pairwise_key_type == KEY_TYPE_CCMP) {
if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
- setKey(dev, 4, 0,
- priv->rtllib->pairwise_key_type,
- (u8 *)dev->dev_addr, 0,
- (u32 *)(&priv->rtllib->swcamtable[4].
- key_buf[0]));
+ rtl92e_set_key(dev, 4, 0,
+ priv->rtllib->pairwise_key_type,
+ (u8 *)dev->dev_addr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[4].
+ key_buf[0]));
} else {
- setKey(dev, 4, 0,
- priv->rtllib->pairwise_key_type, MacAddr,
- 0, (u32 *)(&priv->rtllib->swcamtable[4].
- key_buf[0]));
+ rtl92e_set_key(dev, 4, 0,
+ priv->rtllib->pairwise_key_type, MacAddr,
+ 0, (u32 *)(&priv->rtllib->swcamtable[4].
+ key_buf[0]));
}
}
@@ -216,20 +229,18 @@
MacAddr = CAM_CONST_BROAD;
for (EntryId = 1; EntryId < 4; EntryId++) {
if (priv->rtllib->swcamtable[EntryId].bused) {
- setKey(dev, EntryId, EntryId,
- priv->rtllib->group_key_type,
- MacAddr, 0,
- (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0])
- );
+ rtl92e_set_key(dev, EntryId, EntryId,
+ priv->rtllib->group_key_type,
+ MacAddr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
}
}
if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
if (priv->rtllib->swcamtable[0].bused) {
- setKey(dev, 0, 0,
- priv->rtllib->group_key_type,
- CAM_CONST_ADDR[0], 0,
- (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0])
- );
+ rtl92e_set_key(dev, 0, 0,
+ priv->rtllib->group_key_type,
+ CAM_CONST_ADDR[0], 0,
+ (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
} else {
netdev_warn(dev,
"%s(): ADHOC TKIP: missing key entry.\n",
@@ -241,19 +252,19 @@
MacAddr = CAM_CONST_BROAD;
for (EntryId = 1; EntryId < 4; EntryId++) {
if (priv->rtllib->swcamtable[EntryId].bused) {
- setKey(dev, EntryId, EntryId,
- priv->rtllib->group_key_type,
- MacAddr, 0,
- (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
+ rtl92e_set_key(dev, EntryId, EntryId,
+ priv->rtllib->group_key_type,
+ MacAddr, 0,
+ (u32 *)(&priv->rtllib->swcamtable[EntryId].key_buf[0]));
}
}
if (priv->rtllib->iw_mode == IW_MODE_ADHOC) {
if (priv->rtllib->swcamtable[0].bused) {
- setKey(dev, 0, 0,
- priv->rtllib->group_key_type,
- CAM_CONST_ADDR[0], 0,
- (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
+ rtl92e_set_key(dev, 0, 0,
+ priv->rtllib->group_key_type,
+ CAM_CONST_ADDR[0], 0,
+ (u32 *)(&priv->rtllib->swcamtable[0].key_buf[0]));
} else {
netdev_warn(dev,
"%s(): ADHOC CCMP: missing key entry.\n",
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h
index f23ab46..9ef8b36 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_cam.h
@@ -28,12 +28,14 @@
#include <linux/types.h>
struct net_device;
-void CamResetAllEntry(struct net_device *dev);
-void EnableHWSecurityConfig8192(struct net_device *dev);
-void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
- const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent);
-void set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType,
- const u8 *MacAddr, u8 DefaultKey, u32 *KeyContent, u8 is_mesh);
-void CamRestoreAllEntry(struct net_device *dev);
+void rtl92e_cam_reset(struct net_device *dev);
+void rtl92e_enable_hw_security_config(struct net_device *dev);
+void rtl92e_set_key(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
+ u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
+ u32 *KeyContent);
+void rtl92e_set_swcam(struct net_device *dev, u8 EntryNo, u8 KeyIndex,
+ u16 KeyType, const u8 *MacAddr, u8 DefaultKey,
+ u32 *KeyContent, u8 is_mesh);
+void rtl92e_cam_restore(struct net_device *dev);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index c6cdb43..d6b46df 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -22,25 +22,6 @@
* Contact Information:
* wlanfae <wlanfae@realtek.com>
******************************************************************************/
-#undef RX_DONT_PASS_UL
-#undef DEBUG_EPROM
-#undef DEBUG_RX_VERBOSE
-#undef DUMMY_RX
-#undef DEBUG_ZERO_RX
-#undef DEBUG_RX_SKB
-#undef DEBUG_TX_FRAG
-#undef DEBUG_RX_FRAG
-#undef DEBUG_TX_FILLDESC
-#undef DEBUG_TX
-#undef DEBUG_IRQ
-#undef DEBUG_RX
-#undef DEBUG_RXALLOC
-#undef DEBUG_REGISTERS
-#undef DEBUG_RING
-#undef DEBUG_IRQ_TASKLET
-#undef DEBUG_TX_ALLOC
-#undef DEBUG_TX_DESC
-
#include <linux/uaccess.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
@@ -63,24 +44,24 @@
static struct rtl819x_ops rtl819xp_ops = {
.nic_type = NIC_8192E,
- .get_eeprom_size = rtl8192_get_eeprom_size,
- .init_adapter_variable = rtl8192_InitializeVariables,
- .initialize_adapter = rtl8192_adapter_start,
- .link_change = rtl8192_link_change,
- .tx_fill_descriptor = rtl8192_tx_fill_desc,
- .tx_fill_cmd_descriptor = rtl8192_tx_fill_cmd_desc,
- .rx_query_status_descriptor = rtl8192_rx_query_status_desc,
+ .get_eeprom_size = rtl92e_get_eeprom_size,
+ .init_adapter_variable = rtl92e_init_variables,
+ .initialize_adapter = rtl92e_start_adapter,
+ .link_change = rtl92e_link_change,
+ .tx_fill_descriptor = rtl92e_fill_tx_desc,
+ .tx_fill_cmd_descriptor = rtl92e_fill_tx_cmd_desc,
+ .rx_query_status_descriptor = rtl92e_get_rx_stats,
.rx_command_packet_handler = NULL,
- .stop_adapter = rtl8192_halt_adapter,
- .update_ratr_table = rtl8192_update_ratr_table,
- .irq_enable = rtl8192_EnableInterrupt,
- .irq_disable = rtl8192_DisableInterrupt,
- .irq_clear = rtl8192_ClearInterrupt,
- .rx_enable = rtl8192_enable_rx,
- .tx_enable = rtl8192_enable_tx,
- .interrupt_recognized = rtl8192_interrupt_recognized,
- .TxCheckStuckHandler = rtl8192_HalTxCheckStuck,
- .RxCheckStuckHandler = rtl8192_HalRxCheckStuck,
+ .stop_adapter = rtl92e_stop_adapter,
+ .update_ratr_table = rtl92e_update_ratr_table,
+ .irq_enable = rtl92e_enable_irq,
+ .irq_disable = rtl92e_disable_irq,
+ .irq_clear = rtl92e_clear_irq,
+ .rx_enable = rtl92e_enable_rx,
+ .tx_enable = rtl92e_enable_tx,
+ .interrupt_recognized = rtl92e_ack_irq,
+ .TxCheckStuckHandler = rtl92e_is_tx_stuck,
+ .RxCheckStuckHandler = rtl92e_is_rx_stuck,
};
static struct pci_device_id rtl8192_pci_id_tbl[] = {
@@ -102,202 +83,61 @@
.id_table = rtl8192_pci_id_tbl, /* PCI_ID table */
.probe = rtl8192_pci_probe, /* probe fn */
.remove = rtl8192_pci_disconnect, /* remove fn */
- .suspend = rtl8192E_suspend, /* PM suspend fn */
- .resume = rtl8192E_resume, /* PM resume fn */
+ .suspend = rtl92e_suspend, /* PM suspend fn */
+ .resume = rtl92e_resume, /* PM resume fn */
};
+static short rtl8192_is_tx_queue_empty(struct net_device *dev);
+static void rtl819x_watchdog_wqcallback(void *data);
+static void watch_dog_timer_callback(unsigned long data);
+static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
+ int rate);
+static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb);
+static short rtl8192_tx(struct net_device *dev, struct sk_buff *skb);
+static short rtl8192_pci_initdescring(struct net_device *dev);
+static void rtl8192_irq_tx_tasklet(struct r8192_priv *priv);
+static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
+static void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
+static int _rtl8192_up(struct net_device *dev, bool is_silent_reset);
+static int rtl8192_up(struct net_device *dev);
+static int rtl8192_down(struct net_device *dev, bool shutdownrf);
+static void rtl8192_restart(void *data);
+
/****************************************************************************
-----------------------------IO STUFF-------------------------
*****************************************************************************/
-static bool PlatformIOCheckPageLegalAndGetRegMask(u32 u4bPage, u8 *pu1bPageMask)
-{
- bool bReturn = false;
- *pu1bPageMask = 0xfe;
-
- switch (u4bPage) {
- case 1: case 2: case 3: case 4:
- case 8: case 9: case 10: case 12: case 13:
- bReturn = true;
- *pu1bPageMask = 0xf0;
- break;
-
- default:
- bReturn = false;
- break;
- }
-
- return bReturn;
-}
-
-void write_nic_io_byte(struct net_device *dev, int x, u8 y)
-{
- u32 u4bPage = x >> 8;
- u8 u1PageMask = 0;
- bool bIsLegalPage = false;
-
- if (u4bPage == 0) {
- outb(y&0xff, dev->base_addr + x);
-
- } else {
- bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
- &u1PageMask);
- if (bIsLegalPage) {
- u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
- write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
- (u8)u4bPage));
- write_nic_io_byte(dev, (x & 0xff), y);
- write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
- }
- }
-}
-
-void write_nic_io_word(struct net_device *dev, int x, u16 y)
-{
- u32 u4bPage = x >> 8;
- u8 u1PageMask = 0;
- bool bIsLegalPage = false;
-
- if (u4bPage == 0) {
- outw(y, dev->base_addr + x);
- } else {
- bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
- &u1PageMask);
- if (bIsLegalPage) {
- u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
- write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
- (u8)u4bPage));
- write_nic_io_word(dev, (x & 0xff), y);
- write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
-
- }
- }
-}
-
-void write_nic_io_dword(struct net_device *dev, int x, u32 y)
-{
- u32 u4bPage = x >> 8;
- u8 u1PageMask = 0;
- bool bIsLegalPage = false;
-
- if (u4bPage == 0) {
- outl(y, dev->base_addr + x);
- } else {
- bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
- &u1PageMask);
- if (bIsLegalPage) {
- u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
- write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
- (u8)u4bPage));
- write_nic_io_dword(dev, (x & 0xff), y);
- write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
- }
- }
-}
-
-u8 read_nic_io_byte(struct net_device *dev, int x)
-{
- u32 u4bPage = x >> 8;
- u8 u1PageMask = 0;
- bool bIsLegalPage = false;
- u8 Data = 0;
-
- if (u4bPage == 0)
- return 0xff&inb(dev->base_addr + x);
-
- bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
- &u1PageMask);
- if (bIsLegalPage) {
- u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
- write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
- (u8)u4bPage));
- Data = read_nic_io_byte(dev, (x & 0xff));
- write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
- }
-
- return Data;
-}
-
-u16 read_nic_io_word(struct net_device *dev, int x)
-{
- u32 u4bPage = x >> 8;
- u8 u1PageMask = 0;
- bool bIsLegalPage = false;
- u16 Data = 0;
-
- if (u4bPage == 0)
- return inw(dev->base_addr + x);
- bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
- &u1PageMask);
- if (bIsLegalPage) {
- u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
- write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
- (u8)u4bPage));
- Data = read_nic_io_word(dev, (x & 0xff));
- write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
- }
-
- return Data;
-}
-
-u32 read_nic_io_dword(struct net_device *dev, int x)
-{
- u32 u4bPage = x >> 8;
- u8 u1PageMask = 0;
- bool bIsLegalPage = false;
- u32 Data = 0;
-
- if (u4bPage == 0)
- return inl(dev->base_addr + x);
- bIsLegalPage = PlatformIOCheckPageLegalAndGetRegMask(u4bPage,
- &u1PageMask);
- if (bIsLegalPage) {
- u8 u1bPsr = read_nic_io_byte(dev, PSR);
-
- write_nic_io_byte(dev, PSR, ((u1bPsr & u1PageMask) |
- (u8)u4bPage));
- Data = read_nic_io_dword(dev, (x & 0xff));
- write_nic_io_byte(dev, PSR, (u1bPsr & u1PageMask));
- }
-
- return Data;
-}
-
-u8 read_nic_byte(struct net_device *dev, int x)
+u8 rtl92e_readb(struct net_device *dev, int x)
{
return 0xff & readb((u8 __iomem *)dev->mem_start + x);
}
-u32 read_nic_dword(struct net_device *dev, int x)
+u32 rtl92e_readl(struct net_device *dev, int x)
{
return readl((u8 __iomem *)dev->mem_start + x);
}
-u16 read_nic_word(struct net_device *dev, int x)
+u16 rtl92e_readw(struct net_device *dev, int x)
{
return readw((u8 __iomem *)dev->mem_start + x);
}
-void write_nic_byte(struct net_device *dev, int x, u8 y)
+void rtl92e_writeb(struct net_device *dev, int x, u8 y)
{
writeb(y, (u8 __iomem *)dev->mem_start + x);
udelay(20);
}
-void write_nic_dword(struct net_device *dev, int x, u32 y)
+void rtl92e_writel(struct net_device *dev, int x, u32 y)
{
writel(y, (u8 __iomem *)dev->mem_start + x);
udelay(20);
}
-void write_nic_word(struct net_device *dev, int x, u16 y)
+void rtl92e_writew(struct net_device *dev, int x, u16 y)
{
writew(y, (u8 __iomem *)dev->mem_start + x);
@@ -307,10 +147,9 @@
/****************************************************************************
-----------------------------GENERAL FUNCTION-------------------------
*****************************************************************************/
-bool MgntActSet_RF_State(struct net_device *dev,
+bool rtl92e_set_rf_state(struct net_device *dev,
enum rt_rf_power_state StateToSet,
- RT_RF_CHANGE_SOURCE ChangeSource,
- bool ProtectOrNot)
+ RT_RF_CHANGE_SOURCE ChangeSource)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_device *ieee = priv->rtllib;
@@ -321,39 +160,34 @@
unsigned long flag;
RT_TRACE((COMP_PS | COMP_RF),
- "===>MgntActSet_RF_State(): StateToSet(%d)\n", StateToSet);
+ "===>rtl92e_set_rf_state(): StateToSet(%d)\n", StateToSet);
- ProtectOrNot = false;
+ while (true) {
+ spin_lock_irqsave(&priv->rf_ps_lock, flag);
+ if (priv->RFChangeInProgress) {
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+ RT_TRACE((COMP_PS | COMP_RF),
+ "rtl92e_set_rf_state(): RF Change in progress! Wait to set..StateToSet(%d).\n",
+ StateToSet);
-
- if (!ProtectOrNot) {
- while (true) {
- spin_lock_irqsave(&priv->rf_ps_lock, flag);
- if (priv->RFChangeInProgress) {
- spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+ while (priv->RFChangeInProgress) {
+ RFWaitCounter++;
RT_TRACE((COMP_PS | COMP_RF),
- "MgntActSet_RF_State(): RF Change in progress! Wait to set..StateToSet(%d).\n",
- StateToSet);
+ "rtl92e_set_rf_state(): Wait 1 ms (%d times)...\n",
+ RFWaitCounter);
+ mdelay(1);
- while (priv->RFChangeInProgress) {
- RFWaitCounter++;
- RT_TRACE((COMP_PS | COMP_RF),
- "MgntActSet_RF_State(): Wait 1 ms (%d times)...\n",
- RFWaitCounter);
- mdelay(1);
-
- if (RFWaitCounter > 100) {
- netdev_warn(dev,
- "%s(): Timeout waiting for RF change.\n",
- __func__);
- return false;
- }
+ if (RFWaitCounter > 100) {
+ netdev_warn(dev,
+ "%s(): Timeout waiting for RF change.\n",
+ __func__);
+ return false;
}
- } else {
- priv->RFChangeInProgress = true;
- spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
- break;
}
+ } else {
+ priv->RFChangeInProgress = true;
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
+ break;
}
}
@@ -376,7 +210,7 @@
bConnectBySSID = true;
} else {
RT_TRACE((COMP_PS | COMP_RF),
- "MgntActSet_RF_State - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n",
+ "rtl92e_set_rf_state - eRfon reject pMgntInfo->RfOffReason= 0x%x, ChangeSource=0x%X\n",
priv->rtllib->RfOffReason, ChangeSource);
}
@@ -413,7 +247,7 @@
if (bActionAllowed) {
RT_TRACE((COMP_PS | COMP_RF),
- "MgntActSet_RF_State(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n",
+ "rtl92e_set_rf_state(): Action is allowed.... StateToSet(%d), RfOffReason(%#X)\n",
StateToSet, priv->rtllib->RfOffReason);
PHY_SetRFPowerState(dev, StateToSet);
if (StateToSet == eRfOn) {
@@ -426,17 +260,15 @@
}
} else {
RT_TRACE((COMP_PS | COMP_RF),
- "MgntActSet_RF_State(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n",
+ "rtl92e_set_rf_state(): Action is rejected.... StateToSet(%d), ChangeSource(%#X), RfOffReason(%#X)\n",
StateToSet, ChangeSource, priv->rtllib->RfOffReason);
}
- if (!ProtectOrNot) {
- spin_lock_irqsave(&priv->rf_ps_lock, flag);
- priv->RFChangeInProgress = false;
- spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
- }
+ spin_lock_irqsave(&priv->rf_ps_lock, flag);
+ priv->RFChangeInProgress = false;
+ spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
- RT_TRACE((COMP_PS | COMP_RF), "<===MgntActSet_RF_State()\n");
+ RT_TRACE((COMP_PS | COMP_RF), "<===rtl92e_set_rf_state()\n");
return bActionAllowed;
}
@@ -450,7 +282,7 @@
return 0;
}
-void rtl8192_tx_timeout(struct net_device *dev)
+static void rtl8192_tx_timeout(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -458,7 +290,7 @@
netdev_info(dev, "TXTIMEOUT");
}
-void rtl8192_irq_enable(struct net_device *dev)
+void rtl92e_irq_enable(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -467,7 +299,7 @@
priv->ops->irq_enable(dev);
}
-void rtl8192_irq_disable(struct net_device *dev)
+void rtl92e_irq_disable(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -476,7 +308,7 @@
priv->irq_enabled = 0;
}
-void rtl8192_set_chan(struct net_device *dev, short ch)
+static void rtl8192_set_chan(struct net_device *dev, short ch)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -490,7 +322,7 @@
priv->rf_set_chan(dev, priv->chan);
}
-void rtl8192_update_cap(struct net_device *dev, u16 cap)
+static void rtl8192_update_cap(struct net_device *dev, u16 cap)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_network *net = &priv->rtllib->current_network;
@@ -683,7 +515,7 @@
RT_TRACE(COMP_QOS, "%s: network->flags = %d,%d\n", __func__,
network->flags, priv->rtllib->current_network.qos_data.active);
if (set_qos_param == 1) {
- dm_init_edca_turbo(priv->rtllib->dev);
+ rtl92e_dm_init_edca_turbo(priv->rtllib->dev);
queue_work_rsl(priv->priv_wq, &priv->qos_activate);
}
return 0;
@@ -733,7 +565,7 @@
{
}
-void rtl8192_config_rate(struct net_device *dev, u16 *rate_config)
+void rtl92e_config_rate(struct net_device *dev, u16 *rate_config)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_network *net;
@@ -864,7 +696,7 @@
return ret;
}
-void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode)
+void rtl92e_set_wireless_mode(struct net_device *dev, u8 wireless_mode)
{
struct r8192_priv *priv = rtllib_priv(dev);
u8 bSupportMode = rtl8192_getSupportedWireleeMode(dev);
@@ -895,9 +727,6 @@
priv->rtllib->mode = wireless_mode;
- ActUpdateChannelAccessSetting(dev, wireless_mode,
- &priv->ChannelAccessSetting);
-
if ((wireless_mode == WIRELESS_MODE_N_24G) ||
(wireless_mode == WIRELESS_MODE_N_5G)) {
priv->rtllib->pHTInfo->bEnableHT = 1;
@@ -941,7 +770,7 @@
priv->bfirst_init = false;
if (priv->polling_timer_on == 0)
- check_rfctrl_gpio_timer((unsigned long)dev);
+ rtl92e_check_rfctrl_gpio_timer((unsigned long)dev);
if (priv->rtllib->state != RTLLIB_LINKED)
rtllib_softmac_start_protocol(priv->rtllib, 0);
@@ -969,7 +798,7 @@
priv->rtllib->rtllib_ips_leave(dev);
if (priv->rtllib->state == RTLLIB_LINKED)
- LeisurePSLeave(dev);
+ rtl92e_leisure_ps_leave(dev);
priv->bDriverIsGoingToUnload = true;
priv->up = 0;
@@ -982,9 +811,9 @@
priv->rtllib->wpa_ie_len = 0;
kfree(priv->rtllib->wpa_ie);
priv->rtllib->wpa_ie = NULL;
- CamResetAllEntry(dev);
+ rtl92e_cam_reset(dev);
memset(priv->rtllib->swcamtable, 0, sizeof(struct sw_cam_table) * 32);
- rtl8192_irq_disable(dev);
+ rtl92e_irq_disable(dev);
del_timer_sync(&priv->watch_dog_timer);
rtl8192_cancel_deferred_work(priv);
@@ -1027,38 +856,36 @@
priv->rtllib->set_chan = rtl8192_set_chan;
priv->rtllib->link_change = priv->ops->link_change;
priv->rtllib->softmac_data_hard_start_xmit = rtl8192_hard_data_xmit;
- priv->rtllib->data_hard_stop = rtl8192_data_hard_stop;
- priv->rtllib->data_hard_resume = rtl8192_data_hard_resume;
priv->rtllib->check_nic_enough_desc = rtl8192_check_nic_enough_desc;
priv->rtllib->handle_assoc_response = rtl8192_handle_assoc_response;
priv->rtllib->handle_beacon = rtl8192_handle_beacon;
- priv->rtllib->SetWirelessMode = rtl8192_SetWirelessMode;
- priv->rtllib->LeisurePSLeave = LeisurePSLeave;
- priv->rtllib->SetBWModeHandler = rtl8192_SetBWMode;
- priv->rf_set_chan = rtl8192_phy_SwChnl;
+ priv->rtllib->SetWirelessMode = rtl92e_set_wireless_mode;
+ priv->rtllib->LeisurePSLeave = rtl92e_leisure_ps_leave;
+ priv->rtllib->SetBWModeHandler = rtl92e_set_bw_mode;
+ priv->rf_set_chan = rtl92e_set_channel;
- priv->rtllib->start_send_beacons = rtl8192e_start_beacon;
+ priv->rtllib->start_send_beacons = rtl92e_start_beacon;
priv->rtllib->stop_send_beacons = rtl8192_stop_beacon;
- priv->rtllib->sta_wake_up = rtl8192_hw_wakeup;
- priv->rtllib->enter_sleep_state = rtl8192_hw_to_sleep;
+ priv->rtllib->sta_wake_up = rtl92e_hw_wakeup;
+ priv->rtllib->enter_sleep_state = rtl92e_enter_sleep;
priv->rtllib->ps_is_queue_empty = rtl8192_is_tx_queue_empty;
- priv->rtllib->GetNmodeSupportBySecCfg = rtl8192_GetNmodeSupportBySecCfg;
+ priv->rtllib->GetNmodeSupportBySecCfg = rtl92e_get_nmode_support_by_sec;
priv->rtllib->GetHalfNmodeSupportByAPsHandler =
- rtl8192_GetHalfNmodeSupportByAPs;
+ rtl92e_is_halfn_supported_by_ap;
- priv->rtllib->SetHwRegHandler = rtl8192e_SetHwReg;
- priv->rtllib->AllowAllDestAddrHandler = rtl8192_AllowAllDestAddr;
+ priv->rtllib->SetHwRegHandler = rtl92e_set_reg;
+ priv->rtllib->AllowAllDestAddrHandler = rtl92e_set_monitor_mode;
priv->rtllib->SetFwCmdHandler = NULL;
- priv->rtllib->InitialGainHandler = InitialGain819xPci;
- priv->rtllib->rtllib_ips_leave_wq = rtllib_ips_leave_wq;
- priv->rtllib->rtllib_ips_leave = rtllib_ips_leave;
+ priv->rtllib->InitialGainHandler = rtl92e_init_gain;
+ priv->rtllib->rtllib_ips_leave_wq = rtl92e_rtllib_ips_leave_wq;
+ priv->rtllib->rtllib_ips_leave = rtl92e_rtllib_ips_leave;
priv->rtllib->LedControlHandler = NULL;
priv->rtllib->UpdateBeaconInterruptHandler = NULL;
- priv->rtllib->ScanOperationBackupHandler = PHY_ScanOperationBackup8192;
+ priv->rtllib->ScanOperationBackupHandler = rtl92e_scan_op_backup;
}
static void rtl8192_init_priv_constant(struct net_device *dev)
@@ -1181,20 +1008,21 @@
priv->priv_wq = create_workqueue(DRV_NAME);
INIT_WORK_RSL(&priv->reset_wq, (void *)rtl8192_restart, dev);
- INIT_WORK_RSL(&priv->rtllib->ips_leave_wq, (void *)IPSLeave_wq, dev);
+ INIT_WORK_RSL(&priv->rtllib->ips_leave_wq, (void *)rtl92e_ips_leave_wq,
+ dev);
INIT_DELAYED_WORK_RSL(&priv->watch_dog_wq,
(void *)rtl819x_watchdog_wqcallback, dev);
INIT_DELAYED_WORK_RSL(&priv->txpower_tracking_wq,
- (void *)dm_txpower_trackingcallback, dev);
+ (void *)rtl92e_dm_txpower_tracking_wq, dev);
INIT_DELAYED_WORK_RSL(&priv->rfpath_check_wq,
- (void *)dm_rf_pathcheck_workitemcallback, dev);
+ (void *)rtl92e_dm_rf_pathcheck_wq, dev);
INIT_DELAYED_WORK_RSL(&priv->update_beacon_wq,
(void *)rtl8192_update_beacon, dev);
INIT_WORK_RSL(&priv->qos_activate, (void *)rtl8192_qos_activate, dev);
INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_wakeup_wq,
- (void *) rtl8192_hw_wakeup_wq, dev);
+ (void *) rtl92e_hw_wakeup_wq, dev);
INIT_DELAYED_WORK_RSL(&priv->rtllib->hw_sleep_wq,
- (void *) rtl8192_hw_sleep_wq, dev);
+ (void *) rtl92e_hw_sleep_wq, dev);
tasklet_init(&priv->irq_rx_tasklet,
(void(*)(unsigned long))rtl8192_irq_rx_tasklet,
(unsigned long)priv);
@@ -1250,17 +1078,17 @@
priv->ops->init_adapter_variable(dev);
rtl8192_get_channel_map(dev);
- init_hal_dm(dev);
+ rtl92e_dm_init(dev);
setup_timer(&priv->watch_dog_timer,
watch_dog_timer_callback,
(unsigned long) dev);
setup_timer(&priv->gpio_polling_timer,
- check_rfctrl_gpio_timer,
+ rtl92e_check_rfctrl_gpio_timer,
(unsigned long)dev);
- rtl8192_irq_disable(dev);
+ rtl92e_irq_disable(dev);
if (request_irq(dev->irq, rtl8192_interrupt, IRQF_SHARED,
dev->name, dev)) {
netdev_err(dev, "Error allocating IRQ %d", dev->irq);
@@ -1282,7 +1110,7 @@
/***************************************************************************
-------------------------------WATCHDOG STUFF---------------------------
***************************************************************************/
-short rtl8192_is_tx_queue_empty(struct net_device *dev)
+static short rtl8192_is_tx_queue_empty(struct net_device *dev)
{
int i = 0;
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1439,7 +1267,7 @@
down(&priv->wx_sem);
if (priv->rtllib->state == RTLLIB_LINKED)
- LeisurePSLeave(dev);
+ rtl92e_leisure_ps_leave(dev);
if (priv->up) {
netdev_info(dev, "%s():the driver is not up.\n",
@@ -1459,10 +1287,10 @@
if (!netif_queue_stopped(dev))
netif_stop_queue(dev);
- rtl8192_irq_disable(dev);
+ rtl92e_irq_disable(dev);
del_timer_sync(&priv->watch_dog_timer);
rtl8192_cancel_deferred_work(priv);
- deinit_hal_dm(dev);
+ rtl92e_dm_deinit(dev);
rtllib_stop_scan_syncro(ieee);
if (ieee->state == RTLLIB_LINKED) {
@@ -1479,7 +1307,7 @@
rtllib_softmac_stop_protocol(priv->rtllib, 0, true);
}
- dm_backup_dynamic_mechanism_state(dev);
+ rtl92e_dm_backup_state(dev);
up(&priv->wx_sem);
RT_TRACE(COMP_RESET,
@@ -1508,7 +1336,7 @@
priv->RFChangeInProgress = false;
spin_unlock_irqrestore(&priv->rf_ps_lock, flag);
- EnableHWSecurityConfig8192(dev);
+ rtl92e_enable_hw_security_config(dev);
if (ieee->state == RTLLIB_LINKED && ieee->iw_mode ==
IW_MODE_INFRA) {
@@ -1527,15 +1355,13 @@
rtllib_start_send_beacons(ieee);
- if (ieee->data_hard_resume)
- ieee->data_hard_resume(ieee->dev);
netif_carrier_on(ieee->dev);
} else if (ieee->iw_mode == IW_MODE_MESH) {
rtl819x_silentreset_mesh_bk(dev, IsPortal);
}
- CamRestoreAllEntry(dev);
- dm_restore_dynamic_mechanism_state(dev);
+ rtl92e_cam_restore(dev);
+ rtl92e_dm_restore_state(dev);
END:
priv->ResetProgress = RESET_TYPE_NORESET;
priv->reset_count++;
@@ -1543,7 +1369,7 @@
priv->bForcedSilentReset = false;
priv->bResetInProgress = false;
- write_nic_byte(dev, UFWP, 1);
+ rtl92e_writeb(dev, UFWP, 1);
RT_TRACE(COMP_RESET, "Reset finished!! ====>[%d]\n",
priv->reset_count);
}
@@ -1570,8 +1396,7 @@
}
}
-
-void rtl819x_watchdog_wqcallback(void *data)
+static void rtl819x_watchdog_wqcallback(void *data)
{
struct r8192_priv *priv = container_of_dwork_rsl(data,
struct r8192_priv, watch_dog_wq);
@@ -1597,7 +1422,7 @@
priv->rtllib->CntAfterLink = 0;
}
- hal_dm_watchdog(dev);
+ rtl92e_dm_watchdog(dev);
if (rtllib_act_scanning(priv->rtllib, false) == false) {
if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state ==
@@ -1608,8 +1433,8 @@
IPS_CALLBACK_NONE) &&
(!ieee->bNetPromiscuousMode)) {
RT_TRACE(COMP_PS,
- "====================>haha: IPSEnter()\n");
- IPSEnter(dev);
+ "====================>haha: rtl92e_ips_enter()\n");
+ rtl92e_ips_enter(dev);
}
}
}
@@ -1640,13 +1465,13 @@
bEnterPS = false;
if (bEnterPS)
- LeisurePSEnter(dev);
+ rtl92e_leisure_ps_enter(dev);
else
- LeisurePSLeave(dev);
+ rtl92e_leisure_ps_leave(dev);
} else {
RT_TRACE(COMP_LPS, "====>no link LPS leave\n");
- LeisurePSLeave(dev);
+ rtl92e_leisure_ps_leave(dev);
}
ieee->LinkDetectInfo.NumRxOkInPeriod = 0;
@@ -1725,7 +1550,7 @@
RT_TRACE(COMP_TRACE, " <==RtUsbCheckForHangWorkItemCallback()\n");
}
-void watch_dog_timer_callback(unsigned long data)
+static void watch_dog_timer_callback(unsigned long data)
{
struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
@@ -1737,14 +1562,14 @@
/****************************************************************************
---------------------------- NIC TX/RX STUFF---------------------------
*****************************************************************************/
-void rtl8192_rx_enable(struct net_device *dev)
+void rtl92e_rx_enable(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
priv->ops->rx_enable(dev);
}
-void rtl8192_tx_enable(struct net_device *dev)
+void rtl92e_tx_enable(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -1802,16 +1627,7 @@
ring->desc = NULL;
}
-void rtl8192_data_hard_stop(struct net_device *dev)
-{
-}
-
-
-void rtl8192_data_hard_resume(struct net_device *dev)
-{
-}
-
-void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
+static void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
int rate)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -1826,8 +1642,8 @@
return;
}
- if (queue_index != TXCMD_QUEUE)
- netdev_warn(dev, "%s(): queue index != TXCMD_QUEUE\n",
+ if (queue_index == TXCMD_QUEUE)
+ netdev_warn(dev, "%s(): queue index == TXCMD_QUEUE\n",
__func__);
memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
@@ -1843,7 +1659,7 @@
}
}
-int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
int ret;
@@ -1902,7 +1718,7 @@
tasklet_schedule(&priv->irq_tx_tasklet);
}
-void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb)
+static void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rtl8192_tx_ring *ring;
@@ -1925,7 +1741,7 @@
spin_unlock_irqrestore(&priv->irq_th_lock, flags);
}
-short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
+static short rtl8192_tx(struct net_device *dev, struct sk_buff *skb)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rtl8192_tx_ring *ring;
@@ -1997,7 +1813,7 @@
spin_unlock_irqrestore(&priv->irq_th_lock, flags);
dev->trans_start = jiffies;
- write_nic_word(dev, TPPoll, 0x01 << tcb_desc->queue_index);
+ rtl92e_writew(dev, TPPoll, 0x01 << tcb_desc->queue_index);
return 0;
}
@@ -2077,8 +1893,7 @@
return 0;
}
-
-short rtl8192_pci_initdescring(struct net_device *dev)
+static short rtl8192_pci_initdescring(struct net_device *dev)
{
u32 ret;
int i;
@@ -2104,7 +1919,7 @@
return 1;
}
-void rtl8192_pci_resetdescring(struct net_device *dev)
+void rtl92e_reset_desc_ring(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
int i, rx_queue_idx;
@@ -2144,8 +1959,8 @@
spin_unlock_irqrestore(&priv->irq_th_lock, flags);
}
-void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev,
- struct rtllib_rx_stats *stats)
+void rtl92e_update_rx_pkt_timestamp(struct net_device *dev,
+ struct rtllib_rx_stats *stats)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -2155,7 +1970,7 @@
priv->LastRxDescTSF = stats->mac_time;
}
-long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index)
+long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index)
{
long signal_power;
@@ -2166,11 +1981,8 @@
}
-void
-rtl819x_update_rxsignalstatistics8190pci(
- struct r8192_priv *priv,
- struct rtllib_rx_stats *pprevious_stats
- )
+void rtl92e_update_rx_statistics(struct r8192_priv *priv,
+ struct rtllib_rx_stats *pprevious_stats)
{
int weighting = 0;
@@ -2189,13 +2001,7 @@
weighting) / 6;
}
-void rtl819x_process_cck_rxpathsel(struct r8192_priv *priv,
- struct rtllib_rx_stats *pprevious_stats)
-{
-}
-
-
-u8 rtl819x_query_rxpwrpercentage(char antpower)
+u8 rtl92e_rx_db_to_percent(char antpower)
{
if ((antpower <= -100) || (antpower >= 20))
return 0;
@@ -2206,10 +2012,7 @@
} /* QueryRxPwrPercentage */
-u8
-rtl819x_evm_dbtopercentage(
- char value
- )
+u8 rtl92e_evm_db_to_percent(char value)
{
char ret_val;
@@ -2226,11 +2029,8 @@
return ret_val;
}
-void
-rtl8192_record_rxdesc_forlateruse(
- struct rtllib_rx_stats *psrc_stats,
- struct rtllib_rx_stats *ptarget_stats
-)
+void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats,
+ struct rtllib_rx_stats *ptarget_stats)
{
ptarget_stats->bIsAMPDU = psrc_stats->bIsAMPDU;
ptarget_stats->bFirstMPDU = psrc_stats->bFirstMPDU;
@@ -2344,11 +2144,6 @@
}
-static void rtl8192_rx_cmd(struct net_device *dev)
-{
-}
-
-
static void rtl8192_tx_resume(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
@@ -2366,26 +2161,23 @@
}
}
-void rtl8192_irq_tx_tasklet(struct r8192_priv *priv)
+static void rtl8192_irq_tx_tasklet(struct r8192_priv *priv)
{
rtl8192_tx_resume(priv->rtllib->dev);
}
-void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
+static void rtl8192_irq_rx_tasklet(struct r8192_priv *priv)
{
rtl8192_rx_normal(priv->rtllib->dev);
- if (MAX_RX_QUEUE > 1)
- rtl8192_rx_cmd(priv->rtllib->dev);
-
- write_nic_dword(priv->rtllib->dev, INTA_MASK,
- read_nic_dword(priv->rtllib->dev, INTA_MASK) | IMR_RDU);
+ rtl92e_writel(priv->rtllib->dev, INTA_MASK,
+ rtl92e_readl(priv->rtllib->dev, INTA_MASK) | IMR_RDU);
}
/****************************************************************************
---------------------------- NIC START/CLOSE STUFF---------------------------
*****************************************************************************/
-void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
+static void rtl8192_cancel_deferred_work(struct r8192_priv *priv)
{
cancel_delayed_work(&priv->watch_dog_wq);
cancel_delayed_work(&priv->update_beacon_wq);
@@ -2394,14 +2186,13 @@
cancel_work_sync(&priv->qos_activate);
}
-int _rtl8192_up(struct net_device *dev, bool is_silent_reset)
+static int _rtl8192_up(struct net_device *dev, bool is_silent_reset)
{
if (_rtl8192_sta_up(dev, is_silent_reset) == -1)
return -1;
return 0;
}
-
static int rtl8192_open(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -2414,8 +2205,7 @@
}
-
-int rtl8192_up(struct net_device *dev)
+static int rtl8192_up(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -2445,7 +2235,7 @@
}
-int rtl8192_down(struct net_device *dev, bool shutdownrf)
+static int rtl8192_down(struct net_device *dev, bool shutdownrf)
{
if (rtl8192_sta_down(dev, shutdownrf) == -1)
return -1;
@@ -2453,19 +2243,19 @@
return 0;
}
-void rtl8192_commit(struct net_device *dev)
+void rtl92e_commit(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
if (priv->up == 0)
return;
rtllib_softmac_stop_protocol(priv->rtllib, 0, true);
- rtl8192_irq_disable(dev);
+ rtl92e_irq_disable(dev);
priv->ops->stop_adapter(dev, true);
_rtl8192_up(dev, false);
}
-void rtl8192_restart(void *data)
+static void rtl8192_restart(void *data)
{
struct r8192_priv *priv = container_of_work_rsl(data, struct r8192_priv,
reset_wq);
@@ -2473,7 +2263,7 @@
down(&priv->wx_sem);
- rtl8192_commit(dev);
+ rtl92e_commit(dev);
up(&priv->wx_sem);
}
@@ -2552,30 +2342,34 @@
if (is_zero_ether_addr(ieee->ap_mac_addr))
ieee->iw_mode = IW_MODE_ADHOC;
memcpy((u8 *)key, ipw->u.crypt.key, 16);
- EnableHWSecurityConfig8192(dev);
- set_swcam(dev, 4, ipw->u.crypt.idx,
- ieee->pairwise_key_type,
- (u8 *)ieee->ap_mac_addr,
- 0, key, 0);
- setKey(dev, 4, ipw->u.crypt.idx,
- ieee->pairwise_key_type,
- (u8 *)ieee->ap_mac_addr, 0, key);
- if (ieee->iw_mode == IW_MODE_ADHOC) {
- set_swcam(dev, ipw->u.crypt.idx,
- ipw->u.crypt.idx,
- ieee->pairwise_key_type,
- (u8 *)ieee->ap_mac_addr,
- 0, key, 0);
- setKey(dev, ipw->u.crypt.idx,
- ipw->u.crypt.idx,
+ rtl92e_enable_hw_security_config(dev);
+ rtl92e_set_swcam(dev, 4,
+ ipw->u.crypt.idx,
+ ieee->pairwise_key_type,
+ (u8 *)ieee->ap_mac_addr,
+ 0, key, 0);
+ rtl92e_set_key(dev, 4, ipw->u.crypt.idx,
ieee->pairwise_key_type,
(u8 *)ieee->ap_mac_addr,
0, key);
+ if (ieee->iw_mode == IW_MODE_ADHOC) {
+ rtl92e_set_swcam(dev,
+ ipw->u.crypt.idx,
+ ipw->u.crypt.idx,
+ ieee->pairwise_key_type,
+ (u8 *)ieee->ap_mac_addr,
+ 0, key, 0);
+ rtl92e_set_key(dev,
+ ipw->u.crypt.idx,
+ ipw->u.crypt.idx,
+ ieee->pairwise_key_type,
+ (u8 *)ieee->ap_mac_addr,
+ 0, key);
}
}
if ((ieee->pairwise_key_type == KEY_TYPE_CCMP)
&& ieee->pHTInfo->bCurrentHTSupport) {
- write_nic_byte(dev, 0x173, 1);
+ rtl92e_writeb(dev, 0x173, 1);
}
} else {
@@ -2595,14 +2389,15 @@
ieee->group_key_type = KEY_TYPE_NA;
if (ieee->group_key_type) {
- set_swcam(dev, ipw->u.crypt.idx,
- ipw->u.crypt.idx,
- ieee->group_key_type,
- broadcast_addr, 0, key, 0);
- setKey(dev, ipw->u.crypt.idx,
- ipw->u.crypt.idx,
- ieee->group_key_type,
- broadcast_addr, 0, key);
+ rtl92e_set_swcam(dev, ipw->u.crypt.idx,
+ ipw->u.crypt.idx,
+ ieee->group_key_type,
+ broadcast_addr, 0, key,
+ 0);
+ rtl92e_set_key(dev, ipw->u.crypt.idx,
+ ipw->u.crypt.idx,
+ ieee->group_key_type,
+ broadcast_addr, 0, key);
}
}
}
@@ -2707,8 +2502,8 @@
if (inta & IMR_RDU) {
RT_TRACE(COMP_INTR, "rx descriptor unavailable!\n");
priv->stats.rxrdu++;
- write_nic_dword(dev, INTA_MASK,
- read_nic_dword(dev, INTA_MASK) & ~IMR_RDU);
+ rtl92e_writel(dev, INTA_MASK,
+ rtl92e_readl(dev, INTA_MASK) & ~IMR_RDU);
tasklet_schedule(&priv->irq_rx_tasklet);
}
@@ -2782,7 +2577,6 @@
struct rtl819x_ops *ops = (struct rtl819x_ops *)(id->driver_data);
unsigned long pmem_start, pmem_len, pmem_flags;
int err = -ENOMEM;
- bool bdma64 = false;
u8 revision_id;
RT_TRACE(COMP_INIT, "Configuring chip resources");
@@ -2806,8 +2600,6 @@
goto err_pci_disable;
err = -ENODEV;
- if (bdma64)
- dev->features |= NETIF_F_HIGHDMA;
pci_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -2850,12 +2642,12 @@
pci_read_config_byte(pdev, 0x08, &revision_id);
/* If the revisionid is 0x10, the device uses rtl8192se. */
if (pdev->device == 0x8192 && revision_id == 0x10)
- goto err_rel_mem;
+ goto err_unmap;
priv->ops = ops;
- if (rtl8192_pci_findadapter(pdev, dev) == false)
- goto err_rel_mem;
+ if (rtl92e_check_adapter(pdev, dev) == false)
+ goto err_unmap;
dev->irq = pdev->irq;
priv->irq = 0;
@@ -2888,7 +2680,7 @@
RT_TRACE(COMP_INIT, "dev name: %s\n", dev->name);
if (priv->polling_timer_on == 0)
- check_rfctrl_gpio_timer((unsigned long)dev);
+ rtl92e_check_rfctrl_gpio_timer((unsigned long)dev);
RT_TRACE(COMP_INIT, "Driver probe completed\n");
return 0;
@@ -2896,12 +2688,12 @@
err_free_irq:
free_irq(dev->irq, dev);
priv->irq = 0;
+err_unmap:
+ iounmap((void __iomem *)ioaddr);
err_rel_mem:
release_mem_region(pmem_start, pmem_len);
err_rel_rtllib:
free_rtllib(dev);
-
- DMESG("wlan driver load failed\n");
err_pci_disable:
pci_disable_device(pdev);
return err;
@@ -2922,7 +2714,7 @@
cancel_delayed_work(&priv->gpio_change_rf_wq);
priv->polling_timer_on = 0;
rtl8192_down(dev, true);
- deinit_hal_dm(dev);
+ rtl92e_dm_deinit(dev);
if (priv->pFirmware) {
vfree(priv->pFirmware);
priv->pFirmware = NULL;
@@ -2952,7 +2744,7 @@
RT_TRACE(COMP_DOWN, "wlan driver removed\n");
}
-bool NicIFEnableNIC(struct net_device *dev)
+bool rtl92e_enable_nic(struct net_device *dev)
{
bool init_status = true;
struct r8192_priv *priv = rtllib_priv(dev);
@@ -2977,12 +2769,12 @@
RT_CLEAR_PS_LEVEL(pPSC, RT_RF_OFF_LEVL_HALT_NIC);
priv->bfirst_init = false;
- rtl8192_irq_enable(dev);
+ rtl92e_irq_enable(dev);
priv->bdisable_nic = false;
RT_TRACE(COMP_PS, "<===========%s()\n", __func__);
return init_status;
}
-bool NicIFDisableNIC(struct net_device *dev)
+bool rtl92e_disable_nic(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
u8 tmp_state = 0;
@@ -2993,7 +2785,7 @@
rtllib_softmac_stop_protocol(priv->rtllib, 0, false);
priv->rtllib->state = tmp_state;
rtl8192_cancel_deferred_work(priv);
- rtl8192_irq_disable(dev);
+ rtl92e_irq_disable(dev);
priv->ops->stop_adapter(dev, false);
RT_TRACE(COMP_PS, "<=========%s()\n", __func__);
@@ -3007,7 +2799,6 @@
pr_info("Copyright (c) 2007-2008, Realsil Wlan Driver\n");
if (0 != pci_register_driver(&rtl8192_pci_driver)) {
- DMESG("No device found");
/*pci_unregister_driver (&rtl8192_pci_driver);*/
return -ENODEV;
}
@@ -3021,7 +2812,7 @@
RT_TRACE(COMP_DOWN, "Exiting");
}
-void check_rfctrl_gpio_timer(unsigned long data)
+void rtl92e_check_rfctrl_gpio_timer(unsigned long data)
{
struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
index 776d950..cd948bb 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.h
@@ -578,84 +578,44 @@
extern const struct ethtool_ops rtl819x_ethtool_ops;
-void rtl8192_tx_cmd(struct net_device *dev, struct sk_buff *skb);
-short rtl8192_tx(struct net_device *dev, struct sk_buff *skb);
-
-u8 read_nic_io_byte(struct net_device *dev, int x);
-u32 read_nic_io_dword(struct net_device *dev, int x);
-u16 read_nic_io_word(struct net_device *dev, int x);
-void write_nic_io_byte(struct net_device *dev, int x, u8 y);
-void write_nic_io_word(struct net_device *dev, int x, u16 y);
-void write_nic_io_dword(struct net_device *dev, int x, u32 y);
-
-u8 read_nic_byte(struct net_device *dev, int x);
-u32 read_nic_dword(struct net_device *dev, int x);
-u16 read_nic_word(struct net_device *dev, int x);
-void write_nic_byte(struct net_device *dev, int x, u8 y);
-void write_nic_word(struct net_device *dev, int x, u16 y);
-void write_nic_dword(struct net_device *dev, int x, u32 y);
+u8 rtl92e_readb(struct net_device *dev, int x);
+u32 rtl92e_readl(struct net_device *dev, int x);
+u16 rtl92e_readw(struct net_device *dev, int x);
+void rtl92e_writeb(struct net_device *dev, int x, u8 y);
+void rtl92e_writew(struct net_device *dev, int x, u16 y);
+void rtl92e_writel(struct net_device *dev, int x, u32 y);
void force_pci_posting(struct net_device *dev);
-void rtl8192_rx_enable(struct net_device *);
-void rtl8192_tx_enable(struct net_device *);
+void rtl92e_rx_enable(struct net_device *);
+void rtl92e_tx_enable(struct net_device *);
-int rtl8192_hard_start_xmit(struct sk_buff *skb, struct net_device *dev);
-void rtl8192_hard_data_xmit(struct sk_buff *skb, struct net_device *dev,
- int rate);
-void rtl8192_data_hard_stop(struct net_device *dev);
-void rtl8192_data_hard_resume(struct net_device *dev);
-void rtl8192_restart(void *data);
-void rtl819x_watchdog_wqcallback(void *data);
-void rtl8192_hw_sleep_wq(void *data);
-void watch_dog_timer_callback(unsigned long data);
-void rtl8192_irq_rx_tasklet(struct r8192_priv *priv);
-void rtl8192_irq_tx_tasklet(struct r8192_priv *priv);
-int rtl8192_down(struct net_device *dev, bool shutdownrf);
-int rtl8192_up(struct net_device *dev);
-void rtl8192_commit(struct net_device *dev);
-void rtl8192_set_chan(struct net_device *dev, short ch);
+void rtl92e_hw_sleep_wq(void *data);
+void rtl92e_commit(struct net_device *dev);
-void check_rfctrl_gpio_timer(unsigned long data);
+void rtl92e_check_rfctrl_gpio_timer(unsigned long data);
-void rtl8192_hw_wakeup_wq(void *data);
-short rtl8192_pci_initdescring(struct net_device *dev);
+void rtl92e_hw_wakeup_wq(void *data);
-void rtl8192_cancel_deferred_work(struct r8192_priv *priv);
+void rtl92e_reset_desc_ring(struct net_device *dev);
+void rtl92e_set_wireless_mode(struct net_device *dev, u8 wireless_mode);
+void rtl92e_irq_enable(struct net_device *dev);
+void rtl92e_config_rate(struct net_device *dev, u16 *rate_config);
+void rtl92e_irq_disable(struct net_device *dev);
-int _rtl8192_up(struct net_device *dev, bool is_silent_reset);
+void rtl92e_update_rx_pkt_timestamp(struct net_device *dev,
+ struct rtllib_rx_stats *stats);
+long rtl92e_translate_to_dbm(struct r8192_priv *priv, u8 signal_strength_index);
+void rtl92e_update_rx_statistics(struct r8192_priv *priv,
+ struct rtllib_rx_stats *pprevious_stats);
+u8 rtl92e_evm_db_to_percent(char value);
+u8 rtl92e_rx_db_to_percent(char antpower);
+void rtl92e_copy_mpdu_stats(struct rtllib_rx_stats *psrc_stats,
+ struct rtllib_rx_stats *ptarget_stats);
+bool rtl92e_enable_nic(struct net_device *dev);
+bool rtl92e_disable_nic(struct net_device *dev);
-short rtl8192_is_tx_queue_empty(struct net_device *dev);
-void rtl8192_irq_disable(struct net_device *dev);
-
-void rtl8192_tx_timeout(struct net_device *dev);
-void rtl8192_pci_resetdescring(struct net_device *dev);
-void rtl8192_SetWirelessMode(struct net_device *dev, u8 wireless_mode);
-void rtl8192_irq_enable(struct net_device *dev);
-void rtl8192_config_rate(struct net_device *dev, u16 *rate_config);
-void rtl8192_update_cap(struct net_device *dev, u16 cap);
-void rtl8192_irq_disable(struct net_device *dev);
-
-void rtl819x_UpdateRxPktTimeStamp(struct net_device *dev,
- struct rtllib_rx_stats *stats);
-long rtl819x_translate_todbm(struct r8192_priv *priv, u8 signal_strength_index);
-void rtl819x_update_rxsignalstatistics8190pci(struct r8192_priv *priv,
- struct rtllib_rx_stats *pprevious_stats);
-u8 rtl819x_evm_dbtopercentage(char value);
-void rtl819x_process_cck_rxpathsel(struct r8192_priv *priv,
- struct rtllib_rx_stats *pprevious_stats);
-u8 rtl819x_query_rxpwrpercentage(char antpower);
-void rtl8192_record_rxdesc_forlateruse(struct rtllib_rx_stats *psrc_stats,
- struct rtllib_rx_stats *ptarget_stats);
-bool NicIFEnableNIC(struct net_device *dev);
-bool NicIFDisableNIC(struct net_device *dev);
-
-bool MgntActSet_RF_State(struct net_device *dev,
+bool rtl92e_set_rf_state(struct net_device *dev,
enum rt_rf_power_state StateToSet,
- RT_RF_CHANGE_SOURCE ChangeSource,
- bool ProtectOrNot);
-void ActUpdateChannelAccessSetting(struct net_device *dev,
- enum wireless_mode WirelessMode,
- struct channel_access_setting *ChnlAccessSetting);
-
+ RT_RF_CHANGE_SOURCE ChangeSource);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
index 3de7cc5..1a0c690 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.c
@@ -58,9 +58,6 @@
0x5e4332
};
-#define RTK_UL_EDCA 0xa44f
-#define RTK_DL_EDCA 0x5e4322
-
const u32 dm_tx_bb_gain[TxBBGainTableLength] = {
0x7f8001fe, /* 12 dB */
0x788001e2, /* 11 dB */
@@ -213,6 +210,9 @@
static void dm_check_txrateandretrycount(struct net_device *dev);
static void dm_check_ac_dc_power(struct net_device *dev);
+static void dm_check_fsync(struct net_device *dev);
+static void dm_CheckRfCtrlGPIO(void *data);
+static void dm_fsync_timer_callback(unsigned long data);
/*---------------------Define local function prototype-----------------------*/
@@ -224,7 +224,7 @@
static void dm_ctstoself(struct net_device *dev);
/*---------------------------Define function prototype------------------------*/
-void init_hal_dm(struct net_device *dev)
+void rtl92e_dm_init(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -234,10 +234,10 @@
dm_init_dynamic_txpower(dev);
- init_rate_adaptive(dev);
+ rtl92e_init_adaptive_rate(dev);
dm_dig_init(dev);
- dm_init_edca_turbo(dev);
+ rtl92e_dm_init_edca_turbo(dev);
dm_init_bandwidth_autoswitch(dev);
dm_init_fsync(dev);
dm_init_rxpath_selection(dev);
@@ -249,14 +249,14 @@
(void *)dm_CheckRfCtrlGPIO, dev);
}
-void deinit_hal_dm(struct net_device *dev)
+void rtl92e_dm_deinit(struct net_device *dev)
{
dm_deInit_fsync(dev);
}
-void hal_dm_watchdog(struct net_device *dev)
+void rtl92e_dm_watchdog(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -307,7 +307,7 @@
};
-void init_rate_adaptive(struct net_device *dev)
+void rtl92e_init_adaptive_rate(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -444,7 +444,7 @@
if (priv->rtllib->GetHalfNmodeSupportByAPsHandler(dev))
targetRATR &= 0xf00fffff;
- currentRATR = read_nic_dword(dev, RATR0);
+ currentRATR = rtl92e_readl(dev, RATR0);
if (targetRATR != currentRATR) {
u32 ratr_value;
@@ -454,8 +454,8 @@
currentRATR, targetRATR);
if (priv->rf_type == RF_1T2R)
ratr_value &= ~(RATE_ALL_OFDM_2SS);
- write_nic_dword(dev, RATR0, ratr_value);
- write_nic_byte(dev, UFWP, 1);
+ rtl92e_writel(dev, RATR0, ratr_value);
+ rtl92e_writeb(dev, UFWP, 1);
pra->last_ratr = targetRATR;
}
@@ -561,40 +561,40 @@
p->rfa_txpowertrackingindex--;
if (p->rfa_txpowertrackingindex_real > 4) {
p->rfa_txpowertrackingindex_real--;
- rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
}
p->rfc_txpowertrackingindex--;
if (p->rfc_txpowertrackingindex_real > 4) {
p->rfc_txpowertrackingindex_real--;
- rtl8192_setBBreg(dev,
- rOFDM0_XCTxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]);
+ rtl92e_set_bb_reg(dev,
+ rOFDM0_XCTxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]);
}
} else {
- rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[4]);
- rtl8192_setBBreg(dev,
- rOFDM0_XCTxIQImbalance,
- bMaskDWord, dm_tx_bb_gain[4]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[4]);
+ rtl92e_set_bb_reg(dev,
+ rOFDM0_XCTxIQImbalance,
+ bMaskDWord, dm_tx_bb_gain[4]);
}
} else {
if (p->rfa_txpowertrackingindex > 0) {
p->rfa_txpowertrackingindex--;
if (p->rfa_txpowertrackingindex_real > 4) {
p->rfa_txpowertrackingindex_real--;
- rtl8192_setBBreg(dev,
- rOFDM0_XATxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
+ rtl92e_set_bb_reg(dev,
+ rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
}
} else {
- rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
- bMaskDWord, dm_tx_bb_gain[4]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord, dm_tx_bb_gain[4]);
}
}
}
@@ -608,36 +608,33 @@
(p->rfc_txpowertrackingindex < TxBBGainTableLength - 1)) {
p->rfa_txpowertrackingindex++;
p->rfa_txpowertrackingindex_real++;
- rtl8192_setBBreg(dev,
- rOFDM0_XATxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
p->rfc_txpowertrackingindex++;
p->rfc_txpowertrackingindex_real++;
- rtl8192_setBBreg(dev,
- rOFDM0_XCTxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XCTxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[p->rfc_txpowertrackingindex_real]);
} else {
- rtl8192_setBBreg(dev,
- rOFDM0_XATxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[TxBBGainTableLength - 1]);
- rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[TxBBGainTableLength - 1]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[TxBBGainTableLength - 1]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XCTxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[TxBBGainTableLength - 1]);
}
} else {
if (p->rfa_txpowertrackingindex < (TxBBGainTableLength - 1)) {
p->rfa_txpowertrackingindex++;
p->rfa_txpowertrackingindex_real++;
- rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[p->rfa_txpowertrackingindex_real]);
} else {
- rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance,
- bMaskDWord,
- dm_tx_bb_gain[TxBBGainTableLength - 1]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord,
+ dm_tx_bb_gain[TxBBGainTableLength - 1]);
}
}
}
@@ -656,8 +653,8 @@
u32 delta = 0;
RT_TRACE(COMP_POWER_TRACKING, "%s()\n", __func__);
- write_nic_byte(dev, Pw_Track_Flag, 0);
- write_nic_byte(dev, FW_Busy_Flag, 0);
+ rtl92e_writeb(dev, Pw_Track_Flag, 0);
+ rtl92e_writeb(dev, FW_Busy_Flag, 0);
priv->rtllib->bdynamic_txpower_enable = false;
bHighpowerstate = priv->bDynamicTxHighPower;
@@ -674,12 +671,11 @@
tx_cmd.Op = TXCMD_SET_TX_PWR_TRACKING;
tx_cmd.Length = 4;
tx_cmd.Value = Value;
- cmpk_message_handle_tx(dev, (u8 *)&tx_cmd,
- DESC_PACKET_TYPE_INIT,
- sizeof(struct dcmd_txcmd));
+ rtl92e_send_cmd_pkt(dev, (u8 *)&tx_cmd, DESC_PACKET_TYPE_INIT,
+ sizeof(struct dcmd_txcmd));
mdelay(1);
for (i = 0; i <= 30; i++) {
- Pwr_Flag = read_nic_byte(dev, Pw_Track_Flag);
+ Pwr_Flag = rtl92e_readb(dev, Pw_Track_Flag);
if (Pwr_Flag == 0) {
mdelay(1);
@@ -687,35 +683,35 @@
if (priv->bResetInProgress) {
RT_TRACE(COMP_POWER_TRACKING,
"we are in silent reset progress, so return\n");
- write_nic_byte(dev, Pw_Track_Flag, 0);
- write_nic_byte(dev, FW_Busy_Flag, 0);
+ rtl92e_writeb(dev, Pw_Track_Flag, 0);
+ rtl92e_writeb(dev, FW_Busy_Flag, 0);
return;
}
if (priv->rtllib->eRFPowerState != eRfOn) {
RT_TRACE(COMP_POWER_TRACKING,
"we are in power save, so return\n");
- write_nic_byte(dev, Pw_Track_Flag, 0);
- write_nic_byte(dev, FW_Busy_Flag, 0);
+ rtl92e_writeb(dev, Pw_Track_Flag, 0);
+ rtl92e_writeb(dev, FW_Busy_Flag, 0);
return;
}
continue;
}
- Avg_TSSI_Meas = read_nic_word(dev, Tssi_Mea_Value);
+ Avg_TSSI_Meas = rtl92e_readw(dev, Tssi_Mea_Value);
if (Avg_TSSI_Meas == 0) {
- write_nic_byte(dev, Pw_Track_Flag, 0);
- write_nic_byte(dev, FW_Busy_Flag, 0);
+ rtl92e_writeb(dev, Pw_Track_Flag, 0);
+ rtl92e_writeb(dev, FW_Busy_Flag, 0);
return;
}
for (k = 0; k < 5; k++) {
if (k != 4)
- tmp_report[k] = read_nic_byte(dev,
+ tmp_report[k] = rtl92e_readb(dev,
Tssi_Report_Value1+k);
else
- tmp_report[k] = read_nic_byte(dev,
+ tmp_report[k] = rtl92e_readb(dev,
Tssi_Report_Value2);
RT_TRACE(COMP_POWER_TRACKING,
@@ -729,7 +725,7 @@
}
if (viviflag) {
- write_nic_byte(dev, Pw_Track_Flag, 0);
+ rtl92e_writeb(dev, Pw_Track_Flag, 0);
viviflag = false;
RT_TRACE(COMP_POWER_TRACKING,
"we filted this data\n");
@@ -756,8 +752,8 @@
if (delta <= E_FOR_TX_POWER_TRACK) {
priv->rtllib->bdynamic_txpower_enable = true;
- write_nic_byte(dev, Pw_Track_Flag, 0);
- write_nic_byte(dev, FW_Busy_Flag, 0);
+ rtl92e_writeb(dev, Pw_Track_Flag, 0);
+ rtl92e_writeb(dev, FW_Busy_Flag, 0);
RT_TRACE(COMP_POWER_TRACKING,
"tx power track is done\n");
RT_TRACE(COMP_POWER_TRACKING,
@@ -806,12 +802,12 @@
if (priv->rtllib->current_network.channel == 14 &&
!priv->bcck_in_ch14) {
priv->bcck_in_ch14 = true;
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
} else if (priv->rtllib->current_network.channel != 14 && priv->bcck_in_ch14) {
priv->bcck_in_ch14 = false;
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
} else
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
}
RT_TRACE(COMP_POWER_TRACKING,
"priv->rfa_txpowertrackingindex = %d\n",
@@ -829,23 +825,23 @@
if (priv->CCKPresentAttentuation_difference <= -12 ||
priv->CCKPresentAttentuation_difference >= 24) {
priv->rtllib->bdynamic_txpower_enable = true;
- write_nic_byte(dev, Pw_Track_Flag, 0);
- write_nic_byte(dev, FW_Busy_Flag, 0);
+ rtl92e_writeb(dev, Pw_Track_Flag, 0);
+ rtl92e_writeb(dev, FW_Busy_Flag, 0);
RT_TRACE(COMP_POWER_TRACKING,
"tx power track--->limited\n");
return;
}
- write_nic_byte(dev, Pw_Track_Flag, 0);
+ rtl92e_writeb(dev, Pw_Track_Flag, 0);
Avg_TSSI_Meas_from_driver = 0;
for (k = 0; k < 5; k++)
tmp_report[k] = 0;
break;
}
- write_nic_byte(dev, FW_Busy_Flag, 0);
+ rtl92e_writeb(dev, FW_Busy_Flag, 0);
}
priv->rtllib->bdynamic_txpower_enable = true;
- write_nic_byte(dev, Pw_Track_Flag, 0);
+ rtl92e_writeb(dev, Pw_Track_Flag, 0);
}
static void dm_TXPowerTrackingCallback_ThermalMeter(struct net_device *dev)
@@ -857,8 +853,8 @@
int i = 0, CCKSwingNeedUpdate = 0;
if (!priv->btxpower_trackingInit) {
- tmpRegA = rtl8192_QueryBBReg(dev, rOFDM0_XATxIQImbalance,
- bMaskDWord);
+ tmpRegA = rtl92e_get_bb_reg(dev, rOFDM0_XATxIQImbalance,
+ bMaskDWord);
for (i = 0; i < OFDM_Table_Length; i++) {
if (tmpRegA == OFDMSwingTable[i]) {
priv->OFDM_index[0] = (u8)i;
@@ -869,7 +865,7 @@
}
}
- TempCCk = rtl8192_QueryBBReg(dev, rCCK0_TxFilter1, bMaskByte2);
+ TempCCk = rtl92e_get_bb_reg(dev, rCCK0_TxFilter1, bMaskByte2);
for (i = 0; i < CCK_Table_length; i++) {
if (TempCCk == (u32)CCKSwingTable_Ch1_Ch13[i][0]) {
priv->CCK_index = (u8) i;
@@ -884,7 +880,7 @@
return;
}
- tmpRegA = rtl8192_phy_QueryRFReg(dev, RF90_PATH_A, 0x12, 0x078);
+ tmpRegA = rtl92e_get_rf_reg(dev, RF90_PATH_A, 0x12, 0x078);
RT_TRACE(COMP_POWER_TRACKING, "Readback ThermalMeterA = %d\n", tmpRegA);
if (tmpRegA < 3 || tmpRegA > 13)
return;
@@ -939,11 +935,11 @@
}
if (CCKSwingNeedUpdate)
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
if (priv->OFDM_index[0] != tmpOFDMindex) {
priv->OFDM_index[0] = tmpOFDMindex;
- rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
- OFDMSwingTable[priv->OFDM_index[0]]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
+ OFDMSwingTable[priv->OFDM_index[0]]);
RT_TRACE(COMP_POWER_TRACKING, "Update OFDMSwing[%d] = 0x%x\n",
priv->OFDM_index[0],
OFDMSwingTable[priv->OFDM_index[0]]);
@@ -951,7 +947,7 @@
priv->txpower_count = 0;
}
-void dm_txpower_trackingcallback(void *data)
+void rtl92e_dm_txpower_tracking_wq(void *data)
{
struct r8192_priv *priv = container_of_dwork_rsl(data,
struct r8192_priv, txpower_tracking_wq);
@@ -989,7 +985,7 @@
priv->btxpower_tracking);
}
-void dm_initialize_txpower_tracking(struct net_device *dev)
+void rtl92e_dm_init_txpower_tracking(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1005,7 +1001,7 @@
static u32 tx_power_track_counter;
RT_TRACE(COMP_POWER_TRACKING, "%s()\n", __func__);
- if (read_nic_byte(dev, 0x11e) == 1)
+ if (rtl92e_readb(dev, 0x11e) == 1)
return;
if (!priv->btxpower_tracking)
return;
@@ -1039,10 +1035,10 @@
if (!TM_Trigger) {
{
- rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
- rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
- rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
- rtl8192_phy_SetRFReg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+ rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+ rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
+ rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4d);
+ rtl92e_set_rf_reg(dev, RF90_PATH_A, 0x02, bMask12Bits, 0x4f);
}
TM_Trigger = 1;
return;
@@ -1074,30 +1070,30 @@
TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][0] +
(dm_cck_tx_bb_gain[attenuation][1] << 8));
- rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
TempVal = (u32)((dm_cck_tx_bb_gain[attenuation][2]) +
(dm_cck_tx_bb_gain[attenuation][3] << 8) +
(dm_cck_tx_bb_gain[attenuation][4] << 16)+
(dm_cck_tx_bb_gain[attenuation][5] << 24));
- rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
TempVal = (u32)(dm_cck_tx_bb_gain[attenuation][6] +
(dm_cck_tx_bb_gain[attenuation][7] << 8));
- rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
} else {
TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][0]) +
(dm_cck_tx_bb_gain_ch14[attenuation][1] << 8));
- rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][2]) +
(dm_cck_tx_bb_gain_ch14[attenuation][3] << 8) +
(dm_cck_tx_bb_gain_ch14[attenuation][4] << 16)+
(dm_cck_tx_bb_gain_ch14[attenuation][5] << 24));
- rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
TempVal = (u32)((dm_cck_tx_bb_gain_ch14[attenuation][6]) +
(dm_cck_tx_bb_gain_ch14[attenuation][7] << 8));
- rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
}
}
@@ -1111,7 +1107,7 @@
if (!bInCH14) {
TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][0] +
(CCKSwingTable_Ch1_Ch13[priv->CCK_index][1] << 8);
- rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
RT_TRACE(COMP_POWER_TRACKING,
"CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter1,
TempVal);
@@ -1119,14 +1115,14 @@
(CCKSwingTable_Ch1_Ch13[priv->CCK_index][3] << 8) +
(CCKSwingTable_Ch1_Ch13[priv->CCK_index][4] << 16)+
(CCKSwingTable_Ch1_Ch13[priv->CCK_index][5] << 24);
- rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
RT_TRACE(COMP_POWER_TRACKING,
"CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_TxFilter2,
TempVal);
TempVal = CCKSwingTable_Ch1_Ch13[priv->CCK_index][6] +
(CCKSwingTable_Ch1_Ch13[priv->CCK_index][7] << 8);
- rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
RT_TRACE(COMP_POWER_TRACKING,
"CCK not chnl 14, reg 0x%x = 0x%x\n", rCCK0_DebugPort,
TempVal);
@@ -1134,26 +1130,26 @@
TempVal = CCKSwingTable_Ch14[priv->CCK_index][0] +
(CCKSwingTable_Ch14[priv->CCK_index][1] << 8);
- rtl8192_setBBreg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_TxFilter1, bMaskHWord, TempVal);
RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
rCCK0_TxFilter1, TempVal);
TempVal = CCKSwingTable_Ch14[priv->CCK_index][2] +
(CCKSwingTable_Ch14[priv->CCK_index][3] << 8) +
(CCKSwingTable_Ch14[priv->CCK_index][4] << 16)+
(CCKSwingTable_Ch14[priv->CCK_index][5] << 24);
- rtl8192_setBBreg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_TxFilter2, bMaskDWord, TempVal);
RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
rCCK0_TxFilter2, TempVal);
TempVal = CCKSwingTable_Ch14[priv->CCK_index][6] +
(CCKSwingTable_Ch14[priv->CCK_index][7]<<8);
- rtl8192_setBBreg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
+ rtl92e_set_bb_reg(dev, rCCK0_DebugPort, bMaskLWord, TempVal);
RT_TRACE(COMP_POWER_TRACKING, "CCK chnl 14, reg 0x%x = 0x%x\n",
rCCK0_DebugPort, TempVal);
}
}
-void dm_cck_txpower_adjust(struct net_device *dev, bool binch14)
+void rtl92e_dm_cck_txpower_adjust(struct net_device *dev, bool binch14)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1168,8 +1164,8 @@
struct r8192_priv *priv = rtllib_priv(dev);
RT_TRACE(COMP_POWER_TRACKING, "Start Reset Recovery ==>\n");
- rtl8192_setBBreg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
- dm_tx_bb_gain[priv->rfa_txpowertrackingindex]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XATxIQImbalance, bMaskDWord,
+ dm_tx_bb_gain[priv->rfa_txpowertrackingindex]);
RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc80 is %08x\n",
dm_tx_bb_gain[priv->rfa_txpowertrackingindex]);
RT_TRACE(COMP_POWER_TRACKING,
@@ -1181,10 +1177,10 @@
RT_TRACE(COMP_POWER_TRACKING,
"Reset Recovery: CCK Attenuation is %d dB\n",
priv->CCKPresentAttentuation);
- dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
+ rtl92e_dm_cck_txpower_adjust(dev, priv->bcck_in_ch14);
- rtl8192_setBBreg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord,
- dm_tx_bb_gain[priv->rfc_txpowertrackingindex]);
+ rtl92e_set_bb_reg(dev, rOFDM0_XCTxIQImbalance, bMaskDWord,
+ dm_tx_bb_gain[priv->rfc_txpowertrackingindex]);
RT_TRACE(COMP_POWER_TRACKING, "Reset Recovery: Fill in 0xc90 is %08x\n",
dm_tx_bb_gain[priv->rfc_txpowertrackingindex]);
RT_TRACE(COMP_POWER_TRACKING,
@@ -1195,7 +1191,7 @@
dm_tx_bb_gain_idx_to_amplify(priv->rfc_txpowertrackingindex));
}
-void dm_restore_dynamic_mechanism_state(struct net_device *dev)
+void rtl92e_dm_restore_state(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
u32 reg_ratr = priv->rate_adaptive.last_ratr;
@@ -1203,7 +1199,7 @@
if (!priv->up) {
RT_TRACE(COMP_RATE,
- "<---- dm_restore_dynamic_mechanism_state(): driver is going to unload\n");
+ "<---- rtl92e_dm_restore_state(): driver is going to unload\n");
return;
}
@@ -1215,8 +1211,8 @@
ratr_value = reg_ratr;
if (priv->rf_type == RF_1T2R)
ratr_value &= ~(RATE_ALL_OFDM_2SS);
- write_nic_dword(dev, RATR0, ratr_value);
- write_nic_byte(dev, UFWP, 1);
+ rtl92e_writel(dev, RATR0, ratr_value);
+ rtl92e_writeb(dev, UFWP, 1);
if (priv->btxpower_trackingInit && priv->btxpower_tracking)
dm_txpower_reset_recovery(dev);
@@ -1232,18 +1228,18 @@
if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
return;
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
- rtl8192_setBBreg(dev, rOFDM0_XAAGCCore1, bit_mask,
- (u32)priv->initgain_backup.xaagccore1);
- rtl8192_setBBreg(dev, rOFDM0_XBAGCCore1, bit_mask,
- (u32)priv->initgain_backup.xbagccore1);
- rtl8192_setBBreg(dev, rOFDM0_XCAGCCore1, bit_mask,
- (u32)priv->initgain_backup.xcagccore1);
- rtl8192_setBBreg(dev, rOFDM0_XDAGCCore1, bit_mask,
- (u32)priv->initgain_backup.xdagccore1);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
+ rtl92e_set_bb_reg(dev, rOFDM0_XAAGCCore1, bit_mask,
+ (u32)priv->initgain_backup.xaagccore1);
+ rtl92e_set_bb_reg(dev, rOFDM0_XBAGCCore1, bit_mask,
+ (u32)priv->initgain_backup.xbagccore1);
+ rtl92e_set_bb_reg(dev, rOFDM0_XCAGCCore1, bit_mask,
+ (u32)priv->initgain_backup.xcagccore1);
+ rtl92e_set_bb_reg(dev, rOFDM0_XDAGCCore1, bit_mask,
+ (u32)priv->initgain_backup.xdagccore1);
bit_mask = bMaskByte2;
- rtl8192_setBBreg(dev, rCCK0_CCA, bit_mask,
- (u32)priv->initgain_backup.cca);
+ rtl92e_set_bb_reg(dev, rCCK0_CCA, bit_mask,
+ (u32)priv->initgain_backup.cca);
RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xc50 is %x\n",
priv->initgain_backup.xaagccore1);
@@ -1255,12 +1251,12 @@
priv->initgain_backup.xdagccore1);
RT_TRACE(COMP_DIG, "dm_BBInitialGainRestore 0xa0a is %x\n",
priv->initgain_backup.cca);
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1);
}
-void dm_backup_dynamic_mechanism_state(struct net_device *dev)
+void rtl92e_dm_backup_state(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1279,13 +1275,13 @@
if (dm_digtable.dig_algorithm == DIG_ALGO_BY_RSSI)
return;
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
- priv->initgain_backup.xaagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XAAGCCore1, bit_mask);
- priv->initgain_backup.xbagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XBAGCCore1, bit_mask);
- priv->initgain_backup.xcagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XCAGCCore1, bit_mask);
- priv->initgain_backup.xdagccore1 = (u8)rtl8192_QueryBBReg(dev, rOFDM0_XDAGCCore1, bit_mask);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
+ priv->initgain_backup.xaagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XAAGCCore1, bit_mask);
+ priv->initgain_backup.xbagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XBAGCCore1, bit_mask);
+ priv->initgain_backup.xcagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XCAGCCore1, bit_mask);
+ priv->initgain_backup.xdagccore1 = (u8)rtl92e_get_bb_reg(dev, rOFDM0_XDAGCCore1, bit_mask);
bit_mask = bMaskByte2;
- priv->initgain_backup.cca = (u8)rtl8192_QueryBBReg(dev, rCCK0_CCA, bit_mask);
+ priv->initgain_backup.cca = (u8)rtl92e_get_bb_reg(dev, rCCK0_CCA, bit_mask);
RT_TRACE(COMP_DIG, "BBInitialGainBackup 0xc50 is %x\n",
priv->initgain_backup.xaagccore1);
@@ -1376,7 +1372,7 @@
fw_dig = 0;
if (fw_dig <= 3) {
for (i = 0; i < 3; i++)
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
fw_dig++;
dm_digtable.dig_state = DM_STA_DIG_OFF;
}
@@ -1410,7 +1406,7 @@
if (dm_digtable.dig_algorithm_switch) {
dm_digtable.dig_state = DM_STA_DIG_MAX;
for (i = 0; i < 3; i++)
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1);
dm_digtable.dig_algorithm_switch = 0;
}
@@ -1429,19 +1425,19 @@
dm_digtable.dig_highpwr_state = DM_STA_DIG_MAX;
dm_digtable.dig_state = DM_STA_DIG_OFF;
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x8);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x8);
- write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x17);
- write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x17);
- write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x17);
- write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x17);
+ rtl92e_writeb(dev, rOFDM0_XAAGCCore1, 0x17);
+ rtl92e_writeb(dev, rOFDM0_XBAGCCore1, 0x17);
+ rtl92e_writeb(dev, rOFDM0_XCAGCCore1, 0x17);
+ rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x17);
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00);
else
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+ rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42);
- write_nic_byte(dev, 0xa0a, 0x08);
+ rtl92e_writeb(dev, 0xa0a, 0x08);
return;
}
@@ -1462,25 +1458,25 @@
dm_digtable.dig_state = DM_STA_DIG_ON;
if (reset_flag == 1) {
- write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x2c);
- write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x2c);
- write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x2c);
- write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x2c);
+ rtl92e_writeb(dev, rOFDM0_XAAGCCore1, 0x2c);
+ rtl92e_writeb(dev, rOFDM0_XBAGCCore1, 0x2c);
+ rtl92e_writeb(dev, rOFDM0_XCAGCCore1, 0x2c);
+ rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x2c);
} else {
- write_nic_byte(dev, rOFDM0_XAAGCCore1, 0x20);
- write_nic_byte(dev, rOFDM0_XBAGCCore1, 0x20);
- write_nic_byte(dev, rOFDM0_XCAGCCore1, 0x20);
- write_nic_byte(dev, rOFDM0_XDAGCCore1, 0x20);
+ rtl92e_writeb(dev, rOFDM0_XAAGCCore1, 0x20);
+ rtl92e_writeb(dev, rOFDM0_XBAGCCore1, 0x20);
+ rtl92e_writeb(dev, rOFDM0_XCAGCCore1, 0x20);
+ rtl92e_writeb(dev, rOFDM0_XDAGCCore1, 0x20);
}
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20);
else
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+ rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44);
- write_nic_byte(dev, 0xa0a, 0xcd);
+ rtl92e_writeb(dev, 0xa0a, 0xcd);
- rtl8192_setBBreg(dev, UFWP, bMaskByte1, 0x1);
+ rtl92e_set_bb_reg(dev, UFWP, bMaskByte1, 0x1);
}
dm_ctrl_initgain_byrssi_highpwr(dev);
}
@@ -1505,9 +1501,9 @@
dm_digtable.dig_highpwr_state = DM_STA_DIG_ON;
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10);
else
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+ rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43);
} else {
if (dm_digtable.dig_highpwr_state == DM_STA_DIG_OFF &&
(priv->reset_count == reset_cnt_highpwr))
@@ -1519,9 +1515,9 @@
(priv->undecorated_smoothed_pwdb >=
dm_digtable.rssi_high_thresh)) {
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20);
else
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+ rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44);
}
}
reset_cnt_highpwr = priv->reset_count;
@@ -1568,16 +1564,16 @@
reset_cnt = priv->reset_count;
}
- if (dm_digtable.pre_ig_value != read_nic_byte(dev, rOFDM0_XAAGCCore1))
+ if (dm_digtable.pre_ig_value != rtl92e_readb(dev, rOFDM0_XAAGCCore1))
force_write = 1;
if ((dm_digtable.pre_ig_value != dm_digtable.cur_ig_value)
|| !initialized || force_write) {
initial_gain = (u8)dm_digtable.cur_ig_value;
- write_nic_byte(dev, rOFDM0_XAAGCCore1, initial_gain);
- write_nic_byte(dev, rOFDM0_XBAGCCore1, initial_gain);
- write_nic_byte(dev, rOFDM0_XCAGCCore1, initial_gain);
- write_nic_byte(dev, rOFDM0_XDAGCCore1, initial_gain);
+ rtl92e_writeb(dev, rOFDM0_XAAGCCore1, initial_gain);
+ rtl92e_writeb(dev, rOFDM0_XBAGCCore1, initial_gain);
+ rtl92e_writeb(dev, rOFDM0_XCAGCCore1, initial_gain);
+ rtl92e_writeb(dev, rOFDM0_XDAGCCore1, initial_gain);
dm_digtable.pre_ig_value = dm_digtable.cur_ig_value;
initialized = 1;
force_write = 0;
@@ -1630,20 +1626,20 @@
(initialized <= 3) || force_write) {
if (dm_digtable.curpd_thstate == DIG_PD_AT_LOW_POWER) {
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x00);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x00);
else
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x42);
+ rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x42);
} else if (dm_digtable.curpd_thstate ==
DIG_PD_AT_NORMAL_POWER) {
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x20);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x20);
else
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x44);
+ rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x44);
} else if (dm_digtable.curpd_thstate == DIG_PD_AT_HIGH_POWER) {
if (priv->CurrentChannelBW != HT_CHANNEL_WIDTH_20)
- write_nic_byte(dev, (rOFDM0_XATxAFE+3), 0x10);
+ rtl92e_writeb(dev, (rOFDM0_XATxAFE+3), 0x10);
else
- write_nic_byte(dev, rOFDM0_RxDetector1, 0x43);
+ rtl92e_writeb(dev, rOFDM0_RxDetector1, 0x43);
}
dm_digtable.prepd_thstate = dm_digtable.curpd_thstate;
if (initialized <= 3)
@@ -1687,16 +1683,16 @@
if ((dm_digtable.precs_ratio_state != dm_digtable.curcs_ratio_state) ||
!initialized || force_write) {
if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_LOWER)
- write_nic_byte(dev, 0xa0a, 0x08);
+ rtl92e_writeb(dev, 0xa0a, 0x08);
else if (dm_digtable.curcs_ratio_state == DIG_CS_RATIO_HIGHER)
- write_nic_byte(dev, 0xa0a, 0xcd);
+ rtl92e_writeb(dev, 0xa0a, 0xcd);
dm_digtable.precs_ratio_state = dm_digtable.curcs_ratio_state;
initialized = 1;
force_write = 0;
}
}
-void dm_init_edca_turbo(struct net_device *dev)
+void rtl92e_dm_init_edca_turbo(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -1745,21 +1741,19 @@
if (curTxOkCnt > 4*curRxOkCnt) {
if (priv->bis_cur_rdlstate ||
!priv->bcurrent_turbo_EDCA) {
- write_nic_dword(dev, EDCAPARA_BE,
- edca_setting_UL[pHTInfo->IOTPeer]);
+ rtl92e_writel(dev, EDCAPARA_BE,
+ edca_setting_UL[pHTInfo->IOTPeer]);
priv->bis_cur_rdlstate = false;
}
} else {
if (!priv->bis_cur_rdlstate ||
!priv->bcurrent_turbo_EDCA) {
if (priv->rtllib->mode == WIRELESS_MODE_G)
- write_nic_dword(dev,
- EDCAPARA_BE,
- edca_setting_DL_GMode[pHTInfo->IOTPeer]);
+ rtl92e_writel(dev, EDCAPARA_BE,
+ edca_setting_DL_GMode[pHTInfo->IOTPeer]);
else
- write_nic_dword(dev,
- EDCAPARA_BE,
- edca_setting_DL[pHTInfo->IOTPeer]);
+ rtl92e_writel(dev, EDCAPARA_BE,
+ edca_setting_DL[pHTInfo->IOTPeer]);
priv->bis_cur_rdlstate = true;
}
}
@@ -1769,20 +1763,18 @@
if (!priv->bis_cur_rdlstate ||
!priv->bcurrent_turbo_EDCA) {
if (priv->rtllib->mode == WIRELESS_MODE_G)
- write_nic_dword(dev,
- EDCAPARA_BE,
- edca_setting_DL_GMode[pHTInfo->IOTPeer]);
+ rtl92e_writel(dev, EDCAPARA_BE,
+ edca_setting_DL_GMode[pHTInfo->IOTPeer]);
else
- write_nic_dword(dev,
- EDCAPARA_BE,
- edca_setting_DL[pHTInfo->IOTPeer]);
+ rtl92e_writel(dev, EDCAPARA_BE,
+ edca_setting_DL[pHTInfo->IOTPeer]);
priv->bis_cur_rdlstate = true;
}
} else {
if (priv->bis_cur_rdlstate ||
!priv->bcurrent_turbo_EDCA) {
- write_nic_dword(dev, EDCAPARA_BE,
- edca_setting_UL[pHTInfo->IOTPeer]);
+ rtl92e_writel(dev, EDCAPARA_BE,
+ edca_setting_UL[pHTInfo->IOTPeer]);
priv->bis_cur_rdlstate = false;
}
@@ -1854,7 +1846,7 @@
{
}
-void dm_CheckRfCtrlGPIO(void *data)
+static void dm_CheckRfCtrlGPIO(void *data)
{
struct r8192_priv *priv = container_of_dwork_rsl(data,
struct r8192_priv, gpio_change_rf_wq);
@@ -1877,7 +1869,7 @@
return;
}
- tmp1byte = read_nic_byte(dev, GPI);
+ tmp1byte = rtl92e_readb(dev, GPI);
eRfPowerStateToSet = (tmp1byte&BIT1) ? eRfOn : eRfOff;
@@ -1896,8 +1888,7 @@
if (bActuallySet) {
mdelay(1000);
priv->bHwRfOffAction = 1;
- MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW,
- true);
+ rtl92e_set_rf_state(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW);
if (priv->bHwRadioOff)
argv[1] = "RFOFF";
else
@@ -1909,7 +1900,7 @@
}
}
-void dm_rf_pathcheck_workitemcallback(void *data)
+void rtl92e_dm_rf_pathcheck_wq(void *data)
{
struct r8192_priv *priv = container_of_dwork_rsl(data,
struct r8192_priv,
@@ -1917,7 +1908,7 @@
struct net_device *dev = priv->rtllib->dev;
u8 rfpath = 0, i;
- rfpath = read_nic_byte(dev, 0xc04);
+ rfpath = rtl92e_readb(dev, 0xc04);
for (i = 0; i < RF90_PATH_MAX; i++) {
if (rfpath & (0x01<<i))
@@ -1974,12 +1965,12 @@
return;
if (!cck_Rx_Path_initialized) {
- DM_RxPathSelTable.cck_Rx_path = (read_nic_byte(dev, 0xa07)&0xf);
+ DM_RxPathSelTable.cck_Rx_path = (rtl92e_readb(dev, 0xa07)&0xf);
cck_Rx_Path_initialized = 1;
}
DM_RxPathSelTable.disabledRF = 0xf;
- DM_RxPathSelTable.disabledRF &= ~(read_nic_byte(dev, 0xc04));
+ DM_RxPathSelTable.disabledRF &= ~(rtl92e_readb(dev, 0xc04));
if (priv->rtllib->mode == WIRELESS_MODE_B)
DM_RxPathSelTable.cck_method = CCK_Rx_Version_2;
@@ -2116,10 +2107,10 @@
DM_RxPathSelTable.diff_TH) {
DM_RxPathSelTable.rf_enable_rssi_th[min_rssi_index] =
tmp_max_rssi+5;
- rtl8192_setBBreg(dev, rOFDM0_TRxPathEnable,
- 0x1<<min_rssi_index, 0x0);
- rtl8192_setBBreg(dev, rOFDM1_TRxPathEnable,
- 0x1<<min_rssi_index, 0x0);
+ rtl92e_set_bb_reg(dev, rOFDM0_TRxPathEnable,
+ 0x1<<min_rssi_index, 0x0);
+ rtl92e_set_bb_reg(dev, rOFDM1_TRxPathEnable,
+ 0x1<<min_rssi_index, 0x0);
disabled_rf_cnt++;
}
if (DM_RxPathSelTable.cck_method == CCK_Rx_Version_1) {
@@ -2133,8 +2124,8 @@
if (update_cck_rx_path) {
DM_RxPathSelTable.cck_Rx_path = (cck_default_Rx<<2) |
(cck_optional_Rx);
- rtl8192_setBBreg(dev, rCCK0_AFESetting, 0x0f000000,
- DM_RxPathSelTable.cck_Rx_path);
+ rtl92e_set_bb_reg(dev, rCCK0_AFESetting, 0x0f000000,
+ DM_RxPathSelTable.cck_Rx_path);
}
if (DM_RxPathSelTable.disabledRF) {
@@ -2142,12 +2133,12 @@
if ((DM_RxPathSelTable.disabledRF>>i) & 0x1) {
if (tmp_max_rssi >=
DM_RxPathSelTable.rf_enable_rssi_th[i]) {
- rtl8192_setBBreg(dev,
- rOFDM0_TRxPathEnable, 0x1 << i,
- 0x1);
- rtl8192_setBBreg(dev,
- rOFDM1_TRxPathEnable,
- 0x1 << i, 0x1);
+ rtl92e_set_bb_reg(dev,
+ rOFDM0_TRxPathEnable,
+ 0x1 << i, 0x1);
+ rtl92e_set_bb_reg(dev,
+ rOFDM1_TRxPathEnable,
+ 0x1 << i, 0x1);
DM_RxPathSelTable.rf_enable_rssi_th[i]
= 100;
disabled_rf_cnt--;
@@ -2191,7 +2182,7 @@
del_timer_sync(&priv->fsync_timer);
}
-void dm_fsync_timer_callback(unsigned long data)
+static void dm_fsync_timer_callback(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct r8192_priv *priv = rtllib_priv((struct net_device *)data);
@@ -2252,18 +2243,18 @@
bDoubleTimeInterval = true;
priv->bswitch_fsync = !priv->bswitch_fsync;
if (priv->bswitch_fsync) {
- write_nic_byte(dev, 0xC36, 0x1c);
- write_nic_byte(dev, 0xC3e, 0x90);
+ rtl92e_writeb(dev, 0xC36, 0x1c);
+ rtl92e_writeb(dev, 0xC3e, 0x90);
} else {
- write_nic_byte(dev, 0xC36, 0x5c);
- write_nic_byte(dev, 0xC3e, 0x96);
+ rtl92e_writeb(dev, 0xC36, 0x5c);
+ rtl92e_writeb(dev, 0xC3e, 0x96);
}
} else if (priv->undecorated_smoothed_pwdb <=
priv->rtllib->fsync_rssi_threshold) {
if (priv->bswitch_fsync) {
priv->bswitch_fsync = false;
- write_nic_byte(dev, 0xC36, 0x5c);
- write_nic_byte(dev, 0xC3e, 0x96);
+ rtl92e_writeb(dev, 0xC36, 0x5c);
+ rtl92e_writeb(dev, 0xC3e, 0x96);
}
}
if (bDoubleTimeInterval) {
@@ -2283,11 +2274,11 @@
} else {
if (priv->bswitch_fsync) {
priv->bswitch_fsync = false;
- write_nic_byte(dev, 0xC36, 0x5c);
- write_nic_byte(dev, 0xC3e, 0x96);
+ rtl92e_writeb(dev, 0xC36, 0x5c);
+ rtl92e_writeb(dev, 0xC3e, 0x96);
}
priv->ContinueDiffCount = 0;
- write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+ rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd);
}
RT_TRACE(COMP_HALDM, "ContinueDiffCount %d\n", priv->ContinueDiffCount);
RT_TRACE(COMP_HALDM,
@@ -2302,10 +2293,10 @@
struct r8192_priv *priv = rtllib_priv(dev);
RT_TRACE(COMP_HALDM, "%s\n", __func__);
- write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cf);
+ rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cf);
priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING,
(u8 *)(&rf_timing));
- write_nic_byte(dev, 0xc3b, 0x41);
+ rtl92e_writeb(dev, 0xc3b, 0x41);
}
static void dm_EndHWFsync(struct net_device *dev)
@@ -2314,10 +2305,10 @@
struct r8192_priv *priv = rtllib_priv(dev);
RT_TRACE(COMP_HALDM, "%s\n", __func__);
- write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+ rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd);
priv->rtllib->SetHwRegHandler(dev, HW_VAR_RF_TIMING, (u8 *)
(&rf_timing));
- write_nic_byte(dev, 0xc3b, 0x49);
+ rtl92e_writeb(dev, 0xc3b, 0x49);
}
static void dm_EndSWFsync(struct net_device *dev)
@@ -2330,13 +2321,13 @@
if (priv->bswitch_fsync) {
priv->bswitch_fsync = false;
- write_nic_byte(dev, 0xC36, 0x5c);
+ rtl92e_writeb(dev, 0xC36, 0x5c);
- write_nic_byte(dev, 0xC3e, 0x96);
+ rtl92e_writeb(dev, 0xC3e, 0x96);
}
priv->ContinueDiffCount = 0;
- write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c52cd);
+ rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c52cd);
}
static void dm_StartSWFsync(struct net_device *dev)
@@ -2371,11 +2362,11 @@
msecs_to_jiffies(priv->rtllib->fsync_time_interval);
add_timer(&priv->fsync_timer);
- write_nic_dword(dev, rOFDM0_RxDetector2, 0x465c12cd);
+ rtl92e_writel(dev, rOFDM0_RxDetector2, 0x465c12cd);
}
-void dm_check_fsync(struct net_device *dev)
+static void dm_check_fsync(struct net_device *dev)
{
#define RegC38_Default 0
#define RegC38_NonFsync_Other_AP 1
@@ -2431,7 +2422,7 @@
}
if (priv->framesyncMonitor) {
if (reg_c38_State != RegC38_Fsync_AP_BCM) {
- write_nic_byte(dev, rOFDM0_RxDetector3, 0x95);
+ rtl92e_writeb(dev, rOFDM0_RxDetector3, 0x95);
reg_c38_State = RegC38_Fsync_AP_BCM;
}
@@ -2457,7 +2448,7 @@
RegC38_TH) {
if (reg_c38_State !=
RegC38_NonFsync_Other_AP) {
- write_nic_byte(dev,
+ rtl92e_writeb(dev,
rOFDM0_RxDetector3,
0x90);
@@ -2467,7 +2458,7 @@
} else if (priv->undecorated_smoothed_pwdb >=
(RegC38_TH+5)) {
if (reg_c38_State) {
- write_nic_byte(dev,
+ rtl92e_writeb(dev,
rOFDM0_RxDetector3,
priv->framesync);
reg_c38_State = RegC38_Default;
@@ -2475,8 +2466,8 @@
}
} else {
if (reg_c38_State) {
- write_nic_byte(dev, rOFDM0_RxDetector3,
- priv->framesync);
+ rtl92e_writeb(dev, rOFDM0_RxDetector3,
+ priv->framesync);
reg_c38_State = RegC38_Default;
}
}
@@ -2484,14 +2475,14 @@
}
if (priv->framesyncMonitor) {
if (priv->reset_count != reset_cnt) {
- write_nic_byte(dev, rOFDM0_RxDetector3,
+ rtl92e_writeb(dev, rOFDM0_RxDetector3,
priv->framesync);
reg_c38_State = RegC38_Default;
reset_cnt = priv->reset_count;
}
} else {
if (reg_c38_State) {
- write_nic_byte(dev, rOFDM0_RxDetector3,
+ rtl92e_writeb(dev, rOFDM0_RxDetector3,
priv->framesync);
reg_c38_State = RegC38_Default;
}
@@ -2556,8 +2547,7 @@
RT_TRACE(COMP_TXAGC, "SetTxPowerLevel8190() channel = %d\n",
priv->rtllib->current_network.channel);
- rtl8192_phy_setTxPower(dev,
- priv->rtllib->current_network.channel);
+ rtl92e_set_tx_power(dev, priv->rtllib->current_network.channel);
}
priv->bLastDTPFlag_High = priv->bDynamicTxHighPower;
priv->bLastDTPFlag_Low = priv->bDynamicTxLowPower;
@@ -2569,13 +2559,13 @@
struct r8192_priv *priv = rtllib_priv(dev);
struct rtllib_device *ieee = priv->rtllib;
- ieee->softmac_stats.CurrentShowTxate = read_nic_byte(dev,
+ ieee->softmac_stats.CurrentShowTxate = rtl92e_readb(dev,
Current_Tx_Rate_Reg);
- ieee->softmac_stats.last_packet_rate = read_nic_byte(dev,
+ ieee->softmac_stats.last_packet_rate = rtl92e_readb(dev,
Initial_Tx_Rate_Reg);
- ieee->softmac_stats.txretrycount = read_nic_dword(dev,
+ ieee->softmac_stats.txretrycount = rtl92e_readl(dev,
Tx_Retry_Count_Reg);
}
@@ -2583,5 +2573,5 @@
{
struct r8192_priv *priv = rtllib_priv(dev);
- write_nic_byte(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
+ rtl92e_writeb(dev, DRIVER_RSSI, (u8)priv->undecorated_smoothed_pwdb);
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h
index b037451..097f0dc 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_dm.h
@@ -27,26 +27,17 @@
#define DM_DIG_THRESH_HIGH 40
#define DM_DIG_THRESH_LOW 35
-#define DM_FALSEALARM_THRESH_LOW 40
-#define DM_FALSEALARM_THRESH_HIGH 1000
-
#define DM_DIG_HIGH_PWR_THRESH_HIGH 75
#define DM_DIG_HIGH_PWR_THRESH_LOW 70
#define BW_AUTO_SWITCH_HIGH_LOW 25
#define BW_AUTO_SWITCH_LOW_HIGH 30
-#define DM_check_fsync_time_interval 500
-
-
#define DM_DIG_BACKOFF 12
#define DM_DIG_MAX 0x36
#define DM_DIG_MIN 0x1c
#define DM_DIG_MIN_Netcore 0x12
-#define DM_DIG_BACKOFF_MAX 12
-#define DM_DIG_BACKOFF_MIN -4
-
#define RxPathSelection_SS_TH_low 30
#define RxPathSelection_diff_TH 18
@@ -55,8 +46,6 @@
#define RateAdaptiveTH_Low_40M 10
#define VeryLowRSSI 15
-#define CTSToSelfTHVal 35
-
#define WAIotTHVal 25
#define E_FOR_TX_POWER_TRACK 300
@@ -70,14 +59,6 @@
#define Tx_Retry_Count_Reg 0x1ac
#define RegC38_TH 20
-#define TX_POWER_NEAR_FIELD_THRESH_LVL2 74
-#define TX_POWER_NEAR_FIELD_THRESH_LVL1 67
-
-#define TxHighPwrLevel_Normal 0
-#define TxHighPwrLevel_Level1 1
-#define TxHighPwrLevel_Level2 2
-
-#define DM_Type_ByFW 0
#define DM_Type_ByDriver 1
/*--------------------------Define Parameters-------------------------------*/
@@ -207,23 +188,20 @@
/*--------------------------Exported Function prototype---------------------*/
/*--------------------------Exported Function prototype---------------------*/
-extern void init_hal_dm(struct net_device *dev);
-extern void deinit_hal_dm(struct net_device *dev);
+void rtl92e_dm_init(struct net_device *dev);
+void rtl92e_dm_deinit(struct net_device *dev);
-extern void hal_dm_watchdog(struct net_device *dev);
+void rtl92e_dm_watchdog(struct net_device *dev);
-extern void init_rate_adaptive(struct net_device *dev);
-extern void dm_txpower_trackingcallback(void *data);
+void rtl92e_init_adaptive_rate(struct net_device *dev);
+void rtl92e_dm_txpower_tracking_wq(void *data);
-extern void dm_cck_txpower_adjust(struct net_device *dev, bool binch14);
+void rtl92e_dm_cck_txpower_adjust(struct net_device *dev, bool binch14);
-extern void dm_restore_dynamic_mechanism_state(struct net_device *dev);
-extern void dm_backup_dynamic_mechanism_state(struct net_device *dev);
-extern void dm_init_edca_turbo(struct net_device *dev);
-extern void dm_rf_pathcheck_workitemcallback(void *data);
-extern void dm_fsync_timer_callback(unsigned long data);
-extern void dm_check_fsync(struct net_device *dev);
-extern void dm_initialize_txpower_tracking(struct net_device *dev);
-extern void dm_CheckRfCtrlGPIO(void *data);
+void rtl92e_dm_restore_state(struct net_device *dev);
+void rtl92e_dm_backup_state(struct net_device *dev);
+void rtl92e_dm_init_edca_turbo(struct net_device *dev);
+void rtl92e_dm_rf_pathcheck_wq(void *data);
+void rtl92e_dm_init_txpower_tracking(struct net_device *dev);
#endif /*__R8192UDM_H__ */
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c
index a6778e0..039ccfd 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.c
@@ -25,115 +25,75 @@
#include "rtl_core.h"
#include "rtl_eeprom.h"
-static void eprom_cs(struct net_device *dev, short bit)
+static void _rtl92e_gpio_write_bit(struct net_device *dev, int no, bool val)
{
- if (bit)
- write_nic_byte(dev, EPROM_CMD,
- (1 << EPROM_CS_SHIFT) |
- read_nic_byte(dev, EPROM_CMD));
+ u8 reg = rtl92e_readb(dev, EPROM_CMD);
+
+ if (val)
+ reg |= 1 << no;
else
- write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)
- & ~(1<<EPROM_CS_SHIFT));
+ reg &= ~(1 << no);
+ rtl92e_writeb(dev, EPROM_CMD, reg);
udelay(EPROM_DELAY);
}
-
-static void eprom_ck_cycle(struct net_device *dev)
+static bool _rtl92e_gpio_get_bit(struct net_device *dev, int no)
{
- write_nic_byte(dev, EPROM_CMD,
- (1<<EPROM_CK_SHIFT) | read_nic_byte(dev, EPROM_CMD));
- udelay(EPROM_DELAY);
- write_nic_byte(dev, EPROM_CMD,
- read_nic_byte(dev, EPROM_CMD) & ~(1<<EPROM_CK_SHIFT));
- udelay(EPROM_DELAY);
+ u8 reg = rtl92e_readb(dev, EPROM_CMD);
+
+ return (reg >> no) & 0x1;
}
-
-static void eprom_w(struct net_device *dev, short bit)
+static void _rtl92e_eeprom_ck_cycle(struct net_device *dev)
{
- if (bit)
- write_nic_byte(dev, EPROM_CMD, (1<<EPROM_W_SHIFT) |
- read_nic_byte(dev, EPROM_CMD));
- else
- write_nic_byte(dev, EPROM_CMD, read_nic_byte(dev, EPROM_CMD)
- & ~(1<<EPROM_W_SHIFT));
-
- udelay(EPROM_DELAY);
+ _rtl92e_gpio_write_bit(dev, EPROM_CK_BIT, 1);
+ _rtl92e_gpio_write_bit(dev, EPROM_CK_BIT, 0);
}
-
-static short eprom_r(struct net_device *dev)
+static u16 _rtl92e_eeprom_xfer(struct net_device *dev, u16 data, int tx_len)
{
- short bit;
+ u16 ret = 0;
+ int rx_len = 16;
- bit = (read_nic_byte(dev, EPROM_CMD) & (1<<EPROM_R_SHIFT));
- udelay(EPROM_DELAY);
+ _rtl92e_gpio_write_bit(dev, EPROM_CS_BIT, 1);
+ _rtl92e_eeprom_ck_cycle(dev);
- if (bit)
- return 1;
- return 0;
-}
-
-static void eprom_send_bits_string(struct net_device *dev, short b[], int len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- eprom_w(dev, b[i]);
- eprom_ck_cycle(dev);
+ while (tx_len--) {
+ _rtl92e_gpio_write_bit(dev, EPROM_W_BIT,
+ (data >> tx_len) & 0x1);
+ _rtl92e_eeprom_ck_cycle(dev);
}
+
+ _rtl92e_gpio_write_bit(dev, EPROM_W_BIT, 0);
+
+ while (rx_len--) {
+ _rtl92e_eeprom_ck_cycle(dev);
+ ret |= _rtl92e_gpio_get_bit(dev, EPROM_R_BIT) << rx_len;
+ }
+
+ _rtl92e_gpio_write_bit(dev, EPROM_CS_BIT, 0);
+ _rtl92e_eeprom_ck_cycle(dev);
+
+ return ret;
}
-u32 eprom_read(struct net_device *dev, u32 addr)
+u32 rtl92e_eeprom_read(struct net_device *dev, u32 addr)
{
struct r8192_priv *priv = rtllib_priv(dev);
- short read_cmd[] = {1, 1, 0};
- short addr_str[8];
- int i;
- int addr_len;
- u32 ret;
+ u32 ret = 0;
- ret = 0;
- write_nic_byte(dev, EPROM_CMD,
- (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT));
+ rtl92e_writeb(dev, EPROM_CMD,
+ (EPROM_CMD_PROGRAM << EPROM_CMD_OPERATING_MODE_SHIFT));
udelay(EPROM_DELAY);
- if (priv->epromtype == EEPROM_93C56) {
- addr_str[7] = addr & 1;
- addr_str[6] = addr & (1<<1);
- addr_str[5] = addr & (1<<2);
- addr_str[4] = addr & (1<<3);
- addr_str[3] = addr & (1<<4);
- addr_str[2] = addr & (1<<5);
- addr_str[1] = addr & (1<<6);
- addr_str[0] = addr & (1<<7);
- addr_len = 8;
- } else {
- addr_str[5] = addr & 1;
- addr_str[4] = addr & (1<<1);
- addr_str[3] = addr & (1<<2);
- addr_str[2] = addr & (1<<3);
- addr_str[1] = addr & (1<<4);
- addr_str[0] = addr & (1<<5);
- addr_len = 6;
- }
- eprom_cs(dev, 1);
- eprom_ck_cycle(dev);
- eprom_send_bits_string(dev, read_cmd, 3);
- eprom_send_bits_string(dev, addr_str, addr_len);
+ /* EEPROM is configured as x16 */
+ if (priv->epromtype == EEPROM_93C56)
+ ret = _rtl92e_eeprom_xfer(dev, (addr & 0xFF) | (0x6 << 8), 11);
+ else
+ ret = _rtl92e_eeprom_xfer(dev, (addr & 0x3F) | (0x6 << 6), 9);
- eprom_w(dev, 0);
-
- for (i = 0; i < 16; i++) {
- eprom_ck_cycle(dev);
- ret |= (eprom_r(dev)<<(15-i));
- }
-
- eprom_cs(dev, 0);
- eprom_ck_cycle(dev);
-
- write_nic_byte(dev, EPROM_CMD,
- (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
+ rtl92e_writeb(dev, EPROM_CMD,
+ (EPROM_CMD_NORMAL<<EPROM_CMD_OPERATING_MODE_SHIFT));
return ret;
}
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h
index adea2b4..8d23aea 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_eeprom.h
@@ -26,4 +26,4 @@
#define EPROM_DELAY 10
-u32 eprom_read(struct net_device *dev, u32 addr);
+u32 rtl92e_eeprom_read(struct net_device *dev, u32 addr);
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c
index 6bbd1c6..9fcb099 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.c
@@ -45,7 +45,7 @@
pci_write_config_byte(pdev, 0x70f, tmp);
}
-bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev)
+bool rtl92e_check_adapter(struct pci_dev *pdev, struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
u16 VenderID;
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
index e8d5527..6246841 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pci.h
@@ -29,6 +29,6 @@
#include <linux/pci.h>
struct net_device;
-bool rtl8192_pci_findadapter(struct pci_dev *pdev, struct net_device *dev);
+bool rtl92e_check_adapter(struct pci_dev *pdev, struct net_device *dev);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
index e4908672..b0268fd 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.c
@@ -23,7 +23,7 @@
#include "rtl_pm.h"
-int rtl8192E_suspend(struct pci_dev *pdev, pm_message_t state)
+int rtl92e_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct r8192_priv *priv = rtllib_priv(dev);
@@ -45,16 +45,16 @@
netif_device_detach(dev);
if (!priv->rtllib->bSupportRemoteWakeUp) {
- MgntActSet_RF_State(dev, eRfOff, RF_CHANGE_BY_INIT, true);
- ulRegRead = read_nic_dword(dev, CPU_GEN);
+ rtl92e_set_rf_state(dev, eRfOff, RF_CHANGE_BY_INIT);
+ ulRegRead = rtl92e_readl(dev, CPU_GEN);
ulRegRead |= CPU_GEN_SYSTEM_RESET;
- write_nic_dword(dev, CPU_GEN, ulRegRead);
+ rtl92e_writel(dev, CPU_GEN, ulRegRead);
} else {
- write_nic_dword(dev, WFCRC0, 0xffffffff);
- write_nic_dword(dev, WFCRC1, 0xffffffff);
- write_nic_dword(dev, WFCRC2, 0xffffffff);
- write_nic_byte(dev, PMR, 0x5);
- write_nic_byte(dev, MacBlkCtrl, 0xa);
+ rtl92e_writel(dev, WFCRC0, 0xffffffff);
+ rtl92e_writel(dev, WFCRC1, 0xffffffff);
+ rtl92e_writel(dev, WFCRC2, 0xffffffff);
+ rtl92e_writeb(dev, PMR, 0x5);
+ rtl92e_writeb(dev, MacBlkCtrl, 0xa);
}
out_pci_suspend:
netdev_info(dev, "WOL is %s\n", priv->rtllib->bSupportRemoteWakeUp ?
@@ -70,7 +70,7 @@
return 0;
}
-int rtl8192E_resume(struct pci_dev *pdev)
+int rtl92e_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
struct r8192_priv *priv = rtllib_priv(dev);
@@ -95,7 +95,7 @@
pci_enable_wake(pdev, PCI_D0, 0);
if (priv->polling_timer_on == 0)
- check_rfctrl_gpio_timer((unsigned long)dev);
+ rtl92e_check_rfctrl_gpio_timer((unsigned long)dev);
if (!netif_running(dev)) {
netdev_info(dev,
@@ -108,7 +108,7 @@
dev->netdev_ops->ndo_open(dev);
if (!priv->rtllib->bSupportRemoteWakeUp)
- MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_INIT, true);
+ rtl92e_set_rf_state(dev, eRfOn, RF_CHANGE_BY_INIT);
out:
RT_TRACE(COMP_POWER, "<================r8192E resume call.\n");
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h
index 7bfe448..cdc45f7 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_pm.h
@@ -23,7 +23,7 @@
#include <linux/types.h>
#include <linux/pci.h>
-int rtl8192E_suspend(struct pci_dev *dev, pm_message_t state);
-int rtl8192E_resume(struct pci_dev *dev);
+int rtl92e_suspend(struct pci_dev *dev, pm_message_t state);
+int rtl92e_resume(struct pci_dev *dev);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
index 404cb83..f09560d 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.c
@@ -45,10 +45,10 @@
spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
RT_TRACE(COMP_DBG, "%s()============>come to sleep down\n", __func__);
- MgntActSet_RF_State(dev, eRfSleep, RF_CHANGE_BY_PS, false);
+ rtl92e_set_rf_state(dev, eRfSleep, RF_CHANGE_BY_PS);
}
-void rtl8192_hw_sleep_wq(void *data)
+void rtl92e_hw_sleep_wq(void *data)
{
struct rtllib_device *ieee = container_of_dwork_rsl(data,
struct rtllib_device, hw_sleep_wq);
@@ -57,7 +57,7 @@
rtl8192_hw_sleep_down(dev);
}
-void rtl8192_hw_wakeup(struct net_device *dev)
+void rtl92e_hw_wakeup(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
unsigned long flags = 0;
@@ -66,7 +66,7 @@
if (priv->RFChangeInProgress) {
spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
RT_TRACE(COMP_DBG,
- "rtl8192_hw_wakeup(): RF Change in progress!\n");
+ "rtl92e_hw_wakeup(): RF Change in progress!\n");
queue_delayed_work_rsl(priv->rtllib->wq,
&priv->rtllib->hw_wakeup_wq,
msecs_to_jiffies(10));
@@ -74,21 +74,21 @@
}
spin_unlock_irqrestore(&priv->rf_ps_lock, flags);
RT_TRACE(COMP_PS, "%s()============>come to wake up\n", __func__);
- MgntActSet_RF_State(dev, eRfOn, RF_CHANGE_BY_PS, false);
+ rtl92e_set_rf_state(dev, eRfOn, RF_CHANGE_BY_PS);
}
-void rtl8192_hw_wakeup_wq(void *data)
+void rtl92e_hw_wakeup_wq(void *data)
{
struct rtllib_device *ieee = container_of_dwork_rsl(data,
struct rtllib_device, hw_wakeup_wq);
struct net_device *dev = ieee->dev;
- rtl8192_hw_wakeup(dev);
+ rtl92e_hw_wakeup(dev);
}
#define MIN_SLEEP_TIME 50
#define MAX_SLEEP_TIME 10000
-void rtl8192_hw_to_sleep(struct net_device *dev, u64 time)
+void rtl92e_enter_sleep(struct net_device *dev, u64 time)
{
struct r8192_priv *priv = rtllib_priv(dev);
@@ -133,14 +133,13 @@
RT_TRACE(COMP_PS, "InactivePsWorkItemCallback(): Set RF to %s.\n",
pPSC->eInactivePowerState == eRfOff ? "OFF" : "ON");
- MgntActSet_RF_State(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS,
- false);
+ rtl92e_set_rf_state(dev, pPSC->eInactivePowerState, RF_CHANGE_BY_IPS);
pPSC->bSwRfProcessing = false;
RT_TRACE(COMP_PS, "InactivePsWorkItemCallback() <---------\n");
}
-void IPSEnter(struct net_device *dev)
+void rtl92e_ips_enter(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
@@ -152,7 +151,7 @@
if (rtState == eRfOn && !pPSC->bSwRfProcessing &&
(priv->rtllib->state != RTLLIB_LINKED) &&
(priv->rtllib->iw_mode != IW_MODE_MASTER)) {
- RT_TRACE(COMP_PS, "IPSEnter(): Turn off RF.\n");
+ RT_TRACE(COMP_PS, "rtl92e_ips_enter(): Turn off RF.\n");
pPSC->eInactivePowerState = eRfOff;
priv->isRFOff = true;
priv->bInPowerSaveMode = true;
@@ -161,7 +160,7 @@
}
}
-void IPSLeave(struct net_device *dev)
+void rtl92e_ips_leave(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
@@ -172,7 +171,7 @@
rtState = priv->rtllib->eRFPowerState;
if (rtState != eRfOn && !pPSC->bSwRfProcessing &&
priv->rtllib->RfOffReason <= RF_CHANGE_BY_IPS) {
- RT_TRACE(COMP_PS, "IPSLeave(): Turn on RF.\n");
+ RT_TRACE(COMP_PS, "rtl92e_ips_leave(): Turn on RF.\n");
pPSC->eInactivePowerState = eRfOn;
priv->bInPowerSaveMode = false;
InactivePsWorkItemCallback(dev);
@@ -180,7 +179,7 @@
}
}
-void IPSLeave_wq(void *data)
+void rtl92e_ips_leave_wq(void *data)
{
struct rtllib_device *ieee = container_of_work_rsl(data,
struct rtllib_device, ips_leave_wq);
@@ -188,11 +187,11 @@
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
down(&priv->rtllib->ips_sem);
- IPSLeave(dev);
+ rtl92e_ips_leave(dev);
up(&priv->rtllib->ips_sem);
}
-void rtllib_ips_leave_wq(struct net_device *dev)
+void rtl92e_rtllib_ips_leave_wq(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
enum rt_rf_power_state rtState;
@@ -206,7 +205,7 @@
__func__);
return;
}
- netdev_info(dev, "=========>%s(): IPSLeave\n",
+ netdev_info(dev, "=========>%s(): rtl92e_ips_leave\n",
__func__);
queue_work_rsl(priv->rtllib->wq,
&priv->rtllib->ips_leave_wq);
@@ -214,12 +213,12 @@
}
}
-void rtllib_ips_leave(struct net_device *dev)
+void rtl92e_rtllib_ips_leave(struct net_device *dev)
{
struct r8192_priv *priv = (struct r8192_priv *)rtllib_priv(dev);
down(&priv->rtllib->ips_sem);
- IPSLeave(dev);
+ rtl92e_ips_leave(dev);
up(&priv->rtllib->ips_sem);
}
@@ -238,7 +237,7 @@
rtPsMode == RTLLIB_PS_DISABLED) {
unsigned long flags;
- rtl8192_hw_wakeup(dev);
+ rtl92e_hw_wakeup(dev);
priv->rtllib->sta_sleep = LPS_IS_WAKE;
spin_lock_irqsave(&(priv->rtllib->mgmt_tx_lock), flags);
@@ -251,13 +250,13 @@
return true;
}
-void LeisurePSEnter(struct net_device *dev)
+void rtl92e_leisure_ps_enter(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
&(priv->rtllib->PowerSaveControl);
- RT_TRACE(COMP_PS, "LeisurePSEnter()...\n");
+ RT_TRACE(COMP_PS, "rtl92e_leisure_ps_enter()...\n");
RT_TRACE(COMP_PS,
"pPSC->bLeisurePs = %d, ieee->ps = %d,pPSC->LpsIdleCount is %d,RT_CHECK_FOR_HANG_PERIOD is %d\n",
pPSC->bLeisurePs, priv->rtllib->ps, pPSC->LpsIdleCount,
@@ -275,7 +274,7 @@
if (priv->rtllib->ps == RTLLIB_PS_DISABLED) {
RT_TRACE(COMP_LPS,
- "LeisurePSEnter(): Enter 802.11 power save mode...\n");
+ "rtl92e_leisure_ps_enter(): Enter 802.11 power save mode...\n");
if (!pPSC->bFwCtrlLPS) {
if (priv->rtllib->SetFwCmdHandler)
@@ -291,21 +290,21 @@
}
}
-void LeisurePSLeave(struct net_device *dev)
+void rtl92e_leisure_ps_leave(struct net_device *dev)
{
struct r8192_priv *priv = rtllib_priv(dev);
struct rt_pwr_save_ctrl *pPSC = (struct rt_pwr_save_ctrl *)
&(priv->rtllib->PowerSaveControl);
- RT_TRACE(COMP_PS, "LeisurePSLeave()...\n");
+ RT_TRACE(COMP_PS, "rtl92e_leisure_ps_leave()...\n");
RT_TRACE(COMP_PS, "pPSC->bLeisurePs = %d, ieee->ps = %d\n",
pPSC->bLeisurePs, priv->rtllib->ps);
if (pPSC->bLeisurePs) {
if (priv->rtllib->ps != RTLLIB_PS_DISABLED) {
RT_TRACE(COMP_LPS,
- "LeisurePSLeave(): Busy Traffic , Leave 802.11 power save..\n");
+ "rtl92e_leisure_ps_leave(): Busy Traffic , Leave 802.11 power save..\n");
MgntActSet_802_11_PowerSaveMode(dev,
RTLLIB_PS_DISABLED);
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h
index 962f2e5..35fc9e2 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_ps.h
@@ -30,18 +30,17 @@
struct net_device;
#define RT_CHECK_FOR_HANG_PERIOD 2
-#define INIT_DEFAULT_CHAN 1
-void rtl8192_hw_wakeup(struct net_device *dev);
-void rtl8192_hw_to_sleep(struct net_device *dev, u64 time);
-void rtllib_ips_leave_wq(struct net_device *dev);
-void rtllib_ips_leave(struct net_device *dev);
-void IPSLeave_wq(void *data);
+void rtl92e_hw_wakeup(struct net_device *dev);
+void rtl92e_enter_sleep(struct net_device *dev, u64 time);
+void rtl92e_rtllib_ips_leave_wq(struct net_device *dev);
+void rtl92e_rtllib_ips_leave(struct net_device *dev);
+void rtl92e_ips_leave_wq(void *data);
-void IPSEnter(struct net_device *dev);
-void IPSLeave(struct net_device *dev);
+void rtl92e_ips_enter(struct net_device *dev);
+void rtl92e_ips_leave(struct net_device *dev);
-void LeisurePSEnter(struct net_device *dev);
-void LeisurePSLeave(struct net_device *dev);
+void rtl92e_leisure_ps_enter(struct net_device *dev);
+void rtl92e_leisure_ps_leave(struct net_device *dev);
#endif
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
index f5e4961..7e3ca7e 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_wx.c
@@ -192,7 +192,7 @@
pPSC->bLeisurePs = true;
} else {
if (priv->rtllib->state == RTLLIB_LINKED)
- LeisurePSLeave(dev);
+ rtl92e_leisure_ps_leave(dev);
priv->ps_force = true;
pPSC->bLeisurePs = false;
@@ -282,10 +282,11 @@
up(&priv->wx_sem);
return -1;
}
- netdev_info(dev, "=========>%s(): IPSLeave\n",
+ netdev_info(dev,
+ "=========>%s(): rtl92e_ips_leave\n",
__func__);
down(&priv->rtllib->ips_sem);
- IPSLeave(dev);
+ rtl92e_ips_leave(dev);
up(&priv->rtllib->ips_sem);
}
}
@@ -442,10 +443,11 @@
up(&priv->wx_sem);
return -1;
}
- RT_TRACE(COMP_PS, "=========>%s(): IPSLeave\n",
+ RT_TRACE(COMP_PS,
+ "=========>%s(): rtl92e_ips_leave\n",
__func__);
down(&priv->rtllib->ips_sem);
- IPSLeave(dev);
+ rtl92e_ips_leave(dev);
up(&priv->rtllib->ips_sem);
}
}
@@ -700,7 +702,7 @@
priv->rtllib->wx_set_enc = 1;
down(&priv->rtllib->ips_sem);
- IPSLeave(dev);
+ rtl92e_ips_leave(dev);
up(&priv->rtllib->ips_sem);
down(&priv->wx_sem);
@@ -711,7 +713,7 @@
if (wrqu->encoding.flags & IW_ENCODE_DISABLED) {
ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
- CamResetAllEntry(dev);
+ rtl92e_cam_reset(dev);
memset(priv->rtllib->swcamtable, 0,
sizeof(struct sw_cam_table) * 32);
goto end_hw_sec;
@@ -729,9 +731,6 @@
hwkey[i] |= (key[4 * i + 3] & mask) << 24;
}
- #define CONF_WEP40 0x4
- #define CONF_WEP104 0x14
-
switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
case 0:
key_idx = ieee->crypt_info.tx_keyidx;
@@ -753,16 +752,16 @@
}
if (wrqu->encoding.length == 0x5) {
ieee->pairwise_key_type = KEY_TYPE_WEP40;
- EnableHWSecurityConfig8192(dev);
+ rtl92e_enable_hw_security_config(dev);
}
else if (wrqu->encoding.length == 0xd) {
ieee->pairwise_key_type = KEY_TYPE_WEP104;
- EnableHWSecurityConfig8192(dev);
- setKey(dev, key_idx, key_idx, KEY_TYPE_WEP104,
- zero_addr[key_idx], 0, hwkey);
- set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104,
- zero_addr[key_idx], 0, hwkey, 0);
+ rtl92e_enable_hw_security_config(dev);
+ rtl92e_set_key(dev, key_idx, key_idx, KEY_TYPE_WEP104,
+ zero_addr[key_idx], 0, hwkey);
+ rtl92e_set_swcam(dev, key_idx, key_idx, KEY_TYPE_WEP104,
+ zero_addr[key_idx], 0, hwkey, 0);
} else {
netdev_info(dev,
"wrong type in WEP, not WEP40 and WEP104\n");
@@ -821,17 +820,13 @@
}
if (wrqu->retry.flags & IW_RETRY_MAX) {
priv->retry_rts = wrqu->retry.value;
- DMESG("Setting retry for RTS/CTS data to %d",
- wrqu->retry.value);
} else {
priv->retry_data = wrqu->retry.value;
- DMESG("Setting retry for non RTS/CTS data to %d",
- wrqu->retry.value);
}
- rtl8192_commit(dev);
+ rtl92e_commit(dev);
exit:
up(&priv->wx_sem);
@@ -917,7 +912,7 @@
priv->rtllib->wx_set_enc = 1;
down(&priv->rtllib->ips_sem);
- IPSLeave(dev);
+ rtl92e_ips_leave(dev);
up(&priv->rtllib->ips_sem);
ret = rtllib_wx_set_encode_ext(ieee, info, wrqu, extra);
@@ -933,7 +928,7 @@
ext->alg == IW_ENCODE_ALG_NONE) {
ieee->pairwise_key_type = ieee->group_key_type
= KEY_TYPE_NA;
- CamResetAllEntry(dev);
+ rtl92e_cam_reset(dev);
memset(priv->rtllib->swcamtable, 0,
sizeof(struct sw_cam_table) * 32);
goto end_hw_sec;
@@ -950,28 +945,29 @@
if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
alg = KEY_TYPE_WEP104;
ieee->pairwise_key_type = alg;
- EnableHWSecurityConfig8192(dev);
+ rtl92e_enable_hw_security_config(dev);
}
memcpy((u8 *)key, ext->key, 16);
if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
if (ext->key_len == 13)
ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
- setKey(dev, idx, idx, alg, zero, 0, key);
- set_swcam(dev, idx, idx, alg, zero, 0, key, 0);
+ rtl92e_set_key(dev, idx, idx, alg, zero, 0, key);
+ rtl92e_set_swcam(dev, idx, idx, alg, zero, 0, key, 0);
} else if (group) {
ieee->group_key_type = alg;
- setKey(dev, idx, idx, alg, broadcast_addr, 0, key);
- set_swcam(dev, idx, idx, alg, broadcast_addr, 0,
- key, 0);
+ rtl92e_set_key(dev, idx, idx, alg, broadcast_addr, 0,
+ key);
+ rtl92e_set_swcam(dev, idx, idx, alg, broadcast_addr, 0,
+ key, 0);
} else {
if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) &&
ieee->pHTInfo->bCurrentHTSupport)
- write_nic_byte(dev, 0x173, 1);
- setKey(dev, 4, idx, alg, (u8 *)ieee->ap_mac_addr,
- 0, key);
- set_swcam(dev, 4, idx, alg, (u8 *)ieee->ap_mac_addr,
- 0, key, 0);
+ rtl92e_writeb(dev, 0x173, 1);
+ rtl92e_set_key(dev, 4, idx, alg,
+ (u8 *)ieee->ap_mac_addr, 0, key);
+ rtl92e_set_swcam(dev, 4, idx, alg,
+ (u8 *)ieee->ap_mac_addr, 0, key, 0);
}
@@ -1119,41 +1115,41 @@
}
-#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT]
+#define IW_IOCTL(x) ((x) - SIOCSIWCOMMIT)
static iw_handler r8192_wx_handlers[] = {
- IW_IOCTL(SIOCGIWNAME) = r8192_wx_get_name,
- IW_IOCTL(SIOCSIWFREQ) = r8192_wx_set_freq,
- IW_IOCTL(SIOCGIWFREQ) = r8192_wx_get_freq,
- IW_IOCTL(SIOCSIWMODE) = r8192_wx_set_mode,
- IW_IOCTL(SIOCGIWMODE) = r8192_wx_get_mode,
- IW_IOCTL(SIOCSIWSENS) = r8192_wx_set_sens,
- IW_IOCTL(SIOCGIWSENS) = r8192_wx_get_sens,
- IW_IOCTL(SIOCGIWRANGE) = rtl8192_wx_get_range,
- IW_IOCTL(SIOCSIWAP) = r8192_wx_set_wap,
- IW_IOCTL(SIOCGIWAP) = r8192_wx_get_wap,
- IW_IOCTL(SIOCSIWSCAN) = r8192_wx_set_scan,
- IW_IOCTL(SIOCGIWSCAN) = r8192_wx_get_scan,
- IW_IOCTL(SIOCSIWESSID) = r8192_wx_set_essid,
- IW_IOCTL(SIOCGIWESSID) = r8192_wx_get_essid,
- IW_IOCTL(SIOCSIWNICKN) = r8192_wx_set_nick,
- IW_IOCTL(SIOCGIWNICKN) = r8192_wx_get_nick,
- IW_IOCTL(SIOCSIWRATE) = r8192_wx_set_rate,
- IW_IOCTL(SIOCGIWRATE) = r8192_wx_get_rate,
- IW_IOCTL(SIOCSIWRTS) = r8192_wx_set_rts,
- IW_IOCTL(SIOCGIWRTS) = r8192_wx_get_rts,
- IW_IOCTL(SIOCSIWFRAG) = r8192_wx_set_frag,
- IW_IOCTL(SIOCGIWFRAG) = r8192_wx_get_frag,
- IW_IOCTL(SIOCSIWRETRY) = r8192_wx_set_retry,
- IW_IOCTL(SIOCGIWRETRY) = r8192_wx_get_retry,
- IW_IOCTL(SIOCSIWENCODE) = r8192_wx_set_enc,
- IW_IOCTL(SIOCGIWENCODE) = r8192_wx_get_enc,
- IW_IOCTL(SIOCSIWPOWER) = r8192_wx_set_power,
- IW_IOCTL(SIOCGIWPOWER) = r8192_wx_get_power,
- IW_IOCTL(SIOCSIWGENIE) = r8192_wx_set_gen_ie,
- IW_IOCTL(SIOCGIWGENIE) = r8192_wx_get_gen_ie,
- IW_IOCTL(SIOCSIWMLME) = r8192_wx_set_mlme,
- IW_IOCTL(SIOCSIWAUTH) = r8192_wx_set_auth,
- IW_IOCTL(SIOCSIWENCODEEXT) = r8192_wx_set_enc_ext,
+ [IW_IOCTL(SIOCGIWNAME)] = r8192_wx_get_name,
+ [IW_IOCTL(SIOCSIWFREQ)] = r8192_wx_set_freq,
+ [IW_IOCTL(SIOCGIWFREQ)] = r8192_wx_get_freq,
+ [IW_IOCTL(SIOCSIWMODE)] = r8192_wx_set_mode,
+ [IW_IOCTL(SIOCGIWMODE)] = r8192_wx_get_mode,
+ [IW_IOCTL(SIOCSIWSENS)] = r8192_wx_set_sens,
+ [IW_IOCTL(SIOCGIWSENS)] = r8192_wx_get_sens,
+ [IW_IOCTL(SIOCGIWRANGE)] = rtl8192_wx_get_range,
+ [IW_IOCTL(SIOCSIWAP)] = r8192_wx_set_wap,
+ [IW_IOCTL(SIOCGIWAP)] = r8192_wx_get_wap,
+ [IW_IOCTL(SIOCSIWSCAN)] = r8192_wx_set_scan,
+ [IW_IOCTL(SIOCGIWSCAN)] = r8192_wx_get_scan,
+ [IW_IOCTL(SIOCSIWESSID)] = r8192_wx_set_essid,
+ [IW_IOCTL(SIOCGIWESSID)] = r8192_wx_get_essid,
+ [IW_IOCTL(SIOCSIWNICKN)] = r8192_wx_set_nick,
+ [IW_IOCTL(SIOCGIWNICKN)] = r8192_wx_get_nick,
+ [IW_IOCTL(SIOCSIWRATE)] = r8192_wx_set_rate,
+ [IW_IOCTL(SIOCGIWRATE)] = r8192_wx_get_rate,
+ [IW_IOCTL(SIOCSIWRTS)] = r8192_wx_set_rts,
+ [IW_IOCTL(SIOCGIWRTS)] = r8192_wx_get_rts,
+ [IW_IOCTL(SIOCSIWFRAG)] = r8192_wx_set_frag,
+ [IW_IOCTL(SIOCGIWFRAG)] = r8192_wx_get_frag,
+ [IW_IOCTL(SIOCSIWRETRY)] = r8192_wx_set_retry,
+ [IW_IOCTL(SIOCGIWRETRY)] = r8192_wx_get_retry,
+ [IW_IOCTL(SIOCSIWENCODE)] = r8192_wx_set_enc,
+ [IW_IOCTL(SIOCGIWENCODE)] = r8192_wx_get_enc,
+ [IW_IOCTL(SIOCSIWPOWER)] = r8192_wx_set_power,
+ [IW_IOCTL(SIOCGIWPOWER)] = r8192_wx_get_power,
+ [IW_IOCTL(SIOCSIWGENIE)] = r8192_wx_set_gen_ie,
+ [IW_IOCTL(SIOCGIWGENIE)] = r8192_wx_get_gen_ie,
+ [IW_IOCTL(SIOCSIWMLME)] = r8192_wx_set_mlme,
+ [IW_IOCTL(SIOCSIWAUTH)] = r8192_wx_set_auth,
+ [IW_IOCTL(SIOCSIWENCODEEXT)] = r8192_wx_set_enc_ext,
};
/* the following rule need to be following,
diff --git a/drivers/staging/rtl8192e/rtl819x_BA.h b/drivers/staging/rtl8192e/rtl819x_BA.h
index 613e14c..8946664 100644
--- a/drivers/staging/rtl8192e/rtl819x_BA.h
+++ b/drivers/staging/rtl8192e/rtl819x_BA.h
@@ -19,11 +19,7 @@
#ifndef _BATYPE_H_
#define _BATYPE_H_
-#define TOTAL_TXBA_NUM 16
-#define TOTAL_RXBA_NUM 16
-
#define BA_SETUP_TIMEOUT 200
-#define BA_INACT_TIMEOUT 60000
#define BA_POLICY_DELAYED 0
#define BA_POLICY_IMMEDIATE 1
@@ -32,7 +28,6 @@
#define ADDBA_STATUS_REFUSED 37
#define ADDBA_STATUS_INVALID_PARAM 38
-#define DELBA_REASON_QSTA_LEAVING 36
#define DELBA_REASON_END_BA 37
#define DELBA_REASON_UNKNOWN_BA 38
#define DELBA_REASON_TIMEOUT 39
diff --git a/drivers/staging/rtl8192e/rtl819x_BAProc.c b/drivers/staging/rtl8192e/rtl819x_BAProc.c
index 60f536c..78ede4a 100644
--- a/drivers/staging/rtl8192e/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_BAProc.c
@@ -428,7 +428,6 @@
{
struct rtllib_hdr_3addr *delba = NULL;
union delba_param_set *pDelBaParamSet = NULL;
- u16 *pReasonCode = NULL;
u8 *dst = NULL;
if (skb->len < sizeof(struct rtllib_hdr_3addr) + 6) {
@@ -453,9 +452,7 @@
#endif
delba = (struct rtllib_hdr_3addr *)skb->data;
dst = (u8 *)(&delba->addr2[0]);
- delba += sizeof(struct rtllib_hdr_3addr);
- pDelBaParamSet = (union delba_param_set *)(delba+2);
- pReasonCode = (u16 *)(delba+4);
+ pDelBaParamSet = (union delba_param_set *)&delba->payload[2];
if (pDelBaParamSet->field.Initiator == 1) {
struct rx_ts_record *pRxTs;
diff --git a/drivers/staging/rtl8192e/rtl819x_HT.h b/drivers/staging/rtl8192e/rtl819x_HT.h
index 0c263d9..51711dc 100644
--- a/drivers/staging/rtl8192e/rtl819x_HT.h
+++ b/drivers/staging/rtl8192e/rtl819x_HT.h
@@ -20,8 +20,6 @@
#define _RTL819XU_HTTYPE_H_
#define MIMO_PS_STATIC 0
-#define MIMO_PS_DYNAMIC 1
-#define MIMO_PS_NOLIMIT 3
#define sHTCLng 4
diff --git a/drivers/staging/rtl8192e/rtl819x_HTProc.c b/drivers/staging/rtl8192e/rtl819x_HTProc.c
index b5c3647..555745b 100644
--- a/drivers/staging/rtl8192e/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_HTProc.c
@@ -117,7 +117,7 @@
pHTInfo->RxReorderPendingTime = 30;
}
-u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate)
+static u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate)
{
struct rt_hi_throughput *pHTInfo = ieee->pHTInfo;
@@ -502,7 +502,8 @@
return mcsRate | 0x80;
}
-u8 HTFilterMCSRate(struct rtllib_device *ieee, u8 *pSupportMCS, u8 *pOperateMCS)
+static u8 HTFilterMCSRate(struct rtllib_device *ieee, u8 *pSupportMCS,
+ u8 *pOperateMCS)
{
u8 i;
diff --git a/drivers/staging/rtl8192e/rtl819x_Qos.h b/drivers/staging/rtl8192e/rtl819x_Qos.h
index 3aa35ce..fcc8fab 100644
--- a/drivers/staging/rtl8192e/rtl819x_Qos.h
+++ b/drivers/staging/rtl8192e/rtl819x_Qos.h
@@ -96,11 +96,6 @@
u16 Length;
};
-enum ack_policy {
- eAckPlc0_ACK = 0x00,
- eAckPlc1_NoACK = 0x01,
-};
-
#define AC0_BE 0
#define AC1_BK 1
#define AC2_VI 2
diff --git a/drivers/staging/rtl8192e/rtl819x_TS.h b/drivers/staging/rtl8192e/rtl819x_TS.h
index b8fed55..a93348c 100644
--- a/drivers/staging/rtl8192e/rtl819x_TS.h
+++ b/drivers/staging/rtl8192e/rtl819x_TS.h
@@ -19,8 +19,6 @@
#ifndef _TSTYPE_H_
#define _TSTYPE_H_
#include "rtl819x_Qos.h"
-#define TS_SETUP_TIMEOUT 60
-#define TS_INACT_TIMEOUT 60
#define TS_ADDBA_DELAY 60
#define TOTAL_TS_NUM 16
diff --git a/drivers/staging/rtl8192e/rtl819x_TSProc.c b/drivers/staging/rtl8192e/rtl819x_TSProc.c
index 05aea43..70879594 100644
--- a/drivers/staging/rtl8192e/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192e/rtl819x_TSProc.c
@@ -113,7 +113,7 @@
static void ResetTsCommonInfo(struct ts_common_info *pTsCommonInfo)
{
- memset(pTsCommonInfo->Addr, 0, 6);
+ eth_zero_addr(pTsCommonInfo->Addr);
memset(&pTsCommonInfo->TSpec, 0, sizeof(union tspec_body));
memset(&pTsCommonInfo->TClass, 0, sizeof(union qos_tclas)*TCLAS_NUM);
pTsCommonInfo->TClasProc = 0;
diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h
index fd38c6d..563ac12 100644
--- a/drivers/staging/rtl8192e/rtllib.h
+++ b/drivers/staging/rtl8192e/rtllib.h
@@ -84,9 +84,6 @@
#define iwe_stream_add_point_rsl(info, start, stop, iwe, p) \
iwe_stream_add_point(info, start, stop, iwe, p)
-#define usb_alloc_urb_rsl(x, y) usb_alloc_urb(x, y)
-#define usb_submit_urb_rsl(x, y) usb_submit_urb(x, y)
-
static inline void *netdev_priv_rsl(struct net_device *dev)
{
return netdev_priv(dev);
@@ -110,27 +107,14 @@
#define HIGH_QUEUE 7
#define BEACON_QUEUE 8
-#define LOW_QUEUE BE_QUEUE
-#define NORMAL_QUEUE MGNT_QUEUE
-
#ifndef IW_MODE_MESH
#define IW_MODE_MESH 7
#endif
-#define AMSDU_SUBHEADER_LEN 14
-#define SWRF_TIMEOUT 50
#define IE_CISCO_FLAG_POSITION 0x08
#define SUPPORT_CKIP_MIC 0x08
#define SUPPORT_CKIP_PK 0x10
-#define RT_RF_OFF_LEVL_ASPM BIT0
-#define RT_RF_OFF_LEVL_CLK_REQ BIT1
-#define RT_RF_OFF_LEVL_PCI_D3 BIT2
#define RT_RF_OFF_LEVL_HALT_NIC BIT3
-#define RT_RF_OFF_LEVL_FREE_FW BIT4
-#define RT_RF_OFF_LEVL_FW_32K BIT5
-#define RT_RF_PS_LEVEL_ALWAYS_ASPM BIT6
-#define RT_RF_LPS_DISALBE_2R BIT30
-#define RT_RF_LPS_LEVEL_ASPM BIT31
#define RT_IN_PS_LEVEL(pPSC, _PS_FLAG) \
((pPSC->CurPsLevel & _PS_FLAG) ? true : false)
#define RT_CLEAR_PS_LEVEL(pPSC, _PS_FLAG) \
@@ -244,22 +228,6 @@
#define MGN_MCS13 0x8d
#define MGN_MCS14 0x8e
#define MGN_MCS15 0x8f
-#define MGN_MCS0_SG 0x90
-#define MGN_MCS1_SG 0x91
-#define MGN_MCS2_SG 0x92
-#define MGN_MCS3_SG 0x93
-#define MGN_MCS4_SG 0x94
-#define MGN_MCS5_SG 0x95
-#define MGN_MCS6_SG 0x96
-#define MGN_MCS7_SG 0x97
-#define MGN_MCS8_SG 0x98
-#define MGN_MCS9_SG 0x99
-#define MGN_MCS10_SG 0x9a
-#define MGN_MCS11_SG 0x9b
-#define MGN_MCS12_SG 0x9c
-#define MGN_MCS13_SG 0x9d
-#define MGN_MCS14_SG 0x9e
-#define MGN_MCS15_SG 0x9f
enum hw_variables {
HW_VAR_ETHER_ADDR,
@@ -722,42 +690,13 @@
u8 dst_addr[ETH_ALEN];
};
-struct rtllib_stats {
- unsigned int tx_unicast_frames;
- unsigned int tx_multicast_frames;
- unsigned int tx_fragments;
- unsigned int tx_unicast_octets;
- unsigned int tx_multicast_octets;
- unsigned int tx_deferred_transmissions;
- unsigned int tx_single_retry_frames;
- unsigned int tx_multiple_retry_frames;
- unsigned int tx_retry_limit_exceeded;
- unsigned int tx_discards;
- unsigned int rx_unicast_frames;
- unsigned int rx_multicast_frames;
- unsigned int rx_fragments;
- unsigned int rx_unicast_octets;
- unsigned int rx_multicast_octets;
- unsigned int rx_fcs_errors;
- unsigned int rx_discards_no_buffer;
- unsigned int tx_discards_wrong_sa;
- unsigned int rx_discards_undecryptable;
- unsigned int rx_message_in_msg_fragments;
- unsigned int rx_message_in_bad_msg_fragments;
-};
-
struct rtllib_device;
-#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_ENCRYPT (1<<9)
#define SEC_LEVEL_0 0 /* None */
#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */
@@ -772,7 +711,6 @@
#define WEP_KEY_LEN 13
#define SCM_KEY_LEN 32
-#define SCM_TEMPORAL_KEY_LENGTH 16
struct rtllib_security {
u16 active_key:2,
@@ -1187,8 +1125,6 @@
#define WME_AC_BE 0x01
#define WME_AC_VI 0x02
#define WME_AC_VO 0x03
-#define WME_ACI_MASK 0x03
-#define WME_AIFSN_MASK 0x03
#define WME_AC_PRAM_LEN 16
#define MAX_RECEIVE_BUFFER_SIZE 9100
@@ -1204,12 +1140,6 @@
#define ETHERNET_HEADER_SIZE 14 /* length of two Ethernet address
* plus ether type*/
-struct ether_header {
- u8 ether_dhost[ETHER_ADDR_LEN];
- u8 ether_shost[ETHER_ADDR_LEN];
- u16 ether_type;
-} __packed;
-
enum erp_t {
ERP_NonERPpresent = 0x01,
ERP_UseProtection = 0x02,
@@ -1591,7 +1521,6 @@
/* Bookkeeping structures */
struct net_device_stats stats;
- struct rtllib_stats ieee_stats;
struct rtllib_softmac_stats softmac_stats;
/* Probe / Beacon management */
@@ -1673,7 +1602,6 @@
int short_slot;
int mode; /* A, B, G */
int modulation; /* CCK, OFDM */
- int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */
/* used for forcing the ibss workqueue to terminate
* without wait for the syncro scan to terminate
@@ -2056,244 +1984,199 @@
/* rtllib.c */
-extern void free_rtllib(struct net_device *dev);
-extern struct net_device *alloc_rtllib(int sizeof_priv);
+void free_rtllib(struct net_device *dev);
+struct net_device *alloc_rtllib(int sizeof_priv);
/* rtllib_tx.c */
-extern int rtllib_encrypt_fragment(
+int rtllib_encrypt_fragment(
struct rtllib_device *ieee,
struct sk_buff *frag,
int hdr_len);
-extern int rtllib_xmit(struct sk_buff *skb, struct net_device *dev);
-extern int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev);
-extern void rtllib_txb_free(struct rtllib_txb *);
+int rtllib_xmit(struct sk_buff *skb, struct net_device *dev);
+void rtllib_txb_free(struct rtllib_txb *);
/* rtllib_rx.c */
-extern int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
- struct rtllib_rx_stats *rx_stats);
-extern void rtllib_rx_mgt(struct rtllib_device *ieee,
- struct sk_buff *skb,
- struct rtllib_rx_stats *stats);
-extern void rtllib_rx_probe_rq(struct rtllib_device *ieee,
- struct sk_buff *skb);
-extern int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel);
+int rtllib_rx(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats);
+void rtllib_rx_probe_rq(struct rtllib_device *ieee,
+ struct sk_buff *skb);
+int rtllib_legal_channel(struct rtllib_device *rtllib, u8 channel);
/* rtllib_wx.c */
-extern int rtllib_wx_get_scan(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int rtllib_wx_set_encode(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int rtllib_wx_get_encode(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_set_auth(struct rtllib_device *ieee,
- struct iw_request_info *info,
- struct iw_param *data, char *extra);
-extern int rtllib_wx_set_mlme(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len);
+int rtllib_wx_get_scan(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key);
+int rtllib_wx_set_encode(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key);
+int rtllib_wx_get_encode(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key);
+int rtllib_wx_set_encode_ext(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_auth(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra);
+int rtllib_wx_set_mlme(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_gen_ie(struct rtllib_device *ieee, u8 *ie, size_t len);
/* rtllib_softmac.c */
-extern short rtllib_is_54g(struct rtllib_network *net);
-extern int rtllib_rx_frame_softmac(struct rtllib_device *ieee,
- struct sk_buff *skb,
- struct rtllib_rx_stats *rx_stats, u16 type,
- u16 stype);
-extern void rtllib_softmac_new_net(struct rtllib_device *ieee,
- struct rtllib_network *net);
+int rtllib_rx_frame_softmac(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *rx_stats, u16 type,
+ u16 stype);
+void rtllib_softmac_new_net(struct rtllib_device *ieee,
+ struct rtllib_network *net);
void SendDisassociation(struct rtllib_device *ieee, bool deauth, u16 asRsn);
-extern void rtllib_softmac_xmit(struct rtllib_txb *txb,
- struct rtllib_device *ieee);
+void rtllib_softmac_xmit(struct rtllib_txb *txb, struct rtllib_device *ieee);
-extern void rtllib_stop_send_beacons(struct rtllib_device *ieee);
-extern void notify_wx_assoc_event(struct rtllib_device *ieee);
-extern void rtllib_softmac_check_all_nets(struct rtllib_device *ieee);
-extern void rtllib_start_bss(struct rtllib_device *ieee);
-extern void rtllib_start_master_bss(struct rtllib_device *ieee);
-extern void rtllib_start_ibss(struct rtllib_device *ieee);
-extern void rtllib_softmac_init(struct rtllib_device *ieee);
-extern void rtllib_softmac_free(struct rtllib_device *ieee);
-extern void rtllib_associate_abort(struct rtllib_device *ieee);
-extern void rtllib_disassociate(struct rtllib_device *ieee);
-extern void rtllib_stop_scan(struct rtllib_device *ieee);
-extern bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan);
-extern void rtllib_stop_scan_syncro(struct rtllib_device *ieee);
-extern void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
-extern void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee,
- short pwr);
-extern void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl);
-extern void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee);
-extern void rtllib_start_protocol(struct rtllib_device *ieee);
-extern void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown);
+void rtllib_stop_send_beacons(struct rtllib_device *ieee);
+void notify_wx_assoc_event(struct rtllib_device *ieee);
+void rtllib_start_ibss(struct rtllib_device *ieee);
+void rtllib_softmac_init(struct rtllib_device *ieee);
+void rtllib_softmac_free(struct rtllib_device *ieee);
+void rtllib_disassociate(struct rtllib_device *ieee);
+void rtllib_stop_scan(struct rtllib_device *ieee);
+bool rtllib_act_scanning(struct rtllib_device *ieee, bool sync_scan);
+void rtllib_stop_scan_syncro(struct rtllib_device *ieee);
+void rtllib_start_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
+void rtllib_sta_ps_send_null_frame(struct rtllib_device *ieee, short pwr);
+void rtllib_sta_ps_send_pspoll_frame(struct rtllib_device *ieee);
+void rtllib_start_protocol(struct rtllib_device *ieee);
+void rtllib_stop_protocol(struct rtllib_device *ieee, u8 shutdown);
-extern void rtllib_EnableNetMonitorMode(struct net_device *dev,
+void rtllib_EnableNetMonitorMode(struct net_device *dev, bool bInitState);
+void rtllib_DisableNetMonitorMode(struct net_device *dev, bool bInitState);
+void rtllib_EnableIntelPromiscuousMode(struct net_device *dev, bool bInitState);
+void rtllib_DisableIntelPromiscuousMode(struct net_device *dev,
bool bInitState);
-extern void rtllib_DisableNetMonitorMode(struct net_device *dev,
- bool bInitState);
-extern void rtllib_EnableIntelPromiscuousMode(struct net_device *dev,
- bool bInitState);
-extern void rtllib_DisableIntelPromiscuousMode(struct net_device *dev,
- bool bInitState);
-extern void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh);
+void rtllib_softmac_stop_protocol(struct rtllib_device *ieee,
+ u8 mesh_flag, u8 shutdown);
+void rtllib_softmac_start_protocol(struct rtllib_device *ieee, u8 mesh_flag);
-extern void rtllib_softmac_stop_protocol(struct rtllib_device *ieee,
- u8 mesh_flag, u8 shutdown);
-extern void rtllib_softmac_start_protocol(struct rtllib_device *ieee,
- u8 mesh_flag);
+void rtllib_reset_queue(struct rtllib_device *ieee);
+void rtllib_wake_all_queues(struct rtllib_device *ieee);
+void rtllib_stop_all_queues(struct rtllib_device *ieee);
+struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee);
+void rtllib_start_send_beacons(struct rtllib_device *ieee);
+void rtllib_stop_send_beacons(struct rtllib_device *ieee);
+int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee,
+ struct iw_point *p, u8 is_mesh);
-extern void rtllib_reset_queue(struct rtllib_device *ieee);
-extern void rtllib_wake_all_queues(struct rtllib_device *ieee);
-extern void rtllib_stop_all_queues(struct rtllib_device *ieee);
-extern struct sk_buff *rtllib_get_beacon(struct rtllib_device *ieee);
-extern void rtllib_start_send_beacons(struct rtllib_device *ieee);
-extern void rtllib_stop_send_beacons(struct rtllib_device *ieee);
-extern int rtllib_wpa_supplicant_ioctl(struct rtllib_device *ieee,
- struct iw_point *p, u8 is_mesh);
+void notify_wx_assoc_event(struct rtllib_device *ieee);
+void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success);
-extern void notify_wx_assoc_event(struct rtllib_device *ieee);
-extern void rtllib_ps_tx_ack(struct rtllib_device *ieee, short success);
-
-extern void softmac_mgmt_xmit(struct sk_buff *skb,
- struct rtllib_device *ieee);
-extern u16 rtllib_query_seqnum(struct rtllib_device *ieee,
- struct sk_buff *skb, u8 *dst);
-extern u8 rtllib_ap_sec_type(struct rtllib_device *ieee);
+void softmac_mgmt_xmit(struct sk_buff *skb, struct rtllib_device *ieee);
+u8 rtllib_ap_sec_type(struct rtllib_device *ieee);
/* rtllib_softmac_wx.c */
-extern int rtllib_wx_get_wap(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *ext);
+int rtllib_wx_get_wap(struct rtllib_device *ieee, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *ext);
-extern int rtllib_wx_set_wap(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra);
+int rtllib_wx_set_wap(struct rtllib_device *ieee, struct iw_request_info *info,
+ union iwreq_data *awrq, char *extra);
-extern int rtllib_wx_get_essid(struct rtllib_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int rtllib_wx_get_essid(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int rtllib_wx_set_rate(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_rate(struct rtllib_device *ieee, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_get_rate(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int rtllib_wx_get_rate(struct rtllib_device *ieee, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_set_mode(struct rtllib_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int rtllib_wx_set_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int rtllib_wx_set_scan(struct rtllib_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int rtllib_wx_set_scan(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int rtllib_wx_set_essid(struct rtllib_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_essid(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_get_mode(struct rtllib_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int rtllib_wx_get_mode(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int rtllib_wx_set_freq(struct rtllib_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int rtllib_wx_set_freq(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int rtllib_wx_get_freq(struct rtllib_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
-extern void rtllib_wx_sync_scan_wq(void *data);
+int rtllib_wx_get_freq(struct rtllib_device *ieee, struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
+void rtllib_wx_sync_scan_wq(void *data);
-extern int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_rawtx(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_get_name(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int rtllib_wx_get_name(struct rtllib_device *ieee, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_set_power(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_power(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_get_power(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int rtllib_wx_get_power(struct rtllib_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_set_rts(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int rtllib_wx_set_rts(struct rtllib_device *ieee, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int rtllib_wx_get_rts(struct rtllib_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int rtllib_wx_get_rts(struct rtllib_device *ieee, struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
#define MAX_RECEIVE_BUFFER_SIZE 9100
void HTSetConnectBwMode(struct rtllib_device *ieee,
enum ht_channel_width Bandwidth,
enum ht_extchnl_offset Offset);
-extern void HTUpdateDefaultSetting(struct rtllib_device *ieee);
-extern void HTConstructCapabilityElement(struct rtllib_device *ieee,
- u8 *posHTCap, u8 *len,
- u8 isEncrypt, bool bAssoc);
-extern void HTConstructInfoElement(struct rtllib_device *ieee,
- u8 *posHTInfo, u8 *len, u8 isEncrypt);
-extern void HTConstructRT2RTAggElement(struct rtllib_device *ieee,
- u8 *posRT2RTAgg, u8 *len);
-extern void HTOnAssocRsp(struct rtllib_device *ieee);
-extern void HTInitializeHTInfo(struct rtllib_device *ieee);
-extern void HTInitializeBssDesc(struct bss_ht *pBssHT);
-extern void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee,
- struct rtllib_network *pNetwork);
-extern void HT_update_self_and_peer_setting(struct rtllib_device *ieee,
- struct rtllib_network *pNetwork);
-extern u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
- u8 *pMCSFilter);
+void HTUpdateDefaultSetting(struct rtllib_device *ieee);
+void HTConstructCapabilityElement(struct rtllib_device *ieee,
+ u8 *posHTCap, u8 *len,
+ u8 isEncrypt, bool bAssoc);
+void HTConstructInfoElement(struct rtllib_device *ieee,
+ u8 *posHTInfo, u8 *len, u8 isEncrypt);
+void HTConstructRT2RTAggElement(struct rtllib_device *ieee,
+ u8 *posRT2RTAgg, u8 *len);
+void HTOnAssocRsp(struct rtllib_device *ieee);
+void HTInitializeHTInfo(struct rtllib_device *ieee);
+void HTInitializeBssDesc(struct bss_ht *pBssHT);
+void HTResetSelfAndSavePeerSetting(struct rtllib_device *ieee,
+ struct rtllib_network *pNetwork);
+void HT_update_self_and_peer_setting(struct rtllib_device *ieee,
+ struct rtllib_network *pNetwork);
+u8 HTGetHighestMCSRate(struct rtllib_device *ieee, u8 *pMCSRateSet,
+ u8 *pMCSFilter);
extern u8 MCS_FILTER_ALL[];
extern u16 MCS_DATA_RATE[2][2][77];
-extern u8 HTCCheck(struct rtllib_device *ieee, u8 *pFrame);
-extern void HTResetIOTSetting(struct rt_hi_throughput *pHTInfo);
-extern bool IsHTHalfNmodeAPs(struct rtllib_device *ieee);
-extern u16 HTMcsToDataRate(struct rtllib_device *ieee, u8 nMcsRate);
-extern u16 TxCountToDataRate(struct rtllib_device *ieee, u8 nDataRate);
-extern int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb);
-extern int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb);
-extern int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb);
-extern void TsInitAddBA(struct rtllib_device *ieee, struct tx_ts_record *pTS,
- u8 Policy, u8 bOverwritePending);
-extern void TsInitDelBA(struct rtllib_device *ieee,
- struct ts_common_info *pTsCommonInfo,
- enum tr_select TxRxSelect);
-extern void BaSetupTimeOut(unsigned long data);
-extern void TxBaInactTimeout(unsigned long data);
-extern void RxBaInactTimeout(unsigned long data);
-extern void ResetBaEntry(struct ba_record *pBA);
-extern bool GetTs(
- struct rtllib_device *ieee,
- struct ts_common_info **ppTS,
- u8 *Addr,
- u8 TID,
- enum tr_select TxRxSelect,
- bool bAddNewTs
-);
-extern void TSInitialize(struct rtllib_device *ieee);
-extern void TsStartAddBaProcess(struct rtllib_device *ieee,
- struct tx_ts_record *pTxTS);
-extern void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr);
-extern void RemoveAllTS(struct rtllib_device *ieee);
-void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh);
+u8 HTCCheck(struct rtllib_device *ieee, u8 *pFrame);
+void HTResetIOTSetting(struct rt_hi_throughput *pHTInfo);
+bool IsHTHalfNmodeAPs(struct rtllib_device *ieee);
+u16 TxCountToDataRate(struct rtllib_device *ieee, u8 nDataRate);
+int rtllib_rx_ADDBAReq(struct rtllib_device *ieee, struct sk_buff *skb);
+int rtllib_rx_ADDBARsp(struct rtllib_device *ieee, struct sk_buff *skb);
+int rtllib_rx_DELBA(struct rtllib_device *ieee, struct sk_buff *skb);
+void TsInitAddBA(struct rtllib_device *ieee, struct tx_ts_record *pTS,
+ u8 Policy, u8 bOverwritePending);
+void TsInitDelBA(struct rtllib_device *ieee,
+ struct ts_common_info *pTsCommonInfo,
+ enum tr_select TxRxSelect);
+void BaSetupTimeOut(unsigned long data);
+void TxBaInactTimeout(unsigned long data);
+void RxBaInactTimeout(unsigned long data);
+void ResetBaEntry(struct ba_record *pBA);
+bool GetTs(struct rtllib_device *ieee, struct ts_common_info **ppTS, u8 *Addr,
+ u8 TID, enum tr_select TxRxSelect, bool bAddNewTs);
+void TSInitialize(struct rtllib_device *ieee);
+void TsStartAddBaProcess(struct rtllib_device *ieee,
+ struct tx_ts_record *pTxTS);
+void RemovePeerTS(struct rtllib_device *ieee, u8 *Addr);
+void RemoveAllTS(struct rtllib_device *ieee);
extern const long rtllib_wlan_frequencies[];
@@ -2317,23 +2200,19 @@
/* For the function is more related to hardware setting, it's better to use the
* ieee handler to refer to it.
*/
-extern void rtllib_update_active_chan_map(struct rtllib_device *ieee);
-extern void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee,
- struct rx_ts_record *pTS);
-extern int rtllib_parse_info_param(struct rtllib_device *ieee,
- struct rtllib_info_element *info_element,
- u16 length,
- struct rtllib_network *network,
- struct rtllib_rx_stats *stats);
+void rtllib_FlushRxTsPendingPkts(struct rtllib_device *ieee,
+ struct rx_ts_record *pTS);
+int rtllib_parse_info_param(struct rtllib_device *ieee,
+ struct rtllib_info_element *info_element,
+ u16 length,
+ struct rtllib_network *network,
+ struct rtllib_rx_stats *stats);
void rtllib_indicate_packets(struct rtllib_device *ieee,
struct rtllib_rxb **prxbIndicateArray, u8 index);
-extern u8 HTFilterMCSRate(struct rtllib_device *ieee, u8 *pSupportMCS,
- u8 *pOperateMCS);
-extern void HTUseDefaultSetting(struct rtllib_device *ieee);
+void HTUseDefaultSetting(struct rtllib_device *ieee);
#define RT_ASOC_RETRY_LIMIT 5
u8 MgntQuery_TxRateExcludeCCKRates(struct rtllib_device *ieee);
-extern void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p);
#define SEM_DOWN_IEEE_WX(psem) down(psem)
#define SEM_UP_IEEE_WX(psem) up(psem)
diff --git a/drivers/staging/rtl8192e/rtllib_debug.h b/drivers/staging/rtl8192e/rtllib_debug.h
index 42e88d6..17c276d 100644
--- a/drivers/staging/rtl8192e/rtllib_debug.h
+++ b/drivers/staging/rtl8192e/rtllib_debug.h
@@ -30,8 +30,6 @@
#define DRV_NAME "rtllib_92e"
#endif
-#define DMESG(x, a...)
-
extern u32 rt_global_debug_component;
/* These are the defines for rt_global_debug_component */
@@ -40,10 +38,7 @@
COMP_DBG = (1 << 1),
COMP_INIT = (1 << 2),
COMP_RECV = (1 << 3),
- COMP_SEND = (1 << 4),
- COMP_CMD = (1 << 5),
COMP_POWER = (1 << 6),
- COMP_EPROM = (1 << 7),
COMP_SWBW = (1 << 8),
COMP_SEC = (1 << 9),
COMP_LPS = (1 << 10),
@@ -58,15 +53,12 @@
COMP_CH = (1 << 19),
COMP_RF = (1 << 20),
COMP_FIRMWARE = (1 << 21),
- COMP_HT = (1 << 22),
COMP_RESET = (1 << 23),
COMP_CMDPKT = (1 << 24),
COMP_SCAN = (1 << 25),
COMP_PS = (1 << 26),
COMP_DOWN = (1 << 27),
COMP_INTR = (1 << 28),
- COMP_LED = (1 << 29),
- COMP_MLME = (1 << 30),
COMP_ERR = (1 << 31)
};
diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c
index da862c3d..09f0820 100644
--- a/drivers/staging/rtl8192e/rtllib_rx.c
+++ b/drivers/staging/rtl8192e/rtllib_rx.c
@@ -44,6 +44,9 @@
#include "rtllib.h"
#include "dot11d.h"
+static void rtllib_rx_mgt(struct rtllib_device *ieee, struct sk_buff *skb,
+ struct rtllib_rx_stats *stats);
+
static inline void rtllib_monitor_rx(struct rtllib_device *ieee,
struct sk_buff *skb,
struct rtllib_rx_stats *rx_status,
@@ -317,7 +320,6 @@
netdev_dbg(ieee->dev,
"Decryption failed ICV mismatch (key %d)\n",
skb->data[hdrlen + 3] >> 6);
- ieee->ieee_stats.rx_discards_undecryptable++;
return -1;
}
@@ -1077,7 +1079,6 @@
netdev_dbg(ieee->dev,
"Decryption failed (not set) (SA= %pM)\n",
hdr->addr2);
- ieee->ieee_stats.rx_discards_undecryptable++;
return -1;
}
}
@@ -1743,37 +1744,61 @@
return rc;
}
-#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
-
static const char *get_info_element_string(u16 id)
{
switch (id) {
- MFIE_STRING(SSID);
- MFIE_STRING(RATES);
- MFIE_STRING(FH_SET);
- MFIE_STRING(DS_SET);
- MFIE_STRING(CF_SET);
- MFIE_STRING(TIM);
- MFIE_STRING(IBSS_SET);
- MFIE_STRING(COUNTRY);
- MFIE_STRING(HOP_PARAMS);
- MFIE_STRING(HOP_TABLE);
- MFIE_STRING(REQUEST);
- MFIE_STRING(CHALLENGE);
- MFIE_STRING(POWER_CONSTRAINT);
- MFIE_STRING(POWER_CAPABILITY);
- MFIE_STRING(TPC_REQUEST);
- MFIE_STRING(TPC_REPORT);
- MFIE_STRING(SUPP_CHANNELS);
- MFIE_STRING(CSA);
- MFIE_STRING(MEASURE_REQUEST);
- MFIE_STRING(MEASURE_REPORT);
- MFIE_STRING(QUIET);
- MFIE_STRING(IBSS_DFS);
- MFIE_STRING(RSN);
- MFIE_STRING(RATES_EX);
- MFIE_STRING(GENERIC);
- MFIE_STRING(QOS_PARAMETER);
+ case MFIE_TYPE_SSID:
+ return "SSID";
+ case MFIE_TYPE_RATES:
+ return "RATES";
+ case MFIE_TYPE_FH_SET:
+ return "FH_SET";
+ case MFIE_TYPE_DS_SET:
+ return "DS_SET";
+ case MFIE_TYPE_CF_SET:
+ return "CF_SET";
+ case MFIE_TYPE_TIM:
+ return "TIM";
+ case MFIE_TYPE_IBSS_SET:
+ return "IBSS_SET";
+ case MFIE_TYPE_COUNTRY:
+ return "COUNTRY";
+ case MFIE_TYPE_HOP_PARAMS:
+ return "HOP_PARAMS";
+ case MFIE_TYPE_HOP_TABLE:
+ return "HOP_TABLE";
+ case MFIE_TYPE_REQUEST:
+ return "REQUEST";
+ case MFIE_TYPE_CHALLENGE:
+ return "CHALLENGE";
+ case MFIE_TYPE_POWER_CONSTRAINT:
+ return "POWER_CONSTRAINT";
+ case MFIE_TYPE_POWER_CAPABILITY:
+ return "POWER_CAPABILITY";
+ case MFIE_TYPE_TPC_REQUEST:
+ return "TPC_REQUEST";
+ case MFIE_TYPE_TPC_REPORT:
+ return "TPC_REPORT";
+ case MFIE_TYPE_SUPP_CHANNELS:
+ return "SUPP_CHANNELS";
+ case MFIE_TYPE_CSA:
+ return "CSA";
+ case MFIE_TYPE_MEASURE_REQUEST:
+ return "MEASURE_REQUEST";
+ case MFIE_TYPE_MEASURE_REPORT:
+ return "MEASURE_REPORT";
+ case MFIE_TYPE_QUIET:
+ return "QUIET";
+ case MFIE_TYPE_IBSS_DFS:
+ return "IBSS_DFS";
+ case MFIE_TYPE_RSN:
+ return "RSN";
+ case MFIE_TYPE_RATES_EX:
+ return "RATES_EX";
+ case MFIE_TYPE_GENERIC:
+ return "GENERIC";
+ case MFIE_TYPE_QOS_PARAMETER:
+ return "QOS_PARAMETER";
default:
return "UNKNOWN";
}
@@ -2717,9 +2742,9 @@
kfree(network);
}
-void rtllib_rx_mgt(struct rtllib_device *ieee,
- struct sk_buff *skb,
- struct rtllib_rx_stats *stats)
+static void rtllib_rx_mgt(struct rtllib_device *ieee,
+ struct sk_buff *skb,
+ struct rtllib_rx_stats *stats)
{
struct rtllib_hdr_4addr *header = (struct rtllib_hdr_4addr *)skb->data;
diff --git a/drivers/staging/rtl8192e/rtllib_softmac.c b/drivers/staging/rtl8192e/rtllib_softmac.c
index d320c31..1503cbb 100644
--- a/drivers/staging/rtl8192e/rtllib_softmac.c
+++ b/drivers/staging/rtl8192e/rtllib_softmac.c
@@ -23,7 +23,10 @@
#include <linux/ieee80211.h>
#include "dot11d.h"
-short rtllib_is_54g(struct rtllib_network *net)
+static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl);
+
+
+static short rtllib_is_54g(struct rtllib_network *net)
{
return (net->rates_ex_len > 0) || (net->rates_len > 4);
}
@@ -107,7 +110,7 @@
*tag_p = tag;
}
-void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p)
+static void rtllib_TURBO_Info(struct rtllib_device *ieee, u8 **tag_p)
{
u8 *tag = *tag_p;
@@ -369,7 +372,7 @@
return skb;
}
-struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee);
+static struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee);
static void rtllib_send_beacon(struct rtllib_device *ieee)
{
@@ -483,7 +486,7 @@
}
-void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh)
+static void rtllib_send_probe_requests(struct rtllib_device *ieee, u8 is_mesh)
{
if (ieee->active_scan && (ieee->softmac_features &
IEEE_SOFTMAC_PROBERQ)) {
@@ -492,7 +495,7 @@
}
}
-void rtllib_update_active_chan_map(struct rtllib_device *ieee)
+static void rtllib_update_active_chan_map(struct rtllib_device *ieee)
{
memcpy(ieee->active_channel_map, GET_DOT11D_INFO(ieee)->channel_map,
MAX_CHANNEL_NUMBER+1);
@@ -501,7 +504,7 @@
/* this performs syncro scan blocking the caller until all channels
* in the allowed channel map has been checked.
*/
-void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
+static void rtllib_softmac_scan_syncro(struct rtllib_device *ieee, u8 is_mesh)
{
union iwreq_data wrqu;
short ch = 0;
@@ -1401,7 +1404,7 @@
return skb;
}
-void rtllib_associate_abort(struct rtllib_device *ieee)
+static void rtllib_associate_abort(struct rtllib_device *ieee)
{
unsigned long flags;
@@ -1511,7 +1514,6 @@
}
}
-#define CANCELLED 2
static void rtllib_associate_complete_wq(void *data)
{
struct rtllib_device *ieee = (struct rtllib_device *)
@@ -1753,7 +1755,7 @@
}
}
-void rtllib_softmac_check_all_nets(struct rtllib_device *ieee)
+static void rtllib_softmac_check_all_nets(struct rtllib_device *ieee)
{
unsigned long flags;
struct rtllib_network *target;
@@ -2109,7 +2111,7 @@
}
-void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl)
+static void rtllib_sta_wakeup(struct rtllib_device *ieee, short nl)
{
if (ieee->sta_sleep == LPS_IS_WAKE) {
if (nl) {
@@ -2545,7 +2547,7 @@
}
/* called in user context only */
-void rtllib_start_master_bss(struct rtllib_device *ieee)
+static void rtllib_start_master_bss(struct rtllib_device *ieee)
{
ieee->assoc_id = 1;
@@ -2720,7 +2722,7 @@
}
/* this is called only in user context, with wx_sem held */
-void rtllib_start_bss(struct rtllib_device *ieee)
+static void rtllib_start_bss(struct rtllib_device *ieee)
{
unsigned long flags;
@@ -2817,7 +2819,7 @@
up(&ieee->wx_sem);
}
-struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee)
+static struct sk_buff *rtllib_get_beacon_(struct rtllib_device *ieee)
{
const u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
@@ -3084,7 +3086,7 @@
*/
netdev_info(ieee->dev, "%s WPA\n", value ? "enabling" : "disabling");
ieee->wpa_enabled = value;
- memset(ieee->ap_mac_addr, 0, 6);
+ eth_zero_addr(ieee->ap_mac_addr);
return 0;
}
diff --git a/drivers/staging/rtl8192e/rtllib_tx.c b/drivers/staging/rtl8192e/rtllib_tx.c
index e99ea5e..b992e46 100644
--- a/drivers/staging/rtl8192e/rtllib_tx.c
+++ b/drivers/staging/rtl8192e/rtllib_tx.c
@@ -151,7 +151,7 @@
static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
-inline int rtllib_put_snap(u8 *data, u16 h_proto)
+static int rtllib_put_snap(u8 *data, u16 h_proto)
{
struct rtllib_snap_hdr *snap;
u8 *oui;
@@ -205,7 +205,6 @@
if (res < 0) {
netdev_info(ieee->dev, "%s: Encryption failed: len=%d.\n",
ieee->dev->name, frag->len);
- ieee->ieee_stats.tx_discards++;
return -1;
}
@@ -515,8 +514,8 @@
}
}
-u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
- u8 *dst)
+static u16 rtllib_query_seqnum(struct rtllib_device *ieee, struct sk_buff *skb,
+ u8 *dst)
{
u16 seqnum = 0;
@@ -566,7 +565,7 @@
return ieee->rate & 0x7F;
}
-int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
+static int rtllib_xmit_inter(struct sk_buff *skb, struct net_device *dev)
{
struct rtllib_device *ieee = (struct rtllib_device *)
netdev_priv_rsl(dev);
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211.h b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
index 23af2aa..d481a26 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211.h
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211.h
@@ -2169,98 +2169,99 @@
/* ieee80211.c */
-extern void free_ieee80211(struct net_device *dev);
-extern struct net_device *alloc_ieee80211(int sizeof_priv);
+void free_ieee80211(struct net_device *dev);
+struct net_device *alloc_ieee80211(int sizeof_priv);
-extern int ieee80211_set_encryption(struct ieee80211_device *ieee);
+int ieee80211_set_encryption(struct ieee80211_device *ieee);
/* ieee80211_tx.c */
-extern int ieee80211_encrypt_fragment(
- struct ieee80211_device *ieee,
- struct sk_buff *frag,
- int hdr_len);
+int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
+ struct sk_buff *frag, int hdr_len);
-extern int ieee80211_xmit(struct sk_buff *skb,
- struct net_device *dev);
-extern void ieee80211_txb_free(struct ieee80211_txb *);
+int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev);
+void ieee80211_txb_free(struct ieee80211_txb *);
/* ieee80211_rx.c */
-extern int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
- struct ieee80211_rx_stats *rx_stats);
-extern void ieee80211_rx_mgt(struct ieee80211_device *ieee,
- struct rtl_80211_hdr_4addr *header,
- struct ieee80211_rx_stats *stats);
+int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+ struct ieee80211_rx_stats *rx_stats);
+void ieee80211_rx_mgt(struct ieee80211_device *ieee,
+ struct rtl_80211_hdr_4addr *header,
+ struct ieee80211_rx_stats *stats);
/* ieee80211_wx.c */
-extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *key);
-extern int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
+int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *key);
+int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
+ union iwreq_data *wrqu, char *key);
+int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- struct iw_param *data, char *extra);
-extern int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
+ union iwreq_data *wrqu, char *key);
+int ieee80211_wx_get_encode_ext(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_auth(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra);
+int ieee80211_wx_set_mlme(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len);
/* ieee80211_softmac.c */
-extern short ieee80211_is_54g(const struct ieee80211_network *net);
-extern short ieee80211_is_shortslot(const struct ieee80211_network *net);
-extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
- struct ieee80211_rx_stats *rx_stats, u16 type,
- u16 stype);
-extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net);
+short ieee80211_is_54g(const struct ieee80211_network *net);
+short ieee80211_is_shortslot(const struct ieee80211_network *net);
+int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee,
+ struct sk_buff *skb,
+ struct ieee80211_rx_stats *rx_stats,
+ u16 type, u16 stype);
+void ieee80211_softmac_new_net(struct ieee80211_device *ieee,
+ struct ieee80211_network *net);
void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, u8 asRsn);
-extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee);
+void ieee80211_softmac_xmit(struct ieee80211_txb *txb,
+ struct ieee80211_device *ieee);
-extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_master_bss(struct ieee80211_device *ieee);
-extern void ieee80211_start_ibss(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_init(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_free(struct ieee80211_device *ieee);
-extern void ieee80211_associate_abort(struct ieee80211_device *ieee);
-extern void ieee80211_disassociate(struct ieee80211_device *ieee);
-extern void ieee80211_stop_scan(struct ieee80211_device *ieee);
-extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
-extern void ieee80211_check_all_nets(struct ieee80211_device *ieee);
-extern void ieee80211_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_stop_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
-extern void ieee80211_reset_queue(struct ieee80211_device *ieee);
-extern void ieee80211_wake_queue(struct ieee80211_device *ieee);
-extern void ieee80211_stop_queue(struct ieee80211_device *ieee);
-extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
-extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
-extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
-extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p);
-extern void notify_wx_assoc_event(struct ieee80211_device *ieee);
-extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
+void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
+void notify_wx_assoc_event(struct ieee80211_device *ieee);
+void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee);
+void ieee80211_start_bss(struct ieee80211_device *ieee);
+void ieee80211_start_master_bss(struct ieee80211_device *ieee);
+void ieee80211_start_ibss(struct ieee80211_device *ieee);
+void ieee80211_softmac_init(struct ieee80211_device *ieee);
+void ieee80211_softmac_free(struct ieee80211_device *ieee);
+void ieee80211_associate_abort(struct ieee80211_device *ieee);
+void ieee80211_disassociate(struct ieee80211_device *ieee);
+void ieee80211_stop_scan(struct ieee80211_device *ieee);
+void ieee80211_start_scan_syncro(struct ieee80211_device *ieee);
+void ieee80211_check_all_nets(struct ieee80211_device *ieee);
+void ieee80211_start_protocol(struct ieee80211_device *ieee);
+void ieee80211_stop_protocol(struct ieee80211_device *ieee);
+void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee);
+void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee);
+void ieee80211_reset_queue(struct ieee80211_device *ieee);
+void ieee80211_wake_queue(struct ieee80211_device *ieee);
+void ieee80211_stop_queue(struct ieee80211_device *ieee);
+struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee);
+void ieee80211_start_send_beacons(struct ieee80211_device *ieee);
+void ieee80211_stop_send_beacons(struct ieee80211_device *ieee);
+int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee,
+ struct iw_point *p);
+void notify_wx_assoc_event(struct ieee80211_device *ieee);
+void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success);
-extern void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee);
+void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee);
/* ieee80211_crypt_ccmp&tkip&wep.c */
-extern void ieee80211_tkip_null(void);
-extern void ieee80211_wep_null(void);
-extern void ieee80211_ccmp_null(void);
+void ieee80211_tkip_null(void);
+void ieee80211_wep_null(void);
+void ieee80211_ccmp_null(void);
int ieee80211_crypto_init(void);
void ieee80211_crypto_deinit(void);
@@ -2273,116 +2274,128 @@
/* ieee80211_softmac_wx.c */
-extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *ext);
+int ieee80211_wx_get_wap(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *ext);
-extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
+int ieee80211_wx_set_wap(struct ieee80211_device *ieee,
struct iw_request_info *info,
union iwreq_data *awrq,
char *extra);
-extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b);
+int ieee80211_wx_get_essid(struct ieee80211_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_rate(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_get_rate(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int ieee80211_wx_set_mode(struct ieee80211_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int ieee80211_wx_set_scan(struct ieee80211_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_essid(struct ieee80211_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int ieee80211_wx_get_mode(struct ieee80211_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int ieee80211_wx_set_freq(struct ieee80211_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
-extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b);
+int ieee80211_wx_get_freq(struct ieee80211_device *ieee,
+ struct iw_request_info *a,
+ union iwreq_data *wrqu, char *b);
/* ieee80211_module.c */
-extern int ieee80211_debug_init(void);
-extern void ieee80211_debug_exit(void);
+int ieee80211_debug_init(void);
+void ieee80211_debug_exit(void);
//extern void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee);
-extern void ieee80211_wx_sync_scan_wq(struct work_struct *work);
+void ieee80211_wx_sync_scan_wq(struct work_struct *work);
-extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
- struct iw_request_info *info,
+int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_get_name(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_get_name(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_set_power(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_power(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_get_power(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_get_power(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_set_rts(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
-extern int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
+int ieee80211_wx_get_rts(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
//HT
#define MAX_RECEIVE_BUFFER_SIZE 9100 //
-extern void HTDebugHTCapability(u8 *CapIE, u8 *TitleString );
-extern void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString);
+void HTDebugHTCapability(u8 *CapIE, u8 *TitleString);
+void HTDebugHTInfo(u8 *InfoIE, u8 *TitleString);
-void HTSetConnectBwMode(struct ieee80211_device *ieee, HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
-extern void HTUpdateDefaultSetting(struct ieee80211_device *ieee);
-extern void HTConstructCapabilityElement(struct ieee80211_device *ieee, u8 *posHTCap, u8 *len, u8 isEncrypt);
-extern void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo, u8 *len, u8 isEncrypt);
-extern void HTConstructRT2RTAggElement(struct ieee80211_device *ieee, u8 *posRT2RTAgg, u8 *len);
-extern void HTOnAssocRsp(struct ieee80211_device *ieee);
-extern void HTInitializeHTInfo(struct ieee80211_device *ieee);
-extern void HTInitializeBssDesc(PBSS_HT pBssHT);
-extern void HTResetSelfAndSavePeerSetting(struct ieee80211_device *ieee, struct ieee80211_network *pNetwork);
-extern void HTUpdateSelfAndPeerSetting(struct ieee80211_device *ieee, struct ieee80211_network *pNetwork);
-extern u8 HTGetHighestMCSRate(struct ieee80211_device *ieee, u8 *pMCSRateSet, u8 *pMCSFilter);
+void HTSetConnectBwMode(struct ieee80211_device *ieee,
+ HT_CHANNEL_WIDTH Bandwidth, HT_EXTCHNL_OFFSET Offset);
+void HTUpdateDefaultSetting(struct ieee80211_device *ieee);
+void HTConstructCapabilityElement(struct ieee80211_device *ieee, u8 *posHTCap,
+ u8 *len, u8 isEncrypt);
+void HTConstructInfoElement(struct ieee80211_device *ieee, u8 *posHTInfo,
+ u8 *len, u8 isEncrypt);
+void HTConstructRT2RTAggElement(struct ieee80211_device *ieee, u8 *posRT2RTAgg,
+ u8 *len);
+void HTOnAssocRsp(struct ieee80211_device *ieee);
+void HTInitializeHTInfo(struct ieee80211_device *ieee);
+void HTInitializeBssDesc(PBSS_HT pBssHT);
+void HTResetSelfAndSavePeerSetting(struct ieee80211_device *ieee,
+ struct ieee80211_network *pNetwork);
+void HTUpdateSelfAndPeerSetting(struct ieee80211_device *ieee,
+ struct ieee80211_network *pNetwork);
+u8 HTGetHighestMCSRate(struct ieee80211_device *ieee,
+ u8 *pMCSRateSet, u8 *pMCSFilter);
extern u8 MCS_FILTER_ALL[];
extern u16 MCS_DATA_RATE[2][2][77] ;
-extern u8 HTCCheck(struct ieee80211_device *ieee, u8 *pFrame);
+u8 HTCCheck(struct ieee80211_device *ieee, u8 *pFrame);
//extern void HTSetConnectBwModeCallback(unsigned long data);
-extern void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo);
-extern bool IsHTHalfNmodeAPs(struct ieee80211_device *ieee);
-extern u16 HTHalfMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
-extern u16 HTMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
-extern u16 TxCountToDataRate(struct ieee80211_device *ieee, u8 nDataRate);
+void HTResetIOTSetting(PRT_HIGH_THROUGHPUT pHTInfo);
+bool IsHTHalfNmodeAPs(struct ieee80211_device *ieee);
+u16 HTHalfMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
+u16 HTMcsToDataRate(struct ieee80211_device *ieee, u8 nMcsRate);
+u16 TxCountToDataRate(struct ieee80211_device *ieee, u8 nDataRate);
//function in BAPROC.c
-extern int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee,
- struct sk_buff *skb);
-extern int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee,
- struct sk_buff *skb);
-extern int ieee80211_rx_DELBA(struct ieee80211_device *ieee,struct sk_buff *skb);
-extern void TsInitAddBA(struct ieee80211_device *ieee, PTX_TS_RECORD pTS,
- u8 Policy, u8 bOverwritePending);
-extern void TsInitDelBA(struct ieee80211_device *ieee,
- PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
-extern void BaSetupTimeOut(unsigned long data);
-extern void TxBaInactTimeout(unsigned long data);
-extern void RxBaInactTimeout(unsigned long data);
-extern void ResetBaEntry(PBA_RECORD pBA);
+int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb);
+int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb);
+int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb);
+void TsInitAddBA(struct ieee80211_device *ieee, PTX_TS_RECORD pTS,
+ u8 Policy, u8 bOverwritePending);
+void TsInitDelBA(struct ieee80211_device *ieee,
+ PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect);
+void BaSetupTimeOut(unsigned long data);
+void TxBaInactTimeout(unsigned long data);
+void RxBaInactTimeout(unsigned long data);
+void ResetBaEntry(PBA_RECORD pBA);
//function in TS.c
-extern bool GetTs(
+bool GetTs(
struct ieee80211_device *ieee,
PTS_COMMON_INFO *ppTS,
u8 *Addr,
@@ -2390,10 +2403,10 @@
TR_SELECT TxRxSelect, //Rx:1, Tx:0
bool bAddNewTs
);
-extern void TSInitialize(struct ieee80211_device *ieee);
-extern void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTS);
-extern void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr);
-extern void RemoveAllTS(struct ieee80211_device *ieee);
+void TSInitialize(struct ieee80211_device *ieee);
+void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTS);
+void RemovePeerTS(struct ieee80211_device *ieee, u8 *Addr);
+void RemoveAllTS(struct ieee80211_device *ieee);
void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee);
extern const long ieee80211_wlan_frequencies[];
@@ -2423,14 +2436,16 @@
/* For the function is more related to hardware setting, it's better to use the
* ieee handler to refer to it.
*/
-extern short check_nic_enough_desc(struct net_device *dev, int queue_index);
-extern int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev);
-extern int ieee80211_parse_info_param(struct ieee80211_device *ieee,
- struct ieee80211_info_element *info_element,
- u16 length,
- struct ieee80211_network *network,
- struct ieee80211_rx_stats *stats);
+short check_nic_enough_desc(struct net_device *dev, int queue_index);
+int ieee80211_data_xmit(struct sk_buff *skb, struct net_device *dev);
+int ieee80211_parse_info_param(struct ieee80211_device *ieee,
+ struct ieee80211_info_element *info_element,
+ u16 length,
+ struct ieee80211_network *network,
+ struct ieee80211_rx_stats *stats);
-void ieee80211_indicate_packets(struct ieee80211_device *ieee, struct ieee80211_rxb **prxbIndicateArray,u8 index);
+void ieee80211_indicate_packets(struct ieee80211_device *ieee,
+ struct ieee80211_rxb **prxbIndicateArray,
+ u8 index);
#define RT_ASOC_RETRY_LIMIT 5
#endif /* IEEE80211_H */
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
index b374088..0aa9021 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_rx.c
@@ -1014,7 +1014,7 @@
goto rx_dropped;
// if QoS enabled, should check the sequence for each of the AC
- if( (ieee->pHTInfo->bCurRxReorderEnable == false) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)){
+ if ((!ieee->pHTInfo->bCurRxReorderEnable) || !ieee->current_network.qos_data.active|| !IsDataFrame(skb->data) || IsLegacyDataFrame(skb->data)) {
if (is_duplicate_packet(ieee, hdr))
goto rx_dropped;
@@ -1307,7 +1307,7 @@
}
//added by amy for reorder
- if(ieee->pHTInfo->bCurRxReorderEnable == false ||pTS == NULL){
+ if (!ieee->pHTInfo->bCurRxReorderEnable || pTS == NULL){
//added by amy for reorder
for(i = 0; i<rxb->nr_subframes; i++) {
struct sk_buff *sub_skb = rxb->subframes[i];
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
index 1b11acb..39e9892 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
@@ -1177,7 +1177,7 @@
tag = skb_put(skb, ht_cap_len);
*tag++ = MFIE_TYPE_HT_CAP;
*tag++ = ht_cap_len - 2;
- memcpy(tag, ht_cap_buf,ht_cap_len -2);
+ memcpy(tag, ht_cap_buf, ht_cap_len - 2);
tag += ht_cap_len -2;
}
}
@@ -1214,7 +1214,7 @@
tag = skb_put(skb, realtek_ie_len);
*tag++ = MFIE_TYPE_GENERIC;
*tag++ = realtek_ie_len - 2;
- memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
+ memcpy(tag, realtek_ie_buf, realtek_ie_len - 2);
}
}
// printk("<=====%s(), %p, %p\n", __func__, ieee->dev, ieee->dev->dev_addr);
@@ -1964,7 +1964,7 @@
}
if (ieee->current_network.mode == IEEE_N_24G &&
- bHalfSupportNmode == true) {
+ bHalfSupportNmode) {
netdev_dbg(ieee->dev, "enter half N mode\n");
ieee->bHalfWirelessN24GMode = true;
} else
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c
index 714fbca..3e502520 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_softmac_wx.c
@@ -391,7 +391,7 @@
union iwreq_data *wrqu, char *extra)
{
- int ret=0,len;
+ int ret = 0, len;
short proto_started;
unsigned long flags;
diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
index 5353a45..fff8d58 100644
--- a/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
+++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_tx.c
@@ -336,12 +336,12 @@
printk("===>can't get TS\n");
return;
}
- if (pTxTs->TxAdmittedBARecord.bValid == false)
+ if (!pTxTs->TxAdmittedBARecord.bValid)
{
TsStartAddBaProcess(ieee, pTxTs);
goto FORCED_AGG_SETTING;
}
- else if (pTxTs->bUsingBa == false)
+ else if (!pTxTs->bUsingBa)
{
if (SN_LESS(pTxTs->TxAdmittedBARecord.BaStartSeqCtrl.field.SeqNum, (pTxTs->TxCurSeq+1)%4096))
pTxTs->bUsingBa = true;
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
index 9ff8e05..3bde744 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
@@ -364,8 +364,8 @@
printk("====================>rx ADDBAREQ from :%pM\n", dst);
//some other capability is not ready now.
if ((ieee->current_network.qos_data.active == 0) ||
- (ieee->pHTInfo->bCurrentHTSupport == false)) //||
- // (ieee->pStaQos->bEnableRxImmBA == false) )
+ (!ieee->pHTInfo->bCurrentHTSupport)) //||
+ // (!ieee->pStaQos->bEnableRxImmBA) )
{
rc = ADDBA_STATUS_REFUSED;
IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
@@ -462,8 +462,8 @@
// Check the capability
// Since we can always receive A-MPDU, we just check if it is under HT mode.
if (ieee->current_network.qos_data.active == 0 ||
- ieee->pHTInfo->bCurrentHTSupport == false ||
- ieee->pHTInfo->bCurrentAMPDUEnable == false) {
+ !ieee->pHTInfo->bCurrentHTSupport ||
+ !ieee->pHTInfo->bCurrentAMPDUEnable) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
ReasonCode = DELBA_REASON_UNKNOWN_BA;
goto OnADDBARsp_Reject;
@@ -502,7 +502,7 @@
IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
return -1;
}
- else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
+ else if((!pPendingBA->bValid) ||(*pDialogToken != pPendingBA->DialogToken))
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
ReasonCode = DELBA_REASON_UNKNOWN_BA;
@@ -571,7 +571,6 @@
{
struct rtl_80211_hdr_3addr *delba = NULL;
PDELBA_PARAM_SET pDelBaParamSet = NULL;
- u16 *pReasonCode = NULL;
u8 *dst = NULL;
if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 6) {
@@ -583,7 +582,7 @@
}
if (ieee->current_network.qos_data.active == 0 ||
- ieee->pHTInfo->bCurrentHTSupport == false )
+ !ieee->pHTInfo->bCurrentHTSupport)
{
IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
return -1;
@@ -592,9 +591,7 @@
IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
delba = (struct rtl_80211_hdr_3addr *)skb->data;
dst = (u8 *)(&delba->addr2[0]);
- delba += sizeof(struct rtl_80211_hdr_3addr);
- pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
- pReasonCode = (u16 *)(delba+4);
+ pDelBaParamSet = (PDELBA_PARAM_SET)&delba->payload[2];
if(pDelBaParamSet->field.Initiator == 1)
{
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
index c2588f8..c27397b 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_HTProc.c
@@ -224,9 +224,9 @@
bool retValue = false;
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
- if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode
+ if(!pHTInfo->bCurrentHTSupport) // wireless is n mode
retValue = false;
- else if(pHTInfo->bRegBW40MHz == false) // station supports 40 bw
+ else if(!pHTInfo->bRegBW40MHz) // station supports 40 bw
retValue = false;
else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) // station in half n mode
retValue = false;
@@ -243,7 +243,7 @@
bool retValue = false;
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
- if(pHTInfo->bCurrentHTSupport == false ) // wireless is n mode
+ if(!pHTInfo->bCurrentHTSupport) // wireless is n mode
retValue = false;
else if(!ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) // station in half n mode
retValue = false;
@@ -675,7 +675,7 @@
if ( (ieee->iw_mode == IW_MODE_ADHOC) || (ieee->iw_mode == IW_MODE_MASTER)) //ap mode is not currently supported
{
pHTInfoEle->ControlChl = ieee->current_network.channel;
- pHTInfoEle->ExtChlOffset = ((pHT->bRegBW40MHz == false)?HT_EXTCHNL_OFFSET_NO_EXT:
+ pHTInfoEle->ExtChlOffset = ((!pHT->bRegBW40MHz)?HT_EXTCHNL_OFFSET_NO_EXT:
(ieee->current_network.channel<=6)?
HT_EXTCHNL_OFFSET_UPPER:HT_EXTCHNL_OFFSET_LOWER);
pHTInfoEle->RecommemdedTxWidth = pHT->bRegBW40MHz;
@@ -945,7 +945,7 @@
static u8 EWC11NHTCap[] = {0x00, 0x90, 0x4c, 0x33}; // For 11n EWC definition, 2007.07.17, by Emily
static u8 EWC11NHTInfo[] = {0x00, 0x90, 0x4c, 0x34}; // For 11n EWC definition, 2007.07.17, by Emily
- if (pHTInfo->bCurrentHTSupport == false) {
+ if (!pHTInfo->bCurrentHTSupport) {
IEEE80211_DEBUG(IEEE80211_DL_ERR, "<=== HTOnAssocRsp(): HT_DISABLE\n");
return;
}
@@ -956,7 +956,7 @@
// HTDebugHTCapability(pHTInfo->PeerHTCapBuf,"HTOnAssocRsp_wq");
// HTDebugHTInfo(pHTInfo->PeerHTInfoBuf,"HTOnAssocRsp_wq");
//
- if(!memcmp(pHTInfo->PeerHTCapBuf,EWC11NHTCap, sizeof(EWC11NHTCap)))
+ if (!memcmp(pHTInfo->PeerHTCapBuf, EWC11NHTCap, sizeof(EWC11NHTCap)))
pPeerHTCap = (PHT_CAPABILITY_ELE)(&pHTInfo->PeerHTCapBuf[4]);
else
pPeerHTCap = (PHT_CAPABILITY_ELE)(pHTInfo->PeerHTCapBuf);
@@ -976,7 +976,7 @@
//
HTSetConnectBwMode(ieee, (HT_CHANNEL_WIDTH)(pPeerHTCap->ChlWidth), (HT_EXTCHNL_OFFSET)(pPeerHTInfo->ExtChlOffset));
-// if(pHTInfo->bCurBW40MHz == true)
+// if (pHTInfo->bCurBW40MHz)
pHTInfo->bCurTxBW40MHz = ((pPeerHTInfo->RecommemdedTxWidth == 1)?true:false);
//
@@ -1341,7 +1341,7 @@
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
// u32 flags = 0;
- if(pHTInfo->bRegBW40MHz == false)
+ if(!pHTInfo->bRegBW40MHz)
return;
diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
index ea92fde..f33c743 100644
--- a/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
+++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_TSProc.c
@@ -112,7 +112,7 @@
static void ResetTsCommonInfo(PTS_COMMON_INFO pTsCommonInfo)
{
- memset(pTsCommonInfo->Addr, 0, 6);
+ eth_zero_addr(pTsCommonInfo->Addr);
memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY));
memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM);
pTsCommonInfo->TClasProc = 0;
@@ -584,7 +584,7 @@
void TsStartAddBaProcess(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTS)
{
- if(pTxTS->bAddBaReqInProgress == false)
+ if(!pTxTS->bAddBaReqInProgress)
{
pTxTS->bAddBaReqInProgress = true;
if(pTxTS->bAddBaReqDelayed)
diff --git a/drivers/staging/rtl8192u/r8190_rtl8256.h b/drivers/staging/rtl8192u/r8190_rtl8256.h
index 6e5662f..1ba4f83 100644
--- a/drivers/staging/rtl8192u/r8190_rtl8256.h
+++ b/drivers/staging/rtl8192u/r8190_rtl8256.h
@@ -14,11 +14,10 @@
#define RTL8225H
#define RTL819X_TOTAL_RF_PATH 2 /* for 8192U */
-extern void PHY_SetRF8256Bandwidth(struct net_device *dev,
- HT_CHANNEL_WIDTH Bandwidth);
-extern void PHY_RF8256_Config(struct net_device *dev);
-extern void phy_RF8256_Config_ParaFile(struct net_device *dev);
-extern void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel);
-extern void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
+void PHY_SetRF8256Bandwidth(struct net_device *dev, HT_CHANNEL_WIDTH Bandwidth);
+void PHY_RF8256_Config(struct net_device *dev);
+void phy_RF8256_Config_ParaFile(struct net_device *dev);
+void PHY_SetRF8256CCKTxPower(struct net_device *dev, u8 powerlevel);
+void PHY_SetRF8256OFDMTxPower(struct net_device *dev, u8 powerlevel);
#endif
diff --git a/drivers/staging/rtl8192u/r8192U.h b/drivers/staging/rtl8192u/r8192U.h
index 6c2e438..785fd02 100644
--- a/drivers/staging/rtl8192u/r8192U.h
+++ b/drivers/staging/rtl8192u/r8192U.h
@@ -1187,7 +1187,7 @@
void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data);
void rtl8185_tx_antenna(struct net_device *dev, u8 ant);
void rtl8192_set_rxconf(struct net_device *dev);
-extern void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate);
+void rtl819xusb_beacon_tx(struct net_device *dev, u16 tx_rate);
void EnableHWSecurityConfig8192(struct net_device *dev);
void setKey(struct net_device *dev, u8 EntryNo, u8 KeyIndex, u16 KeyType, u8 *MacAddr, u8 DefaultKey, u32 *KeyContent);
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index b852396..6f6fe38 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -2043,16 +2043,9 @@
static bool GetHalfNmodeSupportByAPs819xUsb(struct net_device *dev)
{
- bool Reval;
struct r8192_priv *priv = ieee80211_priv(dev);
- struct ieee80211_device *ieee = priv->ieee80211;
- if (ieee->bHalfWirelessN24GMode == true)
- Reval = true;
- else
- Reval = false;
-
- return Reval;
+ return priv->ieee80211->bHalfWirelessN24GMode;
}
static void rtl8192_refresh_supportrate(struct r8192_priv *priv)
@@ -2762,7 +2755,7 @@
//
#ifdef TO_DO_LIST
if (Adapter->ResetProgress == RESET_TYPE_NORESET) {
- if (pMgntInfo->RegRfOff == true) { /* User disable RF via registry. */
+ if (pMgntInfo->RegRfOff) { /* User disable RF via registry. */
RT_TRACE((COMP_INIT|COMP_RF), DBG_LOUD, ("InitializeAdapter819xUsb(): Turn off RF for RegRfOff ----------\n"));
MgntActSet_RF_State(Adapter, eRfOff, RF_CHANGE_BY_SW);
// Those actions will be discard in MgntActSet_RF_State because of the same state
@@ -4406,7 +4399,8 @@
/* RTL8190 set this bit to indicate that Hw does not decrypt packet */
stats->Decrypted = !desc->SWDec;
- if ((priv->ieee80211->pHTInfo->bCurrentHTSupport == true) && (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
+ if ((priv->ieee80211->pHTInfo->bCurrentHTSupport) &&
+ (priv->ieee80211->pairwise_key_type == KEY_TYPE_CCMP))
stats->bHwError = false;
else
stats->bHwError = stats->bCRC|stats->bICV;
diff --git a/drivers/staging/rtl8192u/r8192U_dm.c b/drivers/staging/rtl8192u/r8192U_dm.c
index 7ca5d8f..5277f2e 100644
--- a/drivers/staging/rtl8192u/r8192U_dm.c
+++ b/drivers/staging/rtl8192u/r8192U_dm.c
@@ -438,7 +438,7 @@
if (priv->CurrentChannelBW == HT_CHANNEL_WIDTH_20 || !priv->ieee80211->bandwidth_auto_switch.bautoswitch_enable)
return;
- if (priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz == false) { /* If send packets in 40 Mhz in 20/40 */
+ if (!priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz) { /* If send packets in 40 Mhz in 20/40 */
if (priv->undecorated_smoothed_pwdb <= priv->ieee80211->bandwidth_auto_switch.threshold_40Mhzto20Mhz)
priv->ieee80211->bandwidth_auto_switch.bforced_tx20Mhz = true;
} else { /* in force send packets in 20 Mhz in 20/40 */
@@ -1731,7 +1731,7 @@
*---------------------------------------------------------------------------*/
static void dm_ctrl_initgain_byrssi(struct net_device *dev)
{
- if (dm_digtable.dig_enable_flag == false)
+ if (!dm_digtable.dig_enable_flag)
return;
if (dm_digtable.dig_algorithm == DIG_ALGO_BY_FALSE_ALARM)
@@ -1750,7 +1750,7 @@
u8 i;
static u8 fw_dig;
- if (dm_digtable.dig_enable_flag == false)
+ if (!dm_digtable.dig_enable_flag)
return;
/*DbgPrint("Dig by Sw Rssi\n");*/
@@ -1792,7 +1792,7 @@
static u32 reset_cnt;
u8 i;
- if (dm_digtable.dig_enable_flag == false)
+ if (!dm_digtable.dig_enable_flag)
return;
if (dm_digtable.dig_algorithm_switch) {
diff --git a/drivers/staging/rtl8192u/r8192U_dm.h b/drivers/staging/rtl8192u/r8192U_dm.h
index 6cd32eb4..2d0232f 100644
--- a/drivers/staging/rtl8192u/r8192U_dm.h
+++ b/drivers/staging/rtl8192u/r8192U_dm.h
@@ -212,24 +212,24 @@
/*--------------------------Exported Function prototype---------------------*/
-extern void init_hal_dm(struct net_device *dev);
-extern void deinit_hal_dm(struct net_device *dev);
-extern void hal_dm_watchdog(struct net_device *dev);
-extern void init_rate_adaptive(struct net_device *dev);
-extern void dm_txpower_trackingcallback(struct work_struct *work);
-extern void dm_restore_dynamic_mechanism_state(struct net_device *dev);
-extern void dm_backup_dynamic_mechanism_state(struct net_device *dev);
-extern void dm_change_dynamic_initgain_thresh(struct net_device *dev,
- u32 dm_type, u32 dm_value);
-extern void dm_force_tx_fw_info(struct net_device *dev,
- u32 force_type, u32 force_value);
-extern void dm_init_edca_turbo(struct net_device *dev);
-extern void dm_rf_operation_test_callback(unsigned long data);
-extern void dm_rf_pathcheck_workitemcallback(struct work_struct *work);
-extern void dm_fsync_timer_callback(unsigned long data);
-extern void dm_cck_txpower_adjust(struct net_device *dev, bool binch14);
-extern void dm_shadow_init(struct net_device *dev);
-extern void dm_initialize_txpower_tracking(struct net_device *dev);
+void init_hal_dm(struct net_device *dev);
+void deinit_hal_dm(struct net_device *dev);
+void hal_dm_watchdog(struct net_device *dev);
+void init_rate_adaptive(struct net_device *dev);
+void dm_txpower_trackingcallback(struct work_struct *work);
+void dm_restore_dynamic_mechanism_state(struct net_device *dev);
+void dm_backup_dynamic_mechanism_state(struct net_device *dev);
+void dm_change_dynamic_initgain_thresh(struct net_device *dev,
+ u32 dm_type, u32 dm_value);
+void dm_force_tx_fw_info(struct net_device *dev,
+ u32 force_type, u32 force_value);
+void dm_init_edca_turbo(struct net_device *dev);
+void dm_rf_operation_test_callback(unsigned long data);
+void dm_rf_pathcheck_workitemcallback(struct work_struct *work);
+void dm_fsync_timer_callback(unsigned long data);
+void dm_cck_txpower_adjust(struct net_device *dev, bool binch14);
+void dm_shadow_init(struct net_device *dev);
+void dm_initialize_txpower_tracking(struct net_device *dev);
/*--------------------------Exported Function prototype---------------------*/
diff --git a/drivers/staging/rtl8192u/r8192U_wx.h b/drivers/staging/rtl8192u/r8192U_wx.h
index d6a2d97..fb5f808 100644
--- a/drivers/staging/rtl8192u/r8192U_wx.h
+++ b/drivers/staging/rtl8192u/r8192U_wx.h
@@ -19,6 +19,6 @@
extern struct iw_handler_def r8192_wx_handlers_def;
/* Enable the rtl819x_core.c to share this function, david 2008.9.22 */
-extern struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
+struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev);
#endif
diff --git a/drivers/staging/rtl8192u/r819xU_cmdpkt.h b/drivers/staging/rtl8192u/r819xU_cmdpkt.h
index 52cd437..cc8029a 100644
--- a/drivers/staging/rtl8192u/r819xU_cmdpkt.h
+++ b/drivers/staging/rtl8192u/r819xU_cmdpkt.h
@@ -182,10 +182,10 @@
RT_STATUS_RESOURCE
} rt_status, *prt_status;
-extern u32 cmpk_message_handle_rx(struct net_device *dev,
- struct ieee80211_rx_stats *pstats);
-extern rt_status SendTxCommandPacket(struct net_device *dev,
- void *pData, u32 DataLen);
+u32 cmpk_message_handle_rx(struct net_device *dev,
+ struct ieee80211_rx_stats *pstats);
+rt_status SendTxCommandPacket(struct net_device *dev,
+ void *pData, u32 DataLen);
#endif
diff --git a/drivers/staging/rtl8192u/r819xU_firmware.c b/drivers/staging/rtl8192u/r819xU_firmware.c
index d27b1e2..08302df 100644
--- a/drivers/staging/rtl8192u/r819xU_firmware.c
+++ b/drivers/staging/rtl8192u/r819xU_firmware.c
@@ -66,7 +66,7 @@
skb = dev_alloc_skb(USB_HWDESC_HEADER_LEN + frag_length + 4);
if (!skb)
return false;
- memcpy((unsigned char *)(skb->cb),&dev,sizeof(dev));
+ memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
tcb_desc->queue_index = TXCMD_QUEUE;
tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
@@ -91,7 +91,7 @@
if (!priv->ieee80211->check_nic_enough_desc(dev, index) ||
(!skb_queue_empty(&priv->ieee80211->skb_waitQ[index])) ||
(priv->ieee80211->queue_stop)) {
- RT_TRACE(COMP_FIRMWARE,"=====================================================> tx full!\n");
+ RT_TRACE(COMP_FIRMWARE, "=====================================================> tx full!\n");
skb_queue_tail(&priv->ieee80211->skb_waitQ[tcb_desc->queue_index], skb);
} else {
priv->ieee80211->softmac_hard_start_xmit(skb, dev);
@@ -144,7 +144,8 @@
/* Turn On CPU */
read_nic_dword(dev, CPU_GEN, &CPU_status);
- write_nic_byte(dev, CPU_GEN, (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
+ write_nic_byte(dev, CPU_GEN,
+ (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
mdelay(1000);
/* Check whether CPU boot OK */
@@ -242,7 +243,7 @@
* or read image file from array. Default load from IMG file
*/
if (rst_opt == OPT_SYSTEM_RESET) {
- rc = request_firmware(&fw_entry, fw_name[init_step],&priv->udev->dev);
+ rc = request_firmware(&fw_entry, fw_name[init_step], &priv->udev->dev);
if (rc < 0) {
RT_TRACE(COMP_ERR, "request firmware fail!\n");
goto download_firmware_fail;
@@ -254,12 +255,12 @@
}
if (init_step != FW_INIT_STEP1_MAIN) {
- memcpy(pfirmware->firmware_buf,fw_entry->data,fw_entry->size);
+ memcpy(pfirmware->firmware_buf, fw_entry->data, fw_entry->size);
mapped_file = pfirmware->firmware_buf;
file_length = fw_entry->size;
} else {
memset(pfirmware->firmware_buf, 0, 128);
- memcpy(&pfirmware->firmware_buf[128],fw_entry->data,fw_entry->size);
+ memcpy(&pfirmware->firmware_buf[128], fw_entry->data, fw_entry->size);
mapped_file = pfirmware->firmware_buf;
file_length = fw_entry->size + 128;
}
@@ -319,7 +320,7 @@
rt_status = CPUcheck_firmware_ready(dev);
if (!rt_status) {
- RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n",rt_status);
+ RT_TRACE(COMP_ERR, "CPUcheck_firmware_ready fail(%d)!\n", rt_status);
goto download_firmware_fail;
}
diff --git a/drivers/staging/rtl8192u/r819xU_phy.h b/drivers/staging/rtl8192u/r819xU_phy.h
index 66cbe3f..e672126 100644
--- a/drivers/staging/rtl8192u/r819xU_phy.h
+++ b/drivers/staging/rtl8192u/r819xU_phy.h
@@ -57,36 +57,35 @@
#define bMaskLWord 0x0000ffff
#define bMaskDWord 0xffffffff
-extern u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath);
-extern void rtl8192_setBBreg(struct net_device *dev, u32 reg_addr,
- u32 bitmask, u32 data);
-extern u32 rtl8192_QueryBBReg(struct net_device *dev, u32 reg_addr,
- u32 bitmask);
-extern void rtl8192_phy_SetRFReg(struct net_device *dev,
- RF90_RADIO_PATH_E eRFPath, u32 reg_addr, u32 bitmask, u32 data);
-extern u32 rtl8192_phy_QueryRFReg(struct net_device *dev,
- RF90_RADIO_PATH_E eRFPath, u32 reg_addr, u32 bitmask);
-extern void rtl8192_phy_configmac(struct net_device *dev);
-extern void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
-extern u8 rtl8192_phy_checkBBAndRF(struct net_device *dev,
- HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
-extern void rtl8192_BBConfig(struct net_device *dev);
-extern void rtl8192_phy_getTxPower(struct net_device *dev);
-extern void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
-extern void rtl8192_phy_RFConfig(struct net_device *dev);
-extern void rtl8192_phy_updateInitGain(struct net_device *dev);
-extern u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
- RF90_RADIO_PATH_E eRFPath);
+u8 rtl8192_phy_CheckIsLegalRFPath(struct net_device *dev, u32 eRFPath);
+void rtl8192_setBBreg(struct net_device *dev, u32 reg_addr,
+ u32 bitmask, u32 data);
+u32 rtl8192_QueryBBReg(struct net_device *dev, u32 reg_addr, u32 bitmask);
+void rtl8192_phy_SetRFReg(struct net_device *dev, RF90_RADIO_PATH_E eRFPath,
+ u32 reg_addr, u32 bitmask, u32 data);
+u32 rtl8192_phy_QueryRFReg(struct net_device *dev, RF90_RADIO_PATH_E eRFPath,
+ u32 reg_addr, u32 bitmask);
+void rtl8192_phy_configmac(struct net_device *dev);
+void rtl8192_phyConfigBB(struct net_device *dev, u8 ConfigType);
+u8 rtl8192_phy_checkBBAndRF(struct net_device *dev,
+ HW90_BLOCK_E CheckBlock, RF90_RADIO_PATH_E eRFPath);
+void rtl8192_BBConfig(struct net_device *dev);
+void rtl8192_phy_getTxPower(struct net_device *dev);
+void rtl8192_phy_setTxPower(struct net_device *dev, u8 channel);
+void rtl8192_phy_RFConfig(struct net_device *dev);
+void rtl8192_phy_updateInitGain(struct net_device *dev);
+u8 rtl8192_phy_ConfigRFWithHeaderFile(struct net_device *dev,
+ RF90_RADIO_PATH_E eRFPath);
-extern u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
-extern void rtl8192_SetBWMode(struct net_device *dev,
- HT_CHANNEL_WIDTH bandwidth, HT_EXTCHNL_OFFSET offset);
-extern void rtl8192_SwChnl_WorkItem(struct net_device *dev);
+u8 rtl8192_phy_SwChnl(struct net_device *dev, u8 channel);
+void rtl8192_SetBWMode(struct net_device *dev, HT_CHANNEL_WIDTH bandwidth,
+ HT_EXTCHNL_OFFSET offset);
+void rtl8192_SwChnl_WorkItem(struct net_device *dev);
void rtl8192_SetBWModeWorkItem(struct net_device *dev);
-extern bool rtl8192_SetRFPowerState(struct net_device *dev,
- RT_RF_POWER_STATE eRFPowerState);
-extern void InitialGain819xUsb(struct net_device *dev, u8 Operation);
+bool rtl8192_SetRFPowerState(struct net_device *dev,
+ RT_RF_POWER_STATE eRFPowerState);
+void InitialGain819xUsb(struct net_device *dev, u8 Operation);
-extern void InitialGainOperateWorkItemCallBack(struct work_struct *work);
+void InitialGainOperateWorkItemCallBack(struct work_struct *work);
#endif
diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c
index 5786808..c5527c1 100644
--- a/drivers/staging/rtl8712/ieee80211.c
+++ b/drivers/staging/rtl8712/ieee80211.c
@@ -134,22 +134,20 @@
return NULL;
}
-static void set_supported_rate(u8 *SupportedRates, uint mode)
+static void set_supported_rate(u8 *rates, uint mode)
{
- memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+ memset(rates, 0, NDIS_802_11_LENGTH_RATES_EX);
switch (mode) {
case WIRELESS_11B:
- memcpy(SupportedRates, WIFI_CCKRATES,
- IEEE80211_CCK_RATE_LEN);
+ memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
break;
case WIRELESS_11G:
case WIRELESS_11A:
- memcpy(SupportedRates, WIFI_OFDMRATES,
- IEEE80211_NUM_OFDM_RATESLEN);
+ memcpy(rates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
break;
case WIRELESS_11BG:
- memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
- memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES,
+ memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+ memcpy(rates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES,
IEEE80211_NUM_OFDM_RATESLEN);
break;
}
@@ -195,17 +193,16 @@
ie = r8712_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength,
pdev_network->Ssid.Ssid, &sz);
/*supported rates*/
- set_supported_rate(pdev_network->SupportedRates,
- pregistrypriv->wireless_mode);
- rateLen = r8712_get_rateset_len(pdev_network->SupportedRates);
+ set_supported_rate(pdev_network->rates, pregistrypriv->wireless_mode);
+ rateLen = r8712_get_rateset_len(pdev_network->rates);
if (rateLen > 8) {
ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_, 8,
- pdev_network->SupportedRates, &sz);
+ pdev_network->rates, &sz);
ie = r8712_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8),
- (pdev_network->SupportedRates + 8), &sz);
+ (pdev_network->rates + 8), &sz);
} else
ie = r8712_set_ie(ie, _SUPPORTEDRATES_IE_,
- rateLen, pdev_network->SupportedRates, &sz);
+ rateLen, pdev_network->rates, &sz);
/*DS parameter set*/
ie = r8712_set_ie(ie, _DSSET_IE_, 1,
(u8 *)&(pdev_network->Configuration.DSConfig), &sz);
diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c
index fcb8c61..4fa2540 100644
--- a/drivers/staging/rtl8712/rtl8712_recv.c
+++ b/drivers/staging/rtl8712/rtl8712_recv.c
@@ -58,8 +58,8 @@
/*init recv_buf*/
_init_queue(&precvpriv->free_recv_buf_queue);
- precvpriv->pallocated_recv_buf = kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4,
- GFP_ATOMIC);
+ precvpriv->pallocated_recv_buf =
+ kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC);
if (precvpriv->pallocated_recv_buf == NULL)
return _FAIL;
precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 -
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
index e35854d..ef71829 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ b/drivers/staging/rtl8712/rtl871x_cmd.c
@@ -456,9 +456,7 @@
INIT_LIST_HEAD(&pcmd->list);
pcmd->cmdcode = _CreateBss_CMD_;
pcmd->parmbuf = (unsigned char *)pdev_network;
- pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz((
- struct ndis_wlan_bssid_ex *)
- pdev_network);
+ pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(pdev_network);
pcmd->rsp = NULL;
pcmd->rspsz = 0;
/* notes: translate IELength & Length after assign to cmdsz; */
@@ -471,8 +469,7 @@
u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork)
{
- uint t_len = 0;
- struct ndis_wlan_bssid_ex *psecnetwork;
+ struct wlan_bssid_ex *psecnetwork;
struct cmd_obj *pcmd;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
@@ -486,14 +483,6 @@
pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
if (pcmd == NULL)
return _FAIL;
- t_len = sizeof(u32) + 6 * sizeof(unsigned char) + 2 +
- sizeof(struct ndis_802_11_ssid) + sizeof(u32) +
- sizeof(s32) +
- sizeof(enum NDIS_802_11_NETWORK_TYPE) +
- sizeof(struct NDIS_802_11_CONFIGURATION) +
- sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE) +
- sizeof(NDIS_802_11_RATES_EX) +
- sizeof(u32) + MAX_IE_SZ;
/* for hidden ap to set fw_state here */
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) !=
@@ -511,12 +500,12 @@
break;
}
}
- psecnetwork = (struct ndis_wlan_bssid_ex *)&psecuritypriv->sec_bss;
+ psecnetwork = &psecuritypriv->sec_bss;
if (psecnetwork == NULL) {
kfree(pcmd);
return _FAIL;
}
- memcpy(psecnetwork, &pnetwork->network, t_len);
+ memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork));
psecuritypriv->authenticator_ie[0] = (unsigned char)
psecnetwork->IELength;
if ((psecnetwork->IELength-12) < (256 - 1))
@@ -575,7 +564,7 @@
memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
255);
/* get cmdsz before endian conversion */
- pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz(psecnetwork);
+ pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork);
#ifdef __BIG_ENDIAN
/* wlan_network endian conversion */
psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
@@ -903,8 +892,7 @@
struct sta_info *psta = NULL;
struct wlan_network *pwlan = NULL;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_wlan_bssid_ex *pnetwork = (struct ndis_wlan_bssid_ex *)
- pcmd->parmbuf;
+ struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
if (pcmd->res != H2C_SUCCESS)
@@ -958,11 +946,11 @@
} else
list_add_tail(&(pwlan->list),
&pmlmepriv->scanned_queue.queue);
- pnetwork->Length = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork);
+ pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork);
memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
pwlan->fixed = true;
memcpy(&tgt_network->network, pnetwork,
- (r8712_get_ndis_wlan_bssid_ex_sz(pnetwork)));
+ (r8712_get_wlan_bssid_ex_sz(pnetwork)));
if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
/* we will set _FW_LINKED when there is one more sat to
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h
index cb8225b..818cd88 100644
--- a/drivers/staging/rtl8712/rtl871x_cmd.h
+++ b/drivers/staging/rtl8712/rtl871x_cmd.h
@@ -123,15 +123,6 @@
};
/*
- * Caller Mode: Infra, Ad-Hoc
- * Notes: To join the specified bss
- * Command Event Mode
- */
-struct joinbss_parm {
- struct ndis_wlan_bssid_ex network;
-};
-
-/*
* Caller Mode: Infra, Ad-HoC(C)
* Notes: To disconnect the current associated BSS
* Command Mode
@@ -141,15 +132,6 @@
};
/*
- * Caller Mode: AP, Ad-HoC(M)
- * Notes: To create a BSS
- * Command Mode
- */
-struct createbss_parm {
- struct ndis_wlan_bssid_ex network;
-};
-
-/*
* Caller Mode: AP, Ad-HoC, Infra
* Notes: To set the NIC mode of RTL8711
* Command Mode
diff --git a/drivers/staging/rtl8712/rtl871x_event.h b/drivers/staging/rtl8712/rtl871x_event.h
index e03ee90..697c8d7 100644
--- a/drivers/staging/rtl8712/rtl871x_event.h
+++ b/drivers/staging/rtl8712/rtl871x_event.h
@@ -36,7 +36,7 @@
* Used to report a bss has been scanned
*/
struct survey_event {
- struct ndis_wlan_bssid_ex bss;
+ struct wlan_bssid_ex bss;
};
/*
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl.h b/drivers/staging/rtl8712/rtl871x_ioctl.h
index 8e6ef5d..c9218be 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl.h
+++ b/drivers/staging/rtl8712/rtl871x_ioctl.h
@@ -76,22 +76,18 @@
extern struct iw_handler_def r871x_handlers_def;
-extern uint drv_query_info(
- struct net_device *MiniportAdapterContext,
- uint Oid,
- void *InformationBuffer,
- u32 InformationBufferLength,
- u32 *BytesWritten,
- u32 *BytesNeeded
-);
+uint drv_query_info(struct net_device *MiniportAdapterContext,
+ uint Oid,
+ void *InformationBuffer,
+ u32 InformationBufferLength,
+ u32 *BytesWritten,
+ u32 *BytesNeeded);
-extern uint drv_set_info(
- struct net_device *MiniportAdapterContext,
- uint Oid,
- void *InformationBuffer,
- u32 InformationBufferLength,
- u32 *BytesRead,
- u32 *BytesNeeded
-);
+uint drv_set_info(struct net_device *MiniportAdapterContext,
+ uint Oid,
+ void *InformationBuffer,
+ u32 InformationBufferLength,
+ u32 *BytesRead,
+ u32 *BytesNeeded);
#endif
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
index 3388f97..143be0f 100644
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
@@ -203,14 +203,12 @@
}
/* Add the protocol name */
iwe.cmd = SIOCGIWNAME;
- if ((r8712_is_cckratesonly_included((u8 *)&pnetwork->network.
- SupportedRates)) == true) {
+ if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
if (ht_cap == true)
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
else
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
- } else if ((r8712_is_cckrates_included((u8 *)&pnetwork->network.
- SupportedRates)) == true) {
+ } else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
if (ht_cap == true)
snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
else
@@ -270,9 +268,9 @@
iwe.u.bitrate.disabled = 0;
iwe.u.bitrate.value = 0;
i = 0;
- while (pnetwork->network.SupportedRates[i] != 0) {
+ while (pnetwork->network.rates[i] != 0) {
/* Bit rate given in 500 kb/s units */
- iwe.u.bitrate.value = (pnetwork->network.SupportedRates[i++] &
+ iwe.u.bitrate.value = (pnetwork->network.rates[i++] &
0x7F) * 500000;
current_val = iwe_stream_add_value(info, start, current_val,
stop, &iwe, IW_EV_PARAM_LEN);
@@ -634,8 +632,8 @@
char *p;
u8 ht_cap = false;
struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- NDIS_802_11_RATES_EX *prates = NULL;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+ u8 *prates;
if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) ==
true) {
@@ -644,15 +642,15 @@
&ht_ielen, pcur_bss->IELength - 12);
if (p && ht_ielen > 0)
ht_cap = true;
- prates = &pcur_bss->SupportedRates;
- if (r8712_is_cckratesonly_included((u8 *)prates) == true) {
+ prates = pcur_bss->rates;
+ if (r8712_is_cckratesonly_included(prates) == true) {
if (ht_cap == true)
snprintf(wrqu->name, IFNAMSIZ,
"IEEE 802.11bn");
else
snprintf(wrqu->name, IFNAMSIZ,
"IEEE 802.11b");
- } else if ((r8712_is_cckrates_included((u8 *)prates)) == true) {
+ } else if ((r8712_is_cckrates_included(prates)) == true) {
if (ht_cap == true)
snprintf(wrqu->name, IFNAMSIZ,
"IEEE 802.11bgn");
@@ -723,7 +721,7 @@
{
struct _adapter *padapter = netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
wrqu->freq.m = ieee80211_wlan_frequencies[
@@ -1111,7 +1109,7 @@
{
struct _adapter *padapter = netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
wrqu->ap_addr.sa_family = ARPHRD_ETHER;
if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE |
@@ -1327,7 +1325,7 @@
{
struct _adapter *padapter = netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
u32 len, ret = 0;
if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE)) {
@@ -1419,7 +1417,7 @@
{
struct _adapter *padapter = netdev_priv(dev);
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ndis_wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
+ struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
struct ieee80211_ht_cap *pht_capie;
unsigned char rf_type = padapter->registrypriv.rf_config;
int i;
@@ -1444,9 +1442,9 @@
(IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
}
- while ((pcur_bss->SupportedRates[i] != 0) &&
- (pcur_bss->SupportedRates[i] != 0xFF)) {
- rate = pcur_bss->SupportedRates[i] & 0x7F;
+ while ((pcur_bss->rates[i] != 0) &&
+ (pcur_bss->rates[i] != 0xFF)) {
+ rate = pcur_bss->rates[i] & 0x7F;
if (rate > max_rate)
max_rate = rate;
wrqu->bitrate.fixed = 0; /* no auto select */
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
index c044b0e..fc5dbea 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ b/drivers/staging/rtl8712/rtl871x_mlme.c
@@ -208,19 +208,9 @@
pibss[5] = (u8)((curtime>>16) & 0xff);
}
-uint r8712_get_ndis_wlan_bssid_ex_sz(struct ndis_wlan_bssid_ex *bss)
+uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
{
- uint t_len;
-
- t_len = sizeof(u32) + 6 * sizeof(unsigned long) + 2 +
- sizeof(struct ndis_802_11_ssid) + sizeof(u32) +
- sizeof(s32) +
- sizeof(enum NDIS_802_11_NETWORK_TYPE) +
- sizeof(struct NDIS_802_11_CONFIGURATION) +
- sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE) +
- sizeof(NDIS_802_11_RATES_EX) +
- sizeof(u32) + bss->IELength;
- return t_len;
+ return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
}
u8 *r8712_get_capability_from_ie(u8 *ie)
@@ -286,8 +276,8 @@
}
-static int is_same_network(struct ndis_wlan_bssid_ex *src,
- struct ndis_wlan_bssid_ex *dst)
+static int is_same_network(struct wlan_bssid_ex *src,
+ struct wlan_bssid_ex *dst)
{
u16 s_cap, d_cap;
@@ -332,8 +322,8 @@
return oldest;
}
-static void update_network(struct ndis_wlan_bssid_ex *dst,
- struct ndis_wlan_bssid_ex *src,
+static void update_network(struct wlan_bssid_ex *dst,
+ struct wlan_bssid_ex *src,
struct _adapter *padapter)
{
u32 last_evm = 0, tmpVal;
@@ -366,11 +356,11 @@
src->Rssi = padapter->recvpriv.signal;
} else
src->Rssi = (src->Rssi + dst->Rssi) / 2;
- memcpy((u8 *)dst, (u8 *)src, r8712_get_ndis_wlan_bssid_ex_sz(src));
+ memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
}
static void update_current_network(struct _adapter *adapter,
- struct ndis_wlan_bssid_ex *pnetwork)
+ struct wlan_bssid_ex *pnetwork)
{
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
@@ -388,7 +378,7 @@
Caller must hold pmlmepriv->lock first.
*/
static void update_scanned_network(struct _adapter *adapter,
- struct ndis_wlan_bssid_ex *target)
+ struct wlan_bssid_ex *target)
{
struct list_head *plist, *phead;
@@ -426,7 +416,7 @@
target->Rssi = (pnetwork->network.Rssi +
target->Rssi) / 2;
memcpy(&pnetwork->network, target,
- r8712_get_ndis_wlan_bssid_ex_sz(target));
+ r8712_get_wlan_bssid_ex_sz(target));
pnetwork->last_scanned = jiffies;
} else {
/* Otherwise just pull from the free list */
@@ -434,7 +424,7 @@
pnetwork = alloc_network(pmlmepriv);
if (pnetwork == NULL)
return;
- bssid_ex_sz = r8712_get_ndis_wlan_bssid_ex_sz(target);
+ bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
target->Length = bssid_ex_sz;
memcpy(&pnetwork->network, target, bssid_ex_sz);
list_add_tail(&pnetwork->list, &queue->queue);
@@ -451,7 +441,7 @@
}
static void rtl8711_add_network(struct _adapter *adapter,
- struct ndis_wlan_bssid_ex *pnetwork)
+ struct wlan_bssid_ex *pnetwork)
{
unsigned long irqL;
struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
@@ -507,10 +497,10 @@
{
unsigned long flags;
u32 len;
- struct ndis_wlan_bssid_ex *pnetwork;
+ struct wlan_bssid_ex *pnetwork;
struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- pnetwork = (struct ndis_wlan_bssid_ex *)pbuf;
+ pnetwork = (struct wlan_bssid_ex *)pbuf;
#ifdef __BIG_ENDIAN
/* endian_convert */
pnetwork->Length = le32_to_cpu(pnetwork->Length);
@@ -538,7 +528,7 @@
le32_to_cpu(pnetwork->InfrastructureMode);
pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
#endif
- len = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork);
+ len = r8712_get_wlan_bssid_ex_sz(pnetwork);
if (len > sizeof(struct wlan_bssid_ex))
return;
spin_lock_irqsave(&pmlmepriv->lock2, flags);
@@ -769,7 +759,7 @@
the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
cur_network->network.MacAddress, ETH_ALEN);
pnetwork->network.Length =
- r8712_get_ndis_wlan_bssid_ex_sz(&pnetwork->network);
+ r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
spin_lock_irqsave(&pmlmepriv->lock, irqL);
if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
goto ignore_joinbss_callback;
@@ -1001,7 +991,7 @@
pdev_network = &(adapter->registrypriv.dev_network);
pibss = adapter->registrypriv.dev_network.MacAddress;
memcpy(pdev_network, &tgt_network->network,
- r8712_get_ndis_wlan_bssid_ex_sz(&tgt_network->
+ r8712_get_wlan_bssid_ex_sz(&tgt_network->
network));
memcpy(&pdev_network->Ssid,
&pmlmepriv->assoc_ssid,
@@ -1668,8 +1658,7 @@
*/
sz = r8712_generate_ie(pregistrypriv);
pdev_network->IELength = sz;
- pdev_network->Length = r8712_get_ndis_wlan_bssid_ex_sz(
- (struct ndis_wlan_bssid_ex *)pdev_network);
+ pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
}
/*the function is at passive_level*/
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h
index 42bd0bf..08d6c98 100644
--- a/drivers/staging/rtl8712/rtl871x_mlme.h
+++ b/drivers/staging/rtl8712/rtl871x_mlme.h
@@ -202,7 +202,7 @@
struct security_priv *psecuritypriv, sint keyid);
sint r8712_set_auth(struct _adapter *adapter,
struct security_priv *psecuritypriv);
-uint r8712_get_ndis_wlan_bssid_ex_sz(struct ndis_wlan_bssid_ex *bss);
+uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss);
void r8712_generate_random_ibss(u8 *pibss);
u8 *r8712_get_capability_from_ie(u8 *ie);
struct wlan_network *r8712_get_oldest_wlan_network(
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
index 0b54612..77f01bf 100644
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
+++ b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
@@ -160,13 +160,13 @@
struct mp_priv *pmppriv = &padapter->mppriv;
struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
struct wlan_network *tgt_network = &pmlmepriv->cur_network;
- struct ndis_wlan_bssid_ex bssid;
+ struct wlan_bssid_ex bssid;
struct sta_info *psta;
unsigned long length;
unsigned long irqL;
int res = _SUCCESS;
- /* 3 1. initialize a new struct ndis_wlan_bssid_ex */
+ /* 3 1. initialize a new struct wlan_bssid_ex */
memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN);
bssid.Ssid.SsidLength = 16;
memcpy(bssid.Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc",
@@ -174,7 +174,7 @@
bssid.InfrastructureMode = Ndis802_11IBSS;
bssid.NetworkTypeInUse = Ndis802_11DS;
bssid.IELength = 0;
- length = r8712_get_ndis_wlan_bssid_ex_sz(&bssid);
+ length = r8712_get_wlan_bssid_ex_sz(&bssid);
if (length % 4) {
/*round up to multiple of 4 bytes.*/
bssid.Length = ((length >> 2) + 1) << 2;
diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c
index bcd1a51..8627928 100644
--- a/drivers/staging/rtl8712/rtl871x_security.c
+++ b/drivers/staging/rtl8712/rtl871x_security.c
@@ -124,28 +124,25 @@
static void crc32_init(void)
{
+ sint i, j;
+ u32 c;
+ u8 *p = (u8 *)&c, *p1;
+ u8 k;
+
if (bcrc32initialized == 1)
return;
- else {
- sint i, j;
- u32 c;
- u8 *p = (u8 *)&c, *p1;
- u8 k;
- c = 0x12340000;
- for (i = 0; i < 256; ++i) {
- k = crc32_reverseBit((u8)i);
- for (c = ((u32)k) << 24, j = 8; j > 0; --j)
- c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY :
- (c << 1);
- p1 = (u8 *)&crc32_table[i];
- p1[0] = crc32_reverseBit(p[3]);
- p1[1] = crc32_reverseBit(p[2]);
- p1[2] = crc32_reverseBit(p[1]);
- p1[3] = crc32_reverseBit(p[0]);
- }
- bcrc32initialized = 1;
+ for (i = 0; i < 256; ++i) {
+ k = crc32_reverseBit((u8)i);
+ for (c = ((u32)k) << 24, j = 8; j > 0; --j)
+ c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
+ p1 = (u8 *)&crc32_table[i];
+ p1[0] = crc32_reverseBit(p[3]);
+ p1[1] = crc32_reverseBit(p[2]);
+ p1[2] = crc32_reverseBit(p[1]);
+ p1[3] = crc32_reverseBit(p[0]);
}
+ bcrc32initialized = 1;
}
static u32 getcrc32(u8 *buf, u32 len)
diff --git a/drivers/staging/rtl8712/wlan_bssdef.h b/drivers/staging/rtl8712/wlan_bssdef.h
index 2ea8a3d..fda5707 100644
--- a/drivers/staging/rtl8712/wlan_bssdef.h
+++ b/drivers/staging/rtl8712/wlan_bssdef.h
@@ -32,11 +32,6 @@
#define NDIS_802_11_LENGTH_RATES 8
#define NDIS_802_11_LENGTH_RATES_EX 16
-/* Set of 8 data rates*/
-typedef unsigned char NDIS_802_11_RATES[NDIS_802_11_LENGTH_RATES];
-/* Set of 16 data rates */
-typedef unsigned char NDIS_802_11_RATES_EX[NDIS_802_11_LENGTH_RATES_EX];
-
struct ndis_802_11_ssid {
u32 SsidLength;
u8 Ssid[32];
@@ -83,18 +78,7 @@
u16 Capabilities;
};
-/*
- * Length is the 4 bytes multiples of the sume of
- * 6 * sizeof (unsigned char) + 2 + sizeof (ndis_802_11_ssid) + sizeof (u32)
- * + sizeof (s32) + sizeof (NDIS_802_11_NETWORK_TYPE)
- * + sizeof (struct NDIS_802_11_CONFIGURATION)
- * + sizeof (NDIS_802_11_RATES_EX) + IELength
-
- * Except the IELength, all other fields are fixed length. Therefore, we can
- * define a macro to present the partial sum.
- */
-
-struct ndis_wlan_bssid_ex {
+struct wlan_bssid_ex {
u32 Length;
unsigned char MacAddress[6];
u8 Reserved[2];
@@ -104,7 +88,8 @@
enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
struct NDIS_802_11_CONFIGURATION Configuration;
enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
- NDIS_802_11_RATES_EX SupportedRates;
+ u8 rates[NDIS_802_11_LENGTH_RATES_EX];
+ /* number of content bytes in EIs, which varies */
u32 IELength;
/*(timestamp, beacon interval, and capability information) */
u8 IEs[MAX_IE_SZ];
@@ -213,7 +198,7 @@
unsigned int last_scanned; /*timestamp for the network */
int aid; /*will only be valid when a BSS is joined. */
int join_res;
- struct ndis_wlan_bssid_ex network; /*must be the last item */
+ struct wlan_bssid_ex network; /*must be the last item */
};
enum VRTL_CARRIER_SENSE {
@@ -244,24 +229,5 @@
#define NUM_PRE_AUTH_KEY 16
#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY
-/*
- * WPA2
- */
-struct wlan_bssid_ex {
- u32 Length;
- unsigned char MacAddress[6];
- u8 Reserved[2];
- struct ndis_802_11_ssid Ssid;
- u32 Privacy;
- s32 Rssi;
- enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
- struct NDIS_802_11_CONFIGURATION Configuration;
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
- NDIS_802_11_RATES_EX SupportedRates;
- u32 IELength;
- u8 IEs[MAX_IE_SZ]; /* (timestamp, beacon interval, and capability
- * information) */
-};
-
#endif /* #ifndef WLAN_BSSDEF_H_ */
diff --git a/drivers/staging/rtl8723au/core/rtw_recv.c b/drivers/staging/rtl8723au/core/rtw_recv.c
index 274a4b6..ad0549c 100644
--- a/drivers/staging/rtl8723au/core/rtw_recv.c
+++ b/drivers/staging/rtl8723au/core/rtw_recv.c
@@ -1554,8 +1554,7 @@
ether_addr_copy(ptr + ETH_ALEN, pattrib->src);
if (!bsnaphdr) {
- len = htons(len);
- memcpy(ptr + 12, &len, 2);
+ put_unaligned_be16(len, ptr + 12);
}
diff --git a/drivers/staging/rtl8723au/core/rtw_security.c b/drivers/staging/rtl8723au/core/rtw_security.c
index af53c92..3d40bab 100644
--- a/drivers/staging/rtl8723au/core/rtw_security.c
+++ b/drivers/staging/rtl8723au/core/rtw_security.c
@@ -148,7 +148,7 @@
struct xmit_frame *pxmitframe)
{
/* exclude ICV */
- unsigned char crc[4];
+ __le32 crc;
struct arc4context mycontext;
int curfragnum, length, index;
u32 keylength;
@@ -186,18 +186,20 @@
length = pattrib->last_txcmdsz - pattrib->hdrlen -
pattrib->iv_len - pattrib->icv_len;
- *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
+ crc = cpu_to_le32(getcrc32(payload, length));
arcfour_init(&mycontext, wepkey, 3 + keylength);
arcfour_encrypt(&mycontext, payload, payload, length);
- arcfour_encrypt(&mycontext, payload + length, crc, 4);
+ arcfour_encrypt(&mycontext, payload + length,
+ (char *)&crc, 4);
} else {
length = pxmitpriv->frag_len - pattrib->hdrlen -
pattrib->iv_len - pattrib->icv_len;
- *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
+ crc = cpu_to_le32(getcrc32(payload, length));
arcfour_init(&mycontext, wepkey, 3 + keylength);
arcfour_encrypt(&mycontext, payload, payload, length);
- arcfour_encrypt(&mycontext, payload + length, crc, 4);
+ arcfour_encrypt(&mycontext, payload + length,
+ (char *)&crc, 4);
pframe += pxmitpriv->frag_len;
pframe = PTR_ALIGN(pframe, 4);
@@ -602,7 +604,7 @@
u32 pnh;
u8 rc4key[16];
u8 ttkey[16];
- u8 crc[4];
+ __le32 crc;
u8 hw_hdr_offset = 0;
struct arc4context mycontext;
int curfragnum, length;
@@ -679,11 +681,12 @@
"pattrib->iv_len =%x, pattrib->icv_len =%x\n",
pattrib->iv_len,
pattrib->icv_len);
- *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
+ crc = cpu_to_le32(getcrc32(payload, length));
arcfour_init(&mycontext, rc4key, 16);
arcfour_encrypt(&mycontext, payload, payload, length);
- arcfour_encrypt(&mycontext, payload + length, crc, 4);
+ arcfour_encrypt(&mycontext, payload + length,
+ (char *)&crc, 4);
} else {
length = (pxmitpriv->frag_len -
@@ -691,10 +694,11 @@
pattrib->iv_len -
pattrib->icv_len);
- *((u32 *)crc) = cpu_to_le32(getcrc32(payload, length));
+ crc = cpu_to_le32(getcrc32(payload, length));
arcfour_init(&mycontext, rc4key, 16);
arcfour_encrypt(&mycontext, payload, payload, length);
- arcfour_encrypt(&mycontext, payload + length, crc, 4);
+ arcfour_encrypt(&mycontext, payload + length,
+ (char *)&crc, 4);
pframe += pxmitpriv->frag_len;
pframe = PTR_ALIGN(pframe, 4);
diff --git a/drivers/staging/rtl8723au/hal/odm.c b/drivers/staging/rtl8723au/hal/odm.c
index f354f5e..6b9dbef 100644
--- a/drivers/staging/rtl8723au/hal/odm.c
+++ b/drivers/staging/rtl8723au/hal/odm.c
@@ -985,7 +985,7 @@
val32 = rtl8723au_read32(adapter, 0x874);
val32 |= pDM_PSTable->Reg874;
rtl8723au_write32(adapter, 0x874, val32);
-
+
val32 = rtl8723au_read32(adapter, 0xc70);
val32 |= pDM_PSTable->RegC70;
rtl8723au_write32(adapter, 0xc70, val32);
diff --git a/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c b/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c
index 342dec3..a63c6cb 100644
--- a/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c
+++ b/drivers/staging/rtl8723au/hal/odm_RegConfig8723A.c
@@ -21,7 +21,7 @@
struct dm_odm_t *pDM_Odm,
u32 Addr,
u32 Data,
- enum RF_RADIO_PATH RF_PATH,
+ enum RF_RADIO_PATH RF_PATH,
u32 RegAddr
)
{
diff --git a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
index cb5076a..cf2388f 100644
--- a/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
+++ b/drivers/staging/rtl8723au/hal/rtl8723a_hal_init.c
@@ -1838,7 +1838,7 @@
static void rtl8723a_cal_txdesc_chksum(struct tx_desc *ptxdesc)
{
- u16 *usPtr = (u16 *) ptxdesc;
+ __le16 *usPtr = (__le16 *)ptxdesc;
u32 count = 16; /* (32 bytes / 2 bytes per XOR) => 16 times */
u32 index;
u16 checksum = 0;
@@ -1847,7 +1847,7 @@
ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
for (index = 0; index < count; index++)
- checksum ^= le16_to_cpu(*(usPtr + index));
+ checksum ^= le16_to_cpu(usPtr[index]);
ptxdesc->txdw7 |= cpu_to_le32(checksum & 0x0000ffff);
}
diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c
index ee818b0..cdaa1ab 100644
--- a/drivers/staging/rts5208/ms.c
+++ b/drivers/staging/rts5208/ms.c
@@ -1121,11 +1121,10 @@
#ifdef SUPPORT_MSXC
if ((buf[cur_addr_off + 8] == 0x10) ||
- (buf[cur_addr_off + 8] == 0x13))
+ (buf[cur_addr_off + 8] == 0x13)) {
#else
- if (buf[cur_addr_off + 8] == 0x10)
+ if (buf[cur_addr_off + 8] == 0x10) {
#endif
- {
sys_info_addr = ((u32)buf[cur_addr_off + 0] << 24) |
((u32)buf[cur_addr_off + 1] << 16) |
((u32)buf[cur_addr_off + 2] << 8) |
diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c
index a8d657b..d6c4982 100644
--- a/drivers/staging/rts5208/sd.c
+++ b/drivers/staging/rts5208/sd.c
@@ -246,11 +246,10 @@
}
}
#ifdef SUPPORT_SD_LOCK
- if (ptr[1] & 0x7D)
+ if (ptr[1] & 0x7D) {
#else
- if (ptr[1] & 0x7F)
+ if (ptr[1] & 0x7F) {
#endif
- {
dev_dbg(rtsx_dev(chip), "ptr[1]: 0x%02x\n",
ptr[1]);
rtsx_trace(chip);
@@ -3520,12 +3519,11 @@
if (chip->sd_io) {
rtsx_trace(chip);
return STATUS_FAIL;
- } else {
- retval = reset_mmc(chip);
- if (retval != STATUS_SUCCESS) {
- rtsx_trace(chip);
- return STATUS_FAIL;
- }
+ }
+ retval = reset_mmc(chip);
+ if (retval != STATUS_SUCCESS) {
+ rtsx_trace(chip);
+ return STATUS_FAIL;
}
}
}
@@ -4149,11 +4147,10 @@
}
}
#ifdef SUPPORT_SD_LOCK
- if (ptr[1] & 0x7D)
+ if (ptr[1] & 0x7D) {
#else
- if (ptr[1] & 0x7F)
+ if (ptr[1] & 0x7F) {
#endif
- {
rtsx_trace(chip);
return STATUS_FAIL;
}
diff --git a/drivers/staging/slicoss/slicoss.c b/drivers/staging/slicoss/slicoss.c
index a609f3e..8585970 100644
--- a/drivers/staging/slicoss/slicoss.c
+++ b/drivers/staging/slicoss/slicoss.c
@@ -2329,6 +2329,7 @@
if (!adapter->isp_initialized) {
unsigned long flags;
+
pshmem = (struct slic_shmem *)(unsigned long)
adapter->phys_shmem;
diff --git a/drivers/staging/sm750fb/ddk750_chip.c b/drivers/staging/sm750fb/ddk750_chip.c
index f4975d2..5e6798e 100644
--- a/drivers/staging/sm750fb/ddk750_chip.c
+++ b/drivers/staging/sm750fb/ddk750_chip.c
@@ -268,7 +268,7 @@
#endif
- if (pInitParam->powerMode != 0 )
+ if (pInitParam->powerMode != 0)
pInitParam->powerMode = 0;
setPowerMode(pInitParam->powerMode);
@@ -464,17 +464,18 @@
RN = N * request;
quo = RN / input;
rem = RN % input;/* rem always small than 14318181 */
- fl_quo = (rem * 10000 /input);
+ fl_quo = (rem * 10000 / input);
for (d = xcnt - 1; d >= 0; d--) {
X = xparm[d].value;
M = quo*X;
M += fl_quo * X / 10000;
/* round step */
- M += (fl_quo*X % 10000)>5000?1:0;
+ M += (fl_quo*X % 10000) > 5000?1:0;
if (M < 256 && M > 0) {
unsigned int diff;
- tmpClock = pll->inputFreq *M / N / X;
+
+ tmpClock = pll->inputFreq * M / N / X;
diff = absDiff(tmpClock, request_orig);
if (diff < miniDiff) {
pll->M = M;
@@ -599,9 +600,9 @@
On returning a 32 bit number, the value can be applied to any PLL in the calling function.
*/
ulPllReg =
- FIELD_SET( 0, PANEL_PLL_CTRL, BYPASS, OFF)
- | FIELD_SET( 0, PANEL_PLL_CTRL, POWER, ON)
- | FIELD_SET( 0, PANEL_PLL_CTRL, INPUT, OSC)
+ FIELD_SET(0, PANEL_PLL_CTRL, BYPASS, OFF)
+ | FIELD_SET(0, PANEL_PLL_CTRL, POWER, ON)
+ | FIELD_SET(0, PANEL_PLL_CTRL, INPUT, OSC)
#ifndef VALIDATION_CHIP
| FIELD_VALUE(0, PANEL_PLL_CTRL, POD, pPLL->POD)
#endif
diff --git a/drivers/staging/sm750fb/ddk750_chip.h b/drivers/staging/sm750fb/ddk750_chip.h
index 4e030e8..6ff0436 100644
--- a/drivers/staging/sm750fb/ddk750_chip.h
+++ b/drivers/staging/sm750fb/ddk750_chip.h
@@ -8,8 +8,7 @@
#include <linux/io.h>
/* This is all the chips recognized by this library */
-typedef enum _logical_chip_type_t
-{
+typedef enum _logical_chip_type_t {
SM_UNKNOWN,
SM718,
SM750,
@@ -18,8 +17,7 @@
logical_chip_type_t;
-typedef enum _clock_type_t
-{
+typedef enum _clock_type_t {
MXCLK_PLL,
PRIMARY_PLL,
SECONDARY_PLL,
@@ -28,8 +26,7 @@
}
clock_type_t;
-typedef struct _pll_value_t
-{
+typedef struct _pll_value_t {
clock_type_t clockType;
unsigned long inputFreq; /* Input clock frequency to the PLL */
@@ -42,8 +39,7 @@
pll_value_t;
/* input struct to initChipParam() function */
-typedef struct _initchip_param_t
-{
+typedef struct _initchip_param_t {
unsigned short powerMode; /* Use power mode 0 or 1 */
unsigned short chipClock; /**
* Speed of main chip clock in MHz unit
diff --git a/drivers/staging/sm750fb/ddk750_display.c b/drivers/staging/sm750fb/ddk750_display.c
index a3e6720..8348113 100644
--- a/drivers/staging/sm750fb/ddk750_display.c
+++ b/drivers/staging/sm750fb/ddk750_display.c
@@ -15,16 +15,14 @@
cnt = 0;
/* Set the primary display control */
- if (!ctrl)
- {
+ if (!ctrl) {
ulDisplayCtrlReg = PEEK32(PANEL_DISPLAY_CTRL);
/* Turn on/off the Panel display control */
- if (dispState)
- {
+ if (dispState) {
/* Timing should be enabled first before enabling the plane
* because changing at the same time does not guarantee that
* the plane will also enabled or disabled.
- */
+ */
ulDisplayCtrlReg = FIELD_SET(ulDisplayCtrlReg,
PANEL_DISPLAY_CTRL, TIMING, ENABLE);
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
@@ -45,16 +43,13 @@
* until a few delay. Need to write
* and read it a couple times
*/
- do
- {
+ do {
cnt++;
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
- } while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
+ } while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) !=
(ulDisplayCtrlReg & ~ulReservedBits));
printk("Set Panel Plane enbit:after tried %d times\n", cnt);
- }
- else
- {
+ } else {
/* When turning off, there is no rule on the programming
* sequence since whenever the clock is off, then it does not
* matter whether the plane is enabled or disabled.
@@ -71,14 +66,11 @@
POKE32(PANEL_DISPLAY_CTRL, ulDisplayCtrlReg);
}
- }
- /* Set the secondary display control */
- else
- {
+ } else {
+ /* Set the secondary display control */
ulDisplayCtrlReg = PEEK32(CRT_DISPLAY_CTRL);
- if (dispState)
- {
+ if (dispState) {
/* Timing should be enabled first before enabling the plane because changing at the
same time does not guarantee that the plane will also enabled or disabled.
*/
@@ -100,16 +92,13 @@
FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_3_MASK, ENABLE) |
FIELD_SET(0, CRT_DISPLAY_CTRL, RESERVED_4_MASK, ENABLE);
- do
- {
+ do {
cnt++;
POKE32(CRT_DISPLAY_CTRL, ulDisplayCtrlReg);
- } while((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
+ } while ((PEEK32(CRT_DISPLAY_CTRL) & ~ulReservedBits) !=
(ulDisplayCtrlReg & ~ulReservedBits));
printk("Set Crt Plane enbit:after tried %d times\n", cnt);
- }
- else
- {
+ } else {
/* When turning off, there is no rule on the programming
* sequence since whenever the clock is off, then it does not
* matter whether the plane is enabled or disabled.
@@ -132,71 +121,60 @@
static void waitNextVerticalSync(int ctrl, int delay)
{
unsigned int status;
- if(!ctrl){
+
+ if (!ctrl) {
/* primary controller */
- /* Do not wait when the Primary PLL is off or display control is already off.
- This will prevent the software to wait forever. */
+ /* Do not wait when the Primary PLL is off or display control is already off.
+ This will prevent the software to wait forever. */
if ((FIELD_GET(PEEK32(PANEL_PLL_CTRL), PANEL_PLL_CTRL, POWER) ==
PANEL_PLL_CTRL_POWER_OFF) ||
(FIELD_GET(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, TIMING) ==
- PANEL_DISPLAY_CTRL_TIMING_DISABLE))
- {
+ PANEL_DISPLAY_CTRL_TIMING_DISABLE)) {
return;
}
- 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);
+ 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);
- /* Wait for start of vsync. */
- do
- {
- status = FIELD_GET(PEEK32(SYSTEM_CTRL),
- SYSTEM_CTRL,
- PANEL_VSYNC);
- }
- while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
- }
+ /* Wait for start of vsync. */
+ do {
+ status = FIELD_GET(PEEK32(SYSTEM_CTRL),
+ SYSTEM_CTRL,
+ PANEL_VSYNC);
+ } while (status == SYSTEM_CTRL_PANEL_VSYNC_INACTIVE);
+ }
- }else{
+ } else {
/* Do not wait when the Primary PLL is off or display control is already off.
This will prevent the software to wait forever. */
if ((FIELD_GET(PEEK32(CRT_PLL_CTRL), CRT_PLL_CTRL, POWER) ==
CRT_PLL_CTRL_POWER_OFF) ||
(FIELD_GET(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, TIMING) ==
- CRT_DISPLAY_CTRL_TIMING_DISABLE))
- {
+ CRT_DISPLAY_CTRL_TIMING_DISABLE)) {
return;
}
- while (delay-- > 0)
- {
+ while (delay-- > 0) {
/* Wait for end of vsync. */
- do
- {
+ do {
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
CRT_VSYNC);
- }
- while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
+ } while (status == SYSTEM_CTRL_CRT_VSYNC_ACTIVE);
/* Wait for start of vsync. */
- do
- {
+ do {
status = FIELD_GET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
CRT_VSYNC);
- }
- while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
+ } while (status == SYSTEM_CTRL_CRT_VSYNC_INACTIVE);
}
}
}
@@ -233,14 +211,15 @@
void ddk750_setLogicalDispOut(disp_output_t output)
{
unsigned int reg;
- if(output & PNL_2_USAGE){
+
+ if (output & PNL_2_USAGE) {
/* set panel path controller select */
reg = PEEK32(PANEL_DISPLAY_CTRL);
reg = FIELD_VALUE(reg, PANEL_DISPLAY_CTRL, SELECT, (output & PNL_2_MASK)>>PNL_2_OFFSET);
POKE32(PANEL_DISPLAY_CTRL, reg);
}
- if(output & CRT_2_USAGE){
+ if (output & CRT_2_USAGE) {
/* set crt path controller select */
reg = PEEK32(CRT_DISPLAY_CTRL);
reg = FIELD_VALUE(reg, CRT_DISPLAY_CTRL, SELECT, (output & CRT_2_MASK)>>CRT_2_OFFSET);
@@ -250,58 +229,57 @@
}
- if(output & PRI_TP_USAGE){
+ if (output & PRI_TP_USAGE) {
/* set primary timing and plane en_bit */
setDisplayControl(0, (output&PRI_TP_MASK)>>PRI_TP_OFFSET);
}
- if(output & SEC_TP_USAGE){
+ if (output & SEC_TP_USAGE) {
/* set secondary timing and plane en_bit*/
setDisplayControl(1, (output&SEC_TP_MASK)>>SEC_TP_OFFSET);
}
- if(output & PNL_SEQ_USAGE){
+ if (output & PNL_SEQ_USAGE) {
/* set panel sequence */
swPanelPowerSequence((output&PNL_SEQ_MASK)>>PNL_SEQ_OFFSET, 4);
}
- if(output & DAC_USAGE)
+ if (output & DAC_USAGE)
setDAC((output & DAC_MASK)>>DAC_OFFSET);
- if(output & DPMS_USAGE)
+ if (output & DPMS_USAGE)
ddk750_setDPMS((output & DPMS_MASK) >> DPMS_OFFSET);
}
int ddk750_initDVIDisp(void)
{
- /* Initialize DVI. If the dviInit fail and the VendorID or the DeviceID are
- not zeroed, then set the failure flag. If it is zeroe, it might mean
- that the system is in Dual CRT Monitor configuration. */
+ /* Initialize DVI. If the dviInit fail and the VendorID or the DeviceID are
+ not zeroed, then set the failure flag. If it is zeroe, it might mean
+ that the system is in Dual CRT Monitor configuration. */
- /* De-skew enabled with default 111b value.
- This will fix some artifacts problem in some mode on board 2.2.
- Somehow this fix does not affect board 2.1.
- */
- if ((dviInit(1, /* Select Rising Edge */
- 1, /* Select 24-bit bus */
- 0, /* Select Single Edge clock */
- 1, /* Enable HSync as is */
- 1, /* Enable VSync as is */
- 1, /* Enable De-skew */
- 7, /* Set the de-skew setting to maximum setup */
- 1, /* Enable continuous Sync */
- 1, /* Enable PLL Filter */
- 4 /* Use the recommended value for PLL Filter value */
- ) != 0) && (dviGetVendorID() != 0x0000) && (dviGetDeviceID() != 0x0000))
- {
- return (-1);
- }
+ /* De-skew enabled with default 111b value.
+ This will fix some artifacts problem in some mode on board 2.2.
+ Somehow this fix does not affect board 2.1.
+ */
+ if ((dviInit(1, /* Select Rising Edge */
+ 1, /* Select 24-bit bus */
+ 0, /* Select Single Edge clock */
+ 1, /* Enable HSync as is */
+ 1, /* Enable VSync as is */
+ 1, /* Enable De-skew */
+ 7, /* Set the de-skew setting to maximum setup */
+ 1, /* Enable continuous Sync */
+ 1, /* Enable PLL Filter */
+ 4 /* Use the recommended value for PLL Filter value */
+ ) != 0) && (dviGetVendorID() != 0x0000) && (dviGetDeviceID() != 0x0000)) {
+ return (-1);
+ }
- /* TODO: Initialize other display component */
+ /* TODO: Initialize other display component */
- /* Success */
- return 0;
+ /* Success */
+ return 0;
}
diff --git a/drivers/staging/sm750fb/ddk750_display.h b/drivers/staging/sm750fb/ddk750_display.h
index ae0f84c..abccf84 100644
--- a/drivers/staging/sm750fb/ddk750_display.h
+++ b/drivers/staging/sm750fb/ddk750_display.h
@@ -8,7 +8,7 @@
#define PNL_2_OFFSET 0
#define PNL_2_MASK (3 << PNL_2_OFFSET)
#define PNL_2_USAGE (PNL_2_MASK << 16)
-#define PNL_2_PRI ((0 << PNL_2_OFFSET)|PNL_2_USAGE)
+#define PNL_2_PRI ((0 << PNL_2_OFFSET)|PNL_2_USAGE)
#define PNL_2_SEC ((2 << PNL_2_OFFSET)|PNL_2_USAGE)
@@ -46,7 +46,7 @@
0: both off
*/
#define SEC_TP_OFFSET 5
-#define SEC_TP_MASK (1<< SEC_TP_OFFSET)
+#define SEC_TP_MASK (1 << SEC_TP_OFFSET)
#define SEC_TP_USAGE (SEC_TP_MASK << 16)
#define SEC_TP_ON ((0x1 << SEC_TP_OFFSET)|SEC_TP_USAGE)
#define SEC_TP_OFF ((0x0 << SEC_TP_OFFSET)|SEC_TP_USAGE)
@@ -67,7 +67,7 @@
#define DAC_OFFSET 7
#define DAC_MASK (1 << DAC_OFFSET)
#define DAC_USAGE (DAC_MASK << 16)
-#define DAC_ON ((0x0<< DAC_OFFSET)|DAC_USAGE)
+#define DAC_ON ((0x0 << DAC_OFFSET)|DAC_USAGE)
#define DAC_OFF ((0x1 << DAC_OFFSET)|DAC_USAGE)
/* DPMS only affect D-SUB head
@@ -86,8 +86,7 @@
CRT means crt path DSUB
*/
#if 0
-typedef enum _disp_output_t
-{
+typedef enum _disp_output_t {
NO_DISPLAY = DPMS_OFF,
LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DPMS_OFF|DAC_ON,
@@ -129,7 +128,7 @@
}
disp_output_t;
#else
-typedef enum _disp_output_t{
+typedef enum _disp_output_t {
do_LCD1_PRI = PNL_2_PRI|PRI_TP_ON|PNL_SEQ_ON|DAC_ON,
do_LCD1_SEC = PNL_2_SEC|SEC_TP_ON|PNL_SEQ_ON|DAC_ON,
#if 0
diff --git a/drivers/staging/sm750fb/ddk750_dvi.c b/drivers/staging/sm750fb/ddk750_dvi.c
index b2bf7e6..a7a2351 100644
--- a/drivers/staging/sm750fb/ddk750_dvi.c
+++ b/drivers/staging/sm750fb/ddk750_dvi.c
@@ -1,4 +1,4 @@
-#define USE_DVICHIP
+#define USE_DVICHIP
#ifdef USE_DVICHIP
#include "ddk750_help.h"
#include "ddk750_reg.h"
@@ -9,47 +9,46 @@
/* This global variable contains all the supported driver and its corresponding
function API. Please set the function pointer to NULL whenever the function
is not supported. */
-static dvi_ctrl_device_t g_dcftSupportedDviController[] =
-{
+static dvi_ctrl_device_t g_dcftSupportedDviController[] = {
#ifdef DVI_CTRL_SII164
- {
- .pfnInit = sii164InitChip,
- .pfnGetVendorId = sii164GetVendorID,
- .pfnGetDeviceId = sii164GetDeviceID,
+ {
+ .pfnInit = sii164InitChip,
+ .pfnGetVendorId = sii164GetVendorID,
+ .pfnGetDeviceId = sii164GetDeviceID,
#ifdef SII164_FULL_FUNCTIONS
- .pfnResetChip = sii164ResetChip,
- .pfnGetChipString = sii164GetChipString,
- .pfnSetPower = sii164SetPower,
- .pfnEnableHotPlugDetection = sii164EnableHotPlugDetection,
- .pfnIsConnected = sii164IsConnected,
- .pfnCheckInterrupt = sii164CheckInterrupt,
- .pfnClearInterrupt = sii164ClearInterrupt,
+ .pfnResetChip = sii164ResetChip,
+ .pfnGetChipString = sii164GetChipString,
+ .pfnSetPower = sii164SetPower,
+ .pfnEnableHotPlugDetection = sii164EnableHotPlugDetection,
+ .pfnIsConnected = sii164IsConnected,
+ .pfnCheckInterrupt = sii164CheckInterrupt,
+ .pfnClearInterrupt = sii164ClearInterrupt,
#endif
- },
+ },
#endif
};
int dviInit(
- unsigned char edgeSelect,
- unsigned char busSelect,
- unsigned char dualEdgeClkSelect,
- unsigned char hsyncEnable,
- unsigned char vsyncEnable,
- unsigned char deskewEnable,
- unsigned char deskewSetting,
- unsigned char continuousSyncEnable,
- unsigned char pllFilterEnable,
- unsigned char pllFilterValue
+ unsigned char edgeSelect,
+ unsigned char busSelect,
+ unsigned char dualEdgeClkSelect,
+ unsigned char hsyncEnable,
+ unsigned char vsyncEnable,
+ unsigned char deskewEnable,
+ unsigned char deskewSetting,
+ unsigned char continuousSyncEnable,
+ unsigned char pllFilterEnable,
+ unsigned char pllFilterValue
)
{
dvi_ctrl_device_t *pCurrentDviCtrl;
+
pCurrentDviCtrl = g_dcftSupportedDviController;
- if(pCurrentDviCtrl->pfnInit != NULL)
- {
+ if (pCurrentDviCtrl->pfnInit != NULL) {
return pCurrentDviCtrl->pfnInit(edgeSelect, busSelect, dualEdgeClkSelect, hsyncEnable,
- vsyncEnable, deskewEnable, deskewSetting, continuousSyncEnable,
- pllFilterEnable, pllFilterValue);
+ vsyncEnable, deskewEnable, deskewSetting, continuousSyncEnable,
+ pllFilterEnable, pllFilterValue);
}
return -1; /* error */
}
@@ -64,13 +63,13 @@
*/
unsigned short dviGetVendorID(void)
{
- dvi_ctrl_device_t *pCurrentDviCtrl;
+ dvi_ctrl_device_t *pCurrentDviCtrl;
- pCurrentDviCtrl = g_dcftSupportedDviController;
- if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
- return pCurrentDviCtrl->pfnGetVendorId();
+ pCurrentDviCtrl = g_dcftSupportedDviController;
+ if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
+ return pCurrentDviCtrl->pfnGetVendorId();
- return 0x0000;
+ return 0x0000;
}
@@ -83,13 +82,13 @@
*/
unsigned short dviGetDeviceID(void)
{
- dvi_ctrl_device_t *pCurrentDviCtrl;
+ dvi_ctrl_device_t *pCurrentDviCtrl;
pCurrentDviCtrl = g_dcftSupportedDviController;
- if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
- return pCurrentDviCtrl->pfnGetDeviceId();
+ if (pCurrentDviCtrl != (dvi_ctrl_device_t *)0)
+ return pCurrentDviCtrl->pfnGetDeviceId();
- return 0x0000;
+ return 0x0000;
}
#endif
diff --git a/drivers/staging/sm750fb/ddk750_dvi.h b/drivers/staging/sm750fb/ddk750_dvi.h
index 83bbd6d..e1d4c9a 100644
--- a/drivers/staging/sm750fb/ddk750_dvi.h
+++ b/drivers/staging/sm750fb/ddk750_dvi.h
@@ -26,8 +26,7 @@
typedef void (*PFN_DVICTRL_CLEARINTERRUPT)(void);
/* Structure to hold all the function pointer to the DVI Controller. */
-typedef struct _dvi_ctrl_device_t
-{
+typedef struct _dvi_ctrl_device_t {
PFN_DVICTRL_INIT pfnInit;
PFN_DVICTRL_RESETCHIP pfnResetChip;
PFN_DVICTRL_GETCHIPSTRING pfnGetChipString;
diff --git a/drivers/staging/sm750fb/ddk750_help.c b/drivers/staging/sm750fb/ddk750_help.c
index 1adcafc..9637dd3 100644
--- a/drivers/staging/sm750fb/ddk750_help.c
+++ b/drivers/staging/sm750fb/ddk750_help.c
@@ -1,8 +1,8 @@
#include "ddk750_help.h"
-void __iomem *mmio750 = NULL;
-char revId750 = 0;
-unsigned short devId750 = 0;
+void __iomem *mmio750;
+char revId750;
+unsigned short devId750;
/* after driver mapped io registers, use this function first */
void ddk750_set_mmio(void __iomem *addr, unsigned short devId, char revId)
@@ -10,7 +10,7 @@
mmio750 = addr;
devId750 = devId;
revId750 = revId;
- if(revId == 0xfe)
+ if (revId == 0xfe)
printk("found sm750le\n");
}
diff --git a/drivers/staging/sm750fb/ddk750_help.h b/drivers/staging/sm750fb/ddk750_help.h
index 4285b05..3b06aed 100644
--- a/drivers/staging/sm750fb/ddk750_help.h
+++ b/drivers/staging/sm750fb/ddk750_help.h
@@ -12,8 +12,8 @@
#if 0
/* if 718 big endian turned on,be aware that don't use this driver for general use,only for ppc big-endian */
#warning "big endian on target cpu and enable nature big endian support of 718 capability !"
-#define PEEK32(addr) __raw_readl(mmio750 + addr)
-#define POKE32(addr, data) __raw_writel(data, mmio750 + addr)
+#define PEEK32(addr) __raw_readl(mmio750 + addr)
+#define POKE32(addr, data) __raw_writel(data, mmio750 + addr)
#else /* software control endianness */
#define PEEK32(addr) readl(addr + mmio750)
#define POKE32(addr, data) writel(data, addr + mmio750)
diff --git a/drivers/staging/sm750fb/ddk750_hwi2c.c b/drivers/staging/sm750fb/ddk750_hwi2c.c
index 7826376..5ddac43 100644
--- a/drivers/staging/sm750fb/ddk750_hwi2c.c
+++ b/drivers/staging/sm750fb/ddk750_hwi2c.c
@@ -10,70 +10,70 @@
int hwI2CInit(
- unsigned char busSpeedMode
+unsigned char busSpeedMode
)
{
- unsigned int value;
+ unsigned int value;
- /* Enable GPIO 30 & 31 as IIC clock & data */
+ /* 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 = FIELD_SET(value, GPIO_MUX, 30, I2C) |
+ FIELD_SET(0, GPIO_MUX, 31, I2C);
POKE32(GPIO_MUX, value);
- /* Enable Hardware I2C power.
- TODO: Check if we need to enable GPIO power?
- */
- enableI2C(1);
+ /* Enable Hardware I2C power.
+ TODO: Check if we need to enable GPIO power?
+ */
+ enableI2C(1);
- /* Enable the I2C Controller and set the bus speed mode */
- value = PEEK32(I2C_CTRL);
- if (busSpeedMode == 0)
- value = FIELD_SET(value, I2C_CTRL, MODE, STANDARD);
- else
- value = FIELD_SET(value, I2C_CTRL, MODE, FAST);
- value = FIELD_SET(value, I2C_CTRL, EN, ENABLE);
- POKE32(I2C_CTRL, value);
+ /* Enable the I2C Controller and set the bus speed mode */
+ value = PEEK32(I2C_CTRL);
+ if (busSpeedMode == 0)
+ value = FIELD_SET(value, I2C_CTRL, MODE, STANDARD);
+ else
+ value = FIELD_SET(value, I2C_CTRL, MODE, FAST);
+ value = FIELD_SET(value, I2C_CTRL, EN, ENABLE);
+ POKE32(I2C_CTRL, value);
- return 0;
+ return 0;
}
void hwI2CClose(void)
{
- unsigned int value;
+ unsigned int value;
- /* Disable I2C controller */
- value = PEEK32(I2C_CTRL);
- value = FIELD_SET(value, I2C_CTRL, EN, DISABLE);
- POKE32(I2C_CTRL, value);
+ /* Disable I2C controller */
+ value = PEEK32(I2C_CTRL);
+ value = FIELD_SET(value, I2C_CTRL, EN, DISABLE);
+ POKE32(I2C_CTRL, value);
- /* Disable I2C Power */
- enableI2C(0);
+ /* Disable I2C Power */
+ enableI2C(0);
- /* 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);
- POKE32(GPIO_MUX, value);
+ /* 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);
+ POKE32(GPIO_MUX, value);
}
static long hwI2CWaitTXDone(void)
{
- unsigned int timeout;
+ unsigned int timeout;
- /* Wait until the transfer is completed. */
- timeout = HWI2C_WAIT_TIMEOUT;
+ /* Wait until the transfer is completed. */
+ timeout = HWI2C_WAIT_TIMEOUT;
while ((FIELD_GET(PEEK32(I2C_STATUS), I2C_STATUS, TX) != I2C_STATUS_TX_COMPLETED) &&
- (timeout != 0))
+ (timeout != 0))
timeout--;
if (timeout == 0)
- return (-1);
+ return (-1);
- return 0;
+ return 0;
}
@@ -91,53 +91,52 @@
* Total number of bytes those are actually written.
*/
static unsigned int hwI2CWriteData(
- unsigned char deviceAddress,
- unsigned int length,
- unsigned char *pBuffer
+ unsigned char deviceAddress,
+ unsigned int length,
+ unsigned char *pBuffer
)
{
- unsigned char count, i;
- unsigned int totalBytes = 0;
+ unsigned char count, i;
+ unsigned int totalBytes = 0;
- /* Set the Device Address */
- POKE32(I2C_SLAVE_ADDRESS, deviceAddress & ~0x01);
+ /* Set the Device Address */
+ POKE32(I2C_SLAVE_ADDRESS, deviceAddress & ~0x01);
- /* Write data.
- * Note:
- * Only 16 byte can be accessed per i2c start instruction.
- */
- do
- {
- /* Reset I2C by writing 0 to I2C_RESET register to clear the previous status. */
- POKE32(I2C_RESET, 0);
+ /* Write data.
+ * Note:
+ * Only 16 byte can be accessed per i2c start instruction.
+ */
+ do {
+ /* Reset I2C by writing 0 to I2C_RESET register to clear the previous status. */
+ POKE32(I2C_RESET, 0);
- /* Set the number of bytes to be written */
- if (length < MAX_HWI2C_FIFO)
- count = length - 1;
- else
- count = MAX_HWI2C_FIFO - 1;
- POKE32(I2C_BYTE_COUNT, count);
+ /* Set the number of bytes to be written */
+ if (length < MAX_HWI2C_FIFO)
+ count = length - 1;
+ else
+ count = MAX_HWI2C_FIFO - 1;
+ POKE32(I2C_BYTE_COUNT, count);
- /* Move the data to the I2C data register */
- for (i = 0; i <= count; i++)
- POKE32(I2C_DATA0 + i, *pBuffer++);
+ /* Move the data to the I2C data register */
+ for (i = 0; i <= count; i++)
+ POKE32(I2C_DATA0 + i, *pBuffer++);
- /* Start the I2C */
- POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
+ /* Start the I2C */
+ POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
- /* Wait until the transfer is completed. */
- if (hwI2CWaitTXDone() != 0)
- break;
+ /* Wait until the transfer is completed. */
+ if (hwI2CWaitTXDone() != 0)
+ break;
- /* Substract length */
- length -= (count + 1);
+ /* Substract length */
+ length -= (count + 1);
- /* Total byte written */
- totalBytes += (count + 1);
+ /* Total byte written */
+ totalBytes += (count + 1);
- } while (length > 0);
+ } while (length > 0);
- return totalBytes;
+ return totalBytes;
}
@@ -158,53 +157,52 @@
* Total number of actual bytes read from the slave device
*/
static unsigned int hwI2CReadData(
- unsigned char deviceAddress,
- unsigned int length,
- unsigned char *pBuffer
+ unsigned char deviceAddress,
+ unsigned int length,
+ unsigned char *pBuffer
)
{
- unsigned char count, i;
- unsigned int totalBytes = 0;
+ unsigned char count, i;
+ unsigned int totalBytes = 0;
- /* Set the Device Address */
- POKE32(I2C_SLAVE_ADDRESS, deviceAddress | 0x01);
+ /* Set the Device Address */
+ POKE32(I2C_SLAVE_ADDRESS, deviceAddress | 0x01);
- /* Read data and save them to the buffer.
- * Note:
- * Only 16 byte can be accessed per i2c start instruction.
- */
- do
- {
- /* Reset I2C by writing 0 to I2C_RESET register to clear all the status. */
- POKE32(I2C_RESET, 0);
+ /* Read data and save them to the buffer.
+ * Note:
+ * Only 16 byte can be accessed per i2c start instruction.
+ */
+ do {
+ /* Reset I2C by writing 0 to I2C_RESET register to clear all the status. */
+ POKE32(I2C_RESET, 0);
- /* Set the number of bytes to be read */
- if (length <= MAX_HWI2C_FIFO)
- count = length - 1;
- else
- count = MAX_HWI2C_FIFO - 1;
- POKE32(I2C_BYTE_COUNT, count);
+ /* Set the number of bytes to be read */
+ if (length <= MAX_HWI2C_FIFO)
+ count = length - 1;
+ else
+ count = MAX_HWI2C_FIFO - 1;
+ POKE32(I2C_BYTE_COUNT, count);
- /* Start the I2C */
- POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
+ /* Start the I2C */
+ POKE32(I2C_CTRL, FIELD_SET(PEEK32(I2C_CTRL), I2C_CTRL, CTRL, START));
- /* Wait until transaction done. */
- if (hwI2CWaitTXDone() != 0)
- break;
+ /* Wait until transaction done. */
+ if (hwI2CWaitTXDone() != 0)
+ break;
- /* Save the data to the given buffer */
- for (i = 0; i <= count; i++)
- *pBuffer++ = PEEK32(I2C_DATA0 + i);
+ /* Save the data to the given buffer */
+ for (i = 0; i <= count; i++)
+ *pBuffer++ = PEEK32(I2C_DATA0 + i);
- /* Substract length by 16 */
- length -= (count + 1);
+ /* Substract length by 16 */
+ length -= (count + 1);
- /* Number of bytes read. */
- totalBytes += (count + 1);
+ /* Number of bytes read. */
+ totalBytes += (count + 1);
- } while (length > 0);
+ } while (length > 0);
- return totalBytes;
+ return totalBytes;
}
@@ -222,16 +220,16 @@
* Register value
*/
unsigned char hwI2CReadReg(
- unsigned char deviceAddress,
- unsigned char registerIndex
+ unsigned char deviceAddress,
+ unsigned char registerIndex
)
{
- unsigned char value = (0xFF);
+ unsigned char value = (0xFF);
- if (hwI2CWriteData(deviceAddress, 1, ®isterIndex) == 1)
- hwI2CReadData(deviceAddress, 1, &value);
+ if (hwI2CWriteData(deviceAddress, 1, ®isterIndex) == 1)
+ hwI2CReadData(deviceAddress, 1, &value);
- return value;
+ return value;
}
@@ -252,19 +250,19 @@
* -1 - Fail
*/
int hwI2CWriteReg(
- unsigned char deviceAddress,
- unsigned char registerIndex,
- unsigned char data
+ unsigned char deviceAddress,
+ unsigned char registerIndex,
+ unsigned char data
)
{
- unsigned char value[2];
+ unsigned char value[2];
- value[0] = registerIndex;
- value[1] = data;
- if (hwI2CWriteData(deviceAddress, 2, value) == 2)
- return 0;
+ value[0] = registerIndex;
+ value[1] = data;
+ if (hwI2CWriteData(deviceAddress, 2, value) == 2)
+ return 0;
- return (-1);
+ return (-1);
}
diff --git a/drivers/staging/sm750fb/ddk750_mode.c b/drivers/staging/sm750fb/ddk750_mode.c
index 74313ff..2399b17 100644
--- a/drivers/staging/sm750fb/ddk750_mode.c
+++ b/drivers/staging/sm750fb/ddk750_mode.c
@@ -20,54 +20,54 @@
x = pModeParam->horizontal_display_end;
y = pModeParam->vertical_display_end;
- /* SM750LE has to set up the top-left and bottom-right
- registers as well.
- Note that normal SM750/SM718 only use those two register for
- auto-centering mode.
- */
- POKE32(CRT_AUTO_CENTERING_TL,
- FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0)
- | FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, LEFT, 0));
+ /* SM750LE has to set up the top-left and bottom-right
+ registers as well.
+ Note that normal SM750/SM718 only use those two register for
+ auto-centering mode.
+ */
+ POKE32(CRT_AUTO_CENTERING_TL,
+ FIELD_VALUE(0, CRT_AUTO_CENTERING_TL, TOP, 0)
+ | 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));
+ 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));
- /* Assume common fields in dispControl have been properly set before
- calling this function.
- This function only sets the extra fields in dispControl.
- */
+ /* Assume common fields in dispControl have been properly set before
+ calling this function.
+ This function only sets the extra fields in dispControl.
+ */
/* Clear bit 29:27 of display control register */
- dispControl &= FIELD_CLEAR(CRT_DISPLAY_CTRL, CLK);
+ 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. */
- if ( x == 800 && y == 600 )
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41);
+ if (x == 800 && y == 600)
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL41);
else if (x == 1024 && y == 768)
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65);
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL65);
else if (x == 1152 && y == 864)
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
else if (x == 1280 && y == 768)
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL80);
else if (x == 1280 && y == 720)
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74);
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL74);
else if (x == 1280 && y == 960)
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
else if (x == 1280 && y == 1024)
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL108);
else /* default to VGA clock */
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25);
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLK, PLL25);
/* Set bit 25:24 of display controller */
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT);
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT);
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CRTSELECT, CRT);
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, RGBBIT, 24BIT);
- /* Set bit 14 of display controller */
- dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW);
+ /* Set bit 14 of display controller */
+ dispControl = FIELD_SET(dispControl, CRT_DISPLAY_CTRL, CLOCK_PHASE, ACTIVE_LOW);
- POKE32(CRT_DISPLAY_CTRL, dispControl);
+ POKE32(CRT_DISPLAY_CTRL, dispControl);
return dispControl;
}
@@ -80,25 +80,25 @@
int ret = 0;
int cnt = 0;
unsigned int ulTmpValue, ulReg;
- if(pll->clockType == SECONDARY_PLL)
- {
+
+ if (pll->clockType == SECONDARY_PLL) {
/* programe secondary pixel clock */
POKE32(CRT_PLL_CTRL, formatPllReg(pll));
- POKE32(CRT_HORIZONTAL_TOTAL,
- FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
- | FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
+ POKE32(CRT_HORIZONTAL_TOTAL,
+ FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
+ | FIELD_VALUE(0, CRT_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
- POKE32(CRT_HORIZONTAL_SYNC,
- FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
- | FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
+ POKE32(CRT_HORIZONTAL_SYNC,
+ FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
+ | FIELD_VALUE(0, CRT_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
- POKE32(CRT_VERTICAL_TOTAL,
- FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
- | FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
+ POKE32(CRT_VERTICAL_TOTAL,
+ FIELD_VALUE(0, CRT_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
+ | FIELD_VALUE(0, CRT_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
- POKE32(CRT_VERTICAL_SYNC,
- FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
- | FIELD_VALUE(0, CRT_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
+ POKE32(CRT_VERTICAL_SYNC,
+ FIELD_VALUE(0, CRT_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
+ | 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)|
@@ -107,9 +107,9 @@
FIELD_SET(0, CRT_DISPLAY_CTRL, PLANE, ENABLE);
- if(getChipType() == SM750LE){
+ if (getChipType() == SM750LE) {
displayControlAdjust_SM750LE(pModeParam, ulTmpValue);
- }else{
+ } else {
ulReg = PEEK32(CRT_DISPLAY_CTRL)
& FIELD_CLEAR(CRT_DISPLAY_CTRL, VSYNC_PHASE)
& FIELD_CLEAR(CRT_DISPLAY_CTRL, HSYNC_PHASE)
@@ -119,45 +119,44 @@
POKE32(CRT_DISPLAY_CTRL, ulTmpValue|ulReg);
}
- }
- else if(pll->clockType == PRIMARY_PLL)
- {
+ } else if (pll->clockType == PRIMARY_PLL) {
unsigned int ulReservedBits;
+
POKE32(PANEL_PLL_CTRL, formatPllReg(pll));
- POKE32(PANEL_HORIZONTAL_TOTAL,
- FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
- | FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
+ POKE32(PANEL_HORIZONTAL_TOTAL,
+ FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, TOTAL, pModeParam->horizontal_total - 1)
+ | FIELD_VALUE(0, PANEL_HORIZONTAL_TOTAL, DISPLAY_END, pModeParam->horizontal_display_end - 1));
- POKE32(PANEL_HORIZONTAL_SYNC,
- FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
- | FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
+ POKE32(PANEL_HORIZONTAL_SYNC,
+ FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, WIDTH, pModeParam->horizontal_sync_width)
+ | FIELD_VALUE(0, PANEL_HORIZONTAL_SYNC, START, pModeParam->horizontal_sync_start - 1));
- POKE32(PANEL_VERTICAL_TOTAL,
- FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
- | FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
+ POKE32(PANEL_VERTICAL_TOTAL,
+ FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, TOTAL, pModeParam->vertical_total - 1)
+ | FIELD_VALUE(0, PANEL_VERTICAL_TOTAL, DISPLAY_END, pModeParam->vertical_display_end - 1));
- POKE32(PANEL_VERTICAL_SYNC,
- FIELD_VALUE(0, PANEL_VERTICAL_SYNC, HEIGHT, pModeParam->vertical_sync_height)
- | FIELD_VALUE(0, PANEL_VERTICAL_SYNC, START, pModeParam->vertical_sync_start - 1));
+ POKE32(PANEL_VERTICAL_SYNC,
+ 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)|
- FIELD_SET(0, PANEL_DISPLAY_CTRL, PLANE, ENABLE);
+ 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, VSYNC, ACTIVE_LOW);
+ 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, VSYNC, ACTIVE_LOW);
- ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
- & FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE)
- & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
- & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
- & FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
- & FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE);
+ ulReg = (PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits)
+ & FIELD_CLEAR(PANEL_DISPLAY_CTRL, CLOCK_PHASE)
+ & FIELD_CLEAR(PANEL_DISPLAY_CTRL, VSYNC_PHASE)
+ & FIELD_CLEAR(PANEL_DISPLAY_CTRL, HSYNC_PHASE)
+ & FIELD_CLEAR(PANEL_DISPLAY_CTRL, TIMING)
+ & FIELD_CLEAR(PANEL_DISPLAY_CTRL, PLANE);
/* May a hardware bug or just my test chip (not confirmed).
@@ -170,16 +169,14 @@
POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
#if 1
- while((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg))
- {
+ while ((PEEK32(PANEL_DISPLAY_CTRL) & ~ulReservedBits) != (ulTmpValue|ulReg)) {
cnt++;
- if(cnt > 1000)
+ if (cnt > 1000)
break;
POKE32(PANEL_DISPLAY_CTRL, ulTmpValue|ulReg);
}
#endif
- }
- else{
+ } else {
ret = -1;
}
return ret;
@@ -189,11 +186,12 @@
{
pll_value_t pll;
unsigned int uiActualPixelClk;
+
pll.inputFreq = DEFAULT_INPUT_CLOCK;
pll.clockType = clock;
uiActualPixelClk = calcPllValue(parm->pixel_clock, &pll);
- if(getChipType() == SM750LE){
+ if (getChipType() == SM750LE) {
/* set graphic mode via IO method */
outb_p(0x88, 0x3d4);
outb_p(0x06, 0x3d5);
diff --git a/drivers/staging/sm750fb/ddk750_mode.h b/drivers/staging/sm750fb/ddk750_mode.h
index 4e8fab3..e846dc2 100644
--- a/drivers/staging/sm750fb/ddk750_mode.h
+++ b/drivers/staging/sm750fb/ddk750_mode.h
@@ -3,37 +3,35 @@
#include "ddk750_chip.h"
-typedef enum _spolarity_t
-{
- POS = 0, /* positive */
- NEG, /* negative */
+typedef enum _spolarity_t {
+ POS = 0, /* positive */
+ NEG, /* negative */
}
spolarity_t;
-typedef struct _mode_parameter_t
-{
- /* Horizontal timing. */
- unsigned long horizontal_total;
- unsigned long horizontal_display_end;
- unsigned long horizontal_sync_start;
- unsigned long horizontal_sync_width;
- spolarity_t horizontal_sync_polarity;
+typedef struct _mode_parameter_t {
+ /* Horizontal timing. */
+ unsigned long horizontal_total;
+ unsigned long horizontal_display_end;
+ unsigned long horizontal_sync_start;
+ unsigned long horizontal_sync_width;
+ spolarity_t horizontal_sync_polarity;
- /* Vertical timing. */
- unsigned long vertical_total;
- unsigned long vertical_display_end;
- unsigned long vertical_sync_start;
- unsigned long vertical_sync_height;
- spolarity_t vertical_sync_polarity;
+ /* Vertical timing. */
+ unsigned long vertical_total;
+ unsigned long vertical_display_end;
+ unsigned long vertical_sync_start;
+ unsigned long vertical_sync_height;
+ spolarity_t vertical_sync_polarity;
- /* Refresh timing. */
- unsigned long pixel_clock;
- unsigned long horizontal_frequency;
- unsigned long vertical_frequency;
+ /* Refresh timing. */
+ unsigned long pixel_clock;
+ unsigned long horizontal_frequency;
+ unsigned long vertical_frequency;
- /* Clock Phase. This clock phase only applies to Panel. */
- spolarity_t clock_phase_polarity;
+ /* Clock Phase. This clock phase only applies to Panel. */
+ spolarity_t clock_phase_polarity;
}
mode_parameter_t;
diff --git a/drivers/staging/sm750fb/ddk750_power.c b/drivers/staging/sm750fb/ddk750_power.c
index 1e5f398..e580dab 100644
--- a/drivers/staging/sm750fb/ddk750_power.c
+++ b/drivers/staging/sm750fb/ddk750_power.c
@@ -5,21 +5,23 @@
void ddk750_setDPMS(DPMS_t state)
{
unsigned int value;
- if(getChipType() == SM750LE){
+
+ if (getChipType() == SM750LE) {
value = PEEK32(CRT_DISPLAY_CTRL);
- POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(value, CRT_DISPLAY_CTRL, DPMS, state));
- }else{
+ POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(value, CRT_DISPLAY_CTRL,
+ DPMS, state));
+ } else {
value = PEEK32(SYSTEM_CTRL);
- value= FIELD_VALUE(value, SYSTEM_CTRL, DPMS, state);
+ value = FIELD_VALUE(value, SYSTEM_CTRL, DPMS, state);
POKE32(SYSTEM_CTRL, value);
}
}
unsigned int getPowerMode(void)
{
- if(getChipType() == SM750LE)
+ if (getChipType() == SM750LE)
return 0;
- return (FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE));
+ return FIELD_GET(PEEK32(POWER_MODE_CTRL), POWER_MODE_CTRL, MODE);
}
@@ -29,76 +31,74 @@
*/
void setPowerMode(unsigned int powerMode)
{
- unsigned int control_value = 0;
+ unsigned int control_value = 0;
- control_value = PEEK32(POWER_MODE_CTRL);
+ control_value = PEEK32(POWER_MODE_CTRL);
- if(getChipType() == SM750LE)
+ if (getChipType() == SM750LE)
return;
- switch (powerMode)
- {
- case POWER_MODE_CTRL_MODE_MODE0:
- control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE, MODE0);
- break;
+ switch (powerMode) {
+ case POWER_MODE_CTRL_MODE_MODE0:
+ control_value = FIELD_SET(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);
- break;
+ case POWER_MODE_CTRL_MODE_MODE1:
+ control_value = FIELD_SET(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);
- break;
+ case POWER_MODE_CTRL_MODE_SLEEP:
+ control_value = FIELD_SET(control_value, POWER_MODE_CTRL, MODE,
+ SLEEP);
+ break;
- default:
- break;
- }
+ default:
+ break;
+ }
- /* Set up other fields in Power Control Register */
- if (powerMode == POWER_MODE_CTRL_MODE_SLEEP)
- {
- control_value =
+ /* Set up other fields in Power Control Register */
+ if (powerMode == POWER_MODE_CTRL_MODE_SLEEP) {
+ control_value =
#ifdef VALIDATION_CHIP
- FIELD_SET( control_value, POWER_MODE_CTRL, 336CLK, OFF) |
+ FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, OFF) |
#endif
- FIELD_SET( control_value, POWER_MODE_CTRL, OSC_INPUT, OFF);
- }
- else
- {
- control_value =
+ FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT, OFF);
+ } else {
+ control_value =
#ifdef VALIDATION_CHIP
- FIELD_SET( control_value, POWER_MODE_CTRL, 336CLK, ON) |
+ FIELD_SET(control_value, POWER_MODE_CTRL, 336CLK, ON) |
#endif
- FIELD_SET( control_value, POWER_MODE_CTRL, OSC_INPUT, ON);
- }
+ FIELD_SET(control_value, POWER_MODE_CTRL, OSC_INPUT, ON);
+ }
- /* Program new power mode. */
- POKE32(POWER_MODE_CTRL, control_value);
+ /* Program new power mode. */
+ POKE32(POWER_MODE_CTRL, control_value);
}
void setCurrentGate(unsigned int gate)
{
- unsigned int gate_reg;
- unsigned int mode;
+ unsigned int gate_reg;
+ unsigned int mode;
- /* Get current power mode. */
- mode = getPowerMode();
+ /* Get current power mode. */
+ mode = getPowerMode();
- switch (mode)
- {
- case POWER_MODE_CTRL_MODE_MODE0:
- gate_reg = MODE0_GATE;
- break;
+ switch (mode) {
+ case POWER_MODE_CTRL_MODE_MODE0:
+ gate_reg = MODE0_GATE;
+ break;
- case POWER_MODE_CTRL_MODE_MODE1:
- gate_reg = MODE1_GATE;
- break;
+ case POWER_MODE_CTRL_MODE_MODE1:
+ gate_reg = MODE1_GATE;
+ break;
- default:
- gate_reg = MODE0_GATE;
- break;
- }
- POKE32(gate_reg, gate);
+ default:
+ gate_reg = MODE0_GATE;
+ break;
+ }
+ POKE32(gate_reg, gate);
}
@@ -108,21 +108,18 @@
*/
void enable2DEngine(unsigned int enable)
{
- uint32_t gate;
+ uint32_t gate;
- gate = PEEK32(CURRENT_GATE);
- if (enable)
- {
- gate = FIELD_SET(gate, CURRENT_GATE, DE, ON);
- gate = FIELD_SET(gate, CURRENT_GATE, CSC, ON);
- }
- else
- {
- gate = FIELD_SET(gate, CURRENT_GATE, DE, OFF);
- gate = FIELD_SET(gate, CURRENT_GATE, CSC, OFF);
- }
+ gate = PEEK32(CURRENT_GATE);
+ if (enable) {
+ gate = FIELD_SET(gate, CURRENT_GATE, DE, ON);
+ gate = FIELD_SET(gate, CURRENT_GATE, CSC, ON);
+ } else {
+ gate = FIELD_SET(gate, CURRENT_GATE, DE, OFF);
+ gate = FIELD_SET(gate, CURRENT_GATE, CSC, OFF);
+ }
- setCurrentGate(gate);
+ setCurrentGate(gate);
}
@@ -131,58 +128,56 @@
*/
void enableZVPort(unsigned int enable)
{
- uint32_t gate;
+ uint32_t gate;
- /* Enable ZV Port Gate */
- gate = PEEK32(CURRENT_GATE);
- if (enable)
- {
- gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, ON);
+ /* Enable ZV Port Gate */
+ gate = PEEK32(CURRENT_GATE);
+ if (enable) {
+ gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, ON);
#if 1
- /* Using Software I2C */
- gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
+ /* Using Software I2C */
+ gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
#else
- /* Using Hardware I2C */
- gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON);
+ /* Using Hardware I2C */
+ gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON);
#endif
- }
- else
- {
- /* Disable ZV Port Gate. There is no way to know whether the GPIO pins are being used
- or not. Therefore, do not disable the GPIO gate. */
- gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, OFF);
- }
+ } else {
+ /* Disable ZV Port Gate. There is no way to know whether the
+ GPIO pins are being used or not. Therefore, do not disable the
+ GPIO gate. */
+ gate = FIELD_SET(gate, CURRENT_GATE, ZVPORT, OFF);
+ }
- setCurrentGate(gate);
+ setCurrentGate(gate);
}
void enableSSP(unsigned int enable)
{
- uint32_t gate;
+ uint32_t gate;
- /* Enable SSP Gate */
- gate = PEEK32(CURRENT_GATE);
- if (enable)
- gate = FIELD_SET(gate, CURRENT_GATE, SSP, ON);
- else
- gate = FIELD_SET(gate, CURRENT_GATE, SSP, OFF);
+ /* Enable SSP Gate */
+ gate = PEEK32(CURRENT_GATE);
+ if (enable)
+ gate = FIELD_SET(gate, CURRENT_GATE, SSP, ON);
+ else
+ gate = FIELD_SET(gate, CURRENT_GATE, SSP, OFF);
- setCurrentGate(gate);
+ setCurrentGate(gate);
}
void enableDMA(unsigned int enable)
{
- uint32_t gate;
+ uint32_t gate;
- /* Enable DMA Gate */
- gate = PEEK32(CURRENT_GATE);
- if (enable)
- gate = FIELD_SET(gate, CURRENT_GATE, DMA, ON);
- else
- gate = FIELD_SET(gate, CURRENT_GATE, DMA, OFF);
+ /* Enable DMA Gate */
+ gate = PEEK32(CURRENT_GATE);
+ if (enable)
+ gate = FIELD_SET(gate, CURRENT_GATE, DMA, ON);
+ else
+ gate = FIELD_SET(gate, CURRENT_GATE, DMA, OFF);
- setCurrentGate(gate);
+ setCurrentGate(gate);
}
/*
@@ -190,16 +185,16 @@
*/
void enableGPIO(unsigned int enable)
{
- uint32_t gate;
+ uint32_t gate;
- /* Enable GPIO Gate */
- gate = PEEK32(CURRENT_GATE);
- if (enable)
- gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
- else
- gate = FIELD_SET(gate, CURRENT_GATE, GPIO, OFF);
+ /* Enable GPIO Gate */
+ gate = PEEK32(CURRENT_GATE);
+ if (enable)
+ gate = FIELD_SET(gate, CURRENT_GATE, GPIO, ON);
+ else
+ gate = FIELD_SET(gate, CURRENT_GATE, GPIO, OFF);
- setCurrentGate(gate);
+ setCurrentGate(gate);
}
/*
@@ -207,16 +202,16 @@
*/
void enablePWM(unsigned int enable)
{
- uint32_t gate;
+ uint32_t gate;
- /* Enable PWM Gate */
- gate = PEEK32(CURRENT_GATE);
- if (enable)
- gate = FIELD_SET(gate, CURRENT_GATE, PWM, ON);
- else
- gate = FIELD_SET(gate, CURRENT_GATE, PWM, OFF);
+ /* Enable PWM Gate */
+ gate = PEEK32(CURRENT_GATE);
+ if (enable)
+ gate = FIELD_SET(gate, CURRENT_GATE, PWM, ON);
+ else
+ gate = FIELD_SET(gate, CURRENT_GATE, PWM, OFF);
- setCurrentGate(gate);
+ setCurrentGate(gate);
}
/*
@@ -224,16 +219,16 @@
*/
void enableI2C(unsigned int enable)
{
- uint32_t gate;
+ uint32_t gate;
- /* Enable I2C Gate */
- gate = PEEK32(CURRENT_GATE);
- if (enable)
- gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON);
- else
- gate = FIELD_SET(gate, CURRENT_GATE, I2C, OFF);
+ /* Enable I2C Gate */
+ gate = PEEK32(CURRENT_GATE);
+ if (enable)
+ gate = FIELD_SET(gate, CURRENT_GATE, I2C, ON);
+ else
+ gate = FIELD_SET(gate, CURRENT_GATE, I2C, OFF);
- setCurrentGate(gate);
+ setCurrentGate(gate);
}
diff --git a/drivers/staging/sm750fb/ddk750_power.h b/drivers/staging/sm750fb/ddk750_power.h
index 4e00955..b7cf6b2 100644
--- a/drivers/staging/sm750fb/ddk750_power.h
+++ b/drivers/staging/sm750fb/ddk750_power.h
@@ -1,12 +1,11 @@
#ifndef DDK750_POWER_H__
#define DDK750_POWER_H__
-typedef enum _DPMS_t
-{
- crtDPMS_ON = 0x0,
- crtDPMS_STANDBY = 0x1,
- crtDPMS_SUSPEND = 0x2,
- crtDPMS_OFF = 0x3,
+typedef enum _DPMS_t {
+ crtDPMS_ON = 0x0,
+ crtDPMS_STANDBY = 0x1,
+ crtDPMS_SUSPEND = 0x2,
+ crtDPMS_OFF = 0x3,
}
DPMS_t;
diff --git a/drivers/staging/sm750fb/ddk750_reg.h b/drivers/staging/sm750fb/ddk750_reg.h
index 1a40dc2..2995625 100644
--- a/drivers/staging/sm750fb/ddk750_reg.h
+++ b/drivers/staging/sm750fb/ddk750_reg.h
@@ -1640,9 +1640,9 @@
/* CRT Graphics Control */
#define CRT_DISPLAY_CTRL 0x080200
-#define CRT_DISPLAY_CTRL_RESERVED_1_MASK 31:27
-#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_DISABLE 0
-#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_ENABLE 0x1F
+#define CRT_DISPLAY_CTRL_RESERVED_1_MASK 31:27
+#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_DISABLE 0
+#define CRT_DISPLAY_CTRL_RESERVED_1_MASK_ENABLE 0x1F
/* SM750LE definition */
#define CRT_DISPLAY_CTRL_DPMS 31:30
@@ -1664,9 +1664,9 @@
#define CRT_DISPLAY_CTRL_SHIFT_VGA_DAC_ENABLE 0
-#define CRT_DISPLAY_CTRL_RESERVED_2_MASK 25:24
-#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_ENABLE 3
-#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_DISABLE 0
+#define CRT_DISPLAY_CTRL_RESERVED_2_MASK 25:24
+#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_ENABLE 3
+#define CRT_DISPLAY_CTRL_RESERVED_2_MASK_DISABLE 0
/* SM750LE definition */
#define CRT_DISPLAY_CTRL_CRTSELECT 25:25
@@ -1677,11 +1677,11 @@
#define CRT_DISPLAY_CTRL_RGBBIT_12BIT 1
-#define CRT_DISPLAY_CTRL_RESERVED_3_MASK 15:15
+#define CRT_DISPLAY_CTRL_RESERVED_3_MASK 15:15
#define CRT_DISPLAY_CTRL_RESERVED_3_MASK_DISABLE 0
#define CRT_DISPLAY_CTRL_RESERVED_3_MASK_ENABLE 1
-#define CRT_DISPLAY_CTRL_RESERVED_4_MASK 9:9
+#define CRT_DISPLAY_CTRL_RESERVED_4_MASK 9:9
#define CRT_DISPLAY_CTRL_RESERVED_4_MASK_DISABLE 0
#define CRT_DISPLAY_CTRL_RESERVED_4_MASK_ENABLE 1
@@ -1882,7 +1882,7 @@
#endif
/* sm750le new register to control panel output */
-#define DISPLAY_CONTROL_750LE 0x80288
+#define DISPLAY_CONTROL_750LE 0x80288
/* Palette RAM */
/* Panel Palette register starts at 0x080400 ~ 0x0807FC */
diff --git a/drivers/staging/sm750fb/ddk750_sii164.c b/drivers/staging/sm750fb/ddk750_sii164.c
index b6395b8..0bdf3db 100644
--- a/drivers/staging/sm750fb/ddk750_sii164.c
+++ b/drivers/staging/sm750fb/ddk750_sii164.c
@@ -36,12 +36,12 @@
*/
unsigned short sii164GetVendorID(void)
{
- unsigned short vendorID;
+ unsigned short vendorID;
- vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
- (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
+ vendorID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_HIGH) << 8) |
+ (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_VENDOR_ID_LOW);
- return vendorID;
+ return vendorID;
}
/*
@@ -53,12 +53,12 @@
*/
unsigned short sii164GetDeviceID(void)
{
- unsigned short deviceID;
+ unsigned short deviceID;
- deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
- (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
+ deviceID = ((unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_HIGH) << 8) |
+ (unsigned short) i2cReadReg(SII164_I2C_ADDRESS, SII164_DEVICE_ID_LOW);
- return deviceID;
+ return deviceID;
}
@@ -113,132 +113,130 @@
* -1 - Fail.
*/
long sii164InitChip(
- unsigned char edgeSelect,
- unsigned char busSelect,
- unsigned char dualEdgeClkSelect,
- unsigned char hsyncEnable,
- unsigned char vsyncEnable,
- unsigned char deskewEnable,
- unsigned char deskewSetting,
- unsigned char continuousSyncEnable,
- unsigned char pllFilterEnable,
- unsigned char pllFilterValue
+ unsigned char edgeSelect,
+ unsigned char busSelect,
+ unsigned char dualEdgeClkSelect,
+ unsigned char hsyncEnable,
+ unsigned char vsyncEnable,
+ unsigned char deskewEnable,
+ unsigned char deskewSetting,
+ unsigned char continuousSyncEnable,
+ unsigned char pllFilterEnable,
+ unsigned char pllFilterValue
)
{
unsigned char config;
- /* Initialize the i2c bus */
+ /* Initialize the i2c bus */
#ifdef USE_HW_I2C
- /* Use fast mode. */
- hwI2CInit(1);
+ /* Use fast mode. */
+ hwI2CInit(1);
#else
- swI2CInit(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
+ swI2CInit(DEFAULT_I2C_SCL, DEFAULT_I2C_SDA);
#endif
- /* Check if SII164 Chip exists */
- if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID))
- {
- /*
- * Initialize SII164 controller chip.
- */
+ /* Check if SII164 Chip exists */
+ if ((sii164GetVendorID() == SII164_VENDOR_ID) && (sii164GetDeviceID() == SII164_DEVICE_ID)) {
+ /*
+ * Initialize SII164 controller chip.
+ */
- /* Select the edge */
- if (edgeSelect == 0)
- config = SII164_CONFIGURATION_LATCH_FALLING;
- else
- config = SII164_CONFIGURATION_LATCH_RISING;
+ /* Select the edge */
+ if (edgeSelect == 0)
+ config = SII164_CONFIGURATION_LATCH_FALLING;
+ else
+ config = SII164_CONFIGURATION_LATCH_RISING;
- /* Select bus wide */
- if (busSelect == 0)
- config |= SII164_CONFIGURATION_BUS_12BITS;
- else
- config |= SII164_CONFIGURATION_BUS_24BITS;
+ /* Select bus wide */
+ if (busSelect == 0)
+ config |= SII164_CONFIGURATION_BUS_12BITS;
+ else
+ config |= SII164_CONFIGURATION_BUS_24BITS;
- /* Select Dual/Single Edge Clock */
- if (dualEdgeClkSelect == 0)
- config |= SII164_CONFIGURATION_CLOCK_SINGLE;
- else
- config |= SII164_CONFIGURATION_CLOCK_DUAL;
+ /* Select Dual/Single Edge Clock */
+ if (dualEdgeClkSelect == 0)
+ config |= SII164_CONFIGURATION_CLOCK_SINGLE;
+ else
+ config |= SII164_CONFIGURATION_CLOCK_DUAL;
- /* Select HSync Enable */
- if (hsyncEnable == 0)
- config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
- else
- config |= SII164_CONFIGURATION_HSYNC_AS_IS;
+ /* Select HSync Enable */
+ if (hsyncEnable == 0)
+ config |= SII164_CONFIGURATION_HSYNC_FORCE_LOW;
+ else
+ config |= SII164_CONFIGURATION_HSYNC_AS_IS;
- /* Select VSync Enable */
- if (vsyncEnable == 0)
- config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
- else
- config |= SII164_CONFIGURATION_VSYNC_AS_IS;
+ /* Select VSync Enable */
+ if (vsyncEnable == 0)
+ config |= SII164_CONFIGURATION_VSYNC_FORCE_LOW;
+ else
+ config |= SII164_CONFIGURATION_VSYNC_AS_IS;
- i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
+ i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
- /* De-skew enabled with default 111b value.
- This will fix some artifacts problem in some mode on board 2.2.
- Somehow this fix does not affect board 2.1.
- */
- if (deskewEnable == 0)
- config = SII164_DESKEW_DISABLE;
- else
- config = SII164_DESKEW_ENABLE;
+ /* De-skew enabled with default 111b value.
+ This will fix some artifacts problem in some mode on board 2.2.
+ Somehow this fix does not affect board 2.1.
+ */
+ if (deskewEnable == 0)
+ config = SII164_DESKEW_DISABLE;
+ else
+ config = SII164_DESKEW_ENABLE;
- switch (deskewSetting)
- {
- case 0:
- config |= SII164_DESKEW_1_STEP;
- break;
- case 1:
- config |= SII164_DESKEW_2_STEP;
- break;
- case 2:
- config |= SII164_DESKEW_3_STEP;
- break;
- case 3:
- config |= SII164_DESKEW_4_STEP;
- break;
- case 4:
- config |= SII164_DESKEW_5_STEP;
- break;
- case 5:
- config |= SII164_DESKEW_6_STEP;
- break;
- case 6:
- config |= SII164_DESKEW_7_STEP;
- break;
- case 7:
- config |= SII164_DESKEW_8_STEP;
- break;
- }
- i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
+ switch (deskewSetting) {
+ case 0:
+ config |= SII164_DESKEW_1_STEP;
+ break;
+ case 1:
+ config |= SII164_DESKEW_2_STEP;
+ break;
+ case 2:
+ config |= SII164_DESKEW_3_STEP;
+ break;
+ case 3:
+ config |= SII164_DESKEW_4_STEP;
+ break;
+ case 4:
+ config |= SII164_DESKEW_5_STEP;
+ break;
+ case 5:
+ config |= SII164_DESKEW_6_STEP;
+ break;
+ case 6:
+ config |= SII164_DESKEW_7_STEP;
+ break;
+ case 7:
+ config |= SII164_DESKEW_8_STEP;
+ break;
+ }
+ i2cWriteReg(SII164_I2C_ADDRESS, SII164_DESKEW, config);
- /* Enable/Disable Continuous Sync. */
- if (continuousSyncEnable == 0)
- config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
- else
- config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
+ /* Enable/Disable Continuous Sync. */
+ if (continuousSyncEnable == 0)
+ config = SII164_PLL_FILTER_SYNC_CONTINUOUS_DISABLE;
+ else
+ config = SII164_PLL_FILTER_SYNC_CONTINUOUS_ENABLE;
- /* Enable/Disable PLL Filter */
- if (pllFilterEnable == 0)
- config |= SII164_PLL_FILTER_DISABLE;
- else
- config |= SII164_PLL_FILTER_ENABLE;
+ /* Enable/Disable PLL Filter */
+ if (pllFilterEnable == 0)
+ config |= SII164_PLL_FILTER_DISABLE;
+ else
+ config |= SII164_PLL_FILTER_ENABLE;
- /* Set the PLL Filter value */
- config |= ((pllFilterValue & 0x07) << 1);
+ /* Set the PLL Filter value */
+ config |= ((pllFilterValue & 0x07) << 1);
- i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
+ i2cWriteReg(SII164_I2C_ADDRESS, SII164_PLL, config);
- /* Recover from Power Down and enable output. */
- config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
- config |= SII164_CONFIGURATION_POWER_NORMAL;
- i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
+ /* Recover from Power Down and enable output. */
+ config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
+ config |= SII164_CONFIGURATION_POWER_NORMAL;
+ i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
- return 0;
- }
+ return 0;
+ }
- /* Return -1 if initialization fails. */
- return (-1);
+ /* Return -1 if initialization fails. */
+ return (-1);
}
@@ -255,9 +253,9 @@
*/
void sii164ResetChip(void)
{
- /* Power down */
- sii164SetPower(0);
- sii164SetPower(1);
+ /* Power down */
+ sii164SetPower(0);
+ sii164SetPower(1);
}
@@ -268,7 +266,7 @@
*/
char *sii164GetChipString(void)
{
- return gDviCtrlChipName;
+ return gDviCtrlChipName;
}
@@ -280,26 +278,23 @@
* powerUp - Flag to set the power down or up
*/
void sii164SetPower(
- unsigned char powerUp
+ unsigned char powerUp
)
{
- unsigned char config;
+ unsigned char config;
- config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
- if (powerUp == 1)
- {
- /* Power up the chip */
- config &= ~SII164_CONFIGURATION_POWER_MASK;
- config |= SII164_CONFIGURATION_POWER_NORMAL;
- i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
- }
- else
- {
- /* Power down the chip */
- config &= ~SII164_CONFIGURATION_POWER_MASK;
- config |= SII164_CONFIGURATION_POWER_DOWN;
- i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
- }
+ config = i2cReadReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION);
+ if (powerUp == 1) {
+ /* Power up the chip */
+ config &= ~SII164_CONFIGURATION_POWER_MASK;
+ config |= SII164_CONFIGURATION_POWER_NORMAL;
+ i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
+ } else {
+ /* Power down the chip */
+ config &= ~SII164_CONFIGURATION_POWER_MASK;
+ config |= SII164_CONFIGURATION_POWER_DOWN;
+ i2cWriteReg(SII164_I2C_ADDRESS, SII164_CONFIGURATION, config);
+ }
}
@@ -308,31 +303,30 @@
* This function selects the mode of the hot plug detection.
*/
static void sii164SelectHotPlugDetectionMode(
- sii164_hot_plug_mode_t hotPlugMode
+ sii164_hot_plug_mode_t hotPlugMode
)
{
- unsigned char detectReg;
+ unsigned char detectReg;
- detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
- switch (hotPlugMode)
- {
- case SII164_HOTPLUG_DISABLE:
- detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
- break;
- case SII164_HOTPLUG_USE_MDI:
- detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
- detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
- detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
- break;
- case SII164_HOTPLUG_USE_RSEN:
- detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
- break;
- case SII164_HOTPLUG_USE_HTPLG:
- detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
- break;
- }
+ detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & ~SII164_DETECT_MONITOR_SENSE_OUTPUT_FLAG;
+ switch (hotPlugMode) {
+ case SII164_HOTPLUG_DISABLE:
+ detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HIGH;
+ break;
+ case SII164_HOTPLUG_USE_MDI:
+ detectReg &= ~SII164_DETECT_INTERRUPT_MASK;
+ detectReg |= SII164_DETECT_INTERRUPT_BY_HTPLG_PIN;
+ detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_MDI;
+ break;
+ case SII164_HOTPLUG_USE_RSEN:
+ detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_RSEN;
+ break;
+ case SII164_HOTPLUG_USE_HTPLG:
+ detectReg |= SII164_DETECT_MONITOR_SENSE_OUTPUT_HTPLG;
+ break;
+ }
- i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
+ i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg);
}
/*
@@ -342,18 +336,19 @@
* enableHotPlug - Enable (=1) / disable (=0) Hot Plug detection
*/
void sii164EnableHotPlugDetection(
- unsigned char enableHotPlug
+ unsigned char enableHotPlug
)
{
- unsigned char detectReg;
- detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
+ unsigned char detectReg;
- /* Depending on each DVI controller, need to enable the hot plug based on each
- individual chip design. */
- if (enableHotPlug != 0)
- sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
- else
- sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
+ detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
+
+ /* Depending on each DVI controller, need to enable the hot plug based on each
+ individual chip design. */
+ if (enableHotPlug != 0)
+ sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_USE_MDI);
+ else
+ sii164SelectHotPlugDetectionMode(SII164_HOTPLUG_DISABLE);
}
/*
@@ -366,13 +361,13 @@
*/
unsigned char sii164IsConnected(void)
{
- unsigned char hotPlugValue;
+ unsigned char hotPlugValue;
- hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
- if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
- return 1;
- else
- return 0;
+ hotPlugValue = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_HOT_PLUG_STATUS_MASK;
+ if (hotPlugValue == SII164_DETECT_HOT_PLUG_STATUS_ON)
+ return 1;
+ else
+ return 0;
}
/*
@@ -385,13 +380,13 @@
*/
unsigned char sii164CheckInterrupt(void)
{
- unsigned char detectReg;
+ unsigned char detectReg;
- detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
- if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
- return 1;
- else
- return 0;
+ detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT) & SII164_DETECT_MONITOR_STATE_MASK;
+ if (detectReg == SII164_DETECT_MONITOR_STATE_CHANGE)
+ return 1;
+ else
+ return 0;
}
/*
@@ -400,11 +395,11 @@
*/
void sii164ClearInterrupt(void)
{
- unsigned char detectReg;
+ unsigned char detectReg;
- /* Clear the MDI interrupt */
- detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
- i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
+ /* Clear the MDI interrupt */
+ detectReg = i2cReadReg(SII164_I2C_ADDRESS, SII164_DETECT);
+ i2cWriteReg(SII164_I2C_ADDRESS, SII164_DETECT, detectReg | SII164_DETECT_MONITOR_STATE_CLEAR);
}
#endif
diff --git a/drivers/staging/sm750fb/ddk750_sii164.h b/drivers/staging/sm750fb/ddk750_sii164.h
index 2b4c7d3..f2610c9 100644
--- a/drivers/staging/sm750fb/ddk750_sii164.h
+++ b/drivers/staging/sm750fb/ddk750_sii164.h
@@ -4,27 +4,26 @@
#define USE_DVICHIP
/* Hot Plug detection mode structure */
-typedef enum _sii164_hot_plug_mode_t
-{
- SII164_HOTPLUG_DISABLE = 0, /* Disable Hot Plug output bit (always high). */
- SII164_HOTPLUG_USE_MDI, /* Use Monitor Detect Interrupt bit. */
- SII164_HOTPLUG_USE_RSEN, /* Use Receiver Sense detect bit. */
- SII164_HOTPLUG_USE_HTPLG /* Use Hot Plug detect bit. */
+typedef enum _sii164_hot_plug_mode_t {
+ SII164_HOTPLUG_DISABLE = 0, /* Disable Hot Plug output bit (always high). */
+ SII164_HOTPLUG_USE_MDI, /* Use Monitor Detect Interrupt bit. */
+ SII164_HOTPLUG_USE_RSEN, /* Use Receiver Sense detect bit. */
+ SII164_HOTPLUG_USE_HTPLG /* Use Hot Plug detect bit. */
} sii164_hot_plug_mode_t;
/* Silicon Image SiI164 chip prototype */
long sii164InitChip(
- unsigned char edgeSelect,
- unsigned char busSelect,
- unsigned char dualEdgeClkSelect,
- unsigned char hsyncEnable,
- unsigned char vsyncEnable,
- unsigned char deskewEnable,
- unsigned char deskewSetting,
- unsigned char continuousSyncEnable,
- unsigned char pllFilterEnable,
- unsigned char pllFilterValue
+ unsigned char edgeSelect,
+ unsigned char busSelect,
+ unsigned char dualEdgeClkSelect,
+ unsigned char hsyncEnable,
+ unsigned char vsyncEnable,
+ unsigned char deskewEnable,
+ unsigned char deskewSetting,
+ unsigned char continuousSyncEnable,
+ unsigned char pllFilterEnable,
+ unsigned char pllFilterValue
);
unsigned short sii164GetVendorID(void);
diff --git a/drivers/staging/sm750fb/sm750.c b/drivers/staging/sm750fb/sm750.c
index 8e201f1..07f8afd 100644
--- a/drivers/staging/sm750fb/sm750.c
+++ b/drivers/staging/sm750fb/sm750.c
@@ -24,8 +24,7 @@
#include "modedb.h"
-int smi_indent = 0;
-
+int smi_indent;
/*
* #ifdef __BIG_ENDIAN
@@ -40,17 +39,15 @@
typedef int (*PROC_SPEC_MAP)(struct lynx_share*, struct pci_dev*);
typedef int (*PROC_SPEC_INITHW)(struct lynx_share*, struct pci_dev*);
-
/* common var for all device */
static int g_hwcursor = 1;
static int g_noaccel;
static int g_nomtrr;
static const char *g_fbmode[] = {NULL, NULL};
static const char *g_def_fbmode = "800x600-16@60";
-static char *g_settings = NULL;
+static char *g_settings;
static int g_dualview;
-static char *g_option = NULL;
-
+static char *g_option;
static const struct fb_videomode lynx750_ext[] = {
/* 1024x600-60 VESA [1.71:1] */
@@ -115,8 +112,6 @@
};
-
-
/* no hardware cursor supported under version 2.6.10, kernel bug */
static int lynxfb_ops_cursor(struct fb_info *info, struct fb_cursor *fbcursor)
{
@@ -149,18 +144,17 @@
/* get the 16bit color of kernel means */
u16 fg, bg;
- fg = ((info->cmap.red[fbcursor->image.fg_color] & 0xf800))|
- ((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5)|
+ fg = ((info->cmap.red[fbcursor->image.fg_color] & 0xf800)) |
+ ((info->cmap.green[fbcursor->image.fg_color] & 0xfc00) >> 5) |
((info->cmap.blue[fbcursor->image.fg_color] & 0xf800) >> 11);
- bg = ((info->cmap.red[fbcursor->image.bg_color] & 0xf800))|
- ((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5)|
+ bg = ((info->cmap.red[fbcursor->image.bg_color] & 0xf800)) |
+ ((info->cmap.green[fbcursor->image.bg_color] & 0xfc00) >> 5) |
((info->cmap.blue[fbcursor->image.bg_color] & 0xf800) >> 11);
cursor->setColor(cursor, fg, bg);
}
-
if (fbcursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
cursor->setData(cursor,
fbcursor->rop,
@@ -188,14 +182,17 @@
par = info->par;
share = par->share;
- /* each time 2d function begin to work,below three variable always need
- * be set, seems we can put them together in some place */
+ /*
+ * each time 2d function begin to work,below three variable always need
+ * be set, seems we can put them together in some place
+ */
base = par->crtc.oScreen;
pitch = info->fix.line_length;
Bpp = info->var.bits_per_pixel >> 3;
- color = (Bpp == 1)?region->color:((u32 *)info->pseudo_palette)[region->color];
- rop = (region->rop != ROP_COPY) ? HW_ROP2_XOR:HW_ROP2_COPY;
+ color = (Bpp == 1) ? region->color :
+ ((u32 *)info->pseudo_palette)[region->color];
+ rop = (region->rop != ROP_COPY) ? HW_ROP2_XOR : HW_ROP2_COPY;
/*
* If not use spin_lock,system will die if user load driver
@@ -223,8 +220,10 @@
par = info->par;
share = par->share;
- /* each time 2d function begin to work,below three variable always need
- * be set, seems we can put them together in some place */
+ /*
+ * each time 2d function begin to work,below three variable always need
+ * be set, seems we can put them together in some place
+ */
base = par->crtc.oScreen;
pitch = info->fix.line_length;
Bpp = info->var.bits_per_pixel >> 3;
@@ -254,28 +253,29 @@
par = info->par;
share = par->share;
- /* each time 2d function begin to work,below three variable always need
- * be set, seems we can put them together in some place */
+ /*
+ * each time 2d function begin to work,below three variable always need
+ * be set, seems we can put them together in some place
+ */
base = par->crtc.oScreen;
pitch = info->fix.line_length;
Bpp = info->var.bits_per_pixel >> 3;
- if (image->depth == 1) {
- if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
- info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
- fgcol = ((u32 *)info->pseudo_palette)[image->fg_color];
- bgcol = ((u32 *)info->pseudo_palette)[image->bg_color];
- } else {
- fgcol = image->fg_color;
- bgcol = image->bg_color;
- }
- goto _do_work;
- }
/* TODO: Implement hardware acceleration for image->depth > 1 */
- cfb_imageblit(info, image);
- return;
+ if (image->depth != 1) {
+ cfb_imageblit(info, image);
+ return;
+ }
-_do_work:
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+ info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+ fgcol = ((u32 *)info->pseudo_palette)[image->fg_color];
+ bgcol = ((u32 *)info->pseudo_palette)[image->bg_color];
+ } else {
+ fgcol = image->fg_color;
+ bgcol = image->bg_color;
+ }
+
/*
* If not use spin_lock, system will die if user load driver
* and immediately unload driver frequently (dual)
@@ -284,7 +284,7 @@
spin_lock(&share->slock);
share->accel.de_imageblit(&share->accel,
- image->data, image->width>>3, 0,
+ image->data, image->width >> 3, 0,
base, pitch, Bpp,
image->dx, image->dy,
image->width, image->height,
@@ -298,18 +298,13 @@
{
struct lynxfb_par *par;
struct lynxfb_crtc *crtc;
- int ret;
-
if (!info)
return -EINVAL;
- ret = 0;
par = info->par;
crtc = &par->crtc;
- ret = crtc->proc_panDisplay(crtc, var, info);
-
- return ret;
+ return crtc->proc_panDisplay(crtc, var, info);
}
static int lynxfb_ops_set_par(struct fb_info *info)
@@ -340,9 +335,10 @@
fix->line_length = line_length;
pr_info("fix->line_length = %d\n", fix->line_length);
- /* var->red,green,blue,transp are need to be set by driver
+ /*
+ * var->red,green,blue,transp are need to be set by driver
* and these data should be set before setcolreg routine
- * */
+ */
switch (var->bits_per_pixel) {
case 8:
@@ -466,7 +462,6 @@
int ret;
-
ret = 0;
share = pci_get_drvdata(pdev);
@@ -478,7 +473,6 @@
return ret;
}
-
if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) {
pci_restore_state(pdev);
ret = pci_enable_device(pdev);
@@ -493,7 +487,6 @@
hw_sm750_inithw(share, pdev);
-
info = share->fbinfo[0];
if (info) {
@@ -518,7 +511,6 @@
fb_set_suspend(info, 0);
}
-
console_unlock();
return ret;
}
@@ -534,7 +526,6 @@
int ret;
resource_size_t request;
-
par = info->par;
crtc = &par->crtc;
output = &par->output;
@@ -546,7 +537,6 @@
var->yres,
var->bits_per_pixel);
-
switch (var->bits_per_pixel) {
case 8:
case 16:
@@ -617,7 +607,6 @@
return ret;
}
-
static int lynxfb_ops_setcolreg(unsigned regno,
unsigned red,
unsigned green,
@@ -652,7 +641,6 @@
goto exit;
}
-
if (info->fix.visual == FB_VISUAL_TRUECOLOR && regno < 256) {
u32 val;
@@ -699,7 +687,8 @@
output = &par->output;
crtc = &par->crtc;
- crtc->vidmem_size = (share->dual)?share->vidmem_size>>1:share->vidmem_size;
+ crtc->vidmem_size = (share->dual) ? share->vidmem_size >> 1 :
+ share->vidmem_size;
/* setup crtc and output member */
spec_share->hwCursor = g_hwcursor;
@@ -716,10 +705,12 @@
output->proc_setMode = hw_sm750_output_setMode;
output->proc_checkMode = hw_sm750_output_checkMode;
- output->proc_setBLANK = (share->revid == SM750LE_REVISION_ID)?hw_sm750le_setBLANK:hw_sm750_setBLANK;
+ output->proc_setBLANK = (share->revid == SM750LE_REVISION_ID) ?
+ hw_sm750le_setBLANK : hw_sm750_setBLANK;
output->clear = hw_sm750_output_clear;
/* chip specific phase */
- share->accel.de_wait = (share->revid == SM750LE_REVISION_ID)?hw_sm750le_deWait : hw_sm750_deWait;
+ share->accel.de_wait = (share->revid == SM750LE_REVISION_ID) ?
+ hw_sm750le_deWait : hw_sm750_deWait;
switch (spec_share->state.dataflow) {
case sm750_simul_pri:
output->paths = sm750_pnc;
@@ -782,7 +773,6 @@
.fb_cursor = lynxfb_ops_cursor,
};
-
static int lynxfb_set_fbinfo(struct fb_info *info, int index)
{
int i;
@@ -803,7 +793,6 @@
"kernel HELPERS prepared vesa_modes",
};
-
static const char *fixId[2] = {
"sm750_fb1", "sm750_fb2",
};
@@ -824,15 +813,16 @@
sm750fb_set_drv(par);
lynxfb_ops.fb_pan_display = lynxfb_ops_pan_display;
-
- /* set current cursor variable and proc pointer,
- * must be set after crtc member initialized */
+ /*
+ * set current cursor variable and proc pointer,
+ * must be set after crtc member initialized
+ */
crtc->cursor.offset = crtc->oScreen + crtc->vidmem_size - 1024;
crtc->cursor.mmio = share->pvReg + 0x800f0 + (int)crtc->channel * 0x140;
pr_info("crtc->cursor.mmio = %p\n", crtc->cursor.mmio);
crtc->cursor.maxH = crtc->cursor.maxW = 64;
- crtc->cursor.size = crtc->cursor.maxH*crtc->cursor.maxW*2/8;
+ crtc->cursor.size = crtc->cursor.maxH * crtc->cursor.maxW * 2 / 8;
crtc->cursor.disable = hw_cursor_disable;
crtc->cursor.enable = hw_cursor_enable;
crtc->cursor.setColor = hw_cursor_setColor;
@@ -841,7 +831,6 @@
crtc->cursor.setData = hw_cursor_setData;
crtc->cursor.vstart = share->pvMem + crtc->cursor.offset;
-
crtc->cursor.share = share;
memset_io(crtc->cursor.vstart, 0, crtc->cursor.size);
if (!g_hwcursor) {
@@ -849,7 +838,6 @@
crtc->cursor.disable(&crtc->cursor);
}
-
/* set info->fbops, must be set before fb_find_mode */
if (!share->accel_off) {
/* use 2d acceleration */
@@ -865,7 +853,6 @@
g_fbmode[index] = g_fbmode[0];
}
-
for (i = 0; i < 3; i++) {
ret = fb_find_mode(var, info, g_fbmode[index],
@@ -917,13 +904,13 @@
/* set info */
line_length = PADDING(crtc->line_pad,
- (var->xres_virtual * var->bits_per_pixel/8));
+ (var->xres_virtual * var->bits_per_pixel / 8));
info->pseudo_palette = &par->pseudo_palette[0];
info->screen_base = crtc->vScreen;
pr_debug("screen_base vaddr = %p\n", info->screen_base);
info->screen_size = line_length * var->yres_virtual;
- info->flags = FBINFO_FLAG_DEFAULT|0;
+ info->flags = FBINFO_FLAG_DEFAULT | 0;
/* set info->fix */
fix->type = FB_TYPE_PACKED_PIXELS;
@@ -935,15 +922,15 @@
strlcpy(fix->id, fixId[index], sizeof(fix->id));
-
fix->smem_start = crtc->oScreen + share->vidmem_start;
pr_info("fix->smem_start = %lx\n", fix->smem_start);
- /* according to mmap experiment from user space application,
+ /*
+ * according to mmap experiment from user space application,
* fix->mmio_len should not larger than virtual size
* (xres_virtual x yres_virtual x ByPP)
* Below line maybe buggy when user mmap fb dev node and write
* data into the bound over virtual size
- * */
+ */
fix->smem_len = crtc->vidmem_size;
pr_info("fix->smem_len = %x\n", fix->smem_len);
info->screen_size = fix->smem_len;
@@ -967,7 +954,7 @@
var->accel_flags = 0;
var->vmode = FB_VMODE_NONINTERLACED;
- pr_debug("#1 show info->cmap : \nstart=%d,len=%d,red=%p,green=%p,blue=%p,transp=%p\n",
+ pr_debug("#1 show info->cmap :\nstart=%d,len=%d,red=%p,green=%p,blue=%p,transp=%p\n",
info->cmap.start, info->cmap.len,
info->cmap.red, info->cmap.green, info->cmap.blue,
info->cmap.transp);
@@ -998,7 +985,6 @@
#endif
int swap;
-
spec_share = container_of(share, struct sm750_share, share);
#ifdef CAP_EXPENSIION
exp_res = NULL;
@@ -1096,15 +1082,16 @@
size_t spec_offset = 0;
int fbidx;
-
/* enable device */
if (pci_enable_device(pdev)) {
pr_err("can not enable device.\n");
goto err_enable;
}
- /* though offset of share in sm750_share is 0,
- * we use this marcro as the same */
+ /*
+ * though offset of share in sm750_share is 0,
+ * we use this marcro as the same
+ */
spec_offset = offsetof(struct sm750_share, share);
spec_share = kzalloc(sizeof(*spec_share), GFP_KERNEL);
@@ -1128,10 +1115,12 @@
spin_lock_init(&share->slock);
if (!share->accel_off) {
- /* hook deInit and 2d routines, notes that below hw_xxx
+ /*
+ * hook deInit and 2d routines, notes that below hw_xxx
* routine can work on most of lynx chips
* if some chip need specific function,
- * please hook it in smXXX_set_drv routine */
+ * please hook it in smXXX_set_drv routine
+ */
share->accel.de_init = hw_de_init;
share->accel.de_fillrect = hw_fillrect;
share->accel.de_copyarea = hw_copyarea;
@@ -1268,7 +1257,6 @@
int len;
char *opt, *tmp;
-
if (!options || !*options) {
pr_warn("no options.\n");
return 0;
@@ -1283,14 +1271,15 @@
tmp = g_settings;
- /* Notes:
- char * strsep(char **s,const char * ct);
- @s: the string to be searched
- @ct :the characters to search for
-
- strsep() updates @options to pointer after the first found token
- it also returns the pointer ahead the token.
- */
+ /*
+ * Notes:
+ * char * strsep(char **s,const char * ct);
+ * @s: the string to be searched
+ * @ct :the characters to search for
+ *
+ * strsep() updates @options to pointer after the first found token
+ * it also returns the pointer ahead the token.
+ */
while ((opt = strsep(&options, ":")) != NULL) {
/* options that mean for any lynx chips are configured here */
if (!strncmp(opt, "noaccel", strlen("noaccel")))
@@ -1332,7 +1321,6 @@
#endif
};
-
static int __init lynxfb_init(void)
{
char *option;
diff --git a/drivers/staging/sm750fb/sm750.h b/drivers/staging/sm750fb/sm750.h
index cc80580..5bc4455 100644
--- a/drivers/staging/sm750fb/sm750.h
+++ b/drivers/staging/sm750fb/sm750.h
@@ -5,20 +5,20 @@
#define FB_ACCEL_SMI 0xab
/* please use revision id to distinguish sm750le and sm750*/
-#define SPC_SM750 0
+#define SPC_SM750 0
#define MB(x) ((x)<<20)
#define MHZ(x) ((x) * 1000000)
/* align should be 2,4,8,16 */
-#define PADDING(align, data) (((data)+(align)-1)&(~((align) -1)))
+#define PADDING(align, data) (((data)+(align)-1)&(~((align) - 1)))
extern int smi_indent;
-struct lynx_accel{
+struct lynx_accel {
/* base virtual address of DPR registers */
- volatile unsigned char __iomem * dprBase;
+ volatile unsigned char __iomem *dprBase;
/* base virtual address of de data port */
- volatile unsigned char __iomem * dpPortBase;
+ volatile unsigned char __iomem *dpPortBase;
/* function fointers */
void (*de_init)(struct lynx_accel *);
@@ -38,10 +38,10 @@
};
-/* lynx_share stands for a presentation of two frame buffer
- that use one smi adaptor , it is similar to a basic class of C++
+/* lynx_share stands for a presentation of two frame buffer
+ that use one smi adaptor , it is similar to a basic class of C++
*/
-struct lynx_share{
+struct lynx_share {
/* common members */
u16 devid;
u8 revid;
@@ -53,7 +53,7 @@
int mtrr_off;
struct{
int vram;
- }mtrr;
+ } mtrr;
/* all smi graphic adaptor got below attributes */
unsigned long vidmem_start;
unsigned long vidreg_start;
@@ -64,11 +64,11 @@
/* locks*/
spinlock_t slock;
/* function pointers */
- void (*suspend)(struct lynx_share*);
- void (*resume)(struct lynx_share*);
+ void (*suspend)(struct lynx_share *);
+ void (*resume)(struct lynx_share *);
};
-struct lynx_cursor{
+struct lynx_cursor {
/* cursor width ,height and size */
int w;
int h;
@@ -80,7 +80,7 @@
char __iomem *vstart;
int offset;
/* mmio addr of hw cursor */
- volatile char __iomem * mmio;
+ volatile char __iomem *mmio;
/* the lynx_share of this adaptor */
struct lynx_share *share;
/* proc_routines */
@@ -92,7 +92,7 @@
void (*setData)(struct lynx_cursor *, u16, const u8*, const u8*);
};
-struct lynxfb_crtc{
+struct lynxfb_crtc {
unsigned char __iomem *vCursor; /* virtual address of cursor */
unsigned char __iomem *vScreen; /* virtual address of on_screen */
int oCursor; /* cursor address offset in vidmem */
@@ -108,14 +108,14 @@
void *priv;
- int(*proc_setMode)(struct lynxfb_crtc*,
+ int (*proc_setMode)(struct lynxfb_crtc*,
struct fb_var_screeninfo*,
struct fb_fix_screeninfo*);
- int(*proc_checkMode)(struct lynxfb_crtc*, struct fb_var_screeninfo*);
- int(*proc_setColReg)(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
- void (*clear)(struct lynxfb_crtc*);
- /* pan display */
+ int (*proc_checkMode)(struct lynxfb_crtc*, struct fb_var_screeninfo*);
+ int (*proc_setColReg)(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
+ void (*clear)(struct lynxfb_crtc *);
+ /* pan display */
int (*proc_panDisplay)(struct lynxfb_crtc *,
const struct fb_var_screeninfo *,
const struct fb_info *);
@@ -123,33 +123,33 @@
struct lynx_cursor cursor;
};
-struct lynxfb_output{
+struct lynxfb_output {
int dpms;
int paths;
- /* which paths(s) this output stands for,for sm750:
- paths=1:means output for panel paths
- paths=2:means output for crt paths
- paths=3:means output for both panel and crt paths
+ /* which paths(s) this output stands for,for sm750:
+ paths=1:means output for panel paths
+ paths=2:means output for crt paths
+ paths=3:means output for both panel and crt paths
*/
int *channel;
- /* which channel these outputs linked with,for sm750:
- *channel=0 means primary channel
- *channel=1 means secondary channel
- output->channel ==> &crtc->channel
+ /* which channel these outputs linked with,for sm750:
+ *channel=0 means primary channel
+ *channel=1 means secondary channel
+ output->channel ==> &crtc->channel
*/
void *priv;
- int(*proc_setMode)(struct lynxfb_output*,
+ int (*proc_setMode)(struct lynxfb_output*,
struct fb_var_screeninfo*,
struct fb_fix_screeninfo*);
- int(*proc_checkMode)(struct lynxfb_output*, struct fb_var_screeninfo*);
- int(*proc_setBLANK)(struct lynxfb_output*, int);
- void (*clear)(struct lynxfb_output*);
+ int (*proc_checkMode)(struct lynxfb_output*, struct fb_var_screeninfo*);
+ int (*proc_setBLANK)(struct lynxfb_output*, int);
+ void (*clear)(struct lynxfb_output *);
};
-struct lynxfb_par{
+struct lynxfb_par {
/* either 0 or 1 for dual head adaptor,0 is the older one registered */
int index;
unsigned int pseudo_palette[256];
@@ -165,14 +165,14 @@
#define PS_TO_HZ(ps) \
- ({ \
+ ({ \
unsigned long long hz = 1000*1000*1000*1000ULL; \
do_div(hz, ps); \
- (unsigned long)hz;})
+ (unsigned long)hz; })
static inline unsigned long ps_to_hz(unsigned int psvalue)
{
- unsigned long long numerator=1000*1000*1000*1000ULL;
+ unsigned long long numerator = 1000*1000*1000*1000ULL;
/* 10^12 / picosecond period gives frequency in Hz */
do_div(numerator, psvalue);
return (unsigned long)numerator;
diff --git a/drivers/staging/sm750fb/sm750_accel.c b/drivers/staging/sm750fb/sm750_accel.c
index 6eee4cd..1dd06a2 100644
--- a/drivers/staging/sm750fb/sm750_accel.c
+++ b/drivers/staging/sm750fb/sm750_accel.c
@@ -37,7 +37,7 @@
{
/* setup 2d engine registers */
u32 reg, clr;
-
+
write_dpr(accel, DE_MASKS, 0xFFFFFFFF);
/* dpr1c */
@@ -82,7 +82,7 @@
void hw_set2dformat(struct lynx_accel *accel, int fmt)
{
u32 reg;
-
+
/* fmt=0,1,2 for 8,16,32,bpp on sm718/750/502 */
reg = read_dpr(accel, DE_STRETCH_FORMAT);
reg = FIELD_VALUE(reg, DE_STRETCH_FORMAT, PIXEL_FORMAT, fmt);
@@ -96,11 +96,10 @@
{
u32 deCtrl;
- if(accel->de_wait() != 0)
- {
+ if (accel->de_wait() != 0) {
/* int time wait and always busy,seems hardware
* got something error */
- pr_debug("%s:De engine always bussy\n", __func__);
+ pr_debug("De engine always busy\n");
return -1;
}
@@ -151,112 +150,102 @@
unsigned int height, /* width and height of rectangle in pixel value */
unsigned int rop2) /* ROP value */
{
- unsigned int nDirection, de_ctrl;
- int opSign;
- nDirection = LEFT_TO_RIGHT;
+ unsigned int nDirection, de_ctrl;
+ int opSign;
+
+ nDirection = LEFT_TO_RIGHT;
/* Direction of ROP2 operation: 1 = Left to Right, (-1) = Right to Left */
- opSign = 1;
- de_ctrl = 0;
+ opSign = 1;
+ de_ctrl = 0;
- /* If source and destination are the same surface, need to check for overlay cases */
- if (sBase == dBase && sPitch == dPitch)
- {
- /* Determine direction of operation */
- if (sy < dy)
- {
- /* +----------+
- |S |
- | +----------+
- | | | |
- | | | |
- +---|------+ |
- | D|
- +----------+ */
+ /* If source and destination are the same surface, need to check for overlay cases */
+ if (sBase == dBase && sPitch == dPitch) {
+ /* Determine direction of operation */
+ if (sy < dy) {
+ /* +----------+
+ |S |
+ | +----------+
+ | | | |
+ | | | |
+ +---|------+ |
+ | D|
+ +----------+ */
- nDirection = BOTTOM_TO_TOP;
- }
- else if (sy > dy)
- {
- /* +----------+
- |D |
- | +----------+
- | | | |
- | | | |
- +---|------+ |
- | S|
- +----------+ */
+ nDirection = BOTTOM_TO_TOP;
+ } else if (sy > dy) {
+ /* +----------+
+ |D |
+ | +----------+
+ | | | |
+ | | | |
+ +---|------+ |
+ | S|
+ +----------+ */
- nDirection = TOP_TO_BOTTOM;
- }
- else
- {
- /* sy == dy */
+ nDirection = TOP_TO_BOTTOM;
+ } else {
+ /* sy == dy */
- if (sx <= dx)
- {
- /* +------+---+------+
- |S | | D|
- | | | |
- | | | |
- | | | |
- +------+---+------+ */
+ if (sx <= dx) {
+ /* +------+---+------+
+ |S | | D|
+ | | | |
+ | | | |
+ | | | |
+ +------+---+------+ */
- nDirection = RIGHT_TO_LEFT;
- }
- else
- {
- /* sx > dx */
+ nDirection = RIGHT_TO_LEFT;
+ } else {
+ /* sx > dx */
- /* +------+---+------+
- |D | | S|
- | | | |
- | | | |
- | | | |
- +------+---+------+ */
+ /* +------+---+------+
+ |D | | S|
+ | | | |
+ | | | |
+ | | | |
+ +------+---+------+ */
- nDirection = LEFT_TO_RIGHT;
- }
- }
- }
+ nDirection = LEFT_TO_RIGHT;
+ }
+ }
+ }
- if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT))
- {
- sx += width - 1;
- sy += height - 1;
- dx += width - 1;
- dy += height - 1;
- opSign = (-1);
- }
+ if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) {
+ sx += width - 1;
+ sy += height - 1;
+ dx += width - 1;
+ dy += height - 1;
+ opSign = (-1);
+ }
- /* Note:
- DE_FOREGROUND are DE_BACKGROUND are don't care.
- DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency().
- */
+ /* Note:
+ DE_FOREGROUND are DE_BACKGROUND are don't care.
+ DE_COLOR_COMPARE and DE_COLOR_COMPARE_MAKS are set by set deSetTransparency().
+ */
- /* 2D Source Base.
- It is an address offset (128 bit aligned) from the beginning of frame buffer.
- */
- write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */
+ /* 2D Source Base.
+ It is an address offset (128 bit aligned) from the beginning of frame buffer.
+ */
+ write_dpr(accel, DE_WINDOW_SOURCE_BASE, sBase); /* dpr40 */
- /* 2D Destination Base.
- It is an address offset (128 bit aligned) from the beginning of frame buffer.
- */
- write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */
+ /* 2D Destination Base.
+ It is an address offset (128 bit aligned) from the beginning of frame buffer.
+ */
+ write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase); /* dpr44 */
#if 0
/* Program pitch (distance between the 1st points of two adjacent lines).
Note that input pitch is BYTE value, but the 2D Pitch register uses
pixel values. Need Byte to pixel conversion.
*/
- if(Bpp == 3){
+ if (Bpp == 3) {
sx *= 3;
dx *= 3;
width *= 3;
write_dpr(accel, DE_PITCH,
FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
FIELD_VALUE(0, DE_PITCH, SOURCE, sPitch)); /* dpr10 */
- }
- else
+ } else
#endif
{
write_dpr(accel, DE_PITCH,
@@ -267,54 +256,53 @@
/* Screen Window width in Pixels.
2D engine uses this value to calculate the linear address in frame buffer for a given point.
*/
- write_dpr(accel, DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/Bpp)) |
- FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (sPitch/Bpp))); /* dpr3c */
+ write_dpr(accel, DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/Bpp)) |
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (sPitch/Bpp))); /* dpr3c */
- if (accel->de_wait() != 0){
+ if (accel->de_wait() != 0)
return -1;
+
+ {
+
+ write_dpr(accel, DE_SOURCE,
+ FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_SOURCE, X_K1, sx) |
+ FIELD_VALUE(0, DE_SOURCE, Y_K2, sy)); /* dpr0 */
+ write_dpr(accel, DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_DESTINATION, X, dx) |
+ FIELD_VALUE(0, DE_DESTINATION, Y, dy)); /* dpr04 */
+ write_dpr(accel, DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X, width) |
+ FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
+
+ de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
+ FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
+ FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
+ ((nDirection == RIGHT_TO_LEFT) ?
+ FIELD_SET(0, DE_CONTROL, DIRECTION, RIGHT_TO_LEFT)
+ : FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT)) |
+ FIELD_SET(0, DE_CONTROL, STATUS, START);
+ write_dpr(accel, DE_CONTROL, de_ctrl); /* dpr0c */
+
}
- {
-
- write_dpr(accel, DE_SOURCE,
- FIELD_SET (0, DE_SOURCE, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_SOURCE, X_K1, sx) |
- FIELD_VALUE(0, DE_SOURCE, Y_K2, sy)); /* dpr0 */
- write_dpr(accel, DE_DESTINATION,
- FIELD_SET (0, DE_DESTINATION, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_DESTINATION, X, dx) |
- FIELD_VALUE(0, DE_DESTINATION, Y, dy)); /* dpr04 */
- write_dpr(accel, DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X, width) |
- FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
-
- de_ctrl =
- FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
- FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
- FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) |
- ((nDirection == RIGHT_TO_LEFT) ?
- FIELD_SET(0, DE_CONTROL, DIRECTION, RIGHT_TO_LEFT)
- : FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT)) |
- FIELD_SET(0, DE_CONTROL, STATUS, START);
- write_dpr(accel, DE_CONTROL, de_ctrl); /* dpr0c */
- }
-
- return 0;
+ return 0;
}
static unsigned int deGetTransparency(struct lynx_accel *accel)
{
- unsigned int de_ctrl;
+ unsigned int de_ctrl;
- de_ctrl = read_dpr(accel, DE_CONTROL);
+ de_ctrl = read_dpr(accel, DE_CONTROL);
- de_ctrl &=
- FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
- FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT)|
- FIELD_MASK(DE_CONTROL_TRANSPARENCY);
+ de_ctrl &=
+ FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) |
+ FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT)|
+ FIELD_MASK(DE_CONTROL_TRANSPARENCY);
- return de_ctrl;
+ return de_ctrl;
}
int hw_imageblit(struct lynx_accel *accel,
@@ -332,38 +320,36 @@
u32 bColor, /* Background color (corresponding to a 0 in the monochrome data */
u32 rop2) /* ROP value */
{
- unsigned int ulBytesPerScan;
- unsigned int ul4BytesPerScan;
- unsigned int ulBytesRemain;
- unsigned int de_ctrl = 0;
- unsigned char ajRemain[4];
- int i, j;
+ unsigned int ulBytesPerScan;
+ unsigned int ul4BytesPerScan;
+ unsigned int ulBytesRemain;
+ unsigned int de_ctrl = 0;
+ unsigned char ajRemain[4];
+ int i, j;
- startBit &= 7; /* Just make sure the start bit is within legal range */
- ulBytesPerScan = (width + startBit + 7) / 8;
- ul4BytesPerScan = ulBytesPerScan & ~3;
- ulBytesRemain = ulBytesPerScan & 3;
+ startBit &= 7; /* Just make sure the start bit is within legal range */
+ ulBytesPerScan = (width + startBit + 7) / 8;
+ ul4BytesPerScan = ulBytesPerScan & ~3;
+ ulBytesRemain = ulBytesPerScan & 3;
- if(accel->de_wait() != 0)
- {
- return -1;
- }
+ if (accel->de_wait() != 0)
+ return -1;
- /* 2D Source Base.
- Use 0 for HOST Blt.
- */
- write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
+ /* 2D Source Base.
+ Use 0 for HOST Blt.
+ */
+ write_dpr(accel, DE_WINDOW_SOURCE_BASE, 0);
- /* 2D Destination Base.
- It is an address offset (128 bit aligned) from the beginning of frame buffer.
- */
- write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
+ /* 2D Destination Base.
+ It is an address offset (128 bit aligned) from the beginning of frame buffer.
+ */
+ write_dpr(accel, DE_WINDOW_DESTINATION_BASE, dBase);
#if 0
/* Program pitch (distance between the 1st points of two adjacent lines).
Note that input pitch is BYTE value, but the 2D Pitch register uses
pixel values. Need Byte to pixel conversion.
*/
- if(bytePerPixel == 3 ){
+ if (bytePerPixel == 3) {
dx *= 3;
width *= 3;
startBit *= 3;
@@ -371,8 +357,7 @@
FIELD_VALUE(0, DE_PITCH, DESTINATION, dPitch) |
FIELD_VALUE(0, DE_PITCH, SOURCE, dPitch)); /* dpr10 */
- }
- else
+ } else
#endif
{
write_dpr(accel, DE_PITCH,
@@ -380,30 +365,30 @@
FIELD_VALUE(0, DE_PITCH, SOURCE, dPitch/bytePerPixel)); /* dpr10 */
}
- /* Screen Window width in Pixels.
- 2D engine uses this value to calculate the linear address in frame buffer for a given point.
- */
- write_dpr(accel, DE_WINDOW_WIDTH,
- FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/bytePerPixel)) |
- FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (dPitch/bytePerPixel)));
+ /* Screen Window width in Pixels.
+ 2D engine uses this value to calculate the linear address in frame buffer for a given point.
+ */
+ write_dpr(accel, DE_WINDOW_WIDTH,
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, (dPitch/bytePerPixel)) |
+ FIELD_VALUE(0, DE_WINDOW_WIDTH, SOURCE, (dPitch/bytePerPixel)));
- /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
- For mono bitmap, use startBit for X_K1. */
- write_dpr(accel, DE_SOURCE,
- FIELD_SET (0, DE_SOURCE, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_SOURCE, X_K1_MONO, startBit)); /* dpr00 */
+ /* Note: For 2D Source in Host Write, only X_K1_MONO field is needed, and Y_K2 field is not used.
+ For mono bitmap, use startBit for X_K1. */
+ write_dpr(accel, DE_SOURCE,
+ FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_SOURCE, X_K1_MONO, startBit)); /* dpr00 */
- write_dpr(accel, DE_DESTINATION,
- FIELD_SET (0, DE_DESTINATION, WRAP, DISABLE) |
- FIELD_VALUE(0, DE_DESTINATION, X, dx) |
- FIELD_VALUE(0, DE_DESTINATION, Y, dy)); /* dpr04 */
+ write_dpr(accel, DE_DESTINATION,
+ FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) |
+ FIELD_VALUE(0, DE_DESTINATION, X, dx) |
+ FIELD_VALUE(0, DE_DESTINATION, Y, dy)); /* dpr04 */
- write_dpr(accel, DE_DIMENSION,
- FIELD_VALUE(0, DE_DIMENSION, X, width) |
- FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
+ write_dpr(accel, DE_DIMENSION,
+ FIELD_VALUE(0, DE_DIMENSION, X, width) |
+ FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); /* dpr08 */
- write_dpr(accel, DE_FOREGROUND, fColor);
- write_dpr(accel, DE_BACKGROUND, bColor);
+ write_dpr(accel, DE_FOREGROUND, fColor);
+ write_dpr(accel, DE_BACKGROUND, bColor);
de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) |
FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) |
@@ -413,24 +398,20 @@
write_dpr(accel, DE_CONTROL, de_ctrl | deGetTransparency(accel));
- /* Write MONO data (line by line) to 2D Engine data port */
- for (i=0; i<height; i++)
- {
- /* For each line, send the data in chunks of 4 bytes */
- for (j=0; j<(ul4BytesPerScan/4); j++)
- {
- write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
- }
+ /* Write MONO data (line by line) to 2D Engine data port */
+ for (i = 0; i < height; i++) {
+ /* For each line, send the data in chunks of 4 bytes */
+ for (j = 0; j < (ul4BytesPerScan/4); j++)
+ write_dpPort(accel, *(unsigned int *)(pSrcbuf + (j * 4)));
- if (ulBytesRemain)
- {
- memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
- write_dpPort(accel, *(unsigned int *)ajRemain);
- }
+ if (ulBytesRemain) {
+ memcpy(ajRemain, pSrcbuf+ul4BytesPerScan, ulBytesRemain);
+ write_dpPort(accel, *(unsigned int *)ajRemain);
+ }
- pSrcbuf += srcDelta;
- }
+ pSrcbuf += srcDelta;
+ }
- return 0;
+ return 0;
}
diff --git a/drivers/staging/sm750fb/sm750_accel.h b/drivers/staging/sm750fb/sm750_accel.h
index d3d256c..f252e47 100644
--- a/drivers/staging/sm750fb/sm750_accel.h
+++ b/drivers/staging/sm750fb/sm750_accel.h
@@ -7,7 +7,7 @@
/* notes: below address are the offset value from de_base_address (0x100000)*/
/* for sm718/750/502 de_base is at mmreg_1mb*/
-#define DE_BASE_ADDR_TYPE1 0x100000
+#define DE_BASE_ADDR_TYPE1 0x100000
/* for sm712,de_base is at mmreg_32kb */
#define DE_BASE_ADDR_TYPE2 0x8000
/* for sm722,de_base is at mmreg_0 */
@@ -26,7 +26,7 @@
#define DE_SOURCE_WRAP_ENABLE 1
#define DE_SOURCE_X_K1 29:16
#define DE_SOURCE_Y_K2 15:0
-#define DE_SOURCE_X_K1_MONO 20:16
+#define DE_SOURCE_X_K1_MONO 20:16
#define DE_DESTINATION 0x4
#define DE_DESTINATION_WRAP 31:31
diff --git a/drivers/staging/sm750fb/sm750_cursor.c b/drivers/staging/sm750fb/sm750_cursor.c
index 405e24b..a94a4bb 100644
--- a/drivers/staging/sm750fb/sm750_cursor.c
+++ b/drivers/staging/sm750fb/sm750_cursor.c
@@ -61,6 +61,7 @@
void hw_cursor_enable(struct lynx_cursor *cursor)
{
u32 reg;
+
reg = FIELD_VALUE(0, HWC_ADDRESS, ADDRESS, cursor->offset)|
FIELD_SET(0, HWC_ADDRESS, EXT, LOCAL)|
FIELD_SET(0, HWC_ADDRESS, ENABLE, ENABLE);
@@ -81,6 +82,7 @@
int x, int y)
{
u32 reg;
+
reg = FIELD_VALUE(0, HWC_LOCATION, Y, y)|
FIELD_VALUE(0, HWC_LOCATION, X, x);
POKE32(HWC_LOCATION, reg);
@@ -93,7 +95,7 @@
}
void hw_cursor_setData(struct lynx_cursor *cursor,
- u16 rop, const u8* pcol, const u8* pmsk)
+ u16 rop, const u8 *pcol, const u8 *pmsk)
{
int i, j, count, pitch, offset;
u8 color, mask, opr;
@@ -122,8 +124,7 @@
odd=0;
*/
- for(i=0;i<count;i++)
- {
+ for (i = 0; i < count; i++) {
color = *pcol++;
mask = *pmsk++;
data = 0;
@@ -132,26 +133,25 @@
* but method 2 shows no lag
* and method 1 seems a bit wrong*/
#if 0
- if(rop == ROP_XOR)
+ if (rop == ROP_XOR)
opr = mask ^ color;
else
opr = mask & color;
- for(j=0;j<8;j++)
- {
+ for (j = 0; j < 8; j++) {
- if(opr & (0x80 >> j))
- { /* use fg color,id = 2 */
+ if (opr & (0x80 >> j)) {
+ /* use fg color,id = 2 */
data |= 2 << (j*2);
- }else{
+ } else {
/* use bg color,id = 1 */
data |= 1 << (j*2);
}
}
#else
- for(j=0;j<8;j++){
- if(mask & (0x80>>j)){
- if(rop == ROP_XOR)
+ for (j = 0; j < 8; j++) {
+ if (mask & (0x80>>j)) {
+ if (rop == ROP_XOR)
opr = mask ^ color;
else
opr = mask & color;
@@ -165,15 +165,15 @@
/* assume pitch is 1,2,4,8,...*/
#if 0
- if(!((i+1)&(pitch-1))) /* below line equal to is line */
+ if (!((i+1)&(pitch-1))) /* below line equal to is line */
#else
- if((i+1) % pitch == 0)
+ if ((i+1) % pitch == 0)
#endif
{
/* need a return */
pstart += offset;
pbuffer = pstart;
- }else{
+ } else {
pbuffer += sizeof(u16);
}
@@ -184,7 +184,7 @@
void hw_cursor_setData2(struct lynx_cursor *cursor,
- u16 rop, const u8* pcol, const u8* pmsk)
+ u16 rop, const u8 *pcol, const u8 *pmsk)
{
int i, j, count, pitch, offset;
u8 color, mask;
@@ -204,45 +204,42 @@
pstart = cursor->vstart;
pbuffer = pstart;
- for(i=0;i<count;i++)
- {
+ for (i = 0; i < count; i++) {
color = *pcol++;
mask = *pmsk++;
data = 0;
/* either method below works well, but method 2 shows no lag */
#if 0
- if(rop == ROP_XOR)
+ if (rop == ROP_XOR)
opr = mask ^ color;
else
opr = mask & color;
- for(j=0;j<8;j++)
- {
+ for (j = 0; j < 8; j++) {
- if(opr & (0x80 >> j))
- { /* use fg color,id = 2 */
+ if (opr & (0x80 >> j)) {
+ /* use fg color,id = 2 */
data |= 2 << (j*2);
- }else{
+ } else {
/* use bg color,id = 1 */
data |= 1 << (j*2);
}
}
#else
- for(j=0;j<8;j++){
- if(mask & (1<<j))
+ for (j = 0; j < 8; j++) {
+ if (mask & (1<<j))
data |= ((color & (1<<j))?1:2)<<(j*2);
}
#endif
iowrite16(data, pbuffer);
/* assume pitch is 1,2,4,8,...*/
- if(!(i&(pitch-1)))
- {
+ if (!(i&(pitch-1))) {
/* need a return */
pstart += offset;
pbuffer = pstart;
- }else{
+ } else {
pbuffer += sizeof(u16);
}
diff --git a/drivers/staging/sm750fb/sm750_cursor.h b/drivers/staging/sm750fb/sm750_cursor.h
index e1716a6..6c4fc9b 100644
--- a/drivers/staging/sm750fb/sm750_cursor.h
+++ b/drivers/staging/sm750fb/sm750_cursor.h
@@ -11,7 +11,7 @@
void hw_cursor_setColor(struct lynx_cursor *cursor,
u32 fg, u32 bg);
void hw_cursor_setData(struct lynx_cursor *cursor,
- u16 rop, const u8* data, const u8* mask);
+ u16 rop, const u8 *data, const u8 *mask);
void hw_cursor_setData2(struct lynx_cursor *cursor,
- u16 rop, const u8* data, const u8* mask);
+ u16 rop, const u8 *data, const u8 *mask);
#endif
diff --git a/drivers/staging/sm750fb/sm750_help.h b/drivers/staging/sm750fb/sm750_help.h
index 05777f7..8dc6bd2 100644
--- a/drivers/staging/sm750fb/sm750_help.h
+++ b/drivers/staging/sm750fb/sm750_help.h
@@ -11,9 +11,9 @@
#define GET_FIELD(d, f) (((d) >> _LSB(f)) & RAW_MASK(f))
#define TEST_FIELD(d, f, v) (GET_FIELD(d, f) == f ## _ ## v)
#define SET_FIELD(d, f, v) (((d) & ~GET_MASK(f)) | \
- (((f ## _ ## v) & RAW_MASK(f)) << _LSB(f)))
+ (((f ## _ ## v) & RAW_MASK(f)) << _LSB(f)))
#define SET_FIELDV(d, f, v) (((d) & ~GET_MASK(f)) | \
- (((v) & RAW_MASK(f)) << _LSB(f)))
+ (((v) & RAW_MASK(f)) << _LSB(f)))
/* Internal macros */
#define _F_START(f) (0 ? f)
@@ -26,24 +26,24 @@
/* Global macros */
#define FIELD_GET(x, reg, field) \
( \
- _F_NORMALIZE((x), reg ## _ ## field) \
+ _F_NORMALIZE((x), reg ## _ ## field) \
)
#define FIELD_SET(x, reg, field, value) \
( \
- (x & ~_F_MASK(reg ## _ ## field)) \
- | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
+ (x & ~_F_MASK(reg ## _ ## field)) \
+ | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \
)
#define FIELD_VALUE(x, reg, field, value) \
( \
- (x & ~_F_MASK(reg ## _ ## field)) \
- | _F_DENORMALIZE(value, reg ## _ ## field) \
+ (x & ~_F_MASK(reg ## _ ## field)) \
+ | _F_DENORMALIZE(value, reg ## _ ## field) \
)
#define FIELD_CLEAR(reg, field) \
( \
- ~ _F_MASK(reg ## _ ## field) \
+ ~ _F_MASK(reg ## _ ## field) \
)
/* Field Macros */
@@ -55,25 +55,25 @@
#define FIELD_DENORMALIZE(field, value) (((value) << FIELD_START(field)) & FIELD_MASK(field))
#define FIELD_INIT(reg, field, value) FIELD_DENORMALIZE(reg ## _ ## field, \
- reg ## _ ## field ## _ ## value)
+ reg ## _ ## field ## _ ## value)
#define FIELD_INIT_VAL(reg, field, value) \
- (FIELD_DENORMALIZE(reg ## _ ## field, value))
+ (FIELD_DENORMALIZE(reg ## _ ## field, value))
#define FIELD_VAL_SET(x, r, f, v) x = x & ~FIELD_MASK(r ## _ ## f) \
- | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v)
+ | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v)
#define RGB(r, g, b) \
( \
- (unsigned long) (((r) << 16) | ((g) << 8) | (b)) \
+ (unsigned long) (((r) << 16) | ((g) << 8) | (b)) \
)
#define RGB16(r, g, b) \
( \
- (unsigned short) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | (((b) & 0xF8) >> 3)) \
+ (unsigned short) ((((r) & 0xF8) << 8) | (((g) & 0xFC) << 3) | (((b) & 0xF8) >> 3)) \
)
static inline unsigned int absDiff(unsigned int a, unsigned int b)
{
- if(a<b)
+ if (a < b)
return b-a;
else
return a-b;
diff --git a/drivers/staging/sm750fb/sm750_hw.c b/drivers/staging/sm750fb/sm750_hw.c
index 84381bc..7317ba9 100644
--- a/drivers/staging/sm750fb/sm750_hw.c
+++ b/drivers/staging/sm750fb/sm750_hw.c
@@ -24,11 +24,11 @@
#include "ddk750.h"
#include "sm750_accel.h"
-int hw_sm750_map(struct lynx_share* share, struct pci_dev* pdev)
+int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev)
{
int ret;
struct sm750_share *spec_share;
-
+
spec_share = container_of(share, struct sm750_share, share);
ret = 0;
@@ -43,24 +43,23 @@
* in lynxfb_remove, or memory will not be mapped again
* successfully
* */
-
- if((ret = pci_request_region(pdev, 1, "sm750fb")))
- {
+ ret = pci_request_region(pdev, 1, "sm750fb");
+ if (ret) {
pr_err("Can not request PCI regions.\n");
goto exit;
}
/* now map mmio and vidmem*/
share->pvReg = ioremap_nocache(share->vidreg_start, share->vidreg_size);
- if(!share->pvReg){
+ if (!share->pvReg) {
pr_err("mmio failed\n");
ret = -EFAULT;
goto exit;
- }else{
+ } else {
pr_info("mmio virtual addr = %p\n", share->pvReg);
}
-
+
share->accel.dprBase = share->pvReg + DE_BASE_ADDR_TYPE1;
share->accel.dpPortBase = share->pvReg + DE_PORT_ADDR_TYPE1;
@@ -78,8 +77,8 @@
/* reserve the vidmem space of smi adaptor */
#if 0
- if((ret = pci_request_region(pdev, 0, _moduleName_)))
- {
+ ret = pci_request_region(pdev, 0, _moduleName_);
+ if (ret) {
pr_err("Can not request PCI regions.\n");
goto exit;
}
@@ -87,11 +86,11 @@
share->pvMem = ioremap_wc(share->vidmem_start, share->vidmem_size);
- if(!share->pvMem){
+ if (!share->pvMem) {
pr_err("Map video memory failed\n");
ret = -EFAULT;
goto exit;
- }else{
+ } else {
pr_info("video memory vaddr = %p\n", share->pvMem);
}
exit:
@@ -104,22 +103,22 @@
{
struct sm750_share *spec_share;
struct init_status *parm;
-
+
spec_share = container_of(share, struct sm750_share, share);
parm = &spec_share->state.initParm;
- if(parm->chip_clk == 0)
- parm->chip_clk = (getChipType() == SM750LE)?
+ if (parm->chip_clk == 0)
+ parm->chip_clk = (getChipType() == SM750LE) ?
DEFAULT_SM750LE_CHIP_CLOCK :
DEFAULT_SM750_CHIP_CLOCK;
- if(parm->mem_clk == 0)
+ if (parm->mem_clk == 0)
parm->mem_clk = parm->chip_clk;
- if(parm->master_clk == 0)
+ if (parm->master_clk == 0)
parm->master_clk = parm->chip_clk/3;
ddk750_initHw((initchip_param_t *)&spec_share->state.initParm);
/* for sm718,open pci burst */
- if(share->devid == 0x718){
+ if (share->devid == 0x718) {
POKE32(SYSTEM_CTRL,
FIELD_SET(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, PCI_BURST, ON));
}
@@ -130,10 +129,9 @@
ddk750_initDVIDisp();
#endif
- if(getChipType() != SM750LE)
- {
+ if (getChipType() != SM750LE) {
/* does user need CRT ?*/
- if(spec_share->state.nocrt){
+ if (spec_share->state.nocrt) {
POKE32(MISC_CTRL,
FIELD_SET(PEEK32(MISC_CTRL),
MISC_CTRL,
@@ -143,7 +141,7 @@
FIELD_SET(PEEK32(SYSTEM_CTRL),
SYSTEM_CTRL,
DPMS, VNHN));
- }else{
+ } else {
POKE32(MISC_CTRL,
FIELD_SET(PEEK32(MISC_CTRL),
MISC_CTRL,
@@ -155,45 +153,43 @@
DPMS, VPHP));
}
- switch (spec_share->state.pnltype){
- case sm750_doubleTFT:
- case sm750_24TFT:
- case sm750_dualTFT:
- POKE32(PANEL_DISPLAY_CTRL,
- FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),
- PANEL_DISPLAY_CTRL,
- TFT_DISP,
- spec_share->state.pnltype));
- break;
+ switch (spec_share->state.pnltype) {
+ case sm750_doubleTFT:
+ case sm750_24TFT:
+ case sm750_dualTFT:
+ POKE32(PANEL_DISPLAY_CTRL,
+ FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL),
+ PANEL_DISPLAY_CTRL,
+ TFT_DISP,
+ spec_share->state.pnltype));
+ break;
}
- }else{
+ } else {
/* for 750LE ,no DVI chip initilization 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.
*/
- swI2CInit(0, 1);
+ swI2CInit(0, 1);
- /* Customer may NOT use CH7301 DVI chip, which has to be
- initialized differently.
- */
- if (swI2CReadReg(0xec, 0x4a) == 0x95)
- {
- /* The following register values for CH7301 are from
- Chrontel app note and our experiment.
- */
+ /* Customer may NOT use CH7301 DVI chip, which has to be
+ initialized differently.
+ */
+ if (swI2CReadReg(0xec, 0x4a) == 0x95) {
+ /* The following register values for CH7301 are from
+ Chrontel app note and our experiment.
+ */
pr_info("yes,CH7301 DVI chip found\n");
- swI2CWriteReg(0xec, 0x1d, 0x16);
- swI2CWriteReg(0xec, 0x21, 0x9);
- swI2CWriteReg(0xec, 0x49, 0xC0);
+ swI2CWriteReg(0xec, 0x1d, 0x16);
+ swI2CWriteReg(0xec, 0x21, 0x9);
+ swI2CWriteReg(0xec, 0x49, 0xC0);
pr_info("okay,CH7301 DVI chip setup done\n");
- }
+ }
}
/* init 2d engine */
- if(!share->accel_off){
+ if (!share->accel_off)
hw_sm750_initAccel(share);
- }
return 0;
}
@@ -202,86 +198,87 @@
resource_size_t hw_sm750_getVMSize(struct lynx_share *share)
{
resource_size_t ret;
-
+
ret = ddk750_getVMSize();
return ret;
}
-int hw_sm750_output_checkMode(struct lynxfb_output* output, struct fb_var_screeninfo* var)
+int hw_sm750_output_checkMode(struct lynxfb_output *output, struct fb_var_screeninfo *var)
{
-
+
return 0;
}
-int hw_sm750_output_setMode(struct lynxfb_output* output,
- struct fb_var_screeninfo* var, struct fb_fix_screeninfo* fix)
+int hw_sm750_output_setMode(struct lynxfb_output *output,
+ struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix)
{
int ret;
disp_output_t dispSet;
int channel;
-
+
ret = 0;
dispSet = 0;
channel = *output->channel;
- if(getChipType() != SM750LE){
- if(channel == sm750_primary){
+ if (getChipType() != SM750LE) {
+ if (channel == sm750_primary) {
pr_info("primary channel\n");
- if(output->paths & sm750_panel)
+ if (output->paths & sm750_panel)
dispSet |= do_LCD1_PRI;
- if(output->paths & sm750_crt)
+ if (output->paths & sm750_crt)
dispSet |= do_CRT_PRI;
- }else{
+ } else {
pr_info("secondary channel\n");
- if(output->paths & sm750_panel)
+ if (output->paths & sm750_panel)
dispSet |= do_LCD1_SEC;
- if(output->paths & sm750_crt)
+ if (output->paths & sm750_crt)
dispSet |= do_CRT_SEC;
}
ddk750_setLogicalDispOut(dispSet);
- }else{
+ } else {
/* just open DISPLAY_CONTROL_750LE register bit 3:0*/
u32 reg;
+
reg = PEEK32(DISPLAY_CONTROL_750LE);
reg |= 0xf;
POKE32(DISPLAY_CONTROL_750LE, reg);
}
- pr_info("ddk setlogicdispout done \n");
+ pr_info("ddk setlogicdispout done\n");
return ret;
}
-void hw_sm750_output_clear(struct lynxfb_output* output)
+void hw_sm750_output_clear(struct lynxfb_output *output)
{
-
+
return;
}
-int hw_sm750_crtc_checkMode(struct lynxfb_crtc* crtc, struct fb_var_screeninfo* var)
+int hw_sm750_crtc_checkMode(struct lynxfb_crtc *crtc, struct fb_var_screeninfo *var)
{
struct lynx_share *share;
-
+
share = container_of(crtc, struct lynxfb_par, crtc)->share;
- switch (var->bits_per_pixel){
- case 8:
- case 16:
- break;
- case 32:
- if (share->revid == SM750LE_REVISION_ID) {
- pr_debug("750le do not support 32bpp\n");
- return -EINVAL;
- }
- break;
- default:
+ switch (var->bits_per_pixel) {
+ case 8:
+ case 16:
+ break;
+ case 32:
+ if (share->revid == SM750LE_REVISION_ID) {
+ pr_debug("750le do not support 32bpp\n");
return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
}
@@ -292,9 +289,9 @@
/*
set the controller's mode for @crtc charged with @var and @fix parameters
*/
-int hw_sm750_crtc_setMode(struct lynxfb_crtc* crtc,
- struct fb_var_screeninfo* var,
- struct fb_fix_screeninfo* fix)
+int hw_sm750_crtc_setMode(struct lynxfb_crtc *crtc,
+ struct fb_var_screeninfo *var,
+ struct fb_fix_screeninfo *fix)
{
int ret, fmt;
u32 reg;
@@ -303,24 +300,24 @@
struct lynx_share *share;
struct lynxfb_par *par;
-
+
ret = 0;
par = container_of(crtc, struct lynxfb_par, crtc);
share = par->share;
#if 1
- if(!share->accel_off){
+ if (!share->accel_off) {
/* set 2d engine pixel format according to mode bpp */
- switch(var->bits_per_pixel){
- case 8:
- fmt = 0;
- break;
- case 16:
- fmt = 1;
- break;
- case 32:
- default:
- fmt = 2;
- break;
+ switch (var->bits_per_pixel) {
+ case 8:
+ fmt = 0;
+ break;
+ case 16:
+ fmt = 1;
+ break;
+ case 32:
+ default:
+ fmt = 2;
+ break;
}
hw_set2dformat(&share->accel, fmt);
}
@@ -330,7 +327,7 @@
modparm.pixel_clock = ps_to_hz(var->pixclock);
modparm.vertical_sync_polarity = (var->sync & FB_SYNC_HOR_HIGH_ACT) ? POS:NEG;
modparm.horizontal_sync_polarity = (var->sync & FB_SYNC_VERT_HIGH_ACT) ? POS:NEG;
- modparm.clock_phase_polarity = (var->sync& FB_SYNC_COMP_HIGH_ACT) ? POS:NEG;
+ modparm.clock_phase_polarity = (var->sync & FB_SYNC_COMP_HIGH_ACT) ? POS:NEG;
modparm.horizontal_display_end = var->xres;
modparm.horizontal_sync_width = var->hsync_len;
modparm.horizontal_sync_start = var->xres + var->right_margin;
@@ -341,19 +338,19 @@
modparm.vertical_total = var->yres + var->upper_margin + var->lower_margin + var->vsync_len;
/* choose pll */
- if(crtc->channel != sm750_secondary)
+ if (crtc->channel != sm750_secondary)
clock = PRIMARY_PLL;
else
clock = SECONDARY_PLL;
pr_debug("Request pixel clock = %lu\n", modparm.pixel_clock);
ret = ddk750_setModeTiming(&modparm, clock);
- if(ret){
+ if (ret) {
pr_err("Set mode timing failed\n");
goto exit;
}
- if(crtc->channel != sm750_secondary){
+ if (crtc->channel != sm750_secondary) {
/* set pitch, offset ,width,start address ,etc... */
POKE32(PANEL_FB_ADDRESS,
FIELD_SET(0, PANEL_FB_ADDRESS, STATUS, CURRENT)|
@@ -369,7 +366,7 @@
FIELD_VALUE(0, PANEL_FB_WIDTH, OFFSET, fix->line_length));
POKE32(PANEL_WINDOW_WIDTH,
- FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres -1)|
+ FIELD_VALUE(0, PANEL_WINDOW_WIDTH, WIDTH, var->xres - 1)|
FIELD_VALUE(0, PANEL_WINDOW_WIDTH, X, var->xoffset));
POKE32(PANEL_WINDOW_HEIGHT,
@@ -389,7 +386,7 @@
PANEL_DISPLAY_CTRL, FORMAT,
(var->bits_per_pixel >> 4)
));
- }else{
+ } else {
/* not implemented now */
POKE32(CRT_FB_ADDRESS, crtc->oScreen);
reg = var->xres * (var->bits_per_pixel >> 3);
@@ -412,138 +409,137 @@
return ret;
}
-void hw_sm750_crtc_clear(struct lynxfb_crtc* crtc)
+void hw_sm750_crtc_clear(struct lynxfb_crtc *crtc)
{
-
+
return;
}
-int hw_sm750_setColReg(struct lynxfb_crtc* crtc, ushort index,
+int hw_sm750_setColReg(struct lynxfb_crtc *crtc, ushort index,
ushort red, ushort green, ushort blue)
{
- static unsigned int add[]={PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
+ static unsigned int add[] = {PANEL_PALETTE_RAM, CRT_PALETTE_RAM};
+
POKE32(add[crtc->channel] + index*4, (red<<16)|(green<<8)|blue);
return 0;
}
-int hw_sm750le_setBLANK(struct lynxfb_output * output, int blank){
+int hw_sm750le_setBLANK(struct lynxfb_output *output, int blank)
+{
int dpms, crtdb;
-
- switch(blank)
- {
+
+ switch (blank) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_UNBLANK:
+ case FB_BLANK_UNBLANK:
#else
- case VESA_NO_BLANKING:
+ case VESA_NO_BLANKING:
#endif
- dpms = CRT_DISPLAY_CTRL_DPMS_0;
- crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
- break;
+ dpms = CRT_DISPLAY_CTRL_DPMS_0;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
+ break;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_NORMAL:
- dpms = CRT_DISPLAY_CTRL_DPMS_0;
- crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
- break;
+ case FB_BLANK_NORMAL:
+ dpms = CRT_DISPLAY_CTRL_DPMS_0;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+ break;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_VSYNC_SUSPEND:
#else
- case VESA_VSYNC_SUSPEND:
+ case VESA_VSYNC_SUSPEND:
#endif
- dpms = CRT_DISPLAY_CTRL_DPMS_2;
- crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
- break;
+ dpms = CRT_DISPLAY_CTRL_DPMS_2;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+ break;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
#else
- case VESA_HSYNC_SUSPEND:
+ case VESA_HSYNC_SUSPEND:
#endif
- dpms = CRT_DISPLAY_CTRL_DPMS_1;
- crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
- break;
+ dpms = CRT_DISPLAY_CTRL_DPMS_1;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+ break;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_POWERDOWN:
+ case FB_BLANK_POWERDOWN:
#else
- case VESA_POWERDOWN:
+ case VESA_POWERDOWN:
#endif
- dpms = CRT_DISPLAY_CTRL_DPMS_3;
- crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
- break;
- default:
- return -EINVAL;
+ dpms = CRT_DISPLAY_CTRL_DPMS_3;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+ break;
+ default:
+ return -EINVAL;
}
- if(output->paths & sm750_crt){
+ if (output->paths & sm750_crt) {
POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, DPMS, dpms));
POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
}
return 0;
}
-int hw_sm750_setBLANK(struct lynxfb_output* output, int blank)
+int hw_sm750_setBLANK(struct lynxfb_output *output, int blank)
{
unsigned int dpms, pps, crtdb;
-
+
dpms = pps = crtdb = 0;
- switch (blank)
- {
+ switch (blank) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_UNBLANK:
+ case FB_BLANK_UNBLANK:
#else
- case VESA_NO_BLANKING:
+ case VESA_NO_BLANKING:
#endif
- pr_info("flag = FB_BLANK_UNBLANK \n");
- dpms = SYSTEM_CTRL_DPMS_VPHP;
- pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
- crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
- break;
+ pr_info("flag = FB_BLANK_UNBLANK\n");
+ dpms = SYSTEM_CTRL_DPMS_VPHP;
+ pps = PANEL_DISPLAY_CTRL_DATA_ENABLE;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_OFF;
+ break;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_NORMAL:
- pr_info("flag = FB_BLANK_NORMAL \n");
- dpms = SYSTEM_CTRL_DPMS_VPHP;
- pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
- crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
- break;
+ case FB_BLANK_NORMAL:
+ pr_info("flag = FB_BLANK_NORMAL\n");
+ dpms = SYSTEM_CTRL_DPMS_VPHP;
+ pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+ break;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_VSYNC_SUSPEND:
+ case FB_BLANK_VSYNC_SUSPEND:
#else
- case VESA_VSYNC_SUSPEND:
+ case VESA_VSYNC_SUSPEND:
#endif
- dpms = SYSTEM_CTRL_DPMS_VNHP;
- pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
- crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
- break;
+ dpms = SYSTEM_CTRL_DPMS_VNHP;
+ pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+ break;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_HSYNC_SUSPEND:
+ case FB_BLANK_HSYNC_SUSPEND:
#else
- case VESA_HSYNC_SUSPEND:
+ case VESA_HSYNC_SUSPEND:
#endif
- dpms = SYSTEM_CTRL_DPMS_VPHN;
- pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
- crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
- break;
+ dpms = SYSTEM_CTRL_DPMS_VPHN;
+ pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+ break;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 10)
- case FB_BLANK_POWERDOWN:
+ case FB_BLANK_POWERDOWN:
#else
- case VESA_POWERDOWN:
+ case VESA_POWERDOWN:
#endif
- dpms = SYSTEM_CTRL_DPMS_VNHN;
- pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
- crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
- break;
+ dpms = SYSTEM_CTRL_DPMS_VNHN;
+ pps = PANEL_DISPLAY_CTRL_DATA_DISABLE;
+ crtdb = CRT_DISPLAY_CTRL_BLANK_ON;
+ break;
}
- if(output->paths & sm750_crt){
+ if (output->paths & sm750_crt) {
POKE32(SYSTEM_CTRL, FIELD_VALUE(PEEK32(SYSTEM_CTRL), SYSTEM_CTRL, DPMS, dpms));
POKE32(CRT_DISPLAY_CTRL, FIELD_VALUE(PEEK32(CRT_DISPLAY_CTRL), CRT_DISPLAY_CTRL, BLANK, crtdb));
}
- if(output->paths & sm750_panel){
+ if (output->paths & sm750_panel)
POKE32(PANEL_DISPLAY_CTRL, FIELD_VALUE(PEEK32(PANEL_DISPLAY_CTRL), PANEL_DISPLAY_CTRL, DATA, pps));
- }
return 0;
}
@@ -552,9 +548,10 @@
void hw_sm750_initAccel(struct lynx_share *share)
{
u32 reg;
+
enable2DEngine(1);
- if(getChipType() == SM750LE){
+ if (getChipType() == SM750LE) {
reg = PEEK32(DE_STATE1);
reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, ON);
POKE32(DE_STATE1, reg);
@@ -563,7 +560,7 @@
reg = FIELD_SET(reg, DE_STATE1, DE_ABORT, OFF);
POKE32(DE_STATE1, reg);
- }else{
+ } else {
/* engine reset */
reg = PEEK32(SYSTEM_CTRL);
reg = FIELD_SET(reg, SYSTEM_CTRL, DE_ABORT, ON);
@@ -580,13 +577,14 @@
int hw_sm750le_deWait(void)
{
- int i=0x10000000;
- while(i--){
+ int i = 0x10000000;
+
+ while (i--) {
unsigned int dwVal = PEEK32(DE_STATE2);
- if((FIELD_GET(dwVal, DE_STATE2, DE_STATUS) == DE_STATE2_DE_STATUS_IDLE) &&
+
+ 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))
- {
+ (FIELD_GET(dwVal, DE_STATE2, DE_MEM_FIFO) == DE_STATE2_DE_MEM_FIFO_EMPTY)) {
return 0;
}
}
@@ -597,13 +595,14 @@
int hw_sm750_deWait(void)
{
- int i=0x10000000;
- while(i--){
+ int i = 0x10000000;
+
+ while (i--) {
unsigned int dwVal = PEEK32(SYSTEM_CTRL);
- if((FIELD_GET(dwVal, SYSTEM_CTRL, DE_STATUS) == SYSTEM_CTRL_DE_STATUS_IDLE) &&
+
+ 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))
- {
+ (FIELD_GET(dwVal, SYSTEM_CTRL, DE_MEM_FIFO) == SYSTEM_CTRL_DE_MEM_FIFO_EMPTY)) {
return 0;
}
}
@@ -612,28 +611,27 @@
}
int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
- const struct fb_var_screeninfo *var,
- const struct fb_info *info)
+ const struct fb_var_screeninfo *var,
+ const struct fb_info *info)
{
- uint32_t total;
- /* check params */
- if ((var->xoffset + var->xres > var->xres_virtual) ||
- (var->yoffset + var->yres > var->yres_virtual)) {
- return -EINVAL;
- }
+ uint32_t total;
+ /* check params */
+ if ((var->xoffset + var->xres > var->xres_virtual) ||
+ (var->yoffset + var->yres > var->yres_virtual)) {
+ return -EINVAL;
+ }
- total = var->yoffset * info->fix.line_length +
- ((var->xoffset * var->bits_per_pixel) >> 3);
- total += crtc->oScreen;
- if (crtc->channel == sm750_primary) {
- POKE32(PANEL_FB_ADDRESS,
- FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS),
- PANEL_FB_ADDRESS, ADDRESS, total));
- } else {
- POKE32(CRT_FB_ADDRESS,
- FIELD_VALUE(PEEK32(CRT_FB_ADDRESS),
- CRT_FB_ADDRESS, ADDRESS, total));
- }
- return 0;
+ total = var->yoffset * info->fix.line_length +
+ ((var->xoffset * var->bits_per_pixel) >> 3);
+ total += crtc->oScreen;
+ if (crtc->channel == sm750_primary) {
+ POKE32(PANEL_FB_ADDRESS,
+ FIELD_VALUE(PEEK32(PANEL_FB_ADDRESS),
+ PANEL_FB_ADDRESS, ADDRESS, total));
+ } else {
+ POKE32(CRT_FB_ADDRESS,
+ FIELD_VALUE(PEEK32(CRT_FB_ADDRESS),
+ CRT_FB_ADDRESS, ADDRESS, total));
+ }
+ return 0;
}
-
diff --git a/drivers/staging/sm750fb/sm750_hw.h b/drivers/staging/sm750fb/sm750_hw.h
index 93288b3..3781a1a 100644
--- a/drivers/staging/sm750fb/sm750_hw.h
+++ b/drivers/staging/sm750fb/sm750_hw.h
@@ -2,14 +2,14 @@
#define LYNX_HW750_H__
-#define DEFAULT_SM750_CHIP_CLOCK 290
-#define DEFAULT_SM750LE_CHIP_CLOCK 333
+#define DEFAULT_SM750_CHIP_CLOCK 290
+#define DEFAULT_SM750LE_CHIP_CLOCK 333
#ifndef SM750LE_REVISION_ID
#define SM750LE_REVISION_ID (unsigned char)0xfe
#endif
-enum sm750_pnltype{
+enum sm750_pnltype {
sm750_24TFT = 0,/* 24bit tft */
@@ -19,30 +19,30 @@
};
/* vga channel is not concerned */
-enum sm750_dataflow{
+enum sm750_dataflow {
sm750_simul_pri,/* primary => all head */
sm750_simul_sec,/* secondary => all head */
- sm750_dual_normal,/* primary => panel head and secondary => crt */
+ sm750_dual_normal,/* primary => panel head and secondary => crt */
- sm750_dual_swap,/* primary => crt head and secondary => panel */
+ sm750_dual_swap,/* primary => crt head and secondary => panel */
};
-enum sm750_channel{
+enum sm750_channel {
sm750_primary = 0,
/* enum value equal to the register filed data */
sm750_secondary = 1,
};
-enum sm750_path{
+enum sm750_path {
sm750_panel = 1,
sm750_crt = 2,
sm750_pnc = 3,/* panel and crt */
};
-struct init_status{
+struct init_status {
ushort powerMode;
/* below three clocks are in unit of MHZ*/
ushort chip_clk;
@@ -52,7 +52,7 @@
ushort resetMemory;
};
-struct sm750_state{
+struct sm750_state {
struct init_status initParm;
enum sm750_pnltype pnltype;
enum sm750_dataflow dataflow;
@@ -61,24 +61,24 @@
int yLCD;
};
-/* sm750_share stands for a presentation of two frame buffer
- that use one sm750 adaptor, it is similar to the super class of lynx_share
- in C++
-*/
+/* sm750_share stands for a presentation of two frame buffer
+ that use one sm750 adaptor, it is similar to the super class of lynx_share
+ in C++
+ */
-struct sm750_share{
+struct sm750_share {
/* it's better to put lynx_share struct to the first place of sm750_share */
struct lynx_share share;
struct sm750_state state;
int hwCursor;
- /* 0: no hardware cursor
- 1: primary crtc hw cursor enabled,
- 2: secondary crtc hw cursor enabled
- 3: both ctrc hw cursor enabled
+ /* 0: no hardware cursor
+ 1: primary crtc hw cursor enabled,
+ 2: secondary crtc hw cursor enabled
+ 3: both ctrc hw cursor enabled
*/
};
-int hw_sm750_map(struct lynx_share* share, struct pci_dev* pdev);
+int hw_sm750_map(struct lynx_share *share, struct pci_dev *pdev);
int hw_sm750_inithw(struct lynx_share*, struct pci_dev *);
void hw_sm750_initAccel(struct lynx_share *);
int hw_sm750_deWait(void);
@@ -92,10 +92,10 @@
int hw_sm750_setColReg(struct lynxfb_crtc*, ushort, ushort, ushort, ushort);
int hw_sm750_setBLANK(struct lynxfb_output*, int);
int hw_sm750le_setBLANK(struct lynxfb_output*, int);
-void hw_sm750_crtc_clear(struct lynxfb_crtc*);
-void hw_sm750_output_clear(struct lynxfb_output*);
+void hw_sm750_crtc_clear(struct lynxfb_crtc *);
+void hw_sm750_output_clear(struct lynxfb_output *);
int hw_sm750_pan_display(struct lynxfb_crtc *crtc,
- const struct fb_var_screeninfo *var,
- const struct fb_info *info);
+ const struct fb_var_screeninfo *var,
+ const struct fb_info *info);
#endif
diff --git a/drivers/staging/sm7xxfb/Kconfig b/drivers/staging/sm7xxfb/Kconfig
deleted file mode 100644
index e2922ae..0000000
--- a/drivers/staging/sm7xxfb/Kconfig
+++ /dev/null
@@ -1,13 +0,0 @@
-config FB_SM7XX
- tristate "Silicon Motion SM7XX framebuffer support"
- depends on FB && PCI
- select FB_CFB_FILLRECT
- select FB_CFB_COPYAREA
- select FB_CFB_IMAGEBLIT
- help
- Frame buffer driver for the Silicon Motion SM710, SM712, SM721
- and SM722 chips.
-
- This driver is also available as a module. The module will be
- called sm7xxfb. If you want to compile it as a module, say M
- here and read <file:Documentation/kbuild/modules.txt>.
diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile
deleted file mode 100644
index 48f471cf..0000000
--- a/drivers/staging/sm7xxfb/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o
diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO
deleted file mode 100644
index 7cb0b24..0000000
--- a/drivers/staging/sm7xxfb/TODO
+++ /dev/null
@@ -1,12 +0,0 @@
-TODO:
-- Dual head support
-- 2D acceleration support
-- use kernel coding style
-- refine the code and remove unused code
-- move it to drivers/video/fbdev/sm7xxfb.c
-
-Please send any patches to
- Greg Kroah-Hartman <greg@kroah.com>
- Sudip Mukherjee <sudipm.mukherjee@gmail.com>
- Teddy Wang <teddy.wang@siliconmotion.com>
- Sudip Mukherjee <sudip@vectorindia.org>
diff --git a/drivers/staging/speakup/buffers.c b/drivers/staging/speakup/buffers.c
index d45c8af..d4d4598 100644
--- a/drivers/staging/speakup/buffers.c
+++ b/drivers/staging/speakup/buffers.c
@@ -63,7 +63,8 @@
{
if (!synth->alive) {
/* This makes sure that we won't stop TTYs if there is no synth
- * to restart them */
+ * to restart them
+ */
return;
}
if (synth_buffer_free() <= 100) {
diff --git a/drivers/staging/speakup/i18n.c b/drivers/staging/speakup/i18n.c
index 9ea16c5..f061747 100644
--- a/drivers/staging/speakup/i18n.c
+++ b/drivers/staging/speakup/i18n.c
@@ -1,5 +1,6 @@
/* Internationalization implementation. Includes definitions of English
- * string arrays, and the i18n pointer. */
+ * string arrays, and the i18n pointer.
+ */
#include <linux/slab.h> /* For kmalloc. */
#include <linux/ctype.h>
diff --git a/drivers/staging/speakup/i18n.h b/drivers/staging/speakup/i18n.h
index 326d086..8fcce56 100644
--- a/drivers/staging/speakup/i18n.h
+++ b/drivers/staging/speakup/i18n.h
@@ -224,11 +224,11 @@
enum msg_index_t end;
};
-extern char *spk_msg_get(enum msg_index_t index);
-extern ssize_t spk_msg_set(enum msg_index_t index, char *text, size_t length);
-extern struct msg_group_t *spk_find_msg_group(const char *group_name);
-extern void spk_reset_msg_group(struct msg_group_t *group);
-extern void spk_initialize_msgs(void);
-extern void spk_free_user_msgs(void);
+char *spk_msg_get(enum msg_index_t index);
+ssize_t spk_msg_set(enum msg_index_t index, char *text, size_t length);
+struct msg_group_t *spk_find_msg_group(const char *group_name);
+void spk_reset_msg_group(struct msg_group_t *group);
+void spk_initialize_msgs(void);
+void spk_free_user_msgs(void);
#endif
diff --git a/drivers/staging/speakup/keyhelp.c b/drivers/staging/speakup/keyhelp.c
index 9475674..02d5c70 100644
--- a/drivers/staging/speakup/keyhelp.c
+++ b/drivers/staging/speakup/keyhelp.c
@@ -165,7 +165,7 @@
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) <=
diff --git a/drivers/staging/speakup/kobjects.c b/drivers/staging/speakup/kobjects.c
index 0211df6..958add4 100644
--- a/drivers/staging/speakup/kobjects.c
+++ b/drivers/staging/speakup/kobjects.c
@@ -240,7 +240,8 @@
cp += sprintf(cp, "%d, %d, %d,\n", KEY_MAP_VER, num_keys, nstates);
cp1 += 2; /* now pointing at shift states */
/* dump num_keys+1 as first row is shift states + flags,
- * each subsequent row is key + states */
+ * each subsequent row is key + states
+ */
for (n = 0; n <= num_keys; n++) {
for (i = 0; i <= nstates; i++) {
ch = *cp1++;
diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c
index 6c4f9a1..63c59bc 100644
--- a/drivers/staging/speakup/main.c
+++ b/drivers/staging/speakup/main.c
@@ -128,7 +128,8 @@
/* array of 256 char pointers (one for each character description)
* initialized to default_chars and user selectable via
- * /proc/speakup/characters */
+ * /proc/speakup/characters
+ */
char *spk_characters[256];
char *spk_default_chars[256] = {
@@ -194,7 +195,8 @@
/* array of 256 u_short (one for each character)
* initialized to default_chartab and user selectable via
- * /sys/module/speakup/parameters/chartab */
+ * /sys/module/speakup/parameters/chartab
+ */
u_short spk_chartab[256];
static u_short default_chartab[256] = {
@@ -540,7 +542,8 @@
* see if there is a word starting on the next position to the right
* and return that word if it exists. If it does not exist it will
* move left to the beginning of any previous word on the line or the
- * beginning off the line whichever comes first.. */
+ * beginning off the line whichever comes first..
+ */
static u_long get_word(struct vc_data *vc)
{
@@ -1113,7 +1116,8 @@
* suppress multiple to get rid of long pauses and
* clear repeat count
* so if someone has
- * repeats on you don't get nothing repeated count */
+ * repeats on you don't get nothing repeated count
+ */
if (ch != old_ch)
synth_printf("%c", ch);
else
@@ -1509,7 +1513,8 @@
if (spk_no_intr)
spk_do_flush();
/* the key press flushes if !no_inter but we want to flush on cursor
- * moves regardless of no_inter state */
+ * moves regardless of no_inter state
+ */
is_cursor = value + 1;
old_cursor_pos = vc->vc_pos;
old_cursor_x = vc->vc_x;
diff --git a/drivers/staging/speakup/selection.c b/drivers/staging/speakup/selection.c
index a031570..98af3b1 100644
--- a/drivers/staging/speakup/selection.c
+++ b/drivers/staging/speakup/selection.c
@@ -114,7 +114,8 @@
obp = bp;
if (!((i + 2) % vc->vc_size_row)) {
/* strip trailing blanks from line and add newline,
- unless non-space at end of line. */
+ * unless non-space at end of line.
+ */
if (obp != bp) {
bp = obp;
*bp++ = '\r';
diff --git a/drivers/staging/speakup/serialio.c b/drivers/staging/speakup/serialio.c
index 1d9d51b..66ac999 100644
--- a/drivers/staging/speakup/serialio.c
+++ b/drivers/staging/speakup/serialio.c
@@ -51,7 +51,8 @@
}
/* Disable UART interrupts, set DTR and RTS high
- * and set speed. */
+ * and set speed.
+ */
outb(cval | UART_LCR_DLAB, ser->port + UART_LCR); /* set DLAB */
outb(quot & 0xff, ser->port + UART_DLL); /* LS of divisor */
outb(quot >> 8, ser->port + UART_DLM); /* MS of divisor */
@@ -145,7 +146,8 @@
synth->alive = 0;
/* No synth any more, so nobody will restart TTYs, and we thus
* need to do it ourselves. Now that there is no synth we can
- * let application flood anyway */
+ * let application flood anyway
+ */
speakup_start_ttys();
timeouts = 0;
return 0;
@@ -163,7 +165,8 @@
/* CTS */
if (--tmout == 0) {
/* pr_warn("%s: timed out (cts)\n",
- * synth->long_name); */
+ * synth->long_name);
+ */
timeouts++;
return 0;
}
@@ -217,4 +220,3 @@
speakup_info.port_tts = 0;
}
EXPORT_SYMBOL_GPL(spk_serial_release);
-
diff --git a/drivers/staging/speakup/speakup.h b/drivers/staging/speakup/speakup.h
index a7f4962..df74c91 100644
--- a/drivers/staging/speakup/speakup.h
+++ b/drivers/staging/speakup/speakup.h
@@ -42,46 +42,44 @@
#define IS_CHAR(x, type) (spk_chartab[((u_char)x)]&type)
#define IS_TYPE(x, type) ((spk_chartab[((u_char)x)]&type) == type)
-extern int speakup_thread(void *data);
-extern void spk_reset_default_chars(void);
-extern void spk_reset_default_chartab(void);
-extern void synth_start(void);
+int speakup_thread(void *data);
+void spk_reset_default_chars(void);
+void spk_reset_default_chartab(void);
+void synth_start(void);
void synth_insert_next_index(int sent_num);
void spk_reset_index_count(int sc);
void spk_get_index_count(int *linecount, int *sentcount);
-extern int spk_set_key_info(const u_char *key_info, u_char *k_buffer);
-extern char *spk_strlwr(char *s);
-extern char *spk_s2uchar(char *start, char *dest);
-extern int speakup_kobj_init(void);
-extern void speakup_kobj_exit(void);
-extern int spk_chartab_get_value(char *keyword);
-extern void speakup_register_var(struct var_t *var);
-extern void speakup_unregister_var(enum var_id_t var_id);
-extern struct st_var_header *spk_get_var_header(enum var_id_t var_id);
-extern struct st_var_header *spk_var_header_by_name(const char *name);
-extern struct punc_var_t *spk_get_punc_var(enum var_id_t var_id);
-extern int spk_set_num_var(int val, struct st_var_header *var, int how);
-extern int spk_set_string_var(const char *page, struct st_var_header *var,
- int len);
-extern int spk_set_mask_bits(const char *input, const int which, const int how);
+int spk_set_key_info(const u_char *key_info, u_char *k_buffer);
+char *spk_strlwr(char *s);
+char *spk_s2uchar(char *start, char *dest);
+int speakup_kobj_init(void);
+void speakup_kobj_exit(void);
+int spk_chartab_get_value(char *keyword);
+void speakup_register_var(struct var_t *var);
+void speakup_unregister_var(enum var_id_t var_id);
+struct st_var_header *spk_get_var_header(enum var_id_t var_id);
+struct st_var_header *spk_var_header_by_name(const char *name);
+struct punc_var_t *spk_get_punc_var(enum var_id_t var_id);
+int spk_set_num_var(int val, struct st_var_header *var, int how);
+int spk_set_string_var(const char *page, struct st_var_header *var, int len);
+int spk_set_mask_bits(const char *input, const int which, const int how);
extern special_func spk_special_handler;
-extern int spk_handle_help(struct vc_data *vc, u_char type, u_char ch,
- u_short key);
-extern int synth_init(char *name);
-extern void synth_release(void);
+int spk_handle_help(struct vc_data *vc, u_char type, u_char ch, u_short key);
+int synth_init(char *name);
+void synth_release(void);
-extern void spk_do_flush(void);
-extern void speakup_start_ttys(void);
-extern void synth_buffer_add(char ch);
-extern void synth_buffer_clear(void);
-extern void speakup_clear_selection(void);
-extern int speakup_set_selection(struct tty_struct *tty);
-extern int speakup_paste_selection(struct tty_struct *tty);
-extern void speakup_cancel_paste(void);
-extern void speakup_register_devsynth(void);
-extern void speakup_unregister_devsynth(void);
-extern void synth_write(const char *buf, size_t count);
-extern int synth_supports_indexing(void);
+void spk_do_flush(void);
+void speakup_start_ttys(void);
+void synth_buffer_add(char ch);
+void synth_buffer_clear(void);
+void speakup_clear_selection(void);
+int speakup_set_selection(struct tty_struct *tty);
+int speakup_paste_selection(struct tty_struct *tty);
+void speakup_cancel_paste(void);
+void speakup_register_devsynth(void);
+void speakup_unregister_devsynth(void);
+void synth_write(const char *buf, size_t count);
+int synth_supports_indexing(void);
extern struct vc_data *spk_sel_cons;
extern unsigned short spk_xs, spk_ys, spk_xe, spk_ye; /* our region points */
diff --git a/drivers/staging/speakup/speakup_acnt.h b/drivers/staging/speakup/speakup_acnt.h
index 6376fca..107ec11 100644
--- a/drivers/staging/speakup/speakup_acnt.h
+++ b/drivers/staging/speakup/speakup_acnt.h
@@ -6,10 +6,12 @@
/* Port Status Flags */
#define SYNTH_READABLE 0x01 /* mask for bit which is nonzero if a
- byte can be read from the data port */
+ * byte can be read from the data port
+ */
#define SYNTH_WRITABLE 0x02 /* mask for RDY bit, which when set to
- 1, indicates the data port is ready
- to accept a byte of data. */
+ * 1, indicates the data port is ready
+ * to accept a byte of data.
+ */
#define SYNTH_QUIET 'S' /* synth is not speaking */
#define SYNTH_FULL 'F' /* synth is full. */
#define SYNTH_ALMOST_EMPTY 'M' /* synth has less than 2 seconds of text left */
diff --git a/drivers/staging/speakup/speakup_decpc.c b/drivers/staging/speakup/speakup_decpc.c
index 437e13a..4893fef 100644
--- a/drivers/staging/speakup/speakup_decpc.c
+++ b/drivers/staging/speakup/speakup_decpc.c
@@ -88,8 +88,9 @@
#define CTRL_last_index 0x0b00 /* get last index spoken */
#define CTRL_io_priority 0x0c00 /* change i/o priority */
#define CTRL_free_mem 0x0d00 /* get free paragraphs on module */
-#define CTRL_get_lang 0x0e00 /* return bit mask of loaded
- * languages */
+#define CTRL_get_lang 0x0e00 /* return bit mask of loaded
+ * languages
+ */
#define CMD_test 0x2000 /* self-test request */
#define TEST_mask 0x0F00 /* isolate test field */
#define TEST_null 0x0000 /* no test requested */
@@ -500,4 +501,3 @@
MODULE_DESCRIPTION("Speakup support for DECtalk PC synthesizers");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-
diff --git a/drivers/staging/speakup/speakup_dtlk.h b/drivers/staging/speakup/speakup_dtlk.h
index d951d18..46d885f 100644
--- a/drivers/staging/speakup/speakup_dtlk.h
+++ b/drivers/staging/speakup/speakup_dtlk.h
@@ -4,31 +4,37 @@
#define SYNTH_CLEAR 0x18 /* stops speech */
/* TTS Port Status Flags */
#define TTS_READABLE 0x80 /* mask for bit which is nonzero if a
- byte can be read from the TTS port */
+ * byte can be read from the TTS port
+ */
#define TTS_SPEAKING 0x40 /* mask for SYNC bit, which is nonzero
- while DoubleTalk is producing
- output with TTS, PCM or CVSD
- synthesizers or tone generators
- (that is, all but LPC) */
+ * while DoubleTalk is producing
+ * output with TTS, PCM or CVSD
+ * synthesizers or tone generators
+ * (that is, all but LPC)
+ */
#define TTS_SPEAKING2 0x20 /* mask for SYNC2 bit,
- which falls to zero up to 0.4 sec
- before speech stops */
+ * which falls to zero up to 0.4 sec
+ * before speech stops
+ */
#define TTS_WRITABLE 0x10 /* mask for RDY bit, which when set to
- 1, indicates the TTS port is ready
- to accept a byte of data. The RDY
- bit goes zero 2-3 usec after
- writing, and goes 1 again 180-190
- usec later. */
+ * 1, indicates the TTS port is ready
+ * to accept a byte of data. The RDY
+ * bit goes zero 2-3 usec after
+ * writing, and goes 1 again 180-190
+ * usec later.
+ */
#define TTS_ALMOST_FULL 0x08 /* mask for AF bit: When set to 1,
- indicates that less than 300 bytes
- are available in the TTS input
- buffer. AF is always 0 in the PCM,
- TGN and CVSD modes. */
+ * indicates that less than 300 bytes
+ * are available in the TTS input
+ * buffer. AF is always 0 in the PCM,
+ * TGN and CVSD modes.
+ */
#define TTS_ALMOST_EMPTY 0x04 /* mask for AE bit: When set to 1,
- indicates that less than 300 bytes
- are remaining in DoubleTalk's input
- (TTS or PCM) buffer. AE is always 1
- in the TGN and CVSD modes. */
+ * indicates that less than 300 bytes
+ * are remaining in DoubleTalk's input
+ * (TTS or PCM) buffer. AE is always 1
+ * in the TGN and CVSD modes.
+ */
/* data returned by Interrogate command */
struct synth_settings {
@@ -45,10 +51,12 @@
u_char ext_dict_loaded; /* 1=exception dictionary loaded */
u_char ext_dict_status; /* 1=exception dictionary enabled */
u_char free_ram; /* # pages (truncated) remaining for
- * text buffer */
+ * text buffer
+ */
u_char articulation; /* nA; 0-9 */
u_char reverb; /* nR; 0-9 */
u_char eob; /* 7Fh value indicating end of
- * parameter block */
+ * parameter block
+ */
u_char has_indexing; /* nonzero if indexing is implemented */
};
diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c
index fb31bb9..366358b 100644
--- a/drivers/staging/speakup/speakup_soft.c
+++ b/drivers/staging/speakup/speakup_soft.c
@@ -356,4 +356,3 @@
MODULE_DESCRIPTION("Speakup userspace software synthesizer support");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
-
diff --git a/drivers/staging/speakup/thread.c b/drivers/staging/speakup/thread.c
index d95efb7..90c383e 100644
--- a/drivers/staging/speakup/thread.c
+++ b/drivers/staging/speakup/thread.c
@@ -48,7 +48,8 @@
kd_mksound(our_sound.freq, our_sound.jiffies);
if (synth && synth->catch_up && synth->alive) {
/* It is up to the callee to take the lock, so that it
- * can sleep whenever it likes */
+ * can sleep whenever it likes
+ */
synth->catch_up(synth);
}
diff --git a/drivers/staging/speakup/varhandlers.c b/drivers/staging/speakup/varhandlers.c
index 1b0d1c0..75bf40c 100644
--- a/drivers/staging/speakup/varhandlers.c
+++ b/drivers/staging/speakup/varhandlers.c
@@ -269,7 +269,8 @@
/* spk_set_mask_bits sets or clears the punc/delim/repeat bits,
* if input is null uses the defaults.
* values for how: 0 clears bits of chars supplied,
- * 1 clears allk, 2 sets bits for chars */
+ * 1 clears allk, 2 sets bits for chars
+ */
int spk_set_mask_bits(const char *input, const int which, const int how)
{
u_char *cp;
diff --git a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
index 0f524bb..1f9ba8b 100644
--- a/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
+++ b/drivers/staging/ste_rmi4/synaptics_i2c_rmi4.c
@@ -1126,7 +1126,6 @@
static struct i2c_driver synaptics_rmi4_driver = {
.driver = {
.name = DRIVER_NAME,
- .owner = THIS_MODULE,
.pm = &synaptics_rmi4_dev_pm_ops,
},
.probe = synaptics_rmi4_probe,
diff --git a/drivers/staging/unisys/Kconfig b/drivers/staging/unisys/Kconfig
index 778f9d0..624abe6 100644
--- a/drivers/staging/unisys/Kconfig
+++ b/drivers/staging/unisys/Kconfig
@@ -3,7 +3,7 @@
#
menuconfig UNISYSSPAR
bool "Unisys SPAR driver support"
- depends on X86_64
+ depends on X86_64 && !UML
select PCI
select ACPI
---help---
diff --git a/drivers/staging/unisys/include/channel_guid.h b/drivers/staging/unisys/include/channel_guid.h
index 706363fc..17cb499 100644
--- a/drivers/staging/unisys/include/channel_guid.h
+++ b/drivers/staging/unisys/include/channel_guid.h
@@ -17,35 +17,31 @@
* CHANNEL Guids
*/
-/* Used in IOChannel
- * {414815ed-c58c-11da-95a9-00e08161165f}
- */
+/* {414815ed-c58c-11da-95a9-00e08161165f} */
#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID \
UUID_LE(0x414815ed, 0xc58c, 0x11da, \
0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
static const uuid_le spar_vhba_channel_protocol_uuid =
SPAR_VHBA_CHANNEL_PROTOCOL_UUID;
+#define SPAR_VHBA_CHANNEL_PROTOCOL_UUID_STR \
+ "414815ed-c58c-11da-95a9-00e08161165f"
-/* Used in IOChannel
- * {8cd5994d-c58e-11da-95a9-00e08161165f}
- */
+/* {8cd5994d-c58e-11da-95a9-00e08161165f} */
#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID \
UUID_LE(0x8cd5994d, 0xc58e, 0x11da, \
0x95, 0xa9, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f)
static const uuid_le spar_vnic_channel_protocol_uuid =
SPAR_VNIC_CHANNEL_PROTOCOL_UUID;
+#define SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR \
+ "8cd5994d-c58e-11da-95a9-00e08161165f"
-/* Used in IOChannel
- * {72120008-4AAB-11DC-8530-444553544200}
- */
+/* {72120008-4AAB-11DC-8530-444553544200} */
#define SPAR_SIOVM_UUID \
UUID_LE(0x72120008, 0x4AAB, 0x11DC, \
0x85, 0x30, 0x44, 0x45, 0x53, 0x54, 0x42, 0x00)
static const uuid_le spar_siovm_uuid = SPAR_SIOVM_UUID;
-/* Used in visornoop/visornoop_main.c
- * {5b52c5ac-e5f5-4d42-8dff-429eaecd221f}
- */
+/* {5b52c5ac-e5f5-4d42-8dff-429eaecd221f} */
#define SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID \
UUID_LE(0x5b52c5ac, 0xe5f5, 0x4d42, \
0x8d, 0xff, 0x42, 0x9e, 0xae, 0xcd, 0x22, 0x1f)
@@ -53,9 +49,7 @@
static const uuid_le spar_controldirector_channel_protocol_uuid =
SPAR_CONTROLDIRECTOR_CHANNEL_PROTOCOL_UUID;
-/* Used in visorchipset/visorchipset_main.c
- * {B4E79625-AEDE-4EAA-9E11-D3EDDCD4504C}
- */
+/* {b4e79625-aede-4eAA-9e11-D3eddcd4504c} */
#define SPAR_DIAG_POOL_CHANNEL_PROTOCOL_UUID \
UUID_LE(0xb4e79625, 0xaede, 0x4eaa, \
0x9e, 0x11, 0xd3, 0xed, 0xdc, 0xd4, 0x50, 0x4c)
diff --git a/drivers/staging/unisys/include/visorbus.h b/drivers/staging/unisys/include/visorbus.h
index e4a21e4..9235536 100644
--- a/drivers/staging/unisys/include/visorbus.h
+++ b/drivers/staging/unisys/include/visorbus.h
@@ -113,7 +113,8 @@
struct driver_attribute version_attr;
};
-#define to_visor_driver(x) container_of(x, struct visor_driver, driver)
+#define to_visor_driver(x) ((x) ? \
+ (container_of(x, struct visor_driver, driver)) : (NULL))
/** A device type for things "plugged" into the visorbus bus */
@@ -200,6 +201,8 @@
void *msg);
bool visorchannel_signalinsert(struct visorchannel *channel, u32 queue,
void *msg);
+bool visorchannel_signalempty(struct visorchannel *channel, u32 queue);
+
int visorchannel_signalqueue_slots_avail(struct visorchannel *channel,
u32 queue);
int visorchannel_signalqueue_max_slots(struct visorchannel *channel, u32 queue);
diff --git a/drivers/staging/unisys/visorbus/controlvmchannel.h b/drivers/staging/unisys/visorbus/controlvmchannel.h
index a50d9cf..ec25366 100644
--- a/drivers/staging/unisys/visorbus/controlvmchannel.h
+++ b/drivers/staging/unisys/visorbus/controlvmchannel.h
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h b/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
index f74f5d8..3c97ebac4 100644
--- a/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
+++ b/drivers/staging/unisys/visorbus/controlvmcompletionstatus.h
@@ -1,12 +1,11 @@
/* controlvmcompletionstatus.c
*
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/drivers/staging/unisys/visorbus/iovmcall_gnuc.h b/drivers/staging/unisys/visorbus/iovmcall_gnuc.h
index 57dd93e..b08b6ec 100644
--- a/drivers/staging/unisys/visorbus/iovmcall_gnuc.h
+++ b/drivers/staging/unisys/visorbus/iovmcall_gnuc.h
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/drivers/staging/unisys/visorbus/periodic_work.c b/drivers/staging/unisys/visorbus/periodic_work.c
index 5e56088..a3631c3 100644
--- a/drivers/staging/unisys/visorbus/periodic_work.c
+++ b/drivers/staging/unisys/visorbus/periodic_work.c
@@ -1,12 +1,11 @@
/* periodic_work.c
*
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/drivers/staging/unisys/visorbus/vbuschannel.h b/drivers/staging/unisys/visorbus/vbuschannel.h
index 5ed83a3..80e6447 100644
--- a/drivers/staging/unisys/visorbus/vbuschannel.h
+++ b/drivers/staging/unisys/visorbus/vbuschannel.h
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h
index 9b6d3e6..f59fd8a 100644
--- a/drivers/staging/unisys/visorbus/vbusdeviceinfo.h
+++ b/drivers/staging/unisys/visorbus/vbusdeviceinfo.h
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/drivers/staging/unisys/visorbus/visorbus_main.c b/drivers/staging/unisys/visorbus/visorbus_main.c
index 6db4719..2309f5f 100644
--- a/drivers/staging/unisys/visorbus/visorbus_main.c
+++ b/drivers/staging/unisys/visorbus/visorbus_main.c
@@ -1,12 +1,11 @@
/* visorbus_main.c
*
- * Copyright � 2010 - 2013 UNISYS CORPORATION
+ * Copyright � 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -70,6 +69,38 @@
NULL,
};
+/*
+ * DEVICE type attributes
+ *
+ * The modalias file will contain the guid of the device.
+ */
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct visor_device *vdev;
+ uuid_le guid;
+
+ vdev = to_visor_device(dev);
+ guid = visorchannel_get_uuid(vdev->visorchannel);
+ return snprintf(buf, PAGE_SIZE, "visorbus:%pUl\n", &guid);
+}
+static DEVICE_ATTR_RO(modalias);
+
+static struct attribute *visorbus_dev_attrs[] = {
+ &dev_attr_modalias.attr,
+ NULL,
+};
+
+/* sysfs example for bridge-only sysfs files using device_type's */
+static const struct attribute_group visorbus_dev_group = {
+ .attrs = visorbus_dev_attrs,
+};
+
+static const struct attribute_group *visorbus_dev_groups[] = {
+ &visorbus_dev_group,
+ NULL,
+};
+
/** This describes the TYPE of bus.
* (Don't confuse this with an INSTANCE of the bus.)
*/
@@ -77,6 +108,7 @@
.name = "visorbus",
.match = visorbus_match,
.uevent = visorbus_uevent,
+ .dev_groups = visorbus_dev_groups,
.bus_groups = visorbus_bus_groups,
};
@@ -129,7 +161,13 @@
static int
visorbus_uevent(struct device *xdev, struct kobj_uevent_env *env)
{
- if (add_uevent_var(env, "VERSION=%s", VERSION))
+ struct visor_device *dev;
+ uuid_le guid;
+
+ dev = to_visor_device(xdev);
+ guid = visorchannel_get_uuid(dev->visorchannel);
+
+ if (add_uevent_var(env, "MODALIAS=visorbus:%pUl", &guid))
return -ENOMEM;
return 0;
}
@@ -218,9 +256,9 @@
struct devmajorminor_attribute {
struct attribute attr;
int slot;
- ssize_t (*show)(struct visor_device *, int slot, char *buf);
- ssize_t (*store)(struct visor_device *, int slot, const char *buf,
- size_t count);
+ ssize_t (*show)(struct visor_device *, int slot, char *buf);
+ ssize_t (*store)(struct visor_device *, int slot, const char *buf,
+ size_t count);
};
static ssize_t DEVMAJORMINOR_ATTR(struct visor_device *dev, int slot, char *buf)
@@ -281,12 +319,11 @@
rc = -ENOMEM;
goto away;
}
- myattr = kmalloc(sizeof(*myattr), GFP_KERNEL);
+ myattr = kzalloc(sizeof(*myattr), GFP_KERNEL);
if (!myattr) {
rc = -ENOMEM;
goto away;
}
- memset(myattr, 0, sizeof(struct devmajorminor_attribute));
myattr->show = DEVMAJORMINOR_ATTR;
myattr->store = NULL;
myattr->slot = slot;
@@ -471,6 +508,7 @@
&dev_attr_typeguid.attr,
&dev_attr_zoneguid.attr,
&dev_attr_typename.attr,
+ NULL
};
static struct attribute_group channel_attr_grp = {
@@ -478,7 +516,7 @@
.attrs = channel_attrs,
};
-static const struct attribute_group *visorbus_dev_groups[] = {
+static const struct attribute_group *visorbus_channel_groups[] = {
&channel_attr_grp,
NULL
};
@@ -678,7 +716,7 @@
static void
dev_periodic_work(void *xdev)
{
- struct visor_device *dev = (struct visor_device *)xdev;
+ struct visor_device *dev = xdev;
struct visor_driver *drv = to_visor_driver(dev->device.driver);
down(&dev->visordriver_callback_lock);
@@ -937,7 +975,7 @@
sema_init(&dev->visordriver_callback_lock, 1); /* unlocked */
dev->device.bus = &visorbus_type;
- dev->device.groups = visorbus_dev_groups;
+ dev->device.groups = visorbus_channel_groups;
device_initialize(&dev->device);
dev->device.release = visorbus_release_device;
/* keep a reference just for us (now 2) */
@@ -1043,10 +1081,10 @@
int off = sizeof(struct channel_header) + hdr_info->chp_info_offset;
if (hdr_info->chp_info_offset == 0)
- return -1;
+ return -1;
if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
- return -1;
+ return -1;
return 0;
}
@@ -1061,10 +1099,10 @@
int off = sizeof(struct channel_header) + hdr_info->bus_info_offset;
if (hdr_info->bus_info_offset == 0)
- return -1;
+ return -1;
if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
- return -1;
+ return -1;
return 0;
}
@@ -1081,10 +1119,10 @@
(hdr_info->device_info_struct_bytes * devix);
if (hdr_info->dev_info_offset == 0)
- return -1;
+ return -1;
if (visorchannel_write(chan, off, info, sizeof(*info)) < 0)
- return -1;
+ return -1;
return 0;
}
@@ -1106,7 +1144,7 @@
struct spar_vbus_headerinfo *hdr_info;
if (!visordev->device.driver)
- return;
+ return;
hdr_info = (struct spar_vbus_headerinfo *)visordev->vbus_hdr_info;
if (!hdr_info)
@@ -1319,11 +1357,11 @@
pause_state_change_complete(struct visor_device *dev, int status)
{
if (!dev->pausing)
- return;
+ return;
dev->pausing = false;
if (!chipset_responders.device_pause) /* this can never happen! */
- return;
+ return;
/* Notify the chipset driver that the pause is complete, which
* will presumably want to send some sort of response to the
@@ -1339,11 +1377,11 @@
resume_state_change_complete(struct visor_device *dev, int status)
{
if (!dev->resuming)
- return;
+ return;
dev->resuming = false;
if (!chipset_responders.device_resume) /* this can never happen! */
- return;
+ return;
/* Notify the chipset driver that the resume is complete,
* which will presumably want to send some sort of response to
@@ -1367,14 +1405,14 @@
else
notify_func = chipset_responders.device_resume;
if (!notify_func)
- goto away;
+ goto away;
drv = to_visor_driver(dev->device.driver);
if (!drv)
- goto away;
+ goto away;
if (dev->pausing || dev->resuming)
- goto away;
+ goto away;
/* Note that even though both drv->pause() and drv->resume
* specify a callback function, it is NOT necessary for us to
@@ -1385,7 +1423,7 @@
*/
if (is_pause) {
if (!drv->pause)
- goto away;
+ goto away;
dev->pausing = true;
x = drv->pause(dev, pause_state_change_complete);
@@ -1397,7 +1435,7 @@
* would never even get here in that case. */
fix_vbus_dev_info(dev);
if (!drv->resume)
- goto away;
+ goto away;
dev->resuming = true;
x = drv->resume(dev, resume_state_change_complete);
@@ -1413,7 +1451,7 @@
away:
if (rc < 0) {
if (notify_func)
- (*notify_func)(dev, rc);
+ (*notify_func)(dev, rc);
}
}
@@ -1469,8 +1507,8 @@
away:
if (rc)
- POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc,
- POSTCODE_SEVERITY_ERR);
+ POSTCODE_LINUX_3(CHIPSET_INIT_FAILURE_PC, rc,
+ POSTCODE_SEVERITY_ERR);
return rc;
}
@@ -1495,9 +1533,8 @@
list_for_each_safe(listentry, listtmp, &list_all_bus_instances) {
struct visor_device *dev = list_entry(listentry,
- struct
- visor_device,
- list_all);
+ struct visor_device,
+ list_all);
remove_bus_instance(dev);
}
remove_bus_type();
diff --git a/drivers/staging/unisys/visorbus/visorbus_private.h b/drivers/staging/unisys/visorbus/visorbus_private.h
index 2f12483..39edd20 100644
--- a/drivers/staging/unisys/visorbus/visorbus_private.h
+++ b/drivers/staging/unisys/visorbus/visorbus_private.h
@@ -1,12 +1,11 @@
/* visorchipset.h
*
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/drivers/staging/unisys/visorbus/visorchannel.c b/drivers/staging/unisys/visorbus/visorchannel.c
index 20b6349..6da7e49 100644
--- a/drivers/staging/unisys/visorbus/visorchannel.c
+++ b/drivers/staging/unisys/visorbus/visorchannel.c
@@ -1,12 +1,11 @@
/* visorchannel_funcs.c
*
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -259,7 +258,8 @@
if (offset < chdr_size) {
copy_size = min(chdr_size - offset, nbytes);
- memcpy(&channel->chan_hdr + offset, local, copy_size);
+ memcpy(((char *)(&channel->chan_hdr)) + offset,
+ local, copy_size);
}
memcpy_toio(channel->mapped + offset, local, nbytes);
@@ -416,11 +416,12 @@
visorchannel_signalremove(struct visorchannel *channel, u32 queue, void *msg)
{
bool rc;
+ unsigned long flags;
if (channel->needs_lock) {
- spin_lock(&channel->remove_lock);
+ spin_lock_irqsave(&channel->remove_lock, flags);
rc = signalremove_inner(channel, queue, msg);
- spin_unlock(&channel->remove_lock);
+ spin_unlock_irqrestore(&channel->remove_lock, flags);
} else {
rc = signalremove_inner(channel, queue, msg);
}
@@ -429,6 +430,27 @@
}
EXPORT_SYMBOL_GPL(visorchannel_signalremove);
+bool
+visorchannel_signalempty(struct visorchannel *channel, u32 queue)
+{
+ unsigned long flags = 0;
+ struct signal_queue_header sig_hdr;
+ bool rc = false;
+
+ if (channel->needs_lock)
+ spin_lock_irqsave(&channel->remove_lock, flags);
+
+ if (!sig_read_header(channel, queue, &sig_hdr))
+ rc = true;
+ if (sig_hdr.head == sig_hdr.tail)
+ rc = true;
+ if (channel->needs_lock)
+ spin_unlock_irqrestore(&channel->remove_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(visorchannel_signalempty);
+
static bool
signalinsert_inner(struct visorchannel *channel, u32 queue, void *msg)
{
@@ -470,11 +492,12 @@
visorchannel_signalinsert(struct visorchannel *channel, u32 queue, void *msg)
{
bool rc;
+ unsigned long flags;
if (channel->needs_lock) {
- spin_lock(&channel->insert_lock);
+ spin_lock_irqsave(&channel->insert_lock, flags);
rc = signalinsert_inner(channel, queue, msg);
- spin_unlock(&channel->insert_lock);
+ spin_unlock_irqrestore(&channel->insert_lock, flags);
} else {
rc = signalinsert_inner(channel, queue, msg);
}
diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c
index bb8087e..4b76cb4 100644
--- a/drivers/staging/unisys/visorbus/visorchipset.c
+++ b/drivers/staging/unisys/visorbus/visorchipset.c
@@ -1,12 +1,11 @@
/* visorchipset_main.c
*
- * Copyright (C) 2010 - 2013 UNISYS CORPORATION
+ * Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -1247,10 +1246,11 @@
POSTCODE_LINUX_4(DEVICE_CREATE_ENTRY_PC, dev_no, bus_no,
POSTCODE_SEVERITY_INFO);
- visorchannel = visorchannel_create(cmd->create_device.channel_addr,
- cmd->create_device.channel_bytes,
- GFP_KERNEL,
- cmd->create_device.data_type_uuid);
+ visorchannel =
+ visorchannel_create_with_lock(cmd->create_device.channel_addr,
+ cmd->create_device.channel_bytes,
+ GFP_KERNEL,
+ cmd->create_device.data_type_uuid);
if (!visorchannel) {
POSTCODE_LINUX_4(DEVICE_CREATE_FAILURE_PC, dev_no, bus_no,
@@ -2047,6 +2047,7 @@
response);
kfree(dev_info->pending_msg_hdr);
+ dev_info->pending_msg_hdr = NULL;
}
static void
@@ -2381,6 +2382,9 @@
.remove = visorchipset_exit,
},
};
+
+MODULE_DEVICE_TABLE(acpi, unisys_device_ids);
+
static __init uint32_t visorutil_spar_detect(void)
{
unsigned int eax, ebx, ecx, edx;
diff --git a/drivers/staging/unisys/visorbus/vmcallinterface.h b/drivers/staging/unisys/visorbus/vmcallinterface.h
index 7a53df00..7abd27a 100644
--- a/drivers/staging/unisys/visorbus/vmcallinterface.h
+++ b/drivers/staging/unisys/visorbus/vmcallinterface.h
@@ -1,10 +1,9 @@
-/* Copyright (C) 2010 - 2013 UNISYS CORPORATION
+/* Copyright (C) 2010 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
index 7100744..8c9da7e 100644
--- a/drivers/staging/unisys/visornic/visornic_main.c
+++ b/drivers/staging/unisys/visornic/visornic_main.c
@@ -1,10 +1,9 @@
/* Copyright (c) 2012 - 2015 UNISYS CORPORATION
* All rights reserved.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -20,15 +19,16 @@
*/
#include <linux/debugfs.h>
-#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
+#include <linux/netdevice.h>
#include <linux/kthread.h>
+#include <linux/skbuff.h>
+#include <linux/rtnetlink.h>
#include "visorbus.h"
#include "iochannel.h"
-#define VISORNIC_INFINITE_RESPONSE_WAIT 0
+#define VISORNIC_INFINITE_RSP_WAIT 0
#define VISORNICSOPENMAX 32
#define MAXDEVICES 16384
@@ -61,7 +61,6 @@
.write = enable_ints_write,
};
-static struct workqueue_struct *visornic_serverdown_workqueue;
static struct workqueue_struct *visornic_timeout_reset_workqueue;
/* GUIDS for director channel type supported by this driver. */
@@ -72,6 +71,15 @@
{ SPAR_VNIC_CHANNEL_PROTOCOL_UUID, "ultravnic" },
{ NULL_UUID_LE, NULL }
};
+MODULE_DEVICE_TABLE(visorbus, visornic_channel_types);
+/*
+ * FIXME XXX: This next line of code must be fixed and removed before
+ * acceptance into the 'normal' part of the kernel. It is only here as a place
+ * holder to get module autoloading functionality working for visorbus. Code
+ * must be added to scripts/mode/file2alias.c, etc., to get this working
+ * properly.
+ */
+MODULE_ALIAS("visorbus:" SPAR_VNIC_CHANNEL_PROTOCOL_UUID_STR);
/* This is used to tell the visor bus driver which types of visor devices
* we support, and what functions to call when a visor device that we support
@@ -90,12 +98,6 @@
.channel_interrupt = NULL,
};
-struct visor_thread_info {
- struct task_struct *task;
- struct completion has_stopped;
- int id;
-};
-
struct chanstat {
unsigned long got_rcv;
unsigned long got_enbdisack;
@@ -104,6 +106,7 @@
unsigned long sent_enbdis;
unsigned long sent_promisc;
unsigned long sent_post;
+ unsigned long sent_post_failed;
unsigned long sent_xmit;
unsigned long reject_count;
unsigned long extra_rcvbufs_sent;
@@ -111,7 +114,6 @@
struct visornic_devdata {
int devnum;
- int thread_wait_ms;
unsigned short enabled; /* 0 disabled 1 enabled to receive */
unsigned short enab_dis_acked; /* NET_RCV_ENABLE/DISABLE acked by
* IOPART
@@ -119,7 +121,6 @@
struct visor_device *dev;
char name[99];
struct list_head list_all; /* < link within list_all_devices list */
- struct kref kref;
struct net_device *netdev;
struct net_device_stats net_stats;
atomic_t interrupt_rcvd;
@@ -137,20 +138,21 @@
atomic_t num_rcvbuf_in_iovm;
unsigned long alloc_failed_in_if_needed_cnt;
unsigned long alloc_failed_in_repost_rtn_cnt;
- int max_outstanding_net_xmits; /* absolute max number of outstanding
- * xmits - should never hit this
- */
- int upper_threshold_net_xmits; /* high water mark for calling
- * netif_stop_queue()
- */
- int lower_threshold_net_xmits; /* high water mark for calling
- * netif_wake_queue()
- */
+ unsigned long max_outstanding_net_xmits; /* absolute max number of
+ * outstanding xmits - should
+ * never hit this
+ */
+ unsigned long upper_threshold_net_xmits; /* high water mark for
+ * calling netif_stop_queue()
+ */
+ unsigned long lower_threshold_net_xmits; /* high water mark for calling
+ * netif_wake_queue()
+ */
struct sk_buff_head xmitbufhead; /* xmitbufhead is the head of the
* xmit buffer list that have been
* sent to the IOPART end
*/
- struct work_struct serverdown_completion;
+ visorbus_state_complete_func server_down_complete_func;
struct work_struct timeout_reset;
struct uiscmdrsp *cmdrsp_rcv; /* cmdrsp_rcv is used for
* posting/unposting rcv buffers
@@ -161,8 +163,8 @@
*/
bool server_down; /* IOPART is down */
bool server_change_state; /* Processing SERVER_CHANGESTATE msg */
+ bool going_away; /* device is being torn down */
struct dentry *eth_debugfs_dir;
- struct visor_thread_info threadinfo;
u64 interrupts_rcvd;
u64 interrupts_notme;
u64 interrupts_disabled;
@@ -194,16 +196,19 @@
int queuefullmsg_logged;
struct chanstat chstat;
+ struct timer_list irq_poll_timer;
+ struct napi_struct napi;
+ struct uiscmdrsp cmdrsp[SIZEOF_CMDRSP];
};
-/* array of open devices maintained by open() and close() */
-static struct net_device *num_visornic_open[VISORNICSOPENMAX];
/* List of all visornic_devdata structs,
* linked via the list_all member
*/
static LIST_HEAD(list_all_devices);
static DEFINE_SPINLOCK(lock_all_devices);
+static int visornic_poll(struct napi_struct *napi, int budget);
+static void poll_for_irq(unsigned long v);
/**
* visor_copy_fragsinfo_from_skb(
@@ -223,9 +228,25 @@
struct phys_info frags[])
{
unsigned int count = 0, ii, size, offset = 0, numfrags;
+ unsigned int total_count;
numfrags = skb_shinfo(skb)->nr_frags;
+ /*
+ * Compute the number of fragments this skb has, and if its more than
+ * frag array can hold, linearize the skb
+ */
+ total_count = numfrags + (firstfraglen / PI_PAGE_SIZE);
+ if (firstfraglen % PI_PAGE_SIZE)
+ total_count++;
+
+ if (total_count > frags_max) {
+ if (skb_linearize(skb))
+ return -EINVAL;
+ numfrags = skb_shinfo(skb)->nr_frags;
+ firstfraglen = 0;
+ }
+
while (firstfraglen) {
if (count == frags_max)
return -EINVAL;
@@ -256,8 +277,16 @@
page_offset,
skb_shinfo(skb)->frags[ii].
size, count, frags_max, frags);
- if (!count)
- return -EIO;
+ /*
+ * add_physinfo_entries only returns
+ * zero if the frags array is out of room
+ * That should never happen because we
+ * fail above, if count+numfrags > frags_max.
+ * Given that theres no recovery mechanism from putting
+ * half a packet in the I/O channel, panic here as this
+ * should never happen
+ */
+ BUG_ON(!count);
}
}
if (skb_shinfo(skb)->frag_list) {
@@ -279,222 +308,15 @@
return count;
}
-/**
- * visort_thread_start - starts thread for the device
- * @thrinfo: The thread to start
- * @threadfn: Function the thread starts
- * @thrcontext: Context to pass to the thread, i.e. devdata
- * @name: string describing name of thread
- *
- * Starts a thread for the device, currently only thread is
- * process_incoming_rsps
- * Returns 0 on success;
- */
-static int visor_thread_start(struct visor_thread_info *thrinfo,
- int (*threadfn)(void *),
- void *thrcontext, char *name)
-{
- /* used to stop the thread */
- init_completion(&thrinfo->has_stopped);
- thrinfo->task = kthread_run(threadfn, thrcontext, name);
- if (IS_ERR(thrinfo->task)) {
- thrinfo->id = 0;
- return -EINVAL;
- }
- thrinfo->id = thrinfo->task->pid;
- return 0;
-}
-
-/**
- * visor_thread_stop - stop a thread for the device
- * @thrinfo: The thread to stop
- *
- * Stop the thread and wait for completion for a minute
- * Returns void.
- */
-static void visor_thread_stop(struct visor_thread_info *thrinfo)
-{
- if (!thrinfo->id)
- return; /* thread not running */
-
- kthread_stop(thrinfo->task);
- /* give up if the thread has NOT died in 1 minute */
- if (wait_for_completion_timeout(&thrinfo->has_stopped, 60 * HZ))
- thrinfo->id = 0;
-}
-
-/* DebugFS code */
-static ssize_t info_debugfs_read(struct file *file, char __user *buf,
- size_t len, loff_t *offset)
-{
- int i;
- ssize_t bytes_read = 0;
- int str_pos = 0;
- struct visornic_devdata *devdata;
- char *vbuf;
-
- if (len > MAX_BUF)
- len = MAX_BUF;
- vbuf = kzalloc(len, GFP_KERNEL);
- if (!vbuf)
- return -ENOMEM;
-
- /* for each vnic channel
- * dump out channel specific data
- */
- for (i = 0; i < VISORNICSOPENMAX; i++) {
- if (!num_visornic_open[i])
- continue;
-
- devdata = netdev_priv(num_visornic_open[i]);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- "Vnic i = %d\n", i);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- "netdev = %s (0x%p), MAC Addr %pM\n",
- num_visornic_open[i]->name,
- num_visornic_open[i],
- num_visornic_open[i]->dev_addr);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- "VisorNic Dev Info = 0x%p\n", devdata);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " num_rcv_bufs = %d\n",
- devdata->num_rcv_bufs);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " max_oustanding_next_xmits = %d\n",
- devdata->max_outstanding_net_xmits);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " upper_threshold_net_xmits = %d\n",
- devdata->upper_threshold_net_xmits);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " lower_threshold_net_xmits = %d\n",
- devdata->lower_threshold_net_xmits);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " queuefullmsg_logged = %d\n",
- devdata->queuefullmsg_logged);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.got_rcv = %lu\n",
- devdata->chstat.got_rcv);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.got_enbdisack = %lu\n",
- devdata->chstat.got_enbdisack);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.got_xmit_done = %lu\n",
- devdata->chstat.got_xmit_done);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.xmit_fail = %lu\n",
- devdata->chstat.xmit_fail);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.sent_enbdis = %lu\n",
- devdata->chstat.sent_enbdis);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.sent_promisc = %lu\n",
- devdata->chstat.sent_promisc);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.sent_post = %lu\n",
- devdata->chstat.sent_post);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.sent_xmit = %lu\n",
- devdata->chstat.sent_xmit);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.reject_count = %lu\n",
- devdata->chstat.reject_count);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " chstat.extra_rcvbufs_sent = %lu\n",
- devdata->chstat.extra_rcvbufs_sent);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " n_rcv0 = %lu\n", devdata->n_rcv0);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " n_rcv1 = %lu\n", devdata->n_rcv1);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " n_rcv2 = %lu\n", devdata->n_rcv2);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " n_rcvx = %lu\n", devdata->n_rcvx);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " num_rcvbuf_in_iovm = %d\n",
- atomic_read(&devdata->num_rcvbuf_in_iovm));
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " alloc_failed_in_if_needed_cnt = %lu\n",
- devdata->alloc_failed_in_if_needed_cnt);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " alloc_failed_in_repost_rtn_cnt = %lu\n",
- devdata->alloc_failed_in_repost_rtn_cnt);
- /* str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- * " inner_loop_limit_reached_cnt = %lu\n",
- * devdata->inner_loop_limit_reached_cnt);
- */
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " found_repost_rcvbuf_cnt = %lu\n",
- devdata->found_repost_rcvbuf_cnt);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " repost_found_skb_cnt = %lu\n",
- devdata->repost_found_skb_cnt);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " n_repost_deficit = %lu\n",
- devdata->n_repost_deficit);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " bad_rcv_buf = %lu\n",
- devdata->bad_rcv_buf);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " n_rcv_packets_not_accepted = %lu\n",
- devdata->n_rcv_packets_not_accepted);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " interrupts_rcvd = %llu\n",
- devdata->interrupts_rcvd);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " interrupts_notme = %llu\n",
- devdata->interrupts_notme);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " interrupts_disabled = %llu\n",
- devdata->interrupts_disabled);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " busy_cnt = %llu\n",
- devdata->busy_cnt);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " flow_control_upper_hits = %llu\n",
- devdata->flow_control_upper_hits);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " flow_control_lower_hits = %llu\n",
- devdata->flow_control_lower_hits);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " thread_wait_ms = %d\n",
- devdata->thread_wait_ms);
- str_pos += scnprintf(vbuf + str_pos, len - str_pos,
- " netif_queue = %s\n",
- netif_queue_stopped(devdata->netdev) ?
- "stopped" : "running");
- }
- bytes_read = simple_read_from_buffer(buf, len, offset, vbuf, str_pos);
- kfree(vbuf);
- return bytes_read;
-}
-
static ssize_t enable_ints_write(struct file *file,
const char __user *buffer,
size_t count, loff_t *ppos)
{
- char buf[4];
- int i, new_value;
- struct visornic_devdata *devdata;
-
- if (count >= ARRAY_SIZE(buf))
- return -EINVAL;
-
- buf[count] = '\0';
- if (copy_from_user(buf, buffer, count))
- return -EFAULT;
-
- i = kstrtoint(buf, 10, &new_value);
- if (i != 0)
- return -EFAULT;
-
- /* set all counts to new_value usually 0 */
- for (i = 0; i < VISORNICSOPENMAX; i++) {
- if (num_visornic_open[i]) {
- devdata = netdev_priv(num_visornic_open[i]);
- /* TODO update features bit in channel */
- }
- }
-
+ /*
+ * Don't want to break ABI here by having a debugfs
+ * file that no longer exists or is writable, so
+ * lets just make this a vestigual function
+ */
return count;
}
@@ -509,44 +331,29 @@
* Returns void.
*/
static void
-visornic_serverdown_complete(struct work_struct *work)
+visornic_serverdown_complete(struct visornic_devdata *devdata)
{
- struct visornic_devdata *devdata;
struct net_device *netdev;
- unsigned long flags;
- int i = 0, count = 0;
- devdata = container_of(work, struct visornic_devdata,
- serverdown_completion);
netdev = devdata->netdev;
- /* Stop using datachan */
- visor_thread_stop(&devdata->threadinfo);
+ /* Stop polling for interrupts */
+ del_timer_sync(&devdata->irq_poll_timer);
- /* Inform Linux that the link is down */
- netif_carrier_off(netdev);
- netif_stop_queue(netdev);
+ rtnl_lock();
+ dev_close(netdev);
+ rtnl_unlock();
- /* Free the skb for XMITs that haven't been serviced by the server
- * We shouldn't have to inform Linux about these IOs because they
- * are "lost in the ethernet"
- */
- skb_queue_purge(&devdata->xmitbufhead);
-
- spin_lock_irqsave(&devdata->priv_lock, flags);
- /* free rcv buffers */
- for (i = 0; i < devdata->num_rcv_bufs; i++) {
- if (devdata->rcvbuf[i]) {
- kfree_skb(devdata->rcvbuf[i]);
- devdata->rcvbuf[i] = NULL;
- count++;
- }
- }
atomic_set(&devdata->num_rcvbuf_in_iovm, 0);
- spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ devdata->chstat.sent_xmit = 0;
+ devdata->chstat.got_xmit_done = 0;
+
+ if (devdata->server_down_complete_func)
+ (*devdata->server_down_complete_func)(devdata->dev, 0);
devdata->server_down = true;
devdata->server_change_state = false;
+ devdata->server_down_complete_func = NULL;
}
/**
@@ -558,15 +365,31 @@
* Returns 0 if we scheduled the work, -EINVAL on error.
*/
static int
-visornic_serverdown(struct visornic_devdata *devdata)
+visornic_serverdown(struct visornic_devdata *devdata,
+ visorbus_state_complete_func complete_func)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&devdata->priv_lock, flags);
if (!devdata->server_down && !devdata->server_change_state) {
+ if (devdata->going_away) {
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ dev_dbg(&devdata->dev->device,
+ "%s aborting because device removal pending\n",
+ __func__);
+ return -ENODEV;
+ }
devdata->server_change_state = true;
- queue_work(visornic_serverdown_workqueue,
- &devdata->serverdown_completion);
+ devdata->server_down_complete_func = complete_func;
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ visornic_serverdown_complete(devdata);
} else if (devdata->server_change_state) {
+ dev_dbg(&devdata->dev->device, "%s changing state\n",
+ __func__);
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
return -EINVAL;
- }
+ } else
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
return 0;
}
@@ -625,11 +448,14 @@
if ((cmdrsp->net.rcvpost.frag.pi_off + skb->len) <= PI_PAGE_SIZE) {
cmdrsp->net.type = NET_RCV_POST;
cmdrsp->cmdtype = CMD_NET_TYPE;
- visorchannel_signalinsert(devdata->dev->visorchannel,
+ if (visorchannel_signalinsert(devdata->dev->visorchannel,
IOCHAN_TO_IOPART,
- cmdrsp);
- atomic_inc(&devdata->num_rcvbuf_in_iovm);
- devdata->chstat.sent_post++;
+ cmdrsp)) {
+ atomic_inc(&devdata->num_rcvbuf_in_iovm);
+ devdata->chstat.sent_post++;
+ } else {
+ devdata->chstat.sent_post_failed++;
+ }
}
}
@@ -651,10 +477,10 @@
devdata->cmdrsp_rcv->net.enbdis.context = netdev;
devdata->cmdrsp_rcv->net.type = NET_RCV_ENBDIS;
devdata->cmdrsp_rcv->cmdtype = CMD_NET_TYPE;
- visorchannel_signalinsert(devdata->dev->visorchannel,
+ if (visorchannel_signalinsert(devdata->dev->visorchannel,
IOCHAN_TO_IOPART,
- devdata->cmdrsp_rcv);
- devdata->chstat.sent_enbdis++;
+ devdata->cmdrsp_rcv))
+ devdata->chstat.sent_enbdis++;
}
/**
@@ -676,9 +502,6 @@
unsigned long flags;
int wait = 0;
- /* stop the transmit queue so nothing more can be transmitted */
- netif_stop_queue(netdev);
-
/* send a msg telling the other end we are stopping incoming pkts */
spin_lock_irqsave(&devdata->priv_lock, flags);
devdata->enabled = 0;
@@ -695,12 +518,14 @@
* when it gets a disable.
*/
spin_lock_irqsave(&devdata->priv_lock, flags);
- while ((timeout == VISORNIC_INFINITE_RESPONSE_WAIT) ||
+ while ((timeout == VISORNIC_INFINITE_RSP_WAIT) ||
(wait < timeout)) {
if (devdata->enab_dis_acked)
break;
if (devdata->server_down || devdata->server_change_state) {
spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ dev_dbg(&netdev->dev, "%s server went away\n",
+ __func__);
return -EIO;
}
set_current_state(TASK_INTERRUPTIBLE);
@@ -722,10 +547,16 @@
break;
}
}
-
/* we've set enabled to 0, so we can give up the lock. */
spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ /* stop the transmit queue so nothing more can be transmitted */
+ netif_stop_queue(netdev);
+
+ napi_disable(&devdata->napi);
+
+ skb_queue_purge(&devdata->xmitbufhead);
+
/* Free rcv buffers - other end has automatically unposed them on
* disable
*/
@@ -736,13 +567,6 @@
}
}
- /* remove references from array */
- for (i = 0; i < VISORNICSOPENMAX; i++)
- if (num_visornic_open[i] == netdev) {
- num_visornic_open[i] = NULL;
- break;
- }
-
return 0;
}
@@ -814,11 +638,15 @@
* gets a disable.
*/
i = init_rcv_bufs(netdev, devdata);
- if (i < 0)
+ if (i < 0) {
+ dev_err(&netdev->dev,
+ "%s failed to init rcv bufs (%d)\n", __func__, i);
return i;
+ }
spin_lock_irqsave(&devdata->priv_lock, flags);
devdata->enabled = 1;
+ devdata->enab_dis_acked = 0;
/* now we're ready, let's send an ENB to uisnic but until we get
* an ACK back from uisnic, we'll drop the packets
@@ -829,15 +657,18 @@
/* send enable and wait for ack -- don't hold lock when sending enable
* because if the queue is full, insert might sleep.
*/
+ napi_enable(&devdata->napi);
send_enbdis(netdev, 1, devdata);
spin_lock_irqsave(&devdata->priv_lock, flags);
- while ((timeout == VISORNIC_INFINITE_RESPONSE_WAIT) ||
+ while ((timeout == VISORNIC_INFINITE_RSP_WAIT) ||
(wait < timeout)) {
if (devdata->enab_dis_acked)
break;
if (devdata->server_down || devdata->server_change_state) {
spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ dev_dbg(&netdev->dev, "%s server went away\n",
+ __func__);
return -EIO;
}
set_current_state(TASK_INTERRUPTIBLE);
@@ -848,19 +679,13 @@
spin_unlock_irqrestore(&devdata->priv_lock, flags);
- if (!devdata->enab_dis_acked)
+ if (!devdata->enab_dis_acked) {
+ dev_err(&netdev->dev, "%s missing ACK\n", __func__);
return -EIO;
-
- /* find an open slot in the array to save off VisorNic references
- * for debug
- */
- for (i = 0; i < VISORNICSOPENMAX; i++) {
- if (!num_visornic_open[i]) {
- num_visornic_open[i] = netdev;
- break;
- }
}
+ netif_start_queue(netdev);
+
return 0;
}
@@ -882,20 +707,29 @@
devdata = container_of(work, struct visornic_devdata, timeout_reset);
netdev = devdata->netdev;
- netif_stop_queue(netdev);
- response = visornic_disable_with_timeout(netdev, 100);
+ rtnl_lock();
+ if (!netif_running(netdev)) {
+ rtnl_unlock();
+ return;
+ }
+
+ response = visornic_disable_with_timeout(netdev,
+ VISORNIC_INFINITE_RSP_WAIT);
if (response)
goto call_serverdown;
- response = visornic_enable_with_timeout(netdev, 100);
+ response = visornic_enable_with_timeout(netdev,
+ VISORNIC_INFINITE_RSP_WAIT);
if (response)
goto call_serverdown;
- netif_wake_queue(netdev);
+
+ rtnl_unlock();
return;
call_serverdown:
- visornic_serverdown(devdata);
+ visornic_serverdown(devdata, NULL);
+ rtnl_unlock();
}
/**
@@ -908,12 +742,7 @@
static int
visornic_open(struct net_device *netdev)
{
- visornic_enable_with_timeout(netdev, VISORNIC_INFINITE_RESPONSE_WAIT);
-
- /* start the interface's transmit queue, allowing it to accept
- * packets for transmission
- */
- netif_start_queue(netdev);
+ visornic_enable_with_timeout(netdev, VISORNIC_INFINITE_RSP_WAIT);
return 0;
}
@@ -928,13 +757,59 @@
static int
visornic_close(struct net_device *netdev)
{
- netif_stop_queue(netdev);
- visornic_disable_with_timeout(netdev, VISORNIC_INFINITE_RESPONSE_WAIT);
+ visornic_disable_with_timeout(netdev, VISORNIC_INFINITE_RSP_WAIT);
return 0;
}
/**
+ * devdata_xmits_outstanding - compute outstanding xmits
+ * @devdata: visornic_devdata for device
+ *
+ * Return value is the number of outstanding xmits.
+ */
+static unsigned long devdata_xmits_outstanding(struct visornic_devdata *devdata)
+{
+ if (devdata->chstat.sent_xmit >= devdata->chstat.got_xmit_done)
+ return devdata->chstat.sent_xmit -
+ devdata->chstat.got_xmit_done;
+ else
+ return (ULONG_MAX - devdata->chstat.got_xmit_done
+ + devdata->chstat.sent_xmit + 1);
+}
+
+/**
+ * vnic_hit_high_watermark
+ * @devdata: indicates visornic device we are checking
+ * @high_watermark: max num of unacked xmits we will tolerate,
+ * before we will start throttling
+ *
+ * Returns true iff the number of unacked xmits sent to
+ * the IO partition is >= high_watermark.
+ */
+static inline bool vnic_hit_high_watermark(struct visornic_devdata *devdata,
+ ulong high_watermark)
+{
+ return (devdata_xmits_outstanding(devdata) >= high_watermark);
+}
+
+/**
+ * vnic_hit_low_watermark
+ * @devdata: indicates visornic device we are checking
+ * @low_watermark: we will wait until the num of unacked xmits
+ * drops to this value or lower before we start
+ * transmitting again
+ *
+ * Returns true iff the number of unacked xmits sent to
+ * the IO partition is <= low_watermark.
+ */
+static inline bool vnic_hit_low_watermark(struct visornic_devdata *devdata,
+ ulong low_watermark)
+{
+ return (devdata_xmits_outstanding(devdata) <= low_watermark);
+}
+
+/**
* visornic_xmit - send a packet to the IO Partition
* @skb: Packet to be sent
* @netdev: net device the packet is being sent from
@@ -944,7 +819,7 @@
* function is protected from concurrent calls by a spinlock xmit_lock
* in the net_device struct, but as soon as the function returns it
* can be called again.
- * Returns NETDEV_TX_OK for success, NETDEV_TX_BUSY for error.
+ * Returns NETDEV_TX_OK.
*/
static int
visornic_xmit(struct sk_buff *skb, struct net_device *netdev)
@@ -961,7 +836,10 @@
devdata->server_change_state) {
spin_unlock_irqrestore(&devdata->priv_lock, flags);
devdata->busy_cnt++;
- return NETDEV_TX_BUSY;
+ dev_dbg(&netdev->dev,
+ "%s busy - queue stopped\n", __func__);
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
}
/* sk_buff struct is used to host network data throughout all the
@@ -979,7 +857,11 @@
if (firstfraglen < ETH_HEADER_SIZE) {
spin_unlock_irqrestore(&devdata->priv_lock, flags);
devdata->busy_cnt++;
- return NETDEV_TX_BUSY;
+ dev_err(&netdev->dev,
+ "%s busy - first frag too small (%d)\n",
+ __func__, firstfraglen);
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
}
if ((len < ETH_MIN_PACKET_SIZE) &&
@@ -1002,13 +884,8 @@
/* save the pointer to skb -- we'll need it for completion */
cmdrsp->net.buf = skb;
- if (((devdata->chstat.sent_xmit >= devdata->chstat.got_xmit_done) &&
- (devdata->chstat.sent_xmit - devdata->chstat.got_xmit_done >=
- devdata->max_outstanding_net_xmits)) ||
- ((devdata->chstat.sent_xmit < devdata->chstat.got_xmit_done) &&
- (ULONG_MAX - devdata->chstat.got_xmit_done +
- devdata->chstat.sent_xmit >=
- devdata->max_outstanding_net_xmits))) {
+ if (vnic_hit_high_watermark(devdata,
+ devdata->max_outstanding_net_xmits)) {
/* too many NET_XMITs queued over to IOVM - need to wait
*/
devdata->chstat.reject_count++;
@@ -1018,7 +895,11 @@
netif_stop_queue(netdev);
spin_unlock_irqrestore(&devdata->priv_lock, flags);
devdata->busy_cnt++;
- return NETDEV_TX_BUSY;
+ dev_dbg(&netdev->dev,
+ "%s busy - waiting for iovm to catch up\n",
+ __func__);
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
}
if (devdata->queuefullmsg_logged)
devdata->queuefullmsg_logged = 0;
@@ -1055,10 +936,13 @@
visor_copy_fragsinfo_from_skb(skb, firstfraglen,
MAX_PHYS_INFO,
cmdrsp->net.xmt.frags);
- if (cmdrsp->net.xmt.num_frags == -1) {
+ if (cmdrsp->net.xmt.num_frags < 0) {
spin_unlock_irqrestore(&devdata->priv_lock, flags);
devdata->busy_cnt++;
- return NETDEV_TX_BUSY;
+ dev_err(&netdev->dev,
+ "%s busy - copy frags failed\n", __func__);
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
}
if (!visorchannel_signalinsert(devdata->dev->visorchannel,
@@ -1066,18 +950,15 @@
netif_stop_queue(netdev);
spin_unlock_irqrestore(&devdata->priv_lock, flags);
devdata->busy_cnt++;
- return NETDEV_TX_BUSY;
+ dev_dbg(&netdev->dev,
+ "%s busy - signalinsert failed\n", __func__);
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
}
/* Track the skbs that have been sent to the IOVM for XMIT */
skb_queue_head(&devdata->xmitbufhead, skb);
- /* set the last transmission start time
- * linux doc says: Do not forget to update netdev->trans_start to
- * jiffies after each new tx packet is given to the hardware.
- */
- netdev->trans_start = jiffies;
-
/* update xmt stats */
devdata->net_stats.tx_packets++;
devdata->net_stats.tx_bytes += skb->len;
@@ -1086,18 +967,16 @@
/* check to see if we have hit the high watermark for
* netif_stop_queue()
*/
- if (((devdata->chstat.sent_xmit >= devdata->chstat.got_xmit_done) &&
- (devdata->chstat.sent_xmit - devdata->chstat.got_xmit_done >=
- devdata->upper_threshold_net_xmits)) ||
- ((devdata->chstat.sent_xmit < devdata->chstat.got_xmit_done) &&
- (ULONG_MAX - devdata->chstat.got_xmit_done +
- devdata->chstat.sent_xmit >=
- devdata->upper_threshold_net_xmits))) {
+ if (vnic_hit_high_watermark(devdata,
+ devdata->upper_threshold_net_xmits)) {
/* too many NET_XMITs queued over to IOVM - need to wait */
netif_stop_queue(netdev); /* calling stop queue - call
* netif_wake_queue() after lower
* threshold
*/
+ dev_dbg(&netdev->dev,
+ "%s busy - invoking iovm flow control\n",
+ __func__);
devdata->flow_control_upper_hits++;
}
spin_unlock_irqrestore(&devdata->priv_lock, flags);
@@ -1121,21 +1000,6 @@
}
/**
- * visornic_ioctl - ioctl function for netdevice.
- * @netdev: netdevice
- * @ifr: ignored
- * @cmd: ignored
- *
- * Currently not supported.
- * Returns EOPNOTSUPP
- */
-static int
-visornic_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
-{
- return -EOPNOTSUPP;
-}
-
-/**
* visornic_change_mtu - changes mtu of device.
* @netdev: netdevice
* @new_mtu: value of new mtu
@@ -1201,15 +1065,24 @@
unsigned long flags;
spin_lock_irqsave(&devdata->priv_lock, flags);
+ if (devdata->going_away) {
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ dev_dbg(&devdata->dev->device,
+ "%s aborting because device removal pending\n",
+ __func__);
+ return;
+ }
+
/* Ensure that a ServerDown message hasn't been received */
if (!devdata->enabled ||
(devdata->server_down && !devdata->server_change_state)) {
+ dev_dbg(&netdev->dev, "%s no processing\n",
+ __func__);
spin_unlock_irqrestore(&devdata->priv_lock, flags);
return;
}
- spin_unlock_irqrestore(&devdata->priv_lock, flags);
-
queue_work(visornic_timeout_reset_workqueue, &devdata->timeout_reset);
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
}
/**
@@ -1281,7 +1154,6 @@
devdata->bad_rcv_buf++;
}
}
- atomic_dec(&devdata->usage);
return status;
}
@@ -1293,18 +1165,16 @@
* it up the stack.
* Returns void
*/
-static void
+static int
visornic_rx(struct uiscmdrsp *cmdrsp)
{
struct visornic_devdata *devdata;
struct sk_buff *skb, *prev, *curr;
struct net_device *netdev;
- int cc, currsize, off, status;
+ int cc, currsize, off;
struct ethhdr *eth;
unsigned long flags;
-#ifdef DEBUG
- struct phys_info testfrags[MAX_PHYS_INFO];
-#endif
+ int rx_count = 0;
/* post new rcv buf to the other end using the cmdrsp we have at hand
* post it without holding lock - but we'll use the signal lock to
@@ -1314,18 +1184,6 @@
skb = cmdrsp->net.buf;
netdev = skb->dev;
- if (!netdev) {
- /* We must have previously downed this network device and
- * this skb and device is no longer valid. This also means
- * the skb reference was removed from devdata->rcvbuf so no
- * need to search for it.
- * All we can do is free the skb and return.
- * Note: We crash if we try to log this here.
- */
- kfree_skb(skb);
- return;
- }
-
devdata = netdev_priv(netdev);
spin_lock_irqsave(&devdata->priv_lock, flags);
@@ -1335,10 +1193,6 @@
devdata->net_stats.rx_packets++;
devdata->net_stats.rx_bytes = skb->len;
- atomic_inc(&devdata->usage); /* don't want a close to happen before
- * we're done here
- */
-
/* set length to how much was ACTUALLY received -
* NOTE: rcv_done_len includes actual length of data rcvd
* including ethhdr
@@ -1352,7 +1206,7 @@
*/
spin_unlock_irqrestore(&devdata->priv_lock, flags);
repost_return(cmdrsp, devdata, skb, netdev);
- return;
+ return rx_count;
}
spin_unlock_irqrestore(&devdata->priv_lock, flags);
@@ -1371,7 +1225,7 @@
if (repost_return(cmdrsp, devdata, skb, netdev) < 0)
dev_err(&devdata->netdev->dev,
"repost_return failed");
- return;
+ return rx_count;
}
/* length rcvd is greater than firstfrag in this skb rcv buf */
skb->tail += RCVPOST_BUF_SIZE; /* amount in skb->data */
@@ -1386,7 +1240,7 @@
if (repost_return(cmdrsp, devdata, skb, netdev) < 0)
dev_err(&devdata->netdev->dev,
"repost_return failed");
- return;
+ return rx_count;
}
skb->tail += skb->len;
skb->data_len = 0; /* nothing rcvd in frag_list */
@@ -1405,7 +1259,7 @@
if (cmdrsp->net.rcv.rcvbuf[0] != skb) {
if (repost_return(cmdrsp, devdata, skb, netdev) < 0)
dev_err(&devdata->netdev->dev, "repost_return failed");
- return;
+ return rx_count;
}
if (cmdrsp->net.rcv.numrcvbufs > 1) {
@@ -1431,29 +1285,12 @@
curr->data_len = 0;
off += currsize;
}
-#ifdef DEBUG
/* assert skb->len == off */
if (skb->len != off) {
- dev_err(&devdata->netdev->dev,
- "%s something wrong; skb->len:%d != off:%d\n",
- netdev->name, skb->len, off);
+ netdev_err(devdata->netdev,
+ "something wrong; skb->len:%d != off:%d\n",
+ skb->len, off);
}
- /* test code */
- cc = util_copy_fragsinfo_from_skb("rcvchaintest", skb,
- RCVPOST_BUF_SIZE,
- MAX_PHYS_INFO, testfrags);
- if (cc != cmdrsp->net.rcv.numrcvbufs) {
- dev_err(&devdata->netdev->dev,
- "**** %s Something wrong; rcvd chain length %d different from one we calculated %d\n",
- netdev->name, cmdrsp->net.rcv.numrcvbufs, cc);
- }
- for (i = 0; i < cc; i++) {
- dev_inf(&devdata->netdev->dev,
- "test:RCVPOST_BUF_SIZE:%d[%d] pfn:%llu off:0x%x len:%d\n",
- RCVPOST_BUF_SIZE, i, testfrags[i].pi_pfn,
- testfrags[i].pi_off, testfrags[i].pi_len);
- }
-#endif
}
/* set up packet's protocl type using ethernet header - this
@@ -1505,10 +1342,11 @@
/* drop packet - don't forward it up to OS */
devdata->n_rcv_packets_not_accepted++;
repost_return(cmdrsp, devdata, skb, netdev);
- return;
+ return rx_count;
} while (0);
- status = netif_rx(skb);
+ rx_count++;
+ netif_receive_skb(skb);
/* netif_rx returns various values, but "in practice most drivers
* ignore the return value
*/
@@ -1520,6 +1358,7 @@
* new rcv buffer.
*/
repost_return(cmdrsp, devdata, skb, netdev);
+ return rx_count;
}
/**
@@ -1545,14 +1384,11 @@
spin_unlock(&dev_num_pool_lock);
if (devnum == MAXDEVICES)
devnum = -1;
- if (devnum < 0) {
- kfree(devdata);
+ if (devnum < 0)
return NULL;
- }
devdata->devnum = devnum;
devdata->dev = dev;
strncpy(devdata->name, dev_name(&dev->device), sizeof(devdata->name));
- kref_init(&devdata->kref);
spin_lock(&lock_all_devices);
list_add_tail(&devdata->list_all, &list_all_devices);
spin_unlock(&lock_all_devices);
@@ -1560,24 +1396,23 @@
}
/**
- * devdata_release - Frees up a devdata
- * @mykref: kref to the devdata
+ * devdata_release - Frees up references in devdata
+ * @devdata: struct to clean up
*
- * Frees up a devdata.
+ * Frees up references in devdata.
* Returns void
*/
-static void devdata_release(struct kref *mykref)
+static void devdata_release(struct visornic_devdata *devdata)
{
- struct visornic_devdata *devdata =
- container_of(mykref, struct visornic_devdata, kref);
-
spin_lock(&dev_num_pool_lock);
clear_bit(devdata->devnum, dev_num_pool);
spin_unlock(&dev_num_pool_lock);
spin_lock(&lock_all_devices);
list_del(&devdata->list_all);
spin_unlock(&lock_all_devices);
- kfree(devdata);
+ kfree(devdata->rcvbuf);
+ kfree(devdata->cmdrsp_rcv);
+ kfree(devdata->xmit_cmdrsp);
}
static const struct net_device_ops visornic_dev_ops = {
@@ -1585,12 +1420,163 @@
.ndo_stop = visornic_close,
.ndo_start_xmit = visornic_xmit,
.ndo_get_stats = visornic_get_stats,
- .ndo_do_ioctl = visornic_ioctl,
.ndo_change_mtu = visornic_change_mtu,
.ndo_tx_timeout = visornic_xmit_timeout,
.ndo_set_rx_mode = visornic_set_multi,
};
+/* DebugFS code */
+static ssize_t info_debugfs_read(struct file *file, char __user *buf,
+ size_t len, loff_t *offset)
+{
+ ssize_t bytes_read = 0;
+ int str_pos = 0;
+ struct visornic_devdata *devdata;
+ struct net_device *dev;
+ char *vbuf;
+
+ if (len > MAX_BUF)
+ len = MAX_BUF;
+ vbuf = kzalloc(len, GFP_KERNEL);
+ if (!vbuf)
+ return -ENOMEM;
+
+ /* for each vnic channel
+ * dump out channel specific data
+ */
+ rcu_read_lock();
+ for_each_netdev_rcu(current->nsproxy->net_ns, dev) {
+ /*
+ * Only consider netdevs that are visornic, and are open
+ */
+ if ((dev->netdev_ops != &visornic_dev_ops) ||
+ (!netif_queue_stopped(dev)))
+ continue;
+
+ devdata = netdev_priv(dev);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ "netdev = %s (0x%p), MAC Addr %pM\n",
+ dev->name,
+ dev,
+ dev->dev_addr);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ "VisorNic Dev Info = 0x%p\n", devdata);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " num_rcv_bufs = %d\n",
+ devdata->num_rcv_bufs);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " max_oustanding_next_xmits = %lu\n",
+ devdata->max_outstanding_net_xmits);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " upper_threshold_net_xmits = %lu\n",
+ devdata->upper_threshold_net_xmits);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " lower_threshold_net_xmits = %lu\n",
+ devdata->lower_threshold_net_xmits);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " queuefullmsg_logged = %d\n",
+ devdata->queuefullmsg_logged);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.got_rcv = %lu\n",
+ devdata->chstat.got_rcv);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.got_enbdisack = %lu\n",
+ devdata->chstat.got_enbdisack);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.got_xmit_done = %lu\n",
+ devdata->chstat.got_xmit_done);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.xmit_fail = %lu\n",
+ devdata->chstat.xmit_fail);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.sent_enbdis = %lu\n",
+ devdata->chstat.sent_enbdis);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.sent_promisc = %lu\n",
+ devdata->chstat.sent_promisc);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.sent_post = %lu\n",
+ devdata->chstat.sent_post);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.sent_post_failed = %lu\n",
+ devdata->chstat.sent_post_failed);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.sent_xmit = %lu\n",
+ devdata->chstat.sent_xmit);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.reject_count = %lu\n",
+ devdata->chstat.reject_count);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " chstat.extra_rcvbufs_sent = %lu\n",
+ devdata->chstat.extra_rcvbufs_sent);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " n_rcv0 = %lu\n", devdata->n_rcv0);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " n_rcv1 = %lu\n", devdata->n_rcv1);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " n_rcv2 = %lu\n", devdata->n_rcv2);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " n_rcvx = %lu\n", devdata->n_rcvx);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " num_rcvbuf_in_iovm = %d\n",
+ atomic_read(&devdata->num_rcvbuf_in_iovm));
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " alloc_failed_in_if_needed_cnt = %lu\n",
+ devdata->alloc_failed_in_if_needed_cnt);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " alloc_failed_in_repost_rtn_cnt = %lu\n",
+ devdata->alloc_failed_in_repost_rtn_cnt);
+ /* str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ * " inner_loop_limit_reached_cnt = %lu\n",
+ * devdata->inner_loop_limit_reached_cnt);
+ */
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " found_repost_rcvbuf_cnt = %lu\n",
+ devdata->found_repost_rcvbuf_cnt);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " repost_found_skb_cnt = %lu\n",
+ devdata->repost_found_skb_cnt);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " n_repost_deficit = %lu\n",
+ devdata->n_repost_deficit);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " bad_rcv_buf = %lu\n",
+ devdata->bad_rcv_buf);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " n_rcv_packets_not_accepted = %lu\n",
+ devdata->n_rcv_packets_not_accepted);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " interrupts_rcvd = %llu\n",
+ devdata->interrupts_rcvd);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " interrupts_notme = %llu\n",
+ devdata->interrupts_notme);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " interrupts_disabled = %llu\n",
+ devdata->interrupts_disabled);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " busy_cnt = %llu\n",
+ devdata->busy_cnt);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " flow_control_upper_hits = %llu\n",
+ devdata->flow_control_upper_hits);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " flow_control_lower_hits = %llu\n",
+ devdata->flow_control_lower_hits);
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " netif_queue = %s\n",
+ netif_queue_stopped(devdata->netdev) ?
+ "stopped" : "running");
+ str_pos += scnprintf(vbuf + str_pos, len - str_pos,
+ " xmits_outstanding = %lu\n",
+ devdata_xmits_outstanding(devdata));
+ }
+ rcu_read_unlock();
+ bytes_read = simple_read_from_buffer(buf, len, offset, vbuf, str_pos);
+ kfree(vbuf);
+ return bytes_read;
+}
+
/**
* send_rcv_posts_if_needed
* @devdata: visornic device
@@ -1644,15 +1630,15 @@
* Returns when response queue is empty or when the threadd stops.
*/
static void
-drain_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata)
+service_resp_queue(struct uiscmdrsp *cmdrsp, struct visornic_devdata *devdata,
+ int *rx_work_done)
{
unsigned long flags;
struct net_device *netdev;
- /* drain queue */
- while (1) {
- /* TODO: CLIENT ACQUIRE -- Don't really need this at the
- * moment */
+ /* TODO: CLIENT ACQUIRE -- Don't really need this at the
+ * moment */
+ for (;;) {
if (!visorchannel_signalremove(devdata->dev->visorchannel,
IOCHAN_FROM_IOPART,
cmdrsp))
@@ -1662,7 +1648,7 @@
case NET_RCV:
devdata->chstat.got_rcv++;
/* process incoming packet */
- visornic_rx(cmdrsp);
+ *rx_work_done += visornic_rx(cmdrsp);
break;
case NET_XMIT_DONE:
spin_lock_irqsave(&devdata->priv_lock, flags);
@@ -1678,16 +1664,8 @@
* the lower watermark for
* netif_wake_queue()
*/
- if (((devdata->chstat.sent_xmit >=
- devdata->chstat.got_xmit_done) &&
- (devdata->chstat.sent_xmit -
- devdata->chstat.got_xmit_done <=
- devdata->lower_threshold_net_xmits)) ||
- ((devdata->chstat.sent_xmit <
- devdata->chstat.got_xmit_done) &&
- (ULONG_MAX - devdata->chstat.got_xmit_done
- + devdata->chstat.sent_xmit <=
- devdata->lower_threshold_net_xmits))) {
+ if (vnic_hit_low_watermark(devdata,
+ devdata->lower_threshold_net_xmits)) {
/* enough NET_XMITs completed
* so can restart netif queue
*/
@@ -1738,50 +1716,51 @@
break;
}
/* cmdrsp is now available for reuse */
-
- if (kthread_should_stop())
- break;
}
}
+static int visornic_poll(struct napi_struct *napi, int budget)
+{
+ struct visornic_devdata *devdata = container_of(napi,
+ struct visornic_devdata,
+ napi);
+ int rx_count = 0;
+
+ send_rcv_posts_if_needed(devdata);
+ service_resp_queue(devdata->cmdrsp, devdata, &rx_count);
+
+ /*
+ * If there aren't any more packets to receive
+ * stop the poll
+ */
+ if (rx_count < budget)
+ napi_complete(napi);
+
+ return rx_count;
+}
+
/**
- * process_incoming_rsps - Checks the status of the response queue.
+ * poll_for_irq - Checks the status of the response queue.
* @v: void pointer to the visronic devdata
*
* Main function of the vnic_incoming thread. Peridocially check the
* response queue and drain it if needed.
* Returns when thread has stopped.
*/
-static int
-process_incoming_rsps(void *v)
+static void
+poll_for_irq(unsigned long v)
{
- struct visornic_devdata *devdata = v;
- struct uiscmdrsp *cmdrsp = NULL;
- const int SZ = SIZEOF_CMDRSP;
+ struct visornic_devdata *devdata = (struct visornic_devdata *)v;
- cmdrsp = kmalloc(SZ, GFP_ATOMIC);
- if (!cmdrsp)
- complete_and_exit(&devdata->threadinfo.has_stopped, 0);
+ if (!visorchannel_signalempty(
+ devdata->dev->visorchannel,
+ IOCHAN_FROM_IOPART))
+ napi_schedule(&devdata->napi);
- while (1) {
- wait_event_interruptible_timeout(
- devdata->rsp_queue, (atomic_read(
- &devdata->interrupt_rcvd) == 1),
- msecs_to_jiffies(devdata->thread_wait_ms));
+ atomic_set(&devdata->interrupt_rcvd, 0);
- /* periodically check to see if there are any rcf bufs which
- * need to get sent to the IOSP. This can only happen if
- * we run out of memory when trying to allocate skbs.
- */
- atomic_set(&devdata->interrupt_rcvd, 0);
- send_rcv_posts_if_needed(devdata);
- drain_queue(cmdrsp, devdata);
- if (kthread_should_stop())
- break;
- }
+ mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2));
- kfree(cmdrsp);
- complete_and_exit(&devdata->threadinfo.has_stopped, 0);
}
/**
@@ -1801,12 +1780,15 @@
u64 features;
netdev = alloc_etherdev(sizeof(struct visornic_devdata));
- if (!netdev)
+ if (!netdev) {
+ dev_err(&dev->device,
+ "%s alloc_etherdev failed\n", __func__);
return -ENOMEM;
+ }
netdev->netdev_ops = &visornic_dev_ops;
netdev->watchdog_timeo = (5 * HZ);
- netdev->dev.parent = &dev->device;
+ SET_NETDEV_DEV(netdev, &dev->device);
/* Get MAC adddress from channel and read it into the device. */
netdev->addr_len = ETH_ALEN;
@@ -1814,16 +1796,23 @@
vnic.macaddr);
err = visorbus_read_channel(dev, channel_offset, netdev->dev_addr,
ETH_ALEN);
- if (err < 0)
+ if (err < 0) {
+ dev_err(&dev->device,
+ "%s failed to get mac addr from chan (%d)\n",
+ __func__, err);
goto cleanup_netdev;
+ }
devdata = devdata_initialize(netdev_priv(netdev), dev);
if (!devdata) {
+ dev_err(&dev->device,
+ "%s devdata_initialize failed\n", __func__);
err = -ENOMEM;
goto cleanup_netdev;
}
devdata->netdev = netdev;
+ dev_set_drvdata(&dev->device, devdata);
init_waitqueue_head(&devdata->rsp_queue);
spin_lock_init(&devdata->priv_lock);
devdata->enabled = 0; /* not yet */
@@ -1834,10 +1823,14 @@
vnic.num_rcv_bufs);
err = visorbus_read_channel(dev, channel_offset,
&devdata->num_rcv_bufs, 4);
- if (err)
+ if (err) {
+ dev_err(&dev->device,
+ "%s failed to get #rcv bufs from chan (%d)\n",
+ __func__, err);
goto cleanup_netdev;
+ }
- devdata->rcvbuf = kmalloc(sizeof(struct sk_buff *) *
+ devdata->rcvbuf = kzalloc(sizeof(struct sk_buff *) *
devdata->num_rcv_bufs, GFP_KERNEL);
if (!devdata->rcvbuf) {
err = -ENOMEM;
@@ -1846,12 +1839,15 @@
/* set the net_xmit outstanding threshold */
/* always leave two slots open but you should have 3 at a minimum */
+ /* note that max_outstanding_net_xmits must be > 0 */
devdata->max_outstanding_net_xmits =
- max(3, ((devdata->num_rcv_bufs / 3) - 2));
+ max_t(unsigned long, 3, ((devdata->num_rcv_bufs / 3) - 2));
devdata->upper_threshold_net_xmits =
- max(2, devdata->max_outstanding_net_xmits - 1);
+ max_t(unsigned long,
+ 2, (devdata->max_outstanding_net_xmits - 1));
devdata->lower_threshold_net_xmits =
- max(1, devdata->max_outstanding_net_xmits / 2);
+ max_t(unsigned long,
+ 1, (devdata->max_outstanding_net_xmits / 2));
skb_queue_head_init(&devdata->xmitbufhead);
@@ -1866,8 +1862,6 @@
err = -ENOMEM;
goto cleanup_xmit_cmdrsp;
}
- INIT_WORK(&devdata->serverdown_completion,
- visornic_serverdown_complete);
INIT_WORK(&devdata->timeout_reset, visornic_timeout_reset);
devdata->server_down = false;
devdata->server_change_state = false;
@@ -1876,42 +1870,70 @@
channel_offset = offsetof(struct spar_io_channel_protocol,
vnic.mtu);
err = visorbus_read_channel(dev, channel_offset, &netdev->mtu, 4);
- if (err)
+ if (err) {
+ dev_err(&dev->device,
+ "%s failed to get mtu from chan (%d)\n",
+ __func__, err);
goto cleanup_xmit_cmdrsp;
+ }
/* TODO: Setup Interrupt information */
/* Let's start our threads to get responses */
+ netif_napi_add(netdev, &devdata->napi, visornic_poll, 64);
+
+ setup_timer(&devdata->irq_poll_timer, poll_for_irq,
+ (unsigned long)devdata);
+ /*
+ * Note: This time has to start running before the while
+ * loop below because the napi routine is responsible for
+ * setting enab_dis_acked
+ */
+ mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2));
+
channel_offset = offsetof(struct spar_io_channel_protocol,
channel_header.features);
err = visorbus_read_channel(dev, channel_offset, &features, 8);
- if (err)
- goto cleanup_xmit_cmdrsp;
+ if (err) {
+ dev_err(&dev->device,
+ "%s failed to get features from chan (%d)\n",
+ __func__, err);
+ goto cleanup_napi_add;
+ }
features |= ULTRA_IO_CHANNEL_IS_POLLING;
err = visorbus_write_channel(dev, channel_offset, &features, 8);
- if (err)
- goto cleanup_xmit_cmdrsp;
-
- devdata->thread_wait_ms = 2;
- visor_thread_start(&devdata->threadinfo, process_incoming_rsps,
- devdata, "vnic_incoming");
+ if (err) {
+ dev_err(&dev->device,
+ "%s failed to set features in chan (%d)\n",
+ __func__, err);
+ goto cleanup_napi_add;
+ }
err = register_netdev(netdev);
- if (err)
- goto cleanup_thread_stop;
+ if (err) {
+ dev_err(&dev->device,
+ "%s register_netdev failed (%d)\n", __func__, err);
+ goto cleanup_napi_add;
+ }
/* create debgug/sysfs directories */
devdata->eth_debugfs_dir = debugfs_create_dir(netdev->name,
visornic_debugfs_dir);
if (!devdata->eth_debugfs_dir) {
+ dev_err(&dev->device,
+ "%s debugfs_create_dir %s failed\n",
+ __func__, netdev->name);
err = -ENOMEM;
- goto cleanup_thread_stop;
+ goto cleanup_xmit_cmdrsp;
}
+ dev_info(&dev->device, "%s success netdev=%s\n",
+ __func__, netdev->name);
return 0;
-cleanup_thread_stop:
- visor_thread_stop(&devdata->threadinfo);
+cleanup_napi_add:
+ del_timer_sync(&devdata->irq_poll_timer);
+ netif_napi_del(&devdata->napi);
cleanup_xmit_cmdrsp:
kfree(devdata->xmit_cmdrsp);
@@ -1954,12 +1976,41 @@
static void visornic_remove(struct visor_device *dev)
{
struct visornic_devdata *devdata = dev_get_drvdata(&dev->device);
+ struct net_device *netdev;
+ unsigned long flags;
- if (!devdata)
+ if (!devdata) {
+ dev_err(&dev->device, "%s no devdata\n", __func__);
return;
+ }
+ spin_lock_irqsave(&devdata->priv_lock, flags);
+ if (devdata->going_away) {
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ dev_err(&dev->device, "%s already being removed\n", __func__);
+ return;
+ }
+ devdata->going_away = true;
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ netdev = devdata->netdev;
+ if (!netdev) {
+ dev_err(&dev->device, "%s not net device\n", __func__);
+ return;
+ }
+
+ /* going_away prevents new items being added to the workqueues */
+ flush_workqueue(visornic_timeout_reset_workqueue);
+
+ debugfs_remove_recursive(devdata->eth_debugfs_dir);
+
+ unregister_netdev(netdev); /* this will call visornic_close() */
+
+ del_timer_sync(&devdata->irq_poll_timer);
+ netif_napi_del(&devdata->napi);
+
dev_set_drvdata(&dev->device, NULL);
host_side_disappeared(devdata);
- kref_put(&devdata->kref, devdata_release);
+ devdata_release(devdata);
+ free_netdev(netdev);
}
/**
@@ -1980,8 +2031,7 @@
{
struct visornic_devdata *devdata = dev_get_drvdata(&dev->device);
- visornic_serverdown(devdata);
- complete_func(dev, 0);
+ visornic_serverdown(devdata, complete_func);
return 0;
}
@@ -2003,37 +2053,40 @@
unsigned long flags;
devdata = dev_get_drvdata(&dev->device);
- if (!devdata)
+ if (!devdata) {
+ dev_err(&dev->device, "%s no devdata\n", __func__);
return -EINVAL;
+ }
netdev = devdata->netdev;
- if (devdata->server_down && !devdata->server_change_state) {
- devdata->server_change_state = true;
- /* Must transition channel to ATTACHED state BEFORE
- * we can start using the device again.
- * TODO: State transitions
- */
- visor_thread_start(&devdata->threadinfo, process_incoming_rsps,
- devdata, "vnic_incoming");
- init_rcv_bufs(netdev, devdata);
- spin_lock_irqsave(&devdata->priv_lock, flags);
- devdata->enabled = 1;
-
- /* Now we're ready, let's send an ENB to uisnic but until
- * we get an ACK back from uisnic, we'll drop the packets
- */
- devdata->enab_dis_acked = 0;
+ spin_lock_irqsave(&devdata->priv_lock, flags);
+ if (devdata->server_change_state) {
spin_unlock_irqrestore(&devdata->priv_lock, flags);
-
- /* send enable and wait for ack - don't hold lock when
- * sending enable because if the queue if sull, insert
- * might sleep.
- */
- send_enbdis(netdev, 1, devdata);
- } else if (devdata->server_change_state) {
- return -EIO;
+ dev_err(&dev->device, "%s server already changing state\n",
+ __func__);
+ return -EINVAL;
}
+ if (!devdata->server_down) {
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
+ dev_err(&dev->device, "%s server not down\n", __func__);
+ complete_func(dev, 0);
+ return 0;
+ }
+ devdata->server_change_state = true;
+ spin_unlock_irqrestore(&devdata->priv_lock, flags);
+
+ /* Must transition channel to ATTACHED state BEFORE
+ * we can start using the device again.
+ * TODO: State transitions
+ */
+ mod_timer(&devdata->irq_poll_timer, msecs_to_jiffies(2));
+
+ init_rcv_bufs(netdev, devdata);
+
+ rtnl_lock();
+ dev_open(netdev);
+ rtnl_unlock();
complete_func(dev, 0);
return 0;
@@ -2051,18 +2104,6 @@
struct dentry *ret;
int err = -ENOMEM;
- /* create workqueue for serverdown completion */
- visornic_serverdown_workqueue =
- create_singlethread_workqueue("visornic_serverdown");
- if (!visornic_serverdown_workqueue)
- return -ENOMEM;
-
- /* create workqueue for tx timeout reset */
- visornic_timeout_reset_workqueue =
- create_singlethread_workqueue("visornic_timeout_reset");
- if (!visornic_timeout_reset_workqueue)
- return -ENOMEM;
-
visornic_debugfs_dir = debugfs_create_dir("visornic", NULL);
if (!visornic_debugfs_dir)
return err;
@@ -2076,12 +2117,6 @@
if (!ret)
goto cleanup_debugfs;
- /* create workqueue for serverdown completion */
- visornic_serverdown_workqueue =
- create_singlethread_workqueue("visornic_serverdown");
- if (!visornic_serverdown_workqueue)
- goto cleanup_debugfs;
-
/* create workqueue for tx timeout reset */
visornic_timeout_reset_workqueue =
create_singlethread_workqueue("visornic_timeout_reset");
@@ -2097,8 +2132,6 @@
return 0;
cleanup_workqueue:
- flush_workqueue(visornic_serverdown_workqueue);
- destroy_workqueue(visornic_serverdown_workqueue);
if (visornic_timeout_reset_workqueue) {
flush_workqueue(visornic_timeout_reset_workqueue);
destroy_workqueue(visornic_timeout_reset_workqueue);
@@ -2116,17 +2149,14 @@
*/
static void visornic_cleanup(void)
{
- if (visornic_serverdown_workqueue) {
- flush_workqueue(visornic_serverdown_workqueue);
- destroy_workqueue(visornic_serverdown_workqueue);
- }
+ visorbus_unregister_visor_driver(&visornic_driver);
+
if (visornic_timeout_reset_workqueue) {
flush_workqueue(visornic_timeout_reset_workqueue);
destroy_workqueue(visornic_timeout_reset_workqueue);
}
debugfs_remove_recursive(visornic_debugfs_dir);
- visorbus_unregister_visor_driver(&visornic_driver);
kfree(dev_num_pool);
dev_num_pool = NULL;
}
diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
index eabbcc7..35c6ce5 100644
--- a/drivers/staging/vme/devices/vme_pio2_core.c
+++ b/drivers/staging/vme/devices/vme_pio2_core.c
@@ -24,7 +24,6 @@
#include "vme_pio2.h"
-
static const char driver_name[] = "pio2";
static int bus[PIO2_CARDS_MAX];
@@ -118,7 +117,6 @@
}
}
-
/*
* We return whether this has been successful - this is used in the probe to
* ensure we have a valid card.
@@ -158,7 +156,6 @@
.remove = pio2_remove,
};
-
static int __init pio2_init(void)
{
if (bus_num == 0) {
@@ -178,7 +175,6 @@
static int pio2_match(struct vme_dev *vdev)
{
-
if (vdev->num >= bus_num) {
dev_err(&vdev->dev,
"The enumeration of the VMEbus to which the board is connected must be specified\n");
@@ -220,7 +216,7 @@
int vec;
card = kzalloc(sizeof(struct pio2_card), GFP_KERNEL);
- if (card == NULL) {
+ if (!card) {
retval = -ENOMEM;
goto err_struct;
}
@@ -234,7 +230,6 @@
card->vdev = vdev;
for (i = 0; i < PIO2_VARIANT_LENGTH; i++) {
-
if (isdigit(card->variant[i]) == 0) {
dev_err(&card->vdev->dev, "Variant invalid\n");
retval = -EINVAL;
@@ -264,29 +259,29 @@
for (i = 1; i < PIO2_VARIANT_LENGTH; i++) {
switch (card->variant[i]) {
case '0':
- card->bank[i-1].config = NOFIT;
+ card->bank[i - 1].config = NOFIT;
break;
case '1':
case '2':
case '3':
case '4':
- card->bank[i-1].config = INPUT;
+ card->bank[i - 1].config = INPUT;
break;
case '5':
- card->bank[i-1].config = OUTPUT;
+ card->bank[i - 1].config = OUTPUT;
break;
case '6':
case '7':
case '8':
case '9':
- card->bank[i-1].config = BOTH;
+ card->bank[i - 1].config = BOTH;
break;
}
}
/* Get a master window and position over regs */
card->window = vme_master_request(vdev, VME_A24, VME_SCT, VME_D16);
- if (card->window == NULL) {
+ if (!card->window) {
dev_err(&card->vdev->dev,
"Unable to assign VME master resource\n");
retval = -EIO;
@@ -481,7 +476,6 @@
vme_unregister_driver(&pio2_driver);
}
-
/* These are required for each board */
MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected");
module_param_array(bus, int, &bus_num, S_IRUGO);
diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c
index 9cca97a..8e61a3b 100644
--- a/drivers/staging/vme/devices/vme_user.c
+++ b/drivers/staging/vme/devices/vme_user.c
@@ -101,13 +101,13 @@
struct vme_resource *resource; /* VME resource */
int mmap_count; /* Number of current mmap's */
};
+
static struct image_desc image[VME_DEVS];
static struct cdev *vme_user_cdev; /* Character device */
static struct class *vme_user_sysfs_class; /* Sysfs class */
static struct vme_dev *vme_user_bridge; /* Pointer to user device */
-
static const int type[VME_DEVS] = { MASTER_MINOR, MASTER_MINOR,
MASTER_MINOR, MASTER_MINOR,
SLAVE_MINOR, SLAVE_MINOR,
@@ -120,125 +120,68 @@
atomic_t refcnt;
};
-
-/*
- * We are going ot alloc a page during init per window for small transfers.
- * Small transfers will go VME -> buffer -> user space. Larger (more than a
- * page) transfers will lock the user space buffer into memory and then
- * transfer the data directly into the user space buffers.
- */
static ssize_t resource_to_user(int minor, char __user *buf, size_t count,
- loff_t *ppos)
+ loff_t *ppos)
{
- ssize_t retval;
ssize_t copied = 0;
- if (count <= image[minor].size_buf) {
- /* We copy to kernel buffer */
- copied = vme_master_read(image[minor].resource,
- image[minor].kern_buf, count, *ppos);
- if (copied < 0)
- return (int)copied;
+ if (count > image[minor].size_buf)
+ count = image[minor].size_buf;
- retval = __copy_to_user(buf, image[minor].kern_buf,
- (unsigned long)copied);
- if (retval != 0) {
- copied = (copied - retval);
- pr_info("User copy failed\n");
- return -EINVAL;
- }
+ copied = vme_master_read(image[minor].resource, image[minor].kern_buf,
+ count, *ppos);
+ if (copied < 0)
+ return (int)copied;
- } else {
- /* XXX Need to write this */
- pr_info("Currently don't support large transfers\n");
- /* Map in pages from userspace */
-
- /* Call vme_master_read to do the transfer */
- return -EINVAL;
- }
+ if (__copy_to_user(buf, image[minor].kern_buf, (unsigned long)copied))
+ return -EFAULT;
return copied;
}
-/*
- * We are going to alloc a page during init per window for small transfers.
- * Small transfers will go user space -> buffer -> VME. Larger (more than a
- * page) transfers will lock the user space buffer into memory and then
- * transfer the data directly from the user space buffers out to VME.
- */
static ssize_t resource_from_user(unsigned int minor, const char __user *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
- ssize_t retval;
- ssize_t copied = 0;
+ if (count > image[minor].size_buf)
+ count = image[minor].size_buf;
- if (count <= image[minor].size_buf) {
- retval = __copy_from_user(image[minor].kern_buf, buf,
- (unsigned long)count);
- if (retval != 0)
- copied = (copied - retval);
- else
- copied = count;
+ if (__copy_from_user(image[minor].kern_buf, buf, (unsigned long)count))
+ return -EFAULT;
- copied = vme_master_write(image[minor].resource,
- image[minor].kern_buf, copied, *ppos);
- } else {
- /* XXX Need to write this */
- pr_info("Currently don't support large transfers\n");
- /* Map in pages from userspace */
-
- /* Call vme_master_write to do the transfer */
- return -EINVAL;
- }
-
- return copied;
+ return vme_master_write(image[minor].resource, image[minor].kern_buf,
+ count, *ppos);
}
static ssize_t buffer_to_user(unsigned int minor, char __user *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
void *image_ptr;
- ssize_t retval;
image_ptr = image[minor].kern_buf + *ppos;
+ if (__copy_to_user(buf, image_ptr, (unsigned long)count))
+ return -EFAULT;
- retval = __copy_to_user(buf, image_ptr, (unsigned long)count);
- if (retval != 0) {
- retval = (count - retval);
- pr_warn("Partial copy to userspace\n");
- } else
- retval = count;
-
- /* Return number of bytes successfully read */
- return retval;
+ return count;
}
static ssize_t buffer_from_user(unsigned int minor, const char __user *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
void *image_ptr;
- size_t retval;
image_ptr = image[minor].kern_buf + *ppos;
+ if (__copy_from_user(image_ptr, buf, (unsigned long)count))
+ return -EFAULT;
- retval = __copy_from_user(image_ptr, buf, (unsigned long)count);
- if (retval != 0) {
- retval = (count - retval);
- pr_warn("Partial copy to userspace\n");
- } else
- retval = count;
-
- /* Return number of bytes successfully read */
- return retval;
+ return count;
}
static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
- loff_t *ppos)
+ loff_t *ppos)
{
unsigned int minor = MINOR(file_inode(file)->i_rdev);
ssize_t retval;
size_t image_size;
- size_t okcount;
if (minor == CONTROL_MINOR)
return 0;
@@ -256,16 +199,14 @@
/* Ensure not reading past end of the image */
if (*ppos + count > image_size)
- okcount = image_size - *ppos;
- else
- okcount = count;
+ count = image_size - *ppos;
switch (type[minor]) {
case MASTER_MINOR:
- retval = resource_to_user(minor, buf, okcount, ppos);
+ retval = resource_to_user(minor, buf, count, ppos);
break;
case SLAVE_MINOR:
- retval = buffer_to_user(minor, buf, okcount, ppos);
+ retval = buffer_to_user(minor, buf, count, ppos);
break;
default:
retval = -EINVAL;
@@ -279,12 +220,11 @@
}
static ssize_t vme_user_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
unsigned int minor = MINOR(file_inode(file)->i_rdev);
ssize_t retval;
size_t image_size;
- size_t okcount;
if (minor == CONTROL_MINOR)
return 0;
@@ -301,16 +241,14 @@
/* Ensure not reading past end of the image */
if (*ppos + count > image_size)
- okcount = image_size - *ppos;
- else
- okcount = count;
+ count = image_size - *ppos;
switch (type[minor]) {
case MASTER_MINOR:
- retval = resource_from_user(minor, buf, okcount, ppos);
+ retval = resource_from_user(minor, buf, count, ppos);
break;
case SLAVE_MINOR:
- retval = buffer_from_user(minor, buf, okcount, ppos);
+ retval = buffer_from_user(minor, buf, count, ppos);
break;
default:
retval = -EINVAL;
@@ -354,7 +292,7 @@
* already been defined.
*/
static int vme_user_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+ unsigned int cmd, unsigned long arg)
{
struct vme_master master;
struct vme_slave slave;
@@ -390,12 +328,13 @@
* to userspace as they are
*/
retval = vme_master_get(image[minor].resource,
- &master.enable, &master.vme_addr,
- &master.size, &master.aspace,
- &master.cycle, &master.dwidth);
+ &master.enable,
+ &master.vme_addr,
+ &master.size, &master.aspace,
+ &master.cycle, &master.dwidth);
copied = copy_to_user(argp, &master,
- sizeof(struct vme_master));
+ sizeof(struct vme_master));
if (copied != 0) {
pr_warn("Partial copy to userspace\n");
return -EFAULT;
@@ -435,12 +374,12 @@
* to userspace as they are
*/
retval = vme_slave_get(image[minor].resource,
- &slave.enable, &slave.vme_addr,
- &slave.size, &pci_addr, &slave.aspace,
- &slave.cycle);
+ &slave.enable, &slave.vme_addr,
+ &slave.size, &pci_addr,
+ &slave.aspace, &slave.cycle);
copied = copy_to_user(argp, &slave,
- sizeof(struct vme_slave));
+ sizeof(struct vme_slave));
if (copied != 0) {
pr_warn("Partial copy to userspace\n");
return -EFAULT;
@@ -526,8 +465,8 @@
return err;
}
- vma_priv = kmalloc(sizeof(struct vme_user_vma_priv), GFP_KERNEL);
- if (vma_priv == NULL) {
+ vma_priv = kmalloc(sizeof(*vma_priv), GFP_KERNEL);
+ if (!vma_priv) {
mutex_unlock(&image[minor].mutex);
return -ENOMEM;
}
@@ -588,7 +527,7 @@
char *name;
/* Save pointer to the bridge device */
- if (vme_user_bridge != NULL) {
+ if (vme_user_bridge) {
dev_err(&vdev->dev, "Driver can only be loaded for 1 device\n");
err = -EINVAL;
goto err_dev;
@@ -606,7 +545,7 @@
/* Assign major and minor numbers for the driver */
err = register_chrdev_region(MKDEV(VME_MAJOR, 0), VME_DEVS,
- driver_name);
+ driver_name);
if (err) {
dev_warn(&vdev->dev, "Error getting Major Number %d for driver.\n",
VME_MAJOR);
@@ -622,10 +561,8 @@
vme_user_cdev->ops = &vme_user_fops;
vme_user_cdev->owner = THIS_MODULE;
err = cdev_add(vme_user_cdev, MKDEV(VME_MAJOR, 0), VME_DEVS);
- if (err) {
- dev_warn(&vdev->dev, "cdev_all failed\n");
+ if (err)
goto err_char;
- }
/* Request slave resources and allocate buffers (128kB wide) */
for (i = SLAVE_MINOR; i < (SLAVE_MAX + 1); i++) {
@@ -636,7 +573,7 @@
*/
image[i].resource = vme_slave_request(vme_user_bridge,
VME_A24, VME_SCT);
- if (image[i].resource == NULL) {
+ if (!image[i].resource) {
dev_warn(&vdev->dev,
"Unable to allocate slave resource\n");
err = -ENOMEM;
@@ -645,7 +582,7 @@
image[i].size_buf = PCI_BUF_SIZE;
image[i].kern_buf = vme_alloc_consistent(image[i].resource,
image[i].size_buf, &image[i].pci_buf);
- if (image[i].kern_buf == NULL) {
+ if (!image[i].kern_buf) {
dev_warn(&vdev->dev,
"Unable to allocate memory for buffer\n");
image[i].pci_buf = 0;
@@ -663,7 +600,7 @@
/* XXX Need to properly request attributes */
image[i].resource = vme_master_request(vme_user_bridge,
VME_A32, VME_SCT, VME_D32);
- if (image[i].resource == NULL) {
+ if (!image[i].resource) {
dev_warn(&vdev->dev,
"Unable to allocate master resource\n");
err = -ENOMEM;
@@ -671,7 +608,7 @@
}
image[i].size_buf = PCI_BUF_SIZE;
image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL);
- if (image[i].kern_buf == NULL) {
+ if (!image[i].kern_buf) {
err = -ENOMEM;
vme_master_free(image[i].resource);
goto err_master;
@@ -835,7 +772,6 @@
vme_unregister_driver(&vme_user_driver);
}
-
MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the driver is connected");
module_param_array(bus, int, &bus_num, 0);
diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c
index b0ea38f..9e61f2d 100644
--- a/drivers/staging/vt6655/baseband.c
+++ b/drivers/staging/vt6655/baseband.c
@@ -1728,10 +1728,8 @@
unsigned int uRateIdx = (unsigned int) wRate;
unsigned int uRate = 0;
- if (uRateIdx > RATE_54M) {
- ASSERT(0);
+ if (uRateIdx > RATE_54M)
return 0;
- }
uRate = (unsigned int)awcFrameTime[uRateIdx];
@@ -1945,7 +1943,6 @@
VNSvInPortB(dwIoBase + MAC_REG_BBREGDATA, pbyData);
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x30);
pr_debug(" DBG_PORT80(0x30)\n");
return false;
}
@@ -1988,7 +1985,6 @@
}
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x31);
pr_debug(" DBG_PORT80(0x31)\n");
return false;
}
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
index e00c060..c7b75df 100644
--- a/drivers/staging/vt6655/card.c
+++ b/drivers/staging/vt6655/card.c
@@ -514,7 +514,7 @@
)
{
unsigned int uu;
- PSTxDesc pCurrTD;
+ struct vnt_tx_desc *pCurrTD;
/* initialize TD index */
pDevice->apTailTD[0] = pDevice->apCurrTD[0] = &(pDevice->apTD0Rings[0]);
@@ -525,12 +525,12 @@
for (uu = 0; uu < pDevice->sOpts.nTxDescs[0]; uu++) {
pCurrTD = &(pDevice->apTD0Rings[uu]);
- pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST;
+ pCurrTD->td0.owner = OWNED_BY_HOST;
/* init all Tx Packet pointer to NULL */
}
for (uu = 0; uu < pDevice->sOpts.nTxDescs[1]; uu++) {
pCurrTD = &(pDevice->apTD1Rings[uu]);
- pCurrTD->m_td0TD0.f1Owner = OWNED_BY_HOST;
+ pCurrTD->td0.owner = OWNED_BY_HOST;
/* init all Tx Packet pointer to NULL */
}
@@ -573,17 +573,17 @@
/* init state, all RD is chip's */
for (uu = 0; uu < pDevice->sOpts.nRxDescs0; uu++) {
pDesc = &(pDevice->aRD0Ring[uu]);
- pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz);
+ pDesc->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz);
pDesc->m_rd0RD0.f1Owner = OWNED_BY_NIC;
- pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz);
+ pDesc->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz);
}
/* init state, all RD is chip's */
for (uu = 0; uu < pDevice->sOpts.nRxDescs1; uu++) {
pDesc = &(pDevice->aRD1Ring[uu]);
- pDesc->m_rd0RD0.wResCount = (unsigned short)(pDevice->rx_buf_sz);
+ pDesc->m_rd0RD0.wResCount = cpu_to_le16(pDevice->rx_buf_sz);
pDesc->m_rd0RD0.f1Owner = OWNED_BY_NIC;
- pDesc->m_rd1RD1.wReqCount = (unsigned short)(pDevice->rx_buf_sz);
+ pDesc->m_rd1RD1.wReqCount = cpu_to_le16(pDevice->rx_buf_sz);
}
/* set perPkt mode */
@@ -847,7 +847,6 @@
case CARD_LB_PHY:
break;
default:
- ASSERT(false);
break;
}
/* set MAC loopback */
diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h
index 758eeb2..3c9007e 100644
--- a/drivers/staging/vt6655/desc.h
+++ b/drivers/staging/vt6655/desc.h
@@ -170,13 +170,12 @@
typedef struct tagDEVICE_RD_INFO {
struct sk_buff *skb;
dma_addr_t skb_dma;
- dma_addr_t curr_desc;
} DEVICE_RD_INFO, *PDEVICE_RD_INFO;
#ifdef __BIG_ENDIAN
typedef struct tagRDES0 {
- volatile unsigned short wResCount;
+ volatile __le16 wResCount;
union {
volatile u16 f15Reserved;
struct {
@@ -191,7 +190,7 @@
#else
typedef struct tagRDES0 {
- unsigned short wResCount;
+ __le16 wResCount;
unsigned short f15Reserved:15;
unsigned short f1Owner:1;
} __attribute__ ((__packed__))
@@ -200,7 +199,7 @@
#endif
typedef struct tagRDES1 {
- unsigned short wReqCount;
+ __le16 wReqCount;
unsigned short wReserved;
} __attribute__ ((__packed__))
SRDES1;
@@ -209,93 +208,56 @@
typedef struct tagSRxDesc {
volatile SRDES0 m_rd0RD0;
volatile SRDES1 m_rd1RD1;
- volatile u32 buff_addr;
- volatile u32 next_desc;
+ volatile __le32 buff_addr;
+ volatile __le32 next_desc;
struct tagSRxDesc *next __aligned(8);
volatile PDEVICE_RD_INFO pRDInfo __aligned(8);
} __attribute__ ((__packed__))
SRxDesc, *PSRxDesc;
typedef const SRxDesc *PCSRxDesc;
+struct vnt_tdes0 {
+ volatile u8 tsr0;
+ volatile u8 tsr1;
#ifdef __BIG_ENDIAN
-
-typedef struct tagTDES0 {
- volatile unsigned char byTSR0;
- volatile unsigned char byTSR1;
union {
- volatile u16 f15Txtime;
+ volatile u16 f15_txtime;
struct {
- volatile u8 f8Reserved1;
- volatile u8 f1Owner:1;
- volatile u8 f7Reserved:7;
- } __attribute__ ((__packed__));
- } __attribute__ ((__packed__));
-} __attribute__ ((__packed__))
-STDES0, PSTDES0;
-
+ volatile u8 f8_reserved;
+ volatile u8 owner:1;
+ volatile u8 f7_reserved:7;
+ } __packed;
+ } __packed;
#else
-
-typedef struct tagTDES0 {
- volatile unsigned char byTSR0;
- volatile unsigned char byTSR1;
- volatile unsigned short f15Txtime:15;
- volatile unsigned short f1Owner:1;
-} __attribute__ ((__packed__))
-STDES0;
-
+ volatile u16 f15_txtime:15;
+ volatile u16 owner:1;
#endif
+} __packed;
-typedef struct tagTDES1 {
- volatile unsigned short wReqCount;
- volatile unsigned char byTCR;
- volatile unsigned char byReserved;
-} __attribute__ ((__packed__))
-STDES1;
+struct vnt_tdes1 {
+ volatile __le16 req_count;
+ volatile u8 tcr;
+ volatile u8 reserved;
+} __packed;
-typedef struct tagDEVICE_TD_INFO {
+struct vnt_td_info {
void *mic_hdr;
struct sk_buff *skb;
unsigned char *buf;
- dma_addr_t skb_dma;
- dma_addr_t buf_dma;
- dma_addr_t curr_desc;
- unsigned long dwReqCount;
- unsigned long dwHeaderLength;
- unsigned char byFlags;
-} DEVICE_TD_INFO, *PDEVICE_TD_INFO;
+ dma_addr_t buf_dma;
+ u16 req_count;
+ u8 flags;
+};
/* transmit descriptor */
-typedef struct tagSTxDesc {
- volatile STDES0 m_td0TD0;
- volatile STDES1 m_td1TD1;
- volatile u32 buff_addr;
- volatile u32 next_desc;
- struct tagSTxDesc *next __aligned(8);
- volatile PDEVICE_TD_INFO pTDInfo __aligned(8);
-} __attribute__ ((__packed__))
-STxDesc, *PSTxDesc;
-typedef const STxDesc *PCSTxDesc;
-
-typedef struct tagSTxSyncDesc {
- volatile STDES0 m_td0TD0;
- volatile STDES1 m_td1TD1;
- volatile u32 buff_addr; /* pointer to logical buffer */
- volatile u32 next_desc; /* pointer to next logical descriptor */
- volatile unsigned short m_wFIFOCtl;
- volatile unsigned short m_wTimeStamp;
- struct tagSTxSyncDesc *next __aligned(8);
- volatile PDEVICE_TD_INFO pTDInfo __aligned(8);
-} __attribute__ ((__packed__))
-STxSyncDesc, *PSTxSyncDesc;
-typedef const STxSyncDesc *PCSTxSyncDesc;
-
-/* RsvTime buffer header */
-typedef struct tagSRrvTime_atim {
- unsigned short wCTSTxRrvTime_ba;
- unsigned short wTxRrvTime_a;
-} __attribute__ ((__packed__))
-SRrvTime_atim, *PSRrvTime_atim;
-typedef const SRrvTime_atim *PCSRrvTime_atim;
+struct vnt_tx_desc {
+ volatile struct vnt_tdes0 td0;
+ volatile struct vnt_tdes1 td1;
+ volatile __le32 buff_addr;
+ volatile __le32 next_desc;
+ struct vnt_tx_desc *next __aligned(8);
+ struct vnt_td_info *td_info __aligned(8);
+} __packed;
/* Length, Service, and Signal fields of Phy for Tx */
struct vnt_phy_field {
@@ -310,42 +272,4 @@
u32 field_write;
};
-/* Tx FIFO header */
-typedef struct tagSTxBufHead {
- u32 adwTxKey[4];
- unsigned short wFIFOCtl;
- unsigned short wTimeStamp;
- unsigned short wFragCtl;
- unsigned char byTxPower;
- unsigned char wReserved;
-} __attribute__ ((__packed__))
-STxBufHead, *PSTxBufHead;
-typedef const STxBufHead *PCSTxBufHead;
-
-typedef struct tagSBEACONCtl {
- u32 BufReady:1;
- u32 TSF:15;
- u32 BufLen:11;
- u32 Reserved:5;
-} __attribute__ ((__packed__))
-SBEACONCtl;
-
-typedef struct tagSSecretKey {
- u32 dwLowDword;
- unsigned char byHighByte;
-} __attribute__ ((__packed__))
-SSecretKey;
-
-typedef struct tagSKeyEntry {
- unsigned char abyAddrHi[2];
- unsigned short wKCTL;
- unsigned char abyAddrLo[4];
- u32 dwKey0[4];
- u32 dwKey1[4];
- u32 dwKey2[4];
- u32 dwKey3[4];
- u32 dwKey4[4];
-} __attribute__ ((__packed__))
-SKeyEntry;
-
#endif /* __DESC_H__ */
diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h
index 5cf1b33..c9fa6ef 100644
--- a/drivers/staging/vt6655/device.h
+++ b/drivers/staging/vt6655/device.h
@@ -252,11 +252,11 @@
int nTxQueues;
volatile int iTDUsed[TYPE_MAXTD];
- volatile PSTxDesc apCurrTD[TYPE_MAXTD];
- volatile PSTxDesc apTailTD[TYPE_MAXTD];
+ struct vnt_tx_desc *apCurrTD[TYPE_MAXTD];
+ struct vnt_tx_desc *apTailTD[TYPE_MAXTD];
- volatile PSTxDesc apTD0Rings;
- volatile PSTxDesc apTD1Rings;
+ struct vnt_tx_desc *apTD0Rings;
+ struct vnt_tx_desc *apTD1Rings;
volatile PSRxDesc aRD0Ring;
volatile PSRxDesc aRD1Ring;
@@ -403,6 +403,7 @@
unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE]; /* unsigned long alignment */
unsigned short wBeaconInterval;
+ u16 wake_up_count;
struct work_struct interrupt_work;
@@ -414,8 +415,8 @@
return kzalloc(sizeof(DEVICE_RD_INFO), GFP_ATOMIC);
}
-static inline PDEVICE_TD_INFO alloc_td_info(void)
+static inline struct vnt_td_info *alloc_td_info(void)
{
- return kzalloc(sizeof(DEVICE_TD_INFO), GFP_ATOMIC);
+ return kzalloc(sizeof(struct vnt_td_info), GFP_ATOMIC);
}
#endif
diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h
index a4a8a84..b4c9547 100644
--- a/drivers/staging/vt6655/device_cfg.h
+++ b/drivers/staging/vt6655/device_cfg.h
@@ -69,19 +69,4 @@
VT3253 = 1
} CHIP_TYPE, *PCHIP_TYPE;
-#ifdef VIAWET_DEBUG
-#define ASSERT(x) \
-do { \
- if (!(x)) { \
- pr_err("assertion %s failed: file %s line %d\n", \
- #x, __func__, __LINE__); \
- *(int *)0 = 0; \
- } \
-} while (0)
-#define DBG_PORT80(value) outb(value, 0x80)
-#else
-#define ASSERT(x)
-#define DBG_PORT80(value)
-#endif
-
#endif
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
index b0c8e23..0d8f123 100644
--- a/drivers/staging/vt6655/device_main.c
+++ b/drivers/staging/vt6655/device_main.c
@@ -157,7 +157,7 @@
static int device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx);
static bool device_alloc_rx_buf(struct vnt_private *pDevice, PSRxDesc pDesc);
static void device_init_registers(struct vnt_private *pDevice);
-static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc);
+static void device_free_tx_buf(struct vnt_private *, struct vnt_tx_desc *);
static void device_free_td0_ring(struct vnt_private *pDevice);
static void device_free_td1_ring(struct vnt_private *pDevice);
static void device_free_rd0_ring(struct vnt_private *pDevice);
@@ -522,8 +522,8 @@
vir_pool = dma_zalloc_coherent(&pDevice->pcid->dev,
pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
- pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
- pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
+ pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc) +
+ pDevice->sOpts.nTxDescs[1] * sizeof(struct vnt_tx_desc),
&pDevice->pool_dma, GFP_ATOMIC);
if (vir_pool == NULL) {
dev_err(&pDevice->pcid->dev, "allocate desc dma memory failed\n");
@@ -551,8 +551,8 @@
dma_free_coherent(&pDevice->pcid->dev,
pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
- pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
- pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc),
+ pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc) +
+ pDevice->sOpts.nTxDescs[1] * sizeof(struct vnt_tx_desc),
vir_pool, pDevice->pool_dma
);
return false;
@@ -562,7 +562,7 @@
pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc);
pDevice->td1_pool_dma = pDevice->td0_pool_dma +
- pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
+ pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc);
/* vir_pool: pvoid type */
pDevice->apTD0Rings = vir_pool
@@ -572,7 +572,7 @@
pDevice->apTD1Rings = vir_pool
+ pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc)
+ pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc)
- + pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc);
+ + pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc);
pDevice->tx1_bufs = pDevice->tx0_bufs +
pDevice->sOpts.nTxDescs[0] * PKT_BUF_SZ;
@@ -597,8 +597,8 @@
dma_free_coherent(&pDevice->pcid->dev,
pDevice->sOpts.nRxDescs0 * sizeof(SRxDesc) +
pDevice->sOpts.nRxDescs1 * sizeof(SRxDesc) +
- pDevice->sOpts.nTxDescs[0] * sizeof(STxDesc) +
- pDevice->sOpts.nTxDescs[1] * sizeof(STxDesc)
+ pDevice->sOpts.nTxDescs[0] * sizeof(struct vnt_tx_desc) +
+ pDevice->sOpts.nTxDescs[1] * sizeof(struct vnt_tx_desc)
,
pDevice->aRD0Ring, pDevice->pool_dma
);
@@ -623,12 +623,11 @@
for (i = 0; i < pDevice->sOpts.nRxDescs0; i ++, curr += sizeof(SRxDesc)) {
pDesc = &(pDevice->aRD0Ring[i]);
pDesc->pRDInfo = alloc_rd_info();
- ASSERT(pDesc->pRDInfo);
+
if (!device_alloc_rx_buf(pDevice, pDesc))
dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n");
pDesc->next = &(pDevice->aRD0Ring[(i+1) % pDevice->sOpts.nRxDescs0]);
- pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
}
@@ -647,12 +646,11 @@
for (i = 0; i < pDevice->sOpts.nRxDescs1; i ++, curr += sizeof(SRxDesc)) {
pDesc = &(pDevice->aRD1Ring[i]);
pDesc->pRDInfo = alloc_rd_info();
- ASSERT(pDesc->pRDInfo);
+
if (!device_alloc_rx_buf(pDevice, pDesc))
dev_err(&pDevice->pcid->dev, "can not alloc rx bufs\n");
pDesc->next = &(pDevice->aRD1Ring[(i+1) % pDevice->sOpts.nRxDescs1]);
- pDesc->pRDInfo->curr_desc = cpu_to_le32(curr);
pDesc->next_desc = cpu_to_le32(curr + sizeof(SRxDesc));
}
@@ -699,20 +697,20 @@
{
int i;
dma_addr_t curr;
- PSTxDesc pDesc;
+ struct vnt_tx_desc *pDesc;
curr = pDevice->td0_pool_dma;
- for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++, curr += sizeof(STxDesc)) {
+ for (i = 0; i < pDevice->sOpts.nTxDescs[0];
+ i++, curr += sizeof(struct vnt_tx_desc)) {
pDesc = &(pDevice->apTD0Rings[i]);
- pDesc->pTDInfo = alloc_td_info();
- ASSERT(pDesc->pTDInfo);
+ pDesc->td_info = alloc_td_info();
+
if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
- pDesc->pTDInfo->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ;
- pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ;
+ pDesc->td_info->buf = pDevice->tx0_bufs + (i)*PKT_BUF_SZ;
+ pDesc->td_info->buf_dma = pDevice->tx_bufs_dma0 + (i)*PKT_BUF_SZ;
}
pDesc->next = &(pDevice->apTD0Rings[(i+1) % pDevice->sOpts.nTxDescs[0]]);
- pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
- pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
+ pDesc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc));
}
if (i > 0)
@@ -724,21 +722,21 @@
{
int i;
dma_addr_t curr;
- PSTxDesc pDesc;
+ struct vnt_tx_desc *pDesc;
/* Init the TD ring entries */
curr = pDevice->td1_pool_dma;
- for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++, curr += sizeof(STxDesc)) {
+ for (i = 0; i < pDevice->sOpts.nTxDescs[1];
+ i++, curr += sizeof(struct vnt_tx_desc)) {
pDesc = &(pDevice->apTD1Rings[i]);
- pDesc->pTDInfo = alloc_td_info();
- ASSERT(pDesc->pTDInfo);
+ pDesc->td_info = alloc_td_info();
+
if (pDevice->flags & DEVICE_FLAGS_TX_ALIGN) {
- pDesc->pTDInfo->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ;
- pDesc->pTDInfo->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ;
+ pDesc->td_info->buf = pDevice->tx1_bufs + (i) * PKT_BUF_SZ;
+ pDesc->td_info->buf_dma = pDevice->tx_bufs_dma1 + (i) * PKT_BUF_SZ;
}
pDesc->next = &(pDevice->apTD1Rings[(i + 1) % pDevice->sOpts.nTxDescs[1]]);
- pDesc->pTDInfo->curr_desc = cpu_to_le32(curr);
- pDesc->next_desc = cpu_to_le32(curr+sizeof(STxDesc));
+ pDesc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc));
}
if (i > 0)
@@ -751,17 +749,11 @@
int i;
for (i = 0; i < pDevice->sOpts.nTxDescs[0]; i++) {
- PSTxDesc pDesc = &(pDevice->apTD0Rings[i]);
- PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo;
+ struct vnt_tx_desc *pDesc = &pDevice->apTD0Rings[i];
+ struct vnt_td_info *pTDInfo = pDesc->td_info;
- if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
- dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma,
- pTDInfo->skb->len, DMA_TO_DEVICE);
-
- if (pTDInfo->skb)
- dev_kfree_skb(pTDInfo->skb);
-
- kfree(pDesc->pTDInfo);
+ dev_kfree_skb(pTDInfo->skb);
+ kfree(pDesc->td_info);
}
}
@@ -770,17 +762,11 @@
int i;
for (i = 0; i < pDevice->sOpts.nTxDescs[1]; i++) {
- PSTxDesc pDesc = &(pDevice->apTD1Rings[i]);
- PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo;
+ struct vnt_tx_desc *pDesc = &pDevice->apTD1Rings[i];
+ struct vnt_td_info *pTDInfo = pDesc->td_info;
- if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma))
- dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma,
- pTDInfo->skb->len, DMA_TO_DEVICE);
-
- if (pTDInfo->skb)
- dev_kfree_skb(pTDInfo->skb);
-
- kfree(pDesc->pTDInfo);
+ dev_kfree_skb(pTDInfo->skb);
+ kfree(pDesc->td_info);
}
}
@@ -822,7 +808,6 @@
pRDInfo->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
if (pRDInfo->skb == NULL)
return false;
- ASSERT(pRDInfo->skb);
pRDInfo->skb_dma =
dma_map_single(&pDevice->pcid->dev,
@@ -856,7 +841,7 @@
};
static int vnt_int_report_rate(struct vnt_private *priv,
- PDEVICE_TD_INFO context, u8 tsr0, u8 tsr1)
+ struct vnt_td_info *context, u8 tsr0, u8 tsr1)
{
struct vnt_tx_fifo_head *fifo_head;
struct ieee80211_tx_info *info;
@@ -917,23 +902,23 @@
static int device_tx_srv(struct vnt_private *pDevice, unsigned int uIdx)
{
- PSTxDesc pTD;
+ struct vnt_tx_desc *pTD;
int works = 0;
unsigned char byTsr0;
unsigned char byTsr1;
for (pTD = pDevice->apTailTD[uIdx]; pDevice->iTDUsed[uIdx] > 0; pTD = pTD->next) {
- if (pTD->m_td0TD0.f1Owner == OWNED_BY_NIC)
+ if (pTD->td0.owner == OWNED_BY_NIC)
break;
if (works++ > 15)
break;
- byTsr0 = pTD->m_td0TD0.byTSR0;
- byTsr1 = pTD->m_td0TD0.byTSR1;
+ byTsr0 = pTD->td0.tsr0;
+ byTsr1 = pTD->td0.tsr1;
/* Only the status of first TD in the chain is correct */
- if (pTD->m_td1TD1.byTCR & TCR_STP) {
- if ((pTD->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB) != 0) {
+ if (pTD->td1.tcr & TCR_STP) {
+ if ((pTD->td_info->flags & TD_FLAGS_NETIF_SKB) != 0) {
if (!(byTsr1 & TSR1_TERR)) {
if (byTsr0 != 0) {
pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n",
@@ -947,13 +932,13 @@
}
if (byTsr1 & TSR1_TERR) {
- if ((pTD->pTDInfo->byFlags & TD_FLAGS_PRIV_SKB) != 0) {
+ if ((pTD->td_info->flags & TD_FLAGS_PRIV_SKB) != 0) {
pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n",
(int)uIdx, byTsr1, byTsr0);
}
}
- vnt_int_report_rate(pDevice, pTD->pTDInfo, byTsr0, byTsr1);
+ vnt_int_report_rate(pDevice, pTD->td_info, byTsr0, byTsr1);
device_free_tx_buf(pDevice, pTD);
pDevice->iTDUsed[uIdx]--;
@@ -975,23 +960,17 @@
}
}
-static void device_free_tx_buf(struct vnt_private *pDevice, PSTxDesc pDesc)
+static void device_free_tx_buf(struct vnt_private *pDevice,
+ struct vnt_tx_desc *pDesc)
{
- PDEVICE_TD_INFO pTDInfo = pDesc->pTDInfo;
+ struct vnt_td_info *pTDInfo = pDesc->td_info;
struct sk_buff *skb = pTDInfo->skb;
- /* pre-allocated buf_dma can't be unmapped. */
- if (pTDInfo->skb_dma && (pTDInfo->skb_dma != pTDInfo->buf_dma)) {
- dma_unmap_single(&pDevice->pcid->dev, pTDInfo->skb_dma,
- skb->len, DMA_TO_DEVICE);
- }
-
if (skb)
ieee80211_tx_status_irqsafe(pDevice->hw, skb);
- pTDInfo->skb_dma = 0;
pTDInfo->skb = NULL;
- pTDInfo->byFlags = 0;
+ pTDInfo->flags = 0;
}
static void vnt_check_bb_vga(struct vnt_private *priv)
@@ -1180,7 +1159,7 @@
static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- PSTxDesc head_td;
+ struct vnt_tx_desc *head_td;
u32 dma_idx;
unsigned long flags;
@@ -1198,12 +1177,12 @@
head_td = priv->apCurrTD[dma_idx];
- head_td->m_td1TD1.byTCR = 0;
+ head_td->td1.tcr = 0;
- head_td->pTDInfo->skb = skb;
+ head_td->td_info->skb = skb;
if (dma_idx == TYPE_AC0DMA)
- head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB;
+ head_td->td_info->flags = TD_FLAGS_NETIF_SKB;
priv->apCurrTD[dma_idx] = head_td->next;
@@ -1211,26 +1190,22 @@
vnt_generate_fifo_header(priv, dma_idx, head_td, skb);
- if (MACbIsRegBitsOn(priv->PortOffset, MAC_REG_PSCTL, PSCTL_PS))
- MACbPSWakeup(priv->PortOffset);
-
spin_lock_irqsave(&priv->lock, flags);
priv->bPWBitOn = false;
/* Set TSR1 & ReqCount in TxDescHead */
- head_td->m_td1TD1.byTCR |= (TCR_STP | TCR_EDP | EDMSDU);
- head_td->m_td1TD1.wReqCount =
- cpu_to_le16((u16)head_td->pTDInfo->dwReqCount);
+ head_td->td1.tcr |= (TCR_STP | TCR_EDP | EDMSDU);
+ head_td->td1.req_count = cpu_to_le16(head_td->td_info->req_count);
- head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma);
+ head_td->buff_addr = cpu_to_le32(head_td->td_info->buf_dma);
/* Poll Transmit the adapter */
wmb();
- head_td->m_td0TD0.f1Owner = OWNED_BY_NIC;
+ head_td->td0.owner = OWNED_BY_NIC;
wmb(); /* second memory barrier */
- if (head_td->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)
+ if (head_td->td_info->flags & TD_FLAGS_NETIF_SKB)
MACvTransmitAC0(priv->PortOffset);
else
MACvTransmit0(priv->PortOffset);
@@ -1483,8 +1458,9 @@
}
}
- if (changed & BSS_CHANGED_ASSOC && priv->op_mode != NL80211_IFTYPE_AP) {
- if (conf->assoc) {
+ if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) &&
+ priv->op_mode != NL80211_IFTYPE_AP) {
+ if (conf->assoc && conf->beacon_rate) {
CARDbUpdateTSF(priv, conf->beacon_rate->hw_value,
conf->sync_tsf);
@@ -1774,6 +1750,12 @@
return -ENODEV;
}
+ if (dma_set_mask(&pcid->dev, DMA_BIT_MASK(32))) {
+ dev_err(&pcid->dev, ": Failed to set dma 32 bit mask\n");
+ device_free_info(priv);
+ return -ENODEV;
+ }
+
INIT_WORK(&priv->interrupt_work, vnt_interrupt_work);
/* do reset */
@@ -1811,6 +1793,7 @@
ieee80211_hw_set(priv->hw, SIGNAL_DBM);
ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS);
ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS);
+ ieee80211_hw_set(priv->hw, SUPPORTS_PS);
priv->hw->max_signal = 100;
diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c
index b25ee96..e14eed1 100644
--- a/drivers/staging/vt6655/dpc.c
+++ b/drivers/staging/vt6655/dpc.c
@@ -144,7 +144,7 @@
priv->rx_buf_sz, DMA_FROM_DEVICE);
frame_size = le16_to_cpu(curr_rd->m_rd1RD1.wReqCount)
- - cpu_to_le16(curr_rd->m_rd0RD0.wResCount);
+ - le16_to_cpu(curr_rd->m_rd0RD0.wResCount);
if ((frame_size > 2364) || (frame_size < 33)) {
/* Frame Size error drop this packet.*/
diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c
index aed530f..3dfd333 100644
--- a/drivers/staging/vt6655/mac.c
+++ b/drivers/staging/vt6655/mac.c
@@ -186,7 +186,6 @@
{
unsigned char byOrgValue;
- ASSERT(byLoopbackMode < 3);
byLoopbackMode <<= 6;
/* set TCR */
VNSvInPortB(dwIoBase + MAC_REG_TEST, &byOrgValue);
@@ -374,7 +373,6 @@
break;
}
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x10);
pr_debug(" DBG_PORT80(0x10)\n");
return false;
}
@@ -384,7 +382,6 @@
break;
}
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x11);
pr_debug(" DBG_PORT80(0x11)\n");
return false;
}
@@ -398,7 +395,6 @@
break;
}
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x12);
pr_debug(" DBG_PORT80(0x12)\n");
return false;
}
@@ -436,7 +432,6 @@
break;
}
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x20);
pr_debug(" DBG_PORT80(0x20)\n");
return false;
}
@@ -446,7 +441,6 @@
break;
}
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x21);
pr_debug(" DBG_PORT80(0x21)\n");
return false;
}
@@ -461,7 +455,6 @@
break;
}
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x24);
pr_debug(" DBG_PORT80(0x24)\n");
return false;
}
@@ -486,13 +479,11 @@
MACvRegBitsOff(dwIoBase, MAC_REG_TCR, TCR_AUTOBCNTX);
if (!MACbSafeRxOff(dwIoBase)) {
- DBG_PORT80(0xA1);
pr_debug(" MACbSafeRxOff == false)\n");
MACbSafeSoftwareReset(dwIoBase);
return false;
}
if (!MACbSafeTxOff(dwIoBase)) {
- DBG_PORT80(0xA2);
pr_debug(" MACbSafeTxOff == false)\n");
MACbSafeSoftwareReset(dwIoBase);
return false;
@@ -590,9 +581,6 @@
break;
}
- if (ww == W_MAX_TIMEOUT)
- DBG_PORT80(0x13);
-
VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR0, dwCurrDescAddr);
if (byOrgDMACtl & DMACTL_RUN)
VNSvOutPortB(dwIoBase + MAC_REG_RXDMACTL0, DMACTL_RUN);
@@ -627,8 +615,6 @@
if (!(byData & DMACTL_RUN))
break;
}
- if (ww == W_MAX_TIMEOUT)
- DBG_PORT80(0x14);
VNSvOutPortD(dwIoBase + MAC_REG_RXDMAPTR1, dwCurrDescAddr);
if (byOrgDMACtl & DMACTL_RUN)
@@ -666,8 +652,6 @@
if (!(byData & DMACTL_RUN))
break;
}
- if (ww == W_MAX_TIMEOUT)
- DBG_PORT80(0x25);
VNSvOutPortD(dwIoBase + MAC_REG_TXDMAPTR0, dwCurrDescAddr);
if (byOrgDMACtl & DMACTL_RUN)
@@ -706,7 +690,6 @@
break;
}
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x26);
pr_debug(" DBG_PORT80(0x26)\n");
}
VNSvOutPortD(dwIoBase + MAC_REG_AC0DMAPTR, dwCurrDescAddr);
@@ -807,7 +790,6 @@
break;
}
if (ww == W_MAX_TIMEOUT) {
- DBG_PORT80(0x36);
pr_debug(" DBG_PORT80(0x33)\n");
return false;
}
diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c
index be3c4e9..06e6b9d 100644
--- a/drivers/staging/vt6655/power.c
+++ b/drivers/staging/vt6655/power.c
@@ -157,10 +157,18 @@
struct ieee80211_conf *conf = &hw->conf;
bool bWakeUp = false;
- if (conf->listen_interval == 1) {
- /* Turn on wake up to listen next beacon */
- MACvRegBitsOn(pDevice->PortOffset, MAC_REG_PSCTL, PSCTL_LNBCN);
- bWakeUp = true;
+ if (conf->listen_interval > 1) {
+ if (!pDevice->wake_up_count)
+ pDevice->wake_up_count = conf->listen_interval;
+
+ --pDevice->wake_up_count;
+
+ if (pDevice->wake_up_count == 1) {
+ /* Turn on wake up to listen next beacon */
+ MACvRegBitsOn(pDevice->PortOffset,
+ MAC_REG_PSCTL, PSCTL_LNBCN);
+ bWakeUp = true;
+ }
}
return bWakeUp;
diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c
index 7626f63..c537321 100644
--- a/drivers/staging/vt6655/rf.c
+++ b/drivers/staging/vt6655/rf.c
@@ -39,66 +39,66 @@
#include "rf.h"
#include "baseband.h"
-#define BY_AL2230_REG_LEN 23 //24bit
+#define BY_AL2230_REG_LEN 23 /* 24bit */
#define CB_AL2230_INIT_SEQ 15
-#define SWITCH_CHANNEL_DELAY_AL2230 200 //us
+#define SWITCH_CHANNEL_DELAY_AL2230 200 /* us */
#define AL2230_PWR_IDX_LEN 64
-#define BY_AL7230_REG_LEN 23 //24bit
+#define BY_AL7230_REG_LEN 23 /* 24bit */
#define CB_AL7230_INIT_SEQ 16
-#define SWITCH_CHANNEL_DELAY_AL7230 200 //us
+#define SWITCH_CHANNEL_DELAY_AL7230 200 /* us */
#define AL7230_PWR_IDX_LEN 64
static const unsigned long dwAL2230InitTable[CB_AL2230_INIT_SEQ] = {
- 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x00FFF300+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x0F4DC500+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x0805B600+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x0146C700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x00068800+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x0403B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x00DBBA00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
- 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, //
+ 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x01A00200+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x00FFF300+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x0005A400+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x0F4DC500+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x0805B600+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x0146C700+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x00068800+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x0403B900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x00DBBA00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
+ 0x00099B00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
0x0BDFFC00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
0x00000D00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW,
0x00580F00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
};
static const unsigned long dwAL2230ChannelTable0[CB_MAX_CHANNEL] = {
- 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
- 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
- 0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
- 0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
- 0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
- 0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
- 0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
- 0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
- 0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
- 0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
- 0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
- 0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
- 0x03F7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
- 0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW // channel = 14, Tf = 2412M
+ 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
+ 0x03F79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
+ 0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
+ 0x03E79000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
+ 0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
+ 0x03F7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
+ 0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
+ 0x03E7A000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
+ 0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
+ 0x03F7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
+ 0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
+ 0x03E7B000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
+ 0x03F7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
+ 0x03E7C000+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 14, Tf = 2412M */
};
static const unsigned long dwAL2230ChannelTable1[CB_MAX_CHANNEL] = {
- 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
- 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
- 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
- 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
- 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
- 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
- 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
- 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
- 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
- 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
- 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
- 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
- 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
- 0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW // channel = 14, Tf = 2412M
+ 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
+ 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
+ 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
+ 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
+ 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
+ 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
+ 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
+ 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
+ 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
+ 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
+ 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
+ 0x0B333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
+ 0x03333100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
+ 0x06666100+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 14, Tf = 2412M */
};
static unsigned long dwAL2230PowerTable[AL2230_PWR_IDX_LEN] = {
@@ -168,240 +168,240 @@
0x0407F900+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW
};
-// 40MHz reference frequency
-// Need to Pull PLLON(PE3) low when writing channel registers through 3-wire.
+/* 40MHz reference frequency
+ * Need to Pull PLLON(PE3) low when writing channel registers through 3-wire.*/
static const unsigned long dwAL7230InitTable[CB_AL7230_INIT_SEQ] = {
- 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
- 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel1 // Need modify for 11a
- 0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 451FE2
- 0x3FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 5FDFA3
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11b/g // Need modify for 11a
- // RoberYu:20050113, Rev0.47 Regsiter Setting Guide
- 0x802B5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 8D1B55
+ 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */
+ 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel1 // Need modify for 11a */
+ 0x841FF200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 451FE2 */
+ 0x3FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 5FDFA3 */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* 11b/g // Need modify for 11a */
+ /* RoberYu:20050113, Rev0.47 Regsiter Setting Guide */
+ 0x802B5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 8D1B55 */
0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
- 0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 860207
+ 0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 860207 */
0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
- 0xE0000A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: E0600A
- 0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10)
- // RoberYu:20050113, Rev0.47 Regsiter Setting Guide
- 0x000A3C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11a: 00143C
+ 0xE0000A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: E0600A */
+ 0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */
+ /* RoberYu:20050113, Rev0.47 Regsiter Setting Guide */
+ 0x000A3C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11a: 00143C */
0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
- 0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // Need modify for 11a: 12BACF
+ 0x1ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* Need modify for 11a: 12BACF */
};
static const unsigned long dwAL7230InitTableAMode[CB_AL7230_INIT_SEQ] = {
- 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Channel184 // Need modify for 11b/g
- 0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
- 0x5FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
- 0x67F78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // 11a // Need modify for 11b/g
- 0x853F5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g, RoberYu:20050113
+ 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Channel184 // Need modify for 11b/g */
+ 0x451FE200+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
+ 0x5FDFA300+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
+ 0x67F78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* 11a // Need modify for 11b/g */
+ 0x853F5500+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g, RoberYu:20050113 */
0x56AF3600+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
- 0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
+ 0xCE020700+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
0x6EBC0800+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
0x221BB900+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
- 0xE0600A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
- 0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10)
- 0x00147C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // Need modify for 11b/g
+ 0xE0600A00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
+ 0x08031B00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* init 0x080B1B00 => 0x080F1B00 for 3 wire control TxGain(D10) */
+ 0x00147C00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* Need modify for 11b/g */
0xFFFFFD00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
0x00000E00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW,
- 0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // Need modify for 11b/g
+ 0x12BACF00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* Need modify for 11b/g */
};
static const unsigned long dwAL7230ChannelTable0[CB_MAX_CHANNEL] = {
- 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
- 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
- 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
- 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
- 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
- 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
- 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
- 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49
- 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49
- 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49
- 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49
- 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49
- 0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49
- 0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
+ 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
+ 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
+ 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
+ 0x00379000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
+ 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
+ 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
+ 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
+ 0x0037A000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz //RobertYu: 20050218, update for APNode 0.49 */
+ 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz //RobertYu: 20050218, update for APNode 0.49 */
+ 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz //RobertYu: 20050218, update for APNode 0.49 */
+ 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz //RobertYu: 20050218, update for APNode 0.49 */
+ 0x0037B000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz //RobertYu: 20050218, update for APNode 0.49 */
+ 0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz //RobertYu: 20050218, update for APNode 0.49 */
+ 0x0037C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */
- // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22)
- 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
- 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
- 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
- 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
- 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
- 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
- 0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
- 0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
+ /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) */
+ 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */
+ 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */
+ 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */
+ 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */
+ 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */
+ 0x0FF52000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */
+ 0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */
+ 0x0FF53000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */
- // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
- // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56)
+ /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
+ * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) */
- 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 5035MHz (23)
- 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 5040MHz (24)
- 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 5045MHz (25)
- 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 5055MHz (26)
- 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 5060MHz (27)
- 0x0FF55000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 16, Tf = 5080MHz (28)
- 0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 34, Tf = 5170MHz (29)
- 0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 36, Tf = 5180MHz (30)
- 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49
- 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 40, Tf = 5200MHz (32)
- 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 42, Tf = 5210MHz (33)
- 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 44, Tf = 5220MHz (34)
- 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 46, Tf = 5230MHz (35)
- 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 48, Tf = 5240MHz (36)
- 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 52, Tf = 5260MHz (37)
- 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 56, Tf = 5280MHz (38)
- 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 60, Tf = 5300MHz (39)
- 0x0FF59000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 64, Tf = 5320MHz (40)
+ 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */
+ 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */
+ 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */
+ 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */
+ 0x0FF54000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */
+ 0x0FF55000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */
+ 0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */
+ 0x0FF56000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */
+ 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) //RobertYu: 20050218, update for APNode 0.49 */
+ 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */
+ 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */
+ 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */
+ 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */
+ 0x0FF57000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */
+ 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */
+ 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */
+ 0x0FF58000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */
+ 0x0FF59000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */
- 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
- 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
- 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
- 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
- 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
- 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
- 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
- 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
- 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
- 0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
- 0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
- 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
- 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
- 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
- 0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
- 0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // channel = 165, Tf = 5825MHz (56)
+ 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */
+ 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */
+ 0x0FF5C000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */
+ 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */
+ 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */
+ 0x0FF5D000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */
+ 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */
+ 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */
+ 0x0FF5E000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */
+ 0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */
+ 0x0FF5F000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */
+ 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */
+ 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */
+ 0x0FF60000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */
+ 0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */
+ 0x0FF61000+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */
};
static const unsigned long dwAL7230ChannelTable1[CB_MAX_CHANNEL] = {
- 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
- 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
- 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
- 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
- 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
- 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
- 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
- 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
- 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
- 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
- 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
- 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
- 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
- 0x06666100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
+ 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
+ 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
+ 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
+ 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
+ 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
+ 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
+ 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
+ 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
+ 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
+ 0x1B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
+ 0x03333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
+ 0x0B333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
+ 0x13333100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
+ 0x06666100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */
- // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22)
- 0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
- 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
- 0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
- 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
- 0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
- 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
+ /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) */
+ 0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */
+ 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */
+ 0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */
+ 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */
+ 0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */
+ 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */
- // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
- // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56)
- 0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 5035MHz (23)
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 5040MHz (24)
- 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 5045MHz (25)
- 0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 5055MHz (26)
- 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 5060MHz (27)
- 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 16, Tf = 5080MHz (28)
- 0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 34, Tf = 5170MHz (29)
- 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 36, Tf = 5180MHz (30)
- 0x10000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 38, Tf = 5190MHz (31)
- 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 40, Tf = 5200MHz (32)
- 0x1AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 42, Tf = 5210MHz (33)
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 44, Tf = 5220MHz (34)
- 0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 46, Tf = 5230MHz (35)
- 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 48, Tf = 5240MHz (36)
- 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 52, Tf = 5260MHz (37)
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 56, Tf = 5280MHz (38)
- 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 60, Tf = 5300MHz (39)
- 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 64, Tf = 5320MHz (40)
- 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
- 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
- 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
- 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
- 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
- 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
- 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
- 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
- 0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
- 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
- 0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
- 0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
- 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // channel = 165, Tf = 5825MHz (56)
+ /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
+ * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) */
+ 0x1D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */
+ 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */
+ 0x08000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */
+ 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */
+ 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */
+ 0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */
+ 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */
+ 0x10000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */
+ 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */
+ 0x1AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */
+ 0x05555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */
+ 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */
+ 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */
+ 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */
+ 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */
+ 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */
+ 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */
+ 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */
+ 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */
+ 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */
+ 0x0AAAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */
+ 0x15555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */
+ 0x00000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */
+ 0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */
+ 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */
+ 0x0D555100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */
+ 0x18000100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */
+ 0x02AAA100+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */
};
static const unsigned long dwAL7230ChannelTable2[CB_MAX_CHANNEL] = {
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 1, Tf = 2412MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 2, Tf = 2417MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 3, Tf = 2422MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 4, Tf = 2427MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 5, Tf = 2432MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 6, Tf = 2437MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 2442MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 2447MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 2452MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 10, Tf = 2457MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 2462MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 2467MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 13, Tf = 2472MHz
- 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 14, Tf = 2484MHz
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
+ 0x7FD78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 14, Tf = 2484MHz */
- // 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 183, Tf = 4915MHz (15)
- 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 184, Tf = 4920MHz (16)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 185, Tf = 4925MHz (17)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 187, Tf = 4935MHz (18)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 188, Tf = 4940MHz (19)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 189, Tf = 4945MHz (20)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 192, Tf = 4960MHz (21)
- 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 196, Tf = 4980MHz (22)
+ /* 4.9G => Ch 183, 184, 185, 187, 188, 189, 192, 196 (Value:15 ~ 22) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 183, Tf = 4915MHz (15) */
+ 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 184, Tf = 4920MHz (16) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 185, Tf = 4925MHz (17) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 187, Tf = 4935MHz (18) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 188, Tf = 4940MHz (19) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 189, Tf = 4945MHz (20) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 192, Tf = 4960MHz (21) */
+ 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 196, Tf = 4980MHz (22) */
- // 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
- // 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 7, Tf = 5035MHz (23)
- 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 8, Tf = 5040MHz (24)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 9, Tf = 5045MHz (25)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 11, Tf = 5055MHz (26)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 12, Tf = 5060MHz (27)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 16, Tf = 5080MHz (28)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 34, Tf = 5170MHz (29)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 36, Tf = 5180MHz (30)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 38, Tf = 5190MHz (31)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 40, Tf = 5200MHz (32)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 42, Tf = 5210MHz (33)
- 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 44, Tf = 5220MHz (34)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 46, Tf = 5230MHz (35)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 48, Tf = 5240MHz (36)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 52, Tf = 5260MHz (37)
- 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 56, Tf = 5280MHz (38)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 60, Tf = 5300MHz (39)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 64, Tf = 5320MHz (40)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 100, Tf = 5500MHz (41)
- 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 104, Tf = 5520MHz (42)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 108, Tf = 5540MHz (43)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 112, Tf = 5560MHz (44)
- 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 116, Tf = 5580MHz (45)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 120, Tf = 5600MHz (46)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 124, Tf = 5620MHz (47)
- 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 128, Tf = 5640MHz (48)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 132, Tf = 5660MHz (49)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 136, Tf = 5680MHz (50)
- 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 140, Tf = 5700MHz (51)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 149, Tf = 5745MHz (52)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 153, Tf = 5765MHz (53)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 157, Tf = 5785MHz (54)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, // channel = 161, Tf = 5805MHz (55)
- 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW // channel = 165, Tf = 5825MHz (56)
+ /* 5G => Ch 7, 8, 9, 11, 12, 16, 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64,
+ * 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165 (Value 23 ~ 56) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 7, Tf = 5035MHz (23) */
+ 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 8, Tf = 5040MHz (24) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 9, Tf = 5045MHz (25) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 11, Tf = 5055MHz (26) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 12, Tf = 5060MHz (27) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 16, Tf = 5080MHz (28) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 34, Tf = 5170MHz (29) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 36, Tf = 5180MHz (30) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 38, Tf = 5190MHz (31) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 40, Tf = 5200MHz (32) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 42, Tf = 5210MHz (33) */
+ 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 44, Tf = 5220MHz (34) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 46, Tf = 5230MHz (35) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 48, Tf = 5240MHz (36) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 52, Tf = 5260MHz (37) */
+ 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 56, Tf = 5280MHz (38) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 60, Tf = 5300MHz (39) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 64, Tf = 5320MHz (40) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 100, Tf = 5500MHz (41) */
+ 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 104, Tf = 5520MHz (42) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 108, Tf = 5540MHz (43) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 112, Tf = 5560MHz (44) */
+ 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 116, Tf = 5580MHz (45) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 120, Tf = 5600MHz (46) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 124, Tf = 5620MHz (47) */
+ 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 128, Tf = 5640MHz (48) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 132, Tf = 5660MHz (49) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 136, Tf = 5680MHz (50) */
+ 0x67D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 140, Tf = 5700MHz (51) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 149, Tf = 5745MHz (52) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 153, Tf = 5765MHz (53) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 157, Tf = 5785MHz (54) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW, /* channel = 161, Tf = 5805MHz (55) */
+ 0x77D78400+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW /* channel = 165, Tf = 5825MHz (56) */
};
/*
@@ -438,13 +438,13 @@
MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
/* Calibration */
- MACvTimer0MicroSDelay(dwIoBase, 150);//150us
+ MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */
/* TXDCOC:active, RCK:disable */
bResult &= IFRFbWriteEmbedded(priv, (0x9ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW));
- MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+ MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
/* TXDCOC:disable, RCK:active */
bResult &= IFRFbWriteEmbedded(priv, (0x3ABA8F00+(BY_AL7230_REG_LEN<<3)+IFREGCTL_REGW));
- MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+ MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
/* TXDCOC:disable, RCK:disable */
bResult &= IFRFbWriteEmbedded(priv, dwAL7230InitTable[CB_AL7230_INIT_SEQ-1]);
@@ -457,7 +457,7 @@
/* PE1: TX_ON, PE2: RX_ON, PE3: PLLON */
/* 3-wire control for power saving mode */
- VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000
+ VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */
return bResult;
}
@@ -557,16 +557,16 @@
for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++)
bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[ii]);
- MACvTimer0MicroSDelay(dwIoBase, 30); //delay 30 us
+ MACvTimer0MicroSDelay(dwIoBase, 30); /* delay 30 us */
/* PLL On */
MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
- MACvTimer0MicroSDelay(dwIoBase, 150);//150us
+ MACvTimer0MicroSDelay(dwIoBase, 150);/* 150us */
bResult &= IFRFbWriteEmbedded(priv, (0x00d80f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
- MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+ MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
bResult &= IFRFbWriteEmbedded(priv, (0x00780f00+(BY_AL2230_REG_LEN<<3)+IFREGCTL_REGW));
- MACvTimer0MicroSDelay(dwIoBase, 30);//30us
+ MACvTimer0MicroSDelay(dwIoBase, 30);/* 30us */
bResult &= IFRFbWriteEmbedded(priv, dwAL2230InitTable[CB_AL2230_INIT_SEQ-1]);
MACvWordRegBitsOn(dwIoBase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 |
@@ -575,7 +575,7 @@
SOFTPWRCTL_TXPEINV));
/* 3-wire control for power saving mode */
- VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); //1100 0000
+ VNSvOutPortB(dwIoBase + MAC_REG_PSPWRSIG, (PSSIG_WPE3 | PSSIG_WPE2)); /* 1100 0000 */
return bResult;
}
@@ -661,11 +661,11 @@
case RF_AL2230S:
bResult = RFbAL2230SelectChannel(priv, byChannel);
break;
- //{{ RobertYu: 20050104
+ /*{{ RobertYu: 20050104 */
case RF_AIROHA7230:
bResult = s_bAL7230SelectChannel(priv, byChannel);
break;
- //}} RobertYu
+ /*}} RobertYu */
case RF_NOTHING:
bResult = true;
break;
diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h
index 2ea21e2..b5fc3ee 100644
--- a/drivers/staging/vt6655/rf.h
+++ b/drivers/staging/vt6655/rf.h
@@ -33,18 +33,18 @@
#include "device.h"
/*--------------------- Export Definitions -------------------------*/
-//
-// Baseband RF pair definition in eeprom (Bits 6..0)
-//
+/*
+ * Baseband RF pair definition in eeprom (Bits 6..0)
+*/
#define RF_RFMD2959 0x01
#define RF_MAXIMAG 0x02
#define RF_AIROHA 0x03
#define RF_UW2451 0x05
#define RF_MAXIMG 0x06
-#define RF_MAXIM2829 0x07 // RobertYu: 20041118
-#define RF_UW2452 0x08 // RobertYu: 20041210
-#define RF_AIROHA7230 0x0a // RobertYu: 20050104
+#define RF_MAXIM2829 0x07 /* RobertYu: 20041118 */
+#define RF_UW2452 0x08 /* RobertYu: 20041210 */
+#define RF_AIROHA7230 0x0a /* RobertYu: 20050104 */
#define RF_UW2453 0x0b
#define RF_VT3226 0x09
@@ -63,9 +63,9 @@
#define ZONE_MKK 6
#define ZONE_ISRAEL 7
-//[20050104] CB_MAXIM2829_CHANNEL_5G_HIGH, CB_UW2452_CHANNEL_5G_HIGH: 40==>41
-#define CB_MAXIM2829_CHANNEL_5G_HIGH 41 //Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1
-#define CB_UW2452_CHANNEL_5G_HIGH 41 //[20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3
+/* [20050104] CB_MAXIM2829_CHANNEL_5G_HIGH, CB_UW2452_CHANNEL_5G_HIGH: 40==>41 */
+#define CB_MAXIM2829_CHANNEL_5G_HIGH 41 /* Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1 */
+#define CB_UW2452_CHANNEL_5G_HIGH 41 /* [20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3 */
/*--------------------- Export Classes ----------------------------*/
@@ -93,8 +93,8 @@
long *pldBm
);
-//{{ RobertYu: 20050104
+/* {{ RobertYu: 20050104 */
bool RFbAL7230SelectChannelPostProcess(struct vnt_private *, u16, u16);
-//}} RobertYu
+/* }} RobertYu */
-#endif // __RF_H__
+#endif /* __RF_H__ */
diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c
index 534338c..5875d65 100644
--- a/drivers/staging/vt6655/rxtx.c
+++ b/drivers/staging/vt6655/rxtx.c
@@ -130,7 +130,7 @@
static unsigned int
s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
unsigned char *pbyTxBufferAddr,
- unsigned int uDMAIdx, PSTxDesc pHeadTD,
+ unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD,
unsigned int uNodeIndex);
static
@@ -387,7 +387,6 @@
break;
}
- ASSERT(false);
return 0;
}
@@ -1028,10 +1027,10 @@
static unsigned int
s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
unsigned char *pbyTxBufferAddr,
- unsigned int uDMAIdx, PSTxDesc pHeadTD,
+ unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD,
unsigned int is_pspoll)
{
- PDEVICE_TD_INFO td_info = pHeadTD->pTDInfo;
+ struct vnt_td_info *td_info = pHeadTD->td_info;
struct sk_buff *skb = td_info->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -1048,7 +1047,7 @@
unsigned int cbReqCount = 0;
bool bNeedACK = (bool)(fifo_ctl & FIFOCTL_NEEDACK);
bool bRTS = (bool)(fifo_ctl & FIFOCTL_RTS);
- PSTxDesc ptdCurr;
+ struct vnt_tx_desc *ptdCurr;
unsigned int cbHeaderLength = 0;
void *pvRrvTime;
struct vnt_mic_hdr *pMICHDR;
@@ -1089,7 +1088,7 @@
/* Set RrvTime/RTS/CTS Buffer */
- wTxBufSize = sizeof(STxBufHead);
+ wTxBufSize = sizeof(struct vnt_tx_fifo_head);
if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {/* 802.11g packet */
if (byFBOption == AUTO_FB_NONE) {
@@ -1193,17 +1192,15 @@
hdr->duration_id = uDuration;
cbReqCount = cbHeaderLength + uPadding + skb->len;
- pbyBuffer = (unsigned char *)pHeadTD->pTDInfo->buf;
+ pbyBuffer = (unsigned char *)pHeadTD->td_info->buf;
uLength = cbHeaderLength + uPadding;
/* Copy the Packet into a tx Buffer */
memcpy((pbyBuffer + uLength), skb->data, skb->len);
- ptdCurr = (PSTxDesc)pHeadTD;
+ ptdCurr = pHeadTD;
- ptdCurr->pTDInfo->dwReqCount = cbReqCount;
- ptdCurr->pTDInfo->dwHeaderLength = cbHeaderLength;
- ptdCurr->pTDInfo->skb_dma = ptdCurr->pTDInfo->buf_dma;
+ ptdCurr->td_info->req_count = (u16)cbReqCount;
return cbHeaderLength;
}
@@ -1276,9 +1273,9 @@
}
int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
- PSTxDesc head_td, struct sk_buff *skb)
+ struct vnt_tx_desc *head_td, struct sk_buff *skb)
{
- PDEVICE_TD_INFO td_info = head_td->pTDInfo;
+ struct vnt_td_info *td_info = head_td->td_info;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
struct ieee80211_rate *rate;
diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h
index b9bd163..1e30ecb 100644
--- a/drivers/staging/vt6655/rxtx.h
+++ b/drivers/staging/vt6655/rxtx.h
@@ -192,9 +192,9 @@
} __packed;
int vnt_generate_fifo_header(struct vnt_private *, u32,
- PSTxDesc head_td, struct sk_buff *);
+ struct vnt_tx_desc *head_td, struct sk_buff *);
int vnt_beacon_make(struct vnt_private *, struct ieee80211_vif *);
int vnt_beacon_enable(struct vnt_private *, struct ieee80211_vif *,
struct ieee80211_bss_conf *);
-#endif // __RXTX_H__
+#endif /* __RXTX_H__ */
diff --git a/drivers/staging/vt6655/upc.h b/drivers/staging/vt6655/upc.h
index cc63dc8..85fe046 100644
--- a/drivers/staging/vt6655/upc.h
+++ b/drivers/staging/vt6655/upc.h
@@ -37,35 +37,23 @@
/* For memory mapped IO */
-#define VNSvInPortB(dwIOAddress, pbyData) \
-do { \
- *(pbyData) = ioread8(dwIOAddress); \
-} while (0)
+#define VNSvInPortB(dwIOAddress, pbyData) \
+ (*(pbyData) = ioread8(dwIOAddress))
-#define VNSvInPortW(dwIOAddress, pwData) \
-do { \
- *(pwData) = ioread16(dwIOAddress); \
-} while (0)
+#define VNSvInPortW(dwIOAddress, pwData) \
+ (*(pwData) = ioread16(dwIOAddress))
-#define VNSvInPortD(dwIOAddress, pdwData) \
-do { \
- *(pdwData) = ioread32(dwIOAddress); \
-} while (0)
+#define VNSvInPortD(dwIOAddress, pdwData) \
+ (*(pdwData) = ioread32(dwIOAddress))
-#define VNSvOutPortB(dwIOAddress, byData) \
-do { \
- iowrite8((u8)byData, dwIOAddress); \
-} while (0)
+#define VNSvOutPortB(dwIOAddress, byData) \
+ iowrite8((u8)(byData), dwIOAddress)
-#define VNSvOutPortW(dwIOAddress, wData) \
-do { \
- iowrite16((u16)wData, dwIOAddress); \
-} while (0)
+#define VNSvOutPortW(dwIOAddress, wData) \
+ iowrite16((u16)(wData), dwIOAddress)
-#define VNSvOutPortD(dwIOAddress, dwData) \
-do { \
- iowrite32((u32)dwData, dwIOAddress); \
-} while (0)
+#define VNSvOutPortD(dwIOAddress, dwData) \
+ iowrite32((u32)(dwData), dwIOAddress)
#define PCAvDelayByIO(uDelayUnit) \
do { \
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
index 8116791..da075f4 100644
--- a/drivers/staging/vt6656/rxtx.c
+++ b/drivers/staging/vt6656/rxtx.c
@@ -45,8 +45,11 @@
#include "usbpipe.h"
static const u16 vnt_time_stampoff[2][MAX_RATE] = {
- {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23},/* Long Preamble */
- {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23},/* Short Preamble */
+ /* Long Preamble */
+ {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23},
+
+ /* Short Preamble */
+ {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23},
};
static const u16 vnt_fb_opt0[2][5] = {
diff --git a/drivers/staging/wilc1000/Kconfig b/drivers/staging/wilc1000/Kconfig
index 062d9c5..51bbf46 100644
--- a/drivers/staging/wilc1000/Kconfig
+++ b/drivers/staging/wilc1000/Kconfig
@@ -37,17 +37,26 @@
bool "SDIO support"
depends on MMC
---help---
- This module adds support for the SDIO interface
- of adapters using WILC chipset. Select this if
- your platform is using the SDIO bus.
+ This module adds support for the SDIO interface of adapters using
+ WILC1000 chipset. The Atmel WILC1000 SDIO is a full speed interface.
+ It meets SDIO card specification version 2.0. The interface supports
+ the 1-bit/4-bit SD transfer mode at the clock range of 0-50 MHz.
+ The host can use this interface to read and write from any register
+ within the chip as well as configure the WILC1000 for data DMA.
+ To use this interface, pin9 (SDIO_SPI_CFG) must be grounded. Select
+ this if your platform is using the SDIO bus.
config WILC1000_SPI
depends on SPI
bool "SPI support"
---help---
- This module adds support for the SPI interface
- of adapters using WILC chipset. Select this if
- your platform is using the SPI bus.
+ This module adds support for the SPI interface of adapters using
+ WILC1000 chipset. The Atmel WILC1000 has a Serial Peripheral
+ Interface (SPI) that operates as a SPI slave. This SPI interface can
+ be used for control and for serial I/O of 802.11 data. The SPI is a
+ full-duplex slave synchronous serial interface that is available
+ immediately following reset when pin 9 (SDIO_SPI_CFG) is tied to
+ VDDIO. Select this if your platform is using the SPI bus.
endchoice
config WILC1000_HW_OOB_INTR
@@ -55,5 +64,8 @@
depends on WILC1000 && WILC1000_SDIO
default n
---help---
- If your platform don't recognize SDIO IRQ, connect chipset external IRQ pin
- and check this option. Or, Use this to get all interrupts including SDIO interrupts.
+ This option enables out-of-band interrupt support for the WILC1000
+ chipset. This OOB interrupt is intended to provide a faster interrupt
+ mechanism for SDIO host controllers that don't support SDIO interrupt.
+ Select this option If the SDIO host controller in your platform
+ doesn't support SDIO time devision interrupt.
diff --git a/drivers/staging/wilc1000/Makefile b/drivers/staging/wilc1000/Makefile
index a78c4d5..6be8a92 100644
--- a/drivers/staging/wilc1000/Makefile
+++ b/drivers/staging/wilc1000/Makefile
@@ -25,10 +25,10 @@
ccflags-$(CONFIG_WILC1000_DYNAMICALLY_ALLOCATE_MEMROY) += -DWILC_NORMAL_ALLOC
-wilc1000-objs := wilc_wfi_netdevice.o wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \
- wilc_memory.o wilc_msgqueue.o wilc_sleep.o wilc_strutils.o \
- wilc_timer.o coreconfigurator.o host_interface.o \
- fifo_buffer.o wilc_sdio.o wilc_spi.o wilc_wlan_cfg.o wilc_debugfs.o
+wilc1000-objs := wilc_wfi_cfgoperations.o linux_wlan.o linux_mon.o \
+ wilc_memory.o wilc_msgqueue.o \
+ coreconfigurator.o host_interface.o \
+ wilc_sdio.o wilc_spi.o wilc_wlan_cfg.o wilc_debugfs.o
wilc1000-$(CONFIG_WILC1000_SDIO) += linux_wlan_sdio.o
wilc1000-$(CONFIG_WILC1000_SPI) += linux_wlan_spi.o
diff --git a/drivers/staging/wilc1000/coreconfigsimulator.h b/drivers/staging/wilc1000/coreconfigsimulator.h
deleted file mode 100644
index 5e01f8e..0000000
--- a/drivers/staging/wilc1000/coreconfigsimulator.h
+++ /dev/null
@@ -1,17 +0,0 @@
-
-/*!
- * @file coreconfigsimulator.h
- * @brief
- * @author
- * @sa coreconfigsimulator.c
- * @date 1 Mar 2012
- * @version 1.0
- */
-
-#ifndef CORECONFIGSIMULATOR_H
-#define CORECONFIGSIMULATOR_H
-
-extern s32 CoreConfigSimulatorInit(void);
-extern s32 CoreConfigSimulatorDeInit(void);
-
-#endif
diff --git a/drivers/staging/wilc1000/coreconfigurator.c b/drivers/staging/wilc1000/coreconfigurator.c
index ed6ac45..16a0abc 100644
--- a/drivers/staging/wilc1000/coreconfigurator.c
+++ b/drivers/staging/wilc1000/coreconfigurator.c
@@ -167,7 +167,6 @@
static struct semaphore SemHandleSendPkt;
static struct semaphore SemHandlePktResp;
-static s8 *gps8ConfigPacket;
static tstrConfigPktInfo gstrConfigPktInfo;
@@ -544,21 +543,21 @@
/* header and updates the MAC Address in the allocated 'addr' variable. */
INLINE void get_address1(u8 *pu8msa, u8 *addr)
{
- WILC_memcpy(addr, pu8msa + 4, 6);
+ 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. */
INLINE void get_address2(u8 *pu8msa, u8 *addr)
{
- WILC_memcpy(addr, pu8msa + 10, 6);
+ 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. */
INLINE void get_address3(u8 *pu8msa, u8 *addr)
{
- WILC_memcpy(addr, pu8msa + 16, 6);
+ memcpy(addr, pu8msa + 16, 6);
}
/* This function extracts the BSSID from the incoming WLAN packet based on */
@@ -605,7 +604,7 @@
{
u16 cap_info = 0;
u16 index = MAC_HDR_LEN;
- tenuFrmSubtype st = BEACON;
+ tenuFrmSubtype st;
st = get_sub_type(data);
@@ -674,17 +673,8 @@
sema_init(&SemHandleSendPkt, 1);
sema_init(&SemHandlePktResp, 0);
- gps8ConfigPacket = (s8 *)WILC_MALLOC(MAX_PACKET_BUFF_SIZE);
- if (gps8ConfigPacket == NULL) {
- PRINT_ER("failed in gps8ConfigPacket allocation\n");
- s32Error = WILC_NO_MEM;
- goto _fail_;
- }
- WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE);
-
- WILC_memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
-_fail_:
+ memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
return s32Error;
}
@@ -706,11 +696,10 @@
/* Search for the TIM Element Field and return if the element is found */
while (u16index < (u16RxLen - FCS_LEN)) {
- if (pu8msa[u16index] == ITIM) {
+ if (pu8msa[u16index] == ITIM)
return &pu8msa[u16index];
- } else {
+ else
u16index += (IE_HDR_LEN + pu8msa[u16index + 1]);
- }
}
return 0;
@@ -811,8 +800,11 @@
u32 u32Tsf_Lo;
u32 u32Tsf_Hi;
- pstrNetworkInfo = (tstrNetworkInfo *)WILC_MALLOC(sizeof(tstrNetworkInfo));
- WILC_memset((void *)(pstrNetworkInfo), 0, sizeof(tstrNetworkInfo));
+ pstrNetworkInfo = kmalloc(sizeof(tstrNetworkInfo), GFP_KERNEL);
+ if (!pstrNetworkInfo)
+ return -ENOMEM;
+
+ memset((void *)(pstrNetworkInfo), 0, sizeof(tstrNetworkInfo));
pstrNetworkInfo->s8rssi = pu8WidVal[0];
@@ -855,17 +847,19 @@
/* Get DTIM Period */
pu8TimElm = get_tim_elm(pu8msa, (u16RxLen + FCS_LEN), u8index);
- if (pu8TimElm != 0) {
+ if (pu8TimElm != 0)
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 = (u8 *)WILC_MALLOC(u16IEsLen);
- WILC_memset((void *)(pstrNetworkInfo->pu8IEs), 0, u16IEsLen);
+ pstrNetworkInfo->pu8IEs = kmalloc(u16IEsLen, GFP_KERNEL);
+ if (!pstrNetworkInfo->pu8IEs)
+ return -ENOMEM;
- WILC_memcpy(pstrNetworkInfo->pu8IEs, pu8IEs, u16IEsLen);
+ memset((void *)(pstrNetworkInfo->pu8IEs), 0, u16IEsLen);
+
+ memcpy(pstrNetworkInfo->pu8IEs, pu8IEs, u16IEsLen);
}
pstrNetworkInfo->u16IEsLen = u16IEsLen;
@@ -893,13 +887,13 @@
if (pstrNetworkInfo != NULL) {
if (pstrNetworkInfo->pu8IEs != NULL) {
- WILC_FREE(pstrNetworkInfo->pu8IEs);
+ kfree(pstrNetworkInfo->pu8IEs);
pstrNetworkInfo->pu8IEs = NULL;
} else {
s32Error = WILC_FAIL;
}
- WILC_FREE(pstrNetworkInfo);
+ kfree(pstrNetworkInfo);
pstrNetworkInfo = NULL;
} else {
@@ -929,8 +923,11 @@
u8 *pu8IEs = 0;
u16 u16IEsLen = 0;
- pstrConnectRespInfo = (tstrConnectRespInfo *)WILC_MALLOC(sizeof(tstrConnectRespInfo));
- WILC_memset((void *)(pstrConnectRespInfo), 0, sizeof(tstrConnectRespInfo));
+ pstrConnectRespInfo = kmalloc(sizeof(tstrConnectRespInfo), GFP_KERNEL);
+ if (!pstrConnectRespInfo)
+ return -ENOMEM;
+
+ memset((void *)(pstrConnectRespInfo), 0, sizeof(tstrConnectRespInfo));
/* u16AssocRespLen = pu8Buffer[0]; */
u16AssocRespLen = (u16)u32BufferLen;
@@ -949,10 +946,13 @@
pu8IEs = &pu8Buffer[CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN];
u16IEsLen = u16AssocRespLen - (CAP_INFO_LEN + STATUS_CODE_LEN + AID_LEN);
- pstrConnectRespInfo->pu8RespIEs = (u8 *)WILC_MALLOC(u16IEsLen);
- WILC_memset((void *)(pstrConnectRespInfo->pu8RespIEs), 0, u16IEsLen);
+ pstrConnectRespInfo->pu8RespIEs = kmalloc(u16IEsLen, GFP_KERNEL);
+ if (!pstrConnectRespInfo->pu8RespIEs)
+ return -ENOMEM;
- WILC_memcpy(pstrConnectRespInfo->pu8RespIEs, pu8IEs, u16IEsLen);
+ memset((void *)(pstrConnectRespInfo->pu8RespIEs), 0, u16IEsLen);
+
+ memcpy(pstrConnectRespInfo->pu8RespIEs, pu8IEs, u16IEsLen);
pstrConnectRespInfo->u16RespIEsLen = u16IEsLen;
}
@@ -978,13 +978,13 @@
if (pstrConnectRespInfo != NULL) {
if (pstrConnectRespInfo->pu8RespIEs != NULL) {
- WILC_FREE(pstrConnectRespInfo->pu8RespIEs);
+ kfree(pstrConnectRespInfo->pu8RespIEs);
pstrConnectRespInfo->pu8RespIEs = NULL;
} else {
s32Error = WILC_FAIL;
}
- WILC_FREE(pstrConnectRespInfo);
+ kfree(pstrConnectRespInfo);
pstrConnectRespInfo = NULL;
} else {
@@ -1018,13 +1018,12 @@
}
}
- pstrSurveyResults = (wid_site_survey_reslts_s *)WILC_MALLOC(u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s));
- if (pstrSurveyResults == NULL) {
- u32SurveyResultsCount = 0;
- WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
+ pstrSurveyResults = kmalloc_array(u32SurveyResultsCount,
+ sizeof(wid_site_survey_reslts_s), GFP_KERNEL);
+ if (!pstrSurveyResults)
+ return -ENOMEM;
- WILC_memset((void *)(pstrSurveyResults), 0, u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s));
+ memset((void *)(pstrSurveyResults), 0, u32SurveyResultsCount * sizeof(wid_site_survey_reslts_s));
u32SurveyResultsCount = 0;
@@ -1039,7 +1038,7 @@
pu8BufferPtr += 2;
for (j = 0; j < u32SurveyBytesLength; j += SURVEY_RESULT_LENGTH) {
- WILC_memcpy(&pstrSurveyResults[u32SurveyResultsCount], pu8BufferPtr, SURVEY_RESULT_LENGTH);
+ memcpy(&pstrSurveyResults[u32SurveyResultsCount], pu8BufferPtr, SURVEY_RESULT_LENGTH);
pu8BufferPtr += SURVEY_RESULT_LENGTH;
u32SurveyResultsCount++;
}
@@ -1058,7 +1057,7 @@
s32 s32Error = WILC_SUCCESS;
if (pstrSurveyResults != NULL) {
- WILC_FREE(pstrSurveyResults);
+ kfree(pstrSurveyResults);
}
return s32Error;
@@ -1334,7 +1333,6 @@
if (g_oper_mode == SET_CFG) {
/* Message Length */
- /* u16MsgLen = WILC_strlen(pu8val); */
u16MsgLen = (u16)s32ValueSize;
/* Length */
@@ -1441,8 +1439,6 @@
void ProcessBinWid(char *pcPacket, s32 *ps32PktLen,
tstrWID *pstrWID, u8 *pu8val, s32 s32ValueSize)
{
- /* WILC_ERROR("processing Binary WIDs is not supported\n"); */
-
u16 u16MsgLen = 0;
u16 idx = 0;
s32 s32PktLen = *ps32PktLen;
@@ -1528,11 +1524,10 @@
u8 cfg_str[256] = {0};
tenuWIDtype enuWIDtype = WID_UNDEF;
- if (process_wid_num) {
+ if (process_wid_num)
enuWIDtype = get_wid_type(g_wid_num);
- } else {
+ else
enuWIDtype = gastrWIDs[cnt].enuWIDtype;
- }
switch (enuWIDtype) {
@@ -1566,18 +1561,10 @@
}
case WID_STR:
- WILC_memcpy(cfg_str, resp + idx, cfg_len);
+ memcpy(cfg_str, resp + idx, cfg_len);
/* cfg_str[cfg_len] = '\0'; //mostafa: no need currently for NULL termination */
- if (process_wid_num) {
- /*fprintf(out_file,"0x%4.4x = %s\n",g_wid_num,
- * cfg_str);*/
- } else {
- /*fprintf(out_file,"%s = %s\n",gastrWIDs[cnt].cfg_switch,
- * cfg_str);*/
- }
-
if (pstrWIDresult->s32ValueSize >= cfg_len) {
- WILC_memcpy(pstrWIDresult->ps8WidVal, cfg_str, cfg_len); /* mostafa: no need currently for the extra NULL byte */
+ memcpy(pstrWIDresult->ps8WidVal, cfg_str, cfg_len); /* mostafa: no need currently for the extra NULL byte */
pstrWIDresult->s32ValueSize = cfg_len;
} else {
PRINT_ER("allocated WID buffer length is smaller than the received WID Length\n");
@@ -1589,15 +1576,8 @@
case WID_ADR:
create_mac_addr(cfg_str, resp + idx);
- WILC_strncpy(pstrWIDresult->ps8WidVal, cfg_str, WILC_strlen(cfg_str));
- pstrWIDresult->ps8WidVal[WILC_strlen(cfg_str)] = '\0';
- if (process_wid_num) {
- /*fprintf(out_file,"0x%4.4x = %s\n",g_wid_num,
- * cfg_str);*/
- } else {
- /*fprintf(out_file,"%s = %s\n",gastrWIDs[cnt].cfg_switch,
- * cfg_str);*/
- }
+ strncpy(pstrWIDresult->ps8WidVal, cfg_str, strlen(cfg_str));
+ pstrWIDresult->ps8WidVal[strlen(cfg_str)] = '\0';
break;
case WID_IP:
@@ -1606,18 +1586,11 @@
MAKE_WORD16(resp[idx + 2], resp[idx + 3])
);
conv_int_to_ip(cfg_str, cfg_int);
- if (process_wid_num) {
- /*fprintf(out_file,"0x%4.4x = %s\n",g_wid_num,
- * cfg_str);*/
- } else {
- /*fprintf(out_file,"%s = %s\n",gastrWIDs[cnt].cfg_switch,
- * cfg_str);*/
- }
break;
case WID_BIN_DATA:
if (pstrWIDresult->s32ValueSize >= cfg_len) {
- WILC_memcpy(pstrWIDresult->ps8WidVal, resp + idx, cfg_len);
+ memcpy(pstrWIDresult->ps8WidVal, resp + idx, cfg_len);
pstrWIDresult->s32ValueSize = cfg_len;
} else {
PRINT_ER("Allocated WID buffer length is smaller than the received WID Length Err(%d)\n", retval);
@@ -1739,7 +1712,6 @@
s32 ParseWriteResponse(u8 *pu8RespBuffer)
{
s32 s32Error = WILC_FAIL;
- u16 u16RespLen = 0;
u16 u16WIDtype = (u16)WID_NIL;
/* Check whether the received frame is a valid response */
@@ -1748,9 +1720,6 @@
return WILC_FAIL;
}
- /* Extract Response Length */
- u16RespLen = MAKE_WORD16(pu8RespBuffer[2], pu8RespBuffer[3]);
-
u16WIDtype = MAKE_WORD16(pu8RespBuffer[4], pu8RespBuffer[5]);
/* Check for WID_STATUS ID and then check the length and status value */
@@ -1898,104 +1867,21 @@
*ps32BytesRead = gstrConfigPktInfo.s32BytesRead;
}
- WILC_memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
+ memset((void *)(&gstrConfigPktInfo), 0, sizeof(tstrConfigPktInfo));
return s32Error;
}
-/**
- * @brief sends certain Configuration Packet based on the input WIDs pstrWIDs
- * and retrieves the packet response pu8RxResp
- * @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
- */
-#ifdef SIMULATION
-s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
- u32 u32WIDsCount, bool bRespRequired, u32 drvHandler)
-{
- s32 s32Error = WILC_SUCCESS;
- s32 err = WILC_SUCCESS;
- s32 s32ConfigPacketLen = 0;
- s32 s32RcvdRespLen = 0;
-
- down(&SemHandleSendPkt);
-
- /*set the packet mode*/
- g_oper_mode = u8Mode;
-
- WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE);
-
- if (CreateConfigPacket(gps8ConfigPacket, &s32ConfigPacketLen, pstrWIDs, u32WIDsCount) != WILC_SUCCESS) {
- s32Error = WILC_FAIL;
- goto End_ConfigPkt;
- }
- /*bug 3878*/
- gstrConfigPktInfo.pcRespBuffer = gps8ConfigPacket;
- gstrConfigPktInfo.s32MaxRespBuffLen = MAX_PACKET_BUFF_SIZE;
- PRINT_INFO(CORECONFIG_DBG, "GLOBAL =bRespRequired =%d\n", bRespRequired);
- gstrConfigPktInfo.bRespRequired = bRespRequired;
-
- s32Error = SendRawPacket(gps8ConfigPacket, s32ConfigPacketLen);
- if (s32Error != WILC_SUCCESS) {
- goto End_ConfigPkt;
- }
-
- WILC_memset((void *)gps8ConfigPacket, 0, MAX_PACKET_BUFF_SIZE);
-
- ConfigWaitResponse(gps8ConfigPacket, MAX_PACKET_BUFF_SIZE, &s32RcvdRespLen, bRespRequired);
-
-
- if (bRespRequired) {
- /* If the operating Mode is GET, then we expect a response frame from */
- /* the driver. Hence start listening to the port for response */
- if (g_oper_mode == GET_CFG) {
- #if 1
- err = ParseResponse(gps8ConfigPacket, pstrWIDs);
- if (err != 0) {
- s32Error = WILC_FAIL;
- goto End_ConfigPkt;
- } else {
- s32Error = WILC_SUCCESS;
- }
- #endif
- } else {
- err = ParseWriteResponse(gps8ConfigPacket);
- if (err != WRITE_RESP_SUCCESS) {
- s32Error = WILC_FAIL;
- goto End_ConfigPkt;
- } else {
- s32Error = WILC_SUCCESS;
- }
- }
-
-
- }
-
-
-End_ConfigPkt:
- up(&SemHandleSendPkt);
-
- return s32Error;
-}
-#endif
s32 ConfigProvideResponse(char *pcRespBuffer, s32 s32RespLen)
{
s32 s32Error = WILC_SUCCESS;
if (gstrConfigPktInfo.bRespRequired) {
if (s32RespLen <= gstrConfigPktInfo.s32MaxRespBuffLen) {
- WILC_memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, s32RespLen);
+ memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, s32RespLen);
gstrConfigPktInfo.s32BytesRead = s32RespLen;
} else {
- WILC_memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, gstrConfigPktInfo.s32MaxRespBuffLen);
+ memcpy(gstrConfigPktInfo.pcRespBuffer, pcRespBuffer, gstrConfigPktInfo.s32MaxRespBuffLen);
gstrConfigPktInfo.s32BytesRead = gstrConfigPktInfo.s32MaxRespBuffLen;
PRINT_ER("BusProvideResponse() Response greater than the prepared Buffer Size\n");
}
@@ -2069,17 +1955,10 @@
PRINT_D(CORECONFIG_DBG, "CoreConfiguratorDeInit()\n");
- if (gps8ConfigPacket != NULL) {
-
- WILC_FREE(gps8ConfigPacket);
- gps8ConfigPacket = NULL;
- }
return s32Error;
}
-
-#ifndef SIMULATION
/*Using the global handle of the driver*/
extern wilc_wlan_oup_t *gpstrWlanOps;
/**
@@ -2129,7 +2008,6 @@
/**
* get the value
**/
- /* WILC_Sleep(1000); */
counter = 0;
for (counter = 0; counter < u32WIDsCount; counter++) {
pstrWIDs[counter].s32ValueSize = gpstrWlanOps->wlan_cfg_get_value(
@@ -2153,4 +2031,3 @@
return ret;
}
-#endif
diff --git a/drivers/staging/wilc1000/coreconfigurator.h b/drivers/staging/wilc1000/coreconfigurator.h
index 9059c8d..3af1935 100644
--- a/drivers/staging/wilc1000/coreconfigurator.h
+++ b/drivers/staging/wilc1000/coreconfigurator.h
@@ -8,7 +8,6 @@
* @version 1.0
*/
-
#ifndef CORECONFIGURATOR_H
#define CORECONFIGURATOR_H
@@ -42,7 +41,6 @@
#define AID_LEN 2
#define IE_HDR_LEN 2
-
/* Operating Mode: SET */
#define SET_CFG 0
/* Operating Mode: GET */
@@ -59,15 +57,12 @@
#define MAC_CONNECTED 1
#define MAC_DISCONNECTED 0
-
-
/*****************************************************************************/
/* Function Macros */
/*****************************************************************************/
#define MAKE_WORD16(lsb, msb) ((((u16)(msb) << 8) & 0xFF00) | (lsb))
#define MAKE_WORD32(lsw, msw) ((((u32)(msw) << 16) & 0xFFFF0000) | (lsw))
-
/*****************************************************************************/
/* Type Definitions */
/*****************************************************************************/
@@ -140,7 +135,6 @@
u16 u16RespIEsLen;
} tstrConnectRespInfo;
-
typedef struct {
u8 au8bssid[6];
u8 *pu8ReqIEs;
@@ -150,8 +144,6 @@
u16 u16ConnectStatus;
} tstrConnectInfo;
-
-
typedef struct {
u16 u16reason;
u8 *ie;
@@ -171,26 +163,27 @@
} wid_site_survey_reslts_s;
#endif
-extern s32 CoreConfiguratorInit(void);
-extern s32 CoreConfiguratorDeInit(void);
+s32 CoreConfiguratorInit(void);
+s32 CoreConfiguratorDeInit(void);
-extern s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
- u32 u32WIDsCount, bool bRespRequired, u32 drvHandler);
-extern s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo);
-extern s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo);
+s32 SendConfigPkt(u8 u8Mode, tstrWID *pstrWIDs,
+ u32 u32WIDsCount, bool bRespRequired, u32 drvHandler);
+s32 ParseNetworkInfo(u8 *pu8MsgBuffer, tstrNetworkInfo **ppstrNetworkInfo);
+s32 DeallocateNetworkInfo(tstrNetworkInfo *pstrNetworkInfo);
-extern s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
- tstrConnectRespInfo **ppstrConnectRespInfo);
-extern s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo);
+s32 ParseAssocRespInfo(u8 *pu8Buffer, u32 u32BufferLen,
+ tstrConnectRespInfo **ppstrConnectRespInfo);
+s32 DeallocateAssocRespInfo(tstrConnectRespInfo *pstrConnectRespInfo);
#ifndef CONNECT_DIRECT
-extern s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
- wid_site_survey_reslts_s **ppstrSurveyResults, u32 *pu32SurveyResultsCount);
-extern s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults);
+s32 ParseSurveyResults(u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
+ wid_site_survey_reslts_s **ppstrSurveyResults,
+ u32 *pu32SurveyResultsCount);
+s32 DeallocateSurveyResults(wid_site_survey_reslts_s *pstrSurveyResults);
#endif
-extern s32 SendRawPacket(s8 *pspacket, s32 s32PacketLen);
-extern void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length);
+s32 SendRawPacket(s8 *pspacket, s32 s32PacketLen);
+void NetworkInfoReceived(u8 *pu8Buffer, u32 u32Length);
void GnrlAsyncInfoReceived(u8 *pu8Buffer, u32 u32Length);
void host_int_ScanCompleteReceived(u8 *pu8Buffer, u32 u32Length);
diff --git a/drivers/staging/wilc1000/fifo_buffer.c b/drivers/staging/wilc1000/fifo_buffer.c
deleted file mode 100644
index b6c07cf..0000000
--- a/drivers/staging/wilc1000/fifo_buffer.c
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-#include "fifo_buffer.h"
-
-
-
-u32 FIFO_InitBuffer(tHANDLE *hBuffer, u32 u32BufferLength)
-{
- u32 u32Error = 0;
- tstrFifoHandler *pstrFifoHandler = WILC_MALLOC (sizeof (tstrFifoHandler));
- if (pstrFifoHandler) {
- WILC_memset (pstrFifoHandler, 0, sizeof (tstrFifoHandler));
- pstrFifoHandler->pu8Buffer = WILC_MALLOC (u32BufferLength);
- if (pstrFifoHandler->pu8Buffer) {
- pstrFifoHandler->u32BufferLength = u32BufferLength;
- WILC_memset (pstrFifoHandler->pu8Buffer, 0, u32BufferLength);
- /* create semaphore */
- sema_init(&pstrFifoHandler->SemBuffer, 1);
- *hBuffer = pstrFifoHandler;
- } else {
- *hBuffer = NULL;
- u32Error = 1;
- }
- } else {
- u32Error = 1;
- }
- return u32Error;
-}
-u32 FIFO_DeInit(tHANDLE hFifo)
-{
- u32 u32Error = 0;
- tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo;
- if (pstrFifoHandler) {
- if (pstrFifoHandler->pu8Buffer) {
- WILC_FREE (pstrFifoHandler->pu8Buffer);
- } else {
- u32Error = 1;
- }
-
- WILC_FREE (pstrFifoHandler);
- } else {
- u32Error = 1;
- }
- return u32Error;
-}
-
-u32 FIFO_ReadBytes(tHANDLE hFifo, u8 *pu8Buffer, u32 u32BytesToRead, u32 *pu32BytesRead)
-{
- u32 u32Error = 0;
- tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo;
- if (pstrFifoHandler && pu32BytesRead) {
- if (pstrFifoHandler->u32TotalBytes) {
- down(&pstrFifoHandler->SemBuffer);
-
- if (u32BytesToRead > pstrFifoHandler->u32TotalBytes) {
- *pu32BytesRead = pstrFifoHandler->u32TotalBytes;
- } else {
- *pu32BytesRead = u32BytesToRead;
- }
- if ((pstrFifoHandler->u32ReadOffset + u32BytesToRead) <= pstrFifoHandler->u32BufferLength) {
- WILC_memcpy(pu8Buffer, pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32ReadOffset,
- *pu32BytesRead);
- /* update read offset and total bytes */
- pstrFifoHandler->u32ReadOffset += u32BytesToRead;
- pstrFifoHandler->u32TotalBytes -= u32BytesToRead;
-
- } else {
- u32 u32FirstPart =
- pstrFifoHandler->u32BufferLength - pstrFifoHandler->u32ReadOffset;
- WILC_memcpy(pu8Buffer, pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32ReadOffset,
- u32FirstPart);
- WILC_memcpy(pu8Buffer + u32FirstPart, pstrFifoHandler->pu8Buffer,
- u32BytesToRead - u32FirstPart);
- /* update read offset and total bytes */
- pstrFifoHandler->u32ReadOffset = u32BytesToRead - u32FirstPart;
- pstrFifoHandler->u32TotalBytes -= u32BytesToRead;
- }
- up(&pstrFifoHandler->SemBuffer);
- } else {
- u32Error = 1;
- }
- } else {
- u32Error = 1;
- }
- return u32Error;
-}
-
-u32 FIFO_WriteBytes(tHANDLE hFifo, u8 *pu8Buffer, u32 u32BytesToWrite, bool bForceOverWrite)
-{
- u32 u32Error = 0;
- tstrFifoHandler *pstrFifoHandler = (tstrFifoHandler *) hFifo;
- if (pstrFifoHandler) {
- if (u32BytesToWrite < pstrFifoHandler->u32BufferLength) {
- if ((pstrFifoHandler->u32TotalBytes + u32BytesToWrite) <= pstrFifoHandler->u32BufferLength ||
- bForceOverWrite) {
- down(&pstrFifoHandler->SemBuffer);
- if ((pstrFifoHandler->u32WriteOffset + u32BytesToWrite) <= pstrFifoHandler->u32BufferLength) {
- WILC_memcpy(pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32WriteOffset, pu8Buffer,
- u32BytesToWrite);
- /* update read offset and total bytes */
- pstrFifoHandler->u32WriteOffset += u32BytesToWrite;
- pstrFifoHandler->u32TotalBytes += u32BytesToWrite;
-
- } else {
- u32 u32FirstPart =
- pstrFifoHandler->u32BufferLength - pstrFifoHandler->u32WriteOffset;
- WILC_memcpy(pstrFifoHandler->pu8Buffer + pstrFifoHandler->u32WriteOffset, pu8Buffer,
- u32FirstPart);
- WILC_memcpy(pstrFifoHandler->pu8Buffer, pu8Buffer + u32FirstPart,
- u32BytesToWrite - u32FirstPart);
- /* update read offset and total bytes */
- pstrFifoHandler->u32WriteOffset = u32BytesToWrite - u32FirstPart;
- pstrFifoHandler->u32TotalBytes += u32BytesToWrite;
- }
- /* if data overwriten */
- if (pstrFifoHandler->u32TotalBytes > pstrFifoHandler->u32BufferLength) {
- /* adjust read offset to the oldest data available */
- pstrFifoHandler->u32ReadOffset = pstrFifoHandler->u32WriteOffset;
- /* data availabe is the buffer length */
- pstrFifoHandler->u32TotalBytes = pstrFifoHandler->u32BufferLength;
- }
- up(&pstrFifoHandler->SemBuffer);
- } else {
- u32Error = 1;
- }
- } else {
- u32Error = 1;
- }
- } else {
- u32Error = 1;
- }
- return u32Error;
-}
diff --git a/drivers/staging/wilc1000/fifo_buffer.h b/drivers/staging/wilc1000/fifo_buffer.h
deleted file mode 100644
index 7b76998..0000000
--- a/drivers/staging/wilc1000/fifo_buffer.h
+++ /dev/null
@@ -1,26 +0,0 @@
-
-#include <linux/types.h>
-#include <linux/semaphore.h>
-#include "wilc_memory.h"
-#include "wilc_strutils.h"
-
-
-#define tHANDLE void *
-
-typedef struct {
- u8 *pu8Buffer;
- u32 u32BufferLength;
- u32 u32WriteOffset;
- u32 u32ReadOffset;
- u32 u32TotalBytes;
- struct semaphore SemBuffer;
-} tstrFifoHandler;
-
-
-extern u32 FIFO_InitBuffer(tHANDLE *hBuffer,
- u32 u32BufferLength);
-extern u32 FIFO_DeInit(tHANDLE hFifo);
-extern u32 FIFO_ReadBytes(tHANDLE hFifo, u8 *pu8Buffer,
- u32 u32BytesToRead, u32 *pu32BytesRead);
-extern u32 FIFO_WriteBytes(tHANDLE hFifo, u8 *pu8Buffer,
- u32 u32BytesToWrite, bool bForceOverWrite);
diff --git a/drivers/staging/wilc1000/host_interface.c b/drivers/staging/wilc1000/host_interface.c
index 6b10bbb..66fa677 100644
--- a/drivers/staging/wilc1000/host_interface.c
+++ b/drivers/staging/wilc1000/host_interface.c
@@ -6,10 +6,9 @@
extern u8 connecting;
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-extern WILC_TimerHandle hDuringIpTimer;
+extern struct timer_list hDuringIpTimer;
#endif
-extern bool bEnablePS;
/*BugID_5137*/
extern u8 g_wilc_initialized;
/*****************************************************************************/
@@ -467,7 +466,7 @@
typedef struct _tstrHostIFmsg {
u16 u16MsgId; /*!< Message ID */
tuniHostIFmsgBody uniHostIFmsgBody; /*!< Message body */
- void *drvHandler;
+ tstrWILC_WFIDrv *drvHandler;
} tstrHostIFmsg;
#ifdef CONNECT_DIRECT
@@ -534,8 +533,8 @@
/*****************************************************************************/
-tstrWILC_WFIDrv *terminated_handle = NULL;
-tstrWILC_WFIDrv *gWFiDrvHandle = NULL;
+tstrWILC_WFIDrv *terminated_handle;
+tstrWILC_WFIDrv *gWFiDrvHandle;
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
bool g_obtainingIP = false;
#endif
@@ -547,7 +546,7 @@
struct semaphore hSemDeinitDrvHandle;
static struct semaphore hWaitResponse;
struct semaphore hSemHostIntDeinit;
-WILC_TimerHandle g_hPeriodicRSSI;
+struct timer_list g_hPeriodicRSSI;
@@ -570,9 +569,7 @@
static u32 gu32InactiveTime;
static u8 gu8DelBcn;
#endif
-#ifndef SIMULATION
static u32 gu32WidConnRstHack;
-#endif
/*BugID_5137*/
u8 *gu8FlushedJoinReq;
@@ -604,7 +601,7 @@
* @date
* @version 1.0
*/
-static s32 Handle_SetChannel(void *drvHandler, tstrHostIFSetChan *pstrHostIFSetChan)
+static s32 Handle_SetChannel(tstrWILC_WFIDrv *drvHandler, tstrHostIFSetChan *pstrHostIFSetChan)
{
s32 s32Error = WILC_SUCCESS;
@@ -659,9 +656,8 @@
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
- if ((pstrHostIfSetDrvHandler->u32Address) == (u32)NULL) {
+ if ((pstrHostIfSetDrvHandler->u32Address) == (u32)NULL)
up(&hSemDeinitDrvHandle);
- }
if (s32Error) {
@@ -685,7 +681,7 @@
* @date
* @version 1.0
*/
-static s32 Handle_SetOperationMode(void *drvHandler, tstrHostIfSetOperationMode *pstrHostIfSetOperationMode)
+static s32 Handle_SetOperationMode(tstrWILC_WFIDrv *drvHandler, tstrHostIfSetOperationMode *pstrHostIfSetOperationMode)
{
s32 s32Error = WILC_SUCCESS;
@@ -700,14 +696,13 @@
strWID.s32ValueSize = sizeof(u32);
/*Sending Cfg*/
- PRINT_INFO(HOSTINF_DBG, "pstrWFIDrv= %p \n", pstrWFIDrv);
+ PRINT_INFO(HOSTINF_DBG, "pstrWFIDrv= %p\n", pstrWFIDrv);
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
- if ((pstrHostIfSetOperationMode->u32Mode) == (u32)NULL) {
+ if ((pstrHostIfSetOperationMode->u32Mode) == (u32)NULL)
up(&hSemDeinitDrvHandle);
- }
if (s32Error) {
@@ -731,7 +726,7 @@
* @date
* @version 1.0
*/
-s32 Handle_set_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
+s32 Handle_set_IPAddress(tstrWILC_WFIDrv *drvHandler, u8 *pu8IPAddr, u8 idx)
{
s32 s32Error = WILC_SUCCESS;
@@ -742,9 +737,9 @@
if (pu8IPAddr[0] < 192)
pu8IPAddr[0] = 0;
- PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set IP = %d.%d.%d.%d \n", idx, pu8IPAddr[0], pu8IPAddr[1], pu8IPAddr[2], pu8IPAddr[3]);
+ PRINT_INFO(HOSTINF_DBG, "Indx = %d, Handling set IP = %pI4\n", idx, pu8IPAddr);
- WILC_memcpy(gs8SetIP[idx], pu8IPAddr, IP_ALEN);
+ memcpy(gs8SetIP[idx], pu8IPAddr, IP_ALEN);
/*prepare configuration packet*/
strWID.u16WIDid = (u16)WID_IP_ADDRESS;
@@ -756,7 +751,7 @@
- host_int_get_ipaddress((WILC_WFIDrvHandle)drvHandler, firmwareIPAddress, idx);
+ host_int_get_ipaddress(drvHandler, firmwareIPAddress, idx);
if (s32Error) {
PRINT_D(HOSTINF_DBG, "Failed to set IP address\n");
@@ -783,7 +778,7 @@
* @date
* @version 1.0
*/
-s32 Handle_get_IPAddress(void *drvHandler, u8 *pu8IPAddr, u8 idx)
+s32 Handle_get_IPAddress(tstrWILC_WFIDrv *drvHandler, u8 *pu8IPAddr, u8 idx)
{
s32 s32Error = WILC_SUCCESS;
@@ -793,27 +788,27 @@
/*prepare configuration packet*/
strWID.u16WIDid = (u16)WID_IP_ADDRESS;
strWID.enuWIDtype = WID_STR;
- strWID.ps8WidVal = (u8 *)WILC_MALLOC(IP_ALEN);
+ strWID.ps8WidVal = WILC_MALLOC(IP_ALEN);
strWID.s32ValueSize = IP_ALEN;
s32Error = SendConfigPkt(GET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
- PRINT_INFO(HOSTINF_DBG, "%d.%d.%d.%d\n", (u8)(strWID.ps8WidVal[0]), (u8)(strWID.ps8WidVal[1]), (u8)(strWID.ps8WidVal[2]), (u8)(strWID.ps8WidVal[3]));
+ PRINT_INFO(HOSTINF_DBG, "%pI4\n", strWID.ps8WidVal);
- WILC_memcpy(gs8GetIP[idx], strWID.ps8WidVal, IP_ALEN);
+ memcpy(gs8GetIP[idx], strWID.ps8WidVal, IP_ALEN);
/*get the value by searching the local copy*/
- WILC_FREE(strWID.ps8WidVal);
+ kfree(strWID.ps8WidVal);
- if (WILC_memcmp(gs8GetIP[idx], gs8SetIP[idx], IP_ALEN) != 0)
- host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, gs8SetIP[idx], idx);
+ if (memcmp(gs8GetIP[idx], gs8SetIP[idx], IP_ALEN) != 0)
+ host_int_setup_ipaddress(pstrWFIDrv, gs8SetIP[idx], idx);
if (s32Error != WILC_SUCCESS) {
PRINT_ER("Failed to get IP address\n");
WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE);
} else {
- PRINT_INFO(HOSTINF_DBG, "IP address retrieved:: u8IfIdx = %d \n", idx);
- PRINT_INFO(HOSTINF_DBG, "%d.%d.%d.%d\n", gs8GetIP[idx][0], gs8GetIP[idx][1], gs8GetIP[idx][2], gs8GetIP[idx][3]);
+ PRINT_INFO(HOSTINF_DBG, "IP address retrieved:: u8IfIdx = %d\n", idx);
+ PRINT_INFO(HOSTINF_DBG, "%pI4\n", gs8GetIP[idx]);
PRINT_INFO(HOSTINF_DBG, "\n");
}
@@ -836,18 +831,19 @@
* @date November 2013
* @version 7.0
*/
-static s32 Handle_SetMacAddress(void *drvHandler, tstrHostIfSetMacAddress *pstrHostIfSetMacAddress)
+static s32 Handle_SetMacAddress(tstrWILC_WFIDrv *drvHandler, tstrHostIfSetMacAddress *pstrHostIfSetMacAddress)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
- u8 *mac_buf = (u8 *)WILC_MALLOC(ETH_ALEN);
+ u8 *mac_buf = WILC_MALLOC(ETH_ALEN);
+
if (mac_buf == NULL) {
PRINT_ER("No buffer to send mac address\n");
return WILC_FAIL;
}
- WILC_memcpy(mac_buf, pstrHostIfSetMacAddress->u8MacAddress, ETH_ALEN);
+ memcpy(mac_buf, pstrHostIfSetMacAddress->u8MacAddress, ETH_ALEN);
/*prepare configuration packet*/
strWID.u16WIDid = (u16)WID_MAC_ADDR;
@@ -866,7 +862,7 @@
{
}
- WILC_FREE(mac_buf);
+ kfree(mac_buf);
return s32Error;
}
@@ -881,7 +877,7 @@
* @date JAN 2013
* @version 8.0
*/
-static s32 Handle_GetMacAddress(void *drvHandler, tstrHostIfGetMacAddress *pstrHostIfGetMacAddress)
+static s32 Handle_GetMacAddress(tstrWILC_WFIDrv *drvHandler, tstrHostIfGetMacAddress *pstrHostIfGetMacAddress)
{
s32 s32Error = WILC_SUCCESS;
@@ -918,7 +914,7 @@
* @date
* @version 1.0
*/
-static s32 Handle_CfgParam(void *drvHandler, tstrHostIFCfgParamAttr *strHostIFCfgParamAttr)
+static s32 Handle_CfgParam(tstrWILC_WFIDrv *drvHandler, tstrHostIFCfgParamAttr *strHostIFCfgParamAttr)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWIDList[32];
@@ -1204,10 +1200,9 @@
}
s32Error = SendConfigPkt(SET_CFG, strWIDList, u8WidCnt, false, (u32)pstrWFIDrv);
- if (s32Error) {
+ if (s32Error)
PRINT_ER("Error in setting CFG params\n");
- }
WILC_CATCH(s32Error)
{
}
@@ -1228,6 +1223,7 @@
static s32 Handle_wait_msg_q_empty(void)
{
s32 s32Error = WILC_SUCCESS;
+
g_wilc_initialized = 0;
up(&hWaitResponse);
return s32Error;
@@ -1242,7 +1238,7 @@
* @date
* @version 1.0
*/
-static s32 Handle_Scan(void *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
+static s32 Handle_Scan(tstrWILC_WFIDrv *drvHandler, tstrHostIFscanAttr *pstrHostIFscanAttr)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWIDList[5];
@@ -1254,7 +1250,7 @@
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler;
PRINT_D(HOSTINF_DBG, "Setting SCAN params\n");
- PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state \n", pstrWFIDrv->enuHostIFstate);
+ PRINT_D(HOSTINF_DBG, "Scanning: In [%d] state\n", pstrWFIDrv->enuHostIFstate);
pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = pstrHostIFscanAttr->pfScanResult;
pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid = pstrHostIFscanAttr->pvUserArg;
@@ -1284,9 +1280,8 @@
strWIDList[u32WidsCount].u16WIDid = (u16)WID_SSID_PROBE_REQ;
strWIDList[u32WidsCount].enuWIDtype = WID_STR;
- for (i = 0; i < pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum; i++) {
+ for (i = 0; i < pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum; i++)
valuesize += ((pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen) + 1);
- }
pu8HdnNtwrksWidVal = WILC_MALLOC(valuesize + 1);
strWIDList[u32WidsCount].ps8WidVal = pu8HdnNtwrksWidVal;
if (strWIDList[u32WidsCount].ps8WidVal != NULL) {
@@ -1298,7 +1293,7 @@
for (i = 0; i < pstrHostIFscanAttr->strHiddenNetwork.u8ssidnum; i++) {
*pu8Buffer++ = pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen;
- WILC_memcpy(pu8Buffer, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen);
+ memcpy(pu8Buffer, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen);
pu8Buffer += pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen;
}
@@ -1336,9 +1331,8 @@
int i;
for (i = 0; i < pstrHostIFscanAttr->u8ChnlListLen; i++) {
- if (pstrHostIFscanAttr->pu8ChnlFreqList[i] > 0) {
+ if (pstrHostIFscanAttr->pu8ChnlFreqList[i] > 0)
pstrHostIFscanAttr->pu8ChnlFreqList[i] = pstrHostIFscanAttr->pu8ChnlFreqList[i] - 1;
- }
}
}
@@ -1356,11 +1350,10 @@
/*keep the state as is , no need to change it*/
/* gWFiDrvHandle->enuHostIFstate = HOST_IF_SCANNING; */
- if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) {
+ if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED)
gbScanWhileConnected = true;
- } else if (pstrWFIDrv->enuHostIFstate == HOST_IF_IDLE) {
+ else if (pstrWFIDrv->enuHostIFstate == HOST_IF_IDLE)
gbScanWhileConnected = false;
- }
s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, false, (u32)pstrWFIDrv);
@@ -1373,36 +1366,35 @@
WILC_CATCH(s32Error)
{
- WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
+ del_timer(&pstrWFIDrv->hScanTimer);
/*if there is an ongoing scan request*/
Handle_ScanDone(drvHandler, SCAN_EVENT_ABORTED);
}
/* Deallocate pstrHostIFscanAttr->u8ChnlListLen which was prevoisuly allocated by the sending thread */
if (pstrHostIFscanAttr->pu8ChnlFreqList != NULL) {
- WILC_FREE(pstrHostIFscanAttr->pu8ChnlFreqList);
+ kfree(pstrHostIFscanAttr->pu8ChnlFreqList);
pstrHostIFscanAttr->pu8ChnlFreqList = NULL;
}
/* Deallocate pstrHostIFscanAttr->pu8IEs which was previously allocated by the sending thread */
if (pstrHostIFscanAttr->pu8IEs != NULL) {
- WILC_FREE(pstrHostIFscanAttr->pu8IEs);
+ kfree(pstrHostIFscanAttr->pu8IEs);
pstrHostIFscanAttr->pu8IEs = NULL;
}
if (pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo != NULL) {
- WILC_FREE(pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo);
+ kfree(pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo);
pstrHostIFscanAttr->strHiddenNetwork.pstrHiddenNetworkInfo = NULL;
}
/* Deallocate pstrHostIFscanAttr->u8ChnlListLen which was prevoisuly allocated by the sending thread */
if (pstrHostIFscanAttr->pu8ChnlFreqList != NULL) {
- WILC_FREE(pstrHostIFscanAttr->pu8ChnlFreqList);
+ kfree(pstrHostIFscanAttr->pu8ChnlFreqList);
pstrHostIFscanAttr->pu8ChnlFreqList = NULL;
}
- if (pu8HdnNtwrksWidVal != NULL) {
- WILC_FREE(pu8HdnNtwrksWidVal);
- }
+ if (pu8HdnNtwrksWidVal != NULL)
+ kfree(pu8HdnNtwrksWidVal);
return s32Error;
}
@@ -1416,7 +1408,7 @@
* @date
* @version 1.0
*/
-static s32 Handle_ScanDone(void *drvHandler, tenuScanEvent enuEvent)
+static s32 Handle_ScanDone(tstrWILC_WFIDrv *drvHandler, tenuScanEvent enuEvent)
{
s32 s32Error = WILC_SUCCESS;
@@ -1476,7 +1468,7 @@
* @version 1.0
*/
u8 u8ConnectedSSID[6] = {0};
-static s32 Handle_Connect(void *drvHandler, tstrHostIFconnectAttr *pstrHostIFconnectAttr)
+static s32 Handle_Connect(tstrWILC_WFIDrv *drvHandler, tstrHostIFconnectAttr *pstrHostIFconnectAttr)
{
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler;
s32 s32Error = WILC_SUCCESS;
@@ -1500,12 +1492,12 @@
PRINT_D(GENERIC_DBG, "Handling connect request\n");
#ifndef CONNECT_DIRECT
- WILC_memset(gapu8RcvdSurveyResults[0], 0, MAX_SURVEY_RESULT_FRAG_SIZE);
- WILC_memset(gapu8RcvdSurveyResults[1], 0, MAX_SURVEY_RESULT_FRAG_SIZE);
+ memset(gapu8RcvdSurveyResults[0], 0, MAX_SURVEY_RESULT_FRAG_SIZE);
+ memset(gapu8RcvdSurveyResults[1], 0, MAX_SURVEY_RESULT_FRAG_SIZE);
PRINT_D(HOSTINF_DBG, "Getting site survey results\n");
- s32Err = host_int_get_site_survey_results((WILC_WFIDrvHandle)pstrWFIDrv,
+ s32Err = host_int_get_site_survey_results(pstrWFIDrv,
gapu8RcvdSurveyResults,
MAX_SURVEY_RESULT_FRAG_SIZE);
if (s32Err) {
@@ -1521,19 +1513,19 @@
/* use the parsed info in pstrSurveyResults, then deallocate it */
PRINT_D(HOSTINF_DBG, "Copying site survey results in global structure, then deallocate\n");
for (i = 0; i < pstrWFIDrv->u32SurveyResultsCount; i++) {
- WILC_memcpy(&pstrWFIDrv->astrSurveyResults[i], &pstrSurveyResults[i],
+ memcpy(&pstrWFIDrv->astrSurveyResults[i], &pstrSurveyResults[i],
sizeof(wid_site_survey_reslts_s));
}
DeallocateSurveyResults(pstrSurveyResults);
} else {
WILC_ERRORREPORT(s32Error, WILC_FAIL);
- PRINT_ER("ParseSurveyResults() Error(%d) \n", s32Err);
+ PRINT_ER("ParseSurveyResults() Error(%d)\n", s32Err);
}
for (i = 0; i < pstrWFIDrv->u32SurveyResultsCount; i++) {
- if (WILC_memcmp(pstrWFIDrv->astrSurveyResults[i].SSID,
+ if (memcmp(pstrWFIDrv->astrSurveyResults[i].SSID,
pstrHostIFconnectAttr->pu8ssid,
pstrHostIFconnectAttr->ssidLen) == 0) {
PRINT_INFO(HOSTINF_DBG, "Network with required SSID is found %s\n", pstrHostIFconnectAttr->pu8ssid);
@@ -1546,7 +1538,7 @@
/* BSSID is also passed from the user, so decision of matching
* should consider also this passed BSSID */
- if (WILC_memcmp(pstrWFIDrv->astrSurveyResults[i].BSSID,
+ if (memcmp(pstrWFIDrv->astrSurveyResults[i].BSSID,
pstrHostIFconnectAttr->pu8bssid,
6) == 0) {
PRINT_INFO(HOSTINF_DBG, "BSSID is passed from the user and matched\n");
@@ -1559,29 +1551,29 @@
if (i < pstrWFIDrv->u32SurveyResultsCount) {
u8bssDscListIndex = i;
- PRINT_INFO(HOSTINF_DBG, "Connecting to network of Bss Idx %d and SSID %s and channel %d \n",
+ PRINT_INFO(HOSTINF_DBG, "Connecting to network of Bss Idx%d and SSID %s and channel%d\n",
u8bssDscListIndex, pstrWFIDrv->astrSurveyResults[u8bssDscListIndex].SSID,
pstrWFIDrv->astrSurveyResults[u8bssDscListIndex].Channel);
PRINT_INFO(HOSTINF_DBG, "Saving connection parameters in global structure\n");
if (pstrHostIFconnectAttr->pu8bssid != NULL) {
- pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = (u8 *)WILC_MALLOC(6);
- WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
+ pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = WILC_MALLOC(6);
+ memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
}
pstrWFIDrv->strWILC_UsrConnReq.ssidLen = pstrHostIFconnectAttr->ssidLen;
if (pstrHostIFconnectAttr->pu8ssid != NULL) {
- pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1);
- WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid,
+ pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1);
+ memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid,
pstrHostIFconnectAttr->ssidLen);
pstrWFIDrv->strWILC_UsrConnReq.pu8ssid[pstrHostIFconnectAttr->ssidLen] = '\0';
}
pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = pstrHostIFconnectAttr->IEsLen;
if (pstrHostIFconnectAttr->pu8IEs != NULL) {
- pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
- WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs,
+ pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
+ memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs,
pstrHostIFconnectAttr->IEsLen);
}
@@ -1630,14 +1622,12 @@
strWIDList[u32WidsCount].ps8WidVal = (s8 *)&u8bssDscListIndex;
u32WidsCount++;
- #ifndef SIMULATION
/* A temporary workaround to avoid handling the misleading MAC_DISCONNECTED raised from the
* firmware at chip reset when processing the WIDs of the Connect Request.
* (This workaround should be removed in the future when the Chip reset of the Connect WIDs is disabled) */
/* ////////////////////// */
gu32WidConnRstHack = 0;
/* ////////////////////// */
- #endif
s32Error = SendConfigPkt(SET_CFG, strWIDList, u32WidsCount, false, (u32)pstrWFIDrv);
if (s32Error) {
@@ -1656,7 +1646,7 @@
/* if we try to connect to an already connected AP then discard the request */
- if (WILC_memcmp(pstrHostIFconnectAttr->pu8bssid, u8ConnectedSSID, ETH_ALEN) == 0) {
+ if (memcmp(pstrHostIFconnectAttr->pu8bssid, u8ConnectedSSID, ETH_ALEN) == 0) {
s32Error = WILC_SUCCESS;
PRINT_ER("Trying to connect to an already connected AP, Discard connect request\n");
@@ -1675,22 +1665,22 @@
#endif /*WILC_PARSE_SCAN_IN_HOST*/
if (pstrHostIFconnectAttr->pu8bssid != NULL) {
- pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = (u8 *)WILC_MALLOC(6);
- WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
+ pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = WILC_MALLOC(6);
+ memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
}
pstrWFIDrv->strWILC_UsrConnReq.ssidLen = pstrHostIFconnectAttr->ssidLen;
if (pstrHostIFconnectAttr->pu8ssid != NULL) {
- pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1);
- WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid,
+ pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = WILC_MALLOC(pstrHostIFconnectAttr->ssidLen + 1);
+ memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid, pstrHostIFconnectAttr->pu8ssid,
pstrHostIFconnectAttr->ssidLen);
pstrWFIDrv->strWILC_UsrConnReq.pu8ssid[pstrHostIFconnectAttr->ssidLen] = '\0';
}
pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = pstrHostIFconnectAttr->IEsLen;
if (pstrHostIFconnectAttr->pu8IEs != NULL) {
- pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
- WILC_memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs,
+ pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
+ memcpy(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs, pstrHostIFconnectAttr->pu8IEs,
pstrHostIFconnectAttr->IEsLen);
}
@@ -1728,7 +1718,7 @@
u32WidsCount++;
/*BugID_5137*/
- if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
+ if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
gu32FlushedInfoElemAsocSize = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen;
gu8FlushedInfoElemAsoc = WILC_MALLOC(gu32FlushedInfoElemAsocSize);
@@ -1743,7 +1733,7 @@
u32WidsCount++;
/*BugID_5137*/
- if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7))
+ if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7))
gu8Flushed11iMode = pstrWFIDrv->strWILC_UsrConnReq.u8security;
PRINT_INFO(HOSTINF_DBG, "Encrypt Mode = %x\n", pstrWFIDrv->strWILC_UsrConnReq.u8security);
@@ -1756,7 +1746,7 @@
u32WidsCount++;
/*BugID_5137*/
- if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7))
+ if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7))
gu8FlushedAuthType = (u8)pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type;
PRINT_INFO(HOSTINF_DBG, "Authentication Type = %x\n", pstrWFIDrv->strWILC_UsrConnReq.tenuAuth_type);
@@ -1778,14 +1768,13 @@
strWIDList[u32WidsCount].s32ValueSize = MAX_SSID_LEN + 7;
strWIDList[u32WidsCount].ps8WidVal = WILC_MALLOC(strWIDList[u32WidsCount].s32ValueSize);
- if (strWIDList[u32WidsCount].ps8WidVal == NULL) {
+ if (strWIDList[u32WidsCount].ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal;
if (pstrHostIFconnectAttr->pu8ssid != NULL) {
- WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen);
+ memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen);
pu8CurrByte[pstrHostIFconnectAttr->ssidLen] = '\0';
}
pu8CurrByte += MAX_SSID_LEN;
@@ -1795,9 +1784,8 @@
PRINT_ER("Channel out of range\n");
*(pu8CurrByte++) = 0xFF;
}
- if (pstrHostIFconnectAttr->pu8bssid != NULL) {
- WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
- }
+ if (pstrHostIFconnectAttr->pu8bssid != NULL)
+ memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
pu8CurrByte += 6;
/* keep the buffer at the start of the allocated pointer to use it with the free*/
@@ -1813,19 +1801,18 @@
strWIDList[u32WidsCount].ps8WidVal = WILC_MALLOC(strWIDList[u32WidsCount].s32ValueSize);
/*BugID_5137*/
- if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
+ if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
gu32FlushedJoinReqSize = strWIDList[u32WidsCount].s32ValueSize;
gu8FlushedJoinReq = WILC_MALLOC(gu32FlushedJoinReqSize);
}
- if (strWIDList[u32WidsCount].ps8WidVal == NULL) {
+ if (strWIDList[u32WidsCount].ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWIDList[u32WidsCount].ps8WidVal;
if (pstrHostIFconnectAttr->pu8ssid != NULL) {
- WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen);
+ memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8ssid, pstrHostIFconnectAttr->ssidLen);
pu8CurrByte[pstrHostIFconnectAttr->ssidLen] = '\0';
}
pu8CurrByte += MAX_SSID_LEN;
@@ -1845,15 +1832,13 @@
PRINT_D(HOSTINF_DBG, "* Cap Info %0x*\n", (*(pu8CurrByte - 2) | ((*(pu8CurrByte - 1)) << 8)));
/* sa*/
- if (pstrHostIFconnectAttr->pu8bssid != NULL) {
- WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
- }
+ if (pstrHostIFconnectAttr->pu8bssid != NULL)
+ memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
pu8CurrByte += 6;
/* bssid*/
- if (pstrHostIFconnectAttr->pu8bssid != NULL) {
- WILC_memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
- }
+ if (pstrHostIFconnectAttr->pu8bssid != NULL)
+ memcpy(pu8CurrByte, pstrHostIFconnectAttr->pu8bssid, 6);
pu8CurrByte += 6;
/* Beacon Period*/
@@ -1864,7 +1849,7 @@
*(pu8CurrByte++) = ptstrJoinBssParam->dtim_period;
PRINT_D(HOSTINF_DBG, "* DTIM Period %d*\n", (*(pu8CurrByte - 1)));
/* Supported rates*/
- WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->supp_rates, MAX_RATES_SUPPORTED + 1);
+ memcpy(pu8CurrByte, ptstrJoinBssParam->supp_rates, MAX_RATES_SUPPORTED + 1);
pu8CurrByte += (MAX_RATES_SUPPORTED + 1);
/* wmm cap*/
@@ -1888,15 +1873,15 @@
*(pu8CurrByte++) = ptstrJoinBssParam->mode_802_11i;
PRINT_D(HOSTINF_DBG, "* mode_802_11i %d*\n", (*(pu8CurrByte - 1)));
/* rsn pcip policy*/
- WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_pcip_policy, sizeof(ptstrJoinBssParam->rsn_pcip_policy));
+ memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_pcip_policy, sizeof(ptstrJoinBssParam->rsn_pcip_policy));
pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_pcip_policy);
/* rsn auth policy*/
- WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_auth_policy, sizeof(ptstrJoinBssParam->rsn_auth_policy));
+ memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_auth_policy, sizeof(ptstrJoinBssParam->rsn_auth_policy));
pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_auth_policy);
/* rsn auth policy*/
- WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_cap, sizeof(ptstrJoinBssParam->rsn_cap));
+ memcpy(pu8CurrByte, ptstrJoinBssParam->rsn_cap, sizeof(ptstrJoinBssParam->rsn_cap));
pu8CurrByte += sizeof(ptstrJoinBssParam->rsn_cap);
/*BugID_5137*/
@@ -1921,15 +1906,15 @@
*(pu8CurrByte++) = ptstrJoinBssParam->u8Count;
- WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->au8Duration, sizeof(ptstrJoinBssParam->au8Duration));
+ memcpy(pu8CurrByte, ptstrJoinBssParam->au8Duration, sizeof(ptstrJoinBssParam->au8Duration));
pu8CurrByte += sizeof(ptstrJoinBssParam->au8Duration);
- WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->au8Interval, sizeof(ptstrJoinBssParam->au8Interval));
+ memcpy(pu8CurrByte, ptstrJoinBssParam->au8Interval, sizeof(ptstrJoinBssParam->au8Interval));
pu8CurrByte += sizeof(ptstrJoinBssParam->au8Interval);
- WILC_memcpy(pu8CurrByte, ptstrJoinBssParam->au8StartTime, sizeof(ptstrJoinBssParam->au8StartTime));
+ memcpy(pu8CurrByte, ptstrJoinBssParam->au8StartTime, sizeof(ptstrJoinBssParam->au8StartTime));
pu8CurrByte += sizeof(ptstrJoinBssParam->au8StartTime);
@@ -1945,17 +1930,15 @@
#endif /* #ifdef WILC_PARSE_SCAN_IN_HOST*/
u32WidsCount++;
- #ifndef SIMULATION
/* A temporary workaround to avoid handling the misleading MAC_DISCONNECTED raised from the
* firmware at chip reset when processing the WIDs of the Connect Request.
* (This workaround should be removed in the future when the Chip reset of the Connect WIDs is disabled) */
/* ////////////////////// */
gu32WidConnRstHack = 0;
/* ////////////////////// */
- #endif
/*BugID_5137*/
- if (WILC_memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
+ if (memcmp("DIRECT-", pstrHostIFconnectAttr->pu8ssid, 7)) {
memcpy(gu8FlushedJoinReq, pu8CurrByte, gu32FlushedJoinReqSize);
gu8FlushedJoinReqDrvHandler = (u32)pstrWFIDrv;
}
@@ -1963,7 +1946,7 @@
PRINT_D(GENERIC_DBG, "send HOST_IF_WAITING_CONN_RESP\n");
if (pstrHostIFconnectAttr->pu8bssid != NULL) {
- WILC_memcpy(u8ConnectedSSID, pstrHostIFconnectAttr->pu8bssid, ETH_ALEN);
+ memcpy(u8ConnectedSSID, pstrHostIFconnectAttr->pu8bssid, ETH_ALEN);
PRINT_D(GENERIC_DBG, "save Bssid = %x:%x:%x:%x:%x:%x\n", (pstrHostIFconnectAttr->pu8bssid[0]), (pstrHostIFconnectAttr->pu8bssid[1]), (pstrHostIFconnectAttr->pu8bssid[2]), (pstrHostIFconnectAttr->pu8bssid[3]), (pstrHostIFconnectAttr->pu8bssid[4]), (pstrHostIFconnectAttr->pu8bssid[5]));
PRINT_D(GENERIC_DBG, "save bssid = %x:%x:%x:%x:%x:%x\n", (u8ConnectedSSID[0]), (u8ConnectedSSID[1]), (u8ConnectedSSID[2]), (u8ConnectedSSID[3]), (u8ConnectedSSID[4]), (u8ConnectedSSID[5]));
@@ -1983,21 +1966,20 @@
{
tstrConnectInfo strConnectInfo;
- WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), NULL);
+ del_timer(&pstrWFIDrv->hConnectTimer);
PRINT_D(HOSTINF_DBG, "could not start connecting to the required network\n");
- WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
+ memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
if (pstrHostIFconnectAttr->pfConnectResult != NULL) {
- if (pstrHostIFconnectAttr->pu8bssid != NULL) {
- WILC_memcpy(strConnectInfo.au8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
- }
+ if (pstrHostIFconnectAttr->pu8bssid != NULL)
+ memcpy(strConnectInfo.au8bssid, pstrHostIFconnectAttr->pu8bssid, 6);
if (pstrHostIFconnectAttr->pu8IEs != NULL) {
strConnectInfo.ReqIEsLen = pstrHostIFconnectAttr->IEsLen;
- strConnectInfo.pu8ReqIEs = (u8 *)WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
- WILC_memcpy(strConnectInfo.pu8ReqIEs,
+ strConnectInfo.pu8ReqIEs = WILC_MALLOC(pstrHostIFconnectAttr->IEsLen);
+ memcpy(strConnectInfo.pu8ReqIEs,
pstrHostIFconnectAttr->pu8IEs,
pstrHostIFconnectAttr->IEsLen);
}
@@ -2011,37 +1993,36 @@
pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
/* Deallocation */
if (strConnectInfo.pu8ReqIEs != NULL) {
- WILC_FREE(strConnectInfo.pu8ReqIEs);
+ kfree(strConnectInfo.pu8ReqIEs);
strConnectInfo.pu8ReqIEs = NULL;
}
} else {
- PRINT_ER("Connect callback function pointer is NULL \n");
+ PRINT_ER("Connect callback function pointer is NULL\n");
}
}
PRINT_D(HOSTINF_DBG, "Deallocating connection parameters\n");
/* Deallocate pstrHostIFconnectAttr->pu8bssid which was prevoisuly allocated by the sending thread */
if (pstrHostIFconnectAttr->pu8bssid != NULL) {
- WILC_FREE(pstrHostIFconnectAttr->pu8bssid);
+ kfree(pstrHostIFconnectAttr->pu8bssid);
pstrHostIFconnectAttr->pu8bssid = NULL;
}
/* Deallocate pstrHostIFconnectAttr->pu8ssid which was prevoisuly allocated by the sending thread */
if (pstrHostIFconnectAttr->pu8ssid != NULL) {
- WILC_FREE(pstrHostIFconnectAttr->pu8ssid);
+ kfree(pstrHostIFconnectAttr->pu8ssid);
pstrHostIFconnectAttr->pu8ssid = NULL;
}
/* Deallocate pstrHostIFconnectAttr->pu8IEs which was prevoisuly allocated by the sending thread */
if (pstrHostIFconnectAttr->pu8IEs != NULL) {
- WILC_FREE(pstrHostIFconnectAttr->pu8IEs);
+ kfree(pstrHostIFconnectAttr->pu8IEs);
pstrHostIFconnectAttr->pu8IEs = NULL;
}
- if (pu8CurrByte != NULL) {
- WILC_FREE(pu8CurrByte);
- }
+ if (pu8CurrByte != NULL)
+ kfree(pu8CurrByte);
return s32Error;
}
@@ -2056,7 +2037,7 @@
* @version 8.0
*/
-static s32 Handle_FlushConnect(void *drvHandler)
+static s32 Handle_FlushConnect(tstrWILC_WFIDrv *drvHandler)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWIDList[5];
@@ -2123,7 +2104,7 @@
* @date
* @version 1.0
*/
-static s32 Handle_ConnectTimeout(void *drvHandler)
+static s32 Handle_ConnectTimeout(tstrWILC_WFIDrv *drvHandler)
{
s32 s32Error = WILC_SUCCESS;
tstrConnectInfo strConnectInfo;
@@ -2141,7 +2122,7 @@
gbScanWhileConnected = false;
- WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
+ memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
/* First, we will notify the upper layer with the Connection failure {through the Connect Callback function},
@@ -2149,14 +2130,14 @@
* WID_DISCONNECT} */
if (pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult != NULL) {
if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
- WILC_memcpy(strConnectInfo.au8bssid,
+ memcpy(strConnectInfo.au8bssid,
pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, 6);
}
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
strConnectInfo.ReqIEsLen = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen;
- strConnectInfo.pu8ReqIEs = (u8 *)WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
- WILC_memcpy(strConnectInfo.pu8ReqIEs,
+ strConnectInfo.pu8ReqIEs = WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
+ memcpy(strConnectInfo.pu8ReqIEs,
pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs,
pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
}
@@ -2169,11 +2150,11 @@
/* Deallocation of strConnectInfo.pu8ReqIEs */
if (strConnectInfo.pu8ReqIEs != NULL) {
- WILC_FREE(strConnectInfo.pu8ReqIEs);
+ kfree(strConnectInfo.pu8ReqIEs);
strConnectInfo.pu8ReqIEs = NULL;
}
} else {
- PRINT_ER("Connect callback function pointer is NULL \n");
+ PRINT_ER("Connect callback function pointer is NULL\n");
}
/* Here we will notify our firmware also with the Connection failure {through sending to it Cfg packet carrying
@@ -2186,37 +2167,36 @@
PRINT_D(HOSTINF_DBG, "Sending disconnect request\n");
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, false, (u32)pstrWFIDrv);
- if (s32Error) {
+ if (s32Error)
PRINT_ER("Failed to send dissconect config packet\n");
- }
/* Deallocation of the Saved Connect Request in the global Handle */
pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0;
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL;
}
if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL;
}
pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL;
}
- WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+ memset(u8ConnectedSSID, 0, ETH_ALEN);
/*BugID_5213*/
/*Freeing flushed join request params on connect timeout*/
if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
- WILC_FREE(gu8FlushedJoinReq);
+ kfree(gu8FlushedJoinReq);
gu8FlushedJoinReq = NULL;
}
if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
- WILC_FREE(gu8FlushedInfoElemAsoc);
+ kfree(gu8FlushedInfoElemAsoc);
gu8FlushedInfoElemAsoc = NULL;
}
@@ -2232,7 +2212,7 @@
* @date
* @version 1.0
*/
-static s32 Handle_RcvdNtwrkInfo(void *drvHandler, tstrRcvdNetworkInfo *pstrRcvdNetworkInfo)
+static s32 Handle_RcvdNtwrkInfo(tstrWILC_WFIDrv *drvHandler, tstrRcvdNetworkInfo *pstrRcvdNetworkInfo)
{
u32 i;
bool bNewNtwrkFound;
@@ -2264,7 +2244,7 @@
if ((pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid != NULL) &&
(pstrNetworkInfo->au8bssid != NULL)) {
- if (WILC_memcmp(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid,
+ if (memcmp(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].au8bssid,
pstrNetworkInfo->au8bssid, 6) == 0) {
if (pstrNetworkInfo->s8rssi <= pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[i].s8rssi) {
/*we have already found this network with better rssi, so keep the old cached one and don't
@@ -2294,7 +2274,7 @@
if ((pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid != NULL)
&& (pstrNetworkInfo->au8bssid != NULL)) {
- WILC_memcpy(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid,
+ memcpy(pstrWFIDrv->strWILC_UsrScanReq.astrFoundNetworkInfo[pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount].au8bssid,
pstrNetworkInfo->au8bssid, 6);
pstrWFIDrv->strWILC_UsrScanReq.u32RcvdChCount++;
@@ -2313,7 +2293,7 @@
}
} else {
- PRINT_WRN(HOSTINF_DBG, "Discovered networks exceeded max. limit \n");
+ PRINT_WRN(HOSTINF_DBG, "Discovered networks exceeded max. limit\n");
}
} else {
pstrNetworkInfo->bNewNetwork = false;
@@ -2332,7 +2312,7 @@
done:
/* Deallocate pstrRcvdNetworkInfo->pu8Buffer which was prevoisuly allocated by the sending thread */
if (pstrRcvdNetworkInfo->pu8Buffer != NULL) {
- WILC_FREE(pstrRcvdNetworkInfo->pu8Buffer);
+ kfree(pstrRcvdNetworkInfo->pu8Buffer);
pstrRcvdNetworkInfo->pu8Buffer = NULL;
}
@@ -2354,7 +2334,7 @@
* @date
* @version 1.0
*/
-static s32 Handle_RcvdGnrlAsyncInfo(void *drvHandler, tstrRcvdGnrlAsyncInfo *pstrRcvdGnrlAsyncInfo)
+static s32 Handle_RcvdGnrlAsyncInfo(tstrWILC_WFIDrv *drvHandler, tstrRcvdGnrlAsyncInfo *pstrRcvdGnrlAsyncInfo)
{
/* TODO: mostafa: till now, this function just handles only the received mac status msg, */
/* which carries only 1 WID which have WID ID = WID_STATUS */
@@ -2371,9 +2351,9 @@
tstrDisconnectNotifInfo strDisconnectNotifInfo;
s32 s32Err = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *) drvHandler;
- if (pstrWFIDrv == NULL) {
+
+ if (pstrWFIDrv == NULL)
PRINT_ER("Driver handler is NULL\n");
- }
PRINT_D(GENERIC_DBG, "Current State = %d,Received state = %d\n", pstrWFIDrv->enuHostIFstate,
pstrRcvdGnrlAsyncInfo->pu8Buffer[7]);
@@ -2417,12 +2397,12 @@
PRINT_D(HOSTINF_DBG, "Recieved MAC status = %d with Reason = %d , Code = %d\n", u8MacStatus, u8MacStatusReasonCode, u8MacStatusAdditionalInfo);
- WILC_memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
+ memset(&strConnectInfo, 0, sizeof(tstrConnectInfo));
if (u8MacStatus == MAC_CONNECTED) {
- WILC_memset(gapu8RcvdAssocResp, 0, MAX_ASSOC_RESP_FRAME_SIZE);
+ memset(gapu8RcvdAssocResp, 0, MAX_ASSOC_RESP_FRAME_SIZE);
- host_int_get_assoc_res_info((WILC_WFIDrvHandle)pstrWFIDrv,
+ host_int_get_assoc_res_info(pstrWFIDrv,
gapu8RcvdAssocResp,
MAX_ASSOC_RESP_FRAME_SIZE,
&u32RcvdAssocRespInfoLen);
@@ -2435,7 +2415,7 @@
s32Err = ParseAssocRespInfo(gapu8RcvdAssocResp, u32RcvdAssocRespInfoLen,
&pstrConnectRespInfo);
if (s32Err) {
- PRINT_ER("ParseAssocRespInfo() returned error %d \n", s32Err);
+ PRINT_ER("ParseAssocRespInfo() returned error %d\n", s32Err);
} else {
/* use the necessary parsed Info from the Received Association Response */
strConnectInfo.u16ConnectStatus = pstrConnectRespInfo->u16ConnectStatus;
@@ -2446,8 +2426,8 @@
strConnectInfo.u16RespIEsLen = pstrConnectRespInfo->u16RespIEsLen;
- strConnectInfo.pu8RespIEs = (u8 *)WILC_MALLOC(pstrConnectRespInfo->u16RespIEsLen);
- WILC_memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->pu8RespIEs,
+ strConnectInfo.pu8RespIEs = WILC_MALLOC(pstrConnectRespInfo->u16RespIEsLen);
+ memcpy(strConnectInfo.pu8RespIEs, pstrConnectRespInfo->pu8RespIEs,
pstrConnectRespInfo->u16RespIEsLen);
}
}
@@ -2466,23 +2446,23 @@
* So check first the matching between the received mac status and the received status code in Asoc Resp */
if ((u8MacStatus == MAC_CONNECTED) &&
(strConnectInfo.u16ConnectStatus != SUCCESSFUL_STATUSCODE)) {
- PRINT_ER("Received MAC status is MAC_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE \n");
- WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+ PRINT_ER("Received MAC status is MAC_CONNECTED while the received status code in Asoc Resp is not SUCCESSFUL_STATUSCODE\n");
+ memset(u8ConnectedSSID, 0, ETH_ALEN);
} else if (u8MacStatus == MAC_DISCONNECTED) {
PRINT_ER("Received MAC status is MAC_DISCONNECTED\n");
- WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+ memset(u8ConnectedSSID, 0, ETH_ALEN);
}
/* TODO: mostafa: correct BSSID should be retrieved from actual BSSID received from AP */
/* through a structure of type tstrConnectRespInfo */
if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
PRINT_D(HOSTINF_DBG, "Retrieving actual BSSID from AP\n");
- WILC_memcpy(strConnectInfo.au8bssid, pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, 6);
+ memcpy(strConnectInfo.au8bssid, pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, 6);
if ((u8MacStatus == MAC_CONNECTED) &&
(strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
- WILC_memcpy(pstrWFIDrv->au8AssociatedBSSID,
+ memcpy(pstrWFIDrv->au8AssociatedBSSID,
pstrWFIDrv->strWILC_UsrConnReq.pu8bssid, ETH_ALEN);
}
}
@@ -2490,14 +2470,14 @@
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
strConnectInfo.ReqIEsLen = pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen;
- strConnectInfo.pu8ReqIEs = (u8 *)WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
- WILC_memcpy(strConnectInfo.pu8ReqIEs,
+ strConnectInfo.pu8ReqIEs = WILC_MALLOC(pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
+ memcpy(strConnectInfo.pu8ReqIEs,
pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs,
pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen);
}
- WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), NULL);
+ del_timer(&pstrWFIDrv->hConnectTimer);
pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_CONN_RESP,
&strConnectInfo,
u8MacStatus,
@@ -2512,7 +2492,7 @@
(strConnectInfo.u16ConnectStatus == SUCCESSFUL_STATUSCODE)) {
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
- host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0);
+ host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
#endif
PRINT_D(HOSTINF_DBG, "MAC status : CONNECTED and Connect Status : Successful\n");
@@ -2521,7 +2501,8 @@
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
PRINT_D(GENERIC_DBG, "Obtaining an IP, Disable Scan\n");
g_obtainingIP = true;
- WILC_TimerStart(&hDuringIpTimer, 10000, NULL, NULL);
+ mod_timer(&hDuringIpTimer,
+ jiffies + msecs_to_jiffies(10000));
#endif
#ifdef WILC_PARSE_SCAN_IN_HOST
@@ -2540,30 +2521,30 @@
/* Deallocation */
if (strConnectInfo.pu8RespIEs != NULL) {
- WILC_FREE(strConnectInfo.pu8RespIEs);
+ kfree(strConnectInfo.pu8RespIEs);
strConnectInfo.pu8RespIEs = NULL;
}
if (strConnectInfo.pu8ReqIEs != NULL) {
- WILC_FREE(strConnectInfo.pu8ReqIEs);
+ kfree(strConnectInfo.pu8ReqIEs);
strConnectInfo.pu8ReqIEs = NULL;
}
pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0;
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL;
}
if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL;
}
pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL;
}
@@ -2572,11 +2553,11 @@
/* Disassociation or Deauthentication frame has been received */
PRINT_D(HOSTINF_DBG, "Received MAC_DISCONNECTED from the FW\n");
- WILC_memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
+ memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) {
- PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >> \n\n");
- WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
+ PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running OBSS Scan >>\n\n");
+ del_timer(&pstrWFIDrv->hScanTimer);
Handle_ScanDone((void *)pstrWFIDrv, SCAN_EVENT_ABORTED);
}
@@ -2588,7 +2569,7 @@
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
g_obtainingIP = false;
- host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0);
+ host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
#endif
pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_DISCONN_NOTIF,
@@ -2598,10 +2579,10 @@
pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid);
} else {
- PRINT_ER("Connect result callback function is NULL \n");
+ PRINT_ER("Connect result callback function is NULL\n");
}
- WILC_memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN);
+ memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN);
/* Deallocation */
@@ -2611,25 +2592,25 @@
/*
* if(strDisconnectNotifInfo.ie != NULL)
* {
- * WILC_FREE(strDisconnectNotifInfo.ie);
+ * kfree(strDisconnectNotifInfo.ie);
* strDisconnectNotifInfo.ie = NULL;
* }
*/
pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0;
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL;
}
if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL;
}
pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL;
}
@@ -2637,11 +2618,11 @@
/*Freeing flushed join request params on receiving*/
/*MAC_DISCONNECTED while connected*/
if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
- WILC_FREE(gu8FlushedJoinReq);
+ kfree(gu8FlushedJoinReq);
gu8FlushedJoinReq = NULL;
}
if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
- WILC_FREE(gu8FlushedInfoElemAsoc);
+ kfree(gu8FlushedInfoElemAsoc);
gu8FlushedInfoElemAsoc = NULL;
}
@@ -2651,13 +2632,12 @@
} else if ((u8MacStatus == MAC_DISCONNECTED) &&
(pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult != NULL)) {
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");
+ PRINT_D(HOSTINF_DBG, "\n\n<< Abort the running Scan >>\n\n");
/*Abort the running scan*/
- WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
- if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) {
- Handle_ScanDone((void *)pstrWFIDrv, SCAN_EVENT_ABORTED);
+ del_timer(&pstrWFIDrv->hScanTimer);
+ if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult)
+ Handle_ScanDone(pstrWFIDrv, SCAN_EVENT_ABORTED);
- }
}
}
@@ -2669,7 +2649,7 @@
/* Deallocate pstrRcvdGnrlAsyncInfo->pu8Buffer which was prevoisuly allocated by the sending thread */
if (pstrRcvdGnrlAsyncInfo->pu8Buffer != NULL) {
- WILC_FREE(pstrRcvdGnrlAsyncInfo->pu8Buffer);
+ kfree(pstrRcvdGnrlAsyncInfo->pu8Buffer);
pstrRcvdGnrlAsyncInfo->pu8Buffer = NULL;
}
@@ -2685,7 +2665,7 @@
* @date
* @version 1.0
*/
-static int Handle_Key(void *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
+static int Handle_Key(tstrWILC_WFIDrv *drvHandler, tstrHostIFkeyAttr *pstrHostIFkeyAttr)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -2726,7 +2706,7 @@
strWIDList[2].s32ValueSize = sizeof(char);
- pu8keybuf = (u8 *)WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen);
+ pu8keybuf = WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen);
if (pu8keybuf == NULL) {
@@ -2734,11 +2714,11 @@
return -1;
}
- WILC_memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
+ memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen);
- WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey);
+ kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey);
strWIDList[3].u16WIDid = (u16)WID_WEP_KEY_VALUE;
strWIDList[3].enuWIDtype = WID_STR;
@@ -2747,7 +2727,7 @@
s32Error = SendConfigPkt(SET_CFG, strWIDList, 4, true, (u32)pstrWFIDrv);
- WILC_FREE(pu8keybuf);
+ kfree(pu8keybuf);
}
@@ -2755,19 +2735,19 @@
if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) {
PRINT_D(HOSTINF_DBG, "Handling WEP key\n");
- pu8keybuf = (u8 *)WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen + 2);
+ pu8keybuf = WILC_MALLOC(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen + 2);
if (pu8keybuf == NULL) {
PRINT_ER("No buffer to send Key\n");
return -1;
}
pu8keybuf[0] = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx;
- WILC_memcpy(pu8keybuf + 1, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen, 1);
+ memcpy(pu8keybuf + 1, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen, 1);
- WILC_memcpy(pu8keybuf + 2, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
+ memcpy(pu8keybuf + 2, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen);
- WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey);
+ kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey);
strWID.u16WIDid = (u16)WID_ADD_WEP_KEY;
strWID.enuWIDtype = WID_STR;
@@ -2775,7 +2755,7 @@
strWID.s32ValueSize = pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwepAttr.u8WepKeylen + 2;
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
- WILC_FREE(pu8keybuf);
+ kfree(pu8keybuf);
} else if (pstrHostIFkeyAttr->u8KeyAction & REMOVEKEY) {
PRINT_D(HOSTINF_DBG, "Removing key\n");
@@ -2803,14 +2783,14 @@
case WPARxGtk:
#ifdef WILC_AP_EXTERNAL_MLME
if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY_AP) {
- pu8keybuf = (u8 *)WILC_MALLOC(RX_MIC_KEY_MSG_LEN);
+ pu8keybuf = WILC_MALLOC(RX_MIC_KEY_MSG_LEN);
if (pu8keybuf == NULL) {
PRINT_ER("No buffer to send RxGTK Key\n");
ret = -1;
goto _WPARxGtk_end_case_;
}
- WILC_memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN);
+ memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN);
/*|----------------------------------------------------------------------------|
@@ -2821,14 +2801,14 @@
if (pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq != NULL)
- WILC_memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8);
+ memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8);
- WILC_memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
+ memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
- WILC_memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
+ memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
- WILC_memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+ memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen);
/* pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Ciphermode = 0X51; */
strWIDList[0].u16WIDid = (u16)WID_11I_MODE;
@@ -2843,7 +2823,7 @@
s32Error = SendConfigPkt(SET_CFG, strWIDList, 2, true, (u32)pstrWFIDrv);
- WILC_FREE(pu8keybuf);
+ kfree(pu8keybuf);
/* ////////////////////////// */
up(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -2854,14 +2834,14 @@
if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) {
PRINT_D(HOSTINF_DBG, "Handling group key(Rx) function\n");
- pu8keybuf = (u8 *)WILC_MALLOC(RX_MIC_KEY_MSG_LEN);
+ pu8keybuf = WILC_MALLOC(RX_MIC_KEY_MSG_LEN);
if (pu8keybuf == NULL) {
PRINT_ER("No buffer to send RxGTK Key\n");
ret = -1;
goto _WPARxGtk_end_case_;
}
- WILC_memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN);
+ memset(pu8keybuf, 0, RX_MIC_KEY_MSG_LEN);
/*|----------------------------------------------------------------------------|
@@ -2869,18 +2849,17 @@
* |------------|---------|-------|------------|---------------|----------------|
| 6 bytes | 8 byte |1 byte | 1 byte | 16 bytes | 8 bytes |*/
- if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED) {
- WILC_memcpy(pu8keybuf, pstrWFIDrv->au8AssociatedBSSID, ETH_ALEN);
- } else {
- PRINT_ER("Couldn't handle WPARxGtk while enuHostIFstate is not HOST_IF_CONNECTED \n");
- }
+ if (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTED)
+ memcpy(pu8keybuf, pstrWFIDrv->au8AssociatedBSSID, ETH_ALEN);
+ else
+ PRINT_ER("Couldn't handle WPARxGtk while enuHostIFstate is not HOST_IF_CONNECTED\n");
- WILC_memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8);
+ memcpy(pu8keybuf + 6, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq, 8);
- WILC_memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
+ memcpy(pu8keybuf + 14, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
- WILC_memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
- WILC_memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+ memcpy(pu8keybuf + 15, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
+ memcpy(pu8keybuf + 16, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen);
strWID.u16WIDid = (u16)WID_ADD_RX_GTK;
@@ -2890,15 +2869,15 @@
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
- WILC_FREE(pu8keybuf);
+ kfree(pu8keybuf);
/* ////////////////////////// */
up(&(pstrWFIDrv->hSemTestKeyBlock));
/* ///////////////////////// */
}
_WPARxGtk_end_case_:
- WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key);
- WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq);
+ kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key);
+ kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq);
if (ret == -1)
return ret;
@@ -2909,7 +2888,7 @@
if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY_AP) {
- pu8keybuf = (u8 *)WILC_MALLOC(PTK_KEY_MSG_LEN + 1);
+ pu8keybuf = WILC_MALLOC(PTK_KEY_MSG_LEN + 1);
@@ -2926,12 +2905,12 @@
| 6 bytes | 1 byte | 1byte | 16 bytes | 8 bytes | 8 bytes |
|-----------------------------------------------------------------------------|*/
- WILC_memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6); /*1 bytes Key Length */
+ memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6); /*1 bytes Key Length */
- WILC_memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
- WILC_memcpy(pu8keybuf + 7, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
+ memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8keyidx, 1);
+ memcpy(pu8keybuf + 7, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
/*16 byte TK*/
- WILC_memcpy(pu8keybuf + 8, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+ memcpy(pu8keybuf + 8, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen);
@@ -2946,7 +2925,7 @@
strWIDList[1].s32ValueSize = PTK_KEY_MSG_LEN + 1;
s32Error = SendConfigPkt(SET_CFG, strWIDList, 2, true, (u32)pstrWFIDrv);
- WILC_FREE(pu8keybuf);
+ kfree(pu8keybuf);
/* ////////////////////////// */
up(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -2956,7 +2935,7 @@
if (pstrHostIFkeyAttr->u8KeyAction & ADDKEY) {
- pu8keybuf = (u8 *)WILC_MALLOC(PTK_KEY_MSG_LEN);
+ pu8keybuf = WILC_MALLOC(PTK_KEY_MSG_LEN);
@@ -2973,11 +2952,11 @@
| 6 bytes | 1byte | 16 bytes | 8 bytes | 8 bytes |
|-----------------------------------------------------------------------------|*/
- WILC_memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6); /*1 bytes Key Length */
+ memcpy(pu8keybuf, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8macaddr, 6); /*1 bytes Key Length */
- WILC_memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
+ memcpy(pu8keybuf + 6, &pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen, 1);
/*16 byte TK*/
- WILC_memcpy(pu8keybuf + 7, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+ memcpy(pu8keybuf + 7, pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.u8Keylen);
@@ -2987,7 +2966,7 @@
strWID.s32ValueSize = PTK_KEY_MSG_LEN;
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
- WILC_FREE(pu8keybuf);
+ kfree(pu8keybuf);
/* ////////////////////////// */
up(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -2995,7 +2974,7 @@
}
_WPAPtk_end_case_:
- WILC_FREE(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key);
+ kfree(pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFwpaAttr.pu8key);
if (ret == -1)
return ret;
@@ -3006,7 +2985,7 @@
PRINT_D(HOSTINF_DBG, "Handling PMKSA key\n");
- pu8keybuf = (u8 *)WILC_MALLOC((pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid * PMKSA_KEY_LEN) + 1);
+ pu8keybuf = WILC_MALLOC((pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid * PMKSA_KEY_LEN) + 1);
if (pu8keybuf == NULL) {
PRINT_ER("No buffer to send PMKSA Key\n");
return -1;
@@ -3016,8 +2995,8 @@
for (i = 0; i < pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.numpmkid; i++) {
- WILC_memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, ETH_ALEN);
- WILC_memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, PMKID_LEN);
+ memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, ETH_ALEN);
+ memcpy(pu8keybuf + ((PMKSA_KEY_LEN * i) + ETH_ALEN + 1), pstrHostIFkeyAttr->uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, PMKID_LEN);
}
strWID.u16WIDid = (u16)WID_PMKID_INFO;
@@ -3027,7 +3006,7 @@
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
- WILC_FREE(pu8keybuf);
+ kfree(pu8keybuf);
break;
}
@@ -3048,7 +3027,7 @@
* @date
* @version 1.0
*/
-static void Handle_Disconnect(void *drvHandler)
+static void Handle_Disconnect(tstrWILC_WFIDrv *drvHandler)
{
tstrWID strWID;
@@ -3069,10 +3048,10 @@
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
g_obtainingIP = false;
- host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0);
+ host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
#endif
- WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+ memset(u8ConnectedSSID, 0, ETH_ALEN);
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, false, (u32)pstrWFIDrv);
@@ -3082,14 +3061,14 @@
} else {
tstrDisconnectNotifInfo strDisconnectNotifInfo;
- WILC_memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
+ memset(&strDisconnectNotifInfo, 0, sizeof(tstrDisconnectNotifInfo));
strDisconnectNotifInfo.u16reason = 0;
strDisconnectNotifInfo.ie = NULL;
strDisconnectNotifInfo.ie_len = 0;
if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) {
- WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
+ del_timer(&pstrWFIDrv->hScanTimer);
pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult(SCAN_EVENT_ABORTED, NULL,
pstrWFIDrv->strWILC_UsrScanReq.u32UserScanPvoid, NULL);
@@ -3102,48 +3081,48 @@
/*Stop connect timer, if connection in progress*/
if (pstrWFIDrv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) {
PRINT_D(HOSTINF_DBG, "Upper layer requested termination of connection\n");
- WILC_TimerStop(&(pstrWFIDrv->hConnectTimer), NULL);
+ del_timer(&pstrWFIDrv->hConnectTimer);
}
pstrWFIDrv->strWILC_UsrConnReq.pfUserConnectResult(CONN_DISCONN_EVENT_DISCONN_NOTIF, NULL,
0, &strDisconnectNotifInfo, pstrWFIDrv->strWILC_UsrConnReq.u32UserConnectPvoid);
} else {
- PRINT_ER("strWILC_UsrConnReq.pfUserConnectResult = NULL \n");
+ PRINT_ER("strWILC_UsrConnReq.pfUserConnectResult = NULL\n");
}
gbScanWhileConnected = false;
pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
- WILC_memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN);
+ memset(pstrWFIDrv->au8AssociatedBSSID, 0, ETH_ALEN);
/* Deallocation */
pstrWFIDrv->strWILC_UsrConnReq.ssidLen = 0;
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ssid != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ssid);
pstrWFIDrv->strWILC_UsrConnReq.pu8ssid = NULL;
}
if (pstrWFIDrv->strWILC_UsrConnReq.pu8bssid != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8bssid);
pstrWFIDrv->strWILC_UsrConnReq.pu8bssid = NULL;
}
pstrWFIDrv->strWILC_UsrConnReq.ConnReqIEsLen = 0;
if (pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs != NULL) {
- WILC_FREE(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
+ kfree(pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs);
pstrWFIDrv->strWILC_UsrConnReq.pu8ConnReqIEs = NULL;
}
/*BugID_5137*/
if (gu8FlushedJoinReq != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
- WILC_FREE(gu8FlushedJoinReq);
+ kfree(gu8FlushedJoinReq);
gu8FlushedJoinReq = NULL;
}
if (gu8FlushedInfoElemAsoc != NULL && gu8FlushedJoinReqDrvHandler == (u32)drvHandler) {
- WILC_FREE(gu8FlushedInfoElemAsoc);
+ kfree(gu8FlushedInfoElemAsoc);
gu8FlushedInfoElemAsoc = NULL;
}
@@ -3161,7 +3140,7 @@
}
-void resolve_disconnect_aberration(void *drvHandler)
+void resolve_disconnect_aberration(tstrWILC_WFIDrv *drvHandler)
{
tstrWILC_WFIDrv *pstrWFIDrv;
@@ -3170,10 +3149,10 @@
return;
if ((pstrWFIDrv->enuHostIFstate == HOST_IF_WAITING_CONN_RESP) || (pstrWFIDrv->enuHostIFstate == HOST_IF_CONNECTING)) {
PRINT_D(HOSTINF_DBG, "\n\n<< correcting Supplicant state machine >>\n\n");
- host_int_disconnect((WILC_WFIDrvHandle)pstrWFIDrv, 1);
+ host_int_disconnect(pstrWFIDrv, 1);
}
}
-static s32 Switch_Log_Terminal(void *drvHandler)
+static s32 Switch_Log_Terminal(tstrWILC_WFIDrv *drvHandler)
{
@@ -3194,7 +3173,7 @@
PRINT_D(HOSTINF_DBG, "Failed to switch log terminal\n");
WILC_ERRORREPORT(s32Error, WILC_INVALID_STATE);
} else {
- PRINT_INFO(HOSTINF_DBG, "MAC address set :: \n");
+ PRINT_INFO(HOSTINF_DBG, "MAC address set ::\n");
}
@@ -3217,13 +3196,14 @@
* @date
* @version 1.0
*/
-static s32 Handle_GetChnl(void *drvHandler)
+static s32 Handle_GetChnl(tstrWILC_WFIDrv *drvHandler)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
/* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
strWID.u16WIDid = (u16)WID_CURRENT_CHANNEL;
strWID.enuWIDtype = WID_CHAR;
strWID.ps8WidVal = (s8 *)&gu8Chnl;
@@ -3261,7 +3241,7 @@
* @date
* @version 1.0
*/
-static void Handle_GetRssi(void *drvHandler)
+static void Handle_GetRssi(tstrWILC_WFIDrv *drvHandler)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -3291,7 +3271,7 @@
}
-static void Handle_GetLinkspeed(void *drvHandler)
+static void Handle_GetLinkspeed(tstrWILC_WFIDrv *drvHandler)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -3321,7 +3301,7 @@
}
-s32 Handle_GetStatistics(void *drvHandler, tstrStatistics *pstrStatistics)
+s32 Handle_GetStatistics(tstrWILC_WFIDrv *drvHandler, tstrStatistics *pstrStatistics)
{
tstrWID strWIDList[5];
uint32_t u32WidsCount = 0, s32Error = 0;
@@ -3382,7 +3362,7 @@
* @date
* @version 1.0
*/
-static s32 Handle_Get_InActiveTime(void *drvHandler, tstrHostIfStaInactiveT *strHostIfStaInactiveT)
+static s32 Handle_Get_InActiveTime(tstrWILC_WFIDrv *drvHandler, tstrHostIfStaInactiveT *strHostIfStaInactiveT)
{
s32 s32Error = WILC_SUCCESS;
@@ -3394,11 +3374,11 @@
strWID.u16WIDid = (u16)WID_SET_STA_MAC_INACTIVE_TIME;
strWID.enuWIDtype = WID_STR;
strWID.s32ValueSize = ETH_ALEN;
- strWID.ps8WidVal = (u8 *)WILC_MALLOC(strWID.s32ValueSize);
+ strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
stamac = strWID.ps8WidVal;
- WILC_memcpy(stamac, strHostIfStaInactiveT->mac, ETH_ALEN);
+ memcpy(stamac, strHostIfStaInactiveT->mac, ETH_ALEN);
PRINT_D(CFG80211_DBG, "SETING STA inactive time\n");
@@ -3451,21 +3431,21 @@
* @date
* @version 1.0
*/
-static void Handle_AddBeacon(void *drvHandler, tstrHostIFSetBeacon *pstrSetBeaconParam)
+static void Handle_AddBeacon(tstrWILC_WFIDrv *drvHandler, tstrHostIFSetBeacon *pstrSetBeaconParam)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
u8 *pu8CurrByte;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
PRINT_D(HOSTINF_DBG, "Adding BEACON\n");
strWID.u16WIDid = (u16)WID_ADD_BEACON;
strWID.enuWIDtype = WID_BIN;
strWID.s32ValueSize = pstrSetBeaconParam->u32HeadLen + pstrSetBeaconParam->u32TailLen + 16;
strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWID.ps8WidVal;
*pu8CurrByte++ = (pstrSetBeaconParam->u32Interval & 0xFF);
@@ -3508,9 +3488,9 @@
WILC_CATCH(s32Error)
{
}
- WILC_FREE_IF_TRUE(strWID.ps8WidVal);
- WILC_FREE_IF_TRUE(pstrSetBeaconParam->pu8Head);
- WILC_FREE_IF_TRUE(pstrSetBeaconParam->pu8Tail);
+ kfree(strWID.ps8WidVal);
+ kfree(pstrSetBeaconParam->pu8Head);
+ kfree(pstrSetBeaconParam->pu8Tail);
}
@@ -3523,20 +3503,20 @@
* @date
* @version 1.0
*/
-static void Handle_DelBeacon(void *drvHandler, tstrHostIFDelBeacon *pstrDelBeacon)
+static void Handle_DelBeacon(tstrWILC_WFIDrv *drvHandler, tstrHostIFDelBeacon *pstrDelBeacon)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
u8 *pu8CurrByte;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
strWID.u16WIDid = (u16)WID_DEL_BEACON;
strWID.enuWIDtype = WID_CHAR;
strWID.s32ValueSize = sizeof(char);
strWID.ps8WidVal = &gu8DelBcn;
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWID.ps8WidVal;
@@ -3573,16 +3553,15 @@
pu8CurrByte = pu8Buffer;
PRINT_D(HOSTINF_DBG, "Packing STA params\n");
- WILC_memcpy(pu8CurrByte, pstrStationParam->au8BSSID, ETH_ALEN);
+ memcpy(pu8CurrByte, pstrStationParam->au8BSSID, ETH_ALEN);
pu8CurrByte += ETH_ALEN;
*pu8CurrByte++ = pstrStationParam->u16AssocID & 0xFF;
*pu8CurrByte++ = (pstrStationParam->u16AssocID >> 8) & 0xFF;
*pu8CurrByte++ = pstrStationParam->u8NumRates;
- if (pstrStationParam->u8NumRates > 0) {
- WILC_memcpy(pu8CurrByte, pstrStationParam->pu8Rates, pstrStationParam->u8NumRates);
- }
+ if (pstrStationParam->u8NumRates > 0)
+ memcpy(pu8CurrByte, pstrStationParam->pu8Rates, pstrStationParam->u8NumRates);
pu8CurrByte += pstrStationParam->u8NumRates;
*pu8CurrByte++ = pstrStationParam->bIsHTSupported;
@@ -3590,7 +3569,7 @@
*pu8CurrByte++ = (pstrStationParam->u16HTCapInfo >> 8) & 0xFF;
*pu8CurrByte++ = pstrStationParam->u8AmpduParams;
- WILC_memcpy(pu8CurrByte, pstrStationParam->au8SuppMCsSet, WILC_SUPP_MCS_SET_SIZE);
+ memcpy(pu8CurrByte, pstrStationParam->au8SuppMCsSet, WILC_SUPP_MCS_SET_SIZE);
pu8CurrByte += WILC_SUPP_MCS_SET_SIZE;
*pu8CurrByte++ = pstrStationParam->u16HTExtParams & 0xFF;
@@ -3621,21 +3600,21 @@
* @date
* @version 1.0
*/
-static void Handle_AddStation(void *drvHandler, tstrWILC_AddStaParam *pstrStationParam)
+static void Handle_AddStation(tstrWILC_WFIDrv *drvHandler, tstrWILC_AddStaParam *pstrStationParam)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
u8 *pu8CurrByte;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
PRINT_D(HOSTINF_DBG, "Handling add station\n");
strWID.u16WIDid = (u16)WID_ADD_STA;
strWID.enuWIDtype = WID_BIN;
strWID.s32ValueSize = WILC_ADD_STA_LENGTH + pstrStationParam->u8NumRates;
strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWID.ps8WidVal;
pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
@@ -3651,8 +3630,8 @@
WILC_CATCH(s32Error)
{
}
- WILC_FREE_IF_TRUE(pstrStationParam->pu8Rates);
- WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+ kfree(pstrStationParam->pu8Rates);
+ kfree(strWID.ps8WidVal);
}
/**
@@ -3664,24 +3643,25 @@
* @date
* @version 1.0
*/
-static void Handle_DelAllSta(void *drvHandler, tstrHostIFDelAllSta *pstrDelAllStaParam)
+static void Handle_DelAllSta(tstrWILC_WFIDrv *drvHandler, tstrHostIFDelAllSta *pstrDelAllStaParam)
{
s32 s32Error = WILC_SUCCESS;
+
tstrWID strWID;
u8 *pu8CurrByte;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
u8 i;
u8 au8Zero_Buff[6] = {0};
+
strWID.u16WIDid = (u16)WID_DEL_ALL_STA;
strWID.enuWIDtype = WID_STR;
strWID.s32ValueSize = (pstrDelAllStaParam->u8Num_AssocSta * ETH_ALEN) + 1;
- PRINT_D(HOSTINF_DBG, "Handling delete station \n");
+ PRINT_D(HOSTINF_DBG, "Handling delete station\n");
strWID.ps8WidVal = WILC_MALLOC((pstrDelAllStaParam->u8Num_AssocSta * ETH_ALEN) + 1);
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWID.ps8WidVal;
@@ -3689,7 +3669,7 @@
for (i = 0; i < MAX_NUM_STA; i++) {
if (memcmp(pstrDelAllStaParam->au8Sta_DelAllSta[i], au8Zero_Buff, ETH_ALEN))
- WILC_memcpy(pu8CurrByte, pstrDelAllStaParam->au8Sta_DelAllSta[i], ETH_ALEN);
+ memcpy(pu8CurrByte, pstrDelAllStaParam->au8Sta_DelAllSta[i], ETH_ALEN);
else
continue;
@@ -3700,14 +3680,14 @@
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
if (s32Error) {
- PRINT_ER("Failed to send add station config packe\n");
+ PRINT_ER("Failed to send add station config packet\n");
WILC_ERRORREPORT(s32Error, WILC_FAIL);
}
WILC_CATCH(s32Error)
{
}
- WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+ kfree(strWID.ps8WidVal);
up(&hWaitResponse);
}
@@ -3722,7 +3702,7 @@
* @date
* @version 1.0
*/
-static void Handle_DelStation(void *drvHandler, tstrHostIFDelSta *pstrDelStaParam)
+static void Handle_DelStation(tstrWILC_WFIDrv *drvHandler, tstrHostIFDelSta *pstrDelStaParam)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -3733,29 +3713,28 @@
strWID.enuWIDtype = WID_BIN;
strWID.s32ValueSize = ETH_ALEN;
- PRINT_D(HOSTINF_DBG, "Handling delete station \n");
+ PRINT_D(HOSTINF_DBG, "Handling delete station\n");
strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWID.ps8WidVal;
- WILC_memcpy(pu8CurrByte, pstrDelStaParam->au8MacAddr, ETH_ALEN);
+ memcpy(pu8CurrByte, pstrDelStaParam->au8MacAddr, ETH_ALEN);
/*Sending Cfg*/
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, false, (u32)pstrWFIDrv);
if (s32Error) {
- PRINT_ER("Failed to send add station config packe\n");
+ PRINT_ER("Failed to send add station config packet\n");
WILC_ERRORREPORT(s32Error, WILC_FAIL);
}
WILC_CATCH(s32Error)
{
}
- WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+ kfree(strWID.ps8WidVal);
}
@@ -3768,7 +3747,7 @@
* @date
* @version 1.0
*/
-static void Handle_EditStation(void *drvHandler, tstrWILC_AddStaParam *pstrStationParam)
+static void Handle_EditStation(tstrWILC_WFIDrv *drvHandler, tstrWILC_AddStaParam *pstrStationParam)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -3781,9 +3760,8 @@
PRINT_D(HOSTINF_DBG, "Handling edit station\n");
strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWID.ps8WidVal;
pu8CurrByte += WILC_HostIf_PackStaParam(pu8CurrByte, pstrStationParam);
@@ -3799,8 +3777,8 @@
WILC_CATCH(s32Error)
{
}
- WILC_FREE_IF_TRUE(pstrStationParam->pu8Rates);
- WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+ kfree(pstrStationParam->pu8Rates);
+ kfree(strWID.ps8WidVal);
}
#endif /*WILC_AP_EXTERNAL_MLME*/
@@ -3814,7 +3792,7 @@
* @date
* @version 1.0
*/
-static int Handle_RemainOnChan(void *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan)
+static int Handle_RemainOnChan(tstrWILC_WFIDrv *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan)
{
s32 s32Error = WILC_SUCCESS;
u8 u8remain_on_chan_flag;
@@ -3856,30 +3834,30 @@
strWID.u16WIDid = (u16)WID_REMAIN_ON_CHAN;
strWID.enuWIDtype = WID_STR;
strWID.s32ValueSize = 2;
- strWID.ps8WidVal = (s8 *)WILC_MALLOC(strWID.s32ValueSize);
+ strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
strWID.ps8WidVal[0] = u8remain_on_chan_flag;
strWID.ps8WidVal[1] = (s8)pstrHostIfRemainOnChan->u16Channel;
/*Sending Cfg*/
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
- if (s32Error != WILC_SUCCESS) {
+ if (s32Error != WILC_SUCCESS)
PRINT_ER("Failed to set remain on channel\n");
- }
WILC_CATCH(-1)
{
P2P_LISTEN_STATE = 1;
- WILC_TimerStart(&(pstrWFIDrv->hRemainOnChannel), pstrHostIfRemainOnChan->u32duration, (void *)pstrWFIDrv, NULL);
+ pstrWFIDrv->hRemainOnChannel.data = (unsigned long)pstrWFIDrv;
+ mod_timer(&pstrWFIDrv->hRemainOnChannel,
+ jiffies +
+ msecs_to_jiffies(pstrHostIfRemainOnChan->u32duration));
/*Calling CFG ready_on_channel*/
- if (pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanReady) {
+ if (pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanReady)
pstrWFIDrv->strHostIfRemainOnChan.pRemainOnChanReady(pstrWFIDrv->strHostIfRemainOnChan.pVoid);
- }
if (pstrWFIDrv->u8RemainOnChan_pendingreq)
pstrWFIDrv->u8RemainOnChan_pendingreq = 0;
@@ -3896,7 +3874,7 @@
* @date
* @version 1.0
*/
-static int Handle_RegisterFrame(void *drvHandler, tstrHostIfRegisterFrame *pstrHostIfRegisterFrame)
+static int Handle_RegisterFrame(tstrWILC_WFIDrv *drvHandler, tstrHostIfRegisterFrame *pstrHostIfRegisterFrame)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -3909,15 +3887,14 @@
strWID.u16WIDid = (u16)WID_REGISTER_FRAME;
strWID.enuWIDtype = WID_STR;
strWID.ps8WidVal = WILC_MALLOC(sizeof(u16) + 2);
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWID.ps8WidVal;
*pu8CurrByte++ = pstrHostIfRegisterFrame->bReg;
*pu8CurrByte++ = pstrHostIfRegisterFrame->u8Regid;
- WILC_memcpy(pu8CurrByte, &(pstrHostIfRegisterFrame->u16FrameType), sizeof(u16));
+ memcpy(pu8CurrByte, &(pstrHostIfRegisterFrame->u16FrameType), sizeof(u16));
strWID.s32ValueSize = sizeof(u16) + 2;
@@ -3949,7 +3926,7 @@
* @version 1.0
*/
#define FALSE_FRMWR_CHANNEL 100
-static u32 Handle_ListenStateExpired(void *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan)
+static u32 Handle_ListenStateExpired(tstrWILC_WFIDrv *drvHandler, tstrHostIfRemainOnChan *pstrHostIfRemainOnChan)
{
u8 u8remain_on_chan_flag;
tstrWID strWID;
@@ -3968,9 +3945,8 @@
strWID.s32ValueSize = 2;
strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
PRINT_ER("Failed to allocate memory\n");
- }
strWID.ps8WidVal[0] = u8remain_on_chan_flag;
strWID.ps8WidVal[1] = FALSE_FRMWR_CHANNEL;
@@ -4006,25 +3982,24 @@
* @date
* @version 1.0
*/
-static void ListenTimerCB(void *pvArg)
+static void ListenTimerCB(unsigned long arg)
{
s32 s32Error = WILC_SUCCESS;
tstrHostIFmsg strHostIFmsg;
- tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)pvArg;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)arg;
/*Stopping remain-on-channel timer*/
- WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), NULL);
+ del_timer(&pstrWFIDrv->hRemainOnChannel);
/* prepare the Timer Callback message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_LISTEN_TIMER_FIRED;
strHostIFmsg.drvHandler = pstrWFIDrv;
strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = pstrWFIDrv->strHostIfRemainOnChan.u32ListenSessionID;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -4042,19 +4017,19 @@
* @date
* @version 1.0
*/
-static void Handle_PowerManagement(void *drvHandler, tstrHostIfPowerMgmtParam *strPowerMgmtParam)
+static void Handle_PowerManagement(tstrWILC_WFIDrv *drvHandler, tstrHostIfPowerMgmtParam *strPowerMgmtParam)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
s8 s8PowerMode;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
+
strWID.u16WIDid = (u16)WID_POWER_MANAGEMENT;
- if (strPowerMgmtParam->bIsEnabled == true) {
+ if (strPowerMgmtParam->bIsEnabled == true)
s8PowerMode = MIN_FAST_PS;
- } else {
+ else
s8PowerMode = NO_POWERSAVE;
- }
PRINT_D(HOSTINF_DBG, "Handling power mgmt to %d\n", s8PowerMode);
strWID.ps8WidVal = &s8PowerMode;
strWID.s32ValueSize = sizeof(char);
@@ -4083,7 +4058,7 @@
* @date
* @version 1.0
*/
-static void Handle_SetMulticastFilter(void *drvHandler, tstrHostIFSetMulti *strHostIfSetMulti)
+static void Handle_SetMulticastFilter(tstrWILC_WFIDrv *drvHandler, tstrHostIFSetMulti *strHostIfSetMulti)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -4095,9 +4070,8 @@
strWID.enuWIDtype = WID_BIN;
strWID.s32ValueSize = sizeof(tstrHostIFSetMulti) + ((strHostIfSetMulti->u32count) * ETH_ALEN);
strWID.ps8WidVal = WILC_MALLOC(strWID.s32ValueSize);
- if (strWID.ps8WidVal == NULL) {
+ if (strWID.ps8WidVal == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
pu8CurrByte = strWID.ps8WidVal;
*pu8CurrByte++ = (strHostIfSetMulti->bIsEnabled & 0xFF);
@@ -4123,7 +4097,7 @@
WILC_CATCH(s32Error)
{
}
- WILC_FREE_IF_TRUE(strWID.ps8WidVal);
+ kfree(strWID.ps8WidVal);
}
@@ -4138,7 +4112,7 @@
* @date Feb. 2014
* @version 9.0
*/
-static s32 Handle_AddBASession(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
+static s32 Handle_AddBASession(tstrWILC_WFIDrv *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -4146,7 +4120,7 @@
char *ptr = NULL;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
- PRINT_D(HOSTINF_DBG, "Opening Block Ack session with\nBSSID = %.2x:%.2x:%.2x \nTID=%d \nBufferSize == %d \nSessionTimeOut = %d\n",
+ PRINT_D(HOSTINF_DBG, "Opening Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\nBufferSize == %d\nSessionTimeOut = %d\n",
strHostIfBASessionInfo->au8Bssid[0],
strHostIfBASessionInfo->au8Bssid[1],
strHostIfBASessionInfo->au8Bssid[2],
@@ -4156,14 +4130,14 @@
strWID.u16WIDid = (u16)WID_11E_P_ACTION_REQ;
strWID.enuWIDtype = WID_STR;
- strWID.ps8WidVal = (u8 *)WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
+ strWID.ps8WidVal = WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
strWID.s32ValueSize = BLOCK_ACK_REQ_SIZE;
ptr = strWID.ps8WidVal;
/* *ptr++ = 0x14; */
*ptr++ = 0x14;
*ptr++ = 0x3;
*ptr++ = 0x0;
- WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+ memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
ptr += ETH_ALEN;
*ptr++ = strHostIfBASessionInfo->u8Ted;
/* BA Policy*/
@@ -4195,7 +4169,7 @@
*ptr++ = 15;
*ptr++ = 7;
*ptr++ = 0x2;
- WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+ memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
ptr += ETH_ALEN;
/* TID*/
*ptr++ = strHostIfBASessionInfo->u8Ted;
@@ -4209,7 +4183,7 @@
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
if (strWID.ps8WidVal != NULL)
- WILC_FREE(strWID.ps8WidVal);
+ kfree(strWID.ps8WidVal);
return s32Error;
@@ -4226,14 +4200,14 @@
* @date Feb. 2013
* @version 9.0
*/
-static s32 Handle_DelBASession(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
+static s32 Handle_DelBASession(tstrWILC_WFIDrv *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
char *ptr = NULL;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
- PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x \nTID=%d\n",
+ PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\n",
strHostIfBASessionInfo->au8Bssid[0],
strHostIfBASessionInfo->au8Bssid[1],
strHostIfBASessionInfo->au8Bssid[2],
@@ -4241,14 +4215,14 @@
strWID.u16WIDid = (u16)WID_11E_P_ACTION_REQ;
strWID.enuWIDtype = WID_STR;
- strWID.ps8WidVal = (u8 *)WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
+ strWID.ps8WidVal = WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
strWID.s32ValueSize = BLOCK_ACK_REQ_SIZE;
ptr = strWID.ps8WidVal;
/* *ptr++ = 0x14; */
*ptr++ = 0x14;
*ptr++ = 0x3;
*ptr++ = 0x2;
- WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+ memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
ptr += ETH_ALEN;
*ptr++ = strHostIfBASessionInfo->u8Ted;
/* BA direction = recipent*/
@@ -4269,7 +4243,7 @@
*ptr++ = 15;
*ptr++ = 7;
*ptr++ = 0x3;
- WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+ memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
ptr += ETH_ALEN;
/* TID*/
*ptr++ = strHostIfBASessionInfo->u8Ted;
@@ -4277,7 +4251,7 @@
s32Error = SendConfigPkt(SET_CFG, &strWID, 1, true, (u32)pstrWFIDrv);
if (strWID.ps8WidVal != NULL)
- WILC_FREE(strWID.ps8WidVal);
+ kfree(strWID.ps8WidVal);
/*BugID_5222*/
up(&hWaitResponse);
@@ -4296,14 +4270,14 @@
* @date Feb. 2013
* @version 9.0
*/
-static s32 Handle_DelAllRxBASessions(void *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
+static s32 Handle_DelAllRxBASessions(tstrWILC_WFIDrv *drvHandler, tstrHostIfBASessionInfo *strHostIfBASessionInfo)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
char *ptr = NULL;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
- PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x \nTID=%d\n",
+ PRINT_D(GENERIC_DBG, "Delete Block Ack session with\nBSSID = %.2x:%.2x:%.2x\nTID=%d\n",
strHostIfBASessionInfo->au8Bssid[0],
strHostIfBASessionInfo->au8Bssid[1],
strHostIfBASessionInfo->au8Bssid[2],
@@ -4311,13 +4285,13 @@
strWID.u16WIDid = (u16)WID_DEL_ALL_RX_BA;
strWID.enuWIDtype = WID_STR;
- strWID.ps8WidVal = (u8 *)WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
+ strWID.ps8WidVal = WILC_MALLOC(BLOCK_ACK_REQ_SIZE);
strWID.s32ValueSize = BLOCK_ACK_REQ_SIZE;
ptr = strWID.ps8WidVal;
*ptr++ = 0x14;
*ptr++ = 0x3;
*ptr++ = 0x2;
- WILC_memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
+ memcpy(ptr, strHostIfBASessionInfo->au8Bssid, ETH_ALEN);
ptr += ETH_ALEN;
*ptr++ = strHostIfBASessionInfo->u8Ted;
/* BA direction = recipent*/
@@ -4331,7 +4305,7 @@
if (strWID.ps8WidVal != NULL)
- WILC_FREE(strWID.ps8WidVal);
+ kfree(strWID.ps8WidVal);
/*BugID_5222*/
up(&hWaitResponse);
@@ -4355,10 +4329,10 @@
tstrHostIFmsg strHostIFmsg;
tstrWILC_WFIDrv *pstrWFIDrv;
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
while (1) {
- WILC_MsgQueueRecv(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), &u32Ret, NULL);
+ WILC_MsgQueueRecv(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), &u32Ret);
pstrWFIDrv = (tstrWILC_WFIDrv *)strHostIFmsg.drvHandler;
if (strHostIFmsg.u16MsgId == HOST_IF_MSG_EXIT) {
PRINT_D(GENERIC_DBG, "THREAD: Exiting HostIfThread\n");
@@ -4369,15 +4343,15 @@
/*Re-Queue HIF message*/
if ((!g_wilc_initialized)) {
PRINT_D(GENERIC_DBG, "--WAIT--");
- WILC_Sleep(200);
- WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ usleep_range(200 * 1000, 200 * 1000);
+ WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
continue;
}
if (strHostIFmsg.u16MsgId == HOST_IF_MSG_CONNECT && pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult != NULL) {
PRINT_D(HOSTINF_DBG, "Requeue connect request till scan done received\n");
- WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- WILC_Sleep(2);
+ WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ usleep_range(2 * 1000, 2 * 1000);
continue;
}
@@ -4425,14 +4399,13 @@
break;
case HOST_IF_MSG_RCVD_SCAN_COMPLETE:
- WILC_TimerStop(&(pstrWFIDrv->hScanTimer), NULL);
+ del_timer(&pstrWFIDrv->hScanTimer);
PRINT_D(HOSTINF_DBG, "scan completed successfully\n");
/*BugID_5213*/
/*Allow chip sleep, only if both interfaces are not connected*/
- if (!linux_wlan_get_num_conn_ifcs()) {
+ if (!linux_wlan_get_num_conn_ifcs())
chip_sleep_manually(INFINITE_SLEEP_TIME);
- }
Handle_ScanDone(strHostIFmsg.drvHandler, SCAN_EVENT_DONE);
@@ -4492,7 +4465,7 @@
break;
case HOST_IF_MSG_CONNECT_TIMER_FIRED:
- PRINT_D(HOSTINF_DBG, "Connect Timeout \n");
+ PRINT_D(HOSTINF_DBG, "Connect Timeout\n");
Handle_ConnectTimeout(strHostIFmsg.drvHandler);
break;
@@ -4563,7 +4536,7 @@
break;
default:
- PRINT_ER("[Host Interface] undefined Received Msg ID \n");
+ PRINT_ER("[Host Interface] undefined Received Msg ID\n");
break;
}
}
@@ -4573,30 +4546,32 @@
return 0;
}
-static void TimerCB_Scan(void *pvArg)
+static void TimerCB_Scan(unsigned long arg)
{
+ void *pvArg = (void *)arg;
tstrHostIFmsg strHostIFmsg;
/* prepare the Timer Callback message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.drvHandler = pvArg;
strHostIFmsg.u16MsgId = HOST_IF_MSG_SCAN_TIMER_FIRED;
/* send the message */
- WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
}
-static void TimerCB_Connect(void *pvArg)
+static void TimerCB_Connect(unsigned long arg)
{
+ void *pvArg = (void *)arg;
tstrHostIFmsg strHostIFmsg;
/* prepare the Timer Callback message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.drvHandler = pvArg;
strHostIFmsg.u16MsgId = HOST_IF_MSG_CONNECT_TIMER_FIRED;
/* send the message */
- WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
}
@@ -4613,7 +4588,7 @@
* @version 1.0
*/
/* Check implementation in core adding 9 bytes to the input! */
-s32 host_int_remove_key(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8StaAddress)
+s32 host_int_remove_key(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8StaAddress)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -4642,19 +4617,18 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8keyIdx)
+s32 host_int_remove_wep_key(tstrWILC_WFIDrv *hWFIDrv, u8 u8keyIdx)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the Remove Wep Key Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
@@ -4668,9 +4642,9 @@
uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8keyIdx;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
- PRINT_ER("Error in sending message queue : Request to remove WEP key \n");
+ PRINT_ER("Error in sending message queue : Request to remove WEP key\n");
down(&(pstrWFIDrv->hSemTestKeyBlock));
WILC_CATCH(s32Error)
@@ -4692,19 +4666,18 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index)
+s32 host_int_set_WEPDefaultKeyID(tstrWILC_WFIDrv *hWFIDrv, u8 u8Index)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the Key Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
@@ -4717,7 +4690,7 @@
uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8Index;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
PRINT_ER("Error in sending message queue : Default key index\n");
down(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -4749,20 +4722,19 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx)
+s32 host_int_add_wep_key_bss_sta(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the Key Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
@@ -4772,9 +4744,9 @@
strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
- uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = (u8 *)WILC_MALLOC(u8WepKeylen);
+ uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = WILC_MALLOC(u8WepKeylen);
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
pu8WepKey, u8WepKeylen);
@@ -4785,7 +4757,7 @@
uniHostIFkeyAttr.strHostIFwepAttr.u8Wepidx = u8Keyidx;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
PRINT_ER("Error in sending message queue :WEP Key\n");
down(&(pstrWFIDrv->hSemTestKeyBlock));
@@ -4815,7 +4787,7 @@
* @date 28 FEB 2013
* @version 1.0
*/
-s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type)
+s32 host_int_add_wep_key_bss_ap(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type)
{
s32 s32Error = WILC_SUCCESS;
@@ -4823,13 +4795,12 @@
tstrHostIFmsg strHostIFmsg;
u8 i;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the Key Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
if (INFO) {
for (i = 0; i < u8WepKeylen; i++)
@@ -4842,10 +4813,10 @@
strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
- uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = (u8 *)WILC_MALLOC((u8WepKeylen));
+ uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey = WILC_MALLOC((u8WepKeylen));
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwepAttr.pu8WepKey,
pu8WepKey, (u8WepKeylen));
@@ -4861,7 +4832,7 @@
strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
uniHostIFkeyAttr.strHostIFwepAttr.tenuAuth_type = tenuAuth_type;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
PRINT_ER("Error in sending message queue :WEP Key\n");
@@ -4891,7 +4862,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
+s32 host_int_add_ptk(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode, u8 u8Idx)
{
s32 s32Error = WILC_SUCCESS;
@@ -4899,18 +4870,16 @@
tstrHostIFmsg strHostIFmsg;
u8 u8KeyLen = u8PtkKeylen;
u32 i;
- if (pstrWFIDrv == NULL) {
+
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- if (pu8RxMic != NULL) {
+ if (pu8RxMic != NULL)
u8KeyLen += RX_MIC_KEY_LEN;
- }
- if (pu8TxMic != NULL) {
+ if (pu8TxMic != NULL)
u8KeyLen += TX_MIC_KEY_LEN;
- }
/* prepare the Key Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
@@ -4927,15 +4896,15 @@
strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
- uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = (u8 *)WILC_MALLOC(u8PtkKeylen);
+ uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = WILC_MALLOC(u8PtkKeylen);
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
pu8Ptk, u8PtkKeylen);
if (pu8RxMic != NULL) {
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16,
pu8RxMic, RX_MIC_KEY_LEN);
if (INFO) {
for (i = 0; i < RX_MIC_KEY_LEN; i++)
@@ -4944,7 +4913,7 @@
}
if (pu8TxMic != NULL) {
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24,
pu8TxMic, TX_MIC_KEY_LEN);
if (INFO) {
for (i = 0; i < TX_MIC_KEY_LEN; i++)
@@ -4962,14 +4931,13 @@
strHostIFmsg.drvHandler = hWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
PRINT_ER("Error in sending message queue: PTK Key\n");
/* ////////////// */
down(&(pstrWFIDrv->hSemTestKeyBlock));
- /* WILC_Sleep(100); */
/* /////// */
WILC_CATCH(s32Error)
@@ -4993,7 +4961,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
+s32 host_int_add_rx_gtk(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC,
const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode)
{
@@ -5002,24 +4970,21 @@
tstrHostIFmsg strHostIFmsg;
u8 u8KeyLen = u8GtkKeylen;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the Key Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
- if (pu8RxMic != NULL) {
+ if (pu8RxMic != NULL)
u8KeyLen += RX_MIC_KEY_LEN;
- }
- if (pu8TxMic != NULL) {
+ if (pu8TxMic != NULL)
u8KeyLen += TX_MIC_KEY_LEN;
- }
if (KeyRSC != NULL) {
strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
- uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq = (u8 *)WILC_MALLOC(u32KeyRSClen);
+ uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq = WILC_MALLOC(u32KeyRSClen);
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8seq,
KeyRSC, u32KeyRSClen);
}
@@ -5039,20 +5004,20 @@
strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.
- uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = (u8 *)WILC_MALLOC(u8KeyLen);
+ uniHostIFkeyAttr.strHostIFwpaAttr.pu8key = WILC_MALLOC(u8KeyLen);
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key,
pu8RxGtk, u8GtkKeylen);
if (pu8RxMic != NULL) {
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 16,
pu8RxMic, RX_MIC_KEY_LEN);
}
if (pu8TxMic != NULL) {
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFwpaAttr.pu8key + 24,
pu8TxMic, TX_MIC_KEY_LEN);
}
@@ -5068,12 +5033,11 @@
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
PRINT_ER("Error in sending message queue: RX GTK\n");
/* ////////////// */
down(&(pstrWFIDrv->hSemTestKeyBlock));
- /* WILC_Sleep(100); */
/* /////// */
WILC_CATCH(s32Error)
@@ -5103,7 +5067,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray)
+s32 host_int_set_pmkid_info(tstrWILC_WFIDrv *hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -5111,12 +5075,11 @@
u32 i;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the Key Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_KEY;
strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.enuKeyType = PMKSA;
@@ -5125,15 +5088,15 @@
for (i = 0; i < pu8PmkidInfoArray->numpmkid; i++) {
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, &pu8PmkidInfoArray->pmkidlist[i].bssid,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].bssid, &pu8PmkidInfoArray->pmkidlist[i].bssid,
ETH_ALEN);
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, &pu8PmkidInfoArray->pmkidlist[i].pmkid,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFkeyAttr.uniHostIFkeyAttr.strHostIFpmkidAttr.pmkidlist[i].pmkid, &pu8PmkidInfoArray->pmkidlist[i].pmkid,
PMKID_LEN);
}
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
PRINT_ER(" Error in sending messagequeue: PMKID Info\n");
@@ -5166,7 +5129,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_pmkid_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PmkidInfoArray,
+s32 host_int_get_pmkid_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8PmkidInfoArray,
u32 u32PmkidInfoLen)
{
s32 s32Error = WILC_SUCCESS;
@@ -5195,14 +5158,12 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_set_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PassPhrase,
+s32 host_int_set_RSNAConfigPSKPassPhrase(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8PassPhrase,
u8 u8Psklength)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
- /* tstrWILC_WFIDrv * pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv; */
- /* u8 u8Psklength = WILC_strlen(pu8PassPhrase); */
/*validating psk length*/
if ((u8Psklength > 7) && (u8Psklength < 65)) {
strWID.u16WIDid = (u16)WID_11I_PSK;
@@ -5224,20 +5185,20 @@
* @date 19 April 2012
* @version 1.0
*/
-s32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress)
+s32 host_int_get_MacAddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8MacAddress)
{
s32 s32Error = WILC_SUCCESS;
tstrHostIFmsg strHostIFmsg;
/* prepare the Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_MAC_ADDRESS;
strHostIFmsg.uniHostIFmsgBody.strHostIfGetMacAddress.u8MacAddress = pu8MacAddress;
strHostIFmsg.drvHandler = hWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error) {
PRINT_ER("Failed to send get mac address\n");
return WILC_FAIL;
@@ -5258,7 +5219,7 @@
* @date 16 July 2012
* @version 1.0
*/
-s32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress)
+s32 host_int_set_MacAddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8MacAddress)
{
s32 s32Error = WILC_SUCCESS;
tstrHostIFmsg strHostIFmsg;
@@ -5266,12 +5227,12 @@
PRINT_D(GENERIC_DBG, "mac addr = %x:%x:%x\n", pu8MacAddress[0], pu8MacAddress[1], pu8MacAddress[2]);
/* prepare setting mac address message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_MAC_ADDRESS;
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfSetMacAddress.u8MacAddress, pu8MacAddress, ETH_ALEN);
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfSetMacAddress.u8MacAddress, pu8MacAddress, ETH_ALEN);
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error) {
PRINT_ER("Failed to send message queue: Set mac address\n");
WILC_ERRORREPORT(s32Error, s32Error);
@@ -5299,7 +5260,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv,
+s32 host_int_get_RSNAConfigPSKPassPhrase(tstrWILC_WFIDrv *hWFIDrv,
u8 *pu8PassPhrase, u8 u8Psklength)
{
s32 s32Error = WILC_SUCCESS;
@@ -5346,7 +5307,7 @@
* @version 1.0
*/
#ifndef CONNECT_DIRECT
-s32 host_int_get_site_survey_results(WILC_WFIDrvHandle hWFIDrv,
+s32 host_int_get_site_survey_results(tstrWILC_WFIDrv *hWFIDrv,
u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
u32 u32MaxSiteSrvyFragLen)
{
@@ -5396,7 +5357,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_set_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 scanSource)
+s32 host_int_set_start_scan_req(tstrWILC_WFIDrv *hWFIDrv, u8 scanSource)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -5426,7 +5387,7 @@
* @version 1.0
*/
-s32 host_int_get_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ScanSource)
+s32 host_int_get_start_scan_req(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8ScanSource)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -5451,7 +5412,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
+s32 host_int_set_join_req(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8bssid,
const u8 *pu8ssid, size_t ssidLen,
const u8 *pu8IEs, size_t IEsLen,
tWILCpfConnectResult pfConnectResult, void *pvUserArg,
@@ -5464,9 +5425,8 @@
tstrHostIFmsg strHostIFmsg;
tenuScanConnTimer enuScanConnTimer;
- if (pstrWFIDrv == NULL || pfConnectResult == NULL) {
+ if (pstrWFIDrv == NULL || pfConnectResult == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
if (hWFIDrv == NULL) {
PRINT_ER("Driver not initialized: gWFiDrvHandle = NULL\n");
@@ -5486,7 +5446,7 @@
* }
*/
/* prepare the Connect Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_CONNECT;
@@ -5499,39 +5459,41 @@
strHostIFmsg.drvHandler = hWFIDrv;
if (pu8bssid != NULL) {
- strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid = (u8 *)WILC_MALLOC(6); /* will be deallocated by the receiving thread */
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid,
+ strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid = WILC_MALLOC(6); /* will be deallocated by the receiving thread */
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8bssid,
pu8bssid, 6);
}
if (pu8ssid != NULL) {
strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.ssidLen = ssidLen;
- strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid = (u8 *)WILC_MALLOC(ssidLen); /* will be deallocated by the receiving thread */
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid,
+ strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid = WILC_MALLOC(ssidLen); /* will be deallocated by the receiving thread */
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8ssid,
pu8ssid, ssidLen);
}
if (pu8IEs != NULL) {
strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.IEsLen = IEsLen;
- strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs = (u8 *)WILC_MALLOC(IEsLen); /* will be deallocated by the receiving thread */
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs,
+ strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs = WILC_MALLOC(IEsLen); /* will be deallocated by the receiving thread */
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFconnectAttr.pu8IEs,
pu8IEs, IEsLen);
}
- if (pstrWFIDrv->enuHostIFstate < HOST_IF_CONNECTING) {
+ if (pstrWFIDrv->enuHostIFstate < HOST_IF_CONNECTING)
pstrWFIDrv->enuHostIFstate = HOST_IF_CONNECTING;
- } else
+ else
PRINT_D(GENERIC_DBG, "Don't set state to 'connecting' as state is %d\n", pstrWFIDrv->enuHostIFstate);
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error) {
PRINT_ER("Failed to send message queue: Set join request\n");
WILC_ERRORREPORT(s32Error, WILC_FAIL);
}
enuScanConnTimer = CONNECT_TIMER;
- WILC_TimerStart(&(pstrWFIDrv->hConnectTimer), HOST_IF_CONNECT_TIMEOUT, (void *) hWFIDrv, NULL);
+ pstrWFIDrv->hConnectTimer.data = (unsigned long)hWFIDrv;
+ mod_timer(&pstrWFIDrv->hConnectTimer,
+ jiffies + msecs_to_jiffies(HOST_IF_CONNECT_TIMEOUT));
WILC_CATCH(s32Error)
{
@@ -5553,7 +5515,7 @@
* @version 8.0
*/
-s32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv)
+s32 host_int_flush_join_req(tstrWILC_WFIDrv *hWFIDrv)
{
s32 s32Error = WILC_SUCCESS;
tstrHostIFmsg strHostIFmsg;
@@ -5564,16 +5526,15 @@
}
- if (hWFIDrv == NULL) {
+ if (hWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
strHostIFmsg.u16MsgId = HOST_IF_MSG_FLUSH_CONNECT;
strHostIFmsg.drvHandler = hWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error) {
PRINT_ER("Failed to send message queue: Flush join request\n");
WILC_ERRORREPORT(s32Error, WILC_FAIL);
@@ -5597,14 +5558,14 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode)
+s32 host_int_disconnect(tstrWILC_WFIDrv *hWFIDrv, u16 u16ReasonCode)
{
s32 s32Error = WILC_SUCCESS;
tstrHostIFmsg strHostIFmsg;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
if (pstrWFIDrv == NULL) {
- PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
}
@@ -5614,13 +5575,13 @@
}
/* prepare the Disconnect Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_DISCONNECT;
strHostIFmsg.drvHandler = hWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
PRINT_ER("Failed to send message queue: disconnect\n");
/* ////////////// */
@@ -5646,7 +5607,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_disconnect_station(WILC_WFIDrvHandle hWFIDrv, u8 assoc_id)
+s32 host_int_disconnect_station(tstrWILC_WFIDrv *hWFIDrv, u8 assoc_id)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -5686,7 +5647,7 @@
* @version 1.0
*/
-s32 host_int_get_assoc_req_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocReqInfo,
+s32 host_int_get_assoc_req_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8AssocReqInfo,
u32 u32AssocReqInfoLen)
{
s32 s32Error = WILC_SUCCESS;
@@ -5713,7 +5674,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocRespInfo,
+s32 host_int_get_assoc_res_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8AssocRespInfo,
u32 u32MaxAssocRespInfoLen, u32 *pu32RcvdAssocRespInfoLen)
{
s32 s32Error = WILC_SUCCESS;
@@ -5721,7 +5682,7 @@
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
if (pstrWFIDrv == NULL) {
- PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
}
@@ -5763,7 +5724,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_rx_power_level(WILC_WFIDrvHandle hWFIDrv, u8 *pu8RxPowerLevel,
+s32 host_int_get_rx_power_level(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8RxPowerLevel,
u32 u32RxPowerLevelLen)
{
s32 s32Error = WILC_SUCCESS;
@@ -5794,26 +5755,24 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_set_mac_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 u8ChNum)
+s32 host_int_set_mac_chnl_num(tstrWILC_WFIDrv *hWFIDrv, u8 u8ChNum)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the set channel message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_CHANNEL;
strHostIFmsg.uniHostIFmsgBody.strHostIFSetChan.u8SetChan = u8ChNum;
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -5831,12 +5790,11 @@
/* prepare the set driver handler message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_Q_IDLE;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -5849,7 +5807,7 @@
}
-s32 host_int_set_wfi_drv_handler(u32 u32address)
+s32 host_int_set_wfi_drv_handler(tstrWILC_WFIDrv *u32address)
{
s32 s32Error = WILC_SUCCESS;
@@ -5858,15 +5816,14 @@
/* prepare the set driver handler message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_WFIDRV_HANDLER;
strHostIFmsg.uniHostIFmsgBody.strHostIfSetDrvHandler.u32Address = u32address;
/* strHostIFmsg.drvHandler=hWFIDrv; */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -5877,7 +5834,7 @@
-s32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, u32 u32mode)
+s32 host_int_set_operation_mode(tstrWILC_WFIDrv *hWFIDrv, u32 u32mode)
{
s32 s32Error = WILC_SUCCESS;
@@ -5886,15 +5843,14 @@
/* prepare the set driver handler message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_OPERATION_MODE;
strHostIFmsg.uniHostIFmsgBody.strHostIfSetOperationMode.u32Mode = u32mode;
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -5918,25 +5874,25 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ChNo)
+s32 host_int_get_host_chnl_num(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8ChNo)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
if (pstrWFIDrv == NULL) {
- PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
}
/* prepare the Get Channel Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_CHNL;
strHostIFmsg.drvHandler = hWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
PRINT_ER("Failed to send get host channel param's message queue ");
down(&(pstrWFIDrv->hSemGetCHNL));
@@ -5964,7 +5920,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_test_set_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 u32TestMemAddr)
+s32 host_int_test_set_int_wid(tstrWILC_WFIDrv *hWFIDrv, u32 u32TestMemAddr)
{
s32 s32Error = WILC_SUCCESS;
tstrWID strWID;
@@ -5972,7 +5928,7 @@
if (pstrWFIDrv == NULL) {
- PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
}
@@ -6011,28 +5967,28 @@
* @date
* @version 1.0
*/
-s32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, const u8 *mac, u32 *pu32InactiveTime)
+s32 host_int_get_inactive_time(tstrWILC_WFIDrv *hWFIDrv, const u8 *mac, u32 *pu32InactiveTime)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
if (pstrWFIDrv == NULL) {
- PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
}
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfStaInactiveT.mac,
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIfStaInactiveT.mac,
mac, ETH_ALEN);
strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_INACTIVETIME;
strHostIFmsg.drvHandler = hWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error)
PRINT_ER("Failed to send get host channel param's message queue ");
@@ -6057,7 +6013,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_test_get_int_wid(WILC_WFIDrvHandle hWFIDrv, u32 *pu32TestMemAddr)
+s32 host_int_test_get_int_wid(tstrWILC_WFIDrv *hWFIDrv, u32 *pu32TestMemAddr)
{
s32 s32Error = WILC_SUCCESS;
@@ -6066,7 +6022,7 @@
if (pstrWFIDrv == NULL) {
- PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
}
@@ -6106,7 +6062,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, s8 *ps8Rssi)
+s32 host_int_get_rssi(tstrWILC_WFIDrv *hWFIDrv, s8 *ps8Rssi)
{
s32 s32Error = WILC_SUCCESS;
tstrHostIFmsg strHostIFmsg;
@@ -6114,13 +6070,13 @@
/* prepare the Get RSSI Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_RSSI;
strHostIFmsg.drvHandler = hWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error) {
PRINT_ER("Failed to send get host channel param's message queue ");
return WILC_FAIL;
@@ -6141,7 +6097,7 @@
return s32Error;
}
-s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd)
+s32 host_int_get_link_speed(tstrWILC_WFIDrv *hWFIDrv, s8 *ps8lnkspd)
{
tstrHostIFmsg strHostIFmsg;
s32 s32Error = WILC_SUCCESS;
@@ -6151,13 +6107,13 @@
/* prepare the Get LINKSPEED Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_LINKSPEED;
strHostIFmsg.drvHandler = hWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error) {
PRINT_ER("Failed to send GET_LINKSPEED to message queue ");
return WILC_FAIL;
@@ -6178,20 +6134,20 @@
return s32Error;
}
-s32 host_int_get_statistics(WILC_WFIDrvHandle hWFIDrv, tstrStatistics *pstrStatistics)
+s32 host_int_get_statistics(tstrWILC_WFIDrv *hWFIDrv, tstrStatistics *pstrStatistics)
{
s32 s32Error = WILC_SUCCESS;
tstrHostIFmsg strHostIFmsg;
/* prepare the Get RSSI Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_STATISTICS;
strHostIFmsg.uniHostIFmsgBody.pUserData = (char *)pstrStatistics;
strHostIFmsg.drvHandler = hWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error) {
PRINT_ER("Failed to send get host channel param's message queue ");
return WILC_FAIL;
@@ -6218,7 +6174,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
+s32 host_int_scan(tstrWILC_WFIDrv *hWFIDrv, u8 u8ScanSource,
u8 u8ScanType, u8 *pu8ChnlFreqList,
u8 u8ChnlListLen, const u8 *pu8IEs,
size_t IEsLen, tWILCpfScanResult ScanResult,
@@ -6229,13 +6185,12 @@
tstrHostIFmsg strHostIFmsg;
tenuScanConnTimer enuScanConnTimer;
- if (pstrWFIDrv == NULL || ScanResult == NULL) {
+ if (pstrWFIDrv == NULL || ScanResult == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the Scan Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_SCAN;
@@ -6253,17 +6208,17 @@
strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pvUserArg = pvUserArg;
strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.u8ChnlListLen = u8ChnlListLen;
- strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList = (u8 *)WILC_MALLOC(u8ChnlListLen); /* will be deallocated by the receiving thread */
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList,
+ strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList = WILC_MALLOC(u8ChnlListLen); /* will be deallocated by the receiving thread */
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8ChnlFreqList,
pu8ChnlFreqList, u8ChnlListLen);
strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.IEsLen = IEsLen;
- strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs = (u8 *)WILC_MALLOC(IEsLen); /* will be deallocated by the receiving thread */
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs,
+ strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs = WILC_MALLOC(IEsLen); /* will be deallocated by the receiving thread */
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strHostIFscanAttr.pu8IEs,
pu8IEs, IEsLen);
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error) {
PRINT_ER("Error in sending message queue scanning parameters: Error(%d)\n", s32Error);
WILC_ERRORREPORT(s32Error, WILC_FAIL);
@@ -6271,8 +6226,9 @@
enuScanConnTimer = SCAN_TIMER;
PRINT_D(HOSTINF_DBG, ">> Starting the SCAN timer\n");
- WILC_TimerStart(&(pstrWFIDrv->hScanTimer), HOST_IF_SCAN_TIMEOUT, (void *) hWFIDrv, NULL);
-
+ pstrWFIDrv->hScanTimer.data = (unsigned long)hWFIDrv;
+ mod_timer(&pstrWFIDrv->hScanTimer,
+ jiffies + msecs_to_jiffies(HOST_IF_SCAN_TIMEOUT));
WILC_CATCH(s32Error)
{
@@ -6292,7 +6248,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal)
+s32 hif_set_cfg(tstrWILC_WFIDrv *hWFIDrv, tstrCfgParamVal *pstrCfgParamVal)
{
s32 s32Error = WILC_SUCCESS;
@@ -6301,16 +6257,15 @@
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the WiphyParams Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_CFG_PARAMS;
strHostIFmsg.uniHostIFmsgBody.strHostIFCfgParamAttr.pstrCfgParamVal = *pstrCfgParamVal;
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
WILC_CATCH(s32Error)
{
@@ -6334,7 +6289,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 hif_get_cfg(WILC_WFIDrvHandle hWFIDrv, u16 u16WID, u16 *pu16WID_Value)
+s32 hif_get_cfg(tstrWILC_WFIDrv *hWFIDrv, u16 u16WID, u16 *pu16WID_Value)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -6342,7 +6297,7 @@
down(&(pstrWFIDrv->gtOsCfgValuesSem));
if (pstrWFIDrv == NULL) {
- PRINT_ER("Driver not initialized: pstrWFIDrv = NULL \n");
+ PRINT_ER("Driver not initialized: pstrWFIDrv = NULL\n");
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
}
PRINT_D(HOSTINF_DBG, "Getting configuration parameters\n");
@@ -6469,9 +6424,10 @@
* @version 1.0
*/
-void GetPeriodicRSSI(void *pvArg)
+static void GetPeriodicRSSI(unsigned long arg)
{
- tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)pvArg;
+ tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)arg;
+
if (pstrWFIDrv == NULL) {
PRINT_ER("Driver handler is NULL\n");
return;
@@ -6482,19 +6438,20 @@
tstrHostIFmsg strHostIFmsg;
/* prepare the Get RSSI Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_RSSI;
strHostIFmsg.drvHandler = pstrWFIDrv;
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
if (s32Error) {
PRINT_ER("Failed to send get host channel param's message queue ");
return;
}
}
- WILC_TimerStart(&(g_hPeriodicRSSI), 5000, (void *)pstrWFIDrv, NULL);
+ g_hPeriodicRSSI.data = (unsigned long)pstrWFIDrv;
+ mod_timer(&g_hPeriodicRSSI, jiffies + msecs_to_jiffies(5000));
}
@@ -6515,7 +6472,7 @@
static u32 msgQ_created;
static u32 clients_count;
-s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv)
+s32 host_int_init(tstrWILC_WFIDrv **phWFIDrv)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv;
@@ -6535,16 +6492,16 @@
/*Allocate host interface private structure*/
- pstrWFIDrv = (tstrWILC_WFIDrv *)WILC_MALLOC(sizeof(tstrWILC_WFIDrv));
+ pstrWFIDrv = WILC_MALLOC(sizeof(tstrWILC_WFIDrv));
if (pstrWFIDrv == NULL) {
/* WILC_ERRORREPORT(s32Error,WILC_NO_MEM); */
s32Error = WILC_NO_MEM;
PRINT_ER("Failed to allocate memory\n");
goto _fail_timer_2;
}
- WILC_memset(pstrWFIDrv, 0, sizeof(tstrWILC_WFIDrv));
+ memset(pstrWFIDrv, 0, sizeof(tstrWILC_WFIDrv));
/*return driver handle to user*/
- *phWFIDrv = (WILC_WFIDrvHandle)pstrWFIDrv;
+ *phWFIDrv = pstrWFIDrv;
/*save into globl handle*/
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
@@ -6575,9 +6532,7 @@
PRINT_D(HOSTINF_DBG, "INIT: CLIENT COUNT %d\n", clients_count);
if (clients_count == 0) {
-
- s32Error = WILC_MsgQueueCreate(&gMsgQHostIF, NULL);
-
+ s32Error = WILC_MsgQueueCreate(&gMsgQHostIF);
if (s32Error < 0) {
PRINT_ER("Failed to creat MQ\n");
@@ -6590,47 +6545,24 @@
s32Error = WILC_FAIL;
goto _fail_mq_;
}
- s32Error = WILC_TimerCreate(&(g_hPeriodicRSSI), GetPeriodicRSSI, NULL);
- if (s32Error < 0) {
- PRINT_ER("Failed to creat Timer\n");
- goto _fail_timer_1;
- }
- WILC_TimerStart(&(g_hPeriodicRSSI), 5000, (void *)pstrWFIDrv, NULL);
-
+ setup_timer(&g_hPeriodicRSSI, GetPeriodicRSSI,
+ (unsigned long)pstrWFIDrv);
+ mod_timer(&g_hPeriodicRSSI, jiffies + msecs_to_jiffies(5000));
}
- s32Error = WILC_TimerCreate(&(pstrWFIDrv->hScanTimer), TimerCB_Scan, NULL);
- if (s32Error < 0) {
- PRINT_ER("Failed to creat Timer\n");
- goto _fail_thread_;
- }
+ setup_timer(&pstrWFIDrv->hScanTimer, TimerCB_Scan, 0);
- s32Error = WILC_TimerCreate(&(pstrWFIDrv->hConnectTimer), TimerCB_Connect, NULL);
- if (s32Error < 0) {
- PRINT_ER("Failed to creat Timer\n");
- goto _fail_timer_1;
- }
-
+ setup_timer(&pstrWFIDrv->hConnectTimer, TimerCB_Connect, 0);
#ifdef WILC_P2P
/*Remain on channel timer*/
- s32Error = WILC_TimerCreate(&(pstrWFIDrv->hRemainOnChannel), ListenTimerCB, NULL);
- if (s32Error < 0) {
- PRINT_ER("Failed to creat Remain-on-channel Timer\n");
- goto _fail_timer_3;
- }
+ setup_timer(&pstrWFIDrv->hRemainOnChannel, ListenTimerCB, 0);
#endif
sema_init(&(pstrWFIDrv->gtOsCfgValuesSem), 1);
down(&(pstrWFIDrv->gtOsCfgValuesSem));
-
-
-#ifdef SIMULATION
- TransportInit();
-#endif
-
pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
/* gWFiDrvHandle->bPendingConnRequest = false; */
@@ -6666,11 +6598,6 @@
goto _fail_mem_;
}
-#ifdef SIMULATION
- /*Initialize Simulaor*/
- CoreConfigSimulatorInit();
-#endif
-
u32Intialized = 1;
clients_count++; /* increase number of created entities */
@@ -6679,20 +6606,17 @@
_fail_mem_:
if (pstrWFIDrv != NULL)
- WILC_FREE(pstrWFIDrv);
+ kfree(pstrWFIDrv);
#ifdef WILC_P2P
-_fail_timer_3:
- WILC_TimerDestroy(&(pstrWFIDrv->hRemainOnChannel), NULL);
+ del_timer_sync(&pstrWFIDrv->hRemainOnChannel);
#endif
_fail_timer_2:
up(&(pstrWFIDrv->gtOsCfgValuesSem));
- WILC_TimerDestroy(&(pstrWFIDrv->hConnectTimer), NULL);
-_fail_timer_1:
- WILC_TimerDestroy(&(pstrWFIDrv->hScanTimer), NULL);
-_fail_thread_:
+ del_timer_sync(&pstrWFIDrv->hConnectTimer);
+ del_timer_sync(&pstrWFIDrv->hScanTimer);
kthread_stop(HostIFthreadHandler);
_fail_mq_:
- WILC_MsgQueueDestroy(&gMsgQHostIF, NULL);
+ WILC_MsgQueueDestroy(&gMsgQHostIF);
_fail_:
return s32Error;
@@ -6708,7 +6632,7 @@
* @version 1.0
*/
-s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv)
+s32 host_int_deinit(tstrWILC_WFIDrv *hWFIDrv)
{
s32 s32Error = WILC_SUCCESS;
tstrHostIFmsg strHostIFmsg;
@@ -6737,28 +6661,28 @@
/*BugID_5348*/
/*Destroy all timers before acquiring hSemDeinitDrvHandle*/
/*to guarantee handling all messages befor proceeding*/
- if (WILC_TimerDestroy(&(pstrWFIDrv->hScanTimer), NULL)) {
- PRINT_D(HOSTINF_DBG, ">> Scan timer is active \n");
+ if (del_timer_sync(&pstrWFIDrv->hScanTimer)) {
+ PRINT_D(HOSTINF_DBG, ">> Scan timer is active\n");
/* msleep(HOST_IF_SCAN_TIMEOUT+1000); */
}
- if (WILC_TimerDestroy(&(pstrWFIDrv->hConnectTimer), NULL)) {
- PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n");
+ if (del_timer_sync(&pstrWFIDrv->hConnectTimer)) {
+ PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
/* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */
}
- if (WILC_TimerDestroy(&(g_hPeriodicRSSI), NULL)) {
- PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n");
+ if (del_timer_sync(&g_hPeriodicRSSI)) {
+ PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
/* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */
}
#ifdef WILC_P2P
/*Destroy Remain-onchannel Timer*/
- WILC_TimerDestroy(&(pstrWFIDrv->hRemainOnChannel), NULL);
+ del_timer_sync(&pstrWFIDrv->hRemainOnChannel);
#endif
- host_int_set_wfi_drv_handler((u32)NULL);
+ host_int_set_wfi_drv_handler(NULL);
down(&hSemDeinitDrvHandle);
@@ -6770,39 +6694,30 @@
pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult = NULL;
}
/*deinit configurator and simulator*/
-#ifdef SIMULATION
- CoreConfigSimulatorDeInit();
-#endif
CoreConfiguratorDeInit();
-#ifdef SIMULATION
- TransportDeInit();
-#endif
pstrWFIDrv->enuHostIFstate = HOST_IF_IDLE;
gbScanWhileConnected = false;
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
if (clients_count == 1) {
- if (WILC_TimerDestroy(&g_hPeriodicRSSI, NULL)) {
- PRINT_D(HOSTINF_DBG, ">> Connect timer is active \n");
+ if (del_timer_sync(&g_hPeriodicRSSI)) {
+ PRINT_D(HOSTINF_DBG, ">> Connect timer is active\n");
/* msleep(HOST_IF_CONNECT_TIMEOUT+1000); */
}
strHostIFmsg.u16MsgId = HOST_IF_MSG_EXIT;
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error != WILC_SUCCESS) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error != WILC_SUCCESS)
PRINT_ER("Error in sending deinit's message queue message function: Error(%d)\n", s32Error);
- }
down(&hSemHostIFthrdEnd);
-
-
- WILC_MsgQueueDestroy(&gMsgQHostIF, NULL);
+ WILC_MsgQueueDestroy(&gMsgQHostIF);
msgQ_created = 0;
}
@@ -6812,7 +6727,7 @@
u32Intialized = 0;
/* gWFiDrvHandle = NULL; */
if (pstrWFIDrv != NULL) {
- WILC_FREE(pstrWFIDrv);
+ kfree(pstrWFIDrv);
/* pstrWFIDrv=NULL; */
}
@@ -6854,24 +6769,20 @@
}
/* prepare the Asynchronous Network Info message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_NTWRK_INFO;
strHostIFmsg.drvHandler = pstrWFIDrv;
strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.u32Length = u32Length;
- strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer = (u8 *)WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer,
+ strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer = WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdNetworkInfo.pu8Buffer,
pu8Buffer, u32Length);
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
PRINT_ER("Error in sending network info message queue message parameters: Error(%d)\n", s32Error);
- }
-
-
- return;
}
/**
@@ -6897,7 +6808,7 @@
drvHandler = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
- PRINT_D(HOSTINF_DBG, "General asynchronous info packet received \n");
+ PRINT_D(HOSTINF_DBG, "General asynchronous info packet received\n");
if (pstrWFIDrv == NULL || pstrWFIDrv == terminated_handle) {
@@ -6916,7 +6827,7 @@
}
/* prepare the General Asynchronous Info message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_GNRL_ASYNC_INFO;
@@ -6924,19 +6835,17 @@
strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.u32Length = u32Length;
- strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer = (u8 *)WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */
- WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer,
+ strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer = WILC_MALLOC(u32Length); /* will be deallocated by the receiving thread */
+ memcpy(strHostIFmsg.uniHostIFmsgBody.strRcvdGnrlAsyncInfo.pu8Buffer,
pu8Buffer, u32Length);
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
PRINT_ER("Error in sending message queue asynchronous message info: Error(%d)\n", s32Error);
- }
/*BugID_5348*/
up(&hSemHostIntDeinit);
- return;
}
/**
@@ -6954,20 +6863,20 @@
tstrHostIFmsg strHostIFmsg;
u32 drvHandler;
tstrWILC_WFIDrv *pstrWFIDrv = NULL;
+
drvHandler = ((pu8Buffer[u32Length - 4]) | (pu8Buffer[u32Length - 3] << 8) | (pu8Buffer[u32Length - 2] << 16) | (pu8Buffer[u32Length - 1] << 24));
pstrWFIDrv = (tstrWILC_WFIDrv *)drvHandler;
PRINT_D(GENERIC_DBG, "Scan notification received %p\n", pstrWFIDrv);
- if (pstrWFIDrv == NULL || pstrWFIDrv == terminated_handle) {
+ if (pstrWFIDrv == NULL || pstrWFIDrv == terminated_handle)
return;
- }
/*if there is an ongoing scan request*/
if (pstrWFIDrv->strWILC_UsrScanReq.pfUserScanResult) {
/* prepare theScan Done message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_RCVD_SCAN_COMPLETE;
strHostIFmsg.drvHandler = pstrWFIDrv;
@@ -6978,14 +6887,13 @@
/*strHostIFmsg.uniHostIFmsgBody.strScanComplete.u32Length = u32Length;
* strHostIFmsg.uniHostIFmsgBody.strScanComplete.pu8Buffer = (u8*)WILC_MALLOC(u32Length);
- * WILC_memcpy(strHostIFmsg.uniHostIFmsgBody.strScanComplete.pu8Buffer,
+ * memcpy(strHostIFmsg.uniHostIFmsgBody.strScanComplete.pu8Buffer,
* pu8Buffer, u32Length); */
/* send the message */
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
PRINT_ER("Error in sending message queue scan complete parameters: Error(%d)\n", s32Error);
- }
}
@@ -7008,18 +6916,17 @@
* @date
* @version 1.0
*/
-s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg)
+s32 host_int_remain_on_channel(tstrWILC_WFIDrv *hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the remainonchan Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
strHostIFmsg.u16MsgId = HOST_IF_MSG_REMAIN_ON_CHAN;
@@ -7031,10 +6938,9 @@
strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = u32SessionID;
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7057,29 +6963,27 @@
* @date
* @version 1.0
*/
-s32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID)
+s32 host_int_ListenStateExpired(tstrWILC_WFIDrv *hWFIDrv, u32 u32SessionID)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/*Stopping remain-on-channel timer*/
- WILC_TimerStop(&(pstrWFIDrv->hRemainOnChannel), NULL);
+ del_timer(&pstrWFIDrv->hRemainOnChannel);
/* prepare the timer fire Message */
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
strHostIFmsg.u16MsgId = HOST_IF_MSG_LISTEN_TIMER_FIRED;
strHostIFmsg.drvHandler = hWFIDrv;
strHostIFmsg.uniHostIFmsgBody.strHostIfRemainOnChan.u32ListenSessionID = u32SessionID;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7095,17 +6999,16 @@
* @author
* @date
* @version 1.0*/
-s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bReg)
+s32 host_int_frame_register(tstrWILC_WFIDrv *hWFIDrv, u16 u16FrameType, bool bReg)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
strHostIFmsg.u16MsgId = HOST_IF_MSG_REGISTER_FRAME;
@@ -7128,10 +7031,9 @@
strHostIFmsg.uniHostIFmsgBody.strHostIfRegisterFrame.bReg = bReg;
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7155,7 +7057,7 @@
* @date
* @version 1.0
*/
-s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
+s32 host_int_add_beacon(tstrWILC_WFIDrv *hWFIDrv, u32 u32Interval,
u32 u32DTIMPeriod,
u32 u32HeadLen, u8 *pu8Head,
u32 u32TailLen, u8 *pu8Tail)
@@ -7165,11 +7067,10 @@
tstrHostIFmsg strHostIFmsg;
tstrHostIFSetBeacon *pstrSetBeaconParam = &strHostIFmsg.uniHostIFmsgBody.strHostIFSetBeacon;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
PRINT_D(HOSTINF_DBG, "Setting adding beacon message queue params\n");
@@ -7180,38 +7081,33 @@
pstrSetBeaconParam->u32Interval = u32Interval;
pstrSetBeaconParam->u32DTIMPeriod = u32DTIMPeriod;
pstrSetBeaconParam->u32HeadLen = u32HeadLen;
- pstrSetBeaconParam->pu8Head = (u8 *)WILC_MALLOC(u32HeadLen);
- if (pstrSetBeaconParam->pu8Head == NULL) {
+ pstrSetBeaconParam->pu8Head = WILC_MALLOC(u32HeadLen);
+ if (pstrSetBeaconParam->pu8Head == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
- WILC_memcpy(pstrSetBeaconParam->pu8Head, pu8Head, u32HeadLen);
+ memcpy(pstrSetBeaconParam->pu8Head, pu8Head, u32HeadLen);
pstrSetBeaconParam->u32TailLen = u32TailLen;
/* Bug 4599 : if tail length = 0 skip allocating & copying */
if (u32TailLen > 0) {
- pstrSetBeaconParam->pu8Tail = (u8 *)WILC_MALLOC(u32TailLen);
- if (pstrSetBeaconParam->pu8Tail == NULL) {
+ pstrSetBeaconParam->pu8Tail = WILC_MALLOC(u32TailLen);
+ if (pstrSetBeaconParam->pu8Tail == NULL)
WILC_ERRORREPORT(s32Error, WILC_NO_MEM);
- }
- WILC_memcpy(pstrSetBeaconParam->pu8Tail, pu8Tail, u32TailLen);
+ memcpy(pstrSetBeaconParam->pu8Tail, pu8Tail, u32TailLen);
} else {
pstrSetBeaconParam->pu8Tail = NULL;
}
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
- if (pstrSetBeaconParam->pu8Head != NULL) {
- WILC_FREE(pstrSetBeaconParam->pu8Head);
- }
+ if (pstrSetBeaconParam->pu8Head != NULL)
+ kfree(pstrSetBeaconParam->pu8Head);
- if (pstrSetBeaconParam->pu8Tail != NULL) {
- WILC_FREE(pstrSetBeaconParam->pu8Tail);
- }
+ if (pstrSetBeaconParam->pu8Tail != NULL)
+ kfree(pstrSetBeaconParam->pu8Tail);
}
return s32Error;
@@ -7228,22 +7124,21 @@
* @date
* @version 1.0
*/
-s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv)
+s32 host_int_del_beacon(tstrWILC_WFIDrv *hWFIDrv)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
/* prepare the WiphyParams Message */
strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_BEACON;
strHostIFmsg.drvHandler = hWFIDrv;
PRINT_D(HOSTINF_DBG, "Setting deleting beacon message queue params\n");
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
WILC_ERRORCHECK(s32Error);
WILC_CATCH(s32Error)
@@ -7262,7 +7157,7 @@
* @date
* @version 1.0
*/
-s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
+s32 host_int_add_station(tstrWILC_WFIDrv *hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -7270,11 +7165,10 @@
tstrWILC_AddStaParam *pstrAddStationMsg = &strHostIFmsg.uniHostIFmsgBody.strAddStaParam;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
PRINT_D(HOSTINF_DBG, "Setting adding station message queue params\n");
@@ -7283,20 +7177,20 @@
strHostIFmsg.u16MsgId = HOST_IF_MSG_ADD_STATION;
strHostIFmsg.drvHandler = hWFIDrv;
- WILC_memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam));
+ memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam));
if (pstrAddStationMsg->u8NumRates > 0) {
u8 *rates = WILC_MALLOC(pstrAddStationMsg->u8NumRates);
+
WILC_NULLCHECK(s32Error, rates);
- WILC_memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
+ memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
pstrAddStationMsg->pu8Rates = rates;
}
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7313,18 +7207,17 @@
* @date
* @version 1.0
*/
-s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr)
+s32 host_int_del_station(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8MacAddr)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
tstrHostIFDelSta *pstrDelStationMsg = &strHostIFmsg.uniHostIFmsgBody.strDelStaParam;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
PRINT_D(HOSTINF_DBG, "Setting deleting station message queue params\n");
@@ -7336,14 +7229,13 @@
/*BugID_4795: Handling situation of deleting all stations*/
if (pu8MacAddr == NULL)
- WILC_memset(pstrDelStationMsg->au8MacAddr, 255, ETH_ALEN);
+ memset(pstrDelStationMsg->au8MacAddr, 255, ETH_ALEN);
else
- WILC_memcpy(pstrDelStationMsg->au8MacAddr, pu8MacAddr, ETH_ALEN);
+ memcpy(pstrDelStationMsg->au8MacAddr, pu8MacAddr, ETH_ALEN);
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7359,7 +7251,7 @@
* @date
* @version 1.0
*/
-s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN])
+s32 host_int_del_allstation(tstrWILC_WFIDrv *hWFIDrv, u8 pu8MacAddr[][ETH_ALEN])
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -7370,11 +7262,10 @@
u8 u8AssocNumb = 0;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
PRINT_D(HOSTINF_DBG, "Setting deauthenticating station message queue params\n");
@@ -7385,7 +7276,7 @@
/* Handling situation of deauthenticing all associated stations*/
for (i = 0; i < MAX_NUM_STA; i++) {
if (memcmp(pu8MacAddr[i], au8Zero_Buff, ETH_ALEN)) {
- WILC_memcpy(pstrDelAllStationMsg->au8Sta_DelAllSta[i], pu8MacAddr[i], ETH_ALEN);
+ memcpy(pstrDelAllStationMsg->au8Sta_DelAllSta[i], pu8MacAddr[i], ETH_ALEN);
PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", pstrDelAllStationMsg->au8Sta_DelAllSta[i][0], pstrDelAllStationMsg->au8Sta_DelAllSta[i][1], pstrDelAllStationMsg->au8Sta_DelAllSta[i][2], pstrDelAllStationMsg->au8Sta_DelAllSta[i][3], pstrDelAllStationMsg->au8Sta_DelAllSta[i][4],
pstrDelAllStationMsg->au8Sta_DelAllSta[i][5]);
u8AssocNumb++;
@@ -7397,13 +7288,12 @@
}
pstrDelAllStationMsg->u8Num_AssocSta = u8AssocNumb;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
- if (s32Error) {
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7423,38 +7313,37 @@
* @date
* @version 1.0
*/
-s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
+s32 host_int_edit_station(tstrWILC_WFIDrv *hWFIDrv, tstrWILC_AddStaParam *pstrStaParams)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
tstrWILC_AddStaParam *pstrAddStationMsg = &strHostIFmsg.uniHostIFmsgBody.strAddStaParam;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
PRINT_D(HOSTINF_DBG, "Setting editing station message queue params\n");
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
strHostIFmsg.u16MsgId = HOST_IF_MSG_EDIT_STATION;
strHostIFmsg.drvHandler = hWFIDrv;
- WILC_memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam));
+ memcpy(pstrAddStationMsg, pstrStaParams, sizeof(tstrWILC_AddStaParam));
if (pstrAddStationMsg->u8NumRates > 0) {
u8 *rates = WILC_MALLOC(pstrAddStationMsg->u8NumRates);
+
WILC_NULLCHECK(s32Error, rates);
- WILC_memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
+ memcpy(rates, pstrStaParams->pu8Rates, pstrAddStationMsg->u8NumRates);
pstrAddStationMsg->pu8Rates = rates;
}
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
}
@@ -7463,22 +7352,21 @@
#endif /*WILC_AP_EXTERNAL_MLME*/
uint32_t wilc_get_chipid(uint8_t);
-s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout)
+s32 host_int_set_power_mgmt(tstrWILC_WFIDrv *hWFIDrv, bool bIsEnabled, u32 u32Timeout)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
tstrHostIfPowerMgmtParam *pstrPowerMgmtParam = &strHostIFmsg.uniHostIFmsgBody.strPowerMgmtparam;
- PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d << \n\n", bIsEnabled);
+ PRINT_INFO(HOSTINF_DBG, "\n\n>> Setting PS to %d <<\n\n", bIsEnabled);
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
PRINT_D(HOSTINF_DBG, "Setting Power management message queue params\n");
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
@@ -7489,17 +7377,16 @@
pstrPowerMgmtParam->u32Timeout = u32Timeout;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
}
return s32Error;
}
-s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32count)
+s32 host_int_setup_multicast_filter(tstrWILC_WFIDrv *hWFIDrv, bool bIsEnabled, u32 u32count)
{
s32 s32Error = WILC_SUCCESS;
@@ -7508,13 +7395,12 @@
tstrHostIFSetMulti *pstrMulticastFilterParam = &strHostIFmsg.uniHostIFmsgBody.strHostIfSetMulti;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
PRINT_D(HOSTINF_DBG, "Setting Multicast Filter params\n");
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
@@ -7524,10 +7410,9 @@
pstrMulticastFilterParam->bIsEnabled = bIsEnabled;
pstrMulticastFilterParam->u32count = u32count;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
}
@@ -7568,17 +7453,17 @@
pNewJoinBssParam = WILC_MALLOC(sizeof(tstrJoinBssParam));
if (pNewJoinBssParam != NULL) {
- WILC_memset(pNewJoinBssParam, 0, sizeof(tstrJoinBssParam));
+ memset(pNewJoinBssParam, 0, sizeof(tstrJoinBssParam));
pNewJoinBssParam->dtim_period = ptstrNetworkInfo->u8DtimPeriod;
pNewJoinBssParam->beacon_period = ptstrNetworkInfo->u16BeaconPeriod;
pNewJoinBssParam->cap_info = ptstrNetworkInfo->u16CapInfo;
- WILC_memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6);
+ memcpy(pNewJoinBssParam->au8bssid, ptstrNetworkInfo->au8bssid, 6);
/*for(i=0; i<6;i++)
* PRINT_D(HOSTINF_DBG,"%c",pNewJoinBssParam->au8bssid[i]);*/
- WILC_memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1);
+ memcpy((u8 *)pNewJoinBssParam->ssid, ptstrNetworkInfo->au8ssid, ptstrNetworkInfo->u8SsidLen + 1);
pNewJoinBssParam->ssidLen = ptstrNetworkInfo->u8SsidLen;
- WILC_memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3);
- WILC_memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3);
+ memset(pNewJoinBssParam->rsn_pcip_policy, 0xFF, 3);
+ memset(pNewJoinBssParam->rsn_auth_policy, 0xFF, 3);
/*for(i=0; i<pNewJoinBssParam->ssidLen;i++)
* PRINT_D(HOSTINF_DBG,"%c",pNewJoinBssParam->ssid[i]);*/
@@ -7633,9 +7518,8 @@
pNewJoinBssParam->wmm_cap = true;
/* Check if Bit 7 is set indicating U-APSD capability */
- if (pu8IEs[index + 8] & (1 << 7)) {
+ if (pu8IEs[index + 8] & (1 << 7))
pNewJoinBssParam->uapsd_cap = true;
- }
index += pu8IEs[index + 1] + 2;
continue;
}
@@ -7645,6 +7529,7 @@
(pu8IEs[index + 4] == 0x9a) && /* OUI */
(pu8IEs[index + 5] == 0x09) && (pu8IEs[index + 6] == 0x0c)) { /* OUI Type */
u16 u16P2P_count;
+
pNewJoinBssParam->tsf = ptstrNetworkInfo->u32Tsf;
pNewJoinBssParam->u8NoaEnbaled = 1;
pNewJoinBssParam->u8Index = pu8IEs[index + 9];
@@ -7656,20 +7541,20 @@
} else
pNewJoinBssParam->u8OppEnable = 0;
/* HOSTINF_DBG */
- PRINT_D(GENERIC_DBG, "P2P Dump \n");
+ 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]);
+ PRINT_D(GENERIC_DBG, " %x\n", pu8IEs[index + 9 + i]);
pNewJoinBssParam->u8Count = pu8IEs[index + 11];
u16P2P_count = index + 12;
- WILC_memcpy(pNewJoinBssParam->au8Duration, pu8IEs + u16P2P_count, 4);
+ memcpy(pNewJoinBssParam->au8Duration, pu8IEs + u16P2P_count, 4);
u16P2P_count += 4;
- WILC_memcpy(pNewJoinBssParam->au8Interval, pu8IEs + u16P2P_count, 4);
+ memcpy(pNewJoinBssParam->au8Interval, pu8IEs + u16P2P_count, 4);
u16P2P_count += 4;
- WILC_memcpy(pNewJoinBssParam->au8StartTime, pu8IEs + u16P2P_count, 4);
+ memcpy(pNewJoinBssParam->au8StartTime, pu8IEs + u16P2P_count, 4);
index += pu8IEs[index + 1] + 2;
continue;
@@ -7698,7 +7583,7 @@
rsnIndex += 7; /* skipping id, length, version(2B) and first 3 bytes of gcipher */
pNewJoinBssParam->rsn_grp_policy = pu8IEs[rsnIndex];
rsnIndex++;
- /* PRINT_D(HOSTINF_DBG,"Group Policy: %0x \n",pNewJoinBssParam->rsn_grp_policy); */
+ /* PRINT_D(HOSTINF_DBG,"Group Policy: %0x\n",pNewJoinBssParam->rsn_grp_policy); */
/* initialize policies with invalid values */
jumpOffset = pu8IEs[rsnIndex] * 4; /* total no.of bytes of pcipher field (count*4) */
@@ -7709,7 +7594,7 @@
pcipherCount = (pu8IEs[rsnIndex] > 3) ? 3 : pu8IEs[rsnIndex];
rsnIndex += 2; /* jump 2 bytes of pcipher count */
- /* PRINT_D(HOSTINF_DBG,"\npcipher:%d \n",pcipherCount); */
+ /* PRINT_D(HOSTINF_DBG,"\npcipher:%d\n",pcipherCount); */
for (i = pcipherTotalCount, j = 0; i < pcipherCount + pcipherTotalCount && i < 3; i++, j++) {
/* each count corresponds to 4 bytes, only last byte is saved */
pNewJoinBssParam->rsn_pcip_policy[i] = pu8IEs[rsnIndex + ((j + 1) * 4) - 1];
@@ -7755,7 +7640,7 @@
void host_int_freeJoinParams(void *pJoinParams)
{
if ((tstrJoinBssParam *)pJoinParams != NULL)
- WILC_FREE((tstrJoinBssParam *)pJoinParams);
+ kfree((tstrJoinBssParam *)pJoinParams);
else
PRINT_ER("Unable to FREE null pointer\n");
}
@@ -7771,7 +7656,7 @@
* @date
* @version 1.0**/
-static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID, short int BufferSize,
+static int host_int_addBASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID, short int BufferSize,
short int SessionTimeout, void *drvHandler)
{
s32 s32Error = WILC_SUCCESS;
@@ -7779,11 +7664,10 @@
tstrHostIFmsg strHostIFmsg;
tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
strHostIFmsg.u16MsgId = HOST_IF_MSG_ADD_BA_SESSION;
@@ -7794,10 +7678,9 @@
pBASessionInfo->u16SessionTimeout = SessionTimeout;
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7807,18 +7690,17 @@
}
-s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID)
+s32 host_int_delBASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_BA_SESSION;
@@ -7827,10 +7709,9 @@
pBASessionInfo->u8Ted = TID;
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7842,18 +7723,17 @@
return s32Error;
}
-s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID)
+s32 host_int_del_All_Rx_BASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
tstrHostIfBASessionInfo *pBASessionInfo = &strHostIFmsg.uniHostIFmsgBody.strHostIfBASessionInfo;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
strHostIFmsg.u16MsgId = HOST_IF_MSG_DEL_ALL_RX_BA_SESSIONS;
@@ -7862,10 +7742,9 @@
pBASessionInfo->u8Ted = TID;
strHostIFmsg.drvHandler = hWFIDrv;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7885,7 +7764,7 @@
* @author Abdelrahman Sobhy
* @date
* @version 1.0*/
-s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx)
+s32 host_int_setup_ipaddress(tstrWILC_WFIDrv *hWFIDrv, u8 *u16ipadd, u8 idx)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
@@ -7894,11 +7773,10 @@
/* TODO: Enable This feature on softap firmware */
return 0;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
strHostIFmsg.u16MsgId = HOST_IF_MSG_SET_IPADDRESS;
@@ -7907,10 +7785,9 @@
strHostIFmsg.drvHandler = hWFIDrv;
strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx = idx;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
@@ -7929,29 +7806,27 @@
* @author Abdelrahman Sobhy
* @date
* @version 1.0*/
-s32 host_int_get_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *u16ipadd, u8 idx)
+s32 host_int_get_ipaddress(tstrWILC_WFIDrv *hWFIDrv, u8 *u16ipadd, u8 idx)
{
s32 s32Error = WILC_SUCCESS;
tstrWILC_WFIDrv *pstrWFIDrv = (tstrWILC_WFIDrv *)hWFIDrv;
tstrHostIFmsg strHostIFmsg;
- if (pstrWFIDrv == NULL) {
+ if (pstrWFIDrv == NULL)
WILC_ERRORREPORT(s32Error, WILC_INVALID_ARGUMENT);
- }
- WILC_memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
+ memset(&strHostIFmsg, 0, sizeof(tstrHostIFmsg));
/* prepare the WiphyParams Message */
strHostIFmsg.u16MsgId = HOST_IF_MSG_GET_IPADDRESS;
strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.au8IPAddr = u16ipadd;
- strHostIFmsg.drvHandler=hWFIDrv;
- strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx= idx;
+ strHostIFmsg.drvHandler = hWFIDrv;
+ strHostIFmsg.uniHostIFmsgBody.strHostIfSetIP.idx = idx;
- s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg), NULL);
- if (s32Error) {
+ s32Error = WILC_MsgQueueSend(&gMsgQHostIF, &strHostIFmsg, sizeof(tstrHostIFmsg));
+ if (s32Error)
WILC_ERRORREPORT(s32Error, s32Error);
- }
WILC_CATCH(s32Error)
{
diff --git a/drivers/staging/wilc1000/host_interface.h b/drivers/staging/wilc1000/host_interface.h
index 38db740..e66dee9 100644
--- a/drivers/staging/wilc1000/host_interface.h
+++ b/drivers/staging/wilc1000/host_interface.h
@@ -11,7 +11,6 @@
#define HOST_INT_H
#include "coreconfigurator.h"
-#include "coreconfigsimulator.h"
/*****************************************************************************/
/* Macros */
/*****************************************************************************/
@@ -368,10 +367,10 @@
struct semaphore hSemGetCHNL;
struct semaphore hSemInactiveTime;
/* timer handlers */
- WILC_TimerHandle hScanTimer;
- WILC_TimerHandle hConnectTimer;
+ struct timer_list hScanTimer;
+ struct timer_list hConnectTimer;
#ifdef WILC_P2P
- WILC_TimerHandle hRemainOnChannel;
+ struct timer_list hRemainOnChannel;
#endif
bool IFC_UP;
@@ -433,7 +432,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_remove_key(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8StaAddress);
+s32 host_int_remove_key(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8StaAddress);
/**
* @brief removes WEP key
* @details valid only in BSS STA mode if External Supplicant support is enabled.
@@ -448,7 +447,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_remove_wep_key(WILC_WFIDrvHandle hWFIDrv, u8 u8Index);
+s32 host_int_remove_wep_key(tstrWILC_WFIDrv *hWFIDrv, u8 u8Index);
/**
* @brief sets WEP deafault key
* @details Sets the index of the WEP encryption key in use,
@@ -461,7 +460,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_set_WEPDefaultKeyID(WILC_WFIDrvHandle hWFIDrv, u8 u8Index);
+s32 host_int_set_WEPDefaultKeyID(tstrWILC_WFIDrv *hWFIDrv, u8 u8Index);
/**
* @brief sets WEP deafault key
@@ -482,7 +481,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_add_wep_key_bss_sta(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx);
+s32 host_int_add_wep_key_bss_sta(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx);
/**
* @brief host_int_add_wep_key_bss_ap
* @details valid only in AP mode if External Supplicant support is enabled.
@@ -497,7 +496,7 @@
* @date 28 Feb 2013
* @version 1.0
*/
-s32 host_int_add_wep_key_bss_ap(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type);
+s32 host_int_add_wep_key_bss_ap(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8WepKey, u8 u8WepKeylen, u8 u8Keyidx, u8 u8mode, AUTHTYPE_T tenuAuth_type);
/**
* @brief adds ptk Key
@@ -515,7 +514,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_add_ptk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
+s32 host_int_add_ptk(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8Ptk, u8 u8PtkKeylen,
const u8 *mac_addr, const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode, u8 u8Idx);
/**
@@ -530,7 +529,7 @@
* @date 15 April 2013
* @version 1.0
*/
-s32 host_int_get_inactive_time(WILC_WFIDrvHandle hWFIDrv, const u8 *mac, u32 *pu32InactiveTime);
+s32 host_int_get_inactive_time(tstrWILC_WFIDrv *hWFIDrv, const u8 *mac, u32 *pu32InactiveTime);
/**
* @brief adds Rx GTk Key
@@ -548,7 +547,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_add_rx_gtk(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
+s32 host_int_add_rx_gtk(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8RxGtk, u8 u8GtkKeylen,
u8 u8KeyIdx, u32 u32KeyRSClen, const u8 *KeyRSC,
const u8 *pu8RxMic, const u8 *pu8TxMic, u8 mode, u8 u8Ciphermode);
@@ -569,7 +568,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_add_tx_gtk(WILC_WFIDrvHandle hWFIDrv, u8 u8KeyLen, u8 *pu8TxGtk, u8 u8KeyIdx);
+s32 host_int_add_tx_gtk(tstrWILC_WFIDrv *hWFIDrv, u8 u8KeyLen, u8 *pu8TxGtk, u8 u8KeyIdx);
/**
* @brief caches the pmkid
@@ -592,7 +591,7 @@
* @version 1.0
*/
-s32 host_int_set_pmkid_info(WILC_WFIDrvHandle hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray);
+s32 host_int_set_pmkid_info(tstrWILC_WFIDrv *hWFIDrv, tstrHostIFpmkidAttr *pu8PmkidInfoArray);
/**
* @brief gets the cached the pmkid info
* @details valid only in BSS STA mode if External Supplicant
@@ -616,7 +615,7 @@
* @version 1.0
*/
-s32 host_int_get_pmkid_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PmkidInfoArray,
+s32 host_int_get_pmkid_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8PmkidInfoArray,
u32 u32PmkidInfoLen);
/**
@@ -633,7 +632,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_set_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv, u8 *pu8PassPhrase,
+s32 host_int_set_RSNAConfigPSKPassPhrase(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8PassPhrase,
u8 u8Psklength);
/**
* @brief gets the pass phrase
@@ -649,7 +648,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_RSNAConfigPSKPassPhrase(WILC_WFIDrvHandle hWFIDrv,
+s32 host_int_get_RSNAConfigPSKPassPhrase(tstrWILC_WFIDrv *hWFIDrv,
u8 *pu8PassPhrase, u8 u8Psklength);
/**
@@ -663,7 +662,7 @@
* @date 19 April 2012
* @version 1.0
*/
-s32 host_int_get_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress);
+s32 host_int_get_MacAddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8MacAddress);
/**
* @brief sets mac address
@@ -676,7 +675,7 @@
* @date 16 July 2012
* @version 1.0
*/
-s32 host_int_set_MacAddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8MacAddress);
+s32 host_int_set_MacAddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8MacAddress);
/**
* @brief wait until msg q is empty
@@ -721,7 +720,7 @@
* @version 1.0
*/
#ifndef CONNECT_DIRECT
-s32 host_int_get_site_survey_results(WILC_WFIDrvHandle hWFIDrv,
+s32 host_int_get_site_survey_results(tstrWILC_WFIDrv *hWFIDrv,
u8 ppu8RcvdSiteSurveyResults[][MAX_SURVEY_RESULT_FRAG_SIZE],
u32 u32MaxSiteSrvyFragLen);
#endif
@@ -742,7 +741,7 @@
* @version 1.0
*/
-s32 host_int_set_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 scanSource);
+s32 host_int_set_start_scan_req(tstrWILC_WFIDrv *hWFIDrv, u8 scanSource);
/**
* @brief gets scan source of the last scan
* @details
@@ -758,7 +757,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_start_scan_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ScanSource);
+s32 host_int_get_start_scan_req(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8ScanSource);
/**
* @brief sets a join request
@@ -772,7 +771,7 @@
* @version 1.0
*/
-s32 host_int_set_join_req(WILC_WFIDrvHandle hWFIDrv, u8 *pu8bssid,
+s32 host_int_set_join_req(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8bssid,
const u8 *pu8ssid, size_t ssidLen,
const u8 *pu8IEs, size_t IEsLen,
tWILCpfConnectResult pfConnectResult, void *pvUserArg,
@@ -792,7 +791,7 @@
* @version 8.0
*/
-s32 host_int_flush_join_req(WILC_WFIDrvHandle hWFIDrv);
+s32 host_int_flush_join_req(tstrWILC_WFIDrv *hWFIDrv);
/**
@@ -806,7 +805,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_disconnect(WILC_WFIDrvHandle hWFIDrv, u16 u16ReasonCode);
+s32 host_int_disconnect(tstrWILC_WFIDrv *hWFIDrv, u16 u16ReasonCode);
/**
* @brief disconnects a sta
@@ -819,7 +818,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_disconnect_station(WILC_WFIDrvHandle hWFIDrv, u8 assoc_id);
+s32 host_int_disconnect_station(tstrWILC_WFIDrv *hWFIDrv, u8 assoc_id);
/**
* @brief gets a Association request info
* @details
@@ -846,7 +845,7 @@
* @version 1.0
*/
-s32 host_int_get_assoc_req_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocReqInfo,
+s32 host_int_get_assoc_req_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8AssocReqInfo,
u32 u32AssocReqInfoLen);
/**
* @brief gets a Association Response info
@@ -860,7 +859,7 @@
* @version 1.0
*/
-s32 host_int_get_assoc_res_info(WILC_WFIDrvHandle hWFIDrv, u8 *pu8AssocRespInfo,
+s32 host_int_get_assoc_res_info(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8AssocRespInfo,
u32 u32MaxAssocRespInfoLen, u32 *pu32RcvdAssocRespInfoLen);
/**
* @brief gets a Association Response info
@@ -877,7 +876,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_rx_power_level(WILC_WFIDrvHandle hWFIDrv, u8 *pu8RxPowerLevel,
+s32 host_int_get_rx_power_level(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8RxPowerLevel,
u32 u32RxPowerLevelLen);
/**
@@ -895,7 +894,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_set_mac_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 u8ChNum);
+s32 host_int_set_mac_chnl_num(tstrWILC_WFIDrv *hWFIDrv, u8 u8ChNum);
/**
* @brief gets the current channel index
@@ -912,7 +911,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_host_chnl_num(WILC_WFIDrvHandle hWFIDrv, u8 *pu8ChNo);
+s32 host_int_get_host_chnl_num(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8ChNo);
/**
* @brief gets the sta rssi
* @details gets the currently maintained RSSI value for the station.
@@ -926,8 +925,8 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_get_rssi(WILC_WFIDrvHandle hWFIDrv, s8 *ps8Rssi);
-s32 host_int_get_link_speed(WILC_WFIDrvHandle hWFIDrv, s8 *ps8lnkspd);
+s32 host_int_get_rssi(tstrWILC_WFIDrv *hWFIDrv, s8 *ps8Rssi);
+s32 host_int_get_link_speed(tstrWILC_WFIDrv *hWFIDrv, s8 *ps8lnkspd);
/**
* @brief scans a set of channels
* @details
@@ -945,7 +944,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_scan(WILC_WFIDrvHandle hWFIDrv, u8 u8ScanSource,
+s32 host_int_scan(tstrWILC_WFIDrv *hWFIDrv, u8 u8ScanSource,
u8 u8ScanType, u8 *pu8ChnlFreqList,
u8 u8ChnlListLen, const u8 *pu8IEs,
size_t IEsLen, tWILCpfScanResult ScanResult,
@@ -961,7 +960,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 hif_set_cfg(WILC_WFIDrvHandle hWFIDrv, tstrCfgParamVal *pstrCfgParamVal);
+s32 hif_set_cfg(tstrWILC_WFIDrv *hWFIDrv, tstrCfgParamVal *pstrCfgParamVal);
/**
* @brief gets configuration wids values
@@ -975,7 +974,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 hif_get_cfg(WILC_WFIDrvHandle hWFIDrv, u16 u16WID, u16 *pu16WID_Value);
+s32 hif_get_cfg(tstrWILC_WFIDrv *hWFIDrv, u16 u16WID, u16 *pu16WID_Value);
/*****************************************************************************/
/* Notification Functions */
/*****************************************************************************/
@@ -1022,7 +1021,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_init(WILC_WFIDrvHandle *phWFIDrv);
+s32 host_int_init(tstrWILC_WFIDrv **phWFIDrv);
/**
* @brief host interface initialization function
@@ -1033,7 +1032,7 @@
* @date 8 March 2012
* @version 1.0
*/
-s32 host_int_deinit(WILC_WFIDrvHandle hWFIDrv);
+s32 host_int_deinit(tstrWILC_WFIDrv *hWFIDrv);
/*!
@@ -1058,7 +1057,7 @@
* @version 1.0 Description
*
*/
-s32 host_int_add_beacon(WILC_WFIDrvHandle hWFIDrv, u32 u32Interval,
+s32 host_int_add_beacon(tstrWILC_WFIDrv *hWFIDrv, u32 u32Interval,
u32 u32DTIMPeriod,
u32 u32HeadLen, u8 *pu8Head,
u32 u32TailLen, u8 *pu8tail);
@@ -1076,7 +1075,7 @@
* @date 10 Julys 2012
* @version 1.0 Description
*/
-s32 host_int_del_beacon(WILC_WFIDrvHandle hWFIDrv);
+s32 host_int_del_beacon(tstrWILC_WFIDrv *hWFIDrv);
/*!
* @fn s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam strStaParams)
@@ -1091,7 +1090,7 @@
* @date 12 July 2012
* @version 1.0 Description
*/
-s32 host_int_add_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
+s32 host_int_add_station(tstrWILC_WFIDrv *hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
/*!
* @fn s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, const u8* pu8MacAddr)
@@ -1106,7 +1105,7 @@
* @date 09 April 2014
* @version 1.0 Description
*/
-s32 host_int_del_allstation(WILC_WFIDrvHandle hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]);
+s32 host_int_del_allstation(tstrWILC_WFIDrv *hWFIDrv, u8 pu8MacAddr[][ETH_ALEN]);
/*!
* @fn s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, u8* pu8MacAddr)
@@ -1121,7 +1120,7 @@
* @date 15 July 2012
* @version 1.0 Description
*/
-s32 host_int_del_station(WILC_WFIDrvHandle hWFIDrv, const u8 *pu8MacAddr);
+s32 host_int_del_station(tstrWILC_WFIDrv *hWFIDrv, const u8 *pu8MacAddr);
/*!
* @fn s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam strStaParams)
@@ -1136,7 +1135,7 @@
* @date 15 July 2012
* @version 1.0 Description
*/
-s32 host_int_edit_station(WILC_WFIDrvHandle hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
+s32 host_int_edit_station(tstrWILC_WFIDrv *hWFIDrv, tstrWILC_AddStaParam *pstrStaParams);
/*!
* @fn s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout)
@@ -1153,7 +1152,7 @@
* @date 24 November 2012
* @version 1.0 Description
*/
-s32 host_int_set_power_mgmt(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32Timeout);
+s32 host_int_set_power_mgmt(tstrWILC_WFIDrv *hWFIDrv, bool bIsEnabled, u32 u32Timeout);
/* @param[in,out] hWFIDrv handle to the wifi driver
* @param[in] bIsEnabled TRUE if enabled, FALSE otherwise
* @param[in] u8count count of mac address entries in the filter table
@@ -1165,7 +1164,7 @@
* @date 24 November 2012
* @version 1.0 Description
*/
-s32 host_int_setup_multicast_filter(WILC_WFIDrvHandle hWFIDrv, bool bIsEnabled, u32 u32count);
+s32 host_int_setup_multicast_filter(tstrWILC_WFIDrv *hWFIDrv, bool bIsEnabled, u32 u32count);
/**
* @brief host_int_setup_ipaddress
* @details set IP address on firmware
@@ -1175,7 +1174,7 @@
* @date
* @version 1.0
*/
-s32 host_int_setup_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8IPAddr, u8 idx);
+s32 host_int_setup_ipaddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8IPAddr, u8 idx);
/**
@@ -1187,7 +1186,7 @@
* @date
* @version 1.0
*/
-s32 host_int_delBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID);
+s32 host_int_delBASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID);
/**
* @brief host_int_delBASession
@@ -1198,7 +1197,7 @@
* @date
* @version 1.0
*/
-s32 host_int_del_All_Rx_BASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID);
+s32 host_int_del_All_Rx_BASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID);
/**
@@ -1210,7 +1209,7 @@
* @date
* @version 1.0
*/
-s32 host_int_get_ipaddress(WILC_WFIDrvHandle hWFIDrv, u8 *pu8IPAddr, u8 idx);
+s32 host_int_get_ipaddress(tstrWILC_WFIDrv *hWFIDrv, u8 *pu8IPAddr, u8 idx);
#ifdef WILC_P2P
/**
@@ -1222,7 +1221,7 @@
* @date
* @version 1.0
*/
-s32 host_int_remain_on_channel(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg);
+s32 host_int_remain_on_channel(tstrWILC_WFIDrv *hWFIDrv, u32 u32SessionID, u32 u32duration, u16 chan, tWILCpfRemainOnChanExpired RemainOnChanExpired, tWILCpfRemainOnChanReady RemainOnChanReady, void *pvUserArg);
/**
* @brief host_int_ListenStateExpired
@@ -1238,7 +1237,7 @@
* @date
* @version 1.0
*/
-s32 host_int_ListenStateExpired(WILC_WFIDrvHandle hWFIDrv, u32 u32SessionID);
+s32 host_int_ListenStateExpired(tstrWILC_WFIDrv *hWFIDrv, u32 u32SessionID);
/**
* @brief host_int_frame_register
@@ -1249,7 +1248,7 @@
* @date
* @version 1.0
*/
-s32 host_int_frame_register(WILC_WFIDrvHandle hWFIDrv, u16 u16FrameType, bool bReg);
+s32 host_int_frame_register(tstrWILC_WFIDrv *hWFIDrv, u16 u16FrameType, bool bReg);
#endif
/**
* @brief host_int_set_wfi_drv_handler
@@ -1260,18 +1259,18 @@
* @date
* @version 1.0
*/
-s32 host_int_set_wfi_drv_handler(u32 u32address);
-s32 host_int_set_operation_mode(WILC_WFIDrvHandle hWFIDrv, u32 u32mode);
+s32 host_int_set_wfi_drv_handler(tstrWILC_WFIDrv *u32address);
+s32 host_int_set_operation_mode(tstrWILC_WFIDrv *hWFIDrv, u32 u32mode);
-static s32 Handle_ScanDone(void *drvHandler, tenuScanEvent enuEvent);
+static s32 Handle_ScanDone(tstrWILC_WFIDrv *drvHandler, tenuScanEvent enuEvent);
-static int host_int_addBASession(WILC_WFIDrvHandle hWFIDrv, char *pBSSID, char TID, short int BufferSize,
+static int host_int_addBASession(tstrWILC_WFIDrv *hWFIDrv, char *pBSSID, char TID, short int BufferSize,
short int SessionTimeout, void *drvHandler);
void host_int_freeJoinParams(void *pJoinParams);
-s32 host_int_get_statistics(WILC_WFIDrvHandle hWFIDrv, tstrStatistics *pstrStatistics);
+s32 host_int_get_statistics(tstrWILC_WFIDrv *hWFIDrv, tstrStatistics *pstrStatistics);
/*****************************************************************************/
/* */
diff --git a/drivers/staging/wilc1000/linux_mon.c b/drivers/staging/wilc1000/linux_mon.c
index f5296f5..123468a 100644
--- a/drivers/staging/wilc1000/linux_mon.c
+++ b/drivers/staging/wilc1000/linux_mon.c
@@ -6,20 +6,15 @@
* @date 01 MAR 2012
* @version 1.0
*/
-
-#ifndef SIMULATION
#include "wilc_wfi_cfgoperations.h"
#include "linux_wlan_common.h"
#include "wilc_wlan_if.h"
#include "wilc_wlan.h"
-#endif
+
#ifdef WILC_FULLY_HOSTING_AP
#include "wilc_host_ap.h"
#endif
#ifdef WILC_AP_EXTERNAL_MLME
-#ifdef SIMULATION
-#include "wilc_wfi_cfgoperations.h"
-#endif
struct wilc_wfi_radiotap_hdr {
struct ieee80211_radiotap_header hdr;
@@ -39,9 +34,7 @@
static struct net_device *wilc_wfi_mon; /* global monitor netdev */
-#ifdef SIMULATION
-extern int WILC_WFI_Tx(struct sk_buff *skb, struct net_device *dev);
-#elif USE_WIRELESS
+#if USE_WIRELESS
extern int mac_xmit(struct sk_buff *skb, struct net_device *dev);
#endif
@@ -237,14 +230,12 @@
}
static int mon_mgmt_tx(struct net_device *dev, const u8 *buf, size_t len)
{
- linux_wlan_t *nic;
struct tx_complete_mon_data *mgmt_tx = NULL;
if (dev == NULL) {
PRINT_D(HOSTAPD_DBG, "ERROR: dev == NULL\n");
return WILC_FAIL;
}
- nic = netdev_priv(dev);
netif_stop_queue(dev);
mgmt_tx = kmalloc(sizeof(struct tx_complete_mon_data), GFP_ATOMIC);
@@ -298,7 +289,6 @@
static netdev_tx_t WILC_WFI_mon_xmit(struct sk_buff *skb,
struct net_device *dev)
{
- struct ieee80211_radiotap_header *rtap_hdr;
u32 rtap_len, i, ret = 0;
struct WILC_WFI_mon_priv *mon_priv;
@@ -318,7 +308,6 @@
return WILC_FAIL;
}
- rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
rtap_len = ieee80211_get_radiotap_len(skb->data);
if (skb->len < rtap_len) {
@@ -378,9 +367,7 @@
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);
- #ifdef SIMULATION
- ret = WILC_WFI_Tx(skb, mon_priv->real_ndev);
- #elif USE_WIRELESS
+ #if USE_WIRELESS
/* Identify if Ethernet or MAC header (data or mgmt) */
memcpy(srcAdd, &skb->data[10], 6);
memcpy(bssid, &skb->data[16], 6);
@@ -495,7 +482,7 @@
ether_setup(dev);
dev->tx_queue_len = 0;
dev->type = ARPHRD_IEEE80211_RADIOTAP;
- memset(dev->dev_addr, 0, ETH_ALEN);
+ eth_zero_addr(dev->dev_addr);
#ifdef USE_WIRELESS
{
@@ -571,7 +558,7 @@
* @date 12 JUL 2012
* @version 1.0
*/
-int WILC_WFI_deinit_mon_interface()
+int WILC_WFI_deinit_mon_interface(void)
{
bool rollback_lock = false;
diff --git a/drivers/staging/wilc1000/linux_wlan.c b/drivers/staging/wilc1000/linux_wlan.c
index b352c50..b3cc9f5 100644
--- a/drivers/staging/wilc1000/linux_wlan.c
+++ b/drivers/staging/wilc1000/linux_wlan.c
@@ -1,4 +1,3 @@
-#ifndef SIMULATION
#include "wilc_wfi_cfgoperations.h"
#include "linux_wlan_common.h"
#include "wilc_wlan_if.h"
@@ -72,7 +71,7 @@
extern u8 gau8MulticastMacAddrList[WILC_MULTICAST_TABLE_SIZE][ETH_ALEN];
void wilc1000_wlan_deinit(linux_wlan_t *nic);
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-extern WILC_TimerHandle hDuringIpTimer;
+extern struct timer_list hDuringIpTimer;
#endif
static int linux_wlan_device_power(int on_off)
@@ -103,7 +102,6 @@
return 0;
}
-
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr);
@@ -116,7 +114,6 @@
if (g_linux_wlan->oup.wlan_cleanup != NULL) \
g_linux_wlan->oup.wlan_cleanup(); }
-
#ifndef STA_FIRMWARE
#define STA_FIRMWARE "wifi_firmware.bin"
#endif
@@ -129,15 +126,12 @@
#define P2P_CONCURRENCY_FIRMWARE "wifi_firmware_p2p_concurrency.bin"
#endif
-
-
typedef struct android_wifi_priv_cmd {
char *buf;
int used_len;
int total_len;
} android_wifi_priv_cmd;
-
#define IRQ_WAIT 1
#define IRQ_NO_WAIT 0
/*
@@ -158,7 +152,6 @@
extern void WILC_WFI_monitor_rx(uint8_t *buff, uint32_t size);
extern void WILC_WFI_p2p_rx(struct net_device *dev, uint8_t *buff, uint32_t size);
-
static void *internal_alloc(uint32_t size, uint32_t flag);
static void linux_wlan_tx_complete(void *priv, int status);
void frmw_to_linux(uint8_t *buff, uint32_t size, uint32_t pkt_offset);
@@ -170,8 +163,6 @@
static int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd);
static void wilc_set_multicast_list(struct net_device *dev);
-
-
/*
* for now - in frmw_to_linux there should be private data to be passed to it
* and this data should be pointer to net device
@@ -200,22 +191,18 @@
char DebugBuffer[DEGUG_BUFFER_LENGTH + 20] = {0};
static char *ps8current = DebugBuffer;
-
-
void printk_later(const char *format, ...)
{
va_list args;
- va_start (args, format);
- ps8current += vsprintf (ps8current, format, args);
- va_end (args);
- if ((ps8current - DebugBuffer) > DEGUG_BUFFER_LENGTH) {
+ va_start(args, format);
+ ps8current += vsprintf(ps8current, format, args);
+ va_end(args);
+ if ((ps8current - DebugBuffer) > DEGUG_BUFFER_LENGTH)
ps8current = DebugBuffer;
- }
}
-
-void dump_logs()
+void dump_logs(void)
{
if (DebugBuffer[0]) {
DebugBuffer[DEGUG_BUFFER_LENGTH] = 0;
@@ -229,7 +216,7 @@
}
}
-void Reset_WatchDogdebugger()
+void Reset_WatchDogdebugger(void)
{
WatchDogdebuggerCounter = 0;
}
@@ -246,11 +233,8 @@
WatchDogdebuggerCounter = 0;
}
}
-
-
#endif
-
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
static int dev_state_ev_handler(struct notifier_block *this, unsigned long event, void *ptr)
{
@@ -298,25 +282,22 @@
PRINT_INFO(GENERIC_DBG, "\n ============== IP Address Obtained ===============\n\n");
-
/*If we are in station mode or client mode*/
if (nic->iftype == STATION_MODE || nic->iftype == CLIENT_MODE) {
pstrWFIDrv->IFC_UP = 1;
g_obtainingIP = false;
- WILC_TimerStop(&hDuringIpTimer, NULL);
+ del_timer(&hDuringIpTimer);
PRINT_D(GENERIC_DBG, "IP obtained , enable scan\n");
}
-
-
if (bEnablePS)
- host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 1, 0);
+ host_int_set_power_mgmt(pstrWFIDrv, 1, 0);
PRINT_D(GENERIC_DBG, "[%s] Up IP\n", dev_iface->ifa_label);
pIP_Add_buff = (char *) (&(dev_iface->ifa_address));
- PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d \n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
- host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
+ PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
+ host_int_setup_ipaddress(pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
break;
@@ -330,17 +311,16 @@
}
if (memcmp(dev_iface->ifa_label, wlan_dev_name, 5) == 0)
- host_int_set_power_mgmt((WILC_WFIDrvHandle)pstrWFIDrv, 0, 0);
+ host_int_set_power_mgmt(pstrWFIDrv, 0, 0);
resolve_disconnect_aberration(pstrWFIDrv);
-
PRINT_D(GENERIC_DBG, "[%s] Down IP\n", dev_iface->ifa_label);
pIP_Add_buff = null_ip;
- PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d \n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
+ PRINT_D(GENERIC_DBG, "IP add=%d:%d:%d:%d\n", pIP_Add_buff[0], pIP_Add_buff[1], pIP_Add_buff[2], pIP_Add_buff[3]);
- host_int_setup_ipaddress((WILC_WFIDrvHandle)pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
+ host_int_setup_ipaddress(pstrWFIDrv, pIP_Add_buff, nic->u8IfIdx);
break;
@@ -387,8 +367,6 @@
#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
static irqreturn_t isr_uh_routine(int irq, void *user_data)
{
-
-
int_rcvdU++;
#if (RX_BH_TYPE != RX_BH_THREADED_IRQ)
linux_wlan_disable_irq(IRQ_NO_WAIT);
@@ -440,19 +418,14 @@
#else
return;
#endif
-
-
-
}
int_rcvdB++;
PRINT_D(INT_DBG, "Interrupt received BH\n");
- if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) {
+ if (g_linux_wlan->oup.wlan_handle_rx_isr != 0)
g_linux_wlan->oup.wlan_handle_rx_isr();
- } else {
+ else
PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n");
- }
-
#if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
return IRQ_HANDLED;
@@ -476,18 +449,16 @@
}
int_rcvdB++;
PRINT_D(INT_DBG, "Interrupt received BH\n");
- if (g_linux_wlan->oup.wlan_handle_rx_isr != 0) {
+ if (g_linux_wlan->oup.wlan_handle_rx_isr != 0)
g_linux_wlan->oup.wlan_handle_rx_isr();
- } else {
+ else
PRINT_ER("wlan_handle_rx_isr() hasn't been initialized\n");
- }
}
return 0;
}
#endif
-
#if (defined WILC_SPI) || (defined WILC_SDIO_IRQ_GPIO)
static int init_irq(linux_wlan_t *p_nic)
{
@@ -504,9 +475,9 @@
*
* ex) nic->dev_irq_num = gpio_to_irq(GPIO_NUM);
*/
-#elif defined (NM73131_0_BOARD)
+#elif defined(NM73131_0_BOARD)
nic->dev_irq_num = IRQ_WILC1000;
-#elif defined (PANDA_BOARD)
+#elif defined(PANDA_BOARD)
gpio_export(GPIO_NUM, 1);
nic->dev_irq_num = OMAP_GPIO_IRQ(GPIO_NUM);
irq_set_irq_type(nic->dev_irq_num, IRQ_TYPE_LEVEL_LOW);
@@ -518,7 +489,6 @@
PRINT_ER("could not obtain gpio for WILC_INTR\n");
}
-
#if (RX_BH_TYPE == RX_BH_THREADED_IRQ)
if ((ret != -1) && (request_threaded_irq(nic->dev_irq_num, isr_uh_routine, isr_bh_routine,
IRQF_TRIGGER_LOW | IRQF_ONESHOT, /*Without IRQF_ONESHOT the uh will remain kicked in and dont gave a chance to bh*/
@@ -554,7 +524,6 @@
#endif
}
-
/*
* OS functions
*/
@@ -601,7 +570,6 @@
}
}
-
static void *internal_alloc(uint32_t size, uint32_t flag)
{
char *pntr = NULL;
@@ -610,7 +578,6 @@
return (void *)pntr;
}
-
static void linux_wlan_init_lock(char *lockName, void *plock, int count)
{
sema_init((struct semaphore *)plock, count);
@@ -638,25 +605,22 @@
{
int error = -1;
PRINT_D(LOCK_DBG, "Locking %p\n", vp);
- if (vp != NULL) {
+ if (vp != NULL)
error = down_timeout((struct semaphore *)vp, msecs_to_jiffies(timeout));
- } else {
+ else
PRINT_ER("Failed, mutex is NULL\n");
- }
return error;
}
void linux_wlan_unlock(void *vp)
{
PRINT_D(LOCK_DBG, "Unlocking %p\n", vp);
- if (vp != NULL) {
+ if (vp != NULL)
up((struct semaphore *)vp);
- } else {
+ else
PRINT_ER("Failed, mutex is NULL\n");
- }
}
-
static void linux_wlan_init_mutex(char *lockName, void *plock, int count)
{
mutex_init((struct mutex *)plock);
@@ -702,7 +666,6 @@
}
}
-
/*Added by Amr - BugID_4720*/
static void linux_wlan_init_spin_lock(char *lockName, void *plock, int count)
{
@@ -780,9 +743,8 @@
}
}
PRINT_INFO(INIT_DBG, "Invalide handle\n");
- for (i = 0; i < 25; i++) {
+ for (i = 0; i < 25; i++)
PRINT_D(INIT_DBG, "%02x ", pMacHeader[i]);
- }
Bssid = pMacHeader + 18;
Bssid1 = pMacHeader + 12;
for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
@@ -822,9 +784,8 @@
uint8_t ret_val = 0;
for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
- if (memcmp(g_linux_wlan->strInterfaceInfo[i].aBSSID, null_bssid, 6)) {
+ if (memcmp(g_linux_wlan->strInterfaceInfo[i].aBSSID, null_bssid, 6))
ret_val++;
- }
}
return ret_val;
}
@@ -868,7 +829,6 @@
#define TX_BACKOFF_WEIGHT_MIN (0)
#define TX_BACKOFF_WEIGHT_UNIT_MS (10)
int backoff_weight = TX_BACKOFF_WEIGHT_MIN;
- signed long timeout;
#endif
/* inform wilc1000_wlan_init that TXQ task is started. */
@@ -906,7 +866,6 @@
}
if (ret == WILC_TX_ERR_NO_BUF) { /* failed to allocate buffers in chip. */
- timeout = msecs_to_jiffies(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
do {
/* Back off from sending packets for some time. */
/* schedule_timeout will allow RX task to run and free buffers.*/
@@ -915,15 +874,13 @@
msleep(TX_BACKOFF_WEIGHT_UNIT_MS << backoff_weight);
} while (/*timeout*/ 0);
backoff_weight += TX_BACKOFF_WEIGHT_INCR_STEP;
- if (backoff_weight > TX_BACKOFF_WEIGHT_MAX) {
+ if (backoff_weight > TX_BACKOFF_WEIGHT_MAX)
backoff_weight = TX_BACKOFF_WEIGHT_MAX;
- }
} else {
if (backoff_weight > TX_BACKOFF_WEIGHT_MIN) {
backoff_weight -= TX_BACKOFF_WEIGHT_DECR_STEP;
- if (backoff_weight < TX_BACKOFF_WEIGHT_MIN) {
+ if (backoff_weight < TX_BACKOFF_WEIGHT_MIN)
backoff_weight = TX_BACKOFF_WEIGHT_MIN;
- }
}
}
/*TODO: drop packets after a certain time/number of retry count. */
@@ -946,7 +903,6 @@
const struct firmware *wilc_firmware;
char *firmware;
-
if (nic->iftype == AP_MODE)
firmware = AP_FIRMWARE;
else if (nic->iftype == STATION_MODE)
@@ -958,8 +914,6 @@
firmware = P2P_CONCURRENCY_FIRMWARE;
}
-
-
if (nic == NULL) {
PRINT_ER("NIC is NULL\n");
goto _fail_;
@@ -970,7 +924,6 @@
goto _fail_;
}
-
/* the firmare should be located in /lib/firmware in
* root file system with the name specified above */
@@ -1054,9 +1007,8 @@
**/
PRINT_D(INIT_DBG, "Downloading Firmware ...\n");
ret = g_linux_wlan->oup.wlan_firmware_download(g_linux_wlan->wilc_firmware->data, g_linux_wlan->wilc_firmware->size);
- if (ret < 0) {
+ if (ret < 0)
goto _FAIL_;
- }
/* Freeing FW buffer */
PRINT_D(INIT_DBG, "Freeing FW buffer ...\n");
@@ -1064,13 +1016,12 @@
release_firmware(g_linux_wlan->wilc_firmware);
g_linux_wlan->wilc_firmware = NULL;
- PRINT_D(INIT_DBG, "Download Succeeded \n");
+ PRINT_D(INIT_DBG, "Download Succeeded\n");
_FAIL_:
return ret;
}
-
/* startup configuration - could be changed later using iconfig*/
static int linux_wlan_init_test_config(struct net_device *dev, linux_wlan_t *p_nic)
{
@@ -1096,7 +1047,6 @@
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(0);
-
if (g_linux_wlan->oup.wlan_cfg_set == NULL) {
PRINT_D(INIT_DBG, "Null p[ointer\n");
goto _fail_;
@@ -1116,7 +1066,6 @@
if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_BSS_TYPE, c_val, 1, 0, 0))
goto _fail_;
-
/* c_val[0] = RATE_AUTO; / * bug 4275: Enable autorate and limit it to 24Mbps * / */
c_val[0] = RATE_AUTO;
if (!g_linux_wlan->oup.wlan_cfg_set(0, WID_CURRENT_TX_RATE, c_val, 1, 0, 0))
@@ -1351,7 +1300,6 @@
return -1;
}
-
/**************************/
void wilc1000_wlan_deinit(linux_wlan_t *nic)
{
@@ -1385,16 +1333,12 @@
#endif
#endif
-
/* not sure if the following unlocks are needed or not*/
- if (&g_linux_wlan->rxq_event != NULL) {
+ if (&g_linux_wlan->rxq_event != NULL)
linux_wlan_unlock(&g_linux_wlan->rxq_event);
- }
- if (&g_linux_wlan->txq_event != NULL) {
+ if (&g_linux_wlan->txq_event != NULL)
linux_wlan_unlock(&g_linux_wlan->txq_event);
- }
-
#if (RX_BH_TYPE == RX_BH_WORK_QUEUE)
/*Removing the work struct from the linux kernel workqueue*/
@@ -1412,7 +1356,6 @@
PRINT_D(INIT_DBG, "Deinitializing IRQ\n");
deinit_irq(g_linux_wlan);
-
if (&g_linux_wlan->oup != NULL) {
if (g_linux_wlan->oup.wlan_stop != NULL)
g_linux_wlan->oup.wlan_stop();
@@ -1442,7 +1385,6 @@
} else {
PRINT_D(INIT_DBG, "wilc1000 is not initialized\n");
}
- return;
}
int wlan_init_locks(linux_wlan_t *p_nic)
@@ -1536,7 +1478,7 @@
nwi->os_context.txq_wait_event = (void *)&g_linux_wlan->txq_event;
-#if defined (MEMORY_STATIC)
+#if defined(MEMORY_STATIC)
nwi->os_context.rx_buffer_size = LINUX_RX_SIZE;
#endif
nwi->os_context.rxq_critical_section = (void *)&g_linux_wlan->rxq_cs;
@@ -1673,17 +1615,14 @@
if (&g_linux_wlan->rxq_event != NULL)
linux_wlan_unlock(&g_linux_wlan->rxq_event);
-
if (g_linux_wlan->rxq_thread != NULL) {
kthread_stop(g_linux_wlan->rxq_thread);
g_linux_wlan->rxq_thread = NULL;
}
-
if (&g_linux_wlan->txq_event != NULL)
linux_wlan_unlock(&g_linux_wlan->txq_event);
-
if (g_linux_wlan->txq_thread != NULL) {
kthread_stop(g_linux_wlan->txq_thread);
g_linux_wlan->txq_thread = NULL;
@@ -1747,14 +1686,12 @@
}
}
- if (index == array_size) {
+ if (index == array_size)
PRINT_ER("random MAC\n");
- }
exit:
- if (fp && !IS_ERR(fp)) {
+ if (fp && !IS_ERR(fp))
filp_close(fp, NULL);
- }
set_fs(old_fs);
@@ -1786,9 +1723,8 @@
sdio_register_driver(&wilc_bus);
- while (!probe) {
+ while (!probe)
msleep(100);
- }
probe = 0;
g_linux_wlan->wilc_sdio_func = local_sdio_func;
linux_to_wlan(nwi, nic);
@@ -1820,9 +1756,8 @@
sdio_register_driver(&wilc_bus);
/* msleep(1000); */
- while (!probe) {
+ while (!probe)
msleep(100);
- }
probe = 0;
g_linux_wlan->wilc_sdio_func = local_sdio_func;
linux_to_wlan(&nwi, g_linux_wlan);
@@ -1834,7 +1769,7 @@
#endif
if (linux_wlan_get_firmware(nic)) {
- PRINT_ER("Can't get firmware \n");
+ PRINT_ER("Can't get firmware\n");
ret = -1;
goto __fail__;
}
@@ -1847,9 +1782,8 @@
}
/* Start firmware*/
ret = linux_wlan_start_firmware(nic);
- if (ret < 0) {
+ if (ret < 0)
PRINT_ER("Failed to start firmware\n");
- }
__fail__:
return ret;
}
@@ -1871,9 +1805,8 @@
#ifdef STATIC_MACADDRESS
wilc_mac_thread = kthread_run(linux_wlan_read_mac_addr, NULL, "wilc_mac_thread");
- if (wilc_mac_thread < 0) {
+ if (wilc_mac_thread < 0)
PRINT_ER("couldn't create Mac addr thread\n");
- }
#endif
linux_to_wlan(&nwi, g_linux_wlan);
@@ -1889,7 +1822,6 @@
/*Save the oup structre into global pointer*/
gpstrWlanOps = &g_linux_wlan->oup;
-
ret = wlan_initialize_threads(nic);
if (ret < 0) {
PRINT_ER("Initializing Threads FAILED\n");
@@ -1922,12 +1854,11 @@
#endif
if (linux_wlan_get_firmware(nic)) {
- PRINT_ER("Can't get firmware \n");
+ PRINT_ER("Can't get firmware\n");
ret = -EIO;
goto _fail_irq_enable_;
}
-
/*Download firmware*/
ret = linux_wlan_firmware_download(g_linux_wlan);
if (ret < 0) {
@@ -1967,7 +1898,6 @@
g_linux_wlan->wilc1000_initialized = 1;
return 0; /*success*/
-
_fail_fw_start_:
if (&g_linux_wlan->oup != NULL) {
if (g_linux_wlan->oup.wlan_stop != NULL)
@@ -1996,12 +1926,11 @@
return ret;
}
-
/*
* - this function will be called automatically by OS when module inserted.
*/
-#if !defined (NM73131_0_BOARD)
+#if !defined(NM73131_0_BOARD)
int mac_init_fn(struct net_device *ndev)
{
@@ -2028,12 +1957,11 @@
}
#endif
-
void WILC_WFI_frame_register(struct wiphy *wiphy, struct net_device *dev,
u16 frame_type, bool reg);
/* This fn is called, when this device is setup using ifconfig */
-#if !defined (NM73131_0_BOARD)
+#if !defined(NM73131_0_BOARD)
int mac_open(struct net_device *ndev)
{
perInterface_wlan_t *nic;
@@ -2078,7 +2006,7 @@
for (i = 0; i < g_linux_wlan->u8NoIfcs; i++) {
if (ndev == g_linux_wlan->strInterfaceInfo[i].wilc_netdev) {
memcpy(g_linux_wlan->strInterfaceInfo[i].aSrcAddress, mac_add, ETH_ALEN);
- g_linux_wlan->strInterfaceInfo[i].drvHandler = (u32)priv->hWILCWFIDrv;
+ g_linux_wlan->strInterfaceInfo[i].drvHandler = priv->hWILCWFIDrv;
break;
}
}
@@ -2092,7 +2020,6 @@
goto _err_;
}
-
WILC_WFI_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev,
nic->g_struct_frame_reg[0].frame_type, nic->g_struct_frame_reg[0].reg);
WILC_WFI_frame_register(nic->wilc_netdev->ieee80211_ptr->wiphy, nic->wilc_netdev,
@@ -2131,7 +2058,6 @@
{
perInterface_wlan_t *nic = netdev_priv(dev);
-
return &nic->netstats;
}
@@ -2146,17 +2072,16 @@
priv = wiphy_priv(dev->ieee80211_ptr->wiphy);
pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
-
if (!dev)
return;
- PRINT_D(INIT_DBG, "Setting Multicast List with count = %d. \n", dev->mc.count);
+ PRINT_D(INIT_DBG, "Setting Multicast List with count = %d.\n", dev->mc.count);
if (dev->flags & IFF_PROMISC) {
/* Normally, we should configure the chip to retrive all packets
* but we don't wanna support this right now */
/* TODO: add promiscuous mode support */
- PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets \n");
+ PRINT_D(INIT_DBG, "Set promiscuous mode ON, retrive all packets\n");
return;
}
@@ -2165,27 +2090,27 @@
if ((dev->flags & IFF_ALLMULTI) || (dev->mc.count) > WILC_MULTICAST_TABLE_SIZE) {
PRINT_D(INIT_DBG, "Disable multicast filter, retrive all multicast packets\n");
/* get all multicast packets */
- host_int_setup_multicast_filter((WILC_WFIDrvHandle)pstrWFIDrv, false, 0);
+ host_int_setup_multicast_filter(pstrWFIDrv, false, 0);
return;
}
/* No multicast? Just get our own stuff */
if ((dev->mc.count) == 0) {
PRINT_D(INIT_DBG, "Enable multicast filter, retrive directed packets only.\n");
- host_int_setup_multicast_filter((WILC_WFIDrvHandle)pstrWFIDrv, true, 0);
+ host_int_setup_multicast_filter(pstrWFIDrv, true, 0);
return;
}
/* Store all of the multicast addresses in the hardware filter */
netdev_for_each_mc_addr(ha, dev)
{
- WILC_memcpy(gau8MulticastMacAddrList[i], ha->addr, ETH_ALEN);
+ memcpy(gau8MulticastMacAddrList[i], ha->addr, ETH_ALEN);
PRINT_D(INIT_DBG, "Entry[%d]: %x:%x:%x:%x:%x:%x\n", i,
gau8MulticastMacAddrList[i][0], gau8MulticastMacAddrList[i][1], gau8MulticastMacAddrList[i][2], gau8MulticastMacAddrList[i][3], gau8MulticastMacAddrList[i][4], gau8MulticastMacAddrList[i][5]);
i++;
}
- host_int_setup_multicast_filter((WILC_WFIDrvHandle)pstrWFIDrv, true, (dev->mc.count));
+ host_int_setup_multicast_filter(pstrWFIDrv, true, (dev->mc.count));
return;
@@ -2195,11 +2120,10 @@
{
struct tx_complete_data *pv_data = (struct tx_complete_data *)priv;
- if (status == 1) {
+ 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 {
+ 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);
- }
/* Free the SK Buffer, its work is done */
dev_kfree_skb(pv_data->skb);
linux_wlan_free(pv_data);
@@ -2215,7 +2139,7 @@
struct ethhdr *eth_h;
nic = netdev_priv(ndev);
- PRINT_D(INT_DBG, "\n========\n IntUH: %d - IntBH: %d - IntCld: %d \n========\n", int_rcvdU, int_rcvdB, int_clrd);
+ PRINT_D(INT_DBG, "\n========\n IntUH: %d - IntBH: %d - IntCld: %d\n========\n", int_rcvdU, int_rcvdB, int_clrd);
PRINT_D(TX_DBG, "Sending packet just received from TCP/IP\n");
/* Stop the network interface queue */
@@ -2237,18 +2161,16 @@
tx_data->skb = skb;
eth_h = (struct ethhdr *)(skb->data);
- if (eth_h->h_proto == 0x8e88) {
+ if (eth_h->h_proto == 0x8e88)
PRINT_D(INIT_DBG, "EAPOL transmitted\n");
- }
/*get source and dest ip addresses*/
ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
pu8UdpBuffer = (char *)ih + sizeof(struct iphdr);
- if ((pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67) || (pu8UdpBuffer[1] == 67 && pu8UdpBuffer[3] == 68)) {
+ if ((pu8UdpBuffer[1] == 68 && pu8UdpBuffer[3] == 67) || (pu8UdpBuffer[1] == 67 && pu8UdpBuffer[3] == 68))
PRINT_D(GENERIC_DBG, "DHCP Message transmitted, type:%x %x %x\n", pu8UdpBuffer[248], pu8UdpBuffer[249], pu8UdpBuffer[250]);
- }
PRINT_D(TX_DBG, "Sending packet - Size = %d - Address = %p - SKB = %p\n", tx_data->size, tx_data->buff, tx_data->skb);
/* Send packet to MAC HW - for now the tx_complete function will be just status
@@ -2269,7 +2191,6 @@
QueueCount = WILC_Xmit_data((void *)tx_data, HOST_TO_WLAN);
#endif /* WILC_FULLY_HOSTING_AP */
-
if (QueueCount > FLOW_CONTROL_UPPER_THRESHOLD) {
netif_stop_queue(g_linux_wlan->strInterfaceInfo[0].wilc_netdev);
netif_stop_queue(g_linux_wlan->strInterfaceInfo[1].wilc_netdev);
@@ -2278,7 +2199,6 @@
return 0;
}
-
int mac_close(struct net_device *ndev)
{
struct WILC_WFI_priv *priv;
@@ -2301,8 +2221,6 @@
pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
-
-
PRINT_D(GENERIC_DBG, "Mac close\n");
if (g_linux_wlan == NULL) {
@@ -2348,7 +2266,6 @@
return 0;
}
-
int mac_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
{
@@ -2359,8 +2276,6 @@
struct WILC_WFI_priv *priv;
s32 s32Error = WILC_SUCCESS;
-
-
/* struct iwreq *wrq = (struct iwreq *) req; // tony moved to case SIOCSIWPRIV */
#ifdef USE_WIRELESS
nic = netdev_priv(ndev);
@@ -2422,9 +2337,7 @@
done:
- if (buff != NULL) {
- kfree(buff);
- }
+ kfree(buff);
return s32Error;
}
@@ -2455,7 +2368,6 @@
frame_len = size;
buff_to_send = buff;
-
/* Need to send the packet up to the host, allocate a skb buffer */
skb = dev_alloc_skb(frame_len);
if (skb == NULL) {
@@ -2465,14 +2377,12 @@
skb_reserve(skb, (unsigned int)skb->data & 0x3);
- if (g_linux_wlan == NULL || wilc_netdev == NULL) {
+ if (g_linux_wlan == NULL || wilc_netdev == NULL)
PRINT_ER("wilc_netdev in g_linux_wlan is NULL");
- }
skb->dev = wilc_netdev;
- if (skb->dev == NULL) {
+ if (skb->dev == NULL)
PRINT_ER("skb->dev is NULL\n");
- }
/*
* for(i=0;i<40;i++)
@@ -2502,9 +2412,8 @@
ih = (struct iphdr *)(skb->data + sizeof(struct ethhdr));
pu8UdpBuffer = (char *)ih + sizeof(struct iphdr);
- if (buff_to_send[35] == 67 && buff_to_send[37] == 68) {
+ if (buff_to_send[35] == 67 && buff_to_send[37] == 68)
PRINT_D(RX_DBG, "DHCP Message received\n");
- }
if (buff_to_send[12] == 0x88 && buff_to_send[13] == 0x8e)
PRINT_D(GENERIC_DBG, "eapol received\n");
#endif
@@ -2516,9 +2425,8 @@
PRINT_D(RX_DBG, "netif_rx ret value is: %d\n", stats);
}
#ifndef TCP_ENHANCEMENTS
- else {
+ else
PRINT_ER("Discard sending packet with len = %d\n", size);
- }
#endif
}
@@ -2541,9 +2449,8 @@
#ifdef WILC_P2P
nic = netdev_priv(g_linux_wlan->strInterfaceInfo[1].wilc_netdev); /* p2p0 */
if ((buff[0] == nic->g_struct_frame_reg[0].frame_type && nic->g_struct_frame_reg[0].reg) ||
- (buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg)) {
+ (buff[0] == nic->g_struct_frame_reg[1].frame_type && nic->g_struct_frame_reg[1].reg))
WILC_WFI_p2p_rx(g_linux_wlan->strInterfaceInfo[1].wilc_netdev, buff, size);
- }
#endif
}
@@ -2557,7 +2464,7 @@
linux_wlan_init_lock("close_exit_sync", &close_exit_sync, 0);
/*create the common structure*/
- g_linux_wlan = (linux_wlan_t *)WILC_MALLOC(sizeof(linux_wlan_t));
+ g_linux_wlan = WILC_MALLOC(sizeof(linux_wlan_t));
memset(g_linux_wlan, 0, sizeof(linux_wlan_t));
/*Reset interrupt count debug*/
@@ -2625,7 +2532,6 @@
}
#endif
-
if (register_netdev(ndev)) {
PRINT_ER("Device couldn't be registered - %s\n", ndev->name);
return -1; /* ERROR */
@@ -2638,7 +2544,7 @@
#ifndef WILC_SDIO
if (!linux_spi_init(&g_linux_wlan->wilc_spidev)) {
- PRINT_ER("Can't initialize SPI \n");
+ PRINT_ER("Can't initialize SPI\n");
return -1; /* ERROR */
}
g_linux_wlan->wilc_spidev = wilc_spi_dev;
@@ -2649,13 +2555,10 @@
return 0;
}
-
/*The 1st function called after module inserted*/
static int __init init_wilc_driver(void)
{
-
-
-#if defined (WILC_DEBUGFS)
+#if defined(WILC_DEBUGFS)
if (wilc_debugfs_init() < 0) {
PRINT_D(GENERIC_DBG, "fail to create debugfs for wilc driver\n");
return -1;
@@ -2674,17 +2577,15 @@
int ret;
ret = sdio_register_driver(&wilc_bus);
- if (ret < 0) {
+ if (ret < 0)
PRINT_D(INIT_DBG, "init_wilc_driver: Failed register sdio driver\n");
- }
return ret;
}
#else
PRINT_D(INIT_DBG, "Initializing netdev\n");
- if (wilc_netdev_init()) {
+ if (wilc_netdev_init())
PRINT_ER("Couldn't initialize netdev\n");
- }
return 0;
#endif
}
@@ -2702,18 +2603,15 @@
unregister_inetaddr_notifier(&g_dev_notifier);
#endif
- for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
+ for (i = 0; i < NUM_CONCURRENT_IFC; i++)
nic[i] = netdev_priv(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
- }
}
-
if ((g_linux_wlan != NULL) && g_linux_wlan->wilc_firmware != NULL) {
release_firmware(g_linux_wlan->wilc_firmware);
g_linux_wlan->wilc_firmware = NULL;
}
-
if ((g_linux_wlan != NULL) && (((g_linux_wlan->strInterfaceInfo[0].wilc_netdev) != NULL)
|| ((g_linux_wlan->strInterfaceInfo[1].wilc_netdev) != NULL))) {
PRINT_D(INIT_DBG, "Waiting for mac_close ....\n");
@@ -2723,17 +2621,15 @@
else
PRINT_D(INIT_DBG, "mac_closed\n");
-
for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
/* close all opened interfaces */
if (g_linux_wlan->strInterfaceInfo[i].wilc_netdev != NULL) {
- if (nic[i]->mac_opened) {
+ if (nic[i]->mac_opened)
mac_close(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
- }
}
}
for (i = 0; i < NUM_CONCURRENT_IFC; i++) {
- PRINT_D(INIT_DBG, "Unregistering netdev %p \n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
+ PRINT_D(INIT_DBG, "Unregistering netdev %p\n", g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
unregister_netdev(g_linux_wlan->strInterfaceInfo[i].wilc_netdev);
#ifdef USE_WIRELESS
PRINT_D(INIT_DBG, "Freeing Wiphy...\n");
@@ -2744,7 +2640,6 @@
}
}
-
#ifdef USE_WIRELESS
#ifdef WILC_AP_EXTERNAL_MLME
/* Bug 4600 : WILC_WFI_deinit_mon_interface was already called at mac_close */
@@ -2764,12 +2659,12 @@
linux_wlan_deinit_lock(&close_exit_sync);
if (g_linux_wlan != NULL) {
- WILC_FREE(g_linux_wlan);
+ kfree(g_linux_wlan);
g_linux_wlan = NULL;
}
printk("Module_exit Done.\n");
-#if defined (WILC_DEBUGFS)
+#if defined(WILC_DEBUGFS)
wilc_debugfs_remove();
#endif
@@ -2780,4 +2675,3 @@
module_exit(exit_wilc_driver);
MODULE_LICENSE("GPL");
-#endif
diff --git a/drivers/staging/wilc1000/linux_wlan_common.h b/drivers/staging/wilc1000/linux_wlan_common.h
index 2476bfd..e6ebf3e 100644
--- a/drivers/staging/wilc1000/linux_wlan_common.h
+++ b/drivers/staging/wilc1000/linux_wlan_common.h
@@ -39,8 +39,8 @@
#define FIRM_DBG (1 << Firmware_debug)
#if defined (WILC_DEBUGFS)
-extern int wilc_debugfs_init(void);
-extern void wilc_debugfs_remove(void);
+int wilc_debugfs_init(void);
+void wilc_debugfs_remove(void);
extern atomic_t REGION;
extern atomic_t DEBUG_LEVEL;
diff --git a/drivers/staging/wilc1000/linux_wlan_sdio.c b/drivers/staging/wilc1000/linux_wlan_sdio.c
index 858e3a1..37f31f4 100644
--- a/drivers/staging/wilc1000/linux_wlan_sdio.c
+++ b/drivers/staging/wilc1000/linux_wlan_sdio.c
@@ -31,7 +31,6 @@
struct sdio_func *local_sdio_func;
extern linux_wlan_t *g_linux_wlan;
extern int wilc_netdev_init(void);
-extern int sdio_clear_int(void);
extern void wilc_handle_isr(void);
static unsigned int sdio_default_speed;
diff --git a/drivers/staging/wilc1000/wilc_debugfs.c b/drivers/staging/wilc1000/wilc_debugfs.c
index c328208..ae11186 100644
--- a/drivers/staging/wilc1000/wilc_debugfs.c
+++ b/drivers/staging/wilc1000/wilc_debugfs.c
@@ -48,38 +48,28 @@
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
-static ssize_t wilc_debug_level_write(struct file *filp, const char *buf, size_t count, loff_t *ppos)
+static ssize_t wilc_debug_level_write(struct file *filp, const char __user *buf,
+ size_t count, loff_t *ppos)
{
- char buffer[128] = {};
int flag = 0;
+ int ret;
- if (count > sizeof(buffer))
- return -EINVAL;
-
- if (copy_from_user(buffer, buf, count)) {
- return -EFAULT;
- }
-
- flag = buffer[0] - '0';
-
- if (flag > 0) {
- flag = DEBUG | ERR;
- } else if (flag < 0) {
- flag = 100;
- }
+ ret = kstrtouint_from_user(buf, count, 16, &flag);
+ if (ret)
+ return ret;
if (flag > DBG_LEVEL_ALL) {
printk("%s, value (0x%08x) is out of range, stay previous flag (0x%08x)\n", __func__, flag, atomic_read(&DEBUG_LEVEL));
- return -EFAULT;
+ return -EINVAL;
}
atomic_set(&DEBUG_LEVEL, (int)flag);
- if (flag == 0) {
+ if (flag == 0)
printk("Debug-level disabled\n");
- } else {
+ else
printk("Debug-level enabled\n");
- }
+
return count;
}
diff --git a/drivers/staging/wilc1000/wilc_exported_buf.c b/drivers/staging/wilc1000/wilc_exported_buf.c
index 5294578..c3f6a0a 100644
--- a/drivers/staging/wilc1000/wilc_exported_buf.c
+++ b/drivers/staging/wilc1000/wilc_exported_buf.c
@@ -8,9 +8,6 @@
#define LINUX_TX_SIZE (64 * 1024)
#define WILC1000_FW_SIZE (4 * 1024)
-#define DECLARE_WILC_BUFFER(name) \
- void *exported_ ## name = NULL;
-
#define MALLOC_WILC_BUFFER(name, size) \
exported_ ## name = kmalloc(size, GFP_KERNEL); \
if (!exported_ ## name) { \
@@ -24,9 +21,9 @@
/*
* Add necessary buffer pointers
*/
-DECLARE_WILC_BUFFER(g_tx_buf)
-DECLARE_WILC_BUFFER(g_rx_buf)
-DECLARE_WILC_BUFFER(g_fw_buf)
+void *exported_g_tx_buf;
+void *exported_g_rx_buf;
+void *exported_g_fw_buf;
void *get_tx_buffer(void)
{
@@ -65,12 +62,10 @@
FREE_WILC_BUFFER(g_tx_buf)
FREE_WILC_BUFFER(g_rx_buf)
FREE_WILC_BUFFER(g_fw_buf)
-
- return;
}
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Tony Cho");
MODULE_DESCRIPTION("WILC1xxx Memory Manager");
pure_initcall(wilc_module_init);
-module_exit(wilc_module_deinit);
\ No newline at end of file
+module_exit(wilc_module_deinit);
diff --git a/drivers/staging/wilc1000/wilc_log.h b/drivers/staging/wilc1000/wilc_log.h
deleted file mode 100644
index 2269ebd..0000000
--- a/drivers/staging/wilc1000/wilc_log.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef __WILC_LOG_H__
-#define __WILC_LOG_H__
-
-/* Errors will always get printed */
-#define WILC_ERROR(...) do { WILC_PRINTF("(ERR)(%s:%d) ", __WILC_FUNCTION__, __WILC_LINE__); \
- WILC_PRINTF(__VA_ARGS__); \
- } while (0)
-
-/* Wraning only printed if verbosity is 1 or more */
-#if (WILC_LOG_VERBOSITY_LEVEL > 0)
-#define WILC_WARN(...) do { WILC_PRINTF("(WRN)"); \
- WILC_PRINTF(__VA_ARGS__); \
- } while (0)
-#else
-#define WILC_WARN(...) (0)
-#endif
-
-/* Info only printed if verbosity is 2 or more */
-#if (WILC_LOG_VERBOSITY_LEVEL > 1)
-#define WILC_INFO(...) do { WILC_PRINTF("(INF)"); \
- WILC_PRINTF(__VA_ARGS__); \
- } while (0)
-#else
-#define WILC_INFO(...) (0)
-#endif
-
-/* Debug is only printed if verbosity is 3 or more */
-#if (WILC_LOG_VERBOSITY_LEVEL > 2)
-#define WILC_DBG(...) do { WILC_PRINTF("(DBG)(%s:%d) ", __WILC_FUNCTION__, __WILC_LINE__); \
- WILC_PRINTF(__VA_ARGS__); \
- } while (0)
-
-#else
-#define WILC_DBG(...) (0)
-#endif
-
-/* Function In/Out is only printed if verbosity is 4 or more */
-#if (WILC_LOG_VERBOSITY_LEVEL > 3)
-#define WILC_FN_IN do { WILC_PRINTF("(FIN) (%s:%d) \n", __WILC_FUNCTION__, __WILC_LINE__); } while (0)
-#define WILC_FN_OUT(ret) do { WILC_PRINTF("(FOUT) (%s:%d) %d.\n", __WILC_FUNCTION__, __WILC_LINE__, (ret)); } while (0)
-#else
-#define WILC_FN_IN (0)
-#define WILC_FN_OUT(ret) (0)
-#endif
-
-
-#endif
\ No newline at end of file
diff --git a/drivers/staging/wilc1000/wilc_memory.c b/drivers/staging/wilc1000/wilc_memory.c
index c70707f..e90a957 100644
--- a/drivers/staging/wilc1000/wilc_memory.c
+++ b/drivers/staging/wilc1000/wilc_memory.c
@@ -9,50 +9,8 @@
void *WILC_MemoryAlloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
char *pcFileName, u32 u32LineNo)
{
- if (u32Size > 0) {
+ if (u32Size > 0)
return kmalloc(u32Size, GFP_ATOMIC);
- } else {
+ else
return NULL;
- }
-}
-
-/*!
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-void *WILC_MemoryCalloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
- char *pcFileName, u32 u32LineNo)
-{
- return kcalloc(u32Size, 1, GFP_KERNEL);
-}
-
-/*!
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-void *WILC_MemoryRealloc(void *pvOldBlock, u32 u32NewSize,
- tstrWILC_MemoryAttrs *strAttrs, char *pcFileName, u32 u32LineNo)
-{
- if (u32NewSize == 0) {
- kfree(pvOldBlock);
- return NULL;
- } else if (pvOldBlock == NULL) {
- return kmalloc(u32NewSize, GFP_KERNEL);
- } else {
- return krealloc(pvOldBlock, u32NewSize, GFP_KERNEL);
- }
-
-}
-
-/*!
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-void WILC_MemoryFree(const void *pvBlock, tstrWILC_MemoryAttrs *strAttrs,
- char *pcFileName, u32 u32LineNo)
-{
- kfree(pvBlock);
}
diff --git a/drivers/staging/wilc1000/wilc_memory.h b/drivers/staging/wilc1000/wilc_memory.h
index 372d705..f19cec1 100644
--- a/drivers/staging/wilc1000/wilc_memory.h
+++ b/drivers/staging/wilc1000/wilc_memory.h
@@ -38,8 +38,6 @@
* @sa sttrWILC_MemoryAttrs
* @sa WILC_MALLOC
* @sa WILC_MALLOC_EX
- * @sa WILC_NEW
- * @sa WILC_NEW_EX
* @author syounan
* @date 16 Aug 2010
* @version 1.0
@@ -48,140 +46,12 @@
char *pcFileName, u32 u32LineNo);
/*!
- * @brief Allocates a given size of bytes and zero filling it
- * @param[in] u32Size size of memory in bytes to be allocated
- * @param[in] strAttrs Optional attributes, NULL for default
- * if not NULL, pAllocationPool should point to the pool to use for
- * this allocation. if NULL memory will be allocated directly from
- * the system
- * @param[in] pcFileName file name of the calling code for debugging
- * @param[in] u32LineNo line number of the calling code for debugging
- * @return The new allocated block, NULL if allocation fails
- * @note It is recommended to use of of the wrapper macros instead of
- * calling this function directly
- * @sa sttrWILC_MemoryAttrs
- * @sa WILC_CALLOC
- * @sa WILC_CALLOC_EX
- * @sa WILC_NEW_0
- * @sa WILC_NEW_0_EX
- * @author syounan
- * @date 16 Aug 2010
- * @version 1.0
- */
-void *WILC_MemoryCalloc(u32 u32Size, tstrWILC_MemoryAttrs *strAttrs,
- char *pcFileName, u32 u32LineNo);
-
-/*!
- * @brief Reallocates a given block to a new size
- * @param[in] pvOldBlock the old memory block, if NULL then this function
- * behaves as a new allocation function
- * @param[in] u32NewSize size of the new memory block in bytes, if zero then
- * this function behaves as a free function
- * @param[in] strAttrs Optional attributes, NULL for default
- * if pAllocationPool!=NULL and pvOldBlock==NULL, pAllocationPool
- * should point to the pool to use for this allocation.
- * if pAllocationPool==NULL and pvOldBlock==NULL memory will be
- * allocated directly from the system
- * if and pvOldBlock!=NULL, pAllocationPool will not be inspected
- * and reallocation is done from the same pool as the original block
- * @param[in] pcFileName file name of the calling code for debugging
- * @param[in] u32LineNo line number of the calling code for debugging
- * @return The new allocated block, possibly same as pvOldBlock
- * @note It is recommended to use of of the wrapper macros instead of
- * calling this function directly
- * @sa sttrWILC_MemoryAttrs
- * @sa WILC_REALLOC
- * @sa WILC_REALLOC_EX
- * @author syounan
- * @date 16 Aug 2010
- * @version 1.0
- */
-void *WILC_MemoryRealloc(void *pvOldBlock, u32 u32NewSize,
- tstrWILC_MemoryAttrs *strAttrs, char *pcFileName, u32 u32LineNo);
-
-/*!
- * @brief Frees given block
- * @param[in] pvBlock the memory block to be freed
- * @param[in] strAttrs Optional attributes, NULL for default
- * @param[in] pcFileName file name of the calling code for debugging
- * @param[in] u32LineNo line number of the calling code for debugging
- * @note It is recommended to use of of the wrapper macros instead of
- * calling this function directly
- * @sa sttrWILC_MemoryAttrs
- * @sa WILC_FREE
- * @sa WILC_FREE_EX
- * @sa WILC_FREE_SET_NULL
- * @sa WILC_FREE_IF_TRUE
- * @author syounan
- * @date 16 Aug 2010
- * @version 1.0
- */
-void WILC_MemoryFree(const void *pvBlock, tstrWILC_MemoryAttrs *strAttrs,
- char *pcFileName, u32 u32LineNo);
-
-/*!
* @brief standrad malloc wrapper with custom attributes
*/
#define WILC_MALLOC_EX(__size__, __attrs__) \
(WILC_MemoryAlloc( \
(__size__), __attrs__, NULL, 0))
-/*!
- * @brief standrad calloc wrapper with custom attributes
- */
- #define WILC_CALLOC_EX(__size__, __attrs__) \
- (WILC_MemoryCalloc( \
- (__size__), __attrs__, NULL, 0))
-
-/*!
- * @brief standrad realloc wrapper with custom attributes
- */
- #define WILC_REALLOC_EX(__ptr__, __new_size__, __attrs__) \
- (WILC_MemoryRealloc( \
- (__ptr__), (__new_size__), __attrs__, NULL, 0))
-/*!
- * @brief standrad free wrapper with custom attributes
- */
- #define WILC_FREE_EX(__ptr__, __attrs__) \
- (WILC_MemoryFree( \
- (__ptr__), __attrs__, NULL, 0))
-
-/*!
- * @brief Allocates a block (with custom attributes) of given type and number of
- * elements
- */
-#define WILC_NEW_EX(__struct_type__, __n_structs__, __attrs__) \
- ((__struct_type__ *)WILC_MALLOC_EX( \
- sizeof(__struct_type__) * (u32)(__n_structs__), __attrs__))
-
-/*!
- * @brief Allocates a block (with custom attributes) of given type and number of
- * elements and Zero-fills it
- */
-#define WILC_NEW_0_EX(__struct_type__, __n_structs__, __attrs__) \
- ((__struct_type__ *)WILC_CALLOC_EX( \
- sizeof(__struct_type__) * (u32)(__n_structs__), __attrs__))
-
-/*!
- * @brief Frees a block (with custom attributes), also setting the original pointer
- * to NULL
- */
-#define WILC_FREE_SET_NULL_EX(__ptr__, __attrs__) do { \
- if (__ptr__ != NULL) { \
- WILC_FREE_EX(__ptr__, __attrs__); \
- __ptr__ = NULL; \
- } \
-} while (0)
-
-/*!
- * @brief Frees a block (with custom attributes) if the pointer expression evaluates
- * to true
- */
-#define WILC_FREE_IF_TRUE_EX(__ptr__, __attrs__) do { \
- if (__ptr__ != NULL) { \
- WILC_FREE_EX(__ptr__, __attrs__); \
- } \
-} while (0)
/*!
* @brief standrad malloc wrapper with default attributes
@@ -189,51 +59,8 @@
#define WILC_MALLOC(__size__) \
WILC_MALLOC_EX(__size__, NULL)
-/*!
- * @brief standrad calloc wrapper with default attributes
- */
-#define WILC_CALLOC(__size__) \
- WILC_CALLOC_EX(__size__, NULL)
-/*!
- * @brief standrad realloc wrapper with default attributes
- */
-#define WILC_REALLOC(__ptr__, __new_size__) \
- WILC_REALLOC_EX(__ptr__, __new_size__, NULL)
-/*!
- * @brief standrad free wrapper with default attributes
- */
-#define WILC_FREE(__ptr__) \
- WILC_FREE_EX(__ptr__, NULL)
-
-/*!
- * @brief Allocates a block (with default attributes) of given type and number of
- * elements
- */
-#define WILC_NEW(__struct_type__, __n_structs__) \
- WILC_NEW_EX(__struct_type__, __n_structs__, NULL)
-
-/*!
- * @brief Allocates a block (with default attributes) of given type and number of
- * elements and Zero-fills it
- */
-#define WILC_NEW_0(__struct_type__, __n_structs__) \
- WILC_NEW_O_EX(__struct_type__, __n_structs__, NULL)
-
-/*!
- * @brief Frees a block (with default attributes), also setting the original pointer
- * to NULL
- */
-#define WILC_FREE_SET_NULL(__ptr__) \
- WILC_FREE_SET_NULL_EX(__ptr__, NULL)
-
-/*!
- * @brief Frees a block (with default attributes) if the pointer expression evaluates
- * to true
- */
-#define WILC_FREE_IF_TRUE(__ptr__) \
- WILC_FREE_IF_TRUE_EX(__ptr__, NULL)
#endif
diff --git a/drivers/staging/wilc1000/wilc_msgqueue.c b/drivers/staging/wilc1000/wilc_msgqueue.c
index 16bcef4..70e4fa6 100644
--- a/drivers/staging/wilc1000/wilc_msgqueue.c
+++ b/drivers/staging/wilc1000/wilc_msgqueue.c
@@ -8,8 +8,7 @@
* @note copied from FLO glue implementatuion
* @version 1.0
*/
-WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle,
- tstrWILC_MsgQueueAttrs *pstrAttrs)
+WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle)
{
spin_lock_init(&pHandle->strCriticalSection);
sema_init(&pHandle->hSem, 0);
@@ -25,8 +24,7 @@
* @note copied from FLO glue implementatuion
* @version 1.0
*/
-WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle,
- tstrWILC_MsgQueueAttrs *pstrAttrs)
+WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle)
{
pHandle->bExiting = true;
@@ -39,7 +37,7 @@
while (pHandle->pstrMessageList != NULL) {
Message *pstrMessge = pHandle->pstrMessageList->pstrNext;
- WILC_FREE(pHandle->pstrMessageList);
+ kfree(pHandle->pstrMessageList);
pHandle->pstrMessageList = pstrMessge;
}
@@ -53,8 +51,7 @@
* @version 1.0
*/
WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle,
- const void *pvSendBuffer, u32 u32SendBufferSize,
- tstrWILC_MsgQueueAttrs *pstrAttrs)
+ const void *pvSendBuffer, u32 u32SendBufferSize)
{
WILC_ErrNo s32RetStatus = WILC_SUCCESS;
unsigned long flags;
@@ -71,13 +68,13 @@
spin_lock_irqsave(&pHandle->strCriticalSection, flags);
/* construct a new message */
- pstrMessage = WILC_NEW(Message, 1);
+ pstrMessage = kmalloc(sizeof(Message), GFP_ATOMIC);
WILC_NULLCHECK(s32RetStatus, pstrMessage);
pstrMessage->u32Length = u32SendBufferSize;
pstrMessage->pstrNext = NULL;
pstrMessage->pvBuffer = WILC_MALLOC(u32SendBufferSize);
WILC_NULLCHECK(s32RetStatus, pstrMessage->pvBuffer);
- WILC_memcpy(pstrMessage->pvBuffer, pvSendBuffer, u32SendBufferSize);
+ memcpy(pstrMessage->pvBuffer, pvSendBuffer, u32SendBufferSize);
/* add it to the message queue */
@@ -100,9 +97,9 @@
/* error occured, free any allocations */
if (pstrMessage != NULL) {
if (pstrMessage->pvBuffer != NULL) {
- WILC_FREE(pstrMessage->pvBuffer);
+ kfree(pstrMessage->pvBuffer);
}
- WILC_FREE(pstrMessage);
+ kfree(pstrMessage);
}
}
@@ -119,8 +116,7 @@
*/
WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle,
void *pvRecvBuffer, u32 u32RecvBufferSize,
- u32 *pu32ReceivedLength,
- tstrWILC_MsgQueueAttrs *pstrAttrs)
+ u32 *pu32ReceivedLength)
{
Message *pstrMessage;
@@ -170,13 +166,13 @@
/* consume the message */
pHandle->u32ReceiversCount--;
- WILC_memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length);
+ memcpy(pvRecvBuffer, pstrMessage->pvBuffer, pstrMessage->u32Length);
*pu32ReceivedLength = pstrMessage->u32Length;
pHandle->pstrMessageList = pstrMessage->pstrNext;
- WILC_FREE(pstrMessage->pvBuffer);
- WILC_FREE(pstrMessage);
+ kfree(pstrMessage->pvBuffer);
+ kfree(pstrMessage);
spin_unlock_irqrestore(&pHandle->strCriticalSection, flags);
diff --git a/drivers/staging/wilc1000/wilc_msgqueue.h b/drivers/staging/wilc1000/wilc_msgqueue.h
index 35b1001..ef1d2fa 100644
--- a/drivers/staging/wilc1000/wilc_msgqueue.h
+++ b/drivers/staging/wilc1000/wilc_msgqueue.h
@@ -13,20 +13,6 @@
#include "wilc_platform.h"
#include "wilc_errorsupport.h"
#include "wilc_memory.h"
-#include "wilc_strutils.h"
-
-/*!
- * @struct tstrWILC_MsgQueueAttrs
- * @brief Message Queue API options
- * @author syounan
- * @date 30 Aug 2010
- * @version 1.0
- */
-typedef struct {
- /* a dummy member to avoid compiler errors*/
- u8 dummy;
-
-} tstrWILC_MsgQueueAttrs;
/*!
* @brief Creates a new Message queue
@@ -37,14 +23,11 @@
* @param[in,out] pHandle handle to the message queue object
* @param[in] pstrAttrs Optional attributes, NULL for default
* @return Error code indicating sucess/failure
- * @sa tstrWILC_MsgQueueAttrs
* @author syounan
* @date 30 Aug 2010
* @version 1.0
*/
-WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle,
- tstrWILC_MsgQueueAttrs *pstrAttrs);
-
+WILC_ErrNo WILC_MsgQueueCreate(WILC_MsgQueueHandle *pHandle);
/*!
* @brief Sends a message
@@ -57,15 +40,12 @@
* @param[in] u32SendBufferSize the size of the data to send
* @param[in] pstrAttrs Optional attributes, NULL for default
* @return Error code indicating sucess/failure
- * @sa tstrWILC_MsgQueueAttrs
* @author syounan
* @date 30 Aug 2010
* @version 1.0
*/
WILC_ErrNo WILC_MsgQueueSend(WILC_MsgQueueHandle *pHandle,
- const void *pvSendBuffer, u32 u32SendBufferSize,
- tstrWILC_MsgQueueAttrs *pstrAttrs);
-
+ const void *pvSendBuffer, u32 u32SendBufferSize);
/*!
* @brief Receives a message
@@ -79,30 +59,23 @@
* @param[out] pu32ReceivedLength the length of received data
* @param[in] pstrAttrs Optional attributes, NULL for default
* @return Error code indicating sucess/failure
- * @sa tstrWILC_MsgQueueAttrs
* @author syounan
* @date 30 Aug 2010
* @version 1.0
*/
WILC_ErrNo WILC_MsgQueueRecv(WILC_MsgQueueHandle *pHandle,
void *pvRecvBuffer, u32 u32RecvBufferSize,
- u32 *pu32ReceivedLength,
- tstrWILC_MsgQueueAttrs *pstrAttrs);
-
+ 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 sucess/failure
- * @sa tstrWILC_MsgQueueAttrs
* @author syounan
* @date 30 Aug 2010
* @version 1.0
*/
-WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle,
- tstrWILC_MsgQueueAttrs *pstrAttrs);
-
-
+WILC_ErrNo WILC_MsgQueueDestroy(WILC_MsgQueueHandle *pHandle);
#endif
diff --git a/drivers/staging/wilc1000/wilc_osconfig.h b/drivers/staging/wilc1000/wilc_osconfig.h
deleted file mode 100644
index f9c2514..0000000
--- a/drivers/staging/wilc1000/wilc_osconfig.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* Logs options */
-#define WILC_LOGS_NOTHING 0
-#define WILC_LOGS_WARN 1
-#define WILC_LOGS_WARN_INFO 2
-#define WILC_LOGS_WARN_INFO_DBG 3
-#define WILC_LOGS_WARN_INFO_DBG_FN 4
-#define WILC_LOGS_ALL 5
-
-#define WILC_LOG_VERBOSITY_LEVEL WILC_LOGS_ALL
diff --git a/drivers/staging/wilc1000/wilc_oswrapper.h b/drivers/staging/wilc1000/wilc_oswrapper.h
index e97aa96..cb48325 100644
--- a/drivers/staging/wilc1000/wilc_oswrapper.h
+++ b/drivers/staging/wilc1000/wilc_oswrapper.h
@@ -14,26 +14,14 @@
#define WILC_OSW_INTERFACE_VER 2
/* Os Configuration File */
-#include "wilc_osconfig.h"
#include "wilc_platform.h"
-/* Logging Functions */
-#include "wilc_log.h"
-
/* Error reporting and handling support */
#include "wilc_errorsupport.h"
-/* Sleep support */
-#include "wilc_sleep.h"
-
-/* Timer support */
-#include "wilc_timer.h"
-
/* Memory support */
#include "wilc_memory.h"
-/* String Utilities */
-#include "wilc_strutils.h"
/* Message Queue */
#include "wilc_msgqueue.h"
diff --git a/drivers/staging/wilc1000/wilc_platform.h b/drivers/staging/wilc1000/wilc_platform.h
index d03532c..1e56973 100644
--- a/drivers/staging/wilc1000/wilc_platform.h
+++ b/drivers/staging/wilc1000/wilc_platform.h
@@ -1,5 +1,5 @@
-#ifndef __WILC_platfrom_H__
-#define __WILC_platfrom_H__
+#ifndef __WILC_platform_H__
+#define __WILC_platform_H__
#include <linux/kthread.h>
#include <linux/semaphore.h>
@@ -16,10 +16,6 @@
* OS specific types
*******************************************************************/
-typedef struct timer_list WILC_TimerHandle;
-
-
-
/* Message Queue type is a structure */
typedef struct __Message_struct {
void *pvBuffer;
diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c
index 897e47e..5a18148 100644
--- a/drivers/staging/wilc1000/wilc_sdio.c
+++ b/drivers/staging/wilc1000/wilc_sdio.c
@@ -10,17 +10,7 @@
#include "wilc_wlan_if.h"
#include "wilc_wlan.h"
-
-#ifdef WILC1000_SINGLE_TRANSFER
-#define WILC_SDIO_BLOCK_SIZE 256
-#else
- #if defined(PLAT_AML8726_M3) /* johnny */
- #define WILC_SDIO_BLOCK_SIZE 512
- #define MAX_SEG_SIZE (1 << 12) /* 4096 */
- #else
- #define WILC_SDIO_BLOCK_SIZE 512
- #endif
-#endif
+#define WILC_SDIO_BLOCK_SIZE 512
typedef struct {
void *os_context;
@@ -90,7 +80,6 @@
{
sdio_cmd52_t cmd;
-
/**
* Review: BIG ENDIAN
**/
@@ -108,6 +97,7 @@
_fail_:
return 0;
}
+
static int sdio_set_func0_block_size(uint32_t block_size)
{
sdio_cmd52_t cmd;
@@ -170,6 +160,7 @@
#ifndef WILC_SDIO_IRQ_GPIO
/* uint32_t sts; */
sdio_cmd52_t cmd;
+
cmd.read_write = 0;
cmd.function = 1;
cmd.raw = 0;
@@ -181,6 +172,7 @@
return cmd.data;
#else
uint32_t reg;
+
if (!sdio_read_reg(WILC_HOST_RX_CTRL_0, ®)) {
g_sdio.dPrint(N_ERR, "[wilc spi]: Failed read reg (%08x)...\n", WILC_HOST_RX_CTRL_0);
return 0;
@@ -197,6 +189,7 @@
{
uint32_t cnt = 0;
sdio_cmd52_t cmd;
+
cmd.read_write = 0;
cmd.function = 1;
cmd.raw = 0;
@@ -222,8 +215,6 @@
cnt |= (cmd.data << 16);
return cnt;
-
-
}
/********************************************
@@ -263,6 +254,7 @@
if ((addr >= 0xf0) && (addr <= 0xff)) {
sdio_cmd52_t cmd;
+
cmd.read_write = 1;
cmd.function = 0;
cmd.raw = 0;
@@ -325,16 +317,6 @@
cmd.function = 0;
cmd.address = 0x10f;
} else {
-#ifdef WILC1000_SINGLE_TRANSFER
- /**
- * has to be block aligned...
- **/
- nleft = size % block_size;
- if (nleft > 0) {
- size += block_size;
- size &= ~(block_size - 1);
- }
-#else
/**
* has to be word aligned...
**/
@@ -342,7 +324,6 @@
size += 4;
size &= ~0x3;
}
-#endif
/**
* func 1 access
@@ -355,89 +336,6 @@
nleft = size % block_size;
if (nblk > 0) {
-
-#if defined(PLAT_AML8726_M3_BACKUP) /* johnny */
- int i;
-
- for (i = 0; i < nblk; i++) {
- cmd.block_mode = 0; /* 1; */
- cmd.increment = 1;
- cmd.count = block_size; /* nblk; */
- cmd.buffer = buf;
- cmd.block_size = block_size;
- if (addr > 0) {
- if (!sdio_set_func0_csa_address(addr))
- goto _fail_;
- }
- if (!g_sdio.sdio_cmd53(&cmd)) {
- g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr);
- goto _fail_;
- }
-
- if (addr > 0)
- addr += block_size; /* addr += nblk*block_size; */
-
- buf += block_size; /* buf += nblk*block_size; */
- }
-
-#elif defined(PLAT_AML8726_M3) /* johnny */
-
- int i;
- int rest;
- int seg_cnt;
-
- seg_cnt = (nblk * block_size) / MAX_SEG_SIZE;
- rest = (nblk * block_size) & (MAX_SEG_SIZE - 1);
-
- for (i = 0; i < seg_cnt; i++) {
- cmd.block_mode = 1;
- cmd.increment = 1;
- cmd.count = MAX_SEG_SIZE / block_size;
- cmd.buffer = buf;
- cmd.block_size = block_size;
-
- if (addr > 0) {
- if (!sdio_set_func0_csa_address(addr))
- goto _fail_;
- }
- if (!g_sdio.sdio_cmd53(&cmd)) {
- g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block send...\n", addr);
- goto _fail_;
- }
-
- if (addr > 0)
- addr += MAX_SEG_SIZE;
-
- buf += MAX_SEG_SIZE;
-
- }
-
-
- if (rest > 0) {
- cmd.block_mode = 1;
- cmd.increment = 1;
- cmd.count = rest / block_size;
- cmd.buffer = buf;
- cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */
-
- if (addr > 0) {
- if (!sdio_set_func0_csa_address(addr))
- goto _fail_;
- }
- if (!g_sdio.sdio_cmd53(&cmd)) {
- g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], bytes send...\n", addr);
- goto _fail_;
- }
-
- if (addr > 0)
- addr += rest;
-
- buf += rest;
-
- }
-
-#else
-
cmd.block_mode = 1;
cmd.increment = 1;
cmd.count = nblk;
@@ -454,11 +352,8 @@
if (addr > 0)
addr += nblk * block_size;
buf += nblk * block_size;
-
-#endif /* platform */
}
-
if (nleft > 0) {
cmd.block_mode = 0;
cmd.increment = 1;
@@ -488,6 +383,7 @@
{
if ((addr >= 0xf0) && (addr <= 0xff)) {
sdio_cmd52_t cmd;
+
cmd.read_write = 0;
cmd.function = 0;
cmd.raw = 0;
@@ -552,16 +448,6 @@
cmd.function = 0;
cmd.address = 0x10f;
} else {
-#ifdef WILC1000_SINGLE_TRANSFER
- /**
- * has to be block aligned...
- **/
- nleft = size % block_size;
- if (nleft > 0) {
- size += block_size;
- size &= ~(block_size - 1);
- }
-#else
/**
* has to be word aligned...
**/
@@ -569,7 +455,6 @@
size += 4;
size &= ~0x3;
}
-#endif
/**
* func 1 access
@@ -582,89 +467,6 @@
nleft = size % block_size;
if (nblk > 0) {
-
-#if defined(PLAT_AML8726_M3_BACKUP) /* johnny */
-
- int i;
-
- for (i = 0; i < nblk; i++) {
- cmd.block_mode = 0; /* 1; */
- cmd.increment = 1;
- cmd.count = block_size; /* nblk; */
- cmd.buffer = buf;
- cmd.block_size = block_size;
- if (addr > 0) {
- if (!sdio_set_func0_csa_address(addr))
- goto _fail_;
- }
- if (!g_sdio.sdio_cmd53(&cmd)) {
- g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr);
- goto _fail_;
- }
- if (addr > 0)
- addr += block_size; /* addr += nblk*block_size; */
- buf += block_size; /* buf += nblk*block_size; */
- }
-
-#elif defined(PLAT_AML8726_M3) /* johnny */
-
- int i;
- int rest;
- int seg_cnt;
-
- seg_cnt = (nblk * block_size) / MAX_SEG_SIZE;
- rest = (nblk * block_size) & (MAX_SEG_SIZE - 1);
-
- for (i = 0; i < seg_cnt; i++) {
- cmd.block_mode = 1;
- cmd.increment = 1;
- cmd.count = MAX_SEG_SIZE / block_size;
- cmd.buffer = buf;
- cmd.block_size = block_size;
-
-
- if (addr > 0) {
- if (!sdio_set_func0_csa_address(addr))
- goto _fail_;
- }
- if (!g_sdio.sdio_cmd53(&cmd)) {
- g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr);
- goto _fail_;
- }
-
- if (addr > 0)
- addr += MAX_SEG_SIZE;
-
- buf += MAX_SEG_SIZE;
-
- }
-
-
- if (rest > 0) {
- cmd.block_mode = 1;
- cmd.increment = 1;
- cmd.count = rest / block_size;
- cmd.buffer = buf;
- cmd.block_size = block_size; /* johnny : prevent it from setting unexpected value */
-
- if (addr > 0) {
- if (!sdio_set_func0_csa_address(addr))
- goto _fail_;
- }
- if (!g_sdio.sdio_cmd53(&cmd)) {
- g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed cmd53 [%x], block read...\n", addr);
- goto _fail_;
- }
-
- if (addr > 0)
- addr += rest;
-
- buf += rest;
-
- }
-
-#else
-
cmd.block_mode = 1;
cmd.increment = 1;
cmd.count = nblk;
@@ -681,8 +483,6 @@
if (addr > 0)
addr += nblk * block_size;
buf += nblk * block_size;
-
-#endif /* platform */
} /* if (nblk > 0) */
if (nleft > 0) {
@@ -784,6 +584,7 @@
sdio_cmd52_t cmd;
int loop;
uint32_t chipid;
+
memset(&g_sdio, 0, sizeof(wilc_sdio_t));
g_sdio.dPrint = func;
@@ -891,14 +692,12 @@
goto _fail_;
}
g_sdio.dPrint(N_ERR, "[wilc sdio]: chipid (%08x)\n", chipid);
- if ((chipid & 0xfff) > 0x2a0) {
+ if ((chipid & 0xfff) > 0x2a0)
g_sdio.has_thrpt_enh3 = 1;
- } else {
+ else
g_sdio.has_thrpt_enh3 = 0;
- }
g_sdio.dPrint(N_ERR, "[wilc sdio]: has_thrpt_enh3 = %d...\n", g_sdio.has_thrpt_enh3);
-
return 1;
_fail_:
@@ -925,23 +724,21 @@
/**
* Read DMA count in words
**/
- {
- cmd.read_write = 0;
- cmd.function = 0;
- cmd.raw = 0;
- cmd.address = 0xf2;
- cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
- tmp = cmd.data;
+ cmd.read_write = 0;
+ cmd.function = 0;
+ cmd.raw = 0;
+ cmd.address = 0xf2;
+ cmd.data = 0;
+ g_sdio.sdio_cmd52(&cmd);
+ tmp = cmd.data;
- /* cmd.read_write = 0; */
- /* cmd.function = 0; */
- /* cmd.raw = 0; */
- cmd.address = 0xf3;
- cmd.data = 0;
- g_sdio.sdio_cmd52(&cmd);
- tmp |= (cmd.data << 8);
- }
+ /* cmd.read_write = 0; */
+ /* cmd.function = 0; */
+ /* cmd.raw = 0; */
+ cmd.address = 0xf3;
+ cmd.data = 0;
+ g_sdio.sdio_cmd52(&cmd);
+ tmp |= (cmd.data << 8);
*size = tmp;
return 1;
@@ -966,26 +763,21 @@
cmd.data = 0;
g_sdio.sdio_cmd52(&cmd);
- if (cmd.data & (1 << 0)) {
+ if (cmd.data & (1 << 0))
tmp |= INT_0;
- }
- if (cmd.data & (1 << 2)) {
+ if (cmd.data & (1 << 2))
tmp |= INT_1;
- }
- if (cmd.data & (1 << 3)) {
+ if (cmd.data & (1 << 3))
tmp |= INT_2;
- }
- if (cmd.data & (1 << 4)) {
+ if (cmd.data & (1 << 4))
tmp |= INT_3;
- }
- if (cmd.data & (1 << 5)) {
+ if (cmd.data & (1 << 5))
tmp |= INT_4;
- }
- if (cmd.data & (1 << 6)) {
+ if (cmd.data & (1 << 6))
tmp |= INT_5;
- }
{
int i;
+
for (i = g_sdio.nint; i < MAX_NUM_INT; i++) {
if ((tmp >> (IRG_FLAGS_OFFSET + i)) & 0x1) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt (1) : tmp=%x, data=%x\n", tmp, cmd.data);
@@ -1024,6 +816,7 @@
#ifdef WILC_SDIO_IRQ_GPIO
{
uint32_t flags;
+
flags = val & ((1 << MAX_NUN_INT_THRPT_ENH2) - 1);
reg = flags;
}
@@ -1041,6 +834,7 @@
reg |= (1 << 7);
if (reg) {
sdio_cmd52_t cmd;
+
cmd.read_write = 1;
cmd.function = 0;
cmd.raw = 0;
@@ -1060,6 +854,7 @@
/* see below. has_thrpt_enh2 uses register 0xf8 to clear interrupts. */
/* Cannot clear multiple interrupts. Must clear each interrupt individually */
uint32_t flags;
+
flags = val & ((1 << MAX_NUM_INT) - 1);
if (flags) {
int i;
@@ -1068,6 +863,7 @@
for (i = 0; i < g_sdio.nint; i++) {
if (flags & 1) {
sdio_cmd52_t cmd;
+
cmd.read_write = 1;
cmd.function = 0;
cmd.raw = 0;
@@ -1085,9 +881,8 @@
break;
flags >>= 1;
}
- if (!ret) {
+ if (!ret)
goto _fail_;
- }
for (i = g_sdio.nint; i < MAX_NUM_INT; i++) {
if (flags & 1)
g_sdio.dPrint(N_ERR, "[wilc sdio]: Unexpected interrupt cleared %d...\n", i);
@@ -1097,7 +892,6 @@
}
#endif /* WILC_SDIO_IRQ_GPIO */
-
{
uint32_t vmm_ctl;
@@ -1138,7 +932,6 @@
{
uint32_t reg;
-
if (nint > MAX_NUM_INT) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Too many interupts (%d)...\n", nint);
return 0;
@@ -1148,7 +941,6 @@
return 0;
}
-
g_sdio.nint = nint;
/**
@@ -1170,7 +962,6 @@
uint32_t reg;
int ret, i;
-
/**
* interrupt pin mux select
**/
@@ -1195,9 +986,8 @@
return 0;
}
- for (i = 0; (i < 5) && (nint > 0); i++, nint--) {
+ for (i = 0; (i < 5) && (nint > 0); i++, nint--)
reg |= (1 << (27 + i));
- }
ret = sdio_write_reg(WILC_INTR_ENABLE, reg);
if (!ret) {
g_sdio.dPrint(N_ERR, "[wilc sdio]: Failed write reg (%08x)...\n", WILC_INTR_ENABLE);
@@ -1210,9 +1000,8 @@
return 0;
}
- for (i = 0; (i < 3) && (nint > 0); i++, nint--) {
+ for (i = 0; (i < 3) && (nint > 0); i++, nint--)
reg |= (1 << i);
- }
ret = sdio_read_reg(WILC_INTR2_ENABLE, ®);
if (!ret) {
@@ -1225,7 +1014,6 @@
return 1;
}
-
/********************************************
*
* Global sdio HIF function table
diff --git a/drivers/staging/wilc1000/wilc_sleep.c b/drivers/staging/wilc1000/wilc_sleep.c
deleted file mode 100644
index adab3cac..0000000
--- a/drivers/staging/wilc1000/wilc_sleep.c
+++ /dev/null
@@ -1,18 +0,0 @@
-
-#include "wilc_sleep.h"
-
-/*
- * @author mdaftedar
- * @date 10 Aug 2010
- * @version 1.0
- */
-void WILC_Sleep(u32 u32TimeMilliSec)
-{
- if (u32TimeMilliSec <= 4000000) {
- u32 u32Temp = u32TimeMilliSec * 1000;
- usleep_range(u32Temp, u32Temp);
- } else {
- msleep(u32TimeMilliSec);
- }
-
-}
diff --git a/drivers/staging/wilc1000/wilc_sleep.h b/drivers/staging/wilc1000/wilc_sleep.h
deleted file mode 100644
index cf9047f..0000000
--- a/drivers/staging/wilc1000/wilc_sleep.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef __WILC_SLEEP_H__
-#define __WILC_SLEEP_H__
-
-#include <linux/types.h>
-#include <linux/delay.h>
-
-/*!
- * @brief forces the current thread to sleep until the given time has elapsed
- * @param[in] u32TimeMilliSec Time to sleep in Milli seconds
- * @sa WILC_SleepMicrosec
- * @author syounan
- * @date 10 Aug 2010
- * @version 1.0
- * @note This function offers a relatively innacurate and low resolution
- * sleep, for accurate high resolution sleep use u32TimeMicoSec
- */
-/* TODO: remove and open-code in callers */
-void WILC_Sleep(u32 u32TimeMilliSec);
-
-#endif
diff --git a/drivers/staging/wilc1000/wilc_spi.c b/drivers/staging/wilc1000/wilc_spi.c
index abea5df..1bf7d31 100644
--- a/drivers/staging/wilc1000/wilc_spi.c
+++ b/drivers/staging/wilc1000/wilc_spi.c
@@ -374,11 +374,10 @@
return result;
}
- if (!g_spi.crc_off) {
+ if (!g_spi.crc_off)
wb[len - 1] = (crc7(0x7f, (const uint8_t *)&wb[0], len - 1)) << 1;
- } else {
+ else
len -= 1;
- }
#define NUM_SKIP_BYTES (1)
#define NUM_RSP_BYTES (2)
@@ -522,11 +521,10 @@
if (sz > 0) {
int nbytes;
- if (sz <= (DATA_PKT_SZ - ix)) {
+ if (sz <= (DATA_PKT_SZ - ix))
nbytes = sz;
- } else {
+ else
nbytes = DATA_PKT_SZ - ix;
- }
/**
* Read bytes
@@ -557,11 +555,10 @@
while (sz > 0) {
int nbytes;
- if (sz <= DATA_PKT_SZ) {
+ if (sz <= DATA_PKT_SZ)
nbytes = sz;
- } else {
+ else
nbytes = DATA_PKT_SZ;
- }
/**
* read data response only on the next DMA cycles not
diff --git a/drivers/staging/wilc1000/wilc_strutils.c b/drivers/staging/wilc1000/wilc_strutils.c
deleted file mode 100644
index e014595..0000000
--- a/drivers/staging/wilc1000/wilc_strutils.c
+++ /dev/null
@@ -1,80 +0,0 @@
-
-#define _CRT_SECURE_NO_DEPRECATE
-
-#include "wilc_strutils.h"
-
-
-/*!
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-s32 WILC_memcmp(const void *pvArg1, const void *pvArg2, u32 u32Count)
-{
- return memcmp(pvArg1, pvArg2, u32Count);
-}
-
-
-/*!
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-void WILC_memcpy_INTERNAL(void *pvTarget, const void *pvSource, u32 u32Count)
-{
- memcpy(pvTarget, pvSource, u32Count);
-}
-
-/*!
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-void *WILC_memset(void *pvTarget, u8 u8SetValue, u32 u32Count)
-{
- return memset(pvTarget, u8SetValue, u32Count);
-}
-
-/*!
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-char *WILC_strncpy(char *pcTarget, const char *pcSource,
- u32 u32Count)
-{
- return strncpy(pcTarget, pcSource, u32Count);
-}
-
-s32 WILC_strncmp(const char *pcStr1, const char *pcStr2,
- u32 u32Count)
-{
- s32 s32Result;
-
- if (pcStr1 == NULL && pcStr2 == NULL) {
- s32Result = 0;
- } else if (pcStr1 == NULL) {
- s32Result = -1;
- } else if (pcStr2 == NULL) {
- s32Result = 1;
- } else {
- s32Result = strncmp(pcStr1, pcStr2, u32Count);
- if (s32Result < 0) {
- s32Result = -1;
- } else if (s32Result > 0) {
- s32Result = 1;
- }
- }
-
- return s32Result;
-}
-
-/*!
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-u32 WILC_strlen(const char *pcStr)
-{
- return (u32)strlen(pcStr);
-}
diff --git a/drivers/staging/wilc1000/wilc_strutils.h b/drivers/staging/wilc1000/wilc_strutils.h
deleted file mode 100644
index d144557..0000000
--- a/drivers/staging/wilc1000/wilc_strutils.h
+++ /dev/null
@@ -1,134 +0,0 @@
-#ifndef __WILC_STRUTILS_H__
-#define __WILC_STRUTILS_H__
-
-/*!
- * @file wilc_strutils.h
- * @brief Basic string utilities
- * @author syounan
- * @sa wilc_oswrapper.h top level OS wrapper file
- * @date 16 Aug 2010
- * @version 1.0
- */
-
-#include <linux/types.h>
-#include <linux/string.h>
-#include "wilc_errorsupport.h"
-
-/*!
- * @brief Compares two memory buffers
- * @param[in] pvArg1 pointer to the first memory location
- * @param[in] pvArg2 pointer to the second memory location
- * @param[in] u32Count the size of the memory buffers
- * @return 0 if the 2 buffers are equal, 1 if pvArg1 is bigger than pvArg2,
- * -1 if pvArg1 smaller than pvArg2
- * @note this function repeats the functionality of standard memcmp
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-s32 WILC_memcmp(const void *pvArg1, const void *pvArg2, u32 u32Count);
-
-/*!
- * @brief Internal implementation for memory copy
- * @param[in] pvTarget the target buffer to which the data is copied into
- * @param[in] pvSource pointer to the second memory location
- * @param[in] u32Count the size of the data to copy
- * @note this function should not be used directly, use WILC_memcpy instead
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-void WILC_memcpy_INTERNAL(void *pvTarget, const void *pvSource, u32 u32Count);
-
-/*!
- * @brief Copies the contents of a memory buffer into another
- * @param[in] pvTarget the target buffer to which the data is copied into
- * @param[in] pvSource pointer to the second memory location
- * @param[in] u32Count the size of the data to copy
- * @return WILC_SUCCESS if copy is successfully handeled
- * WILC_FAIL if copy failed
- * @note this function repeats the functionality of standard memcpy,
- * however memcpy is undefined if the two buffers overlap but this
- * implementation will check for overlap and report error
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-static WILC_ErrNo WILC_memcpy(void *pvTarget, const void *pvSource, u32 u32Count)
-{
- if (
- (((u8 *)pvTarget <= (u8 *)pvSource)
- && (((u8 *)pvTarget + u32Count) > (u8 *)pvSource))
-
- || (((u8 *)pvSource <= (u8 *)pvTarget)
- && (((u8 *)pvSource + u32Count) > (u8 *)pvTarget))
- ) {
- /* ovelapped memory, return Error */
- return WILC_FAIL;
- } else {
- WILC_memcpy_INTERNAL(pvTarget, pvSource, u32Count);
- return WILC_SUCCESS;
- }
-}
-
-/*!
- * @brief Sets the contents of a memory buffer with the given value
- * @param[in] pvTarget the target buffer which contsnts will be set
- * @param[in] u8SetValue the value to be used
- * @param[in] u32Count the size of the memory buffer
- * @return value of pvTarget
- * @note this function repeats the functionality of standard memset
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-void *WILC_memset(void *pvTarget, u8 u8SetValue, u32 u32Count);
-
-/*!
- * @brief copies the contents of source string into the target string
- * @param[in] pcTarget the target string buffer
- * @param[in] pcSource the source string the will be copied
- * @param[in] u32Count copying will proceed until a null character in pcSource
- * is encountered or u32Count of bytes copied
- * @return value of pcTarget
- * @note this function repeats the functionality of standard strncpy
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-char *WILC_strncpy(char *pcTarget, const char *pcSource,
- u32 u32Count);
-
-/*!
- * @brief Compares two strings up to u32Count characters
- * @details Compares 2 strings reporting which is bigger, NULL is considered
- * the smallest string, then a zero length string then all other
- * strings depending on thier ascii characters order with small case
- * converted to uppder case
- * @param[in] pcStr1 the first string, NULL is valid and considered smaller
- * than any other non-NULL string (incliding zero lenght strings)
- * @param[in] pcStr2 the second string, NULL is valid and considered smaller
- * than any other non-NULL string (incliding zero lenght strings)
- * @param[in] u32Count copying will proceed until a null character in pcStr1 or
- * pcStr2 is encountered or u32Count of bytes copied
- * @return 0 if the 2 strings are equal, 1 if pcStr1 is bigger than pcStr2,
- * -1 if pcStr1 smaller than pcStr2
- * @author aabozaeid
- * @date 7 Dec 2010
- * @version 1.0
- */
-s32 WILC_strncmp(const char *pcStr1, const char *pcStr2,
- u32 u32Count);
-
-/*!
- * @brief gets the length of a string
- * @param[in] pcStr the string
- * @return the length
- * @note this function repeats the functionality of standard strlen
- * @author syounan
- * @date 18 Aug 2010
- * @version 1.0
- */
-u32 WILC_strlen(const char *pcStr);
-
-#endif
diff --git a/drivers/staging/wilc1000/wilc_timer.c b/drivers/staging/wilc1000/wilc_timer.c
deleted file mode 100644
index dc71157..0000000
--- a/drivers/staging/wilc1000/wilc_timer.c
+++ /dev/null
@@ -1,45 +0,0 @@
-
-#include "wilc_timer.h"
-
-WILC_ErrNo WILC_TimerCreate(WILC_TimerHandle *pHandle,
- tpfWILC_TimerFunction pfCallback, tstrWILC_TimerAttrs *pstrAttrs)
-{
- WILC_ErrNo s32RetStatus = WILC_SUCCESS;
- setup_timer(pHandle, (void(*)(unsigned long))pfCallback, 0);
-
- return s32RetStatus;
-}
-
-WILC_ErrNo WILC_TimerDestroy(WILC_TimerHandle *pHandle,
- tstrWILC_TimerAttrs *pstrAttrs)
-{
- WILC_ErrNo s32RetStatus = WILC_FAIL;
- if (pHandle != NULL) {
- s32RetStatus = del_timer_sync(pHandle);
- pHandle = NULL;
- }
-
- return s32RetStatus;
-}
-
-
-WILC_ErrNo WILC_TimerStart(WILC_TimerHandle *pHandle, u32 u32Timeout,
- void *pvArg, tstrWILC_TimerAttrs *pstrAttrs)
-{
- WILC_ErrNo s32RetStatus = WILC_FAIL;
- if (pHandle != NULL) {
- pHandle->data = (unsigned long)pvArg;
- s32RetStatus = mod_timer(pHandle, (jiffies + msecs_to_jiffies(u32Timeout)));
- }
- return s32RetStatus;
-}
-
-WILC_ErrNo WILC_TimerStop(WILC_TimerHandle *pHandle,
- tstrWILC_TimerAttrs *pstrAttrs)
-{
- WILC_ErrNo s32RetStatus = WILC_FAIL;
- if (pHandle != NULL)
- s32RetStatus = del_timer(pHandle);
-
- return s32RetStatus;
-}
diff --git a/drivers/staging/wilc1000/wilc_timer.h b/drivers/staging/wilc1000/wilc_timer.h
deleted file mode 100644
index 931269d..0000000
--- a/drivers/staging/wilc1000/wilc_timer.h
+++ /dev/null
@@ -1,129 +0,0 @@
-#ifndef __WILC_TIMER_H__
-#define __WILC_TIMER_H__
-
-/*!
- * @file wilc_timer.h
- * @brief Timer (One Shot and Periodic) OS wrapper functionality
- * @author syounan
- * @sa wilc_oswrapper.h top level OS wrapper file
- * @date 16 Aug 2010
- * @version 1.0
- */
-
-#include "wilc_platform.h"
-#include "wilc_errorsupport.h"
-
-typedef void (*tpfWILC_TimerFunction)(void *);
-
-/*!
- * @struct tstrWILC_TimerAttrs
- * @brief Timer API options
- * @author syounan
- * @date 16 Aug 2010
- * @version 1.0
- */
-typedef struct {
- /* a dummy member to avoid compiler errors*/
- u8 dummy;
-} tstrWILC_TimerAttrs;
-
-/*!
- * @brief Creates a new timer
- * @details Timers are a useful utility to execute some callback function
- * in the future.
- * A timer object has 3 states : IDLE, PENDING and EXECUTING
- * IDLE : initial timer state after creation, no execution for the
- * callback function is planned
- * PENDING : a request to execute the callback function is made
- * using WILC_TimerStart.
- * EXECUTING : the timer has expired and its callback is now
- * executing, when execution is done the timer returns to PENDING
- * if the feature CONFIG_WILC_TIMER_PERIODIC is enabled and
- * the flag tstrWILC_TimerAttrs.bPeriodicTimer is set. otherwise the
- * timer will return to IDLE
- * @param[out] pHandle handle to the newly created timer object
- * @param[in] pfEntry pointer to the callback function to be called when the
- * timer expires
- * the underlaying OS may put many restrictions on what can be
- * called inside a timer's callback, as a general rule no blocking
- * operations (IO or semaphore Acquision) should be perfomred
- * It is recommended that the callback will be as short as possible
- * and only flags other threads to do the actual work
- * also it should be noted that the underlaying OS maynot give any
- * guarentees on which contect this callback will execute in
- * @param[in] pstrAttrs Optional attributes, NULL for default
- * @return Error code indicating sucess/failure
- * @sa WILC_TimerAttrs
- * @author syounan
- * @date 16 Aug 2010
- * @version 1.0
- */
-WILC_ErrNo WILC_TimerCreate(WILC_TimerHandle *pHandle,
- tpfWILC_TimerFunction pfCallback, tstrWILC_TimerAttrs *pstrAttrs);
-
-
-/*!
- * @brief Destroys a given timer
- * @details This will destroy a given timer freeing any resources used by it
- * if the timer was PENDING Then must be cancelled as well(i.e.
- * goes to IDLE, same effect as calling WILC_TimerCancel first)
- * if the timer was EXECUTING then the callback will be allowed to
- * finish first then all resources are freed
- * @param[in] pHandle handle to the timer object
- * @param[in] pstrAttrs Optional attributes, NULL for default
- * @return Error code indicating sucess/failure
- * @sa WILC_TimerAttrs
- * @author syounan
- * @date 16 Aug 2010
- * @version 1.0
- */
-WILC_ErrNo WILC_TimerDestroy(WILC_TimerHandle *pHandle,
- tstrWILC_TimerAttrs *pstrAttrs);
-
-/*!
- * @brief Starts a given timer
- * @details This function will move the timer to the PENDING state until the
- * given time expires (in msec) then the callback function will be
- * executed (timer in EXECUTING state) after execution is dene the
- * timer either goes to IDLE (if bPeriodicTimer==false) or
- * PENDING with same timeout value (if bPeriodicTimer==true)
- * @param[in] pHandle handle to the timer object
- * @param[in] u32Timeout timeout value in msec after witch the callback
- * function will be executed. Timeout value of 0 is not allowed for
- * periodic timers
- * @param[in] pstrAttrs Optional attributes, NULL for default,
- * set bPeriodicTimer to run this timer as a periodic timer
- * @return Error code indicating sucess/failure
- * @sa WILC_TimerAttrs
- * @author syounan
- * @date 16 Aug 2010
- * @version 1.0
- */
-WILC_ErrNo WILC_TimerStart(WILC_TimerHandle *pHandle, u32 u32Timeout, void *pvArg,
- tstrWILC_TimerAttrs *pstrAttrs);
-
-
-/*!
- * @brief Stops a given timer
- * @details This function will move the timer to the IDLE state cancelling
- * any sheduled callback execution.
- * if this function is called on a timer already in the IDLE state
- * it will have no effect.
- * if this function is called on a timer in EXECUTING state
- * (callback has already started) it will wait until executing is
- * done then move the timer to the IDLE state (which is trivial
- * work if the timer is non periodic)
- * @param[in] pHandle handle to the timer object
- * @param[in] pstrAttrs Optional attributes, NULL for default,
- * @return Error code indicating sucess/failure
- * @sa WILC_TimerAttrs
- * @author syounan
- * @date 16 Aug 2010
- * @version 1.0
- */
-WILC_ErrNo WILC_TimerStop(WILC_TimerHandle *pHandle,
- tstrWILC_TimerAttrs *pstrAttrs);
-
-
-
-#endif
diff --git a/drivers/staging/wilc1000/wilc_type.h b/drivers/staging/wilc1000/wilc_type.h
deleted file mode 100644
index 5f36e7f..0000000
--- a/drivers/staging/wilc1000/wilc_type.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* ////////////////////////////////////////////////////////////////////////// */
-/* */
-/* Copyright (c) Atmel Corporation. All rights reserved. */
-/* */
-/* Module Name: wilc_type.h */
-/* */
-/* */
-/* //////////////////////////////////////////////////////////////////////////// */
-#ifndef WILC_TYPE_H
-#define WILC_TYPE_H
-
-/********************************************
- *
- * Type Defines
- *
- ********************************************/
-#ifdef WIN32
-typedef char int8_t;
-typedef short int16_t;
-typedef long int32_t;
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned long uint32_t;
-#else
-#ifdef _linux_
-/*typedef unsigned char uint8_t;
- * typedef unsigned short uint16_t;
- * typedef unsigned long uint32_t;*/
-#include <stdint.h>
-#else
-#include "wilc_oswrapper.h"
-#endif
-#endif
-#endif
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
index 92064db..a6edc97 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.c
@@ -22,7 +22,6 @@
#define IS_MGMT_STATUS_SUCCES 0x040
#define GET_PKT_OFFSET(a) (((a) >> 22) & 0x1ff)
-extern void linux_wlan_free(void *vp);
extern int linux_wlan_get_firmware(perInterface_wlan_t *p_nic);
extern void linux_wlan_unlock(void *vp);
extern u16 Set_machw_change_vir_if(bool bValue);
@@ -33,9 +32,9 @@
tstrNetworkInfo astrLastScannedNtwrksShadow[MAX_NUM_SCANNED_NETWORKS_SHADOW];
u32 u32LastScannedNtwrksCountShadow;
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-WILC_TimerHandle hDuringIpTimer;
+struct timer_list hDuringIpTimer;
#endif
-WILC_TimerHandle hAgingTimer;
+struct timer_list hAgingTimer;
static u8 op_ifcs;
extern u8 u8ConnectedSSID[6];
@@ -112,7 +111,7 @@
u8 u8P2Plocalrandom = 0x01;
u8 u8P2Precvrandom = 0x00;
u8 u8P2P_vendorspec[] = {0xdd, 0x05, 0x00, 0x08, 0x40, 0x03};
-bool bWilc_ie = false;
+bool bWilc_ie;
#endif
static struct ieee80211_supported_band WILC_WFI_band_2ghz = {
@@ -135,25 +134,23 @@
struct wilc_wfi_key g_key_ptk_params;
struct wilc_wfi_wep_key g_key_wep_params;
u8 g_flushing_in_progress;
-bool g_ptk_keys_saved = false;
-bool g_gtk_keys_saved = false;
-bool g_wep_keys_saved = false;
+bool g_ptk_keys_saved;
+bool g_gtk_keys_saved;
+bool g_wep_keys_saved;
#define AGING_TIME (9 * 1000)
#define duringIP_TIME 15000
void clear_shadow_scan(void *pUserVoid)
{
- struct WILC_WFI_priv *priv;
int i;
- priv = (struct WILC_WFI_priv *)pUserVoid;
if (op_ifcs == 0) {
- WILC_TimerDestroy(&hAgingTimer, NULL);
+ del_timer_sync(&hAgingTimer);
PRINT_INFO(CORECONFIG_DBG, "destroy aging timer\n");
for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
if (astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs != NULL) {
- WILC_FREE(astrLastScannedNtwrksShadow[i].pu8IEs);
+ kfree(astrLastScannedNtwrksShadow[i].pu8IEs);
astrLastScannedNtwrksShadow[u32LastScannedNtwrksCountShadow].pu8IEs = NULL;
}
@@ -204,7 +201,7 @@
channel = ieee80211_get_channel(wiphy, s32Freq);
rssi = get_rssi_avg(pstrNetworkInfo);
- if (WILC_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan) {
+ if (memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7) || bDirectScan) {
bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs,
(size_t)pstrNetworkInfo->u16IEsLen, (((s32)rssi) * 100), GFP_KERNEL);
@@ -219,9 +216,7 @@
void reset_shadow_found(void *pUserVoid)
{
- struct WILC_WFI_priv *priv;
int i;
- priv = (struct WILC_WFI_priv *)pUserVoid;
for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
astrLastScannedNtwrksShadow[i].u8Found = 0;
@@ -230,28 +225,24 @@
void update_scan_time(void *pUserVoid)
{
- struct WILC_WFI_priv *priv;
int i;
- priv = (struct WILC_WFI_priv *)pUserVoid;
for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies;
}
}
-void remove_network_from_shadow(void *pUserVoid)
+static void remove_network_from_shadow(unsigned long arg)
{
- struct WILC_WFI_priv *priv;
unsigned long now = jiffies;
int i, j;
- priv = (struct WILC_WFI_priv *)pUserVoid;
for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
if (time_after(now, astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan + (unsigned long)(SCAN_RESULT_EXPIRE))) {
- PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s \n", astrLastScannedNtwrksShadow[i].au8ssid);
+ PRINT_D(CFG80211_DBG, "Network expired in ScanShadow: %s\n", astrLastScannedNtwrksShadow[i].au8ssid);
if (astrLastScannedNtwrksShadow[i].pu8IEs != NULL) {
- WILC_FREE(astrLastScannedNtwrksShadow[i].pu8IEs);
+ kfree(astrLastScannedNtwrksShadow[i].pu8IEs);
astrLastScannedNtwrksShadow[i].pu8IEs = NULL;
}
@@ -265,14 +256,16 @@
}
PRINT_D(CFG80211_DBG, "Number of cached networks: %d\n", u32LastScannedNtwrksCountShadow);
- if (u32LastScannedNtwrksCountShadow != 0)
- WILC_TimerStart(&(hAgingTimer), AGING_TIME, pUserVoid, NULL);
- else
+ if (u32LastScannedNtwrksCountShadow != 0) {
+ hAgingTimer.data = arg;
+ mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
+ } else {
PRINT_D(CFG80211_DBG, "No need to restart Aging timer\n");
+ }
}
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
-void clear_duringIP(void *pUserVoid)
+static void clear_duringIP(unsigned long arg)
{
PRINT_D(GENERIC_DBG, "GO:IP Obtained , enable scan\n");
g_obtainingIP = false;
@@ -281,19 +274,18 @@
int8_t is_network_in_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid)
{
- struct WILC_WFI_priv *priv;
int8_t state = -1;
int i;
- priv = (struct WILC_WFI_priv *)pUserVoid;
if (u32LastScannedNtwrksCountShadow == 0) {
PRINT_D(CFG80211_DBG, "Starting Aging timer\n");
- WILC_TimerStart(&(hAgingTimer), AGING_TIME, pUserVoid, NULL);
+ hAgingTimer.data = (unsigned long)pUserVoid;
+ mod_timer(&hAgingTimer, jiffies + msecs_to_jiffies(AGING_TIME));
state = -1;
} else {
/* Linear search for now */
for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
- if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
+ if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
pstrNetworkInfo->au8bssid, 6) == 0) {
state = i;
break;
@@ -305,11 +297,9 @@
void add_network_to_shadow(tstrNetworkInfo *pstrNetworkInfo, void *pUserVoid, void *pJoinParams)
{
- struct WILC_WFI_priv *priv;
int8_t ap_found = is_network_in_shadow(pstrNetworkInfo, pUserVoid);
uint32_t ap_index = 0;
uint8_t rssi_index = 0;
- priv = (struct WILC_WFI_priv *)pUserVoid;
if (u32LastScannedNtwrksCountShadow >= MAX_NUM_SCANNED_NETWORKS_SHADOW) {
PRINT_D(CFG80211_DBG, "Shadow network reached its maximum limit\n");
@@ -334,10 +324,10 @@
astrLastScannedNtwrksShadow[ap_index].u16CapInfo = pstrNetworkInfo->u16CapInfo;
astrLastScannedNtwrksShadow[ap_index].u8SsidLen = pstrNetworkInfo->u8SsidLen;
- WILC_memcpy(astrLastScannedNtwrksShadow[ap_index].au8ssid,
+ memcpy(astrLastScannedNtwrksShadow[ap_index].au8ssid,
pstrNetworkInfo->au8ssid, pstrNetworkInfo->u8SsidLen);
- WILC_memcpy(astrLastScannedNtwrksShadow[ap_index].au8bssid,
+ memcpy(astrLastScannedNtwrksShadow[ap_index].au8bssid,
pstrNetworkInfo->au8bssid, ETH_ALEN);
astrLastScannedNtwrksShadow[ap_index].u16BeaconPeriod = pstrNetworkInfo->u16BeaconPeriod;
@@ -347,10 +337,10 @@
astrLastScannedNtwrksShadow[ap_index].u16IEsLen = pstrNetworkInfo->u16IEsLen;
astrLastScannedNtwrksShadow[ap_index].u64Tsf = pstrNetworkInfo->u64Tsf;
if (ap_found != -1)
- WILC_FREE(astrLastScannedNtwrksShadow[ap_index].pu8IEs);
+ kfree(astrLastScannedNtwrksShadow[ap_index].pu8IEs);
astrLastScannedNtwrksShadow[ap_index].pu8IEs =
- (u8 *)WILC_MALLOC(pstrNetworkInfo->u16IEsLen); /* will be deallocated by the WILC_WFI_CfgScan() function */
- WILC_memcpy(astrLastScannedNtwrksShadow[ap_index].pu8IEs,
+ WILC_MALLOC(pstrNetworkInfo->u16IEsLen); /* will be deallocated by the WILC_WFI_CfgScan() function */
+ memcpy(astrLastScannedNtwrksShadow[ap_index].pu8IEs,
pstrNetworkInfo->pu8IEs, pstrNetworkInfo->u16IEsLen);
astrLastScannedNtwrksShadow[ap_index].u32TimeRcvdInScan = jiffies;
@@ -406,7 +396,7 @@
WILC_NULLCHECK(s32Error, channel);
PRINT_INFO(CFG80211_DBG, "Network Info:: CHANNEL Frequency: %d, RSSI: %d, CapabilityInfo: %d,"
- "BeaconPeriod: %d \n", channel->center_freq, (((s32)pstrNetworkInfo->s8rssi) * 100),
+ "BeaconPeriod: %d\n", channel->center_freq, (((s32)pstrNetworkInfo->s8rssi) * 100),
pstrNetworkInfo->u16CapInfo, pstrNetworkInfo->u16BeaconPeriod);
if (pstrNetworkInfo->bNewNetwork == true) {
@@ -426,7 +416,7 @@
/*P2P peers are sent to WPA supplicant and added to shadow table*/
- if (!(WILC_memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7))) {
+ if (!(memcmp("DIRECT-", pstrNetworkInfo->au8ssid, 7))) {
bss = cfg80211_inform_bss(wiphy, channel, CFG80211_BSS_FTYPE_UNKNOWN, pstrNetworkInfo->au8bssid, pstrNetworkInfo->u64Tsf, pstrNetworkInfo->u16CapInfo,
pstrNetworkInfo->u16BeaconPeriod, (const u8 *)pstrNetworkInfo->pu8IEs,
(size_t)pstrNetworkInfo->u16IEsLen, (((s32)pstrNetworkInfo->s8rssi) * 100), GFP_KERNEL);
@@ -441,8 +431,8 @@
u32 i;
/* So this network is discovered before, we'll just update its RSSI */
for (i = 0; i < priv->u32RcvdChCount; i++) {
- if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) {
- PRINT_D(CFG80211_DBG, "Update RSSI of %s \n", astrLastScannedNtwrksShadow[i].au8ssid);
+ if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid, pstrNetworkInfo->au8bssid, 6) == 0) {
+ PRINT_D(CFG80211_DBG, "Update RSSI of %s\n", astrLastScannedNtwrksShadow[i].au8ssid);
astrLastScannedNtwrksShadow[i].s8rssi = pstrNetworkInfo->s8rssi;
astrLastScannedNtwrksShadow[i].u32TimeRcvdInScan = jiffies;
@@ -452,15 +442,14 @@
}
}
} else if (enuScanEvent == SCAN_EVENT_DONE) {
- PRINT_D(CFG80211_DBG, "Scan Done[%p] \n", priv->dev);
- PRINT_D(CFG80211_DBG, "Refreshing Scan ... \n");
+ PRINT_D(CFG80211_DBG, "Scan Done[%p]\n", priv->dev);
+ PRINT_D(CFG80211_DBG, "Refreshing Scan ...\n");
refresh_scan(priv, 1, false);
- if (priv->u32RcvdChCount > 0) {
- PRINT_D(CFG80211_DBG, "%d Network(s) found \n", priv->u32RcvdChCount);
- } else {
- PRINT_D(CFG80211_DBG, "No networks found \n");
- }
+ if (priv->u32RcvdChCount > 0)
+ PRINT_D(CFG80211_DBG, "%d Network(s) found\n", priv->u32RcvdChCount);
+ else
+ PRINT_D(CFG80211_DBG, "No networks found\n");
down(&(priv->hSemScanReq));
@@ -477,7 +466,7 @@
else if (enuScanEvent == SCAN_EVENT_ABORTED) {
down(&(priv->hSemScanReq));
- PRINT_D(CFG80211_DBG, "Scan Aborted \n");
+ PRINT_D(CFG80211_DBG, "Scan Aborted\n");
if (priv->pstrScanReq != NULL) {
update_scan_time(priv);
@@ -515,7 +504,7 @@
for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
- if (!WILC_memcmp(bssid, priv->pmkid_list.pmkidlist[i].bssid,
+ if (!memcmp(bssid, priv->pmkid_list.pmkidlist[i].bssid,
ETH_ALEN)) {
PRINT_D(CFG80211_DBG, "PMKID successful comparison");
@@ -586,7 +575,7 @@
* = SUCCESSFUL_STATUSCODE, while mac status is MAC_DISCONNECTED (which means something wrong happened) */
u16ConnectStatus = WLAN_STATUS_UNSPECIFIED_FAILURE;
linux_wlan_set_bssid(priv->dev, NullBssid);
- WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+ memset(u8ConnectedSSID, 0, ETH_ALEN);
/*BugID_5457*/
/*Invalidate u8WLANChannel value on wlan0 disconnect*/
@@ -595,7 +584,7 @@
u8WLANChannel = INVALID_CHANNEL;
#endif
- PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d \n", u16ConnectStatus, u8MacStatus);
+ PRINT_ER("Unspecified failure: Connection status %d : MAC status = %d\n", u16ConnectStatus, u8MacStatus);
}
if (u16ConnectStatus == WLAN_STATUS_SUCCESS) {
@@ -604,14 +593,14 @@
PRINT_INFO(CFG80211_DBG, "Connection Successful:: BSSID: %x%x%x%x%x%x\n", pstrConnectInfo->au8bssid[0],
pstrConnectInfo->au8bssid[1], pstrConnectInfo->au8bssid[2], pstrConnectInfo->au8bssid[3], pstrConnectInfo->au8bssid[4], pstrConnectInfo->au8bssid[5]);
- WILC_memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN);
+ memcpy(priv->au8AssociatedBss, pstrConnectInfo->au8bssid, ETH_ALEN);
/* BugID_4209: if this network has expired in the scan results in the above nl80211 layer, refresh them here by calling
* cfg80211_inform_bss() with the last Scan results before calling cfg80211_connect_result() to avoid
* Linux kernel warning generated at the nl80211 layer */
for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
- if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
+ if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
pstrConnectInfo->au8bssid, ETH_ALEN) == 0) {
unsigned long now = jiffies;
@@ -652,9 +641,9 @@
u8P2Plocalrandom = 0x01;
u8P2Precvrandom = 0x00;
bWilc_ie = false;
- WILC_memset(priv->au8AssociatedBss, 0, ETH_ALEN);
+ memset(priv->au8AssociatedBss, 0, ETH_ALEN);
linux_wlan_set_bssid(priv->dev, NullBssid);
- WILC_memset(u8ConnectedSSID, 0, ETH_ALEN);
+ memset(u8ConnectedSSID, 0, ETH_ALEN);
/*BugID_5457*/
/*Invalidate u8WLANChannel value on wlan0 disconnect*/
@@ -675,7 +664,8 @@
pstrDisconnectNotifInfo->u16reason = 1;
}
cfg80211_disconnected(dev, pstrDisconnectNotifInfo->u16reason, pstrDisconnectNotifInfo->ie,
- pstrDisconnectNotifInfo->ie_len, GFP_KERNEL);
+ pstrDisconnectNotifInfo->ie_len, false,
+ GFP_KERNEL);
}
@@ -747,7 +737,7 @@
priv->u32RcvdChCount = 0;
- host_int_set_wfi_drv_handler((u32)priv->hWILCWFIDrv);
+ host_int_set_wfi_drv_handler(priv->hWILCWFIDrv);
reset_shadow_found(priv);
@@ -777,20 +767,20 @@
if (request->ssids[i].ssid != NULL && request->ssids[i].ssid_len != 0) {
strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid = WILC_MALLOC(request->ssids[i].ssid_len);
- WILC_memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
+ memcpy(strHiddenNetwork.pstrHiddenNetworkInfo[i].pu8ssid, request->ssids[i].ssid, request->ssids[i].ssid_len);
strHiddenNetwork.pstrHiddenNetworkInfo[i].u8ssidlen = request->ssids[i].ssid_len;
} else {
- PRINT_D(CFG80211_DBG, "Received one NULL SSID \n");
+ PRINT_D(CFG80211_DBG, "Received one NULL SSID\n");
strHiddenNetwork.u8ssidnum -= 1;
}
}
- PRINT_D(CFG80211_DBG, "Trigger Scan Request \n");
+ PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN,
au8ScanChanList, request->n_channels,
(const u8 *)request->ie, request->ie_len,
CfgScanResult, (void *)priv, &strHiddenNetwork);
} else {
- PRINT_D(CFG80211_DBG, "Trigger Scan Request \n");
+ PRINT_D(CFG80211_DBG, "Trigger Scan Request\n");
s32Error = host_int_scan(priv->hWILCWFIDrv, USER_SCAN, ACTIVE_SCAN,
au8ScanChanList, request->n_channels,
(const u8 *)request->ie, request->ie_len,
@@ -799,7 +789,7 @@
} else {
PRINT_ER("Requested num of scanned channels is greater than the max, supported"
- " channels \n");
+ " channels\n");
}
if (s32Error != WILC_SUCCESS) {
@@ -842,21 +832,21 @@
priv = wiphy_priv(wiphy);
pstrWFIDrv = (tstrWILC_WFIDrv *)(priv->hWILCWFIDrv);
- host_int_set_wfi_drv_handler((u32)priv->hWILCWFIDrv);
+ host_int_set_wfi_drv_handler(priv->hWILCWFIDrv);
PRINT_D(CFG80211_DBG, "Connecting to SSID [%s] on netdev [%p] host if [%p]\n", sme->ssid, dev, priv->hWILCWFIDrv);
#ifdef WILC_P2P
- if (!(WILC_strncmp(sme->ssid, "DIRECT-", 7))) {
+ if (!(strncmp(sme->ssid, "DIRECT-", 7))) {
PRINT_D(CFG80211_DBG, "Connected to Direct network,OBSS disabled\n");
pstrWFIDrv->u8P2PConnect = 1;
} else
pstrWFIDrv->u8P2PConnect = 0;
#endif
- PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d \n", sme->ssid, sme->auth_type);
+ PRINT_INFO(CFG80211_DBG, "Required SSID = %s\n , AuthType = %d\n", sme->ssid, sme->auth_type);
for (i = 0; i < u32LastScannedNtwrksCountShadow; i++) {
if ((sme->ssid_len == astrLastScannedNtwrksShadow[i].u8SsidLen) &&
- WILC_memcmp(astrLastScannedNtwrksShadow[i].au8ssid,
+ memcmp(astrLastScannedNtwrksShadow[i].au8ssid,
sme->ssid,
sme->ssid_len) == 0) {
PRINT_INFO(CFG80211_DBG, "Network with required SSID is found %s\n", sme->ssid);
@@ -868,7 +858,7 @@
} else {
/* BSSID is also passed from the user, so decision of matching
* should consider also this passed BSSID */
- if (WILC_memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
+ if (memcmp(astrLastScannedNtwrksShadow[i].au8bssid,
sme->bssid,
ETH_ALEN) == 0) {
PRINT_INFO(CFG80211_DBG, "BSSID is passed from the user and matched\n");
@@ -898,8 +888,8 @@
}
priv->WILC_WFI_wep_default = 0;
- WILC_memset(priv->WILC_WFI_wep_key, 0, sizeof(priv->WILC_WFI_wep_key));
- WILC_memset(priv->WILC_WFI_wep_key_len, 0, sizeof(priv->WILC_WFI_wep_key_len));
+ 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.wpa_versions=%x\n", sme->crypto.wpa_versions);
PRINT_INFO(CFG80211_DBG, "sme->crypto.cipher_group=%x\n", sme->crypto.cipher_group);
@@ -928,7 +918,7 @@
}
priv->WILC_WFI_wep_default = sme->key_idx;
priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
- WILC_memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
+ memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
/*BugID_5137*/
g_key_wep_params.key_len = sme->key_len;
@@ -946,7 +936,7 @@
priv->WILC_WFI_wep_default = sme->key_idx;
priv->WILC_WFI_wep_key_len[sme->key_idx] = sme->key_len;
- WILC_memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
+ memcpy(priv->WILC_WFI_wep_key[sme->key_idx], sme->key, sme->key_len);
/*BugID_5137*/
g_key_wep_params.key_len = sme->key_len;
@@ -1057,7 +1047,7 @@
tenuAuth_type, pstrNetworkInfo->u8channel,
pstrNetworkInfo->pJoinParams);
if (s32Error != WILC_SUCCESS) {
- PRINT_ER("host_int_set_join_req(): Error(%d) \n", s32Error);
+ PRINT_ER("host_int_set_join_req(): Error(%d)\n", s32Error);
s32Error = -ENOENT;
goto done;
}
@@ -1162,7 +1152,7 @@
priv->WILC_WFI_wep_default = key_index;
priv->WILC_WFI_wep_key_len[key_index] = params->key_len;
- WILC_memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
+ memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
PRINT_D(CFG80211_DBG, "Adding AP WEP Default key Idx = %d\n", key_index);
PRINT_D(CFG80211_DBG, "Adding AP WEP Key len= %d\n", params->key_len);
@@ -1181,10 +1171,10 @@
break;
}
#endif
- if (WILC_memcmp(params->key, priv->WILC_WFI_wep_key[key_index], params->key_len)) {
+ 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;
- WILC_memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
+ memcpy(priv->WILC_WFI_wep_key[key_index], params->key, params->key_len);
PRINT_D(CFG80211_DBG, "Adding WEP Default key Idx = %d\n", key_index);
PRINT_D(CFG80211_DBG, "Adding WEP Key length = %d\n", params->key_len);
@@ -1203,21 +1193,20 @@
if (priv->wdev->iftype == NL80211_IFTYPE_AP || priv->wdev->iftype == NL80211_IFTYPE_P2P_GO) {
if (priv->wilc_gtk[key_index] == NULL) {
- priv->wilc_gtk[key_index] = (struct wilc_wfi_key *)WILC_MALLOC(sizeof(struct wilc_wfi_key));
+ priv->wilc_gtk[key_index] = WILC_MALLOC(sizeof(struct wilc_wfi_key));
priv->wilc_gtk[key_index]->key = NULL;
priv->wilc_gtk[key_index]->seq = NULL;
}
if (priv->wilc_ptk[key_index] == NULL) {
- priv->wilc_ptk[key_index] = (struct wilc_wfi_key *)WILC_MALLOC(sizeof(struct wilc_wfi_key));
+ priv->wilc_ptk[key_index] = WILC_MALLOC(sizeof(struct wilc_wfi_key));
priv->wilc_ptk[key_index]->key = NULL;
priv->wilc_ptk[key_index]->seq = NULL;
}
- if (!pairwise)
- {
+ if (!pairwise) {
if (params->cipher == WLAN_CIPHER_SUITE_TKIP)
u8gmode = ENCRYPT_ENABLED | WPA | TKIP;
else
@@ -1233,18 +1222,18 @@
}
/* if there has been previous allocation for the same index through its key, free that memory and allocate again*/
if (priv->wilc_gtk[key_index]->key)
- WILC_FREE(priv->wilc_gtk[key_index]->key);
+ kfree(priv->wilc_gtk[key_index]->key);
- priv->wilc_gtk[key_index]->key = (u8 *)WILC_MALLOC(params->key_len);
- WILC_memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
+ priv->wilc_gtk[key_index]->key = WILC_MALLOC(params->key_len);
+ memcpy(priv->wilc_gtk[key_index]->key, params->key, params->key_len);
/* if there has been previous allocation for the same index through its seq, free that memory and allocate again*/
if (priv->wilc_gtk[key_index]->seq)
- WILC_FREE(priv->wilc_gtk[key_index]->seq);
+ kfree(priv->wilc_gtk[key_index]->seq);
if ((params->seq_len) > 0) {
- priv->wilc_gtk[key_index]->seq = (u8 *)WILC_MALLOC(params->seq_len);
- WILC_memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
+ priv->wilc_gtk[key_index]->seq = WILC_MALLOC(params->seq_len);
+ memcpy(priv->wilc_gtk[key_index]->seq, params->seq, params->seq_len);
}
priv->wilc_gtk[key_index]->cipher = params->cipher;
@@ -1279,15 +1268,15 @@
}
if (priv->wilc_ptk[key_index]->key)
- WILC_FREE(priv->wilc_ptk[key_index]->key);
+ kfree(priv->wilc_ptk[key_index]->key);
- priv->wilc_ptk[key_index]->key = (u8 *)WILC_MALLOC(params->key_len);
+ priv->wilc_ptk[key_index]->key = WILC_MALLOC(params->key_len);
if (priv->wilc_ptk[key_index]->seq)
- WILC_FREE(priv->wilc_ptk[key_index]->seq);
+ kfree(priv->wilc_ptk[key_index]->seq);
if ((params->seq_len) > 0)
- priv->wilc_ptk[key_index]->seq = (u8 *)WILC_MALLOC(params->seq_len);
+ priv->wilc_ptk[key_index]->seq = WILC_MALLOC(params->seq_len);
if (INFO) {
for (i = 0; i < params->key_len; i++)
@@ -1297,10 +1286,10 @@
PRINT_INFO(CFG80211_DBG, "Adding group seq value[%d] = %x\n", i, params->seq[i]);
}
- WILC_memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
+ memcpy(priv->wilc_ptk[key_index]->key, params->key, params->key_len);
if ((params->seq_len) > 0)
- WILC_memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
+ memcpy(priv->wilc_ptk[key_index]->seq, params->seq, params->seq_len);
priv->wilc_ptk[key_index]->cipher = params->cipher;
priv->wilc_ptk[key_index]->key_len = params->key_len;
@@ -1315,8 +1304,7 @@
{
u8mode = 0;
- if (!pairwise)
- {
+ if (!pairwise) {
if (params->key_len > 16 && params->cipher == WLAN_CIPHER_SUITE_TKIP) {
/* swap the tx mic by rx mic */
pu8RxMic = params->key + 24;
@@ -1437,7 +1425,7 @@
/*Delete saved WEP keys params, if any*/
if (g_key_wep_params.key != NULL) {
- WILC_FREE(g_key_wep_params.key);
+ kfree(g_key_wep_params.key);
g_key_wep_params.key = NULL;
}
@@ -1448,16 +1436,16 @@
if (priv->wilc_gtk[key_index]->key != NULL) {
- WILC_FREE(priv->wilc_gtk[key_index]->key);
+ kfree(priv->wilc_gtk[key_index]->key);
priv->wilc_gtk[key_index]->key = NULL;
}
if (priv->wilc_gtk[key_index]->seq) {
- WILC_FREE(priv->wilc_gtk[key_index]->seq);
+ kfree(priv->wilc_gtk[key_index]->seq);
priv->wilc_gtk[key_index]->seq = NULL;
}
- WILC_FREE(priv->wilc_gtk[key_index]);
+ kfree(priv->wilc_gtk[key_index]);
priv->wilc_gtk[key_index] = NULL;
}
@@ -1466,35 +1454,35 @@
if (priv->wilc_ptk[key_index]->key) {
- WILC_FREE(priv->wilc_ptk[key_index]->key);
+ kfree(priv->wilc_ptk[key_index]->key);
priv->wilc_ptk[key_index]->key = NULL;
}
if (priv->wilc_ptk[key_index]->seq) {
- WILC_FREE(priv->wilc_ptk[key_index]->seq);
+ kfree(priv->wilc_ptk[key_index]->seq);
priv->wilc_ptk[key_index]->seq = NULL;
}
- WILC_FREE(priv->wilc_ptk[key_index]);
+ kfree(priv->wilc_ptk[key_index]);
priv->wilc_ptk[key_index] = NULL;
}
#endif
/*Delete saved PTK and GTK keys params, if any*/
if (g_key_ptk_params.key != NULL) {
- WILC_FREE(g_key_ptk_params.key);
+ kfree(g_key_ptk_params.key);
g_key_ptk_params.key = NULL;
}
if (g_key_ptk_params.seq != NULL) {
- WILC_FREE(g_key_ptk_params.seq);
+ kfree(g_key_ptk_params.seq);
g_key_ptk_params.seq = NULL;
}
if (g_key_gtk_params.key != NULL) {
- WILC_FREE(g_key_gtk_params.key);
+ kfree(g_key_gtk_params.key);
g_key_gtk_params.key = NULL;
}
if (g_key_gtk_params.seq != NULL) {
- WILC_FREE(g_key_gtk_params.seq);
+ kfree(g_key_gtk_params.seq);
g_key_gtk_params.seq = NULL;
}
@@ -1503,7 +1491,7 @@
}
if (key_index >= 0 && key_index <= 3) {
- WILC_memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]);
+ memset(priv->WILC_WFI_wep_key[key_index], 0, priv->WILC_WFI_wep_key_len[key_index]);
priv->WILC_WFI_wep_key_len[key_index] = 0;
PRINT_D(CFG80211_DBG, "Removing WEP key with index = %d\n", key_index);
@@ -1588,7 +1576,7 @@
priv = wiphy_priv(wiphy);
- PRINT_D(CFG80211_DBG, "Setting default key with idx = %d \n", key_index);
+ PRINT_D(CFG80211_DBG, "Setting default key with idx = %d\n", key_index);
if (key_index != priv->WILC_WFI_wep_default) {
@@ -1633,7 +1621,6 @@
* @version 1.0
*/
-extern uint32_t Statisitcs_totalAcks, Statisitcs_DroppedAcks;
static int WILC_WFI_get_station(struct wiphy *wiphy, struct net_device *dev,
const u8 *mac, struct station_info *sinfo)
{
@@ -1689,7 +1676,7 @@
* kernel version 3.0.0
*/
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL) |
- BIT( NL80211_STA_INFO_RX_PACKETS) |
+ BIT(NL80211_STA_INFO_RX_PACKETS) |
BIT(NL80211_STA_INFO_TX_PACKETS) |
BIT(NL80211_STA_INFO_TX_FAILED) |
BIT(NL80211_STA_INFO_TX_BITRATE);
@@ -1701,11 +1688,10 @@
sinfo->txrate.legacy = strStatistics.u8LinkSpeed * 10;
#ifdef TCP_ENHANCEMENTS
- if ((strStatistics.u8LinkSpeed > TCP_ACK_FILTER_LINK_SPEED_THRESH) && (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)) {
+ if ((strStatistics.u8LinkSpeed > TCP_ACK_FILTER_LINK_SPEED_THRESH) && (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED))
Enable_TCP_ACK_Filter(true);
- } else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED) {
+ else if (strStatistics.u8LinkSpeed != DEFAULT_LINK_SPEED)
Enable_TCP_ACK_Filter(false);
- }
#endif
PRINT_D(CORECONFIG_DBG, "*** stats[%d][%d][%d][%d][%d]\n", sinfo->signal, sinfo->rx_packets, sinfo->tx_packets,
@@ -1826,7 +1812,7 @@
priv = wiphy_priv(wiphy);
pstrCfgParamVal.u32SetCfgFlag = 0;
- PRINT_D(CFG80211_DBG, "Setting Wiphy params \n");
+ PRINT_D(CFG80211_DBG, "Setting Wiphy params\n");
if (changed & WIPHY_PARAM_RETRY_SHORT) {
PRINT_D(CFG80211_DBG, "Setting WIPHY_PARAM_RETRY_SHORT %d\n",
@@ -1909,7 +1895,7 @@
for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
- if (!WILC_memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
+ if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
ETH_ALEN)) {
/*If bssid already exists and pmkid value needs to reset*/
flag = PMKID_FOUND;
@@ -1919,9 +1905,9 @@
}
if (i < WILC_MAX_NUM_PMKIDS) {
PRINT_D(CFG80211_DBG, "Setting PMKID in private structure\n");
- WILC_memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
+ memcpy(priv->pmkid_list.pmkidlist[i].bssid, pmksa->bssid,
ETH_ALEN);
- WILC_memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
+ memcpy(priv->pmkid_list.pmkidlist[i].pmkid, pmksa->pmkid,
PMKID_LEN);
if (!(flag == PMKID_FOUND))
priv->pmkid_list.numpmkid++;
@@ -1959,11 +1945,11 @@
PRINT_D(CFG80211_DBG, "Deleting PMKSA keys\n");
for (i = 0; i < priv->pmkid_list.numpmkid; i++) {
- if (!WILC_memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
+ if (!memcmp(pmksa->bssid, priv->pmkid_list.pmkidlist[i].bssid,
ETH_ALEN)) {
/*If bssid is found, reset the values*/
PRINT_D(CFG80211_DBG, "Reseting PMKID values\n");
- WILC_memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(tstrHostIFpmkid));
+ memset(&priv->pmkid_list.pmkidlist[i], 0, sizeof(tstrHostIFpmkid));
flag = PMKID_FOUND;
break;
}
@@ -1971,10 +1957,10 @@
if (i < priv->pmkid_list.numpmkid && priv->pmkid_list.numpmkid > 0) {
for (; i < (priv->pmkid_list.numpmkid - 1); i++) {
- WILC_memcpy(priv->pmkid_list.pmkidlist[i].bssid,
+ memcpy(priv->pmkid_list.pmkidlist[i].bssid,
priv->pmkid_list.pmkidlist[i + 1].bssid,
ETH_ALEN);
- WILC_memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
+ memcpy(priv->pmkid_list.pmkidlist[i].pmkid,
priv->pmkid_list.pmkidlist[i].pmkid,
PMKID_LEN);
}
@@ -2002,7 +1988,7 @@
PRINT_D(CFG80211_DBG, "Flushing PMKID key values\n");
/*Get cashed Pmkids and set all with zeros*/
- WILC_memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr));
+ memset(&priv->pmkid_list, 0, sizeof(tstrHostIFpmkidAttr));
return 0;
}
@@ -2074,11 +2060,10 @@
}
#endif /* USE_SUPPLICANT_GO_INTENT */
- if (buf[index] == CHANLIST_ATTR_ID) {
+ if (buf[index] == CHANLIST_ATTR_ID)
channel_list_attr_index = index;
- } else if (buf[index] == OPERCHAN_ATTR_ID) {
+ else if (buf[index] == OPERCHAN_ATTR_ID)
op_channel_attr_index = index;
- }
index += buf[index + 1] + 3; /* ID,Length byte */
}
@@ -2160,11 +2145,10 @@
}
#endif
- if (buf[index] == CHANLIST_ATTR_ID) {
+ if (buf[index] == CHANLIST_ATTR_ID)
channel_list_attr_index = index;
- } else if (buf[index] == OPERCHAN_ATTR_ID) {
+ else if (buf[index] == OPERCHAN_ATTR_ID)
op_channel_attr_index = index;
- }
index += buf[index + 1] + 3; /* ID,Length byte */
}
@@ -2218,7 +2202,7 @@
pstrWFIDrv = (tstrWILC_WFIDrv *)priv->hWILCWFIDrv;
/* Get WILC header */
- WILC_memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
+ memcpy(&header, (buff - HOST_HDR_OFFSET), HOST_HDR_OFFSET);
/* The packet offset field conain info about what type of managment frame */
/* we are dealing with and ack status */
@@ -2270,11 +2254,11 @@
case PUBLIC_ACT_VENDORSPEC:
/*Now we have a public action vendor specific action frame, check if its a p2p public action frame
* based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/
- if (!WILC_memcmp(u8P2P_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
+ if (!memcmp(u8P2P_oui, &buff[ACTION_SUBTYPE_ID + 1], 4)) {
if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
if (!bWilc_ie) {
for (i = P2P_PUB_ACTION_SUBTYPE; i < size; i++) {
- if (!WILC_memcmp(u8P2P_vendorspec, &buff[i], 6)) {
+ if (!memcmp(u8P2P_vendorspec, &buff[i], 6)) {
u8P2Precvrandom = buff[i + 6];
bWilc_ie = true;
PRINT_D(GENERIC_DBG, "WILC Vendor specific IE:%02x\n", u8P2Precvrandom);
@@ -2287,7 +2271,7 @@
if ((buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP
|| buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buff[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)) {
for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < size; i++) {
- if (buff[i] == P2PELEM_ATTR_ID && !(WILC_memcmp(u8P2P_oui, &buff[i + 2], 4))) {
+ if (buff[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buff[i + 2], 4))) {
WILC_WFI_CfgParseRxAction(&buff[i + 6], size - (i + 6));
break;
}
@@ -2351,7 +2335,7 @@
struct WILC_WFI_priv *priv;
priv = (struct WILC_WFI_priv *)pUserVoid;
- PRINT_D(HOSTINF_DBG, "Remain on channel ready \n");
+ PRINT_D(HOSTINF_DBG, "Remain on channel ready\n");
priv->bInP2PlistenState = true;
@@ -2379,7 +2363,7 @@
/*BugID_5477*/
if (u32SessionID == priv->strRemainOnChanParams.u32ListenSessionID) {
- PRINT_D(GENERIC_DBG, "Remain on channel expired \n");
+ PRINT_D(GENERIC_DBG, "Remain on channel expired\n");
priv->bInP2PlistenState = false;
@@ -2485,7 +2469,7 @@
*/
void WILC_WFI_add_wilcvendorspec(u8 *buff)
{
- WILC_memcpy(buff, u8P2P_vendorspec, sizeof(u8P2P_vendorspec));
+ memcpy(buff, u8P2P_vendorspec, sizeof(u8P2P_vendorspec));
}
/**
* @brief WILC_WFI_mgmt_tx_frame
@@ -2528,17 +2512,17 @@
if (ieee80211_is_mgmt(mgmt->frame_control)) {
/*mgmt frame allocation*/
- mgmt_tx = (struct p2p_mgmt_data *)WILC_MALLOC(sizeof(struct p2p_mgmt_data));
+ mgmt_tx = WILC_MALLOC(sizeof(struct p2p_mgmt_data));
if (mgmt_tx == NULL) {
PRINT_ER("Failed to allocate memory for mgmt_tx structure\n");
return WILC_FAIL;
}
- mgmt_tx->buff = (char *)WILC_MALLOC(buf_len);
+ mgmt_tx->buff = WILC_MALLOC(buf_len);
if (mgmt_tx->buff == NULL) {
PRINT_ER("Failed to allocate memory for mgmt_tx buff\n");
return WILC_FAIL;
}
- WILC_memcpy(mgmt_tx->buff, buf, len);
+ memcpy(mgmt_tx->buff, buf, len);
mgmt_tx->size = len;
@@ -2583,7 +2567,7 @@
{
/*Now we have a public action vendor specific action frame, check if its a p2p public action frame
* based on the standard its should have the p2p_oui attribute with the following values 50 6f 9A 09*/
- if (!WILC_memcmp(u8P2P_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
+ if (!memcmp(u8P2P_oui, &buf[ACTION_SUBTYPE_ID + 1], 4)) {
/*For the connection of two WILC's connection generate a rand number to determine who will be a GO*/
if ((buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == GO_NEG_RSP)) {
if (u8P2Plocalrandom == 1 && u8P2Precvrandom < u8P2Plocalrandom) {
@@ -2600,7 +2584,7 @@
/*Search for the p2p information information element , after the Public action subtype theres a byte for teh dialog token, skip that*/
for (i = P2P_PUB_ACTION_SUBTYPE + 2; i < len; i++) {
- if (buf[i] == P2PELEM_ATTR_ID && !(WILC_memcmp(u8P2P_oui, &buf[i + 2], 4))) {
+ if (buf[i] == P2PELEM_ATTR_ID && !(memcmp(u8P2P_oui, &buf[i + 2], 4))) {
if (buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_REQ || buf[P2P_PUB_ACTION_SUBTYPE] == P2P_INV_RSP)
WILC_WFI_CfgParseTxAction(&mgmt_tx->buff[i + 6], len - (i + 6), true, nic->iftype);
@@ -2862,7 +2846,7 @@
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
g_obtainingIP = false;
- WILC_TimerStop(&hDuringIpTimer, NULL);
+ del_timer(&hDuringIpTimer);
PRINT_D(GENERIC_DBG, "Changing virtual interface, enable scan\n");
#endif
/*BugID_5137*/
@@ -2886,7 +2870,6 @@
/*Remove the enteries of the previously connected clients*/
memset(priv->assoc_stainfo.au8Sta_AssociatedBss, 0, MAX_NUM_STA * ETH_ALEN);
- #ifndef SIMULATION
#ifdef WILC_P2P
interface_type = nic->iftype;
nic->iftype = STATION_MODE;
@@ -2907,15 +2890,15 @@
/*Setting interface 1 drv handler and mac address in newly downloaded FW*/
host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
- host_int_set_MacAddress((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
/*Add saved WEP keys, if any*/
if (g_wep_keys_saved) {
- host_int_set_WEPDefaultKeyID((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
g_key_wep_params.key_idx);
- host_int_add_wep_key_bss_sta((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
g_key_wep_params.key,
g_key_wep_params.key_len,
g_key_wep_params.key_idx);
@@ -2964,7 +2947,6 @@
host_int_set_power_mgmt(priv->hWILCWFIDrv, 1, 0);
}
#endif
- #endif
break;
case NL80211_IFTYPE_P2P_CLIENT:
@@ -2979,7 +2961,6 @@
priv->wdev->iftype = type;
nic->monitor_flag = 0;
- #ifndef SIMULATION
#ifdef WILC_P2P
PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
@@ -2995,15 +2976,15 @@
g_wilc_initialized = 1;
host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
- host_int_set_MacAddress((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
host_int_set_operation_mode(priv->hWILCWFIDrv, STATION_MODE);
/*Add saved WEP keys, if any*/
if (g_wep_keys_saved) {
- host_int_set_WEPDefaultKeyID((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
g_key_wep_params.key_idx);
- host_int_add_wep_key_bss_sta((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
g_key_wep_params.key,
g_key_wep_params.key_len,
g_key_wep_params.key_idx);
@@ -3053,7 +3034,6 @@
}
}
#endif
- #endif
break;
case NL80211_IFTYPE_AP:
@@ -3064,7 +3044,6 @@
nic->iftype = AP_MODE;
PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
- #ifndef SIMULATION
PRINT_D(HOSTAPD_DBG, "Downloading AP firmware\n");
linux_wlan_get_firmware(nic);
#ifdef WILC_P2P
@@ -3086,7 +3065,6 @@
}
}
#endif
- #endif
break;
case NL80211_IFTYPE_P2P_GO:
@@ -3094,7 +3072,7 @@
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
g_obtainingIP = true;
- WILC_TimerStart(&hDuringIpTimer, duringIP_TIME, NULL, NULL);
+ mod_timer(&hDuringIpTimer, jiffies + msecs_to_jiffies(duringIP_TIME));
#endif
host_int_set_power_mgmt(priv->hWILCWFIDrv, 0, 0);
/*BugID_5222*/
@@ -3110,7 +3088,6 @@
PRINT_D(CORECONFIG_DBG, "priv->hWILCWFIDrv[%p]\n", priv->hWILCWFIDrv);
- #ifndef SIMULATION
#ifdef WILC_P2P
PRINT_D(HOSTAPD_DBG, "Downloading P2P_CONCURRENCY_FIRMWARE\n");
@@ -3127,15 +3104,15 @@
/*Setting interface 1 drv handler and mac address in newly downloaded FW*/
host_int_set_wfi_drv_handler(g_linux_wlan->strInterfaceInfo[0].drvHandler);
- host_int_set_MacAddress((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ host_int_set_MacAddress(g_linux_wlan->strInterfaceInfo[0].drvHandler,
g_linux_wlan->strInterfaceInfo[0].aSrcAddress);
host_int_set_operation_mode(priv->hWILCWFIDrv, AP_MODE);
/*Add saved WEP keys, if any*/
if (g_wep_keys_saved) {
- host_int_set_WEPDefaultKeyID((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ host_int_set_WEPDefaultKeyID(g_linux_wlan->strInterfaceInfo[0].drvHandler,
g_key_wep_params.key_idx);
- host_int_add_wep_key_bss_sta((WILC_WFIDrvHandle)(g_linux_wlan->strInterfaceInfo[0].drvHandler),
+ host_int_add_wep_key_bss_sta(g_linux_wlan->strInterfaceInfo[0].drvHandler,
g_key_wep_params.key,
g_key_wep_params.key_len,
g_key_wep_params.key_idx);
@@ -3185,7 +3162,6 @@
}
}
#endif
- #endif
break;
default:
@@ -3234,7 +3210,7 @@
priv = wiphy_priv(wiphy);
PRINT_D(HOSTAPD_DBG, "Starting ap\n");
- PRINT_D(HOSTAPD_DBG, "Interval = %d \n DTIM period = %d\n Head length = %zu Tail length = %zu\n",
+ PRINT_D(HOSTAPD_DBG, "Interval = %d\n DTIM period = %d\n Head length = %zu Tail length = %zu\n",
settings->beacon_interval, settings->dtim_period, beacon->head_len, beacon->tail_len);
s32Error = WILC_WFI_CfgSetChannel(wiphy, &settings->chandef);
@@ -3353,7 +3329,7 @@
{
s32 s32Error = WILC_SUCCESS;
struct WILC_WFI_priv *priv;
- tstrWILC_AddStaParam strStaParams = {{0}};
+ tstrWILC_AddStaParam strStaParams = { {0} };
perInterface_wlan_t *nic;
@@ -3365,8 +3341,8 @@
if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
#ifndef WILC_FULLY_HOSTING_AP
- WILC_memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
- WILC_memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
+ memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
+ memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
strStaParams.u16AssocID = params->aid;
strStaParams.u8NumRates = params->supported_rates_len;
strStaParams.pu8Rates = params->supported_rates;
@@ -3384,7 +3360,7 @@
strStaParams.bIsHTSupported = true;
strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
- WILC_memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
+ memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info;
strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info;
strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info;
@@ -3407,7 +3383,7 @@
#else
PRINT_D(CFG80211_DBG, "Adding station parameters %d\n", params->aid);
- WILC_memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
+ memcpy(priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid], mac, ETH_ALEN);
PRINT_D(CFG80211_DBG, "BSSID = %x%x%x%x%x%x\n", priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][0], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][1], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][2], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][3], priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][4],
priv->assoc_stainfo.au8Sta_AssociatedBss[params->aid][5]);
@@ -3450,7 +3426,7 @@
if (mac == NULL) {
- PRINT_D(HOSTAPD_DBG, "All associated stations \n");
+ PRINT_D(HOSTAPD_DBG, "All associated stations\n");
s32Error = host_int_del_allstation(priv->hWILCWFIDrv, priv->assoc_stainfo.au8Sta_AssociatedBss);
} else {
PRINT_D(HOSTAPD_DBG, "With mac address: %x%x%x%x%x%x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
@@ -3484,7 +3460,7 @@
{
s32 s32Error = WILC_SUCCESS;
struct WILC_WFI_priv *priv;
- tstrWILC_AddStaParam strStaParams = {{0}};
+ tstrWILC_AddStaParam strStaParams = { {0} };
perInterface_wlan_t *nic;
@@ -3498,7 +3474,7 @@
if (nic->iftype == AP_MODE || nic->iftype == GO_MODE) {
#ifndef WILC_FULLY_HOSTING_AP
- WILC_memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
+ memcpy(strStaParams.au8BSSID, mac, ETH_ALEN);
strStaParams.u16AssocID = params->aid;
strStaParams.u8NumRates = params->supported_rates_len;
strStaParams.pu8Rates = params->supported_rates;
@@ -3514,7 +3490,7 @@
strStaParams.bIsHTSupported = true;
strStaParams.u16HTCapInfo = params->ht_capa->cap_info;
strStaParams.u8AmpduParams = params->ht_capa->ampdu_params_info;
- WILC_memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
+ memcpy(strStaParams.au8SuppMCsSet, ¶ms->ht_capa->mcs, WILC_SUPP_MCS_SET_SIZE);
strStaParams.u16HTExtParams = params->ht_capa->extended_ht_cap_info;
strStaParams.u32TxBeamformingCap = params->ht_capa->tx_BF_cap_info;
strStaParams.u8ASELCap = params->ht_capa->antenna_selection_info;
@@ -3581,13 +3557,8 @@
new_ifc = WILC_WFI_init_mon_interface(name, nic->wilc_netdev);
if (new_ifc != NULL) {
PRINT_D(HOSTAPD_DBG, "Setting monitor flag in private structure\n");
- #ifdef SIMULATION
- priv = netdev_priv(priv->wdev->netdev);
- priv->monitor_flag = 1;
- #else
nic = netdev_priv(priv->wdev->netdev);
nic->monitor_flag = 1;
- #endif
} else
PRINT_ER("Error in initializing monitor interface\n ");
}
@@ -3856,9 +3827,9 @@
PRINT_D(INIT_DBG, "Host[%p][%p]\n", net, net->ieee80211_ptr);
priv = wdev_priv(net->ieee80211_ptr);
if (op_ifcs == 0) {
- s32Error = WILC_TimerCreate(&(hAgingTimer), remove_network_from_shadow, NULL);
+ setup_timer(&hAgingTimer, remove_network_from_shadow, 0);
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
- s32Error = WILC_TimerCreate(&(hDuringIpTimer), clear_duringIP, NULL);
+ setup_timer(&hDuringIpTimer, clear_duringIP, 0);
#endif
}
op_ifcs++;
@@ -3908,7 +3879,7 @@
#ifdef DISABLE_PWRSAVE_AND_SCAN_DURING_IP
if (op_ifcs == 0) {
PRINT_D(CORECONFIG_DBG, "destroy during ip\n");
- WILC_TimerDestroy(&hDuringIpTimer, NULL);
+ del_timer_sync(&hDuringIpTimer);
}
#endif
diff --git a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
index c25350c..97b663b 100644
--- a/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
+++ b/drivers/staging/wilc1000/wilc_wfi_cfgoperations.h
@@ -123,7 +123,7 @@
#ifdef TCP_ENHANCEMENTS
#define TCP_ACK_FILTER_LINK_SPEED_THRESH 54
#define DEFAULT_LINK_SPEED 72
-extern void Enable_TCP_ACK_Filter(bool value);
+void Enable_TCP_ACK_Filter(bool value);
#endif
#endif
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.c b/drivers/staging/wilc1000/wilc_wfi_netdevice.c
deleted file mode 100644
index ab66ce4b..0000000
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.c
+++ /dev/null
@@ -1,951 +0,0 @@
-/*!
- * @file wilc_wfi_netdevice.c
- * @brief File Operations OS wrapper functionality
- * @author mdaftedar
- * @sa wilc_wfi_netdevice.h
- * @date 01 MAR 2012
- * @version 1.0
- */
-
-#ifdef SIMULATION
-
-#include "wilc_wfi_cfgoperations.h"
-#include "host_interface.h"
-
-
-MODULE_AUTHOR("Mai Daftedar");
-MODULE_LICENSE("Dual BSD/GPL");
-
-
-struct net_device *WILC_WFI_devs[2];
-
-/*
- * Transmitter lockup simulation, normally disabled.
- */
-static int lockup;
-module_param(lockup, int, 0);
-
-static int timeout = WILC_WFI_TIMEOUT;
-module_param(timeout, int, 0);
-
-/*
- * Do we run in NAPI mode?
- */
-static int use_napi ;
-module_param(use_napi, int, 0);
-
-
-/*
- * A structure representing an in-flight packet.
- */
-struct WILC_WFI_packet {
- struct WILC_WFI_packet *next;
- struct net_device *dev;
- int datalen;
- u8 data[ETH_DATA_LEN];
-};
-
-
-
-int pool_size = 8;
-module_param(pool_size, int, 0);
-
-
-static void WILC_WFI_TxTimeout(struct net_device *dev);
-static void (*WILC_WFI_Interrupt)(int, void *, struct pt_regs *);
-
-/**
- * @brief WILC_WFI_SetupPool
- * @details Set up a device's packet pool.
- * @param[in] struct net_device *dev : Network Device Pointer
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-void WILC_WFI_SetupPool(struct net_device *dev)
-{
- struct WILC_WFI_priv *priv = netdev_priv(dev);
- int i;
- struct WILC_WFI_packet *pkt;
-
- priv->ppool = NULL;
- for (i = 0; i < pool_size; i++) {
- pkt = kmalloc (sizeof (struct WILC_WFI_packet), GFP_KERNEL);
- if (pkt == NULL) {
- PRINT_D(RX_DBG, "Ran out of memory allocating packet pool\n");
- return;
- }
- pkt->dev = dev;
- pkt->next = priv->ppool;
- priv->ppool = pkt;
- }
-}
-
-/**
- * @brief WILC_WFI_TearDownPool
- * @details Internal cleanup function that's called after the network device
- * driver is unregistered
- * @param[in] struct net_device *dev : Network Device Driver
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-void WILC_WFI_TearDownPool(struct net_device *dev)
-{
- struct WILC_WFI_priv *priv = netdev_priv(dev);
- struct WILC_WFI_packet *pkt;
-
- while ((pkt = priv->ppool)) {
- priv->ppool = pkt->next;
- kfree (pkt);
- /* FIXME - in-flight packets ? */
- }
-}
-
-/**
- * @brief WILC_WFI_GetTxBuffer
- * @details Buffer/pool management
- * @param[in] net_device *dev : Network Device Driver Structure
- * @return struct WILC_WFI_packet
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-struct WILC_WFI_packet *WILC_WFI_GetTxBuffer(struct net_device *dev)
-{
- struct WILC_WFI_priv *priv = netdev_priv(dev);
- unsigned long flags;
- struct WILC_WFI_packet *pkt;
-
- spin_lock_irqsave(&priv->lock, flags);
- pkt = priv->ppool;
- priv->ppool = pkt->next;
- if (priv->ppool == NULL) {
- PRINT_INFO(RX_DBG, "Pool empty\n");
- netif_stop_queue(dev);
- }
- spin_unlock_irqrestore(&priv->lock, flags);
- return pkt;
-}
-/**
- * @brief WILC_WFI_ReleaseBuffer
- * @details Buffer/pool management
- * @param[in] WILC_WFI_packet *pkt : Structure holding in-flight packet
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-void WILC_WFI_ReleaseBuffer(struct WILC_WFI_packet *pkt)
-{
- unsigned long flags;
- struct WILC_WFI_priv *priv = netdev_priv(pkt->dev);
-
- spin_lock_irqsave(&priv->lock, flags);
- pkt->next = priv->ppool;
- priv->ppool = pkt;
- spin_unlock_irqrestore(&priv->lock, flags);
- if (netif_queue_stopped(pkt->dev) && pkt->next == NULL)
- netif_wake_queue(pkt->dev);
-}
-
-/**
- * @brief WILC_WFI_EnqueueBuf
- * @details Enqueuing packets in an RX buffer queue
- * @param[in] WILC_WFI_packet *pkt : Structure holding in-flight packet
- * @param[in] net_device *dev : Network Device Driver Structure
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-void WILC_WFI_EnqueueBuf(struct net_device *dev, struct WILC_WFI_packet *pkt)
-{
- unsigned long flags;
- struct WILC_WFI_priv *priv = netdev_priv(dev);
-
- spin_lock_irqsave(&priv->lock, flags);
- pkt->next = priv->rx_queue; /* FIXME - misorders packets */
- priv->rx_queue = pkt;
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-/**
- * @brief WILC_WFI_DequeueBuf
- * @details Dequeuing packets from the RX buffer queue
- * @param[in] net_device *dev : Network Device Driver Structure
- * @return WILC_WFI_packet *pkt : Structure holding in-flight pac
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-struct WILC_WFI_packet *WILC_WFI_DequeueBuf(struct net_device *dev)
-{
- struct WILC_WFI_priv *priv = netdev_priv(dev);
- struct WILC_WFI_packet *pkt;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- pkt = priv->rx_queue;
- if (pkt != NULL)
- priv->rx_queue = pkt->next;
- spin_unlock_irqrestore(&priv->lock, flags);
- return pkt;
-}
-/**
- * @brief WILC_WFI_RxInts
- * @details Enable and disable receive interrupts.
- * @param[in] net_device *dev : Network Device Driver Structure
- * @param[in] enable : Enable/Disable flag
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-static void WILC_WFI_RxInts(struct net_device *dev, int enable)
-{
- struct WILC_WFI_priv *priv = netdev_priv(dev);
- priv->rx_int_enabled = enable;
-}
-
-/**
- * @brief WILC_WFI_Open
- * @details Open Network Device Driver, called when the network
- * interface is opened. It starts the interface's transmit queue.
- * @param[in] net_device *dev : Network Device Driver Structure
- * @param[in] enable : Enable/Disable flag
- * @return int : Returns 0 upon success.
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-int WILC_WFI_Open(struct net_device *dev)
-{
- /* request_region(), request_irq(), .... (like fops->open) */
- /*
- * Assign the hardware address of the board: use "\0SNULx", where
- * x is 0 or 1. The first byte is '\0' to avoid being a multicast
- * address (the first byte of multicast addrs is odd).
- */
- memcpy(dev->dev_addr, "\0WLAN0", ETH_ALEN);
- if (dev == WILC_WFI_devs[1])
- dev->dev_addr[ETH_ALEN - 1]++; /* \0SNUL1 */
-
- WILC_WFI_InitHostInt(dev);
- netif_start_queue(dev);
- return 0;
-}
-/**
- * @brief WILC_WFI_Release
- * @details Release Network Device Driver, called when the network
- * interface is stopped or brought down. This function marks
- * the network driver as not being able to transmit
- * @param[in] net_device *dev : Network Device Driver Structure
- * @return int : Return 0 on Success.
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-int WILC_WFI_Release(struct net_device *dev)
-{
- /* release ports, irq and such -- like fops->close */
-
- netif_stop_queue(dev); /* can't transmit any more */
-
- return 0;
-}
-/**
- * @brief WILC_WFI_Config
- * @details Configuration changes (passed on by ifconfig)
- * @param[in] net_device *dev : Network Device Driver Structure
- * @param[in] struct ifmap *map : Contains the ioctl implementation for the
- * network driver.
- * @return int : Return 0 on Success.
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-int WILC_WFI_Config(struct net_device *dev, struct ifmap *map)
-{
- if (dev->flags & IFF_UP) /* can't act on a running interface */
- return -EBUSY;
-
- /* Don't allow changing the I/O address */
- if (map->base_addr != dev->base_addr) {
- PRINT_D(RX_DBG, KERN_WARNING "WILC_WFI: Can't change I/O address\n");
- return -EOPNOTSUPP;
- }
-
- /* Allow changing the IRQ */
- if (map->irq != dev->irq) {
- dev->irq = map->irq;
- /* request_irq() is delayed to open-time */
- }
-
- /* ignore other fields */
- return 0;
-}
-/**
- * @brief WILC_WFI_Rx
- * @details Receive a packet: retrieve, encapsulate and pass over to upper
- * levels
- * @param[in] net_device *dev : Network Device Driver Structure
- * @param[in] WILC_WFI_packet :
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-void WILC_WFI_Rx(struct net_device *dev, struct WILC_WFI_packet *pkt)
-{
- int i;
- struct sk_buff *skb;
- struct WILC_WFI_priv *priv = netdev_priv(dev);
- s8 rssi;
- /*
- * The packet has been retrieved from the transmission
- * medium. Build an skb around it, so upper layers can handle it
- */
-
-
- skb = dev_alloc_skb(pkt->datalen + 2);
- if (!skb) {
- if (printk_ratelimit())
- PRINT_D(RX_DBG, "WILC_WFI rx: low on mem - packet dropped\n");
- priv->stats.rx_dropped++;
- goto out;
- }
- skb_reserve(skb, 2); /* align IP on 16B boundary */
- memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
-
- if (priv->monitor_flag) {
- PRINT_INFO(RX_DBG, "In monitor device name %s\n", dev->name);
- priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy);
- PRINT_D(RX_DBG, "VALUE PASSED IN OF HRWD %p\n", priv->hWILCWFIDrv);
- /* host_int_get_rssi(priv->hWILCWFIDrv, &(rssi)); */
- if (INFO) {
- for (i = 14; i < skb->len; i++)
- PRINT_INFO(RX_DBG, "RXdata[%d] %02x\n", i, skb->data[i]);
- }
- WILC_WFI_monitor_rx(dev, skb);
- return;
- }
-out:
- return;
-}
-
-/**
- * @brief WILC_WFI_Poll
- * @details The poll implementation
- * @param[in] struct napi_struct *napi :
- * @param[in] int budget :
- * @return int : Return 0 on Success.
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-static int WILC_WFI_Poll(struct napi_struct *napi, int budget)
-{
- int npackets = 0;
- struct sk_buff *skb;
- struct WILC_WFI_priv *priv = container_of(napi, struct WILC_WFI_priv, napi);
- struct net_device *dev = priv->dev;
- struct WILC_WFI_packet *pkt;
-
- while (npackets < budget && priv->rx_queue) {
- pkt = WILC_WFI_DequeueBuf(dev);
- skb = dev_alloc_skb(pkt->datalen + 2);
- if (!skb) {
- if (printk_ratelimit())
- PRINT_D(RX_DBG, "WILC_WFI: packet dropped\n");
- priv->stats.rx_dropped++;
- WILC_WFI_ReleaseBuffer(pkt);
- continue;
- }
- skb_reserve(skb, 2); /* align IP on 16B boundary */
- memcpy(skb_put(skb, pkt->datalen), pkt->data, pkt->datalen);
- skb->dev = dev;
- skb->protocol = eth_type_trans(skb, dev);
- skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it */
- netif_receive_skb(skb);
- /* Maintain stats */
- npackets++;
- WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, pkt->datalen, WILC_WFI_RX_PKT);
- WILC_WFI_ReleaseBuffer(pkt);
- }
- /* If we processed all packets, we're done; tell the kernel and re-enable ints */
- if (npackets < budget) {
- napi_complete(napi);
- WILC_WFI_RxInts(dev, 1);
- }
- return npackets;
-}
-
-/**
- * @brief WILC_WFI_Poll
- * @details The typical interrupt entry point
- * @param[in] struct napi_struct *napi :
- * @param[in] int budget :
- * @return int : Return 0 on Success.
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-static void WILC_WFI_RegularInterrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- int statusword;
- struct WILC_WFI_priv *priv;
- struct WILC_WFI_packet *pkt = NULL;
- /*
- * As usual, check the "device" pointer to be sure it is
- * really interrupting.
- * Then assign "struct device *dev"
- */
- struct net_device *dev = (struct net_device *)dev_id;
- /* ... and check with hw if it's really ours */
-
- /* paranoid */
- if (!dev)
- return;
-
- /* Lock the device */
- priv = netdev_priv(dev);
- spin_lock(&priv->lock);
-
- /* retrieve statusword: real netdevices use I/O instructions */
- statusword = priv->status;
- priv->status = 0;
- if (statusword & WILC_WFI_RX_INTR) {
- /* send it to WILC_WFI_rx for handling */
- pkt = priv->rx_queue;
- if (pkt) {
- priv->rx_queue = pkt->next;
- WILC_WFI_Rx(dev, pkt);
- }
- }
- if (statusword & WILC_WFI_TX_INTR) {
- /* a transmission is over: free the skb */
- WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT);
- dev_kfree_skb(priv->skb);
- }
-
- /* Unlock the device and we are done */
- spin_unlock(&priv->lock);
- if (pkt)
- WILC_WFI_ReleaseBuffer(pkt); /* Do this outside the lock! */
- return;
-}
-/**
- * @brief WILC_WFI_NapiInterrupt
- * @details A NAPI interrupt handler
- * @param[in] irq:
- * @param[in] dev_id:
- * @param[in] pt_regs:
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-static void WILC_WFI_NapiInterrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- int statusword;
- struct WILC_WFI_priv *priv;
-
- /*
- * As usual, check the "device" pointer for shared handlers.
- * Then assign "struct device *dev"
- */
- struct net_device *dev = (struct net_device *)dev_id;
- /* ... and check with hw if it's really ours */
-
- /* paranoid */
- if (!dev)
- return;
-
- /* Lock the device */
- priv = netdev_priv(dev);
- spin_lock(&priv->lock);
-
- /* retrieve statusword: real netdevices use I/O instructions */
- statusword = priv->status;
- priv->status = 0;
- if (statusword & WILC_WFI_RX_INTR) {
- WILC_WFI_RxInts(dev, 0); /* Disable further interrupts */
- napi_schedule(&priv->napi);
- }
- if (statusword & WILC_WFI_TX_INTR) {
- /* a transmission is over: free the skb */
-
- WILC_WFI_update_stats(priv->dev->ieee80211_ptr->wiphy, priv->tx_packetlen, WILC_WFI_TX_PKT);
- dev_kfree_skb(priv->skb);
- }
-
- /* Unlock the device and we are done */
- spin_unlock(&priv->lock);
- return;
-}
-
-/**
- * @brief MI_WFI_HwTx
- * @details Transmit a packet (low level interface)
- * @param[in] buf:
- * @param[in] len:
- * @param[in] net_device *dev:
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-void WILC_WFI_HwTx(char *buf, int len, struct net_device *dev)
-{
- /*
- * This function deals with hw details. This interface loops
- * back the packet to the other WILC_WFI interface (if any).
- * In other words, this function implements the WILC_WFI behaviour,
- * while all other procedures are rather device-independent
- */
- struct iphdr *ih;
- struct net_device *dest;
- struct WILC_WFI_priv *priv;
- u32 *saddr, *daddr;
- struct WILC_WFI_packet *tx_buffer;
-
-
- /* I am paranoid. Ain't I? */
- if (len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {
- PRINT_D(RX_DBG, "WILC_WFI: Hmm... packet too short (%i octets)\n",
- len);
- return;
- }
-
- if (0) { /* enable this conditional to look at the data */
- int i;
- PRINT_D(RX_DBG, "len is %i", len);
- for (i = 14; i < len; i++)
- PRINT_D(RX_DBG, "TXdata[%d] %02x\n", i, buf[i] & 0xff);
- /* PRINT_D(RX_DBG, "\n"); */
- }
- /*
- * Ethhdr is 14 bytes, but the kernel arranges for iphdr
- * to be aligned (i.e., ethhdr is unaligned)
- */
- ih = (struct iphdr *)(buf + sizeof(struct ethhdr));
- saddr = &ih->saddr;
- daddr = &ih->daddr;
-
- ((u8 *)saddr)[2] ^= 1; /* change the third octet (class C) */
- ((u8 *)daddr)[2] ^= 1;
-
- ih->check = 0; /* and rebuild the checksum (ip needs it) */
- ih->check = ip_fast_csum((unsigned char *)ih, ih->ihl);
-
-
- if (dev == WILC_WFI_devs[0])
- PRINT_D(RX_DBG, "%08x:%05i --> %08x:%05i\n",
- ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source),
- ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest));
- else
- PRINT_D(RX_DBG, "%08x:%05i <-- %08x:%05i\n",
- ntohl(ih->daddr), ntohs(((struct tcphdr *)(ih + 1))->dest),
- ntohl(ih->saddr), ntohs(((struct tcphdr *)(ih + 1))->source));
-
- /*
- * Ok, now the packet is ready for transmission: first simulate a
- * receive interrupt on the twin device, then a
- * transmission-done on the transmitting device
- */
- dest = WILC_WFI_devs[dev == WILC_WFI_devs[0] ? 1 : 0];
- priv = netdev_priv(dest);
-
- tx_buffer = WILC_WFI_GetTxBuffer(dev);
- tx_buffer->datalen = len;
- memcpy(tx_buffer->data, buf, len);
- WILC_WFI_EnqueueBuf(dest, tx_buffer);
- if (priv->rx_int_enabled) {
- priv->status |= WILC_WFI_RX_INTR;
- WILC_WFI_Interrupt(0, dest, NULL);
- }
-
- priv = netdev_priv(dev);
- priv->tx_packetlen = len;
- priv->tx_packetdata = buf;
- priv->status |= WILC_WFI_TX_INTR;
- if (lockup && ((priv->stats.tx_packets + 1) % lockup) == 0) {
- /* Simulate a dropped transmit interrupt */
- netif_stop_queue(dev);
- PRINT_D(RX_DBG, "Simulate lockup at %ld, txp %ld\n", jiffies,
- (unsigned long) priv->stats.tx_packets);
- } else
- WILC_WFI_Interrupt(0, dev, NULL);
-
-}
-
-/**
- * @brief WILC_WFI_Tx
- * @details Transmit a packet (called by the kernel)
- * @param[in] sk_buff *skb:
- * @param[in] net_device *dev:
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-int WILC_WFI_Tx(struct sk_buff *skb, struct net_device *dev)
-{
- int len;
- char *data, shortpkt[ETH_ZLEN];
- struct WILC_WFI_priv *priv = netdev_priv(dev);
-
- /* priv = wiphy_priv(priv->dev->ieee80211_ptr->wiphy); */
-
- /* if(priv->monitor_flag) */
- /* mac80211_hwsim_monitor_rx(skb); */
-
-
- data = skb->data;
- len = skb->len;
-
- if (len < ETH_ZLEN) {
- memset(shortpkt, 0, ETH_ZLEN);
- memcpy(shortpkt, skb->data, skb->len);
- len = ETH_ZLEN;
- data = shortpkt;
- }
- dev->trans_start = jiffies; /* save the timestamp */
-
- /* Remember the skb, so we can free it at interrupt time */
- priv->skb = skb;
-
- /* actual deliver of data is device-specific, and not shown here */
- WILC_WFI_HwTx(data, len, dev);
-
- return 0; /* Our simple device can not fail */
-}
-
-/**
- * @brief WILC_WFI_TxTimeout
- * @details Deal with a transmit timeout.
- * @param[in] net_device *dev:
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-void WILC_WFI_TxTimeout(struct net_device *dev)
-{
- struct WILC_WFI_priv *priv = netdev_priv(dev);
-
- PRINT_D(RX_DBG, "Transmit timeout at %ld, latency %ld\n", jiffies,
- jiffies - dev->trans_start);
- /* Simulate a transmission interrupt to get things moving */
- priv->status = WILC_WFI_TX_INTR;
- WILC_WFI_Interrupt(0, dev, NULL);
- priv->stats.tx_errors++;
- netif_wake_queue(dev);
- return;
-}
-
-/**
- * @brief WILC_WFI_Ioctl
- * @details Ioctl commands
- * @param[in] net_device *dev:
- * @param[in] ifreq *rq
- * @param[in] cmd:
- * @return int : Return 0 on Success
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-int WILC_WFI_Ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- PRINT_D(RX_DBG, "ioctl\n");
- return 0;
-}
-
-/**
- * @brief WILC_WFI_Stat
- * @details Return statistics to the caller
- * @param[in] net_device *dev:
- * @return WILC_WFI_Stats : Return net_device_stats stucture with the
- * network device driver private data contents.
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-struct net_device_stats *WILC_WFI_Stats(struct net_device *dev)
-{
- struct WILC_WFI_priv *priv = netdev_priv(dev);
- return &priv->stats;
-}
-
-/**
- * @brief WILC_WFI_RebuildHeader
- * @details This function is called to fill up an eth header, since arp is not
- * available on the interface
- * @param[in] sk_buff *skb:
- * @return int : Return 0 on Success
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-int WILC_WFI_RebuildHeader(struct sk_buff *skb)
-{
- struct ethhdr *eth = (struct ethhdr *) skb->data;
- struct net_device *dev = skb->dev;
-
- memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
- memcpy(eth->h_dest, dev->dev_addr, dev->addr_len);
- eth->h_dest[ETH_ALEN - 1] ^= 0x01; /* dest is us xor 1 */
- return 0;
-}
-/**
- * @brief WILC_WFI_RebuildHeader
- * @details This function is called to fill up an eth header, since arp is not
- * available on the interface
- * @param[in] sk_buff *skb:
- * @param[in] struct net_device *dev:
- * @param[in] unsigned short type:
- * @param[in] const void *saddr,
- * @param[in] const void *daddr:
- * @param[in] unsigned int len
- * @return int : Return 0 on Success
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-int WILC_WFI_Header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, const void *daddr, const void *saddr,
- unsigned int len)
-{
- struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN);
-
- eth->h_proto = htons(type);
- memcpy(eth->h_source, saddr ? saddr : dev->dev_addr, dev->addr_len);
- memcpy(eth->h_dest, daddr ? daddr : dev->dev_addr, dev->addr_len);
- eth->h_dest[ETH_ALEN - 1] ^= 0x01; /* dest is us xor 1 */
- return dev->hard_header_len;
-}
-
-/**
- * @brief WILC_WFI_ChangeMtu
- * @details The "change_mtu" method is usually not needed.
- * If you need it, it must be like this.
- * @param[in] net_device *dev : Network Device Driver Structure
- * @param[in] new_mtu :
- * @return int : Returns 0 on Success.
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-int WILC_WFI_ChangeMtu(struct net_device *dev, int new_mtu)
-{
- unsigned long flags;
- struct WILC_WFI_priv *priv = netdev_priv(dev);
- spinlock_t *lock = &priv->lock;
-
- /* check ranges */
- if ((new_mtu < 68) || (new_mtu > 1500))
- return -EINVAL;
- /*
- * Do anything you need, and the accept the value
- */
- spin_lock_irqsave(lock, flags);
- dev->mtu = new_mtu;
- spin_unlock_irqrestore(lock, flags);
- return 0; /* success */
-}
-
-static const struct header_ops WILC_WFI_header_ops = {
- .create = WILC_WFI_Header,
- .rebuild = WILC_WFI_RebuildHeader,
- .cache = NULL, /* disable caching */
-};
-
-
-static const struct net_device_ops WILC_WFI_netdev_ops = {
- .ndo_open = WILC_WFI_Open,
- .ndo_stop = WILC_WFI_Release,
- .ndo_set_config = WILC_WFI_Config,
- .ndo_start_xmit = WILC_WFI_Tx,
- .ndo_do_ioctl = WILC_WFI_Ioctl,
- .ndo_get_stats = WILC_WFI_Stats,
- .ndo_change_mtu = WILC_WFI_ChangeMtu,
- .ndo_tx_timeout = WILC_WFI_TxTimeout,
-};
-
-/**
- * @brief WILC_WFI_Init
- * @details The init function (sometimes called probe).
- * It is invoked by register_netdev()
- * @param[in] net_device *dev:
- * @return NONE
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-void WILC_WFI_Init(struct net_device *dev)
-{
- struct WILC_WFI_priv *priv;
-
-
- /*
- * Then, assign other fields in dev, using ether_setup() and some
- * hand assignments
- */
- ether_setup(dev); /* assign some of the fields */
- /* 1- Allocate space */
-
- dev->netdev_ops = &WILC_WFI_netdev_ops;
- dev->header_ops = &WILC_WFI_header_ops;
- dev->watchdog_timeo = timeout;
- /* keep the default flags, just add NOARP */
- dev->flags |= IFF_NOARP;
- dev->features |= NETIF_F_NO_CSUM;
- /*
- * Then, initialize the priv field. This encloses the statistics
- * and a few private fields.
- */
- priv = netdev_priv(dev);
- memset(priv, 0, sizeof(struct WILC_WFI_priv));
- priv->dev = dev;
- netif_napi_add(dev, &priv->napi, WILC_WFI_Poll, 2);
- /* The last parameter above is the NAPI "weight". */
- spin_lock_init(&priv->lock);
- WILC_WFI_RxInts(dev, 1); /* enable receive interrupts */
- WILC_WFI_SetupPool(dev);
-}
-
-/**
- * @brief WILC_WFI_Stat
- * @details Return statistics to the caller
- * @param[in] net_device *dev:
- * @return WILC_WFI_Stats : Return net_device_stats stucture with the
- * network device driver private data contents.
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-
-void WILC_WFI_Cleanup(void)
-{
- int i;
- struct WILC_WFI_priv *priv[2];
-
- /*if(hwsim_mon!=NULL)
- * {
- * PRINT_D(RX_DBG, "Freeing monitor interface\n");
- * unregister_netdev(hwsim_mon);
- * free_netdev(hwsim_mon);
- * }*/
- for (i = 0; i < 2; i++) {
- priv[i] = netdev_priv(WILC_WFI_devs[i]);
-
- if (WILC_WFI_devs[i]) {
- PRINT_D(RX_DBG, "Unregistering\n");
- unregister_netdev(WILC_WFI_devs[i]);
- WILC_WFI_TearDownPool(WILC_WFI_devs[i]);
- free_netdev(WILC_WFI_devs[i]);
- PRINT_D(RX_DBG, "[NETDEV]Stopping interface\n");
- WILC_WFI_DeInitHostInt(WILC_WFI_devs[i]);
- WILC_WFI_WiphyFree(WILC_WFI_devs[i]);
- }
-
- }
- /* unregister_netdev(hwsim_mon); */
- WILC_WFI_deinit_mon_interface();
- return;
-}
-
-
-void StartConfigSim(void);
-
-
-
-
-
-
-
-/**
- * @brief WILC_WFI_Stat
- * @details Return statistics to the caller
- * @param[in] net_device *dev:
- * @return WILC_WFI_Stats : Return net_device_stats stucture with the
- * network device driver private data contents.
- * @author mdaftedar
- * @date 01 MAR 2012
- * @version 1.0
- */
-int WILC_WFI_InitModule(void)
-{
-
- int result, i, ret = -ENOMEM;
- struct WILC_WFI_priv *priv[2], *netpriv;
- struct wireless_dev *wdev;
- WILC_WFI_Interrupt = use_napi ? WILC_WFI_NapiInterrupt : WILC_WFI_RegularInterrupt;
- char buf[IFNAMSIZ];
-
- for (i = 0; i < 2; i++) {
-
- /* Allocate the net devices */
- WILC_WFI_devs[i] = alloc_netdev(sizeof(struct WILC_WFI_priv), "wlan%d",
- WILC_WFI_Init);
- if (WILC_WFI_devs[i] == NULL)
- goto out;
- /* priv[i] = netdev_priv(WILC_WFI_devs[i]); */
-
- wdev = WILC_WFI_WiphyRegister(WILC_WFI_devs[i]);
- WILC_WFI_devs[i]->ieee80211_ptr = wdev;
- netpriv = netdev_priv(WILC_WFI_devs[i]);
- netpriv->dev->ieee80211_ptr = wdev;
- netpriv->dev->ml_priv = netpriv;
- wdev->netdev = netpriv->dev;
-
- /*Registering the net device*/
- result = register_netdev(WILC_WFI_devs[i]);
- if (result)
- PRINT_D(RX_DBG, "WILC_WFI: error %i registering device \"%s\"\n",
- result, WILC_WFI_devs[i]->name);
- else
- ret = 0;
- }
-
-
- /*init atmel driver */
- priv[0] = netdev_priv(WILC_WFI_devs[0]);
- priv[1] = netdev_priv(WILC_WFI_devs[1]);
-
- if (priv[1]->dev->ieee80211_ptr->wiphy->interface_modes && BIT(NL80211_IFTYPE_MONITOR)) {
- /* snprintf(buf, IFNAMSIZ, "mon.%s", priv[1]->dev->name); */
- /* WILC_WFI_init_mon_interface(); */
- /* priv[1]->monitor_flag = 1; */
-
- }
- priv[0]->bCfgScanning = false;
- priv[0]->u32RcvdChCount = 0;
-
- WILC_memset(priv[0]->au8AssociatedBss, 0xFF, ETH_ALEN);
-
-
- /* ret = host_int_init(&priv[0]->hWILCWFIDrv); */
- /*copy handle to the other driver*/
- /* priv[1]->hWILCWFIDrv = priv[0]->hWILCWFIDrv; */
- if (ret) {
- PRINT_ER("Error Init Driver\n");
- }
-
-
-out:
- if (ret)
- WILC_WFI_Cleanup();
- return ret;
-
-
-}
-
-
-module_init(WILC_WFI_InitModule);
-module_exit(WILC_WFI_Cleanup);
-
-#endif
diff --git a/drivers/staging/wilc1000/wilc_wfi_netdevice.h b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
index d413fa3..77f320d 100644
--- a/drivers/staging/wilc1000/wilc_wfi_netdevice.h
+++ b/drivers/staging/wilc1000/wilc_wfi_netdevice.h
@@ -77,12 +77,12 @@
#define num_reg_frame 2
/*
* If you use RX_BH_WORK_QUEUE on LPC3131: You may lose the first interrupt on
- * LPC3131 which is important to get the MAC start status when you are blocked inside
- * linux_wlan_firmware_download() which blocks mac_open().
+ * LPC3131 which is important to get the MAC start status when you are blocked
+ * inside linux_wlan_firmware_download() which blocks mac_open().
*/
-#if defined (NM73131_0_BOARD)
+#if defined(NM73131_0_BOARD)
#define RX_BH_TYPE RX_BH_KTHREAD
-#elif defined (PANDA_BOARD)
+#elif defined(PANDA_BOARD)
#define RX_BH_TYPE RX_BH_THREADED_IRQ
#else
#define RX_BH_TYPE RX_BH_KTHREAD
@@ -95,6 +95,7 @@
int seq_len;
u32 cipher;
};
+
struct wilc_wfi_wep_key {
u8 *key;
u8 key_len;
@@ -143,14 +144,15 @@
spinlock_t lock;
struct net_device *dev;
struct napi_struct napi;
- WILC_WFIDrvHandle hWILCWFIDrv;
+ tstrWILC_WFIDrv *hWILCWFIDrv;
WILC_WFIDrvHandle hWILCWFIDrv_2;
tstrHostIFpmkidAttr 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];
- struct net_device *real_ndev; /* The real interface that the monitor is on */
+ /* The real interface that the monitor is on */
+ struct net_device *real_ndev;
struct wilc_wfi_key *wilc_gtk[MAX_NUM_STA];
struct wilc_wfi_key *wilc_ptk[MAX_NUM_STA];
u8 wilc_groupkey;
@@ -174,7 +176,7 @@
typedef struct {
uint8_t aSrcAddress[ETH_ALEN];
uint8_t aBSSID[ETH_ALEN];
- uint32_t drvHandler;
+ tstrWILC_WFIDrv *drvHandler;
struct net_device *wilc_netdev;
} tstrInterfaceInfo;
typedef struct {
diff --git a/drivers/staging/wilc1000/wilc_wlan.c b/drivers/staging/wilc1000/wilc_wlan.c
index 3af91f7..7c53a2b 100644
--- a/drivers/staging/wilc1000/wilc_wlan.c
+++ b/drivers/staging/wilc1000/wilc_wlan.c
@@ -16,7 +16,6 @@
* Global
*
********************************************/
-extern unsigned int int_clrd;
extern wilc_hif_func_t hif_sdio;
extern wilc_hif_func_t hif_spi;
extern wilc_cfg_func_t mac_cfg;
@@ -24,8 +23,6 @@
extern u8 g_wilc_initialized; /* AMR : 0422 RK3026 Crash issue */
#endif
extern void WILC_WFI_mgmt_rx(uint8_t *buff, uint32_t size);
-extern void frmw_to_linux(uint8_t *buff, uint32_t size);
-int sdio_xfer_cnt(void);
uint32_t wilc_get_chipid(uint8_t update);
u16 Set_machw_change_vir_if(bool bValue);
@@ -118,18 +115,15 @@
{
char buf[256];
va_list args;
- int len;
if (flag & dbgflag) {
va_start(args, fmt);
- len = vsprintf(buf, fmt, args);
+ vsprintf(buf, fmt, args);
va_end(args);
if (g_wlan.os_func.os_debug)
g_wlan.os_func.os_debug(buf);
}
-
- return;
}
static CHIP_PS_STATE_T genuChipPSstate = CHIP_WAKEDUP;
@@ -292,13 +286,13 @@
#ifdef TCP_ACK_FILTER
struct Ack_session_info;
-typedef struct Ack_session_info {
+struct Ack_session_info {
uint32_t Ack_seq_num;
uint32_t Bigger_Ack_num;
uint16_t src_port;
uint16_t dst_port;
uint16_t status;
-} Ack_session_info_t;
+};
typedef struct {
uint32_t ack_num;
@@ -319,7 +313,7 @@
#define MAX_TCP_SESSION 25
#define MAX_PENDING_ACKS 256
-Ack_session_info_t Acks_keep_track_info[2 * MAX_TCP_SESSION];
+struct Ack_session_info Acks_keep_track_info[2 * MAX_TCP_SESSION];
Pending_Acks_info_t Pending_Acks_info[MAX_PENDING_ACKS];
uint32_t PendingAcks_arrBase;
@@ -451,7 +445,7 @@
for (i = PendingAcks_arrBase; i < (PendingAcks_arrBase + Pending_Acks); i++) {
if (Pending_Acks_info[i].ack_num < Acks_keep_track_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);
+ 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);
@@ -467,11 +461,10 @@
Pending_Acks = 0;
Opened_TCP_session = 0;
- if (PendingAcks_arrBase == 0) {
+ if (PendingAcks_arrBase == 0)
PendingAcks_arrBase = MAX_TCP_SESSION;
- } else {
+ else
PendingAcks_arrBase = 0;
- }
p->os_func.os_spin_unlock(p->txq_spinlock, &p->txq_spinlock_flags);
@@ -735,7 +728,7 @@
do {
/* Wait for the chip to stabilize*/
- WILC_Sleep(2);
+ usleep_range(2 * 1000, 2 * 1000);
/* Make sure chip is awake. This is an extra step that can be removed */
/* later to avoid the bus access overhead */
if ((wilc_get_chipid(true) == 0)) {
@@ -758,7 +751,7 @@
/* If still off, redo the wake up sequence */
while (((clk_status_reg & 0x1) == 0) && (((++trials) % 3) == 0)) {
/* Wait for the chip to stabilize*/
- WILC_Sleep(2);
+ usleep_range(2 * 1000, 2 * 1000);
/* Make sure chip is awake. This is an extra step that can be removed */
/* later to avoid the bus access overhead */
@@ -996,7 +989,7 @@
/**
* wait for vmm table is ready
**/
- PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait... \n");
+ PRINT_WRN(GENERIC_DBG, "[wilc txq]: warn, vmm table not clear yet, wait...\n");
release_bus(RELEASE_ALLOW_SLEEP);
p->os_func.os_sleep(3); /* wait 3 ms */
acquire_bus(ACQUIRE_AND_WAKEUP);
@@ -1063,7 +1056,7 @@
}
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]);
+ 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]);
/* undo the transaction. */
ret = p->hif_func.hif_read_reg(WILC_HOST_TX_CTRL, ®);
@@ -1114,11 +1107,10 @@
/*Bug3959: transmitting mgmt frames received from host*/
/*setting bit 30 in the host header to indicate mgmt frame*/
#ifdef WILC_AP_EXTERNAL_MLME
- if (tqe->type == WILC_MGMT_PKT) {
+ if (tqe->type == WILC_MGMT_PKT)
header |= (1 << 30);
- } else {
+ else
header &= ~(1 << 30);
- }
#endif
#ifdef BIG_ENDIAN
@@ -1213,7 +1205,7 @@
do {
if (p->quit) {
- PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function \n");
+ PRINT_D(RX_DBG, "exit 1st do-while due to Clean_UP function\n");
p->os_func.os_signal(p->cfg_wait);
break;
}
@@ -1330,8 +1322,7 @@
} while (1);
p->rxq_exit = 1;
- PRINT_D(RX_DBG, "THREAD: Exiting RX thread \n");
- return;
+ PRINT_D(RX_DBG, "THREAD: Exiting RX thread\n");
}
/********************************************
@@ -1414,7 +1405,7 @@
buffer = p->os_func.os_malloc(size);
if (buffer == NULL) {
wilc_debug(N_ERR, "[wilc isr]: fail alloc host memory...drop the packets (%d)\n", size);
- WILC_Sleep(100);
+ usleep_range(100 * 1000, 100 * 1000);
goto _end_;
}
#endif
@@ -1545,11 +1536,10 @@
acquire_bus(ACQUIRE_ONLY);
offset += 8;
while (((int)size) && (offset < buffer_size)) {
- if (size <= blksz) {
+ if (size <= blksz)
size2 = size;
- } else {
+ else
size2 = blksz;
- }
/* Copy firmware into a DMA coherent buffer */
memcpy(dma_buffer, &buffer[offset], size2);
ret = p->hif_func.hif_block_tx(addr, dma_buffer, size2);
@@ -1782,7 +1772,7 @@
/******************************************************************************/
reg = ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 8) | (1 << 9) | (1 << 26) | (1 << 29) | (1 << 30) | (1 << 31)); /**/
/**/
- ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg); /**/
+ p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg); /**/
reg = ~(1 << 10); /**/
/**/
ret = p->hif_func.hif_write_reg(WILC_GLB_RESET_0, reg); /**/
@@ -2306,11 +2296,10 @@
PRINT_ER("Error while Reading reg WILC_CHANGING_VIR_IF\n");
}
- if (bValue) {
+ if (bValue)
reg |= (BIT31);
- } else {
+ else
reg &= ~(BIT31);
- }
ret = (&g_wlan)->hif_func.hif_write_reg(WILC_CHANGING_VIR_IF, reg);
diff --git a/drivers/staging/wilc1000/wilc_wlan.h b/drivers/staging/wilc1000/wilc_wlan.h
index 0ba7ec6..244f710 100644
--- a/drivers/staging/wilc1000/wilc_wlan.h
+++ b/drivers/staging/wilc1000/wilc_wlan.h
@@ -1,7 +1,7 @@
#ifndef WILC_WLAN_H
#define WILC_WLAN_H
-#include "wilc_type.h"
+#include "wilc_oswrapper.h"
#define ISWILC1000(id) (((id & 0xfffff000) == 0x100000) ? 1 : 0)
diff --git a/drivers/staging/wilc1000/wilc_wlan_cfg.c b/drivers/staging/wilc1000/wilc_wlan_cfg.c
index 3cffe55..e2842d3 100644
--- a/drivers/staging/wilc1000/wilc_wlan_cfg.c
+++ b/drivers/staging/wilc1000/wilc_wlan_cfg.c
@@ -363,8 +363,6 @@
size -= (2 + len);
info += (2 + len);
}
-
- return;
}
static int wilc_wlan_parse_info_frame(uint8_t *info, int size)
@@ -513,7 +511,6 @@
int ret = 1;
uint8_t msg_type;
uint8_t msg_id;
- uint16_t msg_len;
#ifdef WILC_FULLY_HOSTING_AP
u32 *ptru32Frame;
bool bStatus = frame[2];
@@ -528,11 +525,6 @@
msg_type = frame[0];
msg_id = frame[1]; /* seq no */
-#ifdef BIG_ENDIAN
- msg_len = (frame[2] << 8) | frame[3];
-#else
- msg_len = (frame[3] << 8) | frame[2];
-#endif
frame += 4;
size -= 4;
@@ -557,7 +549,7 @@
case 'L':
#ifndef SWITCH_LOG_TERMINAL
- PRINT_ER("Unexpected firmware log message received \n");
+ PRINT_ER("Unexpected firmware log message received\n");
#else
PRINT_D(FIRM_DBG, "\nFIRMWARE LOGS :\n<<\n%s\n>>\n", frame);
break;
@@ -572,18 +564,18 @@
#endif
/*bug3819:*/
case 'S':
- PRINT_INFO(RX_DBG, "Scan Notification Received \n");
+ PRINT_INFO(RX_DBG, "Scan Notification Received\n");
host_int_ScanCompleteReceived(frame - 4, size + 4);
break;
#ifdef WILC_FULLY_HOSTING_AP
case 'T':
- PRINT_INFO(RX_DBG, "TBTT Notification Received \n");
+ PRINT_INFO(RX_DBG, "TBTT Notification Received\n");
process_tbtt_isr();
break;
case 'A':
- PRINT_INFO(RX_DBG, "HOSTAPD ACK Notification Received \n");
+ PRINT_INFO(RX_DBG, "HOSTAPD ACK Notification Received\n");
WILC_mgm_HOSTAPD_ACK(ptru32Frame, bStatus);
break;
#endif
diff --git a/drivers/staging/wilc1000/wilc_wlan_if.h b/drivers/staging/wilc1000/wilc_wlan_if.h
index 8ed51e3..5cf74e4 100644
--- a/drivers/staging/wilc1000/wilc_wlan_if.h
+++ b/drivers/staging/wilc1000/wilc_wlan_if.h
@@ -20,7 +20,7 @@
/* #define USE_OLD_SPI_SW */
-#include "wilc_type.h"
+#include "wilc_oswrapper.h"
#include "linux_wlan_common.h"
@@ -43,8 +43,8 @@
********************************************/
#define HIF_SDIO (0)
-#define HIF_SPI (1 << 0)
-#define HIF_SDIO_GPIO_IRQ (1 << 2)
+#define HIF_SPI BIT(0)
+#define HIF_SDIO_GPIO_IRQ BIT(2)
/********************************************
diff --git a/drivers/staging/xgifb/Makefile b/drivers/staging/xgifb/Makefile
index 55e5199..964a843 100644
--- a/drivers/staging/xgifb/Makefile
+++ b/drivers/staging/xgifb/Makefile
@@ -1,4 +1,4 @@
obj-$(CONFIG_FB_XGI) += xgifb.o
-xgifb-y := XGI_main_26.o vb_init.o vb_setmode.o vb_util.o
+xgifb-y := XGI_main_26.o vb_init.o vb_setmode.o
diff --git a/drivers/staging/xgifb/XGI_main_26.c b/drivers/staging/xgifb/XGI_main_26.c
index 943d463..5a6251a4 100644
--- a/drivers/staging/xgifb/XGI_main_26.c
+++ b/drivers/staging/xgifb/XGI_main_26.c
@@ -18,8 +18,8 @@
#define Index_CR_GPIO_Reg1 0x48
#define Index_CR_GPIO_Reg3 0x4a
-#define GPIOG_EN (1<<6)
-#define GPIOG_READ (1<<1)
+#define GPIOG_EN BIT(6)
+#define GPIOG_READ BIT(1)
static char *forcecrt2type;
static char *mode;
@@ -29,7 +29,7 @@
/* -------------------- Macro definitions ---------------------------- */
#ifdef DEBUG
-static void dumpVGAReg(void)
+static void dumpVGAReg(struct xgifb_video_info *xgifb_info)
{
u8 i, reg;
@@ -48,7 +48,7 @@
}
}
#else
-static inline void dumpVGAReg(void)
+static inline void dumpVGAReg(struct xgifb_video_info *xgifb_info)
{
}
#endif
@@ -1073,7 +1073,7 @@
}
XGIfb_bpp_to_var(xgifb_info, var); /*update ARGB info*/
- dumpVGAReg();
+ dumpVGAReg(xgifb_info);
return 0;
}
@@ -2019,7 +2019,7 @@
goto error_mtrr;
}
- dumpVGAReg();
+ dumpVGAReg(xgifb_info);
return 0;
diff --git a/drivers/staging/xgifb/vb_init.h b/drivers/staging/xgifb/vb_init.h
index 2457302..500cabe 100644
--- a/drivers/staging/xgifb/vb_init.h
+++ b/drivers/staging/xgifb/vb_init.h
@@ -1,6 +1,6 @@
#ifndef _VBINIT_
#define _VBINIT_
-extern unsigned char XGIInitNew(struct pci_dev *pdev);
-extern void XGIRegInit(struct vb_device_info *, unsigned long);
+unsigned char XGIInitNew(struct pci_dev *pdev);
+void XGIRegInit(struct vb_device_info *, unsigned long);
#endif
diff --git a/drivers/staging/xgifb/vb_setmode.h b/drivers/staging/xgifb/vb_setmode.h
index 5301bec..6f082a7a 100644
--- a/drivers/staging/xgifb/vb_setmode.h
+++ b/drivers/staging/xgifb/vb_setmode.h
@@ -1,23 +1,23 @@
#ifndef _VBSETMODE_
#define _VBSETMODE_
-extern void InitTo330Pointer(unsigned char, struct vb_device_info *);
-extern void XGI_UnLockCRT2(struct vb_device_info *);
-extern void XGI_LockCRT2(struct vb_device_info *);
-extern void XGI_DisplayOff(struct xgifb_video_info *,
- struct xgi_hw_device_info *,
- struct vb_device_info *);
-extern void XGI_GetVBType(struct vb_device_info *);
-extern void XGI_SenseCRT1(struct vb_device_info *);
-extern unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
- struct xgi_hw_device_info *HwDeviceExtension,
- unsigned short ModeNo);
+void InitTo330Pointer(unsigned char, struct vb_device_info *);
+void XGI_UnLockCRT2(struct vb_device_info *);
+void XGI_LockCRT2(struct vb_device_info *);
+void XGI_DisplayOff(struct xgifb_video_info *,
+ struct xgi_hw_device_info *,
+ struct vb_device_info *);
+void XGI_GetVBType(struct vb_device_info *);
+void XGI_SenseCRT1(struct vb_device_info *);
+unsigned char XGISetModeNew(struct xgifb_video_info *xgifb_info,
+ struct xgi_hw_device_info *HwDeviceExtension,
+ unsigned short ModeNo);
-extern unsigned char XGI_SearchModeID(unsigned short ModeNo,
- unsigned short *ModeIdIndex);
-extern unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
- unsigned short ModeNo,
- unsigned short ModeIdIndex,
- struct vb_device_info *);
+unsigned char XGI_SearchModeID(unsigned short ModeNo,
+ unsigned short *ModeIdIndex);
+unsigned short XGI_GetRatePtrCRT2(struct xgi_hw_device_info *pXGIHWDE,
+ unsigned short ModeNo,
+ unsigned short ModeIdIndex,
+ struct vb_device_info *);
#endif
diff --git a/drivers/staging/xgifb/vb_util.c b/drivers/staging/xgifb/vb_util.c
deleted file mode 100644
index be3437ca..0000000
--- a/drivers/staging/xgifb/vb_util.c
+++ /dev/null
@@ -1,42 +0,0 @@
-#include "vgatypes.h"
-#include "vb_util.h"
-
-void xgifb_reg_set(unsigned long port, u8 index, u8 data)
-{
- outb(index, port);
- outb(data, port + 1);
-}
-
-u8 xgifb_reg_get(unsigned long port, u8 index)
-{
- outb(index, port);
- return inb(port + 1);
-}
-
-void xgifb_reg_and_or(unsigned long port, u8 index,
- unsigned data_and, unsigned data_or)
-{
- u8 temp;
-
- temp = xgifb_reg_get(port, index); /* XGINew_Part1Port index 02 */
- temp = (temp & data_and) | data_or;
- xgifb_reg_set(port, index, temp);
-}
-
-void xgifb_reg_and(unsigned long port, u8 index, unsigned data_and)
-{
- u8 temp;
-
- temp = xgifb_reg_get(port, index); /* XGINew_Part1Port index 02 */
- temp &= data_and;
- xgifb_reg_set(port, index, temp);
-}
-
-void xgifb_reg_or(unsigned long port, u8 index, unsigned data_or)
-{
- u8 temp;
-
- temp = xgifb_reg_get(port, index); /* XGINew_Part1Port index 02 */
- temp |= data_or;
- xgifb_reg_set(port, index, temp);
-}
diff --git a/drivers/staging/xgifb/vb_util.h b/drivers/staging/xgifb/vb_util.h
index 9161de1..7bd395f 100644
--- a/drivers/staging/xgifb/vb_util.h
+++ b/drivers/staging/xgifb/vb_util.h
@@ -1,9 +1,43 @@
#ifndef _VBUTIL_
#define _VBUTIL_
-extern void xgifb_reg_set(unsigned long, u8, u8);
-extern u8 xgifb_reg_get(unsigned long, u8);
-extern void xgifb_reg_or(unsigned long, u8, unsigned);
-extern void xgifb_reg_and(unsigned long, u8, unsigned);
-extern void xgifb_reg_and_or(unsigned long, u8, unsigned, unsigned);
+static inline void xgifb_reg_set(unsigned long port, u8 index, u8 data)
+{
+ outb(index, port);
+ outb(data, port + 1);
+}
+
+static inline u8 xgifb_reg_get(unsigned long port, u8 index)
+{
+ outb(index, port);
+ return inb(port + 1);
+}
+
+static inline void xgifb_reg_and_or(unsigned long port, u8 index,
+ unsigned data_and, unsigned data_or)
+{
+ u8 temp;
+
+ temp = xgifb_reg_get(port, index);
+ temp = (temp & data_and) | data_or;
+ xgifb_reg_set(port, index, temp);
+}
+
+static inline void xgifb_reg_and(unsigned long port, u8 index, unsigned data_and)
+{
+ u8 temp;
+
+ temp = xgifb_reg_get(port, index);
+ temp &= data_and;
+ xgifb_reg_set(port, index, temp);
+}
+
+static inline void xgifb_reg_or(unsigned long port, u8 index, unsigned data_or)
+{
+ u8 temp;
+
+ temp = xgifb_reg_get(port, index);
+ temp |= data_or;
+ xgifb_reg_set(port, index, temp);
+}
#endif
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 4e68b62..fd09290 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -968,9 +968,9 @@
cmd->cmd_flags |= ICF_NON_IMMEDIATE_UNSOLICITED_DATA;
conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
- if (hdr->flags & ISCSI_FLAG_CMD_READ) {
+ if (hdr->flags & ISCSI_FLAG_CMD_READ)
cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
- } else if (hdr->flags & ISCSI_FLAG_CMD_WRITE)
+ else
cmd->targ_xfer_tag = 0xFFFFFFFF;
cmd->cmd_sn = be32_to_cpu(hdr->cmdsn);
cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
@@ -3998,7 +3998,13 @@
}
transport_err:
- iscsit_take_action_for_connection_exit(conn);
+ /*
+ * Avoid the normal connection failure code-path if this connection
+ * is still within LOGIN mode, and iscsi_np process context is
+ * responsible for cleaning up the early connection failure.
+ */
+ if (conn->conn_state != TARG_CONN_STATE_IN_LOGIN)
+ iscsit_take_action_for_connection_exit(conn);
out:
return 0;
}
@@ -4082,7 +4088,7 @@
int iscsi_target_rx_thread(void *arg)
{
- int ret;
+ int ret, rc;
u8 buffer[ISCSI_HDR_LEN], opcode;
u32 checksum = 0, digest = 0;
struct iscsi_conn *conn = arg;
@@ -4092,10 +4098,16 @@
* connection recovery / failure event can be triggered externally.
*/
allow_signal(SIGINT);
+ /*
+ * Wait for iscsi_post_login_handler() to complete before allowing
+ * incoming iscsi/tcp socket I/O, and/or failing the connection.
+ */
+ rc = wait_for_completion_interruptible(&conn->rx_login_comp);
+ if (rc < 0)
+ return 0;
if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {
struct completion comp;
- int rc;
init_completion(&comp);
rc = wait_for_completion_interruptible(&comp);
@@ -4532,7 +4544,18 @@
struct iscsi_conn *conn)
{
struct iscsi_session *sess = conn->sess;
- int sleep = cmpxchg(&conn->tx_thread_active, true, false);
+ int sleep = 1;
+ /*
+ * Traditional iscsi/tcp will invoke this logic from TX thread
+ * context during session logout, so clear tx_thread_active and
+ * sleep if iscsit_close_connection() has not already occured.
+ *
+ * Since iser-target invokes this logic from it's own workqueue,
+ * always sleep waiting for RX/TX thread shutdown to complete
+ * within iscsit_close_connection().
+ */
+ if (conn->conn_transport->transport_type == ISCSI_TCP)
+ sleep = cmpxchg(&conn->tx_thread_active, true, false);
atomic_set(&conn->conn_logout_remove, 0);
complete(&conn->conn_logout_comp);
@@ -4546,7 +4569,10 @@
static void iscsit_logout_post_handler_samecid(
struct iscsi_conn *conn)
{
- int sleep = cmpxchg(&conn->tx_thread_active, true, false);
+ int sleep = 1;
+
+ if (conn->conn_transport->transport_type == ISCSI_TCP)
+ sleep = cmpxchg(&conn->tx_thread_active, true, false);
atomic_set(&conn->conn_logout_remove, 0);
complete(&conn->conn_logout_comp);
@@ -4765,6 +4791,7 @@
struct iscsi_session *sess;
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
struct se_session *se_sess, *se_sess_tmp;
+ LIST_HEAD(free_list);
int session_count = 0;
spin_lock_bh(&se_tpg->session_lock);
@@ -4786,15 +4813,18 @@
}
atomic_set(&sess->session_reinstatement, 1);
spin_unlock(&sess->conn_lock);
- spin_unlock_bh(&se_tpg->session_lock);
- iscsit_free_session(sess);
- spin_lock_bh(&se_tpg->session_lock);
-
- session_count++;
+ list_move_tail(&se_sess->sess_list, &free_list);
}
spin_unlock_bh(&se_tpg->session_lock);
+ list_for_each_entry_safe(se_sess, se_sess_tmp, &free_list, sess_list) {
+ sess = (struct iscsi_session *)se_sess->fabric_sess_ptr;
+
+ iscsit_free_session(sess);
+ session_count++;
+ }
+
pr_debug("Released %d iSCSI Session(s) from Target Portal"
" Group: %hu\n", session_count, tpg->tpgt);
return 0;
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index 3d0fe4f..7e8f65e 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -82,6 +82,7 @@
init_completion(&conn->conn_logout_comp);
init_completion(&conn->rx_half_close_comp);
init_completion(&conn->tx_half_close_comp);
+ init_completion(&conn->rx_login_comp);
spin_lock_init(&conn->cmd_lock);
spin_lock_init(&conn->conn_usage_lock);
spin_lock_init(&conn->immed_queue_lock);
@@ -644,7 +645,7 @@
iscsit_start_nopin_timer(conn);
}
-static int iscsit_start_kthreads(struct iscsi_conn *conn)
+int iscsit_start_kthreads(struct iscsi_conn *conn)
{
int ret = 0;
@@ -679,6 +680,7 @@
return 0;
out_tx:
+ send_sig(SIGINT, conn->tx_thread, 1);
kthread_stop(conn->tx_thread);
conn->tx_thread_active = false;
out_bitmap:
@@ -689,7 +691,7 @@
return ret;
}
-int iscsi_post_login_handler(
+void iscsi_post_login_handler(
struct iscsi_np *np,
struct iscsi_conn *conn,
u8 zero_tsih)
@@ -699,7 +701,6 @@
struct se_session *se_sess = sess->se_sess;
struct iscsi_portal_group *tpg = sess->tpg;
struct se_portal_group *se_tpg = &tpg->tpg_se_tpg;
- int rc;
iscsit_inc_conn_usage_count(conn);
@@ -739,10 +740,6 @@
sess->sess_ops->InitiatorName);
spin_unlock_bh(&sess->conn_lock);
- rc = iscsit_start_kthreads(conn);
- if (rc)
- return rc;
-
iscsi_post_login_start_timers(conn);
/*
* Determine CPU mask to ensure connection's RX and TX kthreads
@@ -751,15 +748,20 @@
iscsit_thread_get_cpumask(conn);
conn->conn_rx_reset_cpumask = 1;
conn->conn_tx_reset_cpumask = 1;
-
+ /*
+ * Wakeup the sleeping iscsi_target_rx_thread() now that
+ * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state.
+ */
+ complete(&conn->rx_login_comp);
iscsit_dec_conn_usage_count(conn);
+
if (stop_timer) {
spin_lock_bh(&se_tpg->session_lock);
iscsit_stop_time2retain_timer(sess);
spin_unlock_bh(&se_tpg->session_lock);
}
iscsit_dec_session_usage_count(sess);
- return 0;
+ return;
}
iscsi_set_session_parameters(sess->sess_ops, conn->param_list, 1);
@@ -800,10 +802,6 @@
" iSCSI Target Portal Group: %hu\n", tpg->nsessions, tpg->tpgt);
spin_unlock_bh(&se_tpg->session_lock);
- rc = iscsit_start_kthreads(conn);
- if (rc)
- return rc;
-
iscsi_post_login_start_timers(conn);
/*
* Determine CPU mask to ensure connection's RX and TX kthreads
@@ -812,10 +810,12 @@
iscsit_thread_get_cpumask(conn);
conn->conn_rx_reset_cpumask = 1;
conn->conn_tx_reset_cpumask = 1;
-
+ /*
+ * Wakeup the sleeping iscsi_target_rx_thread() now that
+ * iscsi_conn is in TARG_CONN_STATE_LOGGED_IN state.
+ */
+ complete(&conn->rx_login_comp);
iscsit_dec_conn_usage_count(conn);
-
- return 0;
}
static void iscsi_handle_login_thread_timeout(unsigned long data)
@@ -1380,23 +1380,12 @@
if (ret < 0)
goto new_sess_out;
- if (!conn->sess) {
- pr_err("struct iscsi_conn session pointer is NULL!\n");
- goto new_sess_out;
- }
-
iscsi_stop_login_thread_timer(np);
- if (signal_pending(current))
- goto new_sess_out;
-
if (ret == 1) {
tpg_np = conn->tpg_np;
- ret = iscsi_post_login_handler(np, conn, zero_tsih);
- if (ret < 0)
- goto new_sess_out;
-
+ iscsi_post_login_handler(np, conn, zero_tsih);
iscsit_deaccess_np(np, tpg, tpg_np);
}
diff --git a/drivers/target/iscsi/iscsi_target_login.h b/drivers/target/iscsi/iscsi_target_login.h
index 1c73580..57aa0d0 100644
--- a/drivers/target/iscsi/iscsi_target_login.h
+++ b/drivers/target/iscsi/iscsi_target_login.h
@@ -12,7 +12,8 @@
extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *);
extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
extern void iscsit_free_conn(struct iscsi_np *, struct iscsi_conn *);
-extern int iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
+extern int iscsit_start_kthreads(struct iscsi_conn *);
+extern void iscsi_post_login_handler(struct iscsi_np *, struct iscsi_conn *, u8);
extern void iscsi_target_login_sess_out(struct iscsi_conn *, struct iscsi_np *,
bool, bool);
extern int iscsi_target_login_thread(void *);
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 8c02fa3..f9cde91 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -17,6 +17,7 @@
******************************************************************************/
#include <linux/ctype.h>
+#include <linux/kthread.h>
#include <scsi/iscsi_proto.h>
#include <target/target_core_base.h>
#include <target/target_core_fabric.h>
@@ -361,10 +362,24 @@
ntohl(login_rsp->statsn), login->rsp_length);
padding = ((-login->rsp_length) & 3);
+ /*
+ * Before sending the last login response containing the transition
+ * bit for full-feature-phase, go ahead and start up TX/RX threads
+ * now to avoid potential resource allocation failures after the
+ * final login response has been sent.
+ */
+ if (login->login_complete) {
+ int rc = iscsit_start_kthreads(conn);
+ if (rc) {
+ iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+ ISCSI_LOGIN_STATUS_NO_RESOURCES);
+ return -1;
+ }
+ }
if (conn->conn_transport->iscsit_put_login_tx(conn, login,
login->rsp_length + padding) < 0)
- return -1;
+ goto err;
login->rsp_length = 0;
mutex_lock(&sess->cmdsn_mutex);
@@ -373,6 +388,23 @@
mutex_unlock(&sess->cmdsn_mutex);
return 0;
+
+err:
+ if (login->login_complete) {
+ if (conn->rx_thread && conn->rx_thread_active) {
+ send_sig(SIGINT, conn->rx_thread, 1);
+ kthread_stop(conn->rx_thread);
+ }
+ if (conn->tx_thread && conn->tx_thread_active) {
+ send_sig(SIGINT, conn->tx_thread, 1);
+ kthread_stop(conn->tx_thread);
+ }
+ spin_lock(&iscsit_global->ts_bitmap_lock);
+ bitmap_release_region(iscsit_global->ts_bitmap, conn->bitmap_id,
+ get_order(1));
+ spin_unlock(&iscsit_global->ts_bitmap_lock);
+ }
+ return -1;
}
static void iscsi_target_sk_data_ready(struct sock *sk)
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 0b0de36..860e840 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -457,8 +457,15 @@
if (!strcmp(t->tf_ops->name, fo->name)) {
BUG_ON(atomic_read(&t->tf_access_cnt));
list_del(&t->tf_list);
+ mutex_unlock(&g_tf_lock);
+ /*
+ * Wait for any outstanding fabric se_deve_entry->rcu_head
+ * callbacks to complete post kfree_rcu(), before allowing
+ * fabric driver unload of TFO->module to proceed.
+ */
+ rcu_barrier();
kfree(t);
- break;
+ return;
}
}
mutex_unlock(&g_tf_lock);
@@ -747,7 +754,7 @@
if (!dev->transport->init_prot || !dev->transport->free_prot) {
/* 0 is only allowed value for non-supporting backends */
if (flag == 0)
- return 0;
+ return count;
pr_err("DIF protection not supported by backend: %s\n",
dev->transport->name);
@@ -1590,9 +1597,9 @@
u8 type = 0;
if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
- return 0;
+ return count;
if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
- return 0;
+ return count;
if (dev->export_count) {
pr_debug("Unable to process APTPL metadata while"
@@ -1658,22 +1665,32 @@
* PR APTPL Metadata for Reservation
*/
case Opt_res_holder:
- match_int(args, &arg);
+ ret = match_int(args, &arg);
+ if (ret)
+ goto out;
res_holder = arg;
break;
case Opt_res_type:
- match_int(args, &arg);
+ ret = match_int(args, &arg);
+ if (ret)
+ goto out;
type = (u8)arg;
break;
case Opt_res_scope:
- match_int(args, &arg);
+ ret = match_int(args, &arg);
+ if (ret)
+ goto out;
break;
case Opt_res_all_tg_pt:
- match_int(args, &arg);
+ ret = match_int(args, &arg);
+ if (ret)
+ goto out;
all_tg_pt = (int)arg;
break;
case Opt_mapped_lun:
- match_int(args, &arg);
+ ret = match_int(args, &arg);
+ if (ret)
+ goto out;
mapped_lun = (u64)arg;
break;
/*
@@ -1701,14 +1718,20 @@
}
break;
case Opt_tpgt:
- match_int(args, &arg);
+ ret = match_int(args, &arg);
+ if (ret)
+ goto out;
tpgt = (u16)arg;
break;
case Opt_port_rtpi:
- match_int(args, &arg);
+ ret = match_int(args, &arg);
+ if (ret)
+ goto out;
break;
case Opt_target_lun:
- match_int(args, &arg);
+ ret = match_int(args, &arg);
+ if (ret)
+ goto out;
target_lun = (u64)arg;
break;
default:
@@ -1985,7 +2008,7 @@
lu_gp_mem = dev->dev_alua_lu_gp_mem;
if (!lu_gp_mem)
- return 0;
+ return count;
if (count > LU_GROUP_NAME_BUF) {
pr_err("ALUA LU Group Alias too large!\n");
diff --git a/drivers/target/target_core_hba.c b/drivers/target/target_core_hba.c
index 62ea4e8..be9cefc 100644
--- a/drivers/target/target_core_hba.c
+++ b/drivers/target/target_core_hba.c
@@ -84,8 +84,16 @@
list_for_each_entry(tb, &backend_list, list) {
if (tb->ops == ops) {
list_del(&tb->list);
+ mutex_unlock(&backend_mutex);
+ /*
+ * Wait for any outstanding backend driver ->rcu_head
+ * callbacks to complete post TBO->free_device() ->
+ * call_rcu(), before allowing backend driver module
+ * unload of target_backend_ops->owner to proceed.
+ */
+ rcu_barrier();
kfree(tb);
- break;
+ return;
}
}
mutex_unlock(&backend_mutex);
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index 0fdbe43..5ab7100 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -1474,7 +1474,7 @@
LIST_HEAD(tid_dest_list);
struct pr_transport_id_holder *tidh_new, *tidh, *tidh_tmp;
unsigned char *buf, *ptr, proto_ident;
- const unsigned char *i_str;
+ const unsigned char *i_str = NULL;
char *iport_ptr = NULL, i_buf[PR_REG_ISID_ID_LEN];
sense_reason_t ret;
u32 tpdl, tid_len = 0;
diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index 4703f40..384cf88 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -333,6 +333,7 @@
dev->dev_attrib.hw_block_size = RD_BLOCKSIZE;
dev->dev_attrib.hw_max_sectors = UINT_MAX;
dev->dev_attrib.hw_queue_depth = RD_MAX_DEVICE_QUEUE_DEPTH;
+ dev->dev_attrib.is_nonrot = 1;
rd_dev->rd_dev_id = rd_host->rd_host_dev_id_count++;
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index b074443..f87d4ce 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -454,10 +454,17 @@
cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE1_PROT)
buf[4] = 0x5;
else if (dev->dev_attrib.pi_prot_type == TARGET_DIF_TYPE3_PROT ||
- cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT)
+ cmd->se_sess->sess_prot_type == TARGET_DIF_TYPE3_PROT)
buf[4] = 0x4;
}
+ /* logical unit supports type 1 and type 3 protection */
+ if ((dev->transport->get_device_type(dev) == TYPE_DISK) &&
+ (sess->sup_prot_ops & (TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS)) &&
+ (dev->dev_attrib.pi_prot_type || cmd->se_sess->sess_prot_type)) {
+ buf[4] |= (0x3 << 3);
+ }
+
/* Set HEADSUP, ORDSUP, SIMPSUP */
buf[5] = 0x07;
@@ -1196,17 +1203,13 @@
struct se_dev_entry *deve;
struct se_session *sess = cmd->se_sess;
struct se_node_acl *nacl;
+ struct scsi_lun slun;
unsigned char *buf;
u32 lun_count = 0, offset = 8;
-
- if (cmd->data_length < 16) {
- pr_warn("REPORT LUNS allocation length %u too small\n",
- cmd->data_length);
- return TCM_INVALID_CDB_FIELD;
- }
+ __be32 len;
buf = transport_kmap_data_sg(cmd);
- if (!buf)
+ if (cmd->data_length && !buf)
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
/*
@@ -1214,11 +1217,9 @@
* coming via a target_core_mod PASSTHROUGH op, and not through
* a $FABRIC_MOD. In that case, report LUN=0 only.
*/
- if (!sess) {
- int_to_scsilun(0, (struct scsi_lun *)&buf[offset]);
- lun_count = 1;
+ if (!sess)
goto done;
- }
+
nacl = sess->se_node_acl;
rcu_read_lock();
@@ -1229,10 +1230,12 @@
* See SPC2-R20 7.19.
*/
lun_count++;
- if ((offset + 8) > cmd->data_length)
+ if (offset >= cmd->data_length)
continue;
- int_to_scsilun(deve->mapped_lun, (struct scsi_lun *)&buf[offset]);
+ int_to_scsilun(deve->mapped_lun, &slun);
+ memcpy(buf + offset, &slun,
+ min(8u, cmd->data_length - offset));
offset += 8;
}
rcu_read_unlock();
@@ -1241,12 +1244,22 @@
* See SPC3 r07, page 159.
*/
done:
- lun_count *= 8;
- buf[0] = ((lun_count >> 24) & 0xff);
- buf[1] = ((lun_count >> 16) & 0xff);
- buf[2] = ((lun_count >> 8) & 0xff);
- buf[3] = (lun_count & 0xff);
- transport_kunmap_data_sg(cmd);
+ /*
+ * If no LUNs are accessible, report virtual LUN 0.
+ */
+ if (lun_count == 0) {
+ int_to_scsilun(0, &slun);
+ if (cmd->data_length > 8)
+ memcpy(buf + offset, &slun,
+ min(8u, cmd->data_length - offset));
+ lun_count = 1;
+ }
+
+ if (buf) {
+ len = cpu_to_be32(lun_count * 8);
+ memcpy(buf, &len, min_t(int, sizeof len, cmd->data_length));
+ transport_kunmap_data_sg(cmd);
+ }
target_complete_cmd_with_length(cmd, GOOD, 8 + lun_count * 8);
return 0;
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 6509c61..620dcd4 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -68,7 +68,7 @@
* registered cooling device.
* @cpufreq_state: integer value representing the current state of cpufreq
* cooling devices.
- * @cpufreq_val: integer value representing the absolute value of the clipped
+ * @clipped_freq: integer value representing the absolute value of the clipped
* frequency.
* @max_level: maximum cooling level. One less than total number of valid
* cpufreq frequencies.
@@ -91,7 +91,7 @@
int id;
struct thermal_cooling_device *cool_dev;
unsigned int cpufreq_state;
- unsigned int cpufreq_val;
+ unsigned int clipped_freq;
unsigned int max_level;
unsigned int *freq_table; /* In descending order */
struct cpumask allowed_cpus;
@@ -107,6 +107,9 @@
static DEFINE_IDR(cpufreq_idr);
static DEFINE_MUTEX(cooling_cpufreq_lock);
+static unsigned int cpufreq_dev_count;
+
+static DEFINE_MUTEX(cooling_list_lock);
static LIST_HEAD(cpufreq_dev_list);
/**
@@ -185,14 +188,14 @@
{
struct cpufreq_cooling_device *cpufreq_dev;
- mutex_lock(&cooling_cpufreq_lock);
+ mutex_lock(&cooling_list_lock);
list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) {
- mutex_unlock(&cooling_cpufreq_lock);
+ mutex_unlock(&cooling_list_lock);
return get_level(cpufreq_dev, freq);
}
}
- mutex_unlock(&cooling_cpufreq_lock);
+ mutex_unlock(&cooling_list_lock);
pr_err("%s: cpu:%d not part of any cooling device\n", __func__, cpu);
return THERMAL_CSTATE_INVALID;
@@ -215,29 +218,35 @@
unsigned long event, void *data)
{
struct cpufreq_policy *policy = data;
- unsigned long max_freq = 0;
+ unsigned long clipped_freq;
struct cpufreq_cooling_device *cpufreq_dev;
- switch (event) {
-
- case CPUFREQ_ADJUST:
- mutex_lock(&cooling_cpufreq_lock);
- list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
- if (!cpumask_test_cpu(policy->cpu,
- &cpufreq_dev->allowed_cpus))
- continue;
-
- max_freq = cpufreq_dev->cpufreq_val;
-
- if (policy->max != max_freq)
- cpufreq_verify_within_limits(policy, 0,
- max_freq);
- }
- mutex_unlock(&cooling_cpufreq_lock);
- break;
- default:
+ if (event != CPUFREQ_ADJUST)
return NOTIFY_DONE;
+
+ mutex_lock(&cooling_list_lock);
+ list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
+ if (!cpumask_test_cpu(policy->cpu, &cpufreq_dev->allowed_cpus))
+ continue;
+
+ /*
+ * policy->max is the maximum allowed frequency defined by user
+ * and clipped_freq is the maximum that thermal constraints
+ * allow.
+ *
+ * If clipped_freq is lower than policy->max, then we need to
+ * readjust policy->max.
+ *
+ * But, if clipped_freq is greater than policy->max, we don't
+ * need to do anything.
+ */
+ clipped_freq = cpufreq_dev->clipped_freq;
+
+ if (policy->max > clipped_freq)
+ cpufreq_verify_within_limits(policy, 0, clipped_freq);
+ break;
}
+ mutex_unlock(&cooling_list_lock);
return NOTIFY_OK;
}
@@ -519,7 +528,7 @@
clip_freq = cpufreq_device->freq_table[state];
cpufreq_device->cpufreq_state = state;
- cpufreq_device->cpufreq_val = clip_freq;
+ cpufreq_device->clipped_freq = clip_freq;
cpufreq_update_policy(cpu);
@@ -861,17 +870,19 @@
pr_debug("%s: freq:%u KHz\n", __func__, freq);
}
- cpufreq_dev->cpufreq_val = cpufreq_dev->freq_table[0];
+ cpufreq_dev->clipped_freq = cpufreq_dev->freq_table[0];
cpufreq_dev->cool_dev = cool_dev;
mutex_lock(&cooling_cpufreq_lock);
+ mutex_lock(&cooling_list_lock);
+ list_add(&cpufreq_dev->node, &cpufreq_dev_list);
+ mutex_unlock(&cooling_list_lock);
+
/* Register the notifier for first cpufreq cooling device */
- if (list_empty(&cpufreq_dev_list))
+ if (!cpufreq_dev_count++)
cpufreq_register_notifier(&thermal_cpufreq_notifier_block,
CPUFREQ_POLICY_NOTIFIER);
- list_add(&cpufreq_dev->node, &cpufreq_dev_list);
-
mutex_unlock(&cooling_cpufreq_lock);
return cool_dev;
@@ -1013,13 +1024,17 @@
return;
cpufreq_dev = cdev->devdata;
- mutex_lock(&cooling_cpufreq_lock);
- list_del(&cpufreq_dev->node);
/* Unregister the notifier for the last cpufreq cooling device */
- if (list_empty(&cpufreq_dev_list))
+ mutex_lock(&cooling_cpufreq_lock);
+ if (!--cpufreq_dev_count)
cpufreq_unregister_notifier(&thermal_cpufreq_notifier_block,
CPUFREQ_POLICY_NOTIFIER);
+
+ mutex_lock(&cooling_list_lock);
+ list_del(&cpufreq_dev->node);
+ mutex_unlock(&cooling_list_lock);
+
mutex_unlock(&cooling_cpufreq_lock);
thermal_cooling_device_unregister(cpufreq_dev->cool_dev);
diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c
index d5dd357..b49f97c 100644
--- a/drivers/thermal/hisi_thermal.c
+++ b/drivers/thermal/hisi_thermal.c
@@ -405,7 +405,6 @@
static struct platform_driver hisi_thermal_driver = {
.driver = {
.name = "hisi_thermal",
- .owner = THIS_MODULE,
.pm = &hisi_thermal_pm_ops,
.of_match_table = of_hisi_thermal_match,
},
diff --git a/drivers/thermal/power_allocator.c b/drivers/thermal/power_allocator.c
index 4672250..2516769 100644
--- a/drivers/thermal/power_allocator.c
+++ b/drivers/thermal/power_allocator.c
@@ -229,7 +229,8 @@
struct thermal_instance *instance;
struct power_allocator_params *params = tz->governor_data;
u32 *req_power, *max_power, *granted_power, *extra_actor_power;
- u32 total_req_power, max_allocatable_power;
+ u32 *weighted_req_power;
+ u32 total_req_power, max_allocatable_power, total_weighted_req_power;
u32 total_granted_power, power_range;
int i, num_actors, total_weight, ret = 0;
int trip_max_desired_temperature = params->trip_max_desired_temperature;
@@ -247,17 +248,17 @@
}
/*
- * We need to allocate three arrays of the same size:
- * req_power, max_power and granted_power. They are going to
- * be needed until this function returns. Allocate them all
- * in one go to simplify the allocation and deallocation
- * logic.
+ * We need to allocate five arrays of the same size:
+ * req_power, max_power, granted_power, extra_actor_power and
+ * weighted_req_power. They are going to be needed until this
+ * function returns. Allocate them all in one go to simplify
+ * the allocation and deallocation logic.
*/
BUILD_BUG_ON(sizeof(*req_power) != sizeof(*max_power));
BUILD_BUG_ON(sizeof(*req_power) != sizeof(*granted_power));
BUILD_BUG_ON(sizeof(*req_power) != sizeof(*extra_actor_power));
- req_power = devm_kcalloc(&tz->device, num_actors * 4,
- sizeof(*req_power), GFP_KERNEL);
+ BUILD_BUG_ON(sizeof(*req_power) != sizeof(*weighted_req_power));
+ req_power = kcalloc(num_actors * 5, sizeof(*req_power), GFP_KERNEL);
if (!req_power) {
ret = -ENOMEM;
goto unlock;
@@ -266,8 +267,10 @@
max_power = &req_power[num_actors];
granted_power = &req_power[2 * num_actors];
extra_actor_power = &req_power[3 * num_actors];
+ weighted_req_power = &req_power[4 * num_actors];
i = 0;
+ total_weighted_req_power = 0;
total_req_power = 0;
max_allocatable_power = 0;
@@ -289,13 +292,14 @@
else
weight = instance->weight;
- req_power[i] = frac_to_int(weight * req_power[i]);
+ weighted_req_power[i] = frac_to_int(weight * req_power[i]);
if (power_actor_get_max_power(cdev, tz, &max_power[i]))
continue;
total_req_power += req_power[i];
max_allocatable_power += max_power[i];
+ total_weighted_req_power += weighted_req_power[i];
i++;
}
@@ -303,8 +307,9 @@
power_range = pid_controller(tz, current_temp, control_temp,
max_allocatable_power);
- divvy_up_power(req_power, max_power, num_actors, total_req_power,
- power_range, granted_power, extra_actor_power);
+ divvy_up_power(weighted_req_power, max_power, num_actors,
+ total_weighted_req_power, power_range, granted_power,
+ extra_actor_power);
total_granted_power = 0;
i = 0;
@@ -328,7 +333,7 @@
max_allocatable_power, current_temp,
(s32)control_temp - (s32)current_temp);
- devm_kfree(&tz->device, req_power);
+ kfree(req_power);
unlock:
mutex_unlock(&tz->lock);
@@ -420,7 +425,7 @@
return -EINVAL;
}
- params = devm_kzalloc(&tz->device, sizeof(*params), GFP_KERNEL);
+ params = kzalloc(sizeof(*params), GFP_KERNEL);
if (!params)
return -ENOMEM;
@@ -462,14 +467,14 @@
return 0;
free:
- devm_kfree(&tz->device, params);
+ kfree(params);
return ret;
}
static void power_allocator_unbind(struct thermal_zone_device *tz)
{
dev_dbg(&tz->device, "Unbinding from thermal zone %d\n", tz->id);
- devm_kfree(&tz->device, tz->governor_data);
+ kfree(tz->governor_data);
tz->governor_data = NULL;
}
diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig
index c8e35c1..e0da386 100644
--- a/drivers/thermal/samsung/Kconfig
+++ b/drivers/thermal/samsung/Kconfig
@@ -1,6 +1,6 @@
config EXYNOS_THERMAL
tristate "Exynos thermal management unit driver"
- depends on OF
+ depends on THERMAL_OF
help
If you say yes here you get support for the TMU (Thermal Management
Unit) driver for SAMSUNG EXYNOS series of SoCs. This driver initialises
diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c
index 531f4b17..c96ff10 100644
--- a/drivers/thermal/samsung/exynos_tmu.c
+++ b/drivers/thermal/samsung/exynos_tmu.c
@@ -1296,7 +1296,6 @@
static int exynos_tmu_probe(struct platform_device *pdev)
{
- struct exynos_tmu_platform_data *pdata;
struct exynos_tmu_data *data;
int ret;
@@ -1318,8 +1317,6 @@
if (ret)
goto err_sensor;
- pdata = data->pdata;
-
INIT_WORK(&data->irq_work, exynos_tmu_work);
data->clk = devm_clk_get(&pdev->dev, "tmu_apbif");
@@ -1392,6 +1389,8 @@
if (!IS_ERR(data->clk_sec))
clk_unprepare(data->clk_sec);
err_sensor:
+ if (!IS_ERR_OR_NULL(data->regulator))
+ regulator_disable(data->regulator);
thermal_zone_of_sensor_unregister(&pdev->dev, data->tzd);
return ret;
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 04659bf..4ca211b 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -1333,6 +1333,7 @@
return -ENODEV;
unbind:
+ device_remove_file(&tz->device, &pos->weight_attr);
device_remove_file(&tz->device, &pos->attr);
sysfs_remove_link(&tz->device.kobj, pos->name);
release_idr(&tz->idr, &tz->lock, pos->id);
diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
index 382d3fc..c3fe026 100644
--- a/drivers/tty/n_gsm.c
+++ b/drivers/tty/n_gsm.c
@@ -2712,7 +2712,7 @@
memcpy(skb_put(skb, size), in_buf, size);
skb->dev = net;
- skb->protocol = __constant_htons(ETH_P_IP);
+ skb->protocol = htons(ETH_P_IP);
/* Ship it off to the kernel */
netif_rx(skb);
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index c9c27f6..20932cc 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -1108,19 +1108,29 @@
* Locking: ctrl_lock
*/
-static void isig(int sig, struct tty_struct *tty)
+static void __isig(int sig, struct tty_struct *tty)
{
- struct n_tty_data *ldata = tty->disc_data;
struct pid *tty_pgrp = tty_get_pgrp(tty);
if (tty_pgrp) {
kill_pgrp(tty_pgrp, sig, 1);
put_pid(tty_pgrp);
}
+}
- if (!L_NOFLSH(tty)) {
+static void isig(int sig, struct tty_struct *tty)
+{
+ struct n_tty_data *ldata = tty->disc_data;
+
+ if (L_NOFLSH(tty)) {
+ /* signal only */
+ __isig(sig, tty);
+
+ } else { /* signal and flush */
up_read(&tty->termios_rwsem);
down_write(&tty->termios_rwsem);
+ __isig(sig, tty);
+
/* clear echo buffer */
mutex_lock(&ldata->output_lock);
ldata->echo_head = ldata->echo_tail = 0;
@@ -2137,6 +2147,8 @@
static int job_control(struct tty_struct *tty, struct file *file)
{
+ struct pid *pgrp;
+
/* Job control check -- must be done at start and after
every sleep (POSIX.1 7.1.1.4). */
/* NOTE: not yet done after every sleep pending a thorough
@@ -2146,18 +2158,25 @@
current->signal->tty != tty)
return 0;
+ rcu_read_lock();
+ pgrp = task_pgrp(current);
+
spin_lock_irq(&tty->ctrl_lock);
if (!tty->pgrp)
printk(KERN_ERR "n_tty_read: no tty->pgrp!\n");
- else if (task_pgrp(current) != tty->pgrp) {
+ else if (pgrp != tty->pgrp) {
spin_unlock_irq(&tty->ctrl_lock);
- if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned())
+ if (is_ignored(SIGTTIN) || is_current_pgrp_orphaned()) {
+ rcu_read_unlock();
return -EIO;
- kill_pgrp(task_pgrp(current), SIGTTIN, 1);
+ }
+ kill_pgrp(pgrp, SIGTTIN, 1);
+ rcu_read_unlock();
set_thread_flag(TIF_SIGPENDING);
return -ERESTARTSYS;
}
spin_unlock_irq(&tty->ctrl_lock);
+ rcu_read_unlock();
return 0;
}
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 4d5e840..4d5937c 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -26,6 +26,12 @@
#include <linux/mutex.h>
#include <linux/poll.h>
+#undef TTY_DEBUG_HANGUP
+#ifdef TTY_DEBUG_HANGUP
+# define tty_debug_hangup(tty, f, args...) tty_debug(tty, f, ##args)
+#else
+# define tty_debug_hangup(tty, f, args...) do {} while (0)
+#endif
#ifdef CONFIG_UNIX98_PTYS
static struct tty_driver *ptm_driver;
@@ -779,6 +785,8 @@
if (retval)
goto err_release;
+ tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
+
tty_unlock(tty);
return 0;
err_release:
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index c43f74c..d54dcd8 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -42,9 +42,9 @@
size_t rx_size;
size_t tx_size;
- unsigned char tx_running:1;
- unsigned char tx_err: 1;
- unsigned char rx_running:1;
+ unsigned char tx_running;
+ unsigned char tx_err;
+ unsigned char rx_running;
};
struct old_serial_port {
@@ -211,3 +211,14 @@
}
return 1;
}
+
+static inline int serial_index(struct uart_port *port)
+{
+ return port->minor - 64;
+}
+
+#if 0
+#define DEBUG_INTR(fmt...) printk(fmt)
+#else
+#define DEBUG_INTR(fmt...) do { } while (0)
+#endif
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 37fff12..cfbb9d7 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -1,25 +1,23 @@
/*
- * Driver for 8250/16550-type serial ports
+ * Universal/legacy driver for 8250/16550-type serial ports
*
* Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
*
* Copyright (C) 2001 Russell King.
*
+ * Supports: ISA-compatible 8250/16550 ports
+ * PNP 8250/16550 ports
+ * early_serial_setup() ports
+ * userspace-configurable "phantom" ports
+ * "serial8250" platform devices
+ * serial8250_register_8250_port() ports
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
- * A note about mapbase / membase
- *
- * mapbase is the physical address of the IO port.
- * membase is an 'ioremapped' cookie.
*/
-#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
-#define SUPPORT_SYSRQ
-#endif
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/ioport.h>
@@ -58,33 +56,10 @@
static struct uart_driver serial8250_reg;
-static int serial_index(struct uart_port *port)
-{
- return port->minor - 64;
-}
-
static unsigned int skip_txen_test; /* force skip of txen test at init time */
-/*
- * Debugging.
- */
-#if 0
-#define DEBUG_AUTOCONF(fmt...) printk(fmt)
-#else
-#define DEBUG_AUTOCONF(fmt...) do { } while (0)
-#endif
-
-#if 0
-#define DEBUG_INTR(fmt...) printk(fmt)
-#else
-#define DEBUG_INTR(fmt...) do { } while (0)
-#endif
-
#define PASS_LIMIT 512
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-
#include <asm/serial.h>
/*
* SERIAL_PORT_DFNS tells us about built-in ports that have no
@@ -120,1563 +95,6 @@
static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */
/*
- * Here we define the default xmit fifo size used for each type of UART.
- */
-static const struct serial8250_config uart_config[] = {
- [PORT_UNKNOWN] = {
- .name = "unknown",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_8250] = {
- .name = "8250",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16450] = {
- .name = "16450",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16550] = {
- .name = "16550",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16550A] = {
- .name = "16550A",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .rxtrig_bytes = {1, 4, 8, 14},
- .flags = UART_CAP_FIFO,
- },
- [PORT_CIRRUS] = {
- .name = "Cirrus",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16650] = {
- .name = "ST16650",
- .fifo_size = 1,
- .tx_loadsz = 1,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16650V2] = {
- .name = "ST16650V2",
- .fifo_size = 32,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
- UART_FCR_T_TRIG_00,
- .rxtrig_bytes = {8, 16, 24, 28},
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16750] = {
- .name = "TI16750",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
- UART_FCR7_64BYTE,
- .rxtrig_bytes = {1, 16, 32, 56},
- .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
- },
- [PORT_STARTECH] = {
- .name = "Startech",
- .fifo_size = 1,
- .tx_loadsz = 1,
- },
- [PORT_16C950] = {
- .name = "16C950/954",
- .fifo_size = 128,
- .tx_loadsz = 128,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- /* UART_CAP_EFR breaks billionon CF bluetooth card. */
- .flags = UART_CAP_FIFO | UART_CAP_SLEEP,
- },
- [PORT_16654] = {
- .name = "ST16654",
- .fifo_size = 64,
- .tx_loadsz = 32,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
- UART_FCR_T_TRIG_10,
- .rxtrig_bytes = {8, 16, 56, 60},
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_16850] = {
- .name = "XR16850",
- .fifo_size = 128,
- .tx_loadsz = 128,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
- },
- [PORT_RSA] = {
- .name = "RSA",
- .fifo_size = 2048,
- .tx_loadsz = 2048,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
- .flags = UART_CAP_FIFO,
- },
- [PORT_NS16550A] = {
- .name = "NS16550A",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_NATSEMI,
- },
- [PORT_XSCALE] = {
- .name = "XScale",
- .fifo_size = 32,
- .tx_loadsz = 32,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
- },
- [PORT_OCTEON] = {
- .name = "OCTEON",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO,
- },
- [PORT_AR7] = {
- .name = "AR7",
- .fifo_size = 16,
- .tx_loadsz = 16,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
- [PORT_U6_16550A] = {
- .name = "U6_16550A",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
- [PORT_TEGRA] = {
- .name = "Tegra",
- .fifo_size = 32,
- .tx_loadsz = 8,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
- UART_FCR_T_TRIG_01,
- .rxtrig_bytes = {1, 4, 8, 14},
- .flags = UART_CAP_FIFO | UART_CAP_RTOIE,
- },
- [PORT_XR17D15X] = {
- .name = "XR17D15X",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
- UART_CAP_SLEEP,
- },
- [PORT_XR17V35X] = {
- .name = "XR17V35X",
- .fifo_size = 256,
- .tx_loadsz = 256,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
- UART_FCR_T_TRIG_11,
- .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
- UART_CAP_SLEEP,
- },
- [PORT_LPC3220] = {
- .name = "LPC3220",
- .fifo_size = 64,
- .tx_loadsz = 32,
- .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
- UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
- .flags = UART_CAP_FIFO,
- },
- [PORT_BRCM_TRUMANAGE] = {
- .name = "TruManage",
- .fifo_size = 1,
- .tx_loadsz = 1024,
- .flags = UART_CAP_HFIFO,
- },
- [PORT_8250_CIR] = {
- .name = "CIR port"
- },
- [PORT_ALTR_16550_F32] = {
- .name = "Altera 16550 FIFO32",
- .fifo_size = 32,
- .tx_loadsz = 32,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
- [PORT_ALTR_16550_F64] = {
- .name = "Altera 16550 FIFO64",
- .fifo_size = 64,
- .tx_loadsz = 64,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
- [PORT_ALTR_16550_F128] = {
- .name = "Altera 16550 FIFO128",
- .fifo_size = 128,
- .tx_loadsz = 128,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
-/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement
-workaround of errata A-008006 which states that tx_loadsz should be
-configured less than Maximum supported fifo bytes */
- [PORT_16550A_FSL64] = {
- .name = "16550A_FSL64",
- .fifo_size = 64,
- .tx_loadsz = 63,
- .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
- UART_FCR7_64BYTE,
- .flags = UART_CAP_FIFO,
- },
-};
-
-/* Uart divisor latch read */
-static int default_serial_dl_read(struct uart_8250_port *up)
-{
- return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
-}
-
-/* Uart divisor latch write */
-static void default_serial_dl_write(struct uart_8250_port *up, int value)
-{
- serial_out(up, UART_DLL, value & 0xff);
- serial_out(up, UART_DLM, value >> 8 & 0xff);
-}
-
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
-
-/* Au1x00/RT288x UART hardware has a weird register layout */
-static const s8 au_io_in_map[8] = {
- 0, /* UART_RX */
- 2, /* UART_IER */
- 3, /* UART_IIR */
- 5, /* UART_LCR */
- 6, /* UART_MCR */
- 7, /* UART_LSR */
- 8, /* UART_MSR */
- -1, /* UART_SCR (unmapped) */
-};
-
-static const s8 au_io_out_map[8] = {
- 1, /* UART_TX */
- 2, /* UART_IER */
- 4, /* UART_FCR */
- 5, /* UART_LCR */
- 6, /* UART_MCR */
- -1, /* UART_LSR (unmapped) */
- -1, /* UART_MSR (unmapped) */
- -1, /* UART_SCR (unmapped) */
-};
-
-static unsigned int au_serial_in(struct uart_port *p, int offset)
-{
- if (offset >= ARRAY_SIZE(au_io_in_map))
- return UINT_MAX;
- offset = au_io_in_map[offset];
- if (offset < 0)
- return UINT_MAX;
- return __raw_readl(p->membase + (offset << p->regshift));
-}
-
-static void au_serial_out(struct uart_port *p, int offset, int value)
-{
- if (offset >= ARRAY_SIZE(au_io_out_map))
- return;
- offset = au_io_out_map[offset];
- if (offset < 0)
- return;
- __raw_writel(value, p->membase + (offset << p->regshift));
-}
-
-/* Au1x00 haven't got a standard divisor latch */
-static int au_serial_dl_read(struct uart_8250_port *up)
-{
- return __raw_readl(up->port.membase + 0x28);
-}
-
-static void au_serial_dl_write(struct uart_8250_port *up, int value)
-{
- __raw_writel(value, up->port.membase + 0x28);
-}
-
-#endif
-
-static unsigned int hub6_serial_in(struct uart_port *p, int offset)
-{
- offset = offset << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- return inb(p->iobase + 1);
-}
-
-static void hub6_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = offset << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- outb(value, p->iobase + 1);
-}
-
-static unsigned int mem_serial_in(struct uart_port *p, int offset)
-{
- offset = offset << p->regshift;
- return readb(p->membase + offset);
-}
-
-static void mem_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = offset << p->regshift;
- writeb(value, p->membase + offset);
-}
-
-static void mem32_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = offset << p->regshift;
- writel(value, p->membase + offset);
-}
-
-static unsigned int mem32_serial_in(struct uart_port *p, int offset)
-{
- offset = offset << p->regshift;
- return readl(p->membase + offset);
-}
-
-static void mem32be_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = offset << p->regshift;
- iowrite32be(value, p->membase + offset);
-}
-
-static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
-{
- offset = offset << p->regshift;
- return ioread32be(p->membase + offset);
-}
-
-static unsigned int io_serial_in(struct uart_port *p, int offset)
-{
- offset = offset << p->regshift;
- return inb(p->iobase + offset);
-}
-
-static void io_serial_out(struct uart_port *p, int offset, int value)
-{
- offset = offset << p->regshift;
- outb(value, p->iobase + offset);
-}
-
-static int serial8250_default_handle_irq(struct uart_port *port);
-static int exar_handle_irq(struct uart_port *port);
-
-static void set_io_from_upio(struct uart_port *p)
-{
- struct uart_8250_port *up = up_to_u8250p(p);
-
- up->dl_read = default_serial_dl_read;
- up->dl_write = default_serial_dl_write;
-
- switch (p->iotype) {
- case UPIO_HUB6:
- p->serial_in = hub6_serial_in;
- p->serial_out = hub6_serial_out;
- break;
-
- case UPIO_MEM:
- p->serial_in = mem_serial_in;
- p->serial_out = mem_serial_out;
- break;
-
- case UPIO_MEM32:
- p->serial_in = mem32_serial_in;
- p->serial_out = mem32_serial_out;
- break;
-
- case UPIO_MEM32BE:
- p->serial_in = mem32be_serial_in;
- p->serial_out = mem32be_serial_out;
- break;
-
-#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
- case UPIO_AU:
- p->serial_in = au_serial_in;
- p->serial_out = au_serial_out;
- up->dl_read = au_serial_dl_read;
- up->dl_write = au_serial_dl_write;
- break;
-#endif
-
- default:
- p->serial_in = io_serial_in;
- p->serial_out = io_serial_out;
- break;
- }
- /* Remember loaded iotype */
- up->cur_iotype = p->iotype;
- p->handle_irq = serial8250_default_handle_irq;
-}
-
-static void
-serial_port_out_sync(struct uart_port *p, int offset, int value)
-{
- switch (p->iotype) {
- case UPIO_MEM:
- case UPIO_MEM32:
- case UPIO_MEM32BE:
- case UPIO_AU:
- p->serial_out(p, offset, value);
- p->serial_in(p, UART_LCR); /* safe, no side-effects */
- break;
- default:
- p->serial_out(p, offset, value);
- }
-}
-
-/*
- * For the 16C950
- */
-static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
-{
- serial_out(up, UART_SCR, offset);
- serial_out(up, UART_ICR, value);
-}
-
-static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
-{
- unsigned int value;
-
- serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
- serial_out(up, UART_SCR, offset);
- value = serial_in(up, UART_ICR);
- serial_icr_write(up, UART_ACR, up->acr);
-
- return value;
-}
-
-/*
- * FIFO support.
- */
-static void serial8250_clear_fifos(struct uart_8250_port *p)
-{
- if (p->capabilities & UART_CAP_FIFO) {
- serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_out(p, UART_FCR, 0);
- }
-}
-
-void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
-{
- serial8250_clear_fifos(p);
- serial_out(p, UART_FCR, p->fcr);
-}
-EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
-
-void serial8250_rpm_get(struct uart_8250_port *p)
-{
- if (!(p->capabilities & UART_CAP_RPM))
- return;
- pm_runtime_get_sync(p->port.dev);
-}
-EXPORT_SYMBOL_GPL(serial8250_rpm_get);
-
-void serial8250_rpm_put(struct uart_8250_port *p)
-{
- if (!(p->capabilities & UART_CAP_RPM))
- return;
- pm_runtime_mark_last_busy(p->port.dev);
- pm_runtime_put_autosuspend(p->port.dev);
-}
-EXPORT_SYMBOL_GPL(serial8250_rpm_put);
-
-/*
- * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
- * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
- * empty and the HW can idle again.
- */
-static void serial8250_rpm_get_tx(struct uart_8250_port *p)
-{
- unsigned char rpm_active;
-
- if (!(p->capabilities & UART_CAP_RPM))
- return;
-
- rpm_active = xchg(&p->rpm_tx_active, 1);
- if (rpm_active)
- return;
- pm_runtime_get_sync(p->port.dev);
-}
-
-static void serial8250_rpm_put_tx(struct uart_8250_port *p)
-{
- unsigned char rpm_active;
-
- if (!(p->capabilities & UART_CAP_RPM))
- return;
-
- rpm_active = xchg(&p->rpm_tx_active, 0);
- if (!rpm_active)
- return;
- pm_runtime_mark_last_busy(p->port.dev);
- pm_runtime_put_autosuspend(p->port.dev);
-}
-
-/*
- * IER sleep support. UARTs which have EFRs need the "extended
- * capability" bit enabled. Note that on XR16C850s, we need to
- * reset LCR to write to IER.
- */
-static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
-{
- unsigned char lcr = 0, efr = 0;
- /*
- * Exar UARTs have a SLEEP register that enables or disables
- * each UART to enter sleep mode separately. On the XR17V35x the
- * register is accessible to each UART at the UART_EXAR_SLEEP
- * offset but the UART channel may only write to the corresponding
- * bit.
- */
- serial8250_rpm_get(p);
- if ((p->port.type == PORT_XR17V35X) ||
- (p->port.type == PORT_XR17D15X)) {
- serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
- goto out;
- }
-
- if (p->capabilities & UART_CAP_SLEEP) {
- if (p->capabilities & UART_CAP_EFR) {
- lcr = serial_in(p, UART_LCR);
- efr = serial_in(p, UART_EFR);
- serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(p, UART_EFR, UART_EFR_ECB);
- serial_out(p, UART_LCR, 0);
- }
- serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
- if (p->capabilities & UART_CAP_EFR) {
- serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(p, UART_EFR, efr);
- serial_out(p, UART_LCR, lcr);
- }
- }
-out:
- serial8250_rpm_put(p);
-}
-
-#ifdef CONFIG_SERIAL_8250_RSA
-/*
- * Attempts to turn on the RSA FIFO. Returns zero on failure.
- * We set the port uart clock rate if we succeed.
- */
-static int __enable_rsa(struct uart_8250_port *up)
-{
- unsigned char mode;
- int result;
-
- mode = serial_in(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
-
- if (!result) {
- serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
- mode = serial_in(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
-
- return result;
-}
-
-static void enable_rsa(struct uart_8250_port *up)
-{
- if (up->port.type == PORT_RSA) {
- if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
- spin_lock_irq(&up->port.lock);
- __enable_rsa(up);
- spin_unlock_irq(&up->port.lock);
- }
- if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
- serial_out(up, UART_RSA_FRR, 0);
- }
-}
-
-/*
- * Attempts to turn off the RSA FIFO. Returns zero on failure.
- * It is unknown why interrupts were disabled in here. However,
- * the caller is expected to preserve this behaviour by grabbing
- * the spinlock before calling this function.
- */
-static void disable_rsa(struct uart_8250_port *up)
-{
- unsigned char mode;
- int result;
-
- if (up->port.type == PORT_RSA &&
- up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
- spin_lock_irq(&up->port.lock);
-
- mode = serial_in(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
-
- if (!result) {
- serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
- mode = serial_in(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
- spin_unlock_irq(&up->port.lock);
- }
-}
-#endif /* CONFIG_SERIAL_8250_RSA */
-
-/*
- * This is a quickie test to see how big the FIFO is.
- * It doesn't work at all the time, more's the pity.
- */
-static int size_fifo(struct uart_8250_port *up)
-{
- unsigned char old_fcr, old_mcr, old_lcr;
- unsigned short old_dl;
- int count;
-
- old_lcr = serial_in(up, UART_LCR);
- serial_out(up, UART_LCR, 0);
- old_fcr = serial_in(up, UART_FCR);
- old_mcr = serial_in(up, UART_MCR);
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
- serial_out(up, UART_MCR, UART_MCR_LOOP);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- old_dl = serial_dl_read(up);
- serial_dl_write(up, 0x0001);
- serial_out(up, UART_LCR, 0x03);
- for (count = 0; count < 256; count++)
- serial_out(up, UART_TX, count);
- mdelay(20);/* FIXME - schedule_timeout */
- for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) &&
- (count < 256); count++)
- serial_in(up, UART_RX);
- serial_out(up, UART_FCR, old_fcr);
- serial_out(up, UART_MCR, old_mcr);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_dl_write(up, old_dl);
- serial_out(up, UART_LCR, old_lcr);
-
- return count;
-}
-
-/*
- * Read UART ID using the divisor method - set DLL and DLM to zero
- * and the revision will be in DLL and device type in DLM. We
- * preserve the device state across this.
- */
-static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
-{
- unsigned char old_dll, old_dlm, old_lcr;
- unsigned int id;
-
- old_lcr = serial_in(p, UART_LCR);
- serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
-
- old_dll = serial_in(p, UART_DLL);
- old_dlm = serial_in(p, UART_DLM);
-
- serial_out(p, UART_DLL, 0);
- serial_out(p, UART_DLM, 0);
-
- id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8;
-
- serial_out(p, UART_DLL, old_dll);
- serial_out(p, UART_DLM, old_dlm);
- serial_out(p, UART_LCR, old_lcr);
-
- return id;
-}
-
-/*
- * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
- * When this function is called we know it is at least a StarTech
- * 16650 V2, but it might be one of several StarTech UARTs, or one of
- * its clones. (We treat the broken original StarTech 16650 V1 as a
- * 16550, and why not? Startech doesn't seem to even acknowledge its
- * existence.)
- *
- * What evil have men's minds wrought...
- */
-static void autoconfig_has_efr(struct uart_8250_port *up)
-{
- unsigned int id1, id2, id3, rev;
-
- /*
- * Everything with an EFR has SLEEP
- */
- up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
-
- /*
- * First we check to see if it's an Oxford Semiconductor UART.
- *
- * If we have to do this here because some non-National
- * Semiconductor clone chips lock up if you try writing to the
- * LSR register (which serial_icr_read does)
- */
-
- /*
- * Check for Oxford Semiconductor 16C950.
- *
- * EFR [4] must be set else this test fails.
- *
- * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
- * claims that it's needed for 952 dual UART's (which are not
- * recommended for new designs).
- */
- up->acr = 0;
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, UART_EFR_ECB);
- serial_out(up, UART_LCR, 0x00);
- id1 = serial_icr_read(up, UART_ID1);
- id2 = serial_icr_read(up, UART_ID2);
- id3 = serial_icr_read(up, UART_ID3);
- rev = serial_icr_read(up, UART_REV);
-
- DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
-
- if (id1 == 0x16 && id2 == 0xC9 &&
- (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
- up->port.type = PORT_16C950;
-
- /*
- * Enable work around for the Oxford Semiconductor 952 rev B
- * chip which causes it to seriously miscalculate baud rates
- * when DLL is 0.
- */
- if (id3 == 0x52 && rev == 0x01)
- up->bugs |= UART_BUG_QUOT;
- return;
- }
-
- /*
- * We check for a XR16C850 by setting DLL and DLM to 0, and then
- * reading back DLL and DLM. The chip type depends on the DLM
- * value read back:
- * 0x10 - XR16C850 and the DLL contains the chip revision.
- * 0x12 - XR16C2850.
- * 0x14 - XR16C854.
- */
- id1 = autoconfig_read_divisor_id(up);
- DEBUG_AUTOCONF("850id=%04x ", id1);
-
- id2 = id1 >> 8;
- if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
- up->port.type = PORT_16850;
- return;
- }
-
- /*
- * It wasn't an XR16C850.
- *
- * We distinguish between the '654 and the '650 by counting
- * how many bytes are in the FIFO. I'm using this for now,
- * since that's the technique that was sent to me in the
- * serial driver update, but I'm not convinced this works.
- * I've had problems doing this in the past. -TYT
- */
- if (size_fifo(up) == 64)
- up->port.type = PORT_16654;
- else
- up->port.type = PORT_16650V2;
-}
-
-/*
- * We detected a chip without a FIFO. Only two fall into
- * this category - the original 8250 and the 16450. The
- * 16450 has a scratch register (accessible with LCR=0)
- */
-static void autoconfig_8250(struct uart_8250_port *up)
-{
- unsigned char scratch, status1, status2;
-
- up->port.type = PORT_8250;
-
- scratch = serial_in(up, UART_SCR);
- serial_out(up, UART_SCR, 0xa5);
- status1 = serial_in(up, UART_SCR);
- serial_out(up, UART_SCR, 0x5a);
- status2 = serial_in(up, UART_SCR);
- serial_out(up, UART_SCR, scratch);
-
- if (status1 == 0xa5 && status2 == 0x5a)
- up->port.type = PORT_16450;
-}
-
-static int broken_efr(struct uart_8250_port *up)
-{
- /*
- * Exar ST16C2550 "A2" devices incorrectly detect as
- * having an EFR, and report an ID of 0x0201. See
- * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
- */
- if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
- return 1;
-
- return 0;
-}
-
-/*
- * We know that the chip has FIFOs. Does it have an EFR? The
- * EFR is located in the same register position as the IIR and
- * we know the top two bits of the IIR are currently set. The
- * EFR should contain zero. Try to read the EFR.
- */
-static void autoconfig_16550a(struct uart_8250_port *up)
-{
- unsigned char status1, status2;
- unsigned int iersave;
-
- up->port.type = PORT_16550A;
- up->capabilities |= UART_CAP_FIFO;
-
- /*
- * XR17V35x UARTs have an extra divisor register, DLD
- * that gets enabled with when DLAB is set which will
- * cause the device to incorrectly match and assign
- * port type to PORT_16650. The EFR for this UART is
- * found at offset 0x09. Instead check the Deice ID (DVID)
- * register for a 2, 4 or 8 port UART.
- */
- if (up->port.flags & UPF_EXAR_EFR) {
- status1 = serial_in(up, UART_EXAR_DVID);
- if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
- DEBUG_AUTOCONF("Exar XR17V35x ");
- up->port.type = PORT_XR17V35X;
- up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
- UART_CAP_SLEEP;
-
- return;
- }
-
- }
-
- /*
- * Check for presence of the EFR when DLAB is set.
- * Only ST16C650V1 UARTs pass this test.
- */
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- if (serial_in(up, UART_EFR) == 0) {
- serial_out(up, UART_EFR, 0xA8);
- if (serial_in(up, UART_EFR) != 0) {
- DEBUG_AUTOCONF("EFRv1 ");
- up->port.type = PORT_16650;
- up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
- } else {
- serial_out(up, UART_LCR, 0);
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
- UART_FCR7_64BYTE);
- status1 = serial_in(up, UART_IIR) >> 5;
- serial_out(up, UART_FCR, 0);
- serial_out(up, UART_LCR, 0);
-
- if (status1 == 7)
- up->port.type = PORT_16550A_FSL64;
- else
- DEBUG_AUTOCONF("Motorola 8xxx DUART ");
- }
- serial_out(up, UART_EFR, 0);
- return;
- }
-
- /*
- * Maybe it requires 0xbf to be written to the LCR.
- * (other ST16C650V2 UARTs, TI16C752A, etc)
- */
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
- DEBUG_AUTOCONF("EFRv2 ");
- autoconfig_has_efr(up);
- return;
- }
-
- /*
- * Check for a National Semiconductor SuperIO chip.
- * Attempt to switch to bank 2, read the value of the LOOP bit
- * from EXCR1. Switch back to bank 0, change it in MCR. Then
- * switch back to bank 2, read it from EXCR1 again and check
- * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
- */
- serial_out(up, UART_LCR, 0);
- status1 = serial_in(up, UART_MCR);
- serial_out(up, UART_LCR, 0xE0);
- status2 = serial_in(up, 0x02); /* EXCR1 */
-
- if (!((status2 ^ status1) & UART_MCR_LOOP)) {
- serial_out(up, UART_LCR, 0);
- serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP);
- serial_out(up, UART_LCR, 0xE0);
- status2 = serial_in(up, 0x02); /* EXCR1 */
- serial_out(up, UART_LCR, 0);
- serial_out(up, UART_MCR, status1);
-
- if ((status2 ^ status1) & UART_MCR_LOOP) {
- unsigned short quot;
-
- serial_out(up, UART_LCR, 0xE0);
-
- quot = serial_dl_read(up);
- quot <<= 3;
-
- if (ns16550a_goto_highspeed(up))
- serial_dl_write(up, quot);
-
- serial_out(up, UART_LCR, 0);
-
- up->port.uartclk = 921600*16;
- up->port.type = PORT_NS16550A;
- up->capabilities |= UART_NATSEMI;
- return;
- }
- }
-
- /*
- * No EFR. Try to detect a TI16750, which only sets bit 5 of
- * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
- * Try setting it with and without DLAB set. Cheap clones
- * set bit 5 without DLAB set.
- */
- serial_out(up, UART_LCR, 0);
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
- status1 = serial_in(up, UART_IIR) >> 5;
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
- status2 = serial_in(up, UART_IIR) >> 5;
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_out(up, UART_LCR, 0);
-
- DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
-
- if (status1 == 6 && status2 == 7) {
- up->port.type = PORT_16750;
- up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
- return;
- }
-
- /*
- * Try writing and reading the UART_IER_UUE bit (b6).
- * If it works, this is probably one of the Xscale platform's
- * internal UARTs.
- * We're going to explicitly set the UUE bit to 0 before
- * trying to write and read a 1 just to make sure it's not
- * already a 1 and maybe locked there before we even start start.
- */
- iersave = serial_in(up, UART_IER);
- serial_out(up, UART_IER, iersave & ~UART_IER_UUE);
- if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
- /*
- * OK it's in a known zero state, try writing and reading
- * without disturbing the current state of the other bits.
- */
- serial_out(up, UART_IER, iersave | UART_IER_UUE);
- if (serial_in(up, UART_IER) & UART_IER_UUE) {
- /*
- * It's an Xscale.
- * We'll leave the UART_IER_UUE bit set to 1 (enabled).
- */
- DEBUG_AUTOCONF("Xscale ");
- up->port.type = PORT_XSCALE;
- up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
- return;
- }
- } else {
- /*
- * If we got here we couldn't force the IER_UUE bit to 0.
- * Log it and continue.
- */
- DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
- }
- serial_out(up, UART_IER, iersave);
-
- /*
- * Exar uarts have EFR in a weird location
- */
- if (up->port.flags & UPF_EXAR_EFR) {
- DEBUG_AUTOCONF("Exar XR17D15x ");
- up->port.type = PORT_XR17D15X;
- up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
- UART_CAP_SLEEP;
-
- return;
- }
-
- /*
- * We distinguish between 16550A and U6 16550A by counting
- * how many bytes are in the FIFO.
- */
- if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
- up->port.type = PORT_U6_16550A;
- up->capabilities |= UART_CAP_AFE;
- }
-}
-
-/*
- * This routine is called by rs_init() to initialize a specific serial
- * port. It determines what type of UART chip this serial port is
- * using: 8250, 16450, 16550, 16550A. The important question is
- * whether or not this UART is a 16550A or not, since this will
- * determine whether or not we can use its FIFO features or not.
- */
-static void autoconfig(struct uart_8250_port *up)
-{
- unsigned char status1, scratch, scratch2, scratch3;
- unsigned char save_lcr, save_mcr;
- struct uart_port *port = &up->port;
- unsigned long flags;
- unsigned int old_capabilities;
-
- if (!port->iobase && !port->mapbase && !port->membase)
- return;
-
- DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
- serial_index(port), port->iobase, port->membase);
-
- /*
- * We really do need global IRQs disabled here - we're going to
- * be frobbing the chips IRQ enable register to see if it exists.
- */
- spin_lock_irqsave(&port->lock, flags);
-
- up->capabilities = 0;
- up->bugs = 0;
-
- if (!(port->flags & UPF_BUGGY_UART)) {
- /*
- * Do a simple existence test first; if we fail this,
- * there's no point trying anything else.
- *
- * 0x80 is used as a nonsense port to prevent against
- * false positives due to ISA bus float. The
- * assumption is that 0x80 is a non-existent port;
- * which should be safe since include/asm/io.h also
- * makes this assumption.
- *
- * Note: this is safe as long as MCR bit 4 is clear
- * and the device is in "PC" mode.
- */
- scratch = serial_in(up, UART_IER);
- serial_out(up, UART_IER, 0);
-#ifdef __i386__
- outb(0xff, 0x080);
-#endif
- /*
- * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
- * 16C754B) allow only to modify them if an EFR bit is set.
- */
- scratch2 = serial_in(up, UART_IER) & 0x0f;
- serial_out(up, UART_IER, 0x0F);
-#ifdef __i386__
- outb(0, 0x080);
-#endif
- scratch3 = serial_in(up, UART_IER) & 0x0f;
- serial_out(up, UART_IER, scratch);
- if (scratch2 != 0 || scratch3 != 0x0F) {
- /*
- * We failed; there's nothing here
- */
- spin_unlock_irqrestore(&port->lock, flags);
- DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
- scratch2, scratch3);
- goto out;
- }
- }
-
- save_mcr = serial_in(up, UART_MCR);
- save_lcr = serial_in(up, UART_LCR);
-
- /*
- * Check to see if a UART is really there. Certain broken
- * internal modems based on the Rockwell chipset fail this
- * test, because they apparently don't implement the loopback
- * test mode. So this test is skipped on the COM 1 through
- * COM 4 ports. This *should* be safe, since no board
- * manufacturer would be stupid enough to design a board
- * that conflicts with COM 1-4 --- we hope!
- */
- if (!(port->flags & UPF_SKIP_TEST)) {
- serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
- status1 = serial_in(up, UART_MSR) & 0xF0;
- serial_out(up, UART_MCR, save_mcr);
- if (status1 != 0x90) {
- spin_unlock_irqrestore(&port->lock, flags);
- DEBUG_AUTOCONF("LOOP test failed (%02x) ",
- status1);
- goto out;
- }
- }
-
- /*
- * We're pretty sure there's a port here. Lets find out what
- * type of port it is. The IIR top two bits allows us to find
- * out if it's 8250 or 16450, 16550, 16550A or later. This
- * determines what we test for next.
- *
- * We also initialise the EFR (if any) to zero for later. The
- * EFR occupies the same register location as the FCR and IIR.
- */
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_out(up, UART_EFR, 0);
- serial_out(up, UART_LCR, 0);
-
- serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
- scratch = serial_in(up, UART_IIR) >> 6;
-
- switch (scratch) {
- case 0:
- autoconfig_8250(up);
- break;
- case 1:
- port->type = PORT_UNKNOWN;
- break;
- case 2:
- port->type = PORT_16550;
- break;
- case 3:
- autoconfig_16550a(up);
- break;
- }
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * Only probe for RSA ports if we got the region.
- */
- if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
- __enable_rsa(up))
- port->type = PORT_RSA;
-#endif
-
- serial_out(up, UART_LCR, save_lcr);
-
- port->fifosize = uart_config[up->port.type].fifo_size;
- old_capabilities = up->capabilities;
- up->capabilities = uart_config[port->type].flags;
- up->tx_loadsz = uart_config[port->type].tx_loadsz;
-
- if (port->type == PORT_UNKNOWN)
- goto out_lock;
-
- /*
- * Reset the UART.
- */
-#ifdef CONFIG_SERIAL_8250_RSA
- if (port->type == PORT_RSA)
- serial_out(up, UART_RSA_FRR, 0);
-#endif
- serial_out(up, UART_MCR, save_mcr);
- serial8250_clear_fifos(up);
- serial_in(up, UART_RX);
- if (up->capabilities & UART_CAP_UUE)
- serial_out(up, UART_IER, UART_IER_UUE);
- else
- serial_out(up, UART_IER, 0);
-
-out_lock:
- spin_unlock_irqrestore(&port->lock, flags);
- if (up->capabilities != old_capabilities) {
- printk(KERN_WARNING
- "ttyS%d: detected caps %08x should be %08x\n",
- serial_index(port), old_capabilities,
- up->capabilities);
- }
-out:
- DEBUG_AUTOCONF("iir=%d ", scratch);
- DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name);
-}
-
-static void autoconfig_irq(struct uart_8250_port *up)
-{
- struct uart_port *port = &up->port;
- unsigned char save_mcr, save_ier;
- unsigned char save_ICP = 0;
- unsigned int ICP = 0;
- unsigned long irqs;
- int irq;
-
- if (port->flags & UPF_FOURPORT) {
- ICP = (port->iobase & 0xfe0) | 0x1f;
- save_ICP = inb_p(ICP);
- outb_p(0x80, ICP);
- inb_p(ICP);
- }
-
- /* forget possible initially masked and pending IRQ */
- probe_irq_off(probe_irq_on());
- save_mcr = serial_in(up, UART_MCR);
- save_ier = serial_in(up, UART_IER);
- serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
-
- irqs = probe_irq_on();
- serial_out(up, UART_MCR, 0);
- udelay(10);
- if (port->flags & UPF_FOURPORT) {
- serial_out(up, UART_MCR,
- UART_MCR_DTR | UART_MCR_RTS);
- } else {
- serial_out(up, UART_MCR,
- UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
- }
- serial_out(up, UART_IER, 0x0f); /* enable all intrs */
- serial_in(up, UART_LSR);
- serial_in(up, UART_RX);
- serial_in(up, UART_IIR);
- serial_in(up, UART_MSR);
- serial_out(up, UART_TX, 0xFF);
- udelay(20);
- irq = probe_irq_off(irqs);
-
- serial_out(up, UART_MCR, save_mcr);
- serial_out(up, UART_IER, save_ier);
-
- if (port->flags & UPF_FOURPORT)
- outb_p(save_ICP, ICP);
-
- port->irq = (irq > 0) ? irq : 0;
-}
-
-static inline void __stop_tx(struct uart_8250_port *p)
-{
- if (p->ier & UART_IER_THRI) {
- p->ier &= ~UART_IER_THRI;
- serial_out(p, UART_IER, p->ier);
- serial8250_rpm_put_tx(p);
- }
-}
-
-static void serial8250_stop_tx(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
-
- serial8250_rpm_get(up);
- __stop_tx(up);
-
- /*
- * We really want to stop the transmitter from sending.
- */
- if (port->type == PORT_16C950) {
- up->acr |= UART_ACR_TXDIS;
- serial_icr_write(up, UART_ACR, up->acr);
- }
- serial8250_rpm_put(up);
-}
-
-static void serial8250_start_tx(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
-
- serial8250_rpm_get_tx(up);
-
- if (up->dma && !up->dma->tx_dma(up))
- return;
-
- if (!(up->ier & UART_IER_THRI)) {
- up->ier |= UART_IER_THRI;
- serial_port_out(port, UART_IER, up->ier);
-
- if (up->bugs & UART_BUG_TXEN) {
- unsigned char lsr;
- lsr = serial_in(up, UART_LSR);
- up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
- if (lsr & UART_LSR_THRE)
- serial8250_tx_chars(up);
- }
- }
-
- /*
- * Re-enable the transmitter if we disabled it.
- */
- if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
- up->acr &= ~UART_ACR_TXDIS;
- serial_icr_write(up, UART_ACR, up->acr);
- }
-}
-
-static void serial8250_throttle(struct uart_port *port)
-{
- port->throttle(port);
-}
-
-static void serial8250_unthrottle(struct uart_port *port)
-{
- port->unthrottle(port);
-}
-
-static void serial8250_stop_rx(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
-
- serial8250_rpm_get(up);
-
- up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
- up->port.read_status_mask &= ~UART_LSR_DR;
- serial_port_out(port, UART_IER, up->ier);
-
- serial8250_rpm_put(up);
-}
-
-static void serial8250_disable_ms(struct uart_port *port)
-{
- struct uart_8250_port *up =
- container_of(port, struct uart_8250_port, port);
-
- /* no MSR capabilities */
- if (up->bugs & UART_BUG_NOMSR)
- return;
-
- up->ier &= ~UART_IER_MSI;
- serial_port_out(port, UART_IER, up->ier);
-}
-
-static void serial8250_enable_ms(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
-
- /* no MSR capabilities */
- if (up->bugs & UART_BUG_NOMSR)
- return;
-
- up->ier |= UART_IER_MSI;
-
- serial8250_rpm_get(up);
- serial_port_out(port, UART_IER, up->ier);
- serial8250_rpm_put(up);
-}
-
-/*
- * serial8250_rx_chars: processes according to the passed in LSR
- * value, and returns the remaining LSR bits not handled
- * by this Rx routine.
- */
-unsigned char
-serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
-{
- struct uart_port *port = &up->port;
- unsigned char ch;
- int max_count = 256;
- char flag;
-
- do {
- if (likely(lsr & UART_LSR_DR))
- ch = serial_in(up, UART_RX);
- else
- /*
- * Intel 82571 has a Serial Over Lan device that will
- * set UART_LSR_BI without setting UART_LSR_DR when
- * it receives a break. To avoid reading from the
- * receive buffer without UART_LSR_DR bit set, we
- * just force the read character to be 0
- */
- ch = 0;
-
- flag = TTY_NORMAL;
- port->icount.rx++;
-
- lsr |= up->lsr_saved_flags;
- up->lsr_saved_flags = 0;
-
- if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
- if (lsr & UART_LSR_BI) {
- lsr &= ~(UART_LSR_FE | UART_LSR_PE);
- port->icount.brk++;
- /*
- * We do the SysRQ and SAK checking
- * here because otherwise the break
- * may get masked by ignore_status_mask
- * or read_status_mask.
- */
- if (uart_handle_break(port))
- goto ignore_char;
- } else if (lsr & UART_LSR_PE)
- port->icount.parity++;
- else if (lsr & UART_LSR_FE)
- port->icount.frame++;
- if (lsr & UART_LSR_OE)
- port->icount.overrun++;
-
- /*
- * Mask off conditions which should be ignored.
- */
- lsr &= port->read_status_mask;
-
- if (lsr & UART_LSR_BI) {
- DEBUG_INTR("handling break....");
- flag = TTY_BREAK;
- } else if (lsr & UART_LSR_PE)
- flag = TTY_PARITY;
- else if (lsr & UART_LSR_FE)
- flag = TTY_FRAME;
- }
- if (uart_handle_sysrq_char(port, ch))
- goto ignore_char;
-
- uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
-
-ignore_char:
- lsr = serial_in(up, UART_LSR);
- } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0));
- spin_unlock(&port->lock);
- tty_flip_buffer_push(&port->state->port);
- spin_lock(&port->lock);
- return lsr;
-}
-EXPORT_SYMBOL_GPL(serial8250_rx_chars);
-
-void serial8250_tx_chars(struct uart_8250_port *up)
-{
- struct uart_port *port = &up->port;
- struct circ_buf *xmit = &port->state->xmit;
- int count;
-
- if (port->x_char) {
- serial_out(up, UART_TX, port->x_char);
- port->icount.tx++;
- port->x_char = 0;
- return;
- }
- if (uart_tx_stopped(port)) {
- serial8250_stop_tx(port);
- return;
- }
- if (uart_circ_empty(xmit)) {
- __stop_tx(up);
- return;
- }
-
- count = up->tx_loadsz;
- do {
- serial_out(up, UART_TX, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- if (uart_circ_empty(xmit))
- break;
- if (up->capabilities & UART_CAP_HFIFO) {
- if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
- BOTH_EMPTY)
- break;
- }
- } while (--count > 0);
-
- if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
- uart_write_wakeup(port);
-
- DEBUG_INTR("THRE...");
-
- /*
- * With RPM enabled, we have to wait until the FIFO is empty before the
- * HW can go idle. So we get here once again with empty FIFO and disable
- * the interrupt and RPM in __stop_tx()
- */
- if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
- __stop_tx(up);
-}
-EXPORT_SYMBOL_GPL(serial8250_tx_chars);
-
-/* Caller holds uart port lock */
-unsigned int serial8250_modem_status(struct uart_8250_port *up)
-{
- struct uart_port *port = &up->port;
- unsigned int status = serial_in(up, UART_MSR);
-
- status |= up->msr_saved_flags;
- up->msr_saved_flags = 0;
- if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
- port->state != NULL) {
- if (status & UART_MSR_TERI)
- port->icount.rng++;
- if (status & UART_MSR_DDSR)
- port->icount.dsr++;
- if (status & UART_MSR_DDCD)
- uart_handle_dcd_change(port, status & UART_MSR_DCD);
- if (status & UART_MSR_DCTS)
- uart_handle_cts_change(port, status & UART_MSR_CTS);
-
- wake_up_interruptible(&port->state->port.delta_msr_wait);
- }
-
- return status;
-}
-EXPORT_SYMBOL_GPL(serial8250_modem_status);
-
-/*
- * This handles the interrupt from one port.
- */
-int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
-{
- unsigned char status;
- unsigned long flags;
- struct uart_8250_port *up = up_to_u8250p(port);
- int dma_err = 0;
-
- if (iir & UART_IIR_NO_INT)
- return 0;
-
- spin_lock_irqsave(&port->lock, flags);
-
- status = serial_port_in(port, UART_LSR);
-
- DEBUG_INTR("status = %x...", status);
-
- if (status & (UART_LSR_DR | UART_LSR_BI)) {
- if (up->dma)
- dma_err = up->dma->rx_dma(up, iir);
-
- if (!up->dma || dma_err)
- status = serial8250_rx_chars(up, status);
- }
- serial8250_modem_status(up);
- if ((!up->dma || (up->dma && up->dma->tx_err)) &&
- (status & UART_LSR_THRE))
- serial8250_tx_chars(up);
-
- spin_unlock_irqrestore(&port->lock, flags);
- return 1;
-}
-EXPORT_SYMBOL_GPL(serial8250_handle_irq);
-
-static int serial8250_default_handle_irq(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned int iir;
- int ret;
-
- serial8250_rpm_get(up);
-
- iir = serial_port_in(port, UART_IIR);
- ret = serial8250_handle_irq(port, iir);
-
- serial8250_rpm_put(up);
- return ret;
-}
-
-/*
- * These Exar UARTs have an extra interrupt indicator that could
- * fire for a few unimplemented interrupts. One of which is a
- * wakeup event when coming out of sleep. Put this here just
- * to be on the safe side that these interrupts don't go unhandled.
- */
-static int exar_handle_irq(struct uart_port *port)
-{
- unsigned char int0, int1, int2, int3;
- unsigned int iir = serial_port_in(port, UART_IIR);
- int ret;
-
- ret = serial8250_handle_irq(port, iir);
-
- if ((port->type == PORT_XR17V35X) ||
- (port->type == PORT_XR17D15X)) {
- int0 = serial_port_in(port, 0x80);
- int1 = serial_port_in(port, 0x81);
- int2 = serial_port_in(port, 0x82);
- int3 = serial_port_in(port, 0x83);
- }
-
- return ret;
-}
-
-/*
* This is the serial driver's interrupt routine.
*
* Arjan thinks the old way was overly complex, so it got simplified.
@@ -1941,876 +359,6 @@
serial_unlink_irq_chain(up);
}
-static unsigned int serial8250_tx_empty(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned long flags;
- unsigned int lsr;
-
- serial8250_rpm_get(up);
-
- spin_lock_irqsave(&port->lock, flags);
- lsr = serial_port_in(port, UART_LSR);
- up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
- spin_unlock_irqrestore(&port->lock, flags);
-
- serial8250_rpm_put(up);
-
- return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
-}
-
-static unsigned int serial8250_get_mctrl(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned int status;
- unsigned int ret;
-
- serial8250_rpm_get(up);
- status = serial8250_modem_status(up);
- serial8250_rpm_put(up);
-
- ret = 0;
- if (status & UART_MSR_DCD)
- ret |= TIOCM_CAR;
- if (status & UART_MSR_RI)
- ret |= TIOCM_RNG;
- if (status & UART_MSR_DSR)
- ret |= TIOCM_DSR;
- if (status & UART_MSR_CTS)
- ret |= TIOCM_CTS;
- return ret;
-}
-
-void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned char mcr = 0;
-
- if (mctrl & TIOCM_RTS)
- mcr |= UART_MCR_RTS;
- if (mctrl & TIOCM_DTR)
- mcr |= UART_MCR_DTR;
- if (mctrl & TIOCM_OUT1)
- mcr |= UART_MCR_OUT1;
- if (mctrl & TIOCM_OUT2)
- mcr |= UART_MCR_OUT2;
- if (mctrl & TIOCM_LOOP)
- mcr |= UART_MCR_LOOP;
-
- mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
-
- serial_port_out(port, UART_MCR, mcr);
-}
-EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
-
-static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
-{
- if (port->set_mctrl)
- port->set_mctrl(port, mctrl);
- else
- serial8250_do_set_mctrl(port, mctrl);
-}
-
-static void serial8250_break_ctl(struct uart_port *port, int break_state)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned long flags;
-
- serial8250_rpm_get(up);
- spin_lock_irqsave(&port->lock, flags);
- if (break_state == -1)
- up->lcr |= UART_LCR_SBC;
- else
- up->lcr &= ~UART_LCR_SBC;
- serial_port_out(port, UART_LCR, up->lcr);
- spin_unlock_irqrestore(&port->lock, flags);
- serial8250_rpm_put(up);
-}
-
-/*
- * Wait for transmitter & holding register to empty
- */
-static void wait_for_xmitr(struct uart_8250_port *up, int bits)
-{
- unsigned int status, tmout = 10000;
-
- /* Wait up to 10ms for the character(s) to be sent. */
- for (;;) {
- status = serial_in(up, UART_LSR);
-
- up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
-
- if ((status & bits) == bits)
- break;
- if (--tmout == 0)
- break;
- udelay(1);
- }
-
- /* Wait up to 1s for flow control if necessary */
- if (up->port.flags & UPF_CONS_FLOW) {
- unsigned int tmout;
- for (tmout = 1000000; tmout; tmout--) {
- unsigned int msr = serial_in(up, UART_MSR);
- up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
- if (msr & UART_MSR_CTS)
- break;
- udelay(1);
- touch_nmi_watchdog();
- }
- }
-}
-
-#ifdef CONFIG_CONSOLE_POLL
-/*
- * Console polling routines for writing and reading from the uart while
- * in an interrupt or debug context.
- */
-
-static int serial8250_get_poll_char(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned char lsr;
- int status;
-
- serial8250_rpm_get(up);
-
- lsr = serial_port_in(port, UART_LSR);
-
- if (!(lsr & UART_LSR_DR)) {
- status = NO_POLL_CHAR;
- goto out;
- }
-
- status = serial_port_in(port, UART_RX);
-out:
- serial8250_rpm_put(up);
- return status;
-}
-
-
-static void serial8250_put_poll_char(struct uart_port *port,
- unsigned char c)
-{
- unsigned int ier;
- struct uart_8250_port *up = up_to_u8250p(port);
-
- serial8250_rpm_get(up);
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_port_in(port, UART_IER);
- if (up->capabilities & UART_CAP_UUE)
- serial_port_out(port, UART_IER, UART_IER_UUE);
- else
- serial_port_out(port, UART_IER, 0);
-
- wait_for_xmitr(up, BOTH_EMPTY);
- /*
- * Send the character out.
- */
- serial_port_out(port, UART_TX, c);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up, BOTH_EMPTY);
- serial_port_out(port, UART_IER, ier);
- serial8250_rpm_put(up);
-}
-
-#endif /* CONFIG_CONSOLE_POLL */
-
-int serial8250_do_startup(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned long flags;
- unsigned char lsr, iir;
- int retval;
-
- if (port->type == PORT_8250_CIR)
- return -ENODEV;
-
- if (!port->fifosize)
- port->fifosize = uart_config[port->type].fifo_size;
- if (!up->tx_loadsz)
- up->tx_loadsz = uart_config[port->type].tx_loadsz;
- if (!up->capabilities)
- up->capabilities = uart_config[port->type].flags;
- up->mcr = 0;
-
- if (port->iotype != up->cur_iotype)
- set_io_from_upio(port);
-
- serial8250_rpm_get(up);
- if (port->type == PORT_16C950) {
- /* Wake up and initialize UART */
- up->acr = 0;
- serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_port_out(port, UART_EFR, UART_EFR_ECB);
- serial_port_out(port, UART_IER, 0);
- serial_port_out(port, UART_LCR, 0);
- serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
- serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
- serial_port_out(port, UART_EFR, UART_EFR_ECB);
- serial_port_out(port, UART_LCR, 0);
- }
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * If this is an RSA port, see if we can kick it up to the
- * higher speed clock.
- */
- enable_rsa(up);
-#endif
- /*
- * Clear the FIFO buffers and disable them.
- * (they will be reenabled in set_termios())
- */
- serial8250_clear_fifos(up);
-
- /*
- * Clear the interrupt registers.
- */
- serial_port_in(port, UART_LSR);
- serial_port_in(port, UART_RX);
- serial_port_in(port, UART_IIR);
- serial_port_in(port, UART_MSR);
-
- /*
- * At this point, there's no way the LSR could still be 0xff;
- * if it is, then bail out, because there's likely no UART
- * here.
- */
- if (!(port->flags & UPF_BUGGY_UART) &&
- (serial_port_in(port, UART_LSR) == 0xff)) {
- printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
- serial_index(port));
- retval = -ENODEV;
- goto out;
- }
-
- /*
- * For a XR16C850, we need to set the trigger levels
- */
- if (port->type == PORT_16850) {
- unsigned char fctr;
-
- serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
-
- fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
- serial_port_out(port, UART_FCTR,
- fctr | UART_FCTR_TRGD | UART_FCTR_RX);
- serial_port_out(port, UART_TRG, UART_TRG_96);
- serial_port_out(port, UART_FCTR,
- fctr | UART_FCTR_TRGD | UART_FCTR_TX);
- serial_port_out(port, UART_TRG, UART_TRG_96);
-
- serial_port_out(port, UART_LCR, 0);
- }
-
- if (port->irq) {
- unsigned char iir1;
- /*
- * Test for UARTs that do not reassert THRE when the
- * transmitter is idle and the interrupt has already
- * been cleared. Real 16550s should always reassert
- * this interrupt whenever the transmitter is idle and
- * the interrupt is enabled. Delays are necessary to
- * allow register changes to become visible.
- */
- spin_lock_irqsave(&port->lock, flags);
- if (up->port.irqflags & IRQF_SHARED)
- disable_irq_nosync(port->irq);
-
- wait_for_xmitr(up, UART_LSR_THRE);
- serial_port_out_sync(port, UART_IER, UART_IER_THRI);
- udelay(1); /* allow THRE to set */
- iir1 = serial_port_in(port, UART_IIR);
- serial_port_out(port, UART_IER, 0);
- serial_port_out_sync(port, UART_IER, UART_IER_THRI);
- udelay(1); /* allow a working UART time to re-assert THRE */
- iir = serial_port_in(port, UART_IIR);
- serial_port_out(port, UART_IER, 0);
-
- if (port->irqflags & IRQF_SHARED)
- enable_irq(port->irq);
- spin_unlock_irqrestore(&port->lock, flags);
-
- /*
- * If the interrupt is not reasserted, or we otherwise
- * don't trust the iir, setup a timer to kick the UART
- * on a regular basis.
- */
- if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
- up->port.flags & UPF_BUG_THRE) {
- up->bugs |= UART_BUG_THRE;
- }
- }
-
- retval = up->ops->setup_irq(up);
- if (retval)
- goto out;
-
- /*
- * Now, initialize the UART
- */
- serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
-
- spin_lock_irqsave(&port->lock, flags);
- if (up->port.flags & UPF_FOURPORT) {
- if (!up->port.irq)
- up->port.mctrl |= TIOCM_OUT1;
- } else
- /*
- * Most PC uarts need OUT2 raised to enable interrupts.
- */
- if (port->irq)
- up->port.mctrl |= TIOCM_OUT2;
-
- serial8250_set_mctrl(port, port->mctrl);
-
- /* Serial over Lan (SoL) hack:
- Intel 8257x Gigabit ethernet chips have a
- 16550 emulation, to be used for Serial Over Lan.
- Those chips take a longer time than a normal
- serial device to signalize that a transmission
- data was queued. Due to that, the above test generally
- fails. One solution would be to delay the reading of
- iir. However, this is not reliable, since the timeout
- is variable. So, let's just don't test if we receive
- TX irq. This way, we'll never enable UART_BUG_TXEN.
- */
- if (up->port.flags & UPF_NO_TXEN_TEST)
- goto dont_test_tx_en;
-
- /*
- * Do a quick test to see if we receive an
- * interrupt when we enable the TX irq.
- */
- serial_port_out(port, UART_IER, UART_IER_THRI);
- lsr = serial_port_in(port, UART_LSR);
- iir = serial_port_in(port, UART_IIR);
- serial_port_out(port, UART_IER, 0);
-
- if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
- if (!(up->bugs & UART_BUG_TXEN)) {
- up->bugs |= UART_BUG_TXEN;
- pr_debug("ttyS%d - enabling bad tx status workarounds\n",
- serial_index(port));
- }
- } else {
- up->bugs &= ~UART_BUG_TXEN;
- }
-
-dont_test_tx_en:
- spin_unlock_irqrestore(&port->lock, flags);
-
- /*
- * Clear the interrupt registers again for luck, and clear the
- * saved flags to avoid getting false values from polling
- * routines or the previous session.
- */
- serial_port_in(port, UART_LSR);
- serial_port_in(port, UART_RX);
- serial_port_in(port, UART_IIR);
- serial_port_in(port, UART_MSR);
- up->lsr_saved_flags = 0;
- up->msr_saved_flags = 0;
-
- /*
- * Request DMA channels for both RX and TX.
- */
- if (up->dma) {
- retval = serial8250_request_dma(up);
- if (retval) {
- pr_warn_ratelimited("ttyS%d - failed to request DMA\n",
- serial_index(port));
- up->dma = NULL;
- }
- }
-
- /*
- * Finally, enable interrupts. Note: Modem status interrupts
- * are set via set_termios(), which will be occurring imminently
- * anyway, so we don't enable them here.
- */
- up->ier = UART_IER_RLSI | UART_IER_RDI;
- serial_port_out(port, UART_IER, up->ier);
-
- if (port->flags & UPF_FOURPORT) {
- unsigned int icp;
- /*
- * Enable interrupts on the AST Fourport board
- */
- icp = (port->iobase & 0xfe0) | 0x01f;
- outb_p(0x80, icp);
- inb_p(icp);
- }
- retval = 0;
-out:
- serial8250_rpm_put(up);
- return retval;
-}
-EXPORT_SYMBOL_GPL(serial8250_do_startup);
-
-static int serial8250_startup(struct uart_port *port)
-{
- if (port->startup)
- return port->startup(port);
- return serial8250_do_startup(port);
-}
-
-void serial8250_do_shutdown(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned long flags;
-
- serial8250_rpm_get(up);
- /*
- * Disable interrupts from this port
- */
- up->ier = 0;
- serial_port_out(port, UART_IER, 0);
-
- if (up->dma)
- serial8250_release_dma(up);
-
- spin_lock_irqsave(&port->lock, flags);
- if (port->flags & UPF_FOURPORT) {
- /* reset interrupts on the AST Fourport board */
- inb((port->iobase & 0xfe0) | 0x1f);
- port->mctrl |= TIOCM_OUT1;
- } else
- port->mctrl &= ~TIOCM_OUT2;
-
- serial8250_set_mctrl(port, port->mctrl);
- spin_unlock_irqrestore(&port->lock, flags);
-
- /*
- * Disable break condition and FIFOs
- */
- serial_port_out(port, UART_LCR,
- serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
- serial8250_clear_fifos(up);
-
-#ifdef CONFIG_SERIAL_8250_RSA
- /*
- * Reset the RSA board back to 115kbps compat mode.
- */
- disable_rsa(up);
-#endif
-
- /*
- * Read data port to reset things, and then unlink from
- * the IRQ chain.
- */
- serial_port_in(port, UART_RX);
- serial8250_rpm_put(up);
-
- up->ops->release_irq(up);
-}
-EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
-
-static void serial8250_shutdown(struct uart_port *port)
-{
- if (port->shutdown)
- port->shutdown(port);
- else
- serial8250_do_shutdown(port);
-}
-
-/*
- * XR17V35x UARTs have an extra fractional divisor register (DLD)
- * Calculate divisor with extra 4-bit fractional portion
- */
-static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up,
- unsigned int baud,
- unsigned int *frac)
-{
- struct uart_port *port = &up->port;
- unsigned int quot_16;
-
- quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud);
- *frac = quot_16 & 0x0f;
-
- return quot_16 >> 4;
-}
-
-static unsigned int serial8250_get_divisor(struct uart_8250_port *up,
- unsigned int baud,
- unsigned int *frac)
-{
- struct uart_port *port = &up->port;
- unsigned int quot;
-
- /*
- * Handle magic divisors for baud rates above baud_base on
- * SMSC SuperIO chips.
- *
- */
- if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/4))
- quot = 0x8001;
- else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
- baud == (port->uartclk/8))
- quot = 0x8002;
- else if (up->port.type == PORT_XR17V35X)
- quot = xr17v35x_get_divisor(up, baud, frac);
- else
- quot = uart_get_divisor(port, baud);
-
- /*
- * Oxford Semi 952 rev B workaround
- */
- if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
- quot++;
-
- return quot;
-}
-
-static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
- tcflag_t c_cflag)
-{
- unsigned char cval;
-
- switch (c_cflag & CSIZE) {
- case CS5:
- cval = UART_LCR_WLEN5;
- break;
- case CS6:
- cval = UART_LCR_WLEN6;
- break;
- case CS7:
- cval = UART_LCR_WLEN7;
- break;
- default:
- case CS8:
- cval = UART_LCR_WLEN8;
- break;
- }
-
- if (c_cflag & CSTOPB)
- cval |= UART_LCR_STOP;
- if (c_cflag & PARENB) {
- cval |= UART_LCR_PARITY;
- if (up->bugs & UART_BUG_PARITY)
- up->fifo_bug = true;
- }
- if (!(c_cflag & PARODD))
- cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
- if (c_cflag & CMSPAR)
- cval |= UART_LCR_SPAR;
-#endif
-
- return cval;
-}
-
-static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
- unsigned int quot, unsigned int quot_frac)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
-
- /* Workaround to enable 115200 baud on OMAP1510 internal ports */
- if (is_omap1510_8250(up)) {
- if (baud == 115200) {
- quot = 1;
- serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
- } else
- serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
- }
-
- /*
- * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
- * otherwise just set DLAB
- */
- if (up->capabilities & UART_NATSEMI)
- serial_port_out(port, UART_LCR, 0xe0);
- else
- serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
-
- serial_dl_write(up, quot);
-
- /* XR17V35x UARTs have an extra fractional divisor register (DLD) */
- if (up->port.type == PORT_XR17V35X)
- serial_port_out(port, 0x2, quot_frac);
-}
-
-void
-serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned char cval;
- unsigned long flags;
- unsigned int baud, quot, frac = 0;
-
- cval = serial8250_compute_lcr(up, termios->c_cflag);
-
- /*
- * Ask the core to calculate the divisor for us.
- */
- baud = uart_get_baud_rate(port, termios, old,
- port->uartclk / 16 / 0xffff,
- port->uartclk / 16);
- quot = serial8250_get_divisor(up, baud, &frac);
-
- /*
- * Ok, we're now changing the port state. Do it with
- * interrupts disabled.
- */
- serial8250_rpm_get(up);
- spin_lock_irqsave(&port->lock, flags);
-
- up->lcr = cval; /* Save computed LCR */
-
- if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
- /* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
- if ((baud < 2400 && !up->dma) || up->fifo_bug) {
- up->fcr &= ~UART_FCR_TRIGGER_MASK;
- up->fcr |= UART_FCR_TRIGGER_1;
- }
- }
-
- /*
- * MCR-based auto flow control. When AFE is enabled, RTS will be
- * deasserted when the receive FIFO contains more characters than
- * the trigger, or the MCR RTS bit is cleared. In the case where
- * the remote UART is not using CTS auto flow control, we must
- * have sufficient FIFO entries for the latency of the remote
- * UART to respond. IOW, at least 32 bytes of FIFO.
- */
- if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
- up->mcr &= ~UART_MCR_AFE;
- if (termios->c_cflag & CRTSCTS)
- up->mcr |= UART_MCR_AFE;
- }
-
- /*
- * Update the per-port timeout.
- */
- uart_update_timeout(port, termios->c_cflag, baud);
-
- port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
- if (termios->c_iflag & INPCK)
- port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
- if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
- port->read_status_mask |= UART_LSR_BI;
-
- /*
- * Characteres to ignore
- */
- port->ignore_status_mask = 0;
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
- if (termios->c_iflag & IGNBRK) {
- port->ignore_status_mask |= UART_LSR_BI;
- /*
- * If we're ignoring parity and break indicators,
- * ignore overruns too (for real raw support).
- */
- if (termios->c_iflag & IGNPAR)
- port->ignore_status_mask |= UART_LSR_OE;
- }
-
- /*
- * ignore all characters if CREAD is not set
- */
- if ((termios->c_cflag & CREAD) == 0)
- port->ignore_status_mask |= UART_LSR_DR;
-
- /*
- * CTS flow control flag and modem status interrupts
- */
- up->ier &= ~UART_IER_MSI;
- if (!(up->bugs & UART_BUG_NOMSR) &&
- UART_ENABLE_MS(&up->port, termios->c_cflag))
- up->ier |= UART_IER_MSI;
- if (up->capabilities & UART_CAP_UUE)
- up->ier |= UART_IER_UUE;
- if (up->capabilities & UART_CAP_RTOIE)
- up->ier |= UART_IER_RTOIE;
-
- serial_port_out(port, UART_IER, up->ier);
-
- if (up->capabilities & UART_CAP_EFR) {
- unsigned char efr = 0;
- /*
- * TI16C752/Startech hardware flow control. FIXME:
- * - TI16C752 requires control thresholds to be set.
- * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
- */
- if (termios->c_cflag & CRTSCTS)
- efr |= UART_EFR_CTS;
-
- serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
- if (port->flags & UPF_EXAR_EFR)
- serial_port_out(port, UART_XR_EFR, efr);
- else
- serial_port_out(port, UART_EFR, efr);
- }
-
- serial8250_set_divisor(port, baud, quot, frac);
-
- /*
- * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
- * is written without DLAB set, this mode will be disabled.
- */
- if (port->type == PORT_16750)
- serial_port_out(port, UART_FCR, up->fcr);
-
- serial_port_out(port, UART_LCR, up->lcr); /* reset DLAB */
- if (port->type != PORT_16750) {
- /* emulated UARTs (Lucent Venus 167x) need two steps */
- if (up->fcr & UART_FCR_ENABLE_FIFO)
- serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
- serial_port_out(port, UART_FCR, up->fcr); /* set fcr */
- }
- serial8250_set_mctrl(port, port->mctrl);
- spin_unlock_irqrestore(&port->lock, flags);
- serial8250_rpm_put(up);
-
- /* Don't rewrite B0 */
- if (tty_termios_baud_rate(termios))
- tty_termios_encode_baud_rate(termios, baud, baud);
-}
-EXPORT_SYMBOL(serial8250_do_set_termios);
-
-static void
-serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
- struct ktermios *old)
-{
- if (port->set_termios)
- port->set_termios(port, termios, old);
- else
- serial8250_do_set_termios(port, termios, old);
-}
-
-static void
-serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
-{
- if (termios->c_line == N_PPS) {
- port->flags |= UPF_HARDPPS_CD;
- spin_lock_irq(&port->lock);
- serial8250_enable_ms(port);
- spin_unlock_irq(&port->lock);
- } else {
- port->flags &= ~UPF_HARDPPS_CD;
- if (!UART_ENABLE_MS(port, termios->c_cflag)) {
- spin_lock_irq(&port->lock);
- serial8250_disable_ms(port);
- spin_unlock_irq(&port->lock);
- }
- }
-}
-
-
-void serial8250_do_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- struct uart_8250_port *p = up_to_u8250p(port);
-
- serial8250_set_sleep(p, state != 0);
-}
-EXPORT_SYMBOL(serial8250_do_pm);
-
-static void
-serial8250_pm(struct uart_port *port, unsigned int state,
- unsigned int oldstate)
-{
- if (port->pm)
- port->pm(port, state, oldstate);
- else
- serial8250_do_pm(port, state, oldstate);
-}
-
-static unsigned int serial8250_port_size(struct uart_8250_port *pt)
-{
- if (pt->port.mapsize)
- return pt->port.mapsize;
- if (pt->port.iotype == UPIO_AU) {
- if (pt->port.type == PORT_RT2880)
- return 0x100;
- return 0x1000;
- }
- if (is_omap1_8250(pt))
- return 0x16 << pt->port.regshift;
-
- return 8 << pt->port.regshift;
-}
-
-/*
- * Resource handling.
- */
-static int serial8250_request_std_resource(struct uart_8250_port *up)
-{
- unsigned int size = serial8250_port_size(up);
- struct uart_port *port = &up->port;
- int ret = 0;
-
- switch (port->iotype) {
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_MEM32:
- case UPIO_MEM32BE:
- case UPIO_MEM:
- if (!port->mapbase)
- break;
-
- if (!request_mem_region(port->mapbase, size, "serial")) {
- ret = -EBUSY;
- break;
- }
-
- if (port->flags & UPF_IOREMAP) {
- port->membase = ioremap_nocache(port->mapbase, size);
- if (!port->membase) {
- release_mem_region(port->mapbase, size);
- ret = -ENOMEM;
- }
- }
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- if (!request_region(port->iobase, size, "serial"))
- ret = -EBUSY;
- break;
- }
- return ret;
-}
-
-static void serial8250_release_std_resource(struct uart_8250_port *up)
-{
- unsigned int size = serial8250_port_size(up);
- struct uart_port *port = &up->port;
-
- switch (port->iotype) {
- case UPIO_AU:
- case UPIO_TSI:
- case UPIO_MEM32:
- case UPIO_MEM32BE:
- case UPIO_MEM:
- if (!port->mapbase)
- break;
-
- if (port->flags & UPF_IOREMAP) {
- iounmap(port->membase);
- port->membase = NULL;
- }
-
- release_mem_region(port->mapbase, size);
- break;
-
- case UPIO_HUB6:
- case UPIO_PORT:
- release_region(port->iobase, size);
- break;
- }
-}
-
#ifdef CONFIG_SERIAL_8250_RSA
static int serial8250_request_rsa_resource(struct uart_8250_port *up)
{
@@ -2848,259 +396,6 @@
}
#endif
-static void serial8250_release_port(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
-
- serial8250_release_std_resource(up);
-}
-
-static int serial8250_request_port(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- int ret;
-
- if (port->type == PORT_8250_CIR)
- return -ENODEV;
-
- ret = serial8250_request_std_resource(up);
-
- return ret;
-}
-
-static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
-{
- const struct serial8250_config *conf_type = &uart_config[up->port.type];
- unsigned char bytes;
-
- bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
-
- return bytes ? bytes : -EOPNOTSUPP;
-}
-
-static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
-{
- const struct serial8250_config *conf_type = &uart_config[up->port.type];
- int i;
-
- if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
- return -EOPNOTSUPP;
-
- for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
- if (bytes < conf_type->rxtrig_bytes[i])
- /* Use the nearest lower value */
- return (--i) << UART_FCR_R_TRIG_SHIFT;
- }
-
- return UART_FCR_R_TRIG_11;
-}
-
-static int do_get_rxtrig(struct tty_port *port)
-{
- struct uart_state *state = container_of(port, struct uart_state, port);
- struct uart_port *uport = state->uart_port;
- struct uart_8250_port *up =
- container_of(uport, struct uart_8250_port, port);
-
- if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
- return -EINVAL;
-
- return fcr_get_rxtrig_bytes(up);
-}
-
-static int do_serial8250_get_rxtrig(struct tty_port *port)
-{
- int rxtrig_bytes;
-
- mutex_lock(&port->mutex);
- rxtrig_bytes = do_get_rxtrig(port);
- mutex_unlock(&port->mutex);
-
- return rxtrig_bytes;
-}
-
-static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct tty_port *port = dev_get_drvdata(dev);
- int rxtrig_bytes;
-
- rxtrig_bytes = do_serial8250_get_rxtrig(port);
- if (rxtrig_bytes < 0)
- return rxtrig_bytes;
-
- return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
-}
-
-static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
-{
- struct uart_state *state = container_of(port, struct uart_state, port);
- struct uart_port *uport = state->uart_port;
- struct uart_8250_port *up =
- container_of(uport, struct uart_8250_port, port);
- int rxtrig;
-
- if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
- up->fifo_bug)
- return -EINVAL;
-
- rxtrig = bytes_to_fcr_rxtrig(up, bytes);
- if (rxtrig < 0)
- return rxtrig;
-
- serial8250_clear_fifos(up);
- up->fcr &= ~UART_FCR_TRIGGER_MASK;
- up->fcr |= (unsigned char)rxtrig;
- serial_out(up, UART_FCR, up->fcr);
- return 0;
-}
-
-static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
-{
- int ret;
-
- mutex_lock(&port->mutex);
- ret = do_set_rxtrig(port, bytes);
- mutex_unlock(&port->mutex);
-
- return ret;
-}
-
-static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct tty_port *port = dev_get_drvdata(dev);
- unsigned char bytes;
- int ret;
-
- if (!count)
- return -EINVAL;
-
- ret = kstrtou8(buf, 10, &bytes);
- if (ret < 0)
- return ret;
-
- ret = do_serial8250_set_rxtrig(port, bytes);
- if (ret < 0)
- return ret;
-
- return count;
-}
-
-static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
- serial8250_get_attr_rx_trig_bytes,
- serial8250_set_attr_rx_trig_bytes);
-
-static struct attribute *serial8250_dev_attrs[] = {
- &dev_attr_rx_trig_bytes.attr,
- NULL,
- };
-
-static struct attribute_group serial8250_dev_attr_group = {
- .attrs = serial8250_dev_attrs,
- };
-
-static void register_dev_spec_attr_grp(struct uart_8250_port *up)
-{
- const struct serial8250_config *conf_type = &uart_config[up->port.type];
-
- if (conf_type->rxtrig_bytes[0])
- up->port.attr_group = &serial8250_dev_attr_group;
-}
-
-static void serial8250_config_port(struct uart_port *port, int flags)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- int ret;
-
- if (port->type == PORT_8250_CIR)
- return;
-
- /*
- * Find the region that we can probe for. This in turn
- * tells us whether we can probe for the type of port.
- */
- ret = serial8250_request_std_resource(up);
- if (ret < 0)
- return;
-
- if (port->iotype != up->cur_iotype)
- set_io_from_upio(port);
-
- if (flags & UART_CONFIG_TYPE)
- autoconfig(up);
-
- /* if access method is AU, it is a 16550 with a quirk */
- if (port->type == PORT_16550A && port->iotype == UPIO_AU)
- up->bugs |= UART_BUG_NOMSR;
-
- /* HW bugs may trigger IRQ while IIR == NO_INT */
- if (port->type == PORT_TEGRA)
- up->bugs |= UART_BUG_NOMSR;
-
- if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
- autoconfig_irq(up);
-
- if (port->type == PORT_UNKNOWN)
- serial8250_release_std_resource(up);
-
- /* Fixme: probably not the best place for this */
- if ((port->type == PORT_XR17V35X) ||
- (port->type == PORT_XR17D15X))
- port->handle_irq = exar_handle_irq;
-
- register_dev_spec_attr_grp(up);
- up->fcr = uart_config[up->port.type].fcr;
-}
-
-static int
-serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
-{
- if (ser->irq >= nr_irqs || ser->irq < 0 ||
- ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
- ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
- ser->type == PORT_STARTECH)
- return -EINVAL;
- return 0;
-}
-
-static const char *
-serial8250_type(struct uart_port *port)
-{
- int type = port->type;
-
- if (type >= ARRAY_SIZE(uart_config))
- type = 0;
- return uart_config[type].name;
-}
-
-static const struct uart_ops serial8250_pops = {
- .tx_empty = serial8250_tx_empty,
- .set_mctrl = serial8250_set_mctrl,
- .get_mctrl = serial8250_get_mctrl,
- .stop_tx = serial8250_stop_tx,
- .start_tx = serial8250_start_tx,
- .throttle = serial8250_throttle,
- .unthrottle = serial8250_unthrottle,
- .stop_rx = serial8250_stop_rx,
- .enable_ms = serial8250_enable_ms,
- .break_ctl = serial8250_break_ctl,
- .startup = serial8250_startup,
- .shutdown = serial8250_shutdown,
- .set_termios = serial8250_set_termios,
- .set_ldisc = serial8250_set_ldisc,
- .pm = serial8250_pm,
- .type = serial8250_type,
- .release_port = serial8250_release_port,
- .request_port = serial8250_request_port,
- .config_port = serial8250_config_port,
- .verify_port = serial8250_verify_port,
-#ifdef CONFIG_CONSOLE_POLL
- .poll_get_char = serial8250_get_poll_char,
- .poll_put_char = serial8250_put_poll_char,
-#endif
-};
-
static const struct uart_ops *base_ops;
static struct uart_ops univ8250_port_ops;
@@ -3139,42 +434,6 @@
}
EXPORT_SYMBOL(serial8250_set_isa_configurator);
-static void serial8250_init_port(struct uart_8250_port *up)
-{
- struct uart_port *port = &up->port;
-
- spin_lock_init(&port->lock);
- port->ops = &serial8250_pops;
-
- up->cur_iotype = 0xFF;
-}
-
-static void serial8250_set_defaults(struct uart_8250_port *up)
-{
- struct uart_port *port = &up->port;
-
- if (up->port.flags & UPF_FIXED_TYPE) {
- unsigned int type = up->port.type;
-
- if (!up->port.fifosize)
- up->port.fifosize = uart_config[type].fifo_size;
- if (!up->tx_loadsz)
- up->tx_loadsz = uart_config[type].tx_loadsz;
- if (!up->capabilities)
- up->capabilities = uart_config[type].flags;
- }
-
- set_io_from_upio(port);
-
- /* default dma handlers */
- if (up->dma) {
- if (!up->dma->tx_dma)
- up->dma->tx_dma = serial8250_tx_dma;
- if (!up->dma->rx_dma)
- up->dma->rx_dma = serial8250_rx_dma;
- }
-}
-
#ifdef CONFIG_SERIAL_8250_RSA
static void univ8250_config_port(struct uart_port *port, int flags)
@@ -3324,94 +583,6 @@
#ifdef CONFIG_SERIAL_8250_CONSOLE
-static void serial8250_console_putchar(struct uart_port *port, int ch)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
-
- wait_for_xmitr(up, UART_LSR_THRE);
- serial_port_out(port, UART_TX, ch);
-}
-
-/*
- * Print a string to the serial port trying not to disturb
- * any possible real use of the port...
- *
- * The console_lock must be held when we get here.
- */
-static void serial8250_console_write(struct uart_8250_port *up, const char *s,
- unsigned int count)
-{
- struct uart_port *port = &up->port;
- unsigned long flags;
- unsigned int ier;
- int locked = 1;
-
- touch_nmi_watchdog();
-
- serial8250_rpm_get(up);
-
- if (port->sysrq)
- locked = 0;
- else if (oops_in_progress)
- locked = spin_trylock_irqsave(&port->lock, flags);
- else
- spin_lock_irqsave(&port->lock, flags);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_port_in(port, UART_IER);
-
- if (up->capabilities & UART_CAP_UUE)
- serial_port_out(port, UART_IER, UART_IER_UUE);
- else
- serial_port_out(port, UART_IER, 0);
-
- /* check scratch reg to see if port powered off during system sleep */
- if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
- struct ktermios termios;
- unsigned int baud, quot, frac = 0;
-
- termios.c_cflag = port->cons->cflag;
- if (port->state->port.tty && termios.c_cflag == 0)
- termios.c_cflag = port->state->port.tty->termios.c_cflag;
-
- baud = uart_get_baud_rate(port, &termios, NULL,
- port->uartclk / 16 / 0xffff,
- port->uartclk / 16);
- quot = serial8250_get_divisor(up, baud, &frac);
-
- serial8250_set_divisor(port, baud, quot, frac);
- serial_port_out(port, UART_LCR, up->lcr);
- serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
-
- up->canary = 0;
- }
-
- uart_console_write(port, s, count, serial8250_console_putchar);
-
- /*
- * Finally, wait for transmitter to become empty
- * and restore the IER
- */
- wait_for_xmitr(up, BOTH_EMPTY);
- serial_port_out(port, UART_IER, ier);
-
- /*
- * The receive handling will happen properly because the
- * receive ready bit will still be set; it is not cleared
- * on read. However, modem control will not, we must
- * call it if we have saved something in the saved flags
- * while processing with interrupts off.
- */
- if (up->msr_saved_flags)
- serial8250_modem_status(up);
-
- if (locked)
- spin_unlock_irqrestore(&port->lock, flags);
- serial8250_rpm_put(up);
-}
-
static void univ8250_console_write(struct console *co, const char *s,
unsigned int count)
{
@@ -3420,39 +591,6 @@
serial8250_console_write(up, s, count);
}
-static unsigned int probe_baud(struct uart_port *port)
-{
- unsigned char lcr, dll, dlm;
- unsigned int quot;
-
- lcr = serial_port_in(port, UART_LCR);
- serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
- dll = serial_port_in(port, UART_DLL);
- dlm = serial_port_in(port, UART_DLM);
- serial_port_out(port, UART_LCR, lcr);
-
- quot = (dlm << 8) | dll;
- return (port->uartclk / 16) / quot;
-}
-
-static int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
-{
- int baud = 9600;
- int bits = 8;
- int parity = 'n';
- int flow = 'n';
-
- if (!port->iobase && !port->membase)
- return -ENODEV;
-
- if (options)
- uart_parse_options(options, &baud, &parity, &bits, &flow);
- else if (probe)
- baud = probe_baud(port);
-
- return uart_set_options(port, port->cons, baud, parity, bits, flow);
-}
-
static int univ8250_console_setup(struct console *co, char *options)
{
struct uart_port *port;
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index d48b506..06324f1 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -56,7 +56,6 @@
struct dw8250_data {
u8 usr_reg;
- int last_mcr;
int line;
int msr_mask_on;
int msr_mask_off;
@@ -76,12 +75,6 @@
{
struct dw8250_data *d = p->private_data;
- /* If reading MSR, report CTS asserted when auto-CTS/RTS enabled */
- if (offset == UART_MSR && d->last_mcr & UART_MCR_AFE) {
- value |= UART_MSR_CTS;
- value &= ~UART_MSR_DCTS;
- }
-
/* Override any modem control signals if needed */
if (offset == UART_MSR) {
value |= d->msr_mask_on;
@@ -101,11 +94,6 @@
static void dw8250_serial_out(struct uart_port *p, int offset, int value)
{
- struct dw8250_data *d = p->private_data;
-
- if (offset == UART_MCR)
- d->last_mcr = value;
-
writeb(value, p->membase + (offset << p->regshift));
/* Make sure LCR write wasn't ignored */
@@ -144,11 +132,6 @@
static void dw8250_serial_outq(struct uart_port *p, int offset, int value)
{
- struct dw8250_data *d = p->private_data;
-
- if (offset == UART_MCR)
- d->last_mcr = value;
-
value &= 0xff;
__raw_writeq(value, p->membase + (offset << p->regshift));
/* Read back to ensure register write ordering. */
@@ -175,11 +158,6 @@
static void dw8250_serial_out32(struct uart_port *p, int offset, int value)
{
- struct dw8250_data *d = p->private_data;
-
- if (offset == UART_MCR)
- d->last_mcr = value;
-
writel(value, p->membase + (offset << p->regshift));
/* Make sure LCR write wasn't ignored */
@@ -257,6 +235,11 @@
if (!ret)
p->uartclk = rate;
+
+ p->status &= ~UPSTAT_AUTOCTS;
+ if (termios->c_cflag & CRTSCTS)
+ p->status |= UPSTAT_AUTOCTS;
+
out:
serial8250_do_set_termios(p, termios, old);
}
diff --git a/drivers/tty/serial/8250/8250_early.c b/drivers/tty/serial/8250/8250_early.c
index 771dda2..faed05f 100644
--- a/drivers/tty/serial/8250/8250_early.c
+++ b/drivers/tty/serial/8250/8250_early.c
@@ -35,7 +35,7 @@
#include <asm/io.h>
#include <asm/serial.h>
-unsigned int __weak __init serial8250_early_in(struct uart_port *port, int offset)
+static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
{
switch (port->iotype) {
case UPIO_MEM:
@@ -51,7 +51,7 @@
}
}
-void __weak __init serial8250_early_out(struct uart_port *port, int offset, int value)
+static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
{
switch (port->iotype) {
case UPIO_MEM:
diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c
index 5815e81..8947439 100644
--- a/drivers/tty/serial/8250/8250_fintek.c
+++ b/drivers/tty/serial/8250/8250_fintek.c
@@ -17,18 +17,19 @@
#include <linux/serial_core.h>
#include "8250.h"
-#define ADDR_PORT 0x4E
-#define DATA_PORT 0x4F
-#define ENTRY_KEY 0x77
+#define ADDR_PORT 0
+#define DATA_PORT 1
#define EXIT_KEY 0xAA
#define CHIP_ID1 0x20
-#define CHIP_ID1_VAL 0x02
#define CHIP_ID2 0x21
-#define CHIP_ID2_VAL 0x16
+#define CHIP_ID_0 0x1602
+#define CHIP_ID_1 0x0501
#define VENDOR_ID1 0x23
#define VENDOR_ID1_VAL 0x19
#define VENDOR_ID2 0x24
#define VENDOR_ID2_VAL 0x34
+#define IO_ADDR1 0x61
+#define IO_ADDR2 0x60
#define LDN 0x7
#define RS485 0xF0
@@ -39,51 +40,49 @@
#define DRIVER_NAME "8250_fintek"
-static int fintek_8250_enter_key(void){
+struct fintek_8250 {
+ u16 base_port;
+ u8 index;
+ u8 key;
+ long line;
+};
- if (!request_muxed_region(ADDR_PORT, 2, DRIVER_NAME))
+static int fintek_8250_enter_key(u16 base_port, u8 key)
+{
+
+ if (!request_muxed_region(base_port, 2, DRIVER_NAME))
return -EBUSY;
- outb(ENTRY_KEY, ADDR_PORT);
- outb(ENTRY_KEY, ADDR_PORT);
+ outb(key, base_port + ADDR_PORT);
+ outb(key, base_port + ADDR_PORT);
return 0;
}
-static void fintek_8250_exit_key(void){
-
- outb(EXIT_KEY, ADDR_PORT);
- release_region(ADDR_PORT, 2);
-}
-
-static int fintek_8250_get_index(resource_size_t base_addr)
-{
- resource_size_t base[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8};
- int i;
-
- for (i = 0; i < ARRAY_SIZE(base); i++)
- if (base_addr == base[i])
- return i;
-
- return -ENODEV;
-}
-
-static int fintek_8250_check_id(void)
+static void fintek_8250_exit_key(u16 base_port)
{
- outb(CHIP_ID1, ADDR_PORT);
- if (inb(DATA_PORT) != CHIP_ID1_VAL)
+ outb(EXIT_KEY, base_port + ADDR_PORT);
+ release_region(base_port + ADDR_PORT, 2);
+}
+
+static int fintek_8250_check_id(u16 base_port)
+{
+ u16 chip;
+
+ outb(VENDOR_ID1, base_port + ADDR_PORT);
+ if (inb(base_port + DATA_PORT) != VENDOR_ID1_VAL)
return -ENODEV;
- outb(CHIP_ID2, ADDR_PORT);
- if (inb(DATA_PORT) != CHIP_ID2_VAL)
+ outb(VENDOR_ID2, base_port + ADDR_PORT);
+ if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL)
return -ENODEV;
- outb(VENDOR_ID1, ADDR_PORT);
- if (inb(DATA_PORT) != VENDOR_ID1_VAL)
- return -ENODEV;
+ outb(CHIP_ID1, base_port + ADDR_PORT);
+ chip = inb(base_port + DATA_PORT);
+ outb(CHIP_ID2, base_port + ADDR_PORT);
+ chip |= inb(base_port + DATA_PORT) << 8;
- outb(VENDOR_ID2, ADDR_PORT);
- if (inb(DATA_PORT) != VENDOR_ID2_VAL)
+ if (chip != CHIP_ID_0 && chip != CHIP_ID_1)
return -ENODEV;
return 0;
@@ -93,9 +92,9 @@
struct serial_rs485 *rs485)
{
uint8_t config = 0;
- int index = fintek_8250_get_index(port->iobase);
+ struct fintek_8250 *pdata = port->private_data;
- if (index < 0)
+ if (!pdata)
return -EINVAL;
if (rs485->flags & SER_RS485_ENABLED)
@@ -125,44 +124,84 @@
if (rs485->flags & SER_RS485_RTS_ON_SEND)
config |= RTS_INVERT;
- if (fintek_8250_enter_key())
+ if (fintek_8250_enter_key(pdata->base_port, pdata->key))
return -EBUSY;
- outb(LDN, ADDR_PORT);
- outb(index, DATA_PORT);
- outb(RS485, ADDR_PORT);
- outb(config, DATA_PORT);
- fintek_8250_exit_key();
+ outb(LDN, pdata->base_port + ADDR_PORT);
+ outb(pdata->index, pdata->base_port + DATA_PORT);
+ outb(RS485, pdata->base_port + ADDR_PORT);
+ outb(config, pdata->base_port + DATA_PORT);
+ fintek_8250_exit_key(pdata->base_port);
port->rs485 = *rs485;
return 0;
}
+static int fintek_8250_base_port(u16 io_address, u8 *key, u8 *index)
+{
+ static const u16 addr[] = {0x4e, 0x2e};
+ static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67};
+ int i, j, k;
+
+ for (i = 0; i < ARRAY_SIZE(addr); i++) {
+ for (j = 0; j < ARRAY_SIZE(keys); j++) {
+
+ if (fintek_8250_enter_key(addr[i], keys[j]))
+ continue;
+ if (fintek_8250_check_id(addr[i])) {
+ fintek_8250_exit_key(addr[i]);
+ continue;
+ }
+
+ for (k = 0; k < 4; k++) {
+ u16 aux;
+
+ outb(LDN, addr[i] + ADDR_PORT);
+ outb(k, addr[i] + DATA_PORT);
+
+ outb(IO_ADDR1, addr[i] + ADDR_PORT);
+ aux = inb(addr[i] + DATA_PORT);
+ outb(IO_ADDR2, addr[i] + ADDR_PORT);
+ aux |= inb(addr[i] + DATA_PORT) << 8;
+ if (aux != io_address)
+ continue;
+
+ fintek_8250_exit_key(addr[i]);
+ *key = keys[j];
+ *index = k;
+ return addr[i];
+ }
+ fintek_8250_exit_key(addr[i]);
+ }
+ }
+
+ return -ENODEV;
+}
+
static int
fintek_8250_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
{
- int line;
struct uart_8250_port uart;
- int ret;
+ struct fintek_8250 *pdata;
+ int base_port;
+ u8 key;
+ u8 index;
if (!pnp_port_valid(dev, 0))
return -ENODEV;
- if (fintek_8250_get_index(pnp_port_start(dev, 0)) < 0)
+ base_port = fintek_8250_base_port(pnp_port_start(dev, 0), &key, &index);
+ if (base_port < 0)
return -ENODEV;
- /* Enable configuration registers*/
- if (fintek_8250_enter_key())
- return -EBUSY;
-
- /*Check ID*/
- ret = fintek_8250_check_id();
- fintek_8250_exit_key();
- if (ret)
- return ret;
-
memset(&uart, 0, sizeof(uart));
+
+ pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+ uart.port.private_data = pdata;
+
if (!pnp_irq_valid(dev, 0))
return -ENODEV;
uart.port.irq = pnp_irq(dev, 0);
@@ -176,40 +215,43 @@
uart.port.uartclk = 1843200;
uart.port.dev = &dev->dev;
- line = serial8250_register_8250_port(&uart);
- if (line < 0)
+ pdata->key = key;
+ pdata->base_port = base_port;
+ pdata->index = index;
+ pdata->line = serial8250_register_8250_port(&uart);
+ if (pdata->line < 0)
return -ENODEV;
- pnp_set_drvdata(dev, (void *)((long)line + 1));
+ pnp_set_drvdata(dev, pdata);
return 0;
}
static void fintek_8250_remove(struct pnp_dev *dev)
{
- long line = (long)pnp_get_drvdata(dev);
+ struct fintek_8250 *pdata = pnp_get_drvdata(dev);
- if (line)
- serial8250_unregister_port(line - 1);
+ if (pdata)
+ serial8250_unregister_port(pdata->line);
}
#ifdef CONFIG_PM
static int fintek_8250_suspend(struct pnp_dev *dev, pm_message_t state)
{
- long line = (long)pnp_get_drvdata(dev);
+ struct fintek_8250 *pdata = pnp_get_drvdata(dev);
- if (!line)
+ if (!pdata)
return -ENODEV;
- serial8250_suspend_port(line - 1);
+ serial8250_suspend_port(pdata->line);
return 0;
}
static int fintek_8250_resume(struct pnp_dev *dev)
{
- long line = (long)pnp_get_drvdata(dev);
+ struct fintek_8250 *pdata = pnp_get_drvdata(dev);
- if (!line)
+ if (!pdata)
return -ENODEV;
- serial8250_resume_port(line - 1);
+ serial8250_resume_port(pdata->line);
return 0;
}
#else
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
index 21bf81f..7c1e4be 100644
--- a/drivers/tty/serial/8250/8250_ingenic.c
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -252,7 +252,6 @@
static struct platform_driver ingenic_uart_platform_driver = {
.driver = {
.name = "ingenic-uart",
- .owner = THIS_MODULE,
.of_match_table = of_match,
},
.probe = ingenic_uart_probe,
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index d75a66c..826c5c4 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -16,6 +16,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/delay.h>
@@ -32,6 +33,11 @@
#define UART_ERRATA_i202_MDR1_ACCESS (1 << 0)
#define OMAP_UART_WER_HAS_TX_WAKEUP (1 << 1)
#define OMAP_DMA_TX_KICK (1 << 2)
+/*
+ * See Advisory 21 in AM437x errata SPRZ408B, updated April 2015.
+ * The same errata is applicable to AM335x and DRA7x processors too.
+ */
+#define UART_ERRATA_CLOCK_DISABLE (1 << 3)
#define OMAP_UART_FCR_RX_TRIG 6
#define OMAP_UART_FCR_TX_TRIG 4
@@ -53,6 +59,12 @@
#define OMAP_UART_MVR_MAJ_SHIFT 8
#define OMAP_UART_MVR_MIN_MASK 0x3f
+/* SYSC register bitmasks */
+#define OMAP_UART_SYSC_SOFTRESET (1 << 1)
+
+/* SYSS register bitmasks */
+#define OMAP_UART_SYSS_RESETDONE (1 << 0)
+
#define UART_TI752_TLR_TX 0
#define UART_TI752_TLR_RX 4
@@ -100,6 +112,7 @@
struct work_struct qos_work;
struct uart_8250_dma omap8250_dma;
spinlock_t rx_dma_lock;
+ bool rx_dma_broken;
};
static u32 uart_read(struct uart_8250_port *up, u32 reg)
@@ -232,6 +245,15 @@
serial_out(up, UART_OMAP_SCR, priv->scr);
}
+static void omap8250_update_mdr1(struct uart_8250_port *up,
+ struct omap8250_priv *priv)
+{
+ if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
+ omap_8250_mdr1_errataset(up, priv);
+ else
+ serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+}
+
static void omap8250_restore_regs(struct uart_8250_port *up)
{
struct omap8250_priv *priv = up->port.private_data;
@@ -282,11 +304,9 @@
serial_out(up, UART_XOFF1, priv->xoff);
serial_out(up, UART_LCR, up->lcr);
- /* need mode A for FCR */
- if (priv->habit & UART_ERRATA_i202_MDR1_ACCESS)
- omap_8250_mdr1_errataset(up, priv);
- else
- serial_out(up, UART_OMAP_MDR1, priv->mdr1);
+
+ omap8250_update_mdr1(up, priv);
+
up->port.ops->set_mctrl(&up->port, up->port.mctrl);
}
@@ -428,12 +448,9 @@
priv->efr |= UART_EFR_CTS;
} else if (up->port.flags & UPF_SOFT_FLOW) {
/*
- * IXON Flag:
- * Enable XON/XOFF flow control on input.
- * Receiver compares XON1, XOFF1.
+ * OMAP rx s/w flow control is borked; the transmitter remains
+ * stuck off even if rx flow control is subsequently disabled
*/
- if (termios->c_iflag & IXON)
- priv->efr |= OMAP_UART_SW_RX;
/*
* IXOFF Flag:
@@ -444,15 +461,6 @@
up->port.status |= UPSTAT_AUTOXOFF;
priv->efr |= OMAP_UART_SW_TX;
}
-
- /*
- * IXANY Flag:
- * Enable any character to restart output.
- * Operation resumes after receiving any
- * character after recognition of the XOFF character
- */
- if (termios->c_iflag & IXANY)
- up->mcr |= UART_MCR_XONANY;
}
omap8250_restore_regs(up);
@@ -530,14 +538,14 @@
switch (revision) {
case OMAP_UART_REV_46:
- priv->habit = UART_ERRATA_i202_MDR1_ACCESS;
+ priv->habit |= UART_ERRATA_i202_MDR1_ACCESS;
break;
case OMAP_UART_REV_52:
- priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
+ priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
OMAP_UART_WER_HAS_TX_WAKEUP;
break;
case OMAP_UART_REV_63:
- priv->habit = UART_ERRATA_i202_MDR1_ACCESS |
+ priv->habit |= UART_ERRATA_i202_MDR1_ACCESS |
OMAP_UART_WER_HAS_TX_WAKEUP;
break;
default:
@@ -754,6 +762,7 @@
struct omap8250_priv *priv = p->port.private_data;
struct uart_8250_dma *dma = p->dma;
unsigned long flags;
+ int ret;
spin_lock_irqsave(&priv->rx_dma_lock, flags);
@@ -762,7 +771,9 @@
return;
}
- dmaengine_pause(dma->rxchan);
+ ret = dmaengine_pause(dma->rxchan);
+ if (WARN_ON_ONCE(ret))
+ priv->rx_dma_broken = true;
spin_unlock_irqrestore(&priv->rx_dma_lock, flags);
@@ -806,6 +817,9 @@
break;
}
+ if (priv->rx_dma_broken)
+ return -EINVAL;
+
spin_lock_irqsave(&priv->rx_dma_lock, flags);
if (dma->rx_running)
@@ -1054,6 +1068,20 @@
return 0;
}
+static const u8 am3352_habit = OMAP_DMA_TX_KICK | UART_ERRATA_CLOCK_DISABLE;
+static const u8 am4372_habit = UART_ERRATA_CLOCK_DISABLE;
+
+static const struct of_device_id omap8250_dt_ids[] = {
+ { .compatible = "ti,omap2-uart" },
+ { .compatible = "ti,omap3-uart" },
+ { .compatible = "ti,omap4-uart" },
+ { .compatible = "ti,am3352-uart", .data = &am3352_habit, },
+ { .compatible = "ti,am4372-uart", .data = &am4372_habit, },
+ { .compatible = "ti,dra742-uart", .data = &am4372_habit, },
+ {},
+};
+MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
+
static int omap8250_probe(struct platform_device *pdev)
{
struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1118,11 +1146,17 @@
up.port.unthrottle = omap_8250_unthrottle;
if (pdev->dev.of_node) {
+ const struct of_device_id *id;
+
ret = of_alias_get_id(pdev->dev.of_node, "serial");
of_property_read_u32(pdev->dev.of_node, "clock-frequency",
&up.port.uartclk);
priv->wakeirq = irq_of_parse_and_map(pdev->dev.of_node, 1);
+
+ id = of_match_device(of_match_ptr(omap8250_dt_ids), &pdev->dev);
+ if (id && id->data)
+ priv->habit |= *(u8 *)id->data;
} else {
ret = pdev->id;
}
@@ -1180,6 +1214,11 @@
if (of_machine_is_compatible("ti,am33xx"))
priv->habit |= OMAP_DMA_TX_KICK;
+ /*
+ * pause is currently not supported atleast on omap-sdma
+ * and edma on most earlier kernels.
+ */
+ priv->rx_dma_broken = true;
}
}
#endif
@@ -1257,17 +1296,46 @@
{
u32 val;
- val = serial_in(up, UART_OMAP_MDR1);
+ val = serial_in(up, UART_OMAP_SCR);
/*
- * If we lose context, then MDR1 is set to its reset value which is
- * UART_OMAP_MDR1_DISABLE. After set_termios() we set it either to 13x
- * or 16x but never to disable again.
+ * If we lose context, then SCR is set to its reset value of zero.
+ * After set_termios() we set bit 3 of SCR (TX_EMPTY_CTL_IT) to 1,
+ * among other bits, to never set the register back to zero again.
*/
- if (val == UART_OMAP_MDR1_DISABLE)
+ if (!val)
return 1;
return 0;
}
+/* TODO: in future, this should happen via API in drivers/reset/ */
+static int omap8250_soft_reset(struct device *dev)
+{
+ struct omap8250_priv *priv = dev_get_drvdata(dev);
+ struct uart_8250_port *up = serial8250_get_port(priv->line);
+ int timeout = 100;
+ int sysc;
+ int syss;
+
+ sysc = serial_in(up, UART_OMAP_SYSC);
+
+ /* softreset the UART */
+ sysc |= OMAP_UART_SYSC_SOFTRESET;
+ serial_out(up, UART_OMAP_SYSC, sysc);
+
+ /* By experiments, 1us enough for reset complete on AM335x */
+ do {
+ udelay(1);
+ syss = serial_in(up, UART_OMAP_SYSS);
+ } while (--timeout && !(syss & OMAP_UART_SYSS_RESETDONE));
+
+ if (!timeout) {
+ dev_err(dev, "timed out waiting for reset done\n");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
static int omap8250_runtime_suspend(struct device *dev)
{
struct omap8250_priv *priv = dev_get_drvdata(dev);
@@ -1285,7 +1353,18 @@
return -EBUSY;
}
- if (up->dma)
+ if (priv->habit & UART_ERRATA_CLOCK_DISABLE) {
+ int ret;
+
+ ret = omap8250_soft_reset(dev);
+ if (ret)
+ return ret;
+
+ /* Restore to UART mode after reset (for wakeup) */
+ omap8250_update_mdr1(up, priv);
+ }
+
+ if (up->dma && up->dma->rxchan)
omap_8250_rx_dma(up, UART_IIR_RX_TIMEOUT);
priv->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE;
@@ -1310,7 +1389,7 @@
if (loss_cntx)
omap8250_restore_regs(up);
- if (up->dma)
+ if (up->dma && up->dma->rxchan)
omap_8250_rx_dma(up, 0);
priv->latency = priv->calc_latency;
@@ -1367,14 +1446,6 @@
.complete = omap8250_complete,
};
-static const struct of_device_id omap8250_dt_ids[] = {
- { .compatible = "ti,omap2-uart" },
- { .compatible = "ti,omap3-uart" },
- { .compatible = "ti,omap4-uart" },
- {},
-};
-MODULE_DEVICE_TABLE(of, omap8250_dt_ids);
-
static struct platform_driver omap8250_platform_driver = {
.driver = {
.name = "omap8250",
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index e55f18b..68042dd 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1417,6 +1417,10 @@
reg |= BYT_PRV_CLK_EN | BYT_PRV_CLK_UPDATE;
writel(reg, p->membase + BYT_PRV_CLK);
+ p->status &= ~UPSTAT_AUTOCTS;
+ if (termios->c_cflag & CRTSCTS)
+ p->status |= UPSTAT_AUTOCTS;
+
serial8250_do_set_termios(p, termios, old);
}
@@ -1685,11 +1689,65 @@
return ret;
}
+/* RTS will control by MCR if this bit is 0 */
+#define FINTEK_RTS_CONTROL_BY_HW BIT(4)
+/* only worked with FINTEK_RTS_CONTROL_BY_HW on */
+#define FINTEK_RTS_INVERT BIT(5)
+
+/* We should do proper H/W transceiver setting before change to RS485 mode */
+static int pci_fintek_rs485_config(struct uart_port *port,
+ struct serial_rs485 *rs485)
+{
+ u8 setting;
+ u8 *index = (u8 *) port->private_data;
+ struct pci_dev *pci_dev = container_of(port->dev, struct pci_dev,
+ dev);
+
+ pci_read_config_byte(pci_dev, 0x40 + 8 * *index + 7, &setting);
+
+ if (!rs485)
+ rs485 = &port->rs485;
+ else if (rs485->flags & SER_RS485_ENABLED)
+ memset(rs485->padding, 0, sizeof(rs485->padding));
+ else
+ memset(rs485, 0, sizeof(*rs485));
+
+ /* F81504/508/512 not support RTS delay before or after send */
+ rs485->flags &= SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
+
+ if (rs485->flags & SER_RS485_ENABLED) {
+ /* Enable RTS H/W control mode */
+ setting |= FINTEK_RTS_CONTROL_BY_HW;
+
+ if (rs485->flags & SER_RS485_RTS_ON_SEND) {
+ /* RTS driving high on TX */
+ setting &= ~FINTEK_RTS_INVERT;
+ } else {
+ /* RTS driving low on TX */
+ setting |= FINTEK_RTS_INVERT;
+ }
+
+ rs485->delay_rts_after_send = 0;
+ rs485->delay_rts_before_send = 0;
+ } else {
+ /* Disable RTS H/W control mode */
+ setting &= ~(FINTEK_RTS_CONTROL_BY_HW | FINTEK_RTS_INVERT);
+ }
+
+ pci_write_config_byte(pci_dev, 0x40 + 8 * *index + 7, setting);
+
+ if (rs485 != &port->rs485)
+ port->rs485 = *rs485;
+
+ return 0;
+}
+
static int pci_fintek_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
struct pci_dev *pdev = priv->dev;
+ u8 *data;
u8 config_base;
u16 iobase;
@@ -1702,6 +1760,15 @@
port->port.iotype = UPIO_PORT;
port->port.iobase = iobase;
+ port->port.rs485_config = pci_fintek_rs485_config;
+
+ data = devm_kzalloc(&pdev->dev, sizeof(u8), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* preserve index in PCI configuration space */
+ *data = idx;
+ port->port.private_data = data;
return 0;
}
@@ -1712,6 +1779,8 @@
u32 max_port, i;
u32 bar_data[3];
u8 config_base;
+ struct serial_private *priv = pci_get_drvdata(dev);
+ struct uart_8250_port *port;
switch (dev->device) {
case 0x1104: /* 4 ports */
@@ -1752,6 +1821,19 @@
(u8)((iobase & 0xff00) >> 8));
pci_write_config_byte(dev, config_base + 0x06, dev->irq);
+
+ if (priv) {
+ /* re-apply RS232/485 mode when
+ * pciserial_resume_ports()
+ */
+ port = serial8250_get_port(priv->line[i]);
+ pci_fintek_rs485_config(&port->port, NULL);
+ } else {
+ /* First init without port data
+ * force init to RS232 Mode
+ */
+ pci_write_config_byte(dev, config_base + 0x07, 0x01);
+ }
}
return max_port;
@@ -2017,6 +2099,12 @@
#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250
#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470
+#define PCI_VENDOR_ID_PERICOM 0x12D8
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954
+#define PCI_DEVICE_ID_PERICOM_PI7C9X7958 0x7958
+
/* Unknown vendors/cards - this should not be in linux/pci_ids.h */
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584
#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588
@@ -2331,27 +2419,12 @@
* Pericom
*/
{
- .vendor = 0x12d8,
- .device = 0x7952,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
+ .vendor = PCI_VENDOR_ID_PERICOM,
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = pci_pericom_setup,
},
- {
- .vendor = 0x12d8,
- .device = 0x7954,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
- },
- {
- .vendor = 0x12d8,
- .device = 0x7958,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
- .setup = pci_pericom_setup,
- },
-
/*
* PLX
*/
@@ -3056,6 +3129,10 @@
pbn_fintek_8,
pbn_fintek_12,
pbn_wch384_4,
+ pbn_pericom_PI7C9X7951,
+ pbn_pericom_PI7C9X7952,
+ pbn_pericom_PI7C9X7954,
+ pbn_pericom_PI7C9X7958,
};
/*
@@ -3881,7 +3958,6 @@
.base_baud = 115200,
.first_offset = 0x40,
},
-
[pbn_wch384_4] = {
.flags = FL_BASE0,
.num_ports = 4,
@@ -3889,6 +3965,33 @@
.uart_offset = 8,
.first_offset = 0xC0,
},
+ /*
+ * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
+ */
+ [pbn_pericom_PI7C9X7951] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 0x8,
+ },
+ [pbn_pericom_PI7C9X7952] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 921600,
+ .uart_offset = 0x8,
+ },
+ [pbn_pericom_PI7C9X7954] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 921600,
+ .uart_offset = 0x8,
+ },
+ [pbn_pericom_PI7C9X7958] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 921600,
+ .uart_offset = 0x8,
+ },
};
static const struct pci_device_id blacklist[] = {
@@ -5154,6 +5257,25 @@
0,
0, pbn_exar_XR17V8358 },
/*
+ * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART
+ */
+ { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_pericom_PI7C9X7951 },
+ { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_pericom_PI7C9X7952 },
+ { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_pericom_PI7C9X7954 },
+ { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958,
+ PCI_ANY_ID, PCI_ANY_ID,
+ 0,
+ 0, pbn_pericom_PI7C9X7958 },
+ /*
* Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke)
*/
{ PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560,
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c
index 50a09cd..658b392 100644
--- a/drivers/tty/serial/8250/8250_pnp.c
+++ b/drivers/tty/serial/8250/8250_pnp.c
@@ -41,6 +41,12 @@
{ "AEI1240", 0 },
/* Rockwell 56K ACF II Fax+Data+Voice Modem */
{ "AKY1021", 0 /*SPCI_FL_NO_SHIRQ*/ },
+ /*
+ * ALi Fast Infrared Controller
+ * Native driver (ali-ircc) is broken so at least
+ * it can be used with irtty-sir.
+ */
+ { "ALI5123", 0 },
/* AZT3005 PnP SOUND DEVICE */
{ "AZT4001", 0 },
/* Best Data Products Inc. Smart One 336F PnP Modem */
@@ -364,6 +370,11 @@
/* Winbond CIR port, should not be probed. We should keep track
of it to prevent the legacy serial driver from probing it */
{ "WEC1022", CIR_PORT },
+ /*
+ * SMSC IrCC SIR/FIR port, should not be probed by serial driver
+ * as well so its own driver can bind to it.
+ */
+ { "SMCF010", CIR_PORT },
{ "", 0 }
};
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
new file mode 100644
index 0000000..54e6c8d
--- /dev/null
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -0,0 +1,2912 @@
+/*
+ * Base port operations for 8250/16550-type serial ports
+ *
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ * Split from 8250_core.c, Copyright (C) 2001 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * A note about mapbase / membase
+ *
+ * mapbase is the physical address of the IO port.
+ * membase is an 'ioremapped' cookie.
+ */
+
+#if defined(CONFIG_SERIAL_8250_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/tty.h>
+#include <linux/ratelimit.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+#include <linux/serial_8250.h>
+#include <linux/nmi.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/pm_runtime.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "8250.h"
+
+/*
+ * Debugging.
+ */
+#if 0
+#define DEBUG_AUTOCONF(fmt...) printk(fmt)
+#else
+#define DEBUG_AUTOCONF(fmt...) do { } while (0)
+#endif
+
+#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
+
+/*
+ * Here we define the default xmit fifo size used for each type of UART.
+ */
+static const struct serial8250_config uart_config[] = {
+ [PORT_UNKNOWN] = {
+ .name = "unknown",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_8250] = {
+ .name = "8250",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16450] = {
+ .name = "16450",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16550] = {
+ .name = "16550",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16550A] = {
+ .name = "16550A",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .rxtrig_bytes = {1, 4, 8, 14},
+ .flags = UART_CAP_FIFO,
+ },
+ [PORT_CIRRUS] = {
+ .name = "Cirrus",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16650] = {
+ .name = "ST16650",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+ },
+ [PORT_16650V2] = {
+ .name = "ST16650V2",
+ .fifo_size = 32,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+ UART_FCR_T_TRIG_00,
+ .rxtrig_bytes = {8, 16, 24, 28},
+ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+ },
+ [PORT_16750] = {
+ .name = "TI16750",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+ UART_FCR7_64BYTE,
+ .rxtrig_bytes = {1, 16, 32, 56},
+ .flags = UART_CAP_FIFO | UART_CAP_SLEEP | UART_CAP_AFE,
+ },
+ [PORT_STARTECH] = {
+ .name = "Startech",
+ .fifo_size = 1,
+ .tx_loadsz = 1,
+ },
+ [PORT_16C950] = {
+ .name = "16C950/954",
+ .fifo_size = 128,
+ .tx_loadsz = 128,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ /* UART_CAP_EFR breaks billionon CF bluetooth card. */
+ .flags = UART_CAP_FIFO | UART_CAP_SLEEP,
+ },
+ [PORT_16654] = {
+ .name = "ST16654",
+ .fifo_size = 64,
+ .tx_loadsz = 32,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+ UART_FCR_T_TRIG_10,
+ .rxtrig_bytes = {8, 16, 56, 60},
+ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+ },
+ [PORT_16850] = {
+ .name = "XR16850",
+ .fifo_size = 128,
+ .tx_loadsz = 128,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_EFR | UART_CAP_SLEEP,
+ },
+ [PORT_RSA] = {
+ .name = "RSA",
+ .fifo_size = 2048,
+ .tx_loadsz = 2048,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11,
+ .flags = UART_CAP_FIFO,
+ },
+ [PORT_NS16550A] = {
+ .name = "NS16550A",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_NATSEMI,
+ },
+ [PORT_XSCALE] = {
+ .name = "XScale",
+ .fifo_size = 32,
+ .tx_loadsz = 32,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_UUE | UART_CAP_RTOIE,
+ },
+ [PORT_OCTEON] = {
+ .name = "OCTEON",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO,
+ },
+ [PORT_AR7] = {
+ .name = "AR7",
+ .fifo_size = 16,
+ .tx_loadsz = 16,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
+ [PORT_U6_16550A] = {
+ .name = "U6_16550A",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
+ [PORT_TEGRA] = {
+ .name = "Tegra",
+ .fifo_size = 32,
+ .tx_loadsz = 8,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01 |
+ UART_FCR_T_TRIG_01,
+ .rxtrig_bytes = {1, 4, 8, 14},
+ .flags = UART_CAP_FIFO | UART_CAP_RTOIE,
+ },
+ [PORT_XR17D15X] = {
+ .name = "XR17D15X",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
+ UART_CAP_SLEEP,
+ },
+ [PORT_XR17V35X] = {
+ .name = "XR17V35X",
+ .fifo_size = 256,
+ .tx_loadsz = 256,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_11 |
+ UART_FCR_T_TRIG_11,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR |
+ UART_CAP_SLEEP,
+ },
+ [PORT_LPC3220] = {
+ .name = "LPC3220",
+ .fifo_size = 64,
+ .tx_loadsz = 32,
+ .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO |
+ UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
+ .flags = UART_CAP_FIFO,
+ },
+ [PORT_BRCM_TRUMANAGE] = {
+ .name = "TruManage",
+ .fifo_size = 1,
+ .tx_loadsz = 1024,
+ .flags = UART_CAP_HFIFO,
+ },
+ [PORT_8250_CIR] = {
+ .name = "CIR port"
+ },
+ [PORT_ALTR_16550_F32] = {
+ .name = "Altera 16550 FIFO32",
+ .fifo_size = 32,
+ .tx_loadsz = 32,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
+ [PORT_ALTR_16550_F64] = {
+ .name = "Altera 16550 FIFO64",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
+ [PORT_ALTR_16550_F128] = {
+ .name = "Altera 16550 FIFO128",
+ .fifo_size = 128,
+ .tx_loadsz = 128,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
+ },
+/* tx_loadsz is set to 63-bytes instead of 64-bytes to implement
+workaround of errata A-008006 which states that tx_loadsz should be
+configured less than Maximum supported fifo bytes */
+ [PORT_16550A_FSL64] = {
+ .name = "16550A_FSL64",
+ .fifo_size = 64,
+ .tx_loadsz = 63,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10 |
+ UART_FCR7_64BYTE,
+ .flags = UART_CAP_FIFO,
+ },
+};
+
+/* Uart divisor latch read */
+static int default_serial_dl_read(struct uart_8250_port *up)
+{
+ return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
+}
+
+/* Uart divisor latch write */
+static void default_serial_dl_write(struct uart_8250_port *up, int value)
+{
+ serial_out(up, UART_DLL, value & 0xff);
+ serial_out(up, UART_DLM, value >> 8 & 0xff);
+}
+
+#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+
+/* Au1x00/RT288x UART hardware has a weird register layout */
+static const s8 au_io_in_map[8] = {
+ 0, /* UART_RX */
+ 2, /* UART_IER */
+ 3, /* UART_IIR */
+ 5, /* UART_LCR */
+ 6, /* UART_MCR */
+ 7, /* UART_LSR */
+ 8, /* UART_MSR */
+ -1, /* UART_SCR (unmapped) */
+};
+
+static const s8 au_io_out_map[8] = {
+ 1, /* UART_TX */
+ 2, /* UART_IER */
+ 4, /* UART_FCR */
+ 5, /* UART_LCR */
+ 6, /* UART_MCR */
+ -1, /* UART_LSR (unmapped) */
+ -1, /* UART_MSR (unmapped) */
+ -1, /* UART_SCR (unmapped) */
+};
+
+static unsigned int au_serial_in(struct uart_port *p, int offset)
+{
+ if (offset >= ARRAY_SIZE(au_io_in_map))
+ return UINT_MAX;
+ offset = au_io_in_map[offset];
+ if (offset < 0)
+ return UINT_MAX;
+ return __raw_readl(p->membase + (offset << p->regshift));
+}
+
+static void au_serial_out(struct uart_port *p, int offset, int value)
+{
+ if (offset >= ARRAY_SIZE(au_io_out_map))
+ return;
+ offset = au_io_out_map[offset];
+ if (offset < 0)
+ return;
+ __raw_writel(value, p->membase + (offset << p->regshift));
+}
+
+/* Au1x00 haven't got a standard divisor latch */
+static int au_serial_dl_read(struct uart_8250_port *up)
+{
+ return __raw_readl(up->port.membase + 0x28);
+}
+
+static void au_serial_dl_write(struct uart_8250_port *up, int value)
+{
+ __raw_writel(value, up->port.membase + 0x28);
+}
+
+#endif
+
+static unsigned int hub6_serial_in(struct uart_port *p, int offset)
+{
+ offset = offset << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ return inb(p->iobase + 1);
+}
+
+static void hub6_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = offset << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ outb(value, p->iobase + 1);
+}
+
+static unsigned int mem_serial_in(struct uart_port *p, int offset)
+{
+ offset = offset << p->regshift;
+ return readb(p->membase + offset);
+}
+
+static void mem_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = offset << p->regshift;
+ writeb(value, p->membase + offset);
+}
+
+static void mem32_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = offset << p->regshift;
+ writel(value, p->membase + offset);
+}
+
+static unsigned int mem32_serial_in(struct uart_port *p, int offset)
+{
+ offset = offset << p->regshift;
+ return readl(p->membase + offset);
+}
+
+static void mem32be_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = offset << p->regshift;
+ iowrite32be(value, p->membase + offset);
+}
+
+static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
+{
+ offset = offset << p->regshift;
+ return ioread32be(p->membase + offset);
+}
+
+static unsigned int io_serial_in(struct uart_port *p, int offset)
+{
+ offset = offset << p->regshift;
+ return inb(p->iobase + offset);
+}
+
+static void io_serial_out(struct uart_port *p, int offset, int value)
+{
+ offset = offset << p->regshift;
+ outb(value, p->iobase + offset);
+}
+
+static int serial8250_default_handle_irq(struct uart_port *port);
+static int exar_handle_irq(struct uart_port *port);
+
+static void set_io_from_upio(struct uart_port *p)
+{
+ struct uart_8250_port *up = up_to_u8250p(p);
+
+ up->dl_read = default_serial_dl_read;
+ up->dl_write = default_serial_dl_write;
+
+ switch (p->iotype) {
+ case UPIO_HUB6:
+ p->serial_in = hub6_serial_in;
+ p->serial_out = hub6_serial_out;
+ break;
+
+ case UPIO_MEM:
+ p->serial_in = mem_serial_in;
+ p->serial_out = mem_serial_out;
+ break;
+
+ case UPIO_MEM32:
+ p->serial_in = mem32_serial_in;
+ p->serial_out = mem32_serial_out;
+ break;
+
+ case UPIO_MEM32BE:
+ p->serial_in = mem32be_serial_in;
+ p->serial_out = mem32be_serial_out;
+ break;
+
+#if defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_SERIAL_8250_RT288X)
+ case UPIO_AU:
+ p->serial_in = au_serial_in;
+ p->serial_out = au_serial_out;
+ up->dl_read = au_serial_dl_read;
+ up->dl_write = au_serial_dl_write;
+ break;
+#endif
+
+ default:
+ p->serial_in = io_serial_in;
+ p->serial_out = io_serial_out;
+ break;
+ }
+ /* Remember loaded iotype */
+ up->cur_iotype = p->iotype;
+ p->handle_irq = serial8250_default_handle_irq;
+}
+
+static void
+serial_port_out_sync(struct uart_port *p, int offset, int value)
+{
+ switch (p->iotype) {
+ case UPIO_MEM:
+ case UPIO_MEM32:
+ case UPIO_MEM32BE:
+ case UPIO_AU:
+ p->serial_out(p, offset, value);
+ p->serial_in(p, UART_LCR); /* safe, no side-effects */
+ break;
+ default:
+ p->serial_out(p, offset, value);
+ }
+}
+
+/*
+ * For the 16C950
+ */
+static void serial_icr_write(struct uart_8250_port *up, int offset, int value)
+{
+ serial_out(up, UART_SCR, offset);
+ serial_out(up, UART_ICR, value);
+}
+
+static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
+{
+ unsigned int value;
+
+ serial_icr_write(up, UART_ACR, up->acr | UART_ACR_ICRRD);
+ serial_out(up, UART_SCR, offset);
+ value = serial_in(up, UART_ICR);
+ serial_icr_write(up, UART_ACR, up->acr);
+
+ return value;
+}
+
+/*
+ * FIFO support.
+ */
+static void serial8250_clear_fifos(struct uart_8250_port *p)
+{
+ if (p->capabilities & UART_CAP_FIFO) {
+ serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_out(p, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+ serial_out(p, UART_FCR, 0);
+ }
+}
+
+void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p)
+{
+ serial8250_clear_fifos(p);
+ serial_out(p, UART_FCR, p->fcr);
+}
+EXPORT_SYMBOL_GPL(serial8250_clear_and_reinit_fifos);
+
+void serial8250_rpm_get(struct uart_8250_port *p)
+{
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+ pm_runtime_get_sync(p->port.dev);
+}
+EXPORT_SYMBOL_GPL(serial8250_rpm_get);
+
+void serial8250_rpm_put(struct uart_8250_port *p)
+{
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+ pm_runtime_mark_last_busy(p->port.dev);
+ pm_runtime_put_autosuspend(p->port.dev);
+}
+EXPORT_SYMBOL_GPL(serial8250_rpm_put);
+
+/*
+ * These two wrappers ensure that enable_runtime_pm_tx() can be called more than
+ * once and disable_runtime_pm_tx() will still disable RPM because the fifo is
+ * empty and the HW can idle again.
+ */
+static void serial8250_rpm_get_tx(struct uart_8250_port *p)
+{
+ unsigned char rpm_active;
+
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+
+ rpm_active = xchg(&p->rpm_tx_active, 1);
+ if (rpm_active)
+ return;
+ pm_runtime_get_sync(p->port.dev);
+}
+
+static void serial8250_rpm_put_tx(struct uart_8250_port *p)
+{
+ unsigned char rpm_active;
+
+ if (!(p->capabilities & UART_CAP_RPM))
+ return;
+
+ rpm_active = xchg(&p->rpm_tx_active, 0);
+ if (!rpm_active)
+ return;
+ pm_runtime_mark_last_busy(p->port.dev);
+ pm_runtime_put_autosuspend(p->port.dev);
+}
+
+/*
+ * IER sleep support. UARTs which have EFRs need the "extended
+ * capability" bit enabled. Note that on XR16C850s, we need to
+ * reset LCR to write to IER.
+ */
+static void serial8250_set_sleep(struct uart_8250_port *p, int sleep)
+{
+ unsigned char lcr = 0, efr = 0;
+ /*
+ * Exar UARTs have a SLEEP register that enables or disables
+ * each UART to enter sleep mode separately. On the XR17V35x the
+ * register is accessible to each UART at the UART_EXAR_SLEEP
+ * offset but the UART channel may only write to the corresponding
+ * bit.
+ */
+ serial8250_rpm_get(p);
+ if ((p->port.type == PORT_XR17V35X) ||
+ (p->port.type == PORT_XR17D15X)) {
+ serial_out(p, UART_EXAR_SLEEP, sleep ? 0xff : 0);
+ goto out;
+ }
+
+ if (p->capabilities & UART_CAP_SLEEP) {
+ if (p->capabilities & UART_CAP_EFR) {
+ lcr = serial_in(p, UART_LCR);
+ efr = serial_in(p, UART_EFR);
+ serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(p, UART_EFR, UART_EFR_ECB);
+ serial_out(p, UART_LCR, 0);
+ }
+ serial_out(p, UART_IER, sleep ? UART_IERX_SLEEP : 0);
+ if (p->capabilities & UART_CAP_EFR) {
+ serial_out(p, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(p, UART_EFR, efr);
+ serial_out(p, UART_LCR, lcr);
+ }
+ }
+out:
+ serial8250_rpm_put(p);
+}
+
+#ifdef CONFIG_SERIAL_8250_RSA
+/*
+ * Attempts to turn on the RSA FIFO. Returns zero on failure.
+ * We set the port uart clock rate if we succeed.
+ */
+static int __enable_rsa(struct uart_8250_port *up)
+{
+ unsigned char mode;
+ int result;
+
+ mode = serial_in(up, UART_RSA_MSR);
+ result = mode & UART_RSA_MSR_FIFO;
+
+ if (!result) {
+ serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
+ mode = serial_in(up, UART_RSA_MSR);
+ result = mode & UART_RSA_MSR_FIFO;
+ }
+
+ if (result)
+ up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
+
+ return result;
+}
+
+static void enable_rsa(struct uart_8250_port *up)
+{
+ if (up->port.type == PORT_RSA) {
+ if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
+ spin_lock_irq(&up->port.lock);
+ __enable_rsa(up);
+ spin_unlock_irq(&up->port.lock);
+ }
+ if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
+ serial_out(up, UART_RSA_FRR, 0);
+ }
+}
+
+/*
+ * Attempts to turn off the RSA FIFO. Returns zero on failure.
+ * It is unknown why interrupts were disabled in here. However,
+ * the caller is expected to preserve this behaviour by grabbing
+ * the spinlock before calling this function.
+ */
+static void disable_rsa(struct uart_8250_port *up)
+{
+ unsigned char mode;
+ int result;
+
+ if (up->port.type == PORT_RSA &&
+ up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16) {
+ spin_lock_irq(&up->port.lock);
+
+ mode = serial_in(up, UART_RSA_MSR);
+ result = !(mode & UART_RSA_MSR_FIFO);
+
+ if (!result) {
+ serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
+ mode = serial_in(up, UART_RSA_MSR);
+ result = !(mode & UART_RSA_MSR_FIFO);
+ }
+
+ if (result)
+ up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
+ spin_unlock_irq(&up->port.lock);
+ }
+}
+#endif /* CONFIG_SERIAL_8250_RSA */
+
+/*
+ * This is a quickie test to see how big the FIFO is.
+ * It doesn't work at all the time, more's the pity.
+ */
+static int size_fifo(struct uart_8250_port *up)
+{
+ unsigned char old_fcr, old_mcr, old_lcr;
+ unsigned short old_dl;
+ int count;
+
+ old_lcr = serial_in(up, UART_LCR);
+ serial_out(up, UART_LCR, 0);
+ old_fcr = serial_in(up, UART_FCR);
+ old_mcr = serial_in(up, UART_MCR);
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT);
+ serial_out(up, UART_MCR, UART_MCR_LOOP);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ old_dl = serial_dl_read(up);
+ serial_dl_write(up, 0x0001);
+ serial_out(up, UART_LCR, 0x03);
+ for (count = 0; count < 256; count++)
+ serial_out(up, UART_TX, count);
+ mdelay(20);/* FIXME - schedule_timeout */
+ for (count = 0; (serial_in(up, UART_LSR) & UART_LSR_DR) &&
+ (count < 256); count++)
+ serial_in(up, UART_RX);
+ serial_out(up, UART_FCR, old_fcr);
+ serial_out(up, UART_MCR, old_mcr);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_dl_write(up, old_dl);
+ serial_out(up, UART_LCR, old_lcr);
+
+ return count;
+}
+
+/*
+ * Read UART ID using the divisor method - set DLL and DLM to zero
+ * and the revision will be in DLL and device type in DLM. We
+ * preserve the device state across this.
+ */
+static unsigned int autoconfig_read_divisor_id(struct uart_8250_port *p)
+{
+ unsigned char old_dll, old_dlm, old_lcr;
+ unsigned int id;
+
+ old_lcr = serial_in(p, UART_LCR);
+ serial_out(p, UART_LCR, UART_LCR_CONF_MODE_A);
+
+ old_dll = serial_in(p, UART_DLL);
+ old_dlm = serial_in(p, UART_DLM);
+
+ serial_out(p, UART_DLL, 0);
+ serial_out(p, UART_DLM, 0);
+
+ id = serial_in(p, UART_DLL) | serial_in(p, UART_DLM) << 8;
+
+ serial_out(p, UART_DLL, old_dll);
+ serial_out(p, UART_DLM, old_dlm);
+ serial_out(p, UART_LCR, old_lcr);
+
+ return id;
+}
+
+/*
+ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
+ * When this function is called we know it is at least a StarTech
+ * 16650 V2, but it might be one of several StarTech UARTs, or one of
+ * its clones. (We treat the broken original StarTech 16650 V1 as a
+ * 16550, and why not? Startech doesn't seem to even acknowledge its
+ * existence.)
+ *
+ * What evil have men's minds wrought...
+ */
+static void autoconfig_has_efr(struct uart_8250_port *up)
+{
+ unsigned int id1, id2, id3, rev;
+
+ /*
+ * Everything with an EFR has SLEEP
+ */
+ up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
+
+ /*
+ * First we check to see if it's an Oxford Semiconductor UART.
+ *
+ * If we have to do this here because some non-National
+ * Semiconductor clone chips lock up if you try writing to the
+ * LSR register (which serial_icr_read does)
+ */
+
+ /*
+ * Check for Oxford Semiconductor 16C950.
+ *
+ * EFR [4] must be set else this test fails.
+ *
+ * This shouldn't be necessary, but Mike Hudson (Exoray@isys.ca)
+ * claims that it's needed for 952 dual UART's (which are not
+ * recommended for new designs).
+ */
+ up->acr = 0;
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(up, UART_EFR, UART_EFR_ECB);
+ serial_out(up, UART_LCR, 0x00);
+ id1 = serial_icr_read(up, UART_ID1);
+ id2 = serial_icr_read(up, UART_ID2);
+ id3 = serial_icr_read(up, UART_ID3);
+ rev = serial_icr_read(up, UART_REV);
+
+ DEBUG_AUTOCONF("950id=%02x:%02x:%02x:%02x ", id1, id2, id3, rev);
+
+ if (id1 == 0x16 && id2 == 0xC9 &&
+ (id3 == 0x50 || id3 == 0x52 || id3 == 0x54)) {
+ up->port.type = PORT_16C950;
+
+ /*
+ * Enable work around for the Oxford Semiconductor 952 rev B
+ * chip which causes it to seriously miscalculate baud rates
+ * when DLL is 0.
+ */
+ if (id3 == 0x52 && rev == 0x01)
+ up->bugs |= UART_BUG_QUOT;
+ return;
+ }
+
+ /*
+ * We check for a XR16C850 by setting DLL and DLM to 0, and then
+ * reading back DLL and DLM. The chip type depends on the DLM
+ * value read back:
+ * 0x10 - XR16C850 and the DLL contains the chip revision.
+ * 0x12 - XR16C2850.
+ * 0x14 - XR16C854.
+ */
+ id1 = autoconfig_read_divisor_id(up);
+ DEBUG_AUTOCONF("850id=%04x ", id1);
+
+ id2 = id1 >> 8;
+ if (id2 == 0x10 || id2 == 0x12 || id2 == 0x14) {
+ up->port.type = PORT_16850;
+ return;
+ }
+
+ /*
+ * It wasn't an XR16C850.
+ *
+ * We distinguish between the '654 and the '650 by counting
+ * how many bytes are in the FIFO. I'm using this for now,
+ * since that's the technique that was sent to me in the
+ * serial driver update, but I'm not convinced this works.
+ * I've had problems doing this in the past. -TYT
+ */
+ if (size_fifo(up) == 64)
+ up->port.type = PORT_16654;
+ else
+ up->port.type = PORT_16650V2;
+}
+
+/*
+ * We detected a chip without a FIFO. Only two fall into
+ * this category - the original 8250 and the 16450. The
+ * 16450 has a scratch register (accessible with LCR=0)
+ */
+static void autoconfig_8250(struct uart_8250_port *up)
+{
+ unsigned char scratch, status1, status2;
+
+ up->port.type = PORT_8250;
+
+ scratch = serial_in(up, UART_SCR);
+ serial_out(up, UART_SCR, 0xa5);
+ status1 = serial_in(up, UART_SCR);
+ serial_out(up, UART_SCR, 0x5a);
+ status2 = serial_in(up, UART_SCR);
+ serial_out(up, UART_SCR, scratch);
+
+ if (status1 == 0xa5 && status2 == 0x5a)
+ up->port.type = PORT_16450;
+}
+
+static int broken_efr(struct uart_8250_port *up)
+{
+ /*
+ * Exar ST16C2550 "A2" devices incorrectly detect as
+ * having an EFR, and report an ID of 0x0201. See
+ * http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-11/4812.html
+ */
+ if (autoconfig_read_divisor_id(up) == 0x0201 && size_fifo(up) == 16)
+ return 1;
+
+ return 0;
+}
+
+/*
+ * We know that the chip has FIFOs. Does it have an EFR? The
+ * EFR is located in the same register position as the IIR and
+ * we know the top two bits of the IIR are currently set. The
+ * EFR should contain zero. Try to read the EFR.
+ */
+static void autoconfig_16550a(struct uart_8250_port *up)
+{
+ unsigned char status1, status2;
+ unsigned int iersave;
+
+ up->port.type = PORT_16550A;
+ up->capabilities |= UART_CAP_FIFO;
+
+ /*
+ * XR17V35x UARTs have an extra divisor register, DLD
+ * that gets enabled with when DLAB is set which will
+ * cause the device to incorrectly match and assign
+ * port type to PORT_16650. The EFR for this UART is
+ * found at offset 0x09. Instead check the Deice ID (DVID)
+ * register for a 2, 4 or 8 port UART.
+ */
+ if (up->port.flags & UPF_EXAR_EFR) {
+ status1 = serial_in(up, UART_EXAR_DVID);
+ if (status1 == 0x82 || status1 == 0x84 || status1 == 0x88) {
+ DEBUG_AUTOCONF("Exar XR17V35x ");
+ up->port.type = PORT_XR17V35X;
+ up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
+ UART_CAP_SLEEP;
+
+ return;
+ }
+
+ }
+
+ /*
+ * Check for presence of the EFR when DLAB is set.
+ * Only ST16C650V1 UARTs pass this test.
+ */
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ if (serial_in(up, UART_EFR) == 0) {
+ serial_out(up, UART_EFR, 0xA8);
+ if (serial_in(up, UART_EFR) != 0) {
+ DEBUG_AUTOCONF("EFRv1 ");
+ up->port.type = PORT_16650;
+ up->capabilities |= UART_CAP_EFR | UART_CAP_SLEEP;
+ } else {
+ serial_out(up, UART_LCR, 0);
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO |
+ UART_FCR7_64BYTE);
+ status1 = serial_in(up, UART_IIR) >> 5;
+ serial_out(up, UART_FCR, 0);
+ serial_out(up, UART_LCR, 0);
+
+ if (status1 == 7)
+ up->port.type = PORT_16550A_FSL64;
+ else
+ DEBUG_AUTOCONF("Motorola 8xxx DUART ");
+ }
+ serial_out(up, UART_EFR, 0);
+ return;
+ }
+
+ /*
+ * Maybe it requires 0xbf to be written to the LCR.
+ * (other ST16C650V2 UARTs, TI16C752A, etc)
+ */
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ if (serial_in(up, UART_EFR) == 0 && !broken_efr(up)) {
+ DEBUG_AUTOCONF("EFRv2 ");
+ autoconfig_has_efr(up);
+ return;
+ }
+
+ /*
+ * Check for a National Semiconductor SuperIO chip.
+ * Attempt to switch to bank 2, read the value of the LOOP bit
+ * from EXCR1. Switch back to bank 0, change it in MCR. Then
+ * switch back to bank 2, read it from EXCR1 again and check
+ * it's changed. If so, set baud_base in EXCR2 to 921600. -- dwmw2
+ */
+ serial_out(up, UART_LCR, 0);
+ status1 = serial_in(up, UART_MCR);
+ serial_out(up, UART_LCR, 0xE0);
+ status2 = serial_in(up, 0x02); /* EXCR1 */
+
+ if (!((status2 ^ status1) & UART_MCR_LOOP)) {
+ serial_out(up, UART_LCR, 0);
+ serial_out(up, UART_MCR, status1 ^ UART_MCR_LOOP);
+ serial_out(up, UART_LCR, 0xE0);
+ status2 = serial_in(up, 0x02); /* EXCR1 */
+ serial_out(up, UART_LCR, 0);
+ serial_out(up, UART_MCR, status1);
+
+ if ((status2 ^ status1) & UART_MCR_LOOP) {
+ unsigned short quot;
+
+ serial_out(up, UART_LCR, 0xE0);
+
+ quot = serial_dl_read(up);
+ quot <<= 3;
+
+ if (ns16550a_goto_highspeed(up))
+ serial_dl_write(up, quot);
+
+ serial_out(up, UART_LCR, 0);
+
+ up->port.uartclk = 921600*16;
+ up->port.type = PORT_NS16550A;
+ up->capabilities |= UART_NATSEMI;
+ return;
+ }
+ }
+
+ /*
+ * No EFR. Try to detect a TI16750, which only sets bit 5 of
+ * the IIR when 64 byte FIFO mode is enabled when DLAB is set.
+ * Try setting it with and without DLAB set. Cheap clones
+ * set bit 5 without DLAB set.
+ */
+ serial_out(up, UART_LCR, 0);
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+ status1 = serial_in(up, UART_IIR) >> 5;
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_A);
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
+ status2 = serial_in(up, UART_IIR) >> 5;
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_out(up, UART_LCR, 0);
+
+ DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
+
+ if (status1 == 6 && status2 == 7) {
+ up->port.type = PORT_16750;
+ up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
+ return;
+ }
+
+ /*
+ * Try writing and reading the UART_IER_UUE bit (b6).
+ * If it works, this is probably one of the Xscale platform's
+ * internal UARTs.
+ * We're going to explicitly set the UUE bit to 0 before
+ * trying to write and read a 1 just to make sure it's not
+ * already a 1 and maybe locked there before we even start start.
+ */
+ iersave = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, iersave & ~UART_IER_UUE);
+ if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
+ /*
+ * OK it's in a known zero state, try writing and reading
+ * without disturbing the current state of the other bits.
+ */
+ serial_out(up, UART_IER, iersave | UART_IER_UUE);
+ if (serial_in(up, UART_IER) & UART_IER_UUE) {
+ /*
+ * It's an Xscale.
+ * We'll leave the UART_IER_UUE bit set to 1 (enabled).
+ */
+ DEBUG_AUTOCONF("Xscale ");
+ up->port.type = PORT_XSCALE;
+ up->capabilities |= UART_CAP_UUE | UART_CAP_RTOIE;
+ return;
+ }
+ } else {
+ /*
+ * If we got here we couldn't force the IER_UUE bit to 0.
+ * Log it and continue.
+ */
+ DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
+ }
+ serial_out(up, UART_IER, iersave);
+
+ /*
+ * Exar uarts have EFR in a weird location
+ */
+ if (up->port.flags & UPF_EXAR_EFR) {
+ DEBUG_AUTOCONF("Exar XR17D15x ");
+ up->port.type = PORT_XR17D15X;
+ up->capabilities |= UART_CAP_AFE | UART_CAP_EFR |
+ UART_CAP_SLEEP;
+
+ return;
+ }
+
+ /*
+ * We distinguish between 16550A and U6 16550A by counting
+ * how many bytes are in the FIFO.
+ */
+ if (up->port.type == PORT_16550A && size_fifo(up) == 64) {
+ up->port.type = PORT_U6_16550A;
+ up->capabilities |= UART_CAP_AFE;
+ }
+}
+
+/*
+ * This routine is called by rs_init() to initialize a specific serial
+ * port. It determines what type of UART chip this serial port is
+ * using: 8250, 16450, 16550, 16550A. The important question is
+ * whether or not this UART is a 16550A or not, since this will
+ * determine whether or not we can use its FIFO features or not.
+ */
+static void autoconfig(struct uart_8250_port *up)
+{
+ unsigned char status1, scratch, scratch2, scratch3;
+ unsigned char save_lcr, save_mcr;
+ struct uart_port *port = &up->port;
+ unsigned long flags;
+ unsigned int old_capabilities;
+
+ if (!port->iobase && !port->mapbase && !port->membase)
+ return;
+
+ DEBUG_AUTOCONF("ttyS%d: autoconf (0x%04lx, 0x%p): ",
+ serial_index(port), port->iobase, port->membase);
+
+ /*
+ * We really do need global IRQs disabled here - we're going to
+ * be frobbing the chips IRQ enable register to see if it exists.
+ */
+ spin_lock_irqsave(&port->lock, flags);
+
+ up->capabilities = 0;
+ up->bugs = 0;
+
+ if (!(port->flags & UPF_BUGGY_UART)) {
+ /*
+ * Do a simple existence test first; if we fail this,
+ * there's no point trying anything else.
+ *
+ * 0x80 is used as a nonsense port to prevent against
+ * false positives due to ISA bus float. The
+ * assumption is that 0x80 is a non-existent port;
+ * which should be safe since include/asm/io.h also
+ * makes this assumption.
+ *
+ * Note: this is safe as long as MCR bit 4 is clear
+ * and the device is in "PC" mode.
+ */
+ scratch = serial_in(up, UART_IER);
+ serial_out(up, UART_IER, 0);
+#ifdef __i386__
+ outb(0xff, 0x080);
+#endif
+ /*
+ * Mask out IER[7:4] bits for test as some UARTs (e.g. TL
+ * 16C754B) allow only to modify them if an EFR bit is set.
+ */
+ scratch2 = serial_in(up, UART_IER) & 0x0f;
+ serial_out(up, UART_IER, 0x0F);
+#ifdef __i386__
+ outb(0, 0x080);
+#endif
+ scratch3 = serial_in(up, UART_IER) & 0x0f;
+ serial_out(up, UART_IER, scratch);
+ if (scratch2 != 0 || scratch3 != 0x0F) {
+ /*
+ * We failed; there's nothing here
+ */
+ spin_unlock_irqrestore(&port->lock, flags);
+ DEBUG_AUTOCONF("IER test failed (%02x, %02x) ",
+ scratch2, scratch3);
+ goto out;
+ }
+ }
+
+ save_mcr = serial_in(up, UART_MCR);
+ save_lcr = serial_in(up, UART_LCR);
+
+ /*
+ * Check to see if a UART is really there. Certain broken
+ * internal modems based on the Rockwell chipset fail this
+ * test, because they apparently don't implement the loopback
+ * test mode. So this test is skipped on the COM 1 through
+ * COM 4 ports. This *should* be safe, since no board
+ * manufacturer would be stupid enough to design a board
+ * that conflicts with COM 1-4 --- we hope!
+ */
+ if (!(port->flags & UPF_SKIP_TEST)) {
+ serial_out(up, UART_MCR, UART_MCR_LOOP | 0x0A);
+ status1 = serial_in(up, UART_MSR) & 0xF0;
+ serial_out(up, UART_MCR, save_mcr);
+ if (status1 != 0x90) {
+ spin_unlock_irqrestore(&port->lock, flags);
+ DEBUG_AUTOCONF("LOOP test failed (%02x) ",
+ status1);
+ goto out;
+ }
+ }
+
+ /*
+ * We're pretty sure there's a port here. Lets find out what
+ * type of port it is. The IIR top two bits allows us to find
+ * out if it's 8250 or 16450, 16550, 16550A or later. This
+ * determines what we test for next.
+ *
+ * We also initialise the EFR (if any) to zero for later. The
+ * EFR occupies the same register location as the FCR and IIR.
+ */
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(up, UART_EFR, 0);
+ serial_out(up, UART_LCR, 0);
+
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ scratch = serial_in(up, UART_IIR) >> 6;
+
+ switch (scratch) {
+ case 0:
+ autoconfig_8250(up);
+ break;
+ case 1:
+ port->type = PORT_UNKNOWN;
+ break;
+ case 2:
+ port->type = PORT_16550;
+ break;
+ case 3:
+ autoconfig_16550a(up);
+ break;
+ }
+
+#ifdef CONFIG_SERIAL_8250_RSA
+ /*
+ * Only probe for RSA ports if we got the region.
+ */
+ if (port->type == PORT_16550A && up->probe & UART_PROBE_RSA &&
+ __enable_rsa(up))
+ port->type = PORT_RSA;
+#endif
+
+ serial_out(up, UART_LCR, save_lcr);
+
+ port->fifosize = uart_config[up->port.type].fifo_size;
+ old_capabilities = up->capabilities;
+ up->capabilities = uart_config[port->type].flags;
+ up->tx_loadsz = uart_config[port->type].tx_loadsz;
+
+ if (port->type == PORT_UNKNOWN)
+ goto out_lock;
+
+ /*
+ * Reset the UART.
+ */
+#ifdef CONFIG_SERIAL_8250_RSA
+ if (port->type == PORT_RSA)
+ serial_out(up, UART_RSA_FRR, 0);
+#endif
+ serial_out(up, UART_MCR, save_mcr);
+ serial8250_clear_fifos(up);
+ serial_in(up, UART_RX);
+ if (up->capabilities & UART_CAP_UUE)
+ serial_out(up, UART_IER, UART_IER_UUE);
+ else
+ serial_out(up, UART_IER, 0);
+
+out_lock:
+ spin_unlock_irqrestore(&port->lock, flags);
+ if (up->capabilities != old_capabilities) {
+ printk(KERN_WARNING
+ "ttyS%d: detected caps %08x should be %08x\n",
+ serial_index(port), old_capabilities,
+ up->capabilities);
+ }
+out:
+ DEBUG_AUTOCONF("iir=%d ", scratch);
+ DEBUG_AUTOCONF("type=%s\n", uart_config[port->type].name);
+}
+
+static void autoconfig_irq(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+ unsigned char save_mcr, save_ier;
+ unsigned char save_ICP = 0;
+ unsigned int ICP = 0;
+ unsigned long irqs;
+ int irq;
+
+ if (port->flags & UPF_FOURPORT) {
+ ICP = (port->iobase & 0xfe0) | 0x1f;
+ save_ICP = inb_p(ICP);
+ outb_p(0x80, ICP);
+ inb_p(ICP);
+ }
+
+ /* forget possible initially masked and pending IRQ */
+ probe_irq_off(probe_irq_on());
+ save_mcr = serial_in(up, UART_MCR);
+ save_ier = serial_in(up, UART_IER);
+ serial_out(up, UART_MCR, UART_MCR_OUT1 | UART_MCR_OUT2);
+
+ irqs = probe_irq_on();
+ serial_out(up, UART_MCR, 0);
+ udelay(10);
+ if (port->flags & UPF_FOURPORT) {
+ serial_out(up, UART_MCR,
+ UART_MCR_DTR | UART_MCR_RTS);
+ } else {
+ serial_out(up, UART_MCR,
+ UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2);
+ }
+ serial_out(up, UART_IER, 0x0f); /* enable all intrs */
+ serial_in(up, UART_LSR);
+ serial_in(up, UART_RX);
+ serial_in(up, UART_IIR);
+ serial_in(up, UART_MSR);
+ serial_out(up, UART_TX, 0xFF);
+ udelay(20);
+ irq = probe_irq_off(irqs);
+
+ serial_out(up, UART_MCR, save_mcr);
+ serial_out(up, UART_IER, save_ier);
+
+ if (port->flags & UPF_FOURPORT)
+ outb_p(save_ICP, ICP);
+
+ port->irq = (irq > 0) ? irq : 0;
+}
+
+static inline void __stop_tx(struct uart_8250_port *p)
+{
+ if (p->ier & UART_IER_THRI) {
+ p->ier &= ~UART_IER_THRI;
+ serial_out(p, UART_IER, p->ier);
+ serial8250_rpm_put_tx(p);
+ }
+}
+
+static void serial8250_stop_tx(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ serial8250_rpm_get(up);
+ __stop_tx(up);
+
+ /*
+ * We really want to stop the transmitter from sending.
+ */
+ if (port->type == PORT_16C950) {
+ up->acr |= UART_ACR_TXDIS;
+ serial_icr_write(up, UART_ACR, up->acr);
+ }
+ serial8250_rpm_put(up);
+}
+
+static void serial8250_start_tx(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ serial8250_rpm_get_tx(up);
+
+ if (up->dma && !up->dma->tx_dma(up))
+ return;
+
+ if (!(up->ier & UART_IER_THRI)) {
+ up->ier |= UART_IER_THRI;
+ serial_port_out(port, UART_IER, up->ier);
+
+ if (up->bugs & UART_BUG_TXEN) {
+ unsigned char lsr;
+ lsr = serial_in(up, UART_LSR);
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+ if (lsr & UART_LSR_THRE)
+ serial8250_tx_chars(up);
+ }
+ }
+
+ /*
+ * Re-enable the transmitter if we disabled it.
+ */
+ if (port->type == PORT_16C950 && up->acr & UART_ACR_TXDIS) {
+ up->acr &= ~UART_ACR_TXDIS;
+ serial_icr_write(up, UART_ACR, up->acr);
+ }
+}
+
+static void serial8250_throttle(struct uart_port *port)
+{
+ port->throttle(port);
+}
+
+static void serial8250_unthrottle(struct uart_port *port)
+{
+ port->unthrottle(port);
+}
+
+static void serial8250_stop_rx(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ serial8250_rpm_get(up);
+
+ up->ier &= ~(UART_IER_RLSI | UART_IER_RDI);
+ up->port.read_status_mask &= ~UART_LSR_DR;
+ serial_port_out(port, UART_IER, up->ier);
+
+ serial8250_rpm_put(up);
+}
+
+static void serial8250_disable_ms(struct uart_port *port)
+{
+ struct uart_8250_port *up =
+ container_of(port, struct uart_8250_port, port);
+
+ /* no MSR capabilities */
+ if (up->bugs & UART_BUG_NOMSR)
+ return;
+
+ up->ier &= ~UART_IER_MSI;
+ serial_port_out(port, UART_IER, up->ier);
+}
+
+static void serial8250_enable_ms(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ /* no MSR capabilities */
+ if (up->bugs & UART_BUG_NOMSR)
+ return;
+
+ up->ier |= UART_IER_MSI;
+
+ serial8250_rpm_get(up);
+ serial_port_out(port, UART_IER, up->ier);
+ serial8250_rpm_put(up);
+}
+
+/*
+ * serial8250_rx_chars: processes according to the passed in LSR
+ * value, and returns the remaining LSR bits not handled
+ * by this Rx routine.
+ */
+unsigned char
+serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr)
+{
+ struct uart_port *port = &up->port;
+ unsigned char ch;
+ int max_count = 256;
+ char flag;
+
+ do {
+ if (likely(lsr & UART_LSR_DR))
+ ch = serial_in(up, UART_RX);
+ else
+ /*
+ * Intel 82571 has a Serial Over Lan device that will
+ * set UART_LSR_BI without setting UART_LSR_DR when
+ * it receives a break. To avoid reading from the
+ * receive buffer without UART_LSR_DR bit set, we
+ * just force the read character to be 0
+ */
+ ch = 0;
+
+ flag = TTY_NORMAL;
+ port->icount.rx++;
+
+ lsr |= up->lsr_saved_flags;
+ up->lsr_saved_flags = 0;
+
+ if (unlikely(lsr & UART_LSR_BRK_ERROR_BITS)) {
+ if (lsr & UART_LSR_BI) {
+ lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+ port->icount.brk++;
+ /*
+ * We do the SysRQ and SAK checking
+ * here because otherwise the break
+ * may get masked by ignore_status_mask
+ * or read_status_mask.
+ */
+ if (uart_handle_break(port))
+ goto ignore_char;
+ } else if (lsr & UART_LSR_PE)
+ port->icount.parity++;
+ else if (lsr & UART_LSR_FE)
+ port->icount.frame++;
+ if (lsr & UART_LSR_OE)
+ port->icount.overrun++;
+
+ /*
+ * Mask off conditions which should be ignored.
+ */
+ lsr &= port->read_status_mask;
+
+ if (lsr & UART_LSR_BI) {
+ DEBUG_INTR("handling break....");
+ flag = TTY_BREAK;
+ } else if (lsr & UART_LSR_PE)
+ flag = TTY_PARITY;
+ else if (lsr & UART_LSR_FE)
+ flag = TTY_FRAME;
+ }
+ if (uart_handle_sysrq_char(port, ch))
+ goto ignore_char;
+
+ uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
+
+ignore_char:
+ lsr = serial_in(up, UART_LSR);
+ } while ((lsr & (UART_LSR_DR | UART_LSR_BI)) && (--max_count > 0));
+ spin_unlock(&port->lock);
+ tty_flip_buffer_push(&port->state->port);
+ spin_lock(&port->lock);
+ return lsr;
+}
+EXPORT_SYMBOL_GPL(serial8250_rx_chars);
+
+void serial8250_tx_chars(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+ struct circ_buf *xmit = &port->state->xmit;
+ int count;
+
+ if (port->x_char) {
+ serial_out(up, UART_TX, port->x_char);
+ port->icount.tx++;
+ port->x_char = 0;
+ return;
+ }
+ if (uart_tx_stopped(port)) {
+ serial8250_stop_tx(port);
+ return;
+ }
+ if (uart_circ_empty(xmit)) {
+ __stop_tx(up);
+ return;
+ }
+
+ count = up->tx_loadsz;
+ do {
+ serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ if (uart_circ_empty(xmit))
+ break;
+ if (up->capabilities & UART_CAP_HFIFO) {
+ if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
+ BOTH_EMPTY)
+ break;
+ }
+ } while (--count > 0);
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ DEBUG_INTR("THRE...");
+
+ /*
+ * With RPM enabled, we have to wait until the FIFO is empty before the
+ * HW can go idle. So we get here once again with empty FIFO and disable
+ * the interrupt and RPM in __stop_tx()
+ */
+ if (uart_circ_empty(xmit) && !(up->capabilities & UART_CAP_RPM))
+ __stop_tx(up);
+}
+EXPORT_SYMBOL_GPL(serial8250_tx_chars);
+
+/* Caller holds uart port lock */
+unsigned int serial8250_modem_status(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+ unsigned int status = serial_in(up, UART_MSR);
+
+ status |= up->msr_saved_flags;
+ up->msr_saved_flags = 0;
+ if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
+ port->state != NULL) {
+ if (status & UART_MSR_TERI)
+ port->icount.rng++;
+ if (status & UART_MSR_DDSR)
+ port->icount.dsr++;
+ if (status & UART_MSR_DDCD)
+ uart_handle_dcd_change(port, status & UART_MSR_DCD);
+ if (status & UART_MSR_DCTS)
+ uart_handle_cts_change(port, status & UART_MSR_CTS);
+
+ wake_up_interruptible(&port->state->port.delta_msr_wait);
+ }
+
+ return status;
+}
+EXPORT_SYMBOL_GPL(serial8250_modem_status);
+
+/*
+ * This handles the interrupt from one port.
+ */
+int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
+{
+ unsigned char status;
+ unsigned long flags;
+ struct uart_8250_port *up = up_to_u8250p(port);
+ int dma_err = 0;
+
+ if (iir & UART_IIR_NO_INT)
+ return 0;
+
+ spin_lock_irqsave(&port->lock, flags);
+
+ status = serial_port_in(port, UART_LSR);
+
+ DEBUG_INTR("status = %x...", status);
+
+ if (status & (UART_LSR_DR | UART_LSR_BI)) {
+ if (up->dma)
+ dma_err = up->dma->rx_dma(up, iir);
+
+ if (!up->dma || dma_err)
+ status = serial8250_rx_chars(up, status);
+ }
+ serial8250_modem_status(up);
+ if ((!up->dma || (up->dma && up->dma->tx_err)) &&
+ (status & UART_LSR_THRE))
+ serial8250_tx_chars(up);
+
+ spin_unlock_irqrestore(&port->lock, flags);
+ return 1;
+}
+EXPORT_SYMBOL_GPL(serial8250_handle_irq);
+
+static int serial8250_default_handle_irq(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned int iir;
+ int ret;
+
+ serial8250_rpm_get(up);
+
+ iir = serial_port_in(port, UART_IIR);
+ ret = serial8250_handle_irq(port, iir);
+
+ serial8250_rpm_put(up);
+ return ret;
+}
+
+/*
+ * These Exar UARTs have an extra interrupt indicator that could
+ * fire for a few unimplemented interrupts. One of which is a
+ * wakeup event when coming out of sleep. Put this here just
+ * to be on the safe side that these interrupts don't go unhandled.
+ */
+static int exar_handle_irq(struct uart_port *port)
+{
+ unsigned char int0, int1, int2, int3;
+ unsigned int iir = serial_port_in(port, UART_IIR);
+ int ret;
+
+ ret = serial8250_handle_irq(port, iir);
+
+ if ((port->type == PORT_XR17V35X) ||
+ (port->type == PORT_XR17D15X)) {
+ int0 = serial_port_in(port, 0x80);
+ int1 = serial_port_in(port, 0x81);
+ int2 = serial_port_in(port, 0x82);
+ int3 = serial_port_in(port, 0x83);
+ }
+
+ return ret;
+}
+
+static unsigned int serial8250_tx_empty(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned long flags;
+ unsigned int lsr;
+
+ serial8250_rpm_get(up);
+
+ spin_lock_irqsave(&port->lock, flags);
+ lsr = serial_port_in(port, UART_LSR);
+ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ serial8250_rpm_put(up);
+
+ return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
+}
+
+static unsigned int serial8250_get_mctrl(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned int status;
+ unsigned int ret;
+
+ serial8250_rpm_get(up);
+ status = serial8250_modem_status(up);
+ serial8250_rpm_put(up);
+
+ ret = 0;
+ if (status & UART_MSR_DCD)
+ ret |= TIOCM_CAR;
+ if (status & UART_MSR_RI)
+ ret |= TIOCM_RNG;
+ if (status & UART_MSR_DSR)
+ ret |= TIOCM_DSR;
+ if (status & UART_MSR_CTS)
+ ret |= TIOCM_CTS;
+ return ret;
+}
+
+void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned char mcr = 0;
+
+ if (mctrl & TIOCM_RTS)
+ mcr |= UART_MCR_RTS;
+ if (mctrl & TIOCM_DTR)
+ mcr |= UART_MCR_DTR;
+ if (mctrl & TIOCM_OUT1)
+ mcr |= UART_MCR_OUT1;
+ if (mctrl & TIOCM_OUT2)
+ mcr |= UART_MCR_OUT2;
+ if (mctrl & TIOCM_LOOP)
+ mcr |= UART_MCR_LOOP;
+
+ mcr = (mcr & up->mcr_mask) | up->mcr_force | up->mcr;
+
+ serial_port_out(port, UART_MCR, mcr);
+}
+EXPORT_SYMBOL_GPL(serial8250_do_set_mctrl);
+
+static void serial8250_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+ if (port->set_mctrl)
+ port->set_mctrl(port, mctrl);
+ else
+ serial8250_do_set_mctrl(port, mctrl);
+}
+
+static void serial8250_break_ctl(struct uart_port *port, int break_state)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned long flags;
+
+ serial8250_rpm_get(up);
+ spin_lock_irqsave(&port->lock, flags);
+ if (break_state == -1)
+ up->lcr |= UART_LCR_SBC;
+ else
+ up->lcr &= ~UART_LCR_SBC;
+ serial_port_out(port, UART_LCR, up->lcr);
+ spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);
+}
+
+/*
+ * Wait for transmitter & holding register to empty
+ */
+static void wait_for_xmitr(struct uart_8250_port *up, int bits)
+{
+ unsigned int status, tmout = 10000;
+
+ /* Wait up to 10ms for the character(s) to be sent. */
+ for (;;) {
+ status = serial_in(up, UART_LSR);
+
+ up->lsr_saved_flags |= status & LSR_SAVE_FLAGS;
+
+ if ((status & bits) == bits)
+ break;
+ if (--tmout == 0)
+ break;
+ udelay(1);
+ }
+
+ /* Wait up to 1s for flow control if necessary */
+ if (up->port.flags & UPF_CONS_FLOW) {
+ unsigned int tmout;
+ for (tmout = 1000000; tmout; tmout--) {
+ unsigned int msr = serial_in(up, UART_MSR);
+ up->msr_saved_flags |= msr & MSR_SAVE_FLAGS;
+ if (msr & UART_MSR_CTS)
+ break;
+ udelay(1);
+ touch_nmi_watchdog();
+ }
+ }
+}
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Console polling routines for writing and reading from the uart while
+ * in an interrupt or debug context.
+ */
+
+static int serial8250_get_poll_char(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned char lsr;
+ int status;
+
+ serial8250_rpm_get(up);
+
+ lsr = serial_port_in(port, UART_LSR);
+
+ if (!(lsr & UART_LSR_DR)) {
+ status = NO_POLL_CHAR;
+ goto out;
+ }
+
+ status = serial_port_in(port, UART_RX);
+out:
+ serial8250_rpm_put(up);
+ return status;
+}
+
+
+static void serial8250_put_poll_char(struct uart_port *port,
+ unsigned char c)
+{
+ unsigned int ier;
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ serial8250_rpm_get(up);
+ /*
+ * First save the IER then disable the interrupts
+ */
+ ier = serial_port_in(port, UART_IER);
+ if (up->capabilities & UART_CAP_UUE)
+ serial_port_out(port, UART_IER, UART_IER_UUE);
+ else
+ serial_port_out(port, UART_IER, 0);
+
+ wait_for_xmitr(up, BOTH_EMPTY);
+ /*
+ * Send the character out.
+ */
+ serial_port_out(port, UART_TX, c);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ wait_for_xmitr(up, BOTH_EMPTY);
+ serial_port_out(port, UART_IER, ier);
+ serial8250_rpm_put(up);
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
+
+int serial8250_do_startup(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned long flags;
+ unsigned char lsr, iir;
+ int retval;
+
+ if (port->type == PORT_8250_CIR)
+ return -ENODEV;
+
+ if (!port->fifosize)
+ port->fifosize = uart_config[port->type].fifo_size;
+ if (!up->tx_loadsz)
+ up->tx_loadsz = uart_config[port->type].tx_loadsz;
+ if (!up->capabilities)
+ up->capabilities = uart_config[port->type].flags;
+ up->mcr = 0;
+
+ if (port->iotype != up->cur_iotype)
+ set_io_from_upio(port);
+
+ serial8250_rpm_get(up);
+ if (port->type == PORT_16C950) {
+ /* Wake up and initialize UART */
+ up->acr = 0;
+ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_port_out(port, UART_EFR, UART_EFR_ECB);
+ serial_port_out(port, UART_IER, 0);
+ serial_port_out(port, UART_LCR, 0);
+ serial_icr_write(up, UART_CSR, 0); /* Reset the UART */
+ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_port_out(port, UART_EFR, UART_EFR_ECB);
+ serial_port_out(port, UART_LCR, 0);
+ }
+
+#ifdef CONFIG_SERIAL_8250_RSA
+ /*
+ * If this is an RSA port, see if we can kick it up to the
+ * higher speed clock.
+ */
+ enable_rsa(up);
+#endif
+
+ if (port->type == PORT_XR17V35X) {
+ /*
+ * First enable access to IER [7:5], ISR [5:4], FCR [5:4],
+ * MCR [7:5] and MSR [7:0]
+ */
+ serial_port_out(port, UART_XR_EFR, UART_EFR_ECB);
+
+ /*
+ * Make sure all interrups are masked until initialization is
+ * complete and the FIFOs are cleared
+ */
+ serial_port_out(port, UART_IER, 0);
+ }
+
+ /*
+ * Clear the FIFO buffers and disable them.
+ * (they will be reenabled in set_termios())
+ */
+ serial8250_clear_fifos(up);
+
+ /*
+ * Clear the interrupt registers.
+ */
+ serial_port_in(port, UART_LSR);
+ serial_port_in(port, UART_RX);
+ serial_port_in(port, UART_IIR);
+ serial_port_in(port, UART_MSR);
+
+ /*
+ * At this point, there's no way the LSR could still be 0xff;
+ * if it is, then bail out, because there's likely no UART
+ * here.
+ */
+ if (!(port->flags & UPF_BUGGY_UART) &&
+ (serial_port_in(port, UART_LSR) == 0xff)) {
+ printk_ratelimited(KERN_INFO "ttyS%d: LSR safety check engaged!\n",
+ serial_index(port));
+ retval = -ENODEV;
+ goto out;
+ }
+
+ /*
+ * For a XR16C850, we need to set the trigger levels
+ */
+ if (port->type == PORT_16850) {
+ unsigned char fctr;
+
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+
+ fctr = serial_in(up, UART_FCTR) & ~(UART_FCTR_RX|UART_FCTR_TX);
+ serial_port_out(port, UART_FCTR,
+ fctr | UART_FCTR_TRGD | UART_FCTR_RX);
+ serial_port_out(port, UART_TRG, UART_TRG_96);
+ serial_port_out(port, UART_FCTR,
+ fctr | UART_FCTR_TRGD | UART_FCTR_TX);
+ serial_port_out(port, UART_TRG, UART_TRG_96);
+
+ serial_port_out(port, UART_LCR, 0);
+ }
+
+ if (port->irq) {
+ unsigned char iir1;
+ /*
+ * Test for UARTs that do not reassert THRE when the
+ * transmitter is idle and the interrupt has already
+ * been cleared. Real 16550s should always reassert
+ * this interrupt whenever the transmitter is idle and
+ * the interrupt is enabled. Delays are necessary to
+ * allow register changes to become visible.
+ */
+ spin_lock_irqsave(&port->lock, flags);
+ if (up->port.irqflags & IRQF_SHARED)
+ disable_irq_nosync(port->irq);
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_port_out_sync(port, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow THRE to set */
+ iir1 = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
+ serial_port_out_sync(port, UART_IER, UART_IER_THRI);
+ udelay(1); /* allow a working UART time to re-assert THRE */
+ iir = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
+
+ if (port->irqflags & IRQF_SHARED)
+ enable_irq(port->irq);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /*
+ * If the interrupt is not reasserted, or we otherwise
+ * don't trust the iir, setup a timer to kick the UART
+ * on a regular basis.
+ */
+ if ((!(iir1 & UART_IIR_NO_INT) && (iir & UART_IIR_NO_INT)) ||
+ up->port.flags & UPF_BUG_THRE) {
+ up->bugs |= UART_BUG_THRE;
+ }
+ }
+
+ retval = up->ops->setup_irq(up);
+ if (retval)
+ goto out;
+
+ /*
+ * Now, initialize the UART
+ */
+ serial_port_out(port, UART_LCR, UART_LCR_WLEN8);
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (up->port.flags & UPF_FOURPORT) {
+ if (!up->port.irq)
+ up->port.mctrl |= TIOCM_OUT1;
+ } else
+ /*
+ * Most PC uarts need OUT2 raised to enable interrupts.
+ */
+ if (port->irq)
+ up->port.mctrl |= TIOCM_OUT2;
+
+ serial8250_set_mctrl(port, port->mctrl);
+
+ /* Serial over Lan (SoL) hack:
+ Intel 8257x Gigabit ethernet chips have a
+ 16550 emulation, to be used for Serial Over Lan.
+ Those chips take a longer time than a normal
+ serial device to signalize that a transmission
+ data was queued. Due to that, the above test generally
+ fails. One solution would be to delay the reading of
+ iir. However, this is not reliable, since the timeout
+ is variable. So, let's just don't test if we receive
+ TX irq. This way, we'll never enable UART_BUG_TXEN.
+ */
+ if (up->port.flags & UPF_NO_TXEN_TEST)
+ goto dont_test_tx_en;
+
+ /*
+ * Do a quick test to see if we receive an
+ * interrupt when we enable the TX irq.
+ */
+ serial_port_out(port, UART_IER, UART_IER_THRI);
+ lsr = serial_port_in(port, UART_LSR);
+ iir = serial_port_in(port, UART_IIR);
+ serial_port_out(port, UART_IER, 0);
+
+ if (lsr & UART_LSR_TEMT && iir & UART_IIR_NO_INT) {
+ if (!(up->bugs & UART_BUG_TXEN)) {
+ up->bugs |= UART_BUG_TXEN;
+ pr_debug("ttyS%d - enabling bad tx status workarounds\n",
+ serial_index(port));
+ }
+ } else {
+ up->bugs &= ~UART_BUG_TXEN;
+ }
+
+dont_test_tx_en:
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /*
+ * Clear the interrupt registers again for luck, and clear the
+ * saved flags to avoid getting false values from polling
+ * routines or the previous session.
+ */
+ serial_port_in(port, UART_LSR);
+ serial_port_in(port, UART_RX);
+ serial_port_in(port, UART_IIR);
+ serial_port_in(port, UART_MSR);
+ up->lsr_saved_flags = 0;
+ up->msr_saved_flags = 0;
+
+ /*
+ * Request DMA channels for both RX and TX.
+ */
+ if (up->dma) {
+ retval = serial8250_request_dma(up);
+ if (retval) {
+ pr_warn_ratelimited("ttyS%d - failed to request DMA\n",
+ serial_index(port));
+ up->dma = NULL;
+ }
+ }
+
+ /*
+ * Set the IER shadow for rx interrupts but defer actual interrupt
+ * enable until after the FIFOs are enabled; otherwise, an already-
+ * active sender can swamp the interrupt handler with "too much work".
+ */
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+
+ if (port->flags & UPF_FOURPORT) {
+ unsigned int icp;
+ /*
+ * Enable interrupts on the AST Fourport board
+ */
+ icp = (port->iobase & 0xfe0) | 0x01f;
+ outb_p(0x80, icp);
+ inb_p(icp);
+ }
+ retval = 0;
+out:
+ serial8250_rpm_put(up);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(serial8250_do_startup);
+
+static int serial8250_startup(struct uart_port *port)
+{
+ if (port->startup)
+ return port->startup(port);
+ return serial8250_do_startup(port);
+}
+
+void serial8250_do_shutdown(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned long flags;
+
+ serial8250_rpm_get(up);
+ /*
+ * Disable interrupts from this port
+ */
+ up->ier = 0;
+ serial_port_out(port, UART_IER, 0);
+
+ if (up->dma)
+ serial8250_release_dma(up);
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (port->flags & UPF_FOURPORT) {
+ /* reset interrupts on the AST Fourport board */
+ inb((port->iobase & 0xfe0) | 0x1f);
+ port->mctrl |= TIOCM_OUT1;
+ } else
+ port->mctrl &= ~TIOCM_OUT2;
+
+ serial8250_set_mctrl(port, port->mctrl);
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ /*
+ * Disable break condition and FIFOs
+ */
+ serial_port_out(port, UART_LCR,
+ serial_port_in(port, UART_LCR) & ~UART_LCR_SBC);
+ serial8250_clear_fifos(up);
+
+#ifdef CONFIG_SERIAL_8250_RSA
+ /*
+ * Reset the RSA board back to 115kbps compat mode.
+ */
+ disable_rsa(up);
+#endif
+
+ /*
+ * Read data port to reset things, and then unlink from
+ * the IRQ chain.
+ */
+ serial_port_in(port, UART_RX);
+ serial8250_rpm_put(up);
+
+ up->ops->release_irq(up);
+}
+EXPORT_SYMBOL_GPL(serial8250_do_shutdown);
+
+static void serial8250_shutdown(struct uart_port *port)
+{
+ if (port->shutdown)
+ port->shutdown(port);
+ else
+ serial8250_do_shutdown(port);
+}
+
+/*
+ * XR17V35x UARTs have an extra fractional divisor register (DLD)
+ * Calculate divisor with extra 4-bit fractional portion
+ */
+static unsigned int xr17v35x_get_divisor(struct uart_8250_port *up,
+ unsigned int baud,
+ unsigned int *frac)
+{
+ struct uart_port *port = &up->port;
+ unsigned int quot_16;
+
+ quot_16 = DIV_ROUND_CLOSEST(port->uartclk, baud);
+ *frac = quot_16 & 0x0f;
+
+ return quot_16 >> 4;
+}
+
+static unsigned int serial8250_get_divisor(struct uart_8250_port *up,
+ unsigned int baud,
+ unsigned int *frac)
+{
+ struct uart_port *port = &up->port;
+ unsigned int quot;
+
+ /*
+ * Handle magic divisors for baud rates above baud_base on
+ * SMSC SuperIO chips.
+ *
+ */
+ if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+ baud == (port->uartclk/4))
+ quot = 0x8001;
+ else if ((port->flags & UPF_MAGIC_MULTIPLIER) &&
+ baud == (port->uartclk/8))
+ quot = 0x8002;
+ else if (up->port.type == PORT_XR17V35X)
+ quot = xr17v35x_get_divisor(up, baud, frac);
+ else
+ quot = uart_get_divisor(port, baud);
+
+ /*
+ * Oxford Semi 952 rev B workaround
+ */
+ if (up->bugs & UART_BUG_QUOT && (quot & 0xff) == 0)
+ quot++;
+
+ return quot;
+}
+
+static unsigned char serial8250_compute_lcr(struct uart_8250_port *up,
+ tcflag_t c_cflag)
+{
+ unsigned char cval;
+
+ switch (c_cflag & CSIZE) {
+ case CS5:
+ cval = UART_LCR_WLEN5;
+ break;
+ case CS6:
+ cval = UART_LCR_WLEN6;
+ break;
+ case CS7:
+ cval = UART_LCR_WLEN7;
+ break;
+ default:
+ case CS8:
+ cval = UART_LCR_WLEN8;
+ break;
+ }
+
+ if (c_cflag & CSTOPB)
+ cval |= UART_LCR_STOP;
+ if (c_cflag & PARENB) {
+ cval |= UART_LCR_PARITY;
+ if (up->bugs & UART_BUG_PARITY)
+ up->fifo_bug = true;
+ }
+ if (!(c_cflag & PARODD))
+ cval |= UART_LCR_EPAR;
+#ifdef CMSPAR
+ if (c_cflag & CMSPAR)
+ cval |= UART_LCR_SPAR;
+#endif
+
+ return cval;
+}
+
+static void serial8250_set_divisor(struct uart_port *port, unsigned int baud,
+ unsigned int quot, unsigned int quot_frac)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ /* Workaround to enable 115200 baud on OMAP1510 internal ports */
+ if (is_omap1510_8250(up)) {
+ if (baud == 115200) {
+ quot = 1;
+ serial_port_out(port, UART_OMAP_OSC_12M_SEL, 1);
+ } else
+ serial_port_out(port, UART_OMAP_OSC_12M_SEL, 0);
+ }
+
+ /*
+ * For NatSemi, switch to bank 2 not bank 1, to avoid resetting EXCR2,
+ * otherwise just set DLAB
+ */
+ if (up->capabilities & UART_NATSEMI)
+ serial_port_out(port, UART_LCR, 0xe0);
+ else
+ serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
+
+ serial_dl_write(up, quot);
+
+ /* XR17V35x UARTs have an extra fractional divisor register (DLD) */
+ if (up->port.type == PORT_XR17V35X)
+ serial_port_out(port, 0x2, quot_frac);
+}
+
+void
+serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ unsigned char cval;
+ unsigned long flags;
+ unsigned int baud, quot, frac = 0;
+
+ cval = serial8250_compute_lcr(up, termios->c_cflag);
+
+ /*
+ * Ask the core to calculate the divisor for us.
+ */
+ baud = uart_get_baud_rate(port, termios, old,
+ port->uartclk / 16 / 0xffff,
+ port->uartclk / 16);
+ quot = serial8250_get_divisor(up, baud, &frac);
+
+ /*
+ * Ok, we're now changing the port state. Do it with
+ * interrupts disabled.
+ */
+ serial8250_rpm_get(up);
+ spin_lock_irqsave(&port->lock, flags);
+
+ up->lcr = cval; /* Save computed LCR */
+
+ if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) {
+ /* NOTE: If fifo_bug is not set, a user can set RX_trigger. */
+ if ((baud < 2400 && !up->dma) || up->fifo_bug) {
+ up->fcr &= ~UART_FCR_TRIGGER_MASK;
+ up->fcr |= UART_FCR_TRIGGER_1;
+ }
+ }
+
+ /*
+ * MCR-based auto flow control. When AFE is enabled, RTS will be
+ * deasserted when the receive FIFO contains more characters than
+ * the trigger, or the MCR RTS bit is cleared. In the case where
+ * the remote UART is not using CTS auto flow control, we must
+ * have sufficient FIFO entries for the latency of the remote
+ * UART to respond. IOW, at least 32 bytes of FIFO.
+ */
+ if (up->capabilities & UART_CAP_AFE && port->fifosize >= 32) {
+ up->mcr &= ~UART_MCR_AFE;
+ if (termios->c_cflag & CRTSCTS)
+ up->mcr |= UART_MCR_AFE;
+ }
+
+ /*
+ * Update the per-port timeout.
+ */
+ uart_update_timeout(port, termios->c_cflag, baud);
+
+ port->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+ if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK))
+ port->read_status_mask |= UART_LSR_BI;
+
+ /*
+ * Characteres to ignore
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= UART_LSR_BI;
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= UART_LSR_OE;
+ }
+
+ /*
+ * ignore all characters if CREAD is not set
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->ignore_status_mask |= UART_LSR_DR;
+
+ /*
+ * CTS flow control flag and modem status interrupts
+ */
+ up->ier &= ~UART_IER_MSI;
+ if (!(up->bugs & UART_BUG_NOMSR) &&
+ UART_ENABLE_MS(&up->port, termios->c_cflag))
+ up->ier |= UART_IER_MSI;
+ if (up->capabilities & UART_CAP_UUE)
+ up->ier |= UART_IER_UUE;
+ if (up->capabilities & UART_CAP_RTOIE)
+ up->ier |= UART_IER_RTOIE;
+
+ serial_port_out(port, UART_IER, up->ier);
+
+ if (up->capabilities & UART_CAP_EFR) {
+ unsigned char efr = 0;
+ /*
+ * TI16C752/Startech hardware flow control. FIXME:
+ * - TI16C752 requires control thresholds to be set.
+ * - UART_MCR_RTS is ineffective if auto-RTS mode is enabled.
+ */
+ if (termios->c_cflag & CRTSCTS)
+ efr |= UART_EFR_CTS;
+
+ serial_port_out(port, UART_LCR, UART_LCR_CONF_MODE_B);
+ if (port->flags & UPF_EXAR_EFR)
+ serial_port_out(port, UART_XR_EFR, efr);
+ else
+ serial_port_out(port, UART_EFR, efr);
+ }
+
+ serial8250_set_divisor(port, baud, quot, frac);
+
+ /*
+ * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
+ * is written without DLAB set, this mode will be disabled.
+ */
+ if (port->type == PORT_16750)
+ serial_port_out(port, UART_FCR, up->fcr);
+
+ serial_port_out(port, UART_LCR, up->lcr); /* reset DLAB */
+ if (port->type != PORT_16750) {
+ /* emulated UARTs (Lucent Venus 167x) need two steps */
+ if (up->fcr & UART_FCR_ENABLE_FIFO)
+ serial_port_out(port, UART_FCR, UART_FCR_ENABLE_FIFO);
+ serial_port_out(port, UART_FCR, up->fcr); /* set fcr */
+ }
+ serial8250_set_mctrl(port, port->mctrl);
+ spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);
+
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(termios))
+ tty_termios_encode_baud_rate(termios, baud, baud);
+}
+EXPORT_SYMBOL(serial8250_do_set_termios);
+
+static void
+serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
+ struct ktermios *old)
+{
+ if (port->set_termios)
+ port->set_termios(port, termios, old);
+ else
+ serial8250_do_set_termios(port, termios, old);
+}
+
+static void
+serial8250_set_ldisc(struct uart_port *port, struct ktermios *termios)
+{
+ if (termios->c_line == N_PPS) {
+ port->flags |= UPF_HARDPPS_CD;
+ spin_lock_irq(&port->lock);
+ serial8250_enable_ms(port);
+ spin_unlock_irq(&port->lock);
+ } else {
+ port->flags &= ~UPF_HARDPPS_CD;
+ if (!UART_ENABLE_MS(port, termios->c_cflag)) {
+ spin_lock_irq(&port->lock);
+ serial8250_disable_ms(port);
+ spin_unlock_irq(&port->lock);
+ }
+ }
+}
+
+
+void serial8250_do_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ struct uart_8250_port *p = up_to_u8250p(port);
+
+ serial8250_set_sleep(p, state != 0);
+}
+EXPORT_SYMBOL(serial8250_do_pm);
+
+static void
+serial8250_pm(struct uart_port *port, unsigned int state,
+ unsigned int oldstate)
+{
+ if (port->pm)
+ port->pm(port, state, oldstate);
+ else
+ serial8250_do_pm(port, state, oldstate);
+}
+
+static unsigned int serial8250_port_size(struct uart_8250_port *pt)
+{
+ if (pt->port.mapsize)
+ return pt->port.mapsize;
+ if (pt->port.iotype == UPIO_AU) {
+ if (pt->port.type == PORT_RT2880)
+ return 0x100;
+ return 0x1000;
+ }
+ if (is_omap1_8250(pt))
+ return 0x16 << pt->port.regshift;
+
+ return 8 << pt->port.regshift;
+}
+
+/*
+ * Resource handling.
+ */
+static int serial8250_request_std_resource(struct uart_8250_port *up)
+{
+ unsigned int size = serial8250_port_size(up);
+ struct uart_port *port = &up->port;
+ int ret = 0;
+
+ switch (port->iotype) {
+ case UPIO_AU:
+ case UPIO_TSI:
+ case UPIO_MEM32:
+ case UPIO_MEM32BE:
+ case UPIO_MEM:
+ if (!port->mapbase)
+ break;
+
+ if (!request_mem_region(port->mapbase, size, "serial")) {
+ ret = -EBUSY;
+ break;
+ }
+
+ if (port->flags & UPF_IOREMAP) {
+ port->membase = ioremap_nocache(port->mapbase, size);
+ if (!port->membase) {
+ release_mem_region(port->mapbase, size);
+ ret = -ENOMEM;
+ }
+ }
+ break;
+
+ case UPIO_HUB6:
+ case UPIO_PORT:
+ if (!request_region(port->iobase, size, "serial"))
+ ret = -EBUSY;
+ break;
+ }
+ return ret;
+}
+
+static void serial8250_release_std_resource(struct uart_8250_port *up)
+{
+ unsigned int size = serial8250_port_size(up);
+ struct uart_port *port = &up->port;
+
+ switch (port->iotype) {
+ case UPIO_AU:
+ case UPIO_TSI:
+ case UPIO_MEM32:
+ case UPIO_MEM32BE:
+ case UPIO_MEM:
+ if (!port->mapbase)
+ break;
+
+ if (port->flags & UPF_IOREMAP) {
+ iounmap(port->membase);
+ port->membase = NULL;
+ }
+
+ release_mem_region(port->mapbase, size);
+ break;
+
+ case UPIO_HUB6:
+ case UPIO_PORT:
+ release_region(port->iobase, size);
+ break;
+ }
+}
+
+static void serial8250_release_port(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ serial8250_release_std_resource(up);
+}
+
+static int serial8250_request_port(struct uart_port *port)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ int ret;
+
+ if (port->type == PORT_8250_CIR)
+ return -ENODEV;
+
+ ret = serial8250_request_std_resource(up);
+
+ return ret;
+}
+
+static int fcr_get_rxtrig_bytes(struct uart_8250_port *up)
+{
+ const struct serial8250_config *conf_type = &uart_config[up->port.type];
+ unsigned char bytes;
+
+ bytes = conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(up->fcr)];
+
+ return bytes ? bytes : -EOPNOTSUPP;
+}
+
+static int bytes_to_fcr_rxtrig(struct uart_8250_port *up, unsigned char bytes)
+{
+ const struct serial8250_config *conf_type = &uart_config[up->port.type];
+ int i;
+
+ if (!conf_type->rxtrig_bytes[UART_FCR_R_TRIG_BITS(UART_FCR_R_TRIG_00)])
+ return -EOPNOTSUPP;
+
+ for (i = 1; i < UART_FCR_R_TRIG_MAX_STATE; i++) {
+ if (bytes < conf_type->rxtrig_bytes[i])
+ /* Use the nearest lower value */
+ return (--i) << UART_FCR_R_TRIG_SHIFT;
+ }
+
+ return UART_FCR_R_TRIG_11;
+}
+
+static int do_get_rxtrig(struct tty_port *port)
+{
+ struct uart_state *state = container_of(port, struct uart_state, port);
+ struct uart_port *uport = state->uart_port;
+ struct uart_8250_port *up =
+ container_of(uport, struct uart_8250_port, port);
+
+ if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1)
+ return -EINVAL;
+
+ return fcr_get_rxtrig_bytes(up);
+}
+
+static int do_serial8250_get_rxtrig(struct tty_port *port)
+{
+ int rxtrig_bytes;
+
+ mutex_lock(&port->mutex);
+ rxtrig_bytes = do_get_rxtrig(port);
+ mutex_unlock(&port->mutex);
+
+ return rxtrig_bytes;
+}
+
+static ssize_t serial8250_get_attr_rx_trig_bytes(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tty_port *port = dev_get_drvdata(dev);
+ int rxtrig_bytes;
+
+ rxtrig_bytes = do_serial8250_get_rxtrig(port);
+ if (rxtrig_bytes < 0)
+ return rxtrig_bytes;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", rxtrig_bytes);
+}
+
+static int do_set_rxtrig(struct tty_port *port, unsigned char bytes)
+{
+ struct uart_state *state = container_of(port, struct uart_state, port);
+ struct uart_port *uport = state->uart_port;
+ struct uart_8250_port *up =
+ container_of(uport, struct uart_8250_port, port);
+ int rxtrig;
+
+ if (!(up->capabilities & UART_CAP_FIFO) || uport->fifosize <= 1 ||
+ up->fifo_bug)
+ return -EINVAL;
+
+ rxtrig = bytes_to_fcr_rxtrig(up, bytes);
+ if (rxtrig < 0)
+ return rxtrig;
+
+ serial8250_clear_fifos(up);
+ up->fcr &= ~UART_FCR_TRIGGER_MASK;
+ up->fcr |= (unsigned char)rxtrig;
+ serial_out(up, UART_FCR, up->fcr);
+ return 0;
+}
+
+static int do_serial8250_set_rxtrig(struct tty_port *port, unsigned char bytes)
+{
+ int ret;
+
+ mutex_lock(&port->mutex);
+ ret = do_set_rxtrig(port, bytes);
+ mutex_unlock(&port->mutex);
+
+ return ret;
+}
+
+static ssize_t serial8250_set_attr_rx_trig_bytes(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct tty_port *port = dev_get_drvdata(dev);
+ unsigned char bytes;
+ int ret;
+
+ if (!count)
+ return -EINVAL;
+
+ ret = kstrtou8(buf, 10, &bytes);
+ if (ret < 0)
+ return ret;
+
+ ret = do_serial8250_set_rxtrig(port, bytes);
+ if (ret < 0)
+ return ret;
+
+ return count;
+}
+
+static DEVICE_ATTR(rx_trig_bytes, S_IRUSR | S_IWUSR | S_IRGRP,
+ serial8250_get_attr_rx_trig_bytes,
+ serial8250_set_attr_rx_trig_bytes);
+
+static struct attribute *serial8250_dev_attrs[] = {
+ &dev_attr_rx_trig_bytes.attr,
+ NULL,
+ };
+
+static struct attribute_group serial8250_dev_attr_group = {
+ .attrs = serial8250_dev_attrs,
+ };
+
+static void register_dev_spec_attr_grp(struct uart_8250_port *up)
+{
+ const struct serial8250_config *conf_type = &uart_config[up->port.type];
+
+ if (conf_type->rxtrig_bytes[0])
+ up->port.attr_group = &serial8250_dev_attr_group;
+}
+
+static void serial8250_config_port(struct uart_port *port, int flags)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+ int ret;
+
+ if (port->type == PORT_8250_CIR)
+ return;
+
+ /*
+ * Find the region that we can probe for. This in turn
+ * tells us whether we can probe for the type of port.
+ */
+ ret = serial8250_request_std_resource(up);
+ if (ret < 0)
+ return;
+
+ if (port->iotype != up->cur_iotype)
+ set_io_from_upio(port);
+
+ if (flags & UART_CONFIG_TYPE)
+ autoconfig(up);
+
+ /* if access method is AU, it is a 16550 with a quirk */
+ if (port->type == PORT_16550A && port->iotype == UPIO_AU)
+ up->bugs |= UART_BUG_NOMSR;
+
+ /* HW bugs may trigger IRQ while IIR == NO_INT */
+ if (port->type == PORT_TEGRA)
+ up->bugs |= UART_BUG_NOMSR;
+
+ if (port->type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ)
+ autoconfig_irq(up);
+
+ if (port->type == PORT_UNKNOWN)
+ serial8250_release_std_resource(up);
+
+ /* Fixme: probably not the best place for this */
+ if ((port->type == PORT_XR17V35X) ||
+ (port->type == PORT_XR17D15X))
+ port->handle_irq = exar_handle_irq;
+
+ register_dev_spec_attr_grp(up);
+ up->fcr = uart_config[up->port.type].fcr;
+}
+
+static int
+serial8250_verify_port(struct uart_port *port, struct serial_struct *ser)
+{
+ if (ser->irq >= nr_irqs || ser->irq < 0 ||
+ ser->baud_base < 9600 || ser->type < PORT_UNKNOWN ||
+ ser->type >= ARRAY_SIZE(uart_config) || ser->type == PORT_CIRRUS ||
+ ser->type == PORT_STARTECH)
+ return -EINVAL;
+ return 0;
+}
+
+static const char *
+serial8250_type(struct uart_port *port)
+{
+ int type = port->type;
+
+ if (type >= ARRAY_SIZE(uart_config))
+ type = 0;
+ return uart_config[type].name;
+}
+
+static const struct uart_ops serial8250_pops = {
+ .tx_empty = serial8250_tx_empty,
+ .set_mctrl = serial8250_set_mctrl,
+ .get_mctrl = serial8250_get_mctrl,
+ .stop_tx = serial8250_stop_tx,
+ .start_tx = serial8250_start_tx,
+ .throttle = serial8250_throttle,
+ .unthrottle = serial8250_unthrottle,
+ .stop_rx = serial8250_stop_rx,
+ .enable_ms = serial8250_enable_ms,
+ .break_ctl = serial8250_break_ctl,
+ .startup = serial8250_startup,
+ .shutdown = serial8250_shutdown,
+ .set_termios = serial8250_set_termios,
+ .set_ldisc = serial8250_set_ldisc,
+ .pm = serial8250_pm,
+ .type = serial8250_type,
+ .release_port = serial8250_release_port,
+ .request_port = serial8250_request_port,
+ .config_port = serial8250_config_port,
+ .verify_port = serial8250_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+ .poll_get_char = serial8250_get_poll_char,
+ .poll_put_char = serial8250_put_poll_char,
+#endif
+};
+
+void serial8250_init_port(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+
+ spin_lock_init(&port->lock);
+ port->ops = &serial8250_pops;
+
+ up->cur_iotype = 0xFF;
+}
+EXPORT_SYMBOL_GPL(serial8250_init_port);
+
+void serial8250_set_defaults(struct uart_8250_port *up)
+{
+ struct uart_port *port = &up->port;
+
+ if (up->port.flags & UPF_FIXED_TYPE) {
+ unsigned int type = up->port.type;
+
+ if (!up->port.fifosize)
+ up->port.fifosize = uart_config[type].fifo_size;
+ if (!up->tx_loadsz)
+ up->tx_loadsz = uart_config[type].tx_loadsz;
+ if (!up->capabilities)
+ up->capabilities = uart_config[type].flags;
+ }
+
+ set_io_from_upio(port);
+
+ /* default dma handlers */
+ if (up->dma) {
+ if (!up->dma->tx_dma)
+ up->dma->tx_dma = serial8250_tx_dma;
+ if (!up->dma->rx_dma)
+ up->dma->rx_dma = serial8250_rx_dma;
+ }
+}
+EXPORT_SYMBOL_GPL(serial8250_set_defaults);
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+
+static void serial8250_console_putchar(struct uart_port *port, int ch)
+{
+ struct uart_8250_port *up = up_to_u8250p(port);
+
+ wait_for_xmitr(up, UART_LSR_THRE);
+ serial_port_out(port, UART_TX, ch);
+}
+
+/*
+ * Print a string to the serial port trying not to disturb
+ * any possible real use of the port...
+ *
+ * The console_lock must be held when we get here.
+ */
+void serial8250_console_write(struct uart_8250_port *up, const char *s,
+ unsigned int count)
+{
+ struct uart_port *port = &up->port;
+ unsigned long flags;
+ unsigned int ier;
+ int locked = 1;
+
+ touch_nmi_watchdog();
+
+ serial8250_rpm_get(up);
+
+ if (port->sysrq)
+ locked = 0;
+ else if (oops_in_progress)
+ locked = spin_trylock_irqsave(&port->lock, flags);
+ else
+ spin_lock_irqsave(&port->lock, flags);
+
+ /*
+ * First save the IER then disable the interrupts
+ */
+ ier = serial_port_in(port, UART_IER);
+
+ if (up->capabilities & UART_CAP_UUE)
+ serial_port_out(port, UART_IER, UART_IER_UUE);
+ else
+ serial_port_out(port, UART_IER, 0);
+
+ /* check scratch reg to see if port powered off during system sleep */
+ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) {
+ struct ktermios termios;
+ unsigned int baud, quot, frac = 0;
+
+ termios.c_cflag = port->cons->cflag;
+ if (port->state->port.tty && termios.c_cflag == 0)
+ termios.c_cflag = port->state->port.tty->termios.c_cflag;
+
+ baud = uart_get_baud_rate(port, &termios, NULL,
+ port->uartclk / 16 / 0xffff,
+ port->uartclk / 16);
+ quot = serial8250_get_divisor(up, baud, &frac);
+
+ serial8250_set_divisor(port, baud, quot, frac);
+ serial_port_out(port, UART_LCR, up->lcr);
+ serial_port_out(port, UART_MCR, UART_MCR_DTR | UART_MCR_RTS);
+
+ up->canary = 0;
+ }
+
+ uart_console_write(port, s, count, serial8250_console_putchar);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore the IER
+ */
+ wait_for_xmitr(up, BOTH_EMPTY);
+ serial_port_out(port, UART_IER, ier);
+
+ /*
+ * The receive handling will happen properly because the
+ * receive ready bit will still be set; it is not cleared
+ * on read. However, modem control will not, we must
+ * call it if we have saved something in the saved flags
+ * while processing with interrupts off.
+ */
+ if (up->msr_saved_flags)
+ serial8250_modem_status(up);
+
+ if (locked)
+ spin_unlock_irqrestore(&port->lock, flags);
+ serial8250_rpm_put(up);
+}
+
+static unsigned int probe_baud(struct uart_port *port)
+{
+ unsigned char lcr, dll, dlm;
+ unsigned int quot;
+
+ lcr = serial_port_in(port, UART_LCR);
+ serial_port_out(port, UART_LCR, lcr | UART_LCR_DLAB);
+ dll = serial_port_in(port, UART_DLL);
+ dlm = serial_port_in(port, UART_DLM);
+ serial_port_out(port, UART_LCR, lcr);
+
+ quot = (dlm << 8) | dll;
+ return (port->uartclk / 16) / quot;
+}
+
+int serial8250_console_setup(struct uart_port *port, char *options, bool probe)
+{
+ int baud = 9600;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (!port->iobase && !port->membase)
+ return -ENODEV;
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ else if (probe)
+ baud = probe_baud(port);
+
+ return uart_set_options(port, port->cons, baud, parity, bits, flow);
+}
+
+#endif /* CONFIG_SERIAL_8250_CONSOLE */
diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c
index 7d79425..d11621e 100644
--- a/drivers/tty/serial/8250/8250_uniphier.c
+++ b/drivers/tty/serial/8250/8250_uniphier.c
@@ -218,6 +218,7 @@
ret = serial8250_register_8250_port(&up);
if (ret < 0) {
dev_err(dev, "failed to register 8250 port\n");
+ clk_disable_unprepare(priv->clk);
return ret;
}
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 7062959..39c6d22 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -2,10 +2,11 @@
# Makefile for the 8250 serial device drivers.
#
-obj-$(CONFIG_SERIAL_8250) += 8250.o
+obj-$(CONFIG_SERIAL_8250) += 8250.o 8250_base.o
8250-y := 8250_core.o
8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
-8250-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
+8250_base-y := 8250_port.o
+8250_base-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o
obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o
obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o
obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 76e65b7..ed299b9 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -47,12 +47,12 @@
config SERIAL_AMBA_PL011
tristate "ARM AMBA PL011 serial port support"
- depends on ARM_AMBA
+ depends on ARM_AMBA || SOC_ZX296702
select SERIAL_CORE
help
This selects the ARM(R) AMBA(R) PrimeCell PL011 UART. If you have
an Integrator/PP2, Integrator/CP or Versatile platform, say Y or M
- here.
+ here. Say Y or M if you have SOC_ZX296702.
If unsure, say N.
@@ -594,7 +594,7 @@
config SERIAL_UARTLITE
tristate "Xilinx uartlite serial port support"
- depends on PPC32 || MICROBLAZE || MFD_TIMBERDALE || ARCH_ZYNQ
+ depends on HAS_IOMEM
select SERIAL_CORE
help
Say Y here if you want to use the Xilinx uartlite serial controller.
@@ -1067,6 +1067,7 @@
bool "ETRAX FS serial port support"
depends on ETRAX_ARCH_V32 && OF
select SERIAL_CORE
+ select SERIAL_MCTRL_GPIO if GPIOLIB
config SERIAL_ETRAXFS_CONSOLE
bool "ETRAX FS serial console support"
@@ -1185,7 +1186,7 @@
config SERIAL_SC16IS7XX
tristate "SC16IS7xx serial support"
select SERIAL_CORE
- depends on I2C || SPI_MASTER
+ depends on (SPI_MASTER && !I2C) || I2C
help
This selects support for SC16IS7xx serial ports.
Supported ICs are SC16IS740, SC16IS741, SC16IS750, SC16IS752,
@@ -1376,7 +1377,8 @@
config SERIAL_IFX6X60
tristate "SPI protocol driver for Infineon 6x60 modem (EXPERIMENTAL)"
- depends on GPIOLIB && SPI && HAS_DMA
+ depends on GPIOLIB || COMPILE_TEST
+ depends on SPI && HAS_DMA
help
Support for the IFX6x60 modem devices on Intel MID platforms.
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 50cf5b1..2af09ab 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -74,8 +74,13 @@
/* There is by now at least one vendor with differing details, so handle it */
struct vendor_data {
unsigned int ifls;
+ unsigned int fr_busy;
+ unsigned int fr_dsr;
+ unsigned int fr_cts;
+ unsigned int fr_ri;
unsigned int lcrh_tx;
unsigned int lcrh_rx;
+ u16 *reg_lut;
bool oversampling;
bool dma_threshold;
bool cts_event_workaround;
@@ -85,6 +90,48 @@
unsigned int (*get_fifosize)(struct amba_device *dev);
};
+/* Max address offset of register in use is 0x48 */
+#define REG_NR (0x48 >> 2)
+#define IDX(x) (x >> 2)
+enum reg_idx {
+ REG_DR = IDX(UART01x_DR),
+ REG_RSR = IDX(UART01x_RSR),
+ REG_ST_DMAWM = IDX(ST_UART011_DMAWM),
+ REG_FR = IDX(UART01x_FR),
+ REG_ST_LCRH_RX = IDX(ST_UART011_LCRH_RX),
+ REG_ILPR = IDX(UART01x_ILPR),
+ REG_IBRD = IDX(UART011_IBRD),
+ REG_FBRD = IDX(UART011_FBRD),
+ REG_LCRH = IDX(UART011_LCRH),
+ REG_CR = IDX(UART011_CR),
+ REG_IFLS = IDX(UART011_IFLS),
+ REG_IMSC = IDX(UART011_IMSC),
+ REG_RIS = IDX(UART011_RIS),
+ REG_MIS = IDX(UART011_MIS),
+ REG_ICR = IDX(UART011_ICR),
+ REG_DMACR = IDX(UART011_DMACR),
+};
+
+static u16 arm_reg[] = {
+ [REG_DR] = UART01x_DR,
+ [REG_RSR] = UART01x_RSR,
+ [REG_ST_DMAWM] = ~0,
+ [REG_FR] = UART01x_FR,
+ [REG_ST_LCRH_RX] = ~0,
+ [REG_ILPR] = UART01x_ILPR,
+ [REG_IBRD] = UART011_IBRD,
+ [REG_FBRD] = UART011_FBRD,
+ [REG_LCRH] = UART011_LCRH,
+ [REG_CR] = UART011_CR,
+ [REG_IFLS] = UART011_IFLS,
+ [REG_IMSC] = UART011_IMSC,
+ [REG_RIS] = UART011_RIS,
+ [REG_MIS] = UART011_MIS,
+ [REG_ICR] = UART011_ICR,
+ [REG_DMACR] = UART011_DMACR,
+};
+
+#ifdef CONFIG_ARM_AMBA
static unsigned int get_fifosize_arm(struct amba_device *dev)
{
return amba_rev(dev) < 3 ? 16 : 32;
@@ -92,8 +139,13 @@
static struct vendor_data vendor_arm = {
.ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
- .lcrh_tx = UART011_LCRH,
- .lcrh_rx = UART011_LCRH,
+ .fr_busy = UART01x_FR_BUSY,
+ .fr_dsr = UART01x_FR_DSR,
+ .fr_cts = UART01x_FR_CTS,
+ .fr_ri = UART011_FR_RI,
+ .lcrh_tx = REG_LCRH,
+ .lcrh_rx = REG_LCRH,
+ .reg_lut = arm_reg,
.oversampling = false,
.dma_threshold = false,
.cts_event_workaround = false,
@@ -101,8 +153,14 @@
.fixed_options = false,
.get_fifosize = get_fifosize_arm,
};
+#endif
static struct vendor_data vendor_sbsa = {
+ .fr_busy = UART01x_FR_BUSY,
+ .fr_dsr = UART01x_FR_DSR,
+ .fr_cts = UART01x_FR_CTS,
+ .fr_ri = UART011_FR_RI,
+ .reg_lut = arm_reg,
.oversampling = false,
.dma_threshold = false,
.cts_event_workaround = false,
@@ -110,6 +168,26 @@
.fixed_options = true,
};
+#ifdef CONFIG_ARM_AMBA
+static u16 st_reg[] = {
+ [REG_DR] = UART01x_DR,
+ [REG_RSR] = UART01x_RSR,
+ [REG_ST_DMAWM] = ST_UART011_DMAWM,
+ [REG_FR] = UART01x_FR,
+ [REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+ [REG_ILPR] = UART01x_ILPR,
+ [REG_IBRD] = UART011_IBRD,
+ [REG_FBRD] = UART011_FBRD,
+ [REG_LCRH] = UART011_LCRH,
+ [REG_CR] = UART011_CR,
+ [REG_IFLS] = UART011_IFLS,
+ [REG_IMSC] = UART011_IMSC,
+ [REG_RIS] = UART011_RIS,
+ [REG_MIS] = UART011_MIS,
+ [REG_ICR] = UART011_ICR,
+ [REG_DMACR] = UART011_DMACR,
+};
+
static unsigned int get_fifosize_st(struct amba_device *dev)
{
return 64;
@@ -117,8 +195,13 @@
static struct vendor_data vendor_st = {
.ifls = UART011_IFLS_RX_HALF|UART011_IFLS_TX_HALF,
- .lcrh_tx = ST_UART011_LCRH_TX,
- .lcrh_rx = ST_UART011_LCRH_RX,
+ .fr_busy = UART01x_FR_BUSY,
+ .fr_dsr = UART01x_FR_DSR,
+ .fr_cts = UART01x_FR_CTS,
+ .fr_ri = UART011_FR_RI,
+ .lcrh_tx = REG_LCRH,
+ .lcrh_rx = REG_ST_LCRH_RX,
+ .reg_lut = st_reg,
.oversampling = true,
.dma_threshold = true,
.cts_event_workaround = true,
@@ -126,6 +209,43 @@
.fixed_options = false,
.get_fifosize = get_fifosize_st,
};
+#endif
+
+#ifdef CONFIG_SOC_ZX296702
+static u16 zte_reg[] = {
+ [REG_DR] = ZX_UART01x_DR,
+ [REG_RSR] = UART01x_RSR,
+ [REG_ST_DMAWM] = ST_UART011_DMAWM,
+ [REG_FR] = ZX_UART01x_FR,
+ [REG_ST_LCRH_RX] = ST_UART011_LCRH_RX,
+ [REG_ILPR] = UART01x_ILPR,
+ [REG_IBRD] = UART011_IBRD,
+ [REG_FBRD] = UART011_FBRD,
+ [REG_LCRH] = ZX_UART011_LCRH_TX,
+ [REG_CR] = ZX_UART011_CR,
+ [REG_IFLS] = ZX_UART011_IFLS,
+ [REG_IMSC] = ZX_UART011_IMSC,
+ [REG_RIS] = ZX_UART011_RIS,
+ [REG_MIS] = ZX_UART011_MIS,
+ [REG_ICR] = ZX_UART011_ICR,
+ [REG_DMACR] = ZX_UART011_DMACR,
+};
+
+static struct vendor_data vendor_zte = {
+ .ifls = UART011_IFLS_RX4_8|UART011_IFLS_TX4_8,
+ .fr_busy = ZX_UART01x_FR_BUSY,
+ .fr_dsr = ZX_UART01x_FR_DSR,
+ .fr_cts = ZX_UART01x_FR_CTS,
+ .fr_ri = ZX_UART011_FR_RI,
+ .lcrh_tx = REG_LCRH,
+ .lcrh_rx = REG_ST_LCRH_RX,
+ .reg_lut = zte_reg,
+ .oversampling = false,
+ .dma_threshold = false,
+ .cts_event_workaround = false,
+ .fixed_options = false,
+};
+#endif
/* Deals with DMA transactions */
@@ -164,10 +284,15 @@
struct uart_port port;
struct clk *clk;
const struct vendor_data *vendor;
+ u16 *reg_lut;
unsigned int dmacr; /* dma control reg */
unsigned int im; /* interrupt mask */
unsigned int old_status;
unsigned int fifosize; /* vendor-specific */
+ unsigned int fr_busy; /* vendor-specific */
+ unsigned int fr_dsr; /* vendor-specific */
+ unsigned int fr_cts; /* vendor-specific */
+ unsigned int fr_ri; /* vendor-specific */
unsigned int lcrh_tx; /* vendor-specific */
unsigned int lcrh_rx; /* vendor-specific */
unsigned int old_cr; /* state during shutdown */
@@ -184,6 +309,29 @@
#endif
};
+static bool is_implemented(struct uart_amba_port *uap, unsigned int reg)
+{
+ return uap->reg_lut[reg] != (u16)~0;
+}
+
+static unsigned int pl011_readw(struct uart_amba_port *uap, int index)
+{
+ WARN_ON(index > REG_NR);
+ return readw_relaxed(uap->port.membase + uap->reg_lut[index]);
+}
+
+static void pl011_writew(struct uart_amba_port *uap, int val, int index)
+{
+ WARN_ON(index > REG_NR);
+ writew_relaxed(val, uap->port.membase + uap->reg_lut[index]);
+}
+
+static void pl011_writeb(struct uart_amba_port *uap, u8 val, int index)
+{
+ WARN_ON(index > REG_NR);
+ writeb_relaxed(val, uap->port.membase + uap->reg_lut[index]);
+}
+
/*
* Reads up to 256 characters from the FIFO or until it's empty and
* inserts them into the TTY layer. Returns the number of characters
@@ -196,12 +344,12 @@
int fifotaken = 0;
while (max_count--) {
- status = readw(uap->port.membase + UART01x_FR);
+ status = pl011_readw(uap, REG_FR);
if (status & UART01x_FR_RXFE)
break;
/* Take chars from the FIFO and update status */
- ch = readw(uap->port.membase + UART01x_DR) |
+ ch = pl011_readw(uap, REG_DR) |
UART_DUMMY_DR_RX;
flag = TTY_NORMAL;
uap->port.icount.rx++;
@@ -284,7 +432,7 @@
struct amba_pl011_data *plat = dev_get_platdata(uap->port.dev);
struct device *dev = uap->port.dev;
struct dma_slave_config tx_conf = {
- .dst_addr = uap->port.mapbase + UART01x_DR,
+ .dst_addr = uap->port.mapbase + uap->reg_lut[REG_DR],
.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_MEM_TO_DEV,
.dst_maxburst = uap->fifosize >> 1,
@@ -339,7 +487,7 @@
if (chan) {
struct dma_slave_config rx_conf = {
- .src_addr = uap->port.mapbase + UART01x_DR,
+ .src_addr = uap->port.mapbase + uap->reg_lut[REG_DR],
.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
.direction = DMA_DEV_TO_MEM,
.src_maxburst = uap->fifosize >> 2,
@@ -438,7 +586,7 @@
dmacr = uap->dmacr;
uap->dmacr = dmacr & ~UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
/*
* If TX DMA was disabled, it means that we've stopped the DMA for
@@ -552,7 +700,7 @@
dma_dev->device_issue_pending(chan);
uap->dmacr |= UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
uap->dmatx.queued = true;
/*
@@ -588,9 +736,9 @@
*/
if (uap->dmatx.queued) {
uap->dmacr |= UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
uap->im &= ~UART011_TXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
return true;
}
@@ -600,7 +748,7 @@
*/
if (pl011_dma_tx_refill(uap) > 0) {
uap->im &= ~UART011_TXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
return true;
}
return false;
@@ -614,7 +762,7 @@
{
if (uap->dmatx.queued) {
uap->dmacr &= ~UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
}
}
@@ -640,14 +788,12 @@
if (!uap->dmatx.queued) {
if (pl011_dma_tx_refill(uap) > 0) {
uap->im &= ~UART011_TXIM;
- writew(uap->im, uap->port.membase +
- UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
} else
ret = false;
} else if (!(uap->dmacr & UART011_TXDMAE)) {
uap->dmacr |= UART011_TXDMAE;
- writew(uap->dmacr,
- uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
}
return ret;
}
@@ -658,9 +804,9 @@
*/
dmacr = uap->dmacr;
uap->dmacr &= ~UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
- if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
+ if (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF) {
/*
* No space in the FIFO, so enable the transmit interrupt
* so we know when there is space. Note that once we've
@@ -669,13 +815,13 @@
return false;
}
- writew(uap->port.x_char, uap->port.membase + UART01x_DR);
+ pl011_writew(uap, uap->port.x_char, REG_DR);
uap->port.icount.tx++;
uap->port.x_char = 0;
/* Success - restore the DMA state */
uap->dmacr = dmacr;
- writew(dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, dmacr, REG_DMACR);
return true;
}
@@ -703,7 +849,7 @@
DMA_TO_DEVICE);
uap->dmatx.queued = false;
uap->dmacr &= ~UART011_TXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
}
}
@@ -743,11 +889,11 @@
dma_async_issue_pending(rxchan);
uap->dmacr |= UART011_RXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
uap->dmarx.running = true;
uap->im &= ~UART011_RXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
return 0;
}
@@ -805,8 +951,9 @@
*/
if (dma_count == pending && readfifo) {
/* Clear any error flags */
- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
- uap->port.membase + UART011_ICR);
+ pl011_writew(uap,
+ UART011_OEIS | UART011_BEIS | UART011_PEIS
+ | UART011_FEIS, REG_ICR);
/*
* If we read all the DMA'd characters, and we had an
@@ -854,7 +1001,7 @@
/* Disable RX DMA - incoming data will wait in the FIFO */
uap->dmacr &= ~UART011_RXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
uap->dmarx.running = false;
pending = sgbuf->sg.length - state.residue;
@@ -874,7 +1021,7 @@
dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
"fall back to interrupt mode\n");
uap->im |= UART011_RXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
}
}
@@ -922,7 +1069,7 @@
dev_dbg(uap->port.dev, "could not retrigger RX DMA job "
"fall back to interrupt mode\n");
uap->im |= UART011_RXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
}
}
@@ -935,7 +1082,7 @@
{
/* FIXME. Just disable the DMA enable */
uap->dmacr &= ~UART011_RXDMAE;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
}
/*
@@ -979,7 +1126,7 @@
spin_lock_irqsave(&uap->port.lock, flags);
pl011_dma_rx_stop(uap);
uap->im |= UART011_RXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
spin_unlock_irqrestore(&uap->port.lock, flags);
uap->dmarx.running = false;
@@ -1041,7 +1188,7 @@
skip_rx:
/* Turn on DMA error (RX/TX will be enabled on demand) */
uap->dmacr |= UART011_DMAONERR;
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
/*
* ST Micro variants has some specific dma burst threshold
@@ -1049,8 +1196,9 @@
* be issued above/below 16 bytes.
*/
if (uap->vendor->dma_threshold)
- writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
- uap->port.membase + ST_UART011_DMAWM);
+ pl011_writew(uap,
+ ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
+ REG_ST_DMAWM);
if (uap->using_rx_dma) {
if (pl011_dma_rx_trigger_dma(uap))
@@ -1075,12 +1223,12 @@
return;
/* Disable RX and TX DMA */
- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
+ while (pl011_readw(uap, REG_FR) & uap->fr_busy)
barrier();
spin_lock_irq(&uap->port.lock);
uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
- writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+ pl011_writew(uap, uap->dmacr, REG_DMACR);
spin_unlock_irq(&uap->port.lock);
if (uap->using_tx_dma) {
@@ -1181,7 +1329,7 @@
container_of(port, struct uart_amba_port, port);
uap->im &= ~UART011_TXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
pl011_dma_tx_stop(uap);
}
@@ -1191,7 +1339,7 @@
static void pl011_start_tx_pio(struct uart_amba_port *uap)
{
uap->im |= UART011_TXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
pl011_tx_chars(uap, false);
}
@@ -1211,7 +1359,7 @@
uap->im &= ~(UART011_RXIM|UART011_RTIM|UART011_FEIM|
UART011_PEIM|UART011_BEIM|UART011_OEIM);
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
pl011_dma_rx_stop(uap);
}
@@ -1222,7 +1370,7 @@
container_of(port, struct uart_amba_port, port);
uap->im |= UART011_RIMIM|UART011_CTSMIM|UART011_DCDMIM|UART011_DSRMIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
}
static void pl011_rx_chars(struct uart_amba_port *uap)
@@ -1242,7 +1390,7 @@
dev_dbg(uap->port.dev, "could not trigger RX DMA job "
"fall back to interrupt mode again\n");
uap->im |= UART011_RXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
} else {
#ifdef CONFIG_DMA_ENGINE
/* Start Rx DMA poll */
@@ -1263,10 +1411,10 @@
bool from_irq)
{
if (unlikely(!from_irq) &&
- readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+ pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
return false; /* unable to transmit character */
- writew(c, uap->port.membase + UART01x_DR);
+ pl011_writew(uap, c, REG_DR);
uap->port.icount.tx++;
return true;
@@ -1313,7 +1461,7 @@
{
unsigned int status, delta;
- status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
+ status = pl011_readw(uap, REG_FR) & UART01x_FR_MODEM_ANY;
delta = status ^ uap->old_status;
uap->old_status = status;
@@ -1324,11 +1472,11 @@
if (delta & UART01x_FR_DCD)
uart_handle_dcd_change(&uap->port, status & UART01x_FR_DCD);
- if (delta & UART01x_FR_DSR)
+ if (delta & uap->fr_dsr)
uap->port.icount.dsr++;
- if (delta & UART01x_FR_CTS)
- uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
+ if (delta & uap->fr_cts)
+ uart_handle_cts_change(&uap->port, status & uap->fr_cts);
wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
}
@@ -1341,15 +1489,15 @@
return;
/* workaround to make sure that all bits are unlocked.. */
- writew(0x00, uap->port.membase + UART011_ICR);
+ pl011_writew(uap, 0x00, REG_ICR);
/*
* WA: introduce 26ns(1 uart clk) delay before W1C;
* single apb access will incur 2 pclk(133.12Mhz) delay,
* so add 2 dummy reads
*/
- dummy_read = readw(uap->port.membase + UART011_ICR);
- dummy_read = readw(uap->port.membase + UART011_ICR);
+ dummy_read = pl011_readw(uap, REG_ICR);
+ dummy_read = pl011_readw(uap, REG_ICR);
}
static irqreturn_t pl011_int(int irq, void *dev_id)
@@ -1361,15 +1509,13 @@
int handled = 0;
spin_lock_irqsave(&uap->port.lock, flags);
- imsc = readw(uap->port.membase + UART011_IMSC);
- status = readw(uap->port.membase + UART011_RIS) & imsc;
+ imsc = pl011_readw(uap, REG_IMSC);
+ status = pl011_readw(uap, REG_RIS) & imsc;
if (status) {
do {
check_apply_cts_event_workaround(uap);
-
- writew(status & ~(UART011_TXIS|UART011_RTIS|
- UART011_RXIS),
- uap->port.membase + UART011_ICR);
+ pl011_writew(uap, status & ~(UART011_TXIS|UART011_RTIS|
+ UART011_RXIS), REG_ICR);
if (status & (UART011_RTIS|UART011_RXIS)) {
if (pl011_dma_rx_running(uap))
@@ -1386,7 +1532,7 @@
if (pass_counter-- == 0)
break;
- status = readw(uap->port.membase + UART011_RIS) & imsc;
+ status = pl011_readw(uap, REG_RIS) & imsc;
} while (status != 0);
handled = 1;
}
@@ -1400,8 +1546,8 @@
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
- unsigned int status = readw(uap->port.membase + UART01x_FR);
- return status & (UART01x_FR_BUSY|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
+ unsigned int status = pl011_readw(uap, REG_FR);
+ return status & (uap->fr_busy|UART01x_FR_TXFF) ? 0 : TIOCSER_TEMT;
}
static unsigned int pl011_get_mctrl(struct uart_port *port)
@@ -1409,16 +1555,16 @@
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
unsigned int result = 0;
- unsigned int status = readw(uap->port.membase + UART01x_FR);
+ unsigned int status = pl011_readw(uap, REG_FR);
#define TIOCMBIT(uartbit, tiocmbit) \
if (status & uartbit) \
result |= tiocmbit
TIOCMBIT(UART01x_FR_DCD, TIOCM_CAR);
- TIOCMBIT(UART01x_FR_DSR, TIOCM_DSR);
- TIOCMBIT(UART01x_FR_CTS, TIOCM_CTS);
- TIOCMBIT(UART011_FR_RI, TIOCM_RNG);
+ TIOCMBIT(uap->fr_dsr, TIOCM_DSR);
+ TIOCMBIT(uap->fr_cts, TIOCM_CTS);
+ TIOCMBIT(uap->fr_ri, TIOCM_RNG);
#undef TIOCMBIT
return result;
}
@@ -1429,7 +1575,7 @@
container_of(port, struct uart_amba_port, port);
unsigned int cr;
- cr = readw(uap->port.membase + UART011_CR);
+ cr = pl011_readw(uap, REG_CR);
#define TIOCMBIT(tiocmbit, uartbit) \
if (mctrl & tiocmbit) \
@@ -1449,7 +1595,7 @@
}
#undef TIOCMBIT
- writew(cr, uap->port.membase + UART011_CR);
+ pl011_writew(uap, cr, REG_CR);
}
static void pl011_break_ctl(struct uart_port *port, int break_state)
@@ -1460,12 +1606,12 @@
unsigned int lcr_h;
spin_lock_irqsave(&uap->port.lock, flags);
- lcr_h = readw(uap->port.membase + uap->lcrh_tx);
+ lcr_h = pl011_readw(uap, uap->lcrh_tx);
if (break_state == -1)
lcr_h |= UART01x_LCRH_BRK;
else
lcr_h &= ~UART01x_LCRH_BRK;
- writew(lcr_h, uap->port.membase + uap->lcrh_tx);
+ pl011_writew(uap, lcr_h, uap->lcrh_tx);
spin_unlock_irqrestore(&uap->port.lock, flags);
}
@@ -1475,9 +1621,8 @@
{
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
- unsigned char __iomem *regs = uap->port.membase;
- writew(readw(regs + UART011_MIS), regs + UART011_ICR);
+ pl011_writew(uap, pl011_readw(uap, REG_MIS), REG_ICR);
/*
* There is no way to clear TXIM as this is "ready to transmit IRQ", so
* we simply mask it. start_tx() will unmask it.
@@ -1491,7 +1636,7 @@
* (including tx queue), so we're also fine with start_tx()'s caller
* side.
*/
- writew(readw(regs + UART011_IMSC) & ~UART011_TXIM, regs + UART011_IMSC);
+ pl011_writew(uap, pl011_readw(uap, REG_IMSC) & ~UART011_TXIM, REG_IMSC);
}
static int pl011_get_poll_char(struct uart_port *port)
@@ -1506,11 +1651,11 @@
*/
pl011_quiesce_irqs(port);
- status = readw(uap->port.membase + UART01x_FR);
+ status = pl011_readw(uap, REG_FR);
if (status & UART01x_FR_RXFE)
return NO_POLL_CHAR;
- return readw(uap->port.membase + UART01x_DR);
+ return pl011_readw(uap, REG_DR);
}
static void pl011_put_poll_char(struct uart_port *port,
@@ -1519,10 +1664,10 @@
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+ while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
barrier();
- writew(ch, uap->port.membase + UART01x_DR);
+ pl011_writew(uap, ch, REG_DR);
}
#endif /* CONFIG_CONSOLE_POLL */
@@ -1546,15 +1691,15 @@
uap->port.uartclk = clk_get_rate(uap->clk);
/* Clear pending error and receive interrupts */
- writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS |
- UART011_RTIS | UART011_RXIS, uap->port.membase + UART011_ICR);
+ pl011_writew(uap, UART011_OEIS | UART011_BEIS | UART011_PEIS |
+ UART011_FEIS | UART011_RTIS | UART011_RXIS, REG_ICR);
/*
* Save interrupts enable mask, and enable RX interrupts in case if
* the interrupt is used for NMI entry.
*/
- uap->im = readw(uap->port.membase + UART011_IMSC);
- writew(UART011_RTIM | UART011_RXIM, uap->port.membase + UART011_IMSC);
+ uap->im = pl011_readw(uap, REG_IMSC);
+ pl011_writew(uap, UART011_RTIM | UART011_RXIM, REG_IMSC);
if (dev_get_platdata(uap->port.dev)) {
struct amba_pl011_data *plat;
@@ -1568,22 +1713,22 @@
static void pl011_write_lcr_h(struct uart_amba_port *uap, unsigned int lcr_h)
{
- writew(lcr_h, uap->port.membase + uap->lcrh_rx);
- if (uap->lcrh_rx != uap->lcrh_tx) {
+ pl011_writew(uap, lcr_h, uap->lcrh_rx);
+ if (is_implemented(uap, REG_ST_LCRH_RX)) {
int i;
/*
* Wait 10 PCLKs before writing LCRH_TX register,
* to get this delay write read only register 10 times
*/
for (i = 0; i < 10; ++i)
- writew(0xff, uap->port.membase + UART011_MIS);
- writew(lcr_h, uap->port.membase + uap->lcrh_tx);
+ pl011_writew(uap, 0xff, REG_MIS);
+ pl011_writew(uap, lcr_h, uap->lcrh_tx);
}
}
static int pl011_allocate_irq(struct uart_amba_port *uap)
{
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
return request_irq(uap->port.irq, pl011_int, 0, "uart-pl011", uap);
}
@@ -1598,12 +1743,11 @@
spin_lock_irq(&uap->port.lock);
/* Clear out any spuriously appearing RX interrupts */
- writew(UART011_RTIS | UART011_RXIS,
- uap->port.membase + UART011_ICR);
+ pl011_writew(uap, UART011_RTIS | UART011_RXIS, REG_ICR);
uap->im = UART011_RTIM;
if (!pl011_dma_rx_running(uap))
uap->im |= UART011_RXIM;
- writew(uap->im, uap->port.membase + UART011_IMSC);
+ pl011_writew(uap, uap->im, REG_IMSC);
spin_unlock_irq(&uap->port.lock);
}
@@ -1622,21 +1766,21 @@
if (retval)
goto clk_dis;
- writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
+ pl011_writew(uap, uap->vendor->ifls, REG_IFLS);
spin_lock_irq(&uap->port.lock);
/* restore RTS and DTR */
cr = uap->old_cr & (UART011_CR_RTS | UART011_CR_DTR);
cr |= UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
- writew(cr, uap->port.membase + UART011_CR);
+ pl011_writew(uap, cr, REG_CR);
spin_unlock_irq(&uap->port.lock);
/*
* initialise the old status of the modem signals
*/
- uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
+ uap->old_status = pl011_readw(uap, REG_FR) & UART01x_FR_MODEM_ANY;
/* Startup DMA */
pl011_dma_startup(uap);
@@ -1675,11 +1819,11 @@
static void pl011_shutdown_channel(struct uart_amba_port *uap,
unsigned int lcrh)
{
- unsigned long val;
+ unsigned long val;
- val = readw(uap->port.membase + lcrh);
- val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
- writew(val, uap->port.membase + lcrh);
+ val = pl011_readw(uap, lcrh);
+ val &= ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN);
+ pl011_writew(uap, val, lcrh);
}
/*
@@ -1693,18 +1837,18 @@
uap->autorts = false;
spin_lock_irq(&uap->port.lock);
- cr = readw(uap->port.membase + UART011_CR);
+ cr = pl011_readw(uap, REG_CR);
uap->old_cr = cr;
cr &= UART011_CR_RTS | UART011_CR_DTR;
cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
- writew(cr, uap->port.membase + UART011_CR);
+ pl011_writew(uap, cr, REG_CR);
spin_unlock_irq(&uap->port.lock);
/*
* disable break condition and fifos
*/
pl011_shutdown_channel(uap, uap->lcrh_rx);
- if (uap->lcrh_rx != uap->lcrh_tx)
+ if (is_implemented(uap, REG_ST_LCRH_RX))
pl011_shutdown_channel(uap, uap->lcrh_tx);
}
@@ -1714,8 +1858,8 @@
/* mask all interrupts and clear all pending ones */
uap->im = 0;
- writew(uap->im, uap->port.membase + UART011_IMSC);
- writew(0xffff, uap->port.membase + UART011_ICR);
+ pl011_writew(uap, uap->im, REG_IMSC);
+ pl011_writew(uap, 0xffff, REG_ICR);
spin_unlock_irq(&uap->port.lock);
}
@@ -1867,8 +2011,8 @@
pl011_enable_ms(port);
/* first, disable everything */
- old_cr = readw(port->membase + UART011_CR);
- writew(0, port->membase + UART011_CR);
+ old_cr = pl011_readw(uap, REG_CR);
+ pl011_writew(uap, 0, REG_CR);
if (termios->c_cflag & CRTSCTS) {
if (old_cr & UART011_CR_RTS)
@@ -1901,17 +2045,17 @@
quot -= 2;
}
/* Set baud rate */
- writew(quot & 0x3f, port->membase + UART011_FBRD);
- writew(quot >> 6, port->membase + UART011_IBRD);
+ pl011_writew(uap, quot & 0x3f, REG_FBRD);
+ pl011_writew(uap, quot >> 6, REG_IBRD);
/*
* ----------v----------v----------v----------v-----
* NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER
- * UART011_FBRD & UART011_IBRD.
+ * REG_FBRD & REG_IBRD.
* ----------^----------^----------^----------^-----
*/
pl011_write_lcr_h(uap, lcr_h);
- writew(old_cr, port->membase + UART011_CR);
+ pl011_writew(uap, old_cr, REG_CR);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -2052,9 +2196,9 @@
struct uart_amba_port *uap =
container_of(port, struct uart_amba_port, port);
- while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF)
+ while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
barrier();
- writew(ch, uap->port.membase + UART01x_DR);
+ pl011_writew(uap, ch, REG_DR);
}
static void
@@ -2079,10 +2223,10 @@
* First save the CR then disable the interrupts
*/
if (!uap->vendor->always_enabled) {
- old_cr = readw(uap->port.membase + UART011_CR);
+ old_cr = pl011_readw(uap, REG_CR);
new_cr = old_cr & ~UART011_CR_CTSEN;
new_cr |= UART01x_CR_UARTEN | UART011_CR_TXE;
- writew(new_cr, uap->port.membase + UART011_CR);
+ pl011_writew(uap, new_cr, REG_CR);
}
uart_console_write(&uap->port, s, count, pl011_console_putchar);
@@ -2092,10 +2236,10 @@
* and restore the TCR
*/
do {
- status = readw(uap->port.membase + UART01x_FR);
- } while (status & UART01x_FR_BUSY);
+ status = pl011_readw(uap, REG_FR);
+ } while (status & uap->fr_busy);
if (!uap->vendor->always_enabled)
- writew(old_cr, uap->port.membase + UART011_CR);
+ pl011_writew(uap, old_cr, REG_CR);
if (locked)
spin_unlock(&uap->port.lock);
@@ -2108,10 +2252,10 @@
pl011_console_get_options(struct uart_amba_port *uap, int *baud,
int *parity, int *bits)
{
- if (readw(uap->port.membase + UART011_CR) & UART01x_CR_UARTEN) {
+ if (pl011_readw(uap, REG_CR) & UART01x_CR_UARTEN) {
unsigned int lcr_h, ibrd, fbrd;
- lcr_h = readw(uap->port.membase + uap->lcrh_tx);
+ lcr_h = pl011_readw(uap, uap->lcrh_tx);
*parity = 'n';
if (lcr_h & UART01x_LCRH_PEN) {
@@ -2126,13 +2270,13 @@
else
*bits = 8;
- ibrd = readw(uap->port.membase + UART011_IBRD);
- fbrd = readw(uap->port.membase + UART011_FBRD);
+ ibrd = pl011_readw(uap, REG_IBRD);
+ fbrd = pl011_readw(uap, REG_FBRD);
*baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
if (uap->vendor->oversampling) {
- if (readw(uap->port.membase + UART011_CR)
+ if (pl011_readw(uap, REG_CR)
& ST_UART011_CR_OVSFACT)
*baud *= 2;
}
@@ -2204,10 +2348,13 @@
static void pl011_putc(struct uart_port *port, int c)
{
- while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
+ struct uart_amba_port *uap =
+ container_of(port, struct uart_amba_port, port);
+
+ while (pl011_readw(uap, REG_FR) & UART01x_FR_TXFF)
;
- writeb(c, port->membase + UART01x_DR);
- while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
+ pl011_writeb(uap, c, REG_DR);
+ while (pl011_readw(uap, REG_FR) & uap->fr_busy)
;
}
@@ -2310,8 +2457,8 @@
void __iomem *base;
base = devm_ioremap_resource(dev, mmiobase);
- if (!base)
- return -ENOMEM;
+ if (IS_ERR(base))
+ return PTR_ERR(base);
index = pl011_probe_dt_alias(index, dev);
@@ -2334,8 +2481,8 @@
int ret;
/* Ensure interrupts from this UART are masked and cleared */
- writew(0, uap->port.membase + UART011_IMSC);
- writew(0xffff, uap->port.membase + UART011_ICR);
+ pl011_writew(uap, 0, REG_IMSC);
+ pl011_writew(uap, 0xffff, REG_ICR);
if (!amba_reg.state) {
ret = uart_register_driver(&amba_reg);
@@ -2353,6 +2500,7 @@
return ret;
}
+#ifdef CONFIG_ARM_AMBA
static int pl011_probe(struct amba_device *dev, const struct amba_id *id)
{
struct uart_amba_port *uap;
@@ -2373,8 +2521,13 @@
return PTR_ERR(uap->clk);
uap->vendor = vendor;
+ uap->reg_lut = vendor->reg_lut;
uap->lcrh_rx = vendor->lcrh_rx;
uap->lcrh_tx = vendor->lcrh_tx;
+ uap->fr_busy = vendor->fr_busy;
+ uap->fr_dsr = vendor->fr_dsr;
+ uap->fr_cts = vendor->fr_cts;
+ uap->fr_ri = vendor->fr_ri;
uap->fifosize = vendor->get_fifosize(dev);
uap->port.irq = dev->irq[0];
uap->port.ops = &amba_pl011_pops;
@@ -2398,6 +2551,67 @@
pl011_unregister_port(uap);
return 0;
}
+#endif
+
+#ifdef CONFIG_SOC_ZX296702
+static int zx_uart_probe(struct platform_device *pdev)
+{
+ struct uart_amba_port *uap;
+ struct vendor_data *vendor = &vendor_zte;
+ struct resource *res;
+ int portnr, ret;
+
+ portnr = pl011_find_free_port();
+ if (portnr < 0)
+ return portnr;
+
+ uap = devm_kzalloc(&pdev->dev, sizeof(struct uart_amba_port),
+ GFP_KERNEL);
+ if (!uap) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ uap->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(uap->clk)) {
+ ret = PTR_ERR(uap->clk);
+ goto out;
+ }
+
+ uap->vendor = vendor;
+ uap->reg_lut = vendor->reg_lut;
+ uap->lcrh_rx = vendor->lcrh_rx;
+ uap->lcrh_tx = vendor->lcrh_tx;
+ uap->fr_busy = vendor->fr_busy;
+ uap->fr_dsr = vendor->fr_dsr;
+ uap->fr_cts = vendor->fr_cts;
+ uap->fr_ri = vendor->fr_ri;
+ uap->fifosize = 16;
+ uap->port.irq = platform_get_irq(pdev, 0);
+ uap->port.ops = &amba_pl011_pops;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ ret = pl011_setup_port(&pdev->dev, uap, res, portnr);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, uap);
+
+ return pl011_register_port(uap);
+out:
+ return ret;
+}
+
+static int zx_uart_remove(struct platform_device *pdev)
+{
+ struct uart_amba_port *uap = platform_get_drvdata(pdev);
+
+ uart_remove_one_port(&amba_reg, &uap->port);
+ pl011_unregister_port(uap);
+ return 0;
+}
+#endif
#ifdef CONFIG_PM_SLEEP
static int pl011_suspend(struct device *dev)
@@ -2454,6 +2668,11 @@
return -ENOMEM;
uap->vendor = &vendor_sbsa;
+ uap->reg_lut = vendor_sbsa.reg_lut;
+ uap->fr_busy = vendor_sbsa.fr_busy;
+ uap->fr_dsr = vendor_sbsa.fr_dsr;
+ uap->fr_cts = vendor_sbsa.fr_cts;
+ uap->fr_ri = vendor_sbsa.fr_ri;
uap->fifosize = 32;
uap->port.irq = platform_get_irq(pdev, 0);
uap->port.ops = &sbsa_uart_pops;
@@ -2503,6 +2722,7 @@
},
};
+#ifdef CONFIG_ARM_AMBA
static struct amba_id pl011_ids[] = {
{
.id = 0x00041011,
@@ -2528,20 +2748,57 @@
.probe = pl011_probe,
.remove = pl011_remove,
};
+#endif
+
+#ifdef CONFIG_SOC_ZX296702
+static const struct of_device_id zx_uart_dt_ids[] = {
+ { .compatible = "zte,zx296702-uart", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, zx_uart_dt_ids);
+
+static struct platform_driver zx_uart_driver = {
+ .driver = {
+ .name = "zx-uart",
+ .owner = THIS_MODULE,
+ .pm = &pl011_dev_pm_ops,
+ .of_match_table = zx_uart_dt_ids,
+ },
+ .probe = zx_uart_probe,
+ .remove = zx_uart_remove,
+};
+#endif
+
static int __init pl011_init(void)
{
+ int ret;
printk(KERN_INFO "Serial: AMBA PL011 UART driver\n");
if (platform_driver_register(&arm_sbsa_uart_platform_driver))
pr_warn("could not register SBSA UART platform driver\n");
- return amba_driver_register(&pl011_driver);
+
+#ifdef CONFIG_SOC_ZX296702
+ ret = platform_driver_register(&zx_uart_driver);
+ if (ret)
+ pr_warn("could not register ZX UART platform driver\n");
+#endif
+
+#ifdef CONFIG_ARM_AMBA
+ ret = amba_driver_register(&pl011_driver);
+#endif
+ return ret;
}
static void __exit pl011_exit(void)
{
platform_driver_unregister(&arm_sbsa_uart_platform_driver);
+#ifdef CONFIG_SOC_ZX296702
+ platform_driver_unregister(&zx_uart_driver);
+#endif
+#ifdef CONFIG_ARM_AMBA
amba_driver_unregister(&pl011_driver);
+#endif
}
/*
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 2a8f5281..5ca5cf3 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -56,6 +56,15 @@
/* Revisit: We should calculate this based on the actual port settings */
#define PDC_RX_TIMEOUT (3 * 10) /* 3 bytes */
+/* The minium number of data FIFOs should be able to contain */
+#define ATMEL_MIN_FIFO_SIZE 8
+/*
+ * These two offsets are substracted from the RX FIFO size to define the RTS
+ * high and low thresholds
+ */
+#define ATMEL_RTS_HIGH_OFFSET 16
+#define ATMEL_RTS_LOW_OFFSET 20
+
#if defined(CONFIG_SERIAL_ATMEL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
@@ -88,37 +97,6 @@
#define ATMEL_ISR_PASS_LIMIT 256
-/* UART registers. CR is write-only, hence no GET macro */
-#define UART_PUT_CR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_CR)
-#define UART_GET_MR(port) __raw_readl((port)->membase + ATMEL_US_MR)
-#define UART_PUT_MR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_MR)
-#define UART_PUT_IER(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IER)
-#define UART_PUT_IDR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_IDR)
-#define UART_GET_IMR(port) __raw_readl((port)->membase + ATMEL_US_IMR)
-#define UART_GET_CSR(port) __raw_readl((port)->membase + ATMEL_US_CSR)
-#define UART_GET_CHAR(port) __raw_readl((port)->membase + ATMEL_US_RHR)
-#define UART_PUT_CHAR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_THR)
-#define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR)
-#define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR)
-#define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR)
-#define UART_GET_IP_NAME(port) __raw_readl((port)->membase + ATMEL_US_NAME)
-#define UART_GET_IP_VERSION(port) __raw_readl((port)->membase + ATMEL_US_VERSION)
-
- /* PDC registers */
-#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
-#define UART_GET_PTSR(port) __raw_readl((port)->membase + ATMEL_PDC_PTSR)
-
-#define UART_PUT_RPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
-#define UART_GET_RPR(port) __raw_readl((port)->membase + ATMEL_PDC_RPR)
-#define UART_PUT_RCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RCR)
-#define UART_PUT_RNPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNPR)
-#define UART_PUT_RNCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RNCR)
-
-#define UART_PUT_TPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TPR)
-#define UART_PUT_TCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_TCR)
-#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR)
-
struct atmel_dma_buffer {
unsigned char *buf;
dma_addr_t dma_addr;
@@ -166,12 +144,16 @@
unsigned int irq_status;
unsigned int irq_status_prev;
unsigned int status_change;
+ unsigned int tx_len;
struct circ_buf rx_ring;
struct mctrl_gpios *gpios;
int gpio_irq[UART_GPIO_MAX];
unsigned int tx_done_mask;
+ u32 fifo_size;
+ u32 rts_high;
+ u32 rts_low;
bool ms_irq_enabled;
bool is_usart; /* usart or uart */
struct timer_list uart_timer; /* uart timer */
@@ -212,6 +194,43 @@
return container_of(uart, struct atmel_uart_port, uart);
}
+static inline u32 atmel_uart_readl(struct uart_port *port, u32 reg)
+{
+ return __raw_readl(port->membase + reg);
+}
+
+static inline void atmel_uart_writel(struct uart_port *port, u32 reg, u32 value)
+{
+ __raw_writel(value, port->membase + reg);
+}
+
+#ifdef CONFIG_AVR32
+
+/* AVR32 cannot handle 8 or 16bit I/O accesses but only 32bit I/O accesses */
+static inline u8 atmel_uart_read_char(struct uart_port *port)
+{
+ return __raw_readl(port->membase + ATMEL_US_RHR);
+}
+
+static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
+{
+ __raw_writel(value, port->membase + ATMEL_US_THR);
+}
+
+#else
+
+static inline u8 atmel_uart_read_char(struct uart_port *port)
+{
+ return __raw_readb(port->membase + ATMEL_US_RHR);
+}
+
+static inline void atmel_uart_write_char(struct uart_port *port, u8 value)
+{
+ __raw_writeb(value, port->membase + ATMEL_US_THR);
+}
+
+#endif
+
#ifdef CONFIG_SERIAL_ATMEL_PDC
static bool atmel_use_pdc_rx(struct uart_port *port)
{
@@ -257,7 +276,7 @@
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int status, ret = 0;
- status = UART_GET_CSR(port);
+ status = atmel_uart_readl(port, ATMEL_US_CSR);
mctrl_gpio_get(atmel_port->gpios, &ret);
@@ -304,9 +323,9 @@
unsigned int mode;
/* Disable interrupts */
- UART_PUT_IDR(port, atmel_port->tx_done_mask);
+ atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
- mode = UART_GET_MR(port);
+ mode = atmel_uart_readl(port, ATMEL_US_MR);
/* Resetting serial mode to RS232 (0x0) */
mode &= ~ATMEL_US_USMODE;
@@ -316,7 +335,8 @@
if (rs485conf->flags & SER_RS485_ENABLED) {
dev_dbg(port->dev, "Setting UART to RS485\n");
atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
- UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
+ atmel_uart_writel(port, ATMEL_US_TTGR,
+ rs485conf->delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485;
} else {
dev_dbg(port->dev, "Setting UART to RS232\n");
@@ -326,10 +346,10 @@
else
atmel_port->tx_done_mask = ATMEL_US_TXRDY;
}
- UART_PUT_MR(port, mode);
+ atmel_uart_writel(port, ATMEL_US_MR, mode);
/* Enable interrupts */
- UART_PUT_IER(port, atmel_port->tx_done_mask);
+ atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
return 0;
}
@@ -339,7 +359,9 @@
*/
static u_int atmel_tx_empty(struct uart_port *port)
{
- return (UART_GET_CSR(port) & ATMEL_US_TXEMPTY) ? TIOCSER_TEMT : 0;
+ return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
+ TIOCSER_TEMT :
+ 0;
}
/*
@@ -348,13 +370,14 @@
static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
{
unsigned int control = 0;
- unsigned int mode = UART_GET_MR(port);
+ unsigned int mode = atmel_uart_readl(port, ATMEL_US_MR);
unsigned int rts_paused, rts_ready;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
/* override mode to RS485 if needed, otherwise keep the current mode */
if (port->rs485.flags & SER_RS485_ENABLED) {
- UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+ atmel_uart_writel(port, ATMEL_US_TTGR,
+ port->rs485.delay_rts_after_send);
mode &= ~ATMEL_US_USMODE;
mode |= ATMEL_US_USMODE_RS485;
}
@@ -384,7 +407,7 @@
else
control |= ATMEL_US_DTRDIS;
- UART_PUT_CR(port, control);
+ atmel_uart_writel(port, ATMEL_US_CR, control);
mctrl_gpio_set(atmel_port->gpios, mctrl);
@@ -395,7 +418,7 @@
else
mode |= ATMEL_US_CHMODE_NORMAL;
- UART_PUT_MR(port, mode);
+ atmel_uart_writel(port, ATMEL_US_MR, mode);
}
/*
@@ -406,7 +429,7 @@
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int ret = 0, status;
- status = UART_GET_CSR(port);
+ status = atmel_uart_readl(port, ATMEL_US_CSR);
/*
* The control signals are active low.
@@ -432,10 +455,10 @@
if (atmel_use_pdc_tx(port)) {
/* disable PDC transmit */
- UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
}
/* Disable interrupts */
- UART_PUT_IDR(port, atmel_port->tx_done_mask);
+ atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
if ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX))
@@ -450,7 +473,7 @@
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (atmel_use_pdc_tx(port)) {
- if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN)
+ if (atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN)
/* The transmitter is already running. Yes, we
really need this.*/
return;
@@ -460,10 +483,10 @@
atmel_stop_rx(port);
/* re-enable PDC transmit */
- UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
}
/* Enable interrupts */
- UART_PUT_IER(port, atmel_port->tx_done_mask);
+ atmel_uart_writel(port, ATMEL_US_IER, atmel_port->tx_done_mask);
}
/*
@@ -471,17 +494,19 @@
*/
static void atmel_start_rx(struct uart_port *port)
{
- UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */
+ /* reset status and receiver */
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
- UART_PUT_CR(port, ATMEL_US_RXEN);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXEN);
if (atmel_use_pdc_rx(port)) {
/* enable PDC controller */
- UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
- port->read_status_mask);
- UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+ atmel_uart_writel(port, ATMEL_US_IER,
+ ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+ port->read_status_mask);
+ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
} else {
- UART_PUT_IER(port, ATMEL_US_RXRDY);
+ atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
}
}
@@ -490,15 +515,16 @@
*/
static void atmel_stop_rx(struct uart_port *port)
{
- UART_PUT_CR(port, ATMEL_US_RXDIS);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RXDIS);
if (atmel_use_pdc_rx(port)) {
/* disable PDC receive */
- UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS);
- UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
- port->read_status_mask);
+ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTDIS);
+ atmel_uart_writel(port, ATMEL_US_IDR,
+ ATMEL_US_ENDRX | ATMEL_US_TIMEOUT |
+ port->read_status_mask);
} else {
- UART_PUT_IDR(port, ATMEL_US_RXRDY);
+ atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXRDY);
}
}
@@ -538,7 +564,7 @@
else
ier |= ATMEL_US_DCDIC;
- UART_PUT_IER(port, ier);
+ atmel_uart_writel(port, ATMEL_US_IER, ier);
}
/*
@@ -577,7 +603,7 @@
else
idr |= ATMEL_US_DCDIC;
- UART_PUT_IDR(port, idr);
+ atmel_uart_writel(port, ATMEL_US_IDR, idr);
}
/*
@@ -586,9 +612,11 @@
static void atmel_break_ctl(struct uart_port *port, int break_state)
{
if (break_state != 0)
- UART_PUT_CR(port, ATMEL_US_STTBRK); /* start break */
+ /* start break */
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTBRK);
else
- UART_PUT_CR(port, ATMEL_US_STPBRK); /* stop break */
+ /* stop break */
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STPBRK);
}
/*
@@ -622,7 +650,7 @@
static void atmel_pdc_rxerr(struct uart_port *port, unsigned int status)
{
/* clear error */
- UART_PUT_CR(port, ATMEL_US_RSTSTA);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
if (status & ATMEL_US_RXBRK) {
/* ignore side-effect */
@@ -645,9 +673,9 @@
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
unsigned int status, ch;
- status = UART_GET_CSR(port);
+ status = atmel_uart_readl(port, ATMEL_US_CSR);
while (status & ATMEL_US_RXRDY) {
- ch = UART_GET_CHAR(port);
+ ch = atmel_uart_read_char(port);
/*
* note that the error handling code is
@@ -658,12 +686,13 @@
|| atmel_port->break_active)) {
/* clear error */
- UART_PUT_CR(port, ATMEL_US_RSTSTA);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
if (status & ATMEL_US_RXBRK
&& !atmel_port->break_active) {
atmel_port->break_active = 1;
- UART_PUT_IER(port, ATMEL_US_RXBRK);
+ atmel_uart_writel(port, ATMEL_US_IER,
+ ATMEL_US_RXBRK);
} else {
/*
* This is either the end-of-break
@@ -672,14 +701,15 @@
* being set. In both cases, the next
* RXBRK will indicate start-of-break.
*/
- UART_PUT_IDR(port, ATMEL_US_RXBRK);
+ atmel_uart_writel(port, ATMEL_US_IDR,
+ ATMEL_US_RXBRK);
status &= ~ATMEL_US_RXBRK;
atmel_port->break_active = 0;
}
}
atmel_buffer_rx_char(port, status, ch);
- status = UART_GET_CSR(port);
+ status = atmel_uart_readl(port, ATMEL_US_CSR);
}
tasklet_schedule(&atmel_port->tasklet);
@@ -694,16 +724,18 @@
struct circ_buf *xmit = &port->state->xmit;
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) {
- UART_PUT_CHAR(port, port->x_char);
+ if (port->x_char &&
+ (atmel_uart_readl(port, ATMEL_US_CSR) & atmel_port->tx_done_mask)) {
+ atmel_uart_write_char(port, port->x_char);
port->icount.tx++;
port->x_char = 0;
}
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
return;
- while (UART_GET_CSR(port) & atmel_port->tx_done_mask) {
- UART_PUT_CHAR(port, xmit->buf[xmit->tail]);
+ while (atmel_uart_readl(port, ATMEL_US_CSR) &
+ atmel_port->tx_done_mask) {
+ atmel_uart_write_char(port, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
if (uart_circ_empty(xmit))
@@ -715,7 +747,8 @@
if (!uart_circ_empty(xmit))
/* Enable interrupts */
- UART_PUT_IER(port, atmel_port->tx_done_mask);
+ atmel_uart_writel(port, ATMEL_US_IER,
+ atmel_port->tx_done_mask);
}
static void atmel_complete_tx_dma(void *arg)
@@ -730,10 +763,10 @@
if (chan)
dmaengine_terminate_all(chan);
- xmit->tail += sg_dma_len(&atmel_port->sg_tx);
+ xmit->tail += atmel_port->tx_len;
xmit->tail &= UART_XMIT_SIZE - 1;
- port->icount.tx += sg_dma_len(&atmel_port->sg_tx);
+ port->icount.tx += atmel_port->tx_len;
spin_lock_irq(&atmel_port->lock_tx);
async_tx_ack(atmel_port->desc_tx);
@@ -781,7 +814,9 @@
struct circ_buf *xmit = &port->state->xmit;
struct dma_chan *chan = atmel_port->chan_tx;
struct dma_async_tx_descriptor *desc;
- struct scatterlist *sg = &atmel_port->sg_tx;
+ struct scatterlist sgl[2], *sg, *sg_tx = &atmel_port->sg_tx;
+ unsigned int tx_len, part1_len, part2_len, sg_len;
+ dma_addr_t phys_addr;
/* Make sure we have an idle channel */
if (atmel_port->desc_tx != NULL)
@@ -797,18 +832,46 @@
* Take the port lock to get a
* consistent xmit buffer state.
*/
- sg->offset = xmit->tail & (UART_XMIT_SIZE - 1);
- sg_dma_address(sg) = (sg_dma_address(sg) &
- ~(UART_XMIT_SIZE - 1))
- + sg->offset;
- sg_dma_len(sg) = CIRC_CNT_TO_END(xmit->head,
- xmit->tail,
- UART_XMIT_SIZE);
- BUG_ON(!sg_dma_len(sg));
+ tx_len = CIRC_CNT_TO_END(xmit->head,
+ xmit->tail,
+ UART_XMIT_SIZE);
+
+ if (atmel_port->fifo_size) {
+ /* multi data mode */
+ part1_len = (tx_len & ~0x3); /* DWORD access */
+ part2_len = (tx_len & 0x3); /* BYTE access */
+ } else {
+ /* single data (legacy) mode */
+ part1_len = 0;
+ part2_len = tx_len; /* BYTE access only */
+ }
+
+ sg_init_table(sgl, 2);
+ sg_len = 0;
+ phys_addr = sg_dma_address(sg_tx) + xmit->tail;
+ if (part1_len) {
+ sg = &sgl[sg_len++];
+ sg_dma_address(sg) = phys_addr;
+ sg_dma_len(sg) = part1_len;
+
+ phys_addr += part1_len;
+ }
+
+ if (part2_len) {
+ sg = &sgl[sg_len++];
+ sg_dma_address(sg) = phys_addr;
+ sg_dma_len(sg) = part2_len;
+ }
+
+ /*
+ * save tx_len so atmel_complete_tx_dma() will increase
+ * xmit->tail correctly
+ */
+ atmel_port->tx_len = tx_len;
desc = dmaengine_prep_slave_sg(chan,
- sg,
- 1,
+ sgl,
+ sg_len,
DMA_MEM_TO_DEV,
DMA_PREP_INTERRUPT |
DMA_CTRL_ACK);
@@ -817,7 +880,7 @@
return;
}
- dma_sync_sg_for_device(port->dev, sg, 1, DMA_TO_DEVICE);
+ dma_sync_sg_for_device(port->dev, sg_tx, 1, DMA_TO_DEVICE);
atmel_port->desc_tx = desc;
desc->callback = atmel_complete_tx_dma;
@@ -877,7 +940,9 @@
/* Configure the slave DMA */
memset(&config, 0, sizeof(config));
config.direction = DMA_MEM_TO_DEV;
- config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ config.dst_addr_width = (atmel_port->fifo_size) ?
+ DMA_SLAVE_BUSWIDTH_4_BYTES :
+ DMA_SLAVE_BUSWIDTH_1_BYTE;
config.dst_addr = port->mapbase + ATMEL_US_THR;
config.dst_maxburst = 1;
@@ -935,14 +1000,14 @@
/* Reset the UART timeout early so that we don't miss one */
- UART_PUT_CR(port, ATMEL_US_STTTO);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
dmastat = dmaengine_tx_status(chan,
atmel_port->cookie_rx,
&state);
/* Restart a new tasklet if DMA status is error */
if (dmastat == DMA_ERROR) {
dev_dbg(port->dev, "Get residue error, restart tasklet\n");
- UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+ atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
tasklet_schedule(&atmel_port->tasklet);
return;
}
@@ -1008,7 +1073,7 @@
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
- UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+ atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_TIMEOUT);
}
static int atmel_prepare_rx_dma(struct uart_port *port)
@@ -1118,8 +1183,8 @@
* the moment.
*/
if (pending & (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT)) {
- UART_PUT_IDR(port, (ATMEL_US_ENDRX
- | ATMEL_US_TIMEOUT));
+ atmel_uart_writel(port, ATMEL_US_IDR,
+ (ATMEL_US_ENDRX | ATMEL_US_TIMEOUT));
tasklet_schedule(&atmel_port->tasklet);
}
@@ -1130,7 +1195,8 @@
if (atmel_use_dma_rx(port)) {
if (pending & ATMEL_US_TIMEOUT) {
- UART_PUT_IDR(port, ATMEL_US_TIMEOUT);
+ atmel_uart_writel(port, ATMEL_US_IDR,
+ ATMEL_US_TIMEOUT);
tasklet_schedule(&atmel_port->tasklet);
}
}
@@ -1143,8 +1209,8 @@
* End of break detected. If it came along with a
* character, atmel_rx_chars will handle it.
*/
- UART_PUT_CR(port, ATMEL_US_RSTSTA);
- UART_PUT_IDR(port, ATMEL_US_RXBRK);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+ atmel_uart_writel(port, ATMEL_US_IDR, ATMEL_US_RXBRK);
atmel_port->break_active = 0;
}
}
@@ -1159,7 +1225,8 @@
if (pending & atmel_port->tx_done_mask) {
/* Either PDC or interrupt transmission */
- UART_PUT_IDR(port, atmel_port->tx_done_mask);
+ atmel_uart_writel(port, ATMEL_US_IDR,
+ atmel_port->tx_done_mask);
tasklet_schedule(&atmel_port->tasklet);
}
}
@@ -1197,7 +1264,7 @@
do {
status = atmel_get_lines_status(port);
- mask = UART_GET_IMR(port);
+ mask = atmel_uart_readl(port, ATMEL_US_IMR);
pending = status & mask;
if (!gpio_handled) {
/*
@@ -1223,7 +1290,7 @@
if (atmel_port->suspended) {
atmel_port->pending |= pending;
atmel_port->pending_status = status;
- UART_PUT_IDR(port, mask);
+ atmel_uart_writel(port, ATMEL_US_IDR, mask);
pm_system_wakeup();
break;
}
@@ -1260,7 +1327,7 @@
int count;
/* nothing left to transmit? */
- if (UART_GET_TCR(port))
+ if (atmel_uart_readl(port, ATMEL_PDC_TCR))
return;
xmit->tail += pdc->ofs;
@@ -1272,7 +1339,7 @@
/* more to transmit - setup next transfer */
/* disable PDC transmit */
- UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
if (!uart_circ_empty(xmit) && !uart_tx_stopped(port)) {
dma_sync_single_for_device(port->dev,
@@ -1283,12 +1350,14 @@
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
pdc->ofs = count;
- UART_PUT_TPR(port, pdc->dma_addr + xmit->tail);
- UART_PUT_TCR(port, count);
+ atmel_uart_writel(port, ATMEL_PDC_TPR,
+ pdc->dma_addr + xmit->tail);
+ atmel_uart_writel(port, ATMEL_PDC_TCR, count);
/* re-enable PDC transmit */
- UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
/* Enable interrupts */
- UART_PUT_IER(port, atmel_port->tx_done_mask);
+ atmel_uart_writel(port, ATMEL_US_IER,
+ atmel_port->tx_done_mask);
} else {
if ((port->rs485.flags & SER_RS485_ENABLED) &&
!(port->rs485.flags & SER_RS485_RX_DURING_TX)) {
@@ -1414,10 +1483,10 @@
do {
/* Reset the UART timeout early so that we don't miss one */
- UART_PUT_CR(port, ATMEL_US_STTTO);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
pdc = &atmel_port->pdc_rx[rx_idx];
- head = UART_GET_RPR(port) - pdc->dma_addr;
+ head = atmel_uart_readl(port, ATMEL_PDC_RPR) - pdc->dma_addr;
tail = pdc->ofs;
/* If the PDC has switched buffers, RPR won't contain
@@ -1460,8 +1529,8 @@
*/
if (head >= pdc->dma_size) {
pdc->ofs = 0;
- UART_PUT_RNPR(port, pdc->dma_addr);
- UART_PUT_RNCR(port, pdc->dma_size);
+ atmel_uart_writel(port, ATMEL_PDC_RNPR, pdc->dma_addr);
+ atmel_uart_writel(port, ATMEL_PDC_RNCR, pdc->dma_size);
rx_idx = !rx_idx;
atmel_port->pdc_rx_idx = rx_idx;
@@ -1476,7 +1545,8 @@
tty_flip_buffer_push(tport);
spin_lock(&port->lock);
- UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+ atmel_uart_writel(port, ATMEL_US_IER,
+ ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
}
static int atmel_prepare_rx_pdc(struct uart_port *port)
@@ -1509,11 +1579,12 @@
atmel_port->pdc_rx_idx = 0;
- UART_PUT_RPR(port, atmel_port->pdc_rx[0].dma_addr);
- UART_PUT_RCR(port, PDC_BUFFER_SIZE);
+ atmel_uart_writel(port, ATMEL_PDC_RPR, atmel_port->pdc_rx[0].dma_addr);
+ atmel_uart_writel(port, ATMEL_PDC_RCR, PDC_BUFFER_SIZE);
- UART_PUT_RNPR(port, atmel_port->pdc_rx[1].dma_addr);
- UART_PUT_RNCR(port, PDC_BUFFER_SIZE);
+ atmel_uart_writel(port, ATMEL_PDC_RNPR,
+ atmel_port->pdc_rx[1].dma_addr);
+ atmel_uart_writel(port, ATMEL_PDC_RNCR, PDC_BUFFER_SIZE);
return 0;
}
@@ -1667,7 +1738,7 @@
static void atmel_get_ip_name(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
- int name = UART_GET_IP_NAME(port);
+ int name = atmel_uart_readl(port, ATMEL_US_NAME);
u32 version;
int usart, uart;
/* usart and uart ascii */
@@ -1684,7 +1755,7 @@
atmel_port->is_usart = false;
} else {
/* fallback for older SoCs: use version field */
- version = UART_GET_IP_VERSION(port);
+ version = atmel_uart_readl(port, ATMEL_US_VERSION);
switch (version) {
case 0x302:
case 0x10213:
@@ -1756,7 +1827,7 @@
* request_irq() is called we could get stuck trying to
* handle an unexpected interrupt
*/
- UART_PUT_IDR(port, -1);
+ atmel_uart_writel(port, ATMEL_US_IDR, -1);
atmel_port->ms_irq_enabled = false;
/*
@@ -1797,6 +1868,32 @@
atmel_set_ops(port);
}
+ /*
+ * Enable FIFO when available
+ */
+ if (atmel_port->fifo_size) {
+ unsigned int txrdym = ATMEL_US_ONE_DATA;
+ unsigned int rxrdym = ATMEL_US_ONE_DATA;
+ unsigned int fmr;
+
+ atmel_uart_writel(port, ATMEL_US_CR,
+ ATMEL_US_FIFOEN |
+ ATMEL_US_RXFCLR |
+ ATMEL_US_TXFLCLR);
+
+ if (atmel_use_dma_tx(port))
+ txrdym = ATMEL_US_FOUR_DATA;
+
+ fmr = ATMEL_US_TXRDYM(txrdym) | ATMEL_US_RXRDYM(rxrdym);
+ if (atmel_port->rts_high &&
+ atmel_port->rts_low)
+ fmr |= ATMEL_US_FRTSC |
+ ATMEL_US_RXFTHRES(atmel_port->rts_high) |
+ ATMEL_US_RXFTHRES2(atmel_port->rts_low);
+
+ atmel_uart_writel(port, ATMEL_US_FMR, fmr);
+ }
+
/* Save current CSR for comparison in atmel_tasklet_func() */
atmel_port->irq_status_prev = atmel_get_lines_status(port);
atmel_port->irq_status = atmel_port->irq_status_prev;
@@ -1804,9 +1901,9 @@
/*
* Finally, enable the serial port
*/
- UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
/* enable xmit & rcvr */
- UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
setup_timer(&atmel_port->uart_timer,
atmel_uart_timer_callback,
@@ -1819,13 +1916,14 @@
jiffies + uart_poll_timeout(port));
/* set USART timeout */
} else {
- UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
- UART_PUT_CR(port, ATMEL_US_STTTO);
+ atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
- UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
+ atmel_uart_writel(port, ATMEL_US_IER,
+ ATMEL_US_ENDRX | ATMEL_US_TIMEOUT);
}
/* enable PDC controller */
- UART_PUT_PTCR(port, ATMEL_PDC_RXTEN);
+ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_RXTEN);
} else if (atmel_use_dma_rx(port)) {
/* set UART timeout */
if (!atmel_port->is_usart) {
@@ -1833,14 +1931,15 @@
jiffies + uart_poll_timeout(port));
/* set USART timeout */
} else {
- UART_PUT_RTOR(port, PDC_RX_TIMEOUT);
- UART_PUT_CR(port, ATMEL_US_STTTO);
+ atmel_uart_writel(port, ATMEL_US_RTOR, PDC_RX_TIMEOUT);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_STTTO);
- UART_PUT_IER(port, ATMEL_US_TIMEOUT);
+ atmel_uart_writel(port, ATMEL_US_IER,
+ ATMEL_US_TIMEOUT);
}
} else {
/* enable receive only */
- UART_PUT_IER(port, ATMEL_US_RXRDY);
+ atmel_uart_writel(port, ATMEL_US_IER, ATMEL_US_RXRDY);
}
return 0;
@@ -1860,7 +1959,7 @@
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
if (atmel_use_pdc_tx(port)) {
- UART_PUT_TCR(port, 0);
+ atmel_uart_writel(port, ATMEL_PDC_TCR, 0);
atmel_port->pdc_tx.ofs = 0;
}
}
@@ -1892,8 +1991,8 @@
atmel_stop_rx(port);
atmel_stop_tx(port);
- UART_PUT_CR(port, ATMEL_US_RSTSTA);
- UART_PUT_IDR(port, -1);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA);
+ atmel_uart_writel(port, ATMEL_US_IDR, -1);
/*
@@ -1938,12 +2037,12 @@
clk_prepare_enable(atmel_port->clk);
/* re-enable interrupts if we disabled some on suspend */
- UART_PUT_IER(port, atmel_port->backup_imr);
+ atmel_uart_writel(port, ATMEL_US_IER, atmel_port->backup_imr);
break;
case 3:
/* Back up the interrupt mask and disable all interrupts */
- atmel_port->backup_imr = UART_GET_IMR(port);
- UART_PUT_IDR(port, -1);
+ atmel_port->backup_imr = atmel_uart_readl(port, ATMEL_US_IMR);
+ atmel_uart_writel(port, ATMEL_US_IDR, -1);
/*
* Disable the peripheral clock for this serial port.
@@ -1966,7 +2065,7 @@
unsigned int old_mode, mode, imr, quot, baud;
/* save the current mode register */
- mode = old_mode = UART_GET_MR(port);
+ mode = old_mode = atmel_uart_readl(port, ATMEL_US_MR);
/* reset the mode, clock divisor, parity, stop bits and data size */
mode &= ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | ATMEL_US_NBSTOP |
@@ -2025,7 +2124,7 @@
if (atmel_use_pdc_rx(port))
/* need to enable error interrupts */
- UART_PUT_IER(port, port->read_status_mask);
+ atmel_uart_writel(port, ATMEL_US_IER, port->read_status_mask);
/*
* Characters to ignore
@@ -2052,15 +2151,16 @@
* transmitter is empty if requested by the caller, so there's
* no need to wait for it here.
*/
- imr = UART_GET_IMR(port);
- UART_PUT_IDR(port, -1);
+ imr = atmel_uart_readl(port, ATMEL_US_IMR);
+ atmel_uart_writel(port, ATMEL_US_IDR, -1);
/* disable receiver and transmitter */
- UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
/* mode */
if (port->rs485.flags & SER_RS485_ENABLED) {
- UART_PUT_TTGR(port, port->rs485.delay_rts_after_send);
+ atmel_uart_writel(port, ATMEL_US_TTGR,
+ port->rs485.delay_rts_after_send);
mode |= ATMEL_US_USMODE_RS485;
} else if (termios->c_cflag & CRTSCTS) {
/* RS232 with hardware handshake (RTS/CTS) */
@@ -2071,7 +2171,7 @@
}
/* set the mode, clock divisor, parity, stop bits and data size */
- UART_PUT_MR(port, mode);
+ atmel_uart_writel(port, ATMEL_US_MR, mode);
/*
* when switching the mode, set the RTS line state according to the
@@ -2088,16 +2188,16 @@
rts_state = ATMEL_US_RTSEN;
}
- UART_PUT_CR(port, rts_state);
+ atmel_uart_writel(port, ATMEL_US_CR, rts_state);
}
/* set the baud rate */
- UART_PUT_BRGR(port, quot);
- UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
- UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+ atmel_uart_writel(port, ATMEL_US_BRGR, quot);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
/* restore interrupts */
- UART_PUT_IER(port, imr);
+ atmel_uart_writel(port, ATMEL_US_IER, imr);
/* CTS flow-control and modem-status interrupts */
if (UART_ENABLE_MS(port, termios->c_cflag))
@@ -2208,18 +2308,18 @@
#ifdef CONFIG_CONSOLE_POLL
static int atmel_poll_get_char(struct uart_port *port)
{
- while (!(UART_GET_CSR(port) & ATMEL_US_RXRDY))
+ while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_RXRDY))
cpu_relax();
- return UART_GET_CHAR(port);
+ return atmel_uart_read_char(port);
}
static void atmel_poll_put_char(struct uart_port *port, unsigned char ch)
{
- while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+ while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
cpu_relax();
- UART_PUT_CHAR(port, ch);
+ atmel_uart_write_char(port, ch);
}
#endif
@@ -2324,9 +2424,9 @@
#ifdef CONFIG_SERIAL_ATMEL_CONSOLE
static void atmel_console_putchar(struct uart_port *port, int ch)
{
- while (!(UART_GET_CSR(port) & ATMEL_US_TXRDY))
+ while (!(atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXRDY))
cpu_relax();
- UART_PUT_CHAR(port, ch);
+ atmel_uart_write_char(port, ch);
}
/*
@@ -2342,12 +2442,13 @@
/*
* First, save IMR and then disable interrupts
*/
- imr = UART_GET_IMR(port);
- UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask);
+ imr = atmel_uart_readl(port, ATMEL_US_IMR);
+ atmel_uart_writel(port, ATMEL_US_IDR,
+ ATMEL_US_RXRDY | atmel_port->tx_done_mask);
/* Store PDC transmit status and disable it */
- pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN;
- UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
+ pdc_tx = atmel_uart_readl(port, ATMEL_PDC_PTSR) & ATMEL_PDC_TXTEN;
+ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTDIS);
uart_console_write(port, s, count, atmel_console_putchar);
@@ -2356,15 +2457,15 @@
* and restore IMR
*/
do {
- status = UART_GET_CSR(port);
+ status = atmel_uart_readl(port, ATMEL_US_CSR);
} while (!(status & ATMEL_US_TXRDY));
/* Restore PDC transmit status */
if (pdc_tx)
- UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
+ atmel_uart_writel(port, ATMEL_PDC_PTCR, ATMEL_PDC_TXTEN);
/* set interrupts back the way they were */
- UART_PUT_IER(port, imr);
+ atmel_uart_writel(port, ATMEL_US_IER, imr);
}
/*
@@ -2380,17 +2481,17 @@
* If the baud rate generator isn't running, the port wasn't
* initialized by the boot loader.
*/
- quot = UART_GET_BRGR(port) & ATMEL_US_CD;
+ quot = atmel_uart_readl(port, ATMEL_US_BRGR) & ATMEL_US_CD;
if (!quot)
return;
- mr = UART_GET_MR(port) & ATMEL_US_CHRL;
+ mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_CHRL;
if (mr == ATMEL_US_CHRL_8)
*bits = 8;
else
*bits = 7;
- mr = UART_GET_MR(port) & ATMEL_US_PAR;
+ mr = atmel_uart_readl(port, ATMEL_US_MR) & ATMEL_US_PAR;
if (mr == ATMEL_US_PAR_EVEN)
*parity = 'e';
else if (mr == ATMEL_US_PAR_ODD)
@@ -2423,9 +2524,9 @@
if (ret)
return ret;
- UART_PUT_IDR(port, -1);
- UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
- UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN);
+ atmel_uart_writel(port, ATMEL_US_IDR, -1);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
+ atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
@@ -2532,7 +2633,8 @@
if (atmel_is_console_port(port) && console_suspend_enabled) {
/* Drain the TX shifter */
- while (!(UART_GET_CSR(port) & ATMEL_US_TXEMPTY))
+ while (!(atmel_uart_readl(port, ATMEL_US_CSR) &
+ ATMEL_US_TXEMPTY))
cpu_relax();
}
@@ -2599,6 +2701,48 @@
return 0;
}
+static void atmel_serial_probe_fifos(struct atmel_uart_port *port,
+ struct platform_device *pdev)
+{
+ port->fifo_size = 0;
+ port->rts_low = 0;
+ port->rts_high = 0;
+
+ if (of_property_read_u32(pdev->dev.of_node,
+ "atmel,fifo-size",
+ &port->fifo_size))
+ return;
+
+ if (!port->fifo_size)
+ return;
+
+ if (port->fifo_size < ATMEL_MIN_FIFO_SIZE) {
+ port->fifo_size = 0;
+ dev_err(&pdev->dev, "Invalid FIFO size\n");
+ return;
+ }
+
+ /*
+ * 0 <= rts_low <= rts_high <= fifo_size
+ * Once their CTS line asserted by the remote peer, some x86 UARTs tend
+ * to flush their internal TX FIFO, commonly up to 16 data, before
+ * actually stopping to send new data. So we try to set the RTS High
+ * Threshold to a reasonably high value respecting this 16 data
+ * empirical rule when possible.
+ */
+ port->rts_high = max_t(int, port->fifo_size >> 1,
+ port->fifo_size - ATMEL_RTS_HIGH_OFFSET);
+ port->rts_low = max_t(int, port->fifo_size >> 2,
+ port->fifo_size - ATMEL_RTS_LOW_OFFSET);
+
+ dev_info(&pdev->dev, "Using FIFO (%u data)\n",
+ port->fifo_size);
+ dev_dbg(&pdev->dev, "RTS High Threshold : %2u data\n",
+ port->rts_high);
+ dev_dbg(&pdev->dev, "RTS Low Threshold : %2u data\n",
+ port->rts_low);
+}
+
static int atmel_serial_probe(struct platform_device *pdev)
{
struct atmel_uart_port *port;
@@ -2635,6 +2779,7 @@
port = &atmel_ports[ret];
port->backup_imr = 0;
port->uart.line = ret;
+ atmel_serial_probe_fifos(port, pdev);
spin_lock_init(&port->lock_suspended);
@@ -2684,8 +2829,9 @@
clk_prepare_enable(port->clk);
if (rs485_enabled) {
- UART_PUT_MR(&port->uart, ATMEL_US_USMODE_NORMAL);
- UART_PUT_CR(&port->uart, ATMEL_US_RTSEN);
+ atmel_uart_writel(&port->uart, ATMEL_US_MR,
+ ATMEL_US_USMODE_NORMAL);
+ atmel_uart_writel(&port->uart, ATMEL_US_CR, ATMEL_US_RTSEN);
}
/*
diff --git a/drivers/tty/serial/etraxfs-uart.c b/drivers/tty/serial/etraxfs-uart.c
index a57301a..6813e31 100644
--- a/drivers/tty/serial/etraxfs-uart.c
+++ b/drivers/tty/serial/etraxfs-uart.c
@@ -10,6 +10,8 @@
#include <linux/of_address.h>
#include <hwregs/ser_defs.h>
+#include "serial_mctrl_gpio.h"
+
#define DRV_NAME "etraxfs-uart"
#define UART_NR CONFIG_ETRAX_SERIAL_PORTS
@@ -28,10 +30,7 @@
void __iomem *regi_ser;
- struct gpio_desc *dtr_pin;
- struct gpio_desc *dsr_pin;
- struct gpio_desc *ri_pin;
- struct gpio_desc *cd_pin;
+ struct mctrl_gpios *gpios;
int write_ongoing;
};
@@ -112,17 +111,10 @@
return 0;
}
-static struct tty_driver *cris_console_device(struct console *co, int *index)
-{
- struct uart_driver *p = co->data;
- *index = co->index;
- return p->tty_driver;
-}
-
static struct console cris_console = {
.name = "ttyS",
.write = cris_console_write,
- .device = cris_console_device,
+ .device = uart_console_device,
.setup = cris_console_setup,
.flags = CON_PRINTBUFFER,
.index = -1,
@@ -373,14 +365,6 @@
REG_WR(ser, regi_ser, rw_rec_ctrl, rec_ctrl);
}
-static void etraxfs_uart_enable_ms(struct uart_port *port)
-{
-}
-
-static void check_modem_status(struct uart_cris_port *up)
-{
-}
-
static unsigned int etraxfs_uart_tx_empty(struct uart_port *port)
{
struct uart_cris_port *up = (struct uart_cris_port *)port;
@@ -404,21 +388,9 @@
ret = 0;
if (crisv32_serial_get_rts(up))
ret |= TIOCM_RTS;
- /* DTR is active low */
- if (up->dtr_pin && !gpiod_get_raw_value(up->dtr_pin))
- ret |= TIOCM_DTR;
- /* CD is active low */
- if (up->cd_pin && !gpiod_get_raw_value(up->cd_pin))
- ret |= TIOCM_CD;
- /* RI is active low */
- if (up->ri_pin && !gpiod_get_raw_value(up->ri_pin))
- ret |= TIOCM_RI;
- /* DSR is active low */
- if (up->dsr_pin && !gpiod_get_raw_value(up->dsr_pin))
- ret |= TIOCM_DSR;
if (crisv32_serial_get_cts(up))
ret |= TIOCM_CTS;
- return ret;
+ return mctrl_gpio_get(up->gpios, &ret);
}
static void etraxfs_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
@@ -426,15 +398,7 @@
struct uart_cris_port *up = (struct uart_cris_port *)port;
crisv32_serial_set_rts(up, mctrl & TIOCM_RTS ? 1 : 0, 0);
- /* DTR is active low */
- if (up->dtr_pin)
- gpiod_set_raw_value(up->dtr_pin, mctrl & TIOCM_DTR ? 0 : 1);
- /* RI is active low */
- if (up->ri_pin)
- gpiod_set_raw_value(up->ri_pin, mctrl & TIOCM_RNG ? 0 : 1);
- /* CD is active low */
- if (up->cd_pin)
- gpiod_set_raw_value(up->cd_pin, mctrl & TIOCM_CD ? 0 : 1);
+ mctrl_gpio_set(up->gpios, mctrl);
}
static void etraxfs_uart_break_ctl(struct uart_port *port, int break_state)
@@ -598,7 +562,6 @@
receive_chars_no_dma(up);
handled = 1;
}
- check_modem_status(up);
if (masked_intr.tr_rdy) {
transmit_chars_no_dma(up);
@@ -862,7 +825,6 @@
.start_tx = etraxfs_uart_start_tx,
.send_xchar = etraxfs_uart_send_xchar,
.stop_rx = etraxfs_uart_stop_rx,
- .enable_ms = etraxfs_uart_enable_ms,
.break_ctl = etraxfs_uart_break_ctl,
.startup = etraxfs_uart_startup,
.shutdown = etraxfs_uart_shutdown,
@@ -930,11 +892,12 @@
up->irq = irq_of_parse_and_map(np, 0);
up->regi_ser = of_iomap(np, 0);
- up->dtr_pin = devm_gpiod_get_optional(&pdev->dev, "dtr");
- up->dsr_pin = devm_gpiod_get_optional(&pdev->dev, "dsr");
- up->ri_pin = devm_gpiod_get_optional(&pdev->dev, "ri");
- up->cd_pin = devm_gpiod_get_optional(&pdev->dev, "cd");
up->port.dev = &pdev->dev;
+
+ up->gpios = mctrl_gpio_init(&pdev->dev, 0);
+ if (IS_ERR(up->gpios))
+ return PTR_ERR(up->gpios);
+
cris_serial_port_init(&up->port, dev_id);
etraxfs_uart_ports[dev_id] = up;
@@ -950,7 +913,7 @@
port = platform_get_drvdata(pdev);
uart_remove_one_port(&etraxfs_uart_driver, port);
- etraxfs_uart_ports[pdev->id] = NULL;
+ etraxfs_uart_ports[port->line] = NULL;
return 0;
}
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 2c90dc3..fe3d41c 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -216,6 +216,8 @@
unsigned int tx_bytes;
unsigned int dma_tx_nents;
wait_queue_head_t dma_wait;
+ unsigned int saved_reg[10];
+ bool context_saved;
};
struct imx_port_ucrs {
@@ -700,7 +702,8 @@
if (sport->port.ignore_status_mask & URXD_DUMMY_READ)
goto out;
- tty_insert_flip_char(port, rx, flg);
+ if (tty_insert_flip_char(port, rx, flg) == 0)
+ sport->port.icount.buf_overrun++;
}
out:
@@ -766,7 +769,6 @@
writel(USR1_AWAKE, sport->port.membase + USR1);
if (sts2 & USR2_ORE) {
- dev_err(sport->port.dev, "Rx FIFO overrun\n");
sport->port.icount.overrun++;
writel(USR2_ORE, sport->port.membase + USR2);
}
@@ -921,8 +923,13 @@
dev_dbg(sport->port.dev, "We get %d bytes.\n", count);
if (count) {
- if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ))
- tty_insert_flip_string(port, sport->rx_buf, count);
+ if (!(sport->port.ignore_status_mask & URXD_DUMMY_READ)) {
+ int bytes = tty_insert_flip_string(port, sport->rx_buf,
+ count);
+
+ if (bytes != count)
+ sport->port.icount.buf_overrun++;
+ }
tty_flip_buffer_push(port);
start_rx_dma(sport);
@@ -1121,11 +1128,6 @@
writel(temp & ~UCR4_DREN, sport->port.membase + UCR4);
- /* Can we enable the DMA support? */
- if (is_imx6q_uart(sport) && !uart_console(port) &&
- !sport->dma_is_inited)
- imx_uart_dma_init(sport);
-
spin_lock_irqsave(&sport->port.lock, flags);
/* Reset fifo's and state machines */
i = 100;
@@ -1143,9 +1145,6 @@
writel(USR1_RTSD, sport->port.membase + USR1);
writel(USR2_ORE, sport->port.membase + USR2);
- if (sport->dma_is_inited && !sport->dma_is_enabled)
- imx_enable_dma(sport);
-
temp = readl(sport->port.membase + UCR1);
temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN;
@@ -1316,6 +1315,11 @@
} else {
ucr2 |= UCR2_CTSC;
}
+
+ /* Can we enable the DMA support? */
+ if (is_imx6q_uart(sport) && !uart_console(port)
+ && !sport->dma_is_inited)
+ imx_uart_dma_init(sport);
} else {
termios->c_cflag &= ~CRTSCTS;
}
@@ -1432,6 +1436,8 @@
if (UART_ENABLE_MS(&sport->port, termios->c_cflag))
imx_enable_ms(&sport->port);
+ if (sport->dma_is_inited && !sport->dma_is_enabled)
+ imx_enable_dma(sport);
spin_unlock_irqrestore(&sport->port.lock, flags);
}
@@ -1625,12 +1631,12 @@
int locked = 1;
int retval;
- retval = clk_enable(sport->clk_per);
+ retval = clk_prepare_enable(sport->clk_per);
if (retval)
return;
- retval = clk_enable(sport->clk_ipg);
+ retval = clk_prepare_enable(sport->clk_ipg);
if (retval) {
- clk_disable(sport->clk_per);
+ clk_disable_unprepare(sport->clk_per);
return;
}
@@ -1669,8 +1675,8 @@
if (locked)
spin_unlock_irqrestore(&sport->port.lock, flags);
- clk_disable(sport->clk_ipg);
- clk_disable(sport->clk_per);
+ clk_disable_unprepare(sport->clk_ipg);
+ clk_disable_unprepare(sport->clk_per);
}
/*
@@ -1771,15 +1777,7 @@
retval = uart_set_options(&sport->port, co, baud, parity, bits, flow);
- clk_disable(sport->clk_ipg);
- if (retval) {
- clk_unprepare(sport->clk_ipg);
- goto error_console;
- }
-
- retval = clk_prepare(sport->clk_per);
- if (retval)
- clk_disable_unprepare(sport->clk_ipg);
+ clk_disable_unprepare(sport->clk_ipg);
error_console:
return retval;
@@ -1811,36 +1809,6 @@
.cons = IMX_CONSOLE,
};
-static int serial_imx_suspend(struct platform_device *dev, pm_message_t state)
-{
- struct imx_port *sport = platform_get_drvdata(dev);
- unsigned int val;
-
- /* enable wakeup from i.MX UART */
- val = readl(sport->port.membase + UCR3);
- val |= UCR3_AWAKEN;
- writel(val, sport->port.membase + UCR3);
-
- uart_suspend_port(&imx_reg, &sport->port);
-
- return 0;
-}
-
-static int serial_imx_resume(struct platform_device *dev)
-{
- struct imx_port *sport = platform_get_drvdata(dev);
- unsigned int val;
-
- /* disable wakeup from i.MX UART */
- val = readl(sport->port.membase + UCR3);
- val &= ~UCR3_AWAKEN;
- writel(val, sport->port.membase + UCR3);
-
- uart_resume_port(&imx_reg, &sport->port);
-
- return 0;
-}
-
#ifdef CONFIG_OF
/*
* This function returns 1 iff pdev isn't a device instatiated by dt, 0 iff it
@@ -1902,7 +1870,7 @@
{
struct imx_port *sport;
void __iomem *base;
- int ret = 0;
+ int ret = 0, reg;
struct resource *res;
int txirq, rxirq, rtsirq;
@@ -1957,6 +1925,19 @@
sport->port.uartclk = clk_get_rate(sport->clk_per);
+ /* For register access, we only need to enable the ipg clock. */
+ ret = clk_prepare_enable(sport->clk_ipg);
+ if (ret)
+ return ret;
+
+ /* Disable interrupts before requesting them */
+ reg = readl_relaxed(sport->port.membase + UCR1);
+ reg &= ~(UCR1_ADEN | UCR1_TRDYEN | UCR1_IDEN | UCR1_RRDYEN |
+ UCR1_TXMPTYEN | UCR1_RTSDEN);
+ writel_relaxed(reg, sport->port.membase + UCR1);
+
+ clk_disable_unprepare(sport->clk_ipg);
+
/*
* Allocate the IRQ(s) i.MX1 has three interrupts whereas later
* chips only have one interrupt.
@@ -1992,16 +1973,135 @@
return uart_remove_one_port(&imx_reg, &sport->port);
}
+static void serial_imx_restore_context(struct imx_port *sport)
+{
+ if (!sport->context_saved)
+ return;
+
+ writel(sport->saved_reg[4], sport->port.membase + UFCR);
+ writel(sport->saved_reg[5], sport->port.membase + UESC);
+ writel(sport->saved_reg[6], sport->port.membase + UTIM);
+ writel(sport->saved_reg[7], sport->port.membase + UBIR);
+ writel(sport->saved_reg[8], sport->port.membase + UBMR);
+ writel(sport->saved_reg[9], sport->port.membase + IMX21_UTS);
+ writel(sport->saved_reg[0], sport->port.membase + UCR1);
+ writel(sport->saved_reg[1] | UCR2_SRST, sport->port.membase + UCR2);
+ writel(sport->saved_reg[2], sport->port.membase + UCR3);
+ writel(sport->saved_reg[3], sport->port.membase + UCR4);
+ sport->context_saved = false;
+}
+
+static void serial_imx_save_context(struct imx_port *sport)
+{
+ /* Save necessary regs */
+ sport->saved_reg[0] = readl(sport->port.membase + UCR1);
+ sport->saved_reg[1] = readl(sport->port.membase + UCR2);
+ sport->saved_reg[2] = readl(sport->port.membase + UCR3);
+ sport->saved_reg[3] = readl(sport->port.membase + UCR4);
+ sport->saved_reg[4] = readl(sport->port.membase + UFCR);
+ sport->saved_reg[5] = readl(sport->port.membase + UESC);
+ sport->saved_reg[6] = readl(sport->port.membase + UTIM);
+ sport->saved_reg[7] = readl(sport->port.membase + UBIR);
+ sport->saved_reg[8] = readl(sport->port.membase + UBMR);
+ sport->saved_reg[9] = readl(sport->port.membase + IMX21_UTS);
+ sport->context_saved = true;
+}
+
+static void serial_imx_enable_wakeup(struct imx_port *sport, bool on)
+{
+ unsigned int val;
+
+ val = readl(sport->port.membase + UCR3);
+ if (on)
+ val |= UCR3_AWAKEN;
+ else
+ val &= ~UCR3_AWAKEN;
+ writel(val, sport->port.membase + UCR3);
+
+ val = readl(sport->port.membase + UCR1);
+ if (on)
+ val |= UCR1_RTSDEN;
+ else
+ val &= ~UCR1_RTSDEN;
+ writel(val, sport->port.membase + UCR1);
+}
+
+static int imx_serial_port_suspend_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct imx_port *sport = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = clk_enable(sport->clk_ipg);
+ if (ret)
+ return ret;
+
+ serial_imx_save_context(sport);
+
+ clk_disable(sport->clk_ipg);
+
+ return 0;
+}
+
+static int imx_serial_port_resume_noirq(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct imx_port *sport = platform_get_drvdata(pdev);
+ int ret;
+
+ ret = clk_enable(sport->clk_ipg);
+ if (ret)
+ return ret;
+
+ serial_imx_restore_context(sport);
+
+ clk_disable(sport->clk_ipg);
+
+ return 0;
+}
+
+static int imx_serial_port_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct imx_port *sport = platform_get_drvdata(pdev);
+
+ /* enable wakeup from i.MX UART */
+ serial_imx_enable_wakeup(sport, true);
+
+ uart_suspend_port(&imx_reg, &sport->port);
+
+ return 0;
+}
+
+static int imx_serial_port_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct imx_port *sport = platform_get_drvdata(pdev);
+
+ /* disable wakeup from i.MX UART */
+ serial_imx_enable_wakeup(sport, false);
+
+ uart_resume_port(&imx_reg, &sport->port);
+
+ return 0;
+}
+
+static const struct dev_pm_ops imx_serial_port_pm_ops = {
+ .suspend_noirq = imx_serial_port_suspend_noirq,
+ .resume_noirq = imx_serial_port_resume_noirq,
+ .suspend = imx_serial_port_suspend,
+ .resume = imx_serial_port_resume,
+};
+
static struct platform_driver serial_imx_driver = {
.probe = serial_imx_probe,
.remove = serial_imx_remove,
- .suspend = serial_imx_suspend,
- .resume = serial_imx_resume,
.id_table = imx_uart_devtype,
.driver = {
.name = "imx-uart",
.of_match_table = imx_uart_dt_ids,
+ .pm = &imx_serial_port_pm_ops,
},
};
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index 4ccc039..b88832e 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -21,7 +21,6 @@
*/
#include <linux/slab.h>
-#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/console.h>
@@ -740,7 +739,6 @@
{ .compatible = DRVNAME },
{},
};
-MODULE_DEVICE_TABLE(of, ltq_asc_match);
static struct platform_driver lqasc_driver = {
.driver = {
@@ -764,8 +762,4 @@
return ret;
}
-
-module_init(init_lqasc);
-
-MODULE_DESCRIPTION("Lantiq serial port driver");
-MODULE_LICENSE("GPL");
+device_initcall(init_lqasc);
diff --git a/drivers/tty/serial/men_z135_uart.c b/drivers/tty/serial/men_z135_uart.c
index 35c5550..b90e7b3 100644
--- a/drivers/tty/serial/men_z135_uart.c
+++ b/drivers/tty/serial/men_z135_uart.c
@@ -392,7 +392,6 @@
struct men_z135_port *uart = (struct men_z135_port *)data;
struct uart_port *port = &uart->port;
bool handled = false;
- unsigned long flags;
int irq_id;
uart->stat_reg = ioread32(port->membase + MEN_Z135_STAT_REG);
@@ -401,7 +400,7 @@
if (!irq_id)
goto out;
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock(&port->lock);
/* It's save to write to IIR[7:6] RXC[9:8] */
iowrite8(irq_id, port->membase + MEN_Z135_STAT_REG);
@@ -427,7 +426,7 @@
handled = true;
}
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock(&port->lock);
out:
return IRQ_RETVAL(handled);
}
@@ -717,7 +716,7 @@
baud = uart_get_baud_rate(port, termios, old, 0, uart_freq / 16);
- spin_lock(&port->lock);
+ spin_lock_irq(&port->lock);
if (tty_termios_baud_rate(termios))
tty_termios_encode_baud_rate(termios, baud, baud);
@@ -725,7 +724,7 @@
iowrite32(bd_reg, port->membase + MEN_Z135_BAUD_REG);
uart_update_timeout(port, termios->c_cflag, baud);
- spin_unlock(&port->lock);
+ spin_unlock_irq(&port->lock);
}
static const char *men_z135_type(struct uart_port *port)
@@ -840,7 +839,6 @@
uart->port.membase = NULL;
uart->mdev = mdev;
- spin_lock_init(&uart->port.lock);
spin_lock_init(&uart->lock);
err = uart_add_one_port(&men_z135_driver, &uart->port);
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 6fc07eb..41de374 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -239,8 +239,9 @@
static int mpc52xx_psc_tx_empty(struct uart_port *port)
{
- return in_be16(&PSC(port)->mpc52xx_psc_status)
- & MPC52xx_PSC_SR_TXEMP;
+ u16 sts = in_be16(&PSC(port)->mpc52xx_psc_status);
+
+ return (sts & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0;
}
static void mpc52xx_psc_start_tx(struct uart_port *port)
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 13cf773..7c7f308 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -100,6 +100,8 @@
#define AUART_CTRL2_TXE (1 << 8)
#define AUART_CTRL2_UARTEN (1 << 0)
+#define AUART_LINECTRL_BAUD_DIV_MAX 0x003fffc0
+#define AUART_LINECTRL_BAUD_DIV_MIN 0x000000ec
#define AUART_LINECTRL_BAUD_DIVINT_SHIFT 16
#define AUART_LINECTRL_BAUD_DIVINT_MASK 0xffff0000
#define AUART_LINECTRL_BAUD_DIVINT(v) (((v) & 0xffff) << 16)
@@ -659,7 +661,7 @@
{
struct mxs_auart_port *s = to_auart_port(u);
u32 bm, ctrl, ctrl2, div;
- unsigned int cflag, baud;
+ unsigned int cflag, baud, baud_min, baud_max;
cflag = termios->c_cflag;
@@ -752,7 +754,9 @@
}
/* set baud rate */
- baud = uart_get_baud_rate(u, termios, old, 0, u->uartclk);
+ baud_min = DIV_ROUND_UP(u->uartclk * 32, AUART_LINECTRL_BAUD_DIV_MAX);
+ baud_max = u->uartclk * 32 / AUART_LINECTRL_BAUD_DIV_MIN;
+ baud = uart_get_baud_rate(u, termios, old, baud_min, baud_max);
div = u->uartclk * 32 / baud;
ctrl |= AUART_LINECTRL_BAUD_DIVFRAC(div & 0x3F);
ctrl |= AUART_LINECTRL_BAUD_DIVINT(div >> 6);
@@ -842,7 +846,7 @@
return IRQ_HANDLED;
}
-static void mxs_auart_reset(struct uart_port *u)
+static void mxs_auart_reset_deassert(struct uart_port *u)
{
int i;
unsigned int reg;
@@ -858,6 +862,30 @@
writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
}
+static void mxs_auart_reset_assert(struct uart_port *u)
+{
+ int i;
+ u32 reg;
+
+ reg = readl(u->membase + AUART_CTRL0);
+ /* if already in reset state, keep it untouched */
+ if (reg & AUART_CTRL0_SFTRST)
+ return;
+
+ writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+ writel(AUART_CTRL0_SFTRST, u->membase + AUART_CTRL0_SET);
+
+ for (i = 0; i < 1000; i++) {
+ reg = readl(u->membase + AUART_CTRL0);
+ /* reset is finished when the clock is gated */
+ if (reg & AUART_CTRL0_CLKGATE)
+ return;
+ udelay(10);
+ }
+
+ dev_err(u->dev, "Failed to reset the unit.");
+}
+
static int mxs_auart_startup(struct uart_port *u)
{
int ret;
@@ -867,7 +895,13 @@
if (ret)
return ret;
- writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+ if (uart_console(u)) {
+ writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_CLR);
+ } else {
+ /* reset the unit to a well known state */
+ mxs_auart_reset_assert(u);
+ mxs_auart_reset_deassert(u);
+ }
writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_SET);
@@ -899,12 +933,14 @@
if (auart_dma_enabled(s))
mxs_auart_dma_exit(s);
- writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
-
- writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
- u->membase + AUART_INTR_CLR);
-
- writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+ if (uart_console(u)) {
+ writel(AUART_CTRL2_UARTEN, u->membase + AUART_CTRL2_CLR);
+ writel(AUART_INTR_RXIEN | AUART_INTR_RTIEN | AUART_INTR_CTSMIEN,
+ u->membase + AUART_INTR_CLR);
+ writel(AUART_CTRL0_CLKGATE, u->membase + AUART_CTRL0_SET);
+ } else {
+ mxs_auart_reset_assert(u);
+ }
clk_disable_unprepare(s->clk);
}
@@ -1291,7 +1327,7 @@
auart_port[s->port.line] = s;
- mxs_auart_reset(&s->port);
+ mxs_auart_reset_deassert(&s->port);
ret = uart_add_one_port(&auart_driver, &s->port);
if (ret)
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 67d0c21..856686d 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -53,7 +53,6 @@
#include "samsung.h"
#if defined(CONFIG_SERIAL_SAMSUNG_DEBUG) && \
- defined(CONFIG_DEBUG_LL) && \
!defined(MODULE)
extern void printascii(const char *);
@@ -295,15 +294,6 @@
if (ourport->tx_mode != S3C24XX_TX_DMA)
enable_tx_dma(ourport);
- while (xmit->tail & (dma_get_cache_alignment() - 1)) {
- if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
- return 0;
- wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- count--;
- }
-
dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
@@ -342,7 +332,9 @@
return;
}
- if (!ourport->dma || !ourport->dma->tx_chan || count < port->fifosize)
+ if (!ourport->dma || !ourport->dma->tx_chan ||
+ count < ourport->min_dma_size ||
+ xmit->tail & (dma_get_cache_alignment() - 1))
s3c24xx_serial_start_tx_pio(ourport);
else
s3c24xx_serial_start_tx_dma(ourport, count);
@@ -736,15 +728,20 @@
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit;
unsigned long flags;
- int count;
+ int count, dma_count = 0;
spin_lock_irqsave(&port->lock, flags);
count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
- if (ourport->dma && ourport->dma->tx_chan && count >= port->fifosize) {
- s3c24xx_serial_start_tx_dma(ourport, count);
- goto out;
+ if (ourport->dma && ourport->dma->tx_chan &&
+ count >= ourport->min_dma_size) {
+ int align = dma_get_cache_alignment() -
+ (xmit->tail & (dma_get_cache_alignment() - 1));
+ if (count-align >= ourport->min_dma_size) {
+ dma_count = count-align;
+ count = align;
+ }
}
if (port->x_char) {
@@ -765,14 +762,24 @@
/* try and drain the buffer... */
- count = port->fifosize;
- while (!uart_circ_empty(xmit) && count-- > 0) {
+ if (count > port->fifosize) {
+ count = port->fifosize;
+ dma_count = 0;
+ }
+
+ while (!uart_circ_empty(xmit) && count > 0) {
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
break;
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
+ count--;
+ }
+
+ if (!count && dma_count) {
+ s3c24xx_serial_start_tx_dma(ourport, dma_count);
+ goto out;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {
@@ -1838,6 +1845,13 @@
else if (ourport->info->fifosize)
ourport->port.fifosize = ourport->info->fifosize;
+ /*
+ * DMA transfers must be aligned at least to cache line size,
+ * so find minimal transfer size suitable for DMA mode
+ */
+ ourport->min_dma_size = max_t(int, ourport->port.fifosize,
+ dma_get_cache_alignment());
+
probe_index++;
dbg("%s: initialising port %p...\n", __func__, ourport);
diff --git a/drivers/tty/serial/samsung.h b/drivers/tty/serial/samsung.h
index d275032..fc5deaa 100644
--- a/drivers/tty/serial/samsung.h
+++ b/drivers/tty/serial/samsung.h
@@ -82,6 +82,7 @@
unsigned char tx_claimed;
unsigned int pm_level;
unsigned long baudclk_rate;
+ unsigned int min_dma_size;
unsigned int rx_irq;
unsigned int tx_irq;
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index 9e65760..72ffd0d 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -11,6 +11,8 @@
*
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -29,6 +31,7 @@
#include <linux/uaccess.h>
#define SC16IS7XX_NAME "sc16is7xx"
+#define SC16IS7XX_MAX_DEVS 8
/* SC16IS7XX register definitions */
#define SC16IS7XX_RHR_REG (0x00) /* RX FIFO */
@@ -312,14 +315,14 @@
struct sc16is7xx_one {
struct uart_port port;
+ u8 line;
struct kthread_work tx_work;
struct kthread_work reg_work;
struct sc16is7xx_one_config config;
};
struct sc16is7xx_port {
- struct uart_driver uart;
- struct sc16is7xx_devtype *devtype;
+ const struct sc16is7xx_devtype *devtype;
struct regmap *regmap;
struct clk *clk;
#ifdef CONFIG_GPIOLIB
@@ -332,16 +335,31 @@
struct sc16is7xx_one p[0];
};
+static unsigned long sc16is7xx_lines;
+
+static struct uart_driver sc16is7xx_uart = {
+ .owner = THIS_MODULE,
+ .dev_name = "ttySC",
+ .nr = SC16IS7XX_MAX_DEVS,
+};
+
#define to_sc16is7xx_port(p,e) ((container_of((p), struct sc16is7xx_port, e)))
#define to_sc16is7xx_one(p,e) ((container_of((p), struct sc16is7xx_one, e)))
+static int sc16is7xx_line(struct uart_port *port)
+{
+ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port);
+
+ return one->line;
+}
+
static u8 sc16is7xx_port_read(struct uart_port *port, u8 reg)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
unsigned int val = 0;
+ const u8 line = sc16is7xx_line(port);
- regmap_read(s->regmap,
- (reg << SC16IS7XX_REG_SHIFT) | port->line, &val);
+ regmap_read(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, &val);
return val;
}
@@ -349,21 +367,55 @@
static void sc16is7xx_port_write(struct uart_port *port, u8 reg, u8 val)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+ const u8 line = sc16is7xx_line(port);
- regmap_write(s->regmap,
- (reg << SC16IS7XX_REG_SHIFT) | port->line, val);
+ regmap_write(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line, val);
+}
+
+static void sc16is7xx_fifo_read(struct uart_port *port, unsigned int rxlen)
+{
+ struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+ const u8 line = sc16is7xx_line(port);
+ u8 addr = (SC16IS7XX_RHR_REG << SC16IS7XX_REG_SHIFT) | line;
+
+ regcache_cache_bypass(s->regmap, true);
+ regmap_raw_read(s->regmap, addr, s->buf, rxlen);
+ regcache_cache_bypass(s->regmap, false);
+}
+
+static void sc16is7xx_fifo_write(struct uart_port *port, u8 to_send)
+{
+ struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+ const u8 line = sc16is7xx_line(port);
+ u8 addr = (SC16IS7XX_THR_REG << SC16IS7XX_REG_SHIFT) | line;
+
+ regcache_cache_bypass(s->regmap, true);
+ regmap_raw_write(s->regmap, addr, s->buf, to_send);
+ regcache_cache_bypass(s->regmap, false);
}
static void sc16is7xx_port_update(struct uart_port *port, u8 reg,
u8 mask, u8 val)
{
struct sc16is7xx_port *s = dev_get_drvdata(port->dev);
+ const u8 line = sc16is7xx_line(port);
- regmap_update_bits(s->regmap,
- (reg << SC16IS7XX_REG_SHIFT) | port->line,
+ regmap_update_bits(s->regmap, (reg << SC16IS7XX_REG_SHIFT) | line,
mask, val);
}
+static int sc16is7xx_alloc_line(void)
+{
+ int i;
+
+ BUILD_BUG_ON(SC16IS7XX_MAX_DEVS > BITS_PER_LONG);
+
+ for (i = 0; i < SC16IS7XX_MAX_DEVS; i++)
+ if (!test_and_set_bit(i, &sc16is7xx_lines))
+ break;
+
+ return i;
+}
static void sc16is7xx_power(struct uart_port *port, int on)
{
@@ -488,7 +540,7 @@
if (unlikely(rxlen >= sizeof(s->buf))) {
dev_warn_ratelimited(port->dev,
- "Port %i: Possible RX FIFO overrun: %d\n",
+ "ttySC%i: Possible RX FIFO overrun: %d\n",
port->line, rxlen);
port->icount.buf_overrun++;
/* Ensure sanity of RX level */
@@ -508,10 +560,7 @@
s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG);
bytes_read = 1;
} else {
- regcache_cache_bypass(s->regmap, true);
- regmap_raw_read(s->regmap, SC16IS7XX_RHR_REG,
- s->buf, rxlen);
- regcache_cache_bypass(s->regmap, false);
+ sc16is7xx_fifo_read(port, rxlen);
bytes_read = rxlen;
}
@@ -591,9 +640,8 @@
s->buf[i] = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
}
- regcache_cache_bypass(s->regmap, true);
- regmap_raw_write(s->regmap, SC16IS7XX_THR_REG, s->buf, to_send);
- regcache_cache_bypass(s->regmap, false);
+
+ sc16is7xx_fifo_write(port, to_send);
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
@@ -633,7 +681,7 @@
break;
default:
dev_err_ratelimited(port->dev,
- "Port %i: Unexpected interrupt: %x",
+ "ttySC%i: Unexpected interrupt: %x",
port->line, iir);
break;
}
@@ -645,7 +693,7 @@
struct sc16is7xx_port *s = to_sc16is7xx_port(ws, irq_work);
int i;
- for (i = 0; i < s->uart.nr; ++i)
+ for (i = 0; i < s->devtype->nr_uart; ++i)
sc16is7xx_port_irq(s, i);
}
@@ -1083,7 +1131,7 @@
#endif
static int sc16is7xx_probe(struct device *dev,
- struct sc16is7xx_devtype *devtype,
+ const struct sc16is7xx_devtype *devtype,
struct regmap *regmap, int irq, unsigned long flags)
{
struct sched_param sched_param = { .sched_priority = MAX_RT_PRIO / 2 };
@@ -1118,23 +1166,13 @@
s->devtype = devtype;
dev_set_drvdata(dev, s);
- /* Register UART driver */
- s->uart.owner = THIS_MODULE;
- s->uart.dev_name = "ttySC";
- s->uart.nr = devtype->nr_uart;
- ret = uart_register_driver(&s->uart);
- if (ret) {
- dev_err(dev, "Registering UART driver failed\n");
- goto out_clk;
- }
-
init_kthread_worker(&s->kworker);
init_kthread_work(&s->irq_work, sc16is7xx_ist);
s->kworker_task = kthread_run(kthread_worker_fn, &s->kworker,
"sc16is7xx");
if (IS_ERR(s->kworker_task)) {
ret = PTR_ERR(s->kworker_task);
- goto out_uart;
+ goto out_clk;
}
sched_setscheduler(s->kworker_task, SCHED_FIFO, &sched_param);
@@ -1158,8 +1196,8 @@
#endif
for (i = 0; i < devtype->nr_uart; ++i) {
+ s->p[i].line = i;
/* Initialize port data */
- s->p[i].port.line = i;
s->p[i].port.dev = dev;
s->p[i].port.irq = irq;
s->p[i].port.type = PORT_SC16IS7XX;
@@ -1169,6 +1207,12 @@
s->p[i].port.uartclk = freq;
s->p[i].port.rs485_config = sc16is7xx_config_rs485;
s->p[i].port.ops = &sc16is7xx_ops;
+ s->p[i].port.line = sc16is7xx_alloc_line();
+ if (s->p[i].port.line >= SC16IS7XX_MAX_DEVS) {
+ ret = -ENOMEM;
+ goto out_ports;
+ }
+
/* Disable all interrupts */
sc16is7xx_port_write(&s->p[i].port, SC16IS7XX_IER_REG, 0);
/* Disable TX/RX */
@@ -1179,7 +1223,7 @@
init_kthread_work(&s->p[i].tx_work, sc16is7xx_tx_proc);
init_kthread_work(&s->p[i].reg_work, sc16is7xx_reg_proc);
/* Register port */
- uart_add_one_port(&s->uart, &s->p[i].port);
+ uart_add_one_port(&sc16is7xx_uart, &s->p[i].port);
/* Go to suspend mode */
sc16is7xx_power(&s->p[i].port, 0);
}
@@ -1190,8 +1234,11 @@
if (!ret)
return 0;
- for (i = 0; i < s->uart.nr; i++)
- uart_remove_one_port(&s->uart, &s->p[i].port);
+out_ports:
+ for (i--; i >= 0; i--) {
+ uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
+ clear_bit(s->p[i].port.line, &sc16is7xx_lines);
+ }
#ifdef CONFIG_GPIOLIB
if (devtype->nr_gpio)
@@ -1201,9 +1248,6 @@
#endif
kthread_stop(s->kworker_task);
-out_uart:
- uart_unregister_driver(&s->uart);
-
out_clk:
if (!IS_ERR(s->clk))
clk_disable_unprepare(s->clk);
@@ -1221,15 +1265,15 @@
gpiochip_remove(&s->gpio);
#endif
- for (i = 0; i < s->uart.nr; i++) {
- uart_remove_one_port(&s->uart, &s->p[i].port);
+ for (i = 0; i < s->devtype->nr_uart; i++) {
+ uart_remove_one_port(&sc16is7xx_uart, &s->p[i].port);
+ clear_bit(s->p[i].port.line, &sc16is7xx_lines);
sc16is7xx_power(&s->p[i].port, 0);
}
flush_kthread_worker(&s->kworker);
kthread_stop(s->kworker_task);
- uart_unregister_driver(&s->uart);
if (!IS_ERR(s->clk))
clk_disable_unprepare(s->clk);
@@ -1259,7 +1303,7 @@
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
static int sc16is7xx_spi_probe(struct spi_device *spi)
{
- struct sc16is7xx_devtype *devtype;
+ const struct sc16is7xx_devtype *devtype;
unsigned long flags = 0;
struct regmap *regmap;
int ret;
@@ -1328,7 +1372,7 @@
static int sc16is7xx_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
- struct sc16is7xx_devtype *devtype;
+ const struct sc16is7xx_devtype *devtype;
unsigned long flags = 0;
struct regmap *regmap;
@@ -1369,7 +1413,6 @@
static struct i2c_driver sc16is7xx_i2c_uart_driver = {
.driver = {
.name = SC16IS7XX_NAME,
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(sc16is7xx_dt_ids),
},
.probe = sc16is7xx_i2c_probe,
@@ -1382,7 +1425,14 @@
static int __init sc16is7xx_init(void)
{
- int ret = 0;
+ int ret;
+
+ ret = uart_register_driver(&sc16is7xx_uart);
+ if (ret) {
+ pr_err("Registering UART driver failed\n");
+ return ret;
+ }
+
#ifdef CONFIG_SERIAL_SC16IS7XX_I2C
ret = i2c_add_driver(&sc16is7xx_i2c_uart_driver);
if (ret < 0) {
@@ -1411,6 +1461,7 @@
#ifdef CONFIG_SERIAL_SC16IS7XX_SPI
spi_unregister_driver(&sc16is7xx_spi_uart_driver);
#endif
+ uart_unregister_driver(&sc16is7xx_uart);
}
module_exit(sc16is7xx_exit);
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 7ae1592..603d2cc 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1377,7 +1377,6 @@
struct uart_state *state = tty->driver_data;
struct tty_port *port;
struct uart_port *uport;
- unsigned long flags;
if (!state) {
struct uart_driver *drv = tty->driver->driver_state;
@@ -1403,10 +1402,9 @@
* disable the receive line status interrupts.
*/
if (port->flags & ASYNC_INITIALIZED) {
- unsigned long flags;
- spin_lock_irqsave(&uport->lock, flags);
+ spin_lock_irq(&uport->lock);
uport->ops->stop_rx(uport);
- spin_unlock_irqrestore(&uport->lock, flags);
+ spin_unlock_irq(&uport->lock);
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
@@ -1418,18 +1416,18 @@
mutex_lock(&port->mutex);
uart_shutdown(tty, state);
tty_port_tty_set(port, NULL);
- tty->closing = 0;
- spin_lock_irqsave(&port->lock, flags);
+
+ spin_lock_irq(&port->lock);
if (port->blocked_open) {
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock_irq(&port->lock);
if (port->close_delay)
msleep_interruptible(jiffies_to_msecs(port->close_delay));
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irq(&port->lock);
} else if (!uart_console(uport)) {
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock_irq(&port->lock);
uart_change_pm(state, UART_PM_STATE_OFF);
- spin_lock_irqsave(&port->lock, flags);
+ spin_lock_irq(&port->lock);
}
/*
@@ -1437,13 +1435,14 @@
*/
clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
clear_bit(ASYNCB_CLOSING, &port->flags);
- spin_unlock_irqrestore(&port->lock, flags);
+ spin_unlock_irq(&port->lock);
wake_up_interruptible(&port->open_wait);
wake_up_interruptible(&port->close_wait);
mutex_unlock(&port->mutex);
tty_ldisc_flush(tty);
+ tty->closing = 0;
}
static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
@@ -1531,11 +1530,6 @@
mutex_unlock(&port->mutex);
}
-static int uart_port_activate(struct tty_port *port, struct tty_struct *tty)
-{
- return 0;
-}
-
static void uart_port_shutdown(struct tty_port *port)
{
struct uart_state *state = container_of(port, struct uart_state, port);
@@ -2378,8 +2372,6 @@
};
static const struct tty_port_operations uart_port_ops = {
- .activate = uart_port_activate,
- .shutdown = uart_port_shutdown,
.carrier_raised = uart_carrier_raised,
.dtr_rts = uart_dtr_rts,
};
diff --git a/drivers/tty/serial/sirfsoc_uart.c b/drivers/tty/serial/sirfsoc_uart.c
index 653cdd5..c6657de 100644
--- a/drivers/tty/serial/sirfsoc_uart.c
+++ b/drivers/tty/serial/sirfsoc_uart.c
@@ -413,7 +413,6 @@
break;
}
- sirfport->rx_io_count += rx_count;
port->icount.rx += rx_count;
return rx_count;
@@ -600,7 +599,6 @@
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
- sirfport->rx_io_count = 0;
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
~SIRFUART_IO_MODE);
@@ -632,31 +630,6 @@
sirfport->uart_reg->uart_type));
}
-static void sirfsoc_uart_start_rx(struct uart_port *port)
-{
- struct sirfsoc_uart_port *sirfport = to_sirfport(port);
- struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
- struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
-
- sirfport->rx_io_count = 0;
- wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
- wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
- wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
- if (sirfport->rx_dma_chan)
- sirfsoc_uart_start_next_rx_dma(port);
- else {
- if (!sirfport->is_atlas7)
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- rd_regl(port, ureg->sirfsoc_int_en_reg) |
- SIRFUART_RX_IO_INT_EN(uint_en,
- sirfport->uart_reg->uart_type));
- else
- wr_regl(port, ureg->sirfsoc_int_en_reg,
- SIRFUART_RX_IO_INT_EN(uint_en,
- sirfport->uart_reg->uart_type));
- }
-}
-
static unsigned int
sirfsoc_usp_calc_sample_div(unsigned long set_rate,
unsigned long ioclk_rate, unsigned long *sample_reg)
@@ -850,7 +823,6 @@
rx_time_out = SIRFSOC_UART_RX_TIMEOUT(set_baud, 20000);
rx_time_out = SIRFUART_RECV_TIMEOUT_VALUE(rx_time_out);
txfifo_op_reg = rd_regl(port, ureg->sirfsoc_tx_fifo_op);
- wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_STOP);
wr_regl(port, ureg->sirfsoc_tx_fifo_op,
(txfifo_op_reg & ~SIRFUART_FIFO_START));
if (sirfport->uart_reg->uart_type == SIRF_REAL_UART) {
@@ -886,9 +858,13 @@
else
wr_regl(port, ureg->sirfsoc_tx_dma_io_ctrl, SIRFUART_IO_MODE);
if (sirfport->rx_dma_chan)
- wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_DMA_MODE);
+ wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
+ rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
+ ~SIRFUART_IO_MODE);
else
- wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl, SIRFUART_IO_MODE);
+ wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
+ rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
+ SIRFUART_IO_MODE);
sirfport->rx_period_time = 20000000;
/* Reset Rx/Tx FIFO Threshold level for proper baudrate */
if (set_baud < 1000000)
@@ -902,7 +878,6 @@
txfifo_op_reg |= SIRFUART_FIFO_START;
wr_regl(port, ureg->sirfsoc_tx_fifo_op, txfifo_op_reg);
uart_update_timeout(port, termios->c_cflag, set_baud);
- sirfsoc_uart_start_rx(port);
wr_regl(port, ureg->sirfsoc_tx_rx_en, SIRFUART_TX_EN | SIRFUART_RX_EN);
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -921,6 +896,7 @@
{
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
+ struct sirfsoc_int_en *uint_en = &sirfport->uart_reg->uart_int_en;
unsigned int index = port->line;
int ret;
irq_modify_status(port->irq, IRQ_NOREQUEST, IRQ_NOAUTOEN);
@@ -958,9 +934,9 @@
wr_regl(port, ureg->sirfsoc_rx_fifo_ctrl, SIRFUART_FIFO_THD(port));
if (sirfport->rx_dma_chan)
wr_regl(port, ureg->sirfsoc_rx_fifo_level_chk,
- SIRFUART_RX_FIFO_CHK_SC(port->line, 0x4) |
- SIRFUART_RX_FIFO_CHK_LC(port->line, 0xe) |
- SIRFUART_RX_FIFO_CHK_HC(port->line, 0x1b));
+ SIRFUART_RX_FIFO_CHK_SC(port->line, 0x1) |
+ SIRFUART_RX_FIFO_CHK_LC(port->line, 0x2) |
+ SIRFUART_RX_FIFO_CHK_HC(port->line, 0x4));
if (sirfport->tx_dma_chan) {
sirfport->tx_dma_state = TX_DMA_IDLE;
wr_regl(port, ureg->sirfsoc_tx_fifo_level_chk,
@@ -981,16 +957,41 @@
goto init_rx_err;
}
}
- enable_irq(port->irq);
+ if (sirfport->uart_reg->uart_type == SIRF_REAL_UART &&
+ sirfport->rx_dma_chan)
+ wr_regl(port, ureg->sirfsoc_swh_dma_io,
+ SIRFUART_CLEAR_RX_ADDR_EN);
+ if (sirfport->uart_reg->uart_type == SIRF_USP_UART &&
+ sirfport->rx_dma_chan)
+ wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
+ rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
+ SIRFSOC_USP_FRADDR_CLR_EN);
if (sirfport->rx_dma_chan && !sirfport->is_hrt_enabled) {
sirfport->is_hrt_enabled = true;
sirfport->rx_period_time = 20000000;
+ sirfport->rx_last_pos = -1;
+ sirfport->pio_fetch_cnt = 0;
sirfport->rx_dma_items.xmit.tail =
sirfport->rx_dma_items.xmit.head = 0;
hrtimer_start(&sirfport->hrt,
ns_to_ktime(sirfport->rx_period_time),
HRTIMER_MODE_REL);
}
+ wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
+ if (sirfport->rx_dma_chan)
+ sirfsoc_uart_start_next_rx_dma(port);
+ else {
+ if (!sirfport->is_atlas7)
+ wr_regl(port, ureg->sirfsoc_int_en_reg,
+ rd_regl(port, ureg->sirfsoc_int_en_reg) |
+ SIRFUART_RX_IO_INT_EN(uint_en,
+ sirfport->uart_reg->uart_type));
+ else
+ wr_regl(port, ureg->sirfsoc_int_en_reg,
+ SIRFUART_RX_IO_INT_EN(uint_en,
+ sirfport->uart_reg->uart_type));
+ }
+ enable_irq(port->irq);
return 0;
init_rx_err:
@@ -1003,6 +1004,9 @@
{
struct sirfsoc_uart_port *sirfport = to_sirfport(port);
struct sirfsoc_register *ureg = &sirfport->uart_reg->uart_reg;
+ struct circ_buf *xmit;
+
+ xmit = &sirfport->rx_dma_items.xmit;
if (!sirfport->is_atlas7)
wr_regl(port, ureg->sirfsoc_int_en_reg, 0);
else
@@ -1019,8 +1023,10 @@
if (sirfport->tx_dma_chan)
sirfport->tx_dma_state = TX_DMA_IDLE;
if (sirfport->rx_dma_chan && sirfport->is_hrt_enabled) {
- while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
- SIRFUART_RX_FIFO_MASK) > 0)
+ while (((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
+ SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt) &&
+ !CIRC_CNT(xmit->head, xmit->tail,
+ SIRFSOC_RX_DMA_BUF_SIZE))
;
sirfport->is_hrt_enabled = false;
hrtimer_cancel(&sirfport->hrt);
@@ -1169,6 +1175,8 @@
struct tty_struct *tty;
struct sirfsoc_register *ureg;
struct circ_buf *xmit;
+ struct sirfsoc_fifo_status *ufifo_st;
+ int max_pio_cnt;
sirfport = container_of(hrt, struct sirfsoc_uart_port, hrt);
port = &sirfport->port;
@@ -1176,9 +1184,16 @@
tty = port->state->port.tty;
ureg = &sirfport->uart_reg->uart_reg;
xmit = &sirfport->rx_dma_items.xmit;
+ ufifo_st = &sirfport->uart_reg->fifo_status;
+
dmaengine_tx_status(sirfport->rx_dma_chan,
- sirfport->rx_dma_items.cookie, &tx_state);
- xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
+ sirfport->rx_dma_items.cookie, &tx_state);
+ if (SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue !=
+ sirfport->rx_last_pos) {
+ xmit->head = SIRFSOC_RX_DMA_BUF_SIZE - tx_state.residue;
+ sirfport->rx_last_pos = xmit->head;
+ sirfport->pio_fetch_cnt = 0;
+ }
count = CIRC_CNT_TO_END(xmit->head, xmit->tail,
SIRFSOC_RX_DMA_BUF_SIZE);
while (count > 0) {
@@ -1200,23 +1215,38 @@
*/
if (!inserted && !count &&
((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
- SIRFUART_RX_FIFO_MASK) > 0)) {
+ SIRFUART_RX_FIFO_MASK) > sirfport->pio_fetch_cnt)) {
+ dmaengine_pause(sirfport->rx_dma_chan);
/* switch to pio mode */
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) |
SIRFUART_IO_MODE);
- while ((rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
- SIRFUART_RX_FIFO_MASK) > 0) {
- if (sirfsoc_uart_pio_rx_chars(port, 16) > 0)
- tty_flip_buffer_push(tty->port);
+ /*
+ * UART controller SWH_DMA_IO register have CLEAR_RX_ADDR_EN
+ * When found changing I/O to DMA mode, it clears
+ * two low bits of read point;
+ * USP have similar FRADDR_CLR_EN bit in USP_RX_DMA_IO_CTRL.
+ * Fetch data out from rxfifo into DMA buffer in PIO mode,
+ * while switch back to DMA mode, the data fetched will override
+ * by DMA, as hardware have a strange behaviour:
+ * after switch back to DMA mode, check rxfifo status it will
+ * be the number PIO fetched, so record the fetched data count
+ * to avoid the repeated fetch
+ */
+ max_pio_cnt = 3;
+ while (!(rd_regl(port, ureg->sirfsoc_rx_fifo_status) &
+ ufifo_st->ff_empty(port)) && max_pio_cnt--) {
+ xmit->buf[xmit->head] =
+ rd_regl(port, ureg->sirfsoc_rx_fifo_data);
+ xmit->head = (xmit->head + 1) &
+ (SIRFSOC_RX_DMA_BUF_SIZE - 1);
+ sirfport->pio_fetch_cnt++;
}
- wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_RESET);
- wr_regl(port, ureg->sirfsoc_rx_fifo_op, 0);
- wr_regl(port, ureg->sirfsoc_rx_fifo_op, SIRFUART_FIFO_START);
/* switch back to dma mode */
wr_regl(port, ureg->sirfsoc_rx_dma_io_ctrl,
rd_regl(port, ureg->sirfsoc_rx_dma_io_ctrl) &
~SIRFUART_IO_MODE);
+ dmaengine_resume(sirfport->rx_dma_chan);
}
next_hrt:
hrtimer_forward_now(hrt, ns_to_ktime(sirfport->rx_period_time));
@@ -1239,7 +1269,7 @@
struct resource *res;
int ret;
struct dma_slave_config slv_cfg = {
- .src_maxburst = 2,
+ .src_maxburst = 1,
};
struct dma_slave_config tx_slv_cfg = {
.dst_maxburst = 2,
diff --git a/drivers/tty/serial/sirfsoc_uart.h b/drivers/tty/serial/sirfsoc_uart.h
index eb162b0..c3a885b 100644
--- a/drivers/tty/serial/sirfsoc_uart.h
+++ b/drivers/tty/serial/sirfsoc_uart.h
@@ -296,6 +296,7 @@
#define SIRFUART_DMA_MODE 0x0
#define SIRFUART_RX_DMA_FLUSH 0x4
+#define SIRFUART_CLEAR_RX_ADDR_EN 0x2
/* Baud Rate Calculation */
#define SIRF_USP_MIN_SAMPLE_DIV 0x1
#define SIRF_MIN_SAMPLE_DIV 0xf
@@ -325,6 +326,7 @@
#define SIRFSOC_USP_ASYNC_DIV2_MASK 0x3f
#define SIRFSOC_USP_ASYNC_DIV2_OFFSET 16
#define SIRFSOC_USP_LOOP_BACK_CTRL BIT(2)
+#define SIRFSOC_USP_FRADDR_CLR_EN BIT(1)
/* USP-UART Common */
#define SIRFSOC_UART_RX_TIMEOUT(br, to) (((br) * (((to) + 999) / 1000)) / 1000)
#define SIRFUART_RECV_TIMEOUT_VALUE(x) \
@@ -421,7 +423,6 @@
struct dma_chan *tx_dma_chan;
dma_addr_t tx_dma_addr;
struct dma_async_tx_descriptor *tx_dma_desc;
- unsigned int rx_io_count;
unsigned long transfer_size;
enum sirfsoc_tx_state tx_dma_state;
unsigned int cts_gpio;
@@ -431,6 +432,8 @@
struct hrtimer hrt;
bool is_hrt_enabled;
unsigned long rx_period_time;
+ unsigned long rx_last_pos;
+ unsigned long pio_fetch_cnt;
};
/* Register Access Control */
diff --git a/drivers/tty/serial/sn_console.c b/drivers/tty/serial/sn_console.c
index 33e94e5..d4692d8 100644
--- a/drivers/tty/serial/sn_console.c
+++ b/drivers/tty/serial/sn_console.c
@@ -42,7 +42,7 @@
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/console.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/sysrq.h>
#include <linux/circ_buf.h>
#include <linux/serial_reg.h>
@@ -659,7 +659,7 @@
* @port: Our sn_cons_port (which contains the uart port)
*
* So this is used by sn_sal_serial_console_init (early on, before we're
- * registered with serial core). It's also used by sn_sal_module_init
+ * registered with serial core). It's also used by sn_sal_init
* right after we've registered with serial core. The later only happens
* if we didn't already come through here via sn_sal_serial_console_init.
*
@@ -709,7 +709,7 @@
* sn_sal_switch_to_interrupts - Switch to interrupt driven mode
* @port: Our sn_cons_port (which contains the uart port)
*
- * In sn_sal_module_init, after we're registered with serial core and
+ * In sn_sal_init, after we're registered with serial core and
* the port is added, this function is called to switch us to interrupt
* mode. We were previously in asynch/polling mode (using init_timer).
*
@@ -773,7 +773,7 @@
};
/**
- * sn_sal_module_init - When the kernel loads us, get us rolling w/ serial core
+ * sn_sal_init - When the kernel loads us, get us rolling w/ serial core
*
* Before this is called, we've been printing kernel messages in a special
* early mode not making use of the serial core infrastructure. When our
@@ -781,7 +781,7 @@
* core and try to enable interrupt driven mode.
*
*/
-static int __init sn_sal_module_init(void)
+static int __init sn_sal_init(void)
{
int retval;
@@ -811,7 +811,7 @@
if (uart_register_driver(&sal_console_uart) < 0) {
printk
- ("ERROR sn_sal_module_init failed uart_register_driver, line %d\n",
+ ("ERROR sn_sal_init failed uart_register_driver, line %d\n",
__LINE__);
return -ENODEV;
}
@@ -832,33 +832,19 @@
/* when this driver is compiled in, the console initialization
* will have already switched us into asynchronous operation
- * before we get here through the module initcalls */
+ * before we get here through the initcalls */
if (!sal_console_port.sc_is_asynch) {
sn_sal_switch_to_asynch(&sal_console_port);
}
- /* at this point (module_init) we can try to turn on interrupts */
+ /* at this point (device_init) we can try to turn on interrupts */
if (!IS_RUNNING_ON_SIMULATOR()) {
sn_sal_switch_to_interrupts(&sal_console_port);
}
sn_process_input = 1;
return 0;
}
-
-/**
- * sn_sal_module_exit - When we're unloaded, remove the driver/port
- *
- */
-static void __exit sn_sal_module_exit(void)
-{
- del_timer_sync(&sal_console_port.sc_timer);
- uart_remove_one_port(&sal_console_uart, &sal_console_port.sc_port);
- uart_unregister_driver(&sal_console_uart);
- misc_deregister(&misc);
-}
-
-module_init(sn_sal_module_init);
-module_exit(sn_sal_module_exit);
+device_initcall(sn_sal_init);
/**
* puts_raw_fixed - sn_sal_console_write helper for adding \r's as required
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index 4a6eab6..e3de9c6 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -6,7 +6,7 @@
* Inspired by st-asc.c from STMicroelectronics (c)
*/
-#if defined(CONFIG_SERIAL_STM32_USART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#if defined(CONFIG_SERIAL_STM32_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
#define SUPPORT_SYSRQ
#endif
diff --git a/drivers/tty/serial/suncore.c b/drivers/tty/serial/suncore.c
index 6e4ac8d..127472b 100644
--- a/drivers/tty/serial/suncore.c
+++ b/drivers/tty/serial/suncore.c
@@ -10,7 +10,6 @@
* Copyright (C) 2002 David S. Miller (davem@redhat.com)
*/
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/console.h>
#include <linux/tty.h>
@@ -234,14 +233,10 @@
{
return 0;
}
+device_initcall(suncore_init);
-static void __exit suncore_exit(void)
-{
-}
-
-module_init(suncore_init);
-module_exit(suncore_exit);
-
+#if 0 /* ..def MODULE ; never supported as such */
MODULE_AUTHOR("Eddie C. Dost, David S. Miller");
MODULE_DESCRIPTION("Sun serial common layer");
MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index 5347544..0640318 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -3,7 +3,6 @@
* Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
*/
-#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/tty.h>
@@ -621,7 +620,6 @@
},
{},
};
-MODULE_DEVICE_TABLE(of, hv_match);
static struct platform_driver hv_driver = {
.driver = {
@@ -639,16 +637,11 @@
return platform_driver_register(&hv_driver);
}
+device_initcall(sunhv_init);
-static void __exit sunhv_exit(void)
-{
- platform_driver_unregister(&hv_driver);
-}
-
-module_init(sunhv_init);
-module_exit(sunhv_exit);
-
+#if 0 /* ...def MODULE ; never supported as such */
MODULE_AUTHOR("David S. Miller");
MODULE_DESCRIPTION("SUN4V Hypervisor console driver");
MODULE_VERSION("2.0");
MODULE_LICENSE("GPL");
+#endif
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 7d2532b..73190f5 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -950,7 +950,7 @@
if ((termios->c_cflag & CREAD) == 0)
port->read_status_mask &= ~BD_SC_EMPTY;
- baud = uart_get_baud_rate(port, termios, old, 0, 115200);
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
/* Do we really need a spinlock here? */
spin_lock_irqsave(&port->lock, flags);
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 4cf263d..5a3fa89 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -291,12 +291,11 @@
n->flags = flags;
buf->tail = n;
b->commit = b->used;
- /* paired w/ barrier in flush_to_ldisc(); ensures the
+ /* paired w/ acquire in flush_to_ldisc(); ensures the
* latest commit value can be read before the head is
* advanced to the next buffer
*/
- smp_wmb();
- b->next = n;
+ smp_store_release(&b->next, n);
} else if (change)
size = 0;
else
@@ -445,7 +444,6 @@
if (count)
disc->ops->receive_buf(tty, p, f, count);
}
- head->read += count;
return count;
}
@@ -488,12 +486,11 @@
if (atomic_read(&buf->priority))
break;
- next = head->next;
- /* paired w/ barrier in __tty_buffer_request_room();
+ /* paired w/ release in __tty_buffer_request_room();
* ensures commit value read is not stale if the head
* is advancing to the next buffer
*/
- smp_rmb();
+ next = smp_load_acquire(&head->next);
count = head->commit - head->read;
if (!count) {
if (next == NULL) {
@@ -508,6 +505,7 @@
count = receive_buf(tty, head, count);
if (!count)
break;
+ head->read += count;
}
mutex_unlock(&buf->lock);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 57fc6ee..02785d8 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -106,6 +106,11 @@
#include <linux/nsproxy.h>
#undef TTY_DEBUG_HANGUP
+#ifdef TTY_DEBUG_HANGUP
+# define tty_debug_hangup(tty, f, args...) tty_debug(tty, f, ##args)
+#else
+# define tty_debug_hangup(tty, f, args...) do { } while (0)
+#endif
#define TTY_PARANOIA_CHECK 1
#define CHECK_TTY_COUNT 1
@@ -388,33 +393,40 @@
int tty_check_change(struct tty_struct *tty)
{
unsigned long flags;
+ struct pid *pgrp;
int ret = 0;
if (current->signal->tty != tty)
return 0;
+ rcu_read_lock();
+ pgrp = task_pgrp(current);
+
spin_lock_irqsave(&tty->ctrl_lock, flags);
if (!tty->pgrp) {
printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n");
goto out_unlock;
}
- if (task_pgrp(current) == tty->pgrp)
+ if (pgrp == tty->pgrp)
goto out_unlock;
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
if (is_ignored(SIGTTOU))
- goto out;
+ goto out_rcuunlock;
if (is_current_pgrp_orphaned()) {
ret = -EIO;
- goto out;
+ goto out_rcuunlock;
}
- kill_pgrp(task_pgrp(current), SIGTTOU, 1);
+ kill_pgrp(pgrp, SIGTTOU, 1);
+ rcu_read_unlock();
set_thread_flag(TIF_SIGPENDING);
ret = -ERESTARTSYS;
-out:
return ret;
out_unlock:
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+out_rcuunlock:
+ rcu_read_unlock();
return ret;
}
@@ -524,7 +536,8 @@
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
tty->session = get_pid(task_session(current));
if (current->signal->tty) {
- printk(KERN_DEBUG "tty not NULL!!\n");
+ tty_debug(tty, "current tty %s not NULL!!\n",
+ current->signal->tty->name);
tty_kref_put(current->signal->tty);
}
put_pid(current->signal->tty_old_pgrp);
@@ -766,9 +779,7 @@
void tty_hangup(struct tty_struct *tty)
{
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "%s hangup...\n", tty_name(tty));
-#endif
+ tty_debug_hangup(tty, "\n");
schedule_work(&tty->hangup_work);
}
@@ -785,9 +796,7 @@
void tty_vhangup(struct tty_struct *tty)
{
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty));
-#endif
+ tty_debug_hangup(tty, "\n");
__tty_hangup(tty, 0);
}
@@ -824,9 +833,7 @@
static void tty_vhangup_session(struct tty_struct *tty)
{
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty));
-#endif
+ tty_debug_hangup(tty, "\n");
__tty_hangup(tty, 1);
}
@@ -920,12 +927,8 @@
tty->pgrp = NULL;
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
tty_kref_put(tty);
- } else {
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "error attempted to write to tty [0x%p]"
- " = NULL", tty);
-#endif
- }
+ } else
+ tty_debug_hangup(tty, "no current tty\n");
spin_unlock_irq(¤t->sighand->siglock);
/* Now clear signal->tty under the lock */
@@ -1705,8 +1708,7 @@
{
#ifdef TTY_PARANOIA_CHECK
if (idx < 0 || idx >= tty->driver->num) {
- printk(KERN_DEBUG "%s: bad idx when trying to free (%s)\n",
- __func__, tty->name);
+ tty_debug(tty, "bad idx %d\n", idx);
return -1;
}
@@ -1715,20 +1717,20 @@
return 0;
if (tty != tty->driver->ttys[idx]) {
- printk(KERN_DEBUG "%s: driver.table[%d] not tty for (%s)\n",
- __func__, idx, tty->name);
+ tty_debug(tty, "bad driver table[%d] = %p\n",
+ idx, tty->driver->ttys[idx]);
return -1;
}
if (tty->driver->other) {
struct tty_struct *o_tty = tty->link;
if (o_tty != tty->driver->other->ttys[idx]) {
- printk(KERN_DEBUG "%s: other->table[%d] not o_tty for (%s)\n",
- __func__, idx, tty->name);
+ tty_debug(tty, "bad other table[%d] = %p\n",
+ idx, tty->driver->other->ttys[idx]);
return -1;
}
if (o_tty->link != tty) {
- printk(KERN_DEBUG "%s: bad pty pointers\n", __func__);
+ tty_debug(tty, "bad link = %p\n", o_tty->link);
return -1;
}
}
@@ -1782,10 +1784,7 @@
return 0;
}
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "%s: %s (tty count=%d)...\n", __func__,
- tty_name(tty), tty->count);
-#endif
+ tty_debug_hangup(tty, "(tty count=%d)...\n", tty->count);
if (tty->ops->close)
tty->ops->close(tty, filp);
@@ -1895,9 +1894,7 @@
if (!final)
return 0;
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "%s: %s: final close\n", __func__, tty_name(tty));
-#endif
+ tty_debug_hangup(tty, "final close\n");
/*
* Ask the line discipline code to release its structures
*/
@@ -1906,10 +1903,7 @@
/* Wait for pending work before tty destruction commmences */
tty_flush_works(tty);
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "%s: %s: freeing structure...\n", __func__,
- tty_name(tty));
-#endif
+ tty_debug_hangup(tty, "freeing structure...\n");
/*
* The release_tty function takes care of the details of clearing
* the slots and preserving the termios structure. The tty_unlock_pair
@@ -2098,9 +2092,9 @@
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
tty->driver->subtype == PTY_TYPE_MASTER)
noctty = 1;
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "%s: opening %s...\n", __func__, tty->name);
-#endif
+
+ tty_debug_hangup(tty, "(tty count=%d)\n", tty->count);
+
if (tty->ops->open)
retval = tty->ops->open(tty, filp);
else
@@ -2108,10 +2102,8 @@
filp->f_flags = saved_flags;
if (retval) {
-#ifdef TTY_DEBUG_HANGUP
- printk(KERN_DEBUG "%s: error %d in opening %s...\n", __func__,
- retval, tty->name);
-#endif
+ tty_debug_hangup(tty, "error %d, releasing...\n", retval);
+
tty_unlock(tty); /* need to call tty_release without BTM */
tty_release(inode, filp);
if (retval != -ERESTARTSYS)
@@ -3160,9 +3152,12 @@
unsigned int index, unsigned int count)
{
/* init here, since reused cdevs cause crashes */
- cdev_init(&driver->cdevs[index], &tty_fops);
- driver->cdevs[index].owner = driver->owner;
- return cdev_add(&driver->cdevs[index], dev, count);
+ driver->cdevs[index] = cdev_alloc();
+ if (!driver->cdevs[index])
+ return -ENOMEM;
+ cdev_init(driver->cdevs[index], &tty_fops);
+ driver->cdevs[index]->owner = driver->owner;
+ return cdev_add(driver->cdevs[index], dev, count);
}
/**
@@ -3268,8 +3263,10 @@
error:
put_device(dev);
- if (cdev)
- cdev_del(&driver->cdevs[index]);
+ if (cdev) {
+ cdev_del(driver->cdevs[index]);
+ driver->cdevs[index] = NULL;
+ }
return ERR_PTR(retval);
}
EXPORT_SYMBOL_GPL(tty_register_device_attr);
@@ -3289,8 +3286,10 @@
{
device_destroy(tty_class,
MKDEV(driver->major, driver->minor_start) + index);
- if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC))
- cdev_del(&driver->cdevs[index]);
+ if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
+ cdev_del(driver->cdevs[index]);
+ driver->cdevs[index] = NULL;
+ }
}
EXPORT_SYMBOL(tty_unregister_device);
@@ -3355,6 +3354,7 @@
kfree(driver->ports);
kfree(driver->ttys);
kfree(driver->termios);
+ kfree(driver->cdevs);
kfree(driver);
return ERR_PTR(err);
}
@@ -3383,7 +3383,7 @@
}
proc_tty_unregister_driver(driver);
if (driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)
- cdev_del(&driver->cdevs[0]);
+ cdev_del(driver->cdevs[0]);
}
kfree(driver->cdevs);
kfree(driver->ports);
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index 5232fb6..9c5aebf 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -26,6 +26,12 @@
#undef TTY_DEBUG_WAIT_UNTIL_SENT
+#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
+# define tty_debug_wait_until_sent(tty, f, args...) tty_debug(tty, f, ##args)
+#else
+# define tty_debug_wait_until_sent(tty, f, args...) do {} while (0)
+#endif
+
#undef DEBUG
/*
@@ -210,9 +216,8 @@
void tty_wait_until_sent(struct tty_struct *tty, long timeout)
{
-#ifdef TTY_DEBUG_WAIT_UNTIL_SENT
- printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty));
-#endif
+ tty_debug_wait_until_sent(tty, "\n");
+
if (!timeout)
timeout = MAX_SCHEDULE_TIMEOUT;
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index c07fb5d..71750cb 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -22,9 +22,7 @@
#undef LDISC_DEBUG_HANGUP
#ifdef LDISC_DEBUG_HANGUP
-#define tty_ldisc_debug(tty, f, args...) ({ \
- printk(KERN_DEBUG "%s: %s: " f, __func__, tty_name(tty), ##args); \
-})
+#define tty_ldisc_debug(tty, f, args...) tty_debug(tty, f, ##args)
#else
#define tty_ldisc_debug(tty, f, args...)
#endif
@@ -449,6 +447,8 @@
ret = ld->ops->open(tty);
if (ret)
clear_bit(TTY_LDISC_OPEN, &tty->flags);
+
+ tty_ldisc_debug(tty, "%p: opened\n", tty->ldisc);
return ret;
}
return 0;
@@ -469,6 +469,7 @@
clear_bit(TTY_LDISC_OPEN, &tty->flags);
if (ld->ops->close)
ld->ops->close(tty);
+ tty_ldisc_debug(tty, "%p: closed\n", tty->ldisc);
}
/**
@@ -662,7 +663,7 @@
int reset = tty->driver->flags & TTY_DRIVER_RESET_TERMIOS;
int err = 0;
- tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
+ tty_ldisc_debug(tty, "%p: closing\n", tty->ldisc);
ld = tty_ldisc_ref(tty);
if (ld != NULL) {
@@ -712,7 +713,7 @@
if (reset)
tty_reset_termios(tty);
- tty_ldisc_debug(tty, "re-opened ldisc: %p\n", tty->ldisc);
+ tty_ldisc_debug(tty, "%p: re-opened\n", tty->ldisc);
}
/**
@@ -776,8 +777,6 @@
* it does not race with the set_ldisc code path.
*/
- tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
-
tty_ldisc_lock_pair(tty, o_tty);
tty_ldisc_kill(tty);
if (o_tty)
@@ -787,7 +786,7 @@
/* And the memory resources remaining (buffers, termios) will be
disposed of when the kref hits zero */
- tty_ldisc_debug(tty, "ldisc closed\n");
+ tty_ldisc_debug(tty, "released\n");
}
/**
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c
index ea27804..381a2b1 100644
--- a/drivers/tty/vt/selection.c
+++ b/drivers/tty/vt/selection.c
@@ -356,6 +356,7 @@
schedule();
continue;
}
+ __set_current_state(TASK_RUNNING);
count = sel_buffer_lth - pasted;
count = tty_ldisc_receive_buf(ld, sel_buffer + pasted, NULL,
count);
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 8fe5298..4462d16 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -742,6 +742,8 @@
__module_get(vc->vc_sw->owner);
vc->vc_num = num;
vc->vc_display_fg = &master_display_fg;
+ if (vc->vc_uni_pagedir_loc)
+ con_free_unimap(vc);
vc->vc_uni_pagedir_loc = &vc->vc_uni_pagedir;
vc->vc_uni_pagedir = NULL;
vc->vc_hi_font_mask = 0;
diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig
index 48fb1d9..52c98ce 100644
--- a/drivers/uio/Kconfig
+++ b/drivers/uio/Kconfig
@@ -127,7 +127,7 @@
config UIO_PRUSS
tristate "Texas Instruments PRUSS driver"
select GENERIC_ALLOCATOR
- depends on HAS_IOMEM
+ depends on HAS_IOMEM && HAS_DMA
help
PRUSS driver for OMAPL138/DA850/AM18XX devices
PRUSS driver requires user space components, examples and user space
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index 3257d42..8196581 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -896,6 +896,7 @@
static void __exit uio_exit(void)
{
release_uio_class();
+ idr_destroy(&uio_idr);
}
module_init(uio_init)
diff --git a/drivers/uio/uio_fsl_elbc_gpcm.c b/drivers/uio/uio_fsl_elbc_gpcm.c
index b6cac91..2bcf80c 100644
--- a/drivers/uio/uio_fsl_elbc_gpcm.c
+++ b/drivers/uio/uio_fsl_elbc_gpcm.c
@@ -480,19 +480,7 @@
.probe = uio_fsl_elbc_gpcm_probe,
.remove = uio_fsl_elbc_gpcm_remove,
};
-
-static int __init uio_fsl_elbc_gpcm_init(void)
-{
- return platform_driver_register(&uio_fsl_elbc_gpcm_driver);
-}
-
-static void __exit uio_fsl_elbc_gpcm_exit(void)
-{
- platform_driver_unregister(&uio_fsl_elbc_gpcm_driver);
-}
-
-module_init(uio_fsl_elbc_gpcm_init);
-module_exit(uio_fsl_elbc_gpcm_exit);
+module_platform_driver(uio_fsl_elbc_gpcm_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("John Ogness <john.ogness@linutronix.de>");
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c
index 813d4d3..1173f9c 100644
--- a/drivers/usb/atm/cxacru.c
+++ b/drivers/usb/atm/cxacru.c
@@ -270,6 +270,7 @@
static ssize_t cxacru_sysfs_showattr_bool(u32 value, char *buf)
{
static char *str[] = { "no", "yes" };
+
if (unlikely(value >= ARRAY_SIZE(str)))
return snprintf(buf, PAGE_SIZE, "%u\n", value);
return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
@@ -278,6 +279,7 @@
static ssize_t cxacru_sysfs_showattr_LINK(u32 value, char *buf)
{
static char *str[] = { NULL, "not connected", "connected", "lost" };
+
if (unlikely(value >= ARRAY_SIZE(str) || str[value] == NULL))
return snprintf(buf, PAGE_SIZE, "%u\n", value);
return snprintf(buf, PAGE_SIZE, "%s\n", str[value]);
@@ -702,6 +704,7 @@
len = ret / 4;
for (offb = 0; offb < len; ) {
int l = le32_to_cpu(buf[offb++]);
+
if (l < 0 || l > stride || l > (len - offb) / 2) {
if (printk_ratelimit())
usb_err(instance->usbatm, "invalid data length from cm %#x: %d\n",
@@ -732,6 +735,7 @@
static int cxacru_card_status(struct cxacru_data *instance)
{
int ret = cxacru_cm(instance, CM_REQUEST_CARD_GET_STATUS, NULL, 0, NULL, 0);
+
if (ret < 0) { /* firmware not loaded */
usb_dbg(instance->usbatm, "cxacru_adsl_start: CARD_GET_STATUS returned %d\n", ret);
return ret;
@@ -945,6 +949,7 @@
offb = offd = 0;
do {
int l = min_t(int, stride, size - offd);
+
buf[offb++] = fw;
buf[offb++] = l;
buf[offb++] = code1;
@@ -1091,8 +1096,8 @@
{
const struct firmware *fw, *bp;
struct cxacru_data *instance = usbatm_instance->driver_data;
-
int ret = cxacru_find_firmware(instance, "fw", &fw);
+
if (ret) {
usb_warn(usbatm_instance, "firmware (cxacru-fw.bin) unavailable (system misconfigured?)\n");
return ret;
diff --git a/drivers/usb/chipidea/bits.h b/drivers/usb/chipidea/bits.h
index 3cb9bda..e462f55 100644
--- a/drivers/usb/chipidea/bits.h
+++ b/drivers/usb/chipidea/bits.h
@@ -25,6 +25,9 @@
#define VERSION (0xF << 25)
#define CIVERSION (0x7 << 29)
+/* SBUSCFG */
+#define AHBBRST_MASK 0x7
+
/* HCCPARAMS */
#define HCCPARAMS_LEN BIT(17)
@@ -53,6 +56,15 @@
#define DEVICEADDR_USBADRA BIT(24)
#define DEVICEADDR_USBADR (0x7FUL << 25)
+/* TTCTRL */
+#define TTCTRL_TTHA_MASK (0x7fUL << 24)
+/* Set non-zero value for internal TT Hub address representation */
+#define TTCTRL_TTHA (0x7fUL << 24)
+
+/* BURSTSIZE */
+#define RX_BURST_MASK 0xff
+#define TX_BURST_MASK 0xff00
+
/* PORTSC */
#define PORTSC_CCS BIT(0)
#define PORTSC_CSC BIT(1)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 6d6200e..41d7cf6 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -50,6 +50,8 @@
OP_USBINTR,
OP_DEVICEADDR,
OP_ENDPTLISTADDR,
+ OP_TTCTRL,
+ OP_BURSTSIZE,
OP_PORTSC,
OP_DEVLC,
OP_OTGSC,
@@ -406,8 +408,11 @@
static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci)
{
#ifdef CONFIG_USB_OTG_FSM
+ struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps;
+
return ci->is_otg && ci->roles[CI_ROLE_HOST] &&
- ci->roles[CI_ROLE_GADGET];
+ ci->roles[CI_ROLE_GADGET] && (otg_caps->srp_support ||
+ otg_caps->hnp_support || otg_caps->adp_support);
#else
return false;
#endif
@@ -426,4 +431,6 @@
int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
u32 value, unsigned int timeout_ms);
+void ci_platform_configure(struct ci_hdrc *ci);
+
#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index 389f0e0..867e9f3 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -29,26 +29,31 @@
};
static const struct ci_hdrc_imx_platform_flag imx27_usb_data = {
+ CI_HDRC_DISABLE_STREAMING,
};
static const struct ci_hdrc_imx_platform_flag imx28_usb_data = {
.flags = CI_HDRC_IMX28_WRITE_FIX |
- CI_HDRC_TURN_VBUS_EARLY_ON,
+ CI_HDRC_TURN_VBUS_EARLY_ON |
+ CI_HDRC_DISABLE_STREAMING,
};
static const struct ci_hdrc_imx_platform_flag imx6q_usb_data = {
.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
- CI_HDRC_TURN_VBUS_EARLY_ON,
+ CI_HDRC_TURN_VBUS_EARLY_ON |
+ CI_HDRC_DISABLE_STREAMING,
};
static const struct ci_hdrc_imx_platform_flag imx6sl_usb_data = {
.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
- CI_HDRC_TURN_VBUS_EARLY_ON,
+ CI_HDRC_TURN_VBUS_EARLY_ON |
+ CI_HDRC_DISABLE_HOST_STREAMING,
};
static const struct ci_hdrc_imx_platform_flag imx6sx_usb_data = {
.flags = CI_HDRC_SUPPORTS_RUNTIME_PM |
- CI_HDRC_TURN_VBUS_EARLY_ON,
+ CI_HDRC_TURN_VBUS_EARLY_ON |
+ CI_HDRC_DISABLE_HOST_STREAMING,
};
static const struct of_device_id ci_hdrc_imx_dt_ids[] = {
@@ -104,7 +109,7 @@
misc_pdev = of_find_device_by_node(args.np);
of_node_put(args.np);
- if (!misc_pdev)
+ if (!misc_pdev || !platform_get_drvdata(misc_pdev))
return ERR_PTR(-EPROBE_DEFER);
data->dev = &misc_pdev->dev;
@@ -126,7 +131,7 @@
struct ci_hdrc_platform_data pdata = {
.name = dev_name(&pdev->dev),
.capoffset = DEF_CAPOFFSET,
- .flags = CI_HDRC_DISABLE_STREAMING,
+ .flags = CI_HDRC_SET_NON_ZERO_TTHA,
};
int ret;
const struct of_device_id *of_id =
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 74fea4f..3feebf7 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -64,6 +64,7 @@
#include <linux/of.h>
#include <linux/phy.h>
#include <linux/regulator/consumer.h>
+#include <linux/usb/ehci_def.h>
#include "ci.h"
#include "udc.h"
@@ -84,6 +85,8 @@
[OP_USBINTR] = 0x08U,
[OP_DEVICEADDR] = 0x14U,
[OP_ENDPTLISTADDR] = 0x18U,
+ [OP_TTCTRL] = 0x1CU,
+ [OP_BURSTSIZE] = 0x20U,
[OP_PORTSC] = 0x44U,
[OP_DEVLC] = 0x84U,
[OP_OTGSC] = 0x64U,
@@ -106,6 +109,8 @@
[OP_USBINTR] = 0x08U,
[OP_DEVICEADDR] = 0x14U,
[OP_ENDPTLISTADDR] = 0x18U,
+ [OP_TTCTRL] = 0x1CU,
+ [OP_BURSTSIZE] = 0x20U,
[OP_PORTSC] = 0x44U,
[OP_DEVLC] = 0x84U,
[OP_OTGSC] = 0xC4U,
@@ -118,7 +123,7 @@
[OP_ENDPTCTRL] = 0xECU,
};
-static int hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
+static void hw_alloc_regmap(struct ci_hdrc *ci, bool is_lpm)
{
int i;
@@ -134,7 +139,6 @@
? ci_regs_lpm[OP_ENDPTCTRL]
: ci_regs_nolpm[OP_ENDPTCTRL]);
- return 0;
}
static enum ci_revision ci_get_revision(struct ci_hdrc *ci)
@@ -403,6 +407,55 @@
return ret;
}
+
+/**
+ * ci_platform_configure: do controller configure
+ * @ci: the controller
+ *
+ */
+void ci_platform_configure(struct ci_hdrc *ci)
+{
+ bool is_device_mode, is_host_mode;
+
+ is_device_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_DC;
+ is_host_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_HC;
+
+ if (is_device_mode &&
+ (ci->platdata->flags & CI_HDRC_DISABLE_DEVICE_STREAMING))
+ hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
+
+ if (is_host_mode &&
+ (ci->platdata->flags & CI_HDRC_DISABLE_HOST_STREAMING))
+ hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
+
+ if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) {
+ if (ci->hw_bank.lpm)
+ hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC);
+ else
+ hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC);
+ }
+
+ if (ci->platdata->flags & CI_HDRC_SET_NON_ZERO_TTHA)
+ hw_write(ci, OP_TTCTRL, TTCTRL_TTHA_MASK, TTCTRL_TTHA);
+
+ hw_write(ci, OP_USBCMD, 0xff0000, ci->platdata->itc_setting << 16);
+
+ if (ci->platdata->flags & CI_HDRC_OVERRIDE_AHB_BURST)
+ hw_write_id_reg(ci, ID_SBUSCFG, AHBBRST_MASK,
+ ci->platdata->ahb_burst_config);
+
+ /* override burst size, take effect only when ahb_burst_config is 0 */
+ if (!hw_read_id_reg(ci, ID_SBUSCFG, AHBBRST_MASK)) {
+ if (ci->platdata->flags & CI_HDRC_OVERRIDE_TX_BURST)
+ hw_write(ci, OP_BURSTSIZE, TX_BURST_MASK,
+ ci->platdata->tx_burst_size << __ffs(TX_BURST_MASK));
+
+ if (ci->platdata->flags & CI_HDRC_OVERRIDE_RX_BURST)
+ hw_write(ci, OP_BURSTSIZE, RX_BURST_MASK,
+ ci->platdata->rx_burst_size);
+ }
+}
+
/**
* hw_controller_reset: do controller reset
* @ci: the controller
@@ -447,16 +500,6 @@
ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_RESET_EVENT);
- if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING)
- hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
-
- if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED) {
- if (ci->hw_bank.lpm)
- hw_write(ci, OP_DEVLC, DEVLC_PFSC, DEVLC_PFSC);
- else
- hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC);
- }
-
/* USBMODE should be configured step by step */
hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_IDLE);
hw_write(ci, OP_USBMODE, USBMODE_CM, USBMODE_CM_DC);
@@ -469,6 +512,8 @@
return -ENODEV;
}
+ ci_platform_configure(ci);
+
return 0;
}
@@ -560,6 +605,8 @@
static int ci_get_platdata(struct device *dev,
struct ci_hdrc_platform_data *platdata)
{
+ int ret;
+
if (!platdata->phy_mode)
platdata->phy_mode = of_usb_get_phy_mode(dev->of_node);
@@ -588,9 +635,66 @@
of_usb_host_tpl_support(dev->of_node);
}
+ if (platdata->dr_mode == USB_DR_MODE_OTG) {
+ /* We can support HNP and SRP of OTG 2.0 */
+ platdata->ci_otg_caps.otg_rev = 0x0200;
+ platdata->ci_otg_caps.hnp_support = true;
+ platdata->ci_otg_caps.srp_support = true;
+
+ /* Update otg capabilities by DT properties */
+ ret = of_usb_update_otg_caps(dev->of_node,
+ &platdata->ci_otg_caps);
+ if (ret)
+ return ret;
+ }
+
if (of_usb_get_maximum_speed(dev->of_node) == USB_SPEED_FULL)
platdata->flags |= CI_HDRC_FORCE_FULLSPEED;
+ platdata->itc_setting = 1;
+ if (of_find_property(dev->of_node, "itc-setting", NULL)) {
+ ret = of_property_read_u32(dev->of_node, "itc-setting",
+ &platdata->itc_setting);
+ if (ret) {
+ dev_err(dev,
+ "failed to get itc-setting\n");
+ return ret;
+ }
+ }
+
+ if (of_find_property(dev->of_node, "ahb-burst-config", NULL)) {
+ ret = of_property_read_u32(dev->of_node, "ahb-burst-config",
+ &platdata->ahb_burst_config);
+ if (ret) {
+ dev_err(dev,
+ "failed to get ahb-burst-config\n");
+ return ret;
+ }
+ platdata->flags |= CI_HDRC_OVERRIDE_AHB_BURST;
+ }
+
+ if (of_find_property(dev->of_node, "tx-burst-size-dword", NULL)) {
+ ret = of_property_read_u32(dev->of_node, "tx-burst-size-dword",
+ &platdata->tx_burst_size);
+ if (ret) {
+ dev_err(dev,
+ "failed to get tx-burst-size-dword\n");
+ return ret;
+ }
+ platdata->flags |= CI_HDRC_OVERRIDE_TX_BURST;
+ }
+
+ if (of_find_property(dev->of_node, "rx-burst-size-dword", NULL)) {
+ ret = of_property_read_u32(dev->of_node, "rx-burst-size-dword",
+ &platdata->rx_burst_size);
+ if (ret) {
+ dev_err(dev,
+ "failed to get rx-burst-size-dword\n");
+ return ret;
+ }
+ platdata->flags |= CI_HDRC_OVERRIDE_RX_BURST;
+ }
+
return 0;
}
@@ -1024,7 +1128,18 @@
},
};
-module_platform_driver(ci_hdrc_driver);
+static int __init ci_hdrc_platform_register(void)
+{
+ ci_hdrc_host_driver_init();
+ return platform_driver_register(&ci_hdrc_driver);
+}
+module_init(ci_hdrc_platform_register);
+
+static void __exit ci_hdrc_platform_unregister(void)
+{
+ platform_driver_unregister(&ci_hdrc_driver);
+}
+module_exit(ci_hdrc_platform_unregister);
MODULE_ALIAS("platform:ci_hdrc");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/chipidea/debug.c b/drivers/usb/chipidea/debug.c
index 5b7061a..080b7be 100644
--- a/drivers/usb/chipidea/debug.c
+++ b/drivers/usb/chipidea/debug.c
@@ -10,6 +10,7 @@
#include <linux/usb/phy.h>
#include <linux/usb/otg.h>
#include <linux/usb/otg-fsm.h>
+#include <linux/usb/chipidea.h>
#include "ci.h"
#include "udc.h"
@@ -66,9 +67,11 @@
unsigned long flags;
unsigned mode;
+ pm_runtime_get_sync(ci->dev);
spin_lock_irqsave(&ci->lock, flags);
mode = hw_port_test_get(ci);
spin_unlock_irqrestore(&ci->lock, flags);
+ pm_runtime_put_sync(ci->dev);
seq_printf(s, "mode = %u\n", mode);
@@ -98,9 +101,11 @@
if (sscanf(buf, "%u", &mode) != 1)
return -EINVAL;
+ pm_runtime_get_sync(ci->dev);
spin_lock_irqsave(&ci->lock, flags);
ret = hw_port_test_set(ci, mode);
spin_unlock_irqrestore(&ci->lock, flags);
+ pm_runtime_put_sync(ci->dev);
return ret ? ret : count;
}
@@ -316,8 +321,10 @@
if (role == CI_ROLE_END || role == ci->role)
return -EINVAL;
+ pm_runtime_get_sync(ci->dev);
ci_role_stop(ci);
ret = ci_role_start(ci, role);
+ pm_runtime_put_sync(ci->dev);
return ret ? ret : count;
}
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 6cf87b8..3d24304 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -37,15 +37,14 @@
struct ehci_ci_priv {
struct regulator *reg_vbus;
- struct ci_hdrc *ci;
};
static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
{
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
struct ehci_ci_priv *priv = (struct ehci_ci_priv *)ehci->priv;
- struct ci_hdrc *ci = priv->ci;
struct device *dev = hcd->self.controller;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
int ret = 0;
int port = HCS_N_PORTS(ehci->hcs_params);
@@ -78,9 +77,25 @@
return 0;
};
+static int ehci_ci_reset(struct usb_hcd *hcd)
+{
+ struct device *dev = hcd->self.controller;
+ struct ci_hdrc *ci = dev_get_drvdata(dev);
+ int ret;
+
+ ret = ehci_setup(hcd);
+ if (ret)
+ return ret;
+
+ ci_platform_configure(ci);
+
+ return ret;
+}
+
static const struct ehci_driver_overrides ehci_ci_overrides = {
.extra_priv_size = sizeof(struct ehci_ci_priv),
.port_power = ehci_ci_portpower,
+ .reset = ehci_ci_reset,
};
static irqreturn_t host_irq(struct ci_hdrc *ci)
@@ -123,7 +138,6 @@
priv = (struct ehci_ci_priv *)ehci->priv;
priv->reg_vbus = NULL;
- priv->ci = ci;
if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci)) {
if (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON) {
@@ -153,12 +167,6 @@
}
}
- if (ci->platdata->flags & CI_HDRC_DISABLE_STREAMING)
- hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
-
- if (ci->platdata->flags & CI_HDRC_FORCE_FULLSPEED)
- hw_write(ci, OP_PORTSC, PORTSC_PFSC, PORTSC_PFSC);
-
return ret;
disable_reg:
@@ -249,9 +257,12 @@
rdrv->name = "host";
ci->roles[CI_ROLE_HOST] = rdrv;
+ return 0;
+}
+
+void ci_hdrc_host_driver_init(void)
+{
ehci_init_driver(&ci_ehci_hc_driver, &ehci_ci_overrides);
orig_bus_suspend = ci_ehci_hc_driver.bus_suspend;
ci_ehci_hc_driver.bus_suspend = ci_ehci_bus_suspend;
-
- return 0;
}
diff --git a/drivers/usb/chipidea/host.h b/drivers/usb/chipidea/host.h
index 5707bf3..0f12f13 100644
--- a/drivers/usb/chipidea/host.h
+++ b/drivers/usb/chipidea/host.h
@@ -5,6 +5,7 @@
int ci_hdrc_host_init(struct ci_hdrc *ci);
void ci_hdrc_host_destroy(struct ci_hdrc *ci);
+void ci_hdrc_host_driver_init(void);
#else
@@ -18,6 +19,11 @@
}
+static void ci_hdrc_host_driver_init(void)
+{
+
+}
+
#endif
#endif /* __DRIVERS_USB_CHIPIDEA_HOST_H */
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index 19d655a..00ab59d 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -525,7 +525,6 @@
ci_role_start(ci, CI_ROLE_HOST);
} else {
ci_role_stop(ci);
- hw_device_reset(ci);
ci_role_start(ci, CI_ROLE_GADGET);
}
return 0;
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 764f668..a637da2 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -445,7 +445,7 @@
rest -= count;
}
- if (hwreq->req.zero && hwreq->req.length
+ if (hwreq->req.zero && hwreq->req.length && hwep->dir == TX
&& (hwreq->req.length % hwep->ep.maxpacket == 0))
add_td_to_list(hwep, hwreq, 0);
@@ -1090,6 +1090,13 @@
if (ci_otg_is_fsm_mode(ci))
err = otg_a_alt_hnp_support(ci);
break;
+ case USB_DEVICE_A_HNP_SUPPORT:
+ if (ci_otg_is_fsm_mode(ci)) {
+ ci->gadget.a_hnp_support = 1;
+ err = isr_setup_status_phase(
+ ci);
+ }
+ break;
default:
goto delegate;
}
@@ -1624,6 +1631,20 @@
hwep->ep.name = hwep->name;
hwep->ep.ops = &usb_ep_ops;
+
+ if (i == 0) {
+ hwep->ep.caps.type_control = true;
+ } else {
+ hwep->ep.caps.type_iso = true;
+ hwep->ep.caps.type_bulk = true;
+ hwep->ep.caps.type_int = true;
+ }
+
+ if (j == TX)
+ hwep->ep.caps.dir_in = true;
+ else
+ hwep->ep.caps.dir_out = true;
+
/*
* for ep0: maxP defined in desc, for other
* eps, maxP is set by epautoconfig() called
@@ -1827,6 +1848,7 @@
static int udc_start(struct ci_hdrc *ci)
{
struct device *dev = ci->dev;
+ struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps;
int retval = 0;
spin_lock_init(&ci->lock);
@@ -1834,8 +1856,12 @@
ci->gadget.ops = &usb_gadget_ops;
ci->gadget.speed = USB_SPEED_UNKNOWN;
ci->gadget.max_speed = USB_SPEED_HIGH;
- ci->gadget.is_otg = ci->is_otg ? 1 : 0;
ci->gadget.name = ci->platdata->name;
+ ci->gadget.otg_caps = otg_caps;
+
+ if (ci->is_otg && (otg_caps->hnp_support || otg_caps->srp_support ||
+ otg_caps->adp_support))
+ ci->gadget.is_otg = 1;
INIT_LIST_HEAD(&ci->gadget.ep_list);
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 3cefd49..5ddab30 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -54,6 +54,7 @@
#define MX53_USB_PHYCTRL1_PLLDIV_MASK 0x3
#define MX53_USB_PLL_DIV_24_MHZ 0x01
+#define MX6_BM_NON_BURST_SETTING BIT(1)
#define MX6_BM_OVER_CUR_DIS BIT(7)
#define MX6_BM_WAKEUP_ENABLE BIT(10)
#define MX6_BM_ID_WAKEUP BIT(16)
@@ -255,14 +256,21 @@
if (data->index > 3)
return -EINVAL;
+ spin_lock_irqsave(&usbmisc->lock, flags);
+
if (data->disable_oc) {
- spin_lock_irqsave(&usbmisc->lock, flags);
reg = readl(usbmisc->base + data->index * 4);
writel(reg | MX6_BM_OVER_CUR_DIS,
usbmisc->base + data->index * 4);
- spin_unlock_irqrestore(&usbmisc->lock, flags);
}
+ /* SoC non-burst setting */
+ reg = readl(usbmisc->base + data->index * 4);
+ writel(reg | MX6_BM_NON_BURST_SETTING,
+ usbmisc->base + data->index * 4);
+
+ spin_unlock_irqrestore(&usbmisc->lock, flags);
+
usbmisc_imx6q_set_wakeup(data, false);
return 0;
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 519a77b..b30e742 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1944,6 +1944,7 @@
usb_deregister(&acm_driver);
tty_unregister_driver(acm_tty_driver);
put_tty_driver(acm_tty_driver);
+ idr_destroy(&acm_minors);
}
module_init(acm_init);
diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
index f38e875..433bbc3 100644
--- a/drivers/usb/class/usblp.c
+++ b/drivers/usb/class/usblp.c
@@ -57,6 +57,7 @@
#include <linux/mutex.h>
#undef DEBUG
#include <linux/usb.h>
+#include <linux/usb/ch9.h>
#include <linux/ratelimit.h>
/*
@@ -79,12 +80,20 @@
#define IOCNR_SOFT_RESET 7
/* Get device_id string: */
#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
-/* The following ioctls were added for http://hpoj.sourceforge.net: */
-/* Get two-int array:
- * [0]=current protocol (1=7/1/1, 2=7/1/2, 3=7/1/3),
- * [1]=supported protocol mask (mask&(1<<n)!=0 means 7/1/n supported): */
+/* The following ioctls were added for http://hpoj.sourceforge.net:
+ * Get two-int array:
+ * [0]=current protocol
+ * (1=USB_CLASS_PRINTER/1/1, 2=USB_CLASS_PRINTER/1/2,
+ * 3=USB_CLASS_PRINTER/1/3),
+ * [1]=supported protocol mask (mask&(1<<n)!=0 means
+ * USB_CLASS_PRINTER/1/n supported):
+ */
#define LPIOC_GET_PROTOCOLS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_PROTOCOLS, len)
-/* Set protocol (arg: 1=7/1/1, 2=7/1/2, 3=7/1/3): */
+/*
+ * Set protocol
+ * (arg: 1=USB_CLASS_PRINTER/1/1, 2=USB_CLASS_PRINTER/1/2,
+ * 3=USB_CLASS_PRINTER/1/3):
+ */
#define LPIOC_SET_PROTOCOL _IOC(_IOC_WRITE, 'P', IOCNR_SET_PROTOCOL, 0)
/* Set channel number (HP Vendor-specific command): */
#define LPIOC_HP_SET_CHANNEL _IOC(_IOC_WRITE, 'P', IOCNR_HP_SET_CHANNEL, 0)
@@ -146,8 +155,10 @@
int readcount; /* Counter for reads */
int ifnum; /* Interface number */
struct usb_interface *intf; /* The interface */
- /* Alternate-setting numbers and endpoints for each protocol
- * (7/1/{index=1,2,3}) that the device supports: */
+ /*
+ * Alternate-setting numbers and endpoints for each protocol
+ * (USB_CLASS_PRINTER/1/{index=1,2,3}) that the device supports:
+ */
struct {
int alt_setting;
struct usb_endpoint_descriptor *epwrite;
@@ -1206,19 +1217,23 @@
* but our requirements are too intricate for simple match to handle.
*
* The "proto_bias" option may be used to specify the preferred protocol
- * for all USB printers (1=7/1/1, 2=7/1/2, 3=7/1/3). If the device
- * supports the preferred protocol, then we bind to it.
+ * for all USB printers (1=USB_CLASS_PRINTER/1/1, 2=USB_CLASS_PRINTER/1/2,
+ * 3=USB_CLASS_PRINTER/1/3). If the device supports the preferred protocol,
+ * then we bind to it.
*
- * The best interface for us is 7/1/2, because it is compatible
- * with a stream of characters. If we find it, we bind to it.
+ * The best interface for us is USB_CLASS_PRINTER/1/2, because it
+ * is compatible with a stream of characters. If we find it, we bind to it.
*
* Note that the people from hpoj.sourceforge.net need to be able to
- * bind to 7/1/3 (MLC/1284.4), so we provide them ioctls for this purpose.
+ * bind to USB_CLASS_PRINTER/1/3 (MLC/1284.4), so we provide them ioctls
+ * for this purpose.
*
- * Failing 7/1/2, we look for 7/1/3, even though it's probably not
- * stream-compatible, because this matches the behaviour of the old code.
+ * Failing USB_CLASS_PRINTER/1/2, we look for USB_CLASS_PRINTER/1/3,
+ * even though it's probably not stream-compatible, because this matches
+ * the behaviour of the old code.
*
- * If nothing else, we bind to 7/1/1 - the unidirectional interface.
+ * If nothing else, we bind to USB_CLASS_PRINTER/1/1
+ * - the unidirectional interface.
*/
static int usblp_select_alts(struct usblp *usblp)
{
@@ -1236,7 +1251,8 @@
for (i = 0; i < if_alt->num_altsetting; i++) {
ifd = &if_alt->altsetting[i];
- if (ifd->desc.bInterfaceClass != 7 || ifd->desc.bInterfaceSubClass != 1)
+ if (ifd->desc.bInterfaceClass != USB_CLASS_PRINTER ||
+ ifd->desc.bInterfaceSubClass != 1)
if (!(usblp->quirks & USBLP_QUIRK_BAD_CLASS))
continue;
@@ -1262,8 +1278,10 @@
if (!epwrite || (ifd->desc.bInterfaceProtocol > 1 && !epread))
continue;
- /* Turn off reads for 7/1/1 (unidirectional) interfaces
- * and buggy bidirectional printers. */
+ /*
+ * Turn off reads for USB_CLASS_PRINTER/1/1 (unidirectional)
+ * interfaces and buggy bidirectional printers.
+ */
if (ifd->desc.bInterfaceProtocol == 1) {
epread = NULL;
} else if (usblp->quirks & USBLP_QUIRK_BIDIR) {
@@ -1406,12 +1424,12 @@
}
static const struct usb_device_id usblp_ids[] = {
- { USB_DEVICE_INFO(7, 1, 1) },
- { USB_DEVICE_INFO(7, 1, 2) },
- { USB_DEVICE_INFO(7, 1, 3) },
- { USB_INTERFACE_INFO(7, 1, 1) },
- { USB_INTERFACE_INFO(7, 1, 2) },
- { USB_INTERFACE_INFO(7, 1, 3) },
+ { USB_DEVICE_INFO(USB_CLASS_PRINTER, 1, 1) },
+ { USB_DEVICE_INFO(USB_CLASS_PRINTER, 1, 2) },
+ { USB_DEVICE_INFO(USB_CLASS_PRINTER, 1, 3) },
+ { USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 1) },
+ { USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 2) },
+ { USB_INTERFACE_INFO(USB_CLASS_PRINTER, 1, 3) },
{ USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */
{ } /* Terminating entry */
};
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index b530fd4..9e39286 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -154,6 +154,62 @@
return false;
}
EXPORT_SYMBOL_GPL(of_usb_host_tpl_support);
+
+/**
+ * of_usb_update_otg_caps - to update usb otg capabilities according to
+ * the passed properties in DT.
+ * @np: Pointer to the given device_node
+ * @otg_caps: Pointer to the target usb_otg_caps to be set
+ *
+ * The function updates the otg capabilities
+ */
+int of_usb_update_otg_caps(struct device_node *np,
+ struct usb_otg_caps *otg_caps)
+{
+ u32 otg_rev;
+
+ if (!otg_caps)
+ return -EINVAL;
+
+ if (!of_property_read_u32(np, "otg-rev", &otg_rev)) {
+ switch (otg_rev) {
+ case 0x0100:
+ case 0x0120:
+ case 0x0130:
+ case 0x0200:
+ /* Choose the lesser one if it's already been set */
+ if (otg_caps->otg_rev)
+ otg_caps->otg_rev = min_t(u16, otg_rev,
+ otg_caps->otg_rev);
+ else
+ otg_caps->otg_rev = otg_rev;
+ break;
+ default:
+ pr_err("%s: unsupported otg-rev: 0x%x\n",
+ np->full_name, otg_rev);
+ return -EINVAL;
+ }
+ } else {
+ /*
+ * otg-rev is mandatory for otg properties, if not passed
+ * we set it to be 0 and assume it's a legacy otg device.
+ * Non-dt platform can set it afterwards.
+ */
+ otg_caps->otg_rev = 0;
+ }
+
+ if (of_find_property(np, "hnp-disable", NULL))
+ otg_caps->hnp_support = false;
+ if (of_find_property(np, "srp-disable", NULL))
+ otg_caps->srp_support = false;
+ if (of_find_property(np, "adp-disable", NULL) ||
+ (otg_caps->otg_rev < 0x0200))
+ otg_caps->adp_support = false;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_usb_update_otg_caps);
+
#endif
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
index 0e6f968..01c0c04 100644
--- a/drivers/usb/common/ulpi.c
+++ b/drivers/usb/common/ulpi.c
@@ -242,7 +242,7 @@
{
return bus_register(&ulpi_bus);
}
-module_init(ulpi_init);
+subsys_initcall(ulpi_init);
static void __exit ulpi_exit(void)
{
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 986abde..38ae877c 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -103,7 +103,7 @@
#define snoop(dev, format, arg...) \
do { \
if (usbfs_snoop) \
- dev_info(dev , format , ## arg); \
+ dev_info(dev, format, ## arg); \
} while (0)
enum snoop_when {
@@ -1082,7 +1082,8 @@
ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
if (ret)
return ret;
- if (!(tbuf = kmalloc(len1, GFP_KERNEL))) {
+ tbuf = kmalloc(len1, GFP_KERNEL);
+ if (!tbuf) {
ret = -ENOMEM;
goto done;
}
@@ -1224,7 +1225,8 @@
if (copy_from_user(&setintf, arg, sizeof(setintf)))
return -EFAULT;
- if ((ret = checkintf(ps, setintf.interface)))
+ ret = checkintf(ps, setintf.interface);
+ if (ret)
return ret;
destroy_async_on_interface(ps, setintf.interface);
@@ -1319,7 +1321,7 @@
is_in = (uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0;
u = 0;
- switch(uurb->type) {
+ switch (uurb->type) {
case USBDEVFS_URB_TYPE_CONTROL:
if (!usb_endpoint_xfer_control(&ep->desc))
return -EINVAL;
@@ -1393,7 +1395,8 @@
number_of_packets = uurb->number_of_packets;
isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) *
number_of_packets;
- if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
+ isopkt = kmalloc(isofrmlen, GFP_KERNEL);
+ if (!isopkt)
return -ENOMEM;
if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
ret = -EFAULT;
@@ -1904,7 +1907,8 @@
if (get_user(ifnum, (unsigned int __user *)arg))
return -EFAULT;
- if ((ret = releaseintf(ps, ifnum)) < 0)
+ ret = releaseintf(ps, ifnum);
+ if (ret < 0)
return ret;
destroy_async_on_interface (ps, ifnum);
return 0;
@@ -1919,7 +1923,8 @@
struct usb_driver *driver = NULL;
/* alloc buffer */
- if ((size = _IOC_SIZE(ctl->ioctl_code)) > 0) {
+ size = _IOC_SIZE(ctl->ioctl_code);
+ if (size > 0) {
buf = kmalloc(size, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 818369a..6b5063e 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -160,6 +160,7 @@
spin_lock(&usb_driver->dynids.lock);
list_for_each_entry_safe(dynid, n, &usb_driver->dynids.list, node) {
struct usb_device_id *id = &dynid->id;
+
if ((id->idVendor == idVendor) &&
(id->idProduct == idProduct)) {
list_del(&dynid->node);
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 39a2402..101983b 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -51,7 +51,7 @@
{
struct ep_device *ep = to_ep_device(dev);
return sprintf(buf, "%04x\n",
- usb_endpoint_maxp(ep->desc) & 0x07ff);
+ usb_endpoint_maxp(ep->desc) & 0x07ff);
}
static DEVICE_ATTR_RO(wMaxPacketSize);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index be5b207..4d64e5c4 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1022,9 +1022,12 @@
dev_name(&usb_dev->dev), retval);
return (retval < 0) ? retval : -EMSGSIZE;
}
- if (usb_dev->speed == USB_SPEED_SUPER) {
+
+ if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) {
retval = usb_get_bos_descriptor(usb_dev);
- if (retval < 0) {
+ if (!retval) {
+ usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev);
+ } else if (usb_dev->speed == USB_SPEED_SUPER) {
mutex_unlock(&usb_bus_list_lock);
dev_dbg(parent_dev, "can't read %s bos descriptor %d\n",
dev_name(&usb_dev->dev), retval);
@@ -2683,12 +2686,14 @@
* bottom up so that hcds can customize the root hubs before hub_wq
* starts talking to them. (Note, bus id is assigned early too.)
*/
- if ((retval = hcd_buffer_create(hcd)) != 0) {
+ retval = hcd_buffer_create(hcd);
+ if (retval != 0) {
dev_dbg(hcd->self.controller, "pool alloc failed\n");
goto err_create_buf;
}
- if ((retval = usb_register_bus(&hcd->self)) < 0)
+ retval = usb_register_bus(&hcd->self);
+ if (retval < 0)
goto err_register_bus;
rhdev = usb_alloc_dev(NULL, &hcd->self, 0);
@@ -2734,9 +2739,13 @@
/* "reset" is misnamed; its role is now one-time init. the controller
* should already have been reset (and boot firmware kicked off etc).
*/
- if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
- dev_err(hcd->self.controller, "can't setup: %d\n", retval);
- goto err_hcd_driver_setup;
+ if (hcd->driver->reset) {
+ retval = hcd->driver->reset(hcd);
+ if (retval < 0) {
+ dev_err(hcd->self.controller, "can't setup: %d\n",
+ retval);
+ goto err_hcd_driver_setup;
+ }
}
hcd->rh_pollable = 1;
@@ -2766,7 +2775,8 @@
}
/* starting here, usbcore will pay attention to this root hub */
- if ((retval = register_root_hub(hcd)) != 0)
+ retval = register_root_hub(hcd);
+ if (retval != 0)
goto err_register_root_hub;
retval = sysfs_create_group(&rhdev->dev.kobj, &usb_bus_attr_group);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 43cb2f2..431839b 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -50,8 +50,8 @@
/* cycle leds on hubs that aren't blinking for attention */
static bool blinkenlights = 0;
-module_param (blinkenlights, bool, S_IRUGO);
-MODULE_PARM_DESC (blinkenlights, "true to cycle leds on hubs");
+module_param(blinkenlights, bool, S_IRUGO);
+MODULE_PARM_DESC(blinkenlights, "true to cycle leds on hubs");
/*
* Device SATA8000 FW1.0 from DATAST0R Technology Corp requires about
@@ -122,7 +122,7 @@
return usb_get_intfdata(hdev->actconfig->interface[0]);
}
-static int usb_device_supports_lpm(struct usb_device *udev)
+int usb_device_supports_lpm(struct usb_device *udev)
{
/* USB 2.1 (and greater) devices indicate LPM support through
* their USB 2.0 Extended Capabilities BOS descriptor.
@@ -439,7 +439,7 @@
#define LED_CYCLE_PERIOD ((2*HZ)/3)
-static void led_work (struct work_struct *work)
+static void led_work(struct work_struct *work)
{
struct usb_hub *hub =
container_of(work, struct usb_hub, leds.work);
@@ -646,7 +646,7 @@
default: /* presumably an error */
/* Cause a hub reset after 10 consecutive errors */
- dev_dbg (hub->intfdev, "transfer --> %d\n", status);
+ dev_dbg(hub->intfdev, "transfer --> %d\n", status);
if ((++hub->nerrors < 10) || hub->error)
goto resubmit;
hub->error = status;
@@ -671,14 +671,14 @@
if (hub->quiescing)
return;
- if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
- && status != -ENODEV && status != -EPERM)
- dev_err (hub->intfdev, "resubmit --> %d\n", status);
+ status = usb_submit_urb(hub->urb, GFP_ATOMIC);
+ if (status != 0 && status != -ENODEV && status != -EPERM)
+ dev_err(hub->intfdev, "resubmit --> %d\n", status);
}
/* USB 2.0 spec Section 11.24.2.3 */
static inline int
-hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt)
+hub_clear_tt_buffer(struct usb_device *hdev, u16 devinfo, u16 tt)
{
/* Need to clear both directions for control ep */
if (((devinfo >> 11) & USB_ENDPOINT_XFERTYPE_MASK) ==
@@ -706,7 +706,7 @@
container_of(work, struct usb_hub, tt.clear_work);
unsigned long flags;
- spin_lock_irqsave (&hub->tt.lock, flags);
+ spin_lock_irqsave(&hub->tt.lock, flags);
while (!list_empty(&hub->tt.clear_list)) {
struct list_head *next;
struct usb_tt_clear *clear;
@@ -715,14 +715,14 @@
int status;
next = hub->tt.clear_list.next;
- clear = list_entry (next, struct usb_tt_clear, clear_list);
- list_del (&clear->clear_list);
+ clear = list_entry(next, struct usb_tt_clear, clear_list);
+ list_del(&clear->clear_list);
/* drop lock so HCD can concurrently report other TT errors */
- spin_unlock_irqrestore (&hub->tt.lock, flags);
- status = hub_clear_tt_buffer (hdev, clear->devinfo, clear->tt);
+ spin_unlock_irqrestore(&hub->tt.lock, flags);
+ status = hub_clear_tt_buffer(hdev, clear->devinfo, clear->tt);
if (status && status != -ENODEV)
- dev_err (&hdev->dev,
+ dev_err(&hdev->dev,
"clear tt %d (%04x) error %d\n",
clear->tt, clear->devinfo, status);
@@ -734,7 +734,7 @@
kfree(clear);
spin_lock_irqsave(&hub->tt.lock, flags);
}
- spin_unlock_irqrestore (&hub->tt.lock, flags);
+ spin_unlock_irqrestore(&hub->tt.lock, flags);
}
/**
@@ -797,7 +797,7 @@
*/
clear = kmalloc(sizeof *clear, GFP_ATOMIC);
if (clear == NULL) {
- dev_err (&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
+ dev_err(&udev->dev, "can't save CLEAR_TT_BUFFER state\n");
/* FIXME recover somehow ... RESET_TT? */
return -ENOMEM;
}
@@ -806,10 +806,10 @@
clear->tt = tt->multi ? udev->ttport : 1;
clear->devinfo = usb_pipeendpoint (pipe);
clear->devinfo |= udev->devnum << 4;
- clear->devinfo |= usb_pipecontrol (pipe)
+ clear->devinfo |= usb_pipecontrol(pipe)
? (USB_ENDPOINT_XFER_CONTROL << 11)
: (USB_ENDPOINT_XFER_BULK << 11);
- if (usb_pipein (pipe))
+ if (usb_pipein(pipe))
clear->devinfo |= 1 << 15;
/* info for completion callback */
@@ -817,10 +817,10 @@
clear->ep = urb->ep;
/* tell keventd to clear state for this TT */
- spin_lock_irqsave (&tt->lock, flags);
- list_add_tail (&clear->clear_list, &tt->clear_list);
+ spin_lock_irqsave(&tt->lock, flags);
+ list_add_tail(&clear->clear_list, &tt->clear_list);
schedule_work(&tt->clear_work);
- spin_unlock_irqrestore (&tt->lock, flags);
+ spin_unlock_irqrestore(&tt->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(usb_hub_clear_tt_buffer);
@@ -1442,8 +1442,8 @@
break;
}
- spin_lock_init (&hub->tt.lock);
- INIT_LIST_HEAD (&hub->tt.clear_list);
+ spin_lock_init(&hub->tt.lock);
+ INIT_LIST_HEAD(&hub->tt.clear_list);
INIT_WORK(&hub->tt.clear_work, hub_tt_work);
switch (hdev->descriptor.bDeviceProtocol) {
case USB_HUB_PR_FS:
@@ -1632,7 +1632,7 @@
return 0;
fail:
- dev_err (hub_dev, "config failed, %s (err %d)\n",
+ dev_err(hub_dev, "config failed, %s (err %d)\n",
message, ret);
/* hub_disconnect() frees urb and descriptor */
return ret;
@@ -1775,7 +1775,7 @@
if ((desc->desc.bInterfaceSubClass != 0) &&
(desc->desc.bInterfaceSubClass != 1)) {
descriptor_error:
- dev_err (&intf->dev, "bad descriptor, ignoring hub\n");
+ dev_err(&intf->dev, "bad descriptor, ignoring hub\n");
return -EIO;
}
@@ -1790,11 +1790,11 @@
goto descriptor_error;
/* We found a hub */
- dev_info (&intf->dev, "USB hub found\n");
+ dev_info(&intf->dev, "USB hub found\n");
hub = kzalloc(sizeof(*hub), GFP_KERNEL);
if (!hub) {
- dev_dbg (&intf->dev, "couldn't kmalloc hub struct\n");
+ dev_dbg(&intf->dev, "couldn't kmalloc hub struct\n");
return -ENOMEM;
}
@@ -1807,7 +1807,7 @@
usb_get_intf(intf);
usb_get_dev(hdev);
- usb_set_intfdata (intf, hub);
+ usb_set_intfdata(intf, hub);
intf->needs_remote_wakeup = 1;
pm_suspend_ignore_children(&intf->dev, true);
@@ -1820,14 +1820,14 @@
if (hub_configure(hub, endpoint) >= 0)
return 0;
- hub_disconnect (intf);
+ hub_disconnect(intf);
return -ENODEV;
}
static int
hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data)
{
- struct usb_device *hdev = interface_to_usbdev (intf);
+ struct usb_device *hdev = interface_to_usbdev(intf);
struct usb_hub *hub = usb_hub_to_struct_hub(hdev);
/* assert ifno == 0 (part of hub spec) */
@@ -2143,7 +2143,7 @@
* cleaning up all state associated with the current configuration
* so that the hardware is now fully quiesced.
*/
- dev_dbg (&udev->dev, "unregistering device\n");
+ dev_dbg(&udev->dev, "unregistering device\n");
usb_disable_device(udev, 0);
usb_hcd_synchronize_unlinks(udev);
@@ -2242,7 +2242,7 @@
struct usb_bus *bus = udev->bus;
/* descriptor may appear anywhere in config */
- if (__usb_get_extra_descriptor (udev->rawdescriptors[0],
+ if (__usb_get_extra_descriptor(udev->rawdescriptors[0],
le16_to_cpu(udev->config[0].desc.wTotalLength),
USB_DT_OTG, (void **) &desc) == 0) {
if (desc->bmAttributes & USB_OTG_HNP) {
@@ -3526,7 +3526,7 @@
static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
{
- struct usb_hub *hub = usb_get_intfdata (intf);
+ struct usb_hub *hub = usb_get_intfdata(intf);
struct usb_device *hdev = hub->hdev;
unsigned port1;
int status;
@@ -3950,6 +3950,8 @@
if (usb_disable_link_state(hcd, udev, USB3_LPM_U2))
goto enable_lpm;
+ udev->usb3_lpm_enabled = 0;
+
return 0;
enable_lpm:
@@ -4007,6 +4009,8 @@
usb_enable_link_state(hcd, udev, USB3_LPM_U1);
usb_enable_link_state(hcd, udev, USB3_LPM_U2);
+
+ udev->usb3_lpm_enabled = 1;
}
EXPORT_SYMBOL_GPL(usb_enable_lpm);
diff --git a/drivers/usb/core/otg_whitelist.h b/drivers/usb/core/otg_whitelist.h
index a6315ab..a95b0c9 100644
--- a/drivers/usb/core/otg_whitelist.h
+++ b/drivers/usb/core/otg_whitelist.h
@@ -16,7 +16,7 @@
* YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
*/
-static struct usb_device_id whitelist_table [] = {
+static struct usb_device_id whitelist_table[] = {
/* hubs are optional in OTG, but very handy ... */
{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index d269738..cfc68c1 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -531,6 +531,25 @@
}
static DEVICE_ATTR_RW(usb2_lpm_besl);
+static ssize_t usb3_hardware_lpm_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct usb_device *udev = to_usb_device(dev);
+ const char *p;
+
+ usb_lock_device(udev);
+
+ if (udev->usb3_lpm_enabled)
+ p = "enabled";
+ else
+ p = "disabled";
+
+ usb_unlock_device(udev);
+
+ return sprintf(buf, "%s\n", p);
+}
+static DEVICE_ATTR_RO(usb3_hardware_lpm);
+
static struct attribute *usb2_hardware_lpm_attr[] = {
&dev_attr_usb2_hardware_lpm.attr,
&dev_attr_usb2_lpm_l1_timeout.attr,
@@ -542,6 +561,15 @@
.attrs = usb2_hardware_lpm_attr,
};
+static struct attribute *usb3_hardware_lpm_attr[] = {
+ &dev_attr_usb3_hardware_lpm.attr,
+ NULL,
+};
+static struct attribute_group usb3_hardware_lpm_attr_group = {
+ .name = power_group_name,
+ .attrs = usb3_hardware_lpm_attr,
+};
+
static struct attribute *power_attrs[] = {
&dev_attr_autosuspend.attr,
&dev_attr_level.attr,
@@ -564,6 +592,9 @@
if (udev->usb2_hw_lpm_capable == 1)
rc = sysfs_merge_group(&dev->kobj,
&usb2_hardware_lpm_attr_group);
+ if (udev->lpm_capable == 1)
+ rc = sysfs_merge_group(&dev->kobj,
+ &usb3_hardware_lpm_attr_group);
}
return rc;
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 7eb1e26..457255a 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -65,6 +65,7 @@
extern void usb_hub_cleanup(void);
extern int usb_major_init(void);
extern void usb_major_cleanup(void);
+extern int usb_device_supports_lpm(struct usb_device *udev);
#ifdef CONFIG_PM
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 4d47b7c..3ee5b4c 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2880,7 +2880,7 @@
epctl = readl(hs->regs + epreg);
if (value) {
- epctl |= DXEPCTL_STALL + DXEPCTL_SNAK;
+ epctl |= DXEPCTL_STALL | DXEPCTL_SNAK;
if (epctl & DXEPCTL_EPENA)
epctl |= DXEPCTL_EPDIS;
} else {
@@ -3289,6 +3289,19 @@
usb_ep_set_maxpacket_limit(&hs_ep->ep, epnum ? 1024 : EP0_MPS_LIMIT);
hs_ep->ep.ops = &s3c_hsotg_ep_ops;
+ if (epnum == 0) {
+ hs_ep->ep.caps.type_control = true;
+ } else {
+ hs_ep->ep.caps.type_iso = true;
+ hs_ep->ep.caps.type_bulk = true;
+ hs_ep->ep.caps.type_int = true;
+ }
+
+ if (dir_in)
+ hs_ep->ep.caps.dir_in = true;
+ else
+ hs_ep->ep.caps.dir_out = true;
+
/*
* if we're using dma, we need to set the next-endpoint pointer
* to be something valid.
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index dede32e..5a42c45 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -104,11 +104,4 @@
Recent Qualcomm SoCs ship with one DesignWare Core USB3 IP inside,
say 'Y' or 'M' if you have one such device.
-comment "Debugging features"
-
-config USB_DWC3_DEBUG
- bool "Enable Debugging Messages"
- help
- Say Y here to enable debugging messages on DWC3 Driver.
-
endif
diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index c7076e3..acc951d 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -1,8 +1,6 @@
# define_trace.h needs to know how to find our header
CFLAGS_trace.o := -I$(src)
-ccflags-$(CONFIG_USB_DWC3_DEBUG) := -DDEBUG
-
obj-$(CONFIG_USB_DWC3) += dwc3.o
dwc3-y := core.o debug.o trace.o
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index ff5773c..064123e 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -455,8 +455,6 @@
reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
} else {
- dev_warn(dwc->dev, "HSPHY Interface not defined\n");
-
/* Relying on default value. */
if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
break;
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 7bd0a95..dd5cb55 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -145,7 +145,7 @@
exynos->susp_clk = devm_clk_get(dev, "usbdrd30_susp_clk");
if (IS_ERR(exynos->susp_clk)) {
- dev_dbg(dev, "no suspend clk specified\n");
+ dev_info(dev, "no suspend clk specified\n");
exynos->susp_clk = NULL;
}
clk_prepare_enable(exynos->susp_clk);
diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
index fe3b933..2be268d 100644
--- a/drivers/usb/dwc3/dwc3-keystone.c
+++ b/drivers/usb/dwc3/dwc3-keystone.c
@@ -115,7 +115,7 @@
error = clk_prepare_enable(kdwc->clk);
if (error < 0) {
- dev_dbg(kdwc->dev, "unable to enable usb clock, err %d\n",
+ dev_err(kdwc->dev, "unable to enable usb clock, error %d\n",
error);
return error;
}
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 6b486a3..a5a1b7c 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -128,8 +128,7 @@
u32 dma_status:1;
- struct extcon_specific_cable_nb extcon_vbus_dev;
- struct extcon_specific_cable_nb extcon_id_dev;
+ struct extcon_dev *edev;
struct notifier_block vbus_nb;
struct notifier_block id_nb;
@@ -225,12 +224,10 @@
switch (status) {
case OMAP_DWC3_ID_GROUND:
- dev_dbg(omap->dev, "ID GND\n");
-
if (omap->vbus_reg) {
ret = regulator_enable(omap->vbus_reg);
if (ret) {
- dev_dbg(omap->dev, "regulator enable failed\n");
+ dev_err(omap->dev, "regulator enable failed\n");
return;
}
}
@@ -245,8 +242,6 @@
break;
case OMAP_DWC3_VBUS_VALID:
- dev_dbg(omap->dev, "VBUS Connect\n");
-
val = dwc3_omap_read_utmi_ctrl(omap);
val &= ~USBOTGSS_UTMI_OTG_CTRL_SESSEND;
val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG
@@ -261,8 +256,6 @@
regulator_disable(omap->vbus_reg);
case OMAP_DWC3_VBUS_OFF:
- dev_dbg(omap->dev, "VBUS Disconnect\n");
-
val = dwc3_omap_read_utmi_ctrl(omap);
val &= ~(USBOTGSS_UTMI_OTG_CTRL_SESSVALID
| USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
@@ -273,7 +266,7 @@
break;
default:
- dev_dbg(omap->dev, "invalid state\n");
+ dev_WARN(omap->dev, "invalid state\n");
}
}
@@ -284,37 +277,8 @@
reg = dwc3_omap_read_irqmisc_status(omap);
- if (reg & USBOTGSS_IRQMISC_DMADISABLECLR) {
- dev_dbg(omap->dev, "DMA Disable was Cleared\n");
+ if (reg & USBOTGSS_IRQMISC_DMADISABLECLR)
omap->dma_status = false;
- }
-
- if (reg & USBOTGSS_IRQMISC_OEVT)
- dev_dbg(omap->dev, "OTG Event\n");
-
- if (reg & USBOTGSS_IRQMISC_DRVVBUS_RISE)
- dev_dbg(omap->dev, "DRVVBUS Rise\n");
-
- if (reg & USBOTGSS_IRQMISC_CHRGVBUS_RISE)
- dev_dbg(omap->dev, "CHRGVBUS Rise\n");
-
- if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_RISE)
- dev_dbg(omap->dev, "DISCHRGVBUS Rise\n");
-
- if (reg & USBOTGSS_IRQMISC_IDPULLUP_RISE)
- dev_dbg(omap->dev, "IDPULLUP Rise\n");
-
- if (reg & USBOTGSS_IRQMISC_DRVVBUS_FALL)
- dev_dbg(omap->dev, "DRVVBUS Fall\n");
-
- if (reg & USBOTGSS_IRQMISC_CHRGVBUS_FALL)
- dev_dbg(omap->dev, "CHRGVBUS Fall\n");
-
- if (reg & USBOTGSS_IRQMISC_DISCHRGVBUS_FALL)
- dev_dbg(omap->dev, "DISCHRGVBUS Fall\n");
-
- if (reg & USBOTGSS_IRQMISC_IDPULLUP_FALL)
- dev_dbg(omap->dev, "IDPULLUP Fall\n");
dwc3_omap_write_irqmisc_status(omap, reg);
@@ -434,7 +398,7 @@
reg &= ~USBOTGSS_UTMI_OTG_CTRL_SW_MODE;
break;
default:
- dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
+ dev_WARN(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
}
dwc3_omap_write_utmi_ctrl(omap, reg);
@@ -454,23 +418,23 @@
}
omap->vbus_nb.notifier_call = dwc3_omap_vbus_notifier;
- ret = extcon_register_interest(&omap->extcon_vbus_dev,
- edev->name, "USB",
- &omap->vbus_nb);
+ ret = extcon_register_notifier(edev, EXTCON_USB,
+ &omap->vbus_nb);
if (ret < 0)
dev_vdbg(omap->dev, "failed to register notifier for USB\n");
omap->id_nb.notifier_call = dwc3_omap_id_notifier;
- ret = extcon_register_interest(&omap->extcon_id_dev,
- edev->name, "USB-HOST",
- &omap->id_nb);
+ ret = extcon_register_notifier(edev, EXTCON_USB_HOST,
+ &omap->id_nb);
if (ret < 0)
dev_vdbg(omap->dev, "failed to register notifier for USB-HOST\n");
- if (extcon_get_cable_state(edev, "USB") == true)
+ if (extcon_get_cable_state_(edev, EXTCON_USB) == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
- if (extcon_get_cable_state(edev, "USB-HOST") == true)
+ if (extcon_get_cable_state_(edev, EXTCON_USB_HOST) == true)
dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+
+ omap->edev = edev;
}
return 0;
@@ -565,11 +529,8 @@
return 0;
err3:
- if (omap->extcon_vbus_dev.edev)
- extcon_unregister_interest(&omap->extcon_vbus_dev);
- if (omap->extcon_id_dev.edev)
- extcon_unregister_interest(&omap->extcon_id_dev);
-
+ extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
+ extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
err2:
dwc3_omap_disable_irqs(omap);
@@ -586,10 +547,8 @@
{
struct dwc3_omap *omap = platform_get_drvdata(pdev);
- if (omap->extcon_vbus_dev.edev)
- extcon_unregister_interest(&omap->extcon_vbus_dev);
- if (omap->extcon_id_dev.edev)
- extcon_unregister_interest(&omap->extcon_id_dev);
+ extcon_unregister_notifier(omap->edev, EXTCON_USB, &omap->vbus_nb);
+ extcon_unregister_notifier(omap->edev, EXTCON_USB_HOST, &omap->id_nb);
dwc3_omap_disable_irqs(omap);
of_platform_depopulate(omap->dev);
pm_runtime_put_sync(&pdev->dev);
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c
index 27e4fc8..f626179 100644
--- a/drivers/usb/dwc3/dwc3-pci.c
+++ b/drivers/usb/dwc3/dwc3-pci.c
@@ -83,17 +83,23 @@
acpi_dev_add_driver_gpios(ACPI_COMPANION(&pdev->dev),
acpi_dwc3_byt_gpios);
- /* These GPIOs will turn on the USB2 PHY */
- gpio = gpiod_get(&pdev->dev, "cs");
- if (!IS_ERR(gpio)) {
- gpiod_direction_output(gpio, 0);
- gpiod_set_value_cansleep(gpio, 1);
- gpiod_put(gpio);
- }
+ /*
+ * These GPIOs will turn on the USB2 PHY. Note that we have to
+ * put the gpio descriptors again here because the phy driver
+ * might want to grab them, too.
+ */
+ gpio = gpiod_get_optional(&pdev->dev, "cs", GPIOD_OUT_LOW);
+ if (IS_ERR(gpio))
+ return PTR_ERR(gpio);
- gpio = gpiod_get(&pdev->dev, "reset");
- if (!IS_ERR(gpio)) {
- gpiod_direction_output(gpio, 0);
+ gpiod_set_value_cansleep(gpio, 1);
+ gpiod_put(gpio);
+
+ gpio = gpiod_get_optional(&pdev->dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(gpio))
+ return PTR_ERR(gpio);
+
+ if (gpio) {
gpiod_set_value_cansleep(gpio, 1);
gpiod_put(gpio);
usleep_range(10000, 11000);
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index 8c2e8ee..0880260 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -48,13 +48,13 @@
qdwc->iface_clk = devm_clk_get(qdwc->dev, "iface");
if (IS_ERR(qdwc->iface_clk)) {
- dev_dbg(qdwc->dev, "failed to get optional iface clock\n");
+ dev_info(qdwc->dev, "failed to get optional iface clock\n");
qdwc->iface_clk = NULL;
}
qdwc->sleep_clk = devm_clk_get(qdwc->dev, "sleep");
if (IS_ERR(qdwc->sleep_clk)) {
- dev_dbg(qdwc->dev, "failed to get optional sleep clock\n");
+ dev_info(qdwc->dev, "failed to get optional sleep clock\n");
qdwc->sleep_clk = NULL;
}
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index 4a1a543..de4d52f 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -135,8 +135,6 @@
| USB3_SEL_FORCE_DMPULLDOWN2 | USB3_FORCE_DMPULLDOWN2);
val |= USB3_DEVICE_NOT_HOST;
-
- dev_dbg(dwc3_data->dev, "Configuring as Device\n");
break;
case USB_DR_MODE_HOST:
@@ -154,8 +152,6 @@
*/
val |= USB3_DELAY_VBUSVALID;
-
- dev_dbg(dwc3_data->dev, "Configuring as Host\n");
break;
default:
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 2ef3c8d..5320e93 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -56,7 +56,7 @@
}
static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
- u32 len, u32 type)
+ u32 len, u32 type, bool chain)
{
struct dwc3_gadget_ep_cmd_params params;
struct dwc3_trb *trb;
@@ -70,7 +70,10 @@
return 0;
}
- trb = dwc->ep0_trb;
+ trb = &dwc->ep0_trb[dep->free_slot];
+
+ if (chain)
+ dep->free_slot++;
trb->bpl = lower_32_bits(buf_dma);
trb->bph = upper_32_bits(buf_dma);
@@ -78,10 +81,17 @@
trb->ctrl = type;
trb->ctrl |= (DWC3_TRB_CTRL_HWO
- | DWC3_TRB_CTRL_LST
- | DWC3_TRB_CTRL_IOC
| DWC3_TRB_CTRL_ISP_IMI);
+ if (chain)
+ trb->ctrl |= DWC3_TRB_CTRL_CHN;
+ else
+ trb->ctrl |= (DWC3_TRB_CTRL_IOC
+ | DWC3_TRB_CTRL_LST);
+
+ if (chain)
+ return 0;
+
memset(¶ms, 0, sizeof(params));
params.param0 = upper_32_bits(dwc->ep0_trb_addr);
params.param1 = lower_32_bits(dwc->ep0_trb_addr);
@@ -302,7 +312,7 @@
int ret;
ret = dwc3_ep0_start_trans(dwc, 0, dwc->ctrl_req_addr, 8,
- DWC3_TRBCTL_CONTROL_SETUP);
+ DWC3_TRBCTL_CONTROL_SETUP, false);
WARN_ON(ret < 0);
}
@@ -727,6 +737,10 @@
dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_ISOCH_DELAY");
ret = dwc3_ep0_set_isoch_delay(dwc, ctrl);
break;
+ case USB_REQ_SET_INTERFACE:
+ dwc3_trace(trace_dwc3_ep0, "USB_REQ_SET_INTERFACE");
+ dwc->start_config_issued = false;
+ /* Fall through */
default:
dwc3_trace(trace_dwc3_ep0, "Forwarding to gadget driver");
ret = dwc3_ep0_delegate_req(dwc, ctrl);
@@ -779,7 +793,11 @@
struct usb_request *ur;
struct dwc3_trb *trb;
struct dwc3_ep *ep0;
- u32 transferred;
+ unsigned transfer_size = 0;
+ unsigned maxp;
+ unsigned remaining_ur_length;
+ void *buf;
+ u32 transferred = 0;
u32 status;
u32 length;
u8 epnum;
@@ -808,17 +826,37 @@
}
ur = &r->request;
+ buf = ur->buf;
+ remaining_ur_length = ur->length;
length = trb->size & DWC3_TRB_SIZE_MASK;
- if (dwc->ep0_bounced) {
- unsigned transfer_size = ur->length;
- unsigned maxp = ep0->endpoint.maxpacket;
+ maxp = ep0->endpoint.maxpacket;
- transfer_size += (maxp - (transfer_size % maxp));
- transferred = min_t(u32, ur->length,
- transfer_size - length);
- memcpy(ur->buf, dwc->ep0_bounce, transferred);
+ if (dwc->ep0_bounced) {
+ /*
+ * Handle the first TRB before handling the bounce buffer if
+ * the request length is greater than the bounce buffer size
+ */
+ if (ur->length > DWC3_EP0_BOUNCE_SIZE) {
+ transfer_size = ALIGN(ur->length - maxp, maxp);
+ transferred = transfer_size - length;
+ buf = (u8 *)buf + transferred;
+ ur->actual += transferred;
+ remaining_ur_length -= transferred;
+
+ trb++;
+ length = trb->size & DWC3_TRB_SIZE_MASK;
+
+ ep0->free_slot = 0;
+ }
+
+ transfer_size = roundup((ur->length - transfer_size),
+ maxp);
+
+ transferred = min_t(u32, remaining_ur_length,
+ transfer_size - length);
+ memcpy(buf, dwc->ep0_bounce, transferred);
} else {
transferred = ur->length - length;
}
@@ -840,7 +878,7 @@
ret = dwc3_ep0_start_trans(dwc, epnum,
dwc->ctrl_req_addr, 0,
- DWC3_TRBCTL_CONTROL_DATA);
+ DWC3_TRBCTL_CONTROL_DATA, false);
WARN_ON(ret < 0);
}
}
@@ -924,10 +962,10 @@
if (req->request.length == 0) {
ret = dwc3_ep0_start_trans(dwc, dep->number,
dwc->ctrl_req_addr, 0,
- DWC3_TRBCTL_CONTROL_DATA);
+ DWC3_TRBCTL_CONTROL_DATA, false);
} else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
&& (dep->number == 0)) {
- u32 transfer_size;
+ u32 transfer_size = 0;
u32 maxpacket;
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
@@ -937,21 +975,26 @@
return;
}
- WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE);
-
maxpacket = dep->endpoint.maxpacket;
- transfer_size = roundup(req->request.length, maxpacket);
+
+ if (req->request.length > DWC3_EP0_BOUNCE_SIZE) {
+ transfer_size = ALIGN(req->request.length - maxpacket,
+ maxpacket);
+ ret = dwc3_ep0_start_trans(dwc, dep->number,
+ req->request.dma,
+ transfer_size,
+ DWC3_TRBCTL_CONTROL_DATA,
+ true);
+ }
+
+ transfer_size = roundup((req->request.length - transfer_size),
+ maxpacket);
dwc->ep0_bounced = true;
- /*
- * REVISIT in case request length is bigger than
- * DWC3_EP0_BOUNCE_SIZE we will need two chained
- * TRBs to handle the transfer.
- */
ret = dwc3_ep0_start_trans(dwc, dep->number,
dwc->ep0_bounce_addr, transfer_size,
- DWC3_TRBCTL_CONTROL_DATA);
+ DWC3_TRBCTL_CONTROL_DATA, false);
} else {
ret = usb_gadget_map_request(&dwc->gadget, &req->request,
dep->number);
@@ -961,7 +1004,8 @@
}
ret = dwc3_ep0_start_trans(dwc, dep->number, req->request.dma,
- req->request.length, DWC3_TRBCTL_CONTROL_DATA);
+ req->request.length, DWC3_TRBCTL_CONTROL_DATA,
+ false);
}
WARN_ON(ret < 0);
@@ -976,7 +1020,7 @@
: DWC3_TRBCTL_CONTROL_STATUS2;
return dwc3_ep0_start_trans(dwc, dep->number,
- dwc->ctrl_req_addr, 0, type);
+ dwc->ctrl_req_addr, 0, type, false);
}
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 333a7c0..0c25704 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -547,6 +547,23 @@
trb_link->ctrl |= DWC3_TRB_CTRL_HWO;
}
+ switch (usb_endpoint_type(desc)) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ strlcat(dep->name, "-control", sizeof(dep->name));
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ strlcat(dep->name, "-isoc", sizeof(dep->name));
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ strlcat(dep->name, "-bulk", sizeof(dep->name));
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ strlcat(dep->name, "-int", sizeof(dep->name));
+ break;
+ default:
+ dev_err(dwc->dev, "invalid endpoint transfer type\n");
+ }
+
return 0;
}
@@ -586,6 +603,8 @@
struct dwc3 *dwc = dep->dwc;
u32 reg;
+ dwc3_trace(trace_dwc3_gadget, "Disabling %s", dep->name);
+
dwc3_remove_requests(dwc, dep);
/* make sure HW endpoint isn't stalled */
@@ -602,6 +621,10 @@
dep->type = 0;
dep->flags = 0;
+ snprintf(dep->name, sizeof(dep->name), "ep%d%s",
+ dep->number >> 1,
+ (dep->number & 1) ? "in" : "out");
+
return 0;
}
@@ -647,23 +670,6 @@
return 0;
}
- switch (usb_endpoint_type(desc)) {
- case USB_ENDPOINT_XFER_CONTROL:
- strlcat(dep->name, "-control", sizeof(dep->name));
- break;
- case USB_ENDPOINT_XFER_ISOC:
- strlcat(dep->name, "-isoc", sizeof(dep->name));
- break;
- case USB_ENDPOINT_XFER_BULK:
- strlcat(dep->name, "-bulk", sizeof(dep->name));
- break;
- case USB_ENDPOINT_XFER_INT:
- strlcat(dep->name, "-int", sizeof(dep->name));
- break;
- default:
- dev_err(dwc->dev, "invalid endpoint transfer type\n");
- }
-
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false, false);
spin_unlock_irqrestore(&dwc->lock, flags);
@@ -692,10 +698,6 @@
return 0;
}
- snprintf(dep->name, sizeof(dep->name), "ep%d%s",
- dep->number >> 1,
- (dep->number & 1) ? "in" : "out");
-
spin_lock_irqsave(&dwc->lock, flags);
ret = __dwc3_gadget_ep_disable(dep);
spin_unlock_irqrestore(&dwc->lock, flags);
@@ -1713,6 +1715,17 @@
return ret;
}
+ if (epnum == 0 || epnum == 1) {
+ dep->endpoint.caps.type_control = true;
+ } else {
+ dep->endpoint.caps.type_iso = true;
+ dep->endpoint.caps.type_bulk = true;
+ dep->endpoint.caps.type_int = true;
+ }
+
+ dep->endpoint.caps.dir_in = !!direction;
+ dep->endpoint.caps.dir_out = !direction;
+
INIT_LIST_HEAD(&dep->request_list);
INIT_LIST_HEAD(&dep->req_queued);
}
@@ -2685,7 +2698,7 @@
goto err0;
}
- dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb),
+ dwc->ep0_trb = dma_alloc_coherent(dwc->dev, sizeof(*dwc->ep0_trb) * 2,
&dwc->ep0_trb_addr, GFP_KERNEL);
if (!dwc->ep0_trb) {
dev_err(dwc->dev, "failed to allocate ep0 trb\n");
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 58b4657..b474499 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -19,6 +19,7 @@
#include <linux/utsname.h>
#include <linux/usb/composite.h>
+#include <linux/usb/otg.h>
#include <asm/unaligned.h>
#include "u_os_desc.h"
@@ -209,6 +210,12 @@
function->config = config;
list_add_tail(&function->list, &config->functions);
+ if (function->bind_deactivated) {
+ value = usb_function_deactivate(function);
+ if (value)
+ goto done;
+ }
+
/* REVISIT *require* function->bind? */
if (function->bind) {
value = function->bind(config, function);
@@ -279,7 +286,7 @@
spin_lock_irqsave(&cdev->lock, flags);
if (cdev->deactivations == 0)
- status = usb_gadget_disconnect(cdev->gadget);
+ status = usb_gadget_deactivate(cdev->gadget);
if (status == 0)
cdev->deactivations++;
@@ -311,7 +318,7 @@
else {
cdev->deactivations--;
if (cdev->deactivations == 0)
- status = usb_gadget_connect(cdev->gadget);
+ status = usb_gadget_activate(cdev->gadget);
}
spin_unlock_irqrestore(&cdev->lock, flags);
@@ -896,7 +903,7 @@
/* We support strings in multiple languages ... string descriptor zero
* says which languages are supported. The typical case will be that
- * only one language (probably English) is used, with I18N handled on
+ * only one language (probably English) is used, with i18n handled on
* the host side.
*/
@@ -949,7 +956,7 @@
struct usb_function *f;
int len;
- /* Yes, not only is USB's I18N support probably more than most
+ /* Yes, not only is USB's i18n support probably more than most
* folk will ever care about ... also, it's all supported here.
* (Except for UTF8 support for Unicode's "Astral Planes".)
*/
@@ -1534,6 +1541,32 @@
value = min(w_length, (u16) value);
}
break;
+ case USB_DT_OTG:
+ if (gadget_is_otg(gadget)) {
+ struct usb_configuration *config;
+ int otg_desc_len = 0;
+
+ if (cdev->config)
+ config = cdev->config;
+ else
+ config = list_first_entry(
+ &cdev->configs,
+ struct usb_configuration, list);
+ if (!config)
+ goto done;
+
+ if (gadget->otg_caps &&
+ (gadget->otg_caps->otg_rev >= 0x0200))
+ otg_desc_len += sizeof(
+ struct usb_otg20_descriptor);
+ else
+ otg_desc_len += sizeof(
+ struct usb_otg_descriptor);
+
+ value = min_t(int, w_length, otg_desc_len);
+ memcpy(req->buf, config->descriptors[0], value);
+ }
+ break;
}
break;
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index 34e12fc..0fafa7a 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -20,6 +20,7 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
+#include <linux/usb/otg.h>
/**
* usb_descriptor_fillbuf - fill buffer with descriptors
@@ -195,3 +196,58 @@
usb_free_descriptors(f->ss_descriptors);
}
EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
+
+struct usb_descriptor_header *usb_otg_descriptor_alloc(
+ struct usb_gadget *gadget)
+{
+ struct usb_descriptor_header *otg_desc;
+ unsigned length = 0;
+
+ if (gadget->otg_caps && (gadget->otg_caps->otg_rev >= 0x0200))
+ length = sizeof(struct usb_otg20_descriptor);
+ else
+ length = sizeof(struct usb_otg_descriptor);
+
+ otg_desc = kzalloc(length, GFP_KERNEL);
+ return otg_desc;
+}
+EXPORT_SYMBOL_GPL(usb_otg_descriptor_alloc);
+
+int usb_otg_descriptor_init(struct usb_gadget *gadget,
+ struct usb_descriptor_header *otg_desc)
+{
+ struct usb_otg_descriptor *otg1x_desc;
+ struct usb_otg20_descriptor *otg20_desc;
+ struct usb_otg_caps *otg_caps = gadget->otg_caps;
+ u8 otg_attributes = 0;
+
+ if (!otg_desc)
+ return -EINVAL;
+
+ if (otg_caps && otg_caps->otg_rev) {
+ if (otg_caps->hnp_support)
+ otg_attributes |= USB_OTG_HNP;
+ if (otg_caps->srp_support)
+ otg_attributes |= USB_OTG_SRP;
+ if (otg_caps->adp_support && (otg_caps->otg_rev >= 0x0200))
+ otg_attributes |= USB_OTG_ADP;
+ } else {
+ otg_attributes = USB_OTG_SRP | USB_OTG_HNP;
+ }
+
+ if (otg_caps && (otg_caps->otg_rev >= 0x0200)) {
+ otg20_desc = (struct usb_otg20_descriptor *)otg_desc;
+ otg20_desc->bLength = sizeof(struct usb_otg20_descriptor);
+ otg20_desc->bDescriptorType = USB_DT_OTG;
+ otg20_desc->bmAttributes = otg_attributes;
+ otg20_desc->bcdOTG = cpu_to_le16(otg_caps->otg_rev);
+ } else {
+ otg1x_desc = (struct usb_otg_descriptor *)otg_desc;
+ otg1x_desc->bLength = sizeof(struct usb_otg_descriptor);
+ otg1x_desc->bDescriptorType = USB_DT_OTG;
+ otg1x_desc->bmAttributes = otg_attributes;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(usb_otg_descriptor_init);
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index 289e201..294eb74 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -41,6 +41,8 @@
#define MAX_NAME_LEN 40
#define MAX_USB_STRING_LANGS 2
+static const struct usb_descriptor_header *otg_desc[2];
+
struct gadget_info {
struct config_group group;
struct config_group functions_group;
@@ -55,9 +57,6 @@
struct list_head available_func;
const char *udc_name;
-#ifdef CONFIG_USB_OTG
- struct usb_otg_descriptor otg;
-#endif
struct usb_composite_driver composite;
struct usb_composite_dev cdev;
bool use_os_desc;
@@ -1376,6 +1375,19 @@
memcpy(cdev->qw_sign, gi->qw_sign, OS_STRING_QW_SIGN_LEN);
}
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc) {
+ ret = -ENOMEM;
+ goto err_comp_cleanup;
+ }
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* Go through all configs, attach all functions */
list_for_each_entry(c, &gi->cdev.configs, list) {
struct config_usb_cfg *cfg;
@@ -1383,6 +1395,9 @@
struct usb_function *tmp;
struct gadget_config_name *cn;
+ if (gadget_is_otg(gadget))
+ c->descriptors = otg_desc;
+
cfg = container_of(c, struct config_usb_cfg, c);
if (!list_empty(&cfg->string_list)) {
i = 0;
@@ -1437,6 +1452,8 @@
cdev = get_gadget_data(gadget);
gi = container_of(cdev, struct gadget_info, cdev);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
purge_configs_funcs(gi);
composite_dev_cleanup(cdev);
usb_ep_autoconfig_reset(cdev->gadget);
@@ -1510,12 +1527,6 @@
if (!gi->composite.gadget_driver.function)
goto err;
-#ifdef CONFIG_USB_OTG
- gi->otg.bLength = sizeof(struct usb_otg_descriptor);
- gi->otg.bDescriptorType = USB_DT_OTG;
- gi->otg.bmAttributes = USB_OTG_SRP | USB_OTG_HNP;
-#endif
-
config_group_init_type_name(&gi->group, name,
&gadget_root_type);
return &gi->group;
diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c
index 919cdfd..978435a 100644
--- a/drivers/usb/gadget/epautoconf.c
+++ b/drivers/usb/gadget/epautoconf.c
@@ -20,186 +20,6 @@
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
-#include "gadget_chips.h"
-
-/*
- * This should work with endpoints from controller drivers sharing the
- * same endpoint naming convention. By example:
- *
- * - ep1, ep2, ... address is fixed, not direction or type
- * - ep1in, ep2out, ... address and direction are fixed, not type
- * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction
- * - ep1in-bulk, ep2out-iso, ... all three are fixed
- * - ep-* ... no functionality restrictions
- *
- * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal.
- * Less common restrictions are implied by gadget_is_*().
- *
- * NOTE: each endpoint is unidirectional, as specified by its USB
- * descriptor; and isn't specific to a configuration or altsetting.
- */
-static int
-ep_matches (
- struct usb_gadget *gadget,
- struct usb_ep *ep,
- struct usb_endpoint_descriptor *desc,
- struct usb_ss_ep_comp_descriptor *ep_comp
-)
-{
- u8 type;
- const char *tmp;
- u16 max;
-
- int num_req_streams = 0;
-
- /* endpoint already claimed? */
- if (NULL != ep->driver_data)
- return 0;
-
- /* only support ep0 for portable CONTROL traffic */
- type = usb_endpoint_type(desc);
- if (USB_ENDPOINT_XFER_CONTROL == type)
- return 0;
-
- /* some other naming convention */
- if ('e' != ep->name[0])
- return 0;
-
- /* type-restriction: "-iso", "-bulk", or "-int".
- * direction-restriction: "in", "out".
- */
- if ('-' != ep->name[2]) {
- tmp = strrchr (ep->name, '-');
- if (tmp) {
- switch (type) {
- case USB_ENDPOINT_XFER_INT:
- /* bulk endpoints handle interrupt transfers,
- * except the toggle-quirky iso-synch kind
- */
- if ('s' == tmp[2]) // == "-iso"
- return 0;
- /* for now, avoid PXA "interrupt-in";
- * it's documented as never using DATA1.
- */
- if (gadget_is_pxa (gadget)
- && 'i' == tmp [1])
- return 0;
- break;
- case USB_ENDPOINT_XFER_BULK:
- if ('b' != tmp[1]) // != "-bulk"
- return 0;
- break;
- case USB_ENDPOINT_XFER_ISOC:
- if ('s' != tmp[2]) // != "-iso"
- return 0;
- }
- } else {
- tmp = ep->name + strlen (ep->name);
- }
-
- /* direction-restriction: "..in-..", "out-.." */
- tmp--;
- if (!isdigit (*tmp)) {
- if (desc->bEndpointAddress & USB_DIR_IN) {
- if ('n' != *tmp)
- return 0;
- } else {
- if ('t' != *tmp)
- return 0;
- }
- }
- }
-
- /*
- * Get the number of required streams from the EP companion
- * descriptor and see if the EP matches it
- */
- if (usb_endpoint_xfer_bulk(desc)) {
- if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) {
- num_req_streams = ep_comp->bmAttributes & 0x1f;
- if (num_req_streams > ep->max_streams)
- return 0;
- }
-
- }
-
- /*
- * If the protocol driver hasn't yet decided on wMaxPacketSize
- * and wants to know the maximum possible, provide the info.
- */
- if (desc->wMaxPacketSize == 0)
- desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
-
- /* endpoint maxpacket size is an input parameter, except for bulk
- * where it's an output parameter representing the full speed limit.
- * the usb spec fixes high speed bulk maxpacket at 512 bytes.
- */
- max = 0x7ff & usb_endpoint_maxp(desc);
- switch (type) {
- case USB_ENDPOINT_XFER_INT:
- /* INT: limit 64 bytes full speed, 1024 high/super speed */
- if (!gadget_is_dualspeed(gadget) && max > 64)
- return 0;
- /* FALLTHROUGH */
-
- case USB_ENDPOINT_XFER_ISOC:
- /* ISO: limit 1023 bytes full speed, 1024 high/super speed */
- if (ep->maxpacket_limit < max)
- return 0;
- if (!gadget_is_dualspeed(gadget) && max > 1023)
- return 0;
-
- /* BOTH: "high bandwidth" works only at high speed */
- if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) {
- if (!gadget_is_dualspeed(gadget))
- return 0;
- /* configure your hardware with enough buffering!! */
- }
- break;
- }
-
- /* MATCH!! */
-
- /* report address */
- desc->bEndpointAddress &= USB_DIR_IN;
- if (isdigit (ep->name [2])) {
- u8 num = simple_strtoul (&ep->name [2], NULL, 10);
- desc->bEndpointAddress |= num;
- } else if (desc->bEndpointAddress & USB_DIR_IN) {
- if (++gadget->in_epnum > 15)
- return 0;
- desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
- } else {
- if (++gadget->out_epnum > 15)
- return 0;
- desc->bEndpointAddress |= gadget->out_epnum;
- }
-
- /* report (variable) full speed bulk maxpacket */
- if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) {
- int size = ep->maxpacket_limit;
-
- /* min() doesn't work on bitfields with gcc-3.5 */
- if (size > 64)
- size = 64;
- desc->wMaxPacketSize = cpu_to_le16(size);
- }
- ep->address = desc->bEndpointAddress;
- return 1;
-}
-
-static struct usb_ep *
-find_ep (struct usb_gadget *gadget, const char *name)
-{
- struct usb_ep *ep;
-
- list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- if (0 == strcmp (ep->name, name))
- return ep;
- }
- return NULL;
-}
-
/**
* usb_ep_autoconfig_ss() - choose an endpoint matching the ep
* descriptor and ep companion descriptor
@@ -240,7 +60,7 @@
* updated with the assigned number of streams if it is
* different from the original value. To prevent the endpoint
* from being returned by a later autoconfig call, claim it by
- * assigning ep->driver_data to some non-null value.
+ * assigning ep->claimed to true.
*
* On failure, this returns a null endpoint descriptor.
*/
@@ -255,74 +75,58 @@
type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
- /* First, apply chip-specific "best usage" knowledge.
- * This might make a good usb_gadget_ops hook ...
- */
- if (gadget_is_net2280(gadget)) {
- char name[8];
-
- if (type == USB_ENDPOINT_XFER_INT) {
- /* ep-e, ep-f are PIO with only 64 byte fifos */
- ep = find_ep(gadget, "ep-e");
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
- ep = find_ep(gadget, "ep-f");
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
- }
-
- /* USB3380: use same address for usb and hardware endpoints */
- snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
- usb_endpoint_dir_in(desc) ? "in" : "out");
- ep = find_ep(gadget, name);
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
+ if (gadget->ops->match_ep) {
+ ep = gadget->ops->match_ep(gadget, desc, ep_comp);
+ if (ep)
goto found_ep;
- } else if (gadget_is_goku (gadget)) {
- if (USB_ENDPOINT_XFER_INT == type) {
- /* single buffering is enough */
- ep = find_ep(gadget, "ep3-bulk");
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
- } else if (USB_ENDPOINT_XFER_BULK == type
- && (USB_DIR_IN & desc->bEndpointAddress)) {
- /* DMA may be available */
- ep = find_ep(gadget, "ep2-bulk");
- if (ep && ep_matches(gadget, ep, desc,
- ep_comp))
- goto found_ep;
- }
-
-#ifdef CONFIG_BLACKFIN
- } else if (gadget_is_musbhdrc(gadget)) {
- if ((USB_ENDPOINT_XFER_BULK == type) ||
- (USB_ENDPOINT_XFER_ISOC == type)) {
- if (USB_DIR_IN & desc->bEndpointAddress)
- ep = find_ep (gadget, "ep5in");
- else
- ep = find_ep (gadget, "ep6out");
- } else if (USB_ENDPOINT_XFER_INT == type) {
- if (USB_DIR_IN & desc->bEndpointAddress)
- ep = find_ep(gadget, "ep1in");
- else
- ep = find_ep(gadget, "ep2out");
- } else
- ep = NULL;
- if (ep && ep_matches(gadget, ep, desc, ep_comp))
- goto found_ep;
-#endif
}
/* Second, look at endpoints until an unclaimed one looks usable */
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- if (ep_matches(gadget, ep, desc, ep_comp))
+ if (usb_gadget_ep_match_desc(gadget, ep, desc, ep_comp))
goto found_ep;
}
/* Fail */
return NULL;
found_ep:
+
+ /*
+ * If the protocol driver hasn't yet decided on wMaxPacketSize
+ * and wants to know the maximum possible, provide the info.
+ */
+ if (desc->wMaxPacketSize == 0)
+ desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket_limit);
+
+ /* report address */
+ desc->bEndpointAddress &= USB_DIR_IN;
+ if (isdigit(ep->name[2])) {
+ u8 num = simple_strtoul(&ep->name[2], NULL, 10);
+ desc->bEndpointAddress |= num;
+ } else if (desc->bEndpointAddress & USB_DIR_IN) {
+ if (++gadget->in_epnum > 15)
+ return NULL;
+ desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum;
+ } else {
+ if (++gadget->out_epnum > 15)
+ return NULL;
+ desc->bEndpointAddress |= gadget->out_epnum;
+ }
+
+ /* report (variable) full speed bulk maxpacket */
+ if ((type == USB_ENDPOINT_XFER_BULK) && !ep_comp) {
+ int size = ep->maxpacket_limit;
+
+ /* min() doesn't work on bitfields with gcc-3.5 */
+ if (size > 64)
+ size = 64;
+ desc->wMaxPacketSize = cpu_to_le16(size);
+ }
+
+ ep->address = desc->bEndpointAddress;
ep->desc = NULL;
ep->comp_desc = NULL;
+ ep->claimed = true;
return ep;
}
EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss);
@@ -354,7 +158,7 @@
* descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value
* is initialized as if the endpoint were used at full speed. To prevent
* the endpoint from being returned by a later autoconfig call, claim it
- * by assigning ep->driver_data to some non-null value.
+ * by assigning ep->claimed to true.
*
* On failure, this returns a null endpoint descriptor.
*/
@@ -373,7 +177,7 @@
*
* Use this for devices where one configuration may need to assign
* endpoint resources very differently from the next one. It clears
- * state such as ep->driver_data and the record of assigned endpoints
+ * state such as ep->claimed and the record of assigned endpoints
* used by usb_ep_autoconfig().
*/
void usb_ep_autoconfig_reset (struct usb_gadget *gadget)
@@ -381,7 +185,7 @@
struct usb_ep *ep;
list_for_each_entry (ep, &gadget->ep_list, ep_list) {
- ep->driver_data = NULL;
+ ep->claimed = false;
}
gadget->in_epnum = 0;
gadget->out_epnum = 0;
diff --git a/drivers/usb/gadget/function/f_acm.c b/drivers/usb/gadget/function/f_acm.c
index aad8165..be9df09 100644
--- a/drivers/usb/gadget/function/f_acm.c
+++ b/drivers/usb/gadget/function/f_acm.c
@@ -21,7 +21,6 @@
#include <linux/err.h>
#include "u_serial.h"
-#include "gadget_chips.h"
/*
diff --git a/drivers/usb/gadget/function/f_ecm.c b/drivers/usb/gadget/function/f_ecm.c
index 798760f..7b7424f 100644
--- a/drivers/usb/gadget/function/f_ecm.c
+++ b/drivers/usb/gadget/function/f_ecm.c
@@ -585,8 +585,8 @@
/* Enable zlps by default for ECM conformance;
* override for musb_hdrc (avoids txdma ovhead).
*/
- ecm->port.is_zlp_ok = !(gadget_is_musbhdrc(cdev->gadget)
- );
+ ecm->port.is_zlp_ok =
+ gadget_is_zlp_supported(cdev->gadget);
ecm->port.cdc_filter = DEFAULT_FILTER;
DBG(cdev, "activate ecm\n");
net = gether_connect(&ecm->port);
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 6e7be91..adc6d52 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -2897,11 +2897,17 @@
struct usb_function *f)
{
struct f_fs_opts *ffs_opts = ffs_do_functionfs_bind(f, c);
+ struct ffs_function *func = ffs_func_from_usb(f);
+ int ret;
if (IS_ERR(ffs_opts))
return PTR_ERR(ffs_opts);
- return _ffs_func_bind(c, f);
+ ret = _ffs_func_bind(c, f);
+ if (ret && !--ffs_opts->refcnt)
+ functionfs_unbind(func->ffs);
+
+ return ret;
}
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index f7f35a3..6df9715 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -699,6 +699,10 @@
int ret;
ret = ida_simple_get(&hidg_ida, 0, 0, GFP_KERNEL);
+ if (ret >= HIDG_MINORS) {
+ ida_simple_remove(&hidg_ida, ret);
+ ret = -ENODEV;
+ }
return ret;
}
diff --git a/drivers/usb/gadget/function/f_loopback.c b/drivers/usb/gadget/function/f_loopback.c
index 39f49f1..6e2fe63 100644
--- a/drivers/usb/gadget/function/f_loopback.c
+++ b/drivers/usb/gadget/function/f_loopback.c
@@ -28,11 +28,6 @@
* This takes messages of various sizes written OUT to a device, and loops
* them back so they can be read IN from it. It has been used by certain
* test applications. It supports limited testing of data queueing logic.
- *
- *
- * This is currently packaged as a configuration driver, which can't be
- * combined with other functions to make composite devices. However, it
- * can be combined with other independent configurations.
*/
struct f_loopback {
struct usb_function function;
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index f936268..a6eb537 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -54,7 +54,7 @@
* following fields:
*
* nluns Number of LUNs function have (anywhere from 1
- * to FSG_MAX_LUNS which is 8).
+ * to FSG_MAX_LUNS).
* luns An array of LUN configuration values. This
* should be filled for each LUN that
* function will include (ie. for "nluns"
@@ -214,12 +214,12 @@
#include <linux/string.h>
#include <linux/freezer.h>
#include <linux/module.h>
+#include <linux/uaccess.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
-#include "gadget_chips.h"
#include "configfs.h"
@@ -279,9 +279,8 @@
int cmnd_size;
u8 cmnd[MAX_COMMAND_SIZE];
- unsigned int nluns;
unsigned int lun;
- struct fsg_lun **luns;
+ struct fsg_lun *luns[FSG_MAX_LUNS];
struct fsg_lun *curlun;
unsigned int bulk_out_maxpacket;
@@ -490,6 +489,16 @@
spin_unlock(&common->lock);
}
+static int _fsg_common_get_max_lun(struct fsg_common *common)
+{
+ int i = ARRAY_SIZE(common->luns) - 1;
+
+ while (i >= 0 && !common->luns[i])
+ --i;
+
+ return i;
+}
+
static int fsg_setup(struct usb_function *f,
const struct usb_ctrlrequest *ctrl)
{
@@ -533,7 +542,7 @@
w_length != 1)
return -EDOM;
VDBG(fsg, "get max LUN\n");
- *(u8 *)req->buf = fsg->common->nluns - 1;
+ *(u8 *)req->buf = _fsg_common_get_max_lun(fsg->common);
/* Respond with data/status */
req->length = min((u16)1, w_length);
@@ -2131,8 +2140,9 @@
}
/* Is the CBW meaningful? */
- if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN ||
- cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) {
+ if (cbw->Lun >= ARRAY_SIZE(common->luns) ||
+ cbw->Flags & ~US_BULK_FLAG_IN || cbw->Length <= 0 ||
+ cbw->Length > MAX_COMMAND_SIZE) {
DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, "
"cmdlen %u\n",
cbw->Lun, cbw->Flags, cbw->Length);
@@ -2159,7 +2169,7 @@
if (common->data_size == 0)
common->data_dir = DATA_DIR_NONE;
common->lun = cbw->Lun;
- if (common->lun < common->nluns)
+ if (common->lun < ARRAY_SIZE(common->luns))
common->curlun = common->luns[common->lun];
else
common->curlun = NULL;
@@ -2307,7 +2317,7 @@
}
common->running = 1;
- for (i = 0; i < common->nluns; ++i)
+ for (i = 0; i < ARRAY_SIZE(common->luns); ++i)
if (common->luns[i])
common->luns[i]->unit_attention_data =
SS_RESET_OCCURRED;
@@ -2409,7 +2419,7 @@
if (old_state == FSG_STATE_ABORT_BULK_OUT)
common->state = FSG_STATE_STATUS_PHASE;
else {
- for (i = 0; i < common->nluns; ++i) {
+ for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
curlun = common->luns[i];
if (!curlun)
continue;
@@ -2453,7 +2463,7 @@
* a waste of time. Ditto for the INTERFACE_CHANGE and
* CONFIG_CHANGE cases.
*/
- /* for (i = 0; i < common->nluns; ++i) */
+ /* for (i = 0; i < common->ARRAY_SIZE(common->luns); ++i) */
/* if (common->luns[i]) */
/* common->luns[i]->unit_attention_data = */
/* SS_RESET_OCCURRED; */
@@ -2552,12 +2562,11 @@
if (!common->ops || !common->ops->thread_exits
|| common->ops->thread_exits(common) < 0) {
- struct fsg_lun **curlun_it = common->luns;
- unsigned i = common->nluns;
+ int i;
down_write(&common->filesem);
- for (; i--; ++curlun_it) {
- struct fsg_lun *curlun = *curlun_it;
+ for (i = 0; i < ARRAY_SIZE(common->luns); --i) {
+ struct fsg_lun *curlun = common->luns[i];
if (!curlun || !fsg_lun_is_open(curlun))
continue;
@@ -2676,6 +2685,7 @@
init_completion(&common->thread_notifier);
init_waitqueue_head(&common->fsg_wait);
common->state = FSG_STATE_TERMINATED;
+ memset(common->luns, 0, sizeof(common->luns));
return common;
}
@@ -2742,9 +2752,9 @@
}
EXPORT_SYMBOL_GPL(fsg_common_set_num_buffers);
-void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs)
+void fsg_common_remove_lun(struct fsg_lun *lun)
{
- if (sysfs)
+ if (device_is_registered(&lun->dev))
device_unregister(&lun->dev);
fsg_lun_close(lun);
kfree(lun);
@@ -2757,48 +2767,16 @@
for (i = 0; i < n; ++i)
if (common->luns[i]) {
- fsg_common_remove_lun(common->luns[i], common->sysfs);
+ fsg_common_remove_lun(common->luns[i]);
common->luns[i] = NULL;
}
}
-EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
void fsg_common_remove_luns(struct fsg_common *common)
{
- _fsg_common_remove_luns(common, common->nluns);
+ _fsg_common_remove_luns(common, ARRAY_SIZE(common->luns));
}
-
-void fsg_common_free_luns(struct fsg_common *common)
-{
- fsg_common_remove_luns(common);
- kfree(common->luns);
- common->luns = NULL;
-}
-EXPORT_SYMBOL_GPL(fsg_common_free_luns);
-
-int fsg_common_set_nluns(struct fsg_common *common, int nluns)
-{
- struct fsg_lun **curlun;
-
- /* Find out how many LUNs there should be */
- if (nluns < 1 || nluns > FSG_MAX_LUNS) {
- pr_err("invalid number of LUNs: %u\n", nluns);
- return -EINVAL;
- }
-
- curlun = kcalloc(FSG_MAX_LUNS, sizeof(*curlun), GFP_KERNEL);
- if (unlikely(!curlun))
- return -ENOMEM;
-
- if (common->luns)
- fsg_common_free_luns(common);
-
- common->luns = curlun;
- common->nluns = nluns;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(fsg_common_set_nluns);
+EXPORT_SYMBOL_GPL(fsg_common_remove_luns);
void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops)
@@ -2836,7 +2814,8 @@
* halt bulk endpoints correctly. If one of them is present,
* disable stalls.
*/
- common->can_stall = can_stall && !(gadget_is_at91(common->gadget));
+ common->can_stall = can_stall &&
+ gadget_is_stall_supported(common->gadget);
return 0;
}
@@ -2880,7 +2859,7 @@
char *pathbuf, *p;
int rc = -ENOMEM;
- if (!common->nluns || !common->luns)
+ if (id >= ARRAY_SIZE(common->luns))
return -ENODEV;
if (common->luns[id])
@@ -2949,7 +2928,7 @@
return 0;
error_lun:
- if (common->sysfs)
+ if (device_is_registered(&lun->dev))
device_unregister(&lun->dev);
fsg_lun_close(lun);
common->luns[id] = NULL;
@@ -2964,14 +2943,16 @@
char buf[8]; /* enough for 100000000 different numbers, decimal */
int i, rc;
- for (i = 0; i < common->nluns; ++i) {
+ fsg_common_remove_luns(common);
+
+ for (i = 0; i < cfg->nluns; ++i) {
snprintf(buf, sizeof(buf), "lun%d", i);
rc = fsg_common_create_lun(common, &cfg->luns[i], i, buf, NULL);
if (rc)
goto fail;
}
- pr_info("Number of LUNs=%d\n", common->nluns);
+ pr_info("Number of LUNs=%d\n", cfg->nluns);
return 0;
@@ -3020,6 +3001,7 @@
static void fsg_common_release(struct kref *ref)
{
struct fsg_common *common = container_of(ref, struct fsg_common, ref);
+ int i;
/* If the thread isn't already dead, tell it to exit now */
if (common->state != FSG_STATE_TERMINATED) {
@@ -3027,22 +3009,14 @@
wait_for_completion(&common->thread_notifier);
}
- if (likely(common->luns)) {
- struct fsg_lun **lun_it = common->luns;
- unsigned i = common->nluns;
-
- /* In error recovery common->nluns may be zero. */
- for (; i; --i, ++lun_it) {
- struct fsg_lun *lun = *lun_it;
- if (!lun)
- continue;
- fsg_lun_close(lun);
- if (common->sysfs)
- device_unregister(&lun->dev);
- kfree(lun);
- }
-
- kfree(common->luns);
+ for (i = 0; i < ARRAY_SIZE(common->luns); ++i) {
+ struct fsg_lun *lun = common->luns[i];
+ if (!lun)
+ continue;
+ fsg_lun_close(lun);
+ if (device_is_registered(&lun->dev))
+ device_unregister(&lun->dev);
+ kfree(lun);
}
_fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers);
@@ -3056,6 +3030,7 @@
static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
{
struct fsg_dev *fsg = fsg_from_func(f);
+ struct fsg_common *common = fsg->common;
struct usb_gadget *gadget = c->cdev->gadget;
int i;
struct usb_ep *ep;
@@ -3063,6 +3038,13 @@
int ret;
struct fsg_opts *opts;
+ /* Don't allow to bind if we don't have at least one LUN */
+ ret = _fsg_common_get_max_lun(common);
+ if (ret < 0) {
+ pr_err("There should be at least one LUN.\n");
+ return -EINVAL;
+ }
+
opts = fsg_opts_from_func_inst(f->fi);
if (!opts->no_configfs) {
ret = fsg_common_set_cdev(fsg->common, c->cdev,
@@ -3080,7 +3062,7 @@
/* New interface */
i = usb_interface_id(c, f);
if (i < 0)
- return i;
+ goto fail;
fsg_intf_desc.bInterfaceNumber = i;
fsg->interface_number = i;
@@ -3123,7 +3105,14 @@
autoconf_fail:
ERROR(fsg, "unable to autoconfigure all endpoints\n");
- return -ENOTSUPP;
+ i = -ENOTSUPP;
+fail:
+ /* terminate the thread */
+ if (fsg->common->state != FSG_STATE_TERMINATED) {
+ raise_exception(fsg->common, FSG_STATE_EXIT);
+ wait_for_completion(&fsg->common->thread_notifier);
+ }
+ return i;
}
/****************************** ALLOCATE FUNCTION *************************/
@@ -3355,7 +3344,7 @@
unregister_gadget_item(gadget);
}
- fsg_common_remove_lun(lun_opts->lun, fsg_opts->common->sysfs);
+ fsg_common_remove_lun(lun_opts->lun);
fsg_opts->common->luns[lun_opts->lun_id] = NULL;
lun_opts->lun_id = 0;
mutex_unlock(&fsg_opts->lock);
@@ -3509,14 +3498,11 @@
rc = PTR_ERR(opts->common);
goto release_opts;
}
- rc = fsg_common_set_nluns(opts->common, FSG_MAX_LUNS);
- if (rc)
- goto release_opts;
rc = fsg_common_set_num_buffers(opts->common,
CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS);
if (rc)
- goto release_luns;
+ goto release_opts;
pr_info(FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n");
@@ -3524,6 +3510,9 @@
config.removable = true;
rc = fsg_common_create_lun(opts->common, &config, 0, "lun.0",
(const char **)&opts->func_inst.group.cg_item.ci_name);
+ if (rc)
+ goto release_buffers;
+
opts->lun0.lun = opts->common->luns[0];
opts->lun0.lun_id = 0;
config_group_init_type_name(&opts->lun0.group, "lun.0", &fsg_lun_type);
@@ -3534,8 +3523,8 @@
return &opts->func_inst;
-release_luns:
- kfree(opts->common->luns);
+release_buffers:
+ fsg_common_free_buffers(opts->common);
release_opts:
kfree(opts);
return ERR_PTR(rc);
@@ -3561,23 +3550,12 @@
struct fsg_opts *opts = fsg_opts_from_func_inst(fi);
struct fsg_common *common = opts->common;
struct fsg_dev *fsg;
- unsigned nluns, i;
fsg = kzalloc(sizeof(*fsg), GFP_KERNEL);
if (unlikely(!fsg))
return ERR_PTR(-ENOMEM);
mutex_lock(&opts->lock);
- if (!opts->refcnt) {
- for (nluns = i = 0; i < FSG_MAX_LUNS; ++i)
- if (common->luns[i])
- nluns = i + 1;
- if (!nluns)
- pr_warn("No LUNS defined, continuing anyway\n");
- else
- common->nluns = nluns;
- pr_info("Number of LUNs=%u\n", common->nluns);
- }
opts->refcnt++;
mutex_unlock(&opts->lock);
diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h
index b4866fc..445df67 100644
--- a/drivers/usb/gadget/function/f_mass_storage.h
+++ b/drivers/usb/gadget/function/f_mass_storage.h
@@ -137,14 +137,10 @@
int fsg_common_set_cdev(struct fsg_common *common,
struct usb_composite_dev *cdev, bool can_stall);
-void fsg_common_remove_lun(struct fsg_lun *lun, bool sysfs);
+void fsg_common_remove_lun(struct fsg_lun *lun);
void fsg_common_remove_luns(struct fsg_common *common);
-void fsg_common_free_luns(struct fsg_common *common);
-
-int fsg_common_set_nluns(struct fsg_common *common, int nluns);
-
void fsg_common_set_ops(struct fsg_common *common,
const struct fsg_operations *ops);
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index ad50a67..a287a48 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -329,6 +329,10 @@
unsigned i;
int err;
+ /* For Control Device interface we do nothing */
+ if (intf == 0)
+ return 0;
+
err = f_midi_start_ep(midi, f, midi->in_ep);
if (err)
return err;
diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
index bdcda9f..3f05c6bd 100644
--- a/drivers/usb/gadget/function/f_ncm.c
+++ b/drivers/usb/gadget/function/f_ncm.c
@@ -853,9 +853,8 @@
/* Enable zlps by default for NCM conformance;
* override for musb_hdrc (avoids txdma ovhead)
*/
- ncm->port.is_zlp_ok = !(
- gadget_is_musbhdrc(cdev->gadget)
- );
+ ncm->port.is_zlp_ok =
+ gadget_is_zlp_supported(cdev->gadget);
ncm->port.cdc_filter = DEFAULT_FILTER;
DBG(cdev, "activate ncm\n");
net = gether_connect(&ncm->port);
diff --git a/drivers/usb/gadget/function/f_obex.c b/drivers/usb/gadget/function/f_obex.c
index a1b79c5..5460426 100644
--- a/drivers/usb/gadget/function/f_obex.c
+++ b/drivers/usb/gadget/function/f_obex.c
@@ -20,7 +20,6 @@
#include <linux/module.h>
#include "u_serial.h"
-#include "gadget_chips.h"
/*
@@ -37,7 +36,6 @@
u8 data_id;
u8 cur_alt;
u8 port_num;
- u8 can_activate;
};
static inline struct f_obex *func_to_obex(struct usb_function *f)
@@ -268,9 +266,6 @@
struct usb_composite_dev *cdev = g->func.config->cdev;
int status;
- if (!obex->can_activate)
- return;
-
status = usb_function_activate(&g->func);
if (status)
dev_dbg(&cdev->gadget->dev,
@@ -284,9 +279,6 @@
struct usb_composite_dev *cdev = g->func.config->cdev;
int status;
- if (!obex->can_activate)
- return;
-
status = usb_function_deactivate(&g->func);
if (status)
dev_dbg(&cdev->gadget->dev,
@@ -304,7 +296,7 @@
*
* Altsettings are mandatory, however...
*/
- if (!gadget_supports_altsettings(c->cdev->gadget))
+ if (!gadget_is_altset_supported(c->cdev->gadget))
return false;
/* everything else is *probably* fine ... */
@@ -378,17 +370,6 @@
if (status)
goto fail;
- /* Avoid letting this gadget enumerate until the userspace
- * OBEX server is active.
- */
- status = usb_function_deactivate(f);
- if (status < 0)
- WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n",
- obex->port_num, status);
- else
- obex->can_activate = true;
-
-
dev_dbg(&cdev->gadget->dev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
obex->port_num,
gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -529,6 +510,7 @@
obex->port.func.get_alt = obex_get_alt;
obex->port.func.disable = obex_disable;
obex->port.func.free_func = obex_free;
+ obex->port.func.bind_deactivated = true;
return &obex->port.func;
}
diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c
index 44173df..8e2b6be 100644
--- a/drivers/usb/gadget/function/f_printer.c
+++ b/drivers/usb/gadget/function/f_printer.c
@@ -804,6 +804,8 @@
static void printer_reset_interface(struct printer_dev *dev)
{
+ unsigned long flags;
+
if (dev->interface < 0)
return;
@@ -815,9 +817,11 @@
if (dev->out_ep->desc)
usb_ep_disable(dev->out_ep);
+ spin_lock_irqsave(&dev->lock, flags);
dev->in_ep->desc = NULL;
dev->out_ep->desc = NULL;
dev->interface = -1;
+ spin_unlock_irqrestore(&dev->lock, flags);
}
/* Change our operational Interface. */
@@ -1131,13 +1135,10 @@
static void printer_func_disable(struct usb_function *f)
{
struct printer_dev *dev = func_to_printer(f);
- unsigned long flags;
DBG(dev, "%s\n", __func__);
- spin_lock_irqsave(&dev->lock, flags);
printer_reset_interface(dev);
- spin_unlock_irqrestore(&dev->lock, flags);
}
static inline struct f_printer_opts
@@ -1248,7 +1249,15 @@
static inline int gprinter_get_minor(void)
{
- return ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL);
+ int ret;
+
+ ret = ida_simple_get(&printer_ida, 0, 0, GFP_KERNEL);
+ if (ret >= PRINTER_MINORS) {
+ ida_simple_remove(&printer_ida, ret);
+ ret = -ENODEV;
+ }
+
+ return ret;
}
static inline void gprinter_put_minor(int minor)
diff --git a/drivers/usb/gadget/function/f_serial.c b/drivers/usb/gadget/function/f_serial.c
index 2e02dfa..1d162e2 100644
--- a/drivers/usb/gadget/function/f_serial.c
+++ b/drivers/usb/gadget/function/f_serial.c
@@ -16,7 +16,6 @@
#include <linux/device.h>
#include "u_serial.h"
-#include "gadget_chips.h"
/*
diff --git a/drivers/usb/gadget/function/f_sourcesink.c b/drivers/usb/gadget/function/f_sourcesink.c
index 3a5ae99..cbfaf86 100644
--- a/drivers/usb/gadget/function/f_sourcesink.c
+++ b/drivers/usb/gadget/function/f_sourcesink.c
@@ -20,7 +20,6 @@
#include <linux/err.h>
#include "g_zero.h"
-#include "gadget_chips.h"
#include "u_f.h"
/*
@@ -42,11 +41,6 @@
* queues are relatively independent, will receive a range of packet sizes,
* and can often be made to run out completely. Those issues are important
* when stress testing peripheral controller drivers.
- *
- *
- * This is currently packaged as a configuration driver, which can't be
- * combined with other functions to make composite devices. However, it
- * can be combined with other independent configurations.
*/
struct f_sourcesink {
struct usb_function function;
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index 6d3eb8b..f8de7ea 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -975,6 +975,29 @@
"%s:%d Error!\n", __func__, __LINE__);
}
+static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts,
+ struct usb_endpoint_descriptor *ep_desc,
+ unsigned int factor, bool is_playback)
+{
+ int chmask, srate, ssize;
+ u16 max_packet_size;
+
+ if (is_playback) {
+ chmask = uac2_opts->p_chmask;
+ srate = uac2_opts->p_srate;
+ ssize = uac2_opts->p_ssize;
+ } else {
+ chmask = uac2_opts->c_chmask;
+ srate = uac2_opts->c_srate;
+ ssize = uac2_opts->c_ssize;
+ }
+
+ max_packet_size = num_channels(chmask) * ssize *
+ DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
+ ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_packet_size,
+ le16_to_cpu(ep_desc->wMaxPacketSize)));
+}
+
static int
afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
{
@@ -1070,10 +1093,14 @@
uac2->p_prm.uac2 = uac2;
uac2->c_prm.uac2 = uac2;
+ /* Calculate wMaxPacketSize according to audio bandwidth */
+ set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true);
+ set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false);
+ set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true);
+ set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false);
+
hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress;
- hs_epout_desc.wMaxPacketSize = fs_epout_desc.wMaxPacketSize;
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
- hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
if (ret)
@@ -1162,14 +1189,14 @@
factor = 1000;
} else {
ep_desc = &hs_epin_desc;
- factor = 125;
+ factor = 8000;
}
/* pre-compute some values for iso_complete() */
uac2->p_framesize = opts->p_ssize *
num_channels(opts->p_chmask);
rate = opts->p_srate * uac2->p_framesize;
- uac2->p_interval = (1 << (ep_desc->bInterval - 1)) * factor;
+ uac2->p_interval = factor / (1 << (ep_desc->bInterval - 1));
uac2->p_pktsize = min_t(unsigned int, rate / uac2->p_interval,
prm->max_psize);
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index cf0df8f..743be34 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -733,12 +733,6 @@
uvc->control_req->complete = uvc_function_ep0_complete;
uvc->control_req->context = uvc;
- /* Avoid letting this gadget enumerate until the userspace server is
- * active.
- */
- if ((ret = usb_function_deactivate(f)) < 0)
- goto error;
-
if (v4l2_device_register(&cdev->gadget->dev, &uvc->v4l2_dev)) {
printk(KERN_INFO "v4l2_device_register failed\n");
goto error;
@@ -949,6 +943,7 @@
uvc->func.disable = uvc_function_disable;
uvc->func.setup = uvc_function_setup;
uvc->func.free_func = uvc_free;
+ uvc->func.bind_deactivated = true;
return &uvc->func;
}
diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h
index 70c8914..c3544e6 100644
--- a/drivers/usb/gadget/function/storage_common.h
+++ b/drivers/usb/gadget/function/storage_common.h
@@ -123,7 +123,7 @@
#define FSG_BUFLEN ((u32)16384)
/* Maximal number of LUNs supported in mass storage function */
-#define FSG_MAX_LUNS 8
+#define FSG_MAX_LUNS 16
enum fsg_buffer_state {
BUF_STATE_EMPTY = 0,
diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h
index 334b389..c77145b 100644
--- a/drivers/usb/gadget/function/u_ether.h
+++ b/drivers/usb/gadget/function/u_ether.h
@@ -20,8 +20,6 @@
#include <linux/usb/cdc.h>
#include <linux/netdevice.h>
-#include "gadget_chips.h"
-
#define QMULT_DEFAULT 5
/*
@@ -259,7 +257,7 @@
/* Some controllers can't support CDC Ethernet (ECM) ... */
static inline bool can_support_ecm(struct usb_gadget *gadget)
{
- if (!gadget_supports_altsettings(gadget))
+ if (!gadget_is_altset_supported(gadget))
return false;
/* Everything else is *presumably* fine ... but this is a bit
diff --git a/drivers/usb/gadget/function/u_uac1.h b/drivers/usb/gadget/function/u_uac1.h
index fe386df..5c2ac8e 100644
--- a/drivers/usb/gadget/function/u_uac1.h
+++ b/drivers/usb/gadget/function/u_uac1.h
@@ -21,8 +21,6 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
-#include "gadget_chips.h"
-
#define FILE_PCM_PLAYBACK "/dev/snd/pcmC0D0p"
#define FILE_PCM_CAPTURE "/dev/snd/pcmC0D0c"
#define FILE_CONTROL "/dev/snd/controlC0"
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig
index d5a7102..4d682ad 100644
--- a/drivers/usb/gadget/legacy/Kconfig
+++ b/drivers/usb/gadget/legacy/Kconfig
@@ -339,6 +339,7 @@
config USB_G_NOKIA
tristate "Nokia composite gadget"
depends on PHONET
+ depends on BLOCK
select USB_LIBCOMPOSITE
select USB_U_SERIAL
select USB_U_ETHER
@@ -346,6 +347,7 @@
select USB_F_OBEX
select USB_F_PHONET
select USB_F_ECM
+ select USB_F_MASS_STORAGE
help
The Nokia composite gadget provides support for acm, obex
and phonet in only one composite gadget driver.
diff --git a/drivers/usb/gadget/legacy/acm_ms.c b/drivers/usb/gadget/legacy/acm_ms.c
index 1194b09..4b158e2 100644
--- a/drivers/usb/gadget/legacy/acm_ms.c
+++ b/drivers/usb/gadget/legacy/acm_ms.c
@@ -58,21 +58,7 @@
/*.bNumConfigurations = DYNAMIC*/
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -200,10 +186,6 @@
if (status)
goto fail;
- status = fsg_common_set_nluns(opts->common, config.nluns);
- if (status)
- goto fail_set_nluns;
-
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
@@ -225,10 +207,21 @@
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail_string_ids;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration */
status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config);
if (status < 0)
- goto fail_string_ids;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -236,11 +229,12 @@
return 0;
/* error recovery */
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
- fsg_common_free_luns(opts->common);
-fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
@@ -255,6 +249,9 @@
usb_put_function_instance(fi_msg);
usb_put_function(f_acm);
usb_put_function_instance(f_acm_inst);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/audio.c b/drivers/usb/gadget/legacy/audio.c
index f289caf..685cf3b 100644
--- a/drivers/usb/gadget/legacy/audio.c
+++ b/drivers/usb/gadget/legacy/audio.c
@@ -15,7 +15,6 @@
#include <linux/module.h>
#include <linux/usb/composite.h>
-#include "gadget_chips.h"
#define DRIVER_DESC "Linux USB Audio Gadget"
#define DRIVER_VERSION "Feb 2, 2012"
@@ -124,7 +123,7 @@
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x200),
+ .bcdUSB = cpu_to_le16(0x200),
#ifdef CONFIG_GADGET_UAC1
.bDeviceClass = USB_CLASS_PER_INTERFACE,
@@ -141,8 +140,8 @@
* we support. (As does bNumConfigurations.) These values can
* also be overridden by module parameters.
*/
- .idVendor = __constant_cpu_to_le16(AUDIO_VENDOR_NUM),
- .idProduct = __constant_cpu_to_le16(AUDIO_PRODUCT_NUM),
+ .idVendor = cpu_to_le16(AUDIO_VENDOR_NUM),
+ .idProduct = cpu_to_le16(AUDIO_PRODUCT_NUM),
/* .bcdDevice = f(hardware) */
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@@ -150,20 +149,7 @@
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@@ -259,14 +245,28 @@
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc)
+ goto fail;
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
status = usb_add_config(cdev, &audio_config_driver, audio_do_config);
if (status < 0)
- goto fail;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION);
return 0;
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail:
#ifndef CONFIG_GADGET_UAC1
usb_put_function_instance(fi_uac2);
@@ -289,6 +289,9 @@
if (!IS_ERR_OR_NULL(fi_uac2))
usb_put_function_instance(fi_uac2);
#endif
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/cdc2.c b/drivers/usb/gadget/legacy/cdc2.c
index afd3e37..ecd8c8d 100644
--- a/drivers/usb/gadget/legacy/cdc2.c
+++ b/drivers/usb/gadget/legacy/cdc2.c
@@ -60,21 +60,7 @@
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -193,10 +179,21 @@
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail1;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration */
status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config);
if (status < 0)
- goto fail1;
+ goto fail2;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -204,6 +201,9 @@
return 0;
+fail2:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail1:
usb_put_function_instance(fi_serial);
fail:
@@ -219,6 +219,9 @@
usb_put_function(f_ecm);
if (!IS_ERR_OR_NULL(fi_ecm))
usb_put_function_instance(fi_ecm);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c
index 204b10b..5231a32 100644
--- a/drivers/usb/gadget/legacy/dbgp.c
+++ b/drivers/usb/gadget/legacy/dbgp.c
@@ -35,10 +35,10 @@
static struct usb_device_descriptor device_desc = {
.bLength = sizeof device_desc,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_VENDOR_SPEC,
- .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
- .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
+ .idVendor = cpu_to_le16(DRIVER_VENDOR_ID),
+ .idProduct = cpu_to_le16(DRIVER_PRODUCT_ID),
.bNumConfigurations = 1,
};
@@ -251,7 +251,7 @@
dbgp.i_ep->driver_data = gadget;
i_desc.wMaxPacketSize =
- __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+ cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
if (!dbgp.o_ep) {
@@ -262,7 +262,7 @@
dbgp.o_ep->driver_data = gadget;
o_desc.wMaxPacketSize =
- __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
+ cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress;
dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress;
diff --git a/drivers/usb/gadget/legacy/ether.c b/drivers/usb/gadget/legacy/ether.c
index a3323dc..31e9160 100644
--- a/drivers/usb/gadget/legacy/ether.c
+++ b/drivers/usb/gadget/legacy/ether.c
@@ -171,20 +171,7 @@
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
@@ -416,17 +403,28 @@
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail1;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration(s); RNDIS first, if it's used */
if (has_rndis()) {
status = usb_add_config(cdev, &rndis_config_driver,
rndis_do_config);
if (status < 0)
- goto fail1;
+ goto fail2;
}
status = usb_add_config(cdev, ð_config_driver, eth_do_config);
if (status < 0)
- goto fail1;
+ goto fail2;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n",
@@ -434,6 +432,9 @@
return 0;
+fail2:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail1:
if (has_rndis())
usb_put_function_instance(fi_rndis);
@@ -463,6 +464,9 @@
usb_put_function(f_geth);
usb_put_function_instance(fi_geth);
}
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/g_ffs.c b/drivers/usb/gadget/legacy/g_ffs.c
index e821931..320a81b 100644
--- a/drivers/usb/gadget/legacy/g_ffs.c
+++ b/drivers/usb/gadget/legacy/g_ffs.c
@@ -88,21 +88,7 @@
module_param_array_named(functions, func_names, charp, &func_num, 0);
MODULE_PARM_DESC(functions, "USB Functions list");
-static const struct usb_descriptor_header *gfs_otg_desc[] = {
- (const struct usb_descriptor_header *)
- &(const struct usb_otg_descriptor) {
- .bLength = sizeof(struct usb_otg_descriptor),
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
- },
-
- NULL
-};
+static const struct usb_descriptor_header *gfs_otg_desc[2];
/* String IDs are assigned dynamically */
static struct usb_string gfs_strings[] = {
@@ -412,6 +398,17 @@
goto error_rndis;
gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(cdev->gadget) && !gfs_otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc)
+ goto error_rndis;
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ gfs_otg_desc[0] = usb_desc;
+ gfs_otg_desc[1] = NULL;
+ }
+
for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
struct gfs_configuration *c = gfs_configurations + i;
int sid = USB_GADGET_FIRST_AVAIL_IDX + i;
@@ -432,6 +429,8 @@
/* TODO */
error_unbind:
+ kfree(gfs_otg_desc[0]);
+ gfs_otg_desc[0] = NULL;
error_rndis:
#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
usb_put_function_instance(fi_rndis);
@@ -473,6 +472,9 @@
for (i = 0; i < N_CONF * func_num; ++i)
usb_put_function(*(f_ffs[0] + i));
+ kfree(gfs_otg_desc[0]);
+ gfs_otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c
index da19c48..8a18348 100644
--- a/drivers/usb/gadget/legacy/gmidi.c
+++ b/drivers/usb/gadget/legacy/gmidi.c
@@ -35,8 +35,6 @@
#include <linux/usb/audio.h>
#include <linux/usb/midi.h>
-#include "gadget_chips.h"
-
#include "u_midi.h"
/*-------------------------------------------------------------------------*/
@@ -88,10 +86,10 @@
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_PER_INTERFACE,
- .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM),
- .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM),
+ .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM),
+ .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
.bNumConfigurations = 1,
diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c
index 2baa572..7e5d2c4 100644
--- a/drivers/usb/gadget/legacy/hid.c
+++ b/drivers/usb/gadget/legacy/hid.c
@@ -19,7 +19,6 @@
#include <linux/usb/composite.h>
#include <linux/usb/g_hid.h>
-#include "gadget_chips.h"
#define DRIVER_DESC "HID Gadget"
#define DRIVER_VERSION "2010/03/16"
@@ -68,21 +67,7 @@
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -186,16 +171,30 @@
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto put;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register our configuration */
status = usb_add_config(cdev, &config_driver, do_config);
if (status < 0)
- goto put;
+ goto free_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
return 0;
+free_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
put:
list_for_each_entry(m, &hidg_func_list, node) {
if (m == n)
@@ -213,6 +212,10 @@
usb_put_function(n->f);
usb_put_function_instance(n->fi);
}
+
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c
index e7bfb08..bda3c51 100644
--- a/drivers/usb/gadget/legacy/mass_storage.c
+++ b/drivers/usb/gadget/legacy/mass_storage.c
@@ -64,21 +64,7 @@
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
static struct usb_string strings_dev[] = {
[USB_GADGET_MANUFACTURER_IDX].s = "",
@@ -191,10 +177,6 @@
if (status)
goto fail;
- status = fsg_common_set_nluns(opts->common, config.nluns);
- if (status)
- goto fail_set_nluns;
-
fsg_common_set_ops(opts->common, &ops);
status = fsg_common_set_cdev(opts->common, cdev, config.can_stall);
@@ -214,9 +196,20 @@
goto fail_string_ids;
msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc)
+ goto fail_string_ids;
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
status = usb_add_config(cdev, &msg_config_driver, msg_do_config);
if (status < 0)
- goto fail_string_ids;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&cdev->gadget->dev,
@@ -224,11 +217,12 @@
set_bit(0, &msg_registered);
return 0;
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(opts->common);
fail_set_cdev:
- fsg_common_free_luns(opts->common);
-fail_set_nluns:
fsg_common_free_buffers(opts->common);
fail:
usb_put_function_instance(fi_msg);
@@ -243,6 +237,9 @@
if (!IS_ERR(fi_msg))
usb_put_function_instance(fi_msg);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/multi.c b/drivers/usb/gadget/legacy/multi.c
index b21b51f..4fe794d 100644
--- a/drivers/usb/gadget/legacy/multi.c
+++ b/drivers/usb/gadget/legacy/multi.c
@@ -78,21 +78,7 @@
.idProduct = cpu_to_le16(MULTI_PRODUCT_NUM),
};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &(struct usb_otg_descriptor){
- .bLength = sizeof(struct usb_otg_descriptor),
- .bDescriptorType = USB_DT_OTG,
-
- /*
- * REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
- },
- NULL,
-};
-
+static const struct usb_descriptor_header *otg_desc[2];
enum {
MULTI_STRING_RNDIS_CONFIG_IDX = USB_GADGET_FIRST_AVAIL_IDX,
@@ -407,10 +393,6 @@
if (status)
goto fail2;
- status = fsg_common_set_nluns(fsg_opts->common, config.nluns);
- if (status)
- goto fail_set_nluns;
-
status = fsg_common_set_cdev(fsg_opts->common, cdev, config.can_stall);
if (status)
goto fail_set_cdev;
@@ -429,14 +411,25 @@
goto fail_string_ids;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail_string_ids;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
/* register configurations */
status = rndis_config_register(cdev);
if (unlikely(status < 0))
- goto fail_string_ids;
+ goto fail_otg_desc;
status = cdc_config_register(cdev);
if (unlikely(status < 0))
- goto fail_string_ids;
+ goto fail_otg_desc;
usb_composite_overwrite_options(cdev, &coverwrite);
/* we're done */
@@ -445,11 +438,12 @@
/* error recovery */
+fail_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail_string_ids:
fsg_common_remove_luns(fsg_opts->common);
fail_set_cdev:
- fsg_common_free_luns(fsg_opts->common);
-fail_set_nluns:
fsg_common_free_buffers(fsg_opts->common);
fail2:
usb_put_function_instance(fi_msg);
@@ -490,6 +484,9 @@
usb_put_function(f_ecm);
usb_put_function_instance(fi_ecm);
#endif
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/ncm.c b/drivers/usb/gadget/legacy/ncm.c
index 6ce7421..2bae438 100644
--- a/drivers/usb/gadget/legacy/ncm.c
+++ b/drivers/usb/gadget/legacy/ncm.c
@@ -69,20 +69,7 @@
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
static struct usb_string strings_dev[] = {
@@ -171,16 +158,30 @@
device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
+ if (gadget_is_otg(gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(gadget);
+ if (!usb_desc)
+ goto fail;
+ usb_otg_descriptor_init(gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
+
status = usb_add_config(cdev, &ncm_config_driver,
ncm_do_config);
if (status < 0)
- goto fail;
+ goto fail1;
usb_composite_overwrite_options(cdev, &coverwrite);
dev_info(&gadget->dev, "%s\n", DRIVER_DESC);
return 0;
+fail1:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail:
usb_put_function_instance(f_ncm_inst);
return status;
@@ -192,6 +193,9 @@
usb_put_function(f_ncm);
if (!IS_ERR_OR_NULL(f_ncm_inst))
usb_put_function_instance(f_ncm_inst);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/nokia.c b/drivers/usb/gadget/legacy/nokia.c
index 4bb498a..8b3f6fb 100644
--- a/drivers/usb/gadget/legacy/nokia.c
+++ b/drivers/usb/gadget/legacy/nokia.c
@@ -23,7 +23,7 @@
#include "u_ether.h"
#include "u_phonet.h"
#include "u_ecm.h"
-#include "gadget_chips.h"
+#include "f_mass_storage.h"
/* Defines */
@@ -34,6 +34,29 @@
USB_ETHERNET_MODULE_PARAMETERS();
+static struct fsg_module_parameters fsg_mod_data = {
+ .stall = 0,
+ .luns = 2,
+ .removable_count = 2,
+ .removable = { 1, 1, },
+};
+
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS;
+
+#else
+
+/*
+ * Number of buffers we will use.
+ * 2 is usually enough for good buffering pipeline
+ */
+#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS
+
+#endif /* CONFIG_USB_DEBUG */
+
+FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
+
#define NOKIA_VENDOR_ID 0x0421 /* Nokia */
#define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */
@@ -66,10 +89,10 @@
static struct usb_device_descriptor device_desc = {
.bLength = USB_DT_DEVICE_SIZE,
.bDescriptorType = USB_DT_DEVICE,
- .bcdUSB = __constant_cpu_to_le16(0x0200),
+ .bcdUSB = cpu_to_le16(0x0200),
.bDeviceClass = USB_CLASS_COMM,
- .idVendor = __constant_cpu_to_le16(NOKIA_VENDOR_ID),
- .idProduct = __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
+ .idVendor = cpu_to_le16(NOKIA_VENDOR_ID),
+ .idProduct = cpu_to_le16(NOKIA_PRODUCT_ID),
.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM),
/* .iManufacturer = DYNAMIC */
/* .iProduct = DYNAMIC */
@@ -94,6 +117,8 @@
static struct usb_function *f_obex2_cfg2;
static struct usb_function *f_phonet_cfg1;
static struct usb_function *f_phonet_cfg2;
+static struct usb_function *f_msg_cfg1;
+static struct usb_function *f_msg_cfg2;
static struct usb_configuration nokia_config_500ma_driver = {
@@ -117,6 +142,7 @@
static struct usb_function_instance *fi_obex1;
static struct usb_function_instance *fi_obex2;
static struct usb_function_instance *fi_phonet;
+static struct usb_function_instance *fi_msg;
static int nokia_bind_config(struct usb_configuration *c)
{
@@ -125,6 +151,8 @@
struct usb_function *f_obex1 = NULL;
struct usb_function *f_ecm;
struct usb_function *f_obex2 = NULL;
+ struct usb_function *f_msg;
+ struct fsg_opts *fsg_opts;
int status = 0;
int obex1_stat = -1;
int obex2_stat = -1;
@@ -160,6 +188,12 @@
goto err_get_ecm;
}
+ f_msg = usb_get_function(fi_msg);
+ if (IS_ERR(f_msg)) {
+ status = PTR_ERR(f_msg);
+ goto err_get_msg;
+ }
+
if (!IS_ERR_OR_NULL(f_phonet)) {
phonet_stat = usb_add_function(c, f_phonet);
if (phonet_stat)
@@ -187,21 +221,36 @@
pr_debug("could not bind ecm config %d\n", status);
goto err_ecm;
}
+
+ fsg_opts = fsg_opts_from_func_inst(fi_msg);
+
+ status = fsg_common_run_thread(fsg_opts->common);
+ if (status)
+ goto err_msg;
+
+ status = usb_add_function(c, f_msg);
+ if (status)
+ goto err_msg;
+
if (c == &nokia_config_500ma_driver) {
f_acm_cfg1 = f_acm;
f_ecm_cfg1 = f_ecm;
f_phonet_cfg1 = f_phonet;
f_obex1_cfg1 = f_obex1;
f_obex2_cfg1 = f_obex2;
+ f_msg_cfg1 = f_msg;
} else {
f_acm_cfg2 = f_acm;
f_ecm_cfg2 = f_ecm;
f_phonet_cfg2 = f_phonet;
f_obex1_cfg2 = f_obex1;
f_obex2_cfg2 = f_obex2;
+ f_msg_cfg2 = f_msg;
}
return status;
+err_msg:
+ usb_remove_function(c, f_ecm);
err_ecm:
usb_remove_function(c, f_acm);
err_conf:
@@ -211,6 +260,8 @@
usb_remove_function(c, f_obex1);
if (!phonet_stat)
usb_remove_function(c, f_phonet);
+ usb_put_function(f_msg);
+err_get_msg:
usb_put_function(f_ecm);
err_get_ecm:
usb_put_function(f_acm);
@@ -227,6 +278,8 @@
static int nokia_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
+ struct fsg_opts *fsg_opts;
+ struct fsg_config fsg_config;
int status;
status = usb_string_ids_tab(cdev, strings_dev);
@@ -238,7 +291,7 @@
nokia_config_500ma_driver.iConfiguration = status;
nokia_config_100ma_driver.iConfiguration = status;
- if (!gadget_supports_altsettings(gadget)) {
+ if (!gadget_is_altset_supported(gadget)) {
status = -ENODEV;
goto err_usb;
}
@@ -267,11 +320,42 @@
goto err_acm_inst;
}
+ fi_msg = usb_get_function_instance("mass_storage");
+ if (IS_ERR(fi_msg)) {
+ status = PTR_ERR(fi_msg);
+ goto err_ecm_inst;
+ }
+
+ /* set up mass storage function */
+ fsg_config_from_params(&fsg_config, &fsg_mod_data, fsg_num_buffers);
+ fsg_config.vendor_name = "Nokia";
+ fsg_config.product_name = "N900";
+
+ fsg_opts = fsg_opts_from_func_inst(fi_msg);
+ fsg_opts->no_configfs = true;
+
+ status = fsg_common_set_num_buffers(fsg_opts->common, fsg_num_buffers);
+ if (status)
+ goto err_msg_inst;
+
+ status = fsg_common_set_cdev(fsg_opts->common, cdev, fsg_config.can_stall);
+ if (status)
+ goto err_msg_buf;
+
+ fsg_common_set_sysfs(fsg_opts->common, true);
+
+ status = fsg_common_create_luns(fsg_opts->common, &fsg_config);
+ if (status)
+ goto err_msg_buf;
+
+ fsg_common_set_inquiry_string(fsg_opts->common, fsg_config.vendor_name,
+ fsg_config.product_name);
+
/* finally register the configuration */
status = usb_add_config(cdev, &nokia_config_500ma_driver,
nokia_bind_config);
if (status < 0)
- goto err_ecm_inst;
+ goto err_msg_luns;
status = usb_add_config(cdev, &nokia_config_100ma_driver,
nokia_bind_config);
@@ -292,6 +376,12 @@
if (!IS_ERR_OR_NULL(f_phonet_cfg1))
usb_put_function(f_phonet_cfg1);
usb_put_function(f_ecm_cfg1);
+err_msg_luns:
+ fsg_common_remove_luns(fsg_opts->common);
+err_msg_buf:
+ fsg_common_free_buffers(fsg_opts->common);
+err_msg_inst:
+ usb_put_function_instance(fi_msg);
err_ecm_inst:
usb_put_function_instance(fi_ecm);
err_acm_inst:
@@ -325,7 +415,10 @@
usb_put_function(f_acm_cfg2);
usb_put_function(f_ecm_cfg1);
usb_put_function(f_ecm_cfg2);
+ usb_put_function(f_msg_cfg1);
+ usb_put_function(f_msg_cfg2);
+ usb_put_function_instance(fi_msg);
usb_put_function_instance(fi_ecm);
if (!IS_ERR(fi_obex2))
usb_put_function_instance(fi_obex2);
diff --git a/drivers/usb/gadget/legacy/printer.c b/drivers/usb/gadget/legacy/printer.c
index 1ce7df1..a22d30a 100644
--- a/drivers/usb/gadget/legacy/printer.c
+++ b/drivers/usb/gadget/legacy/printer.c
@@ -19,8 +19,6 @@
#include <linux/usb/gadget.h>
#include <linux/usb/g_printer.h>
-#include "gadget_chips.h"
-
USB_GADGET_COMPOSITE_OPTIONS();
#define DRIVER_DESC "Printer Gadget"
@@ -82,16 +80,7 @@
.bNumConfigurations = 1
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
- .bmAttributes = USB_OTG_SRP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@@ -136,7 +125,6 @@
usb_gadget_set_selfpowered(gadget);
if (gadget_is_otg(gadget)) {
- otg_descriptor.bmAttributes |= USB_OTG_HNP;
printer_cfg_driver.descriptors = otg_desc;
printer_cfg_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
@@ -174,21 +162,39 @@
opts->q_len = QLEN;
ret = usb_string_ids_tab(cdev, strings);
- if (ret < 0) {
- usb_put_function_instance(fi_printer);
- return ret;
- }
+ if (ret < 0)
+ goto fail_put_func_inst;
+
device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id;
device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id;
device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id;
- ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
- if (ret) {
- usb_put_function_instance(fi_printer);
- return ret;
+ if (gadget_is_otg(cdev->gadget) && !otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc) {
+ ret = -ENOMEM;
+ goto fail_put_func_inst;
+ }
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
}
+
+ ret = usb_add_config(cdev, &printer_cfg_driver, printer_do_config);
+ if (ret)
+ goto fail_free_otg_desc;
+
usb_composite_overwrite_options(cdev, &coverwrite);
return ret;
+
+fail_free_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+fail_put_func_inst:
+ usb_put_function_instance(fi_printer);
+ return ret;
}
static int printer_unbind(struct usb_composite_dev *cdev)
@@ -196,6 +202,9 @@
usb_put_function(f_printer);
usb_put_function_instance(fi_printer);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/serial.c b/drivers/usb/gadget/legacy/serial.c
index 8b7528f..c5d42e0 100644
--- a/drivers/usb/gadget/legacy/serial.c
+++ b/drivers/usb/gadget/legacy/serial.c
@@ -17,7 +17,6 @@
#include <linux/tty_flip.h>
#include "u_serial.h"
-#include "gadget_chips.h"
/* Defines */
@@ -79,20 +78,7 @@
.bNumConfigurations = 1,
};
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
+static const struct usb_descriptor_header *otg_desc[2];
/*-------------------------------------------------------------------------*/
@@ -191,6 +177,18 @@
serial_config_driver.iConfiguration = status;
if (gadget_is_otg(cdev->gadget)) {
+ if (!otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc) {
+ status = -ENOMEM;
+ goto fail;
+ }
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
serial_config_driver.descriptors = otg_desc;
serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
@@ -208,13 +206,15 @@
"gser");
}
if (status < 0)
- goto fail;
+ goto fail1;
usb_composite_overwrite_options(cdev, &coverwrite);
INFO(cdev, "%s\n", GS_VERSION_NAME);
return 0;
-
+fail1:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
fail:
return status;
}
@@ -227,6 +227,10 @@
usb_put_function(f_serial[i]);
usb_put_function_instance(fi_serial[i]);
}
+
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/legacy/zero.c b/drivers/usb/gadget/legacy/zero.c
index c986e8a..37a4100 100644
--- a/drivers/usb/gadget/legacy/zero.c
+++ b/drivers/usb/gadget/legacy/zero.c
@@ -121,24 +121,7 @@
.bNumConfigurations = 2,
};
-#ifdef CONFIG_USB_OTG
-static struct usb_otg_descriptor otg_descriptor = {
- .bLength = sizeof otg_descriptor,
- .bDescriptorType = USB_DT_OTG,
-
- /* REVISIT SRP-only hardware is possible, although
- * it would not be called "OTG" ...
- */
- .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
-};
-
-static const struct usb_descriptor_header *otg_desc[] = {
- (struct usb_descriptor_header *) &otg_descriptor,
- NULL,
-};
-#else
-#define otg_desc NULL
-#endif
+static const struct usb_descriptor_header *otg_desc[2];
/* string IDs are assigned dynamically */
/* default serial number takes at least two packets */
@@ -341,6 +324,18 @@
/* support OTG systems */
if (gadget_is_otg(cdev->gadget)) {
+ if (!otg_desc[0]) {
+ struct usb_descriptor_header *usb_desc;
+
+ usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
+ if (!usb_desc) {
+ status = -ENOMEM;
+ goto err_conf_flb;
+ }
+ usb_otg_descriptor_init(cdev->gadget, usb_desc);
+ otg_desc[0] = usb_desc;
+ otg_desc[1] = NULL;
+ }
sourcesink_driver.descriptors = otg_desc;
sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
loopback_driver.descriptors = otg_desc;
@@ -359,12 +354,12 @@
}
status = usb_add_function(&sourcesink_driver, func_ss);
if (status)
- goto err_conf_flb;
+ goto err_free_otg_desc;
usb_ep_autoconfig_reset(cdev->gadget);
status = usb_add_function(&loopback_driver, func_lb);
if (status)
- goto err_conf_flb;
+ goto err_free_otg_desc;
usb_ep_autoconfig_reset(cdev->gadget);
usb_composite_overwrite_options(cdev, &coverwrite);
@@ -373,6 +368,9 @@
return 0;
+err_free_otg_desc:
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
err_conf_flb:
usb_put_function(func_lb);
func_lb = NULL;
@@ -397,6 +395,9 @@
if (!IS_ERR_OR_NULL(func_lb))
usb_put_function(func_lb);
usb_put_function_instance(func_inst_lb);
+ kfree(otg_desc[0]);
+ otg_desc[0] = NULL;
+
return 0;
}
diff --git a/drivers/usb/gadget/udc/amd5536udc.c b/drivers/usb/gadget/udc/amd5536udc.c
index de7e5e2..fdacddb 100644
--- a/drivers/usb/gadget/udc/amd5536udc.c
+++ b/drivers/usb/gadget/udc/amd5536udc.c
@@ -138,15 +138,82 @@
/* endpoint names used for print */
static const char ep0_string[] = "ep0in";
-static const char *const ep_string[] = {
- ep0_string,
- "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk",
- "ep6in-bulk", "ep7in-bulk", "ep8in-bulk", "ep9in-bulk", "ep10in-bulk",
- "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk",
- "ep15in-bulk", "ep0out", "ep1out-bulk", "ep2out-bulk", "ep3out-bulk",
- "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk",
- "ep8out-bulk", "ep9out-bulk", "ep10out-bulk", "ep11out-bulk",
- "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+ EP_INFO(ep0_string,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep1in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep3in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep5in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep6in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep7in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep8in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep9in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep10in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep11in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep12in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep13in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep14in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep15in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep0out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep1out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep2out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep4out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep5out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep6out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep7out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep8out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep9out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep10out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep11out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep12out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep13out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep14out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep15out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
};
/* DMA usage flag */
@@ -1517,7 +1584,8 @@
for (tmp = 0; tmp < UDC_EP_NUM; tmp++) {
ep = &dev->ep[tmp];
ep->dev = dev;
- ep->ep.name = ep_string[tmp];
+ ep->ep.name = ep_info[tmp].name;
+ ep->ep.caps = ep_info[tmp].caps;
ep->num = tmp;
/* txfifo size is calculated at enable time */
ep->txfifo = dev->txfifo;
diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
index fc42264..d0d1894 100644
--- a/drivers/usb/gadget/udc/at91_udc.c
+++ b/drivers/usb/gadget/udc/at91_udc.c
@@ -59,15 +59,34 @@
#define DRIVER_VERSION "3 May 2006"
static const char driver_name [] = "at91_udc";
-static const char * const ep_names[] = {
- "ep0",
- "ep1",
- "ep2",
- "ep3-int",
- "ep4",
- "ep5",
+
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+ EP_INFO("ep0",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep2",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep3-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep4",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep5",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+
+#undef EP_INFO
};
-#define ep0name ep_names[0]
+
+#define ep0name ep_info[0].name
#define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000)
@@ -825,6 +844,7 @@
INIT_LIST_HEAD(&udc->gadget.ep_list);
INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+ udc->gadget.quirk_stall_not_supp = 1;
for (i = 0; i < NUM_ENDPOINTS; i++) {
struct at91_ep *ep = &udc->ep[i];
@@ -1830,7 +1850,8 @@
for (i = 0; i < NUM_ENDPOINTS; i++) {
ep = &udc->ep[i];
- ep->ep.name = ep_names[i];
+ ep->ep.name = ep_info[i].name;
+ ep->ep.caps = ep_info[i].caps;
ep->ep.ops = &at91_ep_ops;
ep->udc = udc;
ep->int_mask = BIT(i);
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index 4095cce..3dfada8 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -22,7 +22,6 @@
#include <linux/usb/gadget.h>
#include <linux/usb/atmel_usba_udc.h>
#include <linux/delay.h>
-#include <linux/platform_data/atmel.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
@@ -1989,6 +1988,10 @@
ep->can_isoc = of_property_read_bool(pp, "atmel,can-isoc");
ret = of_property_read_string(pp, "name", &name);
+ if (ret) {
+ dev_err(&pdev->dev, "of_probe: name error(%d)\n", ret);
+ goto err;
+ }
ep->ep.name = name;
ep->ep_regs = udc->regs + USBA_EPT_BASE(i);
@@ -2063,6 +2066,17 @@
ep->can_dma = pdata->ep[i].can_dma;
ep->can_isoc = pdata->ep[i].can_isoc;
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = ep->can_isoc;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+
if (i)
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
}
diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c
index 9db968b..8cbb003 100644
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -44,9 +44,29 @@
#define DRV_MODULE_NAME "bcm63xx_udc"
static const char bcm63xx_ep0name[] = "ep0";
-static const char *const bcm63xx_ep_name[] = {
- bcm63xx_ep0name,
- "ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int",
+
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} bcm63xx_ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+ EP_INFO(bcm63xx_ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4out-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
};
static bool use_fullspeed;
@@ -943,7 +963,8 @@
for (i = 0; i < BCM63XX_NUM_EP; i++) {
struct bcm63xx_ep *bep = &udc->bep[i];
- bep->ep.name = bcm63xx_ep_name[i];
+ bep->ep.name = bcm63xx_ep_info[i].name;
+ bep->ep.caps = bcm63xx_ep_info[i].caps;
bep->ep_num = i;
bep->ep.ops = &bcm63xx_udc_ep_ops;
list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list);
diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c
index b04980c..d1b8153 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_ep.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c
@@ -779,7 +779,7 @@
/* The current hw dequeue pointer */
tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(0));
deq_ptr_64 = tmp_32;
- tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS0(1));
+ tmp_32 = bdc_readl(bdc->regs, BDC_EPSTS1(0));
deq_ptr_64 |= ((u64)tmp_32 << 32);
/* we have the dma addr of next bd that will be fetched by hardware */
@@ -1952,12 +1952,18 @@
ep->bdc = bdc;
ep->dir = dir;
+ if (dir)
+ ep->usb_ep.caps.dir_in = true;
+ else
+ ep->usb_ep.caps.dir_out = true;
+
/* ep->ep_num is the index inside bdc_ep */
if (epnum == 1) {
ep->ep_num = 1;
bdc->bdc_ep_array[ep->ep_num] = ep;
snprintf(ep->name, sizeof(ep->name), "ep%d", epnum - 1);
usb_ep_set_maxpacket_limit(&ep->usb_ep, EP0_MAX_PKT_SIZE);
+ ep->usb_ep.caps.type_control = true;
ep->comp_desc = NULL;
bdc->gadget.ep0 = &ep->usb_ep;
} else {
@@ -1971,6 +1977,9 @@
dir & 1 ? "in" : "out");
usb_ep_set_maxpacket_limit(&ep->usb_ep, 1024);
+ ep->usb_ep.caps.type_iso = true;
+ ep->usb_ep.caps.type_bulk = true;
+ ep->usb_ep.caps.type_int = true;
ep->usb_ep.max_streams = 0;
list_add_tail(&ep->usb_ep.ep_list, &bdc->gadget.ep_list);
}
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 181112c..1379ad4 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -127,23 +127,87 @@
static const char ep0name[] = "ep0";
-static const char *const ep_name[] = {
- ep0name, /* everyone has ep0 */
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info[] = {
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+ /* everyone has ep0 */
+ EP_INFO(ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
/* act like a pxa250: fifteen fixed function endpoints */
- "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int",
- "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int",
- "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",
- "ep15in-int",
-
+ EP_INFO("ep1in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3in-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4out-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep5in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep6in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep7out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep8in-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep9out-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep10in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep11in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep12out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep13in-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep14out-iso",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep15in-int",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_INT, USB_EP_CAPS_DIR_IN)),
/* or like sa1100: two fixed function endpoints */
- "ep1out-bulk", "ep2in-bulk",
-
+ EP_INFO("ep1out-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep2in-bulk",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK, USB_EP_CAPS_DIR_IN)),
/* and now some generic EPs so we have enough in multi config */
- "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in",
- "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out",
+ EP_INFO("ep3out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep4in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep5out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep6out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep7in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep8out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep9in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep10out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep11out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep12in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep13out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep14in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep15out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+
+#undef EP_INFO
};
-#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name)
+
+#define DUMMY_ENDPOINTS ARRAY_SIZE(ep_info)
/*-------------------------------------------------------------------------*/
@@ -938,9 +1002,10 @@
for (i = 0; i < DUMMY_ENDPOINTS; i++) {
struct dummy_ep *ep = &dum->ep[i];
- if (!ep_name[i])
+ if (!ep_info[i].name)
break;
- ep->ep.name = ep_name[i];
+ ep->ep.name = ep_info[i].name;
+ ep->ep.caps = ep_info[i].caps;
ep->ep.ops = &dummy_ep_ops;
list_add_tail(&ep->ep.ep_list, &dum->gadget.ep_list);
ep->halted = ep->wedged = ep->already_seen =
@@ -1684,7 +1749,7 @@
}
for (i = 0; i < DUMMY_ENDPOINTS; i++) {
- if (!ep_name[i])
+ if (!ep_info[i].name)
break;
dum->ep[i].already_seen = 0;
}
diff --git a/drivers/usb/gadget/udc/fotg210-udc.c b/drivers/usb/gadget/udc/fotg210-udc.c
index 1137e33..6ba122c 100644
--- a/drivers/usb/gadget/udc/fotg210-udc.c
+++ b/drivers/usb/gadget/udc/fotg210-udc.c
@@ -384,25 +384,15 @@
return;
}
if (ep->dir_in) { /* if IN */
- if (req->req.length) {
- fotg210_start_dma(ep, req);
- } else {
- pr_err("%s : req->req.length = 0x%x\n",
- __func__, req->req.length);
- }
+ fotg210_start_dma(ep, req);
if ((req->req.length == req->req.actual) ||
(req->req.actual < ep->ep.maxpacket))
fotg210_done(ep, req, 0);
} else { /* OUT */
- if (!req->req.length) {
- fotg210_done(ep, req, 0);
- } else {
- u32 value = ioread32(ep->fotg210->reg +
- FOTG210_DMISGR0);
+ u32 value = ioread32(ep->fotg210->reg + FOTG210_DMISGR0);
- value &= ~DMISGR0_MCX_OUT_INT;
- iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
- }
+ value &= ~DMISGR0_MCX_OUT_INT;
+ iowrite32(value, ep->fotg210->reg + FOTG210_DMISGR0);
}
}
@@ -1153,6 +1143,17 @@
ep->ep.name = fotg210_ep_name[i];
ep->ep.ops = &fotg210_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&fotg210->ep[0]->ep, 0x40);
fotg210->gadget.ep0 = &fotg210->ep[0]->ep;
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index e0822f1..5fb6f8b 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -2417,6 +2417,17 @@
strcpy(ep->name, ep_name[pipe_num]);
ep->ep.name = ep_name[pipe_num];
+ if (pipe_num == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+
ep->ep.ops = &qe_ep_ops;
ep->stopped = 1;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index c60022b..aab5221 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2313,6 +2313,19 @@
ep->ep.ops = &fsl_ep_ops;
ep->stopped = 0;
+ if (index == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ if (index & 1)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
+
/* for ep0: maxP defined in desc
* for other eps, maxP is set by epautoconfig() called by gadget layer
*/
diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c
index 3970f45..948845c 100644
--- a/drivers/usb/gadget/udc/fusb300_udc.c
+++ b/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1450,6 +1450,17 @@
ep->ep.name = fusb300_ep_name[i];
ep->ep.ops = &fusb300_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, HS_BULK_MAX_PACKET_SIZE);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&fusb300->ep[0]->ep, HS_CTL_MAX_PACKET_SIZE);
fusb300->ep[0]->epnum = 0;
diff --git a/drivers/usb/gadget/udc/gadget_chips.h b/drivers/usb/gadget/udc/gadget_chips.h
deleted file mode 100644
index bcd04bc..0000000
--- a/drivers/usb/gadget/udc/gadget_chips.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * USB device controllers have lots of quirks. Use these macros in
- * gadget drivers or other code that needs to deal with them, and which
- * autoconfigures instead of using early binding to the hardware.
- *
- * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by
- * some config file that gets updated as new hardware is supported.
- * (And avoiding all runtime comparisons in typical one-choice configs!)
- *
- * NOTE: some of these controller drivers may not be available yet.
- * Some are available on 2.4 kernels; several are available, but not
- * yet pushed in the 2.6 mainline tree.
- */
-
-#ifndef __GADGET_CHIPS_H
-#define __GADGET_CHIPS_H
-
-#include <linux/usb/gadget.h>
-
-/*
- * NOTICE: the entries below are alphabetical and should be kept
- * that way.
- *
- * Always be sure to add new entries to the correct position or
- * accept the bashing later.
- *
- * If you have forgotten the alphabetical order let VIM/EMACS
- * do that for you.
- */
-#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name))
-#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name))
-#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name))
-#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name))
-#define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name))
-#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name))
-
-/**
- * gadget_supports_altsettings - return true if altsettings work
- * @gadget: the gadget in question
- */
-static inline bool gadget_supports_altsettings(struct usb_gadget *gadget)
-{
- /* PXA 21x/25x/26x has no altsettings at all */
- if (gadget_is_pxa(gadget))
- return false;
-
- /* PXA 27x and 3xx have *broken* altsetting support */
- if (gadget_is_pxa27x(gadget))
- return false;
-
- /* Everything else is *presumably* fine ... */
- return true;
-}
-
-#endif /* __GADGET_CHIPS_H */
diff --git a/drivers/usb/gadget/udc/goku_udc.c b/drivers/usb/gadget/udc/goku_udc.c
index 9e8d842..1fdfec1 100644
--- a/drivers/usb/gadget/udc/goku_udc.c
+++ b/drivers/usb/gadget/udc/goku_udc.c
@@ -990,6 +990,35 @@
return -EOPNOTSUPP;
}
+static struct usb_ep *goku_match_ep(struct usb_gadget *g,
+ struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ struct goku_udc *dev = to_goku_udc(g);
+ struct usb_ep *ep;
+
+ switch (usb_endpoint_type(desc)) {
+ case USB_ENDPOINT_XFER_INT:
+ /* single buffering is enough */
+ ep = &dev->ep[3].ep;
+ if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+ return ep;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ if (usb_endpoint_dir_in(desc)) {
+ /* DMA may be available */
+ ep = &dev->ep[2].ep;
+ if (usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+ return ep;
+ }
+ break;
+ default:
+ /* nothing */ ;
+ }
+
+ return NULL;
+}
+
static int goku_udc_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int goku_udc_stop(struct usb_gadget *g);
@@ -998,6 +1027,7 @@
.get_frame = goku_get_frame,
.udc_start = goku_udc_start,
.udc_stop = goku_udc_stop,
+ .match_ep = goku_match_ep,
// no remote wakeup
// not selfpowered
};
@@ -1257,6 +1287,14 @@
INIT_LIST_HEAD (&ep->queue);
ep_reset(NULL, ep);
+
+ if (i == 0)
+ ep->ep.caps.type_control = true;
+ else
+ ep->ep.caps.type_bulk = true;
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
dev->ep[0].reg_mode = NULL;
diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c
index c886887..8aa2593 100644
--- a/drivers/usb/gadget/udc/gr_udc.c
+++ b/drivers/usb/gadget/udc/gr_udc.c
@@ -2018,12 +2018,23 @@
usb_ep_set_maxpacket_limit(&ep->ep, MAX_CTRL_PL_SIZE);
ep->bytes_per_buffer = MAX_CTRL_PL_SIZE;
+
+ ep->ep.caps.type_control = true;
} else {
usb_ep_set_maxpacket_limit(&ep->ep, (u16)maxplimit);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
+
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
}
list_add_tail(&ep->ep_list, &dev->ep_list);
+ if (is_in)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
+
ep->tailbuf = dma_alloc_coherent(dev->dev, ep->ep.maxpacket_limit,
&ep->tailbuf_paddr, GFP_ATOMIC);
if (!ep->tailbuf)
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 3b6a785..00b5006 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -2575,6 +2575,8 @@
.ep = {
.name = "ep0",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 0,
@@ -2586,6 +2588,8 @@
.ep = {
.name = "ep1-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 2,
@@ -2597,6 +2601,8 @@
.ep = {
.name = "ep2-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 4,
@@ -2608,6 +2614,8 @@
.ep = {
.name = "ep3-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 6,
@@ -2619,6 +2627,8 @@
.ep = {
.name = "ep4-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 8,
@@ -2630,6 +2640,8 @@
.ep = {
.name = "ep5-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 10,
@@ -2641,6 +2653,8 @@
.ep = {
.name = "ep6-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 12,
@@ -2652,6 +2666,8 @@
.ep = {
.name = "ep7-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 14,
@@ -2663,6 +2679,8 @@
.ep = {
.name = "ep8-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 16,
@@ -2674,6 +2692,8 @@
.ep = {
.name = "ep9-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 18,
@@ -2685,6 +2705,8 @@
.ep = {
.name = "ep10-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 20,
@@ -2696,6 +2718,8 @@
.ep = {
.name = "ep11-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 22,
@@ -2707,6 +2731,8 @@
.ep = {
.name = "ep12-iso",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 24,
@@ -2718,6 +2744,8 @@
.ep = {
.name = "ep13-int",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_INT,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 26,
@@ -2729,6 +2757,8 @@
.ep = {
.name = "ep14-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 64,
.hwep_num_base = 28,
@@ -2740,6 +2770,8 @@
.ep = {
.name = "ep15-bulk",
.ops = &lpc32xx_ep_ops,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.maxpacket = 1023,
.hwep_num_base = 30,
diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
index 309706f..b1cfa96 100644
--- a/drivers/usb/gadget/udc/m66592-udc.c
+++ b/drivers/usb/gadget/udc/m66592-udc.c
@@ -1052,7 +1052,7 @@
tmp = m66592_read(m66592, M66592_INTSTS0) &
M66592_CTSQ;
udelay(1);
- } while (tmp != M66592_CS_IDST || timeout-- > 0);
+ } while (tmp != M66592_CS_IDST && timeout-- > 0);
if (tmp == M66592_CS_IDST)
m66592_bset(m66592,
@@ -1644,6 +1644,17 @@
ep->ep.name = m66592_ep_name[i];
ep->ep.ops = &m66592_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&m66592->ep[0].ep, 64);
m66592->ep[0].pipenum = 0;
diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c
index ea35a24..4c48969 100644
--- a/drivers/usb/gadget/udc/mv_u3d_core.c
+++ b/drivers/usb/gadget/udc/mv_u3d_core.c
@@ -1324,6 +1324,9 @@
ep->ep.ops = &mv_u3d_ep_ops;
ep->wedge = 0;
usb_ep_set_maxpacket_limit(&ep->ep, MV_U3D_EP0_MAX_PKT_SIZE);
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
ep->ep_num = 0;
ep->ep.desc = &mv_u3d_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@@ -1339,14 +1342,20 @@
if (i & 1) {
snprintf(name, sizeof(name), "ep%din", i >> 1);
ep->direction = MV_U3D_EP_DIR_IN;
+ ep->ep.caps.dir_in = true;
} else {
snprintf(name, sizeof(name), "ep%dout", i >> 1);
ep->direction = MV_U3D_EP_DIR_OUT;
+ ep->ep.caps.dir_out = true;
}
ep->u3d = u3d;
strncpy(ep->name, name, sizeof(ep->name));
ep->ep.name = ep->name;
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+
ep->ep.ops = &mv_u3d_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
ep->ep_num = i / 2;
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
index d32160d..339af51 100644
--- a/drivers/usb/gadget/udc/mv_udc_core.c
+++ b/drivers/usb/gadget/udc/mv_udc_core.c
@@ -1257,6 +1257,9 @@
ep->wedge = 0;
ep->stopped = 0;
usb_ep_set_maxpacket_limit(&ep->ep, EP0_MAX_PKT_SIZE);
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
ep->ep_num = 0;
ep->ep.desc = &mv_ep0_desc;
INIT_LIST_HEAD(&ep->queue);
@@ -1269,14 +1272,20 @@
if (i % 2) {
snprintf(name, sizeof(name), "ep%din", i / 2);
ep->direction = EP_DIR_IN;
+ ep->ep.caps.dir_in = true;
} else {
snprintf(name, sizeof(name), "ep%dout", i / 2);
ep->direction = EP_DIR_OUT;
+ ep->ep.caps.dir_out = true;
}
ep->udc = udc;
strncpy(ep->name, name, sizeof(ep->name));
ep->ep.name = ep->name;
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+
ep->ep.ops = &mv_ep_ops;
ep->stopped = 0;
usb_ep_set_maxpacket_limit(&ep->ep, (unsigned short) ~0);
@@ -2167,7 +2176,7 @@
return -ENODEV;
}
- udc->phy_regs = ioremap(r->start, resource_size(r));
+ udc->phy_regs = devm_ioremap(&pdev->dev, r->start, resource_size(r));
if (udc->phy_regs == NULL) {
dev_err(&pdev->dev, "failed to map phy I/O memory\n");
return -EBUSY;
diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
index 195baf3..18f5ebd 100644
--- a/drivers/usb/gadget/udc/net2272.c
+++ b/drivers/usb/gadget/udc/net2272.c
@@ -1404,6 +1404,17 @@
else
ep->fifo_size = 64;
net2272_ep_reset(ep);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&dev->ep[0].ep, 64);
@@ -1826,9 +1837,9 @@
if (!e || u.r.wLength > 2)
goto do_stall;
if (net2272_ep_read(e, EP_RSPSET) & (1 << ENDPOINT_HALT))
- status = __constant_cpu_to_le16(1);
+ status = cpu_to_le16(1);
else
- status = __constant_cpu_to_le16(0);
+ status = cpu_to_le16(0);
/* don't bother with a request object! */
net2272_ep_write(&dev->ep[0], EP_IRQENB, 0);
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index 2bee912..cf0ed42 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -74,18 +74,57 @@
static const u32 ep_bit[9] = { 0, 17, 2, 19, 4, 1, 18, 3, 20 };
static const char ep0name[] = "ep0";
-static const char *const ep_name[] = {
- ep0name,
- "ep-a", "ep-b", "ep-c", "ep-d",
- "ep-e", "ep-f", "ep-g", "ep-h",
+
+#define EP_INFO(_name, _caps) \
+ { \
+ .name = _name, \
+ .caps = _caps, \
+ }
+
+static const struct {
+ const char *name;
+ const struct usb_ep_caps caps;
+} ep_info_dft[] = { /* Default endpoint configuration */
+ EP_INFO(ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-a",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-b",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-c",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-d",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-e",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-f",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-g",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep-h",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_ALL)),
+}, ep_info_adv[] = { /* Endpoints for usb3380 advance mode */
+ EP_INFO(ep0name,
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)),
+ EP_INFO("ep1in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep2out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep3in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep4out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep1out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep2in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
+ EP_INFO("ep3out",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_OUT)),
+ EP_INFO("ep4in",
+ USB_EP_CAPS(USB_EP_CAPS_TYPE_ALL, USB_EP_CAPS_DIR_IN)),
};
-/* Endpoint names for usb3380 advance mode */
-static const char *const ep_name_adv[] = {
- ep0name,
- "ep1in", "ep2out", "ep3in", "ep4out",
- "ep1out", "ep2in", "ep3out", "ep4in",
-};
+#undef EP_INFO
/* mode 0 == ep-{a,b,c,d} 1K fifo each
* mode 1 == ep-{a,b} 2K fifo each, ep-{c,d} unavailable
@@ -1511,6 +1550,33 @@
return 0;
}
+static struct usb_ep *net2280_match_ep(struct usb_gadget *_gadget,
+ struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ char name[8];
+ struct usb_ep *ep;
+
+ if (usb_endpoint_type(desc) == USB_ENDPOINT_XFER_INT) {
+ /* ep-e, ep-f are PIO with only 64 byte fifos */
+ ep = gadget_find_ep_by_name(_gadget, "ep-e");
+ if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+ return ep;
+ ep = gadget_find_ep_by_name(_gadget, "ep-f");
+ if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+ return ep;
+ }
+
+ /* USB3380: use same address for usb and hardware endpoints */
+ snprintf(name, sizeof(name), "ep%d%s", usb_endpoint_num(desc),
+ usb_endpoint_dir_in(desc) ? "in" : "out");
+ ep = gadget_find_ep_by_name(_gadget, name);
+ if (ep && usb_gadget_ep_match_desc(_gadget, ep, desc, ep_comp))
+ return ep;
+
+ return NULL;
+}
+
static int net2280_start(struct usb_gadget *_gadget,
struct usb_gadget_driver *driver);
static int net2280_stop(struct usb_gadget *_gadget);
@@ -1522,6 +1588,7 @@
.pullup = net2280_pullup,
.udc_start = net2280_start,
.udc_stop = net2280_stop,
+ .match_ep = net2280_match_ep,
};
/*-------------------------------------------------------------------------*/
@@ -2055,7 +2122,8 @@
for (tmp = 0; tmp < 7; tmp++) {
struct net2280_ep *ep = &dev->ep[tmp];
- ep->ep.name = ep_name[tmp];
+ ep->ep.name = ep_info_dft[tmp].name;
+ ep->ep.caps = ep_info_dft[tmp].caps;
ep->dev = dev;
ep->num = tmp;
@@ -2095,7 +2163,10 @@
for (i = 0; i < dev->n_ep; i++) {
struct net2280_ep *ep = &dev->ep[i];
- ep->ep.name = dev->enhanced_mode ? ep_name_adv[i] : ep_name[i];
+ ep->ep.name = dev->enhanced_mode ? ep_info_adv[i].name :
+ ep_info_dft[i].name;
+ ep->ep.caps = dev->enhanced_mode ? ep_info_adv[i].caps :
+ ep_info_dft[i].caps;
ep->dev = dev;
ep->num = i;
diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
index e2fcdb8..9b7d394 100644
--- a/drivers/usb/gadget/udc/omap_udc.c
+++ b/drivers/usb/gadget/udc/omap_udc.c
@@ -2579,6 +2579,28 @@
ep->double_buf = dbuf;
ep->udc = udc;
+ switch (type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
+ break;
+ case USB_ENDPOINT_XFER_ISOC:
+ ep->ep.caps.type_iso = true;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ ep->ep.caps.type_bulk = true;
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ ep->ep.caps.type_int = true;
+ break;
+ };
+
+ if (addr & USB_DIR_IN)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
+
ep->ep.name = ep->name;
ep->ep.ops = &omap_ep_ops;
ep->maxpacket = maxp;
diff --git a/drivers/usb/gadget/udc/pch_udc.c b/drivers/usb/gadget/udc/pch_udc.c
index 613547f..e5f4c52 100644
--- a/drivers/usb/gadget/udc/pch_udc.c
+++ b/drivers/usb/gadget/udc/pch_udc.c
@@ -620,9 +620,9 @@
dev->vbus_session = 1;
} else {
if (dev->driver && dev->driver->disconnect) {
- spin_unlock(&dev->lock);
- dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_unlock(&dev->lock);
}
pch_udc_set_disconnect(dev);
dev->vbus_session = 0;
@@ -1191,9 +1191,9 @@
pch_udc_reconnect(dev);
} else {
if (dev->driver && dev->driver->disconnect) {
- spin_unlock(&dev->lock);
- dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_unlock(&dev->lock);
}
pch_udc_set_disconnect(dev);
}
@@ -1488,11 +1488,11 @@
req->dma_mapped = 0;
}
ep->halted = 1;
- spin_unlock(&dev->lock);
+ spin_lock(&dev->lock);
if (!ep->in)
pch_udc_ep_clear_rrdy(ep);
usb_gadget_giveback_request(&ep->ep, &req->req);
- spin_lock(&dev->lock);
+ spin_unlock(&dev->lock);
ep->halted = halted;
}
@@ -1793,7 +1793,7 @@
}
/* prevent from using desc. - set HOST BUSY */
dma_desc->status |= PCH_UDC_BS_HST_BSY;
- dma_desc->dataptr = __constant_cpu_to_le32(DMA_ADDR_INVALID);
+ dma_desc->dataptr = cpu_to_le32(DMA_ADDR_INVALID);
req->td_data = dma_desc;
req->td_data_last = dma_desc;
req->chain_len = 1;
@@ -2414,7 +2414,7 @@
dev->gadget.ep0 = &dev->ep[UDC_EP0IN_IDX].ep;
else /* OUT */
dev->gadget.ep0 = &ep->ep;
- spin_unlock(&dev->lock);
+ spin_lock(&dev->lock);
/* If Mass storage Reset */
if ((dev->setup_data.bRequestType == 0x21) &&
(dev->setup_data.bRequest == 0xFF))
@@ -2422,7 +2422,7 @@
/* call gadget with setup data received */
setup_supported = dev->driver->setup(&dev->gadget,
&dev->setup_data);
- spin_lock(&dev->lock);
+ spin_unlock(&dev->lock);
if (dev->setup_data.bRequestType & USB_DIR_IN) {
ep->td_data->status = (ep->td_data->status &
@@ -2594,9 +2594,9 @@
empty_req_queue(ep);
}
if (dev->driver) {
- spin_unlock(&dev->lock);
- usb_gadget_udc_reset(&dev->gadget, dev->driver);
spin_lock(&dev->lock);
+ usb_gadget_udc_reset(&dev->gadget, dev->driver);
+ spin_unlock(&dev->lock);
}
}
@@ -2675,9 +2675,9 @@
dev->ep[i].halted = 0;
}
dev->stall = 0;
- spin_unlock(&dev->lock);
- ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_lock(&dev->lock);
+ ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+ spin_unlock(&dev->lock);
}
/**
@@ -2712,9 +2712,9 @@
dev->stall = 0;
/* call gadget zero with setup data received */
- spin_unlock(&dev->lock);
- ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
spin_lock(&dev->lock);
+ ret = dev->driver->setup(&dev->gadget, &dev->setup_data);
+ spin_unlock(&dev->lock);
}
/**
@@ -2747,18 +2747,18 @@
if (dev_intr & UDC_DEVINT_US) {
if (dev->driver
&& dev->driver->suspend) {
- spin_unlock(&dev->lock);
- dev->driver->suspend(&dev->gadget);
spin_lock(&dev->lock);
+ dev->driver->suspend(&dev->gadget);
+ spin_unlock(&dev->lock);
}
vbus = pch_vbus_gpio_get_value(dev);
if ((dev->vbus_session == 0)
&& (vbus != 1)) {
if (dev->driver && dev->driver->disconnect) {
- spin_unlock(&dev->lock);
- dev->driver->disconnect(&dev->gadget);
spin_lock(&dev->lock);
+ dev->driver->disconnect(&dev->gadget);
+ spin_unlock(&dev->lock);
}
pch_udc_reconnect(dev);
} else if ((dev->vbus_session == 0)
@@ -2895,11 +2895,21 @@
ep->in = ~i & 1;
ep->ep.name = ep_string[i];
ep->ep.ops = &pch_udc_ep_ops;
- if (ep->in)
+ if (ep->in) {
ep->offset_addr = ep->num * UDC_EP_REG_SHIFT;
- else
+ ep->ep.caps.dir_in = true;
+ } else {
ep->offset_addr = (UDC_EPINT_OUT_SHIFT + ep->num) *
UDC_EP_REG_SHIFT;
+ ep->ep.caps.dir_out = true;
+ }
+ if (i == UDC_EP0IN_IDX || i == UDC_EP0OUT_IDX) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
/* need to set ep->ep.maxpacket and set Default Configuration?*/
usb_ep_set_maxpacket_limit(&ep->ep, UDC_BULK_MAX_PKT_SIZE);
list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
index f6cbe66..b82cb14 100644
--- a/drivers/usb/gadget/udc/pxa25x_udc.c
+++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -1176,6 +1176,7 @@
INIT_LIST_HEAD (&dev->gadget.ep_list);
INIT_LIST_HEAD (&dev->gadget.ep0->ep_list);
dev->ep0state = EP0_IDLE;
+ dev->gadget.quirk_altset_not_supp = 1;
/* basic endpoint records init */
for (i = 0; i < PXA_UDC_NUM_ENDPOINTS; i++) {
@@ -1821,6 +1822,8 @@
.name = ep0name,
.ops = &pxa25x_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.reg_udccs = &UDCCS0,
@@ -1833,6 +1836,8 @@
.name = "ep1in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1846,6 +1851,8 @@
.name = "ep2out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1861,6 +1868,8 @@
.name = "ep3in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1874,6 +1883,8 @@
.name = "ep4out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1888,6 +1899,7 @@
.name = "ep5in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
+ .caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
@@ -1903,6 +1915,8 @@
.name = "ep6in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1916,6 +1930,8 @@
.name = "ep7out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1930,6 +1946,8 @@
.name = "ep8in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1943,6 +1961,8 @@
.name = "ep9out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -1957,6 +1977,7 @@
.name = "ep10in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
+ .caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
@@ -1972,6 +1993,8 @@
.name = "ep11in-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1985,6 +2008,8 @@
.name = "ep12out-bulk",
.ops = &pxa25x_ep_ops,
.maxpacket = BULK_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = BULK_FIFO_SIZE,
@@ -1999,6 +2024,8 @@
.name = "ep13in-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_IN),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -2012,6 +2039,8 @@
.name = "ep14out-iso",
.ops = &pxa25x_ep_ops,
.maxpacket = ISO_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_ISO,
+ USB_EP_CAPS_DIR_OUT),
},
.dev = &memory,
.fifo_size = ISO_FIFO_SIZE,
@@ -2026,6 +2055,7 @@
.name = "ep15in-int",
.ops = &pxa25x_ep_ops,
.maxpacket = INT_FIFO_SIZE,
+ .caps = USB_EP_CAPS(0, 0),
},
.dev = &memory,
.fifo_size = INT_FIFO_SIZE,
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
index b51226a..670ac0b 100644
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -1710,6 +1710,7 @@
INIT_LIST_HEAD(&dev->gadget.ep_list);
INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0];
+ dev->gadget.quirk_altset_not_supp = 1;
ep0_idle(dev);
/* PXA endpoints init */
@@ -2422,7 +2423,7 @@
}
udc->udc_command = mach->udc_command;
} else {
- udc->gpiod = devm_gpiod_get(&pdev->dev, NULL);
+ udc->gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_ASIS);
}
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.h b/drivers/usb/gadget/udc/pxa27x_udc.h
index 11e1423..cea2cb7 100644
--- a/drivers/usb/gadget/udc/pxa27x_udc.h
+++ b/drivers/usb/gadget/udc/pxa27x_udc.h
@@ -234,25 +234,35 @@
/*
* Endpoint definition helpers
*/
-#define USB_EP_DEF(addr, bname, dir, type, maxpkt) \
-{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, }, \
+#define USB_EP_DEF(addr, bname, dir, type, maxpkt, ctype, cdir) \
+{ .usb_ep = { .name = bname, .ops = &pxa_ep_ops, .maxpacket = maxpkt, \
+ .caps = USB_EP_CAPS(ctype, cdir), }, \
.desc = { .bEndpointAddress = addr | (dir ? USB_DIR_IN : 0), \
- .bmAttributes = type, \
+ .bmAttributes = USB_ENDPOINT_XFER_ ## type, \
.wMaxPacketSize = maxpkt, }, \
.dev = &memory \
}
-#define USB_EP_BULK(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_BULK, BULK_FIFO_SIZE)
-#define USB_EP_ISO(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_ISOC, ISO_FIFO_SIZE)
-#define USB_EP_INT(addr, bname, dir) \
- USB_EP_DEF(addr, bname, dir, USB_ENDPOINT_XFER_INT, INT_FIFO_SIZE)
-#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1)
-#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0)
-#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1)
-#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0)
-#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1)
-#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, 0, EP0_FIFO_SIZE)
+#define USB_EP_BULK(addr, bname, dir, cdir) \
+ USB_EP_DEF(addr, bname, dir, BULK, BULK_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_BULK, cdir)
+#define USB_EP_ISO(addr, bname, dir, cdir) \
+ USB_EP_DEF(addr, bname, dir, ISOC, ISO_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_ISO, cdir)
+#define USB_EP_INT(addr, bname, dir, cdir) \
+ USB_EP_DEF(addr, bname, dir, INT, INT_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_INT, cdir)
+#define USB_EP_IN_BULK(n) USB_EP_BULK(n, "ep" #n "in-bulk", 1, \
+ USB_EP_CAPS_DIR_IN)
+#define USB_EP_OUT_BULK(n) USB_EP_BULK(n, "ep" #n "out-bulk", 0, \
+ USB_EP_CAPS_DIR_OUT)
+#define USB_EP_IN_ISO(n) USB_EP_ISO(n, "ep" #n "in-iso", 1, \
+ USB_EP_CAPS_DIR_IN)
+#define USB_EP_OUT_ISO(n) USB_EP_ISO(n, "ep" #n "out-iso", 0, \
+ USB_EP_CAPS_DIR_OUT)
+#define USB_EP_IN_INT(n) USB_EP_INT(n, "ep" #n "in-int", 1, \
+ USB_EP_CAPS_DIR_IN)
+#define USB_EP_CTRL USB_EP_DEF(0, "ep0", 0, CONTROL, EP0_FIFO_SIZE, \
+ USB_EP_CAPS_TYPE_CONTROL, USB_EP_CAPS_DIR_ALL)
#define PXA_EP_DEF(_idx, _addr, dir, _type, maxpkt, _config, iface, altset) \
{ \
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
index 0293f71..baa0609 100644
--- a/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1935,6 +1935,16 @@
ep->ep.name = r8a66597_ep_name[i];
ep->ep.ops = &r8a66597_ep_ops;
usb_ep_set_maxpacket_limit(&ep->ep, 512);
+
+ if (i == 0) {
+ ep->ep.caps.type_control = true;
+ } else {
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
+ }
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
}
usb_ep_set_maxpacket_limit(&r8a66597->ep[0].ep, 64);
r8a66597->ep[0].pipenum = 0;
diff --git a/drivers/usb/gadget/udc/s3c-hsudc.c b/drivers/usb/gadget/udc/s3c-hsudc.c
index 85a712a..e9def42 100644
--- a/drivers/usb/gadget/udc/s3c-hsudc.c
+++ b/drivers/usb/gadget/udc/s3c-hsudc.c
@@ -1005,6 +1005,21 @@
hsep->stopped = 0;
hsep->wedge = 0;
+ if (epnum == 0) {
+ hsep->ep.caps.type_control = true;
+ hsep->ep.caps.dir_in = true;
+ hsep->ep.caps.dir_out = true;
+ } else {
+ hsep->ep.caps.type_iso = true;
+ hsep->ep.caps.type_bulk = true;
+ hsep->ep.caps.type_int = true;
+ }
+
+ if (epnum & 1)
+ hsep->ep.caps.dir_in = true;
+ else
+ hsep->ep.caps.dir_out = true;
+
set_index(hsudc, epnum);
writel(hsep->ep.maxpacket, hsudc->regs + S3C_MPR);
}
diff --git a/drivers/usb/gadget/udc/s3c2410_udc.c b/drivers/usb/gadget/udc/s3c2410_udc.c
index 5d9aa81..eb3571e 100644
--- a/drivers/usb/gadget/udc/s3c2410_udc.c
+++ b/drivers/usb/gadget/udc/s3c2410_udc.c
@@ -1691,6 +1691,8 @@
.name = ep0name,
.ops = &s3c2410_ep_ops,
.maxpacket = EP0_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_CONTROL,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
},
@@ -1702,6 +1704,8 @@
.name = "ep1-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@@ -1714,6 +1718,8 @@
.name = "ep2-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@@ -1726,6 +1732,8 @@
.name = "ep3-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
@@ -1738,6 +1746,8 @@
.name = "ep4-bulk",
.ops = &s3c2410_ep_ops,
.maxpacket = EP_FIFO_SIZE,
+ .caps = USB_EP_CAPS(USB_EP_CAPS_TYPE_BULK,
+ USB_EP_CAPS_DIR_ALL),
},
.dev = &memory,
.fifo_size = EP_FIFO_SIZE,
diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c
index d69c355..f660afb 100644
--- a/drivers/usb/gadget/udc/udc-core.c
+++ b/drivers/usb/gadget/udc/udc-core.c
@@ -60,13 +60,15 @@
int usb_gadget_map_request(struct usb_gadget *gadget,
struct usb_request *req, int is_in)
{
+ struct device *dev = gadget->dev.parent;
+
if (req->length == 0)
return 0;
if (req->num_sgs) {
int mapped;
- mapped = dma_map_sg(&gadget->dev, req->sg, req->num_sgs,
+ mapped = dma_map_sg(dev, req->sg, req->num_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (mapped == 0) {
dev_err(&gadget->dev, "failed to map SGs\n");
@@ -75,11 +77,11 @@
req->num_mapped_sgs = mapped;
} else {
- req->dma = dma_map_single(&gadget->dev, req->buf, req->length,
+ req->dma = dma_map_single(dev, req->buf, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
- if (dma_mapping_error(&gadget->dev, req->dma)) {
- dev_err(&gadget->dev, "failed to map buffer\n");
+ if (dma_mapping_error(dev, req->dma)) {
+ dev_err(dev, "failed to map buffer\n");
return -EFAULT;
}
}
@@ -95,12 +97,12 @@
return;
if (req->num_mapped_sgs) {
- dma_unmap_sg(&gadget->dev, req->sg, req->num_mapped_sgs,
+ dma_unmap_sg(gadget->dev.parent, req->sg, req->num_mapped_sgs,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->num_mapped_sgs = 0;
} else {
- dma_unmap_single(&gadget->dev, req->dma, req->length,
+ dma_unmap_single(gadget->dev.parent, req->dma, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
}
}
@@ -129,6 +131,96 @@
/* ------------------------------------------------------------------------- */
+/**
+ * gadget_find_ep_by_name - returns ep whose name is the same as sting passed
+ * in second parameter or NULL if searched endpoint not found
+ * @g: controller to check for quirk
+ * @name: name of searched endpoint
+ */
+struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, const char *name)
+{
+ struct usb_ep *ep;
+
+ gadget_for_each_ep(ep, g) {
+ if (!strcmp(ep->name, name))
+ return ep;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(gadget_find_ep_by_name);
+
+/* ------------------------------------------------------------------------- */
+
+int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
+ struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ u8 type;
+ u16 max;
+ int num_req_streams = 0;
+
+ /* endpoint already claimed? */
+ if (ep->claimed)
+ return 0;
+
+ type = usb_endpoint_type(desc);
+ max = 0x7ff & usb_endpoint_maxp(desc);
+
+ if (usb_endpoint_dir_in(desc) && !ep->caps.dir_in)
+ return 0;
+ if (usb_endpoint_dir_out(desc) && !ep->caps.dir_out)
+ return 0;
+
+ if (max > ep->maxpacket_limit)
+ return 0;
+
+ /* "high bandwidth" works only at high speed */
+ if (!gadget_is_dualspeed(gadget) && usb_endpoint_maxp(desc) & (3<<11))
+ return 0;
+
+ switch (type) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ /* only support ep0 for portable CONTROL traffic */
+ return 0;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (!ep->caps.type_iso)
+ return 0;
+ /* ISO: limit 1023 bytes full speed, 1024 high/super speed */
+ if (!gadget_is_dualspeed(gadget) && max > 1023)
+ return 0;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ if (!ep->caps.type_bulk)
+ return 0;
+ if (ep_comp && gadget_is_superspeed(gadget)) {
+ /* Get the number of required streams from the
+ * EP companion descriptor and see if the EP
+ * matches it
+ */
+ num_req_streams = ep_comp->bmAttributes & 0x1f;
+ if (num_req_streams > ep->max_streams)
+ return 0;
+ }
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ /* Bulk endpoints handle interrupt transfers,
+ * except the toggle-quirky iso-synch kind
+ */
+ if (!ep->caps.type_int && !ep->caps.type_bulk)
+ return 0;
+ /* INT: limit 64 bytes full speed, 1024 high/super speed */
+ if (!gadget_is_dualspeed(gadget) && max > 64)
+ return 0;
+ break;
+ }
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(usb_gadget_ep_match_desc);
+
+/* ------------------------------------------------------------------------- */
+
static void usb_gadget_state_work(struct work_struct *work)
{
struct usb_gadget *gadget = work_to_gadget(work);
@@ -321,6 +413,7 @@
err3:
put_device(&udc->dev);
+ device_del(&gadget->dev);
err2:
put_device(&gadget->dev);
diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index 1f24274..1cbb0ac 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -1317,12 +1317,21 @@
snprintf(ep->name, EPNAME_SIZE, "ep%d", ep_number);
ep->ep_usb.name = ep->name;
ep->ep_usb.ops = &xusb_ep_ops;
+
+ ep->ep_usb.caps.type_iso = true;
+ ep->ep_usb.caps.type_bulk = true;
+ ep->ep_usb.caps.type_int = true;
} else {
ep->ep_usb.name = ep0name;
usb_ep_set_maxpacket_limit(&ep->ep_usb, EP0_MAX_PACKET);
ep->ep_usb.ops = &xusb_ep0_ops;
+
+ ep->ep_usb.caps.type_control = true;
}
+ ep->ep_usb.caps.dir_in = true;
+ ep->ep_usb.caps.dir_out = true;
+
ep->udc = udc;
ep->epnumber = ep_number;
ep->desc = NULL;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 8afc3c1..079991e 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -32,7 +32,14 @@
default y
config USB_XHCI_PLATFORM
- tristate
+ tristate "Generic xHCI driver for a platform device"
+ ---help---
+ Adds an xHCI host driver for a generic platform device, which
+ provides a memory space and an irq.
+ It is also a prerequisite for platform specific drivers that
+ implement some extra quirks.
+
+ If unsure, say N.
config USB_XHCI_MVEBU
tristate "xHCI support for Marvell Armada 375/38x"
@@ -441,10 +448,10 @@
PXA27x/PXA3xx chips.
config USB_OHCI_HCD_AT91
- tristate "Support for Atmel on-chip OHCI USB controller"
- depends on USB_OHCI_HCD && ARCH_AT91
- default y
- ---help---
+ tristate "Support for Atmel on-chip OHCI USB controller"
+ depends on USB_OHCI_HCD && ARCH_AT91 && OF
+ default y
+ ---help---
Enables support for the on-chip OHCI controller on
Atmel chips.
diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
index 526cfab..5398e3d 100644
--- a/drivers/usb/host/bcma-hcd.c
+++ b/drivers/usb/host/bcma-hcd.c
@@ -2,7 +2,8 @@
* Broadcom specific Advanced Microcontroller Bus
* Broadcom USB-core driver (BCMA bus glue)
*
- * Copyright 2011-2012 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright 2011-2015 Hauke Mehrtens <hauke@hauke-m.de>
+ * Copyright 2015 Felix Fietkau <nbd@openwrt.org>
*
* Based on ssb-ohci driver
* Copyright 2007 Michael Buesch <m@bues.ch>
@@ -23,6 +24,8 @@
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
#include <linux/usb/ehci_pdriver.h>
#include <linux/usb/ohci_pdriver.h>
@@ -88,7 +91,7 @@
}
/* based on arch/mips/brcm-boards/bcm947xx/pcibios.c */
-static void bcma_hcd_init_chip(struct bcma_device *dev)
+static void bcma_hcd_init_chip_mips(struct bcma_device *dev)
{
u32 tmp;
@@ -159,6 +162,87 @@
}
}
+static void bcma_hcd_init_chip_arm_phy(struct bcma_device *dev)
+{
+ struct bcma_device *arm_core;
+ void __iomem *dmu;
+
+ arm_core = bcma_find_core(dev->bus, BCMA_CORE_ARMCA9);
+ if (!arm_core) {
+ dev_err(&dev->dev, "can not find ARM Cortex A9 ihost core\n");
+ return;
+ }
+
+ dmu = ioremap_nocache(arm_core->addr_s[0], 0x1000);
+ if (!dmu) {
+ dev_err(&dev->dev, "can not map ARM Cortex A9 ihost core\n");
+ return;
+ }
+
+ /* Unlock DMU PLL settings */
+ iowrite32(0x0000ea68, dmu + 0x180);
+
+ /* Write USB 2.0 PLL control setting */
+ iowrite32(0x00dd10c3, dmu + 0x164);
+
+ /* Lock DMU PLL settings */
+ iowrite32(0x00000000, dmu + 0x180);
+
+ iounmap(dmu);
+}
+
+static void bcma_hcd_init_chip_arm_hc(struct bcma_device *dev)
+{
+ u32 val;
+
+ /*
+ * Delay after PHY initialized to ensure HC is ready to be configured
+ */
+ usleep_range(1000, 2000);
+
+ /* Set packet buffer OUT threshold */
+ val = bcma_read32(dev, 0x94);
+ val &= 0xffff;
+ val |= 0x80 << 16;
+ bcma_write32(dev, 0x94, val);
+
+ /* Enable break memory transfer */
+ val = bcma_read32(dev, 0x9c);
+ val |= 1;
+ bcma_write32(dev, 0x9c, val);
+}
+
+static void bcma_hcd_init_chip_arm(struct bcma_device *dev)
+{
+ bcma_core_enable(dev, 0);
+
+ if (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4707 ||
+ dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM53018) {
+ if (dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4707 ||
+ dev->bus->chipinfo.pkg == BCMA_PKG_ID_BCM4708)
+ bcma_hcd_init_chip_arm_phy(dev);
+
+ bcma_hcd_init_chip_arm_hc(dev);
+ }
+}
+
+static void bcma_hci_platform_power_gpio(struct bcma_device *dev, bool val)
+{
+ int gpio;
+
+ gpio = of_get_named_gpio(dev->dev.of_node, "vcc-gpio", 0);
+ if (!gpio_is_valid(gpio))
+ return;
+
+ if (val) {
+ gpio_request(gpio, "bcma-hcd-gpio");
+ gpio_set_value(gpio, 1);
+ } else {
+ gpio_set_value(gpio, 0);
+ gpio_free(gpio);
+ }
+}
+
static const struct usb_ehci_pdata ehci_pdata = {
};
@@ -169,7 +253,7 @@
{
struct platform_device *hci_dev;
struct resource hci_res[2];
- int ret = -ENOMEM;
+ int ret;
memset(hci_res, 0, sizeof(hci_res));
@@ -183,7 +267,7 @@
hci_dev = platform_device_alloc(ohci ? "ohci-platform" :
"ehci-platform" , 0);
if (!hci_dev)
- return NULL;
+ return ERR_PTR(-ENOMEM);
hci_dev->dev.parent = &dev->dev;
hci_dev->dev.dma_mask = &hci_dev->dev.coherent_dma_mask;
@@ -214,39 +298,45 @@
static int bcma_hcd_probe(struct bcma_device *dev)
{
int err;
- u16 chipid_top;
u32 ohci_addr;
struct bcma_hcd_device *usb_dev;
struct bcma_chipinfo *chipinfo;
chipinfo = &dev->bus->chipinfo;
- /* USBcores are only connected on embedded devices. */
- chipid_top = (chipinfo->id & 0xFF00);
- if (chipid_top != 0x4700 && chipid_top != 0x5300)
- return -ENODEV;
/* TODO: Probably need checks here; is the core connected? */
if (dma_set_mask_and_coherent(dev->dma_dev, DMA_BIT_MASK(32)))
return -EOPNOTSUPP;
- usb_dev = kzalloc(sizeof(struct bcma_hcd_device), GFP_KERNEL);
+ usb_dev = devm_kzalloc(&dev->dev, sizeof(struct bcma_hcd_device),
+ GFP_KERNEL);
if (!usb_dev)
return -ENOMEM;
- bcma_hcd_init_chip(dev);
+ bcma_hci_platform_power_gpio(dev, true);
+
+ switch (dev->id.id) {
+ case BCMA_CORE_NS_USB20:
+ bcma_hcd_init_chip_arm(dev);
+ break;
+ case BCMA_CORE_USB20_HOST:
+ bcma_hcd_init_chip_mips(dev);
+ break;
+ default:
+ return -ENODEV;
+ }
/* In AI chips EHCI is addrspace 0, OHCI is 1 */
ohci_addr = dev->addr_s[0];
- if ((chipinfo->id == 0x5357 || chipinfo->id == 0x4749)
+ if ((chipinfo->id == BCMA_CHIP_ID_BCM5357 ||
+ chipinfo->id == BCMA_CHIP_ID_BCM4749)
&& chipinfo->rev == 0)
ohci_addr = 0x18009000;
usb_dev->ohci_dev = bcma_hcd_create_pdev(dev, true, ohci_addr);
- if (IS_ERR(usb_dev->ohci_dev)) {
- err = PTR_ERR(usb_dev->ohci_dev);
- goto err_free_usb_dev;
- }
+ if (IS_ERR(usb_dev->ohci_dev))
+ return PTR_ERR(usb_dev->ohci_dev);
usb_dev->ehci_dev = bcma_hcd_create_pdev(dev, false, dev->addr);
if (IS_ERR(usb_dev->ehci_dev)) {
@@ -259,8 +349,6 @@
err_unregister_ohci_dev:
platform_device_unregister(usb_dev->ohci_dev);
-err_free_usb_dev:
- kfree(usb_dev);
return err;
}
@@ -280,6 +368,7 @@
static void bcma_hcd_shutdown(struct bcma_device *dev)
{
+ bcma_hci_platform_power_gpio(dev, false);
bcma_core_disable(dev, 0);
}
@@ -287,6 +376,7 @@
static int bcma_hcd_suspend(struct bcma_device *dev)
{
+ bcma_hci_platform_power_gpio(dev, false);
bcma_core_disable(dev, 0);
return 0;
@@ -294,6 +384,7 @@
static int bcma_hcd_resume(struct bcma_device *dev)
{
+ bcma_hci_platform_power_gpio(dev, true);
bcma_core_enable(dev, 0);
return 0;
@@ -306,6 +397,7 @@
static const struct bcma_device_id bcma_hcd_table[] = {
BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_USB20_HOST, BCMA_ANY_REV, BCMA_ANY_CLASS),
+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_USB20, BCMA_ANY_REV, BCMA_ANY_CLASS),
{},
};
MODULE_DEVICE_TABLE(bcma, bcma_hcd_table);
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 5352e74..3b6eb21 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -127,7 +127,18 @@
/* Enable USB controller, 83xx or 8536 */
if (pdata->have_sysif_regs && pdata->controller_ver < FSL_USB_VER_1_6)
- setbits32(hcd->regs + FSL_SOC_USB_CTRL, 0x4);
+ clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
+ CONTROL_REGISTER_W1C_MASK, 0x4);
+
+ /*
+ * Enable UTMI phy and program PTS field in UTMI mode before asserting
+ * controller reset for USB Controller version 2.5
+ */
+ if (pdata->has_fsl_erratum_a007792) {
+ clrsetbits_be32(hcd->regs + FSL_SOC_USB_CTRL,
+ CONTROL_REGISTER_W1C_MASK, CTRL_UTMI_PHY_EN);
+ writel(PORT_PTS_UTMI, hcd->regs + FSL_SOC_USB_PORTSC1);
+ }
/* Don't need to set host mode here. It will be done by tdi_reset() */
@@ -191,9 +202,11 @@
case FSL_USB2_PHY_ULPI:
if (pdata->have_sysif_regs && pdata->controller_ver) {
/* controller version 1.6 or above */
- clrbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
- setbits32(non_ehci + FSL_SOC_USB_CTRL,
- ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
+ clrbits32(non_ehci + FSL_SOC_USB_CTRL,
+ CONTROL_REGISTER_W1C_MASK | UTMI_PHY_EN);
+ clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
+ CONTROL_REGISTER_W1C_MASK,
+ ULPI_PHY_CLK_SEL | USB_CTRL_USB_EN);
}
portsc |= PORT_PTS_ULPI;
break;
@@ -204,30 +217,33 @@
portsc |= PORT_PTS_PTW;
/* fall through */
case FSL_USB2_PHY_UTMI:
+ case FSL_USB2_PHY_UTMI_DUAL:
if (pdata->have_sysif_regs && pdata->controller_ver) {
/* controller version 1.6 or above */
- setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
+ clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
+ CONTROL_REGISTER_W1C_MASK, UTMI_PHY_EN);
mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to
become stable - 10ms*/
}
/* enable UTMI PHY */
if (pdata->have_sysif_regs)
- setbits32(non_ehci + FSL_SOC_USB_CTRL,
- CTRL_UTMI_PHY_EN);
+ clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
+ CONTROL_REGISTER_W1C_MASK,
+ CTRL_UTMI_PHY_EN);
portsc |= PORT_PTS_UTMI;
break;
case FSL_USB2_PHY_NONE:
break;
}
- if (pdata->have_sysif_regs &&
- pdata->controller_ver > FSL_USB_VER_1_6 &&
- (phy_mode == FSL_USB2_PHY_ULPI)) {
- /* check PHY_CLK_VALID to get phy clk valid */
- if (!(spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
- PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0) ||
- in_be32(non_ehci + FSL_SOC_USB_PRICTRL))) {
- dev_warn(hcd->self.controller, "USB PHY clock invalid\n");
+ /*
+ * check PHY_CLK_VALID to determine phy clock presence before writing
+ * to portsc
+ */
+ if (pdata->check_phy_clk_valid) {
+ if (!(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID)) {
+ dev_warn(hcd->self.controller,
+ "USB PHY clock invalid\n");
return -EINVAL;
}
}
@@ -235,7 +251,8 @@
ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs)
- setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN);
+ clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL,
+ CONTROL_REGISTER_W1C_MASK, USB_CTRL_USB_EN);
return 0;
}
@@ -261,6 +278,10 @@
out_be32(non_ehci + FSL_SOC_USB_SNOOP2, 0x80000000 | SNOOP_SIZE_2GB);
}
+ /* Deal with USB erratum A-005275 */
+ if (pdata->has_fsl_erratum_a005275 == 1)
+ ehci->has_fsl_hs_errata = 1;
+
if ((pdata->operating_mode == FSL_USB2_DR_HOST) ||
(pdata->operating_mode == FSL_USB2_DR_OTG))
if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0))
diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h
index dbd292e..1a8a60a 100644
--- a/drivers/usb/host/ehci-fsl.h
+++ b/drivers/usb/host/ehci-fsl.h
@@ -52,6 +52,7 @@
#define SNOOP_SIZE_2GB 0x1e
/* control Register Bit Masks */
+#define CONTROL_REGISTER_W1C_MASK 0x00020000 /* W1C: PHY_CLK_VALID */
#define ULPI_INT_EN (1<<0)
#define WU_INT_EN (1<<1)
#define USB_CTRL_USB_EN (1<<2)
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 22abb68..086a711 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -1221,6 +1221,13 @@
*/
ehci->reset_done [wIndex] = jiffies
+ msecs_to_jiffies (50);
+
+ /*
+ * Force full-speed connect for FSL high-speed
+ * erratum; disable HS Chirp by setting PFSC bit
+ */
+ if (ehci_has_fsl_hs_errata(ehci))
+ temp |= (1 << PORTSC_FSL_PFSC);
}
ehci_writel(ehci, temp, status_reg);
break;
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 2593def..5c3c085 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -45,6 +45,7 @@
struct reset_control *rst;
struct phy **phys;
int num_phys;
+ bool reset_on_resume;
};
static const char hcd_name[] = "ehci-platform";
@@ -56,7 +57,6 @@
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
int retval;
- hcd->has_tt = pdata->has_tt;
ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug;
if (pdata->pre_setup) {
@@ -193,11 +193,11 @@
if (of_property_read_bool(dev->dev.of_node,
"needs-reset-on-resume"))
- pdata->reset_on_resume = 1;
+ priv->reset_on_resume = true;
if (of_property_read_bool(dev->dev.of_node,
"has-transaction-translator"))
- pdata->has_tt = 1;
+ hcd->has_tt = 1;
priv->num_phys = of_count_phandle_with_args(dev->dev.of_node,
"phys", "#phy-cells");
@@ -247,6 +247,10 @@
ehci->big_endian_desc = 1;
if (pdata->big_endian_mmio)
ehci->big_endian_mmio = 1;
+ if (pdata->has_tt)
+ hcd->has_tt = 1;
+ if (pdata->reset_on_resume)
+ priv->reset_on_resume = true;
#ifndef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO
if (ehci->big_endian_mmio) {
@@ -359,6 +363,7 @@
struct usb_ehci_pdata *pdata = dev_get_platdata(dev);
struct platform_device *pdev =
container_of(dev, struct platform_device, dev);
+ struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd);
if (pdata->power_on) {
int err = pdata->power_on(pdev);
@@ -366,7 +371,7 @@
return err;
}
- ehci_resume(hcd, pdata->reset_on_resume);
+ ehci_resume(hcd, priv->reset_on_resume);
return 0;
}
#endif /* CONFIG_PM_SLEEP */
diff --git a/drivers/usb/host/ehci-st.c b/drivers/usb/host/ehci-st.c
index 7e4bd39..b7c5cfa 100644
--- a/drivers/usb/host/ehci-st.c
+++ b/drivers/usb/host/ehci-st.c
@@ -54,7 +54,6 @@
struct platform_device *pdev = to_platform_device(hcd->self.controller);
struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev);
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
- int retval;
u32 threshold;
/* Set EHCI packet buffer IN/OUT threshold to 128 bytes */
@@ -62,11 +61,7 @@
writel(threshold, hcd->regs + AHB2STBUS_INSREG01);
ehci->caps = hcd->regs + pdata->caps_offset;
- retval = ehci_setup(hcd);
- if (retval)
- return retval;
-
- return 0;
+ return ehci_setup(hcd);
}
static int st_ehci_platform_power_on(struct platform_device *dev)
diff --git a/drivers/usb/host/ehci-sysfs.c b/drivers/usb/host/ehci-sysfs.c
index 5e44407..5216f2b 100644
--- a/drivers/usb/host/ehci-sysfs.c
+++ b/drivers/usb/host/ehci-sysfs.c
@@ -29,7 +29,7 @@
int count = PAGE_SIZE;
char *ptr = buf;
- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+ ehci = hcd_to_ehci(dev_get_drvdata(dev));
nports = HCS_N_PORTS(ehci->hcs_params);
for (index = 0; index < nports; ++index) {
@@ -54,7 +54,7 @@
struct ehci_hcd *ehci;
int portnum, new_owner;
- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+ ehci = hcd_to_ehci(dev_get_drvdata(dev));
new_owner = PORT_OWNER; /* Owned by companion */
if (sscanf(buf, "%d", &portnum) != 1)
return -EINVAL;
@@ -85,7 +85,7 @@
struct ehci_hcd *ehci;
int n;
- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+ ehci = hcd_to_ehci(dev_get_drvdata(dev));
n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max);
return n;
}
@@ -101,7 +101,7 @@
unsigned long flags;
ssize_t ret;
- ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
+ ehci = hcd_to_ehci(dev_get_drvdata(dev));
if (kstrtouint(buf, 0, &uframe_periodic_max) < 0)
return -EINVAL;
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index f700157..46f62e4 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -215,6 +215,7 @@
/* SILICON QUIRKS */
unsigned no_selective_suspend:1;
unsigned has_fsl_port_bug:1; /* FreeScale */
+ unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */
unsigned big_endian_mmio:1;
unsigned big_endian_desc:1;
unsigned big_endian_capbase:1;
@@ -686,6 +687,17 @@
#define ehci_has_fsl_portno_bug(e) (0)
#endif
+#define PORTSC_FSL_PFSC 24 /* Port Force Full-Speed Connect */
+
+#if defined(CONFIG_PPC_85xx)
+/* Some Freescale processors have an erratum (USB A-005275) in which
+ * incoming packets get corrupted in HS mode
+ */
+#define ehci_has_fsl_hs_errata(e) ((e)->has_fsl_hs_errata)
+#else
+#define ehci_has_fsl_hs_errata(e) (0)
+#endif
+
/*
* While most USB host controllers implement their registers in
* little-endian format, a minority (celleb companion chip) implement
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 5e0d600..534c4c5 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -69,6 +69,8 @@
return FSL_USB2_PHY_UTMI;
if (!strcasecmp(phy_type, "utmi_wide"))
return FSL_USB2_PHY_UTMI_WIDE;
+ if (!strcasecmp(phy_type, "utmi_dual"))
+ return FSL_USB2_PHY_UTMI_DUAL;
if (!strcasecmp(phy_type, "serial"))
return FSL_USB2_PHY_SERIAL;
@@ -119,9 +121,9 @@
static const struct of_device_id fsl_usb2_mph_dr_of_match[];
-static int usb_get_ver_info(struct device_node *np)
+static enum fsl_usb2_controller_ver usb_get_ver_info(struct device_node *np)
{
- int ver = -1;
+ enum fsl_usb2_controller_ver ver = FSL_USB_VER_NONE;
/*
* returns 1 for usb controller version 1.6
@@ -142,7 +144,7 @@
else /* for previous controller versions */
ver = FSL_USB_VER_OLD;
- if (ver > -1)
+ if (ver > FSL_USB_VER_NONE)
return ver;
}
@@ -214,8 +216,27 @@
pdata->phy_mode = determine_usb_phy(prop);
pdata->controller_ver = usb_get_ver_info(np);
+ /* Activate Erratum by reading property in device tree */
+ if (of_get_property(np, "fsl,usb-erratum-a007792", NULL))
+ pdata->has_fsl_erratum_a007792 = 1;
+ else
+ pdata->has_fsl_erratum_a007792 = 0;
+ if (of_get_property(np, "fsl,usb-erratum-a005275", NULL))
+ pdata->has_fsl_erratum_a005275 = 1;
+ else
+ pdata->has_fsl_erratum_a005275 = 0;
+
+ /*
+ * Determine whether phy_clk_valid needs to be checked
+ * by reading property in device tree
+ */
+ if (of_get_property(np, "phy-clk-valid", NULL))
+ pdata->check_phy_clk_valid = 1;
+ else
+ pdata->check_phy_clk_valid = 0;
+
if (pdata->have_sysif_regs) {
- if (pdata->controller_ver < 0) {
+ if (pdata->controller_ver == FSL_USB_VER_NONE) {
dev_warn(&ofdev->dev, "Could not get controller version\n");
return -ENODEV;
}
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index 15df00c..342ffd1 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -36,6 +36,17 @@
#define hcd_to_ohci_at91_priv(h) \
((struct ohci_at91_priv *)hcd_to_ohci(h)->priv)
+#define AT91_MAX_USBH_PORTS 3
+struct at91_usbh_data {
+ int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */
+ int overcurrent_pin[AT91_MAX_USBH_PORTS];
+ u8 ports; /* number of ports on root hub */
+ u8 overcurrent_supported;
+ u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
+ u8 overcurrent_status[AT91_MAX_USBH_PORTS];
+ u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
+};
+
struct ohci_at91_priv {
struct clk *iclk;
struct clk *fclk;
@@ -431,7 +442,6 @@
return IRQ_HANDLED;
}
-#ifdef CONFIG_OF
static const struct of_device_id at91_ohci_dt_ids[] = {
{ .compatible = "atmel,at91rm9200-ohci" },
{ /* sentinel */ }
@@ -439,16 +449,17 @@
MODULE_DEVICE_TABLE(of, at91_ohci_dt_ids);
-static int ohci_at91_of_init(struct platform_device *pdev)
+/*-------------------------------------------------------------------------*/
+
+static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
- int i, gpio, ret;
- enum of_gpio_flags flags;
struct at91_usbh_data *pdata;
- u32 ports;
-
- if (!np)
- return 0;
+ int i;
+ int gpio;
+ int ret;
+ enum of_gpio_flags flags;
+ u32 ports;
/* Right now device-tree probed devices don't get dma_mask set.
* Since shared usb code relies on it, set it here for now.
@@ -466,111 +477,83 @@
pdata->ports = ports;
at91_for_each_port(i) {
- gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i, &flags);
+ /*
+ * do not configure PIO if not in relation with
+ * real USB port on board
+ */
+ if (i >= pdata->ports) {
+ pdata->vbus_pin[i] = -EINVAL;
+ continue;
+ }
+
+ gpio = of_get_named_gpio_flags(np, "atmel,vbus-gpio", i,
+ &flags);
pdata->vbus_pin[i] = gpio;
if (!gpio_is_valid(gpio))
continue;
pdata->vbus_pin_active_low[i] = flags & OF_GPIO_ACTIVE_LOW;
+
+ ret = gpio_request(gpio, "ohci_vbus");
+ if (ret) {
+ dev_err(&pdev->dev,
+ "can't request vbus gpio %d\n", gpio);
+ continue;
+ }
+ ret = gpio_direction_output(gpio,
+ !pdata->vbus_pin_active_low[i]);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "can't put vbus gpio %d as output %d\n",
+ gpio, !pdata->vbus_pin_active_low[i]);
+ gpio_free(gpio);
+ continue;
+ }
+
+ ohci_at91_usb_set_power(pdata, i, 1);
}
- at91_for_each_port(i)
+ at91_for_each_port(i) {
+ if (i >= pdata->ports) {
+ pdata->overcurrent_pin[i] = -EINVAL;
+ continue;
+ }
+
pdata->overcurrent_pin[i] =
of_get_named_gpio_flags(np, "atmel,oc-gpio", i, &flags);
- pdev->dev.platform_data = pdata;
+ if (!gpio_is_valid(pdata->overcurrent_pin[i]))
+ continue;
+ gpio = pdata->overcurrent_pin[i];
- return 0;
-}
-#else
-static int ohci_at91_of_init(struct platform_device *pdev)
-{
- return 0;
-}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-static int ohci_hcd_at91_drv_probe(struct platform_device *pdev)
-{
- struct at91_usbh_data *pdata;
- int i;
- int gpio;
- int ret;
-
- ret = ohci_at91_of_init(pdev);
- if (ret)
- return ret;
-
- pdata = dev_get_platdata(&pdev->dev);
-
- if (pdata) {
- at91_for_each_port(i) {
- /*
- * do not configure PIO if not in relation with
- * real USB port on board
- */
- if (i >= pdata->ports) {
- pdata->vbus_pin[i] = -EINVAL;
- pdata->overcurrent_pin[i] = -EINVAL;
- break;
- }
-
- if (!gpio_is_valid(pdata->vbus_pin[i]))
- continue;
- gpio = pdata->vbus_pin[i];
-
- ret = gpio_request(gpio, "ohci_vbus");
- if (ret) {
- dev_err(&pdev->dev,
- "can't request vbus gpio %d\n", gpio);
- continue;
- }
- ret = gpio_direction_output(gpio,
- !pdata->vbus_pin_active_low[i]);
- if (ret) {
- dev_err(&pdev->dev,
- "can't put vbus gpio %d as output %d\n",
- gpio, !pdata->vbus_pin_active_low[i]);
- gpio_free(gpio);
- continue;
- }
-
- ohci_at91_usb_set_power(pdata, i, 1);
+ ret = gpio_request(gpio, "ohci_overcurrent");
+ if (ret) {
+ dev_err(&pdev->dev,
+ "can't request overcurrent gpio %d\n",
+ gpio);
+ continue;
}
- at91_for_each_port(i) {
- if (!gpio_is_valid(pdata->overcurrent_pin[i]))
- continue;
- gpio = pdata->overcurrent_pin[i];
+ ret = gpio_direction_input(gpio);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "can't configure overcurrent gpio %d as input\n",
+ gpio);
+ gpio_free(gpio);
+ continue;
+ }
- ret = gpio_request(gpio, "ohci_overcurrent");
- if (ret) {
- dev_err(&pdev->dev,
- "can't request overcurrent gpio %d\n",
- gpio);
- continue;
- }
-
- ret = gpio_direction_input(gpio);
- if (ret) {
- dev_err(&pdev->dev,
- "can't configure overcurrent gpio %d as input\n",
- gpio);
- gpio_free(gpio);
- continue;
- }
-
- ret = request_irq(gpio_to_irq(gpio),
- ohci_hcd_at91_overcurrent_irq,
- IRQF_SHARED, "ohci_overcurrent", pdev);
- if (ret) {
- gpio_free(gpio);
- dev_err(&pdev->dev,
- "can't get gpio IRQ for overcurrent\n");
- }
+ ret = request_irq(gpio_to_irq(gpio),
+ ohci_hcd_at91_overcurrent_irq,
+ IRQF_SHARED, "ohci_overcurrent", pdev);
+ if (ret) {
+ gpio_free(gpio);
+ dev_err(&pdev->dev,
+ "can't get gpio IRQ for overcurrent\n");
}
}
+ pdev->dev.platform_data = pdata;
+
device_init_wakeup(&pdev->dev, 1);
return usb_hcd_at91_probe(&ohci_at91_hc_driver, pdev);
}
@@ -673,7 +656,7 @@
.driver = {
.name = "at91_ohci",
.pm = &ohci_hcd_at91_pm_ops,
- .of_match_table = of_match_ptr(at91_ohci_dt_ids),
+ .of_match_table = at91_ohci_dt_ids,
},
};
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index f7d561e..d029bbe 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -981,10 +981,6 @@
int completed, modified;
__hc32 *prev;
- /* Is this ED already invisible to the hardware? */
- if (ed->state == ED_IDLE)
- goto ed_idle;
-
/* only take off EDs that the HC isn't using, accounting for
* frame counter wraps and EDs with partially retired TDs
*/
@@ -1012,12 +1008,10 @@
}
/* ED's now officially unlinked, hc doesn't see */
- ed->state = ED_IDLE;
ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H);
ed->hwNextED = 0;
wmb();
ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE);
-ed_idle:
/* reentrancy: if we drop the schedule lock, someone might
* have modified this list. normally it's just prepending
@@ -1088,6 +1082,7 @@
if (list_empty(&ed->td_list)) {
*last = ed->ed_next;
ed->ed_next = NULL;
+ ed->state = ED_IDLE;
list_del(&ed->in_use_list);
} else if (ohci->rh_state == OHCI_RH_RUNNING) {
*last = ed->ed_next;
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index e9a6eec..cfcfadf 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -58,7 +58,7 @@
#define CCR_PM_CKRNEN 0x0002
#define CCR_PM_USBPW1 0x0004
#define CCR_PM_USBPW2 0x0008
-#define CCR_PM_USBPW3 0x0008
+#define CCR_PM_USBPW3 0x0010
#define CCR_PM_PMEE 0x0100
#define CCR_PM_PMES 0x8000
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index 6352f54..fe3bd1c 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -2670,7 +2670,6 @@
static int oxu_reset(struct usb_hcd *hcd)
{
struct oxu_hcd *oxu = hcd_to_oxu(hcd);
- int ret;
spin_lock_init(&oxu->mem_lock);
INIT_LIST_HEAD(&oxu->urb_list);
@@ -2696,11 +2695,7 @@
oxu->hcs_params = readl(&oxu->caps->hcs_params);
oxu->sbrn = 0x20;
- ret = oxu_hcd_init(hcd);
- if (ret)
- return ret;
-
- return 0;
+ return oxu_hcd_init(hcd);
}
static int oxu_run(struct usb_hcd *hcd)
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index d516877..a67bd50 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -1542,11 +1542,8 @@
(fit ^ FIT) | u132->hc_fminterval);
if (retval)
return retval;
- retval = u132_write_pcimem(u132, periodicstart,
- ((9 * fi) / 10) & 0x3fff);
- if (retval)
- return retval;
- return 0;
+ return u132_write_pcimem(u132, periodicstart,
+ ((9 * fi) / 10) & 0x3fff);
}
static char *hcfs2string(int state)
@@ -2701,28 +2698,18 @@
if (wIndex == 0 || wIndex > u132->num_ports) {
return -EINVAL;
} else {
- int retval;
int port_index = wIndex - 1;
struct u132_port *port = &u132->port[port_index];
port->Status &= ~(1 << wValue);
switch (wValue) {
case USB_PORT_FEAT_SUSPEND:
- retval = u132_write_pcimem(u132,
- roothub.portstatus[port_index], RH_PS_PSS);
- if (retval)
- return retval;
- return 0;
+ return u132_write_pcimem(u132,
+ roothub.portstatus[port_index], RH_PS_PSS);
case USB_PORT_FEAT_POWER:
- retval = u132_write_pcimem(u132,
- roothub.portstatus[port_index], RH_PS_PPS);
- if (retval)
- return retval;
- return 0;
+ return u132_write_pcimem(u132,
+ roothub.portstatus[port_index], RH_PS_PPS);
case USB_PORT_FEAT_RESET:
- retval = u132_roothub_portreset(u132, port_index);
- if (retval)
- return retval;
- return 0;
+ return u132_roothub_portreset(u132, port_index);
default:
return -EPIPE;
}
@@ -2737,7 +2724,6 @@
} else {
int port_index = wIndex - 1;
u32 temp;
- int retval;
struct u132_port *port = &u132->port[port_index];
port->Status &= ~(1 << wValue);
switch (wValue) {
@@ -2773,11 +2759,8 @@
default:
return -EPIPE;
}
- retval = u132_write_pcimem(u132, roothub.portstatus[port_index],
- temp);
- if (retval)
- return retval;
- return 0;
+ return u132_write_pcimem(u132, roothub.portstatus[port_index],
+ temp);
}
}
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 745717e..2d16fae 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -99,6 +99,10 @@
xhci_dbg(xhci, "HCC PARAMS 0x%x:\n", (unsigned int) temp);
xhci_dbg(xhci, " HC generates %s bit addresses\n",
HCC_64BIT_ADDR(temp) ? "64" : "32");
+ xhci_dbg(xhci, " HC %s Contiguous Frame ID Capability\n",
+ HCC_CFC(temp) ? "has" : "hasn't");
+ xhci_dbg(xhci, " HC %s generate Stopped - Short Package event\n",
+ HCC_SPC(temp) ? "can" : "can't");
/* FIXME */
xhci_dbg(xhci, " FIXME: more HCCPARAMS debugging\n");
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index e75c565..78241b5 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -484,10 +484,13 @@
u32 pls = status_reg & PORT_PLS_MASK;
/* resume state is a xHCI internal state.
- * Do not report it to usb core.
+ * Do not report it to usb core, instead, pretend to be U3,
+ * thus usb core knows it's not ready for transfer
*/
- if (pls == XDEV_RESUME)
+ if (pls == XDEV_RESUME) {
+ *status |= USB_SS_PORT_LS_U3;
return;
+ }
/* When the CAS bit is set then warm reset
* should be performed on port
@@ -588,7 +591,14 @@
status |= USB_PORT_STAT_C_RESET << 16;
/* USB3.0 only */
if (hcd->speed == HCD_USB3) {
- if ((raw_port_status & PORT_PLC))
+ /* Port link change with port in resume state should not be
+ * reported to usbcore, as this is an internal state to be
+ * handled by xhci driver. Reporting PLC to usbcore may
+ * cause usbcore clearing PLC first and port change event
+ * irq won't be generated.
+ */
+ if ((raw_port_status & PORT_PLC) &&
+ (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME)
status |= USB_PORT_STAT_C_LINK_STATE << 16;
if ((raw_port_status & PORT_WRC))
status |= USB_PORT_STAT_C_BH_RESET << 16;
@@ -1120,10 +1130,10 @@
spin_lock_irqsave(&xhci->lock, flags);
if (hcd->self.root_hub->do_remote_wakeup) {
- if (bus_state->resuming_ports) {
+ if (bus_state->resuming_ports || /* USB2 */
+ bus_state->port_remote_wakeup) { /* USB3 */
spin_unlock_irqrestore(&xhci->lock, flags);
- xhci_dbg(xhci, "suspend failed because "
- "a port is resuming\n");
+ xhci_dbg(xhci, "suspend failed because a port is resuming\n");
return -EBUSY;
}
}
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index f833640..9a8c936 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1427,10 +1427,10 @@
/* Attempt to use the ring cache */
if (virt_dev->num_rings_cached == 0)
return -ENOMEM;
+ virt_dev->num_rings_cached--;
virt_dev->eps[ep_index].new_ring =
virt_dev->ring_cache[virt_dev->num_rings_cached];
virt_dev->ring_cache[virt_dev->num_rings_cached] = NULL;
- virt_dev->num_rings_cached--;
xhci_reinit_cached_ring(xhci, virt_dev->eps[ep_index].new_ring,
1, type);
}
@@ -1792,7 +1792,8 @@
int size;
int i, j, num_ports;
- del_timer_sync(&xhci->cmd_timer);
+ if (timer_pending(&xhci->cmd_timer))
+ del_timer_sync(&xhci->cmd_timer);
/* Free the Event Ring Segment Table and the actual Event Ring */
size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 4a4cb1d..5590eac 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -23,10 +23,15 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/module.h>
+#include <linux/acpi.h>
#include "xhci.h"
#include "xhci-trace.h"
+#define PORT2_SSIC_CONFIG_REG2 0x883c
+#define PROG_DONE (1 << 30)
+#define SSIC_PORT_UNUSED (1 << 31)
+
/* Device for a quirk */
#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
@@ -176,20 +181,63 @@
}
/*
+ * In some Intel xHCI controllers, in order to get D3 working,
+ * through a vendor specific SSIC CONFIG register at offset 0x883c,
+ * SSIC PORT need to be marked as "unused" before putting xHCI
+ * into D3. After D3 exit, the SSIC port need to be marked as "used".
+ * Without this change, xHCI might not enter D3 state.
* Make sure PME works on some Intel xHCI controllers by writing 1 to clear
* the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
*/
-static void xhci_pme_quirk(struct xhci_hcd *xhci)
+static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
{
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
u32 val;
void __iomem *reg;
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
+
+ reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
+
+ /* Notify SSIC that SSIC profile programming is not done */
+ val = readl(reg) & ~PROG_DONE;
+ writel(val, reg);
+
+ /* Mark SSIC port as unused(suspend) or used(resume) */
+ val = readl(reg);
+ if (suspend)
+ val |= SSIC_PORT_UNUSED;
+ else
+ val &= ~SSIC_PORT_UNUSED;
+ writel(val, reg);
+
+ /* Notify SSIC that SSIC profile programming is done */
+ val = readl(reg) | PROG_DONE;
+ writel(val, reg);
+ readl(reg);
+ }
+
reg = (void __iomem *) xhci->cap_regs + 0x80a4;
val = readl(reg);
writel(val | BIT(28), reg);
readl(reg);
}
+#ifdef CONFIG_ACPI
+static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
+{
+ static const u8 intel_dsm_uuid[] = {
+ 0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45,
+ 0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23,
+ };
+ acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1, NULL);
+}
+#else
+ static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
+#endif /* CONFIG_ACPI */
+
/* called during probe() after chip reset completes */
static int xhci_pci_setup(struct usb_hcd *hcd)
{
@@ -263,6 +311,9 @@
HCC_MAX_PSA(xhci->hcc_params) >= 4)
xhci->shared_hcd->can_do_streams = 1;
+ if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
+ xhci_pme_acpi_rtd3_enable(dev);
+
/* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
pm_runtime_put_noidle(&dev->dev);
@@ -307,7 +358,7 @@
pdev->no_d3cold = true;
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
- xhci_pme_quirk(xhci);
+ xhci_pme_quirk(hcd, true);
return xhci_suspend(xhci, do_wakeup);
}
@@ -340,7 +391,7 @@
usb_enable_intel_xhci_ports(pdev);
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
- xhci_pme_quirk(xhci);
+ xhci_pme_quirk(hcd, false);
retval = xhci_resume(xhci, hibernated);
return retval;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 94416ff..a47a1e8 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -82,7 +82,7 @@
return 0;
/* offset in TRBs */
segment_offset = trb - seg->trbs;
- if (segment_offset > TRBS_PER_SEGMENT)
+ if (segment_offset >= TRBS_PER_SEGMENT)
return 0;
return seg->dma + (segment_offset * sizeof(*trb));
}
@@ -1546,6 +1546,9 @@
usb_hcd_resume_root_hub(hcd);
}
+ if (hcd->speed == HCD_USB3 && (temp & PORT_PLS_MASK) == XDEV_INACTIVE)
+ bus_state->port_remote_wakeup &= ~(1 << faked_port_index);
+
if ((temp & PORT_PLC) && (temp & PORT_PLS_MASK) == XDEV_RESUME) {
xhci_dbg(xhci, "port resume event for port %d\n", port_id);
@@ -1809,7 +1812,9 @@
if (skip)
goto td_cleanup;
- if (trb_comp_code == COMP_STOP_INVAL || trb_comp_code == COMP_STOP) {
+ if (trb_comp_code == COMP_STOP_INVAL ||
+ trb_comp_code == COMP_STOP ||
+ trb_comp_code == COMP_STOP_SHORT) {
/* The Endpoint Stop Command completion will take care of any
* stopped TDs. A stopped TD may be restarted, so don't update
* the ring dequeue pointer or take this TD off any lists yet.
@@ -1916,8 +1921,22 @@
else
*status = 0;
break;
- case COMP_STOP_INVAL:
+ case COMP_STOP_SHORT:
+ if (event_trb == ep_ring->dequeue || event_trb == td->last_trb)
+ xhci_warn(xhci, "WARN: Stopped Short Packet on ctrl setup or status TRB\n");
+ else
+ td->urb->actual_length =
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+ return finish_td(xhci, td, event_trb, event, ep, status, false);
case COMP_STOP:
+ /* Did we stop at data stage? */
+ if (event_trb != ep_ring->dequeue && event_trb != td->last_trb)
+ td->urb->actual_length =
+ td->urb->transfer_buffer_length -
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+ /* fall through */
+ case COMP_STOP_INVAL:
return finish_td(xhci, td, event_trb, event, ep, status, false);
default:
if (!xhci_requires_manual_halt_cleanup(xhci,
@@ -2011,6 +2030,8 @@
}
if ((xhci->quirks & XHCI_TRUST_TX_LENGTH))
trb_comp_code = COMP_SHORT_TX;
+ /* fallthrough */
+ case COMP_STOP_SHORT:
case COMP_SHORT_TX:
frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ?
-EREMOTEIO : 0;
@@ -2046,6 +2067,10 @@
if (trb_comp_code == COMP_SUCCESS || skip_td) {
frame->actual_length = frame->length;
td->urb->actual_length += frame->length;
+ } else if (trb_comp_code == COMP_STOP_SHORT) {
+ frame->actual_length =
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+ td->urb->actual_length += frame->actual_length;
} else {
for (cur_trb = ep_ring->dequeue,
cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
@@ -2126,6 +2151,7 @@
*status = 0;
}
break;
+ case COMP_STOP_SHORT:
case COMP_SHORT_TX:
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
*status = -EREMOTEIO;
@@ -2142,8 +2168,20 @@
td->urb->ep->desc.bEndpointAddress,
td->urb->transfer_buffer_length,
EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
+ /* Stopped - short packet completion */
+ if (trb_comp_code == COMP_STOP_SHORT) {
+ td->urb->actual_length =
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
+
+ if (td->urb->transfer_buffer_length <
+ td->urb->actual_length) {
+ xhci_warn(xhci, "HC gave bad length of %d bytes txed\n",
+ EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
+ td->urb->actual_length = 0;
+ /* status will be set by usb core for canceled urbs */
+ }
/* Fast path - was this the last TRB in the TD for this URB? */
- if (event_trb == td->last_trb) {
+ } else if (event_trb == td->last_trb) {
if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
td->urb->actual_length =
td->urb->transfer_buffer_length -
@@ -2297,6 +2335,9 @@
case COMP_STOP_INVAL:
xhci_dbg(xhci, "Stopped on No-op or Link TRB\n");
break;
+ case COMP_STOP_SHORT:
+ xhci_dbg(xhci, "Stopped with short packet transfer detected\n");
+ break;
case COMP_STALL:
xhci_dbg(xhci, "Stalled endpoint\n");
ep->ep_state |= EP_HALTED;
@@ -3038,9 +3079,11 @@
struct xhci_td *td;
struct scatterlist *sg;
int num_sgs;
- int trb_buff_len, this_sg_len, running_total;
+ int trb_buff_len, this_sg_len, running_total, ret;
unsigned int total_packet_count;
+ bool zero_length_needed;
bool first_trb;
+ int last_trb_num;
u64 addr;
bool more_trbs_coming;
@@ -3056,13 +3099,27 @@
total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length,
usb_endpoint_maxp(&urb->ep->desc));
- trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id],
+ ret = prepare_transfer(xhci, xhci->devs[slot_id],
ep_index, urb->stream_id,
num_trbs, urb, 0, mem_flags);
- if (trb_buff_len < 0)
- return trb_buff_len;
+ if (ret < 0)
+ return ret;
urb_priv = urb->hcpriv;
+
+ /* Deal with URB_ZERO_PACKET - need one more td/trb */
+ zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET &&
+ urb_priv->length == 2;
+ if (zero_length_needed) {
+ num_trbs++;
+ xhci_dbg(xhci, "Creating zero length td.\n");
+ ret = prepare_transfer(xhci, xhci->devs[slot_id],
+ ep_index, urb->stream_id,
+ 1, urb, 1, mem_flags);
+ if (ret < 0)
+ return ret;
+ }
+
td = urb_priv->td[0];
/*
@@ -3092,6 +3149,7 @@
trb_buff_len = urb->transfer_buffer_length;
first_trb = true;
+ last_trb_num = zero_length_needed ? 2 : 1;
/* Queue the first TRB, even if it's zero-length */
do {
u32 field = 0;
@@ -3109,12 +3167,15 @@
/* Chain all the TRBs together; clear the chain bit in the last
* TRB to indicate it's the last TRB in the chain.
*/
- if (num_trbs > 1) {
+ if (num_trbs > last_trb_num) {
field |= TRB_CHAIN;
- } else {
- /* FIXME - add check for ZERO_PACKET flag before this */
+ } else if (num_trbs == last_trb_num) {
td->last_trb = ep_ring->enqueue;
field |= TRB_IOC;
+ } else if (zero_length_needed && num_trbs == 1) {
+ trb_buff_len = 0;
+ urb_priv->td[1]->last_trb = ep_ring->enqueue;
+ field |= TRB_IOC;
}
/* Only set interrupt on short packet for IN endpoints */
@@ -3176,7 +3237,7 @@
if (running_total + trb_buff_len > urb->transfer_buffer_length)
trb_buff_len =
urb->transfer_buffer_length - running_total;
- } while (running_total < urb->transfer_buffer_length);
+ } while (num_trbs > 0);
check_trb_math(urb, num_trbs, running_total);
giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
@@ -3194,7 +3255,9 @@
int num_trbs;
struct xhci_generic_trb *start_trb;
bool first_trb;
+ int last_trb_num;
bool more_trbs_coming;
+ bool zero_length_needed;
int start_cycle;
u32 field, length_field;
@@ -3225,7 +3288,6 @@
num_trbs++;
running_total += TRB_MAX_BUFF_SIZE;
}
- /* FIXME: this doesn't deal with URB_ZERO_PACKET - need one more */
ret = prepare_transfer(xhci, xhci->devs[slot_id],
ep_index, urb->stream_id,
@@ -3234,6 +3296,20 @@
return ret;
urb_priv = urb->hcpriv;
+
+ /* Deal with URB_ZERO_PACKET - need one more td/trb */
+ zero_length_needed = urb->transfer_flags & URB_ZERO_PACKET &&
+ urb_priv->length == 2;
+ if (zero_length_needed) {
+ num_trbs++;
+ xhci_dbg(xhci, "Creating zero length td.\n");
+ ret = prepare_transfer(xhci, xhci->devs[slot_id],
+ ep_index, urb->stream_id,
+ 1, urb, 1, mem_flags);
+ if (ret < 0)
+ return ret;
+ }
+
td = urb_priv->td[0];
/*
@@ -3255,7 +3331,7 @@
trb_buff_len = urb->transfer_buffer_length;
first_trb = true;
-
+ last_trb_num = zero_length_needed ? 2 : 1;
/* Queue the first TRB, even if it's zero-length */
do {
u32 remainder = 0;
@@ -3272,12 +3348,15 @@
/* Chain all the TRBs together; clear the chain bit in the last
* TRB to indicate it's the last TRB in the chain.
*/
- if (num_trbs > 1) {
+ if (num_trbs > last_trb_num) {
field |= TRB_CHAIN;
- } else {
- /* FIXME - add check for ZERO_PACKET flag before this */
+ } else if (num_trbs == last_trb_num) {
td->last_trb = ep_ring->enqueue;
field |= TRB_IOC;
+ } else if (zero_length_needed && num_trbs == 1) {
+ trb_buff_len = 0;
+ urb_priv->td[1]->last_trb = ep_ring->enqueue;
+ field |= TRB_IOC;
}
/* Only set interrupt on short packet for IN endpoints */
@@ -3315,7 +3394,7 @@
trb_buff_len = urb->transfer_buffer_length - running_total;
if (trb_buff_len > TRB_MAX_BUFF_SIZE)
trb_buff_len = TRB_MAX_BUFF_SIZE;
- } while (running_total < urb->transfer_buffer_length);
+ } while (num_trbs > 0);
check_trb_math(urb, num_trbs, running_total);
giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
@@ -3514,6 +3593,97 @@
}
}
+/*
+ * Calculates Frame ID field of the isochronous TRB identifies the
+ * target frame that the Interval associated with this Isochronous
+ * Transfer Descriptor will start on. Refer to 4.11.2.5 in 1.1 spec.
+ *
+ * Returns actual frame id on success, negative value on error.
+ */
+static int xhci_get_isoc_frame_id(struct xhci_hcd *xhci,
+ struct urb *urb, int index)
+{
+ int start_frame, ist, ret = 0;
+ int start_frame_id, end_frame_id, current_frame_id;
+
+ if (urb->dev->speed == USB_SPEED_LOW ||
+ urb->dev->speed == USB_SPEED_FULL)
+ start_frame = urb->start_frame + index * urb->interval;
+ else
+ start_frame = (urb->start_frame + index * urb->interval) >> 3;
+
+ /* Isochronous Scheduling Threshold (IST, bits 0~3 in HCSPARAMS2):
+ *
+ * If bit [3] of IST is cleared to '0', software can add a TRB no
+ * later than IST[2:0] Microframes before that TRB is scheduled to
+ * be executed.
+ * If bit [3] of IST is set to '1', software can add a TRB no later
+ * than IST[2:0] Frames before that TRB is scheduled to be executed.
+ */
+ ist = HCS_IST(xhci->hcs_params2) & 0x7;
+ if (HCS_IST(xhci->hcs_params2) & (1 << 3))
+ ist <<= 3;
+
+ /* Software shall not schedule an Isoch TD with a Frame ID value that
+ * is less than the Start Frame ID or greater than the End Frame ID,
+ * where:
+ *
+ * End Frame ID = (Current MFINDEX register value + 895 ms.) MOD 2048
+ * Start Frame ID = (Current MFINDEX register value + IST + 1) MOD 2048
+ *
+ * Both the End Frame ID and Start Frame ID values are calculated
+ * in microframes. When software determines the valid Frame ID value;
+ * The End Frame ID value should be rounded down to the nearest Frame
+ * boundary, and the Start Frame ID value should be rounded up to the
+ * nearest Frame boundary.
+ */
+ current_frame_id = readl(&xhci->run_regs->microframe_index);
+ start_frame_id = roundup(current_frame_id + ist + 1, 8);
+ end_frame_id = rounddown(current_frame_id + 895 * 8, 8);
+
+ start_frame &= 0x7ff;
+ start_frame_id = (start_frame_id >> 3) & 0x7ff;
+ end_frame_id = (end_frame_id >> 3) & 0x7ff;
+
+ xhci_dbg(xhci, "%s: index %d, reg 0x%x start_frame_id 0x%x, end_frame_id 0x%x, start_frame 0x%x\n",
+ __func__, index, readl(&xhci->run_regs->microframe_index),
+ start_frame_id, end_frame_id, start_frame);
+
+ if (start_frame_id < end_frame_id) {
+ if (start_frame > end_frame_id ||
+ start_frame < start_frame_id)
+ ret = -EINVAL;
+ } else if (start_frame_id > end_frame_id) {
+ if ((start_frame > end_frame_id &&
+ start_frame < start_frame_id))
+ ret = -EINVAL;
+ } else {
+ ret = -EINVAL;
+ }
+
+ if (index == 0) {
+ if (ret == -EINVAL || start_frame == start_frame_id) {
+ start_frame = start_frame_id + 1;
+ if (urb->dev->speed == USB_SPEED_LOW ||
+ urb->dev->speed == USB_SPEED_FULL)
+ urb->start_frame = start_frame;
+ else
+ urb->start_frame = start_frame << 3;
+ ret = 0;
+ }
+ }
+
+ if (ret) {
+ xhci_warn(xhci, "Frame ID %d (reg %d, index %d) beyond range (%d, %d)\n",
+ start_frame, current_frame_id, index,
+ start_frame_id, end_frame_id);
+ xhci_warn(xhci, "Ignore frame ID field, use SIA bit instead\n");
+ return ret;
+ }
+
+ return start_frame;
+}
+
/* This is for isoc transfer */
static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
struct urb *urb, int slot_id, unsigned int ep_index)
@@ -3530,7 +3700,9 @@
u64 start_addr, addr;
int i, j;
bool more_trbs_coming;
+ struct xhci_virt_ep *xep;
+ xep = &xhci->devs[slot_id]->eps[ep_index];
ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
num_tds = urb->number_of_packets;
@@ -3578,6 +3750,7 @@
td = urb_priv->td[i];
for (j = 0; j < trbs_per_td; j++) {
+ int frame_id = 0;
u32 remainder = 0;
field = 0;
@@ -3586,8 +3759,20 @@
TRB_TLBPC(residue);
/* Queue the isoc TRB */
field |= TRB_TYPE(TRB_ISOC);
- /* Assume URB_ISO_ASAP is set */
- field |= TRB_SIA;
+
+ /* Calculate Frame ID and SIA fields */
+ if (!(urb->transfer_flags & URB_ISO_ASAP) &&
+ HCC_CFC(xhci->hcc_params)) {
+ frame_id = xhci_get_isoc_frame_id(xhci,
+ urb,
+ i);
+ if (frame_id >= 0)
+ field |= TRB_FRAME_ID(frame_id);
+ else
+ field |= TRB_SIA;
+ } else
+ field |= TRB_SIA;
+
if (i == 0) {
if (start_cycle == 0)
field |= 0x1;
@@ -3663,6 +3848,10 @@
}
}
+ /* store the next frame id */
+ if (HCC_CFC(xhci->hcc_params))
+ xep->next_frame_id = urb->start_frame + num_tds * urb->interval;
+
if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) {
if (xhci->quirks & XHCI_AMD_PLL_FIX)
usb_amd_quirk_pll_disable();
@@ -3696,12 +3885,34 @@
return ret;
}
+static int ep_ring_is_processing(struct xhci_hcd *xhci,
+ int slot_id, unsigned int ep_index)
+{
+ struct xhci_virt_device *xdev;
+ struct xhci_ring *ep_ring;
+ struct xhci_ep_ctx *ep_ctx;
+ struct xhci_virt_ep *xep;
+ dma_addr_t hw_deq;
+
+ xdev = xhci->devs[slot_id];
+ xep = &xhci->devs[slot_id]->eps[ep_index];
+ ep_ring = xep->ring;
+ ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
+
+ if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) != EP_STATE_RUNNING)
+ return 0;
+
+ hw_deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
+ return (hw_deq !=
+ xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue));
+}
+
/*
* Check transfer ring to guarantee there is enough room for the urb.
* Update ISO URB start_frame and interval.
- * Update interval as xhci_queue_intr_tx does. Just use xhci frame_index to
- * update the urb->start_frame by now.
- * Always assume URB_ISO_ASAP set, and NEVER use urb->start_frame as input.
+ * Update interval as xhci_queue_intr_tx does. Use xhci frame_index to
+ * update urb->start_frame if URB_ISO_ASAP is set in transfer_flags or
+ * Contiguous Frame ID is not supported by HC.
*/
int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
struct urb *urb, int slot_id, unsigned int ep_index)
@@ -3714,8 +3925,11 @@
int ep_interval;
int num_tds, num_trbs, i;
int ret;
+ struct xhci_virt_ep *xep;
+ int ist;
xdev = xhci->devs[slot_id];
+ xep = &xhci->devs[slot_id]->eps[ep_index];
ep_ring = xdev->eps[ep_index].ring;
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
@@ -3732,14 +3946,10 @@
if (ret)
return ret;
- start_frame = readl(&xhci->run_regs->microframe_index);
- start_frame &= 0x3fff;
-
- urb->start_frame = start_frame;
- if (urb->dev->speed == USB_SPEED_LOW ||
- urb->dev->speed == USB_SPEED_FULL)
- urb->start_frame >>= 3;
-
+ /*
+ * Check interval value. This should be done before we start to
+ * calculate the start frame value.
+ */
xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx->ep_info));
ep_interval = urb->interval;
/* Convert to microframes */
@@ -3760,6 +3970,40 @@
urb->dev->speed == USB_SPEED_FULL)
urb->interval /= 8;
}
+
+ /* Calculate the start frame and put it in urb->start_frame. */
+ if (HCC_CFC(xhci->hcc_params) &&
+ ep_ring_is_processing(xhci, slot_id, ep_index)) {
+ urb->start_frame = xep->next_frame_id;
+ goto skip_start_over;
+ }
+
+ start_frame = readl(&xhci->run_regs->microframe_index);
+ start_frame &= 0x3fff;
+ /*
+ * Round up to the next frame and consider the time before trb really
+ * gets scheduled by hardare.
+ */
+ ist = HCS_IST(xhci->hcs_params2) & 0x7;
+ if (HCS_IST(xhci->hcs_params2) & (1 << 3))
+ ist <<= 3;
+ start_frame += ist + XHCI_CFC_DELAY;
+ start_frame = roundup(start_frame, 8);
+
+ /*
+ * Round up to the next ESIT (Endpoint Service Interval Time) if ESIT
+ * is greate than 8 microframes.
+ */
+ if (urb->dev->speed == USB_SPEED_LOW ||
+ urb->dev->speed == USB_SPEED_FULL) {
+ start_frame = roundup(start_frame, urb->interval << 3);
+ urb->start_frame = start_frame >> 3;
+ } else {
+ start_frame = roundup(start_frame, urb->interval);
+ urb->start_frame = start_frame;
+ }
+
+skip_start_over:
ep_ring->num_trbs_free_temp = ep_ring->num_trbs_free;
return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 7da0d60..6b0f4a4 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1340,6 +1340,11 @@
if (usb_endpoint_xfer_isoc(&urb->ep->desc))
size = urb->number_of_packets;
+ else if (usb_endpoint_is_bulk_out(&urb->ep->desc) &&
+ urb->transfer_buffer_length > 0 &&
+ urb->transfer_flags & URB_ZERO_PACKET &&
+ !(urb->transfer_buffer_length % usb_endpoint_maxp(&urb->ep->desc)))
+ size = 2;
else
size = 1;
@@ -3117,7 +3122,7 @@
}
/*
- * The USB device drivers use this function (though the HCD interface in USB
+ * The USB device drivers use this function (through the HCD interface in USB
* core) to prepare a set of bulk endpoints to use streams. Streams are used to
* coordinate mass storage command queueing across multiple endpoints (basically
* a stream ID == a task ID).
@@ -3453,6 +3458,9 @@
return -EINVAL;
}
+ if (virt_dev->tt_info)
+ old_active_eps = virt_dev->tt_info->active_eps;
+
if (virt_dev->udev != udev) {
/* If the virt_dev and the udev does not match, this virt_dev
* may belong to another udev.
@@ -4675,7 +4683,6 @@
{
struct xhci_hcd *xhci;
u16 mel;
- int ret;
xhci = hcd_to_xhci(hcd);
if (!xhci || !(xhci->quirks & XHCI_LPM_SUPPORT) ||
@@ -4683,10 +4690,7 @@
return 0;
mel = calculate_max_exit_latency(udev, state, USB3_LPM_DISABLED);
- ret = xhci_change_max_exit_latency(xhci, udev, mel);
- if (ret)
- return ret;
- return 0;
+ return xhci_change_max_exit_latency(xhci, udev, mel);
}
#else /* CONFIG_PM */
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 31e46cc..dbda41e 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -119,6 +119,10 @@
#define HCC_LTC(p) ((p) & (1 << 6))
/* true: no secondary Stream ID Support */
#define HCC_NSS(p) ((p) & (1 << 7))
+/* true: HC supports Stopped - Short Packet */
+#define HCC_SPC(p) ((p) & (1 << 9))
+/* true: HC has Contiguous Frame ID Capability */
+#define HCC_CFC(p) ((p) & (1 << 11))
/* Max size for Primary Stream Arrays - 2^(n+1), where n is bits 12:15 */
#define HCC_MAX_PSA(p) (1 << ((((p) >> 12) & 0xf) + 1))
/* Extended Capabilities pointer from PCI base - section 5.3.6 */
@@ -285,6 +289,7 @@
#define XDEV_U0 (0x0 << 5)
#define XDEV_U2 (0x2 << 5)
#define XDEV_U3 (0x3 << 5)
+#define XDEV_INACTIVE (0x6 << 5)
#define XDEV_RESUME (0xf << 5)
/* true: port has power (see HCC_PPC) */
#define PORT_POWER (1 << 9)
@@ -890,6 +895,8 @@
/* Bandwidth checking storage */
struct xhci_bw_info bw_info;
struct list_head bw_endpoint_list;
+ /* Isoch Frame ID checking storage */
+ int next_frame_id;
};
enum xhci_overhead_type {
@@ -1058,8 +1065,8 @@
#define COMP_STOP 26
/* Same as COMP_EP_STOPPED, but the transferred length in the event is invalid */
#define COMP_STOP_INVAL 27
-/* Control Abort Error - Debug Capability - control pipe aborted */
-#define COMP_DBG_ABORT 28
+/* Same as COMP_EP_STOPPED, but a short packet detected */
+#define COMP_STOP_SHORT 28
/* Max Exit Latency Too Large Error */
#define COMP_MEL_ERR 29
/* TRB type 30 reserved */
@@ -1164,6 +1171,7 @@
/* Isochronous TRB specific fields */
#define TRB_SIA (1<<31)
+#define TRB_FRAME_ID(p) (((p) & 0x7ff) << 20)
struct xhci_generic_trb {
__le32 field[4];
@@ -1600,6 +1608,8 @@
int (*start)(struct usb_hcd *hcd);
};
+#define XHCI_CFC_DELAY 10
+
/* convert between an HCD pointer and the corresponding EHCI_HCD */
static inline struct xhci_hcd *hcd_to_xhci(struct usb_hcd *hcd)
{
diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c
index 18ebf5b..1c3d0fd 100644
--- a/drivers/usb/isp1760/isp1760-udc.c
+++ b/drivers/usb/isp1760/isp1760-udc.c
@@ -1382,14 +1382,25 @@
* This fits in the 8kB FIFO without double-buffering.
*/
if (ep_num == 0) {
- ep->ep.maxpacket = 64;
+ usb_ep_set_maxpacket_limit(&ep->ep, 64);
+ ep->ep.caps.type_control = true;
+ ep->ep.caps.dir_in = true;
+ ep->ep.caps.dir_out = true;
ep->maxpacket = 64;
udc->gadget.ep0 = &ep->ep;
} else {
- ep->ep.maxpacket = 512;
+ usb_ep_set_maxpacket_limit(&ep->ep, 512);
+ ep->ep.caps.type_iso = true;
+ ep->ep.caps.type_bulk = true;
+ ep->ep.caps.type_int = true;
ep->maxpacket = 0;
list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
}
+
+ if (is_in)
+ ep->ep.caps.dir_in = true;
+ else
+ ep->ep.caps.dir_out = true;
}
}
diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c
index 8ab1f8f..52c27ca 100644
--- a/drivers/usb/misc/ftdi-elan.c
+++ b/drivers/usb/misc/ftdi-elan.c
@@ -2568,11 +2568,7 @@
0x00);
if (UxxxStatus)
return UxxxStatus;
- UxxxStatus = ftdi_elan_read_config(ftdi, activePCIfn | reg, 0,
- &pcidata);
- if (UxxxStatus)
- return UxxxStatus;
- return 0;
+ return ftdi_elan_read_config(ftdi, activePCIfn | reg, 0, &pcidata);
}
static int ftdi_elan_found_controller(struct usb_ftdi *ftdi, int fn, int quirk)
@@ -2695,11 +2691,7 @@
}
}
if (ftdi->function > 0) {
- UxxxStatus = ftdi_elan_setup_controller(ftdi,
- ftdi->function - 1);
- if (UxxxStatus)
- return UxxxStatus;
- return 0;
+ return ftdi_elan_setup_controller(ftdi, ftdi->function - 1);
} else if (controllers > 0) {
return -ENXIO;
} else if (unrecognized > 0) {
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 0bbafe7..9517812 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -1925,10 +1925,11 @@
memset(urbs, 0, sizeof(urbs));
udev = testdev_to_usbdev(dev);
dev_info(&dev->intf->dev,
- "... iso period %d %sframes, wMaxPacket %04x\n",
+ "iso period %d %sframes, wMaxPacket %d, transactions: %d\n",
1 << (desc->bInterval - 1),
(udev->speed == USB_SPEED_HIGH) ? "micro" : "",
- usb_endpoint_maxp(desc));
+ usb_endpoint_maxp(desc) & 0x7ff,
+ 1 + (0x3 & (usb_endpoint_maxp(desc) >> 11)));
for (i = 0; i < param->sglen; i++) {
urbs[i] = iso_alloc_urb(udev, pipe, desc,
@@ -1942,7 +1943,7 @@
}
packets *= param->iterations;
dev_info(&dev->intf->dev,
- "... total %lu msec (%lu packets)\n",
+ "total %lu msec (%lu packets)\n",
(packets * (1 << (desc->bInterval - 1)))
/ ((udev->speed == USB_SPEED_HIGH) ? 8 : 1),
packets);
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 39db8b6..1f2037b 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -5,7 +5,7 @@
# (M)HDRC = (Multipoint) Highspeed Dual-Role Controller
config USB_MUSB_HDRC
- tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
+ tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, AW, ...)'
depends on (USB || USB_GADGET)
help
Say Y here if your system has a dual role high speed USB
@@ -20,6 +20,8 @@
Analog Devices parts using this IP include Blackfin BF54x,
BF525 and BF527.
+ Allwinner SoCs using this IP include A10, A13, A20, ...
+
If you do not know what this is, please say N.
To compile this driver as a module, choose M here; the
@@ -60,6 +62,15 @@
comment "Platform Glue Layer"
+config USB_MUSB_SUNXI
+ tristate "Allwinner (sunxi)"
+ depends on ARCH_SUNXI
+ depends on NOP_USB_XCEIV
+ depends on PHY_SUN4I_USB
+ depends on EXTCON
+ depends on GENERIC_PHY
+ select SUNXI_SRAM
+
config USB_MUSB_DAVINCI
tristate "DaVinci"
depends on ARCH_DAVINCI_DMx
@@ -113,19 +124,20 @@
config USB_MUSB_AM335X_CHILD
tristate
-choice
- prompt 'MUSB DMA mode'
- default MUSB_PIO_ONLY if ARCH_MULTIPLATFORM || USB_MUSB_JZ4740
- default USB_UX500_DMA if USB_MUSB_UX500
- default USB_INVENTRA_DMA if USB_MUSB_OMAP2PLUS || USB_MUSB_BLACKFIN
- default USB_TI_CPPI_DMA if USB_MUSB_DAVINCI
- default USB_TUSB_OMAP_DMA if USB_MUSB_TUSB6010
- default MUSB_PIO_ONLY if USB_MUSB_TUSB6010 || USB_MUSB_DA8XX || USB_MUSB_AM35X \
- || USB_MUSB_DSPS
+comment "MUSB DMA mode"
+
+config MUSB_PIO_ONLY
+ bool 'Disable DMA (always use PIO)'
help
- Unfortunately, only one option can be enabled here. Ideally one
- should be able to build all these drivers into one kernel to
- allow using DMA on multiplatform kernels.
+ All data is copied between memory and FIFO by the CPU.
+ DMA controllers are ignored.
+
+ Do not choose this unless DMA support for your SOC or board
+ is unavailable (or unstable). When DMA is enabled at compile time,
+ you can still disable it at run time using the "use_dma=n" module
+ parameter.
+
+if !MUSB_PIO_ONLY
config USB_UX500_DMA
bool 'ST Ericsson Ux500'
@@ -157,17 +169,6 @@
help
Enable DMA transfers on TUSB 6010 when OMAP DMA is available.
-config MUSB_PIO_ONLY
- bool 'Disable DMA (always use PIO)'
- help
- All data is copied between memory and FIFO by the CPU.
- DMA controllers are ignored.
-
- Do not choose this unless DMA support for your SOC or board
- is unavailable (or unstable). When DMA is enabled at compile time,
- you can still disable it at run time using the "use_dma=n" module
- parameter.
-
-endchoice
+endif # !MUSB_PIO_ONLY
endif # USB_MUSB_HDRC
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index ba49501..f95befe 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -20,6 +20,7 @@
obj-$(CONFIG_USB_MUSB_BLACKFIN) += blackfin.o
obj-$(CONFIG_USB_MUSB_UX500) += ux500.o
obj-$(CONFIG_USB_MUSB_JZ4740) += jz4740.o
+obj-$(CONFIG_USB_MUSB_SUNXI) += sunxi.o
obj-$(CONFIG_USB_MUSB_AM335X_CHILD) += musb_am335x.o
diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c
index 4d1b44c..d07cafb 100644
--- a/drivers/usb/musb/musb_cppi41.c
+++ b/drivers/usb/musb/musb_cppi41.c
@@ -614,7 +614,7 @@
{
struct musb *musb = controller->musb;
struct device *dev = musb->controller;
- struct device_node *np = dev->of_node;
+ struct device_node *np = dev->parent->of_node;
struct cppi41_dma_channel *cppi41_channel;
int count;
int i;
@@ -664,7 +664,7 @@
musb_dma->status = MUSB_DMA_STATUS_FREE;
musb_dma->max_len = SZ_4M;
- dc = dma_request_slave_channel(dev, str);
+ dc = dma_request_slave_channel(dev->parent, str);
if (!dc) {
dev_err(dev, "Failed to request %s.\n", str);
ret = -EPROBE_DEFER;
@@ -695,7 +695,7 @@
struct cppi41_dma_controller *controller;
int ret = 0;
- if (!musb->controller->of_node) {
+ if (!musb->controller->parent->of_node) {
dev_err(musb->controller, "Need DT for the DMA engine.\n");
return NULL;
}
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 1334a3d..a0cfead 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -482,11 +482,7 @@
dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val);
}
- ret = dsps_musb_dbg_init(musb, glue);
- if (ret)
- return ret;
-
- return 0;
+ return dsps_musb_dbg_init(musb, glue);
}
static int dsps_musb_exit(struct musb *musb)
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 625d482f..67ad630 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -313,8 +313,7 @@
/* MUSB_TXCSR_P_ISO is still set correctly */
-#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_UX500_DMA)
- {
+ if (musb_dma_inventra(musb) || musb_dma_ux500(musb)) {
if (request_size < musb_ep->packet_sz)
musb_ep->dma->desired_mode = 0;
else
@@ -365,7 +364,6 @@
}
}
-#endif
if (is_cppi_enabled(musb)) {
/* program endpoint CSR first, then setup DMA */
csr &= ~(MUSB_TXCSR_P_UNDERRUN | MUSB_TXCSR_TXPKTRDY);
@@ -641,8 +639,10 @@
use_mode_1 = 0;
if (request->actual < request->length) {
-#ifdef CONFIG_USB_INVENTRA_DMA
- if (is_buffer_mapped(req)) {
+ if (!is_buffer_mapped(req))
+ goto buffer_aint_mapped;
+
+ if (musb_dma_inventra(musb)) {
struct dma_controller *c;
struct dma_channel *channel;
int use_dma = 0;
@@ -716,8 +716,8 @@
if (use_dma)
return;
}
-#elif defined(CONFIG_USB_UX500_DMA)
- if ((is_buffer_mapped(req)) &&
+
+ if ((musb_dma_ux500(musb)) &&
(request->actual < request->length)) {
struct dma_controller *c;
@@ -765,7 +765,6 @@
return;
}
-#endif /* Mentor's DMA */
len = request->length - request->actual;
dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n",
@@ -775,8 +774,7 @@
fifo_count = min_t(unsigned, len, fifo_count);
-#ifdef CONFIG_USB_TUSB_OMAP_DMA
- if (tusb_dma_omap(musb) && is_buffer_mapped(req)) {
+ if (tusb_dma_omap(musb)) {
struct dma_controller *c = musb->dma_controller;
struct dma_channel *channel = musb_ep->dma;
u32 dma_addr = request->dma + request->actual;
@@ -790,23 +788,22 @@
if (ret)
return;
}
-#endif
+
/*
* Unmap the dma buffer back to cpu if dma channel
* programming fails. This buffer is mapped if the
* channel allocation is successful
*/
- if (is_buffer_mapped(req)) {
- unmap_dma_buffer(req, musb);
+ unmap_dma_buffer(req, musb);
- /*
- * Clear DMAENAB and AUTOCLEAR for the
- * PIO mode transfer
- */
- csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR);
- musb_writew(epio, MUSB_RXCSR, csr);
- }
+ /*
+ * Clear DMAENAB and AUTOCLEAR for the
+ * PIO mode transfer
+ */
+ csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR);
+ musb_writew(epio, MUSB_RXCSR, csr);
+buffer_aint_mapped:
musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
(request->buf + request->actual));
request->actual += fifo_count;
@@ -1684,6 +1681,40 @@
return 0;
}
+#ifdef CONFIG_BLACKFIN
+static struct usb_ep *musb_match_ep(struct usb_gadget *g,
+ struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp)
+{
+ struct usb_ep *ep = NULL;
+
+ switch (usb_endpoint_type(desc)) {
+ case USB_ENDPOINT_XFER_ISOC:
+ case USB_ENDPOINT_XFER_BULK:
+ if (usb_endpoint_dir_in(desc))
+ ep = gadget_find_ep_by_name(g, "ep5in");
+ else
+ ep = gadget_find_ep_by_name(g, "ep6out");
+ break;
+ case USB_ENDPOINT_XFER_INT:
+ if (usb_endpoint_dir_in(desc))
+ ep = gadget_find_ep_by_name(g, "ep1in");
+ else
+ ep = gadget_find_ep_by_name(g, "ep2out");
+ break;
+ default:
+ break;
+ }
+
+ if (ep && usb_gadget_ep_match_desc(g, ep, desc, ep_comp))
+ return ep;
+
+ return NULL;
+}
+#else
+#define musb_match_ep NULL
+#endif
+
static int musb_gadget_start(struct usb_gadget *g,
struct usb_gadget_driver *driver);
static int musb_gadget_stop(struct usb_gadget *g);
@@ -1697,6 +1728,7 @@
.pullup = musb_gadget_pullup,
.udc_start = musb_gadget_start,
.udc_stop = musb_gadget_stop,
+ .match_ep = musb_match_ep,
};
/* ----------------------------------------------------------------------- */
@@ -1729,6 +1761,7 @@
INIT_LIST_HEAD(&ep->end_point.ep_list);
if (!epnum) {
usb_ep_set_maxpacket_limit(&ep->end_point, 64);
+ ep->end_point.caps.type_control = true;
ep->end_point.ops = &musb_g_ep0_ops;
musb->g.ep0 = &ep->end_point;
} else {
@@ -1736,9 +1769,20 @@
usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_tx);
else
usb_ep_set_maxpacket_limit(&ep->end_point, hw_ep->max_packet_sz_rx);
+ ep->end_point.caps.type_iso = true;
+ ep->end_point.caps.type_bulk = true;
+ ep->end_point.caps.type_int = true;
ep->end_point.ops = &musb_ep_ops;
list_add_tail(&ep->end_point.ep_list, &musb->g.ep_list);
}
+
+ if (!epnum || hw_ep->is_shared_fifo) {
+ ep->end_point.caps.dir_in = true;
+ ep->end_point.caps.dir_out = true;
+ } else if (is_in)
+ ep->end_point.caps.dir_in = true;
+ else
+ ep->end_point.caps.dir_out = true;
}
/*
@@ -2075,6 +2119,7 @@
musb->g.b_hnp_enable = 0;
musb->g.a_alt_hnp_support = 0;
musb->g.a_hnp_support = 0;
+ musb->g.quirk_zlp_not_supp = 1;
/* Normal reset, as B-Device;
* or else after HNP, as A-Device
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
new file mode 100644
index 0000000..f9f6304
--- /dev/null
+++ b/drivers/usb/musb/sunxi.c
@@ -0,0 +1,756 @@
+/*
+ * Allwinner sun4i MUSB Glue Layer
+ *
+ * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on code from
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.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/clk.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/phy/phy-sun4i-usb.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/soc/sunxi/sunxi_sram.h>
+#include <linux/usb/musb.h>
+#include <linux/usb/of.h>
+#include <linux/usb/usb_phy_generic.h>
+#include <linux/workqueue.h>
+#include "musb_core.h"
+
+/*
+ * Register offsets, note sunxi musb has a different layout then most
+ * musb implementations, we translate the layout in musb_readb & friends.
+ */
+#define SUNXI_MUSB_POWER 0x0040
+#define SUNXI_MUSB_DEVCTL 0x0041
+#define SUNXI_MUSB_INDEX 0x0042
+#define SUNXI_MUSB_VEND0 0x0043
+#define SUNXI_MUSB_INTRTX 0x0044
+#define SUNXI_MUSB_INTRRX 0x0046
+#define SUNXI_MUSB_INTRTXE 0x0048
+#define SUNXI_MUSB_INTRRXE 0x004a
+#define SUNXI_MUSB_INTRUSB 0x004c
+#define SUNXI_MUSB_INTRUSBE 0x0050
+#define SUNXI_MUSB_FRAME 0x0054
+#define SUNXI_MUSB_TXFIFOSZ 0x0090
+#define SUNXI_MUSB_TXFIFOADD 0x0092
+#define SUNXI_MUSB_RXFIFOSZ 0x0094
+#define SUNXI_MUSB_RXFIFOADD 0x0096
+#define SUNXI_MUSB_FADDR 0x0098
+#define SUNXI_MUSB_TXFUNCADDR 0x0098
+#define SUNXI_MUSB_TXHUBADDR 0x009a
+#define SUNXI_MUSB_TXHUBPORT 0x009b
+#define SUNXI_MUSB_RXFUNCADDR 0x009c
+#define SUNXI_MUSB_RXHUBADDR 0x009e
+#define SUNXI_MUSB_RXHUBPORT 0x009f
+#define SUNXI_MUSB_CONFIGDATA 0x00c0
+
+/* VEND0 bits */
+#define SUNXI_MUSB_VEND0_PIO_MODE 0
+
+/* flags */
+#define SUNXI_MUSB_FL_ENABLED 0
+#define SUNXI_MUSB_FL_HOSTMODE 1
+#define SUNXI_MUSB_FL_HOSTMODE_PEND 2
+#define SUNXI_MUSB_FL_VBUS_ON 3
+#define SUNXI_MUSB_FL_PHY_ON 4
+#define SUNXI_MUSB_FL_HAS_SRAM 5
+#define SUNXI_MUSB_FL_HAS_RESET 6
+#define SUNXI_MUSB_FL_NO_CONFIGDATA 7
+
+/* Our read/write methods need access and do not get passed in a musb ref :| */
+static struct musb *sunxi_musb;
+
+struct sunxi_glue {
+ struct device *dev;
+ struct platform_device *musb;
+ struct clk *clk;
+ struct reset_control *rst;
+ struct phy *phy;
+ struct platform_device *usb_phy;
+ struct usb_phy *xceiv;
+ unsigned long flags;
+ struct work_struct work;
+ struct extcon_dev *extcon;
+ struct notifier_block host_nb;
+};
+
+/* phy_power_on / off may sleep, so we use a workqueue */
+static void sunxi_musb_work(struct work_struct *work)
+{
+ struct sunxi_glue *glue = container_of(work, struct sunxi_glue, work);
+ bool vbus_on, phy_on;
+
+ if (!test_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
+ return;
+
+ if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) {
+ struct musb *musb = platform_get_drvdata(glue->musb);
+ unsigned long flags;
+ u8 devctl;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL);
+ if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
+ set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+ musb->xceiv->otg->default_a = 1;
+ musb->xceiv->otg->state = OTG_STATE_A_IDLE;
+ MUSB_HST_MODE(musb);
+ devctl |= MUSB_DEVCTL_SESSION;
+ } else {
+ clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+ musb->xceiv->otg->default_a = 0;
+ musb->xceiv->otg->state = OTG_STATE_B_IDLE;
+ MUSB_DEV_MODE(musb);
+ devctl &= ~MUSB_DEVCTL_SESSION;
+ }
+ writeb(devctl, musb->mregs + SUNXI_MUSB_DEVCTL);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+ }
+
+ vbus_on = test_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+ phy_on = test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+
+ if (phy_on != vbus_on) {
+ if (vbus_on) {
+ phy_power_on(glue->phy);
+ set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+ } else {
+ phy_power_off(glue->phy);
+ clear_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+ }
+ }
+}
+
+static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
+{
+ struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+ if (is_on)
+ set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+ else
+ clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+
+ schedule_work(&glue->work);
+}
+
+static void sunxi_musb_pre_root_reset_end(struct musb *musb)
+{
+ struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+ sun4i_usb_phy_set_squelch_detect(glue->phy, false);
+}
+
+static void sunxi_musb_post_root_reset_end(struct musb *musb)
+{
+ struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+ sun4i_usb_phy_set_squelch_detect(glue->phy, true);
+}
+
+static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
+{
+ struct musb *musb = __hci;
+ unsigned long flags;
+
+ spin_lock_irqsave(&musb->lock, flags);
+
+ musb->int_usb = readb(musb->mregs + SUNXI_MUSB_INTRUSB);
+ if (musb->int_usb)
+ writeb(musb->int_usb, musb->mregs + SUNXI_MUSB_INTRUSB);
+
+ /*
+ * sunxi musb often signals babble on low / full speed device
+ * disconnect, without ever raising MUSB_INTR_DISCONNECT, since
+ * normally babble never happens treat it as disconnect.
+ */
+ if ((musb->int_usb & MUSB_INTR_BABBLE) && is_host_active(musb)) {
+ musb->int_usb &= ~MUSB_INTR_BABBLE;
+ musb->int_usb |= MUSB_INTR_DISCONNECT;
+ }
+
+ if ((musb->int_usb & MUSB_INTR_RESET) && !is_host_active(musb)) {
+ /* ep0 FADDR must be 0 when (re)entering peripheral mode */
+ musb_ep_select(musb->mregs, 0);
+ musb_writeb(musb->mregs, MUSB_FADDR, 0);
+ }
+
+ musb->int_tx = readw(musb->mregs + SUNXI_MUSB_INTRTX);
+ if (musb->int_tx)
+ writew(musb->int_tx, musb->mregs + SUNXI_MUSB_INTRTX);
+
+ musb->int_rx = readw(musb->mregs + SUNXI_MUSB_INTRRX);
+ if (musb->int_rx)
+ writew(musb->int_rx, musb->mregs + SUNXI_MUSB_INTRRX);
+
+ musb_interrupt(musb);
+
+ spin_unlock_irqrestore(&musb->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int sunxi_musb_host_notifier(struct notifier_block *nb,
+ unsigned long event, void *ptr)
+{
+ struct sunxi_glue *glue = container_of(nb, struct sunxi_glue, host_nb);
+
+ if (event)
+ set_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
+ else
+ clear_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
+
+ set_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags);
+ schedule_work(&glue->work);
+
+ return NOTIFY_DONE;
+}
+
+static int sunxi_musb_init(struct musb *musb)
+{
+ struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+ int ret;
+
+ sunxi_musb = musb;
+ musb->phy = glue->phy;
+ musb->xceiv = glue->xceiv;
+
+ if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
+ ret = sunxi_sram_claim(musb->controller->parent);
+ if (ret)
+ return ret;
+ }
+
+ ret = clk_prepare_enable(glue->clk);
+ if (ret)
+ goto error_sram_release;
+
+ if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
+ ret = reset_control_deassert(glue->rst);
+ if (ret)
+ goto error_clk_disable;
+ }
+
+ writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
+
+ /* Register notifier before calling phy_init() */
+ if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) {
+ ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
+ &glue->host_nb);
+ if (ret)
+ goto error_reset_assert;
+ }
+
+ ret = phy_init(glue->phy);
+ if (ret)
+ goto error_unregister_notifier;
+
+ if (musb->port_mode == MUSB_PORT_MODE_HOST) {
+ ret = phy_power_on(glue->phy);
+ if (ret)
+ goto error_phy_exit;
+ set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
+ /* Stop musb work from turning vbus off again */
+ set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
+ }
+
+ musb->isr = sunxi_musb_interrupt;
+
+ /* Stop the musb-core from doing runtime pm (not supported on sunxi) */
+ pm_runtime_get(musb->controller);
+
+ return 0;
+
+error_phy_exit:
+ phy_exit(glue->phy);
+error_unregister_notifier:
+ if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
+ extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
+ &glue->host_nb);
+error_reset_assert:
+ if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
+ reset_control_assert(glue->rst);
+error_clk_disable:
+ clk_disable_unprepare(glue->clk);
+error_sram_release:
+ if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
+ sunxi_sram_release(musb->controller->parent);
+ return ret;
+}
+
+static int sunxi_musb_exit(struct musb *musb)
+{
+ struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+ pm_runtime_put(musb->controller);
+
+ cancel_work_sync(&glue->work);
+ if (test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags))
+ phy_power_off(glue->phy);
+
+ phy_exit(glue->phy);
+
+ if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
+ extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
+ &glue->host_nb);
+
+ if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
+ reset_control_assert(glue->rst);
+
+ clk_disable_unprepare(glue->clk);
+ if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
+ sunxi_sram_release(musb->controller->parent);
+
+ return 0;
+}
+
+static void sunxi_musb_enable(struct musb *musb)
+{
+ struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+ /* musb_core does not call us in a balanced manner */
+ if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
+ return;
+
+ schedule_work(&glue->work);
+}
+
+static void sunxi_musb_disable(struct musb *musb)
+{
+ struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
+
+ clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags);
+}
+
+/*
+ * sunxi musb register layout
+ * 0x00 - 0x17 fifo regs, 1 long per fifo
+ * 0x40 - 0x57 generic control regs (power - frame)
+ * 0x80 - 0x8f ep control regs (addressed through hw_ep->regs, indexed)
+ * 0x90 - 0x97 fifo control regs (indexed)
+ * 0x98 - 0x9f multipoint / busctl regs (indexed)
+ * 0xc0 configdata reg
+ */
+
+static u32 sunxi_musb_fifo_offset(u8 epnum)
+{
+ return (epnum * 4);
+}
+
+static u32 sunxi_musb_ep_offset(u8 epnum, u16 offset)
+{
+ WARN_ONCE(offset != 0,
+ "sunxi_musb_ep_offset called with non 0 offset\n");
+
+ return 0x80; /* indexed, so ignore epnum */
+}
+
+static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset)
+{
+ return SUNXI_MUSB_TXFUNCADDR + offset;
+}
+
+static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset)
+{
+ struct sunxi_glue *glue;
+
+ if (addr == sunxi_musb->mregs) {
+ /* generic control or fifo control reg access */
+ switch (offset) {
+ case MUSB_FADDR:
+ return readb(addr + SUNXI_MUSB_FADDR);
+ case MUSB_POWER:
+ return readb(addr + SUNXI_MUSB_POWER);
+ case MUSB_INTRUSB:
+ return readb(addr + SUNXI_MUSB_INTRUSB);
+ case MUSB_INTRUSBE:
+ return readb(addr + SUNXI_MUSB_INTRUSBE);
+ case MUSB_INDEX:
+ return readb(addr + SUNXI_MUSB_INDEX);
+ case MUSB_TESTMODE:
+ return 0; /* No testmode on sunxi */
+ case MUSB_DEVCTL:
+ return readb(addr + SUNXI_MUSB_DEVCTL);
+ case MUSB_TXFIFOSZ:
+ return readb(addr + SUNXI_MUSB_TXFIFOSZ);
+ case MUSB_RXFIFOSZ:
+ return readb(addr + SUNXI_MUSB_RXFIFOSZ);
+ case MUSB_CONFIGDATA + 0x10: /* See musb_read_configdata() */
+ glue = dev_get_drvdata(sunxi_musb->controller->parent);
+ /* A33 saves a reg, and we get to hardcode this */
+ if (test_bit(SUNXI_MUSB_FL_NO_CONFIGDATA,
+ &glue->flags))
+ return 0xde;
+
+ return readb(addr + SUNXI_MUSB_CONFIGDATA);
+ /* Offset for these is fixed by sunxi_musb_busctl_offset() */
+ case SUNXI_MUSB_TXFUNCADDR:
+ case SUNXI_MUSB_TXHUBADDR:
+ case SUNXI_MUSB_TXHUBPORT:
+ case SUNXI_MUSB_RXFUNCADDR:
+ case SUNXI_MUSB_RXHUBADDR:
+ case SUNXI_MUSB_RXHUBPORT:
+ /* multipoint / busctl reg access */
+ return readb(addr + offset);
+ default:
+ dev_err(sunxi_musb->controller->parent,
+ "Error unknown readb offset %u\n", offset);
+ return 0;
+ }
+ } else if (addr == (sunxi_musb->mregs + 0x80)) {
+ /* ep control reg access */
+ /* sunxi has a 2 byte hole before the txtype register */
+ if (offset >= MUSB_TXTYPE)
+ offset += 2;
+ return readb(addr + offset);
+ }
+
+ dev_err(sunxi_musb->controller->parent,
+ "Error unknown readb at 0x%x bytes offset\n",
+ (int)(addr - sunxi_musb->mregs));
+ return 0;
+}
+
+static void sunxi_musb_writeb(void __iomem *addr, unsigned offset, u8 data)
+{
+ if (addr == sunxi_musb->mregs) {
+ /* generic control or fifo control reg access */
+ switch (offset) {
+ case MUSB_FADDR:
+ return writeb(data, addr + SUNXI_MUSB_FADDR);
+ case MUSB_POWER:
+ return writeb(data, addr + SUNXI_MUSB_POWER);
+ case MUSB_INTRUSB:
+ return writeb(data, addr + SUNXI_MUSB_INTRUSB);
+ case MUSB_INTRUSBE:
+ return writeb(data, addr + SUNXI_MUSB_INTRUSBE);
+ case MUSB_INDEX:
+ return writeb(data, addr + SUNXI_MUSB_INDEX);
+ case MUSB_TESTMODE:
+ if (data)
+ dev_warn(sunxi_musb->controller->parent,
+ "sunxi-musb does not have testmode\n");
+ return;
+ case MUSB_DEVCTL:
+ return writeb(data, addr + SUNXI_MUSB_DEVCTL);
+ case MUSB_TXFIFOSZ:
+ return writeb(data, addr + SUNXI_MUSB_TXFIFOSZ);
+ case MUSB_RXFIFOSZ:
+ return writeb(data, addr + SUNXI_MUSB_RXFIFOSZ);
+ /* Offset for these is fixed by sunxi_musb_busctl_offset() */
+ case SUNXI_MUSB_TXFUNCADDR:
+ case SUNXI_MUSB_TXHUBADDR:
+ case SUNXI_MUSB_TXHUBPORT:
+ case SUNXI_MUSB_RXFUNCADDR:
+ case SUNXI_MUSB_RXHUBADDR:
+ case SUNXI_MUSB_RXHUBPORT:
+ /* multipoint / busctl reg access */
+ return writeb(data, addr + offset);
+ default:
+ dev_err(sunxi_musb->controller->parent,
+ "Error unknown writeb offset %u\n", offset);
+ return;
+ }
+ } else if (addr == (sunxi_musb->mregs + 0x80)) {
+ /* ep control reg access */
+ if (offset >= MUSB_TXTYPE)
+ offset += 2;
+ return writeb(data, addr + offset);
+ }
+
+ dev_err(sunxi_musb->controller->parent,
+ "Error unknown writeb at 0x%x bytes offset\n",
+ (int)(addr - sunxi_musb->mregs));
+}
+
+static u16 sunxi_musb_readw(const void __iomem *addr, unsigned offset)
+{
+ if (addr == sunxi_musb->mregs) {
+ /* generic control or fifo control reg access */
+ switch (offset) {
+ case MUSB_INTRTX:
+ return readw(addr + SUNXI_MUSB_INTRTX);
+ case MUSB_INTRRX:
+ return readw(addr + SUNXI_MUSB_INTRRX);
+ case MUSB_INTRTXE:
+ return readw(addr + SUNXI_MUSB_INTRTXE);
+ case MUSB_INTRRXE:
+ return readw(addr + SUNXI_MUSB_INTRRXE);
+ case MUSB_FRAME:
+ return readw(addr + SUNXI_MUSB_FRAME);
+ case MUSB_TXFIFOADD:
+ return readw(addr + SUNXI_MUSB_TXFIFOADD);
+ case MUSB_RXFIFOADD:
+ return readw(addr + SUNXI_MUSB_RXFIFOADD);
+ case MUSB_HWVERS:
+ return 0; /* sunxi musb version is not known */
+ default:
+ dev_err(sunxi_musb->controller->parent,
+ "Error unknown readw offset %u\n", offset);
+ return 0;
+ }
+ } else if (addr == (sunxi_musb->mregs + 0x80)) {
+ /* ep control reg access */
+ return readw(addr + offset);
+ }
+
+ dev_err(sunxi_musb->controller->parent,
+ "Error unknown readw at 0x%x bytes offset\n",
+ (int)(addr - sunxi_musb->mregs));
+ return 0;
+}
+
+static void sunxi_musb_writew(void __iomem *addr, unsigned offset, u16 data)
+{
+ if (addr == sunxi_musb->mregs) {
+ /* generic control or fifo control reg access */
+ switch (offset) {
+ case MUSB_INTRTX:
+ return writew(data, addr + SUNXI_MUSB_INTRTX);
+ case MUSB_INTRRX:
+ return writew(data, addr + SUNXI_MUSB_INTRRX);
+ case MUSB_INTRTXE:
+ return writew(data, addr + SUNXI_MUSB_INTRTXE);
+ case MUSB_INTRRXE:
+ return writew(data, addr + SUNXI_MUSB_INTRRXE);
+ case MUSB_FRAME:
+ return writew(data, addr + SUNXI_MUSB_FRAME);
+ case MUSB_TXFIFOADD:
+ return writew(data, addr + SUNXI_MUSB_TXFIFOADD);
+ case MUSB_RXFIFOADD:
+ return writew(data, addr + SUNXI_MUSB_RXFIFOADD);
+ default:
+ dev_err(sunxi_musb->controller->parent,
+ "Error unknown writew offset %u\n", offset);
+ return;
+ }
+ } else if (addr == (sunxi_musb->mregs + 0x80)) {
+ /* ep control reg access */
+ return writew(data, addr + offset);
+ }
+
+ dev_err(sunxi_musb->controller->parent,
+ "Error unknown writew at 0x%x bytes offset\n",
+ (int)(addr - sunxi_musb->mregs));
+}
+
+static const struct musb_platform_ops sunxi_musb_ops = {
+ .quirks = MUSB_INDEXED_EP,
+ .init = sunxi_musb_init,
+ .exit = sunxi_musb_exit,
+ .enable = sunxi_musb_enable,
+ .disable = sunxi_musb_disable,
+ .fifo_offset = sunxi_musb_fifo_offset,
+ .ep_offset = sunxi_musb_ep_offset,
+ .busctl_offset = sunxi_musb_busctl_offset,
+ .readb = sunxi_musb_readb,
+ .writeb = sunxi_musb_writeb,
+ .readw = sunxi_musb_readw,
+ .writew = sunxi_musb_writew,
+ .set_vbus = sunxi_musb_set_vbus,
+ .pre_root_reset_end = sunxi_musb_pre_root_reset_end,
+ .post_root_reset_end = sunxi_musb_post_root_reset_end,
+};
+
+/* Allwinner OTG supports up to 5 endpoints */
+#define SUNXI_MUSB_MAX_EP_NUM 6
+#define SUNXI_MUSB_RAM_BITS 11
+
+static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = {
+ MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
+ MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
+ MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
+ MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
+ MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
+ MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
+ MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
+ MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
+ MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512),
+ MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512),
+};
+
+static struct musb_hdrc_config sunxi_musb_hdrc_config = {
+ .fifo_cfg = sunxi_musb_mode_cfg,
+ .fifo_cfg_size = ARRAY_SIZE(sunxi_musb_mode_cfg),
+ .multipoint = true,
+ .dyn_fifo = true,
+ .soft_con = true,
+ .num_eps = SUNXI_MUSB_MAX_EP_NUM,
+ .ram_bits = SUNXI_MUSB_RAM_BITS,
+ .dma = 0,
+};
+
+static int sunxi_musb_probe(struct platform_device *pdev)
+{
+ struct musb_hdrc_platform_data pdata;
+ struct platform_device_info pinfo;
+ struct sunxi_glue *glue;
+ struct device_node *np = pdev->dev.of_node;
+ int ret;
+
+ if (!np) {
+ dev_err(&pdev->dev, "Error no device tree node found\n");
+ return -EINVAL;
+ }
+
+ glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
+ if (!glue)
+ return -ENOMEM;
+
+ memset(&pdata, 0, sizeof(pdata));
+ switch (of_usb_get_dr_mode(np)) {
+#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
+ case USB_DR_MODE_HOST:
+ pdata.mode = MUSB_PORT_MODE_HOST;
+ break;
+#endif
+#ifdef CONFIG_USB_MUSB_DUAL_ROLE
+ case USB_DR_MODE_OTG:
+ glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
+ if (IS_ERR(glue->extcon)) {
+ if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "Invalid or missing extcon\n");
+ return PTR_ERR(glue->extcon);
+ }
+ pdata.mode = MUSB_PORT_MODE_DUAL_ROLE;
+ break;
+#endif
+ default:
+ dev_err(&pdev->dev, "Invalid or missing 'dr_mode' property\n");
+ return -EINVAL;
+ }
+ pdata.platform_ops = &sunxi_musb_ops;
+ pdata.config = &sunxi_musb_hdrc_config;
+
+ glue->dev = &pdev->dev;
+ INIT_WORK(&glue->work, sunxi_musb_work);
+ glue->host_nb.notifier_call = sunxi_musb_host_notifier;
+
+ if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
+ set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
+
+ if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
+ set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
+
+ if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb")) {
+ set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
+ set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags);
+ }
+
+ glue->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(glue->clk)) {
+ dev_err(&pdev->dev, "Error getting clock: %ld\n",
+ PTR_ERR(glue->clk));
+ return PTR_ERR(glue->clk);
+ }
+
+ if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
+ glue->rst = devm_reset_control_get(&pdev->dev, NULL);
+ if (IS_ERR(glue->rst)) {
+ if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "Error getting reset %ld\n",
+ PTR_ERR(glue->rst));
+ return PTR_ERR(glue->rst);
+ }
+ }
+
+ glue->phy = devm_phy_get(&pdev->dev, "usb");
+ if (IS_ERR(glue->phy)) {
+ if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ dev_err(&pdev->dev, "Error getting phy %ld\n",
+ PTR_ERR(glue->phy));
+ return PTR_ERR(glue->phy);
+ }
+
+ glue->usb_phy = usb_phy_generic_register();
+ if (IS_ERR(glue->usb_phy)) {
+ dev_err(&pdev->dev, "Error registering usb-phy %ld\n",
+ PTR_ERR(glue->usb_phy));
+ return PTR_ERR(glue->usb_phy);
+ }
+
+ glue->xceiv = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
+ if (IS_ERR(glue->xceiv)) {
+ ret = PTR_ERR(glue->xceiv);
+ dev_err(&pdev->dev, "Error getting usb-phy %d\n", ret);
+ goto err_unregister_usb_phy;
+ }
+
+ platform_set_drvdata(pdev, glue);
+
+ memset(&pinfo, 0, sizeof(pinfo));
+ pinfo.name = "musb-hdrc";
+ pinfo.id = PLATFORM_DEVID_AUTO;
+ pinfo.parent = &pdev->dev;
+ pinfo.res = pdev->resource;
+ pinfo.num_res = pdev->num_resources;
+ pinfo.data = &pdata;
+ pinfo.size_data = sizeof(pdata);
+
+ glue->musb = platform_device_register_full(&pinfo);
+ if (IS_ERR(glue->musb)) {
+ ret = PTR_ERR(glue->musb);
+ dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret);
+ goto err_unregister_usb_phy;
+ }
+
+ return 0;
+
+err_unregister_usb_phy:
+ usb_phy_generic_unregister(glue->usb_phy);
+ return ret;
+}
+
+static int sunxi_musb_remove(struct platform_device *pdev)
+{
+ struct sunxi_glue *glue = platform_get_drvdata(pdev);
+ struct platform_device *usb_phy = glue->usb_phy;
+
+ platform_device_unregister(glue->musb); /* Frees glue ! */
+ usb_phy_generic_unregister(usb_phy);
+
+ return 0;
+}
+
+static const struct of_device_id sunxi_musb_match[] = {
+ { .compatible = "allwinner,sun4i-a10-musb", },
+ { .compatible = "allwinner,sun6i-a31-musb", },
+ { .compatible = "allwinner,sun8i-a33-musb", },
+ {}
+};
+
+static struct platform_driver sunxi_musb_driver = {
+ .probe = sunxi_musb_probe,
+ .remove = sunxi_musb_remove,
+ .driver = {
+ .name = "musb-sunxi",
+ .of_match_table = sunxi_musb_match,
+ },
+};
+module_platform_driver(sunxi_musb_driver);
+
+MODULE_DESCRIPTION("Allwinner sunxi MUSB Glue Layer");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 869c0cfcad..7d3beee 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -152,6 +152,20 @@
This driver is not supported on boards like trout which
has an external PHY.
+config USB_QCOM_8X16_PHY
+ tristate "Qualcomm APQ8016/MSM8916 on-chip USB PHY controller support"
+ depends on ARCH_QCOM || COMPILE_TEST
+ depends on RESET_CONTROLLER
+ select USB_PHY
+ select USB_ULPI_VIEWPORT
+ help
+ Enable this to support the USB transceiver on Qualcomm 8x16 chipsets.
+ It handles PHY initialization, clock management, power management,
+ and workarounds required after resetting the hardware.
+
+ To compile this driver as a module, choose M here: the
+ module will be called phy-qcom-8x16-usb.
+
config USB_MV_OTG
tristate "Marvell USB OTG support"
depends on USB_EHCI_MV && USB_MV_UDC && PM
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index e36ab1d..19c0dcc 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -20,6 +20,7 @@
obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio-vbus-usb.o
obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o
obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o
+obj-$(CONFIG_USB_QCOM_8X16_PHY) += phy-qcom-8x16-usb.o
obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o
obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o
obj-$(CONFIG_USB_RCAR_PHY) += phy-rcar-usb.o
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index deee68e..ec6ecd0 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -218,11 +218,13 @@
clk_rate = 0;
needs_vcc = of_property_read_bool(node, "vcc-supply");
- nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset");
+ nop->gpiod_reset = devm_gpiod_get_optional(dev, "reset",
+ GPIOD_ASIS);
err = PTR_ERR_OR_ZERO(nop->gpiod_reset);
if (!err) {
nop->gpiod_vbus = devm_gpiod_get_optional(dev,
- "vbus-detect");
+ "vbus-detect",
+ GPIOD_ASIS);
err = PTR_ERR_OR_ZERO(nop->gpiod_vbus);
}
} else if (pdata) {
diff --git a/drivers/usb/phy/phy-keystone.c b/drivers/usb/phy/phy-keystone.c
index e0556f7..01d4e4c 100644
--- a/drivers/usb/phy/phy-keystone.c
+++ b/drivers/usb/phy/phy-keystone.c
@@ -96,11 +96,7 @@
platform_set_drvdata(pdev, k_phy);
- ret = usb_add_phy_dev(&k_phy->usb_phy_gen.phy);
- if (ret)
- return ret;
-
- return 0;
+ return usb_add_phy_dev(&k_phy->usb_phy_gen.phy);
}
static int keystone_usbphy_remove(struct platform_device *pdev)
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index 00c49bb..c58c3c0 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/slab.h>
@@ -32,6 +33,7 @@
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/reboot.h>
#include <linux/reset.h>
#include <linux/usb.h>
@@ -1471,6 +1473,14 @@
else
clear_bit(B_SESS_VLD, &motg->inputs);
+ if (test_bit(B_SESS_VLD, &motg->inputs)) {
+ /* Switch D+/D- lines to Device connector */
+ gpiod_set_value_cansleep(motg->switch_gpio, 0);
+ } else {
+ /* Switch D+/D- lines to Hub */
+ gpiod_set_value_cansleep(motg->switch_gpio, 1);
+ }
+
schedule_work(&motg->sm_work);
return NOTIFY_DONE;
@@ -1546,6 +1556,11 @@
motg->manual_pullup = of_property_read_bool(node, "qcom,manual-pullup");
+ motg->switch_gpio = devm_gpiod_get_optional(&pdev->dev, "switch",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(motg->switch_gpio))
+ return PTR_ERR(motg->switch_gpio);
+
ext_id = ERR_PTR(-ENODEV);
ext_vbus = ERR_PTR(-ENODEV);
if (of_property_read_bool(node, "extcon")) {
@@ -1561,15 +1576,16 @@
}
if (!IS_ERR(ext_vbus)) {
+ motg->vbus.extcon = ext_vbus;
motg->vbus.nb.notifier_call = msm_otg_vbus_notifier;
- ret = extcon_register_interest(&motg->vbus.conn, ext_vbus->name,
- "USB", &motg->vbus.nb);
+ ret = extcon_register_notifier(ext_vbus, EXTCON_USB,
+ &motg->vbus.nb);
if (ret < 0) {
dev_err(&pdev->dev, "register VBUS notifier failed\n");
return ret;
}
- ret = extcon_get_cable_state(ext_vbus, "USB");
+ ret = extcon_get_cable_state_(ext_vbus, EXTCON_USB);
if (ret)
set_bit(B_SESS_VLD, &motg->inputs);
else
@@ -1577,15 +1593,16 @@
}
if (!IS_ERR(ext_id)) {
+ motg->id.extcon = ext_id;
motg->id.nb.notifier_call = msm_otg_id_notifier;
- ret = extcon_register_interest(&motg->id.conn, ext_id->name,
- "USB-HOST", &motg->id.nb);
+ ret = extcon_register_notifier(ext_id, EXTCON_USB_HOST,
+ &motg->id.nb);
if (ret < 0) {
dev_err(&pdev->dev, "register ID notifier failed\n");
return ret;
}
- ret = extcon_get_cable_state(ext_id, "USB-HOST");
+ ret = extcon_get_cable_state_(ext_id, EXTCON_USB_HOST);
if (ret)
clear_bit(ID, &motg->inputs);
else
@@ -1615,6 +1632,19 @@
return 0;
}
+static int msm_otg_reboot_notify(struct notifier_block *this,
+ unsigned long code, void *unused)
+{
+ struct msm_otg *motg = container_of(this, struct msm_otg, reboot);
+
+ /*
+ * Ensure that D+/D- lines are routed to uB connector, so
+ * we could load bootloader/kernel at next reboot
+ */
+ gpiod_set_value_cansleep(motg->switch_gpio, 0);
+ return NOTIFY_DONE;
+}
+
static int msm_otg_probe(struct platform_device *pdev)
{
struct regulator_bulk_data regs[3];
@@ -1779,6 +1809,17 @@
dev_dbg(&pdev->dev, "Can not create mode change file\n");
}
+ if (test_bit(B_SESS_VLD, &motg->inputs)) {
+ /* Switch D+/D- lines to Device connector */
+ gpiod_set_value_cansleep(motg->switch_gpio, 0);
+ } else {
+ /* Switch D+/D- lines to Hub */
+ gpiod_set_value_cansleep(motg->switch_gpio, 1);
+ }
+
+ motg->reboot.notifier_call = msm_otg_reboot_notify;
+ register_reboot_notifier(&motg->reboot);
+
pm_runtime_set_active(&pdev->dev);
pm_runtime_enable(&pdev->dev);
@@ -1805,10 +1846,16 @@
if (phy->otg->host || phy->otg->gadget)
return -EBUSY;
- if (motg->id.conn.edev)
- extcon_unregister_interest(&motg->id.conn);
- if (motg->vbus.conn.edev)
- extcon_unregister_interest(&motg->vbus.conn);
+ unregister_reboot_notifier(&motg->reboot);
+
+ /*
+ * Ensure that D+/D- lines are routed to uB connector, so
+ * we could load bootloader/kernel at next reboot
+ */
+ gpiod_set_value_cansleep(motg->switch_gpio, 0);
+
+ extcon_unregister_notifier(motg->id.extcon, EXTCON_USB_HOST, &motg->id.nb);
+ extcon_unregister_notifier(motg->vbus.extcon, EXTCON_USB, &motg->vbus.nb);
msm_otg_debugfs_cleanup();
cancel_delayed_work_sync(&motg->chg_work);
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index 3fcc048..4d863eb 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -506,11 +506,7 @@
device_set_wakeup_capable(&pdev->dev, true);
- ret = usb_add_phy_dev(&mxs_phy->phy);
- if (ret)
- return ret;
-
- return 0;
+ return usb_add_phy_dev(&mxs_phy->phy);
}
static int mxs_phy_remove(struct platform_device *pdev)
diff --git a/drivers/usb/phy/phy-omap-otg.c b/drivers/usb/phy/phy-omap-otg.c
index 56ee760..1270906 100644
--- a/drivers/usb/phy/phy-omap-otg.c
+++ b/drivers/usb/phy/phy-omap-otg.c
@@ -30,8 +30,7 @@
void __iomem *base;
bool id;
bool vbus;
- struct extcon_specific_cable_nb vbus_dev;
- struct extcon_specific_cable_nb id_dev;
+ struct extcon_dev *extcon;
struct notifier_block vbus_nb;
struct notifier_block id_nb;
};
@@ -106,6 +105,7 @@
extcon = extcon_get_extcon_dev(config->extcon);
if (!extcon)
return -EPROBE_DEFER;
+ otg_dev->extcon = extcon;
otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL);
if (!otg_dev)
@@ -118,20 +118,19 @@
otg_dev->id_nb.notifier_call = omap_otg_id_notifier;
otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier;
- ret = extcon_register_interest(&otg_dev->id_dev, config->extcon,
- "USB-HOST", &otg_dev->id_nb);
+ ret = extcon_register_notifier(extcon, EXTCON_USB_HOST, &otg_dev->id_nb);
if (ret)
return ret;
- ret = extcon_register_interest(&otg_dev->vbus_dev, config->extcon,
- "USB", &otg_dev->vbus_nb);
+ ret = extcon_register_notifier(extcon, EXTCON_USB, &otg_dev->vbus_nb);
if (ret) {
- extcon_unregister_interest(&otg_dev->id_dev);
+ extcon_unregister_notifier(extcon, EXTCON_USB_HOST,
+ &otg_dev->id_nb);
return ret;
}
- otg_dev->id = extcon_get_cable_state(extcon, "USB-HOST");
- otg_dev->vbus = extcon_get_cable_state(extcon, "USB");
+ otg_dev->id = extcon_get_cable_state_(extcon, EXTCON_USB_HOST);
+ otg_dev->vbus = extcon_get_cable_state_(extcon, EXTCON_USB);
omap_otg_set_mode(otg_dev);
rev = readl(otg_dev->base);
@@ -147,9 +146,10 @@
static int omap_otg_remove(struct platform_device *pdev)
{
struct otg_device *otg_dev = platform_get_drvdata(pdev);
+ struct extcon_dev *edev = otg_dev->extcon;
- extcon_unregister_interest(&otg_dev->id_dev);
- extcon_unregister_interest(&otg_dev->vbus_dev);
+ extcon_unregister_notifier(edev, EXTCON_USB_HOST,&otg_dev->id_nb);
+ extcon_unregister_notifier(edev, EXTCON_USB, &otg_dev->vbus_nb);
return 0;
}
diff --git a/drivers/usb/phy/phy-qcom-8x16-usb.c b/drivers/usb/phy/phy-qcom-8x16-usb.c
new file mode 100644
index 0000000..5d357a9
--- /dev/null
+++ b/drivers/usb/phy/phy-qcom-8x16-usb.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/extcon.h>
+#include <linux/gpio/consumer.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+#include <linux/regulator/consumer.h>
+#include <linux/reset.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/ulpi.h>
+
+#define HSPHY_AHBBURST 0x0090
+#define HSPHY_AHBMODE 0x0098
+#define HSPHY_GENCONFIG 0x009c
+#define HSPHY_GENCONFIG_2 0x00a0
+
+#define HSPHY_USBCMD 0x0140
+#define HSPHY_ULPI_VIEWPORT 0x0170
+#define HSPHY_CTRL 0x0240
+
+#define HSPHY_TXFIFO_IDLE_FORCE_DIS BIT(4)
+#define HSPHY_SESS_VLD_CTRL_EN BIT(7)
+#define HSPHY_POR_ASSERT BIT(0)
+#define HSPHY_RETEN BIT(1)
+
+#define HSPHY_SESS_VLD_CTRL BIT(25)
+
+#define ULPI_PWR_CLK_MNG_REG 0x88
+#define ULPI_PWR_OTG_COMP_DISABLE BIT(0)
+
+#define ULPI_MISC_A 0x96
+#define ULPI_MISC_A_VBUSVLDEXTSEL BIT(1)
+#define ULPI_MISC_A_VBUSVLDEXT BIT(0)
+
+#define HSPHY_3P3_MIN 3050000 /* uV */
+#define HSPHY_3P3_MAX 3300000 /* uV */
+
+#define HSPHY_1P8_MIN 1800000 /* uV */
+#define HSPHY_1P8_MAX 1800000 /* uV */
+
+#define HSPHY_VDD_MIN 5
+#define HSPHY_VDD_MAX 7
+
+struct phy_8x16 {
+ struct usb_phy phy;
+ void __iomem *regs;
+ struct clk *core_clk;
+ struct clk *iface_clk;
+ struct regulator *v3p3;
+ struct regulator *v1p8;
+ struct regulator *vdd;
+
+ struct reset_control *phy_reset;
+
+ struct extcon_specific_cable_nb vbus_cable;
+ struct notifier_block vbus_notify;
+
+ struct gpio_desc *switch_gpio;
+ struct notifier_block reboot_notify;
+};
+
+static int phy_8x16_regulators_enable(struct phy_8x16 *qphy)
+{
+ int ret;
+
+ ret = regulator_set_voltage(qphy->vdd, HSPHY_VDD_MIN, HSPHY_VDD_MAX);
+ if (ret)
+ return ret;
+
+ ret = regulator_enable(qphy->vdd);
+ if (ret)
+ return ret;
+
+ ret = regulator_set_voltage(qphy->v3p3, HSPHY_3P3_MIN, HSPHY_3P3_MAX);
+ if (ret)
+ goto off_vdd;
+
+ ret = regulator_enable(qphy->v3p3);
+ if (ret)
+ goto off_vdd;
+
+ ret = regulator_set_voltage(qphy->v1p8, HSPHY_1P8_MIN, HSPHY_1P8_MAX);
+ if (ret)
+ goto off_3p3;
+
+ ret = regulator_enable(qphy->v1p8);
+ if (ret)
+ goto off_3p3;
+
+ return 0;
+
+off_3p3:
+ regulator_disable(qphy->v3p3);
+off_vdd:
+ regulator_disable(qphy->vdd);
+
+ return ret;
+}
+
+static void phy_8x16_regulators_disable(struct phy_8x16 *qphy)
+{
+ regulator_disable(qphy->v1p8);
+ regulator_disable(qphy->v3p3);
+ regulator_disable(qphy->vdd);
+}
+
+static int phy_8x16_notify_connect(struct usb_phy *phy,
+ enum usb_device_speed speed)
+{
+ struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy);
+ u32 val;
+
+ val = ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT;
+ usb_phy_io_write(&qphy->phy, val, ULPI_SET(ULPI_MISC_A));
+
+ val = readl(qphy->regs + HSPHY_USBCMD);
+ val |= HSPHY_SESS_VLD_CTRL;
+ writel(val, qphy->regs + HSPHY_USBCMD);
+
+ return 0;
+}
+
+static int phy_8x16_notify_disconnect(struct usb_phy *phy,
+ enum usb_device_speed speed)
+{
+ struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy);
+ u32 val;
+
+ val = ULPI_MISC_A_VBUSVLDEXT | ULPI_MISC_A_VBUSVLDEXTSEL;
+ usb_phy_io_write(&qphy->phy, val, ULPI_CLR(ULPI_MISC_A));
+
+ val = readl(qphy->regs + HSPHY_USBCMD);
+ val &= ~HSPHY_SESS_VLD_CTRL;
+ writel(val, qphy->regs + HSPHY_USBCMD);
+
+ return 0;
+}
+
+static int phy_8x16_vbus_on(struct phy_8x16 *qphy)
+{
+ phy_8x16_notify_connect(&qphy->phy, USB_SPEED_UNKNOWN);
+
+ /* Switch D+/D- lines to Device connector */
+ gpiod_set_value_cansleep(qphy->switch_gpio, 0);
+
+ return 0;
+}
+
+static int phy_8x16_vbus_off(struct phy_8x16 *qphy)
+{
+ phy_8x16_notify_disconnect(&qphy->phy, USB_SPEED_UNKNOWN);
+
+ /* Switch D+/D- lines to USB HUB */
+ gpiod_set_value_cansleep(qphy->switch_gpio, 1);
+
+ return 0;
+}
+
+static int phy_8x16_vbus_notify(struct notifier_block *nb, unsigned long event,
+ void *ptr)
+{
+ struct phy_8x16 *qphy = container_of(nb, struct phy_8x16, vbus_notify);
+
+ if (event)
+ phy_8x16_vbus_on(qphy);
+ else
+ phy_8x16_vbus_off(qphy);
+
+ return NOTIFY_DONE;
+}
+
+static int phy_8x16_init(struct usb_phy *phy)
+{
+ struct phy_8x16 *qphy = container_of(phy, struct phy_8x16, phy);
+ u32 val, init[] = {0x44, 0x6B, 0x24, 0x13};
+ u32 addr = ULPI_EXT_VENDOR_SPECIFIC;
+ int idx, state;
+
+ for (idx = 0; idx < ARRAY_SIZE(init); idx++)
+ usb_phy_io_write(phy, init[idx], addr + idx);
+
+ reset_control_reset(qphy->phy_reset);
+
+ /* Assert USB HSPHY_POR */
+ val = readl(qphy->regs + HSPHY_CTRL);
+ val |= HSPHY_POR_ASSERT;
+ writel(val, qphy->regs + HSPHY_CTRL);
+
+ /*
+ * wait for minimum 10 microseconds as suggested in HPG.
+ * Use a slightly larger value since the exact value didn't
+ * work 100% of the time.
+ */
+ usleep_range(12, 15);
+
+ /* Deassert USB HSPHY_POR */
+ val = readl(qphy->regs + HSPHY_CTRL);
+ val &= ~HSPHY_POR_ASSERT;
+ writel(val, qphy->regs + HSPHY_CTRL);
+
+ usleep_range(10, 15);
+
+ writel(0x00, qphy->regs + HSPHY_AHBBURST);
+ writel(0x08, qphy->regs + HSPHY_AHBMODE);
+
+ /* workaround for rx buffer collision issue */
+ val = readl(qphy->regs + HSPHY_GENCONFIG);
+ val &= ~HSPHY_TXFIFO_IDLE_FORCE_DIS;
+ writel(val, qphy->regs + HSPHY_GENCONFIG);
+
+ val = readl(qphy->regs + HSPHY_GENCONFIG_2);
+ val |= HSPHY_SESS_VLD_CTRL_EN;
+ writel(val, qphy->regs + HSPHY_GENCONFIG_2);
+
+ val = ULPI_PWR_OTG_COMP_DISABLE;
+ usb_phy_io_write(phy, val, ULPI_SET(ULPI_PWR_CLK_MNG_REG));
+
+ state = extcon_get_cable_state(qphy->vbus_cable.edev, "USB");
+ if (state)
+ phy_8x16_vbus_on(qphy);
+ else
+ phy_8x16_vbus_off(qphy);
+
+ val = usb_phy_io_read(&qphy->phy, ULPI_FUNC_CTRL);
+ val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ val |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
+ usb_phy_io_write(&qphy->phy, val, ULPI_FUNC_CTRL);
+
+ return 0;
+}
+
+static void phy_8x16_shutdown(struct usb_phy *phy)
+{
+ u32 val;
+
+ /* Put the controller in non-driving mode */
+ val = usb_phy_io_read(phy, ULPI_FUNC_CTRL);
+ val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
+ val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
+ usb_phy_io_write(phy, val, ULPI_FUNC_CTRL);
+}
+
+static int phy_8x16_read_devicetree(struct phy_8x16 *qphy)
+{
+ struct regulator_bulk_data regs[3];
+ struct device *dev = qphy->phy.dev;
+ int ret;
+
+ qphy->core_clk = devm_clk_get(dev, "core");
+ if (IS_ERR(qphy->core_clk))
+ return PTR_ERR(qphy->core_clk);
+
+ qphy->iface_clk = devm_clk_get(dev, "iface");
+ if (IS_ERR(qphy->iface_clk))
+ return PTR_ERR(qphy->iface_clk);
+
+ regs[0].supply = "v3p3";
+ regs[1].supply = "v1p8";
+ regs[2].supply = "vddcx";
+
+ ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(regs), regs);
+ if (ret)
+ return ret;
+
+ qphy->v3p3 = regs[0].consumer;
+ qphy->v1p8 = regs[1].consumer;
+ qphy->vdd = regs[2].consumer;
+
+ qphy->phy_reset = devm_reset_control_get(dev, "phy");
+ if (IS_ERR(qphy->phy_reset))
+ return PTR_ERR(qphy->phy_reset);
+
+ qphy->switch_gpio = devm_gpiod_get_optional(dev, "switch",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(qphy->switch_gpio))
+ return PTR_ERR(qphy->switch_gpio);
+
+ return 0;
+}
+
+static int phy_8x16_reboot_notify(struct notifier_block *this,
+ unsigned long code, void *unused)
+{
+ struct phy_8x16 *qphy;
+
+ qphy = container_of(this, struct phy_8x16, reboot_notify);
+
+ /*
+ * Ensure that D+/D- lines are routed to uB connector, so
+ * we could load bootloader/kernel at next reboot_notify
+ */
+ gpiod_set_value_cansleep(qphy->switch_gpio, 0);
+ return NOTIFY_DONE;
+}
+
+static int phy_8x16_probe(struct platform_device *pdev)
+{
+ struct extcon_dev *edev;
+ struct phy_8x16 *qphy;
+ struct resource *res;
+ struct usb_phy *phy;
+ int ret;
+
+ qphy = devm_kzalloc(&pdev->dev, sizeof(*qphy), GFP_KERNEL);
+ if (!qphy)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, qphy);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -EINVAL;
+
+ qphy->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+ if (!qphy->regs)
+ return -ENOMEM;
+
+ phy = &qphy->phy;
+ phy->dev = &pdev->dev;
+ phy->label = dev_name(&pdev->dev);
+ phy->init = phy_8x16_init;
+ phy->shutdown = phy_8x16_shutdown;
+ phy->notify_connect = phy_8x16_notify_connect;
+ phy->notify_disconnect = phy_8x16_notify_disconnect;
+ phy->io_priv = qphy->regs + HSPHY_ULPI_VIEWPORT;
+ phy->io_ops = &ulpi_viewport_access_ops;
+ phy->type = USB_PHY_TYPE_USB2;
+
+ ret = phy_8x16_read_devicetree(qphy);
+ if (ret < 0)
+ return ret;
+
+ edev = extcon_get_edev_by_phandle(phy->dev, 0);
+ if (IS_ERR(edev))
+ return PTR_ERR(edev);
+
+ ret = clk_set_rate(qphy->core_clk, INT_MAX);
+ if (ret < 0)
+ dev_dbg(phy->dev, "Can't boost core clock\n");
+
+ ret = clk_prepare_enable(qphy->core_clk);
+ if (ret < 0)
+ return ret;
+
+ ret = clk_prepare_enable(qphy->iface_clk);
+ if (ret < 0)
+ goto off_core;
+
+ ret = phy_8x16_regulators_enable(qphy);
+ if (0 && ret)
+ goto off_clks;
+
+ qphy->vbus_notify.notifier_call = phy_8x16_vbus_notify;
+ ret = extcon_register_interest(&qphy->vbus_cable, edev->name,
+ "USB", &qphy->vbus_notify);
+ if (ret < 0)
+ goto off_power;
+
+ ret = usb_add_phy_dev(&qphy->phy);
+ if (ret)
+ goto off_extcon;
+
+ qphy->reboot_notify.notifier_call = phy_8x16_reboot_notify;
+ register_reboot_notifier(&qphy->reboot_notify);
+
+ return 0;
+
+off_extcon:
+ extcon_unregister_interest(&qphy->vbus_cable);
+off_power:
+ phy_8x16_regulators_disable(qphy);
+off_clks:
+ clk_disable_unprepare(qphy->iface_clk);
+off_core:
+ clk_disable_unprepare(qphy->core_clk);
+ return ret;
+}
+
+static int phy_8x16_remove(struct platform_device *pdev)
+{
+ struct phy_8x16 *qphy = platform_get_drvdata(pdev);
+
+ unregister_reboot_notifier(&qphy->reboot_notify);
+ extcon_unregister_interest(&qphy->vbus_cable);
+
+ /*
+ * Ensure that D+/D- lines are routed to uB connector, so
+ * we could load bootloader/kernel at next reboot_notify
+ */
+ gpiod_set_value_cansleep(qphy->switch_gpio, 0);
+
+ usb_remove_phy(&qphy->phy);
+
+ clk_disable_unprepare(qphy->iface_clk);
+ clk_disable_unprepare(qphy->core_clk);
+ phy_8x16_regulators_disable(qphy);
+ return 0;
+}
+
+static const struct of_device_id phy_8x16_dt_match[] = {
+ { .compatible = "qcom,usb-8x16-phy" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, phy_8x16_dt_match);
+
+static struct platform_driver phy_8x16_driver = {
+ .probe = phy_8x16_probe,
+ .remove = phy_8x16_remove,
+ .driver = {
+ .name = "phy-qcom-8x16-usb",
+ .of_match_table = phy_8x16_dt_match,
+ },
+};
+module_platform_driver(phy_8x16_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Qualcomm APQ8016/MSM8916 chipsets USB transceiver driver");
diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
index b40d6a8..ab5d364 100644
--- a/drivers/usb/phy/phy-tahvo.c
+++ b/drivers/usb/phy/phy-tahvo.c
@@ -57,7 +57,7 @@
struct clk *ick;
int irq;
int tahvo_mode;
- struct extcon_dev extcon;
+ struct extcon_dev *extcon;
};
static const unsigned int tahvo_cable[] = {
@@ -121,7 +121,7 @@
prev_state = tu->vbus_state;
tu->vbus_state = reg & TAHVO_STAT_VBUS;
if (prev_state != tu->vbus_state) {
- extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state);
+ extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state);
sysfs_notify(&tu->pt_dev->dev.kobj, NULL, "vbus_state");
}
}
@@ -130,7 +130,7 @@
{
struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
- extcon_set_cable_state(&tu->extcon, "USB-HOST", true);
+ extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, true);
/* Power up the transceiver in USB host mode */
retu_write(rdev, TAHVO_REG_USBR, USBR_REGOUT | USBR_NSUSPEND |
@@ -149,7 +149,7 @@
{
struct retu_dev *rdev = dev_get_drvdata(tu->pt_dev->dev.parent);
- extcon_set_cable_state(&tu->extcon, "USB-HOST", false);
+ extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST, false);
/* Power up transceiver and set it in USB peripheral mode */
retu_write(rdev, TAHVO_REG_USBR, USBR_SLAVE_CONTROL | USBR_REGOUT |
@@ -365,11 +365,13 @@
*/
tu->vbus_state = retu_read(rdev, TAHVO_REG_IDSR) & TAHVO_STAT_VBUS;
- tu->extcon.name = DRIVER_NAME;
- tu->extcon.supported_cable = tahvo_cable;
- tu->extcon.dev.parent = &pdev->dev;
+ tu->extcon = devm_extcon_dev_allocate(&pdev->dev, tahvo_cable);
+ if (IS_ERR(tu->extcon)) {
+ dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
+ return -ENOMEM;
+ }
- ret = extcon_dev_register(&tu->extcon);
+ ret = devm_extcon_dev_register(&pdev->dev, tu->extcon);
if (ret) {
dev_err(&pdev->dev, "could not register extcon device: %d\n",
ret);
@@ -377,9 +379,9 @@
}
/* Set the initial cable state. */
- extcon_set_cable_state(&tu->extcon, "USB-HOST",
+ extcon_set_cable_state_(tu->extcon, EXTCON_USB_HOST,
tu->tahvo_mode == TAHVO_MODE_HOST);
- extcon_set_cable_state(&tu->extcon, "USB", tu->vbus_state);
+ extcon_set_cable_state_(tu->extcon, EXTCON_USB, tu->vbus_state);
/* Create OTG interface */
tahvo_usb_power_off(tu);
@@ -396,7 +398,7 @@
if (ret < 0) {
dev_err(&pdev->dev, "cannot register USB transceiver: %d\n",
ret);
- goto err_extcon_unreg;
+ goto err_disable_clk;
}
dev_set_drvdata(&pdev->dev, tu);
@@ -424,8 +426,6 @@
free_irq(tu->irq, tu);
err_remove_phy:
usb_remove_phy(&tu->phy);
-err_extcon_unreg:
- extcon_dev_unregister(&tu->extcon);
err_disable_clk:
if (!IS_ERR(tu->ick))
clk_disable(tu->ick);
@@ -440,7 +440,6 @@
sysfs_remove_group(&pdev->dev.kobj, &tahvo_attr_group);
free_irq(tu->irq, tu);
usb_remove_phy(&tu->phy);
- extcon_dev_unregister(&tu->extcon);
if (!IS_ERR(tu->ick))
clk_disable(tu->ick);
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index e8bf408..7b98e1d 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -388,7 +388,7 @@
if (enable && !mod) {
if (priv->edev) {
- cable = extcon_get_cable_state(priv->edev, "USB-HOST");
+ cable = extcon_get_cable_state_(priv->edev, EXTCON_USB_HOST);
if ((cable > 0 && id != USBHS_HOST) ||
(!cable && id != USBHS_GADGET)) {
dev_info(&pdev->dev,
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index dc2aa32..de4f97d 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/otg.h>
#include "common.h"
/*
@@ -50,6 +51,8 @@
int uep_size;
struct usb_gadget_driver *driver;
+ struct usb_phy *transceiver;
+ bool vbus_active;
u32 status;
#define USBHSG_STATUS_STARTED (1 << 0)
@@ -873,6 +876,27 @@
}
/*
+ * VBUS provided by the PHY
+ */
+static int usbhsm_phy_get_vbus(struct platform_device *pdev)
+{
+ struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
+ struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
+
+ return gpriv->vbus_active;
+}
+
+static void usbhs_mod_phy_mode(struct usbhs_priv *priv)
+{
+ struct usbhs_mod_info *info = &priv->mod_info;
+
+ info->irq_vbus = NULL;
+ priv->pfunc.get_vbus = usbhsm_phy_get_vbus;
+
+ usbhs_irq_callback_update(priv, NULL);
+}
+
+/*
*
* linux usb function
*
@@ -882,12 +906,28 @@
{
struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
+ struct device *dev = usbhs_priv_to_dev(priv);
+ int ret;
if (!driver ||
!driver->setup ||
driver->max_speed < USB_SPEED_FULL)
return -EINVAL;
+ /* connect to bus through transceiver */
+ if (!IS_ERR_OR_NULL(gpriv->transceiver)) {
+ ret = otg_set_peripheral(gpriv->transceiver->otg,
+ &gpriv->gadget);
+ if (ret) {
+ dev_err(dev, "%s: can't bind to transceiver\n",
+ gpriv->gadget.name);
+ return ret;
+ }
+
+ /* get vbus using phy versions */
+ usbhs_mod_phy_mode(priv);
+ }
+
/* first hook up the driver ... */
gpriv->driver = driver;
@@ -900,6 +940,10 @@
struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
usbhsg_try_stop(priv, USBHSG_STATUS_REGISTERD);
+
+ if (!IS_ERR_OR_NULL(gpriv->transceiver))
+ otg_set_peripheral(gpriv->transceiver->otg, NULL);
+
gpriv->driver = NULL;
return 0;
@@ -947,12 +991,26 @@
return 0;
}
+static int usbhsg_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+ struct usbhsg_gpriv *gpriv = usbhsg_gadget_to_gpriv(gadget);
+ struct usbhs_priv *priv = usbhsg_gpriv_to_priv(gpriv);
+ struct platform_device *pdev = usbhs_priv_to_pdev(priv);
+
+ gpriv->vbus_active = !!is_active;
+
+ renesas_usbhs_call_notify_hotplug(pdev);
+
+ return 0;
+}
+
static const struct usb_gadget_ops usbhsg_gadget_ops = {
.get_frame = usbhsg_get_frame,
.set_selfpowered = usbhsg_set_selfpowered,
.udc_start = usbhsg_gadget_start,
.udc_stop = usbhsg_gadget_stop,
.pullup = usbhsg_pullup,
+ .vbus_session = usbhsg_vbus_session,
};
static int usbhsg_start(struct usbhs_priv *priv)
@@ -994,6 +1052,10 @@
goto usbhs_mod_gadget_probe_err_gpriv;
}
+ gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
+ dev_info(dev, "%stransceiver found\n",
+ gpriv->transceiver ? "" : "no ");
+
/*
* CAUTION
*
@@ -1041,12 +1103,18 @@
if (usbhsg_is_dcp(uep)) {
gpriv->gadget.ep0 = &uep->ep;
usb_ep_set_maxpacket_limit(&uep->ep, 64);
+ uep->ep.caps.type_control = true;
}
/* init normal pipe */
else {
usb_ep_set_maxpacket_limit(&uep->ep, 512);
+ uep->ep.caps.type_iso = true;
+ uep->ep.caps.type_bulk = true;
+ uep->ep.caps.type_int = true;
list_add_tail(&uep->ep.ep_list, &gpriv->gadget.ep_list);
}
+ uep->ep.caps.dir_in = true;
+ uep->ep.caps.dir_out = true;
}
ret = usb_add_gadget_udc(dev, &gpriv->gadget);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 4c8b3b8..a5a0376 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -605,6 +605,10 @@
{ USB_DEVICE(FTDI_VID, FTDI_NT_ORIONLXM_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(FTDI_VID, FTDI_SYNAPSE_SS200_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX2WI_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_CUSTOMWARE_MINIPLEX3_PID) },
/*
* ELV devices:
*/
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 792e054..67c6d44 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -568,6 +568,14 @@
*/
#define FTDI_SYNAPSE_SS200_PID 0x9090 /* SS200 - SNAP Stick 200 */
+/*
+ * CustomWare / ShipModul NMEA multiplexers product ids (FTDI_VID)
+ */
+#define FTDI_CUSTOMWARE_MINIPLEX_PID 0xfd48 /* MiniPlex first generation NMEA Multiplexer */
+#define FTDI_CUSTOMWARE_MINIPLEX2_PID 0xfd49 /* MiniPlex-USB and MiniPlex-2 series */
+#define FTDI_CUSTOMWARE_MINIPLEX2WI_PID 0xfd4a /* MiniPlex-2Wi */
+#define FTDI_CUSTOMWARE_MINIPLEX3_PID 0xfd4b /* MiniPlex-3 series */
+
/********************************/
/** third-party VID/PID combos **/
@@ -1365,7 +1373,7 @@
#define FTDI_CTI_NANO_PID 0xF60B
/*
- * ZeitControl cardsystems GmbH rfid-readers http://zeitconrol.de
+ * ZeitControl cardsystems GmbH rfid-readers http://zeitcontrol.de
*/
/* TagTracer MIFARE*/
#define FTDI_ZEITCONTROL_TAGTRACE_MIFARE_PID 0xF7C0
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index ddbb8fe..0ac1b10 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -71,6 +71,25 @@
__u8 hardware_type; /* Type of hardware */
} __attribute__((packed));
+/*
+ * Edgeport firmware header
+ *
+ * "build_number" has been set to 0 in all three of the images I have
+ * seen, and Digi Tech Support suggests that it is safe to ignore it.
+ *
+ * "length" is the number of bytes of actual data following the header.
+ *
+ * "checksum" is the low order byte resulting from adding the values of
+ * all the data bytes.
+ */
+struct edgeport_fw_hdr {
+ u8 major_version;
+ u8 minor_version;
+ __le16 build_number;
+ __le16 length;
+ u8 checksum;
+} __packed;
+
struct edgeport_port {
__u16 uart_base;
__u16 dma_address;
@@ -101,6 +120,9 @@
struct mutex es_lock;
int num_ports_open;
struct usb_serial *serial;
+ struct delayed_work heartbeat_work;
+ int fw_version;
+ bool use_heartbeat;
};
@@ -187,10 +209,6 @@
MODULE_DEVICE_TABLE(usb, id_table_combined);
-static unsigned char OperationalMajorVersion;
-static unsigned char OperationalMinorVersion;
-static unsigned short OperationalBuildNumber;
-
static int closing_wait = EDGE_CLOSING_WAIT;
static bool ignore_cpu_rev;
static int default_uart_mode; /* RS232 */
@@ -209,6 +227,26 @@
static int edge_create_sysfs_attrs(struct usb_serial_port *port);
static int edge_remove_sysfs_attrs(struct usb_serial_port *port);
+/*
+ * Some release of Edgeport firmware "down3.bin" after version 4.80
+ * introduced code to automatically disconnect idle devices on some
+ * Edgeport models after periods of inactivity, typically ~60 seconds.
+ * This occurs without regard to whether ports on the device are open
+ * or not. Digi International Tech Support suggested:
+ *
+ * 1. Adding driver "heartbeat" code to reset the firmware timer by
+ * requesting a descriptor record every 15 seconds, which should be
+ * effective with newer firmware versions that require it, and benign
+ * with older versions that do not. In practice 40 seconds seems often
+ * enough.
+ * 2. The heartbeat code is currently required only on Edgeport/416 models.
+ */
+#define FW_HEARTBEAT_VERSION_CUTOFF ((4 << 8) + 80)
+#define FW_HEARTBEAT_SECS 40
+
+/* Timeouts in msecs: firmware downloads take longer */
+#define TI_VSEND_TIMEOUT_DEFAULT 1000
+#define TI_VSEND_TIMEOUT_FW_DOWNLOAD 10000
static int ti_vread_sync(struct usb_device *dev, __u8 request,
__u16 value, __u16 index, u8 *data, int size)
@@ -228,14 +266,14 @@
return 0;
}
-static int ti_vsend_sync(struct usb_device *dev, __u8 request,
- __u16 value, __u16 index, u8 *data, int size)
+static int ti_vsend_sync(struct usb_device *dev, u8 request, u16 value,
+ u16 index, u8 *data, int size, int timeout)
{
int status;
status = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request,
(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
- value, index, data, size, 1000);
+ value, index, data, size, timeout);
if (status < 0)
return status;
if (status != size) {
@@ -250,7 +288,8 @@
__u8 moduleid, __u16 value, u8 *data,
int size)
{
- return ti_vsend_sync(dev, command, value, moduleid, data, size);
+ return ti_vsend_sync(dev, command, value, moduleid, data, size,
+ TI_VSEND_TIMEOUT_DEFAULT);
}
/* clear tx/rx buffers and fifo in TI UMP */
@@ -378,9 +417,9 @@
}
for (i = 0; i < length; ++i) {
- status = ti_vsend_sync(serial->serial->dev,
- UMPC_MEMORY_WRITE, buffer[i],
- (__u16)(i + start_address), NULL, 0);
+ status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
+ buffer[i], (u16)(i + start_address), NULL,
+ 0, TI_VSEND_TIMEOUT_DEFAULT);
if (status)
return status;
}
@@ -421,10 +460,9 @@
* regardless of host byte order.
*/
be_start_address = swab16((u16)start_address);
- status = ti_vsend_sync(serial->serial->dev,
- UMPC_MEMORY_WRITE, (__u16)address_type,
- be_start_address,
- buffer, write_length);
+ status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
+ (u16)address_type, be_start_address,
+ buffer, write_length, TI_VSEND_TIMEOUT_DEFAULT);
if (status) {
dev_dbg(dev, "%s - ERROR %d\n", __func__, status);
return status;
@@ -454,9 +492,8 @@
*/
be_start_address = swab16((u16)start_address);
status = ti_vsend_sync(serial->serial->dev, UMPC_MEMORY_WRITE,
- (__u16)address_type,
- be_start_address,
- buffer, write_length);
+ (u16)address_type, be_start_address, buffer,
+ write_length, TI_VSEND_TIMEOUT_DEFAULT);
if (status) {
dev_err(dev, "%s - ERROR %d\n", __func__, status);
return status;
@@ -748,18 +785,17 @@
}
/* Build firmware header used for firmware update */
-static int build_i2c_fw_hdr(__u8 *header, struct device *dev)
+static int build_i2c_fw_hdr(u8 *header, struct device *dev,
+ const struct firmware *fw)
{
__u8 *buffer;
int buffer_size;
int i;
- int err;
__u8 cs = 0;
struct ti_i2c_desc *i2c_header;
struct ti_i2c_image_header *img_header;
struct ti_i2c_firmware_rec *firmware_rec;
- const struct firmware *fw;
- const char *fw_name = "edgeport/down3.bin";
+ struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
/* In order to update the I2C firmware we must change the type 2 record
* to type 0xF2. This will force the UMP to come up in Boot Mode.
@@ -782,24 +818,11 @@
// Set entire image of 0xffs
memset(buffer, 0xff, buffer_size);
- err = request_firmware(&fw, fw_name, dev);
- if (err) {
- dev_err(dev, "Failed to load image \"%s\" err %d\n",
- fw_name, err);
- kfree(buffer);
- return err;
- }
-
- /* Save Download Version Number */
- OperationalMajorVersion = fw->data[0];
- OperationalMinorVersion = fw->data[1];
- OperationalBuildNumber = fw->data[2] | (fw->data[3] << 8);
-
/* Copy version number into firmware record */
firmware_rec = (struct ti_i2c_firmware_rec *)buffer;
- firmware_rec->Ver_Major = OperationalMajorVersion;
- firmware_rec->Ver_Minor = OperationalMinorVersion;
+ firmware_rec->Ver_Major = fw_hdr->major_version;
+ firmware_rec->Ver_Minor = fw_hdr->minor_version;
/* Pointer to fw_down memory image */
img_header = (struct ti_i2c_image_header *)&fw->data[4];
@@ -808,8 +831,6 @@
&fw->data[4 + sizeof(struct ti_i2c_image_header)],
le16_to_cpu(img_header->Length));
- release_firmware(fw);
-
for (i=0; i < buffer_size; i++) {
cs = (__u8)(cs + buffer[i]);
}
@@ -823,8 +844,8 @@
i2c_header->Type = I2C_DESC_TYPE_FIRMWARE_BLANK;
i2c_header->Size = cpu_to_le16(buffer_size);
i2c_header->CheckSum = cs;
- firmware_rec->Ver_Major = OperationalMajorVersion;
- firmware_rec->Ver_Minor = OperationalMinorVersion;
+ firmware_rec->Ver_Major = fw_hdr->major_version;
+ firmware_rec->Ver_Minor = fw_hdr->minor_version;
return 0;
}
@@ -925,13 +946,49 @@
return TI_GET_CPU_REVISION(desc->CpuRev_BoardRev);
}
+static int check_fw_sanity(struct edgeport_serial *serial,
+ const struct firmware *fw)
+{
+ u16 length_total;
+ u8 checksum = 0;
+ int pos;
+ struct device *dev = &serial->serial->interface->dev;
+ struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
+ if (fw->size < sizeof(struct edgeport_fw_hdr)) {
+ dev_err(dev, "incomplete fw header\n");
+ return -EINVAL;
+ }
+
+ length_total = le16_to_cpu(fw_hdr->length) +
+ sizeof(struct edgeport_fw_hdr);
+
+ if (fw->size != length_total) {
+ dev_err(dev, "bad fw size (expected: %u, got: %zu)\n",
+ length_total, fw->size);
+ return -EINVAL;
+ }
+
+ for (pos = sizeof(struct edgeport_fw_hdr); pos < fw->size; ++pos)
+ checksum += fw->data[pos];
+
+ if (checksum != fw_hdr->checksum) {
+ dev_err(dev, "bad fw checksum (expected: 0x%x, got: 0x%x)\n",
+ fw_hdr->checksum, checksum);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* DownloadTIFirmware - Download run-time operating firmware to the TI5052
*
* This routine downloads the main operating code into the TI5052, using the
* boot code already burned into E2PROM or ROM.
*/
-static int download_fw(struct edgeport_serial *serial)
+static int download_fw(struct edgeport_serial *serial,
+ const struct firmware *fw)
{
struct device *dev = &serial->serial->dev->dev;
int status = 0;
@@ -940,6 +997,14 @@
struct usb_interface_descriptor *interface;
int download_cur_ver;
int download_new_ver;
+ struct edgeport_fw_hdr *fw_hdr = (struct edgeport_fw_hdr *)fw->data;
+
+ if (check_fw_sanity(serial, fw))
+ return -EINVAL;
+
+ /* If on-board version is newer, "fw_version" will be updated below. */
+ serial->fw_version = (fw_hdr->major_version << 8) +
+ fw_hdr->minor_version;
/* This routine is entered by both the BOOT mode and the Download mode
* We can determine which code is running by the reading the config
@@ -1047,14 +1112,13 @@
version in I2c */
download_cur_ver = (firmware_version->Ver_Major << 8) +
(firmware_version->Ver_Minor);
- download_new_ver = (OperationalMajorVersion << 8) +
- (OperationalMinorVersion);
+ download_new_ver = (fw_hdr->major_version << 8) +
+ (fw_hdr->minor_version);
dev_dbg(dev, "%s - >> FW Versions Device %d.%d Driver %d.%d\n",
__func__, firmware_version->Ver_Major,
firmware_version->Ver_Minor,
- OperationalMajorVersion,
- OperationalMinorVersion);
+ fw_hdr->major_version, fw_hdr->minor_version);
/* Check if we have an old version in the I2C and
update if necessary */
@@ -1063,8 +1127,8 @@
__func__,
firmware_version->Ver_Major,
firmware_version->Ver_Minor,
- OperationalMajorVersion,
- OperationalMinorVersion);
+ fw_hdr->major_version,
+ fw_hdr->minor_version);
record = kmalloc(1, GFP_KERNEL);
if (!record) {
@@ -1129,7 +1193,8 @@
/* Reset UMP -- Back to BOOT MODE */
status = ti_vsend_sync(serial->serial->dev,
UMPC_HARDWARE_RESET,
- 0, 0, NULL, 0);
+ 0, 0, NULL, 0,
+ TI_VSEND_TIMEOUT_DEFAULT);
dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status);
@@ -1139,6 +1204,9 @@
kfree(rom_desc);
kfree(ti_manuf_desc);
return -ENODEV;
+ } else {
+ /* Same or newer fw version is already loaded */
+ serial->fw_version = download_cur_ver;
}
kfree(firmware_version);
}
@@ -1177,7 +1245,7 @@
* UMP Ram to I2C and the firmware will update the
* record type from 0xf2 to 0x02.
*/
- status = build_i2c_fw_hdr(header, dev);
+ status = build_i2c_fw_hdr(header, dev, fw);
if (status) {
kfree(vheader);
kfree(header);
@@ -1229,7 +1297,9 @@
/* Tell firmware to copy download image into I2C */
status = ti_vsend_sync(serial->serial->dev,
- UMPC_COPY_DNLD_TO_I2C, 0, 0, NULL, 0);
+ UMPC_COPY_DNLD_TO_I2C,
+ 0, 0, NULL, 0,
+ TI_VSEND_TIMEOUT_FW_DOWNLOAD);
dev_dbg(dev, "%s - Update complete 0x%x\n", __func__, status);
if (status) {
@@ -1278,9 +1348,6 @@
__u8 cs = 0;
__u8 *buffer;
int buffer_size;
- int err;
- const struct firmware *fw;
- const char *fw_name = "edgeport/down3.bin";
/* Validate Hardware version number
* Read Manufacturing Descriptor from TI Based Edgeport
@@ -1328,16 +1395,7 @@
/* Initialize the buffer to 0xff (pad the buffer) */
memset(buffer, 0xff, buffer_size);
-
- err = request_firmware(&fw, fw_name, dev);
- if (err) {
- dev_err(dev, "Failed to load image \"%s\" err %d\n",
- fw_name, err);
- kfree(buffer);
- return err;
- }
memcpy(buffer, &fw->data[4], fw->size - 4);
- release_firmware(fw);
for (i = sizeof(struct ti_i2c_image_header);
i < buffer_size; i++) {
@@ -1352,7 +1410,9 @@
header->CheckSum = cs;
/* Download the operational code */
- dev_dbg(dev, "%s - Downloading operational code image (TI UMP)\n", __func__);
+ dev_dbg(dev, "%s - Downloading operational code image version %d.%d (TI UMP)\n",
+ __func__,
+ fw_hdr->major_version, fw_hdr->minor_version);
status = download_code(serial, buffer, buffer_size);
kfree(buffer);
@@ -2373,10 +2433,44 @@
__func__, status);
}
+static void edge_heartbeat_schedule(struct edgeport_serial *edge_serial)
+{
+ if (!edge_serial->use_heartbeat)
+ return;
+
+ schedule_delayed_work(&edge_serial->heartbeat_work,
+ FW_HEARTBEAT_SECS * HZ);
+}
+
+static void edge_heartbeat_work(struct work_struct *work)
+{
+ struct edgeport_serial *serial;
+ struct ti_i2c_desc *rom_desc;
+
+ serial = container_of(work, struct edgeport_serial,
+ heartbeat_work.work);
+
+ rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL);
+
+ /* Descriptor address request is enough to reset the firmware timer */
+ if (!rom_desc || !get_descriptor_addr(serial, I2C_DESC_TYPE_ION,
+ rom_desc)) {
+ dev_err(&serial->serial->interface->dev,
+ "%s - Incomplete heartbeat\n", __func__);
+ }
+ kfree(rom_desc);
+
+ edge_heartbeat_schedule(serial);
+}
+
static int edge_startup(struct usb_serial *serial)
{
struct edgeport_serial *edge_serial;
int status;
+ const struct firmware *fw;
+ const char *fw_name = "edgeport/down3.bin";
+ struct device *dev = &serial->interface->dev;
+ u16 product_id;
/* create our private serial structure */
edge_serial = kzalloc(sizeof(struct edgeport_serial), GFP_KERNEL);
@@ -2387,12 +2481,35 @@
edge_serial->serial = serial;
usb_set_serial_data(serial, edge_serial);
- status = download_fw(edge_serial);
+ status = request_firmware(&fw, fw_name, dev);
+ if (status) {
+ dev_err(dev, "Failed to load image \"%s\" err %d\n",
+ fw_name, status);
+ kfree(edge_serial);
+ return status;
+ }
+
+ status = download_fw(edge_serial, fw);
+ release_firmware(fw);
if (status) {
kfree(edge_serial);
return status;
}
+ product_id = le16_to_cpu(
+ edge_serial->serial->dev->descriptor.idProduct);
+
+ /* Currently only the EP/416 models require heartbeat support */
+ if (edge_serial->fw_version > FW_HEARTBEAT_VERSION_CUTOFF) {
+ if (product_id == ION_DEVICE_ID_TI_EDGEPORT_416 ||
+ product_id == ION_DEVICE_ID_TI_EDGEPORT_416B) {
+ edge_serial->use_heartbeat = true;
+ }
+ }
+
+ INIT_DELAYED_WORK(&edge_serial->heartbeat_work, edge_heartbeat_work);
+ edge_heartbeat_schedule(edge_serial);
+
return 0;
}
@@ -2402,7 +2519,10 @@
static void edge_release(struct usb_serial *serial)
{
- kfree(usb_get_serial_data(serial));
+ struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+
+ cancel_delayed_work_sync(&edge_serial->heartbeat_work);
+ kfree(edge_serial);
}
static int edge_port_probe(struct usb_serial_port *port)
@@ -2506,6 +2626,25 @@
return 0;
}
+#ifdef CONFIG_PM
+static int edge_suspend(struct usb_serial *serial, pm_message_t message)
+{
+ struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+
+ cancel_delayed_work_sync(&edge_serial->heartbeat_work);
+
+ return 0;
+}
+
+static int edge_resume(struct usb_serial *serial)
+{
+ struct edgeport_serial *edge_serial = usb_get_serial_data(serial);
+
+ edge_heartbeat_schedule(edge_serial);
+
+ return 0;
+}
+#endif
static struct usb_serial_driver edgeport_1port_device = {
.driver = {
@@ -2538,6 +2677,10 @@
.read_int_callback = edge_interrupt_callback,
.read_bulk_callback = edge_bulk_in_callback,
.write_bulk_callback = edge_bulk_out_callback,
+#ifdef CONFIG_PM
+ .suspend = edge_suspend,
+ .resume = edge_resume,
+#endif
};
static struct usb_serial_driver edgeport_2port_device = {
@@ -2571,6 +2714,10 @@
.read_int_callback = edge_interrupt_callback,
.read_bulk_callback = edge_bulk_in_callback,
.write_bulk_callback = edge_bulk_out_callback,
+#ifdef CONFIG_PM
+ .suspend = edge_suspend,
+ .resume = edge_resume,
+#endif
};
static struct usb_serial_driver * const serial_drivers[] = {
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index 460a406..31a8b47 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -1137,13 +1137,9 @@
return err;
/* Set interface (RS-232) */
- err = mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_INTERFACE,
- MX_INT_RS232,
- port->port_number);
- if (err)
- return err;
-
- return 0;
+ return mxuport_send_ctrl_urb(serial, RQ_VENDOR_SET_INTERFACE,
+ MX_INT_RS232,
+ port->port_number);
}
static int mxuport_alloc_write_urb(struct usb_serial *serial,
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 19b85ee..6d1941a 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1099,6 +1099,8 @@
{ USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
{ USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x68c0, 0xff),
.driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC73xx */
+ { USB_DEVICE_INTERFACE_CLASS(SIERRA_VENDOR_ID, 0x9041, 0xff),
+ .driver_info = (kernel_ulong_t)&sierra_mc73xx_blacklist }, /* MC7305/MC7355 */
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
{ USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
@@ -1939,7 +1941,7 @@
} else if (status == -ENOENT || status == -ESHUTDOWN) {
dev_dbg(dev, "%s: urb stopped: %d\n", __func__, status);
} else
- dev_err(dev, "%s: error %d\n", __func__, status);
+ dev_dbg(dev, "%s: error %d\n", __func__, status);
/* Resubmit urb so we continue receiving IRQ data */
if (status != -ESHUTDOWN && status != -ENOENT) {
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index f5257af..ae682e4 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -362,21 +362,38 @@
static speed_t pl2303_encode_baud_rate_divisor(unsigned char buf[4],
speed_t baud)
{
- unsigned int tmp;
+ unsigned int baseline, mantissa, exponent;
/*
* Apparently the formula is:
- * baudrate = 12M * 32 / (2^buf[1]) / buf[0]
+ * baudrate = 12M * 32 / (mantissa * 4^exponent)
+ * where
+ * mantissa = buf[8:0]
+ * exponent = buf[11:9]
*/
- tmp = 12000000 * 32 / baud;
+ baseline = 12000000 * 32;
+ mantissa = baseline / baud;
+ if (mantissa == 0)
+ mantissa = 1; /* Avoid dividing by zero if baud > 32*12M. */
+ exponent = 0;
+ while (mantissa >= 512) {
+ if (exponent < 7) {
+ mantissa >>= 2; /* divide by 4 */
+ exponent++;
+ } else {
+ /* Exponent is maxed. Trim mantissa and leave. */
+ mantissa = 511;
+ break;
+ }
+ }
+
buf[3] = 0x80;
buf[2] = 0;
- buf[1] = (tmp >= 256);
- while (tmp >= 256) {
- tmp >>= 2;
- buf[1] <<= 1;
- }
- buf[0] = tmp;
+ buf[1] = exponent << 1 | mantissa >> 8;
+ buf[0] = mantissa & 0xff;
+
+ /* Calculate and return the exact baud rate. */
+ baud = (baseline / mantissa) >> (exponent << 1);
return baud;
}
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c
index 9c63897..ebcec8c 100644
--- a/drivers/usb/serial/qcserial.c
+++ b/drivers/usb/serial/qcserial.c
@@ -139,13 +139,13 @@
{USB_DEVICE(0x0AF0, 0x8120)}, /* Option GTM681W */
/* non-Gobi Sierra Wireless devices */
+ {DEVICE_SWI(0x03f0, 0x4e1d)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
{DEVICE_SWI(0x0f3d, 0x68a2)}, /* Sierra Wireless MC7700 */
{DEVICE_SWI(0x114f, 0x68a2)}, /* Sierra Wireless MC7750 */
{DEVICE_SWI(0x1199, 0x68a2)}, /* Sierra Wireless MC7710 */
{DEVICE_SWI(0x1199, 0x901c)}, /* Sierra Wireless EM7700 */
{DEVICE_SWI(0x1199, 0x901f)}, /* Sierra Wireless EM7355 */
{DEVICE_SWI(0x1199, 0x9040)}, /* Sierra Wireless Modem */
- {DEVICE_SWI(0x1199, 0x9041)}, /* Sierra Wireless MC7305/MC7355 */
{DEVICE_SWI(0x1199, 0x9051)}, /* Netgear AirCard 340U */
{DEVICE_SWI(0x1199, 0x9053)}, /* Sierra Wireless Modem */
{DEVICE_SWI(0x1199, 0x9054)}, /* Sierra Wireless Modem */
@@ -158,6 +158,7 @@
{DEVICE_SWI(0x413c, 0x81a4)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
{DEVICE_SWI(0x413c, 0x81a8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
{DEVICE_SWI(0x413c, 0x81a9)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
+ {DEVICE_SWI(0x413c, 0x81b1)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card */
/* Huawei devices */
{DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 46179a0..07d1ecd 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -289,6 +289,7 @@
{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF),
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
},
+ { USB_DEVICE(0x1199, 0x68AB) }, /* Sierra Wireless AR8550 */
/* AT&T Direct IP LTE modems */
{ USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF),
.driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index 8fceec7..37f3ad1 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -60,17 +60,15 @@
usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data);
+ /*
+ * Data from the device comes with a 1 byte header:
+ *
+ * <size of data> <data>...
+ */
if (urb->actual_length > 1) {
- data_length = urb->actual_length - 1;
-
- /*
- * Data from the device comes with a 1 byte header:
- *
- * <size of data>data...
- * This is real data to be sent to the tty layer
- * we pretty much just ignore the size and send everything
- * else to the tty layer.
- */
+ data_length = data[0];
+ if (data_length > (urb->actual_length - 1))
+ data_length = urb->actual_length - 1;
tty_insert_flip_string(&port->port, &data[1], data_length);
tty_flip_buffer_push(&port->port);
} else {
@@ -94,7 +92,7 @@
static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port)
{
- struct symbol_private *priv = usb_get_serial_data(port->serial);
+ struct symbol_private *priv = usb_get_serial_port_data(port);
unsigned long flags;
int result = 0;
@@ -120,7 +118,7 @@
static void symbol_throttle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct symbol_private *priv = usb_get_serial_data(port->serial);
+ struct symbol_private *priv = usb_get_serial_port_data(port);
spin_lock_irq(&priv->lock);
priv->throttled = true;
@@ -130,7 +128,7 @@
static void symbol_unthrottle(struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
- struct symbol_private *priv = usb_get_serial_data(port->serial);
+ struct symbol_private *priv = usb_get_serial_port_data(port);
int result;
bool was_throttled;
diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c
index 2f805cb..825305c 100644
--- a/drivers/usb/serial/usb_wwan.c
+++ b/drivers/usb/serial/usb_wwan.c
@@ -282,7 +282,7 @@
/* Resubmit urb so we continue receiving */
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err) {
- if (err != -EPERM) {
+ if (err != -EPERM && err != -ENODEV) {
dev_err(dev, "%s: resubmit read urb failed. (%d)\n",
__func__, err);
/* busy also in error unless we are killed */
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 540add2..5e67f63 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1111,7 +1111,7 @@
* command phase and the data phase. Some devices need a little
* more than that, probably because of clock rate inaccuracies. */
if (unlikely(us->fflags & US_FL_GO_SLOW))
- udelay(125);
+ usleep_range(125, 150);
if (transfer_length) {
unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index caf1888..6b24791 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -2065,6 +2065,18 @@
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_NO_READ_DISC_INFO ),
+/* Reported by Oliver Neukum <oneukum@suse.com>
+ * This device morphes spontaneously into another device if the access
+ * pattern of Windows isn't followed. Thus writable media would be dirty
+ * if the initial instance is used. So the device is limited to its
+ * virtual CD.
+ * And yes, the concept that BCD goes up to 9 is not heeded */
+UNUSUAL_DEV( 0x19d2, 0x1225, 0x0000, 0xffff,
+ "ZTE,Incorporated",
+ "ZTE WCDMA Technologies MSM",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_SINGLE_LUN ),
+
/* Reported by Sven Geggus <sven-usbst@geggus.net>
* This encrypted pen drive returns bogus data for the initial READ(10).
*/
@@ -2074,6 +2086,17 @@
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_INITIAL_READ10 ),
+/* Reported by Hans de Goede <hdegoede@redhat.com>
+ * These are mini projectors using USB for both power and video data transport
+ * The usb-storage interface is a virtual windows driver CD, which the gm12u320
+ * driver automatically converts into framebuffer & kms dri device nodes.
+ */
+UNUSUAL_DEV( 0x1de1, 0xc102, 0x0000, 0xffff,
+ "Grain-media Technology Corp.",
+ "USB3.0 Device GM12U320",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_IGNORE_DEVICE ),
+
/* Patch by Richard Schütz <r.schtz@t-online.de>
* This external hard drive enclosure uses a JMicron chip which
* needs the US_FL_IGNORE_RESIDUE flag to work properly. */
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 2fb29df..563c510 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -689,6 +689,23 @@
}
EXPORT_SYMBOL_GPL(vfio_device_get_from_dev);
+static struct vfio_device *vfio_device_get_from_name(struct vfio_group *group,
+ char *buf)
+{
+ struct vfio_device *device;
+
+ mutex_lock(&group->device_lock);
+ list_for_each_entry(device, &group->device_list, group_next) {
+ if (!strcmp(dev_name(device->dev), buf)) {
+ vfio_device_get(device);
+ break;
+ }
+ }
+ mutex_unlock(&group->device_lock);
+
+ return device;
+}
+
/*
* Caller must hold a reference to the vfio_device
*/
@@ -1198,53 +1215,53 @@
{
struct vfio_device *device;
struct file *filep;
- int ret = -ENODEV;
+ int ret;
if (0 == atomic_read(&group->container_users) ||
!group->container->iommu_driver || !vfio_group_viable(group))
return -EINVAL;
- mutex_lock(&group->device_lock);
- list_for_each_entry(device, &group->device_list, group_next) {
- if (strcmp(dev_name(device->dev), buf))
- continue;
+ device = vfio_device_get_from_name(group, buf);
+ if (!device)
+ return -ENODEV;
- ret = device->ops->open(device->device_data);
- if (ret)
- break;
- /*
- * We can't use anon_inode_getfd() because we need to modify
- * the f_mode flags directly to allow more than just ioctls
- */
- ret = get_unused_fd_flags(O_CLOEXEC);
- if (ret < 0) {
- device->ops->release(device->device_data);
- break;
- }
-
- filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops,
- device, O_RDWR);
- if (IS_ERR(filep)) {
- put_unused_fd(ret);
- ret = PTR_ERR(filep);
- device->ops->release(device->device_data);
- break;
- }
-
- /*
- * TODO: add an anon_inode interface to do this.
- * Appears to be missing by lack of need rather than
- * explicitly prevented. Now there's need.
- */
- filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
-
- vfio_device_get(device);
- atomic_inc(&group->container_users);
-
- fd_install(ret, filep);
- break;
+ ret = device->ops->open(device->device_data);
+ if (ret) {
+ vfio_device_put(device);
+ return ret;
}
- mutex_unlock(&group->device_lock);
+
+ /*
+ * We can't use anon_inode_getfd() because we need to modify
+ * the f_mode flags directly to allow more than just ioctls
+ */
+ ret = get_unused_fd_flags(O_CLOEXEC);
+ if (ret < 0) {
+ device->ops->release(device->device_data);
+ vfio_device_put(device);
+ return ret;
+ }
+
+ filep = anon_inode_getfile("[vfio-device]", &vfio_device_fops,
+ device, O_RDWR);
+ if (IS_ERR(filep)) {
+ put_unused_fd(ret);
+ ret = PTR_ERR(filep);
+ device->ops->release(device->device_data);
+ vfio_device_put(device);
+ return ret;
+ }
+
+ /*
+ * TODO: add an anon_inode interface to do this.
+ * Appears to be missing by lack of need rather than
+ * explicitly prevented. Now there's need.
+ */
+ filep->f_mode |= (FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
+
+ atomic_inc(&group->container_users);
+
+ fd_install(ret, filep);
return ret;
}
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index dfcc02c..f114a9d 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1573,9 +1573,9 @@
return misc_register(&vhost_scsi_misc);
}
-static int vhost_scsi_deregister(void)
+static void vhost_scsi_deregister(void)
{
- return misc_deregister(&vhost_scsi_misc);
+ misc_deregister(&vhost_scsi_misc);
}
static char *vhost_scsi_dump_proto_id(struct vhost_scsi_tport *tport)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 9e8e004..eec2f11 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -22,14 +22,20 @@
#include <linux/file.h>
#include <linux/highmem.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <linux/kthread.h>
#include <linux/cgroup.h>
#include <linux/module.h>
+#include <linux/sort.h>
#include "vhost.h"
+static ushort max_mem_regions = 64;
+module_param(max_mem_regions, ushort, 0444);
+MODULE_PARM_DESC(max_mem_regions,
+ "Maximum number of memory regions in memory map. (default: 64)");
+
enum {
- VHOST_MEMORY_MAX_NREGIONS = 64,
VHOST_MEMORY_F_LOG = 0x1,
};
@@ -543,7 +549,7 @@
fput(dev->log_file);
dev->log_file = NULL;
/* No one will access memory at this point */
- kfree(dev->memory);
+ kvfree(dev->memory);
dev->memory = NULL;
WARN_ON(!list_empty(&dev->work_list));
if (dev->worker) {
@@ -663,6 +669,25 @@
}
EXPORT_SYMBOL_GPL(vhost_vq_access_ok);
+static int vhost_memory_reg_sort_cmp(const void *p1, const void *p2)
+{
+ const struct vhost_memory_region *r1 = p1, *r2 = p2;
+ if (r1->guest_phys_addr < r2->guest_phys_addr)
+ return 1;
+ if (r1->guest_phys_addr > r2->guest_phys_addr)
+ return -1;
+ return 0;
+}
+
+static void *vhost_kvzalloc(unsigned long size)
+{
+ void *n = kzalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
+
+ if (!n)
+ n = vzalloc(size);
+ return n;
+}
+
static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
{
struct vhost_memory mem, *newmem, *oldmem;
@@ -673,21 +698,23 @@
return -EFAULT;
if (mem.padding)
return -EOPNOTSUPP;
- if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS)
+ if (mem.nregions > max_mem_regions)
return -E2BIG;
- newmem = kmalloc(size + mem.nregions * sizeof *m->regions, GFP_KERNEL);
+ newmem = vhost_kvzalloc(size + mem.nregions * sizeof(*m->regions));
if (!newmem)
return -ENOMEM;
memcpy(newmem, &mem, size);
if (copy_from_user(newmem->regions, m->regions,
mem.nregions * sizeof *m->regions)) {
- kfree(newmem);
+ kvfree(newmem);
return -EFAULT;
}
+ sort(newmem->regions, newmem->nregions, sizeof(*newmem->regions),
+ vhost_memory_reg_sort_cmp, NULL);
if (!memory_access_ok(d, newmem, 0)) {
- kfree(newmem);
+ kvfree(newmem);
return -EFAULT;
}
oldmem = d->memory;
@@ -699,7 +726,7 @@
d->vqs[i]->memory = newmem;
mutex_unlock(&d->vqs[i]->mutex);
}
- kfree(oldmem);
+ kvfree(oldmem);
return 0;
}
@@ -965,6 +992,7 @@
}
if (eventfp != d->log_file) {
filep = d->log_file;
+ d->log_file = eventfp;
ctx = d->log_ctx;
d->log_ctx = eventfp ?
eventfd_ctx_fileget(eventfp) : NULL;
@@ -992,17 +1020,22 @@
static const struct vhost_memory_region *find_region(struct vhost_memory *mem,
__u64 addr, __u32 len)
{
- struct vhost_memory_region *reg;
- int i;
+ const struct vhost_memory_region *reg;
+ int start = 0, end = mem->nregions;
- /* linear search is not brilliant, but we really have on the order of 6
- * regions in practice */
- for (i = 0; i < mem->nregions; ++i) {
- reg = mem->regions + i;
- if (reg->guest_phys_addr <= addr &&
- reg->guest_phys_addr + reg->memory_size - 1 >= addr)
- return reg;
+ while (start < end) {
+ int slot = start + (end - start) / 2;
+ reg = mem->regions + slot;
+ if (addr >= reg->guest_phys_addr)
+ end = slot;
+ else
+ start = slot + 1;
}
+
+ reg = mem->regions + start;
+ if (addr >= reg->guest_phys_addr &&
+ reg->guest_phys_addr + reg->memory_size > addr)
+ return reg;
return NULL;
}
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 658c34b..1aaf893 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -1306,10 +1306,11 @@
int y;
int c = scr_readw((u16 *) vc->vc_pos);
+ ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
+
if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
return;
- ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
if (vc->vc_cursor_type & 0x10)
fbcon_del_cursor_timer(info);
else
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index 2d98de5..811acfc 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -298,7 +298,7 @@
# Helper logic selected only by the ARM Versatile platform family.
config PLAT_VERSATILE_CLCD
- def_bool ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS
+ def_bool ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_INTEGRATOR
depends on ARM
depends on FB_ARMCLCD && FB=y
@@ -2475,3 +2475,17 @@
help
This driver implements support for the Solomon SSD1307
OLED controller over I2C.
+
+config FB_SM712
+ tristate "Silicon Motion SM712 framebuffer support"
+ depends on FB && PCI
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
+ help
+ Frame buffer driver for the Silicon Motion SM710, SM712, SM721
+ and SM722 chips.
+
+ This driver is also available as a module. The module will be
+ called sm712fb. If you want to compile it as a module, say M
+ here and read <file:Documentation/kbuild/modules.txt>.
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
index cecea50..50ed1b4 100644
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -131,6 +131,7 @@
obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o
obj-$(CONFIG_FB_OPENCORES) += ocfb.o
+obj-$(CONFIG_FB_SM712) += sm712fb.o
# Platform or fallback drivers go here
obj-$(CONFIG_FB_UVESA) += uvesafb.o
diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c
index 807ee22..e2451bd 100644
--- a/drivers/video/fbdev/hyperv_fb.c
+++ b/drivers/video/fbdev/hyperv_fb.c
@@ -213,7 +213,7 @@
struct hvfb_par {
struct fb_info *info;
- struct resource mem;
+ struct resource *mem;
bool fb_ready; /* fb device is ready */
struct completion wait;
u32 synthvid_version;
@@ -677,26 +677,18 @@
/* Get framebuffer memory from Hyper-V video pci space */
-static int hvfb_getmem(struct fb_info *info)
+static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
{
struct hvfb_par *par = info->par;
struct pci_dev *pdev = NULL;
void __iomem *fb_virt;
int gen2vm = efi_enabled(EFI_BOOT);
+ resource_size_t pot_start, pot_end;
int ret;
- par->mem.name = KBUILD_MODNAME;
- par->mem.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
if (gen2vm) {
- ret = allocate_resource(&hyperv_mmio, &par->mem,
- screen_fb_size,
- 0, -1,
- screen_fb_size,
- NULL, NULL);
- if (ret != 0) {
- pr_err("Unable to allocate framebuffer memory\n");
- return -ENODEV;
- }
+ pot_start = 0;
+ pot_end = -1;
} else {
pdev = pci_get_device(PCI_VENDOR_ID_MICROSOFT,
PCI_DEVICE_ID_HYPERV_VIDEO, NULL);
@@ -709,16 +701,18 @@
pci_resource_len(pdev, 0) < screen_fb_size)
goto err1;
- par->mem.end = pci_resource_end(pdev, 0);
- par->mem.start = par->mem.end - screen_fb_size + 1;
- ret = request_resource(&pdev->resource[0], &par->mem);
- if (ret != 0) {
- pr_err("Unable to request framebuffer memory\n");
- goto err1;
- }
+ pot_end = pci_resource_end(pdev, 0);
+ pot_start = pot_end - screen_fb_size + 1;
}
- fb_virt = ioremap(par->mem.start, screen_fb_size);
+ ret = vmbus_allocate_mmio(&par->mem, hdev, pot_start, pot_end,
+ screen_fb_size, 0x100000, true);
+ if (ret != 0) {
+ pr_err("Unable to allocate framebuffer memory\n");
+ goto err1;
+ }
+
+ fb_virt = ioremap(par->mem->start, screen_fb_size);
if (!fb_virt)
goto err2;
@@ -736,7 +730,7 @@
info->apertures->ranges[0].size = pci_resource_len(pdev, 0);
}
- info->fix.smem_start = par->mem.start;
+ info->fix.smem_start = par->mem->start;
info->fix.smem_len = screen_fb_size;
info->screen_base = fb_virt;
info->screen_size = screen_fb_size;
@@ -749,7 +743,8 @@
err3:
iounmap(fb_virt);
err2:
- release_resource(&par->mem);
+ release_mem_region(par->mem->start, screen_fb_size);
+ par->mem = NULL;
err1:
if (!gen2vm)
pci_dev_put(pdev);
@@ -763,7 +758,8 @@
struct hvfb_par *par = info->par;
iounmap(info->screen_base);
- release_resource(&par->mem);
+ release_mem_region(par->mem->start, screen_fb_size);
+ par->mem = NULL;
}
@@ -794,7 +790,7 @@
goto error1;
}
- ret = hvfb_getmem(info);
+ ret = hvfb_getmem(hdev, info);
if (ret) {
pr_err("No memory for framebuffer\n");
goto error2;
diff --git a/drivers/video/fbdev/omap2/dss/dss-of.c b/drivers/video/fbdev/omap2/dss/dss-of.c
index 928ee63..bf407b6 100644
--- a/drivers/video/fbdev/omap2/dss/dss-of.c
+++ b/drivers/video/fbdev/omap2/dss/dss-of.c
@@ -60,6 +60,8 @@
}
prev = port;
} while (of_node_cmp(port->name, "port") != 0);
+
+ of_node_put(ports);
}
return port;
@@ -94,7 +96,7 @@
if (!port)
return NULL;
- np = of_get_next_parent(port);
+ np = of_get_parent(port);
for (i = 0; i < 2 && np; ++i) {
struct property *prop;
diff --git a/drivers/video/fbdev/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c
index 86bd457..50bce45 100644
--- a/drivers/video/fbdev/pxa3xx-gcu.c
+++ b/drivers/video/fbdev/pxa3xx-gcu.c
@@ -653,7 +653,7 @@
goto err_free_dma;
}
- ret = clk_enable(priv->clk);
+ ret = clk_prepare_enable(priv->clk);
if (ret < 0) {
dev_err(dev, "failed to enable clock\n");
goto err_misc_deregister;
@@ -685,7 +685,7 @@
misc_deregister(&priv->misc_dev);
err_disable_clk:
- clk_disable(priv->clk);
+ clk_disable_unprepare(priv->clk);
return ret;
}
diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/video/fbdev/sm712.h
similarity index 81%
rename from drivers/staging/sm7xxfb/sm7xx.h
rename to drivers/video/fbdev/sm712.h
index 4bed094..aad1cc4 100644
--- a/drivers/staging/sm7xxfb/sm7xx.h
+++ b/drivers/video/fbdev/sm712.h
@@ -13,8 +13,6 @@
* more details.
*/
-#define NR_PALETTE 256
-
#define FB_ACCEL_SMI_LYNX 88
#define SCREEN_X_RES 1024
@@ -31,12 +29,8 @@
extern void __iomem *smtc_regbaseaddress;
#define smtc_mmiowb(dat, reg) writeb(dat, smtc_regbaseaddress + reg)
-#define smtc_mmioww(dat, reg) writew(dat, smtc_regbaseaddress + reg)
-#define smtc_mmiowl(dat, reg) writel(dat, smtc_regbaseaddress + reg)
#define smtc_mmiorb(reg) readb(smtc_regbaseaddress + reg)
-#define smtc_mmiorw(reg) readw(smtc_regbaseaddress + reg)
-#define smtc_mmiorl(reg) readl(smtc_regbaseaddress + reg)
#define SIZE_SR00_SR04 (0x04 - 0x00 + 1)
#define SIZE_SR10_SR24 (0x24 - 0x10 + 1)
@@ -48,8 +42,6 @@
#define SIZE_CR00_CR18 (0x18 - 0x00 + 1)
#define SIZE_CR30_CR4D (0x4D - 0x30 + 1)
#define SIZE_CR90_CRA7 (0xA7 - 0x90 + 1)
-#define SIZE_VPR (0x6C + 1)
-#define SIZE_DPR (0x44 + 1)
static inline void smtc_crtcw(int reg, int val)
{
@@ -57,24 +49,12 @@
smtc_mmiowb(val, 0x3d5);
}
-static inline unsigned int smtc_crtcr(int reg)
-{
- smtc_mmiowb(reg, 0x3d4);
- return smtc_mmiorb(0x3d5);
-}
-
static inline void smtc_grphw(int reg, int val)
{
smtc_mmiowb(reg, 0x3ce);
smtc_mmiowb(val, 0x3cf);
}
-static inline unsigned int smtc_grphr(int reg)
-{
- smtc_mmiowb(reg, 0x3ce);
- return smtc_mmiorb(0x3cf);
-}
-
static inline void smtc_attrw(int reg, int val)
{
smtc_mmiorb(0x3da);
@@ -115,3 +95,22 @@
unsigned char init_cr30_cr4d[SIZE_CR30_CR4D];
unsigned char init_cr90_cra7[SIZE_CR90_CRA7];
};
+
+#ifdef __BIG_ENDIAN
+#define pal_rgb(r, g, b, val) (((r & 0xf800) >> 8) | \
+ ((g & 0xe000) >> 13) | \
+ ((g & 0x1c00) << 3) | \
+ ((b & 0xf800) >> 3))
+#define big_addr 0x800000
+#define mmio_addr 0x00800000
+#define seqw17() smtc_seqw(0x17, 0x30)
+#define big_pixel_depth(p, d) {if (p == 24) {p = 32; d = 32; } }
+#define big_swap(p) ((p & 0xff00ff00 >> 8) | (p & 0x00ff00ff << 8))
+#else
+#define pal_rgb(r, g, b, val) val
+#define big_addr 0
+#define mmio_addr 0x00c00000
+#define seqw17() do { } while (0)
+#define big_pixel_depth(p, d) do { } while (0)
+#define big_swap(p) p
+#endif
diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/video/fbdev/sm712fb.c
similarity index 96%
rename from drivers/staging/sm7xxfb/sm7xxfb.c
rename to drivers/video/fbdev/sm712fb.c
index 2ff4fe7..629bfa2 100644
--- a/drivers/staging/sm7xxfb/sm7xxfb.c
+++ b/drivers/video/fbdev/sm712fb.c
@@ -32,7 +32,7 @@
#include <linux/pm.h>
#endif
-#include "sm7xx.h"
+#include "sm712.h"
/*
* Private structure
@@ -923,25 +923,14 @@
val = chan_to_field(red, &sfb->fb->var.red);
val |= chan_to_field(green, &sfb->fb->var.green);
val |= chan_to_field(blue, &sfb->fb->var.blue);
-#ifdef __BIG_ENDIAN
- pal[regno] = ((red & 0xf800) >> 8) |
- ((green & 0xe000) >> 13) |
- ((green & 0x1c00) << 3) |
- ((blue & 0xf800) >> 3);
-#else
- pal[regno] = val;
-#endif
+ pal[regno] = pal_rgb(red, green, blue, val);
} else {
u32 *pal = sfb->fb->pseudo_palette;
val = chan_to_field(red, &sfb->fb->var.red);
val |= chan_to_field(green, &sfb->fb->var.green);
val |= chan_to_field(blue, &sfb->fb->var.blue);
-#ifdef __BIG_ENDIAN
- val = (val & 0xff00ff00 >> 8) |
- (val & 0x00ff00ff << 8);
-#endif
- pal[regno] = val;
+ pal[regno] = big_swap(val);
}
break;
@@ -957,7 +946,6 @@
return 0;
}
-#ifdef __BIG_ENDIAN
static ssize_t smtcfb_read(struct fb_info *info, char __user *buf,
size_t count, loff_t *ppos)
{
@@ -1002,8 +990,7 @@
dst = buffer;
for (i = c >> 2; i--;) {
*dst = fb_readl(src++);
- *dst = (*dst & 0xff00ff00 >> 8) |
- (*dst & 0x00ff00ff << 8);
+ *dst = big_swap(*dst);
dst++;
}
if (c & 3) {
@@ -1091,8 +1078,7 @@
}
for (i = c >> 2; i--;) {
- fb_writel((*src & 0xff00ff00 >> 8) |
- (*src & 0x00ff00ff << 8), dst++);
+ fb_writel(big_swap(*src), dst++);
src++;
}
if (c & 3) {
@@ -1120,7 +1106,6 @@
return (cnt) ? cnt : err;
}
-#endif /* ! __BIG_ENDIAN */
static void sm7xx_set_timing(struct smtcfb_info *sfb)
{
@@ -1316,10 +1301,8 @@
.fb_fillrect = cfb_fillrect,
.fb_imageblit = cfb_imageblit,
.fb_copyarea = cfb_copyarea,
-#ifdef __BIG_ENDIAN
.fb_read = smtcfb_read,
.fb_write = smtcfb_write,
-#endif
};
/*
@@ -1341,10 +1324,8 @@
{
sfb->fb->fix.smem_start = pci_resource_start(pdev, 0);
-#ifdef __BIG_ENDIAN
if (sfb->fb->var.bits_per_pixel == 32)
- sfb->fb->fix.smem_start += 0x800000;
-#endif
+ sfb->fb->fix.smem_start += big_addr;
sfb->fb->fix.smem_len = smem_len;
@@ -1437,10 +1418,7 @@
sfb->fb->var.bits_per_pixel = SCREEN_BPP;
}
-#ifdef __BIG_ENDIAN
- if (sfb->fb->var.bits_per_pixel == 24)
- sfb->fb->var.bits_per_pixel = (smtc_scr_info.lfb_depth = 32);
-#endif
+ big_pixel_depth(sfb->fb->var.bits_per_pixel, smtc_scr_info.lfb_depth);
/* Map address and memory detection */
mmio_base = pci_resource_start(pdev, 0);
pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id);
@@ -1451,22 +1429,8 @@
sfb->fb->fix.mmio_start = mmio_base + 0x00400000;
sfb->fb->fix.mmio_len = 0x00400000;
smem_size = SM712_VIDEOMEMORYSIZE;
-#ifdef __BIG_ENDIAN
- sfb->lfb = ioremap(mmio_base, 0x00c00000);
-#else
- sfb->lfb = ioremap(mmio_base, 0x00800000);
-#endif
- sfb->mmio = (smtc_regbaseaddress =
- sfb->lfb + 0x00700000);
- sfb->dp_regs = sfb->lfb + 0x00408000;
- sfb->vp_regs = sfb->lfb + 0x0040c000;
-#ifdef __BIG_ENDIAN
- if (sfb->fb->var.bits_per_pixel == 32) {
- sfb->lfb += 0x800000;
- dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
- }
-#endif
- if (!smtc_regbaseaddress) {
+ sfb->lfb = ioremap(mmio_base, mmio_addr);
+ if (!sfb->lfb) {
dev_err(&pdev->dev,
"%s: unable to map memory mapped IO!\n",
sfb->fb->fix.id);
@@ -1474,6 +1438,15 @@
goto failed_fb;
}
+ sfb->mmio = (smtc_regbaseaddress =
+ sfb->lfb + 0x00700000);
+ sfb->dp_regs = sfb->lfb + 0x00408000;
+ sfb->vp_regs = sfb->lfb + 0x0040c000;
+ if (sfb->fb->var.bits_per_pixel == 32) {
+ sfb->lfb += big_addr;
+ dev_info(&pdev->dev, "sfb->lfb=%p\n", sfb->lfb);
+ }
+
/* set MCLK = 14.31818 * (0x16 / 0x2) */
smtc_seqw(0x6a, 0x16);
smtc_seqw(0x6b, 0x02);
@@ -1481,10 +1454,8 @@
/* enable PCI burst */
smtc_seqw(0x17, 0x20);
/* enable word swap */
-#ifdef __BIG_ENDIAN
if (sfb->fb->var.bits_per_pixel == 32)
- smtc_seqw(0x17, 0x30);
-#endif
+ seqw17();
break;
case 0x720:
sfb->fb->fix.mmio_start = mmio_base;
@@ -1616,10 +1587,8 @@
smtc_seqw(0x62, 0x3e);
/* enable PCI burst */
smtc_seqw(0x17, 0x20);
-#ifdef __BIG_ENDIAN
if (sfb->fb->var.bits_per_pixel == 32)
- smtc_seqw(0x17, 0x30);
-#endif
+ seqw17();
break;
case 0x720:
smtc_seqw(0x62, 0xff);
@@ -1659,14 +1628,12 @@
static int __init sm712fb_init(void)
{
-#ifndef MODULE
char *option = NULL;
if (fb_get_options("sm712fb", &option))
return -ENODEV;
if (option && *option)
mode_option = option;
-#endif
sm7xx_vga_setup(mode_option);
return pci_register_driver(&smtcfb_driver);
diff --git a/drivers/video/of_videomode.c b/drivers/video/of_videomode.c
index 111c2d1..b5102aa 100644
--- a/drivers/video/of_videomode.c
+++ b/drivers/video/of_videomode.c
@@ -44,11 +44,9 @@
index = disp->native_mode;
ret = videomode_from_timings(disp, vm, index);
- if (ret)
- return ret;
display_timings_release(disp);
- return 0;
+ return ret;
}
EXPORT_SYMBOL_GPL(of_get_videomode);
diff --git a/drivers/virtio/virtio_input.c b/drivers/virtio/virtio_input.c
index 60e2a16..c96944b 100644
--- a/drivers/virtio/virtio_input.c
+++ b/drivers/virtio/virtio_input.c
@@ -313,6 +313,7 @@
static void virtinput_remove(struct virtio_device *vdev)
{
struct virtio_input *vi = vdev->priv;
+ void *buf;
unsigned long flags;
spin_lock_irqsave(&vi->lock, flags);
@@ -320,6 +321,9 @@
spin_unlock_irqrestore(&vi->lock, flags);
input_unregister_device(vi->idev);
+ vdev->config->reset(vdev);
+ while ((buf = virtqueue_detach_unused_buf(vi->sts)) != NULL)
+ kfree(buf);
vdev->config->del_vqs(vdev);
kfree(vi);
}
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
index a674409..b05e8fe 100644
--- a/drivers/w1/masters/ds2482.c
+++ b/drivers/w1/masters/ds2482.c
@@ -97,7 +97,6 @@
static struct i2c_driver ds2482_driver = {
.driver = {
- .owner = THIS_MODULE,
.name = "ds2482",
},
.probe = ds2482_probe,
diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
index d8667b0..684bc9d 100644
--- a/drivers/w1/masters/matrox_w1.c
+++ b/drivers/w1/masters/matrox_w1.c
@@ -232,16 +232,4 @@
}
kfree(dev);
}
-
-static int __init matrox_w1_init(void)
-{
- return pci_register_driver(&matrox_w1_pci_driver);
-}
-
-static void __exit matrox_w1_fini(void)
-{
- pci_unregister_driver(&matrox_w1_pci_driver);
-}
-
-module_init(matrox_w1_init);
-module_exit(matrox_w1_fini);
+module_pci_driver(matrox_w1_pci_driver);
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index 41cecb5..9ba1153 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -269,9 +269,8 @@
if (res)
dev_warn(dev, "failed to unregister restart handler\n");
- res = misc_deregister(&at91wdt_miscdev);
- if (!res)
- at91wdt_miscdev.parent = NULL;
+ misc_deregister(&at91wdt_miscdev);
+ at91wdt_miscdev.parent = NULL;
return res;
}
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c
index b7ea39b..1e41818 100644
--- a/drivers/watchdog/ks8695_wdt.c
+++ b/drivers/watchdog/ks8695_wdt.c
@@ -254,13 +254,10 @@
static int ks8695wdt_remove(struct platform_device *pdev)
{
- int res;
+ misc_deregister(&ks8695wdt_miscdev);
+ ks8695wdt_miscdev.parent = NULL;
- res = misc_deregister(&ks8695wdt_miscdev);
- if (!res)
- ks8695wdt_miscdev.parent = NULL;
-
- return res;
+ return 0;
}
static void ks8695wdt_shutdown(struct platform_device *pdev)
diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c
index 119beb7..4b54193 100644
--- a/drivers/watchdog/ts72xx_wdt.c
+++ b/drivers/watchdog/ts72xx_wdt.c
@@ -428,7 +428,8 @@
static int ts72xx_wdt_remove(struct platform_device *pdev)
{
- return misc_deregister(&ts72xx_wdt_miscdev);
+ misc_deregister(&ts72xx_wdt_miscdev);
+ return 0;
}
static struct platform_driver ts72xx_wdt_driver = {
diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c
index fd93369..bf4a23c 100644
--- a/drivers/xen/balloon.c
+++ b/drivers/xen/balloon.c
@@ -472,7 +472,7 @@
}
/*
- * We avoid multiple worker processes conflicting via the balloon mutex.
+ * As this is a work item it is guaranteed to run as a single instance only.
* We may of course race updates of the target counts (which are protected
* by the balloon lock), or with changes to the Xen hard limit, but we will
* recover from these in time.
@@ -482,9 +482,10 @@
enum bp_state state = BP_DONE;
long credit;
- mutex_lock(&balloon_mutex);
do {
+ mutex_lock(&balloon_mutex);
+
credit = current_credit();
if (credit > 0) {
@@ -499,17 +500,15 @@
state = update_schedule(state);
-#ifndef CONFIG_PREEMPT
- if (need_resched())
- schedule();
-#endif
+ mutex_unlock(&balloon_mutex);
+
+ cond_resched();
+
} while (credit && state == BP_DONE);
/* Schedule more work if there is some still to be done. */
if (state == BP_EAGAIN)
schedule_delayed_work(&balloon_worker, balloon_stats.schedule_delay * HZ);
-
- mutex_unlock(&balloon_mutex);
}
/* Resets the Xen limit, sets new target, and kicks off processing. */
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 67b9163..0dbb222 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -568,12 +568,14 @@
pr_debug("priv %p\n", priv);
+ mutex_lock(&priv->lock);
while (!list_empty(&priv->maps)) {
map = list_entry(priv->maps.next, struct grant_map, next);
list_del(&map->next);
gntdev_put_map(NULL /* already removed */, map);
}
WARN_ON(!list_empty(&priv->freeable_maps));
+ mutex_unlock(&priv->lock);
if (use_ptemod)
mmu_notifier_unregister(&priv->mn, priv->mm);
diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
index 9ad3272..e303535 100644
--- a/drivers/xen/xenbus/xenbus_client.c
+++ b/drivers/xen/xenbus/xenbus_client.c
@@ -814,8 +814,10 @@
rv = xenbus_unmap_ring(dev, node->handles, node->nr_handles,
addrs);
- if (!rv)
+ if (!rv) {
vunmap(vaddr);
+ free_xenballooned_pages(node->nr_handles, node->hvm.pages);
+ }
else
WARN(1, "Leaking %p, size %u page(s)\n", vaddr,
node->nr_handles);
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 862fbc2..564a7de 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -378,7 +378,7 @@
ret = btrfs_kobj_add_device(tgt_device->fs_devices, tgt_device);
if (ret)
- btrfs_error(root->fs_info, ret, "kobj add dev failed");
+ btrfs_err(root->fs_info, "kobj add dev failed %d\n", ret);
printk_in_rcu(KERN_INFO
"BTRFS: dev_replace from %s (devid %llu) to %s started\n",
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index a9aadb2..f556c37 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -2842,6 +2842,7 @@
!extent_buffer_uptodate(chunk_root->node)) {
printk(KERN_ERR "BTRFS: failed to read chunk root on %s\n",
sb->s_id);
+ chunk_root->node = NULL;
goto fail_tree_roots;
}
btrfs_set_root_node(&chunk_root->root_item, chunk_root->node);
@@ -2879,7 +2880,7 @@
!extent_buffer_uptodate(tree_root->node)) {
printk(KERN_WARNING "BTRFS: failed to read tree root on %s\n",
sb->s_id);
-
+ tree_root->node = NULL;
goto recovery_tree_root;
}
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 171312d..07204bf 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -4227,6 +4227,24 @@
space_info->chunk_alloc = 0;
spin_unlock(&space_info->lock);
mutex_unlock(&fs_info->chunk_mutex);
+ /*
+ * When we allocate a new chunk we reserve space in the chunk block
+ * reserve to make sure we can COW nodes/leafs in the chunk tree or
+ * add new nodes/leafs to it if we end up needing to do it when
+ * inserting the chunk item and updating device items as part of the
+ * second phase of chunk allocation, performed by
+ * btrfs_finish_chunk_alloc(). So make sure we don't accumulate a
+ * large number of new block groups to create in our transaction
+ * handle's new_bgs list to avoid exhausting the chunk block reserve
+ * in extreme cases - like having a single transaction create many new
+ * block groups when starting to write out the free space caches of all
+ * the block groups that were made dirty during the lifetime of the
+ * transaction.
+ */
+ if (trans->chunk_bytes_reserved >= (2 * 1024 * 1024ull)) {
+ btrfs_create_pending_block_groups(trans, trans->root);
+ btrfs_trans_release_chunk_metadata(trans);
+ }
return ret;
}
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index e9ace09..8a82029 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1651,6 +1651,11 @@
/* Exclusive -> exclusive, nothing changed */
}
}
+
+ /* For exclusive extent, free its reserved bytes too */
+ if (nr_old_roots == 0 && nr_new_roots == 1 &&
+ cur_new_count == nr_new_roots)
+ qg->reserved -= num_bytes;
if (dirty)
qgroup_dirty(fs_info, qg);
}
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index cd7ef34..6bad633 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2163,8 +2163,7 @@
static void btrfs_interface_exit(void)
{
- if (misc_deregister(&btrfs_misc) < 0)
- printk(KERN_INFO "BTRFS: misc_deregister failed for control device\n");
+ misc_deregister(&btrfs_misc);
}
static void btrfs_print_info(void)
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 51e0f0d..f5021fc 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -2152,7 +2152,8 @@
kmem_cache_free(btrfs_trans_handle_cachep, trans);
- if (current != root->fs_info->transaction_kthread)
+ if (current != root->fs_info->transaction_kthread &&
+ current != root->fs_info->cleaner_kthread)
btrfs_run_delayed_iputs(root);
return ret;
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index dc10c9d..ddd5e94 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1506,7 +1506,6 @@
swap(cf, ci->i_prealloc_cap_flush);
cf->caps = flushing;
- cf->kick = false;
spin_lock(&mdsc->cap_dirty_lock);
list_del_init(&ci->i_dirty_item);
@@ -2123,8 +2122,7 @@
static int __kick_flushing_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
- struct ceph_inode_info *ci,
- bool kick_all)
+ struct ceph_inode_info *ci)
{
struct inode *inode = &ci->vfs_inode;
struct ceph_cap *cap;
@@ -2150,9 +2148,7 @@
for (n = rb_first(&ci->i_cap_flush_tree); n; n = rb_next(n)) {
cf = rb_entry(n, struct ceph_cap_flush, i_node);
- if (cf->tid < first_tid)
- continue;
- if (kick_all || cf->kick)
+ if (cf->tid >= first_tid)
break;
}
if (!n) {
@@ -2161,7 +2157,6 @@
}
cf = rb_entry(n, struct ceph_cap_flush, i_node);
- cf->kick = false;
first_tid = cf->tid + 1;
@@ -2181,8 +2176,6 @@
{
struct ceph_inode_info *ci;
struct ceph_cap *cap;
- struct ceph_cap_flush *cf;
- struct rb_node *n;
dout("early_kick_flushing_caps mds%d\n", session->s_mds);
list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
@@ -2205,16 +2198,11 @@
if ((cap->issued & ci->i_flushing_caps) !=
ci->i_flushing_caps) {
spin_unlock(&ci->i_ceph_lock);
- if (!__kick_flushing_caps(mdsc, session, ci, true))
+ if (!__kick_flushing_caps(mdsc, session, ci))
continue;
spin_lock(&ci->i_ceph_lock);
}
- for (n = rb_first(&ci->i_cap_flush_tree); n; n = rb_next(n)) {
- cf = rb_entry(n, struct ceph_cap_flush, i_node);
- cf->kick = true;
- }
-
spin_unlock(&ci->i_ceph_lock);
}
}
@@ -2228,7 +2216,7 @@
dout("kick_flushing_caps mds%d\n", session->s_mds);
list_for_each_entry(ci, &session->s_cap_flushing, i_flushing_item) {
- int delayed = __kick_flushing_caps(mdsc, session, ci, false);
+ int delayed = __kick_flushing_caps(mdsc, session, ci);
if (delayed) {
spin_lock(&ci->i_ceph_lock);
__cap_delay_requeue(mdsc, ci);
@@ -2261,7 +2249,7 @@
spin_unlock(&ci->i_ceph_lock);
- delayed = __kick_flushing_caps(mdsc, session, ci, true);
+ delayed = __kick_flushing_caps(mdsc, session, ci);
if (delayed) {
spin_lock(&ci->i_ceph_lock);
__cap_delay_requeue(mdsc, ci);
diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c
index 4347039..6706bde 100644
--- a/fs/ceph/locks.c
+++ b/fs/ceph/locks.c
@@ -287,7 +287,7 @@
return 0;
spin_lock(&ctx->flc_lock);
- list_for_each_entry(lock, &ctx->flc_flock, fl_list) {
+ list_for_each_entry(lock, &ctx->flc_posix, fl_list) {
++seen_fcntl;
if (seen_fcntl > num_fcntl_locks) {
err = -ENOSPC;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 860cc016..2f2460d 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -189,7 +189,6 @@
struct ceph_cap_flush {
u64 tid;
int caps;
- bool kick;
struct rb_node g_node; // global
union {
struct rb_node i_node; // inode
diff --git a/fs/char_dev.c b/fs/char_dev.c
index ea06a3d..24b1425 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -274,7 +274,7 @@
}
/**
- * unregister_chrdev_region() - return a range of device numbers
+ * unregister_chrdev_region() - unregister a range of device numbers
* @from: the first in the range of numbers to unregister
* @count: the number of device numbers to unregister
*
diff --git a/fs/dax.c b/fs/dax.c
index c3e21cc..a7f77e1 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -319,6 +319,12 @@
* @vma: The virtual memory area where the fault occurred
* @vmf: The description of the fault
* @get_block: The filesystem method used to translate file offsets to blocks
+ * @complete_unwritten: The filesystem method used to convert unwritten blocks
+ * to written so the data written to them is exposed. This is required for
+ * required by write faults for filesystems that will return unwritten
+ * extent mappings from @get_block, but it is optional for reads as
+ * dax_insert_mapping() will always zero unwritten blocks. If the fs does
+ * not support unwritten extents, the it should pass NULL.
*
* When a page fault occurs, filesystems may call this helper in their
* fault handler for DAX files. __dax_fault() assumes the caller has done all
@@ -437,8 +443,12 @@
* as for normal BH based IO completions.
*/
error = dax_insert_mapping(inode, &bh, vma, vmf);
- if (buffer_unwritten(&bh))
- complete_unwritten(&bh, !error);
+ if (buffer_unwritten(&bh)) {
+ if (complete_unwritten)
+ complete_unwritten(&bh, !error);
+ else
+ WARN_ON_ONCE(!(vmf->flags & FAULT_FLAG_WRITE));
+ }
out:
if (error == -ENOMEM)
diff --git a/fs/dcache.c b/fs/dcache.c
index 5c8ea15..9b5fe50 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -3442,22 +3442,15 @@
inode_init_early();
}
-void __init vfs_caches_init(unsigned long mempages)
+void __init vfs_caches_init(void)
{
- unsigned long reserve;
-
- /* Base hash sizes on available memory, with a reserve equal to
- 150% of current kernel size */
-
- reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
- mempages -= reserve;
-
names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
dcache_init();
inode_init();
- files_init(mempages);
+ files_init();
+ files_maxfiles_init();
mnt_init();
bdev_cache_init();
chrdev_init();
diff --git a/fs/dlm/plock.c b/fs/dlm/plock.c
index e0ab3a9..5532f09 100644
--- a/fs/dlm/plock.c
+++ b/fs/dlm/plock.c
@@ -509,7 +509,6 @@
void dlm_plock_exit(void)
{
- if (misc_deregister(&plock_dev_misc) < 0)
- log_print("dlm_plock_exit: misc_deregister failed");
+ misc_deregister(&plock_dev_misc);
}
diff --git a/fs/dlm/user.c b/fs/dlm/user.c
index fb85f32..75ecc0d 100644
--- a/fs/dlm/user.c
+++ b/fs/dlm/user.c
@@ -362,18 +362,15 @@
int dlm_device_deregister(struct dlm_ls *ls)
{
- int error;
-
/* The device is not registered. This happens when the lockspace
was never used from userspace, or when device_create_lockspace()
calls dlm_release_lockspace() after the register fails. */
if (!ls->ls_device.name)
return 0;
- error = misc_deregister(&ls->ls_device);
- if (!error)
- kfree(ls->ls_device.name);
- return error;
+ misc_deregister(&ls->ls_device);
+ kfree(ls->ls_device.name);
+ return 0;
}
static int device_user_purge(struct dlm_user_proc *proc,
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 9bedfa8..f71e19a 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -2072,8 +2072,6 @@
return 1;
}
- mark_inode_dirty(inode);
-
if (!PageDirty(page)) {
__set_page_dirty_nobuffers(page);
update_dirty_page(inode, page);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index ada2a3d..b0f38c3 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1331,12 +1331,13 @@
if (ret)
return ret;
- if (f2fs_is_atomic_file(inode))
+ if (f2fs_is_atomic_file(inode)) {
+ clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
commit_inmem_pages(inode, false);
+ }
ret = f2fs_sync_file(filp, 0, LONG_MAX, 0);
mnt_drop_write_file(filp);
- clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
return ret;
}
@@ -1387,8 +1388,8 @@
f2fs_balance_fs(F2FS_I_SB(inode));
if (f2fs_is_atomic_file(inode)) {
- commit_inmem_pages(inode, false);
clear_inode_flag(F2FS_I(inode), FI_ATOMIC_FILE);
+ commit_inmem_pages(inode, false);
}
if (f2fs_is_volatile_file(inode))
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index e1e7361..22fb5ef 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -556,27 +556,39 @@
if (!fio.encrypted_page)
goto put_out;
- f2fs_submit_page_bio(&fio);
-
- /* allocate block address */
- f2fs_wait_on_page_writeback(dn.node_page, NODE);
-
- allocate_data_block(fio.sbi, NULL, fio.blk_addr,
- &fio.blk_addr, &sum, CURSEG_COLD_DATA);
- dn.data_blkaddr = fio.blk_addr;
+ err = f2fs_submit_page_bio(&fio);
+ if (err)
+ goto put_page_out;
/* write page */
lock_page(fio.encrypted_page);
+
+ if (unlikely(!PageUptodate(fio.encrypted_page)))
+ goto put_page_out;
+ if (unlikely(fio.encrypted_page->mapping != META_MAPPING(fio.sbi)))
+ goto put_page_out;
+
+ set_page_dirty(fio.encrypted_page);
+ f2fs_wait_on_page_writeback(fio.encrypted_page, META);
+ if (clear_page_dirty_for_io(fio.encrypted_page))
+ dec_page_count(fio.sbi, F2FS_DIRTY_META);
+
set_page_writeback(fio.encrypted_page);
+
+ /* allocate block address */
+ f2fs_wait_on_page_writeback(dn.node_page, NODE);
+ allocate_data_block(fio.sbi, NULL, fio.blk_addr,
+ &fio.blk_addr, &sum, CURSEG_COLD_DATA);
fio.rw = WRITE_SYNC;
f2fs_submit_page_mbio(&fio);
+ dn.data_blkaddr = fio.blk_addr;
set_data_blkaddr(&dn);
f2fs_update_extent_cache(&dn);
set_inode_flag(F2FS_I(inode), FI_APPEND_WRITE);
if (page->index == 0)
set_inode_flag(F2FS_I(inode), FI_FIRST_BLOCK_WRITTEN);
-
+put_page_out:
f2fs_put_page(fio.encrypted_page, 1);
put_out:
f2fs_put_dnode(&dn);
@@ -605,8 +617,8 @@
.page = page,
.encrypted_page = NULL,
};
+ set_page_dirty(page);
f2fs_wait_on_page_writeback(page, DATA);
-
if (clear_page_dirty_for_io(page))
inode_dec_dirty_pages(inode);
set_cold_data(page);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index 38e75fb..a13ffcc 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -141,6 +141,8 @@
kunmap_atomic(dst_addr);
SetPageUptodate(page);
no_update:
+ set_page_dirty(page);
+
/* clear dirty state */
dirty = clear_page_dirty_for_io(page);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 1eb3437..61b97f9 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -257,6 +257,7 @@
if (!abort) {
lock_page(cur->page);
if (cur->page->mapping == inode->i_mapping) {
+ set_page_dirty(cur->page);
f2fs_wait_on_page_writeback(cur->page, DATA);
if (clear_page_dirty_for_io(cur->page))
inode_dec_dirty_pages(inode);
diff --git a/fs/file_table.c b/fs/file_table.c
index 7f9d407..ad17e05 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -25,6 +25,7 @@
#include <linux/hardirq.h>
#include <linux/task_work.h>
#include <linux/ima.h>
+#include <linux/swap.h>
#include <linux/atomic.h>
@@ -308,19 +309,24 @@
}
}
-void __init files_init(unsigned long mempages)
+void __init files_init(void)
{
- unsigned long n;
-
filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
-
- /*
- * One file with associated inode and dcache is very roughly 1K.
- * Per default don't use more than 10% of our memory for files.
- */
-
- n = (mempages * (PAGE_SIZE / 1024)) / 10;
- files_stat.max_files = max_t(unsigned long, n, NR_FILE);
percpu_counter_init(&nr_files, 0, GFP_KERNEL);
+}
+
+/*
+ * One file with associated inode and dcache is very roughly 1K. Per default
+ * do not use more than 10% of our memory for files.
+ */
+void __init files_maxfiles_init(void)
+{
+ unsigned long n;
+ unsigned long memreserve = (totalram_pages - nr_free_pages()) * 3/2;
+
+ memreserve = min(memreserve, totalram_pages - 1);
+ n = ((totalram_pages - memreserve) * (PAGE_SIZE / 1024)) / 10;
+
+ files_stat.max_files = max_t(unsigned long, n, NR_FILE);
}
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c
index f0520bc..5fa588e 100644
--- a/fs/fs-writeback.c
+++ b/fs/fs-writeback.c
@@ -702,6 +702,7 @@
else
wbc->wb_tcand_bytes -= min(bytes, wbc->wb_tcand_bytes);
}
+EXPORT_SYMBOL_GPL(wbc_account_io);
/**
* inode_congested - test whether an inode is congested
@@ -843,14 +844,15 @@
struct wb_iter iter;
might_sleep();
-
- if (!bdi_has_dirty_io(bdi))
- return;
restart:
rcu_read_lock();
bdi_for_each_wb(wb, bdi, &iter, next_blkcg_id) {
- if (!wb_has_dirty_io(wb) ||
- (skip_if_busy && writeback_in_progress(wb)))
+ /* SYNC_ALL writes out I_DIRTY_TIME too */
+ if (!wb_has_dirty_io(wb) &&
+ (base_work->sync_mode == WB_SYNC_NONE ||
+ list_empty(&wb->b_dirty_time)))
+ continue;
+ if (skip_if_busy && writeback_in_progress(wb))
continue;
base_work->nr_pages = wb_split_bdi_pages(wb, nr_pages);
@@ -898,8 +900,7 @@
{
might_sleep();
- if (bdi_has_dirty_io(bdi) &&
- (!skip_if_busy || !writeback_in_progress(&bdi->wb))) {
+ if (!skip_if_busy || !writeback_in_progress(&bdi->wb)) {
base_work->auto_free = 0;
base_work->single_wait = 0;
base_work->single_done = 0;
@@ -2274,8 +2275,12 @@
};
struct backing_dev_info *bdi = sb->s_bdi;
- /* Nothing to do? */
- if (!bdi_has_dirty_io(bdi) || bdi == &noop_backing_dev_info)
+ /*
+ * Can't skip on !bdi_has_dirty() because we should wait for !dirty
+ * inodes under writeback and I_DIRTY_TIME inodes ignored by
+ * bdi_has_dirty() need to be written out too.
+ */
+ if (bdi == &noop_backing_dev_info)
return;
WARN_ON(!rwsem_is_locked(&sb->s_umount));
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 80cc1b3..ebb5e37 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -2246,7 +2246,15 @@
err = -EINVAL;
if (old) {
- struct fuse_dev *fud = fuse_get_dev(old);
+ struct fuse_dev *fud = NULL;
+
+ /*
+ * Check against file->f_op because CUSE
+ * uses the same ioctl handler.
+ */
+ if (old->f_op == file->f_op &&
+ old->f_cred->user_ns == file->f_cred->user_ns)
+ fud = fuse_get_dev(old);
if (fud) {
mutex_lock(&fuse_mutex);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 0cf74df..973c24c 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -1010,6 +1010,8 @@
inode = hugetlbfs_get_inode(sb, NULL, S_IFREG | S_IRWXUGO, 0);
if (!inode)
goto out_dentry;
+ if (creat_flags == HUGETLB_SHMFS_INODE)
+ inode->i_flags |= S_PRIVATE;
file = ERR_PTR(-ENOMEM);
if (hugetlb_reserve_pages(inode, 0,
diff --git a/fs/namei.c b/fs/namei.c
index ae4e4c1..1c2105e 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -879,7 +879,7 @@
return 0;
/* Allowed if parent directory not sticky and world-writable. */
- parent = nd->path.dentry->d_inode;
+ parent = nd->inode;
if ((parent->i_mode & (S_ISVTX|S_IWOTH)) != (S_ISVTX|S_IWOTH))
return 0;
@@ -1954,8 +1954,13 @@
continue;
}
}
- if (unlikely(!d_can_lookup(nd->path.dentry)))
+ if (unlikely(!d_can_lookup(nd->path.dentry))) {
+ if (nd->flags & LOOKUP_RCU) {
+ if (unlazy_walk(nd, NULL, 0))
+ return -ECHILD;
+ }
return -ENOTDIR;
+ }
}
}
diff --git a/fs/namespace.c b/fs/namespace.c
index c7cb8a5..2b8aa15 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1361,6 +1361,36 @@
UMOUNT_PROPAGATE = 2,
UMOUNT_CONNECTED = 4,
};
+
+static bool disconnect_mount(struct mount *mnt, enum umount_tree_flags how)
+{
+ /* Leaving mounts connected is only valid for lazy umounts */
+ if (how & UMOUNT_SYNC)
+ return true;
+
+ /* A mount without a parent has nothing to be connected to */
+ if (!mnt_has_parent(mnt))
+ return true;
+
+ /* Because the reference counting rules change when mounts are
+ * unmounted and connected, umounted mounts may not be
+ * connected to mounted mounts.
+ */
+ if (!(mnt->mnt_parent->mnt.mnt_flags & MNT_UMOUNT))
+ return true;
+
+ /* Has it been requested that the mount remain connected? */
+ if (how & UMOUNT_CONNECTED)
+ return false;
+
+ /* Is the mount locked such that it needs to remain connected? */
+ if (IS_MNT_LOCKED(mnt))
+ return false;
+
+ /* By default disconnect the mount */
+ return true;
+}
+
/*
* mount_lock must be held
* namespace_sem must be held for write
@@ -1398,10 +1428,7 @@
if (how & UMOUNT_SYNC)
p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
- disconnect = !(((how & UMOUNT_CONNECTED) &&
- mnt_has_parent(p) &&
- (p->mnt_parent->mnt.mnt_flags & MNT_UMOUNT)) ||
- IS_MNT_LOCKED_AND_LAZY(p));
+ disconnect = disconnect_mount(p, how);
pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt,
disconnect ? &unmounted : NULL);
@@ -1538,11 +1565,8 @@
while (!hlist_empty(&mp->m_list)) {
mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
- struct mount *p, *tmp;
- list_for_each_entry_safe(p, tmp, &mnt->mnt_mounts, mnt_child) {
- hlist_add_head(&p->mnt_umount.s_list, &unmounted);
- umount_mnt(p);
- }
+ hlist_add_head(&mnt->mnt_umount.s_list, &unmounted);
+ umount_mnt(mnt);
}
else umount_tree(mnt, UMOUNT_CONNECTED);
}
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index ecebb40..4a90c9b 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -775,7 +775,7 @@
server->options = data->options;
server->caps |= NFS_CAP_HARDLINKS|NFS_CAP_SYMLINKS|NFS_CAP_FILEID|
NFS_CAP_MODE|NFS_CAP_NLINK|NFS_CAP_OWNER|NFS_CAP_OWNER_GROUP|
- NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME|NFS_CAP_CHANGE_ATTR;
+ NFS_CAP_ATIME|NFS_CAP_CTIME|NFS_CAP_MTIME;
if (data->rsize)
server->rsize = nfs_block_size(data->rsize, NULL);
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index c12951b..b3289d7 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -1852,7 +1852,7 @@
struct nfs42_layoutstat_devinfo *devinfo;
int i;
- for (i = 0; i <= FF_LAYOUT_MIRROR_COUNT(pls); i++) {
+ for (i = 0; i < FF_LAYOUT_MIRROR_COUNT(pls); i++) {
if (*dev_count >= dev_limit)
break;
mirror = FF_LAYOUT_COMP(pls, i);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index b77b328..0adc7d2 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -442,8 +442,9 @@
nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR);
if (fattr->valid & NFS_ATTR_FATTR_CHANGE)
inode->i_version = fattr->change_attr;
- else if (nfs_server_capable(inode, NFS_CAP_CHANGE_ATTR))
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR);
+ else
+ nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATTR
+ | NFS_INO_REVAL_PAGECACHE);
if (fattr->valid & NFS_ATTR_FATTR_SIZE)
inode->i_size = nfs_size_to_loff_t(fattr->size);
else
@@ -1244,9 +1245,11 @@
if (fattr->valid & NFS_ATTR_FATTR_SIZE) {
cur_size = i_size_read(inode);
new_isize = nfs_size_to_loff_t(fattr->size);
- if (cur_size != new_isize && nfsi->nrequests == 0)
+ if (cur_size != new_isize)
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_REVAL_PAGECACHE;
}
+ if (nfsi->nrequests != 0)
+ invalid &= ~NFS_INO_REVAL_PAGECACHE;
/* Have any file permissions changed? */
if ((fattr->valid & NFS_ATTR_FATTR_MODE) && (inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO))
@@ -1684,13 +1687,12 @@
invalid |= NFS_INO_INVALID_ATTR
| NFS_INO_INVALID_DATA
| NFS_INO_INVALID_ACCESS
- | NFS_INO_INVALID_ACL
- | NFS_INO_REVAL_PAGECACHE;
+ | NFS_INO_INVALID_ACL;
if (S_ISDIR(inode->i_mode))
nfs_force_lookup_revalidate(inode);
inode->i_version = fattr->change_attr;
}
- } else if (server->caps & NFS_CAP_CHANGE_ATTR)
+ } else
nfsi->cache_validity |= save_cache_validity;
if (fattr->valid & NFS_ATTR_FATTR_MTIME) {
@@ -1717,7 +1719,6 @@
if ((nfsi->nrequests == 0) || new_isize > cur_isize) {
i_size_write(inode, new_isize);
invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
- invalid &= ~NFS_INO_REVAL_PAGECACHE;
}
dprintk("NFS: isize change on server for file %s/%ld "
"(%Ld to %Ld)\n",
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 7e3c460..9b372b8 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -296,6 +296,22 @@
#ifdef CONFIG_NFS_V4_SECURITY_LABEL
extern struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags);
+static inline struct nfs4_label *
+nfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src)
+{
+ if (!dst || !src)
+ return NULL;
+
+ if (src->len > NFS4_MAXLABELLEN)
+ return NULL;
+
+ dst->lfs = src->lfs;
+ dst->pi = src->pi;
+ dst->len = src->len;
+ memcpy(dst->label, src->label, src->len);
+
+ return dst;
+}
static inline void nfs4_label_free(struct nfs4_label *label)
{
if (label) {
@@ -316,6 +332,11 @@
static inline void nfs_zap_label_cache_locked(struct nfs_inode *nfsi)
{
}
+static inline struct nfs4_label *
+nfs4_label_copy(struct nfs4_label *dst, struct nfs4_label *src)
+{
+ return NULL;
+}
#endif /* CONFIG_NFS_V4_SECURITY_LABEL */
/* proc.c */
diff --git a/fs/nfs/nfs42proc.c b/fs/nfs/nfs42proc.c
index f486b80..d731bbf 100644
--- a/fs/nfs/nfs42proc.c
+++ b/fs/nfs/nfs42proc.c
@@ -135,7 +135,7 @@
return err;
}
-loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
+static loff_t _nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
{
struct inode *inode = file_inode(filep);
struct nfs42_seek_args args = {
@@ -171,6 +171,23 @@
return vfs_setpos(filep, res.sr_offset, inode->i_sb->s_maxbytes);
}
+loff_t nfs42_proc_llseek(struct file *filep, loff_t offset, int whence)
+{
+ struct nfs_server *server = NFS_SERVER(file_inode(filep));
+ struct nfs4_exception exception = { };
+ int err;
+
+ do {
+ err = _nfs42_proc_llseek(filep, offset, whence);
+ if (err == -ENOTSUPP)
+ return -EOPNOTSUPP;
+ err = nfs4_handle_exception(server, err, &exception);
+ } while (exception.retry);
+
+ return err;
+}
+
+
static void
nfs42_layoutstat_prepare(struct rpc_task *task, void *calldata)
{
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 8bee934..3acb1eb 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -467,7 +467,10 @@
static void renew_lease(const struct nfs_server *server, unsigned long timestamp)
{
- do_renew_lease(server->nfs_client, timestamp);
+ struct nfs_client *clp = server->nfs_client;
+
+ if (!nfs4_has_session(clp))
+ do_renew_lease(clp, timestamp);
}
struct nfs4_call_sync_data {
@@ -616,8 +619,7 @@
clp = session->clp;
do_renew_lease(clp, res->sr_timestamp);
/* Check sequence flags */
- if (res->sr_status_flags != 0)
- nfs4_schedule_lease_recovery(clp);
+ nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
nfs41_update_target_slotid(slot->table, slot, res);
break;
case 1:
@@ -910,6 +912,7 @@
struct nfs_open_confirmres c_res;
struct nfs4_string owner_name;
struct nfs4_string group_name;
+ struct nfs4_label *a_label;
struct nfs_fattr f_attr;
struct nfs4_label *f_label;
struct dentry *dir;
@@ -1013,6 +1016,10 @@
if (IS_ERR(p->f_label))
goto err_free_p;
+ p->a_label = nfs4_label_alloc(server, gfp_mask);
+ if (IS_ERR(p->a_label))
+ goto err_free_f;
+
alloc_seqid = server->nfs_client->cl_mvops->alloc_seqid;
p->o_arg.seqid = alloc_seqid(&sp->so_seqid, gfp_mask);
if (IS_ERR(p->o_arg.seqid))
@@ -1041,7 +1048,7 @@
p->o_arg.server = server;
p->o_arg.bitmask = nfs4_bitmask(server, label);
p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0];
- p->o_arg.label = label;
+ p->o_arg.label = nfs4_label_copy(p->a_label, label);
p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim);
switch (p->o_arg.claim) {
case NFS4_OPEN_CLAIM_NULL:
@@ -1074,6 +1081,8 @@
return p;
err_free_label:
+ nfs4_label_free(p->a_label);
+err_free_f:
nfs4_label_free(p->f_label);
err_free_p:
kfree(p);
@@ -1093,6 +1102,7 @@
nfs4_put_open_state(p->state);
nfs4_put_state_owner(p->owner);
+ nfs4_label_free(p->a_label);
nfs4_label_free(p->f_label);
dput(p->dir);
@@ -1198,12 +1208,15 @@
static void nfs_resync_open_stateid_locked(struct nfs4_state *state)
{
+ if (!(state->n_wronly || state->n_rdonly || state->n_rdwr))
+ return;
if (state->n_wronly)
set_bit(NFS_O_WRONLY_STATE, &state->flags);
if (state->n_rdonly)
set_bit(NFS_O_RDONLY_STATE, &state->flags);
if (state->n_rdwr)
set_bit(NFS_O_RDWR_STATE, &state->flags);
+ set_bit(NFS_OPEN_STATE, &state->flags);
}
static void nfs_clear_open_stateid_locked(struct nfs4_state *state,
@@ -7571,13 +7584,8 @@
goto out;
}
ret = rpc_wait_for_completion_task(task);
- if (!ret) {
- struct nfs4_sequence_res *res = task->tk_msg.rpc_resp;
-
- if (task->tk_status == 0)
- nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
+ if (!ret)
ret = task->tk_status;
- }
rpc_put_task(task);
out:
dprintk("<-- %s status=%d\n", __func__, ret);
@@ -7965,16 +7973,17 @@
{
struct nfs4_layoutreturn *lrp = calldata;
struct pnfs_layout_hdr *lo = lrp->args.layout;
+ LIST_HEAD(freeme);
dprintk("--> %s\n", __func__);
spin_lock(&lo->plh_inode->i_lock);
if (lrp->res.lrs_present)
pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
+ pnfs_mark_matching_lsegs_invalid(lo, &freeme, &lrp->args.range);
pnfs_clear_layoutreturn_waitbit(lo);
- clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags);
- rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq);
lo->plh_block_lgets--;
spin_unlock(&lo->plh_inode->i_lock);
+ pnfs_free_lseg_list(&freeme);
pnfs_put_layout_hdr(lrp->args.layout);
nfs_iput_and_deactive(lrp->inode);
kfree(calldata);
@@ -8588,7 +8597,6 @@
.minor_version = 0,
.init_caps = NFS_CAP_READDIRPLUS
| NFS_CAP_ATOMIC_OPEN
- | NFS_CAP_CHANGE_ATTR
| NFS_CAP_POSIX_LOCK,
.init_client = nfs40_init_client,
.shutdown_client = nfs40_shutdown_client,
@@ -8614,7 +8622,6 @@
.minor_version = 1,
.init_caps = NFS_CAP_READDIRPLUS
| NFS_CAP_ATOMIC_OPEN
- | NFS_CAP_CHANGE_ATTR
| NFS_CAP_POSIX_LOCK
| NFS_CAP_STATEID_NFSV41
| NFS_CAP_ATOMIC_OPEN_V1,
@@ -8637,7 +8644,6 @@
.minor_version = 2,
.init_caps = NFS_CAP_READDIRPLUS
| NFS_CAP_ATOMIC_OPEN
- | NFS_CAP_CHANGE_ATTR
| NFS_CAP_POSIX_LOCK
| NFS_CAP_STATEID_NFSV41
| NFS_CAP_ATOMIC_OPEN_V1
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 605840d..f2e2ad8 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -2191,25 +2191,35 @@
}
}
-static void nfs41_handle_state_revoked(struct nfs_client *clp)
+static void nfs41_handle_all_state_revoked(struct nfs_client *clp)
{
nfs4_reset_all_state(clp);
dprintk("%s: state revoked on server %s\n", __func__, clp->cl_hostname);
}
+static void nfs41_handle_some_state_revoked(struct nfs_client *clp)
+{
+ nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
+ nfs4_schedule_state_manager(clp);
+
+ dprintk("%s: state revoked on server %s\n", __func__, clp->cl_hostname);
+}
+
static void nfs41_handle_recallable_state_revoked(struct nfs_client *clp)
{
- /* This will need to handle layouts too */
- nfs_expire_all_delegations(clp);
+ /* FIXME: For now, we destroy all layouts. */
+ pnfs_destroy_all_layouts(clp);
+ /* FIXME: For now, we test all delegations+open state+locks. */
+ nfs41_handle_some_state_revoked(clp);
dprintk("%s: Recallable state revoked on server %s!\n", __func__,
clp->cl_hostname);
}
static void nfs41_handle_backchannel_fault(struct nfs_client *clp)
{
- nfs_expire_all_delegations(clp);
- if (test_and_set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state) == 0)
- nfs4_schedule_state_manager(clp);
+ set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
+ nfs4_schedule_state_manager(clp);
+
dprintk("%s: server %s declared a backchannel fault\n", __func__,
clp->cl_hostname);
}
@@ -2231,10 +2241,11 @@
if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
nfs41_handle_server_reboot(clp);
- if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED |
- SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
+ if (flags & (SEQ4_STATUS_EXPIRED_ALL_STATE_REVOKED))
+ nfs41_handle_all_state_revoked(clp);
+ if (flags & (SEQ4_STATUS_EXPIRED_SOME_STATE_REVOKED |
SEQ4_STATUS_ADMIN_STATE_REVOKED))
- nfs41_handle_state_revoked(clp);
+ nfs41_handle_some_state_revoked(clp);
if (flags & SEQ4_STATUS_LEASE_MOVED)
nfs4_schedule_lease_moved_recovery(clp);
if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c
index 1da68d3..4984bbe 100644
--- a/fs/nfs/pagelist.c
+++ b/fs/nfs/pagelist.c
@@ -1100,8 +1100,6 @@
mirror->pg_base = 0;
mirror->pg_recoalesce = 0;
- desc->pg_moreio = 0;
-
while (!list_empty(&head)) {
struct nfs_page *req;
@@ -1109,8 +1107,11 @@
nfs_list_remove_request(req);
if (__nfs_pageio_add_request(desc, req))
continue;
- if (desc->pg_error < 0)
+ if (desc->pg_error < 0) {
+ list_splice_tail(&head, &mirror->pg_list);
+ mirror->pg_recoalesce = 1;
return 0;
+ }
break;
}
} while (mirror->pg_recoalesce);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 0ba9a02..70bf706 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -352,7 +352,7 @@
{
struct pnfs_layout_segment *s;
- if (!test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
+ if (!test_and_clear_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
return false;
list_for_each_entry(s, &lo->plh_segs, pls_list)
@@ -362,6 +362,18 @@
return true;
}
+static bool
+pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo)
+{
+ if (test_and_set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+ return false;
+ lo->plh_return_iomode = 0;
+ lo->plh_block_lgets++;
+ pnfs_get_layout_hdr(lo);
+ clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE, &lo->plh_flags);
+ return true;
+}
+
static void pnfs_layoutreturn_before_put_lseg(struct pnfs_layout_segment *lseg,
struct pnfs_layout_hdr *lo, struct inode *inode)
{
@@ -372,17 +384,16 @@
if (pnfs_layout_need_return(lo, lseg)) {
nfs4_stateid stateid;
enum pnfs_iomode iomode;
+ bool send;
stateid = lo->plh_stateid;
iomode = lo->plh_return_iomode;
- /* decreased in pnfs_send_layoutreturn() */
- lo->plh_block_lgets++;
- lo->plh_return_iomode = 0;
+ send = pnfs_prepare_layoutreturn(lo);
spin_unlock(&inode->i_lock);
- pnfs_get_layout_hdr(lo);
-
- /* Send an async layoutreturn so we dont deadlock */
- pnfs_send_layoutreturn(lo, stateid, iomode, false);
+ if (send) {
+ /* Send an async layoutreturn so we dont deadlock */
+ pnfs_send_layoutreturn(lo, stateid, iomode, false);
+ }
} else
spin_unlock(&inode->i_lock);
}
@@ -411,6 +422,10 @@
pnfs_layoutreturn_before_put_lseg(lseg, lo, inode);
if (atomic_dec_and_lock(&lseg->pls_refcount, &inode->i_lock)) {
+ if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags)) {
+ spin_unlock(&inode->i_lock);
+ return;
+ }
pnfs_get_layout_hdr(lo);
pnfs_layout_remove_lseg(lo, lseg);
spin_unlock(&inode->i_lock);
@@ -451,6 +466,8 @@
test_bit(NFS_LSEG_VALID, &lseg->pls_flags));
if (atomic_dec_and_test(&lseg->pls_refcount)) {
struct pnfs_layout_hdr *lo = lseg->pls_layout;
+ if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags))
+ return;
pnfs_get_layout_hdr(lo);
pnfs_layout_remove_lseg(lo, lseg);
pnfs_free_lseg_async(lseg);
@@ -924,6 +941,7 @@
clear_bit_unlock(NFS_LAYOUT_RETURN, &lo->plh_flags);
smp_mb__after_atomic();
wake_up_bit(&lo->plh_flags, NFS_LAYOUT_RETURN);
+ rpc_wake_up(&NFS_SERVER(lo->plh_inode)->roc_rpcwaitq);
}
static int
@@ -978,6 +996,7 @@
LIST_HEAD(tmp_list);
nfs4_stateid stateid;
int status = 0, empty;
+ bool send;
dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino);
@@ -1007,17 +1026,18 @@
/* Don't send a LAYOUTRETURN if list was initially empty */
if (empty) {
spin_unlock(&ino->i_lock);
- pnfs_put_layout_hdr(lo);
dprintk("NFS: %s no layout segments to return\n", __func__);
- goto out;
+ goto out_put_layout_hdr;
}
set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
- lo->plh_block_lgets++;
+ send = pnfs_prepare_layoutreturn(lo);
spin_unlock(&ino->i_lock);
pnfs_free_lseg_list(&tmp_list);
-
- status = pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true);
+ if (send)
+ status = pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, true);
+out_put_layout_hdr:
+ pnfs_put_layout_hdr(lo);
out:
dprintk("<-- %s status: %d\n", __func__, status);
return status;
@@ -1097,13 +1117,9 @@
out_noroc:
if (lo) {
stateid = lo->plh_stateid;
- layoutreturn =
- test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
- &lo->plh_flags);
- if (layoutreturn) {
- lo->plh_block_lgets++;
- pnfs_get_layout_hdr(lo);
- }
+ if (test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
+ &lo->plh_flags))
+ layoutreturn = pnfs_prepare_layoutreturn(lo);
}
spin_unlock(&ino->i_lock);
if (layoutreturn) {
@@ -1146,15 +1162,18 @@
struct pnfs_layout_segment *lseg;
nfs4_stateid stateid;
u32 current_seqid;
- bool found = false, layoutreturn = false;
+ bool layoutreturn = false;
spin_lock(&ino->i_lock);
- list_for_each_entry(lseg, &nfsi->layout->plh_segs, pls_list)
- if (test_bit(NFS_LSEG_ROC, &lseg->pls_flags)) {
- rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
- found = true;
- goto out;
- }
+ list_for_each_entry(lseg, &nfsi->layout->plh_segs, pls_list) {
+ if (!test_bit(NFS_LSEG_ROC, &lseg->pls_flags))
+ continue;
+ if (test_bit(NFS_LSEG_VALID, &lseg->pls_flags))
+ continue;
+ rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
+ spin_unlock(&ino->i_lock);
+ return true;
+ }
lo = nfsi->layout;
current_seqid = be32_to_cpu(lo->plh_stateid.seqid);
@@ -1162,23 +1181,19 @@
* a barrier, we choose the worst-case barrier.
*/
*barrier = current_seqid + atomic_read(&lo->plh_outstanding);
-out:
- if (!found) {
- stateid = lo->plh_stateid;
- layoutreturn =
- test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
- &lo->plh_flags);
- if (layoutreturn) {
- lo->plh_block_lgets++;
- pnfs_get_layout_hdr(lo);
- }
- }
+ stateid = lo->plh_stateid;
+ if (test_and_clear_bit(NFS_LAYOUT_RETURN_BEFORE_CLOSE,
+ &lo->plh_flags))
+ layoutreturn = pnfs_prepare_layoutreturn(lo);
+ if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
+ rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
+
spin_unlock(&ino->i_lock);
if (layoutreturn) {
- rpc_sleep_on(&NFS_SERVER(ino)->roc_rpcwaitq, task, NULL);
pnfs_send_layoutreturn(lo, stateid, IOMODE_ANY, false);
+ return true;
}
- return found;
+ return false;
}
/*
@@ -1695,7 +1710,6 @@
spin_lock(&inode->i_lock);
/* set failure bit so that pnfs path will be retried later */
pnfs_layout_set_fail_bit(lo, iomode);
- set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
if (lo->plh_return_iomode == 0)
lo->plh_return_iomode = range.iomode;
else if (lo->plh_return_iomode != range.iomode)
@@ -2207,13 +2221,12 @@
if (ld->prepare_layoutcommit) {
status = ld->prepare_layoutcommit(&data->args);
if (status) {
+ put_rpccred(data->cred);
spin_lock(&inode->i_lock);
set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags);
if (end_pos > nfsi->layout->plh_lwb)
nfsi->layout->plh_lwb = end_pos;
- spin_unlock(&inode->i_lock);
- put_rpccred(data->cred);
- goto clear_layoutcommitting;
+ goto out_unlock;
}
}
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 65869ca..75a35a1 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1379,24 +1379,27 @@
{
struct nfs_pgio_args *argp = &hdr->args;
struct nfs_pgio_res *resp = &hdr->res;
+ u64 size = argp->offset + resp->count;
if (!(fattr->valid & NFS_ATTR_FATTR_SIZE))
+ fattr->size = size;
+ if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode)) {
+ fattr->valid &= ~NFS_ATTR_FATTR_SIZE;
return;
- if (argp->offset + resp->count != fattr->size)
- return;
- if (nfs_size_to_loff_t(fattr->size) < i_size_read(hdr->inode))
+ }
+ if (size != fattr->size)
return;
/* Set attribute barrier */
nfs_fattr_set_barrier(fattr);
+ /* ...and update size */
+ fattr->valid |= NFS_ATTR_FATTR_SIZE;
}
void nfs_writeback_update_inode(struct nfs_pgio_header *hdr)
{
- struct nfs_fattr *fattr = hdr->res.fattr;
+ struct nfs_fattr *fattr = &hdr->fattr;
struct inode *inode = hdr->inode;
- if (fattr == NULL)
- return;
spin_lock(&inode->i_lock);
nfs_writeback_check_extend(hdr, fattr);
nfs_post_op_update_inode_force_wcc_locked(inode, fattr);
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c
index 6904213..ebf90e4 100644
--- a/fs/nfsd/nfs4layouts.c
+++ b/fs/nfsd/nfs4layouts.c
@@ -212,6 +212,7 @@
BUG_ON(!ls->ls_file);
if (nfsd4_layout_setlease(ls)) {
+ fput(ls->ls_file);
put_nfs4_file(fp);
kmem_cache_free(nfs4_layout_stateid_cache, ls);
return NULL;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 61dfb33..9520271 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4396,9 +4396,9 @@
queue_delayed_work(laundry_wq, &nn->laundromat_work, t*HZ);
}
-static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *stp)
+static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stid *stp)
{
- if (!fh_match(&fhp->fh_handle, &stp->st_stid.sc_file->fi_fhandle))
+ if (!fh_match(&fhp->fh_handle, &stp->sc_file->fi_fhandle))
return nfserr_bad_stateid;
return nfs_ok;
}
@@ -4601,9 +4601,6 @@
{
__be32 status;
- status = nfs4_check_fh(fhp, ols);
- if (status)
- return status;
status = nfsd4_check_openowner_confirmed(ols);
if (status)
return status;
@@ -4690,6 +4687,9 @@
status = nfserr_bad_stateid;
break;
}
+ if (status)
+ goto out;
+ status = nfs4_check_fh(fhp, s);
done:
if (!status && filpp)
@@ -4798,7 +4798,7 @@
status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
if (status)
return status;
- return nfs4_check_fh(current_fh, stp);
+ return nfs4_check_fh(current_fh, &stp->st_stid);
}
/*
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 5463385..75e0563 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -2143,6 +2143,7 @@
#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
FATTR4_WORD0_RDATTR_ERROR)
#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
+#define WORD2_ABSENT_FS_ATTRS 0
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
static inline __be32
@@ -2171,7 +2172,7 @@
{ return 0; }
#endif
-static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
+static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *bmval2, u32 *rdattr_err)
{
/* As per referral draft: */
if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
@@ -2184,6 +2185,7 @@
}
*bmval0 &= WORD0_ABSENT_FS_ATTRS;
*bmval1 &= WORD1_ABSENT_FS_ATTRS;
+ *bmval2 &= WORD2_ABSENT_FS_ATTRS;
return 0;
}
@@ -2246,8 +2248,7 @@
BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));
if (exp->ex_fslocs.migrated) {
- BUG_ON(bmval[2]);
- status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
+ status = fattr_handle_absent_fs(&bmval0, &bmval1, &bmval2, &rdattr_err);
if (status)
goto out;
}
@@ -2286,8 +2287,8 @@
}
#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
- if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) ||
- bmval[0] & FATTR4_WORD0_SUPPORTED_ATTRS) {
+ if ((bmval2 & FATTR4_WORD2_SECURITY_LABEL) ||
+ bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
err = security_inode_getsecctx(d_inode(dentry),
&context, &contextlen);
contextsupport = (err == 0);
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 3e594ce4..39ddcaf 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -152,15 +152,31 @@
BUG();
list_del_init(&mark->g_list);
+
spin_unlock(&mark->lock);
if (inode && (mark->flags & FSNOTIFY_MARK_FLAG_OBJECT_PINNED))
iput(inode);
+ /* release lock temporarily */
+ mutex_unlock(&group->mark_mutex);
spin_lock(&destroy_lock);
list_add(&mark->g_list, &destroy_list);
spin_unlock(&destroy_lock);
wake_up(&destroy_waitq);
+ /*
+ * We don't necessarily have a ref on mark from caller so the above destroy
+ * may have actually freed it, unless this group provides a 'freeing_mark'
+ * function which must be holding a reference.
+ */
+
+ /*
+ * Some groups like to know that marks are being freed. This is a
+ * callback to the group function to let it know that this mark
+ * is being freed.
+ */
+ if (group->ops->freeing_mark)
+ group->ops->freeing_mark(mark, group);
/*
* __fsnotify_update_child_dentry_flags(inode);
@@ -175,6 +191,8 @@
*/
atomic_dec(&group->num_marks);
+
+ mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
}
void fsnotify_destroy_mark(struct fsnotify_mark *mark,
@@ -187,10 +205,7 @@
/*
* Destroy all marks in the given list. The marks must be already detached from
- * the original inode / vfsmount. Note that we can race with
- * fsnotify_clear_marks_by_group_flags(). However we hold a reference to each
- * mark so they won't get freed from under us and nobody else touches our
- * free_list list_head.
+ * the original inode / vfsmount.
*/
void fsnotify_destroy_marks(struct list_head *to_free)
{
@@ -391,22 +406,42 @@
}
/*
- * Clear any marks in a group in which mark->flags & flags is true.
+ * clear any marks in a group in which mark->flags & flags is true
*/
void fsnotify_clear_marks_by_group_flags(struct fsnotify_group *group,
unsigned int flags)
{
struct fsnotify_mark *lmark, *mark;
+ LIST_HEAD(to_free);
+ /*
+ * We have to be really careful here. Anytime we drop mark_mutex, e.g.
+ * fsnotify_clear_marks_by_inode() can come and free marks. Even in our
+ * to_free list so we have to use mark_mutex even when accessing that
+ * list. And freeing mark requires us to drop mark_mutex. So we can
+ * reliably free only the first mark in the list. That's why we first
+ * move marks to free to to_free list in one go and then free marks in
+ * to_free list one by one.
+ */
mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
list_for_each_entry_safe(mark, lmark, &group->marks_list, g_list) {
- if (mark->flags & flags) {
- fsnotify_get_mark(mark);
- fsnotify_destroy_mark_locked(mark, group);
- fsnotify_put_mark(mark);
- }
+ if (mark->flags & flags)
+ list_move(&mark->g_list, &to_free);
}
mutex_unlock(&group->mark_mutex);
+
+ while (1) {
+ mutex_lock_nested(&group->mark_mutex, SINGLE_DEPTH_NESTING);
+ if (list_empty(&to_free)) {
+ mutex_unlock(&group->mark_mutex);
+ break;
+ }
+ mark = list_first_entry(&to_free, struct fsnotify_mark, g_list);
+ fsnotify_get_mark(mark);
+ fsnotify_destroy_mark_locked(mark, group);
+ mutex_unlock(&group->mark_mutex);
+ fsnotify_put_mark(mark);
+ }
}
/*
@@ -445,7 +480,6 @@
{
struct fsnotify_mark *mark, *next;
struct list_head private_destroy_list;
- struct fsnotify_group *group;
for (;;) {
spin_lock(&destroy_lock);
@@ -457,14 +491,6 @@
list_for_each_entry_safe(mark, next, &private_destroy_list, g_list) {
list_del_init(&mark->g_list);
- group = mark->group;
- /*
- * Some groups like to know that marks are being freed.
- * This is a callback to the group function to let it
- * know that this mark is being freed.
- */
- if (group && group->ops->freeing_mark)
- group->ops->freeing_mark(mark, group);
fsnotify_put_mark(mark);
}
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
index 1a35c61..0f5fd9d 100644
--- a/fs/ocfs2/aops.c
+++ b/fs/ocfs2/aops.c
@@ -685,7 +685,7 @@
if (p_cpos && !(ext_flags & OCFS2_EXT_UNWRITTEN)) {
u64 s = i_size_read(inode);
- sector_t sector = (p_cpos << (osb->s_clustersize_bits - 9)) +
+ sector_t sector = ((u64)p_cpos << (osb->s_clustersize_bits - 9)) +
(do_div(s, osb->s_clustersize) >> 9);
ret = blkdev_issue_zeroout(osb->sb->s_bdev, sector,
@@ -910,7 +910,7 @@
BUG_ON(!p_cpos || (ext_flags & OCFS2_EXT_UNWRITTEN));
ret = blkdev_issue_zeroout(osb->sb->s_bdev,
- p_cpos << (osb->s_clustersize_bits - 9),
+ (u64)p_cpos << (osb->s_clustersize_bits - 9),
zero_len_head >> 9, GFP_NOFS, false);
if (ret < 0)
mlog_errno(ret);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 8b23aa2..23157e4 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -4025,9 +4025,13 @@
osb->dc_work_sequence = osb->dc_wake_sequence;
processed = osb->blocked_lock_count;
- while (processed) {
- BUG_ON(list_empty(&osb->blocked_lock_list));
-
+ /*
+ * blocked lock processing in this loop might call iput which can
+ * remove items off osb->blocked_lock_list. Downconvert up to
+ * 'processed' number of locks, but stop short if we had some
+ * removed in ocfs2_mark_lockres_freeing when downconverting.
+ */
+ while (processed && !list_empty(&osb->blocked_lock_list)) {
lockres = list_entry(osb->blocked_lock_list.next,
struct ocfs2_lock_res, l_blocked_list);
list_del_init(&lockres->l_blocked_list);
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
index 2768eb1..ced70c8 100644
--- a/fs/ocfs2/stack_user.c
+++ b/fs/ocfs2/stack_user.c
@@ -655,14 +655,7 @@
static void ocfs2_control_exit(void)
{
- int rc;
-
- rc = misc_deregister(&ocfs2_control_device);
- if (rc)
- printk(KERN_ERR
- "ocfs2: Unable to deregister ocfs2_control device "
- "(errno %d)\n",
- -rc);
+ misc_deregister(&ocfs2_control_device);
}
static void fsdlm_lock_ast_wrapper(void *astarg)
diff --git a/fs/pnode.h b/fs/pnode.h
index 7114ce6..0fcdbe7 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -20,8 +20,6 @@
#define SET_MNT_MARK(m) ((m)->mnt.mnt_flags |= MNT_MARKED)
#define CLEAR_MNT_MARK(m) ((m)->mnt.mnt_flags &= ~MNT_MARKED)
#define IS_MNT_LOCKED(m) ((m)->mnt.mnt_flags & MNT_LOCKED)
-#define IS_MNT_LOCKED_AND_LAZY(m) \
- (((m)->mnt.mnt_flags & (MNT_LOCKED|MNT_SYNC_UMOUNT)) == MNT_LOCKED)
#define CL_EXPIRE 0x01
#define CL_SLAVE 0x02
diff --git a/fs/signalfd.c b/fs/signalfd.c
index 7e412ad..270221f 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -121,8 +121,9 @@
* Other callers might not initialize the si_lsb field,
* so check explicitly for the right codes here.
*/
- if (kinfo->si_code == BUS_MCEERR_AR ||
- kinfo->si_code == BUS_MCEERR_AO)
+ if (kinfo->si_signo == SIGBUS &&
+ (kinfo->si_code == BUS_MCEERR_AR ||
+ kinfo->si_code == BUS_MCEERR_AO))
err |= __put_user((short) kinfo->si_addr_lsb,
&uinfo->ssi_addr_lsb);
#endif
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 6afac3d..8d0b3ad 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1652,17 +1652,9 @@
iinfo->i_ext.i_data, inode->i_sb->s_blocksize -
sizeof(struct unallocSpaceEntry));
use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE);
- use->descTag.tagLocation =
- cpu_to_le32(iinfo->i_location.logicalBlockNum);
- crclen = sizeof(struct unallocSpaceEntry) +
- iinfo->i_lenAlloc - sizeof(struct tag);
- use->descTag.descCRCLength = cpu_to_le16(crclen);
- use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use +
- sizeof(struct tag),
- crclen));
- use->descTag.tagChecksum = udf_tag_checksum(&use->descTag);
+ crclen = sizeof(struct unallocSpaceEntry);
- goto out;
+ goto finish;
}
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_UID_FORGET))
@@ -1782,6 +1774,8 @@
efe->descTag.tagIdent = cpu_to_le16(TAG_IDENT_EFE);
crclen = sizeof(struct extendedFileEntry);
}
+
+finish:
if (iinfo->i_strat4096) {
fe->icbTag.strategyType = cpu_to_le16(4096);
fe->icbTag.strategyParameter = cpu_to_le16(1);
@@ -1791,7 +1785,9 @@
fe->icbTag.numEntries = cpu_to_le16(1);
}
- if (S_ISDIR(inode->i_mode))
+ if (iinfo->i_use)
+ fe->icbTag.fileType = ICBTAG_FILE_TYPE_USE;
+ else if (S_ISDIR(inode->i_mode))
fe->icbTag.fileType = ICBTAG_FILE_TYPE_DIRECTORY;
else if (S_ISREG(inode->i_mode))
fe->icbTag.fileType = ICBTAG_FILE_TYPE_REGULAR;
@@ -1828,7 +1824,6 @@
crclen));
fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag);
-out:
set_buffer_uptodate(bh);
unlock_buffer(bh);
diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c
index 20de88d..dd71403 100644
--- a/fs/xfs/libxfs/xfs_attr_remote.c
+++ b/fs/xfs/libxfs/xfs_attr_remote.c
@@ -159,11 +159,10 @@
struct xfs_buf *bp)
{
struct xfs_mount *mp = bp->b_target->bt_mount;
- struct xfs_buf_log_item *bip = bp->b_fspriv;
+ int blksize = mp->m_attr_geo->blksize;
char *ptr;
int len;
xfs_daddr_t bno;
- int blksize = mp->m_attr_geo->blksize;
/* no verification of non-crc buffers */
if (!xfs_sb_version_hascrc(&mp->m_sb))
@@ -175,16 +174,22 @@
ASSERT(len >= blksize);
while (len > 0) {
+ struct xfs_attr3_rmt_hdr *rmt = (struct xfs_attr3_rmt_hdr *)ptr;
+
if (!xfs_attr3_rmt_verify(mp, ptr, blksize, bno)) {
xfs_buf_ioerror(bp, -EFSCORRUPTED);
xfs_verifier_error(bp);
return;
}
- if (bip) {
- struct xfs_attr3_rmt_hdr *rmt;
- rmt = (struct xfs_attr3_rmt_hdr *)ptr;
- rmt->rm_lsn = cpu_to_be64(bip->bli_item.li_lsn);
+ /*
+ * Ensure we aren't writing bogus LSNs to disk. See
+ * xfs_attr3_rmt_hdr_set() for the explanation.
+ */
+ if (rmt->rm_lsn != cpu_to_be64(NULLCOMMITLSN)) {
+ xfs_buf_ioerror(bp, -EFSCORRUPTED);
+ xfs_verifier_error(bp);
+ return;
}
xfs_update_cksum(ptr, blksize, XFS_ATTR3_RMT_CRC_OFF);
@@ -221,6 +226,18 @@
rmt->rm_owner = cpu_to_be64(ino);
rmt->rm_blkno = cpu_to_be64(bno);
+ /*
+ * Remote attribute blocks are written synchronously, so we don't
+ * have an LSN that we can stamp in them that makes any sense to log
+ * recovery. To ensure that log recovery handles overwrites of these
+ * blocks sanely (i.e. once they've been freed and reallocated as some
+ * other type of metadata) we need to ensure that the LSN has a value
+ * that tells log recovery to ignore the LSN and overwrite the buffer
+ * with whatever is in it's log. To do this, we use the magic
+ * NULLCOMMITLSN to indicate that the LSN is invalid.
+ */
+ rmt->rm_lsn = cpu_to_be64(NULLCOMMITLSN);
+
return sizeof(struct xfs_attr3_rmt_hdr);
}
@@ -434,14 +451,21 @@
/*
* Allocate a single extent, up to the size of the value.
+ *
+ * Note that we have to consider this a data allocation as we
+ * write the remote attribute without logging the contents.
+ * Hence we must ensure that we aren't using blocks that are on
+ * the busy list so that we don't overwrite blocks which have
+ * recently been freed but their transactions are not yet
+ * committed to disk. If we overwrite the contents of a busy
+ * extent and then crash then the block may not contain the
+ * correct metadata after log recovery occurs.
*/
xfs_bmap_init(args->flist, args->firstblock);
nmap = 1;
error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno,
- blkcnt,
- XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA,
- args->firstblock, args->total, &map, &nmap,
- args->flist);
+ blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock,
+ args->total, &map, &nmap, args->flist);
if (!error) {
error = xfs_bmap_finish(&args->trans, args->flist,
&committed);
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index f0e8249..db4acc1 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1514,18 +1514,27 @@
struct vm_area_struct *vma,
struct vm_fault *vmf)
{
- struct xfs_inode *ip = XFS_I(file_inode(vma->vm_file));
+ struct inode *inode = file_inode(vma->vm_file);
int ret;
- trace_xfs_filemap_fault(ip);
+ trace_xfs_filemap_fault(XFS_I(inode));
/* DAX can shortcut the normal fault path on write faults! */
- if ((vmf->flags & FAULT_FLAG_WRITE) && IS_DAX(VFS_I(ip)))
+ if ((vmf->flags & FAULT_FLAG_WRITE) && IS_DAX(inode))
return xfs_filemap_page_mkwrite(vma, vmf);
- xfs_ilock(ip, XFS_MMAPLOCK_SHARED);
- ret = filemap_fault(vma, vmf);
- xfs_iunlock(ip, XFS_MMAPLOCK_SHARED);
+ xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
+ if (IS_DAX(inode)) {
+ /*
+ * we do not want to trigger unwritten extent conversion on read
+ * faults - that is unnecessary overhead and would also require
+ * changes to xfs_get_blocks_direct() to map unwritten extent
+ * ioend for conversion on read-only mappings.
+ */
+ ret = __dax_fault(vma, vmf, xfs_get_blocks_direct, NULL);
+ } else
+ ret = filemap_fault(vma, vmf);
+ xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED);
return ret;
}
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 01dd228..480ebba 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1886,9 +1886,14 @@
uuid = &((struct xfs_dir3_blk_hdr *)blk)->uuid;
break;
case XFS_ATTR3_RMT_MAGIC:
- lsn = be64_to_cpu(((struct xfs_attr3_rmt_hdr *)blk)->rm_lsn);
- uuid = &((struct xfs_attr3_rmt_hdr *)blk)->rm_uuid;
- break;
+ /*
+ * Remote attr blocks are written synchronously, rather than
+ * being logged. That means they do not contain a valid LSN
+ * (i.e. transactionally ordered) in them, and hence any time we
+ * see a buffer to replay over the top of a remote attribute
+ * block we should simply do so.
+ */
+ goto recover_immediately;
case XFS_SB_MAGIC:
lsn = be64_to_cpu(((struct xfs_dsb *)blk)->sb_lsn);
uuid = &((struct xfs_dsb *)blk)->sb_uuid;
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 48db6a5..5aa5197 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -691,7 +691,7 @@
struct timer_list disable_timer; /* delayed disable timer */
/* vblank counter, protected by dev->vblank_time_lock for writes */
- unsigned long count;
+ u32 count;
/* vblank timestamps, protected by dev->vblank_time_lock for writes */
struct timeval time[DRM_VBLANKTIME_RBSIZE];
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 57ca8cc..3b4d8a4 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -743,8 +743,6 @@
uint8_t num_h_tile, num_v_tile;
uint8_t tile_h_loc, tile_v_loc;
uint16_t tile_h_size, tile_v_size;
-
- struct list_head destroy_list;
};
/**
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index c8fc187..918aa68 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -168,6 +168,7 @@
* @get_modes: get mode list for this connector
* @mode_valid: is this mode valid on the given connector? (optional)
* @best_encoder: return the preferred encoder for this connector
+ * @atomic_best_encoder: atomic version of @best_encoder
*
* The helper operations are called by the mid-layer CRTC helper.
*/
@@ -176,6 +177,8 @@
enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
struct drm_display_mode *mode);
struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
+ struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector,
+ struct drm_connector_state *connector_state);
};
extern void drm_helper_disable_unused_functions(struct drm_device *dev);
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h
index 7990501..53c53c4 100644
--- a/include/drm/drm_edid.h
+++ b/include/drm/drm_edid.h
@@ -348,6 +348,25 @@
}
/**
+ * drm_eld_sad - Get ELD SAD structures.
+ * @eld: pointer to an eld memory structure with sad_count set
+ */
+static inline const uint8_t *drm_eld_sad(const uint8_t *eld)
+{
+ unsigned int ver, mnl;
+
+ ver = (eld[DRM_ELD_VER] & DRM_ELD_VER_MASK) >> DRM_ELD_VER_SHIFT;
+ if (ver != 2 && ver != 31)
+ return NULL;
+
+ mnl = drm_eld_mnl(eld);
+ if (mnl > 16)
+ return NULL;
+
+ return eld + DRM_ELD_CEA_SAD(mnl, 0);
+}
+
+/**
* drm_eld_sad_count - Get ELD SAD count.
* @eld: pointer to an eld memory structure with sad_count set
*/
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
index 45c39a3..8bc073d 100644
--- a/include/drm/drm_pciids.h
+++ b/include/drm/drm_pciids.h
@@ -172,6 +172,7 @@
{0x1002, 0x6610, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6611, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6613, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6617, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6620, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6621, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6623, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_OLAND|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
diff --git a/include/linux/amba/serial.h b/include/linux/amba/serial.h
index 0ddb5c0..6a0a89e 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -33,12 +33,14 @@
#define UART01x_DR 0x00 /* Data read or written from the interface. */
#define UART01x_RSR 0x04 /* Receive status register (Read). */
#define UART01x_ECR 0x04 /* Error clear register (Write). */
+#define ZX_UART01x_DR 0x04 /* Data read or written from the interface. */
#define UART010_LCRH 0x08 /* Line control register, high byte. */
#define ST_UART011_DMAWM 0x08 /* DMA watermark configure register. */
#define UART010_LCRM 0x0C /* Line control register, middle byte. */
#define ST_UART011_TIMEOUT 0x0C /* Timeout period register. */
#define UART010_LCRL 0x10 /* Line control register, low byte. */
#define UART010_CR 0x14 /* Control register. */
+#define ZX_UART01x_FR 0x14 /* Flag register (Read only). */
#define UART01x_FR 0x18 /* Flag register (Read only). */
#define UART010_IIR 0x1C /* Interrupt identification register (Read). */
#define UART010_ICR 0x1C /* Interrupt clear register (Write). */
@@ -49,13 +51,21 @@
#define UART011_LCRH 0x2c /* Line control register. */
#define ST_UART011_LCRH_TX 0x2c /* Tx Line control register. */
#define UART011_CR 0x30 /* Control register. */
+#define ZX_UART011_LCRH_TX 0x30 /* Tx Line control register. */
#define UART011_IFLS 0x34 /* Interrupt fifo level select. */
+#define ZX_UART011_CR 0x34 /* Control register. */
+#define ZX_UART011_IFLS 0x38 /* Interrupt fifo level select. */
#define UART011_IMSC 0x38 /* Interrupt mask. */
#define UART011_RIS 0x3c /* Raw interrupt status. */
#define UART011_MIS 0x40 /* Masked interrupt status. */
+#define ZX_UART011_IMSC 0x40 /* Interrupt mask. */
#define UART011_ICR 0x44 /* Interrupt clear register. */
+#define ZX_UART011_RIS 0x44 /* Raw interrupt status. */
#define UART011_DMACR 0x48 /* DMA control register. */
+#define ZX_UART011_MIS 0x48 /* Masked interrupt status. */
+#define ZX_UART011_ICR 0x4c /* Interrupt clear register. */
#define ST_UART011_XFCR 0x50 /* XON/XOFF control register. */
+#define ZX_UART011_DMACR 0x50 /* DMA control register. */
#define ST_UART011_XON1 0x54 /* XON1 register. */
#define ST_UART011_XON2 0x58 /* XON2 register. */
#define ST_UART011_XOFF1 0x5C /* XON1 register. */
@@ -75,15 +85,19 @@
#define UART01x_RSR_PE 0x02
#define UART01x_RSR_FE 0x01
+#define ZX_UART01x_FR_BUSY 0x300
#define UART011_FR_RI 0x100
#define UART011_FR_TXFE 0x080
#define UART011_FR_RXFF 0x040
#define UART01x_FR_TXFF 0x020
#define UART01x_FR_RXFE 0x010
#define UART01x_FR_BUSY 0x008
+#define ZX_UART01x_FR_DSR 0x008
#define UART01x_FR_DCD 0x004
#define UART01x_FR_DSR 0x002
+#define ZX_UART01x_FR_CTS 0x002
#define UART01x_FR_CTS 0x001
+#define ZX_UART011_FR_RI 0x001
#define UART01x_FR_TMSK (UART01x_FR_TXFF + UART01x_FR_BUSY)
#define UART011_CR_CTSEN 0x8000 /* CTS hardware flow control */
diff --git a/include/linux/ata.h b/include/linux/ata.h
index fed3641..d2992bf 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -45,6 +45,7 @@
ATA_SECT_SIZE = 512,
ATA_MAX_SECTORS_128 = 128,
ATA_MAX_SECTORS = 256,
+ ATA_MAX_SECTORS_1024 = 1024,
ATA_MAX_SECTORS_LBA48 = 65535,/* TODO: 65536? */
ATA_MAX_SECTORS_TAPE = 65535,
@@ -384,8 +385,6 @@
SATA_SSP = 0x06, /* Software Settings Preservation */
SATA_DEVSLP = 0x09, /* Device Sleep */
- SETFEATURE_SENSE_DATA = 0xC3, /* Sense Data Reporting feature */
-
/* feature values for SET_MAX */
ATA_SET_MAX_ADDR = 0x00,
ATA_SET_MAX_PASSWD = 0x01,
@@ -529,8 +528,6 @@
#define ata_id_cdb_intr(id) (((id)[ATA_ID_CONFIG] & 0x60) == 0x20)
#define ata_id_has_da(id) ((id)[ATA_ID_SATA_CAPABILITY_2] & (1 << 4))
#define ata_id_has_devslp(id) ((id)[ATA_ID_FEATURE_SUPP] & (1 << 8))
-#define ata_id_has_ncq_autosense(id) \
- ((id)[ATA_ID_FEATURE_SUPP] & (1 << 7))
static inline bool ata_id_has_hipm(const u16 *id)
{
@@ -719,20 +716,6 @@
return false;
}
-static inline bool ata_id_has_sense_reporting(const u16 *id)
-{
- if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
- return false;
- return id[ATA_ID_COMMAND_SET_3] & (1 << 6);
-}
-
-static inline bool ata_id_sense_reporting_enabled(const u16 *id)
-{
- if (!(id[ATA_ID_CFS_ENABLE_2] & (1 << 15)))
- return false;
- return id[ATA_ID_COMMAND_SET_4] & (1 << 6);
-}
-
/**
* ata_id_major_version - get ATA level of drive
* @id: Identify data
diff --git a/include/linux/atmel_serial.h b/include/linux/atmel_serial.h
index 00beddf..ee696d7 100644
--- a/include/linux/atmel_serial.h
+++ b/include/linux/atmel_serial.h
@@ -16,115 +16,151 @@
#ifndef ATMEL_SERIAL_H
#define ATMEL_SERIAL_H
-#define ATMEL_US_CR 0x00 /* Control Register */
-#define ATMEL_US_RSTRX (1 << 2) /* Reset Receiver */
-#define ATMEL_US_RSTTX (1 << 3) /* Reset Transmitter */
-#define ATMEL_US_RXEN (1 << 4) /* Receiver Enable */
-#define ATMEL_US_RXDIS (1 << 5) /* Receiver Disable */
-#define ATMEL_US_TXEN (1 << 6) /* Transmitter Enable */
-#define ATMEL_US_TXDIS (1 << 7) /* Transmitter Disable */
-#define ATMEL_US_RSTSTA (1 << 8) /* Reset Status Bits */
-#define ATMEL_US_STTBRK (1 << 9) /* Start Break */
-#define ATMEL_US_STPBRK (1 << 10) /* Stop Break */
-#define ATMEL_US_STTTO (1 << 11) /* Start Time-out */
-#define ATMEL_US_SENDA (1 << 12) /* Send Address */
-#define ATMEL_US_RSTIT (1 << 13) /* Reset Iterations */
-#define ATMEL_US_RSTNACK (1 << 14) /* Reset Non Acknowledge */
-#define ATMEL_US_RETTO (1 << 15) /* Rearm Time-out */
-#define ATMEL_US_DTREN (1 << 16) /* Data Terminal Ready Enable [AT91RM9200 only] */
-#define ATMEL_US_DTRDIS (1 << 17) /* Data Terminal Ready Disable [AT91RM9200 only] */
-#define ATMEL_US_RTSEN (1 << 18) /* Request To Send Enable */
-#define ATMEL_US_RTSDIS (1 << 19) /* Request To Send Disable */
+#define ATMEL_US_CR 0x00 /* Control Register */
+#define ATMEL_US_RSTRX BIT(2) /* Reset Receiver */
+#define ATMEL_US_RSTTX BIT(3) /* Reset Transmitter */
+#define ATMEL_US_RXEN BIT(4) /* Receiver Enable */
+#define ATMEL_US_RXDIS BIT(5) /* Receiver Disable */
+#define ATMEL_US_TXEN BIT(6) /* Transmitter Enable */
+#define ATMEL_US_TXDIS BIT(7) /* Transmitter Disable */
+#define ATMEL_US_RSTSTA BIT(8) /* Reset Status Bits */
+#define ATMEL_US_STTBRK BIT(9) /* Start Break */
+#define ATMEL_US_STPBRK BIT(10) /* Stop Break */
+#define ATMEL_US_STTTO BIT(11) /* Start Time-out */
+#define ATMEL_US_SENDA BIT(12) /* Send Address */
+#define ATMEL_US_RSTIT BIT(13) /* Reset Iterations */
+#define ATMEL_US_RSTNACK BIT(14) /* Reset Non Acknowledge */
+#define ATMEL_US_RETTO BIT(15) /* Rearm Time-out */
+#define ATMEL_US_DTREN BIT(16) /* Data Terminal Ready Enable */
+#define ATMEL_US_DTRDIS BIT(17) /* Data Terminal Ready Disable */
+#define ATMEL_US_RTSEN BIT(18) /* Request To Send Enable */
+#define ATMEL_US_RTSDIS BIT(19) /* Request To Send Disable */
+#define ATMEL_US_TXFCLR BIT(24) /* Transmit FIFO Clear */
+#define ATMEL_US_RXFCLR BIT(25) /* Receive FIFO Clear */
+#define ATMEL_US_TXFLCLR BIT(26) /* Transmit FIFO Lock Clear */
+#define ATMEL_US_FIFOEN BIT(30) /* FIFO enable */
+#define ATMEL_US_FIFODIS BIT(31) /* FIFO disable */
-#define ATMEL_US_MR 0x04 /* Mode Register */
-#define ATMEL_US_USMODE (0xf << 0) /* Mode of the USART */
-#define ATMEL_US_USMODE_NORMAL 0
-#define ATMEL_US_USMODE_RS485 1
-#define ATMEL_US_USMODE_HWHS 2
-#define ATMEL_US_USMODE_MODEM 3
-#define ATMEL_US_USMODE_ISO7816_T0 4
-#define ATMEL_US_USMODE_ISO7816_T1 6
-#define ATMEL_US_USMODE_IRDA 8
-#define ATMEL_US_USCLKS (3 << 4) /* Clock Selection */
-#define ATMEL_US_USCLKS_MCK (0 << 4)
-#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
-#define ATMEL_US_USCLKS_SCK (3 << 4)
-#define ATMEL_US_CHRL (3 << 6) /* Character Length */
-#define ATMEL_US_CHRL_5 (0 << 6)
-#define ATMEL_US_CHRL_6 (1 << 6)
-#define ATMEL_US_CHRL_7 (2 << 6)
-#define ATMEL_US_CHRL_8 (3 << 6)
-#define ATMEL_US_SYNC (1 << 8) /* Synchronous Mode Select */
-#define ATMEL_US_PAR (7 << 9) /* Parity Type */
-#define ATMEL_US_PAR_EVEN (0 << 9)
-#define ATMEL_US_PAR_ODD (1 << 9)
-#define ATMEL_US_PAR_SPACE (2 << 9)
-#define ATMEL_US_PAR_MARK (3 << 9)
-#define ATMEL_US_PAR_NONE (4 << 9)
-#define ATMEL_US_PAR_MULTI_DROP (6 << 9)
-#define ATMEL_US_NBSTOP (3 << 12) /* Number of Stop Bits */
-#define ATMEL_US_NBSTOP_1 (0 << 12)
-#define ATMEL_US_NBSTOP_1_5 (1 << 12)
-#define ATMEL_US_NBSTOP_2 (2 << 12)
-#define ATMEL_US_CHMODE (3 << 14) /* Channel Mode */
-#define ATMEL_US_CHMODE_NORMAL (0 << 14)
-#define ATMEL_US_CHMODE_ECHO (1 << 14)
-#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14)
-#define ATMEL_US_CHMODE_REM_LOOP (3 << 14)
-#define ATMEL_US_MSBF (1 << 16) /* Bit Order */
-#define ATMEL_US_MODE9 (1 << 17) /* 9-bit Character Length */
-#define ATMEL_US_CLKO (1 << 18) /* Clock Output Select */
-#define ATMEL_US_OVER (1 << 19) /* Oversampling Mode */
-#define ATMEL_US_INACK (1 << 20) /* Inhibit Non Acknowledge */
-#define ATMEL_US_DSNACK (1 << 21) /* Disable Successive NACK */
-#define ATMEL_US_MAX_ITER (7 << 24) /* Max Iterations */
-#define ATMEL_US_FILTER (1 << 28) /* Infrared Receive Line Filter */
+#define ATMEL_US_MR 0x04 /* Mode Register */
+#define ATMEL_US_USMODE GENMASK(3, 0) /* Mode of the USART */
+#define ATMEL_US_USMODE_NORMAL 0
+#define ATMEL_US_USMODE_RS485 1
+#define ATMEL_US_USMODE_HWHS 2
+#define ATMEL_US_USMODE_MODEM 3
+#define ATMEL_US_USMODE_ISO7816_T0 4
+#define ATMEL_US_USMODE_ISO7816_T1 6
+#define ATMEL_US_USMODE_IRDA 8
+#define ATMEL_US_USCLKS GENMASK(5, 4) /* Clock Selection */
+#define ATMEL_US_USCLKS_MCK (0 << 4)
+#define ATMEL_US_USCLKS_MCK_DIV8 (1 << 4)
+#define ATMEL_US_USCLKS_SCK (3 << 4)
+#define ATMEL_US_CHRL GENMASK(7, 6) /* Character Length */
+#define ATMEL_US_CHRL_5 (0 << 6)
+#define ATMEL_US_CHRL_6 (1 << 6)
+#define ATMEL_US_CHRL_7 (2 << 6)
+#define ATMEL_US_CHRL_8 (3 << 6)
+#define ATMEL_US_SYNC BIT(8) /* Synchronous Mode Select */
+#define ATMEL_US_PAR GENMASK(11, 9) /* Parity Type */
+#define ATMEL_US_PAR_EVEN (0 << 9)
+#define ATMEL_US_PAR_ODD (1 << 9)
+#define ATMEL_US_PAR_SPACE (2 << 9)
+#define ATMEL_US_PAR_MARK (3 << 9)
+#define ATMEL_US_PAR_NONE (4 << 9)
+#define ATMEL_US_PAR_MULTI_DROP (6 << 9)
+#define ATMEL_US_NBSTOP GENMASK(13, 12) /* Number of Stop Bits */
+#define ATMEL_US_NBSTOP_1 (0 << 12)
+#define ATMEL_US_NBSTOP_1_5 (1 << 12)
+#define ATMEL_US_NBSTOP_2 (2 << 12)
+#define ATMEL_US_CHMODE GENMASK(15, 14) /* Channel Mode */
+#define ATMEL_US_CHMODE_NORMAL (0 << 14)
+#define ATMEL_US_CHMODE_ECHO (1 << 14)
+#define ATMEL_US_CHMODE_LOC_LOOP (2 << 14)
+#define ATMEL_US_CHMODE_REM_LOOP (3 << 14)
+#define ATMEL_US_MSBF BIT(16) /* Bit Order */
+#define ATMEL_US_MODE9 BIT(17) /* 9-bit Character Length */
+#define ATMEL_US_CLKO BIT(18) /* Clock Output Select */
+#define ATMEL_US_OVER BIT(19) /* Oversampling Mode */
+#define ATMEL_US_INACK BIT(20) /* Inhibit Non Acknowledge */
+#define ATMEL_US_DSNACK BIT(21) /* Disable Successive NACK */
+#define ATMEL_US_MAX_ITER GENMASK(26, 24) /* Max Iterations */
+#define ATMEL_US_FILTER BIT(28) /* Infrared Receive Line Filter */
-#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */
-#define ATMEL_US_RXRDY (1 << 0) /* Receiver Ready */
-#define ATMEL_US_TXRDY (1 << 1) /* Transmitter Ready */
-#define ATMEL_US_RXBRK (1 << 2) /* Break Received / End of Break */
-#define ATMEL_US_ENDRX (1 << 3) /* End of Receiver Transfer */
-#define ATMEL_US_ENDTX (1 << 4) /* End of Transmitter Transfer */
-#define ATMEL_US_OVRE (1 << 5) /* Overrun Error */
-#define ATMEL_US_FRAME (1 << 6) /* Framing Error */
-#define ATMEL_US_PARE (1 << 7) /* Parity Error */
-#define ATMEL_US_TIMEOUT (1 << 8) /* Receiver Time-out */
-#define ATMEL_US_TXEMPTY (1 << 9) /* Transmitter Empty */
-#define ATMEL_US_ITERATION (1 << 10) /* Max number of Repetitions Reached */
-#define ATMEL_US_TXBUFE (1 << 11) /* Transmission Buffer Empty */
-#define ATMEL_US_RXBUFF (1 << 12) /* Reception Buffer Full */
-#define ATMEL_US_NACK (1 << 13) /* Non Acknowledge */
-#define ATMEL_US_RIIC (1 << 16) /* Ring Indicator Input Change [AT91RM9200 only] */
-#define ATMEL_US_DSRIC (1 << 17) /* Data Set Ready Input Change [AT91RM9200 only] */
-#define ATMEL_US_DCDIC (1 << 18) /* Data Carrier Detect Input Change [AT91RM9200 only] */
-#define ATMEL_US_CTSIC (1 << 19) /* Clear to Send Input Change */
-#define ATMEL_US_RI (1 << 20) /* RI */
-#define ATMEL_US_DSR (1 << 21) /* DSR */
-#define ATMEL_US_DCD (1 << 22) /* DCD */
-#define ATMEL_US_CTS (1 << 23) /* CTS */
+#define ATMEL_US_IER 0x08 /* Interrupt Enable Register */
+#define ATMEL_US_RXRDY BIT(0) /* Receiver Ready */
+#define ATMEL_US_TXRDY BIT(1) /* Transmitter Ready */
+#define ATMEL_US_RXBRK BIT(2) /* Break Received / End of Break */
+#define ATMEL_US_ENDRX BIT(3) /* End of Receiver Transfer */
+#define ATMEL_US_ENDTX BIT(4) /* End of Transmitter Transfer */
+#define ATMEL_US_OVRE BIT(5) /* Overrun Error */
+#define ATMEL_US_FRAME BIT(6) /* Framing Error */
+#define ATMEL_US_PARE BIT(7) /* Parity Error */
+#define ATMEL_US_TIMEOUT BIT(8) /* Receiver Time-out */
+#define ATMEL_US_TXEMPTY BIT(9) /* Transmitter Empty */
+#define ATMEL_US_ITERATION BIT(10) /* Max number of Repetitions Reached */
+#define ATMEL_US_TXBUFE BIT(11) /* Transmission Buffer Empty */
+#define ATMEL_US_RXBUFF BIT(12) /* Reception Buffer Full */
+#define ATMEL_US_NACK BIT(13) /* Non Acknowledge */
+#define ATMEL_US_RIIC BIT(16) /* Ring Indicator Input Change */
+#define ATMEL_US_DSRIC BIT(17) /* Data Set Ready Input Change */
+#define ATMEL_US_DCDIC BIT(18) /* Data Carrier Detect Input Change */
+#define ATMEL_US_CTSIC BIT(19) /* Clear to Send Input Change */
+#define ATMEL_US_RI BIT(20) /* RI */
+#define ATMEL_US_DSR BIT(21) /* DSR */
+#define ATMEL_US_DCD BIT(22) /* DCD */
+#define ATMEL_US_CTS BIT(23) /* CTS */
-#define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */
-#define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */
-#define ATMEL_US_CSR 0x14 /* Channel Status Register */
-#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */
-#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */
-#define ATMEL_US_SYNH (1 << 15) /* Transmit/Receive Sync [AT91SAM9261 only] */
+#define ATMEL_US_IDR 0x0c /* Interrupt Disable Register */
+#define ATMEL_US_IMR 0x10 /* Interrupt Mask Register */
+#define ATMEL_US_CSR 0x14 /* Channel Status Register */
+#define ATMEL_US_RHR 0x18 /* Receiver Holding Register */
+#define ATMEL_US_THR 0x1c /* Transmitter Holding Register */
+#define ATMEL_US_SYNH BIT(15) /* Transmit/Receive Sync */
-#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */
-#define ATMEL_US_CD (0xffff << 0) /* Clock Divider */
+#define ATMEL_US_BRGR 0x20 /* Baud Rate Generator Register */
+#define ATMEL_US_CD GENMASK(15, 0) /* Clock Divider */
-#define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register */
-#define ATMEL_US_TO (0xffff << 0) /* Time-out Value */
+#define ATMEL_US_RTOR 0x24 /* Receiver Time-out Register */
+#define ATMEL_US_TO GENMASK(15, 0) /* Time-out Value */
-#define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */
-#define ATMEL_US_TG (0xff << 0) /* Timeguard Value */
+#define ATMEL_US_TTGR 0x28 /* Transmitter Timeguard Register */
+#define ATMEL_US_TG GENMASK(7, 0) /* Timeguard Value */
-#define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */
-#define ATMEL_US_NER 0x44 /* Number of Errors Register */
-#define ATMEL_US_IF 0x4c /* IrDA Filter Register */
+#define ATMEL_US_FIDI 0x40 /* FI DI Ratio Register */
+#define ATMEL_US_NER 0x44 /* Number of Errors Register */
+#define ATMEL_US_IF 0x4c /* IrDA Filter Register */
-#define ATMEL_US_NAME 0xf0 /* Ip Name */
-#define ATMEL_US_VERSION 0xfc /* Ip Version */
+#define ATMEL_US_CMPR 0x90 /* Comparaison Register */
+#define ATMEL_US_FMR 0xa0 /* FIFO Mode Register */
+#define ATMEL_US_TXRDYM(data) (((data) & 0x3) << 0) /* TX Ready Mode */
+#define ATMEL_US_RXRDYM(data) (((data) & 0x3) << 4) /* RX Ready Mode */
+#define ATMEL_US_ONE_DATA 0x0
+#define ATMEL_US_TWO_DATA 0x1
+#define ATMEL_US_FOUR_DATA 0x2
+#define ATMEL_US_FRTSC BIT(7) /* FIFO RTS pin Control */
+#define ATMEL_US_TXFTHRES(thr) (((thr) & 0x3f) << 8) /* TX FIFO Threshold */
+#define ATMEL_US_RXFTHRES(thr) (((thr) & 0x3f) << 16) /* RX FIFO Threshold */
+#define ATMEL_US_RXFTHRES2(thr) (((thr) & 0x3f) << 24) /* RX FIFO Threshold2 */
+
+#define ATMEL_US_FLR 0xa4 /* FIFO Level Register */
+#define ATMEL_US_TXFL(reg) (((reg) >> 0) & 0x3f) /* TX FIFO Level */
+#define ATMEL_US_RXFL(reg) (((reg) >> 16) & 0x3f) /* RX FIFO Level */
+
+#define ATMEL_US_FIER 0xa8 /* FIFO Interrupt Enable Register */
+#define ATMEL_US_FIDR 0xac /* FIFO Interrupt Disable Register */
+#define ATMEL_US_FIMR 0xb0 /* FIFO Interrupt Mask Register */
+#define ATMEL_US_FESR 0xb4 /* FIFO Event Status Register */
+#define ATMEL_US_TXFEF BIT(0) /* Transmit FIFO Empty Flag */
+#define ATMEL_US_TXFFF BIT(1) /* Transmit FIFO Full Flag */
+#define ATMEL_US_TXFTHF BIT(2) /* Transmit FIFO Threshold Flag */
+#define ATMEL_US_RXFEF BIT(3) /* Receive FIFO Empty Flag */
+#define ATMEL_US_RXFFF BIT(4) /* Receive FIFO Full Flag */
+#define ATMEL_US_RXFTHF BIT(5) /* Receive FIFO Threshold Flag */
+#define ATMEL_US_TXFPTEF BIT(6) /* Transmit FIFO Pointer Error Flag */
+#define ATMEL_US_RXFPTEF BIT(7) /* Receive FIFO Pointer Error Flag */
+#define ATMEL_US_TXFLOCK BIT(8) /* Transmit FIFO Lock (FESR only) */
+#define ATMEL_US_RXFTHF2 BIT(9) /* Receive FIFO Threshold Flag 2 */
+
+#define ATMEL_US_NAME 0xf0 /* Ip Name */
+#define ATMEL_US_VERSION 0xfc /* Ip Version */
#endif
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index 3486b908..c69e1b9 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -14,6 +14,7 @@
#define _LINUX_CORESIGHT_H
#include <linux/device.h>
+#include <linux/sched.h>
/* Peripheral id registers (0xFD0-0xFEC) */
#define CORESIGHT_PERIPHIDR4 0xfd0
@@ -248,4 +249,24 @@
struct device *dev, struct device_node *node) { return NULL; }
#endif
+#ifdef CONFIG_PID_NS
+static inline unsigned long
+coresight_vpid_to_pid(unsigned long vpid)
+{
+ struct task_struct *task = NULL;
+ unsigned long pid = 0;
+
+ rcu_read_lock();
+ task = find_task_by_vpid(vpid);
+ if (task)
+ pid = task_pid_nr(task);
+ rcu_read_unlock();
+
+ return pid;
+}
+#else
+static inline unsigned long
+coresight_vpid_to_pid(unsigned long vpid) { return vpid; }
+#endif
+
#endif
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 76abba4..dcacb1a 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -340,7 +340,27 @@
__u64 mm_reg_addr;
};
-/* Memory Error Section */
+/* Old Memory Error Section UEFI 2.1, 2.2 */
+struct cper_sec_mem_err_old {
+ __u64 validation_bits;
+ __u64 error_status;
+ __u64 physical_addr;
+ __u64 physical_addr_mask;
+ __u16 node;
+ __u16 card;
+ __u16 module;
+ __u16 bank;
+ __u16 device;
+ __u16 row;
+ __u16 column;
+ __u16 bit_pos;
+ __u64 requestor_id;
+ __u64 responder_id;
+ __u64 target_id;
+ __u8 error_type;
+};
+
+/* Memory Error Section UEFI >= 2.3 */
struct cper_sec_mem_err {
__u64 validation_bits;
__u64 error_status;
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 29ad97c..bde1e56 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -62,6 +62,7 @@
/* CPUs sharing clock, require sw coordination */
cpumask_var_t cpus; /* Online CPUs only */
cpumask_var_t related_cpus; /* Online + Offline CPUs */
+ cpumask_var_t real_cpus; /* Related and present */
unsigned int shared_type; /* ACPI: ANY or ALL affected CPUs
should set cpufreq */
diff --git a/include/linux/device.h b/include/linux/device.h
index a2b4ea7..1225f98 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -341,7 +341,7 @@
struct bus_type *subsys;
struct list_head node;
int (*add_dev)(struct device *dev, struct subsys_interface *sif);
- int (*remove_dev)(struct device *dev, struct subsys_interface *sif);
+ void (*remove_dev)(struct device *dev, struct subsys_interface *sif);
};
int subsys_interface_register(struct subsys_interface *sif);
diff --git a/include/linux/extcon.h b/include/linux/extcon.h
index b16d929..c0f8c4f 100644
--- a/include/linux/extcon.h
+++ b/include/linux/extcon.h
@@ -27,8 +27,6 @@
#define __LINUX_EXTCON_H__
#include <linux/device.h>
-#include <linux/notifier.h>
-#include <linux/sysfs.h>
/*
* Define the unique id of supported external connectors
@@ -77,8 +75,6 @@
* be attached simulataneously. {0x7, 0} is equivalent to
* {0x3, 0x6, 0x5, 0}. If it is {0xFFFFFFFF, 0}, there
* can be no simultaneous connections.
- * @print_state: An optional callback to override the method to print the
- * status of the extcon device.
* @dev: Device of this extcon.
* @state: Attach/detach state of this extcon. Do not provide at
* register-time.
@@ -102,9 +98,6 @@
const unsigned int *supported_cable;
const u32 *mutually_exclusive;
- /* Optional callbacks to override class functions */
- ssize_t (*print_state)(struct extcon_dev *edev, char *buf);
-
/* Internal data. Please do not set. */
struct device dev;
struct raw_notifier_head *nh;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index cc008c3..84b783f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -55,7 +55,8 @@
extern void __init inode_init(void);
extern void __init inode_init_early(void);
-extern void __init files_init(unsigned long);
+extern void __init files_init(void);
+extern void __init files_maxfiles_init(void);
extern struct files_stat_struct files_stat;
extern unsigned long get_max_files(void);
@@ -2245,7 +2246,7 @@
/* fs/dcache.c */
extern void __init vfs_caches_init_early(void);
-extern void __init vfs_caches_init(unsigned long);
+extern void __init vfs_caches_init(void);
extern struct kmem_cache *names_cachep;
diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h
index 2a2f56b..f291291 100644
--- a/include/linux/fsl_devices.h
+++ b/include/linux/fsl_devices.h
@@ -20,11 +20,6 @@
#define FSL_UTMI_PHY_DLY 10 /*As per P1010RM, delay for UTMI
PHY CLK to become stable - 10ms*/
#define FSL_USB_PHY_CLK_TIMEOUT 10000 /* uSec */
-#define FSL_USB_VER_OLD 0
-#define FSL_USB_VER_1_6 1
-#define FSL_USB_VER_2_2 2
-#define FSL_USB_VER_2_4 3
-#define FSL_USB_VER_2_5 4
#include <linux/types.h>
@@ -52,6 +47,15 @@
*
*/
+enum fsl_usb2_controller_ver {
+ FSL_USB_VER_NONE = -1,
+ FSL_USB_VER_OLD = 0,
+ FSL_USB_VER_1_6 = 1,
+ FSL_USB_VER_2_2 = 2,
+ FSL_USB_VER_2_4 = 3,
+ FSL_USB_VER_2_5 = 4,
+};
+
enum fsl_usb2_operating_modes {
FSL_USB2_MPH_HOST,
FSL_USB2_DR_HOST,
@@ -65,6 +69,7 @@
FSL_USB2_PHY_UTMI,
FSL_USB2_PHY_UTMI_WIDE,
FSL_USB2_PHY_SERIAL,
+ FSL_USB2_PHY_UTMI_DUAL,
};
struct clk;
@@ -72,7 +77,7 @@
struct fsl_usb2_platform_data {
/* board specific information */
- int controller_ver;
+ enum fsl_usb2_controller_ver controller_ver;
enum fsl_usb2_operating_modes operating_mode;
enum fsl_usb2_phy_modes phy_mode;
unsigned int port_enables;
@@ -93,6 +98,9 @@
unsigned suspended:1;
unsigned already_suspended:1;
+ unsigned has_fsl_erratum_a007792:1;
+ unsigned has_fsl_erratum_a005275:1;
+ unsigned check_phy_clk_valid:1;
/* register save area for suspend/resume */
u32 pm_command;
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index 1da6029..6cd8c0e 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -116,6 +116,7 @@
* SAVE_REGS. If another ops with this flag set is already registered
* for any of the functions that this ops will be registered for, then
* this ops will fail to register or set_filter_ip.
+ * PID - Is affected by set_ftrace_pid (allows filtering on those pids)
*/
enum {
FTRACE_OPS_FL_ENABLED = 1 << 0,
@@ -132,6 +133,7 @@
FTRACE_OPS_FL_MODIFYING = 1 << 11,
FTRACE_OPS_FL_ALLOC_TRAMP = 1 << 12,
FTRACE_OPS_FL_IPMODIFY = 1 << 13,
+ FTRACE_OPS_FL_PID = 1 << 14,
};
#ifdef CONFIG_DYNAMIC_FTRACE
@@ -159,6 +161,7 @@
struct ftrace_ops *next;
unsigned long flags;
void *private;
+ ftrace_func_t saved_func;
int __percpu *disabled;
#ifdef CONFIG_DYNAMIC_FTRACE
int nr_trampolines;
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 30d3a1f..54733d5 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -977,6 +977,11 @@
const char *mod_name);
void vmbus_driver_unregister(struct hv_driver *hv_driver);
+int vmbus_allocate_mmio(struct resource **new, struct hv_device *device_obj,
+ resource_size_t min, resource_size_t max,
+ resource_size_t size, resource_size_t align,
+ bool fb_overlap_ok);
+
/**
* VMBUS_DEVICE - macro used to describe a specific hyperv vmbus device
*
@@ -1233,8 +1238,6 @@
void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid);
-extern struct resource hyperv_mmio;
-
/*
* Negotiated version with the Host.
*/
diff --git a/include/linux/iio/common/st_sensors.h b/include/linux/iio/common/st_sensors.h
index 2c476ac..3c17cd7 100644
--- a/include/linux/iio/common/st_sensors.h
+++ b/include/linux/iio/common/st_sensors.h
@@ -166,6 +166,7 @@
/**
* struct st_sensor_settings - ST specific sensor settings
* @wai: Contents of WhoAmI register.
+ * @wai_addr: The address of WhoAmI register.
* @sensors_supported: List of supported sensors by struct itself.
* @ch: IIO channels for the sensor.
* @odr: Output data rate register and ODR list available.
@@ -179,6 +180,7 @@
*/
struct st_sensor_settings {
u8 wai;
+ u8 wai_addr;
char sensors_supported[ST_SENSORS_MAX_4WAI][ST_SENSORS_MAX_NAME];
struct iio_chan_spec *ch;
int num_ch;
diff --git a/include/linux/iio/consumer.h b/include/linux/iio/consumer.h
index 26fb8f6..fad5867 100644
--- a/include/linux/iio/consumer.h
+++ b/include/linux/iio/consumer.h
@@ -100,7 +100,7 @@
/**
* iio_channel_cb_get_channels() - get access to the underlying channels.
- * @cb_buff: The callback buffer from whom we want the channel
+ * @cb_buffer: The callback buffer from whom we want the channel
* information.
*
* This function allows one to obtain information about the channels.
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index f791482..7bb7f67 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -645,6 +645,15 @@
#define IIO_DEGREE_TO_RAD(deg) (((deg) * 314159ULL + 9000000ULL) / 18000000ULL)
/**
+ * IIO_RAD_TO_DEGREE() - Convert rad to degree
+ * @rad: A value in rad
+ *
+ * Returns the given value converted from rad to degree
+ */
+#define IIO_RAD_TO_DEGREE(rad) \
+ (((rad) * 18000000ULL + 314159ULL / 2) / 314159ULL)
+
+/**
* IIO_G_TO_M_S_2() - Convert g to meter / second**2
* @g: A value in g
*
@@ -652,4 +661,12 @@
*/
#define IIO_G_TO_M_S_2(g) ((g) * 980665ULL / 100000ULL)
+/**
+ * IIO_M_S_2_TO_G() - Convert meter / second**2 to g
+ * @ms2: A value in meter / second**2
+ *
+ * Returns the given value converted from meter / second**2 to g
+ */
+#define IIO_M_S_2_TO_G(ms2) (((ms2) * 100000ULL + 980665ULL / 2) / 980665ULL)
+
#endif /* _INDUSTRIAL_IO_H_ */
diff --git a/include/linux/iio/sysfs.h b/include/linux/iio/sysfs.h
index 8a1d186..9cd8f74 100644
--- a/include/linux/iio/sysfs.h
+++ b/include/linux/iio/sysfs.h
@@ -18,7 +18,8 @@
* struct iio_dev_attr - iio specific device attribute
* @dev_attr: underlying device attribute
* @address: associated register address
- * @l: list head for maintaining list of dynamically created attrs.
+ * @l: list head for maintaining list of dynamically created attrs
+ * @c: specification for the underlying channel
*/
struct iio_dev_attr {
struct device_attribute dev_attr;
diff --git a/include/linux/iio/trigger.h b/include/linux/iio/trigger.h
index fa76c79..1c9e028 100644
--- a/include/linux/iio/trigger.h
+++ b/include/linux/iio/trigger.h
@@ -18,6 +18,9 @@
bool enabled;
};
+struct iio_dev;
+struct iio_trigger;
+
/**
* struct iio_trigger_ops - operations structure for an iio_trigger.
* @owner: used to monitor usage count of the trigger.
diff --git a/include/linux/iio/triggered_buffer.h b/include/linux/iio/triggered_buffer.h
index c378ebe..f72f70d 100644
--- a/include/linux/iio/triggered_buffer.h
+++ b/include/linux/iio/triggered_buffer.h
@@ -7,8 +7,8 @@
struct iio_buffer_setup_ops;
int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
- irqreturn_t (*pollfunc_bh)(int irq, void *p),
- irqreturn_t (*pollfunc_th)(int irq, void *p),
+ irqreturn_t (*h)(int irq, void *p),
+ irqreturn_t (*thread)(int irq, void *p),
const struct iio_buffer_setup_ops *setup_ops);
void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev);
diff --git a/include/linux/irq.h b/include/linux/irq.h
index 92188b0..51744bc 100644
--- a/include/linux/irq.h
+++ b/include/linux/irq.h
@@ -484,6 +484,7 @@
extern int irq_chip_set_wake_parent(struct irq_data *data, unsigned int on);
extern int irq_chip_set_vcpu_affinity_parent(struct irq_data *data,
void *vcpu_info);
+extern int irq_chip_set_type_parent(struct irq_data *data, unsigned int type);
#endif
/* Handling of unhandled and spurious interrupts: */
diff --git a/include/linux/kexec.h b/include/linux/kexec.h
index e804306..b63218f 100644
--- a/include/linux/kexec.h
+++ b/include/linux/kexec.h
@@ -323,6 +323,7 @@
struct task_struct;
static inline void crash_kexec(struct pt_regs *regs) { }
static inline int kexec_should_crash(struct task_struct *p) { return 0; }
+#define kexec_in_progress false
#endif /* CONFIG_KEXEC */
#endif /* !defined(__ASSEBMLY__) */
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 05e99b8..81089cf 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -139,6 +139,7 @@
#define KVM_REQ_DISABLE_IBS 24
#define KVM_REQ_APIC_PAGE_RELOAD 25
#define KVM_REQ_SMI 26
+#define KVM_REQ_HV_CRASH 27
#define KVM_USERSPACE_IRQ_SOURCE_ID 0
#define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1
@@ -363,9 +364,6 @@
struct kvm_memslots *memslots[KVM_ADDRESS_SPACE_NUM];
struct srcu_struct srcu;
struct srcu_struct irq_srcu;
-#ifdef CONFIG_KVM_APIC_ARCHITECTURE
- u32 bsp_vcpu_id;
-#endif
struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
atomic_t online_vcpus;
int last_boosted_vcpu;
@@ -424,8 +422,15 @@
#define vcpu_unimpl(vcpu, fmt, ...) \
kvm_pr_unimpl("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__)
+#define vcpu_debug(vcpu, fmt, ...) \
+ kvm_debug("vcpu%i " fmt, (vcpu)->vcpu_id, ## __VA_ARGS__)
+
static inline struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i)
{
+ /* Pairs with smp_wmb() in kvm_vm_ioctl_create_vcpu, in case
+ * the caller has read kvm->online_vcpus before (as is the case
+ * for kvm_for_each_vcpu, for example).
+ */
smp_rmb();
return kvm->vcpus[i];
}
@@ -1055,22 +1060,9 @@
#endif /* CONFIG_HAVE_KVM_EVENTFD */
#ifdef CONFIG_KVM_APIC_ARCHITECTURE
-static inline bool kvm_vcpu_is_reset_bsp(struct kvm_vcpu *vcpu)
-{
- return vcpu->kvm->bsp_vcpu_id == vcpu->vcpu_id;
-}
-
-static inline bool kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu)
-{
- return (vcpu->arch.apic_base & MSR_IA32_APICBASE_BSP) != 0;
-}
-
bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu);
-
#else
-
static inline bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu) { return true; }
-
#endif
static inline void kvm_make_request(int req, struct kvm_vcpu *vcpu)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 36ce37b..c9cfbcd 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -431,6 +431,8 @@
ATA_HORKAGE_WD_BROKEN_LPM = (1 << 21), /* some WDs have broken LPM */
ATA_HORKAGE_ZERO_AFTER_TRIM = (1 << 22),/* guarantees zero after trim */
ATA_HORKAGE_NO_NCQ_LOG = (1 << 23), /* don't use NCQ for log read */
+ ATA_HORKAGE_NOTRIM = (1 << 24), /* don't use TRIM */
+ ATA_HORKAGE_MAX_SEC_1024 = (1 << 25), /* Limit max sects to 1024 */
/* DMA mask for user DMA control: User visible values; DO NOT
renumber */
diff --git a/include/linux/mei_cl_bus.h b/include/linux/mei_cl_bus.h
index a16b1f9..0962b2c 100644
--- a/include/linux/mei_cl_bus.h
+++ b/include/linux/mei_cl_bus.h
@@ -6,6 +6,7 @@
#include <linux/mod_devicetable.h>
struct mei_cl_device;
+struct mei_device;
typedef void (*mei_cl_event_cb_t)(struct mei_cl_device *device,
u32 events, void *context);
@@ -17,6 +18,8 @@
* Drivers for MEI devices will get an mei_cl_device pointer
* when being probed and shall use it for doing ME bus I/O.
*
+ * @bus_list: device on the bus list
+ * @bus: parent mei device
* @dev: linux driver model device pointer
* @me_cl: me client
* @cl: mei client
@@ -25,10 +28,16 @@
* @event_cb: Drivers register this callback to get asynchronous ME
* events (e.g. Rx buffer pending) notifications.
* @event_context: event callback run context
+ * @events_mask: Events bit mask requested by driver.
* @events: Events bitmask sent to the driver.
+ *
+ * @do_match: wheather device can be matched with a driver
+ * @is_added: device is already scanned
* @priv_data: client private data
*/
struct mei_cl_device {
+ struct list_head bus_list;
+ struct mei_device *bus;
struct device dev;
struct mei_me_client *me_cl;
@@ -38,8 +47,12 @@
struct work_struct event_work;
mei_cl_event_cb_t event_cb;
void *event_context;
+ unsigned long events_mask;
unsigned long events;
+ unsigned int do_match:1;
+ unsigned int is_added:1;
+
void *priv_data;
};
@@ -65,10 +78,12 @@
ssize_t mei_cl_recv(struct mei_cl_device *device, u8 *buf, size_t length);
int mei_cl_register_event_cb(struct mei_cl_device *device,
+ unsigned long event_mask,
mei_cl_event_cb_t read_cb, void *context);
#define MEI_CL_EVENT_RX 0
#define MEI_CL_EVENT_TX 1
+#define MEI_CL_EVENT_NOTIF 2
void *mei_cl_get_drvdata(const struct mei_cl_device *device);
void mei_cl_set_drvdata(struct mei_cl_device *device, void *data);
diff --git a/include/linux/mfd/palmas.h b/include/linux/mfd/palmas.h
index bb270bd..13e1d96 100644
--- a/include/linux/mfd/palmas.h
+++ b/include/linux/mfd/palmas.h
@@ -21,6 +21,7 @@
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/extcon.h>
+#include <linux/of_gpio.h>
#include <linux/usb/phy_companion.h>
#define PALMAS_NUM_CLIENTS 3
@@ -551,10 +552,16 @@
int vbus_otg_irq;
int vbus_irq;
+ int gpio_id_irq;
+ struct gpio_desc *id_gpiod;
+ unsigned long sw_debounce_jiffies;
+ struct delayed_work wq_detectid;
+
enum palmas_usb_state linkstat;
int wakeup;
bool enable_vbus_detection;
bool enable_id_detection;
+ bool enable_gpio_id_detection;
};
#define comparator_to_palmas(x) container_of((x), struct palmas_usb, comparator)
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h
index 819077c..81f6e42 100644
--- a/include/linux/miscdevice.h
+++ b/include/linux/miscdevice.h
@@ -67,7 +67,7 @@
};
extern int misc_register(struct miscdevice *misc);
-extern int misc_deregister(struct miscdevice *misc);
+extern void misc_deregister(struct miscdevice *misc);
#define MODULE_ALIAS_MISCDEV(minor) \
MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR) \
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 2e872f9..bf6f117 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1003,6 +1003,34 @@
}
/*
+ * Return true only if the page has been allocated with
+ * ALLOC_NO_WATERMARKS and the low watermark was not
+ * met implying that the system is under some pressure.
+ */
+static inline bool page_is_pfmemalloc(struct page *page)
+{
+ /*
+ * Page index cannot be this large so this must be
+ * a pfmemalloc page.
+ */
+ return page->index == -1UL;
+}
+
+/*
+ * Only to be called by the page allocator on a freshly allocated
+ * page.
+ */
+static inline void set_page_pfmemalloc(struct page *page)
+{
+ page->index = -1UL;
+}
+
+static inline void clear_page_pfmemalloc(struct page *page)
+{
+ page->index = 0;
+}
+
+/*
* Different kinds of faults, as returned by handle_mm_fault().
* Used to decide whether a process gets delivered SIGBUS or
* just gets major/minor fault counters bumped up.
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 0038ac7..1554957 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -63,15 +63,6 @@
union {
pgoff_t index; /* Our offset within mapping. */
void *freelist; /* sl[aou]b first free object */
- bool pfmemalloc; /* If set by the page allocator,
- * ALLOC_NO_WATERMARKS was set
- * and the low watermark was not
- * met implying that the system
- * is under some pressure. The
- * caller should try ensure
- * this page is only used to
- * free other pages.
- */
};
union {
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index f25e2bd..272f429 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -178,17 +178,17 @@
/* Chip may not exist, so silence any errors in scan */
#define NAND_SCAN_SILENT_NODEV 0x00040000
/*
- * This option could be defined by controller drivers to protect against
- * kmap'ed, vmalloc'ed highmem buffers being passed from upper layers
- */
-#define NAND_USE_BOUNCE_BUFFER 0x00080000
-/*
* Autodetect nand buswidth with readid/onfi.
* This suppose the driver will configure the hardware in 8 bits mode
* when calling nand_scan_ident, and update its configuration
* before calling nand_scan_tail.
*/
#define NAND_BUSWIDTH_AUTO 0x00080000
+/*
+ * This option could be defined by controller drivers to protect against
+ * kmap'ed, vmalloc'ed highmem buffers being passed from upper layers
+ */
+#define NAND_USE_BOUNCE_BUFFER 0x00100000
/* Options set by nand scan */
/* Nand scan has allocated controller struct */
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index f91b5ad..874b772 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -292,9 +292,12 @@
struct nfs_inode *nfsi = NFS_I(inode);
spin_lock(&inode->i_lock);
- nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+ nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
+ NFS_INO_REVAL_PAGECACHE |
+ NFS_INO_INVALID_ACCESS |
+ NFS_INO_INVALID_ACL;
if (S_ISDIR(inode->i_mode))
- nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE|NFS_INO_INVALID_DATA;
+ nfsi->cache_validity |= NFS_INO_INVALID_DATA;
spin_unlock(&inode->i_lock);
}
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
index a2ea149..20bc8e5 100644
--- a/include/linux/nfs_fs_sb.h
+++ b/include/linux/nfs_fs_sb.h
@@ -220,7 +220,7 @@
#define NFS_CAP_SYMLINKS (1U << 2)
#define NFS_CAP_ACLS (1U << 3)
#define NFS_CAP_ATOMIC_OPEN (1U << 4)
-#define NFS_CAP_CHANGE_ATTR (1U << 5)
+/* #define NFS_CAP_CHANGE_ATTR (1U << 5) */
#define NFS_CAP_FILEID (1U << 6)
#define NFS_CAP_MODE (1U << 7)
#define NFS_CAP_NLINK (1U << 8)
diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h
new file mode 100644
index 0000000..9bb77d3
--- /dev/null
+++ b/include/linux/nvmem-consumer.h
@@ -0,0 +1,157 @@
+/*
+ * nvmem framework consumer.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.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.
+ */
+
+#ifndef _LINUX_NVMEM_CONSUMER_H
+#define _LINUX_NVMEM_CONSUMER_H
+
+struct device;
+struct device_node;
+/* consumer cookie */
+struct nvmem_cell;
+struct nvmem_device;
+
+struct nvmem_cell_info {
+ const char *name;
+ unsigned int offset;
+ unsigned int bytes;
+ unsigned int bit_offset;
+ unsigned int nbits;
+};
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+/* Cell based interface */
+struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name);
+struct nvmem_cell *devm_nvmem_cell_get(struct device *dev, const char *name);
+void nvmem_cell_put(struct nvmem_cell *cell);
+void devm_nvmem_cell_put(struct device *dev, struct nvmem_cell *cell);
+void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len);
+int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len);
+
+/* direct nvmem device read/write interface */
+struct nvmem_device *nvmem_device_get(struct device *dev, const char *name);
+struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+ const char *name);
+void nvmem_device_put(struct nvmem_device *nvmem);
+void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem);
+int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset,
+ size_t bytes, void *buf);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+ size_t bytes, void *buf);
+ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf);
+int nvmem_device_cell_write(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info, void *buf);
+
+#else
+
+static inline struct nvmem_cell *nvmem_cell_get(struct device *dev,
+ const char *name)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_cell *devm_nvmem_cell_get(struct device *dev,
+ const char *name)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void devm_nvmem_cell_put(struct device *dev,
+ struct nvmem_cell *cell)
+{
+
+}
+static inline void nvmem_cell_put(struct nvmem_cell *cell)
+{
+}
+
+static inline char *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_cell_write(struct nvmem_cell *cell,
+ const char *buf, size_t len)
+{
+ return -ENOSYS;
+}
+
+static inline struct nvmem_device *nvmem_device_get(struct device *dev,
+ const char *name)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_device *devm_nvmem_device_get(struct device *dev,
+ const char *name)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void nvmem_device_put(struct nvmem_device *nvmem)
+{
+}
+
+static inline void devm_nvmem_device_put(struct device *dev,
+ struct nvmem_device *nvmem)
+{
+}
+
+static inline ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info,
+ void *buf)
+{
+ return -ENOSYS;
+}
+
+static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info,
+ void *buf)
+{
+ return -ENOSYS;
+}
+
+static inline int nvmem_device_read(struct nvmem_device *nvmem,
+ unsigned int offset, size_t bytes,
+ void *buf)
+{
+ return -ENOSYS;
+}
+
+static inline int nvmem_device_write(struct nvmem_device *nvmem,
+ unsigned int offset, size_t bytes,
+ void *buf)
+{
+ return -ENOSYS;
+}
+#endif /* CONFIG_NVMEM */
+
+#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OF)
+struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+ const char *name);
+struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+ const char *name);
+#else
+static inline struct nvmem_cell *of_nvmem_cell_get(struct device_node *np,
+ const char *name)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct nvmem_device *of_nvmem_device_get(struct device_node *np,
+ const char *name)
+{
+ return ERR_PTR(-ENOSYS);
+}
+#endif /* CONFIG_NVMEM && CONFIG_OF */
+
+#endif /* ifndef _LINUX_NVMEM_CONSUMER_H */
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
new file mode 100644
index 0000000..0b68caf
--- /dev/null
+++ b/include/linux/nvmem-provider.h
@@ -0,0 +1,47 @@
+/*
+ * nvmem framework provider.
+ *
+ * Copyright (C) 2015 Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+ * Copyright (C) 2013 Maxime Ripard <maxime.ripard@free-electrons.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.
+ */
+
+#ifndef _LINUX_NVMEM_PROVIDER_H
+#define _LINUX_NVMEM_PROVIDER_H
+
+struct nvmem_device;
+struct nvmem_cell_info;
+
+struct nvmem_config {
+ struct device *dev;
+ const char *name;
+ int id;
+ struct module *owner;
+ const struct nvmem_cell_info *cells;
+ int ncells;
+ bool read_only;
+};
+
+#if IS_ENABLED(CONFIG_NVMEM)
+
+struct nvmem_device *nvmem_register(const struct nvmem_config *cfg);
+int nvmem_unregister(struct nvmem_device *nvmem);
+
+#else
+
+static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline int nvmem_unregister(struct nvmem_device *nvmem)
+{
+ return -ENOSYS;
+}
+
+#endif /* CONFIG_NVMEM */
+
+#endif /* ifndef _LINUX_NVMEM_PROVIDER_H */
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index 4c50854..cc7dd687 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -59,7 +59,7 @@
#else /* CONFIG_OF */
static inline int of_driver_match_device(struct device *dev,
- struct device_driver *drv)
+ const struct device_driver *drv)
{
return 0;
}
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index f34e040..41c9384 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -631,15 +631,19 @@
1 << PG_private | 1 << PG_private_2 | \
1 << PG_writeback | 1 << PG_reserved | \
1 << PG_slab | 1 << PG_swapcache | 1 << PG_active | \
- 1 << PG_unevictable | __PG_MLOCKED | __PG_HWPOISON | \
+ 1 << PG_unevictable | __PG_MLOCKED | \
__PG_COMPOUND_LOCK)
/*
* Flags checked when a page is prepped for return by the page allocator.
- * Pages being prepped should not have any flags set. It they are set,
+ * Pages being prepped should not have these flags set. It they are set,
* there has been a kernel bug or struct page corruption.
+ *
+ * __PG_HWPOISON is exceptional because it needs to be kept beyond page's
+ * alloc-free cycle to prevent from reusing the page.
*/
-#define PAGE_FLAGS_CHECK_AT_PREP ((1 << NR_PAGEFLAGS) - 1)
+#define PAGE_FLAGS_CHECK_AT_PREP \
+ (((1 << NR_PAGEFLAGS) - 1) & ~__PG_HWPOISON)
#define PAGE_FLAGS_PRIVATE \
(1 << PG_private | 1 << PG_private_2)
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 8a0321a..860c751 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1202,6 +1202,7 @@
u16 entry; /* driver uses to specify entry, OS writes */
};
+void pci_msi_setup_pci_dev(struct pci_dev *dev);
#ifdef CONFIG_PCI_MSI
int pci_msi_vec_count(struct pci_dev *dev);
diff --git a/include/linux/platform_data/atmel.h b/include/linux/platform_data/atmel.h
index 4b452c6..527a85c 100644
--- a/include/linux/platform_data/atmel.h
+++ b/include/linux/platform_data/atmel.h
@@ -46,18 +46,6 @@
#define AT91_IDE_SWAP_A0_A2 0x02
};
- /* USB Host */
-#define AT91_MAX_USBH_PORTS 3
-struct at91_usbh_data {
- int vbus_pin[AT91_MAX_USBH_PORTS]; /* port power-control pin */
- int overcurrent_pin[AT91_MAX_USBH_PORTS];
- u8 ports; /* number of ports on root hub */
- u8 overcurrent_supported;
- u8 vbus_pin_active_low[AT91_MAX_USBH_PORTS];
- u8 overcurrent_status[AT91_MAX_USBH_PORTS];
- u8 overcurrent_changed[AT91_MAX_USBH_PORTS];
-};
-
/* NAND / SmartMedia */
struct atmel_nand_data {
int enable_pin; /* chip enable */
diff --git a/include/linux/platform_data/macb.h b/include/linux/platform_data/macb.h
index 044a124..21b15f6 100644
--- a/include/linux/platform_data/macb.h
+++ b/include/linux/platform_data/macb.h
@@ -8,11 +8,19 @@
#ifndef __MACB_PDATA_H__
#define __MACB_PDATA_H__
+/**
+ * struct macb_platform_data - platform data for MACB Ethernet
+ * @phy_mask: phy mask passed when register the MDIO bus
+ * within the driver
+ * @phy_irq_pin: PHY IRQ
+ * @is_rmii: using RMII interface?
+ * @rev_eth_addr: reverse Ethernet address byte order
+ */
struct macb_platform_data {
u32 phy_mask;
- int phy_irq_pin; /* PHY IRQ */
- u8 is_rmii; /* using RMII interface? */
- u8 rev_eth_addr; /* reverse Ethernet address byte order */
+ int phy_irq_pin;
+ u8 is_rmii;
+ u8 rev_eth_addr;
};
#endif /* __MACB_PDATA_H__ */
diff --git a/include/linux/platform_data/mmc-esdhc-imx.h b/include/linux/platform_data/mmc-esdhc-imx.h
index 75f70f6..e1571ef 100644
--- a/include/linux/platform_data/mmc-esdhc-imx.h
+++ b/include/linux/platform_data/mmc-esdhc-imx.h
@@ -43,7 +43,6 @@
enum wp_types wp_type;
enum cd_types cd_type;
int max_bus_width;
- unsigned int f_max;
bool support_vsel;
unsigned int delay_line;
};
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index ba82c07..faa0e03 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -136,8 +136,6 @@
extern int early_serial_setup(struct uart_port *port);
-extern unsigned int serial8250_early_in(struct uart_port *port, int offset);
-extern void serial8250_early_out(struct uart_port *port, int offset, int value);
extern int early_serial8250_setup(struct earlycon_device *device,
const char *options);
extern void serial8250_do_set_termios(struct uart_port *port,
@@ -152,6 +150,11 @@
unsigned char serial8250_rx_chars(struct uart_8250_port *up, unsigned char lsr);
void serial8250_tx_chars(struct uart_8250_port *up);
unsigned int serial8250_modem_status(struct uart_8250_port *up);
+void serial8250_init_port(struct uart_8250_port *up);
+void serial8250_set_defaults(struct uart_8250_port *up);
+void serial8250_console_write(struct uart_8250_port *up, const char *s,
+ unsigned int count);
+int serial8250_console_setup(struct uart_port *port, char *options, bool probe);
extern void serial8250_set_isa_configurator(void (*v)
(int port, struct uart_port *up,
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index d6cdd6e..9b88536 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1602,20 +1602,16 @@
skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
/*
- * Propagate page->pfmemalloc to the skb if we can. The problem is
- * that not all callers have unique ownership of the page. If
- * pfmemalloc is set, we check the mapping as a mapping implies
- * page->index is set (index and pfmemalloc share space).
- * If it's a valid mapping, we cannot use page->pfmemalloc but we
- * do not lose pfmemalloc information as the pages would not be
- * allocated using __GFP_MEMALLOC.
+ * Propagate page pfmemalloc to the skb if we can. The problem is
+ * that not all callers have unique ownership of the page but rely
+ * on page_is_pfmemalloc doing the right thing(tm).
*/
frag->page.p = page;
frag->page_offset = off;
skb_frag_size_set(frag, size);
page = compound_head(page);
- if (page->pfmemalloc && !page->mapping)
+ if (page_is_pfmemalloc(page))
skb->pfmemalloc = true;
}
@@ -2263,7 +2259,7 @@
static inline void skb_propagate_pfmemalloc(struct page *page,
struct sk_buff *skb)
{
- if (page && page->pfmemalloc)
+ if (page_is_pfmemalloc(page))
skb->pfmemalloc = true;
}
@@ -2884,11 +2880,11 @@
*
* PHY drivers may accept clones of transmitted packets for
* timestamping via their phy_driver.txtstamp method. These drivers
- * must call this function to return the skb back to the stack, with
- * or without a timestamp.
+ * must call this function to return the skb back to the stack with a
+ * timestamp.
*
* @skb: clone of the the original outgoing packet
- * @hwtstamps: hardware time stamps, may be NULL if not available
+ * @hwtstamps: hardware time stamps
*
*/
void skb_complete_tx_timestamp(struct sk_buff *skb,
diff --git a/include/linux/ti_wilink_st.h b/include/linux/ti_wilink_st.h
index c78dcfe..d4217ef 100644
--- a/include/linux/ti_wilink_st.h
+++ b/include/linux/ti_wilink_st.h
@@ -86,7 +86,6 @@
extern long st_register(struct st_proto_s *);
extern long st_unregister(struct st_proto_s *);
-extern struct ti_st_plat_data *dt_pdata;
/*
* header information used by st_core.c
diff --git a/include/linux/tty.h b/include/linux/tty.h
index ad6c891..d072ded 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -709,4 +709,10 @@
static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
#endif
+#define tty_debug(tty, f, args...) \
+ do { \
+ printk(KERN_DEBUG "%s: %s: " f, __func__, \
+ tty_name(tty), ##args); \
+ } while (0)
+
#endif
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index 92e337c..1610524 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -296,7 +296,7 @@
struct tty_driver {
int magic; /* magic number for this structure */
struct kref kref; /* Reference management */
- struct cdev *cdevs;
+ struct cdev **cdevs;
struct module *owner;
const char *driver_name;
const char *name;
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index ab94f78..a41833c 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -19,8 +19,11 @@
enum usb_phy_interface phy_mode;
unsigned long flags;
#define CI_HDRC_REGS_SHARED BIT(0)
+#define CI_HDRC_DISABLE_DEVICE_STREAMING BIT(1)
#define CI_HDRC_SUPPORTS_RUNTIME_PM BIT(2)
-#define CI_HDRC_DISABLE_STREAMING BIT(3)
+#define CI_HDRC_DISABLE_HOST_STREAMING BIT(3)
+#define CI_HDRC_DISABLE_STREAMING (CI_HDRC_DISABLE_DEVICE_STREAMING | \
+ CI_HDRC_DISABLE_HOST_STREAMING)
/*
* Only set it when DCCPARAMS.DC==1 and DCCPARAMS.HC==1,
* but otg is not supported (no register otgsc).
@@ -29,12 +32,22 @@
#define CI_HDRC_IMX28_WRITE_FIX BIT(5)
#define CI_HDRC_FORCE_FULLSPEED BIT(6)
#define CI_HDRC_TURN_VBUS_EARLY_ON BIT(7)
+#define CI_HDRC_SET_NON_ZERO_TTHA BIT(8)
+#define CI_HDRC_OVERRIDE_AHB_BURST BIT(9)
+#define CI_HDRC_OVERRIDE_TX_BURST BIT(10)
+#define CI_HDRC_OVERRIDE_RX_BURST BIT(11)
enum usb_dr_mode dr_mode;
#define CI_HDRC_CONTROLLER_RESET_EVENT 0
#define CI_HDRC_CONTROLLER_STOPPED_EVENT 1
void (*notify_event) (struct ci_hdrc *ci, unsigned event);
struct regulator *reg_vbus;
+ struct usb_otg_caps ci_otg_caps;
bool tpl_support;
+ /* interrupt threshold setting */
+ u32 itc_setting;
+ u32 ahb_burst_config;
+ u32 tx_burst_size;
+ u32 rx_burst_size;
};
/* Default offset of capability registers */
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 2511469..1074b89 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -228,6 +228,8 @@
struct list_head list;
DECLARE_BITMAP(endpoints, 32);
const struct usb_function_instance *fi;
+
+ unsigned int bind_deactivated:1;
};
int usb_add_function(struct usb_configuration *, struct usb_function *);
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 4f3dfb7..c14a69b 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -141,10 +141,49 @@
};
/**
+ * struct usb_ep_caps - endpoint capabilities description
+ * @type_control:Endpoint supports control type (reserved for ep0).
+ * @type_iso:Endpoint supports isochronous transfers.
+ * @type_bulk:Endpoint supports bulk transfers.
+ * @type_int:Endpoint supports interrupt transfers.
+ * @dir_in:Endpoint supports IN direction.
+ * @dir_out:Endpoint supports OUT direction.
+ */
+struct usb_ep_caps {
+ unsigned type_control:1;
+ unsigned type_iso:1;
+ unsigned type_bulk:1;
+ unsigned type_int:1;
+ unsigned dir_in:1;
+ unsigned dir_out:1;
+};
+
+#define USB_EP_CAPS_TYPE_CONTROL 0x01
+#define USB_EP_CAPS_TYPE_ISO 0x02
+#define USB_EP_CAPS_TYPE_BULK 0x04
+#define USB_EP_CAPS_TYPE_INT 0x08
+#define USB_EP_CAPS_TYPE_ALL \
+ (USB_EP_CAPS_TYPE_ISO | USB_EP_CAPS_TYPE_BULK | USB_EP_CAPS_TYPE_INT)
+#define USB_EP_CAPS_DIR_IN 0x01
+#define USB_EP_CAPS_DIR_OUT 0x02
+#define USB_EP_CAPS_DIR_ALL (USB_EP_CAPS_DIR_IN | USB_EP_CAPS_DIR_OUT)
+
+#define USB_EP_CAPS(_type, _dir) \
+ { \
+ .type_control = !!(_type & USB_EP_CAPS_TYPE_CONTROL), \
+ .type_iso = !!(_type & USB_EP_CAPS_TYPE_ISO), \
+ .type_bulk = !!(_type & USB_EP_CAPS_TYPE_BULK), \
+ .type_int = !!(_type & USB_EP_CAPS_TYPE_INT), \
+ .dir_in = !!(_dir & USB_EP_CAPS_DIR_IN), \
+ .dir_out = !!(_dir & USB_EP_CAPS_DIR_OUT), \
+ }
+
+/**
* struct usb_ep - device side representation of USB endpoint
* @name:identifier for the endpoint, such as "ep-a" or "ep9in-bulk"
* @ops: Function pointers used to access hardware-specific operations.
* @ep_list:the gadget's ep_list holds all of its endpoints
+ * @caps:The structure describing types and directions supported by endoint.
* @maxpacket:The maximum packet size used on this endpoint. The initial
* value can sometimes be reduced (hardware allowing), according to
* the endpoint descriptor used to configure the endpoint.
@@ -167,12 +206,15 @@
* gadget->ep_list. the control endpoint (gadget->ep0) is not in that list,
* and is accessed only in response to a driver setup() callback.
*/
+
struct usb_ep {
void *driver_data;
const char *name;
const struct usb_ep_ops *ops;
struct list_head ep_list;
+ struct usb_ep_caps caps;
+ bool claimed;
unsigned maxpacket:16;
unsigned maxpacket_limit:16;
unsigned max_streams:16;
@@ -492,6 +534,9 @@
int (*udc_start)(struct usb_gadget *,
struct usb_gadget_driver *);
int (*udc_stop)(struct usb_gadget *);
+ struct usb_ep *(*match_ep)(struct usb_gadget *,
+ struct usb_endpoint_descriptor *,
+ struct usb_ss_ep_comp_descriptor *);
};
/**
@@ -511,6 +556,7 @@
* @dev: Driver model state for this abstract device.
* @out_epnum: last used out ep number
* @in_epnum: last used in ep number
+ * @otg_caps: OTG capabilities of this gadget.
* @sg_supported: true if we can handle scatter-gather
* @is_otg: True if the USB device port uses a Mini-AB jack, so that the
* gadget driver must provide a USB OTG descriptor.
@@ -526,6 +572,9 @@
* @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to
* MaxPacketSize.
* @is_selfpowered: if the gadget is self-powered.
+ * @deactivated: True if gadget is deactivated - in deactivated state it cannot
+ * be connected.
+ * @connected: True if gadget is connected.
*
* Gadgets have a mostly-portable "gadget driver" implementing device
* functions, handling all usb configurations and interfaces. Gadget
@@ -559,6 +608,7 @@
struct device dev;
unsigned out_epnum;
unsigned in_epnum;
+ struct usb_otg_caps *otg_caps;
unsigned sg_supported:1;
unsigned is_otg:1;
@@ -567,7 +617,12 @@
unsigned a_hnp_support:1;
unsigned a_alt_hnp_support:1;
unsigned quirk_ep_out_aligned_size:1;
+ unsigned quirk_altset_not_supp:1;
+ unsigned quirk_stall_not_supp:1;
+ unsigned quirk_zlp_not_supp:1;
unsigned is_selfpowered:1;
+ unsigned deactivated:1;
+ unsigned connected:1;
};
#define work_to_gadget(w) (container_of((w), struct usb_gadget, work))
@@ -584,7 +639,6 @@
#define gadget_for_each_ep(tmp, gadget) \
list_for_each_entry(tmp, &(gadget)->ep_list, ep_list)
-
/**
* usb_ep_align_maybe - returns @len aligned to ep's maxpacketsize if gadget
* requires quirk_ep_out_aligned_size, otherwise reguens len.
@@ -603,6 +657,34 @@
}
/**
+ * gadget_is_altset_supported - return true iff the hardware supports
+ * altsettings
+ * @g: controller to check for quirk
+ */
+static inline int gadget_is_altset_supported(struct usb_gadget *g)
+{
+ return !g->quirk_altset_not_supp;
+}
+
+/**
+ * gadget_is_stall_supported - return true iff the hardware supports stalling
+ * @g: controller to check for quirk
+ */
+static inline int gadget_is_stall_supported(struct usb_gadget *g)
+{
+ return !g->quirk_stall_not_supp;
+}
+
+/**
+ * gadget_is_zlp_supported - return true iff the hardware supports zlp
+ * @g: controller to check for quirk
+ */
+static inline int gadget_is_zlp_supported(struct usb_gadget *g)
+{
+ return !g->quirk_zlp_not_supp;
+}
+
+/**
* gadget_is_dualspeed - return true iff the hardware handles high speed
* @g: controller that might support both high and full speeds
*/
@@ -771,9 +853,24 @@
*/
static inline int usb_gadget_connect(struct usb_gadget *gadget)
{
+ int ret;
+
if (!gadget->ops->pullup)
return -EOPNOTSUPP;
- return gadget->ops->pullup(gadget, 1);
+
+ if (gadget->deactivated) {
+ /*
+ * If gadget is deactivated we only save new state.
+ * Gadget will be connected automatically after activation.
+ */
+ gadget->connected = true;
+ return 0;
+ }
+
+ ret = gadget->ops->pullup(gadget, 1);
+ if (!ret)
+ gadget->connected = 1;
+ return ret;
}
/**
@@ -784,20 +881,88 @@
* as a disconnect (when a VBUS session is active). Not all systems
* support software pullup controls.
*
- * This routine may be used during the gadget driver bind() call to prevent
- * the peripheral from ever being visible to the USB host, unless later
- * usb_gadget_connect() is called. For example, user mode components may
- * need to be activated before the system can talk to hosts.
- *
* Returns zero on success, else negative errno.
*/
static inline int usb_gadget_disconnect(struct usb_gadget *gadget)
{
+ int ret;
+
if (!gadget->ops->pullup)
return -EOPNOTSUPP;
- return gadget->ops->pullup(gadget, 0);
+
+ if (gadget->deactivated) {
+ /*
+ * If gadget is deactivated we only save new state.
+ * Gadget will stay disconnected after activation.
+ */
+ gadget->connected = false;
+ return 0;
+ }
+
+ ret = gadget->ops->pullup(gadget, 0);
+ if (!ret)
+ gadget->connected = 0;
+ return ret;
}
+/**
+ * usb_gadget_deactivate - deactivate function which is not ready to work
+ * @gadget: the peripheral being deactivated
+ *
+ * This routine may be used during the gadget driver bind() call to prevent
+ * the peripheral from ever being visible to the USB host, unless later
+ * usb_gadget_activate() is called. For example, user mode components may
+ * need to be activated before the system can talk to hosts.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int usb_gadget_deactivate(struct usb_gadget *gadget)
+{
+ int ret;
+
+ if (gadget->deactivated)
+ return 0;
+
+ if (gadget->connected) {
+ ret = usb_gadget_disconnect(gadget);
+ if (ret)
+ return ret;
+ /*
+ * If gadget was being connected before deactivation, we want
+ * to reconnect it in usb_gadget_activate().
+ */
+ gadget->connected = true;
+ }
+ gadget->deactivated = true;
+
+ return 0;
+}
+
+/**
+ * usb_gadget_activate - activate function which is not ready to work
+ * @gadget: the peripheral being activated
+ *
+ * This routine activates gadget which was previously deactivated with
+ * usb_gadget_deactivate() call. It calls usb_gadget_connect() if needed.
+ *
+ * Returns zero on success, else negative errno.
+ */
+static inline int usb_gadget_activate(struct usb_gadget *gadget)
+{
+ if (!gadget->deactivated)
+ return 0;
+
+ gadget->deactivated = false;
+
+ /*
+ * If gadget has been connected before deactivation, or became connected
+ * while it was being deactivated, we call usb_gadget_connect().
+ */
+ if (gadget->connected)
+ return usb_gadget_connect(gadget);
+
+ return 0;
+}
/*-------------------------------------------------------------------------*/
@@ -1002,6 +1167,10 @@
struct usb_descriptor_header **ss);
void usb_free_all_descriptors(struct usb_function *f);
+struct usb_descriptor_header *usb_otg_descriptor_alloc(
+ struct usb_gadget *gadget);
+int usb_otg_descriptor_init(struct usb_gadget *gadget,
+ struct usb_descriptor_header *otg_desc);
/*-------------------------------------------------------------------------*/
/* utility to simplify map/unmap of usb_requests to/from DMA */
@@ -1034,6 +1203,21 @@
/*-------------------------------------------------------------------------*/
+/* utility to find endpoint by name */
+
+extern struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g,
+ const char *name);
+
+/*-------------------------------------------------------------------------*/
+
+/* utility to check if endpoint caps match descriptor needs */
+
+extern int usb_gadget_ep_match_desc(struct usb_gadget *gadget,
+ struct usb_ep *ep, struct usb_endpoint_descriptor *desc,
+ struct usb_ss_ep_comp_descriptor *ep_comp);
+
+/*-------------------------------------------------------------------------*/
+
/* utility to update vbus status for udc core, it may be scheduled */
extern void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status);
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h
index c9aa779..d2784c1 100644
--- a/include/linux/usb/hcd.h
+++ b/include/linux/usb/hcd.h
@@ -564,9 +564,9 @@
/*-------------------------------------------------------------------------*/
-/* class requests from USB 3.0 hub spec, table 10-5 */
-#define SetHubDepth (0x3000 | HUB_SET_DEPTH)
-#define GetPortErrorCount (0x8000 | HUB_GET_PORT_ERR_COUNT)
+/* class requests from USB 3.1 hub spec, table 10-7 */
+#define SetHubDepth (0x2000 | HUB_SET_DEPTH)
+#define GetPortErrorCount (0xa300 | HUB_GET_PORT_ERR_COUNT)
/*
* Generic bandwidth allocation constants/support
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index e55a150..8c8f685 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -128,7 +128,7 @@
*/
struct msm_usb_cable {
struct notifier_block nb;
- struct extcon_specific_cable_nb conn;
+ struct extcon_dev *extcon;
};
/**
@@ -155,6 +155,10 @@
* starting controller using usbcmd run/stop bit.
* @vbus: VBUS signal state trakining, using extcon framework
* @id: ID signal state trakining, using extcon framework
+ * @switch_gpio: Descriptor for GPIO used to control external Dual
+ * SPDT USB Switch.
+ * @reboot: Used to inform the driver to route USB D+/D- line to Device
+ * connector
*/
struct msm_otg {
struct usb_phy phy;
@@ -188,6 +192,9 @@
struct msm_usb_cable vbus;
struct msm_usb_cable id;
+
+ struct gpio_desc *switch_gpio;
+ struct notifier_block reboot;
};
#endif
diff --git a/include/linux/usb/of.h b/include/linux/usb/of.h
index cfe0528..8c5a818 100644
--- a/include/linux/usb/of.h
+++ b/include/linux/usb/of.h
@@ -15,6 +15,8 @@
enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np);
enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np);
bool of_usb_host_tpl_support(struct device_node *np);
+int of_usb_update_otg_caps(struct device_node *np,
+ struct usb_otg_caps *otg_caps);
#else
static inline enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np)
{
@@ -30,6 +32,11 @@
{
return false;
}
+static inline int of_usb_update_otg_caps(struct device_node *np,
+ struct usb_otg_caps *otg_caps)
+{
+ return 0;
+}
#endif
#if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_USB_SUPPORT)
diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h
index 52661c5..bd1dcf8 100644
--- a/include/linux/usb/otg.h
+++ b/include/linux/usb/otg.h
@@ -41,6 +41,21 @@
};
+/**
+ * struct usb_otg_caps - describes the otg capabilities of the device
+ * @otg_rev: The OTG revision number the device is compliant with, it's
+ * in binary-coded decimal (i.e. 2.0 is 0200H).
+ * @hnp_support: Indicates if the device supports HNP.
+ * @srp_support: Indicates if the device supports SRP.
+ * @adp_support: Indicates if the device supports ADP.
+ */
+struct usb_otg_caps {
+ u16 otg_rev;
+ bool hnp_support;
+ bool srp_support;
+ bool adp_support;
+};
+
extern const char *usb_otg_state_string(enum usb_otg_state state);
/* Context: can sleep */
diff --git a/include/media/rc-core.h b/include/media/rc-core.h
index 45534da5..644bdc6 100644
--- a/include/media/rc-core.h
+++ b/include/media/rc-core.h
@@ -74,8 +74,6 @@
* @input_dev: the input child device used to communicate events to userspace
* @driver_type: specifies if protocol decoding is done in hardware or software
* @idle: used to keep track of RX state
- * @encode_wakeup: wakeup filtering uses IR encode API, therefore the allowed
- * wakeup protocols is the set of all raw encoders
* @allowed_protocols: bitmask with the supported RC_BIT_* protocols
* @enabled_protocols: bitmask with the enabled RC_BIT_* protocols
* @allowed_wakeup_protocols: bitmask with the supported RC_BIT_* wakeup protocols
@@ -136,7 +134,6 @@
struct input_dev *input_dev;
enum rc_driver_type driver_type;
bool idle;
- bool encode_wakeup;
u64 allowed_protocols;
u64 enabled_protocols;
u64 allowed_wakeup_protocols;
@@ -246,7 +243,6 @@
#define US_TO_NS(usec) ((usec) * 1000)
#define MS_TO_US(msec) ((msec) * 1000)
#define MS_TO_NS(msec) ((msec) * 1000 * 1000)
-#define NS_TO_US(nsec) DIV_ROUND_UP(nsec, 1000L)
void ir_raw_event_handle(struct rc_dev *dev);
int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev);
@@ -254,9 +250,6 @@
int ir_raw_event_store_with_filter(struct rc_dev *dev,
struct ir_raw_event *ev);
void ir_raw_event_set_idle(struct rc_dev *dev, bool idle);
-int ir_raw_encode_scancode(u64 protocols,
- const struct rc_scancode_filter *scancode,
- struct ir_raw_event *events, unsigned int max);
static inline void ir_raw_event_reset(struct rc_dev *dev)
{
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 22a44c2..c192e1b 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -139,6 +139,7 @@
* @VB2_BUF_STATE_PREPARING: buffer is being prepared in videobuf
* @VB2_BUF_STATE_PREPARED: buffer prepared in videobuf and by the driver
* @VB2_BUF_STATE_QUEUED: buffer queued in videobuf, but not in driver
+ * @VB2_BUF_STATE_REQUEUEING: re-queue a buffer to the driver
* @VB2_BUF_STATE_ACTIVE: buffer queued in driver and possibly used
* in a hardware operation
* @VB2_BUF_STATE_DONE: buffer returned from driver to videobuf, but
@@ -152,6 +153,7 @@
VB2_BUF_STATE_PREPARING,
VB2_BUF_STATE_PREPARED,
VB2_BUF_STATE_QUEUED,
+ VB2_BUF_STATE_REQUEUEING,
VB2_BUF_STATE_ACTIVE,
VB2_BUF_STATE_DONE,
VB2_BUF_STATE_ERROR,
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 3ee4c92..931738b 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -99,7 +99,6 @@
int tcf_hash_search(struct tc_action *a, u32 index);
void tcf_hash_destroy(struct tc_action *a);
-int tcf_hash_release(struct tc_action *a, int bind);
u32 tcf_hash_new_index(struct tcf_hashinfo *hinfo);
int tcf_hash_check(u32 index, struct tc_action *a, int bind);
int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a,
@@ -107,6 +106,13 @@
void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);
void tcf_hash_insert(struct tc_action *a);
+int __tcf_hash_release(struct tc_action *a, bool bind, bool strict);
+
+static inline int tcf_hash_release(struct tc_action *a, bool bind)
+{
+ return __tcf_hash_release(a, bind, false);
+}
+
int tcf_register_action(struct tc_action_ops *a, unsigned int mask);
int tcf_unregister_action(struct tc_action_ops *a);
int tcf_action_destroy(struct list_head *actions, int bind);
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a741678..883fe1e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4868,6 +4868,23 @@
struct cfg80211_chan_def *chandef,
enum nl80211_iftype iftype);
+/**
+ * cfg80211_reg_can_beacon_relax - check if beaconing is allowed with relaxation
+ * @wiphy: the wiphy
+ * @chandef: the channel definition
+ * @iftype: interface type
+ *
+ * Return: %true if there is no secondary channel or the secondary channel(s)
+ * can be used for beaconing (i.e. is not a radar channel etc.). This version
+ * also checks if IR-relaxation conditions apply, to allow beaconing under
+ * more permissive conditions.
+ *
+ * Requires the RTNL to be held.
+ */
+bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef,
+ enum nl80211_iftype iftype);
+
/*
* cfg80211_ch_switch_notify - update wdev channel and notify userspace
* @dev: the device which switched channels
diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h
index e1300b3..53eead2 100644
--- a/include/net/inet_frag.h
+++ b/include/net/inet_frag.h
@@ -21,13 +21,11 @@
* @INET_FRAG_FIRST_IN: first fragment has arrived
* @INET_FRAG_LAST_IN: final fragment has arrived
* @INET_FRAG_COMPLETE: frag queue has been processed and is due for destruction
- * @INET_FRAG_EVICTED: frag queue is being evicted
*/
enum {
INET_FRAG_FIRST_IN = BIT(0),
INET_FRAG_LAST_IN = BIT(1),
INET_FRAG_COMPLETE = BIT(2),
- INET_FRAG_EVICTED = BIT(3)
};
/**
@@ -45,6 +43,7 @@
* @flags: fragment queue flags
* @max_size: maximum received fragment size
* @net: namespace that this frag belongs to
+ * @list_evictor: list of queues to forcefully evict (e.g. due to low memory)
*/
struct inet_frag_queue {
spinlock_t lock;
@@ -59,6 +58,7 @@
__u8 flags;
u16 max_size;
struct netns_frags *net;
+ struct hlist_node list_evictor;
};
#define INETFRAGS_HASHSZ 1024
@@ -125,6 +125,11 @@
inet_frag_destroy(q, f);
}
+static inline bool inet_frag_evicting(struct inet_frag_queue *q)
+{
+ return !hlist_unhashed(&q->list_evictor);
+}
+
/* Memory Tracking Functions. */
/* The default percpu_counter batch size is not big enough to scale to
@@ -139,14 +144,14 @@
return percpu_counter_read(&nf->mem);
}
-static inline void sub_frag_mem_limit(struct inet_frag_queue *q, int i)
+static inline void sub_frag_mem_limit(struct netns_frags *nf, int i)
{
- __percpu_counter_add(&q->net->mem, -i, frag_percpu_counter_batch);
+ __percpu_counter_add(&nf->mem, -i, frag_percpu_counter_batch);
}
-static inline void add_frag_mem_limit(struct inet_frag_queue *q, int i)
+static inline void add_frag_mem_limit(struct netns_frags *nf, int i)
{
- __percpu_counter_add(&q->net->mem, i, frag_percpu_counter_batch);
+ __percpu_counter_add(&nf->mem, i, frag_percpu_counter_batch);
}
static inline void init_frag_mem_limit(struct netns_frags *nf)
diff --git a/include/net/ip.h b/include/net/ip.h
index 0750a18..d5fe9f2 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -161,6 +161,7 @@
}
/* datagram.c */
+int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len);
void ip4_datagram_release_cb(struct sock *sk);
diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h
index 49c142b..5fa643b 100644
--- a/include/net/ip_fib.h
+++ b/include/net/ip_fib.h
@@ -183,7 +183,6 @@
struct fib_table {
struct hlist_node tb_hlist;
u32 tb_id;
- int tb_default;
int tb_num_default;
struct rcu_head rcu;
unsigned long *tb_data;
@@ -290,7 +289,7 @@
int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
u8 tos, int oif, struct net_device *dev,
struct in_device *idev, u32 *itag);
-void fib_select_default(struct fib_result *res);
+void fib_select_default(const struct flowi4 *flp, struct fib_result *res);
#ifdef CONFIG_IP_ROUTE_CLASSID
static inline int fib_num_tclassid_users(struct net *net)
{
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 095433b..37cd391 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -291,7 +291,7 @@
extern unsigned int nf_conntrack_hash_rnd;
void init_nf_conntrack_hash_rnd(void);
-void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl);
+struct nf_conn *nf_ct_tmpl_alloc(struct net *net, u16 zone, gfp_t flags);
#define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count)
#define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index 29d6a94..723b61c 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -68,7 +68,6 @@
spinlock_t lock;
struct hlist_nulls_head unconfirmed;
struct hlist_nulls_head dying;
- struct hlist_nulls_head tmpl;
};
struct netns_ct {
diff --git a/include/net/sock.h b/include/net/sock.h
index 05a8c1a..f21f070 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -902,7 +902,7 @@
void sk_set_memalloc(struct sock *sk);
void sk_clear_memalloc(struct sock *sk);
-int sk_wait_data(struct sock *sk, long *timeo);
+int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb);
struct request_sock_ops;
struct timewait_sock_ops;
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
index 4942710..8d1d7fa 100644
--- a/include/scsi/scsi_eh.h
+++ b/include/scsi/scsi_eh.h
@@ -28,7 +28,6 @@
u64 * info_out);
extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
-extern void scsi_set_sense_information(u8 *buf, u64 info);
extern int scsi_ioctl_reset(struct scsi_device *, int __user *);
diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h
index 865a141..427bc41 100644
--- a/include/sound/soc-topology.h
+++ b/include/sound/soc-topology.h
@@ -141,6 +141,8 @@
int io_ops_count;
};
+#ifdef CONFIG_SND_SOC_TOPOLOGY
+
/* gets a pointer to data from the firmware block header */
static inline const void *snd_soc_tplg_get_data(struct snd_soc_tplg_hdr *hdr)
{
@@ -165,4 +167,14 @@
const struct snd_soc_tplg_widget_events *events, int num_events,
u16 event_type);
+#else
+
+static inline int snd_soc_tplg_component_remove(struct snd_soc_component *comp,
+ u32 index)
+{
+ return 0;
+}
+
+#endif
+
#endif
diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h
index 34117b8..0aedbb2 100644
--- a/include/target/iscsi/iscsi_target_core.h
+++ b/include/target/iscsi/iscsi_target_core.h
@@ -595,6 +595,7 @@
int bitmap_id;
int rx_thread_active;
struct task_struct *rx_thread;
+ struct completion rx_login_comp;
int tx_thread_active;
struct task_struct *tx_thread;
/* list_head for session connection list */
diff --git a/include/trace/events/spmi.h b/include/trace/events/spmi.h
new file mode 100644
index 0000000..62f005e
--- /dev/null
+++ b/include/trace/events/spmi.h
@@ -0,0 +1,135 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM spmi
+
+#if !defined(_TRACE_SPMI_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SPMI_H
+
+#include <linux/spmi.h>
+#include <linux/tracepoint.h>
+
+/*
+ * drivers/spmi/spmi.c
+ */
+
+TRACE_EVENT(spmi_write_begin,
+ TP_PROTO(u8 opcode, u8 sid, u16 addr, u8 len, const u8 *buf),
+ TP_ARGS(opcode, sid, addr, len, buf),
+
+ TP_STRUCT__entry(
+ __field ( u8, opcode )
+ __field ( u8, sid )
+ __field ( u16, addr )
+ __field ( u8, len )
+ __dynamic_array ( u8, buf, len + 1 )
+ ),
+
+ TP_fast_assign(
+ __entry->opcode = opcode;
+ __entry->sid = sid;
+ __entry->addr = addr;
+ __entry->len = len + 1;
+ memcpy(__get_dynamic_array(buf), buf, len + 1);
+ ),
+
+ TP_printk("opc=%d sid=%02d addr=0x%04x len=%d buf=0x[%*phD]",
+ (int)__entry->opcode, (int)__entry->sid,
+ (int)__entry->addr, (int)__entry->len,
+ (int)__entry->len, __get_dynamic_array(buf))
+);
+
+TRACE_EVENT(spmi_write_end,
+ TP_PROTO(u8 opcode, u8 sid, u16 addr, int ret),
+ TP_ARGS(opcode, sid, addr, ret),
+
+ TP_STRUCT__entry(
+ __field ( u8, opcode )
+ __field ( u8, sid )
+ __field ( u16, addr )
+ __field ( int, ret )
+ ),
+
+ TP_fast_assign(
+ __entry->opcode = opcode;
+ __entry->sid = sid;
+ __entry->addr = addr;
+ __entry->ret = ret;
+ ),
+
+ TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d",
+ (int)__entry->opcode, (int)__entry->sid,
+ (int)__entry->addr, __entry->ret)
+);
+
+TRACE_EVENT(spmi_read_begin,
+ TP_PROTO(u8 opcode, u8 sid, u16 addr),
+ TP_ARGS(opcode, sid, addr),
+
+ TP_STRUCT__entry(
+ __field ( u8, opcode )
+ __field ( u8, sid )
+ __field ( u16, addr )
+ ),
+
+ TP_fast_assign(
+ __entry->opcode = opcode;
+ __entry->sid = sid;
+ __entry->addr = addr;
+ ),
+
+ TP_printk("opc=%d sid=%02d addr=0x%04x",
+ (int)__entry->opcode, (int)__entry->sid,
+ (int)__entry->addr)
+);
+
+TRACE_EVENT(spmi_read_end,
+ TP_PROTO(u8 opcode, u8 sid, u16 addr, int ret, u8 len, const u8 *buf),
+ TP_ARGS(opcode, sid, addr, ret, len, buf),
+
+ TP_STRUCT__entry(
+ __field ( u8, opcode )
+ __field ( u8, sid )
+ __field ( u16, addr )
+ __field ( int, ret )
+ __field ( u8, len )
+ __dynamic_array ( u8, buf, len + 1 )
+ ),
+
+ TP_fast_assign(
+ __entry->opcode = opcode;
+ __entry->sid = sid;
+ __entry->addr = addr;
+ __entry->ret = ret;
+ __entry->len = len + 1;
+ memcpy(__get_dynamic_array(buf), buf, len + 1);
+ ),
+
+ TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d len=%02d buf=0x[%*phD]",
+ (int)__entry->opcode, (int)__entry->sid,
+ (int)__entry->addr, __entry->ret, (int)__entry->len,
+ (int)__entry->len, __get_dynamic_array(buf))
+);
+
+TRACE_EVENT(spmi_cmd,
+ TP_PROTO(u8 opcode, u8 sid, int ret),
+ TP_ARGS(opcode, sid, ret),
+
+ TP_STRUCT__entry(
+ __field ( u8, opcode )
+ __field ( u8, sid )
+ __field ( int, ret )
+ ),
+
+ TP_fast_assign(
+ __entry->opcode = opcode;
+ __entry->sid = sid;
+ __entry->ret = ret;
+ ),
+
+ TP_printk("opc=%d sid=%02d ret=%d", (int)__entry->opcode,
+ (int)__entry->sid, ret)
+);
+
+#endif /* _TRACE_SPMI_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index b6fce90..fbdd118 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -32,7 +32,7 @@
#ifndef __AMDGPU_DRM_H__
#define __AMDGPU_DRM_H__
-#include <drm/drm.h>
+#include "drm.h"
#define DRM_AMDGPU_GEM_CREATE 0x00
#define DRM_AMDGPU_GEM_MMAP 0x01
@@ -614,6 +614,8 @@
uint32_t vram_type;
/** video memory bit width*/
uint32_t vram_bit_width;
+ /* vce harvesting instance */
+ uint32_t vce_harvest_config;
};
struct drm_amdgpu_info_hw_ip {
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 6e1a2ed..db809b7 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1070,6 +1070,14 @@
__u64 offset;
__u64 val; /* Return value */
};
+/* Known registers:
+ *
+ * Render engine timestamp - 0x2358 + 64bit - gen7+
+ * - Note this register returns an invalid value if using the default
+ * single instruction 8byte read, in order to workaround that use
+ * offset (0x2538 | 1) instead.
+ *
+ */
struct drm_i915_reset_stats {
__u32 ctx_id;
diff --git a/include/uapi/drm/radeon_drm.h b/include/uapi/drm/radeon_drm.h
index 1ef7666..01aa2a8 100644
--- a/include/uapi/drm/radeon_drm.h
+++ b/include/uapi/drm/radeon_drm.h
@@ -33,7 +33,7 @@
#ifndef __RADEON_DRM_H__
#define __RADEON_DRM_H__
-#include <drm/drm.h>
+#include "drm.h"
/* WARNING: If you change any of these defines, make sure to change the
* defines in the X server file (radeon_sarea.h)
diff --git a/include/uapi/linux/gsmmux.h b/include/uapi/linux/gsmmux.h
index c06742d..ab055d8 100644
--- a/include/uapi/linux/gsmmux.h
+++ b/include/uapi/linux/gsmmux.h
@@ -3,6 +3,7 @@
#include <linux/if.h>
#include <linux/ioctl.h>
+#include <linux/types.h>
struct gsm_config
{
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 716ad4a..0d831f9 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -317,6 +317,7 @@
struct {
#define KVM_SYSTEM_EVENT_SHUTDOWN 1
#define KVM_SYSTEM_EVENT_RESET 2
+#define KVM_SYSTEM_EVENT_CRASH 3
__u32 type;
__u64 flags;
} system_event;
@@ -481,6 +482,7 @@
((ai) << 26))
#define KVM_S390_INT_IO_MIN 0x00000000u
#define KVM_S390_INT_IO_MAX 0xfffdffffu
+#define KVM_S390_INT_IO_AI_MASK 0x04000000u
struct kvm_s390_interrupt {
diff --git a/include/uapi/linux/mei.h b/include/uapi/linux/mei.h
index bc0d8b6..7c3b64f 100644
--- a/include/uapi/linux/mei.h
+++ b/include/uapi/linux/mei.h
@@ -107,4 +107,23 @@
};
};
+/**
+ * DOC: set and unset event notification for a connected client
+ *
+ * The IOCTL argument is 1 for enabling event notification and 0 for
+ * disabling the service
+ * Return: -EOPNOTSUPP if the devices doesn't support the feature
+ */
+#define IOCTL_MEI_NOTIFY_SET _IOW('H', 0x02, __u32)
+
+/**
+ * DOC: retrieve notification
+ *
+ * The IOCTL output argument is 1 if an event was is pending and 0 otherwise
+ * the ioctl has to be called in order to acknowledge pending event
+ *
+ * Return: -EOPNOTSUPP if the devices doesn't support the feature
+ */
+#define IOCTL_MEI_NOTIFY_GET _IOR('H', 0x03, __u32)
+
#endif /* _LINUX_MEI_H */
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
index efe3443..413417f 100644
--- a/include/uapi/linux/pci_regs.h
+++ b/include/uapi/linux/pci_regs.h
@@ -319,6 +319,7 @@
#define PCI_MSIX_PBA 8 /* Pending Bit Array offset */
#define PCI_MSIX_PBA_BIR 0x00000007 /* BAR index */
#define PCI_MSIX_PBA_OFFSET 0xfffffff8 /* Offset into specified BAR */
+#define PCI_MSIX_FLAGS_BIRMASK PCI_MSIX_PBA_BIR /* deprecated */
#define PCI_CAP_MSIX_SIZEOF 12 /* size of MSIX registers */
/* MSI-X Table entry format */
diff --git a/include/uapi/linux/usb/ch9.h b/include/uapi/linux/usb/ch9.h
index aa33fd1..f7adc6e 100644
--- a/include/uapi/linux/usb/ch9.h
+++ b/include/uapi/linux/usb/ch9.h
@@ -674,9 +674,21 @@
__u8 bmAttributes; /* support for HNP, SRP, etc */
} __attribute__ ((packed));
+/* USB_DT_OTG (from OTG 2.0 supplement) */
+struct usb_otg20_descriptor {
+ __u8 bLength;
+ __u8 bDescriptorType;
+
+ __u8 bmAttributes; /* support for HNP, SRP and ADP, etc */
+ __le16 bcdOTG; /* OTG and EH supplement release number
+ * in binary-coded decimal(i.e. 2.0 is 0200H)
+ */
+} __attribute__ ((packed));
+
/* from usb_otg_descriptor.bmAttributes */
#define USB_OTG_SRP (1 << 0)
#define USB_OTG_HNP (1 << 1) /* swap host/device roles */
+#define USB_OTG_ADP (1 << 2) /* support ADP */
/*-------------------------------------------------------------------------*/
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 7bbee79..ec32293 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -34,6 +34,7 @@
/* The feature bitmap for virtio net */
#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
+#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Dynamic offload configuration. */
#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */
@@ -226,4 +227,19 @@
#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1
#define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000
+/*
+ * Control network offloads
+ *
+ * Reconfigures the network offloads that Guest can handle.
+ *
+ * Available with the VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit.
+ *
+ * Command data format matches the feature bit mask exactly.
+ *
+ * See VIRTIO_NET_F_GUEST_* for the list of offloads
+ * that can be enabled/disabled.
+ */
+#define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5
+#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0
+
#endif /* _LINUX_VIRTIO_NET_H */
diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index 7530146..90007a1 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -157,6 +157,12 @@
__le32 queue_used_hi; /* read-write */
};
+/* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
+struct virtio_pci_cfg_cap {
+ struct virtio_pci_cap cap;
+ __u8 pci_cfg_data[4]; /* Data for BAR access. */
+};
+
/* Macro versions of offsets for the Old Timers! */
#define VIRTIO_PCI_CAP_VNDR 0
#define VIRTIO_PCI_CAP_NEXT 1
diff --git a/include/uapi/linux/virtio_ring.h b/include/uapi/linux/virtio_ring.h
index 915980a..c072959 100644
--- a/include/uapi/linux/virtio_ring.h
+++ b/include/uapi/linux/virtio_ring.h
@@ -31,6 +31,9 @@
* SUCH DAMAGE.
*
* Copyright Rusty Russell IBM Corporation 2007. */
+#ifndef __KERNEL__
+#include <stdint.h>
+#endif
#include <linux/types.h>
#include <linux/virtio_types.h>
@@ -143,7 +146,7 @@
vr->num = num;
vr->desc = p;
vr->avail = p + num*sizeof(struct vring_desc);
- vr->used = (void *)(((unsigned long)&vr->avail->ring[num] + sizeof(__virtio16)
+ vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] + sizeof(__virtio16)
+ align-1) & ~(align - 1));
}
diff --git a/include/uapi/sound/asoc.h b/include/uapi/sound/asoc.h
index 1221520..247c50b 100644
--- a/include/uapi/sound/asoc.h
+++ b/include/uapi/sound/asoc.h
@@ -18,6 +18,12 @@
#include <linux/types.h>
#include <sound/asound.h>
+#ifndef __KERNEL__
+#error This API is an early revision and not enabled in the current
+#error kernel release, it will be enabled in a future kernel version
+#error with incompatible changes to what is here.
+#endif
+
/*
* Maximum number of channels topology kcontrol can represent.
*/
@@ -77,7 +83,7 @@
#define SND_SOC_TPLG_NUM_TEXTS 16
/* ABI version */
-#define SND_SOC_TPLG_ABI_VERSION 0x2
+#define SND_SOC_TPLG_ABI_VERSION 0x3
/* Max size of TLV data */
#define SND_SOC_TPLG_TLV_SIZE 32
@@ -97,7 +103,8 @@
#define SND_SOC_TPLG_TYPE_PCM 7
#define SND_SOC_TPLG_TYPE_MANIFEST 8
#define SND_SOC_TPLG_TYPE_CODEC_LINK 9
-#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_CODEC_LINK
+#define SND_SOC_TPLG_TYPE_PDATA 10
+#define SND_SOC_TPLG_TYPE_MAX SND_SOC_TPLG_TYPE_PDATA
/* vendor block IDs - please add new vendor types to end */
#define SND_SOC_TPLG_TYPE_VENDOR_FW 1000
@@ -110,7 +117,7 @@
/*
* Block Header.
- * This header preceeds all object and object arrays below.
+ * This header precedes all object and object arrays below.
*/
struct snd_soc_tplg_hdr {
__le32 magic; /* magic number */
@@ -137,11 +144,19 @@
/*
* Kcontrol TLV data.
*/
+struct snd_soc_tplg_tlv_dbscale {
+ __le32 min;
+ __le32 step;
+ __le32 mute;
+} __attribute__((packed));
+
struct snd_soc_tplg_ctl_tlv {
- __le32 size; /* in bytes aligned to 4 */
- __le32 numid; /* control element numeric identification */
- __le32 count; /* number of elem in data array */
- __le32 data[SND_SOC_TPLG_TLV_SIZE];
+ __le32 size; /* in bytes of this structure */
+ __le32 type; /* SNDRV_CTL_TLVT_*, type of TLV */
+ union {
+ __le32 data[SND_SOC_TPLG_TLV_SIZE];
+ struct snd_soc_tplg_tlv_dbscale scale;
+ };
} __attribute__((packed));
/*
@@ -155,9 +170,11 @@
} __attribute__((packed));
/*
- * Kcontrol Operations IDs
+ * Genericl Operations IDs, for binding Kcontrol or Bytes ext ops
+ * Kcontrol ops need get/put/info.
+ * Bytes ext ops need get/put.
*/
-struct snd_soc_tplg_kcontrol_ops_id {
+struct snd_soc_tplg_io_ops {
__le32 get;
__le32 put;
__le32 info;
@@ -171,8 +188,8 @@
__le32 type;
char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
__le32 access;
- struct snd_soc_tplg_kcontrol_ops_id ops;
- __le32 tlv_size; /* non zero means control has TLV data */
+ struct snd_soc_tplg_io_ops ops;
+ struct snd_soc_tplg_ctl_tlv tlv;
} __attribute__((packed));
/*
@@ -222,7 +239,7 @@
/*
* Manifest. List totals for each payload type. Not used in parsing, but will
* be passed to the component driver before any other objects in order for any
- * global componnent resource allocations.
+ * global component resource allocations.
*
* File block representation for manifest :-
* +-----------------------------------+----+
@@ -238,6 +255,7 @@
__le32 graph_elems; /* number of graph elements */
__le32 dai_elems; /* number of DAI elements */
__le32 dai_link_elems; /* number of DAI link elements */
+ struct snd_soc_tplg_private priv;
} __attribute__((packed));
/*
@@ -259,7 +277,6 @@
__le32 invert;
__le32 num_channels;
struct snd_soc_tplg_channel channel[SND_SOC_TPLG_MAX_CHAN];
- struct snd_soc_tplg_ctl_tlv tlv;
struct snd_soc_tplg_private priv;
} __attribute__((packed));
@@ -303,6 +320,7 @@
__le32 mask;
__le32 base;
__le32 num_regs;
+ struct snd_soc_tplg_io_ops ext_ops;
struct snd_soc_tplg_private priv;
} __attribute__((packed));
@@ -347,6 +365,7 @@
__le32 reg; /* negative reg = no direct dapm */
__le32 shift; /* bits to shift */
__le32 mask; /* non-shifted mask */
+ __le32 subseq; /* sort within widget type */
__u32 invert; /* invert the power bit */
__u32 ignore_suspend; /* kept enabled over suspend */
__u16 event_flags;
diff --git a/init/main.c b/init/main.c
index c5d5626..5650655 100644
--- a/init/main.c
+++ b/init/main.c
@@ -656,7 +656,7 @@
key_init();
security_init();
dbg_late_init();
- vfs_caches_init(totalram_pages);
+ vfs_caches_init();
signals_init();
/* rootfs populating might need page-writeback */
page_writeback_init();
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index a24ba9f..161a180 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -142,7 +142,6 @@
if (!leaf)
return -ENOMEM;
INIT_LIST_HEAD(&leaf->msg_list);
- info->qsize += sizeof(*leaf);
}
leaf->priority = msg->m_type;
rb_link_node(&leaf->rb_node, parent, p);
@@ -187,7 +186,6 @@
"lazy leaf delete!\n");
rb_erase(&leaf->rb_node, &info->msg_tree);
if (info->node_cache) {
- info->qsize -= sizeof(*leaf);
kfree(leaf);
} else {
info->node_cache = leaf;
@@ -200,7 +198,6 @@
if (list_empty(&leaf->msg_list)) {
rb_erase(&leaf->rb_node, &info->msg_tree);
if (info->node_cache) {
- info->qsize -= sizeof(*leaf);
kfree(leaf);
} else {
info->node_cache = leaf;
@@ -1034,7 +1031,6 @@
/* Save our speculative allocation into the cache */
INIT_LIST_HEAD(&new_leaf->msg_list);
info->node_cache = new_leaf;
- info->qsize += sizeof(*new_leaf);
new_leaf = NULL;
} else {
kfree(new_leaf);
@@ -1142,7 +1138,6 @@
/* Save our speculative allocation into the cache */
INIT_LIST_HEAD(&new_leaf->msg_list);
info->node_cache = new_leaf;
- info->qsize += sizeof(*new_leaf);
} else {
kfree(new_leaf);
}
diff --git a/ipc/sem.c b/ipc/sem.c
index bc3d530..b471e5a 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -253,6 +253,16 @@
}
/*
+ * spin_unlock_wait() and !spin_is_locked() are not memory barriers, they
+ * are only control barriers.
+ * The code must pair with spin_unlock(&sem->lock) or
+ * spin_unlock(&sem_perm.lock), thus just the control barrier is insufficient.
+ *
+ * smp_rmb() is sufficient, as writes cannot pass the control barrier.
+ */
+#define ipc_smp_acquire__after_spin_is_unlocked() smp_rmb()
+
+/*
* Wait until all currently ongoing simple ops have completed.
* Caller must own sem_perm.lock.
* New simple ops cannot start, because simple ops first check
@@ -275,6 +285,7 @@
sem = sma->sem_base + i;
spin_unlock_wait(&sem->lock);
}
+ ipc_smp_acquire__after_spin_is_unlocked();
}
/*
@@ -327,13 +338,12 @@
/* Then check that the global lock is free */
if (!spin_is_locked(&sma->sem_perm.lock)) {
/*
- * The ipc object lock check must be visible on all
- * cores before rechecking the complex count. Otherwise
- * we can race with another thread that does:
+ * We need a memory barrier with acquire semantics,
+ * otherwise we can race with another thread that does:
* complex_count++;
* spin_unlock(sem_perm.lock);
*/
- smp_rmb();
+ ipc_smp_acquire__after_spin_is_unlocked();
/*
* Now repeat the test of complex_count:
@@ -2074,17 +2084,28 @@
rcu_read_lock();
un = list_entry_rcu(ulp->list_proc.next,
struct sem_undo, list_proc);
- if (&un->list_proc == &ulp->list_proc)
- semid = -1;
- else
- semid = un->semid;
-
- if (semid == -1) {
+ if (&un->list_proc == &ulp->list_proc) {
+ /*
+ * We must wait for freeary() before freeing this ulp,
+ * in case we raced with last sem_undo. There is a small
+ * possibility where we exit while freeary() didn't
+ * finish unlocking sem_undo_list.
+ */
+ spin_unlock_wait(&ulp->lock);
rcu_read_unlock();
break;
}
+ spin_lock(&ulp->lock);
+ semid = un->semid;
+ spin_unlock(&ulp->lock);
- sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, un->semid);
+ /* exit_sem raced with IPC_RMID, nothing to do */
+ if (semid == -1) {
+ rcu_read_unlock();
+ continue;
+ }
+
+ sma = sem_obtain_object_check(tsk->nsproxy->ipc_ns, semid);
/* exit_sem raced with IPC_RMID, nothing to do */
if (IS_ERR(sma)) {
rcu_read_unlock();
@@ -2112,9 +2133,11 @@
ipc_assert_locked_object(&sma->sem_perm);
list_del(&un->list_id);
- spin_lock(&ulp->lock);
+ /* we are the last process using this ulp, acquiring ulp->lock
+ * isn't required. Besides that, we are also protected against
+ * IPC_RMID as we hold sma->sem_perm lock now
+ */
list_del_rcu(&un->list_proc);
- spin_unlock(&ulp->lock);
/* perform adjustments registered in un */
for (i = 0; i < sma->sem_nsems; i++) {
diff --git a/ipc/shm.c b/ipc/shm.c
index 06e5cf2..4aef24d 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -545,7 +545,7 @@
if ((shmflg & SHM_NORESERVE) &&
sysctl_overcommit_memory != OVERCOMMIT_NEVER)
acctflag = VM_NORESERVE;
- file = shmem_file_setup(name, size, acctflag);
+ file = shmem_kernel_file_setup(name, size, acctflag);
}
error = PTR_ERR(file);
if (IS_ERR(file))
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 5644ec5..964b4ef 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -191,21 +191,22 @@
void cpu_hotplug_disable(void)
{
cpu_maps_update_begin();
- cpu_hotplug_disabled = 1;
+ cpu_hotplug_disabled++;
cpu_maps_update_done();
}
+EXPORT_SYMBOL_GPL(cpu_hotplug_disable);
void cpu_hotplug_enable(void)
{
cpu_maps_update_begin();
- cpu_hotplug_disabled = 0;
+ WARN_ON(--cpu_hotplug_disabled < 0);
cpu_maps_update_done();
}
-
+EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
#endif /* CONFIG_HOTPLUG_CPU */
/* Need to know about CPUs going up/down? */
-int __ref register_cpu_notifier(struct notifier_block *nb)
+int register_cpu_notifier(struct notifier_block *nb)
{
int ret;
cpu_maps_update_begin();
@@ -214,7 +215,7 @@
return ret;
}
-int __ref __register_cpu_notifier(struct notifier_block *nb)
+int __register_cpu_notifier(struct notifier_block *nb)
{
return raw_notifier_chain_register(&cpu_chain, nb);
}
@@ -244,7 +245,7 @@
EXPORT_SYMBOL(register_cpu_notifier);
EXPORT_SYMBOL(__register_cpu_notifier);
-void __ref unregister_cpu_notifier(struct notifier_block *nb)
+void unregister_cpu_notifier(struct notifier_block *nb)
{
cpu_maps_update_begin();
raw_notifier_chain_unregister(&cpu_chain, nb);
@@ -252,7 +253,7 @@
}
EXPORT_SYMBOL(unregister_cpu_notifier);
-void __ref __unregister_cpu_notifier(struct notifier_block *nb)
+void __unregister_cpu_notifier(struct notifier_block *nb)
{
raw_notifier_chain_unregister(&cpu_chain, nb);
}
@@ -329,7 +330,7 @@
};
/* Take this CPU down. */
-static int __ref take_cpu_down(void *_param)
+static int take_cpu_down(void *_param)
{
struct take_cpu_down_param *param = _param;
int err;
@@ -348,7 +349,7 @@
}
/* Requires cpu_add_remove_lock to be held */
-static int __ref _cpu_down(unsigned int cpu, int tasks_frozen)
+static int _cpu_down(unsigned int cpu, int tasks_frozen)
{
int err, nr_calls = 0;
void *hcpu = (void *)(long)cpu;
@@ -442,7 +443,7 @@
return err;
}
-int __ref cpu_down(unsigned int cpu)
+int cpu_down(unsigned int cpu)
{
int err;
@@ -608,13 +609,18 @@
}
}
- if (!error) {
+ if (!error)
BUG_ON(num_online_cpus() > 1);
- /* Make sure the CPUs won't be enabled by someone else */
- cpu_hotplug_disabled = 1;
- } else {
+ else
pr_err("Non-boot CPUs are not disabled\n");
- }
+
+ /*
+ * Make sure the CPUs won't be enabled by someone else. We need to do
+ * this even in case of failure as all disable_nonboot_cpus() users are
+ * supposed to do enable_nonboot_cpus() on the failure path.
+ */
+ cpu_hotplug_disabled++;
+
cpu_maps_update_done();
return error;
}
@@ -627,13 +633,13 @@
{
}
-void __ref enable_nonboot_cpus(void)
+void enable_nonboot_cpus(void)
{
int cpu, error;
/* Allow everyone to use the CPU hotplug again */
cpu_maps_update_begin();
- cpu_hotplug_disabled = 0;
+ WARN_ON(--cpu_hotplug_disabled < 0);
if (cpumask_empty(frozen_cpus))
goto out;
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index ee14e3a..f0acff0 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1223,7 +1223,7 @@
spin_unlock_irq(&callback_lock);
/* use trialcs->mems_allowed as a temp variable */
- update_nodemasks_hier(cs, &cs->mems_allowed);
+ update_nodemasks_hier(cs, &trialcs->mems_allowed);
done:
return retval;
}
diff --git a/kernel/events/core.c b/kernel/events/core.c
index d3dae34..e6feb51 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1868,8 +1868,6 @@
perf_pmu_disable(event->pmu);
- event->tstamp_running += tstamp - event->tstamp_stopped;
-
perf_set_shadow_time(event, ctx, tstamp);
perf_log_itrace_start(event);
@@ -1881,6 +1879,8 @@
goto out;
}
+ event->tstamp_running += tstamp - event->tstamp_stopped;
+
if (!is_software_event(event))
cpuctx->active_oncpu++;
if (!ctx->nr_active++)
@@ -3958,28 +3958,21 @@
perf_event_for_each_child(sibling, func);
}
-static int perf_event_period(struct perf_event *event, u64 __user *arg)
-{
- struct perf_event_context *ctx = event->ctx;
- int ret = 0, active;
+struct period_event {
+ struct perf_event *event;
u64 value;
+};
- if (!is_sampling_event(event))
- return -EINVAL;
+static int __perf_event_period(void *info)
+{
+ struct period_event *pe = info;
+ struct perf_event *event = pe->event;
+ struct perf_event_context *ctx = event->ctx;
+ u64 value = pe->value;
+ bool active;
- if (copy_from_user(&value, arg, sizeof(value)))
- return -EFAULT;
-
- if (!value)
- return -EINVAL;
-
- raw_spin_lock_irq(&ctx->lock);
+ raw_spin_lock(&ctx->lock);
if (event->attr.freq) {
- if (value > sysctl_perf_event_sample_rate) {
- ret = -EINVAL;
- goto unlock;
- }
-
event->attr.sample_freq = value;
} else {
event->attr.sample_period = value;
@@ -3998,11 +3991,53 @@
event->pmu->start(event, PERF_EF_RELOAD);
perf_pmu_enable(ctx->pmu);
}
+ raw_spin_unlock(&ctx->lock);
-unlock:
+ return 0;
+}
+
+static int perf_event_period(struct perf_event *event, u64 __user *arg)
+{
+ struct period_event pe = { .event = event, };
+ struct perf_event_context *ctx = event->ctx;
+ struct task_struct *task;
+ u64 value;
+
+ if (!is_sampling_event(event))
+ return -EINVAL;
+
+ if (copy_from_user(&value, arg, sizeof(value)))
+ return -EFAULT;
+
+ if (!value)
+ return -EINVAL;
+
+ if (event->attr.freq && value > sysctl_perf_event_sample_rate)
+ return -EINVAL;
+
+ task = ctx->task;
+ pe.value = value;
+
+ if (!task) {
+ cpu_function_call(event->cpu, __perf_event_period, &pe);
+ return 0;
+ }
+
+retry:
+ if (!task_function_call(task, __perf_event_period, &pe))
+ return 0;
+
+ raw_spin_lock_irq(&ctx->lock);
+ if (ctx->is_active) {
+ raw_spin_unlock_irq(&ctx->lock);
+ task = ctx->task;
+ goto retry;
+ }
+
+ __perf_event_period(&pe);
raw_spin_unlock_irq(&ctx->lock);
- return ret;
+ return 0;
}
static const struct file_operations perf_fops;
@@ -4740,12 +4775,20 @@
* to user-space before waking everybody up.
*/
+static inline struct fasync_struct **perf_event_fasync(struct perf_event *event)
+{
+ /* only the parent has fasync state */
+ if (event->parent)
+ event = event->parent;
+ return &event->fasync;
+}
+
void perf_event_wakeup(struct perf_event *event)
{
ring_buffer_wakeup(event);
if (event->pending_kill) {
- kill_fasync(&event->fasync, SIGIO, event->pending_kill);
+ kill_fasync(perf_event_fasync(event), SIGIO, event->pending_kill);
event->pending_kill = 0;
}
}
@@ -6124,7 +6167,7 @@
else
perf_event_output(event, data, regs);
- if (event->fasync && event->pending_kill) {
+ if (*perf_event_fasync(event) && event->pending_kill) {
event->pending_wakeup = 1;
irq_work_queue(&event->pending);
}
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c
index b2be01b..c8aa3f7 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -559,11 +559,13 @@
rb->aux_priv = NULL;
}
- for (pg = 0; pg < rb->aux_nr_pages; pg++)
- rb_free_aux_page(rb, pg);
+ if (rb->aux_nr_pages) {
+ for (pg = 0; pg < rb->aux_nr_pages; pg++)
+ rb_free_aux_page(rb, pg);
- kfree(rb->aux_pages);
- rb->aux_nr_pages = 0;
+ kfree(rb->aux_pages);
+ rb->aux_nr_pages = 0;
+ }
}
void rb_free_aux(struct ring_buffer *rb)
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 27f4332..ae21682 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -985,6 +985,23 @@
}
/**
+ * irq_chip_set_type_parent - Set IRQ type on the parent interrupt
+ * @data: Pointer to interrupt specific data
+ * @type: IRQ_TYPE_{LEVEL,EDGE}_* value - see include/linux/irq.h
+ *
+ * Conditional, as the underlying parent chip might not implement it.
+ */
+int irq_chip_set_type_parent(struct irq_data *data, unsigned int type)
+{
+ data = data->parent_data;
+
+ if (data->chip->irq_set_type)
+ return data->chip->irq_set_type(data, type);
+
+ return -ENOSYS;
+}
+
+/**
* irq_chip_retrigger_hierarchy - Retrigger an interrupt in hardware
* @data: Pointer to interrupt specific data
*
@@ -997,7 +1014,7 @@
if (data->chip && data->chip->irq_retrigger)
return data->chip->irq_retrigger(data);
- return -ENOSYS;
+ return 0;
}
/**
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 10e489c..fdea0be 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -97,6 +97,7 @@
{
return test_bit(KTHREAD_SHOULD_PARK, &to_kthread(current)->flags);
}
+EXPORT_SYMBOL_GPL(kthread_should_park);
/**
* kthread_freezable_should_stop - should this freezable kthread return now?
@@ -171,6 +172,7 @@
{
__kthread_parkme(to_kthread(current));
}
+EXPORT_SYMBOL_GPL(kthread_parkme);
static int kthread(void *_create)
{
@@ -411,6 +413,7 @@
if (kthread)
__kthread_unpark(k, kthread);
}
+EXPORT_SYMBOL_GPL(kthread_unpark);
/**
* kthread_park - park a thread created by kthread_create().
@@ -441,6 +444,7 @@
}
return ret;
}
+EXPORT_SYMBOL_GPL(kthread_park);
/**
* kthread_stop - stop a thread created by kthread_create().
diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock_paravirt.h
index 04ab181..df19ae4 100644
--- a/kernel/locking/qspinlock_paravirt.h
+++ b/kernel/locking/qspinlock_paravirt.h
@@ -4,6 +4,7 @@
#include <linux/hash.h>
#include <linux/bootmem.h>
+#include <linux/debug_locks.h>
/*
* Implement paravirt qspinlocks; the general idea is to halt the vcpus instead
@@ -286,15 +287,23 @@
{
struct __qspinlock *l = (void *)lock;
struct pv_node *node;
+ u8 lockval = cmpxchg(&l->locked, _Q_LOCKED_VAL, 0);
/*
* We must not unlock if SLOW, because in that case we must first
* unhash. Otherwise it would be possible to have multiple @lock
* entries, which would be BAD.
*/
- if (likely(cmpxchg(&l->locked, _Q_LOCKED_VAL, 0) == _Q_LOCKED_VAL))
+ if (likely(lockval == _Q_LOCKED_VAL))
return;
+ if (unlikely(lockval != _Q_SLOW_VAL)) {
+ if (debug_locks_silent)
+ return;
+ WARN(1, "pvqspinlock: lock %p has corrupted value 0x%x!\n", lock, atomic_read(&lock->val));
+ return;
+ }
+
/*
* Since the above failed to release, this must be the SLOW path.
* Therefore start by looking up the blocked node and unhashing it.
diff --git a/kernel/module.c b/kernel/module.c
index 4d2b82e..b86b7bf 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -602,13 +602,16 @@
}
EXPORT_SYMBOL_GPL(find_symbol);
-/* Search for module by name: must hold module_mutex. */
+/*
+ * Search for module by name: must hold module_mutex (or preempt disabled
+ * for read-only access).
+ */
static struct module *find_module_all(const char *name, size_t len,
bool even_unformed)
{
struct module *mod;
- module_assert_mutex();
+ module_assert_mutex_or_preempt();
list_for_each_entry(mod, &modules, list) {
if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
@@ -621,6 +624,7 @@
struct module *find_module(const char *name)
{
+ module_assert_mutex();
return find_module_all(name, strlen(name), false);
}
EXPORT_SYMBOL_GPL(find_module);
diff --git a/kernel/resource.c b/kernel/resource.c
index 90552aa..fed052a 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -504,13 +504,13 @@
{
struct resource *p;
resource_size_t end = start + size - 1;
- int flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+ unsigned long flags = IORESOURCE_MEM | IORESOURCE_BUSY;
const char *name = "System RAM";
int ret = -1;
read_lock(&resource_lock);
for (p = iomem_resource.child; p ; p = p->sibling) {
- if (end < p->start)
+ if (p->end < start)
continue;
if (p->start <= start && end <= p->end) {
@@ -521,7 +521,7 @@
ret = 1;
break;
}
- if (p->end < start)
+ if (end < p->start)
break; /* not found */
}
read_unlock(&resource_lock);
diff --git a/kernel/signal.c b/kernel/signal.c
index 836df8d..0f6bbbe 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2748,12 +2748,15 @@
* Other callers might not initialize the si_lsb field,
* so check explicitly for the right codes here.
*/
- if (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO)
+ if (from->si_signo == SIGBUS &&
+ (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
#endif
#ifdef SEGV_BNDERR
- err |= __put_user(from->si_lower, &to->si_lower);
- err |= __put_user(from->si_upper, &to->si_upper);
+ if (from->si_signo == SIGSEGV && from->si_code == SEGV_BNDERR) {
+ err |= __put_user(from->si_lower, &to->si_lower);
+ err |= __put_user(from->si_upper, &to->si_upper);
+ }
#endif
break;
case __SI_CHLD:
@@ -3017,7 +3020,7 @@
int, sig,
struct compat_siginfo __user *, uinfo)
{
- siginfo_t info;
+ siginfo_t info = {};
int ret = copy_siginfo_from_user32(&info, uinfo);
if (unlikely(ret))
return ret;
@@ -3061,7 +3064,7 @@
int, sig,
struct compat_siginfo __user *, uinfo)
{
- siginfo_t info;
+ siginfo_t info = {};
if (copy_siginfo_from_user32(&info, uinfo))
return -EFAULT;
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index 5e097fa..84190f0 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -807,8 +807,8 @@
spin_unlock(&base->lock);
base = new_base;
spin_lock(&base->lock);
- timer->flags &= ~TIMER_BASEMASK;
- timer->flags |= base->cpu;
+ WRITE_ONCE(timer->flags,
+ (timer->flags & ~TIMER_BASEMASK) | base->cpu);
}
}
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 02bece4..eb11011 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -98,6 +98,13 @@
struct pid *pid;
};
+static bool ftrace_pids_enabled(void)
+{
+ return !list_empty(&ftrace_pids);
+}
+
+static void ftrace_update_trampoline(struct ftrace_ops *ops);
+
/*
* ftrace_disabled is set when an anomaly is discovered.
* ftrace_disabled is much stronger than ftrace_enabled.
@@ -109,7 +116,6 @@
static struct ftrace_ops *ftrace_control_list __read_mostly = &ftrace_list_end;
static struct ftrace_ops *ftrace_ops_list __read_mostly = &ftrace_list_end;
ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub;
-ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
static struct ftrace_ops global_ops;
static struct ftrace_ops control_ops;
@@ -183,14 +189,7 @@
if (!test_tsk_trace_trace(current))
return;
- ftrace_pid_function(ip, parent_ip, op, regs);
-}
-
-static void set_ftrace_pid_function(ftrace_func_t func)
-{
- /* do not set ftrace_pid_function to itself! */
- if (func != ftrace_pid_func)
- ftrace_pid_function = func;
+ op->saved_func(ip, parent_ip, op, regs);
}
/**
@@ -202,7 +201,6 @@
void clear_ftrace_function(void)
{
ftrace_trace_function = ftrace_stub;
- ftrace_pid_function = ftrace_stub;
}
static void control_ops_disable_all(struct ftrace_ops *ops)
@@ -436,6 +434,12 @@
} else
add_ftrace_ops(&ftrace_ops_list, ops);
+ /* Always save the function, and reset at unregistering */
+ ops->saved_func = ops->func;
+
+ if (ops->flags & FTRACE_OPS_FL_PID && ftrace_pids_enabled())
+ ops->func = ftrace_pid_func;
+
ftrace_update_trampoline(ops);
if (ftrace_enabled)
@@ -463,15 +467,28 @@
if (ftrace_enabled)
update_ftrace_function();
+ ops->func = ops->saved_func;
+
return 0;
}
static void ftrace_update_pid_func(void)
{
+ bool enabled = ftrace_pids_enabled();
+ struct ftrace_ops *op;
+
/* Only do something if we are tracing something */
if (ftrace_trace_function == ftrace_stub)
return;
+ do_for_each_ftrace_op(op, ftrace_ops_list) {
+ if (op->flags & FTRACE_OPS_FL_PID) {
+ op->func = enabled ? ftrace_pid_func :
+ op->saved_func;
+ ftrace_update_trampoline(op);
+ }
+ } while_for_each_ftrace_op(op);
+
update_ftrace_function();
}
@@ -1133,7 +1150,8 @@
.local_hash.filter_hash = EMPTY_HASH,
INIT_OPS_HASH(global_ops)
.flags = FTRACE_OPS_FL_RECURSION_SAFE |
- FTRACE_OPS_FL_INITIALIZED,
+ FTRACE_OPS_FL_INITIALIZED |
+ FTRACE_OPS_FL_PID,
};
/*
@@ -5023,7 +5041,9 @@
static struct ftrace_ops global_ops = {
.func = ftrace_stub,
- .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED,
+ .flags = FTRACE_OPS_FL_RECURSION_SAFE |
+ FTRACE_OPS_FL_INITIALIZED |
+ FTRACE_OPS_FL_PID,
};
static int __init ftrace_nodyn_init(void)
@@ -5080,11 +5100,6 @@
if (WARN_ON(tr->ops->func != ftrace_stub))
printk("ftrace ops had %pS for function\n",
tr->ops->func);
- /* Only the top level instance does pid tracing */
- if (!list_empty(&ftrace_pids)) {
- set_ftrace_pid_function(func);
- func = ftrace_pid_func;
- }
}
tr->ops->func = func;
tr->ops->private = tr;
@@ -5371,7 +5386,7 @@
{
mutex_lock(&ftrace_lock);
- if (list_empty(&ftrace_pids) && (!*pos))
+ if (!ftrace_pids_enabled() && (!*pos))
return (void *) 1;
return seq_list_start(&ftrace_pids, *pos);
@@ -5610,6 +5625,7 @@
.func = ftrace_stub,
.flags = FTRACE_OPS_FL_RECURSION_SAFE |
FTRACE_OPS_FL_INITIALIZED |
+ FTRACE_OPS_FL_PID |
FTRACE_OPS_FL_STUB,
#ifdef FTRACE_GRAPH_TRAMP_ADDR
.trampoline = FTRACE_GRAPH_TRAMP_ADDR,
diff --git a/lib/iommu-common.c b/lib/iommu-common.c
index df30632..ff19f66 100644
--- a/lib/iommu-common.c
+++ b/lib/iommu-common.c
@@ -119,7 +119,7 @@
unsigned long align_mask = 0;
if (align_order > 0)
- align_mask = 0xffffffffffffffffl >> (64 - align_order);
+ align_mask = ~0ul >> (BITS_PER_LONG - align_order);
/* Sanity check */
if (unlikely(npages == 0)) {
diff --git a/mm/cma.h b/mm/cma.h
index 1132d73..17c75a4 100644
--- a/mm/cma.h
+++ b/mm/cma.h
@@ -16,7 +16,7 @@
extern struct cma cma_areas[MAX_CMA_AREAS];
extern unsigned cma_area_count;
-static unsigned long cma_bitmap_maxno(struct cma *cma)
+static inline unsigned long cma_bitmap_maxno(struct cma *cma)
{
return cma->count >> cma->order_per_bit;
}
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index c107094..097c7a4 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1676,12 +1676,7 @@
/* after clearing PageTail the gup refcount can be released */
smp_mb__after_atomic();
- /*
- * retain hwpoison flag of the poisoned tail page:
- * fix for the unsuitable process killed on Guest Machine(KVM)
- * by the memory-failure.
- */
- page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP | __PG_HWPOISON;
+ page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
page_tail->flags |= (page->flags &
((1L << PG_referenced) |
(1L << PG_swapbacked) |
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index 6c513a6..7b28e9cd 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -2,7 +2,7 @@
* This file contains shadow memory manipulation code.
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
- * Author: Andrey Ryabinin <a.ryabinin@samsung.com>
+ * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
*
* Some of code borrowed from https://github.com/xairy/linux by
* Andrey Konovalov <adech.fo@gmail.com>
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 680ceed..e07c94f 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -2,7 +2,7 @@
* This file contains error reporting code.
*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
- * Author: Andrey Ryabinin <a.ryabinin@samsung.com>
+ * Author: Andrey Ryabinin <ryabinin.a.a@gmail.com>
*
* Some of code borrowed from https://github.com/xairy/linux by
* Andrey Konovalov <adech.fo@gmail.com>
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index c53543d..1f4446a9 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -909,6 +909,18 @@
* directly for tail pages.
*/
if (PageTransHuge(head)) {
+ /*
+ * Non anonymous thp exists only in allocation/free time. We
+ * can't handle such a case correctly, so let's give it up.
+ * This should be better than triggering BUG_ON when kernel
+ * tries to touch the "partially handled" page.
+ */
+ if (!PageAnon(head)) {
+ pr_err("MCE: %#lx: non anonymous thp\n",
+ page_to_pfn(page));
+ return 0;
+ }
+
if (get_page_unless_zero(head)) {
if (PageTail(page))
get_page(page);
@@ -1134,17 +1146,11 @@
}
if (!PageHuge(p) && PageTransHuge(hpage)) {
- if (!PageAnon(hpage)) {
- pr_err("MCE: %#lx: non anonymous thp\n", pfn);
- if (TestClearPageHWPoison(p))
- atomic_long_sub(nr_pages, &num_poisoned_pages);
- put_page(p);
- if (p != hpage)
- put_page(hpage);
- return -EBUSY;
- }
- if (unlikely(split_huge_page(hpage))) {
- pr_err("MCE: %#lx: thp split failed\n", pfn);
+ if (!PageAnon(hpage) || unlikely(split_huge_page(hpage))) {
+ if (!PageAnon(hpage))
+ pr_err("MCE: %#lx: non anonymous thp\n", pfn);
+ else
+ pr_err("MCE: %#lx: thp split failed\n", pfn);
if (TestClearPageHWPoison(p))
atomic_long_sub(nr_pages, &num_poisoned_pages);
put_page(p);
@@ -1209,9 +1215,9 @@
if (!PageHWPoison(p)) {
printk(KERN_ERR "MCE %#lx: just unpoisoned\n", pfn);
atomic_long_sub(nr_pages, &num_poisoned_pages);
+ unlock_page(hpage);
put_page(hpage);
- res = 0;
- goto out;
+ return 0;
}
if (hwpoison_filter(p)) {
if (TestClearPageHWPoison(p))
@@ -1535,6 +1541,8 @@
*/
ret = __get_any_page(page, pfn, 0);
if (!PageLRU(page)) {
+ /* Drop page reference which is from __get_any_page() */
+ put_page(page);
pr_info("soft_offline: %#lx: unknown non LRU page type %lx\n",
pfn, page->flags);
return -EIO;
@@ -1564,13 +1572,12 @@
unlock_page(hpage);
ret = isolate_huge_page(hpage, &pagelist);
- if (ret) {
- /*
- * get_any_page() and isolate_huge_page() takes a refcount each,
- * so need to drop one here.
- */
- put_page(hpage);
- } else {
+ /*
+ * get_any_page() and isolate_huge_page() takes a refcount each,
+ * so need to drop one here.
+ */
+ put_page(hpage);
+ if (!ret) {
pr_info("soft offline: %#lx hugepage failed to isolate\n", pfn);
return -EBUSY;
}
@@ -1656,6 +1663,8 @@
inc_zone_page_state(page, NR_ISOLATED_ANON +
page_is_file_cache(page));
list_add(&page->lru, &pagelist);
+ if (!TestSetPageHWPoison(page))
+ atomic_long_inc(&num_poisoned_pages);
ret = migrate_pages(&pagelist, new_page, NULL, MPOL_MF_MOVE_ALL,
MIGRATE_SYNC, MR_MEMORY_FAILURE);
if (ret) {
@@ -1670,9 +1679,8 @@
pfn, ret, page->flags);
if (ret > 0)
ret = -EIO;
- } else {
- SetPageHWPoison(page);
- atomic_long_inc(&num_poisoned_pages);
+ if (TestClearPageHWPoison(page))
+ atomic_long_dec(&num_poisoned_pages);
}
} else {
pr_info("soft offline: %#lx: isolation failed: %d, page count %d, type %lx\n",
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 26fbba7..6da82bc 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -446,7 +446,7 @@
int nr_pages = PAGES_PER_SECTION;
int nid = pgdat->node_id;
int zone_type;
- unsigned long flags;
+ unsigned long flags, pfn;
int ret;
zone_type = zone - pgdat->node_zones;
@@ -461,6 +461,14 @@
pgdat_resize_unlock(zone->zone_pgdat, &flags);
memmap_init_zone(nr_pages, nid, zone_type,
phys_start_pfn, MEMMAP_HOTPLUG);
+
+ /* online_page_range is called later and expects pages reserved */
+ for (pfn = phys_start_pfn; pfn < phys_start_pfn + nr_pages; pfn++) {
+ if (!pfn_valid(pfn))
+ continue;
+
+ SetPageReserved(pfn_to_page(pfn));
+ }
return 0;
}
@@ -1269,6 +1277,7 @@
/* create new memmap entry */
firmware_map_add_hotplug(start, start + size, "System RAM");
+ memblock_add_node(start, size, nid);
goto out;
@@ -2005,6 +2014,8 @@
/* remove memmap entry */
firmware_map_remove(start, start + size, "System RAM");
+ memblock_free(start, size);
+ memblock_remove(start, size);
arch_remove_memory(start, size);
diff --git a/mm/migrate.c b/mm/migrate.c
index ee401e4..eb42671 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -880,7 +880,8 @@
/* Establish migration ptes or remove ptes */
if (page_mapped(page)) {
try_to_unmap(page,
- TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS);
+ TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS|
+ TTU_IGNORE_HWPOISON);
page_was_mapped = 1;
}
@@ -950,7 +951,10 @@
list_del(&page->lru);
dec_zone_page_state(page, NR_ISOLATED_ANON +
page_is_file_cache(page));
- if (reason != MR_MEMORY_FAILURE)
+ /* Soft-offlined page shouldn't go through lru cache list */
+ if (reason == MR_MEMORY_FAILURE)
+ put_page(page);
+ else
putback_lru_page(page);
}
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 22cddd3..5cccc12 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2063,10 +2063,10 @@
*/
void __init page_writeback_init(void)
{
+ BUG_ON(wb_domain_init(&global_wb_domain, GFP_KERNEL));
+
writeback_set_ratelimit();
register_cpu_notifier(&ratelimit_nb);
-
- BUG_ON(wb_domain_init(&global_wb_domain, GFP_KERNEL));
}
/**
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ef19f22..5b5240b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -18,7 +18,6 @@
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/interrupt.h>
-#include <linux/rwsem.h>
#include <linux/pagemap.h>
#include <linux/jiffies.h>
#include <linux/bootmem.h>
@@ -981,21 +980,21 @@
#if defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) || \
defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP)
-/* Only safe to use early in boot when initialisation is single-threaded */
+
static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata;
int __meminit early_pfn_to_nid(unsigned long pfn)
{
+ static DEFINE_SPINLOCK(early_pfn_lock);
int nid;
- /* The system will behave unpredictably otherwise */
- BUG_ON(system_state != SYSTEM_BOOTING);
-
+ spin_lock(&early_pfn_lock);
nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache);
- if (nid >= 0)
- return nid;
- /* just returns 0 */
- return 0;
+ if (nid < 0)
+ nid = 0;
+ spin_unlock(&early_pfn_lock);
+
+ return nid;
}
#endif
@@ -1060,7 +1059,15 @@
__free_pages_boot_core(page, pfn, 0);
}
-static __initdata DECLARE_RWSEM(pgdat_init_rwsem);
+/* Completion tracking for deferred_init_memmap() threads */
+static atomic_t pgdat_init_n_undone __initdata;
+static __initdata DECLARE_COMPLETION(pgdat_init_all_done_comp);
+
+static inline void __init pgdat_init_report_one_done(void)
+{
+ if (atomic_dec_and_test(&pgdat_init_n_undone))
+ complete(&pgdat_init_all_done_comp);
+}
/* Initialise remaining memory on a node */
static int __init deferred_init_memmap(void *data)
@@ -1077,7 +1084,7 @@
const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id);
if (first_init_pfn == ULONG_MAX) {
- up_read(&pgdat_init_rwsem);
+ pgdat_init_report_one_done();
return 0;
}
@@ -1177,7 +1184,8 @@
pr_info("node %d initialised, %lu pages in %ums\n", nid, nr_pages,
jiffies_to_msecs(jiffies - start));
- up_read(&pgdat_init_rwsem);
+
+ pgdat_init_report_one_done();
return 0;
}
@@ -1185,14 +1193,17 @@
{
int nid;
+ /* There will be num_node_state(N_MEMORY) threads */
+ atomic_set(&pgdat_init_n_undone, num_node_state(N_MEMORY));
for_each_node_state(nid, N_MEMORY) {
- down_read(&pgdat_init_rwsem);
kthread_run(deferred_init_memmap, NODE_DATA(nid), "pgdatinit%d", nid);
}
/* Block until all are initialised */
- down_write(&pgdat_init_rwsem);
- up_write(&pgdat_init_rwsem);
+ wait_for_completion(&pgdat_init_all_done_comp);
+
+ /* Reinit limits that are based on free pages after the kernel is up */
+ files_maxfiles_init();
}
#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
@@ -1285,6 +1296,10 @@
bad_reason = "non-NULL mapping";
if (unlikely(atomic_read(&page->_count) != 0))
bad_reason = "nonzero _count";
+ if (unlikely(page->flags & __PG_HWPOISON)) {
+ bad_reason = "HWPoisoned (hardware-corrupted)";
+ bad_flags = __PG_HWPOISON;
+ }
if (unlikely(page->flags & PAGE_FLAGS_CHECK_AT_PREP)) {
bad_reason = "PAGE_FLAGS_CHECK_AT_PREP flag set";
bad_flags = PAGE_FLAGS_CHECK_AT_PREP;
@@ -1328,12 +1343,15 @@
set_page_owner(page, order, gfp_flags);
/*
- * page->pfmemalloc is set when ALLOC_NO_WATERMARKS was necessary to
+ * page is set pfmemalloc when ALLOC_NO_WATERMARKS was necessary to
* allocate the page. The expectation is that the caller is taking
* steps that will free more memory. The caller should avoid the page
* being used for !PFMEMALLOC purposes.
*/
- page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS);
+ if (alloc_flags & ALLOC_NO_WATERMARKS)
+ set_page_pfmemalloc(page);
+ else
+ clear_page_pfmemalloc(page);
return 0;
}
@@ -3330,7 +3348,7 @@
atomic_add(size - 1, &page->_count);
/* reset page count bias and offset to start of new frag */
- nc->pfmemalloc = page->pfmemalloc;
+ nc->pfmemalloc = page_is_pfmemalloc(page);
nc->pagecnt_bias = size;
nc->offset = size;
}
@@ -5045,6 +5063,10 @@
{
unsigned long zone_start_pfn, zone_end_pfn;
+ /* When hotadd a new node, the node should be empty */
+ if (!node_start_pfn && !node_end_pfn)
+ return 0;
+
/* Get the start and end of the zone */
zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type];
zone_end_pfn = arch_zone_highest_possible_pfn[zone_type];
@@ -5108,6 +5130,10 @@
unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type];
unsigned long zone_start_pfn, zone_end_pfn;
+ /* When hotadd a new node, the node should be empty */
+ if (!node_start_pfn && !node_end_pfn)
+ return 0;
+
zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high);
zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high);
diff --git a/mm/shmem.c b/mm/shmem.c
index 4caf8ed..dbe0c1e 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -3363,8 +3363,8 @@
* shmem_kernel_file_setup - get an unlinked file living in tmpfs which must be
* kernel internal. There will be NO LSM permission checks against the
* underlying inode. So users of this interface must do LSM checks at a
- * higher layer. The one user is the big_key implementation. LSM checks
- * are provided at the key level rather than the inode level.
+ * higher layer. The users are the big_key and shm implementations. LSM
+ * checks are provided at the key or shm level rather than the inode.
* @name: name for dentry (to be seen in /proc/<pid>/maps
* @size: size to be set for the file
* @flags: VM_NORESERVE suppresses pre-accounting of the entire object size
diff --git a/mm/slab.c b/mm/slab.c
index 200e224..bbd0b47 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1603,7 +1603,7 @@
}
/* Record if ALLOC_NO_WATERMARKS was set when allocating the slab */
- if (unlikely(page->pfmemalloc))
+ if (page_is_pfmemalloc(page))
pfmemalloc_active = true;
nr_pages = (1 << cachep->gfporder);
@@ -1614,7 +1614,7 @@
add_zone_page_state(page_zone(page),
NR_SLAB_UNRECLAIMABLE, nr_pages);
__SetPageSlab(page);
- if (page->pfmemalloc)
+ if (page_is_pfmemalloc(page))
SetPageSlabPfmemalloc(page);
if (kmemcheck_enabled && !(cachep->flags & SLAB_NOTRACK)) {
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 3e5f8f2..8683110 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -37,8 +37,7 @@
SLAB_TRACE | SLAB_DESTROY_BY_RCU | SLAB_NOLEAKTRACE | \
SLAB_FAILSLAB)
-#define SLAB_MERGE_SAME (SLAB_DEBUG_FREE | SLAB_RECLAIM_ACCOUNT | \
- SLAB_CACHE_DMA | SLAB_NOTRACK)
+#define SLAB_MERGE_SAME (SLAB_RECLAIM_ACCOUNT | SLAB_CACHE_DMA | SLAB_NOTRACK)
/*
* Merge control. If this is set then no merging of slab caches will occur.
diff --git a/mm/slub.c b/mm/slub.c
index 816df00..f68c0e5 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1427,7 +1427,7 @@
inc_slabs_node(s, page_to_nid(page), page->objects);
page->slab_cache = s;
__SetPageSlab(page);
- if (page->pfmemalloc)
+ if (page_is_pfmemalloc(page))
SetPageSlabPfmemalloc(page);
start = page_address(page);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index e61445d..8286938 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -973,22 +973,18 @@
* caller can stall after page list has been processed.
*
* 2) Global or new memcg reclaim encounters a page that is
- * not marked for immediate reclaim or the caller does not
- * have __GFP_IO. In this case mark the page for immediate
+ * not marked for immediate reclaim, or the caller does not
+ * have __GFP_FS (or __GFP_IO if it's simply going to swap,
+ * not to fs). In this case mark the page for immediate
* reclaim and continue scanning.
*
- * __GFP_IO is checked because a loop driver thread might
+ * Require may_enter_fs because we would wait on fs, which
+ * may not have submitted IO yet. And the loop driver might
* enter reclaim, and deadlock if it waits on a page for
* which it is needed to do the write (loop masks off
* __GFP_IO|__GFP_FS for this reason); but more thought
* would probably show more reasons.
*
- * Don't require __GFP_FS, since we're not going into the
- * FS, just waiting on its writeback completion. Worryingly,
- * ext4 gfs2 and xfs allocate pages with
- * grab_cache_page_write_begin(,,AOP_FLAG_NOFS), so testing
- * may_enter_fs here is liable to OOM on them.
- *
* 3) Legacy memcg encounters a page that is not already marked
* PageReclaim. memcg does not have any dirty pages
* throttling so we could easily OOM just because too many
@@ -1005,7 +1001,7 @@
/* Case 2 above */
} else if (sane_reclaim(sc) ||
- !PageReclaim(page) || !(sc->gfp_mask & __GFP_IO)) {
+ !PageReclaim(page) || !may_enter_fs) {
/*
* This is slightly racy - end_page_writeback()
* might have just cleared PageReclaim, then
diff --git a/net/9p/client.c b/net/9p/client.c
index 498454b..ea79ee9 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -1541,6 +1541,7 @@
struct p9_client *clnt = fid->clnt;
struct p9_req_t *req;
int total = 0;
+ *err = 0;
p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n",
fid->fid, (unsigned long long) offset, (int)iov_iter_count(to));
@@ -1620,6 +1621,7 @@
struct p9_client *clnt = fid->clnt;
struct p9_req_t *req;
int total = 0;
+ *err = 0;
p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n",
fid->fid, (unsigned long long) offset,
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 9dd49ca..6e70ddb 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -704,6 +704,7 @@
mutex_unlock(&virtio_9p_lock);
+ vdev->config->reset(vdev);
vdev->config->del_vqs(vdev);
sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr);
diff --git a/net/ax25/ax25_subr.c b/net/ax25/ax25_subr.c
index 1997538..3b78e84 100644
--- a/net/ax25/ax25_subr.c
+++ b/net/ax25/ax25_subr.c
@@ -264,6 +264,7 @@
{
ax25_clear_queues(ax25);
+ ax25_stop_heartbeat(ax25);
ax25_stop_t1timer(ax25);
ax25_stop_t2timer(ax25);
ax25_stop_t3timer(ax25);
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index fb54e6a..6d0b471 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -1138,6 +1138,9 @@
* @bat_priv: the bat priv with all the soft interface information
* @skb: packet to check
* @hdr_size: size of the encapsulation header
+ *
+ * Returns true if the packet was snooped and consumed by DAT. False if the
+ * packet has to be delivered to the interface
*/
bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
struct sk_buff *skb, int hdr_size)
@@ -1145,7 +1148,7 @@
uint16_t type;
__be32 ip_src, ip_dst;
uint8_t *hw_src, *hw_dst;
- bool ret = false;
+ bool dropped = false;
unsigned short vid;
if (!atomic_read(&bat_priv->distributed_arp_table))
@@ -1174,12 +1177,17 @@
/* if this REPLY is directed to a client of mine, let's deliver the
* packet to the interface
*/
- ret = !batadv_is_my_client(bat_priv, hw_dst, vid);
+ dropped = !batadv_is_my_client(bat_priv, hw_dst, vid);
+
+ /* if this REPLY is sent on behalf of a client of mine, let's drop the
+ * packet because the client will reply by itself
+ */
+ dropped |= batadv_is_my_client(bat_priv, hw_src, vid);
out:
- if (ret)
+ if (dropped)
kfree_skb(skb);
- /* if ret == false -> packet has to be delivered to the interface */
- return ret;
+ /* if dropped == false -> deliver to the interface */
+ return dropped;
}
/**
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
index bb015862..cffa92d 100644
--- a/net/batman-adv/gateway_client.c
+++ b/net/batman-adv/gateway_client.c
@@ -439,6 +439,8 @@
INIT_HLIST_NODE(&gw_node->list);
gw_node->orig_node = orig_node;
+ gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
+ gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
atomic_set(&gw_node->refcount, 1);
spin_lock_bh(&bat_priv->gw.list_lock);
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
index c002961..a2fc843 100644
--- a/net/batman-adv/soft-interface.c
+++ b/net/batman-adv/soft-interface.c
@@ -479,6 +479,9 @@
*/
void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
{
+ if (!vlan)
+ return;
+
if (atomic_dec_and_test(&vlan->refcount)) {
spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
hlist_del_rcu(&vlan->list);
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index b482495..5809b39 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -594,6 +594,12 @@
/* increase the refcounter of the related vlan */
vlan = batadv_softif_vlan_get(bat_priv, vid);
+ if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d",
+ addr, BATADV_PRINT_VID(vid))) {
+ kfree(tt_local);
+ tt_local = NULL;
+ goto out;
+ }
batadv_dbg(BATADV_DBG_TT, bat_priv,
"Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
@@ -1034,6 +1040,7 @@
struct batadv_tt_local_entry *tt_local_entry;
uint16_t flags, curr_flags = BATADV_NO_FLAGS;
struct batadv_softif_vlan *vlan;
+ void *tt_entry_exists;
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
if (!tt_local_entry)
@@ -1061,11 +1068,22 @@
* immediately purge it
*/
batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
- hlist_del_rcu(&tt_local_entry->common.hash_entry);
+
+ tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash,
+ batadv_compare_tt,
+ batadv_choose_tt,
+ &tt_local_entry->common);
+ if (!tt_entry_exists)
+ goto out;
+
+ /* extra call to free the local tt entry */
batadv_tt_local_entry_free_ref(tt_local_entry);
/* decrease the reference held for this vlan */
vlan = batadv_softif_vlan_get(bat_priv, vid);
+ if (!vlan)
+ goto out;
+
batadv_softif_vlan_free_ref(vlan);
batadv_softif_vlan_free_ref(vlan);
@@ -1166,8 +1184,10 @@
/* decrease the reference held for this vlan */
vlan = batadv_softif_vlan_get(bat_priv,
tt_common_entry->vid);
- batadv_softif_vlan_free_ref(vlan);
- batadv_softif_vlan_free_ref(vlan);
+ if (vlan) {
+ batadv_softif_vlan_free_ref(vlan);
+ batadv_softif_vlan_free_ref(vlan);
+ }
batadv_tt_local_entry_free_ref(tt_local);
}
@@ -3207,8 +3227,10 @@
/* decrease the reference held for this vlan */
vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid);
- batadv_softif_vlan_free_ref(vlan);
- batadv_softif_vlan_free_ref(vlan);
+ if (vlan) {
+ batadv_softif_vlan_free_ref(vlan);
+ batadv_softif_vlan_free_ref(vlan);
+ }
batadv_tt_local_entry_free_ref(tt_local);
}
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 7998fb2..92720f3 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -7820,7 +7820,7 @@
/* Make sure we copy only the significant bytes based on the
* encryption key size, and set the rest of the value to zeroes.
*/
- memcpy(ev.key.val, key->val, sizeof(key->enc_size));
+ memcpy(ev.key.val, key->val, key->enc_size);
memset(ev.key.val + key->enc_size, 0,
sizeof(ev.key.val) - key->enc_size);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 3d0f7d2..ad82324 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -2312,6 +2312,10 @@
return 1;
chan = conn->smp;
+ if (!chan) {
+ BT_ERR("SMP security requested but not available");
+ return 1;
+ }
if (!hci_dev_test_flag(hcon->hdev, HCI_LE_ENABLED))
return 1;
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 0ff6e1b..fa7bfce 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -37,15 +37,30 @@
int br_dev_queue_push_xmit(struct sock *sk, struct sk_buff *skb)
{
- if (!is_skb_forwardable(skb->dev, skb)) {
- kfree_skb(skb);
- } else {
- skb_push(skb, ETH_HLEN);
- br_drop_fake_rtable(skb);
- skb_sender_cpu_clear(skb);
- dev_queue_xmit(skb);
+ if (!is_skb_forwardable(skb->dev, skb))
+ goto drop;
+
+ skb_push(skb, ETH_HLEN);
+ br_drop_fake_rtable(skb);
+ skb_sender_cpu_clear(skb);
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL &&
+ (skb->protocol == htons(ETH_P_8021Q) ||
+ skb->protocol == htons(ETH_P_8021AD))) {
+ int depth;
+
+ if (!__vlan_get_protocol(skb, skb->protocol, &depth))
+ goto drop;
+
+ skb_set_network_header(skb, depth);
}
+ dev_queue_xmit(skb);
+
+ return 0;
+
+drop:
+ kfree_skb(skb);
return 0;
}
EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index c11cf26..c943219 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -351,7 +351,6 @@
if (state == MDB_TEMPORARY)
mod_timer(&p->timer, now + br->multicast_membership_interval);
- br_mdb_notify(br->dev, port, group, RTM_NEWMDB);
return 0;
}
@@ -446,6 +445,7 @@
if (p->port->state == BR_STATE_DISABLED)
goto unlock;
+ entry->state = p->state;
rcu_assign_pointer(*pp, p->next);
hlist_del_init(&p->mglist);
del_timer(&p->timer);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 742a6c2..1285eaf 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -39,6 +39,16 @@
struct bridge_mcast_own_query *query);
static void br_multicast_add_router(struct net_bridge *br,
struct net_bridge_port *port);
+static void br_ip4_multicast_leave_group(struct net_bridge *br,
+ struct net_bridge_port *port,
+ __be32 group,
+ __u16 vid);
+#if IS_ENABLED(CONFIG_IPV6)
+static void br_ip6_multicast_leave_group(struct net_bridge *br,
+ struct net_bridge_port *port,
+ const struct in6_addr *group,
+ __u16 vid);
+#endif
unsigned int br_mdb_rehash_seq;
static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
@@ -1010,9 +1020,15 @@
continue;
}
- err = br_ip4_multicast_add_group(br, port, group, vid);
- if (err)
- break;
+ if ((type == IGMPV3_CHANGE_TO_INCLUDE ||
+ type == IGMPV3_MODE_IS_INCLUDE) &&
+ ntohs(grec->grec_nsrcs) == 0) {
+ br_ip4_multicast_leave_group(br, port, group, vid);
+ } else {
+ err = br_ip4_multicast_add_group(br, port, group, vid);
+ if (err)
+ break;
+ }
}
return err;
@@ -1071,10 +1087,17 @@
continue;
}
- err = br_ip6_multicast_add_group(br, port, &grec->grec_mca,
- vid);
- if (err)
- break;
+ if ((grec->grec_type == MLD2_CHANGE_TO_INCLUDE ||
+ grec->grec_type == MLD2_MODE_IS_INCLUDE) &&
+ ntohs(*nsrcs) == 0) {
+ br_ip6_multicast_leave_group(br, port, &grec->grec_mca,
+ vid);
+ } else {
+ err = br_ip6_multicast_add_group(br, port,
+ &grec->grec_mca, vid);
+ if (!err)
+ break;
+ }
}
return err;
@@ -1393,8 +1416,7 @@
spin_lock(&br->multicast_lock);
if (!netif_running(br->dev) ||
- (port && port->state == BR_STATE_DISABLED) ||
- timer_pending(&other_query->timer))
+ (port && port->state == BR_STATE_DISABLED))
goto out;
mdb = mlock_dereference(br->mdb, br);
@@ -1402,6 +1424,31 @@
if (!mp)
goto out;
+ if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
+ struct net_bridge_port_group __rcu **pp;
+
+ for (pp = &mp->ports;
+ (p = mlock_dereference(*pp, br)) != NULL;
+ pp = &p->next) {
+ if (p->port != port)
+ continue;
+
+ rcu_assign_pointer(*pp, p->next);
+ hlist_del_init(&p->mglist);
+ del_timer(&p->timer);
+ call_rcu_bh(&p->rcu, br_multicast_free_pg);
+ br_mdb_notify(br->dev, port, group, RTM_DELMDB);
+
+ if (!mp->ports && !mp->mglist &&
+ netif_running(br->dev))
+ mod_timer(&mp->timer, jiffies);
+ }
+ goto out;
+ }
+
+ if (timer_pending(&other_query->timer))
+ goto out;
+
if (br->multicast_querier) {
__br_multicast_send_query(br, port, &mp->addr);
@@ -1427,28 +1474,6 @@
}
}
- if (port && (port->flags & BR_MULTICAST_FAST_LEAVE)) {
- struct net_bridge_port_group __rcu **pp;
-
- for (pp = &mp->ports;
- (p = mlock_dereference(*pp, br)) != NULL;
- pp = &p->next) {
- if (p->port != port)
- continue;
-
- rcu_assign_pointer(*pp, p->next);
- hlist_del_init(&p->mglist);
- del_timer(&p->timer);
- call_rcu_bh(&p->rcu, br_multicast_free_pg);
- br_mdb_notify(br->dev, port, group, RTM_DELMDB);
-
- if (!mp->ports && !mp->mglist &&
- netif_running(br->dev))
- mod_timer(&mp->timer, jiffies);
- }
- goto out;
- }
-
now = jiffies;
time = now + br->multicast_last_member_count *
br->multicast_last_member_interval;
@@ -1566,7 +1591,7 @@
break;
}
- if (skb_trimmed)
+ if (skb_trimmed && skb_trimmed != skb)
kfree_skb(skb_trimmed);
return err;
@@ -1611,7 +1636,7 @@
break;
}
- if (skb_trimmed)
+ if (skb_trimmed && skb_trimmed != skb)
kfree_skb(skb_trimmed);
return err;
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 364bdc9..4d74a06 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -112,6 +112,8 @@
+ nla_total_size(1) /* IFLA_BRPORT_FAST_LEAVE */
+ nla_total_size(1) /* IFLA_BRPORT_LEARNING */
+ nla_total_size(1) /* IFLA_BRPORT_UNICAST_FLOOD */
+ + nla_total_size(1) /* IFLA_BRPORT_PROXYARP */
+ + nla_total_size(1) /* IFLA_BRPORT_PROXYARP_WIFI */
+ 0;
}
@@ -506,6 +508,8 @@
[IFLA_BRPORT_FAST_LEAVE]= { .type = NLA_U8 },
[IFLA_BRPORT_LEARNING] = { .type = NLA_U8 },
[IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
+ [IFLA_BRPORT_PROXYARP] = { .type = NLA_U8 },
+ [IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 },
};
/* Change the state of the port and notify spanning tree */
@@ -693,9 +697,17 @@
struct nlattr *tb[],
struct nlattr *data[])
{
+ struct net_bridge *br = netdev_priv(brdev);
+ int ret;
+
if (!data)
return 0;
- return br_setport(br_port_get_rtnl(dev), data);
+
+ spin_lock_bh(&br->lock);
+ ret = br_setport(br_port_get_rtnl(dev), data);
+ spin_unlock_bh(&br->lock);
+
+ return ret;
}
static int br_port_fill_slave_info(struct sk_buff *skb,
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
index b4b6dab..ed74ffa 100644
--- a/net/bridge/br_stp.c
+++ b/net/bridge/br_stp.c
@@ -209,8 +209,9 @@
br_send_config_bpdu(p, &bpdu);
p->topology_change_ack = 0;
p->config_pending = 0;
- mod_timer(&p->hold_timer,
- round_jiffies(jiffies + BR_HOLD_TIME));
+ if (p->br->stp_enabled == BR_KERNEL_STP)
+ mod_timer(&p->hold_timer,
+ round_jiffies(jiffies + BR_HOLD_TIME));
}
}
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
index a2730e7..4ca449a 100644
--- a/net/bridge/br_stp_if.c
+++ b/net/bridge/br_stp_if.c
@@ -48,7 +48,8 @@
struct net_bridge_port *p;
spin_lock_bh(&br->lock);
- mod_timer(&br->hello_timer, jiffies + br->hello_time);
+ if (br->stp_enabled == BR_KERNEL_STP)
+ mod_timer(&br->hello_timer, jiffies + br->hello_time);
mod_timer(&br->gc_timer, jiffies + HZ/10);
br_config_bpdu_generation(br);
@@ -127,6 +128,7 @@
int r;
char *argv[] = { BR_STP_PROG, br->dev->name, "start", NULL };
char *envp[] = { NULL };
+ struct net_bridge_port *p;
r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
@@ -140,6 +142,10 @@
if (r == 0) {
br->stp_enabled = BR_USER_STP;
br_debug(br, "userspace STP started\n");
+ /* Stop hello and hold timers */
+ del_timer(&br->hello_timer);
+ list_for_each_entry(p, &br->port_list, list)
+ del_timer(&p->hold_timer);
} else {
br->stp_enabled = BR_KERNEL_STP;
br_debug(br, "using kernel STP\n");
@@ -156,12 +162,17 @@
int r;
char *argv[] = { BR_STP_PROG, br->dev->name, "stop", NULL };
char *envp[] = { NULL };
+ struct net_bridge_port *p;
if (br->stp_enabled == BR_USER_STP) {
r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC);
br_info(br, "userspace STP stopped, return code %d\n", r);
/* To start timers on any ports left in blocking */
+ mod_timer(&br->hello_timer, jiffies + br->hello_time);
+ list_for_each_entry(p, &br->port_list, list)
+ mod_timer(&p->hold_timer,
+ round_jiffies(jiffies + BR_HOLD_TIME));
spin_lock_bh(&br->lock);
br_port_state_selection(br);
spin_unlock_bh(&br->lock);
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c
index 7caf7fa..5f0f5af 100644
--- a/net/bridge/br_stp_timer.c
+++ b/net/bridge/br_stp_timer.c
@@ -40,7 +40,9 @@
if (br->dev->flags & IFF_UP) {
br_config_bpdu_generation(br);
- mod_timer(&br->hello_timer, round_jiffies(jiffies + br->hello_time));
+ if (br->stp_enabled != BR_USER_STP)
+ mod_timer(&br->hello_timer,
+ round_jiffies(jiffies + br->hello_time));
}
spin_unlock(&br->lock);
}
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c
index 3cc71b9..cc85891 100644
--- a/net/caif/caif_socket.c
+++ b/net/caif/caif_socket.c
@@ -121,12 +121,13 @@
* Copied from sock.c:sock_queue_rcv_skb(), but changed so packets are
* not dropped, but CAIF is sending flow off instead.
*/
-static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static void caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
int err;
unsigned long flags;
struct sk_buff_head *list = &sk->sk_receive_queue;
struct caifsock *cf_sk = container_of(sk, struct caifsock, sk);
+ bool queued = false;
if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
(unsigned int)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) {
@@ -139,7 +140,8 @@
err = sk_filter(sk, skb);
if (err)
- return err;
+ goto out;
+
if (!sk_rmem_schedule(sk, skb, skb->truesize) && rx_flow_is_on(cf_sk)) {
set_rx_flow_off(cf_sk);
net_dbg_ratelimited("sending flow OFF due to rmem_schedule\n");
@@ -147,21 +149,16 @@
}
skb->dev = NULL;
skb_set_owner_r(skb, sk);
- /* Cache the SKB length before we tack it onto the receive
- * queue. Once it is added it no longer belongs to us and
- * may be freed by other threads of control pulling packets
- * from the queue.
- */
spin_lock_irqsave(&list->lock, flags);
- if (!sock_flag(sk, SOCK_DEAD))
+ queued = !sock_flag(sk, SOCK_DEAD);
+ if (queued)
__skb_queue_tail(list, skb);
spin_unlock_irqrestore(&list->lock, flags);
-
- if (!sock_flag(sk, SOCK_DEAD))
+out:
+ if (queued)
sk->sk_data_ready(sk);
else
kfree_skb(skb);
- return 0;
}
/* Packet Receive Callback function called from CAIF Stack */
diff --git a/net/core/datagram.c b/net/core/datagram.c
index b80fb91..617088a 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -131,6 +131,35 @@
goto out;
}
+static struct sk_buff *skb_set_peeked(struct sk_buff *skb)
+{
+ struct sk_buff *nskb;
+
+ if (skb->peeked)
+ return skb;
+
+ /* We have to unshare an skb before modifying it. */
+ if (!skb_shared(skb))
+ goto done;
+
+ nskb = skb_clone(skb, GFP_ATOMIC);
+ if (!nskb)
+ return ERR_PTR(-ENOMEM);
+
+ skb->prev->next = nskb;
+ skb->next->prev = nskb;
+ nskb->prev = skb->prev;
+ nskb->next = skb->next;
+
+ consume_skb(skb);
+ skb = nskb;
+
+done:
+ skb->peeked = 1;
+
+ return skb;
+}
+
/**
* __skb_recv_datagram - Receive a datagram skbuff
* @sk: socket
@@ -165,7 +194,9 @@
struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned int flags,
int *peeked, int *off, int *err)
{
+ struct sk_buff_head *queue = &sk->sk_receive_queue;
struct sk_buff *skb, *last;
+ unsigned long cpu_flags;
long timeo;
/*
* Caller is allowed not to check sk->sk_err before skb_recv_datagram()
@@ -184,8 +215,6 @@
* Look at current nfs client by the way...
* However, this function was correct in any case. 8)
*/
- unsigned long cpu_flags;
- struct sk_buff_head *queue = &sk->sk_receive_queue;
int _off = *off;
last = (struct sk_buff *)queue;
@@ -199,7 +228,12 @@
_off -= skb->len;
continue;
}
- skb->peeked = 1;
+
+ skb = skb_set_peeked(skb);
+ error = PTR_ERR(skb);
+ if (IS_ERR(skb))
+ goto unlock_err;
+
atomic_inc(&skb->users);
} else
__skb_unlink(skb, queue);
@@ -223,6 +257,8 @@
return NULL;
+unlock_err:
+ spin_unlock_irqrestore(&queue->lock, cpu_flags);
no_packet:
*err = error;
return NULL;
@@ -622,7 +658,8 @@
!skb->csum_complete_sw)
netdev_rx_csum_fault(skb->dev);
}
- skb->csum_valid = !sum;
+ if (!skb_shared(skb))
+ skb->csum_valid = !sum;
return sum;
}
EXPORT_SYMBOL(__skb_checksum_complete_head);
@@ -642,11 +679,13 @@
netdev_rx_csum_fault(skb->dev);
}
- /* Save full packet checksum */
- skb->csum = csum;
- skb->ip_summed = CHECKSUM_COMPLETE;
- skb->csum_complete_sw = 1;
- skb->csum_valid = !sum;
+ if (!skb_shared(skb)) {
+ /* Save full packet checksum */
+ skb->csum = csum;
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ skb->csum_complete_sw = 1;
+ skb->csum_valid = !sum;
+ }
return sum;
}
diff --git a/net/core/dst.c b/net/core/dst.c
index e956ce6..002144be 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -284,7 +284,9 @@
int newrefcnt;
newrefcnt = atomic_dec_return(&dst->__refcnt);
- WARN_ON(newrefcnt < 0);
+ if (unlikely(newrefcnt < 0))
+ net_warn_ratelimited("%s: dst:%p refcnt:%d\n",
+ __func__, dst, newrefcnt);
if (unlikely(dst->flags & DST_NOCACHE) && !newrefcnt)
call_rcu(&dst->rcu_head, dst_destroy_rcu);
}
diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c
index 1f2a126..6441f47 100644
--- a/net/core/netclassid_cgroup.c
+++ b/net/core/netclassid_cgroup.c
@@ -23,7 +23,8 @@
struct cgroup_cls_state *task_cls_state(struct task_struct *p)
{
- return css_cls_state(task_css(p, net_cls_cgrp_id));
+ return css_cls_state(task_css_check(p, net_cls_cgrp_id,
+ rcu_read_lock_bh_held()));
}
EXPORT_SYMBOL_GPL(task_cls_state);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 1ebdf1c..1cbd209 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3514,8 +3514,6 @@
set_freezable();
- __set_current_state(TASK_RUNNING);
-
while (!kthread_should_stop()) {
pkt_dev = next_to_run(t);
@@ -3560,7 +3558,6 @@
try_to_freeze();
}
- set_current_state(TASK_INTERRUPTIBLE);
pr_debug("%s stopping all device\n", t->tsk->comm);
pktgen_stop(t);
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index 87b22c0..b42f0e2 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -103,10 +103,16 @@
spin_lock_bh(&queue->syn_wait_lock);
while ((req = lopt->syn_table[i]) != NULL) {
lopt->syn_table[i] = req->dl_next;
+ /* Because of following del_timer_sync(),
+ * we must release the spinlock here
+ * or risk a dead lock.
+ */
+ spin_unlock_bh(&queue->syn_wait_lock);
atomic_inc(&lopt->qlen_dec);
- if (del_timer(&req->rsk_timer))
+ if (del_timer_sync(&req->rsk_timer))
reqsk_put(req);
reqsk_put(req);
+ spin_lock_bh(&queue->syn_wait_lock);
}
spin_unlock_bh(&queue->syn_wait_lock);
}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 9e433d5..dc004b1 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -1804,10 +1804,13 @@
goto errout;
nla_for_each_nested(attr, tb[IFLA_VF_PORTS], rem) {
- if (nla_type(attr) != IFLA_VF_PORT)
- continue;
- err = nla_parse_nested(port, IFLA_PORT_MAX,
- attr, ifla_port_policy);
+ if (nla_type(attr) != IFLA_VF_PORT ||
+ nla_len(attr) < NLA_HDRLEN) {
+ err = -EINVAL;
+ goto errout;
+ }
+ err = nla_parse_nested(port, IFLA_PORT_MAX, attr,
+ ifla_port_policy);
if (err < 0)
goto errout;
if (!port[IFLA_PORT_VF]) {
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index b6a19ca..7b84330 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -340,7 +340,7 @@
if (skb && frag_size) {
skb->head_frag = 1;
- if (virt_to_head_page(data)->pfmemalloc)
+ if (page_is_pfmemalloc(virt_to_head_page(data)))
skb->pfmemalloc = 1;
}
return skb;
@@ -4022,8 +4022,8 @@
* Otherwise returns the provided skb. Returns NULL in error cases
* (e.g. transport_len exceeds skb length or out-of-memory).
*
- * Caller needs to set the skb transport header and release the returned skb.
- * Provided skb is consumed.
+ * Caller needs to set the skb transport header and free any returned skb if it
+ * differs from the provided skb.
*/
static struct sk_buff *skb_checksum_maybe_trim(struct sk_buff *skb,
unsigned int transport_len)
@@ -4032,16 +4032,12 @@
unsigned int len = skb_transport_offset(skb) + transport_len;
int ret;
- if (skb->len < len) {
- kfree_skb(skb);
+ if (skb->len < len)
return NULL;
- } else if (skb->len == len) {
+ else if (skb->len == len)
return skb;
- }
skb_chk = skb_clone(skb, GFP_ATOMIC);
- kfree_skb(skb);
-
if (!skb_chk)
return NULL;
@@ -4066,8 +4062,8 @@
* If the skb has data beyond the given transport length, then a
* trimmed & cloned skb is checked and returned.
*
- * Caller needs to set the skb transport header and release the returned skb.
- * Provided skb is consumed.
+ * Caller needs to set the skb transport header and free any returned skb if it
+ * differs from the provided skb.
*/
struct sk_buff *skb_checksum_trimmed(struct sk_buff *skb,
unsigned int transport_len,
@@ -4079,23 +4075,26 @@
skb_chk = skb_checksum_maybe_trim(skb, transport_len);
if (!skb_chk)
- return NULL;
+ goto err;
- if (!pskb_may_pull(skb_chk, offset)) {
- kfree_skb(skb_chk);
- return NULL;
- }
+ if (!pskb_may_pull(skb_chk, offset))
+ goto err;
__skb_pull(skb_chk, offset);
ret = skb_chkf(skb_chk);
__skb_push(skb_chk, offset);
- if (ret) {
- kfree_skb(skb_chk);
- return NULL;
- }
+ if (ret)
+ goto err;
return skb_chk;
+
+err:
+ if (skb_chk && skb_chk != skb)
+ kfree_skb(skb_chk);
+
+ return NULL;
+
}
EXPORT_SYMBOL(skb_checksum_trimmed);
diff --git a/net/core/sock.c b/net/core/sock.c
index 08f16db..193901d 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1497,7 +1497,8 @@
sock_copy(newsk, sk);
/* SANITY */
- get_net(sock_net(newsk));
+ if (likely(newsk->sk_net_refcnt))
+ get_net(sock_net(newsk));
sk_node_init(&newsk->sk_node);
sock_lock_init(newsk);
bh_lock_sock(newsk);
@@ -1967,20 +1968,21 @@
* sk_wait_data - wait for data to arrive at sk_receive_queue
* @sk: sock to wait on
* @timeo: for how long
+ * @skb: last skb seen on sk_receive_queue
*
* Now socket state including sk->sk_err is changed only under lock,
* hence we may omit checks after joining wait queue.
* We check receive queue before schedule() only as optimization;
* it is very likely that release_sock() added new data.
*/
-int sk_wait_data(struct sock *sk, long *timeo)
+int sk_wait_data(struct sock *sk, long *timeo, const struct sk_buff *skb)
{
int rc;
DEFINE_WAIT(wait);
prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
- rc = sk_wait_event(sk, timeo, !skb_queue_empty(&sk->sk_receive_queue));
+ rc = sk_wait_event(sk, timeo, skb_peek_tail(&sk->sk_receive_queue) != skb);
clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags);
finish_wait(sk_sleep(sk), &wait);
return rc;
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index 52a9401..b5cf13a 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -886,7 +886,7 @@
break;
}
- sk_wait_data(sk, &timeo);
+ sk_wait_data(sk, &timeo, NULL);
continue;
found_ok_skb:
if (len > skb->len)
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 0917123..35c47dd 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -756,7 +756,8 @@
return -ENODEV;
/* Use already configured phy mode */
- p->phy_interface = p->phy->interface;
+ if (p->phy_interface == PHY_INTERFACE_MODE_NA)
+ p->phy_interface = p->phy->interface;
phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
p->phy_interface);
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c
index f46e4d1..214d44a 100644
--- a/net/ieee802154/6lowpan/reassembly.c
+++ b/net/ieee802154/6lowpan/reassembly.c
@@ -207,7 +207,7 @@
} else {
fq->q.meat += skb->len;
}
- add_frag_mem_limit(&fq->q, skb->truesize);
+ add_frag_mem_limit(fq->q.net, skb->truesize);
if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
fq->q.meat == fq->q.len) {
@@ -287,7 +287,7 @@
clone->data_len = clone->len;
head->data_len -= clone->len;
head->len -= clone->len;
- add_frag_mem_limit(&fq->q, clone->truesize);
+ add_frag_mem_limit(fq->q.net, clone->truesize);
}
WARN_ON(head == NULL);
@@ -310,7 +310,7 @@
}
fp = next;
}
- sub_frag_mem_limit(&fq->q, sum_truesize);
+ sub_frag_mem_limit(fq->q.net, sum_truesize);
head->next = NULL;
head->dev = dev;
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index 933a928..6c8b1fb 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -1017,14 +1017,16 @@
neigh = neigh_lookup(&arp_tbl, &ip, dev);
if (neigh) {
- read_lock_bh(&neigh->lock);
- memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
- r->arp_flags = arp_state_to_flags(neigh);
- read_unlock_bh(&neigh->lock);
- r->arp_ha.sa_family = dev->type;
- strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
+ if (!(neigh->nud_state & NUD_NOARP)) {
+ read_lock_bh(&neigh->lock);
+ memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len);
+ r->arp_flags = arp_state_to_flags(neigh);
+ read_unlock_bh(&neigh->lock);
+ r->arp_ha.sa_family = dev->type;
+ strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
+ err = 0;
+ }
neigh_release(neigh);
- err = 0;
}
return err;
}
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index 90c0e83..574fad9 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -20,7 +20,7 @@
#include <net/route.h>
#include <net/tcp_states.h>
-int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct inet_sock *inet = inet_sk(sk);
struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
@@ -39,8 +39,6 @@
sk_dst_reset(sk);
- lock_sock(sk);
-
oif = sk->sk_bound_dev_if;
saddr = inet->inet_saddr;
if (ipv4_is_multicast(usin->sin_addr.s_addr)) {
@@ -82,9 +80,19 @@
sk_dst_set(sk, &rt->dst);
err = 0;
out:
- release_sock(sk);
return err;
}
+EXPORT_SYMBOL(__ip4_datagram_connect);
+
+int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+ int res;
+
+ lock_sock(sk);
+ res = __ip4_datagram_connect(sk, uaddr, addr_len);
+ release_sock(sk);
+ return res;
+}
EXPORT_SYMBOL(ip4_datagram_connect);
/* Because UDP xmit path can manipulate sk_dst_cache without holding
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index e813196..2d9cb17 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -882,7 +882,6 @@
queue_delayed_work(system_power_efficient_wq,
&check_lifetime_work, 0);
rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid);
- blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
}
return 0;
}
diff --git a/net/ipv4/fib_lookup.h b/net/ipv4/fib_lookup.h
index c6211ed..9c02920 100644
--- a/net/ipv4/fib_lookup.h
+++ b/net/ipv4/fib_lookup.h
@@ -13,6 +13,7 @@
u8 fa_state;
u8 fa_slen;
u32 tb_id;
+ s16 fa_default;
struct rcu_head rcu;
};
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index c7358ea..3a06586 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -1202,23 +1202,40 @@
}
/* Must be invoked inside of an RCU protected region. */
-void fib_select_default(struct fib_result *res)
+void fib_select_default(const struct flowi4 *flp, struct fib_result *res)
{
struct fib_info *fi = NULL, *last_resort = NULL;
struct hlist_head *fa_head = res->fa_head;
struct fib_table *tb = res->table;
+ u8 slen = 32 - res->prefixlen;
int order = -1, last_idx = -1;
- struct fib_alias *fa;
+ struct fib_alias *fa, *fa1 = NULL;
+ u32 last_prio = res->fi->fib_priority;
+ u8 last_tos = 0;
hlist_for_each_entry_rcu(fa, fa_head, fa_list) {
struct fib_info *next_fi = fa->fa_info;
+ if (fa->fa_slen != slen)
+ continue;
+ if (fa->fa_tos && fa->fa_tos != flp->flowi4_tos)
+ continue;
+ if (fa->tb_id != tb->tb_id)
+ continue;
+ if (next_fi->fib_priority > last_prio &&
+ fa->fa_tos == last_tos) {
+ if (last_tos)
+ continue;
+ break;
+ }
+ if (next_fi->fib_flags & RTNH_F_DEAD)
+ continue;
+ last_tos = fa->fa_tos;
+ last_prio = next_fi->fib_priority;
+
if (next_fi->fib_scope != res->scope ||
fa->fa_type != RTN_UNICAST)
continue;
-
- if (next_fi->fib_priority > res->fi->fib_priority)
- break;
if (!next_fi->fib_nh[0].nh_gw ||
next_fi->fib_nh[0].nh_scope != RT_SCOPE_LINK)
continue;
@@ -1228,10 +1245,11 @@
if (!fi) {
if (next_fi != res->fi)
break;
+ fa1 = fa;
} else if (!fib_detect_death(fi, order, &last_resort,
- &last_idx, tb->tb_default)) {
+ &last_idx, fa1->fa_default)) {
fib_result_assign(res, fi);
- tb->tb_default = order;
+ fa1->fa_default = order;
goto out;
}
fi = next_fi;
@@ -1239,20 +1257,21 @@
}
if (order <= 0 || !fi) {
- tb->tb_default = -1;
+ if (fa1)
+ fa1->fa_default = -1;
goto out;
}
if (!fib_detect_death(fi, order, &last_resort, &last_idx,
- tb->tb_default)) {
+ fa1->fa_default)) {
fib_result_assign(res, fi);
- tb->tb_default = order;
+ fa1->fa_default = order;
goto out;
}
if (last_idx >= 0)
fib_result_assign(res, last_resort);
- tb->tb_default = last_idx;
+ fa1->fa_default = last_idx;
out:
return;
}
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 15d3261..b0c6258 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -1171,6 +1171,7 @@
new_fa->fa_state = state & ~FA_S_ACCESSED;
new_fa->fa_slen = fa->fa_slen;
new_fa->tb_id = tb->tb_id;
+ new_fa->fa_default = -1;
err = switchdev_fib_ipv4_add(key, plen, fi,
new_fa->fa_tos,
@@ -1222,6 +1223,7 @@
new_fa->fa_state = 0;
new_fa->fa_slen = slen;
new_fa->tb_id = tb->tb_id;
+ new_fa->fa_default = -1;
/* (Optionally) offload fib entry to switch hardware. */
err = switchdev_fib_ipv4_add(key, plen, fi, tos, cfg->fc_type,
@@ -1791,8 +1793,6 @@
if (hlist_empty(&n->leaf)) {
put_child_root(pn, n->key, NULL);
node_free(n);
- } else {
- leaf_pull_suffix(pn, n);
}
}
}
@@ -1862,8 +1862,6 @@
if (hlist_empty(&n->leaf)) {
put_child_root(pn, n->key, NULL);
node_free(n);
- } else {
- leaf_pull_suffix(pn, n);
}
}
@@ -1990,7 +1988,6 @@
return NULL;
tb->tb_id = id;
- tb->tb_default = -1;
tb->tb_num_default = 0;
tb->tb_data = (alias ? alias->__data : tb->__data);
@@ -2468,7 +2465,7 @@
key = l->key + 1;
iter->pos++;
- if (pos-- <= 0)
+ if (--pos <= 0)
break;
l = NULL;
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 651cdf6..9fdfd9d 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1435,33 +1435,35 @@
struct sk_buff *skb_chk;
unsigned int transport_len;
unsigned int len = skb_transport_offset(skb) + sizeof(struct igmphdr);
- int ret;
+ int ret = -EINVAL;
transport_len = ntohs(ip_hdr(skb)->tot_len) - ip_hdrlen(skb);
- skb_get(skb);
skb_chk = skb_checksum_trimmed(skb, transport_len,
ip_mc_validate_checksum);
if (!skb_chk)
- return -EINVAL;
+ goto err;
- if (!pskb_may_pull(skb_chk, len)) {
- kfree_skb(skb_chk);
- return -EINVAL;
- }
+ if (!pskb_may_pull(skb_chk, len))
+ goto err;
ret = ip_mc_check_igmp_msg(skb_chk);
- if (ret) {
- kfree_skb(skb_chk);
- return ret;
- }
+ if (ret)
+ goto err;
if (skb_trimmed)
*skb_trimmed = skb_chk;
- else
+ /* free now unneeded clone */
+ else if (skb_chk != skb)
kfree_skb(skb_chk);
- return 0;
+ ret = 0;
+
+err:
+ if (ret && skb_chk && skb_chk != skb)
+ kfree_skb(skb_chk);
+
+ return ret;
}
/**
@@ -1470,7 +1472,7 @@
* @skb_trimmed: to store an skb pointer trimmed to IPv4 packet tail (optional)
*
* Checks whether an IPv4 packet is a valid IGMP packet. If so sets
- * skb network and transport headers accordingly and returns zero.
+ * skb transport header accordingly and returns zero.
*
* -EINVAL: A broken packet was detected, i.e. it violates some internet
* standard
@@ -1485,7 +1487,8 @@
* to leave the original skb and its full frame unchanged (which might be
* desirable for layer 2 frame jugglers).
*
- * The caller needs to release a reference count from any returned skb_trimmed.
+ * Caller needs to set the skb network header and free any returned skb if it
+ * differs from the provided skb.
*/
int ip_mc_check_igmp(struct sk_buff *skb, struct sk_buff **skb_trimmed)
{
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 60021d0..1349571 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -593,7 +593,7 @@
}
spin_unlock(&queue->syn_wait_lock);
- if (del_timer(&req->rsk_timer))
+ if (timer_pending(&req->rsk_timer) && del_timer_sync(&req->rsk_timer))
reqsk_put(req);
return found;
}
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c
index 5e346a0..d0a7c03 100644
--- a/net/ipv4/inet_fragment.c
+++ b/net/ipv4/inet_fragment.c
@@ -131,34 +131,22 @@
unsigned int evicted = 0;
HLIST_HEAD(expired);
-evict_again:
spin_lock(&hb->chain_lock);
hlist_for_each_entry_safe(fq, n, &hb->chain, list) {
if (!inet_fragq_should_evict(fq))
continue;
- if (!del_timer(&fq->timer)) {
- /* q expiring right now thus increment its refcount so
- * it won't be freed under us and wait until the timer
- * has finished executing then destroy it
- */
- atomic_inc(&fq->refcnt);
- spin_unlock(&hb->chain_lock);
- del_timer_sync(&fq->timer);
- inet_frag_put(fq, f);
- goto evict_again;
- }
+ if (!del_timer(&fq->timer))
+ continue;
- fq->flags |= INET_FRAG_EVICTED;
- hlist_del(&fq->list);
- hlist_add_head(&fq->list, &expired);
+ hlist_add_head(&fq->list_evictor, &expired);
++evicted;
}
spin_unlock(&hb->chain_lock);
- hlist_for_each_entry_safe(fq, n, &expired, list)
+ hlist_for_each_entry_safe(fq, n, &expired, list_evictor)
f->frag_expire((unsigned long) fq);
return evicted;
@@ -240,18 +228,20 @@
int i;
nf->low_thresh = 0;
- local_bh_disable();
evict_again:
+ local_bh_disable();
seq = read_seqbegin(&f->rnd_seqlock);
for (i = 0; i < INETFRAGS_HASHSZ ; i++)
inet_evict_bucket(f, &f->hash[i]);
- if (read_seqretry(&f->rnd_seqlock, seq))
- goto evict_again;
-
local_bh_enable();
+ cond_resched();
+
+ if (read_seqretry(&f->rnd_seqlock, seq) ||
+ percpu_counter_sum(&nf->mem))
+ goto evict_again;
percpu_counter_destroy(&nf->mem);
}
@@ -284,8 +274,8 @@
struct inet_frag_bucket *hb;
hb = get_frag_bucket_locked(fq, f);
- if (!(fq->flags & INET_FRAG_EVICTED))
- hlist_del(&fq->list);
+ hlist_del(&fq->list);
+ fq->flags |= INET_FRAG_COMPLETE;
spin_unlock(&hb->chain_lock);
}
@@ -297,7 +287,6 @@
if (!(fq->flags & INET_FRAG_COMPLETE)) {
fq_unlink(fq, f);
atomic_dec(&fq->refcnt);
- fq->flags |= INET_FRAG_COMPLETE;
}
}
EXPORT_SYMBOL(inet_frag_kill);
@@ -330,11 +319,12 @@
fp = xp;
}
sum = sum_truesize + f->qsize;
- sub_frag_mem_limit(q, sum);
if (f->destructor)
f->destructor(q);
kmem_cache_free(f->frags_cachep, q);
+
+ sub_frag_mem_limit(nf, sum);
}
EXPORT_SYMBOL(inet_frag_destroy);
@@ -390,7 +380,7 @@
q->net = nf;
f->constructor(q, arg);
- add_frag_mem_limit(q, f->qsize);
+ add_frag_mem_limit(nf, f->qsize);
setup_timer(&q->timer, f->frag_expire, (unsigned long)q);
spin_lock_init(&q->lock);
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 5f9b063..0cb9165 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -624,22 +624,21 @@
int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo)
{
+ unsigned int locksz = sizeof(spinlock_t);
unsigned int i, nblocks = 1;
- if (sizeof(spinlock_t) != 0) {
+ if (locksz != 0) {
/* allocate 2 cache lines or at least one spinlock per cpu */
- nblocks = max_t(unsigned int,
- 2 * L1_CACHE_BYTES / sizeof(spinlock_t),
- 1);
+ nblocks = max(2U * L1_CACHE_BYTES / locksz, 1U);
nblocks = roundup_pow_of_two(nblocks * num_possible_cpus());
/* no more locks than number of hash buckets */
nblocks = min(nblocks, hashinfo->ehash_mask + 1);
- hashinfo->ehash_locks = kmalloc_array(nblocks, sizeof(spinlock_t),
+ hashinfo->ehash_locks = kmalloc_array(nblocks, locksz,
GFP_KERNEL | __GFP_NOWARN);
if (!hashinfo->ehash_locks)
- hashinfo->ehash_locks = vmalloc(nblocks * sizeof(spinlock_t));
+ hashinfo->ehash_locks = vmalloc(nblocks * locksz);
if (!hashinfo->ehash_locks)
return -ENOMEM;
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index a50dc6d4..921138f 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -202,7 +202,7 @@
ipq_kill(qp);
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS);
- if (!(qp->q.flags & INET_FRAG_EVICTED)) {
+ if (!inet_frag_evicting(&qp->q)) {
struct sk_buff *head = qp->q.fragments;
const struct iphdr *iph;
int err;
@@ -309,7 +309,7 @@
kfree_skb(fp);
fp = xp;
} while (fp);
- sub_frag_mem_limit(&qp->q, sum_truesize);
+ sub_frag_mem_limit(qp->q.net, sum_truesize);
qp->q.flags = 0;
qp->q.len = 0;
@@ -351,7 +351,7 @@
ihl = ip_hdrlen(skb);
/* Determine the position of this fragment. */
- end = offset + skb->len - ihl;
+ end = offset + skb->len - skb_network_offset(skb) - ihl;
err = -EINVAL;
/* Is this the final fragment? */
@@ -381,7 +381,7 @@
goto err;
err = -ENOMEM;
- if (!pskb_pull(skb, ihl))
+ if (!pskb_pull(skb, skb_network_offset(skb) + ihl))
goto err;
err = pskb_trim_rcsum(skb, end - offset);
@@ -455,7 +455,7 @@
qp->q.fragments = next;
qp->q.meat -= free_it->len;
- sub_frag_mem_limit(&qp->q, free_it->truesize);
+ sub_frag_mem_limit(qp->q.net, free_it->truesize);
kfree_skb(free_it);
}
}
@@ -479,7 +479,7 @@
qp->q.stamp = skb->tstamp;
qp->q.meat += skb->len;
qp->ecn |= ecn;
- add_frag_mem_limit(&qp->q, skb->truesize);
+ add_frag_mem_limit(qp->q.net, skb->truesize);
if (offset == 0)
qp->q.flags |= INET_FRAG_FIRST_IN;
@@ -587,7 +587,7 @@
head->len -= clone->len;
clone->csum = 0;
clone->ip_summed = head->ip_summed;
- add_frag_mem_limit(&qp->q, clone->truesize);
+ add_frag_mem_limit(qp->q.net, clone->truesize);
}
skb_push(head, head->data - skb_network_header(head));
@@ -615,7 +615,7 @@
}
fp = next;
}
- sub_frag_mem_limit(&qp->q, sum_truesize);
+ sub_frag_mem_limit(qp->q.net, sum_truesize);
head->next = NULL;
head->dev = dev;
@@ -641,6 +641,8 @@
iph->frag_off = 0;
}
+ ip_send_check(iph);
+
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
qp->q.fragments = NULL;
qp->q.fragments_tail = NULL;
diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c b/net/ipv4/netfilter/ipt_SYNPROXY.c
index fe8cc18..95ea633e 100644
--- a/net/ipv4/netfilter/ipt_SYNPROXY.c
+++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
@@ -226,7 +226,8 @@
synproxy_build_options(nth, opts);
- synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
+ synproxy_send_tcp(skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
+ niph, nth, tcp_hdr_size);
}
static bool
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d0362a2..e681b85 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2176,7 +2176,7 @@
if (!res.prefixlen &&
res.table->tb_num_default > 1 &&
res.type == RTN_UNICAST && !fl4->flowi4_oif)
- fib_select_default(&res);
+ fib_select_default(fl4, &res);
if (!fl4->saddr)
fl4->saddr = FIB_RES_PREFSRC(net, res);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index 433231c..0330ab2 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -41,8 +41,6 @@
static int tcp_syn_retries_max = MAX_TCP_SYNCNT;
static int ip_ping_group_range_min[] = { 0, 0 };
static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX };
-static int min_sndbuf = SOCK_MIN_SNDBUF;
-static int min_rcvbuf = SOCK_MIN_RCVBUF;
/* Update system visible IP port range */
static void set_local_port_range(struct net *net, int range[2])
@@ -530,7 +528,7 @@
.maxlen = sizeof(sysctl_tcp_wmem),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
- .extra1 = &min_sndbuf,
+ .extra1 = &one,
},
{
.procname = "tcp_notsent_lowat",
@@ -545,7 +543,7 @@
.maxlen = sizeof(sysctl_tcp_rmem),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
- .extra1 = &min_rcvbuf,
+ .extra1 = &one,
},
{
.procname = "tcp_app_win",
@@ -758,7 +756,7 @@
.maxlen = sizeof(sysctl_udp_rmem_min),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
- .extra1 = &min_rcvbuf,
+ .extra1 = &one
},
{
.procname = "udp_wmem_min",
@@ -766,7 +764,7 @@
.maxlen = sizeof(sysctl_udp_wmem_min),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
- .extra1 = &min_sndbuf,
+ .extra1 = &one
},
{ }
};
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 7f40567..45534a5 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -780,7 +780,7 @@
ret = -EAGAIN;
break;
}
- sk_wait_data(sk, &timeo);
+ sk_wait_data(sk, &timeo, NULL);
if (signal_pending(current)) {
ret = sock_intr_errno(timeo);
break;
@@ -1575,7 +1575,7 @@
int target; /* Read at least this many bytes */
long timeo;
struct task_struct *user_recv = NULL;
- struct sk_buff *skb;
+ struct sk_buff *skb, *last;
u32 urg_hole = 0;
if (unlikely(flags & MSG_ERRQUEUE))
@@ -1635,7 +1635,9 @@
/* Next get a buffer. */
+ last = skb_peek_tail(&sk->sk_receive_queue);
skb_queue_walk(&sk->sk_receive_queue, skb) {
+ last = skb;
/* Now that we have two receive queues this
* shouldn't happen.
*/
@@ -1754,8 +1756,9 @@
/* Do not sleep, just process backlog. */
release_sock(sk);
lock_sock(sk);
- } else
- sk_wait_data(sk, &timeo);
+ } else {
+ sk_wait_data(sk, &timeo, last);
+ }
if (user_recv) {
int chunk;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 684f095..728f5b3 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1917,14 +1917,13 @@
const struct inet_connection_sock *icsk = inet_csk(sk);
struct tcp_sock *tp = tcp_sk(sk);
struct sk_buff *skb;
- bool new_recovery = false;
+ bool new_recovery = icsk->icsk_ca_state < TCP_CA_Recovery;
bool is_reneg; /* is receiver reneging on SACKs? */
/* Reduce ssthresh if it has not yet been made inside this window. */
if (icsk->icsk_ca_state <= TCP_CA_Disorder ||
!after(tp->high_seq, tp->snd_una) ||
(icsk->icsk_ca_state == TCP_CA_Loss && !icsk->icsk_retransmits)) {
- new_recovery = true;
tp->prior_ssthresh = tcp_current_ssthresh(sk);
tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk);
tcp_ca_event(sk, CA_EVENT_LOSS);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index d7d4c2b..0ea2e1c 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1348,7 +1348,7 @@
req = inet_csk_search_req(sk, th->source, iph->saddr, iph->daddr);
if (req) {
nsk = tcp_check_req(sk, skb, req, false);
- if (!nsk)
+ if (!nsk || nsk == sk)
reqsk_put(req);
return nsk;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 83aa604..1b8c5ba 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1995,12 +1995,19 @@
skb->sk = sk;
skb->destructor = sock_efree;
- dst = sk->sk_rx_dst;
+ dst = READ_ONCE(sk->sk_rx_dst);
if (dst)
dst = dst_check(dst, 0);
- if (dst)
- skb_dst_set_noref(skb, dst);
+ if (dst) {
+ /* DST_NOCACHE can not be used without taking a reference */
+ if (dst->flags & DST_NOCACHE) {
+ if (likely(atomic_inc_not_zero(&dst->__refcnt)))
+ skb_dst_set(skb, dst);
+ } else {
+ skb_dst_set_noref(skb, dst);
+ }
+ }
}
int udp_rcv(struct sk_buff *skb)
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
index 62d908e..b10a889 100644
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -40,7 +40,7 @@
return ipv6_addr_v4mapped(a) && (a->s6_addr32[3] == 0);
}
-int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
struct inet_sock *inet = inet_sk(sk);
@@ -56,7 +56,7 @@
if (usin->sin6_family == AF_INET) {
if (__ipv6_only_sock(sk))
return -EAFNOSUPPORT;
- err = ip4_datagram_connect(sk, uaddr, addr_len);
+ err = __ip4_datagram_connect(sk, uaddr, addr_len);
goto ipv4_connected;
}
@@ -98,9 +98,9 @@
sin.sin_addr.s_addr = daddr->s6_addr32[3];
sin.sin_port = usin->sin6_port;
- err = ip4_datagram_connect(sk,
- (struct sockaddr *) &sin,
- sizeof(sin));
+ err = __ip4_datagram_connect(sk,
+ (struct sockaddr *) &sin,
+ sizeof(sin));
ipv4_connected:
if (err)
@@ -204,6 +204,16 @@
fl6_sock_release(flowlabel);
return err;
}
+
+int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+ int res;
+
+ lock_sock(sk);
+ res = __ip6_datagram_connect(sk, uaddr, addr_len);
+ release_sock(sk);
+ return res;
+}
EXPORT_SYMBOL_GPL(ip6_datagram_connect);
int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *uaddr,
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 55d1986..548c623 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -172,6 +172,8 @@
*ppcpu_rt = NULL;
}
}
+
+ non_pcpu_rt->rt6i_pcpu = NULL;
}
static void rt6_release(struct rt6_info *rt)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index a38d3ac..69f4f68 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -361,6 +361,7 @@
struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id);
ip6gre_tunnel_unlink(ign, t);
+ ip6_tnl_dst_reset(t);
dev_put(dev);
}
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index e893cd1..08b6204 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -292,8 +292,6 @@
static const struct net_offload sit_offload = {
.callbacks = {
.gso_segment = ipv6_gso_segment,
- .gro_receive = ipv6_gro_receive,
- .gro_complete = ipv6_gro_complete,
},
};
diff --git a/net/ipv6/mcast_snoop.c b/net/ipv6/mcast_snoop.c
index df8afe5..9405b04 100644
--- a/net/ipv6/mcast_snoop.c
+++ b/net/ipv6/mcast_snoop.c
@@ -143,34 +143,36 @@
struct sk_buff *skb_chk = NULL;
unsigned int transport_len;
unsigned int len = skb_transport_offset(skb) + sizeof(struct mld_msg);
- int ret;
+ int ret = -EINVAL;
transport_len = ntohs(ipv6_hdr(skb)->payload_len);
transport_len -= skb_transport_offset(skb) - sizeof(struct ipv6hdr);
- skb_get(skb);
skb_chk = skb_checksum_trimmed(skb, transport_len,
ipv6_mc_validate_checksum);
if (!skb_chk)
- return -EINVAL;
+ goto err;
- if (!pskb_may_pull(skb_chk, len)) {
- kfree_skb(skb_chk);
- return -EINVAL;
- }
+ if (!pskb_may_pull(skb_chk, len))
+ goto err;
ret = ipv6_mc_check_mld_msg(skb_chk);
- if (ret) {
- kfree_skb(skb_chk);
- return ret;
- }
+ if (ret)
+ goto err;
if (skb_trimmed)
*skb_trimmed = skb_chk;
- else
+ /* free now unneeded clone */
+ else if (skb_chk != skb)
kfree_skb(skb_chk);
- return 0;
+ ret = 0;
+
+err:
+ if (ret && skb_chk && skb_chk != skb)
+ kfree_skb(skb_chk);
+
+ return ret;
}
/**
@@ -179,7 +181,7 @@
* @skb_trimmed: to store an skb pointer trimmed to IPv6 packet tail (optional)
*
* Checks whether an IPv6 packet is a valid MLD packet. If so sets
- * skb network and transport headers accordingly and returns zero.
+ * skb transport header accordingly and returns zero.
*
* -EINVAL: A broken packet was detected, i.e. it violates some internet
* standard
@@ -194,7 +196,8 @@
* to leave the original skb and its full frame unchanged (which might be
* desirable for layer 2 frame jugglers).
*
- * The caller needs to release a reference count from any returned skb_trimmed.
+ * Caller needs to set the skb network header and free any returned skb if it
+ * differs from the provided skb.
*/
int ipv6_mc_check_mld(struct sk_buff *skb, struct sk_buff **skb_trimmed)
{
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 0a05b35..c53331c 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1650,6 +1650,7 @@
static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+ struct netdev_notifier_change_info *change_info;
struct net *net = dev_net(dev);
struct inet6_dev *idev;
@@ -1664,6 +1665,11 @@
ndisc_send_unsol_na(dev);
in6_dev_put(idev);
break;
+ case NETDEV_CHANGE:
+ change_info = ptr;
+ if (change_info->flags_changed & IFF_NOARP)
+ neigh_changeaddr(&nd_tbl, dev);
+ break;
case NETDEV_DOWN:
neigh_ifdown(&nd_tbl, dev);
fib6_run_gc(0, net, false);
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index 6edb7b1..ebbb754 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -37,12 +37,13 @@
}
static void
-synproxy_send_tcp(const struct sk_buff *skb, struct sk_buff *nskb,
+synproxy_send_tcp(const struct synproxy_net *snet,
+ const struct sk_buff *skb, struct sk_buff *nskb,
struct nf_conntrack *nfct, enum ip_conntrack_info ctinfo,
struct ipv6hdr *niph, struct tcphdr *nth,
unsigned int tcp_hdr_size)
{
- struct net *net = nf_ct_net((struct nf_conn *)nfct);
+ struct net *net = nf_ct_net(snet->tmpl);
struct dst_entry *dst;
struct flowi6 fl6;
@@ -83,7 +84,8 @@
}
static void
-synproxy_send_client_synack(const struct sk_buff *skb, const struct tcphdr *th,
+synproxy_send_client_synack(const struct synproxy_net *snet,
+ const struct sk_buff *skb, const struct tcphdr *th,
const struct synproxy_options *opts)
{
struct sk_buff *nskb;
@@ -119,7 +121,7 @@
synproxy_build_options(nth, opts);
- synproxy_send_tcp(skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
+ synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
niph, nth, tcp_hdr_size);
}
@@ -163,7 +165,7 @@
synproxy_build_options(nth, opts);
- synproxy_send_tcp(skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
+ synproxy_send_tcp(snet, skb, nskb, &snet->tmpl->ct_general, IP_CT_NEW,
niph, nth, tcp_hdr_size);
}
@@ -203,7 +205,7 @@
synproxy_build_options(nth, opts);
- synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
+ synproxy_send_tcp(snet, skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
}
static void
@@ -241,7 +243,8 @@
synproxy_build_options(nth, opts);
- synproxy_send_tcp(skb, nskb, NULL, 0, niph, nth, tcp_hdr_size);
+ synproxy_send_tcp(snet, skb, nskb, skb->nfct, IP_CT_ESTABLISHED_REPLY,
+ niph, nth, tcp_hdr_size);
}
static bool
@@ -301,7 +304,7 @@
XT_SYNPROXY_OPT_SACK_PERM |
XT_SYNPROXY_OPT_ECN);
- synproxy_send_client_synack(skb, th, &opts);
+ synproxy_send_client_synack(snet, skb, th, &opts);
return NF_DROP;
} else if (th->ack && !(th->fin || th->rst || th->syn)) {
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 6f187c8..6d02498 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -348,7 +348,7 @@
fq->ecn |= ecn;
if (payload_len > fq->q.max_size)
fq->q.max_size = payload_len;
- add_frag_mem_limit(&fq->q, skb->truesize);
+ add_frag_mem_limit(fq->q.net, skb->truesize);
/* The first fragment.
* nhoffset is obtained from the first fragment, of course.
@@ -430,7 +430,7 @@
clone->ip_summed = head->ip_summed;
NFCT_FRAG6_CB(clone)->orig = NULL;
- add_frag_mem_limit(&fq->q, clone->truesize);
+ add_frag_mem_limit(fq->q.net, clone->truesize);
}
/* We have to remove fragment header from datagram and to relocate
@@ -454,7 +454,7 @@
head->csum = csum_add(head->csum, fp->csum);
head->truesize += fp->truesize;
}
- sub_frag_mem_limit(&fq->q, head->truesize);
+ sub_frag_mem_limit(fq->q.net, head->truesize);
head->ignore_df = 1;
head->next = NULL;
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index 8ffa2c8..f1159bb 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -144,7 +144,7 @@
IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
- if (fq->q.flags & INET_FRAG_EVICTED)
+ if (inet_frag_evicting(&fq->q))
goto out_rcu_unlock;
IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT);
@@ -330,7 +330,7 @@
fq->q.stamp = skb->tstamp;
fq->q.meat += skb->len;
fq->ecn |= ecn;
- add_frag_mem_limit(&fq->q, skb->truesize);
+ add_frag_mem_limit(fq->q.net, skb->truesize);
/* The first fragment.
* nhoffset is obtained from the first fragment, of course.
@@ -443,7 +443,7 @@
head->len -= clone->len;
clone->csum = 0;
clone->ip_summed = head->ip_summed;
- add_frag_mem_limit(&fq->q, clone->truesize);
+ add_frag_mem_limit(fq->q.net, clone->truesize);
}
/* We have to remove fragment header from datagram and to relocate
@@ -481,7 +481,7 @@
}
fp = next;
}
- sub_frag_mem_limit(&fq->q, sum_truesize);
+ sub_frag_mem_limit(fq->q.net, sum_truesize);
head->next = NULL;
head->dev = dev;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 6090969..d155864 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -318,8 +318,7 @@
/* allocate dst with ip6_dst_ops */
static struct rt6_info *__ip6_dst_alloc(struct net *net,
struct net_device *dev,
- int flags,
- struct fib6_table *table)
+ int flags)
{
struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
0, DST_OBSOLETE_FORCE_CHK, flags);
@@ -336,10 +335,9 @@
static struct rt6_info *ip6_dst_alloc(struct net *net,
struct net_device *dev,
- int flags,
- struct fib6_table *table)
+ int flags)
{
- struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags, table);
+ struct rt6_info *rt = __ip6_dst_alloc(net, dev, flags);
if (rt) {
rt->rt6i_pcpu = alloc_percpu_gfp(struct rt6_info *, GFP_ATOMIC);
@@ -950,8 +948,7 @@
if (ort->rt6i_flags & (RTF_CACHE | RTF_PCPU))
ort = (struct rt6_info *)ort->dst.from;
- rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev,
- 0, ort->rt6i_table);
+ rt = __ip6_dst_alloc(dev_net(ort->dst.dev), ort->dst.dev, 0);
if (!rt)
return NULL;
@@ -983,8 +980,7 @@
struct rt6_info *pcpu_rt;
pcpu_rt = __ip6_dst_alloc(dev_net(rt->dst.dev),
- rt->dst.dev, rt->dst.flags,
- rt->rt6i_table);
+ rt->dst.dev, rt->dst.flags);
if (!pcpu_rt)
return NULL;
@@ -997,32 +993,53 @@
/* It should be called with read_lock_bh(&tb6_lock) acquired */
static struct rt6_info *rt6_get_pcpu_route(struct rt6_info *rt)
{
- struct rt6_info *pcpu_rt, *prev, **p;
+ struct rt6_info *pcpu_rt, **p;
p = this_cpu_ptr(rt->rt6i_pcpu);
pcpu_rt = *p;
- if (pcpu_rt)
- goto done;
+ if (pcpu_rt) {
+ dst_hold(&pcpu_rt->dst);
+ rt6_dst_from_metrics_check(pcpu_rt);
+ }
+ return pcpu_rt;
+}
+
+static struct rt6_info *rt6_make_pcpu_route(struct rt6_info *rt)
+{
+ struct fib6_table *table = rt->rt6i_table;
+ struct rt6_info *pcpu_rt, *prev, **p;
pcpu_rt = ip6_rt_pcpu_alloc(rt);
if (!pcpu_rt) {
struct net *net = dev_net(rt->dst.dev);
- pcpu_rt = net->ipv6.ip6_null_entry;
- goto done;
+ dst_hold(&net->ipv6.ip6_null_entry->dst);
+ return net->ipv6.ip6_null_entry;
}
- prev = cmpxchg(p, NULL, pcpu_rt);
- if (prev) {
- /* If someone did it before us, return prev instead */
+ read_lock_bh(&table->tb6_lock);
+ if (rt->rt6i_pcpu) {
+ p = this_cpu_ptr(rt->rt6i_pcpu);
+ prev = cmpxchg(p, NULL, pcpu_rt);
+ if (prev) {
+ /* If someone did it before us, return prev instead */
+ dst_destroy(&pcpu_rt->dst);
+ pcpu_rt = prev;
+ }
+ } else {
+ /* rt has been removed from the fib6 tree
+ * before we have a chance to acquire the read_lock.
+ * In this case, don't brother to create a pcpu rt
+ * since rt is going away anyway. The next
+ * dst_check() will trigger a re-lookup.
+ */
dst_destroy(&pcpu_rt->dst);
- pcpu_rt = prev;
+ pcpu_rt = rt;
}
-
-done:
dst_hold(&pcpu_rt->dst);
rt6_dst_from_metrics_check(pcpu_rt);
+ read_unlock_bh(&table->tb6_lock);
return pcpu_rt;
}
@@ -1097,9 +1114,22 @@
rt->dst.lastuse = jiffies;
rt->dst.__use++;
pcpu_rt = rt6_get_pcpu_route(rt);
- read_unlock_bh(&table->tb6_lock);
+
+ if (pcpu_rt) {
+ read_unlock_bh(&table->tb6_lock);
+ } else {
+ /* We have to do the read_unlock first
+ * because rt6_make_pcpu_route() may trigger
+ * ip6_dst_gc() which will take the write_lock.
+ */
+ dst_hold(&rt->dst);
+ read_unlock_bh(&table->tb6_lock);
+ pcpu_rt = rt6_make_pcpu_route(rt);
+ dst_release(&rt->dst);
+ }
return pcpu_rt;
+
}
}
@@ -1555,7 +1585,7 @@
if (unlikely(!idev))
return ERR_PTR(-ENODEV);
- rt = ip6_dst_alloc(net, dev, 0, NULL);
+ rt = ip6_dst_alloc(net, dev, 0);
if (unlikely(!rt)) {
in6_dev_put(idev);
dst = ERR_PTR(-ENOMEM);
@@ -1742,7 +1772,8 @@
if (!table)
goto out;
- rt = ip6_dst_alloc(net, NULL, (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT, table);
+ rt = ip6_dst_alloc(net, NULL,
+ (cfg->fc_flags & RTF_ADDRCONF) ? 0 : DST_NOCOUNT);
if (!rt) {
err = -ENOMEM;
@@ -1831,6 +1862,7 @@
int gwa_type;
gw_addr = &cfg->fc_gateway;
+ gwa_type = ipv6_addr_type(gw_addr);
/* if gw_addr is local we will fail to detect this in case
* address is still TENTATIVE (DAD in progress). rt6_lookup()
@@ -1838,11 +1870,12 @@
* prefix route was assigned to, which might be non-loopback.
*/
err = -EINVAL;
- if (ipv6_chk_addr_and_flags(net, gw_addr, NULL, 0, 0))
+ if (ipv6_chk_addr_and_flags(net, gw_addr,
+ gwa_type & IPV6_ADDR_LINKLOCAL ?
+ dev : NULL, 0, 0))
goto out;
rt->rt6i_gateway = *gw_addr;
- gwa_type = ipv6_addr_type(gw_addr);
if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
struct rt6_info *grt;
@@ -2397,7 +2430,7 @@
{
struct net *net = dev_net(idev->dev);
struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev,
- DST_NOCOUNT, NULL);
+ DST_NOCOUNT);
if (!rt)
return ERR_PTR(-ENOMEM);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 6748c42..7a6cea5 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -943,7 +943,7 @@
&ipv6_hdr(skb)->daddr, tcp_v6_iif(skb));
if (req) {
nsk = tcp_check_req(sk, skb, req, false);
- if (!nsk)
+ if (!nsk || nsk == sk)
reqsk_put(req);
return nsk;
}
diff --git a/net/key/af_key.c b/net/key/af_key.c
index b397f0a..83a7068 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -219,7 +219,7 @@
#define BROADCAST_ONE 1
#define BROADCAST_REGISTERED 2
#define BROADCAST_PROMISC_ONLY 4
-static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
+static int pfkey_broadcast(struct sk_buff *skb,
int broadcast_flags, struct sock *one_sk,
struct net *net)
{
@@ -244,7 +244,7 @@
* socket.
*/
if (pfk->promisc)
- pfkey_broadcast_one(skb, &skb2, allocation, sk);
+ pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
/* the exact target will be processed later */
if (sk == one_sk)
@@ -259,7 +259,7 @@
continue;
}
- err2 = pfkey_broadcast_one(skb, &skb2, allocation, sk);
+ err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
/* Error is cleare after succecful sending to at least one
* registered KM */
@@ -269,7 +269,7 @@
rcu_read_unlock();
if (one_sk != NULL)
- err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
+ err = pfkey_broadcast_one(skb, &skb2, GFP_KERNEL, one_sk);
kfree_skb(skb2);
kfree_skb(skb);
@@ -292,7 +292,7 @@
hdr = (struct sadb_msg *) pfk->dump.skb->data;
hdr->sadb_msg_seq = 0;
hdr->sadb_msg_errno = rc;
- pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
+ pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
&pfk->sk, sock_net(&pfk->sk));
pfk->dump.skb = NULL;
}
@@ -333,7 +333,7 @@
hdr->sadb_msg_len = (sizeof(struct sadb_msg) /
sizeof(uint64_t));
- pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk));
+ pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
return 0;
}
@@ -1365,7 +1365,7 @@
xfrm_state_put(x);
- pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk, net);
+ pfkey_broadcast(resp_skb, BROADCAST_ONE, sk, net);
return 0;
}
@@ -1452,7 +1452,7 @@
hdr->sadb_msg_seq = c->seq;
hdr->sadb_msg_pid = c->portid;
- pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x));
+ pfkey_broadcast(skb, BROADCAST_ALL, NULL, xs_net(x));
return 0;
}
@@ -1565,7 +1565,7 @@
out_hdr->sadb_msg_reserved = 0;
out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
+ pfkey_broadcast(out_skb, BROADCAST_ONE, sk, sock_net(sk));
return 0;
}
@@ -1670,7 +1670,7 @@
return -ENOBUFS;
}
- pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk, sock_net(sk));
+ pfkey_broadcast(supp_skb, BROADCAST_REGISTERED, sk, sock_net(sk));
return 0;
}
@@ -1689,7 +1689,7 @@
hdr->sadb_msg_errno = (uint8_t) 0;
hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
- return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
+ return pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
}
static int key_notify_sa_flush(const struct km_event *c)
@@ -1710,7 +1710,7 @@
hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
hdr->sadb_msg_reserved = 0;
- pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
+ pfkey_broadcast(skb, BROADCAST_ALL, NULL, c->net);
return 0;
}
@@ -1767,7 +1767,7 @@
out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
if (pfk->dump.skb)
- pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
+ pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
&pfk->sk, sock_net(&pfk->sk));
pfk->dump.skb = out_skb;
@@ -1847,7 +1847,7 @@
new_hdr->sadb_msg_errno = 0;
}
- pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk));
+ pfkey_broadcast(skb, BROADCAST_ALL, NULL, sock_net(sk));
return 0;
}
@@ -2181,7 +2181,7 @@
out_hdr->sadb_msg_errno = 0;
out_hdr->sadb_msg_seq = c->seq;
out_hdr->sadb_msg_pid = c->portid;
- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp));
+ pfkey_broadcast(out_skb, BROADCAST_ALL, NULL, xp_net(xp));
return 0;
}
@@ -2401,7 +2401,7 @@
out_hdr->sadb_msg_errno = 0;
out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, xp_net(xp));
+ pfkey_broadcast(out_skb, BROADCAST_ONE, sk, xp_net(xp));
err = 0;
out:
@@ -2655,7 +2655,7 @@
out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
if (pfk->dump.skb)
- pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
+ pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
&pfk->sk, sock_net(&pfk->sk));
pfk->dump.skb = out_skb;
@@ -2708,7 +2708,7 @@
hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
hdr->sadb_msg_reserved = 0;
- pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
+ pfkey_broadcast(skb_out, BROADCAST_ALL, NULL, c->net);
return 0;
}
@@ -2770,7 +2770,7 @@
void *ext_hdrs[SADB_EXT_MAX];
int err;
- pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
+ pfkey_broadcast(skb_clone(skb, GFP_KERNEL),
BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
memset(ext_hdrs, 0, sizeof(ext_hdrs));
@@ -2992,7 +2992,7 @@
out_hdr->sadb_msg_seq = 0;
out_hdr->sadb_msg_pid = 0;
- pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
+ pfkey_broadcast(out_skb, BROADCAST_REGISTERED, NULL, xs_net(x));
return 0;
}
@@ -3182,7 +3182,7 @@
xfrm_ctx->ctx_len);
}
- return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
+ return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
}
static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
@@ -3380,7 +3380,7 @@
n_port->sadb_x_nat_t_port_port = sport;
n_port->sadb_x_nat_t_port_reserved = 0;
- return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x));
+ return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
}
#ifdef CONFIG_NET_KEY_MIGRATE
@@ -3572,7 +3572,7 @@
}
/* broadcast migrate message to sockets */
- pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net);
+ pfkey_broadcast(skb, BROADCAST_ALL, NULL, &init_net);
return 0;
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 8fd9feb..8dab4e5 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -613,7 +613,7 @@
if (signal_pending(current))
break;
rc = 0;
- if (sk_wait_data(sk, &timeo))
+ if (sk_wait_data(sk, &timeo, NULL))
break;
}
return rc;
@@ -802,7 +802,7 @@
release_sock(sk);
lock_sock(sk);
} else
- sk_wait_data(sk, &timeo);
+ sk_wait_data(sk, &timeo, NULL);
if ((flags & MSG_PEEK) && peek_seq != llc->copied_seq) {
net_dbg_ratelimited("LLC(%s:%d): Application bug, race in MSG_PEEK\n",
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 29236e8..c09c013 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -723,6 +723,7 @@
debugfs_remove_recursive(sdata->vif.debugfs_dir);
sdata->vif.debugfs_dir = NULL;
+ sdata->debugfs.subdir_stations = NULL;
}
void ieee80211_debugfs_rename_netdev(struct ieee80211_sub_if_data *sdata)
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index ed1edac..553ac6d 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1863,10 +1863,6 @@
ieee80211_teardown_sdata(sdata);
}
-/*
- * Remove all interfaces, may only be called at hardware unregistration
- * time because it doesn't do RCU-safe list removals.
- */
void ieee80211_remove_interfaces(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata, *tmp;
@@ -1875,14 +1871,21 @@
ASSERT_RTNL();
- /*
- * Close all AP_VLAN interfaces first, as otherwise they
- * might be closed while the AP interface they belong to
- * is closed, causing unregister_netdevice_many() to crash.
+ /* Before destroying the interfaces, make sure they're all stopped so
+ * that the hardware is stopped. Otherwise, the driver might still be
+ * iterating the interfaces during the shutdown, e.g. from a worker
+ * or from RX processing or similar, and if it does so (using atomic
+ * iteration) while we're manipulating the list, the iteration will
+ * crash.
+ *
+ * After this, the hardware should be stopped and the driver should
+ * have stopped all of its activities, so that we can do RCU-unaware
+ * manipulations of the interface list below.
*/
- list_for_each_entry(sdata, &local->interfaces, list)
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- dev_close(sdata->dev);
+ cfg80211_shutdown_all_interfaces(local->hw.wiphy);
+
+ WARN(local->open_count, "%s: open count remains %d\n",
+ wiphy_name(local->hw.wiphy), local->open_count);
mutex_lock(&local->iflist_mtx);
list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 5438d13..3b59099 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -306,7 +306,7 @@
if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
/* AID */
pos = skb_put(skb, 2);
- put_unaligned_le16(plid, pos + 2);
+ put_unaligned_le16(plid, pos);
}
if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
@@ -1122,6 +1122,9 @@
WLAN_SP_MESH_PEERING_CONFIRM) {
baseaddr += 4;
baselen += 4;
+
+ if (baselen > len)
+ return;
}
ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems);
mesh_process_plink_frame(sdata, mgmt, &elems);
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 06b60980..b676b9f 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -76,6 +76,22 @@
if (sdata->vif.type != NL80211_IFTYPE_STATION)
continue;
ieee80211_mgd_quiesce(sdata);
+ /* If suspended during TX in progress, and wowlan
+ * is enabled (connection will be active) there
+ * can be a race where the driver is put out
+ * of power-save due to TX and during suspend
+ * dynamic_ps_timer is cancelled and TX packet
+ * is flushed, leaving the driver in ACTIVE even
+ * after resuming until dynamic_ps_timer puts
+ * driver back in DOZE.
+ */
+ if (sdata->u.mgd.associated &&
+ sdata->u.mgd.powersave &&
+ !(local->hw.conf.flags & IEEE80211_CONF_PS)) {
+ local->hw.conf.flags |= IEEE80211_CONF_PS;
+ ieee80211_hw_config(local,
+ IEEE80211_CONF_CHANGE_PS);
+ }
}
err = drv_suspend(local, wowlan);
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 247552a..3ece7d1 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -92,14 +92,15 @@
static inline void
minstrel_sort_best_tp_rates(struct minstrel_sta_info *mi, int i, u8 *tp_list)
{
- int j = MAX_THR_RATES;
- struct minstrel_rate_stats *tmp_mrs = &mi->r[j - 1].stats;
+ int j;
+ struct minstrel_rate_stats *tmp_mrs;
struct minstrel_rate_stats *cur_mrs = &mi->r[i].stats;
- while (j > 0 && (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) >
- minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))) {
- j--;
+ for (j = MAX_THR_RATES; j > 0; --j) {
tmp_mrs = &mi->r[tp_list[j - 1]].stats;
+ if (minstrel_get_tp_avg(&mi->r[i], cur_mrs->prob_ewma) <=
+ minstrel_get_tp_avg(&mi->r[tp_list[j - 1]], tmp_mrs->prob_ewma))
+ break;
}
if (j < MAX_THR_RATES - 1)
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index ad31b2d..8db6e29 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -60,6 +60,7 @@
struct ieee80211_channel *ch;
struct cfg80211_chan_def chandef;
int i, subband_start;
+ struct wiphy *wiphy = sdata->local->hw.wiphy;
for (i = start; i <= end; i += spacing) {
if (!ch_cnt)
@@ -70,9 +71,8 @@
/* we will be active on the channel */
cfg80211_chandef_create(&chandef, ch,
NL80211_CHAN_NO_HT);
- if (cfg80211_reg_can_beacon(sdata->local->hw.wiphy,
- &chandef,
- sdata->wdev.iftype)) {
+ if (cfg80211_reg_can_beacon_relax(wiphy, &chandef,
+ sdata->wdev.iftype)) {
ch_cnt++;
/*
* check if the next channel is also part of
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8410bb3..b823350 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1117,7 +1117,9 @@
queued = true;
info->control.vif = &tx->sdata->vif;
info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
- info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS;
+ info->flags &= ~IEEE80211_TX_TEMPORARY_FLAGS |
+ IEEE80211_TX_CTL_NO_PS_BUFFER |
+ IEEE80211_TX_STATUS_EOSP;
__skb_queue_tail(&tid_tx->pending, skb);
if (skb_queue_len(&tid_tx->pending) > STA_MAX_TX_BUFFER)
purge_skb = __skb_dequeue(&tid_tx->pending);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 5d2b806..38fbc19 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -319,7 +319,13 @@
* return *ignored=0 i.e. ICMP and NF_DROP
*/
sched = rcu_dereference(svc->scheduler);
- dest = sched->schedule(svc, skb, iph);
+ if (sched) {
+ /* read svc->sched_data after svc->scheduler */
+ smp_rmb();
+ dest = sched->schedule(svc, skb, iph);
+ } else {
+ dest = NULL;
+ }
if (!dest) {
IP_VS_DBG(1, "p-schedule: no dest found.\n");
kfree(param.pe_data);
@@ -467,7 +473,13 @@
}
sched = rcu_dereference(svc->scheduler);
- dest = sched->schedule(svc, skb, iph);
+ if (sched) {
+ /* read svc->sched_data after svc->scheduler */
+ smp_rmb();
+ dest = sched->schedule(svc, skb, iph);
+ } else {
+ dest = NULL;
+ }
if (dest == NULL) {
IP_VS_DBG(1, "Schedule: no dest found.\n");
return NULL;
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 285eae3..24c5542 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -842,15 +842,16 @@
__ip_vs_dst_cache_reset(dest);
spin_unlock_bh(&dest->dst_lock);
- sched = rcu_dereference_protected(svc->scheduler, 1);
if (add) {
ip_vs_start_estimator(svc->net, &dest->stats);
list_add_rcu(&dest->n_list, &svc->destinations);
svc->num_dests++;
- if (sched->add_dest)
+ sched = rcu_dereference_protected(svc->scheduler, 1);
+ if (sched && sched->add_dest)
sched->add_dest(svc, dest);
} else {
- if (sched->upd_dest)
+ sched = rcu_dereference_protected(svc->scheduler, 1);
+ if (sched && sched->upd_dest)
sched->upd_dest(svc, dest);
}
}
@@ -1084,7 +1085,7 @@
struct ip_vs_scheduler *sched;
sched = rcu_dereference_protected(svc->scheduler, 1);
- if (sched->del_dest)
+ if (sched && sched->del_dest)
sched->del_dest(svc, dest);
}
}
@@ -1175,11 +1176,14 @@
ip_vs_use_count_inc();
/* Lookup the scheduler by 'u->sched_name' */
- sched = ip_vs_scheduler_get(u->sched_name);
- if (sched == NULL) {
- pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name);
- ret = -ENOENT;
- goto out_err;
+ if (strcmp(u->sched_name, "none")) {
+ sched = ip_vs_scheduler_get(u->sched_name);
+ if (!sched) {
+ pr_info("Scheduler module ip_vs_%s not found\n",
+ u->sched_name);
+ ret = -ENOENT;
+ goto out_err;
+ }
}
if (u->pe_name && *u->pe_name) {
@@ -1240,10 +1244,12 @@
spin_lock_init(&svc->stats.lock);
/* Bind the scheduler */
- ret = ip_vs_bind_scheduler(svc, sched);
- if (ret)
- goto out_err;
- sched = NULL;
+ if (sched) {
+ ret = ip_vs_bind_scheduler(svc, sched);
+ if (ret)
+ goto out_err;
+ sched = NULL;
+ }
/* Bind the ct retriever */
RCU_INIT_POINTER(svc->pe, pe);
@@ -1291,17 +1297,20 @@
static int
ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u)
{
- struct ip_vs_scheduler *sched, *old_sched;
+ struct ip_vs_scheduler *sched = NULL, *old_sched;
struct ip_vs_pe *pe = NULL, *old_pe = NULL;
int ret = 0;
/*
* Lookup the scheduler, by 'u->sched_name'
*/
- sched = ip_vs_scheduler_get(u->sched_name);
- if (sched == NULL) {
- pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name);
- return -ENOENT;
+ if (strcmp(u->sched_name, "none")) {
+ sched = ip_vs_scheduler_get(u->sched_name);
+ if (!sched) {
+ pr_info("Scheduler module ip_vs_%s not found\n",
+ u->sched_name);
+ return -ENOENT;
+ }
}
old_sched = sched;
@@ -1329,14 +1338,20 @@
old_sched = rcu_dereference_protected(svc->scheduler, 1);
if (sched != old_sched) {
- /* Bind the new scheduler */
- ret = ip_vs_bind_scheduler(svc, sched);
- if (ret) {
- old_sched = sched;
- goto out;
+ if (old_sched) {
+ ip_vs_unbind_scheduler(svc, old_sched);
+ RCU_INIT_POINTER(svc->scheduler, NULL);
+ /* Wait all svc->sched_data users */
+ synchronize_rcu();
}
- /* Unbind the old scheduler on success */
- ip_vs_unbind_scheduler(svc, old_sched);
+ /* Bind the new scheduler */
+ if (sched) {
+ ret = ip_vs_bind_scheduler(svc, sched);
+ if (ret) {
+ ip_vs_scheduler_put(sched);
+ goto out;
+ }
+ }
}
/*
@@ -1982,6 +1997,7 @@
const struct ip_vs_iter *iter = seq->private;
const struct ip_vs_dest *dest;
struct ip_vs_scheduler *sched = rcu_dereference(svc->scheduler);
+ char *sched_name = sched ? sched->name : "none";
if (iter->table == ip_vs_svc_table) {
#ifdef CONFIG_IP_VS_IPV6
@@ -1990,18 +2006,18 @@
ip_vs_proto_name(svc->protocol),
&svc->addr.in6,
ntohs(svc->port),
- sched->name);
+ sched_name);
else
#endif
seq_printf(seq, "%s %08X:%04X %s %s ",
ip_vs_proto_name(svc->protocol),
ntohl(svc->addr.ip),
ntohs(svc->port),
- sched->name,
+ sched_name,
(svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":"");
} else {
seq_printf(seq, "FWM %08X %s %s",
- svc->fwmark, sched->name,
+ svc->fwmark, sched_name,
(svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":"");
}
@@ -2427,13 +2443,15 @@
{
struct ip_vs_scheduler *sched;
struct ip_vs_kstats kstats;
+ char *sched_name;
sched = rcu_dereference_protected(src->scheduler, 1);
+ sched_name = sched ? sched->name : "none";
dst->protocol = src->protocol;
dst->addr = src->addr.ip;
dst->port = src->port;
dst->fwmark = src->fwmark;
- strlcpy(dst->sched_name, sched->name, sizeof(dst->sched_name));
+ strlcpy(dst->sched_name, sched_name, sizeof(dst->sched_name));
dst->flags = src->flags;
dst->timeout = src->timeout / HZ;
dst->netmask = src->netmask;
@@ -2892,6 +2910,7 @@
struct ip_vs_flags flags = { .flags = svc->flags,
.mask = ~0 };
struct ip_vs_kstats kstats;
+ char *sched_name;
nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE);
if (!nl_service)
@@ -2910,8 +2929,9 @@
}
sched = rcu_dereference_protected(svc->scheduler, 1);
+ sched_name = sched ? sched->name : "none";
pe = rcu_dereference_protected(svc->pe, 1);
- if (nla_put_string(skb, IPVS_SVC_ATTR_SCHED_NAME, sched->name) ||
+ if (nla_put_string(skb, IPVS_SVC_ATTR_SCHED_NAME, sched_name) ||
(pe && nla_put_string(skb, IPVS_SVC_ATTR_PE_NAME, pe->name)) ||
nla_put(skb, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags) ||
nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) ||
diff --git a/net/netfilter/ipvs/ip_vs_sched.c b/net/netfilter/ipvs/ip_vs_sched.c
index 199760c..7e81416 100644
--- a/net/netfilter/ipvs/ip_vs_sched.c
+++ b/net/netfilter/ipvs/ip_vs_sched.c
@@ -74,7 +74,7 @@
if (sched->done_service)
sched->done_service(svc);
- /* svc->scheduler can not be set to NULL */
+ /* svc->scheduler can be set to NULL only by caller */
}
@@ -147,21 +147,21 @@
void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg)
{
- struct ip_vs_scheduler *sched;
+ struct ip_vs_scheduler *sched = rcu_dereference(svc->scheduler);
+ char *sched_name = sched ? sched->name : "none";
- sched = rcu_dereference(svc->scheduler);
if (svc->fwmark) {
IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n",
- sched->name, svc->fwmark, svc->fwmark, msg);
+ sched_name, svc->fwmark, svc->fwmark, msg);
#ifdef CONFIG_IP_VS_IPV6
} else if (svc->af == AF_INET6) {
IP_VS_ERR_RL("%s: %s [%pI6c]:%d - %s\n",
- sched->name, ip_vs_proto_name(svc->protocol),
+ sched_name, ip_vs_proto_name(svc->protocol),
&svc->addr.in6, ntohs(svc->port), msg);
#endif
} else {
IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n",
- sched->name, ip_vs_proto_name(svc->protocol),
+ sched_name, ip_vs_proto_name(svc->protocol),
&svc->addr.ip, ntohs(svc->port), msg);
}
}
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index b08ba95..d99ad93e 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -612,7 +612,7 @@
pkts = atomic_add_return(1, &cp->in_pkts);
else
pkts = sysctl_sync_threshold(ipvs);
- ip_vs_sync_conn(net, cp->control, pkts);
+ ip_vs_sync_conn(net, cp, pkts);
}
}
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index bf66a86..258a0b0 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -130,7 +130,6 @@
memset(&fl4, 0, sizeof(fl4));
fl4.daddr = daddr;
- fl4.saddr = (rt_mode & IP_VS_RT_MODE_CONNECT) ? *saddr : 0;
fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ?
FLOWI_FLAG_KNOWN_NH : 0;
@@ -505,6 +504,13 @@
return -1;
err_unreach:
+ /* The ip6_link_failure function requires the dev field to be set
+ * in order to get the net (further for the sake of fwmark
+ * reflection).
+ */
+ if (!skb->dev)
+ skb->dev = skb_dst(skb)->dev;
+
dst_link_failure(skb);
return -1;
}
@@ -523,10 +529,27 @@
if (ret == NF_ACCEPT) {
nf_reset(skb);
skb_forward_csum(skb);
+ if (!skb->sk)
+ skb_sender_cpu_clear(skb);
}
return ret;
}
+/* In the event of a remote destination, it's possible that we would have
+ * matches against an old socket (particularly a TIME-WAIT socket). This
+ * causes havoc down the line (ip_local_out et. al. expect regular sockets
+ * and invalid memory accesses will happen) so simply drop the association
+ * in this case.
+*/
+static inline void ip_vs_drop_early_demux_sk(struct sk_buff *skb)
+{
+ /* If dev is set, the packet came from the LOCAL_IN callback and
+ * not from a local TCP socket.
+ */
+ if (skb->dev)
+ skb_orphan(skb);
+}
+
/* return NF_STOLEN (sent) or NF_ACCEPT if local=1 (not sent) */
static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb,
struct ip_vs_conn *cp, int local)
@@ -538,12 +561,23 @@
ip_vs_notrack(skb);
else
ip_vs_update_conntrack(skb, cp, 1);
+
+ /* Remove the early_demux association unless it's bound for the
+ * exact same port and address on this host after translation.
+ */
+ if (!local || cp->vport != cp->dport ||
+ !ip_vs_addr_equal(cp->af, &cp->vaddr, &cp->daddr))
+ ip_vs_drop_early_demux_sk(skb);
+
if (!local) {
skb_forward_csum(skb);
+ if (!skb->sk)
+ skb_sender_cpu_clear(skb);
NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb,
NULL, skb_dst(skb)->dev, dst_output_sk);
} else
ret = NF_ACCEPT;
+
return ret;
}
@@ -557,7 +591,10 @@
if (likely(!(cp->flags & IP_VS_CONN_F_NFCT)))
ip_vs_notrack(skb);
if (!local) {
+ ip_vs_drop_early_demux_sk(skb);
skb_forward_csum(skb);
+ if (!skb->sk)
+ skb_sender_cpu_clear(skb);
NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb,
NULL, skb_dst(skb)->dev, dst_output_sk);
} else
@@ -845,6 +882,8 @@
struct ipv6hdr *old_ipv6h = NULL;
#endif
+ ip_vs_drop_early_demux_sk(skb);
+
if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) {
new_skb = skb_realloc_headroom(skb, max_headroom);
if (!new_skb)
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 13fad86..3c20d02 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -287,6 +287,46 @@
spin_unlock(&pcpu->lock);
}
+/* Released via destroy_conntrack() */
+struct nf_conn *nf_ct_tmpl_alloc(struct net *net, u16 zone, gfp_t flags)
+{
+ struct nf_conn *tmpl;
+
+ tmpl = kzalloc(sizeof(*tmpl), flags);
+ if (tmpl == NULL)
+ return NULL;
+
+ tmpl->status = IPS_TEMPLATE;
+ write_pnet(&tmpl->ct_net, net);
+
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+ if (zone) {
+ struct nf_conntrack_zone *nf_ct_zone;
+
+ nf_ct_zone = nf_ct_ext_add(tmpl, NF_CT_EXT_ZONE, flags);
+ if (!nf_ct_zone)
+ goto out_free;
+ nf_ct_zone->id = zone;
+ }
+#endif
+ atomic_set(&tmpl->ct_general.use, 0);
+
+ return tmpl;
+#ifdef CONFIG_NF_CONNTRACK_ZONES
+out_free:
+ kfree(tmpl);
+ return NULL;
+#endif
+}
+EXPORT_SYMBOL_GPL(nf_ct_tmpl_alloc);
+
+static void nf_ct_tmpl_free(struct nf_conn *tmpl)
+{
+ nf_ct_ext_destroy(tmpl);
+ nf_ct_ext_free(tmpl);
+ kfree(tmpl);
+}
+
static void
destroy_conntrack(struct nf_conntrack *nfct)
{
@@ -298,6 +338,10 @@
NF_CT_ASSERT(atomic_read(&nfct->use) == 0);
NF_CT_ASSERT(!timer_pending(&ct->timeout));
+ if (unlikely(nf_ct_is_template(ct))) {
+ nf_ct_tmpl_free(ct);
+ return;
+ }
rcu_read_lock();
l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
if (l4proto && l4proto->destroy)
@@ -540,28 +584,6 @@
}
EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert);
-/* deletion from this larval template list happens via nf_ct_put() */
-void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl)
-{
- struct ct_pcpu *pcpu;
-
- __set_bit(IPS_TEMPLATE_BIT, &tmpl->status);
- __set_bit(IPS_CONFIRMED_BIT, &tmpl->status);
- nf_conntrack_get(&tmpl->ct_general);
-
- /* add this conntrack to the (per cpu) tmpl list */
- local_bh_disable();
- tmpl->cpu = smp_processor_id();
- pcpu = per_cpu_ptr(nf_ct_net(tmpl)->ct.pcpu_lists, tmpl->cpu);
-
- spin_lock(&pcpu->lock);
- /* Overload tuple linked list to put us in template list. */
- hlist_nulls_add_head_rcu(&tmpl->tuplehash[IP_CT_DIR_ORIGINAL].hnnode,
- &pcpu->tmpl);
- spin_unlock_bh(&pcpu->lock);
-}
-EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert);
-
/* Confirm a connection given skb; places it in hash table */
int
__nf_conntrack_confirm(struct sk_buff *skb)
@@ -1522,10 +1544,8 @@
sz = nr_slots * sizeof(struct hlist_nulls_head);
hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
get_order(sz));
- if (!hash) {
- printk(KERN_WARNING "nf_conntrack: falling back to vmalloc.\n");
+ if (!hash)
hash = vzalloc(sz);
- }
if (hash && nulls)
for (i = 0; i < nr_slots; i++)
@@ -1751,7 +1771,6 @@
spin_lock_init(&pcpu->lock);
INIT_HLIST_NULLS_HEAD(&pcpu->unconfirmed, UNCONFIRMED_NULLS_VAL);
INIT_HLIST_NULLS_HEAD(&pcpu->dying, DYING_NULLS_VAL);
- INIT_HLIST_NULLS_HEAD(&pcpu->tmpl, TEMPLATE_NULLS_VAL);
}
net->ct.stat = alloc_percpu(struct ip_conntrack_stat);
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 7a17070..b45a422 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -219,7 +219,8 @@
a->mask.src.u3.all[count] & b->mask.src.u3.all[count];
}
- return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask);
+ return nf_ct_tuple_mask_cmp(&a->tuple, &b->tuple, &intersect_mask) &&
+ nf_ct_zone(a->master) == nf_ct_zone(b->master);
}
static inline int expect_matches(const struct nf_conntrack_expect *a,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index d1c2394..6b8b0ab 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -2995,11 +2995,6 @@
}
err = nf_ct_expect_related_report(exp, portid, report);
- if (err < 0)
- goto err_exp;
-
- return 0;
-err_exp:
nf_ct_expect_put(exp);
err_ct:
nf_ct_put(ct);
diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
index 789feea..d7f1685 100644
--- a/net/netfilter/nf_synproxy_core.c
+++ b/net/netfilter/nf_synproxy_core.c
@@ -349,23 +349,20 @@
static int __net_init synproxy_net_init(struct net *net)
{
struct synproxy_net *snet = synproxy_pernet(net);
- struct nf_conntrack_tuple t;
struct nf_conn *ct;
int err = -ENOMEM;
- memset(&t, 0, sizeof(t));
- ct = nf_conntrack_alloc(net, 0, &t, &t, GFP_KERNEL);
- if (IS_ERR(ct)) {
- err = PTR_ERR(ct);
+ ct = nf_ct_tmpl_alloc(net, 0, GFP_KERNEL);
+ if (!ct)
goto err1;
- }
if (!nfct_seqadj_ext_add(ct))
goto err2;
if (!nfct_synproxy_ext_add(ct))
goto err2;
- nf_conntrack_tmpl_insert(net, ct);
+ __set_bit(IPS_CONFIRMED_BIT, &ct->status);
+ nf_conntrack_get(&ct->ct_general);
snet->tmpl = ct;
snet->stats = alloc_percpu(struct synproxy_stats);
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 75747ae..43ddeee 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -184,7 +184,6 @@
static int xt_ct_tg_check(const struct xt_tgchk_param *par,
struct xt_ct_target_info_v1 *info)
{
- struct nf_conntrack_tuple t;
struct nf_conn *ct;
int ret = -EOPNOTSUPP;
@@ -202,11 +201,11 @@
if (ret < 0)
goto err1;
- memset(&t, 0, sizeof(t));
- ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
- ret = PTR_ERR(ct);
- if (IS_ERR(ct))
+ ct = nf_ct_tmpl_alloc(par->net, info->zone, GFP_KERNEL);
+ if (!ct) {
+ ret = -ENOMEM;
goto err2;
+ }
ret = 0;
if ((info->ct_events || info->exp_events) &&
@@ -227,8 +226,8 @@
if (ret < 0)
goto err3;
}
-
- nf_conntrack_tmpl_insert(par->net, ct);
+ __set_bit(IPS_CONFIRMED_BIT, &ct->status);
+ nf_conntrack_get(&ct->ct_general);
out:
info->ct = ct;
return 0;
diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c
index f407ebc1..29d2c31 100644
--- a/net/netfilter/xt_IDLETIMER.c
+++ b/net/netfilter/xt_IDLETIMER.c
@@ -126,6 +126,7 @@
goto out;
}
+ sysfs_attr_init(&info->timer->attr.attr);
info->timer->attr.attr.name = kstrdup(info->label, GFP_KERNEL);
if (!info->timer->attr.attr.name) {
ret = -ENOMEM;
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 9a0ae71..a774985 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -357,25 +357,52 @@
return NULL;
}
+
+static void
+__netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, bool tx_ring, void **pg_vec,
+ unsigned int order)
+{
+ struct netlink_sock *nlk = nlk_sk(sk);
+ struct sk_buff_head *queue;
+ struct netlink_ring *ring;
+
+ queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue;
+ ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring;
+
+ spin_lock_bh(&queue->lock);
+
+ ring->frame_max = req->nm_frame_nr - 1;
+ ring->head = 0;
+ ring->frame_size = req->nm_frame_size;
+ ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE;
+
+ swap(ring->pg_vec_len, req->nm_block_nr);
+ swap(ring->pg_vec_order, order);
+ swap(ring->pg_vec, pg_vec);
+
+ __skb_queue_purge(queue);
+ spin_unlock_bh(&queue->lock);
+
+ WARN_ON(atomic_read(&nlk->mapped));
+
+ if (pg_vec)
+ free_pg_vec(pg_vec, order, req->nm_block_nr);
+}
+
static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req,
- bool closing, bool tx_ring)
+ bool tx_ring)
{
struct netlink_sock *nlk = nlk_sk(sk);
struct netlink_ring *ring;
- struct sk_buff_head *queue;
void **pg_vec = NULL;
unsigned int order = 0;
- int err;
ring = tx_ring ? &nlk->tx_ring : &nlk->rx_ring;
- queue = tx_ring ? &sk->sk_write_queue : &sk->sk_receive_queue;
- if (!closing) {
- if (atomic_read(&nlk->mapped))
- return -EBUSY;
- if (atomic_read(&ring->pending))
- return -EBUSY;
- }
+ if (atomic_read(&nlk->mapped))
+ return -EBUSY;
+ if (atomic_read(&ring->pending))
+ return -EBUSY;
if (req->nm_block_nr) {
if (ring->pg_vec != NULL)
@@ -407,31 +434,19 @@
return -EINVAL;
}
- err = -EBUSY;
mutex_lock(&nlk->pg_vec_lock);
- if (closing || atomic_read(&nlk->mapped) == 0) {
- err = 0;
- spin_lock_bh(&queue->lock);
-
- ring->frame_max = req->nm_frame_nr - 1;
- ring->head = 0;
- ring->frame_size = req->nm_frame_size;
- ring->pg_vec_pages = req->nm_block_size / PAGE_SIZE;
-
- swap(ring->pg_vec_len, req->nm_block_nr);
- swap(ring->pg_vec_order, order);
- swap(ring->pg_vec, pg_vec);
-
- __skb_queue_purge(queue);
- spin_unlock_bh(&queue->lock);
-
- WARN_ON(atomic_read(&nlk->mapped));
+ if (atomic_read(&nlk->mapped) == 0) {
+ __netlink_set_ring(sk, req, tx_ring, pg_vec, order);
+ mutex_unlock(&nlk->pg_vec_lock);
+ return 0;
}
+
mutex_unlock(&nlk->pg_vec_lock);
if (pg_vec)
free_pg_vec(pg_vec, order, req->nm_block_nr);
- return err;
+
+ return -EBUSY;
}
static void netlink_mm_open(struct vm_area_struct *vma)
@@ -900,10 +915,10 @@
memset(&req, 0, sizeof(req));
if (nlk->rx_ring.pg_vec)
- netlink_set_ring(sk, &req, true, false);
+ __netlink_set_ring(sk, &req, false, NULL, 0);
memset(&req, 0, sizeof(req));
if (nlk->tx_ring.pg_vec)
- netlink_set_ring(sk, &req, true, true);
+ __netlink_set_ring(sk, &req, true, NULL, 0);
}
#endif /* CONFIG_NETLINK_MMAP */
@@ -1081,6 +1096,11 @@
err = __netlink_insert(table, sk);
if (err) {
+ /* In case the hashtable backend returns with -EBUSY
+ * from here, it must not escape to the caller.
+ */
+ if (unlikely(err == -EBUSY))
+ err = -EOVERFLOW;
if (err == -EEXIST)
err = -EADDRINUSE;
nlk_sk(sk)->portid = 0;
@@ -2223,7 +2243,7 @@
return -EINVAL;
if (copy_from_user(&req, optval, sizeof(req)))
return -EFAULT;
- err = netlink_set_ring(sk, &req, false,
+ err = netlink_set_ring(sk, &req,
optname == NETLINK_TX_RING);
break;
}
@@ -2381,7 +2401,7 @@
* sendmsg(), but that's what we've got...
*/
if (netlink_tx_is_mmaped(sk) &&
- msg->msg_iter.type == ITER_IOVEC &&
+ iter_is_iovec(&msg->msg_iter) &&
msg->msg_iter.nr_segs == 1 &&
msg->msg_iter.iov->iov_base == NULL) {
err = netlink_mmap_sendmsg(sk, msg, dst_portid, dst_group,
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 8a8c0b8..ee34f47 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -273,28 +273,36 @@
return 0;
}
-static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
- __be32 *addr, __be32 new_addr)
+static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh,
+ __be32 addr, __be32 new_addr)
{
int transport_len = skb->len - skb_transport_offset(skb);
+ if (nh->frag_off & htons(IP_OFFSET))
+ return;
+
if (nh->protocol == IPPROTO_TCP) {
if (likely(transport_len >= sizeof(struct tcphdr)))
inet_proto_csum_replace4(&tcp_hdr(skb)->check, skb,
- *addr, new_addr, 1);
+ addr, new_addr, 1);
} else if (nh->protocol == IPPROTO_UDP) {
if (likely(transport_len >= sizeof(struct udphdr))) {
struct udphdr *uh = udp_hdr(skb);
if (uh->check || skb->ip_summed == CHECKSUM_PARTIAL) {
inet_proto_csum_replace4(&uh->check, skb,
- *addr, new_addr, 1);
+ addr, new_addr, 1);
if (!uh->check)
uh->check = CSUM_MANGLED_0;
}
}
}
+}
+static void set_ip_addr(struct sk_buff *skb, struct iphdr *nh,
+ __be32 *addr, __be32 new_addr)
+{
+ update_ip_l4_checksum(skb, nh, *addr, new_addr);
csum_replace4(&nh->check, *addr, new_addr);
skb_clear_hash(skb);
*addr = new_addr;
diff --git a/net/openvswitch/flow_table.c b/net/openvswitch/flow_table.c
index 4613df8..6552394 100644
--- a/net/openvswitch/flow_table.c
+++ b/net/openvswitch/flow_table.c
@@ -752,7 +752,7 @@
BUILD_BUG_ON(sizeof(struct sw_flow_key) % sizeof(long));
flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow)
- + (num_possible_nodes()
+ + (nr_node_ids
* sizeof(struct flow_stats *)),
0, 0, NULL);
if (flow_cache == NULL)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index c9e8741..ed458b3 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2403,7 +2403,8 @@
}
tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto,
addr, hlen);
- if (tp_len > dev->mtu + dev->hard_header_len) {
+ if (likely(tp_len >= 0) &&
+ tp_len > dev->mtu + dev->hard_header_len) {
struct ethhdr *ehdr;
/* Earlier code assumed this would be a VLAN pkt,
* double-check this now that we have the actual
@@ -2784,7 +2785,7 @@
static int packet_do_bind(struct sock *sk, struct net_device *dev, __be16 proto)
{
struct packet_sock *po = pkt_sk(sk);
- const struct net_device *dev_curr;
+ struct net_device *dev_curr;
__be16 proto_curr;
bool need_rehook;
@@ -2808,15 +2809,13 @@
po->num = proto;
po->prot_hook.type = proto;
-
- if (po->prot_hook.dev)
- dev_put(po->prot_hook.dev);
-
po->prot_hook.dev = dev;
po->ifindex = dev ? dev->ifindex : 0;
packet_cached_dev_assign(po, dev);
}
+ if (dev_curr)
+ dev_put(dev_curr);
if (proto == 0 || !need_rehook)
goto out_unlock;
diff --git a/net/rds/info.c b/net/rds/info.c
index 9a6b4f6..140a44a 100644
--- a/net/rds/info.c
+++ b/net/rds/info.c
@@ -176,7 +176,7 @@
/* check for all kinds of wrapping and the like */
start = (unsigned long)optval;
- if (len < 0 || len + PAGE_SIZE - 1 < len || start + len < start) {
+ if (len < 0 || len > INT_MAX - PAGE_SIZE + 1 || start + len < start) {
ret = -EINVAL;
goto out;
}
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index af427a3..43ec926 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -45,7 +45,7 @@
}
EXPORT_SYMBOL(tcf_hash_destroy);
-int tcf_hash_release(struct tc_action *a, int bind)
+int __tcf_hash_release(struct tc_action *a, bool bind, bool strict)
{
struct tcf_common *p = a->priv;
int ret = 0;
@@ -53,7 +53,7 @@
if (p) {
if (bind)
p->tcfc_bindcnt--;
- else if (p->tcfc_bindcnt > 0)
+ else if (strict && p->tcfc_bindcnt > 0)
return -EPERM;
p->tcfc_refcnt--;
@@ -64,9 +64,10 @@
ret = 1;
}
}
+
return ret;
}
-EXPORT_SYMBOL(tcf_hash_release);
+EXPORT_SYMBOL(__tcf_hash_release);
static int tcf_dump_walker(struct sk_buff *skb, struct netlink_callback *cb,
struct tc_action *a)
@@ -136,7 +137,7 @@
head = &hinfo->htab[tcf_hash(i, hinfo->hmask)];
hlist_for_each_entry_safe(p, n, head, tcfc_head) {
a->priv = p;
- ret = tcf_hash_release(a, 0);
+ ret = __tcf_hash_release(a, false, true);
if (ret == ACT_P_DELETED) {
module_put(a->ops->owner);
n_i++;
@@ -408,7 +409,7 @@
int ret = 0;
list_for_each_entry_safe(a, tmp, actions, list) {
- ret = tcf_hash_release(a, bind);
+ ret = __tcf_hash_release(a, bind, true);
if (ret == ACT_P_DELETED)
module_put(a->ops->owner);
else if (ret < 0)
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index 1d56903..d0edeb7 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -27,9 +27,10 @@
struct tcf_bpf_cfg {
struct bpf_prog *filter;
struct sock_filter *bpf_ops;
- char *bpf_name;
+ const char *bpf_name;
u32 bpf_fd;
u16 bpf_num_ops;
+ bool is_ebpf;
};
static int tcf_bpf(struct sk_buff *skb, const struct tc_action *act,
@@ -207,6 +208,7 @@
cfg->bpf_ops = bpf_ops;
cfg->bpf_num_ops = bpf_num_ops;
cfg->filter = fp;
+ cfg->is_ebpf = false;
return 0;
}
@@ -241,18 +243,40 @@
cfg->bpf_fd = bpf_fd;
cfg->bpf_name = name;
cfg->filter = fp;
+ cfg->is_ebpf = true;
return 0;
}
+static void tcf_bpf_cfg_cleanup(const struct tcf_bpf_cfg *cfg)
+{
+ if (cfg->is_ebpf)
+ bpf_prog_put(cfg->filter);
+ else
+ bpf_prog_destroy(cfg->filter);
+
+ kfree(cfg->bpf_ops);
+ kfree(cfg->bpf_name);
+}
+
+static void tcf_bpf_prog_fill_cfg(const struct tcf_bpf *prog,
+ struct tcf_bpf_cfg *cfg)
+{
+ cfg->is_ebpf = tcf_bpf_is_ebpf(prog);
+ cfg->filter = prog->filter;
+
+ cfg->bpf_ops = prog->bpf_ops;
+ cfg->bpf_name = prog->bpf_name;
+}
+
static int tcf_bpf_init(struct net *net, struct nlattr *nla,
struct nlattr *est, struct tc_action *act,
int replace, int bind)
{
struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
+ struct tcf_bpf_cfg cfg, old;
struct tc_act_bpf *parm;
struct tcf_bpf *prog;
- struct tcf_bpf_cfg cfg;
bool is_bpf, is_ebpf;
int ret;
@@ -301,6 +325,9 @@
prog = to_bpf(act);
spin_lock_bh(&prog->tcf_lock);
+ if (ret != ACT_P_CREATED)
+ tcf_bpf_prog_fill_cfg(prog, &old);
+
prog->bpf_ops = cfg.bpf_ops;
prog->bpf_name = cfg.bpf_name;
@@ -316,29 +343,22 @@
if (ret == ACT_P_CREATED)
tcf_hash_insert(act);
+ else
+ tcf_bpf_cfg_cleanup(&old);
return ret;
destroy_fp:
- if (is_ebpf)
- bpf_prog_put(cfg.filter);
- else
- bpf_prog_destroy(cfg.filter);
-
- kfree(cfg.bpf_ops);
- kfree(cfg.bpf_name);
-
+ tcf_bpf_cfg_cleanup(&cfg);
return ret;
}
static void tcf_bpf_cleanup(struct tc_action *act, int bind)
{
- const struct tcf_bpf *prog = act->priv;
+ struct tcf_bpf_cfg tmp;
- if (tcf_bpf_is_ebpf(prog))
- bpf_prog_put(prog->filter);
- else
- bpf_prog_destroy(prog->filter);
+ tcf_bpf_prog_fill_cfg(act->priv, &tmp);
+ tcf_bpf_cfg_cleanup(&tmp);
}
static struct tc_action_ops act_bpf_ops __read_mostly = {
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index a42a3b2..2685450 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -98,6 +98,8 @@
return ret;
ret = ACT_P_CREATED;
} else {
+ if (bind)
+ return 0;
if (!ovr) {
tcf_hash_release(a, bind);
return -EEXIST;
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 17e6d66..ff8b466 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -68,13 +68,12 @@
}
ret = ACT_P_CREATED;
} else {
- p = to_pedit(a);
- tcf_hash_release(a, bind);
if (bind)
return 0;
+ tcf_hash_release(a, bind);
if (!ovr)
return -EEXIST;
-
+ p = to_pedit(a);
if (p->tcfp_nkeys && p->tcfp_nkeys != parm->nkeys) {
keys = kmalloc(ksize, GFP_KERNEL);
if (keys == NULL)
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c
index c79ecfd..e5168f8 100644
--- a/net/sched/cls_bpf.c
+++ b/net/sched/cls_bpf.c
@@ -378,7 +378,7 @@
goto errout;
if (oldprog) {
- list_replace_rcu(&prog->link, &oldprog->link);
+ list_replace_rcu(&oldprog->link, &prog->link);
tcf_unbind_filter(tp, &oldprog->res);
call_rcu(&oldprog->rcu, __cls_bpf_delete_prog);
} else {
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 76bc3a2..bb2a0f5 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -425,6 +425,8 @@
if (!fnew)
goto err2;
+ tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE);
+
fold = (struct flow_filter *)*arg;
if (fold) {
err = -EINVAL;
@@ -486,7 +488,6 @@
fnew->mask = ~0U;
fnew->tp = tp;
get_random_bytes(&fnew->hashrnd, 4);
- tcf_exts_init(&fnew->exts, TCA_FLOW_ACT, TCA_FLOW_POLICE);
}
fnew->perturb_timer.function = flow_perturbation;
@@ -526,7 +527,7 @@
if (*arg == 0)
list_add_tail_rcu(&fnew->list, &head->filters);
else
- list_replace_rcu(&fnew->list, &fold->list);
+ list_replace_rcu(&fold->list, &fnew->list);
*arg = (unsigned long)fnew;
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index 9d37ccd..2f3d03f 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -499,7 +499,7 @@
*arg = (unsigned long) fnew;
if (fold) {
- list_replace_rcu(&fnew->list, &fold->list);
+ list_replace_rcu(&fold->list, &fnew->list);
tcf_unbind_filter(tp, &fold->res);
call_rcu(&fold->rcu, fl_destroy_filter);
} else {
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index cab9e9b..4fbb674 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -490,6 +490,19 @@
return false;
}
}
+
+ if (tp_c->refcnt > 1)
+ return false;
+
+ if (tp_c->refcnt == 1) {
+ struct tc_u_hnode *ht;
+
+ for (ht = rtnl_dereference(tp_c->hlist);
+ ht;
+ ht = rtnl_dereference(ht->next))
+ if (!ht_empty(ht))
+ return false;
+ }
}
if (root_ht && --root_ht->refcnt == 0)
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 93d5742..6a783af 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -385,6 +385,19 @@
{
struct choke_sched_data *q = qdisc_priv(sch);
+ while (q->head != q->tail) {
+ struct sk_buff *skb = q->tab[q->head];
+
+ q->head = (q->head + 1) & q->tab_mask;
+ if (!skb)
+ continue;
+ qdisc_qstats_backlog_dec(sch, skb);
+ --sch->q.qlen;
+ qdisc_drop(skb, sch);
+ }
+
+ memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *));
+ q->head = q->tail = 0;
red_restart(&q->vars);
}
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index d75993f..a9ba030 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -155,14 +155,23 @@
skb = dequeue_head(flow);
len = qdisc_pkt_len(skb);
q->backlogs[idx] -= len;
- kfree_skb(skb);
sch->q.qlen--;
qdisc_qstats_drop(sch);
qdisc_qstats_backlog_dec(sch, skb);
+ kfree_skb(skb);
flow->dropped++;
return idx;
}
+static unsigned int fq_codel_qdisc_drop(struct Qdisc *sch)
+{
+ unsigned int prev_backlog;
+
+ prev_backlog = sch->qstats.backlog;
+ fq_codel_drop(sch);
+ return prev_backlog - sch->qstats.backlog;
+}
+
static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
{
struct fq_codel_sched_data *q = qdisc_priv(sch);
@@ -279,10 +288,26 @@
static void fq_codel_reset(struct Qdisc *sch)
{
- struct sk_buff *skb;
+ struct fq_codel_sched_data *q = qdisc_priv(sch);
+ int i;
- while ((skb = fq_codel_dequeue(sch)) != NULL)
- kfree_skb(skb);
+ INIT_LIST_HEAD(&q->new_flows);
+ INIT_LIST_HEAD(&q->old_flows);
+ for (i = 0; i < q->flows_cnt; i++) {
+ struct fq_codel_flow *flow = q->flows + i;
+
+ while (flow->head) {
+ struct sk_buff *skb = dequeue_head(flow);
+
+ qdisc_qstats_backlog_dec(sch, skb);
+ kfree_skb(skb);
+ }
+
+ INIT_LIST_HEAD(&flow->flowchain);
+ codel_vars_init(&flow->cvars);
+ }
+ memset(q->backlogs, 0, q->flows_cnt * sizeof(u32));
+ sch->q.qlen = 0;
}
static const struct nla_policy fq_codel_policy[TCA_FQ_CODEL_MAX + 1] = {
@@ -604,7 +629,7 @@
.enqueue = fq_codel_enqueue,
.dequeue = fq_codel_dequeue,
.peek = qdisc_peek_dequeued,
- .drop = fq_codel_drop,
+ .drop = fq_codel_qdisc_drop,
.init = fq_codel_init,
.reset = fq_codel_reset,
.destroy = fq_codel_destroy,
diff --git a/net/sched/sch_plug.c b/net/sched/sch_plug.c
index 89f8fcf..ade9445 100644
--- a/net/sched/sch_plug.c
+++ b/net/sched/sch_plug.c
@@ -216,6 +216,7 @@
.peek = qdisc_peek_head,
.init = plug_init,
.change = plug_change,
+ .reset = qdisc_reset_queue,
.owner = THIS_MODULE,
};
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index 7d14926..52f75a5 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -306,10 +306,10 @@
len = qdisc_pkt_len(skb);
slot->backlog -= len;
sfq_dec(q, x);
- kfree_skb(skb);
sch->q.qlen--;
qdisc_qstats_drop(sch);
qdisc_qstats_backlog_dec(sch, skb);
+ kfree_skb(skb);
return len;
}
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 06320c8..a655ddc 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3132,11 +3132,18 @@
case SCTP_PARAM_IPV4_ADDRESS:
if (length != sizeof(sctp_ipv4addr_param_t))
return false;
+ /* ensure there is only one addr param and it's in the
+ * beginning of addip_hdr params, or we reject it.
+ */
+ if (param.v != addip->addip_hdr.params)
+ return false;
addr_param_seen = true;
break;
case SCTP_PARAM_IPV6_ADDRESS:
if (length != sizeof(sctp_ipv6addr_param_t))
return false;
+ if (param.v != addip->addip_hdr.params)
+ return false;
addr_param_seen = true;
break;
case SCTP_PARAM_ADD_IP:
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index fef2acd..85e6f03 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -702,7 +702,7 @@
* outstanding data and rely on the retransmission limit be reached
* to shutdown the association.
*/
- if (t->asoc->state != SCTP_STATE_SHUTDOWN_PENDING)
+ if (t->asoc->state < SCTP_STATE_SHUTDOWN_PENDING)
t->asoc->overall_error_count = 0;
/* Clear the hb_sent flag to signal that we had a good
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 1425ec2..17bef01 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -2200,12 +2200,6 @@
if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen))
return -EFAULT;
- if (sctp_sk(sk)->subscribe.sctp_data_io_event)
- pr_warn_ratelimited(DEPRECATED "%s (pid %d) "
- "Requested SCTP_SNDRCVINFO event.\n"
- "Use SCTP_RCVINFO through SCTP_RECVRCVINFO option instead.\n",
- current->comm, task_pid_nr(current));
-
/* At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT,
* if there is no data to be sent or retransmit, the stack will
* immediately send up this notification.
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c
index 9825ff0..6255d14 100644
--- a/net/sunrpc/backchannel_rqst.c
+++ b/net/sunrpc/backchannel_rqst.c
@@ -240,8 +240,8 @@
req = xprt_alloc_bc_req(xprt, GFP_ATOMIC);
if (!req)
goto not_found;
- /* Note: this 'free' request adds it to xprt->bc_pa_list */
- xprt_free_bc_request(req);
+ list_add_tail(&req->rq_bc_pa_list, &xprt->bc_pa_list);
+ xprt->bc_alloc_count++;
}
req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst,
rq_bc_pa_list);
@@ -336,7 +336,7 @@
spin_lock(&xprt->bc_pa_lock);
list_del(&req->rq_bc_pa_list);
- xprt->bc_alloc_count--;
+ xprt_dec_alloc_count(xprt, 1);
spin_unlock(&xprt->bc_pa_lock);
req->rq_private_buf.len = copied;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index cbc6af9..23608eb 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1902,6 +1902,7 @@
switch (task->tk_status) {
case -EAGAIN:
+ case -ENOBUFS:
break;
default:
dprint_status(task);
@@ -1928,7 +1929,6 @@
case -ECONNABORTED:
case -EADDRINUSE:
case -ENOTCONN:
- case -ENOBUFS:
case -EPIPE:
rpc_task_force_reencode(task);
}
@@ -2057,12 +2057,13 @@
case -ECONNABORTED:
rpc_force_rebind(clnt);
case -EADDRINUSE:
- case -ENOBUFS:
rpc_delay(task, 3*HZ);
case -EPIPE:
case -ENOTCONN:
task->tk_action = call_bind;
break;
+ case -ENOBUFS:
+ rpc_delay(task, HZ>>2);
case -EAGAIN:
task->tk_action = call_transmit;
break;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index e193c2b..0030376 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -527,6 +527,10 @@
true, &sent);
dprintk("RPC: %s(%u) = %d\n",
__func__, xdr->len - req->rq_bytes_sent, status);
+
+ if (status == -EAGAIN && sock_writeable(transport->inet))
+ status = -ENOBUFS;
+
if (likely(sent > 0) || status == 0) {
req->rq_bytes_sent += sent;
req->rq_xmit_bytes_sent += sent;
@@ -539,6 +543,7 @@
switch (status) {
case -ENOBUFS:
+ break;
case -EAGAIN:
status = xs_nospace(task);
break;
@@ -589,6 +594,9 @@
if (status == -EPERM)
goto process_status;
+ if (status == -EAGAIN && sock_writeable(transport->inet))
+ status = -ENOBUFS;
+
if (sent > 0 || status == 0) {
req->rq_xmit_bytes_sent += sent;
if (sent >= req->rq_slen)
@@ -669,9 +677,6 @@
dprintk("RPC: xs_tcp_send_request(%u) = %d\n",
xdr->len - req->rq_bytes_sent, status);
- if (unlikely(sent == 0 && status < 0))
- break;
-
/* If we've sent the entire packet, immediately
* reset the count of bytes sent. */
req->rq_bytes_sent += sent;
@@ -681,18 +686,21 @@
return 0;
}
- if (sent != 0)
- continue;
- status = -EAGAIN;
- break;
+ if (status < 0)
+ break;
+ if (sent == 0) {
+ status = -EAGAIN;
+ break;
+ }
}
+ if (status == -EAGAIN && sk_stream_is_writeable(transport->inet))
+ status = -ENOBUFS;
switch (status) {
case -ENOTSOCK:
status = -ENOTCONN;
/* Should we call xs_close() here? */
break;
- case -ENOBUFS:
case -EAGAIN:
status = xs_nospace(task);
break;
@@ -703,6 +711,7 @@
case -ECONNREFUSED:
case -ENOTCONN:
case -EADDRINUSE:
+ case -ENOBUFS:
case -EPIPE:
clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
}
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 915b328..59cabc9 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -797,23 +797,18 @@
return false;
}
-bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
- struct cfg80211_chan_def *chandef,
- enum nl80211_iftype iftype)
+static bool _cfg80211_reg_can_beacon(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef,
+ enum nl80211_iftype iftype,
+ bool check_no_ir)
{
bool res;
u32 prohibited_flags = IEEE80211_CHAN_DISABLED |
IEEE80211_CHAN_RADAR;
- trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype);
+ trace_cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
- /*
- * Under certain conditions suggested by some regulatory bodies a
- * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag
- * only if such relaxations are not enabled and the conditions are not
- * met.
- */
- if (!cfg80211_ir_permissive_chan(wiphy, iftype, chandef->chan))
+ if (check_no_ir)
prohibited_flags |= IEEE80211_CHAN_NO_IR;
if (cfg80211_chandef_dfs_required(wiphy, chandef, iftype) > 0 &&
@@ -827,8 +822,36 @@
trace_cfg80211_return_bool(res);
return res;
}
+
+bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef,
+ enum nl80211_iftype iftype)
+{
+ return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, true);
+}
EXPORT_SYMBOL(cfg80211_reg_can_beacon);
+bool cfg80211_reg_can_beacon_relax(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef,
+ enum nl80211_iftype iftype)
+{
+ bool check_no_ir;
+
+ ASSERT_RTNL();
+
+ /*
+ * Under certain conditions suggested by some regulatory bodies a
+ * GO/STA can IR on channels marked with IEEE80211_NO_IR. Set this flag
+ * only if such relaxations are not enabled and the conditions are not
+ * met.
+ */
+ check_no_ir = !cfg80211_ir_permissive_chan(wiphy, iftype,
+ chandef->chan);
+
+ return _cfg80211_reg_can_beacon(wiphy, chandef, iftype, check_no_ir);
+}
+EXPORT_SYMBOL(cfg80211_reg_can_beacon_relax);
+
int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev,
struct cfg80211_chan_def *chandef)
{
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c264eff..76b4157 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2003,7 +2003,8 @@
switch (iftype) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, iftype)) {
+ if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
+ iftype)) {
result = -EINVAL;
break;
}
@@ -3403,8 +3404,8 @@
} else if (!nl80211_get_ap_channel(rdev, ¶ms))
return -EINVAL;
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef,
- wdev->iftype))
+ if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef,
+ wdev->iftype))
return -EINVAL;
if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
@@ -6492,8 +6493,8 @@
if (err)
return err;
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef,
- wdev->iftype))
+ if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, ¶ms.chandef,
+ wdev->iftype))
return -EINVAL;
err = cfg80211_chandef_dfs_required(wdev->wiphy,
@@ -10170,7 +10171,8 @@
return -EINVAL;
/* we will be active on the TDLS link */
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, wdev->iftype))
+ if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &chandef,
+ wdev->iftype))
return -EINVAL;
/* don't allow switching to DFS channels */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index d359e06..aa2d754 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -544,15 +544,15 @@
reg_regdb_query(alpha2);
if (reg_crda_timeouts > REG_MAX_CRDA_TIMEOUTS) {
- pr_info("Exceeded CRDA call max attempts. Not calling CRDA\n");
+ pr_debug("Exceeded CRDA call max attempts. Not calling CRDA\n");
return -EINVAL;
}
if (!is_world_regdom((char *) alpha2))
- pr_info("Calling CRDA for country: %c%c\n",
+ pr_debug("Calling CRDA for country: %c%c\n",
alpha2[0], alpha2[1]);
else
- pr_info("Calling CRDA to update world regulatory domain\n");
+ pr_debug("Calling CRDA to update world regulatory domain\n");
return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env);
}
@@ -1589,7 +1589,7 @@
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_ADHOC:
- return cfg80211_reg_can_beacon(wiphy, &chandef, iftype);
+ return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
return cfg80211_chandef_usable(wiphy, &chandef,
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index af3617c..a808279 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2358,20 +2358,23 @@
TRACE_EVENT(cfg80211_reg_can_beacon,
TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef,
- enum nl80211_iftype iftype),
- TP_ARGS(wiphy, chandef, iftype),
+ enum nl80211_iftype iftype, bool check_no_ir),
+ TP_ARGS(wiphy, chandef, iftype, check_no_ir),
TP_STRUCT__entry(
WIPHY_ENTRY
CHAN_DEF_ENTRY
__field(enum nl80211_iftype, iftype)
+ __field(bool, check_no_ir)
),
TP_fast_assign(
WIPHY_ASSIGN;
CHAN_DEF_ASSIGN(chandef);
__entry->iftype = iftype;
+ __entry->check_no_ir = check_no_ir;
),
- TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d",
- WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype)
+ TP_printk(WIPHY_PR_FMT ", " CHAN_DEF_PR_FMT ", iftype=%d check_no_ir=%s",
+ WIPHY_PR_ARG, CHAN_DEF_PR_ARG, __entry->iftype,
+ BOOL_TO_STR(__entry->check_no_ir))
);
TRACE_EVENT(cfg80211_chandef_dfs_required,
diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h
index 8965d1b..125d640 100644
--- a/samples/trace_events/trace-events-sample.h
+++ b/samples/trace_events/trace-events-sample.h
@@ -168,7 +168,10 @@
*
* For __dynamic_array(int, foo, bar) use __get_dynamic_array(foo)
* Use __get_dynamic_array_len(foo) to get the length of the array
- * saved.
+ * saved. Note, __get_dynamic_array_len() returns the total allocated
+ * length of the dynamic array; __print_array() expects the second
+ * parameter to be the number of elements. To get that, the array length
+ * needs to be divided by the element size.
*
* For __string(foo, bar) use __get_str(foo)
*
@@ -288,7 +291,7 @@
* This prints out the array that is defined by __array in a nice format.
*/
__print_array(__get_dynamic_array(list),
- __get_dynamic_array_len(list),
+ __get_dynamic_array_len(list) / sizeof(int),
sizeof(int)),
__get_str(str), __get_bitmask(cpus))
);
diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py
index c89fdca..2f4b7ff 100755
--- a/scripts/checkkconfigsymbols.py
+++ b/scripts/checkkconfigsymbols.py
@@ -2,7 +2,7 @@
"""Find Kconfig symbols that are referenced but not defined."""
-# (c) 2014-2015 Valentin Rothberg <Valentin.Rothberg@lip6.fr>
+# (c) 2014-2015 Valentin Rothberg <valentinrothberg@gmail.com>
# (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
#
# Licensed under the terms of the GNU GPL License version 2
@@ -20,18 +20,20 @@
FEATURE = r"(?:\w*[A-Z0-9]\w*){2,}"
DEF = r"^\s*(?:menu){,1}config\s+(" + FEATURE + r")\s*"
EXPR = r"(?:" + OPERATORS + r"|\s|" + FEATURE + r")+"
-STMT = r"^\s*(?:if|select|depends\s+on)\s+" + EXPR
+DEFAULT = r"default\s+.*?(?:if\s.+){,1}"
+STMT = r"^\s*(?:if|select|depends\s+on|(?:" + DEFAULT + r"))\s+" + EXPR
SOURCE_FEATURE = r"(?:\W|\b)+[D]{,1}CONFIG_(" + FEATURE + r")"
# regex objects
REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$")
-REGEX_FEATURE = re.compile(r"(" + FEATURE + r")")
+REGEX_FEATURE = re.compile(r'(?!\B"[^"]*)' + FEATURE + r'(?![^"]*"\B)')
REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE)
REGEX_KCONFIG_DEF = re.compile(DEF)
REGEX_KCONFIG_EXPR = re.compile(EXPR)
REGEX_KCONFIG_STMT = re.compile(STMT)
REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$")
REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$")
+REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+")
def parse_options():
@@ -58,6 +60,11 @@
"input format bases on Git log's "
"\'commmit1..commit2\'.")
+ parser.add_option('-f', '--find', dest='find', action='store_true',
+ default=False,
+ help="Find and show commits that may cause symbols to be "
+ "missing. Required to run with --diff.")
+
parser.add_option('-i', '--ignore', dest='ignore', action='store',
default="",
help="Ignore files matching this pattern. Note that "
@@ -86,6 +93,9 @@
"'--force' if you\nwant to ignore this warning and "
"continue.")
+ if opts.commit:
+ opts.find = False
+
if opts.ignore:
try:
re.match(opts.ignore, "this/is/just/a/test.c")
@@ -128,13 +138,19 @@
# feature has not been undefined before
if not feature in undefined_a:
files = sorted(undefined_b.get(feature))
- print "%s\t%s" % (feature, ", ".join(files))
+ print "%s\t%s" % (yel(feature), ", ".join(files))
+ if opts.find:
+ commits = find_commits(feature, opts.diff)
+ print red(commits)
# check if there are new files that reference the undefined feature
else:
files = sorted(undefined_b.get(feature) -
undefined_a.get(feature))
if files:
- print "%s\t%s" % (feature, ", ".join(files))
+ print "%s\t%s" % (yel(feature), ", ".join(files))
+ if opts.find:
+ commits = find_commits(feature, opts.diff)
+ print red(commits)
# reset to head
execute("git reset --hard %s" % head)
@@ -144,7 +160,21 @@
undefined = check_symbols(opts.ignore)
for feature in sorted(undefined):
files = sorted(undefined.get(feature))
- print "%s\t%s" % (feature, ", ".join(files))
+ print "%s\t%s" % (yel(feature), ", ".join(files))
+
+
+def yel(string):
+ """
+ Color %string yellow.
+ """
+ return "\033[33m%s\033[0m" % string
+
+
+def red(string):
+ """
+ Color %string red.
+ """
+ return "\033[31m%s\033[0m" % string
def execute(cmd):
@@ -156,6 +186,13 @@
return stdout
+def find_commits(symbol, diff):
+ """Find commits changing %symbol in the given range of %diff."""
+ commits = execute("git log --pretty=oneline --abbrev-commit -G %s %s"
+ % (symbol, diff))
+ return commits
+
+
def tree_is_dirty():
"""Return true if the current working tree is dirty (i.e., if any file has
been added, deleted, modified, renamed or copied but not committed)."""
@@ -279,6 +316,9 @@
line = line.strip('\n')
features.extend(get_features_in_line(line))
for feature in set(features):
+ if REGEX_NUMERIC.match(feature):
+ # ignore numeric values
+ continue
paths = referenced_features.get(feature, set())
paths.add(kfile)
referenced_features[feature] = paths
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index 9cb8522..f3d3fb4 100755
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -137,7 +137,7 @@
my $kconfig = $ARGV[1];
my $lsmod_file = $ENV{'LSMOD'};
-my @makefiles = `find $ksource -name Makefile 2>/dev/null`;
+my @makefiles = `find $ksource -name Makefile -or -name Kbuild 2>/dev/null`;
chomp @makefiles;
my %depends;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index e72548b..d334370 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1181,9 +1181,11 @@
if (index_key->type == &key_type_keyring)
up_write(&keyring_serialise_link_sem);
- if (edit && !edit->dead_leaf) {
- key_payload_reserve(keyring,
- keyring->datalen - KEYQUOTA_LINK_BYTES);
+ if (edit) {
+ if (!edit->dead_leaf) {
+ key_payload_reserve(keyring,
+ keyring->datalen - KEYQUOTA_LINK_BYTES);
+ }
assoc_array_cancel_edit(edit);
}
up_write(&keyring->sem);
diff --git a/security/security.c b/security/security.c
index 595fffa..9942836 100644
--- a/security/security.c
+++ b/security/security.c
@@ -380,8 +380,8 @@
return 0;
if (!initxattrs)
- return call_int_hook(inode_init_security, 0, inode, dir, qstr,
- NULL, NULL, NULL);
+ return call_int_hook(inode_init_security, -EOPNOTSUPP, inode,
+ dir, qstr, NULL, NULL, NULL);
memset(new_xattrs, 0, sizeof(new_xattrs));
lsm_xattr = new_xattrs;
ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr,
@@ -409,8 +409,8 @@
{
if (unlikely(IS_PRIVATE(inode)))
return -EOPNOTSUPP;
- return call_int_hook(inode_init_security, 0, inode, dir, qstr,
- name, value, len);
+ return call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir,
+ qstr, name, value, len);
}
EXPORT_SYMBOL(security_old_inode_init_security);
@@ -1281,7 +1281,8 @@
int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
{
- return call_int_hook(socket_getpeersec_dgram, 0, sock, skb, secid);
+ return call_int_hook(socket_getpeersec_dgram, -ENOPROTOOPT, sock,
+ skb, secid);
}
EXPORT_SYMBOL(security_socket_getpeersec_dgram);
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index 9ed3250..5ebb896 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -406,6 +406,7 @@
*/
if (!security_module_enable("yama"))
return 0;
+ yama_add_hooks();
#endif
pr_info("Yama: becoming mindful.\n");
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index d126c03..75888dd 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -85,7 +85,7 @@
void snd_pcm_stream_lock(struct snd_pcm_substream *substream)
{
if (substream->pcm->nonatomic) {
- down_read(&snd_pcm_link_rwsem);
+ down_read_nested(&snd_pcm_link_rwsem, SINGLE_DEPTH_NESTING);
mutex_lock(&substream->self_group.mutex);
} else {
read_lock(&snd_pcm_link_rwlock);
diff --git a/sound/firewire/amdtp.c b/sound/firewire/amdtp.c
index 7bb988f..2a153d2 100644
--- a/sound/firewire/amdtp.c
+++ b/sound/firewire/amdtp.c
@@ -740,8 +740,9 @@
s->data_block_counter != UINT_MAX)
data_block_counter = s->data_block_counter;
- if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) && data_block_counter == 0) ||
- (s->data_block_counter == UINT_MAX)) {
+ if (((s->flags & CIP_SKIP_DBC_ZERO_CHECK) &&
+ data_block_counter == s->tx_first_dbc) ||
+ s->data_block_counter == UINT_MAX) {
lost = false;
} else if (!(s->flags & CIP_DBC_IS_END_EVENT)) {
lost = data_block_counter != s->data_block_counter;
diff --git a/sound/firewire/amdtp.h b/sound/firewire/amdtp.h
index 26b9093..b2cf9e7 100644
--- a/sound/firewire/amdtp.h
+++ b/sound/firewire/amdtp.h
@@ -157,6 +157,8 @@
/* quirk: fixed interval of dbc between previos/current packets. */
unsigned int tx_dbc_interval;
+ /* quirk: indicate the value of dbc field in a first packet. */
+ unsigned int tx_first_dbc;
bool callbacked;
wait_queue_head_t callback_wait;
diff --git a/sound/firewire/fireworks/fireworks.c b/sound/firewire/fireworks/fireworks.c
index 2682e7e..c94a432 100644
--- a/sound/firewire/fireworks/fireworks.c
+++ b/sound/firewire/fireworks/fireworks.c
@@ -248,8 +248,16 @@
err = get_hardware_info(efw);
if (err < 0)
goto error;
+ /* AudioFire8 (since 2009) and AudioFirePre8 */
if (entry->model_id == MODEL_ECHO_AUDIOFIRE_9)
efw->is_af9 = true;
+ /* These models uses the same firmware. */
+ if (entry->model_id == MODEL_ECHO_AUDIOFIRE_2 ||
+ entry->model_id == MODEL_ECHO_AUDIOFIRE_4 ||
+ entry->model_id == MODEL_ECHO_AUDIOFIRE_9 ||
+ entry->model_id == MODEL_GIBSON_RIP ||
+ entry->model_id == MODEL_GIBSON_GOLDTOP)
+ efw->is_fireworks3 = true;
snd_efw_proc_init(efw);
diff --git a/sound/firewire/fireworks/fireworks.h b/sound/firewire/fireworks/fireworks.h
index 4f0201a..084d414 100644
--- a/sound/firewire/fireworks/fireworks.h
+++ b/sound/firewire/fireworks/fireworks.h
@@ -71,6 +71,7 @@
/* for quirks */
bool is_af9;
+ bool is_fireworks3;
u32 firmware_version;
unsigned int midi_in_ports;
diff --git a/sound/firewire/fireworks/fireworks_stream.c b/sound/firewire/fireworks/fireworks_stream.c
index c55db1b..7e353f1 100644
--- a/sound/firewire/fireworks/fireworks_stream.c
+++ b/sound/firewire/fireworks/fireworks_stream.c
@@ -172,6 +172,15 @@
efw->tx_stream.flags |= CIP_DBC_IS_END_EVENT;
/* Fireworks reset dbc at bus reset. */
efw->tx_stream.flags |= CIP_SKIP_DBC_ZERO_CHECK;
+ /*
+ * But Recent firmwares starts packets with non-zero dbc.
+ * Driver version 5.7.6 installs firmware version 5.7.3.
+ */
+ if (efw->is_fireworks3 &&
+ (efw->firmware_version == 0x5070000 ||
+ efw->firmware_version == 0x5070300 ||
+ efw->firmware_version == 0x5080000))
+ efw->tx_stream.tx_first_dbc = 0x02;
/* AudioFire9 always reports wrong dbs. */
if (efw->is_af9)
efw->tx_stream.flags |= CIP_WRONG_DBS;
diff --git a/sound/hda/ext/hdac_ext_controller.c b/sound/hda/ext/hdac_ext_controller.c
index b2da19b..358f161 100644
--- a/sound/hda/ext/hdac_ext_controller.c
+++ b/sound/hda/ext/hdac_ext_controller.c
@@ -44,16 +44,10 @@
offset = snd_hdac_chip_readl(bus, LLCH);
- if (offset < 0)
- return -EIO;
-
/* Lets walk the linked capabilities list */
do {
cur_cap = _snd_hdac_chip_read(l, bus, offset);
- if (cur_cap < 0)
- return -EIO;
-
dev_dbg(bus->dev, "Capability version: 0x%x\n",
((cur_cap & AZX_CAP_HDR_VER_MASK) >> AZX_CAP_HDR_VER_OFF));
diff --git a/sound/hda/ext/hdac_ext_stream.c b/sound/hda/ext/hdac_ext_stream.c
index f8ffbdb..3de47dd 100644
--- a/sound/hda/ext/hdac_ext_stream.c
+++ b/sound/hda/ext/hdac_ext_stream.c
@@ -299,7 +299,7 @@
if (stream->direction != substream->stream)
continue;
- if (stream->opened) {
+ if (!stream->opened) {
if (!hstream->decoupled)
snd_hdac_ext_stream_decouple(ebus, hstream, true);
res = hstream;
diff --git a/sound/hda/hdac_i915.c b/sound/hda/hdac_i915.c
index 442500e..5676b84 100644
--- a/sound/hda/hdac_i915.c
+++ b/sound/hda/hdac_i915.c
@@ -56,8 +56,11 @@
enable ? "enable" : "disable");
if (enable) {
- if (!bus->i915_power_refcount++)
+ if (!bus->i915_power_refcount++) {
acomp->ops->get_power(acomp->dev);
+ snd_hdac_set_codec_wakeup(bus, true);
+ snd_hdac_set_codec_wakeup(bus, false);
+ }
} else {
WARN_ON(!bus->i915_power_refcount);
if (!--bus->i915_power_refcount)
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 5de3c5d..d1a2cb6 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -3172,7 +3172,7 @@
struct snd_pcm_chmap *chmap;
const struct snd_pcm_chmap_elem *elem;
- if (!pcm || pcm->own_chmap ||
+ if (!pcm || !pcm->pcm || pcm->own_chmap ||
!hinfo->substreams)
continue;
elem = hinfo->chmap ? hinfo->chmap : snd_pcm_std_chmaps;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index b077bb6..24f9111 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -671,7 +671,8 @@
}
for (i = 0; i < path->depth; i++) {
if (path->path[i] == nid) {
- if (dir == HDA_OUTPUT || path->idx[i] == idx)
+ if (dir == HDA_OUTPUT || idx == -1 ||
+ path->idx[i] == idx)
return true;
break;
}
@@ -682,7 +683,7 @@
/* check whether the NID is referred by any active paths */
#define is_active_nid_for_any(codec, nid) \
- is_active_nid(codec, nid, HDA_OUTPUT, 0)
+ is_active_nid(codec, nid, HDA_OUTPUT, -1)
/* get the default amp value for the target state */
static int get_amp_val_to_activate(struct hda_codec *codec, hda_nid_t nid,
@@ -883,8 +884,7 @@
struct hda_gen_spec *spec = codec->spec;
int i;
- if (!enable)
- path->active = false;
+ path->active = enable;
/* make sure the widget is powered up */
if (enable && (spec->power_down_unused || codec->power_save_node))
@@ -902,9 +902,6 @@
if (has_amp_out(codec, path, i))
activate_amp_out(codec, path, i, enable);
}
-
- if (enable)
- path->active = true;
}
EXPORT_SYMBOL_GPL(snd_hda_activate_path);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 745535d..c38c68f5 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -867,7 +867,7 @@
chip = card->private_data;
hda = container_of(chip, struct hda_intel, chip);
- if (chip->disabled || hda->init_failed)
+ if (chip->disabled || hda->init_failed || !chip->running)
return 0;
bus = azx_bus(chip);
@@ -902,7 +902,7 @@
chip = card->private_data;
hda = container_of(chip, struct hda_intel, chip);
- if (chip->disabled || hda->init_failed)
+ if (chip->disabled || hda->init_failed || !chip->running)
return 0;
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
@@ -979,14 +979,16 @@
if (!azx_has_pm_runtime(chip))
return 0;
- if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL
- && hda->need_i915_power) {
- bus = azx_bus(chip);
- snd_hdac_display_power(bus, true);
- haswell_set_bclk(hda);
- /* toggle codec wakeup bit for STATESTS read */
- snd_hdac_set_codec_wakeup(bus, true);
- snd_hdac_set_codec_wakeup(bus, false);
+ if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
+ bus = azx_bus(chip);
+ if (hda->need_i915_power) {
+ snd_hdac_display_power(bus, true);
+ haswell_set_bclk(hda);
+ } else {
+ /* toggle codec wakeup bit for STATESTS read */
+ snd_hdac_set_codec_wakeup(bus, true);
+ snd_hdac_set_codec_wakeup(bus, false);
+ }
}
/* Read STATESTS before controller reset */
@@ -1025,7 +1027,7 @@
return 0;
if (!power_save_controller || !azx_has_pm_runtime(chip) ||
- azx_bus(chip)->codec_powered)
+ azx_bus(chip)->codec_powered || !chip->running)
return -EBUSY;
return 0;
@@ -2182,6 +2184,8 @@
/* ATI HDMI */
{ PCI_DEVICE(0x1002, 0x1308),
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+ { PCI_DEVICE(0x1002, 0x157a),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
{ PCI_DEVICE(0x1002, 0x793b),
.driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
{ PCI_DEVICE(0x1002, 0x7919),
@@ -2236,8 +2240,14 @@
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
{ PCI_DEVICE(0x1002, 0xaab0),
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+ { PCI_DEVICE(0x1002, 0xaac0),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
{ PCI_DEVICE(0x1002, 0xaac8),
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+ { PCI_DEVICE(0x1002, 0xaad8),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
+ { PCI_DEVICE(0x1002, 0xaae8),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS },
/* VIA VT8251/VT8237A */
{ PCI_DEVICE(0x1106, 0x3288),
.driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA },
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 25ccf78..584a034 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -999,9 +999,7 @@
spec->spdif_present = spdif_present;
/* SPDIF TX on/off */
- if (spdif_present)
- snd_hda_set_pin_ctl(codec, spdif_pin,
- spdif_present ? PIN_OUT : 0);
+ snd_hda_set_pin_ctl(codec, spdif_pin, spdif_present ? PIN_OUT : 0);
cs_automute(codec);
}
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index f788a91..ca03c40 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -200,12 +200,33 @@
return 0;
}
-#define cx_auto_free snd_hda_gen_free
+static void cx_auto_reboot_notify(struct hda_codec *codec)
+{
+ struct conexant_spec *spec = codec->spec;
+
+ if (codec->core.vendor_id != 0x14f150f2)
+ return;
+
+ /* Turn the CX20722 codec into D3 to avoid spurious noises
+ from the internal speaker during (and after) reboot */
+ cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, false);
+
+ snd_hda_codec_set_power_to_all(codec, codec->core.afg, AC_PWRST_D3);
+ snd_hda_codec_write(codec, codec->core.afg, 0,
+ AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+}
+
+static void cx_auto_free(struct hda_codec *codec)
+{
+ cx_auto_reboot_notify(codec);
+ snd_hda_gen_free(codec);
+}
static const struct hda_codec_ops cx_auto_patch_ops = {
.build_controls = cx_auto_build_controls,
.build_pcms = snd_hda_gen_build_pcms,
.init = cx_auto_init,
+ .reboot_notify = cx_auto_reboot_notify,
.free = cx_auto_free,
.unsol_event = snd_hda_jack_unsol_event,
#ifdef CONFIG_PM
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 9515891..a97db5f 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -3512,6 +3512,7 @@
{ .id = 0x10de0070, .name = "GPU 70 HDMI/DP", .patch = patch_nvhdmi },
{ .id = 0x10de0071, .name = "GPU 71 HDMI/DP", .patch = patch_nvhdmi },
{ .id = 0x10de0072, .name = "GPU 72 HDMI/DP", .patch = patch_nvhdmi },
+{ .id = 0x10de007d, .name = "GPU 7d HDMI/DP", .patch = patch_nvhdmi },
{ .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch },
{ .id = 0x11069f80, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi },
{ .id = 0x11069f81, .name = "VX900 HDMI/DP", .patch = patch_via_hdmi },
@@ -3576,6 +3577,7 @@
MODULE_ALIAS("snd-hda-codec-id:10de0070");
MODULE_ALIAS("snd-hda-codec-id:10de0071");
MODULE_ALIAS("snd-hda-codec-id:10de0072");
+MODULE_ALIAS("snd-hda-codec-id:10de007d");
MODULE_ALIAS("snd-hda-codec-id:10de8001");
MODULE_ALIAS("snd-hda-codec-id:11069f80");
MODULE_ALIAS("snd-hda-codec-id:11069f81");
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index d35cf50..374ea53 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2222,7 +2222,7 @@
SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
- SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
@@ -5061,7 +5061,7 @@
{ 0x14, 0x90170110 },
{ 0x17, 0x40000008 },
{ 0x18, 0x411111f0 },
- { 0x19, 0x411111f0 },
+ { 0x19, 0x01a1913c },
{ 0x1a, 0x411111f0 },
{ 0x1b, 0x411111f0 },
{ 0x1d, 0x40f89b2d },
@@ -5185,9 +5185,12 @@
SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x064b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x0665, "Dell XPS 13", ALC288_FIXUP_DELL_XPS_13),
+ SND_PCI_QUIRK(0x1028, 0x069a, "Dell Vostro 5480", ALC290_FIXUP_SUBWOOFER_HSJACK),
SND_PCI_QUIRK(0x1028, 0x06c7, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x06d9, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x06da, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1028, 0x06de, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
+ SND_PCI_QUIRK(0x1028, 0x06db, "Dell", ALC292_FIXUP_DISABLE_AAMIX),
SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -5289,6 +5292,7 @@
SND_PCI_QUIRK(0x17aa, 0x220c, "Thinkpad T440s", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x220e, "Thinkpad T440p", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2210, "Thinkpad T540p", ALC292_FIXUP_TPT440_DOCK),
+ SND_PCI_QUIRK(0x17aa, 0x2211, "Thinkpad W541", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2212, "Thinkpad T440", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2214, "Thinkpad X240", ALC292_FIXUP_TPT440_DOCK),
SND_PCI_QUIRK(0x17aa, 0x2215, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -5398,8 +5402,6 @@
{0x19, 0x411111f0}, \
{0x1a, 0x411111f0}, \
{0x1b, 0x411111f0}, \
- {0x1d, 0x40700001}, \
- {0x1e, 0x411111f0}, \
{0x21, 0x02211020}
#define ALC282_STANDARD_PINS \
@@ -5430,8 +5432,7 @@
{0x15, 0x0221401f}, \
{0x1a, 0x411111f0}, \
{0x1b, 0x411111f0}, \
- {0x1d, 0x40700001}, \
- {0x1e, 0x411111f0}
+ {0x1d, 0x40700001}
#define ALC298_STANDARD_PINS \
{0x18, 0x411111f0}, \
@@ -5463,6 +5464,39 @@
{0x1d, 0x40700001},
{0x21, 0x02211030}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x12, 0x40000000},
+ {0x14, 0x90170130},
+ {0x17, 0x411111f0},
+ {0x18, 0x411111f0},
+ {0x19, 0x411111f0},
+ {0x1a, 0x411111f0},
+ {0x1b, 0x01014020},
+ {0x1d, 0x4054c029},
+ {0x1e, 0x411111f0},
+ {0x21, 0x0221103f}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x12, 0x40000000},
+ {0x14, 0x90170150},
+ {0x17, 0x411111f0},
+ {0x18, 0x411111f0},
+ {0x19, 0x411111f0},
+ {0x1a, 0x411111f0},
+ {0x1b, 0x02011020},
+ {0x1d, 0x4054c029},
+ {0x1e, 0x411111f0},
+ {0x21, 0x0221105f}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ {0x12, 0x40000000},
+ {0x14, 0x90170110},
+ {0x17, 0x411111f0},
+ {0x18, 0x411111f0},
+ {0x19, 0x411111f0},
+ {0x1a, 0x411111f0},
+ {0x1b, 0x01014020},
+ {0x1d, 0x4054c029},
+ {0x1e, 0x411111f0},
+ {0x21, 0x0221101f}),
+ SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
{0x12, 0x90a60160},
{0x14, 0x90170120},
{0x17, 0x90170140},
@@ -5524,10 +5558,19 @@
{0x21, 0x02211030}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC256_STANDARD_PINS,
- {0x13, 0x40000000}),
+ {0x13, 0x40000000},
+ {0x1d, 0x40700001},
+ {0x1e, 0x411111f0}),
SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC256_STANDARD_PINS,
- {0x13, 0x411111f0}),
+ {0x13, 0x411111f0},
+ {0x1d, 0x40700001},
+ {0x1e, 0x411111f0}),
+ SND_HDA_PIN_QUIRK(0x10ec0256, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC256_STANDARD_PINS,
+ {0x13, 0x411111f0},
+ {0x1d, 0x4077992d},
+ {0x1e, 0x411111ff}),
SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
{0x12, 0x90a60130},
{0x13, 0x40000000},
@@ -5690,35 +5733,48 @@
{0x13, 0x411111f0},
{0x16, 0x01014020},
{0x18, 0x411111f0},
- {0x19, 0x01a19030}),
+ {0x19, 0x01a19030},
+ {0x1e, 0x411111f0}),
SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE,
ALC292_STANDARD_PINS,
{0x12, 0x90a60140},
{0x13, 0x411111f0},
{0x16, 0x01014020},
{0x18, 0x02a19031},
- {0x19, 0x01a1903e}),
+ {0x19, 0x01a1903e},
+ {0x1e, 0x411111f0}),
SND_HDA_PIN_QUIRK(0x10ec0292, 0x1028, "Dell", ALC269_FIXUP_DELL3_MIC_NO_PRESENCE,
ALC292_STANDARD_PINS,
{0x12, 0x90a60140},
{0x13, 0x411111f0},
{0x16, 0x411111f0},
{0x18, 0x411111f0},
- {0x19, 0x411111f0}),
+ {0x19, 0x411111f0},
+ {0x1e, 0x411111f0}),
SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC292_STANDARD_PINS,
{0x12, 0x40000000},
{0x13, 0x90a60140},
{0x16, 0x21014020},
{0x18, 0x411111f0},
- {0x19, 0x21a19030}),
+ {0x19, 0x21a19030},
+ {0x1e, 0x411111f0}),
SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC292_STANDARD_PINS,
{0x12, 0x40000000},
{0x13, 0x90a60140},
{0x16, 0x411111f0},
{0x18, 0x411111f0},
- {0x19, 0x411111f0}),
+ {0x19, 0x411111f0},
+ {0x1e, 0x411111f0}),
+ SND_HDA_PIN_QUIRK(0x10ec0293, 0x1028, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC292_STANDARD_PINS,
+ {0x12, 0x40000000},
+ {0x13, 0x90a60140},
+ {0x16, 0x21014020},
+ {0x18, 0x411111f0},
+ {0x19, 0x21a19030},
+ {0x1e, 0x411111ff}),
SND_HDA_PIN_QUIRK(0x10ec0298, 0x1028, "Dell", ALC298_FIXUP_DELL1_MIC_NO_PRESENCE,
ALC298_STANDARD_PINS,
{0x12, 0x90a60130},
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index dcc7fe9..9d947ae 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2920,7 +2920,8 @@
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x148a,
"HP Mini", STAC_92HD83XXX_HP_LED),
SND_PCI_QUIRK_VENDOR(PCI_VENDOR_ID_HP, "HP", STAC_92HD83XXX_HP),
- SND_PCI_QUIRK(PCI_VENDOR_ID_TOSHIBA, 0xfa91,
+ /* match both for 0xfa91 and 0xfa93 */
+ SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_TOSHIBA, 0xfffd, 0xfa91,
"Toshiba Satellite S50D", STAC_92HD83XXX_GPIO10_EAPD),
{} /* terminator */
};
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 6492bca..4ca1266 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -88,7 +88,7 @@
int changed;
mutex_lock(&chip->mutex);
- changed = !value->value.integer.value[0] != chip->dac_mute;
+ changed = (!value->value.integer.value[0]) != chip->dac_mute;
if (changed) {
chip->dac_mute = !value->value.integer.value[0];
chip->model.update_dac_mute(chip);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 2ae9619..1d651b8 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -30,6 +30,9 @@
bool
select SND_DMAENGINE_PCM
+config SND_SOC_TOPOLOGY
+ bool
+
# All the supported SoCs
source "sound/soc/adi/Kconfig"
source "sound/soc/atmel/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index e189903..669648b 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,6 +1,9 @@
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o soc-devres.o soc-ops.o
+
+ifneq ($(CONFIG_SND_SOC_TOPOLOGY),)
snd-soc-core-objs += soc-topology.o
+endif
ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
snd-soc-core-objs += soc-generic-dmaengine-pcm.o
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c
index d7ec4756..8e36198 100644
--- a/sound/soc/codecs/cs4265.c
+++ b/sound/soc/codecs/cs4265.c
@@ -457,14 +457,14 @@
case SND_SOC_DAIFMT_RIGHT_J:
if (params_width(params) == 16) {
snd_soc_update_bits(codec, CS4265_DAC_CTL,
- CS4265_DAC_CTL_DIF, (1 << 5));
+ CS4265_DAC_CTL_DIF, (2 << 4));
snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
- CS4265_SPDIF_CTL2_DIF, (1 << 7));
+ CS4265_SPDIF_CTL2_DIF, (2 << 6));
} else {
snd_soc_update_bits(codec, CS4265_DAC_CTL,
- CS4265_DAC_CTL_DIF, (3 << 5));
+ CS4265_DAC_CTL_DIF, (3 << 4));
snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
- CS4265_SPDIF_CTL2_DIF, (1 << 7));
+ CS4265_SPDIF_CTL2_DIF, (3 << 6));
}
break;
case SND_SOC_DAIFMT_LEFT_J:
@@ -473,7 +473,7 @@
snd_soc_update_bits(codec, CS4265_ADC_CTL,
CS4265_ADC_DIF, 0);
snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
- CS4265_SPDIF_CTL2_DIF, (1 << 6));
+ CS4265_SPDIF_CTL2_DIF, 0);
break;
default:
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c
index 477e13d..e7ba557 100644
--- a/sound/soc/codecs/pcm1681.c
+++ b/sound/soc/codecs/pcm1681.c
@@ -102,7 +102,7 @@
if (val != -1) {
regmap_update_bits(priv->regmap, PCM1681_DEEMPH_CONTROL,
- PCM1681_DEEMPH_RATE_MASK, val);
+ PCM1681_DEEMPH_RATE_MASK, val << 3);
enable = 1;
} else
enable = 0;
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 9ce311e..961bd7e 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -2943,6 +2943,9 @@
{
int val, btn_type, gpio_state = 0, report = 0;
+ if (!rt5645->codec)
+ return -EINVAL;
+
switch (rt5645->pdata.jd_mode) {
case 0: /* Not using rt5645 JD */
if (rt5645->gpiod_hp_det) {
@@ -3338,6 +3341,8 @@
break;
case RT5645_DMIC_DATA_GPIO5:
+ regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
+ RT5645_I2S2_DAC_PIN_MASK, RT5645_I2S2_DAC_PIN_GPIO);
regmap_update_bits(rt5645->regmap, RT5645_DMIC_CTRL1,
RT5645_DMIC_1_DP_MASK, RT5645_DMIC_1_DP_GPIO5);
regmap_update_bits(rt5645->regmap, RT5645_GPIO_CTRL1,
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h
index 0353a6a..278bb9f 100644
--- a/sound/soc/codecs/rt5645.h
+++ b/sound/soc/codecs/rt5645.h
@@ -1693,6 +1693,10 @@
#define RT5645_GP6_PIN_SFT 6
#define RT5645_GP6_PIN_GPIO6 (0x0 << 6)
#define RT5645_GP6_PIN_DMIC2_SDA (0x1 << 6)
+#define RT5645_I2S2_DAC_PIN_MASK (0x1 << 4)
+#define RT5645_I2S2_DAC_PIN_SFT 4
+#define RT5645_I2S2_DAC_PIN_I2S (0x0 << 4)
+#define RT5645_I2S2_DAC_PIN_GPIO (0x1 << 4)
#define RT5645_GP8_PIN_MASK (0x1 << 3)
#define RT5645_GP8_PIN_SFT 3
#define RT5645_GP8_PIN_GPIO8 (0x0 << 3)
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h
index bd7a344..1c317de 100644
--- a/sound/soc/codecs/sgtl5000.h
+++ b/sound/soc/codecs/sgtl5000.h
@@ -275,7 +275,7 @@
#define SGTL5000_BIAS_CTRL_MASK 0x000e
#define SGTL5000_BIAS_CTRL_SHIFT 1
#define SGTL5000_BIAS_CTRL_WIDTH 3
-#define SGTL5000_SMALL_POP 0
+#define SGTL5000_SMALL_POP 1
/*
* SGTL5000_CHIP_MIC_CTRL
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c
index 938d2cb..84a4f5a 100644
--- a/sound/soc/codecs/ssm4567.c
+++ b/sound/soc/codecs/ssm4567.c
@@ -315,7 +315,13 @@
if (invert_fclk)
ctrl1 |= SSM4567_SAI_CTRL_1_FSYNC;
- return regmap_write(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1, ctrl1);
+ return regmap_update_bits(ssm4567->regmap, SSM4567_REG_SAI_CTRL_1,
+ SSM4567_SAI_CTRL_1_BCLK |
+ SSM4567_SAI_CTRL_1_FSYNC |
+ SSM4567_SAI_CTRL_1_LJ |
+ SSM4567_SAI_CTRL_1_TDM |
+ SSM4567_SAI_CTRL_1_PDM,
+ ctrl1);
}
static int ssm4567_set_power(struct ssm4567 *ssm4567, bool enable)
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c7647e0..c0b940e 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -633,7 +633,7 @@
sub *= 100000;
do_div(sub, freq);
- if (sub < savesub) {
+ if (sub < savesub && !(i == 0 && psr == 0 && div2 == 0)) {
baudrate = tmprate;
savesub = sub;
pm = i;
diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile
index 3853ec2..6de5d5c 100644
--- a/sound/soc/intel/Makefile
+++ b/sound/soc/intel/Makefile
@@ -7,4 +7,4 @@
obj-$(CONFIG_SND_SST_MFLD_PLATFORM) += atom/
# Machine support
-obj-$(CONFIG_SND_SOC_INTEL_SST) += boards/
+obj-$(CONFIG_SND_SOC) += boards/
diff --git a/sound/soc/intel/atom/sst/sst_drv_interface.c b/sound/soc/intel/atom/sst/sst_drv_interface.c
index 620da1d..0e0e4d9 100644
--- a/sound/soc/intel/atom/sst/sst_drv_interface.c
+++ b/sound/soc/intel/atom/sst/sst_drv_interface.c
@@ -42,6 +42,11 @@
#define MIN_FRAGMENT_SIZE (50 * 1024)
#define MAX_FRAGMENT_SIZE (1024 * 1024)
#define SST_GET_BYTES_PER_SAMPLE(pcm_wd_sz) (((pcm_wd_sz + 15) >> 4) << 1)
+#ifdef CONFIG_PM
+#define GET_USAGE_COUNT(dev) (atomic_read(&dev->power.usage_count))
+#else
+#define GET_USAGE_COUNT(dev) 1
+#endif
int free_stream_context(struct intel_sst_drv *ctx, unsigned int str_id)
{
@@ -141,15 +146,9 @@
int ret = 0;
int usage_count = 0;
-#ifdef CONFIG_PM
- usage_count = atomic_read(&dev->power.usage_count);
-#else
- usage_count = 1;
-#endif
-
if (state == true) {
ret = pm_runtime_get_sync(dev);
-
+ usage_count = GET_USAGE_COUNT(dev);
dev_dbg(ctx->dev, "Enable: pm usage count: %d\n", usage_count);
if (ret < 0) {
dev_err(ctx->dev, "Runtime get failed with err: %d\n", ret);
@@ -164,6 +163,7 @@
}
}
} else {
+ usage_count = GET_USAGE_COUNT(dev);
dev_dbg(ctx->dev, "Disable: pm usage count: %d\n", usage_count);
return sst_pm_runtime_put(ctx);
}
diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c
index 4c01bb4..5bbaa66 100644
--- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c
+++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c
@@ -701,6 +701,8 @@
if (byt == NULL)
return -ENOMEM;
+ byt->dev = dev;
+
ipc = &byt->ipc;
ipc->dev = dev;
ipc->ops.tx_msg = byt_tx_msg;
diff --git a/sound/soc/intel/boards/cht_bsw_max98090_ti.c b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
index d604ee8..70f8321 100644
--- a/sound/soc/intel/boards/cht_bsw_max98090_ti.c
+++ b/sound/soc/intel/boards/cht_bsw_max98090_ti.c
@@ -69,12 +69,12 @@
{"Headphone", NULL, "HPR"},
{"Ext Spk", NULL, "SPKL"},
{"Ext Spk", NULL, "SPKR"},
- {"AIF1 Playback", NULL, "ssp2 Tx"},
+ {"HiFi Playback", NULL, "ssp2 Tx"},
{"ssp2 Tx", NULL, "codec_out0"},
{"ssp2 Tx", NULL, "codec_out1"},
{"codec_in0", NULL, "ssp2 Rx" },
{"codec_in1", NULL, "ssp2 Rx" },
- {"ssp2 Rx", NULL, "AIF1 Capture"},
+ {"ssp2 Rx", NULL, "HiFi Capture"},
};
static const struct snd_kcontrol_new cht_mc_controls[] = {
diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c
index f95f271..f6efa9d 100644
--- a/sound/soc/intel/haswell/sst-haswell-ipc.c
+++ b/sound/soc/intel/haswell/sst-haswell-ipc.c
@@ -2119,6 +2119,8 @@
if (hsw == NULL)
return -ENOMEM;
+ hsw->dev = dev;
+
ipc = &hsw->ipc;
ipc->dev = dev;
ipc->ops.tx_msg = hsw_tx_msg;
diff --git a/sound/soc/mediatek/mt8173-max98090.c b/sound/soc/mediatek/mt8173-max98090.c
index 4d44b58..2d2536a 100644
--- a/sound/soc/mediatek/mt8173-max98090.c
+++ b/sound/soc/mediatek/mt8173-max98090.c
@@ -103,7 +103,6 @@
.name = "MAX98090 Playback",
.stream_name = "MAX98090 Playback",
.cpu_dai_name = "DL1",
- .platform_name = "11220000.mt8173-afe-pcm",
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
@@ -114,7 +113,6 @@
.name = "MAX98090 Capture",
.stream_name = "MAX98090 Capture",
.cpu_dai_name = "VUL",
- .platform_name = "11220000.mt8173-afe-pcm",
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
@@ -125,7 +123,6 @@
{
.name = "Codec",
.cpu_dai_name = "I2S",
- .platform_name = "11220000.mt8173-afe-pcm",
.no_pcm = 1,
.codec_dai_name = "HiFi",
.init = mt8173_max98090_init,
@@ -152,9 +149,21 @@
static int mt8173_max98090_dev_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mt8173_max98090_card;
- struct device_node *codec_node;
+ struct device_node *codec_node, *platform_node;
int ret, i;
+ platform_node = of_parse_phandle(pdev->dev.of_node,
+ "mediatek,platform", 0);
+ if (!platform_node) {
+ dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
+ return -EINVAL;
+ }
+ for (i = 0; i < card->num_links; i++) {
+ if (mt8173_max98090_dais[i].platform_name)
+ continue;
+ mt8173_max98090_dais[i].platform_of_node = platform_node;
+ }
+
codec_node = of_parse_phandle(pdev->dev.of_node,
"mediatek,audio-codec", 0);
if (!codec_node) {
diff --git a/sound/soc/mediatek/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173-rt5650-rt5676.c
index 0940553..6f52eca 100644
--- a/sound/soc/mediatek/mt8173-rt5650-rt5676.c
+++ b/sound/soc/mediatek/mt8173-rt5650-rt5676.c
@@ -138,7 +138,6 @@
.name = "rt5650_rt5676 Playback",
.stream_name = "rt5650_rt5676 Playback",
.cpu_dai_name = "DL1",
- .platform_name = "11220000.mt8173-afe-pcm",
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
@@ -149,7 +148,6 @@
.name = "rt5650_rt5676 Capture",
.stream_name = "rt5650_rt5676 Capture",
.cpu_dai_name = "VUL",
- .platform_name = "11220000.mt8173-afe-pcm",
.codec_name = "snd-soc-dummy",
.codec_dai_name = "snd-soc-dummy-dai",
.trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
@@ -161,7 +159,6 @@
{
.name = "Codec",
.cpu_dai_name = "I2S",
- .platform_name = "11220000.mt8173-afe-pcm",
.no_pcm = 1,
.codecs = mt8173_rt5650_rt5676_codecs,
.num_codecs = 2,
@@ -209,7 +206,21 @@
static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &mt8173_rt5650_rt5676_card;
- int ret;
+ struct device_node *platform_node;
+ int i, ret;
+
+ platform_node = of_parse_phandle(pdev->dev.of_node,
+ "mediatek,platform", 0);
+ if (!platform_node) {
+ dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < card->num_links; i++) {
+ if (mt8173_rt5650_rt5676_dais[i].platform_name)
+ continue;
+ mt8173_rt5650_rt5676_dais[i].platform_of_node = platform_node;
+ }
mt8173_rt5650_rt5676_codecs[0].of_node =
of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0);
diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c
index cc228db..9863da7 100644
--- a/sound/soc/mediatek/mtk-afe-pcm.c
+++ b/sound/soc/mediatek/mtk-afe-pcm.c
@@ -1199,6 +1199,8 @@
static int mtk_afe_pcm_dev_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ mtk_afe_runtime_suspend(&pdev->dev);
snd_soc_unregister_component(&pdev->dev);
snd_soc_unregister_platform(&pdev->dev);
return 0;
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 3a4a5c0..0e1e69c 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1716,6 +1716,7 @@
if (card->remove)
card->remove(card);
+ snd_soc_dapm_free(&card->dapm);
soc_cleanup_card_debugfs(card);
snd_card_free(card->snd_card);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index aa327c9..e0de807 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -358,9 +358,10 @@
data->widget =
snd_soc_dapm_new_control_unlocked(widget->dapm,
&template);
+ kfree(name);
if (!data->widget) {
ret = -ENOMEM;
- goto err_name;
+ goto err_data;
}
}
break;
@@ -389,11 +390,12 @@
data->value = template.on_val;
- data->widget = snd_soc_dapm_new_control(widget->dapm,
- &template);
+ data->widget = snd_soc_dapm_new_control_unlocked(
+ widget->dapm, &template);
+ kfree(name);
if (!data->widget) {
ret = -ENOMEM;
- goto err_name;
+ goto err_data;
}
snd_soc_dapm_add_path(widget->dapm, data->widget,
@@ -408,8 +410,6 @@
return 0;
-err_name:
- kfree(name);
err_data:
kfree(data);
return ret;
@@ -418,8 +418,6 @@
static void dapm_kcontrol_free(struct snd_kcontrol *kctl)
{
struct dapm_kcontrol_data *data = snd_kcontrol_chip(kctl);
- if (data->widget)
- kfree(data->widget->name);
kfree(data->wlist);
kfree(data);
}
@@ -1952,6 +1950,7 @@
size_t count, loff_t *ppos)
{
struct snd_soc_dapm_widget *w = file->private_data;
+ struct snd_soc_card *card = w->dapm->card;
char *buf;
int in, out;
ssize_t ret;
@@ -1961,6 +1960,8 @@
if (!buf)
return -ENOMEM;
+ mutex_lock(&card->dapm_mutex);
+
/* Supply widgets are not handled by is_connected_{input,output}_ep() */
if (w->is_supply) {
in = 0;
@@ -2007,6 +2008,8 @@
p->sink->name);
}
+ mutex_unlock(&card->dapm_mutex);
+
ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
kfree(buf);
@@ -2281,11 +2284,15 @@
struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
int i, count = 0;
+ mutex_lock(&rtd->card->dapm_mutex);
+
for (i = 0; i < rtd->num_codecs; i++) {
struct snd_soc_codec *codec = rtd->codec_dais[i]->codec;
count += dapm_widget_show_codec(codec, buf + count);
}
+ mutex_unlock(&rtd->card->dapm_mutex);
+
return count;
}
@@ -3334,16 +3341,10 @@
}
prefix = soc_dapm_prefix(dapm);
- if (prefix) {
+ if (prefix)
w->name = kasprintf(GFP_KERNEL, "%s %s", prefix, widget->name);
- if (widget->sname)
- w->sname = kasprintf(GFP_KERNEL, "%s %s", prefix,
- widget->sname);
- } else {
+ else
w->name = kasprintf(GFP_KERNEL, "%s", widget->name);
- if (widget->sname)
- w->sname = kasprintf(GFP_KERNEL, "%s", widget->sname);
- }
if (w->name == NULL) {
kfree(w);
return NULL;
@@ -3792,7 +3793,7 @@
break;
}
- if (!w->sname || !strstr(w->sname, dai_w->name))
+ if (!w->sname || !strstr(w->sname, dai_w->sname))
continue;
if (dai_w->id == snd_soc_dapm_dai_in) {
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index d096068..31068b8 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -33,6 +33,7 @@
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/soc-topology.h>
+#include <sound/tlv.h>
/*
* We make several passes over the data (since it wont necessarily be ordered)
@@ -144,7 +145,7 @@
{SND_SOC_TPLG_CTL_STROBE, snd_soc_get_strobe,
snd_soc_put_strobe, NULL},
{SND_SOC_TPLG_DAPM_CTL_VOLSW, snd_soc_dapm_get_volsw,
- snd_soc_dapm_put_volsw, NULL},
+ snd_soc_dapm_put_volsw, snd_soc_info_volsw},
{SND_SOC_TPLG_DAPM_CTL_ENUM_DOUBLE, snd_soc_dapm_get_enum_double,
snd_soc_dapm_put_enum_double, snd_soc_info_enum_double},
{SND_SOC_TPLG_DAPM_CTL_ENUM_VIRT, snd_soc_dapm_get_enum_double,
@@ -534,7 +535,7 @@
k->put = bops[i].put;
if (k->get == NULL && bops[i].id == hdr->ops.get)
k->get = bops[i].get;
- if (k->info == NULL && ops[i].id == hdr->ops.info)
+ if (k->info == NULL && bops[i].id == hdr->ops.info)
k->info = bops[i].info;
}
@@ -579,29 +580,51 @@
return 0;
}
-static int soc_tplg_create_tlv(struct soc_tplg *tplg,
- struct snd_kcontrol_new *kc, u32 tlv_size)
+
+static int soc_tplg_create_tlv_db_scale(struct soc_tplg *tplg,
+ struct snd_kcontrol_new *kc, struct snd_soc_tplg_tlv_dbscale *scale)
{
- struct snd_soc_tplg_ctl_tlv *tplg_tlv;
- struct snd_ctl_tlv *tlv;
+ unsigned int item_len = 2 * sizeof(unsigned int);
+ unsigned int *p;
- if (tlv_size == 0)
- return 0;
-
- tplg_tlv = (struct snd_soc_tplg_ctl_tlv *) tplg->pos;
- tplg->pos += tlv_size;
-
- tlv = kzalloc(sizeof(*tlv) + tlv_size, GFP_KERNEL);
- if (tlv == NULL)
+ p = kzalloc(item_len + 2 * sizeof(unsigned int), GFP_KERNEL);
+ if (!p)
return -ENOMEM;
- dev_dbg(tplg->dev, " created TLV type %d size %d bytes\n",
- tplg_tlv->numid, tplg_tlv->size);
+ p[0] = SNDRV_CTL_TLVT_DB_SCALE;
+ p[1] = item_len;
+ p[2] = scale->min;
+ p[3] = (scale->step & TLV_DB_SCALE_MASK)
+ | (scale->mute ? TLV_DB_SCALE_MUTE : 0);
- tlv->numid = tplg_tlv->numid;
- tlv->length = tplg_tlv->size;
- memcpy(tlv->tlv, tplg_tlv + 1, tplg_tlv->size);
- kc->tlv.p = (void *)tlv;
+ kc->tlv.p = (void *)p;
+ return 0;
+}
+
+static int soc_tplg_create_tlv(struct soc_tplg *tplg,
+ struct snd_kcontrol_new *kc, struct snd_soc_tplg_ctl_hdr *tc)
+{
+ struct snd_soc_tplg_ctl_tlv *tplg_tlv;
+
+ if (!(tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE))
+ return 0;
+
+ if (tc->access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+ kc->tlv.c = snd_soc_bytes_tlv_callback;
+ } else {
+ tplg_tlv = &tc->tlv;
+ switch (tplg_tlv->type) {
+ case SNDRV_CTL_TLVT_DB_SCALE:
+ return soc_tplg_create_tlv_db_scale(tplg, kc,
+ &tplg_tlv->scale);
+
+ /* TODO: add support for other TLV types */
+ default:
+ dev_dbg(tplg->dev, "Unsupported TLV type %d\n",
+ tplg_tlv->type);
+ return -EINVAL;
+ }
+ }
return 0;
}
@@ -773,7 +796,7 @@
}
/* create any TLV data */
- soc_tplg_create_tlv(tplg, &kc, mc->hdr.tlv_size);
+ soc_tplg_create_tlv(tplg, &kc, &mc->hdr);
/* register control here */
err = soc_tplg_add_kcontrol(tplg, &kc,
@@ -1351,6 +1374,7 @@
template.reg = w->reg;
template.shift = w->shift;
template.mask = w->mask;
+ template.subseq = w->subseq;
template.on_val = w->invert ? 0 : 1;
template.off_val = w->invert ? 1 : 0;
template.ignore_suspend = w->ignore_suspend;
diff --git a/sound/soc/zte/zx296702-i2s.c b/sound/soc/zte/zx296702-i2s.c
index 98d96e1..1930c42 100644
--- a/sound/soc/zte/zx296702-i2s.c
+++ b/sound/soc/zte/zx296702-i2s.c
@@ -393,9 +393,9 @@
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
zx_i2s->mapbase = res->start;
zx_i2s->reg_base = devm_ioremap_resource(&pdev->dev, res);
- if (!zx_i2s->reg_base) {
+ if (IS_ERR(zx_i2s->reg_base)) {
dev_err(&pdev->dev, "ioremap failed!\n");
- return -EIO;
+ return PTR_ERR(zx_i2s->reg_base);
}
writel_relaxed(0, zx_i2s->reg_base + ZX_I2S_FIFO_CTRL);
diff --git a/sound/soc/zte/zx296702-spdif.c b/sound/soc/zte/zx296702-spdif.c
index 11a0e46..26265ce 100644
--- a/sound/soc/zte/zx296702-spdif.c
+++ b/sound/soc/zte/zx296702-spdif.c
@@ -322,9 +322,9 @@
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
zx_spdif->mapbase = res->start;
zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res);
- if (!zx_spdif->reg_base) {
+ if (IS_ERR(zx_spdif->reg_base)) {
dev_err(&pdev->dev, "ioremap failed!\n");
- return -EIO;
+ return PTR_ERR(zx_spdif->reg_base);
}
zx_spdif_dev_init(zx_spdif->reg_base);
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index 1b1a89e..784ceb8 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -956,6 +956,7 @@
if (!amd->regs) {
snd_printk(KERN_ERR
"amd7930-%d: Unable to map chip registers.\n", dev);
+ kfree(amd);
return -EIO;
}
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 1fab977..0450593 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -638,7 +638,7 @@
int err = -ENODEV;
down_read(&chip->shutdown_rwsem);
- if (chip->probing && chip->in_pm)
+ if (chip->probing || chip->in_pm)
err = 0;
else if (!chip->shutdown)
err = usb_autopm_get_interface(chip->pm_intf);
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index e5000da..6a803ef 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -341,6 +341,20 @@
{ 0 }
};
+/* Bose companion 5, the dB conversion factor is 16 instead of 256 */
+static struct usbmix_dB_map bose_companion5_dB = {-5006, -6};
+static struct usbmix_name_map bose_companion5_map[] = {
+ { 3, NULL, .dB = &bose_companion5_dB },
+ { 0 } /* terminator */
+};
+
+/* Dragonfly DAC 1.2, the dB conversion factor is 1 instead of 256 */
+static struct usbmix_dB_map dragonfly_1_2_dB = {0, 5000};
+static struct usbmix_name_map dragonfly_1_2_map[] = {
+ { 7, NULL, .dB = &dragonfly_1_2_dB },
+ { 0 } /* terminator */
+};
+
/*
* Control map entries
*/
@@ -451,6 +465,16 @@
.id = USB_ID(0x25c4, 0x0003),
.map = scms_usb3318_map,
},
+ {
+ /* Bose Companion 5 */
+ .id = USB_ID(0x05a7, 0x1020),
+ .map = bose_companion5_map,
+ },
+ {
+ /* Dragonfly DAC 1.2 */
+ .id = USB_ID(0x21b4, 0x0081),
+ .map = dragonfly_1_2_map,
+ },
{ 0 } /* terminator */
};
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 754e689..00ebc0c 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1268,6 +1268,7 @@
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
+ case USB_ID(0x20b1, 0x000a): /* Gustard DAC-X20U */
case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */
case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */
if (fp->altsetting == 3)
diff --git a/tools/hv/lsvmbus b/tools/hv/lsvmbus
new file mode 100644
index 0000000..162a378
--- /dev/null
+++ b/tools/hv/lsvmbus
@@ -0,0 +1,101 @@
+#!/usr/bin/env python
+
+import os
+from optparse import OptionParser
+
+parser = OptionParser()
+parser.add_option("-v", "--verbose", dest="verbose",
+ help="print verbose messages. Try -vv, -vvv for \
+ more verbose messages", action="count")
+
+(options, args) = parser.parse_args()
+
+verbose = 0
+if options.verbose is not None:
+ verbose = options.verbose
+
+vmbus_sys_path = '/sys/bus/vmbus/devices'
+if not os.path.isdir(vmbus_sys_path):
+ print "%s doesn't exist: exiting..." % vmbus_sys_path
+ exit(-1)
+
+vmbus_dev_dict = {
+ '{0e0b6031-5213-4934-818b-38d90ced39db}' : '[Operating system shutdown]',
+ '{9527e630-d0ae-497b-adce-e80ab0175caf}' : '[Time Synchronization]',
+ '{57164f39-9115-4e78-ab55-382f3bd5422d}' : '[Heartbeat]',
+ '{a9a0f4e7-5a45-4d96-b827-8a841e8c03e6}' : '[Data Exchange]',
+ '{35fa2e29-ea23-4236-96ae-3a6ebacba440}' : '[Backup (volume checkpoint)]',
+ '{34d14be3-dee4-41c8-9ae7-6b174977c192}' : '[Guest services]',
+ '{525074dc-8985-46e2-8057-a307dc18a502}' : '[Dynamic Memory]',
+ '{cfa8b69e-5b4a-4cc0-b98b-8ba1a1f3f95a}' : 'Synthetic mouse',
+ '{f912ad6d-2b17-48ea-bd65-f927a61c7684}' : 'Synthetic keyboard',
+ '{da0a7802-e377-4aac-8e77-0558eb1073f8}' : 'Synthetic framebuffer adapter',
+ '{f8615163-df3e-46c5-913f-f2d2f965ed0e}' : 'Synthetic network adapter',
+ '{32412632-86cb-44a2-9b5c-50d1417354f5}' : 'Synthetic IDE Controller',
+ '{ba6163d9-04a1-4d29-b605-72e2ffb1dc7f}' : 'Synthetic SCSI Controller',
+ '{2f9bcc4a-0069-4af3-b76b-6fd0be528cda}' : 'Synthetic fiber channel adapter',
+ '{8c2eaf3d-32a7-4b09-ab99-bd1f1c86b501}' : 'Synthetic RDMA adapter',
+ '{276aacf4-ac15-426c-98dd-7521ad3f01fe}' : '[Reserved system device]',
+ '{f8e65716-3cb3-4a06-9a60-1889c5cccab5}' : '[Reserved system device]',
+ '{3375baf4-9e15-4b30-b765-67acb10d607b}' : '[Reserved system device]',
+}
+
+def get_vmbus_dev_attr(dev_name, attr):
+ try:
+ f = open('%s/%s/%s' % (vmbus_sys_path, dev_name, attr), 'r')
+ lines = f.readlines()
+ f.close()
+ except IOError:
+ lines = []
+
+ return lines
+
+class VMBus_Dev:
+ pass
+
+
+vmbus_dev_list = []
+
+for f in os.listdir(vmbus_sys_path):
+ vmbus_id = get_vmbus_dev_attr(f, 'id')[0].strip()
+ class_id = get_vmbus_dev_attr(f, 'class_id')[0].strip()
+ device_id = get_vmbus_dev_attr(f, 'device_id')[0].strip()
+ dev_desc = vmbus_dev_dict.get(class_id, 'Unknown')
+
+ chn_vp_mapping = get_vmbus_dev_attr(f, 'channel_vp_mapping')
+ chn_vp_mapping = [c.strip() for c in chn_vp_mapping]
+ chn_vp_mapping = sorted(chn_vp_mapping,
+ key = lambda c : int(c.split(':')[0]))
+
+ chn_vp_mapping = ['\tRel_ID=%s, target_cpu=%s' %
+ (c.split(':')[0], c.split(':')[1])
+ for c in chn_vp_mapping]
+ d = VMBus_Dev()
+ d.sysfs_path = '%s/%s' % (vmbus_sys_path, f)
+ d.vmbus_id = vmbus_id
+ d.class_id = class_id
+ d.device_id = device_id
+ d.dev_desc = dev_desc
+ d.chn_vp_mapping = '\n'.join(chn_vp_mapping)
+ if d.chn_vp_mapping:
+ d.chn_vp_mapping += '\n'
+
+ vmbus_dev_list.append(d)
+
+
+vmbus_dev_list = sorted(vmbus_dev_list, key = lambda d : int(d.vmbus_id))
+
+format0 = '%2s: %s'
+format1 = '%2s: Class_ID = %s - %s\n%s'
+format2 = '%2s: Class_ID = %s - %s\n\tDevice_ID = %s\n\tSysfs path: %s\n%s'
+
+for d in vmbus_dev_list:
+ if verbose == 0:
+ print ('VMBUS ID ' + format0) % (d.vmbus_id, d.dev_desc)
+ elif verbose == 1:
+ print ('VMBUS ID ' + format1) % \
+ (d.vmbus_id, d.class_id, d.dev_desc, d.chn_vp_mapping)
+ else:
+ print ('VMBUS ID ' + format2) % \
+ (d.vmbus_id, d.class_id, d.dev_desc, \
+ d.device_id, d.sysfs_path, d.chn_vp_mapping)
diff --git a/tools/iio/generic_buffer.c b/tools/iio/generic_buffer.c
index 4eebb66..9f7b85b 100644
--- a/tools/iio/generic_buffer.c
+++ b/tools/iio/generic_buffer.c
@@ -51,14 +51,33 @@
if (bytes % channels[i].bytes == 0)
channels[i].location = bytes;
else
- channels[i].location = bytes - bytes%channels[i].bytes
- + channels[i].bytes;
+ channels[i].location = bytes - bytes % channels[i].bytes
+ + channels[i].bytes;
+
bytes = channels[i].location + channels[i].bytes;
i++;
}
+
return bytes;
}
+void print1byte(uint8_t input, struct iio_channel_info *info)
+{
+ /*
+ * Shift before conversion to avoid sign extension
+ * of left aligned data
+ */
+ input >>= info->shift;
+ input &= info->mask;
+ if (info->is_signed) {
+ int8_t val = (int8_t)(input << (8 - info->bits_used)) >>
+ (8 - info->bits_used);
+ printf("%05f ", ((float)val + info->offset) * info->scale);
+ } else {
+ printf("%05f ", ((float)input + info->offset) * info->scale);
+ }
+}
+
void print2byte(uint16_t input, struct iio_channel_info *info)
{
/* First swap if incorrect endian */
@@ -136,9 +155,9 @@
/**
* process_scan() - print out the values in SI units
* @data: pointer to the start of the scan
- * @channels: information about the channels. Note
- * size_from_channelarray must have been called first to fill the
- * location offsets.
+ * @channels: information about the channels.
+ * Note: size_from_channelarray must have been called first
+ * to fill the location offsets.
* @num_channels: number of channels
**/
void process_scan(char *data,
@@ -150,6 +169,10 @@
for (k = 0; k < num_channels; k++)
switch (channels[k].bytes) {
/* only a few cases implemented so far */
+ case 1:
+ print1byte(*(uint8_t *)(data + channels[k].location),
+ &channels[k]);
+ break;
case 2:
print2byte(*(uint16_t *)(data + channels[k].location),
&channels[k]);
@@ -170,15 +193,15 @@
void print_usage(void)
{
- printf("Usage: generic_buffer [options]...\n"
- "Capture, convert and output data from IIO device buffer\n"
- " -c <n> Do n conversions\n"
- " -e Disable wait for event (new data)\n"
- " -g Use trigger-less mode\n"
- " -l <n> Set buffer length to n samples\n"
- " -n <name> Set device name (mandatory)\n"
- " -t <name> Set trigger name\n"
- " -w <n> Set delay between reads in us (event-less mode)\n");
+ fprintf(stderr, "Usage: generic_buffer [options]...\n"
+ "Capture, convert and output data from IIO device buffer\n"
+ " -c <n> Do n conversions\n"
+ " -e Disable wait for event (new data)\n"
+ " -g Use trigger-less mode\n"
+ " -l <n> Set buffer length to n samples\n"
+ " -n <name> Set device name (mandatory)\n"
+ " -t <name> Set trigger name\n"
+ " -w <n> Set delay between reads in us (event-less mode)\n");
}
int main(int argc, char **argv)
@@ -213,6 +236,7 @@
num_loops = strtoul(optarg, &dummy, 10);
if (errno)
return -errno;
+
break;
case 'e':
noevents = 1;
@@ -225,6 +249,7 @@
buf_len = strtoul(optarg, &dummy, 10);
if (errno)
return -errno;
+
break;
case 'n':
device_name = optarg;
@@ -245,8 +270,8 @@
}
}
- if (device_name == NULL) {
- printf("Device name not set\n");
+ if (!device_name) {
+ fprintf(stderr, "Device name not set\n");
print_usage();
return -1;
}
@@ -254,9 +279,10 @@
/* Find the device requested */
dev_num = find_type_by_name(device_name, "iio:device");
if (dev_num < 0) {
- printf("Failed to find the %s\n", device_name);
+ fprintf(stderr, "Failed to find the %s\n", device_name);
return dev_num;
}
+
printf("iio device number being used is %d\n", dev_num);
ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
@@ -264,7 +290,7 @@
return -ENOMEM;
if (!notrigger) {
- if (trigger_name == NULL) {
+ if (!trigger_name) {
/*
* Build the trigger name. If it is device associated
* its name is <device_name>_dev[n] where n matches
@@ -281,13 +307,16 @@
/* Verify the trigger exists */
trig_num = find_type_by_name(trigger_name, "trigger");
if (trig_num < 0) {
- printf("Failed to find the trigger %s\n", trigger_name);
+ fprintf(stderr, "Failed to find the trigger %s\n",
+ trigger_name);
ret = trig_num;
goto error_free_triggername;
}
+
printf("iio trigger number being used is %d\n", trig_num);
- } else
+ } else {
printf("trigger-less mode selected\n");
+ }
/*
* Parse the files in scan_elements to identify what channels are
@@ -295,8 +324,8 @@
*/
ret = build_channel_array(dev_dir_name, &channels, &num_channels);
if (ret) {
- printf("Problem reading scan element information\n");
- printf("diag %s\n", dev_dir_name);
+ fprintf(stderr, "Problem reading scan element information\n"
+ "diag %s\n", dev_dir_name);
goto error_free_triggername;
}
@@ -314,13 +343,16 @@
if (!notrigger) {
printf("%s %s\n", dev_dir_name, trigger_name);
- /* Set the device trigger to be the data ready trigger found
- * above */
+ /*
+ * Set the device trigger to be the data ready trigger found
+ * above
+ */
ret = write_sysfs_string_and_verify("trigger/current_trigger",
dev_dir_name,
trigger_name);
if (ret < 0) {
- printf("Failed to write current_trigger file\n");
+ fprintf(stderr,
+ "Failed to write current_trigger file\n");
goto error_free_buf_dir_name;
}
}
@@ -332,10 +364,14 @@
/* Enable the buffer */
ret = write_sysfs_int("enable", buf_dir_name, 1);
- if (ret < 0)
+ if (ret < 0) {
+ fprintf(stderr,
+ "Failed to enable buffer: %s\n", strerror(-ret));
goto error_free_buf_dir_name;
+ }
+
scan_size = size_from_channelarray(channels, num_channels);
- data = malloc(scan_size*buf_len);
+ data = malloc(scan_size * buf_len);
if (!data) {
ret = -ENOMEM;
goto error_free_buf_dir_name;
@@ -349,13 +385,12 @@
/* Attempt to open non blocking the access dev */
fp = open(buffer_access, O_RDONLY | O_NONBLOCK);
- if (fp == -1) { /* If it isn't there make the node */
+ if (fp == -1) { /* TODO: If it isn't there make the node */
ret = -errno;
- printf("Failed to open %s\n", buffer_access);
+ fprintf(stderr, "Failed to open %s\n", buffer_access);
goto error_free_buffer_access;
}
- /* Wait for events 10 times */
for (j = 0; j < num_loops; j++) {
if (!noevents) {
struct pollfd pfd = {
@@ -372,25 +407,22 @@
}
toread = buf_len;
-
} else {
usleep(timedelay);
toread = 64;
}
- read_size = read(fp,
- data,
- toread*scan_size);
+ read_size = read(fp, data, toread * scan_size);
if (read_size < 0) {
if (errno == EAGAIN) {
- printf("nothing available\n");
+ fprintf(stderr, "nothing available\n");
continue;
- } else
+ } else {
break;
+ }
}
- for (i = 0; i < read_size/scan_size; i++)
- process_scan(data + scan_size*i,
- channels,
+ for (i = 0; i < read_size / scan_size; i++)
+ process_scan(data + scan_size * i, channels,
num_channels);
}
@@ -404,11 +436,13 @@
ret = write_sysfs_string("trigger/current_trigger",
dev_dir_name, "NULL");
if (ret < 0)
- printf("Failed to write to %s\n", dev_dir_name);
+ fprintf(stderr, "Failed to write to %s\n",
+ dev_dir_name);
error_close_buffer_access:
if (close(fp) == -1)
perror("Failed to close buffer");
+
error_free_buffer_access:
free(buffer_access);
error_free_data:
@@ -424,6 +458,7 @@
error_free_triggername:
if (datardytrigger)
free(trigger_name);
+
error_free_dev_dir_name:
free(dev_dir_name);
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index 016760e..cd3fd41 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -13,7 +13,6 @@
*
* Usage:
* iio_event_monitor <device_name>
- *
*/
#include <unistd.h>
@@ -51,6 +50,9 @@
[IIO_HUMIDITYRELATIVE] = "humidityrelative",
[IIO_ACTIVITY] = "activity",
[IIO_STEPS] = "steps",
+ [IIO_ENERGY] = "energy",
+ [IIO_DISTANCE] = "distance",
+ [IIO_VELOCITY] = "velocity",
};
static const char * const iio_ev_type_text[] = {
@@ -99,6 +101,7 @@
[IIO_MOD_JOGGING] = "jogging",
[IIO_MOD_WALKING] = "walking",
[IIO_MOD_STILL] = "still",
+ [IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z] = "sqrt(x^2+y^2+z^2)",
};
static bool event_is_known(struct iio_event_data *event)
@@ -130,6 +133,9 @@
case IIO_HUMIDITYRELATIVE:
case IIO_ACTIVITY:
case IIO_STEPS:
+ case IIO_ENERGY:
+ case IIO_DISTANCE:
+ case IIO_VELOCITY:
break;
default:
return false;
@@ -167,6 +173,7 @@
case IIO_MOD_JOGGING:
case IIO_MOD_WALKING:
case IIO_MOD_STILL:
+ case IIO_MOD_ROOT_SUM_SQUARED_X_Y_Z:
break;
default:
return false;
@@ -208,8 +215,9 @@
bool diff = IIO_EVENT_CODE_EXTRACT_DIFF(event->id);
if (!event_is_known(event)) {
- printf("Unknown event: time: %lld, id: %llx\n",
- event->timestamp, event->id);
+ fprintf(stderr, "Unknown event: time: %lld, id: %llx\n",
+ event->timestamp, event->id);
+
return;
}
@@ -229,6 +237,7 @@
if (dir != IIO_EV_DIR_NONE)
printf(", direction: %s", iio_ev_dir_text[dir]);
+
printf("\n");
}
@@ -242,7 +251,7 @@
int fd, event_fd;
if (argc <= 1) {
- printf("Usage: %s <device_name>\n", argv[0]);
+ fprintf(stderr, "Usage: %s <device_name>\n", argv[0]);
return -1;
}
@@ -251,14 +260,15 @@
dev_num = find_type_by_name(device_name, "iio:device");
if (dev_num >= 0) {
printf("Found IIO device with name %s with device number %d\n",
- device_name, dev_num);
+ device_name, dev_num);
ret = asprintf(&chrdev_name, "/dev/iio:device%d", dev_num);
- if (ret < 0) {
+ if (ret < 0)
return -ENOMEM;
- }
} else {
- /* If we can't find a IIO device by name assume device_name is a
- IIO chrdev */
+ /*
+ * If we can't find an IIO device by name assume device_name is
+ * an IIO chrdev
+ */
chrdev_name = strdup(device_name);
if (!chrdev_name)
return -ENOMEM;
@@ -267,14 +277,14 @@
fd = open(chrdev_name, 0);
if (fd == -1) {
ret = -errno;
- fprintf(stdout, "Failed to open %s\n", chrdev_name);
+ fprintf(stderr, "Failed to open %s\n", chrdev_name);
goto error_free_chrdev_name;
}
ret = ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
if (ret == -1 || event_fd == -1) {
ret = -errno;
- fprintf(stdout, "Failed to retrieve event fd\n");
+ fprintf(stderr, "Failed to retrieve event fd\n");
if (close(fd) == -1)
perror("Failed to close character device file");
@@ -290,7 +300,7 @@
ret = read(event_fd, &event, sizeof(event));
if (ret == -1) {
if (errno == EAGAIN) {
- printf("nothing available\n");
+ fprintf(stderr, "nothing available\n");
continue;
} else {
ret = -errno;
@@ -299,6 +309,12 @@
}
}
+ if (ret != sizeof(event)) {
+ fprintf(stderr, "Reading event failed!\n");
+ ret = -EIO;
+ break;
+ }
+
print_event(&event);
}
diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
index ec9ab7f..5eb6793 100644
--- a/tools/iio/iio_utils.c
+++ b/tools/iio/iio_utils.c
@@ -6,9 +6,6 @@
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
-#ifndef _IIO_UTILS_H
-#define _IIO_UTILS_H
-
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
@@ -32,15 +29,14 @@
*
* Returns 0 on success, or a negative error code if string extraction failed.
**/
-int iioutils_break_up_name(const char *full_name,
- char **generic_name)
+int iioutils_break_up_name(const char *full_name, char **generic_name)
{
char *current;
char *w, *r;
char *working, *prefix = "";
int i, ret;
- for (i = 0; i < sizeof(iio_direction) / sizeof(iio_direction[0]); i++)
+ for (i = 0; i < ARRAY_SIZE(iio_direction); i++)
if (!strncmp(full_name, iio_direction[i],
strlen(iio_direction[i]))) {
prefix = iio_direction[i];
@@ -65,6 +61,7 @@
*w = *r;
w++;
}
+
r++;
}
*w = '\0';
@@ -88,15 +85,10 @@
*
* Returns a value >= 0 on success, otherwise a negative error code.
**/
-int iioutils_get_type(unsigned *is_signed,
- unsigned *bytes,
- unsigned *bits_used,
- unsigned *shift,
- uint64_t *mask,
- unsigned *be,
- const char *device_dir,
- const char *name,
- const char *generic_name)
+int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
+ unsigned *shift, uint64_t *mask, unsigned *be,
+ const char *device_dir, const char *name,
+ const char *generic_name)
{
FILE *sysfsfp;
int ret;
@@ -122,12 +114,13 @@
}
dp = opendir(scan_el_dir);
- if (dp == NULL) {
+ if (!dp) {
ret = -errno;
goto error_free_builtname_generic;
}
+
ret = -ENOENT;
- while (ent = readdir(dp), ent != NULL)
+ while (ent = readdir(dp), ent)
/*
* Do we allow devices to override a generic name with
* a specific one?
@@ -140,10 +133,12 @@
ret = -ENOMEM;
goto error_closedir;
}
+
sysfsfp = fopen(filename, "r");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
- printf("failed to open %s\n", filename);
+ fprintf(stderr, "failed to open %s\n",
+ filename);
goto error_free_filename;
}
@@ -155,31 +150,36 @@
&padint, shift);
if (ret < 0) {
ret = -errno;
- printf("failed to pass scan type description\n");
+ fprintf(stderr,
+ "failed to pass scan type description\n");
goto error_close_sysfsfp;
} else if (ret != 5) {
ret = -EIO;
- printf("scan type description didn't match\n");
+ fprintf(stderr,
+ "scan type description didn't match\n");
goto error_close_sysfsfp;
}
+
*be = (endianchar == 'b');
*bytes = padint / 8;
if (*bits_used == 64)
*mask = ~0;
else
- *mask = (1 << *bits_used) - 1;
+ *mask = (1ULL << *bits_used) - 1;
+
*is_signed = (signchar == 's');
if (fclose(sysfsfp)) {
ret = -errno;
- printf("Failed to close %s\n", filename);
+ fprintf(stderr, "Failed to close %s\n",
+ filename);
goto error_free_filename;
}
sysfsfp = 0;
free(filename);
-
filename = 0;
}
+
error_close_sysfsfp:
if (sysfsfp)
if (fclose(sysfsfp))
@@ -188,6 +188,7 @@
error_free_filename:
if (filename)
free(filename);
+
error_closedir:
if (closedir(dp) == -1)
perror("iioutils_get_type(): Failed to close directory");
@@ -212,11 +213,9 @@
*
* Returns a value >= 0 on success, otherwise a negative error code.
**/
-int iioutils_get_param_float(float *output,
- const char *param_name,
- const char *device_dir,
- const char *name,
- const char *generic_name)
+int iioutils_get_param_float(float *output, const char *param_name,
+ const char *device_dir, const char *name,
+ const char *generic_name)
{
FILE *sysfsfp;
int ret;
@@ -235,13 +234,15 @@
ret = -ENOMEM;
goto error_free_builtname;
}
+
dp = opendir(device_dir);
- if (dp == NULL) {
+ if (!dp) {
ret = -errno;
goto error_free_builtname_generic;
}
+
ret = -ENOENT;
- while (ent = readdir(dp), ent != NULL)
+ while (ent = readdir(dp), ent)
if ((strcmp(builtname, ent->d_name) == 0) ||
(strcmp(builtname_generic, ent->d_name) == 0)) {
ret = asprintf(&filename,
@@ -250,11 +251,13 @@
ret = -ENOMEM;
goto error_closedir;
}
+
sysfsfp = fopen(filename, "r");
if (!sysfsfp) {
ret = -errno;
goto error_free_filename;
}
+
errno = 0;
if (fscanf(sysfsfp, "%f", output) != 1)
ret = errno ? -errno : -ENODATA;
@@ -264,6 +267,7 @@
error_free_filename:
if (filename)
free(filename);
+
error_closedir:
if (closedir(dp) == -1)
perror("iioutils_get_param_float(): Failed to close directory");
@@ -282,19 +286,17 @@
* @cnt: the amount of array elements
**/
-void bsort_channel_array_by_index(struct iio_channel_info **ci_array,
- int cnt)
+void bsort_channel_array_by_index(struct iio_channel_info *ci_array, int cnt)
{
-
struct iio_channel_info temp;
int x, y;
for (x = 0; x < cnt; x++)
for (y = 0; y < (cnt - 1); y++)
- if ((*ci_array)[y].index > (*ci_array)[y+1].index) {
- temp = (*ci_array)[y + 1];
- (*ci_array)[y + 1] = (*ci_array)[y];
- (*ci_array)[y] = temp;
+ if (ci_array[y].index > ci_array[y + 1].index) {
+ temp = ci_array[y + 1];
+ ci_array[y + 1] = ci_array[y];
+ ci_array[y] = temp;
}
}
@@ -307,8 +309,7 @@
* Returns 0 on success, otherwise a negative error code.
**/
int build_channel_array(const char *device_dir,
- struct iio_channel_info **ci_array,
- int *counter)
+ struct iio_channel_info **ci_array, int *counter)
{
DIR *dp;
FILE *sysfsfp;
@@ -325,11 +326,12 @@
return -ENOMEM;
dp = opendir(scan_el_dir);
- if (dp == NULL) {
+ if (!dp) {
ret = -errno;
goto error_free_name;
}
- while (ent = readdir(dp), ent != NULL)
+
+ while (ent = readdir(dp), ent)
if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
"_en") == 0) {
ret = asprintf(&filename,
@@ -338,12 +340,14 @@
ret = -ENOMEM;
goto error_close_dir;
}
+
sysfsfp = fopen(filename, "r");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
free(filename);
goto error_close_dir;
}
+
errno = 0;
if (fscanf(sysfsfp, "%i", &ret) != 1) {
ret = errno ? -errno : -ENODATA;
@@ -353,9 +357,9 @@
free(filename);
goto error_close_dir;
}
-
if (ret == 1)
(*counter)++;
+
if (fclose(sysfsfp)) {
ret = -errno;
free(filename);
@@ -364,13 +368,15 @@
free(filename);
}
+
*ci_array = malloc(sizeof(**ci_array) * (*counter));
- if (*ci_array == NULL) {
+ if (!*ci_array) {
ret = -ENOMEM;
goto error_close_dir;
}
+
seekdir(dp, 0);
- while (ent = readdir(dp), ent != NULL) {
+ while (ent = readdir(dp), ent) {
if (strcmp(ent->d_name + strlen(ent->d_name) - strlen("_en"),
"_en") == 0) {
int current_enabled = 0;
@@ -384,13 +390,15 @@
count--;
goto error_cleanup_array;
}
+
sysfsfp = fopen(filename, "r");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
free(filename);
count--;
goto error_cleanup_array;
}
+
errno = 0;
if (fscanf(sysfsfp, "%i", ¤t_enabled) != 1) {
ret = errno ? -errno : -ENODATA;
@@ -417,12 +425,13 @@
current->name = strndup(ent->d_name,
strlen(ent->d_name) -
strlen("_en"));
- if (current->name == NULL) {
+ if (!current->name) {
free(filename);
ret = -ENOMEM;
count--;
goto error_cleanup_array;
}
+
/* Get the generic and specific name elements */
ret = iioutils_break_up_name(current->name,
¤t->generic_name);
@@ -432,6 +441,7 @@
count--;
goto error_cleanup_array;
}
+
ret = asprintf(&filename,
"%s/%s_index",
scan_el_dir,
@@ -441,10 +451,12 @@
ret = -ENOMEM;
goto error_cleanup_array;
}
+
sysfsfp = fopen(filename, "r");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
- printf("failed to open %s\n", filename);
+ fprintf(stderr, "failed to open %s\n",
+ filename);
free(filename);
goto error_cleanup_array;
}
@@ -472,15 +484,17 @@
device_dir,
current->name,
current->generic_name);
- if (ret < 0)
+ if ((ret < 0) && (ret != -ENOENT))
goto error_cleanup_array;
+
ret = iioutils_get_param_float(¤t->offset,
"offset",
device_dir,
current->name,
current->generic_name);
- if (ret < 0)
+ if ((ret < 0) && (ret != -ENOENT))
goto error_cleanup_array;
+
ret = iioutils_get_type(¤t->is_signed,
¤t->bytes,
¤t->bits_used,
@@ -502,7 +516,7 @@
free(scan_el_dir);
/* reorder so that the array is in index order */
- bsort_channel_array_by_index(ci_array, *counter);
+ bsort_channel_array_by_index(*ci_array, *counter);
return 0;
@@ -512,6 +526,8 @@
free((*ci_array)[i].generic_name);
}
free(*ci_array);
+ *ci_array = NULL;
+ *counter = 0;
error_close_dir:
if (dp)
if (closedir(dp) == -1)
@@ -523,7 +539,7 @@
return ret;
}
-int calc_digits(int num)
+static int calc_digits(int num)
{
int count = 0;
@@ -549,44 +565,43 @@
const struct dirent *ent;
int number, numstrlen, ret;
- FILE *nameFile;
+ FILE *namefp;
DIR *dp;
char thisname[IIO_MAX_NAME_LENGTH];
char *filename;
dp = opendir(iio_dir);
- if (dp == NULL) {
- printf("No industrialio devices available\n");
+ if (!dp) {
+ fprintf(stderr, "No industrialio devices available\n");
return -ENODEV;
}
- while (ent = readdir(dp), ent != NULL) {
+ while (ent = readdir(dp), ent) {
if (strcmp(ent->d_name, ".") != 0 &&
- strcmp(ent->d_name, "..") != 0 &&
- strlen(ent->d_name) > strlen(type) &&
- strncmp(ent->d_name, type, strlen(type)) == 0) {
+ strcmp(ent->d_name, "..") != 0 &&
+ strlen(ent->d_name) > strlen(type) &&
+ strncmp(ent->d_name, type, strlen(type)) == 0) {
errno = 0;
ret = sscanf(ent->d_name + strlen(type), "%d", &number);
if (ret < 0) {
ret = -errno;
- printf("failed to read element number\n");
+ fprintf(stderr,
+ "failed to read element number\n");
goto error_close_dir;
} else if (ret != 1) {
ret = -EIO;
- printf("failed to match element number\n");
+ fprintf(stderr,
+ "failed to match element number\n");
goto error_close_dir;
}
numstrlen = calc_digits(number);
/* verify the next character is not a colon */
if (strncmp(ent->d_name + strlen(type) + numstrlen,
- ":",
- 1) != 0) {
- filename = malloc(strlen(iio_dir)
- + strlen(type)
- + numstrlen
- + 6);
- if (filename == NULL) {
+ ":", 1) != 0) {
+ filename = malloc(strlen(iio_dir) + strlen(type)
+ + numstrlen + 6);
+ if (!filename) {
ret = -ENOMEM;
goto error_close_dir;
}
@@ -598,19 +613,20 @@
goto error_close_dir;
}
- nameFile = fopen(filename, "r");
- if (!nameFile) {
+ namefp = fopen(filename, "r");
+ if (!namefp) {
free(filename);
continue;
}
+
free(filename);
errno = 0;
- if (fscanf(nameFile, "%s", thisname) != 1) {
+ if (fscanf(namefp, "%s", thisname) != 1) {
ret = errno ? -errno : -ENODATA;
goto error_close_dir;
}
- if (fclose(nameFile)) {
+ if (fclose(namefp)) {
ret = -errno;
goto error_close_dir;
}
@@ -618,6 +634,7 @@
if (strcmp(name, thisname) == 0) {
if (closedir(dp) == -1)
return -errno;
+
return number;
}
}
@@ -631,6 +648,7 @@
error_close_dir:
if (closedir(dp) == -1)
perror("find_type_by_name(): Failed to close directory");
+
return ret;
}
@@ -642,18 +660,20 @@
int test;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
- if (temp == NULL)
+ if (!temp)
return -ENOMEM;
+
ret = sprintf(temp, "%s/%s", basedir, filename);
if (ret < 0)
goto error_free;
sysfsfp = fopen(temp, "w");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
- printf("failed to open %s\n", temp);
+ fprintf(stderr, "failed to open %s\n", temp);
goto error_free;
}
+
ret = fprintf(sysfsfp, "%d", val);
if (ret < 0) {
if (fclose(sysfsfp))
@@ -669,11 +689,12 @@
if (verify) {
sysfsfp = fopen(temp, "r");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
- printf("failed to open %s\n", temp);
+ fprintf(stderr, "failed to open %s\n", temp);
goto error_free;
}
+
if (fscanf(sysfsfp, "%d", &test) != 1) {
ret = errno ? -errno : -ENODATA;
if (fclose(sysfsfp))
@@ -688,13 +709,13 @@
}
if (test != val) {
- printf("Possible failure in int write %d to %s%s\n",
- val,
- basedir,
- filename);
+ fprintf(stderr,
+ "Possible failure in int write %d to %s/%s\n",
+ val, basedir, filename);
ret = -1;
}
}
+
error_free:
free(temp);
return ret;
@@ -735,20 +756,22 @@
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
- if (temp == NULL) {
- printf("Memory allocation failed\n");
+ if (!temp) {
+ fprintf(stderr, "Memory allocation failed\n");
return -ENOMEM;
}
+
ret = sprintf(temp, "%s/%s", basedir, filename);
if (ret < 0)
goto error_free;
sysfsfp = fopen(temp, "w");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
- printf("Could not open %s\n", temp);
+ fprintf(stderr, "Could not open %s\n", temp);
goto error_free;
}
+
ret = fprintf(sysfsfp, "%s", val);
if (ret < 0) {
if (fclose(sysfsfp))
@@ -764,11 +787,12 @@
if (verify) {
sysfsfp = fopen(temp, "r");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
- printf("could not open file to verify\n");
+ fprintf(stderr, "Could not open file to verify\n");
goto error_free;
}
+
if (fscanf(sysfsfp, "%s", temp) != 1) {
ret = errno ? -errno : -ENODATA;
if (fclose(sysfsfp))
@@ -783,16 +807,14 @@
}
if (strcmp(temp, val) != 0) {
- printf("Possible failure in string write of %s "
- "Should be %s "
- "written to %s\%s\n",
- temp,
- val,
- basedir,
- filename);
+ fprintf(stderr,
+ "Possible failure in string write of %s "
+ "Should be %s written to %s/%s\n", temp, val,
+ basedir, filename);
ret = -1;
}
}
+
error_free:
free(temp);
@@ -841,19 +863,21 @@
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
- if (temp == NULL) {
- printf("Memory allocation failed");
+ if (!temp) {
+ fprintf(stderr, "Memory allocation failed");
return -ENOMEM;
}
+
ret = sprintf(temp, "%s/%s", basedir, filename);
if (ret < 0)
goto error_free;
sysfsfp = fopen(temp, "r");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
goto error_free;
}
+
errno = 0;
if (fscanf(sysfsfp, "%d\n", &ret) != 1) {
ret = errno ? -errno : -ENODATA;
@@ -868,6 +892,7 @@
error_free:
free(temp);
+
return ret;
}
@@ -885,19 +910,21 @@
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
- if (temp == NULL) {
- printf("Memory allocation failed");
+ if (!temp) {
+ fprintf(stderr, "Memory allocation failed");
return -ENOMEM;
}
+
ret = sprintf(temp, "%s/%s", basedir, filename);
if (ret < 0)
goto error_free;
sysfsfp = fopen(temp, "r");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
goto error_free;
}
+
errno = 0;
if (fscanf(sysfsfp, "%f\n", val) != 1) {
ret = errno ? -errno : -ENODATA;
@@ -912,6 +939,7 @@
error_free:
free(temp);
+
return ret;
}
@@ -929,19 +957,21 @@
FILE *sysfsfp;
char *temp = malloc(strlen(basedir) + strlen(filename) + 2);
- if (temp == NULL) {
- printf("Memory allocation failed");
+ if (!temp) {
+ fprintf(stderr, "Memory allocation failed");
return -ENOMEM;
}
+
ret = sprintf(temp, "%s/%s", basedir, filename);
if (ret < 0)
goto error_free;
sysfsfp = fopen(temp, "r");
- if (sysfsfp == NULL) {
+ if (!sysfsfp) {
ret = -errno;
goto error_free;
}
+
errno = 0;
if (fscanf(sysfsfp, "%s\n", str) != 1) {
ret = errno ? -errno : -ENODATA;
@@ -956,7 +986,6 @@
error_free:
free(temp);
+
return ret;
}
-
-#endif /* _IIO_UTILS_H */
diff --git a/tools/iio/iio_utils.h b/tools/iio/iio_utils.h
index 379eed9..e3503bf 100644
--- a/tools/iio/iio_utils.h
+++ b/tools/iio/iio_utils.h
@@ -18,6 +18,8 @@
#define FORMAT_SCAN_ELEMENTS_DIR "%s/scan_elements"
#define FORMAT_TYPE_FILE "%s_type"
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+
extern const char *iio_dir;
/**
@@ -51,17 +53,16 @@
};
int iioutils_break_up_name(const char *full_name, char **generic_name);
-int iioutils_get_type(unsigned *is_signed, unsigned *bytes,
- unsigned *bits_used, unsigned *shift,
- uint64_t *mask, unsigned *be,
- const char *device_dir, const char *name,
- const char *generic_name);
+int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
+ unsigned *shift, uint64_t *mask, unsigned *be,
+ const char *device_dir, const char *name,
+ const char *generic_name);
int iioutils_get_param_float(float *output, const char *param_name,
- const char *device_dir, const char *name,
- const char *generic_name);
-void bsort_channel_array_by_index(struct iio_channel_info **ci_array, int cnt);
+ const char *device_dir, const char *name,
+ const char *generic_name);
+void bsort_channel_array_by_index(struct iio_channel_info *ci_array, int cnt);
int build_channel_array(const char *device_dir,
- struct iio_channel_info **ci_array, int *counter);
+ struct iio_channel_info **ci_array, int *counter);
int find_type_by_name(const char *name, const char *type);
int write_sysfs_int(const char *filename, const char *basedir, int val);
int write_sysfs_int_and_verify(const char *filename, const char *basedir,
diff --git a/tools/iio/lsiio.c b/tools/iio/lsiio.c
index b59ee17..3d650e6 100644
--- a/tools/iio/lsiio.c
+++ b/tools/iio/lsiio.c
@@ -20,7 +20,6 @@
#include <sys/dir.h>
#include "iio_utils.h"
-
static enum verbosity {
VERBLEVEL_DEFAULT, /* 0 gives lspci behaviour */
VERBLEVEL_SENSORS, /* 1 lists sensors */
@@ -29,17 +28,16 @@
const char *type_device = "iio:device";
const char *type_trigger = "trigger";
-
static inline int check_prefix(const char *str, const char *prefix)
{
return strlen(str) > strlen(prefix) &&
- strncmp(str, prefix, strlen(prefix)) == 0;
+ strncmp(str, prefix, strlen(prefix)) == 0;
}
static inline int check_postfix(const char *str, const char *postfix)
{
return strlen(str) > strlen(postfix) &&
- strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
+ strcmp(str + strlen(str) - strlen(postfix), postfix) == 0;
}
static int dump_channels(const char *dev_dir_name)
@@ -48,13 +46,13 @@
const struct dirent *ent;
dp = opendir(dev_dir_name);
- if (dp == NULL)
+ if (!dp)
return -errno;
- while (ent = readdir(dp), ent != NULL)
+
+ while (ent = readdir(dp), ent)
if (check_prefix(ent->d_name, "in_") &&
- check_postfix(ent->d_name, "_raw")) {
+ check_postfix(ent->d_name, "_raw"))
printf(" %-10s\n", ent->d_name);
- }
return (closedir(dp) == -1) ? -errno : 0;
}
@@ -63,20 +61,22 @@
{
char name[IIO_MAX_NAME_LENGTH];
int dev_idx;
- int retval;
+ int ret;
- retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device),
- "%i", &dev_idx);
- if (retval != 1)
+ ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_device), "%i",
+ &dev_idx);
+ if (ret != 1)
return -EINVAL;
- retval = read_sysfs_string("name", dev_dir_name, name);
- if (retval)
- return retval;
+
+ ret = read_sysfs_string("name", dev_dir_name, name);
+ if (ret < 0)
+ return ret;
printf("Device %03d: %s\n", dev_idx, name);
if (verblevel >= VERBLEVEL_SENSORS)
return dump_channels(dev_dir_name);
+
return 0;
}
@@ -84,17 +84,19 @@
{
char name[IIO_MAX_NAME_LENGTH];
int dev_idx;
- int retval;
+ int ret;
- retval = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
- "%i", &dev_idx);
- if (retval != 1)
+ ret = sscanf(dev_dir_name + strlen(iio_dir) + strlen(type_trigger),
+ "%i", &dev_idx);
+ if (ret != 1)
return -EINVAL;
- retval = read_sysfs_string("name", dev_dir_name, name);
- if (retval)
- return retval;
+
+ ret = read_sysfs_string("name", dev_dir_name, name);
+ if (ret < 0)
+ return ret;
printf("Trigger %03d: %s\n", dev_idx, name);
+
return 0;
}
@@ -105,12 +107,12 @@
DIR *dp;
dp = opendir(iio_dir);
- if (dp == NULL) {
- printf("No industrial I/O devices available\n");
+ if (!dp) {
+ fprintf(stderr, "No industrial I/O devices available\n");
return -ENODEV;
}
- while (ent = readdir(dp), ent != NULL) {
+ while (ent = readdir(dp), ent) {
if (check_prefix(ent->d_name, type_device)) {
char *dev_dir_name;
@@ -132,7 +134,7 @@
}
}
rewinddir(dp);
- while (ent = readdir(dp), ent != NULL) {
+ while (ent = readdir(dp), ent) {
if (check_prefix(ent->d_name, type_trigger)) {
char *dev_dir_name;
@@ -151,6 +153,7 @@
free(dev_dir_name);
}
}
+
return (closedir(dp) == -1) ? -errno : 0;
error_close_dir:
diff --git a/tools/perf/arch/xtensa/Build b/tools/perf/arch/xtensa/Build
new file mode 100644
index 0000000..54afe4a
--- /dev/null
+++ b/tools/perf/arch/xtensa/Build
@@ -0,0 +1 @@
+libperf-y += util/
diff --git a/tools/perf/arch/xtensa/Makefile b/tools/perf/arch/xtensa/Makefile
new file mode 100644
index 0000000..7fbca17
--- /dev/null
+++ b/tools/perf/arch/xtensa/Makefile
@@ -0,0 +1,3 @@
+ifndef NO_DWARF
+PERF_HAVE_DWARF_REGS := 1
+endif
diff --git a/tools/perf/arch/xtensa/util/Build b/tools/perf/arch/xtensa/util/Build
new file mode 100644
index 0000000..954e287
--- /dev/null
+++ b/tools/perf/arch/xtensa/util/Build
@@ -0,0 +1 @@
+libperf-$(CONFIG_DWARF) += dwarf-regs.o
diff --git a/tools/perf/arch/xtensa/util/dwarf-regs.c b/tools/perf/arch/xtensa/util/dwarf-regs.c
new file mode 100644
index 0000000..4dba76b
--- /dev/null
+++ b/tools/perf/arch/xtensa/util/dwarf-regs.c
@@ -0,0 +1,25 @@
+/*
+ * Mapping of DWARF debug register numbers into register names.
+ *
+ * Copyright (c) 2015 Cadence Design Systems Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <stddef.h>
+#include <dwarf-regs.h>
+
+#define XTENSA_MAX_REGS 16
+
+const char *xtensa_regs_table[XTENSA_MAX_REGS] = {
+ "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
+ "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
+};
+
+const char *get_arch_regstr(unsigned int n)
+{
+ return n < XTENSA_MAX_REGS ? xtensa_regs_table[n] : NULL;
+}
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index de165a1..20b56eb 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -521,6 +521,15 @@
goto out_child;
}
+ /*
+ * Normally perf_session__new would do this, but it doesn't have the
+ * evlist.
+ */
+ if (rec->tool.ordered_events && !perf_evlist__sample_id_all(rec->evlist)) {
+ pr_warning("WARNING: No sample_id_all support, falling back to unordered processing\n");
+ rec->tool.ordered_events = false;
+ }
+
if (!rec->evlist->nr_groups)
perf_header__clear_feat(&session->header, HEADER_GROUP_DESC);
@@ -965,9 +974,11 @@
.tool = {
.sample = process_sample_event,
.fork = perf_event__process_fork,
+ .exit = perf_event__process_exit,
.comm = perf_event__process_comm,
.mmap = perf_event__process_mmap,
.mmap2 = perf_event__process_mmap2,
+ .ordered_events = true,
},
};
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index ecf3197..6135cc0 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -601,8 +601,8 @@
static void display_setup_sig(void)
{
- signal(SIGSEGV, display_sig);
- signal(SIGFPE, display_sig);
+ signal(SIGSEGV, sighandler_dump_stack);
+ signal(SIGFPE, sighandler_dump_stack);
signal(SIGINT, display_sig);
signal(SIGQUIT, display_sig);
signal(SIGTERM, display_sig);
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index 094ddae..d31fac1 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -638,7 +638,7 @@
prefix ?= $(HOME)
endif
bindir_relative = bin
-bindir = $(prefix)/$(bindir_relative)
+bindir = $(abspath $(prefix)/$(bindir_relative))
mandir = share/man
infodir = share/info
perfexecdir = libexec/perf-core
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 7ff6827..f1a4c83 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -1387,6 +1387,24 @@
event->fork.ptid);
int err = 0;
+ if (dump_trace)
+ perf_event__fprintf_task(event, stdout);
+
+ /*
+ * There may be an existing thread that is not actually the parent,
+ * either because we are processing events out of order, or because the
+ * (fork) event that would have removed the thread was lost. Assume the
+ * latter case and continue on as best we can.
+ */
+ if (parent->pid_ != (pid_t)event->fork.ppid) {
+ dump_printf("removing erroneous parent thread %d/%d\n",
+ parent->pid_, parent->tid);
+ machine__remove_thread(machine, parent);
+ thread__put(parent);
+ parent = machine__findnew_thread(machine, event->fork.ppid,
+ event->fork.ptid);
+ }
+
/* if a thread currently exists for the thread id remove it */
if (thread != NULL) {
machine__remove_thread(machine, thread);
@@ -1395,8 +1413,6 @@
thread = machine__findnew_thread(machine, event->fork.pid,
event->fork.tid);
- if (dump_trace)
- perf_event__fprintf_task(event, stdout);
if (thread == NULL || parent == NULL ||
thread__fork(thread, parent, sample->time) < 0) {
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index 53e8bb7..2a5d8d7 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -85,7 +85,7 @@
else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
update_stats(&runtime_cycles_stats[ctx][cpu], count[0]);
else if (perf_stat_evsel__is(counter, CYCLES_IN_TX))
- update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
+ update_stats(&runtime_cycles_in_tx_stats[ctx][cpu], count[0]);
else if (perf_stat_evsel__is(counter, TRANSACTION_START))
update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
else if (perf_stat_evsel__is(counter, ELISION_START))
@@ -398,20 +398,18 @@
" # %5.2f%% aborted cycles ",
100.0 * ((total2-avg) / total));
} else if (perf_stat_evsel__is(evsel, TRANSACTION_START) &&
- avg > 0 &&
runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
- if (total)
+ if (avg)
ratio = total / avg;
fprintf(out, " # %8.0f cycles / transaction ", ratio);
} else if (perf_stat_evsel__is(evsel, ELISION_START) &&
- avg > 0 &&
runtime_cycles_in_tx_stats[ctx][cpu].n != 0) {
total = avg_stats(&runtime_cycles_in_tx_stats[ctx][cpu]);
- if (total)
+ if (avg)
ratio = total / avg;
fprintf(out, " # %8.0f cycles / elision ", ratio);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 28c4b74..0a9ae80 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -191,6 +191,12 @@
if (thread->pid_ == parent->pid_)
return 0;
+ if (thread->mg == parent->mg) {
+ pr_debug("broken map groups on thread %d/%d parent %d/%d\n",
+ thread->pid_, thread->tid, parent->pid_, parent->tid);
+ return 0;
+ }
+
/* But this one is new process, copy maps. */
for (i = 0; i < MAP__NR_TYPES; ++i)
if (map_groups__clone(thread->mg, parent->mg, i) < 0)
diff --git a/tools/testing/selftests/firmware/fw_filesystem.sh b/tools/testing/selftests/firmware/fw_filesystem.sh
index 3fc6c10..c4366dc 100755
--- a/tools/testing/selftests/firmware/fw_filesystem.sh
+++ b/tools/testing/selftests/firmware/fw_filesystem.sh
@@ -9,7 +9,15 @@
DIR=/sys/devices/virtual/misc/test_firmware
-OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
+# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
+# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
+# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
+HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
+
+if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+ OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
+fi
+
OLD_FWPATH=$(cat /sys/module/firmware_class/parameters/path)
FWPATH=$(mktemp -d)
@@ -17,7 +25,9 @@
test_finish()
{
- echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
+ if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+ echo "$OLD_TIMEOUT" >/sys/class/firmware/timeout
+ fi
echo -n "$OLD_PATH" >/sys/module/firmware_class/parameters/path
rm -f "$FW"
rmdir "$FWPATH"
@@ -25,8 +35,11 @@
trap "test_finish" EXIT
-# Turn down the timeout so failures don't take so long.
-echo 1 >/sys/class/firmware/timeout
+if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+ # Turn down the timeout so failures don't take so long.
+ echo 1 >/sys/class/firmware/timeout
+fi
+
# Set the kernel search path.
echo -n "$FWPATH" >/sys/module/firmware_class/parameters/path
@@ -41,7 +54,9 @@
echo "$0: firmware was not expected to match" >&2
exit 1
else
- echo "$0: timeout works"
+ if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+ echo "$0: timeout works"
+ fi
fi
# This should succeed via kernel load or will fail after 1 second after
diff --git a/tools/testing/selftests/firmware/fw_userhelper.sh b/tools/testing/selftests/firmware/fw_userhelper.sh
index 6efbade..b9983f8 100755
--- a/tools/testing/selftests/firmware/fw_userhelper.sh
+++ b/tools/testing/selftests/firmware/fw_userhelper.sh
@@ -9,7 +9,17 @@
DIR=/sys/devices/virtual/misc/test_firmware
-OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
+# CONFIG_FW_LOADER_USER_HELPER has a sysfs class under /sys/class/firmware/
+# These days no one enables CONFIG_FW_LOADER_USER_HELPER so check for that
+# as an indicator for CONFIG_FW_LOADER_USER_HELPER.
+HAS_FW_LOADER_USER_HELPER=$(if [ -d /sys/class/firmware/ ]; then echo yes; else echo no; fi)
+
+if [ "$HAS_FW_LOADER_USER_HELPER" = "yes" ]; then
+ OLD_TIMEOUT=$(cat /sys/class/firmware/timeout)
+else
+ echo "usermode helper disabled so ignoring test"
+ exit 0
+fi
FWPATH=$(mktemp -d)
FW="$FWPATH/test-firmware.bin"
diff --git a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
index 7f0c756..3d7dc6a 100644
--- a/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
+++ b/tools/testing/selftests/futex/functional/futex_requeue_pi_signal_restart.c
@@ -191,7 +191,7 @@
if (res > 0) {
atomic_set(&requeued, 1);
break;
- } else if (res > 0) {
+ } else if (res < 0) {
error("FUTEX_CMP_REQUEUE_PI failed\n", errno);
ret = RET_ERROR;
break;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 8b8a444..d8db2f8f 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2206,6 +2206,11 @@
}
kvm->vcpus[atomic_read(&kvm->online_vcpus)] = vcpu;
+
+ /*
+ * Pairs with smp_rmb() in kvm_get_vcpu. Write kvm->vcpus
+ * before kvm->online_vcpu's incremented value.
+ */
smp_wmb();
atomic_inc(&kvm->online_vcpus);
@@ -2618,9 +2623,6 @@
case KVM_CAP_USER_MEMORY:
case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS:
-#ifdef CONFIG_KVM_APIC_ARCHITECTURE
- case KVM_CAP_SET_BOOT_CPU_ID:
-#endif
case KVM_CAP_INTERNAL_ERROR_DATA:
#ifdef CONFIG_HAVE_KVM_MSI
case KVM_CAP_SIGNAL_MSI:
@@ -2716,17 +2718,6 @@
r = kvm_ioeventfd(kvm, &data);
break;
}
-#ifdef CONFIG_KVM_APIC_ARCHITECTURE
- case KVM_SET_BOOT_CPU_ID:
- r = 0;
- mutex_lock(&kvm->lock);
- if (atomic_read(&kvm->online_vcpus) != 0)
- r = -EBUSY;
- else
- kvm->bsp_vcpu_id = arg;
- mutex_unlock(&kvm->lock);
- break;
-#endif
#ifdef CONFIG_HAVE_KVM_MSI
case KVM_SIGNAL_MSI: {
struct kvm_msi msi;