D: Co-author of German book ``Linux-Kernel-Programmierung''
D: Co-founder of Berlin Linux User Group
+N: Andrew Victor
+E: linux@maxim.org.za
+W: http://maxim.org.za/at91_26.html
+D: First maintainer of Atmel ARM-based SoC, aka AT91
+D: Introduced support for at91rm9200, the first chip of AT91 family
+S: South Africa
+
N: Riku Voipio
E: riku.voipio@iki.fi
D: Author of PCA9532 LED and Fintek f75375s hwmon driver
The addresses are normal I2C addresses. The adapter is the string
name of the adapter, as shown in /sys/class/i2c-adapter/i2c-<n>/name.
-It is *NOT* i2c-<n> itself.
+It is *NOT* i2c-<n> itself. Also, the comparison is done ignoring
+spaces, so if the name is "This is an I2C chip" you can say
+adapter_name=ThisisanI2cchip. This is because it's hard to pass in
+spaces in kernel parameters.
The debug flags are bit flags for each BMC found, they are:
IPMI messages: 1, driver state: 2, timing: 4, I2C probe: 8
GPIO support
~~~~~~~~~~~~
ACPI 5 introduced two new resources to describe GPIO connections: GpioIo
-and GpioInt. These resources are used be used to pass GPIO numbers used by
+and GpioInt. These resources can be used to pass GPIO numbers used by
the device to the driver. ACPI 5.1 extended this with _DSD (Device
Specific Data) which made it possible to name the GPIOs among other things.
_DSD Device Properties Related to GPIO
--------------------------------------
-With the release of ACPI 5.1 and the _DSD configuration objecte names
-can finally be given to GPIOs (and other things as well) returned by
-_CRS. Previously, we were only able to use an integer index to find
+With the release of ACPI 5.1, the _DSD configuration object finally
+allows names to be given to GPIOs (and other things as well) returned
+by _CRS. Previously, we were only able to use an integer index to find
the corresponding GPIO, which is pretty error prone (it depends on
the _CRS output ordering, for example).
Required properties:
- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
Should be "ti,omap4-l3-noc" for OMAP4 family
+ Should be "ti,omap5-l3-noc" for OMAP5 family
Should be "ti,dra7-l3-noc" for DRA7 family
Should be "ti,am4372-l3-noc" for AM43 family
- reg: Contains L3 register address range for each noc domain.
80 81 68 69
70 71 72 73
74 75 76 77>;
- interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+ interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
"saif0", "saif1", "i2c0", "i2c1",
"auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
"auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
--- /dev/null
+* MTD SPI driver for ST M25Pxx (and similar) serial flash chips
+
+Required properties:
+- #address-cells, #size-cells : Must be present if the device has sub-nodes
+ representing partitions.
+- compatible : May include a device-specific string consisting of the
+ manufacturer and name of the chip. Bear in mind the DT binding
+ is not Linux-only, but in case of Linux, see the "m25p_ids"
+ table in drivers/mtd/devices/m25p80.c for the list of supported
+ chips.
+ Must also include "jedec,spi-nor" for any SPI NOR flash that can
+ be identified by the JEDEC READ ID opcode (0x9F).
+- reg : Chip-Select number
+- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
+
+Optional properties:
+- m25p,fast-read : Use the "fast read" opcode to read data from the chip instead
+ of the usual "read" opcode. This opcode is not supported by
+ all chips and support for it can not be detected at runtime.
+ Refer to your chips' datasheet to check if this is supported
+ by your chip.
+
+Example:
+
+ flash: m25p80@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spansion,m25p80", "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ m25p,fast-read;
+ };
+++ /dev/null
-* MTD SPI driver for ST M25Pxx (and similar) serial flash chips
-
-Required properties:
-- #address-cells, #size-cells : Must be present if the device has sub-nodes
- representing partitions.
-- compatible : May include a device-specific string consisting of the
- manufacturer and name of the chip. Bear in mind the DT binding
- is not Linux-only, but in case of Linux, see the "m25p_ids"
- table in drivers/mtd/devices/m25p80.c for the list of supported
- chips.
- Must also include "nor-jedec" for any SPI NOR flash that can be
- identified by the JEDEC READ ID opcode (0x9F).
-- reg : Chip-Select number
-- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
-
-Optional properties:
-- m25p,fast-read : Use the "fast read" opcode to read data from the chip instead
- of the usual "read" opcode. This opcode is not supported by
- all chips and support for it can not be detected at runtime.
- Refer to your chips' datasheet to check if this is supported
- by your chip.
-
-Example:
-
- flash: m25p80@0 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "spansion,m25p80", "nor-jedec";
- reg = <0>;
- spi-max-frequency = <40000000>;
- m25p,fast-read;
- };
--- /dev/null
+Abracon ABX80X I2C ultra low power RTC/Alarm chip
+
+The Abracon ABX80X family consist of the ab0801, ab0803, ab0804, ab0805, ab1801,
+ab1803, ab1804 and ab1805. The ab0805 is the superset of ab080x and the ab1805
+is the superset of ab180x.
+
+Required properties:
+
+ - "compatible": should one of:
+ "abracon,abx80x"
+ "abracon,ab0801"
+ "abracon,ab0803"
+ "abracon,ab0804"
+ "abracon,ab0805"
+ "abracon,ab1801"
+ "abracon,ab1803"
+ "abracon,ab1804"
+ "abracon,ab1805"
+ Using "abracon,abx80x" will enable chip autodetection.
+ - "reg": I2C bus address of the device
+
+Optional properties:
+
+The abx804 and abx805 have a trickle charger that is able to charge the
+connected battery or supercap. Both the following properties have to be defined
+and valid to enable charging:
+
+ - "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V)
+ - "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output
+ resistor, the other values are in ohm.
bugs.
KASan uses compile-time instrumentation for checking every memory access,
-therefore you will need a certain version of GCC > 4.9.2
+therefore you will need a gcc version of 4.9.2 or later. KASan could detect out
+of bounds accesses to stack or global variables, but only if gcc 5.0 or later was
+used to built the kernel.
Currently KASan is supported only for x86_64 architecture and requires that the
kernel be built with the SLUB allocator.
and choose between CONFIG_KASAN_OUTLINE and CONFIG_KASAN_INLINE. Outline/inline
is compiler instrumentation types. The former produces smaller binary the
-latter is 1.1 - 2 times faster. Inline instrumentation requires GCC 5.0 or
-latter.
+latter is 1.1 - 2 times faster. Inline instrumentation requires a gcc version
+of 5.0 or later.
Currently KASAN works only with the SLUB memory allocator.
For better bug detection and nicer report, enable CONFIG_STACKTRACE and put
TTY_OTHER_CLOSED Device is a pty and the other side has closed.
+TTY_OTHER_DONE Device is a pty and the other side has closed and
+ all pending input processing has been completed.
+
TTY_NO_WRITE_SPLIT Prevent driver from splitting up writes into
smaller chunks.
F: arch/arm/mach-alpine/
ARM/ATMEL AT91RM9200 AND AT91SAM ARM ARCHITECTURES
-M: Andrew Victor <linux@maxim.org.za>
M: Nicolas Ferre <nicolas.ferre@atmel.com>
+M: Alexandre Belloni <alexandre.belloni@free-electrons.com>
M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-W: http://maxim.org.za/at91_26.html
W: http://www.linux4sam.org
S: Supported
F: arch/arm/mach-at91/
ARM/CORTINA SYSTEMS GEMINI ARM ARCHITECTURE
M: Hans Ulli Kroll <ulli.kroll@googlemail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-T: git git://git.berlios.de/gemini-board
+T: git git://github.com/ulli-kroll/linux.git
S: Maintained
F: arch/arm/mach-gemini/
F: drivers/clocksource/timer-atlas7.c
N: [^a-z]sirf
+ARM/CONEXANT DIGICOLOR MACHINE SUPPORT
+M: Baruch Siach <baruch@tkos.co.il>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+N: digicolor
+
ARM/EBSA110 MACHINE SUPPORT
M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
M: Philipp Zabel <philipp.zabel@gmail.com>
S: Maintained
-ARM/Marvell Armada 370 and Armada XP SOC support
+ARM/Marvell Kirkwood and Armada 370, 375, 38x, XP SOC support
M: Jason Cooper <jason@lakedaemon.net>
M: Andrew Lunn <andrew@lunn.ch>
M: Gregory Clement <gregory.clement@free-electrons.com>
S: Maintained
F: arch/arm/mach-mvebu/
F: drivers/rtc/rtc-armada38x.c
+F: arch/arm/boot/dts/armada*
+F: arch/arm/boot/dts/kirkwood*
+
ARM/Marvell Berlin SoC support
M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-berlin/
+F: arch/arm/boot/dts/berlin*
+
ARM/Marvell Dove/MV78xx0/Orion SOC support
M: Jason Cooper <jason@lakedaemon.net>
F: arch/arm/mach-mv78xx0/
F: arch/arm/mach-orion5x/
F: arch/arm/plat-orion/
+F: arch/arm/boot/dts/dove*
+F: arch/arm/boot/dts/orion5x*
+
ARM/Orion SoC/Technologic Systems TS-78xx platform support
M: Alexander Clouter <alex@digriz.org.uk>
ARM/SAMSUNG EXYNOS ARM ARCHITECTURES
M: Kukjin Kim <kgene@kernel.org>
+M: Krzysztof Kozlowski <k.kozlowski@samsung.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
S: Maintained
M: Dinh Nguyen <dinguyen@opensource.altera.com>
S: Maintained
F: arch/arm/mach-socfpga/
+F: arch/arm/boot/dts/socfpga*
+F: arch/arm/configs/socfpga_defconfig
W: http://www.rocketboards.org
-T: git://git.rocketboards.org/linux-socfpga.git
-T: git://git.rocketboards.org/linux-socfpga-next.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/dinguyen/linux.git
ARM/SOCFPGA CLOCK FRAMEWORK SUPPORT
M: Dinh Nguyen <dinguyen@opensource.altera.com>
F: drivers/net/wireless/b43legacy/
BACKLIGHT CLASS/SUBSYSTEM
-M: Jingoo Han <jg1.han@samsung.com>
+M: Jingoo Han <jingoohan1@gmail.com>
M: Lee Jones <lee.jones@linaro.org>
S: Maintained
F: drivers/video/backlight/
F: drivers/net/ethernet/broadcom/bnx2x/
BROADCOM BCM281XX/BCM11XXX/BCM216XX ARM ARCHITECTURE
-M: Christian Daudt <bcm@fixthebug.org>
M: Florian Fainelli <f.fainelli@gmail.com>
+M: Ray Jui <rjui@broadcom.com>
+M: Scott Branden <sbranden@broadcom.com>
L: bcm-kernel-feedback-list@broadcom.com
T: git git://github.com/broadcom/mach-bcm
S: Maintained
F: drivers/usb/gadget/udc/bcm63xx_udc.*
BROADCOM BCM7XXX ARM ARCHITECTURE
-M: Marc Carino <marc.ceeeee@gmail.com>
M: Brian Norris <computersforpeace@gmail.com>
M: Gregory Fong <gregory.0xf0@gmail.com>
M: Florian Fainelli <f.fainelli@gmail.com>
F: Documentation/extcon/
EXYNOS DP DRIVER
-M: Jingoo Han <jg1.han@samsung.com>
+M: Jingoo Han <jingoohan1@gmail.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
F: drivers/gpu/drm/exynos/exynos_dp*
F: include/uapi/linux/gfs2_ondisk.h
GIGASET ISDN DRIVERS
-M: Hansjoerg Lipp <hjlipp@web.de>
-M: Tilman Schmidt <tilman@imap.cc>
+M: Paul Bolle <pebolle@tiscali.nl>
L: gigaset307x-common@lists.sourceforge.net
W: http://gigaset307x.sourceforge.net/
-S: Maintained
+S: Odd Fixes
F: Documentation/isdn/README.gigaset
F: drivers/isdn/gigaset/
F: include/uapi/linux/gigaset_dev.h
F: drivers/video/fbdev/imsttfb.c
INFINIBAND SUBSYSTEM
-M: Roland Dreier <roland@kernel.org>
+M: Doug Ledford <dledford@redhat.com>
M: Sean Hefty <sean.hefty@intel.com>
M: Hal Rosenstock <hal.rosenstock@gmail.com>
L: linux-rdma@vger.kernel.org
W: http://www.openfabrics.org/
Q: http://patchwork.kernel.org/project/linux-rdma/list/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/roland/infiniband.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/dledford/rdma.git
S: Supported
F: Documentation/infiniband/
F: drivers/infiniband/
F: include/uapi/linux/if_infiniband.h
+F: include/uapi/rdma/
+F: include/rdma/
INOTIFY
M: John McCutchan <john@johnmccutchan.com>
LED SUBSYSTEM
M: Bryan Wu <cooloney@gmail.com>
M: Richard Purdie <rpurdie@rpsys.net>
+M: Jacek Anaszewski <j.anaszewski@samsung.com>
L: linux-leds@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/linux-leds.git
S: Maintained
S: Maintained
F: arch/nios2/
+NOKIA N900 POWER SUPPLY DRIVERS
+M: Pali Rohár <pali.rohar@gmail.com>
+S: Maintained
+F: include/linux/power/bq2415x_charger.h
+F: include/linux/power/bq27x00_battery.h
+F: include/linux/power/isp1704_charger.h
+F: drivers/power/bq2415x_charger.c
+F: drivers/power/bq27x00_battery.c
+F: drivers/power/isp1704_charger.c
+F: drivers/power/rx51_battery.c
+
NTB DRIVER
M: Jon Mason <jdmason@kudzu.us>
M: Dave Jiang <dave.jiang@intel.com>
F: drivers/pci/host/*rcar*
PCI DRIVER FOR SAMSUNG EXYNOS
-M: Jingoo Han <jg1.han@samsung.com>
+M: Jingoo Han <jingoohan1@gmail.com>
L: linux-pci@vger.kernel.org
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
F: drivers/pci/host/pci-exynos.c
PCI DRIVER FOR SYNOPSIS DESIGNWARE
-M: Jingoo Han <jg1.han@samsung.com>
+M: Jingoo Han <jingoohan1@gmail.com>
L: linux-pci@vger.kernel.org
S: Maintained
F: drivers/pci/host/*designware*
F: sound/soc/samsung/
SAMSUNG FRAMEBUFFER DRIVER
-M: Jingoo Han <jg1.han@samsung.com>
+M: Jingoo Han <jingoohan1@gmail.com>
L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/video/fbdev/s3c-fb.c
S: Supported
F: drivers/scsi/be2iscsi/
-SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER
-M: Sathya Perla <sathya.perla@emulex.com>
-M: Subbu Seetharaman <subbu.seetharaman@emulex.com>
-M: Ajit Khaparde <ajit.khaparde@emulex.com>
+Emulex 10Gbps NIC BE2, BE3-R, Lancer, Skyhawk-R DRIVER
+M: Sathya Perla <sathya.perla@avagotech.com>
+M: Ajit Khaparde <ajit.khaparde@avagotech.com>
+M: Padmanabh Ratnakar <padmanabh.ratnakar@avagotech.com>
+M: Sriharsha Basavapatna <sriharsha.basavapatna@avagotech.com>
L: netdev@vger.kernel.org
W: http://www.emulex.com
S: Supported
ZRAM COMPRESSED RAM BLOCK DEVICE DRVIER
M: Minchan Kim <minchan@kernel.org>
M: Nitin Gupta <ngupta@vflare.org>
+R: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/block/zram/
VERSION = 4
PATCHLEVEL = 1
SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
NAME = Hurr durr I'ma sheep
# *DOCUMENTATION*
source "lib/Kconfig.debug"
-config EARLY_PRINTK
- bool "Early printk" if EMBEDDED
- default y
- help
- Write kernel log output directly into the VGA buffer or to a serial
- port.
-
- This is useful for kernel debugging when your machine crashes very
- early before the console code is initialized. For normal operation
- it is not recommended because it looks ugly and doesn't cooperate
- with klogd/syslogd or the X server. You should normally N here,
- unless you want to debug such a crash.
-
config 16KSTACKS
bool "Use 16Kb for kernel stacks instead of 8Kb"
help
atomic_ops_unlock(flags); \
}
-#define ATOMIC_OP_RETURN(op, c_op) \
+#define ATOMIC_OP_RETURN(op, c_op, asm_op) \
static inline int atomic_##op##_return(int i, atomic_t *v) \
{ \
unsigned long flags; \
* Machine specific helpers for Entire D-Cache or Per Line ops
*/
-static unsigned int __before_dc_op(const int op)
+static inline unsigned int __before_dc_op(const int op)
{
unsigned int reg = reg;
return reg;
}
-static void __after_dc_op(const int op, unsigned int reg)
+static inline void __after_dc_op(const int op, unsigned int reg)
{
if (op & OP_FLUSH) /* flush / flush-n-inv both wait */
while (read_aux_reg(ARC_REG_DC_CTRL) & DC_CTRL_FLUSH_STATUS);
pinctrl-0 = <&matrix_keypad_pins>;
debounce-delay-ms = <5>;
- col-scan-delay-us = <1500>;
+ col-scan-delay-us = <5>;
row-gpios = <&gpio5 5 GPIO_ACTIVE_HIGH /* Bank5, pin5 */
&gpio5 6 GPIO_ACTIVE_HIGH>; /* Bank5, pin6 */
interrupt-parent = <&gpio0>;
interrupts = <31 0>;
- wake-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
touchscreen-size-x = <480>;
touchscreen-size-y = <272>;
aliases {
rtc0 = &mcp_rtc;
rtc1 = &tps659038_rtc;
+ rtc2 = &rtc;
};
memory {
gpio_fan: gpio_fan {
/* Based on 5v 500mA AFB02505HHB */
compatible = "gpio-fan";
- gpios = <&tps659038_gpio 1 GPIO_ACTIVE_HIGH>;
+ gpios = <&tps659038_gpio 2 GPIO_ACTIVE_HIGH>;
gpio-fan,speed-map = <0 0>,
<13000 1>;
#cooling-cells = <2>;
uart3_pins_default: uart3_pins_default {
pinctrl-single,pins = <
- 0x248 (PIN_INPUT_SLEW | MUX_MODE0) /* uart3_rxd.rxd */
- 0x24c (PIN_INPUT_SLEW | MUX_MODE0) /* uart3_txd.txd */
+ 0x3f8 (PIN_INPUT_SLEW | MUX_MODE2) /* uart2_ctsn.uart3_rxd */
+ 0x3fc (PIN_INPUT_SLEW | MUX_MODE1) /* uart2_rtsn.uart3_txd */
>;
};
mcp_rtc: rtc@6f {
compatible = "microchip,mcp7941x";
reg = <0x6f>;
- interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_LOW>; /* IRQ_SYS_1N */
+ interrupts = <GIC_SPI 2 IRQ_TYPE_EDGE_RISING>; /* IRQ_SYS_1N */
pinctrl-names = "default";
pinctrl-0 = <&mcp79410_pins_default>;
&uart3 {
status = "okay";
interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
- <&dra7_pmx_core 0x248>;
+ <&dra7_pmx_core 0x3f8>;
pinctrl-names = "default";
pinctrl-0 = <&uart3_pins_default>;
mainpll: mainpll {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <2000000000>;
+ clock-frequency = <1000000000>;
};
/* 25 MHz reference crystal */
refclk: oscillator {
mainpll: mainpll {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <2000000000>;
+ clock-frequency = <1000000000>;
};
/* 25 MHz reference crystal */
mainpll: mainpll {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <2000000000>;
+ clock-frequency = <1000000000>;
};
};
};
};
internal-regs {
+ rtc@10300 {
+ /* No crystal connected to the internal RTC */
+ status = "disabled";
+ };
serial@12000 {
status = "okay";
};
/* connect xtal input to 25MHz reference */
clocks = <&ref25>;
+ clock-names = "xtal";
/* connect xtal input as source of pll0 and pll1 */
silabs,pll-source = <0 0>, <1 0>;
ti,clock-cycles = <16>;
reg = <0x4ae07ddc 0x4>, <0x4ae07de0 0x4>,
- <0x4ae06014 0x4>, <0x4a003b20 0x8>,
+ <0x4ae06014 0x4>, <0x4a003b20 0xc>,
<0x4ae0c158 0x4>;
reg-names = "setup-address", "control-address",
"int-address", "efuse-address",
ti,clock-cycles = <16>;
reg = <0x4ae07e34 0x4>, <0x4ae07e24 0x4>,
- <0x4ae06010 0x4>, <0x4a0025cc 0x8>,
+ <0x4ae06010 0x4>, <0x4a0025cc 0xc>,
<0x4a002470 0x4>;
reg-names = "setup-address", "control-address",
"int-address", "efuse-address",
ti,clock-cycles = <16>;
reg = <0x4ae07e30 0x4>, <0x4ae07e20 0x4>,
- <0x4ae06010 0x4>, <0x4a0025e0 0x8>,
+ <0x4ae06010 0x4>, <0x4a0025e0 0xc>,
<0x4a00246c 0x4>;
reg-names = "setup-address", "control-address",
"int-address", "efuse-address",
ti,clock-cycles = <16>;
reg = <0x4ae07de4 0x4>, <0x4ae07de8 0x4>,
- <0x4ae06010 0x4>, <0x4a003b08 0x8>,
+ <0x4ae06010 0x4>, <0x4a003b08 0xc>,
<0x4ae0c154 0x4>;
reg-names = "setup-address", "control-address",
"int-address", "efuse-address",
status = "disabled";
};
- rtc@48838000 {
+ rtc: rtc@48838000 {
compatible = "ti,am3352-rtc";
reg = <0x48838000 0x100>;
interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>,
#include <dt-bindings/sound/samsung-i2s.h>
#include <dt-bindings/input/input.h>
+#include <dt-bindings/clock/maxim,max77686.h>
#include "exynos4412.dtsi"
/ {
rtc@10070000 {
status = "okay";
+ clocks = <&clock CLK_RTC>, <&max77686 MAX77686_CLK_AP>;
+ clock-names = "rtc", "rtc_src";
};
g2d@10800000 {
num-slots = <1>;
broken-cd;
cap-sdio-irq;
+ keep-power-in-suspend;
card-detect-delay = <200>;
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <2 3>;
num-slots = <1>;
broken-cd;
cap-sdio-irq;
+ keep-power-in-suspend;
card-detect-delay = <200>;
clock-frequency = <400000000>;
samsung,dw-mshc-ciu-div = <1>;
type = "active";
};
cpu-crit-0 {
- temperature = <1200000>; /* millicelsius */
+ temperature = <120000>; /* millicelsius */
hysteresis = <0>; /* millicelsius */
type = "critical";
};
clock-names = "dp";
phys = <&dp_phy>;
phy-names = "dp";
+ power-domains = <&disp_pd>;
};
mipi_phy: video-phy@10040714 {
type = "active";
};
cpu-crit-0 {
- temperature = <1050000>; /* millicelsius */
+ temperature = <105000>; /* millicelsius */
hysteresis = <0>; /* millicelsius */
type = "critical";
};
num-slots = <1>;
broken-cd;
cap-sdio-irq;
+ keep-power-in-suspend;
card-detect-delay = <200>;
clock-frequency = <400000000>;
samsung,dw-mshc-ciu-div = <1>;
*/
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
#include "imx23.dtsi"
/ {
ahb@80080000 {
usb0: usb@80080000 {
+ dr_mode = "host";
vbus-supply = <®_usb0_vbus>;
status = "okay";
};
user {
label = "green";
- gpios = <&gpio2 1 1>;
+ gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
};
};
};
pwm4: pwm@53fc8000 {
compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+ #pwm-cells = <2>;
reg = <0x53fc8000 0x4000>;
clocks = <&clks 108>, <&clks 52>;
clock-names = "ipg", "per";
80 81 68 69
70 71 72 73
74 75 76 77>;
- interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+ interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
"saif0", "saif1", "i2c0", "i2c1",
"auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
"auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio4 15 0>;
+ enable-active-high;
};
reg_usb_h1_vbus: regulator@1 {
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio1 0 0>;
+ enable-active-high;
};
};
&i2c3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
- pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>;
status = "okay";
max7310_a: gpio@30 {
DRVDD-supply = <&vmmc2>;
IOVDD-supply = <&vio>;
DVDD-supply = <&vio>;
+
+ ai3x-micbias-vg = <1>;
};
tlv320aic3x_aux: tlv320aic3x@19 {
DRVDD-supply = <&vmmc2>;
IOVDD-supply = <&vio>;
DVDD-supply = <&vio>;
+
+ ai3x-micbias-vg = <2>;
};
tsl2563: tsl2563@29 {
};
mmu_isp: mmu@480bd400 {
+ #iommu-cells = <0>;
compatible = "ti,omap2-iommu";
reg = <0x480bd400 0x80>;
interrupts = <24>;
};
mmu_iva: mmu@5d000000 {
+ #iommu-cells = <0>;
compatible = "ti,omap2-iommu";
reg = <0x5d000000 0x80>;
interrupts = <28>;
* hierarchy.
*/
ocp {
- compatible = "ti,omap4-l3-noc", "simple-bus";
+ compatible = "ti,omap5-l3-noc", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
compatible = "adi,adv7511w";
reg = <0x39>;
interrupt-parent = <&gpio3>;
- interrupts = <29 IRQ_TYPE_EDGE_FALLING>;
+ interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
adi,input-depth = <8>;
adi,input-colorspace = "rgb";
status = "disabled";
};
- vmmci: regulator-gpio {
- compatible = "regulator-gpio";
-
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2900000>;
- regulator-name = "mmci-reg";
- regulator-type = "voltage";
-
- startup-delay-us = <100>;
- enable-active-high;
-
- states = <1800000 0x1
- 2900000 0x0>;
-
- status = "disabled";
- };
-
mcde@a0350000 {
compatible = "stericsson,mcde";
reg = <0xa0350000 0x1000>, /* MCDE */
pinctrl-1 = <&i2c3_sleep_mode>;
};
+ vmmci: regulator-gpio {
+ compatible = "regulator-gpio";
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-name = "mmci-reg";
+ regulator-type = "voltage";
+
+ startup-delay-us = <100>;
+ enable-active-high;
+
+ states = <1800000 0x1
+ 2900000 0x0>;
+ };
+
// External Micro SD slot
sdi0_per1@80126000 {
arm,primecell-periphid = <0x10480180>;
};
vmmci: regulator-gpio {
+ compatible = "regulator-gpio";
+
gpios = <&gpio7 4 0x4>;
enable-gpio = <&gpio6 25 0x4>;
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-name = "mmci-reg";
+ regulator-type = "voltage";
+
+ startup-delay-us = <100>;
+ enable-active-high;
+
+ states = <1800000 0x1
+ 2900000 0x0>;
};
// External Micro SD slot
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
- resets = <&tegra_car 59>, <&tegra_car 22>;
+ resets = <&tegra_car 22>, <&tegra_car 22>;
reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
nvidia,hssquelch-level = <2>;
nvidia,hsdiscon-level = <5>;
nvidia,xcvr-hsslew = <12>;
+ nvidia,has-utmi-pad-registers;
status = "disabled";
};
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
- resets = <&tegra_car 22>, <&tegra_car 22>;
+ resets = <&tegra_car 58>, <&tegra_car 22>;
reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
nvidia,hssquelch-level = <2>;
nvidia,hsdiscon-level = <5>;
nvidia,xcvr-hsslew = <12>;
- nvidia,has-utmi-pad-registers;
status = "disabled";
};
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
- resets = <&tegra_car 58>, <&tegra_car 22>;
+ resets = <&tegra_car 59>, <&tegra_car 22>;
reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
compatible = "arm,cortex-a15-pmu";
interrupts = <0 68 4>,
<0 69 4>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
};
oscclk6a: oscclk6a {
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ A9_0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
next-level-cache = <&L2>;
};
- cpu@1 {
+ A9_1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <1>;
next-level-cache = <&L2>;
};
- cpu@2 {
+ A9_2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <2>;
next-level-cache = <&L2>;
};
- cpu@3 {
+ A9_3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <3>;
compatible = "arm,pl310-cache";
reg = <0x1e00a000 0x1000>;
interrupts = <0 43 4>;
+ cache-unified;
cache-level = <2>;
arm,data-latency = <1 1 1>;
arm,tag-latency = <1 1 1>;
<0 61 4>,
<0 62 4>,
<0 63 4>;
+ interrupt-affinity = <&A9_0>, <&A9_1>, <&A9_2>, <&A9_3>;
+
};
dcc {
CONFIG_ARCH_KEYSTONE=y
CONFIG_ARCH_MESON=y
CONFIG_ARCH_MXC=y
+CONFIG_SOC_IMX50=y
CONFIG_SOC_IMX51=y
CONFIG_SOC_IMX53=y
CONFIG_SOC_IMX6Q=y
CONFIG_SOC_IMX6SL=y
+CONFIG_SOC_IMX6SX=y
CONFIG_SOC_VF610=y
+CONFIG_SOC_LS1021A=y
CONFIG_ARCH_OMAP3=y
CONFIG_ARCH_OMAP4=y
CONFIG_SOC_OMAP5=y
CONFIG_DMA_OMAP=y
# CONFIG_IOMMU_SUPPORT is not set
CONFIG_EXTCON=m
-CONFIG_EXTCON_GPIO=m
+CONFIG_EXTCON_USB_GPIO=m
CONFIG_EXTCON_PALMAS=m
CONFIG_TI_EMIF=m
CONFIG_PWM=y
};
struct dma_iommu_mapping *
-arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size);
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, u64 size);
void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping);
bool xen_arch_need_swiotlb(struct device *dev,
unsigned long pfn,
unsigned long mfn);
+unsigned long xen_get_swiotlb_free_pages(unsigned int order);
#endif /* _ASM_ARM_XEN_PAGE_H */
static int of_pmu_irq_cfg(struct platform_device *pdev)
{
- int i;
+ int i, irq;
int *irqs = kcalloc(pdev->num_resources, sizeof(*irqs), GFP_KERNEL);
if (!irqs)
return -ENOMEM;
+ /* Don't bother with PPIs; they're already affine */
+ irq = platform_get_irq(pdev, 0);
+ if (irq >= 0 && irq_is_percpu(irq))
+ return 0;
+
for (i = 0; i < pdev->num_resources; ++i) {
struct device_node *dn;
int cpu;
i);
if (!dn) {
pr_warn("Failed to parse %s/interrupt-affinity[%d]\n",
- of_node_full_name(dn), i);
+ of_node_full_name(pdev->dev.of_node), i);
break;
}
extern struct cpuidle_exynos_data cpuidle_coupled_exynos_data;
+extern void exynos_set_delayed_reset_assertion(bool enable);
+
extern void s5p_init_cpu(void __iomem *cpuid_addr);
extern unsigned int samsung_rev(void);
extern void __iomem *cpu_boot_reg_base(void);
exynos_map_io();
}
+/*
+ * Set or clear the USE_DELAYED_RESET_ASSERTION option. Used by smp code
+ * and suspend.
+ *
+ * This is necessary only on Exynos4 SoCs. When system is running
+ * USE_DELAYED_RESET_ASSERTION should be set so the ARM CLK clock down
+ * feature could properly detect global idle state when secondary CPU is
+ * powered down.
+ *
+ * However this should not be set when such system is going into suspend.
+ */
+void exynos_set_delayed_reset_assertion(bool enable)
+{
+ if (of_machine_is_compatible("samsung,exynos4")) {
+ unsigned int tmp, core_id;
+
+ for (core_id = 0; core_id < num_possible_cpus(); core_id++) {
+ tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id));
+ if (enable)
+ tmp |= S5P_USE_DELAYED_RESET_ASSERTION;
+ else
+ tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION);
+ pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id));
+ }
+ }
+}
+
/*
* Apparently, these SoCs are not able to wake-up from suspend using
* the PMU. Too bad. Should they suddenly become capable of such a
extern void exynos4_secondary_startup(void);
-/*
- * Set or clear the USE_DELAYED_RESET_ASSERTION option, set on Exynos4 SoCs
- * during hot-(un)plugging CPUx.
- *
- * The feature can be cleared safely during first boot of secondary CPU.
- *
- * Exynos4 SoCs require setting USE_DELAYED_RESET_ASSERTION during powering
- * down a CPU so the CPU idle clock down feature could properly detect global
- * idle state when CPUx is off.
- */
-static void exynos_set_delayed_reset_assertion(u32 core_id, bool enable)
-{
- if (soc_is_exynos4()) {
- unsigned int tmp;
-
- tmp = pmu_raw_readl(EXYNOS_ARM_CORE_OPTION(core_id));
- if (enable)
- tmp |= S5P_USE_DELAYED_RESET_ASSERTION;
- else
- tmp &= ~(S5P_USE_DELAYED_RESET_ASSERTION);
- pmu_raw_writel(tmp, EXYNOS_ARM_CORE_OPTION(core_id));
- }
-}
-
#ifdef CONFIG_HOTPLUG_CPU
static inline void cpu_leave_lowpower(u32 core_id)
{
: "=&r" (v)
: "Ir" (CR_C), "Ir" (0x40)
: "cc");
-
- exynos_set_delayed_reset_assertion(core_id, false);
}
static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
/* Turn the CPU off on next WFI instruction. */
exynos_cpu_power_down(core_id);
- /*
- * Exynos4 SoCs require setting
- * USE_DELAYED_RESET_ASSERTION so the CPU idle
- * clock down feature could properly detect
- * global idle state when CPUx is off.
- */
- exynos_set_delayed_reset_assertion(core_id, true);
-
wfi();
if (pen_release == core_id) {
udelay(10);
}
- /* No harm if this is called during first boot of secondary CPU */
- exynos_set_delayed_reset_assertion(core_id, false);
-
/*
* now the secondary core is starting up let it run its
* calibrations, then wait for it to finish
exynos_sysram_init();
+ exynos_set_delayed_reset_assertion(true);
+
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
scu_enable(scu_base_addr());
args.np = np;
args.args_count = 0;
child_domain = of_genpd_get_from_provider(&args);
- if (!child_domain)
+ if (IS_ERR(child_domain))
continue;
if (of_parse_phandle_with_args(np, "power-domains",
continue;
parent_domain = of_genpd_get_from_provider(&args);
- if (!parent_domain)
+ if (IS_ERR(parent_domain))
continue;
if (pm_genpd_add_subdomain(parent_domain, child_domain))
static void exynos_pm_prepare(void)
{
+ exynos_set_delayed_reset_assertion(false);
+
/* Set wake-up mask registers */
exynos_pm_set_wakeup_mask();
/* Clear SLEEP mode set in INFORM1 */
pmu_raw_writel(0x0, S5P_INFORM1);
+ exynos_set_delayed_reset_assertion(true);
}
static void exynos3250_pm_resume(void)
return;
}
- if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL)))
+ if (WARN_ON(!of_find_property(np, "interrupt-controller", NULL))) {
pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
+ return;
+ }
pm_data = (const struct exynos_pm_data *) match->data;
#ifndef __GEMINI_COMMON_H__
#define __GEMINI_COMMON_H__
+#include <linux/reboot.h>
+
struct mtd_partition;
extern void gemini_map_io(void);
struct mtd_partition *parts,
unsigned int nr_parts);
-extern void gemini_restart(char mode, const char *cmd);
+extern void gemini_restart(enum reboot_mode mode, const char *cmd);
#endif /* __GEMINI_COMMON_H__ */
#include <mach/hardware.h>
#include <mach/global_reg.h>
-void gemini_restart(char mode, const char *cmd)
+#include "common.h"
+
+void gemini_restart(enum reboot_mode mode, const char *cmd)
{
__raw_writel(RESET_GLOBAL | RESET_CPU1,
IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_RESET);
/*
- * Copyright (C) 2010 Pengutronix, Wolfram Sang <w.sang@pengutronix.de>
+ * Copyright (C) 2010 Pengutronix, Wolfram Sang <kernel@pengutronix.de>
*
* 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
*/
#define LINKS_PER_OCP_IF 2
+/*
+ * Address offset (in bytes) between the reset control and the reset
+ * status registers: 4 bytes on OMAP4
+ */
+#define OMAP4_RST_CTRL_ST_OFFSET 4
+
/**
* struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations
* @enable_module: function to enable a module (via MODULEMODE)
if (ohri->st_shift)
pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
oh->name, ohri->name);
- return omap_prm_deassert_hardreset(ohri->rst_shift, 0,
+ return omap_prm_deassert_hardreset(ohri->rst_shift, ohri->rst_shift,
oh->clkdm->pwrdm.ptr->prcm_partition,
oh->clkdm->pwrdm.ptr->prcm_offs,
- oh->prcm.omap4.rstctrl_offs, 0);
+ oh->prcm.omap4.rstctrl_offs,
+ oh->prcm.omap4.rstctrl_offs +
+ OMAP4_RST_CTRL_ST_OFFSET);
}
/**
oh->prcm.omap4.rstctrl_offs);
}
-/**
- * _am33xx_assert_hardreset - call AM33XX PRM hardreset fn with hwmod args
- * @oh: struct omap_hwmod * to assert hardreset
- * @ohri: hardreset line data
- *
- * Call am33xx_prminst_assert_hardreset() with parameters extracted
- * from the hwmod @oh and the hardreset line data @ohri. Only
- * intended for use as an soc_ops function pointer. Passes along the
- * return value from am33xx_prminst_assert_hardreset(). XXX This
- * function is scheduled for removal when the PRM code is moved into
- * drivers/.
- */
-static int _am33xx_assert_hardreset(struct omap_hwmod *oh,
- struct omap_hwmod_rst_info *ohri)
-
-{
- return omap_prm_assert_hardreset(ohri->rst_shift, 0,
- oh->clkdm->pwrdm.ptr->prcm_offs,
- oh->prcm.omap4.rstctrl_offs);
-}
-
/**
* _am33xx_deassert_hardreset - call AM33XX PRM hardreset fn with hwmod args
* @oh: struct omap_hwmod * to deassert hardreset
static int _am33xx_deassert_hardreset(struct omap_hwmod *oh,
struct omap_hwmod_rst_info *ohri)
{
- return omap_prm_deassert_hardreset(ohri->rst_shift, ohri->st_shift, 0,
+ return omap_prm_deassert_hardreset(ohri->rst_shift, ohri->st_shift,
+ oh->clkdm->pwrdm.ptr->prcm_partition,
oh->clkdm->pwrdm.ptr->prcm_offs,
oh->prcm.omap4.rstctrl_offs,
oh->prcm.omap4.rstst_offs);
}
-/**
- * _am33xx_is_hardreset_asserted - call AM33XX PRM hardreset fn with hwmod args
- * @oh: struct omap_hwmod * to test hardreset
- * @ohri: hardreset line data
- *
- * Call am33xx_prminst_is_hardreset_asserted() with parameters
- * extracted from the hwmod @oh and the hardreset line data @ohri.
- * Only intended for use as an soc_ops function pointer. Passes along
- * the return value from am33xx_prminst_is_hardreset_asserted(). XXX
- * This function is scheduled for removal when the PRM code is moved
- * into drivers/.
- */
-static int _am33xx_is_hardreset_asserted(struct omap_hwmod *oh,
- struct omap_hwmod_rst_info *ohri)
-{
- return omap_prm_is_hardreset_asserted(ohri->rst_shift, 0,
- oh->clkdm->pwrdm.ptr->prcm_offs,
- oh->prcm.omap4.rstctrl_offs);
-}
-
/* Public functions */
u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs)
soc_ops.init_clkdm = _init_clkdm;
soc_ops.update_context_lost = _omap4_update_context_lost;
soc_ops.get_context_lost = _omap4_get_context_lost;
- } else if (soc_is_am43xx()) {
+ } else if (cpu_is_ti816x() || soc_is_am33xx() || soc_is_am43xx()) {
soc_ops.enable_module = _omap4_enable_module;
soc_ops.disable_module = _omap4_disable_module;
soc_ops.wait_target_ready = _omap4_wait_target_ready;
soc_ops.assert_hardreset = _omap4_assert_hardreset;
- soc_ops.deassert_hardreset = _omap4_deassert_hardreset;
- soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
- soc_ops.init_clkdm = _init_clkdm;
- } else if (cpu_is_ti816x() || soc_is_am33xx()) {
- soc_ops.enable_module = _omap4_enable_module;
- soc_ops.disable_module = _omap4_disable_module;
- soc_ops.wait_target_ready = _omap4_wait_target_ready;
- soc_ops.assert_hardreset = _am33xx_assert_hardreset;
soc_ops.deassert_hardreset = _am33xx_deassert_hardreset;
- soc_ops.is_hardreset_asserted = _am33xx_is_hardreset_asserted;
+ soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
soc_ops.init_clkdm = _init_clkdm;
} else {
WARN(1, "omap_hwmod: unknown SoC type\n");
},
};
+static struct omap_hwmod_class_sysconfig am43xx_vpfe_sysc = {
+ .rev_offs = 0x0,
+ .sysc_offs = 0x104,
+ .sysc_flags = SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE,
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+ MSTANDBY_FORCE | MSTANDBY_SMART | MSTANDBY_NO),
+ .sysc_fields = &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class am43xx_vpfe_hwmod_class = {
+ .name = "vpfe",
+ .sysc = &am43xx_vpfe_sysc,
+};
+
+static struct omap_hwmod am43xx_vpfe0_hwmod = {
+ .name = "vpfe0",
+ .class = &am43xx_vpfe_hwmod_class,
+ .clkdm_name = "l3s_clkdm",
+ .prcm = {
+ .omap4 = {
+ .modulemode = MODULEMODE_SWCTRL,
+ .clkctrl_offs = AM43XX_CM_PER_VPFE0_CLKCTRL_OFFSET,
+ },
+ },
+};
+
+static struct omap_hwmod am43xx_vpfe1_hwmod = {
+ .name = "vpfe1",
+ .class = &am43xx_vpfe_hwmod_class,
+ .clkdm_name = "l3s_clkdm",
+ .prcm = {
+ .omap4 = {
+ .modulemode = MODULEMODE_SWCTRL,
+ .clkctrl_offs = AM43XX_CM_PER_VPFE1_CLKCTRL_OFFSET,
+ },
+ },
+};
+
/* Interfaces */
static struct omap_hwmod_ocp_if am43xx_l3_main__l4_hs = {
.master = &am33xx_l3_main_hwmod,
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
+static struct omap_hwmod_ocp_if am43xx_l3__vpfe0 = {
+ .master = &am43xx_vpfe0_hwmod,
+ .slave = &am33xx_l3_main_hwmod,
+ .clk = "l3_gclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l3__vpfe1 = {
+ .master = &am43xx_vpfe1_hwmod,
+ .slave = &am33xx_l3_main_hwmod,
+ .clk = "l3_gclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__vpfe0 = {
+ .master = &am33xx_l4_ls_hwmod,
+ .slave = &am43xx_vpfe0_hwmod,
+ .clk = "l4ls_gclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if am43xx_l4_ls__vpfe1 = {
+ .master = &am33xx_l4_ls_hwmod,
+ .slave = &am43xx_vpfe1_hwmod,
+ .clk = "l4ls_gclk",
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
+};
+
static struct omap_hwmod_ocp_if *am43xx_hwmod_ocp_ifs[] __initdata = {
&am33xx_l4_wkup__synctimer,
&am43xx_l4_ls__timer8,
&am43xx_l4_ls__dss_dispc,
&am43xx_l4_ls__dss_rfbi,
&am43xx_l4_ls__hdq1w,
+ &am43xx_l3__vpfe0,
+ &am43xx_l3__vpfe1,
+ &am43xx_l4_ls__vpfe0,
+ &am43xx_l4_ls__vpfe1,
NULL,
};
#define AM43XX_CM_PER_USBPHYOCP2SCP1_CLKCTRL_OFFSET 0x05C0
#define AM43XX_CM_PER_DSS_CLKCTRL_OFFSET 0x0a20
#define AM43XX_CM_PER_HDQ1W_CLKCTRL_OFFSET 0x04a0
-
+#define AM43XX_CM_PER_VPFE0_CLKCTRL_OFFSET 0x0068
+#define AM43XX_CM_PER_VPFE1_CLKCTRL_OFFSET 0x0070
#endif
#define OMAP3430_VC_CMD_ONLP_SHIFT 16
#define OMAP3430_VC_CMD_RET_SHIFT 8
#define OMAP3430_VC_CMD_OFF_SHIFT 0
+#define OMAP3430_SREN_MASK (1 << 4)
#define OMAP3430_HSEN_MASK (1 << 3)
#define OMAP3430_MCODE_MASK (0x7 << 0)
#define OMAP3430_VALID_MASK (1 << 24)
#define OMAP4430_GLOBAL_WARM_SW_RST_SHIFT 1
#define OMAP4430_GLOBAL_WUEN_MASK (1 << 16)
#define OMAP4430_HSMCODE_MASK (0x7 << 0)
+#define OMAP4430_SRMODEEN_MASK (1 << 4)
#define OMAP4430_HSMODEEN_MASK (1 << 3)
#define OMAP4430_HSSCLL_SHIFT 24
#define OMAP4430_ICEPICK_RST_SHIFT 9
return v;
}
-/*
- * Address offset (in bytes) between the reset control and the reset
- * status registers: 4 bytes on OMAP4
- */
-#define OMAP4_RST_CTRL_ST_OFFSET 4
-
/**
* omap4_prminst_is_hardreset_asserted - read the HW reset line state of
* submodules contained in the hwmod module
* omap4_prminst_deassert_hardreset - deassert a submodule hardreset line and
* wait
* @shift: register bit shift corresponding to the reset line to deassert
- * @st_shift: status bit offset, not used for OMAP4+
+ * @st_shift: status bit offset corresponding to the reset line
* @part: PRM partition
* @inst: PRM instance offset
* @rstctrl_offs: reset register offset
- * @st_offs: reset status register offset, not used for OMAP4+
+ * @rstst_offs: reset status register offset
*
* Some IPs like dsp, ipu or iva contain processors that require an HW
* reset line to be asserted / deasserted in order to fully enable the
* of reset, or -EBUSY if the submodule did not exit reset promptly.
*/
int omap4_prminst_deassert_hardreset(u8 shift, u8 st_shift, u8 part, s16 inst,
- u16 rstctrl_offs, u16 st_offs)
+ u16 rstctrl_offs, u16 rstst_offs)
{
int c;
u32 mask = 1 << shift;
- u16 rstst_offs = rstctrl_offs + OMAP4_RST_CTRL_ST_OFFSET;
+ u32 st_mask = 1 << st_shift;
/* Check the current status to avoid de-asserting the line twice */
if (omap4_prminst_is_hardreset_asserted(shift, part, inst,
return -EEXIST;
/* Clear the reset status by writing 1 to the status bit */
- omap4_prminst_rmw_inst_reg_bits(0xffffffff, mask, part, inst,
+ omap4_prminst_rmw_inst_reg_bits(0xffffffff, st_mask, part, inst,
rstst_offs);
/* de-assert the reset control line */
omap4_prminst_rmw_inst_reg_bits(mask, 0, part, inst, rstctrl_offs);
/* wait the status to be set */
- omap_test_timeout(omap4_prminst_is_hardreset_asserted(shift, part, inst,
- rstst_offs),
+ omap_test_timeout(omap4_prminst_is_hardreset_asserted(st_shift, part,
+ inst, rstst_offs),
MAX_MODULE_HARDRESET_WAIT, c);
return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
if (IS_ERR(src))
return PTR_ERR(src);
- if (clk_get_parent(timer->fclk) != src) {
- r = clk_set_parent(timer->fclk, src);
- if (r < 0) {
- pr_warn("%s: %s cannot set source\n", __func__,
- oh->name);
- clk_put(src);
- return r;
- }
+ r = clk_set_parent(timer->fclk, src);
+ if (r < 0) {
+ pr_warn("%s: %s cannot set source\n", __func__, oh->name);
+ clk_put(src);
+ return r;
}
clk_put(src);
* idle. And we can also scale voltages to zero for off-idle.
* Note that no actual voltage scaling during off-idle will
* happen unless the board specific twl4030 PMIC scripts are
- * loaded.
+ * loaded. See also omap_vc_i2c_init for comments regarding
+ * erratum i531.
*/
val = voltdm->read(OMAP3_PRM_VOLTCTRL_OFFSET);
if (!(val & OMAP3430_PRM_VOLTCTRL_SEL_OFF)) {
return;
}
+ /*
+ * Note that for omap3 OMAP3430_SREN_MASK clears SREN to work around
+ * erratum i531 "Extra Power Consumed When Repeated Start Operation
+ * Mode Is Enabled on I2C Interface Dedicated for Smart Reflex (I2C4)".
+ * Otherwise I2C4 eventually leads into about 23mW extra power being
+ * consumed even during off idle using VMODE.
+ */
i2c_high_speed = voltdm->pmic->i2c_high_speed;
if (i2c_high_speed)
- voltdm->rmw(vc->common->i2c_cfg_hsen_mask,
+ voltdm->rmw(vc->common->i2c_cfg_clear_mask,
vc->common->i2c_cfg_hsen_mask,
vc->common->i2c_cfg_reg);
* @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
* @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
* @i2c_cfg_reg: I2C configuration register offset
+ * @i2c_cfg_clear_mask: high-speed mode bit clear mask in I2C config register
* @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register
* @i2c_mcode_mask: MCODE field mask for I2C config register
*
u8 cmd_ret_shift;
u8 cmd_off_shift;
u8 i2c_cfg_reg;
+ u8 i2c_cfg_clear_mask;
u8 i2c_cfg_hsen_mask;
u8 i2c_mcode_mask;
};
.cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT,
.cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT,
.cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT,
+ .i2c_cfg_clear_mask = OMAP3430_SREN_MASK | OMAP3430_HSEN_MASK,
.i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK,
.i2c_cfg_reg = OMAP3_PRM_VC_I2C_CFG_OFFSET,
.i2c_mcode_mask = OMAP3430_MCODE_MASK,
.cmd_ret_shift = OMAP4430_RET_SHIFT,
.cmd_off_shift = OMAP4430_OFF_SHIFT,
.i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET,
+ .i2c_cfg_clear_mask = OMAP4430_SRMODEEN_MASK | OMAP4430_HSMODEEN_MASK,
.i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK,
.i2c_mcode_mask = OMAP4430_HSMCODE_MASK,
};
config PXA310_ULPI
bool
+config PXA_SYSTEMS_CPLDS
+ tristate "Motherboard cplds"
+ default ARCH_LUBBOCK || MACH_MAINSTONE
+ help
+ This driver supports the Lubbock and Mainstone multifunction chip
+ found on the pxa25x development platform system (Lubbock) and pxa27x
+ development platform system (Mainstone). This IO board supports the
+ interrupts handling, ethernet controller, flash chips, etc ...
+
endif
obj-$(CONFIG_MACH_RAUMFELD_SPEAKER) += raumfeld.o
obj-$(CONFIG_MACH_ZIPIT2) += z2.o
+obj-$(CONFIG_PXA_SYSTEMS_CPLDS) += pxa_cplds_irqs.o
obj-$(CONFIG_TOSA_BT) += tosa-bt.o
#define LUB_GP __LUB_REG(LUBBOCK_FPGA_PHYS + 0x100)
/* Board specific IRQs */
-#define LUBBOCK_IRQ(x) (IRQ_BOARD_START + (x))
+#define LUBBOCK_NR_IRQS IRQ_BOARD_START
+
+#define LUBBOCK_IRQ(x) (LUBBOCK_NR_IRQS + (x))
#define LUBBOCK_SD_IRQ LUBBOCK_IRQ(0)
#define LUBBOCK_SA1111_IRQ LUBBOCK_IRQ(1)
#define LUBBOCK_USB_IRQ LUBBOCK_IRQ(2) /* usb connect */
#define LUBBOCK_USB_DISC_IRQ LUBBOCK_IRQ(6) /* usb disconnect */
#define LUBBOCK_LAST_IRQ LUBBOCK_IRQ(6)
-#define LUBBOCK_SA1111_IRQ_BASE (IRQ_BOARD_START + 16)
-#define LUBBOCK_NR_IRQS (IRQ_BOARD_START + 16 + 55)
+#define LUBBOCK_SA1111_IRQ_BASE (LUBBOCK_NR_IRQS + 32)
#ifndef __ASSEMBLY__
extern void lubbock_set_misc_wr(unsigned int mask, unsigned int set);
#define MST_PCMCIA_PWR_VCC_50 0x4 /* voltage VCC = 5.0V */
/* board specific IRQs */
-#define MAINSTONE_IRQ(x) (IRQ_BOARD_START + (x))
+#define MAINSTONE_NR_IRQS IRQ_BOARD_START
+
+#define MAINSTONE_IRQ(x) (MAINSTONE_NR_IRQS + (x))
#define MAINSTONE_MMC_IRQ MAINSTONE_IRQ(0)
#define MAINSTONE_USIM_IRQ MAINSTONE_IRQ(1)
#define MAINSTONE_USBC_IRQ MAINSTONE_IRQ(2)
#define MAINSTONE_S1_STSCHG_IRQ MAINSTONE_IRQ(14)
#define MAINSTONE_S1_IRQ MAINSTONE_IRQ(15)
-#define MAINSTONE_NR_IRQS (IRQ_BOARD_START + 16)
-
#endif
* published by the Free Software Foundation.
*/
#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
}
EXPORT_SYMBOL(lubbock_set_misc_wr);
-static unsigned long lubbock_irq_enabled;
-
-static void lubbock_mask_irq(struct irq_data *d)
-{
- int lubbock_irq = (d->irq - LUBBOCK_IRQ(0));
- LUB_IRQ_MASK_EN = (lubbock_irq_enabled &= ~(1 << lubbock_irq));
-}
-
-static void lubbock_unmask_irq(struct irq_data *d)
-{
- int lubbock_irq = (d->irq - LUBBOCK_IRQ(0));
- /* the irq can be acknowledged only if deasserted, so it's done here */
- LUB_IRQ_SET_CLR &= ~(1 << lubbock_irq);
- LUB_IRQ_MASK_EN = (lubbock_irq_enabled |= (1 << lubbock_irq));
-}
-
-static struct irq_chip lubbock_irq_chip = {
- .name = "FPGA",
- .irq_ack = lubbock_mask_irq,
- .irq_mask = lubbock_mask_irq,
- .irq_unmask = lubbock_unmask_irq,
-};
-
-static void lubbock_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- unsigned long pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
- do {
- /* clear our parent irq */
- desc->irq_data.chip->irq_ack(&desc->irq_data);
- if (likely(pending)) {
- irq = LUBBOCK_IRQ(0) + __ffs(pending);
- generic_handle_irq(irq);
- }
- pending = LUB_IRQ_SET_CLR & lubbock_irq_enabled;
- } while (pending);
-}
-
-static void __init lubbock_init_irq(void)
-{
- int irq;
-
- pxa25x_init_irq();
-
- /* setup extra lubbock irqs */
- for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
- irq_set_chip_and_handler(irq, &lubbock_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- }
-
- irq_set_chained_handler(PXA_GPIO_TO_IRQ(0), lubbock_irq_handler);
- irq_set_irq_type(PXA_GPIO_TO_IRQ(0), IRQ_TYPE_EDGE_FALLING);
-}
-
-#ifdef CONFIG_PM
-
-static void lubbock_irq_resume(void)
-{
- LUB_IRQ_MASK_EN = lubbock_irq_enabled;
-}
-
-static struct syscore_ops lubbock_irq_syscore_ops = {
- .resume = lubbock_irq_resume,
-};
-
-static int __init lubbock_irq_device_init(void)
-{
- if (machine_is_lubbock()) {
- register_syscore_ops(&lubbock_irq_syscore_ops);
- return 0;
- }
- return -ENODEV;
-}
-
-device_initcall(lubbock_irq_device_init);
-
-#endif
-
static int lubbock_udc_is_connected(void)
{
return (LUB_MISC_RD & (1 << 9)) == 0;
},
};
+static struct resource lubbock_cplds_resources[] = {
+ [0] = {
+ .start = LUBBOCK_FPGA_PHYS + 0xc0,
+ .end = LUBBOCK_FPGA_PHYS + 0xe0 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PXA_GPIO_TO_IRQ(0),
+ .end = PXA_GPIO_TO_IRQ(0),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
+ },
+ [2] = {
+ .start = LUBBOCK_IRQ(0),
+ .end = LUBBOCK_IRQ(6),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device lubbock_cplds_device = {
+ .name = "pxa_cplds_irqs",
+ .id = -1,
+ .resource = &lubbock_cplds_resources[0],
+ .num_resources = 3,
+};
+
+
static struct platform_device *devices[] __initdata = {
&sa1111_device,
&smc91x_device,
&lubbock_flash_device[0],
&lubbock_flash_device[1],
+ &lubbock_cplds_device,
};
static struct pxafb_mode_info sharp_lm8v31_mode = {
/* Maintainer: MontaVista Software Inc. */
.map_io = lubbock_map_io,
.nr_irqs = LUBBOCK_NR_IRQS,
- .init_irq = lubbock_init_irq,
+ .init_irq = pxa25x_init_irq,
.handle_irq = pxa25x_handle_irq,
.init_time = pxa_timer_init,
.init_machine = lubbock_init,
* published by the Free Software Foundation.
*/
#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/syscore_ops.h>
GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
};
-static unsigned long mainstone_irq_enabled;
-
-static void mainstone_mask_irq(struct irq_data *d)
-{
- int mainstone_irq = (d->irq - MAINSTONE_IRQ(0));
- MST_INTMSKENA = (mainstone_irq_enabled &= ~(1 << mainstone_irq));
-}
-
-static void mainstone_unmask_irq(struct irq_data *d)
-{
- int mainstone_irq = (d->irq - MAINSTONE_IRQ(0));
- /* the irq can be acknowledged only if deasserted, so it's done here */
- MST_INTSETCLR &= ~(1 << mainstone_irq);
- MST_INTMSKENA = (mainstone_irq_enabled |= (1 << mainstone_irq));
-}
-
-static struct irq_chip mainstone_irq_chip = {
- .name = "FPGA",
- .irq_ack = mainstone_mask_irq,
- .irq_mask = mainstone_mask_irq,
- .irq_unmask = mainstone_unmask_irq,
-};
-
-static void mainstone_irq_handler(unsigned int irq, struct irq_desc *desc)
-{
- unsigned long pending = MST_INTSETCLR & mainstone_irq_enabled;
- do {
- /* clear useless edge notification */
- desc->irq_data.chip->irq_ack(&desc->irq_data);
- if (likely(pending)) {
- irq = MAINSTONE_IRQ(0) + __ffs(pending);
- generic_handle_irq(irq);
- }
- pending = MST_INTSETCLR & mainstone_irq_enabled;
- } while (pending);
-}
-
-static void __init mainstone_init_irq(void)
-{
- int irq;
-
- pxa27x_init_irq();
-
- /* setup extra Mainstone irqs */
- for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
- irq_set_chip_and_handler(irq, &mainstone_irq_chip,
- handle_level_irq);
- if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14))
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN);
- else
- set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
- }
- set_irq_flags(MAINSTONE_IRQ(8), 0);
- set_irq_flags(MAINSTONE_IRQ(12), 0);
-
- MST_INTMSKENA = 0;
- MST_INTSETCLR = 0;
-
- irq_set_chained_handler(PXA_GPIO_TO_IRQ(0), mainstone_irq_handler);
- irq_set_irq_type(PXA_GPIO_TO_IRQ(0), IRQ_TYPE_EDGE_FALLING);
-}
-
-#ifdef CONFIG_PM
-
-static void mainstone_irq_resume(void)
-{
- MST_INTMSKENA = mainstone_irq_enabled;
-}
-
-static struct syscore_ops mainstone_irq_syscore_ops = {
- .resume = mainstone_irq_resume,
-};
-
-static int __init mainstone_irq_device_init(void)
-{
- if (machine_is_mainstone())
- register_syscore_ops(&mainstone_irq_syscore_ops);
-
- return 0;
-}
-
-device_initcall(mainstone_irq_device_init);
-
-#endif
-
-
static struct resource smc91x_resources[] = {
[0] = {
.start = (MST_ETH_PHYS + 0x300),
},
};
+static struct resource mst_cplds_resources[] = {
+ [0] = {
+ .start = MST_FPGA_PHYS + 0xc0,
+ .end = MST_FPGA_PHYS + 0xe0 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = PXA_GPIO_TO_IRQ(0),
+ .end = PXA_GPIO_TO_IRQ(0),
+ .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
+ },
+ [2] = {
+ .start = MAINSTONE_IRQ(0),
+ .end = MAINSTONE_IRQ(15),
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device mst_cplds_device = {
+ .name = "pxa_cplds_irqs",
+ .id = -1,
+ .resource = &mst_cplds_resources[0],
+ .num_resources = 3,
+};
+
static struct platform_device *platform_devices[] __initdata = {
&smc91x_device,
&mst_flash_device[0],
&mst_flash_device[1],
&mst_gpio_keys_device,
+ &mst_cplds_device,
};
static struct pxaohci_platform_data mainstone_ohci_platform_data = {
.atag_offset = 0x100, /* BLOB boot parameter setting */
.map_io = mainstone_map_io,
.nr_irqs = MAINSTONE_NR_IRQS,
- .init_irq = mainstone_init_irq,
+ .init_irq = pxa27x_init_irq,
.handle_irq = pxa27x_handle_irq,
.init_time = pxa_timer_init,
.init_machine = mainstone_init,
--- /dev/null
+/*
+ * Intel Reference Systems cplds
+ *
+ * Copyright (C) 2014 Robert Jarzmik
+ *
+ * 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.
+ *
+ * Cplds motherboard driver, supporting lubbock and mainstone SoC board.
+ */
+
+#include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/mfd/core.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+
+#define FPGA_IRQ_MASK_EN 0x0
+#define FPGA_IRQ_SET_CLR 0x10
+
+#define CPLDS_NB_IRQ 32
+
+struct cplds {
+ void __iomem *base;
+ int irq;
+ unsigned int irq_mask;
+ struct gpio_desc *gpio0;
+ struct irq_domain *irqdomain;
+};
+
+static irqreturn_t cplds_irq_handler(int in_irq, void *d)
+{
+ struct cplds *fpga = d;
+ unsigned long pending;
+ unsigned int bit;
+
+ pending = readl(fpga->base + FPGA_IRQ_SET_CLR) & fpga->irq_mask;
+ for_each_set_bit(bit, &pending, CPLDS_NB_IRQ)
+ generic_handle_irq(irq_find_mapping(fpga->irqdomain, bit));
+
+ return IRQ_HANDLED;
+}
+
+static void cplds_irq_mask_ack(struct irq_data *d)
+{
+ struct cplds *fpga = irq_data_get_irq_chip_data(d);
+ unsigned int cplds_irq = irqd_to_hwirq(d);
+ unsigned int set, bit = BIT(cplds_irq);
+
+ fpga->irq_mask &= ~bit;
+ writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN);
+ set = readl(fpga->base + FPGA_IRQ_SET_CLR);
+ writel(set & ~bit, fpga->base + FPGA_IRQ_SET_CLR);
+}
+
+static void cplds_irq_unmask(struct irq_data *d)
+{
+ struct cplds *fpga = irq_data_get_irq_chip_data(d);
+ unsigned int cplds_irq = irqd_to_hwirq(d);
+ unsigned int bit = BIT(cplds_irq);
+
+ fpga->irq_mask |= bit;
+ writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN);
+}
+
+static struct irq_chip cplds_irq_chip = {
+ .name = "pxa_cplds",
+ .irq_mask_ack = cplds_irq_mask_ack,
+ .irq_unmask = cplds_irq_unmask,
+ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+};
+
+static int cplds_irq_domain_map(struct irq_domain *d, unsigned int irq,
+ irq_hw_number_t hwirq)
+{
+ struct cplds *fpga = d->host_data;
+
+ irq_set_chip_and_handler(irq, &cplds_irq_chip, handle_level_irq);
+ irq_set_chip_data(irq, fpga);
+
+ return 0;
+}
+
+static const struct irq_domain_ops cplds_irq_domain_ops = {
+ .xlate = irq_domain_xlate_twocell,
+ .map = cplds_irq_domain_map,
+};
+
+static int cplds_resume(struct platform_device *pdev)
+{
+ struct cplds *fpga = platform_get_drvdata(pdev);
+
+ writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN);
+
+ return 0;
+}
+
+static int cplds_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct cplds *fpga;
+ int ret;
+ unsigned int base_irq = 0;
+ unsigned long irqflags = 0;
+
+ fpga = devm_kzalloc(&pdev->dev, sizeof(*fpga), GFP_KERNEL);
+ if (!fpga)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (res) {
+ fpga->irq = (unsigned int)res->start;
+ irqflags = res->flags;
+ }
+ if (!fpga->irq)
+ return -ENODEV;
+
+ base_irq = platform_get_irq(pdev, 1);
+ if (base_irq < 0)
+ base_irq = 0;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ fpga->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(fpga->base))
+ return PTR_ERR(fpga->base);
+
+ platform_set_drvdata(pdev, fpga);
+
+ writel(fpga->irq_mask, fpga->base + FPGA_IRQ_MASK_EN);
+ writel(0, fpga->base + FPGA_IRQ_SET_CLR);
+
+ ret = devm_request_irq(&pdev->dev, fpga->irq, cplds_irq_handler,
+ irqflags, dev_name(&pdev->dev), fpga);
+ if (ret == -ENOSYS)
+ return -EPROBE_DEFER;
+
+ if (ret) {
+ dev_err(&pdev->dev, "couldn't request main irq%d: %d\n",
+ fpga->irq, ret);
+ return ret;
+ }
+
+ irq_set_irq_wake(fpga->irq, 1);
+ fpga->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
+ CPLDS_NB_IRQ,
+ &cplds_irq_domain_ops, fpga);
+ if (!fpga->irqdomain)
+ return -ENODEV;
+
+ if (base_irq) {
+ ret = irq_create_strict_mappings(fpga->irqdomain, base_irq, 0,
+ CPLDS_NB_IRQ);
+ if (ret) {
+ dev_err(&pdev->dev, "couldn't create the irq mapping %d..%d\n",
+ base_irq, base_irq + CPLDS_NB_IRQ);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int cplds_remove(struct platform_device *pdev)
+{
+ struct cplds *fpga = platform_get_drvdata(pdev);
+
+ irq_set_chip_and_handler(fpga->irq, NULL, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id cplds_id_table[] = {
+ { .compatible = "intel,lubbock-cplds-irqs", },
+ { .compatible = "intel,mainstone-cplds-irqs", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, cplds_id_table);
+
+static struct platform_driver cplds_driver = {
+ .driver = {
+ .name = "pxa_cplds_irqs",
+ .of_match_table = of_match_ptr(cplds_id_table),
+ },
+ .probe = cplds_probe,
+ .remove = cplds_remove,
+ .resume = cplds_resume,
+};
+
+module_platform_driver(cplds_driver);
+
+MODULE_DESCRIPTION("PXA Cplds interrupts driver");
+MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik@free.fr>");
+MODULE_LICENSE("GPL");
SGRF_PCLK_WDT_GATE | SGRF_FAST_BOOT_EN
| SGRF_PCLK_WDT_GATE_WRITE | SGRF_FAST_BOOT_EN_WRITE);
+ /*
+ * The dapswjdp can not auto reset before resume, that cause it may
+ * access some illegal address during resume. Let's disable it before
+ * suspend, and the MASKROM will enable it back.
+ */
+ regmap_write(sgrf_regmap, RK3288_SGRF_CPU_CON0, SGRF_DAPDEVICEEN_WRITE);
+
/* booting address of resuming system is from this register value */
regmap_write(sgrf_regmap, RK3288_SGRF_FAST_BOOT_ADDR,
rk3288_bootram_phy);
#define SGRF_FAST_BOOT_EN BIT(8)
#define SGRF_FAST_BOOT_EN_WRITE BIT(24)
+#define RK3288_SGRF_CPU_CON0 (0x40)
+#define SGRF_DAPDEVICEEN BIT(0)
+#define SGRF_DAPDEVICEEN_WRITE BIT(16)
+
#define RK3288_CRU_MODE_CON 0x50
#define RK3288_CRU_SEL0_CON 0x60
#define RK3288_CRU_SEL1_CON 0x64
#include "pm.h"
#define RK3288_GRF_SOC_CON0 0x244
+#define RK3288_TIMER6_7_PHYS 0xff810000
static void __init rockchip_timer_init(void)
{
if (of_machine_is_compatible("rockchip,rk3288")) {
struct regmap *grf;
+ void __iomem *reg_base;
+
+ /*
+ * Most/all uboot versions for rk3288 don't enable timer7
+ * which is needed for the architected timer to work.
+ * So make sure it is running during early boot.
+ */
+ reg_base = ioremap(RK3288_TIMER6_7_PHYS, SZ_16K);
+ if (reg_base) {
+ writel(0, reg_base + 0x30);
+ writel(0xffffffff, reg_base + 0x20);
+ writel(0xffffffff, reg_base + 0x24);
+ writel(1, reg_base + 0x30);
+ dsb();
+ iounmap(reg_base);
+ } else {
+ pr_err("rockchip: could not map timer7 registers\n");
+ }
/*
* Disable auto jtag/sdmmc switching that causes issues
* arm_iommu_attach_device function.
*/
struct dma_iommu_mapping *
-arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size)
+arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, u64 size)
{
unsigned int bits = size >> PAGE_SHIFT;
unsigned int bitmap_size = BITS_TO_LONGS(bits) * sizeof(long);
int extensions = 1;
int err = -ENOMEM;
+ /* currently only 32-bit DMA address space is supported */
+ if (size > DMA_BIT_MASK(32) + 1)
+ return ERR_PTR(-ERANGE);
+
if (!bitmap_size)
return ERR_PTR(-EINVAL);
if (!iommu)
return false;
- /*
- * currently arm_iommu_create_mapping() takes a max of size_t
- * for size param. So check this limit for now.
- */
- if (size > SIZE_MAX)
- return false;
-
mapping = arm_iommu_create_mapping(dev->bus, dma_base, size);
if (IS_ERR(mapping)) {
pr_warn("Failed to create %llu-byte IOMMU mapping for device %s\n",
*
* These are the low level assembler for performing cache and TLB
* functions on the arm1020.
- *
- * CONFIG_CPU_ARM1020_CPU_IDLE -> nohlt
*/
#include <linux/linkage.h>
#include <linux/init.h>
*
* These are the low level assembler for performing cache and TLB
* functions on the arm1020e.
- *
- * CONFIG_CPU_ARM1020_CPU_IDLE -> nohlt
*/
#include <linux/linkage.h>
#include <linux/init.h>
.type __arm925_setup, #function
__arm925_setup:
mov r0, #0
-#if defined(CONFIG_CPU_ICACHE_STREAMING_DISABLE)
- orr r0,r0,#1 << 7
-#endif
/* Transparent on, D-cache clean & flush mode. See NOTE2 above */
orr r0,r0,#1 << 1 @ transparent mode on
PMD_SECT_AP_WRITE | \
PMD_SECT_AP_READ
initfn __feroceon_setup, __\name\()_proc_info
- .long __feroceon_setup
.long cpu_arch_name
.long cpu_elf_name
.long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
#define SEEN_DATA (1 << (BPF_MEMWORDS + 3))
#define FLAG_NEED_X_RESET (1 << 0)
+#define FLAG_IMM_OVERFLOW (1 << 1)
struct jit_ctx {
const struct bpf_prog *skf;
/* PC in ARM mode == address of the instruction + 8 */
imm = offset - (8 + ctx->idx * 4);
+ if (imm & ~0xfff) {
+ /*
+ * literal pool is too far, signal it into flags. we
+ * can only detect it on the second pass unfortunately.
+ */
+ ctx->flags |= FLAG_IMM_OVERFLOW;
+ return 0;
+ }
+
return imm;
}
return;
}
#endif
- if (rm != ARM_R0)
- emit(ARM_MOV_R(ARM_R0, rm), ctx);
+
+ /*
+ * For BPF_ALU | BPF_DIV | BPF_K instructions, rm is ARM_R4
+ * (r_A) and rn is ARM_R0 (r_scratch) so load rn first into
+ * ARM_R1 to avoid accidentally overwriting ARM_R0 with rm
+ * before using it as a source for ARM_R1.
+ *
+ * For BPF_ALU | BPF_DIV | BPF_X rm is ARM_R4 (r_A) and rn is
+ * ARM_R5 (r_X) so there is no particular register overlap
+ * issues.
+ */
if (rn != ARM_R1)
emit(ARM_MOV_R(ARM_R1, rn), ctx);
+ if (rm != ARM_R0)
+ emit(ARM_MOV_R(ARM_R0, rm), ctx);
ctx->seen |= SEEN_CALL;
emit_mov_i(ARM_R3, (u32)jit_udiv, ctx);
default:
return -1;
}
+
+ if (ctx->flags & FLAG_IMM_OVERFLOW)
+ /*
+ * this instruction generated an overflow when
+ * trying to access the literal pool, so
+ * delegate this filter to the kernel interpreter.
+ */
+ return -1;
}
/* compute offsets only during the first pass */
ctx.idx = 0;
build_prologue(&ctx);
- build_body(&ctx);
+ if (build_body(&ctx) < 0) {
+#if __LINUX_ARM_ARCH__ < 7
+ if (ctx.imm_count)
+ kfree(ctx.imms);
+#endif
+ bpf_jit_binary_free(header);
+ goto out;
+ }
build_epilogue(&ctx);
flush_icache_range((u32)ctx.target, (u32)(ctx.target + ctx.idx));
#include <linux/gfp.h>
#include <linux/highmem.h>
#include <linux/export.h>
+#include <linux/memblock.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <asm/xen/hypercall.h>
#include <asm/xen/interface.h>
+unsigned long xen_get_swiotlb_free_pages(unsigned int order)
+{
+ struct memblock_region *reg;
+ gfp_t flags = __GFP_NOWARN;
+
+ for_each_memblock(memory, reg) {
+ if (reg->base < (phys_addr_t)0xffffffff) {
+ flags |= __GFP_DMA;
+ break;
+ }
+ }
+ return __get_free_pages(flags, order);
+}
+
enum dma_cache_op {
DMA_UNMAP,
DMA_MAP,
clock-output-names = "juno_mb:clk25mhz";
};
+ v2m_refclk1mhz: refclk1mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000>;
+ clock-output-names = "juno_mb:refclk1mhz";
+ };
+
+ v2m_refclk32khz: refclk32khz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "juno_mb:refclk32khz";
+ };
+
motherboard {
compatible = "arm,vexpress,v2p-p1", "simple-bus";
#address-cells = <2>; /* SMB chipselect number and offset */
#size-cells = <1>;
ranges = <0 3 0 0x200000>;
+ v2m_sysctl: sysctl@020000 {
+ compatible = "arm,sp810", "arm,primecell";
+ reg = <0x020000 0x1000>;
+ clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&mb_clk24mhz>;
+ clock-names = "refclk", "timclk", "apb_pclk";
+ #clock-cells = <1>;
+ clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+ };
+
mmci@050000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x050000 0x1000>;
compatible = "arm,sp804", "arm,primecell";
reg = <0x110000 0x10000>;
interrupts = <9>;
- clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
- clock-names = "timclken1", "apb_pclk";
+ clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&mb_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
};
v2m_timer23: timer@120000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x120000 0x10000>;
interrupts = <9>;
- clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
- clock-names = "timclken1", "apb_pclk";
+ clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&mb_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
};
rtc@170000 {
{
struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
+ put_unaligned_le32(ctx->crc, out);
+ return 0;
+}
+
+static int chksumc_final(struct shash_desc *desc, u8 *out)
+{
+ struct chksum_desc_ctx *ctx = shash_desc_ctx(desc);
+
put_unaligned_le32(~ctx->crc, out);
return 0;
}
static int __chksum_finup(u32 crc, const u8 *data, unsigned int len, u8 *out)
{
- put_unaligned_le32(~crc32_arm64_le_hw(crc, data, len), out);
+ put_unaligned_le32(crc32_arm64_le_hw(crc, data, len), out);
return 0;
}
{
struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
+ mctx->key = 0;
+ return 0;
+}
+
+static int crc32c_cra_init(struct crypto_tfm *tfm)
+{
+ struct chksum_ctx *mctx = crypto_tfm_ctx(tfm);
+
mctx->key = ~0;
return 0;
}
.setkey = chksum_setkey,
.init = chksum_init,
.update = chksumc_update,
- .final = chksum_final,
+ .final = chksumc_final,
.finup = chksumc_finup,
.digest = chksumc_digest,
.descsize = sizeof(struct chksum_desc_ctx),
.cra_alignmask = 0,
.cra_ctxsize = sizeof(struct chksum_ctx),
.cra_module = THIS_MODULE,
- .cra_init = crc32_cra_init,
+ .cra_init = crc32c_cra_init,
}
};
static int sha1_ce_final(struct shash_desc *desc, u8 *out)
{
+ struct sha1_ce_state *sctx = shash_desc_ctx(desc);
+
+ sctx->finalize = 0;
kernel_neon_begin_partial(16);
sha1_base_do_finalize(desc, (sha1_block_fn *)sha1_ce_transform);
kernel_neon_end();
static int sha256_ce_final(struct shash_desc *desc, u8 *out)
{
+ struct sha256_ce_state *sctx = shash_desc_ctx(desc);
+
+ sctx->finalize = 0;
kernel_neon_begin_partial(28);
sha256_base_do_finalize(desc, (sha256_block_fn *)sha2_ce_transform);
kernel_neon_end();
#include <asm/cacheflush.h>
#include <asm/alternative.h>
#include <asm/cpufeature.h>
-#include <asm/insn.h>
#include <linux/stop_machine.h>
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
struct alt_instr *end;
};
-/*
- * Decode the imm field of a b/bl instruction, and return the byte
- * offset as a signed value (so it can be used when computing a new
- * branch target).
- */
-static s32 get_branch_offset(u32 insn)
-{
- s32 imm = aarch64_insn_decode_immediate(AARCH64_INSN_IMM_26, insn);
-
- /* sign-extend the immediate before turning it into a byte offset */
- return (imm << 6) >> 4;
-}
-
-static u32 get_alt_insn(u8 *insnptr, u8 *altinsnptr)
-{
- u32 insn;
-
- aarch64_insn_read(altinsnptr, &insn);
-
- /* Stop the world on instructions we don't support... */
- BUG_ON(aarch64_insn_is_cbz(insn));
- BUG_ON(aarch64_insn_is_cbnz(insn));
- BUG_ON(aarch64_insn_is_bcond(insn));
- /* ... and there is probably more. */
-
- if (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn)) {
- enum aarch64_insn_branch_type type;
- unsigned long target;
-
- if (aarch64_insn_is_b(insn))
- type = AARCH64_INSN_BRANCH_NOLINK;
- else
- type = AARCH64_INSN_BRANCH_LINK;
-
- target = (unsigned long)altinsnptr + get_branch_offset(insn);
- insn = aarch64_insn_gen_branch_imm((unsigned long)insnptr,
- target, type);
- }
-
- return insn;
-}
-
static int __apply_alternatives(void *alt_region)
{
struct alt_instr *alt;
u8 *origptr, *replptr;
for (alt = region->begin; alt < region->end; alt++) {
- u32 insn;
- int i;
-
if (!cpus_have_cap(alt->cpufeature))
continue;
origptr = (u8 *)&alt->orig_offset + alt->orig_offset;
replptr = (u8 *)&alt->alt_offset + alt->alt_offset;
-
- for (i = 0; i < alt->alt_len; i += sizeof(insn)) {
- insn = get_alt_insn(origptr + i, replptr + i);
- aarch64_insn_write(origptr + i, insn);
- }
-
+ memcpy(origptr, replptr, alt->alt_len);
flush_icache_range((uintptr_t)origptr,
(uintptr_t)(origptr + alt->alt_len));
}
if (!cpu_pmu)
return -ENODEV;
- irqs = kcalloc(pdev->num_resources, sizeof(*irqs), GFP_KERNEL);
- if (!irqs)
- return -ENOMEM;
-
/* Don't bother with PPIs; they're already affine */
irq = platform_get_irq(pdev, 0);
if (irq >= 0 && irq_is_percpu(irq))
return 0;
+ irqs = kcalloc(pdev->num_resources, sizeof(*irqs), GFP_KERNEL);
+ if (!irqs)
+ return -ENOMEM;
+
for (i = 0; i < pdev->num_resources; ++i) {
struct device_node *dn;
int cpu;
for (j = 0; j < pg_level[i].num; j++)
pg_level[i].mask |= pg_level[i].bits[j].mask;
+#ifdef CONFIG_SPARSEMEM_VMEMMAP
address_markers[VMEMMAP_START_NR].start_address =
(unsigned long)virt_to_page(PAGE_OFFSET);
address_markers[VMEMMAP_END_NR].start_address =
(unsigned long)virt_to_page(high_memory);
+#endif
pe = debugfs_create_file("kernel_page_tables", 0400, NULL, NULL,
&ptdump_fops);
return -EINVAL;
}
- imm64 = (u64)insn1.imm << 32 | imm;
+ imm64 = (u64)insn1.imm << 32 | (u32)imm;
emit_a64_mov_i64(dst, imm64, ctx);
return 1;
/*
* For flush_tlb_others()
*/
-static volatile cpumask_t flush_cpumask;
+static cpumask_t flush_cpumask;
static struct mm_struct *flush_mm;
static struct vm_area_struct *flush_vma;
static volatile unsigned long flush_va;
*/
send_IPI_mask(&cpumask, INVALIDATE_TLB_IPI, 0);
- while (!cpumask_empty((cpumask_t*)&flush_cpumask)) {
+ while (!cpumask_empty(&flush_cpumask)) {
/* nothing. lockup detection does not belong here */
mb();
}
__flush_tlb_page(va);
}
}
- cpumask_clear_cpu(cpu_id, (cpumask_t*)&flush_cpumask);
+ cpumask_clear_cpu(cpu_id, &flush_cpumask);
}
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
ifdef CONFIG_MIPS
CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
- sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/")
+ sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')
ifdef CONFIG_64BIT
CHECKFLAGS += -m64
endif
\
current->thread.abi = &mips_abi; \
\
- current->thread.fpu.fcr31 = current_cpu_data.fpu_csr31; \
+ current->thread.fpu.fcr31 = boot_cpu_data.fpu_csr31; \
} while (0)
#endif /* CONFIG_32BIT */
else \
current->thread.abi = &mips_abi; \
\
- current->thread.fpu.fcr31 = current_cpu_data.fpu_csr31; \
+ current->thread.fpu.fcr31 = boot_cpu_data.fpu_csr31; \
\
p = personality(current->personality); \
if (p != PER_LINUX32 && p != PER_LINUX) \
#define SMP_DUMP 0x8
#define SMP_ASK_C0COUNT 0x10
-extern volatile cpumask_t cpu_callin_map;
+extern cpumask_t cpu_callin_map;
/* Mask of CPUs which are currently definitely operating coherently */
extern cpumask_t cpu_coherent_mask;
/* Lets see if this is an O32 ELF */
if (ehdr32->e_ident[EI_CLASS] == ELFCLASS32) {
- /* FR = 1 for N32 */
- if (ehdr32->e_flags & EF_MIPS_ABI2)
- state->overall_fp_mode = FP_FR1;
- else
- /* Set a good default FPU mode for O32 */
- state->overall_fp_mode = cpu_has_mips_r6 ?
- FP_FRE : FP_FR0;
-
if (ehdr32->e_flags & EF_MIPS_FP64) {
/*
* Set MIPS_ABI_FP_OLD_64 for EF_MIPS_FP64. We will override it
(char *)&abiflags,
sizeof(abiflags));
} else {
- /* FR=1 is really the only option for 64-bit */
- state->overall_fp_mode = FP_FR1;
-
if (phdr64->p_type != PT_MIPS_ABIFLAGS)
return 0;
if (phdr64->p_filesz < sizeof(abiflags))
struct elf32_hdr *ehdr = _ehdr;
struct mode_req prog_req, interp_req;
int fp_abi, interp_fp_abi, abi0, abi1, max_abi;
+ bool is_mips64;
if (!config_enabled(CONFIG_MIPS_O32_FP64_SUPPORT))
return 0;
abi0 = abi1 = fp_abi;
}
- /* ABI limits. O32 = FP_64A, N32/N64 = FP_SOFT */
- max_abi = ((ehdr->e_ident[EI_CLASS] == ELFCLASS32) &&
- (!(ehdr->e_flags & EF_MIPS_ABI2))) ?
- MIPS_ABI_FP_64A : MIPS_ABI_FP_SOFT;
+ is_mips64 = (ehdr->e_ident[EI_CLASS] == ELFCLASS64) ||
+ (ehdr->e_flags & EF_MIPS_ABI2);
+
+ if (is_mips64) {
+ /* MIPS64 code always uses FR=1, thus the default is easy */
+ state->overall_fp_mode = FP_FR1;
+
+ /* Disallow access to the various FPXX & FP64 ABIs */
+ max_abi = MIPS_ABI_FP_SOFT;
+ } else {
+ /* Default to a mode capable of running code expecting FR=0 */
+ state->overall_fp_mode = cpu_has_mips_r6 ? FP_FRE : FP_FR0;
+
+ /* Allow all ABIs we know about */
+ max_abi = MIPS_ABI_FP_64A;
+ }
if ((abi0 > max_abi && abi0 != MIPS_ABI_FP_UNKNOWN) ||
(abi1 > max_abi && abi1 != MIPS_ABI_FP_UNKNOWN))
__get_user(value, data + 64);
fcr31 = child->thread.fpu.fcr31;
- mask = current_cpu_data.fpu_msk31;
+ mask = boot_cpu_data.fpu_msk31;
child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
/* FIR may not be written. */
#ifdef CONFIG_MIPS_MT_FPAFF
/* If we have an FPU, enroll ourselves in the FPU-full mask */
if (cpu_has_fpu)
- cpu_set(0, mt_fpu_cpumask);
+ cpumask_set_cpu(0, &mt_fpu_cpumask);
#endif /* CONFIG_MIPS_MT_FPAFF */
}
#include <asm/time.h>
#include <asm/setup.h>
-volatile cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
+cpumask_t cpu_callin_map; /* Bitmask of started secondaries */
int __cpu_number_map[NR_CPUS]; /* Map physical to logical */
EXPORT_SYMBOL(__cpu_number_map);
/*
* Trust is futile. We should really have timeouts ...
*/
- while (!cpumask_test_cpu(cpu, &cpu_callin_map))
+ while (!cpumask_test_cpu(cpu, &cpu_callin_map)) {
udelay(100);
+ schedule();
+ }
synchronise_count_master(cpu);
return 0;
*/
printk("epc : %0*lx %pS\n", field, regs->cp0_epc,
(void *) regs->cp0_epc);
- printk(" %s\n", print_tainted());
printk("ra : %0*lx %pS\n", field, regs->regs[31],
(void *) regs->regs[31]);
{
unsigned long *gpr = &vcpu->arch.gprs[vcpu->arch.io_gpr];
enum emulation_result er = EMULATE_DONE;
- unsigned long curr_pc;
if (run->mmio.len > sizeof(*gpr)) {
kvm_err("Bad MMIO length: %d", run->mmio.len);
goto done;
}
- /*
- * Update PC and hold onto current PC in case there is
- * an error and we want to rollback the PC
- */
- curr_pc = vcpu->arch.pc;
er = update_pc(vcpu, vcpu->arch.pending_load_cause);
if (er == EMULATE_FAIL)
return er;
break;
case FPCREG_RID:
- value = current_cpu_data.fpu_id;
+ value = boot_cpu_data.fpu_id;
break;
default:
(void *)xcp->cp0_epc, MIPSInst_RT(ir), value);
/* Preserve read-only bits. */
- mask = current_cpu_data.fpu_msk31;
+ mask = boot_cpu_data.fpu_msk31;
fcr31 = (value & ~mask) | (fcr31 & mask);
break;
if (cpu_has_rixi) {
/*
- * Enable the no read, no exec bits, and enable large virtual
+ * Enable the no read, no exec bits, and enable large physical
* address.
*/
#ifdef CONFIG_64BIT
.resource = ip32_rtc_resources,
};
-+static int __init sgio2_rtc_devinit(void)
+static __init int sgio2_rtc_devinit(void)
{
return platform_device_register(&ip32_rtc_device);
}
-device_initcall(sgio2_cmos_devinit);
+device_initcall(sgio2_rtc_devinit);
#define ELF_HWCAP 0
+#define STACK_RND_MASK (is_32bit_task() ? \
+ 0x7ff >> (PAGE_SHIFT - 12) : \
+ 0x3ffff >> (PAGE_SHIFT - 12))
+
struct mm_struct;
extern unsigned long arch_randomize_brk(struct mm_struct *);
#define arch_randomize_brk arch_randomize_brk
return 1;
}
+/*
+ * Copy architecture-specific thread state
+ */
int
copy_thread(unsigned long clone_flags, unsigned long usp,
- unsigned long arg, struct task_struct *p)
+ unsigned long kthread_arg, struct task_struct *p)
{
struct pt_regs *cregs = &(p->thread.regs);
void *stack = task_stack_page(p);
extern void * const child_return;
if (unlikely(p->flags & PF_KTHREAD)) {
+ /* kernel thread */
memset(cregs, 0, sizeof(struct pt_regs));
if (!usp) /* idle thread */
return 0;
-
- /* kernel thread */
/* Must exit via ret_from_kernel_thread in order
* to call schedule_tail()
*/
#else
cregs->gr[26] = usp;
#endif
- cregs->gr[25] = arg;
+ cregs->gr[25] = kthread_arg;
} else {
/* user thread */
/* usp must be word aligned. This also prevents users from
if (stack_base > STACK_SIZE_MAX)
stack_base = STACK_SIZE_MAX;
+ /* Add space for stack randomization. */
+ stack_base += (STACK_RND_MASK << PAGE_SHIFT);
+
return PAGE_ALIGN(STACK_TOP - stack_base);
}
if (!cmdline_ptr)
goto fail;
hdr->cmd_line_ptr = (unsigned long)cmdline_ptr;
+ /* Fill in upper bits of command line address, NOP on 32 bit */
+ boot_params->ext_cmd_line_ptr = (u64)(unsigned long)cmdline_ptr >> 32;
hdr->ramdisk_image = 0;
hdr->ramdisk_size = 0;
/* Recognized hypervisors */
extern const struct hypervisor_x86 x86_hyper_vmware;
extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
-extern const struct hypervisor_x86 x86_hyper_xen_hvm;
+extern const struct hypervisor_x86 x86_hyper_xen;
extern const struct hypervisor_x86 x86_hyper_kvm;
extern void init_hypervisor(struct cpuinfo_x86 *c);
struct __raw_tickets tmp = READ_ONCE(lock->tickets);
tmp.head &= ~TICKET_SLOWPATH_FLAG;
- return (tmp.tail - tmp.head) > TICKET_LOCK_INC;
+ return (__ticket_t)(tmp.tail - tmp.head) > TICKET_LOCK_INC;
}
#define arch_spin_is_contended arch_spin_is_contended
return false;
}
+static inline unsigned long xen_get_swiotlb_free_pages(unsigned int order)
+{
+ return __get_free_pages(__GFP_NOWARN, order);
+}
+
#endif /* _ASM_X86_XEN_PAGE_H */
static const __initconst struct hypervisor_x86 * const hypervisors[] =
{
-#ifdef CONFIG_XEN_PVHVM
- &x86_hyper_xen_hvm,
+#ifdef CONFIG_XEN
+ &x86_hyper_xen,
#endif
&x86_hyper_vmware,
&x86_hyper_ms_hyperv,
[ C(LL ) ] = {
[ C(OP_READ) ] = {
[ C(RESULT_ACCESS) ] = SLM_DMND_READ|SLM_LLC_ACCESS,
- [ C(RESULT_MISS) ] = SLM_DMND_READ|SLM_LLC_MISS,
+ [ C(RESULT_MISS) ] = 0,
},
[ C(OP_WRITE) ] = {
[ C(RESULT_ACCESS) ] = SLM_DMND_WRITE|SLM_LLC_ACCESS,
[ C(OP_READ) ] = {
/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
[ C(RESULT_ACCESS) ] = 0x01b7,
- /* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
- [ C(RESULT_MISS) ] = 0x01b7,
+ [ C(RESULT_MISS) ] = 0,
},
[ C(OP_WRITE) ] = {
/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
[ C(ITLB) ] = {
[ C(OP_READ) ] = {
[ C(RESULT_ACCESS) ] = 0x00c0, /* INST_RETIRED.ANY_P */
- [ C(RESULT_MISS) ] = 0x0282, /* ITLB.MISSES */
+ [ C(RESULT_MISS) ] = 0x40205, /* PAGE_WALKS.I_SIDE_WALKS */
},
[ C(OP_WRITE) ] = {
[ C(RESULT_ACCESS) ] = -1,
return x86_event_sysfs_show(page, config, event);
}
-static __initconst const struct x86_pmu core_pmu = {
- .name = "core",
- .handle_irq = x86_pmu_handle_irq,
- .disable_all = x86_pmu_disable_all,
- .enable_all = core_pmu_enable_all,
- .enable = core_pmu_enable_event,
- .disable = x86_pmu_disable_event,
- .hw_config = x86_pmu_hw_config,
- .schedule_events = x86_schedule_events,
- .eventsel = MSR_ARCH_PERFMON_EVENTSEL0,
- .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
- .event_map = intel_pmu_event_map,
- .max_events = ARRAY_SIZE(intel_perfmon_event_map),
- .apic = 1,
- /*
- * Intel PMCs cannot be accessed sanely above 32 bit width,
- * so we install an artificial 1<<31 period regardless of
- * the generic event period:
- */
- .max_period = (1ULL << 31) - 1,
- .get_event_constraints = intel_get_event_constraints,
- .put_event_constraints = intel_put_event_constraints,
- .event_constraints = intel_core_event_constraints,
- .guest_get_msrs = core_guest_get_msrs,
- .format_attrs = intel_arch_formats_attr,
- .events_sysfs_show = intel_event_sysfs_show,
-};
-
struct intel_shared_regs *allocate_shared_regs(int cpu)
{
struct intel_shared_regs *regs;
NULL,
};
+static __initconst const struct x86_pmu core_pmu = {
+ .name = "core",
+ .handle_irq = x86_pmu_handle_irq,
+ .disable_all = x86_pmu_disable_all,
+ .enable_all = core_pmu_enable_all,
+ .enable = core_pmu_enable_event,
+ .disable = x86_pmu_disable_event,
+ .hw_config = x86_pmu_hw_config,
+ .schedule_events = x86_schedule_events,
+ .eventsel = MSR_ARCH_PERFMON_EVENTSEL0,
+ .perfctr = MSR_ARCH_PERFMON_PERFCTR0,
+ .event_map = intel_pmu_event_map,
+ .max_events = ARRAY_SIZE(intel_perfmon_event_map),
+ .apic = 1,
+ /*
+ * Intel PMCs cannot be accessed sanely above 32-bit width,
+ * so we install an artificial 1<<31 period regardless of
+ * the generic event period:
+ */
+ .max_period = (1ULL<<31) - 1,
+ .get_event_constraints = intel_get_event_constraints,
+ .put_event_constraints = intel_put_event_constraints,
+ .event_constraints = intel_core_event_constraints,
+ .guest_get_msrs = core_guest_get_msrs,
+ .format_attrs = intel_arch_formats_attr,
+ .events_sysfs_show = intel_event_sysfs_show,
+
+ /*
+ * Virtual (or funny metal) CPU can define x86_pmu.extra_regs
+ * together with PMU version 1 and thus be using core_pmu with
+ * shared_regs. We need following callbacks here to allocate
+ * it properly.
+ */
+ .cpu_prepare = intel_pmu_cpu_prepare,
+ .cpu_starting = intel_pmu_cpu_starting,
+ .cpu_dying = intel_pmu_cpu_dying,
+};
+
static __initconst const struct x86_pmu intel_pmu = {
.name = "Intel",
.handle_irq = intel_pmu_handle_irq,
break;
case 60: /* Haswell */
case 69: /* Haswell-Celeron */
+ case 61: /* Broadwell */
rapl_cntr_mask = RAPL_IDX_HSW;
rapl_pmu_events_group.attrs = rapl_events_hsw_attr;
break;
/* Nehalem/SandBridge/Haswell uncore support */
#include "perf_event_intel_uncore.h"
+/* Uncore IMC PCI IDs */
+#define PCI_DEVICE_ID_INTEL_SNB_IMC 0x0100
+#define PCI_DEVICE_ID_INTEL_IVB_IMC 0x0154
+#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150
+#define PCI_DEVICE_ID_INTEL_HSW_IMC 0x0c00
+#define PCI_DEVICE_ID_INTEL_HSW_U_IMC 0x0a04
+
/* SNB event control */
#define SNB_UNC_CTL_EV_SEL_MASK 0x000000ff
#define SNB_UNC_CTL_UMASK_MASK 0x0000ff00
PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_IMC),
.driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
},
+ { /* IMC */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HSW_U_IMC),
+ .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+ },
{ /* end: all zeroes */ },
};
IMC_DEV(IVB_IMC, &ivb_uncore_pci_driver), /* 3rd Gen Core processor */
IMC_DEV(IVB_E3_IMC, &ivb_uncore_pci_driver), /* Xeon E3-1200 v2/3rd Gen Core processor */
IMC_DEV(HSW_IMC, &hsw_uncore_pci_driver), /* 4th Gen Core Processor */
+ IMC_DEV(HSW_U_IMC, &hsw_uncore_pci_driver), /* 4th Gen Core ULT Mobile Processor */
{ /* end marker */ }
};
.io_bitmap = { [0 ... IO_BITMAP_LONGS] = ~0 },
#endif
};
-EXPORT_PER_CPU_SYMBOL_GPL(cpu_tss);
+EXPORT_PER_CPU_SYMBOL(cpu_tss);
#ifdef CONFIG_X86_64
static DEFINE_PER_CPU(unsigned char, is_idle);
/* FPU state will be reallocated lazily at the first use. */
drop_fpu(tsk);
free_thread_xstate(tsk);
- } else if (!used_math()) {
- /* kthread execs. TODO: cleanup this horror. */
- if (WARN_ON(init_fpu(tsk)))
- force_sig(SIGKILL, tsk);
- user_fpu_begin();
+ } else {
+ if (!tsk_used_math(tsk)) {
+ /* kthread execs. TODO: cleanup this horror. */
+ if (WARN_ON(init_fpu(tsk)))
+ force_sig(SIGKILL, tsk);
+ user_fpu_begin();
+ }
restore_init_xstate();
}
}
*/
void *xlate_dev_mem_ptr(phys_addr_t phys)
{
- void *addr;
- unsigned long start = phys & PAGE_MASK;
+ unsigned long start = phys & PAGE_MASK;
+ unsigned long offset = phys & ~PAGE_MASK;
+ unsigned long vaddr;
/* If page is RAM, we can use __va. Otherwise ioremap and unmap. */
if (page_is_ram(start >> PAGE_SHIFT))
return __va(phys);
- addr = (void __force *)ioremap_cache(start, PAGE_SIZE);
- if (addr)
- addr = (void *)((unsigned long)addr | (phys & ~PAGE_MASK));
+ vaddr = (unsigned long)ioremap_cache(start, PAGE_SIZE);
+ /* Only add the offset on success and return NULL if the ioremap() failed: */
+ if (vaddr)
+ vaddr += offset;
- return addr;
+ return (void *)vaddr;
}
void unxlate_dev_mem_ptr(phys_addr_t phys, void *addr)
if (is_ereg(dst_reg))
EMIT1(0x41);
EMIT3(0xC1, add_1reg(0xC8, dst_reg), 8);
+
+ /* emit 'movzwl eax, ax' */
+ if (is_ereg(dst_reg))
+ EMIT3(0x45, 0x0F, 0xB7);
+ else
+ EMIT2(0x0F, 0xB7);
+ EMIT1(add_2reg(0xC0, dst_reg, dst_reg));
break;
case 32:
/* emit 'bswap eax' to swap lower 4 bytes */
break;
case BPF_ALU | BPF_END | BPF_FROM_LE:
+ switch (imm32) {
+ case 16:
+ /* emit 'movzwl eax, ax' to zero extend 16-bit
+ * into 64 bit
+ */
+ if (is_ereg(dst_reg))
+ EMIT3(0x45, 0x0F, 0xB7);
+ else
+ EMIT2(0x0F, 0xB7);
+ EMIT1(add_2reg(0xC0, dst_reg, dst_reg));
+ break;
+ case 32:
+ /* emit 'mov eax, eax' to clear upper 32-bits */
+ if (is_ereg(dst_reg))
+ EMIT1(0x45);
+ EMIT2(0x89, add_2reg(0xC0, dst_reg, dst_reg));
+ break;
+ case 64:
+ /* nop */
+ break;
+ }
break;
/* ST: *(u8*)(dst_reg + off) = imm */
kfree(info);
}
+/*
+ * An IO port or MMIO resource assigned to a PCI host bridge may be
+ * consumed by the host bridge itself or available to its child
+ * bus/devices. The ACPI specification defines a bit (Producer/Consumer)
+ * to tell whether the resource is consumed by the host bridge itself,
+ * but firmware hasn't used that bit consistently, so we can't rely on it.
+ *
+ * On x86 and IA64 platforms, all IO port and MMIO resources are assumed
+ * to be available to child bus/devices except one special case:
+ * IO port [0xCF8-0xCFF] is consumed by the host bridge itself
+ * to access PCI configuration space.
+ *
+ * So explicitly filter out PCI CFG IO ports[0xCF8-0xCFF].
+ */
+static bool resource_is_pcicfg_ioport(struct resource *res)
+{
+ return (res->flags & IORESOURCE_IO) &&
+ res->start == 0xCF8 && res->end == 0xCFF;
+}
+
static void probe_pci_root_info(struct pci_root_info *info,
struct acpi_device *device,
int busnum, int domain,
"no IO and memory resources present in _CRS\n");
else
resource_list_for_each_entry_safe(entry, tmp, list) {
- if ((entry->res->flags & IORESOURCE_WINDOW) == 0 ||
- (entry->res->flags & IORESOURCE_DISABLED))
+ if ((entry->res->flags & IORESOURCE_DISABLED) ||
+ resource_is_pcicfg_ioport(entry->res))
resource_list_destroy_entry(entry);
else
entry->res->name = info->name;
$(obj)/vdso64.so.dbg: $(src)/vdso.lds $(vobjs) FORCE
$(call if_changed,vdso)
-HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi
+HOST_EXTRACFLAGS += -I$(srctree)/tools/include -I$(srctree)/include/uapi -I$(srctree)/arch/x86/include/uapi
hostprogs-y += vdso2c
quiet_cmd_vdso2c = VDSO2C $@
static void __init xen_hvm_guest_init(void)
{
+ if (xen_pv_domain())
+ return;
+
init_hvm_pv_info();
xen_hvm_init_shared_info();
xen_hvm_init_time_ops();
xen_hvm_init_mmu_ops();
}
+#endif
static bool xen_nopv = false;
static __init int xen_parse_nopv(char *arg)
}
early_param("xen_nopv", xen_parse_nopv);
-static uint32_t __init xen_hvm_platform(void)
+static uint32_t __init xen_platform(void)
{
if (xen_nopv)
return 0;
- if (xen_pv_domain())
- return 0;
-
return xen_cpuid_base();
}
}
EXPORT_SYMBOL_GPL(xen_hvm_need_lapic);
-const struct hypervisor_x86 x86_hyper_xen_hvm __refconst = {
- .name = "Xen HVM",
- .detect = xen_hvm_platform,
+static void xen_set_cpu_features(struct cpuinfo_x86 *c)
+{
+ if (xen_pv_domain())
+ clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+}
+
+const struct hypervisor_x86 x86_hyper_xen = {
+ .name = "Xen",
+ .detect = xen_platform,
+#ifdef CONFIG_XEN_PVHVM
.init_platform = xen_hvm_guest_init,
+#endif
.x2apic_available = xen_x2apic_para_available,
+ .set_cpu_features = xen_set_cpu_features,
};
-EXPORT_SYMBOL(x86_hyper_xen_hvm);
-#endif
+EXPORT_SYMBOL(x86_hyper_xen);
tick_resume_local();
}
+static void xen_vcpu_notify_suspend(void *data)
+{
+ tick_suspend_local();
+}
+
void xen_arch_resume(void)
{
on_each_cpu(xen_vcpu_notify_restore, NULL, 1);
}
+
+void xen_arch_suspend(void)
+{
+ on_each_cpu(xen_vcpu_notify_suspend, NULL, 1);
+}
q->queue_lock = &q->__queue_lock;
spin_unlock_irq(lock);
+ bdi_destroy(&q->backing_dev_info);
+
/* @q is and will stay empty, shutdown and put */
blk_put_queue(q);
}
data.next = blk_rq_timeout(round_jiffies_up(data.next));
mod_timer(&q->timeout, data.next);
} else {
- queue_for_each_hw_ctx(q, hctx, i)
- blk_mq_tag_idle(hctx);
+ queue_for_each_hw_ctx(q, hctx, i) {
+ /* the hctx may be unmapped, so check it here */
+ if (blk_mq_hw_queue_mapped(hctx))
+ blk_mq_tag_idle(hctx);
+ }
}
}
spin_lock(&hctx->lock);
list_splice(&rq_list, &hctx->dispatch);
spin_unlock(&hctx->lock);
+ /*
+ * the queue is expected stopped with BLK_MQ_RQ_QUEUE_BUSY, but
+ * it's possible the queue is stopped and restarted again
+ * before this. Queue restart will dispatch requests. And since
+ * requests in rq_list aren't added into hctx->dispatch yet,
+ * the requests in rq_list might get lost.
+ *
+ * blk_mq_run_hw_queue() already checks the STOPPED bit
+ **/
+ blk_mq_run_hw_queue(hctx, true);
}
}
return NOTIFY_OK;
}
-static int blk_mq_hctx_cpu_online(struct blk_mq_hw_ctx *hctx, int cpu)
-{
- struct request_queue *q = hctx->queue;
- struct blk_mq_tag_set *set = q->tag_set;
-
- if (set->tags[hctx->queue_num])
- return NOTIFY_OK;
-
- set->tags[hctx->queue_num] = blk_mq_init_rq_map(set, hctx->queue_num);
- if (!set->tags[hctx->queue_num])
- return NOTIFY_STOP;
-
- hctx->tags = set->tags[hctx->queue_num];
- return NOTIFY_OK;
-}
-
static int blk_mq_hctx_notify(void *data, unsigned long action,
unsigned int cpu)
{
if (action == CPU_DEAD || action == CPU_DEAD_FROZEN)
return blk_mq_hctx_cpu_offline(hctx, cpu);
- else if (action == CPU_ONLINE || action == CPU_ONLINE_FROZEN)
- return blk_mq_hctx_cpu_online(hctx, cpu);
+
+ /*
+ * In case of CPU online, tags may be reallocated
+ * in blk_mq_map_swqueue() after mapping is updated.
+ */
return NOTIFY_OK;
}
unsigned int i;
struct blk_mq_hw_ctx *hctx;
struct blk_mq_ctx *ctx;
+ struct blk_mq_tag_set *set = q->tag_set;
queue_for_each_hw_ctx(q, hctx, i) {
cpumask_clear(hctx->cpumask);
* disable it and free the request entries.
*/
if (!hctx->nr_ctx) {
- struct blk_mq_tag_set *set = q->tag_set;
-
if (set->tags[i]) {
blk_mq_free_rq_map(set, set->tags[i], i);
set->tags[i] = NULL;
- hctx->tags = NULL;
}
+ hctx->tags = NULL;
continue;
}
+ /* unmapped hw queue can be remapped after CPU topo changed */
+ if (!set->tags[i])
+ set->tags[i] = blk_mq_init_rq_map(set, i);
+ hctx->tags = set->tags[i];
+ WARN_ON(!hctx->tags);
+
/*
* Set the map size to the number of mapped software queues.
* This is more accurate and more efficient than looping
*/
list_for_each_entry(q, &all_q_list, all_q_node)
blk_mq_freeze_queue_start(q);
- list_for_each_entry(q, &all_q_list, all_q_node)
+ list_for_each_entry(q, &all_q_list, all_q_node) {
blk_mq_freeze_queue_wait(q);
+ /*
+ * timeout handler can't touch hw queue during the
+ * reinitialization
+ */
+ del_timer_sync(&q->timeout);
+ }
+
list_for_each_entry(q, &all_q_list, all_q_node)
blk_mq_queue_reinit(q);
blk_trace_shutdown(q);
- bdi_destroy(&q->backing_dev_info);
-
ida_simple_remove(&blk_queue_ida, q->id);
call_rcu(&q->rcu_head, blk_free_queue_rcu);
}
if (page_to_pfn(page) <= queue_bounce_pfn(q) && !force)
continue;
- inc_zone_page_state(to->bv_page, NR_BOUNCE);
to->bv_page = mempool_alloc(pool, q->bounce_gfp);
+ inc_zone_page_state(to->bv_page, NR_BOUNCE);
if (rw == WRITE) {
char *vto, *vfrom;
eq = kzalloc_node(sizeof(*eq), GFP_KERNEL, q->node);
if (unlikely(!eq))
- goto err;
+ return NULL;
eq->type = e;
kobject_init(&eq->kobj, &elv_ktype);
hash_init(eq->hash);
return eq;
-err:
- kfree(eq);
- elevator_put(e);
- return NULL;
}
EXPORT_SYMBOL(elevator_alloc);
{"PNPb006"},
/* cs423x-pnpbios */
{"CSC0100"},
+ {"CSC0103"},
+ {"CSC0110"},
{"CSC0000"},
{"GIM0100"}, /* Guillemot Turtlebeach something appears to be cs4232 compatible */
/* es18xx-pnpbios */
{"_SB_", ACPI_TYPE_DEVICE, NULL},
{"_SI_", ACPI_TYPE_LOCAL_SCOPE, NULL},
{"_TZ_", ACPI_TYPE_DEVICE, NULL},
- /*
- * March, 2015:
- * The _REV object is in the process of being deprecated, because
- * other ACPI implementations permanently return 2. Thus, it
- * has little or no value. Return 2 for compatibility with
- * other ACPI implementations.
- */
- {"_REV", ACPI_TYPE_INTEGER, ACPI_CAST_PTR(char, 2)},
+ {"_REV", ACPI_TYPE_INTEGER, (char *)ACPI_CA_SUPPORT_LEVEL},
{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
- {"_GL_", ACPI_TYPE_MUTEX, ACPI_CAST_PTR(char, 1)},
+ {"_GL_", ACPI_TYPE_MUTEX, (char *)1},
#if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
- {"_OSI", ACPI_TYPE_METHOD, ACPI_CAST_PTR(char, 1)},
+ {"_OSI", ACPI_TYPE_METHOD, (char *)1},
#endif
/* Table terminator */
request_mem_region(addr, length, desc);
}
-static int __init acpi_reserve_resources(void)
+static void __init acpi_reserve_resources(void)
{
acpi_request_region(&acpi_gbl_FADT.xpm1a_event_block, acpi_gbl_FADT.pm1_event_length,
"ACPI PM1a_EVT_BLK");
if (!(acpi_gbl_FADT.gpe1_block_length & 0x1))
acpi_request_region(&acpi_gbl_FADT.xgpe1_block,
acpi_gbl_FADT.gpe1_block_length, "ACPI GPE1_BLK");
-
- return 0;
}
-device_initcall(acpi_reserve_resources);
void acpi_os_printf(const char *fmt, ...)
{
acpi_status __init acpi_os_initialize1(void)
{
+ acpi_reserve_resources();
kacpid_wq = alloc_workqueue("kacpid", 0, 1);
kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
kacpi_hotplug_wq = alloc_ordered_workqueue("kacpi_hotplug", 0);
* @ares: Input ACPI resource object.
* @types: Valid resource types of IORESOURCE_XXX
*
- * This is a hepler function to support acpi_dev_get_resources(), which filters
+ * This is a helper function to support acpi_dev_get_resources(), which filters
* ACPI resource objects according to resource types.
*/
int acpi_dev_filter_resource_type(struct acpi_resource *ares,
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/interrupt.h>
+#include <linux/dmi.h>
#include "sbshc.h"
#define PREFIX "ACPI: "
ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */
};
+static bool macbook;
+
static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data)
{
return ec_read(hc->offset + address, data);
}
mutex_lock(&hc->lock);
+ if (macbook)
+ udelay(5);
if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp))
goto end;
if (temp) {
acpi_handle handle, acpi_ec_query_func func,
void *data);
+static int macbook_dmi_match(const struct dmi_system_id *d)
+{
+ pr_debug("Detected MacBook, enabling workaround\n");
+ macbook = true;
+ return 0;
+}
+
+static struct dmi_system_id acpi_smbus_dmi_table[] = {
+ { macbook_dmi_match, "Apple MacBook", {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") },
+ },
+ { },
+};
+
static int acpi_smbus_hc_add(struct acpi_device *device)
{
int status;
unsigned long long val;
struct acpi_smb_hc *hc;
+ dmi_check_system(acpi_smbus_dmi_table);
+
if (!device)
return -EINVAL;
config SATA_DWC
tristate "DesignWare Cores SATA support"
depends on 460EX
+ select DW_DMAC
help
This option enables support for the on-chip SATA controller of the
AppliedMicro processor 460EX.
If unsure, say N.
-config PATA_SCC
- tristate "Toshiba's Cell Reference Set IDE support"
- depends on PCI && PPC_CELLEB
- help
- This option enables support for the built-in IDE controller on
- Toshiba Cell Reference Board.
-
- If unsure, say N.
-
config PATA_SCH
tristate "Intel SCH PATA support"
depends on PCI
obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o
obj-$(CONFIG_PATA_RDC) += pata_rdc.o
obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o
-obj-$(CONFIG_PATA_SCC) += pata_scc.o
obj-$(CONFIG_PATA_SCH) += pata_sch.o
obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o
obj-$(CONFIG_PATA_SIL680) += pata_sil680.o
board_ahci_yes_fbs,
/* board IDs for specific chipsets in alphabetical order */
+ board_ahci_avn,
board_ahci_mcp65,
board_ahci_mcp77,
board_ahci_mcp89,
static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
static int ahci_vt8251_hardreset(struct ata_link *link, unsigned int *class,
unsigned long deadline);
+static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline);
static void ahci_mcp89_apple_enable(struct pci_dev *pdev);
static bool is_mcp89_apple(struct pci_dev *pdev);
static int ahci_p5wdh_hardreset(struct ata_link *link, unsigned int *class,
.hardreset = ahci_p5wdh_hardreset,
};
+static struct ata_port_operations ahci_avn_ops = {
+ .inherits = &ahci_ops,
+ .hardreset = ahci_avn_hardreset,
+};
+
static const struct ata_port_info ahci_port_info[] = {
/* by features */
[board_ahci] = {
.port_ops = &ahci_ops,
},
/* by chipsets */
+ [board_ahci_avn] = {
+ .flags = AHCI_FLAG_COMMON,
+ .pio_mask = ATA_PIO4,
+ .udma_mask = ATA_UDMA6,
+ .port_ops = &ahci_avn_ops,
+ },
[board_ahci_mcp65] = {
AHCI_HFLAGS (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
AHCI_HFLAG_YES_NCQ),
{ PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */
- { PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */
- { PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */
- { PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */
- { PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */
- { PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */
- { PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
- { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
- { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
+ { PCI_VDEVICE(INTEL, 0x1f32), board_ahci_avn }, /* Avoton AHCI */
+ { PCI_VDEVICE(INTEL, 0x1f33), board_ahci_avn }, /* Avoton AHCI */
+ { PCI_VDEVICE(INTEL, 0x1f34), board_ahci_avn }, /* Avoton RAID */
+ { PCI_VDEVICE(INTEL, 0x1f35), board_ahci_avn }, /* Avoton RAID */
+ { PCI_VDEVICE(INTEL, 0x1f36), board_ahci_avn }, /* Avoton RAID */
+ { PCI_VDEVICE(INTEL, 0x1f37), board_ahci_avn }, /* Avoton RAID */
+ { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci_avn }, /* Avoton RAID */
+ { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci_avn }, /* Avoton RAID */
{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
{ PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
return rc;
}
+/*
+ * ahci_avn_hardreset - attempt more aggressive recovery of Avoton ports.
+ *
+ * It has been observed with some SSDs that the timing of events in the
+ * link synchronization phase can leave the port in a state that can not
+ * be recovered by a SATA-hard-reset alone. The failing signature is
+ * SStatus.DET stuck at 1 ("Device presence detected but Phy
+ * communication not established"). It was found that unloading and
+ * reloading the driver when this problem occurs allows the drive
+ * connection to be recovered (DET advanced to 0x3). The critical
+ * component of reloading the driver is that the port state machines are
+ * reset by bouncing "port enable" in the AHCI PCS configuration
+ * register. So, reproduce that effect by bouncing a port whenever we
+ * see DET==1 after a reset.
+ */
+static int ahci_avn_hardreset(struct ata_link *link, unsigned int *class,
+ unsigned long deadline)
+{
+ const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+ struct ata_port *ap = link->ap;
+ struct ahci_port_priv *pp = ap->private_data;
+ struct ahci_host_priv *hpriv = ap->host->private_data;
+ u8 *d2h_fis = pp->rx_fis + RX_FIS_D2H_REG;
+ unsigned long tmo = deadline - jiffies;
+ struct ata_taskfile tf;
+ bool online;
+ int rc, i;
+
+ DPRINTK("ENTER\n");
+
+ ahci_stop_engine(ap);
+
+ for (i = 0; i < 2; i++) {
+ u16 val;
+ u32 sstatus;
+ int port = ap->port_no;
+ struct ata_host *host = ap->host;
+ struct pci_dev *pdev = to_pci_dev(host->dev);
+
+ /* clear D2H reception area to properly wait for D2H FIS */
+ ata_tf_init(link->device, &tf);
+ tf.command = ATA_BUSY;
+ ata_tf_to_fis(&tf, 0, 0, d2h_fis);
+
+ rc = sata_link_hardreset(link, timing, deadline, &online,
+ ahci_check_ready);
+
+ if (sata_scr_read(link, SCR_STATUS, &sstatus) != 0 ||
+ (sstatus & 0xf) != 1)
+ break;
+
+ ata_link_printk(link, KERN_INFO, "avn bounce port%d\n",
+ port);
+
+ pci_read_config_word(pdev, 0x92, &val);
+ val &= ~(1 << port);
+ pci_write_config_word(pdev, 0x92, val);
+ ata_msleep(ap, 1000);
+ val |= 1 << port;
+ pci_write_config_word(pdev, 0x92, val);
+ deadline += tmo;
+ }
+
+ hpriv->start_engine(ap);
+
+ if (online)
+ *class = ahci_dev_classify(ap);
+
+ DPRINTK("EXIT, rc=%d, class=%u\n", rc, *class);
+ return rc;
+}
+
+
#ifdef CONFIG_PM
static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
{
struct reset_control *pwr;
struct reset_control *sw_rst;
struct reset_control *pwr_rst;
- struct ahci_host_priv *hpriv;
};
static void st_ahci_configure_oob(void __iomem *mmio)
writel(new_val, mmio + ST_AHCI_OOBR);
}
-static int st_ahci_deassert_resets(struct device *dev)
+static int st_ahci_deassert_resets(struct ahci_host_priv *hpriv,
+ struct device *dev)
{
- struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
+ struct st_ahci_drv_data *drv_data = hpriv->plat_data;
int err;
if (drv_data->pwr) {
static void st_ahci_host_stop(struct ata_host *host)
{
struct ahci_host_priv *hpriv = host->private_data;
+ struct st_ahci_drv_data *drv_data = hpriv->plat_data;
struct device *dev = host->dev;
- struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
int err;
if (drv_data->pwr) {
ahci_platform_disable_resources(hpriv);
}
-static int st_ahci_probe_resets(struct platform_device *pdev)
+static int st_ahci_probe_resets(struct ahci_host_priv *hpriv,
+ struct device *dev)
{
- struct st_ahci_drv_data *drv_data = platform_get_drvdata(pdev);
+ struct st_ahci_drv_data *drv_data = hpriv->plat_data;
- drv_data->pwr = devm_reset_control_get(&pdev->dev, "pwr-dwn");
+ drv_data->pwr = devm_reset_control_get(dev, "pwr-dwn");
if (IS_ERR(drv_data->pwr)) {
- dev_info(&pdev->dev, "power reset control not defined\n");
+ dev_info(dev, "power reset control not defined\n");
drv_data->pwr = NULL;
}
- drv_data->sw_rst = devm_reset_control_get(&pdev->dev, "sw-rst");
+ drv_data->sw_rst = devm_reset_control_get(dev, "sw-rst");
if (IS_ERR(drv_data->sw_rst)) {
- dev_info(&pdev->dev, "soft reset control not defined\n");
+ dev_info(dev, "soft reset control not defined\n");
drv_data->sw_rst = NULL;
}
- drv_data->pwr_rst = devm_reset_control_get(&pdev->dev, "pwr-rst");
+ drv_data->pwr_rst = devm_reset_control_get(dev, "pwr-rst");
if (IS_ERR(drv_data->pwr_rst)) {
- dev_dbg(&pdev->dev, "power soft reset control not defined\n");
+ dev_dbg(dev, "power soft reset control not defined\n");
drv_data->pwr_rst = NULL;
}
- return st_ahci_deassert_resets(&pdev->dev);
+ return st_ahci_deassert_resets(hpriv, dev);
}
static struct ata_port_operations st_ahci_port_ops = {
if (!drv_data)
return -ENOMEM;
- platform_set_drvdata(pdev, drv_data);
-
hpriv = ahci_platform_get_resources(pdev);
if (IS_ERR(hpriv))
return PTR_ERR(hpriv);
+ hpriv->plat_data = drv_data;
- drv_data->hpriv = hpriv;
-
- err = st_ahci_probe_resets(pdev);
+ err = st_ahci_probe_resets(hpriv, &pdev->dev);
if (err)
return err;
if (err)
return err;
- st_ahci_configure_oob(drv_data->hpriv->mmio);
+ st_ahci_configure_oob(hpriv->mmio);
err = ahci_platform_init_host(pdev, hpriv, &st_ahci_port_info,
&ahci_platform_sht);
#ifdef CONFIG_PM_SLEEP
static int st_ahci_suspend(struct device *dev)
{
- struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
- struct ahci_host_priv *hpriv = drv_data->hpriv;
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
+ struct st_ahci_drv_data *drv_data = hpriv->plat_data;
int err;
err = ahci_platform_suspend_host(dev);
static int st_ahci_resume(struct device *dev)
{
- struct st_ahci_drv_data *drv_data = dev_get_drvdata(dev);
- struct ahci_host_priv *hpriv = drv_data->hpriv;
+ struct ata_host *host = dev_get_drvdata(dev);
+ struct ahci_host_priv *hpriv = host->private_data;
int err;
err = ahci_platform_enable_resources(hpriv);
if (err)
return err;
- err = st_ahci_deassert_resets(dev);
+ err = st_ahci_deassert_resets(hpriv, dev);
if (err) {
ahci_platform_disable_resources(hpriv);
return err;
}
- st_ahci_configure_oob(drv_data->hpriv->mmio);
+ st_ahci_configure_oob(hpriv->mmio);
return ahci_platform_resume_host(dev);
}
if (unlikely(resetting))
status &= ~PORT_IRQ_BAD_PMP;
- /* if LPM is enabled, PHYRDY doesn't mean anything */
- if (ap->link.lpm_policy > ATA_LPM_MAX_POWER) {
+ if (sata_lpm_ignore_phy_events(&ap->link)) {
status &= ~PORT_IRQ_PHYRDY;
ahci_scr_write(&ap->link, SCR_ERROR, SERR_PHYRDY_CHG);
}
ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Crucial_CT*MX100*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
- { "Samsung SSD 850 PRO*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
+ { "Samsung SSD 8*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
/*
return tmp;
}
+/**
+ * sata_lpm_ignore_phy_events - test if PHY event should be ignored
+ * @link: Link receiving the event
+ *
+ * Test whether the received PHY event has to be ignored or not.
+ *
+ * LOCKING:
+ * None:
+ *
+ * RETURNS:
+ * True if the event has to be ignored.
+ */
+bool sata_lpm_ignore_phy_events(struct ata_link *link)
+{
+ unsigned long lpm_timeout = link->last_lpm_change +
+ msecs_to_jiffies(ATA_TMOUT_SPURIOUS_PHY);
+
+ /* if LPM is enabled, PHYRDY doesn't mean anything */
+ if (link->lpm_policy > ATA_LPM_MAX_POWER)
+ return true;
+
+ /* ignore the first PHY event after the LPM policy changed
+ * as it is might be spurious
+ */
+ if ((link->flags & ATA_LFLAG_CHANGED) &&
+ time_before(jiffies, lpm_timeout))
+ return true;
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(sata_lpm_ignore_phy_events);
+
/*
* Dummy port_ops
*/
}
}
+ link->last_lpm_change = jiffies;
+ link->flags |= ATA_LFLAG_CHANGED;
+
return 0;
fail:
+++ /dev/null
-/*
- * Support for IDE interfaces on Celleb platform
- *
- * (C) Copyright 2006 TOSHIBA CORPORATION
- *
- * This code is based on drivers/ata/ata_piix.c:
- * Copyright 2003-2005 Red Hat Inc
- * Copyright 2003-2005 Jeff Garzik
- * Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
- * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2003 Red Hat Inc
- *
- * and drivers/ata/ahci.c:
- * Copyright 2004-2005 Red Hat, Inc.
- *
- * and drivers/ata/libata-core.c:
- * Copyright 2003-2004 Red Hat, Inc. All rights reserved.
- * Copyright 2003-2004 Jeff Garzik
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <scsi/scsi_host.h>
-#include <linux/libata.h>
-
-#define DRV_NAME "pata_scc"
-#define DRV_VERSION "0.3"
-
-#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4
-
-/* PCI BARs */
-#define SCC_CTRL_BAR 0
-#define SCC_BMID_BAR 1
-
-/* offset of CTRL registers */
-#define SCC_CTL_PIOSHT 0x000
-#define SCC_CTL_PIOCT 0x004
-#define SCC_CTL_MDMACT 0x008
-#define SCC_CTL_MCRCST 0x00C
-#define SCC_CTL_SDMACT 0x010
-#define SCC_CTL_SCRCST 0x014
-#define SCC_CTL_UDENVT 0x018
-#define SCC_CTL_TDVHSEL 0x020
-#define SCC_CTL_MODEREG 0x024
-#define SCC_CTL_ECMODE 0xF00
-#define SCC_CTL_MAEA0 0xF50
-#define SCC_CTL_MAEC0 0xF54
-#define SCC_CTL_CCKCTRL 0xFF0
-
-/* offset of BMID registers */
-#define SCC_DMA_CMD 0x000
-#define SCC_DMA_STATUS 0x004
-#define SCC_DMA_TABLE_OFS 0x008
-#define SCC_DMA_INTMASK 0x010
-#define SCC_DMA_INTST 0x014
-#define SCC_DMA_PTERADD 0x018
-#define SCC_REG_CMD_ADDR 0x020
-#define SCC_REG_DATA 0x000
-#define SCC_REG_ERR 0x004
-#define SCC_REG_FEATURE 0x004
-#define SCC_REG_NSECT 0x008
-#define SCC_REG_LBAL 0x00C
-#define SCC_REG_LBAM 0x010
-#define SCC_REG_LBAH 0x014
-#define SCC_REG_DEVICE 0x018
-#define SCC_REG_STATUS 0x01C
-#define SCC_REG_CMD 0x01C
-#define SCC_REG_ALTSTATUS 0x020
-
-/* register value */
-#define TDVHSEL_MASTER 0x00000001
-#define TDVHSEL_SLAVE 0x00000004
-
-#define MODE_JCUSFEN 0x00000080
-
-#define ECMODE_VALUE 0x01
-
-#define CCKCTRL_ATARESET 0x00040000
-#define CCKCTRL_BUFCNT 0x00020000
-#define CCKCTRL_CRST 0x00010000
-#define CCKCTRL_OCLKEN 0x00000100
-#define CCKCTRL_ATACLKOEN 0x00000002
-#define CCKCTRL_LCLKEN 0x00000001
-
-#define QCHCD_IOS_SS 0x00000001
-
-#define QCHSD_STPDIAG 0x00020000
-
-#define INTMASK_MSK 0xD1000012
-#define INTSTS_SERROR 0x80000000
-#define INTSTS_PRERR 0x40000000
-#define INTSTS_RERR 0x10000000
-#define INTSTS_ICERR 0x01000000
-#define INTSTS_BMSINT 0x00000010
-#define INTSTS_BMHE 0x00000008
-#define INTSTS_IOIRQS 0x00000004
-#define INTSTS_INTRQ 0x00000002
-#define INTSTS_ACTEINT 0x00000001
-
-
-/* PIO transfer mode table */
-/* JCHST */
-static const unsigned long JCHSTtbl[2][7] = {
- {0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00}, /* 100MHz */
- {0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00} /* 133MHz */
-};
-
-/* JCHHT */
-static const unsigned long JCHHTtbl[2][7] = {
- {0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00}, /* 100MHz */
- {0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00} /* 133MHz */
-};
-
-/* JCHCT */
-static const unsigned long JCHCTtbl[2][7] = {
- {0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00}, /* 100MHz */
- {0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00} /* 133MHz */
-};
-
-/* DMA transfer mode table */
-/* JCHDCTM/JCHDCTS */
-static const unsigned long JCHDCTxtbl[2][7] = {
- {0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00}, /* 100MHz */
- {0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00} /* 133MHz */
-};
-
-/* JCSTWTM/JCSTWTS */
-static const unsigned long JCSTWTxtbl[2][7] = {
- {0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00}, /* 100MHz */
- {0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02} /* 133MHz */
-};
-
-/* JCTSS */
-static const unsigned long JCTSStbl[2][7] = {
- {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00}, /* 100MHz */
- {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05} /* 133MHz */
-};
-
-/* JCENVT */
-static const unsigned long JCENVTtbl[2][7] = {
- {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}, /* 100MHz */
- {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} /* 133MHz */
-};
-
-/* JCACTSELS/JCACTSELM */
-static const unsigned long JCACTSELtbl[2][7] = {
- {0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00}, /* 100MHz */
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} /* 133MHz */
-};
-
-static const struct pci_device_id scc_pci_tbl[] = {
- { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA), 0},
- { } /* terminate list */
-};
-
-/**
- * scc_set_piomode - Initialize host controller PATA PIO timings
- * @ap: Port whose timings we are configuring
- * @adev: um
- *
- * Set PIO mode for device.
- *
- * LOCKING:
- * None (inherited from caller).
- */
-
-static void scc_set_piomode (struct ata_port *ap, struct ata_device *adev)
-{
- unsigned int pio = adev->pio_mode - XFER_PIO_0;
- void __iomem *ctrl_base = ap->host->iomap[SCC_CTRL_BAR];
- void __iomem *cckctrl_port = ctrl_base + SCC_CTL_CCKCTRL;
- void __iomem *piosht_port = ctrl_base + SCC_CTL_PIOSHT;
- void __iomem *pioct_port = ctrl_base + SCC_CTL_PIOCT;
- unsigned long reg;
- int offset;
-
- reg = in_be32(cckctrl_port);
- if (reg & CCKCTRL_ATACLKOEN)
- offset = 1; /* 133MHz */
- else
- offset = 0; /* 100MHz */
-
- reg = JCHSTtbl[offset][pio] << 16 | JCHHTtbl[offset][pio];
- out_be32(piosht_port, reg);
- reg = JCHCTtbl[offset][pio];
- out_be32(pioct_port, reg);
-}
-
-/**
- * scc_set_dmamode - Initialize host controller PATA DMA timings
- * @ap: Port whose timings we are configuring
- * @adev: um
- *
- * Set UDMA mode for device.
- *
- * LOCKING:
- * None (inherited from caller).
- */
-
-static void scc_set_dmamode (struct ata_port *ap, struct ata_device *adev)
-{
- unsigned int udma = adev->dma_mode;
- unsigned int is_slave = (adev->devno != 0);
- u8 speed = udma;
- void __iomem *ctrl_base = ap->host->iomap[SCC_CTRL_BAR];
- void __iomem *cckctrl_port = ctrl_base + SCC_CTL_CCKCTRL;
- void __iomem *mdmact_port = ctrl_base + SCC_CTL_MDMACT;
- void __iomem *mcrcst_port = ctrl_base + SCC_CTL_MCRCST;
- void __iomem *sdmact_port = ctrl_base + SCC_CTL_SDMACT;
- void __iomem *scrcst_port = ctrl_base + SCC_CTL_SCRCST;
- void __iomem *udenvt_port = ctrl_base + SCC_CTL_UDENVT;
- void __iomem *tdvhsel_port = ctrl_base + SCC_CTL_TDVHSEL;
- int offset, idx;
-
- if (in_be32(cckctrl_port) & CCKCTRL_ATACLKOEN)
- offset = 1; /* 133MHz */
- else
- offset = 0; /* 100MHz */
-
- if (speed >= XFER_UDMA_0)
- idx = speed - XFER_UDMA_0;
- else
- return;
-
- if (is_slave) {
- out_be32(sdmact_port, JCHDCTxtbl[offset][idx]);
- out_be32(scrcst_port, JCSTWTxtbl[offset][idx]);
- out_be32(tdvhsel_port,
- (in_be32(tdvhsel_port) & ~TDVHSEL_SLAVE) | (JCACTSELtbl[offset][idx] << 2));
- } else {
- out_be32(mdmact_port, JCHDCTxtbl[offset][idx]);
- out_be32(mcrcst_port, JCSTWTxtbl[offset][idx]);
- out_be32(tdvhsel_port,
- (in_be32(tdvhsel_port) & ~TDVHSEL_MASTER) | JCACTSELtbl[offset][idx]);
- }
- out_be32(udenvt_port,
- JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx]);
-}
-
-unsigned long scc_mode_filter(struct ata_device *adev, unsigned long mask)
-{
- /* errata A308 workaround: limit ATAPI UDMA mode to UDMA4 */
- if (adev->class == ATA_DEV_ATAPI &&
- (mask & (0xE0 << ATA_SHIFT_UDMA))) {
- printk(KERN_INFO "%s: limit ATAPI UDMA to UDMA4\n", DRV_NAME);
- mask &= ~(0xE0 << ATA_SHIFT_UDMA);
- }
- return mask;
-}
-
-/**
- * scc_tf_load - send taskfile registers to host controller
- * @ap: Port to which output is sent
- * @tf: ATA taskfile register set
- *
- * Note: Original code is ata_sff_tf_load().
- */
-
-static void scc_tf_load (struct ata_port *ap, const struct ata_taskfile *tf)
-{
- struct ata_ioports *ioaddr = &ap->ioaddr;
- unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
-
- if (tf->ctl != ap->last_ctl) {
- out_be32(ioaddr->ctl_addr, tf->ctl);
- ap->last_ctl = tf->ctl;
- ata_wait_idle(ap);
- }
-
- if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
- out_be32(ioaddr->feature_addr, tf->hob_feature);
- out_be32(ioaddr->nsect_addr, tf->hob_nsect);
- out_be32(ioaddr->lbal_addr, tf->hob_lbal);
- out_be32(ioaddr->lbam_addr, tf->hob_lbam);
- out_be32(ioaddr->lbah_addr, tf->hob_lbah);
- VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
- tf->hob_feature,
- tf->hob_nsect,
- tf->hob_lbal,
- tf->hob_lbam,
- tf->hob_lbah);
- }
-
- if (is_addr) {
- out_be32(ioaddr->feature_addr, tf->feature);
- out_be32(ioaddr->nsect_addr, tf->nsect);
- out_be32(ioaddr->lbal_addr, tf->lbal);
- out_be32(ioaddr->lbam_addr, tf->lbam);
- out_be32(ioaddr->lbah_addr, tf->lbah);
- VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
- tf->feature,
- tf->nsect,
- tf->lbal,
- tf->lbam,
- tf->lbah);
- }
-
- if (tf->flags & ATA_TFLAG_DEVICE) {
- out_be32(ioaddr->device_addr, tf->device);
- VPRINTK("device 0x%X\n", tf->device);
- }
-
- ata_wait_idle(ap);
-}
-
-/**
- * scc_check_status - Read device status reg & clear interrupt
- * @ap: port where the device is
- *
- * Note: Original code is ata_check_status().
- */
-
-static u8 scc_check_status (struct ata_port *ap)
-{
- return in_be32(ap->ioaddr.status_addr);
-}
-
-/**
- * scc_tf_read - input device's ATA taskfile shadow registers
- * @ap: Port from which input is read
- * @tf: ATA taskfile register set for storing input
- *
- * Note: Original code is ata_sff_tf_read().
- */
-
-static void scc_tf_read (struct ata_port *ap, struct ata_taskfile *tf)
-{
- struct ata_ioports *ioaddr = &ap->ioaddr;
-
- tf->command = scc_check_status(ap);
- tf->feature = in_be32(ioaddr->error_addr);
- tf->nsect = in_be32(ioaddr->nsect_addr);
- tf->lbal = in_be32(ioaddr->lbal_addr);
- tf->lbam = in_be32(ioaddr->lbam_addr);
- tf->lbah = in_be32(ioaddr->lbah_addr);
- tf->device = in_be32(ioaddr->device_addr);
-
- if (tf->flags & ATA_TFLAG_LBA48) {
- out_be32(ioaddr->ctl_addr, tf->ctl | ATA_HOB);
- tf->hob_feature = in_be32(ioaddr->error_addr);
- tf->hob_nsect = in_be32(ioaddr->nsect_addr);
- tf->hob_lbal = in_be32(ioaddr->lbal_addr);
- tf->hob_lbam = in_be32(ioaddr->lbam_addr);
- tf->hob_lbah = in_be32(ioaddr->lbah_addr);
- out_be32(ioaddr->ctl_addr, tf->ctl);
- ap->last_ctl = tf->ctl;
- }
-}
-
-/**
- * scc_exec_command - issue ATA command to host controller
- * @ap: port to which command is being issued
- * @tf: ATA taskfile register set
- *
- * Note: Original code is ata_sff_exec_command().
- */
-
-static void scc_exec_command (struct ata_port *ap,
- const struct ata_taskfile *tf)
-{
- DPRINTK("ata%u: cmd 0x%X\n", ap->print_id, tf->command);
-
- out_be32(ap->ioaddr.command_addr, tf->command);
- ata_sff_pause(ap);
-}
-
-/**
- * scc_check_altstatus - Read device alternate status reg
- * @ap: port where the device is
- */
-
-static u8 scc_check_altstatus (struct ata_port *ap)
-{
- return in_be32(ap->ioaddr.altstatus_addr);
-}
-
-/**
- * scc_dev_select - Select device 0/1 on ATA bus
- * @ap: ATA channel to manipulate
- * @device: ATA device (numbered from zero) to select
- *
- * Note: Original code is ata_sff_dev_select().
- */
-
-static void scc_dev_select (struct ata_port *ap, unsigned int device)
-{
- u8 tmp;
-
- if (device == 0)
- tmp = ATA_DEVICE_OBS;
- else
- tmp = ATA_DEVICE_OBS | ATA_DEV1;
-
- out_be32(ap->ioaddr.device_addr, tmp);
- ata_sff_pause(ap);
-}
-
-/**
- * scc_set_devctl - Write device control reg
- * @ap: port where the device is
- * @ctl: value to write
- */
-
-static void scc_set_devctl(struct ata_port *ap, u8 ctl)
-{
- out_be32(ap->ioaddr.ctl_addr, ctl);
-}
-
-/**
- * scc_bmdma_setup - Set up PCI IDE BMDMA transaction
- * @qc: Info associated with this ATA transaction.
- *
- * Note: Original code is ata_bmdma_setup().
- */
-
-static void scc_bmdma_setup (struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
- u8 dmactl;
- void __iomem *mmio = ap->ioaddr.bmdma_addr;
-
- /* load PRD table addr */
- out_be32(mmio + SCC_DMA_TABLE_OFS, ap->bmdma_prd_dma);
-
- /* specify data direction, triple-check start bit is clear */
- dmactl = in_be32(mmio + SCC_DMA_CMD);
- dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
- if (!rw)
- dmactl |= ATA_DMA_WR;
- out_be32(mmio + SCC_DMA_CMD, dmactl);
-
- /* issue r/w command */
- ap->ops->sff_exec_command(ap, &qc->tf);
-}
-
-/**
- * scc_bmdma_start - Start a PCI IDE BMDMA transaction
- * @qc: Info associated with this ATA transaction.
- *
- * Note: Original code is ata_bmdma_start().
- */
-
-static void scc_bmdma_start (struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- u8 dmactl;
- void __iomem *mmio = ap->ioaddr.bmdma_addr;
-
- /* start host DMA transaction */
- dmactl = in_be32(mmio + SCC_DMA_CMD);
- out_be32(mmio + SCC_DMA_CMD, dmactl | ATA_DMA_START);
-}
-
-/**
- * scc_devchk - PATA device presence detection
- * @ap: ATA channel to examine
- * @device: Device to examine (starting at zero)
- *
- * Note: Original code is ata_devchk().
- */
-
-static unsigned int scc_devchk (struct ata_port *ap,
- unsigned int device)
-{
- struct ata_ioports *ioaddr = &ap->ioaddr;
- u8 nsect, lbal;
-
- ap->ops->sff_dev_select(ap, device);
-
- out_be32(ioaddr->nsect_addr, 0x55);
- out_be32(ioaddr->lbal_addr, 0xaa);
-
- out_be32(ioaddr->nsect_addr, 0xaa);
- out_be32(ioaddr->lbal_addr, 0x55);
-
- out_be32(ioaddr->nsect_addr, 0x55);
- out_be32(ioaddr->lbal_addr, 0xaa);
-
- nsect = in_be32(ioaddr->nsect_addr);
- lbal = in_be32(ioaddr->lbal_addr);
-
- if ((nsect == 0x55) && (lbal == 0xaa))
- return 1; /* we found a device */
-
- return 0; /* nothing found */
-}
-
-/**
- * scc_wait_after_reset - wait for devices to become ready after reset
- *
- * Note: Original code is ata_sff_wait_after_reset
- */
-
-static int scc_wait_after_reset(struct ata_link *link, unsigned int devmask,
- unsigned long deadline)
-{
- struct ata_port *ap = link->ap;
- struct ata_ioports *ioaddr = &ap->ioaddr;
- unsigned int dev0 = devmask & (1 << 0);
- unsigned int dev1 = devmask & (1 << 1);
- int rc, ret = 0;
-
- /* Spec mandates ">= 2ms" before checking status. We wait
- * 150ms, because that was the magic delay used for ATAPI
- * devices in Hale Landis's ATADRVR, for the period of time
- * between when the ATA command register is written, and then
- * status is checked. Because waiting for "a while" before
- * checking status is fine, post SRST, we perform this magic
- * delay here as well.
- *
- * Old drivers/ide uses the 2mS rule and then waits for ready.
- */
- ata_msleep(ap, 150);
-
- /* always check readiness of the master device */
- rc = ata_sff_wait_ready(link, deadline);
- /* -ENODEV means the odd clown forgot the D7 pulldown resistor
- * and TF status is 0xff, bail out on it too.
- */
- if (rc)
- return rc;
-
- /* if device 1 was found in ata_devchk, wait for register
- * access briefly, then wait for BSY to clear.
- */
- if (dev1) {
- int i;
-
- ap->ops->sff_dev_select(ap, 1);
-
- /* Wait for register access. Some ATAPI devices fail
- * to set nsect/lbal after reset, so don't waste too
- * much time on it. We're gonna wait for !BSY anyway.
- */
- for (i = 0; i < 2; i++) {
- u8 nsect, lbal;
-
- nsect = in_be32(ioaddr->nsect_addr);
- lbal = in_be32(ioaddr->lbal_addr);
- if ((nsect == 1) && (lbal == 1))
- break;
- ata_msleep(ap, 50); /* give drive a breather */
- }
-
- rc = ata_sff_wait_ready(link, deadline);
- if (rc) {
- if (rc != -ENODEV)
- return rc;
- ret = rc;
- }
- }
-
- /* is all this really necessary? */
- ap->ops->sff_dev_select(ap, 0);
- if (dev1)
- ap->ops->sff_dev_select(ap, 1);
- if (dev0)
- ap->ops->sff_dev_select(ap, 0);
-
- return ret;
-}
-
-/**
- * scc_bus_softreset - PATA device software reset
- *
- * Note: Original code is ata_bus_softreset().
- */
-
-static int scc_bus_softreset(struct ata_port *ap, unsigned int devmask,
- unsigned long deadline)
-{
- struct ata_ioports *ioaddr = &ap->ioaddr;
-
- DPRINTK("ata%u: bus reset via SRST\n", ap->print_id);
-
- /* software reset. causes dev0 to be selected */
- out_be32(ioaddr->ctl_addr, ap->ctl);
- udelay(20);
- out_be32(ioaddr->ctl_addr, ap->ctl | ATA_SRST);
- udelay(20);
- out_be32(ioaddr->ctl_addr, ap->ctl);
-
- return scc_wait_after_reset(&ap->link, devmask, deadline);
-}
-
-/**
- * scc_softreset - reset host port via ATA SRST
- * @ap: port to reset
- * @classes: resulting classes of attached devices
- * @deadline: deadline jiffies for the operation
- *
- * Note: Original code is ata_sff_softreset().
- */
-
-static int scc_softreset(struct ata_link *link, unsigned int *classes,
- unsigned long deadline)
-{
- struct ata_port *ap = link->ap;
- unsigned int slave_possible = ap->flags & ATA_FLAG_SLAVE_POSS;
- unsigned int devmask = 0;
- int rc;
- u8 err;
-
- DPRINTK("ENTER\n");
-
- /* determine if device 0/1 are present */
- if (scc_devchk(ap, 0))
- devmask |= (1 << 0);
- if (slave_possible && scc_devchk(ap, 1))
- devmask |= (1 << 1);
-
- /* select device 0 again */
- ap->ops->sff_dev_select(ap, 0);
-
- /* issue bus reset */
- DPRINTK("about to softreset, devmask=%x\n", devmask);
- rc = scc_bus_softreset(ap, devmask, deadline);
- if (rc) {
- ata_port_err(ap, "SRST failed (err_mask=0x%x)\n", rc);
- return -EIO;
- }
-
- /* determine by signature whether we have ATA or ATAPI devices */
- classes[0] = ata_sff_dev_classify(&ap->link.device[0],
- devmask & (1 << 0), &err);
- if (slave_possible && err != 0x81)
- classes[1] = ata_sff_dev_classify(&ap->link.device[1],
- devmask & (1 << 1), &err);
-
- DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
- return 0;
-}
-
-/**
- * scc_bmdma_stop - Stop PCI IDE BMDMA transfer
- * @qc: Command we are ending DMA for
- */
-
-static void scc_bmdma_stop (struct ata_queued_cmd *qc)
-{
- struct ata_port *ap = qc->ap;
- void __iomem *ctrl_base = ap->host->iomap[SCC_CTRL_BAR];
- void __iomem *bmid_base = ap->host->iomap[SCC_BMID_BAR];
- u32 reg;
-
- while (1) {
- reg = in_be32(bmid_base + SCC_DMA_INTST);
-
- if (reg & INTSTS_SERROR) {
- printk(KERN_WARNING "%s: SERROR\n", DRV_NAME);
- out_be32(bmid_base + SCC_DMA_INTST, INTSTS_SERROR|INTSTS_BMSINT);
- out_be32(bmid_base + SCC_DMA_CMD,
- in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
- continue;
- }
-
- if (reg & INTSTS_PRERR) {
- u32 maea0, maec0;
- maea0 = in_be32(ctrl_base + SCC_CTL_MAEA0);
- maec0 = in_be32(ctrl_base + SCC_CTL_MAEC0);
- printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", DRV_NAME, maea0, maec0);
- out_be32(bmid_base + SCC_DMA_INTST, INTSTS_PRERR|INTSTS_BMSINT);
- out_be32(bmid_base + SCC_DMA_CMD,
- in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
- continue;
- }
-
- if (reg & INTSTS_RERR) {
- printk(KERN_WARNING "%s: Response Error\n", DRV_NAME);
- out_be32(bmid_base + SCC_DMA_INTST, INTSTS_RERR|INTSTS_BMSINT);
- out_be32(bmid_base + SCC_DMA_CMD,
- in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
- continue;
- }
-
- if (reg & INTSTS_ICERR) {
- out_be32(bmid_base + SCC_DMA_CMD,
- in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
- printk(KERN_WARNING "%s: Illegal Configuration\n", DRV_NAME);
- out_be32(bmid_base + SCC_DMA_INTST, INTSTS_ICERR|INTSTS_BMSINT);
- continue;
- }
-
- if (reg & INTSTS_BMSINT) {
- unsigned int classes;
- unsigned long deadline = ata_deadline(jiffies, ATA_TMOUT_BOOT);
- printk(KERN_WARNING "%s: Internal Bus Error\n", DRV_NAME);
- out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMSINT);
- /* TBD: SW reset */
- scc_softreset(&ap->link, &classes, deadline);
- continue;
- }
-
- if (reg & INTSTS_BMHE) {
- out_be32(bmid_base + SCC_DMA_INTST, INTSTS_BMHE);
- continue;
- }
-
- if (reg & INTSTS_ACTEINT) {
- out_be32(bmid_base + SCC_DMA_INTST, INTSTS_ACTEINT);
- continue;
- }
-
- if (reg & INTSTS_IOIRQS) {
- out_be32(bmid_base + SCC_DMA_INTST, INTSTS_IOIRQS);
- continue;
- }
- break;
- }
-
- /* clear start/stop bit */
- out_be32(bmid_base + SCC_DMA_CMD,
- in_be32(bmid_base + SCC_DMA_CMD) & ~ATA_DMA_START);
-
- /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
- ata_sff_dma_pause(ap); /* dummy read */
-}
-
-/**
- * scc_bmdma_status - Read PCI IDE BMDMA status
- * @ap: Port associated with this ATA transaction.
- */
-
-static u8 scc_bmdma_status (struct ata_port *ap)
-{
- void __iomem *mmio = ap->ioaddr.bmdma_addr;
- u8 host_stat = in_be32(mmio + SCC_DMA_STATUS);
- u32 int_status = in_be32(mmio + SCC_DMA_INTST);
- struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->link.active_tag);
- static int retry = 0;
-
- /* return if IOS_SS is cleared */
- if (!(in_be32(mmio + SCC_DMA_CMD) & ATA_DMA_START))
- return host_stat;
-
- /* errata A252,A308 workaround: Step4 */
- if ((scc_check_altstatus(ap) & ATA_ERR)
- && (int_status & INTSTS_INTRQ))
- return (host_stat | ATA_DMA_INTR);
-
- /* errata A308 workaround Step5 */
- if (int_status & INTSTS_IOIRQS) {
- host_stat |= ATA_DMA_INTR;
-
- /* We don't check ATAPI DMA because it is limited to UDMA4 */
- if ((qc->tf.protocol == ATA_PROT_DMA &&
- qc->dev->xfer_mode > XFER_UDMA_4)) {
- if (!(int_status & INTSTS_ACTEINT)) {
- printk(KERN_WARNING "ata%u: operation failed (transfer data loss)\n",
- ap->print_id);
- host_stat |= ATA_DMA_ERR;
- if (retry++)
- ap->udma_mask &= ~(1 << qc->dev->xfer_mode);
- } else
- retry = 0;
- }
- }
-
- return host_stat;
-}
-
-/**
- * scc_data_xfer - Transfer data by PIO
- * @dev: device for this I/O
- * @buf: data buffer
- * @buflen: buffer length
- * @rw: read/write
- *
- * Note: Original code is ata_sff_data_xfer().
- */
-
-static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
- unsigned int buflen, int rw)
-{
- struct ata_port *ap = dev->link->ap;
- unsigned int words = buflen >> 1;
- unsigned int i;
- __le16 *buf16 = (__le16 *) buf;
- void __iomem *mmio = ap->ioaddr.data_addr;
-
- /* Transfer multiple of 2 bytes */
- if (rw == READ)
- for (i = 0; i < words; i++)
- buf16[i] = cpu_to_le16(in_be32(mmio));
- else
- for (i = 0; i < words; i++)
- out_be32(mmio, le16_to_cpu(buf16[i]));
-
- /* Transfer trailing 1 byte, if any. */
- if (unlikely(buflen & 0x01)) {
- __le16 align_buf[1] = { 0 };
- unsigned char *trailing_buf = buf + buflen - 1;
-
- if (rw == READ) {
- align_buf[0] = cpu_to_le16(in_be32(mmio));
- memcpy(trailing_buf, align_buf, 1);
- } else {
- memcpy(align_buf, trailing_buf, 1);
- out_be32(mmio, le16_to_cpu(align_buf[0]));
- }
- words++;
- }
-
- return words << 1;
-}
-
-/**
- * scc_postreset - standard postreset callback
- * @ap: the target ata_port
- * @classes: classes of attached devices
- *
- * Note: Original code is ata_sff_postreset().
- */
-
-static void scc_postreset(struct ata_link *link, unsigned int *classes)
-{
- struct ata_port *ap = link->ap;
-
- DPRINTK("ENTER\n");
-
- /* is double-select really necessary? */
- if (classes[0] != ATA_DEV_NONE)
- ap->ops->sff_dev_select(ap, 1);
- if (classes[1] != ATA_DEV_NONE)
- ap->ops->sff_dev_select(ap, 0);
-
- /* bail out if no device is present */
- if (classes[0] == ATA_DEV_NONE && classes[1] == ATA_DEV_NONE) {
- DPRINTK("EXIT, no device\n");
- return;
- }
-
- /* set up device control */
- out_be32(ap->ioaddr.ctl_addr, ap->ctl);
-
- DPRINTK("EXIT\n");
-}
-
-/**
- * scc_irq_clear - Clear PCI IDE BMDMA interrupt.
- * @ap: Port associated with this ATA transaction.
- *
- * Note: Original code is ata_bmdma_irq_clear().
- */
-
-static void scc_irq_clear (struct ata_port *ap)
-{
- void __iomem *mmio = ap->ioaddr.bmdma_addr;
-
- if (!mmio)
- return;
-
- out_be32(mmio + SCC_DMA_STATUS, in_be32(mmio + SCC_DMA_STATUS));
-}
-
-/**
- * scc_port_start - Set port up for dma.
- * @ap: Port to initialize
- *
- * Allocate space for PRD table using ata_bmdma_port_start().
- * Set PRD table address for PTERADD. (PRD Transfer End Read)
- */
-
-static int scc_port_start (struct ata_port *ap)
-{
- void __iomem *mmio = ap->ioaddr.bmdma_addr;
- int rc;
-
- rc = ata_bmdma_port_start(ap);
- if (rc)
- return rc;
-
- out_be32(mmio + SCC_DMA_PTERADD, ap->bmdma_prd_dma);
- return 0;
-}
-
-/**
- * scc_port_stop - Undo scc_port_start()
- * @ap: Port to shut down
- *
- * Reset PTERADD.
- */
-
-static void scc_port_stop (struct ata_port *ap)
-{
- void __iomem *mmio = ap->ioaddr.bmdma_addr;
-
- out_be32(mmio + SCC_DMA_PTERADD, 0);
-}
-
-static struct scsi_host_template scc_sht = {
- ATA_BMDMA_SHT(DRV_NAME),
-};
-
-static struct ata_port_operations scc_pata_ops = {
- .inherits = &ata_bmdma_port_ops,
-
- .set_piomode = scc_set_piomode,
- .set_dmamode = scc_set_dmamode,
- .mode_filter = scc_mode_filter,
-
- .sff_tf_load = scc_tf_load,
- .sff_tf_read = scc_tf_read,
- .sff_exec_command = scc_exec_command,
- .sff_check_status = scc_check_status,
- .sff_check_altstatus = scc_check_altstatus,
- .sff_dev_select = scc_dev_select,
- .sff_set_devctl = scc_set_devctl,
-
- .bmdma_setup = scc_bmdma_setup,
- .bmdma_start = scc_bmdma_start,
- .bmdma_stop = scc_bmdma_stop,
- .bmdma_status = scc_bmdma_status,
- .sff_data_xfer = scc_data_xfer,
-
- .cable_detect = ata_cable_80wire,
- .softreset = scc_softreset,
- .postreset = scc_postreset,
-
- .sff_irq_clear = scc_irq_clear,
-
- .port_start = scc_port_start,
- .port_stop = scc_port_stop,
-};
-
-static struct ata_port_info scc_port_info[] = {
- {
- .flags = ATA_FLAG_SLAVE_POSS,
- .pio_mask = ATA_PIO4,
- /* No MWDMA */
- .udma_mask = ATA_UDMA6,
- .port_ops = &scc_pata_ops,
- },
-};
-
-/**
- * scc_reset_controller - initialize SCC PATA controller.
- */
-
-static int scc_reset_controller(struct ata_host *host)
-{
- void __iomem *ctrl_base = host->iomap[SCC_CTRL_BAR];
- void __iomem *bmid_base = host->iomap[SCC_BMID_BAR];
- void __iomem *cckctrl_port = ctrl_base + SCC_CTL_CCKCTRL;
- void __iomem *mode_port = ctrl_base + SCC_CTL_MODEREG;
- void __iomem *ecmode_port = ctrl_base + SCC_CTL_ECMODE;
- void __iomem *intmask_port = bmid_base + SCC_DMA_INTMASK;
- void __iomem *dmastatus_port = bmid_base + SCC_DMA_STATUS;
- u32 reg = 0;
-
- out_be32(cckctrl_port, reg);
- reg |= CCKCTRL_ATACLKOEN;
- out_be32(cckctrl_port, reg);
- reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN;
- out_be32(cckctrl_port, reg);
- reg |= CCKCTRL_CRST;
- out_be32(cckctrl_port, reg);
-
- for (;;) {
- reg = in_be32(cckctrl_port);
- if (reg & CCKCTRL_CRST)
- break;
- udelay(5000);
- }
-
- reg |= CCKCTRL_ATARESET;
- out_be32(cckctrl_port, reg);
- out_be32(ecmode_port, ECMODE_VALUE);
- out_be32(mode_port, MODE_JCUSFEN);
- out_be32(intmask_port, INTMASK_MSK);
-
- if (in_be32(dmastatus_port) & QCHSD_STPDIAG) {
- printk(KERN_WARNING "%s: failed to detect 80c cable. (PDIAG# is high)\n", DRV_NAME);
- return -EIO;
- }
-
- return 0;
-}
-
-/**
- * scc_setup_ports - initialize ioaddr with SCC PATA port offsets.
- * @ioaddr: IO address structure to be initialized
- * @base: base address of BMID region
- */
-
-static void scc_setup_ports (struct ata_ioports *ioaddr, void __iomem *base)
-{
- ioaddr->cmd_addr = base + SCC_REG_CMD_ADDR;
- ioaddr->altstatus_addr = ioaddr->cmd_addr + SCC_REG_ALTSTATUS;
- ioaddr->ctl_addr = ioaddr->cmd_addr + SCC_REG_ALTSTATUS;
- ioaddr->bmdma_addr = base;
- ioaddr->data_addr = ioaddr->cmd_addr + SCC_REG_DATA;
- ioaddr->error_addr = ioaddr->cmd_addr + SCC_REG_ERR;
- ioaddr->feature_addr = ioaddr->cmd_addr + SCC_REG_FEATURE;
- ioaddr->nsect_addr = ioaddr->cmd_addr + SCC_REG_NSECT;
- ioaddr->lbal_addr = ioaddr->cmd_addr + SCC_REG_LBAL;
- ioaddr->lbam_addr = ioaddr->cmd_addr + SCC_REG_LBAM;
- ioaddr->lbah_addr = ioaddr->cmd_addr + SCC_REG_LBAH;
- ioaddr->device_addr = ioaddr->cmd_addr + SCC_REG_DEVICE;
- ioaddr->status_addr = ioaddr->cmd_addr + SCC_REG_STATUS;
- ioaddr->command_addr = ioaddr->cmd_addr + SCC_REG_CMD;
-}
-
-static int scc_host_init(struct ata_host *host)
-{
- struct pci_dev *pdev = to_pci_dev(host->dev);
- int rc;
-
- rc = scc_reset_controller(host);
- if (rc)
- return rc;
-
- rc = dma_set_mask(&pdev->dev, ATA_DMA_MASK);
- if (rc)
- return rc;
- rc = dma_set_coherent_mask(&pdev->dev, ATA_DMA_MASK);
- if (rc)
- return rc;
-
- scc_setup_ports(&host->ports[0]->ioaddr, host->iomap[SCC_BMID_BAR]);
-
- pci_set_master(pdev);
-
- return 0;
-}
-
-/**
- * scc_init_one - Register SCC PATA device with kernel services
- * @pdev: PCI device to register
- * @ent: Entry in scc_pci_tbl matching with @pdev
- *
- * LOCKING:
- * Inherited from PCI layer (may sleep).
- *
- * RETURNS:
- * Zero on success, or -ERRNO value.
- */
-
-static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
-{
- unsigned int board_idx = (unsigned int) ent->driver_data;
- const struct ata_port_info *ppi[] = { &scc_port_info[board_idx], NULL };
- struct ata_host *host;
- int rc;
-
- ata_print_version_once(&pdev->dev, DRV_VERSION);
-
- host = ata_host_alloc_pinfo(&pdev->dev, ppi, 1);
- if (!host)
- return -ENOMEM;
-
- rc = pcim_enable_device(pdev);
- if (rc)
- return rc;
-
- rc = pcim_iomap_regions(pdev, (1 << SCC_CTRL_BAR) | (1 << SCC_BMID_BAR), DRV_NAME);
- if (rc == -EBUSY)
- pcim_pin_device(pdev);
- if (rc)
- return rc;
- host->iomap = pcim_iomap_table(pdev);
-
- ata_port_pbar_desc(host->ports[0], SCC_CTRL_BAR, -1, "ctrl");
- ata_port_pbar_desc(host->ports[0], SCC_BMID_BAR, -1, "bmid");
-
- rc = scc_host_init(host);
- if (rc)
- return rc;
-
- return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
- IRQF_SHARED, &scc_sht);
-}
-
-static struct pci_driver scc_pci_driver = {
- .name = DRV_NAME,
- .id_table = scc_pci_tbl,
- .probe = scc_init_one,
- .remove = ata_pci_remove_one,
-#ifdef CONFIG_PM_SLEEP
- .suspend = ata_pci_device_suspend,
- .resume = ata_pci_device_resume,
-#endif
-};
-
-module_pci_driver(scc_pci_driver);
-
-MODULE_AUTHOR("Toshiba corp");
-MODULE_DESCRIPTION("SCSI low-level driver for Toshiba SCC PATA controller");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
-MODULE_VERSION(DRV_VERSION);
static void loop_remove(struct loop_device *lo)
{
- del_gendisk(lo->lo_disk);
blk_cleanup_queue(lo->lo_queue);
+ del_gendisk(lo->lo_disk);
blk_mq_free_tag_set(&lo->tag_set);
put_disk(lo->lo_disk);
kfree(lo);
static int nvme_trans_bdev_limits_page(struct nvme_ns *ns, struct sg_io_hdr *hdr,
u8 *inq_response, int alloc_len)
{
- __be32 max_sectors = cpu_to_be32(queue_max_hw_sectors(ns->queue));
+ __be32 max_sectors = cpu_to_be32(
+ nvme_block_nr(ns, queue_max_hw_sectors(ns->queue)));
__be32 max_discard = cpu_to_be32(ns->queue->limits.max_discard_sectors);
__be32 discard_desc_count = cpu_to_be32(0x100);
atomic_dec(&blkif->persistent_gnt_in_use);
}
-static void free_persistent_gnts_unmap_callback(int result,
- struct gntab_unmap_queue_data *data)
-{
- struct completion *c = data->data;
-
- /* BUG_ON used to reproduce existing behaviour,
- but is this the best way to deal with this? */
- BUG_ON(result);
- complete(c);
-}
-
static void free_persistent_gnts(struct xen_blkif *blkif, struct rb_root *root,
unsigned int num)
{
struct rb_node *n;
int segs_to_unmap = 0;
struct gntab_unmap_queue_data unmap_data;
- struct completion unmap_completion;
- init_completion(&unmap_completion);
-
- unmap_data.data = &unmap_completion;
- unmap_data.done = &free_persistent_gnts_unmap_callback;
unmap_data.pages = pages;
unmap_data.unmap_ops = unmap;
unmap_data.kunmap_ops = NULL;
!rb_next(&persistent_gnt->node)) {
unmap_data.count = segs_to_unmap;
- gnttab_unmap_refs_async(&unmap_data);
- wait_for_completion(&unmap_completion);
+ BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
put_free_pages(blkif, pages, segs_to_unmap);
segs_to_unmap = 0;
struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST];
struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST];
struct persistent_gnt *persistent_gnt;
- int ret, segs_to_unmap = 0;
+ int segs_to_unmap = 0;
struct xen_blkif *blkif = container_of(work, typeof(*blkif), persistent_purge_work);
+ struct gntab_unmap_queue_data unmap_data;
+
+ unmap_data.pages = pages;
+ unmap_data.unmap_ops = unmap;
+ unmap_data.kunmap_ops = NULL;
while(!list_empty(&blkif->persistent_purge_list)) {
persistent_gnt = list_first_entry(&blkif->persistent_purge_list,
pages[segs_to_unmap] = persistent_gnt->page;
if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST) {
- ret = gnttab_unmap_refs(unmap, NULL, pages,
- segs_to_unmap);
- BUG_ON(ret);
+ unmap_data.count = segs_to_unmap;
+ BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
put_free_pages(blkif, pages, segs_to_unmap);
segs_to_unmap = 0;
}
kfree(persistent_gnt);
}
if (segs_to_unmap > 0) {
- ret = gnttab_unmap_refs(unmap, NULL, pages, segs_to_unmap);
- BUG_ON(ret);
+ unmap_data.count = segs_to_unmap;
+ BUG_ON(gnttab_unmap_refs_sync(&unmap_data));
put_free_pages(blkif, pages, segs_to_unmap);
}
}
return (struct zram *)dev_to_disk(dev)->private_data;
}
+static ssize_t compact_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t len)
+{
+ unsigned long nr_migrated;
+ struct zram *zram = dev_to_zram(dev);
+ struct zram_meta *meta;
+
+ down_read(&zram->init_lock);
+ if (!init_done(zram)) {
+ up_read(&zram->init_lock);
+ return -EINVAL;
+ }
+
+ meta = zram->meta;
+ nr_migrated = zs_compact(meta->mem_pool);
+ atomic64_add(nr_migrated, &zram->stats.num_migrated);
+ up_read(&zram->init_lock);
+
+ return len;
+}
+
static ssize_t disksize_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
.owner = THIS_MODULE
};
+static DEVICE_ATTR_WO(compact);
static DEVICE_ATTR_RW(disksize);
static DEVICE_ATTR_RO(initstate);
static DEVICE_ATTR_WO(reset);
&dev_attr_num_writes.attr,
&dev_attr_failed_reads.attr,
&dev_attr_failed_writes.attr,
+ &dev_attr_compact.attr,
&dev_attr_invalid_io.attr,
&dev_attr_notify_free.attr,
&dev_attr_zero_pages.attr,
iobase = info->p_dev->resource[0]->start;
avail = bt3c_read(iobase, 0x7006);
- //printk("bt3c_cs: receiving %d bytes\n", avail);
bt3c_address(iobase, 0x7480);
while (size < avail) {
bt_cb(info->rx_skb)->pkt_type = inb(iobase + DATA_L);
inb(iobase + DATA_H);
- //printk("bt3c: PACKET_TYPE=%02x\n", bt_cb(info->rx_skb)->pkt_type);
switch (bt_cb(info->rx_skb)->pkt_type) {
if (stat & 0x0001)
bt3c_receive(info);
if (stat & 0x0002) {
- //BT_ERR("Ack (stat=0x%04x)", stat);
clear_bit(XMIT_SENDING, &(info->tx_state));
bt3c_write_wakeup(info);
}
}
EXPORT_SYMBOL_GPL(btbcm_set_bdaddr);
+int btbcm_patchram(struct hci_dev *hdev, const char *firmware)
+{
+ const struct hci_command_hdr *cmd;
+ const struct firmware *fw;
+ const u8 *fw_ptr;
+ size_t fw_size;
+ struct sk_buff *skb;
+ u16 opcode;
+ int err;
+
+ err = request_firmware(&fw, firmware, &hdev->dev);
+ if (err < 0) {
+ BT_INFO("%s: BCM: Patch %s not found", hdev->name, firmware);
+ return err;
+ }
+
+ /* Start Download */
+ skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: BCM: Download Minidrv command failed (%d)",
+ hdev->name, err);
+ goto done;
+ }
+ kfree_skb(skb);
+
+ /* 50 msec delay after Download Minidrv completes */
+ msleep(50);
+
+ fw_ptr = fw->data;
+ fw_size = fw->size;
+
+ while (fw_size >= sizeof(*cmd)) {
+ const u8 *cmd_param;
+
+ cmd = (struct hci_command_hdr *)fw_ptr;
+ fw_ptr += sizeof(*cmd);
+ fw_size -= sizeof(*cmd);
+
+ if (fw_size < cmd->plen) {
+ BT_ERR("%s: BCM: Patch %s is corrupted", hdev->name,
+ firmware);
+ err = -EINVAL;
+ goto done;
+ }
+
+ cmd_param = fw_ptr;
+ fw_ptr += cmd->plen;
+ fw_size -= cmd->plen;
+
+ opcode = le16_to_cpu(cmd->opcode);
+
+ skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: BCM: Patch command %04x failed (%d)",
+ hdev->name, opcode, err);
+ goto done;
+ }
+ kfree_skb(skb);
+ }
+
+ /* 250 msec delay after Launch Ram completes */
+ msleep(250);
+
+done:
+ release_firmware(fw);
+ return err;
+}
+EXPORT_SYMBOL(btbcm_patchram);
+
static int btbcm_reset(struct hci_dev *hdev)
{
struct sk_buff *skb;
int btbcm_setup_patchram(struct hci_dev *hdev)
{
- const struct hci_command_hdr *cmd;
- const struct firmware *fw;
- const u8 *fw_ptr;
- size_t fw_size;
char fw_name[64];
- u16 opcode, subver, rev, pid, vid;
+ u16 subver, rev, pid, vid;
const char *hw_name = NULL;
struct sk_buff *skb;
struct hci_rp_read_local_version *ver;
hw_name ? : "BCM", (subver & 0x7000) >> 13,
(subver & 0x1f00) >> 8, (subver & 0x00ff), rev & 0x0fff);
- err = request_firmware(&fw, fw_name, &hdev->dev);
- if (err < 0) {
- BT_INFO("%s: BCM: patch %s not found", hdev->name, fw_name);
+ err = btbcm_patchram(hdev, fw_name);
+ if (err == -ENOENT)
return 0;
- }
-
- /* Start Download */
- skb = __hci_cmd_sync(hdev, 0xfc2e, 0, NULL, HCI_INIT_TIMEOUT);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
- BT_ERR("%s: BCM: Download Minidrv command failed (%d)",
- hdev->name, err);
- goto reset;
- }
- kfree_skb(skb);
-
- /* 50 msec delay after Download Minidrv completes */
- msleep(50);
-
- fw_ptr = fw->data;
- fw_size = fw->size;
-
- while (fw_size >= sizeof(*cmd)) {
- const u8 *cmd_param;
-
- cmd = (struct hci_command_hdr *)fw_ptr;
- fw_ptr += sizeof(*cmd);
- fw_size -= sizeof(*cmd);
-
- if (fw_size < cmd->plen) {
- BT_ERR("%s: BCM: patch %s is corrupted", hdev->name,
- fw_name);
- err = -EINVAL;
- goto reset;
- }
- cmd_param = fw_ptr;
- fw_ptr += cmd->plen;
- fw_size -= cmd->plen;
-
- opcode = le16_to_cpu(cmd->opcode);
-
- skb = __hci_cmd_sync(hdev, opcode, cmd->plen, cmd_param,
- HCI_INIT_TIMEOUT);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
- BT_ERR("%s: BCM: patch command %04x failed (%d)",
- hdev->name, opcode, err);
- goto reset;
- }
- kfree_skb(skb);
- }
-
- /* 250 msec delay after Launch Ram completes */
- msleep(250);
-
-reset:
/* Reset */
err = btbcm_reset(hdev);
if (err)
- goto done;
+ return err;
/* Read Local Version Info */
skb = btbcm_read_local_version(hdev);
- if (IS_ERR(skb)) {
- err = PTR_ERR(skb);
- goto done;
- }
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
ver = (struct hci_rp_read_local_version *)skb->data;
rev = le16_to_cpu(ver->hci_rev);
set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
-done:
- release_firmware(fw);
-
- return err;
+ return 0;
}
EXPORT_SYMBOL_GPL(btbcm_setup_patchram);
int btbcm_check_bdaddr(struct hci_dev *hdev);
int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr);
+int btbcm_patchram(struct hci_dev *hdev, const char *firmware);
int btbcm_setup_patchram(struct hci_dev *hdev);
int btbcm_setup_apple(struct hci_dev *hdev);
return -EOPNOTSUPP;
}
+static inline int btbcm_patchram(struct hci_dev *hdev, const char *firmware)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int btbcm_setup_patchram(struct hci_dev *hdev)
{
return 0;
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/firmware.h>
+#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#define BTUSB_AMP 0x4000
#define BTUSB_QCA_ROME 0x8000
#define BTUSB_BCM_APPLE 0x10000
+#define BTUSB_REALTEK 0x20000
static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
.driver_info = BTUSB_IGNORE },
+ /* Realtek Bluetooth devices */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x0bda, 0xe0, 0x01, 0x01),
+ .driver_info = BTUSB_REALTEK },
+
+ /* Additional Realtek 8723AE Bluetooth devices */
+ { USB_DEVICE(0x0930, 0x021d), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3394), .driver_info = BTUSB_REALTEK },
+
+ /* Additional Realtek 8723BE Bluetooth devices */
+ { USB_DEVICE(0x0489, 0xe085), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x0489, 0xe08b), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
+
+ /* Additional Realtek 8821AE Bluetooth devices */
+ { USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3458), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
+
{ } /* Terminating entry */
};
*/
if (data->setup_on_usb) {
err = data->setup_on_usb(hdev);
- if (err <0)
+ if (err < 0)
return err;
}
return ret;
}
+#define RTL_FRAG_LEN 252
+
+struct rtl_download_cmd {
+ __u8 index;
+ __u8 data[RTL_FRAG_LEN];
+} __packed;
+
+struct rtl_download_response {
+ __u8 status;
+ __u8 index;
+} __packed;
+
+struct rtl_rom_version_evt {
+ __u8 status;
+ __u8 version;
+} __packed;
+
+struct rtl_epatch_header {
+ __u8 signature[8];
+ __le32 fw_version;
+ __le16 num_patches;
+} __packed;
+
+#define RTL_EPATCH_SIGNATURE "Realtech"
+#define RTL_ROM_LMP_3499 0x3499
+#define RTL_ROM_LMP_8723A 0x1200
+#define RTL_ROM_LMP_8723B 0x8723
+#define RTL_ROM_LMP_8821A 0x8821
+#define RTL_ROM_LMP_8761A 0x8761
+
+static int rtl_read_rom_version(struct hci_dev *hdev, u8 *version)
+{
+ struct rtl_rom_version_evt *rom_version;
+ struct sk_buff *skb;
+ int ret;
+
+ /* Read RTL ROM version command */
+ skb = __hci_cmd_sync(hdev, 0xfc6d, 0, NULL, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ BT_ERR("%s: Read ROM version failed (%ld)",
+ hdev->name, PTR_ERR(skb));
+ return PTR_ERR(skb);
+ }
+
+ if (skb->len != sizeof(*rom_version)) {
+ BT_ERR("%s: RTL version event length mismatch", hdev->name);
+ kfree_skb(skb);
+ return -EIO;
+ }
+
+ rom_version = (struct rtl_rom_version_evt *)skb->data;
+ BT_INFO("%s: rom_version status=%x version=%x",
+ hdev->name, rom_version->status, rom_version->version);
+
+ ret = rom_version->status;
+ if (ret == 0)
+ *version = rom_version->version;
+
+ kfree_skb(skb);
+ return ret;
+}
+
+static int rtl8723b_parse_firmware(struct hci_dev *hdev, u16 lmp_subver,
+ const struct firmware *fw,
+ unsigned char **_buf)
+{
+ const u8 extension_sig[] = { 0x51, 0x04, 0xfd, 0x77 };
+ struct rtl_epatch_header *epatch_info;
+ unsigned char *buf;
+ int i, ret, len;
+ size_t min_size;
+ u8 opcode, length, data, rom_version = 0;
+ int project_id = -1;
+ const unsigned char *fwptr, *chip_id_base;
+ const unsigned char *patch_length_base, *patch_offset_base;
+ u32 patch_offset = 0;
+ u16 patch_length, num_patches;
+ const u16 project_id_to_lmp_subver[] = {
+ RTL_ROM_LMP_8723A,
+ RTL_ROM_LMP_8723B,
+ RTL_ROM_LMP_8821A,
+ RTL_ROM_LMP_8761A
+ };
+
+ ret = rtl_read_rom_version(hdev, &rom_version);
+ if (ret)
+ return -bt_to_errno(ret);
+
+ min_size = sizeof(struct rtl_epatch_header) + sizeof(extension_sig) + 3;
+ if (fw->size < min_size)
+ return -EINVAL;
+
+ fwptr = fw->data + fw->size - sizeof(extension_sig);
+ if (memcmp(fwptr, extension_sig, sizeof(extension_sig)) != 0) {
+ BT_ERR("%s: extension section signature mismatch", hdev->name);
+ return -EINVAL;
+ }
+
+ /* Loop from the end of the firmware parsing instructions, until
+ * we find an instruction that identifies the "project ID" for the
+ * hardware supported by this firwmare file.
+ * Once we have that, we double-check that that project_id is suitable
+ * for the hardware we are working with.
+ */
+ while (fwptr >= fw->data + (sizeof(struct rtl_epatch_header) + 3)) {
+ opcode = *--fwptr;
+ length = *--fwptr;
+ data = *--fwptr;
+
+ BT_DBG("check op=%x len=%x data=%x", opcode, length, data);
+
+ if (opcode == 0xff) /* EOF */
+ break;
+
+ if (length == 0) {
+ BT_ERR("%s: found instruction with length 0",
+ hdev->name);
+ return -EINVAL;
+ }
+
+ if (opcode == 0 && length == 1) {
+ project_id = data;
+ break;
+ }
+
+ fwptr -= length;
+ }
+
+ if (project_id < 0) {
+ BT_ERR("%s: failed to find version instruction", hdev->name);
+ return -EINVAL;
+ }
+
+ if (project_id >= ARRAY_SIZE(project_id_to_lmp_subver)) {
+ BT_ERR("%s: unknown project id %d", hdev->name, project_id);
+ return -EINVAL;
+ }
+
+ if (lmp_subver != project_id_to_lmp_subver[project_id]) {
+ BT_ERR("%s: firmware is for %x but this is a %x", hdev->name,
+ project_id_to_lmp_subver[project_id], lmp_subver);
+ return -EINVAL;
+ }
+
+ epatch_info = (struct rtl_epatch_header *)fw->data;
+ if (memcmp(epatch_info->signature, RTL_EPATCH_SIGNATURE, 8) != 0) {
+ BT_ERR("%s: bad EPATCH signature", hdev->name);
+ return -EINVAL;
+ }
+
+ num_patches = le16_to_cpu(epatch_info->num_patches);
+ BT_DBG("fw_version=%x, num_patches=%d",
+ le32_to_cpu(epatch_info->fw_version), num_patches);
+
+ /* After the rtl_epatch_header there is a funky patch metadata section.
+ * Assuming 2 patches, the layout is:
+ * ChipID1 ChipID2 PatchLength1 PatchLength2 PatchOffset1 PatchOffset2
+ *
+ * Find the right patch for this chip.
+ */
+ min_size += 8 * num_patches;
+ if (fw->size < min_size)
+ return -EINVAL;
+
+ chip_id_base = fw->data + sizeof(struct rtl_epatch_header);
+ patch_length_base = chip_id_base + (sizeof(u16) * num_patches);
+ patch_offset_base = patch_length_base + (sizeof(u16) * num_patches);
+ for (i = 0; i < num_patches; i++) {
+ u16 chip_id = get_unaligned_le16(chip_id_base +
+ (i * sizeof(u16)));
+ if (chip_id == rom_version + 1) {
+ patch_length = get_unaligned_le16(patch_length_base +
+ (i * sizeof(u16)));
+ patch_offset = get_unaligned_le32(patch_offset_base +
+ (i * sizeof(u32)));
+ break;
+ }
+ }
+
+ if (!patch_offset) {
+ BT_ERR("%s: didn't find patch for chip id %d",
+ hdev->name, rom_version);
+ return -EINVAL;
+ }
+
+ BT_DBG("length=%x offset=%x index %d", patch_length, patch_offset, i);
+ min_size = patch_offset + patch_length;
+ if (fw->size < min_size)
+ return -EINVAL;
+
+ /* Copy the firmware into a new buffer and write the version at
+ * the end.
+ */
+ len = patch_length;
+ buf = kmemdup(fw->data + patch_offset, patch_length, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy(buf + patch_length - 4, &epatch_info->fw_version, 4);
+
+ *_buf = buf;
+ return len;
+}
+
+static int rtl_download_firmware(struct hci_dev *hdev,
+ const unsigned char *data, int fw_len)
+{
+ struct rtl_download_cmd *dl_cmd;
+ int frag_num = fw_len / RTL_FRAG_LEN + 1;
+ int frag_len = RTL_FRAG_LEN;
+ int ret = 0;
+ int i;
+
+ dl_cmd = kmalloc(sizeof(struct rtl_download_cmd), GFP_KERNEL);
+ if (!dl_cmd)
+ return -ENOMEM;
+
+ for (i = 0; i < frag_num; i++) {
+ struct rtl_download_response *dl_resp;
+ struct sk_buff *skb;
+
+ BT_DBG("download fw (%d/%d)", i, frag_num);
+
+ dl_cmd->index = i;
+ if (i == (frag_num - 1)) {
+ dl_cmd->index |= 0x80; /* data end */
+ frag_len = fw_len % RTL_FRAG_LEN;
+ }
+ memcpy(dl_cmd->data, data, frag_len);
+
+ /* Send download command */
+ skb = __hci_cmd_sync(hdev, 0xfc20, frag_len + 1, dl_cmd,
+ HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ BT_ERR("%s: download fw command failed (%ld)",
+ hdev->name, PTR_ERR(skb));
+ ret = -PTR_ERR(skb);
+ goto out;
+ }
+
+ if (skb->len != sizeof(*dl_resp)) {
+ BT_ERR("%s: download fw event length mismatch",
+ hdev->name);
+ kfree_skb(skb);
+ ret = -EIO;
+ goto out;
+ }
+
+ dl_resp = (struct rtl_download_response *)skb->data;
+ if (dl_resp->status != 0) {
+ kfree_skb(skb);
+ ret = bt_to_errno(dl_resp->status);
+ goto out;
+ }
+
+ kfree_skb(skb);
+ data += RTL_FRAG_LEN;
+ }
+
+out:
+ kfree(dl_cmd);
+ return ret;
+}
+
+static int btusb_setup_rtl8723a(struct hci_dev *hdev)
+{
+ struct btusb_data *data = dev_get_drvdata(&hdev->dev);
+ struct usb_device *udev = interface_to_usbdev(data->intf);
+ const struct firmware *fw;
+ int ret;
+
+ BT_INFO("%s: rtl: loading rtl_bt/rtl8723a_fw.bin", hdev->name);
+ ret = request_firmware(&fw, "rtl_bt/rtl8723a_fw.bin", &udev->dev);
+ if (ret < 0) {
+ BT_ERR("%s: Failed to load rtl_bt/rtl8723a_fw.bin", hdev->name);
+ return ret;
+ }
+
+ if (fw->size < 8) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Check that the firmware doesn't have the epatch signature
+ * (which is only for RTL8723B and newer).
+ */
+ if (!memcmp(fw->data, RTL_EPATCH_SIGNATURE, 8)) {
+ BT_ERR("%s: unexpected EPATCH signature!", hdev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = rtl_download_firmware(hdev, fw->data, fw->size);
+
+out:
+ release_firmware(fw);
+ return ret;
+}
+
+static int btusb_setup_rtl8723b(struct hci_dev *hdev, u16 lmp_subver,
+ const char *fw_name)
+{
+ struct btusb_data *data = dev_get_drvdata(&hdev->dev);
+ struct usb_device *udev = interface_to_usbdev(data->intf);
+ unsigned char *fw_data = NULL;
+ const struct firmware *fw;
+ int ret;
+
+ BT_INFO("%s: rtl: loading %s", hdev->name, fw_name);
+ ret = request_firmware(&fw, fw_name, &udev->dev);
+ if (ret < 0) {
+ BT_ERR("%s: Failed to load %s", hdev->name, fw_name);
+ return ret;
+ }
+
+ ret = rtl8723b_parse_firmware(hdev, lmp_subver, fw, &fw_data);
+ if (ret < 0)
+ goto out;
+
+ ret = rtl_download_firmware(hdev, fw_data, ret);
+ kfree(fw_data);
+ if (ret < 0)
+ goto out;
+
+out:
+ release_firmware(fw);
+ return ret;
+}
+
+static int btusb_setup_realtek(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+ struct hci_rp_read_local_version *resp;
+ u16 lmp_subver;
+
+ skb = btusb_read_local_version(hdev);
+ if (IS_ERR(skb))
+ return -PTR_ERR(skb);
+
+ resp = (struct hci_rp_read_local_version *)skb->data;
+ BT_INFO("%s: rtl: examining hci_ver=%02x hci_rev=%04x lmp_ver=%02x "
+ "lmp_subver=%04x", hdev->name, resp->hci_ver, resp->hci_rev,
+ resp->lmp_ver, resp->lmp_subver);
+
+ lmp_subver = le16_to_cpu(resp->lmp_subver);
+ kfree_skb(skb);
+
+ /* Match a set of subver values that correspond to stock firmware,
+ * which is not compatible with standard btusb.
+ * If matched, upload an alternative firmware that does conform to
+ * standard btusb. Once that firmware is uploaded, the subver changes
+ * to a different value.
+ */
+ switch (lmp_subver) {
+ case RTL_ROM_LMP_8723A:
+ case RTL_ROM_LMP_3499:
+ return btusb_setup_rtl8723a(hdev);
+ case RTL_ROM_LMP_8723B:
+ return btusb_setup_rtl8723b(hdev, lmp_subver,
+ "rtl_bt/rtl8723b_fw.bin");
+ case RTL_ROM_LMP_8821A:
+ return btusb_setup_rtl8723b(hdev, lmp_subver,
+ "rtl_bt/rtl8821a_fw.bin");
+ case RTL_ROM_LMP_8761A:
+ return btusb_setup_rtl8723b(hdev, lmp_subver,
+ "rtl_bt/rtl8761a_fw.bin");
+ default:
+ BT_INFO("rtl: assuming no firmware upload needed.");
+ return 0;
+ }
+}
+
static const struct firmware *btusb_setup_intel_get_fw(struct hci_dev *hdev,
struct intel_version *ver)
{
int i, err;
err = btusb_qca_send_vendor_req(hdev, QCA_GET_TARGET_VERSION, &ver,
- sizeof(ver));
+ sizeof(ver));
if (err < 0)
return err;
hdev->set_bdaddr = btusb_set_bdaddr_ath3012;
}
+ if (id->driver_info & BTUSB_REALTEK)
+ hdev->setup = btusb_setup_realtek;
+
if (id->driver_info & BTUSB_AMP) {
/* AMP controllers do not support SCO packets */
data->isoc = NULL;
hci_uart_tx_wakeup(hu);
}
-/* Initialize protocol */
static int ath_open(struct hci_uart *hu)
{
struct ath_struct *ath;
return 0;
}
-/* Flush protocol data */
-static int ath_flush(struct hci_uart *hu)
+static int ath_close(struct hci_uart *hu)
{
struct ath_struct *ath = hu->priv;
skb_queue_purge(&ath->txq);
+ kfree_skb(ath->rx_skb);
+
+ cancel_work_sync(&ath->ctxtsw);
+
+ hu->priv = NULL;
+ kfree(ath);
+
return 0;
}
-/* Close protocol */
-static int ath_close(struct hci_uart *hu)
+static int ath_flush(struct hci_uart *hu)
{
struct ath_struct *ath = hu->priv;
skb_queue_purge(&ath->txq);
- kfree_skb(ath->rx_skb);
+ return 0;
+}
- cancel_work_sync(&ath->ctxtsw);
+static int ath_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
+{
+ struct sk_buff *skb;
+ u8 buf[10];
+ int err;
+
+ buf[0] = 0x01;
+ buf[1] = 0x01;
+ buf[2] = 0x00;
+ buf[3] = sizeof(bdaddr_t);
+ memcpy(buf + 4, bdaddr, sizeof(bdaddr_t));
+
+ skb = __hci_cmd_sync(hdev, 0xfc0b, sizeof(buf), buf, HCI_INIT_TIMEOUT);
+ if (IS_ERR(skb)) {
+ err = PTR_ERR(skb);
+ BT_ERR("%s: Change address command failed (%d)",
+ hdev->name, err);
+ return err;
+ }
+ kfree_skb(skb);
- hu->priv = NULL;
- kfree(ath);
+ return 0;
+}
+
+static int ath_setup(struct hci_uart *hu)
+{
+ BT_DBG("hu %p", hu);
+
+ hu->hdev->set_bdaddr = ath_set_bdaddr;
return 0;
}
+static const struct h4_recv_pkt ath_recv_pkts[] = {
+ { H4_RECV_ACL, .recv = hci_recv_frame },
+ { H4_RECV_SCO, .recv = hci_recv_frame },
+ { H4_RECV_EVENT, .recv = hci_recv_frame },
+};
+
+static int ath_recv(struct hci_uart *hu, const void *data, int count)
+{
+ struct ath_struct *ath = hu->priv;
+
+ ath->rx_skb = h4_recv_buf(hu->hdev, ath->rx_skb, data, count,
+ ath_recv_pkts, ARRAY_SIZE(ath_recv_pkts));
+ if (IS_ERR(ath->rx_skb)) {
+ int err = PTR_ERR(ath->rx_skb);
+ BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err);
+ return err;
+ }
+
+ return count;
+}
+
#define HCI_OP_ATH_SLEEP 0xFC04
-/* Enqueue frame for transmittion */
static int ath_enqueue(struct hci_uart *hu, struct sk_buff *skb)
{
struct ath_struct *ath = hu->priv;
return 0;
}
- /*
- * Update power management enable flag with parameters of
+ /* Update power management enable flag with parameters of
* HCI sleep enable vendor specific HCI command.
*/
if (bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) {
return skb_dequeue(&ath->txq);
}
-static const struct h4_recv_pkt ath_recv_pkts[] = {
- { H4_RECV_ACL, .recv = hci_recv_frame },
- { H4_RECV_SCO, .recv = hci_recv_frame },
- { H4_RECV_EVENT, .recv = hci_recv_frame },
-};
-
-/* Recv data */
-static int ath_recv(struct hci_uart *hu, const void *data, int count)
-{
- struct ath_struct *ath = hu->priv;
-
- ath->rx_skb = h4_recv_buf(hu->hdev, ath->rx_skb, data, count,
- ath_recv_pkts, ARRAY_SIZE(ath_recv_pkts));
- if (IS_ERR(ath->rx_skb)) {
- int err = PTR_ERR(ath->rx_skb);
- BT_ERR("%s: Frame reassembly failed (%d)", hu->hdev->name, err);
- return err;
- }
-
- return count;
-}
-
static const struct hci_uart_proto athp = {
.id = HCI_UART_ATH3K,
.name = "ATH3K",
.open = ath_open,
.close = ath_close,
+ .flush = ath_flush,
+ .setup = ath_setup,
.recv = ath_recv,
.enqueue = ath_enqueue,
.dequeue = ath_dequeue,
- .flush = ath_flush,
};
int __init ath_init(void)
* Initialise the fake PMU. We only need to populate the
* used_mask for the purposes of validation.
*/
- .used_mask = CPU_BITS_NONE,
+ .used_mask = { 0 },
};
if (!validate_event(event->pmu, &fake_pmu, leader))
/*
* OMAP L3 Interconnect error handling driver
*
- * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2011-2015 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <santosh.shilimkar@ti.com>
* Sricharan <r.sricharan@ti.com>
*
}
static const struct of_device_id l3_noc_match[] = {
- {.compatible = "ti,omap4-l3-noc", .data = &omap_l3_data},
+ {.compatible = "ti,omap4-l3-noc", .data = &omap4_l3_data},
+ {.compatible = "ti,omap5-l3-noc", .data = &omap5_l3_data},
{.compatible = "ti,dra7-l3-noc", .data = &dra_l3_data},
{.compatible = "ti,am4372-l3-noc", .data = &am4372_l3_data},
{},
/*
* OMAP L3 Interconnect error handling driver header
*
- * Copyright (C) 2011-2014 Texas Instruments Incorporated - http://www.ti.com/
+ * Copyright (C) 2011-2015 Texas Instruments Incorporated - http://www.ti.com/
* Santosh Shilimkar <santosh.shilimkar@ti.com>
* sricharan <r.sricharan@ti.com>
*
};
-static struct l3_target_data omap_l3_target_data_clk3[] = {
- {0x0100, "EMUSS",},
- {0x0300, "DEBUG SOURCE",},
- {0x0, "HOST CLK3",},
+static struct l3_target_data omap4_l3_target_data_clk3[] = {
+ {0x0100, "DEBUGSS",},
};
-static struct l3_flagmux_data omap_l3_flagmux_clk3 = {
+static struct l3_flagmux_data omap4_l3_flagmux_clk3 = {
.offset = 0x0200,
- .l3_targ = omap_l3_target_data_clk3,
- .num_targ_data = ARRAY_SIZE(omap_l3_target_data_clk3),
+ .l3_targ = omap4_l3_target_data_clk3,
+ .num_targ_data = ARRAY_SIZE(omap4_l3_target_data_clk3),
};
static struct l3_masters_data omap_l3_masters[] = {
{ 0x32, "USBHOSTFS"}
};
-static struct l3_flagmux_data *omap_l3_flagmux[] = {
+static struct l3_flagmux_data *omap4_l3_flagmux[] = {
&omap_l3_flagmux_clk1,
&omap_l3_flagmux_clk2,
- &omap_l3_flagmux_clk3,
+ &omap4_l3_flagmux_clk3,
};
-static const struct omap_l3 omap_l3_data = {
- .l3_flagmux = omap_l3_flagmux,
- .num_modules = ARRAY_SIZE(omap_l3_flagmux),
+static const struct omap_l3 omap4_l3_data = {
+ .l3_flagmux = omap4_l3_flagmux,
+ .num_modules = ARRAY_SIZE(omap4_l3_flagmux),
.l3_masters = omap_l3_masters,
.num_masters = ARRAY_SIZE(omap_l3_masters),
/* The 6 MSBs of register field used to distinguish initiator */
.mst_addr_mask = 0xFC,
};
+/* OMAP5 data */
+static struct l3_target_data omap5_l3_target_data_clk3[] = {
+ {0x0100, "L3INSTR",},
+ {0x0300, "DEBUGSS",},
+ {0x0, "HOSTCLK3",},
+};
+
+static struct l3_flagmux_data omap5_l3_flagmux_clk3 = {
+ .offset = 0x0200,
+ .l3_targ = omap5_l3_target_data_clk3,
+ .num_targ_data = ARRAY_SIZE(omap5_l3_target_data_clk3),
+};
+
+static struct l3_flagmux_data *omap5_l3_flagmux[] = {
+ &omap_l3_flagmux_clk1,
+ &omap_l3_flagmux_clk2,
+ &omap5_l3_flagmux_clk3,
+};
+
+static const struct omap_l3 omap5_l3_data = {
+ .l3_flagmux = omap5_l3_flagmux,
+ .num_modules = ARRAY_SIZE(omap5_l3_flagmux),
+ .l3_masters = omap_l3_masters,
+ .num_masters = ARRAY_SIZE(omap_l3_masters),
+ /* The 6 MSBs of register field used to distinguish initiator */
+ .mst_addr_mask = 0x7E0,
+};
+
/* DRA7 data */
static struct l3_target_data dra_l3_target_data_clk1[] = {
{0x2a00, "AES1",},
static struct l3_target_data dra_l3_target_data_clk2[] = {
{0x0, "HOST CLK1",},
- {0x0, "HOST CLK2",},
+ {0x800000, "HOST CLK2",},
{0xdead, L3_TARGET_NOT_SUPPORTED,},
{0x3400, "SHA2_2",},
{0x0900, "BB2D",},
val &= ~RNG_EN;
__raw_writel(val, priv->regs + RNG_CTRL);
- clk_didsable_unprepare(prov->clk);
+ clk_disable_unprepare(priv->clk);
}
static int bcm63xx_rng_data_present(struct hwrng *rng, int wait)
priv->rng.name = pdev->name;
priv->rng.init = bcm63xx_rng_init;
priv->rng.cleanup = bcm63xx_rng_cleanup;
- prov->rng.data_present = bcm63xx_rng_data_present;
+ priv->rng.data_present = bcm63xx_rng_data_present;
priv->rng.data_read = bcm63xx_rng_data_read;
priv->clk = devm_clk_get(&pdev->dev, "ipsec");
if (IS_ERR(priv->clk)) {
- error = PTR_ERR(priv->clk);
- dev_err(&pdev->dev, "no clock for device: %d\n", error);
- return error;
+ ret = PTR_ERR(priv->clk);
+ dev_err(&pdev->dev, "no clock for device: %d\n", ret);
+ return ret;
}
if (!devm_request_mem_region(&pdev->dev, r->start,
return -ENOMEM;
}
- error = devm_hwrng_register(&pdev->dev, &priv->rng);
- if (error) {
+ ret = devm_hwrng_register(&pdev->dev, &priv->rng);
+ if (ret) {
dev_err(&pdev->dev, "failed to register rng device: %d\n",
- error);
- return error;
+ ret);
+ return ret;
}
dev_info(&pdev->dev, "registered RNG driver\n");
seq_printf(m, " %x", intf->channels[i].address);
seq_putc(m, '\n');
- return seq_has_overflowed(m);
+ return 0;
}
static int smi_ipmb_proc_open(struct inode *inode, struct file *file)
ipmi_version_major(&intf->bmc->id),
ipmi_version_minor(&intf->bmc->id));
- return seq_has_overflowed(m);
+ return 0;
}
static int smi_version_proc_open(struct inode *inode, struct file *file)
* If we are running to completion, start it and run
* transactions until everything is clear.
*/
- smi_info->curr_msg = msg;
- smi_info->waiting_msg = NULL;
+ smi_info->waiting_msg = msg;
/*
* Run to completion means we are single-threaded, no
acpi_handle handle;
acpi_status status;
unsigned long long tmp;
- int rv;
+ int rv = -EINVAL;
acpi_dev = pnp_acpi_device(dev);
if (!acpi_dev)
/* _IFT tells us the interface type: KCS, BT, etc */
status = acpi_evaluate_integer(handle, "_IFT", NULL, &tmp);
- if (ACPI_FAILURE(status))
+ if (ACPI_FAILURE(status)) {
+ dev_err(&dev->dev, "Could not find ACPI IPMI interface type\n");
goto err_free;
+ }
switch (tmp) {
case 1:
info->si_type = SI_BT;
break;
case 4: /* SSIF, just ignore */
+ rv = -ENODEV;
goto err_free;
default:
dev_info(&dev->dev, "unknown IPMI type %lld\n", tmp);
err_free:
kfree(info);
- return -EINVAL;
+ return rv;
}
static void ipmi_pnp_remove(struct pnp_dev *dev)
seq_printf(m, "%s\n", si_to_str[smi->si_type]);
- return seq_has_overflowed(m);
+ return 0;
}
static int smi_type_proc_open(struct inode *inode, struct file *file)
smi->irq,
smi->slave_addr);
- return seq_has_overflowed(m);
+ return 0;
}
static int smi_params_proc_open(struct inode *inode, struct file *file)
* interface into the I2C driver, I believe.
*/
-#include <linux/version.h>
#if defined(MODVERSIONS)
#include <linux/modversions.h>
#endif
/* Number of watchdog pretimeouts. */
SSIF_STAT_watchdog_pretimeouts,
+ /* Number of alers received. */
+ SSIF_STAT_alerts,
+
/* Always add statistics before this value, it must be last. */
SSIF_NUM_STATS
};
#define WDT_PRE_TIMEOUT_INT 0x08
unsigned char msg_flags;
+ u8 global_enables;
bool has_event_buffer;
+ bool supports_alert;
+
+ /*
+ * Used to tell what we should do with alerts. If we are
+ * waiting on a response, read the data immediately.
+ */
+ bool got_alert;
+ bool waiting_alert;
/*
* If set to true, this will request events the next time the
if (ssif_info->i2c_read_write == I2C_SMBUS_WRITE) {
result = i2c_smbus_write_block_data(
- ssif_info->client, SSIF_IPMI_REQUEST,
+ ssif_info->client, ssif_info->i2c_command,
ssif_info->i2c_data[0],
ssif_info->i2c_data + 1);
ssif_info->done_handler(ssif_info, result, NULL, 0);
} else {
result = i2c_smbus_read_block_data(
- ssif_info->client, SSIF_IPMI_RESPONSE,
+ ssif_info->client, ssif_info->i2c_command,
ssif_info->i2c_data);
if (result < 0)
ssif_info->done_handler(ssif_info, result,
static void msg_done_handler(struct ssif_info *ssif_info, int result,
unsigned char *data, unsigned int len);
-static void retry_timeout(unsigned long data)
+static void start_get(struct ssif_info *ssif_info)
{
- struct ssif_info *ssif_info = (void *) data;
int rv;
- if (ssif_info->stopping)
- return;
-
ssif_info->rtc_us_timer = 0;
+ ssif_info->multi_pos = 0;
rv = ssif_i2c_send(ssif_info, msg_done_handler, I2C_SMBUS_READ,
SSIF_IPMI_RESPONSE,
}
}
+static void retry_timeout(unsigned long data)
+{
+ struct ssif_info *ssif_info = (void *) data;
+ unsigned long oflags, *flags;
+ bool waiting;
+
+ if (ssif_info->stopping)
+ return;
+
+ flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+ waiting = ssif_info->waiting_alert;
+ ssif_info->waiting_alert = false;
+ ipmi_ssif_unlock_cond(ssif_info, flags);
+
+ if (waiting)
+ start_get(ssif_info);
+}
+
+
+static void ssif_alert(struct i2c_client *client, unsigned int data)
+{
+ struct ssif_info *ssif_info = i2c_get_clientdata(client);
+ unsigned long oflags, *flags;
+ bool do_get = false;
+
+ ssif_inc_stat(ssif_info, alerts);
+
+ flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+ if (ssif_info->waiting_alert) {
+ ssif_info->waiting_alert = false;
+ del_timer(&ssif_info->retry_timer);
+ do_get = true;
+ } else if (ssif_info->curr_msg) {
+ ssif_info->got_alert = true;
+ }
+ ipmi_ssif_unlock_cond(ssif_info, flags);
+ if (do_get)
+ start_get(ssif_info);
+}
+
static int start_resend(struct ssif_info *ssif_info);
static void msg_done_handler(struct ssif_info *ssif_info, int result,
if (ssif_info->retries_left > 0) {
ssif_inc_stat(ssif_info, receive_retries);
+ flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+ ssif_info->waiting_alert = true;
+ ssif_info->rtc_us_timer = SSIF_MSG_USEC;
mod_timer(&ssif_info->retry_timer,
jiffies + SSIF_MSG_JIFFIES);
- ssif_info->rtc_us_timer = SSIF_MSG_USEC;
+ ipmi_ssif_unlock_cond(ssif_info, flags);
return;
}
ssif_inc_stat(ssif_info, received_message_parts);
/* Remove the multi-part read marker. */
- for (i = 0; i < (len-2); i++)
- ssif_info->data[i] = data[i+2];
len -= 2;
+ for (i = 0; i < len; i++)
+ ssif_info->data[i] = data[i+2];
ssif_info->multi_len = len;
ssif_info->multi_pos = 1;
goto continue_op;
}
- blocknum = data[ssif_info->multi_len];
+ blocknum = data[0];
- if (ssif_info->multi_len+len-1 > IPMI_MAX_MSG_LENGTH) {
+ if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) {
/* Received message too big, abort the operation. */
result = -E2BIG;
if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
}
/* Remove the blocknum from the data. */
- for (i = 0; i < (len-1); i++)
- ssif_info->data[i+ssif_info->multi_len] = data[i+1];
len--;
+ for (i = 0; i < len; i++)
+ ssif_info->data[i + ssif_info->multi_len] = data[i + 1];
ssif_info->multi_len += len;
if (blocknum == 0xff) {
/* End of read */
len = ssif_info->multi_len;
data = ssif_info->data;
- } else if ((blocknum+1) != ssif_info->multi_pos) {
+ } else if (blocknum + 1 != ssif_info->multi_pos) {
/*
* Out of sequence block, just abort. Block
* numbers start at zero for the second block,
if (rv < 0) {
if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
pr_info(PFX
- "Error from i2c_non_blocking_op(2)\n");
+ "Error from ssif_i2c_send\n");
result = -EIO;
} else
}
if (ssif_info->multi_data) {
- /* In the middle of a multi-data write. */
+ /*
+ * In the middle of a multi-data write. See the comment
+ * in the SSIF_MULTI_n_PART case in the probe function
+ * for details on the intricacies of this.
+ */
int left;
ssif_inc_stat(ssif_info, sent_messages_parts);
msg_done_handler(ssif_info, -EIO, NULL, 0);
}
} else {
+ unsigned long oflags, *flags;
+ bool got_alert;
+
ssif_inc_stat(ssif_info, sent_messages);
ssif_inc_stat(ssif_info, sent_messages_parts);
- /* Wait a jiffie then request the next message */
- ssif_info->retries_left = SSIF_RECV_RETRIES;
- ssif_info->rtc_us_timer = SSIF_MSG_PART_USEC;
- mod_timer(&ssif_info->retry_timer,
- jiffies + SSIF_MSG_PART_JIFFIES);
- return;
+ flags = ipmi_ssif_lock_cond(ssif_info, &oflags);
+ got_alert = ssif_info->got_alert;
+ if (got_alert) {
+ ssif_info->got_alert = false;
+ ssif_info->waiting_alert = false;
+ }
+
+ if (got_alert) {
+ ipmi_ssif_unlock_cond(ssif_info, flags);
+ /* The alert already happened, try now. */
+ retry_timeout((unsigned long) ssif_info);
+ } else {
+ /* Wait a jiffie then request the next message */
+ ssif_info->waiting_alert = true;
+ ssif_info->retries_left = SSIF_RECV_RETRIES;
+ ssif_info->rtc_us_timer = SSIF_MSG_PART_USEC;
+ mod_timer(&ssif_info->retry_timer,
+ jiffies + SSIF_MSG_PART_JIFFIES);
+ ipmi_ssif_unlock_cond(ssif_info, flags);
+ }
}
}
int rv;
int command;
+ ssif_info->got_alert = false;
+
if (ssif_info->data_len > 32) {
command = SSIF_IPMI_MULTI_PART_REQUEST_START;
ssif_info->multi_data = ssif_info->data;
return -E2BIG;
ssif_info->retries_left = SSIF_SEND_RETRIES;
- memcpy(ssif_info->data+1, data, len);
+ memcpy(ssif_info->data + 1, data, len);
ssif_info->data_len = len;
return start_resend(ssif_info);
}
{
seq_puts(m, "ssif\n");
- return seq_has_overflowed(m);
+ return 0;
}
static int smi_type_proc_open(struct inode *inode, struct file *file)
ssif_get_stat(ssif_info, events));
seq_printf(m, "watchdog_pretimeouts: %u\n",
ssif_get_stat(ssif_info, watchdog_pretimeouts));
+ seq_printf(m, "alerts: %u\n",
+ ssif_get_stat(ssif_info, alerts));
return 0;
}
.release = single_release,
};
+static int strcmp_nospace(char *s1, char *s2)
+{
+ while (*s1 && *s2) {
+ while (isspace(*s1))
+ s1++;
+ while (isspace(*s2))
+ s2++;
+ if (*s1 > *s2)
+ return 1;
+ if (*s1 < *s2)
+ return -1;
+ s1++;
+ s2++;
+ }
+ return 0;
+}
+
static struct ssif_addr_info *ssif_info_find(unsigned short addr,
char *adapter_name,
bool match_null_name)
/* One is NULL and one is not */
continue;
}
- if (strcmp(info->adapter_name, adapter_name))
- /* Names to not match */
+ if (adapter_name &&
+ strcmp_nospace(info->adapter_name,
+ adapter_name))
+ /* Names do not match */
continue;
}
found = info;
return false;
}
+/*
+ * Global enables we care about.
+ */
+#define GLOBAL_ENABLES_MASK (IPMI_BMC_EVT_MSG_BUFF | IPMI_BMC_RCV_MSG_INTR | \
+ IPMI_BMC_EVT_MSG_INTR)
+
static int ssif_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
unsigned char msg[3];
break;
case SSIF_MULTI_2_PART:
- if (ssif_info->max_xmit_msg_size > 64)
- ssif_info->max_xmit_msg_size = 64;
+ if (ssif_info->max_xmit_msg_size > 63)
+ ssif_info->max_xmit_msg_size = 63;
if (ssif_info->max_recv_msg_size > 62)
ssif_info->max_recv_msg_size = 62;
break;
case SSIF_MULTI_n_PART:
+ /*
+ * The specification is rather confusing at
+ * this point, but I think I understand what
+ * is meant. At least I have a workable
+ * solution. With multi-part messages, you
+ * cannot send a message that is a multiple of
+ * 32-bytes in length, because the start and
+ * middle messages are 32-bytes and the end
+ * message must be at least one byte. You
+ * can't fudge on an extra byte, that would
+ * screw up things like fru data writes. So
+ * we limit the length to 63 bytes. That way
+ * a 32-byte message gets sent as a single
+ * part. A larger message will be a 32-byte
+ * start and the next message is always going
+ * to be 1-31 bytes in length. Not ideal, but
+ * it should work.
+ */
+ if (ssif_info->max_xmit_msg_size > 63)
+ ssif_info->max_xmit_msg_size = 63;
break;
default:
} else {
no_support:
/* Assume no multi-part or PEC support */
- pr_info(PFX "Error fetching SSIF: %d %d %2.2x, your system probably doesn't support this command so using defaults\n",
+ pr_info(PFX "Error fetching SSIF: %d %d %2.2x, your system probably doesn't support this command so using defaults\n",
rv, len, resp[2]);
ssif_info->max_xmit_msg_size = 32;
goto found;
}
+ ssif_info->global_enables = resp[3];
+
if (resp[3] & IPMI_BMC_EVT_MSG_BUFF) {
ssif_info->has_event_buffer = true;
/* buffer is already enabled, nothing to do. */
msg[0] = IPMI_NETFN_APP_REQUEST << 2;
msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
- msg[2] = resp[3] | IPMI_BMC_EVT_MSG_BUFF;
+ msg[2] = ssif_info->global_enables | IPMI_BMC_EVT_MSG_BUFF;
rv = do_cmd(client, 3, msg, &len, resp);
if (rv || (len < 2)) {
- pr_warn(PFX "Error getting global enables: %d %d %2.2x\n",
+ pr_warn(PFX "Error setting global enables: %d %d %2.2x\n",
rv, len, resp[2]);
rv = 0; /* Not fatal */
goto found;
}
- if (resp[2] == 0)
+ if (resp[2] == 0) {
/* A successful return means the event buffer is supported. */
ssif_info->has_event_buffer = true;
+ ssif_info->global_enables |= IPMI_BMC_EVT_MSG_BUFF;
+ }
+
+ msg[0] = IPMI_NETFN_APP_REQUEST << 2;
+ msg[1] = IPMI_SET_BMC_GLOBAL_ENABLES_CMD;
+ msg[2] = ssif_info->global_enables | IPMI_BMC_RCV_MSG_INTR;
+ rv = do_cmd(client, 3, msg, &len, resp);
+ if (rv || (len < 2)) {
+ pr_warn(PFX "Error setting global enables: %d %d %2.2x\n",
+ rv, len, resp[2]);
+ rv = 0; /* Not fatal */
+ goto found;
+ }
+
+ if (resp[2] == 0) {
+ /* A successful return means the alert is supported. */
+ ssif_info->supports_alert = true;
+ ssif_info->global_enables |= IPMI_BMC_RCV_MSG_INTR;
+ }
found:
ssif_info->intf_num = atomic_inc_return(&next_intf);
},
.probe = ssif_probe,
.remove = ssif_remove,
+ .alert = ssif_alert,
.id_table = ssif_id,
.detect = ssif_detect
};
rv = new_ssif_client(addr[i], adapter_name[i],
dbg[i], slave_addrs[i],
SI_HARDCODED);
- if (!rv)
+ if (rv)
pr_err(PFX
"Couldn't add hardcoded device at addr 0x%x\n",
addr[i]);
return PTR_ERR(info->id_gpiod);
}
+ info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
+ if (IS_ERR(info->edev)) {
+ dev_err(dev, "failed to allocate extcon device\n");
+ return -ENOMEM;
+ }
+
+ ret = devm_extcon_dev_register(dev, info->edev);
+ if (ret < 0) {
+ dev_err(dev, "failed to register extcon device\n");
+ return ret;
+ }
+
ret = gpiod_set_debounce(info->id_gpiod,
USB_GPIO_DEBOUNCE_MS * 1000);
if (ret < 0)
return ret;
}
- info->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
- if (IS_ERR(info->edev)) {
- dev_err(dev, "failed to allocate extcon device\n");
- return -ENOMEM;
- }
-
- ret = devm_extcon_dev_register(dev, info->edev);
- if (ret < 0) {
- dev_err(dev, "failed to register extcon device\n");
- return ret;
- }
-
platform_set_drvdata(pdev, info);
device_init_wakeup(dev, 1);
buf += 16;
if (memcmp(buf, "_DMI_", 5) == 0 && dmi_checksum(buf, 15)) {
+ if (smbios_ver)
+ dmi_ver = smbios_ver;
+ else
+ dmi_ver = (buf[14] & 0xF0) << 4 | (buf[14] & 0x0F);
dmi_num = get_unaligned_le16(buf + 12);
dmi_len = get_unaligned_le16(buf + 6);
dmi_base = get_unaligned_le32(buf + 8);
if (dmi_walk_early(dmi_decode) == 0) {
if (smbios_ver) {
- dmi_ver = smbios_ver;
- pr_info("SMBIOS %d.%d%s present.\n",
- dmi_ver >> 8, dmi_ver & 0xFF,
- (dmi_ver < 0x0300) ? "" : ".x");
+ pr_info("SMBIOS %d.%d present.\n",
+ dmi_ver >> 8, dmi_ver & 0xFF);
} else {
- dmi_ver = (buf[14] & 0xF0) << 4 |
- (buf[14] & 0x0F);
pr_info("Legacy DMI %d.%d present.\n",
dmi_ver >> 8, dmi_ver & 0xFF);
}
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
kset_unregister(map_kset);
- return entry;
+ map_kset = NULL;
+ return ERR_PTR(-ENOMEM);
}
memcpy(&entry->md, efi_runtime_map + nr * efi_memdesc_size,
if (ret) {
kobject_put(&entry->kobj);
kset_unregister(map_kset);
+ map_kset = NULL;
return ERR_PTR(ret);
}
entry = *(map_entries + j);
kobject_put(&entry->kobj);
}
- if (map_kset)
- kset_unregister(map_kset);
out:
return ret;
}
dev_err(bank->dev, "Could not get gpio dbck\n");
}
-static void
-omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
- unsigned int num)
-{
- struct irq_chip_generic *gc;
- struct irq_chip_type *ct;
-
- gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
- handle_simple_irq);
- if (!gc) {
- dev_err(bank->dev, "Memory alloc failed for gc\n");
- return;
- }
-
- ct = gc->chip_types;
-
- /* NOTE: No ack required, reading IRQ status clears it. */
- ct->chip.irq_mask = irq_gc_mask_set_bit;
- ct->chip.irq_unmask = irq_gc_mask_clr_bit;
- ct->chip.irq_set_type = omap_gpio_irq_type;
-
- if (bank->regs->wkup_en)
- ct->chip.irq_set_wake = omap_gpio_wake_enable;
-
- ct->regs.mask = OMAP_MPUIO_GPIO_INT / bank->stride;
- irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
- IRQ_NOREQUEST | IRQ_NOPROBE, 0);
-}
-
static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
{
- int j;
static int gpio;
int irq_base = 0;
int ret;
}
#endif
+ /* MPUIO is a bit different, reading IRQ status clears it */
+ if (bank->is_mpuio) {
+ irqc->irq_ack = dummy_irq_chip.irq_ack;
+ irqc->irq_mask = irq_gc_mask_set_bit;
+ irqc->irq_unmask = irq_gc_mask_clr_bit;
+ if (!bank->regs->wkup_en)
+ irqc->irq_set_wake = NULL;
+ }
+
ret = gpiochip_irqchip_add(&bank->chip, irqc,
irq_base, omap_gpio_irq_handler,
IRQ_TYPE_NONE);
gpiochip_set_chained_irqchip(&bank->chip, irqc,
bank->irq, omap_gpio_irq_handler);
- for (j = 0; j < bank->width; j++) {
- int irq = irq_find_mapping(bank->chip.irqdomain, j);
- if (bank->is_mpuio) {
- omap_mpuio_alloc_gc(bank, irq, bank->width);
- irq_set_chip_and_handler(irq, NULL, NULL);
- set_irq_flags(irq, 0);
- }
- }
-
return 0;
}
length = min(agpio->pin_table_length, (u16)(pin_index + bits));
for (i = pin_index; i < length; ++i) {
- unsigned pin = agpio->pin_table[i];
+ int pin = agpio->pin_table[i];
struct acpi_gpio_connection *conn;
struct gpio_desc *desc;
bool found;
*/
int gpiod_export(struct gpio_desc *desc, bool direction_may_change)
{
+ struct gpio_chip *chip;
unsigned long flags;
int status;
const char *ioname = NULL;
return -EINVAL;
}
+ chip = desc->chip;
+
mutex_lock(&sysfs_lock);
+ /* check if chip is being removed */
+ if (!chip || !chip->exported) {
+ status = -ENODEV;
+ goto fail_unlock;
+ }
+
spin_lock_irqsave(&gpio_lock, flags);
if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
test_bit(FLAG_EXPORT, &desc->flags)) {
{
int status;
struct device *dev;
+ struct gpio_desc *desc;
+ unsigned int i;
mutex_lock(&sysfs_lock);
dev = class_find_device(&gpio_class, NULL, chip, match_export);
if (dev) {
put_device(dev);
device_unregister(dev);
+ /* prevent further gpiod exports */
chip->exported = false;
status = 0;
} else
if (status)
chip_dbg(chip, "%s: status %d\n", __func__, status);
+
+ /* unregister gpiod class devices owned by sysfs */
+ for (i = 0; i < chip->ngpio; i++) {
+ desc = &chip->desc[i];
+ if (test_and_clear_bit(FLAG_SYSFS, &desc->flags))
+ gpiod_free(desc);
+ }
}
static int __init gpiolib_sysfs_init(void)
BUG_ON(!dqm || !qpd);
- BUG_ON(!list_empty(&qpd->queues_list));
+ pr_debug("In func %s\n", __func__);
- pr_debug("kfd: In func %s\n", __func__);
+ pr_debug("qpd->queues_list is %s\n",
+ list_empty(&qpd->queues_list) ? "empty" : "not empty");
retval = 0;
mutex_lock(&dqm->lock);
return -ENOMEM;
}
+ init_sdma_vm(dqm, q, qpd);
+
retval = mqd->init_mqd(mqd, &q->mqd, &q->mqd_mem_obj,
&q->gart_mqd_addr, &q->properties);
if (retval != 0)
sysfs_show_32bit_prop(buffer, "max_engine_clk_fcompute",
dev->gpu->kfd2kgd->get_max_engine_clock_in_mhz(
dev->gpu->kgd));
+
sysfs_show_64bit_prop(buffer, "local_mem_size",
- dev->gpu->kfd2kgd->get_vmem_size(
- dev->gpu->kgd));
+ (unsigned long long int) 0);
sysfs_show_32bit_prop(buffer, "fw_version",
dev->gpu->kfd2kgd->get_fw_version(
/* Reinitialize corresponding vblank timestamp if high-precision query
* available. Skip this step if query unsupported or failed. Will
- * reinitialize delayed at next vblank interrupt in that case.
+ * reinitialize delayed at next vblank interrupt in that case and
+ * assign 0 for now, to mark the vblanktimestamp as invalid.
*/
- if (rc) {
- tslot = atomic_read(&vblank->count) + diff;
- vblanktimestamp(dev, crtc, tslot) = t_vblank;
- }
+ tslot = atomic_read(&vblank->count) + diff;
+ vblanktimestamp(dev, crtc, tslot) = rc ? t_vblank : (struct timeval) {0, 0};
smp_mb__before_atomic();
atomic_add(diff, &vblank->count);
intel_init_pch_refclk(dev);
drm_mode_config_reset(dev);
+ /*
+ * Interrupts have to be enabled before any batches are run. If not the
+ * GPU will hang. i915_gem_init_hw() will initiate batches to
+ * update/restore the context.
+ *
+ * Modeset enabling in intel_modeset_init_hw() also needs working
+ * interrupts.
+ */
+ intel_runtime_pm_enable_interrupts(dev_priv);
+
mutex_lock(&dev->struct_mutex);
if (i915_gem_init_hw(dev)) {
DRM_ERROR("failed to re-initialize GPU, declaring wedged!\n");
}
mutex_unlock(&dev->struct_mutex);
- /* We need working interrupts for modeset enabling ... */
- intel_runtime_pm_enable_interrupts(dev_priv);
-
intel_modeset_init_hw(dev);
spin_lock_irq(&dev_priv->irq_lock);
};
static struct intel_quirk intel_quirks[] = {
- /* HP Mini needs pipe A force quirk (LP: #322104) */
- { 0x27ae, 0x103c, 0x361a, quirk_pipea_force },
-
/* Toshiba Protege R-205, S-209 needs pipe A force quirk */
{ 0x2592, 0x1179, 0x0001, quirk_pipea_force },
pipe_config->has_dp_encoder = true;
pipe_config->has_drrs = false;
- pipe_config->has_audio = intel_dp->has_audio;
+ pipe_config->has_audio = intel_dp->has_audio && port != PORT_A;
if (is_edp(intel_dp) && intel_connector->panel.fixed_mode) {
intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
int dotclock;
tmp = I915_READ(intel_dp->output_reg);
- if (tmp & DP_AUDIO_OUTPUT_ENABLE)
- pipe_config->has_audio = true;
+
+ pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A;
if ((port == PORT_A) || !HAS_PCH_CPT(dev)) {
if (tmp & DP_SYNC_HS_HIGH)
if (val == 0)
break;
- intel_dp->sink_rates[i] = val * 200;
+ /* Value read is in kHz while drm clock is saved in deca-kHz */
+ intel_dp->sink_rates[i] = (val * 200) / 10;
}
intel_dp->num_sink_rates = i;
}
static const struct dmi_system_id intel_dual_link_lvds[] = {
{
.callback = intel_dual_link_lvds_callback,
- .ident = "Apple MacBook Pro (Core i5/i7 Series)",
+ .ident = "Apple MacBook Pro 15\" (2010)",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"),
+ },
+ },
+ {
+ .callback = intel_dual_link_lvds_callback,
+ .ident = "Apple MacBook Pro 15\" (2011)",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
},
},
+ {
+ .callback = intel_dual_link_lvds_callback,
+ .ident = "Apple MacBook Pro 15\" (2012)",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"),
+ },
+ },
{ } /* terminating entry */
};
if (i915.lvds_channel_mode > 0)
return i915.lvds_channel_mode == 2;
+ /* single channel LVDS is limited to 112 MHz */
+ if (lvds_encoder->attached_connector->base.panel.fixed_mode->clock
+ > 112999)
+ return true;
+
if (dmi_check_system(intel_dual_link_lvds))
return true;
out:
mutex_unlock(&dev->mode_config.mutex);
+ intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
+
lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
lvds_encoder->is_dual_link ? "dual" : "single");
}
drm_connector_register(connector);
- intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
intel_panel_setup_backlight(connector, INVALID_PIPE);
return;
L2_CACHE_BIGK_FRAGMENT_SIZE(4));
/* setup context0 */
WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1);
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
(u32)(rdev->dummy_page.addr >> 12));
/* restore context1-15 */
/* set vm size, must be a multiple of 4 */
WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
- WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn);
+ WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn - 1);
for (i = 1; i < 16; i++) {
if (i < 8)
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1);
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
L2_CACHE_BIGK_FRAGMENT_SIZE(6));
/* setup context0 */
WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1);
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
(u32)(rdev->dummy_page.addr >> 12));
*/
for (i = 1; i < 8; i++) {
WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR + (i << 2), 0);
- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2), rdev->vm_manager.max_pfn);
+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR + (i << 2),
+ rdev->vm_manager.max_pfn - 1);
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2),
rdev->vm_manager.saved_table_addr[i]);
}
WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE);
WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1);
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
struct radeon_bo *vcpu_bo;
void *cpu_addr;
uint64_t gpu_addr;
- void *saved_bo;
atomic_t handles[RADEON_MAX_UVD_HANDLES];
struct drm_file *filp[RADEON_MAX_UVD_HANDLES];
unsigned img_size[RADEON_MAX_UVD_HANDLES];
static struct radeon_asic_ring rv770_uvd_ring = {
.ib_execute = &uvd_v1_0_ib_execute,
.emit_fence = &uvd_v2_2_fence_emit,
- .emit_semaphore = &uvd_v1_0_semaphore_emit,
+ .emit_semaphore = &uvd_v2_2_semaphore_emit,
.cs_parse = &radeon_uvd_cs_parse,
.ring_test = &uvd_v1_0_ring_test,
.ib_test = &uvd_v1_0_ib_test,
int uvd_v2_2_resume(struct radeon_device *rdev);
void uvd_v2_2_fence_emit(struct radeon_device *rdev,
struct radeon_fence *fence);
+bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait);
/* uvd v3.1 */
bool uvd_v3_1_semaphore_emit(struct radeon_device *rdev,
return;
rdev = connector->encoder->dev->dev_private;
+
+ if (!radeon_audio_chipset_supported(rdev))
+ return;
+
radeon_encoder = to_radeon_encoder(connector->encoder);
dig = radeon_encoder->enc_priv;
int ret;
u8 msg[1];
+ if (!radeon_mst)
+ return 0;
+
if (dig_connector->dpcd[DP_DPCD_REV] < 0x12)
return 0;
list_for_each_entry(bo, &node->bos, mn_list) {
+ if (!bo->tbo.ttm || bo->tbo.ttm->state != tt_bound)
+ continue;
+
r = radeon_bo_reserve(bo, true);
if (r) {
DRM_ERROR("(%ld) failed to reserve user bo\n", r);
{
struct radeon_device *rdev = radeon_get_rdev(ttm->bdev);
struct radeon_ttm_tt *gtt = (void *)ttm;
- struct scatterlist *sg;
- int i;
+ struct sg_page_iter sg_iter;
int write = !(gtt->userflags & RADEON_GEM_USERPTR_READONLY);
enum dma_data_direction direction = write ?
/* free the sg table and pages again */
dma_unmap_sg(rdev->dev, ttm->sg->sgl, ttm->sg->nents, direction);
- for_each_sg(ttm->sg->sgl, sg, ttm->sg->nents, i) {
- struct page *page = sg_page(sg);
-
+ for_each_sg_page(ttm->sg->sgl, &sg_iter, ttm->sg->nents, 0) {
+ struct page *page = sg_page_iter_page(&sg_iter);
if (!(gtt->userflags & RADEON_GEM_USERPTR_READONLY))
set_page_dirty(page);
int radeon_uvd_suspend(struct radeon_device *rdev)
{
- unsigned size;
- void *ptr;
- int i;
+ int i, r;
if (rdev->uvd.vcpu_bo == NULL)
return 0;
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
- if (atomic_read(&rdev->uvd.handles[i]))
- break;
+ for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+ uint32_t handle = atomic_read(&rdev->uvd.handles[i]);
+ if (handle != 0) {
+ struct radeon_fence *fence;
- if (i == RADEON_MAX_UVD_HANDLES)
- return 0;
+ radeon_uvd_note_usage(rdev);
- size = radeon_bo_size(rdev->uvd.vcpu_bo);
- size -= rdev->uvd_fw->size;
+ r = radeon_uvd_get_destroy_msg(rdev,
+ R600_RING_TYPE_UVD_INDEX, handle, &fence);
+ if (r) {
+ DRM_ERROR("Error destroying UVD (%d)!\n", r);
+ continue;
+ }
- ptr = rdev->uvd.cpu_addr;
- ptr += rdev->uvd_fw->size;
+ radeon_fence_wait(fence, false);
+ radeon_fence_unref(&fence);
- rdev->uvd.saved_bo = kmalloc(size, GFP_KERNEL);
- memcpy(rdev->uvd.saved_bo, ptr, size);
+ rdev->uvd.filp[i] = NULL;
+ atomic_set(&rdev->uvd.handles[i], 0);
+ }
+ }
return 0;
}
ptr = rdev->uvd.cpu_addr;
ptr += rdev->uvd_fw->size;
- if (rdev->uvd.saved_bo != NULL) {
- memcpy(ptr, rdev->uvd.saved_bo, size);
- kfree(rdev->uvd.saved_bo);
- rdev->uvd.saved_bo = NULL;
- } else
- memset(ptr, 0, size);
+ memset(ptr, 0, size);
return 0;
}
return 0;
}
+static int radeon_uvd_validate_codec(struct radeon_cs_parser *p,
+ unsigned stream_type)
+{
+ switch (stream_type) {
+ case 0: /* H264 */
+ case 1: /* VC1 */
+ /* always supported */
+ return 0;
+
+ case 3: /* MPEG2 */
+ case 4: /* MPEG4 */
+ /* only since UVD 3 */
+ if (p->rdev->family >= CHIP_PALM)
+ return 0;
+
+ /* fall through */
+ default:
+ DRM_ERROR("UVD codec not supported by hardware %d!\n",
+ stream_type);
+ return -EINVAL;
+ }
+}
+
static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo,
unsigned offset, unsigned buf_sizes[])
{
return -EINVAL;
}
- if (msg_type == 1) {
- /* it's a decode msg, calc buffer sizes */
- r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
- /* calc image size (width * height) */
- img_size = msg[6] * msg[7];
+ switch (msg_type) {
+ case 0:
+ /* it's a create msg, calc image size (width * height) */
+ img_size = msg[7] * msg[8];
+
+ r = radeon_uvd_validate_codec(p, msg[4]);
radeon_bo_kunmap(bo);
if (r)
return r;
- } else if (msg_type == 2) {
+ /* try to alloc a new handle */
+ for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+ if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
+ DRM_ERROR("Handle 0x%x already in use!\n", handle);
+ return -EINVAL;
+ }
+
+ if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
+ p->rdev->uvd.filp[i] = p->filp;
+ p->rdev->uvd.img_size[i] = img_size;
+ return 0;
+ }
+ }
+
+ DRM_ERROR("No more free UVD handles!\n");
+ return -EINVAL;
+
+ case 1:
+ /* it's a decode msg, validate codec and calc buffer sizes */
+ r = radeon_uvd_validate_codec(p, msg[4]);
+ if (!r)
+ r = radeon_uvd_cs_msg_decode(msg, buf_sizes);
+ radeon_bo_kunmap(bo);
+ if (r)
+ return r;
+
+ /* validate the handle */
+ for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
+ if (atomic_read(&p->rdev->uvd.handles[i]) == handle) {
+ if (p->rdev->uvd.filp[i] != p->filp) {
+ DRM_ERROR("UVD handle collision detected!\n");
+ return -EINVAL;
+ }
+ return 0;
+ }
+ }
+
+ DRM_ERROR("Invalid UVD handle 0x%x!\n", handle);
+ return -ENOENT;
+
+ case 2:
/* it's a destroy msg, free the handle */
for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i)
atomic_cmpxchg(&p->rdev->uvd.handles[i], handle, 0);
radeon_bo_kunmap(bo);
return 0;
- } else {
- /* it's a create msg, calc image size (width * height) */
- img_size = msg[7] * msg[8];
- radeon_bo_kunmap(bo);
- if (msg_type != 0) {
- DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
- return -EINVAL;
- }
-
- /* it's a create msg, no special handling needed */
- }
-
- /* create or decode, validate the handle */
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
- if (atomic_read(&p->rdev->uvd.handles[i]) == handle)
- return 0;
- }
+ default:
- /* handle not found try to alloc a new one */
- for (i = 0; i < RADEON_MAX_UVD_HANDLES; ++i) {
- if (!atomic_cmpxchg(&p->rdev->uvd.handles[i], 0, handle)) {
- p->rdev->uvd.filp[i] = p->filp;
- p->rdev->uvd.img_size[i] = img_size;
- return 0;
- }
+ DRM_ERROR("Illegal UVD message type (%d)!\n", msg_type);
+ return -EINVAL;
}
- DRM_ERROR("No more free UVD handles!\n");
+ BUG();
return -EINVAL;
}
*
* @p: parser context
* @handle: handle to validate
+ * @allocated: allocated a new handle?
*
* Validates the handle and return the found session index or -EINVAL
* we we don't have another free session index.
*/
-int radeon_vce_validate_handle(struct radeon_cs_parser *p, uint32_t handle)
+static int radeon_vce_validate_handle(struct radeon_cs_parser *p,
+ uint32_t handle, bool *allocated)
{
unsigned i;
+ *allocated = false;
+
/* validate the handle */
for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i) {
- if (atomic_read(&p->rdev->vce.handles[i]) == handle)
+ if (atomic_read(&p->rdev->vce.handles[i]) == handle) {
+ if (p->rdev->vce.filp[i] != p->filp) {
+ DRM_ERROR("VCE handle collision detected!\n");
+ return -EINVAL;
+ }
return i;
+ }
}
/* handle not found try to alloc a new one */
if (!atomic_cmpxchg(&p->rdev->vce.handles[i], 0, handle)) {
p->rdev->vce.filp[i] = p->filp;
p->rdev->vce.img_size[i] = 0;
+ *allocated = true;
return i;
}
}
int radeon_vce_cs_parse(struct radeon_cs_parser *p)
{
int session_idx = -1;
- bool destroyed = false;
+ bool destroyed = false, created = false, allocated = false;
uint32_t tmp, handle = 0;
uint32_t *size = &tmp;
- int i, r;
+ int i, r = 0;
while (p->idx < p->chunk_ib->length_dw) {
uint32_t len = radeon_get_ib_value(p, p->idx);
if ((len < 8) || (len & 3)) {
DRM_ERROR("invalid VCE command length (%d)!\n", len);
- return -EINVAL;
+ r = -EINVAL;
+ goto out;
}
if (destroyed) {
DRM_ERROR("No other command allowed after destroy!\n");
- return -EINVAL;
+ r = -EINVAL;
+ goto out;
}
switch (cmd) {
case 0x00000001: // session
handle = radeon_get_ib_value(p, p->idx + 2);
- session_idx = radeon_vce_validate_handle(p, handle);
+ session_idx = radeon_vce_validate_handle(p, handle,
+ &allocated);
if (session_idx < 0)
return session_idx;
size = &p->rdev->vce.img_size[session_idx];
break;
case 0x01000001: // create
+ created = true;
+ if (!allocated) {
+ DRM_ERROR("Handle already in use!\n");
+ r = -EINVAL;
+ goto out;
+ }
+
*size = radeon_get_ib_value(p, p->idx + 8) *
radeon_get_ib_value(p, p->idx + 10) *
8 * 3 / 2;
r = radeon_vce_cs_reloc(p, p->idx + 10, p->idx + 9,
*size);
if (r)
- return r;
+ goto out;
r = radeon_vce_cs_reloc(p, p->idx + 12, p->idx + 11,
*size / 3);
if (r)
- return r;
+ goto out;
break;
case 0x02000001: // destroy
r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
*size * 2);
if (r)
- return r;
+ goto out;
break;
case 0x05000004: // video bitstream buffer
r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
tmp);
if (r)
- return r;
+ goto out;
break;
case 0x05000005: // feedback buffer
r = radeon_vce_cs_reloc(p, p->idx + 3, p->idx + 2,
4096);
if (r)
- return r;
+ goto out;
break;
default:
DRM_ERROR("invalid VCE command (0x%x)!\n", cmd);
- return -EINVAL;
+ r = -EINVAL;
+ goto out;
}
if (session_idx == -1) {
DRM_ERROR("no session command at start of IB\n");
- return -EINVAL;
+ r = -EINVAL;
+ goto out;
}
p->idx += len / 4;
}
- if (destroyed) {
- /* IB contains a destroy msg, free the handle */
+ if (allocated && !created) {
+ DRM_ERROR("New session without create command!\n");
+ r = -ENOENT;
+ }
+
+out:
+ if ((!r && destroyed) || (r && allocated)) {
+ /*
+ * IB contains a destroy msg or we have allocated an
+ * handle and got an error, anyway free the handle
+ */
for (i = 0; i < RADEON_MAX_VCE_HANDLES; ++i)
atomic_cmpxchg(&p->rdev->vce.handles[i], handle, 0);
}
- return 0;
+ return r;
}
/**
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1);
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
((n) & 0x3FFF) << 16)
/* UVD */
+#define UVD_SEMA_ADDR_LOW 0xef00
+#define UVD_SEMA_ADDR_HIGH 0xef04
+#define UVD_SEMA_CMD 0xef08
#define UVD_GPCOM_VCPU_CMD 0xef0c
#define UVD_GPCOM_VCPU_DATA0 0xef10
#define UVD_GPCOM_VCPU_DATA1 0xef14
L2_CACHE_BIGK_FRAGMENT_SIZE(4));
/* setup context0 */
WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
- WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+ WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, (rdev->mc.gtt_end >> 12) - 1);
WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
(u32)(rdev->dummy_page.addr >> 12));
/* empty context1-15 */
/* set vm size, must be a multiple of 4 */
WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0);
- WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn);
+ WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn - 1);
/* Assign the pt base to something valid for now; the pts used for
* the VMs are determined by the application and setup and assigned
* on the fly in the vm part of radeon_gart.c
struct radeon_semaphore *semaphore,
bool emit_wait)
{
- uint64_t addr = semaphore->gpu_addr;
-
- radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
- radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
-
- radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
- radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
-
- radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
- radeon_ring_write(ring, emit_wait ? 1 : 0);
-
- return true;
+ /* disable semaphores for UVD V1 hardware */
+ return false;
}
/**
radeon_ring_write(ring, 2);
}
+/**
+ * uvd_v2_2_semaphore_emit - emit semaphore command
+ *
+ * @rdev: radeon_device pointer
+ * @ring: radeon_ring pointer
+ * @semaphore: semaphore to emit commands for
+ * @emit_wait: true if we should emit a wait command
+ *
+ * Emit a semaphore command (either wait or signal) to the UVD ring.
+ */
+bool uvd_v2_2_semaphore_emit(struct radeon_device *rdev,
+ struct radeon_ring *ring,
+ struct radeon_semaphore *semaphore,
+ bool emit_wait)
+{
+ uint64_t addr = semaphore->gpu_addr;
+
+ radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_LOW, 0));
+ radeon_ring_write(ring, (addr >> 3) & 0x000FFFFF);
+
+ radeon_ring_write(ring, PACKET0(UVD_SEMA_ADDR_HIGH, 0));
+ radeon_ring_write(ring, (addr >> 23) & 0x000FFFFF);
+
+ radeon_ring_write(ring, PACKET0(UVD_SEMA_CMD, 0));
+ radeon_ring_write(ring, emit_wait ? 1 : 0);
+
+ return true;
+}
+
/**
* uvd_v2_2_resume - memory controller programming
*
drm->irq_enabled = true;
/* syncpoints are used for full 32-bit hardware VBLANK counters */
- drm->vblank_disable_immediate = true;
drm->max_vblank_count = 0xffffffff;
err = drm_vblank_init(drm, drm->mode_config.num_crtc);
help
This driver adds support for Toshiba TC86C001 GOKU-S chip.
-config BLK_DEV_CELLEB
- tristate "Toshiba's Cell Reference Set IDE support"
- depends on PPC_CELLEB
- select BLK_DEV_IDEDMA_PCI
- help
- This driver provides support for the on-board IDE controller on
- Toshiba Cell Reference Board.
- If unsure, say Y.
-
endif
# TODO: BLK_DEV_IDEDMA_PCI -> BLK_DEV_IDEDMA_SFF
obj-$(CONFIG_BLK_DEV_ALI15X3) += alim15x3.o
obj-$(CONFIG_BLK_DEV_AMD74XX) += amd74xx.o
obj-$(CONFIG_BLK_DEV_ATIIXP) += atiixp.o
-obj-$(CONFIG_BLK_DEV_CELLEB) += scc_pata.o
obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o
obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o
obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o
+++ /dev/null
-/*
- * Support for IDE interfaces on Celleb platform
- *
- * (C) Copyright 2006 TOSHIBA CORPORATION
- *
- * This code is based on drivers/ide/pci/siimage.c:
- * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
- * Copyright (C) 2003 Red Hat
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/init.h>
-
-#define PCI_DEVICE_ID_TOSHIBA_SCC_ATA 0x01b4
-
-#define SCC_PATA_NAME "scc IDE"
-
-#define TDVHSEL_MASTER 0x00000001
-#define TDVHSEL_SLAVE 0x00000004
-
-#define MODE_JCUSFEN 0x00000080
-
-#define CCKCTRL_ATARESET 0x00040000
-#define CCKCTRL_BUFCNT 0x00020000
-#define CCKCTRL_CRST 0x00010000
-#define CCKCTRL_OCLKEN 0x00000100
-#define CCKCTRL_ATACLKOEN 0x00000002
-#define CCKCTRL_LCLKEN 0x00000001
-
-#define QCHCD_IOS_SS 0x00000001
-
-#define QCHSD_STPDIAG 0x00020000
-
-#define INTMASK_MSK 0xD1000012
-#define INTSTS_SERROR 0x80000000
-#define INTSTS_PRERR 0x40000000
-#define INTSTS_RERR 0x10000000
-#define INTSTS_ICERR 0x01000000
-#define INTSTS_BMSINT 0x00000010
-#define INTSTS_BMHE 0x00000008
-#define INTSTS_IOIRQS 0x00000004
-#define INTSTS_INTRQ 0x00000002
-#define INTSTS_ACTEINT 0x00000001
-
-#define ECMODE_VALUE 0x01
-
-static struct scc_ports {
- unsigned long ctl, dma;
- struct ide_host *host; /* for removing port from system */
-} scc_ports[MAX_HWIFS];
-
-/* PIO transfer mode table */
-/* JCHST */
-static unsigned long JCHSTtbl[2][7] = {
- {0x0E, 0x05, 0x02, 0x03, 0x02, 0x00, 0x00}, /* 100MHz */
- {0x13, 0x07, 0x04, 0x04, 0x03, 0x00, 0x00} /* 133MHz */
-};
-
-/* JCHHT */
-static unsigned long JCHHTtbl[2][7] = {
- {0x0E, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00}, /* 100MHz */
- {0x13, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00} /* 133MHz */
-};
-
-/* JCHCT */
-static unsigned long JCHCTtbl[2][7] = {
- {0x1D, 0x1D, 0x1C, 0x0B, 0x06, 0x00, 0x00}, /* 100MHz */
- {0x27, 0x26, 0x26, 0x0E, 0x09, 0x00, 0x00} /* 133MHz */
-};
-
-
-/* DMA transfer mode table */
-/* JCHDCTM/JCHDCTS */
-static unsigned long JCHDCTxtbl[2][7] = {
- {0x0A, 0x06, 0x04, 0x03, 0x01, 0x00, 0x00}, /* 100MHz */
- {0x0E, 0x09, 0x06, 0x04, 0x02, 0x01, 0x00} /* 133MHz */
-};
-
-/* JCSTWTM/JCSTWTS */
-static unsigned long JCSTWTxtbl[2][7] = {
- {0x06, 0x04, 0x03, 0x02, 0x02, 0x02, 0x00}, /* 100MHz */
- {0x09, 0x06, 0x04, 0x02, 0x02, 0x02, 0x02} /* 133MHz */
-};
-
-/* JCTSS */
-static unsigned long JCTSStbl[2][7] = {
- {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x00}, /* 100MHz */
- {0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05} /* 133MHz */
-};
-
-/* JCENVT */
-static unsigned long JCENVTtbl[2][7] = {
- {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00}, /* 100MHz */
- {0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02} /* 133MHz */
-};
-
-/* JCACTSELS/JCACTSELM */
-static unsigned long JCACTSELtbl[2][7] = {
- {0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00}, /* 100MHz */
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} /* 133MHz */
-};
-
-
-static u8 scc_ide_inb(unsigned long port)
-{
- u32 data = in_be32((void*)port);
- return (u8)data;
-}
-
-static void scc_exec_command(ide_hwif_t *hwif, u8 cmd)
-{
- out_be32((void *)hwif->io_ports.command_addr, cmd);
- eieio();
- in_be32((void *)(hwif->dma_base + 0x01c));
- eieio();
-}
-
-static u8 scc_read_status(ide_hwif_t *hwif)
-{
- return (u8)in_be32((void *)hwif->io_ports.status_addr);
-}
-
-static u8 scc_read_altstatus(ide_hwif_t *hwif)
-{
- return (u8)in_be32((void *)hwif->io_ports.ctl_addr);
-}
-
-static u8 scc_dma_sff_read_status(ide_hwif_t *hwif)
-{
- return (u8)in_be32((void *)(hwif->dma_base + 4));
-}
-
-static void scc_write_devctl(ide_hwif_t *hwif, u8 ctl)
-{
- out_be32((void *)hwif->io_ports.ctl_addr, ctl);
- eieio();
- in_be32((void *)(hwif->dma_base + 0x01c));
- eieio();
-}
-
-static void scc_ide_insw(unsigned long port, void *addr, u32 count)
-{
- u16 *ptr = (u16 *)addr;
- while (count--) {
- *ptr++ = le16_to_cpu(in_be32((void*)port));
- }
-}
-
-static void scc_ide_insl(unsigned long port, void *addr, u32 count)
-{
- u16 *ptr = (u16 *)addr;
- while (count--) {
- *ptr++ = le16_to_cpu(in_be32((void*)port));
- *ptr++ = le16_to_cpu(in_be32((void*)port));
- }
-}
-
-static void scc_ide_outb(u8 addr, unsigned long port)
-{
- out_be32((void*)port, addr);
-}
-
-static void
-scc_ide_outsw(unsigned long port, void *addr, u32 count)
-{
- u16 *ptr = (u16 *)addr;
- while (count--) {
- out_be32((void*)port, cpu_to_le16(*ptr++));
- }
-}
-
-static void
-scc_ide_outsl(unsigned long port, void *addr, u32 count)
-{
- u16 *ptr = (u16 *)addr;
- while (count--) {
- out_be32((void*)port, cpu_to_le16(*ptr++));
- out_be32((void*)port, cpu_to_le16(*ptr++));
- }
-}
-
-/**
- * scc_set_pio_mode - set host controller for PIO mode
- * @hwif: port
- * @drive: drive
- *
- * Load the timing settings for this device mode into the
- * controller.
- */
-
-static void scc_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
-{
- struct scc_ports *ports = ide_get_hwifdata(hwif);
- unsigned long ctl_base = ports->ctl;
- unsigned long cckctrl_port = ctl_base + 0xff0;
- unsigned long piosht_port = ctl_base + 0x000;
- unsigned long pioct_port = ctl_base + 0x004;
- unsigned long reg;
- int offset;
- const u8 pio = drive->pio_mode - XFER_PIO_0;
-
- reg = in_be32((void __iomem *)cckctrl_port);
- if (reg & CCKCTRL_ATACLKOEN) {
- offset = 1; /* 133MHz */
- } else {
- offset = 0; /* 100MHz */
- }
- reg = JCHSTtbl[offset][pio] << 16 | JCHHTtbl[offset][pio];
- out_be32((void __iomem *)piosht_port, reg);
- reg = JCHCTtbl[offset][pio];
- out_be32((void __iomem *)pioct_port, reg);
-}
-
-/**
- * scc_set_dma_mode - set host controller for DMA mode
- * @hwif: port
- * @drive: drive
- *
- * Load the timing settings for this device mode into the
- * controller.
- */
-
-static void scc_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive)
-{
- struct scc_ports *ports = ide_get_hwifdata(hwif);
- unsigned long ctl_base = ports->ctl;
- unsigned long cckctrl_port = ctl_base + 0xff0;
- unsigned long mdmact_port = ctl_base + 0x008;
- unsigned long mcrcst_port = ctl_base + 0x00c;
- unsigned long sdmact_port = ctl_base + 0x010;
- unsigned long scrcst_port = ctl_base + 0x014;
- unsigned long udenvt_port = ctl_base + 0x018;
- unsigned long tdvhsel_port = ctl_base + 0x020;
- int is_slave = drive->dn & 1;
- int offset, idx;
- unsigned long reg;
- unsigned long jcactsel;
- const u8 speed = drive->dma_mode;
-
- reg = in_be32((void __iomem *)cckctrl_port);
- if (reg & CCKCTRL_ATACLKOEN) {
- offset = 1; /* 133MHz */
- } else {
- offset = 0; /* 100MHz */
- }
-
- idx = speed - XFER_UDMA_0;
-
- jcactsel = JCACTSELtbl[offset][idx];
- if (is_slave) {
- out_be32((void __iomem *)sdmact_port, JCHDCTxtbl[offset][idx]);
- out_be32((void __iomem *)scrcst_port, JCSTWTxtbl[offset][idx]);
- jcactsel = jcactsel << 2;
- out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_SLAVE) | jcactsel);
- } else {
- out_be32((void __iomem *)mdmact_port, JCHDCTxtbl[offset][idx]);
- out_be32((void __iomem *)mcrcst_port, JCSTWTxtbl[offset][idx]);
- out_be32((void __iomem *)tdvhsel_port, (in_be32((void __iomem *)tdvhsel_port) & ~TDVHSEL_MASTER) | jcactsel);
- }
- reg = JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx];
- out_be32((void __iomem *)udenvt_port, reg);
-}
-
-static void scc_dma_host_set(ide_drive_t *drive, int on)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 unit = drive->dn & 1;
- u8 dma_stat = scc_dma_sff_read_status(hwif);
-
- if (on)
- dma_stat |= (1 << (5 + unit));
- else
- dma_stat &= ~(1 << (5 + unit));
-
- scc_ide_outb(dma_stat, hwif->dma_base + 4);
-}
-
-/**
- * scc_dma_setup - begin a DMA phase
- * @drive: target device
- * @cmd: command
- *
- * Build an IDE DMA PRD (IDE speak for scatter gather table)
- * and then set up the DMA transfer registers.
- *
- * Returns 0 on success. If a PIO fallback is required then 1
- * is returned.
- */
-
-static int scc_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd)
-{
- ide_hwif_t *hwif = drive->hwif;
- u32 rw = (cmd->tf_flags & IDE_TFLAG_WRITE) ? 0 : ATA_DMA_WR;
- u8 dma_stat;
-
- /* fall back to pio! */
- if (ide_build_dmatable(drive, cmd) == 0)
- return 1;
-
- /* PRD table */
- out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
-
- /* specify r/w */
- out_be32((void __iomem *)hwif->dma_base, rw);
-
- /* read DMA status for INTR & ERROR flags */
- dma_stat = scc_dma_sff_read_status(hwif);
-
- /* clear INTR & ERROR flags */
- out_be32((void __iomem *)(hwif->dma_base + 4), dma_stat | 6);
-
- return 0;
-}
-
-static void scc_dma_start(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 dma_cmd = scc_ide_inb(hwif->dma_base);
-
- /* start DMA */
- scc_ide_outb(dma_cmd | 1, hwif->dma_base);
-}
-
-static int __scc_dma_end(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 dma_stat, dma_cmd;
-
- /* get DMA command mode */
- dma_cmd = scc_ide_inb(hwif->dma_base);
- /* stop DMA */
- scc_ide_outb(dma_cmd & ~1, hwif->dma_base);
- /* get DMA status */
- dma_stat = scc_dma_sff_read_status(hwif);
- /* clear the INTR & ERROR bits */
- scc_ide_outb(dma_stat | 6, hwif->dma_base + 4);
- /* verify good DMA status */
- return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
-}
-
-/**
- * scc_dma_end - Stop DMA
- * @drive: IDE drive
- *
- * Check and clear INT Status register.
- * Then call __scc_dma_end().
- */
-
-static int scc_dma_end(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- void __iomem *dma_base = (void __iomem *)hwif->dma_base;
- unsigned long intsts_port = hwif->dma_base + 0x014;
- u32 reg;
- int dma_stat, data_loss = 0;
- static int retry = 0;
-
- /* errata A308 workaround: Step5 (check data loss) */
- /* We don't check non ide_disk because it is limited to UDMA4 */
- if (!(in_be32((void __iomem *)hwif->io_ports.ctl_addr)
- & ATA_ERR) &&
- drive->media == ide_disk && drive->current_speed > XFER_UDMA_4) {
- reg = in_be32((void __iomem *)intsts_port);
- if (!(reg & INTSTS_ACTEINT)) {
- printk(KERN_WARNING "%s: operation failed (transfer data loss)\n",
- drive->name);
- data_loss = 1;
- if (retry++) {
- struct request *rq = hwif->rq;
- ide_drive_t *drive;
- int i;
-
- /* ERROR_RESET and drive->crc_count are needed
- * to reduce DMA transfer mode in retry process.
- */
- if (rq)
- rq->errors |= ERROR_RESET;
-
- ide_port_for_each_dev(i, drive, hwif)
- drive->crc_count++;
- }
- }
- }
-
- while (1) {
- reg = in_be32((void __iomem *)intsts_port);
-
- if (reg & INTSTS_SERROR) {
- printk(KERN_WARNING "%s: SERROR\n", SCC_PATA_NAME);
- out_be32((void __iomem *)intsts_port, INTSTS_SERROR|INTSTS_BMSINT);
-
- out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
- continue;
- }
-
- if (reg & INTSTS_PRERR) {
- u32 maea0, maec0;
- unsigned long ctl_base = hwif->config_data;
-
- maea0 = in_be32((void __iomem *)(ctl_base + 0xF50));
- maec0 = in_be32((void __iomem *)(ctl_base + 0xF54));
-
- printk(KERN_WARNING "%s: PRERR [addr:%x cmd:%x]\n", SCC_PATA_NAME, maea0, maec0);
-
- out_be32((void __iomem *)intsts_port, INTSTS_PRERR|INTSTS_BMSINT);
-
- out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
- continue;
- }
-
- if (reg & INTSTS_RERR) {
- printk(KERN_WARNING "%s: Response Error\n", SCC_PATA_NAME);
- out_be32((void __iomem *)intsts_port, INTSTS_RERR|INTSTS_BMSINT);
-
- out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
- continue;
- }
-
- if (reg & INTSTS_ICERR) {
- out_be32(dma_base, in_be32(dma_base) & ~QCHCD_IOS_SS);
-
- printk(KERN_WARNING "%s: Illegal Configuration\n", SCC_PATA_NAME);
- out_be32((void __iomem *)intsts_port, INTSTS_ICERR|INTSTS_BMSINT);
- continue;
- }
-
- if (reg & INTSTS_BMSINT) {
- printk(KERN_WARNING "%s: Internal Bus Error\n", SCC_PATA_NAME);
- out_be32((void __iomem *)intsts_port, INTSTS_BMSINT);
-
- ide_do_reset(drive);
- continue;
- }
-
- if (reg & INTSTS_BMHE) {
- out_be32((void __iomem *)intsts_port, INTSTS_BMHE);
- continue;
- }
-
- if (reg & INTSTS_ACTEINT) {
- out_be32((void __iomem *)intsts_port, INTSTS_ACTEINT);
- continue;
- }
-
- if (reg & INTSTS_IOIRQS) {
- out_be32((void __iomem *)intsts_port, INTSTS_IOIRQS);
- continue;
- }
- break;
- }
-
- dma_stat = __scc_dma_end(drive);
- if (data_loss)
- dma_stat |= 2; /* emulate DMA error (to retry command) */
- return dma_stat;
-}
-
-/* returns 1 if dma irq issued, 0 otherwise */
-static int scc_dma_test_irq(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u32 int_stat = in_be32((void __iomem *)hwif->dma_base + 0x014);
-
- /* SCC errata A252,A308 workaround: Step4 */
- if ((in_be32((void __iomem *)hwif->io_ports.ctl_addr)
- & ATA_ERR) &&
- (int_stat & INTSTS_INTRQ))
- return 1;
-
- /* SCC errata A308 workaround: Step5 (polling IOIRQS) */
- if (int_stat & INTSTS_IOIRQS)
- return 1;
-
- return 0;
-}
-
-static u8 scc_udma_filter(ide_drive_t *drive)
-{
- ide_hwif_t *hwif = drive->hwif;
- u8 mask = hwif->ultra_mask;
-
- /* errata A308 workaround: limit non ide_disk drive to UDMA4 */
- if ((drive->media != ide_disk) && (mask & 0xE0)) {
- printk(KERN_INFO "%s: limit %s to UDMA4\n",
- SCC_PATA_NAME, drive->name);
- mask = ATA_UDMA4;
- }
-
- return mask;
-}
-
-/**
- * setup_mmio_scc - map CTRL/BMID region
- * @dev: PCI device we are configuring
- * @name: device name
- *
- */
-
-static int setup_mmio_scc (struct pci_dev *dev, const char *name)
-{
- void __iomem *ctl_addr;
- void __iomem *dma_addr;
- int i, ret;
-
- for (i = 0; i < MAX_HWIFS; i++) {
- if (scc_ports[i].ctl == 0)
- break;
- }
- if (i >= MAX_HWIFS)
- return -ENOMEM;
-
- ret = pci_request_selected_regions(dev, (1 << 2) - 1, name);
- if (ret < 0) {
- printk(KERN_ERR "%s: can't reserve resources\n", name);
- return ret;
- }
-
- ctl_addr = pci_ioremap_bar(dev, 0);
- if (!ctl_addr)
- goto fail_0;
-
- dma_addr = pci_ioremap_bar(dev, 1);
- if (!dma_addr)
- goto fail_1;
-
- pci_set_master(dev);
- scc_ports[i].ctl = (unsigned long)ctl_addr;
- scc_ports[i].dma = (unsigned long)dma_addr;
- pci_set_drvdata(dev, (void *) &scc_ports[i]);
-
- return 1;
-
- fail_1:
- iounmap(ctl_addr);
- fail_0:
- return -ENOMEM;
-}
-
-static int scc_ide_setup_pci_device(struct pci_dev *dev,
- const struct ide_port_info *d)
-{
- struct scc_ports *ports = pci_get_drvdata(dev);
- struct ide_host *host;
- struct ide_hw hw, *hws[] = { &hw };
- int i, rc;
-
- memset(&hw, 0, sizeof(hw));
- for (i = 0; i <= 8; i++)
- hw.io_ports_array[i] = ports->dma + 0x20 + i * 4;
- hw.irq = dev->irq;
- hw.dev = &dev->dev;
-
- rc = ide_host_add(d, hws, 1, &host);
- if (rc)
- return rc;
-
- ports->host = host;
-
- return 0;
-}
-
-/**
- * init_setup_scc - set up an SCC PATA Controller
- * @dev: PCI device
- * @d: IDE port info
- *
- * Perform the initial set up for this device.
- */
-
-static int init_setup_scc(struct pci_dev *dev, const struct ide_port_info *d)
-{
- unsigned long ctl_base;
- unsigned long dma_base;
- unsigned long cckctrl_port;
- unsigned long intmask_port;
- unsigned long mode_port;
- unsigned long ecmode_port;
- u32 reg = 0;
- struct scc_ports *ports;
- int rc;
-
- rc = pci_enable_device(dev);
- if (rc)
- goto end;
-
- rc = setup_mmio_scc(dev, d->name);
- if (rc < 0)
- goto end;
-
- ports = pci_get_drvdata(dev);
- ctl_base = ports->ctl;
- dma_base = ports->dma;
- cckctrl_port = ctl_base + 0xff0;
- intmask_port = dma_base + 0x010;
- mode_port = ctl_base + 0x024;
- ecmode_port = ctl_base + 0xf00;
-
- /* controller initialization */
- reg = 0;
- out_be32((void*)cckctrl_port, reg);
- reg |= CCKCTRL_ATACLKOEN;
- out_be32((void*)cckctrl_port, reg);
- reg |= CCKCTRL_LCLKEN | CCKCTRL_OCLKEN;
- out_be32((void*)cckctrl_port, reg);
- reg |= CCKCTRL_CRST;
- out_be32((void*)cckctrl_port, reg);
-
- for (;;) {
- reg = in_be32((void*)cckctrl_port);
- if (reg & CCKCTRL_CRST)
- break;
- udelay(5000);
- }
-
- reg |= CCKCTRL_ATARESET;
- out_be32((void*)cckctrl_port, reg);
-
- out_be32((void*)ecmode_port, ECMODE_VALUE);
- out_be32((void*)mode_port, MODE_JCUSFEN);
- out_be32((void*)intmask_port, INTMASK_MSK);
-
- rc = scc_ide_setup_pci_device(dev, d);
-
- end:
- return rc;
-}
-
-static void scc_tf_load(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid)
-{
- struct ide_io_ports *io_ports = &drive->hwif->io_ports;
-
- if (valid & IDE_VALID_FEATURE)
- scc_ide_outb(tf->feature, io_ports->feature_addr);
- if (valid & IDE_VALID_NSECT)
- scc_ide_outb(tf->nsect, io_ports->nsect_addr);
- if (valid & IDE_VALID_LBAL)
- scc_ide_outb(tf->lbal, io_ports->lbal_addr);
- if (valid & IDE_VALID_LBAM)
- scc_ide_outb(tf->lbam, io_ports->lbam_addr);
- if (valid & IDE_VALID_LBAH)
- scc_ide_outb(tf->lbah, io_ports->lbah_addr);
- if (valid & IDE_VALID_DEVICE)
- scc_ide_outb(tf->device, io_ports->device_addr);
-}
-
-static void scc_tf_read(ide_drive_t *drive, struct ide_taskfile *tf, u8 valid)
-{
- struct ide_io_ports *io_ports = &drive->hwif->io_ports;
-
- if (valid & IDE_VALID_ERROR)
- tf->error = scc_ide_inb(io_ports->feature_addr);
- if (valid & IDE_VALID_NSECT)
- tf->nsect = scc_ide_inb(io_ports->nsect_addr);
- if (valid & IDE_VALID_LBAL)
- tf->lbal = scc_ide_inb(io_ports->lbal_addr);
- if (valid & IDE_VALID_LBAM)
- tf->lbam = scc_ide_inb(io_ports->lbam_addr);
- if (valid & IDE_VALID_LBAH)
- tf->lbah = scc_ide_inb(io_ports->lbah_addr);
- if (valid & IDE_VALID_DEVICE)
- tf->device = scc_ide_inb(io_ports->device_addr);
-}
-
-static void scc_input_data(ide_drive_t *drive, struct ide_cmd *cmd,
- void *buf, unsigned int len)
-{
- unsigned long data_addr = drive->hwif->io_ports.data_addr;
-
- len++;
-
- if (drive->io_32bit) {
- scc_ide_insl(data_addr, buf, len / 4);
-
- if ((len & 3) >= 2)
- scc_ide_insw(data_addr, (u8 *)buf + (len & ~3), 1);
- } else
- scc_ide_insw(data_addr, buf, len / 2);
-}
-
-static void scc_output_data(ide_drive_t *drive, struct ide_cmd *cmd,
- void *buf, unsigned int len)
-{
- unsigned long data_addr = drive->hwif->io_ports.data_addr;
-
- len++;
-
- if (drive->io_32bit) {
- scc_ide_outsl(data_addr, buf, len / 4);
-
- if ((len & 3) >= 2)
- scc_ide_outsw(data_addr, (u8 *)buf + (len & ~3), 1);
- } else
- scc_ide_outsw(data_addr, buf, len / 2);
-}
-
-/**
- * init_mmio_iops_scc - set up the iops for MMIO
- * @hwif: interface to set up
- *
- */
-
-static void init_mmio_iops_scc(ide_hwif_t *hwif)
-{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
- struct scc_ports *ports = pci_get_drvdata(dev);
- unsigned long dma_base = ports->dma;
-
- ide_set_hwifdata(hwif, ports);
-
- hwif->dma_base = dma_base;
- hwif->config_data = ports->ctl;
-}
-
-/**
- * init_iops_scc - set up iops
- * @hwif: interface to set up
- *
- * Do the basic setup for the SCC hardware interface
- * and then do the MMIO setup.
- */
-
-static void init_iops_scc(ide_hwif_t *hwif)
-{
- struct pci_dev *dev = to_pci_dev(hwif->dev);
-
- hwif->hwif_data = NULL;
- if (pci_get_drvdata(dev) == NULL)
- return;
- init_mmio_iops_scc(hwif);
-}
-
-static int scc_init_dma(ide_hwif_t *hwif, const struct ide_port_info *d)
-{
- return ide_allocate_dma_engine(hwif);
-}
-
-static u8 scc_cable_detect(ide_hwif_t *hwif)
-{
- return ATA_CBL_PATA80;
-}
-
-/**
- * init_hwif_scc - set up hwif
- * @hwif: interface to set up
- *
- * We do the basic set up of the interface structure. The SCC
- * requires several custom handlers so we override the default
- * ide DMA handlers appropriately.
- */
-
-static void init_hwif_scc(ide_hwif_t *hwif)
-{
- /* PTERADD */
- out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
-
- if (in_be32((void __iomem *)(hwif->config_data + 0xff0)) & CCKCTRL_ATACLKOEN)
- hwif->ultra_mask = ATA_UDMA6; /* 133MHz */
- else
- hwif->ultra_mask = ATA_UDMA5; /* 100MHz */
-}
-
-static const struct ide_tp_ops scc_tp_ops = {
- .exec_command = scc_exec_command,
- .read_status = scc_read_status,
- .read_altstatus = scc_read_altstatus,
- .write_devctl = scc_write_devctl,
-
- .dev_select = ide_dev_select,
- .tf_load = scc_tf_load,
- .tf_read = scc_tf_read,
-
- .input_data = scc_input_data,
- .output_data = scc_output_data,
-};
-
-static const struct ide_port_ops scc_port_ops = {
- .set_pio_mode = scc_set_pio_mode,
- .set_dma_mode = scc_set_dma_mode,
- .udma_filter = scc_udma_filter,
- .cable_detect = scc_cable_detect,
-};
-
-static const struct ide_dma_ops scc_dma_ops = {
- .dma_host_set = scc_dma_host_set,
- .dma_setup = scc_dma_setup,
- .dma_start = scc_dma_start,
- .dma_end = scc_dma_end,
- .dma_test_irq = scc_dma_test_irq,
- .dma_lost_irq = ide_dma_lost_irq,
- .dma_timer_expiry = ide_dma_sff_timer_expiry,
- .dma_sff_read_status = scc_dma_sff_read_status,
-};
-
-static const struct ide_port_info scc_chipset = {
- .name = "sccIDE",
- .init_iops = init_iops_scc,
- .init_dma = scc_init_dma,
- .init_hwif = init_hwif_scc,
- .tp_ops = &scc_tp_ops,
- .port_ops = &scc_port_ops,
- .dma_ops = &scc_dma_ops,
- .host_flags = IDE_HFLAG_SINGLE,
- .irq_flags = IRQF_SHARED,
- .pio_mask = ATA_PIO4,
- .chipset = ide_pci,
-};
-
-/**
- * scc_init_one - pci layer discovery entry
- * @dev: PCI device
- * @id: ident table entry
- *
- * Called by the PCI code when it finds an SCC PATA controller.
- * We then use the IDE PCI generic helper to do most of the work.
- */
-
-static int scc_init_one(struct pci_dev *dev, const struct pci_device_id *id)
-{
- return init_setup_scc(dev, &scc_chipset);
-}
-
-/**
- * scc_remove - pci layer remove entry
- * @dev: PCI device
- *
- * Called by the PCI code when it removes an SCC PATA controller.
- */
-
-static void scc_remove(struct pci_dev *dev)
-{
- struct scc_ports *ports = pci_get_drvdata(dev);
- struct ide_host *host = ports->host;
-
- ide_host_remove(host);
-
- iounmap((void*)ports->dma);
- iounmap((void*)ports->ctl);
- pci_release_selected_regions(dev, (1 << 2) - 1);
- memset(ports, 0, sizeof(*ports));
-}
-
-static const struct pci_device_id scc_pci_tbl[] = {
- { PCI_VDEVICE(TOSHIBA_2, PCI_DEVICE_ID_TOSHIBA_SCC_ATA), 0 },
- { 0, },
-};
-MODULE_DEVICE_TABLE(pci, scc_pci_tbl);
-
-static struct pci_driver scc_pci_driver = {
- .name = "SCC IDE",
- .id_table = scc_pci_tbl,
- .probe = scc_init_one,
- .remove = scc_remove,
-};
-
-static int __init scc_ide_init(void)
-{
- return ide_pci_register_driver(&scc_pci_driver);
-}
-
-static void __exit scc_ide_exit(void)
-{
- pci_unregister_driver(&scc_pci_driver);
-}
-
-module_init(scc_ide_init);
-module_exit(scc_ide_exit);
-
-MODULE_DESCRIPTION("PCI driver module for Toshiba SCC IDE");
-MODULE_LICENSE("GPL");
{
int ret, i;
int len_words = len / sizeof(u16);
- __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS];
+ __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
+
+ if (len_words > 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);
{
int ret, i;
int len_words = len / sizeof(u16);
- __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS];
+ __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS / 2];
+
+ if (len_words > 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);
{
int i;
int len_words = len / sizeof(u16);
- __be16 be_buf[MMA9551_MAX_MAILBOX_DATA_REGS];
+ __be16 be_buf[(MMA9551_MAX_MAILBOX_DATA_REGS - 1) / 2];
+
+ if (len_words > ARRAY_SIZE(be_buf)) {
+ dev_err(&client->dev, "Invalid buffer size %d\n", len);
+ return -EINVAL;
+ }
for (i = 0; i < len_words; i++)
be_buf[i] = cpu_to_be16(buf[i]);
#define MMA9553_MASK_CONF_STEPCOALESCE GENMASK(7, 0)
#define MMA9553_REG_CONF_ACTTHD 0x0E
+#define MMA9553_MAX_ACTTHD GENMASK(15, 0)
/* Pedometer status registers (R-only) */
#define MMA9553_REG_STATUS 0x00
static int mma9553_read_activity_stepcnt(struct mma9553_data *data,
u8 *activity, u16 *stepcnt)
{
- u32 status_stepcnt;
- u16 status;
+ u16 buf[2];
int ret;
ret = mma9551_read_status_words(data->client, MMA9551_APPID_PEDOMETER,
- MMA9553_REG_STATUS, sizeof(u32),
- (u16 *) &status_stepcnt);
+ MMA9553_REG_STATUS, sizeof(u32), buf);
if (ret < 0) {
dev_err(&data->client->dev,
"error reading status and stepcnt\n");
return ret;
}
- status = status_stepcnt & MMA9553_MASK_CONF_WORD;
- *activity = mma9553_get_bits(status, MMA9553_MASK_STATUS_ACTIVITY);
- *stepcnt = status_stepcnt >> 16;
+ *activity = mma9553_get_bits(buf[0], MMA9553_MASK_STATUS_ACTIVITY);
+ *stepcnt = buf[1];
return 0;
}
case IIO_EV_INFO_PERIOD:
switch (chan->type) {
case IIO_ACTIVITY:
+ if (val < 0 || val > MMA9553_ACTIVITY_THD_TO_SEC(
+ MMA9553_MAX_ACTTHD))
+ return -EINVAL;
mutex_lock(&data->mutex);
ret = mma9553_set_config(data, MMA9553_REG_CONF_ACTTHD,
&data->conf.actthd,
.modified = 1, \
.channel2 = _chan2, \
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBHEIGHT), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_CALIBHEIGHT) | \
+ BIT(IIO_CHAN_INFO_ENABLE), \
.event_spec = mma9553_activity_events, \
.num_event_specs = ARRAY_SIZE(mma9553_activity_events), \
.ext_info = mma9553_ext_info, \
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &accel_info;
+ mutex_init(&adata->tb.buf_lock);
st_sensors_power_enable(indio_dev);
.channel = 0,
.address = AXP288_TS_ADC_H,
.datasheet_name = "TS_PIN",
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
}, {
.indexed = 1,
.type = IIO_TEMP,
.channel = 1,
.address = AXP288_PMIC_ADC_H,
.datasheet_name = "PMIC_TEMP",
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
}, {
.indexed = 1,
.type = IIO_TEMP,
.channel = 2,
.address = AXP288_GP_ADC_H,
.datasheet_name = "GPADC",
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
}, {
.indexed = 1,
.type = IIO_CURRENT,
.channel = 3,
.address = AXP20X_BATT_CHRG_I_H,
.datasheet_name = "BATT_CHG_I",
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
}, {
.indexed = 1,
.type = IIO_CURRENT,
.channel = 4,
.address = AXP20X_BATT_DISCHRG_I_H,
.datasheet_name = "BATT_DISCHRG_I",
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
}, {
.indexed = 1,
.type = IIO_VOLTAGE,
.channel = 5,
.address = AXP20X_BATT_V_H,
.datasheet_name = "BATT_V",
- .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
},
};
chan->address))
dev_err(&indio_dev->dev, "TS pin restore\n");
break;
- case IIO_CHAN_INFO_PROCESSED:
- ret = axp288_adc_read_channel(val, chan->address, info->regmap);
- break;
default:
ret = -EINVAL;
}
#define CC10001_ADC_EOC_SET BIT(0)
#define CC10001_ADC_CHSEL_SAMPLED 0x0c
-#define CC10001_ADC_POWER_UP 0x10
-#define CC10001_ADC_POWER_UP_SET BIT(0)
+#define CC10001_ADC_POWER_DOWN 0x10
+#define CC10001_ADC_POWER_DOWN_SET BIT(0)
+
#define CC10001_ADC_DEBUG 0x14
#define CC10001_ADC_DATA_COUNT 0x20
u16 *buf;
struct mutex lock;
- unsigned long channel_map;
unsigned int start_delay_ns;
unsigned int eoc_delay_ns;
};
return readl(adc_dev->reg_base + reg);
}
+static void cc10001_adc_power_up(struct cc10001_adc_device *adc_dev)
+{
+ cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_DOWN, 0);
+ ndelay(adc_dev->start_delay_ns);
+}
+
+static void cc10001_adc_power_down(struct cc10001_adc_device *adc_dev)
+{
+ cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_DOWN,
+ CC10001_ADC_POWER_DOWN_SET);
+}
+
static void cc10001_adc_start(struct cc10001_adc_device *adc_dev,
unsigned int channel)
{
val = (channel & CC10001_ADC_CH_MASK) | CC10001_ADC_MODE_SINGLE_CONV;
cc10001_adc_write_reg(adc_dev, CC10001_ADC_CONFIG, val);
+ udelay(1);
val = cc10001_adc_read_reg(adc_dev, CC10001_ADC_CONFIG);
val = val | CC10001_ADC_START_CONV;
cc10001_adc_write_reg(adc_dev, CC10001_ADC_CONFIG, val);
struct iio_dev *indio_dev;
unsigned int delay_ns;
unsigned int channel;
+ unsigned int scan_idx;
bool sample_invalid;
u16 *data;
int i;
mutex_lock(&adc_dev->lock);
- cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP,
- CC10001_ADC_POWER_UP_SET);
-
- /* Wait for 8 (6+2) clock cycles before activating START */
- ndelay(adc_dev->start_delay_ns);
+ 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;
i = 0;
sample_invalid = false;
- for_each_set_bit(channel, indio_dev->active_scan_mask,
+ for_each_set_bit(scan_idx, indio_dev->active_scan_mask,
indio_dev->masklength) {
+ channel = indio_dev->channels[scan_idx].channel;
cc10001_adc_start(adc_dev, channel);
data[i] = cc10001_adc_poll_done(indio_dev, channel, delay_ns);
}
done:
- cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP, 0);
+ cc10001_adc_power_down(adc_dev);
mutex_unlock(&adc_dev->lock);
unsigned int delay_ns;
u16 val;
- cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP,
- CC10001_ADC_POWER_UP_SET);
-
- /* Wait for 8 (6+2) clock cycles before activating START */
- ndelay(adc_dev->start_delay_ns);
+ 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;
val = cc10001_adc_poll_done(indio_dev, chan->channel, delay_ns);
- cc10001_adc_write_reg(adc_dev, CC10001_ADC_POWER_UP, 0);
+ cc10001_adc_power_down(adc_dev);
return val;
}
case IIO_CHAN_INFO_SCALE:
ret = regulator_get_voltage(adc_dev->reg);
- if (ret)
+ if (ret < 0)
return ret;
*val = ret / 1000;
.update_scan_mode = &cc10001_update_scan_mode,
};
-static int cc10001_adc_channel_init(struct iio_dev *indio_dev)
+static int cc10001_adc_channel_init(struct iio_dev *indio_dev,
+ unsigned long channel_map)
{
- struct cc10001_adc_device *adc_dev = iio_priv(indio_dev);
struct iio_chan_spec *chan_array, *timestamp;
unsigned int bit, idx = 0;
- indio_dev->num_channels = bitmap_weight(&adc_dev->channel_map,
- CC10001_ADC_NUM_CHANNELS);
+ indio_dev->num_channels = bitmap_weight(&channel_map,
+ CC10001_ADC_NUM_CHANNELS) + 1;
- chan_array = devm_kcalloc(&indio_dev->dev, indio_dev->num_channels + 1,
+ chan_array = devm_kcalloc(&indio_dev->dev, indio_dev->num_channels,
sizeof(struct iio_chan_spec),
GFP_KERNEL);
if (!chan_array)
return -ENOMEM;
- for_each_set_bit(bit, &adc_dev->channel_map, CC10001_ADC_NUM_CHANNELS) {
+ for_each_set_bit(bit, &channel_map, CC10001_ADC_NUM_CHANNELS) {
struct iio_chan_spec *chan = &chan_array[idx];
chan->type = IIO_VOLTAGE;
unsigned long adc_clk_rate;
struct resource *res;
struct iio_dev *indio_dev;
+ unsigned long channel_map;
int ret;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc_dev));
adc_dev = iio_priv(indio_dev);
- adc_dev->channel_map = GENMASK(CC10001_ADC_NUM_CHANNELS - 1, 0);
+ channel_map = GENMASK(CC10001_ADC_NUM_CHANNELS - 1, 0);
if (!of_property_read_u32(node, "adc-reserved-channels", &ret))
- adc_dev->channel_map &= ~ret;
+ channel_map &= ~ret;
adc_dev->reg = devm_regulator_get(&pdev->dev, "vref");
if (IS_ERR(adc_dev->reg))
adc_dev->start_delay_ns = adc_dev->eoc_delay_ns * CC10001_WAIT_CYCLES;
/* Setup the ADC channels available on the device */
- ret = cc10001_adc_channel_init(indio_dev);
+ ret = cc10001_adc_channel_init(indio_dev, channel_map);
if (ret < 0)
goto err_disable_clk;
struct spi_message msg;
struct spi_transfer transfer[2];
- u8 tx_buf;
- u8 rx_buf[2];
-
struct regulator *reg;
struct mutex lock;
const struct mcp320x_chip_info *chip_info;
+
+ u8 tx_buf ____cacheline_aligned;
+ u8 rx_buf[2];
};
static int mcp320x_channel_to_tx_data(int device_index,
#include <linux/iio/iio.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
+#include <linux/math64.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
const struct vadc_channel_prop *prop, u16 adc_code)
{
const struct vadc_prescale_ratio *prescale;
- s32 voltage;
+ s64 voltage;
voltage = adc_code - vadc->graph[prop->calibration].gnd;
voltage *= vadc->graph[prop->calibration].dx;
- voltage = voltage / vadc->graph[prop->calibration].dy;
+ voltage = div64_s64(voltage, vadc->graph[prop->calibration].dy);
if (prop->calibration == VADC_CALIB_ABSOLUTE)
voltage += vadc->graph[prop->calibration].dx;
voltage = voltage * prescale->den;
- return voltage / prescale->num;
+ return div64_s64(voltage, prescale->num);
}
static int vadc_decimation_from_dt(u32 value)
switch (chan->address) {
case XADC_REG_VCCINT:
case XADC_REG_VCCAUX:
+ case XADC_REG_VREFP:
case XADC_REG_VCCBRAM:
case XADC_REG_VCCPINT:
case XADC_REG_VCCPAUX:
.num_event_specs = (_alarm) ? ARRAY_SIZE(xadc_voltage_events) : 0, \
.scan_index = (_scan_index), \
.scan_type = { \
- .sign = 'u', \
+ .sign = ((_addr) == XADC_REG_VREFN) ? 's' : 'u', \
.realbits = 12, \
.storagebits = 16, \
.shift = 4, \
static const struct iio_chan_spec xadc_channels[] = {
XADC_CHAN_TEMP(0, 8, XADC_REG_TEMP),
XADC_CHAN_VOLTAGE(0, 9, XADC_REG_VCCINT, "vccint", true),
- XADC_CHAN_VOLTAGE(1, 10, XADC_REG_VCCINT, "vccaux", true),
+ XADC_CHAN_VOLTAGE(1, 10, XADC_REG_VCCAUX, "vccaux", true),
XADC_CHAN_VOLTAGE(2, 14, XADC_REG_VCCBRAM, "vccbram", true),
XADC_CHAN_VOLTAGE(3, 5, XADC_REG_VCCPINT, "vccpint", true),
XADC_CHAN_VOLTAGE(4, 6, XADC_REG_VCCPAUX, "vccpaux", true),
#define XADC_REG_MAX_VCCPINT 0x28
#define XADC_REG_MAX_VCCPAUX 0x29
#define XADC_REG_MAX_VCCO_DDR 0x2a
-#define XADC_REG_MIN_VCCPINT 0x2b
-#define XADC_REG_MIN_VCCPAUX 0x2c
-#define XADC_REG_MIN_VCCO_DDR 0x2d
+#define XADC_REG_MIN_VCCPINT 0x2c
+#define XADC_REG_MIN_VCCPAUX 0x2d
+#define XADC_REG_MIN_VCCO_DDR 0x2e
#define XADC_REG_CONF0 0x40
#define XADC_REG_CONF1 0x41
struct st_sensors_platform_data *of_pdata;
int err = 0;
- mutex_init(&sdata->tb.buf_lock);
-
/* If OF/DT pdata exists, it will take precedence of anything else */
of_pdata = st_sensors_of_probe(indio_dev->dev.parent, pdata);
if (of_pdata)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &gyro_info;
+ mutex_init(&gdata->tb.buf_lock);
st_sensors_power_enable(indio_dev);
kfifo_free(&buf->kf);
ret = __iio_allocate_kfifo(buf, buf->buffer.bytes_per_datum,
buf->buffer.length);
- buf->update_needed = false;
+ if (ret >= 0)
+ buf->update_needed = false;
} else {
kfifo_reset_out(&buf->kf);
}
static const struct iio_chan_spec prox_channels[] = {
{
.type = IIO_PROXIMITY,
- .modified = 1,
- .channel2 = IIO_NO_MOD,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) |
struct iio_dev *indio_dev;
struct prox_state *prox_state;
struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
- struct iio_chan_spec *channels;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct prox_state));
return ret;
}
- channels = kmemdup(prox_channels, sizeof(prox_channels), GFP_KERNEL);
- if (!channels) {
+ indio_dev->channels = kmemdup(prox_channels, sizeof(prox_channels),
+ GFP_KERNEL);
+ if (!indio_dev->channels) {
dev_err(&pdev->dev, "failed to duplicate channels\n");
return -ENOMEM;
}
- ret = prox_parse_report(pdev, hsdev, channels,
+ ret = prox_parse_report(pdev, hsdev,
+ (struct iio_chan_spec *)indio_dev->channels,
HID_USAGE_SENSOR_PROX, prox_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
goto error_free_dev_mem;
}
- indio_dev->channels = channels;
indio_dev->num_channels =
ARRAY_SIZE(prox_channels);
indio_dev->dev.parent = &pdev->dev;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &magn_info;
+ mutex_init(&mdata->tb.buf_lock);
st_sensors_power_enable(indio_dev);
var2 = (((((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1]))) *
((adc_temp >> 4) - ((s32)le16_to_cpu(buf[T1])))) >> 12) *
((s32)(s16)le16_to_cpu(buf[T3]))) >> 14;
+ data->t_fine = var1 + var2;
return (data->t_fine * 5 + 128) >> 8;
}
static const struct iio_chan_spec press_channels[] = {
{
.type = IIO_PRESSURE,
- .modified = 1,
- .channel2 = IIO_NO_MOD,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
BIT(IIO_CHAN_INFO_SCALE) |
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &press_info;
+ mutex_init(&press_data->tb.buf_lock);
st_sensors_power_enable(indio_dev);
} sgid_addr, dgid_addr;
- ret = rdma_gid2ip(&sgid_addr._sockaddr, sgid);
- if (ret)
- return ret;
-
- ret = rdma_gid2ip(&dgid_addr._sockaddr, dgid);
- if (ret)
- return ret;
+ rdma_gid2ip(&sgid_addr._sockaddr, sgid);
+ rdma_gid2ip(&dgid_addr._sockaddr, dgid);
memset(&dev_addr, 0, sizeof(dev_addr));
struct sockaddr_in6 _sockaddr_in6;
} gid_addr;
- ret = rdma_gid2ip(&gid_addr._sockaddr, sgid);
+ rdma_gid2ip(&gid_addr._sockaddr, sgid);
- if (ret)
- return ret;
memset(&dev_addr, 0, sizeof(dev_addr));
ret = rdma_translate_ip(&gid_addr._sockaddr, &dev_addr, vlan_id);
if (ret)
return cm_id_priv;
}
-static void cm_mask_copy(u8 *dst, u8 *src, u8 *mask)
+static void cm_mask_copy(u32 *dst, const u32 *src, const u32 *mask)
{
int i;
- for (i = 0; i < IB_CM_COMPARE_SIZE / sizeof(unsigned long); i++)
- ((unsigned long *) dst)[i] = ((unsigned long *) src)[i] &
- ((unsigned long *) mask)[i];
+ for (i = 0; i < IB_CM_COMPARE_SIZE; i++)
+ dst[i] = src[i] & mask[i];
}
static int cm_compare_data(struct ib_cm_compare_data *src_data,
struct ib_cm_compare_data *dst_data)
{
- u8 src[IB_CM_COMPARE_SIZE];
- u8 dst[IB_CM_COMPARE_SIZE];
+ u32 src[IB_CM_COMPARE_SIZE];
+ u32 dst[IB_CM_COMPARE_SIZE];
if (!src_data || !dst_data)
return 0;
cm_mask_copy(src, src_data->data, dst_data->mask);
cm_mask_copy(dst, dst_data->data, src_data->mask);
- return memcmp(src, dst, IB_CM_COMPARE_SIZE);
+ return memcmp(src, dst, sizeof(src));
}
-static int cm_compare_private_data(u8 *private_data,
+static int cm_compare_private_data(u32 *private_data,
struct ib_cm_compare_data *dst_data)
{
- u8 src[IB_CM_COMPARE_SIZE];
+ u32 src[IB_CM_COMPARE_SIZE];
if (!dst_data)
return 0;
cm_mask_copy(src, private_data, dst_data->mask);
- return memcmp(src, dst_data->data, IB_CM_COMPARE_SIZE);
+ return memcmp(src, dst_data->data, sizeof(src));
}
/*
static struct cm_id_private * cm_find_listen(struct ib_device *device,
__be64 service_id,
- u8 *private_data)
+ u32 *private_data)
{
struct rb_node *node = cm.listen_service_table.rb_node;
struct cm_id_private *cm_id_priv;
cm_mask_copy(cm_id_priv->compare_data->data,
compare_data->data, compare_data->mask);
memcpy(cm_id_priv->compare_data->mask, compare_data->mask,
- IB_CM_COMPARE_SIZE);
+ sizeof(compare_data->mask));
}
cm_id->state = IB_CM_LISTEN;
/* local ACK timeout:5, rsvd:3 */
u8 alt_offset139;
- u8 private_data[IB_CM_REQ_PRIVATE_DATA_SIZE];
+ u32 private_data[IB_CM_REQ_PRIVATE_DATA_SIZE / sizeof(u32)];
} __attribute__ ((packed));
__be16 rsvd;
__be64 service_id;
- u8 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE];
+ u32 private_data[IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE / sizeof(u32)];
} __attribute__ ((packed));
struct cm_sidr_rep_msg {
memcpy(&ib->sib_addr, &path->dgid, 16);
}
+static __be16 ss_get_port(const struct sockaddr_storage *ss)
+{
+ if (ss->ss_family == AF_INET)
+ return ((struct sockaddr_in *)ss)->sin_port;
+ else if (ss->ss_family == AF_INET6)
+ return ((struct sockaddr_in6 *)ss)->sin6_port;
+ BUG();
+}
+
static void cma_save_ip4_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id,
struct cma_hdr *hdr)
{
- struct sockaddr_in *listen4, *ip4;
+ struct sockaddr_in *ip4;
- listen4 = (struct sockaddr_in *) &listen_id->route.addr.src_addr;
ip4 = (struct sockaddr_in *) &id->route.addr.src_addr;
- ip4->sin_family = listen4->sin_family;
+ ip4->sin_family = AF_INET;
ip4->sin_addr.s_addr = hdr->dst_addr.ip4.addr;
- ip4->sin_port = listen4->sin_port;
+ ip4->sin_port = ss_get_port(&listen_id->route.addr.src_addr);
ip4 = (struct sockaddr_in *) &id->route.addr.dst_addr;
- ip4->sin_family = listen4->sin_family;
+ ip4->sin_family = AF_INET;
ip4->sin_addr.s_addr = hdr->src_addr.ip4.addr;
ip4->sin_port = hdr->port;
}
static void cma_save_ip6_info(struct rdma_cm_id *id, struct rdma_cm_id *listen_id,
struct cma_hdr *hdr)
{
- struct sockaddr_in6 *listen6, *ip6;
+ struct sockaddr_in6 *ip6;
- listen6 = (struct sockaddr_in6 *) &listen_id->route.addr.src_addr;
ip6 = (struct sockaddr_in6 *) &id->route.addr.src_addr;
- ip6->sin6_family = listen6->sin6_family;
+ ip6->sin6_family = AF_INET6;
ip6->sin6_addr = hdr->dst_addr.ip6;
- ip6->sin6_port = listen6->sin6_port;
+ ip6->sin6_port = ss_get_port(&listen_id->route.addr.src_addr);
ip6 = (struct sockaddr_in6 *) &id->route.addr.dst_addr;
- ip6->sin6_family = listen6->sin6_family;
+ ip6->sin6_family = AF_INET6;
ip6->sin6_addr = hdr->src_addr.ip6;
ip6->sin6_port = hdr->port;
}
#include "iwpm_util.h"
-static const char iwpm_ulib_name[] = "iWarpPortMapperUser";
+static const char iwpm_ulib_name[IWPM_ULIBNAME_SIZE] = "iWarpPortMapperUser";
static int iwpm_ulib_version = 3;
static int iwpm_user_pid = IWPM_PID_UNDEFINED;
static atomic_t echo_nlmsg_seq;
}
EXPORT_SYMBOL(iwpm_add_mapping_cb);
-/* netlink attribute policy for the response to add and query mapping request */
+/* netlink attribute policy for the response to add and query mapping request
+ * and response with remote address info */
static const struct nla_policy resp_query_policy[IWPM_NLA_RQUERY_MAPPING_MAX] = {
[IWPM_NLA_QUERY_MAPPING_SEQ] = { .type = NLA_U32 },
[IWPM_NLA_QUERY_LOCAL_ADDR] = { .len = sizeof(struct sockaddr_storage) },
}
EXPORT_SYMBOL(iwpm_add_and_query_mapping_cb);
+/*
+ * iwpm_remote_info_cb - Process a port mapper message, containing
+ * the remote connecting peer address info
+ */
+int iwpm_remote_info_cb(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct nlattr *nltb[IWPM_NLA_RQUERY_MAPPING_MAX];
+ struct sockaddr_storage *local_sockaddr, *remote_sockaddr;
+ struct sockaddr_storage *mapped_loc_sockaddr, *mapped_rem_sockaddr;
+ struct iwpm_remote_info *rem_info;
+ const char *msg_type;
+ u8 nl_client;
+ int ret = -EINVAL;
+
+ msg_type = "Remote Mapping info";
+ if (iwpm_parse_nlmsg(cb, IWPM_NLA_RQUERY_MAPPING_MAX,
+ resp_query_policy, nltb, msg_type))
+ return ret;
+
+ nl_client = RDMA_NL_GET_CLIENT(cb->nlh->nlmsg_type);
+ if (!iwpm_valid_client(nl_client)) {
+ pr_info("%s: Invalid port mapper client = %d\n",
+ __func__, nl_client);
+ return ret;
+ }
+ atomic_set(&echo_nlmsg_seq, cb->nlh->nlmsg_seq);
+
+ local_sockaddr = (struct sockaddr_storage *)
+ nla_data(nltb[IWPM_NLA_QUERY_LOCAL_ADDR]);
+ remote_sockaddr = (struct sockaddr_storage *)
+ nla_data(nltb[IWPM_NLA_QUERY_REMOTE_ADDR]);
+ mapped_loc_sockaddr = (struct sockaddr_storage *)
+ nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_LOC_ADDR]);
+ mapped_rem_sockaddr = (struct sockaddr_storage *)
+ nla_data(nltb[IWPM_NLA_RQUERY_MAPPED_REM_ADDR]);
+
+ if (mapped_loc_sockaddr->ss_family != local_sockaddr->ss_family ||
+ mapped_rem_sockaddr->ss_family != remote_sockaddr->ss_family) {
+ pr_info("%s: Sockaddr family doesn't match the requested one\n",
+ __func__);
+ return ret;
+ }
+ rem_info = kzalloc(sizeof(struct iwpm_remote_info), GFP_ATOMIC);
+ if (!rem_info) {
+ pr_err("%s: Unable to allocate a remote info\n", __func__);
+ ret = -ENOMEM;
+ return ret;
+ }
+ memcpy(&rem_info->mapped_loc_sockaddr, mapped_loc_sockaddr,
+ sizeof(struct sockaddr_storage));
+ memcpy(&rem_info->remote_sockaddr, remote_sockaddr,
+ sizeof(struct sockaddr_storage));
+ memcpy(&rem_info->mapped_rem_sockaddr, mapped_rem_sockaddr,
+ sizeof(struct sockaddr_storage));
+ rem_info->nl_client = nl_client;
+
+ iwpm_add_remote_info(rem_info);
+
+ iwpm_print_sockaddr(local_sockaddr,
+ "remote_info: Local sockaddr:");
+ iwpm_print_sockaddr(mapped_loc_sockaddr,
+ "remote_info: Mapped local sockaddr:");
+ iwpm_print_sockaddr(remote_sockaddr,
+ "remote_info: Remote sockaddr:");
+ iwpm_print_sockaddr(mapped_rem_sockaddr,
+ "remote_info: Mapped remote sockaddr:");
+ return ret;
+}
+EXPORT_SYMBOL(iwpm_remote_info_cb);
+
/* netlink attribute policy for the received request for mapping info */
static const struct nla_policy resp_mapinfo_policy[IWPM_NLA_MAPINFO_REQ_MAX] = {
[IWPM_NLA_MAPINFO_ULIB_NAME] = { .type = NLA_STRING,
#include "iwpm_util.h"
-#define IWPM_HASH_BUCKET_SIZE 512
-#define IWPM_HASH_BUCKET_MASK (IWPM_HASH_BUCKET_SIZE - 1)
+#define IWPM_MAPINFO_HASH_SIZE 512
+#define IWPM_MAPINFO_HASH_MASK (IWPM_MAPINFO_HASH_SIZE - 1)
+#define IWPM_REMINFO_HASH_SIZE 64
+#define IWPM_REMINFO_HASH_MASK (IWPM_REMINFO_HASH_SIZE - 1)
static LIST_HEAD(iwpm_nlmsg_req_list);
static DEFINE_SPINLOCK(iwpm_nlmsg_req_lock);
static struct hlist_head *iwpm_hash_bucket;
static DEFINE_SPINLOCK(iwpm_mapinfo_lock);
+static struct hlist_head *iwpm_reminfo_bucket;
+static DEFINE_SPINLOCK(iwpm_reminfo_lock);
+
static DEFINE_MUTEX(iwpm_admin_lock);
static struct iwpm_admin_data iwpm_admin;
int iwpm_init(u8 nl_client)
{
+ int ret = 0;
if (iwpm_valid_client(nl_client))
return -EINVAL;
mutex_lock(&iwpm_admin_lock);
if (atomic_read(&iwpm_admin.refcount) == 0) {
- iwpm_hash_bucket = kzalloc(IWPM_HASH_BUCKET_SIZE *
+ iwpm_hash_bucket = kzalloc(IWPM_MAPINFO_HASH_SIZE *
sizeof(struct hlist_head), GFP_KERNEL);
if (!iwpm_hash_bucket) {
- mutex_unlock(&iwpm_admin_lock);
+ ret = -ENOMEM;
pr_err("%s Unable to create mapinfo hash table\n", __func__);
- return -ENOMEM;
+ goto init_exit;
+ }
+ iwpm_reminfo_bucket = kzalloc(IWPM_REMINFO_HASH_SIZE *
+ sizeof(struct hlist_head), GFP_KERNEL);
+ if (!iwpm_reminfo_bucket) {
+ kfree(iwpm_hash_bucket);
+ ret = -ENOMEM;
+ pr_err("%s Unable to create reminfo hash table\n", __func__);
+ goto init_exit;
}
}
atomic_inc(&iwpm_admin.refcount);
+init_exit:
mutex_unlock(&iwpm_admin_lock);
- iwpm_set_valid(nl_client, 1);
- return 0;
+ if (!ret) {
+ iwpm_set_valid(nl_client, 1);
+ pr_debug("%s: Mapinfo and reminfo tables are created\n",
+ __func__);
+ }
+ return ret;
}
EXPORT_SYMBOL(iwpm_init);
static void free_hash_bucket(void);
+static void free_reminfo_bucket(void);
int iwpm_exit(u8 nl_client)
{
}
if (atomic_dec_and_test(&iwpm_admin.refcount)) {
free_hash_bucket();
- pr_debug("%s: Mapinfo hash table is destroyed\n", __func__);
+ free_reminfo_bucket();
+ pr_debug("%s: Resources are destroyed\n", __func__);
}
mutex_unlock(&iwpm_admin_lock);
iwpm_set_valid(nl_client, 0);
}
EXPORT_SYMBOL(iwpm_exit);
-static struct hlist_head *get_hash_bucket_head(struct sockaddr_storage *,
+static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage *,
struct sockaddr_storage *);
int iwpm_create_mapinfo(struct sockaddr_storage *local_sockaddr,
struct hlist_head *hash_bucket_head;
struct iwpm_mapping_info *map_info;
unsigned long flags;
+ int ret = -EINVAL;
if (!iwpm_valid_client(nl_client))
- return -EINVAL;
+ return ret;
map_info = kzalloc(sizeof(struct iwpm_mapping_info), GFP_KERNEL);
if (!map_info) {
pr_err("%s: Unable to allocate a mapping info\n", __func__);
spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
if (iwpm_hash_bucket) {
- hash_bucket_head = get_hash_bucket_head(
+ hash_bucket_head = get_mapinfo_hash_bucket(
&map_info->local_sockaddr,
&map_info->mapped_sockaddr);
- hlist_add_head(&map_info->hlist_node, hash_bucket_head);
+ if (hash_bucket_head) {
+ hlist_add_head(&map_info->hlist_node, hash_bucket_head);
+ ret = 0;
+ }
}
spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
- return 0;
+ return ret;
}
EXPORT_SYMBOL(iwpm_create_mapinfo);
spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
if (iwpm_hash_bucket) {
- hash_bucket_head = get_hash_bucket_head(
+ hash_bucket_head = get_mapinfo_hash_bucket(
local_sockaddr,
mapped_local_addr);
+ if (!hash_bucket_head)
+ goto remove_mapinfo_exit;
+
hlist_for_each_entry_safe(map_info, tmp_hlist_node,
hash_bucket_head, hlist_node) {
}
}
}
+remove_mapinfo_exit:
spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
return ret;
}
/* remove all the mapinfo data from the list */
spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
- for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) {
+ for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
hlist_for_each_entry_safe(map_info, tmp_hlist_node,
&iwpm_hash_bucket[i], hlist_node) {
spin_unlock_irqrestore(&iwpm_mapinfo_lock, flags);
}
+static void free_reminfo_bucket(void)
+{
+ struct hlist_node *tmp_hlist_node;
+ struct iwpm_remote_info *rem_info;
+ unsigned long flags;
+ int i;
+
+ /* remove all the remote info from the list */
+ spin_lock_irqsave(&iwpm_reminfo_lock, flags);
+ for (i = 0; i < IWPM_REMINFO_HASH_SIZE; i++) {
+ hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
+ &iwpm_reminfo_bucket[i], hlist_node) {
+
+ hlist_del_init(&rem_info->hlist_node);
+ kfree(rem_info);
+ }
+ }
+ /* free the hash list */
+ kfree(iwpm_reminfo_bucket);
+ iwpm_reminfo_bucket = NULL;
+ spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
+}
+
+static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage *,
+ struct sockaddr_storage *);
+
+void iwpm_add_remote_info(struct iwpm_remote_info *rem_info)
+{
+ struct hlist_head *hash_bucket_head;
+ unsigned long flags;
+
+ spin_lock_irqsave(&iwpm_reminfo_lock, flags);
+ if (iwpm_reminfo_bucket) {
+ hash_bucket_head = get_reminfo_hash_bucket(
+ &rem_info->mapped_loc_sockaddr,
+ &rem_info->mapped_rem_sockaddr);
+ if (hash_bucket_head)
+ hlist_add_head(&rem_info->hlist_node, hash_bucket_head);
+ }
+ spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
+}
+
+int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
+ struct sockaddr_storage *mapped_rem_addr,
+ struct sockaddr_storage *remote_addr,
+ u8 nl_client)
+{
+ struct hlist_node *tmp_hlist_node;
+ struct hlist_head *hash_bucket_head;
+ struct iwpm_remote_info *rem_info = NULL;
+ unsigned long flags;
+ int ret = -EINVAL;
+
+ if (!iwpm_valid_client(nl_client)) {
+ pr_info("%s: Invalid client = %d\n", __func__, nl_client);
+ return ret;
+ }
+ spin_lock_irqsave(&iwpm_reminfo_lock, flags);
+ if (iwpm_reminfo_bucket) {
+ hash_bucket_head = get_reminfo_hash_bucket(
+ mapped_loc_addr,
+ mapped_rem_addr);
+ if (!hash_bucket_head)
+ goto get_remote_info_exit;
+ hlist_for_each_entry_safe(rem_info, tmp_hlist_node,
+ hash_bucket_head, hlist_node) {
+
+ if (!iwpm_compare_sockaddr(&rem_info->mapped_loc_sockaddr,
+ mapped_loc_addr) &&
+ !iwpm_compare_sockaddr(&rem_info->mapped_rem_sockaddr,
+ mapped_rem_addr)) {
+
+ memcpy(remote_addr, &rem_info->remote_sockaddr,
+ sizeof(struct sockaddr_storage));
+ iwpm_print_sockaddr(remote_addr,
+ "get_remote_info: Remote sockaddr:");
+
+ hlist_del_init(&rem_info->hlist_node);
+ kfree(rem_info);
+ ret = 0;
+ break;
+ }
+ }
+ }
+get_remote_info_exit:
+ spin_unlock_irqrestore(&iwpm_reminfo_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL(iwpm_get_remote_info);
+
struct iwpm_nlmsg_request *iwpm_get_nlmsg_request(__u32 nlmsg_seq,
u8 nl_client, gfp_t gfp)
{
return hash;
}
-static struct hlist_head *get_hash_bucket_head(struct sockaddr_storage
- *local_sockaddr,
- struct sockaddr_storage
- *mapped_sockaddr)
+static int get_hash_bucket(struct sockaddr_storage *a_sockaddr,
+ struct sockaddr_storage *b_sockaddr, u32 *hash)
{
- u32 local_hash, mapped_hash, hash;
+ u32 a_hash, b_hash;
- if (local_sockaddr->ss_family == AF_INET) {
- local_hash = iwpm_ipv4_jhash((struct sockaddr_in *) local_sockaddr);
- mapped_hash = iwpm_ipv4_jhash((struct sockaddr_in *) mapped_sockaddr);
+ if (a_sockaddr->ss_family == AF_INET) {
+ a_hash = iwpm_ipv4_jhash((struct sockaddr_in *) a_sockaddr);
+ b_hash = iwpm_ipv4_jhash((struct sockaddr_in *) b_sockaddr);
- } else if (local_sockaddr->ss_family == AF_INET6) {
- local_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) local_sockaddr);
- mapped_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) mapped_sockaddr);
+ } else if (a_sockaddr->ss_family == AF_INET6) {
+ a_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) a_sockaddr);
+ b_hash = iwpm_ipv6_jhash((struct sockaddr_in6 *) b_sockaddr);
} else {
pr_err("%s: Invalid sockaddr family\n", __func__);
- return NULL;
+ return -EINVAL;
}
- if (local_hash == mapped_hash) /* if port mapper isn't available */
- hash = local_hash;
+ if (a_hash == b_hash) /* if port mapper isn't available */
+ *hash = a_hash;
else
- hash = jhash_2words(local_hash, mapped_hash, 0);
+ *hash = jhash_2words(a_hash, b_hash, 0);
+ return 0;
+}
+
+static struct hlist_head *get_mapinfo_hash_bucket(struct sockaddr_storage
+ *local_sockaddr, struct sockaddr_storage
+ *mapped_sockaddr)
+{
+ u32 hash;
+ int ret;
- return &iwpm_hash_bucket[hash & IWPM_HASH_BUCKET_MASK];
+ ret = get_hash_bucket(local_sockaddr, mapped_sockaddr, &hash);
+ if (ret)
+ return NULL;
+ return &iwpm_hash_bucket[hash & IWPM_MAPINFO_HASH_MASK];
+}
+
+static struct hlist_head *get_reminfo_hash_bucket(struct sockaddr_storage
+ *mapped_loc_sockaddr, struct sockaddr_storage
+ *mapped_rem_sockaddr)
+{
+ u32 hash;
+ int ret;
+
+ ret = get_hash_bucket(mapped_loc_sockaddr, mapped_rem_sockaddr, &hash);
+ if (ret)
+ return NULL;
+ return &iwpm_reminfo_bucket[hash & IWPM_REMINFO_HASH_MASK];
}
static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid)
}
skb_num++;
spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
- for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) {
+ for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
hlist_for_each_entry(map_info, &iwpm_hash_bucket[i],
hlist_node) {
if (map_info->nl_client != nl_client)
spin_lock_irqsave(&iwpm_mapinfo_lock, flags);
if (iwpm_hash_bucket) {
- for (i = 0; i < IWPM_HASH_BUCKET_SIZE; i++) {
+ for (i = 0; i < IWPM_MAPINFO_HASH_SIZE; i++) {
if (!hlist_empty(&iwpm_hash_bucket[i])) {
full_bucket = 1;
break;
u8 nl_client;
};
+struct iwpm_remote_info {
+ struct hlist_node hlist_node;
+ struct sockaddr_storage remote_sockaddr;
+ struct sockaddr_storage mapped_loc_sockaddr;
+ struct sockaddr_storage mapped_rem_sockaddr;
+ u8 nl_client;
+};
+
struct iwpm_admin_data {
atomic_t refcount;
atomic_t nlmsg_seq;
*/
int iwpm_get_nlmsg_seq(void);
+/**
+ * iwpm_add_reminfo - Add remote address info of the connecting peer
+ * to the remote info hash table
+ * @reminfo: The remote info to be added
+ */
+void iwpm_add_remote_info(struct iwpm_remote_info *reminfo);
+
/**
* iwpm_valid_client - Check if the port mapper client is valid
* @nl_client: The index of the netlink client
int remove_existing_mapping = 0;
int ret = 0;
- mutex_lock(&umem->odp_data->umem_mutex);
/*
* Note: we avoid writing if seq is different from the initial seq, to
* handle case of a racing notifier. This check also allows us to bail
}
out:
- mutex_unlock(&umem->odp_data->umem_mutex);
-
/* On Demand Paging - avoid pinning the page */
if (umem->context->invalidate_range || !stored_page)
put_page(page);
bcnt -= min_t(size_t, npages << PAGE_SHIFT, bcnt);
user_virt += npages << PAGE_SHIFT;
+ mutex_lock(&umem->odp_data->umem_mutex);
for (j = 0; j < npages; ++j) {
ret = ib_umem_odp_map_dma_single_page(
umem, k, base_virt_addr, local_page_list[j],
break;
k++;
}
+ mutex_unlock(&umem->odp_data->umem_mutex);
if (ret < 0) {
/* Release left over pages when handling errors. */
* faults from completion. We might be racing with other
* invalidations, so we must make sure we free each page only
* once. */
+ mutex_lock(&umem->odp_data->umem_mutex);
for (addr = virt; addr < bound; addr += (u64)umem->page_size) {
idx = (addr - ib_umem_start(umem)) / PAGE_SIZE;
- mutex_lock(&umem->odp_data->umem_mutex);
if (umem->odp_data->page_list[idx]) {
struct page *page = umem->odp_data->page_list[idx];
- struct page *head_page = compound_head(page);
dma_addr_t dma = umem->odp_data->dma_list[idx];
dma_addr_t dma_addr = dma & ODP_DMA_ADDR_MASK;
ib_dma_unmap_page(dev, dma_addr, PAGE_SIZE,
DMA_BIDIRECTIONAL);
- if (dma & ODP_WRITE_ALLOWED_BIT)
+ if (dma & ODP_WRITE_ALLOWED_BIT) {
+ struct page *head_page = compound_head(page);
/*
* set_page_dirty prefers being called with
* the page lock. However, MMU notifiers are
* be removed.
*/
set_page_dirty(head_page);
+ }
/* on demand pinning support */
if (!umem->context->invalidate_range)
put_page(page);
umem->odp_data->page_list[idx] = NULL;
umem->odp_data->dma_list[idx] = 0;
}
- mutex_unlock(&umem->odp_data->umem_mutex);
}
+ mutex_unlock(&umem->odp_data->umem_mutex);
}
EXPORT_SYMBOL(ib_umem_odp_unmap_dma_pages);
sizeof(ep->com.mapped_remote_addr));
}
+static int get_remote_addr(struct c4iw_ep *parent_ep, struct c4iw_ep *child_ep)
+{
+ int ret;
+
+ print_addr(&parent_ep->com, __func__, "get_remote_addr parent_ep ");
+ print_addr(&child_ep->com, __func__, "get_remote_addr child_ep ");
+
+ ret = iwpm_get_remote_info(&parent_ep->com.mapped_local_addr,
+ &child_ep->com.mapped_remote_addr,
+ &child_ep->com.remote_addr, RDMA_NL_C4IW);
+ if (ret)
+ PDBG("Unable to find remote peer addr info - err %d\n", ret);
+
+ return ret;
+}
+
static void best_mtu(const unsigned short *mtus, unsigned short mtu,
unsigned int *idx, int use_ts, int ipv6)
{
if (is_t5(ep->com.dev->rdev.lldi.adapter_type)) {
opt2 |= T5_OPT_2_VALID_F;
opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE);
- opt2 |= CONG_CNTRL_VALID; /* OPT_2_ISS for T5 */
+ opt2 |= T5_ISS_F;
}
t4_set_arp_err_handler(skb, ep, act_open_req_arp_failure);
status, status2errno(status));
if (is_neg_adv(status)) {
- dev_warn(&dev->rdev.lldi.pdev->dev,
- "Connection problems for atid %u status %u (%s)\n",
- atid, status, neg_adv_str(status));
+ PDBG("%s Connection problems for atid %u status %u (%s)\n",
+ __func__, atid, status, neg_adv_str(status));
+ ep->stats.connect_neg_adv++;
+ mutex_lock(&dev->rdev.stats.lock);
+ dev->rdev.stats.neg_adv++;
+ mutex_unlock(&dev->rdev.stats.lock);
return 0;
}
u32 isn = (prandom_u32() & ~7UL) - 1;
opt2 |= T5_OPT_2_VALID_F;
opt2 |= CONG_CNTRL_V(CONG_ALG_TAHOE);
- opt2 |= CONG_CNTRL_VALID; /* OPT_2_ISS for T5 */
+ opt2 |= T5_ISS_F;
rpl5 = (void *)rpl;
memset(&rpl5->iss, 0, roundup(sizeof(*rpl5)-sizeof(*rpl), 16));
if (peer2peer)
state_set(&child_ep->com, CONNECTING);
child_ep->com.dev = dev;
child_ep->com.cm_id = NULL;
+
+ /*
+ * The mapped_local and mapped_remote addresses get setup with
+ * the actual 4-tuple. The local address will be based on the
+ * actual local address of the connection, but on the port number
+ * of the parent listening endpoint. The remote address is
+ * setup based on a query to the IWPM since we don't know what it
+ * originally was before mapping. If no mapping was done, then
+ * mapped_remote == remote, and mapped_local == local.
+ */
if (iptype == 4) {
struct sockaddr_in *sin = (struct sockaddr_in *)
- &child_ep->com.local_addr;
+ &child_ep->com.mapped_local_addr;
+
sin->sin_family = PF_INET;
sin->sin_port = local_port;
sin->sin_addr.s_addr = *(__be32 *)local_ip;
- sin = (struct sockaddr_in *)&child_ep->com.remote_addr;
+
+ sin = (struct sockaddr_in *)&child_ep->com.local_addr;
+ sin->sin_family = PF_INET;
+ sin->sin_port = ((struct sockaddr_in *)
+ &parent_ep->com.local_addr)->sin_port;
+ sin->sin_addr.s_addr = *(__be32 *)local_ip;
+
+ sin = (struct sockaddr_in *)&child_ep->com.mapped_remote_addr;
sin->sin_family = PF_INET;
sin->sin_port = peer_port;
sin->sin_addr.s_addr = *(__be32 *)peer_ip;
} else {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)
- &child_ep->com.local_addr;
+ &child_ep->com.mapped_local_addr;
+
sin6->sin6_family = PF_INET6;
sin6->sin6_port = local_port;
memcpy(sin6->sin6_addr.s6_addr, local_ip, 16);
- sin6 = (struct sockaddr_in6 *)&child_ep->com.remote_addr;
+
+ sin6 = (struct sockaddr_in6 *)&child_ep->com.local_addr;
+ sin6->sin6_family = PF_INET6;
+ sin6->sin6_port = ((struct sockaddr_in6 *)
+ &parent_ep->com.local_addr)->sin6_port;
+ memcpy(sin6->sin6_addr.s6_addr, local_ip, 16);
+
+ sin6 = (struct sockaddr_in6 *)&child_ep->com.mapped_remote_addr;
sin6->sin6_family = PF_INET6;
sin6->sin6_port = peer_port;
memcpy(sin6->sin6_addr.s6_addr, peer_ip, 16);
}
+ memcpy(&child_ep->com.remote_addr, &child_ep->com.mapped_remote_addr,
+ sizeof(child_ep->com.remote_addr));
+ get_remote_addr(parent_ep, child_ep);
+
c4iw_get_ep(&parent_ep->com);
child_ep->parent_ep = parent_ep;
child_ep->tos = PASS_OPEN_TOS_G(ntohl(req->tos_stid));
ep = lookup_tid(t, tid);
if (is_neg_adv(req->status)) {
- dev_warn(&dev->rdev.lldi.pdev->dev,
- "Negative advice on abort - tid %u status %d (%s)\n",
- ep->hwtid, req->status, neg_adv_str(req->status));
+ PDBG("%s Negative advice on abort- tid %u status %d (%s)\n",
+ __func__, ep->hwtid, req->status,
+ neg_adv_str(req->status));
+ ep->stats.abort_neg_adv++;
+ mutex_lock(&dev->rdev.stats.lock);
+ dev->rdev.stats.neg_adv++;
+ mutex_unlock(&dev->rdev.stats.lock);
return 0;
}
PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
* TP will ignore any value > 0 for MSS index.
*/
req->tcb.opt0 = cpu_to_be64(MSS_IDX_V(0xF));
- req->cookie = (unsigned long)skb;
+ req->cookie = (uintptr_t)skb;
set_wr_txq(req_skb, CPL_PRIORITY_CONTROL, port_id);
ret = cxgb4_ofld_send(dev->rdev.lldi.ports[0], req_skb);
return 0;
}
if (is_neg_adv(req->status)) {
- dev_warn(&dev->rdev.lldi.pdev->dev,
- "Negative advice on abort - tid %u status %d (%s)\n",
- ep->hwtid, req->status, neg_adv_str(req->status));
+ PDBG("%s Negative advice on abort- tid %u status %d (%s)\n",
+ __func__, ep->hwtid, req->status,
+ neg_adv_str(req->status));
+ ep->stats.abort_neg_adv++;
+ dev->rdev.stats.neg_adv++;
kfree_skb(skb);
return 0;
}
FW_RI_RES_WR_NRES_V(1) |
FW_WR_COMPL_F);
res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
- res_wr->cookie = (unsigned long) &wr_wait;
+ res_wr->cookie = (uintptr_t)&wr_wait;
res = res_wr->res;
res->u.cq.restype = FW_RI_RES_TYPE_CQ;
res->u.cq.op = FW_RI_RES_OP_RESET;
FW_RI_RES_WR_NRES_V(1) |
FW_WR_COMPL_F);
res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
- res_wr->cookie = (unsigned long) &wr_wait;
+ res_wr->cookie = (uintptr_t)&wr_wait;
res = res_wr->res;
res->u.cq.restype = FW_RI_RES_TYPE_CQ;
res->u.cq.op = FW_RI_RES_OP_WRITE;
goto err4;
cq->gen = 1;
- cq->gts = rdev->lldi.gts_reg;
cq->rdev = rdev;
if (user) {
- cq->ugts = (u64)pci_resource_start(rdev->lldi.pdev, 2) +
- (cq->cqid << rdev->cqshift);
- cq->ugts &= PAGE_MASK;
+ u32 off = (cq->cqid << rdev->cqshift) & PAGE_MASK;
+
+ cq->ugts = (u64)rdev->bar2_pa + off;
+ } else if (is_t4(rdev->lldi.adapter_type)) {
+ cq->gts = rdev->lldi.gts_reg;
+ cq->qid_mask = -1U;
+ } else {
+ u32 off = ((cq->cqid << rdev->cqshift) & PAGE_MASK) + 12;
+
+ cq->gts = rdev->bar2_kva + off;
+ cq->qid_mask = rdev->qpmask;
}
return 0;
err4:
}
PDBG("%s cqid 0x%0x chp %p size %u memsize %zu, dma_addr 0x%0llx\n",
__func__, chp->cq.cqid, chp, chp->cq.size,
- chp->cq.memsize,
- (unsigned long long) chp->cq.dma_addr);
+ chp->cq.memsize, (unsigned long long) chp->cq.dma_addr);
return &chp->ibcq;
err5:
kfree(mm2);
[RDMA_NL_IWPM_ADD_MAPPING] = {.dump = iwpm_add_mapping_cb},
[RDMA_NL_IWPM_QUERY_MAPPING] = {.dump = iwpm_add_and_query_mapping_cb},
[RDMA_NL_IWPM_HANDLE_ERR] = {.dump = iwpm_mapping_error_cb},
+ [RDMA_NL_IWPM_REMOTE_INFO] = {.dump = iwpm_remote_info_cb},
[RDMA_NL_IWPM_MAPINFO] = {.dump = iwpm_mapping_info_cb},
[RDMA_NL_IWPM_MAPINFO_NUM] = {.dump = iwpm_ack_mapping_info_cb}
};
int prev_ts_set = 0;
int idx, end;
-#define ts2ns(ts) div64_ul((ts) * dev->rdev.lldi.cclk_ps, 1000)
+#define ts2ns(ts) div64_u64((ts) * dev->rdev.lldi.cclk_ps, 1000)
idx = atomic_read(&dev->rdev.wr_log_idx) &
(dev->rdev.wr_log_size - 1);
dev->rdev.stats.act_ofld_conn_fails);
seq_printf(seq, "PAS_OFLD_CONN_FAILS: %10llu\n",
dev->rdev.stats.pas_ofld_conn_fails);
+ seq_printf(seq, "NEG_ADV_RCVD: %10llu\n", dev->rdev.stats.neg_adv);
seq_printf(seq, "AVAILABLE IRD: %10u\n", dev->avail_ird);
return 0;
}
cc = snprintf(epd->buf + epd->pos, space,
"ep %p cm_id %p qp %p state %d flags 0x%lx "
"history 0x%lx hwtid %d atid %d "
+ "conn_na %u abort_na %u "
"%pI4:%d/%d <-> %pI4:%d/%d\n",
ep, ep->com.cm_id, ep->com.qp,
(int)ep->com.state, ep->com.flags,
ep->com.history, ep->hwtid, ep->atid,
+ ep->stats.connect_neg_adv,
+ ep->stats.abort_neg_adv,
&lsin->sin_addr, ntohs(lsin->sin_port),
ntohs(mapped_lsin->sin_port),
&rsin->sin_addr, ntohs(rsin->sin_port),
cc = snprintf(epd->buf + epd->pos, space,
"ep %p cm_id %p qp %p state %d flags 0x%lx "
"history 0x%lx hwtid %d atid %d "
+ "conn_na %u abort_na %u "
"%pI6:%d/%d <-> %pI6:%d/%d\n",
ep, ep->com.cm_id, ep->com.qp,
(int)ep->com.state, ep->com.flags,
ep->com.history, ep->hwtid, ep->atid,
+ ep->stats.connect_neg_adv,
+ ep->stats.abort_neg_adv,
&lsin6->sin6_addr, ntohs(lsin6->sin6_port),
ntohs(mapped_lsin6->sin6_port),
&rsin6->sin6_addr, ntohs(rsin6->sin6_port),
c4iw_init_dev_ucontext(rdev, &rdev->uctx);
+ /*
+ * This implementation assumes udb_density == ucq_density! Eventually
+ * we might need to support this but for now fail the open. Also the
+ * cqid and qpid range must match for now.
+ */
+ if (rdev->lldi.udb_density != rdev->lldi.ucq_density) {
+ pr_err(MOD "%s: unsupported udb/ucq densities %u/%u\n",
+ pci_name(rdev->lldi.pdev), rdev->lldi.udb_density,
+ rdev->lldi.ucq_density);
+ err = -EINVAL;
+ goto err1;
+ }
+ if (rdev->lldi.vr->qp.start != rdev->lldi.vr->cq.start ||
+ rdev->lldi.vr->qp.size != rdev->lldi.vr->cq.size) {
+ pr_err(MOD "%s: unsupported qp and cq id ranges "
+ "qp start %u size %u cq start %u size %u\n",
+ pci_name(rdev->lldi.pdev), rdev->lldi.vr->qp.start,
+ rdev->lldi.vr->qp.size, rdev->lldi.vr->cq.size,
+ rdev->lldi.vr->cq.size);
+ err = -EINVAL;
+ goto err1;
+ }
+
/*
* qpshift is the number of bits to shift the qpid left in order
* to get the correct address of the doorbell for that qp.
rdev->lldi.vr->qp.size,
rdev->lldi.vr->cq.start,
rdev->lldi.vr->cq.size);
- PDBG("udb len 0x%x udb base %llx db_reg %p gts_reg %p qpshift %lu "
+ PDBG("udb len 0x%x udb base %p db_reg %p gts_reg %p qpshift %lu "
"qpmask 0x%x cqshift %lu cqmask 0x%x\n",
(unsigned)pci_resource_len(rdev->lldi.pdev, 2),
- (u64)pci_resource_start(rdev->lldi.pdev, 2),
+ (void *)pci_resource_start(rdev->lldi.pdev, 2),
rdev->lldi.db_reg,
rdev->lldi.gts_reg,
rdev->qpshift, rdev->qpmask,
t4_sq_host_wq_pidx(&qp->wq),
t4_sq_wq_size(&qp->wq));
if (ret) {
- pr_err(KERN_ERR MOD "%s: Fatal error - "
+ pr_err(MOD "%s: Fatal error - "
"DB overflow recovery failed - "
"error syncing SQ qid %u\n",
pci_name(ctx->lldi.pdev), qp->wq.sq.qid);
t4_rq_wq_size(&qp->wq));
if (ret) {
- pr_err(KERN_ERR MOD "%s: Fatal error - "
+ pr_err(MOD "%s: Fatal error - "
"DB overflow recovery failed - "
"error syncing RQ qid %u\n",
pci_name(ctx->lldi.pdev), qp->wq.rq.qid);
u64 tcam_full;
u64 act_ofld_conn_fails;
u64 pas_ofld_conn_fails;
+ u64 neg_adv;
};
struct c4iw_hw_queue {
int backlog;
};
+struct c4iw_ep_stats {
+ unsigned connect_neg_adv;
+ unsigned abort_neg_adv;
+};
+
struct c4iw_ep {
struct c4iw_ep_common com;
struct c4iw_ep *parent_ep;
unsigned int retry_count;
int snd_win;
int rcv_win;
+ struct c4iw_ep_stats stats;
};
static inline void print_addr(struct c4iw_ep_common *epc, const char *func,
if (i == (num_wqe-1)) {
req->wr.wr_hi = cpu_to_be32(FW_WR_OP_V(FW_ULPTX_WR) |
FW_WR_COMPL_F);
- req->wr.wr_lo = (__force __be64)(unsigned long) &wr_wait;
+ req->wr.wr_lo = (__force __be64)&wr_wait;
} else
req->wr.wr_hi = cpu_to_be32(FW_WR_OP_V(FW_ULPTX_WR));
req->wr.wr_mid = cpu_to_be32(
mhp->attr.zbva = 0;
mhp->attr.va_fbo = 0;
mhp->attr.page_size = 0;
- mhp->attr.len = ~0UL;
+ mhp->attr.len = ~0ULL;
mhp->attr.pbl_size = 0;
ret = write_tpt_entry(&rhp->rdev, 0, &stag, 1, php->pdid,
FW_RI_STAG_NSMR, mhp->attr.perms,
- mhp->attr.mw_bind_enable, 0, 0, ~0UL, 0, 0, 0);
+ mhp->attr.mw_bind_enable, 0, 0, ~0ULL, 0, 0, 0);
if (ret)
goto err1;
FW_RI_RES_WR_NRES_V(2) |
FW_WR_COMPL_F);
res_wr->len16_pkd = cpu_to_be32(DIV_ROUND_UP(wr_len, 16));
- res_wr->cookie = (unsigned long) &wr_wait;
+ res_wr->cookie = (uintptr_t)&wr_wait;
res = res_wr->res;
res->u.sqrq.restype = FW_RI_RES_TYPE_SQ;
res->u.sqrq.op = FW_RI_RES_OP_WRITE;
wqe->flowid_len16 = cpu_to_be32(
FW_WR_FLOWID_V(ep->hwtid) |
FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*wqe), 16)));
- wqe->cookie = (unsigned long) &ep->com.wr_wait;
+ wqe->cookie = (uintptr_t)&ep->com.wr_wait;
wqe->u.fini.type = FW_RI_TYPE_FINI;
ret = c4iw_ofld_send(&rhp->rdev, skb);
FW_WR_FLOWID_V(qhp->ep->hwtid) |
FW_WR_LEN16_V(DIV_ROUND_UP(sizeof(*wqe), 16)));
- wqe->cookie = (unsigned long) &qhp->ep->com.wr_wait;
+ wqe->cookie = (uintptr_t)&qhp->ep->com.wr_wait;
wqe->u.init.type = FW_RI_TYPE_INIT;
wqe->u.init.mpareqbit_p2ptype =
mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize);
insert_mmap(ucontext, mm2);
mm3->key = uresp.sq_db_gts_key;
- mm3->addr = (__force unsigned long) qhp->wq.sq.udb;
+ mm3->addr = (__force unsigned long)qhp->wq.sq.udb;
mm3->len = PAGE_SIZE;
insert_mmap(ucontext, mm3);
mm4->key = uresp.rq_db_gts_key;
- mm4->addr = (__force unsigned long) qhp->wq.rq.udb;
+ mm4->addr = (__force unsigned long)qhp->wq.rq.udb;
mm4->len = PAGE_SIZE;
insert_mmap(ucontext, mm4);
if (mm5) {
size_t memsize;
__be64 bits_type_ts;
u32 cqid;
+ u32 qid_mask;
int vector;
u16 size; /* including status page */
u16 cidx;
set_bit(CQ_ARMED, &cq->flags);
while (cq->cidx_inc > CIDXINC_M) {
val = SEINTARM_V(0) | CIDXINC_V(CIDXINC_M) | TIMERREG_V(7) |
- INGRESSQID_V(cq->cqid);
+ INGRESSQID_V(cq->cqid & cq->qid_mask);
writel(val, cq->gts);
cq->cidx_inc -= CIDXINC_M;
}
val = SEINTARM_V(se) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(6) |
- INGRESSQID_V(cq->cqid);
+ INGRESSQID_V(cq->cqid & cq->qid_mask);
writel(val, cq->gts);
cq->cidx_inc = 0;
return 0;
u32 val;
val = SEINTARM_V(0) | CIDXINC_V(cq->cidx_inc) | TIMERREG_V(7) |
- INGRESSQID_V(cq->cqid);
+ INGRESSQID_V(cq->cqid & cq->qid_mask);
writel(val, cq->gts);
cq->cidx_inc = 0;
}
#define CONG_CNTRL_V(x) ((x) << CONG_CNTRL_S)
#define CONG_CNTRL_G(x) (((x) >> CONG_CNTRL_S) & CONG_CNTRL_M)
-#define CONG_CNTRL_VALID (1 << 18)
+#define T5_ISS_S 18
+#define T5_ISS_V(x) ((x) << T5_ISS_S)
+#define T5_ISS_F T5_ISS_V(1U)
#endif /* _T4FW_RI_API_H_ */
return -EINVAL;
}
- memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid));
+ memcpy(&my_gid, gid->raw, sizeof(union ib_gid));
subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);
interface_id = be64_to_cpu(my_gid.global.interface_id);
return -EINVAL;
}
- memcpy(&my_gid.raw, gid->raw, sizeof(union ib_gid));
+ memcpy(&my_gid, gid->raw, sizeof(union ib_gid));
subnet_prefix = be64_to_cpu(my_gid.global.subnet_prefix);
interface_id = be64_to_cpu(my_gid.global.interface_id);
MLX4_CMD_TIME_CLASS_B,
MLX4_CMD_WRAPPED);
if (err)
- pr_warn(KERN_WARNING
- "set port %d command failed\n", gw->port);
+ pr_warn("set port %d command failed\n", gw->port);
}
mlx4_free_cmd_mailbox(dev, mailbox);
if (ah->ah_flags & IB_AH_GRH) {
if (ah->grh.sgid_index >= gen->port[port - 1].gid_table_len) {
- pr_err(KERN_ERR "sgid_index (%u) too large. max is %d\n",
+ pr_err("sgid_index (%u) too large. max is %d\n",
ah->grh.sgid_index, gen->port[port - 1].gid_table_len);
return -EINVAL;
}
[RDMA_NL_IWPM_REG_PID] = {.dump = iwpm_register_pid_cb},
[RDMA_NL_IWPM_ADD_MAPPING] = {.dump = iwpm_add_mapping_cb},
[RDMA_NL_IWPM_QUERY_MAPPING] = {.dump = iwpm_add_and_query_mapping_cb},
+ [RDMA_NL_IWPM_REMOTE_INFO] = {.dump = iwpm_remote_info_cb},
[RDMA_NL_IWPM_HANDLE_ERR] = {.dump = iwpm_mapping_error_cb},
[RDMA_NL_IWPM_MAPINFO] = {.dump = iwpm_mapping_info_cb},
[RDMA_NL_IWPM_MAPINFO_NUM] = {.dump = iwpm_ack_mapping_info_cb}
memcpy(pm_msg->if_name, nesvnic->netdev->name, IWPM_IFNAME_SIZE);
}
+static void record_sockaddr_info(struct sockaddr_storage *addr_info,
+ nes_addr_t *ip_addr, u16 *port_num)
+{
+ struct sockaddr_in *in_addr = (struct sockaddr_in *)addr_info;
+
+ if (in_addr->sin_family == AF_INET) {
+ *ip_addr = ntohl(in_addr->sin_addr.s_addr);
+ *port_num = ntohs(in_addr->sin_port);
+ }
+}
+
/*
* nes_record_pm_msg - Save the received mapping info
*/
static void nes_record_pm_msg(struct nes_cm_info *cm_info,
struct iwpm_sa_data *pm_msg)
{
- struct sockaddr_in *mapped_loc_addr =
- (struct sockaddr_in *)&pm_msg->mapped_loc_addr;
- struct sockaddr_in *mapped_rem_addr =
- (struct sockaddr_in *)&pm_msg->mapped_rem_addr;
-
- if (mapped_loc_addr->sin_family == AF_INET) {
- cm_info->mapped_loc_addr =
- ntohl(mapped_loc_addr->sin_addr.s_addr);
- cm_info->mapped_loc_port = ntohs(mapped_loc_addr->sin_port);
- }
- if (mapped_rem_addr->sin_family == AF_INET) {
- cm_info->mapped_rem_addr =
- ntohl(mapped_rem_addr->sin_addr.s_addr);
- cm_info->mapped_rem_port = ntohs(mapped_rem_addr->sin_port);
- }
+ record_sockaddr_info(&pm_msg->mapped_loc_addr,
+ &cm_info->mapped_loc_addr, &cm_info->mapped_loc_port);
+
+ record_sockaddr_info(&pm_msg->mapped_rem_addr,
+ &cm_info->mapped_rem_addr, &cm_info->mapped_rem_port);
+}
+
+/*
+ * nes_get_reminfo - Get the address info of the remote connecting peer
+ */
+static int nes_get_remote_addr(struct nes_cm_node *cm_node)
+{
+ struct sockaddr_storage mapped_loc_addr, mapped_rem_addr;
+ struct sockaddr_storage remote_addr;
+ int ret;
+
+ nes_create_sockaddr(htonl(cm_node->mapped_loc_addr),
+ htons(cm_node->mapped_loc_port), &mapped_loc_addr);
+ nes_create_sockaddr(htonl(cm_node->mapped_rem_addr),
+ htons(cm_node->mapped_rem_port), &mapped_rem_addr);
+
+ ret = iwpm_get_remote_info(&mapped_loc_addr, &mapped_rem_addr,
+ &remote_addr, RDMA_NL_NES);
+ if (ret)
+ nes_debug(NES_DBG_CM, "Unable to find remote peer address info\n");
+ else
+ record_sockaddr_info(&remote_addr, &cm_node->rem_addr,
+ &cm_node->rem_port);
+ return ret;
}
/**
return NULL;
/* set our node specific transport info */
- cm_node->loc_addr = cm_info->loc_addr;
+ if (listener) {
+ cm_node->loc_addr = listener->loc_addr;
+ cm_node->loc_port = listener->loc_port;
+ } else {
+ cm_node->loc_addr = cm_info->loc_addr;
+ cm_node->loc_port = cm_info->loc_port;
+ }
cm_node->rem_addr = cm_info->rem_addr;
- cm_node->loc_port = cm_info->loc_port;
cm_node->rem_port = cm_info->rem_port;
cm_node->mapped_loc_addr = cm_info->mapped_loc_addr;
cm_node->state = NES_CM_STATE_ESTABLISHED;
if (datasize) {
cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize;
+ nes_get_remote_addr(cm_node);
handle_rcv_mpa(cm_node, skb);
} else { /* rcvd ACK only */
dev_kfree_skb_any(skb);
/* PCI Device ID (here for NodeInfo) */
u16 deviceid;
/* for write combining settings */
- unsigned long wc_cookie;
+ int wc_cookie;
unsigned long wc_base;
unsigned long wc_len;
extern u32 qib_cpulist_count;
extern unsigned long *qib_cpulist;
-extern unsigned qib_wc_pat;
extern unsigned qib_cc_table_size;
int qib_init(struct qib_devdata *, int);
int init_chip_wc_pat(struct qib_devdata *dd, u32);
vma->vm_flags &= ~VM_MAYREAD;
vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND;
- if (qib_wc_pat)
+ /* We used PAT if wc_cookie == 0 */
+ if (!dd->wc_cookie)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
ret = io_remap_pfn_range(vma, vma->vm_start, phys >> PAGE_SHIFT,
qib_6120_config_ctxts(dd);
qib_set_ctxtcnt(dd);
- if (qib_wc_pat) {
- ret = init_chip_wc_pat(dd, 0);
- if (ret)
- goto bail;
- }
+ ret = init_chip_wc_pat(dd, 0);
+ if (ret)
+ goto bail;
set_6120_baseaddrs(dd); /* set chip access pointers now */
ret = 0;
qib_7220_config_ctxts(dd);
qib_set_ctxtcnt(dd); /* needed for PAT setup */
- if (qib_wc_pat) {
- ret = init_chip_wc_pat(dd, 0);
- if (ret)
- goto bail;
- }
+ ret = init_chip_wc_pat(dd, 0);
+ if (ret)
+ goto bail;
set_7220_baseaddrs(dd); /* set chip access pointers now */
ret = 0;
unsigned features, pidx, sbufcnt;
int ret, mtu;
u32 sbufs, updthresh;
+ resource_size_t vl15off;
/* pport structs are contiguous, allocated after devdata */
ppd = (struct qib_pportdata *)(dd + 1);
qib_7322_config_ctxts(dd);
qib_set_ctxtcnt(dd);
- if (qib_wc_pat) {
- resource_size_t vl15off;
- /*
- * We do not set WC on the VL15 buffers to avoid
- * a rare problem with unaligned writes from
- * interrupt-flushed store buffers, so we need
- * to map those separately here. We can't solve
- * this for the rarely used mtrr case.
- */
- ret = init_chip_wc_pat(dd, 0);
- if (ret)
- goto bail;
+ /*
+ * We do not set WC on the VL15 buffers to avoid
+ * a rare problem with unaligned writes from
+ * interrupt-flushed store buffers, so we need
+ * to map those separately here. We can't solve
+ * this for the rarely used mtrr case.
+ */
+ ret = init_chip_wc_pat(dd, 0);
+ if (ret)
+ goto bail;
- /* vl15 buffers start just after the 4k buffers */
- vl15off = dd->physaddr + (dd->piobufbase >> 32) +
- dd->piobcnt4k * dd->align4k;
- dd->piovl15base = ioremap_nocache(vl15off,
- NUM_VL15_BUFS * dd->align4k);
- if (!dd->piovl15base) {
- ret = -ENOMEM;
- goto bail;
- }
+ /* vl15 buffers start just after the 4k buffers */
+ vl15off = dd->physaddr + (dd->piobufbase >> 32) +
+ dd->piobcnt4k * dd->align4k;
+ dd->piovl15base = ioremap_nocache(vl15off,
+ NUM_VL15_BUFS * dd->align4k);
+ if (!dd->piovl15base) {
+ ret = -ENOMEM;
+ goto bail;
}
+
qib_7322_set_baseaddrs(dd); /* set chip access pointers now */
ret = 0;
unsigned qib_cc_table_size;
module_param_named(cc_table_size, qib_cc_table_size, uint, S_IRUGO);
MODULE_PARM_DESC(cc_table_size, "Congestion control table entries 0 (CCA disabled - default), min = 128, max = 1984");
-/*
- * qib_wc_pat parameter:
- * 0 is WC via MTRR
- * 1 is WC via PAT
- * If PAT initialization fails, code reverts back to MTRR
- */
-unsigned qib_wc_pat = 1; /* default (1) is to use PAT, not MTRR */
-module_param_named(wc_pat, qib_wc_pat, uint, S_IRUGO);
-MODULE_PARM_DESC(wc_pat, "enable write-combining via PAT mechanism");
static void verify_interrupt(unsigned long);
spin_unlock(&dd->pport[pidx].cc_shadow_lock);
}
- if (!qib_wc_pat)
- qib_disable_wc(dd);
+ qib_disable_wc(dd);
if (dd->pioavailregs_dma) {
dma_free_coherent(&dd->pcidev->dev, PAGE_SIZE,
goto bail;
}
- if (!qib_wc_pat) {
- ret = qib_enable_wc(dd);
- if (ret) {
- qib_dev_err(dd,
- "Write combining not enabled (err %d): performance may be poor\n",
- -ret);
- ret = 0;
- }
+ ret = qib_enable_wc(dd);
+ if (ret) {
+ qib_dev_err(dd,
+ "Write combining not enabled (err %d): performance may be poor\n",
+ -ret);
+ ret = 0;
}
qib_verify_pioperf(dd);
}
if (!ret) {
- int cookie;
-
- cookie = mtrr_add(pioaddr, piolen, MTRR_TYPE_WRCOMB, 0);
- if (cookie < 0) {
- {
- qib_devinfo(dd->pcidev,
- "mtrr_add() WC for PIO bufs failed (%d)\n",
- cookie);
- ret = -EINVAL;
- }
- } else {
- dd->wc_cookie = cookie;
- dd->wc_base = (unsigned long) pioaddr;
- dd->wc_len = (unsigned long) piolen;
- }
+ dd->wc_cookie = arch_phys_wc_add(pioaddr, piolen);
+ if (dd->wc_cookie < 0)
+ /* use error from routine */
+ ret = dd->wc_cookie;
}
return ret;
*/
void qib_disable_wc(struct qib_devdata *dd)
{
- if (dd->wc_cookie) {
- int r;
-
- r = mtrr_del(dd->wc_cookie, dd->wc_base,
- dd->wc_len);
- if (r < 0)
- qib_devinfo(dd->pcidev,
- "mtrr_del(%lx, %lx, %lx) failed: %d\n",
- dd->wc_cookie, dd->wc_base,
- dd->wc_len, r);
- dd->wc_cookie = 0; /* even on failure */
- }
+ arch_phys_wc_del(dd->wc_cookie);
}
/**
rx->rx_ring[i].mapping,
GFP_KERNEL)) {
ipoib_warn(priv, "failed to allocate receive buffer %d\n", i);
- ret = -ENOMEM;
- goto err_count;
+ ret = -ENOMEM;
+ goto err_count;
}
ret = ipoib_cm_post_receive_nonsrq(dev, rx, &t->wr, t->sge, i);
if (ret) {
static void put_pasid_state_wait(struct pasid_state *pasid_state)
{
+ atomic_dec(&pasid_state->count);
wait_event(pasid_state->wq, !atomic_read(&pasid_state->count));
free_pasid_state(pasid_state);
}
#define RESUME_TERMINATE (1 << 0)
#define TTBCR2_SEP_SHIFT 15
-#define TTBCR2_SEP_MASK 0x7
-
-#define TTBCR2_ADDR_32 0
-#define TTBCR2_ADDR_36 1
-#define TTBCR2_ADDR_40 2
-#define TTBCR2_ADDR_42 3
-#define TTBCR2_ADDR_44 4
-#define TTBCR2_ADDR_48 5
+#define TTBCR2_SEP_UPSTREAM (0x7 << TTBCR2_SEP_SHIFT)
#define TTBRn_HI_ASID_SHIFT 16
writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
if (smmu->version > ARM_SMMU_V1) {
reg = pgtbl_cfg->arm_lpae_s1_cfg.tcr >> 32;
- switch (smmu->va_size) {
- case 32:
- reg |= (TTBCR2_ADDR_32 << TTBCR2_SEP_SHIFT);
- break;
- case 36:
- reg |= (TTBCR2_ADDR_36 << TTBCR2_SEP_SHIFT);
- break;
- case 40:
- reg |= (TTBCR2_ADDR_40 << TTBCR2_SEP_SHIFT);
- break;
- case 42:
- reg |= (TTBCR2_ADDR_42 << TTBCR2_SEP_SHIFT);
- break;
- case 44:
- reg |= (TTBCR2_ADDR_44 << TTBCR2_SEP_SHIFT);
- break;
- case 48:
- reg |= (TTBCR2_ADDR_48 << TTBCR2_SEP_SHIFT);
- break;
- }
+ reg |= TTBCR2_SEP_UPSTREAM;
writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR2);
}
} else {
return 0;
}
-#ifdef CONFIG_OF
static const struct of_device_id rk_iommu_dt_ids[] = {
{ .compatible = "rockchip,iommu" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, rk_iommu_dt_ids);
-#endif
static struct platform_driver rk_iommu_driver = {
.probe = rk_iommu_probe,
.remove = rk_iommu_remove,
.driver = {
.name = "rk_iommu",
- .of_match_table = of_match_ptr(rk_iommu_dt_ids),
+ .of_match_table = rk_iommu_dt_ids,
},
};
#define NR_GIC_CPU_IF 8
static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
-/*
- * Supported arch specific GIC irq extension.
- * Default make them NULL.
- */
-struct irq_chip gic_arch_extn = {
- .irq_eoi = NULL,
- .irq_mask = NULL,
- .irq_unmask = NULL,
- .irq_retrigger = NULL,
- .irq_set_type = NULL,
- .irq_set_wake = NULL,
-};
-
#ifndef MAX_GIC_NR
#define MAX_GIC_NR 1
#endif
static void gic_mask_irq(struct irq_data *d)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&irq_controller_lock, flags);
gic_poke_irq(d, GIC_DIST_ENABLE_CLEAR);
- if (gic_arch_extn.irq_mask)
- gic_arch_extn.irq_mask(d);
- raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
}
static void gic_unmask_irq(struct irq_data *d)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&irq_controller_lock, flags);
- if (gic_arch_extn.irq_unmask)
- gic_arch_extn.irq_unmask(d);
gic_poke_irq(d, GIC_DIST_ENABLE_SET);
- raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
}
static void gic_eoi_irq(struct irq_data *d)
{
- if (gic_arch_extn.irq_eoi) {
- raw_spin_lock(&irq_controller_lock);
- gic_arch_extn.irq_eoi(d);
- raw_spin_unlock(&irq_controller_lock);
- }
-
writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
}
{
void __iomem *base = gic_dist_base(d);
unsigned int gicirq = gic_irq(d);
- unsigned long flags;
- int ret;
/* Interrupt configuration for SGIs can't be changed */
if (gicirq < 16)
type != IRQ_TYPE_EDGE_RISING)
return -EINVAL;
- raw_spin_lock_irqsave(&irq_controller_lock, flags);
-
- if (gic_arch_extn.irq_set_type)
- gic_arch_extn.irq_set_type(d, type);
-
- ret = gic_configure_irq(gicirq, type, base, NULL);
-
- raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
-
- return ret;
-}
-
-static int gic_retrigger(struct irq_data *d)
-{
- if (gic_arch_extn.irq_retrigger)
- return gic_arch_extn.irq_retrigger(d);
-
- /* the genirq layer expects 0 if we can't retrigger in hardware */
- return 0;
+ return gic_configure_irq(gicirq, type, base, NULL);
}
#ifdef CONFIG_SMP
}
#endif
-#ifdef CONFIG_PM
-static int gic_set_wake(struct irq_data *d, unsigned int on)
-{
- int ret = -ENXIO;
-
- if (gic_arch_extn.irq_set_wake)
- ret = gic_arch_extn.irq_set_wake(d, on);
-
- return ret;
-}
-
-#else
-#define gic_set_wake NULL
-#endif
-
static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
{
u32 irqstat, irqnr;
.irq_unmask = gic_unmask_irq,
.irq_eoi = gic_eoi_irq,
.irq_set_type = gic_set_type,
- .irq_retrigger = gic_retrigger,
#ifdef CONFIG_SMP
.irq_set_affinity = gic_set_affinity,
#endif
- .irq_set_wake = gic_set_wake,
.irq_get_irqchip_state = gic_irq_get_irqchip_state,
.irq_set_irqchip_state = gic_irq_set_irqchip_state,
};
set_handle_irq(gic_handle_irq);
}
- gic_chip.flags |= gic_arch_extn.flags;
gic_dist_init(gic);
gic_cpu_init(gic);
gic_pm_init(gic);
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
&tegra_ictlr_chip,
- &info->base[ictlr]);
+ info->base[ictlr]);
}
parent_args = *args;
switch (r) {
/* async */
- case -EINPROGRESS:
case -EBUSY:
wait_for_completion(&ctx->restart);
reinit_completion(&ctx->restart);
+ /* fall through*/
+ case -EINPROGRESS:
ctx->req = NULL;
ctx->cc_sector++;
continue;
struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx);
struct crypt_config *cc = io->cc;
- if (error == -EINPROGRESS)
+ if (error == -EINPROGRESS) {
+ complete(&ctx->restart);
return;
+ }
if (!error && cc->iv_gen_ops && cc->iv_gen_ops->post)
error = cc->iv_gen_ops->post(cc, iv_of_dmreq(cc, dmreq), dmreq);
crypt_free_req(cc, req_of_dmreq(cc, dmreq), io->base_bio);
if (!atomic_dec_and_test(&ctx->cc_pending))
- goto done;
+ return;
if (bio_data_dir(io->base_bio) == READ)
kcryptd_crypt_read_done(io);
else
kcryptd_crypt_write_io_submit(io, 1);
-done:
- if (!completion_done(&ctx->restart))
- complete(&ctx->restart);
}
static void kcryptd_crypt(struct work_struct *work)
if (mddev->sysfs_state)
sysfs_put(mddev->sysfs_state);
+ if (mddev->queue)
+ blk_cleanup_queue(mddev->queue);
if (mddev->gendisk) {
del_gendisk(mddev->gendisk);
put_disk(mddev->gendisk);
}
- if (mddev->queue)
- blk_cleanup_queue(mddev->queue);
kfree(mddev);
}
}
dev[j] = rdev1;
- disk_stack_limits(mddev->gendisk, rdev1->bdev,
- rdev1->data_offset << 9);
+ if (mddev->queue)
+ disk_stack_limits(mddev->gendisk, rdev1->bdev,
+ rdev1->data_offset << 9);
if (rdev1->bdev->bd_disk->queue->merge_bvec_fn)
conf->has_merge_bvec = 1;
pr_debug("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
- if (sh->batch_head)
- set_bit(STRIPE_BATCH_ERR,
- &sh->batch_head->state);
set_bit(STRIPE_HANDLE, &sh->state);
}
put_cpu();
}
+static struct stripe_head *alloc_stripe(struct kmem_cache *sc, gfp_t gfp)
+{
+ struct stripe_head *sh;
+
+ sh = kmem_cache_zalloc(sc, gfp);
+ if (sh) {
+ spin_lock_init(&sh->stripe_lock);
+ spin_lock_init(&sh->batch_lock);
+ INIT_LIST_HEAD(&sh->batch_list);
+ INIT_LIST_HEAD(&sh->lru);
+ atomic_set(&sh->count, 1);
+ }
+ return sh;
+}
static int grow_one_stripe(struct r5conf *conf, gfp_t gfp)
{
struct stripe_head *sh;
- sh = kmem_cache_zalloc(conf->slab_cache, gfp);
+
+ sh = alloc_stripe(conf->slab_cache, gfp);
if (!sh)
return 0;
sh->raid_conf = conf;
- spin_lock_init(&sh->stripe_lock);
-
if (grow_buffers(sh, gfp)) {
shrink_buffers(sh);
kmem_cache_free(conf->slab_cache, sh);
sh->hash_lock_index =
conf->max_nr_stripes % NR_STRIPE_HASH_LOCKS;
/* we just created an active stripe so... */
- atomic_set(&sh->count, 1);
atomic_inc(&conf->active_stripes);
- INIT_LIST_HEAD(&sh->lru);
- spin_lock_init(&sh->batch_lock);
- INIT_LIST_HEAD(&sh->batch_list);
- sh->batch_head = NULL;
release_stripe(sh);
conf->max_nr_stripes++;
return 1;
return ret;
}
+static int resize_chunks(struct r5conf *conf, int new_disks, int new_sectors)
+{
+ unsigned long cpu;
+ int err = 0;
+
+ mddev_suspend(conf->mddev);
+ get_online_cpus();
+ for_each_present_cpu(cpu) {
+ struct raid5_percpu *percpu;
+ struct flex_array *scribble;
+
+ percpu = per_cpu_ptr(conf->percpu, cpu);
+ scribble = scribble_alloc(new_disks,
+ new_sectors / STRIPE_SECTORS,
+ GFP_NOIO);
+
+ if (scribble) {
+ flex_array_free(percpu->scribble);
+ percpu->scribble = scribble;
+ } else {
+ err = -ENOMEM;
+ break;
+ }
+ }
+ put_online_cpus();
+ mddev_resume(conf->mddev);
+ return err;
+}
+
static int resize_stripes(struct r5conf *conf, int newsize)
{
/* Make all the stripes able to hold 'newsize' devices.
struct stripe_head *osh, *nsh;
LIST_HEAD(newstripes);
struct disk_info *ndisks;
- unsigned long cpu;
int err;
struct kmem_cache *sc;
int i;
return -ENOMEM;
for (i = conf->max_nr_stripes; i; i--) {
- nsh = kmem_cache_zalloc(sc, GFP_KERNEL);
+ nsh = alloc_stripe(sc, GFP_KERNEL);
if (!nsh)
break;
nsh->raid_conf = conf;
- spin_lock_init(&nsh->stripe_lock);
-
list_add(&nsh->lru, &newstripes);
}
if (i) {
lock_device_hash_lock(conf, hash));
osh = get_free_stripe(conf, hash);
unlock_device_hash_lock(conf, hash);
- atomic_set(&nsh->count, 1);
+
for(i=0; i<conf->pool_size; i++) {
nsh->dev[i].page = osh->dev[i].page;
nsh->dev[i].orig_page = osh->dev[i].page;
}
- for( ; i<newsize; i++)
- nsh->dev[i].page = NULL;
nsh->hash_lock_index = hash;
kmem_cache_free(conf->slab_cache, osh);
cnt++;
} else
err = -ENOMEM;
- get_online_cpus();
- for_each_present_cpu(cpu) {
- struct raid5_percpu *percpu;
- struct flex_array *scribble;
-
- percpu = per_cpu_ptr(conf->percpu, cpu);
- scribble = scribble_alloc(newsize, conf->chunk_sectors /
- STRIPE_SECTORS, GFP_NOIO);
-
- if (scribble) {
- flex_array_free(percpu->scribble);
- percpu->scribble = scribble;
- } else {
- err = -ENOMEM;
- break;
- }
- }
- put_online_cpus();
-
/* Step 4, return new stripes to service */
while(!list_empty(&newstripes)) {
nsh = list_entry(newstripes.next, struct stripe_head, lru);
conf->slab_cache = sc;
conf->active_name = 1-conf->active_name;
- conf->pool_size = newsize;
+ if (!err)
+ conf->pool_size = newsize;
return err;
}
}
rdev_dec_pending(rdev, conf->mddev);
- if (sh->batch_head && !uptodate)
+ if (sh->batch_head && !uptodate && !replacement)
set_bit(STRIPE_BATCH_ERR, &sh->batch_head->state);
if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags))
/* reconstruct-write isn't being forced */
return 0;
for (i = 0; i < s->failed; i++) {
- if (!test_bit(R5_UPTODATE, &fdev[i]->flags) &&
+ if (s->failed_num[i] != sh->pd_idx &&
+ s->failed_num[i] != sh->qd_idx &&
+ !test_bit(R5_UPTODATE, &fdev[i]->flags) &&
!test_bit(R5_OVERWRITE, &fdev[i]->flags))
return 1;
}
*/
BUG_ON(test_bit(R5_Wantcompute, &dev->flags));
BUG_ON(test_bit(R5_Wantread, &dev->flags));
+ BUG_ON(sh->batch_head);
if ((s->uptodate == disks - 1) &&
(s->failed && (disk_idx == s->failed_num[0] ||
disk_idx == s->failed_num[1]))) {
{
int i;
- BUG_ON(sh->batch_head);
/* look for blocks to read/compute, skip this if a compute
* is already in flight, or if the stripe contents are in the
* midst of changing due to a write
return;
head_sh = sh;
- do {
- sh = list_first_entry(&sh->batch_list,
- struct stripe_head, batch_list);
- BUG_ON(sh == head_sh);
- } while (!test_bit(STRIPE_DEGRADED, &sh->state));
- while (sh != head_sh) {
- next = list_first_entry(&sh->batch_list,
- struct stripe_head, batch_list);
+ list_for_each_entry_safe(sh, next, &head_sh->batch_list, batch_list) {
+
list_del_init(&sh->batch_list);
set_mask_bits(&sh->state, ~STRIPE_EXPAND_SYNC_FLAG,
set_bit(STRIPE_HANDLE, &sh->state);
release_stripe(sh);
-
- sh = next;
}
}
percpu->spare_page = alloc_page(GFP_KERNEL);
if (!percpu->scribble)
percpu->scribble = scribble_alloc(max(conf->raid_disks,
- conf->previous_raid_disks), conf->chunk_sectors /
- STRIPE_SECTORS, GFP_KERNEL);
+ conf->previous_raid_disks),
+ max(conf->chunk_sectors,
+ conf->prev_chunk_sectors)
+ / STRIPE_SECTORS,
+ GFP_KERNEL);
if (!percpu->scribble || (conf->level == 6 && !percpu->spare_page)) {
free_scratch_buffer(conf, percpu);
if (!check_stripe_cache(mddev))
return -ENOSPC;
+ if (mddev->new_chunk_sectors > mddev->chunk_sectors ||
+ mddev->delta_disks > 0)
+ if (resize_chunks(conf,
+ conf->previous_raid_disks
+ + max(0, mddev->delta_disks),
+ max(mddev->new_chunk_sectors,
+ mddev->chunk_sectors)
+ ) < 0)
+ return -ENOMEM;
return resize_stripes(conf, (conf->previous_raid_disks
+ mddev->delta_disks));
}
.planar = false,
},
{
- .desc = "UYVY 4:2:2",
- .pixelformat = V4L2_PIX_FMT_UYVY,
+ .desc = "YVYU 4:2:2",
+ .pixelformat = V4L2_PIX_FMT_YVYU,
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
.bpp = 2,
.planar = false,
switch (fmt->pixelformat) {
case V4L2_PIX_FMT_YUYV:
- case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YVYU:
widthy = fmt->width * 2;
widthuv = 0;
break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
mcam_reg_write_mask(cam, REG_CTRL0,
- C0_DF_YUV | C0_YUV_420PL | C0_YUVE_YVYU, C0_DF_MASK);
+ C0_DF_YUV | C0_YUV_420PL | C0_YUVE_VYUY, C0_DF_MASK);
break;
case V4L2_PIX_FMT_YUYV:
mcam_reg_write_mask(cam, REG_CTRL0,
- C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_UYVY, C0_DF_MASK);
+ C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_NOSWAP, C0_DF_MASK);
break;
- case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YVYU:
mcam_reg_write_mask(cam, REG_CTRL0,
- C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_YUYV, C0_DF_MASK);
+ C0_DF_YUV | C0_YUV_PACKED | C0_YUVE_SWAP24, C0_DF_MASK);
break;
case V4L2_PIX_FMT_JPEG:
mcam_reg_write_mask(cam, REG_CTRL0,
#define C0_YUVE_YVYU 0x00010000 /* Y1CrY0Cb */
#define C0_YUVE_VYUY 0x00020000 /* CrY1CbY0 */
#define C0_YUVE_UYVY 0x00030000 /* CbY1CrY0 */
-#define C0_YUVE_XYUV 0x00000000 /* 420: .YUV */
-#define C0_YUVE_XYVU 0x00010000 /* 420: .YVU */
-#define C0_YUVE_XUVY 0x00020000 /* 420: .UVY */
-#define C0_YUVE_XVUY 0x00030000 /* 420: .VUY */
+#define C0_YUVE_NOSWAP 0x00000000 /* no bytes swapping */
+#define C0_YUVE_SWAP13 0x00010000 /* swap byte 1 and 3 */
+#define C0_YUVE_SWAP24 0x00020000 /* swap byte 2 and 4 */
+#define C0_YUVE_SWAP1324 0x00030000 /* swap bytes 1&3 and 2&4 */
/* Bayer bits 18,19 if needed */
#define C0_EOF_VSYNC 0x00400000 /* Generate EOF by VSYNC */
#define C0_VEDGE_CTRL 0x00800000 /* Detect falling edge of VSYNC */
#define VIN_MAX_WIDTH 2048
#define VIN_MAX_HEIGHT 2048
+#define TIMEOUT_MS 100
+
enum chip_id {
RCAR_GEN2,
RCAR_H1,
if (priv->state == STOPPING) {
priv->request_to_stop = true;
spin_unlock_irq(&priv->lock);
- wait_for_completion(&priv->capture_stop);
+ if (!wait_for_completion_timeout(
+ &priv->capture_stop,
+ msecs_to_jiffies(TIMEOUT_MS)))
+ priv->state = STOPPED;
spin_lock_irq(&priv->lock);
}
}
md->reset_done &= ~type;
}
+int mmc_access_rpmb(struct mmc_queue *mq)
+{
+ struct mmc_blk_data *md = mq->data;
+ /*
+ * If this is a RPMB partition access, return ture
+ */
+ if (md && md->part_type == EXT_CSD_PART_CONFIG_ACC_RPMB)
+ return true;
+
+ return false;
+}
+
static int mmc_blk_issue_discard_rq(struct mmc_queue *mq, struct request *req)
{
struct mmc_blk_data *md = mq->data;
return BLKPREP_KILL;
}
- if (mq && mmc_card_removed(mq->card))
+ if (mq && (mmc_card_removed(mq->card) || mmc_access_rpmb(mq)))
return BLKPREP_KILL;
req->cmd_flags |= REQ_DONTPREP;
extern int mmc_packed_init(struct mmc_queue *, struct mmc_card *);
extern void mmc_packed_clean(struct mmc_queue *);
+extern int mmc_access_rpmb(struct mmc_queue *);
+
#endif
switch (mode) {
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
+ case PM_RESTORE_PREPARE:
spin_lock_irqsave(&host->lock, flags);
host->rescan_disable = 1;
spin_unlock_irqrestore(&host->lock, flags);
host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
/* Forward link the descriptor list */
- for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
+ for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) {
p->des3 = cpu_to_le32(host->sg_dma +
(sizeof(struct idmac_desc) * (i + 1)));
+ p->des1 = 0;
+ }
/* Set the last descriptor as the end-of-ring descriptor */
p->des3 = cpu_to_le32(host->sg_dma);
int gpio_cd = mmc_gpio_get_cd(mmc);
/* Use platform get_cd function, else try onboard card detect */
- if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
+ if ((brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION) ||
+ (mmc->caps & MMC_CAP_NONREMOVABLE))
present = 1;
else if (!IS_ERR_VALUE(gpio_cd))
present = gpio_cd;
host = mmc_priv(mmc);
host->mmc = mmc;
host->addr = reg;
- host->timeout = msecs_to_jiffies(1000);
+ host->timeout = msecs_to_jiffies(10000);
host->ccs_enable = !pd || !pd->ccs_unsupported;
host->clk_ctrl2_enable = pd && pd->clk_ctrl2_present;
*/
if (data && data->type)
flash_name = data->type;
- else if (!strcmp(spi->modalias, "nor-jedec"))
+ else if (!strcmp(spi->modalias, "spi-nor"))
flash_name = NULL; /* auto-detect */
else
flash_name = spi->modalias;
* since most of these flash are compatible to some extent, and their
* differences can often be differentiated by the JEDEC read-ID command, we
* encourage new users to add support to the spi-nor library, and simply bind
- * against a generic string here (e.g., "nor-jedec").
+ * against a generic string here (e.g., "jedec,spi-nor").
*
* Many flash names are kept here in this list (as well as in spi-nor.c) to
* keep them available as module aliases for existing platforms.
* Generic support for SPI NOR that can be identified by the JEDEC READ
* ID opcode (0x9F). Use this, if possible.
*/
- {"nor-jedec"},
+ {"spi-nor"},
{ },
};
MODULE_DEVICE_TABLE(spi, m25p_ids);
err = ret;
}
- err = mtdtest_relax();
- if (err)
+ ret = mtdtest_relax();
+ if (ret) {
+ err = ret;
goto out;
+ }
}
if (err)
blk_rq_map_sg(req->q, req, pdu->usgl.sg);
ret = ubiblock_read(pdu);
+ rq_flush_dcache_pages(req);
+
blk_mq_end_request(req, ret);
}
cf->can_id |= CAN_RTR_FLAG;
}
- if (!(id_xcan & XCAN_IDR_SRR_MASK)) {
- data[0] = priv->read_reg(priv, XCAN_RXFIFO_DW1_OFFSET);
- data[1] = priv->read_reg(priv, XCAN_RXFIFO_DW2_OFFSET);
+ /* DW1/DW2 must always be read to remove message from RXFIFO */
+ data[0] = priv->read_reg(priv, XCAN_RXFIFO_DW1_OFFSET);
+ data[1] = priv->read_reg(priv, XCAN_RXFIFO_DW2_OFFSET);
+ if (!(cf->can_id & CAN_RTR_FLAG)) {
/* Change Xilinx CAN data format to socketCAN data format */
if (cf->can_dlc > 0)
*(__be32 *)(cf->data) = cpu_to_be32(data[0]);
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
unregister_switch_driver(&mv88e6171_switch_driver);
#endif
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
+ unregister_switch_driver(&mv88e6352_switch_driver);
+#endif
#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
unregister_switch_driver(&mv88e6123_61_65_switch_driver);
#endif
config AMD_XGBE
tristate "AMD 10GbE Ethernet driver"
depends on (OF_NET || ACPI) && HAS_IOMEM && HAS_DMA
+ depends on ARM64 || COMPILE_TEST
select PHYLIB
select AMD_XGBE_PHY
select BITREVERSE
config NET_XGENE
tristate "APM X-Gene SoC Ethernet Driver"
depends on HAS_DMA
+ depends on ARCH_XGENE || COMPILE_TEST
select PHYLIB
help
This is the Ethernet driver for the on-chip ethernet interface on the
{
struct bnx2x *bp = netdev_priv(dev);
+ if (pci_num_vf(bp->pdev)) {
+ DP(BNX2X_MSG_IOV, "VFs are enabled, can not change MTU\n");
+ return -EPERM;
+ }
+
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
BNX2X_ERR("Can't perform change MTU during parity recovery\n");
return -EAGAIN;
}
bp = netdev_priv(dev);
- if (pci_num_vf(bp->pdev)) {
- DP(BNX2X_MSG_IOV, "VFs are enabled, can not change MTU\n");
- return -EPERM;
- }
-
if (bp->recovery_state != BNX2X_RECOVERY_DONE) {
BNX2X_ERR("Handling parity error recovery. Try again later\n");
return -EAGAIN;
/* Management FW 'remembers' living interfaces. Allow it some time
* to forget previously living interfaces, allowing a proper re-load.
*/
- if (is_kdump_kernel())
- msleep(5000);
+ if (is_kdump_kernel()) {
+ ktime_t now = ktime_get_boottime();
+ ktime_t fw_ready_time = ktime_set(5, 0);
+
+ if (ktime_before(now, fw_ready_time))
+ msleep(ktime_ms_delta(fw_ready_time, now));
+ }
/* An estimated maximum supported CoS number according to the chip
* version.
struct macb_queue *queue = dev_id;
struct macb *bp = queue->bp;
struct net_device *dev = bp->dev;
- u32 status;
+ u32 status, ctrl;
status = queue_readl(queue, ISR);
* add that if/when we get our hands on a full-blown MII PHY.
*/
+ if (status & MACB_BIT(RXUBR)) {
+ ctrl = macb_readl(bp, NCR);
+ macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE));
+ macb_writel(bp, NCR, ctrl | MACB_BIT(RE));
+
+ if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
+ macb_writel(bp, ISR, MACB_BIT(RXUBR));
+ }
+
if (status & MACB_BIT(ISR_ROVR)) {
/* We missed at least one packet */
if (macb_is_gem(bp))
#include <linux/ptp_classify.h>
#include <linux/mii.h>
#include <linux/mdio.h>
+#include <linux/pm_qos.h>
#include "hw.h"
struct e1000_info;
unsigned int total_bytes = 0, total_packets = 0;
u16 cleaned_count = fm10k_desc_unused(rx_ring);
- do {
+ while (likely(total_packets < budget)) {
union fm10k_rx_desc *rx_desc;
/* return some buffers to hardware, one at a time is too slow */
/* update budget accounting */
total_packets++;
- } while (likely(total_packets < budget));
+ }
/* place incomplete frames back on ring for completion */
rx_ring->skb = skb;
adapter->tx_ring[q_vector->tx.ring->queue_index] = NULL;
if (q_vector->rx.ring)
- adapter->tx_ring[q_vector->rx.ring->queue_index] = NULL;
+ adapter->rx_ring[q_vector->rx.ring->queue_index] = NULL;
netif_napi_del(&q_vector->napi);
q_vector = adapter->q_vector[v_idx];
if (!q_vector)
q_vector = kzalloc(size, GFP_KERNEL);
+ else
+ memset(q_vector, 0, size);
if (!q_vector)
return -ENOMEM;
u8 *dst_mac = skb_header_pointer(skb, 0, 0, NULL);
if (!dst_mac || is_link_local_ether_addr(dst_mac)) {
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
return NETDEV_TX_OK;
}
int i;
int offset = next - start;
- for (i = 0; i <= num; i++) {
+ for (i = 0; i < num; i++) {
ret += be64_to_cpu(*curr);
curr += offset;
}
{
int err;
int eqn = vhcr->in_modifier;
- int res_id = (slave << 8) | eqn;
+ int res_id = (slave << 10) | eqn;
struct mlx4_eq_context *eqc = inbox->buf;
int mtt_base = eq_get_mtt_addr(eqc) / dev->caps.mtt_entry_sz;
int mtt_size = eq_get_mtt_size(eqc);
struct mlx4_cmd_info *cmd)
{
int eqn = vhcr->in_modifier;
- int res_id = eqn | (slave << 8);
+ int res_id = eqn | (slave << 10);
struct res_eq *eq;
int err;
return 0;
mutex_lock(&priv->mfunc.master.gen_eqe_mutex[slave]);
- res_id = (slave << 8) | event_eq->eqn;
+ res_id = (slave << 10) | event_eq->eqn;
err = get_res(dev, slave, res_id, RES_EQ, &req);
if (err)
goto unlock;
memcpy(mailbox->buf, (u8 *) eqe, 28);
- in_modifier = (slave & 0xff) | ((event_eq->eqn & 0xff) << 16);
+ in_modifier = (slave & 0xff) | ((event_eq->eqn & 0x3ff) << 16);
err = mlx4_cmd(dev, mailbox->dma, in_modifier, 0,
MLX4_CMD_GEN_EQE, MLX4_CMD_TIME_CLASS_B,
struct mlx4_cmd_info *cmd)
{
int eqn = vhcr->in_modifier;
- int res_id = eqn | (slave << 8);
+ int res_id = eqn | (slave << 10);
struct res_eq *eq;
int err;
break;
case RES_EQ_HW:
- err = mlx4_cmd(dev, slave, eqn & 0xff,
+ err = mlx4_cmd(dev, slave, eqn & 0x3ff,
1, MLX4_CMD_HW2SW_EQ,
MLX4_CMD_TIME_CLASS_A,
MLX4_CMD_NATIVE);
if (err)
mlx4_dbg(dev, "rem_slave_eqs: failed to move slave %d eqs %d to SW ownership\n",
- slave, eqn);
+ slave, eqn & 0x3ff);
atomic_dec(&eq->mtt->ref_count);
state = RES_EQ_RESERVED;
break;
int done = 0;
struct nx_host_tx_ring *tx_ring = adapter->tx_ring;
- if (!spin_trylock(&adapter->tx_clean_lock))
+ if (!spin_trylock_bh(&adapter->tx_clean_lock))
return 1;
sw_consumer = tx_ring->sw_consumer;
*/
hw_consumer = le32_to_cpu(*(tx_ring->hw_consumer));
done = (sw_consumer == hw_consumer);
- spin_unlock(&adapter->tx_clean_lock);
+ spin_unlock_bh(&adapter->tx_clean_lock);
return done;
}
qca->spi_dev = spi_device;
qca->legacy_mode = legacy_mode;
+ spi_set_drvdata(spi_device, qcaspi_devs);
+
mac = of_get_mac_address(spi_device->dev.of_node);
if (mac)
return -EFAULT;
}
- spi_set_drvdata(spi_device, qcaspi_devs);
-
qcaspi_init_device_debugfs(qca);
return 0;
rtl8169_start_xmit(nskb, tp->dev);
} while (segs);
- dev_kfree_skb(skb);
+ dev_consume_skb_any(skb);
} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
if (skb_checksum_help(skb) < 0)
goto drop;
drop:
stats = &tp->dev->stats;
stats->tx_dropped++;
- dev_kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
}
const struct of_device_id *match = NULL;
struct smc_local *lp;
struct net_device *ndev;
- struct resource *res, *ires;
+ struct resource *res;
unsigned int __iomem *addr;
unsigned long irq_flags = SMC_IRQ_FLAGS;
+ unsigned long irq_resflags;
int ret;
ndev = alloc_etherdev(sizeof(struct smc_local));
goto out_free_netdev;
}
- ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!ires) {
+ ndev->irq = platform_get_irq(pdev, 0);
+ if (ndev->irq <= 0) {
ret = -ENODEV;
goto out_release_io;
}
-
- ndev->irq = ires->start;
-
- if (irq_flags == -1 || ires->flags & IRQF_TRIGGER_MASK)
- irq_flags = ires->flags & IRQF_TRIGGER_MASK;
+ /*
+ * If this platform does not specify any special irqflags, or if
+ * the resource supplies a trigger, override the irqflags with
+ * the trigger flags from the resource.
+ */
+ irq_resflags = irqd_get_trigger_type(irq_get_irq_data(ndev->irq));
+ if (irq_flags == -1 || irq_resflags & IRQF_TRIGGER_MASK)
+ irq_flags = irq_resflags & IRQF_TRIGGER_MASK;
ret = smc_request_attrib(pdev, ndev);
if (ret)
struct net_device *dev;
struct smsc911x_data *pdata;
struct smsc911x_platform_config *config = dev_get_platdata(&pdev->dev);
- struct resource *res, *irq_res;
+ struct resource *res;
unsigned int intcfg = 0;
- int res_size, irq_flags;
+ int res_size, irq, irq_flags;
int retval;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
}
res_size = resource_size(res);
- irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!irq_res) {
+ irq = platform_get_irq(pdev, 0);
+ if (irq <= 0) {
pr_warn("Could not allocate irq resource\n");
retval = -ENODEV;
goto out_0;
SET_NETDEV_DEV(dev, &pdev->dev);
pdata = netdev_priv(dev);
- dev->irq = irq_res->start;
- irq_flags = irq_res->flags & IRQF_TRIGGER_MASK;
+ dev->irq = irq;
+ irq_flags = irq_get_trigger_type(irq);
pdata->ioaddr = ioremap_nocache(res->start, res_size);
pdata->dev = dev;
*******************************************************************************/
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_net.h>
cur_p->app0 |= STS_CTRL_APP0_SOP;
cur_p->len = skb_headlen(skb);
- cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len,
- DMA_TO_DEVICE);
+ cur_p->phys = dma_map_single(ndev->dev.parent, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
cur_p->app4 = (unsigned long)skb;
for (ii = 0; ii < num_frag; ii++) {
u16 q_idx = packet->q_idx;
u32 pktlen = packet->total_data_buflen, msd_len = 0;
unsigned int section_index = NETVSC_INVALID_INDEX;
- struct sk_buff *skb = NULL;
unsigned long flag;
struct multi_send_data *msdp;
struct hv_netvsc_packet *msd_send = NULL, *cur_send = NULL;
if (cur_send)
ret = netvsc_send_pkt(cur_send, net_device);
- if (ret != 0) {
- if (section_index != NETVSC_INVALID_INDEX)
- netvsc_free_send_slot(net_device, section_index);
- } else if (skb) {
- dev_kfree_skb_any(skb);
- }
+ if (ret != 0 && section_index != NETVSC_INVALID_INDEX)
+ netvsc_free_send_slot(net_device, section_index);
return ret;
}
struct ieee802154_hw *hw;
struct at86rf2xx_chip_data *data;
struct regmap *regmap;
+ int slp_tr;
struct completion state_complete;
struct at86rf230_state_change state;
unsigned long cal_timeout;
s8 max_frame_retries;
bool is_tx;
+ bool is_tx_from_off;
u8 tx_retry;
struct sk_buff *tx_skb;
struct at86rf230_state_change tx;
};
-#define RG_TRX_STATUS (0x01)
-#define SR_TRX_STATUS 0x01, 0x1f, 0
-#define SR_RESERVED_01_3 0x01, 0x20, 5
-#define SR_CCA_STATUS 0x01, 0x40, 6
-#define SR_CCA_DONE 0x01, 0x80, 7
-#define RG_TRX_STATE (0x02)
-#define SR_TRX_CMD 0x02, 0x1f, 0
-#define SR_TRAC_STATUS 0x02, 0xe0, 5
-#define RG_TRX_CTRL_0 (0x03)
-#define SR_CLKM_CTRL 0x03, 0x07, 0
-#define SR_CLKM_SHA_SEL 0x03, 0x08, 3
-#define SR_PAD_IO_CLKM 0x03, 0x30, 4
-#define SR_PAD_IO 0x03, 0xc0, 6
-#define RG_TRX_CTRL_1 (0x04)
-#define SR_IRQ_POLARITY 0x04, 0x01, 0
-#define SR_IRQ_MASK_MODE 0x04, 0x02, 1
-#define SR_SPI_CMD_MODE 0x04, 0x0c, 2
-#define SR_RX_BL_CTRL 0x04, 0x10, 4
-#define SR_TX_AUTO_CRC_ON 0x04, 0x20, 5
-#define SR_IRQ_2_EXT_EN 0x04, 0x40, 6
-#define SR_PA_EXT_EN 0x04, 0x80, 7
-#define RG_PHY_TX_PWR (0x05)
-#define SR_TX_PWR 0x05, 0x0f, 0
-#define SR_PA_LT 0x05, 0x30, 4
-#define SR_PA_BUF_LT 0x05, 0xc0, 6
-#define RG_PHY_RSSI (0x06)
-#define SR_RSSI 0x06, 0x1f, 0
-#define SR_RND_VALUE 0x06, 0x60, 5
-#define SR_RX_CRC_VALID 0x06, 0x80, 7
-#define RG_PHY_ED_LEVEL (0x07)
-#define SR_ED_LEVEL 0x07, 0xff, 0
-#define RG_PHY_CC_CCA (0x08)
-#define SR_CHANNEL 0x08, 0x1f, 0
-#define SR_CCA_MODE 0x08, 0x60, 5
-#define SR_CCA_REQUEST 0x08, 0x80, 7
-#define RG_CCA_THRES (0x09)
-#define SR_CCA_ED_THRES 0x09, 0x0f, 0
-#define SR_RESERVED_09_1 0x09, 0xf0, 4
-#define RG_RX_CTRL (0x0a)
-#define SR_PDT_THRES 0x0a, 0x0f, 0
-#define SR_RESERVED_0a_1 0x0a, 0xf0, 4
-#define RG_SFD_VALUE (0x0b)
-#define SR_SFD_VALUE 0x0b, 0xff, 0
-#define RG_TRX_CTRL_2 (0x0c)
-#define SR_OQPSK_DATA_RATE 0x0c, 0x03, 0
-#define SR_SUB_MODE 0x0c, 0x04, 2
-#define SR_BPSK_QPSK 0x0c, 0x08, 3
-#define SR_OQPSK_SUB1_RC_EN 0x0c, 0x10, 4
-#define SR_RESERVED_0c_5 0x0c, 0x60, 5
-#define SR_RX_SAFE_MODE 0x0c, 0x80, 7
-#define RG_ANT_DIV (0x0d)
-#define SR_ANT_CTRL 0x0d, 0x03, 0
-#define SR_ANT_EXT_SW_EN 0x0d, 0x04, 2
-#define SR_ANT_DIV_EN 0x0d, 0x08, 3
-#define SR_RESERVED_0d_2 0x0d, 0x70, 4
-#define SR_ANT_SEL 0x0d, 0x80, 7
-#define RG_IRQ_MASK (0x0e)
-#define SR_IRQ_MASK 0x0e, 0xff, 0
-#define RG_IRQ_STATUS (0x0f)
-#define SR_IRQ_0_PLL_LOCK 0x0f, 0x01, 0
-#define SR_IRQ_1_PLL_UNLOCK 0x0f, 0x02, 1
-#define SR_IRQ_2_RX_START 0x0f, 0x04, 2
-#define SR_IRQ_3_TRX_END 0x0f, 0x08, 3
-#define SR_IRQ_4_CCA_ED_DONE 0x0f, 0x10, 4
-#define SR_IRQ_5_AMI 0x0f, 0x20, 5
-#define SR_IRQ_6_TRX_UR 0x0f, 0x40, 6
-#define SR_IRQ_7_BAT_LOW 0x0f, 0x80, 7
-#define RG_VREG_CTRL (0x10)
-#define SR_RESERVED_10_6 0x10, 0x03, 0
-#define SR_DVDD_OK 0x10, 0x04, 2
-#define SR_DVREG_EXT 0x10, 0x08, 3
-#define SR_RESERVED_10_3 0x10, 0x30, 4
-#define SR_AVDD_OK 0x10, 0x40, 6
-#define SR_AVREG_EXT 0x10, 0x80, 7
-#define RG_BATMON (0x11)
-#define SR_BATMON_VTH 0x11, 0x0f, 0
-#define SR_BATMON_HR 0x11, 0x10, 4
-#define SR_BATMON_OK 0x11, 0x20, 5
-#define SR_RESERVED_11_1 0x11, 0xc0, 6
-#define RG_XOSC_CTRL (0x12)
-#define SR_XTAL_TRIM 0x12, 0x0f, 0
-#define SR_XTAL_MODE 0x12, 0xf0, 4
-#define RG_RX_SYN (0x15)
-#define SR_RX_PDT_LEVEL 0x15, 0x0f, 0
-#define SR_RESERVED_15_2 0x15, 0x70, 4
-#define SR_RX_PDT_DIS 0x15, 0x80, 7
-#define RG_XAH_CTRL_1 (0x17)
-#define SR_RESERVED_17_8 0x17, 0x01, 0
-#define SR_AACK_PROM_MODE 0x17, 0x02, 1
-#define SR_AACK_ACK_TIME 0x17, 0x04, 2
-#define SR_RESERVED_17_5 0x17, 0x08, 3
-#define SR_AACK_UPLD_RES_FT 0x17, 0x10, 4
-#define SR_AACK_FLTR_RES_FT 0x17, 0x20, 5
-#define SR_CSMA_LBT_MODE 0x17, 0x40, 6
-#define SR_RESERVED_17_1 0x17, 0x80, 7
-#define RG_FTN_CTRL (0x18)
-#define SR_RESERVED_18_2 0x18, 0x7f, 0
-#define SR_FTN_START 0x18, 0x80, 7
-#define RG_PLL_CF (0x1a)
-#define SR_RESERVED_1a_2 0x1a, 0x7f, 0
-#define SR_PLL_CF_START 0x1a, 0x80, 7
-#define RG_PLL_DCU (0x1b)
-#define SR_RESERVED_1b_3 0x1b, 0x3f, 0
-#define SR_RESERVED_1b_2 0x1b, 0x40, 6
-#define SR_PLL_DCU_START 0x1b, 0x80, 7
-#define RG_PART_NUM (0x1c)
-#define SR_PART_NUM 0x1c, 0xff, 0
-#define RG_VERSION_NUM (0x1d)
-#define SR_VERSION_NUM 0x1d, 0xff, 0
-#define RG_MAN_ID_0 (0x1e)
-#define SR_MAN_ID_0 0x1e, 0xff, 0
-#define RG_MAN_ID_1 (0x1f)
-#define SR_MAN_ID_1 0x1f, 0xff, 0
-#define RG_SHORT_ADDR_0 (0x20)
-#define SR_SHORT_ADDR_0 0x20, 0xff, 0
-#define RG_SHORT_ADDR_1 (0x21)
-#define SR_SHORT_ADDR_1 0x21, 0xff, 0
-#define RG_PAN_ID_0 (0x22)
-#define SR_PAN_ID_0 0x22, 0xff, 0
-#define RG_PAN_ID_1 (0x23)
-#define SR_PAN_ID_1 0x23, 0xff, 0
-#define RG_IEEE_ADDR_0 (0x24)
-#define SR_IEEE_ADDR_0 0x24, 0xff, 0
-#define RG_IEEE_ADDR_1 (0x25)
-#define SR_IEEE_ADDR_1 0x25, 0xff, 0
-#define RG_IEEE_ADDR_2 (0x26)
-#define SR_IEEE_ADDR_2 0x26, 0xff, 0
-#define RG_IEEE_ADDR_3 (0x27)
-#define SR_IEEE_ADDR_3 0x27, 0xff, 0
-#define RG_IEEE_ADDR_4 (0x28)
-#define SR_IEEE_ADDR_4 0x28, 0xff, 0
-#define RG_IEEE_ADDR_5 (0x29)
-#define SR_IEEE_ADDR_5 0x29, 0xff, 0
-#define RG_IEEE_ADDR_6 (0x2a)
-#define SR_IEEE_ADDR_6 0x2a, 0xff, 0
-#define RG_IEEE_ADDR_7 (0x2b)
-#define SR_IEEE_ADDR_7 0x2b, 0xff, 0
-#define RG_XAH_CTRL_0 (0x2c)
-#define SR_SLOTTED_OPERATION 0x2c, 0x01, 0
-#define SR_MAX_CSMA_RETRIES 0x2c, 0x0e, 1
-#define SR_MAX_FRAME_RETRIES 0x2c, 0xf0, 4
-#define RG_CSMA_SEED_0 (0x2d)
-#define SR_CSMA_SEED_0 0x2d, 0xff, 0
-#define RG_CSMA_SEED_1 (0x2e)
-#define SR_CSMA_SEED_1 0x2e, 0x07, 0
-#define SR_AACK_I_AM_COORD 0x2e, 0x08, 3
-#define SR_AACK_DIS_ACK 0x2e, 0x10, 4
-#define SR_AACK_SET_PD 0x2e, 0x20, 5
-#define SR_AACK_FVN_MODE 0x2e, 0xc0, 6
-#define RG_CSMA_BE (0x2f)
-#define SR_MIN_BE 0x2f, 0x0f, 0
-#define SR_MAX_BE 0x2f, 0xf0, 4
+#define RG_TRX_STATUS (0x01)
+#define SR_TRX_STATUS 0x01, 0x1f, 0
+#define SR_RESERVED_01_3 0x01, 0x20, 5
+#define SR_CCA_STATUS 0x01, 0x40, 6
+#define SR_CCA_DONE 0x01, 0x80, 7
+#define RG_TRX_STATE (0x02)
+#define SR_TRX_CMD 0x02, 0x1f, 0
+#define SR_TRAC_STATUS 0x02, 0xe0, 5
+#define RG_TRX_CTRL_0 (0x03)
+#define SR_CLKM_CTRL 0x03, 0x07, 0
+#define SR_CLKM_SHA_SEL 0x03, 0x08, 3
+#define SR_PAD_IO_CLKM 0x03, 0x30, 4
+#define SR_PAD_IO 0x03, 0xc0, 6
+#define RG_TRX_CTRL_1 (0x04)
+#define SR_IRQ_POLARITY 0x04, 0x01, 0
+#define SR_IRQ_MASK_MODE 0x04, 0x02, 1
+#define SR_SPI_CMD_MODE 0x04, 0x0c, 2
+#define SR_RX_BL_CTRL 0x04, 0x10, 4
+#define SR_TX_AUTO_CRC_ON 0x04, 0x20, 5
+#define SR_IRQ_2_EXT_EN 0x04, 0x40, 6
+#define SR_PA_EXT_EN 0x04, 0x80, 7
+#define RG_PHY_TX_PWR (0x05)
+#define SR_TX_PWR 0x05, 0x0f, 0
+#define SR_PA_LT 0x05, 0x30, 4
+#define SR_PA_BUF_LT 0x05, 0xc0, 6
+#define RG_PHY_RSSI (0x06)
+#define SR_RSSI 0x06, 0x1f, 0
+#define SR_RND_VALUE 0x06, 0x60, 5
+#define SR_RX_CRC_VALID 0x06, 0x80, 7
+#define RG_PHY_ED_LEVEL (0x07)
+#define SR_ED_LEVEL 0x07, 0xff, 0
+#define RG_PHY_CC_CCA (0x08)
+#define SR_CHANNEL 0x08, 0x1f, 0
+#define SR_CCA_MODE 0x08, 0x60, 5
+#define SR_CCA_REQUEST 0x08, 0x80, 7
+#define RG_CCA_THRES (0x09)
+#define SR_CCA_ED_THRES 0x09, 0x0f, 0
+#define SR_RESERVED_09_1 0x09, 0xf0, 4
+#define RG_RX_CTRL (0x0a)
+#define SR_PDT_THRES 0x0a, 0x0f, 0
+#define SR_RESERVED_0a_1 0x0a, 0xf0, 4
+#define RG_SFD_VALUE (0x0b)
+#define SR_SFD_VALUE 0x0b, 0xff, 0
+#define RG_TRX_CTRL_2 (0x0c)
+#define SR_OQPSK_DATA_RATE 0x0c, 0x03, 0
+#define SR_SUB_MODE 0x0c, 0x04, 2
+#define SR_BPSK_QPSK 0x0c, 0x08, 3
+#define SR_OQPSK_SUB1_RC_EN 0x0c, 0x10, 4
+#define SR_RESERVED_0c_5 0x0c, 0x60, 5
+#define SR_RX_SAFE_MODE 0x0c, 0x80, 7
+#define RG_ANT_DIV (0x0d)
+#define SR_ANT_CTRL 0x0d, 0x03, 0
+#define SR_ANT_EXT_SW_EN 0x0d, 0x04, 2
+#define SR_ANT_DIV_EN 0x0d, 0x08, 3
+#define SR_RESERVED_0d_2 0x0d, 0x70, 4
+#define SR_ANT_SEL 0x0d, 0x80, 7
+#define RG_IRQ_MASK (0x0e)
+#define SR_IRQ_MASK 0x0e, 0xff, 0
+#define RG_IRQ_STATUS (0x0f)
+#define SR_IRQ_0_PLL_LOCK 0x0f, 0x01, 0
+#define SR_IRQ_1_PLL_UNLOCK 0x0f, 0x02, 1
+#define SR_IRQ_2_RX_START 0x0f, 0x04, 2
+#define SR_IRQ_3_TRX_END 0x0f, 0x08, 3
+#define SR_IRQ_4_CCA_ED_DONE 0x0f, 0x10, 4
+#define SR_IRQ_5_AMI 0x0f, 0x20, 5
+#define SR_IRQ_6_TRX_UR 0x0f, 0x40, 6
+#define SR_IRQ_7_BAT_LOW 0x0f, 0x80, 7
+#define RG_VREG_CTRL (0x10)
+#define SR_RESERVED_10_6 0x10, 0x03, 0
+#define SR_DVDD_OK 0x10, 0x04, 2
+#define SR_DVREG_EXT 0x10, 0x08, 3
+#define SR_RESERVED_10_3 0x10, 0x30, 4
+#define SR_AVDD_OK 0x10, 0x40, 6
+#define SR_AVREG_EXT 0x10, 0x80, 7
+#define RG_BATMON (0x11)
+#define SR_BATMON_VTH 0x11, 0x0f, 0
+#define SR_BATMON_HR 0x11, 0x10, 4
+#define SR_BATMON_OK 0x11, 0x20, 5
+#define SR_RESERVED_11_1 0x11, 0xc0, 6
+#define RG_XOSC_CTRL (0x12)
+#define SR_XTAL_TRIM 0x12, 0x0f, 0
+#define SR_XTAL_MODE 0x12, 0xf0, 4
+#define RG_RX_SYN (0x15)
+#define SR_RX_PDT_LEVEL 0x15, 0x0f, 0
+#define SR_RESERVED_15_2 0x15, 0x70, 4
+#define SR_RX_PDT_DIS 0x15, 0x80, 7
+#define RG_XAH_CTRL_1 (0x17)
+#define SR_RESERVED_17_8 0x17, 0x01, 0
+#define SR_AACK_PROM_MODE 0x17, 0x02, 1
+#define SR_AACK_ACK_TIME 0x17, 0x04, 2
+#define SR_RESERVED_17_5 0x17, 0x08, 3
+#define SR_AACK_UPLD_RES_FT 0x17, 0x10, 4
+#define SR_AACK_FLTR_RES_FT 0x17, 0x20, 5
+#define SR_CSMA_LBT_MODE 0x17, 0x40, 6
+#define SR_RESERVED_17_1 0x17, 0x80, 7
+#define RG_FTN_CTRL (0x18)
+#define SR_RESERVED_18_2 0x18, 0x7f, 0
+#define SR_FTN_START 0x18, 0x80, 7
+#define RG_PLL_CF (0x1a)
+#define SR_RESERVED_1a_2 0x1a, 0x7f, 0
+#define SR_PLL_CF_START 0x1a, 0x80, 7
+#define RG_PLL_DCU (0x1b)
+#define SR_RESERVED_1b_3 0x1b, 0x3f, 0
+#define SR_RESERVED_1b_2 0x1b, 0x40, 6
+#define SR_PLL_DCU_START 0x1b, 0x80, 7
+#define RG_PART_NUM (0x1c)
+#define SR_PART_NUM 0x1c, 0xff, 0
+#define RG_VERSION_NUM (0x1d)
+#define SR_VERSION_NUM 0x1d, 0xff, 0
+#define RG_MAN_ID_0 (0x1e)
+#define SR_MAN_ID_0 0x1e, 0xff, 0
+#define RG_MAN_ID_1 (0x1f)
+#define SR_MAN_ID_1 0x1f, 0xff, 0
+#define RG_SHORT_ADDR_0 (0x20)
+#define SR_SHORT_ADDR_0 0x20, 0xff, 0
+#define RG_SHORT_ADDR_1 (0x21)
+#define SR_SHORT_ADDR_1 0x21, 0xff, 0
+#define RG_PAN_ID_0 (0x22)
+#define SR_PAN_ID_0 0x22, 0xff, 0
+#define RG_PAN_ID_1 (0x23)
+#define SR_PAN_ID_1 0x23, 0xff, 0
+#define RG_IEEE_ADDR_0 (0x24)
+#define SR_IEEE_ADDR_0 0x24, 0xff, 0
+#define RG_IEEE_ADDR_1 (0x25)
+#define SR_IEEE_ADDR_1 0x25, 0xff, 0
+#define RG_IEEE_ADDR_2 (0x26)
+#define SR_IEEE_ADDR_2 0x26, 0xff, 0
+#define RG_IEEE_ADDR_3 (0x27)
+#define SR_IEEE_ADDR_3 0x27, 0xff, 0
+#define RG_IEEE_ADDR_4 (0x28)
+#define SR_IEEE_ADDR_4 0x28, 0xff, 0
+#define RG_IEEE_ADDR_5 (0x29)
+#define SR_IEEE_ADDR_5 0x29, 0xff, 0
+#define RG_IEEE_ADDR_6 (0x2a)
+#define SR_IEEE_ADDR_6 0x2a, 0xff, 0
+#define RG_IEEE_ADDR_7 (0x2b)
+#define SR_IEEE_ADDR_7 0x2b, 0xff, 0
+#define RG_XAH_CTRL_0 (0x2c)
+#define SR_SLOTTED_OPERATION 0x2c, 0x01, 0
+#define SR_MAX_CSMA_RETRIES 0x2c, 0x0e, 1
+#define SR_MAX_FRAME_RETRIES 0x2c, 0xf0, 4
+#define RG_CSMA_SEED_0 (0x2d)
+#define SR_CSMA_SEED_0 0x2d, 0xff, 0
+#define RG_CSMA_SEED_1 (0x2e)
+#define SR_CSMA_SEED_1 0x2e, 0x07, 0
+#define SR_AACK_I_AM_COORD 0x2e, 0x08, 3
+#define SR_AACK_DIS_ACK 0x2e, 0x10, 4
+#define SR_AACK_SET_PD 0x2e, 0x20, 5
+#define SR_AACK_FVN_MODE 0x2e, 0xc0, 6
+#define RG_CSMA_BE (0x2f)
+#define SR_MIN_BE 0x2f, 0x0f, 0
+#define SR_MAX_BE 0x2f, 0xf0, 4
#define CMD_REG 0x80
#define CMD_REG_MASK 0x3f
#define STATE_BUSY_RX_AACK_NOCLK 0x1E
#define STATE_TRANSITION_IN_PROGRESS 0x1F
+#define TRX_STATE_MASK (0x1F)
+
#define AT86RF2XX_NUMREGS 0x3F
static void
return regmap_update_bits(lp->regmap, addr, mask, data << shift);
}
+static inline void
+at86rf230_slp_tr_rising_edge(struct at86rf230_local *lp)
+{
+ gpio_set_value(lp->slp_tr, 1);
+ udelay(1);
+ gpio_set_value(lp->slp_tr, 0);
+}
+
static bool
at86rf230_reg_writeable(struct device *dev, unsigned int reg)
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
const u8 *buf = ctx->buf;
- const u8 trx_state = buf[1] & 0x1f;
+ const u8 trx_state = buf[1] & TRX_STATE_MASK;
/* Assert state change */
if (trx_state != ctx->to_state) {
switch (ctx->to_state) {
case STATE_RX_AACK_ON:
tim = ktime_set(0, c->t_off_to_aack * NSEC_PER_USEC);
+ /* state change from TRX_OFF to RX_AACK_ON to do a
+ * calibration, we need to reset the timeout for the
+ * next one.
+ */
+ lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
goto change;
+ case STATE_TX_ARET_ON:
case STATE_TX_ON:
tim = ktime_set(0, c->t_off_to_tx_on * NSEC_PER_USEC);
- /* state change from TRX_OFF to TX_ON to do a
- * calibration, we need to reset the timeout for the
+ /* state change from TRX_OFF to TX_ON or ARET_ON to do
+ * a calibration, we need to reset the timeout for the
* next one.
*/
lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
u8 *buf = ctx->buf;
- const u8 trx_state = buf[1] & 0x1f;
+ const u8 trx_state = buf[1] & TRX_STATE_MASK;
int rc;
/* Check for "possible" STATE_TRANSITION_IN_PROGRESS */
at86rf230_tx_complete, true);
}
-static void
-at86rf230_tx_trac_error(void *context)
-{
- struct at86rf230_state_change *ctx = context;
- struct at86rf230_local *lp = ctx->lp;
-
- at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
- at86rf230_tx_on, true);
-}
-
static void
at86rf230_tx_trac_check(void *context)
{
const u8 trac = (buf[1] & 0xe0) >> 5;
/* If trac status is different than zero we need to do a state change
- * to STATE_FORCE_TRX_OFF then STATE_TX_ON to recover the transceiver
- * state to TX_ON.
+ * to STATE_FORCE_TRX_OFF then STATE_RX_AACK_ON to recover the
+ * transceiver.
*/
if (trac)
at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
- at86rf230_tx_trac_error, true);
+ at86rf230_tx_on, true);
else
at86rf230_tx_on(context);
}
u8 *buf = ctx->buf;
int rc;
- buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
- buf[1] = STATE_BUSY_TX;
ctx->trx.len = 2;
- ctx->msg.complete = NULL;
- rc = spi_async(lp->spi, &ctx->msg);
- if (rc)
- at86rf230_async_error(lp, ctx, rc);
+
+ if (gpio_is_valid(lp->slp_tr)) {
+ at86rf230_slp_tr_rising_edge(lp);
+ } else {
+ buf[0] = (RG_TRX_STATE & CMD_REG_MASK) | CMD_REG | CMD_WRITE;
+ buf[1] = STATE_BUSY_TX;
+ ctx->msg.complete = NULL;
+ rc = spi_async(lp->spi, &ctx->msg);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
+ }
}
static void
* are in STATE_TX_ON. The pfad differs here, so we change
* the complete handler.
*/
- if (lp->tx_aret)
- at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
- at86rf230_xmit_tx_on, false);
- else
+ if (lp->tx_aret) {
+ if (lp->is_tx_from_off) {
+ lp->is_tx_from_off = false;
+ at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
+ at86rf230_xmit_tx_on,
+ false);
+ } else {
+ at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+ at86rf230_xmit_tx_on,
+ false);
+ }
+ } else {
at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
at86rf230_write_frame, false);
+ }
}
static int
* to TX_ON, the lp->cal_timeout should be reinit by state_delay
* function then to start in the next 5 minutes.
*/
- if (time_is_before_jiffies(lp->cal_timeout))
+ if (time_is_before_jiffies(lp->cal_timeout)) {
+ lp->is_tx_from_off = true;
at86rf230_async_state_change(lp, ctx, STATE_TRX_OFF,
at86rf230_xmit_start, false);
- else
+ } else {
at86rf230_xmit_start(ctx);
+ }
return 0;
}
static int
at86rf230_start(struct ieee802154_hw *hw)
{
- struct at86rf230_local *lp = hw->priv;
-
- lp->cal_timeout = jiffies + AT86RF2XX_CAL_LOOP_TIMEOUT;
return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON);
}
lp = hw->priv;
lp->hw = hw;
lp->spi = spi;
+ lp->slp_tr = slp_tr;
hw->parent = &spi->dev;
hw->vif_data_size = sizeof(*lp);
ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
goto del_unicast;
}
+ if (dev->flags & IFF_PROMISC) {
+ err = dev_set_promiscuity(lowerdev, 1);
+ if (err < 0)
+ goto clear_multi;
+ }
+
hash_add:
macvlan_hash_add(vlan);
return 0;
+clear_multi:
+ dev_set_allmulti(lowerdev, -1);
del_unicast:
dev_uc_del(lowerdev, dev->dev_addr);
out:
if (dev->flags & IFF_ALLMULTI)
dev_set_allmulti(lowerdev, -1);
+ if (dev->flags & IFF_PROMISC)
+ dev_set_promiscuity(lowerdev, -1);
+
dev_uc_del(lowerdev, dev->dev_addr);
hash_del:
if (dev->flags & IFF_UP) {
if (change & IFF_ALLMULTI)
dev_set_allmulti(lowerdev, dev->flags & IFF_ALLMULTI ? 1 : -1);
+ if (change & IFF_PROMISC)
+ dev_set_promiscuity(lowerdev,
+ dev->flags & IFF_PROMISC ? 1 : -1);
+
}
}
config AMD_XGBE_PHY
tristate "Driver for the AMD 10GbE (amd-xgbe) PHYs"
depends on (OF || ACPI) && HAS_IOMEM
+ depends on ARM64 || COMPILE_TEST
---help---
Currently supports the AMD 10GbE PHY
if (!new_bus->irq[i])
new_bus->irq[i] = PHY_POLL;
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id);
+ if (bus_id != -1)
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id);
+ else
+ strncpy(new_bus->id, "gpio", MII_BUS_ID_SIZE);
if (devm_gpio_request(dev, bitbang->mdc, "mdc"))
goto out_free_bus;
}
clk = devm_clk_get(&phydev->dev, "rmii-ref");
- if (!IS_ERR(clk)) {
+ /* NOTE: clk may be NULL if building without CONFIG_HAVE_CLK */
+ if (!IS_ERR_OR_NULL(clk)) {
unsigned long rate = clk_get_rate(clk);
bool rmii_ref_clk_sel_25_mhz;
struct sock *sk = sk_pppox(po);
lock_sock(sk);
+ if (po->pppoe_dev) {
+ dev_put(po->pppoe_dev);
+ po->pppoe_dev = NULL;
+ }
pppox_unbind_sock(sk);
release_sock(sk);
sock_put(sk);
{REALTEK_USB_DEVICE(VENDOR_ID_REALTEK, 0x8153)},
{REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101)},
{REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)},
+ {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x304f)},
{}
};
struct net_device *net)
{
struct usbnet *dev = netdev_priv(net);
- int length;
+ unsigned int length;
struct urb *urb = NULL;
struct skb_data *entry;
struct driver_info *info = dev->driver_info;
}
} else
netif_dbg(dev, tx_queued, dev->net,
- "> tx, len %d, type 0x%x\n", length, skb->protocol);
+ "> tx, len %u, type 0x%x\n", length, skb->protocol);
#ifdef CONFIG_PM
deferred:
#endif
struct sk_buff *skb;
struct ath_frame_info *fi;
struct ieee80211_tx_info *info;
- struct ieee80211_vif *vif;
struct ath_hw *ah = sc->sc_ah;
if (sc->tx99_state || !ah->tpc_enabled)
return MAX_RATE_POWER;
skb = bf->bf_mpdu;
- info = IEEE80211_SKB_CB(skb);
- vif = info->control.vif;
-
- if (!vif) {
- max_power = sc->cur_chan->cur_txpower;
- goto out;
- }
-
- if (vif->bss_conf.txpower_type != NL80211_TX_POWER_LIMITED) {
- max_power = min_t(u8, sc->cur_chan->cur_txpower,
- 2 * vif->bss_conf.txpower);
- goto out;
- }
-
fi = get_frame_info(skb);
+ info = IEEE80211_SKB_CB(skb);
if (!AR_SREV_9300_20_OR_LATER(ah)) {
int txpower = fi->tx_power;
txpower -= 2;
txpower = max(txpower, 0);
- max_power = min_t(u8, ah->tx_power[rateidx],
- 2 * vif->bss_conf.txpower);
- max_power = min_t(u8, max_power, txpower);
+ max_power = min_t(u8, ah->tx_power[rateidx], txpower);
+
+ /* XXX: clamp minimum TX power at 1 for AR9160 since if
+ * max_power is set to 0, frames are transmitted at max
+ * TX power
+ */
+ if (!max_power && !AR_SREV_9280_20_OR_LATER(ah))
+ max_power = 1;
} else if (!bf->bf_state.bfs_paprd) {
if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC))
max_power = min_t(u8, ah->tx_power_stbc[rateidx],
- 2 * vif->bss_conf.txpower);
+ fi->tx_power);
else
max_power = min_t(u8, ah->tx_power[rateidx],
- 2 * vif->bss_conf.txpower);
- max_power = min(max_power, fi->tx_power);
+ fi->tx_power);
} else {
max_power = ah->paprd_training_power;
}
-out:
- /* XXX: clamp minimum TX power at 1 for AR9160 since if max_power
- * is set to 0, frames are transmitted at max TX power
- */
- return (!max_power && !AR_SREV_9280_20_OR_LATER(ah)) ? 1 : max_power;
+
+ return max_power;
}
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ath_node *an = NULL;
enum ath9k_key_type keytype;
bool short_preamble = false;
+ u8 txpower;
/*
* We check if Short Preamble is needed for the CTS rate by
if (sta)
an = (struct ath_node *) sta->drv_priv;
+ if (tx_info->control.vif) {
+ struct ieee80211_vif *vif = tx_info->control.vif;
+
+ txpower = 2 * vif->bss_conf.txpower;
+ } else {
+ struct ath_softc *sc = hw->priv;
+
+ txpower = sc->cur_chan->cur_txpower;
+ }
+
memset(fi, 0, sizeof(*fi));
fi->txq = -1;
if (hw_key)
fi->keyix = ATH9K_TXKEYIX_INVALID;
fi->keytype = keytype;
fi->framelen = framelen;
- fi->tx_power = MAX_RATE_POWER;
+ fi->tx_power = txpower;
if (!rate)
return;
* longer than the passive one, which is essential for fragmented scan.
* @IWL_UCODE_TLV_API_WIFI_MCC_UPDATE: ucode supports MCC updates with source.
* IWL_UCODE_TLV_API_HDC_PHASE_0: ucode supports finer configuration of LTR
+ * @IWL_UCODE_TLV_API_TX_POWER_DEV: new API for tx power.
* @IWL_UCODE_TLV_API_BASIC_DWELL: use only basic dwell time in scan command,
* regardless of the band or the number of the probes. FW will calculate
* the actual dwell time.
IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8),
IWL_UCODE_TLV_API_WIFI_MCC_UPDATE = BIT(9),
IWL_UCODE_TLV_API_HDC_PHASE_0 = BIT(10),
+ IWL_UCODE_TLV_API_TX_POWER_DEV = BIT(11),
IWL_UCODE_TLV_API_BASIC_DWELL = BIT(13),
IWL_UCODE_TLV_API_SCD_CFG = BIT(15),
IWL_UCODE_TLV_API_SINGLE_SCAN_EBS = BIT(16),
* GPL LICENSE SUMMARY
*
* Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* 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
* BSD LICENSE
*
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*
* All the handlers MUST be implemented
*
- * @start_hw: starts the HW- from that point on, the HW can send interrupts
- * May sleep
+ * @start_hw: starts the HW. If low_power is true, the NIC needs to be taken
+ * out of a low power state. From that point on, the HW can send
+ * interrupts. May sleep.
* @op_mode_leave: Turn off the HW RF kill indication if on
* May sleep
* @start_fw: allocates and inits all the resources for the transport
* the SCD base address in SRAM, then provide it here, or 0 otherwise.
* May sleep
* @stop_device: stops the whole device (embedded CPU put to reset) and stops
- * the HW. From that point on, the HW will be in low power but will still
- * issue interrupt if the HW RF kill is triggered. This callback must do
- * the right thing and not crash even if start_hw() was called but not
- * start_fw(). May sleep
+ * the HW. If low_power is true, the NIC will be put in low power state.
+ * From that point on, the HW will be stopped but will still issue an
+ * interrupt if the HW RF kill switch is triggered.
+ * This callback must do the right thing and not crash even if %start_hw()
+ * was called but not &start_fw(). May sleep.
* @d3_suspend: put the device into the correct mode for WoWLAN during
* suspend. This is optional, if not implemented WoWLAN will not be
* supported. This callback may sleep.
*/
struct iwl_trans_ops {
- int (*start_hw)(struct iwl_trans *iwl_trans);
+ int (*start_hw)(struct iwl_trans *iwl_trans, bool low_power);
void (*op_mode_leave)(struct iwl_trans *iwl_trans);
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw,
bool run_in_rfkill);
int (*update_sf)(struct iwl_trans *trans,
struct iwl_sf_region *st_fwrd_space);
void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
- void (*stop_device)(struct iwl_trans *trans);
+ void (*stop_device)(struct iwl_trans *trans, bool low_power);
void (*d3_suspend)(struct iwl_trans *trans, bool test);
int (*d3_resume)(struct iwl_trans *trans, enum iwl_d3_status *status,
trans->ops->configure(trans, trans_cfg);
}
-static inline int iwl_trans_start_hw(struct iwl_trans *trans)
+static inline int _iwl_trans_start_hw(struct iwl_trans *trans, bool low_power)
{
might_sleep();
- return trans->ops->start_hw(trans);
+ return trans->ops->start_hw(trans, low_power);
+}
+
+static inline int iwl_trans_start_hw(struct iwl_trans *trans)
+{
+ return trans->ops->start_hw(trans, true);
}
static inline void iwl_trans_op_mode_leave(struct iwl_trans *trans)
return 0;
}
-static inline void iwl_trans_stop_device(struct iwl_trans *trans)
+static inline void _iwl_trans_stop_device(struct iwl_trans *trans,
+ bool low_power)
{
might_sleep();
- trans->ops->stop_device(trans);
+ trans->ops->stop_device(trans, low_power);
trans->state = IWL_TRANS_NO_FW;
}
+static inline void iwl_trans_stop_device(struct iwl_trans *trans)
+{
+ _iwl_trans_stop_device(trans, true);
+}
+
static inline void iwl_trans_d3_suspend(struct iwl_trans *trans, bool test)
{
might_sleep();
results->matched_profiles = le32_to_cpu(query->matched_profiles);
memcpy(results->matches, query->matches, sizeof(results->matches));
-#ifdef CPTCFG_IWLWIFI_DEBUGFS
+#ifdef CONFIG_IWLWIFI_DEBUGFS
mvm->last_netdetect_scans = le32_to_cpu(query->n_scans_done);
#endif
u8 reserved[3];
} __packed;
+/**
+ * struct iwl_reduce_tx_power_cmd - TX power reduction command
+ * REDUCE_TX_POWER_CMD = 0x9f
+ * @flags: (reserved for future implementation)
+ * @mac_context_id: id of the mac ctx for which we are reducing TX power.
+ * @pwr_restriction: TX power restriction in dBms.
+ */
+struct iwl_reduce_tx_power_cmd {
+ u8 flags;
+ u8 mac_context_id;
+ __le16 pwr_restriction;
+} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
+
+/**
+ * struct iwl_dev_tx_power_cmd - TX power reduction command
+ * REDUCE_TX_POWER_CMD = 0x9f
+ * @set_mode: 0 - MAC tx power, 1 - device tx power
+ * @mac_context_id: id of the mac ctx for which we are reducing TX power.
+ * @pwr_restriction: TX power restriction in 1/8 dBms.
+ * @dev_24: device TX power restriction in 1/8 dBms
+ * @dev_52_low: device TX power restriction upper band - low
+ * @dev_52_high: device TX power restriction upper band - high
+ */
+struct iwl_dev_tx_power_cmd {
+ __le32 set_mode;
+ __le32 mac_context_id;
+ __le16 pwr_restriction;
+ __le16 dev_24;
+ __le16 dev_52_low;
+ __le16 dev_52_high;
+} __packed; /* TX_REDUCED_POWER_API_S_VER_2 */
+
+#define IWL_DEV_MAX_TX_POWER 0x7FFF
+
/**
* struct iwl_beacon_filter_cmd
* REPLY_BEACON_FILTERING_CMD = 0xd2 (command)
SCAN_COMP_STATUS_ERR_ALLOC_TE = 0x0C,
};
-/**
- * struct iwl_scan_results_notif - scan results for one channel
- * ( SCAN_RESULTS_NOTIFICATION = 0x83 )
- * @channel: which channel the results are from
- * @band: 0 for 5.2 GHz, 1 for 2.4 GHz
- * @probe_status: SCAN_PROBE_STATUS_*, indicates success of probe request
- * @num_probe_not_sent: # of request that weren't sent due to not enough time
- * @duration: duration spent in channel, in usecs
- * @statistics: statistics gathered for this channel
- */
-struct iwl_scan_results_notif {
- u8 channel;
- u8 band;
- u8 probe_status;
- u8 num_probe_not_sent;
- __le32 duration;
- __le32 statistics[SCAN_RESULTS_STATISTICS];
-} __packed; /* SCAN_RESULT_NTF_API_S_VER_2 */
-
-/**
- * struct iwl_scan_complete_notif - notifies end of scanning (all channels)
- * ( SCAN_COMPLETE_NOTIFICATION = 0x84 )
- * @scanned_channels: number of channels scanned (and number of valid results)
- * @status: one of SCAN_COMP_STATUS_*
- * @bt_status: BT on/off status
- * @last_channel: last channel that was scanned
- * @tsf_low: TSF timer (lower half) in usecs
- * @tsf_high: TSF timer (higher half) in usecs
- * @results: array of scan results, only "scanned_channels" of them are valid
- */
-struct iwl_scan_complete_notif {
- u8 scanned_channels;
- u8 status;
- u8 bt_status;
- u8 last_channel;
- __le32 tsf_low;
- __le32 tsf_high;
- struct iwl_scan_results_notif results[];
-} __packed; /* SCAN_COMPLETE_NTF_API_S_VER_2 */
-
/* scan offload */
#define IWL_SCAN_MAX_BLACKLIST_LEN 64
#define IWL_SCAN_SHORT_BLACKLIST_LEN 16
} __packed;
/**
- * struct iwl_lmac_scan_results_notif - scan results for one channel -
+ * struct iwl_scan_results_notif - scan results for one channel -
* SCAN_RESULT_NTF_API_S_VER_3
* @channel: which channel the results are from
* @band: 0 for 5.2 GHz, 1 for 2.4 GHz
* @num_probe_not_sent: # of request that weren't sent due to not enough time
* @duration: duration spent in channel, in usecs
*/
-struct iwl_lmac_scan_results_notif {
+struct iwl_scan_results_notif {
u8 channel;
u8 band;
u8 probe_status;
__le32 valid;
} __packed;
-/**
- * struct iwl_reduce_tx_power_cmd - TX power reduction command
- * REDUCE_TX_POWER_CMD = 0x9f
- * @flags: (reserved for future implementation)
- * @mac_context_id: id of the mac ctx for which we are reducing TX power.
- * @pwr_restriction: TX power restriction in dBms.
- */
-struct iwl_reduce_tx_power_cmd {
- u8 flags;
- u8 mac_context_id;
- __le16 pwr_restriction;
-} __packed; /* TX_REDUCED_POWER_API_S_VER_1 */
-
/*
* Calibration control struct.
* Sent as part of the phy configuration command.
* GPL LICENSE SUMMARY
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* 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
* BSD LICENSE
*
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating))
+ if (WARN_ON_ONCE(mvm->calibrating))
return 0;
iwl_init_notification_wait(&mvm->notif_wait,
*/
ret = iwl_wait_notification(&mvm->notif_wait, &calib_wait,
MVM_UCODE_CALIB_TIMEOUT);
- if (!ret)
- mvm->init_ucode_complete = true;
if (ret && iwl_mvm_is_radio_killed(mvm)) {
IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
mvm->fw_dump_desc = desc;
- /* stop recording */
- if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
- iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
- } else {
- iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
- /* wait before we collect the data till the DBGC stop */
- udelay(100);
- }
-
queue_delayed_work(system_wq, &mvm->fw_dump_wk, delay);
return 0;
* module loading, load init ucode now
* (for example, if we were in RFKILL)
*/
- if (!mvm->init_ucode_complete) {
- ret = iwl_run_init_mvm_ucode(mvm, false);
- if (ret && !iwlmvm_mod_params.init_dbg) {
- IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
- /* this can't happen */
- if (WARN_ON(ret > 0))
- ret = -ERFKILL;
- goto error;
- }
- if (!iwlmvm_mod_params.init_dbg) {
- /*
- * should stop and start HW since that INIT
- * image just loaded
- */
- iwl_trans_stop_device(mvm->trans);
- ret = iwl_trans_start_hw(mvm->trans);
- if (ret)
- return ret;
- }
+ ret = iwl_run_init_mvm_ucode(mvm, false);
+ if (ret && !iwlmvm_mod_params.init_dbg) {
+ IWL_ERR(mvm, "Failed to run INIT ucode: %d\n", ret);
+ /* this can't happen */
+ if (WARN_ON(ret > 0))
+ ret = -ERFKILL;
+ goto error;
+ }
+ if (!iwlmvm_mod_params.init_dbg) {
+ /*
+ * Stop and start the transport without entering low power
+ * mode. This will save the state of other components on the
+ * device that are triggered by the INIT firwmare (MFUART).
+ */
+ _iwl_trans_stop_device(mvm->trans, false);
+ _iwl_trans_start_hw(mvm->trans, false);
+ if (ret)
+ return ret;
}
if (iwlmvm_mod_params.init_dbg)
clear_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
iwl_mvm_d0i3_enable_tx(mvm, NULL);
- ret = iwl_mvm_update_quotas(mvm, false, NULL);
+ ret = iwl_mvm_update_quotas(mvm, true, NULL);
if (ret)
IWL_ERR(mvm, "Failed to update quotas after restart (%d)\n",
ret);
return NULL;
}
-static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- s8 tx_power)
+static int iwl_mvm_set_tx_power_old(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif, s8 tx_power)
{
/* FW is in charge of regulatory enforcement */
struct iwl_reduce_tx_power_cmd reduce_txpwr_cmd = {
&reduce_txpwr_cmd);
}
+static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ s16 tx_power)
+{
+ struct iwl_dev_tx_power_cmd cmd = {
+ .set_mode = 0,
+ .mac_context_id =
+ cpu_to_le32(iwl_mvm_vif_from_mac80211(vif)->id),
+ .pwr_restriction = cpu_to_le16(8 * tx_power),
+ };
+
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_TX_POWER_DEV))
+ return iwl_mvm_set_tx_power_old(mvm, vif, tx_power);
+
+ if (tx_power == IWL_DEFAULT_MAX_TX_POWER)
+ cmd.pwr_restriction = cpu_to_le16(IWL_DEV_MAX_TX_POWER);
+
+ return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0,
+ sizeof(cmd), &cmd);
+}
+
static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
enum iwl_ucode_type cur_ucode;
bool ucode_loaded;
- bool init_ucode_complete;
bool calibrating;
u32 error_event_table;
u32 log_event_table;
return;
mutex_lock(&mvm->mutex);
+
+ /* stop recording */
+ if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
+ iwl_set_bits_prph(mvm->trans, MON_BUFF_SAMPLE_CTL, 0x100);
+ } else {
+ iwl_write_prph(mvm->trans, DBGC_IN_SAMPLE, 0);
+ /* wait before we collect the data till the DBGC stop */
+ udelay(100);
+ }
+
iwl_mvm_fw_error_dump(mvm);
/* start recording again if the firmware is not crashed */
if (vif->type != NL80211_IFTYPE_STATION)
return;
+ if (sig == 0) {
+ IWL_DEBUG_RX(mvm, "RSSI is 0 - skip signal based decision\n");
+ return;
+ }
+
mvmvif->bf_data.ave_beacon_signal = sig;
/* BT Coex */
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_scan_complete_notif *notif = (void *)pkt->data;
+ struct iwl_lmac_scan_complete_notif *notif = (void *)pkt->data;
IWL_DEBUG_SCAN(mvm,
"Scan offload iteration complete: status=0x%x scanned channels=%d\n",
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* 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
*
* BSD LICENSE
*
- * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved.
- * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved.
+ * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- struct page *page;
+ struct page *page = NULL;
dma_addr_t phys;
u32 size;
u8 power;
DMA_FROM_DEVICE);
if (dma_mapping_error(trans->dev, phys)) {
__free_pages(page, order);
+ page = NULL;
continue;
}
IWL_INFO(trans,
iwl_pcie_tx_start(trans, scd_addr);
}
-static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
+static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool hw_rfkill, was_hw_rfkill;
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state)
{
if (iwl_op_mode_hw_rf_kill(trans->op_mode, state))
- iwl_trans_pcie_stop_device(trans);
+ iwl_trans_pcie_stop_device(trans, true);
}
static void iwl_trans_pcie_d3_suspend(struct iwl_trans *trans, bool test)
return 0;
}
-static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
+static int iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
{
bool hw_rfkill;
int err;
do {
status = usb_control_msg(udev, pipe, request, reqtype, value,
- index, pdata, len, 0); /*max. timeout*/
+ index, pdata, len, 1000);
if (status < 0) {
/* firmware download is checksumed, don't retry */
if ((value >= FW_8192C_START_ADDRESS &&
BUG();
return -1;
}
- printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %pf\n",
+ printk(KERN_DEBUG "superio_fixup_irq(%s) ven 0x%x dev 0x%x from %ps\n",
pci_name(pcidev),
pcidev->vendor, pcidev->device,
__builtin_return_address(0));
EXPORT_SYMBOL_GPL(devm_pinctrl_put);
int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
- bool dup, bool locked)
+ bool dup)
{
int i, ret;
struct pinctrl_maps *maps_node;
maps_node->maps = maps;
}
- if (!locked)
- mutex_lock(&pinctrl_maps_mutex);
+ mutex_lock(&pinctrl_maps_mutex);
list_add_tail(&maps_node->node, &pinctrl_maps);
- if (!locked)
- mutex_unlock(&pinctrl_maps_mutex);
+ mutex_unlock(&pinctrl_maps_mutex);
return 0;
}
int pinctrl_register_mappings(struct pinctrl_map const *maps,
unsigned num_maps)
{
- return pinctrl_register_map(maps, num_maps, true, false);
+ return pinctrl_register_map(maps, num_maps, true);
}
void pinctrl_unregister_map(struct pinctrl_map const *map)
}
int pinctrl_register_map(struct pinctrl_map const *maps, unsigned num_maps,
- bool dup, bool locked);
+ bool dup);
void pinctrl_unregister_map(struct pinctrl_map const *map);
extern int pinctrl_force_sleep(struct pinctrl_dev *pctldev);
dt_map->num_maps = num_maps;
list_add_tail(&dt_map->node, &p->dt_maps);
- return pinctrl_register_map(map, num_maps, false, true);
+ return pinctrl_register_map(map, num_maps, false);
}
struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
if (!mtk_eint_get_mask(pctl, eint_num)) {
mtk_eint_mask(d);
unmask = 1;
+ } else {
+ unmask = 0;
}
clr_bit = 0xff << eint_offset;
MPP_FUNCTION(0x5, "audio", "mclk"),
MPP_FUNCTION(0x6, "uart0", "cts")),
MPP_MODE(63,
- MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x0, "gpio", NULL),
MPP_FUNCTION(0x1, "spi0", "sck"),
MPP_FUNCTION(0x2, "tclk", NULL)),
MPP_MODE(64,
val = 1;
}
+ val = val << PMIC_GPIO_REG_MODE_DIR_SHIFT;
val |= pad->function << PMIC_GPIO_REG_MODE_FUNCTION_SHIFT;
val |= pad->out_value & PMIC_GPIO_REG_MODE_VALUE_SHIFT;
return ret;
val = pad->buffer_type << PMIC_GPIO_REG_OUT_TYPE_SHIFT;
- val = pad->strength << PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;
+ val |= pad->strength << PMIC_GPIO_REG_OUT_STRENGTH_SHIFT;
ret = pmic_gpio_write(state, pad, PMIC_GPIO_REG_DIG_OUT_CTL, val);
if (ret < 0)
seq_puts(s, " ---");
} else {
- if (!pad->input_enabled) {
+ if (pad->input_enabled) {
ret = pmic_gpio_read(state, pad, PMIC_MPP_REG_RT_STS);
- if (!ret) {
- ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
- pad->out_value = ret;
- }
+ if (ret < 0)
+ return;
+
+ ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
+ pad->out_value = ret;
}
seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");
}
}
+ val = val << PMIC_MPP_REG_MODE_DIR_SHIFT;
val |= pad->function << PMIC_MPP_REG_MODE_FUNCTION_SHIFT;
val |= pad->out_value & PMIC_MPP_REG_MODE_VALUE_MASK;
if (pad->input_enabled) {
ret = pmic_mpp_read(state, pad, PMIC_MPP_REG_RT_STS);
- if (!ret) {
- ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
- pad->out_value = ret;
- }
+ if (ret < 0)
+ return;
+
+ ret &= PMIC_MPP_REG_RT_STS_VAL_MASK;
+ pad->out_value = ret;
}
seq_printf(s, " %-4s", pad->output_enabled ? "out" : "in");
* report all radios as hardware-blocked.
*/
static const struct dmi_system_id no_hw_rfkill_list[] = {
+ {
+ .ident = "Lenovo G40-30",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo G40-30"),
+ },
+ },
{
.ident = "Lenovo Yoga 2 11 / 13 / Pro",
.matches = {
return 0;
}
-void static hotkey_mask_warn_incomplete_mask(void)
+static void hotkey_mask_warn_incomplete_mask(void)
{
/* log only what the user can fix... */
const u32 wantedmask = hotkey_driver_mask &
module_platform_driver(axp288_fuel_gauge_driver);
+MODULE_AUTHOR("Ramakrishna Pallala <ramakrishna.pallala@intel.com>");
MODULE_AUTHOR("Todd Brandt <todd.e.brandt@linux.intel.com>");
MODULE_DESCRIPTION("Xpower AXP288 Fuel Gauge Driver");
MODULE_LICENSE("GPL");
}
module_exit(bq27x00_battery_exit);
+#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
+MODULE_ALIAS("platform:bq27000-battery");
+#endif
+
+#ifdef CONFIG_BATTERY_BQ27X00_I2C
+MODULE_ALIAS("i2c:bq27000-battery");
+#endif
+
MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>");
MODULE_DESCRIPTION("BQ27x00 battery monitor driver");
MODULE_LICENSE("GPL");
goto err_psy_reg_main;
}
- psy_main_cfg.drv_data = &collie_bat_bu;
+ psy_bu_cfg.drv_data = &collie_bat_bu;
collie_bat_bu.psy = power_supply_register(&dev->ucb->dev,
&collie_bat_bu_desc,
&psy_bu_cfg);
config POWER_RESET_BRCMSTB
bool "Broadcom STB reset driver"
depends on ARM || MIPS || COMPILE_TEST
+ depends on MFD_SYSCON
default ARCH_BRCMSTB
help
This driver provides restart support for Broadcom STB boards.
res = platform_get_resource(pdev, IORESOURCE_MEM, idx + 1 );
at91_ramc_base[idx] = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
- if (IS_ERR(at91_ramc_base[idx])) {
+ if (!at91_ramc_base[idx]) {
dev_err(&pdev->dev, "Could not map ram controller address\n");
- return PTR_ERR(at91_ramc_base[idx]);
+ return -ENOMEM;
}
}
static void ltc2952_poweroff_start_wde(struct ltc2952_poweroff *data)
{
- if (hrtimer_start(&data->timer_wde, data->wde_interval,
- HRTIMER_MODE_REL)) {
- /*
- * The device will not toggle the watchdog reset,
- * thus shut down is only safe if the PowerPath controller
- * has a long enough time-off before triggering a hardware
- * power-off.
- *
- * Only sending a warning as the system will power-off anyway
- */
- dev_err(data->dev, "unable to start the timer\n");
- }
+ hrtimer_start(&data->timer_wde, data->wde_interval, HRTIMER_MODE_REL);
}
static enum hrtimer_restart
}
if (gpiod_get_value(data->gpio_trigger)) {
- if (hrtimer_start(&data->timer_trigger, data->trigger_delay,
- HRTIMER_MODE_REL))
- dev_err(data->dev, "unable to start the wait timer\n");
+ hrtimer_start(&data->timer_trigger, data->trigger_delay,
+ HRTIMER_MODE_REL);
} else {
hrtimer_cancel(&data->timer_trigger);
/* omitting return value check, timer should have been valid */
This driver can also be built as a module. If so, the module
will be called rtc-ab-b5ze-s3.
+config RTC_DRV_ABX80X
+ tristate "Abracon ABx80x"
+ help
+ If you say yes here you get support for Abracon AB080X and AB180X
+ families of ultra-low-power battery- and capacitor-backed real-time
+ clock chips.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-abx80x.
+
config RTC_DRV_AS3722
tristate "ams AS3722 RTC driver"
depends on MFD_AS3722
obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o
obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o
obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
+obj-$(CONFIG_RTC_DRV_ABX80X) += rtc-abx80x.o
obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o
obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o
obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o
--- /dev/null
+/*
+ * A driver for the I2C members of the Abracon AB x8xx RTC family,
+ * and compatible: AB 1805 and AB 0805
+ *
+ * Copyright 2014-2015 Macq S.A.
+ *
+ * Author: Philippe De Muyter <phdm@macqel.be>
+ * Author: Alexandre Belloni <alexandre.belloni@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/bcd.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/rtc.h>
+
+#define ABX8XX_REG_HTH 0x00
+#define ABX8XX_REG_SC 0x01
+#define ABX8XX_REG_MN 0x02
+#define ABX8XX_REG_HR 0x03
+#define ABX8XX_REG_DA 0x04
+#define ABX8XX_REG_MO 0x05
+#define ABX8XX_REG_YR 0x06
+#define ABX8XX_REG_WD 0x07
+
+#define ABX8XX_REG_CTRL1 0x10
+#define ABX8XX_CTRL_WRITE BIT(1)
+#define ABX8XX_CTRL_12_24 BIT(6)
+
+#define ABX8XX_REG_CFG_KEY 0x1f
+#define ABX8XX_CFG_KEY_MISC 0x9d
+
+#define ABX8XX_REG_ID0 0x28
+
+#define ABX8XX_REG_TRICKLE 0x20
+#define ABX8XX_TRICKLE_CHARGE_ENABLE 0xa0
+#define ABX8XX_TRICKLE_STANDARD_DIODE 0x8
+#define ABX8XX_TRICKLE_SCHOTTKY_DIODE 0x4
+
+static u8 trickle_resistors[] = {0, 3, 6, 11};
+
+enum abx80x_chip {AB0801, AB0803, AB0804, AB0805,
+ AB1801, AB1803, AB1804, AB1805, ABX80X};
+
+struct abx80x_cap {
+ u16 pn;
+ bool has_tc;
+};
+
+static struct abx80x_cap abx80x_caps[] = {
+ [AB0801] = {.pn = 0x0801},
+ [AB0803] = {.pn = 0x0803},
+ [AB0804] = {.pn = 0x0804, .has_tc = true},
+ [AB0805] = {.pn = 0x0805, .has_tc = true},
+ [AB1801] = {.pn = 0x1801},
+ [AB1803] = {.pn = 0x1803},
+ [AB1804] = {.pn = 0x1804, .has_tc = true},
+ [AB1805] = {.pn = 0x1805, .has_tc = true},
+ [ABX80X] = {.pn = 0}
+};
+
+static struct i2c_driver abx80x_driver;
+
+static int abx80x_enable_trickle_charger(struct i2c_client *client,
+ u8 trickle_cfg)
+{
+ int err;
+
+ /*
+ * Write the configuration key register to enable access to the Trickle
+ * register
+ */
+ err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CFG_KEY,
+ ABX8XX_CFG_KEY_MISC);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write configuration key\n");
+ return -EIO;
+ }
+
+ err = i2c_smbus_write_byte_data(client, ABX8XX_REG_TRICKLE,
+ ABX8XX_TRICKLE_CHARGE_ENABLE |
+ trickle_cfg);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write trickle register\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int abx80x_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned char buf[8];
+ int err;
+
+ err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_HTH,
+ sizeof(buf), buf);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to read date\n");
+ return -EIO;
+ }
+
+ tm->tm_sec = bcd2bin(buf[ABX8XX_REG_SC] & 0x7F);
+ tm->tm_min = bcd2bin(buf[ABX8XX_REG_MN] & 0x7F);
+ tm->tm_hour = bcd2bin(buf[ABX8XX_REG_HR] & 0x3F);
+ tm->tm_wday = buf[ABX8XX_REG_WD] & 0x7;
+ tm->tm_mday = bcd2bin(buf[ABX8XX_REG_DA] & 0x3F);
+ tm->tm_mon = bcd2bin(buf[ABX8XX_REG_MO] & 0x1F) - 1;
+ tm->tm_year = bcd2bin(buf[ABX8XX_REG_YR]) + 100;
+
+ err = rtc_valid_tm(tm);
+ if (err < 0)
+ dev_err(&client->dev, "retrieved date/time is not valid.\n");
+
+ return err;
+}
+
+static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned char buf[8];
+ int err;
+
+ if (tm->tm_year < 100)
+ return -EINVAL;
+
+ buf[ABX8XX_REG_HTH] = 0;
+ buf[ABX8XX_REG_SC] = bin2bcd(tm->tm_sec);
+ buf[ABX8XX_REG_MN] = bin2bcd(tm->tm_min);
+ buf[ABX8XX_REG_HR] = bin2bcd(tm->tm_hour);
+ buf[ABX8XX_REG_DA] = bin2bcd(tm->tm_mday);
+ buf[ABX8XX_REG_MO] = bin2bcd(tm->tm_mon + 1);
+ buf[ABX8XX_REG_YR] = bin2bcd(tm->tm_year - 100);
+ buf[ABX8XX_REG_WD] = tm->tm_wday;
+
+ err = i2c_smbus_write_i2c_block_data(client, ABX8XX_REG_HTH,
+ sizeof(buf), buf);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write to date registers\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static const struct rtc_class_ops abx80x_rtc_ops = {
+ .read_time = abx80x_rtc_read_time,
+ .set_time = abx80x_rtc_set_time,
+};
+
+static int abx80x_dt_trickle_cfg(struct device_node *np)
+{
+ const char *diode;
+ int trickle_cfg = 0;
+ int i, ret;
+ u32 tmp;
+
+ ret = of_property_read_string(np, "abracon,tc-diode", &diode);
+ if (ret)
+ return ret;
+
+ if (!strcmp(diode, "standard"))
+ trickle_cfg |= ABX8XX_TRICKLE_STANDARD_DIODE;
+ else if (!strcmp(diode, "schottky"))
+ trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE;
+ else
+ return -EINVAL;
+
+ ret = of_property_read_u32(np, "abracon,tc-resistor", &tmp);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < sizeof(trickle_resistors); i++)
+ if (trickle_resistors[i] == tmp)
+ break;
+
+ if (i == sizeof(trickle_resistors))
+ return -EINVAL;
+
+ return (trickle_cfg | i);
+}
+
+static int abx80x_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct device_node *np = client->dev.of_node;
+ struct rtc_device *rtc;
+ int i, data, err, trickle_cfg = -EINVAL;
+ char buf[7];
+ unsigned int part = id->driver_data;
+ unsigned int partnumber;
+ unsigned int majrev, minrev;
+ unsigned int lot;
+ unsigned int wafer;
+ unsigned int uid;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return -ENODEV;
+
+ err = i2c_smbus_read_i2c_block_data(client, ABX8XX_REG_ID0,
+ sizeof(buf), buf);
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to read partnumber\n");
+ return -EIO;
+ }
+
+ partnumber = (buf[0] << 8) | buf[1];
+ majrev = buf[2] >> 3;
+ minrev = buf[2] & 0x7;
+ lot = ((buf[4] & 0x80) << 2) | ((buf[6] & 0x80) << 1) | buf[3];
+ uid = ((buf[4] & 0x7f) << 8) | buf[5];
+ wafer = (buf[6] & 0x7c) >> 2;
+ dev_info(&client->dev, "model %04x, revision %u.%u, lot %x, wafer %x, uid %x\n",
+ partnumber, majrev, minrev, lot, wafer, uid);
+
+ data = i2c_smbus_read_byte_data(client, ABX8XX_REG_CTRL1);
+ if (data < 0) {
+ dev_err(&client->dev, "Unable to read control register\n");
+ return -EIO;
+ }
+
+ err = i2c_smbus_write_byte_data(client, ABX8XX_REG_CTRL1,
+ ((data & ~ABX8XX_CTRL_12_24) |
+ ABX8XX_CTRL_WRITE));
+ if (err < 0) {
+ dev_err(&client->dev, "Unable to write control register\n");
+ return -EIO;
+ }
+
+ /* part autodetection */
+ if (part == ABX80X) {
+ for (i = 0; abx80x_caps[i].pn; i++)
+ if (partnumber == abx80x_caps[i].pn)
+ break;
+ if (abx80x_caps[i].pn == 0) {
+ dev_err(&client->dev, "Unknown part: %04x\n",
+ partnumber);
+ return -EINVAL;
+ }
+ part = i;
+ }
+
+ if (partnumber != abx80x_caps[part].pn) {
+ dev_err(&client->dev, "partnumber mismatch %04x != %04x\n",
+ partnumber, abx80x_caps[part].pn);
+ return -EINVAL;
+ }
+
+ if (np && abx80x_caps[part].has_tc)
+ trickle_cfg = abx80x_dt_trickle_cfg(np);
+
+ if (trickle_cfg > 0) {
+ dev_info(&client->dev, "Enabling trickle charger: %02x\n",
+ trickle_cfg);
+ abx80x_enable_trickle_charger(client, trickle_cfg);
+ }
+
+ rtc = devm_rtc_device_register(&client->dev, abx80x_driver.driver.name,
+ &abx80x_rtc_ops, THIS_MODULE);
+
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ i2c_set_clientdata(client, rtc);
+
+ return 0;
+}
+
+static int abx80x_remove(struct i2c_client *client)
+{
+ return 0;
+}
+
+static const struct i2c_device_id abx80x_id[] = {
+ { "abx80x", ABX80X },
+ { "ab0801", AB0801 },
+ { "ab0803", AB0803 },
+ { "ab0804", AB0804 },
+ { "ab0805", AB0805 },
+ { "ab1801", AB1801 },
+ { "ab1803", AB1803 },
+ { "ab1804", AB1804 },
+ { "ab1805", AB1805 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, abx80x_id);
+
+static struct i2c_driver abx80x_driver = {
+ .driver = {
+ .name = "rtc-abx80x",
+ },
+ .probe = abx80x_probe,
+ .remove = abx80x_remove,
+ .id_table = abx80x_id,
+};
+
+module_i2c_driver(abx80x_driver);
+
+MODULE_AUTHOR("Philippe De Muyter <phdm@macqel.be>");
+MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@free-electrons.com>");
+MODULE_DESCRIPTION("Abracon ABX80X RTC driver");
+MODULE_LICENSE("GPL v2");
void __iomem *regs;
void __iomem *regs_soc;
spinlock_t lock;
+ /*
+ * While setting the time, the RTC TIME register should not be
+ * accessed. Setting the RTC time involves sleeping during
+ * 100ms, so a mutex instead of a spinlock is used to protect
+ * it
+ */
+ struct mutex mutex_time;
int irq;
};
static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct armada38x_rtc *rtc = dev_get_drvdata(dev);
- unsigned long time, time_check, flags;
-
- spin_lock_irqsave(&rtc->lock, flags);
+ unsigned long time, time_check;
+ mutex_lock(&rtc->mutex_time);
time = readl(rtc->regs + RTC_TIME);
/*
* WA for failing time set attempts. As stated in HW ERRATA if
if ((time_check - time) > 1)
time_check = readl(rtc->regs + RTC_TIME);
- spin_unlock_irqrestore(&rtc->lock, flags);
+ mutex_unlock(&rtc->mutex_time);
rtc_time_to_tm(time_check, tm);
* then wait for 100ms before writing to the time register to be
* sure that the data will be taken into account.
*/
- spin_lock_irqsave(&rtc->lock, flags);
-
+ mutex_lock(&rtc->mutex_time);
rtc_delayed_write(0, rtc, RTC_STATUS);
-
- spin_unlock_irqrestore(&rtc->lock, flags);
-
msleep(100);
-
- spin_lock_irqsave(&rtc->lock, flags);
-
rtc_delayed_write(time, rtc, RTC_TIME);
+ mutex_unlock(&rtc->mutex_time);
- spin_unlock_irqrestore(&rtc->lock, flags);
out:
return ret;
}
return -ENOMEM;
spin_lock_init(&rtc->lock);
+ mutex_init(&rtc->mutex_time);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
rtc->regs = devm_ioremap_resource(&pdev->dev, res);
config SPI_BCM2835
tristate "BCM2835 SPI controller"
depends on ARCH_BCM2835 || COMPILE_TEST
+ depends on GPIOLIB
help
This selects a driver for the Broadcom BCM2835 SPI master.
config SPI_FSL_DSPI
tristate "Freescale DSPI controller"
select REGMAP_MMIO
- depends on SOC_VF610 || COMPILE_TEST
+ depends on SOC_VF610 || SOC_LS1021A || COMPILE_TEST
help
This enables support for the Freescale DSPI controller in master
mode. VF610 platform uses the controller.
unsigned long xfer_time_us)
{
struct bcm2835_spi *bs = spi_master_get_devdata(master);
- unsigned long timeout = jiffies +
- max(4 * xfer_time_us * HZ / 1000000, 2uL);
+ /* set timeout to 1 second of maximum polling */
+ unsigned long timeout = jiffies + HZ;
/* enable HW block without interrupts */
bcm2835_wr(bs, BCM2835_SPI_CS, cs | BCM2835_SPI_CS_TA);
- /* set timeout to 4x the expected time, or 2 jiffies */
/* loop until finished the transfer */
while (bs->rx_len) {
/* read from fifo as much as possible */
{
struct spi_bitbang_cs *cs = spi->controller_state;
struct spi_bitbang *bitbang;
- int retval;
unsigned long flags;
bitbang = spi_master_get_devdata(spi->master);
if (!cs->txrx_word)
return -EINVAL;
- retval = bitbang->setup_transfer(spi, NULL);
- if (retval < 0)
- return retval;
+ if (bitbang->setup_transfer) {
+ int retval = bitbang->setup_transfer(spi, NULL);
+ if (retval < 0)
+ return retval;
+ }
dev_dbg(&spi->dev, "%s, %u nsec/bit\n", __func__, 2 * cs->nsecs);
/* init (-1) or override (1) transfer params */
if (do_setup != 0) {
- status = bitbang->setup_transfer(spi, t);
- if (status < 0)
- break;
+ if (bitbang->setup_transfer) {
+ status = bitbang->setup_transfer(spi, t);
+ if (status < 0)
+ break;
+ }
if (do_setup == -1)
do_setup = 0;
}
#include <linux/of_address.h>
#include <linux/spi/spi.h>
#include <linux/types.h>
+#include <linux/platform_device.h>
#include "spi-fsl-cpm.h"
#include "spi-fsl-lib.h"
if (mspi->flags & SPI_CPM2) {
pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
out_be16(spi_base, pram_ofs);
- } else {
- struct spi_pram __iomem *pram = spi_base;
- u16 rpbase = in_be16(&pram->rpbase);
-
- /* Microcode relocation patch applied? */
- if (rpbase) {
- pram_ofs = rpbase;
- } else {
- pram_ofs = cpm_muram_alloc(SPI_PRAM_SIZE, 64);
- out_be16(spi_base, pram_ofs);
- }
}
iounmap(spi_base);
struct device_node *np = dev->of_node;
const u32 *iprop;
int size;
- unsigned long pram_ofs;
unsigned long bds_ofs;
if (!(mspi->flags & SPI_CPM_MODE))
}
}
- pram_ofs = fsl_spi_cpm_get_pram(mspi);
- if (IS_ERR_VALUE(pram_ofs)) {
+ if (mspi->flags & SPI_CPM1) {
+ struct resource *res;
+ void *pram;
+
+ res = platform_get_resource(to_platform_device(dev),
+ IORESOURCE_MEM, 1);
+ pram = devm_ioremap_resource(dev, res);
+ if (IS_ERR(pram))
+ mspi->pram = NULL;
+ else
+ mspi->pram = pram;
+ } else {
+ unsigned long pram_ofs = fsl_spi_cpm_get_pram(mspi);
+
+ if (IS_ERR_VALUE(pram_ofs))
+ mspi->pram = NULL;
+ else
+ mspi->pram = cpm_muram_addr(pram_ofs);
+ }
+ if (mspi->pram == NULL) {
dev_err(dev, "can't allocate spi parameter ram\n");
goto err_pram;
}
goto err_dummy_rx;
}
- mspi->pram = cpm_muram_addr(pram_ofs);
-
mspi->tx_bd = cpm_muram_addr(bds_ofs);
mspi->rx_bd = cpm_muram_addr(bds_ofs + sizeof(*mspi->tx_bd));
err_dummy_tx:
cpm_muram_free(bds_ofs);
err_bds:
- cpm_muram_free(pram_ofs);
+ if (!(mspi->flags & SPI_CPM1))
+ cpm_muram_free(cpm_muram_offset(mspi->pram));
err_pram:
fsl_spi_free_dummy_rx();
return -ENOMEM;
struct fsl_espi_transfer *trans, u8 *rx_buff)
{
struct fsl_espi_transfer *espi_trans = trans;
- unsigned int n_tx = espi_trans->n_tx;
- unsigned int n_rx = espi_trans->n_rx;
+ unsigned int total_len = espi_trans->len;
struct spi_transfer *t;
u8 *local_buf;
u8 *rx_buf = rx_buff;
unsigned int trans_len;
unsigned int addr;
- int i, pos, loop;
+ unsigned int tx_only;
+ unsigned int rx_pos = 0;
+ unsigned int pos;
+ int i, loop;
local_buf = kzalloc(SPCOM_TRANLEN_MAX, GFP_KERNEL);
if (!local_buf) {
return;
}
- for (pos = 0, loop = 0; pos < n_rx; pos += trans_len, loop++) {
- trans_len = n_rx - pos;
- if (trans_len > SPCOM_TRANLEN_MAX - n_tx)
- trans_len = SPCOM_TRANLEN_MAX - n_tx;
+ for (pos = 0, loop = 0; pos < total_len; pos += trans_len, loop++) {
+ trans_len = total_len - pos;
i = 0;
+ tx_only = 0;
list_for_each_entry(t, &m->transfers, transfer_list) {
if (t->tx_buf) {
memcpy(local_buf + i, t->tx_buf, t->len);
i += t->len;
+ if (!t->rx_buf)
+ tx_only += t->len;
}
}
+ /* Add additional TX bytes to compensate SPCOM_TRANLEN_MAX */
+ if (loop > 0)
+ trans_len += tx_only;
+
+ if (trans_len > SPCOM_TRANLEN_MAX)
+ trans_len = SPCOM_TRANLEN_MAX;
+
+ /* Update device offset */
if (pos > 0) {
addr = fsl_espi_cmd2addr(local_buf);
- addr += pos;
+ addr += rx_pos;
fsl_espi_addr2cmd(addr, local_buf);
}
- espi_trans->n_tx = n_tx;
- espi_trans->n_rx = trans_len;
- espi_trans->len = trans_len + n_tx;
+ espi_trans->len = trans_len;
espi_trans->tx_buf = local_buf;
espi_trans->rx_buf = local_buf;
fsl_espi_do_trans(m, espi_trans);
- memcpy(rx_buf + pos, espi_trans->rx_buf + n_tx, trans_len);
+ /* If there is at least one RX byte then copy it to rx_buf */
+ if (tx_only < SPCOM_TRANLEN_MAX)
+ memcpy(rx_buf + rx_pos, espi_trans->rx_buf + tx_only,
+ trans_len - tx_only);
+
+ rx_pos += trans_len - tx_only;
if (loop > 0)
- espi_trans->actual_length += espi_trans->len - n_tx;
+ espi_trans->actual_length += espi_trans->len - tx_only;
else
espi_trans->actual_length += espi_trans->len;
}
u8 *rx_buf = NULL;
unsigned int n_tx = 0;
unsigned int n_rx = 0;
+ unsigned int xfer_len = 0;
struct fsl_espi_transfer espi_trans;
list_for_each_entry(t, &m->transfers, transfer_list) {
n_rx += t->len;
rx_buf = t->rx_buf;
}
+ if ((t->tx_buf) || (t->rx_buf))
+ xfer_len += t->len;
}
espi_trans.n_tx = n_tx;
espi_trans.n_rx = n_rx;
- espi_trans.len = n_tx + n_rx;
+ espi_trans.len = xfer_len;
espi_trans.actual_length = 0;
espi_trans.status = 0;
struct omap2_mcspi *mcspi;
struct omap2_mcspi_dma *mcspi_dma;
struct spi_transfer *t;
+ int status;
spi = m->spi;
mcspi = spi_master_get_devdata(master);
tx_buf ? "tx" : "",
rx_buf ? "rx" : "",
t->bits_per_word);
- return -EINVAL;
+ status = -EINVAL;
+ goto out;
}
if (m->is_dma_mapped || len < DMA_MIN_BYTES)
if (dma_mapping_error(mcspi->dev, t->tx_dma)) {
dev_dbg(mcspi->dev, "dma %cX %d bytes error\n",
'T', len);
- return -EINVAL;
+ status = -EINVAL;
+ goto out;
}
}
if (mcspi_dma->dma_rx && rx_buf != NULL) {
if (tx_buf != NULL)
dma_unmap_single(mcspi->dev, t->tx_dma,
len, DMA_TO_DEVICE);
- return -EINVAL;
+ status = -EINVAL;
+ goto out;
}
}
}
omap2_mcspi_work(mcspi, m);
+ /* spi_finalize_current_message() changes the status inside the
+ * spi_message, save the status here. */
+ status = m->status;
+out:
spi_finalize_current_message(master);
- return 0;
+ return status;
}
static int omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
rx_dev = master->dma_rx->device->dev;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+ /*
+ * Restore the original value of tx_buf or rx_buf if they are
+ * NULL.
+ */
+ if (xfer->tx_buf == master->dummy_tx)
+ xfer->tx_buf = NULL;
+ if (xfer->rx_buf == master->dummy_rx)
+ xfer->rx_buf = NULL;
+
if (!master->can_dma(master, msg->spi, xfer))
continue;
source "drivers/staging/fbtft/Kconfig"
-source "drivers/staging/i2o/Kconfig"
-
source "drivers/staging/fsl-mc/Kconfig"
endif # STAGING
obj-$(CONFIG_UNISYSSPAR) += unisys/
obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/
obj-$(CONFIG_FB_TFT) += fbtft/
-obj-$(CONFIG_I2O) += i2o/
obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
p->pid, p->comm, oom_score_adj, tasksize);
}
if (selected) {
- lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n",
- selected->pid, selected->comm,
- selected_oom_score_adj, selected_tasksize);
- lowmem_deathpending_timeout = jiffies + HZ;
+ task_lock(selected);
+ if (!selected->mm) {
+ /* Already exited, cannot do mark_tsk_oom_victim() */
+ task_unlock(selected);
+ goto out;
+ }
/*
* FIXME: lowmemorykiller shouldn't abuse global OOM killer
* infrastructure. There is no real reason why the selected
* task should have access to the memory reserves.
*/
mark_tsk_oom_victim(selected);
+ task_unlock(selected);
+ lowmem_print(1, "send sigkill to %d (%s), adj %hd, size %d\n",
+ selected->pid, selected->comm,
+ selected_oom_score_adj, selected_tasksize);
+ lowmem_deathpending_timeout = jiffies + HZ;
send_sig(SIGKILL, selected, 0);
rem += selected_tasksize;
}
-
+out:
lowmem_print(4, "lowmem_scan %lu, %x, return %lu\n",
sc->nr_to_scan, sc->gfp_mask, rem);
rcu_read_unlock();
/*
- comedi/drivers/daqboard2000.c
- hardware driver for IOtech DAQboard/2000
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ * comedi/drivers/daqboard2000.c
+ * hardware driver for IOtech DAQboard/2000
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se>
+ *
+ * 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: daqboard2000
-Description: IOTech DAQBoard/2000
-Author: Anders Blomdell <anders.blomdell@control.lth.se>
-Status: works
-Updated: Mon, 14 Apr 2008 15:28:52 +0100
-Devices: [IOTech] DAQBoard/2000 (daqboard2000)
-
-Much of the functionality of this driver was determined from reading
-the source code for the Windows driver.
-
-The FPGA on the board requires fimware, which is available from
-http://www.comedi.org in the comedi_nonfree_firmware tarball.
-
-Configuration options: not applicable, uses PCI auto config
-*/
+ * Driver: daqboard2000
+ * Description: IOTech DAQBoard/2000
+ * Author: Anders Blomdell <anders.blomdell@control.lth.se>
+ * Status: works
+ * Updated: Mon, 14 Apr 2008 15:28:52 +0100
+ * Devices: [IOTech] DAQBoard/2000 (daqboard2000)
+ *
+ * Much of the functionality of this driver was determined from reading
+ * the source code for the Windows driver.
+ *
+ * The FPGA on the board requires fimware, which is available from
+ * http://www.comedi.org in the comedi_nonfree_firmware tarball.
+ *
+ * Configuration options: not applicable, uses PCI auto config
+ */
/*
- This card was obviously never intended to leave the Windows world,
- since it lacked all kind of hardware documentation (except for cable
- pinouts, plug and pray has something to catch up with yet).
-
- With some help from our swedish distributor, we got the Windows sourcecode
- for the card, and here are the findings so far.
-
- 1. A good document that describes the PCI interface chip is 9080db-106.pdf
- available from http://www.plxtech.com/products/io/pci9080
-
- 2. The initialization done so far is:
- a. program the FPGA (windows code sans a lot of error messages)
- b.
-
- 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled,
- you have to output values to all enabled DAC's until result appears, I
- guess that it has something to do with pacer clocks, but the source
- gives me no clues. I'll keep it simple so far.
-
- 4. Analog in.
- Each channel in the scanlist seems to be controlled by four
- control words:
-
- Word0:
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! | | | ! | | | ! | | | ! | | | !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- Word1:
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! | | | ! | | | ! | | | ! | | | !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | | | | | | |
- +------+------+ | | | | +-- Digital input (??)
- | | | | +---- 10 us settling time
- | | | +------ Suspend acquisition (last to scan)
- | | +-------- Simultaneous sample and hold
- | +---------- Signed data format
- +------------------------- Correction offset low
-
- Word2:
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! | | | ! | | | ! | | | ! | | | !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | | | | | | | | | |
- +-----+ +--+--+ +++ +++ +--+--+
- | | | | +----- Expansion channel
- | | | +----------- Expansion gain
- | | +--------------- Channel (low)
- | +--------------------- Correction offset high
- +----------------------------- Correction gain low
- Word3:
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- ! | | | ! | | | ! | | | ! | | | !
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | | | | | | | | |
- +------+------+ | | +-+-+ | | +-- Low bank enable
- | | | | | +---- High bank enable
- | | | | +------ Hi/low select
- | | | +---------- Gain (1,?,2,4,8,16,32,64)
- | | +-------------- differential/single ended
- | +---------------- Unipolar
- +------------------------- Correction gain high
-
- 999. The card seems to have an incredible amount of capabilities, but
- trying to reverse engineer them from the Windows source is beyond my
- patience.
-
+ * This card was obviously never intended to leave the Windows world,
+ * since it lacked all kind of hardware documentation (except for cable
+ * pinouts, plug and pray has something to catch up with yet).
+ *
+ * With some help from our swedish distributor, we got the Windows sourcecode
+ * for the card, and here are the findings so far.
+ *
+ * 1. A good document that describes the PCI interface chip is 9080db-106.pdf
+ * available from http://www.plxtech.com/products/io/pci9080
+ *
+ * 2. The initialization done so far is:
+ * a. program the FPGA (windows code sans a lot of error messages)
+ * b.
+ *
+ * 3. Analog out seems to work OK with DAC's disabled, if DAC's are enabled,
+ * you have to output values to all enabled DAC's until result appears, I
+ * guess that it has something to do with pacer clocks, but the source
+ * gives me no clues. I'll keep it simple so far.
+ *
+ * 4. Analog in.
+ * Each channel in the scanlist seems to be controlled by four
+ * control words:
+ *
+ * Word0:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ! | | | ! | | | ! | | | ! | | | !
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * Word1:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ! | | | ! | | | ! | | | ! | | | !
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | |
+ * +------+------+ | | | | +-- Digital input (??)
+ * | | | | +---- 10 us settling time
+ * | | | +------ Suspend acquisition (last to scan)
+ * | | +-------- Simultaneous sample and hold
+ * | +---------- Signed data format
+ * +------------------------- Correction offset low
+ *
+ * Word2:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ! | | | ! | | | ! | | | ! | | | !
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | | |
+ * +-----+ +--+--+ +++ +++ +--+--+
+ * | | | | +----- Expansion channel
+ * | | | +----------- Expansion gain
+ * | | +--------------- Channel (low)
+ * | +--------------------- Correction offset high
+ * +----------------------------- Correction gain low
+ * Word3:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * ! | | | ! | | | ! | | | ! | | | !
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | | | | | | | | |
+ * +------+------+ | | +-+-+ | | +-- Low bank enable
+ * | | | | | +---- High bank enable
+ * | | | | +------ Hi/low select
+ * | | | +---------- Gain (1,?,2,4,8,16,32,64)
+ * | | +-------------- differential/single ended
+ * | +---------------- Unipolar
+ * +------------------------- Correction gain high
+ *
+ * 999. The card seems to have an incredible amount of capabilities, but
+ * trying to reverse engineer them from the Windows source is beyond my
+ * patience.
+ *
*/
#include <linux/module.h>
(2) - the list must have an even number of entries.
Options:
- [0] - base io address
- [1] - irq (optional, but you probably want it)
+ [0] - base io address
+ [1] - irq (optional, but you probably want it)
irq can be omitted, although the cmd interface will not work without it.
*/
* PCI BAR2 Register map (dev->mmio)
*/
#define FIRMWARE_REV_REG 0x00
-#define FEATURES_REG_PRESENT_BIT (1 << 15)
+#define FEATURES_REG_PRESENT_BIT BIT(15)
#define BOARD_CONTROL_REG 0x04
-#define BOARD_RESET_BIT (1 << 0)
-#define TX_FIFO_RESET_BIT (1 << 1)
-#define RX_FIFO_RESET_BIT (1 << 2)
-#define TX_ENABLE_BIT (1 << 4)
-#define RX_ENABLE_BIT (1 << 5)
-#define DEMAND_DMA_DIRECTION_TX_BIT (1 << 6) /* ch 0 only */
-#define LINE_VALID_ON_STATUS_VALID_BIT (1 << 7)
-#define START_TX_BIT (1 << 8)
-#define CABLE_THROTTLE_ENABLE_BIT (1 << 9)
-#define TEST_MODE_ENABLE_BIT (1 << 31)
+#define BOARD_RESET_BIT BIT(0)
+#define TX_FIFO_RESET_BIT BIT(1)
+#define RX_FIFO_RESET_BIT BIT(2)
+#define TX_ENABLE_BIT BIT(4)
+#define RX_ENABLE_BIT BIT(5)
+#define DEMAND_DMA_DIRECTION_TX_BIT BIT(6) /* ch 0 only */
+#define LINE_VALID_ON_STATUS_VALID_BIT BIT(7)
+#define START_TX_BIT BIT(8)
+#define CABLE_THROTTLE_ENABLE_BIT BIT(9)
+#define TEST_MODE_ENABLE_BIT BIT(31)
#define BOARD_STATUS_REG 0x08
#define COMMAND_LINE_STATUS_MASK (0x7f << 0)
-#define TX_IN_PROGRESS_BIT (1 << 7)
-#define TX_NOT_EMPTY_BIT (1 << 8)
-#define TX_NOT_ALMOST_EMPTY_BIT (1 << 9)
-#define TX_NOT_ALMOST_FULL_BIT (1 << 10)
-#define TX_NOT_FULL_BIT (1 << 11)
-#define RX_NOT_EMPTY_BIT (1 << 12)
-#define RX_NOT_ALMOST_EMPTY_BIT (1 << 13)
-#define RX_NOT_ALMOST_FULL_BIT (1 << 14)
-#define RX_NOT_FULL_BIT (1 << 15)
-#define BOARD_JUMPER0_INSTALLED_BIT (1 << 16)
-#define BOARD_JUMPER1_INSTALLED_BIT (1 << 17)
-#define TX_OVERRUN_BIT (1 << 21)
-#define RX_UNDERRUN_BIT (1 << 22)
-#define RX_OVERRUN_BIT (1 << 23)
+#define TX_IN_PROGRESS_BIT BIT(7)
+#define TX_NOT_EMPTY_BIT BIT(8)
+#define TX_NOT_ALMOST_EMPTY_BIT BIT(9)
+#define TX_NOT_ALMOST_FULL_BIT BIT(10)
+#define TX_NOT_FULL_BIT BIT(11)
+#define RX_NOT_EMPTY_BIT BIT(12)
+#define RX_NOT_ALMOST_EMPTY_BIT BIT(13)
+#define RX_NOT_ALMOST_FULL_BIT BIT(14)
+#define RX_NOT_FULL_BIT BIT(15)
+#define BOARD_JUMPER0_INSTALLED_BIT BIT(16)
+#define BOARD_JUMPER1_INSTALLED_BIT BIT(17)
+#define TX_OVERRUN_BIT BIT(21)
+#define RX_UNDERRUN_BIT BIT(22)
+#define RX_OVERRUN_BIT BIT(23)
#define TX_PROG_ALMOST_REG 0x0c
#define RX_PROG_ALMOST_REG 0x10
#define ALMOST_EMPTY_BITS(x) (((x) & 0xffff) << 0)
#define ALMOST_FULL_BITS(x) (((x) & 0xff) << 16)
#define FEATURES_REG 0x14
-#define FIFO_SIZE_PRESENT_BIT (1 << 0)
-#define FIFO_WORDS_PRESENT_BIT (1 << 1)
-#define LEVEL_EDGE_INTERRUPTS_PRESENT_BIT (1 << 2)
-#define GPIO_SUPPORTED_BIT (1 << 3)
-#define PLX_DMA_CH1_SUPPORTED_BIT (1 << 4)
-#define OVERRUN_UNDERRUN_SUPPORTED_BIT (1 << 5)
+#define FIFO_SIZE_PRESENT_BIT BIT(0)
+#define FIFO_WORDS_PRESENT_BIT BIT(1)
+#define LEVEL_EDGE_INTERRUPTS_PRESENT_BIT BIT(2)
+#define GPIO_SUPPORTED_BIT BIT(3)
+#define PLX_DMA_CH1_SUPPORTED_BIT BIT(4)
+#define OVERRUN_UNDERRUN_SUPPORTED_BIT BIT(5)
#define FIFO_REG 0x18
#define TX_STATUS_COUNT_REG 0x1c
#define TX_LINE_VALID_COUNT_REG 0x20,
#define RX_STATUS_COUNT_REG 0x28
#define RX_LINE_COUNT_REG 0x2c
#define INTERRUPT_CONTROL_REG 0x30
-#define FRAME_VALID_START_INTR (1 << 0)
-#define FRAME_VALID_END_INTR (1 << 1)
-#define TX_FIFO_EMPTY_INTR (1 << 8)
-#define TX_FIFO_ALMOST_EMPTY_INTR (1 << 9)
-#define TX_FIFO_ALMOST_FULL_INTR (1 << 10)
-#define TX_FIFO_FULL_INTR (1 << 11)
-#define RX_EMPTY_INTR (1 << 12)
-#define RX_ALMOST_EMPTY_INTR (1 << 13)
-#define RX_ALMOST_FULL_INTR (1 << 14)
-#define RX_FULL_INTR (1 << 15)
+#define FRAME_VALID_START_INTR BIT(0)
+#define FRAME_VALID_END_INTR BIT(1)
+#define TX_FIFO_EMPTY_INTR BIT(8)
+#define TX_FIFO_ALMOST_EMPTY_INTR BIT(9)
+#define TX_FIFO_ALMOST_FULL_INTR BIT(10)
+#define TX_FIFO_FULL_INTR BIT(11)
+#define RX_EMPTY_INTR BIT(12)
+#define RX_ALMOST_EMPTY_INTR BIT(13)
+#define RX_ALMOST_FULL_INTR BIT(14)
+#define RX_FULL_INTR BIT(15)
#define INTERRUPT_STATUS_REG 0x34
#define TX_CLOCK_DIVIDER_REG 0x38
#define TX_FIFO_SIZE_REG 0x40
#define NUM_DMA_BUFFERS 4
#define NUM_DMA_DESCRIPTORS 256
-struct hpdi_board {
- const char *name;
- int device_id;
- int subdevice_id;
-};
-
-static const struct hpdi_board hpdi_boards[] = {
- {
- .name = "pci-hpdi32",
- .device_id = PCI_DEVICE_ID_PLX_9080,
- .subdevice_id = 0x2400,
- },
-};
-
struct hpdi_private {
void __iomem *plx9080_mmio;
- uint32_t *dio_buffer[NUM_DMA_BUFFERS]; /* dma buffers */
+ uint32_t *dio_buffer[NUM_DMA_BUFFERS]; /* dma buffers */
/* physical addresses of dma buffers */
dma_addr_t dio_buffer_phys_addr[NUM_DMA_BUFFERS];
- /* array of dma descriptors read by plx9080, allocated to get proper
- * alignment */
+ /*
+ * array of dma descriptors read by plx9080, allocated to get proper
+ * alignment
+ */
struct plx_dma_desc *dma_desc;
/* physical address of dma descriptor array */
dma_addr_t dma_desc_phys_addr;
devpriv->dma_desc_index = idx;
}
- /* XXX check for buffer overrun somehow */
+ /* XXX check for buffer overrun somehow */
}
static irqreturn_t gsc_hpdi_interrupt(int irq, void *d)
if (hpdi_intr_status)
writel(hpdi_intr_status, dev->mmio + INTERRUPT_STATUS_REG);
- /* spin lock makes sure no one else changes plx dma control reg */
+ /* spin lock makes sure no one else changes plx dma control reg */
spin_lock_irqsave(&dev->spinlock, flags);
dma0_status = readb(devpriv->plx9080_mmio + PLX_DMA0_CS_REG);
- if (plx_status & ICS_DMA0_A) { /* dma chan 0 interrupt */
+ if (plx_status & ICS_DMA0_A) {
+ /* dma chan 0 interrupt */
writeb((dma0_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
devpriv->plx9080_mmio + PLX_DMA0_CS_REG);
}
spin_unlock_irqrestore(&dev->spinlock, flags);
- /* spin lock makes sure no one else changes plx dma control reg */
+ /* spin lock makes sure no one else changes plx dma control reg */
spin_lock_irqsave(&dev->spinlock, flags);
dma1_status = readb(devpriv->plx9080_mmio + PLX_DMA1_CS_REG);
- if (plx_status & ICS_DMA1_A) { /* XXX *//* dma chan 1 interrupt */
+ if (plx_status & ICS_DMA1_A) {
+ /* XXX */ /* dma chan 1 interrupt */
writeb((dma1_status & PLX_DMA_EN_BIT) | PLX_CLEAR_DMA_INTR_BIT,
devpriv->plx9080_mmio + PLX_DMA1_CS_REG);
}
spin_unlock_irqrestore(&dev->spinlock, flags);
- /* clear possible plx9080 interrupt sources */
- if (plx_status & ICS_LDIA) { /* clear local doorbell interrupt */
+ /* clear possible plx9080 interrupt sources */
+ if (plx_status & ICS_LDIA) {
+ /* clear local doorbell interrupt */
plx_bits = readl(devpriv->plx9080_mmio + PLX_DBR_OUT_REG);
writel(plx_bits, devpriv->plx9080_mmio + PLX_DBR_OUT_REG);
}
struct hpdi_private *devpriv = dev->private;
unsigned long flags;
- /* spinlock for plx dma control/status reg */
+ /* spinlock for plx dma control/status reg */
spin_lock_irqsave(&dev->spinlock, flags);
plx9080_abort_dma(devpriv->plx9080_mmio, channel);
/* wait 10usec after reset before accessing fifos */
writel(BOARD_RESET_BIT, dev->mmio + BOARD_CONTROL_REG);
- udelay(10);
+ usleep_range(10, 1000);
writel(ALMOST_EMPTY_BITS(32) | ALMOST_FULL_BITS(32),
dev->mmio + RX_PROG_ALMOST_REG);
writel(0, dev->mmio + INTERRUPT_CONTROL_REG);
- /* enable interrupts */
+ /* enable interrupts */
plx_intcsr_bits =
ICS_AERR | ICS_PERR | ICS_PIE | ICS_PLIE | ICS_PAIE | ICS_LIE |
ICS_DMA0_E;
gsc_hpdi_abort_dma(dev, 0);
gsc_hpdi_abort_dma(dev, 1);
- /* configure dma0 mode */
+ /* configure dma0 mode */
bits = 0;
- /* enable ready input */
+ /* enable ready input */
bits |= PLX_DMA_EN_READYIN_BIT;
- /* enable dma chaining */
+ /* enable dma chaining */
bits |= PLX_EN_CHAIN_BIT;
- /* enable interrupt on dma done
- * (probably don't need this, since chain never finishes) */
+ /*
+ * enable interrupt on dma done
+ * (probably don't need this, since chain never finishes)
+ */
bits |= PLX_EN_DMA_DONE_INTR_BIT;
- /* don't increment local address during transfers
- * (we are transferring from a fixed fifo register) */
+ /*
+ * don't increment local address during transfers
+ * (we are transferring from a fixed fifo register)
+ */
bits |= PLX_LOCAL_ADDR_CONST_BIT;
- /* route dma interrupt to pci bus */
+ /* route dma interrupt to pci bus */
bits |= PLX_DMA_INTR_PCI_BIT;
- /* enable demand mode */
+ /* enable demand mode */
bits |= PLX_DEMAND_MODE_BIT;
- /* enable local burst mode */
+ /* enable local burst mode */
bits |= PLX_DMA_LOCAL_BURST_EN_BIT;
bits |= PLX_LOCAL_BUS_32_WIDE_BITS;
writel(bits, plx_iobase + PLX_DMA0_MODE_REG);
}
-static const struct hpdi_board *gsc_hpdi_find_board(struct pci_dev *pcidev)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(hpdi_boards); i++)
- if (pcidev->device == hpdi_boards[i].device_id &&
- pcidev->subsystem_device == hpdi_boards[i].subdevice_id)
- return &hpdi_boards[i];
- return NULL;
-}
-
static int gsc_hpdi_auto_attach(struct comedi_device *dev,
unsigned long context_unused)
{
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
- const struct hpdi_board *thisboard;
struct hpdi_private *devpriv;
struct comedi_subdevice *s;
int i;
int retval;
- thisboard = gsc_hpdi_find_board(pcidev);
- if (!thisboard) {
- dev_err(dev->class_dev, "gsc_hpdi: pci %s not supported\n",
- pci_name(pcidev));
- return -EINVAL;
- }
- dev->board_ptr = thisboard;
- dev->board_name = thisboard->name;
+ dev->board_name = "pci-hpdi32";
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
if (!devpriv)
gsc_hpdi_init_plx9080(dev);
- /* get irq */
+ /* get irq */
if (request_irq(pcidev->irq, gsc_hpdi_interrupt, IRQF_SHARED,
dev->board_name, dev)) {
dev_warn(dev->class_dev,
dev_dbg(dev->class_dev, " irq %u\n", dev->irq);
- /* allocate pci dma buffers */
+ /* allocate pci dma buffers */
for (i = 0; i < NUM_DMA_BUFFERS; i++) {
devpriv->dio_buffer[i] =
pci_alloc_consistent(pcidev, DMA_BUFFER_SIZE,
&devpriv->dio_buffer_phys_addr[i]);
}
- /* allocate dma descriptors */
+ /* allocate dma descriptors */
devpriv->dma_desc = pci_alloc_consistent(pcidev,
sizeof(struct plx_dma_desc) *
NUM_DMA_DESCRIPTORS,
}
static const struct pci_device_id gsc_hpdi_pci_table[] = {
- { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080, PCI_VENDOR_ID_PLX,
- 0x2400, 0, 0, 0},
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9080,
+ PCI_VENDOR_ID_PLX, 0x2400) },
{ 0 }
};
MODULE_DEVICE_TABLE(pci, gsc_hpdi_pci_table);
module_comedi_pci_driver(gsc_hpdi_driver, gsc_hpdi_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org");
-MODULE_DESCRIPTION("Comedi low-level driver");
+MODULE_DESCRIPTION("Comedi driver for General Standards PCI-HPDI32/PMC-HPDI32");
MODULE_LICENSE("GPL");
/* A timeout count */
#define NI_TIMEOUT 1000
-static const unsigned old_RTSI_clock_channel = 7;
/* Note: this table must match the ai_gain_* definitions */
static const short ni_gainlkup[][16] = {
* windowed STC registers to the m series register offsets.
*/
-static void m_series_stc_writel(struct comedi_device *dev,
- uint32_t data, int reg)
+struct mio_regmap {
+ unsigned int mio_reg;
+ int size;
+};
+
+static const struct mio_regmap m_series_stc_write_regmap[] = {
+ [NISTC_INTA_ACK_REG] = { 0x104, 2 },
+ [NISTC_INTB_ACK_REG] = { 0x106, 2 },
+ [NISTC_AI_CMD2_REG] = { 0x108, 2 },
+ [NISTC_AO_CMD2_REG] = { 0x10a, 2 },
+ [NISTC_G0_CMD_REG] = { 0x10c, 2 },
+ [NISTC_G1_CMD_REG] = { 0x10e, 2 },
+ [NISTC_AI_CMD1_REG] = { 0x110, 2 },
+ [NISTC_AO_CMD1_REG] = { 0x112, 2 },
+ /*
+ * NISTC_DIO_OUT_REG maps to:
+ * { NI_M_DIO_REG, 4 } and { NI_M_SCXI_SER_DO_REG, 1 }
+ */
+ [NISTC_DIO_OUT_REG] = { 0, 0 }, /* DOES NOT MAP CLEANLY */
+ [NISTC_DIO_CTRL_REG] = { 0, 0 }, /* DOES NOT MAP CLEANLY */
+ [NISTC_AI_MODE1_REG] = { 0x118, 2 },
+ [NISTC_AI_MODE2_REG] = { 0x11a, 2 },
+ [NISTC_AI_SI_LOADA_REG] = { 0x11c, 4 },
+ [NISTC_AI_SI_LOADB_REG] = { 0x120, 4 },
+ [NISTC_AI_SC_LOADA_REG] = { 0x124, 4 },
+ [NISTC_AI_SC_LOADB_REG] = { 0x128, 4 },
+ [NISTC_AI_SI2_LOADA_REG] = { 0x12c, 4 },
+ [NISTC_AI_SI2_LOADB_REG] = { 0x130, 4 },
+ [NISTC_G0_MODE_REG] = { 0x134, 2 },
+ [NISTC_G1_MODE_REG] = { 0x136, 2 },
+ [NISTC_G0_LOADA_REG] = { 0x138, 4 },
+ [NISTC_G0_LOADB_REG] = { 0x13c, 4 },
+ [NISTC_G1_LOADA_REG] = { 0x140, 4 },
+ [NISTC_G1_LOADB_REG] = { 0x144, 4 },
+ [NISTC_G0_INPUT_SEL_REG] = { 0x148, 2 },
+ [NISTC_G1_INPUT_SEL_REG] = { 0x14a, 2 },
+ [NISTC_AO_MODE1_REG] = { 0x14c, 2 },
+ [NISTC_AO_MODE2_REG] = { 0x14e, 2 },
+ [NISTC_AO_UI_LOADA_REG] = { 0x150, 4 },
+ [NISTC_AO_UI_LOADB_REG] = { 0x154, 4 },
+ [NISTC_AO_BC_LOADA_REG] = { 0x158, 4 },
+ [NISTC_AO_BC_LOADB_REG] = { 0x15c, 4 },
+ [NISTC_AO_UC_LOADA_REG] = { 0x160, 4 },
+ [NISTC_AO_UC_LOADB_REG] = { 0x164, 4 },
+ [NISTC_CLK_FOUT_REG] = { 0x170, 2 },
+ [NISTC_IO_BIDIR_PIN_REG] = { 0x172, 2 },
+ [NISTC_RTSI_TRIG_DIR_REG] = { 0x174, 2 },
+ [NISTC_INT_CTRL_REG] = { 0x176, 2 },
+ [NISTC_AI_OUT_CTRL_REG] = { 0x178, 2 },
+ [NISTC_ATRIG_ETC_REG] = { 0x17a, 2 },
+ [NISTC_AI_START_STOP_REG] = { 0x17c, 2 },
+ [NISTC_AI_TRIG_SEL_REG] = { 0x17e, 2 },
+ [NISTC_AI_DIV_LOADA_REG] = { 0x180, 4 },
+ [NISTC_AO_START_SEL_REG] = { 0x184, 2 },
+ [NISTC_AO_TRIG_SEL_REG] = { 0x186, 2 },
+ [NISTC_G0_AUTOINC_REG] = { 0x188, 2 },
+ [NISTC_G1_AUTOINC_REG] = { 0x18a, 2 },
+ [NISTC_AO_MODE3_REG] = { 0x18c, 2 },
+ [NISTC_RESET_REG] = { 0x190, 2 },
+ [NISTC_INTA_ENA_REG] = { 0x192, 2 },
+ [NISTC_INTA2_ENA_REG] = { 0, 0 }, /* E-Series only */
+ [NISTC_INTB_ENA_REG] = { 0x196, 2 },
+ [NISTC_INTB2_ENA_REG] = { 0, 0 }, /* E-Series only */
+ [NISTC_AI_PERSONAL_REG] = { 0x19a, 2 },
+ [NISTC_AO_PERSONAL_REG] = { 0x19c, 2 },
+ [NISTC_RTSI_TRIGA_OUT_REG] = { 0x19e, 2 },
+ [NISTC_RTSI_TRIGB_OUT_REG] = { 0x1a0, 2 },
+ [NISTC_RTSI_BOARD_REG] = { 0, 0 }, /* Unknown */
+ [NISTC_CFG_MEM_CLR_REG] = { 0x1a4, 2 },
+ [NISTC_ADC_FIFO_CLR_REG] = { 0x1a6, 2 },
+ [NISTC_DAC_FIFO_CLR_REG] = { 0x1a8, 2 },
+ [NISTC_AO_OUT_CTRL_REG] = { 0x1ac, 2 },
+ [NISTC_AI_MODE3_REG] = { 0x1ae, 2 },
+};
+
+static void m_series_stc_write(struct comedi_device *dev,
+ unsigned int data, unsigned int reg)
{
- unsigned offset;
+ const struct mio_regmap *regmap;
- switch (reg) {
- case AI_SC_Load_A_Registers:
- offset = M_Offset_AI_SC_Load_A;
- break;
- case AI_SI_Load_A_Registers:
- offset = M_Offset_AI_SI_Load_A;
- break;
- case AO_BC_Load_A_Register:
- offset = M_Offset_AO_BC_Load_A;
- break;
- case AO_UC_Load_A_Register:
- offset = M_Offset_AO_UC_Load_A;
- break;
- case AO_UI_Load_A_Register:
- offset = M_Offset_AO_UI_Load_A;
- break;
- case G_Load_A_Register(0):
- offset = M_Offset_G0_Load_A;
- break;
- case G_Load_A_Register(1):
- offset = M_Offset_G1_Load_A;
- break;
- case G_Load_B_Register(0):
- offset = M_Offset_G0_Load_B;
- break;
- case G_Load_B_Register(1):
- offset = M_Offset_G1_Load_B;
- break;
- default:
- dev_warn(dev->class_dev,
- "%s: bug! unhandled register=0x%x in switch\n",
+ if (reg < ARRAY_SIZE(m_series_stc_write_regmap)) {
+ regmap = &m_series_stc_write_regmap[reg];
+ } else {
+ dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n",
__func__, reg);
return;
}
- ni_writel(dev, data, offset);
-}
-static void m_series_stc_writew(struct comedi_device *dev,
- uint16_t data, int reg)
-{
- unsigned offset;
-
- switch (reg) {
- case ADC_FIFO_Clear:
- offset = M_Offset_AI_FIFO_Clear;
- break;
- case AI_Command_1_Register:
- offset = M_Offset_AI_Command_1;
- break;
- case AI_Command_2_Register:
- offset = M_Offset_AI_Command_2;
- break;
- case AI_Mode_1_Register:
- offset = M_Offset_AI_Mode_1;
- break;
- case AI_Mode_2_Register:
- offset = M_Offset_AI_Mode_2;
- break;
- case AI_Mode_3_Register:
- offset = M_Offset_AI_Mode_3;
- break;
- case AI_Output_Control_Register:
- offset = M_Offset_AI_Output_Control;
- break;
- case AI_Personal_Register:
- offset = M_Offset_AI_Personal;
- break;
- case AI_SI2_Load_A_Register:
- /* this is a 32 bit register on m series boards */
- ni_writel(dev, data, M_Offset_AI_SI2_Load_A);
- return;
- case AI_SI2_Load_B_Register:
- /* this is a 32 bit register on m series boards */
- ni_writel(dev, data, M_Offset_AI_SI2_Load_B);
- return;
- case AI_START_STOP_Select_Register:
- offset = M_Offset_AI_START_STOP_Select;
- break;
- case AI_Trigger_Select_Register:
- offset = M_Offset_AI_Trigger_Select;
- break;
- case Analog_Trigger_Etc_Register:
- offset = M_Offset_Analog_Trigger_Etc;
- break;
- case AO_Command_1_Register:
- offset = M_Offset_AO_Command_1;
- break;
- case AO_Command_2_Register:
- offset = M_Offset_AO_Command_2;
- break;
- case AO_Mode_1_Register:
- offset = M_Offset_AO_Mode_1;
- break;
- case AO_Mode_2_Register:
- offset = M_Offset_AO_Mode_2;
- break;
- case AO_Mode_3_Register:
- offset = M_Offset_AO_Mode_3;
- break;
- case AO_Output_Control_Register:
- offset = M_Offset_AO_Output_Control;
- break;
- case AO_Personal_Register:
- offset = M_Offset_AO_Personal;
- break;
- case AO_Start_Select_Register:
- offset = M_Offset_AO_Start_Select;
- break;
- case AO_Trigger_Select_Register:
- offset = M_Offset_AO_Trigger_Select;
- break;
- case Clock_and_FOUT_Register:
- offset = M_Offset_Clock_and_FOUT;
- break;
- case Configuration_Memory_Clear:
- offset = M_Offset_Configuration_Memory_Clear;
- break;
- case DAC_FIFO_Clear:
- offset = M_Offset_AO_FIFO_Clear;
- break;
- case DIO_Control_Register:
- dev_dbg(dev->class_dev,
- "%s: FIXME: register 0x%x does not map cleanly on to m-series boards\n",
- __func__, reg);
- return;
- case G_Autoincrement_Register(0):
- offset = M_Offset_G0_Autoincrement;
- break;
- case G_Autoincrement_Register(1):
- offset = M_Offset_G1_Autoincrement;
- break;
- case G_Command_Register(0):
- offset = M_Offset_G0_Command;
- break;
- case G_Command_Register(1):
- offset = M_Offset_G1_Command;
- break;
- case G_Input_Select_Register(0):
- offset = M_Offset_G0_Input_Select;
- break;
- case G_Input_Select_Register(1):
- offset = M_Offset_G1_Input_Select;
- break;
- case G_Mode_Register(0):
- offset = M_Offset_G0_Mode;
- break;
- case G_Mode_Register(1):
- offset = M_Offset_G1_Mode;
- break;
- case Interrupt_A_Ack_Register:
- offset = M_Offset_Interrupt_A_Ack;
- break;
- case Interrupt_A_Enable_Register:
- offset = M_Offset_Interrupt_A_Enable;
- break;
- case Interrupt_B_Ack_Register:
- offset = M_Offset_Interrupt_B_Ack;
- break;
- case Interrupt_B_Enable_Register:
- offset = M_Offset_Interrupt_B_Enable;
- break;
- case Interrupt_Control_Register:
- offset = M_Offset_Interrupt_Control;
- break;
- case IO_Bidirection_Pin_Register:
- offset = M_Offset_IO_Bidirection_Pin;
- break;
- case Joint_Reset_Register:
- offset = M_Offset_Joint_Reset;
- break;
- case RTSI_Trig_A_Output_Register:
- offset = M_Offset_RTSI_Trig_A_Output;
- break;
- case RTSI_Trig_B_Output_Register:
- offset = M_Offset_RTSI_Trig_B_Output;
+ switch (regmap->size) {
+ case 4:
+ ni_writel(dev, data, regmap->mio_reg);
break;
- case RTSI_Trig_Direction_Register:
- offset = M_Offset_RTSI_Trig_Direction;
+ case 2:
+ ni_writew(dev, data, regmap->mio_reg);
break;
- /*
- * FIXME: DIO_Output_Register (16 bit reg) is replaced by
- * M_Offset_Static_Digital_Output (32 bit) and
- * M_Offset_SCXI_Serial_Data_Out (8 bit)
- */
default:
- dev_warn(dev->class_dev,
- "%s: bug! unhandled register=0x%x in switch\n",
+ dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n",
__func__, reg);
- return;
+ break;
}
- ni_writew(dev, data, offset);
}
-static uint32_t m_series_stc_readl(struct comedi_device *dev, int reg)
+static const struct mio_regmap m_series_stc_read_regmap[] = {
+ [NISTC_AI_STATUS1_REG] = { 0x104, 2 },
+ [NISTC_AO_STATUS1_REG] = { 0x106, 2 },
+ [NISTC_G01_STATUS_REG] = { 0x108, 2 },
+ [NISTC_AI_STATUS2_REG] = { 0, 0 }, /* Unknown */
+ [NISTC_AO_STATUS2_REG] = { 0x10c, 2 },
+ [NISTC_DIO_IN_REG] = { 0, 0 }, /* Unknown */
+ [NISTC_G0_HW_SAVE_REG] = { 0x110, 4 },
+ [NISTC_G1_HW_SAVE_REG] = { 0x114, 4 },
+ [NISTC_G0_SAVE_REG] = { 0x118, 4 },
+ [NISTC_G1_SAVE_REG] = { 0x11c, 4 },
+ [NISTC_AO_UI_SAVE_REG] = { 0x120, 4 },
+ [NISTC_AO_BC_SAVE_REG] = { 0x124, 4 },
+ [NISTC_AO_UC_SAVE_REG] = { 0x128, 4 },
+ [NISTC_STATUS1_REG] = { 0x136, 2 },
+ [NISTC_DIO_SERIAL_IN_REG] = { 0x009, 1 },
+ [NISTC_STATUS2_REG] = { 0x13a, 2 },
+ [NISTC_AI_SI_SAVE_REG] = { 0x180, 4 },
+ [NISTC_AI_SC_SAVE_REG] = { 0x184, 4 },
+};
+
+static unsigned int m_series_stc_read(struct comedi_device *dev,
+ unsigned int reg)
{
- unsigned offset;
+ const struct mio_regmap *regmap;
- switch (reg) {
- case G_HW_Save_Register(0):
- offset = M_Offset_G0_HW_Save;
- break;
- case G_HW_Save_Register(1):
- offset = M_Offset_G1_HW_Save;
- break;
- case G_Save_Register(0):
- offset = M_Offset_G0_Save;
- break;
- case G_Save_Register(1):
- offset = M_Offset_G1_Save;
- break;
- default:
- dev_warn(dev->class_dev,
- "%s: bug! unhandled register=0x%x in switch\n",
+ if (reg < ARRAY_SIZE(m_series_stc_read_regmap)) {
+ regmap = &m_series_stc_read_regmap[reg];
+ } else {
+ dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n",
__func__, reg);
return 0;
}
- return ni_readl(dev, offset);
-}
-static uint16_t m_series_stc_readw(struct comedi_device *dev, int reg)
-{
- unsigned offset;
-
- switch (reg) {
- case AI_Status_1_Register:
- offset = M_Offset_AI_Status_1;
- break;
- case AO_Status_1_Register:
- offset = M_Offset_AO_Status_1;
- break;
- case AO_Status_2_Register:
- offset = M_Offset_AO_Status_2;
- break;
- case DIO_Serial_Input_Register:
- return ni_readb(dev, M_Offset_SCXI_Serial_Data_In);
- case Joint_Status_1_Register:
- offset = M_Offset_Joint_Status_1;
- break;
- case Joint_Status_2_Register:
- offset = M_Offset_Joint_Status_2;
- break;
- case G_Status_Register:
- offset = M_Offset_G01_Status;
- break;
+ switch (regmap->size) {
+ case 4:
+ return ni_readl(dev, regmap->mio_reg);
+ case 2:
+ return ni_readw(dev, regmap->mio_reg);
+ case 1:
+ return ni_readb(dev, regmap->mio_reg);
default:
- dev_warn(dev->class_dev,
- "%s: bug! unhandled register=0x%x in switch\n",
+ dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n",
__func__, reg);
return 0;
}
- return ni_readw(dev, offset);
}
static void ni_stc_writew(struct comedi_device *dev, uint16_t data, int reg)
unsigned long flags;
if (devpriv->is_m_series) {
- m_series_stc_writew(dev, data, reg);
+ m_series_stc_write(dev, data, reg);
} else {
spin_lock_irqsave(&devpriv->window_lock, flags);
if (!devpriv->mite && reg < 8) {
ni_writew(dev, data, reg * 2);
} else {
- ni_writew(dev, reg, Window_Address);
- ni_writew(dev, data, Window_Data);
+ ni_writew(dev, reg, NI_E_STC_WINDOW_ADDR_REG);
+ ni_writew(dev, data, NI_E_STC_WINDOW_DATA_REG);
}
spin_unlock_irqrestore(&devpriv->window_lock, flags);
}
struct ni_private *devpriv = dev->private;
if (devpriv->is_m_series) {
- m_series_stc_writel(dev, data, reg);
+ m_series_stc_write(dev, data, reg);
} else {
ni_stc_writew(dev, data >> 16, reg);
ni_stc_writew(dev, data & 0xffff, reg + 1);
uint16_t val;
if (devpriv->is_m_series) {
- val = m_series_stc_readw(dev, reg);
+ val = m_series_stc_read(dev, reg);
} else {
spin_lock_irqsave(&devpriv->window_lock, flags);
if (!devpriv->mite && reg < 8) {
val = ni_readw(dev, reg * 2);
} else {
- ni_writew(dev, reg, Window_Address);
- val = ni_readw(dev, Window_Data);
+ ni_writew(dev, reg, NI_E_STC_WINDOW_ADDR_REG);
+ val = ni_readw(dev, NI_E_STC_WINDOW_DATA_REG);
}
spin_unlock_irqrestore(&devpriv->window_lock, flags);
}
uint32_t val;
if (devpriv->is_m_series) {
- val = m_series_stc_readl(dev, reg);
+ val = m_series_stc_read(dev, reg);
} else {
val = ni_stc_readw(dev, reg) << 16;
val |= ni_stc_readw(dev, reg + 1);
spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
switch (reg) {
- case Interrupt_A_Enable_Register:
+ case NISTC_INTA_ENA_REG:
devpriv->int_a_enable_reg &= ~bit_mask;
devpriv->int_a_enable_reg |= bit_values & bit_mask;
- ni_stc_writew(dev, devpriv->int_a_enable_reg,
- Interrupt_A_Enable_Register);
+ ni_stc_writew(dev, devpriv->int_a_enable_reg, reg);
break;
- case Interrupt_B_Enable_Register:
+ case NISTC_INTB_ENA_REG:
devpriv->int_b_enable_reg &= ~bit_mask;
devpriv->int_b_enable_reg |= bit_values & bit_mask;
- ni_stc_writew(dev, devpriv->int_b_enable_reg,
- Interrupt_B_Enable_Register);
+ ni_stc_writew(dev, devpriv->int_b_enable_reg, reg);
break;
- case IO_Bidirection_Pin_Register:
+ case NISTC_IO_BIDIR_PIN_REG:
devpriv->io_bidirection_pin_reg &= ~bit_mask;
devpriv->io_bidirection_pin_reg |= bit_values & bit_mask;
- ni_stc_writew(dev, devpriv->io_bidirection_pin_reg,
- IO_Bidirection_Pin_Register);
+ ni_stc_writew(dev, devpriv->io_bidirection_pin_reg, reg);
break;
- case AI_AO_Select:
+ case NI_E_DMA_AI_AO_SEL_REG:
devpriv->ai_ao_select_reg &= ~bit_mask;
devpriv->ai_ao_select_reg |= bit_values & bit_mask;
- ni_writeb(dev, devpriv->ai_ao_select_reg, AI_AO_Select);
+ ni_writeb(dev, devpriv->ai_ao_select_reg, reg);
break;
- case G0_G1_Select:
+ case NI_E_DMA_G0_G1_SEL_REG:
devpriv->g0_g1_select_reg &= ~bit_mask;
devpriv->g0_g1_select_reg |= bit_values & bit_mask;
- ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select);
+ ni_writeb(dev, devpriv->g0_g1_select_reg, reg);
break;
default:
dev_err(dev->class_dev, "called with invalid register %d\n",
#ifdef PCIDMA
/* DMA channel setup */
+static inline unsigned ni_stc_dma_channel_select_bitfield(unsigned channel)
+{
+ if (channel < 4)
+ return 1 << channel;
+ if (channel == 4)
+ return 0x3;
+ if (channel == 5)
+ return 0x5;
+ BUG();
+ return 0;
+}
/* negative channel means no channel */
static inline void ni_set_ai_dma_channel(struct comedi_device *dev, int channel)
{
- unsigned bitfield;
+ unsigned bits = 0;
if (channel >= 0)
- bitfield =
- (ni_stc_dma_channel_select_bitfield(channel) <<
- AI_DMA_Select_Shift) & AI_DMA_Select_Mask;
- else
- bitfield = 0;
- ni_set_bitfield(dev, AI_AO_Select, AI_DMA_Select_Mask, bitfield);
+ bits = ni_stc_dma_channel_select_bitfield(channel);
+
+ ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG,
+ NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits));
}
/* negative channel means no channel */
static inline void ni_set_ao_dma_channel(struct comedi_device *dev, int channel)
{
- unsigned bitfield;
+ unsigned bits = 0;
if (channel >= 0)
- bitfield =
- (ni_stc_dma_channel_select_bitfield(channel) <<
- AO_DMA_Select_Shift) & AO_DMA_Select_Mask;
- else
- bitfield = 0;
- ni_set_bitfield(dev, AI_AO_Select, AO_DMA_Select_Mask, bitfield);
+ bits = ni_stc_dma_channel_select_bitfield(channel);
+
+ ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG,
+ NI_E_DMA_AO_SEL_MASK, NI_E_DMA_AO_SEL(bits));
}
-/* negative mite_channel means no channel */
+/* negative channel means no channel */
static inline void ni_set_gpct_dma_channel(struct comedi_device *dev,
unsigned gpct_index,
- int mite_channel)
+ int channel)
{
- unsigned bitfield;
+ unsigned bits = 0;
- if (mite_channel >= 0)
- bitfield = GPCT_DMA_Select_Bits(gpct_index, mite_channel);
- else
- bitfield = 0;
- ni_set_bitfield(dev, G0_G1_Select, GPCT_DMA_Select_Mask(gpct_index),
- bitfield);
+ if (channel >= 0)
+ bits = ni_stc_dma_channel_select_bitfield(channel);
+
+ ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG,
+ NI_E_DMA_G0_G1_SEL_MASK(gpct_index),
+ NI_E_DMA_G0_G1_SEL(gpct_index, bits));
}
/* negative mite_channel means no channel */
{
struct ni_private *devpriv = dev->private;
unsigned long flags;
+ unsigned bits;
spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags);
- devpriv->cdio_dma_select_reg &= ~CDO_DMA_Select_Mask;
+ devpriv->cdio_dma_select_reg &= ~NI_M_CDIO_DMA_SEL_CDO_MASK;
if (mite_channel >= 0) {
- /*XXX just guessing ni_stc_dma_channel_select_bitfield() returns the right bits,
- under the assumption the cdio dma selection works just like ai/ao/gpct.
- Definitely works for dma channels 0 and 1. */
- devpriv->cdio_dma_select_reg |=
- (ni_stc_dma_channel_select_bitfield(mite_channel) <<
- CDO_DMA_Select_Shift) & CDO_DMA_Select_Mask;
- }
- ni_writeb(dev, devpriv->cdio_dma_select_reg, M_Offset_CDIO_DMA_Select);
+ /*
+ * XXX just guessing ni_stc_dma_channel_select_bitfield()
+ * returns the right bits, under the assumption the cdio dma
+ * selection works just like ai/ao/gpct.
+ * Definitely works for dma channels 0 and 1.
+ */
+ bits = ni_stc_dma_channel_select_bitfield(mite_channel);
+ devpriv->cdio_dma_select_reg |= NI_M_CDIO_DMA_SEL_CDO(bits);
+ }
+ ni_writeb(dev, devpriv->cdio_dma_select_reg, NI_M_CDIO_DMA_SEL_REG);
mmiowb();
spin_unlock_irqrestore(&devpriv->soft_reg_copy_lock, flags);
}
unsigned long flags;
struct mite_channel *mite_chan;
- BUG_ON(gpct_index >= NUM_GPCT);
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
BUG_ON(devpriv->counter_dev->counters[gpct_index].mite_chan);
mite_chan =
struct ni_private *devpriv = dev->private;
unsigned long flags;
- BUG_ON(gpct_index >= NUM_GPCT);
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->counter_dev->counters[gpct_index].mite_chan) {
struct mite_channel *mite_chan =
* dma requests for their counters
*/
if (gpct_index == 0) {
- reg = Second_IRQ_A_Enable_Register;
+ reg = NISTC_INTA2_ENA_REG;
if (enable)
- val = G0_Gate_Second_Irq_Enable;
+ val = NISTC_INTA_ENA_G0_GATE;
} else {
- reg = Second_IRQ_B_Enable_Register;
+ reg = NISTC_INTB2_ENA_REG;
if (enable)
- val = G1_Gate_Second_Irq_Enable;
+ val = NISTC_INTB_ENA_G1_GATE;
}
ni_stc_writew(dev, val, reg);
}
if (devpriv->is_6143) {
/* Flush the 6143 data FIFO */
- ni_writel(dev, 0x10, AIFIFO_Control_6143);
- ni_writel(dev, 0x00, AIFIFO_Control_6143);
+ ni_writel(dev, 0x10, NI6143_AI_FIFO_CTRL_REG);
+ ni_writel(dev, 0x00, NI6143_AI_FIFO_CTRL_REG);
/* Wait for complete */
for (i = 0; i < timeout; i++) {
- if (!(ni_readl(dev, AIFIFO_Status_6143) & 0x10))
+ if (!(ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x10))
break;
udelay(1);
}
if (i == timeout)
dev_err(dev->class_dev, "FIFO flush timeout\n");
} else {
- ni_stc_writew(dev, 1, ADC_FIFO_Clear);
+ ni_stc_writew(dev, 1, NISTC_ADC_FIFO_CLR_REG);
if (devpriv->is_625x) {
- ni_writeb(dev, 0, M_Offset_Static_AI_Control(0));
- ni_writeb(dev, 1, M_Offset_Static_AI_Control(0));
+ ni_writeb(dev, 0, NI_M_STATIC_AI_CTRL_REG(0));
+ ni_writeb(dev, 1, NI_M_STATIC_AI_CTRL_REG(0));
#if 0
/* the NI example code does 3 convert pulses for 625x boards,
but that appears to be wrong in practice. */
- ni_stc_writew(dev, AI_CONVERT_Pulse,
- AI_Command_1_Register);
- ni_stc_writew(dev, AI_CONVERT_Pulse,
- AI_Command_1_Register);
- ni_stc_writew(dev, AI_CONVERT_Pulse,
- AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
+ NISTC_AI_CMD1_REG);
+ ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
+ NISTC_AI_CMD1_REG);
+ ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
+ NISTC_AI_CMD1_REG);
#endif
}
}
unsigned long flags;
spin_lock_irqsave(&devpriv->window_lock, flags);
- ni_writew(dev, addr, AO_Window_Address_611x);
- ni_writew(dev, data, AO_Window_Data_611x);
+ ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG);
+ ni_writew(dev, data, NI611X_AO_WINDOW_DATA_REG);
spin_unlock_irqrestore(&devpriv->window_lock, flags);
}
unsigned long flags;
spin_lock_irqsave(&devpriv->window_lock, flags);
- ni_writew(dev, addr, AO_Window_Address_611x);
- ni_writel(dev, data, AO_Window_Data_611x);
+ ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG);
+ ni_writel(dev, data, NI611X_AO_WINDOW_DATA_REG);
spin_unlock_irqrestore(&devpriv->window_lock, flags);
}
unsigned short data;
spin_lock_irqsave(&devpriv->window_lock, flags);
- ni_writew(dev, addr, AO_Window_Address_611x);
- data = ni_readw(dev, AO_Window_Data_611x);
+ ni_writew(dev, addr, NI611X_AO_WINDOW_ADDR_REG);
+ data = ni_readw(dev, NI611X_AO_WINDOW_DATA_REG);
spin_unlock_irqrestore(&devpriv->window_lock, flags);
return data;
}
spin_lock_irqsave(&devpriv->mite_channel_lock, flags);
if (devpriv->ai_mite_chan) {
for (i = 0; i < timeout; i++) {
- if ((ni_stc_readw(dev, AI_Status_1_Register) &
- AI_FIFO_Empty_St)
+ if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
+ NISTC_AI_STATUS1_FIFO_E)
&& mite_bytes_in_transit(devpriv->ai_mite_chan) ==
0)
break;
dev_err(dev->class_dev,
"mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n",
mite_bytes_in_transit(devpriv->ai_mite_chan),
- ni_stc_readw(dev, AI_Status_1_Register));
+ ni_stc_readw(dev, NISTC_AI_STATUS1_REG));
retval = -1;
}
}
for (i = 0; i < timeout; i++) {
unsigned short b_status;
- b_status = ni_stc_readw(dev, AO_Status_1_Register);
- if (b_status & AO_FIFO_Half_Full_St)
+ b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG);
+ if (b_status & NISTC_AO_STATUS1_FIFO_HF)
break;
/* if we poll too often, the pci bus activity seems
to slow the dma transfer down */
i++;
packed_data |= (d << 16) & 0xffff0000;
}
- ni_writel(dev, packed_data, DAC_FIFO_Data_611x);
+ ni_writel(dev, packed_data, NI611X_AO_FIFO_DATA_REG);
} else {
- ni_writew(dev, d, DAC_FIFO_Data);
+ ni_writew(dev, d, NI_E_AO_FIFO_DATA_REG);
}
}
}
unsigned int nsamples;
/* reset fifo */
- ni_stc_writew(dev, 1, DAC_FIFO_Clear);
+ ni_stc_writew(dev, 1, NISTC_DAC_FIFO_CLR_REG);
if (devpriv->is_6xxx)
- ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x);
+ ni_ao_win_outl(dev, 0x6, NI611X_AO_FIFO_OFFSET_LOAD_REG);
/* load some data */
nbytes = comedi_buf_read_n_available(s);
if (devpriv->is_611x) {
for (i = 0; i < n / 2; i++) {
- dl = ni_readl(dev, ADC_FIFO_Data_611x);
+ dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG);
/* This may get the hi/lo data in the wrong order */
data = (dl >> 16) & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
/* Check if there's a single sample stuck in the FIFO */
if (n % 2) {
- dl = ni_readl(dev, ADC_FIFO_Data_611x);
+ dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG);
data = dl & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
} else if (devpriv->is_6143) {
/* This just reads the FIFO assuming the data is present, no checks on the FIFO status are performed */
for (i = 0; i < n / 2; i++) {
- dl = ni_readl(dev, AIFIFO_Data_6143);
+ dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
data = (dl >> 16) & 0xffff;
comedi_buf_write_samples(s, &data, 1);
if (n % 2) {
/* Assume there is a single sample stuck in the FIFO */
/* Get stranded sample into FIFO */
- ni_writel(dev, 0x01, AIFIFO_Control_6143);
- dl = ni_readl(dev, AIFIFO_Data_6143);
+ ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG);
+ dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
data = (dl >> 16) & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
}
for (i = 0; i < n; i++) {
devpriv->ai_fifo_buffer[i] =
- ni_readw(dev, ADC_FIFO_Data_Register);
+ ni_readw(dev, NI_E_AI_FIFO_DATA_REG);
}
comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, n);
}
int i;
if (devpriv->is_611x) {
- while ((ni_stc_readw(dev, AI_Status_1_Register) &
- AI_FIFO_Empty_St) == 0) {
- dl = ni_readl(dev, ADC_FIFO_Data_611x);
+ while ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
+ NISTC_AI_STATUS1_FIFO_E) == 0) {
+ dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG);
/* This may get the hi/lo data in the wrong order */
data = dl >> 16;
}
} else if (devpriv->is_6143) {
i = 0;
- while (ni_readl(dev, AIFIFO_Status_6143) & 0x04) {
- dl = ni_readl(dev, AIFIFO_Data_6143);
+ while (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x04) {
+ dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
/* This may get the hi/lo data in the wrong order */
data = dl >> 16;
i += 2;
}
/* Check if stranded sample is present */
- if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) {
+ if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) {
/* Get stranded sample into FIFO */
- ni_writel(dev, 0x01, AIFIFO_Control_6143);
- dl = ni_readl(dev, AIFIFO_Data_6143);
+ ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG);
+ dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
data = (dl >> 16) & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
} else {
- fifo_empty = ni_stc_readw(dev, AI_Status_1_Register) &
- AI_FIFO_Empty_St;
+ fifo_empty = ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
+ NISTC_AI_STATUS1_FIFO_E;
while (fifo_empty == 0) {
for (i = 0;
i <
sizeof(devpriv->ai_fifo_buffer) /
sizeof(devpriv->ai_fifo_buffer[0]); i++) {
fifo_empty = ni_stc_readw(dev,
- AI_Status_1_Register) &
- AI_FIFO_Empty_St;
+ NISTC_AI_STATUS1_REG) &
+ NISTC_AI_STATUS1_FIFO_E;
if (fifo_empty)
break;
devpriv->ai_fifo_buffer[i] =
- ni_readw(dev, ADC_FIFO_Data_Register);
+ ni_readw(dev, NI_E_AI_FIFO_DATA_REG);
}
comedi_buf_write_samples(s, devpriv->ai_fifo_buffer, i);
}
return;
/* Check if there's a single sample stuck in the FIFO */
- if (ni_readb(dev, XXX_Status) & 0x80) {
- dl = ni_readl(dev, ADC_FIFO_Data_611x);
+ if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) {
+ dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG);
data = dl & 0xffff;
comedi_buf_write_samples(s, &data, 1);
}
return;
/* Check if there's a single sample stuck in the FIFO */
- if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) {
+ if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) {
/* Get stranded sample into FIFO */
- ni_writel(dev, 0x01, AIFIFO_Control_6143);
- dl = ni_readl(dev, AIFIFO_Data_6143);
+ ni_writel(dev, 0x01, NI6143_AI_FIFO_CTRL_REG);
+ dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG);
/* This may get the hi/lo data in the wrong order */
data = (dl >> 16) & 0xffff;
s->async->events |= COMEDI_CB_EOS;
#endif
}
- /* handle special case of single scan using AI_End_On_End_Of_Scan */
- if ((devpriv->ai_cmd2 & AI_End_On_End_Of_Scan))
+ /* handle special case of single scan */
+ if (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS)
shutdown_ai_command(dev);
}
{
unsigned short ack = 0;
- if (a_status & AI_SC_TC_St)
- ack |= AI_SC_TC_Interrupt_Ack;
- if (a_status & AI_START1_St)
- ack |= AI_START1_Interrupt_Ack;
- if (a_status & AI_START_St)
- ack |= AI_START_Interrupt_Ack;
- if (a_status & AI_STOP_St)
- /* not sure why we used to ack the START here also, instead of doing it independently. Frank Hess 2007-07-06 */
- ack |= AI_STOP_Interrupt_Ack /*| AI_START_Interrupt_Ack */;
+ if (a_status & NISTC_AI_STATUS1_SC_TC)
+ ack |= NISTC_INTA_ACK_AI_SC_TC;
+ if (a_status & NISTC_AI_STATUS1_START1)
+ ack |= NISTC_INTA_ACK_AI_START1;
+ if (a_status & NISTC_AI_STATUS1_START)
+ ack |= NISTC_INTA_ACK_AI_START;
+ if (a_status & NISTC_AI_STATUS1_STOP)
+ ack |= NISTC_INTA_ACK_AI_STOP;
if (ack)
- ni_stc_writew(dev, ack, Interrupt_A_Ack_Register);
+ ni_stc_writew(dev, ack, NISTC_INTA_ACK_REG);
}
static void handle_a_interrupt(struct comedi_device *dev, unsigned short status,
#endif
/* test for all uncommon interrupt events at the same time */
- if (status & (AI_Overrun_St | AI_Overflow_St | AI_SC_TC_Error_St |
- AI_SC_TC_St | AI_START1_St)) {
+ if (status & (NISTC_AI_STATUS1_ERR |
+ NISTC_AI_STATUS1_SC_TC | NISTC_AI_STATUS1_START1)) {
if (status == 0xffff) {
dev_err(dev->class_dev, "Card removed?\n");
/* we probably aren't even running a command now,
}
return;
}
- if (status & (AI_Overrun_St | AI_Overflow_St |
- AI_SC_TC_Error_St)) {
+ if (status & NISTC_AI_STATUS1_ERR) {
dev_err(dev->class_dev, "ai error a_status=%04x\n",
status);
shutdown_ai_command(dev);
s->async->events |= COMEDI_CB_ERROR;
- if (status & (AI_Overrun_St | AI_Overflow_St))
+ if (status & NISTC_AI_STATUS1_OVER)
s->async->events |= COMEDI_CB_OVERFLOW;
comedi_handle_events(dev, s);
return;
}
- if (status & AI_SC_TC_St) {
+ if (status & NISTC_AI_STATUS1_SC_TC) {
if (cmd->stop_src == TRIG_COUNT)
shutdown_ai_command(dev);
}
}
#ifndef PCIDMA
- if (status & AI_FIFO_Half_Full_St) {
+ if (status & NISTC_AI_STATUS1_FIFO_HF) {
int i;
static const int timeout = 10;
/* pcmcia cards (at least 6036) seem to stop producing interrupts if we
*fail to get the fifo less than half full, so loop to be sure.*/
for (i = 0; i < timeout; ++i) {
ni_handle_fifo_half_full(dev);
- if ((ni_stc_readw(dev, AI_Status_1_Register) &
- AI_FIFO_Half_Full_St) == 0)
+ if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
+ NISTC_AI_STATUS1_FIFO_HF) == 0)
break;
}
}
#endif /* !PCIDMA */
- if ((status & AI_STOP_St))
+ if (status & NISTC_AI_STATUS1_STOP)
ni_handle_eos(dev, s);
comedi_handle_events(dev, s);
{
unsigned short ack = 0;
- if (b_status & AO_BC_TC_St)
- ack |= AO_BC_TC_Interrupt_Ack;
- if (b_status & AO_Overrun_St)
- ack |= AO_Error_Interrupt_Ack;
- if (b_status & AO_START_St)
- ack |= AO_START_Interrupt_Ack;
- if (b_status & AO_START1_St)
- ack |= AO_START1_Interrupt_Ack;
- if (b_status & AO_UC_TC_St)
- ack |= AO_UC_TC_Interrupt_Ack;
- if (b_status & AO_UI2_TC_St)
- ack |= AO_UI2_TC_Interrupt_Ack;
- if (b_status & AO_UPDATE_St)
- ack |= AO_UPDATE_Interrupt_Ack;
+ if (b_status & NISTC_AO_STATUS1_BC_TC)
+ ack |= NISTC_INTB_ACK_AO_BC_TC;
+ if (b_status & NISTC_AO_STATUS1_OVERRUN)
+ ack |= NISTC_INTB_ACK_AO_ERR;
+ if (b_status & NISTC_AO_STATUS1_START)
+ ack |= NISTC_INTB_ACK_AO_START;
+ if (b_status & NISTC_AO_STATUS1_START1)
+ ack |= NISTC_INTB_ACK_AO_START1;
+ if (b_status & NISTC_AO_STATUS1_UC_TC)
+ ack |= NISTC_INTB_ACK_AO_UC_TC;
+ if (b_status & NISTC_AO_STATUS1_UI2_TC)
+ ack |= NISTC_INTB_ACK_AO_UI2_TC;
+ if (b_status & NISTC_AO_STATUS1_UPDATE)
+ ack |= NISTC_INTB_ACK_AO_UPDATE;
if (ack)
- ni_stc_writew(dev, ack, Interrupt_B_Ack_Register);
+ ni_stc_writew(dev, ack, NISTC_INTB_ACK_REG);
}
static void handle_b_interrupt(struct comedi_device *dev,
if (b_status == 0xffff)
return;
- if (b_status & AO_Overrun_St) {
+ if (b_status & NISTC_AO_STATUS1_OVERRUN) {
dev_err(dev->class_dev,
"AO FIFO underrun status=0x%04x status2=0x%04x\n",
- b_status, ni_stc_readw(dev, AO_Status_2_Register));
+ b_status, ni_stc_readw(dev, NISTC_AO_STATUS2_REG));
s->async->events |= COMEDI_CB_OVERFLOW;
}
- if (b_status & AO_BC_TC_St)
+ if (b_status & NISTC_AO_STATUS1_BC_TC)
s->async->events |= COMEDI_CB_EOA;
#ifndef PCIDMA
- if (b_status & AO_FIFO_Request_St) {
+ if (b_status & NISTC_AO_STATUS1_FIFO_REQ) {
int ret;
ret = ni_ao_fifo_half_empty(dev, s);
if (!ret) {
dev_err(dev->class_dev, "AO buffer underrun\n");
- ni_set_bits(dev, Interrupt_B_Enable_Register,
- AO_FIFO_Interrupt_Enable |
- AO_Error_Interrupt_Enable, 0);
+ ni_set_bits(dev, NISTC_INTB_ENA_REG,
+ NISTC_INTB_ENA_AO_FIFO |
+ NISTC_INTB_ENA_AO_ERR, 0);
s->async->events |= COMEDI_CB_OVERFLOW;
}
}
static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s)
{
struct ni_private *devpriv = dev->private;
+ unsigned ai_personal;
+ unsigned ai_out_ctrl;
ni_release_ai_mite_channel(dev);
/* ai configuration */
- ni_stc_writew(dev, AI_Configuration_Start | AI_Reset,
- Joint_Reset_Register);
+ ni_stc_writew(dev, NISTC_RESET_AI_CFG_START | NISTC_RESET_AI,
+ NISTC_RESET_REG);
- ni_set_bits(dev, Interrupt_A_Enable_Register,
- AI_SC_TC_Interrupt_Enable | AI_START1_Interrupt_Enable |
- AI_START2_Interrupt_Enable | AI_START_Interrupt_Enable |
- AI_STOP_Interrupt_Enable | AI_Error_Interrupt_Enable |
- AI_FIFO_Interrupt_Enable, 0);
+ ni_set_bits(dev, NISTC_INTA_ENA_REG, NISTC_INTA_ENA_AI_MASK, 0);
ni_clear_ai_fifo(dev);
if (!devpriv->is_6143)
- ni_writeb(dev, 0, Misc_Command);
-
- ni_stc_writew(dev, AI_Disarm, AI_Command_1_Register); /* reset pulses */
- ni_stc_writew(dev, AI_Start_Stop | AI_Mode_1_Reserved
- /*| AI_Trigger_Once */,
- AI_Mode_1_Register);
- ni_stc_writew(dev, 0x0000, AI_Mode_2_Register);
+ ni_writeb(dev, NI_E_MISC_CMD_EXT_ATRIG, NI_E_MISC_CMD_REG);
+
+ ni_stc_writew(dev, NISTC_AI_CMD1_DISARM, NISTC_AI_CMD1_REG);
+ ni_stc_writew(dev, NISTC_AI_MODE1_START_STOP |
+ NISTC_AI_MODE1_RSVD
+ /*| NISTC_AI_MODE1_TRIGGER_ONCE */,
+ NISTC_AI_MODE1_REG);
+ ni_stc_writew(dev, 0, NISTC_AI_MODE2_REG);
/* generate FIFO interrupts on non-empty */
- ni_stc_writew(dev, (0 << 6) | 0x0000, AI_Mode_3_Register);
+ ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE,
+ NISTC_AI_MODE3_REG);
+
+ ai_personal = NISTC_AI_PERSONAL_SHIFTIN_PW |
+ NISTC_AI_PERSONAL_SOC_POLARITY |
+ NISTC_AI_PERSONAL_LOCALMUX_CLK_PW;
+ ai_out_ctrl = NISTC_AI_OUT_CTRL_SCAN_IN_PROG_SEL(3) |
+ NISTC_AI_OUT_CTRL_EXTMUX_CLK_SEL(0) |
+ NISTC_AI_OUT_CTRL_LOCALMUX_CLK_SEL(2) |
+ NISTC_AI_OUT_CTRL_SC_TC_SEL(3);
if (devpriv->is_611x) {
- ni_stc_writew(dev,
- AI_SHIFTIN_Pulse_Width |
- AI_SOC_Polarity |
- AI_LOCALMUX_CLK_Pulse_Width,
- AI_Personal_Register);
- ni_stc_writew(dev,
- AI_SCAN_IN_PROG_Output_Select(3) |
- AI_EXTMUX_CLK_Output_Select(0) |
- AI_LOCALMUX_CLK_Output_Select(2) |
- AI_SC_TC_Output_Select(3) |
- AI_CONVERT_Output_Select
- (AI_CONVERT_Output_Enable_High),
- AI_Output_Control_Register);
+ ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH;
} else if (devpriv->is_6143) {
- ni_stc_writew(dev, AI_SHIFTIN_Pulse_Width |
- AI_SOC_Polarity |
- AI_LOCALMUX_CLK_Pulse_Width,
- AI_Personal_Register);
- ni_stc_writew(dev,
- AI_SCAN_IN_PROG_Output_Select(3) |
- AI_EXTMUX_CLK_Output_Select(0) |
- AI_LOCALMUX_CLK_Output_Select(2) |
- AI_SC_TC_Output_Select(3) |
- AI_CONVERT_Output_Select
- (AI_CONVERT_Output_Enable_Low),
- AI_Output_Control_Register);
+ ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW;
} else {
- unsigned ai_output_control_bits;
-
- ni_stc_writew(dev,
- AI_SHIFTIN_Pulse_Width |
- AI_SOC_Polarity |
- AI_CONVERT_Pulse_Width |
- AI_LOCALMUX_CLK_Pulse_Width,
- AI_Personal_Register);
- ai_output_control_bits =
- AI_SCAN_IN_PROG_Output_Select(3) |
- AI_EXTMUX_CLK_Output_Select(0) |
- AI_LOCALMUX_CLK_Output_Select(2) |
- AI_SC_TC_Output_Select(3);
+ ai_personal |= NISTC_AI_PERSONAL_CONVERT_PW;
if (devpriv->is_622x)
- ai_output_control_bits |=
- AI_CONVERT_Output_Select
- (AI_CONVERT_Output_Enable_High);
+ ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH;
else
- ai_output_control_bits |=
- AI_CONVERT_Output_Select
- (AI_CONVERT_Output_Enable_Low);
- ni_stc_writew(dev, ai_output_control_bits,
- AI_Output_Control_Register);
+ ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW;
}
+ ni_stc_writew(dev, ai_personal, NISTC_AI_PERSONAL_REG);
+ ni_stc_writew(dev, ai_out_ctrl, NISTC_AI_OUT_CTRL_REG);
+
/* the following registers should not be changed, because there
* are no backup registers in devpriv. If you want to change
* any of these, add a backup register and other appropriate code:
- * AI_Mode_1_Register
- * AI_Mode_3_Register
- * AI_Personal_Register
- * AI_Output_Control_Register
+ * NISTC_AI_MODE1_REG
+ * NISTC_AI_MODE3_REG
+ * NISTC_AI_PERSONAL_REG
+ * NISTC_AI_OUT_CTRL_REG
*/
- ni_stc_writew(dev,
- AI_SC_TC_Error_Confirm |
- AI_START_Interrupt_Ack |
- AI_START2_Interrupt_Ack |
- AI_START1_Interrupt_Ack |
- AI_SC_TC_Interrupt_Ack |
- AI_Error_Interrupt_Ack |
- AI_STOP_Interrupt_Ack,
- Interrupt_A_Ack_Register); /* clear interrupts */
-
- ni_stc_writew(dev, AI_Configuration_End, Joint_Reset_Register);
+
+ /* clear interrupts */
+ ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG);
+
+ ni_stc_writew(dev, NISTC_RESET_AI_CFG_END, NISTC_RESET_REG);
return 0;
}
{
int i;
- ni_stc_writew(dev, AI_CONVERT_Pulse, AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, NISTC_AI_CMD1_REG);
for (i = 0; i < NI_TIMEOUT; ++i) {
- if (!(ni_stc_readw(dev, AI_Status_1_Register) &
- AI_FIFO_Empty_St)) {
- ni_stc_writew(dev, 1, ADC_FIFO_Clear);
+ if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
+ NISTC_AI_STATUS1_FIFO_E)) {
+ ni_stc_writew(dev, 1, NISTC_ADC_FIFO_CLR_REG);
return;
}
udelay(1);
unsigned int dither;
unsigned range_code;
- ni_stc_writew(dev, 1, Configuration_Memory_Clear);
+ ni_stc_writew(dev, 1, NISTC_CFG_MEM_CLR_REG);
if ((list[0] & CR_ALT_SOURCE)) {
unsigned bypass_bits;
range = CR_RANGE(list[0]);
range_code = ni_gainlkup[board->gainlkup][range];
dither = (list[0] & CR_ALT_FILTER) != 0;
- bypass_bits = MSeries_AI_Bypass_Config_FIFO_Bit;
- bypass_bits |= chan;
- bypass_bits |=
- (devpriv->ai_calib_source) &
- (MSeries_AI_Bypass_Cal_Sel_Pos_Mask |
- MSeries_AI_Bypass_Cal_Sel_Neg_Mask |
- MSeries_AI_Bypass_Mode_Mux_Mask |
- MSeries_AO_Bypass_AO_Cal_Sel_Mask);
- bypass_bits |= MSeries_AI_Bypass_Gain_Bits(range_code);
+ bypass_bits = NI_M_CFG_BYPASS_FIFO |
+ NI_M_CFG_BYPASS_AI_CHAN(chan) |
+ NI_M_CFG_BYPASS_AI_GAIN(range_code) |
+ devpriv->ai_calib_source;
if (dither)
- bypass_bits |= MSeries_AI_Bypass_Dither_Bit;
+ bypass_bits |= NI_M_CFG_BYPASS_AI_DITHER;
/* don't use 2's complement encoding */
- bypass_bits |= MSeries_AI_Bypass_Polarity_Bit;
- ni_writel(dev, bypass_bits, M_Offset_AI_Config_FIFO_Bypass);
+ bypass_bits |= NI_M_CFG_BYPASS_AI_POLARITY;
+ ni_writel(dev, bypass_bits, NI_M_CFG_BYPASS_FIFO_REG);
} else {
- ni_writel(dev, 0, M_Offset_AI_Config_FIFO_Bypass);
+ ni_writel(dev, 0, NI_M_CFG_BYPASS_FIFO_REG);
}
for (i = 0; i < n_chan; i++) {
unsigned config_bits = 0;
devpriv->ai_offset[i] = 0;
switch (aref) {
case AREF_DIFF:
- config_bits |=
- MSeries_AI_Config_Channel_Type_Differential_Bits;
+ config_bits |= NI_M_AI_CFG_CHAN_TYPE_DIFF;
break;
case AREF_COMMON:
- config_bits |=
- MSeries_AI_Config_Channel_Type_Common_Ref_Bits;
+ config_bits |= NI_M_AI_CFG_CHAN_TYPE_COMMON;
break;
case AREF_GROUND:
- config_bits |=
- MSeries_AI_Config_Channel_Type_Ground_Ref_Bits;
+ config_bits |= NI_M_AI_CFG_CHAN_TYPE_GROUND;
break;
case AREF_OTHER:
break;
}
- config_bits |= MSeries_AI_Config_Channel_Bits(chan);
- config_bits |=
- MSeries_AI_Config_Bank_Bits(board->reg_type, chan);
- config_bits |= MSeries_AI_Config_Gain_Bits(range_code);
+ config_bits |= NI_M_AI_CFG_CHAN_SEL(chan);
+ config_bits |= NI_M_AI_CFG_BANK_SEL(chan);
+ config_bits |= NI_M_AI_CFG_GAIN(range_code);
if (i == n_chan - 1)
- config_bits |= MSeries_AI_Config_Last_Channel_Bit;
+ config_bits |= NI_M_AI_CFG_LAST_CHAN;
if (dither)
- config_bits |= MSeries_AI_Config_Dither_Bit;
+ config_bits |= NI_M_AI_CFG_DITHER;
/* don't use 2's complement encoding */
- config_bits |= MSeries_AI_Config_Polarity_Bit;
- ni_writew(dev, config_bits, M_Offset_AI_Config_FIFO_Data);
+ config_bits |= NI_M_AI_CFG_POLARITY;
+ ni_writew(dev, config_bits, NI_M_AI_CFG_FIFO_DATA_REG);
}
ni_prime_channelgain_list(dev);
}
devpriv->changain_state = 0;
}
- ni_stc_writew(dev, 1, Configuration_Memory_Clear);
+ ni_stc_writew(dev, 1, NISTC_CFG_MEM_CLR_REG);
/* Set up Calibration mode if required */
if (devpriv->is_6143) {
&& !devpriv->ai_calib_source_enabled) {
/* Strobe Relay enable bit */
ni_writew(dev, devpriv->ai_calib_source |
- Calibration_Channel_6143_RelayOn,
- Calibration_Channel_6143);
+ NI6143_CALIB_CHAN_RELAY_ON,
+ NI6143_CALIB_CHAN_REG);
ni_writew(dev, devpriv->ai_calib_source,
- Calibration_Channel_6143);
+ NI6143_CALIB_CHAN_REG);
devpriv->ai_calib_source_enabled = 1;
msleep_interruptible(100); /* Allow relays to change */
} else if (!(list[0] & CR_ALT_SOURCE)
&& devpriv->ai_calib_source_enabled) {
/* Strobe Relay disable bit */
ni_writew(dev, devpriv->ai_calib_source |
- Calibration_Channel_6143_RelayOff,
- Calibration_Channel_6143);
+ NI6143_CALIB_CHAN_RELAY_OFF,
+ NI6143_CALIB_CHAN_REG);
ni_writew(dev, devpriv->ai_calib_source,
- Calibration_Channel_6143);
+ NI6143_CALIB_CHAN_REG);
devpriv->ai_calib_source_enabled = 0;
msleep_interruptible(100); /* Allow relays to change */
}
if ((list[i] & CR_ALT_SOURCE)) {
if (devpriv->is_611x)
ni_writew(dev, CR_CHAN(list[i]) & 0x0003,
- Calibration_Channel_Select_611x);
+ NI611X_CALIB_CHAN_SEL_REG);
} else {
if (devpriv->is_611x)
aref = AREF_DIFF;
aref = AREF_OTHER;
switch (aref) {
case AREF_DIFF:
- hi |= AI_DIFFERENTIAL;
+ hi |= NI_E_AI_CFG_HI_TYPE_DIFF;
break;
case AREF_COMMON:
- hi |= AI_COMMON;
+ hi |= NI_E_AI_CFG_HI_TYPE_COMMON;
break;
case AREF_GROUND:
- hi |= AI_GROUND;
+ hi |= NI_E_AI_CFG_HI_TYPE_GROUND;
break;
case AREF_OTHER:
break;
}
}
- hi |= AI_CONFIG_CHANNEL(chan);
+ hi |= NI_E_AI_CFG_HI_CHAN(chan);
- ni_writew(dev, hi, Configuration_Memory_High);
+ ni_writew(dev, hi, NI_E_AI_CFG_HI_REG);
if (!devpriv->is_6143) {
- lo = range;
+ lo = NI_E_AI_CFG_LO_GAIN(range);
+
if (i == n_chan - 1)
- lo |= AI_LAST_CHANNEL;
+ lo |= NI_E_AI_CFG_LO_LAST_CHAN;
if (dither)
- lo |= AI_DITHER;
+ lo |= NI_E_AI_CFG_LO_DITHER;
- ni_writew(dev, lo, Configuration_Memory_Low);
+ ni_writew(dev, lo, NI_E_AI_CFG_LO_REG);
}
}
signbits = devpriv->ai_offset[0];
if (devpriv->is_611x) {
for (n = 0; n < num_adc_stages_611x; n++) {
- ni_stc_writew(dev, AI_CONVERT_Pulse,
- AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
+ NISTC_AI_CMD1_REG);
udelay(1);
}
for (n = 0; n < insn->n; n++) {
- ni_stc_writew(dev, AI_CONVERT_Pulse,
- AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
+ NISTC_AI_CMD1_REG);
/* The 611x has screwy 32-bit FIFOs. */
d = 0;
for (i = 0; i < NI_TIMEOUT; i++) {
- if (ni_readb(dev, XXX_Status) & 0x80) {
- d = ni_readl(dev, ADC_FIFO_Data_611x);
+ if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) {
+ d = ni_readl(dev,
+ NI611X_AI_FIFO_DATA_REG);
d >>= 16;
d &= 0xffff;
break;
}
- if (!(ni_stc_readw(dev, AI_Status_1_Register) &
- AI_FIFO_Empty_St)) {
- d = ni_readl(dev, ADC_FIFO_Data_611x);
+ if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
+ NISTC_AI_STATUS1_FIFO_E)) {
+ d = ni_readl(dev,
+ NI611X_AI_FIFO_DATA_REG);
d &= 0xffff;
break;
}
}
} else if (devpriv->is_6143) {
for (n = 0; n < insn->n; n++) {
- ni_stc_writew(dev, AI_CONVERT_Pulse,
- AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
+ NISTC_AI_CMD1_REG);
/* The 6143 has 32-bit FIFOs. You need to strobe a bit to move a single 16bit stranded sample into the FIFO */
dl = 0;
for (i = 0; i < NI_TIMEOUT; i++) {
- if (ni_readl(dev, AIFIFO_Status_6143) & 0x01) {
+ if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) &
+ 0x01) {
/* Get stranded sample into FIFO */
ni_writel(dev, 0x01,
- AIFIFO_Control_6143);
- dl = ni_readl(dev, AIFIFO_Data_6143);
+ NI6143_AI_FIFO_CTRL_REG);
+ dl = ni_readl(dev,
+ NI6143_AI_FIFO_DATA_REG);
break;
}
}
}
} else {
for (n = 0; n < insn->n; n++) {
- ni_stc_writew(dev, AI_CONVERT_Pulse,
- AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE,
+ NISTC_AI_CMD1_REG);
for (i = 0; i < NI_TIMEOUT; i++) {
- if (!(ni_stc_readw(dev, AI_Status_1_Register) &
- AI_FIFO_Empty_St))
+ if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) &
+ NISTC_AI_STATUS1_FIFO_E))
break;
}
if (i == NI_TIMEOUT) {
return -ETIME;
}
if (devpriv->is_m_series) {
- dl = ni_readl(dev, M_Offset_AI_FIFO_Data);
+ dl = ni_readl(dev, NI_M_AI_FIFO_DATA_REG);
dl &= mask;
data[n] = dl;
} else {
- d = ni_readw(dev, ADC_FIFO_Data_Register);
+ d = ni_readw(dev, NI_E_AI_FIFO_DATA_REG);
d += signbits; /* subtle: needs to be short addition */
data[n] = d;
}
if (trig_num != cmd->start_arg)
return -EINVAL;
- ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2,
- AI_Command_2_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE | devpriv->ai_cmd2,
+ NISTC_AI_CMD2_REG);
s->async->inttrig = NULL;
return 1;
int start_stop_select = 0;
unsigned int stop_count;
int interrupt_a_enable = 0;
+ unsigned ai_trig;
if (dev->irq == 0) {
dev_err(dev->class_dev, "cannot run command without an irq\n");
ni_load_channelgain_list(dev, s, cmd->chanlist_len, cmd->chanlist);
/* start configuration */
- ni_stc_writew(dev, AI_Configuration_Start, Joint_Reset_Register);
+ ni_stc_writew(dev, NISTC_RESET_AI_CFG_START, NISTC_RESET_REG);
/* disable analog triggering for now, since it
* interferes with the use of pfi0 */
- devpriv->an_trig_etc_reg &= ~Analog_Trigger_Enable;
- ni_stc_writew(dev, devpriv->an_trig_etc_reg,
- Analog_Trigger_Etc_Register);
+ devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_ENA;
+ ni_stc_writew(dev, devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG);
+ ai_trig = NISTC_AI_TRIG_START2_SEL(0) | NISTC_AI_TRIG_START1_SYNC;
switch (cmd->start_src) {
case TRIG_INT:
case TRIG_NOW:
- ni_stc_writew(dev,
- AI_START2_Select(0) |
- AI_START1_Sync | AI_START1_Edge |
- AI_START1_Select(0),
- AI_Trigger_Select_Register);
+ ai_trig |= NISTC_AI_TRIG_START1_EDGE |
+ NISTC_AI_TRIG_START1_SEL(0);
break;
case TRIG_EXT:
- {
- int chan = CR_CHAN(cmd->start_arg);
- unsigned int bits = AI_START2_Select(0) |
- AI_START1_Sync | AI_START1_Select(chan + 1);
-
- if (cmd->start_arg & CR_INVERT)
- bits |= AI_START1_Polarity;
- if (cmd->start_arg & CR_EDGE)
- bits |= AI_START1_Edge;
- ni_stc_writew(dev, bits, AI_Trigger_Select_Register);
- break;
- }
+ ai_trig |= NISTC_AI_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) +
+ 1);
+
+ if (cmd->start_arg & CR_INVERT)
+ ai_trig |= NISTC_AI_TRIG_START1_POLARITY;
+ if (cmd->start_arg & CR_EDGE)
+ ai_trig |= NISTC_AI_TRIG_START1_EDGE;
+ break;
}
+ ni_stc_writew(dev, ai_trig, NISTC_AI_TRIG_SEL_REG);
- mode2 &= ~AI_Pre_Trigger;
- mode2 &= ~AI_SC_Initial_Load_Source;
- mode2 &= ~AI_SC_Reload_Mode;
- ni_stc_writew(dev, mode2, AI_Mode_2_Register);
+ mode2 &= ~NISTC_AI_MODE2_PRE_TRIGGER;
+ mode2 &= ~NISTC_AI_MODE2_SC_INIT_LOAD_SRC;
+ mode2 &= ~NISTC_AI_MODE2_SC_RELOAD_MODE;
+ ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG);
if (cmd->chanlist_len == 1 || devpriv->is_611x || devpriv->is_6143) {
- start_stop_select |= AI_STOP_Polarity;
- start_stop_select |= AI_STOP_Select(31); /* logic low */
- start_stop_select |= AI_STOP_Sync;
+ /* logic low */
+ start_stop_select |= NISTC_AI_STOP_POLARITY |
+ NISTC_AI_STOP_SEL(31) |
+ NISTC_AI_STOP_SYNC;
} else {
- start_stop_select |= AI_STOP_Select(19); /* ai configuration memory */
+ /* ai configuration memory */
+ start_stop_select |= NISTC_AI_STOP_SEL(19);
}
- ni_stc_writew(dev, start_stop_select, AI_START_STOP_Select_Register);
+ ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG);
devpriv->ai_cmd2 = 0;
switch (cmd->stop_src) {
stop_count += num_adc_stages_611x;
}
/* stage number of scans */
- ni_stc_writel(dev, stop_count, AI_SC_Load_A_Registers);
+ ni_stc_writel(dev, stop_count, NISTC_AI_SC_LOADA_REG);
- mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Trigger_Once;
- ni_stc_writew(dev, mode1, AI_Mode_1_Register);
+ mode1 |= NISTC_AI_MODE1_START_STOP |
+ NISTC_AI_MODE1_RSVD |
+ NISTC_AI_MODE1_TRIGGER_ONCE;
+ ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG);
/* load SC (Scan Count) */
- ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_SC_LOAD, NISTC_AI_CMD1_REG);
if (stop_count == 0) {
- devpriv->ai_cmd2 |= AI_End_On_End_Of_Scan;
- interrupt_a_enable |= AI_STOP_Interrupt_Enable;
+ devpriv->ai_cmd2 |= NISTC_AI_CMD2_END_ON_EOS;
+ interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP;
/* this is required to get the last sample for chanlist_len > 1, not sure why */
if (cmd->chanlist_len > 1)
- start_stop_select |=
- AI_STOP_Polarity | AI_STOP_Edge;
+ start_stop_select |= NISTC_AI_STOP_POLARITY |
+ NISTC_AI_STOP_EDGE;
}
break;
case TRIG_NONE:
/* stage number of scans */
- ni_stc_writel(dev, 0, AI_SC_Load_A_Registers);
+ ni_stc_writel(dev, 0, NISTC_AI_SC_LOADA_REG);
- mode1 |= AI_Start_Stop | AI_Mode_1_Reserved | AI_Continuous;
- ni_stc_writew(dev, mode1, AI_Mode_1_Register);
+ mode1 |= NISTC_AI_MODE1_START_STOP |
+ NISTC_AI_MODE1_RSVD |
+ NISTC_AI_MODE1_CONTINUOUS;
+ ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG);
/* load SC (Scan Count) */
- ni_stc_writew(dev, AI_SC_Load, AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_SC_LOAD, NISTC_AI_CMD1_REG);
break;
}
switch (cmd->scan_begin_src) {
case TRIG_TIMER:
/*
- stop bits for non 611x boards
- AI_SI_Special_Trigger_Delay=0
- AI_Pre_Trigger=0
- AI_START_STOP_Select_Register:
- AI_START_Polarity=0 (?) rising edge
- AI_START_Edge=1 edge triggered
- AI_START_Sync=1 (?)
- AI_START_Select=0 SI_TC
- AI_STOP_Polarity=0 rising edge
- AI_STOP_Edge=0 level
- AI_STOP_Sync=1
- AI_STOP_Select=19 external pin (configuration mem)
+ * stop bits for non 611x boards
+ * NISTC_AI_MODE3_SI_TRIG_DELAY=0
+ * NISTC_AI_MODE2_PRE_TRIGGER=0
+ * NISTC_AI_START_STOP_REG:
+ * NISTC_AI_START_POLARITY=0 (?) rising edge
+ * NISTC_AI_START_EDGE=1 edge triggered
+ * NISTC_AI_START_SYNC=1 (?)
+ * NISTC_AI_START_SEL=0 SI_TC
+ * NISTC_AI_STOP_POLARITY=0 rising edge
+ * NISTC_AI_STOP_EDGE=0 level
+ * NISTC_AI_STOP_SYNC=1
+ * NISTC_AI_STOP_SEL=19 external pin (configuration mem)
*/
- start_stop_select |= AI_START_Edge | AI_START_Sync;
- ni_stc_writew(dev, start_stop_select,
- AI_START_STOP_Select_Register);
+ start_stop_select |= NISTC_AI_START_EDGE | NISTC_AI_START_SYNC;
+ ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG);
- mode2 |= AI_SI_Reload_Mode(0);
- /* AI_SI_Initial_Load_Source=A */
- mode2 &= ~AI_SI_Initial_Load_Source;
- /* mode2 |= AI_SC_Reload_Mode; */
- ni_stc_writew(dev, mode2, AI_Mode_2_Register);
+ mode2 &= ~NISTC_AI_MODE2_SI_INIT_LOAD_SRC; /* A */
+ mode2 |= NISTC_AI_MODE2_SI_RELOAD_MODE(0);
+ /* mode2 |= NISTC_AI_MODE2_SC_RELOAD_MODE; */
+ ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG);
/* load SI */
timer = ni_ns_to_timer(dev, cmd->scan_begin_arg,
CMDF_ROUND_NEAREST);
- ni_stc_writel(dev, timer, AI_SI_Load_A_Registers);
- ni_stc_writew(dev, AI_SI_Load, AI_Command_1_Register);
+ ni_stc_writel(dev, timer, NISTC_AI_SI_LOADA_REG);
+ ni_stc_writew(dev, NISTC_AI_CMD1_SI_LOAD, NISTC_AI_CMD1_REG);
break;
case TRIG_EXT:
if (cmd->scan_begin_arg & CR_EDGE)
- start_stop_select |= AI_START_Edge;
- /* AI_START_Polarity==1 is falling edge */
- if (cmd->scan_begin_arg & CR_INVERT)
- start_stop_select |= AI_START_Polarity;
+ start_stop_select |= NISTC_AI_START_EDGE;
+ if (cmd->scan_begin_arg & CR_INVERT) /* falling edge */
+ start_stop_select |= NISTC_AI_START_POLARITY;
if (cmd->scan_begin_src != cmd->convert_src ||
(cmd->scan_begin_arg & ~CR_EDGE) !=
(cmd->convert_arg & ~CR_EDGE))
- start_stop_select |= AI_START_Sync;
+ start_stop_select |= NISTC_AI_START_SYNC;
start_stop_select |=
- AI_START_Select(1 + CR_CHAN(cmd->scan_begin_arg));
- ni_stc_writew(dev, start_stop_select,
- AI_START_STOP_Select_Register);
+ NISTC_AI_START_SEL(1 + CR_CHAN(cmd->scan_begin_arg));
+ ni_stc_writew(dev, start_stop_select, NISTC_AI_START_STOP_REG);
break;
}
timer = ni_ns_to_timer(dev, cmd->convert_arg,
CMDF_ROUND_NEAREST);
/* 0,0 does not work */
- ni_stc_writew(dev, 1, AI_SI2_Load_A_Register);
- ni_stc_writew(dev, timer, AI_SI2_Load_B_Register);
-
- /* AI_SI2_Reload_Mode = alternate */
- /* AI_SI2_Initial_Load_Source = A */
- mode2 &= ~AI_SI2_Initial_Load_Source;
- mode2 |= AI_SI2_Reload_Mode;
- ni_stc_writew(dev, mode2, AI_Mode_2_Register);
+ ni_stc_writew(dev, 1, NISTC_AI_SI2_LOADA_REG);
+ ni_stc_writew(dev, timer, NISTC_AI_SI2_LOADB_REG);
- /* AI_SI2_Load */
- ni_stc_writew(dev, AI_SI2_Load, AI_Command_1_Register);
+ mode2 &= ~NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* A */
+ mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */
+ ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG);
- mode2 |= AI_SI2_Reload_Mode; /* alternate */
- mode2 |= AI_SI2_Initial_Load_Source; /* B */
+ ni_stc_writew(dev, NISTC_AI_CMD1_SI2_LOAD, NISTC_AI_CMD1_REG);
- ni_stc_writew(dev, mode2, AI_Mode_2_Register);
+ mode2 |= NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* B */
+ mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */
+ ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG);
break;
case TRIG_EXT:
- mode1 |= AI_CONVERT_Source_Select(1 + cmd->convert_arg);
+ mode1 |= NISTC_AI_MODE1_CONVERT_SRC(1 + cmd->convert_arg);
if ((cmd->convert_arg & CR_INVERT) == 0)
- mode1 |= AI_CONVERT_Source_Polarity;
- ni_stc_writew(dev, mode1, AI_Mode_1_Register);
+ mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY;
+ ni_stc_writew(dev, mode1, NISTC_AI_MODE1_REG);
- mode2 |= AI_Start_Stop_Gate_Enable | AI_SC_Gate_Enable;
- ni_stc_writew(dev, mode2, AI_Mode_2_Register);
+ mode2 |= NISTC_AI_MODE2_SC_GATE_ENA |
+ NISTC_AI_MODE2_START_STOP_GATE_ENA;
+ ni_stc_writew(dev, mode2, NISTC_AI_MODE2_REG);
break;
}
if (dev->irq) {
/* interrupt on FIFO, errors, SC_TC */
- interrupt_a_enable |= AI_Error_Interrupt_Enable |
- AI_SC_TC_Interrupt_Enable;
+ interrupt_a_enable |= NISTC_INTA_ENA_AI_ERR |
+ NISTC_INTA_ENA_AI_SC_TC;
#ifndef PCIDMA
- interrupt_a_enable |= AI_FIFO_Interrupt_Enable;
+ interrupt_a_enable |= NISTC_INTA_ENA_AI_FIFO;
#endif
- if (cmd->flags & CMDF_WAKE_EOS
- || (devpriv->ai_cmd2 & AI_End_On_End_Of_Scan)) {
+ if ((cmd->flags & CMDF_WAKE_EOS) ||
+ (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS)) {
/* wake on end-of-scan */
devpriv->aimode = AIMODE_SCAN;
} else {
case AIMODE_HALF_FULL:
/*generate FIFO interrupts and DMA requests on half-full */
#ifdef PCIDMA
- ni_stc_writew(dev, AI_FIFO_Mode_HF_to_E,
- AI_Mode_3_Register);
+ ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF_E,
+ NISTC_AI_MODE3_REG);
#else
- ni_stc_writew(dev, AI_FIFO_Mode_HF,
- AI_Mode_3_Register);
+ ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF,
+ NISTC_AI_MODE3_REG);
#endif
break;
case AIMODE_SAMPLE:
/*generate FIFO interrupts on non-empty */
- ni_stc_writew(dev, AI_FIFO_Mode_NE,
- AI_Mode_3_Register);
+ ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE,
+ NISTC_AI_MODE3_REG);
break;
case AIMODE_SCAN:
#ifdef PCIDMA
- ni_stc_writew(dev, AI_FIFO_Mode_NE,
- AI_Mode_3_Register);
+ ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE,
+ NISTC_AI_MODE3_REG);
#else
- ni_stc_writew(dev, AI_FIFO_Mode_HF,
- AI_Mode_3_Register);
+ ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF,
+ NISTC_AI_MODE3_REG);
#endif
- interrupt_a_enable |= AI_STOP_Interrupt_Enable;
+ interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP;
break;
default:
break;
}
/* clear interrupts */
- ni_stc_writew(dev,
- AI_Error_Interrupt_Ack |
- AI_STOP_Interrupt_Ack |
- AI_START_Interrupt_Ack |
- AI_START2_Interrupt_Ack |
- AI_START1_Interrupt_Ack |
- AI_SC_TC_Interrupt_Ack |
- AI_SC_TC_Error_Confirm,
- Interrupt_A_Ack_Register);
-
- ni_set_bits(dev, Interrupt_A_Enable_Register,
- interrupt_a_enable, 1);
+ ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG);
+
+ ni_set_bits(dev, NISTC_INTA_ENA_REG, interrupt_a_enable, 1);
} else {
/* interrupt on nothing */
- ni_set_bits(dev, Interrupt_A_Enable_Register, ~0, 0);
+ ni_set_bits(dev, NISTC_INTA_ENA_REG, ~0, 0);
/* XXX start polling if necessary */
}
/* end configuration */
- ni_stc_writew(dev, AI_Configuration_End, Joint_Reset_Register);
+ ni_stc_writew(dev, NISTC_RESET_AI_CFG_END, NISTC_RESET_REG);
switch (cmd->scan_begin_src) {
case TRIG_TIMER:
- ni_stc_writew(dev,
- AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm,
- AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM |
+ NISTC_AI_CMD1_SI_ARM |
+ NISTC_AI_CMD1_DIV_ARM |
+ NISTC_AI_CMD1_SC_ARM,
+ NISTC_AI_CMD1_REG);
break;
case TRIG_EXT:
- /* XXX AI_SI_Arm? */
- ni_stc_writew(dev,
- AI_SI2_Arm | AI_SI_Arm | AI_DIV_Arm | AI_SC_Arm,
- AI_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM |
+ NISTC_AI_CMD1_SI_ARM | /* XXX ? */
+ NISTC_AI_CMD1_DIV_ARM |
+ NISTC_AI_CMD1_SC_ARM,
+ NISTC_AI_CMD1_REG);
break;
}
#endif
if (cmd->start_src == TRIG_NOW) {
- /* AI_START1_Pulse */
- ni_stc_writew(dev, AI_START1_Pulse | devpriv->ai_cmd2,
- AI_Command_2_Register);
+ ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE |
+ devpriv->ai_cmd2,
+ NISTC_AI_CMD2_REG);
s->async->inttrig = NULL;
} else if (cmd->start_src == TRIG_EXT) {
s->async->inttrig = NULL;
switch (data[0]) {
case INSN_CONFIG_ALT_SOURCE:
if (devpriv->is_m_series) {
- if (data[1] & ~(MSeries_AI_Bypass_Cal_Sel_Pos_Mask |
- MSeries_AI_Bypass_Cal_Sel_Neg_Mask |
- MSeries_AI_Bypass_Mode_Mux_Mask |
- MSeries_AO_Bypass_AO_Cal_Sel_Mask)) {
+ if (data[1] & ~NI_M_CFG_BYPASS_AI_CAL_MASK)
return -EINVAL;
- }
devpriv->ai_calib_source = data[1];
} else if (devpriv->is_6143) {
unsigned int calib_source;
calib_source = data[1] & 0xf;
devpriv->ai_calib_source = calib_source;
- ni_writew(dev, calib_source, Calibration_Channel_6143);
+ ni_writew(dev, calib_source, NI6143_CALIB_CHAN_REG);
} else {
unsigned int calib_source;
unsigned int calib_source_adjust;
devpriv->ai_calib_source = calib_source;
if (devpriv->is_611x) {
ni_writeb(dev, calib_source_adjust,
- Cal_Gain_Select_611x);
+ NI611X_CAL_GAIN_SEL_REG);
}
}
return 2;
if (timed) {
for (i = 0; i < s->n_chan; ++i) {
- devpriv->ao_conf[i] &= ~MSeries_AO_Update_Timed_Bit;
+ devpriv->ao_conf[i] &= ~NI_M_AO_CFG_BANK_UPDATE_TIMED;
ni_writeb(dev, devpriv->ao_conf[i],
- M_Offset_AO_Config_Bank(i));
- ni_writeb(dev, 0xf, M_Offset_AO_Waveform_Order(i));
+ NI_M_AO_CFG_BANK_REG(i));
+ ni_writeb(dev, 0xf, NI_M_AO_WAVEFORM_ORDER_REG(i));
}
}
for (i = 0; i < n_chans; i++) {
conf = 0;
switch (krange->max - krange->min) {
case 20000000:
- conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits;
- ni_writeb(dev, 0,
- M_Offset_AO_Reference_Attenuation(chan));
+ conf |= NI_M_AO_CFG_BANK_REF_INT_10V;
+ ni_writeb(dev, 0, NI_M_AO_REF_ATTENUATION_REG(chan));
break;
case 10000000:
- conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits;
- ni_writeb(dev, 0,
- M_Offset_AO_Reference_Attenuation(chan));
+ conf |= NI_M_AO_CFG_BANK_REF_INT_5V;
+ ni_writeb(dev, 0, NI_M_AO_REF_ATTENUATION_REG(chan));
break;
case 4000000:
- conf |= MSeries_AO_DAC_Reference_10V_Internal_Bits;
- ni_writeb(dev, MSeries_Attenuate_x5_Bit,
- M_Offset_AO_Reference_Attenuation(chan));
+ conf |= NI_M_AO_CFG_BANK_REF_INT_10V;
+ ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5,
+ NI_M_AO_REF_ATTENUATION_REG(chan));
break;
case 2000000:
- conf |= MSeries_AO_DAC_Reference_5V_Internal_Bits;
- ni_writeb(dev, MSeries_Attenuate_x5_Bit,
- M_Offset_AO_Reference_Attenuation(chan));
+ conf |= NI_M_AO_CFG_BANK_REF_INT_5V;
+ ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5,
+ NI_M_AO_REF_ATTENUATION_REG(chan));
break;
default:
dev_err(dev->class_dev,
}
switch (krange->max + krange->min) {
case 0:
- conf |= MSeries_AO_DAC_Offset_0V_Bits;
+ conf |= NI_M_AO_CFG_BANK_OFFSET_0V;
break;
case 10000000:
- conf |= MSeries_AO_DAC_Offset_5V_Bits;
+ conf |= NI_M_AO_CFG_BANK_OFFSET_5V;
break;
default:
dev_err(dev->class_dev,
break;
}
if (timed)
- conf |= MSeries_AO_Update_Timed_Bit;
- ni_writeb(dev, conf, M_Offset_AO_Config_Bank(chan));
+ conf |= NI_M_AO_CFG_BANK_UPDATE_TIMED;
+ ni_writeb(dev, conf, NI_M_AO_CFG_BANK_REG(chan));
devpriv->ao_conf[chan] = conf;
- ni_writeb(dev, i, M_Offset_AO_Waveform_Order(chan));
+ ni_writeb(dev, i, NI_M_AO_WAVEFORM_ORDER_REG(chan));
}
return invert;
}
for (i = 0; i < n_chans; i++) {
chan = CR_CHAN(chanspec[i]);
range = CR_RANGE(chanspec[i]);
- conf = AO_Channel(chan);
+ conf = NI_E_AO_DACSEL(chan);
if (comedi_range_is_bipolar(s, range)) {
- conf |= AO_Bipolar;
+ conf |= NI_E_AO_CFG_BIP;
invert = (s->maxdata + 1) >> 1;
} else {
invert = 0;
}
if (comedi_range_is_external(s, range))
- conf |= AO_Ext_Ref;
+ conf |= NI_E_AO_EXT_REF;
/* not all boards can deglitch, but this shouldn't hurt */
if (chanspec[i] & CR_DEGLITCH)
- conf |= AO_Deglitch;
+ conf |= NI_E_AO_DEGLITCH;
/* analog reference */
/* AREF_OTHER connects AO ground to AI ground, i think */
- conf |= (CR_AREF(chanspec[i]) ==
- AREF_OTHER) ? AO_Ground_Ref : 0;
+ if (CR_AREF(chanspec[i]) == AREF_OTHER)
+ conf |= NI_E_AO_GROUND_REF;
- ni_writew(dev, conf, AO_Configuration);
+ ni_writew(dev, conf, NI_E_AO_CFG_REG);
devpriv->ao_conf[chan] = conf;
}
return invert;
int i;
if (devpriv->is_6xxx) {
- ni_ao_win_outw(dev, 1 << chan, AO_Immediate_671x);
+ ni_ao_win_outw(dev, 1 << chan, NI671X_AO_IMMEDIATE_REG);
- reg = DACx_Direct_Data_671x(chan);
+ reg = NI671X_DAC_DIRECT_DATA_REG(chan);
} else if (devpriv->is_m_series) {
- reg = M_Offset_DAC_Direct_Data(chan);
+ reg = NI_M_DAC_DIRECT_DATA_REG(chan);
} else {
- reg = (chan) ? DAC1_Direct_Data : DAC0_Direct_Data;
+ reg = NI_E_DAC_DIRECT_DATA_REG(chan);
}
ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0);
multiple times) */
s->async->inttrig = NULL;
- ni_set_bits(dev, Interrupt_B_Enable_Register,
- AO_FIFO_Interrupt_Enable | AO_Error_Interrupt_Enable, 0);
- interrupt_b_bits = AO_Error_Interrupt_Enable;
+ ni_set_bits(dev, NISTC_INTB_ENA_REG,
+ NISTC_INTB_ENA_AO_FIFO | NISTC_INTB_ENA_AO_ERR, 0);
+ interrupt_b_bits = NISTC_INTB_ENA_AO_ERR;
#ifdef PCIDMA
- ni_stc_writew(dev, 1, DAC_FIFO_Clear);
+ ni_stc_writew(dev, 1, NISTC_DAC_FIFO_CLR_REG);
if (devpriv->is_6xxx)
- ni_ao_win_outl(dev, 0x6, AO_FIFO_Offset_Load_611x);
+ ni_ao_win_outl(dev, 0x6, NI611X_AO_FIFO_OFFSET_LOAD_REG);
ret = ni_ao_setup_MITE_dma(dev);
if (ret)
return ret;
if (ret == 0)
return -EPIPE;
- interrupt_b_bits |= AO_FIFO_Interrupt_Enable;
+ interrupt_b_bits |= NISTC_INTB_ENA_AO_FIFO;
#endif
- ni_stc_writew(dev, devpriv->ao_mode3 | AO_Not_An_UPDATE,
- AO_Mode_3_Register);
- ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
+ ni_stc_writew(dev, devpriv->ao_mode3 | NISTC_AO_MODE3_NOT_AN_UPDATE,
+ NISTC_AO_MODE3_REG);
+ ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
/* wait for DACs to be loaded */
for (i = 0; i < timeout; i++) {
udelay(1);
- if ((ni_stc_readw(dev, Joint_Status_2_Register) &
- AO_TMRDACWRs_In_Progress_St) == 0)
+ if ((ni_stc_readw(dev, NISTC_STATUS2_REG) &
+ NISTC_STATUS2_AO_TMRDACWRS_IN_PROGRESS) == 0)
break;
}
if (i == timeout) {
* stc manual says we are need to clear error interrupt after
* AO_TMRDACWRs_In_Progress_St clears
*/
- ni_stc_writew(dev, AO_Error_Interrupt_Ack, Interrupt_B_Ack_Register);
+ ni_stc_writew(dev, NISTC_INTB_ACK_AO_ERR, NISTC_INTB_ACK_REG);
- ni_set_bits(dev, Interrupt_B_Enable_Register, interrupt_b_bits, 1);
+ ni_set_bits(dev, NISTC_INTB_ENA_REG, interrupt_b_bits, 1);
- ni_stc_writew(dev, devpriv->ao_cmd1 |
- AO_UI_Arm | AO_UC_Arm | AO_BC_Arm |
- AO_DAC1_Update_Mode | AO_DAC0_Update_Mode,
- AO_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM |
+ NISTC_AO_CMD1_UC_ARM |
+ NISTC_AO_CMD1_BC_ARM |
+ NISTC_AO_CMD1_DAC1_UPDATE_MODE |
+ NISTC_AO_CMD1_DAC0_UPDATE_MODE |
+ devpriv->ao_cmd1,
+ NISTC_AO_CMD1_REG);
- ni_stc_writew(dev, devpriv->ao_cmd2 | AO_START1_Pulse,
- AO_Command_2_Register);
+ ni_stc_writew(dev, NISTC_AO_CMD2_START1_PULSE | devpriv->ao_cmd2,
+ NISTC_AO_CMD2_REG);
return 0;
}
int bits;
int i;
unsigned trigvar;
+ unsigned val;
if (dev->irq == 0) {
dev_err(dev->class_dev, "cannot run command without an irq\n");
return -EIO;
}
- ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
- ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG);
if (devpriv->is_6xxx) {
- ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x);
+ ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG,
+ NI611X_AO_MISC_REG);
bits = 0;
for (i = 0; i < cmd->chanlist_len; i++) {
chan = CR_CHAN(cmd->chanlist[i]);
bits |= 1 << chan;
- ni_ao_win_outw(dev, chan, AO_Waveform_Generation_611x);
+ ni_ao_win_outw(dev, chan, NI611X_AO_WAVEFORM_GEN_REG);
}
- ni_ao_win_outw(dev, bits, AO_Timed_611x);
+ ni_ao_win_outw(dev, bits, NI611X_AO_TIMED_REG);
}
ni_ao_config_chanlist(dev, s, cmd->chanlist, cmd->chanlist_len, 1);
if (cmd->stop_src == TRIG_NONE) {
- devpriv->ao_mode1 |= AO_Continuous;
- devpriv->ao_mode1 &= ~AO_Trigger_Once;
+ devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS;
+ devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE;
} else {
- devpriv->ao_mode1 &= ~AO_Continuous;
- devpriv->ao_mode1 |= AO_Trigger_Once;
+ devpriv->ao_mode1 &= ~NISTC_AO_MODE1_CONTINUOUS;
+ devpriv->ao_mode1 |= NISTC_AO_MODE1_TRIGGER_ONCE;
}
- ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
+ ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+
+ val = devpriv->ao_trigger_select;
switch (cmd->start_src) {
case TRIG_INT:
case TRIG_NOW:
- devpriv->ao_trigger_select &=
- ~(AO_START1_Polarity | AO_START1_Select(-1));
- devpriv->ao_trigger_select |= AO_START1_Edge | AO_START1_Sync;
- ni_stc_writew(dev, devpriv->ao_trigger_select,
- AO_Trigger_Select_Register);
+ val &= ~(NISTC_AO_TRIG_START1_POLARITY |
+ NISTC_AO_TRIG_START1_SEL_MASK);
+ val |= NISTC_AO_TRIG_START1_EDGE |
+ NISTC_AO_TRIG_START1_SYNC;
break;
case TRIG_EXT:
- devpriv->ao_trigger_select =
- AO_START1_Select(CR_CHAN(cmd->start_arg) + 1);
- if (cmd->start_arg & CR_INVERT)
- devpriv->ao_trigger_select |= AO_START1_Polarity; /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */
- if (cmd->start_arg & CR_EDGE)
- devpriv->ao_trigger_select |= AO_START1_Edge; /* 0=edge detection disabled, 1=enabled */
+ val = NISTC_AO_TRIG_START1_SEL(CR_CHAN(cmd->start_arg) + 1);
+ if (cmd->start_arg & CR_INVERT) {
+ /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */
+ val |= NISTC_AO_TRIG_START1_POLARITY;
+ }
+ if (cmd->start_arg & CR_EDGE) {
+ /* 0=edge detection disabled, 1=enabled */
+ val |= NISTC_AO_TRIG_START1_EDGE;
+ }
ni_stc_writew(dev, devpriv->ao_trigger_select,
- AO_Trigger_Select_Register);
+ NISTC_AO_TRIG_SEL_REG);
break;
default:
BUG();
break;
}
- devpriv->ao_mode3 &= ~AO_Trigger_Length;
- ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
+ devpriv->ao_trigger_select = val;
+ ni_stc_writew(dev, devpriv->ao_trigger_select, NISTC_AO_TRIG_SEL_REG);
- ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
- devpriv->ao_mode2 &= ~AO_BC_Initial_Load_Source;
- ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+ devpriv->ao_mode3 &= ~NISTC_AO_MODE3_TRIG_LEN;
+ ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
+
+ ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC;
+ ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
if (cmd->stop_src == TRIG_NONE)
- ni_stc_writel(dev, 0xffffff, AO_BC_Load_A_Register);
+ ni_stc_writel(dev, 0xffffff, NISTC_AO_BC_LOADA_REG);
else
- ni_stc_writel(dev, 0, AO_BC_Load_A_Register);
- ni_stc_writew(dev, AO_BC_Load, AO_Command_1_Register);
- devpriv->ao_mode2 &= ~AO_UC_Initial_Load_Source;
- ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+ ni_stc_writel(dev, 0, NISTC_AO_BC_LOADA_REG);
+ ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG);
+ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC;
+ ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
switch (cmd->stop_src) {
case TRIG_COUNT:
if (devpriv->is_m_series) {
/* this is how the NI example code does it for m-series boards, verified correct with 6259 */
ni_stc_writel(dev, cmd->stop_arg - 1,
- AO_UC_Load_A_Register);
- ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
+ NISTC_AO_UC_LOADA_REG);
+ ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD,
+ NISTC_AO_CMD1_REG);
} else {
ni_stc_writel(dev, cmd->stop_arg,
- AO_UC_Load_A_Register);
- ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
+ NISTC_AO_UC_LOADA_REG);
+ ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD,
+ NISTC_AO_CMD1_REG);
ni_stc_writel(dev, cmd->stop_arg - 1,
- AO_UC_Load_A_Register);
+ NISTC_AO_UC_LOADA_REG);
}
break;
case TRIG_NONE:
- ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register);
- ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
- ni_stc_writel(dev, 0xffffff, AO_UC_Load_A_Register);
+ ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG);
+ ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG);
+ ni_stc_writel(dev, 0xffffff, NISTC_AO_UC_LOADA_REG);
break;
default:
- ni_stc_writel(dev, 0, AO_UC_Load_A_Register);
- ni_stc_writew(dev, AO_UC_Load, AO_Command_1_Register);
- ni_stc_writel(dev, cmd->stop_arg, AO_UC_Load_A_Register);
+ ni_stc_writel(dev, 0, NISTC_AO_UC_LOADA_REG);
+ ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, NISTC_AO_CMD1_REG);
+ ni_stc_writel(dev, cmd->stop_arg, NISTC_AO_UC_LOADA_REG);
}
- devpriv->ao_mode1 &=
- ~(AO_UI_Source_Select(0x1f) | AO_UI_Source_Polarity |
- AO_UPDATE_Source_Select(0x1f) | AO_UPDATE_Source_Polarity);
+ devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UPDATE_SRC_MASK |
+ NISTC_AO_MODE1_UI_SRC_MASK |
+ NISTC_AO_MODE1_UPDATE_SRC_POLARITY |
+ NISTC_AO_MODE1_UI_SRC_POLARITY);
switch (cmd->scan_begin_src) {
case TRIG_TIMER:
- devpriv->ao_cmd2 &= ~AO_BC_Gate_Enable;
+ devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA;
trigvar =
ni_ns_to_timer(dev, cmd->scan_begin_arg,
CMDF_ROUND_NEAREST);
- ni_stc_writel(dev, 1, AO_UI_Load_A_Register);
- ni_stc_writew(dev, AO_UI_Load, AO_Command_1_Register);
- ni_stc_writel(dev, trigvar, AO_UI_Load_A_Register);
+ ni_stc_writel(dev, 1, NISTC_AO_UI_LOADA_REG);
+ ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG);
+ ni_stc_writel(dev, trigvar, NISTC_AO_UI_LOADA_REG);
break;
case TRIG_EXT:
devpriv->ao_mode1 |=
- AO_UPDATE_Source_Select(cmd->scan_begin_arg);
+ NISTC_AO_MODE1_UPDATE_SRC(cmd->scan_begin_arg);
if (cmd->scan_begin_arg & CR_INVERT)
- devpriv->ao_mode1 |= AO_UPDATE_Source_Polarity;
- devpriv->ao_cmd2 |= AO_BC_Gate_Enable;
+ devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY;
+ devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA;
break;
default:
BUG();
break;
}
- ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register);
- ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
- devpriv->ao_mode2 &=
- ~(AO_UI_Reload_Mode(3) | AO_UI_Initial_Load_Source);
- ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+ ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG);
+ ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
+ devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) |
+ NISTC_AO_MODE2_UI_INIT_LOAD_SRC);
+ ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
if (cmd->scan_end_arg > 1) {
- devpriv->ao_mode1 |= AO_Multiple_Channels;
+ devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN;
ni_stc_writew(dev,
- AO_Number_Of_Channels(cmd->scan_end_arg - 1) |
- AO_UPDATE_Output_Select(AO_Update_Output_High_Z),
- AO_Output_Control_Register);
+ NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) |
+ NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ,
+ NISTC_AO_OUT_CTRL_REG);
} else {
unsigned bits;
- devpriv->ao_mode1 &= ~AO_Multiple_Channels;
- bits = AO_UPDATE_Output_Select(AO_Update_Output_High_Z);
+ devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN;
+ bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ;
if (devpriv->is_m_series || devpriv->is_6xxx) {
- bits |= AO_Number_Of_Channels(0);
+ bits |= NISTC_AO_OUT_CTRL_CHANS(0);
} else {
bits |=
- AO_Number_Of_Channels(CR_CHAN(cmd->chanlist[0]));
+ NISTC_AO_OUT_CTRL_CHANS(CR_CHAN(cmd->chanlist[0]));
}
- ni_stc_writew(dev, bits, AO_Output_Control_Register);
+ ni_stc_writew(dev, bits, NISTC_AO_OUT_CTRL_REG);
}
- ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
+ ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
- ni_stc_writew(dev, AO_DAC0_Update_Mode | AO_DAC1_Update_Mode,
- AO_Command_1_Register);
+ ni_stc_writew(dev, NISTC_AO_CMD1_DAC1_UPDATE_MODE |
+ NISTC_AO_CMD1_DAC0_UPDATE_MODE,
+ NISTC_AO_CMD1_REG);
- devpriv->ao_mode3 |= AO_Stop_On_Overrun_Error;
- ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
+ devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR;
+ ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
- devpriv->ao_mode2 &= ~AO_FIFO_Mode_Mask;
+ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_MODE_MASK;
#ifdef PCIDMA
- devpriv->ao_mode2 |= AO_FIFO_Mode_HF_to_F;
+ devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF_F;
#else
- devpriv->ao_mode2 |= AO_FIFO_Mode_HF;
+ devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF;
#endif
- devpriv->ao_mode2 &= ~AO_FIFO_Retransmit_Enable;
- ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+ devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA;
+ ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
- bits = AO_BC_Source_Select | AO_UPDATE_Pulse_Width |
- AO_TMRDACWR_Pulse_Width;
+ bits = NISTC_AO_PERSONAL_BC_SRC_SEL |
+ NISTC_AO_PERSONAL_UPDATE_PW |
+ NISTC_AO_PERSONAL_TMRDACWR_PW;
if (board->ao_fifo_depth)
- bits |= AO_FIFO_Enable;
+ bits |= NISTC_AO_PERSONAL_FIFO_ENA;
else
- bits |= AO_DMA_PIO_Control;
+ bits |= NISTC_AO_PERSONAL_DMA_PIO_CTRL;
#if 0
- /* F Hess: windows driver does not set AO_Number_Of_DAC_Packages bit for 6281,
- verified with bus analyzer. */
+ /*
+ * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit
+ * for 6281, verified with bus analyzer.
+ */
if (devpriv->is_m_series)
- bits |= AO_Number_Of_DAC_Packages;
+ bits |= NISTC_AO_PERSONAL_NUM_DAC;
#endif
- ni_stc_writew(dev, bits, AO_Personal_Register);
+ ni_stc_writew(dev, bits, NISTC_AO_PERSONAL_REG);
/* enable sending of ao dma requests */
- ni_stc_writew(dev, AO_AOFREQ_Enable, AO_Start_Select_Register);
+ ni_stc_writew(dev, NISTC_AO_START_AOFREQ_ENA, NISTC_AO_START_SEL_REG);
- ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
if (cmd->stop_src == TRIG_COUNT) {
- ni_stc_writew(dev, AO_BC_TC_Interrupt_Ack,
- Interrupt_B_Ack_Register);
- ni_set_bits(dev, Interrupt_B_Enable_Register,
- AO_BC_TC_Interrupt_Enable, 1);
+ ni_stc_writew(dev, NISTC_INTB_ACK_AO_BC_TC,
+ NISTC_INTB_ACK_REG);
+ ni_set_bits(dev, NISTC_INTB_ENA_REG,
+ NISTC_INTB_ENA_AO_BC_TC, 1);
}
s->async->inttrig = ni_ao_inttrig;
ni_release_ao_mite_channel(dev);
- ni_stc_writew(dev, AO_Configuration_Start, Joint_Reset_Register);
- ni_stc_writew(dev, AO_Disarm, AO_Command_1_Register);
- ni_set_bits(dev, Interrupt_B_Enable_Register, ~0, 0);
- ni_stc_writew(dev, AO_BC_Source_Select, AO_Personal_Register);
- ni_stc_writew(dev, 0x3f98, Interrupt_B_Ack_Register);
- ni_stc_writew(dev, AO_BC_Source_Select | AO_UPDATE_Pulse_Width |
- AO_TMRDACWR_Pulse_Width, AO_Personal_Register);
- ni_stc_writew(dev, 0, AO_Output_Control_Register);
- ni_stc_writew(dev, 0, AO_Start_Select_Register);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG);
+ ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG);
+ ni_set_bits(dev, NISTC_INTB_ENA_REG, ~0, 0);
+ ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG);
+ ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG);
+ ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL |
+ NISTC_AO_PERSONAL_UPDATE_PW |
+ NISTC_AO_PERSONAL_TMRDACWR_PW,
+ NISTC_AO_PERSONAL_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_OUT_CTRL_REG);
+ ni_stc_writew(dev, 0, NISTC_AO_START_SEL_REG);
devpriv->ao_cmd1 = 0;
- ni_stc_writew(dev, devpriv->ao_cmd1, AO_Command_1_Register);
+ ni_stc_writew(dev, devpriv->ao_cmd1, NISTC_AO_CMD1_REG);
devpriv->ao_cmd2 = 0;
- ni_stc_writew(dev, devpriv->ao_cmd2, AO_Command_2_Register);
+ ni_stc_writew(dev, devpriv->ao_cmd2, NISTC_AO_CMD2_REG);
devpriv->ao_mode1 = 0;
- ni_stc_writew(dev, devpriv->ao_mode1, AO_Mode_1_Register);
+ ni_stc_writew(dev, devpriv->ao_mode1, NISTC_AO_MODE1_REG);
devpriv->ao_mode2 = 0;
- ni_stc_writew(dev, devpriv->ao_mode2, AO_Mode_2_Register);
+ ni_stc_writew(dev, devpriv->ao_mode2, NISTC_AO_MODE2_REG);
if (devpriv->is_m_series)
- devpriv->ao_mode3 = AO_Last_Gate_Disable;
+ devpriv->ao_mode3 = NISTC_AO_MODE3_LAST_GATE_DISABLE;
else
devpriv->ao_mode3 = 0;
- ni_stc_writew(dev, devpriv->ao_mode3, AO_Mode_3_Register);
+ ni_stc_writew(dev, devpriv->ao_mode3, NISTC_AO_MODE3_REG);
devpriv->ao_trigger_select = 0;
ni_stc_writew(dev, devpriv->ao_trigger_select,
- AO_Trigger_Select_Register);
+ NISTC_AO_TRIG_SEL_REG);
if (devpriv->is_6xxx) {
unsigned immediate_bits = 0;
unsigned i;
for (i = 0; i < s->n_chan; ++i)
immediate_bits |= 1 << i;
- ni_ao_win_outw(dev, immediate_bits, AO_Immediate_671x);
- ni_ao_win_outw(dev, CLEAR_WG, AO_Misc_611x);
+ ni_ao_win_outw(dev, immediate_bits, NI671X_AO_IMMEDIATE_REG);
+ ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG,
+ NI611X_AO_MISC_REG);
}
- ni_stc_writew(dev, AO_Configuration_End, Joint_Reset_Register);
+ ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG);
return 0;
}
if (ret)
return ret;
- devpriv->dio_control &= ~DIO_Pins_Dir_Mask;
- devpriv->dio_control |= DIO_Pins_Dir(s->io_bits);
- ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
+ devpriv->dio_control &= ~NISTC_DIO_CTRL_DIR_MASK;
+ devpriv->dio_control |= NISTC_DIO_CTRL_DIR(s->io_bits);
+ ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG);
return insn->n;
}
struct ni_private *devpriv = dev->private;
/* Make sure we're not using the serial part of the dio */
- if ((data[0] & (DIO_SDIN | DIO_SDOUT)) && devpriv->serial_interval_ns)
+ if ((data[0] & (NISTC_DIO_SDIN | NISTC_DIO_SDOUT)) &&
+ devpriv->serial_interval_ns)
return -EBUSY;
if (comedi_dio_update_state(s, data)) {
- devpriv->dio_output &= ~DIO_Parallel_Data_Mask;
- devpriv->dio_output |= DIO_Parallel_Data_Out(s->state);
- ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register);
+ devpriv->dio_output &= ~NISTC_DIO_OUT_PARALLEL_MASK;
+ devpriv->dio_output |= NISTC_DIO_OUT_PARALLEL(s->state);
+ ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG);
}
- data[1] = ni_stc_readw(dev, DIO_Parallel_Input_Register);
+ data[1] = ni_stc_readw(dev, NISTC_DIO_IN_REG);
return insn->n;
}
if (ret)
return ret;
- ni_writel(dev, s->io_bits, M_Offset_DIO_Direction);
+ ni_writel(dev, s->io_bits, NI_M_DIO_DIR_REG);
return insn->n;
}
unsigned int *data)
{
if (comedi_dio_update_state(s, data))
- ni_writel(dev, s->state, M_Offset_Static_Digital_Output);
+ ni_writel(dev, s->state, NI_M_DIO_REG);
- data[1] = ni_readl(dev, M_Offset_Static_Digital_Input);
+ data[1] = ni_readl(dev, NI_M_DIO_REG);
return insn->n;
}
err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
tmp = cmd->scan_begin_arg;
- tmp &= CR_PACK_FLAGS(CDO_Sample_Source_Select_Mask, 0, 0, CR_INVERT);
+ tmp &= CR_PACK_FLAGS(NI_M_CDO_MODE_SAMPLE_SRC_MASK, 0, 0, CR_INVERT);
if (tmp != cmd->scan_begin_arg)
err |= -EINVAL;
if (retval < 0)
return retval;
#endif
-/*
-* XXX not sure what interrupt C group does
-* ni_writeb(dev, Interrupt_Group_C_Enable_Bit,
-* M_Offset_Interrupt_C_Enable); wait for dma to fill output fifo
-*/
+ /*
+ * XXX not sure what interrupt C group does
+ * wait for dma to fill output fifo
+ * ni_writeb(dev, NI_M_INTC_ENA, NI_M_INTC_ENA_REG);
+ */
for (i = 0; i < timeout; ++i) {
- if (ni_readl(dev, M_Offset_CDIO_Status) & CDO_FIFO_Full_Bit)
+ if (ni_readl(dev, NI_M_CDIO_STATUS_REG) &
+ NI_M_CDIO_STATUS_CDO_FIFO_FULL)
break;
udelay(10);
}
s->cancel(dev, s);
return -EIO;
}
- ni_writel(dev, CDO_Arm_Bit | CDO_Error_Interrupt_Enable_Set_Bit |
- CDO_Empty_FIFO_Interrupt_Enable_Set_Bit,
- M_Offset_CDIO_Command);
+ ni_writel(dev, NI_M_CDO_CMD_ARM |
+ NI_M_CDO_CMD_ERR_INT_ENA_SET |
+ NI_M_CDO_CMD_F_E_INT_ENA_SET,
+ NI_M_CDIO_CMD_REG);
return retval;
}
static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
{
const struct comedi_cmd *cmd = &s->async->cmd;
- unsigned cdo_mode_bits = CDO_FIFO_Mode_Bit | CDO_Halt_On_Error_Bit;
+ unsigned cdo_mode_bits;
int retval;
- ni_writel(dev, CDO_Reset_Bit, M_Offset_CDIO_Command);
- switch (cmd->scan_begin_src) {
- case TRIG_EXT:
- cdo_mode_bits |=
- CR_CHAN(cmd->scan_begin_arg) &
- CDO_Sample_Source_Select_Mask;
- break;
- default:
- BUG();
- break;
- }
+ ni_writel(dev, NI_M_CDO_CMD_RESET, NI_M_CDIO_CMD_REG);
+ cdo_mode_bits = NI_M_CDO_MODE_FIFO_MODE |
+ NI_M_CDO_MODE_HALT_ON_ERROR |
+ NI_M_CDO_MODE_SAMPLE_SRC(CR_CHAN(cmd->scan_begin_arg));
if (cmd->scan_begin_arg & CR_INVERT)
- cdo_mode_bits |= CDO_Polarity_Bit;
- ni_writel(dev, cdo_mode_bits, M_Offset_CDO_Mode);
+ cdo_mode_bits |= NI_M_CDO_MODE_POLARITY;
+ ni_writel(dev, cdo_mode_bits, NI_M_CDO_MODE_REG);
if (s->io_bits) {
- ni_writel(dev, s->state, M_Offset_CDO_FIFO_Data);
- ni_writel(dev, CDO_SW_Update_Bit, M_Offset_CDIO_Command);
- ni_writel(dev, s->io_bits, M_Offset_CDO_Mask_Enable);
+ ni_writel(dev, s->state, NI_M_CDO_FIFO_DATA_REG);
+ ni_writel(dev, NI_M_CDO_CMD_SW_UPDATE, NI_M_CDIO_CMD_REG);
+ ni_writel(dev, s->io_bits, NI_M_CDO_MASK_ENA_REG);
} else {
dev_err(dev->class_dev,
"attempted to run digital output command with no lines configured as outputs\n");
static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{
- ni_writel(dev, CDO_Disarm_Bit | CDO_Error_Interrupt_Enable_Clear_Bit |
- CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit |
- CDO_FIFO_Request_Interrupt_Enable_Clear_Bit,
- M_Offset_CDIO_Command);
-/*
-* XXX not sure what interrupt C group does ni_writeb(dev, 0,
-* M_Offset_Interrupt_C_Enable);
-*/
- ni_writel(dev, 0, M_Offset_CDO_Mask_Enable);
+ ni_writel(dev, NI_M_CDO_CMD_DISARM |
+ NI_M_CDO_CMD_ERR_INT_ENA_CLR |
+ NI_M_CDO_CMD_F_E_INT_ENA_CLR |
+ NI_M_CDO_CMD_F_REQ_INT_ENA_CLR,
+ NI_M_CDIO_CMD_REG);
+ /*
+ * XXX not sure what interrupt C group does
+ * ni_writeb(dev, 0, NI_M_INTC_ENA_REG);
+ */
+ ni_writel(dev, 0, NI_M_CDO_MASK_ENA_REG);
ni_release_cdo_mite_channel(dev);
return 0;
}
spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags);
#endif
- cdio_status = ni_readl(dev, M_Offset_CDIO_Status);
- if (cdio_status & (CDO_Overrun_Bit | CDO_Underflow_Bit)) {
+ cdio_status = ni_readl(dev, NI_M_CDIO_STATUS_REG);
+ if (cdio_status & NI_M_CDIO_STATUS_CDO_ERROR) {
/* XXX just guessing this is needed and does something useful */
- ni_writel(dev, CDO_Error_Interrupt_Confirm_Bit,
- M_Offset_CDIO_Command);
+ ni_writel(dev, NI_M_CDO_CMD_ERR_INT_CONFIRM,
+ NI_M_CDIO_CMD_REG);
s->async->events |= COMEDI_CB_OVERFLOW;
}
- if (cdio_status & CDO_FIFO_Empty_Bit) {
- ni_writel(dev, CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit,
- M_Offset_CDIO_Command);
+ if (cdio_status & NI_M_CDIO_STATUS_CDO_FIFO_EMPTY) {
+ ni_writel(dev, NI_M_CDO_CMD_F_E_INT_ENA_CLR,
+ NI_M_CDIO_CMD_REG);
/* s->async->events |= COMEDI_CB_EOA; */
}
comedi_handle_events(dev, s);
unsigned int status1;
int err = 0, count = 20;
- devpriv->dio_output &= ~DIO_Serial_Data_Mask;
- devpriv->dio_output |= DIO_Serial_Data_Out(data_out);
- ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register);
+ devpriv->dio_output &= ~NISTC_DIO_OUT_SERIAL_MASK;
+ devpriv->dio_output |= NISTC_DIO_OUT_SERIAL(data_out);
+ ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG);
- status1 = ni_stc_readw(dev, Joint_Status_1_Register);
- if (status1 & DIO_Serial_IO_In_Progress_St) {
+ status1 = ni_stc_readw(dev, NISTC_STATUS1_REG);
+ if (status1 & NISTC_STATUS1_SERIO_IN_PROG) {
err = -EBUSY;
goto Error;
}
- devpriv->dio_control |= DIO_HW_Serial_Start;
- ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
- devpriv->dio_control &= ~DIO_HW_Serial_Start;
+ devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_START;
+ ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG);
+ devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_START;
/* Wait until STC says we're done, but don't loop infinitely. */
- while ((status1 = ni_stc_readw(dev, Joint_Status_1_Register)) &
- DIO_Serial_IO_In_Progress_St) {
+ while ((status1 = ni_stc_readw(dev, NISTC_STATUS1_REG)) &
+ NISTC_STATUS1_SERIO_IN_PROG) {
/* Delay one bit per loop */
udelay((devpriv->serial_interval_ns + 999) / 1000);
if (--count < 0) {
}
}
- /* Delay for last bit. This delay is absolutely necessary, because
- DIO_Serial_IO_In_Progress_St goes high one bit too early. */
+ /*
+ * Delay for last bit. This delay is absolutely necessary, because
+ * NISTC_STATUS1_SERIO_IN_PROG goes high one bit too early.
+ */
udelay((devpriv->serial_interval_ns + 999) / 1000);
if (data_in)
- *data_in = ni_stc_readw(dev, DIO_Serial_Input_Register);
+ *data_in = ni_stc_readw(dev, NISTC_DIO_SERIAL_IN_REG);
Error:
- ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
+ ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG);
return err;
}
/* Output current bit; note that we cannot touch s->state
because it is a per-subdevice field, and serial is
a separate subdevice from DIO. */
- devpriv->dio_output &= ~DIO_SDOUT;
+ devpriv->dio_output &= ~NISTC_DIO_SDOUT;
if (data_out & mask)
- devpriv->dio_output |= DIO_SDOUT;
- ni_stc_writew(dev, devpriv->dio_output, DIO_Output_Register);
+ devpriv->dio_output |= NISTC_DIO_SDOUT;
+ ni_stc_writew(dev, devpriv->dio_output, NISTC_DIO_OUT_REG);
/* Assert SDCLK (active low, inverted), wait for half of
the delay, deassert SDCLK, and wait for the other half. */
- devpriv->dio_control |= DIO_Software_Serial_Control;
- ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
+ devpriv->dio_control |= NISTC_DIO_SDCLK;
+ ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG);
udelay((devpriv->serial_interval_ns + 999) / 2000);
- devpriv->dio_control &= ~DIO_Software_Serial_Control;
- ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
+ devpriv->dio_control &= ~NISTC_DIO_SDCLK;
+ ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG);
udelay((devpriv->serial_interval_ns + 999) / 2000);
/* Input current bit */
- if (ni_stc_readw(dev, DIO_Parallel_Input_Register) & DIO_SDIN)
+ if (ni_stc_readw(dev, NISTC_DIO_IN_REG) & NISTC_DIO_SDIN)
input |= mask;
}
unsigned int *data)
{
struct ni_private *devpriv = dev->private;
+ unsigned clk_fout = devpriv->clock_and_fout;
int err = insn->n;
unsigned char byte_out, byte_in = 0;
switch (data[0]) {
case INSN_CONFIG_SERIAL_CLOCK:
devpriv->serial_hw_mode = 1;
- devpriv->dio_control |= DIO_HW_Serial_Enable;
+ devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_ENA;
if (data[1] == SERIAL_DISABLED) {
devpriv->serial_hw_mode = 0;
- devpriv->dio_control &= ~(DIO_HW_Serial_Enable |
- DIO_Software_Serial_Control);
+ devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA |
+ NISTC_DIO_SDCLK);
data[1] = SERIAL_DISABLED;
devpriv->serial_interval_ns = data[1];
} else if (data[1] <= SERIAL_600NS) {
/* Warning: this clock speed is too fast to reliably
control SCXI. */
- devpriv->dio_control &= ~DIO_HW_Serial_Timebase;
- devpriv->clock_and_fout |= Slow_Internal_Timebase;
- devpriv->clock_and_fout &= ~DIO_Serial_Out_Divide_By_2;
+ devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE;
+ clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE;
+ clk_fout &= ~NISTC_CLK_FOUT_DIO_SER_OUT_DIV2;
data[1] = SERIAL_600NS;
devpriv->serial_interval_ns = data[1];
} else if (data[1] <= SERIAL_1_2US) {
- devpriv->dio_control &= ~DIO_HW_Serial_Timebase;
- devpriv->clock_and_fout |= Slow_Internal_Timebase |
- DIO_Serial_Out_Divide_By_2;
+ devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE;
+ clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE |
+ NISTC_CLK_FOUT_DIO_SER_OUT_DIV2;
data[1] = SERIAL_1_2US;
devpriv->serial_interval_ns = data[1];
} else if (data[1] <= SERIAL_10US) {
- devpriv->dio_control |= DIO_HW_Serial_Timebase;
- devpriv->clock_and_fout |= Slow_Internal_Timebase |
- DIO_Serial_Out_Divide_By_2;
- /* Note: DIO_Serial_Out_Divide_By_2 only affects
+ devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_TIMEBASE;
+ clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE |
+ NISTC_CLK_FOUT_DIO_SER_OUT_DIV2;
+ /* Note: NISTC_CLK_FOUT_DIO_SER_OUT_DIV2 only affects
600ns/1.2us. If you turn divide_by_2 off with the
slow clock, you will still get 10us, except then
all your delays are wrong. */
data[1] = SERIAL_10US;
devpriv->serial_interval_ns = data[1];
} else {
- devpriv->dio_control &= ~(DIO_HW_Serial_Enable |
- DIO_Software_Serial_Control);
+ devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA |
+ NISTC_DIO_SDCLK);
devpriv->serial_hw_mode = 0;
data[1] = (data[1] / 1000) * 1000;
devpriv->serial_interval_ns = data[1];
}
+ devpriv->clock_and_fout = clk_fout;
- ni_stc_writew(dev, devpriv->dio_control, DIO_Control_Register);
- ni_stc_writew(dev, devpriv->clock_and_fout,
- Clock_and_FOUT_Register);
+ ni_stc_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG);
+ ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG);
return 1;
case INSN_CONFIG_BIDIRECTIONAL_DATA:
int i;
for (i = 0; i < s->n_chan; i++) {
- ni_ao_win_outw(dev, AO_Channel(i) | 0x0,
- AO_Configuration_2_67xx);
- }
- ni_ao_win_outw(dev, 0x0, AO_Later_Single_Point_Updates);
-}
+ ni_ao_win_outw(dev, NI_E_AO_DACSEL(i) | 0x0,
+ NI67XX_AO_CFG2_REG);
+ }
+ ni_ao_win_outw(dev, 0x0, NI67XX_AO_SP_UPDATES_REG);
+}
+
+static const struct mio_regmap ni_gpct_to_stc_regmap[] = {
+ [NITIO_G0_AUTO_INC] = { NISTC_G0_AUTOINC_REG, 2 },
+ [NITIO_G1_AUTO_INC] = { NISTC_G1_AUTOINC_REG, 2 },
+ [NITIO_G0_CMD] = { NISTC_G0_CMD_REG, 2 },
+ [NITIO_G1_CMD] = { NISTC_G1_CMD_REG, 2 },
+ [NITIO_G0_HW_SAVE] = { NISTC_G0_HW_SAVE_REG, 4 },
+ [NITIO_G1_HW_SAVE] = { NISTC_G1_HW_SAVE_REG, 4 },
+ [NITIO_G0_SW_SAVE] = { NISTC_G0_SAVE_REG, 4 },
+ [NITIO_G1_SW_SAVE] = { NISTC_G1_SAVE_REG, 4 },
+ [NITIO_G0_MODE] = { NISTC_G0_MODE_REG, 2 },
+ [NITIO_G1_MODE] = { NISTC_G1_MODE_REG, 2 },
+ [NITIO_G0_LOADA] = { NISTC_G0_LOADA_REG, 4 },
+ [NITIO_G1_LOADA] = { NISTC_G1_LOADA_REG, 4 },
+ [NITIO_G0_LOADB] = { NISTC_G0_LOADB_REG, 4 },
+ [NITIO_G1_LOADB] = { NISTC_G1_LOADB_REG, 4 },
+ [NITIO_G0_INPUT_SEL] = { NISTC_G0_INPUT_SEL_REG, 2 },
+ [NITIO_G1_INPUT_SEL] = { NISTC_G1_INPUT_SEL_REG, 2 },
+ [NITIO_G0_CNT_MODE] = { 0x1b0, 2 }, /* M-Series only */
+ [NITIO_G1_CNT_MODE] = { 0x1b2, 2 }, /* M-Series only */
+ [NITIO_G0_GATE2] = { 0x1b4, 2 }, /* M-Series only */
+ [NITIO_G1_GATE2] = { 0x1b6, 2 }, /* M-Series only */
+ [NITIO_G01_STATUS] = { NISTC_G01_STATUS_REG, 2 },
+ [NITIO_G01_RESET] = { NISTC_RESET_REG, 2 },
+ [NITIO_G01_STATUS1] = { NISTC_STATUS1_REG, 2 },
+ [NITIO_G01_STATUS2] = { NISTC_STATUS2_REG, 2 },
+ [NITIO_G0_DMA_CFG] = { 0x1b8, 2 }, /* M-Series only */
+ [NITIO_G1_DMA_CFG] = { 0x1ba, 2 }, /* M-Series only */
+ [NITIO_G0_DMA_STATUS] = { 0x1b8, 2 }, /* M-Series only */
+ [NITIO_G1_DMA_STATUS] = { 0x1ba, 2 }, /* M-Series only */
+ [NITIO_G0_ABZ] = { 0x1c0, 2 }, /* M-Series only */
+ [NITIO_G1_ABZ] = { 0x1c2, 2 }, /* M-Series only */
+ [NITIO_G0_INT_ACK] = { NISTC_INTA_ACK_REG, 2 },
+ [NITIO_G1_INT_ACK] = { NISTC_INTB_ACK_REG, 2 },
+ [NITIO_G0_STATUS] = { NISTC_AI_STATUS1_REG, 2 },
+ [NITIO_G1_STATUS] = { NISTC_AO_STATUS1_REG, 2 },
+ [NITIO_G0_INT_ENA] = { NISTC_INTA_ENA_REG, 2 },
+ [NITIO_G1_INT_ENA] = { NISTC_INTB_ENA_REG, 2 },
+};
-static unsigned ni_gpct_to_stc_register(enum ni_gpct_register reg)
+static unsigned int ni_gpct_to_stc_register(struct comedi_device *dev,
+ enum ni_gpct_register reg)
{
- unsigned stc_register;
+ const struct mio_regmap *regmap;
- switch (reg) {
- case NITIO_G0_AUTO_INC:
- stc_register = G_Autoincrement_Register(0);
- break;
- case NITIO_G1_AUTO_INC:
- stc_register = G_Autoincrement_Register(1);
- break;
- case NITIO_G0_CMD:
- stc_register = G_Command_Register(0);
- break;
- case NITIO_G1_CMD:
- stc_register = G_Command_Register(1);
- break;
- case NITIO_G0_HW_SAVE:
- stc_register = G_HW_Save_Register(0);
- break;
- case NITIO_G1_HW_SAVE:
- stc_register = G_HW_Save_Register(1);
- break;
- case NITIO_G0_SW_SAVE:
- stc_register = G_Save_Register(0);
- break;
- case NITIO_G1_SW_SAVE:
- stc_register = G_Save_Register(1);
- break;
- case NITIO_G0_MODE:
- stc_register = G_Mode_Register(0);
- break;
- case NITIO_G1_MODE:
- stc_register = G_Mode_Register(1);
- break;
- case NITIO_G0_LOADA:
- stc_register = G_Load_A_Register(0);
- break;
- case NITIO_G1_LOADA:
- stc_register = G_Load_A_Register(1);
- break;
- case NITIO_G0_LOADB:
- stc_register = G_Load_B_Register(0);
- break;
- case NITIO_G1_LOADB:
- stc_register = G_Load_B_Register(1);
- break;
- case NITIO_G0_INPUT_SEL:
- stc_register = G_Input_Select_Register(0);
- break;
- case NITIO_G1_INPUT_SEL:
- stc_register = G_Input_Select_Register(1);
- break;
- case NITIO_G01_STATUS:
- stc_register = G_Status_Register;
- break;
- case NITIO_G01_RESET:
- stc_register = Joint_Reset_Register;
- break;
- case NITIO_G01_STATUS1:
- stc_register = Joint_Status_1_Register;
- break;
- case NITIO_G01_STATUS2:
- stc_register = Joint_Status_2_Register;
- break;
- case NITIO_G0_INT_ACK:
- stc_register = Interrupt_A_Ack_Register;
- break;
- case NITIO_G1_INT_ACK:
- stc_register = Interrupt_B_Ack_Register;
- break;
- case NITIO_G0_STATUS:
- stc_register = AI_Status_1_Register;
- break;
- case NITIO_G1_STATUS:
- stc_register = AO_Status_1_Register;
- break;
- case NITIO_G0_INT_ENA:
- stc_register = Interrupt_A_Enable_Register;
- break;
- case NITIO_G1_INT_ENA:
- stc_register = Interrupt_B_Enable_Register;
- break;
- default:
- pr_err("%s: unhandled register 0x%x in switch.\n",
- __func__, reg);
- BUG();
+ if (reg < ARRAY_SIZE(ni_gpct_to_stc_regmap)) {
+ regmap = &ni_gpct_to_stc_regmap[reg];
+ } else {
+ dev_warn(dev->class_dev,"%s: unhandled register 0x%x\n",
+ __func__, reg);
return 0;
}
- return stc_register;
+
+ return regmap->mio_reg;
}
static void ni_gpct_write_register(struct ni_gpct *counter, unsigned bits,
enum ni_gpct_register reg)
{
struct comedi_device *dev = counter->counter_dev->dev;
- unsigned stc_register;
- /* bits in the join reset register which are relevant to counters */
- static const unsigned gpct_joint_reset_mask = G0_Reset | G1_Reset;
+ unsigned int stc_register = ni_gpct_to_stc_register(dev, reg);
static const unsigned gpct_interrupt_a_enable_mask =
- G0_Gate_Interrupt_Enable | G0_TC_Interrupt_Enable;
+ NISTC_INTA_ENA_G0_GATE | NISTC_INTA_ENA_G0_TC;
static const unsigned gpct_interrupt_b_enable_mask =
- G1_Gate_Interrupt_Enable | G1_TC_Interrupt_Enable;
+ NISTC_INTB_ENA_G1_GATE | NISTC_INTB_ENA_G1_TC;
+
+ if (stc_register == 0)
+ return;
switch (reg) {
- /* m-series-only registers */
+ /* m-series only registers */
case NITIO_G0_CNT_MODE:
- ni_writew(dev, bits, M_Offset_G0_Counting_Mode);
- break;
case NITIO_G1_CNT_MODE:
- ni_writew(dev, bits, M_Offset_G1_Counting_Mode);
- break;
case NITIO_G0_GATE2:
- ni_writew(dev, bits, M_Offset_G0_Second_Gate);
- break;
case NITIO_G1_GATE2:
- ni_writew(dev, bits, M_Offset_G1_Second_Gate);
- break;
case NITIO_G0_DMA_CFG:
- ni_writew(dev, bits, M_Offset_G0_DMA_Config);
- break;
case NITIO_G1_DMA_CFG:
- ni_writew(dev, bits, M_Offset_G1_DMA_Config);
- break;
case NITIO_G0_ABZ:
- ni_writew(dev, bits, M_Offset_G0_MSeries_ABZ);
- break;
case NITIO_G1_ABZ:
- ni_writew(dev, bits, M_Offset_G1_MSeries_ABZ);
+ ni_writew(dev, bits, stc_register);
break;
/* 32 bit registers */
case NITIO_G1_LOADA:
case NITIO_G0_LOADB:
case NITIO_G1_LOADB:
- stc_register = ni_gpct_to_stc_register(reg);
ni_stc_writel(dev, bits, stc_register);
break;
/* 16 bit registers */
case NITIO_G0_INT_ENA:
BUG_ON(bits & ~gpct_interrupt_a_enable_mask);
- ni_set_bitfield(dev, Interrupt_A_Enable_Register,
+ ni_set_bitfield(dev, stc_register,
gpct_interrupt_a_enable_mask, bits);
break;
case NITIO_G1_INT_ENA:
BUG_ON(bits & ~gpct_interrupt_b_enable_mask);
- ni_set_bitfield(dev, Interrupt_B_Enable_Register,
+ ni_set_bitfield(dev, stc_register,
gpct_interrupt_b_enable_mask, bits);
break;
case NITIO_G01_RESET:
- BUG_ON(bits & ~gpct_joint_reset_mask);
+ BUG_ON(bits & ~(NISTC_RESET_G0 | NISTC_RESET_G1));
/* fall-through */
default:
- stc_register = ni_gpct_to_stc_register(reg);
ni_stc_writew(dev, bits, stc_register);
}
}
enum ni_gpct_register reg)
{
struct comedi_device *dev = counter->counter_dev->dev;
- unsigned stc_register;
+ unsigned int stc_register = ni_gpct_to_stc_register(dev, reg);
+
+ if (stc_register == 0)
+ return 0;
switch (reg) {
/* m-series only registers */
case NITIO_G0_DMA_STATUS:
- return ni_readw(dev, M_Offset_G0_DMA_Status);
case NITIO_G1_DMA_STATUS:
- return ni_readw(dev, M_Offset_G1_DMA_Status);
+ return ni_readw(dev, stc_register);
/* 32 bit registers */
case NITIO_G0_HW_SAVE:
case NITIO_G1_HW_SAVE:
case NITIO_G0_SW_SAVE:
case NITIO_G1_SW_SAVE:
- stc_register = ni_gpct_to_stc_register(reg);
return ni_stc_readl(dev, stc_register);
/* 16 bit registers */
default:
- stc_register = ni_gpct_to_stc_register(reg);
return ni_stc_readw(dev, stc_register);
}
- return 0;
}
static int ni_freq_out_insn_read(struct comedi_device *dev,
unsigned int *data)
{
struct ni_private *devpriv = dev->private;
- unsigned int val = devpriv->clock_and_fout & FOUT_Divider_mask;
+ unsigned int val = NISTC_CLK_FOUT_TO_DIVIDER(devpriv->clock_and_fout);
int i;
for (i = 0; i < insn->n; i++)
struct ni_private *devpriv = dev->private;
if (insn->n) {
- devpriv->clock_and_fout &= ~FOUT_Enable;
- ni_stc_writew(dev, devpriv->clock_and_fout,
- Clock_and_FOUT_Register);
- devpriv->clock_and_fout &= ~FOUT_Divider_mask;
+ unsigned int val = data[insn->n - 1];
+
+ devpriv->clock_and_fout &= ~NISTC_CLK_FOUT_ENA;
+ ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG);
+ devpriv->clock_and_fout &= ~NISTC_CLK_FOUT_DIVIDER_MASK;
/* use the last data value to set the fout divider */
- devpriv->clock_and_fout |= FOUT_Divider(data[insn->n - 1]);
+ devpriv->clock_and_fout |= NISTC_CLK_FOUT_DIVIDER(val);
- devpriv->clock_and_fout |= FOUT_Enable;
- ni_stc_writew(dev, devpriv->clock_and_fout,
- Clock_and_FOUT_Register);
+ devpriv->clock_and_fout |= NISTC_CLK_FOUT_ENA;
+ ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG);
}
return insn->n;
}
case INSN_CONFIG_SET_CLOCK_SRC:
switch (data[1]) {
case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC:
- devpriv->clock_and_fout &= ~FOUT_Timebase_Select;
+ devpriv->clock_and_fout &= ~NISTC_CLK_FOUT_TIMEBASE_SEL;
break;
case NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC:
- devpriv->clock_and_fout |= FOUT_Timebase_Select;
+ devpriv->clock_and_fout |= NISTC_CLK_FOUT_TIMEBASE_SEL;
break;
default:
return -EINVAL;
}
- ni_stc_writew(dev, devpriv->clock_and_fout,
- Clock_and_FOUT_Register);
+ ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG);
break;
case INSN_CONFIG_GET_CLOCK_SRC:
- if (devpriv->clock_and_fout & FOUT_Timebase_Select) {
+ if (devpriv->clock_and_fout & NISTC_CLK_FOUT_TIMEBASE_SEL) {
data[1] = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC;
data[2] = TIMEBASE_2_NS;
} else {
data[4] = down_count * devpriv->clock_ns;
return -EAGAIN;
}
- ni_writel(dev, MSeries_Cal_PWM_High_Time_Bits(up_count) |
- MSeries_Cal_PWM_Low_Time_Bits(down_count),
- M_Offset_Cal_PWM);
+ ni_writel(dev, NI_M_CAL_PWM_HIGH_TIME(up_count) |
+ NI_M_CAL_PWM_LOW_TIME(down_count),
+ NI_M_CAL_PWM_REG);
devpriv->pwm_up_count = up_count;
devpriv->pwm_down_count = down_count;
return 5;
data[4] = down_count * devpriv->clock_ns;
return -EAGAIN;
}
- ni_writel(dev, up_count, Calibration_HighTime_6143);
+ ni_writel(dev, up_count, NI6143_CALIB_HI_TIME_REG);
devpriv->pwm_up_count = up_count;
- ni_writel(dev, down_count, Calibration_LowTime_6143);
+ ni_writel(dev, down_count, NI6143_CALIB_LO_TIME_REG);
devpriv->pwm_down_count = down_count;
return 5;
case INSN_CONFIG_GET_PWM_OUTPUT:
const struct ni_board_struct *board = dev->board_ptr;
struct ni_private *devpriv = dev->private;
unsigned int loadbit = 0, bits = 0, bit, bitstring = 0;
+ unsigned int cmd;
int i;
int type;
break;
if (addr < caldacs[type].n_chans) {
bits = caldacs[type].packbits(addr, val, &bitstring);
- loadbit = SerDacLd(i);
+ loadbit = NI_E_SERIAL_CMD_DAC_LD(i);
break;
}
addr -= caldacs[type].n_chans;
return;
for (bit = 1 << (bits - 1); bit; bit >>= 1) {
- ni_writeb(dev, ((bit & bitstring) ? 0x02 : 0), Serial_Command);
+ cmd = (bit & bitstring) ? NI_E_SERIAL_CMD_SDATA : 0;
+ ni_writeb(dev, cmd, NI_E_SERIAL_CMD_REG);
udelay(1);
- ni_writeb(dev, 1 | ((bit & bitstring) ? 0x02 : 0),
- Serial_Command);
+ ni_writeb(dev, NI_E_SERIAL_CMD_SCLK | cmd, NI_E_SERIAL_CMD_REG);
udelay(1);
}
- ni_writeb(dev, loadbit, Serial_Command);
+ ni_writeb(dev, loadbit, NI_E_SERIAL_CMD_REG);
udelay(1);
- ni_writeb(dev, 0, Serial_Command);
+ ni_writeb(dev, 0, NI_E_SERIAL_CMD_REG);
}
static int ni_calib_insn_write(struct comedi_device *dev,
static int ni_read_eeprom(struct comedi_device *dev, int addr)
{
+ unsigned int cmd = NI_E_SERIAL_CMD_EEPROM_CS;
int bit;
int bitstring;
bitstring = 0x0300 | ((addr & 0x100) << 3) | (addr & 0xff);
- ni_writeb(dev, 0x04, Serial_Command);
+ ni_writeb(dev, cmd, NI_E_SERIAL_CMD_REG);
for (bit = 0x8000; bit; bit >>= 1) {
- ni_writeb(dev, 0x04 | ((bit & bitstring) ? 0x02 : 0),
- Serial_Command);
- ni_writeb(dev, 0x05 | ((bit & bitstring) ? 0x02 : 0),
- Serial_Command);
+ if (bit & bitstring)
+ cmd |= NI_E_SERIAL_CMD_SDATA;
+ else
+ cmd &= ~NI_E_SERIAL_CMD_SDATA;
+
+ ni_writeb(dev, cmd, NI_E_SERIAL_CMD_REG);
+ ni_writeb(dev, NI_E_SERIAL_CMD_SCLK | cmd, NI_E_SERIAL_CMD_REG);
}
+ cmd = NI_E_SERIAL_CMD_EEPROM_CS;
bitstring = 0;
for (bit = 0x80; bit; bit >>= 1) {
- ni_writeb(dev, 0x04, Serial_Command);
- ni_writeb(dev, 0x05, Serial_Command);
- bitstring |= ((ni_readb(dev, XXX_Status) & PROMOUT) ? bit : 0);
+ ni_writeb(dev, cmd, NI_E_SERIAL_CMD_REG);
+ ni_writeb(dev, NI_E_SERIAL_CMD_SCLK | cmd, NI_E_SERIAL_CMD_REG);
+ if (ni_readb(dev, NI_E_STATUS_REG) & NI_E_STATUS_PROMOUT)
+ bitstring |= bit;
}
- ni_writeb(dev, 0x00, Serial_Command);
+ ni_writeb(dev, 0, NI_E_SERIAL_CMD_REG);
return bitstring;
}
struct ni_private *devpriv = dev->private;
const unsigned array_offset = chan / 3;
- return MSeries_PFI_Output_Select_Source(chan,
+ return NI_M_PFI_OUT_SEL_TO_SRC(chan,
devpriv->pfi_output_select_reg[array_offset]);
}
unsigned chan, unsigned source)
{
struct ni_private *devpriv = dev->private;
- unsigned pfi_reg_index;
- unsigned array_offset;
+ unsigned index = chan / 3;
+ unsigned short val = devpriv->pfi_output_select_reg[index];
if ((source & 0x1f) != source)
return -EINVAL;
- pfi_reg_index = 1 + chan / 3;
- array_offset = pfi_reg_index - 1;
- devpriv->pfi_output_select_reg[array_offset] &=
- ~MSeries_PFI_Output_Select_Mask(chan);
- devpriv->pfi_output_select_reg[array_offset] |=
- MSeries_PFI_Output_Select_Bits(chan, source);
- ni_writew(dev, devpriv->pfi_output_select_reg[array_offset],
- M_Offset_PFI_Output_Select(pfi_reg_index));
+
+ val &= ~NI_M_PFI_OUT_SEL_MASK(chan);
+ val |= NI_M_PFI_OUT_SEL(chan, source);
+ ni_writew(dev, val, NI_M_PFI_OUT_SEL_REG(index));
+ devpriv->pfi_output_select_reg[index] = val;
+
return 2;
}
if (!devpriv->is_m_series)
return -ENOTSUPP;
- bits = ni_readl(dev, M_Offset_PFI_Filter);
- bits &= ~MSeries_PFI_Filter_Select_Mask(pfi_channel);
- bits |= MSeries_PFI_Filter_Select_Bits(pfi_channel, filter);
- ni_writel(dev, bits, M_Offset_PFI_Filter);
+ bits = ni_readl(dev, NI_M_PFI_FILTER_REG);
+ bits &= ~NI_M_PFI_FILTER_SEL_MASK(pfi_channel);
+ bits |= NI_M_PFI_FILTER_SEL(pfi_channel, filter);
+ ni_writel(dev, bits, NI_M_PFI_FILTER_REG);
return 0;
}
switch (data[0]) {
case COMEDI_OUTPUT:
- ni_set_bits(dev, IO_Bidirection_Pin_Register, 1 << chan, 1);
+ ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, 1 << chan, 1);
break;
case COMEDI_INPUT:
- ni_set_bits(dev, IO_Bidirection_Pin_Register, 1 << chan, 0);
+ ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, 1 << chan, 0);
break;
case INSN_CONFIG_DIO_QUERY:
data[1] =
return -ENOTSUPP;
if (comedi_dio_update_state(s, data))
- ni_writew(dev, s->state, M_Offset_PFI_DO);
+ ni_writew(dev, s->state, NI_M_PFI_DO_REG);
- data[1] = ni_readw(dev, M_Offset_PFI_DI);
+ data[1] = ni_readw(dev, NI_M_PFI_DI_REG);
return insn->n;
}
int i;
for (i = 0; i < timeout; i++) {
- status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx);
- if ((status & CSS_ADC_BUSY) == 0)
+ status = ni_ao_win_inw(dev, NI67XX_CAL_STATUS_REG);
+ if ((status & NI67XX_CAL_STATUS_BUSY) == 0)
break;
set_current_state(TASK_INTERRUPTIBLE);
if (schedule_timeout(1))
static const int timeout = 100;
int i;
- ni_ao_win_outw(dev, value, CAL_ADC_Command_67xx);
+ ni_ao_win_outw(dev, value, NI67XX_CAL_CMD_REG);
/* give time for command to start being serially clocked into cs5529.
- * this insures that the CSS_ADC_BUSY bit will get properly
+ * this insures that the NI67XX_CAL_STATUS_BUSY bit will get properly
* set before we exit this function.
*/
for (i = 0; i < timeout; i++) {
- if ((ni_ao_win_inw(dev, CAL_ADC_Status_67xx) & CSS_ADC_BUSY))
+ if (ni_ao_win_inw(dev, NI67XX_CAL_STATUS_REG) &
+ NI67XX_CAL_STATUS_BUSY)
break;
udelay(1);
}
int retval;
unsigned short status;
- cs5529_command(dev, CSCMD_COMMAND | CSCMD_SINGLE_CONVERSION);
+ cs5529_command(dev, CS5529_CMD_CB | CS5529_CMD_SINGLE_CONV);
retval = cs5529_wait_for_idle(dev);
if (retval) {
dev_err(dev->class_dev,
"timeout or signal in cs5529_do_conversion()\n");
return -ETIME;
}
- status = ni_ao_win_inw(dev, CAL_ADC_Status_67xx);
- if (status & CSS_OSC_DETECT) {
+ status = ni_ao_win_inw(dev, NI67XX_CAL_STATUS_REG);
+ if (status & NI67XX_CAL_STATUS_OSC_DETECT) {
dev_err(dev->class_dev,
"cs5529 conversion error, status CSS_OSC_DETECT\n");
return -EIO;
}
- if (status & CSS_OVERRANGE) {
+ if (status & NI67XX_CAL_STATUS_OVERRANGE) {
dev_err(dev->class_dev,
"cs5529 conversion error, overrange (ignoring)\n");
}
if (data) {
- *data = ni_ao_win_inw(dev, CAL_ADC_Data_67xx);
+ *data = ni_ao_win_inw(dev, NI67XX_CAL_DATA_REG);
/* cs5529 returns 16 bit signed data in bipolar mode */
*data ^= (1 << 15);
}
channel_select = INTERNAL_REF;
else
channel_select = CR_CHAN(insn->chanspec);
- ni_ao_win_outw(dev, channel_select, AO_Calibration_Channel_Select_67xx);
+ ni_ao_win_outw(dev, channel_select, NI67XX_AO_CAL_CHAN_SEL_REG);
for (n = 0; n < insn->n; n++) {
retval = cs5529_do_conversion(dev, &sample);
static void cs5529_config_write(struct comedi_device *dev, unsigned int value,
unsigned int reg_select_bits)
{
- ni_ao_win_outw(dev, ((value >> 16) & 0xff),
- CAL_ADC_Config_Data_High_Word_67xx);
- ni_ao_win_outw(dev, (value & 0xffff),
- CAL_ADC_Config_Data_Low_Word_67xx);
- reg_select_bits &= CSCMD_REGISTER_SELECT_MASK;
- cs5529_command(dev, CSCMD_COMMAND | reg_select_bits);
+ ni_ao_win_outw(dev, (value >> 16) & 0xff, NI67XX_CAL_CFG_HI_REG);
+ ni_ao_win_outw(dev, value & 0xffff, NI67XX_CAL_CFG_LO_REG);
+ reg_select_bits &= CS5529_CMD_REG_MASK;
+ cs5529_command(dev, CS5529_CMD_CB | reg_select_bits);
if (cs5529_wait_for_idle(dev))
dev_err(dev->class_dev,
"timeout or signal in %s\n", __func__);
static int init_cs5529(struct comedi_device *dev)
{
- unsigned int config_bits =
- CSCFG_PORT_MODE | CSCFG_WORD_RATE_2180_CYCLES;
+ unsigned int config_bits = CS5529_CFG_PORT_FLAG |
+ CS5529_CFG_WORD_RATE_2180;
#if 1
/* do self-calibration */
- cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET_GAIN,
- CSCMD_CONFIG_REGISTER);
+ cs5529_config_write(dev, config_bits | CS5529_CFG_CALIB_BOTH_SELF,
+ CS5529_CFG_REG);
/* need to force a conversion for calibration to run */
cs5529_do_conversion(dev, NULL);
#else
/* force gain calibration to 1 */
- cs5529_config_write(dev, 0x400000, CSCMD_GAIN_REGISTER);
- cs5529_config_write(dev, config_bits | CSCFG_SELF_CAL_OFFSET,
- CSCMD_CONFIG_REGISTER);
+ cs5529_config_write(dev, 0x400000, CS5529_GAIN_REG);
+ cs5529_config_write(dev, config_bits | CS5529_CFG_CALIB_OFFSET_SELF,
+ CS5529_CFG_REG);
if (cs5529_wait_for_idle(dev))
dev_err(dev->class_dev,
"timeout or signal in %s\n", __func__);
{
unsigned div;
unsigned best_div = 1;
- static const unsigned max_div = 0x10;
unsigned mult;
unsigned best_mult = 1;
- static const unsigned max_mult = 0x100;
static const unsigned pico_per_nano = 1000;
const unsigned reference_picosec = reference_period_ns * pico_per_nano;
static const unsigned fudge_factor_80_to_20Mhz = 4;
int best_period_picosec = 0;
- for (div = 1; div <= max_div; ++div) {
- for (mult = 1; mult <= max_mult; ++mult) {
+ for (div = 1; div <= NI_M_PLL_MAX_DIVISOR; ++div) {
+ for (mult = 1; mult <= NI_M_PLL_MAX_MULTIPLIER; ++mult) {
unsigned new_period_ps =
(reference_picosec * div) / mult;
if (abs(new_period_ps - target_picosec) <
unsigned pll_control_bits;
unsigned freq_divider;
unsigned freq_multiplier;
+ unsigned rtsi;
unsigned i;
int retval;
__func__, min_period_ns, max_period_ns);
return -EINVAL;
}
- devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit;
+ devpriv->rtsi_trig_direction_reg &= ~NISTC_RTSI_TRIG_USE_CLK;
ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
- RTSI_Trig_Direction_Register);
- pll_control_bits =
- MSeries_PLL_Enable_Bit | MSeries_PLL_VCO_Mode_75_150MHz_Bits;
- devpriv->clock_and_fout2 |=
- MSeries_Timebase1_Select_Bit | MSeries_Timebase3_Select_Bit;
- devpriv->clock_and_fout2 &= ~MSeries_PLL_In_Source_Select_Mask;
+ NISTC_RTSI_TRIG_DIR_REG);
+ pll_control_bits = NI_M_PLL_CTRL_ENA | NI_M_PLL_CTRL_VCO_MODE_75_150MHZ;
+ devpriv->clock_and_fout2 |= NI_M_CLK_FOUT2_TIMEBASE1_PLL |
+ NI_M_CLK_FOUT2_TIMEBASE3_PLL;
+ devpriv->clock_and_fout2 &= ~NI_M_CLK_FOUT2_PLL_SRC_MASK;
switch (source) {
case NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK:
- devpriv->clock_and_fout2 |=
- MSeries_PLL_In_Source_Select_Star_Trigger_Bits;
+ devpriv->clock_and_fout2 |= NI_M_CLK_FOUT2_PLL_SRC_STAR;
break;
case NI_MIO_PLL_PXI10_CLOCK:
/* pxi clock is 10MHz */
- devpriv->clock_and_fout2 |=
- MSeries_PLL_In_Source_Select_PXI_Clock10;
+ devpriv->clock_and_fout2 |= NI_M_CLK_FOUT2_PLL_SRC_PXI10;
break;
default:
- {
- unsigned rtsi_channel;
- static const unsigned max_rtsi_channel = 7;
-
- for (rtsi_channel = 0; rtsi_channel <= max_rtsi_channel;
- ++rtsi_channel) {
- if (source ==
- NI_MIO_PLL_RTSI_CLOCK(rtsi_channel)) {
- devpriv->clock_and_fout2 |=
- MSeries_PLL_In_Source_Select_RTSI_Bits
- (rtsi_channel);
- break;
- }
+ for (rtsi = 0; rtsi <= NI_M_MAX_RTSI_CHAN; ++rtsi) {
+ if (source == NI_MIO_PLL_RTSI_CLOCK(rtsi)) {
+ devpriv->clock_and_fout2 |=
+ NI_M_CLK_FOUT2_PLL_SRC_RTSI(rtsi);
+ break;
}
- if (rtsi_channel > max_rtsi_channel)
- return -EINVAL;
}
+ if (rtsi > NI_M_MAX_RTSI_CHAN)
+ return -EINVAL;
break;
}
retval = ni_mseries_get_pll_parameters(period_ns,
return retval;
}
- ni_writew(dev, devpriv->clock_and_fout2, M_Offset_Clock_and_Fout2);
- pll_control_bits |=
- MSeries_PLL_Divisor_Bits(freq_divider) |
- MSeries_PLL_Multiplier_Bits(freq_multiplier);
+ ni_writew(dev, devpriv->clock_and_fout2, NI_M_CLK_FOUT2_REG);
+ pll_control_bits |= NI_M_PLL_CTRL_DIVISOR(freq_divider) |
+ NI_M_PLL_CTRL_MULTIPLIER(freq_multiplier);
- ni_writew(dev, pll_control_bits, M_Offset_PLL_Control);
+ ni_writew(dev, pll_control_bits, NI_M_PLL_CTRL_REG);
devpriv->clock_source = source;
/* it seems to typically take a few hundred microseconds for PLL to lock */
for (i = 0; i < timeout; ++i) {
- if (ni_readw(dev, M_Offset_PLL_Status) & MSeries_PLL_Locked_Bit)
+ if (ni_readw(dev, NI_M_PLL_STATUS_REG) & NI_M_PLL_STATUS_LOCKED)
break;
udelay(1);
}
struct ni_private *devpriv = dev->private;
if (source == NI_MIO_INTERNAL_CLOCK) {
- devpriv->rtsi_trig_direction_reg &= ~Use_RTSI_Clock_Bit;
+ devpriv->rtsi_trig_direction_reg &= ~NISTC_RTSI_TRIG_USE_CLK;
ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
- RTSI_Trig_Direction_Register);
+ NISTC_RTSI_TRIG_DIR_REG);
devpriv->clock_ns = TIMEBASE_1_NS;
if (devpriv->is_m_series) {
devpriv->clock_and_fout2 &=
- ~(MSeries_Timebase1_Select_Bit |
- MSeries_Timebase3_Select_Bit);
+ ~(NI_M_CLK_FOUT2_TIMEBASE1_PLL |
+ NI_M_CLK_FOUT2_TIMEBASE3_PLL);
ni_writew(dev, devpriv->clock_and_fout2,
- M_Offset_Clock_and_Fout2);
- ni_writew(dev, 0, M_Offset_PLL_Control);
+ NI_M_CLK_FOUT2_REG);
+ ni_writew(dev, 0, NI_M_PLL_CTRL_REG);
}
devpriv->clock_source = source;
} else {
} else {
if (source == NI_MIO_RTSI_CLOCK) {
devpriv->rtsi_trig_direction_reg |=
- Use_RTSI_Clock_Bit;
+ NISTC_RTSI_TRIG_USE_CLK;
ni_stc_writew(dev,
devpriv->rtsi_trig_direction_reg,
- RTSI_Trig_Direction_Register);
+ NISTC_RTSI_TRIG_DIR_REG);
if (period_ns == 0) {
dev_err(dev->class_dev,
"we don't handle an unspecified clock period correctly yet, returning error\n");
return 3;
}
-static unsigned num_configurable_rtsi_channels(struct comedi_device *dev)
-{
- struct ni_private *devpriv = dev->private;
-
- return (devpriv->is_m_series) ? 8 : 7;
-}
-
static int ni_valid_rtsi_output_source(struct comedi_device *dev,
unsigned chan, unsigned source)
{
struct ni_private *devpriv = dev->private;
- if (chan >= num_configurable_rtsi_channels(dev)) {
- if (chan == old_RTSI_clock_channel) {
+ if (chan >= NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) {
+ if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) {
if (source == NI_RTSI_OUTPUT_RTSI_OSC)
return 1;
dev_err(dev->class_dev,
"%s: invalid source for channel=%i, channel %i is always the RTSI clock for pre-m-series boards\n",
- __func__, chan, old_RTSI_clock_channel);
+ __func__, chan, NISTC_RTSI_TRIG_OLD_CLK_CHAN);
return 0;
}
return 0;
}
static int ni_set_rtsi_routing(struct comedi_device *dev,
- unsigned chan, unsigned source)
+ unsigned chan, unsigned src)
{
struct ni_private *devpriv = dev->private;
- if (ni_valid_rtsi_output_source(dev, chan, source) == 0)
+ if (ni_valid_rtsi_output_source(dev, chan, src) == 0)
return -EINVAL;
if (chan < 4) {
- devpriv->rtsi_trig_a_output_reg &= ~RTSI_Trig_Output_Mask(chan);
- devpriv->rtsi_trig_a_output_reg |=
- RTSI_Trig_Output_Bits(chan, source);
+ devpriv->rtsi_trig_a_output_reg &= ~NISTC_RTSI_TRIG_MASK(chan);
+ devpriv->rtsi_trig_a_output_reg |= NISTC_RTSI_TRIG(chan, src);
ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg,
- RTSI_Trig_A_Output_Register);
+ NISTC_RTSI_TRIGA_OUT_REG);
} else if (chan < 8) {
- devpriv->rtsi_trig_b_output_reg &= ~RTSI_Trig_Output_Mask(chan);
- devpriv->rtsi_trig_b_output_reg |=
- RTSI_Trig_Output_Bits(chan, source);
+ devpriv->rtsi_trig_b_output_reg &= ~NISTC_RTSI_TRIG_MASK(chan);
+ devpriv->rtsi_trig_b_output_reg |= NISTC_RTSI_TRIG(chan, src);
ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
- RTSI_Trig_B_Output_Register);
+ NISTC_RTSI_TRIGB_OUT_REG);
}
return 2;
}
struct ni_private *devpriv = dev->private;
if (chan < 4) {
- return RTSI_Trig_Output_Source(chan,
- devpriv->rtsi_trig_a_output_reg);
- } else if (chan < num_configurable_rtsi_channels(dev)) {
- return RTSI_Trig_Output_Source(chan,
- devpriv->rtsi_trig_b_output_reg);
+ return NISTC_RTSI_TRIG_TO_SRC(chan,
+ devpriv->rtsi_trig_a_output_reg);
+ } else if (chan < NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) {
+ return NISTC_RTSI_TRIG_TO_SRC(chan,
+ devpriv->rtsi_trig_b_output_reg);
} else {
- if (chan == old_RTSI_clock_channel)
+ if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN)
return NI_RTSI_OUTPUT_RTSI_OSC;
dev_err(dev->class_dev, "bug! should never get here?\n");
return 0;
{
struct ni_private *devpriv = dev->private;
unsigned int chan = CR_CHAN(insn->chanspec);
+ unsigned int max_chan = NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series);
switch (data[0]) {
case INSN_CONFIG_DIO_OUTPUT:
- if (chan < num_configurable_rtsi_channels(dev)) {
+ if (chan < max_chan) {
devpriv->rtsi_trig_direction_reg |=
- RTSI_Output_Bit(chan, devpriv->is_m_series);
- } else if (chan == old_RTSI_clock_channel) {
+ NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series);
+ } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) {
devpriv->rtsi_trig_direction_reg |=
- Drive_RTSI_Clock_Bit;
+ NISTC_RTSI_TRIG_DRV_CLK;
}
ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
- RTSI_Trig_Direction_Register);
+ NISTC_RTSI_TRIG_DIR_REG);
break;
case INSN_CONFIG_DIO_INPUT:
- if (chan < num_configurable_rtsi_channels(dev)) {
+ if (chan < max_chan) {
devpriv->rtsi_trig_direction_reg &=
- ~RTSI_Output_Bit(chan, devpriv->is_m_series);
- } else if (chan == old_RTSI_clock_channel) {
+ ~NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series);
+ } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) {
devpriv->rtsi_trig_direction_reg &=
- ~Drive_RTSI_Clock_Bit;
+ ~NISTC_RTSI_TRIG_DRV_CLK;
}
ni_stc_writew(dev, devpriv->rtsi_trig_direction_reg,
- RTSI_Trig_Direction_Register);
+ NISTC_RTSI_TRIG_DIR_REG);
break;
case INSN_CONFIG_DIO_QUERY:
- if (chan < num_configurable_rtsi_channels(dev)) {
+ if (chan < max_chan) {
data[1] =
(devpriv->rtsi_trig_direction_reg &
- RTSI_Output_Bit(chan, devpriv->is_m_series))
+ NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series))
? INSN_CONFIG_DIO_OUTPUT
: INSN_CONFIG_DIO_INPUT;
- } else if (chan == old_RTSI_clock_channel) {
- data[1] =
- (devpriv->rtsi_trig_direction_reg &
- Drive_RTSI_Clock_Bit)
- ? INSN_CONFIG_DIO_OUTPUT : INSN_CONFIG_DIO_INPUT;
+ } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) {
+ data[1] = (devpriv->rtsi_trig_direction_reg &
+ NISTC_RTSI_TRIG_DRV_CLK)
+ ? INSN_CONFIG_DIO_OUTPUT
+ : INSN_CONFIG_DIO_INPUT;
}
return 2;
case INSN_CONFIG_SET_CLOCK_SRC:
/* Initialises the RTSI bus signal switch to a default state */
+ /*
+ * Use 10MHz instead of 20MHz for RTSI clock frequency. Appears
+ * to have no effect, at least on pxi-6281, which always uses
+ * 20MHz rtsi clock frequency
+ */
+ devpriv->clock_and_fout2 = NI_M_CLK_FOUT2_RTSI_10MHZ;
/* Set clock mode to internal */
- devpriv->clock_and_fout2 = MSeries_RTSI_10MHz_Bit;
if (ni_set_master_clock(dev, NI_MIO_INTERNAL_CLOCK, 0) < 0)
dev_err(dev->class_dev, "ni_set_master_clock failed, bug?\n");
/* default internal lines routing to RTSI bus lines */
devpriv->rtsi_trig_a_output_reg =
- RTSI_Trig_Output_Bits(0,
- NI_RTSI_OUTPUT_ADR_START1) |
- RTSI_Trig_Output_Bits(1,
- NI_RTSI_OUTPUT_ADR_START2) |
- RTSI_Trig_Output_Bits(2,
- NI_RTSI_OUTPUT_SCLKG) |
- RTSI_Trig_Output_Bits(3, NI_RTSI_OUTPUT_DACUPDN);
+ NISTC_RTSI_TRIG(0, NI_RTSI_OUTPUT_ADR_START1) |
+ NISTC_RTSI_TRIG(1, NI_RTSI_OUTPUT_ADR_START2) |
+ NISTC_RTSI_TRIG(2, NI_RTSI_OUTPUT_SCLKG) |
+ NISTC_RTSI_TRIG(3, NI_RTSI_OUTPUT_DACUPDN);
ni_stc_writew(dev, devpriv->rtsi_trig_a_output_reg,
- RTSI_Trig_A_Output_Register);
+ NISTC_RTSI_TRIGA_OUT_REG);
devpriv->rtsi_trig_b_output_reg =
- RTSI_Trig_Output_Bits(4,
- NI_RTSI_OUTPUT_DA_START1) |
- RTSI_Trig_Output_Bits(5,
- NI_RTSI_OUTPUT_G_SRC0) |
- RTSI_Trig_Output_Bits(6, NI_RTSI_OUTPUT_G_GATE0);
+ NISTC_RTSI_TRIG(4, NI_RTSI_OUTPUT_DA_START1) |
+ NISTC_RTSI_TRIG(5, NI_RTSI_OUTPUT_G_SRC0) |
+ NISTC_RTSI_TRIG(6, NI_RTSI_OUTPUT_G_GATE0);
if (devpriv->is_m_series)
devpriv->rtsi_trig_b_output_reg |=
- RTSI_Trig_Output_Bits(7, NI_RTSI_OUTPUT_RTSI_OSC);
+ NISTC_RTSI_TRIG(7, NI_RTSI_OUTPUT_RTSI_OSC);
ni_stc_writew(dev, devpriv->rtsi_trig_b_output_reg,
- RTSI_Trig_B_Output_Register);
+ NISTC_RTSI_TRIGB_OUT_REG);
-/*
-* Sets the source and direction of the 4 on board lines
-* ni_stc_writew(dev, 0x0000, RTSI_Board_Register);
-*/
+ /*
+ * Sets the source and direction of the 4 on board lines
+ * ni_stc_writew(dev, 0, NISTC_RTSI_BOARD_REG);
+ */
}
#ifdef PCIDMA
}
#endif
-#if 0
-/*
- * Read the GPCTs current value.
- */
-static int GPCT_G_Watch(struct comedi_device *dev, int chan)
-{
- unsigned int hi1, hi2, lo;
-
- devpriv->gpct_command[chan] &= ~G_Save_Trace;
- ni_stc_writew(dev, devpriv->gpct_command[chan],
- G_Command_Register(chan));
-
- devpriv->gpct_command[chan] |= G_Save_Trace;
- ni_stc_writew(dev, devpriv->gpct_command[chan],
- G_Command_Register(chan));
-
- /* This procedure is used because the two registers cannot
- * be read atomically. */
- do {
- hi1 = ni_stc_readw(dev, G_Save_Register_High(chan));
- lo = ni_stc_readw(dev, G_Save_Register_Low(chan));
- hi2 = ni_stc_readw(dev, G_Save_Register_High(chan));
- } while (hi1 != hi2);
-
- return (hi1 << 16) | lo;
-}
-
-static void GPCT_Reset(struct comedi_device *dev, int chan)
-{
- int temp_ack_reg = 0;
-
- devpriv->gpct_cur_operation[chan] = GPCT_RESET;
-
- switch (chan) {
- case 0:
- ni_stc_writew(dev, G0_Reset, Joint_Reset_Register);
- ni_set_bits(dev, Interrupt_A_Enable_Register,
- G0_TC_Interrupt_Enable, 0);
- ni_set_bits(dev, Interrupt_A_Enable_Register,
- G0_Gate_Interrupt_Enable, 0);
- temp_ack_reg |= G0_Gate_Error_Confirm;
- temp_ack_reg |= G0_TC_Error_Confirm;
- temp_ack_reg |= G0_TC_Interrupt_Ack;
- temp_ack_reg |= G0_Gate_Interrupt_Ack;
- ni_stc_writew(dev, temp_ack_reg, Interrupt_A_Ack_Register);
-
- /* problem...this interferes with the other ctr... */
- devpriv->an_trig_etc_reg |= GPFO_0_Output_Enable;
- ni_stc_writew(dev, devpriv->an_trig_etc_reg,
- Analog_Trigger_Etc_Register);
- break;
- case 1:
- ni_stc_writew(dev, G1_Reset, Joint_Reset_Register);
- ni_set_bits(dev, Interrupt_B_Enable_Register,
- G1_TC_Interrupt_Enable, 0);
- ni_set_bits(dev, Interrupt_B_Enable_Register,
- G0_Gate_Interrupt_Enable, 0);
- temp_ack_reg |= G1_Gate_Error_Confirm;
- temp_ack_reg |= G1_TC_Error_Confirm;
- temp_ack_reg |= G1_TC_Interrupt_Ack;
- temp_ack_reg |= G1_Gate_Interrupt_Ack;
- ni_stc_writew(dev, temp_ack_reg, Interrupt_B_Ack_Register);
-
- devpriv->an_trig_etc_reg |= GPFO_1_Output_Enable;
- ni_stc_writew(dev, devpriv->an_trig_etc_reg,
- Analog_Trigger_Etc_Register);
- break;
- }
-
- devpriv->gpct_mode[chan] = 0;
- devpriv->gpct_input_select[chan] = 0;
- devpriv->gpct_command[chan] = 0;
-
- devpriv->gpct_command[chan] |= G_Synchronized_Gate;
-
- ni_stc_writew(dev, devpriv->gpct_mode[chan], G_Mode_Register(chan));
- ni_stc_writew(dev, devpriv->gpct_input_select[chan],
- G_Input_Select_Register(chan));
- ni_stc_writew(dev, 0, G_Autoincrement_Register(chan));
-}
-#endif
-
static irqreturn_t ni_E_interrupt(int irq, void *d)
{
struct comedi_device *dev = d;
/* lock to avoid race with comedi_poll */
spin_lock_irqsave(&dev->spinlock, flags);
- a_status = ni_stc_readw(dev, AI_Status_1_Register);
- b_status = ni_stc_readw(dev, AO_Status_1_Register);
+ a_status = ni_stc_readw(dev, NISTC_AI_STATUS1_REG);
+ b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG);
#ifdef PCIDMA
if (mite) {
struct ni_private *devpriv = dev->private;
#endif
ack_a_interrupt(dev, a_status);
ack_b_interrupt(dev, b_status);
- if ((a_status & Interrupt_A_St) || (ai_mite_status & CHSR_INT))
+ if ((a_status & NISTC_AI_STATUS1_INTA) || (ai_mite_status & CHSR_INT))
handle_a_interrupt(dev, a_status, ai_mite_status);
- if ((b_status & Interrupt_B_St) || (ao_mite_status & CHSR_INT))
+ if ((b_status & NISTC_AO_STATUS1_INTB) || (ao_mite_status & CHSR_INT))
handle_b_interrupt(dev, b_status, ao_mite_status);
handle_gpct_interrupt(dev, 0);
handle_gpct_interrupt(dev, 1);
}
/* initialize clock dividers */
- devpriv->clock_and_fout = Slow_Internal_Time_Divide_By_2 |
- Slow_Internal_Timebase |
- Clock_To_Board_Divide_By_2 |
- Clock_To_Board;
+ devpriv->clock_and_fout = NISTC_CLK_FOUT_SLOW_DIV2 |
+ NISTC_CLK_FOUT_SLOW_TIMEBASE |
+ NISTC_CLK_FOUT_TO_BOARD_DIV2 |
+ NISTC_CLK_FOUT_TO_BOARD;
if (!devpriv->is_6xxx) {
/* BEAM is this needed for PCI-6143 ?? */
- devpriv->clock_and_fout |= (AI_Output_Divide_By_2 |
- AO_Output_Divide_By_2);
+ devpriv->clock_and_fout |= (NISTC_CLK_FOUT_AI_OUT_DIV2 |
+ NISTC_CLK_FOUT_AO_OUT_DIV2);
}
- ni_stc_writew(dev, devpriv->clock_and_fout, Clock_and_FOUT_Register);
+ ni_stc_writew(dev, devpriv->clock_and_fout, NISTC_CLK_FOUT_REG);
ret = comedi_alloc_subdevices(dev, NI_NUM_SUBDEVICES);
if (ret)
}
/* reset DIO and set all channels to inputs */
- ni_writel(dev, CDO_Reset_Bit | CDI_Reset_Bit,
- M_Offset_CDIO_Command);
- ni_writel(dev, s->io_bits, M_Offset_DIO_Direction);
+ ni_writel(dev, NI_M_CDO_CMD_RESET |
+ NI_M_CDI_CMD_RESET,
+ NI_M_CDIO_CMD_REG);
+ ni_writel(dev, s->io_bits, NI_M_DIO_DIR_REG);
} else {
s->insn_bits = ni_dio_insn_bits;
s->insn_config = ni_dio_insn_config;
/* set all channels to inputs */
- devpriv->dio_control = DIO_Pins_Dir(s->io_bits);
- ni_writew(dev, devpriv->dio_control, DIO_Control_Register);
+ devpriv->dio_control = NISTC_DIO_CTRL_DIR(s->io_bits);
+ ni_writew(dev, devpriv->dio_control, NISTC_DIO_CTRL_REG);
}
/* 8255 device */
s = &dev->subdevices[NI_8255_DIO_SUBDEV];
if (board->has_8255) {
- ret = subdev_8255_init(dev, s, ni_8255_callback, Port_A);
+ ret = subdev_8255_init(dev, s, ni_8255_callback,
+ NI_E_8255_BASE);
if (ret)
return ret;
} else {
/* internal PWM output used for AI nonlinearity calibration */
s->insn_config = ni_m_series_pwm_config;
- ni_writel(dev, 0x0, M_Offset_Cal_PWM);
+ ni_writel(dev, 0x0, NI_M_CAL_PWM_REG);
} else if (devpriv->is_6143) {
/* internal PWM output used for AI nonlinearity calibration */
s->insn_config = ni_6143_pwm_config;
s->n_chan = 16;
s->insn_bits = ni_pfi_insn_bits;
- ni_writew(dev, s->state, M_Offset_PFI_DO);
+ ni_writew(dev, s->state, NI_M_PFI_DO_REG);
for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) {
ni_writew(dev, devpriv->pfi_output_select_reg[i],
- M_Offset_PFI_Output_Select(i + 1));
+ NI_M_PFI_OUT_SEL_REG(i));
}
} else {
s->n_chan = 10;
}
s->insn_config = ni_pfi_insn_config;
- ni_set_bits(dev, IO_Bidirection_Pin_Register, ~0, 0);
+ ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, ~0, 0);
/* cs5529 calibration adc */
s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV];
if (dev->irq) {
ni_stc_writew(dev,
- (irq_polarity ? Interrupt_Output_Polarity : 0) |
- (Interrupt_Output_On_3_Pins & 0) |
- Interrupt_A_Enable | Interrupt_B_Enable |
- Interrupt_A_Output_Select(interrupt_pin) |
- Interrupt_B_Output_Select(interrupt_pin),
- Interrupt_Control_Register);
+ (irq_polarity ? NISTC_INT_CTRL_INT_POL : 0) |
+ (NISTC_INT_CTRL_3PIN_INT & 0) |
+ NISTC_INT_CTRL_INTA_ENA |
+ NISTC_INT_CTRL_INTB_ENA |
+ NISTC_INT_CTRL_INTA_SEL(interrupt_pin) |
+ NISTC_INT_CTRL_INTB_SEL(interrupt_pin),
+ NISTC_INT_CTRL_REG);
}
/* DMA setup */
- ni_writeb(dev, devpriv->ai_ao_select_reg, AI_AO_Select);
- ni_writeb(dev, devpriv->g0_g1_select_reg, G0_G1_Select);
+ ni_writeb(dev, devpriv->ai_ao_select_reg, NI_E_DMA_AI_AO_SEL_REG);
+ ni_writeb(dev, devpriv->g0_g1_select_reg, NI_E_DMA_G0_G1_SEL_REG);
if (devpriv->is_6xxx) {
- ni_writeb(dev, 0, Magic_611x);
+ ni_writeb(dev, 0, NI611X_MAGIC_REG);
} else if (devpriv->is_m_series) {
int channel;
for (channel = 0; channel < board->n_aochan; ++channel) {
ni_writeb(dev, 0xf,
- M_Offset_AO_Waveform_Order(channel));
+ NI_M_AO_WAVEFORM_ORDER_REG(channel));
ni_writeb(dev, 0x0,
- M_Offset_AO_Reference_Attenuation(channel));
+ NI_M_AO_REF_ATTENUATION_REG(channel));
}
- ni_writeb(dev, 0x0, M_Offset_AO_Calibration);
+ ni_writeb(dev, 0x0, NI_M_AO_CALIB_REG);
}
return 0;
struct ni_private *devpriv = dev->private;
/* Disable interrupts */
- ni_stc_writew(dev, 0, Interrupt_Control_Register);
+ ni_stc_writew(dev, 0, NISTC_INT_CTRL_REG);
/* Initialise 6143 AI specific bits */
/* Set G0,G1 DMA mode to E series version */
- ni_writeb(dev, 0x00, Magic_6143);
+ ni_writeb(dev, 0x00, NI6143_MAGIC_REG);
/* Set EOCMode, ADCMode and pipelinedelay */
- ni_writeb(dev, 0x80, PipelineDelay_6143);
+ ni_writeb(dev, 0x80, NI6143_PIPELINE_DELAY_REG);
/* Set EOC Delay */
- ni_writeb(dev, 0x00, EOC_Set_6143);
+ ni_writeb(dev, 0x00, NI6143_EOC_SET_REG);
/* Set the FIFO half full level */
- ni_writel(dev, board->ai_fifo_depth / 2, AIFIFO_Flag_6143);
+ ni_writel(dev, board->ai_fifo_depth / 2, NI6143_AI_FIFO_FLAG_REG);
/* Strobe Relay disable bit */
devpriv->ai_calib_source_enabled = 0;
- ni_writew(dev, devpriv->ai_calib_source |
- Calibration_Channel_6143_RelayOff,
- Calibration_Channel_6143);
- ni_writew(dev, devpriv->ai_calib_source, Calibration_Channel_6143);
+ ni_writew(dev, devpriv->ai_calib_source | NI6143_CALIB_CHAN_RELAY_OFF,
+ NI6143_CALIB_CHAN_REG);
+ ni_writew(dev, devpriv->ai_calib_source, NI6143_CALIB_CHAN_REG);
}
static void pcimio_detach(struct comedi_device *dev)
#include "ni_tio.h"
-#define _bit15 0x8000
-#define _bit14 0x4000
-#define _bit13 0x2000
-#define _bit12 0x1000
-#define _bit11 0x0800
-#define _bit10 0x0400
-#define _bit9 0x0200
-#define _bit8 0x0100
-#define _bit7 0x0080
-#define _bit6 0x0040
-#define _bit5 0x0020
-#define _bit4 0x0010
-#define _bit3 0x0008
-#define _bit2 0x0004
-#define _bit1 0x0002
-#define _bit0 0x0001
-
-#define NUM_PFI_OUTPUT_SELECT_REGS 6
-
-/* Registers in the National Instruments DAQ-STC chip */
-
-#define Interrupt_A_Ack_Register 2
-#define G0_Gate_Interrupt_Ack _bit15
-#define G0_TC_Interrupt_Ack _bit14
-#define AI_Error_Interrupt_Ack _bit13
-#define AI_STOP_Interrupt_Ack _bit12
-#define AI_START_Interrupt_Ack _bit11
-#define AI_START2_Interrupt_Ack _bit10
-#define AI_START1_Interrupt_Ack _bit9
-#define AI_SC_TC_Interrupt_Ack _bit8
-#define AI_SC_TC_Error_Confirm _bit7
-#define G0_TC_Error_Confirm _bit6
-#define G0_Gate_Error_Confirm _bit5
-
-#define AI_Status_1_Register 2
-#define Interrupt_A_St 0x8000
-#define AI_FIFO_Full_St 0x4000
-#define AI_FIFO_Half_Full_St 0x2000
-#define AI_FIFO_Empty_St 0x1000
-#define AI_Overrun_St 0x0800
-#define AI_Overflow_St 0x0400
-#define AI_SC_TC_Error_St 0x0200
-#define AI_START2_St 0x0100
-#define AI_START1_St 0x0080
-#define AI_SC_TC_St 0x0040
-#define AI_START_St 0x0020
-#define AI_STOP_St 0x0010
-#define G0_TC_St 0x0008
-#define G0_Gate_Interrupt_St 0x0004
-#define AI_FIFO_Request_St 0x0002
-#define Pass_Thru_0_Interrupt_St 0x0001
-
-#define AI_Status_2_Register 5
-
-#define Interrupt_B_Ack_Register 3
-enum Interrupt_B_Ack_Bits {
- G1_Gate_Error_Confirm = _bit1,
- G1_TC_Error_Confirm = _bit2,
- AO_BC_TC_Trigger_Error_Confirm = _bit3,
- AO_BC_TC_Error_Confirm = _bit4,
- AO_UI2_TC_Error_Confrim = _bit5,
- AO_UI2_TC_Interrupt_Ack = _bit6,
- AO_UC_TC_Interrupt_Ack = _bit7,
- AO_BC_TC_Interrupt_Ack = _bit8,
- AO_START1_Interrupt_Ack = _bit9,
- AO_UPDATE_Interrupt_Ack = _bit10,
- AO_START_Interrupt_Ack = _bit11,
- AO_STOP_Interrupt_Ack = _bit12,
- AO_Error_Interrupt_Ack = _bit13,
- G1_TC_Interrupt_Ack = _bit14,
- G1_Gate_Interrupt_Ack = _bit15
-};
-
-#define AO_Status_1_Register 3
-#define Interrupt_B_St _bit15
-#define AO_FIFO_Full_St _bit14
-#define AO_FIFO_Half_Full_St _bit13
-#define AO_FIFO_Empty_St _bit12
-#define AO_BC_TC_Error_St _bit11
-#define AO_START_St _bit10
-#define AO_Overrun_St _bit9
-#define AO_START1_St _bit8
-#define AO_BC_TC_St _bit7
-#define AO_UC_TC_St _bit6
-#define AO_UPDATE_St _bit5
-#define AO_UI2_TC_St _bit4
-#define G1_TC_St _bit3
-#define G1_Gate_Interrupt_St _bit2
-#define AO_FIFO_Request_St _bit1
-#define Pass_Thru_1_Interrupt_St _bit0
-
-#define AI_Command_2_Register 4
-#define AI_End_On_SC_TC _bit15
-#define AI_End_On_End_Of_Scan _bit14
-#define AI_START1_Disable _bit11
-#define AI_SC_Save_Trace _bit10
-#define AI_SI_Switch_Load_On_SC_TC _bit9
-#define AI_SI_Switch_Load_On_STOP _bit8
-#define AI_SI_Switch_Load_On_TC _bit7
-#define AI_SC_Switch_Load_On_TC _bit4
-#define AI_STOP_Pulse _bit3
-#define AI_START_Pulse _bit2
-#define AI_START2_Pulse _bit1
-#define AI_START1_Pulse _bit0
-
-#define AO_Command_2_Register 5
-#define AO_End_On_BC_TC(x) (((x) & 0x3) << 14)
-#define AO_Start_Stop_Gate_Enable _bit13
-#define AO_UC_Save_Trace _bit12
-#define AO_BC_Gate_Enable _bit11
-#define AO_BC_Save_Trace _bit10
-#define AO_UI_Switch_Load_On_BC_TC _bit9
-#define AO_UI_Switch_Load_On_Stop _bit8
-#define AO_UI_Switch_Load_On_TC _bit7
-#define AO_UC_Switch_Load_On_BC_TC _bit6
-#define AO_UC_Switch_Load_On_TC _bit5
-#define AO_BC_Switch_Load_On_TC _bit4
-#define AO_Mute_B _bit3
-#define AO_Mute_A _bit2
-#define AO_UPDATE2_Pulse _bit1
-#define AO_START1_Pulse _bit0
-
-#define AO_Status_2_Register 6
-
-#define DIO_Parallel_Input_Register 7
-
-#define AI_Command_1_Register 8
-#define AI_Analog_Trigger_Reset _bit14
-#define AI_Disarm _bit13
-#define AI_SI2_Arm _bit12
-#define AI_SI2_Load _bit11
-#define AI_SI_Arm _bit10
-#define AI_SI_Load _bit9
-#define AI_DIV_Arm _bit8
-#define AI_DIV_Load _bit7
-#define AI_SC_Arm _bit6
-#define AI_SC_Load _bit5
-#define AI_SCAN_IN_PROG_Pulse _bit4
-#define AI_EXTMUX_CLK_Pulse _bit3
-#define AI_LOCALMUX_CLK_Pulse _bit2
-#define AI_SC_TC_Pulse _bit1
-#define AI_CONVERT_Pulse _bit0
-
-#define AO_Command_1_Register 9
-#define AO_Analog_Trigger_Reset _bit15
-#define AO_START_Pulse _bit14
-#define AO_Disarm _bit13
-#define AO_UI2_Arm_Disarm _bit12
-#define AO_UI2_Load _bit11
-#define AO_UI_Arm _bit10
-#define AO_UI_Load _bit9
-#define AO_UC_Arm _bit8
-#define AO_UC_Load _bit7
-#define AO_BC_Arm _bit6
-#define AO_BC_Load _bit5
-#define AO_DAC1_Update_Mode _bit4
-#define AO_LDAC1_Source_Select _bit3
-#define AO_DAC0_Update_Mode _bit2
-#define AO_LDAC0_Source_Select _bit1
-#define AO_UPDATE_Pulse _bit0
-
-#define DIO_Output_Register 10
-#define DIO_Parallel_Data_Out(a) ((a)&0xff)
-#define DIO_Parallel_Data_Mask 0xff
-#define DIO_SDOUT _bit0
-#define DIO_SDIN _bit4
-#define DIO_Serial_Data_Out(a) (((a)&0xff)<<8)
-#define DIO_Serial_Data_Mask 0xff00
-
-#define DIO_Control_Register 11
-#define DIO_Software_Serial_Control _bit11
-#define DIO_HW_Serial_Timebase _bit10
-#define DIO_HW_Serial_Enable _bit9
-#define DIO_HW_Serial_Start _bit8
-#define DIO_Pins_Dir(a) ((a)&0xff)
-#define DIO_Pins_Dir_Mask 0xff
-
-#define AI_Mode_1_Register 12
-#define AI_CONVERT_Source_Select(a) (((a) & 0x1f) << 11)
-#define AI_SI_Source_select(a) (((a) & 0x1f) << 6)
-#define AI_CONVERT_Source_Polarity _bit5
-#define AI_SI_Source_Polarity _bit4
-#define AI_Start_Stop _bit3
-#define AI_Mode_1_Reserved _bit2
-#define AI_Continuous _bit1
-#define AI_Trigger_Once _bit0
-
-#define AI_Mode_2_Register 13
-#define AI_SC_Gate_Enable _bit15
-#define AI_Start_Stop_Gate_Enable _bit14
-#define AI_Pre_Trigger _bit13
-#define AI_External_MUX_Present _bit12
-#define AI_SI2_Initial_Load_Source _bit9
-#define AI_SI2_Reload_Mode _bit8
-#define AI_SI_Initial_Load_Source _bit7
-#define AI_SI_Reload_Mode(a) (((a) & 0x7)<<4)
-#define AI_SI_Write_Switch _bit3
-#define AI_SC_Initial_Load_Source _bit2
-#define AI_SC_Reload_Mode _bit1
-#define AI_SC_Write_Switch _bit0
-
-#define AI_SI_Load_A_Registers 14
-#define AI_SI_Load_B_Registers 16
-#define AI_SC_Load_A_Registers 18
-#define AI_SC_Load_B_Registers 20
-#define AI_SI_Save_Registers 64
-#define AI_SC_Save_Registers 66
-
-#define AI_SI2_Load_A_Register 23
-#define AI_SI2_Load_B_Register 25
-
-#define Joint_Status_1_Register 27
-#define DIO_Serial_IO_In_Progress_St _bit12
-
-#define DIO_Serial_Input_Register 28
-#define Joint_Status_2_Register 29
-enum Joint_Status_2_Bits {
- AO_TMRDACWRs_In_Progress_St = 0x20,
-};
-
-#define AO_Mode_1_Register 38
-#define AO_UPDATE_Source_Select(x) (((x)&0x1f)<<11)
-#define AO_UI_Source_Select(x) (((x)&0x1f)<<6)
-#define AO_Multiple_Channels _bit5
-#define AO_UPDATE_Source_Polarity _bit4
-#define AO_UI_Source_Polarity _bit3
-#define AO_UC_Switch_Load_Every_TC _bit2
-#define AO_Continuous _bit1
-#define AO_Trigger_Once _bit0
-
-#define AO_Mode_2_Register 39
-#define AO_FIFO_Mode_Mask (0x3 << 14)
-enum AO_FIFO_Mode_Bits {
- AO_FIFO_Mode_HF_to_F = (3 << 14),
- AO_FIFO_Mode_F = (2 << 14),
- AO_FIFO_Mode_HF = (1 << 14),
- AO_FIFO_Mode_E = (0 << 14),
-};
-#define AO_FIFO_Retransmit_Enable _bit13
-#define AO_START1_Disable _bit12
-#define AO_UC_Initial_Load_Source _bit11
-#define AO_UC_Write_Switch _bit10
-#define AO_UI2_Initial_Load_Source _bit9
-#define AO_UI2_Reload_Mode _bit8
-#define AO_UI_Initial_Load_Source _bit7
-#define AO_UI_Reload_Mode(x) (((x) & 0x7) << 4)
-#define AO_UI_Write_Switch _bit3
-#define AO_BC_Initial_Load_Source _bit2
-#define AO_BC_Reload_Mode _bit1
-#define AO_BC_Write_Switch _bit0
-
-#define AO_UI_Load_A_Register 40
-#define AO_UI_Load_A_Register_High 40
-#define AO_UI_Load_A_Register_Low 41
-#define AO_UI_Load_B_Register 42
-#define AO_UI_Save_Registers 16
-#define AO_BC_Load_A_Register 44
-#define AO_BC_Load_A_Register_High 44
-#define AO_BC_Load_A_Register_Low 45
-#define AO_BC_Load_B_Register 46
-#define AO_BC_Load_B_Register_High 46
-#define AO_BC_Load_B_Register_Low 47
-#define AO_BC_Save_Registers 18
-#define AO_UC_Load_A_Register 48
-#define AO_UC_Load_A_Register_High 48
-#define AO_UC_Load_A_Register_Low 49
-#define AO_UC_Load_B_Register 50
-#define AO_UC_Save_Registers 20
-
-#define Clock_and_FOUT_Register 56
-enum Clock_and_FOUT_bits {
- FOUT_Enable = _bit15,
- FOUT_Timebase_Select = _bit14,
- DIO_Serial_Out_Divide_By_2 = _bit13,
- Slow_Internal_Time_Divide_By_2 = _bit12,
- Slow_Internal_Timebase = _bit11,
- G_Source_Divide_By_2 = _bit10,
- Clock_To_Board_Divide_By_2 = _bit9,
- Clock_To_Board = _bit8,
- AI_Output_Divide_By_2 = _bit7,
- AI_Source_Divide_By_2 = _bit6,
- AO_Output_Divide_By_2 = _bit5,
- AO_Source_Divide_By_2 = _bit4,
- FOUT_Divider_mask = 0xf
-};
-static inline unsigned FOUT_Divider(unsigned divider)
-{
- return divider & FOUT_Divider_mask;
-}
-
-#define IO_Bidirection_Pin_Register 57
-#define RTSI_Trig_Direction_Register 58
-enum RTSI_Trig_Direction_Bits {
- Drive_RTSI_Clock_Bit = 0x1,
- Use_RTSI_Clock_Bit = 0x2,
-};
-static inline unsigned RTSI_Output_Bit(unsigned channel, int is_mseries)
-{
- unsigned max_channel;
- unsigned base_bit_shift;
- if (is_mseries) {
- base_bit_shift = 8;
- max_channel = 7;
- } else {
- base_bit_shift = 9;
- max_channel = 6;
- }
- if (channel > max_channel) {
- pr_err("%s: bug, invalid RTSI_channel=%i\n", __func__, channel);
- return 0;
- }
- return 1 << (base_bit_shift + channel);
-}
-
-#define Interrupt_Control_Register 59
-#define Interrupt_B_Enable _bit15
-#define Interrupt_B_Output_Select(x) ((x)<<12)
-#define Interrupt_A_Enable _bit11
-#define Interrupt_A_Output_Select(x) ((x)<<8)
-#define Pass_Thru_0_Interrupt_Polarity _bit3
-#define Pass_Thru_1_Interrupt_Polarity _bit2
-#define Interrupt_Output_On_3_Pins _bit1
-#define Interrupt_Output_Polarity _bit0
-
-#define AI_Output_Control_Register 60
-#define AI_START_Output_Select _bit10
-#define AI_SCAN_IN_PROG_Output_Select(x) (((x) & 0x3) << 8)
-#define AI_EXTMUX_CLK_Output_Select(x) (((x) & 0x3) << 6)
-#define AI_LOCALMUX_CLK_Output_Select(x) ((x)<<4)
-#define AI_SC_TC_Output_Select(x) ((x)<<2)
-enum ai_convert_output_selection {
- AI_CONVERT_Output_High_Z = 0,
- AI_CONVERT_Output_Ground = 1,
- AI_CONVERT_Output_Enable_Low = 2,
- AI_CONVERT_Output_Enable_High = 3
-};
-static unsigned AI_CONVERT_Output_Select(enum ai_convert_output_selection
- selection)
-{
- return selection & 0x3;
-}
-
-#define AI_START_STOP_Select_Register 62
-#define AI_START_Polarity _bit15
-#define AI_STOP_Polarity _bit14
-#define AI_STOP_Sync _bit13
-#define AI_STOP_Edge _bit12
-#define AI_STOP_Select(a) (((a) & 0x1f)<<7)
-#define AI_START_Sync _bit6
-#define AI_START_Edge _bit5
-#define AI_START_Select(a) ((a) & 0x1f)
-
-#define AI_Trigger_Select_Register 63
-#define AI_START1_Polarity _bit15
-#define AI_START2_Polarity _bit14
-#define AI_START2_Sync _bit13
-#define AI_START2_Edge _bit12
-#define AI_START2_Select(a) (((a) & 0x1f) << 7)
-#define AI_START1_Sync _bit6
-#define AI_START1_Edge _bit5
-#define AI_START1_Select(a) ((a) & 0x1f)
-
-#define AI_DIV_Load_A_Register 64
-
-#define AO_Start_Select_Register 66
-#define AO_UI2_Software_Gate _bit15
-#define AO_UI2_External_Gate_Polarity _bit14
-#define AO_START_Polarity _bit13
-#define AO_AOFREQ_Enable _bit12
-#define AO_UI2_External_Gate_Select(a) (((a) & 0x1f) << 7)
-#define AO_START_Sync _bit6
-#define AO_START_Edge _bit5
-#define AO_START_Select(a) ((a) & 0x1f)
-
-#define AO_Trigger_Select_Register 67
-#define AO_UI2_External_Gate_Enable _bit15
-#define AO_Delayed_START1 _bit14
-#define AO_START1_Polarity _bit13
-#define AO_UI2_Source_Polarity _bit12
-#define AO_UI2_Source_Select(x) (((x)&0x1f)<<7)
-#define AO_START1_Sync _bit6
-#define AO_START1_Edge _bit5
-#define AO_START1_Select(x) (((x)&0x1f)<<0)
-
-#define AO_Mode_3_Register 70
-#define AO_UI2_Switch_Load_Next_TC _bit13
-#define AO_UC_Switch_Load_Every_BC_TC _bit12
-#define AO_Trigger_Length _bit11
-#define AO_Stop_On_Overrun_Error _bit5
-#define AO_Stop_On_BC_TC_Trigger_Error _bit4
-#define AO_Stop_On_BC_TC_Error _bit3
-#define AO_Not_An_UPDATE _bit2
-#define AO_Software_Gate _bit1
-#define AO_Last_Gate_Disable _bit0 /* M Series only */
-
-#define Joint_Reset_Register 72
-#define Software_Reset _bit11
-#define AO_Configuration_End _bit9
-#define AI_Configuration_End _bit8
-#define AO_Configuration_Start _bit5
-#define AI_Configuration_Start _bit4
-#define G1_Reset _bit3
-#define G0_Reset _bit2
-#define AO_Reset _bit1
-#define AI_Reset _bit0
-
-#define Interrupt_A_Enable_Register 73
-#define Pass_Thru_0_Interrupt_Enable _bit9
-#define G0_Gate_Interrupt_Enable _bit8
-#define AI_FIFO_Interrupt_Enable _bit7
-#define G0_TC_Interrupt_Enable _bit6
-#define AI_Error_Interrupt_Enable _bit5
-#define AI_STOP_Interrupt_Enable _bit4
-#define AI_START_Interrupt_Enable _bit3
-#define AI_START2_Interrupt_Enable _bit2
-#define AI_START1_Interrupt_Enable _bit1
-#define AI_SC_TC_Interrupt_Enable _bit0
-
-#define Interrupt_B_Enable_Register 75
-#define Pass_Thru_1_Interrupt_Enable _bit11
-#define G1_Gate_Interrupt_Enable _bit10
-#define G1_TC_Interrupt_Enable _bit9
-#define AO_FIFO_Interrupt_Enable _bit8
-#define AO_UI2_TC_Interrupt_Enable _bit7
-#define AO_UC_TC_Interrupt_Enable _bit6
-#define AO_Error_Interrupt_Enable _bit5
-#define AO_STOP_Interrupt_Enable _bit4
-#define AO_START_Interrupt_Enable _bit3
-#define AO_UPDATE_Interrupt_Enable _bit2
-#define AO_START1_Interrupt_Enable _bit1
-#define AO_BC_TC_Interrupt_Enable _bit0
-
-#define Second_IRQ_A_Enable_Register 74
-enum Second_IRQ_A_Enable_Bits {
- AI_SC_TC_Second_Irq_Enable = _bit0,
- AI_START1_Second_Irq_Enable = _bit1,
- AI_START2_Second_Irq_Enable = _bit2,
- AI_START_Second_Irq_Enable = _bit3,
- AI_STOP_Second_Irq_Enable = _bit4,
- AI_Error_Second_Irq_Enable = _bit5,
- G0_TC_Second_Irq_Enable = _bit6,
- AI_FIFO_Second_Irq_Enable = _bit7,
- G0_Gate_Second_Irq_Enable = _bit8,
- Pass_Thru_0_Second_Irq_Enable = _bit9
-};
+/*
+ * Registers in the National Instruments DAQ-STC chip
+ */
+
+#define NISTC_INTA_ACK_REG 2
+#define NISTC_INTA_ACK_G0_GATE BIT(15)
+#define NISTC_INTA_ACK_G0_TC BIT(14)
+#define NISTC_INTA_ACK_AI_ERR BIT(13)
+#define NISTC_INTA_ACK_AI_STOP BIT(12)
+#define NISTC_INTA_ACK_AI_START BIT(11)
+#define NISTC_INTA_ACK_AI_START2 BIT(10)
+#define NISTC_INTA_ACK_AI_START1 BIT(9)
+#define NISTC_INTA_ACK_AI_SC_TC BIT(8)
+#define NISTC_INTA_ACK_AI_SC_TC_ERR BIT(7)
+#define NISTC_INTA_ACK_G0_TC_ERR BIT(6)
+#define NISTC_INTA_ACK_G0_GATE_ERR BIT(5)
+#define NISTC_INTA_ACK_AI_ALL (NISTC_INTA_ACK_AI_ERR | \
+ NISTC_INTA_ACK_AI_STOP | \
+ NISTC_INTA_ACK_AI_START | \
+ NISTC_INTA_ACK_AI_START2 | \
+ NISTC_INTA_ACK_AI_START1 | \
+ NISTC_INTA_ACK_AI_SC_TC | \
+ NISTC_INTA_ACK_AI_SC_TC_ERR)
+
+#define NISTC_INTB_ACK_REG 3
+#define NISTC_INTB_ACK_G1_GATE BIT(15)
+#define NISTC_INTB_ACK_G1_TC BIT(14)
+#define NISTC_INTB_ACK_AO_ERR BIT(13)
+#define NISTC_INTB_ACK_AO_STOP BIT(12)
+#define NISTC_INTB_ACK_AO_START BIT(11)
+#define NISTC_INTB_ACK_AO_UPDATE BIT(10)
+#define NISTC_INTB_ACK_AO_START1 BIT(9)
+#define NISTC_INTB_ACK_AO_BC_TC BIT(8)
+#define NISTC_INTB_ACK_AO_UC_TC BIT(7)
+#define NISTC_INTB_ACK_AO_UI2_TC BIT(6)
+#define NISTC_INTB_ACK_AO_UI2_TC_ERR BIT(5)
+#define NISTC_INTB_ACK_AO_BC_TC_ERR BIT(4)
+#define NISTC_INTB_ACK_AO_BC_TC_TRIG_ERR BIT(3)
+#define NISTC_INTB_ACK_G1_TC_ERR BIT(2)
+#define NISTC_INTB_ACK_G1_GATE_ERR BIT(1)
+#define NISTC_INTB_ACK_AO_ALL (NISTC_INTB_ACK_AO_ERR | \
+ NISTC_INTB_ACK_AO_STOP | \
+ NISTC_INTB_ACK_AO_START | \
+ NISTC_INTB_ACK_AO_UPDATE | \
+ NISTC_INTB_ACK_AO_START1 | \
+ NISTC_INTB_ACK_AO_BC_TC | \
+ NISTC_INTB_ACK_AO_UC_TC | \
+ NISTC_INTB_ACK_AO_BC_TC_ERR | \
+ NISTC_INTB_ACK_AO_BC_TC_TRIG_ERR)
+
+#define NISTC_AI_CMD2_REG 4
+#define NISTC_AI_CMD2_END_ON_SC_TC BIT(15)
+#define NISTC_AI_CMD2_END_ON_EOS BIT(14)
+#define NISTC_AI_CMD2_START1_DISABLE BIT(11)
+#define NISTC_AI_CMD2_SC_SAVE_TRACE BIT(10)
+#define NISTC_AI_CMD2_SI_SW_ON_SC_TC BIT(9)
+#define NISTC_AI_CMD2_SI_SW_ON_STOP BIT(8)
+#define NISTC_AI_CMD2_SI_SW_ON_TC BIT(7)
+#define NISTC_AI_CMD2_SC_SW_ON_TC BIT(4)
+#define NISTC_AI_CMD2_STOP_PULSE BIT(3)
+#define NISTC_AI_CMD2_START_PULSE BIT(2)
+#define NISTC_AI_CMD2_START2_PULSE BIT(1)
+#define NISTC_AI_CMD2_START1_PULSE BIT(0)
+
+#define NISTC_AO_CMD2_REG 5
+#define NISTC_AO_CMD2_END_ON_BC_TC(x) (((x) & 0x3) << 14)
+#define NISTC_AO_CMD2_START_STOP_GATE_ENA BIT(13)
+#define NISTC_AO_CMD2_UC_SAVE_TRACE BIT(12)
+#define NISTC_AO_CMD2_BC_GATE_ENA BIT(11)
+#define NISTC_AO_CMD2_BC_SAVE_TRACE BIT(10)
+#define NISTC_AO_CMD2_UI_SW_ON_BC_TC BIT(9)
+#define NISTC_AO_CMD2_UI_SW_ON_STOP BIT(8)
+#define NISTC_AO_CMD2_UI_SW_ON_TC BIT(7)
+#define NISTC_AO_CMD2_UC_SW_ON_BC_TC BIT(6)
+#define NISTC_AO_CMD2_UC_SW_ON_TC BIT(5)
+#define NISTC_AO_CMD2_BC_SW_ON_TC BIT(4)
+#define NISTC_AO_CMD2_MUTE_B BIT(3)
+#define NISTC_AO_CMD2_MUTE_A BIT(2)
+#define NISTC_AO_CMD2_UPDATE2_PULSE BIT(1)
+#define NISTC_AO_CMD2_START1_PULSE BIT(0)
+
+#define NISTC_G0_CMD_REG 6
+#define NISTC_G1_CMD_REG 7
+
+#define NISTC_AI_CMD1_REG 8
+#define NISTC_AI_CMD1_ATRIG_RESET BIT(14)
+#define NISTC_AI_CMD1_DISARM BIT(13)
+#define NISTC_AI_CMD1_SI2_ARM BIT(12)
+#define NISTC_AI_CMD1_SI2_LOAD BIT(11)
+#define NISTC_AI_CMD1_SI_ARM BIT(10)
+#define NISTC_AI_CMD1_SI_LOAD BIT(9)
+#define NISTC_AI_CMD1_DIV_ARM BIT(8)
+#define NISTC_AI_CMD1_DIV_LOAD BIT(7)
+#define NISTC_AI_CMD1_SC_ARM BIT(6)
+#define NISTC_AI_CMD1_SC_LOAD BIT(5)
+#define NISTC_AI_CMD1_SCAN_IN_PROG_PULSE BIT(4)
+#define NISTC_AI_CMD1_EXTMUX_CLK_PULSE BIT(3)
+#define NISTC_AI_CMD1_LOCALMUX_CLK_PULSE BIT(2)
+#define NISTC_AI_CMD1_SC_TC_PULSE BIT(1)
+#define NISTC_AI_CMD1_CONVERT_PULSE BIT(0)
+
+#define NISTC_AO_CMD1_REG 9
+#define NISTC_AO_CMD1_ATRIG_RESET BIT(15)
+#define NISTC_AO_CMD1_START_PULSE BIT(14)
+#define NISTC_AO_CMD1_DISARM BIT(13)
+#define NISTC_AO_CMD1_UI2_ARM_DISARM BIT(12)
+#define NISTC_AO_CMD1_UI2_LOAD BIT(11)
+#define NISTC_AO_CMD1_UI_ARM BIT(10)
+#define NISTC_AO_CMD1_UI_LOAD BIT(9)
+#define NISTC_AO_CMD1_UC_ARM BIT(8)
+#define NISTC_AO_CMD1_UC_LOAD BIT(7)
+#define NISTC_AO_CMD1_BC_ARM BIT(6)
+#define NISTC_AO_CMD1_BC_LOAD BIT(5)
+#define NISTC_AO_CMD1_DAC1_UPDATE_MODE BIT(4)
+#define NISTC_AO_CMD1_LDAC1_SRC_SEL BIT(3)
+#define NISTC_AO_CMD1_DAC0_UPDATE_MODE BIT(2)
+#define NISTC_AO_CMD1_LDAC0_SRC_SEL BIT(1)
+#define NISTC_AO_CMD1_UPDATE_PULSE BIT(0)
+
+#define NISTC_DIO_OUT_REG 10
+#define NISTC_DIO_OUT_SERIAL(x) (((x) & 0xff) << 8)
+#define NISTC_DIO_OUT_SERIAL_MASK NISTC_DIO_OUT_SERIAL(0xff)
+#define NISTC_DIO_OUT_PARALLEL(x) ((x) & 0xff)
+#define NISTC_DIO_OUT_PARALLEL_MASK NISTC_DIO_OUT_PARALLEL(0xff)
+#define NISTC_DIO_SDIN BIT(4)
+#define NISTC_DIO_SDOUT BIT(0)
+
+#define NISTC_DIO_CTRL_REG 11
+#define NISTC_DIO_SDCLK BIT(11)
+#define NISTC_DIO_CTRL_HW_SER_TIMEBASE BIT(10)
+#define NISTC_DIO_CTRL_HW_SER_ENA BIT(9)
+#define NISTC_DIO_CTRL_HW_SER_START BIT(8)
+#define NISTC_DIO_CTRL_DIR(x) ((x) & 0xff)
+#define NISTC_DIO_CTRL_DIR_MASK NISTC_DIO_CTRL_DIR(0xff)
+
+#define NISTC_AI_MODE1_REG 12
+#define NISTC_AI_MODE1_CONVERT_SRC(x) (((x) & 0x1f) << 11)
+#define NISTC_AI_MODE1_SI_SRC(x) (((x) & 0x1f) << 6)
+#define NISTC_AI_MODE1_CONVERT_POLARITY BIT(5)
+#define NISTC_AI_MODE1_SI_POLARITY BIT(4)
+#define NISTC_AI_MODE1_START_STOP BIT(3)
+#define NISTC_AI_MODE1_RSVD BIT(2)
+#define NISTC_AI_MODE1_CONTINUOUS BIT(1)
+#define NISTC_AI_MODE1_TRIGGER_ONCE BIT(0)
+
+#define NISTC_AI_MODE2_REG 13
+#define NISTC_AI_MODE2_SC_GATE_ENA BIT(15)
+#define NISTC_AI_MODE2_START_STOP_GATE_ENA BIT(14)
+#define NISTC_AI_MODE2_PRE_TRIGGER BIT(13)
+#define NISTC_AI_MODE2_EXTMUX_PRESENT BIT(12)
+#define NISTC_AI_MODE2_SI2_INIT_LOAD_SRC BIT(9)
+#define NISTC_AI_MODE2_SI2_RELOAD_MODE BIT(8)
+#define NISTC_AI_MODE2_SI_INIT_LOAD_SRC BIT(7)
+#define NISTC_AI_MODE2_SI_RELOAD_MODE(x) (((x) & 0x7) << 4)
+#define NISTC_AI_MODE2_SI_WR_SWITCH BIT(3)
+#define NISTC_AI_MODE2_SC_INIT_LOAD_SRC BIT(2)
+#define NISTC_AI_MODE2_SC_RELOAD_MODE BIT(1)
+#define NISTC_AI_MODE2_SC_WR_SWITCH BIT(0)
+
+#define NISTC_AI_SI_LOADA_REG 14
+#define NISTC_AI_SI_LOADB_REG 16
+#define NISTC_AI_SC_LOADA_REG 18
+#define NISTC_AI_SC_LOADB_REG 20
+#define NISTC_AI_SI2_LOADA_REG 23
+#define NISTC_AI_SI2_LOADB_REG 25
+
+#define NISTC_G0_MODE_REG 26
+#define NISTC_G1_MODE_REG 27
+#define NISTC_G0_LOADA_REG 28
+#define NISTC_G0_LOADB_REG 30
+#define NISTC_G1_LOADA_REG 32
+#define NISTC_G1_LOADB_REG 34
+#define NISTC_G0_INPUT_SEL_REG 36
+#define NISTC_G1_INPUT_SEL_REG 37
+
+#define NISTC_AO_MODE1_REG 38
+#define NISTC_AO_MODE1_UPDATE_SRC(x) (((x) & 0x1f) << 11)
+#define NISTC_AO_MODE1_UPDATE_SRC_MASK NISTC_AO_MODE1_UPDATE_SRC(0x1f)
+#define NISTC_AO_MODE1_UI_SRC(x) (((x) & 0x1f) << 6)
+#define NISTC_AO_MODE1_UI_SRC_MASK NISTC_AO_MODE1_UI_SRC(0x1f)
+#define NISTC_AO_MODE1_MULTI_CHAN BIT(5)
+#define NISTC_AO_MODE1_UPDATE_SRC_POLARITY BIT(4)
+#define NISTC_AO_MODE1_UI_SRC_POLARITY BIT(3)
+#define NISTC_AO_MODE1_UC_SW_EVERY_TC BIT(2)
+#define NISTC_AO_MODE1_CONTINUOUS BIT(1)
+#define NISTC_AO_MODE1_TRIGGER_ONCE BIT(0)
+
+#define NISTC_AO_MODE2_REG 39
+#define NISTC_AO_MODE2_FIFO_MODE(x) (((x) & 0x3) << 14)
+#define NISTC_AO_MODE2_FIFO_MODE_MASK NISTC_AO_MODE2_FIFO_MODE(3)
+#define NISTC_AO_MODE2_FIFO_MODE_E NISTC_AO_MODE2_FIFO_MODE(0)
+#define NISTC_AO_MODE2_FIFO_MODE_HF NISTC_AO_MODE2_FIFO_MODE(1)
+#define NISTC_AO_MODE2_FIFO_MODE_F NISTC_AO_MODE2_FIFO_MODE(2)
+#define NISTC_AO_MODE2_FIFO_MODE_HF_F NISTC_AO_MODE2_FIFO_MODE(3)
+#define NISTC_AO_MODE2_FIFO_REXMIT_ENA BIT(13)
+#define NISTC_AO_MODE2_START1_DISABLE BIT(12)
+#define NISTC_AO_MODE2_UC_INIT_LOAD_SRC BIT(11)
+#define NISTC_AO_MODE2_UC_WR_SWITCH BIT(10)
+#define NISTC_AO_MODE2_UI2_INIT_LOAD_SRC BIT(9)
+#define NISTC_AO_MODE2_UI2_RELOAD_MODE BIT(8)
+#define NISTC_AO_MODE2_UI_INIT_LOAD_SRC BIT(7)
+#define NISTC_AO_MODE2_UI_RELOAD_MODE(x) (((x) & 0x7) << 4)
+#define NISTC_AO_MODE2_UI_WR_SWITCH BIT(3)
+#define NISTC_AO_MODE2_BC_INIT_LOAD_SRC BIT(2)
+#define NISTC_AO_MODE2_BC_RELOAD_MODE BIT(1)
+#define NISTC_AO_MODE2_BC_WR_SWITCH BIT(0)
+
+#define NISTC_AO_UI_LOADA_REG 40
+#define NISTC_AO_UI_LOADB_REG 42
+#define NISTC_AO_BC_LOADA_REG 44
+#define NISTC_AO_BC_LOADB_REG 46
+#define NISTC_AO_UC_LOADA_REG 48
+#define NISTC_AO_UC_LOADB_REG 50
+
+#define NISTC_CLK_FOUT_REG 56
+#define NISTC_CLK_FOUT_ENA BIT(15)
+#define NISTC_CLK_FOUT_TIMEBASE_SEL BIT(14)
+#define NISTC_CLK_FOUT_DIO_SER_OUT_DIV2 BIT(13)
+#define NISTC_CLK_FOUT_SLOW_DIV2 BIT(12)
+#define NISTC_CLK_FOUT_SLOW_TIMEBASE BIT(11)
+#define NISTC_CLK_FOUT_G_SRC_DIV2 BIT(10)
+#define NISTC_CLK_FOUT_TO_BOARD_DIV2 BIT(9)
+#define NISTC_CLK_FOUT_TO_BOARD BIT(8)
+#define NISTC_CLK_FOUT_AI_OUT_DIV2 BIT(7)
+#define NISTC_CLK_FOUT_AI_SRC_DIV2 BIT(6)
+#define NISTC_CLK_FOUT_AO_OUT_DIV2 BIT(5)
+#define NISTC_CLK_FOUT_AO_SRC_DIV2 BIT(4)
+#define NISTC_CLK_FOUT_DIVIDER(x) (((x) & 0xf) << 0)
+#define NISTC_CLK_FOUT_TO_DIVIDER(x) (((x) >> 0) & 0xf)
+#define NISTC_CLK_FOUT_DIVIDER_MASK NISTC_CLK_FOUT_DIVIDER(0xf)
+
+#define NISTC_IO_BIDIR_PIN_REG 57
+
+#define NISTC_RTSI_TRIG_DIR_REG 58
+#define NISTC_RTSI_TRIG_OLD_CLK_CHAN 7
+#define NISTC_RTSI_TRIG_NUM_CHAN(_m) ((_m) ? 8 : 7)
+#define NISTC_RTSI_TRIG_DIR(_c, _m) ((_m) ? BIT(8 + (_c)) : BIT(7 + (_c)))
+#define NISTC_RTSI_TRIG_USE_CLK BIT(1)
+#define NISTC_RTSI_TRIG_DRV_CLK BIT(0)
+
+#define NISTC_INT_CTRL_REG 59
+#define NISTC_INT_CTRL_INTB_ENA BIT(15)
+#define NISTC_INT_CTRL_INTB_SEL(x) (((x) & 0x7) << 12)
+#define NISTC_INT_CTRL_INTA_ENA BIT(11)
+#define NISTC_INT_CTRL_INTA_SEL(x) (((x) & 0x7) << 8)
+#define NISTC_INT_CTRL_PASSTHRU0_POL BIT(3)
+#define NISTC_INT_CTRL_PASSTHRU1_POL BIT(2)
+#define NISTC_INT_CTRL_3PIN_INT BIT(1)
+#define NISTC_INT_CTRL_INT_POL BIT(0)
+
+#define NISTC_AI_OUT_CTRL_REG 60
+#define NISTC_AI_OUT_CTRL_START_SEL BIT(10)
+#define NISTC_AI_OUT_CTRL_SCAN_IN_PROG_SEL(x) (((x) & 0x3) << 8)
+#define NISTC_AI_OUT_CTRL_EXTMUX_CLK_SEL(x) (((x) & 0x3) << 6)
+#define NISTC_AI_OUT_CTRL_LOCALMUX_CLK_SEL(x) (((x) & 0x3) << 4)
+#define NISTC_AI_OUT_CTRL_SC_TC_SEL(x) (((x) & 0x3) << 2)
+#define NISTC_AI_OUT_CTRL_CONVERT_SEL(x) (((x) & 0x3) << 0)
+#define NISTC_AI_OUT_CTRL_CONVERT_HIGH_Z NISTC_AI_OUT_CTRL_CONVERT_SEL(0)
+#define NISTC_AI_OUT_CTRL_CONVERT_GND NISTC_AI_OUT_CTRL_CONVERT_SEL(1)
+#define NISTC_AI_OUT_CTRL_CONVERT_LOW NISTC_AI_OUT_CTRL_CONVERT_SEL(2)
+#define NISTC_AI_OUT_CTRL_CONVERT_HIGH NISTC_AI_OUT_CTRL_CONVERT_SEL(3)
+
+#define NISTC_ATRIG_ETC_REG 61
+#define NISTC_ATRIG_ETC_GPFO_1_ENA BIT(15)
+#define NISTC_ATRIG_ETC_GPFO_0_ENA BIT(14)
+#define NISTC_ATRIG_ETC_GPFO_0_SEL(x) (((x) & 0x3) << 11)
+#define NISTC_ATRIG_ETC_GPFO_1_SEL BIT(7)
+#define NISTC_ATRIG_ETC_DRV BIT(4)
+#define NISTC_ATRIG_ETC_ENA BIT(3)
+#define NISTC_ATRIG_ETC_MODE(x) (((x) & 0x7) << 0)
+
+#define NISTC_AI_START_STOP_REG 62
+#define NISTC_AI_START_POLARITY BIT(15)
+#define NISTC_AI_STOP_POLARITY BIT(14)
+#define NISTC_AI_STOP_SYNC BIT(13)
+#define NISTC_AI_STOP_EDGE BIT(12)
+#define NISTC_AI_STOP_SEL(x) (((x) & 0x1f) << 7)
+#define NISTC_AI_START_SYNC BIT(6)
+#define NISTC_AI_START_EDGE BIT(5)
+#define NISTC_AI_START_SEL(x) (((x) & 0x1f) << 0)
+
+#define NISTC_AI_TRIG_SEL_REG 63
+#define NISTC_AI_TRIG_START1_POLARITY BIT(15)
+#define NISTC_AI_TRIG_START2_POLARITY BIT(14)
+#define NISTC_AI_TRIG_START2_SYNC BIT(13)
+#define NISTC_AI_TRIG_START2_EDGE BIT(12)
+#define NISTC_AI_TRIG_START2_SEL(x) (((x) & 0x1f) << 7)
+#define NISTC_AI_TRIG_START1_SYNC BIT(6)
+#define NISTC_AI_TRIG_START1_EDGE BIT(5)
+#define NISTC_AI_TRIG_START1_SEL(x) (((x) & 0x1f) << 0)
+
+#define NISTC_AI_DIV_LOADA_REG 64
+
+#define NISTC_AO_START_SEL_REG 66
+#define NISTC_AO_START_UI2_SW_GATE BIT(15)
+#define NISTC_AO_START_UI2_EXT_GATE_POL BIT(14)
+#define NISTC_AO_START_POLARITY BIT(13)
+#define NISTC_AO_START_AOFREQ_ENA BIT(12)
+#define NISTC_AO_START_UI2_EXT_GATE_SEL(x) (((x) & 0x1f) << 7)
+#define NISTC_AO_START_SYNC BIT(6)
+#define NISTC_AO_START_EDGE BIT(5)
+#define NISTC_AO_START_SEL(x) (((x) & 0x1f) << 0)
+
+#define NISTC_AO_TRIG_SEL_REG 67
+#define NISTC_AO_TRIG_UI2_EXT_GATE_ENA BIT(15)
+#define NISTC_AO_TRIG_DELAYED_START1 BIT(14)
+#define NISTC_AO_TRIG_START1_POLARITY BIT(13)
+#define NISTC_AO_TRIG_UI2_SRC_POLARITY BIT(12)
+#define NISTC_AO_TRIG_UI2_SRC_SEL(x) (((x) & 0x1f) << 7)
+#define NISTC_AO_TRIG_START1_SYNC BIT(6)
+#define NISTC_AO_TRIG_START1_EDGE BIT(5)
+#define NISTC_AO_TRIG_START1_SEL(x) (((x) & 0x1f) << 0)
+#define NISTC_AO_TRIG_START1_SEL_MASK NISTC_AO_TRIG_START1_SEL(0x1f)
+
+#define NISTC_G0_AUTOINC_REG 68
+#define NISTC_G1_AUTOINC_REG 69
+
+#define NISTC_AO_MODE3_REG 70
+#define NISTC_AO_MODE3_UI2_SW_NEXT_TC BIT(13)
+#define NISTC_AO_MODE3_UC_SW_EVERY_BC_TC BIT(12)
+#define NISTC_AO_MODE3_TRIG_LEN BIT(11)
+#define NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR BIT(5)
+#define NISTC_AO_MODE3_STOP_ON_BC_TC_TRIG_ERR BIT(4)
+#define NISTC_AO_MODE3_STOP_ON_BC_TC_ERR BIT(3)
+#define NISTC_AO_MODE3_NOT_AN_UPDATE BIT(2)
+#define NISTC_AO_MODE3_SW_GATE BIT(1)
+#define NISTC_AO_MODE3_LAST_GATE_DISABLE BIT(0) /* M-Series only */
+
+#define NISTC_RESET_REG 72
+#define NISTC_RESET_SOFTWARE BIT(11)
+#define NISTC_RESET_AO_CFG_END BIT(9)
+#define NISTC_RESET_AI_CFG_END BIT(8)
+#define NISTC_RESET_AO_CFG_START BIT(5)
+#define NISTC_RESET_AI_CFG_START BIT(4)
+#define NISTC_RESET_G1 BIT(3)
+#define NISTC_RESET_G0 BIT(2)
+#define NISTC_RESET_AO BIT(1)
+#define NISTC_RESET_AI BIT(0)
+
+#define NISTC_INTA_ENA_REG 73
+#define NISTC_INTA2_ENA_REG 74
+#define NISTC_INTA_ENA_PASSTHRU0 BIT(9)
+#define NISTC_INTA_ENA_G0_GATE BIT(8)
+#define NISTC_INTA_ENA_AI_FIFO BIT(7)
+#define NISTC_INTA_ENA_G0_TC BIT(6)
+#define NISTC_INTA_ENA_AI_ERR BIT(5)
+#define NISTC_INTA_ENA_AI_STOP BIT(4)
+#define NISTC_INTA_ENA_AI_START BIT(3)
+#define NISTC_INTA_ENA_AI_START2 BIT(2)
+#define NISTC_INTA_ENA_AI_START1 BIT(1)
+#define NISTC_INTA_ENA_AI_SC_TC BIT(0)
+#define NISTC_INTA_ENA_AI_MASK (NISTC_INTA_ENA_AI_FIFO | \
+ NISTC_INTA_ENA_AI_ERR | \
+ NISTC_INTA_ENA_AI_STOP | \
+ NISTC_INTA_ENA_AI_START | \
+ NISTC_INTA_ENA_AI_START2 | \
+ NISTC_INTA_ENA_AI_START1 | \
+ NISTC_INTA_ENA_AI_SC_TC)
+
+#define NISTC_INTB_ENA_REG 75
+#define NISTC_INTB2_ENA_REG 76
+#define NISTC_INTB_ENA_PASSTHRU1 BIT(11)
+#define NISTC_INTB_ENA_G1_GATE BIT(10)
+#define NISTC_INTB_ENA_G1_TC BIT(9)
+#define NISTC_INTB_ENA_AO_FIFO BIT(8)
+#define NISTC_INTB_ENA_AO_UI2_TC BIT(7)
+#define NISTC_INTB_ENA_AO_UC_TC BIT(6)
+#define NISTC_INTB_ENA_AO_ERR BIT(5)
+#define NISTC_INTB_ENA_AO_STOP BIT(4)
+#define NISTC_INTB_ENA_AO_START BIT(3)
+#define NISTC_INTB_ENA_AO_UPDATE BIT(2)
+#define NISTC_INTB_ENA_AO_START1 BIT(1)
+#define NISTC_INTB_ENA_AO_BC_TC BIT(0)
+
+#define NISTC_AI_PERSONAL_REG 77
+#define NISTC_AI_PERSONAL_SHIFTIN_PW BIT(15)
+#define NISTC_AI_PERSONAL_EOC_POLARITY BIT(14)
+#define NISTC_AI_PERSONAL_SOC_POLARITY BIT(13)
+#define NISTC_AI_PERSONAL_SHIFTIN_POL BIT(12)
+#define NISTC_AI_PERSONAL_CONVERT_TIMEBASE BIT(11)
+#define NISTC_AI_PERSONAL_CONVERT_PW BIT(10)
+#define NISTC_AI_PERSONAL_CONVERT_ORIG_PULSE BIT(9)
+#define NISTC_AI_PERSONAL_FIFO_FLAGS_POL BIT(8)
+#define NISTC_AI_PERSONAL_OVERRUN_MODE BIT(7)
+#define NISTC_AI_PERSONAL_EXTMUX_CLK_PW BIT(6)
+#define NISTC_AI_PERSONAL_LOCALMUX_CLK_PW BIT(5)
+#define NISTC_AI_PERSONAL_AIFREQ_POL BIT(4)
+
+#define NISTC_AO_PERSONAL_REG 78
+#define NISTC_AO_PERSONAL_MULTI_DACS BIT(15) /* M-Series only */
+#define NISTC_AO_PERSONAL_NUM_DAC BIT(14) /* 1:single; 0:dual */
+#define NISTC_AO_PERSONAL_FAST_CPU BIT(13) /* M-Series reserved */
+#define NISTC_AO_PERSONAL_TMRDACWR_PW BIT(12)
+#define NISTC_AO_PERSONAL_FIFO_FLAGS_POL BIT(11) /* M-Series reserved */
+#define NISTC_AO_PERSONAL_FIFO_ENA BIT(10)
+#define NISTC_AO_PERSONAL_AOFREQ_POL BIT(9) /* M-Series reserved */
+#define NISTC_AO_PERSONAL_DMA_PIO_CTRL BIT(8) /* M-Series reserved */
+#define NISTC_AO_PERSONAL_UPDATE_ORIG_PULSE BIT(7)
+#define NISTC_AO_PERSONAL_UPDATE_TIMEBASE BIT(6)
+#define NISTC_AO_PERSONAL_UPDATE_PW BIT(5)
+#define NISTC_AO_PERSONAL_BC_SRC_SEL BIT(4)
+#define NISTC_AO_PERSONAL_INTERVAL_BUFFER_MODE BIT(3)
+
+#define NISTC_RTSI_TRIGA_OUT_REG 79
+#define NISTC_RTSI_TRIGB_OUT_REG 80
+#define NISTC_RTSI_TRIGB_SUB_SEL1 BIT(15) /* not for M-Series */
+#define NISTC_RTSI_TRIG(_c, _s) (((_s) & 0xf) << (((_c) % 4) * 4))
+#define NISTC_RTSI_TRIG_MASK(_c) NISTC_RTSI_TRIG((_c), 0xf)
+#define NISTC_RTSI_TRIG_TO_SRC(_c, _b) (((_b) >> (((_c) % 4) * 4)) & 0xf)
+
+#define NISTC_RTSI_BOARD_REG 81
+
+#define NISTC_CFG_MEM_CLR_REG 82
+#define NISTC_ADC_FIFO_CLR_REG 83
+#define NISTC_DAC_FIFO_CLR_REG 84
+#define NISTC_WR_STROBE3_REG 85
+
+#define NISTC_AO_OUT_CTRL_REG 86
+#define NISTC_AO_OUT_CTRL_EXT_GATE_ENA BIT(15)
+#define NISTC_AO_OUT_CTRL_EXT_GATE_SEL(x) (((x) & 0x1f) << 10)
+#define NISTC_AO_OUT_CTRL_CHANS(x) (((x) & 0xf) << 6)
+#define NISTC_AO_OUT_CTRL_UPDATE2_SEL(x) (((x) & 0x3) << 4)
+#define NISTC_AO_OUT_CTRL_EXT_GATE_POL BIT(3)
+#define NISTC_AO_OUT_CTRL_UPDATE2_TOGGLE BIT(2)
+#define NISTC_AO_OUT_CTRL_UPDATE_SEL(x) (((x) & 0x3) << 0)
+#define NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ NISTC_AO_OUT_CTRL_UPDATE_SEL(0)
+#define NISTC_AO_OUT_CTRL_UPDATE_SEL_GND NISTC_AO_OUT_CTRL_UPDATE_SEL(1)
+#define NISTC_AO_OUT_CTRL_UPDATE_SEL_LOW NISTC_AO_OUT_CTRL_UPDATE_SEL(2)
+#define NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGH NISTC_AO_OUT_CTRL_UPDATE_SEL(3)
+
+#define NISTC_AI_MODE3_REG 87
+#define NISTC_AI_MODE3_TRIG_LEN BIT(15)
+#define NISTC_AI_MODE3_DELAY_START BIT(14)
+#define NISTC_AI_MODE3_SOFTWARE_GATE BIT(13)
+#define NISTC_AI_MODE3_SI_TRIG_DELAY BIT(12)
+#define NISTC_AI_MODE3_SI2_SRC_SEL BIT(11)
+#define NISTC_AI_MODE3_DELAYED_START2 BIT(10)
+#define NISTC_AI_MODE3_DELAYED_START1 BIT(9)
+#define NISTC_AI_MODE3_EXT_GATE_MODE BIT(8)
+#define NISTC_AI_MODE3_FIFO_MODE(x) (((x) & 0x3) << 6)
+#define NISTC_AI_MODE3_FIFO_MODE_NE NISTC_AI_MODE3_FIFO_MODE(0)
+#define NISTC_AI_MODE3_FIFO_MODE_HF NISTC_AI_MODE3_FIFO_MODE(1)
+#define NISTC_AI_MODE3_FIFO_MODE_F NISTC_AI_MODE3_FIFO_MODE(2)
+#define NISTC_AI_MODE3_FIFO_MODE_HF_E NISTC_AI_MODE3_FIFO_MODE(3)
+#define NISTC_AI_MODE3_EXT_GATE_POL BIT(5)
+#define NISTC_AI_MODE3_EXT_GATE_SEL(x) (((x) & 0x1f) << 0)
+
+#define NISTC_AI_STATUS1_REG 2
+#define NISTC_AI_STATUS1_INTA BIT(15)
+#define NISTC_AI_STATUS1_FIFO_F BIT(14)
+#define NISTC_AI_STATUS1_FIFO_HF BIT(13)
+#define NISTC_AI_STATUS1_FIFO_E BIT(12)
+#define NISTC_AI_STATUS1_OVERRUN BIT(11)
+#define NISTC_AI_STATUS1_OVERFLOW BIT(10)
+#define NISTC_AI_STATUS1_SC_TC_ERR BIT(9)
+#define NISTC_AI_STATUS1_OVER (NISTC_AI_STATUS1_OVERRUN | \
+ NISTC_AI_STATUS1_OVERFLOW)
+#define NISTC_AI_STATUS1_ERR (NISTC_AI_STATUS1_OVER | \
+ NISTC_AI_STATUS1_SC_TC_ERR)
+#define NISTC_AI_STATUS1_START2 BIT(8)
+#define NISTC_AI_STATUS1_START1 BIT(7)
+#define NISTC_AI_STATUS1_SC_TC BIT(6)
+#define NISTC_AI_STATUS1_START BIT(5)
+#define NISTC_AI_STATUS1_STOP BIT(4)
+#define NISTC_AI_STATUS1_G0_TC BIT(3)
+#define NISTC_AI_STATUS1_G0_GATE BIT(2)
+#define NISTC_AI_STATUS1_FIFO_REQ BIT(1)
+#define NISTC_AI_STATUS1_PASSTHRU0 BIT(0)
+
+#define NISTC_AO_STATUS1_REG 3
+#define NISTC_AO_STATUS1_INTB BIT(15)
+#define NISTC_AO_STATUS1_FIFO_F BIT(14)
+#define NISTC_AO_STATUS1_FIFO_HF BIT(13)
+#define NISTC_AO_STATUS1_FIFO_E BIT(12)
+#define NISTC_AO_STATUS1_BC_TC_ERR BIT(11)
+#define NISTC_AO_STATUS1_START BIT(10)
+#define NISTC_AO_STATUS1_OVERRUN BIT(9)
+#define NISTC_AO_STATUS1_START1 BIT(8)
+#define NISTC_AO_STATUS1_BC_TC BIT(7)
+#define NISTC_AO_STATUS1_UC_TC BIT(6)
+#define NISTC_AO_STATUS1_UPDATE BIT(5)
+#define NISTC_AO_STATUS1_UI2_TC BIT(4)
+#define NISTC_AO_STATUS1_G1_TC BIT(3)
+#define NISTC_AO_STATUS1_G1_GATE BIT(2)
+#define NISTC_AO_STATUS1_FIFO_REQ BIT(1)
+#define NISTC_AO_STATUS1_PASSTHRU1 BIT(0)
+
+#define NISTC_G01_STATUS_REG 4
+
+#define NISTC_AI_STATUS2_REG 5
+
+#define NISTC_AO_STATUS2_REG 6
+
+#define NISTC_DIO_IN_REG 7
+
+#define NISTC_G0_HW_SAVE_REG 8
+#define NISTC_G1_HW_SAVE_REG 10
+
+#define NISTC_G0_SAVE_REG 12
+#define NISTC_G1_SAVE_REG 14
+
+#define NISTC_AO_UI_SAVE_REG 16
+#define NISTC_AO_BC_SAVE_REG 18
+#define NISTC_AO_UC_SAVE_REG 20
+
+#define NISTC_STATUS1_REG 27
+#define NISTC_STATUS1_SERIO_IN_PROG BIT(12)
+
+#define NISTC_DIO_SERIAL_IN_REG 28
+
+#define NISTC_STATUS2_REG 29
+#define NISTC_STATUS2_AO_TMRDACWRS_IN_PROGRESS BIT(5)
+
+#define NISTC_AI_SI_SAVE_REG 64
+#define NISTC_AI_SC_SAVE_REG 66
-#define Second_IRQ_B_Enable_Register 76
-enum Second_IRQ_B_Enable_Bits {
- AO_BC_TC_Second_Irq_Enable = _bit0,
- AO_START1_Second_Irq_Enable = _bit1,
- AO_UPDATE_Second_Irq_Enable = _bit2,
- AO_START_Second_Irq_Enable = _bit3,
- AO_STOP_Second_Irq_Enable = _bit4,
- AO_Error_Second_Irq_Enable = _bit5,
- AO_UC_TC_Second_Irq_Enable = _bit6,
- AO_UI2_TC_Second_Irq_Enable = _bit7,
- AO_FIFO_Second_Irq_Enable = _bit8,
- G1_TC_Second_Irq_Enable = _bit9,
- G1_Gate_Second_Irq_Enable = _bit10,
- Pass_Thru_1_Second_Irq_Enable = _bit11
-};
+/*
+ * PCI E Series Registers
+ */
+#define NI_E_STC_WINDOW_ADDR_REG 0x00 /* rw16 */
+#define NI_E_STC_WINDOW_DATA_REG 0x02 /* rw16 */
+
+#define NI_E_STATUS_REG 0x01 /* r8 */
+#define NI_E_STATUS_AI_FIFO_LOWER_NE BIT(3)
+#define NI_E_STATUS_PROMOUT BIT(0)
+
+#define NI_E_DMA_AI_AO_SEL_REG 0x09 /* w8 */
+#define NI_E_DMA_AI_SEL(x) (((x) & 0xf) << 0)
+#define NI_E_DMA_AI_SEL_MASK NI_E_DMA_AI_SEL(0xf)
+#define NI_E_DMA_AO_SEL(x) (((x) & 0xf) << 4)
+#define NI_E_DMA_AO_SEL_MASK NI_E_DMA_AO_SEL(0xf)
+
+#define NI_E_DMA_G0_G1_SEL_REG 0x0b /* w8 */
+#define NI_E_DMA_G0_G1_SEL(_g, _c) (((_c) & 0xf) << ((_g) * 4))
+#define NI_E_DMA_G0_G1_SEL_MASK(_g) NI_E_DMA_G0_G1_SEL((_g), 0xf)
+
+#define NI_E_SERIAL_CMD_REG 0x0d /* w8 */
+#define NI_E_SERIAL_CMD_DAC_LD(x) BIT(3 + (x))
+#define NI_E_SERIAL_CMD_EEPROM_CS BIT(2)
+#define NI_E_SERIAL_CMD_SDATA BIT(1)
+#define NI_E_SERIAL_CMD_SCLK BIT(0)
+
+#define NI_E_MISC_CMD_REG 0x0f /* w8 */
+#define NI_E_MISC_CMD_INTEXT_ATRIG(x) (((x) & 0x1) << 7)
+#define NI_E_MISC_CMD_EXT_ATRIG NI_E_MISC_CMD_INTEXT_ATRIG(0)
+#define NI_E_MISC_CMD_INT_ATRIG NI_E_MISC_CMD_INTEXT_ATRIG(1)
+
+#define NI_E_AI_CFG_LO_REG 0x10 /* w16 */
+#define NI_E_AI_CFG_LO_LAST_CHAN BIT(15)
+#define NI_E_AI_CFG_LO_GEN_TRIG BIT(12)
+#define NI_E_AI_CFG_LO_DITHER BIT(9)
+#define NI_E_AI_CFG_LO_UNI BIT(8)
+#define NI_E_AI_CFG_LO_GAIN(x) ((x) << 0)
+
+#define NI_E_AI_CFG_HI_REG 0x12 /* w16 */
+#define NI_E_AI_CFG_HI_TYPE(x) (((x) & 0x7) << 12)
+#define NI_E_AI_CFG_HI_TYPE_DIFF NI_E_AI_CFG_HI_TYPE(1)
+#define NI_E_AI_CFG_HI_TYPE_COMMON NI_E_AI_CFG_HI_TYPE(2)
+#define NI_E_AI_CFG_HI_TYPE_GROUND NI_E_AI_CFG_HI_TYPE(3)
+#define NI_E_AI_CFG_HI_AC_COUPLE BIT(11)
+#define NI_E_AI_CFG_HI_CHAN(x) (((x) & 0x3f) << 0)
+
+#define NI_E_AO_CFG_REG 0x16 /* w16 */
+#define NI_E_AO_DACSEL(x) ((x) << 8)
+#define NI_E_AO_GROUND_REF BIT(3)
+#define NI_E_AO_EXT_REF BIT(2)
+#define NI_E_AO_DEGLITCH BIT(1)
+#define NI_E_AO_CFG_BIP BIT(0)
+
+#define NI_E_DAC_DIRECT_DATA_REG(x) (0x18 + ((x) * 2)) /* w16 */
+
+#define NI_E_8255_BASE 0x19 /* rw8 */
+
+#define NI_E_AI_FIFO_DATA_REG 0x1c /* r16 */
+
+#define NI_E_AO_FIFO_DATA_REG 0x1e /* w16 */
-#define AI_Personal_Register 77
-#define AI_SHIFTIN_Pulse_Width _bit15
-#define AI_EOC_Polarity _bit14
-#define AI_SOC_Polarity _bit13
-#define AI_SHIFTIN_Polarity _bit12
-#define AI_CONVERT_Pulse_Timebase _bit11
-#define AI_CONVERT_Pulse_Width _bit10
-#define AI_CONVERT_Original_Pulse _bit9
-#define AI_FIFO_Flags_Polarity _bit8
-#define AI_Overrun_Mode _bit7
-#define AI_EXTMUX_CLK_Pulse_Width _bit6
-#define AI_LOCALMUX_CLK_Pulse_Width _bit5
-#define AI_AIFREQ_Polarity _bit4
-
-#define AO_Personal_Register 78
-enum AO_Personal_Bits {
- AO_Interval_Buffer_Mode = 1 << 3,
- AO_BC_Source_Select = 1 << 4,
- AO_UPDATE_Pulse_Width = 1 << 5,
- AO_UPDATE_Pulse_Timebase = 1 << 6,
- AO_UPDATE_Original_Pulse = 1 << 7,
- AO_DMA_PIO_Control = 1 << 8, /* M Series: reserved */
- AO_AOFREQ_Polarity = 1 << 9, /* M Series: reserved */
- AO_FIFO_Enable = 1 << 10,
- AO_FIFO_Flags_Polarity = 1 << 11, /* M Series: reserved */
- AO_TMRDACWR_Pulse_Width = 1 << 12,
- AO_Fast_CPU = 1 << 13, /* M Series: reserved */
- AO_Number_Of_DAC_Packages = 1 << 14, /* 1 for "single" mode, 0 for "dual" */
- AO_Multiple_DACS_Per_Package = 1 << 15 /* m-series only */
-};
-#define RTSI_Trig_A_Output_Register 79
-#define RTSI_Trig_B_Output_Register 80
-enum RTSI_Trig_B_Output_Bits {
- RTSI_Sub_Selection_1_Bit = 0x8000 /* not for m-series */
-};
-static inline unsigned RTSI_Trig_Output_Bits(unsigned rtsi_channel,
- unsigned source)
-{
- return (source & 0xf) << ((rtsi_channel % 4) * 4);
-};
+/*
+ * 611x registers (these boards differ from the e-series)
+ */
+#define NI611X_MAGIC_REG 0x19 /* w8 (new) */
+#define NI611X_CALIB_CHAN_SEL_REG 0x1a /* w16 (new) */
+#define NI611X_AI_FIFO_DATA_REG 0x1c /* r32 (incompatible) */
+#define NI611X_AI_FIFO_OFFSET_LOAD_REG 0x05 /* r8 (new) */
+#define NI611X_AO_FIFO_DATA_REG 0x14 /* w32 (incompatible) */
+#define NI611X_CAL_GAIN_SEL_REG 0x05 /* w8 (new) */
+
+#define NI611X_AO_WINDOW_ADDR_REG 0x18
+#define NI611X_AO_WINDOW_DATA_REG 0x1e
-static inline unsigned RTSI_Trig_Output_Mask(unsigned rtsi_channel)
-{
- return 0xf << ((rtsi_channel % 4) * 4);
-};
+/*
+ * 6143 registers
+ */
+#define NI6143_MAGIC_REG 0x19 /* w8 */
+#define NI6143_DMA_G0_G1_SEL_REG 0x0b /* w8 */
+#define NI6143_PIPELINE_DELAY_REG 0x1f /* w8 */
+#define NI6143_EOC_SET_REG 0x1d /* w8 */
+#define NI6143_DMA_AI_SEL_REG 0x09 /* w8 */
+#define NI6143_AI_FIFO_DATA_REG 0x8c /* r32 */
+#define NI6143_AI_FIFO_FLAG_REG 0x84 /* w32 */
+#define NI6143_AI_FIFO_CTRL_REG 0x88 /* w32 */
+#define NI6143_AI_FIFO_STATUS_REG 0x88 /* r32 */
+#define NI6143_AI_FIFO_DMA_THRESH_REG 0x90 /* w32 */
+#define NI6143_AI_FIFO_WORDS_AVAIL_REG 0x94 /* w32 */
+
+#define NI6143_CALIB_CHAN_REG 0x42 /* w16 */
+#define NI6143_CALIB_CHAN_RELAY_ON BIT(15)
+#define NI6143_CALIB_CHAN_RELAY_OFF BIT(14)
+#define NI6143_CALIB_CHAN(x) (((x) & 0xf) << 0)
+#define NI6143_CALIB_CHAN_GND_GND NI6143_CALIB_CHAN(0) /* Offset Cal */
+#define NI6143_CALIB_CHAN_2V5_GND NI6143_CALIB_CHAN(2) /* 2.5V ref */
+#define NI6143_CALIB_CHAN_PWM_GND NI6143_CALIB_CHAN(5) /* +-5V Self Cal */
+#define NI6143_CALIB_CHAN_2V5_PWM NI6143_CALIB_CHAN(10) /* PWM Cal */
+#define NI6143_CALIB_CHAN_PWM_PWM NI6143_CALIB_CHAN(13) /* CMRR */
+#define NI6143_CALIB_CHAN_GND_PWM NI6143_CALIB_CHAN(14) /* PWM Cal */
+#define NI6143_CALIB_LO_TIME_REG 0x20 /* w16 */
+#define NI6143_CALIB_HI_TIME_REG 0x22 /* w16 */
+#define NI6143_RELAY_COUNTER_LOAD_REG 0x4c /* w32 */
+#define NI6143_SIGNATURE_REG 0x50 /* w32 */
+#define NI6143_RELEASE_DATE_REG 0x54 /* w32 */
+#define NI6143_RELEASE_OLDEST_DATE_REG 0x58 /* w32 */
-/* inverse to RTSI_Trig_Output_Bits() */
-static inline unsigned RTSI_Trig_Output_Source(unsigned rtsi_channel,
- unsigned bits)
-{
- return (bits >> ((rtsi_channel % 4) * 4)) & 0xf;
-};
+/*
+ * 671x, 611x windowed ao registers
+ */
+#define NI671X_DAC_DIRECT_DATA_REG(x) (0x00 + (x)) /* w16 */
+#define NI611X_AO_TIMED_REG 0x10 /* w16 */
+#define NI671X_AO_IMMEDIATE_REG 0x11 /* w16 */
+#define NI611X_AO_FIFO_OFFSET_LOAD_REG 0x13 /* w32 */
+#define NI67XX_AO_SP_UPDATES_REG 0x14 /* w16 */
+#define NI611X_AO_WAVEFORM_GEN_REG 0x15 /* w16 */
+#define NI611X_AO_MISC_REG 0x16 /* w16 */
+#define NI611X_AO_MISC_CLEAR_WG BIT(0)
+#define NI67XX_AO_CAL_CHAN_SEL_REG 0x17 /* w16 */
+#define NI67XX_AO_CFG2_REG 0x18 /* w16 */
+#define NI67XX_CAL_CMD_REG 0x19 /* w16 */
+#define NI67XX_CAL_STATUS_REG 0x1a /* r8 */
+#define NI67XX_CAL_STATUS_BUSY BIT(0)
+#define NI67XX_CAL_STATUS_OSC_DETECT BIT(1)
+#define NI67XX_CAL_STATUS_OVERRANGE BIT(2)
+#define NI67XX_CAL_DATA_REG 0x1b /* r16 */
+#define NI67XX_CAL_CFG_HI_REG 0x1c /* rw16 */
+#define NI67XX_CAL_CFG_LO_REG 0x1d /* rw16 */
+
+#define CS5529_CMD_CB BIT(7)
+#define CS5529_CMD_SINGLE_CONV BIT(6)
+#define CS5529_CMD_CONT_CONV BIT(5)
+#define CS5529_CMD_READ BIT(4)
+#define CS5529_CMD_REG(x) (((x) & 0x7) << 1)
+#define CS5529_CMD_REG_MASK CS5529_CMD_REG(7)
+#define CS5529_CMD_PWR_SAVE BIT(0)
+
+#define CS5529_OFFSET_REG CS5529_CMD_REG(0)
+#define CS5529_GAIN_REG CS5529_CMD_REG(1)
+#define CS5529_CONV_DATA_REG CS5529_CMD_REG(3)
+#define CS5529_SETUP_REG CS5529_CMD_REG(4)
+
+#define CS5529_CFG_REG CS5529_CMD_REG(2)
+#define CS5529_CFG_AOUT(x) BIT(22 + (x))
+#define CS5529_CFG_DOUT(x) BIT(18 + (x))
+#define CS5529_CFG_LOW_PWR_MODE BIT(16)
+#define CS5529_CFG_WORD_RATE(x) (((x) & 0x7) << 13)
+#define CS5529_CFG_WORD_RATE_MASK CS5529_CFG_WORD_RATE(0x7)
+#define CS5529_CFG_WORD_RATE_2180 CS5529_CFG_WORD_RATE(0)
+#define CS5529_CFG_WORD_RATE_1092 CS5529_CFG_WORD_RATE(1)
+#define CS5529_CFG_WORD_RATE_532 CS5529_CFG_WORD_RATE(2)
+#define CS5529_CFG_WORD_RATE_388 CS5529_CFG_WORD_RATE(3)
+#define CS5529_CFG_WORD_RATE_324 CS5529_CFG_WORD_RATE(4)
+#define CS5529_CFG_WORD_RATE_17444 CS5529_CFG_WORD_RATE(5)
+#define CS5529_CFG_WORD_RATE_8724 CS5529_CFG_WORD_RATE(6)
+#define CS5529_CFG_WORD_RATE_4364 CS5529_CFG_WORD_RATE(7)
+#define CS5529_CFG_UNIPOLAR BIT(12)
+#define CS5529_CFG_RESET BIT(7)
+#define CS5529_CFG_RESET_VALID BIT(6)
+#define CS5529_CFG_PORT_FLAG BIT(5)
+#define CS5529_CFG_PWR_SAVE_SEL BIT(4)
+#define CS5529_CFG_DONE_FLAG BIT(3)
+#define CS5529_CFG_CALIB(x) (((x) & 0x7) << 0)
+#define CS5529_CFG_CALIB_NONE CS5529_CFG_CALIB(0)
+#define CS5529_CFG_CALIB_OFFSET_SELF CS5529_CFG_CALIB(1)
+#define CS5529_CFG_CALIB_GAIN_SELF CS5529_CFG_CALIB(2)
+#define CS5529_CFG_CALIB_BOTH_SELF CS5529_CFG_CALIB(3)
+#define CS5529_CFG_CALIB_OFFSET_SYS CS5529_CFG_CALIB(5)
+#define CS5529_CFG_CALIB_GAIN_SYS CS5529_CFG_CALIB(6)
-#define RTSI_Board_Register 81
-#define Write_Strobe_0_Register 82
-#define Write_Strobe_1_Register 83
-#define Write_Strobe_2_Register 84
-#define Write_Strobe_3_Register 85
-
-#define AO_Output_Control_Register 86
-#define AO_External_Gate_Enable _bit15
-#define AO_External_Gate_Select(x) (((x)&0x1f)<<10)
-#define AO_Number_Of_Channels(x) (((x)&0xf)<<6)
-#define AO_UPDATE2_Output_Select(x) (((x)&0x3)<<4)
-#define AO_External_Gate_Polarity _bit3
-#define AO_UPDATE2_Output_Toggle _bit2
-enum ao_update_output_selection {
- AO_Update_Output_High_Z = 0,
- AO_Update_Output_Ground = 1,
- AO_Update_Output_Enable_Low = 2,
- AO_Update_Output_Enable_High = 3
-};
-static unsigned AO_UPDATE_Output_Select(enum ao_update_output_selection
- selection)
-{
- return selection & 0x3;
-}
-
-#define AI_Mode_3_Register 87
-#define AI_Trigger_Length _bit15
-#define AI_Delay_START _bit14
-#define AI_Software_Gate _bit13
-#define AI_SI_Special_Trigger_Delay _bit12
-#define AI_SI2_Source_Select _bit11
-#define AI_Delayed_START2 _bit10
-#define AI_Delayed_START1 _bit9
-#define AI_External_Gate_Mode _bit8
-#define AI_FIFO_Mode_HF_to_E (3<<6)
-#define AI_FIFO_Mode_F (2<<6)
-#define AI_FIFO_Mode_HF (1<<6)
-#define AI_FIFO_Mode_NE (0<<6)
-#define AI_External_Gate_Polarity _bit5
-#define AI_External_Gate_Select(a) ((a) & 0x1f)
-
-#define G_Autoincrement_Register(a) (68+(a))
-#define G_Command_Register(a) (6+(a))
-#define G_HW_Save_Register(a) (8+(a)*2)
-#define G_HW_Save_Register_High(a) (8+(a)*2)
-#define G_HW_Save_Register_Low(a) (9+(a)*2)
-#define G_Input_Select_Register(a) (36+(a))
-#define G_Load_A_Register(a) (28+(a)*4)
-#define G_Load_A_Register_High(a) (28+(a)*4)
-#define G_Load_A_Register_Low(a) (29+(a)*4)
-#define G_Load_B_Register(a) (30+(a)*4)
-#define G_Load_B_Register_High(a) (30+(a)*4)
-#define G_Load_B_Register_Low(a) (31+(a)*4)
-#define G_Mode_Register(a) (26+(a))
-#define G_Save_Register(a) (12+(a)*2)
-#define G_Save_Register_High(a) (12+(a)*2)
-#define G_Save_Register_Low(a) (13+(a)*2)
-#define G_Status_Register 4
-#define Analog_Trigger_Etc_Register 61
-
-/* command register */
-#define G_Disarm_Copy _bit15 /* strobe */
-#define G_Save_Trace_Copy _bit14
-#define G_Arm_Copy _bit13 /* strobe */
-#define G_Bank_Switch_Start _bit10 /* strobe */
-#define G_Little_Big_Endian _bit9
-#define G_Synchronized_Gate _bit8
-#define G_Write_Switch _bit7
-#define G_Up_Down(a) (((a)&0x03)<<5)
-#define G_Disarm _bit4 /* strobe */
-#define G_Analog_Trigger_Reset _bit3 /* strobe */
-#define G_Save_Trace _bit1
-#define G_Arm _bit0 /* strobe */
-
-/*channel agnostic names for the command register #defines */
-#define G_Bank_Switch_Enable _bit12
-#define G_Bank_Switch_Mode _bit11
-#define G_Load _bit2 /* strobe */
-
-/* input select register */
-#define G_Gate_Select(a) (((a)&0x1f)<<7)
-#define G_Source_Select(a) (((a)&0x1f)<<2)
-#define G_Write_Acknowledges_Irq _bit1
-#define G_Read_Acknowledges_Irq _bit0
-
-/* same input select register, but with channel agnostic names */
-#define G_Source_Polarity _bit15
-#define G_Output_Polarity _bit14
-#define G_OR_Gate _bit13
-#define G_Gate_Select_Load_Source _bit12
-
-/* mode register */
-#define G_Loading_On_TC _bit12
-#define G_Output_Mode(a) (((a)&0x03)<<8)
-#define G_Trigger_Mode_For_Edge_Gate(a) (((a)&0x03)<<3)
-#define G_Gating_Mode(a) (((a)&0x03)<<0)
-
-/* same input mode register, but with channel agnostic names */
-#define G_Load_Source_Select _bit7
-#define G_Reload_Source_Switching _bit15
-#define G_Loading_On_Gate _bit14
-#define G_Gate_Polarity _bit13
-
-#define G_Counting_Once(a) (((a)&0x03)<<10)
-#define G_Stop_Mode(a) (((a)&0x03)<<5)
-#define G_Gate_On_Both_Edges _bit2
-
-/* G_Status_Register */
-#define G1_Gate_Error_St _bit15
-#define G0_Gate_Error_St _bit14
-#define G1_TC_Error_St _bit13
-#define G0_TC_Error_St _bit12
-#define G1_No_Load_Between_Gates_St _bit11
-#define G0_No_Load_Between_Gates_St _bit10
-#define G1_Armed_St _bit9
-#define G0_Armed_St _bit8
-#define G1_Stale_Data_St _bit7
-#define G0_Stale_Data_St _bit6
-#define G1_Next_Load_Source_St _bit5
-#define G0_Next_Load_Source_St _bit4
-#define G1_Counting_St _bit3
-#define G0_Counting_St _bit2
-#define G1_Save_St _bit1
-#define G0_Save_St _bit0
-
-/* general purpose counter timer */
-#define G_Autoincrement(a) ((a)<<0)
-
-/*Analog_Trigger_Etc_Register*/
-#define Analog_Trigger_Mode(x) ((x) & 0x7)
-#define Analog_Trigger_Enable _bit3
-#define Analog_Trigger_Drive _bit4
-#define GPFO_1_Output_Select _bit7
-#define GPFO_0_Output_Select(a) ((a)<<11)
-#define GPFO_0_Output_Enable _bit14
-#define GPFO_1_Output_Enable _bit15
-
-/* Additional windowed registers unique to E series */
-
-/* 16 bit registers shadowed from DAQ-STC */
-#define Window_Address 0x00
-#define Window_Data 0x02
-
-#define Configuration_Memory_Clear 82
-#define ADC_FIFO_Clear 83
-#define DAC_FIFO_Clear 84
-
-/* i/o port offsets */
-
-/* 8 bit registers */
-#define XXX_Status 0x01
-enum XXX_Status_Bits {
- PROMOUT = 0x1,
- AI_FIFO_LOWER_NOT_EMPTY = 0x8,
-};
-#define Serial_Command 0x0d
-#define Misc_Command 0x0f
-#define Port_A 0x19
-#define Port_B 0x1b
-#define Port_C 0x1d
-#define Configuration 0x1f
-#define Strobes 0x01
-#define Channel_A_Mode 0x03
-#define Channel_B_Mode 0x05
-#define Channel_C_Mode 0x07
-#define AI_AO_Select 0x09
-enum AI_AO_Select_Bits {
- AI_DMA_Select_Shift = 0,
- AI_DMA_Select_Mask = 0xf,
- AO_DMA_Select_Shift = 4,
- AO_DMA_Select_Mask = 0xf << AO_DMA_Select_Shift
-};
-#define G0_G1_Select 0x0b
-static inline unsigned ni_stc_dma_channel_select_bitfield(unsigned channel)
-{
- if (channel < 4)
- return 1 << channel;
- if (channel == 4)
- return 0x3;
- if (channel == 5)
- return 0x5;
- BUG();
- return 0;
-}
-
-static inline unsigned GPCT_DMA_Select_Bits(unsigned gpct_index,
- unsigned mite_channel)
-{
- BUG_ON(gpct_index > 1);
- return ni_stc_dma_channel_select_bitfield(mite_channel) << (4 *
- gpct_index);
-}
-
-static inline unsigned GPCT_DMA_Select_Mask(unsigned gpct_index)
-{
- BUG_ON(gpct_index > 1);
- return 0xf << (4 * gpct_index);
-}
-
-/* 16 bit registers */
-
-#define Configuration_Memory_Low 0x10
-enum Configuration_Memory_Low_Bits {
- AI_DITHER = 0x200,
- AI_LAST_CHANNEL = 0x8000,
-};
-#define Configuration_Memory_High 0x12
-enum Configuration_Memory_High_Bits {
- AI_AC_COUPLE = 0x800,
- AI_DIFFERENTIAL = 0x1000,
- AI_COMMON = 0x2000,
- AI_GROUND = 0x3000,
-};
-static inline unsigned int AI_CONFIG_CHANNEL(unsigned int channel)
-{
- return channel & 0x3f;
-}
-
-#define ADC_FIFO_Data_Register 0x1c
-
-#define AO_Configuration 0x16
-#define AO_Bipolar _bit0
-#define AO_Deglitch _bit1
-#define AO_Ext_Ref _bit2
-#define AO_Ground_Ref _bit3
-#define AO_Channel(x) ((x) << 8)
-
-#define DAC_FIFO_Data 0x1e
-#define DAC0_Direct_Data 0x18
-#define DAC1_Direct_Data 0x1a
-
-/* 611x registers (these boards differ from the e-series) */
-
-#define Magic_611x 0x19 /* w8 (new) */
-#define Calibration_Channel_Select_611x 0x1a /* w16 (new) */
-#define ADC_FIFO_Data_611x 0x1c /* r32 (incompatible) */
-#define AI_FIFO_Offset_Load_611x 0x05 /* r8 (new) */
-#define DAC_FIFO_Data_611x 0x14 /* w32 (incompatible) */
-#define Cal_Gain_Select_611x 0x05 /* w8 (new) */
-
-#define AO_Window_Address_611x 0x18
-#define AO_Window_Data_611x 0x1e
-
-/* 6143 registers */
-#define Magic_6143 0x19 /* w8 */
-#define G0G1_DMA_Select_6143 0x0B /* w8 */
-#define PipelineDelay_6143 0x1f /* w8 */
-#define EOC_Set_6143 0x1D /* w8 */
-#define AIDMA_Select_6143 0x09 /* w8 */
-#define AIFIFO_Data_6143 0x8C /* w32 */
-#define AIFIFO_Flag_6143 0x84 /* w32 */
-#define AIFIFO_Control_6143 0x88 /* w32 */
-#define AIFIFO_Status_6143 0x88 /* w32 */
-#define AIFIFO_DMAThreshold_6143 0x90 /* w32 */
-#define AIFIFO_Words_Available_6143 0x94 /* w32 */
-
-#define Calibration_Channel_6143 0x42 /* w16 */
-#define Calibration_LowTime_6143 0x20 /* w16 */
-#define Calibration_HighTime_6143 0x22 /* w16 */
-#define Relay_Counter_Load_Val__6143 0x4C /* w32 */
-#define Signature_6143 0x50 /* w32 */
-#define Release_Date_6143 0x54 /* w32 */
-#define Release_Oldest_Date_6143 0x58 /* w32 */
-
-#define Calibration_Channel_6143_RelayOn 0x8000 /* Calibration relay switch On */
-#define Calibration_Channel_6143_RelayOff 0x4000 /* Calibration relay switch Off */
-#define Calibration_Channel_Gnd_Gnd 0x00 /* Offset Calibration */
-#define Calibration_Channel_2v5_Gnd 0x02 /* 2.5V Reference */
-#define Calibration_Channel_Pwm_Gnd 0x05 /* +/- 5V Self Cal */
-#define Calibration_Channel_2v5_Pwm 0x0a /* PWM Calibration */
-#define Calibration_Channel_Pwm_Pwm 0x0d /* CMRR */
-#define Calibration_Channel_Gnd_Pwm 0x0e /* PWM Calibration */
-
-/* 671x, 611x registers */
-
-/* 671xi, 611x windowed ao registers */
-enum windowed_regs_67xx_61xx {
- AO_Immediate_671x = 0x11, /* W 16 */
- AO_Timed_611x = 0x10, /* W 16 */
- AO_FIFO_Offset_Load_611x = 0x13, /* W32 */
- AO_Later_Single_Point_Updates = 0x14, /* W 16 */
- AO_Waveform_Generation_611x = 0x15, /* W 16 */
- AO_Misc_611x = 0x16, /* W 16 */
- AO_Calibration_Channel_Select_67xx = 0x17, /* W 16 */
- AO_Configuration_2_67xx = 0x18, /* W 16 */
- CAL_ADC_Command_67xx = 0x19, /* W 8 */
- CAL_ADC_Status_67xx = 0x1a, /* R 8 */
- CAL_ADC_Data_67xx = 0x1b, /* R 16 */
- CAL_ADC_Config_Data_High_Word_67xx = 0x1c, /* RW 16 */
- CAL_ADC_Config_Data_Low_Word_67xx = 0x1d, /* RW 16 */
+/*
+ * M-Series specific registers not handled by the DAQ-STC and GPCT register
+ * remapping.
+ */
+#define NI_M_CDIO_DMA_SEL_REG 0x007
+#define NI_M_CDIO_DMA_SEL_CDO(x) (((x) & 0xf) << 4)
+#define NI_M_CDIO_DMA_SEL_CDO_MASK NI_M_CDIO_DMA_SEL_CDO(0xf)
+#define NI_M_CDIO_DMA_SEL_CDI(x) (((x) & 0xf) << 0)
+#define NI_M_CDIO_DMA_SEL_CDI_MASK NI_M_CDIO_DMA_SEL_CDI(0xf)
+#define NI_M_SCXI_STATUS_REG 0x007
+#define NI_M_AI_AO_SEL_REG 0x009
+#define NI_M_G0_G1_SEL_REG 0x00b
+#define NI_M_MISC_CMD_REG 0x00f
+#define NI_M_SCXI_SER_DO_REG 0x011
+#define NI_M_SCXI_CTRL_REG 0x013
+#define NI_M_SCXI_OUT_ENA_REG 0x015
+#define NI_M_AI_FIFO_DATA_REG 0x01c
+#define NI_M_DIO_REG 0x024
+#define NI_M_DIO_DIR_REG 0x028
+#define NI_M_CAL_PWM_REG 0x040
+#define NI_M_CAL_PWM_HIGH_TIME(x) (((x) & 0xffff) << 16)
+#define NI_M_CAL_PWM_LOW_TIME(x) (((x) & 0xffff) << 0)
+#define NI_M_GEN_PWM_REG(x) (0x044 + ((x) * 2))
+#define NI_M_AI_CFG_FIFO_DATA_REG 0x05e
+#define NI_M_AI_CFG_LAST_CHAN BIT(14)
+#define NI_M_AI_CFG_DITHER BIT(13)
+#define NI_M_AI_CFG_POLARITY BIT(12)
+#define NI_M_AI_CFG_GAIN(x) (((x) & 0x7) << 9)
+#define NI_M_AI_CFG_CHAN_TYPE(x) (((x) & 0x7) << 6)
+#define NI_M_AI_CFG_CHAN_TYPE_MASK NI_M_AI_CFG_CHAN_TYPE(7)
+#define NI_M_AI_CFG_CHAN_TYPE_CALIB NI_M_AI_CFG_CHAN_TYPE(0)
+#define NI_M_AI_CFG_CHAN_TYPE_DIFF NI_M_AI_CFG_CHAN_TYPE(1)
+#define NI_M_AI_CFG_CHAN_TYPE_COMMON NI_M_AI_CFG_CHAN_TYPE(2)
+#define NI_M_AI_CFG_CHAN_TYPE_GROUND NI_M_AI_CFG_CHAN_TYPE(3)
+#define NI_M_AI_CFG_CHAN_TYPE_AUX NI_M_AI_CFG_CHAN_TYPE(5)
+#define NI_M_AI_CFG_CHAN_TYPE_GHOST NI_M_AI_CFG_CHAN_TYPE(7)
+#define NI_M_AI_CFG_BANK_SEL(x) ((((x) & 0x40) << 4) | ((x) & 0x30))
+#define NI_M_AI_CFG_CHAN_SEL(x) (((x) & 0xf) << 0)
+#define NI_M_INTC_ENA_REG 0x088
+#define NI_M_INTC_ENA BIT(0)
+#define NI_M_INTC_STATUS_REG 0x088
+#define NI_M_INTC_STATUS BIT(0)
+#define NI_M_ATRIG_CTRL_REG 0x08c
+#define NI_M_AO_SER_INT_ENA_REG 0x0a0
+#define NI_M_AO_SER_INT_ACK_REG 0x0a1
+#define NI_M_AO_SER_INT_STATUS_REG 0x0a1
+#define NI_M_AO_CALIB_REG 0x0a3
+#define NI_M_AO_FIFO_DATA_REG 0x0a4
+#define NI_M_PFI_FILTER_REG 0x0b0
+#define NI_M_PFI_FILTER_SEL(_c, _f) (((_f) & 0x3) << ((_c) * 2))
+#define NI_M_PFI_FILTER_SEL_MASK(_c) NI_M_PFI_FILTER_SEL((_c), 0x3)
+#define NI_M_RTSI_FILTER_REG 0x0b4
+#define NI_M_SCXI_LEGACY_COMPAT_REG 0x0bc
+#define NI_M_DAC_DIRECT_DATA_REG(x) (0x0c0 + ((x) * 4))
+#define NI_M_AO_WAVEFORM_ORDER_REG(x) (0x0c2 + ((x) * 4))
+#define NI_M_AO_CFG_BANK_REG(x) (0x0c3 + ((x) * 4))
+#define NI_M_AO_CFG_BANK_BIPOLAR BIT(7)
+#define NI_M_AO_CFG_BANK_UPDATE_TIMED BIT(6)
+#define NI_M_AO_CFG_BANK_REF(x) (((x) & 0x7) << 3)
+#define NI_M_AO_CFG_BANK_REF_MASK NI_M_AO_CFG_BANK_REF(7)
+#define NI_M_AO_CFG_BANK_REF_INT_10V NI_M_AO_CFG_BANK_REF(0)
+#define NI_M_AO_CFG_BANK_REF_INT_5V NI_M_AO_CFG_BANK_REF(1)
+#define NI_M_AO_CFG_BANK_OFFSET(x) (((x) & 0x7) << 0)
+#define NI_M_AO_CFG_BANK_OFFSET_MASK NI_M_AO_CFG_BANK_OFFSET(7)
+#define NI_M_AO_CFG_BANK_OFFSET_0V NI_M_AO_CFG_BANK_OFFSET(0)
+#define NI_M_AO_CFG_BANK_OFFSET_5V NI_M_AO_CFG_BANK_OFFSET(1)
+#define NI_M_RTSI_SHARED_MUX_REG 0x1a2
+#define NI_M_CLK_FOUT2_REG 0x1c4
+#define NI_M_CLK_FOUT2_RTSI_10MHZ BIT(7)
+#define NI_M_CLK_FOUT2_TIMEBASE3_PLL BIT(6)
+#define NI_M_CLK_FOUT2_TIMEBASE1_PLL BIT(5)
+#define NI_M_CLK_FOUT2_PLL_SRC(x) (((x) & 0x1f) << 0)
+#define NI_M_CLK_FOUT2_PLL_SRC_MASK NI_M_CLK_FOUT2_PLL_SRC(0x1f)
+#define NI_M_MAX_RTSI_CHAN 7
+#define NI_M_CLK_FOUT2_PLL_SRC_RTSI(x) (((x) == NI_M_MAX_RTSI_CHAN) \
+ ? NI_M_CLK_FOUT2_PLL_SRC(0x1b) \
+ : NI_M_CLK_FOUT2_PLL_SRC(0xb + (x)))
+#define NI_M_CLK_FOUT2_PLL_SRC_STAR NI_M_CLK_FOUT2_PLL_SRC(0x14)
+#define NI_M_CLK_FOUT2_PLL_SRC_PXI10 NI_M_CLK_FOUT2_PLL_SRC(0x1d)
+#define NI_M_PLL_CTRL_REG 0x1c6
+#define NI_M_PLL_CTRL_VCO_MODE(x) (((x) & 0x3) << 13)
+#define NI_M_PLL_CTRL_VCO_MODE_200_325MHZ NI_M_PLL_CTRL_VCO_MODE(0)
+#define NI_M_PLL_CTRL_VCO_MODE_175_225MHZ NI_M_PLL_CTRL_VCO_MODE(1)
+#define NI_M_PLL_CTRL_VCO_MODE_100_225MHZ NI_M_PLL_CTRL_VCO_MODE(2)
+#define NI_M_PLL_CTRL_VCO_MODE_75_150MHZ NI_M_PLL_CTRL_VCO_MODE(3)
+#define NI_M_PLL_CTRL_ENA BIT(12)
+#define NI_M_PLL_MAX_DIVISOR 0x10
+#define NI_M_PLL_CTRL_DIVISOR(x) (((x) & 0xf) << 8)
+#define NI_M_PLL_MAX_MULTIPLIER 0x100
+#define NI_M_PLL_CTRL_MULTIPLIER(x) (((x) & 0xff) << 0)
+#define NI_M_PLL_STATUS_REG 0x1c8
+#define NI_M_PLL_STATUS_LOCKED BIT(0)
+#define NI_M_PFI_OUT_SEL_REG(x) (0x1d0 + ((x) * 2))
+#define NI_M_PFI_CHAN(_c) (((_c) % 3) * 5)
+#define NI_M_PFI_OUT_SEL(_c, _s) (((_s) & 0x1f) << NI_M_PFI_CHAN(_c))
+#define NI_M_PFI_OUT_SEL_MASK(_c) (0x1f << NI_M_PFI_CHAN(_c))
+#define NI_M_PFI_OUT_SEL_TO_SRC(_c, _b) (((_b) >> NI_M_PFI_CHAN(_c)) & 0x1f)
+#define NI_M_PFI_DI_REG 0x1dc
+#define NI_M_PFI_DO_REG 0x1de
+#define NI_M_CFG_BYPASS_FIFO_REG 0x218
+#define NI_M_CFG_BYPASS_FIFO BIT(31)
+#define NI_M_CFG_BYPASS_AI_POLARITY BIT(22)
+#define NI_M_CFG_BYPASS_AI_DITHER BIT(21)
+#define NI_M_CFG_BYPASS_AI_GAIN(x) (((x) & 0x7) << 18)
+#define NI_M_CFG_BYPASS_AO_CAL(x) (((x) & 0xf) << 15)
+#define NI_M_CFG_BYPASS_AO_CAL_MASK NI_M_CFG_BYPASS_AO_CAL(0xf)
+#define NI_M_CFG_BYPASS_AI_MODE_MUX(x) (((x) & 0x3) << 13)
+#define NI_M_CFG_BYPASS_AI_MODE_MUX_MASK NI_M_CFG_BYPASS_AI_MODE_MUX(3)
+#define NI_M_CFG_BYPASS_AI_CAL_NEG(x) (((x) & 0x7) << 10)
+#define NI_M_CFG_BYPASS_AI_CAL_NEG_MASK NI_M_CFG_BYPASS_AI_CAL_NEG(7)
+#define NI_M_CFG_BYPASS_AI_CAL_POS(x) (((x) & 0x7) << 7)
+#define NI_M_CFG_BYPASS_AI_CAL_POS_MASK NI_M_CFG_BYPASS_AI_CAL_POS(7)
+#define NI_M_CFG_BYPASS_AI_CAL_MASK (NI_M_CFG_BYPASS_AI_CAL_POS_MASK | \
+ NI_M_CFG_BYPASS_AI_CAL_NEG_MASK | \
+ NI_M_CFG_BYPASS_AI_MODE_MUX_MASK | \
+ NI_M_CFG_BYPASS_AO_CAL_MASK)
+#define NI_M_CFG_BYPASS_AI_BANK(x) (((x) & 0xf) << 3)
+#define NI_M_CFG_BYPASS_AI_BANK_MASK NI_M_CFG_BYPASS_AI_BANK(0xf)
+#define NI_M_CFG_BYPASS_AI_CHAN(x) (((x) & 0x7) << 0)
+#define NI_M_CFG_BYPASS_AI_CHAN_MASK NI_M_CFG_BYPASS_AI_CHAN(7)
+#define NI_M_SCXI_DIO_ENA_REG 0x21c
+#define NI_M_CDI_FIFO_DATA_REG 0x220
+#define NI_M_CDO_FIFO_DATA_REG 0x220
+#define NI_M_CDIO_STATUS_REG 0x224
+#define NI_M_CDIO_STATUS_CDI_OVERFLOW BIT(20)
+#define NI_M_CDIO_STATUS_CDI_OVERRUN BIT(19)
+#define NI_M_CDIO_STATUS_CDI_ERROR (NI_M_CDIO_STATUS_CDI_OVERFLOW | \
+ NI_M_CDIO_STATUS_CDI_OVERRUN)
+#define NI_M_CDIO_STATUS_CDI_FIFO_REQ BIT(18)
+#define NI_M_CDIO_STATUS_CDI_FIFO_FULL BIT(17)
+#define NI_M_CDIO_STATUS_CDI_FIFO_EMPTY BIT(16)
+#define NI_M_CDIO_STATUS_CDO_UNDERFLOW BIT(4)
+#define NI_M_CDIO_STATUS_CDO_OVERRUN BIT(3)
+#define NI_M_CDIO_STATUS_CDO_ERROR (NI_M_CDIO_STATUS_CDO_UNDERFLOW | \
+ NI_M_CDIO_STATUS_CDO_OVERRUN)
+#define NI_M_CDIO_STATUS_CDO_FIFO_REQ BIT(2)
+#define NI_M_CDIO_STATUS_CDO_FIFO_FULL BIT(1)
+#define NI_M_CDIO_STATUS_CDO_FIFO_EMPTY BIT(0)
+#define NI_M_CDIO_CMD_REG 0x224
+#define NI_M_CDI_CMD_SW_UPDATE BIT(20)
+#define NI_M_CDO_CMD_SW_UPDATE BIT(19)
+#define NI_M_CDO_CMD_F_E_INT_ENA_CLR BIT(17)
+#define NI_M_CDO_CMD_F_E_INT_ENA_SET BIT(16)
+#define NI_M_CDI_CMD_ERR_INT_CONFIRM BIT(15)
+#define NI_M_CDO_CMD_ERR_INT_CONFIRM BIT(14)
+#define NI_M_CDI_CMD_F_REQ_INT_ENA_CLR BIT(13)
+#define NI_M_CDI_CMD_F_REQ_INT_ENA_SET BIT(12)
+#define NI_M_CDO_CMD_F_REQ_INT_ENA_CLR BIT(11)
+#define NI_M_CDO_CMD_F_REQ_INT_ENA_SET BIT(10)
+#define NI_M_CDI_CMD_ERR_INT_ENA_CLR BIT(9)
+#define NI_M_CDI_CMD_ERR_INT_ENA_SET BIT(8)
+#define NI_M_CDO_CMD_ERR_INT_ENA_CLR BIT(7)
+#define NI_M_CDO_CMD_ERR_INT_ENA_SET BIT(6)
+#define NI_M_CDI_CMD_RESET BIT(5)
+#define NI_M_CDO_CMD_RESET BIT(4)
+#define NI_M_CDI_CMD_ARM BIT(3)
+#define NI_M_CDI_CMD_DISARM BIT(2)
+#define NI_M_CDO_CMD_ARM BIT(1)
+#define NI_M_CDO_CMD_DISARM BIT(0)
+#define NI_M_CDI_MODE_REG 0x228
+#define NI_M_CDI_MODE_DATA_LANE(x) (((x) & 0x3) << 12)
+#define NI_M_CDI_MODE_DATA_LANE_MASK NI_M_CDI_MODE_DATA_LANE(3)
+#define NI_M_CDI_MODE_DATA_LANE_0_15 NI_M_CDI_MODE_DATA_LANE(0)
+#define NI_M_CDI_MODE_DATA_LANE_16_31 NI_M_CDI_MODE_DATA_LANE(1)
+#define NI_M_CDI_MODE_DATA_LANE_0_7 NI_M_CDI_MODE_DATA_LANE(0)
+#define NI_M_CDI_MODE_DATA_LANE_8_15 NI_M_CDI_MODE_DATA_LANE(1)
+#define NI_M_CDI_MODE_DATA_LANE_16_23 NI_M_CDI_MODE_DATA_LANE(2)
+#define NI_M_CDI_MODE_DATA_LANE_24_31 NI_M_CDI_MODE_DATA_LANE(3)
+#define NI_M_CDI_MODE_FIFO_MODE BIT(11)
+#define NI_M_CDI_MODE_POLARITY BIT(10)
+#define NI_M_CDI_MODE_HALT_ON_ERROR BIT(9)
+#define NI_M_CDI_MODE_SAMPLE_SRC(x) (((x) & 0x3f) << 0)
+#define NI_M_CDI_MODE_SAMPLE_SRC_MASK NI_M_CDI_MODE_SAMPLE_SRC(0x3f)
+#define NI_M_CDO_MODE_REG 0x22c
+#define NI_M_CDO_MODE_DATA_LANE(x) (((x) & 0x3) << 12)
+#define NI_M_CDO_MODE_DATA_LANE_MASK NI_M_CDO_MODE_DATA_LANE(3)
+#define NI_M_CDO_MODE_DATA_LANE_0_15 NI_M_CDO_MODE_DATA_LANE(0)
+#define NI_M_CDO_MODE_DATA_LANE_16_31 NI_M_CDO_MODE_DATA_LANE(1)
+#define NI_M_CDO_MODE_DATA_LANE_0_7 NI_M_CDO_MODE_DATA_LANE(0)
+#define NI_M_CDO_MODE_DATA_LANE_8_15 NI_M_CDO_MODE_DATA_LANE(1)
+#define NI_M_CDO_MODE_DATA_LANE_16_23 NI_M_CDO_MODE_DATA_LANE(2)
+#define NI_M_CDO_MODE_DATA_LANE_24_31 NI_M_CDO_MODE_DATA_LANE(3)
+#define NI_M_CDO_MODE_FIFO_MODE BIT(11)
+#define NI_M_CDO_MODE_POLARITY BIT(10)
+#define NI_M_CDO_MODE_HALT_ON_ERROR BIT(9)
+#define NI_M_CDO_MODE_RETRANSMIT BIT(8)
+#define NI_M_CDO_MODE_SAMPLE_SRC(x) (((x) & 0x3f) << 0)
+#define NI_M_CDO_MODE_SAMPLE_SRC_MASK NI_M_CDO_MODE_SAMPLE_SRC(0x3f)
+#define NI_M_CDI_MASK_ENA_REG 0x230
+#define NI_M_CDO_MASK_ENA_REG 0x234
+#define NI_M_STATIC_AI_CTRL_REG(x) ((x) ? (0x260 + (x)) : 0x064)
+#define NI_M_AO_REF_ATTENUATION_REG(x) (0x264 + (x))
+#define NI_M_AO_REF_ATTENUATION_X5 BIT(0)
+
+enum {
+ ai_gain_16 = 0,
+ ai_gain_8,
+ ai_gain_14,
+ ai_gain_4,
+ ai_gain_611x,
+ ai_gain_622x,
+ ai_gain_628x,
+ ai_gain_6143
};
-static inline unsigned int DACx_Direct_Data_671x(int channel)
-{
- return channel;
-}
-enum AO_Misc_611x_Bits {
- CLEAR_WG = 1,
+enum caldac_enum {
+ caldac_none = 0,
+ mb88341,
+ dac8800,
+ dac8043,
+ ad8522,
+ ad8804,
+ ad8842,
+ ad8804_debug
};
-enum cs5529_configuration_bits {
- CSCFG_CAL_CONTROL_MASK = 0x7,
- CSCFG_SELF_CAL_OFFSET = 0x1,
- CSCFG_SELF_CAL_GAIN = 0x2,
- CSCFG_SELF_CAL_OFFSET_GAIN = 0x3,
- CSCFG_SYSTEM_CAL_OFFSET = 0x5,
- CSCFG_SYSTEM_CAL_GAIN = 0x6,
- CSCFG_DONE = 1 << 3,
- CSCFG_POWER_SAVE_SELECT = 1 << 4,
- CSCFG_PORT_MODE = 1 << 5,
- CSCFG_RESET_VALID = 1 << 6,
- CSCFG_RESET = 1 << 7,
- CSCFG_UNIPOLAR = 1 << 12,
- CSCFG_WORD_RATE_2180_CYCLES = 0x0 << 13,
- CSCFG_WORD_RATE_1092_CYCLES = 0x1 << 13,
- CSCFG_WORD_RATE_532_CYCLES = 0x2 << 13,
- CSCFG_WORD_RATE_388_CYCLES = 0x3 << 13,
- CSCFG_WORD_RATE_324_CYCLES = 0x4 << 13,
- CSCFG_WORD_RATE_17444_CYCLES = 0x5 << 13,
- CSCFG_WORD_RATE_8724_CYCLES = 0x6 << 13,
- CSCFG_WORD_RATE_4364_CYCLES = 0x7 << 13,
- CSCFG_WORD_RATE_MASK = 0x7 << 13,
- CSCFG_LOW_POWER = 1 << 16,
-};
-static inline unsigned int CS5529_CONFIG_DOUT(int output)
-{
- return 1 << (18 + output);
-}
-
-static inline unsigned int CS5529_CONFIG_AOUT(int output)
-{
- return 1 << (22 + output);
-}
-
-enum cs5529_command_bits {
- CSCMD_POWER_SAVE = 0x1,
- CSCMD_REGISTER_SELECT_MASK = 0xe,
- CSCMD_OFFSET_REGISTER = 0x0,
- CSCMD_GAIN_REGISTER = 0x2,
- CSCMD_CONFIG_REGISTER = 0x4,
- CSCMD_READ = 0x10,
- CSCMD_CONTINUOUS_CONVERSIONS = 0x20,
- CSCMD_SINGLE_CONVERSION = 0x40,
- CSCMD_COMMAND = 0x80,
-};
-enum cs5529_status_bits {
- CSS_ADC_BUSY = 0x1,
- CSS_OSC_DETECT = 0x2, /* indicates adc error */
- CSS_OVERRANGE = 0x4,
-};
-#define SerDacLd(x) (0x08<<(x))
-
-/*
- This is stuff unique to the NI E series drivers,
- but I thought I'd put it here anyway.
-*/
-enum { ai_gain_16 =
- 0, ai_gain_8, ai_gain_14, ai_gain_4, ai_gain_611x, ai_gain_622x,
- ai_gain_628x, ai_gain_6143
-};
-enum caldac_enum { caldac_none = 0, mb88341, dac8800, dac8043, ad8522,
- ad8804, ad8842, ad8804_debug
-};
enum ni_reg_type {
ni_reg_normal = 0x0,
ni_reg_611x = 0x1,
ni_reg_6143 = 0x20
};
-static const struct comedi_lrange range_ni_E_ao_ext;
-
-enum m_series_register_offsets {
- M_Offset_CDIO_DMA_Select = 0x7, /* write */
- M_Offset_SCXI_Status = 0x7, /* read */
- M_Offset_AI_AO_Select = 0x9, /* write, same offset as e-series */
- M_Offset_SCXI_Serial_Data_In = 0x9, /* read */
- M_Offset_G0_G1_Select = 0xb, /* write, same offset as e-series */
- M_Offset_Misc_Command = 0xf,
- M_Offset_SCXI_Serial_Data_Out = 0x11,
- M_Offset_SCXI_Control = 0x13,
- M_Offset_SCXI_Output_Enable = 0x15,
- M_Offset_AI_FIFO_Data = 0x1c,
- M_Offset_Static_Digital_Output = 0x24, /* write */
- M_Offset_Static_Digital_Input = 0x24, /* read */
- M_Offset_DIO_Direction = 0x28,
- M_Offset_Cal_PWM = 0x40,
- M_Offset_AI_Config_FIFO_Data = 0x5e,
- M_Offset_Interrupt_C_Enable = 0x88, /* write */
- M_Offset_Interrupt_C_Status = 0x88, /* read */
- M_Offset_Analog_Trigger_Control = 0x8c,
- M_Offset_AO_Serial_Interrupt_Enable = 0xa0,
- M_Offset_AO_Serial_Interrupt_Ack = 0xa1, /* write */
- M_Offset_AO_Serial_Interrupt_Status = 0xa1, /* read */
- M_Offset_AO_Calibration = 0xa3,
- M_Offset_AO_FIFO_Data = 0xa4,
- M_Offset_PFI_Filter = 0xb0,
- M_Offset_RTSI_Filter = 0xb4,
- M_Offset_SCXI_Legacy_Compatibility = 0xbc,
- M_Offset_Interrupt_A_Ack = 0x104, /* write */
- M_Offset_AI_Status_1 = 0x104, /* read */
- M_Offset_Interrupt_B_Ack = 0x106, /* write */
- M_Offset_AO_Status_1 = 0x106, /* read */
- M_Offset_AI_Command_2 = 0x108, /* write */
- M_Offset_G01_Status = 0x108, /* read */
- M_Offset_AO_Command_2 = 0x10a,
- M_Offset_AO_Status_2 = 0x10c, /* read */
- M_Offset_G0_Command = 0x10c, /* write */
- M_Offset_G1_Command = 0x10e, /* write */
- M_Offset_G0_HW_Save = 0x110,
- M_Offset_G0_HW_Save_High = 0x110,
- M_Offset_AI_Command_1 = 0x110,
- M_Offset_G0_HW_Save_Low = 0x112,
- M_Offset_AO_Command_1 = 0x112,
- M_Offset_G1_HW_Save = 0x114,
- M_Offset_G1_HW_Save_High = 0x114,
- M_Offset_G1_HW_Save_Low = 0x116,
- M_Offset_AI_Mode_1 = 0x118,
- M_Offset_G0_Save = 0x118,
- M_Offset_G0_Save_High = 0x118,
- M_Offset_AI_Mode_2 = 0x11a,
- M_Offset_G0_Save_Low = 0x11a,
- M_Offset_AI_SI_Load_A = 0x11c,
- M_Offset_G1_Save = 0x11c,
- M_Offset_G1_Save_High = 0x11c,
- M_Offset_G1_Save_Low = 0x11e,
- M_Offset_AI_SI_Load_B = 0x120, /* write */
- M_Offset_AO_UI_Save = 0x120, /* read */
- M_Offset_AI_SC_Load_A = 0x124, /* write */
- M_Offset_AO_BC_Save = 0x124, /* read */
- M_Offset_AI_SC_Load_B = 0x128, /* write */
- M_Offset_AO_UC_Save = 0x128, /* read */
- M_Offset_AI_SI2_Load_A = 0x12c,
- M_Offset_AI_SI2_Load_B = 0x130,
- M_Offset_G0_Mode = 0x134,
- M_Offset_G1_Mode = 0x136, /* write */
- M_Offset_Joint_Status_1 = 0x136, /* read */
- M_Offset_G0_Load_A = 0x138,
- M_Offset_Joint_Status_2 = 0x13a,
- M_Offset_G0_Load_B = 0x13c,
- M_Offset_G1_Load_A = 0x140,
- M_Offset_G1_Load_B = 0x144,
- M_Offset_G0_Input_Select = 0x148,
- M_Offset_G1_Input_Select = 0x14a,
- M_Offset_AO_Mode_1 = 0x14c,
- M_Offset_AO_Mode_2 = 0x14e,
- M_Offset_AO_UI_Load_A = 0x150,
- M_Offset_AO_UI_Load_B = 0x154,
- M_Offset_AO_BC_Load_A = 0x158,
- M_Offset_AO_BC_Load_B = 0x15c,
- M_Offset_AO_UC_Load_A = 0x160,
- M_Offset_AO_UC_Load_B = 0x164,
- M_Offset_Clock_and_FOUT = 0x170,
- M_Offset_IO_Bidirection_Pin = 0x172,
- M_Offset_RTSI_Trig_Direction = 0x174,
- M_Offset_Interrupt_Control = 0x176,
- M_Offset_AI_Output_Control = 0x178,
- M_Offset_Analog_Trigger_Etc = 0x17a,
- M_Offset_AI_START_STOP_Select = 0x17c,
- M_Offset_AI_Trigger_Select = 0x17e,
- M_Offset_AI_SI_Save = 0x180, /* read */
- M_Offset_AI_DIV_Load_A = 0x180, /* write */
- M_Offset_AI_SC_Save = 0x184, /* read */
- M_Offset_AO_Start_Select = 0x184, /* write */
- M_Offset_AO_Trigger_Select = 0x186,
- M_Offset_AO_Mode_3 = 0x18c,
- M_Offset_G0_Autoincrement = 0x188,
- M_Offset_G1_Autoincrement = 0x18a,
- M_Offset_Joint_Reset = 0x190,
- M_Offset_Interrupt_A_Enable = 0x192,
- M_Offset_Interrupt_B_Enable = 0x196,
- M_Offset_AI_Personal = 0x19a,
- M_Offset_AO_Personal = 0x19c,
- M_Offset_RTSI_Trig_A_Output = 0x19e,
- M_Offset_RTSI_Trig_B_Output = 0x1a0,
- M_Offset_RTSI_Shared_MUX = 0x1a2,
- M_Offset_AO_Output_Control = 0x1ac,
- M_Offset_AI_Mode_3 = 0x1ae,
- M_Offset_Configuration_Memory_Clear = 0x1a4,
- M_Offset_AI_FIFO_Clear = 0x1a6,
- M_Offset_AO_FIFO_Clear = 0x1a8,
- M_Offset_G0_Counting_Mode = 0x1b0,
- M_Offset_G1_Counting_Mode = 0x1b2,
- M_Offset_G0_Second_Gate = 0x1b4,
- M_Offset_G1_Second_Gate = 0x1b6,
- M_Offset_G0_DMA_Config = 0x1b8, /* write */
- M_Offset_G0_DMA_Status = 0x1b8, /* read */
- M_Offset_G1_DMA_Config = 0x1ba, /* write */
- M_Offset_G1_DMA_Status = 0x1ba, /* read */
- M_Offset_G0_MSeries_ABZ = 0x1c0,
- M_Offset_G1_MSeries_ABZ = 0x1c2,
- M_Offset_Clock_and_Fout2 = 0x1c4,
- M_Offset_PLL_Control = 0x1c6,
- M_Offset_PLL_Status = 0x1c8,
- M_Offset_PFI_Output_Select_1 = 0x1d0,
- M_Offset_PFI_Output_Select_2 = 0x1d2,
- M_Offset_PFI_Output_Select_3 = 0x1d4,
- M_Offset_PFI_Output_Select_4 = 0x1d6,
- M_Offset_PFI_Output_Select_5 = 0x1d8,
- M_Offset_PFI_Output_Select_6 = 0x1da,
- M_Offset_PFI_DI = 0x1dc,
- M_Offset_PFI_DO = 0x1de,
- M_Offset_AI_Config_FIFO_Bypass = 0x218,
- M_Offset_SCXI_DIO_Enable = 0x21c,
- M_Offset_CDI_FIFO_Data = 0x220, /* read */
- M_Offset_CDO_FIFO_Data = 0x220, /* write */
- M_Offset_CDIO_Status = 0x224, /* read */
- M_Offset_CDIO_Command = 0x224, /* write */
- M_Offset_CDI_Mode = 0x228,
- M_Offset_CDO_Mode = 0x22c,
- M_Offset_CDI_Mask_Enable = 0x230,
- M_Offset_CDO_Mask_Enable = 0x234,
-};
-static inline int M_Offset_AO_Waveform_Order(int channel)
-{
- return 0xc2 + 0x4 * channel;
-};
-
-static inline int M_Offset_AO_Config_Bank(int channel)
-{
- return 0xc3 + 0x4 * channel;
-};
-
-static inline int M_Offset_DAC_Direct_Data(int channel)
-{
- return 0xc0 + 0x4 * channel;
-}
-
-static inline int M_Offset_Gen_PWM(int channel)
-{
- return 0x44 + 0x2 * channel;
-}
-
-static inline int M_Offset_Static_AI_Control(int i)
-{
- int offset[] = {
- 0x64,
- 0x261,
- 0x262,
- 0x263,
- };
- if (((unsigned)i) >= ARRAY_SIZE(offset)) {
- pr_err("%s: invalid channel=%i\n", __func__, i);
- return offset[0];
- }
- return offset[i];
-};
-
-static inline int M_Offset_AO_Reference_Attenuation(int channel)
-{
- int offset[] = {
- 0x264,
- 0x265,
- 0x266,
- 0x267
- };
- if (((unsigned)channel) >= ARRAY_SIZE(offset)) {
- pr_err("%s: invalid channel=%i\n", __func__, channel);
- return offset[0];
- }
- return offset[channel];
-};
-
-static inline unsigned M_Offset_PFI_Output_Select(unsigned n)
-{
- if (n < 1 || n > NUM_PFI_OUTPUT_SELECT_REGS) {
- pr_err("%s: invalid pfi output select register=%i\n",
- __func__, n);
- return M_Offset_PFI_Output_Select_1;
- }
- return M_Offset_PFI_Output_Select_1 + (n - 1) * 2;
-}
-
-enum MSeries_AI_Config_FIFO_Data_Bits {
- MSeries_AI_Config_Channel_Type_Mask = 0x7 << 6,
- MSeries_AI_Config_Channel_Type_Calibration_Bits = 0x0,
- MSeries_AI_Config_Channel_Type_Differential_Bits = 0x1 << 6,
- MSeries_AI_Config_Channel_Type_Common_Ref_Bits = 0x2 << 6,
- MSeries_AI_Config_Channel_Type_Ground_Ref_Bits = 0x3 << 6,
- MSeries_AI_Config_Channel_Type_Aux_Bits = 0x5 << 6,
- MSeries_AI_Config_Channel_Type_Ghost_Bits = 0x7 << 6,
- MSeries_AI_Config_Polarity_Bit = 0x1000, /* 0 for 2's complement encoding */
- MSeries_AI_Config_Dither_Bit = 0x2000,
- MSeries_AI_Config_Last_Channel_Bit = 0x4000,
-};
-static inline unsigned MSeries_AI_Config_Channel_Bits(unsigned channel)
-{
- return channel & 0xf;
-}
-
-static inline unsigned MSeries_AI_Config_Bank_Bits(enum ni_reg_type reg_type,
- unsigned channel)
-{
- unsigned bits = channel & 0x30;
- if (reg_type == ni_reg_622x) {
- if (channel & 0x40)
- bits |= 0x400;
- }
- return bits;
-}
-
-static inline unsigned MSeries_AI_Config_Gain_Bits(unsigned range)
-{
- return (range & 0x7) << 9;
-}
-
-enum MSeries_Clock_and_Fout2_Bits {
- MSeries_PLL_In_Source_Select_RTSI0_Bits = 0xb,
- MSeries_PLL_In_Source_Select_Star_Trigger_Bits = 0x14,
- MSeries_PLL_In_Source_Select_RTSI7_Bits = 0x1b,
- MSeries_PLL_In_Source_Select_PXI_Clock10 = 0x1d,
- MSeries_PLL_In_Source_Select_Mask = 0x1f,
- MSeries_Timebase1_Select_Bit = 0x20, /* use PLL for timebase 1 */
- MSeries_Timebase3_Select_Bit = 0x40, /* use PLL for timebase 3 */
- /* use 10MHz instead of 20MHz for RTSI clock frequency. Appears
- to have no effect, at least on pxi-6281, which always uses
- 20MHz rtsi clock frequency */
- MSeries_RTSI_10MHz_Bit = 0x80
-};
-static inline unsigned MSeries_PLL_In_Source_Select_RTSI_Bits(unsigned
- RTSI_channel)
-{
- if (RTSI_channel > 7) {
- pr_err("%s: bug, invalid RTSI_channel=%i\n", __func__,
- RTSI_channel);
- return 0;
- }
- if (RTSI_channel == 7)
- return MSeries_PLL_In_Source_Select_RTSI7_Bits;
- else
- return MSeries_PLL_In_Source_Select_RTSI0_Bits + RTSI_channel;
-}
-
-enum MSeries_PLL_Control_Bits {
- MSeries_PLL_Enable_Bit = 0x1000,
- MSeries_PLL_VCO_Mode_200_325MHz_Bits = 0x0,
- MSeries_PLL_VCO_Mode_175_225MHz_Bits = 0x2000,
- MSeries_PLL_VCO_Mode_100_225MHz_Bits = 0x4000,
- MSeries_PLL_VCO_Mode_75_150MHz_Bits = 0x6000,
-};
-static inline unsigned MSeries_PLL_Divisor_Bits(unsigned divisor)
-{
- static const unsigned max_divisor = 0x10;
- if (divisor < 1 || divisor > max_divisor) {
- pr_err("%s: bug, invalid divisor=%i\n", __func__, divisor);
- return 0;
- }
- return (divisor & 0xf) << 8;
-}
-
-static inline unsigned MSeries_PLL_Multiplier_Bits(unsigned multiplier)
-{
- static const unsigned max_multiplier = 0x100;
- if (multiplier < 1 || multiplier > max_multiplier) {
- pr_err("%s: bug, invalid multiplier=%i\n", __func__,
- multiplier);
- return 0;
- }
- return multiplier & 0xff;
-}
-
-enum MSeries_PLL_Status {
- MSeries_PLL_Locked_Bit = 0x1
-};
-
-enum MSeries_AI_Config_FIFO_Bypass_Bits {
- MSeries_AI_Bypass_Channel_Mask = 0x7,
- MSeries_AI_Bypass_Bank_Mask = 0x78,
- MSeries_AI_Bypass_Cal_Sel_Pos_Mask = 0x380,
- MSeries_AI_Bypass_Cal_Sel_Neg_Mask = 0x1c00,
- MSeries_AI_Bypass_Mode_Mux_Mask = 0x6000,
- MSeries_AO_Bypass_AO_Cal_Sel_Mask = 0x38000,
- MSeries_AI_Bypass_Gain_Mask = 0x1c0000,
- MSeries_AI_Bypass_Dither_Bit = 0x200000,
- MSeries_AI_Bypass_Polarity_Bit = 0x400000, /* 0 for 2's complement encoding */
- MSeries_AI_Bypass_Config_FIFO_Bit = 0x80000000
-};
-static inline unsigned MSeries_AI_Bypass_Cal_Sel_Pos_Bits(int
- calibration_source)
-{
- return (calibration_source << 7) & MSeries_AI_Bypass_Cal_Sel_Pos_Mask;
-}
-
-static inline unsigned MSeries_AI_Bypass_Cal_Sel_Neg_Bits(int
- calibration_source)
-{
- return (calibration_source << 10) & MSeries_AI_Bypass_Cal_Sel_Pos_Mask;
-}
-
-static inline unsigned MSeries_AI_Bypass_Gain_Bits(int gain)
-{
- return (gain << 18) & MSeries_AI_Bypass_Gain_Mask;
-}
-
-enum MSeries_AO_Config_Bank_Bits {
- MSeries_AO_DAC_Offset_Select_Mask = 0x7,
- MSeries_AO_DAC_Offset_0V_Bits = 0x0,
- MSeries_AO_DAC_Offset_5V_Bits = 0x1,
- MSeries_AO_DAC_Reference_Mask = 0x38,
- MSeries_AO_DAC_Reference_10V_Internal_Bits = 0x0,
- MSeries_AO_DAC_Reference_5V_Internal_Bits = 0x8,
- MSeries_AO_Update_Timed_Bit = 0x40,
- MSeries_AO_Bipolar_Bit = 0x80 /* turns on 2's complement encoding */
-};
-
-enum MSeries_AO_Reference_Attenuation_Bits {
- MSeries_Attenuate_x5_Bit = 0x1
-};
-
-static inline unsigned MSeries_Cal_PWM_High_Time_Bits(unsigned count)
-{
- return (count << 16) & 0xffff0000;
-}
-
-static inline unsigned MSeries_Cal_PWM_Low_Time_Bits(unsigned count)
-{
- return count & 0xffff;
-}
-
-static inline unsigned MSeries_PFI_Output_Select_Mask(unsigned channel)
-{
- return 0x1f << (channel % 3) * 5;
-};
-
-static inline unsigned MSeries_PFI_Output_Select_Bits(unsigned channel,
- unsigned source)
-{
- return (source & 0x1f) << ((channel % 3) * 5);
-};
-
-/* inverse to MSeries_PFI_Output_Select_Bits */
-static inline unsigned MSeries_PFI_Output_Select_Source(unsigned channel,
- unsigned bits)
-{
- return (bits >> ((channel % 3) * 5)) & 0x1f;
-};
-
-static inline unsigned MSeries_PFI_Filter_Select_Mask(unsigned channel)
-{
- return 0x3 << (channel * 2);
-}
-
-static inline unsigned MSeries_PFI_Filter_Select_Bits(unsigned channel,
- unsigned filter)
-{
- return (filter << (channel *
- 2)) & MSeries_PFI_Filter_Select_Mask(channel);
-}
-
-enum CDIO_DMA_Select_Bits {
- CDI_DMA_Select_Shift = 0,
- CDI_DMA_Select_Mask = 0xf,
- CDO_DMA_Select_Shift = 4,
- CDO_DMA_Select_Mask = 0xf << CDO_DMA_Select_Shift
-};
-
-enum CDIO_Status_Bits {
- CDO_FIFO_Empty_Bit = 0x1,
- CDO_FIFO_Full_Bit = 0x2,
- CDO_FIFO_Request_Bit = 0x4,
- CDO_Overrun_Bit = 0x8,
- CDO_Underflow_Bit = 0x10,
- CDI_FIFO_Empty_Bit = 0x10000,
- CDI_FIFO_Full_Bit = 0x20000,
- CDI_FIFO_Request_Bit = 0x40000,
- CDI_Overrun_Bit = 0x80000,
- CDI_Overflow_Bit = 0x100000
-};
-
-enum CDIO_Command_Bits {
- CDO_Disarm_Bit = 0x1,
- CDO_Arm_Bit = 0x2,
- CDI_Disarm_Bit = 0x4,
- CDI_Arm_Bit = 0x8,
- CDO_Reset_Bit = 0x10,
- CDI_Reset_Bit = 0x20,
- CDO_Error_Interrupt_Enable_Set_Bit = 0x40,
- CDO_Error_Interrupt_Enable_Clear_Bit = 0x80,
- CDI_Error_Interrupt_Enable_Set_Bit = 0x100,
- CDI_Error_Interrupt_Enable_Clear_Bit = 0x200,
- CDO_FIFO_Request_Interrupt_Enable_Set_Bit = 0x400,
- CDO_FIFO_Request_Interrupt_Enable_Clear_Bit = 0x800,
- CDI_FIFO_Request_Interrupt_Enable_Set_Bit = 0x1000,
- CDI_FIFO_Request_Interrupt_Enable_Clear_Bit = 0x2000,
- CDO_Error_Interrupt_Confirm_Bit = 0x4000,
- CDI_Error_Interrupt_Confirm_Bit = 0x8000,
- CDO_Empty_FIFO_Interrupt_Enable_Set_Bit = 0x10000,
- CDO_Empty_FIFO_Interrupt_Enable_Clear_Bit = 0x20000,
- CDO_SW_Update_Bit = 0x80000,
- CDI_SW_Update_Bit = 0x100000
-};
-
-enum CDI_Mode_Bits {
- CDI_Sample_Source_Select_Mask = 0x3f,
- CDI_Halt_On_Error_Bit = 0x200,
- CDI_Polarity_Bit = 0x400, /* sample clock on falling edge */
- CDI_FIFO_Mode_Bit = 0x800, /* set for half full mode, clear for not empty mode */
- CDI_Data_Lane_Mask = 0x3000, /* data lanes specify which dio channels map to byte or word accesses to the dio fifos */
- CDI_Data_Lane_0_15_Bits = 0x0,
- CDI_Data_Lane_16_31_Bits = 0x1000,
- CDI_Data_Lane_0_7_Bits = 0x0,
- CDI_Data_Lane_8_15_Bits = 0x1000,
- CDI_Data_Lane_16_23_Bits = 0x2000,
- CDI_Data_Lane_24_31_Bits = 0x3000
-};
-
-enum CDO_Mode_Bits {
- CDO_Sample_Source_Select_Mask = 0x3f,
- CDO_Retransmit_Bit = 0x100,
- CDO_Halt_On_Error_Bit = 0x200,
- CDO_Polarity_Bit = 0x400, /* sample clock on falling edge */
- CDO_FIFO_Mode_Bit = 0x800, /* set for half full mode, clear for not full mode */
- CDO_Data_Lane_Mask = 0x3000, /* data lanes specify which dio channels map to byte or word accesses to the dio fifos */
- CDO_Data_Lane_0_15_Bits = 0x0,
- CDO_Data_Lane_16_31_Bits = 0x1000,
- CDO_Data_Lane_0_7_Bits = 0x0,
- CDO_Data_Lane_8_15_Bits = 0x1000,
- CDO_Data_Lane_16_23_Bits = 0x2000,
- CDO_Data_Lane_24_31_Bits = 0x3000
-};
-
-enum Interrupt_C_Enable_Bits {
- Interrupt_Group_C_Enable_Bit = 0x1
-};
-
-enum Interrupt_C_Status_Bits {
- Interrupt_Group_C_Status_Bit = 0x1
-};
-
-#define M_SERIES_EEPROM_SIZE 1024
-
struct ni_board_struct {
const char *name;
int device_id;
enum caldac_enum caldac[3];
};
-#define MAX_N_CALDACS 34
-#define MAX_N_AO_CHAN 8
-#define NUM_GPCT 2
+#define MAX_N_CALDACS 34
+#define MAX_N_AO_CHAN 8
+#define NUM_GPCT 2
+
+#define NUM_PFI_OUTPUT_SELECT_REGS 6
+
+#define M_SERIES_EEPROM_SIZE 1024
struct ni_private {
unsigned short dio_output;
int aimode;
unsigned int ai_calib_source;
unsigned int ai_calib_source_enabled;
+ /* protects access to windowed registers */
spinlock_t window_lock;
+ /* protects interrupt/dma register access */
spinlock_t soft_reg_copy_lock;
+ /* protects mite DMA channel request/release */
spinlock_t mite_channel_lock;
int changain_state;
unsigned int is_6713:1;
};
+static const struct comedi_lrange range_ni_E_ao_ext;
+
#endif /* _COMEDI_NI_STC_H */
/*
* dgap_sindex: much like index(), but it looks for a match of any character in
- * the group, and returns that position. If the first character is a ^, then
- * this will match the first occurrence not in that group.
+ * the group, and returns that position.
*/
static char *dgap_sindex(char *string, char *group)
{
if (!string || !group)
return NULL;
- if (*group == '^') {
- group++;
- for (; *string; string++) {
- for (ptr = group; *ptr; ptr++) {
- if (*ptr == *string)
- break;
- }
- if (*ptr == '\0')
+ for (; *string; string++) {
+ for (ptr = group; *ptr; ptr++) {
+ if (*ptr == *string)
return string;
}
- } else {
- for (; *string; string++) {
- for (ptr = group; *ptr; ptr++) {
- if (*ptr == *string)
- return string;
- }
- }
}
return NULL;
return rc;
}
+/*
+ * dgap_cleanup_board()
+ *
+ * Free all the memory associated with a board
+ */
+static void dgap_cleanup_board(struct board_t *brd)
+{
+ unsigned int i;
+
+ if (!brd || brd->magic != DGAP_BOARD_MAGIC)
+ return;
+
+ dgap_free_irq(brd);
+
+ tasklet_kill(&brd->helper_tasklet);
+
+ dgap_unmap(brd);
+
+ /* Free all allocated channels structs */
+ for (i = 0; i < MAXPORTS ; i++)
+ kfree(brd->channels[i]);
+
+ kfree(brd->flipbuf);
+ kfree(brd->flipflagbuf);
+
+ dgap_board[brd->boardnum] = NULL;
+
+ kfree(brd);
+}
+
static void dgap_remove_one(struct pci_dev *dev)
{
- /* Do Nothing */
+ unsigned int i;
+ ulong lock_flags;
+ struct pci_driver *drv = to_pci_driver(dev->dev.driver);
+
+ 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);
+
+ device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
+ class_destroy(dgap_class);
+ unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
+
+ for (i = 0; i < dgap_numboards; ++i) {
+ dgap_remove_ports_sysfiles(dgap_board[i]);
+ dgap_cleanup_tty(dgap_board[i]);
+ dgap_cleanup_board(dgap_board[i]);
+ }
+
+ dgap_cleanup_nodes();
}
static struct pci_driver dgap_driver = {
unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
}
-/*
- * dgap_cleanup_board()
- *
- * Free all the memory associated with a board
- */
-static void dgap_cleanup_board(struct board_t *brd)
-{
- unsigned int i;
-
- if (!brd || brd->magic != DGAP_BOARD_MAGIC)
- return;
-
- dgap_free_irq(brd);
-
- tasklet_kill(&brd->helper_tasklet);
-
- dgap_unmap(brd);
-
- /* Free all allocated channels structs */
- for (i = 0; i < MAXPORTS ; i++)
- kfree(brd->channels[i]);
-
- kfree(brd->flipbuf);
- kfree(brd->flipflagbuf);
-
- dgap_board[brd->boardnum] = NULL;
-
- kfree(brd);
-}
-
-
/************************************************************************
*
* Driver load/unload functions
*/
static void dgap_cleanup_module(void)
{
- unsigned int i;
- ulong 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(&dgap_driver);
-
- device_destroy(dgap_class, MKDEV(DIGI_DGAP_MAJOR, 0));
- class_destroy(dgap_class);
- unregister_chrdev(DIGI_DGAP_MAJOR, "dgap");
-
- for (i = 0; i < dgap_numboards; ++i) {
- dgap_remove_ports_sysfiles(dgap_board[i]);
- dgap_cleanup_tty(dgap_board[i]);
- dgap_cleanup_board(dgap_board[i]);
- }
-
- dgap_cleanup_nodes();
-
if (dgap_numboards)
pci_unregister_driver(&dgap_driver);
}
unsigned int start_flag;
unsigned int payload_size;
unsigned short packet_type;
- int dummy_cnt;
+ int total_len;
u32 packet_size_sum = r->offset;
int index;
int ret = TO_HOST_INVALID_PACKET;
break;
}
- dummy_cnt = ALIGN(MUX_HEADER_SIZE + payload_size, 4);
+ total_len = ALIGN(MUX_HEADER_SIZE + payload_size, 4);
if (len - packet_size_sum <
- MUX_HEADER_SIZE + payload_size + dummy_cnt) {
+ total_len) {
pr_err("invalid payload : %d %d %04x\n",
payload_size, len, packet_type);
break;
break;
}
- packet_size_sum += MUX_HEADER_SIZE + payload_size + dummy_cnt;
+ packet_size_sum += total_len;
if (len - packet_size_sum <= MUX_HEADER_SIZE + 2) {
ret = r->callback(NULL,
0,
struct mux_pkt_header *mux_header;
struct mux_tx *t = NULL;
static u32 seq_num = 1;
- int dummy_cnt;
int total_len;
int ret;
unsigned long flags;
spin_lock_irqsave(&mux_dev->write_lock, flags);
- dummy_cnt = ALIGN(MUX_HEADER_SIZE + len, 4);
-
- total_len = len + MUX_HEADER_SIZE + dummy_cnt;
+ total_len = ALIGN(MUX_HEADER_SIZE + len, 4);
t = alloc_mux_tx(total_len);
if (!t) {
mux_header->packet_type = __cpu_to_le16(packet_type[tty_index]);
memcpy(t->buf+MUX_HEADER_SIZE, data, len);
- memset(t->buf+MUX_HEADER_SIZE+len, 0, dummy_cnt);
+ memset(t->buf+MUX_HEADER_SIZE+len, 0, total_len - MUX_HEADER_SIZE -
+ len);
t->len = total_len;
t->callback = cb;
+++ /dev/null
-menuconfig I2O
- tristate "I2O device support"
- depends on PCI
- ---help---
- The Intelligent Input/Output (I2O) architecture allows hardware
- drivers to be split into two parts: an operating system specific
- module called the OSM and an hardware specific module called the
- HDM. The OSM can talk to a whole range of HDM's, and ideally the
- HDM's are not OS dependent. This allows for the same HDM driver to
- be used under different operating systems if the relevant OSM is in
- place. In order for this to work, you need to have an I2O interface
- adapter card in your computer. This card contains a special I/O
- processor (IOP), thus allowing high speeds since the CPU does not
- have to deal with I/O.
-
- If you say Y here, you will get a choice of interface adapter
- drivers and OSM's with the following questions.
-
- To compile this support as a module, choose M here: the
- modules will be called i2o_core.
-
- If unsure, say N.
-
-if I2O
-
-config I2O_LCT_NOTIFY_ON_CHANGES
- bool "Enable LCT notification"
- default y
- ---help---
- Only say N here if you have a I2O controller from SUN. The SUN
- firmware doesn't support LCT notification on changes. If this option
- is enabled on such a controller the driver will hang up in a endless
- loop. On all other controllers say Y.
-
- If unsure, say Y.
-
-config I2O_EXT_ADAPTEC
- bool "Enable Adaptec extensions"
- default y
- ---help---
- Say Y for support of raidutils for Adaptec I2O controllers. You also
- have to say Y to "I2O Configuration support", "I2O SCSI OSM" below
- and to "SCSI generic support" under "SCSI device configuration".
-
-config I2O_EXT_ADAPTEC_DMA64
- bool "Enable 64-bit DMA"
- depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G )
- default y
- ---help---
- Say Y for support of 64-bit DMA transfer mode on Adaptec I2O
- controllers.
- Note: You need at least firmware version 3709.
-
-config I2O_CONFIG
- tristate "I2O Configuration support"
- depends on VIRT_TO_BUS
- ---help---
- Say Y for support of the configuration interface for the I2O adapters.
- If you have a RAID controller from Adaptec and you want to use the
- raidutils to manage your RAID array, you have to say Y here.
-
- To compile this support as a module, choose M here: the
- module will be called i2o_config.
-
- Note: If you want to use the new API you have to download the
- i2o_config patch from http://i2o.shadowconnect.com/
-
-config I2O_CONFIG_OLD_IOCTL
- bool "Enable ioctls (OBSOLETE)"
- depends on I2O_CONFIG
- default y
- ---help---
- Enables old ioctls.
-
-config I2O_BUS
- tristate "I2O Bus Adapter OSM"
- ---help---
- Include support for the I2O Bus Adapter OSM. The Bus Adapter OSM
- provides access to the busses on the I2O controller. The main purpose
- is to rescan the bus to find new devices.
-
- To compile this support as a module, choose M here: the
- module will be called i2o_bus.
-
-config I2O_BLOCK
- tristate "I2O Block OSM"
- depends on BLOCK
- ---help---
- Include support for the I2O Block OSM. The Block OSM presents disk
- and other structured block devices to the operating system. If you
- are using an RAID controller, you could access the array only by
- the Block OSM driver. But it is possible to access the single disks
- by the SCSI OSM driver, for example to monitor the disks.
-
- To compile this support as a module, choose M here: the
- module will be called i2o_block.
-
-config I2O_SCSI
- tristate "I2O SCSI OSM"
- depends on SCSI
- ---help---
- Allows direct SCSI access to SCSI devices on a SCSI or FibreChannel
- I2O controller. You can use both the SCSI and Block OSM together if
- you wish. To access a RAID array, you must use the Block OSM driver.
- But you could use the SCSI OSM driver to monitor the single disks.
-
- To compile this support as a module, choose M here: the
- module will be called i2o_scsi.
-
-config I2O_PROC
- tristate "I2O /proc support"
- ---help---
- If you say Y here and to "/proc file system support", you will be
- able to read I2O related information from the virtual directory
- /proc/i2o.
-
- To compile this support as a module, choose M here: the
- module will be called i2o_proc.
-
-endif # I2O
+++ /dev/null
-#
-# Makefile for the kernel I2O OSM.
-#
-# Note : at this point, these files are compiled on all systems.
-# In the future, some of these should be built conditionally.
-#
-
-i2o_core-y += iop.o driver.o device.o debug.o pci.o exec-osm.o memory.o
-i2o_bus-y += bus-osm.o
-i2o_config-y += config-osm.o
-obj-$(CONFIG_I2O) += i2o_core.o
-obj-$(CONFIG_I2O_CONFIG)+= i2o_config.o
-obj-$(CONFIG_I2O_BUS) += i2o_bus.o
-obj-$(CONFIG_I2O_BLOCK) += i2o_block.o
-obj-$(CONFIG_I2O_SCSI) += i2o_scsi.o
-obj-$(CONFIG_I2O_PROC) += i2o_proc.o
+++ /dev/null
-
- Linux I2O Support (c) Copyright 1999 Red Hat Software
- and others.
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version
- 2 of the License, or (at your option) any later version.
-
-AUTHORS (so far)
-
-Alan Cox, Building Number Three Ltd.
- Core code, SCSI and Block OSMs
-
-Steve Ralston, LSI Logic Corp.
- Debugging SCSI and Block OSM
-
-Deepak Saxena, Intel Corp.
- Various core/block extensions
- /proc interface, bug fixes
- Ioctl interfaces for control
- Debugging LAN OSM
-
-Philip Rumpf
- Fixed assorted dumb SMP locking bugs
-
-Juha Sievanen, University of Helsinki Finland
- LAN OSM code
- /proc interface to LAN class
- Bug fixes
- Core code extensions
-
-Auvo Häkkinen, University of Helsinki Finland
- LAN OSM code
- /Proc interface to LAN class
- Bug fixes
- Core code extensions
-
-Taneli Vähäkangas, University of Helsinki Finland
- Fixes to i2o_config
-
-CREDITS
-
- This work was made possible by
-
-Red Hat Software
- Funding for the Building #3 part of the project
-
-Symbios Logic (Now LSI)
- Host adapters, hints, known to work platforms when I hit
- compatibility problems
-
-BoxHill Corporation
- Loan of initial FibreChannel disk array used for development work.
-
-European Commission
- Funding the work done by the University of Helsinki
-
-SysKonnect
- Loan of FDDI and Gigabit Ethernet cards
-
-ASUSTeK
- Loan of I2O motherboard
-
-STATUS:
-
-o The core setup works within limits.
-o The scsi layer seems to almost work.
- I'm still chasing down the hang bug.
-o The block OSM is mostly functional
-o LAN OSM works with FDDI and Ethernet cards.
-
-TO DO:
-
-General:
-o Provide hidden address space if asked
-o Long term message flow control
-o PCI IOP's without interrupts are not supported yet
-o Push FAIL handling into the core
-o DDM control interfaces for module load etc
-o Add I2O 2.0 support (Deffered to 2.5 kernel)
-
-Block:
-o Multiple major numbers
-o Read ahead and cache handling stuff. Talk to Ingo and people
-o Power management
-o Finish Media changers
-
-SCSI:
-o Find the right way to associate drives/luns/busses
-
-Lan:
-o Performance tuning
-o Test Fibre Channel code
-
-Tape:
-o Anyone seen anything implementing this ?
- (D.S: Will attempt to do so if spare cycles permit)
+++ /dev/null
-
-Linux I2O User Space Interface
-rev 0.3 - 04/20/99
-
-=============================================================================
-Originally written by Deepak Saxena(deepak@plexity.net)
-Currently maintained by Deepak Saxena(deepak@plexity.net)
-=============================================================================
-
-I. Introduction
-
-The Linux I2O subsystem provides a set of ioctl() commands that can be
-utilized by user space applications to communicate with IOPs and devices
-on individual IOPs. This document defines the specific ioctl() commands
-that are available to the user and provides examples of their uses.
-
-This document assumes the reader is familiar with or has access to the
-I2O specification as no I2O message parameters are outlined. For information
-on the specification, see http://www.i2osig.org
-
-This document and the I2O user space interface are currently maintained
-by Deepak Saxena. Please send all comments, errata, and bug fixes to
-deepak@csociety.purdue.edu
-
-II. IOP Access
-
-Access to the I2O subsystem is provided through the device file named
-/dev/i2o/ctl. This file is a character file with major number 10 and minor
-number 166. It can be created through the following command:
-
- mknod /dev/i2o/ctl c 10 166
-
-III. Determining the IOP Count
-
- SYNOPSIS
-
- ioctl(fd, I2OGETIOPS, int *count);
-
- u8 count[MAX_I2O_CONTROLLERS];
-
- DESCRIPTION
-
- This function returns the system's active IOP table. count should
- point to a buffer containing MAX_I2O_CONTROLLERS entries. Upon
- returning, each entry will contain a non-zero value if the given
- IOP unit is active, and NULL if it is inactive or non-existent.
-
- RETURN VALUE.
-
- Returns 0 if no errors occur, and -1 otherwise. If an error occurs,
- errno is set appropriately:
-
- EFAULT Invalid user space pointer was passed
-
-IV. Getting Hardware Resource Table
-
- SYNOPSIS
-
- ioctl(fd, I2OHRTGET, struct i2o_cmd_hrt *hrt);
-
- struct i2o_cmd_hrtlct
- {
- u32 iop; /* IOP unit number */
- void *resbuf; /* Buffer for result */
- u32 *reslen; /* Buffer length in bytes */
- };
-
- DESCRIPTION
-
- This function returns the Hardware Resource Table of the IOP specified
- by hrt->iop in the buffer pointed to by hrt->resbuf. The actual size of
- the data is written into *(hrt->reslen).
-
- RETURNS
-
- This function returns 0 if no errors occur. If an error occurs, -1
- is returned and errno is set appropriately:
-
- EFAULT Invalid user space pointer was passed
- ENXIO Invalid IOP number
- ENOBUFS Buffer not large enough. If this occurs, the required
- buffer length is written into *(hrt->reslen)
-
-V. Getting Logical Configuration Table
-
- SYNOPSIS
-
- ioctl(fd, I2OLCTGET, struct i2o_cmd_lct *lct);
-
- struct i2o_cmd_hrtlct
- {
- u32 iop; /* IOP unit number */
- void *resbuf; /* Buffer for result */
- u32 *reslen; /* Buffer length in bytes */
- };
-
- DESCRIPTION
-
- This function returns the Logical Configuration Table of the IOP specified
- by lct->iop in the buffer pointed to by lct->resbuf. The actual size of
- the data is written into *(lct->reslen).
-
- RETURNS
-
- This function returns 0 if no errors occur. If an error occurs, -1
- is returned and errno is set appropriately:
-
- EFAULT Invalid user space pointer was passed
- ENXIO Invalid IOP number
- ENOBUFS Buffer not large enough. If this occurs, the required
- buffer length is written into *(lct->reslen)
-
-VI. Setting Parameters
-
- SYNOPSIS
-
- ioctl(fd, I2OPARMSET, struct i2o_parm_setget *ops);
-
- struct i2o_cmd_psetget
- {
- u32 iop; /* IOP unit number */
- u32 tid; /* Target device TID */
- void *opbuf; /* Operation List buffer */
- u32 oplen; /* Operation List buffer length in bytes */
- void *resbuf; /* Result List buffer */
- u32 *reslen; /* Result List buffer length in bytes */
- };
-
- DESCRIPTION
-
- This function posts a UtilParamsSet message to the device identified
- by ops->iop and ops->tid. The operation list for the message is
- sent through the ops->opbuf buffer, and the result list is written
- into the buffer pointed to by ops->resbuf. The number of bytes
- written is placed into *(ops->reslen).
-
- RETURNS
-
- The return value is the size in bytes of the data written into
- ops->resbuf if no errors occur. If an error occurs, -1 is returned
- and errno is set appropriately:
-
- EFAULT Invalid user space pointer was passed
- ENXIO Invalid IOP number
- ENOBUFS Buffer not large enough. If this occurs, the required
- buffer length is written into *(ops->reslen)
- ETIMEDOUT Timeout waiting for reply message
- ENOMEM Kernel memory allocation error
-
- A return value of 0 does not mean that the value was actually
- changed properly on the IOP. The user should check the result
- list to determine the specific status of the transaction.
-
-VII. Getting Parameters
-
- SYNOPSIS
-
- ioctl(fd, I2OPARMGET, struct i2o_parm_setget *ops);
-
- struct i2o_parm_setget
- {
- u32 iop; /* IOP unit number */
- u32 tid; /* Target device TID */
- void *opbuf; /* Operation List buffer */
- u32 oplen; /* Operation List buffer length in bytes */
- void *resbuf; /* Result List buffer */
- u32 *reslen; /* Result List buffer length in bytes */
- };
-
- DESCRIPTION
-
- This function posts a UtilParamsGet message to the device identified
- by ops->iop and ops->tid. The operation list for the message is
- sent through the ops->opbuf buffer, and the result list is written
- into the buffer pointed to by ops->resbuf. The actual size of data
- written is placed into *(ops->reslen).
-
- RETURNS
-
- EFAULT Invalid user space pointer was passed
- ENXIO Invalid IOP number
- ENOBUFS Buffer not large enough. If this occurs, the required
- buffer length is written into *(ops->reslen)
- ETIMEDOUT Timeout waiting for reply message
- ENOMEM Kernel memory allocation error
-
- A return value of 0 does not mean that the value was actually
- properly retrieved. The user should check the result list
- to determine the specific status of the transaction.
-
-VIII. Downloading Software
-
- SYNOPSIS
-
- ioctl(fd, I2OSWDL, struct i2o_sw_xfer *sw);
-
- struct i2o_sw_xfer
- {
- u32 iop; /* IOP unit number */
- u8 flags; /* DownloadFlags field */
- u8 sw_type; /* Software type */
- u32 sw_id; /* Software ID */
- void *buf; /* Pointer to software buffer */
- u32 *swlen; /* Length of software buffer */
- u32 *maxfrag; /* Number of fragments */
- u32 *curfrag; /* Current fragment number */
- };
-
- DESCRIPTION
-
- This function downloads a software fragment pointed by sw->buf
- to the iop identified by sw->iop. The DownloadFlags, SwID, SwType
- and SwSize fields of the ExecSwDownload message are filled in with
- the values of sw->flags, sw->sw_id, sw->sw_type and *(sw->swlen).
-
- The fragments _must_ be sent in order and be 8K in size. The last
- fragment _may_ be shorter, however. The kernel will compute its
- size based on information in the sw->swlen field.
-
- Please note that SW transfers can take a long time.
-
- RETURNS
-
- This function returns 0 no errors occur. If an error occurs, -1
- is returned and errno is set appropriately:
-
- EFAULT Invalid user space pointer was passed
- ENXIO Invalid IOP number
- ETIMEDOUT Timeout waiting for reply message
- ENOMEM Kernel memory allocation error
-
-IX. Uploading Software
-
- SYNOPSIS
-
- ioctl(fd, I2OSWUL, struct i2o_sw_xfer *sw);
-
- struct i2o_sw_xfer
- {
- u32 iop; /* IOP unit number */
- u8 flags; /* UploadFlags */
- u8 sw_type; /* Software type */
- u32 sw_id; /* Software ID */
- void *buf; /* Pointer to software buffer */
- u32 *swlen; /* Length of software buffer */
- u32 *maxfrag; /* Number of fragments */
- u32 *curfrag; /* Current fragment number */
- };
-
- DESCRIPTION
-
- This function uploads a software fragment from the IOP identified
- by sw->iop, sw->sw_type, sw->sw_id and optionally sw->swlen fields.
- The UploadFlags, SwID, SwType and SwSize fields of the ExecSwUpload
- message are filled in with the values of sw->flags, sw->sw_id,
- sw->sw_type and *(sw->swlen).
-
- The fragments _must_ be requested in order and be 8K in size. The
- user is responsible for allocating memory pointed by sw->buf. The
- last fragment _may_ be shorter.
-
- Please note that SW transfers can take a long time.
-
- RETURNS
-
- This function returns 0 if no errors occur. If an error occurs, -1
- is returned and errno is set appropriately:
-
- EFAULT Invalid user space pointer was passed
- ENXIO Invalid IOP number
- ETIMEDOUT Timeout waiting for reply message
- ENOMEM Kernel memory allocation error
-
-X. Removing Software
-
- SYNOPSIS
-
- ioctl(fd, I2OSWDEL, struct i2o_sw_xfer *sw);
-
- struct i2o_sw_xfer
- {
- u32 iop; /* IOP unit number */
- u8 flags; /* RemoveFlags */
- u8 sw_type; /* Software type */
- u32 sw_id; /* Software ID */
- void *buf; /* Unused */
- u32 *swlen; /* Length of the software data */
- u32 *maxfrag; /* Unused */
- u32 *curfrag; /* Unused */
- };
-
- DESCRIPTION
-
- This function removes software from the IOP identified by sw->iop.
- The RemoveFlags, SwID, SwType and SwSize fields of the ExecSwRemove message
- are filled in with the values of sw->flags, sw->sw_id, sw->sw_type and
- *(sw->swlen). Give zero in *(sw->len) if the value is unknown. IOP uses
- *(sw->swlen) value to verify correct identication of the module to remove.
- The actual size of the module is written into *(sw->swlen).
-
- RETURNS
-
- This function returns 0 if no errors occur. If an error occurs, -1
- is returned and errno is set appropriately:
-
- EFAULT Invalid user space pointer was passed
- ENXIO Invalid IOP number
- ETIMEDOUT Timeout waiting for reply message
- ENOMEM Kernel memory allocation error
-
-X. Validating Configuration
-
- SYNOPSIS
-
- ioctl(fd, I2OVALIDATE, int *iop);
- u32 iop;
-
- DESCRIPTION
-
- This function posts an ExecConfigValidate message to the controller
- identified by iop. This message indicates that the current
- configuration is accepted. The iop changes the status of suspect drivers
- to valid and may delete old drivers from its store.
-
- RETURNS
-
- This function returns 0 if no erro occur. If an error occurs, -1 is
- returned and errno is set appropriately:
-
- ETIMEDOUT Timeout waiting for reply message
- ENXIO Invalid IOP number
-
-XI. Configuration Dialog
-
- SYNOPSIS
-
- ioctl(fd, I2OHTML, struct i2o_html *htquery);
- struct i2o_html
- {
- u32 iop; /* IOP unit number */
- u32 tid; /* Target device ID */
- u32 page; /* HTML page */
- void *resbuf; /* Buffer for reply HTML page */
- u32 *reslen; /* Length in bytes of reply buffer */
- void *qbuf; /* Pointer to HTTP query string */
- u32 qlen; /* Length in bytes of query string buffer */
- };
-
- DESCRIPTION
-
- This function posts an UtilConfigDialog message to the device identified
- by htquery->iop and htquery->tid. The requested HTML page number is
- provided by the htquery->page field, and the resultant data is stored
- in the buffer pointed to by htquery->resbuf. If there is an HTTP query
- string that is to be sent to the device, it should be sent in the buffer
- pointed to by htquery->qbuf. If there is no query string, this field
- should be set to NULL. The actual size of the reply received is written
- into *(htquery->reslen).
-
- RETURNS
-
- This function returns 0 if no error occur. If an error occurs, -1
- is returned and errno is set appropriately:
-
- EFAULT Invalid user space pointer was passed
- ENXIO Invalid IOP number
- ENOBUFS Buffer not large enough. If this occurs, the required
- buffer length is written into *(ops->reslen)
- ETIMEDOUT Timeout waiting for reply message
- ENOMEM Kernel memory allocation error
-
-XII. Events
-
- In the process of determining this. Current idea is to have use
- the select() interface to allow user apps to periodically poll
- the /dev/i2o/ctl device for events. When select() notifies the user
- that an event is available, the user would call read() to retrieve
- a list of all the events that are pending for the specific device.
-
-=============================================================================
-Revision History
-=============================================================================
-
-Rev 0.1 - 04/01/99
-- Initial revision
-
-Rev 0.2 - 04/06/99
-- Changed return values to match UNIX ioctl() standard. Only return values
- are 0 and -1. All errors are reported through errno.
-- Added summary of proposed possible event interfaces
-
-Rev 0.3 - 04/20/99
-- Changed all ioctls() to use pointers to user data instead of actual data
-- Updated error values to match the code
+++ /dev/null
-/*
- * Bus Adapter OSM
- *
- * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.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.
- *
- * Fixes/additions:
- * Markus Lidel <Markus.Lidel@shadowconnect.com>
- * initial version.
- */
-
-#include <linux/module.h>
-#include "i2o.h"
-
-#define OSM_NAME "bus-osm"
-#define OSM_VERSION "1.317"
-#define OSM_DESCRIPTION "I2O Bus Adapter OSM"
-
-static struct i2o_driver i2o_bus_driver;
-
-/* Bus OSM class handling definition */
-static struct i2o_class_id i2o_bus_class_id[] = {
- {I2O_CLASS_BUS_ADAPTER},
- {I2O_CLASS_END}
-};
-
-/**
- * i2o_bus_scan - Scan the bus for new devices
- * @dev: I2O device of the bus, which should be scanned
- *
- * Scans the bus dev for new / removed devices. After the scan a new LCT
- * will be fetched automatically.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_bus_scan(struct i2o_device *dev)
-{
- struct i2o_message *msg;
-
- msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return -ETIMEDOUT;
-
- msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_BUS_SCAN << 24 | HOST_TID << 12 | dev->lct_data.
- tid);
-
- return i2o_msg_post_wait(dev->iop, msg, 60);
-};
-
-/**
- * i2o_bus_store_scan - Scan the I2O Bus Adapter
- * @d: device which should be scanned
- * @attr: device_attribute
- * @buf: output buffer
- * @count: buffer size
- *
- * Returns count.
- */
-static ssize_t i2o_bus_store_scan(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct i2o_device *i2o_dev = to_i2o_device(d);
- int rc;
-
- rc = i2o_bus_scan(i2o_dev);
- if (rc)
- osm_warn("bus scan failed %d\n", rc);
-
- return count;
-}
-
-/* Bus Adapter OSM device attributes */
-static DEVICE_ATTR(scan, S_IWUSR, NULL, i2o_bus_store_scan);
-
-/**
- * i2o_bus_probe - verify if dev is a I2O Bus Adapter device and install it
- * @dev: device to verify if it is a I2O Bus Adapter device
- *
- * Because we want all Bus Adapters always return 0.
- * Except when we fail. Then we are sad.
- *
- * Returns 0, except when we fail to excel.
- */
-static int i2o_bus_probe(struct device *dev)
-{
- struct i2o_device *i2o_dev = to_i2o_device(get_device(dev));
- int rc;
-
- rc = device_create_file(dev, &dev_attr_scan);
- if (rc)
- goto err_out;
-
- osm_info("device added (TID: %03x)\n", i2o_dev->lct_data.tid);
-
- return 0;
-
-err_out:
- put_device(dev);
- return rc;
-};
-
-/**
- * i2o_bus_remove - remove the I2O Bus Adapter device from the system again
- * @dev: I2O Bus Adapter device which should be removed
- *
- * Always returns 0.
- */
-static int i2o_bus_remove(struct device *dev)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
-
- device_remove_file(dev, &dev_attr_scan);
-
- put_device(dev);
-
- osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
-
- return 0;
-};
-
-/* Bus Adapter OSM driver struct */
-static struct i2o_driver i2o_bus_driver = {
- .name = OSM_NAME,
- .classes = i2o_bus_class_id,
- .driver = {
- .probe = i2o_bus_probe,
- .remove = i2o_bus_remove,
- },
-};
-
-/**
- * i2o_bus_init - Bus Adapter OSM initialization function
- *
- * Only register the Bus Adapter OSM in the I2O core.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int __init i2o_bus_init(void)
-{
- int rc;
-
- printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
-
- /* Register Bus Adapter OSM into I2O core */
- rc = i2o_driver_register(&i2o_bus_driver);
- if (rc) {
- osm_err("Could not register Bus Adapter OSM\n");
- return rc;
- }
-
- return 0;
-};
-
-/**
- * i2o_bus_exit - Bus Adapter OSM exit function
- *
- * Unregisters Bus Adapter OSM from I2O core.
- */
-static void __exit i2o_bus_exit(void)
-{
- i2o_driver_unregister(&i2o_bus_driver);
-};
-
-MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(OSM_DESCRIPTION);
-MODULE_VERSION(OSM_VERSION);
-
-module_init(i2o_bus_init);
-module_exit(i2o_bus_exit);
+++ /dev/null
-/*
- * Configuration OSM
- *
- * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.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.
- *
- * Fixes/additions:
- * Markus Lidel <Markus.Lidel@shadowconnect.com>
- * initial version.
- */
-
-#include <linux/module.h>
-#include "i2o.h"
-#include <linux/dcache.h>
-#include <linux/namei.h>
-#include <linux/fs.h>
-
-#include <linux/uaccess.h>
-
-#define OSM_NAME "config-osm"
-#define OSM_VERSION "1.323"
-#define OSM_DESCRIPTION "I2O Configuration OSM"
-
-/* access mode user rw */
-#define S_IWRSR (S_IRUSR | S_IWUSR)
-
-static struct i2o_driver i2o_config_driver;
-
-/* Config OSM driver struct */
-static struct i2o_driver i2o_config_driver = {
- .name = OSM_NAME,
-};
-
-#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
-#include "i2o_config.c"
-#endif
-
-/**
- * i2o_config_init - Configuration OSM initialization function
- *
- * Registers Configuration OSM in the I2O core and if old ioctl's are
- * compiled in initialize them.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int __init i2o_config_init(void)
-{
- printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
-
- if (i2o_driver_register(&i2o_config_driver)) {
- osm_err("handler register failed.\n");
- return -EBUSY;
- }
-#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
- if (i2o_config_old_init()) {
- osm_err("old config handler initialization failed\n");
- i2o_driver_unregister(&i2o_config_driver);
- return -EBUSY;
- }
-#endif
-
- return 0;
-}
-
-/**
- * i2o_config_exit - Configuration OSM exit function
- *
- * If old ioctl's are compiled in exit remove them and unregisters
- * Configuration OSM from I2O core.
- */
-static void i2o_config_exit(void)
-{
-#ifdef CONFIG_I2O_CONFIG_OLD_IOCTL
- i2o_config_old_exit();
-#endif
-
- i2o_driver_unregister(&i2o_config_driver);
-}
-
-MODULE_AUTHOR("Markus Lidel <Markus.Lidel@shadowconnect.com>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(OSM_DESCRIPTION);
-MODULE_VERSION(OSM_VERSION);
-
-module_init(i2o_config_init);
-module_exit(i2o_config_exit);
+++ /dev/null
-/*
- * I2O core internal declarations
- *
- * Copyright (C) 2005 Markus Lidel <Markus.Lidel@shadowconnect.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.
- *
- * Fixes/additions:
- * Markus Lidel <Markus.Lidel@shadowconnect.com>
- * initial version.
- */
-
-/* Exec-OSM */
-extern struct i2o_driver i2o_exec_driver;
-extern int i2o_exec_lct_get(struct i2o_controller *);
-
-extern int __init i2o_exec_init(void);
-extern void i2o_exec_exit(void);
-
-/* driver */
-extern struct bus_type i2o_bus_type;
-
-extern int i2o_driver_dispatch(struct i2o_controller *, u32);
-
-extern int __init i2o_driver_init(void);
-extern void i2o_driver_exit(void);
-
-/* PCI */
-extern int __init i2o_pci_init(void);
-extern void __exit i2o_pci_exit(void);
-
-/* device */
-extern const struct attribute_group *i2o_device_groups[];
-
-extern void i2o_device_remove(struct i2o_device *);
-extern int i2o_device_parse_lct(struct i2o_controller *);
-
-int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
- int oplen, void *reslist, int reslen);
-
-/* IOP */
-extern struct i2o_controller *i2o_iop_alloc(void);
-
-/**
- * i2o_iop_free - Free the i2o_controller struct
- * @c: I2O controller to free
- */
-static inline void i2o_iop_free(struct i2o_controller *c)
-{
- i2o_pool_free(&c->in_msg);
- kfree(c);
-}
-
-extern int i2o_iop_add(struct i2o_controller *);
-extern void i2o_iop_remove(struct i2o_controller *);
-
-/* control registers relative to c->base */
-#define I2O_IRQ_STATUS 0x30
-#define I2O_IRQ_MASK 0x34
-#define I2O_IN_PORT 0x40
-#define I2O_OUT_PORT 0x44
-
-/* Motorola/Freescale specific register offset */
-#define I2O_MOTOROLA_PORT_OFFSET 0x10400
-
-#define I2O_IRQ_OUTBOUND_POST 0x00000008
+++ /dev/null
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include "i2o.h"
-
-static void i2o_report_util_cmd(u8 cmd);
-static void i2o_report_exec_cmd(u8 cmd);
-static void i2o_report_fail_status(u8 req_status, u32 *msg);
-static void i2o_report_common_status(u8 req_status);
-static void i2o_report_common_dsc(u16 detailed_status);
-
-/*
- * Used for error reporting/debugging purposes.
- * Report Cmd name, Request status, Detailed Status.
- */
-void i2o_report_status(const char *severity, const char *str,
- struct i2o_message *m)
-{
- u32 *msg = (u32 *) m;
- u8 cmd = (msg[1] >> 24) & 0xFF;
- u8 req_status = (msg[4] >> 24) & 0xFF;
- u16 detailed_status = msg[4] & 0xFFFF;
-
- if (cmd == I2O_CMD_UTIL_EVT_REGISTER)
- return; /* No status in this reply */
-
- printk("%s%s: ", severity, str);
-
- if (cmd < 0x1F) // Utility cmd
- i2o_report_util_cmd(cmd);
-
- else if (cmd >= 0xA0 && cmd <= 0xEF) // Executive cmd
- i2o_report_exec_cmd(cmd);
- else
- printk("Cmd = %0#2x, ", cmd); // Other cmds
-
- if (msg[0] & MSG_FAIL) {
- i2o_report_fail_status(req_status, msg);
- return;
- }
-
- i2o_report_common_status(req_status);
-
- if (cmd < 0x1F || (cmd >= 0xA0 && cmd <= 0xEF))
- i2o_report_common_dsc(detailed_status);
- else
- printk(" / DetailedStatus = %0#4x.\n",
- detailed_status);
-}
-
-/* Used to dump a message to syslog during debugging */
-void i2o_dump_message(struct i2o_message *m)
-{
-#ifdef DEBUG
- u32 *msg = (u32 *) m;
- int i;
-
- printk(KERN_INFO "Dumping I2O message size %d @ %p\n",
- msg[0] >> 16 & 0xffff, msg);
- for (i = 0; i < ((msg[0] >> 16) & 0xffff); i++)
- printk(KERN_INFO " msg[%d] = %0#10x\n", i, msg[i]);
-#endif
-}
-
-/*
- * Used for error reporting/debugging purposes.
- * Following fail status are common to all classes.
- * The preserved message must be handled in the reply handler.
- */
-static void i2o_report_fail_status(u8 req_status, u32 *msg)
-{
- static char *FAIL_STATUS[] = {
- "0x80", /* not used */
- "SERVICE_SUSPENDED", /* 0x81 */
- "SERVICE_TERMINATED", /* 0x82 */
- "CONGESTION",
- "FAILURE",
- "STATE_ERROR",
- "TIME_OUT",
- "ROUTING_FAILURE",
- "INVALID_VERSION",
- "INVALID_OFFSET",
- "INVALID_MSG_FLAGS",
- "FRAME_TOO_SMALL",
- "FRAME_TOO_LARGE",
- "INVALID_TARGET_ID",
- "INVALID_INITIATOR_ID",
- "INVALID_INITIATOR_CONTEX", /* 0x8F */
- "UNKNOWN_FAILURE" /* 0xFF */
- };
-
- if (req_status == I2O_FSC_TRANSPORT_UNKNOWN_FAILURE)
- printk("TRANSPORT_UNKNOWN_FAILURE (%0#2x).\n",
- req_status);
- else
- printk("TRANSPORT_%s.\n",
- FAIL_STATUS[req_status & 0x0F]);
-
- /* Dump some details */
-
- printk(KERN_ERR " InitiatorId = %d, TargetId = %d\n",
- (msg[1] >> 12) & 0xFFF, msg[1] & 0xFFF);
- printk(KERN_ERR " LowestVersion = 0x%02X, HighestVersion = 0x%02X\n",
- (msg[4] >> 8) & 0xFF, msg[4] & 0xFF);
- printk(KERN_ERR " FailingHostUnit = 0x%04X, FailingIOP = 0x%03X\n",
- msg[5] >> 16, msg[5] & 0xFFF);
-
- printk(KERN_ERR " Severity: 0x%02X\n", (msg[4] >> 16) & 0xFF);
- if (msg[4] & (1 << 16))
- printk(KERN_DEBUG "(FormatError), "
- "this msg can never be delivered/processed.\n");
- if (msg[4] & (1 << 17))
- printk(KERN_DEBUG "(PathError), "
- "this msg can no longer be delivered/processed.\n");
- if (msg[4] & (1 << 18))
- printk(KERN_DEBUG "(PathState), "
- "the system state does not allow delivery.\n");
- if (msg[4] & (1 << 19))
- printk(KERN_DEBUG
- "(Congestion), resources temporarily not available;"
- "do not retry immediately.\n");
-}
-
-/*
- * Used for error reporting/debugging purposes.
- * Following reply status are common to all classes.
- */
-static void i2o_report_common_status(u8 req_status)
-{
- static char *REPLY_STATUS[] = {
- "SUCCESS",
- "ABORT_DIRTY",
- "ABORT_NO_DATA_TRANSFER",
- "ABORT_PARTIAL_TRANSFER",
- "ERROR_DIRTY",
- "ERROR_NO_DATA_TRANSFER",
- "ERROR_PARTIAL_TRANSFER",
- "PROCESS_ABORT_DIRTY",
- "PROCESS_ABORT_NO_DATA_TRANSFER",
- "PROCESS_ABORT_PARTIAL_TRANSFER",
- "TRANSACTION_ERROR",
- "PROGRESS_REPORT"
- };
-
- if (req_status >= ARRAY_SIZE(REPLY_STATUS))
- printk("RequestStatus = %0#2x", req_status);
- else
- printk("%s", REPLY_STATUS[req_status]);
-}
-
-/*
- * Used for error reporting/debugging purposes.
- * Following detailed status are valid for executive class,
- * utility class, DDM class and for transaction error replies.
- */
-static void i2o_report_common_dsc(u16 detailed_status)
-{
- static char *COMMON_DSC[] = {
- "SUCCESS",
- "0x01", // not used
- "BAD_KEY",
- "TCL_ERROR",
- "REPLY_BUFFER_FULL",
- "NO_SUCH_PAGE",
- "INSUFFICIENT_RESOURCE_SOFT",
- "INSUFFICIENT_RESOURCE_HARD",
- "0x08", // not used
- "CHAIN_BUFFER_TOO_LARGE",
- "UNSUPPORTED_FUNCTION",
- "DEVICE_LOCKED",
- "DEVICE_RESET",
- "INAPPROPRIATE_FUNCTION",
- "INVALID_INITIATOR_ADDRESS",
- "INVALID_MESSAGE_FLAGS",
- "INVALID_OFFSET",
- "INVALID_PARAMETER",
- "INVALID_REQUEST",
- "INVALID_TARGET_ADDRESS",
- "MESSAGE_TOO_LARGE",
- "MESSAGE_TOO_SMALL",
- "MISSING_PARAMETER",
- "TIMEOUT",
- "UNKNOWN_ERROR",
- "UNKNOWN_FUNCTION",
- "UNSUPPORTED_VERSION",
- "DEVICE_BUSY",
- "DEVICE_NOT_AVAILABLE"
- };
-
- if (detailed_status > I2O_DSC_DEVICE_NOT_AVAILABLE)
- printk(" / DetailedStatus = %0#4x.\n",
- detailed_status);
- else
- printk(" / %s.\n", COMMON_DSC[detailed_status]);
-}
-
-/*
- * Used for error reporting/debugging purposes
- */
-static void i2o_report_util_cmd(u8 cmd)
-{
- switch (cmd) {
- case I2O_CMD_UTIL_NOP:
- printk("UTIL_NOP, ");
- break;
- case I2O_CMD_UTIL_ABORT:
- printk("UTIL_ABORT, ");
- break;
- case I2O_CMD_UTIL_CLAIM:
- printk("UTIL_CLAIM, ");
- break;
- case I2O_CMD_UTIL_RELEASE:
- printk("UTIL_CLAIM_RELEASE, ");
- break;
- case I2O_CMD_UTIL_CONFIG_DIALOG:
- printk("UTIL_CONFIG_DIALOG, ");
- break;
- case I2O_CMD_UTIL_DEVICE_RESERVE:
- printk("UTIL_DEVICE_RESERVE, ");
- break;
- case I2O_CMD_UTIL_DEVICE_RELEASE:
- printk("UTIL_DEVICE_RELEASE, ");
- break;
- case I2O_CMD_UTIL_EVT_ACK:
- printk("UTIL_EVENT_ACKNOWLEDGE, ");
- break;
- case I2O_CMD_UTIL_EVT_REGISTER:
- printk("UTIL_EVENT_REGISTER, ");
- break;
- case I2O_CMD_UTIL_LOCK:
- printk("UTIL_LOCK, ");
- break;
- case I2O_CMD_UTIL_LOCK_RELEASE:
- printk("UTIL_LOCK_RELEASE, ");
- break;
- case I2O_CMD_UTIL_PARAMS_GET:
- printk("UTIL_PARAMS_GET, ");
- break;
- case I2O_CMD_UTIL_PARAMS_SET:
- printk("UTIL_PARAMS_SET, ");
- break;
- case I2O_CMD_UTIL_REPLY_FAULT_NOTIFY:
- printk("UTIL_REPLY_FAULT_NOTIFY, ");
- break;
- default:
- printk("Cmd = %0#2x, ", cmd);
- }
-}
-
-/*
- * Used for error reporting/debugging purposes
- */
-static void i2o_report_exec_cmd(u8 cmd)
-{
- switch (cmd) {
- case I2O_CMD_ADAPTER_ASSIGN:
- printk("EXEC_ADAPTER_ASSIGN, ");
- break;
- case I2O_CMD_ADAPTER_READ:
- printk("EXEC_ADAPTER_READ, ");
- break;
- case I2O_CMD_ADAPTER_RELEASE:
- printk("EXEC_ADAPTER_RELEASE, ");
- break;
- case I2O_CMD_BIOS_INFO_SET:
- printk("EXEC_BIOS_INFO_SET, ");
- break;
- case I2O_CMD_BOOT_DEVICE_SET:
- printk("EXEC_BOOT_DEVICE_SET, ");
- break;
- case I2O_CMD_CONFIG_VALIDATE:
- printk("EXEC_CONFIG_VALIDATE, ");
- break;
- case I2O_CMD_CONN_SETUP:
- printk("EXEC_CONN_SETUP, ");
- break;
- case I2O_CMD_DDM_DESTROY:
- printk("EXEC_DDM_DESTROY, ");
- break;
- case I2O_CMD_DDM_ENABLE:
- printk("EXEC_DDM_ENABLE, ");
- break;
- case I2O_CMD_DDM_QUIESCE:
- printk("EXEC_DDM_QUIESCE, ");
- break;
- case I2O_CMD_DDM_RESET:
- printk("EXEC_DDM_RESET, ");
- break;
- case I2O_CMD_DDM_SUSPEND:
- printk("EXEC_DDM_SUSPEND, ");
- break;
- case I2O_CMD_DEVICE_ASSIGN:
- printk("EXEC_DEVICE_ASSIGN, ");
- break;
- case I2O_CMD_DEVICE_RELEASE:
- printk("EXEC_DEVICE_RELEASE, ");
- break;
- case I2O_CMD_HRT_GET:
- printk("EXEC_HRT_GET, ");
- break;
- case I2O_CMD_ADAPTER_CLEAR:
- printk("EXEC_IOP_CLEAR, ");
- break;
- case I2O_CMD_ADAPTER_CONNECT:
- printk("EXEC_IOP_CONNECT, ");
- break;
- case I2O_CMD_ADAPTER_RESET:
- printk("EXEC_IOP_RESET, ");
- break;
- case I2O_CMD_LCT_NOTIFY:
- printk("EXEC_LCT_NOTIFY, ");
- break;
- case I2O_CMD_OUTBOUND_INIT:
- printk("EXEC_OUTBOUND_INIT, ");
- break;
- case I2O_CMD_PATH_ENABLE:
- printk("EXEC_PATH_ENABLE, ");
- break;
- case I2O_CMD_PATH_QUIESCE:
- printk("EXEC_PATH_QUIESCE, ");
- break;
- case I2O_CMD_PATH_RESET:
- printk("EXEC_PATH_RESET, ");
- break;
- case I2O_CMD_STATIC_MF_CREATE:
- printk("EXEC_STATIC_MF_CREATE, ");
- break;
- case I2O_CMD_STATIC_MF_RELEASE:
- printk("EXEC_STATIC_MF_RELEASE, ");
- break;
- case I2O_CMD_STATUS_GET:
- printk("EXEC_STATUS_GET, ");
- break;
- case I2O_CMD_SW_DOWNLOAD:
- printk("EXEC_SW_DOWNLOAD, ");
- break;
- case I2O_CMD_SW_UPLOAD:
- printk("EXEC_SW_UPLOAD, ");
- break;
- case I2O_CMD_SW_REMOVE:
- printk("EXEC_SW_REMOVE, ");
- break;
- case I2O_CMD_SYS_ENABLE:
- printk("EXEC_SYS_ENABLE, ");
- break;
- case I2O_CMD_SYS_MODIFY:
- printk("EXEC_SYS_MODIFY, ");
- break;
- case I2O_CMD_SYS_QUIESCE:
- printk("EXEC_SYS_QUIESCE, ");
- break;
- case I2O_CMD_SYS_TAB_SET:
- printk("EXEC_SYS_TAB_SET, ");
- break;
- default:
- printk("Cmd = %#02x, ", cmd);
- }
-}
-
-void i2o_debug_state(struct i2o_controller *c)
-{
- printk(KERN_INFO "%s: State = ", c->name);
- switch (((i2o_status_block *) c->status_block.virt)->iop_state) {
- case 0x01:
- printk("INIT\n");
- break;
- case 0x02:
- printk("RESET\n");
- break;
- case 0x04:
- printk("HOLD\n");
- break;
- case 0x05:
- printk("READY\n");
- break;
- case 0x08:
- printk("OPERATIONAL\n");
- break;
- case 0x10:
- printk("FAILED\n");
- break;
- case 0x11:
- printk("FAULTED\n");
- break;
- default:
- printk("%x (unknown !!)\n",
- ((i2o_status_block *) c->status_block.virt)->iop_state);
- }
-};
-
-void i2o_dump_hrt(struct i2o_controller *c)
-{
- u32 *rows = (u32 *) c->hrt.virt;
- u8 *p = (u8 *) c->hrt.virt;
- u8 *d;
- int count;
- int length;
- int i;
- int state;
-
- if (p[3] != 0) {
- printk(KERN_ERR
- "%s: HRT table for controller is too new a version.\n",
- c->name);
- return;
- }
-
- count = p[0] | (p[1] << 8);
- length = p[2];
-
- printk(KERN_INFO "%s: HRT has %d entries of %d bytes each.\n",
- c->name, count, length << 2);
-
- rows += 2;
-
- for (i = 0; i < count; i++) {
- printk(KERN_INFO "Adapter %08X: ", rows[0]);
- p = (u8 *) (rows + 1);
- d = (u8 *) (rows + 2);
- state = p[1] << 8 | p[0];
-
- printk("TID %04X:[", state & 0xFFF);
- state >>= 12;
- if (state & (1 << 0))
- printk("H"); /* Hidden */
- if (state & (1 << 2)) {
- printk("P"); /* Present */
- if (state & (1 << 1))
- printk("C"); /* Controlled */
- }
- if (state > 9)
- printk("*"); /* Hard */
-
- printk("]:");
-
- switch (p[3] & 0xFFFF) {
- case 0:
- /* Adapter private bus - easy */
- printk("Local bus %d: I/O at 0x%04X Mem 0x%08X", p[2],
- d[1] << 8 | d[0], *(u32 *) (d + 4));
- break;
- case 1:
- /* ISA bus */
- printk("ISA %d: CSN %d I/O at 0x%04X Mem 0x%08X", p[2],
- d[2], d[1] << 8 | d[0], *(u32 *) (d + 4));
- break;
-
- case 2: /* EISA bus */
- printk("EISA %d: Slot %d I/O at 0x%04X Mem 0x%08X",
- p[2], d[3], d[1] << 8 | d[0], *(u32 *) (d + 4));
- break;
-
- case 3: /* MCA bus */
- printk("MCA %d: Slot %d I/O at 0x%04X Mem 0x%08X", p[2],
- d[3], d[1] << 8 | d[0], *(u32 *) (d + 4));
- break;
-
- case 4: /* PCI bus */
- printk("PCI %d: Bus %d Device %d Function %d", p[2],
- d[2], d[1], d[0]);
- break;
-
- case 0x80: /* Other */
- default:
- printk("Unsupported bus type.");
- break;
- }
- printk("\n");
- rows += length;
- }
-}
-
-EXPORT_SYMBOL(i2o_dump_message);
+++ /dev/null
-/*
- * Functions to handle I2O devices
- *
- * Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.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.
- *
- * Fixes/additions:
- * Markus Lidel <Markus.Lidel@shadowconnect.com>
- * initial version.
- */
-
-#include <linux/module.h>
-#include "i2o.h"
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include "core.h"
-
-/**
- * i2o_device_issue_claim - claim or release a device
- * @dev: I2O device to claim or release
- * @cmd: claim or release command
- * @type: type of claim
- *
- * Issue I2O UTIL_CLAIM or UTIL_RELEASE messages. The message to be sent
- * is set by cmd. dev is the I2O device which should be claim or
- * released and the type is the claim type (see the I2O spec).
- *
- * Returs 0 on success or negative error code on failure.
- */
-static inline int i2o_device_issue_claim(struct i2o_device *dev, u32 cmd,
- u32 type)
-{
- struct i2o_message *msg;
-
- msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(cmd << 24 | HOST_TID << 12 | dev->lct_data.tid);
- msg->body[0] = cpu_to_le32(type);
-
- return i2o_msg_post_wait(dev->iop, msg, 60);
-}
-
-/**
- * i2o_device_claim - claim a device for use by an OSM
- * @dev: I2O device to claim
- *
- * Do the leg work to assign a device to a given OSM. If the claim succeeds,
- * the owner is the primary. If the attempt fails a negative errno code
- * is returned. On success zero is returned.
- */
-int i2o_device_claim(struct i2o_device *dev)
-{
- int rc = 0;
-
- mutex_lock(&dev->lock);
-
- rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY);
- if (!rc)
- pr_debug("i2o: claim of device %d succeeded\n",
- dev->lct_data.tid);
- else
- pr_debug("i2o: claim of device %d failed %d\n",
- dev->lct_data.tid, rc);
-
- mutex_unlock(&dev->lock);
-
- return rc;
-}
-
-/**
- * i2o_device_claim_release - release a device that the OSM is using
- * @dev: device to release
- *
- * Drop a claim by an OSM on a given I2O device.
- *
- * AC - some devices seem to want to refuse an unclaim until they have
- * finished internal processing. It makes sense since you don't want a
- * new device to go reconfiguring the entire system until you are done.
- * Thus we are prepared to wait briefly.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_device_claim_release(struct i2o_device *dev)
-{
- int tries;
- int rc = 0;
-
- mutex_lock(&dev->lock);
-
- /*
- * If the controller takes a nonblocking approach to
- * releases we have to sleep/poll for a few times.
- */
- for (tries = 0; tries < 10; tries++) {
- rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_RELEASE,
- I2O_CLAIM_PRIMARY);
- if (!rc)
- break;
-
- ssleep(1);
- }
-
- if (!rc)
- pr_debug("i2o: claim release of device %d succeeded\n",
- dev->lct_data.tid);
- else
- pr_debug("i2o: claim release of device %d failed %d\n",
- dev->lct_data.tid, rc);
-
- mutex_unlock(&dev->lock);
-
- return rc;
-}
-
-/**
- * i2o_device_release - release the memory for a I2O device
- * @dev: I2O device which should be released
- *
- * Release the allocated memory. This function is called if refcount of
- * device reaches 0 automatically.
- */
-static void i2o_device_release(struct device *dev)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
-
- pr_debug("i2o: device %s released\n", dev_name(dev));
-
- kfree(i2o_dev);
-}
-
-/**
- * class_id_show - Displays class id of I2O device
- * @dev: device of which the class id should be displayed
- * @attr: pointer to device attribute
- * @buf: buffer into which the class id should be printed
- *
- * Returns the number of bytes which are printed into the buffer.
- */
-static ssize_t class_id_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
-
- sprintf(buf, "0x%03x\n", i2o_dev->lct_data.class_id);
- return strlen(buf) + 1;
-}
-static DEVICE_ATTR_RO(class_id);
-
-/**
- * tid_show - Displays TID of I2O device
- * @dev: device of which the TID should be displayed
- * @attr: pointer to device attribute
- * @buf: buffer into which the TID should be printed
- *
- * Returns the number of bytes which are printed into the buffer.
- */
-static ssize_t tid_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
-
- sprintf(buf, "0x%03x\n", i2o_dev->lct_data.tid);
- return strlen(buf) + 1;
-}
-static DEVICE_ATTR_RO(tid);
-
-/* I2O device attributes */
-static struct attribute *i2o_device_attrs[] = {
- &dev_attr_class_id.attr,
- &dev_attr_tid.attr,
- NULL,
-};
-
-static const struct attribute_group i2o_device_group = {
- .attrs = i2o_device_attrs,
-};
-
-const struct attribute_group *i2o_device_groups[] = {
- &i2o_device_group,
- NULL,
-};
-
-/**
- * i2o_device_alloc - Allocate a I2O device and initialize it
- *
- * Allocate the memory for a I2O device and initialize locks and lists
- *
- * Returns the allocated I2O device or a negative error code if the device
- * could not be allocated.
- */
-static struct i2o_device *i2o_device_alloc(void)
-{
- struct i2o_device *dev;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return ERR_PTR(-ENOMEM);
-
- INIT_LIST_HEAD(&dev->list);
- mutex_init(&dev->lock);
-
- dev->device.bus = &i2o_bus_type;
- dev->device.release = &i2o_device_release;
-
- return dev;
-}
-
-/**
- * i2o_device_add - allocate a new I2O device and add it to the IOP
- * @c: I2O controller that the device is on
- * @entry: LCT entry of the I2O device
- *
- * Allocate a new I2O device and initialize it with the LCT entry. The
- * device is appended to the device list of the controller.
- *
- * Returns zero on success, or a -ve errno.
- */
-static int i2o_device_add(struct i2o_controller *c, i2o_lct_entry *entry)
-{
- struct i2o_device *i2o_dev, *tmp;
- int rc;
-
- i2o_dev = i2o_device_alloc();
- if (IS_ERR(i2o_dev)) {
- printk(KERN_ERR "i2o: unable to allocate i2o device\n");
- return PTR_ERR(i2o_dev);
- }
-
- i2o_dev->lct_data = *entry;
-
- dev_set_name(&i2o_dev->device, "%d:%03x", c->unit,
- i2o_dev->lct_data.tid);
-
- i2o_dev->iop = c;
- i2o_dev->device.parent = &c->device;
-
- rc = device_register(&i2o_dev->device);
- if (rc)
- goto err;
-
- list_add_tail(&i2o_dev->list, &c->devices);
-
- /* create user entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.user_tid);
- if (tmp && (tmp != i2o_dev)) {
- rc = sysfs_create_link(&i2o_dev->device.kobj,
- &tmp->device.kobj, "user");
- if (rc)
- goto unreg_dev;
- }
-
- /* create user entries referring to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev)) {
- rc = sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "user");
- if (rc)
- goto rmlink1;
- }
-
- /* create parent entries for this device */
- tmp = i2o_iop_find_device(i2o_dev->iop, i2o_dev->lct_data.parent_tid);
- if (tmp && (tmp != i2o_dev)) {
- rc = sysfs_create_link(&i2o_dev->device.kobj,
- &tmp->device.kobj, "parent");
- if (rc)
- goto rmlink1;
- }
-
- /* create parent entries referring to this device */
- list_for_each_entry(tmp, &c->devices, list)
- if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- && (tmp != i2o_dev)) {
- rc = sysfs_create_link(&tmp->device.kobj,
- &i2o_dev->device.kobj, "parent");
- if (rc)
- goto rmlink2;
- }
-
- i2o_driver_notify_device_add_all(i2o_dev);
-
- pr_debug("i2o: device %s added\n", dev_name(&i2o_dev->device));
-
- return 0;
-
-rmlink2:
- /* If link creating failed halfway, we loop whole list to cleanup.
- * And we don't care wrong removing of link, because sysfs_remove_link
- * will take care of it.
- */
- list_for_each_entry(tmp, &c->devices, list) {
- if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "parent");
- }
- sysfs_remove_link(&i2o_dev->device.kobj, "parent");
-rmlink1:
- list_for_each_entry(tmp, &c->devices, list)
- if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "user");
- sysfs_remove_link(&i2o_dev->device.kobj, "user");
-unreg_dev:
- list_del(&i2o_dev->list);
- device_unregister(&i2o_dev->device);
-err:
- kfree(i2o_dev);
- return rc;
-}
-
-/**
- * i2o_device_remove - remove an I2O device from the I2O core
- * @i2o_dev: I2O device which should be released
- *
- * Is used on I2O controller removal or LCT modification, when the device
- * is removed from the system. Note that the device could still hang
- * around until the refcount reaches 0.
- */
-void i2o_device_remove(struct i2o_device *i2o_dev)
-{
- struct i2o_device *tmp;
- struct i2o_controller *c = i2o_dev->iop;
-
- i2o_driver_notify_device_remove_all(i2o_dev);
-
- sysfs_remove_link(&i2o_dev->device.kobj, "parent");
- sysfs_remove_link(&i2o_dev->device.kobj, "user");
-
- list_for_each_entry(tmp, &c->devices, list) {
- if (tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "parent");
- if (tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
- sysfs_remove_link(&tmp->device.kobj, "user");
- }
- list_del(&i2o_dev->list);
-
- device_unregister(&i2o_dev->device);
-}
-
-/**
- * i2o_device_parse_lct - Parse a previously fetched LCT and create devices
- * @c: I2O controller from which the LCT should be parsed.
- *
- * The Logical Configuration Table tells us what we can talk to on the
- * board. For every entry we create an I2O device, which is registered in
- * the I2O core.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_device_parse_lct(struct i2o_controller *c)
-{
- struct i2o_device *dev, *tmp;
- i2o_lct *lct;
- u32 *dlct = c->dlct.virt;
- int max = 0, i = 0;
- u16 table_size;
- u32 buf;
-
- mutex_lock(&c->lct_lock);
-
- kfree(c->lct);
-
- buf = le32_to_cpu(*dlct++);
- table_size = buf & 0xffff;
-
- lct = c->lct = kmalloc(table_size * 4, GFP_KERNEL);
- if (!lct) {
- mutex_unlock(&c->lct_lock);
- return -ENOMEM;
- }
-
- lct->lct_ver = buf >> 28;
- lct->boot_tid = buf >> 16 & 0xfff;
- lct->table_size = table_size;
- lct->change_ind = le32_to_cpu(*dlct++);
- lct->iop_flags = le32_to_cpu(*dlct++);
-
- table_size -= 3;
-
- pr_debug("%s: LCT has %d entries (LCT size: %d)\n", c->name, max,
- lct->table_size);
-
- while (table_size > 0) {
- i2o_lct_entry *entry = &lct->lct_entry[max];
- int found = 0;
-
- buf = le32_to_cpu(*dlct++);
- entry->entry_size = buf & 0xffff;
- entry->tid = buf >> 16 & 0xfff;
-
- entry->change_ind = le32_to_cpu(*dlct++);
- entry->device_flags = le32_to_cpu(*dlct++);
-
- buf = le32_to_cpu(*dlct++);
- entry->class_id = buf & 0xfff;
- entry->version = buf >> 12 & 0xf;
- entry->vendor_id = buf >> 16;
-
- entry->sub_class = le32_to_cpu(*dlct++);
-
- buf = le32_to_cpu(*dlct++);
- entry->user_tid = buf & 0xfff;
- entry->parent_tid = buf >> 12 & 0xfff;
- entry->bios_info = buf >> 24;
-
- memcpy(&entry->identity_tag, dlct, 8);
- dlct += 2;
-
- entry->event_capabilities = le32_to_cpu(*dlct++);
-
- /* add new devices, which are new in the LCT */
- list_for_each_entry_safe(dev, tmp, &c->devices, list) {
- if (entry->tid == dev->lct_data.tid) {
- found = 1;
- break;
- }
- }
-
- if (!found)
- i2o_device_add(c, entry);
-
- table_size -= 9;
- max++;
- }
-
- /* remove devices, which are not in the LCT anymore */
- list_for_each_entry_safe(dev, tmp, &c->devices, list) {
- int found = 0;
-
- for (i = 0; i < max; i++) {
- if (lct->lct_entry[i].tid == dev->lct_data.tid) {
- found = 1;
- break;
- }
- }
-
- if (!found)
- i2o_device_remove(dev);
- }
-
- mutex_unlock(&c->lct_lock);
-
- return 0;
-}
-
-/*
- * Run time support routines
- */
-
-/* Issue UTIL_PARAMS_GET or UTIL_PARAMS_SET
- *
- * This function can be used for all UtilParamsGet/Set operations.
- * The OperationList is given in oplist-buffer,
- * and results are returned in reslist-buffer.
- * Note that the minimum sized reslist is 8 bytes and contains
- * ResultCount, ErrorInfoSize, BlockStatus and BlockSize.
- */
-int i2o_parm_issue(struct i2o_device *i2o_dev, int cmd, void *oplist,
- int oplen, void *reslist, int reslen)
-{
- struct i2o_message *msg;
- int i = 0;
- int rc;
- struct i2o_dma res;
- struct i2o_controller *c = i2o_dev->iop;
- struct device *dev = &c->pdev->dev;
-
- res.virt = NULL;
-
- if (i2o_dma_alloc(dev, &res, reslen))
- return -ENOMEM;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg)) {
- i2o_dma_free(dev, &res);
- return PTR_ERR(msg);
- }
-
- i = 0;
- msg->u.head[1] =
- cpu_to_le32(cmd << 24 | HOST_TID << 12 | i2o_dev->lct_data.tid);
- msg->body[i++] = cpu_to_le32(0x00000000);
- msg->body[i++] = cpu_to_le32(0x4C000000 | oplen); /* OperationList */
- memcpy(&msg->body[i], oplist, oplen);
- i += (oplen / 4 + (oplen % 4 ? 1 : 0));
- msg->body[i++] = cpu_to_le32(0xD0000000 | res.len); /* ResultList */
- msg->body[i++] = cpu_to_le32(res.phys);
-
- msg->u.head[0] =
- cpu_to_le32(I2O_MESSAGE_SIZE(i + sizeof(struct i2o_message) / 4) |
- SGL_OFFSET_5);
-
- rc = i2o_msg_post_wait_mem(c, msg, 10, &res);
-
- /* This only looks like a memory leak - don't "fix" it. */
- if (rc == -ETIMEDOUT)
- return rc;
-
- memcpy(reslist, res.virt, res.len);
- i2o_dma_free(dev, &res);
-
- return rc;
-}
-
-/*
- * Query one field group value or a whole scalar group.
- */
-int i2o_parm_field_get(struct i2o_device *i2o_dev, int group, int field,
- void *buf, int buflen)
-{
- u32 opblk[] = { cpu_to_le32(0x00000001),
- cpu_to_le32((u16) group << 16 | I2O_PARAMS_FIELD_GET),
- cpu_to_le32((s16) field << 16 | 0x00000001)
- };
- u8 *resblk; /* 8 bytes for header */
- int rc;
-
- resblk = kmalloc(buflen + 8, GFP_KERNEL);
- if (!resblk)
- return -ENOMEM;
-
- rc = i2o_parm_issue(i2o_dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
- sizeof(opblk), resblk, buflen + 8);
-
- memcpy(buf, resblk + 8, buflen); /* cut off header */
-
- kfree(resblk);
-
- return rc;
-}
-
-/*
- * if oper == I2O_PARAMS_TABLE_GET, get from all rows
- * if fieldcount == -1 return all fields
- * ibuf and ibuflen are unused (use NULL, 0)
- * else return specific fields
- * ibuf contains fieldindexes
- *
- * if oper == I2O_PARAMS_LIST_GET, get from specific rows
- * if fieldcount == -1 return all fields
- * ibuf contains rowcount, keyvalues
- * else return specific fields
- * fieldcount is # of fieldindexes
- * ibuf contains fieldindexes, rowcount, keyvalues
- *
- * You could also use directly function i2o_issue_params().
- */
-int i2o_parm_table_get(struct i2o_device *dev, int oper, int group,
- int fieldcount, void *ibuf, int ibuflen, void *resblk,
- int reslen)
-{
- u16 *opblk;
- int size;
-
- size = 10 + ibuflen;
- if (size % 4)
- size += 4 - size % 4;
-
- opblk = kmalloc(size, GFP_KERNEL);
- if (opblk == NULL)
- return -ENOMEM;
-
- opblk[0] = 1; /* operation count */
- opblk[1] = 0; /* pad */
- opblk[2] = oper;
- opblk[3] = group;
- opblk[4] = fieldcount;
- memcpy(opblk + 5, ibuf, ibuflen); /* other params */
-
- size = i2o_parm_issue(dev, I2O_CMD_UTIL_PARAMS_GET, opblk,
- size, resblk, reslen);
-
- kfree(opblk);
- if (size > reslen)
- return reslen;
-
- return size;
-}
-
-EXPORT_SYMBOL(i2o_device_claim);
-EXPORT_SYMBOL(i2o_device_claim_release);
-EXPORT_SYMBOL(i2o_parm_field_get);
-EXPORT_SYMBOL(i2o_parm_table_get);
-EXPORT_SYMBOL(i2o_parm_issue);
+++ /dev/null
-/*
- * Functions to handle I2O drivers (OSMs) and I2O bus type for sysfs
- *
- * Copyright (C) 2004 Markus Lidel <Markus.Lidel@shadowconnect.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.
- *
- * Fixes/additions:
- * Markus Lidel <Markus.Lidel@shadowconnect.com>
- * initial version.
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/rwsem.h>
-#include "i2o.h"
-#include <linux/workqueue.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include "core.h"
-
-#define OSM_NAME "i2o"
-
-/* max_drivers - Maximum I2O drivers (OSMs) which could be registered */
-static unsigned int i2o_max_drivers = I2O_MAX_DRIVERS;
-module_param_named(max_drivers, i2o_max_drivers, uint, 0);
-MODULE_PARM_DESC(max_drivers, "maximum number of OSM's to support");
-
-/* I2O drivers lock and array */
-static spinlock_t i2o_drivers_lock;
-static struct i2o_driver **i2o_drivers;
-
-/**
- * i2o_bus_match - Tell if I2O device class id matches the class ids of the I2O driver (OSM)
- * @dev: device which should be verified
- * @drv: the driver to match against
- *
- * Used by the bus to check if the driver wants to handle the device.
- *
- * Returns 1 if the class ids of the driver match the class id of the
- * device, otherwise 0.
- */
-static int i2o_bus_match(struct device *dev, struct device_driver *drv)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
- struct i2o_driver *i2o_drv = to_i2o_driver(drv);
- struct i2o_class_id *ids = i2o_drv->classes;
-
- if (ids)
- while (ids->class_id != I2O_CLASS_END) {
- if (ids->class_id == i2o_dev->lct_data.class_id)
- return 1;
- ids++;
- }
- return 0;
-};
-
-/* I2O bus type */
-struct bus_type i2o_bus_type = {
- .name = "i2o",
- .match = i2o_bus_match,
- .dev_groups = i2o_device_groups,
-};
-
-/**
- * i2o_driver_register - Register a I2O driver (OSM) in the I2O core
- * @drv: I2O driver which should be registered
- *
- * Registers the OSM drv in the I2O core and creates an event queues if
- * necessary.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_driver_register(struct i2o_driver *drv)
-{
- struct i2o_controller *c;
- int i;
- int rc = 0;
- unsigned long flags;
-
- osm_debug("Register driver %s\n", drv->name);
-
- if (drv->event) {
- drv->event_queue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1,
- drv->name);
- if (!drv->event_queue) {
- osm_err("Could not initialize event queue for driver "
- "%s\n", drv->name);
- return -EFAULT;
- }
- osm_debug("Event queue initialized for driver %s\n", drv->name);
- } else
- drv->event_queue = NULL;
-
- drv->driver.name = drv->name;
- drv->driver.bus = &i2o_bus_type;
-
- spin_lock_irqsave(&i2o_drivers_lock, flags);
-
- for (i = 0; i2o_drivers[i]; i++)
- if (i >= i2o_max_drivers) {
- osm_err("too many drivers registered, increase max_drivers\n");
- spin_unlock_irqrestore(&i2o_drivers_lock, flags);
- rc = -EFAULT;
- goto out;
- }
-
- drv->context = i;
- i2o_drivers[i] = drv;
-
- spin_unlock_irqrestore(&i2o_drivers_lock, flags);
-
- osm_debug("driver %s gets context id %d\n", drv->name, drv->context);
-
- list_for_each_entry(c, &i2o_controllers, list) {
- struct i2o_device *i2o_dev;
-
- i2o_driver_notify_controller_add(drv, c);
- list_for_each_entry(i2o_dev, &c->devices, list)
- i2o_driver_notify_device_add(drv, i2o_dev);
- }
-
- rc = driver_register(&drv->driver);
- if (rc)
- goto out;
-
- return 0;
-out:
- if (drv->event_queue) {
- destroy_workqueue(drv->event_queue);
- drv->event_queue = NULL;
- }
-
- return rc;
-};
-
-/**
- * i2o_driver_unregister - Unregister a I2O driver (OSM) from the I2O core
- * @drv: I2O driver which should be unregistered
- *
- * Unregisters the OSM drv from the I2O core and cleanup event queues if
- * necessary.
- */
-void i2o_driver_unregister(struct i2o_driver *drv)
-{
- struct i2o_controller *c;
- unsigned long flags;
-
- osm_debug("unregister driver %s\n", drv->name);
-
- driver_unregister(&drv->driver);
-
- list_for_each_entry(c, &i2o_controllers, list) {
- struct i2o_device *i2o_dev;
-
- list_for_each_entry(i2o_dev, &c->devices, list)
- i2o_driver_notify_device_remove(drv, i2o_dev);
-
- i2o_driver_notify_controller_remove(drv, c);
- }
-
- spin_lock_irqsave(&i2o_drivers_lock, flags);
- i2o_drivers[drv->context] = NULL;
- spin_unlock_irqrestore(&i2o_drivers_lock, flags);
-
- if (drv->event_queue) {
- destroy_workqueue(drv->event_queue);
- drv->event_queue = NULL;
- osm_debug("event queue removed for %s\n", drv->name);
- }
-};
-
-/**
- * i2o_driver_dispatch - dispatch an I2O reply message
- * @c: I2O controller of the message
- * @m: I2O message number
- *
- * The reply is delivered to the driver from which the original message
- * was. This function is only called from interrupt context.
- *
- * Returns 0 on success and the message should not be flushed. Returns > 0
- * on success and if the message should be flushed afterwords. Returns
- * negative error code on failure (the message will be flushed too).
- */
-int i2o_driver_dispatch(struct i2o_controller *c, u32 m)
-{
- struct i2o_driver *drv;
- struct i2o_message *msg = i2o_msg_out_to_virt(c, m);
- u32 context = le32_to_cpu(msg->u.s.icntxt);
- unsigned long flags;
-
- if (unlikely(context >= i2o_max_drivers)) {
- osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
- context);
- return -EIO;
- }
-
- spin_lock_irqsave(&i2o_drivers_lock, flags);
- drv = i2o_drivers[context];
- spin_unlock_irqrestore(&i2o_drivers_lock, flags);
-
- if (unlikely(!drv)) {
- osm_warn("%s: Spurious reply to unknown driver %d\n", c->name,
- context);
- return -EIO;
- }
-
- if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_UTIL_EVT_REGISTER) {
- struct i2o_device *dev, *tmp;
- struct i2o_event *evt;
- u16 size;
- u16 tid = le32_to_cpu(msg->u.head[1]) & 0xfff;
-
- osm_debug("event received from device %d\n", tid);
-
- if (!drv->event)
- return -EIO;
-
- /* cut of header from message size (in 32-bit words) */
- size = (le32_to_cpu(msg->u.head[0]) >> 16) - 5;
-
- evt = kzalloc(size * 4 + sizeof(*evt), GFP_ATOMIC);
- if (!evt)
- return -ENOMEM;
-
- evt->size = size;
- evt->tcntxt = le32_to_cpu(msg->u.s.tcntxt);
- evt->event_indicator = le32_to_cpu(msg->body[0]);
- memcpy(&evt->data, &msg->body[1], size * 4);
-
- list_for_each_entry_safe(dev, tmp, &c->devices, list)
- if (dev->lct_data.tid == tid) {
- evt->i2o_dev = dev;
- break;
- }
-
- INIT_WORK(&evt->work, drv->event);
- queue_work(drv->event_queue, &evt->work);
- return 1;
- }
-
- if (unlikely(!drv->reply)) {
- osm_debug("%s: Reply to driver %s, but no reply function defined!\n",
- c->name, drv->name);
- return -EIO;
- }
-
- return drv->reply(c, m, msg);
-}
-
-/**
- * i2o_driver_notify_controller_add_all - Send notify of added controller
- * @c: newly added controller
- *
- * Send notifications to all registered drivers that a new controller was
- * added.
- */
-void i2o_driver_notify_controller_add_all(struct i2o_controller *c)
-{
- int i;
- struct i2o_driver *drv;
-
- for (i = 0; i < i2o_max_drivers; i++) {
- drv = i2o_drivers[i];
-
- if (drv)
- i2o_driver_notify_controller_add(drv, c);
- }
-}
-
-/**
- * i2o_driver_notify_controller_remove_all - Send notify of removed controller
- * @c: controller that is being removed
- *
- * Send notifications to all registered drivers that a controller was
- * removed.
- */
-void i2o_driver_notify_controller_remove_all(struct i2o_controller *c)
-{
- int i;
- struct i2o_driver *drv;
-
- for (i = 0; i < i2o_max_drivers; i++) {
- drv = i2o_drivers[i];
-
- if (drv)
- i2o_driver_notify_controller_remove(drv, c);
- }
-}
-
-/**
- * i2o_driver_notify_device_add_all - Send notify of added device
- * @i2o_dev: newly added I2O device
- *
- * Send notifications to all registered drivers that a device was added.
- */
-void i2o_driver_notify_device_add_all(struct i2o_device *i2o_dev)
-{
- int i;
- struct i2o_driver *drv;
-
- for (i = 0; i < i2o_max_drivers; i++) {
- drv = i2o_drivers[i];
-
- if (drv)
- i2o_driver_notify_device_add(drv, i2o_dev);
- }
-}
-
-/**
- * i2o_driver_notify_device_remove_all - Send notify of removed device
- * @i2o_dev: device that is being removed
- *
- * Send notifications to all registered drivers that a device was removed.
- */
-void i2o_driver_notify_device_remove_all(struct i2o_device *i2o_dev)
-{
- int i;
- struct i2o_driver *drv;
-
- for (i = 0; i < i2o_max_drivers; i++) {
- drv = i2o_drivers[i];
-
- if (drv)
- i2o_driver_notify_device_remove(drv, i2o_dev);
- }
-}
-
-/**
- * i2o_driver_init - initialize I2O drivers (OSMs)
- *
- * Registers the I2O bus and allocate memory for the array of OSMs.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int __init i2o_driver_init(void)
-{
- int rc = 0;
-
- spin_lock_init(&i2o_drivers_lock);
-
- if ((i2o_max_drivers < 2) || (i2o_max_drivers > 64)) {
- osm_warn("max_drivers set to %d, but must be >=2 and <= 64\n",
- i2o_max_drivers);
- i2o_max_drivers = I2O_MAX_DRIVERS;
- }
- osm_info("max drivers = %d\n", i2o_max_drivers);
-
- i2o_drivers =
- kcalloc(i2o_max_drivers, sizeof(*i2o_drivers), GFP_KERNEL);
- if (!i2o_drivers)
- return -ENOMEM;
-
- rc = bus_register(&i2o_bus_type);
-
- if (rc < 0)
- kfree(i2o_drivers);
-
- return rc;
-};
-
-/**
- * i2o_driver_exit - clean up I2O drivers (OSMs)
- *
- * Unregisters the I2O bus and frees driver array.
- */
-void i2o_driver_exit(void)
-{
- bus_unregister(&i2o_bus_type);
- kfree(i2o_drivers);
-};
-
-EXPORT_SYMBOL(i2o_driver_register);
-EXPORT_SYMBOL(i2o_driver_unregister);
-EXPORT_SYMBOL(i2o_driver_notify_controller_add_all);
-EXPORT_SYMBOL(i2o_driver_notify_controller_remove_all);
-EXPORT_SYMBOL(i2o_driver_notify_device_add_all);
-EXPORT_SYMBOL(i2o_driver_notify_device_remove_all);
+++ /dev/null
-/*
- * Executive OSM
- *
- * Copyright (C) 1999-2002 Red Hat Software
- *
- * Written by Alan Cox, Building Number Three Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * A lot of the I2O message side code from this is taken from the Red
- * Creek RCPCI45 adapter driver by Red Creek Communications
- *
- * Fixes/additions:
- * Philipp Rumpf
- * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
- * Deepak Saxena <deepak@plexity.net>
- * Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
- * Alan Cox <alan@lxorguk.ukuu.org.uk>:
- * Ported to Linux 2.5.
- * Markus Lidel <Markus.Lidel@shadowconnect.com>:
- * Minor fixes for 2.6.
- * Markus Lidel <Markus.Lidel@shadowconnect.com>:
- * Support for sysfs included.
- */
-
-#include <linux/module.h>
-#include "i2o.h"
-#include <linux/delay.h>
-#include <linux/workqueue.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/sched.h> /* wait_event_interruptible_timeout() needs this */
-#include <asm/param.h> /* HZ */
-#include "core.h"
-
-#define OSM_NAME "exec-osm"
-
-struct i2o_driver i2o_exec_driver;
-
-/* global wait list for POST WAIT */
-static LIST_HEAD(i2o_exec_wait_list);
-
-/* Wait struct needed for POST WAIT */
-struct i2o_exec_wait {
- wait_queue_head_t *wq; /* Pointer to Wait queue */
- struct i2o_dma dma; /* DMA buffers to free on failure */
- u32 tcntxt; /* transaction context from reply */
- int complete; /* 1 if reply received otherwise 0 */
- u32 m; /* message id */
- struct i2o_message *msg; /* pointer to the reply message */
- struct list_head list; /* node in global wait list */
- spinlock_t lock; /* lock before modifying */
-};
-
-/* Work struct needed to handle LCT NOTIFY replies */
-struct i2o_exec_lct_notify_work {
- struct work_struct work; /* work struct */
- struct i2o_controller *c; /* controller on which the LCT NOTIFY
- was received */
-};
-
-/* Exec OSM class handling definition */
-static struct i2o_class_id i2o_exec_class_id[] = {
- {I2O_CLASS_EXECUTIVE},
- {I2O_CLASS_END}
-};
-
-/**
- * i2o_exec_wait_alloc - Allocate a i2o_exec_wait struct an initialize it
- *
- * Allocate the i2o_exec_wait struct and initialize the wait.
- *
- * Returns i2o_exec_wait pointer on success or negative error code on
- * failure.
- */
-static struct i2o_exec_wait *i2o_exec_wait_alloc(void)
-{
- struct i2o_exec_wait *wait;
-
- wait = kzalloc(sizeof(*wait), GFP_KERNEL);
- if (!wait)
- return NULL;
-
- INIT_LIST_HEAD(&wait->list);
- spin_lock_init(&wait->lock);
-
- return wait;
-};
-
-/**
- * i2o_exec_wait_free - Free an i2o_exec_wait struct
- * @wait: I2O wait data which should be cleaned up
- */
-static void i2o_exec_wait_free(struct i2o_exec_wait *wait)
-{
- kfree(wait);
-};
-
-/**
- * i2o_msg_post_wait_mem - Post and wait a message with DMA buffers
- * @c: controller
- * @msg: message to post
- * @timeout: time in seconds to wait
- * @dma: i2o_dma struct of the DMA buffer to free on failure
- *
- * This API allows an OSM to post a message and then be told whether or
- * not the system received a successful reply. If the message times out
- * then the value '-ETIMEDOUT' is returned. This is a special case. In
- * this situation the message may (should) complete at an indefinite time
- * in the future. When it completes it will use the memory buffer
- * attached to the request. If -ETIMEDOUT is returned then the memory
- * buffer must not be freed. Instead the event completion will free them
- * for you. In all other cases the buffer are your problem.
- *
- * Returns 0 on success, negative error code on timeout or positive error
- * code from reply.
- */
-int i2o_msg_post_wait_mem(struct i2o_controller *c, struct i2o_message *msg,
- unsigned long timeout, struct i2o_dma *dma)
-{
- DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
- struct i2o_exec_wait *wait;
- static u32 tcntxt = 0x80000000;
- unsigned long flags;
- int rc = 0;
-
- wait = i2o_exec_wait_alloc();
- if (!wait) {
- i2o_msg_nop(c, msg);
- return -ENOMEM;
- }
-
- if (tcntxt == 0xffffffff)
- tcntxt = 0x80000000;
-
- if (dma)
- wait->dma = *dma;
-
- /*
- * Fill in the message initiator context and transaction context.
- * We will only use transaction contexts >= 0x80000000 for POST WAIT,
- * so we could find a POST WAIT reply easier in the reply handler.
- */
- msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
- wait->tcntxt = tcntxt++;
- msg->u.s.tcntxt = cpu_to_le32(wait->tcntxt);
-
- wait->wq = &wq;
- /*
- * we add elements to the head, because if a entry in the list will
- * never be removed, we have to iterate over it every time
- */
- list_add(&wait->list, &i2o_exec_wait_list);
-
- /*
- * Post the message to the controller. At some point later it will
- * return. If we time out before it returns then complete will be zero.
- */
- i2o_msg_post(c, msg);
-
- wait_event_interruptible_timeout(wq, wait->complete, timeout * HZ);
-
- spin_lock_irqsave(&wait->lock, flags);
-
- wait->wq = NULL;
-
- if (wait->complete)
- rc = le32_to_cpu(wait->msg->body[0]) >> 24;
- else {
- /*
- * We cannot remove it now. This is important. When it does
- * terminate (which it must do if the controller has not
- * died...) then it will otherwise scribble on stuff.
- *
- * FIXME: try abort message
- */
- if (dma)
- dma->virt = NULL;
-
- rc = -ETIMEDOUT;
- }
-
- spin_unlock_irqrestore(&wait->lock, flags);
-
- if (rc != -ETIMEDOUT) {
- i2o_flush_reply(c, wait->m);
- i2o_exec_wait_free(wait);
- }
-
- return rc;
-};
-
-/**
- * i2o_msg_post_wait_complete - Reply to a i2o_msg_post request from IOP
- * @c: I2O controller which answers
- * @m: message id
- * @msg: pointer to the I2O reply message
- * @context: transaction context of request
- *
- * This function is called in interrupt context only. If the reply reached
- * before the timeout, the i2o_exec_wait struct is filled with the message
- * and the task will be waked up. The task is now responsible for returning
- * the message m back to the controller! If the message reaches us after
- * the timeout clean up the i2o_exec_wait struct (including allocated
- * DMA buffer).
- *
- * Return 0 on success and if the message m should not be given back to the
- * I2O controller, or >0 on success and if the message should be given back
- * afterwords. Returns negative error code on failure. In this case the
- * message must also be given back to the controller.
- */
-static int i2o_msg_post_wait_complete(struct i2o_controller *c, u32 m,
- struct i2o_message *msg, u32 context)
-{
- struct i2o_exec_wait *wait, *tmp;
- unsigned long flags;
- int rc = 1;
-
- /*
- * We need to search through the i2o_exec_wait_list to see if the given
- * message is still outstanding. If not, it means that the IOP took
- * longer to respond to the message than we had allowed and timer has
- * already expired. Not much we can do about that except log it for
- * debug purposes, increase timeout, and recompile.
- */
- list_for_each_entry_safe(wait, tmp, &i2o_exec_wait_list, list) {
- if (wait->tcntxt == context) {
- spin_lock_irqsave(&wait->lock, flags);
-
- list_del(&wait->list);
-
- wait->m = m;
- wait->msg = msg;
- wait->complete = 1;
-
- if (wait->wq)
- rc = 0;
- else
- rc = -1;
-
- spin_unlock_irqrestore(&wait->lock, flags);
-
- if (rc) {
- struct device *dev;
-
- dev = &c->pdev->dev;
-
- pr_debug("%s: timedout reply received!\n",
- c->name);
- i2o_dma_free(dev, &wait->dma);
- i2o_exec_wait_free(wait);
- } else
- wake_up_interruptible(wait->wq);
-
- return rc;
- }
- }
-
- osm_warn("%s: Bogus reply in POST WAIT (tr-context: %08x)!\n", c->name,
- context);
-
- return -1;
-};
-
-/**
- * i2o_exec_show_vendor_id - Displays Vendor ID of controller
- * @d: device of which the Vendor ID should be displayed
- * @attr: device_attribute to display
- * @buf: buffer into which the Vendor ID should be printed
- *
- * Returns number of bytes printed into buffer.
- */
-static ssize_t i2o_exec_show_vendor_id(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct i2o_device *dev = to_i2o_device(d);
- u16 id;
-
- if (!i2o_parm_field_get(dev, 0x0000, 0, &id, 2)) {
- sprintf(buf, "0x%04x", le16_to_cpu(id));
- return strlen(buf) + 1;
- }
-
- return 0;
-};
-
-/**
- * i2o_exec_show_product_id - Displays Product ID of controller
- * @d: device of which the Product ID should be displayed
- * @attr: device_attribute to display
- * @buf: buffer into which the Product ID should be printed
- *
- * Returns number of bytes printed into buffer.
- */
-static ssize_t i2o_exec_show_product_id(struct device *d,
- struct device_attribute *attr,
- char *buf)
-{
- struct i2o_device *dev = to_i2o_device(d);
- u16 id;
-
- if (!i2o_parm_field_get(dev, 0x0000, 1, &id, 2)) {
- sprintf(buf, "0x%04x", le16_to_cpu(id));
- return strlen(buf) + 1;
- }
-
- return 0;
-};
-
-/* Exec-OSM device attributes */
-static DEVICE_ATTR(vendor_id, S_IRUGO, i2o_exec_show_vendor_id, NULL);
-static DEVICE_ATTR(product_id, S_IRUGO, i2o_exec_show_product_id, NULL);
-
-/**
- * i2o_exec_probe - Called if a new I2O device (executive class) appears
- * @dev: I2O device which should be probed
- *
- * Registers event notification for every event from Executive device. The
- * return is always 0, because we want all devices of class Executive.
- *
- * Returns 0 on success.
- */
-static int i2o_exec_probe(struct device *dev)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
- int rc;
-
- rc = i2o_event_register(i2o_dev, &i2o_exec_driver, 0, 0xffffffff);
- if (rc) goto err_out;
-
- rc = device_create_file(dev, &dev_attr_vendor_id);
- if (rc) goto err_evtreg;
- rc = device_create_file(dev, &dev_attr_product_id);
- if (rc) goto err_vid;
-
- i2o_dev->iop->exec = i2o_dev;
-
- return 0;
-
-err_vid:
- device_remove_file(dev, &dev_attr_vendor_id);
-err_evtreg:
- i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0);
-err_out:
- return rc;
-};
-
-/**
- * i2o_exec_remove - Called on I2O device removal
- * @dev: I2O device which was removed
- *
- * Unregisters event notification from Executive I2O device.
- *
- * Returns 0 on success.
- */
-static int i2o_exec_remove(struct device *dev)
-{
- device_remove_file(dev, &dev_attr_product_id);
- device_remove_file(dev, &dev_attr_vendor_id);
-
- i2o_event_register(to_i2o_device(dev), &i2o_exec_driver, 0, 0);
-
- return 0;
-};
-
-#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES
-/**
- * i2o_exec_lct_notify - Send a asynchronus LCT NOTIFY request
- * @c: I2O controller to which the request should be send
- * @change_ind: change indicator
- *
- * This function sends a LCT NOTIFY request to the I2O controller with
- * the change indicator change_ind. If the change_ind == 0 the controller
- * replies immediately after the request. If change_ind > 0 the reply is
- * send after change indicator of the LCT is > change_ind.
- */
-static int i2o_exec_lct_notify(struct i2o_controller *c, u32 change_ind)
-{
- i2o_status_block *sb = c->status_block.virt;
- struct device *dev;
- struct i2o_message *msg;
-
- mutex_lock(&c->lct_lock);
-
- dev = &c->pdev->dev;
-
- if (i2o_dma_realloc(dev, &c->dlct,
- le32_to_cpu(sb->expected_lct_size))) {
- mutex_unlock(&c->lct_lock);
- return -ENOMEM;
- }
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg)) {
- mutex_unlock(&c->lct_lock);
- return PTR_ERR(msg);
- }
-
- msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
- msg->u.head[1] = cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
- ADAPTER_TID);
- msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
- msg->u.s.tcntxt = cpu_to_le32(0x00000000);
- msg->body[0] = cpu_to_le32(0xffffffff);
- msg->body[1] = cpu_to_le32(change_ind);
- msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
- msg->body[3] = cpu_to_le32(c->dlct.phys);
-
- i2o_msg_post(c, msg);
-
- mutex_unlock(&c->lct_lock);
-
- return 0;
-}
-#endif
-
-/**
- * i2o_exec_lct_modified - Called on LCT NOTIFY reply
- * @_work: work struct for a specific controller
- *
- * This function handles asynchronus LCT NOTIFY replies. It parses the
- * new LCT and if the buffer for the LCT was to small sends a LCT NOTIFY
- * again, otherwise send LCT NOTIFY to get informed on next LCT change.
- */
-static void i2o_exec_lct_modified(struct work_struct *_work)
-{
- struct i2o_exec_lct_notify_work *work =
- container_of(_work, struct i2o_exec_lct_notify_work, work);
- u32 change_ind = 0;
- struct i2o_controller *c = work->c;
-
- kfree(work);
-
- if (i2o_device_parse_lct(c) != -EAGAIN)
- change_ind = c->lct->change_ind + 1;
-
-#ifdef CONFIG_I2O_LCT_NOTIFY_ON_CHANGES
- i2o_exec_lct_notify(c, change_ind);
-#endif
-};
-
-/**
- * i2o_exec_reply - I2O Executive reply handler
- * @c: I2O controller from which the reply comes
- * @m: message id
- * @msg: pointer to the I2O reply message
- *
- * This function is always called from interrupt context. If a POST WAIT
- * reply was received, pass it to the complete function. If a LCT NOTIFY
- * reply was received, a new event is created to handle the update.
- *
- * Returns 0 on success and if the reply should not be flushed or > 0
- * on success and if the reply should be flushed. Returns negative error
- * code on failure and if the reply should be flushed.
- */
-static int i2o_exec_reply(struct i2o_controller *c, u32 m,
- struct i2o_message *msg)
-{
- u32 context;
-
- if (le32_to_cpu(msg->u.head[0]) & MSG_FAIL) {
- struct i2o_message __iomem *pmsg;
- u32 pm;
-
- /*
- * If Fail bit is set we must take the transaction context of
- * the preserved message to find the right request again.
- */
-
- pm = le32_to_cpu(msg->body[3]);
- pmsg = i2o_msg_in_to_virt(c, pm);
- context = readl(&pmsg->u.s.tcntxt);
-
- i2o_report_status(KERN_INFO, "i2o_core", msg);
-
- /* Release the preserved msg */
- i2o_msg_nop_mfa(c, pm);
- } else
- context = le32_to_cpu(msg->u.s.tcntxt);
-
- if (context & 0x80000000)
- return i2o_msg_post_wait_complete(c, m, msg, context);
-
- if ((le32_to_cpu(msg->u.head[1]) >> 24) == I2O_CMD_LCT_NOTIFY) {
- struct i2o_exec_lct_notify_work *work;
-
- pr_debug("%s: LCT notify received\n", c->name);
-
- work = kmalloc(sizeof(*work), GFP_ATOMIC);
- if (!work)
- return -ENOMEM;
-
- work->c = c;
-
- INIT_WORK(&work->work, i2o_exec_lct_modified);
- queue_work(i2o_exec_driver.event_queue, &work->work);
- return 1;
- }
-
- /*
- * If this happens, we want to dump the message to the syslog so
- * it can be sent back to the card manufacturer by the end user
- * to aid in debugging.
- *
- */
- printk(KERN_WARNING "%s: Unsolicited message reply sent to core! Message dumped to syslog\n",
- c->name);
- i2o_dump_message(msg);
-
- return -EFAULT;
-}
-
-/**
- * i2o_exec_event - Event handling function
- * @work: Work item in occurring event
- *
- * Handles events send by the Executive device. At the moment does not do
- * anything useful.
- */
-static void i2o_exec_event(struct work_struct *work)
-{
- struct i2o_event *evt = container_of(work, struct i2o_event, work);
-
- if (likely(evt->i2o_dev))
- osm_debug("Event received from device: %d\n",
- evt->i2o_dev->lct_data.tid);
- kfree(evt);
-};
-
-/**
- * i2o_exec_lct_get - Get the IOP's Logical Configuration Table
- * @c: I2O controller from which the LCT should be fetched
- *
- * Send a LCT NOTIFY request to the controller, and wait
- * I2O_TIMEOUT_LCT_GET seconds until arrival of response. If the LCT is
- * to large, retry it.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_exec_lct_get(struct i2o_controller *c)
-{
- struct i2o_message *msg;
- int i = 0;
- int rc = -EAGAIN;
-
- for (i = 1; i <= I2O_LCT_GET_TRIES; i++) {
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] =
- cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_LCT_NOTIFY << 24 | HOST_TID << 12 |
- ADAPTER_TID);
- msg->body[0] = cpu_to_le32(0xffffffff);
- msg->body[1] = cpu_to_le32(0x00000000);
- msg->body[2] = cpu_to_le32(0xd0000000 | c->dlct.len);
- msg->body[3] = cpu_to_le32(c->dlct.phys);
-
- rc = i2o_msg_post_wait(c, msg, I2O_TIMEOUT_LCT_GET);
- if (rc < 0)
- break;
-
- rc = i2o_device_parse_lct(c);
- if (rc != -EAGAIN)
- break;
- }
-
- return rc;
-}
-
-/* Exec OSM driver struct */
-struct i2o_driver i2o_exec_driver = {
- .name = OSM_NAME,
- .reply = i2o_exec_reply,
- .event = i2o_exec_event,
- .classes = i2o_exec_class_id,
- .driver = {
- .probe = i2o_exec_probe,
- .remove = i2o_exec_remove,
- },
-};
-
-/**
- * i2o_exec_init - Registers the Exec OSM
- *
- * Registers the Exec OSM in the I2O core.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int __init i2o_exec_init(void)
-{
- return i2o_driver_register(&i2o_exec_driver);
-};
-
-/**
- * i2o_exec_exit - Removes the Exec OSM
- *
- * Unregisters the Exec OSM from the I2O core.
- */
-void i2o_exec_exit(void)
-{
- i2o_driver_unregister(&i2o_exec_driver);
-};
-
-EXPORT_SYMBOL(i2o_msg_post_wait_mem);
-EXPORT_SYMBOL(i2o_exec_lct_get);
+++ /dev/null
-/*
- * I2O kernel space accessible structures/APIs
- *
- * (c) Copyright 1999, 2000 Red Hat Software
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- *************************************************************************
- *
- * This header file defined the I2O APIs/structures for use by
- * the I2O kernel modules.
- *
- */
-
-#ifndef _I2O_H
-#define _I2O_H
-
-#include <linux/i2o-dev.h>
-
-/* How many different OSM's are we allowing */
-#define I2O_MAX_DRIVERS 8
-
-#include <linux/pci.h>
-#include <linux/bug.h>
-#include <linux/dma-mapping.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h> /* work_struct */
-#include <linux/mempool.h>
-#include <linux/mutex.h>
-#include <linux/scatterlist.h>
-#include <linux/semaphore.h> /* Needed for MUTEX init macros */
-
-#include <asm/io.h>
-
-/* message queue empty */
-#define I2O_QUEUE_EMPTY 0xffffffff
-
-/*
- * Cache strategies
- */
-
-/* The NULL strategy leaves everything up to the controller. This tends to be a
- * pessimal but functional choice.
- */
-#define CACHE_NULL 0
-/* Prefetch data when reading. We continually attempt to load the next 32 sectors
- * into the controller cache.
- */
-#define CACHE_PREFETCH 1
-/* Prefetch data when reading. We sometimes attempt to load the next 32 sectors
- * into the controller cache. When an I/O is less <= 8K we assume its probably
- * not sequential and don't prefetch (default)
- */
-#define CACHE_SMARTFETCH 2
-/* Data is written to the cache and then out on to the disk. The I/O must be
- * physically on the medium before the write is acknowledged (default without
- * NVRAM)
- */
-#define CACHE_WRITETHROUGH 17
-/* Data is written to the cache and then out on to the disk. The controller
- * is permitted to write back the cache any way it wants. (default if battery
- * backed NVRAM is present). It can be useful to set this for swap regardless of
- * battery state.
- */
-#define CACHE_WRITEBACK 18
-/* Optimise for under powered controllers, especially on RAID1 and RAID0. We
- * write large I/O's directly to disk bypassing the cache to avoid the extra
- * memory copy hits. Small writes are writeback cached
- */
-#define CACHE_SMARTBACK 19
-/* Optimise for under powered controllers, especially on RAID1 and RAID0. We
- * write large I/O's directly to disk bypassing the cache to avoid the extra
- * memory copy hits. Small writes are writethrough cached. Suitable for devices
- * lacking battery backup
- */
-#define CACHE_SMARTTHROUGH 20
-
-/*
- * Ioctl structures
- */
-
-#define BLKI2OGRSTRAT _IOR('2', 1, int)
-#define BLKI2OGWSTRAT _IOR('2', 2, int)
-#define BLKI2OSRSTRAT _IOW('2', 3, int)
-#define BLKI2OSWSTRAT _IOW('2', 4, int)
-
-/*
- * I2O Function codes
- */
-
-/*
- * Executive Class
- */
-#define I2O_CMD_ADAPTER_ASSIGN 0xB3
-#define I2O_CMD_ADAPTER_READ 0xB2
-#define I2O_CMD_ADAPTER_RELEASE 0xB5
-#define I2O_CMD_BIOS_INFO_SET 0xA5
-#define I2O_CMD_BOOT_DEVICE_SET 0xA7
-#define I2O_CMD_CONFIG_VALIDATE 0xBB
-#define I2O_CMD_CONN_SETUP 0xCA
-#define I2O_CMD_DDM_DESTROY 0xB1
-#define I2O_CMD_DDM_ENABLE 0xD5
-#define I2O_CMD_DDM_QUIESCE 0xC7
-#define I2O_CMD_DDM_RESET 0xD9
-#define I2O_CMD_DDM_SUSPEND 0xAF
-#define I2O_CMD_DEVICE_ASSIGN 0xB7
-#define I2O_CMD_DEVICE_RELEASE 0xB9
-#define I2O_CMD_HRT_GET 0xA8
-#define I2O_CMD_ADAPTER_CLEAR 0xBE
-#define I2O_CMD_ADAPTER_CONNECT 0xC9
-#define I2O_CMD_ADAPTER_RESET 0xBD
-#define I2O_CMD_LCT_NOTIFY 0xA2
-#define I2O_CMD_OUTBOUND_INIT 0xA1
-#define I2O_CMD_PATH_ENABLE 0xD3
-#define I2O_CMD_PATH_QUIESCE 0xC5
-#define I2O_CMD_PATH_RESET 0xD7
-#define I2O_CMD_STATIC_MF_CREATE 0xDD
-#define I2O_CMD_STATIC_MF_RELEASE 0xDF
-#define I2O_CMD_STATUS_GET 0xA0
-#define I2O_CMD_SW_DOWNLOAD 0xA9
-#define I2O_CMD_SW_UPLOAD 0xAB
-#define I2O_CMD_SW_REMOVE 0xAD
-#define I2O_CMD_SYS_ENABLE 0xD1
-#define I2O_CMD_SYS_MODIFY 0xC1
-#define I2O_CMD_SYS_QUIESCE 0xC3
-#define I2O_CMD_SYS_TAB_SET 0xA3
-
-/*
- * Utility Class
- */
-#define I2O_CMD_UTIL_NOP 0x00
-#define I2O_CMD_UTIL_ABORT 0x01
-#define I2O_CMD_UTIL_CLAIM 0x09
-#define I2O_CMD_UTIL_RELEASE 0x0B
-#define I2O_CMD_UTIL_PARAMS_GET 0x06
-#define I2O_CMD_UTIL_PARAMS_SET 0x05
-#define I2O_CMD_UTIL_EVT_REGISTER 0x13
-#define I2O_CMD_UTIL_EVT_ACK 0x14
-#define I2O_CMD_UTIL_CONFIG_DIALOG 0x10
-#define I2O_CMD_UTIL_DEVICE_RESERVE 0x0D
-#define I2O_CMD_UTIL_DEVICE_RELEASE 0x0F
-#define I2O_CMD_UTIL_LOCK 0x17
-#define I2O_CMD_UTIL_LOCK_RELEASE 0x19
-#define I2O_CMD_UTIL_REPLY_FAULT_NOTIFY 0x15
-
-/*
- * SCSI Host Bus Adapter Class
- */
-#define I2O_CMD_SCSI_EXEC 0x81
-#define I2O_CMD_SCSI_ABORT 0x83
-#define I2O_CMD_SCSI_BUSRESET 0x27
-
-/*
- * Bus Adapter Class
- */
-#define I2O_CMD_BUS_ADAPTER_RESET 0x85
-#define I2O_CMD_BUS_RESET 0x87
-#define I2O_CMD_BUS_SCAN 0x89
-#define I2O_CMD_BUS_QUIESCE 0x8b
-
-/*
- * Random Block Storage Class
- */
-#define I2O_CMD_BLOCK_READ 0x30
-#define I2O_CMD_BLOCK_WRITE 0x31
-#define I2O_CMD_BLOCK_CFLUSH 0x37
-#define I2O_CMD_BLOCK_MLOCK 0x49
-#define I2O_CMD_BLOCK_MUNLOCK 0x4B
-#define I2O_CMD_BLOCK_MMOUNT 0x41
-#define I2O_CMD_BLOCK_MEJECT 0x43
-#define I2O_CMD_BLOCK_POWER 0x70
-
-#define I2O_CMD_PRIVATE 0xFF
-
-/* Command status values */
-
-#define I2O_CMD_IN_PROGRESS 0x01
-#define I2O_CMD_REJECTED 0x02
-#define I2O_CMD_FAILED 0x03
-#define I2O_CMD_COMPLETED 0x04
-
-/* I2O API function return values */
-
-#define I2O_RTN_NO_ERROR 0
-#define I2O_RTN_NOT_INIT 1
-#define I2O_RTN_FREE_Q_EMPTY 2
-#define I2O_RTN_TCB_ERROR 3
-#define I2O_RTN_TRANSACTION_ERROR 4
-#define I2O_RTN_ADAPTER_ALREADY_INIT 5
-#define I2O_RTN_MALLOC_ERROR 6
-#define I2O_RTN_ADPTR_NOT_REGISTERED 7
-#define I2O_RTN_MSG_REPLY_TIMEOUT 8
-#define I2O_RTN_NO_STATUS 9
-#define I2O_RTN_NO_FIRM_VER 10
-#define I2O_RTN_NO_LINK_SPEED 11
-
-/* Reply message status defines for all messages */
-
-#define I2O_REPLY_STATUS_SUCCESS 0x00
-#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
-#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
-#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
-#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04
-#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
-#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06
-#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x08
-#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x09
-#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x0A
-#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0B
-#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80
-
-/* Status codes and Error Information for Parameter functions */
-
-#define I2O_PARAMS_STATUS_SUCCESS 0x00
-#define I2O_PARAMS_STATUS_BAD_KEY_ABORT 0x01
-#define I2O_PARAMS_STATUS_BAD_KEY_CONTINUE 0x02
-#define I2O_PARAMS_STATUS_BUFFER_FULL 0x03
-#define I2O_PARAMS_STATUS_BUFFER_TOO_SMALL 0x04
-#define I2O_PARAMS_STATUS_FIELD_UNREADABLE 0x05
-#define I2O_PARAMS_STATUS_FIELD_UNWRITEABLE 0x06
-#define I2O_PARAMS_STATUS_INSUFFICIENT_FIELDS 0x07
-#define I2O_PARAMS_STATUS_INVALID_GROUP_ID 0x08
-#define I2O_PARAMS_STATUS_INVALID_OPERATION 0x09
-#define I2O_PARAMS_STATUS_NO_KEY_FIELD 0x0A
-#define I2O_PARAMS_STATUS_NO_SUCH_FIELD 0x0B
-#define I2O_PARAMS_STATUS_NON_DYNAMIC_GROUP 0x0C
-#define I2O_PARAMS_STATUS_OPERATION_ERROR 0x0D
-#define I2O_PARAMS_STATUS_SCALAR_ERROR 0x0E
-#define I2O_PARAMS_STATUS_TABLE_ERROR 0x0F
-#define I2O_PARAMS_STATUS_WRONG_GROUP_TYPE 0x10
-
-/* DetailedStatusCode defines for Executive, DDM, Util and Transaction error
- * messages: Table 3-2 Detailed Status Codes.*/
-
-#define I2O_DSC_SUCCESS 0x0000
-#define I2O_DSC_BAD_KEY 0x0002
-#define I2O_DSC_TCL_ERROR 0x0003
-#define I2O_DSC_REPLY_BUFFER_FULL 0x0004
-#define I2O_DSC_NO_SUCH_PAGE 0x0005
-#define I2O_DSC_INSUFFICIENT_RESOURCE_SOFT 0x0006
-#define I2O_DSC_INSUFFICIENT_RESOURCE_HARD 0x0007
-#define I2O_DSC_CHAIN_BUFFER_TOO_LARGE 0x0009
-#define I2O_DSC_UNSUPPORTED_FUNCTION 0x000A
-#define I2O_DSC_DEVICE_LOCKED 0x000B
-#define I2O_DSC_DEVICE_RESET 0x000C
-#define I2O_DSC_INAPPROPRIATE_FUNCTION 0x000D
-#define I2O_DSC_INVALID_INITIATOR_ADDRESS 0x000E
-#define I2O_DSC_INVALID_MESSAGE_FLAGS 0x000F
-#define I2O_DSC_INVALID_OFFSET 0x0010
-#define I2O_DSC_INVALID_PARAMETER 0x0011
-#define I2O_DSC_INVALID_REQUEST 0x0012
-#define I2O_DSC_INVALID_TARGET_ADDRESS 0x0013
-#define I2O_DSC_MESSAGE_TOO_LARGE 0x0014
-#define I2O_DSC_MESSAGE_TOO_SMALL 0x0015
-#define I2O_DSC_MISSING_PARAMETER 0x0016
-#define I2O_DSC_TIMEOUT 0x0017
-#define I2O_DSC_UNKNOWN_ERROR 0x0018
-#define I2O_DSC_UNKNOWN_FUNCTION 0x0019
-#define I2O_DSC_UNSUPPORTED_VERSION 0x001A
-#define I2O_DSC_DEVICE_BUSY 0x001B
-#define I2O_DSC_DEVICE_NOT_AVAILABLE 0x001C
-
-/* DetailedStatusCode defines for Block Storage Operation: Table 6-7 Detailed
- Status Codes.*/
-
-#define I2O_BSA_DSC_SUCCESS 0x0000
-#define I2O_BSA_DSC_MEDIA_ERROR 0x0001
-#define I2O_BSA_DSC_ACCESS_ERROR 0x0002
-#define I2O_BSA_DSC_DEVICE_FAILURE 0x0003
-#define I2O_BSA_DSC_DEVICE_NOT_READY 0x0004
-#define I2O_BSA_DSC_MEDIA_NOT_PRESENT 0x0005
-#define I2O_BSA_DSC_MEDIA_LOCKED 0x0006
-#define I2O_BSA_DSC_MEDIA_FAILURE 0x0007
-#define I2O_BSA_DSC_PROTOCOL_FAILURE 0x0008
-#define I2O_BSA_DSC_BUS_FAILURE 0x0009
-#define I2O_BSA_DSC_ACCESS_VIOLATION 0x000A
-#define I2O_BSA_DSC_WRITE_PROTECTED 0x000B
-#define I2O_BSA_DSC_DEVICE_RESET 0x000C
-#define I2O_BSA_DSC_VOLUME_CHANGED 0x000D
-#define I2O_BSA_DSC_TIMEOUT 0x000E
-
-/* FailureStatusCodes, Table 3-3 Message Failure Codes */
-
-#define I2O_FSC_TRANSPORT_SERVICE_SUSPENDED 0x81
-#define I2O_FSC_TRANSPORT_SERVICE_TERMINATED 0x82
-#define I2O_FSC_TRANSPORT_CONGESTION 0x83
-#define I2O_FSC_TRANSPORT_FAILURE 0x84
-#define I2O_FSC_TRANSPORT_STATE_ERROR 0x85
-#define I2O_FSC_TRANSPORT_TIME_OUT 0x86
-#define I2O_FSC_TRANSPORT_ROUTING_FAILURE 0x87
-#define I2O_FSC_TRANSPORT_INVALID_VERSION 0x88
-#define I2O_FSC_TRANSPORT_INVALID_OFFSET 0x89
-#define I2O_FSC_TRANSPORT_INVALID_MSG_FLAGS 0x8A
-#define I2O_FSC_TRANSPORT_FRAME_TOO_SMALL 0x8B
-#define I2O_FSC_TRANSPORT_FRAME_TOO_LARGE 0x8C
-#define I2O_FSC_TRANSPORT_INVALID_TARGET_ID 0x8D
-#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_ID 0x8E
-#define I2O_FSC_TRANSPORT_INVALID_INITIATOR_CONTEXT 0x8F
-#define I2O_FSC_TRANSPORT_UNKNOWN_FAILURE 0xFF
-
-/* Device Claim Types */
-#define I2O_CLAIM_PRIMARY 0x01000000
-#define I2O_CLAIM_MANAGEMENT 0x02000000
-#define I2O_CLAIM_AUTHORIZED 0x03000000
-#define I2O_CLAIM_SECONDARY 0x04000000
-
-/* Message header defines for VersionOffset */
-#define I2OVER15 0x0001
-#define I2OVER20 0x0002
-
-/* Default is 1.5 */
-#define I2OVERSION I2OVER15
-
-#define SGL_OFFSET_0 I2OVERSION
-#define SGL_OFFSET_4 (0x0040 | I2OVERSION)
-#define SGL_OFFSET_5 (0x0050 | I2OVERSION)
-#define SGL_OFFSET_6 (0x0060 | I2OVERSION)
-#define SGL_OFFSET_7 (0x0070 | I2OVERSION)
-#define SGL_OFFSET_8 (0x0080 | I2OVERSION)
-#define SGL_OFFSET_9 (0x0090 | I2OVERSION)
-#define SGL_OFFSET_10 (0x00A0 | I2OVERSION)
-#define SGL_OFFSET_11 (0x00B0 | I2OVERSION)
-#define SGL_OFFSET_12 (0x00C0 | I2OVERSION)
-#define SGL_OFFSET(x) (((x)<<4) | I2OVERSION)
-
-/* Transaction Reply Lists (TRL) Control Word structure */
-#define TRL_SINGLE_FIXED_LENGTH 0x00
-#define TRL_SINGLE_VARIABLE_LENGTH 0x40
-#define TRL_MULTIPLE_FIXED_LENGTH 0x80
-
- /* msg header defines for MsgFlags */
-#define MSG_STATIC 0x0100
-#define MSG_64BIT_CNTXT 0x0200
-#define MSG_MULTI_TRANS 0x1000
-#define MSG_FAIL 0x2000
-#define MSG_FINAL 0x4000
-#define MSG_REPLY 0x8000
-
- /* minimum size msg */
-#define THREE_WORD_MSG_SIZE 0x00030000
-#define FOUR_WORD_MSG_SIZE 0x00040000
-#define FIVE_WORD_MSG_SIZE 0x00050000
-#define SIX_WORD_MSG_SIZE 0x00060000
-#define SEVEN_WORD_MSG_SIZE 0x00070000
-#define EIGHT_WORD_MSG_SIZE 0x00080000
-#define NINE_WORD_MSG_SIZE 0x00090000
-#define TEN_WORD_MSG_SIZE 0x000A0000
-#define ELEVEN_WORD_MSG_SIZE 0x000B0000
-#define I2O_MESSAGE_SIZE(x) ((x)<<16)
-
-/* special TID assignments */
-#define ADAPTER_TID 0
-#define HOST_TID 1
-
-/* outbound queue defines */
-#define I2O_MAX_OUTBOUND_MSG_FRAMES 128
-#define I2O_OUTBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */
-
-/* inbound queue definitions */
-#define I2O_MSG_INPOOL_MIN 32
-#define I2O_INBOUND_MSG_FRAME_SIZE 128 /* in 32-bit words */
-
-#define I2O_POST_WAIT_OK 0
-#define I2O_POST_WAIT_TIMEOUT -ETIMEDOUT
-
-#define I2O_CONTEXT_LIST_MIN_LENGTH 15
-#define I2O_CONTEXT_LIST_USED 0x01
-#define I2O_CONTEXT_LIST_DELETED 0x02
-
-/* timeouts */
-#define I2O_TIMEOUT_INIT_OUTBOUND_QUEUE 15
-#define I2O_TIMEOUT_MESSAGE_GET 5
-#define I2O_TIMEOUT_RESET 30
-#define I2O_TIMEOUT_STATUS_GET 5
-#define I2O_TIMEOUT_LCT_GET 360
-#define I2O_TIMEOUT_SCSI_SCB_ABORT 240
-
-/* retries */
-#define I2O_HRT_GET_TRIES 3
-#define I2O_LCT_GET_TRIES 3
-
-/* defines for max_sectors and max_phys_segments */
-#define I2O_MAX_SECTORS 1024
-#define I2O_MAX_SECTORS_LIMITED 128
-#define I2O_MAX_PHYS_SEGMENTS BLK_MAX_SEGMENTS
-
-/*
- * Message structures
- */
-struct i2o_message {
- union {
- struct {
- u8 version_offset;
- u8 flags;
- u16 size;
- u32 target_tid:12;
- u32 init_tid:12;
- u32 function:8;
- u32 icntxt; /* initiator context */
- u32 tcntxt; /* transaction context */
- } s;
- u32 head[4];
- } u;
- /* List follows */
- u32 body[0];
-};
-
-/* MFA and I2O message used by mempool */
-struct i2o_msg_mfa {
- u32 mfa; /* MFA returned by the controller */
- struct i2o_message msg; /* I2O message */
-};
-
-/*
- * Each I2O device entity has one of these. There is one per device.
- */
-struct i2o_device {
- i2o_lct_entry lct_data; /* Device LCT information */
-
- struct i2o_controller *iop; /* Controlling IOP */
- struct list_head list; /* node in IOP devices list */
-
- struct device device;
-
- struct mutex lock; /* device lock */
-};
-
-/*
- * Event structure provided to the event handling function
- */
-struct i2o_event {
- struct work_struct work;
- struct i2o_device *i2o_dev; /* I2O device pointer from which the
- event reply was initiated */
- u16 size; /* Size of data in 32-bit words */
- u32 tcntxt; /* Transaction context used at
- registration */
- u32 event_indicator; /* Event indicator from reply */
- u32 data[0]; /* Event data from reply */
-};
-
-/*
- * I2O classes which could be handled by the OSM
- */
-struct i2o_class_id {
- u16 class_id:12;
-};
-
-/*
- * I2O driver structure for OSMs
- */
-struct i2o_driver {
- char *name; /* OSM name */
- int context; /* Low 8 bits of the transaction info */
- struct i2o_class_id *classes; /* I2O classes that this OSM handles */
-
- /* Message reply handler */
- int (*reply) (struct i2o_controller *, u32, struct i2o_message *);
-
- /* Event handler */
- work_func_t event;
-
- struct workqueue_struct *event_queue; /* Event queue */
-
- struct device_driver driver;
-
- /* notification of changes */
- void (*notify_controller_add) (struct i2o_controller *);
- void (*notify_controller_remove) (struct i2o_controller *);
- void (*notify_device_add) (struct i2o_device *);
- void (*notify_device_remove) (struct i2o_device *);
-
- struct semaphore lock;
-};
-
-/*
- * Contains DMA mapped address information
- */
-struct i2o_dma {
- void *virt;
- dma_addr_t phys;
- size_t len;
-};
-
-/*
- * Contains slab cache and mempool information
- */
-struct i2o_pool {
- char *name;
- struct kmem_cache *slab;
- mempool_t *mempool;
-};
-
-/*
- * Contains IO mapped address information
- */
-struct i2o_io {
- void __iomem *virt;
- unsigned long phys;
- unsigned long len;
-};
-
-/*
- * Context queue entry, used for 32-bit context on 64-bit systems
- */
-struct i2o_context_list_element {
- struct list_head list;
- u32 context;
- void *ptr;
- unsigned long timestamp;
-};
-
-/*
- * Each I2O controller has one of these objects
- */
-struct i2o_controller {
- char name[16];
- int unit;
- int type;
-
- struct pci_dev *pdev; /* PCI device */
-
- unsigned int promise:1; /* Promise controller */
- unsigned int adaptec:1; /* DPT / Adaptec controller */
- unsigned int raptor:1; /* split bar */
- unsigned int no_quiesce:1; /* dont quiesce before reset */
- unsigned int short_req:1; /* use small block sizes */
- unsigned int limit_sectors:1; /* limit number of sectors / request */
- unsigned int pae_support:1; /* controller has 64-bit SGL support */
-
- struct list_head devices; /* list of I2O devices */
- struct list_head list; /* Controller list */
-
- void __iomem *in_port; /* Inbout port address */
- void __iomem *out_port; /* Outbound port address */
- void __iomem *irq_status; /* Interrupt status register address */
- void __iomem *irq_mask; /* Interrupt mask register address */
-
- struct i2o_dma status; /* IOP status block */
-
- struct i2o_dma hrt; /* HW Resource Table */
- i2o_lct *lct; /* Logical Config Table */
- struct i2o_dma dlct; /* Temp LCT */
- struct mutex lct_lock; /* Lock for LCT updates */
- struct i2o_dma status_block; /* IOP status block */
-
- struct i2o_io base; /* controller messaging unit */
- struct i2o_io in_queue; /* inbound message queue Host->IOP */
- struct i2o_dma out_queue; /* outbound message queue IOP->Host */
-
- struct i2o_pool in_msg; /* mempool for inbound messages */
-
- unsigned int battery:1; /* Has a battery backup */
- unsigned int io_alloc:1; /* An I/O resource was allocated */
- unsigned int mem_alloc:1; /* A memory resource was allocated */
-
- struct resource io_resource; /* I/O resource allocated to the IOP */
- struct resource mem_resource; /* Mem resource allocated to the IOP */
-
- struct device device;
- struct i2o_device *exec; /* Executive */
-#if BITS_PER_LONG == 64
- spinlock_t context_list_lock; /* lock for context_list */
- atomic_t context_list_counter; /* needed for unique contexts */
- struct list_head context_list; /* list of context id's
- and pointers */
-#endif
- spinlock_t lock; /* lock for controller
- configuration */
- void *driver_data[I2O_MAX_DRIVERS]; /* storage for drivers */
-};
-
-/*
- * I2O System table entry
- *
- * The system table contains information about all the IOPs in the
- * system. It is sent to all IOPs so that they can create peer2peer
- * connections between them.
- */
-struct i2o_sys_tbl_entry {
- u16 org_id;
- u16 reserved1;
- u32 iop_id:12;
- u32 reserved2:20;
- u16 seg_num:12;
- u16 i2o_version:4;
- u8 iop_state;
- u8 msg_type;
- u16 frame_size;
- u16 reserved3;
- u32 last_changed;
- u32 iop_capabilities;
- u32 inbound_low;
- u32 inbound_high;
-};
-
-struct i2o_sys_tbl {
- u8 num_entries;
- u8 version;
- u16 reserved1;
- u32 change_ind;
- u32 reserved2;
- u32 reserved3;
- struct i2o_sys_tbl_entry iops[0];
-};
-
-extern struct list_head i2o_controllers;
-
-/* Message functions */
-extern struct i2o_message *i2o_msg_get_wait(struct i2o_controller *, int);
-extern int i2o_msg_post_wait_mem(struct i2o_controller *, struct i2o_message *,
- unsigned long, struct i2o_dma *);
-
-/* IOP functions */
-extern int i2o_status_get(struct i2o_controller *);
-
-extern int i2o_event_register(struct i2o_device *, struct i2o_driver *, int,
- u32);
-extern struct i2o_device *i2o_iop_find_device(struct i2o_controller *, u16);
-extern struct i2o_controller *i2o_find_iop(int);
-
-/* Functions needed for handling 64-bit pointers in 32-bit context */
-#if BITS_PER_LONG == 64
-extern u32 i2o_cntxt_list_add(struct i2o_controller *, void *);
-extern void *i2o_cntxt_list_get(struct i2o_controller *, u32);
-extern u32 i2o_cntxt_list_remove(struct i2o_controller *, void *);
-extern u32 i2o_cntxt_list_get_ptr(struct i2o_controller *, void *);
-
-static inline u32 i2o_ptr_low(void *ptr)
-{
- return (u32) (u64) ptr;
-};
-
-static inline u32 i2o_ptr_high(void *ptr)
-{
- return (u32) ((u64) ptr >> 32);
-};
-
-static inline u32 i2o_dma_low(dma_addr_t dma_addr)
-{
- return (u32) (u64) dma_addr;
-};
-
-static inline u32 i2o_dma_high(dma_addr_t dma_addr)
-{
- return (u32) ((u64) dma_addr >> 32);
-};
-#else
-static inline u32 i2o_cntxt_list_add(struct i2o_controller *c, void *ptr)
-{
- return (u32) ptr;
-};
-
-static inline void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context)
-{
- return (void *)context;
-};
-
-static inline u32 i2o_cntxt_list_remove(struct i2o_controller *c, void *ptr)
-{
- return (u32) ptr;
-};
-
-static inline u32 i2o_cntxt_list_get_ptr(struct i2o_controller *c, void *ptr)
-{
- return (u32) ptr;
-};
-
-static inline u32 i2o_ptr_low(void *ptr)
-{
- return (u32) ptr;
-};
-
-static inline u32 i2o_ptr_high(void *ptr)
-{
- return 0;
-};
-
-static inline u32 i2o_dma_low(dma_addr_t dma_addr)
-{
- return (u32) dma_addr;
-};
-
-static inline u32 i2o_dma_high(dma_addr_t dma_addr)
-{
- return 0;
-};
-#endif
-
-extern u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size);
-extern dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
- size_t size,
- enum dma_data_direction direction,
- u32 ** sg_ptr);
-extern int i2o_dma_map_sg(struct i2o_controller *c,
- struct scatterlist *sg, int sg_count,
- enum dma_data_direction direction,
- u32 ** sg_ptr);
-extern int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len);
-extern void i2o_dma_free(struct device *dev, struct i2o_dma *addr);
-extern int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr,
- size_t len);
-extern int i2o_pool_alloc(struct i2o_pool *pool, const char *name,
- size_t size, int min_nr);
-extern void i2o_pool_free(struct i2o_pool *pool);
-/* I2O driver (OSM) functions */
-extern int i2o_driver_register(struct i2o_driver *);
-extern void i2o_driver_unregister(struct i2o_driver *);
-
-/**
- * i2o_driver_notify_controller_add - Send notification of added controller
- * @drv: I2O driver
- * @c: I2O controller
- *
- * Send notification of added controller to a single registered driver.
- */
-static inline void i2o_driver_notify_controller_add(struct i2o_driver *drv,
- struct i2o_controller *c)
-{
- if (drv->notify_controller_add)
- drv->notify_controller_add(c);
-};
-
-/**
- * i2o_driver_notify_controller_remove - Send notification of removed controller
- * @drv: I2O driver
- * @c: I2O controller
- *
- * Send notification of removed controller to a single registered driver.
- */
-static inline void i2o_driver_notify_controller_remove(struct i2o_driver *drv,
- struct i2o_controller *c)
-{
- if (drv->notify_controller_remove)
- drv->notify_controller_remove(c);
-};
-
-/**
- * i2o_driver_notify_device_add - Send notification of added device
- * @drv: I2O driver
- * @i2o_dev: the added i2o_device
- *
- * Send notification of added device to a single registered driver.
- */
-static inline void i2o_driver_notify_device_add(struct i2o_driver *drv,
- struct i2o_device *i2o_dev)
-{
- if (drv->notify_device_add)
- drv->notify_device_add(i2o_dev);
-};
-
-/**
- * i2o_driver_notify_device_remove - Send notification of removed device
- * @drv: I2O driver
- * @i2o_dev: the added i2o_device
- *
- * Send notification of removed device to a single registered driver.
- */
-static inline void i2o_driver_notify_device_remove(struct i2o_driver *drv,
- struct i2o_device *i2o_dev)
-{
- if (drv->notify_device_remove)
- drv->notify_device_remove(i2o_dev);
-};
-
-extern void i2o_driver_notify_controller_add_all(struct i2o_controller *);
-extern void i2o_driver_notify_controller_remove_all(struct i2o_controller *);
-extern void i2o_driver_notify_device_add_all(struct i2o_device *);
-extern void i2o_driver_notify_device_remove_all(struct i2o_device *);
-
-/* I2O device functions */
-extern int i2o_device_claim(struct i2o_device *);
-extern int i2o_device_claim_release(struct i2o_device *);
-
-/* Exec OSM functions */
-extern int i2o_exec_lct_get(struct i2o_controller *);
-
-/* device / driver / kobject conversion functions */
-#define to_i2o_driver(drv) container_of(drv,struct i2o_driver, driver)
-#define to_i2o_device(dev) container_of(dev, struct i2o_device, device)
-#define to_i2o_controller(dev) container_of(dev, struct i2o_controller, device)
-
-/**
- * i2o_out_to_virt - Turn an I2O message to a virtual address
- * @c: controller
- * @m: message engine value
- *
- * Turn a receive message from an I2O controller bus address into
- * a Linux virtual address. The shared page frame is a linear block
- * so we simply have to shift the offset. This function does not
- * work for sender side messages as they are ioremap objects
- * provided by the I2O controller.
- */
-static inline struct i2o_message *i2o_msg_out_to_virt(struct i2o_controller *c,
- u32 m)
-{
- BUG_ON(m < c->out_queue.phys
- || m >= c->out_queue.phys + c->out_queue.len);
-
- return c->out_queue.virt + (m - c->out_queue.phys);
-};
-
-/**
- * i2o_msg_in_to_virt - Turn an I2O message to a virtual address
- * @c: controller
- * @m: message engine value
- *
- * Turn a send message from an I2O controller bus address into
- * a Linux virtual address. The shared page frame is a linear block
- * so we simply have to shift the offset. This function does not
- * work for receive side messages as they are kmalloc objects
- * in a different pool.
- */
-static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct
- i2o_controller *c,
- u32 m)
-{
- return c->in_queue.virt + m;
-};
-
-/**
- * i2o_msg_get - obtain an I2O message from the IOP
- * @c: I2O controller
- *
- * This function tries to get a message frame. If no message frame is
- * available do not wait until one is available (see also i2o_msg_get_wait).
- * The returned pointer to the message frame is not in I/O memory, it is
- * allocated from a mempool. But because a MFA is allocated from the
- * controller too it is guaranteed that i2o_msg_post() will never fail.
- *
- * On a success a pointer to the message frame is returned. If the message
- * queue is empty -EBUSY is returned and if no memory is available -ENOMEM
- * is returned.
- */
-static inline struct i2o_message *i2o_msg_get(struct i2o_controller *c)
-{
- struct i2o_msg_mfa *mmsg = mempool_alloc(c->in_msg.mempool, GFP_ATOMIC);
- if (!mmsg)
- return ERR_PTR(-ENOMEM);
-
- mmsg->mfa = readl(c->in_port);
- if (unlikely(mmsg->mfa >= c->in_queue.len)) {
- u32 mfa = mmsg->mfa;
-
- mempool_free(mmsg, c->in_msg.mempool);
-
- if (mfa == I2O_QUEUE_EMPTY)
- return ERR_PTR(-EBUSY);
- return ERR_PTR(-EFAULT);
- }
-
- return &mmsg->msg;
-};
-
-/**
- * i2o_msg_post - Post I2O message to I2O controller
- * @c: I2O controller to which the message should be send
- * @msg: message returned by i2o_msg_get()
- *
- * Post the message to the I2O controller and return immediately.
- */
-static inline void i2o_msg_post(struct i2o_controller *c,
- struct i2o_message *msg)
-{
- struct i2o_msg_mfa *mmsg;
-
- mmsg = container_of(msg, struct i2o_msg_mfa, msg);
- memcpy_toio(i2o_msg_in_to_virt(c, mmsg->mfa), msg,
- (le32_to_cpu(msg->u.head[0]) >> 16) << 2);
- writel(mmsg->mfa, c->in_port);
- mempool_free(mmsg, c->in_msg.mempool);
-};
-
-/**
- * i2o_msg_post_wait - Post and wait a message and wait until return
- * @c: controller
- * @msg: message to post
- * @timeout: time in seconds to wait
- *
- * This API allows an OSM to post a message and then be told whether or
- * not the system received a successful reply. If the message times out
- * then the value '-ETIMEDOUT' is returned.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static inline int i2o_msg_post_wait(struct i2o_controller *c,
- struct i2o_message *msg,
- unsigned long timeout)
-{
- return i2o_msg_post_wait_mem(c, msg, timeout, NULL);
-};
-
-/**
- * i2o_msg_nop_mfa - Returns a fetched MFA back to the controller
- * @c: I2O controller from which the MFA was fetched
- * @mfa: MFA which should be returned
- *
- * This function must be used for preserved messages, because i2o_msg_nop()
- * also returns the allocated memory back to the msg_pool mempool.
- */
-static inline void i2o_msg_nop_mfa(struct i2o_controller *c, u32 mfa)
-{
- struct i2o_message __iomem *msg;
- u32 nop[3] = {
- THREE_WORD_MSG_SIZE | SGL_OFFSET_0,
- I2O_CMD_UTIL_NOP << 24 | HOST_TID << 12 | ADAPTER_TID,
- 0x00000000
- };
-
- msg = i2o_msg_in_to_virt(c, mfa);
- memcpy_toio(msg, nop, sizeof(nop));
- writel(mfa, c->in_port);
-};
-
-/**
- * i2o_msg_nop - Returns a message which is not used
- * @c: I2O controller from which the message was created
- * @msg: message which should be returned
- *
- * If you fetch a message via i2o_msg_get, and can't use it, you must
- * return the message with this function. Otherwise the MFA is lost as well
- * as the allocated memory from the mempool.
- */
-static inline void i2o_msg_nop(struct i2o_controller *c,
- struct i2o_message *msg)
-{
- struct i2o_msg_mfa *mmsg;
- mmsg = container_of(msg, struct i2o_msg_mfa, msg);
-
- i2o_msg_nop_mfa(c, mmsg->mfa);
- mempool_free(mmsg, c->in_msg.mempool);
-};
-
-/**
- * i2o_flush_reply - Flush reply from I2O controller
- * @c: I2O controller
- * @m: the message identifier
- *
- * The I2O controller must be informed that the reply message is not needed
- * anymore. If you forget to flush the reply, the message frame can't be
- * used by the controller anymore and is therefore lost.
- */
-static inline void i2o_flush_reply(struct i2o_controller *c, u32 m)
-{
- writel(m, c->out_port);
-};
-
-/*
- * Endian handling wrapped into the macro - keeps the core code
- * cleaner.
- */
-
-#define i2o_raw_writel(val, mem) __raw_writel(cpu_to_le32(val), mem)
-
-extern int i2o_parm_field_get(struct i2o_device *, int, int, void *, int);
-extern int i2o_parm_table_get(struct i2o_device *, int, int, int, void *, int,
- void *, int);
-
-/* debugging and troubleshooting/diagnostic helpers. */
-#define osm_printk(level, format, arg...) \
- printk(level "%s: " format, OSM_NAME , ## arg)
-
-#ifdef DEBUG
-#define osm_debug(format, arg...) \
- osm_printk(KERN_DEBUG, format , ## arg)
-#else
-#define osm_debug(format, arg...) \
- do { } while (0)
-#endif
-
-#define osm_err(format, arg...) \
- osm_printk(KERN_ERR, format , ## arg)
-#define osm_info(format, arg...) \
- osm_printk(KERN_INFO, format , ## arg)
-#define osm_warn(format, arg...) \
- osm_printk(KERN_WARNING, format , ## arg)
-
-/* debugging functions */
-extern void i2o_report_status(const char *, const char *, struct i2o_message *);
-extern void i2o_dump_message(struct i2o_message *);
-extern void i2o_dump_hrt(struct i2o_controller *c);
-extern void i2o_debug_state(struct i2o_controller *c);
-
-#endif /* _I2O_H */
+++ /dev/null
-/*
- * Block OSM
- *
- * Copyright (C) 1999-2002 Red Hat Software
- *
- * Written by Alan Cox, Building Number Three Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * For the purpose of avoiding doubt the preferred form of the work
- * for making modifications shall be a standards compliant form such
- * gzipped tar and not one requiring a proprietary or patent encumbered
- * tool to unpack.
- *
- * Fixes/additions:
- * Steve Ralston:
- * Multiple device handling error fixes,
- * Added a queue depth.
- * Alan Cox:
- * FC920 has an rmw bug. Dont or in the end marker.
- * Removed queue walk, fixed for 64bitness.
- * Rewrote much of the code over time
- * Added indirect block lists
- * Handle 64K limits on many controllers
- * Don't use indirects on the Promise (breaks)
- * Heavily chop down the queue depths
- * Deepak Saxena:
- * Independent queues per IOP
- * Support for dynamic device creation/deletion
- * Code cleanup
- * Support for larger I/Os through merge* functions
- * (taken from DAC960 driver)
- * Boji T Kannanthanam:
- * Set the I2O Block devices to be detected in increasing
- * order of TIDs during boot.
- * Search and set the I2O block device that we boot off
- * from as the first device to be claimed (as /dev/i2o/hda)
- * Properly attach/detach I2O gendisk structure from the
- * system gendisk list. The I2O block devices now appear in
- * /proc/partitions.
- * Markus Lidel <Markus.Lidel@shadowconnect.com>:
- * Minor bugfixes for 2.6.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include "i2o.h"
-#include <linux/mutex.h>
-
-#include <linux/mempool.h>
-
-#include <linux/genhd.h>
-#include <linux/blkdev.h>
-#include <linux/hdreg.h>
-
-#include <scsi/scsi.h>
-
-#include "i2o_block.h"
-
-#define OSM_NAME "block-osm"
-#define OSM_VERSION "1.325"
-#define OSM_DESCRIPTION "I2O Block Device OSM"
-
-static DEFINE_MUTEX(i2o_block_mutex);
-static struct i2o_driver i2o_block_driver;
-
-/* global Block OSM request mempool */
-static struct i2o_block_mempool i2o_blk_req_pool;
-
-/* Block OSM class handling definition */
-static struct i2o_class_id i2o_block_class_id[] = {
- {I2O_CLASS_RANDOM_BLOCK_STORAGE},
- {I2O_CLASS_END}
-};
-
-/**
- * i2o_block_device_free - free the memory of the I2O Block device
- * @dev: I2O Block device, which should be cleaned up
- *
- * Frees the request queue, gendisk and the i2o_block_device structure.
- */
-static void i2o_block_device_free(struct i2o_block_device *dev)
-{
- blk_cleanup_queue(dev->gd->queue);
-
- put_disk(dev->gd);
-
- kfree(dev);
-};
-
-/**
- * i2o_block_remove - remove the I2O Block device from the system again
- * @dev: I2O Block device which should be removed
- *
- * Remove gendisk from system and free all allocated memory.
- *
- * Always returns 0.
- */
-static int i2o_block_remove(struct device *dev)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
- struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev);
-
- osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid,
- i2o_blk_dev->gd->disk_name);
-
- i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0);
-
- del_gendisk(i2o_blk_dev->gd);
-
- dev_set_drvdata(dev, NULL);
-
- i2o_device_claim_release(i2o_dev);
-
- i2o_block_device_free(i2o_blk_dev);
-
- return 0;
-};
-
-/**
- * i2o_block_device flush - Flush all dirty data of I2O device dev
- * @dev: I2O device which should be flushed
- *
- * Flushes all dirty data on device dev.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_block_device_flush(struct i2o_device *dev)
-{
- struct i2o_message *msg;
-
- msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->
- lct_data.tid);
- msg->body[0] = cpu_to_le32(60 << 16);
- osm_debug("Flushing...\n");
-
- return i2o_msg_post_wait(dev->iop, msg, 60);
-};
-
-/**
- * i2o_block_device_mount - Mount (load) the media of device dev
- * @dev: I2O device which should receive the mount request
- * @media_id: Media Identifier
- *
- * Load a media into drive. Identifier should be set to -1, because the
- * spec does not support any other value.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id)
-{
- struct i2o_message *msg;
-
- msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->
- lct_data.tid);
- msg->body[0] = cpu_to_le32(-1);
- msg->body[1] = cpu_to_le32(0x00000000);
- osm_debug("Mounting...\n");
-
- return i2o_msg_post_wait(dev->iop, msg, 2);
-};
-
-/**
- * i2o_block_device_lock - Locks the media of device dev
- * @dev: I2O device which should receive the lock request
- * @media_id: Media Identifier
- *
- * Lock media of device dev to prevent removal. The media identifier
- * should be set to -1, because the spec does not support any other value.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id)
-{
- struct i2o_message *msg;
-
- msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->
- lct_data.tid);
- msg->body[0] = cpu_to_le32(-1);
- osm_debug("Locking...\n");
-
- return i2o_msg_post_wait(dev->iop, msg, 2);
-};
-
-/**
- * i2o_block_device_unlock - Unlocks the media of device dev
- * @dev: I2O device which should receive the unlocked request
- * @media_id: Media Identifier
- *
- * Unlocks the media in device dev. The media identifier should be set to
- * -1, because the spec does not support any other value.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id)
-{
- struct i2o_message *msg;
-
- msg = i2o_msg_get_wait(dev->iop, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->
- lct_data.tid);
- msg->body[0] = cpu_to_le32(media_id);
- osm_debug("Unlocking...\n");
-
- return i2o_msg_post_wait(dev->iop, msg, 2);
-};
-
-/**
- * i2o_block_device_power - Power management for device dev
- * @dev: I2O device which should receive the power management request
- * @op: Operation to send
- *
- * Send a power management request to the device dev.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_block_device_power(struct i2o_block_device *dev, u8 op)
-{
- struct i2o_device *i2o_dev = dev->i2o_dev;
- struct i2o_controller *c = i2o_dev->iop;
- struct i2o_message *msg;
- int rc;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->
- lct_data.tid);
- msg->body[0] = cpu_to_le32(op << 24);
- osm_debug("Power...\n");
-
- rc = i2o_msg_post_wait(c, msg, 60);
- if (!rc)
- dev->power = op;
-
- return rc;
-};
-
-/**
- * i2o_block_request_alloc - Allocate an I2O block request struct
- *
- * Allocates an I2O block request struct and initialize the list.
- *
- * Returns a i2o_block_request pointer on success or negative error code
- * on failure.
- */
-static inline struct i2o_block_request *i2o_block_request_alloc(void)
-{
- struct i2o_block_request *ireq;
-
- ireq = mempool_alloc(i2o_blk_req_pool.pool, GFP_ATOMIC);
- if (!ireq)
- return ERR_PTR(-ENOMEM);
-
- INIT_LIST_HEAD(&ireq->queue);
- sg_init_table(ireq->sg_table, I2O_MAX_PHYS_SEGMENTS);
-
- return ireq;
-};
-
-/**
- * i2o_block_request_free - Frees a I2O block request
- * @ireq: I2O block request which should be freed
- *
- * Frees the allocated memory (give it back to the request mempool).
- */
-static inline void i2o_block_request_free(struct i2o_block_request *ireq)
-{
- mempool_free(ireq, i2o_blk_req_pool.pool);
-};
-
-/**
- * i2o_block_sglist_alloc - Allocate the SG list and map it
- * @c: I2O controller to which the request belongs
- * @ireq: I2O block request
- * @mptr: message body pointer
- *
- * Builds the SG list and map it to be accessible by the controller.
- *
- * Returns 0 on failure or 1 on success.
- */
-static inline int i2o_block_sglist_alloc(struct i2o_controller *c,
- struct i2o_block_request *ireq,
- u32 ** mptr)
-{
- int nents;
- enum dma_data_direction direction;
-
- ireq->dev = &c->pdev->dev;
- nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table);
-
- if (rq_data_dir(ireq->req) == READ)
- direction = PCI_DMA_FROMDEVICE;
- else
- direction = PCI_DMA_TODEVICE;
-
- ireq->sg_nents = nents;
-
- return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr);
-};
-
-/**
- * i2o_block_sglist_free - Frees the SG list
- * @ireq: I2O block request from which the SG should be freed
- *
- * Frees the SG list from the I2O block request.
- */
-static inline void i2o_block_sglist_free(struct i2o_block_request *ireq)
-{
- enum dma_data_direction direction;
-
- if (rq_data_dir(ireq->req) == READ)
- direction = PCI_DMA_FROMDEVICE;
- else
- direction = PCI_DMA_TODEVICE;
-
- dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction);
-};
-
-/**
- * i2o_block_prep_req_fn - Allocates I2O block device specific struct
- * @q: request queue for the request
- * @req: the request to prepare
- *
- * Allocate the necessary i2o_block_request struct and connect it to
- * the request. This is needed that we not lose the SG list later on.
- *
- * Returns BLKPREP_OK on success or BLKPREP_DEFER on failure.
- */
-static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req)
-{
- struct i2o_block_device *i2o_blk_dev = q->queuedata;
- struct i2o_block_request *ireq;
-
- if (unlikely(!i2o_blk_dev)) {
- osm_err("block device already removed\n");
- return BLKPREP_KILL;
- }
-
- /* connect the i2o_block_request to the request */
- if (!req->special) {
- ireq = i2o_block_request_alloc();
- if (IS_ERR(ireq)) {
- osm_debug("unable to allocate i2o_block_request!\n");
- return BLKPREP_DEFER;
- }
-
- ireq->i2o_blk_dev = i2o_blk_dev;
- req->special = ireq;
- ireq->req = req;
- }
- /* do not come back here */
- req->cmd_flags |= REQ_DONTPREP;
-
- return BLKPREP_OK;
-};
-
-/**
- * i2o_block_delayed_request_fn - delayed request queue function
- * @work: the delayed request with the queue to start
- *
- * If the request queue is stopped for a disk, and there is no open
- * request, a new event is created, which calls this function to start
- * the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never
- * be started again.
- */
-static void i2o_block_delayed_request_fn(struct work_struct *work)
-{
- struct i2o_block_delayed_request *dreq =
- container_of(work, struct i2o_block_delayed_request,
- work.work);
- struct request_queue *q = dreq->queue;
- unsigned long flags;
-
- spin_lock_irqsave(q->queue_lock, flags);
- blk_start_queue(q);
- spin_unlock_irqrestore(q->queue_lock, flags);
- kfree(dreq);
-};
-
-/**
- * i2o_block_end_request - Post-processing of completed commands
- * @req: request which should be completed
- * @error: 0 for success, < 0 for error
- * @nr_bytes: number of bytes to complete
- *
- * Mark the request as complete. The lock must not be held when entering.
- *
- */
-static void i2o_block_end_request(struct request *req, int error,
- int nr_bytes)
-{
- struct i2o_block_request *ireq = req->special;
- struct i2o_block_device *dev = ireq->i2o_blk_dev;
- struct request_queue *q = req->q;
- unsigned long flags;
-
- if (blk_end_request(req, error, nr_bytes))
- if (error)
- blk_end_request_all(req, -EIO);
-
- spin_lock_irqsave(q->queue_lock, flags);
-
- if (likely(dev)) {
- dev->open_queue_depth--;
- list_del(&ireq->queue);
- }
-
- blk_start_queue(q);
-
- spin_unlock_irqrestore(q->queue_lock, flags);
-
- i2o_block_sglist_free(ireq);
- i2o_block_request_free(ireq);
-};
-
-/**
- * i2o_block_reply - Block OSM reply handler.
- * @c: I2O controller from which the message arrives
- * @m: message id of reply
- * @msg: the actual I2O message reply
- *
- * This function gets all the message replies.
- *
- */
-static int i2o_block_reply(struct i2o_controller *c, u32 m,
- struct i2o_message *msg)
-{
- struct request *req;
- int error = 0;
-
- req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
- if (unlikely(!req)) {
- osm_err("NULL reply received!\n");
- return -1;
- }
-
- /*
- * Lets see what is cooking. We stuffed the
- * request in the context.
- */
-
- if ((le32_to_cpu(msg->body[0]) >> 24) != 0) {
- u32 status = le32_to_cpu(msg->body[0]);
- /*
- * Device not ready means two things. One is that the
- * the thing went offline (but not a removal media)
- *
- * The second is that you have a SuperTrak 100 and the
- * firmware got constipated. Unlike standard i2o card
- * setups the supertrak returns an error rather than
- * blocking for the timeout in these cases.
- *
- * Don't stick a supertrak100 into cache aggressive modes
- */
-
- osm_err("TID %03x error status: 0x%02x, detailed status: "
- "0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff),
- status >> 24, status & 0xffff);
-
- req->errors++;
-
- error = -EIO;
- }
-
- i2o_block_end_request(req, error, le32_to_cpu(msg->body[1]));
-
- return 1;
-};
-
-static void i2o_block_event(struct work_struct *work)
-{
- struct i2o_event *evt = container_of(work, struct i2o_event, work);
- osm_debug("event received\n");
- kfree(evt);
-};
-
-/*
- * SCSI-CAM for ioctl geometry mapping
- * Duplicated with SCSI - this should be moved into somewhere common
- * perhaps genhd ?
- *
- * LBA -> CHS mapping table taken from:
- *
- * "Incorporating the I2O Architecture into BIOS for Intel Architecture
- * Platforms"
- *
- * This is an I2O document that is only available to I2O members,
- * not developers.
- *
- * From my understanding, this is how all the I2O cards do this
- *
- * Disk Size | Sectors | Heads | Cylinders
- * ---------------+---------+-------+-------------------
- * 1 < X <= 528M | 63 | 16 | X/(63 * 16 * 512)
- * 528M < X <= 1G | 63 | 32 | X/(63 * 32 * 512)
- * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512)
- * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512)
- *
- */
-#define BLOCK_SIZE_528M 1081344
-#define BLOCK_SIZE_1G 2097152
-#define BLOCK_SIZE_21G 4403200
-#define BLOCK_SIZE_42G 8806400
-#define BLOCK_SIZE_84G 17612800
-
-static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls,
- unsigned char *hds, unsigned char *secs)
-{
- unsigned long heads, sectors, cylinders;
-
- sectors = 63L; /* Maximize sectors per track */
- if (capacity <= BLOCK_SIZE_528M)
- heads = 16;
- else if (capacity <= BLOCK_SIZE_1G)
- heads = 32;
- else if (capacity <= BLOCK_SIZE_21G)
- heads = 64;
- else if (capacity <= BLOCK_SIZE_42G)
- heads = 128;
- else
- heads = 255;
-
- cylinders = (unsigned long)capacity / (heads * sectors);
-
- *cyls = (unsigned short)cylinders; /* Stuff return values */
- *secs = (unsigned char)sectors;
- *hds = (unsigned char)heads;
-}
-
-/**
- * i2o_block_open - Open the block device
- * @bdev: block device being opened
- * @mode: file open mode
- *
- * Power up the device, mount and lock the media. This function is called,
- * if the block device is opened for access.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_block_open(struct block_device *bdev, fmode_t mode)
-{
- struct i2o_block_device *dev = bdev->bd_disk->private_data;
-
- if (!dev->i2o_dev)
- return -ENODEV;
-
- mutex_lock(&i2o_block_mutex);
- if (dev->power > 0x1f)
- i2o_block_device_power(dev, 0x02);
-
- i2o_block_device_mount(dev->i2o_dev, -1);
-
- i2o_block_device_lock(dev->i2o_dev, -1);
-
- osm_debug("Ready.\n");
- mutex_unlock(&i2o_block_mutex);
-
- return 0;
-};
-
-/**
- * i2o_block_release - Release the I2O block device
- * @disk: gendisk device being released
- * @mode: file open mode
- *
- * Unlock and unmount the media, and power down the device. Gets called if
- * the block device is closed.
- */
-static void i2o_block_release(struct gendisk *disk, fmode_t mode)
-{
- struct i2o_block_device *dev = disk->private_data;
- u8 operation;
-
- /*
- * This is to deal with the case of an application
- * opening a device and then the device disappears while
- * it's in use, and then the application tries to release
- * it. ex: Unmounting a deleted RAID volume at reboot.
- * If we send messages, it will just cause FAILs since
- * the TID no longer exists.
- */
- if (!dev->i2o_dev)
- return;
-
- mutex_lock(&i2o_block_mutex);
- i2o_block_device_flush(dev->i2o_dev);
-
- i2o_block_device_unlock(dev->i2o_dev, -1);
-
- if (dev->flags & (1 << 3 | 1 << 4)) /* Removable */
- operation = 0x21;
- else
- operation = 0x24;
-
- i2o_block_device_power(dev, operation);
- mutex_unlock(&i2o_block_mutex);
-}
-
-static int i2o_block_getgeo(struct block_device *bdev, struct hd_geometry *geo)
-{
- i2o_block_biosparam(get_capacity(bdev->bd_disk),
- &geo->cylinders, &geo->heads, &geo->sectors);
- return 0;
-}
-
-/**
- * i2o_block_ioctl - Issue device specific ioctl calls.
- * @bdev: block device being opened
- * @mode: file open mode
- * @cmd: ioctl command
- * @arg: arg
- *
- * Handles ioctl request for the block device.
- *
- * Return 0 on success or negative error on failure.
- */
-static int i2o_block_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned int cmd, unsigned long arg)
-{
- struct gendisk *disk = bdev->bd_disk;
- struct i2o_block_device *dev = disk->private_data;
- int ret = -ENOTTY;
-
- /* Anyone capable of this syscall can do *real bad* things */
-
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
-
- mutex_lock(&i2o_block_mutex);
- switch (cmd) {
- case BLKI2OGRSTRAT:
- ret = put_user(dev->rcache, (int __user *)arg);
- break;
- case BLKI2OGWSTRAT:
- ret = put_user(dev->wcache, (int __user *)arg);
- break;
- case BLKI2OSRSTRAT:
- ret = -EINVAL;
- if (arg < 0 || arg > CACHE_SMARTFETCH)
- break;
- dev->rcache = arg;
- ret = 0;
- break;
- case BLKI2OSWSTRAT:
- ret = -EINVAL;
- if (arg != 0
- && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK))
- break;
- dev->wcache = arg;
- ret = 0;
- break;
- }
- mutex_unlock(&i2o_block_mutex);
-
- return ret;
-};
-
-/**
- * i2o_block_check_events - Have we seen a media change?
- * @disk: gendisk which should be verified
- * @clearing: events being cleared
- *
- * Verifies if the media has changed.
- *
- * Returns 1 if the media was changed or 0 otherwise.
- */
-static unsigned int i2o_block_check_events(struct gendisk *disk,
- unsigned int clearing)
-{
- struct i2o_block_device *p = disk->private_data;
-
- if (p->media_change_flag) {
- p->media_change_flag = 0;
- return DISK_EVENT_MEDIA_CHANGE;
- }
- return 0;
-}
-
-/**
- * i2o_block_transfer - Transfer a request to/from the I2O controller
- * @req: the request which should be transferred
- *
- * This function converts the request into a I2O message. The necessary
- * DMA buffers are allocated and after everything is setup post the message
- * to the I2O controller. No cleanup is done by this function. It is done
- * on the interrupt side when the reply arrives.
- *
- * Return 0 on success or negative error code on failure.
- */
-static int i2o_block_transfer(struct request *req)
-{
- struct i2o_block_device *dev = req->rq_disk->private_data;
- struct i2o_controller *c;
- u32 tid;
- struct i2o_message *msg;
- u32 *mptr;
- struct i2o_block_request *ireq = req->special;
- u32 tcntxt;
- u32 sgl_offset = SGL_OFFSET_8;
- u32 ctl_flags = 0x00000000;
- int rc;
- u32 cmd;
-
- if (unlikely(!dev->i2o_dev)) {
- osm_err("transfer to removed drive\n");
- rc = -ENODEV;
- goto exit;
- }
-
- tid = dev->i2o_dev->lct_data.tid;
- c = dev->i2o_dev->iop;
-
- msg = i2o_msg_get(c);
- if (IS_ERR(msg)) {
- rc = PTR_ERR(msg);
- goto exit;
- }
-
- tcntxt = i2o_cntxt_list_add(c, req);
- if (!tcntxt) {
- rc = -ENOMEM;
- goto nop_msg;
- }
-
- msg->u.s.icntxt = cpu_to_le32(i2o_block_driver.context);
- msg->u.s.tcntxt = cpu_to_le32(tcntxt);
-
- mptr = &msg->body[0];
-
- if (rq_data_dir(req) == READ) {
- cmd = I2O_CMD_BLOCK_READ << 24;
-
- switch (dev->rcache) {
- case CACHE_PREFETCH:
- ctl_flags = 0x201F0008;
- break;
-
- case CACHE_SMARTFETCH:
- if (blk_rq_sectors(req) > 16)
- ctl_flags = 0x201F0008;
- else
- ctl_flags = 0x001F0000;
- break;
-
- default:
- break;
- }
- } else {
- cmd = I2O_CMD_BLOCK_WRITE << 24;
-
- switch (dev->wcache) {
- case CACHE_WRITETHROUGH:
- ctl_flags = 0x001F0008;
- break;
- case CACHE_WRITEBACK:
- ctl_flags = 0x001F0010;
- break;
- case CACHE_SMARTBACK:
- if (blk_rq_sectors(req) > 16)
- ctl_flags = 0x001F0004;
- else
- ctl_flags = 0x001F0010;
- break;
- case CACHE_SMARTTHROUGH:
- if (blk_rq_sectors(req) > 16)
- ctl_flags = 0x001F0004;
- else
- ctl_flags = 0x001F0010;
- default:
- break;
- }
- }
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- u8 cmd[10];
- u32 scsi_flags;
- u16 hwsec;
-
- hwsec = queue_logical_block_size(req->q) >> KERNEL_SECTOR_SHIFT;
- memset(cmd, 0, 10);
-
- sgl_offset = SGL_OFFSET_12;
-
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_PRIVATE << 24 | HOST_TID << 12 | tid);
-
- *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC);
- *mptr++ = cpu_to_le32(tid);
-
- /*
- * ENABLE_DISCONNECT
- * SIMPLE_TAG
- * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
- */
- if (rq_data_dir(req) == READ) {
- cmd[0] = READ_10;
- scsi_flags = 0x60a0000a;
- } else {
- cmd[0] = WRITE_10;
- scsi_flags = 0xa0a0000a;
- }
-
- *mptr++ = cpu_to_le32(scsi_flags);
-
- *((u32 *) & cmd[2]) = cpu_to_be32(blk_rq_pos(req) * hwsec);
- *((u16 *) & cmd[7]) = cpu_to_be16(blk_rq_sectors(req) * hwsec);
-
- memcpy(mptr, cmd, 10);
- mptr += 4;
- *mptr++ = cpu_to_le32(blk_rq_bytes(req));
- } else
-#endif
- {
- msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
- *mptr++ = cpu_to_le32(ctl_flags);
- *mptr++ = cpu_to_le32(blk_rq_bytes(req));
- *mptr++ =
- cpu_to_le32((u32) (blk_rq_pos(req) << KERNEL_SECTOR_SHIFT));
- *mptr++ =
- cpu_to_le32(blk_rq_pos(req) >> (32 - KERNEL_SECTOR_SHIFT));
- }
-
- if (!i2o_block_sglist_alloc(c, ireq, &mptr)) {
- rc = -ENOMEM;
- goto context_remove;
- }
-
- msg->u.head[0] =
- cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset);
-
- list_add_tail(&ireq->queue, &dev->open_queue);
- dev->open_queue_depth++;
-
- i2o_msg_post(c, msg);
-
- return 0;
-
-context_remove:
- i2o_cntxt_list_remove(c, req);
-
-nop_msg:
- i2o_msg_nop(c, msg);
-
-exit:
- return rc;
-};
-
-/**
- * i2o_block_request_fn - request queue handling function
- * @q: request queue from which the request could be fetched
- *
- * Takes the next request from the queue, transfers it and if no error
- * occurs dequeue it from the queue. On arrival of the reply the message
- * will be processed further. If an error occurs requeue the request.
- */
-static void i2o_block_request_fn(struct request_queue *q)
-{
- struct request *req;
-
- while ((req = blk_peek_request(q)) != NULL) {
- if (req->cmd_type == REQ_TYPE_FS) {
- struct i2o_block_delayed_request *dreq;
- struct i2o_block_request *ireq = req->special;
- unsigned int queue_depth;
-
- queue_depth = ireq->i2o_blk_dev->open_queue_depth;
-
- if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) {
- if (!i2o_block_transfer(req)) {
- blk_start_request(req);
- continue;
- } else
- osm_info("transfer error\n");
- }
-
- if (queue_depth)
- break;
-
- /* stop the queue and retry later */
- dreq = kmalloc(sizeof(*dreq), GFP_ATOMIC);
- if (!dreq)
- continue;
-
- dreq->queue = q;
- INIT_DELAYED_WORK(&dreq->work,
- i2o_block_delayed_request_fn);
-
- if (!queue_delayed_work(i2o_block_driver.event_queue,
- &dreq->work,
- I2O_BLOCK_RETRY_TIME))
- kfree(dreq);
- else {
- blk_stop_queue(q);
- break;
- }
- } else {
- blk_start_request(req);
- __blk_end_request_all(req, -EIO);
- }
- }
-};
-
-/* I2O Block device operations definition */
-static const struct block_device_operations i2o_block_fops = {
- .owner = THIS_MODULE,
- .open = i2o_block_open,
- .release = i2o_block_release,
- .ioctl = i2o_block_ioctl,
- .compat_ioctl = i2o_block_ioctl,
- .getgeo = i2o_block_getgeo,
- .check_events = i2o_block_check_events,
-};
-
-/**
- * i2o_block_device_alloc - Allocate memory for a I2O Block device
- *
- * Allocate memory for the i2o_block_device struct, gendisk and request
- * queue and initialize them as far as no additional information is needed.
- *
- * Returns a pointer to the allocated I2O Block device on success or a
- * negative error code on failure.
- */
-static struct i2o_block_device *i2o_block_device_alloc(void)
-{
- struct i2o_block_device *dev;
- struct gendisk *gd;
- struct request_queue *queue;
- int rc;
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) {
- osm_err("Insufficient memory to allocate I2O Block disk.\n");
- rc = -ENOMEM;
- goto exit;
- }
-
- INIT_LIST_HEAD(&dev->open_queue);
- spin_lock_init(&dev->lock);
- dev->rcache = CACHE_PREFETCH;
- dev->wcache = CACHE_WRITEBACK;
-
- /* allocate a gendisk with 16 partitions */
- gd = alloc_disk(16);
- if (!gd) {
- osm_err("Insufficient memory to allocate gendisk.\n");
- rc = -ENOMEM;
- goto cleanup_dev;
- }
-
- /* initialize the request queue */
- queue = blk_init_queue(i2o_block_request_fn, &dev->lock);
- if (!queue) {
- osm_err("Insufficient memory to allocate request queue.\n");
- rc = -ENOMEM;
- goto cleanup_queue;
- }
-
- blk_queue_prep_rq(queue, i2o_block_prep_req_fn);
-
- gd->major = I2O_MAJOR;
- gd->queue = queue;
- gd->fops = &i2o_block_fops;
- gd->private_data = dev;
-
- dev->gd = gd;
-
- return dev;
-
-cleanup_queue:
- put_disk(gd);
-
-cleanup_dev:
- kfree(dev);
-
-exit:
- return ERR_PTR(rc);
-};
-
-/**
- * i2o_block_probe - verify if dev is a I2O Block device and install it
- * @dev: device to verify if it is a I2O Block device
- *
- * We only verify if the user_tid of the device is 0xfff and then install
- * the device. Otherwise it is used by some other device (e. g. RAID).
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_block_probe(struct device *dev)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
- struct i2o_controller *c = i2o_dev->iop;
- struct i2o_block_device *i2o_blk_dev;
- struct gendisk *gd;
- struct request_queue *queue;
- static int unit;
- int rc;
- u64 size;
- u32 blocksize;
- u16 body_size = 4;
- u16 power;
- unsigned short max_sectors;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec)
- body_size = 8;
-#endif
-
- if (c->limit_sectors)
- max_sectors = I2O_MAX_SECTORS_LIMITED;
- else
- max_sectors = I2O_MAX_SECTORS;
-
- /* skip devices which are used by IOP */
- if (i2o_dev->lct_data.user_tid != 0xfff) {
- osm_debug("skipping used device %03x\n", i2o_dev->lct_data.tid);
- return -ENODEV;
- }
-
- if (i2o_device_claim(i2o_dev)) {
- osm_warn("Unable to claim device. Installation aborted\n");
- rc = -EFAULT;
- goto exit;
- }
-
- i2o_blk_dev = i2o_block_device_alloc();
- if (IS_ERR(i2o_blk_dev)) {
- osm_err("could not alloc a new I2O block device");
- rc = PTR_ERR(i2o_blk_dev);
- goto claim_release;
- }
-
- i2o_blk_dev->i2o_dev = i2o_dev;
- dev_set_drvdata(dev, i2o_blk_dev);
-
- /* setup gendisk */
- gd = i2o_blk_dev->gd;
- gd->first_minor = unit << 4;
- sprintf(gd->disk_name, "i2o/hd%c", 'a' + unit);
- gd->driverfs_dev = &i2o_dev->device;
-
- /* setup request queue */
- queue = gd->queue;
- queue->queuedata = i2o_blk_dev;
-
- blk_queue_max_hw_sectors(queue, max_sectors);
- blk_queue_max_segments(queue, i2o_sg_tablesize(c, body_size));
-
- osm_debug("max sectors = %d\n", queue->max_sectors);
- osm_debug("phys segments = %d\n", queue->max_phys_segments);
- osm_debug("max hw segments = %d\n", queue->max_hw_segments);
-
- /*
- * Ask for the current media data. If that isn't supported
- * then we ask for the device capacity data
- */
- if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) ||
- !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) {
- blk_queue_logical_block_size(queue, le32_to_cpu(blocksize));
- } else
- osm_warn("unable to get blocksize of %s\n", gd->disk_name);
-
- if (!i2o_parm_field_get(i2o_dev, 0x0004, 0, &size, 8) ||
- !i2o_parm_field_get(i2o_dev, 0x0000, 4, &size, 8)) {
- set_capacity(gd, le64_to_cpu(size) >> KERNEL_SECTOR_SHIFT);
- } else
- osm_warn("could not get size of %s\n", gd->disk_name);
-
- if (!i2o_parm_field_get(i2o_dev, 0x0000, 2, &power, 2))
- i2o_blk_dev->power = power;
-
- i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0xffffffff);
-
- add_disk(gd);
-
- unit++;
-
- osm_info("device added (TID: %03x): %s\n", i2o_dev->lct_data.tid,
- i2o_blk_dev->gd->disk_name);
-
- return 0;
-
-claim_release:
- i2o_device_claim_release(i2o_dev);
-
-exit:
- return rc;
-};
-
-/* Block OSM driver struct */
-static struct i2o_driver i2o_block_driver = {
- .name = OSM_NAME,
- .event = i2o_block_event,
- .reply = i2o_block_reply,
- .classes = i2o_block_class_id,
- .driver = {
- .probe = i2o_block_probe,
- .remove = i2o_block_remove,
- },
-};
-
-/**
- * i2o_block_init - Block OSM initialization function
- *
- * Allocate the slab and mempool for request structs, registers i2o_block
- * block device and finally register the Block OSM in the I2O core.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int __init i2o_block_init(void)
-{
- int rc;
- int size;
-
- printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
-
- /* Allocate request mempool and slab */
- size = sizeof(struct i2o_block_request);
- i2o_blk_req_pool.slab = kmem_cache_create("i2o_block_req", size, 0,
- SLAB_HWCACHE_ALIGN, NULL);
- if (!i2o_blk_req_pool.slab) {
- osm_err("can't init request slab\n");
- rc = -ENOMEM;
- goto exit;
- }
-
- i2o_blk_req_pool.pool =
- mempool_create_slab_pool(I2O_BLOCK_REQ_MEMPOOL_SIZE,
- i2o_blk_req_pool.slab);
- if (!i2o_blk_req_pool.pool) {
- osm_err("can't init request mempool\n");
- rc = -ENOMEM;
- goto free_slab;
- }
-
- /* Register the block device interfaces */
- rc = register_blkdev(I2O_MAJOR, "i2o_block");
- if (rc) {
- osm_err("unable to register block device\n");
- goto free_mempool;
- }
-#ifdef MODULE
- osm_info("registered device at major %d\n", I2O_MAJOR);
-#endif
-
- /* Register Block OSM into I2O core */
- rc = i2o_driver_register(&i2o_block_driver);
- if (rc) {
- osm_err("Could not register Block driver\n");
- goto unregister_blkdev;
- }
-
- return 0;
-
-unregister_blkdev:
- unregister_blkdev(I2O_MAJOR, "i2o_block");
-
-free_mempool:
- mempool_destroy(i2o_blk_req_pool.pool);
-
-free_slab:
- kmem_cache_destroy(i2o_blk_req_pool.slab);
-
-exit:
- return rc;
-};
-
-/**
- * i2o_block_exit - Block OSM exit function
- *
- * Unregisters Block OSM from I2O core, unregisters i2o_block block device
- * and frees the mempool and slab.
- */
-static void __exit i2o_block_exit(void)
-{
- /* Unregister I2O Block OSM from I2O core */
- i2o_driver_unregister(&i2o_block_driver);
-
- /* Unregister block device */
- unregister_blkdev(I2O_MAJOR, "i2o_block");
-
- /* Free request mempool and slab */
- mempool_destroy(i2o_blk_req_pool.pool);
- kmem_cache_destroy(i2o_blk_req_pool.slab);
-};
-
-MODULE_AUTHOR("Red Hat");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(OSM_DESCRIPTION);
-MODULE_VERSION(OSM_VERSION);
-
-module_init(i2o_block_init);
-module_exit(i2o_block_exit);
+++ /dev/null
-/*
- * Block OSM structures/API
- *
- * Copyright (C) 1999-2002 Red Hat Software
- *
- * Written by Alan Cox, Building Number Three Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * For the purpose of avoiding doubt the preferred form of the work
- * for making modifications shall be a standards compliant form such
- * gzipped tar and not one requiring a proprietary or patent encumbered
- * tool to unpack.
- *
- * Fixes/additions:
- * Steve Ralston:
- * Multiple device handling error fixes,
- * Added a queue depth.
- * Alan Cox:
- * FC920 has an rmw bug. Dont or in the end marker.
- * Removed queue walk, fixed for 64bitness.
- * Rewrote much of the code over time
- * Added indirect block lists
- * Handle 64K limits on many controllers
- * Don't use indirects on the Promise (breaks)
- * Heavily chop down the queue depths
- * Deepak Saxena:
- * Independent queues per IOP
- * Support for dynamic device creation/deletion
- * Code cleanup
- * Support for larger I/Os through merge* functions
- * (taken from DAC960 driver)
- * Boji T Kannanthanam:
- * Set the I2O Block devices to be detected in increasing
- * order of TIDs during boot.
- * Search and set the I2O block device that we boot off
- * from as the first device to be claimed (as /dev/i2o/hda)
- * Properly attach/detach I2O gendisk structure from the
- * system gendisk list. The I2O block devices now appear in
- * /proc/partitions.
- * Markus Lidel <Markus.Lidel@shadowconnect.com>:
- * Minor bugfixes for 2.6.
- */
-
-#ifndef I2O_BLOCK_OSM_H
-#define I2O_BLOCK_OSM_H
-
-#define I2O_BLOCK_RETRY_TIME HZ/4
-#define I2O_BLOCK_MAX_OPEN_REQUESTS 50
-
-/* request queue sizes */
-#define I2O_BLOCK_REQ_MEMPOOL_SIZE 32
-
-#define KERNEL_SECTOR_SHIFT 9
-#define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT)
-
-/* I2O Block OSM mempool struct */
-struct i2o_block_mempool {
- struct kmem_cache *slab;
- mempool_t *pool;
-};
-
-/* I2O Block device descriptor */
-struct i2o_block_device {
- struct i2o_device *i2o_dev; /* pointer to I2O device */
- struct gendisk *gd;
- spinlock_t lock; /* queue lock */
- struct list_head open_queue; /* list of transferred, but unfinished
- requests */
- unsigned int open_queue_depth; /* number of requests in the queue */
-
- int rcache; /* read cache flags */
- int wcache; /* write cache flags */
- int flags;
- u16 power; /* power state */
- int media_change_flag; /* media changed flag */
-};
-
-/* I2O Block device request */
-struct i2o_block_request {
- struct list_head queue;
- struct request *req; /* corresponding request */
- struct i2o_block_device *i2o_blk_dev; /* I2O block device */
- struct device *dev; /* device used for DMA */
- int sg_nents; /* number of SG elements */
- struct scatterlist sg_table[I2O_MAX_PHYS_SEGMENTS]; /* SG table */
-};
-
-/* I2O Block device delayed request */
-struct i2o_block_delayed_request {
- struct delayed_work work;
- struct request_queue *queue;
-};
-
-#endif
+++ /dev/null
-/*
- * I2O Configuration Interface Driver
- *
- * (C) Copyright 1999-2002 Red Hat
- *
- * Written by Alan Cox, Building Number Three Ltd
- *
- * Fixes/additions:
- * Deepak Saxena (04/20/1999):
- * Added basic ioctl() support
- * Deepak Saxena (06/07/1999):
- * Added software download ioctl (still testing)
- * Auvo Häkkinen (09/10/1999):
- * Changes to i2o_cfg_reply(), ioctl_parms()
- * Added ioct_validate()
- * Taneli Vähäkangas (09/30/1999):
- * Fixed ioctl_swdl()
- * Taneli Vähäkangas (10/04/1999):
- * Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel()
- * Deepak Saxena (11/18/1999):
- * Added event managmenet support
- * Alan Cox <alan@lxorguk.ukuu.org.uk>:
- * 2.4 rewrite ported to 2.5
- * Markus Lidel <Markus.Lidel@shadowconnect.com>:
- * Added pass-thru support for Adaptec's raidutils
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/miscdevice.h>
-#include <linux/mutex.h>
-#include <linux/compat.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include "core.h"
-
-#define SG_TABLESIZE 30
-
-static DEFINE_MUTEX(i2o_cfg_mutex);
-static long i2o_cfg_ioctl(struct file *, unsigned int, unsigned long);
-
-static spinlock_t i2o_config_lock;
-
-#define MODINC(x,y) ((x) = ((x) + 1) % (y))
-
-struct sg_simple_element {
- u32 flag_count;
- u32 addr_bus;
-};
-
-struct i2o_cfg_info {
- struct file *fp;
- struct fasync_struct *fasync;
- struct i2o_evt_info event_q[I2O_EVT_Q_LEN];
- u16 q_in; // Queue head index
- u16 q_out; // Queue tail index
- u16 q_len; // Queue length
- u16 q_lost; // Number of lost events
- ulong q_id; // Event queue ID...used as tx_context
- struct i2o_cfg_info *next;
-};
-static struct i2o_cfg_info *open_files = NULL;
-static ulong i2o_cfg_info_id;
-
-static int i2o_cfg_getiops(unsigned long arg)
-{
- struct i2o_controller *c;
- u8 __user *user_iop_table = (void __user *)arg;
- u8 tmp[MAX_I2O_CONTROLLERS];
- int ret = 0;
-
- memset(tmp, 0, MAX_I2O_CONTROLLERS);
-
- list_for_each_entry(c, &i2o_controllers, list)
- tmp[c->unit] = 1;
-
- if (copy_to_user(user_iop_table, tmp, MAX_I2O_CONTROLLERS))
- ret = -EFAULT;
-
- return ret;
-};
-
-static int i2o_cfg_gethrt(unsigned long arg)
-{
- struct i2o_controller *c;
- struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg;
- struct i2o_cmd_hrtlct kcmd;
- i2o_hrt *hrt;
- int len;
- u32 reslen;
- int ret = 0;
-
- if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
- return -EFAULT;
-
- if (get_user(reslen, kcmd.reslen) < 0)
- return -EFAULT;
-
- if (kcmd.resbuf == NULL)
- return -EFAULT;
-
- c = i2o_find_iop(kcmd.iop);
- if (!c)
- return -ENXIO;
-
- hrt = (i2o_hrt *) c->hrt.virt;
-
- len = 8 + ((hrt->entry_len * hrt->num_entries) << 2);
-
- if (put_user(len, kcmd.reslen))
- ret = -EFAULT;
- else if (len > reslen)
- ret = -ENOBUFS;
- else if (copy_to_user(kcmd.resbuf, (void *)hrt, len))
- ret = -EFAULT;
-
- return ret;
-};
-
-static int i2o_cfg_getlct(unsigned long arg)
-{
- struct i2o_controller *c;
- struct i2o_cmd_hrtlct __user *cmd = (struct i2o_cmd_hrtlct __user *)arg;
- struct i2o_cmd_hrtlct kcmd;
- i2o_lct *lct;
- int len;
- int ret = 0;
- u32 reslen;
-
- if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_hrtlct)))
- return -EFAULT;
-
- if (get_user(reslen, kcmd.reslen) < 0)
- return -EFAULT;
-
- if (kcmd.resbuf == NULL)
- return -EFAULT;
-
- c = i2o_find_iop(kcmd.iop);
- if (!c)
- return -ENXIO;
-
- lct = (i2o_lct *) c->lct;
-
- len = (unsigned int)lct->table_size << 2;
- if (put_user(len, kcmd.reslen))
- ret = -EFAULT;
- else if (len > reslen)
- ret = -ENOBUFS;
- else if (copy_to_user(kcmd.resbuf, lct, len))
- ret = -EFAULT;
-
- return ret;
-};
-
-static int i2o_cfg_parms(unsigned long arg, unsigned int type)
-{
- int ret = 0;
- struct i2o_controller *c;
- struct i2o_device *dev;
- struct i2o_cmd_psetget __user *cmd =
- (struct i2o_cmd_psetget __user *)arg;
- struct i2o_cmd_psetget kcmd;
- u32 reslen;
- u8 *ops;
- u8 *res;
- int len = 0;
-
- u32 i2o_cmd = (type == I2OPARMGET ?
- I2O_CMD_UTIL_PARAMS_GET : I2O_CMD_UTIL_PARAMS_SET);
-
- if (copy_from_user(&kcmd, cmd, sizeof(struct i2o_cmd_psetget)))
- return -EFAULT;
-
- if (get_user(reslen, kcmd.reslen))
- return -EFAULT;
-
- c = i2o_find_iop(kcmd.iop);
- if (!c)
- return -ENXIO;
-
- dev = i2o_iop_find_device(c, kcmd.tid);
- if (!dev)
- return -ENXIO;
-
- /*
- * Stop users being able to try and allocate arbitrary amounts
- * of DMA space. 64K is way more than sufficient for this.
- */
- if (kcmd.oplen > 65536)
- return -EMSGSIZE;
-
- ops = memdup_user(kcmd.opbuf, kcmd.oplen);
- if (IS_ERR(ops))
- return PTR_ERR(ops);
-
- /*
- * It's possible to have a _very_ large table
- * and that the user asks for all of it at once...
- */
- res = kmalloc(65536, GFP_KERNEL);
- if (!res) {
- kfree(ops);
- return -ENOMEM;
- }
-
- len = i2o_parm_issue(dev, i2o_cmd, ops, kcmd.oplen, res, 65536);
- kfree(ops);
-
- if (len < 0) {
- kfree(res);
- return -EAGAIN;
- }
-
- if (put_user(len, kcmd.reslen))
- ret = -EFAULT;
- else if (len > reslen)
- ret = -ENOBUFS;
- else if (copy_to_user(kcmd.resbuf, res, len))
- ret = -EFAULT;
-
- kfree(res);
-
- return ret;
-};
-
-static int i2o_cfg_swdl(unsigned long arg)
-{
- struct i2o_sw_xfer kxfer;
- struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
- unsigned char maxfrag = 0, curfrag = 1;
- struct i2o_dma buffer;
- struct i2o_message *msg;
- unsigned int status = 0, swlen = 0, fragsize = 8192;
- struct i2o_controller *c;
-
- if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
- return -EFAULT;
-
- if (get_user(swlen, kxfer.swlen) < 0)
- return -EFAULT;
-
- if (get_user(maxfrag, kxfer.maxfrag) < 0)
- return -EFAULT;
-
- if (get_user(curfrag, kxfer.curfrag) < 0)
- return -EFAULT;
-
- if (curfrag == maxfrag)
- fragsize = swlen - (maxfrag - 1) * 8192;
-
- if (!kxfer.buf || !access_ok(VERIFY_READ, kxfer.buf, fragsize))
- return -EFAULT;
-
- c = i2o_find_iop(kxfer.iop);
- if (!c)
- return -ENXIO;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) {
- i2o_msg_nop(c, msg);
- return -ENOMEM;
- }
-
- if (__copy_from_user(buffer.virt, kxfer.buf, fragsize)) {
- i2o_msg_nop(c, msg);
- i2o_dma_free(&c->pdev->dev, &buffer);
- return -EFAULT;
- }
-
- msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_SW_DOWNLOAD << 24 | HOST_TID << 12 |
- ADAPTER_TID);
- msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
- msg->u.head[3] = cpu_to_le32(0);
- msg->body[0] =
- cpu_to_le32((((u32) kxfer.flags) << 24) | (((u32) kxfer.
- sw_type) << 16) |
- (((u32) maxfrag) << 8) | (((u32) curfrag)));
- msg->body[1] = cpu_to_le32(swlen);
- msg->body[2] = cpu_to_le32(kxfer.sw_id);
- msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
- msg->body[4] = cpu_to_le32(buffer.phys);
-
- osm_debug("swdl frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
- status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
-
- if (status != -ETIMEDOUT)
- i2o_dma_free(&c->pdev->dev, &buffer);
-
- if (status != I2O_POST_WAIT_OK) {
- // it fails if you try and send frags out of order
- // and for some yet unknown reasons too
- osm_info("swdl failed, DetailedStatus = %d\n", status);
- return status;
- }
-
- return 0;
-};
-
-static int i2o_cfg_swul(unsigned long arg)
-{
- struct i2o_sw_xfer kxfer;
- struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
- unsigned char maxfrag = 0, curfrag = 1;
- struct i2o_dma buffer;
- struct i2o_message *msg;
- unsigned int status = 0, swlen = 0, fragsize = 8192;
- struct i2o_controller *c;
- int ret = 0;
-
- if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
- return -EFAULT;
-
- if (get_user(swlen, kxfer.swlen) < 0)
- return -EFAULT;
-
- if (get_user(maxfrag, kxfer.maxfrag) < 0)
- return -EFAULT;
-
- if (get_user(curfrag, kxfer.curfrag) < 0)
- return -EFAULT;
-
- if (curfrag == maxfrag)
- fragsize = swlen - (maxfrag - 1) * 8192;
-
- if (!kxfer.buf)
- return -EFAULT;
-
- c = i2o_find_iop(kxfer.iop);
- if (!c)
- return -ENXIO;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- if (i2o_dma_alloc(&c->pdev->dev, &buffer, fragsize)) {
- i2o_msg_nop(c, msg);
- return -ENOMEM;
- }
-
- msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_7);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_SW_UPLOAD << 24 | HOST_TID << 12 | ADAPTER_TID);
- msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
- msg->u.head[3] = cpu_to_le32(0);
- msg->body[0] =
- cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.
- sw_type << 16 | (u32) maxfrag << 8 | (u32) curfrag);
- msg->body[1] = cpu_to_le32(swlen);
- msg->body[2] = cpu_to_le32(kxfer.sw_id);
- msg->body[3] = cpu_to_le32(0xD0000000 | fragsize);
- msg->body[4] = cpu_to_le32(buffer.phys);
-
- osm_debug("swul frag %d/%d (size %d)\n", curfrag, maxfrag, fragsize);
- status = i2o_msg_post_wait_mem(c, msg, 60, &buffer);
-
- if (status != I2O_POST_WAIT_OK) {
- if (status != -ETIMEDOUT)
- i2o_dma_free(&c->pdev->dev, &buffer);
-
- osm_info("swul failed, DetailedStatus = %d\n", status);
- return status;
- }
-
- if (copy_to_user(kxfer.buf, buffer.virt, fragsize))
- ret = -EFAULT;
-
- i2o_dma_free(&c->pdev->dev, &buffer);
-
- return ret;
-}
-
-static int i2o_cfg_swdel(unsigned long arg)
-{
- struct i2o_controller *c;
- struct i2o_sw_xfer kxfer;
- struct i2o_sw_xfer __user *pxfer = (struct i2o_sw_xfer __user *)arg;
- struct i2o_message *msg;
- unsigned int swlen;
- int token;
-
- if (copy_from_user(&kxfer, pxfer, sizeof(struct i2o_sw_xfer)))
- return -EFAULT;
-
- if (get_user(swlen, kxfer.swlen) < 0)
- return -EFAULT;
-
- c = i2o_find_iop(kxfer.iop);
- if (!c)
- return -ENXIO;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_SW_REMOVE << 24 | HOST_TID << 12 | ADAPTER_TID);
- msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
- msg->u.head[3] = cpu_to_le32(0);
- msg->body[0] =
- cpu_to_le32((u32) kxfer.flags << 24 | (u32) kxfer.sw_type << 16);
- msg->body[1] = cpu_to_le32(swlen);
- msg->body[2] = cpu_to_le32(kxfer.sw_id);
-
- token = i2o_msg_post_wait(c, msg, 10);
-
- if (token != I2O_POST_WAIT_OK) {
- osm_info("swdel failed, DetailedStatus = %d\n", token);
- return -ETIMEDOUT;
- }
-
- return 0;
-};
-
-static int i2o_cfg_validate(unsigned long arg)
-{
- int token;
- int iop = (int)arg;
- struct i2o_message *msg;
- struct i2o_controller *c;
-
- c = i2o_find_iop(iop);
- if (!c)
- return -ENXIO;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_CONFIG_VALIDATE << 24 | HOST_TID << 12 | iop);
- msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
- msg->u.head[3] = cpu_to_le32(0);
-
- token = i2o_msg_post_wait(c, msg, 10);
-
- if (token != I2O_POST_WAIT_OK) {
- osm_info("Can't validate configuration, ErrorStatus = %d\n",
- token);
- return -ETIMEDOUT;
- }
-
- return 0;
-};
-
-static int i2o_cfg_evt_reg(unsigned long arg, struct file *fp)
-{
- struct i2o_message *msg;
- struct i2o_evt_id __user *pdesc = (struct i2o_evt_id __user *)arg;
- struct i2o_evt_id kdesc;
- struct i2o_controller *c;
- struct i2o_device *d;
-
- if (copy_from_user(&kdesc, pdesc, sizeof(struct i2o_evt_id)))
- return -EFAULT;
-
- /* IOP exists? */
- c = i2o_find_iop(kdesc.iop);
- if (!c)
- return -ENXIO;
-
- /* Device exists? */
- d = i2o_iop_find_device(c, kdesc.tid);
- if (!d)
- return -ENODEV;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 |
- kdesc.tid);
- msg->u.head[2] = cpu_to_le32(i2o_config_driver.context);
- msg->u.head[3] = cpu_to_le32(i2o_cntxt_list_add(c, fp->private_data));
- msg->body[0] = cpu_to_le32(kdesc.evt_mask);
-
- i2o_msg_post(c, msg);
-
- return 0;
-}
-
-static int i2o_cfg_evt_get(unsigned long arg, struct file *fp)
-{
- struct i2o_cfg_info *p = NULL;
- struct i2o_evt_get __user *uget = (struct i2o_evt_get __user *)arg;
- struct i2o_evt_get kget;
- unsigned long flags;
-
- for (p = open_files; p; p = p->next)
- if (p->q_id == (ulong) fp->private_data)
- break;
-
- if (!p->q_len)
- return -ENOENT;
-
- memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info));
- MODINC(p->q_out, I2O_EVT_Q_LEN);
- spin_lock_irqsave(&i2o_config_lock, flags);
- p->q_len--;
- kget.pending = p->q_len;
- kget.lost = p->q_lost;
- spin_unlock_irqrestore(&i2o_config_lock, flags);
-
- if (copy_to_user(uget, &kget, sizeof(struct i2o_evt_get)))
- return -EFAULT;
- return 0;
-}
-
-#ifdef CONFIG_COMPAT
-static int i2o_cfg_passthru32(struct file *file, unsigned cmnd,
- unsigned long arg)
-{
- struct i2o_cmd_passthru32 __user *cmd;
- struct i2o_controller *c;
- u32 __user *user_msg;
- u32 *reply = NULL;
- u32 __user *user_reply = NULL;
- u32 size = 0;
- u32 reply_size = 0;
- u32 rcode = 0;
- struct i2o_dma sg_list[SG_TABLESIZE];
- u32 sg_offset = 0;
- u32 sg_count = 0;
- u32 i = 0;
- u32 sg_index = 0;
- i2o_status_block *sb;
- struct i2o_message *msg;
- unsigned int iop;
-
- cmd = (struct i2o_cmd_passthru32 __user *)arg;
-
- if (get_user(iop, &cmd->iop) || get_user(i, &cmd->msg))
- return -EFAULT;
-
- user_msg = compat_ptr(i);
-
- c = i2o_find_iop(iop);
- if (!c) {
- osm_debug("controller %d not found\n", iop);
- return -ENXIO;
- }
-
- sb = c->status_block.virt;
-
- if (get_user(size, &user_msg[0])) {
- osm_warn("unable to get size!\n");
- return -EFAULT;
- }
- size = size >> 16;
-
- if (size > sb->inbound_frame_size) {
- osm_warn("size of message > inbound_frame_size");
- return -EFAULT;
- }
-
- user_reply = &user_msg[size];
-
- size <<= 2; // Convert to bytes
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- rcode = -EFAULT;
- /* Copy in the user's I2O command */
- if (copy_from_user(msg, user_msg, size)) {
- osm_warn("unable to copy user message\n");
- goto out;
- }
- i2o_dump_message(msg);
-
- if (get_user(reply_size, &user_reply[0]) < 0)
- goto out;
-
- reply_size >>= 16;
- reply_size <<= 2;
-
- rcode = -ENOMEM;
- reply = kzalloc(reply_size, GFP_KERNEL);
- if (!reply) {
- printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
- c->name);
- goto out;
- }
-
- sg_offset = (msg->u.head[0] >> 4) & 0x0f;
-
- memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
- if (sg_offset) {
- struct sg_simple_element *sg;
-
- if (sg_offset * 4 >= size) {
- rcode = -EFAULT;
- goto cleanup;
- }
- // TODO 64bit fix
- sg = (struct sg_simple_element *)((&msg->u.head[0]) +
- sg_offset);
- sg_count =
- (size - sg_offset * 4) / sizeof(struct sg_simple_element);
- if (sg_count > SG_TABLESIZE) {
- printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
- c->name, sg_count);
- rcode = -EINVAL;
- goto cleanup;
- }
-
- for (i = 0; i < sg_count; i++) {
- int sg_size;
- struct i2o_dma *p;
-
- if (!(sg[i].flag_count & 0x10000000
- /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) {
- printk(KERN_DEBUG
- "%s:Bad SG element %d - not simple (%x)\n",
- c->name, i, sg[i].flag_count);
- rcode = -EINVAL;
- goto cleanup;
- }
- sg_size = sg[i].flag_count & 0xffffff;
- p = &(sg_list[sg_index]);
- /* Allocate memory for the transfer */
- if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) {
- printk(KERN_DEBUG
- "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
- c->name, sg_size, i, sg_count);
- rcode = -ENOMEM;
- goto sg_list_cleanup;
- }
- sg_index++;
- /* Copy in the user's SG buffer if necessary */
- if (sg[i].
- flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
- // TODO 64bit fix
- if (copy_from_user
- (p->virt,
- (void __user *)(unsigned long)sg[i].
- addr_bus, sg_size)) {
- printk(KERN_DEBUG
- "%s: Could not copy SG buf %d FROM user\n",
- c->name, i);
- rcode = -EFAULT;
- goto sg_list_cleanup;
- }
- }
- //TODO 64bit fix
- sg[i].addr_bus = (u32) p->phys;
- }
- }
-
- rcode = i2o_msg_post_wait(c, msg, 60);
- msg = NULL;
- if (rcode) {
- reply[4] = ((u32) rcode) << 24;
- goto sg_list_cleanup;
- }
-
- if (sg_offset) {
- u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE];
- /* Copy back the Scatter Gather buffers back to user space */
- u32 j;
- // TODO 64bit fix
- struct sg_simple_element *sg;
- int sg_size;
-
- // re-acquire the original message to handle correctly the sg copy operation
- memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
- // get user msg size in u32s
- if (get_user(size, &user_msg[0])) {
- rcode = -EFAULT;
- goto sg_list_cleanup;
- }
- size = size >> 16;
- size *= 4;
- if (size > sizeof(rmsg)) {
- rcode = -EINVAL;
- goto sg_list_cleanup;
- }
-
- /* Copy in the user's I2O command */
- if (copy_from_user(rmsg, user_msg, size)) {
- rcode = -EFAULT;
- goto sg_list_cleanup;
- }
- sg_count =
- (size - sg_offset * 4) / sizeof(struct sg_simple_element);
-
- // TODO 64bit fix
- sg = (struct sg_simple_element *)(rmsg + sg_offset);
- for (j = 0; j < sg_count; j++) {
- /* Copy out the SG list to user's buffer if necessary */
- if (!
- (sg[j].
- flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) {
- sg_size = sg[j].flag_count & 0xffffff;
- // TODO 64bit fix
- if (copy_to_user
- ((void __user *)(u64) sg[j].addr_bus,
- sg_list[j].virt, sg_size)) {
- printk(KERN_WARNING
- "%s: Could not copy %p TO user %x\n",
- c->name, sg_list[j].virt,
- sg[j].addr_bus);
- rcode = -EFAULT;
- goto sg_list_cleanup;
- }
- }
- }
- }
-
-sg_list_cleanup:
- /* Copy back the reply to user space */
- if (reply_size) {
- // we wrote our own values for context - now restore the user supplied ones
- if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {
- printk(KERN_WARNING
- "%s: Could not copy message context FROM user\n",
- c->name);
- rcode = -EFAULT;
- }
- if (copy_to_user(user_reply, reply, reply_size)) {
- printk(KERN_WARNING
- "%s: Could not copy reply TO user\n", c->name);
- rcode = -EFAULT;
- }
- }
- for (i = 0; i < sg_index; i++)
- i2o_dma_free(&c->pdev->dev, &sg_list[i]);
-
-cleanup:
- kfree(reply);
-out:
- if (msg)
- i2o_msg_nop(c, msg);
- return rcode;
-}
-
-static long i2o_cfg_compat_ioctl(struct file *file, unsigned cmd,
- unsigned long arg)
-{
- int ret;
- switch (cmd) {
- case I2OGETIOPS:
- ret = i2o_cfg_ioctl(file, cmd, arg);
- break;
- case I2OPASSTHRU32:
- mutex_lock(&i2o_cfg_mutex);
- ret = i2o_cfg_passthru32(file, cmd, arg);
- mutex_unlock(&i2o_cfg_mutex);
- break;
- default:
- ret = -ENOIOCTLCMD;
- break;
- }
- return ret;
-}
-
-#endif
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
-static int i2o_cfg_passthru(unsigned long arg)
-{
- struct i2o_cmd_passthru __user *cmd =
- (struct i2o_cmd_passthru __user *)arg;
- struct i2o_controller *c;
- u32 __user *user_msg;
- u32 *reply = NULL;
- u32 __user *user_reply = NULL;
- u32 size = 0;
- u32 reply_size = 0;
- u32 rcode = 0;
- struct i2o_dma sg_list[SG_TABLESIZE];
- u32 sg_offset = 0;
- u32 sg_count = 0;
- int sg_index = 0;
- u32 i = 0;
- i2o_status_block *sb;
- struct i2o_message *msg;
- unsigned int iop;
-
- if (get_user(iop, &cmd->iop) || get_user(user_msg, &cmd->msg))
- return -EFAULT;
-
- c = i2o_find_iop(iop);
- if (!c) {
- osm_warn("controller %d not found\n", iop);
- return -ENXIO;
- }
-
- sb = c->status_block.virt;
-
- if (get_user(size, &user_msg[0]))
- return -EFAULT;
- size = size >> 16;
-
- if (size > sb->inbound_frame_size) {
- osm_warn("size of message > inbound_frame_size");
- return -EFAULT;
- }
-
- user_reply = &user_msg[size];
-
- size <<= 2; // Convert to bytes
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- rcode = -EFAULT;
- /* Copy in the user's I2O command */
- if (copy_from_user(msg, user_msg, size))
- goto out;
-
- if (get_user(reply_size, &user_reply[0]) < 0)
- goto out;
-
- reply_size >>= 16;
- reply_size <<= 2;
-
- reply = kzalloc(reply_size, GFP_KERNEL);
- if (!reply) {
- printk(KERN_WARNING "%s: Could not allocate reply buffer\n",
- c->name);
- rcode = -ENOMEM;
- goto out;
- }
-
- sg_offset = (msg->u.head[0] >> 4) & 0x0f;
-
- memset(sg_list, 0, sizeof(sg_list[0]) * SG_TABLESIZE);
- if (sg_offset) {
- struct sg_simple_element *sg;
- struct i2o_dma *p;
-
- if (sg_offset * 4 >= size) {
- rcode = -EFAULT;
- goto cleanup;
- }
- // TODO 64bit fix
- sg = (struct sg_simple_element *)((&msg->u.head[0]) +
- sg_offset);
- sg_count =
- (size - sg_offset * 4) / sizeof(struct sg_simple_element);
- if (sg_count > SG_TABLESIZE) {
- printk(KERN_DEBUG "%s:IOCTL SG List too large (%u)\n",
- c->name, sg_count);
- rcode = -EINVAL;
- goto cleanup;
- }
-
- for (i = 0; i < sg_count; i++) {
- int sg_size;
-
- if (!(sg[i].flag_count & 0x10000000
- /*I2O_SGL_FLAGS_SIMPLE_ADDRESS_ELEMENT */ )) {
- printk(KERN_DEBUG
- "%s:Bad SG element %d - not simple (%x)\n",
- c->name, i, sg[i].flag_count);
- rcode = -EINVAL;
- goto sg_list_cleanup;
- }
- sg_size = sg[i].flag_count & 0xffffff;
- p = &(sg_list[sg_index]);
- if (i2o_dma_alloc(&c->pdev->dev, p, sg_size)) {
- /* Allocate memory for the transfer */
- printk(KERN_DEBUG
- "%s: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
- c->name, sg_size, i, sg_count);
- rcode = -ENOMEM;
- goto sg_list_cleanup;
- }
- sg_index++;
- /* Copy in the user's SG buffer if necessary */
- if (sg[i].
- flag_count & 0x04000000 /*I2O_SGL_FLAGS_DIR */ ) {
- // TODO 64bit fix
- if (copy_from_user
- (p->virt, (void __user *)sg[i].addr_bus,
- sg_size)) {
- printk(KERN_DEBUG
- "%s: Could not copy SG buf %d FROM user\n",
- c->name, i);
- rcode = -EFAULT;
- goto sg_list_cleanup;
- }
- }
- sg[i].addr_bus = p->phys;
- }
- }
-
- rcode = i2o_msg_post_wait(c, msg, 60);
- msg = NULL;
- if (rcode) {
- reply[4] = ((u32) rcode) << 24;
- goto sg_list_cleanup;
- }
-
- if (sg_offset) {
- u32 rmsg[I2O_OUTBOUND_MSG_FRAME_SIZE];
- /* Copy back the Scatter Gather buffers back to user space */
- u32 j;
- // TODO 64bit fix
- struct sg_simple_element *sg;
- int sg_size;
-
- // re-acquire the original message to handle correctly the sg copy operation
- memset(&rmsg, 0, I2O_OUTBOUND_MSG_FRAME_SIZE * 4);
- // get user msg size in u32s
- if (get_user(size, &user_msg[0])) {
- rcode = -EFAULT;
- goto sg_list_cleanup;
- }
- size = size >> 16;
- size *= 4;
- if (size > sizeof(rmsg)) {
- rcode = -EFAULT;
- goto sg_list_cleanup;
- }
-
- /* Copy in the user's I2O command */
- if (copy_from_user(rmsg, user_msg, size)) {
- rcode = -EFAULT;
- goto sg_list_cleanup;
- }
- sg_count =
- (size - sg_offset * 4) / sizeof(struct sg_simple_element);
-
- // TODO 64bit fix
- sg = (struct sg_simple_element *)(rmsg + sg_offset);
- for (j = 0; j < sg_count; j++) {
- /* Copy out the SG list to user's buffer if necessary */
- if (!
- (sg[j].
- flag_count & 0x4000000 /*I2O_SGL_FLAGS_DIR */ )) {
- sg_size = sg[j].flag_count & 0xffffff;
- // TODO 64bit fix
- if (copy_to_user
- ((void __user *)sg[j].addr_bus, sg_list[j].virt,
- sg_size)) {
- printk(KERN_WARNING
- "%s: Could not copy %p TO user %x\n",
- c->name, sg_list[j].virt,
- sg[j].addr_bus);
- rcode = -EFAULT;
- goto sg_list_cleanup;
- }
- }
- }
- }
-
-sg_list_cleanup:
- /* Copy back the reply to user space */
- if (reply_size) {
- // we wrote our own values for context - now restore the user supplied ones
- if (copy_from_user(reply + 2, user_msg + 2, sizeof(u32) * 2)) {
- printk(KERN_WARNING
- "%s: Could not copy message context FROM user\n",
- c->name);
- rcode = -EFAULT;
- }
- if (copy_to_user(user_reply, reply, reply_size)) {
- printk(KERN_WARNING
- "%s: Could not copy reply TO user\n", c->name);
- rcode = -EFAULT;
- }
- }
-
- for (i = 0; i < sg_index; i++)
- i2o_dma_free(&c->pdev->dev, &sg_list[i]);
-
-cleanup:
- kfree(reply);
-out:
- if (msg)
- i2o_msg_nop(c, msg);
- return rcode;
-}
-#endif
-
-/*
- * IOCTL Handler
- */
-static long i2o_cfg_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-{
- int ret;
-
- mutex_lock(&i2o_cfg_mutex);
- switch (cmd) {
- case I2OGETIOPS:
- ret = i2o_cfg_getiops(arg);
- break;
-
- case I2OHRTGET:
- ret = i2o_cfg_gethrt(arg);
- break;
-
- case I2OLCTGET:
- ret = i2o_cfg_getlct(arg);
- break;
-
- case I2OPARMSET:
- ret = i2o_cfg_parms(arg, I2OPARMSET);
- break;
-
- case I2OPARMGET:
- ret = i2o_cfg_parms(arg, I2OPARMGET);
- break;
-
- case I2OSWDL:
- ret = i2o_cfg_swdl(arg);
- break;
-
- case I2OSWUL:
- ret = i2o_cfg_swul(arg);
- break;
-
- case I2OSWDEL:
- ret = i2o_cfg_swdel(arg);
- break;
-
- case I2OVALIDATE:
- ret = i2o_cfg_validate(arg);
- break;
-
- case I2OEVTREG:
- ret = i2o_cfg_evt_reg(arg, fp);
- break;
-
- case I2OEVTGET:
- ret = i2o_cfg_evt_get(arg, fp);
- break;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- case I2OPASSTHRU:
- ret = i2o_cfg_passthru(arg);
- break;
-#endif
-
- default:
- osm_debug("unknown ioctl called!\n");
- ret = -EINVAL;
- }
- mutex_unlock(&i2o_cfg_mutex);
- return ret;
-}
-
-static int cfg_open(struct inode *inode, struct file *file)
-{
- struct i2o_cfg_info *tmp = kmalloc(sizeof(struct i2o_cfg_info),
- GFP_KERNEL);
- unsigned long flags;
-
- if (!tmp)
- return -ENOMEM;
-
- mutex_lock(&i2o_cfg_mutex);
- file->private_data = (void *)(i2o_cfg_info_id++);
- tmp->fp = file;
- tmp->fasync = NULL;
- tmp->q_id = (ulong) file->private_data;
- tmp->q_len = 0;
- tmp->q_in = 0;
- tmp->q_out = 0;
- tmp->q_lost = 0;
- tmp->next = open_files;
-
- spin_lock_irqsave(&i2o_config_lock, flags);
- open_files = tmp;
- spin_unlock_irqrestore(&i2o_config_lock, flags);
- mutex_unlock(&i2o_cfg_mutex);
-
- return 0;
-}
-
-static int cfg_fasync(int fd, struct file *fp, int on)
-{
- ulong id = (ulong) fp->private_data;
- struct i2o_cfg_info *p;
- int ret = -EBADF;
-
- mutex_lock(&i2o_cfg_mutex);
- for (p = open_files; p; p = p->next)
- if (p->q_id == id)
- break;
-
- if (p)
- ret = fasync_helper(fd, fp, on, &p->fasync);
- mutex_unlock(&i2o_cfg_mutex);
- return ret;
-}
-
-static int cfg_release(struct inode *inode, struct file *file)
-{
- ulong id = (ulong) file->private_data;
- struct i2o_cfg_info *p, **q;
- unsigned long flags;
-
- mutex_lock(&i2o_cfg_mutex);
- spin_lock_irqsave(&i2o_config_lock, flags);
- for (q = &open_files; (p = *q) != NULL; q = &p->next) {
- if (p->q_id == id) {
- *q = p->next;
- kfree(p);
- break;
- }
- }
- spin_unlock_irqrestore(&i2o_config_lock, flags);
- mutex_unlock(&i2o_cfg_mutex);
-
- return 0;
-}
-
-static const struct file_operations config_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .unlocked_ioctl = i2o_cfg_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = i2o_cfg_compat_ioctl,
-#endif
- .open = cfg_open,
- .release = cfg_release,
- .fasync = cfg_fasync,
-};
-
-static struct miscdevice i2o_miscdev = {
- I2O_MINOR,
- "i2octl",
- &config_fops
-};
-
-static int __init i2o_config_old_init(void)
-{
- spin_lock_init(&i2o_config_lock);
-
- if (misc_register(&i2o_miscdev) < 0) {
- osm_err("can't register device.\n");
- return -EBUSY;
- }
-
- return 0;
-}
-
-static void i2o_config_old_exit(void)
-{
- misc_deregister(&i2o_miscdev);
-}
-
-MODULE_AUTHOR("Red Hat Software");
+++ /dev/null
-/*
- * procfs handler for Linux I2O subsystem
- *
- * (c) Copyright 1999 Deepak Saxena
- *
- * Originally written by Deepak Saxena(deepak@plexity.net)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This is an initial test release. The code is based on the design of the
- * ide procfs system (drivers/block/ide-proc.c). Some code taken from
- * i2o-core module by Alan Cox.
- *
- * DISCLAIMER: This code is still under development/test and may cause
- * your system to behave unpredictably. Use at your own discretion.
- *
- *
- * Fixes/additions:
- * Juha Sievänen (Juha.Sievanen@cs.Helsinki.FI),
- * Auvo Häkkinen (Auvo.Hakkinen@cs.Helsinki.FI)
- * University of Helsinki, Department of Computer Science
- * LAN entries
- * Markus Lidel <Markus.Lidel@shadowconnect.com>
- * Changes for new I2O API
- */
-
-#define OSM_NAME "proc-osm"
-#define OSM_VERSION "1.316"
-#define OSM_DESCRIPTION "I2O ProcFS OSM"
-
-#define I2O_MAX_MODULES 4
-// FIXME!
-#define FMT_U64_HEX "0x%08x%08x"
-#define U64_VAL(pu64) *((u32*)(pu64)+1), *((u32*)(pu64))
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include "i2o.h"
-#include <linux/slab.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/uaccess.h>
-
-#include <asm/io.h>
-#include <asm/byteorder.h>
-
-/* Structure used to define /proc entries */
-typedef struct _i2o_proc_entry_t {
- char *name; /* entry name */
- umode_t mode; /* mode */
- const struct file_operations *fops; /* open function */
-} i2o_proc_entry;
-
-/* global I2O /proc/i2o entry */
-static struct proc_dir_entry *i2o_proc_dir_root;
-
-/* proc OSM driver struct */
-static struct i2o_driver i2o_proc_driver = {
- .name = OSM_NAME,
-};
-
-static int print_serial_number(struct seq_file *seq, u8 * serialno, int max_len)
-{
- int i;
-
- /* 19990419 -sralston
- * The I2O v1.5 (and v2.0 so far) "official specification"
- * got serial numbers WRONG!
- * Apparently, and despite what Section 3.4.4 says and
- * Figure 3-35 shows (pg 3-39 in the pdf doc),
- * the convention / consensus seems to be:
- * + First byte is SNFormat
- * + Second byte is SNLen (but only if SNFormat==7 (?))
- * + (v2.0) SCSI+BS may use IEEE Registered (64 or 128 bit) format
- */
- switch (serialno[0]) {
- case I2O_SNFORMAT_BINARY: /* Binary */
- seq_printf(seq, "0x");
- for (i = 0; i < serialno[1]; i++)
- seq_printf(seq, "%02X", serialno[2 + i]);
- break;
-
- case I2O_SNFORMAT_ASCII: /* ASCII */
- if (serialno[1] < ' ') { /* printable or SNLen? */
- /* sanity */
- max_len =
- (max_len < serialno[1]) ? max_len : serialno[1];
- serialno[1 + max_len] = '\0';
-
- /* just print it */
- seq_printf(seq, "%s", &serialno[2]);
- } else {
- /* print chars for specified length */
- for (i = 0; i < serialno[1]; i++)
- seq_printf(seq, "%c", serialno[2 + i]);
- }
- break;
-
- case I2O_SNFORMAT_UNICODE: /* UNICODE */
- seq_printf(seq, "UNICODE Format. Can't Display\n");
- break;
-
- case I2O_SNFORMAT_LAN48_MAC: /* LAN-48 MAC Address */
- seq_printf(seq, "LAN-48 MAC address @ %pM", &serialno[2]);
- break;
-
- case I2O_SNFORMAT_WAN: /* WAN MAC Address */
- /* FIXME: Figure out what a WAN access address looks like?? */
- seq_printf(seq, "WAN Access Address");
- break;
-
-/* plus new in v2.0 */
- case I2O_SNFORMAT_LAN64_MAC: /* LAN-64 MAC Address */
- /* FIXME: Figure out what a LAN-64 address really looks like?? */
- seq_printf(seq,
- "LAN-64 MAC address @ [?:%02X:%02X:?] %pM",
- serialno[8], serialno[9], &serialno[2]);
- break;
-
- case I2O_SNFORMAT_DDM: /* I2O DDM */
- seq_printf(seq,
- "DDM: Tid=%03Xh, Rsvd=%04Xh, OrgId=%04Xh",
- *(u16 *) & serialno[2],
- *(u16 *) & serialno[4], *(u16 *) & serialno[6]);
- break;
-
- case I2O_SNFORMAT_IEEE_REG64: /* IEEE Registered (64-bit) */
- case I2O_SNFORMAT_IEEE_REG128: /* IEEE Registered (128-bit) */
- /* FIXME: Figure if this is even close?? */
- seq_printf(seq,
- "IEEE NodeName(hi,lo)=(%08Xh:%08Xh), PortName(hi,lo)=(%08Xh:%08Xh)\n",
- *(u32 *) & serialno[2],
- *(u32 *) & serialno[6],
- *(u32 *) & serialno[10], *(u32 *) & serialno[14]);
- break;
-
- case I2O_SNFORMAT_UNKNOWN: /* Unknown 0 */
- case I2O_SNFORMAT_UNKNOWN2: /* Unknown 0xff */
- default:
- seq_printf(seq, "Unknown data format (0x%02x)", serialno[0]);
- break;
- }
-
- return 0;
-}
-
-/**
- * i2o_get_class_name - do i2o class name lookup
- * @class: class number
- *
- * Return a descriptive string for an i2o class.
- */
-static const char *i2o_get_class_name(int class)
-{
- int idx = 16;
- static char *i2o_class_name[] = {
- "Executive",
- "Device Driver Module",
- "Block Device",
- "Tape Device",
- "LAN Interface",
- "WAN Interface",
- "Fibre Channel Port",
- "Fibre Channel Device",
- "SCSI Device",
- "ATE Port",
- "ATE Device",
- "Floppy Controller",
- "Floppy Device",
- "Secondary Bus Port",
- "Peer Transport Agent",
- "Peer Transport",
- "Unknown"
- };
-
- switch (class & 0xfff) {
- case I2O_CLASS_EXECUTIVE:
- idx = 0;
- break;
- case I2O_CLASS_DDM:
- idx = 1;
- break;
- case I2O_CLASS_RANDOM_BLOCK_STORAGE:
- idx = 2;
- break;
- case I2O_CLASS_SEQUENTIAL_STORAGE:
- idx = 3;
- break;
- case I2O_CLASS_LAN:
- idx = 4;
- break;
- case I2O_CLASS_WAN:
- idx = 5;
- break;
- case I2O_CLASS_FIBRE_CHANNEL_PORT:
- idx = 6;
- break;
- case I2O_CLASS_FIBRE_CHANNEL_PERIPHERAL:
- idx = 7;
- break;
- case I2O_CLASS_SCSI_PERIPHERAL:
- idx = 8;
- break;
- case I2O_CLASS_ATE_PORT:
- idx = 9;
- break;
- case I2O_CLASS_ATE_PERIPHERAL:
- idx = 10;
- break;
- case I2O_CLASS_FLOPPY_CONTROLLER:
- idx = 11;
- break;
- case I2O_CLASS_FLOPPY_DEVICE:
- idx = 12;
- break;
- case I2O_CLASS_BUS_ADAPTER:
- idx = 13;
- break;
- case I2O_CLASS_PEER_TRANSPORT_AGENT:
- idx = 14;
- break;
- case I2O_CLASS_PEER_TRANSPORT:
- idx = 15;
- break;
- }
-
- return i2o_class_name[idx];
-}
-
-#define SCSI_TABLE_SIZE 13
-static char *scsi_devices[] = {
- "Direct-Access Read/Write",
- "Sequential-Access Storage",
- "Printer",
- "Processor",
- "WORM Device",
- "CD-ROM Device",
- "Scanner Device",
- "Optical Memory Device",
- "Medium Changer Device",
- "Communications Device",
- "Graphics Art Pre-Press Device",
- "Graphics Art Pre-Press Device",
- "Array Controller Device"
-};
-
-static char *chtostr(char *tmp, u8 *chars, int n)
-{
- tmp[0] = 0;
- return strncat(tmp, (char *)chars, n);
-}
-
-static int i2o_report_query_status(struct seq_file *seq, int block_status,
- char *group)
-{
- switch (block_status) {
- case -ETIMEDOUT:
- seq_printf(seq, "Timeout reading group %s.\n", group);
- break;
- case -ENOMEM:
- seq_puts(seq, "No free memory to read the table.\n");
- break;
- case -I2O_PARAMS_STATUS_INVALID_GROUP_ID:
- seq_printf(seq, "Group %s not supported.\n", group);
- break;
- default:
- seq_printf(seq,
- "Error reading group %s. BlockStatus 0x%02X\n",
- group, -block_status);
- break;
- }
-
- return 0;
-}
-
-static char *bus_strings[] = {
- "Local Bus",
- "ISA",
- "EISA",
- "PCI",
- "PCMCIA",
- "NUBUS",
- "CARDBUS"
-};
-
-static int i2o_seq_show_hrt(struct seq_file *seq, void *v)
-{
- struct i2o_controller *c = (struct i2o_controller *)seq->private;
- i2o_hrt *hrt = (i2o_hrt *) c->hrt.virt;
- u32 bus;
- int i;
-
- if (hrt->hrt_version) {
- seq_printf(seq,
- "HRT table for controller is too new a version.\n");
- return 0;
- }
-
- seq_printf(seq, "HRT has %d entries of %d bytes each.\n",
- hrt->num_entries, hrt->entry_len << 2);
-
- for (i = 0; i < hrt->num_entries; i++) {
- seq_printf(seq, "Entry %d:\n", i);
- seq_printf(seq, " Adapter ID: %0#10x\n",
- hrt->hrt_entry[i].adapter_id);
- seq_printf(seq, " Controlling tid: %0#6x\n",
- hrt->hrt_entry[i].parent_tid);
-
- if (hrt->hrt_entry[i].bus_type != 0x80) {
- bus = hrt->hrt_entry[i].bus_type;
- seq_printf(seq, " %s Information\n",
- bus_strings[bus]);
-
- switch (bus) {
- case I2O_BUS_LOCAL:
- seq_printf(seq, " IOBase: %0#6x,",
- hrt->hrt_entry[i].bus.local_bus.
- LbBaseIOPort);
- seq_printf(seq, " MemoryBase: %0#10x\n",
- hrt->hrt_entry[i].bus.local_bus.
- LbBaseMemoryAddress);
- break;
-
- case I2O_BUS_ISA:
- seq_printf(seq, " IOBase: %0#6x,",
- hrt->hrt_entry[i].bus.isa_bus.
- IsaBaseIOPort);
- seq_printf(seq, " MemoryBase: %0#10x,",
- hrt->hrt_entry[i].bus.isa_bus.
- IsaBaseMemoryAddress);
- seq_printf(seq, " CSN: %0#4x,",
- hrt->hrt_entry[i].bus.isa_bus.CSN);
- break;
-
- case I2O_BUS_EISA:
- seq_printf(seq, " IOBase: %0#6x,",
- hrt->hrt_entry[i].bus.eisa_bus.
- EisaBaseIOPort);
- seq_printf(seq, " MemoryBase: %0#10x,",
- hrt->hrt_entry[i].bus.eisa_bus.
- EisaBaseMemoryAddress);
- seq_printf(seq, " Slot: %0#4x,",
- hrt->hrt_entry[i].bus.eisa_bus.
- EisaSlotNumber);
- break;
-
- case I2O_BUS_PCI:
- seq_printf(seq, " Bus: %0#4x",
- hrt->hrt_entry[i].bus.pci_bus.
- PciBusNumber);
- seq_printf(seq, " Dev: %0#4x",
- hrt->hrt_entry[i].bus.pci_bus.
- PciDeviceNumber);
- seq_printf(seq, " Func: %0#4x",
- hrt->hrt_entry[i].bus.pci_bus.
- PciFunctionNumber);
- seq_printf(seq, " Vendor: %0#6x",
- hrt->hrt_entry[i].bus.pci_bus.
- PciVendorID);
- seq_printf(seq, " Device: %0#6x\n",
- hrt->hrt_entry[i].bus.pci_bus.
- PciDeviceID);
- break;
-
- default:
- seq_printf(seq, " Unsupported Bus Type\n");
- }
- } else
- seq_printf(seq, " Unknown Bus Type\n");
- }
-
- return 0;
-}
-
-static int i2o_seq_show_lct(struct seq_file *seq, void *v)
-{
- struct i2o_controller *c = (struct i2o_controller *)seq->private;
- i2o_lct *lct = (i2o_lct *) c->lct;
- int entries;
- int i;
-
-#define BUS_TABLE_SIZE 3
- static char *bus_ports[] = {
- "Generic Bus",
- "SCSI Bus",
- "Fibre Channel Bus"
- };
-
- entries = (lct->table_size - 3) / 9;
-
- seq_printf(seq, "LCT contains %d %s\n", entries,
- entries == 1 ? "entry" : "entries");
- if (lct->boot_tid)
- seq_printf(seq, "Boot Device @ ID %d\n", lct->boot_tid);
-
- seq_printf(seq, "Current Change Indicator: %#10x\n", lct->change_ind);
-
- for (i = 0; i < entries; i++) {
- seq_printf(seq, "Entry %d\n", i);
- seq_printf(seq, " Class, SubClass : %s",
- i2o_get_class_name(lct->lct_entry[i].class_id));
-
- /*
- * Classes which we'll print subclass info for
- */
- switch (lct->lct_entry[i].class_id & 0xFFF) {
- case I2O_CLASS_RANDOM_BLOCK_STORAGE:
- switch (lct->lct_entry[i].sub_class) {
- case 0x00:
- seq_printf(seq, ", Direct-Access Read/Write");
- break;
-
- case 0x04:
- seq_printf(seq, ", WORM Drive");
- break;
-
- case 0x05:
- seq_printf(seq, ", CD-ROM Drive");
- break;
-
- case 0x07:
- seq_printf(seq, ", Optical Memory Device");
- break;
-
- default:
- seq_printf(seq, ", Unknown (0x%02x)",
- lct->lct_entry[i].sub_class);
- break;
- }
- break;
-
- case I2O_CLASS_LAN:
- switch (lct->lct_entry[i].sub_class & 0xFF) {
- case 0x30:
- seq_printf(seq, ", Ethernet");
- break;
-
- case 0x40:
- seq_printf(seq, ", 100base VG");
- break;
-
- case 0x50:
- seq_printf(seq, ", IEEE 802.5/Token-Ring");
- break;
-
- case 0x60:
- seq_printf(seq, ", ANSI X3T9.5 FDDI");
- break;
-
- case 0x70:
- seq_printf(seq, ", Fibre Channel");
- break;
-
- default:
- seq_printf(seq, ", Unknown Sub-Class (0x%02x)",
- lct->lct_entry[i].sub_class & 0xFF);
- break;
- }
- break;
-
- case I2O_CLASS_SCSI_PERIPHERAL:
- if (lct->lct_entry[i].sub_class < SCSI_TABLE_SIZE)
- seq_printf(seq, ", %s",
- scsi_devices[lct->lct_entry[i].
- sub_class]);
- else
- seq_printf(seq, ", Unknown Device Type");
- break;
-
- case I2O_CLASS_BUS_ADAPTER:
- if (lct->lct_entry[i].sub_class < BUS_TABLE_SIZE)
- seq_printf(seq, ", %s",
- bus_ports[lct->lct_entry[i].
- sub_class]);
- else
- seq_printf(seq, ", Unknown Bus Type");
- break;
- }
- seq_printf(seq, "\n");
-
- seq_printf(seq, " Local TID : 0x%03x\n",
- lct->lct_entry[i].tid);
- seq_printf(seq, " User TID : 0x%03x\n",
- lct->lct_entry[i].user_tid);
- seq_printf(seq, " Parent TID : 0x%03x\n",
- lct->lct_entry[i].parent_tid);
- seq_printf(seq, " Identity Tag : 0x%x%x%x%x%x%x%x%x\n",
- lct->lct_entry[i].identity_tag[0],
- lct->lct_entry[i].identity_tag[1],
- lct->lct_entry[i].identity_tag[2],
- lct->lct_entry[i].identity_tag[3],
- lct->lct_entry[i].identity_tag[4],
- lct->lct_entry[i].identity_tag[5],
- lct->lct_entry[i].identity_tag[6],
- lct->lct_entry[i].identity_tag[7]);
- seq_printf(seq, " Change Indicator : %0#10x\n",
- lct->lct_entry[i].change_ind);
- seq_printf(seq, " Event Capab Mask : %0#10x\n",
- lct->lct_entry[i].device_flags);
- }
-
- return 0;
-}
-
-static int i2o_seq_show_status(struct seq_file *seq, void *v)
-{
- struct i2o_controller *c = (struct i2o_controller *)seq->private;
- char prodstr[25];
- int version;
- i2o_status_block *sb = c->status_block.virt;
-
- i2o_status_get(c); // reread the status block
-
- seq_printf(seq, "Organization ID : %0#6x\n", sb->org_id);
-
- version = sb->i2o_version;
-
-/* FIXME for Spec 2.0
- if (version == 0x02) {
- seq_printf(seq, "Lowest I2O version supported: ");
- switch(workspace[2]) {
- case 0x00:
- seq_printf(seq, "1.0\n");
- break;
- case 0x01:
- seq_printf(seq, "1.5\n");
- break;
- case 0x02:
- seq_printf(seq, "2.0\n");
- break;
- }
-
- seq_printf(seq, "Highest I2O version supported: ");
- switch(workspace[3]) {
- case 0x00:
- seq_printf(seq, "1.0\n");
- break;
- case 0x01:
- seq_printf(seq, "1.5\n");
- break;
- case 0x02:
- seq_printf(seq, "2.0\n");
- break;
- }
- }
-*/
- seq_printf(seq, "IOP ID : %0#5x\n", sb->iop_id);
- seq_printf(seq, "Host Unit ID : %0#6x\n", sb->host_unit_id);
- seq_printf(seq, "Segment Number : %0#5x\n", sb->segment_number);
-
- seq_printf(seq, "I2O version : ");
- switch (version) {
- case 0x00:
- seq_printf(seq, "1.0\n");
- break;
- case 0x01:
- seq_printf(seq, "1.5\n");
- break;
- case 0x02:
- seq_printf(seq, "2.0\n");
- break;
- default:
- seq_printf(seq, "Unknown version\n");
- }
-
- seq_printf(seq, "IOP State : ");
- switch (sb->iop_state) {
- case 0x01:
- seq_printf(seq, "INIT\n");
- break;
-
- case 0x02:
- seq_printf(seq, "RESET\n");
- break;
-
- case 0x04:
- seq_printf(seq, "HOLD\n");
- break;
-
- case 0x05:
- seq_printf(seq, "READY\n");
- break;
-
- case 0x08:
- seq_printf(seq, "OPERATIONAL\n");
- break;
-
- case 0x10:
- seq_printf(seq, "FAILED\n");
- break;
-
- case 0x11:
- seq_printf(seq, "FAULTED\n");
- break;
-
- default:
- seq_printf(seq, "Unknown\n");
- break;
- }
-
- seq_printf(seq, "Messenger Type : ");
- switch (sb->msg_type) {
- case 0x00:
- seq_printf(seq, "Memory mapped\n");
- break;
- case 0x01:
- seq_printf(seq, "Memory mapped only\n");
- break;
- case 0x02:
- seq_printf(seq, "Remote only\n");
- break;
- case 0x03:
- seq_printf(seq, "Memory mapped and remote\n");
- break;
- default:
- seq_printf(seq, "Unknown\n");
- }
-
- seq_printf(seq, "Inbound Frame Size : %d bytes\n",
- sb->inbound_frame_size << 2);
- seq_printf(seq, "Max Inbound Frames : %d\n",
- sb->max_inbound_frames);
- seq_printf(seq, "Current Inbound Frames : %d\n",
- sb->cur_inbound_frames);
- seq_printf(seq, "Max Outbound Frames : %d\n",
- sb->max_outbound_frames);
-
- /* Spec doesn't say if NULL terminated or not... */
- memcpy(prodstr, sb->product_id, 24);
- prodstr[24] = '\0';
- seq_printf(seq, "Product ID : %s\n", prodstr);
- seq_printf(seq, "Expected LCT Size : %d bytes\n",
- sb->expected_lct_size);
-
- seq_printf(seq, "IOP Capabilities\n");
- seq_printf(seq, " Context Field Size Support : ");
- switch (sb->iop_capabilities & 0x0000003) {
- case 0:
- seq_printf(seq, "Supports only 32-bit context fields\n");
- break;
- case 1:
- seq_printf(seq, "Supports only 64-bit context fields\n");
- break;
- case 2:
- seq_printf(seq, "Supports 32-bit and 64-bit context fields, "
- "but not concurrently\n");
- break;
- case 3:
- seq_printf(seq, "Supports 32-bit and 64-bit context fields "
- "concurrently\n");
- break;
- default:
- seq_printf(seq, "0x%08x\n", sb->iop_capabilities);
- }
- seq_printf(seq, " Current Context Field Size : ");
- switch (sb->iop_capabilities & 0x0000000C) {
- case 0:
- seq_printf(seq, "not configured\n");
- break;
- case 4:
- seq_printf(seq, "Supports only 32-bit context fields\n");
- break;
- case 8:
- seq_printf(seq, "Supports only 64-bit context fields\n");
- break;
- case 12:
- seq_printf(seq, "Supports both 32-bit or 64-bit context fields "
- "concurrently\n");
- break;
- default:
- seq_printf(seq, "\n");
- }
- seq_printf(seq, " Inbound Peer Support : %s\n",
- (sb->
- iop_capabilities & 0x00000010) ? "Supported" :
- "Not supported");
- seq_printf(seq, " Outbound Peer Support : %s\n",
- (sb->
- iop_capabilities & 0x00000020) ? "Supported" :
- "Not supported");
- seq_printf(seq, " Peer to Peer Support : %s\n",
- (sb->
- iop_capabilities & 0x00000040) ? "Supported" :
- "Not supported");
-
- seq_printf(seq, "Desired private memory size : %d kB\n",
- sb->desired_mem_size >> 10);
- seq_printf(seq, "Allocated private memory size : %d kB\n",
- sb->current_mem_size >> 10);
- seq_printf(seq, "Private memory base address : %0#10x\n",
- sb->current_mem_base);
- seq_printf(seq, "Desired private I/O size : %d kB\n",
- sb->desired_io_size >> 10);
- seq_printf(seq, "Allocated private I/O size : %d kB\n",
- sb->current_io_size >> 10);
- seq_printf(seq, "Private I/O base address : %0#10x\n",
- sb->current_io_base);
-
- return 0;
-}
-
-static int i2o_seq_show_hw(struct seq_file *seq, void *v)
-{
- struct i2o_controller *c = (struct i2o_controller *)seq->private;
- static u32 work32[5];
- static u8 *work8 = (u8 *) work32;
- static u16 *work16 = (u16 *) work32;
- int token;
- u32 hwcap;
-
- static char *cpu_table[] = {
- "Intel 80960 series",
- "AMD2900 series",
- "Motorola 68000 series",
- "ARM series",
- "MIPS series",
- "Sparc series",
- "PowerPC series",
- "Intel x86 series"
- };
-
- token =
- i2o_parm_field_get(c->exec, 0x0000, -1, &work32, sizeof(work32));
-
- if (token < 0) {
- i2o_report_query_status(seq, token, "0x0000 IOP Hardware");
- return 0;
- }
-
- seq_printf(seq, "I2O Vendor ID : %0#6x\n", work16[0]);
- seq_printf(seq, "Product ID : %0#6x\n", work16[1]);
- seq_printf(seq, "CPU : ");
- if (work8[16] > 8)
- seq_printf(seq, "Unknown\n");
- else
- seq_printf(seq, "%s\n", cpu_table[work8[16]]);
- /* Anyone using ProcessorVersion? */
-
- seq_printf(seq, "RAM : %dkB\n", work32[1] >> 10);
- seq_printf(seq, "Non-Volatile Mem : %dkB\n", work32[2] >> 10);
-
- hwcap = work32[3];
- seq_printf(seq, "Capabilities : 0x%08x\n", hwcap);
- seq_printf(seq, " [%s] Self booting\n",
- (hwcap & 0x00000001) ? "+" : "-");
- seq_printf(seq, " [%s] Upgradable IRTOS\n",
- (hwcap & 0x00000002) ? "+" : "-");
- seq_printf(seq, " [%s] Supports downloading DDMs\n",
- (hwcap & 0x00000004) ? "+" : "-");
- seq_printf(seq, " [%s] Supports installing DDMs\n",
- (hwcap & 0x00000008) ? "+" : "-");
- seq_printf(seq, " [%s] Battery-backed RAM\n",
- (hwcap & 0x00000010) ? "+" : "-");
-
- return 0;
-}
-
-/* Executive group 0003h - Executing DDM List (table) */
-static int i2o_seq_show_ddm_table(struct seq_file *seq, void *v)
-{
- struct i2o_controller *c = (struct i2o_controller *)seq->private;
- int token;
- int i;
-
- typedef struct _i2o_exec_execute_ddm_table {
- u16 ddm_tid;
- u8 module_type;
- u8 reserved;
- u16 i2o_vendor_id;
- u16 module_id;
- u8 module_name_version[28];
- u32 data_size;
- u32 code_size;
- } i2o_exec_execute_ddm_table;
-
- struct {
- u16 result_count;
- u16 pad;
- u16 block_size;
- u8 block_status;
- u8 error_info_size;
- u16 row_count;
- u16 more_flag;
- i2o_exec_execute_ddm_table ddm_table[I2O_MAX_MODULES];
- } *result;
-
- i2o_exec_execute_ddm_table ddm_table;
- char tmp[28 + 1];
-
- result = kmalloc(sizeof(*result), GFP_KERNEL);
- if (!result)
- return -ENOMEM;
-
- token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0003, -1,
- NULL, 0, result, sizeof(*result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token,
- "0x0003 Executing DDM List");
- goto out;
- }
-
- seq_printf(seq,
- "Tid Module_type Vendor Mod_id Module_name Vrs Data_size Code_size\n");
- ddm_table = result->ddm_table[0];
-
- for (i = 0; i < result->row_count; ddm_table = result->ddm_table[++i]) {
- seq_printf(seq, "0x%03x ", ddm_table.ddm_tid & 0xFFF);
-
- switch (ddm_table.module_type) {
- case 0x01:
- seq_printf(seq, "Downloaded DDM ");
- break;
- case 0x22:
- seq_printf(seq, "Embedded DDM ");
- break;
- default:
- seq_printf(seq, " ");
- }
-
- seq_printf(seq, "%-#7x", ddm_table.i2o_vendor_id);
- seq_printf(seq, "%-#8x", ddm_table.module_id);
- seq_printf(seq, "%-29s",
- chtostr(tmp, ddm_table.module_name_version, 28));
- seq_printf(seq, "%9d ", ddm_table.data_size);
- seq_printf(seq, "%8d", ddm_table.code_size);
-
- seq_printf(seq, "\n");
- }
- out:
- kfree(result);
- return 0;
-}
-
-/* Executive group 0004h - Driver Store (scalar) */
-static int i2o_seq_show_driver_store(struct seq_file *seq, void *v)
-{
- struct i2o_controller *c = (struct i2o_controller *)seq->private;
- u32 work32[8];
- int token;
-
- token =
- i2o_parm_field_get(c->exec, 0x0004, -1, &work32, sizeof(work32));
- if (token < 0) {
- i2o_report_query_status(seq, token, "0x0004 Driver Store");
- return 0;
- }
-
- seq_printf(seq, "Module limit : %d\n"
- "Module count : %d\n"
- "Current space : %d kB\n"
- "Free space : %d kB\n",
- work32[0], work32[1], work32[2] >> 10, work32[3] >> 10);
-
- return 0;
-}
-
-/* Executive group 0005h - Driver Store Table (table) */
-static int i2o_seq_show_drivers_stored(struct seq_file *seq, void *v)
-{
- typedef struct _i2o_driver_store {
- u16 stored_ddm_index;
- u8 module_type;
- u8 reserved;
- u16 i2o_vendor_id;
- u16 module_id;
- u8 module_name_version[28];
- u8 date[8];
- u32 module_size;
- u32 mpb_size;
- u32 module_flags;
- } i2o_driver_store_table;
-
- struct i2o_controller *c = (struct i2o_controller *)seq->private;
- int token;
- int i;
-
- typedef struct {
- u16 result_count;
- u16 pad;
- u16 block_size;
- u8 block_status;
- u8 error_info_size;
- u16 row_count;
- u16 more_flag;
- i2o_driver_store_table dst[I2O_MAX_MODULES];
- } i2o_driver_result_table;
-
- i2o_driver_result_table *result;
- i2o_driver_store_table *dst;
- char tmp[28 + 1];
-
- result = kmalloc(sizeof(i2o_driver_result_table), GFP_KERNEL);
- if (result == NULL)
- return -ENOMEM;
-
- token = i2o_parm_table_get(c->exec, I2O_PARAMS_TABLE_GET, 0x0005, -1,
- NULL, 0, result, sizeof(*result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token,
- "0x0005 DRIVER STORE TABLE");
- kfree(result);
- return 0;
- }
-
- seq_printf(seq,
- "# Module_type Vendor Mod_id Module_name Vrs"
- "Date Mod_size Par_size Flags\n");
- for (i = 0, dst = &result->dst[0]; i < result->row_count;
- dst = &result->dst[++i]) {
- seq_printf(seq, "%-3d", dst->stored_ddm_index);
- switch (dst->module_type) {
- case 0x01:
- seq_printf(seq, "Downloaded DDM ");
- break;
- case 0x22:
- seq_printf(seq, "Embedded DDM ");
- break;
- default:
- seq_printf(seq, " ");
- }
-
- seq_printf(seq, "%-#7x", dst->i2o_vendor_id);
- seq_printf(seq, "%-#8x", dst->module_id);
- seq_printf(seq, "%-29s",
- chtostr(tmp, dst->module_name_version, 28));
- seq_printf(seq, "%-9s", chtostr(tmp, dst->date, 8));
- seq_printf(seq, "%8d ", dst->module_size);
- seq_printf(seq, "%8d ", dst->mpb_size);
- seq_printf(seq, "0x%04x", dst->module_flags);
- seq_printf(seq, "\n");
- }
-
- kfree(result);
- return 0;
-}
-
-/* Generic group F000h - Params Descriptor (table) */
-static int i2o_seq_show_groups(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- int token;
- int i;
- u8 properties;
-
- typedef struct _i2o_group_info {
- u16 group_number;
- u16 field_count;
- u16 row_count;
- u8 properties;
- u8 reserved;
- } i2o_group_info;
-
- struct {
- u16 result_count;
- u16 pad;
- u16 block_size;
- u8 block_status;
- u8 error_info_size;
- u16 row_count;
- u16 more_flag;
- i2o_group_info group[256];
- } *result;
-
- result = kmalloc(sizeof(*result), GFP_KERNEL);
- if (!result)
- return -ENOMEM;
-
- token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0,
- result, sizeof(*result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token, "0xF000 Params Descriptor");
- goto out;
- }
-
- seq_printf(seq,
- "# Group FieldCount RowCount Type Add Del Clear\n");
-
- for (i = 0; i < result->row_count; i++) {
- seq_printf(seq, "%-3d", i);
- seq_printf(seq, "0x%04X ", result->group[i].group_number);
- seq_printf(seq, "%10d ", result->group[i].field_count);
- seq_printf(seq, "%8d ", result->group[i].row_count);
-
- properties = result->group[i].properties;
- if (properties & 0x1)
- seq_printf(seq, "Table ");
- else
- seq_printf(seq, "Scalar ");
- if (properties & 0x2)
- seq_printf(seq, " + ");
- else
- seq_printf(seq, " - ");
- if (properties & 0x4)
- seq_printf(seq, " + ");
- else
- seq_printf(seq, " - ");
- if (properties & 0x8)
- seq_printf(seq, " + ");
- else
- seq_printf(seq, " - ");
-
- seq_printf(seq, "\n");
- }
-
- if (result->more_flag)
- seq_printf(seq, "There is more...\n");
- out:
- kfree(result);
- return 0;
-}
-
-/* Generic group F001h - Physical Device Table (table) */
-static int i2o_seq_show_phys_device(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- int token;
- int i;
-
- struct {
- u16 result_count;
- u16 pad;
- u16 block_size;
- u8 block_status;
- u8 error_info_size;
- u16 row_count;
- u16 more_flag;
- u32 adapter_id[64];
- } result;
-
- token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF001, -1, NULL, 0,
- &result, sizeof(result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token,
- "0xF001 Physical Device Table");
- return 0;
- }
-
- if (result.row_count)
- seq_printf(seq, "# AdapterId\n");
-
- for (i = 0; i < result.row_count; i++) {
- seq_printf(seq, "%-2d", i);
- seq_printf(seq, "%#7x\n", result.adapter_id[i]);
- }
-
- if (result.more_flag)
- seq_printf(seq, "There is more...\n");
-
- return 0;
-}
-
-/* Generic group F002h - Claimed Table (table) */
-static int i2o_seq_show_claimed(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- int token;
- int i;
-
- struct {
- u16 result_count;
- u16 pad;
- u16 block_size;
- u8 block_status;
- u8 error_info_size;
- u16 row_count;
- u16 more_flag;
- u16 claimed_tid[64];
- } result;
-
- token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF002, -1, NULL, 0,
- &result, sizeof(result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token, "0xF002 Claimed Table");
- return 0;
- }
-
- if (result.row_count)
- seq_printf(seq, "# ClaimedTid\n");
-
- for (i = 0; i < result.row_count; i++) {
- seq_printf(seq, "%-2d", i);
- seq_printf(seq, "%#7x\n", result.claimed_tid[i]);
- }
-
- if (result.more_flag)
- seq_printf(seq, "There is more...\n");
-
- return 0;
-}
-
-/* Generic group F003h - User Table (table) */
-static int i2o_seq_show_users(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- int token;
- int i;
-
- typedef struct _i2o_user_table {
- u16 instance;
- u16 user_tid;
- u8 claim_type;
- u8 reserved1;
- u16 reserved2;
- } i2o_user_table;
-
- struct {
- u16 result_count;
- u16 pad;
- u16 block_size;
- u8 block_status;
- u8 error_info_size;
- u16 row_count;
- u16 more_flag;
- i2o_user_table user[64];
- } *result;
-
- result = kmalloc(sizeof(*result), GFP_KERNEL);
- if (!result)
- return -ENOMEM;
-
- token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF003, -1, NULL, 0,
- result, sizeof(*result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token, "0xF003 User Table");
- goto out;
- }
-
- seq_printf(seq, "# Instance UserTid ClaimType\n");
-
- for (i = 0; i < result->row_count; i++) {
- seq_printf(seq, "%-3d", i);
- seq_printf(seq, "%#8x ", result->user[i].instance);
- seq_printf(seq, "%#7x ", result->user[i].user_tid);
- seq_printf(seq, "%#9x\n", result->user[i].claim_type);
- }
-
- if (result->more_flag)
- seq_printf(seq, "There is more...\n");
- out:
- kfree(result);
- return 0;
-}
-
-/* Generic group F005h - Private message extensions (table) (optional) */
-static int i2o_seq_show_priv_msgs(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- int token;
- int i;
-
- typedef struct _i2o_private {
- u16 ext_instance;
- u16 organization_id;
- u16 x_function_code;
- } i2o_private;
-
- struct {
- u16 result_count;
- u16 pad;
- u16 block_size;
- u8 block_status;
- u8 error_info_size;
- u16 row_count;
- u16 more_flag;
- i2o_private extension[64];
- } result;
-
- token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF000, -1, NULL, 0,
- &result, sizeof(result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token,
- "0xF005 Private Message Extensions (optional)");
- return 0;
- }
-
- seq_printf(seq, "Instance# OrgId FunctionCode\n");
-
- for (i = 0; i < result.row_count; i++) {
- seq_printf(seq, "%0#9x ", result.extension[i].ext_instance);
- seq_printf(seq, "%0#6x ", result.extension[i].organization_id);
- seq_printf(seq, "%0#6x", result.extension[i].x_function_code);
-
- seq_printf(seq, "\n");
- }
-
- if (result.more_flag)
- seq_printf(seq, "There is more...\n");
-
- return 0;
-}
-
-/* Generic group F006h - Authorized User Table (table) */
-static int i2o_seq_show_authorized_users(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- int token;
- int i;
-
- struct {
- u16 result_count;
- u16 pad;
- u16 block_size;
- u8 block_status;
- u8 error_info_size;
- u16 row_count;
- u16 more_flag;
- u32 alternate_tid[64];
- } result;
-
- token = i2o_parm_table_get(d, I2O_PARAMS_TABLE_GET, 0xF006, -1, NULL, 0,
- &result, sizeof(result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token,
- "0xF006 Autohorized User Table");
- return 0;
- }
-
- if (result.row_count)
- seq_printf(seq, "# AlternateTid\n");
-
- for (i = 0; i < result.row_count; i++) {
- seq_printf(seq, "%-2d", i);
- seq_printf(seq, "%#7x ", result.alternate_tid[i]);
- }
-
- if (result.more_flag)
- seq_printf(seq, "There is more...\n");
-
- return 0;
-}
-
-/* Generic group F100h - Device Identity (scalar) */
-static int i2o_seq_show_dev_identity(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- static u32 work32[128]; // allow for "stuff" + up to 256 byte (max) serial number
- // == (allow) 512d bytes (max)
- static u16 *work16 = (u16 *) work32;
- int token;
- char tmp[16 + 1];
-
- token = i2o_parm_field_get(d, 0xF100, -1, &work32, sizeof(work32));
-
- if (token < 0) {
- i2o_report_query_status(seq, token, "0xF100 Device Identity");
- return 0;
- }
-
- seq_printf(seq, "Device Class : %s\n", i2o_get_class_name(work16[0]));
- seq_printf(seq, "Owner TID : %0#5x\n", work16[2]);
- seq_printf(seq, "Parent TID : %0#5x\n", work16[3]);
- seq_printf(seq, "Vendor info : %s\n",
- chtostr(tmp, (u8 *) (work32 + 2), 16));
- seq_printf(seq, "Product info : %s\n",
- chtostr(tmp, (u8 *) (work32 + 6), 16));
- seq_printf(seq, "Description : %s\n",
- chtostr(tmp, (u8 *) (work32 + 10), 16));
- seq_printf(seq, "Product rev. : %s\n",
- chtostr(tmp, (u8 *) (work32 + 14), 8));
-
- seq_printf(seq, "Serial number : ");
- print_serial_number(seq, (u8 *) (work32 + 16),
- /* allow for SNLen plus
- * possible trailing '\0'
- */
- sizeof(work32) - (16 * sizeof(u32)) - 2);
- seq_printf(seq, "\n");
-
- return 0;
-}
-
-static int i2o_seq_show_dev_name(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
-
- seq_printf(seq, "%s\n", dev_name(&d->device));
-
- return 0;
-}
-
-/* Generic group F101h - DDM Identity (scalar) */
-static int i2o_seq_show_ddm_identity(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- int token;
-
- struct {
- u16 ddm_tid;
- u8 module_name[24];
- u8 module_rev[8];
- u8 sn_format;
- u8 serial_number[12];
- u8 pad[256]; // allow up to 256 byte (max) serial number
- } result;
-
- char tmp[24 + 1];
-
- token = i2o_parm_field_get(d, 0xF101, -1, &result, sizeof(result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token, "0xF101 DDM Identity");
- return 0;
- }
-
- seq_printf(seq, "Registering DDM TID : 0x%03x\n", result.ddm_tid);
- seq_printf(seq, "Module name : %s\n",
- chtostr(tmp, result.module_name, 24));
- seq_printf(seq, "Module revision : %s\n",
- chtostr(tmp, result.module_rev, 8));
-
- seq_printf(seq, "Serial number : ");
- print_serial_number(seq, result.serial_number, sizeof(result) - 36);
- /* allow for SNLen plus possible trailing '\0' */
-
- seq_printf(seq, "\n");
-
- return 0;
-}
-
-/* Generic group F102h - User Information (scalar) */
-static int i2o_seq_show_uinfo(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- int token;
-
- struct {
- u8 device_name[64];
- u8 service_name[64];
- u8 physical_location[64];
- u8 instance_number[4];
- } result;
-
- char tmp[64 + 1];
-
- token = i2o_parm_field_get(d, 0xF102, -1, &result, sizeof(result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token, "0xF102 User Information");
- return 0;
- }
-
- seq_printf(seq, "Device name : %s\n",
- chtostr(tmp, result.device_name, 64));
- seq_printf(seq, "Service name : %s\n",
- chtostr(tmp, result.service_name, 64));
- seq_printf(seq, "Physical name : %s\n",
- chtostr(tmp, result.physical_location, 64));
- seq_printf(seq, "Instance number : %s\n",
- chtostr(tmp, result.instance_number, 4));
-
- return 0;
-}
-
-/* Generic group F103h - SGL Operating Limits (scalar) */
-static int i2o_seq_show_sgl_limits(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- static u32 work32[12];
- static u16 *work16 = (u16 *) work32;
- static u8 *work8 = (u8 *) work32;
- int token;
-
- token = i2o_parm_field_get(d, 0xF103, -1, &work32, sizeof(work32));
-
- if (token < 0) {
- i2o_report_query_status(seq, token,
- "0xF103 SGL Operating Limits");
- return 0;
- }
-
- seq_printf(seq, "SGL chain size : %d\n", work32[0]);
- seq_printf(seq, "Max SGL chain size : %d\n", work32[1]);
- seq_printf(seq, "SGL chain size target : %d\n", work32[2]);
- seq_printf(seq, "SGL frag count : %d\n", work16[6]);
- seq_printf(seq, "Max SGL frag count : %d\n", work16[7]);
- seq_printf(seq, "SGL frag count target : %d\n", work16[8]);
-
-/* FIXME
- if (d->i2oversion == 0x02)
- {
-*/
- seq_printf(seq, "SGL data alignment : %d\n", work16[8]);
- seq_printf(seq, "SGL addr limit : %d\n", work8[20]);
- seq_printf(seq, "SGL addr sizes supported : ");
- if (work8[21] & 0x01)
- seq_printf(seq, "32 bit ");
- if (work8[21] & 0x02)
- seq_printf(seq, "64 bit ");
- if (work8[21] & 0x04)
- seq_printf(seq, "96 bit ");
- if (work8[21] & 0x08)
- seq_printf(seq, "128 bit ");
- seq_printf(seq, "\n");
-/*
- }
-*/
-
- return 0;
-}
-
-/* Generic group F200h - Sensors (scalar) */
-static int i2o_seq_show_sensors(struct seq_file *seq, void *v)
-{
- struct i2o_device *d = (struct i2o_device *)seq->private;
- int token;
-
- struct {
- u16 sensor_instance;
- u8 component;
- u16 component_instance;
- u8 sensor_class;
- u8 sensor_type;
- u8 scaling_exponent;
- u32 actual_reading;
- u32 minimum_reading;
- u32 low2lowcat_treshold;
- u32 lowcat2low_treshold;
- u32 lowwarn2low_treshold;
- u32 low2lowwarn_treshold;
- u32 norm2lowwarn_treshold;
- u32 lowwarn2norm_treshold;
- u32 nominal_reading;
- u32 hiwarn2norm_treshold;
- u32 norm2hiwarn_treshold;
- u32 high2hiwarn_treshold;
- u32 hiwarn2high_treshold;
- u32 hicat2high_treshold;
- u32 hi2hicat_treshold;
- u32 maximum_reading;
- u8 sensor_state;
- u16 event_enable;
- } result;
-
- token = i2o_parm_field_get(d, 0xF200, -1, &result, sizeof(result));
-
- if (token < 0) {
- i2o_report_query_status(seq, token,
- "0xF200 Sensors (optional)");
- return 0;
- }
-
- seq_printf(seq, "Sensor instance : %d\n", result.sensor_instance);
-
- seq_printf(seq, "Component : %d = ", result.component);
- switch (result.component) {
- case 0:
- seq_printf(seq, "Other");
- break;
- case 1:
- seq_printf(seq, "Planar logic Board");
- break;
- case 2:
- seq_printf(seq, "CPU");
- break;
- case 3:
- seq_printf(seq, "Chassis");
- break;
- case 4:
- seq_printf(seq, "Power Supply");
- break;
- case 5:
- seq_printf(seq, "Storage");
- break;
- case 6:
- seq_printf(seq, "External");
- break;
- }
- seq_printf(seq, "\n");
-
- seq_printf(seq, "Component instance : %d\n",
- result.component_instance);
- seq_printf(seq, "Sensor class : %s\n",
- result.sensor_class ? "Analog" : "Digital");
-
- seq_printf(seq, "Sensor type : %d = ", result.sensor_type);
- switch (result.sensor_type) {
- case 0:
- seq_printf(seq, "Other\n");
- break;
- case 1:
- seq_printf(seq, "Thermal\n");
- break;
- case 2:
- seq_printf(seq, "DC voltage (DC volts)\n");
- break;
- case 3:
- seq_printf(seq, "AC voltage (AC volts)\n");
- break;
- case 4:
- seq_printf(seq, "DC current (DC amps)\n");
- break;
- case 5:
- seq_printf(seq, "AC current (AC volts)\n");
- break;
- case 6:
- seq_printf(seq, "Door open\n");
- break;
- case 7:
- seq_printf(seq, "Fan operational\n");
- break;
- }
-
- seq_printf(seq, "Scaling exponent : %d\n",
- result.scaling_exponent);
- seq_printf(seq, "Actual reading : %d\n", result.actual_reading);
- seq_printf(seq, "Minimum reading : %d\n", result.minimum_reading);
- seq_printf(seq, "Low2LowCat treshold : %d\n",
- result.low2lowcat_treshold);
- seq_printf(seq, "LowCat2Low treshold : %d\n",
- result.lowcat2low_treshold);
- seq_printf(seq, "LowWarn2Low treshold : %d\n",
- result.lowwarn2low_treshold);
- seq_printf(seq, "Low2LowWarn treshold : %d\n",
- result.low2lowwarn_treshold);
- seq_printf(seq, "Norm2LowWarn treshold : %d\n",
- result.norm2lowwarn_treshold);
- seq_printf(seq, "LowWarn2Norm treshold : %d\n",
- result.lowwarn2norm_treshold);
- seq_printf(seq, "Nominal reading : %d\n", result.nominal_reading);
- seq_printf(seq, "HiWarn2Norm treshold : %d\n",
- result.hiwarn2norm_treshold);
- seq_printf(seq, "Norm2HiWarn treshold : %d\n",
- result.norm2hiwarn_treshold);
- seq_printf(seq, "High2HiWarn treshold : %d\n",
- result.high2hiwarn_treshold);
- seq_printf(seq, "HiWarn2High treshold : %d\n",
- result.hiwarn2high_treshold);
- seq_printf(seq, "HiCat2High treshold : %d\n",
- result.hicat2high_treshold);
- seq_printf(seq, "High2HiCat treshold : %d\n",
- result.hi2hicat_treshold);
- seq_printf(seq, "Maximum reading : %d\n", result.maximum_reading);
-
- seq_printf(seq, "Sensor state : %d = ", result.sensor_state);
- switch (result.sensor_state) {
- case 0:
- seq_printf(seq, "Normal\n");
- break;
- case 1:
- seq_printf(seq, "Abnormal\n");
- break;
- case 2:
- seq_printf(seq, "Unknown\n");
- break;
- case 3:
- seq_printf(seq, "Low Catastrophic (LoCat)\n");
- break;
- case 4:
- seq_printf(seq, "Low (Low)\n");
- break;
- case 5:
- seq_printf(seq, "Low Warning (LoWarn)\n");
- break;
- case 6:
- seq_printf(seq, "High Warning (HiWarn)\n");
- break;
- case 7:
- seq_printf(seq, "High (High)\n");
- break;
- case 8:
- seq_printf(seq, "High Catastrophic (HiCat)\n");
- break;
- }
-
- seq_printf(seq, "Event_enable : 0x%02X\n", result.event_enable);
- seq_printf(seq, " [%s] Operational state change. \n",
- (result.event_enable & 0x01) ? "+" : "-");
- seq_printf(seq, " [%s] Low catastrophic. \n",
- (result.event_enable & 0x02) ? "+" : "-");
- seq_printf(seq, " [%s] Low reading. \n",
- (result.event_enable & 0x04) ? "+" : "-");
- seq_printf(seq, " [%s] Low warning. \n",
- (result.event_enable & 0x08) ? "+" : "-");
- seq_printf(seq,
- " [%s] Change back to normal from out of range state. \n",
- (result.event_enable & 0x10) ? "+" : "-");
- seq_printf(seq, " [%s] High warning. \n",
- (result.event_enable & 0x20) ? "+" : "-");
- seq_printf(seq, " [%s] High reading. \n",
- (result.event_enable & 0x40) ? "+" : "-");
- seq_printf(seq, " [%s] High catastrophic. \n",
- (result.event_enable & 0x80) ? "+" : "-");
-
- return 0;
-}
-
-static int i2o_seq_open_hrt(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_hrt, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_lct(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_lct, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_status(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_status, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_hw(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_hw, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_ddm_table(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_ddm_table, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_driver_store(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_driver_store, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_drivers_stored(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_drivers_stored, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_groups(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_groups, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_phys_device(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_phys_device, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_claimed(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_claimed, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_users(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_users, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_priv_msgs(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_priv_msgs, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_authorized_users(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_authorized_users,
- PDE_DATA(inode));
-};
-
-static int i2o_seq_open_dev_identity(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_dev_identity, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_ddm_identity(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_ddm_identity, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_uinfo(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_uinfo, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_sgl_limits(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_sgl_limits, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_sensors(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_sensors, PDE_DATA(inode));
-};
-
-static int i2o_seq_open_dev_name(struct inode *inode, struct file *file)
-{
- return single_open(file, i2o_seq_show_dev_name, PDE_DATA(inode));
-};
-
-static const struct file_operations i2o_seq_fops_lct = {
- .open = i2o_seq_open_lct,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_hrt = {
- .open = i2o_seq_open_hrt,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_status = {
- .open = i2o_seq_open_status,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_hw = {
- .open = i2o_seq_open_hw,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_ddm_table = {
- .open = i2o_seq_open_ddm_table,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_driver_store = {
- .open = i2o_seq_open_driver_store,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_drivers_stored = {
- .open = i2o_seq_open_drivers_stored,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_groups = {
- .open = i2o_seq_open_groups,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_phys_device = {
- .open = i2o_seq_open_phys_device,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_claimed = {
- .open = i2o_seq_open_claimed,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_users = {
- .open = i2o_seq_open_users,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_priv_msgs = {
- .open = i2o_seq_open_priv_msgs,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_authorized_users = {
- .open = i2o_seq_open_authorized_users,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_dev_name = {
- .open = i2o_seq_open_dev_name,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_dev_identity = {
- .open = i2o_seq_open_dev_identity,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_ddm_identity = {
- .open = i2o_seq_open_ddm_identity,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_uinfo = {
- .open = i2o_seq_open_uinfo,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_sgl_limits = {
- .open = i2o_seq_open_sgl_limits,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static const struct file_operations i2o_seq_fops_sensors = {
- .open = i2o_seq_open_sensors,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-/*
- * IOP specific entries...write field just in case someone
- * ever wants one.
- */
-static i2o_proc_entry i2o_proc_generic_iop_entries[] = {
- {"hrt", S_IFREG | S_IRUGO, &i2o_seq_fops_hrt},
- {"lct", S_IFREG | S_IRUGO, &i2o_seq_fops_lct},
- {"status", S_IFREG | S_IRUGO, &i2o_seq_fops_status},
- {"hw", S_IFREG | S_IRUGO, &i2o_seq_fops_hw},
- {"ddm_table", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_table},
- {"driver_store", S_IFREG | S_IRUGO, &i2o_seq_fops_driver_store},
- {"drivers_stored", S_IFREG | S_IRUGO, &i2o_seq_fops_drivers_stored},
- {NULL, 0, NULL}
-};
-
-/*
- * Device specific entries
- */
-static i2o_proc_entry generic_dev_entries[] = {
- {"groups", S_IFREG | S_IRUGO, &i2o_seq_fops_groups},
- {"phys_dev", S_IFREG | S_IRUGO, &i2o_seq_fops_phys_device},
- {"claimed", S_IFREG | S_IRUGO, &i2o_seq_fops_claimed},
- {"users", S_IFREG | S_IRUGO, &i2o_seq_fops_users},
- {"priv_msgs", S_IFREG | S_IRUGO, &i2o_seq_fops_priv_msgs},
- {"authorized_users", S_IFREG | S_IRUGO, &i2o_seq_fops_authorized_users},
- {"dev_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_identity},
- {"ddm_identity", S_IFREG | S_IRUGO, &i2o_seq_fops_ddm_identity},
- {"user_info", S_IFREG | S_IRUGO, &i2o_seq_fops_uinfo},
- {"sgl_limits", S_IFREG | S_IRUGO, &i2o_seq_fops_sgl_limits},
- {"sensors", S_IFREG | S_IRUGO, &i2o_seq_fops_sensors},
- {NULL, 0, NULL}
-};
-
-/*
- * Storage unit specific entries (SCSI Periph, BS) with device names
- */
-static i2o_proc_entry rbs_dev_entries[] = {
- {"dev_name", S_IFREG | S_IRUGO, &i2o_seq_fops_dev_name},
- {NULL, 0, NULL}
-};
-
-/**
- * i2o_proc_create_entries - Creates proc dir entries
- * @dir: proc dir entry under which the entries should be placed
- * @i2o_pe: pointer to the entries which should be added
- * @data: pointer to I2O controller or device
- *
- * Create proc dir entries for a I2O controller or I2O device.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_proc_create_entries(struct proc_dir_entry *dir,
- i2o_proc_entry * i2o_pe, void *data)
-{
- struct proc_dir_entry *tmp;
-
- while (i2o_pe->name) {
- tmp = proc_create_data(i2o_pe->name, i2o_pe->mode, dir,
- i2o_pe->fops, data);
- if (!tmp)
- return -1;
-
- i2o_pe++;
- }
-
- return 0;
-}
-
-/**
- * i2o_proc_device_add - Add an I2O device to the proc dir
- * @dir: proc dir entry to which the device should be added
- * @dev: I2O device which should be added
- *
- * Add an I2O device to the proc dir entry dir and create the entries for
- * the device depending on the class of the I2O device.
- */
-static void i2o_proc_device_add(struct proc_dir_entry *dir,
- struct i2o_device *dev)
-{
- char buff[10];
- struct proc_dir_entry *devdir;
- i2o_proc_entry *i2o_pe = NULL;
-
- sprintf(buff, "%03x", dev->lct_data.tid);
-
- osm_debug("adding device /proc/i2o/%s/%s\n", dev->iop->name, buff);
-
- devdir = proc_mkdir_data(buff, 0, dir, dev);
- if (!devdir) {
- osm_warn("Could not allocate procdir!\n");
- return;
- }
-
- i2o_proc_create_entries(devdir, generic_dev_entries, dev);
-
- /* Inform core that we want updates about this device's status */
- switch (dev->lct_data.class_id) {
- case I2O_CLASS_SCSI_PERIPHERAL:
- case I2O_CLASS_RANDOM_BLOCK_STORAGE:
- i2o_pe = rbs_dev_entries;
- break;
- default:
- break;
- }
- if (i2o_pe)
- i2o_proc_create_entries(devdir, i2o_pe, dev);
-}
-
-/**
- * i2o_proc_iop_add - Add an I2O controller to the i2o proc tree
- * @dir: parent proc dir entry
- * @c: I2O controller which should be added
- *
- * Add the entries to the parent proc dir entry. Also each device is added
- * to the controllers proc dir entry.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_proc_iop_add(struct proc_dir_entry *dir,
- struct i2o_controller *c)
-{
- struct proc_dir_entry *iopdir;
- struct i2o_device *dev;
-
- osm_debug("adding IOP /proc/i2o/%s\n", c->name);
-
- iopdir = proc_mkdir_data(c->name, 0, dir, c);
- if (!iopdir)
- return -1;
-
- i2o_proc_create_entries(iopdir, i2o_proc_generic_iop_entries, c);
-
- list_for_each_entry(dev, &c->devices, list)
- i2o_proc_device_add(iopdir, dev);
-
- return 0;
-}
-
-/**
- * i2o_proc_fs_create - Create the i2o proc fs.
- *
- * Iterate over each I2O controller and create the entries for it.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int __init i2o_proc_fs_create(void)
-{
- struct i2o_controller *c;
-
- i2o_proc_dir_root = proc_mkdir("i2o", NULL);
- if (!i2o_proc_dir_root)
- return -1;
-
- list_for_each_entry(c, &i2o_controllers, list)
- i2o_proc_iop_add(i2o_proc_dir_root, c);
-
- return 0;
-};
-
-/**
- * i2o_proc_fs_destroy - Cleanup the all i2o proc entries
- *
- * Iterate over each I2O controller and remove the entries for it.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int __exit i2o_proc_fs_destroy(void)
-{
- remove_proc_subtree("i2o", NULL);
-
- return 0;
-};
-
-/**
- * i2o_proc_init - Init function for procfs
- *
- * Registers Proc OSM and creates procfs entries.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int __init i2o_proc_init(void)
-{
- int rc;
-
- printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
-
- rc = i2o_driver_register(&i2o_proc_driver);
- if (rc)
- return rc;
-
- rc = i2o_proc_fs_create();
- if (rc) {
- i2o_driver_unregister(&i2o_proc_driver);
- return rc;
- }
-
- return 0;
-};
-
-/**
- * i2o_proc_exit - Exit function for procfs
- *
- * Unregisters Proc OSM and removes procfs entries.
- */
-static void __exit i2o_proc_exit(void)
-{
- i2o_driver_unregister(&i2o_proc_driver);
- i2o_proc_fs_destroy();
-};
-
-MODULE_AUTHOR("Deepak Saxena");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(OSM_DESCRIPTION);
-MODULE_VERSION(OSM_VERSION);
-
-module_init(i2o_proc_init);
-module_exit(i2o_proc_exit);
+++ /dev/null
-/*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * For the avoidance of doubt the "preferred form" of this code is one which
- * is in an open non patent encumbered format. Where cryptographic key signing
- * forms part of the process of creating an executable the information
- * including keys needed to generate an equivalently functional executable
- * are deemed to be part of the source code.
- *
- * Complications for I2O scsi
- *
- * o Each (bus,lun) is a logical device in I2O. We keep a map
- * table. We spoof failed selection for unmapped units
- * o Request sense buffers can come back for free.
- * o Scatter gather is a bit dynamic. We have to investigate at
- * setup time.
- * o Some of our resources are dynamically shared. The i2o core
- * needs a message reservation protocol to avoid swap v net
- * deadlocking. We need to back off queue requests.
- *
- * In general the firmware wants to help. Where its help isn't performance
- * useful we just ignore the aid. Its not worth the code in truth.
- *
- * Fixes/additions:
- * Steve Ralston:
- * Scatter gather now works
- * Markus Lidel <Markus.Lidel@shadowconnect.com>:
- * Minor fixes for 2.6.
- *
- * To Do:
- * 64bit cleanups
- * Fix the resource management problems.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/jiffies.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/proc_fs.h>
-#include <linux/prefetch.h>
-#include <linux/pci.h>
-#include <linux/blkdev.h>
-#include "i2o.h"
-#include <linux/scatterlist.h>
-
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <linux/atomic.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/sg.h>
-
-#define OSM_NAME "scsi-osm"
-#define OSM_VERSION "1.316"
-#define OSM_DESCRIPTION "I2O SCSI Peripheral OSM"
-
-static struct i2o_driver i2o_scsi_driver;
-
-static unsigned int i2o_scsi_max_id = 16;
-static unsigned int i2o_scsi_max_lun = 255;
-
-struct i2o_scsi_host {
- struct Scsi_Host *scsi_host; /* pointer to the SCSI host */
- struct i2o_controller *iop; /* pointer to the I2O controller */
- u64 lun; /* lun's used for block devices */
- struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */
-};
-
-static struct scsi_host_template i2o_scsi_host_template;
-
-#define I2O_SCSI_CAN_QUEUE 4
-
-/* SCSI OSM class handling definition */
-static struct i2o_class_id i2o_scsi_class_id[] = {
- {I2O_CLASS_SCSI_PERIPHERAL},
- {I2O_CLASS_END}
-};
-
-static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c)
-{
- struct i2o_scsi_host *i2o_shost;
- struct i2o_device *i2o_dev;
- struct Scsi_Host *scsi_host;
- int max_channel = 0;
- u8 type;
- int i;
- size_t size;
- u16 body_size = 6;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec)
- body_size = 8;
-#endif
-
- list_for_each_entry(i2o_dev, &c->devices, list)
- if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
- if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
- && (type == 0x01)) /* SCSI bus */
- max_channel++;
- }
-
- if (!max_channel) {
- osm_warn("no channels found on %s\n", c->name);
- return ERR_PTR(-EFAULT);
- }
-
- size = max_channel * sizeof(struct i2o_device *)
- + sizeof(struct i2o_scsi_host);
-
- scsi_host = scsi_host_alloc(&i2o_scsi_host_template, size);
- if (!scsi_host) {
- osm_warn("Could not allocate SCSI host\n");
- return ERR_PTR(-ENOMEM);
- }
-
- scsi_host->max_channel = max_channel - 1;
- scsi_host->max_id = i2o_scsi_max_id;
- scsi_host->max_lun = i2o_scsi_max_lun;
- scsi_host->this_id = c->unit;
- scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size);
-
- i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata;
- i2o_shost->scsi_host = scsi_host;
- i2o_shost->iop = c;
- i2o_shost->lun = 1;
-
- i = 0;
- list_for_each_entry(i2o_dev, &c->devices, list)
- if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) {
- if (!i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1)
- && (type == 0x01)) /* only SCSI bus */
- i2o_shost->channel[i++] = i2o_dev;
-
- if (i >= max_channel)
- break;
- }
-
- return i2o_shost;
-};
-
-/**
- * i2o_scsi_get_host - Get an I2O SCSI host
- * @c: I2O controller to for which to get the SCSI host
- *
- * If the I2O controller already exists as SCSI host, the SCSI host
- * is returned, otherwise the I2O controller is added to the SCSI
- * core.
- *
- * Returns pointer to the I2O SCSI host on success or NULL on failure.
- */
-static struct i2o_scsi_host *i2o_scsi_get_host(struct i2o_controller *c)
-{
- return c->driver_data[i2o_scsi_driver.context];
-};
-
-/**
- * i2o_scsi_remove - Remove I2O device from SCSI core
- * @dev: device which should be removed
- *
- * Removes the I2O device from the SCSI core again.
- *
- * Returns 0 on success.
- */
-static int i2o_scsi_remove(struct device *dev)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
- struct i2o_controller *c = i2o_dev->iop;
- struct i2o_scsi_host *i2o_shost;
- struct scsi_device *scsi_dev;
-
- osm_info("device removed (TID: %03x)\n", i2o_dev->lct_data.tid);
-
- i2o_shost = i2o_scsi_get_host(c);
-
- shost_for_each_device(scsi_dev, i2o_shost->scsi_host)
- if (scsi_dev->hostdata == i2o_dev) {
- sysfs_remove_link(&i2o_dev->device.kobj, "scsi");
- scsi_remove_device(scsi_dev);
- scsi_device_put(scsi_dev);
- break;
- }
-
- return 0;
-};
-
-/**
- * i2o_scsi_probe - verify if dev is a I2O SCSI device and install it
- * @dev: device to verify if it is a I2O SCSI device
- *
- * Retrieve channel, id and lun for I2O device. If everything goes well
- * register the I2O device as SCSI device on the I2O SCSI controller.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_scsi_probe(struct device *dev)
-{
- struct i2o_device *i2o_dev = to_i2o_device(dev);
- struct i2o_controller *c = i2o_dev->iop;
- struct i2o_scsi_host *i2o_shost;
- struct Scsi_Host *scsi_host;
- struct i2o_device *parent;
- struct scsi_device *scsi_dev;
- u32 id = -1;
- u64 lun = -1;
- int channel = -1;
- int i, rc;
-
- i2o_shost = i2o_scsi_get_host(c);
- if (!i2o_shost)
- return -EFAULT;
-
- scsi_host = i2o_shost->scsi_host;
-
- switch (i2o_dev->lct_data.class_id) {
- case I2O_CLASS_RANDOM_BLOCK_STORAGE:
- case I2O_CLASS_EXECUTIVE:
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- u8 type;
- struct i2o_device *d = i2o_shost->channel[0];
-
- if (!i2o_parm_field_get(d, 0x0000, 0, &type, 1)
- && (type == 0x01)) /* SCSI bus */
- if (!i2o_parm_field_get(d, 0x0200, 4, &id, 4)) {
- channel = 0;
- if (i2o_dev->lct_data.class_id ==
- I2O_CLASS_RANDOM_BLOCK_STORAGE)
- lun =
- cpu_to_le64(i2o_shost->
- lun++);
- else
- lun = 0;
- }
- }
-#endif
- break;
-
- case I2O_CLASS_SCSI_PERIPHERAL:
- if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4))
- return -EFAULT;
-
- if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8))
- return -EFAULT;
-
- parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid);
- if (!parent) {
- osm_warn("can not find parent of device %03x\n",
- i2o_dev->lct_data.tid);
- return -EFAULT;
- }
-
- for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++)
- if (i2o_shost->channel[i] == parent)
- channel = i;
- break;
-
- default:
- return -EFAULT;
- }
-
- if (channel == -1) {
- osm_warn("can not find channel of device %03x\n",
- i2o_dev->lct_data.tid);
- return -EFAULT;
- }
-
- if (le32_to_cpu(id) >= scsi_host->max_id) {
- osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)",
- le32_to_cpu(id), scsi_host->max_id);
- return -EFAULT;
- }
-
- if (le64_to_cpu(lun) >= scsi_host->max_lun) {
- osm_warn("SCSI device lun (%llu) >= max_lun of I2O host (%llu)",
- le64_to_cpu(lun), scsi_host->max_lun);
- return -EFAULT;
- }
-
- scsi_dev =
- __scsi_add_device(i2o_shost->scsi_host, channel, le32_to_cpu(id),
- le64_to_cpu(lun), i2o_dev);
-
- if (IS_ERR(scsi_dev)) {
- osm_warn("can not add SCSI device %03x\n",
- i2o_dev->lct_data.tid);
- return PTR_ERR(scsi_dev);
- }
-
- rc = sysfs_create_link(&i2o_dev->device.kobj,
- &scsi_dev->sdev_gendev.kobj, "scsi");
- if (rc)
- goto err;
-
- osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %llu\n",
- i2o_dev->lct_data.tid, channel, le32_to_cpu(id),
- le64_to_cpu(lun));
-
- return 0;
-
-err:
- scsi_remove_device(scsi_dev);
- return rc;
-};
-
-static const char *i2o_scsi_info(struct Scsi_Host *SChost)
-{
- struct i2o_scsi_host *hostdata;
- hostdata = (struct i2o_scsi_host *)SChost->hostdata;
- return hostdata->iop->name;
-}
-
-/**
- * i2o_scsi_reply - SCSI OSM message reply handler
- * @c: controller issuing the reply
- * @m: message id for flushing
- * @msg: the message from the controller
- *
- * Process reply messages (interrupts in normal scsi controller think).
- * We can get a variety of messages to process. The normal path is
- * scsi command completions. We must also deal with IOP failures,
- * the reply to a bus reset and the reply to a LUN query.
- *
- * Returns 0 on success and if the reply should not be flushed or > 0
- * on success and if the reply should be flushed. Returns negative error
- * code on failure and if the reply should be flushed.
- */
-static int i2o_scsi_reply(struct i2o_controller *c, u32 m,
- struct i2o_message *msg)
-{
- struct scsi_cmnd *cmd;
- u32 error;
- struct device *dev;
-
- cmd = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));
- if (unlikely(!cmd)) {
- osm_err("NULL reply received!\n");
- return -1;
- }
-
- /*
- * Low byte is device status, next is adapter status,
- * (then one byte reserved), then request status.
- */
- error = le32_to_cpu(msg->body[0]);
-
- osm_debug("Completed %0x%p\n", cmd);
-
- cmd->result = error & 0xff;
- /*
- * if DeviceStatus is not SCSI_SUCCESS copy over the sense data and let
- * the SCSI layer handle the error
- */
- if (cmd->result)
- memcpy(cmd->sense_buffer, &msg->body[3],
- min(SCSI_SENSE_BUFFERSIZE, 40));
-
- /* only output error code if AdapterStatus is not HBA_SUCCESS */
- if ((error >> 8) & 0xff)
- osm_err("SCSI error %08x\n", error);
-
- dev = &c->pdev->dev;
-
- scsi_dma_unmap(cmd);
-
- cmd->scsi_done(cmd);
-
- return 1;
-};
-
-/**
- * i2o_scsi_notify_device_add - Retrieve notifications of added devices
- * @i2o_dev: the I2O device which was added
- *
- * If a I2O device is added we catch the notification, because I2O classes
- * other than SCSI peripheral will not be received through
- * i2o_scsi_probe().
- */
-static void i2o_scsi_notify_device_add(struct i2o_device *i2o_dev)
-{
- switch (i2o_dev->lct_data.class_id) {
- case I2O_CLASS_EXECUTIVE:
- case I2O_CLASS_RANDOM_BLOCK_STORAGE:
- i2o_scsi_probe(&i2o_dev->device);
- break;
-
- default:
- break;
- }
-};
-
-/**
- * i2o_scsi_notify_device_remove - Retrieve notifications of removed devices
- * @i2o_dev: the I2O device which was removed
- *
- * If a I2O device is removed, we catch the notification to remove the
- * corresponding SCSI device.
- */
-static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev)
-{
- switch (i2o_dev->lct_data.class_id) {
- case I2O_CLASS_EXECUTIVE:
- case I2O_CLASS_RANDOM_BLOCK_STORAGE:
- i2o_scsi_remove(&i2o_dev->device);
- break;
-
- default:
- break;
- }
-};
-
-/**
- * i2o_scsi_notify_controller_add - Retrieve notifications of added controllers
- * @c: the controller which was added
- *
- * If a I2O controller is added, we catch the notification to add a
- * corresponding Scsi_Host.
- */
-static void i2o_scsi_notify_controller_add(struct i2o_controller *c)
-{
- struct i2o_scsi_host *i2o_shost;
- int rc;
-
- i2o_shost = i2o_scsi_host_alloc(c);
- if (IS_ERR(i2o_shost)) {
- osm_err("Could not initialize SCSI host\n");
- return;
- }
-
- rc = scsi_add_host(i2o_shost->scsi_host, &c->device);
- if (rc) {
- osm_err("Could not add SCSI host\n");
- scsi_host_put(i2o_shost->scsi_host);
- return;
- }
-
- c->driver_data[i2o_scsi_driver.context] = i2o_shost;
-
- osm_debug("new I2O SCSI host added\n");
-};
-
-/**
- * i2o_scsi_notify_controller_remove - Retrieve notifications of removed controllers
- * @c: the controller which was removed
- *
- * If a I2O controller is removed, we catch the notification to remove the
- * corresponding Scsi_Host.
- */
-static void i2o_scsi_notify_controller_remove(struct i2o_controller *c)
-{
- struct i2o_scsi_host *i2o_shost;
- i2o_shost = i2o_scsi_get_host(c);
- if (!i2o_shost)
- return;
-
- c->driver_data[i2o_scsi_driver.context] = NULL;
-
- scsi_remove_host(i2o_shost->scsi_host);
- scsi_host_put(i2o_shost->scsi_host);
- osm_debug("I2O SCSI host removed\n");
-};
-
-/* SCSI OSM driver struct */
-static struct i2o_driver i2o_scsi_driver = {
- .name = OSM_NAME,
- .reply = i2o_scsi_reply,
- .classes = i2o_scsi_class_id,
- .notify_device_add = i2o_scsi_notify_device_add,
- .notify_device_remove = i2o_scsi_notify_device_remove,
- .notify_controller_add = i2o_scsi_notify_controller_add,
- .notify_controller_remove = i2o_scsi_notify_controller_remove,
- .driver = {
- .probe = i2o_scsi_probe,
- .remove = i2o_scsi_remove,
- },
-};
-
-/**
- * i2o_scsi_queuecommand - queue a SCSI command
- * @SCpnt: scsi command pointer
- * @done: callback for completion
- *
- * Issue a scsi command asynchronously. Return 0 on success or 1 if
- * we hit an error (normally message queue congestion). The only
- * minor complication here is that I2O deals with the device addressing
- * so we have to map the bus/dev/lun back to an I2O handle as well
- * as faking absent devices ourself.
- *
- * Locks: takes the controller lock on error path only
- */
-
-static int i2o_scsi_queuecommand_lck(struct scsi_cmnd *SCpnt,
- void (*done) (struct scsi_cmnd *))
-{
- struct i2o_controller *c;
- struct i2o_device *i2o_dev;
- int tid;
- struct i2o_message *msg;
- /*
- * ENABLE_DISCONNECT
- * SIMPLE_TAG
- * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME
- */
- u32 scsi_flags = 0x20a00000;
- u32 sgl_offset;
- u32 *mptr;
- u32 cmd = I2O_CMD_SCSI_EXEC << 24;
- int rc = 0;
-
- /*
- * Do the incoming paperwork
- */
- i2o_dev = SCpnt->device->hostdata;
-
- SCpnt->scsi_done = done;
-
- if (unlikely(!i2o_dev)) {
- osm_warn("no I2O device in request\n");
- SCpnt->result = DID_NO_CONNECT << 16;
- done(SCpnt);
- goto exit;
- }
- c = i2o_dev->iop;
- tid = i2o_dev->lct_data.tid;
-
- osm_debug("qcmd: Tid = %03x\n", tid);
- osm_debug("Real scsi messages.\n");
-
- /*
- * Put together a scsi execscb message
- */
- switch (SCpnt->sc_data_direction) {
- case PCI_DMA_NONE:
- /* DATA NO XFER */
- sgl_offset = SGL_OFFSET_0;
- break;
-
- case PCI_DMA_TODEVICE:
- /* DATA OUT (iop-->dev) */
- scsi_flags |= 0x80000000;
- sgl_offset = SGL_OFFSET_10;
- break;
-
- case PCI_DMA_FROMDEVICE:
- /* DATA IN (iop<--dev) */
- scsi_flags |= 0x40000000;
- sgl_offset = SGL_OFFSET_10;
- break;
-
- default:
- /* Unknown - kill the command */
- SCpnt->result = DID_NO_CONNECT << 16;
- done(SCpnt);
- goto exit;
- }
-
- /*
- * Obtain an I2O message. If there are none free then
- * throw it back to the scsi layer
- */
-
- msg = i2o_msg_get(c);
- if (IS_ERR(msg)) {
- rc = SCSI_MLQUEUE_HOST_BUSY;
- goto exit;
- }
-
- mptr = &msg->body[0];
-
-#if 0 /* this code can't work */
-#ifdef CONFIG_I2O_EXT_ADAPTEC
- if (c->adaptec) {
- u32 adpt_flags = 0;
-
- if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) {
- i2o_sg_io_hdr_t __user *usr_ptr =
- ((Sg_request *) (SCpnt->sc_request->
- upper_private_data))->header.
- usr_ptr;
-
- if (usr_ptr)
- get_user(adpt_flags, &usr_ptr->flags);
- }
-
- switch (i2o_dev->lct_data.class_id) {
- case I2O_CLASS_EXECUTIVE:
- case I2O_CLASS_RANDOM_BLOCK_STORAGE:
- /* interpret flag has to be set for executive */
- adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET;
- break;
-
- default:
- break;
- }
-
- /*
- * for Adaptec controllers we use the PRIVATE command, because
- * the normal SCSI EXEC doesn't support all SCSI commands on
- * all controllers (for example READ CAPACITY).
- */
- if (sgl_offset == SGL_OFFSET_10)
- sgl_offset = SGL_OFFSET_12;
- cmd = I2O_CMD_PRIVATE << 24;
- *mptr++ = cpu_to_le32(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC);
- *mptr++ = cpu_to_le32(adpt_flags | tid);
- }
-#endif
-#endif
-
- msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid);
- msg->u.s.icntxt = cpu_to_le32(i2o_scsi_driver.context);
-
- /* We want the SCSI control block back */
- msg->u.s.tcntxt = cpu_to_le32(i2o_cntxt_list_add(c, SCpnt));
-
- /* LSI_920_PCI_QUIRK
- *
- * Intermittant observations of msg frame word data corruption
- * observed on msg[4] after:
- * WRITE, READ-MODIFY-WRITE
- * operations. 19990606 -sralston
- *
- * (Hence we build this word via tag. Its good practice anyway
- * we don't want fetches over PCI needlessly)
- */
-
- /* Attach tags to the devices */
- /* FIXME: implement
- if(SCpnt->device->tagged_supported) {
- if(SCpnt->tag == HEAD_OF_QUEUE_TAG)
- scsi_flags |= 0x01000000;
- else if(SCpnt->tag == ORDERED_QUEUE_TAG)
- scsi_flags |= 0x01800000;
- }
- */
-
- *mptr++ = cpu_to_le32(scsi_flags | SCpnt->cmd_len);
-
- /* Write SCSI command into the message - always 16 byte block */
- memcpy(mptr, SCpnt->cmnd, 16);
- mptr += 4;
-
- if (sgl_offset != SGL_OFFSET_0) {
- /* write size of data addressed by SGL */
- *mptr++ = cpu_to_le32(scsi_bufflen(SCpnt));
-
- /* Now fill in the SGList and command */
-
- if (scsi_sg_count(SCpnt)) {
- if (!i2o_dma_map_sg(c, scsi_sglist(SCpnt),
- scsi_sg_count(SCpnt),
- SCpnt->sc_data_direction, &mptr))
- goto nomem;
- }
- }
-
- /* Stick the headers on */
- msg->u.head[0] =
- cpu_to_le32(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset);
-
- /* Queue the message */
- i2o_msg_post(c, msg);
-
- osm_debug("Issued %0x%p\n", SCpnt);
-
- return 0;
-
- nomem:
- rc = -ENOMEM;
- i2o_msg_nop(c, msg);
-
- exit:
- return rc;
-}
-
-static DEF_SCSI_QCMD(i2o_scsi_queuecommand)
-
-/**
- * i2o_scsi_abort - abort a running command
- * @SCpnt: command to abort
- *
- * Ask the I2O controller to abort a command. This is an asynchrnous
- * process and our callback handler will see the command complete with an
- * aborted message if it succeeds.
- *
- * Returns 0 if the command is successfully aborted or negative error code
- * on failure.
- */
-static int i2o_scsi_abort(struct scsi_cmnd *SCpnt)
-{
- struct i2o_device *i2o_dev;
- struct i2o_controller *c;
- struct i2o_message *msg;
- int tid;
- int status = FAILED;
-
- osm_warn("Aborting command block.\n");
-
- i2o_dev = SCpnt->device->hostdata;
- c = i2o_dev->iop;
- tid = i2o_dev->lct_data.tid;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return SCSI_MLQUEUE_HOST_BUSY;
-
- msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid);
- msg->body[0] = cpu_to_le32(i2o_cntxt_list_get_ptr(c, SCpnt));
-
- if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))
- status = SUCCESS;
-
- return status;
-}
-
-/**
- * i2o_scsi_bios_param - Invent disk geometry
- * @sdev: scsi device
- * @dev: block layer device
- * @capacity: size in sectors
- * @ip: geometry array
- *
- * This is anyone's guess quite frankly. We use the same rules everyone
- * else appears to and hope. It seems to work.
- */
-
-static int i2o_scsi_bios_param(struct scsi_device *sdev,
- struct block_device *dev, sector_t capacity,
- int *ip)
-{
- int size;
-
- size = capacity;
- ip[0] = 64; /* heads */
- ip[1] = 32; /* sectors */
- if ((ip[2] = size >> 11) > 1024) { /* cylinders, test for big disk */
- ip[0] = 255; /* heads */
- ip[1] = 63; /* sectors */
- ip[2] = size / (255 * 63); /* cylinders */
- }
- return 0;
-}
-
-static struct scsi_host_template i2o_scsi_host_template = {
- .proc_name = OSM_NAME,
- .name = OSM_DESCRIPTION,
- .info = i2o_scsi_info,
- .queuecommand = i2o_scsi_queuecommand,
- .eh_abort_handler = i2o_scsi_abort,
- .bios_param = i2o_scsi_bios_param,
- .can_queue = I2O_SCSI_CAN_QUEUE,
- .sg_tablesize = 8,
- .cmd_per_lun = 6,
- .use_clustering = ENABLE_CLUSTERING,
-};
-
-/**
- * i2o_scsi_init - SCSI OSM initialization function
- *
- * Register SCSI OSM into I2O core.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int __init i2o_scsi_init(void)
-{
- int rc;
-
- printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
-
- /* Register SCSI OSM into I2O core */
- rc = i2o_driver_register(&i2o_scsi_driver);
- if (rc) {
- osm_err("Could not register SCSI driver\n");
- return rc;
- }
-
- return 0;
-};
-
-/**
- * i2o_scsi_exit - SCSI OSM exit function
- *
- * Unregisters SCSI OSM from I2O core.
- */
-static void __exit i2o_scsi_exit(void)
-{
- /* Unregister I2O SCSI OSM from I2O core */
- i2o_driver_unregister(&i2o_scsi_driver);
-};
-
-MODULE_AUTHOR("Red Hat Software");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(OSM_DESCRIPTION);
-MODULE_VERSION(OSM_VERSION);
-
-module_init(i2o_scsi_init);
-module_exit(i2o_scsi_exit);
+++ /dev/null
-/*
- * Functions to handle I2O controllers and I2O message handling
- *
- * Copyright (C) 1999-2002 Red Hat Software
- *
- * Written by Alan Cox, Building Number Three Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * A lot of the I2O message side code from this is taken from the
- * Red Creek RCPCI45 adapter driver by Red Creek Communications
- *
- * Fixes/additions:
- * Philipp Rumpf
- * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
- * Deepak Saxena <deepak@plexity.net>
- * Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
- * Alan Cox <alan@lxorguk.ukuu.org.uk>:
- * Ported to Linux 2.5.
- * Markus Lidel <Markus.Lidel@shadowconnect.com>:
- * Minor fixes for 2.6.
- */
-
-#include <linux/module.h>
-#include "i2o.h"
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include "core.h"
-
-#define OSM_NAME "i2o"
-#define OSM_VERSION "1.325"
-#define OSM_DESCRIPTION "I2O subsystem"
-
-/* global I2O controller list */
-LIST_HEAD(i2o_controllers);
-
-/*
- * global I2O System Table. Contains information about all the IOPs in the
- * system. Used to inform IOPs about each others existence.
- */
-static struct i2o_dma i2o_systab;
-
-static int i2o_hrt_get(struct i2o_controller *c);
-
-/**
- * i2o_msg_get_wait - obtain an I2O message from the IOP
- * @c: I2O controller
- * @wait: how long to wait until timeout
- *
- * This function waits up to wait seconds for a message slot to be
- * available.
- *
- * On a success the message is returned and the pointer to the message is
- * set in msg. The returned message is the physical page frame offset
- * address from the read port (see the i2o spec). If no message is
- * available returns I2O_QUEUE_EMPTY and msg is leaved untouched.
- */
-struct i2o_message *i2o_msg_get_wait(struct i2o_controller *c, int wait)
-{
- unsigned long timeout = jiffies + wait * HZ;
- struct i2o_message *msg;
-
- while (IS_ERR(msg = i2o_msg_get(c))) {
- if (time_after(jiffies, timeout)) {
- osm_debug("%s: Timeout waiting for message frame.\n",
- c->name);
- return ERR_PTR(-ETIMEDOUT);
- }
- schedule_timeout_uninterruptible(1);
- }
-
- return msg;
-}
-
-#if BITS_PER_LONG == 64
-/**
- * i2o_cntxt_list_add - Append a pointer to context list and return a id
- * @c: controller to which the context list belong
- * @ptr: pointer to add to the context list
- *
- * Because the context field in I2O is only 32-bit large, on 64-bit the
- * pointer is to large to fit in the context field. The i2o_cntxt_list
- * functions therefore map pointers to context fields.
- *
- * Returns context id > 0 on success or 0 on failure.
- */
-u32 i2o_cntxt_list_add(struct i2o_controller * c, void *ptr)
-{
- struct i2o_context_list_element *entry;
- unsigned long flags;
-
- if (!ptr)
- osm_err("%s: couldn't add NULL pointer to context list!\n",
- c->name);
-
- entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
- if (!entry) {
- osm_err("%s: Could not allocate memory for context list element"
- "\n", c->name);
- return 0;
- }
-
- entry->ptr = ptr;
- entry->timestamp = jiffies;
- INIT_LIST_HEAD(&entry->list);
-
- spin_lock_irqsave(&c->context_list_lock, flags);
-
- if (unlikely(atomic_inc_and_test(&c->context_list_counter)))
- atomic_inc(&c->context_list_counter);
-
- entry->context = atomic_read(&c->context_list_counter);
-
- list_add(&entry->list, &c->context_list);
-
- spin_unlock_irqrestore(&c->context_list_lock, flags);
-
- osm_debug("%s: Add context to list %p -> %d\n", c->name, ptr, context);
-
- return entry->context;
-}
-
-/**
- * i2o_cntxt_list_remove - Remove a pointer from the context list
- * @c: controller to which the context list belong
- * @ptr: pointer which should be removed from the context list
- *
- * Removes a previously added pointer from the context list and returns
- * the matching context id.
- *
- * Returns context id on success or 0 on failure.
- */
-u32 i2o_cntxt_list_remove(struct i2o_controller * c, void *ptr)
-{
- struct i2o_context_list_element *entry;
- u32 context = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&c->context_list_lock, flags);
- list_for_each_entry(entry, &c->context_list, list)
- if (entry->ptr == ptr) {
- list_del(&entry->list);
- context = entry->context;
- kfree(entry);
- break;
- }
- spin_unlock_irqrestore(&c->context_list_lock, flags);
-
- if (!context)
- osm_warn("%s: Could not remove nonexistent ptr %p\n", c->name,
- ptr);
-
- osm_debug("%s: remove ptr from context list %d -> %p\n", c->name,
- context, ptr);
-
- return context;
-}
-
-/**
- * i2o_cntxt_list_get - Get a pointer from the context list and remove it
- * @c: controller to which the context list belong
- * @context: context id to which the pointer belong
- *
- * Returns pointer to the matching context id on success or NULL on
- * failure.
- */
-void *i2o_cntxt_list_get(struct i2o_controller *c, u32 context)
-{
- struct i2o_context_list_element *entry;
- unsigned long flags;
- void *ptr = NULL;
-
- spin_lock_irqsave(&c->context_list_lock, flags);
- list_for_each_entry(entry, &c->context_list, list)
- if (entry->context == context) {
- list_del(&entry->list);
- ptr = entry->ptr;
- kfree(entry);
- break;
- }
- spin_unlock_irqrestore(&c->context_list_lock, flags);
-
- if (!ptr)
- osm_warn("%s: context id %d not found\n", c->name, context);
-
- osm_debug("%s: get ptr from context list %d -> %p\n", c->name, context,
- ptr);
-
- return ptr;
-}
-
-/**
- * i2o_cntxt_list_get_ptr - Get a context id from the context list
- * @c: controller to which the context list belong
- * @ptr: pointer to which the context id should be fetched
- *
- * Returns context id which matches to the pointer on success or 0 on
- * failure.
- */
-u32 i2o_cntxt_list_get_ptr(struct i2o_controller * c, void *ptr)
-{
- struct i2o_context_list_element *entry;
- u32 context = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&c->context_list_lock, flags);
- list_for_each_entry(entry, &c->context_list, list)
- if (entry->ptr == ptr) {
- context = entry->context;
- break;
- }
- spin_unlock_irqrestore(&c->context_list_lock, flags);
-
- if (!context)
- osm_warn("%s: Could not find nonexistent ptr %p\n", c->name,
- ptr);
-
- osm_debug("%s: get context id from context list %p -> %d\n", c->name,
- ptr, context);
-
- return context;
-}
-#endif
-
-/**
- * i2o_iop_find - Find an I2O controller by id
- * @unit: unit number of the I2O controller to search for
- *
- * Lookup the I2O controller on the controller list.
- *
- * Returns pointer to the I2O controller on success or NULL if not found.
- */
-struct i2o_controller *i2o_find_iop(int unit)
-{
- struct i2o_controller *c;
-
- list_for_each_entry(c, &i2o_controllers, list) {
- if (c->unit == unit)
- return c;
- }
-
- return NULL;
-}
-
-/**
- * i2o_iop_find_device - Find a I2O device on an I2O controller
- * @c: I2O controller where the I2O device hangs on
- * @tid: TID of the I2O device to search for
- *
- * Searches the devices of the I2O controller for a device with TID tid and
- * returns it.
- *
- * Returns a pointer to the I2O device if found, otherwise NULL.
- */
-struct i2o_device *i2o_iop_find_device(struct i2o_controller *c, u16 tid)
-{
- struct i2o_device *dev;
-
- list_for_each_entry(dev, &c->devices, list)
- if (dev->lct_data.tid == tid)
- return dev;
-
- return NULL;
-}
-
-/**
- * i2o_quiesce_controller - quiesce controller
- * @c: controller
- *
- * Quiesce an IOP. Causes IOP to make external operation quiescent
- * (i2o 'READY' state). Internal operation of the IOP continues normally.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_iop_quiesce(struct i2o_controller *c)
-{
- struct i2o_message *msg;
- i2o_status_block *sb = c->status_block.virt;
- int rc;
-
- i2o_status_get(c);
-
- /* SysQuiesce discarded if IOP not in READY or OPERATIONAL state */
- if ((sb->iop_state != ADAPTER_STATE_READY) &&
- (sb->iop_state != ADAPTER_STATE_OPERATIONAL))
- return 0;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_SYS_QUIESCE << 24 | HOST_TID << 12 |
- ADAPTER_TID);
-
- /* Long timeout needed for quiesce if lots of devices */
- rc = i2o_msg_post_wait(c, msg, 240);
- if (rc)
- osm_info("%s: Unable to quiesce (status=%#x).\n", c->name, -rc);
- else
- osm_debug("%s: Quiesced.\n", c->name);
-
- i2o_status_get(c); // Entered READY state
-
- return rc;
-}
-
-/**
- * i2o_iop_enable - move controller from ready to OPERATIONAL
- * @c: I2O controller
- *
- * Enable IOP. This allows the IOP to resume external operations and
- * reverses the effect of a quiesce. Returns zero or an error code if
- * an error occurs.
- */
-static int i2o_iop_enable(struct i2o_controller *c)
-{
- struct i2o_message *msg;
- i2o_status_block *sb = c->status_block.virt;
- int rc;
-
- i2o_status_get(c);
-
- /* Enable only allowed on READY state */
- if (sb->iop_state != ADAPTER_STATE_READY)
- return -EINVAL;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_SYS_ENABLE << 24 | HOST_TID << 12 |
- ADAPTER_TID);
-
- /* How long of a timeout do we need? */
- rc = i2o_msg_post_wait(c, msg, 240);
- if (rc)
- osm_err("%s: Could not enable (status=%#x).\n", c->name, -rc);
- else
- osm_debug("%s: Enabled.\n", c->name);
-
- i2o_status_get(c); // entered OPERATIONAL state
-
- return rc;
-}
-
-/**
- * i2o_iop_quiesce_all - Quiesce all I2O controllers on the system
- *
- * Quiesce all I2O controllers which are connected to the system.
- */
-static inline void i2o_iop_quiesce_all(void)
-{
- struct i2o_controller *c, *tmp;
-
- list_for_each_entry_safe(c, tmp, &i2o_controllers, list) {
- if (!c->no_quiesce)
- i2o_iop_quiesce(c);
- }
-}
-
-/**
- * i2o_iop_enable_all - Enables all controllers on the system
- *
- * Enables all I2O controllers which are connected to the system.
- */
-static inline void i2o_iop_enable_all(void)
-{
- struct i2o_controller *c, *tmp;
-
- list_for_each_entry_safe(c, tmp, &i2o_controllers, list)
- i2o_iop_enable(c);
-}
-
-/**
- * i2o_clear_controller - Bring I2O controller into HOLD state
- * @c: controller
- *
- * Clear an IOP to HOLD state, ie. terminate external operations, clear all
- * input queues and prepare for a system restart. IOP's internal operation
- * continues normally and the outbound queue is alive. The IOP is not
- * expected to rebuild its LCT.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_iop_clear(struct i2o_controller *c)
-{
- struct i2o_message *msg;
- int rc;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- /* Quiesce all IOPs first */
- i2o_iop_quiesce_all();
-
- msg->u.head[0] = cpu_to_le32(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_ADAPTER_CLEAR << 24 | HOST_TID << 12 |
- ADAPTER_TID);
-
- rc = i2o_msg_post_wait(c, msg, 30);
- if (rc)
- osm_info("%s: Unable to clear (status=%#x).\n", c->name, -rc);
- else
- osm_debug("%s: Cleared.\n", c->name);
-
- /* Enable all IOPs */
- i2o_iop_enable_all();
-
- return rc;
-}
-
-/**
- * i2o_iop_init_outbound_queue - setup the outbound message queue
- * @c: I2O controller
- *
- * Clear and (re)initialize IOP's outbound queue and post the message
- * frames to the IOP.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_iop_init_outbound_queue(struct i2o_controller *c)
-{
- u32 m;
- volatile u8 *status = c->status.virt;
- struct i2o_message *msg;
- ulong timeout;
- int i;
-
- osm_debug("%s: Initializing Outbound Queue...\n", c->name);
-
- memset(c->status.virt, 0, 4);
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_6);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 |
- ADAPTER_TID);
- msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
- msg->u.s.tcntxt = cpu_to_le32(0x00000000);
- msg->body[0] = cpu_to_le32(PAGE_SIZE);
- /* Outbound msg frame size in words and Initcode */
- msg->body[1] = cpu_to_le32(I2O_OUTBOUND_MSG_FRAME_SIZE << 16 | 0x80);
- msg->body[2] = cpu_to_le32(0xd0000004);
- msg->body[3] = cpu_to_le32(i2o_dma_low(c->status.phys));
- msg->body[4] = cpu_to_le32(i2o_dma_high(c->status.phys));
-
- i2o_msg_post(c, msg);
-
- timeout = jiffies + I2O_TIMEOUT_INIT_OUTBOUND_QUEUE * HZ;
- while (*status <= I2O_CMD_IN_PROGRESS) {
- if (time_after(jiffies, timeout)) {
- osm_warn("%s: Timeout Initializing\n", c->name);
- return -ETIMEDOUT;
- }
- schedule_timeout_uninterruptible(1);
- }
-
- m = c->out_queue.phys;
-
- /* Post frames */
- for (i = 0; i < I2O_MAX_OUTBOUND_MSG_FRAMES; i++) {
- i2o_flush_reply(c, m);
- udelay(1); /* Promise */
- m += I2O_OUTBOUND_MSG_FRAME_SIZE * sizeof(u32);
- }
-
- return 0;
-}
-
-/**
- * i2o_iop_reset - reset an I2O controller
- * @c: controller to reset
- *
- * Reset the IOP into INIT state and wait until IOP gets into RESET state.
- * Terminate all external operations, clear IOP's inbound and outbound
- * queues, terminate all DDMs, and reload the IOP's operating environment
- * and all local DDMs. The IOP rebuilds its LCT.
- */
-static int i2o_iop_reset(struct i2o_controller *c)
-{
- volatile u8 *status = c->status.virt;
- struct i2o_message *msg;
- unsigned long timeout;
- i2o_status_block *sb = c->status_block.virt;
- int rc = 0;
-
- osm_debug("%s: Resetting controller\n", c->name);
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- memset(c->status_block.virt, 0, 8);
-
- /* Quiesce all IOPs first */
- i2o_iop_quiesce_all();
-
- msg->u.head[0] = cpu_to_le32(EIGHT_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 |
- ADAPTER_TID);
- msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
- msg->u.s.tcntxt = cpu_to_le32(0x00000000);
- msg->body[0] = cpu_to_le32(0x00000000);
- msg->body[1] = cpu_to_le32(0x00000000);
- msg->body[2] = cpu_to_le32(i2o_dma_low(c->status.phys));
- msg->body[3] = cpu_to_le32(i2o_dma_high(c->status.phys));
-
- i2o_msg_post(c, msg);
-
- /* Wait for a reply */
- timeout = jiffies + I2O_TIMEOUT_RESET * HZ;
- while (!*status) {
- if (time_after(jiffies, timeout))
- break;
-
- schedule_timeout_uninterruptible(1);
- }
-
- switch (*status) {
- case I2O_CMD_REJECTED:
- osm_warn("%s: IOP reset rejected\n", c->name);
- rc = -EPERM;
- break;
-
- case I2O_CMD_IN_PROGRESS:
- /*
- * Once the reset is sent, the IOP goes into the INIT state
- * which is indeterminate. We need to wait until the IOP has
- * rebooted before we can let the system talk to it. We read
- * the inbound Free_List until a message is available. If we
- * can't read one in the given amount of time, we assume the
- * IOP could not reboot properly.
- */
- osm_debug("%s: Reset in progress, waiting for reboot...\n",
- c->name);
-
- while (IS_ERR(msg = i2o_msg_get_wait(c, I2O_TIMEOUT_RESET))) {
- if (time_after(jiffies, timeout)) {
- osm_err("%s: IOP reset timeout.\n", c->name);
- rc = PTR_ERR(msg);
- goto exit;
- }
- schedule_timeout_uninterruptible(1);
- }
- i2o_msg_nop(c, msg);
-
- /* from here all quiesce commands are safe */
- c->no_quiesce = 0;
-
- /* verify if controller is in state RESET */
- i2o_status_get(c);
-
- if (!c->promise && (sb->iop_state != ADAPTER_STATE_RESET))
- osm_warn("%s: reset completed, but adapter not in RESET"
- " state.\n", c->name);
- else
- osm_debug("%s: reset completed.\n", c->name);
-
- break;
-
- default:
- osm_err("%s: IOP reset timeout.\n", c->name);
- rc = -ETIMEDOUT;
- break;
- }
-
- exit:
- /* Enable all IOPs */
- i2o_iop_enable_all();
-
- return rc;
-}
-
-/**
- * i2o_iop_activate - Bring controller up to HOLD
- * @c: controller
- *
- * This function brings an I2O controller into HOLD state. The adapter
- * is reset if necessary and then the queues and resource table are read.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_iop_activate(struct i2o_controller *c)
-{
- i2o_status_block *sb = c->status_block.virt;
- int rc;
- int state;
-
- /* In INIT state, Wait Inbound Q to initialize (in i2o_status_get) */
- /* In READY state, Get status */
-
- rc = i2o_status_get(c);
- if (rc) {
- osm_info("%s: Unable to obtain status, attempting a reset.\n",
- c->name);
- rc = i2o_iop_reset(c);
- if (rc)
- return rc;
- }
-
- if (sb->i2o_version > I2OVER15) {
- osm_err("%s: Not running version 1.5 of the I2O Specification."
- "\n", c->name);
- return -ENODEV;
- }
-
- switch (sb->iop_state) {
- case ADAPTER_STATE_FAULTED:
- osm_err("%s: hardware fault\n", c->name);
- return -EFAULT;
-
- case ADAPTER_STATE_READY:
- case ADAPTER_STATE_OPERATIONAL:
- case ADAPTER_STATE_HOLD:
- case ADAPTER_STATE_FAILED:
- osm_debug("%s: already running, trying to reset...\n", c->name);
- rc = i2o_iop_reset(c);
- if (rc)
- return rc;
- }
-
- /* preserve state */
- state = sb->iop_state;
-
- rc = i2o_iop_init_outbound_queue(c);
- if (rc)
- return rc;
-
- /* if adapter was not in RESET state clear now */
- if (state != ADAPTER_STATE_RESET)
- i2o_iop_clear(c);
-
- i2o_status_get(c);
-
- if (sb->iop_state != ADAPTER_STATE_HOLD) {
- osm_err("%s: failed to bring IOP into HOLD state\n", c->name);
- return -EIO;
- }
-
- return i2o_hrt_get(c);
-}
-
-static void i2o_res_alloc(struct i2o_controller *c, unsigned long flags)
-{
- i2o_status_block *sb = c->status_block.virt;
- struct resource *res = &c->mem_resource;
- resource_size_t size, align;
- int err;
-
- res->name = c->pdev->bus->name;
- res->flags = flags;
- res->start = 0;
- res->end = 0;
- osm_info("%s: requires private memory resources.\n", c->name);
-
- if (flags & IORESOURCE_MEM) {
- size = sb->desired_mem_size;
- align = 1 << 20; /* unspecified, use 1Mb and play safe */
- } else {
- size = sb->desired_io_size;
- align = 1 << 12; /* unspecified, use 4Kb and play safe */
- }
-
- err = pci_bus_alloc_resource(c->pdev->bus, res, size, align, 0, 0,
- NULL, NULL);
- if (err < 0)
- return;
-
- if (flags & IORESOURCE_MEM) {
- c->mem_alloc = 1;
- sb->current_mem_size = resource_size(res);
- sb->current_mem_base = res->start;
- } else if (flags & IORESOURCE_IO) {
- c->io_alloc = 1;
- sb->current_io_size = resource_size(res);
- sb->current_io_base = res->start;
- }
- osm_info("%s: allocated PCI space %pR\n", c->name, res);
-}
-
-/**
- * i2o_iop_systab_set - Set the I2O System Table of the specified IOP
- * @c: I2O controller to which the system table should be send
- *
- * Before the systab could be set i2o_systab_build() must be called.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_iop_systab_set(struct i2o_controller *c)
-{
- struct i2o_message *msg;
- i2o_status_block *sb = c->status_block.virt;
- struct device *dev = &c->pdev->dev;
- int rc;
-
- if (sb->current_mem_size < sb->desired_mem_size)
- i2o_res_alloc(c, IORESOURCE_MEM);
-
- if (sb->current_io_size < sb->desired_io_size)
- i2o_res_alloc(c, IORESOURCE_IO);
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- i2o_systab.phys = dma_map_single(dev, i2o_systab.virt, i2o_systab.len,
- PCI_DMA_TODEVICE);
- if (!i2o_systab.phys) {
- i2o_msg_nop(c, msg);
- return -ENOMEM;
- }
-
- msg->u.head[0] = cpu_to_le32(I2O_MESSAGE_SIZE(12) | SGL_OFFSET_6);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_SYS_TAB_SET << 24 | HOST_TID << 12 |
- ADAPTER_TID);
-
- /*
- * Provide three SGL-elements:
- * System table (SysTab), Private memory space declaration and
- * Private i/o space declaration
- */
-
- msg->body[0] = cpu_to_le32(c->unit + 2);
- msg->body[1] = cpu_to_le32(0x00000000);
- msg->body[2] = cpu_to_le32(0x54000000 | i2o_systab.len);
- msg->body[3] = cpu_to_le32(i2o_systab.phys);
- msg->body[4] = cpu_to_le32(0x54000000 | sb->current_mem_size);
- msg->body[5] = cpu_to_le32(sb->current_mem_base);
- msg->body[6] = cpu_to_le32(0xd4000000 | sb->current_io_size);
- msg->body[6] = cpu_to_le32(sb->current_io_base);
-
- rc = i2o_msg_post_wait(c, msg, 120);
-
- dma_unmap_single(dev, i2o_systab.phys, i2o_systab.len,
- PCI_DMA_TODEVICE);
-
- if (rc < 0)
- osm_err("%s: Unable to set SysTab (status=%#x).\n", c->name,
- -rc);
- else
- osm_debug("%s: SysTab set.\n", c->name);
-
- return rc;
-}
-
-/**
- * i2o_iop_online - Bring a controller online into OPERATIONAL state.
- * @c: I2O controller
- *
- * Send the system table and enable the I2O controller.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_iop_online(struct i2o_controller *c)
-{
- int rc;
-
- rc = i2o_iop_systab_set(c);
- if (rc)
- return rc;
-
- /* In READY state */
- osm_debug("%s: Attempting to enable...\n", c->name);
- return i2o_iop_enable(c);
-}
-
-/**
- * i2o_iop_remove - Remove the I2O controller from the I2O core
- * @c: I2O controller
- *
- * Remove the I2O controller from the I2O core. If devices are attached to
- * the controller remove these also and finally reset the controller.
- */
-void i2o_iop_remove(struct i2o_controller *c)
-{
- struct i2o_device *dev, *tmp;
-
- osm_debug("%s: deleting controller\n", c->name);
-
- i2o_driver_notify_controller_remove_all(c);
-
- list_del(&c->list);
-
- list_for_each_entry_safe(dev, tmp, &c->devices, list)
- i2o_device_remove(dev);
-
- device_del(&c->device);
-
- /* Ask the IOP to switch to RESET state */
- i2o_iop_reset(c);
-}
-
-/**
- * i2o_systab_build - Build system table
- *
- * The system table contains information about all the IOPs in the system
- * (duh) and is used by the Executives on the IOPs to establish peer2peer
- * connections. We're not supporting peer2peer at the moment, but this
- * will be needed down the road for things like lan2lan forwarding.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_systab_build(void)
-{
- struct i2o_controller *c, *tmp;
- int num_controllers = 0;
- u32 change_ind = 0;
- int count = 0;
- struct i2o_sys_tbl *systab = i2o_systab.virt;
-
- list_for_each_entry_safe(c, tmp, &i2o_controllers, list)
- num_controllers++;
-
- if (systab) {
- change_ind = systab->change_ind;
- kfree(i2o_systab.virt);
- }
-
- /* Header + IOPs */
- i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers *
- sizeof(struct i2o_sys_tbl_entry);
-
- systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL);
- if (!systab) {
- osm_err("unable to allocate memory for System Table\n");
- return -ENOMEM;
- }
-
- systab->version = I2OVERSION;
- systab->change_ind = change_ind + 1;
-
- list_for_each_entry_safe(c, tmp, &i2o_controllers, list) {
- i2o_status_block *sb;
-
- if (count >= num_controllers) {
- osm_err("controller added while building system table"
- "\n");
- break;
- }
-
- sb = c->status_block.virt;
-
- /*
- * Get updated IOP state so we have the latest information
- *
- * We should delete the controller at this point if it
- * doesn't respond since if it's not on the system table
- * it is techninically not part of the I2O subsystem...
- */
- if (unlikely(i2o_status_get(c))) {
- osm_err("%s: Deleting b/c could not get status while "
- "attempting to build system table\n", c->name);
- i2o_iop_remove(c);
- continue; // try the next one
- }
-
- systab->iops[count].org_id = sb->org_id;
- systab->iops[count].iop_id = c->unit + 2;
- systab->iops[count].seg_num = 0;
- systab->iops[count].i2o_version = sb->i2o_version;
- systab->iops[count].iop_state = sb->iop_state;
- systab->iops[count].msg_type = sb->msg_type;
- systab->iops[count].frame_size = sb->inbound_frame_size;
- systab->iops[count].last_changed = change_ind;
- systab->iops[count].iop_capabilities = sb->iop_capabilities;
- systab->iops[count].inbound_low =
- i2o_dma_low(c->base.phys + I2O_IN_PORT);
- systab->iops[count].inbound_high =
- i2o_dma_high(c->base.phys + I2O_IN_PORT);
-
- count++;
- }
-
- systab->num_entries = count;
-
- return 0;
-}
-
-/**
- * i2o_parse_hrt - Parse the hardware resource table.
- * @c: I2O controller
- *
- * We don't do anything with it except dumping it (in debug mode).
- *
- * Returns 0.
- */
-static int i2o_parse_hrt(struct i2o_controller *c)
-{
- i2o_dump_hrt(c);
- return 0;
-}
-
-/**
- * i2o_status_get - Get the status block from the I2O controller
- * @c: I2O controller
- *
- * Issue a status query on the controller. This updates the attached
- * status block. The status block could then be accessed through
- * c->status_block.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_status_get(struct i2o_controller *c)
-{
- struct i2o_message *msg;
- volatile u8 *status_block;
- unsigned long timeout;
-
- status_block = (u8 *) c->status_block.virt;
- memset(c->status_block.virt, 0, sizeof(i2o_status_block));
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 |
- ADAPTER_TID);
- msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);
- msg->u.s.tcntxt = cpu_to_le32(0x00000000);
- msg->body[0] = cpu_to_le32(0x00000000);
- msg->body[1] = cpu_to_le32(0x00000000);
- msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys));
- msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys));
- msg->body[4] = cpu_to_le32(sizeof(i2o_status_block)); /* always 88 bytes */
-
- i2o_msg_post(c, msg);
-
- /* Wait for a reply */
- timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;
- while (status_block[87] != 0xFF) {
- if (time_after(jiffies, timeout)) {
- osm_err("%s: Get status timeout.\n", c->name);
- return -ETIMEDOUT;
- }
-
- schedule_timeout_uninterruptible(1);
- }
-
-#ifdef DEBUG
- i2o_debug_state(c);
-#endif
-
- return 0;
-}
-
-/*
- * i2o_hrt_get - Get the Hardware Resource Table from the I2O controller
- * @c: I2O controller from which the HRT should be fetched
- *
- * The HRT contains information about possible hidden devices but is
- * mostly useless to us.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_hrt_get(struct i2o_controller *c)
-{
- int rc;
- int i;
- i2o_hrt *hrt = c->hrt.virt;
- u32 size = sizeof(i2o_hrt);
- struct device *dev = &c->pdev->dev;
-
- for (i = 0; i < I2O_HRT_GET_TRIES; i++) {
- struct i2o_message *msg;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 |
- ADAPTER_TID);
- msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len);
- msg->body[1] = cpu_to_le32(c->hrt.phys);
-
- rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt);
-
- if (rc < 0) {
- osm_err("%s: Unable to get HRT (status=%#x)\n", c->name,
- -rc);
- return rc;
- }
-
- size = hrt->num_entries * hrt->entry_len << 2;
- if (size > c->hrt.len) {
- if (i2o_dma_realloc(dev, &c->hrt, size))
- return -ENOMEM;
- else
- hrt = c->hrt.virt;
- } else
- return i2o_parse_hrt(c);
- }
-
- osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name,
- I2O_HRT_GET_TRIES);
-
- return -EBUSY;
-}
-
-/**
- * i2o_iop_release - release the memory for a I2O controller
- * @dev: I2O controller which should be released
- *
- * Release the allocated memory. This function is called if refcount of
- * device reaches 0 automatically.
- */
-static void i2o_iop_release(struct device *dev)
-{
- struct i2o_controller *c = to_i2o_controller(dev);
-
- i2o_iop_free(c);
-}
-
-/**
- * i2o_iop_alloc - Allocate and initialize a i2o_controller struct
- *
- * Allocate the necessary memory for a i2o_controller struct and
- * initialize the lists and message mempool.
- *
- * Returns a pointer to the I2O controller or a negative error code on
- * failure.
- */
-struct i2o_controller *i2o_iop_alloc(void)
-{
- static int unit; /* 0 and 1 are NULL IOP and Local Host */
- struct i2o_controller *c;
- char poolname[32];
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c) {
- osm_err("i2o: Insufficient memory to allocate a I2O controller."
- "\n");
- return ERR_PTR(-ENOMEM);
- }
-
- c->unit = unit++;
- sprintf(c->name, "iop%d", c->unit);
-
- snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);
- if (i2o_pool_alloc
- (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32),
- I2O_MSG_INPOOL_MIN)) {
- kfree(c);
- return ERR_PTR(-ENOMEM);
- }
-
- INIT_LIST_HEAD(&c->devices);
- spin_lock_init(&c->lock);
- mutex_init(&c->lct_lock);
-
- device_initialize(&c->device);
-
- c->device.release = &i2o_iop_release;
-
- dev_set_name(&c->device, "iop%d", c->unit);
-
-#if BITS_PER_LONG == 64
- spin_lock_init(&c->context_list_lock);
- atomic_set(&c->context_list_counter, 0);
- INIT_LIST_HEAD(&c->context_list);
-#endif
-
- return c;
-}
-
-/**
- * i2o_iop_add - Initialize the I2O controller and add him to the I2O core
- * @c: controller
- *
- * Initialize the I2O controller and if no error occurs add him to the I2O
- * core.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_iop_add(struct i2o_controller *c)
-{
- int rc;
-
- rc = device_add(&c->device);
- if (rc) {
- osm_err("%s: could not add controller\n", c->name);
- goto iop_reset;
- }
-
- osm_info("%s: Activating I2O controller...\n", c->name);
- osm_info("%s: This may take a few minutes if there are many devices\n",
- c->name);
-
- rc = i2o_iop_activate(c);
- if (rc) {
- osm_err("%s: could not activate controller\n", c->name);
- goto device_del;
- }
-
- osm_debug("%s: building sys table...\n", c->name);
-
- rc = i2o_systab_build();
- if (rc)
- goto device_del;
-
- osm_debug("%s: online controller...\n", c->name);
-
- rc = i2o_iop_online(c);
- if (rc)
- goto device_del;
-
- osm_debug("%s: getting LCT...\n", c->name);
-
- rc = i2o_exec_lct_get(c);
- if (rc)
- goto device_del;
-
- list_add(&c->list, &i2o_controllers);
-
- i2o_driver_notify_controller_add_all(c);
-
- osm_info("%s: Controller added\n", c->name);
-
- return 0;
-
- device_del:
- device_del(&c->device);
-
- iop_reset:
- i2o_iop_reset(c);
-
- return rc;
-}
-
-/**
- * i2o_event_register - Turn on/off event notification for a I2O device
- * @dev: I2O device which should receive the event registration request
- * @drv: driver which want to get notified
- * @tcntxt: transaction context to use with this notifier
- * @evt_mask: mask of events
- *
- * Create and posts an event registration message to the task. No reply
- * is waited for, or expected. If you do not want further notifications,
- * call the i2o_event_register again with a evt_mask of 0.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv,
- int tcntxt, u32 evt_mask)
-{
- struct i2o_controller *c = dev->iop;
- struct i2o_message *msg;
-
- msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);
- if (IS_ERR(msg))
- return PTR_ERR(msg);
-
- msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);
- msg->u.head[1] =
- cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->
- lct_data.tid);
- msg->u.s.icntxt = cpu_to_le32(drv->context);
- msg->u.s.tcntxt = cpu_to_le32(tcntxt);
- msg->body[0] = cpu_to_le32(evt_mask);
-
- i2o_msg_post(c, msg);
-
- return 0;
-}
-
-/**
- * i2o_iop_init - I2O main initialization function
- *
- * Initialize the I2O drivers (OSM) functions, register the Executive OSM,
- * initialize the I2O PCI part and finally initialize I2O device stuff.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int __init i2o_iop_init(void)
-{
- int rc = 0;
-
- printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");
-
- rc = i2o_driver_init();
- if (rc)
- goto exit;
-
- rc = i2o_exec_init();
- if (rc)
- goto driver_exit;
-
- rc = i2o_pci_init();
- if (rc)
- goto exec_exit;
-
- return 0;
-
- exec_exit:
- i2o_exec_exit();
-
- driver_exit:
- i2o_driver_exit();
-
- exit:
- return rc;
-}
-
-/**
- * i2o_iop_exit - I2O main exit function
- *
- * Removes I2O controllers from PCI subsystem and shut down OSMs.
- */
-static void __exit i2o_iop_exit(void)
-{
- i2o_pci_exit();
- i2o_exec_exit();
- i2o_driver_exit();
-}
-
-module_init(i2o_iop_init);
-module_exit(i2o_iop_exit);
-
-MODULE_AUTHOR("Red Hat Software");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(OSM_DESCRIPTION);
-MODULE_VERSION(OSM_VERSION);
-
-#if BITS_PER_LONG == 64
-EXPORT_SYMBOL(i2o_cntxt_list_add);
-EXPORT_SYMBOL(i2o_cntxt_list_get);
-EXPORT_SYMBOL(i2o_cntxt_list_remove);
-EXPORT_SYMBOL(i2o_cntxt_list_get_ptr);
-#endif
-EXPORT_SYMBOL(i2o_msg_get_wait);
-EXPORT_SYMBOL(i2o_find_iop);
-EXPORT_SYMBOL(i2o_iop_find_device);
-EXPORT_SYMBOL(i2o_event_register);
-EXPORT_SYMBOL(i2o_status_get);
-EXPORT_SYMBOL(i2o_controllers);
+++ /dev/null
-/*
- * Functions to handle I2O memory
- *
- * Pulled from the inlines in i2o headers and uninlined
- *
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#include <linux/module.h>
-#include "i2o.h"
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include "core.h"
-
-/* Protects our 32/64bit mask switching */
-static DEFINE_MUTEX(mem_lock);
-
-/**
- * i2o_sg_tablesize - Calculate the maximum number of elements in a SGL
- * @c: I2O controller for which the calculation should be done
- * @body_size: maximum body size used for message in 32-bit words.
- *
- * Return the maximum number of SG elements in a SG list.
- */
-u16 i2o_sg_tablesize(struct i2o_controller *c, u16 body_size)
-{
- i2o_status_block *sb = c->status_block.virt;
- u16 sg_count =
- (sb->inbound_frame_size - sizeof(struct i2o_message) / 4) -
- body_size;
-
- if (c->pae_support) {
- /*
- * for 64-bit a SG attribute element must be added and each
- * SG element needs 12 bytes instead of 8.
- */
- sg_count -= 2;
- sg_count /= 3;
- } else
- sg_count /= 2;
-
- if (c->short_req && (sg_count > 8))
- sg_count = 8;
-
- return sg_count;
-}
-EXPORT_SYMBOL_GPL(i2o_sg_tablesize);
-
-
-/**
- * i2o_dma_map_single - Map pointer to controller and fill in I2O message.
- * @c: I2O controller
- * @ptr: pointer to the data which should be mapped
- * @size: size of data in bytes
- * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
- * @sg_ptr: pointer to the SG list inside the I2O message
- *
- * This function does all necessary DMA handling and also writes the I2O
- * SGL elements into the I2O message. For details on DMA handling see also
- * dma_map_single(). The pointer sg_ptr will only be set to the end of the
- * SG list if the allocation was successful.
- *
- * Returns DMA address which must be checked for failures using
- * dma_mapping_error().
- */
-dma_addr_t i2o_dma_map_single(struct i2o_controller *c, void *ptr,
- size_t size,
- enum dma_data_direction direction,
- u32 ** sg_ptr)
-{
- u32 sg_flags;
- u32 *mptr = *sg_ptr;
- dma_addr_t dma_addr;
-
- switch (direction) {
- case DMA_TO_DEVICE:
- sg_flags = 0xd4000000;
- break;
- case DMA_FROM_DEVICE:
- sg_flags = 0xd0000000;
- break;
- default:
- return 0;
- }
-
- dma_addr = dma_map_single(&c->pdev->dev, ptr, size, direction);
- if (!dma_mapping_error(&c->pdev->dev, dma_addr)) {
-#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
- if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
- *mptr++ = cpu_to_le32(0x7C020002);
- *mptr++ = cpu_to_le32(PAGE_SIZE);
- }
-#endif
-
- *mptr++ = cpu_to_le32(sg_flags | size);
- *mptr++ = cpu_to_le32(i2o_dma_low(dma_addr));
-#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
- if ((sizeof(dma_addr_t) > 4) && c->pae_support)
- *mptr++ = cpu_to_le32(i2o_dma_high(dma_addr));
-#endif
- *sg_ptr = mptr;
- }
- return dma_addr;
-}
-EXPORT_SYMBOL_GPL(i2o_dma_map_single);
-
-/**
- * i2o_dma_map_sg - Map a SG List to controller and fill in I2O message.
- * @c: I2O controller
- * @sg: SG list to be mapped
- * @sg_count: number of elements in the SG list
- * @direction: DMA_TO_DEVICE / DMA_FROM_DEVICE
- * @sg_ptr: pointer to the SG list inside the I2O message
- *
- * This function does all necessary DMA handling and also writes the I2O
- * SGL elements into the I2O message. For details on DMA handling see also
- * dma_map_sg(). The pointer sg_ptr will only be set to the end of the SG
- * list if the allocation was successful.
- *
- * Returns 0 on failure or 1 on success.
- */
-int i2o_dma_map_sg(struct i2o_controller *c, struct scatterlist *sg,
- int sg_count, enum dma_data_direction direction, u32 ** sg_ptr)
-{
- u32 sg_flags;
- u32 *mptr = *sg_ptr;
-
- switch (direction) {
- case DMA_TO_DEVICE:
- sg_flags = 0x14000000;
- break;
- case DMA_FROM_DEVICE:
- sg_flags = 0x10000000;
- break;
- default:
- return 0;
- }
-
- sg_count = dma_map_sg(&c->pdev->dev, sg, sg_count, direction);
- if (!sg_count)
- return 0;
-
-#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
- if ((sizeof(dma_addr_t) > 4) && c->pae_support) {
- *mptr++ = cpu_to_le32(0x7C020002);
- *mptr++ = cpu_to_le32(PAGE_SIZE);
- }
-#endif
-
- while (sg_count-- > 0) {
- if (!sg_count)
- sg_flags |= 0xC0000000;
- *mptr++ = cpu_to_le32(sg_flags | sg_dma_len(sg));
- *mptr++ = cpu_to_le32(i2o_dma_low(sg_dma_address(sg)));
-#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
- if ((sizeof(dma_addr_t) > 4) && c->pae_support)
- *mptr++ = cpu_to_le32(i2o_dma_high(sg_dma_address(sg)));
-#endif
- sg = sg_next(sg);
- }
- *sg_ptr = mptr;
-
- return 1;
-}
-EXPORT_SYMBOL_GPL(i2o_dma_map_sg);
-
-/**
- * i2o_dma_alloc - Allocate DMA memory
- * @dev: struct device pointer to the PCI device of the I2O controller
- * @addr: i2o_dma struct which should get the DMA buffer
- * @len: length of the new DMA memory
- *
- * Allocate a coherent DMA memory and write the pointers into addr.
- *
- * Returns 0 on success or -ENOMEM on failure.
- */
-int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, size_t len)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
- int dma_64 = 0;
-
- mutex_lock(&mem_lock);
- if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_BIT_MASK(64))) {
- dma_64 = 1;
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
- mutex_unlock(&mem_lock);
- return -ENOMEM;
- }
- }
-
- addr->virt = dma_alloc_coherent(dev, len, &addr->phys, GFP_KERNEL);
-
- if ((sizeof(dma_addr_t) > 4) && dma_64)
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
- printk(KERN_WARNING "i2o: unable to set 64-bit DMA");
- mutex_unlock(&mem_lock);
-
- if (!addr->virt)
- return -ENOMEM;
-
- memset(addr->virt, 0, len);
- addr->len = len;
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(i2o_dma_alloc);
-
-
-/**
- * i2o_dma_free - Free DMA memory
- * @dev: struct device pointer to the PCI device of the I2O controller
- * @addr: i2o_dma struct which contains the DMA buffer
- *
- * Free a coherent DMA memory and set virtual address of addr to NULL.
- */
-void i2o_dma_free(struct device *dev, struct i2o_dma *addr)
-{
- if (addr->virt) {
- if (addr->phys)
- dma_free_coherent(dev, addr->len, addr->virt,
- addr->phys);
- else
- kfree(addr->virt);
- addr->virt = NULL;
- }
-}
-EXPORT_SYMBOL_GPL(i2o_dma_free);
-
-
-/**
- * i2o_dma_realloc - Realloc DMA memory
- * @dev: struct device pointer to the PCI device of the I2O controller
- * @addr: pointer to a i2o_dma struct DMA buffer
- * @len: new length of memory
- *
- * If there was something allocated in the addr, free it first. If len > 0
- * than try to allocate it and write the addresses back to the addr
- * structure. If len == 0 set the virtual address to NULL.
- *
- * Returns the 0 on success or negative error code on failure.
- */
-int i2o_dma_realloc(struct device *dev, struct i2o_dma *addr, size_t len)
-{
- i2o_dma_free(dev, addr);
-
- if (len)
- return i2o_dma_alloc(dev, addr, len);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(i2o_dma_realloc);
-
-/*
- * i2o_pool_alloc - Allocate an slab cache and mempool
- * @mempool: pointer to struct i2o_pool to write data into.
- * @name: name which is used to identify cache
- * @size: size of each object
- * @min_nr: minimum number of objects
- *
- * First allocates a slab cache with name and size. Then allocates a
- * mempool which uses the slab cache for allocation and freeing.
- *
- * Returns 0 on success or negative error code on failure.
- */
-int i2o_pool_alloc(struct i2o_pool *pool, const char *name,
- size_t size, int min_nr)
-{
- pool->name = kstrdup(name, GFP_KERNEL);
- if (!pool->name)
- goto exit;
-
- pool->slab =
- kmem_cache_create(pool->name, size, 0, SLAB_HWCACHE_ALIGN, NULL);
- if (!pool->slab)
- goto free_name;
-
- pool->mempool = mempool_create_slab_pool(min_nr, pool->slab);
- if (!pool->mempool)
- goto free_slab;
-
- return 0;
-
-free_slab:
- kmem_cache_destroy(pool->slab);
-
-free_name:
- kfree(pool->name);
-
-exit:
- return -ENOMEM;
-}
-EXPORT_SYMBOL_GPL(i2o_pool_alloc);
-
-/*
- * i2o_pool_free - Free slab cache and mempool again
- * @mempool: pointer to struct i2o_pool which should be freed
- *
- * Note that you have to return all objects to the mempool again before
- * calling i2o_pool_free().
- */
-void i2o_pool_free(struct i2o_pool *pool)
-{
- mempool_destroy(pool->mempool);
- kmem_cache_destroy(pool->slab);
- kfree(pool->name);
-};
-EXPORT_SYMBOL_GPL(i2o_pool_free);
+++ /dev/null
-/*
- * PCI handling of I2O controller
- *
- * Copyright (C) 1999-2002 Red Hat Software
- *
- * Written by Alan Cox, Building Number Three Ltd
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * A lot of the I2O message side code from this is taken from the Red
- * Creek RCPCI45 adapter driver by Red Creek Communications
- *
- * Fixes/additions:
- * Philipp Rumpf
- * Juha Sievänen <Juha.Sievanen@cs.Helsinki.FI>
- * Auvo Häkkinen <Auvo.Hakkinen@cs.Helsinki.FI>
- * Deepak Saxena <deepak@plexity.net>
- * Boji T Kannanthanam <boji.t.kannanthanam@intel.com>
- * Alan Cox <alan@lxorguk.ukuu.org.uk>:
- * Ported to Linux 2.5.
- * Markus Lidel <Markus.Lidel@shadowconnect.com>:
- * Minor fixes for 2.6.
- * Markus Lidel <Markus.Lidel@shadowconnect.com>:
- * Support for sysfs included.
- */
-
-#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include "i2o.h"
-#include <linux/module.h>
-#include "core.h"
-
-#define OSM_DESCRIPTION "I2O-subsystem"
-
-/* PCI device id table for all I2O controllers */
-static struct pci_device_id i2o_pci_ids[] = {
- {PCI_DEVICE_CLASS(PCI_CLASS_INTELLIGENT_I2O << 8, 0xffff00)},
- {PCI_DEVICE(PCI_VENDOR_ID_DPT, 0xa511)},
- {.vendor = PCI_VENDOR_ID_INTEL,.device = 0x1962,
- .subvendor = PCI_VENDOR_ID_PROMISE,.subdevice = PCI_ANY_ID},
- {0}
-};
-
-/**
- * i2o_pci_free - Frees the DMA memory for the I2O controller
- * @c: I2O controller to free
- *
- * Remove all allocated DMA memory and unmap memory IO regions. If MTRR
- * is enabled, also remove it again.
- */
-static void i2o_pci_free(struct i2o_controller *c)
-{
- struct device *dev;
-
- dev = &c->pdev->dev;
-
- i2o_dma_free(dev, &c->out_queue);
- i2o_dma_free(dev, &c->status_block);
- kfree(c->lct);
- i2o_dma_free(dev, &c->dlct);
- i2o_dma_free(dev, &c->hrt);
- i2o_dma_free(dev, &c->status);
-
- if (c->raptor && c->in_queue.virt)
- iounmap(c->in_queue.virt);
-
- if (c->base.virt)
- iounmap(c->base.virt);
-
- pci_release_regions(c->pdev);
-}
-
-/**
- * i2o_pci_alloc - Allocate DMA memory, map IO memory for I2O controller
- * @c: I2O controller
- *
- * Allocate DMA memory for a PCI (or in theory AGP) I2O controller. All
- * IO mappings are also done here. If MTRR is enabled, also do add memory
- * regions here.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_pci_alloc(struct i2o_controller *c)
-{
- struct pci_dev *pdev = c->pdev;
- struct device *dev = &pdev->dev;
- int i;
-
- if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
- printk(KERN_ERR "%s: device already claimed\n", c->name);
- return -ENODEV;
- }
-
- for (i = 0; i < 6; i++) {
- /* Skip I/O spaces */
- if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
- if (!c->base.phys) {
- c->base.phys = pci_resource_start(pdev, i);
- c->base.len = pci_resource_len(pdev, i);
-
- /*
- * If we know what card it is, set the size
- * correctly. Code is taken from dpt_i2o.c
- */
- if (pdev->device == 0xa501) {
- if (pdev->subsystem_device >= 0xc032 &&
- pdev->subsystem_device <= 0xc03b) {
- if (c->base.len > 0x400000)
- c->base.len = 0x400000;
- } else {
- if (c->base.len > 0x100000)
- c->base.len = 0x100000;
- }
- }
- if (!c->raptor)
- break;
- } else {
- c->in_queue.phys = pci_resource_start(pdev, i);
- c->in_queue.len = pci_resource_len(pdev, i);
- break;
- }
- }
- }
-
- if (i == 6) {
- printk(KERN_ERR "%s: I2O controller has no memory regions"
- " defined.\n", c->name);
- i2o_pci_free(c);
- return -EINVAL;
- }
-
- /* Map the I2O controller */
- if (c->raptor) {
- printk(KERN_INFO "%s: PCI I2O controller\n", c->name);
- printk(KERN_INFO " BAR0 at 0x%08lX size=%ld\n",
- (unsigned long)c->base.phys, (unsigned long)c->base.len);
- printk(KERN_INFO " BAR1 at 0x%08lX size=%ld\n",
- (unsigned long)c->in_queue.phys,
- (unsigned long)c->in_queue.len);
- } else
- printk(KERN_INFO "%s: PCI I2O controller at %08lX size=%ld\n",
- c->name, (unsigned long)c->base.phys,
- (unsigned long)c->base.len);
-
- c->base.virt = ioremap_nocache(c->base.phys, c->base.len);
- if (!c->base.virt) {
- printk(KERN_ERR "%s: Unable to map controller.\n", c->name);
- i2o_pci_free(c);
- return -ENOMEM;
- }
-
- if (c->raptor) {
- c->in_queue.virt =
- ioremap_nocache(c->in_queue.phys, c->in_queue.len);
- if (!c->in_queue.virt) {
- printk(KERN_ERR "%s: Unable to map controller.\n",
- c->name);
- i2o_pci_free(c);
- return -ENOMEM;
- }
- } else
- c->in_queue = c->base;
-
- c->irq_status = c->base.virt + I2O_IRQ_STATUS;
- c->irq_mask = c->base.virt + I2O_IRQ_MASK;
- c->in_port = c->base.virt + I2O_IN_PORT;
- c->out_port = c->base.virt + I2O_OUT_PORT;
-
- /* Motorola/Freescale chip does not follow spec */
- if (pdev->vendor == PCI_VENDOR_ID_MOTOROLA && pdev->device == 0x18c0) {
- /* Check if CPU is enabled */
- if (be32_to_cpu(readl(c->base.virt + 0x10000)) & 0x10000000) {
- printk(KERN_INFO "%s: MPC82XX needs CPU running to "
- "service I2O.\n", c->name);
- i2o_pci_free(c);
- return -ENODEV;
- } else {
- c->irq_status += I2O_MOTOROLA_PORT_OFFSET;
- c->irq_mask += I2O_MOTOROLA_PORT_OFFSET;
- c->in_port += I2O_MOTOROLA_PORT_OFFSET;
- c->out_port += I2O_MOTOROLA_PORT_OFFSET;
- printk(KERN_INFO "%s: MPC82XX workarounds activated.\n",
- c->name);
- }
- }
-
- if (i2o_dma_alloc(dev, &c->status, 8)) {
- i2o_pci_free(c);
- return -ENOMEM;
- }
-
- if (i2o_dma_alloc(dev, &c->hrt, sizeof(i2o_hrt))) {
- i2o_pci_free(c);
- return -ENOMEM;
- }
-
- if (i2o_dma_alloc(dev, &c->dlct, 8192)) {
- i2o_pci_free(c);
- return -ENOMEM;
- }
-
- if (i2o_dma_alloc(dev, &c->status_block, sizeof(i2o_status_block))) {
- i2o_pci_free(c);
- return -ENOMEM;
- }
-
- if (i2o_dma_alloc(dev, &c->out_queue,
- I2O_MAX_OUTBOUND_MSG_FRAMES * I2O_OUTBOUND_MSG_FRAME_SIZE *
- sizeof(u32))) {
- i2o_pci_free(c);
- return -ENOMEM;
- }
-
- pci_set_drvdata(pdev, c);
-
- return 0;
-}
-
-/**
- * i2o_pci_interrupt - Interrupt handler for I2O controller
- * @irq: interrupt line
- * @dev_id: pointer to the I2O controller
- *
- * Handle an interrupt from a PCI based I2O controller. This turns out
- * to be rather simple. We keep the controller pointer in the cookie.
- */
-static irqreturn_t i2o_pci_interrupt(int irq, void *dev_id)
-{
- struct i2o_controller *c = dev_id;
- u32 m;
- irqreturn_t rc = IRQ_NONE;
-
- while (readl(c->irq_status) & I2O_IRQ_OUTBOUND_POST) {
- m = readl(c->out_port);
- if (m == I2O_QUEUE_EMPTY) {
- /*
- * Old 960 steppings had a bug in the I2O unit that
- * caused the queue to appear empty when it wasn't.
- */
- m = readl(c->out_port);
- if (unlikely(m == I2O_QUEUE_EMPTY))
- break;
- }
-
- /* dispatch it */
- if (i2o_driver_dispatch(c, m))
- /* flush it if result != 0 */
- i2o_flush_reply(c, m);
-
- rc = IRQ_HANDLED;
- }
-
- return rc;
-}
-
-/**
- * i2o_pci_irq_enable - Allocate interrupt for I2O controller
- * @c: i2o_controller that the request is for
- *
- * Allocate an interrupt for the I2O controller, and activate interrupts
- * on the I2O controller.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_pci_irq_enable(struct i2o_controller *c)
-{
- struct pci_dev *pdev = c->pdev;
- int rc;
-
- writel(0xffffffff, c->irq_mask);
-
- if (pdev->irq) {
- rc = request_irq(pdev->irq, i2o_pci_interrupt, IRQF_SHARED,
- c->name, c);
- if (rc < 0) {
- printk(KERN_ERR "%s: unable to allocate interrupt %d."
- "\n", c->name, pdev->irq);
- return rc;
- }
- }
-
- writel(0x00000000, c->irq_mask);
-
- printk(KERN_INFO "%s: Installed at IRQ %d\n", c->name, pdev->irq);
-
- return 0;
-}
-
-/**
- * i2o_pci_irq_disable - Free interrupt for I2O controller
- * @c: I2O controller
- *
- * Disable interrupts in I2O controller and then free interrupt.
- */
-static void i2o_pci_irq_disable(struct i2o_controller *c)
-{
- writel(0xffffffff, c->irq_mask);
-
- if (c->pdev->irq > 0)
- free_irq(c->pdev->irq, c);
-}
-
-/**
- * i2o_pci_probe - Probe the PCI device for an I2O controller
- * @pdev: PCI device to test
- * @id: id which matched with the PCI device id table
- *
- * Probe the PCI device for any device which is a memory of the
- * Intelligent, I2O class or an Adaptec Zero Channel Controller. We
- * attempt to set up each such device and register it with the core.
- *
- * Returns 0 on success or negative error code on failure.
- */
-static int i2o_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
- struct i2o_controller *c;
- int rc;
- struct pci_dev *i960 = NULL;
-
- printk(KERN_INFO "i2o: Checking for PCI I2O controllers...\n");
-
- if ((pdev->class & 0xff) > 1) {
- printk(KERN_WARNING "i2o: %s does not support I2O 1.5 "
- "(skipping).\n", pci_name(pdev));
- return -ENODEV;
- }
-
- rc = pci_enable_device(pdev);
- if (rc) {
- printk(KERN_WARNING "i2o: couldn't enable device %s\n",
- pci_name(pdev));
- return rc;
- }
-
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
- printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
- pci_name(pdev));
- rc = -ENODEV;
- goto disable;
- }
-
- pci_set_master(pdev);
-
- c = i2o_iop_alloc();
- if (IS_ERR(c)) {
- printk(KERN_ERR "i2o: couldn't allocate memory for %s\n",
- pci_name(pdev));
- rc = PTR_ERR(c);
- goto disable;
- } else
- printk(KERN_INFO "%s: controller found (%s)\n", c->name,
- pci_name(pdev));
-
- c->pdev = pdev;
- c->device.parent = &pdev->dev;
-
- /* Cards that fall apart if you hit them with large I/O loads... */
- if (pdev->vendor == PCI_VENDOR_ID_NCR && pdev->device == 0x0630) {
- c->short_req = 1;
- printk(KERN_INFO "%s: Symbios FC920 workarounds activated.\n",
- c->name);
- }
-
- if (pdev->subsystem_vendor == PCI_VENDOR_ID_PROMISE) {
- /*
- * Expose the ship behind i960 for initialization, or it will
- * failed
- */
- i960 = pci_get_slot(c->pdev->bus,
- PCI_DEVFN(PCI_SLOT(c->pdev->devfn), 0));
-
- if (i960) {
- pci_write_config_word(i960, 0x42, 0);
- pci_dev_put(i960);
- }
-
- c->promise = 1;
- c->limit_sectors = 1;
- }
-
- if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT)
- c->adaptec = 1;
-
- /* Cards that go bananas if you quiesce them before you reset them. */
- if (pdev->vendor == PCI_VENDOR_ID_DPT) {
- c->no_quiesce = 1;
- if (pdev->device == 0xa511)
- c->raptor = 1;
-
- if (pdev->subsystem_device == 0xc05a) {
- c->limit_sectors = 1;
- printk(KERN_INFO
- "%s: limit sectors per request to %d\n", c->name,
- I2O_MAX_SECTORS_LIMITED);
- }
-#ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64
- if (sizeof(dma_addr_t) > 4) {
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
- printk(KERN_INFO "%s: 64-bit DMA unavailable\n",
- c->name);
- else {
- c->pae_support = 1;
- printk(KERN_INFO "%s: using 64-bit DMA\n",
- c->name);
- }
- }
-#endif
- }
-
- rc = i2o_pci_alloc(c);
- if (rc) {
- printk(KERN_ERR "%s: DMA / IO allocation for I2O controller "
- "failed\n", c->name);
- goto free_controller;
- }
-
- if (i2o_pci_irq_enable(c)) {
- printk(KERN_ERR "%s: unable to enable interrupts for I2O "
- "controller\n", c->name);
- goto free_pci;
- }
-
- rc = i2o_iop_add(c);
- if (rc)
- goto uninstall;
-
- if (i960)
- pci_write_config_word(i960, 0x42, 0x03ff);
-
- return 0;
-
- uninstall:
- i2o_pci_irq_disable(c);
-
- free_pci:
- i2o_pci_free(c);
-
- free_controller:
- i2o_iop_free(c);
-
- disable:
- pci_disable_device(pdev);
-
- return rc;
-}
-
-/**
- * i2o_pci_remove - Removes a I2O controller from the system
- * @pdev: I2O controller which should be removed
- *
- * Reset the I2O controller, disable interrupts and remove all allocated
- * resources.
- */
-static void i2o_pci_remove(struct pci_dev *pdev)
-{
- struct i2o_controller *c;
- c = pci_get_drvdata(pdev);
-
- i2o_iop_remove(c);
- i2o_pci_irq_disable(c);
- i2o_pci_free(c);
-
- pci_disable_device(pdev);
-
- printk(KERN_INFO "%s: Controller removed.\n", c->name);
-
- put_device(&c->device);
-};
-
-/* PCI driver for I2O controller */
-static struct pci_driver i2o_pci_driver = {
- .name = "PCI_I2O",
- .id_table = i2o_pci_ids,
- .probe = i2o_pci_probe,
- .remove = i2o_pci_remove,
-};
-
-/**
- * i2o_pci_init - registers I2O PCI driver in PCI subsystem
- *
- * Returns > 0 on success or negative error code on failure.
- */
-int __init i2o_pci_init(void)
-{
- return pci_register_driver(&i2o_pci_driver);
-};
-
-/**
- * i2o_pci_exit - unregisters I2O PCI driver from PCI subsystem
- */
-void __exit i2o_pci_exit(void)
-{
- pci_unregister_driver(&i2o_pci_driver);
-};
-
-MODULE_DEVICE_TABLE(pci, i2o_pci_ids);
#define _LIBCFS_H
+void *libcfs_kvzalloc(size_t size, gfp_t flags);
+void *libcfs_kvzalloc_cpt(struct cfs_cpt_table *cptab, int cpt, size_t size,
+ gfp_t flags);
+
#endif /* _LIBCFS_H */
__OBD_VMALLOC_VEROBSE(ptr, cptab, cpt, size)
-/* Allocations above this size are considered too big and could not be done
- * atomically.
- *
- * Be very careful when changing this value, especially when decreasing it,
- * since vmalloc in Linux doesn't perform well on multi-cores system, calling
- * vmalloc in critical path would hurt performance badly. See LU-66.
- */
-#define OBD_ALLOC_BIG (4 * PAGE_CACHE_SIZE)
-
#define OBD_ALLOC_LARGE(ptr, size) \
do { \
- if (size > OBD_ALLOC_BIG) \
- OBD_VMALLOC(ptr, size); \
- else \
- OBD_ALLOC(ptr, size); \
+ ptr = libcfs_kvzalloc(size, GFP_NOFS); \
} while (0)
#define OBD_CPT_ALLOC_LARGE(ptr, cptab, cpt, size) \
do { \
- if (size > OBD_ALLOC_BIG) \
- OBD_CPT_VMALLOC(ptr, cptab, cpt, size); \
- else \
- OBD_CPT_ALLOC(ptr, cptab, cpt, size); \
+ ptr = libcfs_kvzalloc_cpt(cptab, cpt, size, GFP_NOFS); \
} while (0)
#define OBD_FREE_LARGE(ptr, size) \
do { \
- if (size > OBD_ALLOC_BIG) \
- OBD_VFREE(ptr, size); \
- else \
- OBD_FREE(ptr, size); \
+ kvfree(ptr); \
} while (0)
libcfs-linux-objs += linux-module.o
libcfs-linux-objs += linux-crypto.o
libcfs-linux-objs += linux-crypto-adler.o
+libcfs-linux-objs += linux-mem.o
libcfs-linux-objs := $(addprefix linux/,$(libcfs-linux-objs))
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 only,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License version 2 for more details (a copy is included
+ * in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 2 along with this program; If not, see
+ * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
+ *
+ */
+/*
+ * This file creates a memory allocation primitive for Lustre, that
+ * allows to fallback to vmalloc allocations should regular kernel allocations
+ * fail due to size or system memory fragmentation.
+ *
+ * Author: Oleg Drokin <green@linuxhacker.ru>
+ *
+ */
+/*
+ * This file is part of Lustre, http://www.lustre.org/
+ * Lustre is a trademark of Seagate Technology.
+ */
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include "../../../include/linux/libcfs/libcfs.h"
+
+void *libcfs_kvzalloc(size_t size, gfp_t flags)
+{
+ void *ret;
+
+ ret = kzalloc(size, flags | __GFP_NOWARN);
+ if (!ret)
+ ret = __vmalloc(size, flags | __GFP_ZERO, PAGE_KERNEL);
+ return ret;
+}
+EXPORT_SYMBOL(libcfs_kvzalloc);
+
+void *libcfs_kvzalloc_cpt(struct cfs_cpt_table *cptab, int cpt, size_t size,
+ gfp_t flags)
+{
+ void *ret;
+
+ ret = kzalloc_node(size, flags | __GFP_NOWARN,
+ cfs_cpt_spread_node(cptab, cpt));
+ if (!ret) {
+ WARN_ON(!(flags & (__GFP_FS|__GFP_HIGH)));
+ ret = vmalloc_node(size, cfs_cpt_spread_node(cptab, cpt));
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(libcfs_kvzalloc_cpt);
down_write(&llioc.ioc_sem);
list_for_each_entry(tmp, &llioc.ioc_head, iocd_list) {
if (tmp == magic) {
- unsigned int size = tmp->iocd_size;
-
list_del(&tmp->iocd_list);
up_write(&llioc.ioc_sem);
char *dt = NULL, *md = NULL;
char *profilenm = get_profile_name(sb);
struct config_llog_instance *cfg;
- /* %p for void* in printf needs 16+2 characters: 0xffffffffffffffff */
- const int instlen = sizeof(cfg->cfg_instance) * 2 + 2;
int err;
CDEBUG(D_VFSTRACE, "VFS Op: sb %p\n", sb);
# define PINVRNT(env, page, exp) \
((void)sizeof(env), (void)sizeof(page), (void)sizeof !!(exp))
-/* Disable page statistic by default due to huge performance penalty. */
-#define CS_PAGE_INC(o, item)
-#define CS_PAGE_DEC(o, item)
-#define CS_PAGESTATE_INC(o, state)
-#define CS_PAGESTATE_DEC(o, state)
-
/**
* Internal version of cl_page_top, it should be called if the page is
* known to be not freed, says with page referenced, or radix tree lock held,
static void cl_page_free(const struct lu_env *env, struct cl_page *page)
{
struct cl_object *obj = page->cp_obj;
- int pagesize = cl_object_header(obj)->coh_page_bufsize;
PASSERT(env, page, list_empty(&page->cp_batch));
PASSERT(env, page, page->cp_owner == NULL);
list_del_init(page->cp_layers.next);
slice->cpl_ops->cpo_fini(env, slice);
}
- CS_PAGE_DEC(obj, total);
- CS_PAGESTATE_DEC(obj, page->cp_state);
lu_object_ref_del_at(&obj->co_lu, &page->cp_obj_ref, "cl_page", page);
cl_object_put(env, obj);
lu_ref_fini(&page->cp_reference);
}
}
}
- if (result == 0) {
- CS_PAGE_INC(o, total);
- CS_PAGE_INC(o, create);
- CS_PAGESTATE_DEC(o, CPS_CACHED);
- }
} else {
page = ERR_PTR(-ENOMEM);
}
might_sleep();
hdr = cl_object_header(o);
- CS_PAGE_INC(o, lookup);
CDEBUG(D_PAGE, "%lu@"DFID" %p %lx %d\n",
idx, PFID(&hdr->coh_lu.loh_fid), vmpage, vmpage->private, type);
}
if (page != NULL) {
- CS_PAGE_INC(o, hit);
return page;
}
PASSERT(env, page,
equi(state == CPS_OWNED, page->cp_owner != NULL));
- CS_PAGESTATE_DEC(page->cp_obj, page->cp_state);
- CS_PAGESTATE_INC(page->cp_obj, state);
cl_page_state_set_trust(page, state);
}
}
bool "OMAP 4 Camera support"
depends on VIDEO_V4L2=y && VIDEO_V4L2_SUBDEV_API && I2C=y && ARCH_OMAP4
depends on HAS_DMA
+ select MFD_SYSCON
select VIDEOBUF2_DMA_CONTIG
---help---
Driver for an OMAP 4 ISS controller.
#include <linux/dma-mapping.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
platform_set_drvdata(pdev, iss);
+ /*
+ * TODO: When implementing DT support switch to syscon regmap lookup by
+ * phandle.
+ */
+ iss->syscon = syscon_regmap_lookup_by_compatible("syscon");
+ if (IS_ERR(iss->syscon)) {
+ ret = PTR_ERR(iss->syscon);
+ goto error;
+ }
+
/* Clocks */
ret = iss_map_mem_resource(pdev, iss, OMAP4_ISS_MEM_TOP);
if (ret < 0)
#include "iss_ipipe.h"
#include "iss_resizer.h"
+struct regmap;
+
#define to_iss_device(ptr_module) \
container_of(ptr_module, struct iss_device, ptr_module)
#define to_device(ptr_module) \
/*
* struct iss_device - ISS device structure.
+ * @syscon: Regmap for the syscon register space
* @crashed: Bitmask of crashed entities (indexed by entity ID)
*/
struct iss_device {
struct resource *res[OMAP4_ISS_MEM_LAST];
void __iomem *regs[OMAP4_ISS_MEM_LAST];
+ struct regmap *syscon;
u64 raw_dmamask;
#include <linux/delay.h>
#include <linux/device.h>
+#include <linux/regmap.h>
#include "../../../../arch/arm/mach-omap2/control.h"
* - bit [18] : CSIPHY1 CTRLCLK enable
* - bit [17:16] : CSIPHY1 config: 00 d-phy, 01/10 ccp2
*/
- cam_rx_ctrl = omap4_ctrl_pad_readl(
- OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX);
-
+ /*
+ * TODO: When implementing DT support specify the CONTROL_CAMERA_RX
+ * register offset in the syscon property instead of hardcoding it.
+ */
+ regmap_read(iss->syscon, 0x68, &cam_rx_ctrl);
if (subdevs->interface == ISS_INTERFACE_CSI2A_PHY1) {
cam_rx_ctrl &= ~(OMAP4_CAMERARX_CSI21_LANEENABLE_MASK |
cam_rx_ctrl |= OMAP4_CAMERARX_CSI22_CTRLCLKEN_MASK;
}
- omap4_ctrl_pad_writel(cam_rx_ctrl,
- OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_CAMERA_RX);
+ regmap_write(iss->syscon, 0x68, cam_rx_ctrl);
/* Reset used lane count */
csi2->phy->used_data_lanes = 0;
struct rtllib_rx_stats stats = {
.signal = 0,
- .noise = -98,
+ .noise = (u8) -98,
.rate = 0,
.freq = RTLLIB_24GHZ_BAND,
};
#include "r8192E_phyreg.h"
#include "r8190P_rtl8256.h" /* RTL8225 Radio frontend */
#include "r8192E_cmdpkt.h"
+#include <linux/jiffies.h>
static void rtl8192_hw_sleep_down(struct net_device *dev)
{
u32 tmp;
unsigned long flags;
+ unsigned long timeout;
spin_lock_irqsave(&priv->ps_lock, flags);
time -= msecs_to_jiffies(8 + 16 + 7);
- if ((time - jiffies) <= msecs_to_jiffies(MIN_SLEEP_TIME)) {
+ timeout = jiffies + msecs_to_jiffies(MIN_SLEEP_TIME);
+ if (time_before((unsigned long)time,timeout)) {
spin_unlock_irqrestore(&priv->ps_lock, flags);
netdev_info(dev, "too short to sleep::%lld < %ld\n",
time - jiffies, msecs_to_jiffies(MIN_SLEEP_TIME));
return;
}
-
- if ((time - jiffies) > msecs_to_jiffies(MAX_SLEEP_TIME)) {
+ timeout = jiffies + msecs_to_jiffies(MAX_SLEEP_TIME);
+ if (time_after((unsigned long)time, timeout)) {
netdev_info(dev, "========>too long to sleep:%lld > %ld\n",
time - jiffies, msecs_to_jiffies(MAX_SLEEP_TIME));
spin_unlock_irqrestore(&priv->ps_lock, flags);
return -ENOMEM;
}
}
- return cpu_to_le16(a->status);
+ return le16_to_cpu(a->status);
}
static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
struct mp_ioctl_handler *phandler;
struct mp_ioctl_param *poidparam;
unsigned long BytesRead, BytesWritten, BytesNeeded;
- u8 *pparmbuf = NULL, bset;
+ u8 *pparmbuf, bset;
u16 len;
uint status;
int ret = 0;
- if ((!p->length) || (!p->pointer)) {
- ret = -EINVAL;
- goto _r871x_mp_ioctl_hdl_exit;
- }
+ if ((!p->length) || (!p->pointer))
+ return -EINVAL;
+
bset = (u8)(p->flags & 0xFFFF);
len = p->length;
- pparmbuf = NULL;
pparmbuf = memdup_user(p->pointer, len);
- if (IS_ERR(pparmbuf)) {
- ret = PTR_ERR(pparmbuf);
- goto _r871x_mp_ioctl_hdl_exit;
- }
+ if (IS_ERR(pparmbuf))
+ return PTR_ERR(pparmbuf);
+
poidparam = (struct mp_ioctl_param *)pparmbuf;
if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
ret = -EINVAL;
- state variables for things that are
easily available and shouldn't be kept in card structure, cardnum, ...
slotnumber, events, ...
- - get rid of slic_spinlock wrapper
- volatile == bad design => bad code
- locking too fine grained, not designed just throw more locks
at problem
static u32 GBRcvUCodeLen = 512;
#define SECTION_SIZE 65536
-struct slic_spinlock {
- spinlock_t lock;
- unsigned long flags;
-};
-
#define SLIC_RSPQ_PAGES_GB 10
#define SLIC_RSPQ_BUFSINPAGE (PAGE_SIZE / SLIC_RSPBUF_SIZE)
struct slic_hostcmd *head;
struct slic_hostcmd *tail;
int count;
- struct slic_spinlock lock;
+ spinlock_t lock;
};
#define SLIC_MAX_CARDS 32
};
struct base_driver {
- struct slic_spinlock driver_lock;
+ spinlock_t driver_lock;
u32 num_slic_cards;
u32 num_slic_ports;
u32 num_slic_ports_active;
uint card_size;
uint chipid;
struct net_device *netdev;
- struct slic_spinlock adapter_lock;
- struct slic_spinlock reset_lock;
+ spinlock_t adapter_lock;
+ spinlock_t reset_lock;
struct pci_dev *pcidev;
uint busnumber;
uint slotnumber;
u32 intrregistered;
uint isp_initialized;
uint gennumber;
- u32 curaddrupper;
struct slic_shmem *pshmem;
dma_addr_t phys_shmem;
u32 isrcopy;
u32 pingtimerset;
struct timer_list loadtimer;
u32 loadtimerset;
- struct slic_spinlock upr_lock;
- struct slic_spinlock bit64reglock;
+ spinlock_t upr_lock;
+ spinlock_t bit64reglock;
struct slic_rspqueue rspqueue;
struct slic_rcvqueue rcvqueue;
struct slic_cmdqueue cmdq_free;
/* Free object handles*/
struct slic_handle *pfree_slic_handles;
/* Object handle list lock*/
- struct slic_spinlock handle_lock;
+ spinlock_t handle_lock;
ushort slic_handle_ix;
u32 xmitq_full;
u32 value, void __iomem *regh, u32 paddrh,
bool flush)
{
- spin_lock_irqsave(&adapter->bit64reglock.lock,
- adapter->bit64reglock.flags);
- if (paddrh != adapter->curaddrupper) {
- adapter->curaddrupper = paddrh;
- writel(paddrh, regh);
- }
+ unsigned long flags;
+
+ spin_lock_irqsave(&adapter->bit64reglock, flags);
+ writel(paddrh, regh);
writel(value, reg);
if (flush)
mb();
- spin_unlock_irqrestore(&adapter->bit64reglock.lock,
- adapter->bit64reglock.flags);
+ spin_unlock_irqrestore(&adapter->bit64reglock, flags);
}
static void slic_mcast_set_bit(struct adapter *adapter, char *address)
u32 upr_data_h,
u32 upr_buffer, u32 upr_buffer_h)
{
+ unsigned long flags;
int rc;
- spin_lock_irqsave(&adapter->upr_lock.lock, adapter->upr_lock.flags);
+ spin_lock_irqsave(&adapter->upr_lock, flags);
rc = slic_upr_queue_request(adapter,
upr_request,
upr_data,
slic_upr_start(adapter);
err_unlock_irq:
- spin_unlock_irqrestore(&adapter->upr_lock.lock,
- adapter->upr_lock.flags);
+ spin_unlock_irqrestore(&adapter->upr_lock, flags);
return rc;
}
{
struct sliccard *card = adapter->card;
struct slic_upr *upr;
+ unsigned long flags;
- spin_lock_irqsave(&adapter->upr_lock.lock, adapter->upr_lock.flags);
+ spin_lock_irqsave(&adapter->upr_lock, flags);
upr = adapter->upr_list;
if (!upr) {
- spin_unlock_irqrestore(&adapter->upr_lock.lock,
- adapter->upr_lock.flags);
+ spin_unlock_irqrestore(&adapter->upr_lock, flags);
return;
}
adapter->upr_list = upr->next;
}
kfree(upr);
slic_upr_start(adapter);
- spin_unlock_irqrestore(&adapter->upr_lock.lock,
- adapter->upr_lock.flags);
+ spin_unlock_irqrestore(&adapter->upr_lock, flags);
}
static int slic_config_get(struct adapter *adapter, u32 config, u32 config_h)
u32 phys_addrl;
u32 phys_addrh;
struct slic_handle *pslic_handle;
+ unsigned long flags;
cmdaddr = page;
cmd = (struct slic_hostcmd *)cmdaddr;
while ((cmdcnt < SLIC_CMDQ_CMDSINPAGE) &&
(adapter->slic_handle_ix < 256)) {
/* Allocate and initialize a SLIC_HANDLE for this command */
- spin_lock_irqsave(&adapter->handle_lock.lock,
- adapter->handle_lock.flags);
+ spin_lock_irqsave(&adapter->handle_lock, flags);
pslic_handle = adapter->pfree_slic_handles;
adapter->pfree_slic_handles = pslic_handle->next;
- spin_unlock_irqrestore(&adapter->handle_lock.lock,
- adapter->handle_lock.flags);
+ spin_unlock_irqrestore(&adapter->handle_lock, flags);
pslic_handle->type = SLIC_HANDLE_CMD;
pslic_handle->address = (void *) cmd;
pslic_handle->offset = (ushort) adapter->slic_handle_ix++;
tail->next_all = cmdq->head;
cmdq->head = prev;
cmdq = &adapter->cmdq_free;
- spin_lock_irqsave(&cmdq->lock.lock, cmdq->lock.flags);
+ spin_lock_irqsave(&cmdq->lock, flags);
cmdq->count += cmdcnt; /* SLIC_CMDQ_CMDSINPAGE; mooktodo */
tail->next = cmdq->head;
cmdq->head = prev;
- spin_unlock_irqrestore(&cmdq->lock.lock, cmdq->lock.flags);
+ spin_unlock_irqrestore(&cmdq->lock, flags);
}
static int slic_cmdq_init(struct adapter *adapter)
memset(&adapter->cmdq_all, 0, sizeof(struct slic_cmdqueue));
memset(&adapter->cmdq_free, 0, sizeof(struct slic_cmdqueue));
memset(&adapter->cmdq_done, 0, sizeof(struct slic_cmdqueue));
- spin_lock_init(&adapter->cmdq_all.lock.lock);
- spin_lock_init(&adapter->cmdq_free.lock.lock);
- spin_lock_init(&adapter->cmdq_done.lock.lock);
+ spin_lock_init(&adapter->cmdq_all.lock);
+ spin_lock_init(&adapter->cmdq_free.lock);
+ spin_lock_init(&adapter->cmdq_done.lock);
memset(&adapter->cmdqmem, 0, sizeof(struct slic_cmdqmem));
adapter->slic_handle_ix = 1;
for (i = 0; i < SLIC_CMDQ_INITPAGES; i++) {
struct slic_hostcmd *hcmd;
struct sk_buff *skb;
u32 outstanding;
+ unsigned long flags;
- spin_lock_irqsave(&adapter->cmdq_free.lock.lock,
- adapter->cmdq_free.lock.flags);
- spin_lock_irqsave(&adapter->cmdq_done.lock.lock,
- adapter->cmdq_done.lock.flags);
+ spin_lock_irqsave(&adapter->cmdq_free.lock, flags);
+ spin_lock_irqsave(&adapter->cmdq_done.lock, flags);
outstanding = adapter->cmdq_all.count - adapter->cmdq_done.count;
outstanding -= adapter->cmdq_free.count;
hcmd = adapter->cmdq_all.head;
"free_count %d != all count %d\n",
adapter->cmdq_free.count, adapter->cmdq_all.count);
}
- spin_unlock_irqrestore(&adapter->cmdq_done.lock.lock,
- adapter->cmdq_done.lock.flags);
- spin_unlock_irqrestore(&adapter->cmdq_free.lock.lock,
- adapter->cmdq_free.lock.flags);
+ spin_unlock_irqrestore(&adapter->cmdq_done.lock, flags);
+ spin_unlock_irqrestore(&adapter->cmdq_free.lock, flags);
}
static void slic_cmdq_getdone(struct adapter *adapter)
{
struct slic_cmdqueue *done_cmdq = &adapter->cmdq_done;
struct slic_cmdqueue *free_cmdq = &adapter->cmdq_free;
+ unsigned long flags;
- spin_lock_irqsave(&done_cmdq->lock.lock, done_cmdq->lock.flags);
+ spin_lock_irqsave(&done_cmdq->lock, flags);
free_cmdq->head = done_cmdq->head;
free_cmdq->count = done_cmdq->count;
done_cmdq->head = NULL;
done_cmdq->tail = NULL;
done_cmdq->count = 0;
- spin_unlock_irqrestore(&done_cmdq->lock.lock, done_cmdq->lock.flags);
+ spin_unlock_irqrestore(&done_cmdq->lock, flags);
}
static struct slic_hostcmd *slic_cmdq_getfree(struct adapter *adapter)
{
struct slic_cmdqueue *cmdq = &adapter->cmdq_free;
struct slic_hostcmd *cmd = NULL;
+ unsigned long flags;
lock_and_retry:
- spin_lock_irqsave(&cmdq->lock.lock, cmdq->lock.flags);
+ spin_lock_irqsave(&cmdq->lock, flags);
retry:
cmd = cmdq->head;
if (cmd) {
cmdq->head = cmd->next;
cmdq->count--;
- spin_unlock_irqrestore(&cmdq->lock.lock, cmdq->lock.flags);
+ spin_unlock_irqrestore(&cmdq->lock, flags);
} else {
slic_cmdq_getdone(adapter);
cmd = cmdq->head;
} else {
u32 *pageaddr;
- spin_unlock_irqrestore(&cmdq->lock.lock,
- cmdq->lock.flags);
+ spin_unlock_irqrestore(&cmdq->lock, flags);
pageaddr = slic_cmdqmem_addpage(adapter);
if (pageaddr) {
slic_cmdq_addcmdpage(adapter, pageaddr);
{
struct slic_cmdqueue *cmdq = &adapter->cmdq_done;
- spin_lock(&cmdq->lock.lock);
+ spin_lock(&cmdq->lock);
cmd->busy = 0;
cmd->next = cmdq->head;
cmdq->head = cmd;
cmdq->count++;
if ((adapter->xmitq_full) && (cmdq->count > 10))
netif_wake_queue(adapter->netdev);
- spin_unlock(&cmdq->lock.lock);
+ spin_unlock(&cmdq->lock);
}
static int slic_rcvqueue_fill(struct adapter *adapter)
adapter->rcv_unicasts = 0;
}
-static int slic_adapter_allocresources(struct adapter *adapter)
+static int slic_adapter_allocresources(struct adapter *adapter,
+ unsigned long *flags)
{
if (!adapter->intrregistered) {
int retval;
- spin_unlock_irqrestore(&slic_global.driver_lock.lock,
- slic_global.driver_lock.flags);
+ spin_unlock_irqrestore(&slic_global.driver_lock, *flags);
retval = request_irq(adapter->netdev->irq,
&slic_interrupt,
IRQF_SHARED,
adapter->netdev->name, adapter->netdev);
- spin_lock_irqsave(&slic_global.driver_lock.lock,
- slic_global.driver_lock.flags);
+ spin_lock_irqsave(&slic_global.driver_lock, *flags);
if (retval) {
dev_err(&adapter->netdev->dev,
* Perform initialization of our slic interface.
*
*/
-static int slic_if_init(struct adapter *adapter)
+static int slic_if_init(struct adapter *adapter, unsigned long *flags)
{
struct sliccard *card = adapter->card;
struct net_device *dev = adapter->netdev;
if (dev->flags & IFF_MULTICAST)
adapter->macopts |= MAC_MCAST;
}
- rc = slic_adapter_allocresources(adapter);
+ rc = slic_adapter_allocresources(adapter, flags);
if (rc) {
dev_err(&dev->dev, "slic_adapter_allocresources FAILED %x\n",
rc);
mdelay(1);
if (!adapter->isp_initialized) {
+ unsigned long flags;
pshmem = (struct slic_shmem *)(unsigned long)
adapter->phys_shmem;
- spin_lock_irqsave(&adapter->bit64reglock.lock,
- adapter->bit64reglock.flags);
+ spin_lock_irqsave(&adapter->bit64reglock, flags);
#if BITS_PER_LONG == 64
slic_reg32_write(&slic_regs->slic_addr_upper,
slic_reg32_write(&slic_regs->slic_isp, (u32)&pshmem->isr,
FLUSH);
#endif
- spin_unlock_irqrestore(&adapter->bit64reglock.lock,
- adapter->bit64reglock.flags);
+ spin_unlock_irqrestore(&adapter->bit64reglock, flags);
adapter->isp_initialized = 1;
}
{
struct adapter *adapter = netdev_priv(dev);
struct sliccard *card = adapter->card;
+ unsigned long flags;
int status;
netif_stop_queue(adapter->netdev);
- spin_lock_irqsave(&slic_global.driver_lock.lock,
- slic_global.driver_lock.flags);
+ spin_lock_irqsave(&slic_global.driver_lock, flags);
if (!adapter->activated) {
card->adapters_activated++;
slic_global.num_slic_ports_active++;
adapter->activated = 1;
}
- status = slic_if_init(adapter);
+ status = slic_if_init(adapter, &flags);
if (status != 0) {
if (adapter->activated) {
card->master = adapter;
spin_unlock:
- spin_unlock_irqrestore(&slic_global.driver_lock.lock,
- slic_global.driver_lock.flags);
+ spin_unlock_irqrestore(&slic_global.driver_lock, flags);
return status;
}
struct adapter *adapter = netdev_priv(dev);
struct sliccard *card = adapter->card;
__iomem struct slic_regs *slic_regs = adapter->slic_regs;
+ unsigned long flags;
- spin_lock_irqsave(&slic_global.driver_lock.lock,
- slic_global.driver_lock.flags);
+ spin_lock_irqsave(&slic_global.driver_lock, flags);
netif_stop_queue(adapter->netdev);
adapter->state = ADAPT_DOWN;
adapter->linkstate = LINK_DOWN;
slic_card_init(card, adapter);
#endif
- spin_unlock_irqrestore(&slic_global.driver_lock.lock,
- slic_global.driver_lock.flags);
+ spin_unlock_irqrestore(&slic_global.driver_lock, flags);
return 0;
}
unsigned char oemfruformat;
struct atk_fru *patkfru;
union oemfru *poemfru;
+ unsigned long flags;
/* Reset everything except PCI configuration space */
slic_soft_reset(adapter);
pshmem = (struct slic_shmem *)(unsigned long)
adapter->phys_shmem;
- spin_lock_irqsave(&adapter->bit64reglock.lock,
- adapter->bit64reglock.flags);
+ spin_lock_irqsave(&adapter->bit64reglock, flags);
slic_reg32_write(&slic_regs->slic_addr_upper,
SLIC_GET_ADDR_HIGH(&pshmem->isr), DONT_FLUSH);
slic_reg32_write(&slic_regs->slic_isp,
SLIC_GET_ADDR_LOW(&pshmem->isr), FLUSH);
- spin_unlock_irqrestore(&adapter->bit64reglock.lock,
- adapter->bit64reglock.flags);
+ spin_unlock_irqrestore(&adapter->bit64reglock, flags);
status = slic_config_get(adapter, phys_configl, phys_configh);
if (status) {
{
if (slic_first_init) {
slic_first_init = 0;
- spin_lock_init(&slic_global.driver_lock.lock);
+ spin_lock_init(&slic_global.driver_lock);
}
}
adapter->chipid = chip_idx;
adapter->port = 0; /*adapter->functionnumber;*/
adapter->cardindex = adapter->port;
- spin_lock_init(&adapter->upr_lock.lock);
- spin_lock_init(&adapter->bit64reglock.lock);
- spin_lock_init(&adapter->adapter_lock.lock);
- spin_lock_init(&adapter->reset_lock.lock);
- spin_lock_init(&adapter->handle_lock.lock);
+ spin_lock_init(&adapter->upr_lock);
+ spin_lock_init(&adapter->bit64reglock);
+ spin_lock_init(&adapter->adapter_lock);
+ spin_lock_init(&adapter->reset_lock);
+ spin_lock_init(&adapter->handle_lock);
adapter->card_size = 1;
/*
return -ENODEV;
}
-static void __exit lynxfb_pci_remove(struct pci_dev *pdev)
+static void lynxfb_pci_remove(struct pci_dev *pdev)
{
struct fb_info *info;
struct lynx_share *share;
* Return Value: none
*/
bool CARDbUpdateTSF(struct vnt_private *pDevice, unsigned char byRxRate,
- u64 qwBSSTimestamp, u64 qwLocalTSF)
+ u64 qwBSSTimestamp)
{
+ u64 local_tsf;
u64 qwTSFOffset = 0;
- if (qwBSSTimestamp != qwLocalTSF) {
- qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp, qwLocalTSF);
+ CARDbGetCurrentTSF(pDevice, &local_tsf);
+
+ if (qwBSSTimestamp != local_tsf) {
+ qwTSFOffset = CARDqGetTSFOffset(byRxRate, qwBSSTimestamp,
+ local_tsf);
/* adjust TSF, HW's TSF add TSF Offset reg */
VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST, (u32)qwTSFOffset);
VNSvOutPortD(pDevice->PortOffset + MAC_REG_TSFOFST + 4, (u32)(qwTSFOffset >> 32));
bool CARDbRadioPowerOn(struct vnt_private *);
bool CARDbSetPhyParameter(struct vnt_private *, u8);
bool CARDbUpdateTSF(struct vnt_private *, unsigned char byRxRate,
- u64 qwBSSTimestamp, u64 qwLocalTSF);
+ u64 qwBSSTimestamp);
bool CARDbSetBeaconPeriod(struct vnt_private *, unsigned short wBeaconInterval);
#endif /* __CARD_H__ */
if (!(tsr1 & TSR1_TERR)) {
info->status.rates[0].idx = idx;
- info->flags |= IEEE80211_TX_STAT_ACK;
+
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
+ else
+ info->flags |= IEEE80211_TX_STAT_ACK;
}
return 0;
/* 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) {
-
- vnt_int_report_rate(pDevice, pTD->pTDInfo, byTsr0, byTsr1);
-
if (!(byTsr1 & TSR1_TERR)) {
if (byTsr0 != 0) {
pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n",
(int)uIdx, byTsr1, byTsr0);
}
}
+
+ vnt_int_report_rate(pDevice, pTD->pTDInfo, byTsr0, byTsr1);
+
device_free_tx_buf(pDevice, pTD);
pDevice->iTDUsed[uIdx]--;
}
skb->len, DMA_TO_DEVICE);
}
- if (pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)
+ if (skb)
ieee80211_tx_status_irqsafe(pDevice->hw, skb);
- else
- dev_kfree_skb_irq(skb);
pTDInfo->skb_dma = 0;
pTDInfo->skb = NULL;
if (dma_idx == TYPE_AC0DMA)
head_td->pTDInfo->byFlags = TD_FLAGS_NETIF_SKB;
- priv->iTDUsed[dma_idx]++;
-
- /* Take ownership */
- wmb();
- head_td->m_td0TD0.f1Owner = OWNED_BY_NIC;
-
- /* get Next */
- wmb();
priv->apCurrTD[dma_idx] = head_td->next;
spin_unlock_irqrestore(&priv->lock, flags);
head_td->buff_addr = cpu_to_le32(head_td->pTDInfo->skb_dma);
+ /* Poll Transmit the adapter */
+ wmb();
+ head_td->m_td0TD0.f1Owner = OWNED_BY_NIC;
+ wmb(); /* second memory barrier */
+
if (head_td->pTDInfo->byFlags & TD_FLAGS_NETIF_SKB)
MACvTransmitAC0(priv->PortOffset);
else
MACvTransmit0(priv->PortOffset);
+ priv->iTDUsed[dma_idx]++;
+
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
priv->current_aid = conf->aid;
- if (changed & BSS_CHANGED_BSSID)
+ if (changed & BSS_CHANGED_BSSID) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
MACvWriteBSSIDAddress(priv->PortOffset, (u8 *)conf->bssid);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+
if (changed & BSS_CHANGED_BASIC_RATES) {
priv->basic_rates = conf->basic_rates;
if (changed & BSS_CHANGED_ASSOC && priv->op_mode != NL80211_IFTYPE_AP) {
if (conf->assoc) {
CARDbUpdateTSF(priv, conf->beacon_rate->hw_value,
- conf->sync_device_ts, conf->sync_tsf);
+ conf->sync_tsf);
CARDbSetBeaconPeriod(priv, conf->beacon_int);
vnt_schedule_command(priv, WLAN_CMD_SETPOWER);
}
- if (current_rate > RATE_11M)
- pkt_type = priv->packet_type;
- else
+ if (current_rate > RATE_11M) {
+ if (info->band == IEEE80211_BAND_5GHZ) {
+ pkt_type = PK_TYPE_11A;
+ } else {
+ if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+ pkt_type = PK_TYPE_11GB;
+ else
+ pkt_type = PK_TYPE_11GA;
+ }
+ } else {
pkt_type = PK_TYPE_11B;
+ }
spin_lock_irqsave(&priv->lock, flags);
}
+struct pkg_cstate_info {
+ bool skip;
+ int msr_index;
+ int cstate_id;
+};
+
+#define PKG_CSTATE_INIT(id) { \
+ .msr_index = MSR_PKG_C##id##_RESIDENCY, \
+ .cstate_id = id \
+ }
+
+static struct pkg_cstate_info pkg_cstates[] = {
+ PKG_CSTATE_INIT(2),
+ PKG_CSTATE_INIT(3),
+ PKG_CSTATE_INIT(6),
+ PKG_CSTATE_INIT(7),
+ PKG_CSTATE_INIT(8),
+ PKG_CSTATE_INIT(9),
+ PKG_CSTATE_INIT(10),
+ {NULL},
+};
+
static bool has_pkg_state_counter(void)
{
- u64 tmp;
- return !rdmsrl_safe(MSR_PKG_C2_RESIDENCY, &tmp) ||
- !rdmsrl_safe(MSR_PKG_C3_RESIDENCY, &tmp) ||
- !rdmsrl_safe(MSR_PKG_C6_RESIDENCY, &tmp) ||
- !rdmsrl_safe(MSR_PKG_C7_RESIDENCY, &tmp);
+ u64 val;
+ struct pkg_cstate_info *info = pkg_cstates;
+
+ /* check if any one of the counter msrs exists */
+ while (info->msr_index) {
+ if (!rdmsrl_safe(info->msr_index, &val))
+ return true;
+ info++;
+ }
+
+ return false;
}
static u64 pkg_state_counter(void)
{
u64 val;
u64 count = 0;
-
- static bool skip_c2;
- static bool skip_c3;
- static bool skip_c6;
- static bool skip_c7;
-
- if (!skip_c2) {
- if (!rdmsrl_safe(MSR_PKG_C2_RESIDENCY, &val))
- count += val;
- else
- skip_c2 = true;
- }
-
- if (!skip_c3) {
- if (!rdmsrl_safe(MSR_PKG_C3_RESIDENCY, &val))
- count += val;
- else
- skip_c3 = true;
- }
-
- if (!skip_c6) {
- if (!rdmsrl_safe(MSR_PKG_C6_RESIDENCY, &val))
- count += val;
- else
- skip_c6 = true;
- }
-
- if (!skip_c7) {
- if (!rdmsrl_safe(MSR_PKG_C7_RESIDENCY, &val))
- count += val;
- else
- skip_c7 = true;
+ struct pkg_cstate_info *info = pkg_cstates;
+
+ while (info->msr_index) {
+ if (!info->skip) {
+ if (!rdmsrl_safe(info->msr_index, &val))
+ count += val;
+ else
+ info->skip = true;
+ }
+ info++;
}
return count;
};
/* runs on Nehalem and later */
-static const struct x86_cpu_id intel_powerclamp_ids[] = {
+static const struct x86_cpu_id intel_powerclamp_ids[] __initconst = {
{ X86_VENDOR_INTEL, 6, 0x1a},
{ X86_VENDOR_INTEL, 6, 0x1c},
{ X86_VENDOR_INTEL, 6, 0x1e},
{ X86_VENDOR_INTEL, 6, 0x46},
{ X86_VENDOR_INTEL, 6, 0x4c},
{ X86_VENDOR_INTEL, 6, 0x4d},
+ { X86_VENDOR_INTEL, 6, 0x4f},
{ X86_VENDOR_INTEL, 6, 0x56},
{}
};
MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids);
-static int powerclamp_probe(void)
+static int __init powerclamp_probe(void)
{
if (!x86_match_cpu(intel_powerclamp_ids)) {
pr_err("Intel powerclamp does not run on family %d model %d\n",
debugfs_remove_recursive(debug_dir);
}
-static int powerclamp_init(void)
+static int __init powerclamp_init(void)
{
int retval;
int bitmap_size;
}
module_init(powerclamp_init);
-static void powerclamp_exit(void)
+static void __exit powerclamp_exit(void)
{
unregister_hotcpu_notifier(&powerclamp_cpu_notifier);
end_power_clamp();
thermal->pclk = devm_clk_get(&pdev->dev, "apb_pclk");
if (IS_ERR(thermal->pclk)) {
- error = PTR_ERR(thermal->clk);
+ error = PTR_ERR(thermal->pclk);
dev_err(&pdev->dev, "failed to get apb_pclk clock: %d\n",
error);
return error;
static inline bool of_thermal_is_trip_valid(struct thermal_zone_device *tz,
int trip)
{
- return 0;
+ return false;
}
static inline const struct thermal_trip *
of_thermal_get_trip_points(struct thermal_zone_device *tz)
return 0;
}
+static void xen_console_update_evtchn(struct xencons_info *info)
+{
+ if (xen_hvm_domain()) {
+ uint64_t v;
+ int err;
+
+ err = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v);
+ if (!err && v)
+ info->evtchn = v;
+ } else
+ info->evtchn = xen_start_info->console.domU.evtchn;
+}
+
void xen_console_resume(void)
{
struct xencons_info *info = vtermno_to_xencons(HVC_COOKIE);
- if (info != NULL && info->irq)
+ if (info != NULL && info->irq) {
+ if (!xen_initial_domain())
+ xen_console_update_evtchn(info);
rebind_evtchn_irq(info->evtchn, info->irq);
+ }
}
static void xencons_disconnect_backend(struct xencons_info *info)
return gsmtty_modem_update(dlci, encode);
}
-static void gsmtty_remove(struct tty_driver *driver, struct tty_struct *tty)
+static void gsmtty_cleanup(struct tty_struct *tty)
{
struct gsm_dlci *dlci = tty->driver_data;
struct gsm_mux *gsm = dlci->gsm;
dlci_put(dlci);
dlci_put(gsm->dlci[0]);
mux_put(gsm);
- driver->ttys[tty->index] = NULL;
}
/* Virtual ttys for the demux */
.tiocmget = gsmtty_tiocmget,
.tiocmset = gsmtty_tiocmset,
.break_ctl = gsmtty_break_ctl,
- .remove = gsmtty_remove,
+ .cleanup = gsmtty_cleanup,
};
add_wait_queue(&tty->read_wait, &wait);
for (;;) {
- if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
+ if (test_bit(TTY_OTHER_DONE, &tty->flags)) {
ret = -EIO;
break;
}
/* set bits for operations that won't block */
if (n_hdlc->rx_buf_list.head)
mask |= POLLIN | POLLRDNORM; /* readable */
- if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
+ if (test_bit(TTY_OTHER_DONE, &tty->flags))
mask |= POLLHUP;
if (tty_hung_up_p(filp))
mask |= POLLHUP;
return ldata->commit_head - ldata->read_tail >= amt;
}
+static inline int check_other_done(struct tty_struct *tty)
+{
+ int done = test_bit(TTY_OTHER_DONE, &tty->flags);
+ if (done) {
+ /* paired with cmpxchg() in check_other_closed(); ensures
+ * read buffer head index is not stale
+ */
+ smp_mb__after_atomic();
+ }
+ return done;
+}
+
/**
* copy_from_read_buf - copy read data directly
* @tty: terminal device
struct n_tty_data *ldata = tty->disc_data;
unsigned char __user *b = buf;
DEFINE_WAIT_FUNC(wait, woken_wake_function);
- int c;
+ int c, done;
int minimum, time;
ssize_t retval = 0;
long timeout;
((minimum - (b - buf)) >= 1))
ldata->minimum_to_wake = (minimum - (b - buf));
+ done = check_other_done(tty);
+
if (!input_available_p(tty, 0)) {
- if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) {
+ if (done) {
retval = -EIO;
break;
}
poll_wait(file, &tty->read_wait, wait);
poll_wait(file, &tty->write_wait, wait);
+ if (check_other_done(tty))
+ mask |= POLLHUP;
if (input_available_p(tty, 1))
mask |= POLLIN | POLLRDNORM;
if (tty->packet && tty->link->ctrl_status)
mask |= POLLPRI | POLLIN | POLLRDNORM;
- if (test_bit(TTY_OTHER_CLOSED, &tty->flags))
- mask |= POLLHUP;
if (tty_hung_up_p(file))
mask |= POLLHUP;
if (!(mask & (POLLHUP | POLLIN | POLLRDNORM))) {
/* Review - krefs on tty_link ?? */
if (!tty->link)
return;
- tty_flush_to_ldisc(tty->link);
set_bit(TTY_OTHER_CLOSED, &tty->link->flags);
- wake_up_interruptible(&tty->link->read_wait);
+ tty_flip_buffer_push(tty->link->port);
wake_up_interruptible(&tty->link->write_wait);
if (tty->driver->subtype == PTY_TYPE_MASTER) {
set_bit(TTY_OTHER_CLOSED, &tty->flags);
goto out;
clear_bit(TTY_IO_ERROR, &tty->flags);
+ /* TTY_OTHER_CLOSED must be cleared before TTY_OTHER_DONE */
clear_bit(TTY_OTHER_CLOSED, &tty->link->flags);
+ clear_bit(TTY_OTHER_DONE, &tty->link->flags);
set_bit(TTY_THROTTLED, &tty->flags);
return 0;
writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
+ /* Assume that TX IRQ doesn't work until we see one: */
+ uap->tx_irq_seen = 0;
+
spin_lock_irq(&uap->port.lock);
/* restore RTS and DTR */
spin_lock_irq(&uap->port.lock);
uap->im = 0;
writew(uap->im, uap->port.membase + UART011_IMSC);
- writew(0xffff & ~UART011_TXIS, uap->port.membase + UART011_ICR);
+ writew(0xffff, uap->port.membase + UART011_ICR);
spin_unlock_irq(&uap->port.lock);
pl011_dma_shutdown(uap);
return 0;
err = setup_earlycon(buf);
- if (err == -ENOENT) {
- pr_warn("no match for %s\n", buf);
- err = 0;
- } else if (err == -EALREADY) {
- pr_warn("already registered\n");
- err = 0;
- }
+ if (err == -ENOENT || err == -EALREADY)
+ return 0;
return err;
}
early_param("earlycon", param_setup_earlycon);
err_add_port:
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ pm_qos_remove_request(&up->pm_qos_request);
+ device_init_wakeup(up->dev, false);
err_rs485:
err_port_line:
return ret;
#define TTY_BUFFER_PAGE (((PAGE_SIZE - sizeof(struct tty_buffer)) / 2) & ~0xFF)
+/*
+ * If all tty flip buffers have been processed by flush_to_ldisc() or
+ * dropped by tty_buffer_flush(), check if the linked pty has been closed.
+ * If so, wake the reader/poll to process
+ */
+static inline void check_other_closed(struct tty_struct *tty)
+{
+ unsigned long flags, old;
+
+ /* transition from TTY_OTHER_CLOSED => TTY_OTHER_DONE must be atomic */
+ for (flags = ACCESS_ONCE(tty->flags);
+ test_bit(TTY_OTHER_CLOSED, &flags);
+ ) {
+ old = flags;
+ __set_bit(TTY_OTHER_DONE, &flags);
+ flags = cmpxchg(&tty->flags, old, flags);
+ if (old == flags) {
+ wake_up_interruptible(&tty->read_wait);
+ break;
+ }
+ }
+}
/**
* tty_buffer_lock_exclusive - gain exclusive access to buffer
if (ld && ld->ops->flush_buffer)
ld->ops->flush_buffer(tty);
+ check_other_closed(tty);
+
atomic_dec(&buf->priority);
mutex_unlock(&buf->lock);
}
smp_rmb();
count = head->commit - head->read;
if (!count) {
- if (next == NULL)
+ if (next == NULL) {
+ check_other_closed(tty);
break;
+ }
buf->head = next;
tty_buffer_free(port, head);
continue;
tty_ldisc_deref(disc);
}
-/**
- * tty_flush_to_ldisc
- * @tty: tty to push
- *
- * Push the terminal flip buffers to the line discipline.
- *
- * Must not be called from IRQ context.
- */
-void tty_flush_to_ldisc(struct tty_struct *tty)
-{
- flush_work(&tty->port->buf.work);
-}
-
/**
* tty_flip_buffer_push - terminal
* @port: tty port to push
char buf[32];
int ret;
- if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
+ count = min_t(size_t, sizeof(buf) - 1, count);
+ if (copy_from_user(buf, ubuf, count))
return -EFAULT;
+ /* sscanf requires a zero terminated string */
+ buf[count] = '\0';
+
if (sscanf(buf, "%u", &mode) != 1)
return -EINVAL;
{ USB_DEVICE(0x04f3, 0x010c), .driver_info =
USB_QUIRK_DEVICE_QUALIFIER },
+ { USB_DEVICE(0x04f3, 0x0125), .driver_info =
+ USB_QUIRK_DEVICE_QUALIFIER },
+
{ USB_DEVICE(0x04f3, 0x016f), .driver_info =
USB_QUIRK_DEVICE_QUALIFIER },
#define USBOTGSS_IRQENABLE_SET_MISC 0x003c
#define USBOTGSS_IRQENABLE_CLR_MISC 0x0040
#define USBOTGSS_IRQMISC_OFFSET 0x03fc
-#define USBOTGSS_UTMI_OTG_CTRL 0x0080
-#define USBOTGSS_UTMI_OTG_STATUS 0x0084
+#define USBOTGSS_UTMI_OTG_STATUS 0x0080
+#define USBOTGSS_UTMI_OTG_CTRL 0x0084
#define USBOTGSS_UTMI_OTG_OFFSET 0x0480
#define USBOTGSS_TXFIFO_DEPTH 0x0508
#define USBOTGSS_RXFIFO_DEPTH 0x050c
#define USBOTGSS_IRQMISC_DISCHRGVBUS_FALL (1 << 3)
#define USBOTGSS_IRQMISC_IDPULLUP_FALL (1 << 0)
-/* UTMI_OTG_CTRL REGISTER */
-#define USBOTGSS_UTMI_OTG_CTRL_DRVVBUS (1 << 5)
-#define USBOTGSS_UTMI_OTG_CTRL_CHRGVBUS (1 << 4)
-#define USBOTGSS_UTMI_OTG_CTRL_DISCHRGVBUS (1 << 3)
-#define USBOTGSS_UTMI_OTG_CTRL_IDPULLUP (1 << 0)
-
/* UTMI_OTG_STATUS REGISTER */
-#define USBOTGSS_UTMI_OTG_STATUS_SW_MODE (1 << 31)
-#define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT (1 << 9)
-#define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE (1 << 8)
-#define USBOTGSS_UTMI_OTG_STATUS_IDDIG (1 << 4)
-#define USBOTGSS_UTMI_OTG_STATUS_SESSEND (1 << 3)
-#define USBOTGSS_UTMI_OTG_STATUS_SESSVALID (1 << 2)
-#define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID (1 << 1)
+#define USBOTGSS_UTMI_OTG_STATUS_DRVVBUS (1 << 5)
+#define USBOTGSS_UTMI_OTG_STATUS_CHRGVBUS (1 << 4)
+#define USBOTGSS_UTMI_OTG_STATUS_DISCHRGVBUS (1 << 3)
+#define USBOTGSS_UTMI_OTG_STATUS_IDPULLUP (1 << 0)
+
+/* UTMI_OTG_CTRL REGISTER */
+#define USBOTGSS_UTMI_OTG_CTRL_SW_MODE (1 << 31)
+#define USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT (1 << 9)
+#define USBOTGSS_UTMI_OTG_CTRL_TXBITSTUFFENABLE (1 << 8)
+#define USBOTGSS_UTMI_OTG_CTRL_IDDIG (1 << 4)
+#define USBOTGSS_UTMI_OTG_CTRL_SESSEND (1 << 3)
+#define USBOTGSS_UTMI_OTG_CTRL_SESSVALID (1 << 2)
+#define USBOTGSS_UTMI_OTG_CTRL_VBUSVALID (1 << 1)
struct dwc3_omap {
struct device *dev;
int irq;
void __iomem *base;
- u32 utmi_otg_status;
+ u32 utmi_otg_ctrl;
u32 utmi_otg_offset;
u32 irqmisc_offset;
u32 irq_eoi_offset;
writel(value, base + offset);
}
-static u32 dwc3_omap_read_utmi_status(struct dwc3_omap *omap)
+static u32 dwc3_omap_read_utmi_ctrl(struct dwc3_omap *omap)
{
- return dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_STATUS +
+ return dwc3_omap_readl(omap->base, USBOTGSS_UTMI_OTG_CTRL +
omap->utmi_otg_offset);
}
-static void dwc3_omap_write_utmi_status(struct dwc3_omap *omap, u32 value)
+static void dwc3_omap_write_utmi_ctrl(struct dwc3_omap *omap, u32 value)
{
- dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_STATUS +
+ dwc3_omap_writel(omap->base, USBOTGSS_UTMI_OTG_CTRL +
omap->utmi_otg_offset, value);
}
}
}
- val = dwc3_omap_read_utmi_status(omap);
- val &= ~(USBOTGSS_UTMI_OTG_STATUS_IDDIG
- | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
- | USBOTGSS_UTMI_OTG_STATUS_SESSEND);
- val |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID
- | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
- dwc3_omap_write_utmi_status(omap, val);
+ val = dwc3_omap_read_utmi_ctrl(omap);
+ val &= ~(USBOTGSS_UTMI_OTG_CTRL_IDDIG
+ | USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
+ | USBOTGSS_UTMI_OTG_CTRL_SESSEND);
+ val |= USBOTGSS_UTMI_OTG_CTRL_SESSVALID
+ | USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT;
+ dwc3_omap_write_utmi_ctrl(omap, val);
break;
case OMAP_DWC3_VBUS_VALID:
dev_dbg(omap->dev, "VBUS Connect\n");
- val = dwc3_omap_read_utmi_status(omap);
- val &= ~USBOTGSS_UTMI_OTG_STATUS_SESSEND;
- val |= USBOTGSS_UTMI_OTG_STATUS_IDDIG
- | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
- | USBOTGSS_UTMI_OTG_STATUS_SESSVALID
- | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
- dwc3_omap_write_utmi_status(omap, val);
+ val = dwc3_omap_read_utmi_ctrl(omap);
+ val &= ~USBOTGSS_UTMI_OTG_CTRL_SESSEND;
+ val |= USBOTGSS_UTMI_OTG_CTRL_IDDIG
+ | USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
+ | USBOTGSS_UTMI_OTG_CTRL_SESSVALID
+ | USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT;
+ dwc3_omap_write_utmi_ctrl(omap, val);
break;
case OMAP_DWC3_ID_FLOAT:
case OMAP_DWC3_VBUS_OFF:
dev_dbg(omap->dev, "VBUS Disconnect\n");
- val = dwc3_omap_read_utmi_status(omap);
- val &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSVALID
- | USBOTGSS_UTMI_OTG_STATUS_VBUSVALID
- | USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT);
- val |= USBOTGSS_UTMI_OTG_STATUS_SESSEND
- | USBOTGSS_UTMI_OTG_STATUS_IDDIG;
- dwc3_omap_write_utmi_status(omap, val);
+ val = dwc3_omap_read_utmi_ctrl(omap);
+ val &= ~(USBOTGSS_UTMI_OTG_CTRL_SESSVALID
+ | USBOTGSS_UTMI_OTG_CTRL_VBUSVALID
+ | USBOTGSS_UTMI_OTG_CTRL_POWERPRESENT);
+ val |= USBOTGSS_UTMI_OTG_CTRL_SESSEND
+ | USBOTGSS_UTMI_OTG_CTRL_IDDIG;
+ dwc3_omap_write_utmi_ctrl(omap, val);
break;
default:
struct device_node *node = omap->dev->of_node;
int utmi_mode = 0;
- reg = dwc3_omap_read_utmi_status(omap);
+ reg = dwc3_omap_read_utmi_ctrl(omap);
of_property_read_u32(node, "utmi-mode", &utmi_mode);
switch (utmi_mode) {
case DWC3_OMAP_UTMI_MODE_SW:
- reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+ reg |= USBOTGSS_UTMI_OTG_CTRL_SW_MODE;
break;
case DWC3_OMAP_UTMI_MODE_HW:
- reg &= ~USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
+ reg &= ~USBOTGSS_UTMI_OTG_CTRL_SW_MODE;
break;
default:
dev_dbg(omap->dev, "UNKNOWN utmi mode %d\n", utmi_mode);
}
- dwc3_omap_write_utmi_status(omap, reg);
+ dwc3_omap_write_utmi_ctrl(omap, reg);
}
static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
- omap->utmi_otg_status = dwc3_omap_read_utmi_status(omap);
+ omap->utmi_otg_ctrl = dwc3_omap_read_utmi_ctrl(omap);
dwc3_omap_disable_irqs(omap);
return 0;
{
struct dwc3_omap *omap = dev_get_drvdata(dev);
- dwc3_omap_write_utmi_status(omap, omap->utmi_otg_status);
+ dwc3_omap_write_utmi_ctrl(omap, omap->utmi_otg_ctrl);
dwc3_omap_enable_irqs(omap);
pm_runtime_disable(dev);
}
}
c->next_interface_id = 0;
+ memset(c->interface, 0, sizeof(c->interface));
c->superspeed = 0;
c->highspeed = 0;
c->fullspeed = 0;
| USB_REQ_GET_DESCRIPTOR):
switch (value >> 8) {
case HID_DT_HID:
+ {
+ struct hid_descriptor hidg_desc_copy = hidg_desc;
+
VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: HID\n");
+ hidg_desc_copy.desc[0].bDescriptorType = HID_DT_REPORT;
+ hidg_desc_copy.desc[0].wDescriptorLength =
+ cpu_to_le16(hidg->report_desc_length);
+
length = min_t(unsigned short, length,
- hidg_desc.bLength);
- memcpy(req->buf, &hidg_desc, length);
+ hidg_desc_copy.bLength);
+ memcpy(req->buf, &hidg_desc_copy, length);
goto respond;
break;
+ }
case HID_DT_REPORT:
VDBG(cdev, "USB_REQ_GET_DESCRIPTOR: REPORT\n");
length = min_t(unsigned short, length,
hidg_fs_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_hs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
hidg_fs_out_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
+ /*
+ * We can use hidg_desc struct here but we should not relay
+ * that its content won't change after returning from this function.
+ */
hidg_desc.desc[0].bDescriptorType = HID_DT_REPORT;
hidg_desc.desc[0].wDescriptorLength =
cpu_to_le16(hidg->report_desc_length);
int write_allocated;
struct gs_buf port_write_buf;
wait_queue_head_t drain_wait; /* wait while writes drain */
+ bool write_busy;
/* REVISIT this state ... */
struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
int status = 0;
bool do_tty_wake = false;
- while (!list_empty(pool)) {
+ while (!port->write_busy && !list_empty(pool)) {
struct usb_request *req;
int len;
* NOTE that we may keep sending data for a while after
* the TTY closed (dev->ioport->port_tty is NULL).
*/
+ port->write_busy = true;
spin_unlock(&port->port_lock);
status = usb_ep_queue(in, req, GFP_ATOMIC);
spin_lock(&port->port_lock);
+ port->write_busy = false;
if (status) {
pr_debug("%s: %s %s err %d\n",
/*
* We _always_ have both ACM and mass storage functions.
*/
-static int __init acm_ms_do_config(struct usb_configuration *c)
+static int acm_ms_do_config(struct usb_configuration *c)
{
struct fsg_opts *opts;
int status;
/*-------------------------------------------------------------------------*/
-static int __init acm_ms_bind(struct usb_composite_dev *cdev)
+static int acm_ms_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct fsg_opts *opts;
return status;
}
-static int __exit acm_ms_unbind(struct usb_composite_dev *cdev)
+static int acm_ms_unbind(struct usb_composite_dev *cdev)
{
usb_put_function(f_msg);
usb_put_function_instance(fi_msg);
return 0;
}
-static __refdata struct usb_composite_driver acm_ms_driver = {
+static struct usb_composite_driver acm_ms_driver = {
.name = "g_acm_ms",
.dev = &device_desc,
.max_speed = USB_SPEED_SUPER,
.strings = dev_strings,
.bind = acm_ms_bind,
- .unbind = __exit_p(acm_ms_unbind),
+ .unbind = acm_ms_unbind,
};
module_usb_composite_driver(acm_ms_driver);
/*-------------------------------------------------------------------------*/
-static int __init audio_do_config(struct usb_configuration *c)
+static int audio_do_config(struct usb_configuration *c)
{
int status;
/*-------------------------------------------------------------------------*/
-static int __init audio_bind(struct usb_composite_dev *cdev)
+static int audio_bind(struct usb_composite_dev *cdev)
{
#ifndef CONFIG_GADGET_UAC1
struct f_uac2_opts *uac2_opts;
return status;
}
-static int __exit audio_unbind(struct usb_composite_dev *cdev)
+static int audio_unbind(struct usb_composite_dev *cdev)
{
#ifdef CONFIG_GADGET_UAC1
if (!IS_ERR_OR_NULL(f_uac1))
return 0;
}
-static __refdata struct usb_composite_driver audio_driver = {
+static struct usb_composite_driver audio_driver = {
.name = "g_audio",
.dev = &device_desc,
.strings = audio_strings,
.max_speed = USB_SPEED_HIGH,
.bind = audio_bind,
- .unbind = __exit_p(audio_unbind),
+ .unbind = audio_unbind,
};
module_usb_composite_driver(audio_driver);
/*
* We _always_ have both CDC ECM and CDC ACM functions.
*/
-static int __init cdc_do_config(struct usb_configuration *c)
+static int cdc_do_config(struct usb_configuration *c)
{
int status;
/*-------------------------------------------------------------------------*/
-static int __init cdc_bind(struct usb_composite_dev *cdev)
+static int cdc_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct f_ecm_opts *ecm_opts;
return status;
}
-static int __exit cdc_unbind(struct usb_composite_dev *cdev)
+static int cdc_unbind(struct usb_composite_dev *cdev)
{
usb_put_function(f_acm);
usb_put_function_instance(fi_serial);
return 0;
}
-static __refdata struct usb_composite_driver cdc_driver = {
+static struct usb_composite_driver cdc_driver = {
.name = "g_cdc",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.bind = cdc_bind,
- .unbind = __exit_p(cdc_unbind),
+ .unbind = cdc_unbind,
};
module_usb_composite_driver(cdc_driver);
return -ENODEV;
}
-static int __init dbgp_bind(struct usb_gadget *gadget,
+static int dbgp_bind(struct usb_gadget *gadget,
struct usb_gadget_driver *driver)
{
int err, stp;
return err;
}
-static __refdata struct usb_gadget_driver dbgp_driver = {
+static struct usb_gadget_driver dbgp_driver = {
.function = "dbgp",
.max_speed = USB_SPEED_HIGH,
.bind = dbgp_bind,
* the first one present. That's to make Microsoft's drivers happy,
* and to follow DOCSIS 1.0 (cable modem standard).
*/
-static int __init rndis_do_config(struct usb_configuration *c)
+static int rndis_do_config(struct usb_configuration *c)
{
int status;
/*
* We _always_ have an ECM, CDC Subset, or EEM configuration.
*/
-static int __init eth_do_config(struct usb_configuration *c)
+static int eth_do_config(struct usb_configuration *c)
{
int status = 0;
/*-------------------------------------------------------------------------*/
-static int __init eth_bind(struct usb_composite_dev *cdev)
+static int eth_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct f_eem_opts *eem_opts = NULL;
return status;
}
-static int __exit eth_unbind(struct usb_composite_dev *cdev)
+static int eth_unbind(struct usb_composite_dev *cdev)
{
if (has_rndis()) {
usb_put_function(f_rndis);
return 0;
}
-static __refdata struct usb_composite_driver eth_driver = {
+static struct usb_composite_driver eth_driver = {
.name = "g_ether",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_SUPER,
.bind = eth_bind,
- .unbind = __exit_p(eth_unbind),
+ .unbind = eth_unbind,
};
module_usb_composite_driver(eth_driver);
static int gfs_do_config(struct usb_configuration *c);
-static __refdata struct usb_composite_driver gfs_driver = {
+static struct usb_composite_driver gfs_driver = {
.name = DRIVER_NAME,
.dev = &gfs_dev_desc,
.strings = gfs_dev_strings,
static struct usb_function_instance *fi_midi;
static struct usb_function *f_midi;
-static int __exit midi_unbind(struct usb_composite_dev *dev)
+static int midi_unbind(struct usb_composite_dev *dev)
{
usb_put_function(f_midi);
usb_put_function_instance(fi_midi);
.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW,
};
-static int __init midi_bind_config(struct usb_configuration *c)
+static int midi_bind_config(struct usb_configuration *c)
{
int status;
return 0;
}
-static int __init midi_bind(struct usb_composite_dev *cdev)
+static int midi_bind(struct usb_composite_dev *cdev)
{
struct f_midi_opts *midi_opts;
int status;
return status;
}
-static __refdata struct usb_composite_driver midi_driver = {
+static struct usb_composite_driver midi_driver = {
.name = (char *) longname,
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.bind = midi_bind,
- .unbind = __exit_p(midi_unbind),
+ .unbind = midi_unbind,
};
module_usb_composite_driver(midi_driver);
/****************************** Configurations ******************************/
-static int __init do_config(struct usb_configuration *c)
+static int do_config(struct usb_configuration *c)
{
struct hidg_func_node *e, *n;
int status = 0;
/****************************** Gadget Bind ******************************/
-static int __init hid_bind(struct usb_composite_dev *cdev)
+static int hid_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct list_head *tmp;
return status;
}
-static int __exit hid_unbind(struct usb_composite_dev *cdev)
+static int hid_unbind(struct usb_composite_dev *cdev)
{
struct hidg_func_node *n;
return 0;
}
-static int __init hidg_plat_driver_probe(struct platform_device *pdev)
+static int hidg_plat_driver_probe(struct platform_device *pdev)
{
struct hidg_func_descriptor *func = dev_get_platdata(&pdev->dev);
struct hidg_func_node *entry;
/****************************** Some noise ******************************/
-static __refdata struct usb_composite_driver hidg_driver = {
+static struct usb_composite_driver hidg_driver = {
.name = "g_hid",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.bind = hid_bind,
- .unbind = __exit_p(hid_unbind),
+ .unbind = hid_unbind,
};
static struct platform_driver hidg_plat_driver = {
return 0;
}
-static int __init msg_do_config(struct usb_configuration *c)
+static int msg_do_config(struct usb_configuration *c)
{
struct fsg_opts *opts;
int ret;
/****************************** Gadget Bind ******************************/
-static int __init msg_bind(struct usb_composite_dev *cdev)
+static int msg_bind(struct usb_composite_dev *cdev)
{
static const struct fsg_operations ops = {
.thread_exits = msg_thread_exits,
/****************************** Some noise ******************************/
-static __refdata struct usb_composite_driver msg_driver = {
+static struct usb_composite_driver msg_driver = {
.name = "g_mass_storage",
.dev = &msg_device_desc,
.max_speed = USB_SPEED_SUPER,
static struct usb_function *f_rndis;
static struct usb_function *f_msg_rndis;
-static __init int rndis_do_config(struct usb_configuration *c)
+static int rndis_do_config(struct usb_configuration *c)
{
struct fsg_opts *fsg_opts;
int ret;
static struct usb_function *f_ecm;
static struct usb_function *f_msg_multi;
-static __init int cdc_do_config(struct usb_configuration *c)
+static int cdc_do_config(struct usb_configuration *c)
{
struct fsg_opts *fsg_opts;
int ret;
return status;
}
-static int __exit multi_unbind(struct usb_composite_dev *cdev)
+static int multi_unbind(struct usb_composite_dev *cdev)
{
#ifdef CONFIG_USB_G_MULTI_CDC
usb_put_function(f_msg_multi);
/****************************** Some noise ******************************/
-static __refdata struct usb_composite_driver multi_driver = {
+static struct usb_composite_driver multi_driver = {
.name = "g_multi",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.bind = multi_bind,
- .unbind = __exit_p(multi_unbind),
+ .unbind = multi_unbind,
.needs_serial = 1,
};
/*-------------------------------------------------------------------------*/
-static int __init ncm_do_config(struct usb_configuration *c)
+static int ncm_do_config(struct usb_configuration *c)
{
int status;
/*-------------------------------------------------------------------------*/
-static int __init gncm_bind(struct usb_composite_dev *cdev)
+static int gncm_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
struct f_ncm_opts *ncm_opts;
return status;
}
-static int __exit gncm_unbind(struct usb_composite_dev *cdev)
+static int gncm_unbind(struct usb_composite_dev *cdev)
{
if (!IS_ERR_OR_NULL(f_ncm))
usb_put_function(f_ncm);
return 0;
}
-static __refdata struct usb_composite_driver ncm_driver = {
+static struct usb_composite_driver ncm_driver = {
.name = "g_ncm",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.bind = gncm_bind,
- .unbind = __exit_p(gncm_unbind),
+ .unbind = gncm_unbind,
};
module_usb_composite_driver(ncm_driver);
static struct usb_function_instance *fi_obex2;
static struct usb_function_instance *fi_phonet;
-static int __init nokia_bind_config(struct usb_configuration *c)
+static int nokia_bind_config(struct usb_configuration *c)
{
struct usb_function *f_acm;
struct usb_function *f_phonet = NULL;
return status;
}
-static int __init nokia_bind(struct usb_composite_dev *cdev)
+static int nokia_bind(struct usb_composite_dev *cdev)
{
struct usb_gadget *gadget = cdev->gadget;
int status;
return status;
}
-static int __exit nokia_unbind(struct usb_composite_dev *cdev)
+static int nokia_unbind(struct usb_composite_dev *cdev)
{
if (!IS_ERR_OR_NULL(f_obex1_cfg2))
usb_put_function(f_obex1_cfg2);
return 0;
}
-static __refdata struct usb_composite_driver nokia_driver = {
+static struct usb_composite_driver nokia_driver = {
.name = "g_nokia",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.bind = nokia_bind,
- .unbind = __exit_p(nokia_unbind),
+ .unbind = nokia_unbind,
};
module_usb_composite_driver(nokia_driver);
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
};
-static int __init printer_do_config(struct usb_configuration *c)
+static int printer_do_config(struct usb_configuration *c)
{
struct usb_gadget *gadget = c->cdev->gadget;
int status = 0;
return status;
}
-static int __init printer_bind(struct usb_composite_dev *cdev)
+static int printer_bind(struct usb_composite_dev *cdev)
{
struct f_printer_opts *opts;
int ret, len;
return ret;
}
-static int __exit printer_unbind(struct usb_composite_dev *cdev)
+static int printer_unbind(struct usb_composite_dev *cdev)
{
usb_put_function(f_printer);
usb_put_function_instance(fi_printer);
return 0;
}
-static __refdata struct usb_composite_driver printer_driver = {
+static struct usb_composite_driver printer_driver = {
.name = shortname,
.dev = &device_desc,
.strings = dev_strings,
return ret;
}
-static int __init gs_bind(struct usb_composite_dev *cdev)
+static int gs_bind(struct usb_composite_dev *cdev)
{
int status;
return 0;
}
-static __refdata struct usb_composite_driver gserial_driver = {
+static struct usb_composite_driver gserial_driver = {
.name = "g_serial",
.dev = &device_desc,
.strings = dev_strings,
return 0;
}
-static __refdata struct usb_composite_driver usbg_driver = {
+static struct usb_composite_driver usbg_driver = {
.name = "g_target",
.dev = &usbg_device_desc,
.strings = usbg_strings,
* USB configuration
*/
-static int __init
+static int
webcam_config_bind(struct usb_configuration *c)
{
int status = 0;
.MaxPower = CONFIG_USB_GADGET_VBUS_DRAW,
};
-static int /* __init_or_exit */
+static int
webcam_unbind(struct usb_composite_dev *cdev)
{
if (!IS_ERR_OR_NULL(f_uvc))
return 0;
}
-static int __init
+static int
webcam_bind(struct usb_composite_dev *cdev)
{
struct f_uvc_opts *uvc_opts;
* Driver
*/
-static __refdata struct usb_composite_driver webcam_driver = {
+static struct usb_composite_driver webcam_driver = {
.name = "g_webcam",
.dev = &webcam_device_descriptor,
.strings = webcam_device_strings,
module_param_named(qlen, gzero_options.qlen, uint, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(qlen, "depth of loopback queue");
-static int __init zero_bind(struct usb_composite_dev *cdev)
+static int zero_bind(struct usb_composite_dev *cdev)
{
struct f_ss_opts *ss_opts;
struct f_lb_opts *lb_opts;
return 0;
}
-static __refdata struct usb_composite_driver zero_driver = {
+static struct usb_composite_driver zero_driver = {
.name = "zero",
.dev = &device_desc,
.strings = dev_strings,
return retval;
}
-static int __exit at91udc_remove(struct platform_device *pdev)
+static int at91udc_remove(struct platform_device *pdev)
{
struct at91_udc *udc = platform_get_drvdata(pdev);
unsigned long flags;
#endif
static struct platform_driver at91_udc_driver = {
- .remove = __exit_p(at91udc_remove),
+ .remove = at91udc_remove,
.shutdown = at91udc_shutdown,
.suspend = at91udc_suspend,
.resume = at91udc_resume,
return 0;
}
-static int __exit usba_udc_remove(struct platform_device *pdev)
+static int usba_udc_remove(struct platform_device *pdev)
{
struct usba_udc *udc;
int i;
static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume);
static struct platform_driver udc_driver = {
- .remove = __exit_p(usba_udc_remove),
+ .remove = usba_udc_remove,
.driver = {
.name = "atmel_usba_udc",
.pm = &usba_udc_pm_ops,
/* Driver removal function
* Free resources and finish pending transactions
*/
-static int __exit fsl_udc_remove(struct platform_device *pdev)
+static int fsl_udc_remove(struct platform_device *pdev)
{
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
};
MODULE_DEVICE_TABLE(platform, fsl_udc_devtype);
static struct platform_driver udc_driver = {
- .remove = __exit_p(fsl_udc_remove),
+ .remove = fsl_udc_remove,
/* Just for FSL i.mx SoC currently */
.id_table = fsl_udc_devtype,
/* these suspend and resume are not usb suspend and resume */
.udc_stop = fusb300_udc_stop,
};
-static int __exit fusb300_remove(struct platform_device *pdev)
+static int fusb300_remove(struct platform_device *pdev)
{
struct fusb300 *fusb300 = platform_get_drvdata(pdev);
}
static struct platform_driver fusb300_driver = {
- .remove = __exit_p(fusb300_remove),
+ .remove = fusb300_remove,
.driver = {
.name = (char *) udc_name,
},
.pullup = m66592_pullup,
};
-static int __exit m66592_remove(struct platform_device *pdev)
+static int m66592_remove(struct platform_device *pdev)
{
struct m66592 *m66592 = platform_get_drvdata(pdev);
/*-------------------------------------------------------------------------*/
static struct platform_driver m66592_driver = {
- .remove = __exit_p(m66592_remove),
+ .remove = m66592_remove,
.driver = {
.name = (char *) udc_name,
},
.set_selfpowered = r8a66597_set_selfpowered,
};
-static int __exit r8a66597_remove(struct platform_device *pdev)
+static int r8a66597_remove(struct platform_device *pdev)
{
struct r8a66597 *r8a66597 = platform_get_drvdata(pdev);
/*-------------------------------------------------------------------------*/
static struct platform_driver r8a66597_driver = {
- .remove = __exit_p(r8a66597_remove),
+ .remove = r8a66597_remove,
.driver = {
.name = (char *) udc_name,
},
/* Map the registers */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
udc->addr = devm_ioremap_resource(&pdev->dev, res);
- if (!udc->addr)
- return -ENOMEM;
+ if (IS_ERR(udc->addr))
+ return PTR_ERR(udc->addr);
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
break;
case COMP_DEV_ERR:
case COMP_STALL:
+ frame->status = -EPROTO;
+ skip_td = true;
+ break;
case COMP_TX_ERR:
frame->status = -EPROTO;
+ if (event_trb != td->last_trb)
+ return 0;
skip_td = true;
break;
case COMP_STOP:
xhci_halt(xhci);
hw_died:
spin_unlock(&xhci->lock);
- return -ESHUTDOWN;
+ return IRQ_HANDLED;
}
/*
* since the command ring is 64-byte aligned.
* It must also be greater than 16.
*/
-#define TRBS_PER_SEGMENT 64
+#define TRBS_PER_SEGMENT 256
/* Allow two commands + a link TRB, along with any reserved command TRBs */
#define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3)
#define TRB_SEGMENT_SIZE (TRBS_PER_SEGMENT*16)
#if defined(CONFIG_MACH_OMAP_H2) || defined(CONFIG_MACH_OMAP_H3)
-#if defined(CONFIG_TPS65010) || defined(CONFIG_TPS65010_MODULE)
+#if defined(CONFIG_TPS65010) || (defined(CONFIG_TPS65010_MODULE) && defined(MODULE))
#include <linux/i2c/tps65010.h>
{ USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */
{ USB_DEVICE(0x10C4, 0x8946) }, /* Ketra N1 Wireless Interface */
{ USB_DEVICE(0x10C4, 0x8977) }, /* CEL MeshWorks DevKit Device */
+ { USB_DEVICE(0x10C4, 0x8998) }, /* KCF Technologies PRN */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
{ USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
{ USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_SX1),
.driver_info = PL2303_QUIRK_UART_STATE_IDX0 },
{ USB_DEVICE(SIEMENS_VENDOR_ID, SIEMENS_PRODUCT_ID_X65),
#define ALCATEL_VENDOR_ID 0x11f7
#define ALCATEL_PRODUCT_ID 0x02df
-/* Samsung I330 phone cradle */
-#define SAMSUNG_VENDOR_ID 0x04e8
-#define SAMSUNG_PRODUCT_ID 0x8001
-
#define SIEMENS_VENDOR_ID 0x11f5
#define SIEMENS_PRODUCT_ID_SX1 0x0001
#define SIEMENS_PRODUCT_ID_X65 0x0003
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(ACER_VENDOR_ID, ACER_S10_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
- { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID),
+ { USB_DEVICE_INTERFACE_CLASS(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID, 0xff),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
USB_SC_DEVICE, USB_PR_DEVICE, NULL,
US_FL_GO_SLOW ),
+/* Reported by Christian Schaller <cschalle@redhat.com> */
+UNUSUAL_DEV( 0x059f, 0x0651, 0x0000, 0x0000,
+ "LaCie",
+ "External HDD",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_NO_WP_DETECT ),
+
/* Submitted by Joel Bourquard <numlock@freesurf.ch>
* Some versions of this device need the SubClass and Protocol overrides
* while others don't.
mutex_lock(&vdev->igate);
if (vdev->req_trigger) {
- dev_dbg(&vdev->pdev->dev, "Requesting device from user\n");
+ if (!(count % 10))
+ dev_notice_ratelimited(&vdev->pdev->dev,
+ "Relaying device request to user (#%u)\n",
+ count);
eventfd_signal(vdev->req_trigger, 1);
+ } else if (count == 0) {
+ dev_warn(&vdev->pdev->dev,
+ "No device request channel registered, blocked until released by user\n");
}
mutex_unlock(&vdev->igate);
void *device_data = device->device_data;
struct vfio_unbound_dev *unbound;
unsigned int i = 0;
+ long ret;
+ bool interrupted = false;
/*
* The group exists so long as we have a device reference. Get
vfio_device_put(device);
- } while (wait_event_interruptible_timeout(vfio.release_q,
- !vfio_dev_present(group, dev),
- HZ * 10) <= 0);
+ if (interrupted) {
+ ret = wait_event_timeout(vfio.release_q,
+ !vfio_dev_present(group, dev), HZ * 10);
+ } else {
+ ret = wait_event_interruptible_timeout(vfio.release_q,
+ !vfio_dev_present(group, dev), HZ * 10);
+ if (ret == -ERESTARTSYS) {
+ interrupted = true;
+ dev_warn(dev,
+ "Device is currently in use, task"
+ " \"%s\" (%d) "
+ "blocked until device is released",
+ current->comm, task_pid_nr(current));
+ }
+ }
+ } while (ret <= 0);
vfio_group_put(group);
return IRQ_HANDLED;
}
+static void evtchn_2l_resume(void)
+{
+ int i;
+
+ for_each_online_cpu(i)
+ memset(per_cpu(cpu_evtchn_mask, i), 0, sizeof(xen_ulong_t) *
+ EVTCHN_2L_NR_CHANNELS/BITS_PER_EVTCHN_WORD);
+}
+
static const struct evtchn_ops evtchn_ops_2l = {
.max_channels = evtchn_2l_max_channels,
.nr_channels = evtchn_2l_max_channels,
.mask = evtchn_2l_mask,
.unmask = evtchn_2l_unmask,
.handle_events = evtchn_2l_handle_events,
+ .resume = evtchn_2l_resume,
};
void __init xen_evtchn_2l_init(void)
if (rc)
goto err;
- bind_evtchn_to_cpu(evtchn, 0);
info->evtchn = evtchn;
+ bind_evtchn_to_cpu(evtchn, 0);
rc = xen_evtchn_port_setup(info);
if (rc)
mutex_unlock(&irq_mapping_update_lock);
- /* new event channels are always bound to cpu 0 */
- irq_set_affinity(irq, cpumask_of(0));
+ bind_evtchn_to_cpu(evtchn, info->cpu);
+ /* This will be deferred until interrupt is processed */
+ irq_set_affinity(irq, cpumask_of(info->cpu));
/* Unmask the event channel. */
enable_irq(irq);
return err;
}
-struct unmap_grant_pages_callback_data
-{
- struct completion completion;
- int result;
-};
-
-static void unmap_grant_callback(int result,
- struct gntab_unmap_queue_data *data)
-{
- struct unmap_grant_pages_callback_data* d = data->data;
-
- d->result = result;
- complete(&d->completion);
-}
-
static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
{
int i, err = 0;
struct gntab_unmap_queue_data unmap_data;
- struct unmap_grant_pages_callback_data data;
-
- init_completion(&data.completion);
- unmap_data.data = &data;
- unmap_data.done= &unmap_grant_callback;
if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) {
int pgno = (map->notify.addr >> PAGE_SHIFT);
unmap_data.pages = map->pages + offset;
unmap_data.count = pages;
- gnttab_unmap_refs_async(&unmap_data);
-
- wait_for_completion(&data.completion);
- if (data.result)
- return data.result;
+ err = gnttab_unmap_refs_sync(&unmap_data);
+ if (err)
+ return err;
for (i = 0; i < pages; i++) {
if (map->unmap_ops[offset+i].status)
int (*query_foreign_access)(grant_ref_t ref);
};
+struct unmap_refs_callback_data {
+ struct completion completion;
+ int result;
+};
+
static struct gnttab_ops *gnttab_interface;
static int grant_table_version;
}
EXPORT_SYMBOL_GPL(gnttab_unmap_refs_async);
+static void unmap_refs_callback(int result,
+ struct gntab_unmap_queue_data *data)
+{
+ struct unmap_refs_callback_data *d = data->data;
+
+ d->result = result;
+ complete(&d->completion);
+}
+
+int gnttab_unmap_refs_sync(struct gntab_unmap_queue_data *item)
+{
+ struct unmap_refs_callback_data data;
+
+ init_completion(&data.completion);
+ item->data = &data;
+ item->done = &unmap_refs_callback;
+ gnttab_unmap_refs_async(item);
+ wait_for_completion(&data.completion);
+
+ return data.result;
+}
+EXPORT_SYMBOL_GPL(gnttab_unmap_refs_sync);
+
static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
{
int rc;
goto out_resume;
}
+ xen_arch_suspend();
+
si.cancelled = 1;
err = stop_machine(xen_suspend, &si, cpumask_of(0));
si.cancelled = 1;
}
+ xen_arch_resume();
+
out_resume:
- if (!si.cancelled) {
- xen_arch_resume();
+ if (!si.cancelled)
xs_resume();
- } else
+ else
xs_suspend_cancel();
dpm_resume_end(si.cancelled ? PMSG_THAW : PMSG_RESTORE);
#define SLABS_PER_PAGE (1 << (PAGE_SHIFT - IO_TLB_SHIFT))
#define IO_TLB_MIN_SLABS ((1<<20) >> IO_TLB_SHIFT)
while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
- xen_io_tlb_start = (void *)__get_free_pages(__GFP_NOWARN, order);
+ xen_io_tlb_start = (void *)xen_get_swiotlb_free_pages(order);
if (xen_io_tlb_start)
break;
order--;
#include "conf_space.h"
#include "conf_space_quirks.h"
-bool permissive;
-module_param(permissive, bool, 0644);
+bool xen_pcibk_permissive;
+module_param_named(permissive, xen_pcibk_permissive, bool, 0644);
/* This is where xen_pcibk_read_config_byte, xen_pcibk_read_config_word,
* xen_pcibk_write_config_word, and xen_pcibk_write_config_byte are created. */
* This means that some fields may still be read-only because
* they have entries in the config_field list that intercept
* the write and do nothing. */
- if (dev_data->permissive || permissive) {
+ if (dev_data->permissive || xen_pcibk_permissive) {
switch (size) {
case 1:
err = pci_write_config_byte(dev, offset,
void *data;
};
-extern bool permissive;
+extern bool xen_pcibk_permissive;
#define OFFSET(cfg_entry) ((cfg_entry)->base_offset+(cfg_entry)->field->offset)
cmd->val = value;
- if (!permissive && (!dev_data || !dev_data->permissive))
+ if (!xen_pcibk_permissive && (!dev_data || !dev_data->permissive))
return 0;
/* Only allow the guest to control certain bits. */
#include <xen/xen.h>
#include <xen/xenbus.h>
#include <xen/events.h>
+#include <xen/xen-ops.h>
#include <xen/page.h>
#include <xen/hvm.h>
return err;
}
+static int xenbus_resume_cb(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ int err = 0;
+
+ if (xen_hvm_domain()) {
+ uint64_t v;
+
+ err = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN, &v);
+ if (!err && v)
+ xen_store_evtchn = v;
+ else
+ pr_warn("Cannot update xenstore event channel: %d\n",
+ err);
+ } else
+ xen_store_evtchn = xen_start_info->store_evtchn;
+
+ return err;
+}
+
+static struct notifier_block xenbus_resume_nb = {
+ .notifier_call = xenbus_resume_cb,
+};
+
static int __init xenbus_init(void)
{
int err = 0;
goto out_error;
}
+ if ((xen_store_domain_type != XS_LOCAL) &&
+ (xen_store_domain_type != XS_UNKNOWN))
+ xen_resume_notifier_register(&xenbus_resume_nb);
+
#ifdef CONFIG_XEN_COMPAT_XENFS
/*
* Create xenfs mountpoint in /proc for compatibility with
btrfs_mark_buffer_dirty(leaf);
fail:
btrfs_release_path(path);
- if (ret)
- btrfs_abort_transaction(trans, root, ret);
return ret;
}
ret = 0;
}
}
- if (!ret)
+ if (!ret) {
ret = write_one_cache_group(trans, root, path, cache);
+ /*
+ * Our block group might still be attached to the list
+ * of new block groups in the transaction handle of some
+ * other task (struct btrfs_trans_handle->new_bgs). This
+ * means its block group item isn't yet in the extent
+ * tree. If this happens ignore the error, as we will
+ * try again later in the critical section of the
+ * transaction commit.
+ */
+ if (ret == -ENOENT) {
+ ret = 0;
+ spin_lock(&cur_trans->dirty_bgs_lock);
+ if (list_empty(&cache->dirty_list)) {
+ list_add_tail(&cache->dirty_list,
+ &cur_trans->dirty_bgs);
+ btrfs_get_block_group(cache);
+ }
+ spin_unlock(&cur_trans->dirty_bgs_lock);
+ } else if (ret) {
+ btrfs_abort_transaction(trans, root, ret);
+ }
+ }
/* if its not on the io list, we need to put the block group */
if (should_put)
ret = 0;
}
}
- if (!ret)
+ if (!ret) {
ret = write_one_cache_group(trans, root, path, cache);
+ if (ret)
+ btrfs_abort_transaction(trans, root, ret);
+ }
/* if its not on the io list, we need to put the block group */
if (should_put)
start >> PAGE_CACHE_SHIFT);
if (eb && atomic_inc_not_zero(&eb->refs)) {
rcu_read_unlock();
+ /*
+ * Lock our eb's refs_lock to avoid races with
+ * free_extent_buffer. When we get our eb it might be flagged
+ * with EXTENT_BUFFER_STALE and another task running
+ * free_extent_buffer might have seen that flag set,
+ * eb->refs == 2, that the buffer isn't under IO (dirty and
+ * writeback flags not set) and it's still in the tree (flag
+ * EXTENT_BUFFER_TREE_REF set), therefore being in the process
+ * of decrementing the extent buffer's reference count twice.
+ * So here we could race and increment the eb's reference count,
+ * clear its stale flag, mark it as dirty and drop our reference
+ * before the other task finishes executing free_extent_buffer,
+ * which would later result in an attempt to free an extent
+ * buffer that is dirty.
+ */
+ if (test_bit(EXTENT_BUFFER_STALE, &eb->bflags)) {
+ spin_lock(&eb->refs_lock);
+ spin_unlock(&eb->refs_lock);
+ }
mark_extent_buffer_accessed(eb, NULL);
return eb;
}
mapping_set_gfp_mask(inode->i_mapping,
mapping_gfp_mask(inode->i_mapping) &
- ~(GFP_NOFS & ~__GFP_HIGHMEM));
+ ~(__GFP_FS | __GFP_HIGHMEM));
return inode;
}
struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
int ret;
struct btrfs_io_ctl io_ctl;
+ bool release_metadata = true;
if (!btrfs_test_opt(root, INODE_MAP_CACHE))
return 0;
memset(&io_ctl, 0, sizeof(io_ctl));
ret = __btrfs_write_out_cache(root, inode, ctl, NULL, &io_ctl,
trans, path, 0);
- if (!ret)
+ if (!ret) {
+ /*
+ * At this point writepages() didn't error out, so our metadata
+ * reservation is released when the writeback finishes, at
+ * inode.c:btrfs_finish_ordered_io(), regardless of it finishing
+ * with or without an error.
+ */
+ release_metadata = false;
ret = btrfs_wait_cache_io(root, trans, NULL, &io_ctl, path, 0);
+ }
if (ret) {
- btrfs_delalloc_release_metadata(inode, inode->i_size);
+ if (release_metadata)
+ btrfs_delalloc_release_metadata(inode, inode->i_size);
#ifdef DEBUG
btrfs_err(root->fs_info,
"failed to write free ino cache for root %llu",
int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)
{
int ret = 0;
+ int ret_wb = 0;
u64 end;
u64 orig_end;
struct btrfs_ordered_extent *ordered;
if (ret)
return ret;
- ret = filemap_fdatawait_range(inode->i_mapping, start, orig_end);
- if (ret)
- return ret;
+ /*
+ * If we have a writeback error don't return immediately. Wait first
+ * for any ordered extents that haven't completed yet. This is to make
+ * sure no one can dirty the same page ranges and call writepages()
+ * before the ordered extents complete - to avoid failures (-EEXIST)
+ * when adding the new ordered extents to the ordered tree.
+ */
+ ret_wb = filemap_fdatawait_range(inode->i_mapping, start, orig_end);
end = orig_end;
while (1) {
break;
end--;
}
- return ret;
+ return ret_wb ? ret_wb : ret;
}
/*
MODULE_VERSION("0.0.2");
MODULE_DESCRIPTION("Simple RAM filesystem for user driven kernel subsystem configuration.");
-module_init(configfs_init);
+core_initcall(configfs_init);
module_exit(configfs_exit);
int len, i;
int err = -ENOMEM;
- entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return err;
if (stack_base > STACK_SIZE_MAX)
stack_base = STACK_SIZE_MAX;
+ /* Add space for stack randomization. */
+ stack_base += (STACK_RND_MASK << PAGE_SHIFT);
+
/* Make sure we didn't let the argument array grow too large. */
if (vma->vm_end - vma->vm_start > stack_base)
return -ENOMEM;
struct ext4_map_blocks *map, int flags);
extern int ext4_ext_calc_metadata_amount(struct inode *inode,
ext4_lblk_t lblocks);
-extern int ext4_extent_tree_init(handle_t *, struct inode *);
extern int ext4_ext_calc_credits_for_single_extent(struct inode *inode,
int num,
struct ext4_ext_path *path);
ext4_put_nojournal(handle);
return 0;
}
+
+ if (!handle->h_transaction) {
+ err = jbd2_journal_stop(handle);
+ return handle->h_err ? handle->h_err : err;
+ }
+
sb = handle->h_transaction->t_journal->j_private;
err = handle->h_err;
rc = jbd2_journal_stop(handle);
ext4_lblk_t lblock = le32_to_cpu(ext->ee_block);
ext4_lblk_t last = lblock + len - 1;
- if (lblock > last)
+ if (len == 0 || lblock > last)
return 0;
return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len);
}
loff_t new_size, ioffset;
int ret;
+ /*
+ * We need to test this early because xfstests assumes that a
+ * collapse range of (0, 1) will return EOPNOTSUPP if the file
+ * system does not support collapse range.
+ */
+ if (!ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+ return -EOPNOTSUPP;
+
/* Collapse range works only on fs block size aligned offsets. */
if (offset & (EXT4_CLUSTER_SIZE(sb) - 1) ||
len & (EXT4_CLUSTER_SIZE(sb) - 1))
int inode_size = EXT4_INODE_SIZE(sb);
oi.orig_ino = orig_ino;
- ino = orig_ino & ~(inodes_per_block - 1);
+ ino = (orig_ino & ~(inodes_per_block - 1)) + 1;
for (i = 0; i < inodes_per_block; i++, ino++, buf += inode_size) {
if (ino == orig_ino)
continue;
struct ext4_super_block *es = EXT4_SB(sb)->s_es;
EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS;
+ if (bdev_read_only(sb->s_bdev))
+ return;
es->s_state |= cpu_to_le16(EXT4_ERROR_FS);
es->s_last_error_time = cpu_to_le32(get_seconds());
strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func));
{
struct inode *inode = mapping->host;
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+ bool locked = false;
int ret;
long diff;
diff = nr_pages_to_write(sbi, DATA, wbc);
+ if (!S_ISDIR(inode->i_mode)) {
+ mutex_lock(&sbi->writepages);
+ locked = true;
+ }
ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping);
+ if (locked)
+ mutex_unlock(&sbi->writepages);
f2fs_submit_merged_bio(sbi, DATA, WRITE);
struct mutex cp_mutex; /* checkpoint procedure lock */
struct rw_semaphore cp_rwsem; /* blocking FS operations */
struct rw_semaphore node_write; /* locking node writes */
+ struct mutex writepages; /* mutex for writepages() */
wait_queue_head_t cp_wait;
struct inode_management im[MAX_INO_ENTRY]; /* manage inode cache */
static void *f2fs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
- struct page *page;
+ struct page *page = page_follow_link_light(dentry, nd);
- page = page_follow_link_light(dentry, nd);
- if (IS_ERR(page))
+ if (IS_ERR_OR_NULL(page))
return page;
/* this is broken symlink case */
if (*nd_get_link(nd) == 0) {
- kunmap(page);
- page_cache_release(page);
+ page_put_link(dentry, nd, page);
return ERR_PTR(-ENOENT);
}
return page;
sbi->raw_super = raw_super;
sbi->raw_super_buf = raw_super_buf;
mutex_init(&sbi->gc_mutex);
+ mutex_init(&sbi->writepages);
mutex_init(&sbi->cp_mutex);
init_rwsem(&sbi->node_write);
clear_sbi_flag(sbi, SBI_POR_DOING);
if (name == NULL)
goto out_put;
- fd = file_create(name, mode & S_IFMT);
+ fd = file_create(name, mode & 0777);
if (fd < 0)
error = fd;
else
{
jbd2_journal_revoke_header_t *header;
int offset, max;
+ int csum_size = 0;
+ __u32 rcount;
int record_len = 4;
header = (jbd2_journal_revoke_header_t *) bh->b_data;
offset = sizeof(jbd2_journal_revoke_header_t);
- max = be32_to_cpu(header->r_count);
+ rcount = be32_to_cpu(header->r_count);
if (!jbd2_revoke_block_csum_verify(journal, header))
return -EINVAL;
+ if (jbd2_journal_has_csum_v2or3(journal))
+ csum_size = sizeof(struct jbd2_journal_revoke_tail);
+ if (rcount > journal->j_blocksize - csum_size)
+ return -EINVAL;
+ max = rcount;
+
if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
record_len = 8;
{
int csum_size = 0;
struct buffer_head *descriptor;
- int offset;
+ int sz, offset;
journal_header_t *header;
/* If we are already aborting, this all becomes a noop. We
if (jbd2_journal_has_csum_v2or3(journal))
csum_size = sizeof(struct jbd2_journal_revoke_tail);
+ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
+ sz = 8;
+ else
+ sz = 4;
+
/* Make sure we have a descriptor with space left for the record */
if (descriptor) {
- if (offset >= journal->j_blocksize - csum_size) {
+ if (offset + sz > journal->j_blocksize - csum_size) {
flush_descriptor(journal, descriptor, offset, write_op);
descriptor = NULL;
}
*descriptorp = descriptor;
}
- if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT)) {
+ if (JBD2_HAS_INCOMPAT_FEATURE(journal, JBD2_FEATURE_INCOMPAT_64BIT))
* ((__be64 *)(&descriptor->b_data[offset])) =
cpu_to_be64(record->blocknr);
- offset += 8;
-
- } else {
+ else
* ((__be32 *)(&descriptor->b_data[offset])) =
cpu_to_be32(record->blocknr);
- offset += 4;
- }
+ offset += sz;
*offsetp = offset;
}
int result;
int wanted;
- WARN_ON(!transaction);
if (is_handle_aborted(handle))
return -EROFS;
journal = transaction->t_journal;
tid_t tid;
int need_to_start, ret;
- WARN_ON(!transaction);
/* If we've had an abort of any type, don't even think about
* actually doing the restart! */
if (is_handle_aborted(handle))
int need_copy = 0;
unsigned long start_lock, time_lock;
- WARN_ON(!transaction);
if (is_handle_aborted(handle))
return -EROFS;
journal = transaction->t_journal;
int err;
jbd_debug(5, "journal_head %p\n", jh);
- WARN_ON(!transaction);
err = -EROFS;
if (is_handle_aborted(handle))
goto out;
struct journal_head *jh;
int ret = 0;
- WARN_ON(!transaction);
if (is_handle_aborted(handle))
return -EROFS;
journal = transaction->t_journal;
int err = 0;
int was_modified = 0;
- WARN_ON(!transaction);
if (is_handle_aborted(handle))
return -EROFS;
journal = transaction->t_journal;
tid_t tid;
pid_t pid;
- if (!transaction)
- goto free_and_exit;
+ if (!transaction) {
+ /*
+ * Handle is already detached from the transaction so
+ * there is nothing to do other than decrease a refcount,
+ * or free the handle if refcount drops to zero
+ */
+ if (--handle->h_ref > 0) {
+ jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1,
+ handle->h_ref);
+ return err;
+ } else {
+ if (handle->h_rsv_handle)
+ jbd2_free_handle(handle->h_rsv_handle);
+ goto free_and_exit;
+ }
+ }
journal = transaction->t_journal;
J_ASSERT(journal_current_handle() == handle);
transaction_t *transaction = handle->h_transaction;
journal_t *journal;
- WARN_ON(!transaction);
if (is_handle_aborted(handle))
return -EROFS;
journal = transaction->t_journal;
if (!kn)
goto err_out1;
- ret = ida_simple_get(&root->ino_ida, 1, 0, GFP_KERNEL);
+ /*
+ * If the ino of the sysfs entry created for a kmem cache gets
+ * allocated from an ida layer, which is accounted to the memcg that
+ * owns the cache, the memcg will get pinned forever. So do not account
+ * ino ida allocations.
+ */
+ ret = ida_simple_get(&root->ino_ida, 1, 0,
+ GFP_KERNEL | __GFP_NOACCOUNT);
if (ret < 0)
goto err_out2;
kn->ino = ret;
*/
if (nd->flags & LOOKUP_RCU) {
unsigned seq;
+ bool negative;
dentry = __d_lookup_rcu(parent, &nd->last, &seq);
if (!dentry)
goto unlazy;
* the dentry name information from lookup.
*/
*inode = dentry->d_inode;
+ negative = d_is_negative(dentry);
if (read_seqcount_retry(&dentry->d_seq, seq))
return -ECHILD;
+ if (negative)
+ return -ENOENT;
/*
* This sequence count validates that the parent had no
goto need_lookup;
}
+ if (unlikely(d_is_negative(dentry))) {
+ dput(dentry);
+ return -ENOENT;
+ }
path->mnt = mnt;
path->dentry = dentry;
err = follow_managed(path, nd->flags);
goto out_err;
inode = path->dentry->d_inode;
+ err = -ENOENT;
+ if (d_is_negative(path->dentry))
+ goto out_path_put;
}
- err = -ENOENT;
- if (d_is_negative(path->dentry))
- goto out_path_put;
if (should_follow_link(path->dentry, follow)) {
if (nd->flags & LOOKUP_RCU) {
BUG_ON(nd->flags & LOOKUP_RCU);
inode = path->dentry->d_inode;
-finish_lookup:
- /* we _can_ be in RCU mode here */
error = -ENOENT;
if (d_is_negative(path->dentry)) {
path_to_nameidata(path, nd);
goto out;
}
-
+finish_lookup:
+ /* we _can_ be in RCU mode here */
if (should_follow_link(path->dentry, !symlink_ok)) {
if (nd->flags & LOOKUP_RCU) {
if (unlikely(nd->path.mnt != path->mnt ||
if (unlikely(file->f_flags & __O_TMPFILE)) {
error = do_tmpfile(dfd, pathname, nd, flags, op, file, &opened);
- goto out;
+ goto out2;
}
error = path_init(dfd, pathname, flags, nd);
}
out:
path_cleanup(nd);
+out2:
if (!(opened & FILE_OPENED)) {
BUG_ON(!error);
put_filp(file);
if (mnt->mnt.mnt_sb->s_type != type)
continue;
+ /* This mount is not fully visible if it's root directory
+ * is not the root directory of the filesystem.
+ */
+ if (mnt->mnt.mnt_root != mnt->mnt.mnt_sb->s_root)
+ continue;
+
/* This mount is not fully visible if there are any child mounts
* that cover anything except for empty directories.
*/
}
const struct nfsd4_layout_ops bl_layout_ops = {
+ /*
+ * Pretend that we send notification to the client. This is a blatant
+ * lie to force recent Linux clients to cache our device IDs.
+ * We rarely ever change the device ID, so the harm of leaking deviceids
+ * for a while isn't too bad. Unfortunately RFC5661 is a complete mess
+ * in this regard, but I filed errata 4119 for this a while ago, and
+ * hopefully the Linux client will eventually start caching deviceids
+ * without this again.
+ */
+ .notify_types =
+ NOTIFY_DEVICEID4_DELETE | NOTIFY_DEVICEID4_CHANGE,
.proc_getdeviceinfo = nfsd4_block_proc_getdeviceinfo,
.encode_getdeviceinfo = nfsd4_block_encode_getdeviceinfo,
.proc_layoutget = nfsd4_block_proc_layoutget,
}
static int decode_cb_op_status(struct xdr_stream *xdr, enum nfs_opnum4 expected,
- enum nfsstat4 *status)
+ int *status)
{
__be32 *p;
u32 op;
op = be32_to_cpup(p++);
if (unlikely(op != expected))
goto out_unexpected;
- *status = be32_to_cpup(p);
+ *status = nfs_cb_stat_to_errno(be32_to_cpup(p));
return 0;
out_overflow:
print_overflow_msg(__func__, xdr);
static int decode_cb_sequence4res(struct xdr_stream *xdr,
struct nfsd4_callback *cb)
{
- enum nfsstat4 nfserr;
int status;
if (cb->cb_minorversion == 0)
return 0;
- status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &nfserr);
- if (unlikely(status))
- goto out;
- if (unlikely(nfserr != NFS4_OK))
- goto out_default;
- status = decode_cb_sequence4resok(xdr, cb);
-out:
- return status;
-out_default:
- return nfs_cb_stat_to_errno(nfserr);
+ status = decode_cb_op_status(xdr, OP_CB_SEQUENCE, &cb->cb_status);
+ if (unlikely(status || cb->cb_status))
+ return status;
+
+ return decode_cb_sequence4resok(xdr, cb);
}
/*
struct nfsd4_callback *cb)
{
struct nfs4_cb_compound_hdr hdr;
- enum nfsstat4 nfserr;
int status;
status = decode_cb_compound4res(xdr, &hdr);
if (unlikely(status))
- goto out;
+ return status;
if (cb != NULL) {
status = decode_cb_sequence4res(xdr, cb);
- if (unlikely(status))
- goto out;
+ if (unlikely(status || cb->cb_status))
+ return status;
}
- status = decode_cb_op_status(xdr, OP_CB_RECALL, &nfserr);
- if (unlikely(status))
- goto out;
- if (unlikely(nfserr != NFS4_OK))
- status = nfs_cb_stat_to_errno(nfserr);
-out:
- return status;
+ return decode_cb_op_status(xdr, OP_CB_RECALL, &cb->cb_status);
}
#ifdef CONFIG_NFSD_PNFS
struct nfsd4_callback *cb)
{
struct nfs4_cb_compound_hdr hdr;
- enum nfsstat4 nfserr;
int status;
status = decode_cb_compound4res(xdr, &hdr);
if (unlikely(status))
- goto out;
+ return status;
+
if (cb) {
status = decode_cb_sequence4res(xdr, cb);
- if (unlikely(status))
- goto out;
+ if (unlikely(status || cb->cb_status))
+ return status;
}
- status = decode_cb_op_status(xdr, OP_CB_LAYOUTRECALL, &nfserr);
- if (unlikely(status))
- goto out;
- if (unlikely(nfserr != NFS4_OK))
- status = nfs_cb_stat_to_errno(nfserr);
-out:
- return status;
+ return decode_cb_op_status(xdr, OP_CB_LAYOUTRECALL, &cb->cb_status);
}
#endif /* CONFIG_NFSD_PNFS */
if (!nfsd41_cb_get_slot(clp, task))
return;
}
- spin_lock(&clp->cl_lock);
- if (list_empty(&cb->cb_per_client)) {
- /* This is the first call, not a restart */
- cb->cb_done = false;
- list_add(&cb->cb_per_client, &clp->cl_callbacks);
- }
- spin_unlock(&clp->cl_lock);
rpc_call_start(task);
}
if (clp->cl_minorversion) {
/* No need for lock, access serialized in nfsd4_cb_prepare */
- ++clp->cl_cb_session->se_cb_seq_nr;
+ if (!task->tk_status)
+ ++clp->cl_cb_session->se_cb_seq_nr;
clear_bit(0, &clp->cl_cb_slot_busy);
rpc_wake_up_next(&clp->cl_cb_waitq);
dprintk("%s: freed slot, new seqid=%d\n", __func__,
clp->cl_cb_session->se_cb_seq_nr);
}
- if (clp->cl_cb_client != task->tk_client) {
- /* We're shutting down or changing cl_cb_client; leave
- * it to nfsd4_process_cb_update to restart the call if
- * necessary. */
+ /*
+ * If the backchannel connection was shut down while this
+ * task was queued, we need to resubmit it after setting up
+ * a new backchannel connection.
+ *
+ * Note that if we lost our callback connection permanently
+ * the submission code will error out, so we don't need to
+ * handle that case here.
+ */
+ if (task->tk_flags & RPC_TASK_KILLED) {
+ task->tk_status = 0;
+ cb->cb_need_restart = true;
return;
}
- if (cb->cb_done)
- return;
+ if (cb->cb_status) {
+ WARN_ON_ONCE(task->tk_status);
+ task->tk_status = cb->cb_status;
+ }
switch (cb->cb_ops->done(cb, task)) {
case 0:
default:
BUG();
}
- cb->cb_done = true;
}
static void nfsd4_cb_release(void *calldata)
{
struct nfsd4_callback *cb = calldata;
- struct nfs4_client *clp = cb->cb_clp;
-
- if (cb->cb_done) {
- spin_lock(&clp->cl_lock);
- list_del(&cb->cb_per_client);
- spin_unlock(&clp->cl_lock);
+ if (cb->cb_need_restart)
+ nfsd4_run_cb(cb);
+ else
cb->cb_ops->release(cb);
- }
+
}
static const struct rpc_call_ops nfsd4_cb_ops = {
nfsd4_mark_cb_down(clp, err);
return;
}
- /* Yay, the callback channel's back! Restart any callbacks: */
- list_for_each_entry(cb, &clp->cl_callbacks, cb_per_client)
- queue_work(callback_wq, &cb->cb_work);
}
static void
struct nfs4_client *clp = cb->cb_clp;
struct rpc_clnt *clnt;
- if (cb->cb_ops && cb->cb_ops->prepare)
- cb->cb_ops->prepare(cb);
+ if (cb->cb_need_restart) {
+ cb->cb_need_restart = false;
+ } else {
+ if (cb->cb_ops && cb->cb_ops->prepare)
+ cb->cb_ops->prepare(cb);
+ }
if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK)
nfsd4_process_cb_update(cb);
cb->cb_ops->release(cb);
return;
}
+
+ /*
+ * Don't send probe messages for 4.1 or later.
+ */
+ if (!cb->cb_ops && clp->cl_minorversion) {
+ clp->cl_cb_state = NFSD4_CB_UP;
+ return;
+ }
+
cb->cb_msg.rpc_cred = clp->cl_cb_cred;
rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN,
cb->cb_ops ? &nfsd4_cb_ops : &nfsd4_cb_probe_ops, cb);
cb->cb_msg.rpc_resp = cb;
cb->cb_ops = ops;
INIT_WORK(&cb->cb_work, nfsd4_run_cb_work);
- INIT_LIST_HEAD(&cb->cb_per_client);
- cb->cb_done = true;
+ cb->cb_status = 0;
+ cb->cb_need_restart = false;
}
void nfsd4_run_cb(struct nfsd4_callback *cb)
static struct kmem_cache *file_slab;
static struct kmem_cache *stateid_slab;
static struct kmem_cache *deleg_slab;
+static struct kmem_cache *odstate_slab;
static void free_session(struct nfsd4_session *);
if (atomic_dec_and_lock(&fi->fi_ref, &state_lock)) {
hlist_del_rcu(&fi->fi_hash);
spin_unlock(&state_lock);
+ WARN_ON_ONCE(!list_empty(&fi->fi_clnt_odstate));
WARN_ON_ONCE(!list_empty(&fi->fi_delegations));
call_rcu(&fi->fi_rcu, nfsd4_free_file_rcu);
}
__nfs4_file_put_access(fp, O_RDONLY);
}
+/*
+ * Allocate a new open/delegation state counter. This is needed for
+ * pNFS for proper return on close semantics.
+ *
+ * Note that we only allocate it for pNFS-enabled exports, otherwise
+ * all pointers to struct nfs4_clnt_odstate are always NULL.
+ */
+static struct nfs4_clnt_odstate *
+alloc_clnt_odstate(struct nfs4_client *clp)
+{
+ struct nfs4_clnt_odstate *co;
+
+ co = kmem_cache_zalloc(odstate_slab, GFP_KERNEL);
+ if (co) {
+ co->co_client = clp;
+ atomic_set(&co->co_odcount, 1);
+ }
+ return co;
+}
+
+static void
+hash_clnt_odstate_locked(struct nfs4_clnt_odstate *co)
+{
+ struct nfs4_file *fp = co->co_file;
+
+ lockdep_assert_held(&fp->fi_lock);
+ list_add(&co->co_perfile, &fp->fi_clnt_odstate);
+}
+
+static inline void
+get_clnt_odstate(struct nfs4_clnt_odstate *co)
+{
+ if (co)
+ atomic_inc(&co->co_odcount);
+}
+
+static void
+put_clnt_odstate(struct nfs4_clnt_odstate *co)
+{
+ struct nfs4_file *fp;
+
+ if (!co)
+ return;
+
+ fp = co->co_file;
+ if (atomic_dec_and_lock(&co->co_odcount, &fp->fi_lock)) {
+ list_del(&co->co_perfile);
+ spin_unlock(&fp->fi_lock);
+
+ nfsd4_return_all_file_layouts(co->co_client, fp);
+ kmem_cache_free(odstate_slab, co);
+ }
+}
+
+static struct nfs4_clnt_odstate *
+find_or_hash_clnt_odstate(struct nfs4_file *fp, struct nfs4_clnt_odstate *new)
+{
+ struct nfs4_clnt_odstate *co;
+ struct nfs4_client *cl;
+
+ if (!new)
+ return NULL;
+
+ cl = new->co_client;
+
+ spin_lock(&fp->fi_lock);
+ list_for_each_entry(co, &fp->fi_clnt_odstate, co_perfile) {
+ if (co->co_client == cl) {
+ get_clnt_odstate(co);
+ goto out;
+ }
+ }
+ co = new;
+ co->co_file = fp;
+ hash_clnt_odstate_locked(new);
+out:
+ spin_unlock(&fp->fi_lock);
+ return co;
+}
+
struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl,
struct kmem_cache *slab)
{
}
static struct nfs4_delegation *
-alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh)
+alloc_init_deleg(struct nfs4_client *clp, struct svc_fh *current_fh,
+ struct nfs4_clnt_odstate *odstate)
{
struct nfs4_delegation *dp;
long n;
INIT_LIST_HEAD(&dp->dl_perfile);
INIT_LIST_HEAD(&dp->dl_perclnt);
INIT_LIST_HEAD(&dp->dl_recall_lru);
+ dp->dl_clnt_odstate = odstate;
+ get_clnt_odstate(odstate);
dp->dl_type = NFS4_OPEN_DELEGATE_READ;
dp->dl_retries = 1;
nfsd4_init_cb(&dp->dl_recall, dp->dl_stid.sc_client,
spin_lock(&state_lock);
unhash_delegation_locked(dp);
spin_unlock(&state_lock);
+ put_clnt_odstate(dp->dl_clnt_odstate);
nfs4_put_deleg_lease(dp->dl_stid.sc_file);
nfs4_put_stid(&dp->dl_stid);
}
WARN_ON(!list_empty(&dp->dl_recall_lru));
+ put_clnt_odstate(dp->dl_clnt_odstate);
nfs4_put_deleg_lease(dp->dl_stid.sc_file);
if (clp->cl_minorversion == 0)
{
struct nfs4_ol_stateid *stp = openlockstateid(stid);
+ put_clnt_odstate(stp->st_clnt_odstate);
release_all_access(stp);
if (stp->st_stateowner)
nfs4_put_stateowner(stp->st_stateowner);
INIT_LIST_HEAD(&clp->cl_openowners);
INIT_LIST_HEAD(&clp->cl_delegations);
INIT_LIST_HEAD(&clp->cl_lru);
- INIT_LIST_HEAD(&clp->cl_callbacks);
INIT_LIST_HEAD(&clp->cl_revoked);
#ifdef CONFIG_NFSD_PNFS
INIT_LIST_HEAD(&clp->cl_lo_states);
while (!list_empty(&reaplist)) {
dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
list_del_init(&dp->dl_recall_lru);
+ put_clnt_odstate(dp->dl_clnt_odstate);
nfs4_put_deleg_lease(dp->dl_stid.sc_file);
nfs4_put_stid(&dp->dl_stid);
}
spin_lock_init(&fp->fi_lock);
INIT_LIST_HEAD(&fp->fi_stateids);
INIT_LIST_HEAD(&fp->fi_delegations);
+ INIT_LIST_HEAD(&fp->fi_clnt_odstate);
fh_copy_shallow(&fp->fi_fhandle, fh);
fp->fi_deleg_file = NULL;
fp->fi_had_conflict = false;
void
nfsd4_free_slabs(void)
{
+ kmem_cache_destroy(odstate_slab);
kmem_cache_destroy(openowner_slab);
kmem_cache_destroy(lockowner_slab);
kmem_cache_destroy(file_slab);
sizeof(struct nfs4_delegation), 0, 0, NULL);
if (deleg_slab == NULL)
goto out_free_stateid_slab;
+ odstate_slab = kmem_cache_create("nfsd4_odstate",
+ sizeof(struct nfs4_clnt_odstate), 0, 0, NULL);
+ if (odstate_slab == NULL)
+ goto out_free_deleg_slab;
return 0;
+out_free_deleg_slab:
+ kmem_cache_destroy(deleg_slab);
out_free_stateid_slab:
kmem_cache_destroy(stateid_slab);
out_free_file_slab:
open->op_stp = nfs4_alloc_open_stateid(clp);
if (!open->op_stp)
return nfserr_jukebox;
+
+ if (nfsd4_has_session(cstate) &&
+ (cstate->current_fh.fh_export->ex_flags & NFSEXP_PNFS)) {
+ open->op_odstate = alloc_clnt_odstate(clp);
+ if (!open->op_odstate)
+ return nfserr_jukebox;
+ }
+
return nfs_ok;
}
static struct nfs4_delegation *
nfs4_set_delegation(struct nfs4_client *clp, struct svc_fh *fh,
- struct nfs4_file *fp)
+ struct nfs4_file *fp, struct nfs4_clnt_odstate *odstate)
{
int status;
struct nfs4_delegation *dp;
if (fp->fi_had_conflict)
return ERR_PTR(-EAGAIN);
- dp = alloc_init_deleg(clp, fh);
+ dp = alloc_init_deleg(clp, fh, odstate);
if (!dp)
return ERR_PTR(-ENOMEM);
spin_unlock(&state_lock);
out:
if (status) {
+ put_clnt_odstate(dp->dl_clnt_odstate);
nfs4_put_stid(&dp->dl_stid);
return ERR_PTR(status);
}
default:
goto out_no_deleg;
}
- dp = nfs4_set_delegation(clp, fh, stp->st_stid.sc_file);
+ dp = nfs4_set_delegation(clp, fh, stp->st_stid.sc_file, stp->st_clnt_odstate);
if (IS_ERR(dp))
goto out_no_deleg;
release_open_stateid(stp);
goto out;
}
+
+ stp->st_clnt_odstate = find_or_hash_clnt_odstate(fp,
+ open->op_odstate);
+ if (stp->st_clnt_odstate == open->op_odstate)
+ open->op_odstate = NULL;
}
update_stateid(&stp->st_stid.sc_stateid);
memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
kmem_cache_free(file_slab, open->op_file);
if (open->op_stp)
nfs4_put_stid(&open->op_stp->st_stid);
+ if (open->op_odstate)
+ kmem_cache_free(odstate_slab, open->op_odstate);
}
__be32
return nfserr_old_stateid;
}
+static __be32 nfsd4_check_openowner_confirmed(struct nfs4_ol_stateid *ols)
+{
+ if (ols->st_stateowner->so_is_open_owner &&
+ !(openowner(ols->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
+ return nfserr_bad_stateid;
+ return nfs_ok;
+}
+
static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
{
struct nfs4_stid *s;
- struct nfs4_ol_stateid *ols;
__be32 status = nfserr_bad_stateid;
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
break;
case NFS4_OPEN_STID:
case NFS4_LOCK_STID:
- ols = openlockstateid(s);
- if (ols->st_stateowner->so_is_open_owner
- && !(openowner(ols->st_stateowner)->oo_flags
- & NFS4_OO_CONFIRMED))
- status = nfserr_bad_stateid;
- else
- status = nfs_ok;
+ status = nfsd4_check_openowner_confirmed(openlockstateid(s));
break;
default:
printk("unknown stateid type %x\n", s->sc_type);
status = nfs4_check_fh(current_fh, stp);
if (status)
goto out;
- if (stp->st_stateowner->so_is_open_owner
- && !(openowner(stp->st_stateowner)->oo_flags & NFS4_OO_CONFIRMED))
+ status = nfsd4_check_openowner_confirmed(stp);
+ if (status)
goto out;
status = nfs4_check_openmode(stp, flags);
if (status)
update_stateid(&stp->st_stid.sc_stateid);
memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
- nfsd4_return_all_file_layouts(stp->st_stateowner->so_client,
- stp->st_stid.sc_file);
-
nfsd4_close_open_stateid(stp);
/* put reference from nfs4_preprocess_seqid_op */
list_for_each_safe(pos, next, &reaplist) {
dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
list_del_init(&dp->dl_recall_lru);
+ put_clnt_odstate(dp->dl_clnt_odstate);
nfs4_put_deleg_lease(dp->dl_stid.sc_file);
nfs4_put_stid(&dp->dl_stid);
}
struct nfsd4_callback {
struct nfs4_client *cb_clp;
- struct list_head cb_per_client;
u32 cb_minorversion;
struct rpc_message cb_msg;
struct nfsd4_callback_ops *cb_ops;
struct work_struct cb_work;
- bool cb_done;
+ int cb_status;
+ bool cb_need_restart;
};
struct nfsd4_callback_ops {
struct list_head dl_perfile;
struct list_head dl_perclnt;
struct list_head dl_recall_lru; /* delegation recalled */
+ struct nfs4_clnt_odstate *dl_clnt_odstate;
u32 dl_type;
time_t dl_time;
/* For recall: */
int cl_cb_state;
struct nfsd4_callback cl_cb_null;
struct nfsd4_session *cl_cb_session;
- struct list_head cl_callbacks; /* list of in-progress callbacks */
/* for all client information that callback code might need: */
spinlock_t cl_lock;
return container_of(so, struct nfs4_lockowner, lo_owner);
}
+/*
+ * Per-client state indicating no. of opens and outstanding delegations
+ * on a file from a particular client.'od' stands for 'open & delegation'
+ */
+struct nfs4_clnt_odstate {
+ struct nfs4_client *co_client;
+ struct nfs4_file *co_file;
+ struct list_head co_perfile;
+ atomic_t co_odcount;
+};
+
/*
* nfs4_file: a file opened by some number of (open) nfs4_stateowners.
*
struct list_head fi_delegations;
struct rcu_head fi_rcu;
};
+ struct list_head fi_clnt_odstate;
/* One each for O_RDONLY, O_WRONLY, O_RDWR: */
struct file * fi_fds[3];
/*
struct list_head st_perstateowner;
struct list_head st_locks;
struct nfs4_stateowner * st_stateowner;
+ struct nfs4_clnt_odstate * st_clnt_odstate;
unsigned char st_access_bmap;
unsigned char st_deny_bmap;
struct nfs4_ol_stateid * st_openstp;
struct nfs4_openowner *op_openowner; /* used during processing */
struct nfs4_file *op_file; /* used during processing */
struct nfs4_ol_stateid *op_stp; /* used during processing */
+ struct nfs4_clnt_odstate *op_odstate; /* used during processing */
struct nfs4_acl *op_acl;
struct xdr_netobj op_label;
};
nchildren = nilfs_btree_node_get_nchildren(node);
if (unlikely(level < NILFS_BTREE_LEVEL_NODE_MIN ||
- level > NILFS_BTREE_LEVEL_MAX ||
+ level >= NILFS_BTREE_LEVEL_MAX ||
nchildren < 0 ||
nchildren > NILFS_BTREE_ROOT_NCHILDREN_MAX)) {
pr_crit("NILFS: bad btree root (inode number=%lu): level = %d, flags = 0x%x, nchildren = %d\n",
if (tmpres) {
spin_unlock(&dlm->spinlock);
spin_lock(&tmpres->spinlock);
+
+ /*
+ * Right after dlm spinlock was released, dlm_thread could have
+ * purged the lockres. Check if lockres got unhashed. If so
+ * start over.
+ */
+ if (hlist_unhashed(&tmpres->hash_node)) {
+ spin_unlock(&tmpres->spinlock);
+ dlm_lockres_put(tmpres);
+ tmpres = NULL;
+ goto lookup;
+ }
+
/* Wait on the thread that is mastering the resource */
if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
__dlm_wait_on_lockres(tmpres);
long ret, bytes;
umode_t i_mode;
size_t len;
- int i, flags;
+ int i, flags, more;
/*
* We require the input being a regular file, as we don't want to
* Don't block on output, we have to drain the direct pipe.
*/
sd->flags &= ~SPLICE_F_NONBLOCK;
+ more = sd->flags & SPLICE_F_MORE;
while (len) {
size_t read_len;
read_len = ret;
sd->total_len = read_len;
+ /*
+ * If more data is pending, set SPLICE_F_MORE
+ * If this is the last data and SPLICE_F_MORE was not set
+ * initially, clears it.
+ */
+ if (read_len < len)
+ sd->flags |= SPLICE_F_MORE;
+ else if (!more)
+ sd->flags &= ~SPLICE_F_MORE;
/*
* NOTE: nonblocking mode only applies to the input. We
* must not do the output in nonblocking mode as then we
{0x1002, 0x6658, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x665c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x665d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x665f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BONAIRE|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6660, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6663, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
{0x1002, 0x6664, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HAINAN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
/* This mask is used for both bio and request merge checking */
#define REQ_NOMERGE_FLAGS \
- (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA)
+ (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA | REQ_FLUSH_SEQ)
#define REQ_RAHEAD (1ULL << __REQ_RAHEAD)
#define REQ_THROTTLED (1ULL << __REQ_THROTTLED)
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
-
/* Optimization barrier */
+
/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")
+/*
+ * This version is i.e. to prevent dead stores elimination on @ptr
+ * where gcc and llvm may behave differently when otherwise using
+ * normal barrier(): while gcc behavior gets along with a normal
+ * barrier(), llvm needs an explicit input variable to be assumed
+ * clobbered. The issue is as follows: while the inline asm might
+ * access any memory it wants, the compiler could have fit all of
+ * @ptr into memory registers instead, and since @ptr never escaped
+ * from that, it proofed that the inline asm wasn't touching any of
+ * it. This version works well with both compilers, i.e. we're telling
+ * the compiler that the inline asm absolutely may see the contents
+ * of @ptr. See also: https://llvm.org/bugs/show_bug.cgi?id=15495
+ */
+#define barrier_data(ptr) __asm__ __volatile__("": :"r"(ptr) :"memory")
/*
* This macro obfuscates arithmetic on a variable address so that gcc
/* Intel ECC compiler doesn't support gcc specific asm stmts.
* It uses intrinsics to do the equivalent things.
*/
+#undef barrier_data
#undef RELOC_HIDE
#undef OPTIMIZER_HIDE_VAR
+#define barrier_data(ptr) barrier()
+
#define RELOC_HIDE(ptr, off) \
({ unsigned long __ptr; \
__ptr = (unsigned long) (ptr); \
# define barrier() __memory_barrier()
#endif
+#ifndef barrier_data
+# define barrier_data(ptr) barrier()
+#endif
+
/* Unreachable code */
#ifndef unreachable
# define unreachable() do { } while (1)
const unsigned char *buf, int len);
const char *ftrace_print_array_seq(struct trace_seq *p,
- const void *buf, int buf_len,
+ const void *buf, int count,
size_t el_size);
struct trace_iterator;
#define ___GFP_HARDWALL 0x20000u
#define ___GFP_THISNODE 0x40000u
#define ___GFP_RECLAIMABLE 0x80000u
+#define ___GFP_NOACCOUNT 0x100000u
#define ___GFP_NOTRACK 0x200000u
#define ___GFP_NO_KSWAPD 0x400000u
#define ___GFP_OTHER_NODE 0x800000u
#define __GFP_HARDWALL ((__force gfp_t)___GFP_HARDWALL) /* Enforce hardwall cpuset memory allocs */
#define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE)/* No fallback, no policies */
#define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */
+#define __GFP_NOACCOUNT ((__force gfp_t)___GFP_NOACCOUNT) /* Don't account to kmemcg */
#define __GFP_NOTRACK ((__force gfp_t)___GFP_NOTRACK) /* Don't track with kmemcheck */
#define __GFP_NO_KSWAPD ((__force gfp_t)___GFP_NO_KSWAPD)
struct device_node;
-extern struct irq_chip gic_arch_extn;
-
void gic_set_irqchip_flags(unsigned long flags);
void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
u32 offset, struct device_node *);
ATA_LFLAG_SW_ACTIVITY = (1 << 7), /* keep activity stats */
ATA_LFLAG_NO_LPM = (1 << 8), /* disable LPM on this link */
ATA_LFLAG_RST_ONCE = (1 << 9), /* limit recovery to one reset */
+ ATA_LFLAG_CHANGED = (1 << 10), /* LPM state changed on this link */
/* struct ata_port flags */
ATA_FLAG_SLAVE_POSS = (1 << 0), /* host supports slave dev */
*/
ATA_TMOUT_PMP_SRST_WAIT = 5000,
+ /* When the LPM policy is set to ATA_LPM_MAX_POWER, there might
+ * be a spurious PHY event, so ignore the first PHY event that
+ * occurs within 10s after the policy change.
+ */
+ ATA_TMOUT_SPURIOUS_PHY = 10000,
+
/* ATA bus states */
BUS_UNKNOWN = 0,
BUS_DMA = 1,
struct ata_eh_context eh_context;
struct ata_device device[ATA_MAX_DEVICES];
+
+ unsigned long last_lpm_change; /* when last LPM change happened */
};
#define ATA_LINK_CLEAR_BEGIN offsetof(struct ata_link, active_tag)
#define ATA_LINK_CLEAR_END offsetof(struct ata_link, device[0])
extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap);
extern void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, struct list_head *eh_q);
+extern bool sata_lpm_ignore_phy_events(struct ata_link *link);
extern int ata_cable_40wire(struct ata_port *ap);
extern int ata_cable_80wire(struct ata_port *ap);
if (!memcg_kmem_enabled())
return true;
+ if (gfp & __GFP_NOACCOUNT)
+ return true;
/*
* __GFP_NOFAIL allocations will move on even if charging is not
* possible. Therefore we don't even try, and have this allocation
{
if (!memcg_kmem_enabled())
return cachep;
+ if (gfp & __GFP_NOACCOUNT)
+ return cachep;
if (gfp & __GFP_NOFAIL)
return cachep;
if (in_interrupt() || (!current->mm) || (current->flags & PF_KTHREAD))
#ifndef _LINUX_NETDEVICE_H
#define _LINUX_NETDEVICE_H
-#include <linux/pm_qos.h>
#include <linux/timer.h>
#include <linux/bug.h>
#include <linux/delay.h>
*
* @qdisc_tx_busylock: XXX: need comments on this one
*
- * @pm_qos_req: Power Management QoS object
- *
* FIXME: cleanup struct net_device such that network protocol info
* moves out.
*/
/* level */
#define NILFS_BTREE_LEVEL_DATA 0
#define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1)
-#define NILFS_BTREE_LEVEL_MAX 14
+#define NILFS_BTREE_LEVEL_MAX 14 /* Max level (exclusive) */
/**
* struct nilfs_palloc_group_desc - block group descriptor
#define PCI_VENDOR_ID_INTEL 0x8086
#define PCI_DEVICE_ID_INTEL_EESSC 0x0008
-#define PCI_DEVICE_ID_INTEL_SNB_IMC 0x0100
-#define PCI_DEVICE_ID_INTEL_IVB_IMC 0x0154
-#define PCI_DEVICE_ID_INTEL_IVB_E3_IMC 0x0150
-#define PCI_DEVICE_ID_INTEL_HSW_IMC 0x0c00
#define PCI_DEVICE_ID_INTEL_PXHD_0 0x0320
#define PCI_DEVICE_ID_INTEL_PXHD_1 0x0321
#define PCI_DEVICE_ID_INTEL_PXH_0 0x0329
#ifdef CONFIG_RT_MUTEXES
extern int rt_mutex_getprio(struct task_struct *p);
extern void rt_mutex_setprio(struct task_struct *p, int prio);
-extern int rt_mutex_check_prio(struct task_struct *task, int newprio);
+extern int rt_mutex_get_effective_prio(struct task_struct *task, int newprio);
extern struct task_struct *rt_mutex_get_top_task(struct task_struct *task);
extern void rt_mutex_adjust_pi(struct task_struct *p);
static inline bool tsk_is_pi_blocked(struct task_struct *tsk)
return p->normal_prio;
}
-static inline int rt_mutex_check_prio(struct task_struct *task, int newprio)
+static inline int rt_mutex_get_effective_prio(struct task_struct *task,
+ int newprio)
{
- return 0;
+ return newprio;
}
static inline struct task_struct *rt_mutex_get_top_task(struct task_struct *task)
* read the code and the spec side by side (and laugh ...)
* See RFC793 and RFC1122. The RFC writes these in capitals.
*/
+ u64 bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived
+ * sum(delta(rcv_nxt)), or how many bytes
+ * were acked.
+ */
u32 rcv_nxt; /* What we want to receive next */
u32 copied_seq; /* Head of yet unread data */
u32 rcv_wup; /* rcv_nxt on last window update sent */
u32 snd_nxt; /* Next sequence we send */
+ u64 bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked
+ * sum(delta(snd_una)), or how many bytes
+ * were acked.
+ */
u32 snd_una; /* First byte we want an ack for */
u32 snd_sml; /* Last byte of the most recently transmitted small packet */
u32 rcv_tstamp; /* timestamp of last received ACK (for keepalives) */
#define TTY_EXCLUSIVE 3 /* Exclusive open mode */
#define TTY_DEBUG 4 /* Debugging */
#define TTY_DO_WRITE_WAKEUP 5 /* Call write_wakeup after queuing new */
+#define TTY_OTHER_DONE 6 /* Closed pty has completed input processing */
#define TTY_LDISC_OPEN 11 /* Line discipline is open */
#define TTY_PTY_LOCK 16 /* pty private */
#define TTY_NO_WRITE_SPLIT 17 /* Preserve write boundaries to driver */
extern void do_SAK(struct tty_struct *tty);
extern void __do_SAK(struct tty_struct *tty);
extern void no_tty(void);
-extern void tty_flush_to_ldisc(struct tty_struct *tty);
extern void tty_buffer_free_all(struct tty_port *port);
extern void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld);
extern void tty_buffer_init(struct tty_port *port);
static inline bool uid_valid(kuid_t uid)
{
- return !uid_eq(uid, INVALID_UID);
+ return __kuid_val(uid) != (uid_t) -1;
}
static inline bool gid_valid(kgid_t gid)
{
- return !gid_eq(gid, INVALID_GID);
+ return __kgid_val(gid) != (gid_t) -1;
}
#ifdef CONFIG_USER_NS
({ \
typeof(as) __fc_i, __fc_as = (as) - 1; \
typeof(x) __fc_x = (x); \
- typeof(*a) *__fc_a = (a); \
+ typeof(*a) const *__fc_a = (a); \
for (__fc_i = 0; __fc_i < __fc_as; __fc_i++) { \
if (__fc_x op DIV_ROUND_CLOSEST(__fc_a[__fc_i] + \
__fc_a[__fc_i + 1], 2)) \
struct cfg802154_ops {
struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
const char *name,
+ unsigned char name_assign_type,
int type);
void (*del_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
struct net_device *dev);
int (*add_virtual_intf)(struct wpan_phy *wpan_phy,
const char *name,
+ unsigned char name_assign_type,
enum nl802154_iftype type,
__le64 extended_addr);
int (*del_virtual_intf)(struct wpan_phy *wpan_phy,
* struct codel_params - contains codel parameters
* @target: target queue size (in time units)
* @interval: width of moving time window
+ * @mtu: device mtu, or minimal queue backlog in bytes.
* @ecn: is Explicit Congestion Notification enabled
*/
struct codel_params {
codel_time_t target;
codel_time_t interval;
+ u32 mtu;
bool ecn;
};
u32 ecn_mark;
};
-static void codel_params_init(struct codel_params *params)
+static void codel_params_init(struct codel_params *params,
+ const struct Qdisc *sch)
{
params->interval = MS2TIME(100);
params->target = MS2TIME(5);
+ params->mtu = psched_mtu(qdisc_dev(sch));
params->ecn = false;
}
static void codel_stats_init(struct codel_stats *stats)
{
- stats->maxpacket = 256;
+ stats->maxpacket = 0;
}
/*
stats->maxpacket = qdisc_pkt_len(skb);
if (codel_time_before(vars->ldelay, params->target) ||
- sch->qstats.backlog <= stats->maxpacket) {
+ sch->qstats.backlog <= params->mtu) {
/* went below - stay below for at least interval */
vars->first_above_time = 0;
return false;
* @sta: station table entry, %NULL for per-vif queue
* @tid: the TID for this queue (unused for per-vif queue)
* @ac: the AC for this queue
+ * @drv_priv: data area for driver use, will always be aligned to
+ * sizeof(void *).
*
* The driver can obtain packets from this queue by calling
* ieee80211_tx_dequeue().
__put_unaligned_memmove64(swab64p(le64_src), be64_dst);
}
-/* Basic interface to register ieee802154 device */
+/**
+ * ieee802154_alloc_hw - Allocate a new hardware device
+ *
+ * This must be called once for each hardware device. The returned pointer
+ * must be used to refer to this device when calling other functions.
+ * mac802154 allocates a private data area for the driver pointed to by
+ * @priv in &struct ieee802154_hw, the size of this area is given as
+ * @priv_data_len.
+ *
+ * @priv_data_len: length of private data
+ * @ops: callbacks for this device
+ *
+ * Return: A pointer to the new hardware device, or %NULL on error.
+ */
struct ieee802154_hw *
ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops);
+
+/**
+ * ieee802154_free_hw - free hardware descriptor
+ *
+ * This function frees everything that was allocated, including the
+ * private data for the driver. You must call ieee802154_unregister_hw()
+ * before calling this function.
+ *
+ * @hw: the hardware to free
+ */
void ieee802154_free_hw(struct ieee802154_hw *hw);
+
+/**
+ * ieee802154_register_hw - Register hardware device
+ *
+ * You must call this function before any other functions in
+ * mac802154. Note that before a hardware can be registered, you
+ * need to fill the contained wpan_phy's information.
+ *
+ * @hw: the device to register as returned by ieee802154_alloc_hw()
+ *
+ * Return: 0 on success. An error code otherwise.
+ */
int ieee802154_register_hw(struct ieee802154_hw *hw);
+
+/**
+ * ieee802154_unregister_hw - Unregister a hardware device
+ *
+ * This function instructs mac802154 to free allocated resources
+ * and unregister netdevices from the networking subsystem.
+ *
+ * @hw: the hardware to unregister
+ */
void ieee802154_unregister_hw(struct ieee802154_hw *hw);
+/**
+ * ieee802154_rx - receive frame
+ *
+ * Use this function to hand received frames to mac802154. The receive
+ * buffer in @skb must start with an IEEE 802.15.4 header. In case of a
+ * paged @skb is used, the driver is recommended to put the ieee802154
+ * header of the frame on the linear part of the @skb to avoid memory
+ * allocation and/or memcpy by the stack.
+ *
+ * This function may not be called in IRQ context. Calls to this function
+ * for a single hardware must be synchronized against each other.
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac802154 after this call
+ */
void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb);
+
+/**
+ * ieee802154_rx_irqsafe - receive frame
+ *
+ * Like ieee802154_rx() but can be called in IRQ context
+ * (internally defers to a tasklet.)
+ *
+ * @hw: the hardware this frame came in on
+ * @skb: the buffer to receive, owned by mac802154 after this call
+ * @lqi: link quality indicator
+ */
void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb,
u8 lqi);
-
+/**
+ * ieee802154_wake_queue - wake ieee802154 queue
+ * @hw: pointer as obtained from ieee802154_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_wake_queue.
+ */
void ieee802154_wake_queue(struct ieee802154_hw *hw);
+
+/**
+ * ieee802154_stop_queue - stop ieee802154 queue
+ * @hw: pointer as obtained from ieee802154_alloc_hw().
+ *
+ * Drivers should use this function instead of netif_stop_queue.
+ */
void ieee802154_stop_queue(struct ieee802154_hw *hw);
+
+/**
+ * ieee802154_xmit_complete - frame transmission complete
+ *
+ * @hw: pointer as obtained from ieee802154_alloc_hw().
+ * @skb: buffer for transmission
+ * @ifs_handling: indicate interframe space handling
+ */
void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
bool ifs_handling);
}
/* tcp.c */
-void tcp_get_info(const struct sock *, struct tcp_info *);
+void tcp_get_info(struct sock *, struct tcp_info *);
/* Read 'sendfile()'-style from a TCP socket */
typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
/* Requires ECN/ECT set on all packets */
#define TCP_CONG_NEEDS_ECN 0x2
+union tcp_cc_info;
+
struct tcp_congestion_ops {
struct list_head list;
u32 key;
/* hook for packet ack accounting (optional) */
void (*pkts_acked)(struct sock *sk, u32 num_acked, s32 rtt_us);
/* get info for inet_diag (optional) */
- int (*get_info)(struct sock *sk, u32 ext, struct sk_buff *skb);
+ size_t (*get_info)(struct sock *sk, u32 ext, int *attr,
+ union tcp_cc_info *info);
char name[TCP_CA_NAME_MAX];
struct module *owner;
}
/* Important - sockaddr should be a union of sockaddr_in and sockaddr_in6 */
-static inline int rdma_gid2ip(struct sockaddr *out, union ib_gid *gid)
+static inline void rdma_gid2ip(struct sockaddr *out, union ib_gid *gid)
{
if (ipv6_addr_v4mapped((struct in6_addr *)gid)) {
struct sockaddr_in *out_in = (struct sockaddr_in *)out;
out_in->sin6_family = AF_INET6;
memcpy(&out_in->sin6_addr.s6_addr, gid->raw, 16);
}
- return 0;
}
static inline void iboe_addr_get_sgid(struct rdma_dev_addr *dev_addr,
IB_CM_SIDR_REQ_PRIVATE_DATA_SIZE = 216,
IB_CM_SIDR_REP_PRIVATE_DATA_SIZE = 136,
IB_CM_SIDR_REP_INFO_LENGTH = 72,
- IB_CM_COMPARE_SIZE = 64
+ /* compare done u32 at a time */
+ IB_CM_COMPARE_SIZE = (64 / sizeof(u32))
};
struct ib_cm_id;
#define IB_SDP_SERVICE_ID_MASK cpu_to_be64(0xFFFFFFFFFFFF0000ULL)
struct ib_cm_compare_data {
- u8 data[IB_CM_COMPARE_SIZE];
- u8 mask[IB_CM_COMPARE_SIZE];
+ u32 data[IB_CM_COMPARE_SIZE];
+ u32 mask[IB_CM_COMPARE_SIZE];
};
/**
*/
int iwpm_add_and_query_mapping_cb(struct sk_buff *, struct netlink_callback *);
+/**
+ * iwpm_remote_info_cb - Process remote connecting peer address info, which
+ * the port mapper has received from the connecting peer
+ *
+ * @cb: Contains the received message (payload and netlink header)
+ *
+ * Stores the IPv4/IPv6 address info in a hash table
+ */
+int iwpm_remote_info_cb(struct sk_buff *, struct netlink_callback *);
+
/**
* iwpm_mapping_error_cb - Process port mapper notification for error
*
*/
int iwpm_ack_mapping_info_cb(struct sk_buff *, struct netlink_callback *);
+/**
+ * iwpm_get_remote_info - Get the remote connecting peer address info
+ *
+ * @mapped_loc_addr: Mapped local address of the listening peer
+ * @mapped_rem_addr: Mapped remote address of the connecting peer
+ * @remote_addr: To store the remote address of the connecting peer
+ * @nl_client: The index of the netlink client
+ *
+ * The remote address info is retrieved and provided to the client in
+ * the remote_addr. After that it is removed from the hash table
+ */
+int iwpm_get_remote_info(struct sockaddr_storage *mapped_loc_addr,
+ struct sockaddr_storage *mapped_rem_addr,
+ struct sockaddr_storage *remote_addr, u8 nl_client);
+
/**
* iwpm_create_mapinfo - Store local and mapped IPv4/IPv6 address
* info in a hash table
__u32 dctcp_ab_tot;
};
+union tcp_cc_info {
+ struct tcpvegas_info vegas;
+ struct tcp_dctcp_info dctcp;
+};
#endif /* _UAPI_INET_DIAG_H_ */
#define MPLS_LS_TTL_MASK 0x000000FF
#define MPLS_LS_TTL_SHIFT 0
+/* Reserved labels */
+#define MPLS_LABEL_IPV4NULL 0 /* RFC3032 */
+#define MPLS_LABEL_RTALERT 1 /* RFC3032 */
+#define MPLS_LABEL_IPV6NULL 2 /* RFC3032 */
+#define MPLS_LABEL_IMPLNULL 3 /* RFC3032 */
+#define MPLS_LABEL_ENTROPY 7 /* RFC6790 */
+#define MPLS_LABEL_GAL 13 /* RFC5586 */
+#define MPLS_LABEL_OAMALERT 14 /* RFC3429 */
+#define MPLS_LABEL_EXTENSION 15 /* RFC7274 */
+
#endif /* _UAPI_MPLS_H */
#define TCP_FASTOPEN 23 /* Enable FastOpen on listeners */
#define TCP_TIMESTAMP 24
#define TCP_NOTSENT_LOWAT 25 /* limit number of unsent bytes in write queue */
+#define TCP_CC_INFO 26 /* Get Congestion Control (optional) info */
struct tcp_repair_opt {
__u32 opt_code;
__u64 tcpi_pacing_rate;
__u64 tcpi_max_pacing_rate;
+ __u64 tcpi_bytes_acked; /* RFC4898 tcpEStatsAppHCThruOctetsAcked */
+ __u64 tcpi_bytes_received; /* RFC4898 tcpEStatsAppHCThruOctetsReceived */
};
/* for TCP_MD5SIG socket option */
RDMA_NL_IWPM_ADD_MAPPING,
RDMA_NL_IWPM_QUERY_MAPPING,
RDMA_NL_IWPM_REMOVE_MAPPING,
+ RDMA_NL_IWPM_REMOTE_INFO,
RDMA_NL_IWPM_HANDLE_ERR,
RDMA_NL_IWPM_MAPINFO,
RDMA_NL_IWPM_MAPINFO_NUM,
struct gnttab_unmap_grant_ref *kunmap_ops,
struct page **pages, unsigned int count);
void gnttab_unmap_refs_async(struct gntab_unmap_queue_data* item);
+int gnttab_unmap_refs_sync(struct gntab_unmap_queue_data *item);
/* Perform a batch of grant map/copy operations. Retry every batch slot
void xen_timer_resume(void);
void xen_arch_resume(void);
+void xen_arch_suspend(void);
void xen_resume_notifier_register(struct notifier_block *nb);
void xen_resume_notifier_unregister(struct notifier_block *nb);
#endif
if (strncmp(name, "/dev/", 5) != 0) {
- unsigned maj, min;
+ unsigned maj, min, offset;
char dummy;
- if (sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2) {
+ if ((sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2) ||
+ (sscanf(name, "%u:%u:%u:%c", &maj, &min, &offset, &dummy) == 3)) {
res = MKDEV(maj, min);
if (maj != MAJOR(res) || min != MINOR(res))
goto fail;
* Those places that change perf_event::ctx will hold both
* perf_event_ctx::mutex of the 'old' and 'new' ctx value.
*
- * Lock ordering is by mutex address. There is one other site where
- * perf_event_context::mutex nests and that is put_event(). But remember that
- * that is a parent<->child context relation, and migration does not affect
- * children, therefore these two orderings should not interact.
+ * Lock ordering is by mutex address. There are two other sites where
+ * perf_event_context::mutex nests and those are:
+ *
+ * - perf_event_exit_task_context() [ child , 0 ]
+ * __perf_event_exit_task()
+ * sync_child_event()
+ * put_event() [ parent, 1 ]
+ *
+ * - perf_event_init_context() [ parent, 0 ]
+ * inherit_task_group()
+ * inherit_group()
+ * inherit_event()
+ * perf_event_alloc()
+ * perf_init_event()
+ * perf_try_init_event() [ child , 1 ]
+ *
+ * While it appears there is an obvious deadlock here -- the parent and child
+ * nesting levels are inverted between the two. This is in fact safe because
+ * life-time rules separate them. That is an exiting task cannot fork, and a
+ * spawning task cannot (yet) exit.
+ *
+ * But remember that that these are parent<->child context relations, and
+ * migration does not affect children, therefore these two orderings should not
+ * interact.
*
* The change in perf_event::ctx does not affect children (as claimed above)
* because the sys_perf_event_open() case will install a new event and break
}
}
-/*
- * Called when the last reference to the file is gone.
- */
static void put_event(struct perf_event *event)
{
struct perf_event_context *ctx;
}
EXPORT_SYMBOL_GPL(perf_event_release_kernel);
+/*
+ * Called when the last reference to the file is gone.
+ */
static int perf_release(struct inode *inode, struct file *file)
{
put_event(file->private_data);
return -ENODEV;
if (event->group_leader != event) {
- ctx = perf_event_ctx_lock(event->group_leader);
+ /*
+ * This ctx->mutex can nest when we're called through
+ * inheritance. See the perf_event_ctx_lock_nested() comment.
+ */
+ ctx = perf_event_ctx_lock_nested(event->group_leader,
+ SINGLE_DEPTH_NESTING);
BUG_ON(!ctx);
}
.irq_ack = noop,
.irq_mask = noop,
.irq_unmask = noop,
+ .flags = IRQCHIP_SKIP_SET_WAKE,
};
EXPORT_SYMBOL_GPL(dummy_irq_chip);
}
/*
- * Called by sched_setscheduler() to check whether the priority change
- * is overruled by a possible priority boosting.
+ * Called by sched_setscheduler() to get the priority which will be
+ * effective after the change.
*/
-int rt_mutex_check_prio(struct task_struct *task, int newprio)
+int rt_mutex_get_effective_prio(struct task_struct *task, int newprio)
{
if (!task_has_pi_waiters(task))
- return 0;
+ return newprio;
- return task_top_pi_waiter(task)->task->prio <= newprio;
+ if (task_top_pi_waiter(task)->task->prio <= newprio)
+ return task_top_pi_waiter(task)->task->prio;
+ return newprio;
}
/*
static int kthread_prio = CONFIG_RCU_KTHREAD_PRIO;
module_param(kthread_prio, int, 0644);
-/* Delay in jiffies for grace-period initialization delays. */
-static int gp_init_delay = IS_ENABLED(CONFIG_RCU_TORTURE_TEST_SLOW_INIT)
- ? CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY
- : 0;
+/* Delay in jiffies for grace-period initialization delays, debug only. */
+#ifdef CONFIG_RCU_TORTURE_TEST_SLOW_INIT
+static int gp_init_delay = CONFIG_RCU_TORTURE_TEST_SLOW_INIT_DELAY;
module_param(gp_init_delay, int, 0644);
+#else /* #ifdef CONFIG_RCU_TORTURE_TEST_SLOW_INIT */
+static const int gp_init_delay;
+#endif /* #else #ifdef CONFIG_RCU_TORTURE_TEST_SLOW_INIT */
+#define PER_RCU_NODE_PERIOD 10 /* Number of grace periods between delays. */
/*
* Track the rcutorture test sequence number and the update version
raw_spin_unlock_irq(&rnp->lock);
cond_resched_rcu_qs();
ACCESS_ONCE(rsp->gp_activity) = jiffies;
- if (IS_ENABLED(CONFIG_RCU_TORTURE_TEST_SLOW_INIT) &&
- gp_init_delay > 0 &&
- !(rsp->gpnum % (rcu_num_nodes * 10)))
+ if (gp_init_delay > 0 &&
+ !(rsp->gpnum % (rcu_num_nodes * PER_RCU_NODE_PERIOD)))
schedule_timeout_uninterruptible(gp_init_delay);
}
/* Actually do priority change: must hold pi & rq lock. */
static void __setscheduler(struct rq *rq, struct task_struct *p,
- const struct sched_attr *attr)
+ const struct sched_attr *attr, bool keep_boost)
{
__setscheduler_params(p, attr);
/*
- * If we get here, there was no pi waiters boosting the
- * task. It is safe to use the normal prio.
+ * Keep a potential priority boosting if called from
+ * sched_setscheduler().
*/
- p->prio = normal_prio(p);
+ if (keep_boost)
+ p->prio = rt_mutex_get_effective_prio(p, normal_prio(p));
+ else
+ p->prio = normal_prio(p);
if (dl_prio(p->prio))
p->sched_class = &dl_sched_class;
int newprio = dl_policy(attr->sched_policy) ? MAX_DL_PRIO - 1 :
MAX_RT_PRIO - 1 - attr->sched_priority;
int retval, oldprio, oldpolicy = -1, queued, running;
- int policy = attr->sched_policy;
+ int new_effective_prio, policy = attr->sched_policy;
unsigned long flags;
const struct sched_class *prev_class;
struct rq *rq;
oldprio = p->prio;
/*
- * Special case for priority boosted tasks.
- *
- * If the new priority is lower or equal (user space view)
- * than the current (boosted) priority, we just store the new
+ * Take priority boosted tasks into account. If the new
+ * effective priority is unchanged, we just store the new
* normal parameters and do not touch the scheduler class and
* the runqueue. This will be done when the task deboost
* itself.
*/
- if (rt_mutex_check_prio(p, newprio)) {
+ new_effective_prio = rt_mutex_get_effective_prio(p, newprio);
+ if (new_effective_prio == oldprio) {
__setscheduler_params(p, attr);
task_rq_unlock(rq, p, &flags);
return 0;
put_prev_task(rq, p);
prev_class = p->sched_class;
- __setscheduler(rq, p, attr);
+ __setscheduler(rq, p, attr, true);
if (running)
p->sched_class->set_curr_task(rq);
unsigned long flags;
long cpu = (long)hcpu;
struct dl_bw *dl_b;
+ bool overflow;
+ int cpus;
- switch (action & ~CPU_TASKS_FROZEN) {
+ switch (action) {
case CPU_DOWN_PREPARE:
- /* explicitly allow suspend */
- if (!(action & CPU_TASKS_FROZEN)) {
- bool overflow;
- int cpus;
-
- rcu_read_lock_sched();
- dl_b = dl_bw_of(cpu);
+ rcu_read_lock_sched();
+ dl_b = dl_bw_of(cpu);
- raw_spin_lock_irqsave(&dl_b->lock, flags);
- cpus = dl_bw_cpus(cpu);
- overflow = __dl_overflow(dl_b, cpus, 0, 0);
- raw_spin_unlock_irqrestore(&dl_b->lock, flags);
+ raw_spin_lock_irqsave(&dl_b->lock, flags);
+ cpus = dl_bw_cpus(cpu);
+ overflow = __dl_overflow(dl_b, cpus, 0, 0);
+ raw_spin_unlock_irqrestore(&dl_b->lock, flags);
- rcu_read_unlock_sched();
+ rcu_read_unlock_sched();
- if (overflow)
- return notifier_from_errno(-EBUSY);
- }
+ if (overflow)
+ return notifier_from_errno(-EBUSY);
cpuset_update_active_cpus(false);
break;
case CPU_DOWN_PREPARE_FROZEN:
queued = task_on_rq_queued(p);
if (queued)
dequeue_task(rq, p, 0);
- __setscheduler(rq, p, &attr);
+ __setscheduler(rq, p, &attr, false);
if (queued) {
enqueue_task(rq, p, 0);
resched_curr(rq);
/* Transition with new state-specific callbacks */
switch (state) {
case CLOCK_EVT_STATE_DETACHED:
- /*
- * This is an internal state, which is guaranteed to go from
- * SHUTDOWN to DETACHED. No driver interaction required.
- */
- return 0;
+ /* The clockevent device is getting replaced. Shut it down. */
case CLOCK_EVT_STATE_SHUTDOWN:
return dev->set_state_shutdown(dev);
EXPORT_SYMBOL(ftrace_print_hex_seq);
const char *
-ftrace_print_array_seq(struct trace_seq *p, const void *buf, int buf_len,
+ftrace_print_array_seq(struct trace_seq *p, const void *buf, int count,
size_t el_size)
{
const char *ret = trace_seq_buffer_ptr(p);
const char *prefix = "";
void *ptr = (void *)buf;
+ size_t buf_len = count * el_size;
trace_seq_putc(p, '{');
#define NMI_WATCHDOG_ENABLED (1 << NMI_WATCHDOG_ENABLED_BIT)
#define SOFT_WATCHDOG_ENABLED (1 << SOFT_WATCHDOG_ENABLED_BIT)
+static DEFINE_MUTEX(watchdog_proc_mutex);
+
#ifdef CONFIG_HARDLOCKUP_DETECTOR
static unsigned long __read_mostly watchdog_enabled = SOFT_WATCHDOG_ENABLED|NMI_WATCHDOG_ENABLED;
#else
{
int cpu;
- if (!watchdog_user_enabled)
- return;
+ mutex_lock(&watchdog_proc_mutex);
+
+ if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
+ goto unlock;
get_online_cpus();
for_each_online_cpu(cpu)
watchdog_nmi_enable(cpu);
put_online_cpus();
+
+unlock:
+ mutex_lock(&watchdog_proc_mutex);
}
void watchdog_nmi_disable_all(void)
{
int cpu;
+ mutex_lock(&watchdog_proc_mutex);
+
if (!watchdog_running)
- return;
+ goto unlock;
get_online_cpus();
for_each_online_cpu(cpu)
watchdog_nmi_disable(cpu);
put_online_cpus();
+
+unlock:
+ mutex_unlock(&watchdog_proc_mutex);
}
#else
static int watchdog_nmi_enable(unsigned int cpu) { return 0; }
}
-static DEFINE_MUTEX(watchdog_proc_mutex);
-
/*
* common function for watchdog, nmi_watchdog and soft_watchdog parameter
*
int "How much to slow down RCU grace-period initialization"
range 0 5
default 3
+ depends on RCU_TORTURE_TEST_SLOW_INIT
help
This option specifies the number of jiffies to wait between
each rcu_node structure initialization.
help
Enables kernel address sanitizer - runtime memory debugger,
designed to find out-of-bounds accesses and use-after-free bugs.
- This is strictly debugging feature. It consumes about 1/8
- of available memory and brings about ~x3 performance slowdown.
+ This is strictly a debugging feature and it requires a gcc version
+ of 4.9.2 or later. Detection of out of bounds accesses to stack or
+ global variables requires gcc 5.0 or later.
+ This feature consumes about 1/8 of available memory and brings about
+ ~x3 performance slowdown.
For better error detection enable CONFIG_STACKTRACE,
and add slub_debug=U to boot cmdline.
memory accesses. This is faster than outline (in some workloads
it gives about x2 boost over outline instrumentation), but
make kernel's .text size much bigger.
+ This requires a gcc version of 5.0 or later.
endchoice
+++ /dev/null
-/* find_last_bit.c: fallback find next bit implementation
- *
- * Copyright (C) 2008 IBM Corporation
- * Written by Rusty Russell <rusty@rustcorp.com.au>
- * (Inspired by David Howell's find_next_bit implementation)
- *
- * Rewritten by Yury Norov <yury.norov@gmail.com> to decrease
- * size and improve performance, 2015.
- *
- * 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 <linux/bitops.h>
-#include <linux/bitmap.h>
-#include <linux/export.h>
-#include <linux/kernel.h>
-
-#ifndef find_last_bit
-
-unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
-{
- if (size) {
- unsigned long val = BITMAP_LAST_WORD_MASK(size);
- unsigned long idx = (size-1) / BITS_PER_LONG;
-
- do {
- val &= addr[idx];
- if (val)
- return idx * BITS_PER_LONG + __fls(val);
-
- val = ~0ul;
- } while (idx--);
- }
- return size;
-}
-EXPORT_SYMBOL(find_last_bit);
-
-#endif
void memzero_explicit(void *s, size_t count)
{
memset(s, 0, count);
- barrier();
+ barrier_data(s);
}
EXPORT_SYMBOL(memzero_explicit);
if (!hwpoison_filter_enable)
goto inject;
- if (!PageLRU(p) && !PageHuge(p))
- shake_page(p, 0);
+ if (!PageLRU(hpage) && !PageHuge(p))
+ shake_page(hpage, 0);
/*
* This implies unable to support non-LRU pages.
*/
- if (!PageLRU(p) && !PageHuge(p))
- return 0;
+ if (!PageLRU(hpage) && !PageHuge(p))
+ goto put_out;
/*
* do a racy check with elevated page count, to make sure PG_hwpoison
err = hwpoison_filter(hpage);
unlock_page(hpage);
if (err)
- return 0;
+ goto put_out;
inject:
pr_info("Injecting memory failure at pfn %#lx\n", pfn);
return memory_failure(pfn, 18, MF_COUNT_INCREASED);
+put_out:
+ put_page(hpage);
+ return 0;
}
static int hwpoison_unpoison(void *data, u64 val)
#define BYTES_PER_POINTER sizeof(void *)
/* GFP bitmask for kmemleak internal allocations */
-#define gfp_kmemleak_mask(gfp) (((gfp) & (GFP_KERNEL | GFP_ATOMIC)) | \
+#define gfp_kmemleak_mask(gfp) (((gfp) & (GFP_KERNEL | GFP_ATOMIC | \
+ __GFP_NOACCOUNT)) | \
__GFP_NORETRY | __GFP_NOMEMALLOC | \
__GFP_NOWARN)
* The check (unnecessarily) ignores LRU pages being isolated and
* walked by the page reclaim code, however that's not a big loss.
*/
- if (!PageHuge(p) && !PageTransTail(p)) {
- if (!PageLRU(p))
- shake_page(p, 0);
- if (!PageLRU(p)) {
+ if (!PageHuge(p)) {
+ if (!PageLRU(hpage))
+ shake_page(hpage, 0);
+ if (!PageLRU(hpage)) {
/*
* shake_page could have turned it free.
*/
} else if (ret == 0) { /* for free pages */
if (PageHuge(page)) {
set_page_hwpoison_huge_page(hpage);
- dequeue_hwpoisoned_huge_page(hpage);
- atomic_long_add(1 << compound_order(hpage),
+ if (!dequeue_hwpoisoned_huge_page(hpage))
+ atomic_long_add(1 << compound_order(hpage),
&num_poisoned_pages);
} else {
- SetPageHWPoison(page);
- atomic_long_inc(&num_poisoned_pages);
+ if (!TestSetPageHWPoison(page))
+ atomic_long_inc(&num_poisoned_pages);
}
}
unset_migratetype_isolate(page, MIGRATE_MOVABLE);
if (numabalancing_override)
set_numabalancing_state(numabalancing_override == 1);
- if (nr_node_ids > 1 && !numabalancing_override) {
+ if (num_online_nodes() > 1 && !numabalancing_override) {
pr_info("%s automatic NUMA balancing. "
"Configure with numa_balancing= or the "
"kernel.numa_balancing sysctl",
long x;
x = div64_s64(((s64)setpoint - (s64)dirty) << RATELIMIT_CALC_SHIFT,
- limit - setpoint + 1);
+ (limit - setpoint) | 1);
pos_ratio = x;
pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT;
pos_ratio = pos_ratio * x >> RATELIMIT_CALC_SHIFT;
* scale global setpoint to bdi's:
* bdi_setpoint = setpoint * bdi_thresh / thresh
*/
- x = div_u64((u64)bdi_thresh << 16, thresh + 1);
+ x = div_u64((u64)bdi_thresh << 16, thresh | 1);
bdi_setpoint = setpoint * (u64)x >> 16;
/*
* Use span=(8*write_bw) in single bdi case as indicated by
if (bdi_dirty < x_intercept - span / 4) {
pos_ratio = div64_u64(pos_ratio * (x_intercept - bdi_dirty),
- x_intercept - bdi_setpoint + 1);
+ (x_intercept - bdi_setpoint) | 1);
} else
pos_ratio /= 4;
buddy_idx = __find_buddy_index(page_idx, order);
buddy = page + (buddy_idx - page_idx);
- if (!is_migrate_isolate_page(buddy)) {
+ if (pfn_valid_within(page_to_pfn(buddy)) &&
+ !is_migrate_isolate_page(buddy)) {
__isolate_free_page(page, order);
kernel_map_pages(page, (1 << order), 1);
set_page_refcounted(page);
{
BT_DBG("%s %p", hdev->name, hdev);
- if (!hci_dev_test_flag(hdev, HCI_UNREGISTER)) {
+ if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) &&
+ test_bit(HCI_UP, &hdev->flags)) {
/* Execute vendor specific shutdown routine */
if (hdev->shutdown)
hdev->shutdown(hdev);
if (__netdev_find_adj(upper_dev, dev, &upper_dev->all_adj_list.upper))
return -EBUSY;
- if (__netdev_find_adj(dev, upper_dev, &dev->all_adj_list.upper))
+ if (__netdev_find_adj(dev, upper_dev, &dev->adj_list.upper))
return -EEXIST;
if (master && netdev_master_upper_dev_get(dev))
}
err = rtnl_net_fill(msg, NETLINK_CB(skb).portid, nlh->nlmsg_seq, 0,
- RTM_GETNSID, net, peer, -1);
+ RTM_NEWNSID, net, peer, -1);
if (err < 0)
goto err_out;
return;
sock_hold(sk);
- sock_net_set(sk, get_net(&init_net));
sock_release(sk->sk_socket);
+ sock_net_set(sk, get_net(&init_net));
sock_put(sk);
}
EXPORT_SYMBOL(sk_release_kernel);
obj-y += 6lowpan/
ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \
- header_ops.o sysfs.o nl802154.o
+ header_ops.o sysfs.o nl802154.o trace.o
ieee802154_socket-y := socket.o
+CFLAGS_trace.o := -I$(src)
+
ccflags-y += -D__CHECK_ENDIAN__
int rc = -ENOBUFS;
struct net_device *dev;
int type = __IEEE802154_DEV_INVALID;
+ unsigned char name_assign_type;
pr_debug("%s\n", __func__);
if (devname[nla_len(info->attrs[IEEE802154_ATTR_DEV_NAME]) - 1]
!= '\0')
return -EINVAL; /* phy name should be null-terminated */
+ name_assign_type = NET_NAME_USER;
} else {
devname = "wpan%d";
+ name_assign_type = NET_NAME_ENUM;
}
if (strlen(devname) >= IFNAMSIZ)
}
dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname,
- type);
+ name_assign_type, type);
if (IS_ERR(dev)) {
rc = PTR_ERR(dev);
goto nla_put_failure;
return rdev_add_virtual_intf(rdev,
nla_data(info->attrs[NL802154_ATTR_IFNAME]),
- type, extended_addr);
+ NET_NAME_USER, type, extended_addr);
}
static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info)
#include <net/cfg802154.h>
#include "core.h"
+#include "trace.h"
static inline struct net_device *
rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev,
- const char *name, int type)
+ const char *name,
+ unsigned char name_assign_type,
+ int type)
{
return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name,
- type);
+ name_assign_type, type);
}
static inline void
static inline int
rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name,
+ unsigned char name_assign_type,
enum nl802154_iftype type, __le64 extended_addr)
{
- return rdev->ops->add_virtual_intf(&rdev->wpan_phy, name, type,
+ int ret;
+
+ trace_802154_rdev_add_virtual_intf(&rdev->wpan_phy, name, type,
extended_addr);
+ ret = rdev->ops->add_virtual_intf(&rdev->wpan_phy, name,
+ name_assign_type, type,
+ extended_addr);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
static inline int
rdev_del_virtual_intf(struct cfg802154_registered_device *rdev,
struct wpan_dev *wpan_dev)
{
- return rdev->ops->del_virtual_intf(&rdev->wpan_phy, wpan_dev);
+ int ret;
+
+ trace_802154_rdev_del_virtual_intf(&rdev->wpan_phy, wpan_dev);
+ ret = rdev->ops->del_virtual_intf(&rdev->wpan_phy, wpan_dev);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
static inline int
rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel)
{
- return rdev->ops->set_channel(&rdev->wpan_phy, page, channel);
+ int ret;
+
+ trace_802154_rdev_set_channel(&rdev->wpan_phy, page, channel);
+ ret = rdev->ops->set_channel(&rdev->wpan_phy, page, channel);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
static inline int
rdev_set_cca_mode(struct cfg802154_registered_device *rdev,
const struct wpan_phy_cca *cca)
{
- return rdev->ops->set_cca_mode(&rdev->wpan_phy, cca);
+ int ret;
+
+ trace_802154_rdev_set_cca_mode(&rdev->wpan_phy, cca);
+ ret = rdev->ops->set_cca_mode(&rdev->wpan_phy, cca);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
static inline int
rdev_set_pan_id(struct cfg802154_registered_device *rdev,
struct wpan_dev *wpan_dev, __le16 pan_id)
{
- return rdev->ops->set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id);
+ int ret;
+
+ trace_802154_rdev_set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id);
+ ret = rdev->ops->set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
static inline int
rdev_set_short_addr(struct cfg802154_registered_device *rdev,
struct wpan_dev *wpan_dev, __le16 short_addr)
{
- return rdev->ops->set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr);
+ int ret;
+
+ trace_802154_rdev_set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr);
+ ret = rdev->ops->set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
static inline int
rdev_set_backoff_exponent(struct cfg802154_registered_device *rdev,
struct wpan_dev *wpan_dev, u8 min_be, u8 max_be)
{
- return rdev->ops->set_backoff_exponent(&rdev->wpan_phy, wpan_dev,
+ int ret;
+
+ trace_802154_rdev_set_backoff_exponent(&rdev->wpan_phy, wpan_dev,
min_be, max_be);
+ ret = rdev->ops->set_backoff_exponent(&rdev->wpan_phy, wpan_dev,
+ min_be, max_be);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
static inline int
rdev_set_max_csma_backoffs(struct cfg802154_registered_device *rdev,
struct wpan_dev *wpan_dev, u8 max_csma_backoffs)
{
- return rdev->ops->set_max_csma_backoffs(&rdev->wpan_phy, wpan_dev,
- max_csma_backoffs);
+ int ret;
+
+ trace_802154_rdev_set_csma_backoffs(&rdev->wpan_phy, wpan_dev,
+ max_csma_backoffs);
+ ret = rdev->ops->set_max_csma_backoffs(&rdev->wpan_phy, wpan_dev,
+ max_csma_backoffs);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
static inline int
rdev_set_max_frame_retries(struct cfg802154_registered_device *rdev,
struct wpan_dev *wpan_dev, s8 max_frame_retries)
{
- return rdev->ops->set_max_frame_retries(&rdev->wpan_phy, wpan_dev,
+ int ret;
+
+ trace_802154_rdev_set_max_frame_retries(&rdev->wpan_phy, wpan_dev,
max_frame_retries);
+ ret = rdev->ops->set_max_frame_retries(&rdev->wpan_phy, wpan_dev,
+ max_frame_retries);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
static inline int
rdev_set_lbt_mode(struct cfg802154_registered_device *rdev,
struct wpan_dev *wpan_dev, bool mode)
{
- return rdev->ops->set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode);
+ int ret;
+
+ trace_802154_rdev_set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode);
+ ret = rdev->ops->set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode);
+ trace_802154_rdev_return_int(&rdev->wpan_phy, ret);
+ return ret;
}
#endif /* __CFG802154_RDEV_OPS */
--- /dev/null
+#include <linux/module.h>
+
+#ifndef __CHECKER__
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#endif
--- /dev/null
+/* Based on net/wireless/tracing.h */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM cfg802154
+
+#if !defined(__RDEV_CFG802154_OPS_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define __RDEV_CFG802154_OPS_TRACE
+
+#include <linux/tracepoint.h>
+
+#include <net/cfg802154.h>
+
+#define MAXNAME 32
+#define WPAN_PHY_ENTRY __array(char, wpan_phy_name, MAXNAME)
+#define WPAN_PHY_ASSIGN strlcpy(__entry->wpan_phy_name, \
+ wpan_phy_name(wpan_phy), \
+ MAXNAME)
+#define WPAN_PHY_PR_FMT "%s"
+#define WPAN_PHY_PR_ARG __entry->wpan_phy_name
+
+#define WPAN_DEV_ENTRY __field(u32, identifier)
+#define WPAN_DEV_ASSIGN (__entry->identifier) = (!IS_ERR_OR_NULL(wpan_dev) \
+ ? wpan_dev->identifier : 0)
+#define WPAN_DEV_PR_FMT "wpan_dev(%u)"
+#define WPAN_DEV_PR_ARG (__entry->identifier)
+
+#define WPAN_CCA_ENTRY __field(enum nl802154_cca_modes, cca_mode) \
+ __field(enum nl802154_cca_opts, cca_opt)
+#define WPAN_CCA_ASSIGN \
+ do { \
+ (__entry->cca_mode) = cca->mode; \
+ (__entry->cca_opt) = cca->opt; \
+ } while (0)
+#define WPAN_CCA_PR_FMT "cca_mode: %d, cca_opt: %d"
+#define WPAN_CCA_PR_ARG __entry->cca_mode, __entry->cca_opt
+
+#define BOOL_TO_STR(bo) (bo) ? "true" : "false"
+
+/*************************************************************
+ * rdev->ops traces *
+ *************************************************************/
+
+TRACE_EVENT(802154_rdev_add_virtual_intf,
+ TP_PROTO(struct wpan_phy *wpan_phy, char *name,
+ enum nl802154_iftype type, __le64 extended_addr),
+ TP_ARGS(wpan_phy, name, type, extended_addr),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ __string(vir_intf_name, name ? name : "<noname>")
+ __field(enum nl802154_iftype, type)
+ __field(__le64, extended_addr)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ __assign_str(vir_intf_name, name ? name : "<noname>");
+ __entry->type = type;
+ __entry->extended_addr = extended_addr;
+ ),
+ TP_printk(WPAN_PHY_PR_FMT ", virtual intf name: %s, type: %d, ea %llx",
+ WPAN_PHY_PR_ARG, __get_str(vir_intf_name), __entry->type,
+ __le64_to_cpu(__entry->extended_addr))
+);
+
+TRACE_EVENT(802154_rdev_del_virtual_intf,
+ TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev),
+ TP_ARGS(wpan_phy, wpan_dev),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ WPAN_DEV_ENTRY
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ WPAN_DEV_ASSIGN;
+ ),
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT, WPAN_PHY_PR_ARG,
+ WPAN_DEV_PR_ARG)
+);
+
+TRACE_EVENT(802154_rdev_set_channel,
+ TP_PROTO(struct wpan_phy *wpan_phy, u8 page, u8 channel),
+ TP_ARGS(wpan_phy, page, channel),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ __field(u8, page)
+ __field(u8, channel)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ __entry->page = page;
+ __entry->channel = channel;
+ ),
+ TP_printk(WPAN_PHY_PR_FMT ", page: %d, channel: %d", WPAN_PHY_PR_ARG,
+ __entry->page, __entry->channel)
+);
+
+TRACE_EVENT(802154_rdev_set_cca_mode,
+ TP_PROTO(struct wpan_phy *wpan_phy, const struct wpan_phy_cca *cca),
+ TP_ARGS(wpan_phy, cca),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ WPAN_CCA_ENTRY
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ WPAN_CCA_ASSIGN;
+ ),
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_CCA_PR_FMT, WPAN_PHY_PR_ARG,
+ WPAN_CCA_PR_ARG)
+);
+
+DECLARE_EVENT_CLASS(802154_le16_template,
+ TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
+ __le16 le16arg),
+ TP_ARGS(wpan_phy, wpan_dev, le16arg),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ WPAN_DEV_ENTRY
+ __field(__le16, le16arg)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ WPAN_DEV_ASSIGN;
+ __entry->le16arg = le16arg;
+ ),
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT ", pan id: 0x%04x",
+ WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG,
+ __le16_to_cpu(__entry->le16arg))
+);
+
+DEFINE_EVENT(802154_le16_template, 802154_rdev_set_pan_id,
+ TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
+ __le16 le16arg),
+ TP_ARGS(wpan_phy, wpan_dev, le16arg)
+);
+
+DEFINE_EVENT_PRINT(802154_le16_template, 802154_rdev_set_short_addr,
+ TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
+ __le16 le16arg),
+ TP_ARGS(wpan_phy, wpan_dev, le16arg),
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT ", sa: 0x%04x",
+ WPAN_PHY_PR_ARG, WPAN_DEV_PR_ARG,
+ __le16_to_cpu(__entry->le16arg))
+);
+
+TRACE_EVENT(802154_rdev_set_backoff_exponent,
+ TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
+ u8 min_be, u8 max_be),
+ TP_ARGS(wpan_phy, wpan_dev, min_be, max_be),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ WPAN_DEV_ENTRY
+ __field(u8, min_be)
+ __field(u8, max_be)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ WPAN_DEV_ASSIGN;
+ __entry->min_be = min_be;
+ __entry->max_be = max_be;
+ ),
+
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT
+ ", min be: %d, max_be: %d", WPAN_PHY_PR_ARG,
+ WPAN_DEV_PR_ARG, __entry->min_be, __entry->max_be)
+);
+
+TRACE_EVENT(802154_rdev_set_csma_backoffs,
+ TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
+ u8 max_csma_backoffs),
+ TP_ARGS(wpan_phy, wpan_dev, max_csma_backoffs),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ WPAN_DEV_ENTRY
+ __field(u8, max_csma_backoffs)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ WPAN_DEV_ASSIGN;
+ __entry->max_csma_backoffs = max_csma_backoffs;
+ ),
+
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT
+ ", max csma backoffs: %d", WPAN_PHY_PR_ARG,
+ WPAN_DEV_PR_ARG, __entry->max_csma_backoffs)
+);
+
+TRACE_EVENT(802154_rdev_set_max_frame_retries,
+ TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
+ s8 max_frame_retries),
+ TP_ARGS(wpan_phy, wpan_dev, max_frame_retries),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ WPAN_DEV_ENTRY
+ __field(s8, max_frame_retries)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ WPAN_DEV_ASSIGN;
+ __entry->max_frame_retries = max_frame_retries;
+ ),
+
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT
+ ", max frame retries: %d", WPAN_PHY_PR_ARG,
+ WPAN_DEV_PR_ARG, __entry->max_frame_retries)
+);
+
+TRACE_EVENT(802154_rdev_set_lbt_mode,
+ TP_PROTO(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
+ bool mode),
+ TP_ARGS(wpan_phy, wpan_dev, mode),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ WPAN_DEV_ENTRY
+ __field(bool, mode)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ WPAN_DEV_ASSIGN;
+ __entry->mode = mode;
+ ),
+ TP_printk(WPAN_PHY_PR_FMT ", " WPAN_DEV_PR_FMT
+ ", lbt mode: %s", WPAN_PHY_PR_ARG,
+ WPAN_DEV_PR_ARG, BOOL_TO_STR(__entry->mode))
+);
+
+TRACE_EVENT(802154_rdev_return_int,
+ TP_PROTO(struct wpan_phy *wpan_phy, int ret),
+ TP_ARGS(wpan_phy, ret),
+ TP_STRUCT__entry(
+ WPAN_PHY_ENTRY
+ __field(int, ret)
+ ),
+ TP_fast_assign(
+ WPAN_PHY_ASSIGN;
+ __entry->ret = ret;
+ ),
+ TP_printk(WPAN_PHY_PR_FMT ", returned: %d", WPAN_PHY_PR_ARG,
+ __entry->ret)
+);
+
+#endif /* !__RDEV_CFG802154_OPS_TRACE || TRACE_HEADER_MULTI_READ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+#include <trace/define_trace.h>
handler->idiag_get_info(sk, r, info);
if (sk->sk_state < TCP_TIME_WAIT) {
- int err = 0;
+ union tcp_cc_info info;
+ size_t sz = 0;
+ int attr;
rcu_read_lock();
ca_ops = READ_ONCE(icsk->icsk_ca_ops);
if (ca_ops && ca_ops->get_info)
- err = ca_ops->get_info(sk, ext, skb);
+ sz = ca_ops->get_info(sk, ext, &attr, &info);
rcu_read_unlock();
- if (err < 0)
+ if (sz && nla_put(skb, attr, sz, &info) < 0)
goto errout;
}
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/poll.h>
+#include <linux/inet_diag.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/skbuff.h>
#endif
/* Return information about state of tcp endpoint in API format. */
-void tcp_get_info(const struct sock *sk, struct tcp_info *info)
+void tcp_get_info(struct sock *sk, struct tcp_info *info)
{
const struct tcp_sock *tp = tcp_sk(sk);
const struct inet_connection_sock *icsk = inet_csk(sk);
rate = READ_ONCE(sk->sk_max_pacing_rate);
info->tcpi_max_pacing_rate = rate != ~0U ? rate : ~0ULL;
+
+ spin_lock_bh(&sk->sk_lock.slock);
+ info->tcpi_bytes_acked = tp->bytes_acked;
+ info->tcpi_bytes_received = tp->bytes_received;
+ spin_unlock_bh(&sk->sk_lock.slock);
}
EXPORT_SYMBOL_GPL(tcp_get_info);
return -EFAULT;
return 0;
}
+ case TCP_CC_INFO: {
+ const struct tcp_congestion_ops *ca_ops;
+ union tcp_cc_info info;
+ size_t sz = 0;
+ int attr;
+
+ if (get_user(len, optlen))
+ return -EFAULT;
+
+ ca_ops = icsk->icsk_ca_ops;
+ if (ca_ops && ca_ops->get_info)
+ sz = ca_ops->get_info(sk, ~0U, &attr, &info);
+
+ len = min_t(unsigned int, len, sz);
+ if (put_user(len, optlen))
+ return -EFAULT;
+ if (copy_to_user(optval, &info, len))
+ return -EFAULT;
+ return 0;
+ }
case TCP_QUICKACK:
val = !icsk->icsk_ack.pingpong;
break;
}
}
-static int dctcp_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
+static size_t dctcp_get_info(struct sock *sk, u32 ext, int *attr,
+ union tcp_cc_info *info)
{
const struct dctcp *ca = inet_csk_ca(sk);
*/
if (ext & (1 << (INET_DIAG_DCTCPINFO - 1)) ||
ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
- struct tcp_dctcp_info info;
-
- memset(&info, 0, sizeof(info));
+ memset(info, 0, sizeof(struct tcp_dctcp_info));
if (inet_csk(sk)->icsk_ca_ops != &dctcp_reno) {
- info.dctcp_enabled = 1;
- info.dctcp_ce_state = (u16) ca->ce_state;
- info.dctcp_alpha = ca->dctcp_alpha;
- info.dctcp_ab_ecn = ca->acked_bytes_ecn;
- info.dctcp_ab_tot = ca->acked_bytes_total;
+ info->dctcp.dctcp_enabled = 1;
+ info->dctcp.dctcp_ce_state = (u16) ca->ce_state;
+ info->dctcp.dctcp_alpha = ca->dctcp_alpha;
+ info->dctcp.dctcp_ab_ecn = ca->acked_bytes_ecn;
+ info->dctcp.dctcp_ab_tot = ca->acked_bytes_total;
}
- return nla_put(skb, INET_DIAG_DCTCPINFO, sizeof(info), &info);
+ *attr = INET_DIAG_DCTCPINFO;
+ return sizeof(*info);
}
return 0;
}
skb_set_owner_r(skb2, child);
__skb_queue_tail(&child->sk_receive_queue, skb2);
tp->syn_data_acked = 1;
+ tp->bytes_received = end_seq - TCP_SKB_CB(skb)->seq - 1;
} else {
end_seq = TCP_SKB_CB(skb)->seq + 1;
}
}
/* Extract info for Tcp socket info provided via netlink. */
-static int tcp_illinois_info(struct sock *sk, u32 ext, struct sk_buff *skb)
+static size_t tcp_illinois_info(struct sock *sk, u32 ext, int *attr,
+ union tcp_cc_info *info)
{
const struct illinois *ca = inet_csk_ca(sk);
if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
- struct tcpvegas_info info = {
- .tcpv_enabled = 1,
- .tcpv_rttcnt = ca->cnt_rtt,
- .tcpv_minrtt = ca->base_rtt,
- };
+ info->vegas.tcpv_enabled = 1;
+ info->vegas.tcpv_rttcnt = ca->cnt_rtt;
+ info->vegas.tcpv_minrtt = ca->base_rtt;
+ info->vegas.tcpv_rtt = 0;
- if (info.tcpv_rttcnt > 0) {
+ if (info->vegas.tcpv_rttcnt > 0) {
u64 t = ca->sum_rtt;
- do_div(t, info.tcpv_rttcnt);
- info.tcpv_rtt = t;
+ do_div(t, info->vegas.tcpv_rttcnt);
+ info->vegas.tcpv_rtt = t;
}
- return nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
+ *attr = INET_DIAG_VEGASINFO;
+ return sizeof(struct tcpvegas_info);
}
return 0;
}
for (j = 0; j < used_sacks; j++)
tp->recv_sack_cache[i++] = sp[j];
- tcp_mark_lost_retrans(sk);
-
- tcp_verify_left_out(tp);
-
if ((state.reord < tp->fackets_out) &&
((inet_csk(sk)->icsk_ca_state != TCP_CA_Loss) || tp->undo_marker))
tcp_update_reordering(sk, tp->fackets_out - state.reord, 0);
+ tcp_mark_lost_retrans(sk);
+ tcp_verify_left_out(tp);
out:
#if FASTRETRANS_DEBUG > 0
(ack_seq == tp->snd_wl1 && nwin > tp->snd_wnd);
}
+/* If we update tp->snd_una, also update tp->bytes_acked */
+static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack)
+{
+ u32 delta = ack - tp->snd_una;
+
+ tp->bytes_acked += delta;
+ tp->snd_una = ack;
+}
+
+/* If we update tp->rcv_nxt, also update tp->bytes_received */
+static void tcp_rcv_nxt_update(struct tcp_sock *tp, u32 seq)
+{
+ u32 delta = seq - tp->rcv_nxt;
+
+ tp->bytes_received += delta;
+ tp->rcv_nxt = seq;
+}
+
/* Update our send window.
*
* Window update algorithm, described in RFC793/RFC1122 (used in linux-2.2
}
}
- tp->snd_una = ack;
+ tcp_snd_una_update(tp, ack);
return flag;
}
* Note, we use the fact that SND.UNA>=SND.WL2.
*/
tcp_update_wl(tp, ack_seq);
- tp->snd_una = ack;
+ tcp_snd_una_update(tp, ack);
flag |= FLAG_WIN_UPDATE;
tcp_in_ack_event(sk, CA_ACK_WIN_UPDATE);
tail = skb_peek_tail(&sk->sk_receive_queue);
eaten = tail && tcp_try_coalesce(sk, tail, skb, &fragstolen);
- tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
if (!eaten)
__skb_queue_tail(&sk->sk_receive_queue, skb);
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
__skb_pull(skb, hdrlen);
eaten = (tail &&
tcp_try_coalesce(sk, tail, skb, fragstolen)) ? 1 : 0;
- tcp_sk(sk)->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ tcp_rcv_nxt_update(tcp_sk(sk), TCP_SKB_CB(skb)->end_seq);
if (!eaten) {
__skb_queue_tail(&sk->sk_receive_queue, skb);
skb_set_owner_r(skb, sk);
eaten = tcp_queue_rcv(sk, skb, 0, &fragstolen);
}
- tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
if (skb->len)
tcp_event_data_recv(sk, skb);
if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)
tcp_rcv_rtt_measure_ts(sk, skb);
__skb_pull(skb, tcp_header_len);
- tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ tcp_rcv_nxt_update(tp, TCP_SKB_CB(skb)->end_seq);
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITSTOUSER);
eaten = 1;
}
}
/* Extract info for Tcp socket info provided via netlink. */
-int tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb)
+size_t tcp_vegas_get_info(struct sock *sk, u32 ext, int *attr,
+ union tcp_cc_info *info)
{
const struct vegas *ca = inet_csk_ca(sk);
+
if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
- struct tcpvegas_info info = {
- .tcpv_enabled = ca->doing_vegas_now,
- .tcpv_rttcnt = ca->cntRTT,
- .tcpv_rtt = ca->baseRTT,
- .tcpv_minrtt = ca->minRTT,
- };
-
- return nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
+ info->vegas.tcpv_enabled = ca->doing_vegas_now,
+ info->vegas.tcpv_rttcnt = ca->cntRTT,
+ info->vegas.tcpv_rtt = ca->baseRTT,
+ info->vegas.tcpv_minrtt = ca->minRTT,
+
+ *attr = INET_DIAG_VEGASINFO;
+ return sizeof(struct tcpvegas_info);
}
return 0;
}
void tcp_vegas_state(struct sock *sk, u8 ca_state);
void tcp_vegas_pkts_acked(struct sock *sk, u32 cnt, s32 rtt_us);
void tcp_vegas_cwnd_event(struct sock *sk, enum tcp_ca_event event);
-int tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb);
+size_t tcp_vegas_get_info(struct sock *sk, u32 ext, int *attr,
+ union tcp_cc_info *info);
#endif /* __TCP_VEGAS_H */
}
/* Extract info for Tcp socket info provided via netlink. */
-static int tcp_westwood_info(struct sock *sk, u32 ext, struct sk_buff *skb)
+static size_t tcp_westwood_info(struct sock *sk, u32 ext, int *attr,
+ union tcp_cc_info *info)
{
const struct westwood *ca = inet_csk_ca(sk);
if (ext & (1 << (INET_DIAG_VEGASINFO - 1))) {
- struct tcpvegas_info info = {
- .tcpv_enabled = 1,
- .tcpv_rtt = jiffies_to_usecs(ca->rtt),
- .tcpv_minrtt = jiffies_to_usecs(ca->rtt_min),
- };
+ info->vegas.tcpv_enabled = 1;
+ info->vegas.tcpv_rttcnt = 0;
+ info->vegas.tcpv_rtt = jiffies_to_usecs(ca->rtt),
+ info->vegas.tcpv_minrtt = jiffies_to_usecs(ca->rtt_min),
- return nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);
+ *attr = INET_DIAG_VEGASINFO;
+ return sizeof(struct tcpvegas_info);
}
return 0;
}
#endif
int err;
- if (!*dst)
- *dst = ip6_route_output(net, sk, fl6);
-
- err = (*dst)->error;
- if (err)
- goto out_err_release;
+ /* The correct way to handle this would be to do
+ * ip6_route_get_saddr, and then ip6_route_output; however,
+ * the route-specific preferred source forces the
+ * ip6_route_output call _before_ ip6_route_get_saddr.
+ *
+ * In source specific routing (no src=any default route),
+ * ip6_route_output will fail given src=any saddr, though, so
+ * that's why we try it again later.
+ */
+ if (ipv6_addr_any(&fl6->saddr) && (!*dst || !(*dst)->error)) {
+ struct rt6_info *rt;
+ bool had_dst = *dst != NULL;
- if (ipv6_addr_any(&fl6->saddr)) {
- struct rt6_info *rt = (struct rt6_info *) *dst;
+ if (!had_dst)
+ *dst = ip6_route_output(net, sk, fl6);
+ rt = (*dst)->error ? NULL : (struct rt6_info *)*dst;
err = ip6_route_get_saddr(net, rt, &fl6->daddr,
sk ? inet6_sk(sk)->srcprefs : 0,
&fl6->saddr);
if (err)
goto out_err_release;
+
+ /* If we had an erroneous initial result, pretend it
+ * never existed and let the SA-enabled version take
+ * over.
+ */
+ if (!had_dst && (*dst)->error) {
+ dst_release(*dst);
+ *dst = NULL;
+ }
}
+ if (!*dst)
+ *dst = ip6_route_output(net, sk, fl6);
+
+ err = (*dst)->error;
+ if (err)
+ goto out_err_release;
+
#ifdef CONFIG_IPV6_OPTIMISTIC_DAD
/*
* Here if the dst entry we've looked up
unsigned int prefs,
struct in6_addr *saddr)
{
- struct inet6_dev *idev = ip6_dst_idev((struct dst_entry *)rt);
+ struct inet6_dev *idev =
+ rt ? ip6_dst_idev((struct dst_entry *)rt) : NULL;
int err = 0;
- if (rt->rt6i_prefsrc.plen)
+ if (rt && rt->rt6i_prefsrc.plen)
*saddr = rt->rt6i_prefsrc.addr;
else
err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL,
* (because if we remove a STA after ops->remove_interface()
* the driver will have removed the vif info already!)
*
- * This is relevant only in WDS mode, in all other modes we've
- * already removed all stations when disconnecting or similar,
- * so warn otherwise.
+ * In WDS mode a station must exist here and be flushed, for
+ * AP_VLANs stations may exist since there's nothing else that
+ * would have removed them, but in other modes there shouldn't
+ * be any stations.
*/
flushed = sta_info_flush(sdata);
- WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
- (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));
+ WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+ ((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
+ (sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1)));
/* don't count this interface for promisc/allmulti while it is down */
if (sdata->flags & IEEE80211_SDATA_ALLMULTI)
static const struct rhashtable_params sta_rht_params = {
.nelem_hint = 3, /* start small */
+ .automatic_shrinking = true,
.head_offset = offsetof(struct sta_info, hash_node),
.key_offset = offsetof(struct sta_info, sta.addr),
.key_len = ETH_ALEN,
const u8 *addr)
{
struct ieee80211_local *local = sdata->local;
+ struct sta_info *sta;
+ struct rhash_head *tmp;
+ const struct bucket_table *tbl;
+
+ rcu_read_lock();
+ tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
- return rhashtable_lookup_fast(&local->sta_hash, addr, sta_rht_params);
+ for_each_sta_info(local, tbl, addr, sta, tmp) {
+ if (sta->sdata == sdata) {
+ rcu_read_unlock();
+ /* this is safe as the caller must already hold
+ * another rcu read section or the mutex
+ */
+ return sta;
+ }
+ }
+ rcu_read_unlock();
+ return NULL;
}
/*
static struct net_device *
ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy,
- const char *name, int type)
+ const char *name,
+ unsigned char name_assign_type, int type)
{
struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
struct net_device *dev;
rtnl_lock();
- dev = ieee802154_if_add(local, name, type,
+ dev = ieee802154_if_add(local, name, name_assign_type, type,
cpu_to_le64(0x0000000000000000ULL));
rtnl_unlock();
static int
ieee802154_add_iface(struct wpan_phy *phy, const char *name,
+ unsigned char name_assign_type,
enum nl802154_iftype type, __le64 extended_addr)
{
struct ieee802154_local *local = wpan_phy_priv(phy);
struct net_device *err;
- err = ieee802154_if_add(local, name, type, extended_addr);
+ err = ieee802154_if_add(local, name, name_assign_type, type,
+ extended_addr);
return PTR_ERR_OR_ZERO(err);
}
void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata);
struct net_device *
ieee802154_if_add(struct ieee802154_local *local, const char *name,
- enum nl802154_iftype type, __le64 extended_addr);
+ unsigned char name_assign_type, enum nl802154_iftype type,
+ __le64 extended_addr);
void ieee802154_remove_interfaces(struct ieee802154_local *local);
#endif /* __IEEE802154_I_H */
struct net_device *
ieee802154_if_add(struct ieee802154_local *local, const char *name,
- enum nl802154_iftype type, __le64 extended_addr)
+ unsigned char name_assign_type, enum nl802154_iftype type,
+ __le64 extended_addr)
{
struct net_device *ndev = NULL;
struct ieee802154_sub_if_data *sdata = NULL;
ASSERT_RTNL();
ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name,
- NET_NAME_UNKNOWN, ieee802154_if_setup);
+ name_assign_type, ieee802154_if_setup);
if (!ndev)
return ERR_PTR(-ENOMEM);
for (i = 0; i < ARRAY_SIZE(key->tfm); i++) {
key->tfm[i] = crypto_alloc_aead("ccm(aes)", 0,
CRYPTO_ALG_ASYNC);
- if (!key->tfm[i])
+ if (IS_ERR(key->tfm[i]))
goto err_tfm;
if (crypto_aead_setkey(key->tfm[i], template->key,
IEEE802154_LLSEC_KEY_SIZE))
}
key->tfm0 = crypto_alloc_blkcipher("ctr(aes)", 0, CRYPTO_ALG_ASYNC);
- if (!key->tfm0)
+ if (IS_ERR(key->tfm0))
goto err_tfm;
if (crypto_blkcipher_setkey(key->tfm0, template->key,
rtnl_lock();
- dev = ieee802154_if_add(local, "wpan%d", NL802154_IFTYPE_NODE,
+ dev = ieee802154_if_add(local, "wpan%d", NET_NAME_ENUM,
+ NL802154_IFTYPE_NODE,
cpu_to_le64(0x0000000000000000ULL));
if (IS_ERR(dev)) {
rtnl_unlock();
rc = PTR_ERR(dev);
- goto out_wq;
+ goto out_phy;
}
rtnl_unlock();
return 0;
+out_phy:
+ wpan_phy_unregister(local->phy);
out_wq:
destroy_workqueue(local->workqueue);
out:
return -EINVAL;
switch (dec.label) {
- case LABEL_IMPLICIT_NULL:
+ case MPLS_LABEL_IMPLNULL:
/* RFC3032: This is a label that an LSR may
* assign and distribute, but which never
* actually appears in the encapsulation.
}
/* In case the predefined labels need to be populated */
- if (limit > LABEL_IPV4_EXPLICIT_NULL) {
+ if (limit > MPLS_LABEL_IPV4NULL) {
struct net_device *lo = net->loopback_dev;
rt0 = mpls_rt_alloc(lo->addr_len);
if (!rt0)
rt0->rt_via_table = NEIGH_LINK_TABLE;
memcpy(rt0->rt_via, lo->dev_addr, lo->addr_len);
}
- if (limit > LABEL_IPV6_EXPLICIT_NULL) {
+ if (limit > MPLS_LABEL_IPV6NULL) {
struct net_device *lo = net->loopback_dev;
rt2 = mpls_rt_alloc(lo->addr_len);
if (!rt2)
memcpy(labels, old, cp_size);
/* If needed set the predefined labels */
- if ((old_limit <= LABEL_IPV6_EXPLICIT_NULL) &&
- (limit > LABEL_IPV6_EXPLICIT_NULL)) {
- RCU_INIT_POINTER(labels[LABEL_IPV6_EXPLICIT_NULL], rt2);
+ if ((old_limit <= MPLS_LABEL_IPV6NULL) &&
+ (limit > MPLS_LABEL_IPV6NULL)) {
+ RCU_INIT_POINTER(labels[MPLS_LABEL_IPV6NULL], rt2);
rt2 = NULL;
}
- if ((old_limit <= LABEL_IPV4_EXPLICIT_NULL) &&
- (limit > LABEL_IPV4_EXPLICIT_NULL)) {
- RCU_INIT_POINTER(labels[LABEL_IPV4_EXPLICIT_NULL], rt0);
+ if ((old_limit <= MPLS_LABEL_IPV4NULL) &&
+ (limit > MPLS_LABEL_IPV4NULL)) {
+ RCU_INIT_POINTER(labels[MPLS_LABEL_IPV4NULL], rt0);
rt0 = NULL;
}
#ifndef MPLS_INTERNAL_H
#define MPLS_INTERNAL_H
-#define LABEL_IPV4_EXPLICIT_NULL 0 /* RFC3032 */
-#define LABEL_ROUTER_ALERT_LABEL 1 /* RFC3032 */
-#define LABEL_IPV6_EXPLICIT_NULL 2 /* RFC3032 */
-#define LABEL_IMPLICIT_NULL 3 /* RFC3032 */
-#define LABEL_ENTROPY_INDICATOR 7 /* RFC6790 */
-#define LABEL_GAL 13 /* RFC5586 */
-#define LABEL_OAM_ALERT 14 /* RFC3429 */
-#define LABEL_EXTENSION 15 /* RFC7274 */
-
-
struct mpls_shim_hdr {
__be32 label_stack_entry;
};
.key_len = netlink_compare_arg_len,
.obj_hashfn = netlink_hash,
.obj_cmpfn = netlink_compare,
- .max_size = 65536,
.automatic_shrinking = true,
};
tlen = dev->needed_tailroom;
skb = sock_alloc_send_skb(&po->sk,
hlen + tlen + sizeof(struct sockaddr_ll),
- 0, &err);
+ !need_wait, &err);
- if (unlikely(skb == NULL))
+ if (unlikely(skb == NULL)) {
+ /* we assume the socket was initially writeable ... */
+ if (likely(len_sum > 0))
+ err = len_sum;
goto out_status;
-
+ }
tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto,
addr, hlen);
if (tp_len > dev->mtu + dev->hard_header_len) {
struct rds_transport *loop_trans;
unsigned long flags;
int ret;
+ struct rds_transport *otrans = trans;
+ if (!is_outgoing && otrans->t_type == RDS_TRANS_TCP)
+ goto new_conn;
rcu_read_lock();
conn = rds_conn_lookup(head, laddr, faddr, trans);
if (conn && conn->c_loopback && conn->c_trans != &rds_loop_transport &&
if (conn)
goto out;
+new_conn:
conn = kmem_cache_zalloc(rds_conn_slab, gfp);
if (!conn) {
conn = ERR_PTR(-ENOMEM);
/* Creating normal conn */
struct rds_connection *found;
- found = rds_conn_lookup(head, laddr, faddr, trans);
+ if (!is_outgoing && otrans->t_type == RDS_TRANS_TCP)
+ found = NULL;
+ else
+ found = rds_conn_lookup(head, laddr, faddr, trans);
if (found) {
trans->conn_free(conn->c_transport_data);
kmem_cache_free(rds_conn_slab, conn);
conn = found;
} else {
- hlist_add_head_rcu(&conn->c_hash_node, head);
+ if ((is_outgoing && otrans->t_type == RDS_TRANS_TCP) ||
+ (otrans->t_type != RDS_TRANS_TCP)) {
+ /* Only the active side should be added to
+ * reconnect list for TCP.
+ */
+ hlist_add_head_rcu(&conn->c_hash_node, head);
+ }
rds_cong_add_conn(conn);
rds_conn_count++;
}
/* If the peer gave us the last packet it saw, process this as if
* we had received a regular ACK. */
- if (dp && dp->dp_ack_seq)
- rds_send_drop_acked(conn, be64_to_cpu(dp->dp_ack_seq), NULL);
+ if (dp) {
+ /* dp structure start is not guaranteed to be 8 bytes aligned.
+ * Since dp_ack_seq is 64-bit extended load operations can be
+ * used so go through get_unaligned to avoid unaligned errors.
+ */
+ __be64 dp_ack_seq = get_unaligned(&dp->dp_ack_seq);
+
+ if (dp_ack_seq)
+ rds_send_drop_acked(conn, be64_to_cpu(dp_ack_seq),
+ NULL);
+ }
rds_connect_complete(conn);
}
case TCP_ESTABLISHED:
rds_connect_complete(conn);
break;
+ case TCP_CLOSE_WAIT:
case TCP_CLOSE:
rds_conn_drop(conn);
default:
static DECLARE_WORK(rds_tcp_listen_work, rds_tcp_accept_worker);
static struct socket *rds_tcp_listen_sock;
+static int rds_tcp_keepalive(struct socket *sock)
+{
+ /* values below based on xs_udp_default_timeout */
+ int keepidle = 5; /* send a probe 'keepidle' secs after last data */
+ int keepcnt = 5; /* number of unack'ed probes before declaring dead */
+ int keepalive = 1;
+ int ret = 0;
+
+ ret = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+ (char *)&keepalive, sizeof(keepalive));
+ if (ret < 0)
+ goto bail;
+
+ ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPCNT,
+ (char *)&keepcnt, sizeof(keepcnt));
+ if (ret < 0)
+ goto bail;
+
+ ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE,
+ (char *)&keepidle, sizeof(keepidle));
+ if (ret < 0)
+ goto bail;
+
+ /* KEEPINTVL is the interval between successive probes. We follow
+ * the model in xs_tcp_finish_connecting() and re-use keepidle.
+ */
+ ret = kernel_setsockopt(sock, IPPROTO_TCP, TCP_KEEPINTVL,
+ (char *)&keepidle, sizeof(keepidle));
+bail:
+ return ret;
+}
+
static int rds_tcp_accept_one(struct socket *sock)
{
struct socket *new_sock = NULL;
struct rds_connection *conn;
int ret;
struct inet_sock *inet;
+ struct rds_tcp_connection *rs_tcp;
ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type,
sock->sk->sk_protocol, &new_sock);
if (ret < 0)
goto out;
+ ret = rds_tcp_keepalive(new_sock);
+ if (ret < 0)
+ goto out;
+
rds_tcp_tune(new_sock);
inet = inet_sk(new_sock->sk);
ret = PTR_ERR(conn);
goto out;
}
+ /* An incoming SYN request came in, and TCP just accepted it.
+ * We always create a new conn for listen side of TCP, and do not
+ * add it to the c_hash_list.
+ *
+ * If the client reboots, this conn will need to be cleaned up.
+ * rds_tcp_state_change() will do that cleanup
+ */
+ rs_tcp = (struct rds_tcp_connection *)conn->c_transport_data;
+ WARN_ON(!rs_tcp || rs_tcp->t_sock);
/*
* see the comment above rds_queue_delayed_reconnect()
case RTM_DELTFILTER:
err = tp->ops->delete(tp, fh);
if (err == 0) {
- tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER);
- if (tcf_destroy(tp, false)) {
- struct tcf_proto *next = rtnl_dereference(tp->next);
+ struct tcf_proto *next = rtnl_dereference(tp->next);
+ tfilter_notify(net, skb, n, tp, fh, RTM_DELTFILTER);
+ if (tcf_destroy(tp, false))
RCU_INIT_POINTER(*back, next);
- }
}
goto errout;
case RTM_GETTFILTER:
sch->limit = DEFAULT_CODEL_LIMIT;
- codel_params_init(&q->params);
+ codel_params_init(&q->params, sch);
codel_vars_init(&q->vars);
codel_stats_init(&q->stats);
q->perturbation = prandom_u32();
INIT_LIST_HEAD(&q->new_flows);
INIT_LIST_HEAD(&q->old_flows);
- codel_params_init(&q->cparams);
+ codel_params_init(&q->cparams, sch);
codel_stats_init(&q->cstats);
q->cparams.ecn = true;
break;
}
- if (q->backlog + qdisc_pkt_len(skb) <= q->limit) {
+ if (gred_backlog(t, q, sch) + qdisc_pkt_len(skb) <= q->limit) {
q->backlog += qdisc_pkt_len(skb);
return qdisc_enqueue_tail(skb, sch);
}
opt.limit = q->limit;
opt.DP = q->DP;
- opt.backlog = q->backlog;
+ opt.backlog = gred_backlog(table, q, sch);
opt.prio = q->prio;
opt.qth_min = q->parms.qth_min >> q->parms.Wlog;
opt.qth_max = q->parms.qth_max >> q->parms.Wlog;
{
u32 value_follows;
int err;
+ struct page *scratch;
+
+ scratch = alloc_page(GFP_KERNEL);
+ if (!scratch)
+ return -ENOMEM;
+ xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE);
/* res->status */
err = gssx_dec_status(xdr, &res->status);
if (err)
- return err;
+ goto out_free;
/* res->context_handle */
err = gssx_dec_bool(xdr, &value_follows);
if (err)
- return err;
+ goto out_free;
if (value_follows) {
err = gssx_dec_ctx(xdr, res->context_handle);
if (err)
- return err;
+ goto out_free;
} else {
res->context_handle = NULL;
}
/* res->output_token */
err = gssx_dec_bool(xdr, &value_follows);
if (err)
- return err;
+ goto out_free;
if (value_follows) {
err = gssx_dec_buffer(xdr, res->output_token);
if (err)
- return err;
+ goto out_free;
} else {
res->output_token = NULL;
}
/* res->delegated_cred_handle */
err = gssx_dec_bool(xdr, &value_follows);
if (err)
- return err;
+ goto out_free;
if (value_follows) {
/* we do not support upcall servers sending this data. */
- return -EINVAL;
+ err = -EINVAL;
+ goto out_free;
}
/* res->options */
err = gssx_dec_option_array(xdr, &res->options);
+out_free:
+ __free_page(scratch);
return err;
}
LIBFILE = $(OUTPUT)libapi.a
CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
-CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -D_FORTIFY_SOURCE=2 -fPIC
+CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
RM = rm -f
$(eval $(1) = $(2)))
endef
-# Allow setting CC and AR, or setting CROSS_COMPILE as a prefix.
+# Allow setting CC and AR and LD, or setting CROSS_COMPILE as a prefix.
$(call allow-override,CC,$(CROSS_COMPILE)gcc)
$(call allow-override,AR,$(CROSS_COMPILE)ar)
+$(call allow-override,LD,$(CROSS_COMPILE)ld)
INSTALL = install
#define __init
#define noinline
#define list_add_tail_rcu list_add_tail
+#define list_for_each_entry_rcu list_for_each_entry
+#define barrier()
+#define synchronize_sched()
#ifndef CALLER_ADDR0
#define CALLER_ADDR0 ((unsigned long)__builtin_return_address(0))
} else if (el_size == 4) {
trace_seq_printf(s, "%u", *(uint32_t *)num);
} else if (el_size == 8) {
- trace_seq_printf(s, "%lu", *(uint64_t *)num);
+ trace_seq_printf(s, "%"PRIu64, *(uint64_t *)num);
} else {
trace_seq_printf(s, "BAD SIZE:%d 0x%x",
el_size, *(uint8_t *)num);
# (To override it, run 'make JOBS=1' and similar.)
#
ifeq ($(JOBS),)
- JOBS := $(shell egrep -c '^processor|^CPU' /proc/cpuinfo 2>/dev/null)
+ JOBS := $(shell (getconf _NPROCESSORS_ONLN || egrep -c '^processor|^CPU[0-9]' /proc/cpuinfo) 2>/dev/null)
ifeq ($(JOBS),0)
JOBS := 1
endif
if (!fshared)
futex_flag = FUTEX_PRIVATE_FLAG;
+ if (nrequeue > nthreads)
+ nrequeue = nthreads;
+
printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %p), "
"%d at a time.\n\n", getpid(), nthreads,
fshared ? "shared":"private", &futex1, &futex2, nrequeue);
/* Ok, all threads are patiently blocked, start requeueing */
gettimeofday(&start, NULL);
- for (nrequeued = 0; nrequeued < nthreads; nrequeued += nrequeue) {
+ while (nrequeued < nthreads) {
/*
* Do not wakeup any tasks blocked on futex1, allowing
* us to really measure futex_wait functionality.
*/
- futex_cmp_requeue(&futex1, 0, &futex2, 0,
- nrequeue, futex_flag);
+ nrequeued += futex_cmp_requeue(&futex1, 0, &futex2, 0,
+ nrequeue, futex_flag);
}
+
gettimeofday(&end, NULL);
timersub(&end, &start, &runtime);
- if (nrequeued > nthreads)
- nrequeued = nthreads;
-
update_stats(&requeued_stats, nrequeued);
update_stats(&requeuetime_stats, runtime.tv_usec);
}
/* everybody should be blocked on futex2, wake'em up */
- nrequeued = futex_wake(&futex2, nthreads, futex_flag);
+ nrequeued = futex_wake(&futex2, nrequeued, futex_flag);
if (nthreads != nrequeued)
warnx("couldn't wakeup all tasks (%d/%d)", nrequeued, nthreads);
OPT_INTEGER('H', "thp" , &p0.thp, "MADV_NOHUGEPAGE < 0 < MADV_HUGEPAGE"),
OPT_BOOLEAN('c', "show_convergence", &p0.show_convergence, "show convergence details"),
OPT_BOOLEAN('m', "measure_convergence", &p0.measure_convergence, "measure convergence latency"),
- OPT_BOOLEAN('q', "quiet" , &p0.show_quiet, "bzero the initial allocations"),
+ OPT_BOOLEAN('q', "quiet" , &p0.show_quiet, "quiet mode"),
OPT_BOOLEAN('S', "serialize-startup", &p0.serialize_startup,"serialize thread startup"),
/* Special option string parsing callbacks: */
td = g->threads + task_nr;
node = numa_node_of_cpu(td->curr_cpu);
+ if (node < 0) /* curr_cpu was likely still -1 */
+ return 0;
+
node_present[node] = 1;
}
for (p = 0; p < g->p.nr_proc; p++) {
unsigned int nodes = count_process_nodes(p);
+ if (!nodes) {
+ *strong = 0;
+ return;
+ }
+
nodes_min = min(nodes, nodes_min);
nodes_max = max(nodes, nodes_max);
}
if (!name)
name = "main,";
- if (g->p.show_quiet)
+ if (!g->p.show_quiet)
printf(" %-30s %15.3f, %-15s %s\n", name, val, txt_unit, txt_short);
else
printf(" %14.3f %s\n", val, txt_long);
return 0;
}
-static struct page_stat *search_page_alloc_stat(struct page_stat *stat, bool create)
+static struct page_stat *search_page_alloc_stat(struct page_stat *pstat, bool create)
{
struct rb_node **node = &page_alloc_tree.rb_node;
struct rb_node *parent = NULL;
parent = *node;
data = rb_entry(*node, struct page_stat, node);
- cmp = page_stat_cmp(data, stat);
+ cmp = page_stat_cmp(data, pstat);
if (cmp < 0)
node = &parent->rb_left;
else if (cmp > 0)
data = zalloc(sizeof(*data));
if (data != NULL) {
- data->page = stat->page;
- data->order = stat->order;
- data->gfp_flags = stat->gfp_flags;
- data->migrate_type = stat->migrate_type;
+ data->page = pstat->page;
+ data->order = pstat->order;
+ data->gfp_flags = pstat->gfp_flags;
+ data->migrate_type = pstat->migrate_type;
rb_link_node(&data->node, parent, node);
rb_insert_color(&data->node, &page_alloc_tree);
unsigned int migrate_type = perf_evsel__intval(evsel, sample,
"migratetype");
u64 bytes = kmem_page_size << order;
- struct page_stat *stat;
+ struct page_stat *pstat;
struct page_stat this = {
.order = order,
.gfp_flags = gfp_flags,
* This is to find the current page (with correct gfp flags and
* migrate type) at free event.
*/
- stat = search_page(page, true);
- if (stat == NULL)
+ pstat = search_page(page, true);
+ if (pstat == NULL)
return -ENOMEM;
- stat->order = order;
- stat->gfp_flags = gfp_flags;
- stat->migrate_type = migrate_type;
+ pstat->order = order;
+ pstat->gfp_flags = gfp_flags;
+ pstat->migrate_type = migrate_type;
this.page = page;
- stat = search_page_alloc_stat(&this, true);
- if (stat == NULL)
+ pstat = search_page_alloc_stat(&this, true);
+ if (pstat == NULL)
return -ENOMEM;
- stat->nr_alloc++;
- stat->alloc_bytes += bytes;
+ pstat->nr_alloc++;
+ pstat->alloc_bytes += bytes;
order_stats[order][migrate_type]++;
u64 page;
unsigned int order = perf_evsel__intval(evsel, sample, "order");
u64 bytes = kmem_page_size << order;
- struct page_stat *stat;
+ struct page_stat *pstat;
struct page_stat this = {
.order = order,
};
nr_page_frees++;
total_page_free_bytes += bytes;
- stat = search_page(page, false);
- if (stat == NULL) {
+ pstat = search_page(page, false);
+ if (pstat == NULL) {
pr_debug2("missing free at page %"PRIx64" (order: %d)\n",
page, order);
}
this.page = page;
- this.gfp_flags = stat->gfp_flags;
- this.migrate_type = stat->migrate_type;
+ this.gfp_flags = pstat->gfp_flags;
+ this.migrate_type = pstat->migrate_type;
- rb_erase(&stat->node, &page_tree);
- free(stat);
+ rb_erase(&pstat->node, &page_tree);
+ free(pstat);
- stat = search_page_alloc_stat(&this, false);
- if (stat == NULL)
+ pstat = search_page_alloc_stat(&this, false);
+ if (pstat == NULL)
return -ENOENT;
- stat->nr_free++;
- stat->free_bytes += bytes;
+ pstat->nr_free++;
+ pstat->free_bytes += bytes;
return 0;
}
nr_page_frees, total_page_free_bytes / 1024);
printf("\n");
- printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total alloc+freed requests",
+ printf("%-30s: %'16"PRIu64" [ %'16"PRIu64" KB ]\n", "Total alloc+freed requests",
nr_alloc_freed, (total_alloc_freed_bytes) / 1024);
- printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total alloc-only requests",
+ printf("%-30s: %'16"PRIu64" [ %'16"PRIu64" KB ]\n", "Total alloc-only requests",
nr_page_allocs - nr_alloc_freed,
(total_page_alloc_bytes - total_alloc_freed_bytes) / 1024);
printf("%-30s: %'16lu [ %'16"PRIu64" KB ]\n", "Total free-only requests",
fprintf(stdout, "\n\n");
}
- if (sort_order == default_sort_order &&
+ if (sort_order == NULL &&
parent_pattern == default_parent_pattern) {
fprintf(stdout, "#\n# (%s)\n#\n", help);
"Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
"Check /proc/sys/kernel/kptr_restrict.\n\n"
"Kernel%s samples will not be resolved.\n",
- !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ?
+ al.map && !RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION]) ?
" modules" : "");
if (use_browser <= 0)
sleep(5);
if (err < 0)
goto out_error_mmap;
+ if (!target__none(&trace->opts.target))
+ perf_evlist__enable(evlist);
+
if (forks)
perf_evlist__start_workload(evlist);
- else
- perf_evlist__enable(evlist);
trace->multiple_threads = evlist->threads->map[0] == -1 ||
evlist->threads->nr > 1 ||
if (interrupted)
goto out_disable;
+
+ if (done && !draining) {
+ perf_evlist__disable(evlist);
+ draining = true;
+ }
}
}
*
* TODO:Group name support
*/
+ if (!arg)
+ return -EINVAL;
ptr = strpbrk(arg, ";=@+%");
if (ptr && *ptr == '=') { /* Event name */
/* Search child die for local variables and parameters. */
if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) {
/* Search again in global variables */
- if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 0, &vr_die))
+ if (!die_find_variable_at(&pf->cu_die, pf->pvar->var,
+ 0, &vr_die)) {
pr_warning("Failed to find '%s' in this function.\n",
pf->pvar->var);
ret = -ENOENT;
+ }
}
if (ret >= 0)
ret = convert_variable(&vr_die, pf);
-.PHONY: all all_32 all_64 check_build32 clean run_tests
+all:
+
+include ../lib.mk
+
+.PHONY: all all_32 all_64 warn_32bit_failure clean
TARGETS_C_BOTHBITS := sigreturn single_step_syscall
CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
-UNAME_P := $(shell uname -p)
+UNAME_M := $(shell uname -m)
+CAN_BUILD_I386 := $(shell ./check_cc.sh $(CC) trivial_32bit_program.c -m32)
+CAN_BUILD_X86_64 := $(shell ./check_cc.sh $(CC) trivial_64bit_program.c)
-# Always build 32-bit tests
+ifeq ($(CAN_BUILD_I386),1)
all: all_32
+TEST_PROGS += $(BINARIES_32)
+endif
-# If we're on a 64-bit host, build 64-bit tests as well
-ifeq ($(shell uname -p),x86_64)
+ifeq ($(CAN_BUILD_X86_64),1)
all: all_64
+TEST_PROGS += $(BINARIES_64)
endif
-all_32: check_build32 $(BINARIES_32)
+all_32: $(BINARIES_32)
all_64: $(BINARIES_64)
clean:
$(RM) $(BINARIES_32) $(BINARIES_64)
-run_tests:
- ./run_x86_tests.sh
-
$(TARGETS_C_BOTHBITS:%=%_32): %_32: %.c
$(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
$(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c
$(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
-check_build32:
- @if ! $(CC) -m32 -o /dev/null trivial_32bit_program.c; then \
- echo "Warning: you seem to have a broken 32-bit build" 2>&1; \
- echo "environment. If you are using a Debian-like"; \
- echo " distribution, try:"; \
- echo ""; \
- echo " apt-get install gcc-multilib libc6-i386 libc6-dev-i386"; \
- echo ""; \
- echo "If you are using a Fedora-like distribution, try:"; \
- echo ""; \
- echo " yum install glibc-devel.*i686"; \
- exit 1; \
- fi
+# x86_64 users should be encouraged to install 32-bit libraries
+ifeq ($(CAN_BUILD_I386)$(CAN_BUILD_X86_64),01)
+all: warn_32bit_failure
+
+warn_32bit_failure:
+ @echo "Warning: you seem to have a broken 32-bit build" 2>&1; \
+ echo "environment. This will reduce test coverage of 64-bit" 2>&1; \
+ echo "kernels. If you are using a Debian-like distribution," 2>&1; \
+ echo "try:"; 2>&1; \
+ echo ""; \
+ echo " apt-get install gcc-multilib libc6-i386 libc6-dev-i386"; \
+ echo ""; \
+ echo "If you are using a Fedora-like distribution, try:"; \
+ echo ""; \
+ echo " yum install glibc-devel.*i686"; \
+ exit 0;
+endif
--- /dev/null
+#!/bin/sh
+# check_cc.sh - Helper to test userspace compilation support
+# Copyright (c) 2015 Andrew Lutomirski
+# GPL v2
+
+CC="$1"
+TESTPROG="$2"
+shift 2
+
+if "$CC" -o /dev/null "$TESTPROG" -O0 "$@" 2>/dev/null; then
+ echo 1
+else
+ echo 0
+fi
+
+exit 0
+++ /dev/null
-#!/bin/bash
-
-# This is deliberately minimal. IMO kselftests should provide a standard
-# script here.
-./sigreturn_32 || exit 1
-./single_step_syscall_32 || exit 1
-
-if [[ "$uname -p" -eq "x86_64" ]]; then
- ./sigreturn_64 || exit 1
- ./single_step_syscall_64 || exit 1
-fi
-
-exit 0
* GPL v2
*/
+#ifndef __i386__
+# error wrong architecture
+#endif
+
#include <stdio.h>
int main()
--- /dev/null
+/*
+ * Trivial program to check that we have a valid 32-bit build environment.
+ * Copyright (c) 2015 Andy Lutomirski
+ * GPL v2
+ */
+
+#ifndef __x86_64__
+# error wrong architecture
+#endif
+
+#include <stdio.h>
+
+int main()
+{
+ printf("\n");
+
+ return 0;
+}
INSTALL_PROGRAM=install -m 755 -p
DEL_FILE=rm -f
-INSTALL_CONFIGFILE=install -m 644 -p
-CONFIG_FILE=
-CONFIG_PATH=
-
# Static builds might require -ltinfo, for instance
ifneq ($(findstring -static, $(LDFLAGS)),)
STATIC := --static
install:
- mkdir -p $(INSTALL_ROOT)/$(BINDIR)
- $(INSTALL_PROGRAM) "$(TARGET)" "$(INSTALL_ROOT)/$(BINDIR)/$(TARGET)"
- - mkdir -p $(INSTALL_ROOT)/$(CONFIG_PATH)
- - $(INSTALL_CONFIGFILE) "$(CONFIG_FILE)" "$(INSTALL_ROOT)/$(CONFIG_PATH)"
uninstall:
$(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/$(TARGET)"
- $(CONFIG_FILE) "$(CONFIG_PATH)"
-
clean:
find . -name "*.o" | xargs $(DEL_FILE)
TARGETS=page-types slabinfo page_owner_sort
LIB_DIR = ../lib/api
-LIBS = $(LIB_DIR)/libapikfs.a
+LIBS = $(LIB_DIR)/libapi.a
CC = $(CROSS_COMPILE)gcc
CFLAGS = -Wall -Wextra -I../lib/