Merge branch 'drm-intel-fixes' into drm-intel-next
This commit is contained in:
commit
bc67f799e7
153 changed files with 24389 additions and 502 deletions
2
CREDITS
2
CREDITS
|
@ -518,7 +518,7 @@ N: Zach Brown
|
|||
E: zab@zabbo.net
|
||||
D: maestro pci sound
|
||||
|
||||
M: David Brownell
|
||||
N: David Brownell
|
||||
D: Kernel engineer, mentor, and friend. Maintained USB EHCI and
|
||||
D: gadget layers, SPI subsystem, GPIO subsystem, and more than a few
|
||||
D: device drivers. His encouragement also helped many engineers get
|
||||
|
|
|
@ -22,6 +22,10 @@ Supported chips:
|
|||
Prefix: 'f71869'
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
Datasheet: Available from the Fintek website
|
||||
* Fintek F71869A
|
||||
Prefix: 'f71869a'
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
Datasheet: Not public
|
||||
* Fintek F71882FG and F71883FG
|
||||
Prefix: 'f71882fg'
|
||||
Addresses scanned: none, address read from Super I/O config space
|
||||
|
|
|
@ -9,8 +9,8 @@ Supported chips:
|
|||
Socket S1G3: Athlon II, Sempron, Turion II
|
||||
* AMD Family 11h processors:
|
||||
Socket S1G2: Athlon (X2), Sempron (X2), Turion X2 (Ultra)
|
||||
* AMD Family 12h processors: "Llano"
|
||||
* AMD Family 14h processors: "Brazos" (C/E/G-Series)
|
||||
* AMD Family 12h processors: "Llano" (E2/A4/A6/A8-Series)
|
||||
* AMD Family 14h processors: "Brazos" (C/E/G/Z-Series)
|
||||
* AMD Family 15h processors: "Bulldozer"
|
||||
|
||||
Prefix: 'k10temp'
|
||||
|
@ -20,12 +20,16 @@ Supported chips:
|
|||
http://support.amd.com/us/Processor_TechDocs/31116.pdf
|
||||
BIOS and Kernel Developer's Guide (BKDG) for AMD Family 11h Processors:
|
||||
http://support.amd.com/us/Processor_TechDocs/41256.pdf
|
||||
BIOS and Kernel Developer's Guide (BKDG) for AMD Family 12h Processors:
|
||||
http://support.amd.com/us/Processor_TechDocs/41131.pdf
|
||||
BIOS and Kernel Developer's Guide (BKDG) for AMD Family 14h Models 00h-0Fh Processors:
|
||||
http://support.amd.com/us/Processor_TechDocs/43170.pdf
|
||||
Revision Guide for AMD Family 10h Processors:
|
||||
http://support.amd.com/us/Processor_TechDocs/41322.pdf
|
||||
Revision Guide for AMD Family 11h Processors:
|
||||
http://support.amd.com/us/Processor_TechDocs/41788.pdf
|
||||
Revision Guide for AMD Family 12h Processors:
|
||||
http://support.amd.com/us/Processor_TechDocs/44739.pdf
|
||||
Revision Guide for AMD Family 14h Models 00h-0Fh Processors:
|
||||
http://support.amd.com/us/Processor_TechDocs/47534.pdf
|
||||
AMD Family 11h Processor Power and Thermal Data Sheet for Notebooks:
|
||||
|
|
|
@ -501,13 +501,29 @@ helper functions described in Section 4. In that case, pm_runtime_resume()
|
|||
should be used. Of course, for this purpose the device's run-time PM has to be
|
||||
enabled earlier by calling pm_runtime_enable().
|
||||
|
||||
If the device bus type's or driver's ->probe() or ->remove() callback runs
|
||||
If the device bus type's or driver's ->probe() callback runs
|
||||
pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
|
||||
they will fail returning -EAGAIN, because the device's usage counter is
|
||||
incremented by the core before executing ->probe() and ->remove(). Still, it
|
||||
may be desirable to suspend the device as soon as ->probe() or ->remove() has
|
||||
finished, so the PM core uses pm_runtime_idle_sync() to invoke the
|
||||
subsystem-level idle callback for the device at that time.
|
||||
incremented by the driver core before executing ->probe(). Still, it may be
|
||||
desirable to suspend the device as soon as ->probe() has finished, so the driver
|
||||
core uses pm_runtime_put_sync() to invoke the subsystem-level idle callback for
|
||||
the device at that time.
|
||||
|
||||
Moreover, the driver core prevents runtime PM callbacks from racing with the bus
|
||||
notifier callback in __device_release_driver(), which is necessary, because the
|
||||
notifier is used by some subsystems to carry out operations affecting the
|
||||
runtime PM functionality. It does so by calling pm_runtime_get_sync() before
|
||||
driver_sysfs_remove() and the BUS_NOTIFY_UNBIND_DRIVER notifications. This
|
||||
resumes the device if it's in the suspended state and prevents it from
|
||||
being suspended again while those routines are being executed.
|
||||
|
||||
To allow bus types and drivers to put devices into the suspended state by
|
||||
calling pm_runtime_suspend() from their ->remove() routines, the driver core
|
||||
executes pm_runtime_put_sync() after running the BUS_NOTIFY_UNBIND_DRIVER
|
||||
notifications in __device_release_driver(). This requires bus types and
|
||||
drivers to make their ->remove() callbacks avoid races with runtime PM directly,
|
||||
but also it allows of more flexibility in the handling of devices during the
|
||||
removal of their drivers.
|
||||
|
||||
The user space can effectively disallow the driver of the device to power manage
|
||||
it at run time by changing the value of its /sys/devices/.../power/control
|
||||
|
|
17
MAINTAINERS
17
MAINTAINERS
|
@ -1345,16 +1345,18 @@ F: drivers/auxdisplay/
|
|||
F: include/linux/cfag12864b.h
|
||||
|
||||
AVR32 ARCHITECTURE
|
||||
M: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
|
||||
M: Haavard Skinnemoen <hskinnemoen@gmail.com>
|
||||
M: Hans-Christian Egtvedt <egtvedt@samfundet.no>
|
||||
W: http://www.atmel.com/products/AVR32/
|
||||
W: http://avr32linux.org/
|
||||
W: http://avrfreaks.net/
|
||||
S: Supported
|
||||
S: Maintained
|
||||
F: arch/avr32/
|
||||
|
||||
AVR32/AT32AP MACHINE SUPPORT
|
||||
M: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
|
||||
S: Supported
|
||||
M: Haavard Skinnemoen <hskinnemoen@gmail.com>
|
||||
M: Hans-Christian Egtvedt <egtvedt@samfundet.no>
|
||||
S: Maintained
|
||||
F: arch/avr32/mach-at32ap/
|
||||
|
||||
AX.25 NETWORK LAYER
|
||||
|
@ -1390,7 +1392,6 @@ F: include/linux/backlight.h
|
|||
BATMAN ADVANCED
|
||||
M: Marek Lindner <lindner_marek@yahoo.de>
|
||||
M: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
|
||||
M: Sven Eckelmann <sven@narfation.org>
|
||||
L: b.a.t.m.a.n@lists.open-mesh.org
|
||||
W: http://www.open-mesh.org/
|
||||
S: Maintained
|
||||
|
@ -1423,7 +1424,6 @@ S: Supported
|
|||
F: arch/blackfin/
|
||||
|
||||
BLACKFIN EMAC DRIVER
|
||||
M: Michael Hennerich <michael.hennerich@analog.com>
|
||||
L: uclinux-dist-devel@blackfin.uclinux.org
|
||||
W: http://blackfin.uclinux.org
|
||||
S: Supported
|
||||
|
@ -1639,7 +1639,7 @@ CAN NETWORK LAYER
|
|||
M: Oliver Hartkopp <socketcan@hartkopp.net>
|
||||
M: Oliver Hartkopp <oliver.hartkopp@volkswagen.de>
|
||||
M: Urs Thuermann <urs.thuermann@volkswagen.de>
|
||||
L: socketcan-core@lists.berlios.de
|
||||
L: socketcan-core@lists.berlios.de (subscribers-only)
|
||||
L: netdev@vger.kernel.org
|
||||
W: http://developer.berlios.de/projects/socketcan/
|
||||
S: Maintained
|
||||
|
@ -1651,7 +1651,7 @@ F: include/linux/can/raw.h
|
|||
|
||||
CAN NETWORK DRIVERS
|
||||
M: Wolfgang Grandegger <wg@grandegger.com>
|
||||
L: socketcan-core@lists.berlios.de
|
||||
L: socketcan-core@lists.berlios.de (subscribers-only)
|
||||
L: netdev@vger.kernel.org
|
||||
W: http://developer.berlios.de/projects/socketcan/
|
||||
S: Maintained
|
||||
|
@ -5181,6 +5181,7 @@ S: Supported
|
|||
F: drivers/net/qlcnic/
|
||||
|
||||
QLOGIC QLGE 10Gb ETHERNET DRIVER
|
||||
M: Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
|
||||
M: Ron Mercer <ron.mercer@qlogic.com>
|
||||
M: linux-driver@qlogic.com
|
||||
L: netdev@vger.kernel.org
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 3
|
||||
PATCHLEVEL = 0
|
||||
SUBLEVEL = 0
|
||||
EXTRAVERSION = -rc5
|
||||
EXTRAVERSION = -rc6
|
||||
NAME = Sneaky Weasel
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
42
README
42
README
|
@ -1,6 +1,6 @@
|
|||
Linux kernel release 2.6.xx <http://kernel.org/>
|
||||
Linux kernel release 3.x <http://kernel.org/>
|
||||
|
||||
These are the release notes for Linux version 2.6. Read them carefully,
|
||||
These are the release notes for Linux version 3. Read them carefully,
|
||||
as they tell you what this is all about, explain how to install the
|
||||
kernel, and what to do if something goes wrong.
|
||||
|
||||
|
@ -62,10 +62,10 @@ INSTALLING the kernel source:
|
|||
directory where you have permissions (eg. your home directory) and
|
||||
unpack it:
|
||||
|
||||
gzip -cd linux-2.6.XX.tar.gz | tar xvf -
|
||||
gzip -cd linux-3.X.tar.gz | tar xvf -
|
||||
|
||||
or
|
||||
bzip2 -dc linux-2.6.XX.tar.bz2 | tar xvf -
|
||||
bzip2 -dc linux-3.X.tar.bz2 | tar xvf -
|
||||
|
||||
|
||||
Replace "XX" with the version number of the latest kernel.
|
||||
|
@ -75,15 +75,15 @@ INSTALLING the kernel source:
|
|||
files. They should match the library, and not get messed up by
|
||||
whatever the kernel-du-jour happens to be.
|
||||
|
||||
- You can also upgrade between 2.6.xx releases by patching. Patches are
|
||||
- You can also upgrade between 3.x releases by patching. Patches are
|
||||
distributed in the traditional gzip and the newer bzip2 format. To
|
||||
install by patching, get all the newer patch files, enter the
|
||||
top level directory of the kernel source (linux-2.6.xx) and execute:
|
||||
top level directory of the kernel source (linux-3.x) and execute:
|
||||
|
||||
gzip -cd ../patch-2.6.xx.gz | patch -p1
|
||||
gzip -cd ../patch-3.x.gz | patch -p1
|
||||
|
||||
or
|
||||
bzip2 -dc ../patch-2.6.xx.bz2 | patch -p1
|
||||
bzip2 -dc ../patch-3.x.bz2 | patch -p1
|
||||
|
||||
(repeat xx for all versions bigger than the version of your current
|
||||
source tree, _in_order_) and you should be ok. You may want to remove
|
||||
|
@ -91,9 +91,9 @@ INSTALLING the kernel source:
|
|||
failed patches (xxx# or xxx.rej). If there are, either you or me has
|
||||
made a mistake.
|
||||
|
||||
Unlike patches for the 2.6.x kernels, patches for the 2.6.x.y kernels
|
||||
Unlike patches for the 3.x kernels, patches for the 3.x.y kernels
|
||||
(also known as the -stable kernels) are not incremental but instead apply
|
||||
directly to the base 2.6.x kernel. Please read
|
||||
directly to the base 3.x kernel. Please read
|
||||
Documentation/applying-patches.txt for more information.
|
||||
|
||||
Alternatively, the script patch-kernel can be used to automate this
|
||||
|
@ -107,14 +107,14 @@ INSTALLING the kernel source:
|
|||
an alternative directory can be specified as the second argument.
|
||||
|
||||
- If you are upgrading between releases using the stable series patches
|
||||
(for example, patch-2.6.xx.y), note that these "dot-releases" are
|
||||
not incremental and must be applied to the 2.6.xx base tree. For
|
||||
example, if your base kernel is 2.6.12 and you want to apply the
|
||||
2.6.12.3 patch, you do not and indeed must not first apply the
|
||||
2.6.12.1 and 2.6.12.2 patches. Similarly, if you are running kernel
|
||||
version 2.6.12.2 and want to jump to 2.6.12.3, you must first
|
||||
reverse the 2.6.12.2 patch (that is, patch -R) _before_ applying
|
||||
the 2.6.12.3 patch.
|
||||
(for example, patch-3.x.y), note that these "dot-releases" are
|
||||
not incremental and must be applied to the 3.x base tree. For
|
||||
example, if your base kernel is 3.0 and you want to apply the
|
||||
3.0.3 patch, you do not and indeed must not first apply the
|
||||
3.0.1 and 3.0.2 patches. Similarly, if you are running kernel
|
||||
version 3.0.2 and want to jump to 3.0.3, you must first
|
||||
reverse the 3.0.2 patch (that is, patch -R) _before_ applying
|
||||
the 3.0.3 patch.
|
||||
You can read more on this in Documentation/applying-patches.txt
|
||||
|
||||
- Make sure you have no stale .o files and dependencies lying around:
|
||||
|
@ -126,7 +126,7 @@ INSTALLING the kernel source:
|
|||
|
||||
SOFTWARE REQUIREMENTS
|
||||
|
||||
Compiling and running the 2.6.xx kernels requires up-to-date
|
||||
Compiling and running the 3.x kernels requires up-to-date
|
||||
versions of various software packages. Consult
|
||||
Documentation/Changes for the minimum version numbers required
|
||||
and how to get updates for these packages. Beware that using
|
||||
|
@ -142,11 +142,11 @@ BUILD directory for the kernel:
|
|||
Using the option "make O=output/dir" allow you to specify an alternate
|
||||
place for the output files (including .config).
|
||||
Example:
|
||||
kernel source code: /usr/src/linux-2.6.N
|
||||
kernel source code: /usr/src/linux-3.N
|
||||
build directory: /home/name/build/kernel
|
||||
|
||||
To configure and build the kernel use:
|
||||
cd /usr/src/linux-2.6.N
|
||||
cd /usr/src/linux-3.N
|
||||
make O=/home/name/build/kernel menuconfig
|
||||
make O=/home/name/build/kernel
|
||||
sudo make O=/home/name/build/kernel modules_install install
|
||||
|
|
|
@ -223,15 +223,15 @@ static struct clk *periph_clocks[] __initdata = {
|
|||
};
|
||||
|
||||
static struct clk_lookup periph_clocks_lookups[] = {
|
||||
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk),
|
||||
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
|
||||
CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
|
||||
CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk),
|
||||
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
|
||||
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
|
||||
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb_clk),
|
||||
CLKDEV_CON_DEV_ID("ssc", "ssc.0", &ssc0_clk),
|
||||
CLKDEV_CON_DEV_ID("ssc", "ssc.1", &ssc1_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
|
||||
};
|
||||
|
||||
static struct clk_lookup usart_clocks_lookups[] = {
|
||||
|
|
|
@ -1220,7 +1220,7 @@ void __init at91_set_serial_console(unsigned portnr)
|
|||
{
|
||||
if (portnr < ATMEL_MAX_UART) {
|
||||
atmel_default_console_device = at91_uarts[portnr];
|
||||
at91cap9_set_console_clock(portnr);
|
||||
at91cap9_set_console_clock(at91_uarts[portnr]->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -199,9 +199,9 @@ static struct clk_lookup periph_clocks_lookups[] = {
|
|||
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.1", &tc3_clk),
|
||||
CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.1", &tc4_clk),
|
||||
CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.1", &tc5_clk),
|
||||
CLKDEV_CON_DEV_ID("ssc", "ssc.0", &ssc0_clk),
|
||||
CLKDEV_CON_DEV_ID("ssc", "ssc.1", &ssc1_clk),
|
||||
CLKDEV_CON_DEV_ID("ssc", "ssc.2", &ssc2_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "ssc.0", &ssc0_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "ssc.1", &ssc1_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "ssc.2", &ssc2_clk),
|
||||
};
|
||||
|
||||
static struct clk_lookup usart_clocks_lookups[] = {
|
||||
|
|
|
@ -1135,7 +1135,7 @@ void __init at91_set_serial_console(unsigned portnr)
|
|||
{
|
||||
if (portnr < ATMEL_MAX_UART) {
|
||||
atmel_default_console_device = at91_uarts[portnr];
|
||||
at91rm9200_set_console_clock(portnr);
|
||||
at91rm9200_set_console_clock(at91_uarts[portnr]->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1173,7 +1173,7 @@ void __init at91_set_serial_console(unsigned portnr)
|
|||
{
|
||||
if (portnr < ATMEL_MAX_UART) {
|
||||
atmel_default_console_device = at91_uarts[portnr];
|
||||
at91sam9260_set_console_clock(portnr);
|
||||
at91sam9260_set_console_clock(at91_uarts[portnr]->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1013,7 +1013,7 @@ void __init at91_set_serial_console(unsigned portnr)
|
|||
{
|
||||
if (portnr < ATMEL_MAX_UART) {
|
||||
atmel_default_console_device = at91_uarts[portnr];
|
||||
at91sam9261_set_console_clock(portnr);
|
||||
at91sam9261_set_console_clock(at91_uarts[portnr]->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1395,7 +1395,7 @@ void __init at91_set_serial_console(unsigned portnr)
|
|||
{
|
||||
if (portnr < ATMEL_MAX_UART) {
|
||||
atmel_default_console_device = at91_uarts[portnr];
|
||||
at91sam9263_set_console_clock(portnr);
|
||||
at91sam9263_set_console_clock(at91_uarts[portnr]->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -217,11 +217,11 @@ static struct clk *periph_clocks[] __initdata = {
|
|||
static struct clk_lookup periph_clocks_lookups[] = {
|
||||
/* One additional fake clock for ohci */
|
||||
CLKDEV_CON_ID("ohci_clk", &uhphs_clk),
|
||||
CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci.0", &uhphs_clk),
|
||||
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk),
|
||||
CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.0", &mmc0_clk),
|
||||
CLKDEV_CON_DEV_ID("mci_clk", "at91_mci.1", &mmc1_clk),
|
||||
CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk),
|
||||
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
|
||||
CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
|
||||
CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
|
||||
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
|
||||
CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
|
||||
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tcb0_clk),
|
||||
|
|
|
@ -1550,7 +1550,7 @@ void __init at91_set_serial_console(unsigned portnr)
|
|||
{
|
||||
if (portnr < ATMEL_MAX_UART) {
|
||||
atmel_default_console_device = at91_uarts[portnr];
|
||||
at91sam9g45_set_console_clock(portnr);
|
||||
at91sam9g45_set_console_clock(at91_uarts[portnr]->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -191,8 +191,8 @@ static struct clk *periph_clocks[] __initdata = {
|
|||
};
|
||||
|
||||
static struct clk_lookup periph_clocks_lookups[] = {
|
||||
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc.0", &utmi_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc.0", &udphs_clk),
|
||||
CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
|
||||
CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
|
||||
CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
|
||||
CLKDEV_CON_DEV_ID("t1_clk", "atmel_tcb.0", &tc1_clk),
|
||||
CLKDEV_CON_DEV_ID("t2_clk", "atmel_tcb.0", &tc2_clk),
|
||||
|
|
|
@ -1168,7 +1168,7 @@ void __init at91_set_serial_console(unsigned portnr)
|
|||
{
|
||||
if (portnr < ATMEL_MAX_UART) {
|
||||
atmel_default_console_device = at91_uarts[portnr];
|
||||
at91sam9rl_set_console_clock(portnr);
|
||||
at91sam9rl_set_console_clock(at91_uarts[portnr]->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -215,7 +215,7 @@ static void __init cap9adk_add_device_nand(void)
|
|||
csa = at91_sys_read(AT91_MATRIX_EBICSA);
|
||||
at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_VDDIOMSEL_3_3V);
|
||||
|
||||
cap9adk_nand_data.bus_width_16 = !board_have_nand_8bit();
|
||||
cap9adk_nand_data.bus_width_16 = board_have_nand_16bit();
|
||||
/* setup bus-width (8 or 16) */
|
||||
if (cap9adk_nand_data.bus_width_16)
|
||||
cap9adk_nand_smc_config.mode |= AT91_SMC_DBW_16;
|
||||
|
|
|
@ -214,7 +214,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
|||
|
||||
static void __init ek_add_device_nand(void)
|
||||
{
|
||||
ek_nand_data.bus_width_16 = !board_have_nand_8bit();
|
||||
ek_nand_data.bus_width_16 = board_have_nand_16bit();
|
||||
/* setup bus-width (8 or 16) */
|
||||
if (ek_nand_data.bus_width_16)
|
||||
ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
|
||||
|
|
|
@ -220,7 +220,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
|||
|
||||
static void __init ek_add_device_nand(void)
|
||||
{
|
||||
ek_nand_data.bus_width_16 = !board_have_nand_8bit();
|
||||
ek_nand_data.bus_width_16 = board_have_nand_16bit();
|
||||
/* setup bus-width (8 or 16) */
|
||||
if (ek_nand_data.bus_width_16)
|
||||
ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
|
||||
|
|
|
@ -221,7 +221,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
|||
|
||||
static void __init ek_add_device_nand(void)
|
||||
{
|
||||
ek_nand_data.bus_width_16 = !board_have_nand_8bit();
|
||||
ek_nand_data.bus_width_16 = board_have_nand_16bit();
|
||||
/* setup bus-width (8 or 16) */
|
||||
if (ek_nand_data.bus_width_16)
|
||||
ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
|
||||
|
|
|
@ -198,7 +198,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
|||
|
||||
static void __init ek_add_device_nand(void)
|
||||
{
|
||||
ek_nand_data.bus_width_16 = !board_have_nand_8bit();
|
||||
ek_nand_data.bus_width_16 = board_have_nand_16bit();
|
||||
/* setup bus-width (8 or 16) */
|
||||
if (ek_nand_data.bus_width_16)
|
||||
ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
|
||||
|
|
|
@ -178,7 +178,7 @@ static struct sam9_smc_config __initdata ek_nand_smc_config = {
|
|||
|
||||
static void __init ek_add_device_nand(void)
|
||||
{
|
||||
ek_nand_data.bus_width_16 = !board_have_nand_8bit();
|
||||
ek_nand_data.bus_width_16 = board_have_nand_16bit();
|
||||
/* setup bus-width (8 or 16) */
|
||||
if (ek_nand_data.bus_width_16)
|
||||
ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
* the 16-31 bit are reserved for at91 generic information
|
||||
*
|
||||
* bit 31:
|
||||
* 0 => nand 16 bit
|
||||
* 1 => nand 8 bit
|
||||
* 0 => nand 8 bit
|
||||
* 1 => nand 16 bit
|
||||
*/
|
||||
#define BOARD_HAVE_NAND_8BIT (1 << 31)
|
||||
static int inline board_have_nand_8bit(void)
|
||||
#define BOARD_HAVE_NAND_16BIT (1 << 31)
|
||||
static inline int board_have_nand_16bit(void)
|
||||
{
|
||||
return system_rev & BOARD_HAVE_NAND_8BIT;
|
||||
return system_rev & BOARD_HAVE_NAND_16BIT;
|
||||
}
|
||||
|
||||
#endif /* __ARCH_SYSTEM_REV_H__ */
|
||||
|
|
|
@ -381,7 +381,7 @@ void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state)
|
|||
gpio_set_value(GPIO_PORT114, state);
|
||||
}
|
||||
|
||||
static struct sh_mobile_sdhi_info sh_sdhi1_platdata = {
|
||||
static struct sh_mobile_sdhi_info sh_sdhi1_info = {
|
||||
.tmio_flags = TMIO_MMC_WRPROTECT_DISABLE,
|
||||
.tmio_caps = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
|
||||
.tmio_ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
|
@ -413,7 +413,7 @@ static struct platform_device sdhi1_device = {
|
|||
.name = "sh_mobile_sdhi",
|
||||
.id = 1,
|
||||
.dev = {
|
||||
.platform_data = &sh_sdhi1_platdata,
|
||||
.platform_data = &sh_sdhi1_info,
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(sdhi1_resources),
|
||||
.resource = sdhi1_resources,
|
||||
|
|
|
@ -913,7 +913,7 @@ static struct i2c_board_info imx074_info = {
|
|||
I2C_BOARD_INFO("imx074", 0x1a),
|
||||
};
|
||||
|
||||
struct soc_camera_link imx074_link = {
|
||||
static struct soc_camera_link imx074_link = {
|
||||
.bus_id = 0,
|
||||
.board_info = &imx074_info,
|
||||
.i2c_adapter_id = 0,
|
||||
|
|
|
@ -1287,9 +1287,9 @@ static struct platform_device *mackerel_devices[] __initdata = {
|
|||
&nor_flash_device,
|
||||
&smc911x_device,
|
||||
&lcdc_device,
|
||||
&usbhs0_device,
|
||||
&usb1_host_device,
|
||||
&usbhs1_device,
|
||||
&usbhs0_device,
|
||||
&leds_device,
|
||||
&fsi_device,
|
||||
&fsi_ak4643_device,
|
||||
|
|
|
@ -209,8 +209,10 @@
|
|||
wm8776:codec@1a {
|
||||
compatible = "wlf,wm8776";
|
||||
reg = <0x1a>;
|
||||
/* MCLK source is a stand-alone oscillator */
|
||||
clock-frequency = <12288000>;
|
||||
/*
|
||||
* clock-frequency will be set by U-Boot if
|
||||
* the clock is enabled.
|
||||
*/
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -280,7 +282,8 @@
|
|||
codec-handle = <&wm8776>;
|
||||
fsl,playback-dma = <&dma00>;
|
||||
fsl,capture-dma = <&dma01>;
|
||||
fsl,fifo-depth = <16>;
|
||||
fsl,fifo-depth = <15>;
|
||||
fsl,ssi-asynchronous;
|
||||
};
|
||||
|
||||
dma@c300 {
|
||||
|
|
|
@ -148,7 +148,6 @@ CONFIG_SCSI_SAS_ATTRS=m
|
|||
CONFIG_SCSI_CXGB3_ISCSI=m
|
||||
CONFIG_SCSI_CXGB4_ISCSI=m
|
||||
CONFIG_SCSI_BNX2_ISCSI=m
|
||||
CONFIG_SCSI_BNX2_ISCSI=m
|
||||
CONFIG_BE2ISCSI=m
|
||||
CONFIG_SCSI_IBMVSCSI=y
|
||||
CONFIG_SCSI_IBMVFC=m
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/rtc.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/rtas.h>
|
||||
#include <asm/time.h>
|
||||
|
@ -29,9 +30,10 @@ unsigned long __init rtas_get_boot_time(void)
|
|||
}
|
||||
} while (wait_time && (get_tb() < max_wait_tb));
|
||||
|
||||
if (error != 0 && printk_ratelimit()) {
|
||||
printk(KERN_WARNING "error: reading the clock failed (%d)\n",
|
||||
error);
|
||||
if (error != 0) {
|
||||
printk_ratelimited(KERN_WARNING
|
||||
"error: reading the clock failed (%d)\n",
|
||||
error);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -55,19 +57,21 @@ void rtas_get_rtc_time(struct rtc_time *rtc_tm)
|
|||
|
||||
wait_time = rtas_busy_delay_time(error);
|
||||
if (wait_time) {
|
||||
if (in_interrupt() && printk_ratelimit()) {
|
||||
if (in_interrupt()) {
|
||||
memset(rtc_tm, 0, sizeof(struct rtc_time));
|
||||
printk(KERN_WARNING "error: reading clock"
|
||||
" would delay interrupt\n");
|
||||
printk_ratelimited(KERN_WARNING
|
||||
"error: reading clock "
|
||||
"would delay interrupt\n");
|
||||
return; /* delay not allowed */
|
||||
}
|
||||
msleep(wait_time);
|
||||
}
|
||||
} while (wait_time && (get_tb() < max_wait_tb));
|
||||
|
||||
if (error != 0 && printk_ratelimit()) {
|
||||
printk(KERN_WARNING "error: reading the clock failed (%d)\n",
|
||||
error);
|
||||
if (error != 0) {
|
||||
printk_ratelimited(KERN_WARNING
|
||||
"error: reading the clock failed (%d)\n",
|
||||
error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -99,9 +103,10 @@ int rtas_set_rtc_time(struct rtc_time *tm)
|
|||
}
|
||||
} while (wait_time && (get_tb() < max_wait_tb));
|
||||
|
||||
if (error != 0 && printk_ratelimit())
|
||||
printk(KERN_WARNING "error: setting the clock failed (%d)\n",
|
||||
error);
|
||||
if (error != 0)
|
||||
printk_ratelimited(KERN_WARNING
|
||||
"error: setting the clock failed (%d)\n",
|
||||
error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/errno.h>
|
||||
#include <linux/elf.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#ifdef CONFIG_PPC64
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/compat.h>
|
||||
|
@ -892,11 +893,12 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
|
|||
printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
|
||||
regs, frame, newsp);
|
||||
#endif
|
||||
if (show_unhandled_signals && printk_ratelimit())
|
||||
printk(KERN_INFO "%s[%d]: bad frame in handle_rt_signal32: "
|
||||
"%p nip %08lx lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
addr, regs->nip, regs->link);
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(KERN_INFO
|
||||
"%s[%d]: bad frame in handle_rt_signal32: "
|
||||
"%p nip %08lx lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
addr, regs->nip, regs->link);
|
||||
|
||||
force_sigsegv(sig, current);
|
||||
return 0;
|
||||
|
@ -1058,11 +1060,12 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
|
|||
return 0;
|
||||
|
||||
bad:
|
||||
if (show_unhandled_signals && printk_ratelimit())
|
||||
printk(KERN_INFO "%s[%d]: bad frame in sys_rt_sigreturn: "
|
||||
"%p nip %08lx lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
rt_sf, regs->nip, regs->link);
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(KERN_INFO
|
||||
"%s[%d]: bad frame in sys_rt_sigreturn: "
|
||||
"%p nip %08lx lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
rt_sf, regs->nip, regs->link);
|
||||
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
|
@ -1149,12 +1152,12 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
|
|||
* We kill the task with a SIGSEGV in this situation.
|
||||
*/
|
||||
if (do_setcontext(ctx, regs, 1)) {
|
||||
if (show_unhandled_signals && printk_ratelimit())
|
||||
printk(KERN_INFO "%s[%d]: bad frame in "
|
||||
"sys_debug_setcontext: %p nip %08lx "
|
||||
"lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
ctx, regs->nip, regs->link);
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(KERN_INFO "%s[%d]: bad frame in "
|
||||
"sys_debug_setcontext: %p nip %08lx "
|
||||
"lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
ctx, regs->nip, regs->link);
|
||||
|
||||
force_sig(SIGSEGV, current);
|
||||
goto out;
|
||||
|
@ -1236,11 +1239,12 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
|||
printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
|
||||
regs, frame, newsp);
|
||||
#endif
|
||||
if (show_unhandled_signals && printk_ratelimit())
|
||||
printk(KERN_INFO "%s[%d]: bad frame in handle_signal32: "
|
||||
"%p nip %08lx lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
frame, regs->nip, regs->link);
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(KERN_INFO
|
||||
"%s[%d]: bad frame in handle_signal32: "
|
||||
"%p nip %08lx lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
frame, regs->nip, regs->link);
|
||||
|
||||
force_sigsegv(sig, current);
|
||||
return 0;
|
||||
|
@ -1288,11 +1292,12 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
|
|||
return 0;
|
||||
|
||||
badframe:
|
||||
if (show_unhandled_signals && printk_ratelimit())
|
||||
printk(KERN_INFO "%s[%d]: bad frame in sys_sigreturn: "
|
||||
"%p nip %08lx lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
addr, regs->nip, regs->link);
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(KERN_INFO
|
||||
"%s[%d]: bad frame in sys_sigreturn: "
|
||||
"%p nip %08lx lr %08lx\n",
|
||||
current->comm, current->pid,
|
||||
addr, regs->nip, regs->link);
|
||||
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/elf.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
#include <asm/sigcontext.h>
|
||||
#include <asm/ucontext.h>
|
||||
|
@ -380,10 +381,10 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
|
|||
printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n",
|
||||
regs, uc, &uc->uc_mcontext);
|
||||
#endif
|
||||
if (show_unhandled_signals && printk_ratelimit())
|
||||
printk(regs->msr & MSR_64BIT ? fmt64 : fmt32,
|
||||
current->comm, current->pid, "rt_sigreturn",
|
||||
(long)uc, regs->nip, regs->link);
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
|
||||
current->comm, current->pid, "rt_sigreturn",
|
||||
(long)uc, regs->nip, regs->link);
|
||||
|
||||
force_sig(SIGSEGV, current);
|
||||
return 0;
|
||||
|
@ -468,10 +469,10 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
|||
printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
|
||||
regs, frame, newsp);
|
||||
#endif
|
||||
if (show_unhandled_signals && printk_ratelimit())
|
||||
printk(regs->msr & MSR_64BIT ? fmt64 : fmt32,
|
||||
current->comm, current->pid, "setup_rt_frame",
|
||||
(long)frame, regs->nip, regs->link);
|
||||
if (show_unhandled_signals)
|
||||
printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
|
||||
current->comm, current->pid, "setup_rt_frame",
|
||||
(long)frame, regs->nip, regs->link);
|
||||
|
||||
force_sigsegv(signr, current);
|
||||
return 0;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <linux/bug.h>
|
||||
#include <linux/kdebug.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
#include <asm/emulated_ops.h>
|
||||
#include <asm/pgtable.h>
|
||||
|
@ -197,12 +198,11 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
|
|||
if (die("Exception in kernel mode", regs, signr))
|
||||
return;
|
||||
} else if (show_unhandled_signals &&
|
||||
unhandled_signal(current, signr) &&
|
||||
printk_ratelimit()) {
|
||||
printk(regs->msr & MSR_64BIT ? fmt64 : fmt32,
|
||||
current->comm, current->pid, signr,
|
||||
addr, regs->nip, regs->link, code);
|
||||
}
|
||||
unhandled_signal(current, signr)) {
|
||||
printk_ratelimited(regs->msr & MSR_64BIT ? fmt64 : fmt32,
|
||||
current->comm, current->pid, signr,
|
||||
addr, regs->nip, regs->link, code);
|
||||
}
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.si_signo = signr;
|
||||
|
@ -425,7 +425,7 @@ int machine_check_e500mc(struct pt_regs *regs)
|
|||
unsigned long reason = mcsr;
|
||||
int recoverable = 1;
|
||||
|
||||
if (reason & MCSR_BUS_RBERR) {
|
||||
if (reason & MCSR_LD) {
|
||||
recoverable = fsl_rio_mcheck_exception(regs);
|
||||
if (recoverable == 1)
|
||||
goto silent_out;
|
||||
|
@ -1342,9 +1342,8 @@ void altivec_assist_exception(struct pt_regs *regs)
|
|||
} else {
|
||||
/* didn't recognize the instruction */
|
||||
/* XXX quick hack for now: set the non-Java bit in the VSCR */
|
||||
if (printk_ratelimit())
|
||||
printk(KERN_ERR "Unrecognized altivec instruction "
|
||||
"in %s at %lx\n", current->comm, regs->nip);
|
||||
printk_ratelimited(KERN_ERR "Unrecognized altivec instruction "
|
||||
"in %s at %lx\n", current->comm, regs->nip);
|
||||
current->thread.vscr.u[3] |= 0x10000;
|
||||
}
|
||||
}
|
||||
|
@ -1548,9 +1547,8 @@ u32 ppc_warn_emulated;
|
|||
|
||||
void ppc_warn_emulated_print(const char *type)
|
||||
{
|
||||
if (printk_ratelimit())
|
||||
pr_warning("%s used emulated %s instruction\n", current->comm,
|
||||
type);
|
||||
pr_warn_ratelimited("%s used emulated %s instruction\n", current->comm,
|
||||
type);
|
||||
}
|
||||
|
||||
static int __init ppc_warn_emulated_init(void)
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/kdebug.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/magic.h>
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
#include <asm/firmware.h>
|
||||
#include <asm/page.h>
|
||||
|
@ -346,11 +347,10 @@ int __kprobes do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (is_exec && (error_code & DSISR_PROTFAULT)
|
||||
&& printk_ratelimit())
|
||||
printk(KERN_CRIT "kernel tried to execute NX-protected"
|
||||
" page (%lx) - exploit attempt? (uid: %d)\n",
|
||||
address, current_uid());
|
||||
if (is_exec && (error_code & DSISR_PROTFAULT))
|
||||
printk_ratelimited(KERN_CRIT "kernel tried to execute NX-protected"
|
||||
" page (%lx) - exploit attempt? (uid: %d)\n",
|
||||
address, current_uid());
|
||||
|
||||
return SIGSEGV;
|
||||
|
||||
|
|
|
@ -283,23 +283,24 @@ static void __iomem *rio_regs_win;
|
|||
#ifdef CONFIG_E500
|
||||
int fsl_rio_mcheck_exception(struct pt_regs *regs)
|
||||
{
|
||||
const struct exception_table_entry *entry = NULL;
|
||||
unsigned long reason = mfspr(SPRN_MCSR);
|
||||
const struct exception_table_entry *entry;
|
||||
unsigned long reason;
|
||||
|
||||
if (reason & MCSR_BUS_RBERR) {
|
||||
reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
|
||||
if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
|
||||
/* Check if we are prepared to handle this fault */
|
||||
entry = search_exception_tables(regs->nip);
|
||||
if (entry) {
|
||||
pr_debug("RIO: %s - MC Exception handled\n",
|
||||
__func__);
|
||||
out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
|
||||
0);
|
||||
regs->msr |= MSR_RI;
|
||||
regs->nip = entry->fixup;
|
||||
return 1;
|
||||
}
|
||||
if (!rio_regs_win)
|
||||
return 0;
|
||||
|
||||
reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
|
||||
if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
|
||||
/* Check if we are prepared to handle this fault */
|
||||
entry = search_exception_tables(regs->nip);
|
||||
if (entry) {
|
||||
pr_debug("RIO: %s - MC Exception handled\n",
|
||||
__func__);
|
||||
out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
|
||||
0);
|
||||
regs->msr |= MSR_RI;
|
||||
regs->nip = entry->fixup;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <linux/pci.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <linux/ratelimit.h>
|
||||
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/signal.h>
|
||||
|
@ -1648,9 +1649,8 @@ static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg)
|
|||
return NO_IRQ;
|
||||
}
|
||||
if (unlikely(mpic->protected && test_bit(src, mpic->protected))) {
|
||||
if (printk_ratelimit())
|
||||
printk(KERN_WARNING "%s: Got protected source %d !\n",
|
||||
mpic->name, (int)src);
|
||||
printk_ratelimited(KERN_WARNING "%s: Got protected source %d !\n",
|
||||
mpic->name, (int)src);
|
||||
mpic_eoi(mpic);
|
||||
return NO_IRQ;
|
||||
}
|
||||
|
@ -1688,9 +1688,8 @@ unsigned int mpic_get_coreint_irq(void)
|
|||
return NO_IRQ;
|
||||
}
|
||||
if (unlikely(mpic->protected && test_bit(src, mpic->protected))) {
|
||||
if (printk_ratelimit())
|
||||
printk(KERN_WARNING "%s: Got protected source %d !\n",
|
||||
mpic->name, (int)src);
|
||||
printk_ratelimited(KERN_WARNING "%s: Got protected source %d !\n",
|
||||
mpic->name, (int)src);
|
||||
return NO_IRQ;
|
||||
}
|
||||
|
||||
|
|
|
@ -348,6 +348,7 @@ config CPU_SUBTYPE_SH7720
|
|||
select SYS_SUPPORTS_CMT
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_OHCI_SH if USB_OHCI_HCD
|
||||
help
|
||||
Select SH7720 if you have a SH3-DSP SH7720 CPU.
|
||||
|
||||
|
@ -357,6 +358,7 @@ config CPU_SUBTYPE_SH7721
|
|||
select CPU_HAS_DSP
|
||||
select SYS_SUPPORTS_CMT
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_OHCI_SH if USB_OHCI_HCD
|
||||
help
|
||||
Select SH7721 if you have a SH3-DSP SH7721 CPU.
|
||||
|
||||
|
@ -440,6 +442,7 @@ config CPU_SUBTYPE_SH7763
|
|||
bool "Support SH7763 processor"
|
||||
select CPU_SH4A
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_OHCI_SH if USB_OHCI_HCD
|
||||
help
|
||||
Select SH7763 if you have a SH4A SH7763(R5S77631) CPU.
|
||||
|
||||
|
@ -467,7 +470,9 @@ config CPU_SUBTYPE_SH7786
|
|||
select GENERIC_CLOCKEVENTS_BROADCAST if SMP
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_OHCI_SH if USB_OHCI_HCD
|
||||
select USB_ARCH_HAS_EHCI
|
||||
select USB_EHCI_SH if USB_EHCI_HCD
|
||||
|
||||
config CPU_SUBTYPE_SHX3
|
||||
bool "Support SH-X3 processor"
|
||||
|
|
|
@ -9,7 +9,6 @@ CONFIG_TASK_XACCT=y
|
|||
CONFIG_TASK_IO_ACCOUNTING=y
|
||||
CONFIG_LOG_BUF_SHIFT=14
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
|
||||
# CONFIG_SYSCTL_SYSCALL is not set
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
CONFIG_SLAB=y
|
||||
|
@ -39,8 +38,6 @@ CONFIG_IPV6=y
|
|||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
# CONFIG_FW_LOADER is not set
|
||||
CONFIG_MTD=y
|
||||
CONFIG_MTD_CONCAT=y
|
||||
CONFIG_MTD_PARTITIONS=y
|
||||
CONFIG_MTD_CHAR=y
|
||||
CONFIG_MTD_BLOCK=y
|
||||
CONFIG_MTD_M25P80=y
|
||||
|
@ -56,18 +53,19 @@ CONFIG_SH_ETH=y
|
|||
# CONFIG_KEYBOARD_ATKBD is not set
|
||||
# CONFIG_MOUSE_PS2 is not set
|
||||
# CONFIG_SERIO is not set
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
CONFIG_SERIAL_SH_SCI=y
|
||||
CONFIG_SERIAL_SH_SCI_NR_UARTS=3
|
||||
CONFIG_SERIAL_SH_SCI_CONSOLE=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_SH=y
|
||||
# CONFIG_HWMON is not set
|
||||
CONFIG_MFD_SH_MOBILE_SDHI=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_USB_EHCI_SH=y
|
||||
CONFIG_USB_OHCI_HCD=y
|
||||
CONFIG_USB_OHCI_SH=y
|
||||
CONFIG_USB_STORAGE=y
|
||||
CONFIG_MMC=y
|
||||
CONFIG_MMC_SDHI=y
|
||||
|
|
|
@ -183,7 +183,7 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_SCIF2_RX,
|
||||
.addr = 0x1f4b0014,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x22,
|
||||
},
|
||||
|
@ -197,7 +197,7 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_SCIF3_RX,
|
||||
.addr = 0x1f4c0014,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x2a,
|
||||
},
|
||||
|
@ -211,7 +211,7 @@ static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_SCIF4_RX,
|
||||
.addr = 0x1f4d0014,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x42,
|
||||
},
|
||||
|
@ -228,7 +228,7 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC0_RX,
|
||||
.addr = 0x1e500013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x22,
|
||||
},
|
||||
|
@ -242,7 +242,7 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC1_RX,
|
||||
.addr = 0x1e510013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x2a,
|
||||
},
|
||||
|
@ -256,7 +256,7 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC2_RX,
|
||||
.addr = 0x1e520013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0xa2,
|
||||
},
|
||||
|
@ -265,12 +265,12 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
|
|||
.addr = 0x1e530012,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0xab,
|
||||
.mid_rid = 0xa9,
|
||||
},
|
||||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC3_RX,
|
||||
.addr = 0x1e530013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0xaf,
|
||||
},
|
||||
|
@ -279,14 +279,14 @@ static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
|
|||
.addr = 0x1e540012,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0xc1,
|
||||
.mid_rid = 0xc5,
|
||||
},
|
||||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC4_RX,
|
||||
.addr = 0x1e540013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0xc2,
|
||||
.mid_rid = 0xc6,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -301,7 +301,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC5_RX,
|
||||
.addr = 0x1e550013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x22,
|
||||
},
|
||||
|
@ -315,7 +315,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC6_RX,
|
||||
.addr = 0x1e560013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x2a,
|
||||
},
|
||||
|
@ -329,7 +329,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC7_RX,
|
||||
.addr = 0x1e570013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x42,
|
||||
},
|
||||
|
@ -343,7 +343,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC8_RX,
|
||||
.addr = 0x1e580013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x46,
|
||||
},
|
||||
|
@ -357,7 +357,7 @@ static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
|
|||
{
|
||||
.slave_id = SHDMA_SLAVE_RIIC9_RX,
|
||||
.addr = 0x1e590013,
|
||||
.chcr = SM_INC | 0x800 | 0x40000000 |
|
||||
.chcr = DM_INC | 0x800 | 0x40000000 |
|
||||
TS_INDEX2VAL(XMIT_SZ_8BIT),
|
||||
.mid_rid = 0x52,
|
||||
},
|
||||
|
@ -659,6 +659,54 @@ static struct platform_device spi0_device = {
|
|||
.resource = spi0_resources,
|
||||
};
|
||||
|
||||
static struct resource usb_ehci_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xfe4f1000,
|
||||
.end = 0xfe4f10ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 57,
|
||||
.end = 57,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device usb_ehci_device = {
|
||||
.name = "sh_ehci",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &usb_ehci_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(usb_ehci_resources),
|
||||
.resource = usb_ehci_resources,
|
||||
};
|
||||
|
||||
static struct resource usb_ohci_resources[] = {
|
||||
[0] = {
|
||||
.start = 0xfe4f1800,
|
||||
.end = 0xfe4f18ff,
|
||||
.flags = IORESOURCE_MEM,
|
||||
},
|
||||
[1] = {
|
||||
.start = 57,
|
||||
.end = 57,
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
};
|
||||
|
||||
static struct platform_device usb_ohci_device = {
|
||||
.name = "sh_ohci",
|
||||
.id = -1,
|
||||
.dev = {
|
||||
.dma_mask = &usb_ohci_device.dev.coherent_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
},
|
||||
.num_resources = ARRAY_SIZE(usb_ohci_resources),
|
||||
.resource = usb_ohci_resources,
|
||||
};
|
||||
|
||||
static struct platform_device *sh7757_devices[] __initdata = {
|
||||
&scif2_device,
|
||||
&scif3_device,
|
||||
|
@ -670,6 +718,8 @@ static struct platform_device *sh7757_devices[] __initdata = {
|
|||
&dma2_device,
|
||||
&dma3_device,
|
||||
&spi0_device,
|
||||
&usb_ehci_device,
|
||||
&usb_ohci_device,
|
||||
};
|
||||
|
||||
static int __init sh7757_devices_setup(void)
|
||||
|
@ -1039,13 +1089,13 @@ static DECLARE_INTC_DESC(intc_desc, "sh7757", vectors, groups,
|
|||
|
||||
/* Support for external interrupt pins in IRQ mode */
|
||||
static struct intc_vect vectors_irq0123[] __initdata = {
|
||||
INTC_VECT(IRQ0, 0x240), INTC_VECT(IRQ1, 0x280),
|
||||
INTC_VECT(IRQ2, 0x2c0), INTC_VECT(IRQ3, 0x300),
|
||||
INTC_VECT(IRQ0, 0x200), INTC_VECT(IRQ1, 0x240),
|
||||
INTC_VECT(IRQ2, 0x280), INTC_VECT(IRQ3, 0x2c0),
|
||||
};
|
||||
|
||||
static struct intc_vect vectors_irq4567[] __initdata = {
|
||||
INTC_VECT(IRQ4, 0x340), INTC_VECT(IRQ5, 0x380),
|
||||
INTC_VECT(IRQ6, 0x3c0), INTC_VECT(IRQ7, 0x200),
|
||||
INTC_VECT(IRQ4, 0x300), INTC_VECT(IRQ5, 0x340),
|
||||
INTC_VECT(IRQ6, 0x380), INTC_VECT(IRQ7, 0x3c0),
|
||||
};
|
||||
|
||||
static struct intc_sense_reg sense_registers[] __initdata = {
|
||||
|
@ -1079,14 +1129,14 @@ static struct intc_vect vectors_irl0123[] __initdata = {
|
|||
};
|
||||
|
||||
static struct intc_vect vectors_irl4567[] __initdata = {
|
||||
INTC_VECT(IRL4_LLLL, 0xb00), INTC_VECT(IRL4_LLLH, 0xb20),
|
||||
INTC_VECT(IRL4_LLHL, 0xb40), INTC_VECT(IRL4_LLHH, 0xb60),
|
||||
INTC_VECT(IRL4_LHLL, 0xb80), INTC_VECT(IRL4_LHLH, 0xba0),
|
||||
INTC_VECT(IRL4_LHHL, 0xbc0), INTC_VECT(IRL4_LHHH, 0xbe0),
|
||||
INTC_VECT(IRL4_HLLL, 0xc00), INTC_VECT(IRL4_HLLH, 0xc20),
|
||||
INTC_VECT(IRL4_HLHL, 0xc40), INTC_VECT(IRL4_HLHH, 0xc60),
|
||||
INTC_VECT(IRL4_HHLL, 0xc80), INTC_VECT(IRL4_HHLH, 0xca0),
|
||||
INTC_VECT(IRL4_HHHL, 0xcc0),
|
||||
INTC_VECT(IRL4_LLLL, 0x200), INTC_VECT(IRL4_LLLH, 0x220),
|
||||
INTC_VECT(IRL4_LLHL, 0x240), INTC_VECT(IRL4_LLHH, 0x260),
|
||||
INTC_VECT(IRL4_LHLL, 0x280), INTC_VECT(IRL4_LHLH, 0x2a0),
|
||||
INTC_VECT(IRL4_LHHL, 0x2c0), INTC_VECT(IRL4_LHHH, 0x2e0),
|
||||
INTC_VECT(IRL4_HLLL, 0x300), INTC_VECT(IRL4_HLLH, 0x320),
|
||||
INTC_VECT(IRL4_HLHL, 0x340), INTC_VECT(IRL4_HLHH, 0x360),
|
||||
INTC_VECT(IRL4_HHLL, 0x380), INTC_VECT(IRL4_HHLH, 0x3a0),
|
||||
INTC_VECT(IRL4_HHHL, 0x3c0),
|
||||
};
|
||||
|
||||
static DECLARE_INTC_DESC(intc_desc_irl0123, "sh7757-irl0123", vectors_irl0123,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <asm/processor.h>
|
||||
#include <asm/machvec.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -268,9 +269,8 @@ void migrate_irqs(void)
|
|||
unsigned int newcpu = cpumask_any_and(data->affinity,
|
||||
cpu_online_mask);
|
||||
if (newcpu >= nr_cpu_ids) {
|
||||
if (printk_ratelimit())
|
||||
printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n",
|
||||
irq, cpu);
|
||||
pr_info_ratelimited("IRQ%u no longer affine to CPU%u\n",
|
||||
irq, cpu);
|
||||
|
||||
cpumask_setall(data->affinity);
|
||||
newcpu = cpumask_any_and(data->affinity,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <asm/alignment.h>
|
||||
#include <asm/processor.h>
|
||||
|
||||
|
@ -95,13 +96,13 @@ int set_unalign_ctl(struct task_struct *tsk, unsigned int val)
|
|||
void unaligned_fixups_notify(struct task_struct *tsk, insn_size_t insn,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
if (user_mode(regs) && (se_usermode & UM_WARN) && printk_ratelimit())
|
||||
pr_notice("Fixing up unaligned userspace access "
|
||||
if (user_mode(regs) && (se_usermode & UM_WARN))
|
||||
pr_notice_ratelimited("Fixing up unaligned userspace access "
|
||||
"in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
|
||||
tsk->comm, task_pid_nr(tsk),
|
||||
(void *)instruction_pointer(regs), insn);
|
||||
else if (se_kernmode_warn && printk_ratelimit())
|
||||
pr_notice("Fixing up unaligned kernel access "
|
||||
else if (se_kernmode_warn)
|
||||
pr_notice_ratelimited("Fixing up unaligned kernel access "
|
||||
"in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n",
|
||||
tsk->comm, task_pid_nr(tsk),
|
||||
(void *)instruction_pointer(regs), insn);
|
||||
|
|
|
@ -62,7 +62,7 @@ extern int sfi_mtimer_num;
|
|||
#else /* CONFIG_APB_TIMER */
|
||||
|
||||
static inline unsigned long apbt_quick_calibrate(void) {return 0; }
|
||||
static inline void apbt_time_init(void) {return 0; }
|
||||
static inline void apbt_time_init(void) { }
|
||||
|
||||
#endif
|
||||
#endif /* ASM_X86_APBT_H */
|
||||
|
|
|
@ -3372,7 +3372,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
|
|||
int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
|
||||
bool op_prefix = false;
|
||||
struct opcode opcode;
|
||||
struct operand memop = { .type = OP_NONE };
|
||||
struct operand memop = { .type = OP_NONE }, *memopp = NULL;
|
||||
|
||||
c->eip = ctxt->eip;
|
||||
c->fetch.start = c->eip;
|
||||
|
@ -3547,9 +3547,6 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
|
|||
if (memop.type == OP_MEM && c->ad_bytes != 8)
|
||||
memop.addr.mem.ea = (u32)memop.addr.mem.ea;
|
||||
|
||||
if (memop.type == OP_MEM && c->rip_relative)
|
||||
memop.addr.mem.ea += c->eip;
|
||||
|
||||
/*
|
||||
* Decode and fetch the source operand: register, memory
|
||||
* or immediate.
|
||||
|
@ -3571,6 +3568,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
|
|||
c->op_bytes;
|
||||
srcmem_common:
|
||||
c->src = memop;
|
||||
memopp = &c->src;
|
||||
break;
|
||||
case SrcImmU16:
|
||||
rc = decode_imm(ctxt, &c->src, 2, false);
|
||||
|
@ -3667,6 +3665,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
|
|||
case DstMem:
|
||||
case DstMem64:
|
||||
c->dst = memop;
|
||||
memopp = &c->dst;
|
||||
if ((c->d & DstMask) == DstMem64)
|
||||
c->dst.bytes = 8;
|
||||
else
|
||||
|
@ -3700,10 +3699,13 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
|
|||
/* Special instructions do their own operand decoding. */
|
||||
default:
|
||||
c->dst.type = OP_NONE; /* Disable writeback. */
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
if (memopp && memopp->type == OP_MEM && c->rip_relative)
|
||||
memopp->addr.mem.ea += c->eip;
|
||||
|
||||
return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -333,6 +333,7 @@ static int xen_register_pirq(u32 gsi, int triggering)
|
|||
struct physdev_map_pirq map_irq;
|
||||
int shareable = 0;
|
||||
char *name;
|
||||
bool gsi_override = false;
|
||||
|
||||
if (!xen_pv_domain())
|
||||
return -1;
|
||||
|
@ -349,11 +350,32 @@ static int xen_register_pirq(u32 gsi, int triggering)
|
|||
if (pirq < 0)
|
||||
goto out;
|
||||
|
||||
irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
|
||||
/* Before we bind the GSI to a Linux IRQ, check whether
|
||||
* we need to override it with bus_irq (IRQ) value. Usually for
|
||||
* IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
|
||||
* ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
|
||||
* but there are oddballs where the IRQ != GSI:
|
||||
* ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
|
||||
* which ends up being: gsi_to_irq[9] == 20
|
||||
* (which is what acpi_gsi_to_irq ends up calling when starting the
|
||||
* the ACPI interpreter and keels over since IRQ 9 has not been
|
||||
* setup as we had setup IRQ 20 for it).
|
||||
*/
|
||||
if (gsi == acpi_sci_override_gsi) {
|
||||
/* Check whether the GSI != IRQ */
|
||||
acpi_gsi_to_irq(gsi, &irq);
|
||||
if (irq != gsi)
|
||||
/* Bugger, we MUST have that IRQ. */
|
||||
gsi_override = true;
|
||||
}
|
||||
if (gsi_override)
|
||||
irq = xen_bind_pirq_gsi_to_irq(irq, pirq, shareable, name);
|
||||
else
|
||||
irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
|
||||
if (irq < 0)
|
||||
goto out;
|
||||
|
||||
printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d\n", pirq, irq);
|
||||
printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi);
|
||||
|
||||
map_irq.domid = DOMID_SELF;
|
||||
map_irq.type = MAP_PIRQ_TYPE_GSI;
|
||||
|
|
|
@ -1232,7 +1232,11 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
|
|||
{
|
||||
struct {
|
||||
struct mmuext_op op;
|
||||
#ifdef CONFIG_SMP
|
||||
DECLARE_BITMAP(mask, num_processors);
|
||||
#else
|
||||
DECLARE_BITMAP(mask, NR_CPUS);
|
||||
#endif
|
||||
} *args;
|
||||
struct multicall_space mcs;
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#define DEFLATE_DEF_LEVEL Z_DEFAULT_COMPRESSION
|
||||
#define DEFLATE_DEF_WINBITS 11
|
||||
|
@ -73,7 +72,7 @@ static int deflate_decomp_init(struct deflate_ctx *ctx)
|
|||
int ret = 0;
|
||||
struct z_stream_s *stream = &ctx->decomp_stream;
|
||||
|
||||
stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
|
||||
stream->workspace = vzalloc(zlib_inflate_workspacesize());
|
||||
if (!stream->workspace) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -86,7 +85,7 @@ static int deflate_decomp_init(struct deflate_ctx *ctx)
|
|||
out:
|
||||
return ret;
|
||||
out_free:
|
||||
kfree(stream->workspace);
|
||||
vfree(stream->workspace);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -99,7 +98,7 @@ static void deflate_comp_exit(struct deflate_ctx *ctx)
|
|||
static void deflate_decomp_exit(struct deflate_ctx *ctx)
|
||||
{
|
||||
zlib_inflateEnd(&ctx->decomp_stream);
|
||||
kfree(ctx->decomp_stream.workspace);
|
||||
vfree(ctx->decomp_stream.workspace);
|
||||
}
|
||||
|
||||
static int deflate_init(struct crypto_tfm *tfm)
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <crypto/internal/compress.h>
|
||||
|
||||
|
@ -60,7 +59,7 @@ static void zlib_decomp_exit(struct zlib_ctx *ctx)
|
|||
|
||||
if (stream->workspace) {
|
||||
zlib_inflateEnd(stream);
|
||||
kfree(stream->workspace);
|
||||
vfree(stream->workspace);
|
||||
stream->workspace = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -228,13 +227,13 @@ static int zlib_decompress_setup(struct crypto_pcomp *tfm, void *params,
|
|||
? nla_get_u32(tb[ZLIB_DECOMP_WINDOWBITS])
|
||||
: DEF_WBITS;
|
||||
|
||||
stream->workspace = kzalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
|
||||
stream->workspace = vzalloc(zlib_inflate_workspacesize());
|
||||
if (!stream->workspace)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = zlib_inflateInit2(stream, ctx->decomp_windowBits);
|
||||
if (ret != Z_OK) {
|
||||
kfree(stream->workspace);
|
||||
vfree(stream->workspace);
|
||||
stream->workspace = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
|
|
@ -452,7 +452,7 @@ void ahci_save_initial_config(struct device *dev,
|
|||
}
|
||||
|
||||
if (mask_port_map) {
|
||||
dev_printk(KERN_ERR, dev, "masking port_map 0x%x -> 0x%x\n",
|
||||
dev_printk(KERN_WARNING, dev, "masking port_map 0x%x -> 0x%x\n",
|
||||
port_map,
|
||||
port_map & mask_port_map);
|
||||
port_map &= mask_port_map;
|
||||
|
|
|
@ -238,9 +238,9 @@ static int build_sh_desc_ipsec(struct caam_ctx *ctx)
|
|||
|
||||
/* build shared descriptor for this session */
|
||||
sh_desc = kmalloc(CAAM_CMD_SZ * DESC_AEAD_SHARED_TEXT_LEN +
|
||||
keys_fit_inline ?
|
||||
ctx->split_key_pad_len + ctx->enckeylen :
|
||||
CAAM_PTR_SZ * 2, GFP_DMA | GFP_KERNEL);
|
||||
(keys_fit_inline ?
|
||||
ctx->split_key_pad_len + ctx->enckeylen :
|
||||
CAAM_PTR_SZ * 2), GFP_DMA | GFP_KERNEL);
|
||||
if (!sh_desc) {
|
||||
dev_err(jrdev, "could not allocate shared descriptor\n");
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -50,7 +50,6 @@ struct intel_dp {
|
|||
bool has_audio;
|
||||
int force_audio;
|
||||
uint32_t color_range;
|
||||
int dpms_mode;
|
||||
uint8_t link_bw;
|
||||
uint8_t lane_count;
|
||||
uint8_t dpcd[4];
|
||||
|
@ -138,8 +137,8 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp)
|
|||
{
|
||||
int max_lane_count = 4;
|
||||
|
||||
if (intel_dp->dpcd[0] >= 0x11) {
|
||||
max_lane_count = intel_dp->dpcd[2] & 0x1f;
|
||||
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
|
||||
max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
|
||||
switch (max_lane_count) {
|
||||
case 1: case 2: case 4:
|
||||
break;
|
||||
|
@ -153,7 +152,7 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp)
|
|||
static int
|
||||
intel_dp_max_link_bw(struct intel_dp *intel_dp)
|
||||
{
|
||||
int max_link_bw = intel_dp->dpcd[1];
|
||||
int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
|
||||
|
||||
switch (max_link_bw) {
|
||||
case DP_LINK_BW_1_62:
|
||||
|
@ -775,7 +774,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
|
|||
/*
|
||||
* Check for DPCD version > 1.1 and enhanced framing support
|
||||
*/
|
||||
if (intel_dp->dpcd[0] >= 0x11 && (intel_dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)) {
|
||||
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
|
||||
(intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
|
||||
intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
|
||||
intel_dp->DP |= DP_ENHANCED_FRAMING;
|
||||
}
|
||||
|
@ -943,11 +943,44 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder)
|
|||
udelay(200);
|
||||
}
|
||||
|
||||
/* If the sink supports it, try to set the power state appropriately */
|
||||
static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
/* Should have a valid DPCD by this point */
|
||||
if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
|
||||
return;
|
||||
|
||||
if (mode != DRM_MODE_DPMS_ON) {
|
||||
ret = intel_dp_aux_native_write_1(intel_dp, DP_SET_POWER,
|
||||
DP_SET_POWER_D3);
|
||||
if (ret != 1)
|
||||
DRM_DEBUG_DRIVER("failed to write sink power state\n");
|
||||
} else {
|
||||
/*
|
||||
* When turning on, we need to retry for 1ms to give the sink
|
||||
* time to wake up.
|
||||
*/
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = intel_dp_aux_native_write_1(intel_dp,
|
||||
DP_SET_POWER,
|
||||
DP_SET_POWER_D0);
|
||||
if (ret == 1)
|
||||
break;
|
||||
msleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void intel_dp_prepare(struct drm_encoder *encoder)
|
||||
{
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
struct drm_device *dev = encoder->dev;
|
||||
|
||||
/* Wake up the sink first */
|
||||
intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
|
||||
|
||||
if (is_edp(intel_dp)) {
|
||||
ironlake_edp_backlight_off(dev);
|
||||
ironlake_edp_panel_off(dev);
|
||||
|
@ -991,6 +1024,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
|||
if (mode != DRM_MODE_DPMS_ON) {
|
||||
if (is_edp(intel_dp))
|
||||
ironlake_edp_backlight_off(dev);
|
||||
intel_dp_sink_dpms(intel_dp, mode);
|
||||
intel_dp_link_down(intel_dp);
|
||||
if (is_edp(intel_dp))
|
||||
ironlake_edp_panel_off(dev);
|
||||
|
@ -999,6 +1033,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
|||
} else {
|
||||
if (is_edp(intel_dp))
|
||||
ironlake_edp_panel_vdd_on(intel_dp);
|
||||
intel_dp_sink_dpms(intel_dp, mode);
|
||||
if (!(dp_reg & DP_PORT_EN)) {
|
||||
intel_dp_start_link_train(intel_dp);
|
||||
if (is_edp(intel_dp)) {
|
||||
|
@ -1010,7 +1045,31 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
|||
if (is_edp(intel_dp))
|
||||
ironlake_edp_backlight_on(dev);
|
||||
}
|
||||
intel_dp->dpms_mode = mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Native read with retry for link status and receiver capability reads for
|
||||
* cases where the sink may still be asleep.
|
||||
*/
|
||||
static bool
|
||||
intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address,
|
||||
uint8_t *recv, int recv_bytes)
|
||||
{
|
||||
int ret, i;
|
||||
|
||||
/*
|
||||
* Sinks are *supposed* to come up within 1ms from an off state,
|
||||
* but we're also supposed to retry 3 times per the spec.
|
||||
*/
|
||||
for (i = 0; i < 3; i++) {
|
||||
ret = intel_dp_aux_native_read(intel_dp, address, recv,
|
||||
recv_bytes);
|
||||
if (ret == recv_bytes)
|
||||
return true;
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1020,14 +1079,10 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
|
|||
static bool
|
||||
intel_dp_get_link_status(struct intel_dp *intel_dp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = intel_dp_aux_native_read(intel_dp,
|
||||
DP_LANE0_1_STATUS,
|
||||
intel_dp->link_status, DP_LINK_STATUS_SIZE);
|
||||
if (ret != DP_LINK_STATUS_SIZE)
|
||||
return false;
|
||||
return true;
|
||||
return intel_dp_aux_native_read_retry(intel_dp,
|
||||
DP_LANE0_1_STATUS,
|
||||
intel_dp->link_status,
|
||||
DP_LINK_STATUS_SIZE);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
|
@ -1516,6 +1571,8 @@ intel_dp_link_down(struct intel_dp *intel_dp)
|
|||
static void
|
||||
intel_dp_check_link_status(struct intel_dp *intel_dp)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!intel_dp->base.base.crtc)
|
||||
return;
|
||||
|
||||
|
@ -1524,6 +1581,15 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Try to read receiver status if the link appears to be up */
|
||||
ret = intel_dp_aux_native_read(intel_dp,
|
||||
0x000, intel_dp->dpcd,
|
||||
sizeof (intel_dp->dpcd));
|
||||
if (ret != sizeof(intel_dp->dpcd)) {
|
||||
intel_dp_link_down(intel_dp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!intel_channel_eq_ok(intel_dp)) {
|
||||
intel_dp_start_link_train(intel_dp);
|
||||
intel_dp_complete_link_train(intel_dp);
|
||||
|
@ -1534,6 +1600,7 @@ static enum drm_connector_status
|
|||
ironlake_dp_detect(struct intel_dp *intel_dp)
|
||||
{
|
||||
enum drm_connector_status status;
|
||||
bool ret;
|
||||
|
||||
/* Can't disconnect eDP, but you can close the lid... */
|
||||
if (is_edp(intel_dp)) {
|
||||
|
@ -1544,13 +1611,11 @@ ironlake_dp_detect(struct intel_dp *intel_dp)
|
|||
}
|
||||
|
||||
status = connector_status_disconnected;
|
||||
if (intel_dp_aux_native_read(intel_dp,
|
||||
0x000, intel_dp->dpcd,
|
||||
sizeof (intel_dp->dpcd))
|
||||
== sizeof(intel_dp->dpcd)) {
|
||||
if (intel_dp->dpcd[0] != 0)
|
||||
status = connector_status_connected;
|
||||
}
|
||||
ret = intel_dp_aux_native_read_retry(intel_dp,
|
||||
0x000, intel_dp->dpcd,
|
||||
sizeof (intel_dp->dpcd));
|
||||
if (ret && intel_dp->dpcd[DP_DPCD_REV] != 0)
|
||||
status = connector_status_connected;
|
||||
DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0],
|
||||
intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]);
|
||||
return status;
|
||||
|
@ -1587,7 +1652,7 @@ g4x_dp_detect(struct intel_dp *intel_dp)
|
|||
if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd,
|
||||
sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))
|
||||
{
|
||||
if (intel_dp->dpcd[0] != 0)
|
||||
if (intel_dp->dpcd[DP_DPCD_REV] != 0)
|
||||
status = connector_status_connected;
|
||||
}
|
||||
|
||||
|
@ -1791,8 +1856,7 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder)
|
|||
{
|
||||
struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base);
|
||||
|
||||
if (intel_dp->dpms_mode == DRM_MODE_DPMS_ON)
|
||||
intel_dp_check_link_status(intel_dp);
|
||||
intel_dp_check_link_status(intel_dp);
|
||||
}
|
||||
|
||||
/* Return which DP Port should be selected for Transcoder DP control */
|
||||
|
@ -1860,7 +1924,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
|||
return;
|
||||
|
||||
intel_dp->output_reg = output_reg;
|
||||
intel_dp->dpms_mode = -1;
|
||||
|
||||
intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
|
||||
if (!intel_connector) {
|
||||
|
@ -1955,8 +2018,9 @@ intel_dp_init(struct drm_device *dev, int output_reg)
|
|||
sizeof(intel_dp->dpcd));
|
||||
ironlake_edp_panel_vdd_off(intel_dp);
|
||||
if (ret == sizeof(intel_dp->dpcd)) {
|
||||
if (intel_dp->dpcd[0] >= 0x11)
|
||||
dev_priv->no_aux_handshake = intel_dp->dpcd[3] &
|
||||
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
|
||||
dev_priv->no_aux_handshake =
|
||||
intel_dp->dpcd[DP_MAX_DOWNSPREAD] &
|
||||
DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
|
||||
} else {
|
||||
/* if this fails, presume the device is a ghost */
|
||||
|
|
|
@ -371,7 +371,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
|||
engine->vram.flags_valid = nv50_vram_flags_valid;
|
||||
break;
|
||||
case 0xC0:
|
||||
case 0xD0:
|
||||
engine->instmem.init = nvc0_instmem_init;
|
||||
engine->instmem.takedown = nvc0_instmem_takedown;
|
||||
engine->instmem.suspend = nvc0_instmem_suspend;
|
||||
|
@ -923,7 +922,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
|
|||
dev_priv->card_type = NV_50;
|
||||
break;
|
||||
case 0xc0:
|
||||
case 0xd0:
|
||||
dev_priv->card_type = NV_C0;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -2248,7 +2248,10 @@ int evergreen_mc_init(struct radeon_device *rdev)
|
|||
|
||||
/* Get VRAM informations */
|
||||
rdev->mc.vram_is_ddr = true;
|
||||
tmp = RREG32(MC_ARB_RAMCFG);
|
||||
if (rdev->flags & RADEON_IS_IGP)
|
||||
tmp = RREG32(FUS_MC_ARB_RAMCFG);
|
||||
else
|
||||
tmp = RREG32(MC_ARB_RAMCFG);
|
||||
if (tmp & CHANSIZE_OVERRIDE) {
|
||||
chansize = 16;
|
||||
} else if (tmp & CHANSIZE_MASK) {
|
||||
|
|
|
@ -320,7 +320,7 @@
|
|||
#define CGTS_USER_TCC_DISABLE 0x914C
|
||||
#define TCC_DISABLE_MASK 0xFFFF0000
|
||||
#define TCC_DISABLE_SHIFT 16
|
||||
#define CGTS_SM_CTRL_REG 0x915C
|
||||
#define CGTS_SM_CTRL_REG 0x9150
|
||||
#define OVERRIDE (1 << 21)
|
||||
|
||||
#define TA_CNTL_AUX 0x9508
|
||||
|
|
|
@ -104,7 +104,7 @@ static bool radeon_read_bios(struct radeon_device *rdev)
|
|||
static bool radeon_atrm_get_bios(struct radeon_device *rdev)
|
||||
{
|
||||
int ret;
|
||||
int size = 64 * 1024;
|
||||
int size = 256 * 1024;
|
||||
int i;
|
||||
|
||||
if (!radeon_atrm_supported(rdev->pdev))
|
||||
|
|
|
@ -575,6 +575,12 @@ static void rv770_program_channel_remap(struct radeon_device *rdev)
|
|||
else
|
||||
tcp_chan_steer = 0x00fac688;
|
||||
|
||||
/* RV770 CE has special chremap setup */
|
||||
if (rdev->pdev->device == 0x944e) {
|
||||
tcp_chan_steer = 0x00b08b08;
|
||||
mc_shared_chremap = 0x00b08b08;
|
||||
}
|
||||
|
||||
WREG32(TCP_CHAN_STEER, tcp_chan_steer);
|
||||
WREG32(MC_SHARED_CHREMAP, mc_shared_chremap);
|
||||
}
|
||||
|
|
|
@ -333,7 +333,7 @@ config SENSORS_F71882FG
|
|||
F71858FG
|
||||
F71862FG
|
||||
F71863FG
|
||||
F71869F/E
|
||||
F71869F/E/A
|
||||
F71882FG
|
||||
F71883FG
|
||||
F71889FG/ED/A
|
||||
|
|
|
@ -32,6 +32,7 @@ static int adm1275_probe(struct i2c_client *client,
|
|||
const struct i2c_device_id *id)
|
||||
{
|
||||
int config;
|
||||
int ret;
|
||||
struct pmbus_driver_info *info;
|
||||
|
||||
if (!i2c_check_functionality(client->adapter,
|
||||
|
@ -43,8 +44,10 @@ static int adm1275_probe(struct i2c_client *client,
|
|||
return -ENOMEM;
|
||||
|
||||
config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG);
|
||||
if (config < 0)
|
||||
return config;
|
||||
if (config < 0) {
|
||||
ret = config;
|
||||
goto err_mem;
|
||||
}
|
||||
|
||||
info->pages = 1;
|
||||
info->direct[PSC_VOLTAGE_IN] = true;
|
||||
|
@ -76,7 +79,14 @@ static int adm1275_probe(struct i2c_client *client,
|
|||
else
|
||||
info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT;
|
||||
|
||||
return pmbus_do_probe(client, id, info);
|
||||
ret = pmbus_do_probe(client, id, info);
|
||||
if (ret)
|
||||
goto err_mem;
|
||||
return 0;
|
||||
|
||||
err_mem:
|
||||
kfree(info);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int adm1275_remove(struct i2c_client *client)
|
||||
|
|
|
@ -78,8 +78,9 @@ static u16 emc6w201_read16(struct i2c_client *client, u8 reg)
|
|||
|
||||
lsb = i2c_smbus_read_byte_data(client, reg);
|
||||
msb = i2c_smbus_read_byte_data(client, reg + 1);
|
||||
if (lsb < 0 || msb < 0) {
|
||||
dev_err(&client->dev, "16-bit read failed at 0x%02x\n", reg);
|
||||
if (unlikely(lsb < 0 || msb < 0)) {
|
||||
dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
|
||||
16, "read", reg);
|
||||
return 0xFFFF; /* Arbitrary value */
|
||||
}
|
||||
|
||||
|
@ -95,10 +96,39 @@ static int emc6w201_write16(struct i2c_client *client, u8 reg, u16 val)
|
|||
int err;
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, reg, val & 0xff);
|
||||
if (!err)
|
||||
if (likely(!err))
|
||||
err = i2c_smbus_write_byte_data(client, reg + 1, val >> 8);
|
||||
if (err < 0)
|
||||
dev_err(&client->dev, "16-bit write failed at 0x%02x\n", reg);
|
||||
if (unlikely(err < 0))
|
||||
dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
|
||||
16, "write", reg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Read 8-bit value from register */
|
||||
static u8 emc6w201_read8(struct i2c_client *client, u8 reg)
|
||||
{
|
||||
int val;
|
||||
|
||||
val = i2c_smbus_read_byte_data(client, reg);
|
||||
if (unlikely(val < 0)) {
|
||||
dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
|
||||
8, "read", reg);
|
||||
return 0x00; /* Arbitrary value */
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Write 8-bit value to register */
|
||||
static int emc6w201_write8(struct i2c_client *client, u8 reg, u8 val)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = i2c_smbus_write_byte_data(client, reg, val);
|
||||
if (unlikely(err < 0))
|
||||
dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
|
||||
8, "write", reg);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -114,25 +144,25 @@ static struct emc6w201_data *emc6w201_update_device(struct device *dev)
|
|||
if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
|
||||
for (nr = 0; nr < 6; nr++) {
|
||||
data->in[input][nr] =
|
||||
i2c_smbus_read_byte_data(client,
|
||||
emc6w201_read8(client,
|
||||
EMC6W201_REG_IN(nr));
|
||||
data->in[min][nr] =
|
||||
i2c_smbus_read_byte_data(client,
|
||||
emc6w201_read8(client,
|
||||
EMC6W201_REG_IN_LOW(nr));
|
||||
data->in[max][nr] =
|
||||
i2c_smbus_read_byte_data(client,
|
||||
emc6w201_read8(client,
|
||||
EMC6W201_REG_IN_HIGH(nr));
|
||||
}
|
||||
|
||||
for (nr = 0; nr < 6; nr++) {
|
||||
data->temp[input][nr] =
|
||||
i2c_smbus_read_byte_data(client,
|
||||
emc6w201_read8(client,
|
||||
EMC6W201_REG_TEMP(nr));
|
||||
data->temp[min][nr] =
|
||||
i2c_smbus_read_byte_data(client,
|
||||
emc6w201_read8(client,
|
||||
EMC6W201_REG_TEMP_LOW(nr));
|
||||
data->temp[max][nr] =
|
||||
i2c_smbus_read_byte_data(client,
|
||||
emc6w201_read8(client,
|
||||
EMC6W201_REG_TEMP_HIGH(nr));
|
||||
}
|
||||
|
||||
|
@ -192,7 +222,7 @@ static ssize_t set_in(struct device *dev, struct device_attribute *devattr,
|
|||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->in[sf][nr] = SENSORS_LIMIT(val, 0, 255);
|
||||
err = i2c_smbus_write_byte_data(client, reg, data->in[sf][nr]);
|
||||
err = emc6w201_write8(client, reg, data->in[sf][nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return err < 0 ? err : count;
|
||||
|
@ -229,7 +259,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
|
|||
|
||||
mutex_lock(&data->update_lock);
|
||||
data->temp[sf][nr] = SENSORS_LIMIT(val, -127, 128);
|
||||
err = i2c_smbus_write_byte_data(client, reg, data->temp[sf][nr]);
|
||||
err = emc6w201_write8(client, reg, data->temp[sf][nr]);
|
||||
mutex_unlock(&data->update_lock);
|
||||
|
||||
return err < 0 ? err : count;
|
||||
|
@ -444,7 +474,7 @@ static int emc6w201_detect(struct i2c_client *client,
|
|||
|
||||
/* Check configuration */
|
||||
config = i2c_smbus_read_byte_data(client, EMC6W201_REG_CONFIG);
|
||||
if ((config & 0xF4) != 0x04)
|
||||
if (config < 0 || (config & 0xF4) != 0x04)
|
||||
return -ENODEV;
|
||||
if (!(config & 0x01)) {
|
||||
dev_err(&client->dev, "Monitoring not enabled\n");
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#define SIO_F71858_ID 0x0507 /* Chipset ID */
|
||||
#define SIO_F71862_ID 0x0601 /* Chipset ID */
|
||||
#define SIO_F71869_ID 0x0814 /* Chipset ID */
|
||||
#define SIO_F71869A_ID 0x1007 /* Chipset ID */
|
||||
#define SIO_F71882_ID 0x0541 /* Chipset ID */
|
||||
#define SIO_F71889_ID 0x0723 /* Chipset ID */
|
||||
#define SIO_F71889E_ID 0x0909 /* Chipset ID */
|
||||
|
@ -108,8 +109,8 @@ static unsigned short force_id;
|
|||
module_param(force_id, ushort, 0);
|
||||
MODULE_PARM_DESC(force_id, "Override the detected device ID");
|
||||
|
||||
enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71882fg, f71889fg,
|
||||
f71889ed, f71889a, f8000, f81865f };
|
||||
enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71869a, f71882fg,
|
||||
f71889fg, f71889ed, f71889a, f8000, f81865f };
|
||||
|
||||
static const char *f71882fg_names[] = {
|
||||
"f71808e",
|
||||
|
@ -117,6 +118,7 @@ static const char *f71882fg_names[] = {
|
|||
"f71858fg",
|
||||
"f71862fg",
|
||||
"f71869", /* Both f71869f and f71869e, reg. compatible and same id */
|
||||
"f71869a",
|
||||
"f71882fg",
|
||||
"f71889fg", /* f81801u too, same id */
|
||||
"f71889ed",
|
||||
|
@ -131,6 +133,7 @@ static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
|
|||
[f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
|
||||
[f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71869a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
[f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
|
||||
|
@ -145,6 +148,7 @@ static const char f71882fg_has_in1_alarm[] = {
|
|||
[f71858fg] = 0,
|
||||
[f71862fg] = 0,
|
||||
[f71869] = 0,
|
||||
[f71869a] = 0,
|
||||
[f71882fg] = 1,
|
||||
[f71889fg] = 1,
|
||||
[f71889ed] = 1,
|
||||
|
@ -159,6 +163,7 @@ static const char f71882fg_fan_has_beep[] = {
|
|||
[f71858fg] = 0,
|
||||
[f71862fg] = 1,
|
||||
[f71869] = 1,
|
||||
[f71869a] = 1,
|
||||
[f71882fg] = 1,
|
||||
[f71889fg] = 1,
|
||||
[f71889ed] = 1,
|
||||
|
@ -173,6 +178,7 @@ static const char f71882fg_nr_fans[] = {
|
|||
[f71858fg] = 3,
|
||||
[f71862fg] = 3,
|
||||
[f71869] = 3,
|
||||
[f71869a] = 3,
|
||||
[f71882fg] = 4,
|
||||
[f71889fg] = 3,
|
||||
[f71889ed] = 3,
|
||||
|
@ -187,6 +193,7 @@ static const char f71882fg_temp_has_beep[] = {
|
|||
[f71858fg] = 0,
|
||||
[f71862fg] = 1,
|
||||
[f71869] = 1,
|
||||
[f71869a] = 1,
|
||||
[f71882fg] = 1,
|
||||
[f71889fg] = 1,
|
||||
[f71889ed] = 1,
|
||||
|
@ -201,6 +208,7 @@ static const char f71882fg_nr_temps[] = {
|
|||
[f71858fg] = 3,
|
||||
[f71862fg] = 3,
|
||||
[f71869] = 3,
|
||||
[f71869a] = 3,
|
||||
[f71882fg] = 3,
|
||||
[f71889fg] = 3,
|
||||
[f71889ed] = 3,
|
||||
|
@ -2243,6 +2251,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
|
|||
case f71808e:
|
||||
case f71808a:
|
||||
case f71869:
|
||||
case f71869a:
|
||||
/* These always have signed auto point temps */
|
||||
data->auto_point_temp_signed = 1;
|
||||
/* Fall through to select correct fan/pwm reg bank! */
|
||||
|
@ -2305,6 +2314,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
|
|||
case f71808e:
|
||||
case f71808a:
|
||||
case f71869:
|
||||
case f71869a:
|
||||
case f71889fg:
|
||||
case f71889ed:
|
||||
case f71889a:
|
||||
|
@ -2528,6 +2538,9 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
|
|||
case SIO_F71869_ID:
|
||||
sio_data->type = f71869;
|
||||
break;
|
||||
case SIO_F71869A_ID:
|
||||
sio_data->type = f71869a;
|
||||
break;
|
||||
case SIO_F71882_ID:
|
||||
sio_data->type = f71882fg;
|
||||
break;
|
||||
|
@ -2662,7 +2675,7 @@ static void __exit f71882fg_exit(void)
|
|||
}
|
||||
|
||||
MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver");
|
||||
MODULE_AUTHOR("Hans Edgington, Hans de Goede (hdegoede@redhat.com)");
|
||||
MODULE_AUTHOR("Hans Edgington, Hans de Goede <hdegoede@redhat.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(f71882fg_init);
|
||||
|
|
|
@ -202,7 +202,7 @@ static struct vrm_model vrm_models[] = {
|
|||
|
||||
{X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85}, /* Eden ESP/Ezra */
|
||||
{X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */
|
||||
{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nemiah */
|
||||
{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nehemiah */
|
||||
{X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M, Eden-N */
|
||||
{X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0}, /* No information */
|
||||
{X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13}, /* C7, Esther */
|
||||
|
|
|
@ -47,12 +47,14 @@ static void pmbus_find_sensor_groups(struct i2c_client *client,
|
|||
if (info->func[0]
|
||||
&& pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT))
|
||||
info->func[0] |= PMBUS_HAVE_STATUS_INPUT;
|
||||
if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
|
||||
if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) &&
|
||||
pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
|
||||
info->func[0] |= PMBUS_HAVE_FAN12;
|
||||
if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12))
|
||||
info->func[0] |= PMBUS_HAVE_STATUS_FAN12;
|
||||
}
|
||||
if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
|
||||
if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) &&
|
||||
pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
|
||||
info->func[0] |= PMBUS_HAVE_FAN34;
|
||||
if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34))
|
||||
info->func[0] |= PMBUS_HAVE_STATUS_FAN34;
|
||||
|
@ -63,6 +65,10 @@ static void pmbus_find_sensor_groups(struct i2c_client *client,
|
|||
PMBUS_STATUS_TEMPERATURE))
|
||||
info->func[0] |= PMBUS_HAVE_STATUS_TEMP;
|
||||
}
|
||||
if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2))
|
||||
info->func[0] |= PMBUS_HAVE_TEMP2;
|
||||
if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3))
|
||||
info->func[0] |= PMBUS_HAVE_TEMP3;
|
||||
|
||||
/* Sensors detected on all pages */
|
||||
for (page = 0; page < info->pages; page++) {
|
||||
|
|
|
@ -1430,14 +1430,9 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
|
|||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
|
||||
/*
|
||||
* Bail out if status register or PMBus revision register
|
||||
* does not exist.
|
||||
*/
|
||||
if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0
|
||||
|| i2c_smbus_read_byte_data(client, PMBUS_REVISION) < 0) {
|
||||
dev_err(&client->dev,
|
||||
"Status or revision register not found\n");
|
||||
/* Bail out if PMBus status register does not exist. */
|
||||
if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0) {
|
||||
dev_err(&client->dev, "PMBus status register not found\n");
|
||||
ret = -ENODEV;
|
||||
goto out_data;
|
||||
}
|
||||
|
|
|
@ -887,7 +887,7 @@ static void __exit sch5627_exit(void)
|
|||
}
|
||||
|
||||
MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver");
|
||||
MODULE_AUTHOR("Hans de Goede (hdegoede@redhat.com)");
|
||||
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(sch5627_init);
|
||||
|
|
|
@ -234,7 +234,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv)
|
|||
|
||||
if (taos->state != TAOS_STATE_IDLE) {
|
||||
err = -ENODEV;
|
||||
dev_dbg(&serio->dev, "TAOS EVM reset failed (state=%d, "
|
||||
dev_err(&serio->dev, "TAOS EVM reset failed (state=%d, "
|
||||
"pos=%d)\n", taos->state, taos->pos);
|
||||
goto exit_close;
|
||||
}
|
||||
|
@ -255,7 +255,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv)
|
|||
msecs_to_jiffies(250));
|
||||
if (taos->state != TAOS_STATE_IDLE) {
|
||||
err = -ENODEV;
|
||||
dev_err(&adapter->dev, "Echo off failed "
|
||||
dev_err(&serio->dev, "TAOS EVM echo off failed "
|
||||
"(state=%d)\n", taos->state);
|
||||
goto exit_close;
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv)
|
|||
err = i2c_add_adapter(adapter);
|
||||
if (err)
|
||||
goto exit_close;
|
||||
dev_dbg(&serio->dev, "Connected to TAOS EVM\n");
|
||||
dev_info(&serio->dev, "Connected to TAOS EVM\n");
|
||||
|
||||
taos->client = taos_instantiate_device(adapter);
|
||||
return 0;
|
||||
|
@ -288,7 +288,7 @@ static void taos_disconnect(struct serio *serio)
|
|||
serio_set_drvdata(serio, NULL);
|
||||
kfree(taos);
|
||||
|
||||
dev_dbg(&serio->dev, "Disconnected from TAOS EVM\n");
|
||||
dev_info(&serio->dev, "Disconnected from TAOS EVM\n");
|
||||
}
|
||||
|
||||
static struct serio_device_id taos_serio_ids[] = {
|
||||
|
|
|
@ -201,10 +201,11 @@ static int pca954x_probe(struct i2c_client *client,
|
|||
|
||||
i2c_set_clientdata(client, data);
|
||||
|
||||
/* Read the mux register at addr to verify
|
||||
* that the mux is in fact present.
|
||||
/* Write the mux register at addr to verify
|
||||
* that the mux is in fact present. This also
|
||||
* initializes the mux to disconnected state.
|
||||
*/
|
||||
if (i2c_smbus_read_byte(client) < 0) {
|
||||
if (i2c_smbus_write_byte(client, 0) < 0) {
|
||||
dev_warn(&client->dev, "probe failed\n");
|
||||
goto exit_free;
|
||||
}
|
||||
|
|
|
@ -3641,7 +3641,8 @@ static struct kobj_type cm_port_obj_type = {
|
|||
|
||||
static char *cm_devnode(struct device *dev, mode_t *mode)
|
||||
{
|
||||
*mode = 0666;
|
||||
if (mode)
|
||||
*mode = 0666;
|
||||
return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev));
|
||||
}
|
||||
|
||||
|
|
|
@ -826,7 +826,8 @@ static void ib_uverbs_remove_one(struct ib_device *device)
|
|||
|
||||
static char *uverbs_devnode(struct device *dev, mode_t *mode)
|
||||
{
|
||||
*mode = 0666;
|
||||
if (mode)
|
||||
*mode = 0666;
|
||||
return kasprintf(GFP_KERNEL, "infiniband/%s", dev_name(dev));
|
||||
}
|
||||
|
||||
|
|
|
@ -339,9 +339,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
|
|||
(FIR_OP_UA << FIR_OP1_SHIFT) |
|
||||
(FIR_OP_RBW << FIR_OP2_SHIFT));
|
||||
out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
|
||||
/* 5 bytes for manuf, device and exts */
|
||||
out_be32(&lbc->fbcr, 5);
|
||||
elbc_fcm_ctrl->read_bytes = 5;
|
||||
/* nand_get_flash_type() reads 8 bytes of entire ID string */
|
||||
out_be32(&lbc->fbcr, 8);
|
||||
elbc_fcm_ctrl->read_bytes = 8;
|
||||
elbc_fcm_ctrl->use_mdr = 1;
|
||||
elbc_fcm_ctrl->mdr = 0;
|
||||
|
||||
|
|
|
@ -3416,7 +3416,8 @@ config NETCONSOLE
|
|||
|
||||
config NETCONSOLE_DYNAMIC
|
||||
bool "Dynamic reconfiguration of logging targets"
|
||||
depends on NETCONSOLE && SYSFS && CONFIGFS_FS
|
||||
depends on NETCONSOLE && SYSFS && CONFIGFS_FS && \
|
||||
!(NETCONSOLE=y && CONFIGFS_FS=m)
|
||||
help
|
||||
This option enables the ability to dynamically reconfigure target
|
||||
parameters (interface, IP addresses, port numbers, MAC addresses)
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include <linux/zlib.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <linux/vmalloc.h>
|
||||
|
||||
#define BNX2X_MAIN
|
||||
#include "bnx2x.h"
|
||||
|
@ -4537,8 +4538,7 @@ static int bnx2x_gunzip_init(struct bnx2x *bp)
|
|||
if (bp->strm == NULL)
|
||||
goto gunzip_nomem2;
|
||||
|
||||
bp->strm->workspace = kmalloc(zlib_inflate_workspacesize(),
|
||||
GFP_KERNEL);
|
||||
bp->strm->workspace = vmalloc(zlib_inflate_workspacesize());
|
||||
if (bp->strm->workspace == NULL)
|
||||
goto gunzip_nomem3;
|
||||
|
||||
|
@ -4562,7 +4562,7 @@ static int bnx2x_gunzip_init(struct bnx2x *bp)
|
|||
static void bnx2x_gunzip_end(struct bnx2x *bp)
|
||||
{
|
||||
if (bp->strm) {
|
||||
kfree(bp->strm->workspace);
|
||||
vfree(bp->strm->workspace);
|
||||
kfree(bp->strm);
|
||||
bp->strm = NULL;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ config CAN_SLCAN
|
|||
config CAN_DEV
|
||||
tristate "Platform CAN drivers with Netlink support"
|
||||
depends on CAN
|
||||
default Y
|
||||
default y
|
||||
---help---
|
||||
Enables the common framework for platform CAN drivers with Netlink
|
||||
support. This is the standard library for CAN drivers.
|
||||
|
@ -45,7 +45,7 @@ config CAN_DEV
|
|||
config CAN_CALC_BITTIMING
|
||||
bool "CAN bit-timing calculation"
|
||||
depends on CAN_DEV
|
||||
default Y
|
||||
default y
|
||||
---help---
|
||||
If enabled, CAN bit-timing parameters will be calculated for the
|
||||
bit-rate specified via Netlink argument "bitrate" when the device
|
||||
|
|
|
@ -2026,7 +2026,7 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
|
|||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
} else
|
||||
skb_checksum_none_assert(skb);
|
||||
skb_record_rx_queue(skb, qs - &adap->sge.qs[0]);
|
||||
skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
|
||||
|
||||
if (unlikely(p->vlan_valid)) {
|
||||
struct vlan_group *grp = pi->vlan_grp;
|
||||
|
@ -2145,7 +2145,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs,
|
|||
if (!complete)
|
||||
return;
|
||||
|
||||
skb_record_rx_queue(skb, qs - &adap->sge.qs[0]);
|
||||
skb_record_rx_queue(skb, qs - &adap->sge.qs[pi->first_qset]);
|
||||
|
||||
if (unlikely(cpl->vlan_valid)) {
|
||||
struct vlan_group *grp = pi->vlan_grp;
|
||||
|
|
|
@ -305,7 +305,7 @@ static void z_decomp_free(void *arg)
|
|||
|
||||
if (state) {
|
||||
zlib_inflateEnd(&state->strm);
|
||||
kfree(state->strm.workspace);
|
||||
vfree(state->strm.workspace);
|
||||
kfree(state);
|
||||
}
|
||||
}
|
||||
|
@ -345,8 +345,7 @@ static void *z_decomp_alloc(unsigned char *options, int opt_len)
|
|||
|
||||
state->w_size = w_size;
|
||||
state->strm.next_out = NULL;
|
||||
state->strm.workspace = kmalloc(zlib_inflate_workspacesize(),
|
||||
GFP_KERNEL|__GFP_REPEAT);
|
||||
state->strm.workspace = vmalloc(zlib_inflate_workspacesize());
|
||||
if (state->strm.workspace == NULL)
|
||||
goto out_free;
|
||||
|
||||
|
|
|
@ -742,7 +742,7 @@ static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd)
|
|||
msleep(2);
|
||||
for (i = 0; i < 5; i++) {
|
||||
udelay(100);
|
||||
if (!(RTL_R32(ERIDR) & ERIAR_FLAG))
|
||||
if (!(RTL_R32(ERIAR) & ERIAR_FLAG))
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -378,7 +378,7 @@ static int rionet_close(struct net_device *ndev)
|
|||
|
||||
static void rionet_remove(struct rio_dev *rdev)
|
||||
{
|
||||
struct net_device *ndev = NULL;
|
||||
struct net_device *ndev = rio_get_drvdata(rdev);
|
||||
struct rionet_peer *peer, *tmp;
|
||||
|
||||
free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
|
||||
|
@ -433,22 +433,12 @@ static const struct net_device_ops rionet_netdev_ops = {
|
|||
.ndo_set_mac_address = eth_mac_addr,
|
||||
};
|
||||
|
||||
static int rionet_setup_netdev(struct rio_mport *mport)
|
||||
static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct net_device *ndev = NULL;
|
||||
struct rionet_private *rnet;
|
||||
u16 device_id;
|
||||
|
||||
/* Allocate our net_device structure */
|
||||
ndev = alloc_etherdev(sizeof(struct rionet_private));
|
||||
if (ndev == NULL) {
|
||||
printk(KERN_INFO "%s: could not allocate ethernet device.\n",
|
||||
DRV_NAME);
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
|
||||
mport->sys_size ? __fls(sizeof(void *)) + 4 : 0);
|
||||
if (!rionet_active) {
|
||||
|
@ -504,11 +494,21 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
|
|||
int rc = -ENODEV;
|
||||
u32 lpef, lsrc_ops, ldst_ops;
|
||||
struct rionet_peer *peer;
|
||||
struct net_device *ndev = NULL;
|
||||
|
||||
/* If local device is not rionet capable, give up quickly */
|
||||
if (!rionet_capable)
|
||||
goto out;
|
||||
|
||||
/* Allocate our net_device structure */
|
||||
ndev = alloc_etherdev(sizeof(struct rionet_private));
|
||||
if (ndev == NULL) {
|
||||
printk(KERN_INFO "%s: could not allocate ethernet device.\n",
|
||||
DRV_NAME);
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* First time through, make sure local device is rionet
|
||||
* capable, setup netdev, and set flags so this is skipped
|
||||
|
@ -529,7 +529,7 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
|
|||
goto out;
|
||||
}
|
||||
|
||||
rc = rionet_setup_netdev(rdev->net->hport);
|
||||
rc = rionet_setup_netdev(rdev->net->hport, ndev);
|
||||
rionet_check = 1;
|
||||
}
|
||||
|
||||
|
@ -546,6 +546,8 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
|
|||
list_add_tail(&peer->node, &rionet_peers);
|
||||
}
|
||||
|
||||
rio_set_drvdata(rdev, ndev);
|
||||
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -100,34 +100,42 @@ kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len,
|
|||
static int
|
||||
kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
|
||||
{
|
||||
char init_msg_1[] =
|
||||
const static char init_msg_1[] =
|
||||
{ 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
|
||||
0x00, 0x00 };
|
||||
char init_msg_2[] =
|
||||
const static char init_msg_2[] =
|
||||
{ 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4,
|
||||
0x00, 0x00 };
|
||||
char receive_buf[28];
|
||||
const static int buflen = 28;
|
||||
char *usb_buf;
|
||||
int status;
|
||||
|
||||
status = kalmia_send_init_packet(dev, init_msg_1, sizeof(init_msg_1)
|
||||
/ sizeof(init_msg_1[0]), receive_buf, 24);
|
||||
usb_buf = kmalloc(buflen, GFP_DMA | GFP_KERNEL);
|
||||
if (!usb_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(usb_buf, init_msg_1, 12);
|
||||
status = kalmia_send_init_packet(dev, usb_buf, sizeof(init_msg_1)
|
||||
/ sizeof(init_msg_1[0]), usb_buf, 24);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
status = kalmia_send_init_packet(dev, init_msg_2, sizeof(init_msg_2)
|
||||
/ sizeof(init_msg_2[0]), receive_buf, 28);
|
||||
memcpy(usb_buf, init_msg_2, 12);
|
||||
status = kalmia_send_init_packet(dev, usb_buf, sizeof(init_msg_2)
|
||||
/ sizeof(init_msg_2[0]), usb_buf, 28);
|
||||
if (status != 0)
|
||||
return status;
|
||||
|
||||
memcpy(ethernet_addr, receive_buf + 10, ETH_ALEN);
|
||||
memcpy(ethernet_addr, usb_buf + 10, ETH_ALEN);
|
||||
|
||||
kfree(usb_buf);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
kalmia_bind(struct usbnet *dev, struct usb_interface *intf)
|
||||
{
|
||||
u8 status;
|
||||
int status;
|
||||
u8 ethernet_addr[ETH_ALEN];
|
||||
|
||||
/* Don't bind to AT command interface */
|
||||
|
@ -190,7 +198,8 @@ kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
|
|||
dev_kfree_skb_any(skb);
|
||||
skb = skb2;
|
||||
|
||||
done: header_start = skb_push(skb, KALMIA_HEADER_LENGTH);
|
||||
done:
|
||||
header_start = skb_push(skb, KALMIA_HEADER_LENGTH);
|
||||
ether_type_1 = header_start[KALMIA_HEADER_LENGTH + 12];
|
||||
ether_type_2 = header_start[KALMIA_HEADER_LENGTH + 13];
|
||||
|
||||
|
@ -201,9 +210,8 @@ kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
|
|||
header_start[0] = 0x57;
|
||||
header_start[1] = 0x44;
|
||||
content_len = skb->len - KALMIA_HEADER_LENGTH;
|
||||
header_start[2] = (content_len & 0xff); /* low byte */
|
||||
header_start[3] = (content_len >> 8); /* high byte */
|
||||
|
||||
put_unaligned_le16(content_len, &header_start[2]);
|
||||
header_start[4] = ether_type_1;
|
||||
header_start[5] = ether_type_2;
|
||||
|
||||
|
@ -231,13 +239,13 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
|||
* Our task here is to strip off framing, leaving skb with one
|
||||
* data frame for the usbnet framework code to process.
|
||||
*/
|
||||
const u8 HEADER_END_OF_USB_PACKET[] =
|
||||
const static u8 HEADER_END_OF_USB_PACKET[] =
|
||||
{ 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 };
|
||||
const u8 EXPECTED_UNKNOWN_HEADER_1[] =
|
||||
const static u8 EXPECTED_UNKNOWN_HEADER_1[] =
|
||||
{ 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 };
|
||||
const u8 EXPECTED_UNKNOWN_HEADER_2[] =
|
||||
const static u8 EXPECTED_UNKNOWN_HEADER_2[] =
|
||||
{ 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 };
|
||||
u8 i = 0;
|
||||
int i = 0;
|
||||
|
||||
/* incomplete header? */
|
||||
if (skb->len < KALMIA_HEADER_LENGTH)
|
||||
|
@ -285,7 +293,7 @@ kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
|
|||
|
||||
/* subtract start header and end header */
|
||||
usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH);
|
||||
ether_packet_length = header_start[2] + (header_start[3] << 8);
|
||||
ether_packet_length = get_unaligned_le16(&header_start[2]);
|
||||
skb_pull(skb, KALMIA_HEADER_LENGTH);
|
||||
|
||||
/* Some small packets misses end marker */
|
||||
|
|
|
@ -331,17 +331,7 @@ static const struct usb_device_id products [] = {
|
|||
ZAURUS_MASTER_INTERFACE,
|
||||
.driver_info = ZAURUS_PXA_INFO,
|
||||
},
|
||||
|
||||
|
||||
/* At least some of the newest PXA units have very different lies about
|
||||
* their standards support: they claim to be cell phones offering
|
||||
* direct access to their radios! (No, they don't conform to CDC MDLM.)
|
||||
*/
|
||||
{
|
||||
USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long) &bogus_mdlm_info,
|
||||
}, {
|
||||
/* Motorola MOTOMAGX phones */
|
||||
USB_DEVICE_AND_INTERFACE_INFO(0x22b8, 0x6425, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_MDLM, USB_CDC_PROTO_NONE),
|
||||
|
|
|
@ -1624,6 +1624,16 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
|
|||
pci_read_config_byte(pdev, 0x8, &revisionid);
|
||||
pci_read_config_word(pdev, 0x3C, &irqline);
|
||||
|
||||
/* PCI ID 0x10ec:0x8192 occurs for both RTL8192E, which uses
|
||||
* r8192e_pci, and RTL8192SE, which uses this driver. If the
|
||||
* revision ID is RTL_PCI_REVISION_ID_8192PCIE (0x01), then
|
||||
* the correct driver is r8192e_pci, thus this routine should
|
||||
* return false.
|
||||
*/
|
||||
if (deviceid == RTL_PCI_8192SE_DID &&
|
||||
revisionid == RTL_PCI_REVISION_ID_8192PCIE)
|
||||
return false;
|
||||
|
||||
if (deviceid == RTL_PCI_8192_DID ||
|
||||
deviceid == RTL_PCI_0044_DID ||
|
||||
deviceid == RTL_PCI_0047_DID ||
|
||||
|
@ -1856,7 +1866,8 @@ int __devinit rtl_pci_probe(struct pci_dev *pdev,
|
|||
pci_write_config_byte(pdev, 0x04, 0x07);
|
||||
|
||||
/* find adapter */
|
||||
_rtl_pci_find_adapter(pdev, hw);
|
||||
if (!_rtl_pci_find_adapter(pdev, hw))
|
||||
goto fail3;
|
||||
|
||||
/* Init IO handler */
|
||||
_rtl_pci_io_handler_init(&pdev->dev, hw);
|
||||
|
|
|
@ -53,6 +53,8 @@ MODULE_FIRMWARE("rtlwifi/rtl8192cufw.bin");
|
|||
static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
const struct firmware *firmware;
|
||||
int err;
|
||||
|
||||
rtlpriv->dm.dm_initialgain_enable = 1;
|
||||
rtlpriv->dm.dm_flag = 0;
|
||||
|
@ -64,6 +66,24 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
|
|||
("Can't alloc buffer for fw.\n"));
|
||||
return 1;
|
||||
}
|
||||
/* request fw */
|
||||
err = request_firmware(&firmware, rtlpriv->cfg->fw_name,
|
||||
rtlpriv->io.dev);
|
||||
if (err) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
("Failed to request firmware!\n"));
|
||||
return 1;
|
||||
}
|
||||
if (firmware->size > 0x4000) {
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
|
||||
("Firmware is too big!\n"));
|
||||
release_firmware(firmware);
|
||||
return 1;
|
||||
}
|
||||
memcpy(rtlpriv->rtlhal.pfirmware, firmware->data, firmware->size);
|
||||
rtlpriv->rtlhal.fwsize = firmware->size;
|
||||
release_firmware(firmware);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -830,6 +830,19 @@ config SCSI_GDTH
|
|||
To compile this driver as a module, choose M here: the
|
||||
module will be called gdth.
|
||||
|
||||
config SCSI_ISCI
|
||||
tristate "Intel(R) C600 Series Chipset SAS Controller"
|
||||
depends on PCI && SCSI
|
||||
depends on X86
|
||||
# (temporary): known alpha quality driver
|
||||
depends on EXPERIMENTAL
|
||||
select SCSI_SAS_LIBSAS
|
||||
---help---
|
||||
This driver supports the 6Gb/s SAS capabilities of the storage
|
||||
control unit found in the Intel(R) C600 series chipset.
|
||||
|
||||
The experimental tag will be removed after the driver exits alpha
|
||||
|
||||
config SCSI_GENERIC_NCR5380
|
||||
tristate "Generic NCR5380/53c400 SCSI PIO support"
|
||||
depends on ISA && SCSI
|
||||
|
|
|
@ -73,6 +73,7 @@ obj-$(CONFIG_SCSI_AACRAID) += aacraid/
|
|||
obj-$(CONFIG_SCSI_AIC7XXX_OLD) += aic7xxx_old.o
|
||||
obj-$(CONFIG_SCSI_AIC94XX) += aic94xx/
|
||||
obj-$(CONFIG_SCSI_PM8001) += pm8001/
|
||||
obj-$(CONFIG_SCSI_ISCI) += isci/
|
||||
obj-$(CONFIG_SCSI_IPS) += ips.o
|
||||
obj-$(CONFIG_SCSI_FD_MCS) += fd_mcs.o
|
||||
obj-$(CONFIG_SCSI_FUTURE_DOMAIN)+= fdomain.o
|
||||
|
|
|
@ -1037,6 +1037,7 @@ static void complete_scsi_command(struct CommandList *cp)
|
|||
unsigned char sense_key;
|
||||
unsigned char asc; /* additional sense code */
|
||||
unsigned char ascq; /* additional sense code qualifier */
|
||||
unsigned long sense_data_size;
|
||||
|
||||
ei = cp->err_info;
|
||||
cmd = (struct scsi_cmnd *) cp->scsi_cmd;
|
||||
|
@ -1051,10 +1052,14 @@ static void complete_scsi_command(struct CommandList *cp)
|
|||
cmd->result |= ei->ScsiStatus;
|
||||
|
||||
/* copy the sense data whether we need to or not. */
|
||||
memcpy(cmd->sense_buffer, ei->SenseInfo,
|
||||
ei->SenseLen > SCSI_SENSE_BUFFERSIZE ?
|
||||
SCSI_SENSE_BUFFERSIZE :
|
||||
ei->SenseLen);
|
||||
if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo))
|
||||
sense_data_size = SCSI_SENSE_BUFFERSIZE;
|
||||
else
|
||||
sense_data_size = sizeof(ei->SenseInfo);
|
||||
if (ei->SenseLen < sense_data_size)
|
||||
sense_data_size = ei->SenseLen;
|
||||
|
||||
memcpy(cmd->sense_buffer, ei->SenseInfo, sense_data_size);
|
||||
scsi_set_resid(cmd, ei->ResidualCnt);
|
||||
|
||||
if (ei->CommandStatus == 0) {
|
||||
|
@ -2580,7 +2585,8 @@ static int hpsa_passthru_ioctl(struct ctlr_info *h, void __user *argp)
|
|||
c->SG[0].Ext = 0; /* we are not chaining*/
|
||||
}
|
||||
hpsa_scsi_do_simple_cmd_core(h, c);
|
||||
hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL);
|
||||
if (iocommand.buf_size > 0)
|
||||
hpsa_pci_unmap(h->pdev, c, 1, PCI_DMA_BIDIRECTIONAL);
|
||||
check_ioctl_unit_attention(h, c);
|
||||
|
||||
/* Copy the error information out */
|
||||
|
|
|
@ -4306,8 +4306,8 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
|
|||
spin_lock_irqsave(vhost->host->host_lock, flags);
|
||||
if (rc == H_CLOSED)
|
||||
vio_enable_interrupts(to_vio_dev(vhost->dev));
|
||||
else if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
|
||||
(rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
|
||||
if (rc || (rc = ibmvfc_send_crq_init(vhost)) ||
|
||||
(rc = vio_enable_interrupts(to_vio_dev(vhost->dev)))) {
|
||||
ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
|
||||
dev_err(vhost->dev, "Error after reset (rc=%d)\n", rc);
|
||||
}
|
||||
|
|
8
drivers/scsi/isci/Makefile
Normal file
8
drivers/scsi/isci/Makefile
Normal file
|
@ -0,0 +1,8 @@
|
|||
obj-$(CONFIG_SCSI_ISCI) += isci.o
|
||||
isci-objs := init.o phy.o request.o \
|
||||
remote_device.o port.o \
|
||||
host.o task.o probe_roms.o \
|
||||
remote_node_context.o \
|
||||
remote_node_table.o \
|
||||
unsolicited_frame_control.o \
|
||||
port_config.o \
|
19
drivers/scsi/isci/firmware/Makefile
Normal file
19
drivers/scsi/isci/firmware/Makefile
Normal file
|
@ -0,0 +1,19 @@
|
|||
# Makefile for create_fw
|
||||
#
|
||||
CC=gcc
|
||||
CFLAGS=-c -Wall -O2 -g
|
||||
LDFLAGS=
|
||||
SOURCES=create_fw.c
|
||||
OBJECTS=$(SOURCES:.cpp=.o)
|
||||
EXECUTABLE=create_fw
|
||||
|
||||
all: $(SOURCES) $(EXECUTABLE)
|
||||
|
||||
$(EXECUTABLE): $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $< -O $@
|
||||
|
||||
clean:
|
||||
rm -f *.o $(EXECUTABLE)
|
36
drivers/scsi/isci/firmware/README
Normal file
36
drivers/scsi/isci/firmware/README
Normal file
|
@ -0,0 +1,36 @@
|
|||
This defines the temporary binary blow we are to pass to the SCU
|
||||
driver to emulate the binary firmware that we will eventually be
|
||||
able to access via NVRAM on the SCU controller.
|
||||
|
||||
The current size of the binary blob is expected to be 149 bytes or larger
|
||||
|
||||
Header Types:
|
||||
0x1: Phy Masks
|
||||
0x2: Phy Gens
|
||||
0x3: SAS Addrs
|
||||
0xff: End of Data
|
||||
|
||||
ID string - u8[12]: "#SCU MAGIC#\0"
|
||||
Version - u8: 1
|
||||
SubVersion - u8: 0
|
||||
|
||||
Header Type - u8: 0x1
|
||||
Size - u8: 8
|
||||
Phy Mask - u32[8]
|
||||
|
||||
Header Type - u8: 0x2
|
||||
Size - u8: 8
|
||||
Phy Gen - u32[8]
|
||||
|
||||
Header Type - u8: 0x3
|
||||
Size - u8: 8
|
||||
Sas Addr - u64[8]
|
||||
|
||||
Header Type - u8: 0xf
|
||||
|
||||
|
||||
==============================================================================
|
||||
|
||||
Place isci_firmware.bin in /lib/firmware
|
||||
Be sure to recreate the initramfs image to include the firmware.
|
||||
|
99
drivers/scsi/isci/firmware/create_fw.c
Normal file
99
drivers/scsi/isci/firmware/create_fw.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <asm/types.h>
|
||||
#include <strings.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "create_fw.h"
|
||||
#include "../probe_roms.h"
|
||||
|
||||
int write_blob(struct isci_orom *isci_orom)
|
||||
{
|
||||
FILE *fd;
|
||||
int err;
|
||||
size_t count;
|
||||
|
||||
fd = fopen(blob_name, "w+");
|
||||
if (!fd) {
|
||||
perror("Open file for write failed");
|
||||
fclose(fd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
count = fwrite(isci_orom, sizeof(struct isci_orom), 1, fd);
|
||||
if (count != 1) {
|
||||
perror("Write data failed");
|
||||
fclose(fd);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void set_binary_values(struct isci_orom *isci_orom)
|
||||
{
|
||||
int ctrl_idx, phy_idx, port_idx;
|
||||
|
||||
/* setting OROM signature */
|
||||
strncpy(isci_orom->hdr.signature, sig, strlen(sig));
|
||||
isci_orom->hdr.version = version;
|
||||
isci_orom->hdr.total_block_length = sizeof(struct isci_orom);
|
||||
isci_orom->hdr.hdr_length = sizeof(struct sci_bios_oem_param_block_hdr);
|
||||
isci_orom->hdr.num_elements = num_elements;
|
||||
|
||||
for (ctrl_idx = 0; ctrl_idx < 2; ctrl_idx++) {
|
||||
isci_orom->ctrl[ctrl_idx].controller.mode_type = mode_type;
|
||||
isci_orom->ctrl[ctrl_idx].controller.max_concurrent_dev_spin_up =
|
||||
max_num_concurrent_dev_spin_up;
|
||||
isci_orom->ctrl[ctrl_idx].controller.do_enable_ssc =
|
||||
enable_ssc;
|
||||
|
||||
for (port_idx = 0; port_idx < 4; port_idx++)
|
||||
isci_orom->ctrl[ctrl_idx].ports[port_idx].phy_mask =
|
||||
phy_mask[ctrl_idx][port_idx];
|
||||
|
||||
for (phy_idx = 0; phy_idx < 4; phy_idx++) {
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.high =
|
||||
(__u32)(sas_addr[ctrl_idx][phy_idx] >> 32);
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].sas_address.low =
|
||||
(__u32)(sas_addr[ctrl_idx][phy_idx]);
|
||||
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control0 =
|
||||
afe_tx_amp_control0;
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control1 =
|
||||
afe_tx_amp_control1;
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control2 =
|
||||
afe_tx_amp_control2;
|
||||
isci_orom->ctrl[ctrl_idx].phys[phy_idx].afe_tx_amp_control3 =
|
||||
afe_tx_amp_control3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err;
|
||||
struct isci_orom *isci_orom;
|
||||
|
||||
isci_orom = malloc(sizeof(struct isci_orom));
|
||||
memset(isci_orom, 0, sizeof(struct isci_orom));
|
||||
|
||||
set_binary_values(isci_orom);
|
||||
|
||||
err = write_blob(isci_orom);
|
||||
if (err < 0) {
|
||||
free(isci_orom);
|
||||
return err;
|
||||
}
|
||||
|
||||
free(isci_orom);
|
||||
return 0;
|
||||
}
|
77
drivers/scsi/isci/firmware/create_fw.h
Normal file
77
drivers/scsi/isci/firmware/create_fw.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
#ifndef _CREATE_FW_H_
|
||||
#define _CREATE_FW_H_
|
||||
#include "../probe_roms.h"
|
||||
|
||||
|
||||
/* we are configuring for 2 SCUs */
|
||||
static const int num_elements = 2;
|
||||
|
||||
/*
|
||||
* For all defined arrays:
|
||||
* elements 0-3 are for SCU0, ports 0-3
|
||||
* elements 4-7 are for SCU1, ports 0-3
|
||||
*
|
||||
* valid configurations for one SCU are:
|
||||
* P0 P1 P2 P3
|
||||
* ----------------
|
||||
* 0xF,0x0,0x0,0x0 # 1 x4 port
|
||||
* 0x3,0x0,0x4,0x8 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are each x1
|
||||
* # ports
|
||||
* 0x1,0x2,0xC,0x0 # Phys 0 and 1 are each x1 ports, phy 2 and phy 3 are a x2
|
||||
* # port
|
||||
* 0x3,0x0,0xC,0x0 # Phys 0 and 1 are a x2 port, phy 2 and phy 3 are a x2 port
|
||||
* 0x1,0x2,0x4,0x8 # Each phy is a x1 port (this is the default configuration)
|
||||
*
|
||||
* if there is a port/phy on which you do not wish to override the default
|
||||
* values, use the value assigned to UNINIT_PARAM (255).
|
||||
*/
|
||||
|
||||
/* discovery mode type (port auto config mode by default ) */
|
||||
|
||||
/*
|
||||
* if there is a port/phy on which you do not wish to override the default
|
||||
* values, use the value "0000000000000000". SAS address of zero's is
|
||||
* considered invalid and will not be used.
|
||||
*/
|
||||
#ifdef MPC
|
||||
static const int mode_type = SCIC_PORT_MANUAL_CONFIGURATION_MODE;
|
||||
static const __u8 phy_mask[2][4] = { {1, 2, 4, 8},
|
||||
{1, 2, 4, 8} };
|
||||
static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFFF0000001ULL,
|
||||
0x5FCFFFFFF0000002ULL,
|
||||
0x5FCFFFFFF0000003ULL,
|
||||
0x5FCFFFFFF0000004ULL },
|
||||
{ 0x5FCFFFFFF0000005ULL,
|
||||
0x5FCFFFFFF0000006ULL,
|
||||
0x5FCFFFFFF0000007ULL,
|
||||
0x5FCFFFFFF0000008ULL } };
|
||||
#else /* APC (default) */
|
||||
static const int mode_type = SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE;
|
||||
static const __u8 phy_mask[2][4];
|
||||
static const unsigned long long sas_addr[2][4] = { { 0x5FCFFFFF00000001ULL,
|
||||
0x5FCFFFFF00000001ULL,
|
||||
0x5FCFFFFF00000001ULL,
|
||||
0x5FCFFFFF00000001ULL },
|
||||
{ 0x5FCFFFFF00000002ULL,
|
||||
0x5FCFFFFF00000002ULL,
|
||||
0x5FCFFFFF00000002ULL,
|
||||
0x5FCFFFFF00000002ULL } };
|
||||
#endif
|
||||
|
||||
/* Maximum number of concurrent device spin up */
|
||||
static const int max_num_concurrent_dev_spin_up = 1;
|
||||
|
||||
/* enable of ssc operation */
|
||||
static const int enable_ssc;
|
||||
|
||||
/* AFE_TX_AMP_CONTROL */
|
||||
static const unsigned int afe_tx_amp_control0 = 0x000bdd08;
|
||||
static const unsigned int afe_tx_amp_control1 = 0x000ffc00;
|
||||
static const unsigned int afe_tx_amp_control2 = 0x000b7c09;
|
||||
static const unsigned int afe_tx_amp_control3 = 0x000afc6e;
|
||||
|
||||
static const char blob_name[] = "isci_firmware.bin";
|
||||
static const char sig[] = "ISCUOEMB";
|
||||
static const unsigned char version = 0x10;
|
||||
|
||||
#endif
|
2751
drivers/scsi/isci/host.c
Normal file
2751
drivers/scsi/isci/host.c
Normal file
File diff suppressed because it is too large
Load diff
542
drivers/scsi/isci/host.h
Normal file
542
drivers/scsi/isci/host.h
Normal file
|
@ -0,0 +1,542 @@
|
|||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _SCI_HOST_H_
|
||||
#define _SCI_HOST_H_
|
||||
|
||||
#include "remote_device.h"
|
||||
#include "phy.h"
|
||||
#include "isci.h"
|
||||
#include "remote_node_table.h"
|
||||
#include "registers.h"
|
||||
#include "unsolicited_frame_control.h"
|
||||
#include "probe_roms.h"
|
||||
|
||||
struct isci_request;
|
||||
struct scu_task_context;
|
||||
|
||||
|
||||
/**
|
||||
* struct sci_power_control -
|
||||
*
|
||||
* This structure defines the fields for managing power control for direct
|
||||
* attached disk devices.
|
||||
*/
|
||||
struct sci_power_control {
|
||||
/**
|
||||
* This field is set when the power control timer is running and cleared when
|
||||
* it is not.
|
||||
*/
|
||||
bool timer_started;
|
||||
|
||||
/**
|
||||
* Timer to control when the directed attached disks can consume power.
|
||||
*/
|
||||
struct sci_timer timer;
|
||||
|
||||
/**
|
||||
* This field is used to keep track of how many phys are put into the
|
||||
* requesters field.
|
||||
*/
|
||||
u8 phys_waiting;
|
||||
|
||||
/**
|
||||
* This field is used to keep track of how many phys have been granted to consume power
|
||||
*/
|
||||
u8 phys_granted_power;
|
||||
|
||||
/**
|
||||
* This field is an array of phys that we are waiting on. The phys are direct
|
||||
* mapped into requesters via struct sci_phy.phy_index
|
||||
*/
|
||||
struct isci_phy *requesters[SCI_MAX_PHYS];
|
||||
|
||||
};
|
||||
|
||||
struct sci_port_configuration_agent;
|
||||
typedef void (*port_config_fn)(struct isci_host *,
|
||||
struct sci_port_configuration_agent *,
|
||||
struct isci_port *, struct isci_phy *);
|
||||
|
||||
struct sci_port_configuration_agent {
|
||||
u16 phy_configured_mask;
|
||||
u16 phy_ready_mask;
|
||||
struct {
|
||||
u8 min_index;
|
||||
u8 max_index;
|
||||
} phy_valid_port_range[SCI_MAX_PHYS];
|
||||
bool timer_pending;
|
||||
port_config_fn link_up_handler;
|
||||
port_config_fn link_down_handler;
|
||||
struct sci_timer timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* isci_host - primary host/controller object
|
||||
* @timer: timeout start/stop operations
|
||||
* @device_table: rni (hw remote node index) to remote device lookup table
|
||||
* @available_remote_nodes: rni allocator
|
||||
* @power_control: manage device spin up
|
||||
* @io_request_sequence: generation number for tci's (task contexts)
|
||||
* @task_context_table: hw task context table
|
||||
* @remote_node_context_table: hw remote node context table
|
||||
* @completion_queue: hw-producer driver-consumer communication ring
|
||||
* @completion_queue_get: tracks the driver 'head' of the ring to notify hw
|
||||
* @logical_port_entries: min({driver|silicon}-supported-port-count)
|
||||
* @remote_node_entries: min({driver|silicon}-supported-node-count)
|
||||
* @task_context_entries: min({driver|silicon}-supported-task-count)
|
||||
* @phy_timer: phy startup timer
|
||||
* @invalid_phy_mask: if an invalid_link_up notification is reported a bit for
|
||||
* the phy index is set so further notifications are not
|
||||
* made. Once the phy reports link up and is made part of a
|
||||
* port then this bit is cleared.
|
||||
|
||||
*/
|
||||
struct isci_host {
|
||||
struct sci_base_state_machine sm;
|
||||
/* XXX can we time this externally */
|
||||
struct sci_timer timer;
|
||||
/* XXX drop reference module params directly */
|
||||
struct sci_user_parameters user_parameters;
|
||||
/* XXX no need to be a union */
|
||||
struct sci_oem_params oem_parameters;
|
||||
struct sci_port_configuration_agent port_agent;
|
||||
struct isci_remote_device *device_table[SCI_MAX_REMOTE_DEVICES];
|
||||
struct sci_remote_node_table available_remote_nodes;
|
||||
struct sci_power_control power_control;
|
||||
u8 io_request_sequence[SCI_MAX_IO_REQUESTS];
|
||||
struct scu_task_context *task_context_table;
|
||||
dma_addr_t task_context_dma;
|
||||
union scu_remote_node_context *remote_node_context_table;
|
||||
u32 *completion_queue;
|
||||
u32 completion_queue_get;
|
||||
u32 logical_port_entries;
|
||||
u32 remote_node_entries;
|
||||
u32 task_context_entries;
|
||||
struct sci_unsolicited_frame_control uf_control;
|
||||
|
||||
/* phy startup */
|
||||
struct sci_timer phy_timer;
|
||||
/* XXX kill */
|
||||
bool phy_startup_timer_pending;
|
||||
u32 next_phy_to_start;
|
||||
/* XXX convert to unsigned long and use bitops */
|
||||
u8 invalid_phy_mask;
|
||||
|
||||
/* TODO attempt dynamic interrupt coalescing scheme */
|
||||
u16 interrupt_coalesce_number;
|
||||
u32 interrupt_coalesce_timeout;
|
||||
struct smu_registers __iomem *smu_registers;
|
||||
struct scu_registers __iomem *scu_registers;
|
||||
|
||||
u16 tci_head;
|
||||
u16 tci_tail;
|
||||
u16 tci_pool[SCI_MAX_IO_REQUESTS];
|
||||
|
||||
int id; /* unique within a given pci device */
|
||||
struct isci_phy phys[SCI_MAX_PHYS];
|
||||
struct isci_port ports[SCI_MAX_PORTS + 1]; /* includes dummy port */
|
||||
struct sas_ha_struct sas_ha;
|
||||
|
||||
spinlock_t state_lock;
|
||||
struct pci_dev *pdev;
|
||||
enum isci_status status;
|
||||
#define IHOST_START_PENDING 0
|
||||
#define IHOST_STOP_PENDING 1
|
||||
unsigned long flags;
|
||||
wait_queue_head_t eventq;
|
||||
struct Scsi_Host *shost;
|
||||
struct tasklet_struct completion_tasklet;
|
||||
struct list_head requests_to_complete;
|
||||
struct list_head requests_to_errorback;
|
||||
spinlock_t scic_lock;
|
||||
struct isci_request *reqs[SCI_MAX_IO_REQUESTS];
|
||||
struct isci_remote_device devices[SCI_MAX_REMOTE_DEVICES];
|
||||
};
|
||||
|
||||
/**
|
||||
* enum sci_controller_states - This enumeration depicts all the states
|
||||
* for the common controller state machine.
|
||||
*/
|
||||
enum sci_controller_states {
|
||||
/**
|
||||
* Simply the initial state for the base controller state machine.
|
||||
*/
|
||||
SCIC_INITIAL = 0,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller is reset. The memory for
|
||||
* the controller is in it's initial state, but the controller requires
|
||||
* initialization.
|
||||
* This state is entered from the INITIAL state.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCIC_RESET,
|
||||
|
||||
/**
|
||||
* This state is typically an action state that indicates the controller
|
||||
* is in the process of initialization. In this state no new IO operations
|
||||
* are permitted.
|
||||
* This state is entered from the RESET state.
|
||||
*/
|
||||
SCIC_INITIALIZING,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller has been successfully
|
||||
* initialized. In this state no new IO operations are permitted.
|
||||
* This state is entered from the INITIALIZING state.
|
||||
*/
|
||||
SCIC_INITIALIZED,
|
||||
|
||||
/**
|
||||
* This state indicates the the controller is in the process of becoming
|
||||
* ready (i.e. starting). In this state no new IO operations are permitted.
|
||||
* This state is entered from the INITIALIZED state.
|
||||
*/
|
||||
SCIC_STARTING,
|
||||
|
||||
/**
|
||||
* This state indicates the controller is now ready. Thus, the user
|
||||
* is able to perform IO operations on the controller.
|
||||
* This state is entered from the STARTING state.
|
||||
*/
|
||||
SCIC_READY,
|
||||
|
||||
/**
|
||||
* This state is typically an action state that indicates the controller
|
||||
* is in the process of resetting. Thus, the user is unable to perform
|
||||
* IO operations on the controller. A reset is considered destructive in
|
||||
* most cases.
|
||||
* This state is entered from the READY state.
|
||||
* This state is entered from the FAILED state.
|
||||
* This state is entered from the STOPPED state.
|
||||
*/
|
||||
SCIC_RESETTING,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller is in the process of stopping.
|
||||
* In this state no new IO operations are permitted, but existing IO
|
||||
* operations are allowed to complete.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCIC_STOPPING,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller has successfully been stopped.
|
||||
* In this state no new IO operations are permitted.
|
||||
* This state is entered from the STOPPING state.
|
||||
*/
|
||||
SCIC_STOPPED,
|
||||
|
||||
/**
|
||||
* This state indicates that the controller could not successfully be
|
||||
* initialized. In this state no new IO operations are permitted.
|
||||
* This state is entered from the INITIALIZING state.
|
||||
* This state is entered from the STARTING state.
|
||||
* This state is entered from the STOPPING state.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCIC_FAILED,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct isci_pci_info - This class represents the pci function containing the
|
||||
* controllers. Depending on PCI SKU, there could be up to 2 controllers in
|
||||
* the PCI function.
|
||||
*/
|
||||
#define SCI_MAX_MSIX_INT (SCI_NUM_MSI_X_INT*SCI_MAX_CONTROLLERS)
|
||||
|
||||
struct isci_pci_info {
|
||||
struct msix_entry msix_entries[SCI_MAX_MSIX_INT];
|
||||
struct isci_host *hosts[SCI_MAX_CONTROLLERS];
|
||||
struct isci_orom *orom;
|
||||
};
|
||||
|
||||
static inline struct isci_pci_info *to_pci_info(struct pci_dev *pdev)
|
||||
{
|
||||
return pci_get_drvdata(pdev);
|
||||
}
|
||||
|
||||
#define for_each_isci_host(id, ihost, pdev) \
|
||||
for (id = 0, ihost = to_pci_info(pdev)->hosts[id]; \
|
||||
id < ARRAY_SIZE(to_pci_info(pdev)->hosts) && ihost; \
|
||||
ihost = to_pci_info(pdev)->hosts[++id])
|
||||
|
||||
static inline enum isci_status isci_host_get_state(struct isci_host *isci_host)
|
||||
{
|
||||
return isci_host->status;
|
||||
}
|
||||
|
||||
static inline void isci_host_change_state(struct isci_host *isci_host,
|
||||
enum isci_status status)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
dev_dbg(&isci_host->pdev->dev,
|
||||
"%s: isci_host = %p, state = 0x%x",
|
||||
__func__,
|
||||
isci_host,
|
||||
status);
|
||||
spin_lock_irqsave(&isci_host->state_lock, flags);
|
||||
isci_host->status = status;
|
||||
spin_unlock_irqrestore(&isci_host->state_lock, flags);
|
||||
|
||||
}
|
||||
|
||||
static inline void wait_for_start(struct isci_host *ihost)
|
||||
{
|
||||
wait_event(ihost->eventq, !test_bit(IHOST_START_PENDING, &ihost->flags));
|
||||
}
|
||||
|
||||
static inline void wait_for_stop(struct isci_host *ihost)
|
||||
{
|
||||
wait_event(ihost->eventq, !test_bit(IHOST_STOP_PENDING, &ihost->flags));
|
||||
}
|
||||
|
||||
static inline void wait_for_device_start(struct isci_host *ihost, struct isci_remote_device *idev)
|
||||
{
|
||||
wait_event(ihost->eventq, !test_bit(IDEV_START_PENDING, &idev->flags));
|
||||
}
|
||||
|
||||
static inline void wait_for_device_stop(struct isci_host *ihost, struct isci_remote_device *idev)
|
||||
{
|
||||
wait_event(ihost->eventq, !test_bit(IDEV_STOP_PENDING, &idev->flags));
|
||||
}
|
||||
|
||||
static inline struct isci_host *dev_to_ihost(struct domain_device *dev)
|
||||
{
|
||||
return dev->port->ha->lldd_ha;
|
||||
}
|
||||
|
||||
/* we always use protocol engine group zero */
|
||||
#define ISCI_PEG 0
|
||||
|
||||
/* see sci_controller_io_tag_allocate|free for how seq and tci are built */
|
||||
#define ISCI_TAG(seq, tci) (((u16) (seq)) << 12 | tci)
|
||||
|
||||
/* these are returned by the hardware, so sanitize them */
|
||||
#define ISCI_TAG_SEQ(tag) (((tag) >> 12) & (SCI_MAX_SEQ-1))
|
||||
#define ISCI_TAG_TCI(tag) ((tag) & (SCI_MAX_IO_REQUESTS-1))
|
||||
|
||||
/* expander attached sata devices require 3 rnc slots */
|
||||
static inline int sci_remote_device_node_count(struct isci_remote_device *idev)
|
||||
{
|
||||
struct domain_device *dev = idev->domain_dev;
|
||||
|
||||
if ((dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) &&
|
||||
!idev->is_direct_attached)
|
||||
return SCU_STP_REMOTE_NODE_COUNT;
|
||||
return SCU_SSP_REMOTE_NODE_COUNT;
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_controller_clear_invalid_phy() -
|
||||
*
|
||||
* This macro will clear the bit in the invalid phy mask for this controller
|
||||
* object. This is used to control messages reported for invalid link up
|
||||
* notifications.
|
||||
*/
|
||||
#define sci_controller_clear_invalid_phy(controller, phy) \
|
||||
((controller)->invalid_phy_mask &= ~(1 << (phy)->phy_index))
|
||||
|
||||
static inline struct device *sciphy_to_dev(struct isci_phy *iphy)
|
||||
{
|
||||
|
||||
if (!iphy || !iphy->isci_port || !iphy->isci_port->isci_host)
|
||||
return NULL;
|
||||
|
||||
return &iphy->isci_port->isci_host->pdev->dev;
|
||||
}
|
||||
|
||||
static inline struct device *sciport_to_dev(struct isci_port *iport)
|
||||
{
|
||||
|
||||
if (!iport || !iport->isci_host)
|
||||
return NULL;
|
||||
|
||||
return &iport->isci_host->pdev->dev;
|
||||
}
|
||||
|
||||
static inline struct device *scirdev_to_dev(struct isci_remote_device *idev)
|
||||
{
|
||||
if (!idev || !idev->isci_port || !idev->isci_port->isci_host)
|
||||
return NULL;
|
||||
|
||||
return &idev->isci_port->isci_host->pdev->dev;
|
||||
}
|
||||
|
||||
static inline bool is_a2(struct pci_dev *pdev)
|
||||
{
|
||||
if (pdev->revision < 4)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool is_b0(struct pci_dev *pdev)
|
||||
{
|
||||
if (pdev->revision == 4)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool is_c0(struct pci_dev *pdev)
|
||||
{
|
||||
if (pdev->revision >= 5)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void sci_controller_post_request(struct isci_host *ihost,
|
||||
u32 request);
|
||||
void sci_controller_release_frame(struct isci_host *ihost,
|
||||
u32 frame_index);
|
||||
void sci_controller_copy_sata_response(void *response_buffer,
|
||||
void *frame_header,
|
||||
void *frame_buffer);
|
||||
enum sci_status sci_controller_allocate_remote_node_context(struct isci_host *ihost,
|
||||
struct isci_remote_device *idev,
|
||||
u16 *node_id);
|
||||
void sci_controller_free_remote_node_context(
|
||||
struct isci_host *ihost,
|
||||
struct isci_remote_device *idev,
|
||||
u16 node_id);
|
||||
|
||||
struct isci_request *sci_request_by_tag(struct isci_host *ihost,
|
||||
u16 io_tag);
|
||||
|
||||
void sci_controller_power_control_queue_insert(
|
||||
struct isci_host *ihost,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
void sci_controller_power_control_queue_remove(
|
||||
struct isci_host *ihost,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
void sci_controller_link_up(
|
||||
struct isci_host *ihost,
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
void sci_controller_link_down(
|
||||
struct isci_host *ihost,
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
void sci_controller_remote_device_stopped(
|
||||
struct isci_host *ihost,
|
||||
struct isci_remote_device *idev);
|
||||
|
||||
void sci_controller_copy_task_context(
|
||||
struct isci_host *ihost,
|
||||
struct isci_request *ireq);
|
||||
|
||||
void sci_controller_register_setup(struct isci_host *ihost);
|
||||
|
||||
enum sci_status sci_controller_continue_io(struct isci_request *ireq);
|
||||
int isci_host_scan_finished(struct Scsi_Host *, unsigned long);
|
||||
void isci_host_scan_start(struct Scsi_Host *);
|
||||
u16 isci_alloc_tag(struct isci_host *ihost);
|
||||
enum sci_status isci_free_tag(struct isci_host *ihost, u16 io_tag);
|
||||
void isci_tci_free(struct isci_host *ihost, u16 tci);
|
||||
|
||||
int isci_host_init(struct isci_host *);
|
||||
|
||||
void isci_host_init_controller_names(
|
||||
struct isci_host *isci_host,
|
||||
unsigned int controller_idx);
|
||||
|
||||
void isci_host_deinit(
|
||||
struct isci_host *);
|
||||
|
||||
void isci_host_port_link_up(
|
||||
struct isci_host *,
|
||||
struct isci_port *,
|
||||
struct isci_phy *);
|
||||
int isci_host_dev_found(struct domain_device *);
|
||||
|
||||
void isci_host_remote_device_start_complete(
|
||||
struct isci_host *,
|
||||
struct isci_remote_device *,
|
||||
enum sci_status);
|
||||
|
||||
void sci_controller_disable_interrupts(
|
||||
struct isci_host *ihost);
|
||||
|
||||
enum sci_status sci_controller_start_io(
|
||||
struct isci_host *ihost,
|
||||
struct isci_remote_device *idev,
|
||||
struct isci_request *ireq);
|
||||
|
||||
enum sci_task_status sci_controller_start_task(
|
||||
struct isci_host *ihost,
|
||||
struct isci_remote_device *idev,
|
||||
struct isci_request *ireq);
|
||||
|
||||
enum sci_status sci_controller_terminate_request(
|
||||
struct isci_host *ihost,
|
||||
struct isci_remote_device *idev,
|
||||
struct isci_request *ireq);
|
||||
|
||||
enum sci_status sci_controller_complete_io(
|
||||
struct isci_host *ihost,
|
||||
struct isci_remote_device *idev,
|
||||
struct isci_request *ireq);
|
||||
|
||||
void sci_port_configuration_agent_construct(
|
||||
struct sci_port_configuration_agent *port_agent);
|
||||
|
||||
enum sci_status sci_port_configuration_agent_initialize(
|
||||
struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent);
|
||||
#endif
|
565
drivers/scsi/isci/init.c
Normal file
565
drivers/scsi/isci/init.c
Normal file
|
@ -0,0 +1,565 @@
|
|||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/efi.h>
|
||||
#include <asm/string.h>
|
||||
#include "isci.h"
|
||||
#include "task.h"
|
||||
#include "probe_roms.h"
|
||||
|
||||
static struct scsi_transport_template *isci_transport_template;
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(isci_id_table) = {
|
||||
{ PCI_VDEVICE(INTEL, 0x1D61),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D63),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D65),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D67),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D69),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D6B),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D60),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D62),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D64),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D66),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D68),},
|
||||
{ PCI_VDEVICE(INTEL, 0x1D6A),},
|
||||
{}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, isci_id_table);
|
||||
|
||||
/* linux isci specific settings */
|
||||
|
||||
unsigned char no_outbound_task_to = 20;
|
||||
module_param(no_outbound_task_to, byte, 0);
|
||||
MODULE_PARM_DESC(no_outbound_task_to, "No Outbound Task Timeout (1us incr)");
|
||||
|
||||
u16 ssp_max_occ_to = 20;
|
||||
module_param(ssp_max_occ_to, ushort, 0);
|
||||
MODULE_PARM_DESC(ssp_max_occ_to, "SSP Max occupancy timeout (100us incr)");
|
||||
|
||||
u16 stp_max_occ_to = 5;
|
||||
module_param(stp_max_occ_to, ushort, 0);
|
||||
MODULE_PARM_DESC(stp_max_occ_to, "STP Max occupancy timeout (100us incr)");
|
||||
|
||||
u16 ssp_inactive_to = 5;
|
||||
module_param(ssp_inactive_to, ushort, 0);
|
||||
MODULE_PARM_DESC(ssp_inactive_to, "SSP inactivity timeout (100us incr)");
|
||||
|
||||
u16 stp_inactive_to = 5;
|
||||
module_param(stp_inactive_to, ushort, 0);
|
||||
MODULE_PARM_DESC(stp_inactive_to, "STP inactivity timeout (100us incr)");
|
||||
|
||||
unsigned char phy_gen = 3;
|
||||
module_param(phy_gen, byte, 0);
|
||||
MODULE_PARM_DESC(phy_gen, "PHY generation (1: 1.5Gbps 2: 3.0Gbps 3: 6.0Gbps)");
|
||||
|
||||
unsigned char max_concurr_spinup = 1;
|
||||
module_param(max_concurr_spinup, byte, 0);
|
||||
MODULE_PARM_DESC(max_concurr_spinup, "Max concurrent device spinup");
|
||||
|
||||
static struct scsi_host_template isci_sht = {
|
||||
|
||||
.module = THIS_MODULE,
|
||||
.name = DRV_NAME,
|
||||
.proc_name = DRV_NAME,
|
||||
.queuecommand = sas_queuecommand,
|
||||
.target_alloc = sas_target_alloc,
|
||||
.slave_configure = sas_slave_configure,
|
||||
.slave_destroy = sas_slave_destroy,
|
||||
.scan_finished = isci_host_scan_finished,
|
||||
.scan_start = isci_host_scan_start,
|
||||
.change_queue_depth = sas_change_queue_depth,
|
||||
.change_queue_type = sas_change_queue_type,
|
||||
.bios_param = sas_bios_param,
|
||||
.can_queue = ISCI_CAN_QUEUE_VAL,
|
||||
.cmd_per_lun = 1,
|
||||
.this_id = -1,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.max_sectors = SCSI_DEFAULT_MAX_SECTORS,
|
||||
.use_clustering = ENABLE_CLUSTERING,
|
||||
.eh_device_reset_handler = sas_eh_device_reset_handler,
|
||||
.eh_bus_reset_handler = isci_bus_reset_handler,
|
||||
.slave_alloc = sas_slave_alloc,
|
||||
.target_destroy = sas_target_destroy,
|
||||
.ioctl = sas_ioctl,
|
||||
};
|
||||
|
||||
static struct sas_domain_function_template isci_transport_ops = {
|
||||
|
||||
/* The class calls these to notify the LLDD of an event. */
|
||||
.lldd_port_formed = isci_port_formed,
|
||||
.lldd_port_deformed = isci_port_deformed,
|
||||
|
||||
/* The class calls these when a device is found or gone. */
|
||||
.lldd_dev_found = isci_remote_device_found,
|
||||
.lldd_dev_gone = isci_remote_device_gone,
|
||||
|
||||
.lldd_execute_task = isci_task_execute_task,
|
||||
/* Task Management Functions. Must be called from process context. */
|
||||
.lldd_abort_task = isci_task_abort_task,
|
||||
.lldd_abort_task_set = isci_task_abort_task_set,
|
||||
.lldd_clear_aca = isci_task_clear_aca,
|
||||
.lldd_clear_task_set = isci_task_clear_task_set,
|
||||
.lldd_I_T_nexus_reset = isci_task_I_T_nexus_reset,
|
||||
.lldd_lu_reset = isci_task_lu_reset,
|
||||
.lldd_query_task = isci_task_query_task,
|
||||
|
||||
/* Port and Adapter management */
|
||||
.lldd_clear_nexus_port = isci_task_clear_nexus_port,
|
||||
.lldd_clear_nexus_ha = isci_task_clear_nexus_ha,
|
||||
|
||||
/* Phy management */
|
||||
.lldd_control_phy = isci_phy_control,
|
||||
};
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
* P R O T E C T E D M E T H O D S
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* isci_register_sas_ha() - This method initializes various lldd
|
||||
* specific members of the sas_ha struct and calls the libsas
|
||||
* sas_register_ha() function.
|
||||
* @isci_host: This parameter specifies the lldd specific wrapper for the
|
||||
* libsas sas_ha struct.
|
||||
*
|
||||
* This method returns an error code indicating sucess or failure. The user
|
||||
* should check for possible memory allocation error return otherwise, a zero
|
||||
* indicates success.
|
||||
*/
|
||||
static int isci_register_sas_ha(struct isci_host *isci_host)
|
||||
{
|
||||
int i;
|
||||
struct sas_ha_struct *sas_ha = &(isci_host->sas_ha);
|
||||
struct asd_sas_phy **sas_phys;
|
||||
struct asd_sas_port **sas_ports;
|
||||
|
||||
sas_phys = devm_kzalloc(&isci_host->pdev->dev,
|
||||
SCI_MAX_PHYS * sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (!sas_phys)
|
||||
return -ENOMEM;
|
||||
|
||||
sas_ports = devm_kzalloc(&isci_host->pdev->dev,
|
||||
SCI_MAX_PORTS * sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (!sas_ports)
|
||||
return -ENOMEM;
|
||||
|
||||
/*----------------- Libsas Initialization Stuff----------------------
|
||||
* Set various fields in the sas_ha struct:
|
||||
*/
|
||||
|
||||
sas_ha->sas_ha_name = DRV_NAME;
|
||||
sas_ha->lldd_module = THIS_MODULE;
|
||||
sas_ha->sas_addr = &isci_host->phys[0].sas_addr[0];
|
||||
|
||||
/* set the array of phy and port structs. */
|
||||
for (i = 0; i < SCI_MAX_PHYS; i++) {
|
||||
sas_phys[i] = &isci_host->phys[i].sas_phy;
|
||||
sas_ports[i] = &isci_host->ports[i].sas_port;
|
||||
}
|
||||
|
||||
sas_ha->sas_phy = sas_phys;
|
||||
sas_ha->sas_port = sas_ports;
|
||||
sas_ha->num_phys = SCI_MAX_PHYS;
|
||||
|
||||
sas_ha->lldd_queue_size = ISCI_CAN_QUEUE_VAL;
|
||||
sas_ha->lldd_max_execute_num = 1;
|
||||
sas_ha->strict_wide_ports = 1;
|
||||
|
||||
sas_register_ha(sas_ha);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t isci_show_id(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = container_of(dev, typeof(*shost), shost_dev);
|
||||
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
|
||||
struct isci_host *ihost = container_of(sas_ha, typeof(*ihost), sas_ha);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", ihost->id);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(isci_id, S_IRUGO, isci_show_id, NULL);
|
||||
|
||||
static void isci_unregister(struct isci_host *isci_host)
|
||||
{
|
||||
struct Scsi_Host *shost;
|
||||
|
||||
if (!isci_host)
|
||||
return;
|
||||
|
||||
shost = isci_host->shost;
|
||||
device_remove_file(&shost->shost_dev, &dev_attr_isci_id);
|
||||
|
||||
sas_unregister_ha(&isci_host->sas_ha);
|
||||
|
||||
sas_remove_host(isci_host->shost);
|
||||
scsi_remove_host(isci_host->shost);
|
||||
scsi_host_put(isci_host->shost);
|
||||
}
|
||||
|
||||
static int __devinit isci_pci_init(struct pci_dev *pdev)
|
||||
{
|
||||
int err, bar_num, bar_mask = 0;
|
||||
void __iomem * const *iomap;
|
||||
|
||||
err = pcim_enable_device(pdev);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed enable PCI device %s!\n",
|
||||
pci_name(pdev));
|
||||
return err;
|
||||
}
|
||||
|
||||
for (bar_num = 0; bar_num < SCI_PCI_BAR_COUNT; bar_num++)
|
||||
bar_mask |= 1 << (bar_num * 2);
|
||||
|
||||
err = pcim_iomap_regions(pdev, bar_mask, DRV_NAME);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
iomap = pcim_iomap_table(pdev);
|
||||
if (!iomap)
|
||||
return -ENOMEM;
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
|
||||
if (err) {
|
||||
err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64));
|
||||
if (err) {
|
||||
err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int num_controllers(struct pci_dev *pdev)
|
||||
{
|
||||
/* bar size alone can tell us if we are running with a dual controller
|
||||
* part, no need to trust revision ids that might be under broken firmware
|
||||
* control
|
||||
*/
|
||||
resource_size_t scu_bar_size = pci_resource_len(pdev, SCI_SCU_BAR*2);
|
||||
resource_size_t smu_bar_size = pci_resource_len(pdev, SCI_SMU_BAR*2);
|
||||
|
||||
if (scu_bar_size >= SCI_SCU_BAR_SIZE*SCI_MAX_CONTROLLERS &&
|
||||
smu_bar_size >= SCI_SMU_BAR_SIZE*SCI_MAX_CONTROLLERS)
|
||||
return SCI_MAX_CONTROLLERS;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int isci_setup_interrupts(struct pci_dev *pdev)
|
||||
{
|
||||
int err, i, num_msix;
|
||||
struct isci_host *ihost;
|
||||
struct isci_pci_info *pci_info = to_pci_info(pdev);
|
||||
|
||||
/*
|
||||
* Determine the number of vectors associated with this
|
||||
* PCI function.
|
||||
*/
|
||||
num_msix = num_controllers(pdev) * SCI_NUM_MSI_X_INT;
|
||||
|
||||
for (i = 0; i < num_msix; i++)
|
||||
pci_info->msix_entries[i].entry = i;
|
||||
|
||||
err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix);
|
||||
if (err)
|
||||
goto intx;
|
||||
|
||||
for (i = 0; i < num_msix; i++) {
|
||||
int id = i / SCI_NUM_MSI_X_INT;
|
||||
struct msix_entry *msix = &pci_info->msix_entries[i];
|
||||
irq_handler_t isr;
|
||||
|
||||
ihost = pci_info->hosts[id];
|
||||
/* odd numbered vectors are error interrupts */
|
||||
if (i & 1)
|
||||
isr = isci_error_isr;
|
||||
else
|
||||
isr = isci_msix_isr;
|
||||
|
||||
err = devm_request_irq(&pdev->dev, msix->vector, isr, 0,
|
||||
DRV_NAME"-msix", ihost);
|
||||
if (!err)
|
||||
continue;
|
||||
|
||||
dev_info(&pdev->dev, "msix setup failed falling back to intx\n");
|
||||
while (i--) {
|
||||
id = i / SCI_NUM_MSI_X_INT;
|
||||
ihost = pci_info->hosts[id];
|
||||
msix = &pci_info->msix_entries[i];
|
||||
devm_free_irq(&pdev->dev, msix->vector, ihost);
|
||||
}
|
||||
pci_disable_msix(pdev);
|
||||
goto intx;
|
||||
}
|
||||
return 0;
|
||||
|
||||
intx:
|
||||
for_each_isci_host(i, ihost, pdev) {
|
||||
err = devm_request_irq(&pdev->dev, pdev->irq, isci_intx_isr,
|
||||
IRQF_SHARED, DRV_NAME"-intx", ihost);
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
|
||||
{
|
||||
struct isci_host *isci_host;
|
||||
struct Scsi_Host *shost;
|
||||
int err;
|
||||
|
||||
isci_host = devm_kzalloc(&pdev->dev, sizeof(*isci_host), GFP_KERNEL);
|
||||
if (!isci_host)
|
||||
return NULL;
|
||||
|
||||
isci_host->pdev = pdev;
|
||||
isci_host->id = id;
|
||||
|
||||
shost = scsi_host_alloc(&isci_sht, sizeof(void *));
|
||||
if (!shost)
|
||||
return NULL;
|
||||
isci_host->shost = shost;
|
||||
|
||||
err = isci_host_init(isci_host);
|
||||
if (err)
|
||||
goto err_shost;
|
||||
|
||||
SHOST_TO_SAS_HA(shost) = &isci_host->sas_ha;
|
||||
isci_host->sas_ha.core.shost = shost;
|
||||
shost->transportt = isci_transport_template;
|
||||
|
||||
shost->max_id = ~0;
|
||||
shost->max_lun = ~0;
|
||||
shost->max_cmd_len = MAX_COMMAND_SIZE;
|
||||
|
||||
err = scsi_add_host(shost, &pdev->dev);
|
||||
if (err)
|
||||
goto err_shost;
|
||||
|
||||
err = isci_register_sas_ha(isci_host);
|
||||
if (err)
|
||||
goto err_shost_remove;
|
||||
|
||||
err = device_create_file(&shost->shost_dev, &dev_attr_isci_id);
|
||||
if (err)
|
||||
goto err_unregister_ha;
|
||||
|
||||
return isci_host;
|
||||
|
||||
err_unregister_ha:
|
||||
sas_unregister_ha(&(isci_host->sas_ha));
|
||||
err_shost_remove:
|
||||
scsi_remove_host(shost);
|
||||
err_shost:
|
||||
scsi_host_put(shost);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct isci_pci_info *pci_info;
|
||||
int err, i;
|
||||
struct isci_host *isci_host;
|
||||
const struct firmware *fw = NULL;
|
||||
struct isci_orom *orom = NULL;
|
||||
char *source = "(platform)";
|
||||
|
||||
dev_info(&pdev->dev, "driver configured for rev: %d silicon\n",
|
||||
pdev->revision);
|
||||
|
||||
pci_info = devm_kzalloc(&pdev->dev, sizeof(*pci_info), GFP_KERNEL);
|
||||
if (!pci_info)
|
||||
return -ENOMEM;
|
||||
pci_set_drvdata(pdev, pci_info);
|
||||
|
||||
if (efi_enabled)
|
||||
orom = isci_get_efi_var(pdev);
|
||||
|
||||
if (!orom)
|
||||
orom = isci_request_oprom(pdev);
|
||||
|
||||
for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) {
|
||||
if (sci_oem_parameters_validate(&orom->ctrl[i])) {
|
||||
dev_warn(&pdev->dev,
|
||||
"[%d]: invalid oem parameters detected, falling back to firmware\n", i);
|
||||
devm_kfree(&pdev->dev, orom);
|
||||
orom = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!orom) {
|
||||
source = "(firmware)";
|
||||
orom = isci_request_firmware(pdev, fw);
|
||||
if (!orom) {
|
||||
/* TODO convert this to WARN_TAINT_ONCE once the
|
||||
* orom/efi parameter support is widely available
|
||||
*/
|
||||
dev_warn(&pdev->dev,
|
||||
"Loading user firmware failed, using default "
|
||||
"values\n");
|
||||
dev_warn(&pdev->dev,
|
||||
"Default OEM configuration being used: 4 "
|
||||
"narrow ports, and default SAS Addresses\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (orom)
|
||||
dev_info(&pdev->dev,
|
||||
"OEM SAS parameters (version: %u.%u) loaded %s\n",
|
||||
(orom->hdr.version & 0xf0) >> 4,
|
||||
(orom->hdr.version & 0xf), source);
|
||||
|
||||
pci_info->orom = orom;
|
||||
|
||||
err = isci_pci_init(pdev);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < num_controllers(pdev); i++) {
|
||||
struct isci_host *h = isci_host_alloc(pdev, i);
|
||||
|
||||
if (!h) {
|
||||
err = -ENOMEM;
|
||||
goto err_host_alloc;
|
||||
}
|
||||
pci_info->hosts[i] = h;
|
||||
}
|
||||
|
||||
err = isci_setup_interrupts(pdev);
|
||||
if (err)
|
||||
goto err_host_alloc;
|
||||
|
||||
for_each_isci_host(i, isci_host, pdev)
|
||||
scsi_scan_host(isci_host->shost);
|
||||
|
||||
return 0;
|
||||
|
||||
err_host_alloc:
|
||||
for_each_isci_host(i, isci_host, pdev)
|
||||
isci_unregister(isci_host);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __devexit isci_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct isci_host *ihost;
|
||||
int i;
|
||||
|
||||
for_each_isci_host(i, ihost, pdev) {
|
||||
isci_unregister(ihost);
|
||||
isci_host_deinit(ihost);
|
||||
sci_controller_disable_interrupts(ihost);
|
||||
}
|
||||
}
|
||||
|
||||
static struct pci_driver isci_pci_driver = {
|
||||
.name = DRV_NAME,
|
||||
.id_table = isci_id_table,
|
||||
.probe = isci_pci_probe,
|
||||
.remove = __devexit_p(isci_pci_remove),
|
||||
};
|
||||
|
||||
static __init int isci_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
pr_info("%s: Intel(R) C600 SAS Controller Driver\n", DRV_NAME);
|
||||
|
||||
isci_transport_template = sas_domain_attach_transport(&isci_transport_ops);
|
||||
if (!isci_transport_template)
|
||||
return -ENOMEM;
|
||||
|
||||
err = pci_register_driver(&isci_pci_driver);
|
||||
if (err)
|
||||
sas_release_transport(isci_transport_template);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static __exit void isci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&isci_pci_driver);
|
||||
sas_release_transport(isci_transport_template);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_FIRMWARE(ISCI_FW_NAME);
|
||||
module_init(isci_init);
|
||||
module_exit(isci_exit);
|
538
drivers/scsi/isci/isci.h
Normal file
538
drivers/scsi/isci/isci.h
Normal file
|
@ -0,0 +1,538 @@
|
|||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __ISCI_H__
|
||||
#define __ISCI_H__
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#define DRV_NAME "isci"
|
||||
#define SCI_PCI_BAR_COUNT 2
|
||||
#define SCI_NUM_MSI_X_INT 2
|
||||
#define SCI_SMU_BAR 0
|
||||
#define SCI_SMU_BAR_SIZE (16*1024)
|
||||
#define SCI_SCU_BAR 1
|
||||
#define SCI_SCU_BAR_SIZE (4*1024*1024)
|
||||
#define SCI_IO_SPACE_BAR0 2
|
||||
#define SCI_IO_SPACE_BAR1 3
|
||||
#define ISCI_CAN_QUEUE_VAL 250 /* < SCI_MAX_IO_REQUESTS ? */
|
||||
#define SCIC_CONTROLLER_STOP_TIMEOUT 5000
|
||||
|
||||
#define SCI_CONTROLLER_INVALID_IO_TAG 0xFFFF
|
||||
|
||||
#define SCI_MAX_PHYS (4UL)
|
||||
#define SCI_MAX_PORTS SCI_MAX_PHYS
|
||||
#define SCI_MAX_SMP_PHYS (384) /* not silicon constrained */
|
||||
#define SCI_MAX_REMOTE_DEVICES (256UL)
|
||||
#define SCI_MAX_IO_REQUESTS (256UL)
|
||||
#define SCI_MAX_SEQ (16)
|
||||
#define SCI_MAX_MSIX_MESSAGES (2)
|
||||
#define SCI_MAX_SCATTER_GATHER_ELEMENTS 130 /* not silicon constrained */
|
||||
#define SCI_MAX_CONTROLLERS 2
|
||||
#define SCI_MAX_DOMAINS SCI_MAX_PORTS
|
||||
|
||||
#define SCU_MAX_CRITICAL_NOTIFICATIONS (384)
|
||||
#define SCU_MAX_EVENTS_SHIFT (7)
|
||||
#define SCU_MAX_EVENTS (1 << SCU_MAX_EVENTS_SHIFT)
|
||||
#define SCU_MAX_UNSOLICITED_FRAMES (128)
|
||||
#define SCU_MAX_COMPLETION_QUEUE_SCRATCH (128)
|
||||
#define SCU_MAX_COMPLETION_QUEUE_ENTRIES (SCU_MAX_CRITICAL_NOTIFICATIONS \
|
||||
+ SCU_MAX_EVENTS \
|
||||
+ SCU_MAX_UNSOLICITED_FRAMES \
|
||||
+ SCI_MAX_IO_REQUESTS \
|
||||
+ SCU_MAX_COMPLETION_QUEUE_SCRATCH)
|
||||
#define SCU_MAX_COMPLETION_QUEUE_SHIFT (ilog2(SCU_MAX_COMPLETION_QUEUE_ENTRIES))
|
||||
|
||||
#define SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES (4096)
|
||||
#define SCU_UNSOLICITED_FRAME_BUFFER_SIZE (1024)
|
||||
#define SCU_INVALID_FRAME_INDEX (0xFFFF)
|
||||
|
||||
#define SCU_IO_REQUEST_MAX_SGE_SIZE (0x00FFFFFF)
|
||||
#define SCU_IO_REQUEST_MAX_TRANSFER_LENGTH (0x00FFFFFF)
|
||||
|
||||
static inline void check_sizes(void)
|
||||
{
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(SCU_MAX_EVENTS);
|
||||
BUILD_BUG_ON(SCU_MAX_UNSOLICITED_FRAMES <= 8);
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(SCU_MAX_UNSOLICITED_FRAMES);
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(SCU_MAX_COMPLETION_QUEUE_ENTRIES);
|
||||
BUILD_BUG_ON(SCU_MAX_UNSOLICITED_FRAMES > SCU_ABSOLUTE_MAX_UNSOLICITED_FRAMES);
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(SCI_MAX_IO_REQUESTS);
|
||||
BUILD_BUG_ON_NOT_POWER_OF_2(SCI_MAX_SEQ);
|
||||
}
|
||||
|
||||
/**
|
||||
* enum sci_status - This is the general return status enumeration for non-IO,
|
||||
* non-task management related SCI interface methods.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_status {
|
||||
/**
|
||||
* This member indicates successful completion.
|
||||
*/
|
||||
SCI_SUCCESS = 0,
|
||||
|
||||
/**
|
||||
* This value indicates that the calling method completed successfully,
|
||||
* but that the IO may have completed before having it's start method
|
||||
* invoked. This occurs during SAT translation for requests that do
|
||||
* not require an IO to the target or for any other requests that may
|
||||
* be completed without having to submit IO.
|
||||
*/
|
||||
SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
|
||||
|
||||
/**
|
||||
* This Value indicates that the SCU hardware returned an early response
|
||||
* because the io request specified more data than is returned by the
|
||||
* target device (mode pages, inquiry data, etc.). The completion routine
|
||||
* will handle this case to get the actual number of bytes transferred.
|
||||
*/
|
||||
SCI_SUCCESS_IO_DONE_EARLY,
|
||||
|
||||
/**
|
||||
* This member indicates that the object for which a state change is
|
||||
* being requested is already in said state.
|
||||
*/
|
||||
SCI_WARNING_ALREADY_IN_STATE,
|
||||
|
||||
/**
|
||||
* This member indicates interrupt coalescence timer may cause SAS
|
||||
* specification compliance issues (i.e. SMP target mode response
|
||||
* frames must be returned within 1.9 milliseconds).
|
||||
*/
|
||||
SCI_WARNING_TIMER_CONFLICT,
|
||||
|
||||
/**
|
||||
* This field indicates a sequence of action is not completed yet. Mostly,
|
||||
* this status is used when multiple ATA commands are needed in a SATI translation.
|
||||
*/
|
||||
SCI_WARNING_SEQUENCE_INCOMPLETE,
|
||||
|
||||
/**
|
||||
* This member indicates that there was a general failure.
|
||||
*/
|
||||
SCI_FAILURE,
|
||||
|
||||
/**
|
||||
* This member indicates that the SCI implementation is unable to complete
|
||||
* an operation due to a critical flaw the prevents any further operation
|
||||
* (i.e. an invalid pointer).
|
||||
*/
|
||||
SCI_FATAL_ERROR,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the state
|
||||
* of the controller is in a state that prevents successful completion.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_STATE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because there is
|
||||
* insufficient resources/memory to complete the request.
|
||||
*/
|
||||
SCI_FAILURE_INSUFFICIENT_RESOURCES,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* controller object required for the operation can't be located.
|
||||
*/
|
||||
SCI_FAILURE_CONTROLLER_NOT_FOUND,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* discovered controller type is not supported by the library.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_CONTROLLER_TYPE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested initialization data version isn't supported.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_INIT_DATA_VERSION,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested configuration of SAS Phys into SAS Ports is not supported.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested protocol is not supported by the remote device, port,
|
||||
* or controller.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_PROTOCOL,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested information type is not supported by the SCI implementation.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_INFORMATION_TYPE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* device already exists.
|
||||
*/
|
||||
SCI_FAILURE_DEVICE_EXISTS,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because adding
|
||||
* a phy to the object is not possible.
|
||||
*/
|
||||
SCI_FAILURE_ADDING_PHY_UNSUPPORTED,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the
|
||||
* requested information type is not supported by the SCI implementation.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_INFORMATION_FIELD,
|
||||
|
||||
/**
|
||||
* This member indicates the calling function failed, because the SCI
|
||||
* implementation does not support the supplied time limit.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_TIME_LIMIT,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the SCI
|
||||
* implementation does not contain the specified Phy.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_PHY,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the SCI
|
||||
* implementation does not contain the specified Port.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_PORT,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method was partly successful
|
||||
* The port was reset but not all phys in port are operational
|
||||
*/
|
||||
SCI_FAILURE_RESET_PORT_PARTIAL_SUCCESS,
|
||||
|
||||
/**
|
||||
* This member indicates that calling method failed
|
||||
* The port reset did not complete because none of the phys are operational
|
||||
*/
|
||||
SCI_FAILURE_RESET_PORT_FAILURE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the SCI
|
||||
* implementation does not contain the specified remote device.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_REMOTE_DEVICE,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the remote
|
||||
* device is in a bad state and requires a reset.
|
||||
*/
|
||||
SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method failed, because the SCI
|
||||
* implementation does not contain or support the specified IO tag.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_IO_TAG,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed and the user should
|
||||
* check the response data associated with the IO.
|
||||
*/
|
||||
SCI_FAILURE_IO_RESPONSE_VALID,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed, the failure is
|
||||
* controller implementation specific, and the response data associated
|
||||
* with the request is not valid. You can query for the controller
|
||||
* specific error information via sci_controller_get_request_status()
|
||||
*/
|
||||
SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
|
||||
|
||||
/**
|
||||
* This member indicated that the operation failed because the
|
||||
* user requested this IO to be terminated.
|
||||
*/
|
||||
SCI_FAILURE_IO_TERMINATED,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed and the associated
|
||||
* request requires a SCSI abort task to be sent to the target.
|
||||
*/
|
||||
SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed because the supplied
|
||||
* device could not be located.
|
||||
*/
|
||||
SCI_FAILURE_DEVICE_NOT_FOUND,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed because the
|
||||
* objects association is required and is not correctly set.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_ASSOCIATION,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed, because a timeout
|
||||
* occurred.
|
||||
*/
|
||||
SCI_FAILURE_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This member indicates that the operation failed, because the user
|
||||
* specified a value that is either invalid or not supported.
|
||||
*/
|
||||
SCI_FAILURE_INVALID_PARAMETER_VALUE,
|
||||
|
||||
/**
|
||||
* This value indicates that the operation failed, because the number
|
||||
* of messages (MSI-X) is not supported.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_MESSAGE_COUNT,
|
||||
|
||||
/**
|
||||
* This value indicates that the method failed due to a lack of
|
||||
* available NCQ tags.
|
||||
*/
|
||||
SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
|
||||
|
||||
/**
|
||||
* This value indicates that a protocol violation has occurred on the
|
||||
* link.
|
||||
*/
|
||||
SCI_FAILURE_PROTOCOL_VIOLATION,
|
||||
|
||||
/**
|
||||
* This value indicates a failure condition that retry may help to clear.
|
||||
*/
|
||||
SCI_FAILURE_RETRY_REQUIRED,
|
||||
|
||||
/**
|
||||
* This field indicates the retry limit was reached when a retry is attempted
|
||||
*/
|
||||
SCI_FAILURE_RETRY_LIMIT_REACHED,
|
||||
|
||||
/**
|
||||
* This member indicates the calling method was partly successful.
|
||||
* Mostly, this status is used when a LUN_RESET issued to an expander attached
|
||||
* STP device in READY NCQ substate needs to have RNC suspended/resumed
|
||||
* before posting TC.
|
||||
*/
|
||||
SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS,
|
||||
|
||||
/**
|
||||
* This field indicates an illegal phy connection based on the routing attribute
|
||||
* of both expander phy attached to each other.
|
||||
*/
|
||||
SCI_FAILURE_ILLEGAL_ROUTING_ATTRIBUTE_CONFIGURATION,
|
||||
|
||||
/**
|
||||
* This field indicates a CONFIG ROUTE INFO command has a response with function result
|
||||
* INDEX DOES NOT EXIST, usually means exceeding max route index.
|
||||
*/
|
||||
SCI_FAILURE_EXCEED_MAX_ROUTE_INDEX,
|
||||
|
||||
/**
|
||||
* This value indicates that an unsupported PCI device ID has been
|
||||
* specified. This indicates that attempts to invoke
|
||||
* sci_library_allocate_controller() will fail.
|
||||
*/
|
||||
SCI_FAILURE_UNSUPPORTED_PCI_DEVICE_ID
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum sci_io_status - This enumeration depicts all of the possible IO
|
||||
* completion status values. Each value in this enumeration maps directly
|
||||
* to a value in the enum sci_status enumeration. Please refer to that
|
||||
* enumeration for detailed comments concerning what the status represents.
|
||||
*
|
||||
* Add the API to retrieve the SCU status from the core. Check to see that the
|
||||
* following status are properly handled: - SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL
|
||||
* - SCI_IO_FAILURE_INVALID_IO_TAG
|
||||
*/
|
||||
enum sci_io_status {
|
||||
SCI_IO_SUCCESS = SCI_SUCCESS,
|
||||
SCI_IO_FAILURE = SCI_FAILURE,
|
||||
SCI_IO_SUCCESS_COMPLETE_BEFORE_START = SCI_SUCCESS_IO_COMPLETE_BEFORE_START,
|
||||
SCI_IO_SUCCESS_IO_DONE_EARLY = SCI_SUCCESS_IO_DONE_EARLY,
|
||||
SCI_IO_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE,
|
||||
SCI_IO_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES,
|
||||
SCI_IO_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
|
||||
SCI_IO_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID,
|
||||
SCI_IO_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
|
||||
SCI_IO_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED,
|
||||
SCI_IO_FAILURE_REQUIRES_SCSI_ABORT = SCI_FAILURE_IO_REQUIRES_SCSI_ABORT,
|
||||
SCI_IO_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
|
||||
SCI_IO_FAILURE_NO_NCQ_TAG_AVAILABLE = SCI_FAILURE_NO_NCQ_TAG_AVAILABLE,
|
||||
SCI_IO_FAILURE_PROTOCOL_VIOLATION = SCI_FAILURE_PROTOCOL_VIOLATION,
|
||||
|
||||
SCI_IO_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
|
||||
|
||||
SCI_IO_FAILURE_RETRY_REQUIRED = SCI_FAILURE_RETRY_REQUIRED,
|
||||
SCI_IO_FAILURE_RETRY_LIMIT_REACHED = SCI_FAILURE_RETRY_LIMIT_REACHED,
|
||||
SCI_IO_FAILURE_INVALID_REMOTE_DEVICE = SCI_FAILURE_INVALID_REMOTE_DEVICE
|
||||
};
|
||||
|
||||
/**
|
||||
* enum sci_task_status - This enumeration depicts all of the possible task
|
||||
* completion status values. Each value in this enumeration maps directly
|
||||
* to a value in the enum sci_status enumeration. Please refer to that
|
||||
* enumeration for detailed comments concerning what the status represents.
|
||||
*
|
||||
* Check to see that the following status are properly handled:
|
||||
*/
|
||||
enum sci_task_status {
|
||||
SCI_TASK_SUCCESS = SCI_SUCCESS,
|
||||
SCI_TASK_FAILURE = SCI_FAILURE,
|
||||
SCI_TASK_FAILURE_INVALID_STATE = SCI_FAILURE_INVALID_STATE,
|
||||
SCI_TASK_FAILURE_INSUFFICIENT_RESOURCES = SCI_FAILURE_INSUFFICIENT_RESOURCES,
|
||||
SCI_TASK_FAILURE_UNSUPPORTED_PROTOCOL = SCI_FAILURE_UNSUPPORTED_PROTOCOL,
|
||||
SCI_TASK_FAILURE_INVALID_TAG = SCI_FAILURE_INVALID_IO_TAG,
|
||||
SCI_TASK_FAILURE_RESPONSE_VALID = SCI_FAILURE_IO_RESPONSE_VALID,
|
||||
SCI_TASK_FAILURE_CONTROLLER_SPECIFIC_ERR = SCI_FAILURE_CONTROLLER_SPECIFIC_IO_ERR,
|
||||
SCI_TASK_FAILURE_TERMINATED = SCI_FAILURE_IO_TERMINATED,
|
||||
SCI_TASK_FAILURE_INVALID_PARAMETER_VALUE = SCI_FAILURE_INVALID_PARAMETER_VALUE,
|
||||
|
||||
SCI_TASK_FAILURE_REMOTE_DEVICE_RESET_REQUIRED = SCI_FAILURE_REMOTE_DEVICE_RESET_REQUIRED,
|
||||
SCI_TASK_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS = SCI_FAILURE_RESET_DEVICE_PARTIAL_SUCCESS
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* sci_swab32_cpy - convert between scsi and scu-hardware byte format
|
||||
* @dest: receive the 4-byte endian swapped version of src
|
||||
* @src: word aligned source buffer
|
||||
*
|
||||
* scu hardware handles SSP/SMP control, response, and unidentified
|
||||
* frames in "big endian dword" order. Regardless of host endian this
|
||||
* is always a swab32()-per-dword conversion of the standard definition,
|
||||
* i.e. single byte fields swapped and multi-byte fields in little-
|
||||
* endian
|
||||
*/
|
||||
static inline void sci_swab32_cpy(void *_dest, void *_src, ssize_t word_cnt)
|
||||
{
|
||||
u32 *dest = _dest, *src = _src;
|
||||
|
||||
while (--word_cnt >= 0)
|
||||
dest[word_cnt] = swab32(src[word_cnt]);
|
||||
}
|
||||
|
||||
extern unsigned char no_outbound_task_to;
|
||||
extern u16 ssp_max_occ_to;
|
||||
extern u16 stp_max_occ_to;
|
||||
extern u16 ssp_inactive_to;
|
||||
extern u16 stp_inactive_to;
|
||||
extern unsigned char phy_gen;
|
||||
extern unsigned char max_concurr_spinup;
|
||||
|
||||
irqreturn_t isci_msix_isr(int vec, void *data);
|
||||
irqreturn_t isci_intx_isr(int vec, void *data);
|
||||
irqreturn_t isci_error_isr(int vec, void *data);
|
||||
|
||||
/*
|
||||
* Each timer is associated with a cancellation flag that is set when
|
||||
* del_timer() is called and checked in the timer callback function. This
|
||||
* is needed since del_timer_sync() cannot be called with sci_lock held.
|
||||
* For deinit however, del_timer_sync() is used without holding the lock.
|
||||
*/
|
||||
struct sci_timer {
|
||||
struct timer_list timer;
|
||||
bool cancel;
|
||||
};
|
||||
|
||||
static inline
|
||||
void sci_init_timer(struct sci_timer *tmr, void (*fn)(unsigned long))
|
||||
{
|
||||
tmr->timer.function = fn;
|
||||
tmr->timer.data = (unsigned long) tmr;
|
||||
tmr->cancel = 0;
|
||||
init_timer(&tmr->timer);
|
||||
}
|
||||
|
||||
static inline void sci_mod_timer(struct sci_timer *tmr, unsigned long msec)
|
||||
{
|
||||
tmr->cancel = 0;
|
||||
mod_timer(&tmr->timer, jiffies + msecs_to_jiffies(msec));
|
||||
}
|
||||
|
||||
static inline void sci_del_timer(struct sci_timer *tmr)
|
||||
{
|
||||
tmr->cancel = 1;
|
||||
del_timer(&tmr->timer);
|
||||
}
|
||||
|
||||
struct sci_base_state_machine {
|
||||
const struct sci_base_state *state_table;
|
||||
u32 initial_state_id;
|
||||
u32 current_state_id;
|
||||
u32 previous_state_id;
|
||||
};
|
||||
|
||||
typedef void (*sci_state_transition_t)(struct sci_base_state_machine *sm);
|
||||
|
||||
struct sci_base_state {
|
||||
sci_state_transition_t enter_state; /* Called on state entry */
|
||||
sci_state_transition_t exit_state; /* Called on state exit */
|
||||
};
|
||||
|
||||
extern void sci_init_sm(struct sci_base_state_machine *sm,
|
||||
const struct sci_base_state *state_table,
|
||||
u32 initial_state);
|
||||
extern void sci_change_state(struct sci_base_state_machine *sm, u32 next_state);
|
||||
#endif /* __ISCI_H__ */
|
1312
drivers/scsi/isci/phy.c
Normal file
1312
drivers/scsi/isci/phy.c
Normal file
File diff suppressed because it is too large
Load diff
504
drivers/scsi/isci/phy.h
Normal file
504
drivers/scsi/isci/phy.h
Normal file
|
@ -0,0 +1,504 @@
|
|||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _ISCI_PHY_H_
|
||||
#define _ISCI_PHY_H_
|
||||
|
||||
#include <scsi/sas.h>
|
||||
#include <scsi/libsas.h>
|
||||
#include "isci.h"
|
||||
#include "sas.h"
|
||||
|
||||
/* This is the timeout value for the SATA phy to wait for a SIGNATURE FIS
|
||||
* before restarting the starting state machine. Technically, the old parallel
|
||||
* ATA specification required up to 30 seconds for a device to issue its
|
||||
* signature FIS as a result of a soft reset. Now we see that devices respond
|
||||
* generally within 15 seconds, but we'll use 25 for now.
|
||||
*/
|
||||
#define SCIC_SDS_SIGNATURE_FIS_TIMEOUT 25000
|
||||
|
||||
/* This is the timeout for the SATA OOB/SN because the hardware does not
|
||||
* recognize a hot plug after OOB signal but before the SN signals. We need to
|
||||
* make sure after a hotplug timeout if we have not received the speed event
|
||||
* notification from the hardware that we restart the hardware OOB state
|
||||
* machine.
|
||||
*/
|
||||
#define SCIC_SDS_SATA_LINK_TRAINING_TIMEOUT 250
|
||||
|
||||
enum sci_phy_protocol {
|
||||
SCIC_SDS_PHY_PROTOCOL_UNKNOWN,
|
||||
SCIC_SDS_PHY_PROTOCOL_SAS,
|
||||
SCIC_SDS_PHY_PROTOCOL_SATA,
|
||||
SCIC_SDS_MAX_PHY_PROTOCOLS
|
||||
};
|
||||
|
||||
/**
|
||||
* isci_phy - hba local phy infrastructure
|
||||
* @sm:
|
||||
* @protocol: attached device protocol
|
||||
* @phy_index: physical index relative to the controller (0-3)
|
||||
* @bcn_received_while_port_unassigned: bcn to report after port association
|
||||
* @sata_timer: timeout SATA signature FIS arrival
|
||||
*/
|
||||
struct isci_phy {
|
||||
struct sci_base_state_machine sm;
|
||||
struct isci_port *owning_port;
|
||||
enum sas_linkrate max_negotiated_speed;
|
||||
enum sci_phy_protocol protocol;
|
||||
u8 phy_index;
|
||||
bool bcn_received_while_port_unassigned;
|
||||
bool is_in_link_training;
|
||||
struct sci_timer sata_timer;
|
||||
struct scu_transport_layer_registers __iomem *transport_layer_registers;
|
||||
struct scu_link_layer_registers __iomem *link_layer_registers;
|
||||
struct asd_sas_phy sas_phy;
|
||||
struct isci_port *isci_port;
|
||||
u8 sas_addr[SAS_ADDR_SIZE];
|
||||
union {
|
||||
struct sas_identify_frame iaf;
|
||||
struct dev_to_host_fis fis;
|
||||
} frame_rcvd;
|
||||
};
|
||||
|
||||
static inline struct isci_phy *to_iphy(struct asd_sas_phy *sas_phy)
|
||||
{
|
||||
struct isci_phy *iphy = container_of(sas_phy, typeof(*iphy), sas_phy);
|
||||
|
||||
return iphy;
|
||||
}
|
||||
|
||||
struct sci_phy_cap {
|
||||
union {
|
||||
struct {
|
||||
/*
|
||||
* The SAS specification indicates the start bit shall
|
||||
* always be set to
|
||||
* 1. This implementation will have the start bit set
|
||||
* to 0 if the PHY CAPABILITIES were either not
|
||||
* received or speed negotiation failed.
|
||||
*/
|
||||
u8 start:1;
|
||||
u8 tx_ssc_type:1;
|
||||
u8 res1:2;
|
||||
u8 req_logical_linkrate:4;
|
||||
|
||||
u32 gen1_no_ssc:1;
|
||||
u32 gen1_ssc:1;
|
||||
u32 gen2_no_ssc:1;
|
||||
u32 gen2_ssc:1;
|
||||
u32 gen3_no_ssc:1;
|
||||
u32 gen3_ssc:1;
|
||||
u32 res2:17;
|
||||
u32 parity:1;
|
||||
};
|
||||
u32 all;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
/* this data structure reflects the link layer transmit identification reg */
|
||||
struct sci_phy_proto {
|
||||
union {
|
||||
struct {
|
||||
u16 _r_a:1;
|
||||
u16 smp_iport:1;
|
||||
u16 stp_iport:1;
|
||||
u16 ssp_iport:1;
|
||||
u16 _r_b:4;
|
||||
u16 _r_c:1;
|
||||
u16 smp_tport:1;
|
||||
u16 stp_tport:1;
|
||||
u16 ssp_tport:1;
|
||||
u16 _r_d:4;
|
||||
};
|
||||
u16 all;
|
||||
};
|
||||
} __packed;
|
||||
|
||||
|
||||
/**
|
||||
* struct sci_phy_properties - This structure defines the properties common to
|
||||
* all phys that can be retrieved.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_phy_properties {
|
||||
/**
|
||||
* This field specifies the port that currently contains the
|
||||
* supplied phy. This field may be set to NULL
|
||||
* if the phy is not currently contained in a port.
|
||||
*/
|
||||
struct isci_port *iport;
|
||||
|
||||
/**
|
||||
* This field specifies the link rate at which the phy is
|
||||
* currently operating.
|
||||
*/
|
||||
enum sas_linkrate negotiated_link_rate;
|
||||
|
||||
/**
|
||||
* This field specifies the index of the phy in relation to other
|
||||
* phys within the controller. This index is zero relative.
|
||||
*/
|
||||
u8 index;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_sas_phy_properties - This structure defines the properties,
|
||||
* specific to a SAS phy, that can be retrieved.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_sas_phy_properties {
|
||||
/**
|
||||
* This field delineates the Identify Address Frame received
|
||||
* from the remote end point.
|
||||
*/
|
||||
struct sas_identify_frame rcvd_iaf;
|
||||
|
||||
/**
|
||||
* This field delineates the Phy capabilities structure received
|
||||
* from the remote end point.
|
||||
*/
|
||||
struct sci_phy_cap rcvd_cap;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* struct sci_sata_phy_properties - This structure defines the properties,
|
||||
* specific to a SATA phy, that can be retrieved.
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct sci_sata_phy_properties {
|
||||
/**
|
||||
* This field delineates the signature FIS received from the
|
||||
* attached target.
|
||||
*/
|
||||
struct dev_to_host_fis signature_fis;
|
||||
|
||||
/**
|
||||
* This field specifies to the user if a port selector is connected
|
||||
* on the specified phy.
|
||||
*/
|
||||
bool is_port_selector_present;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* enum sci_phy_counter_id - This enumeration depicts the various pieces of
|
||||
* optional information that can be retrieved for a specific phy.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_phy_counter_id {
|
||||
/**
|
||||
* This PHY information field tracks the number of frames received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of frames transmitted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_TRANSMITTED_FRAME,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DWORDs received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME_WORD,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DWORDs transmitted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_TRANSMITTED_FRAME_DWORD,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of times DWORD
|
||||
* synchronization was lost.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_LOSS_OF_SYNC_ERROR,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of received DWORDs with
|
||||
* running disparity errors.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_DISPARITY_ERROR,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of received frames with a
|
||||
* CRC error (not including short or truncated frames).
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME_CRC_ERROR,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
|
||||
* primitives received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_DONE_ACK_NAK_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DONE (ACK/NAK TIMEOUT)
|
||||
* primitives transmitted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_TRANSMITTED_DONE_ACK_NAK_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of times the inactivity
|
||||
* timer for connections on the phy has been utilized.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_INACTIVITY_TIMER_EXPIRED,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
|
||||
* primitives received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_DONE_CREDIT_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of DONE (CREDIT TIMEOUT)
|
||||
* primitives transmitted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_TRANSMITTED_DONE_CREDIT_TIMEOUT,
|
||||
|
||||
/**
|
||||
* This PHY information field tracks the number of CREDIT BLOCKED
|
||||
* primitives received.
|
||||
* @note Depending on remote device implementation, credit blocks
|
||||
* may occur regularly.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_CREDIT_BLOCKED,
|
||||
|
||||
/**
|
||||
* This PHY information field contains the number of short frames
|
||||
* received. A short frame is simply a frame smaller then what is
|
||||
* allowed by either the SAS or SATA specification.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_SHORT_FRAME,
|
||||
|
||||
/**
|
||||
* This PHY information field contains the number of frames received after
|
||||
* credit has been exhausted.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME_WITHOUT_CREDIT,
|
||||
|
||||
/**
|
||||
* This PHY information field contains the number of frames received after
|
||||
* a DONE has been received.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_RECEIVED_FRAME_AFTER_DONE,
|
||||
|
||||
/**
|
||||
* This PHY information field contains the number of times the phy
|
||||
* failed to achieve DWORD synchronization during speed negotiation.
|
||||
*/
|
||||
SCIC_PHY_COUNTER_SN_DWORD_SYNC_ERROR
|
||||
};
|
||||
|
||||
enum sci_phy_states {
|
||||
/**
|
||||
* Simply the initial state for the base domain state machine.
|
||||
*/
|
||||
SCI_PHY_INITIAL,
|
||||
|
||||
/**
|
||||
* This state indicates that the phy has successfully been stopped.
|
||||
* In this state no new IO operations are permitted on this phy.
|
||||
* This state is entered from the INITIAL state.
|
||||
* This state is entered from the STARTING state.
|
||||
* This state is entered from the READY state.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCI_PHY_STOPPED,
|
||||
|
||||
/**
|
||||
* This state indicates that the phy is in the process of becomming
|
||||
* ready. In this state no new IO operations are permitted on this phy.
|
||||
* This state is entered from the STOPPED state.
|
||||
* This state is entered from the READY state.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCI_PHY_STARTING,
|
||||
|
||||
/**
|
||||
* Initial state
|
||||
*/
|
||||
SCI_PHY_SUB_INITIAL,
|
||||
|
||||
/**
|
||||
* Wait state for the hardware OSSP event type notification
|
||||
*/
|
||||
SCI_PHY_SUB_AWAIT_OSSP_EN,
|
||||
|
||||
/**
|
||||
* Wait state for the PHY speed notification
|
||||
*/
|
||||
SCI_PHY_SUB_AWAIT_SAS_SPEED_EN,
|
||||
|
||||
/**
|
||||
* Wait state for the IAF Unsolicited frame notification
|
||||
*/
|
||||
SCI_PHY_SUB_AWAIT_IAF_UF,
|
||||
|
||||
/**
|
||||
* Wait state for the request to consume power
|
||||
*/
|
||||
SCI_PHY_SUB_AWAIT_SAS_POWER,
|
||||
|
||||
/**
|
||||
* Wait state for request to consume power
|
||||
*/
|
||||
SCI_PHY_SUB_AWAIT_SATA_POWER,
|
||||
|
||||
/**
|
||||
* Wait state for the SATA PHY notification
|
||||
*/
|
||||
SCI_PHY_SUB_AWAIT_SATA_PHY_EN,
|
||||
|
||||
/**
|
||||
* Wait for the SATA PHY speed notification
|
||||
*/
|
||||
SCI_PHY_SUB_AWAIT_SATA_SPEED_EN,
|
||||
|
||||
/**
|
||||
* Wait state for the SIGNATURE FIS unsolicited frame notification
|
||||
*/
|
||||
SCI_PHY_SUB_AWAIT_SIG_FIS_UF,
|
||||
|
||||
/**
|
||||
* Exit state for this state machine
|
||||
*/
|
||||
SCI_PHY_SUB_FINAL,
|
||||
|
||||
/**
|
||||
* This state indicates the the phy is now ready. Thus, the user
|
||||
* is able to perform IO operations utilizing this phy as long as it
|
||||
* is currently part of a valid port.
|
||||
* This state is entered from the STARTING state.
|
||||
*/
|
||||
SCI_PHY_READY,
|
||||
|
||||
/**
|
||||
* This state indicates that the phy is in the process of being reset.
|
||||
* In this state no new IO operations are permitted on this phy.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCI_PHY_RESETTING,
|
||||
|
||||
/**
|
||||
* Simply the final state for the base phy state machine.
|
||||
*/
|
||||
SCI_PHY_FINAL,
|
||||
};
|
||||
|
||||
void sci_phy_construct(
|
||||
struct isci_phy *iphy,
|
||||
struct isci_port *iport,
|
||||
u8 phy_index);
|
||||
|
||||
struct isci_port *phy_get_non_dummy_port(struct isci_phy *iphy);
|
||||
|
||||
void sci_phy_set_port(
|
||||
struct isci_phy *iphy,
|
||||
struct isci_port *iport);
|
||||
|
||||
enum sci_status sci_phy_initialize(
|
||||
struct isci_phy *iphy,
|
||||
struct scu_transport_layer_registers __iomem *transport_layer_registers,
|
||||
struct scu_link_layer_registers __iomem *link_layer_registers);
|
||||
|
||||
enum sci_status sci_phy_start(
|
||||
struct isci_phy *iphy);
|
||||
|
||||
enum sci_status sci_phy_stop(
|
||||
struct isci_phy *iphy);
|
||||
|
||||
enum sci_status sci_phy_reset(
|
||||
struct isci_phy *iphy);
|
||||
|
||||
void sci_phy_resume(
|
||||
struct isci_phy *iphy);
|
||||
|
||||
void sci_phy_setup_transport(
|
||||
struct isci_phy *iphy,
|
||||
u32 device_id);
|
||||
|
||||
enum sci_status sci_phy_event_handler(
|
||||
struct isci_phy *iphy,
|
||||
u32 event_code);
|
||||
|
||||
enum sci_status sci_phy_frame_handler(
|
||||
struct isci_phy *iphy,
|
||||
u32 frame_index);
|
||||
|
||||
enum sci_status sci_phy_consume_power_handler(
|
||||
struct isci_phy *iphy);
|
||||
|
||||
void sci_phy_get_sas_address(
|
||||
struct isci_phy *iphy,
|
||||
struct sci_sas_address *sas_address);
|
||||
|
||||
void sci_phy_get_attached_sas_address(
|
||||
struct isci_phy *iphy,
|
||||
struct sci_sas_address *sas_address);
|
||||
|
||||
struct sci_phy_proto;
|
||||
void sci_phy_get_protocols(
|
||||
struct isci_phy *iphy,
|
||||
struct sci_phy_proto *protocols);
|
||||
enum sas_linkrate sci_phy_linkrate(struct isci_phy *iphy);
|
||||
|
||||
struct isci_host;
|
||||
void isci_phy_init(struct isci_phy *iphy, struct isci_host *ihost, int index);
|
||||
int isci_phy_control(struct asd_sas_phy *phy, enum phy_func func, void *buf);
|
||||
|
||||
#endif /* !defined(_ISCI_PHY_H_) */
|
1757
drivers/scsi/isci/port.c
Normal file
1757
drivers/scsi/isci/port.c
Normal file
File diff suppressed because it is too large
Load diff
306
drivers/scsi/isci/port.h
Normal file
306
drivers/scsi/isci/port.h
Normal file
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _ISCI_PORT_H_
|
||||
#define _ISCI_PORT_H_
|
||||
|
||||
#include <scsi/libsas.h>
|
||||
#include "isci.h"
|
||||
#include "sas.h"
|
||||
#include "phy.h"
|
||||
|
||||
#define SCIC_SDS_DUMMY_PORT 0xFF
|
||||
|
||||
struct isci_phy;
|
||||
struct isci_host;
|
||||
|
||||
enum isci_status {
|
||||
isci_freed = 0x00,
|
||||
isci_starting = 0x01,
|
||||
isci_ready = 0x02,
|
||||
isci_ready_for_io = 0x03,
|
||||
isci_stopping = 0x04,
|
||||
isci_stopped = 0x05,
|
||||
};
|
||||
|
||||
/**
|
||||
* struct isci_port - isci direct attached sas port object
|
||||
* @event: counts bcns and port stop events (for bcn filtering)
|
||||
* @ready_exit: several states constitute 'ready'. When exiting ready we
|
||||
* need to take extra port-teardown actions that are
|
||||
* skipped when exiting to another 'ready' state.
|
||||
* @logical_port_index: software port index
|
||||
* @physical_port_index: hardware port index
|
||||
* @active_phy_mask: identifies phy members
|
||||
* @reserved_tag:
|
||||
* @reserved_rni: reserver for port task scheduler workaround
|
||||
* @started_request_count: reference count for outstanding commands
|
||||
* @not_ready_reason: set during state transitions and notified
|
||||
* @timer: timeout start/stop operations
|
||||
*/
|
||||
struct isci_port {
|
||||
enum isci_status status;
|
||||
#define IPORT_BCN_BLOCKED 0
|
||||
#define IPORT_BCN_PENDING 1
|
||||
unsigned long flags;
|
||||
atomic_t event;
|
||||
struct isci_host *isci_host;
|
||||
struct asd_sas_port sas_port;
|
||||
struct list_head remote_dev_list;
|
||||
spinlock_t state_lock;
|
||||
struct list_head domain_dev_list;
|
||||
struct completion start_complete;
|
||||
struct completion hard_reset_complete;
|
||||
enum sci_status hard_reset_status;
|
||||
struct sci_base_state_machine sm;
|
||||
bool ready_exit;
|
||||
u8 logical_port_index;
|
||||
u8 physical_port_index;
|
||||
u8 active_phy_mask;
|
||||
u16 reserved_rni;
|
||||
u16 reserved_tag;
|
||||
u32 started_request_count;
|
||||
u32 assigned_device_count;
|
||||
u32 not_ready_reason;
|
||||
struct isci_phy *phy_table[SCI_MAX_PHYS];
|
||||
struct isci_host *owning_controller;
|
||||
struct sci_timer timer;
|
||||
struct scu_port_task_scheduler_registers __iomem *port_task_scheduler_registers;
|
||||
/* XXX rework: only one register, no need to replicate per-port */
|
||||
u32 __iomem *port_pe_configuration_register;
|
||||
struct scu_viit_entry __iomem *viit_registers;
|
||||
};
|
||||
|
||||
enum sci_port_not_ready_reason_code {
|
||||
SCIC_PORT_NOT_READY_NO_ACTIVE_PHYS,
|
||||
SCIC_PORT_NOT_READY_HARD_RESET_REQUESTED,
|
||||
SCIC_PORT_NOT_READY_INVALID_PORT_CONFIGURATION,
|
||||
SCIC_PORT_NOT_READY_RECONFIGURING,
|
||||
|
||||
SCIC_PORT_NOT_READY_REASON_CODE_MAX
|
||||
};
|
||||
|
||||
struct sci_port_end_point_properties {
|
||||
struct sci_sas_address sas_address;
|
||||
struct sci_phy_proto protocols;
|
||||
};
|
||||
|
||||
struct sci_port_properties {
|
||||
u32 index;
|
||||
struct sci_port_end_point_properties local;
|
||||
struct sci_port_end_point_properties remote;
|
||||
u32 phy_mask;
|
||||
};
|
||||
|
||||
/**
|
||||
* enum sci_port_states - This enumeration depicts all the states for the
|
||||
* common port state machine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
enum sci_port_states {
|
||||
/**
|
||||
* This state indicates that the port has successfully been stopped.
|
||||
* In this state no new IO operations are permitted.
|
||||
* This state is entered from the STOPPING state.
|
||||
*/
|
||||
SCI_PORT_STOPPED,
|
||||
|
||||
/**
|
||||
* This state indicates that the port is in the process of stopping.
|
||||
* In this state no new IO operations are permitted, but existing IO
|
||||
* operations are allowed to complete.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCI_PORT_STOPPING,
|
||||
|
||||
/**
|
||||
* This state indicates the port is now ready. Thus, the user is
|
||||
* able to perform IO operations on this port.
|
||||
* This state is entered from the STARTING state.
|
||||
*/
|
||||
SCI_PORT_READY,
|
||||
|
||||
/**
|
||||
* The substate where the port is started and ready but has no
|
||||
* active phys.
|
||||
*/
|
||||
SCI_PORT_SUB_WAITING,
|
||||
|
||||
/**
|
||||
* The substate where the port is started and ready and there is
|
||||
* at least one phy operational.
|
||||
*/
|
||||
SCI_PORT_SUB_OPERATIONAL,
|
||||
|
||||
/**
|
||||
* The substate where the port is started and there was an
|
||||
* add/remove phy event. This state is only used in Automatic
|
||||
* Port Configuration Mode (APC)
|
||||
*/
|
||||
SCI_PORT_SUB_CONFIGURING,
|
||||
|
||||
/**
|
||||
* This state indicates the port is in the process of performing a hard
|
||||
* reset. Thus, the user is unable to perform IO operations on this
|
||||
* port.
|
||||
* This state is entered from the READY state.
|
||||
*/
|
||||
SCI_PORT_RESETTING,
|
||||
|
||||
/**
|
||||
* This state indicates the port has failed a reset request. This state
|
||||
* is entered when a port reset request times out.
|
||||
* This state is entered from the RESETTING state.
|
||||
*/
|
||||
SCI_PORT_FAILED,
|
||||
|
||||
|
||||
};
|
||||
|
||||
static inline void sci_port_decrement_request_count(struct isci_port *iport)
|
||||
{
|
||||
if (WARN_ONCE(iport->started_request_count == 0,
|
||||
"%s: tried to decrement started_request_count past 0!?",
|
||||
__func__))
|
||||
/* pass */;
|
||||
else
|
||||
iport->started_request_count--;
|
||||
}
|
||||
|
||||
#define sci_port_active_phy(port, phy) \
|
||||
(((port)->active_phy_mask & (1 << (phy)->phy_index)) != 0)
|
||||
|
||||
void sci_port_construct(
|
||||
struct isci_port *iport,
|
||||
u8 port_index,
|
||||
struct isci_host *ihost);
|
||||
|
||||
enum sci_status sci_port_start(struct isci_port *iport);
|
||||
enum sci_status sci_port_stop(struct isci_port *iport);
|
||||
|
||||
enum sci_status sci_port_add_phy(
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
enum sci_status sci_port_remove_phy(
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
void sci_port_setup_transports(
|
||||
struct isci_port *iport,
|
||||
u32 device_id);
|
||||
|
||||
void isci_port_bcn_enable(struct isci_host *, struct isci_port *);
|
||||
|
||||
void sci_port_deactivate_phy(
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy,
|
||||
bool do_notify_user);
|
||||
|
||||
bool sci_port_link_detected(
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
enum sci_status sci_port_link_up(struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
enum sci_status sci_port_link_down(struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
struct isci_request;
|
||||
struct isci_remote_device;
|
||||
enum sci_status sci_port_start_io(
|
||||
struct isci_port *iport,
|
||||
struct isci_remote_device *idev,
|
||||
struct isci_request *ireq);
|
||||
|
||||
enum sci_status sci_port_complete_io(
|
||||
struct isci_port *iport,
|
||||
struct isci_remote_device *idev,
|
||||
struct isci_request *ireq);
|
||||
|
||||
enum sas_linkrate sci_port_get_max_allowed_speed(
|
||||
struct isci_port *iport);
|
||||
|
||||
void sci_port_broadcast_change_received(
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
|
||||
bool sci_port_is_valid_phy_assignment(
|
||||
struct isci_port *iport,
|
||||
u32 phy_index);
|
||||
|
||||
void sci_port_get_sas_address(
|
||||
struct isci_port *iport,
|
||||
struct sci_sas_address *sas_address);
|
||||
|
||||
void sci_port_get_attached_sas_address(
|
||||
struct isci_port *iport,
|
||||
struct sci_sas_address *sas_address);
|
||||
|
||||
enum isci_status isci_port_get_state(
|
||||
struct isci_port *isci_port);
|
||||
|
||||
void isci_port_formed(struct asd_sas_phy *);
|
||||
void isci_port_deformed(struct asd_sas_phy *);
|
||||
|
||||
void isci_port_init(
|
||||
struct isci_port *port,
|
||||
struct isci_host *host,
|
||||
int index);
|
||||
|
||||
int isci_port_perform_hard_reset(struct isci_host *ihost, struct isci_port *iport,
|
||||
struct isci_phy *iphy);
|
||||
#endif /* !defined(_ISCI_PORT_H_) */
|
754
drivers/scsi/isci/port_config.c
Normal file
754
drivers/scsi/isci/port_config.c
Normal file
|
@ -0,0 +1,754 @@
|
|||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "host.h"
|
||||
|
||||
#define SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT (10)
|
||||
#define SCIC_SDS_APC_RECONFIGURATION_TIMEOUT (10)
|
||||
#define SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION (100)
|
||||
|
||||
enum SCIC_SDS_APC_ACTIVITY {
|
||||
SCIC_SDS_APC_SKIP_PHY,
|
||||
SCIC_SDS_APC_ADD_PHY,
|
||||
SCIC_SDS_APC_START_TIMER,
|
||||
|
||||
SCIC_SDS_APC_ACTIVITY_MAX
|
||||
};
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* General port configuration agent routines
|
||||
* ****************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
* @address_one: A SAS Address to be compared.
|
||||
* @address_two: A SAS Address to be compared.
|
||||
*
|
||||
* Compare the two SAS Address and if SAS Address One is greater than SAS
|
||||
* Address Two then return > 0 else if SAS Address One is less than SAS Address
|
||||
* Two return < 0 Otherwise they are the same return 0 A signed value of x > 0
|
||||
* > y where x is returned for Address One > Address Two y is returned for
|
||||
* Address One < Address Two 0 is returned ofr Address One = Address Two
|
||||
*/
|
||||
static s32 sci_sas_address_compare(
|
||||
struct sci_sas_address address_one,
|
||||
struct sci_sas_address address_two)
|
||||
{
|
||||
if (address_one.high > address_two.high) {
|
||||
return 1;
|
||||
} else if (address_one.high < address_two.high) {
|
||||
return -1;
|
||||
} else if (address_one.low > address_two.low) {
|
||||
return 1;
|
||||
} else if (address_one.low < address_two.low) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The two SAS Address must be identical */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: The controller object used for the port search.
|
||||
* @phy: The phy object to match.
|
||||
*
|
||||
* This routine will find a matching port for the phy. This means that the
|
||||
* port and phy both have the same broadcast sas address and same received sas
|
||||
* address. The port address or the NULL if there is no matching
|
||||
* port. port address if the port can be found to match the phy.
|
||||
* NULL if there is no matching port for the phy.
|
||||
*/
|
||||
static struct isci_port *sci_port_configuration_agent_find_port(
|
||||
struct isci_host *ihost,
|
||||
struct isci_phy *iphy)
|
||||
{
|
||||
u8 i;
|
||||
struct sci_sas_address port_sas_address;
|
||||
struct sci_sas_address port_attached_device_address;
|
||||
struct sci_sas_address phy_sas_address;
|
||||
struct sci_sas_address phy_attached_device_address;
|
||||
|
||||
/*
|
||||
* Since this phy can be a member of a wide port check to see if one or
|
||||
* more phys match the sent and received SAS address as this phy in which
|
||||
* case it should participate in the same port.
|
||||
*/
|
||||
sci_phy_get_sas_address(iphy, &phy_sas_address);
|
||||
sci_phy_get_attached_sas_address(iphy, &phy_attached_device_address);
|
||||
|
||||
for (i = 0; i < ihost->logical_port_entries; i++) {
|
||||
struct isci_port *iport = &ihost->ports[i];
|
||||
|
||||
sci_port_get_sas_address(iport, &port_sas_address);
|
||||
sci_port_get_attached_sas_address(iport, &port_attached_device_address);
|
||||
|
||||
if (sci_sas_address_compare(port_sas_address, phy_sas_address) == 0 &&
|
||||
sci_sas_address_compare(port_attached_device_address, phy_attached_device_address) == 0)
|
||||
return iport;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object that contains the port agent
|
||||
* @port_agent: This is the port configruation agent for the controller.
|
||||
*
|
||||
* This routine will validate the port configuration is correct for the SCU
|
||||
* hardware. The SCU hardware allows for port configurations as follows. LP0
|
||||
* -> (PE0), (PE0, PE1), (PE0, PE1, PE2, PE3) LP1 -> (PE1) LP2 -> (PE2), (PE2,
|
||||
* PE3) LP3 -> (PE3) enum sci_status SCI_SUCCESS the port configuration is valid for
|
||||
* this port configuration agent. SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION
|
||||
* the port configuration is not valid for this port configuration agent.
|
||||
*/
|
||||
static enum sci_status sci_port_configuration_agent_validate_ports(
|
||||
struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent)
|
||||
{
|
||||
struct sci_sas_address first_address;
|
||||
struct sci_sas_address second_address;
|
||||
|
||||
/*
|
||||
* Sanity check the max ranges for all the phys the max index
|
||||
* is always equal to the port range index */
|
||||
if (port_agent->phy_valid_port_range[0].max_index != 0 ||
|
||||
port_agent->phy_valid_port_range[1].max_index != 1 ||
|
||||
port_agent->phy_valid_port_range[2].max_index != 2 ||
|
||||
port_agent->phy_valid_port_range[3].max_index != 3)
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
|
||||
/*
|
||||
* This is a request to configure a single x4 port or at least attempt
|
||||
* to make all the phys into a single port */
|
||||
if (port_agent->phy_valid_port_range[0].min_index == 0 &&
|
||||
port_agent->phy_valid_port_range[1].min_index == 0 &&
|
||||
port_agent->phy_valid_port_range[2].min_index == 0 &&
|
||||
port_agent->phy_valid_port_range[3].min_index == 0)
|
||||
return SCI_SUCCESS;
|
||||
|
||||
/*
|
||||
* This is a degenerate case where phy 1 and phy 2 are assigned
|
||||
* to the same port this is explicitly disallowed by the hardware
|
||||
* unless they are part of the same x4 port and this condition was
|
||||
* already checked above. */
|
||||
if (port_agent->phy_valid_port_range[2].min_index == 1) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
/*
|
||||
* PE0 and PE3 can never have the same SAS Address unless they
|
||||
* are part of the same x4 wide port and we have already checked
|
||||
* for this condition. */
|
||||
sci_phy_get_sas_address(&ihost->phys[0], &first_address);
|
||||
sci_phy_get_sas_address(&ihost->phys[3], &second_address);
|
||||
|
||||
if (sci_sas_address_compare(first_address, second_address) == 0) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
/*
|
||||
* PE0 and PE1 are configured into a 2x1 ports make sure that the
|
||||
* SAS Address for PE0 and PE2 are different since they can not be
|
||||
* part of the same port. */
|
||||
if (port_agent->phy_valid_port_range[0].min_index == 0 &&
|
||||
port_agent->phy_valid_port_range[1].min_index == 1) {
|
||||
sci_phy_get_sas_address(&ihost->phys[0], &first_address);
|
||||
sci_phy_get_sas_address(&ihost->phys[2], &second_address);
|
||||
|
||||
if (sci_sas_address_compare(first_address, second_address) == 0) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* PE2 and PE3 are configured into a 2x1 ports make sure that the
|
||||
* SAS Address for PE1 and PE3 are different since they can not be
|
||||
* part of the same port. */
|
||||
if (port_agent->phy_valid_port_range[2].min_index == 2 &&
|
||||
port_agent->phy_valid_port_range[3].min_index == 3) {
|
||||
sci_phy_get_sas_address(&ihost->phys[1], &first_address);
|
||||
sci_phy_get_sas_address(&ihost->phys[3], &second_address);
|
||||
|
||||
if (sci_sas_address_compare(first_address, second_address) == 0) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
}
|
||||
|
||||
return SCI_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* Manual port configuration agent routines
|
||||
* ****************************************************************************** */
|
||||
|
||||
/* verify all of the phys in the same port are using the same SAS address */
|
||||
static enum sci_status
|
||||
sci_mpc_agent_validate_phy_configuration(struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent)
|
||||
{
|
||||
u32 phy_mask;
|
||||
u32 assigned_phy_mask;
|
||||
struct sci_sas_address sas_address;
|
||||
struct sci_sas_address phy_assigned_address;
|
||||
u8 port_index;
|
||||
u8 phy_index;
|
||||
|
||||
assigned_phy_mask = 0;
|
||||
sas_address.high = 0;
|
||||
sas_address.low = 0;
|
||||
|
||||
for (port_index = 0; port_index < SCI_MAX_PORTS; port_index++) {
|
||||
phy_mask = ihost->oem_parameters.ports[port_index].phy_mask;
|
||||
|
||||
if (!phy_mask)
|
||||
continue;
|
||||
/*
|
||||
* Make sure that one or more of the phys were not already assinged to
|
||||
* a different port. */
|
||||
if ((phy_mask & ~assigned_phy_mask) == 0) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
/* Find the starting phy index for this round through the loop */
|
||||
for (phy_index = 0; phy_index < SCI_MAX_PHYS; phy_index++) {
|
||||
if ((phy_mask & (1 << phy_index)) == 0)
|
||||
continue;
|
||||
sci_phy_get_sas_address(&ihost->phys[phy_index],
|
||||
&sas_address);
|
||||
|
||||
/*
|
||||
* The phy_index can be used as the starting point for the
|
||||
* port range since the hardware starts all logical ports
|
||||
* the same as the PE index. */
|
||||
port_agent->phy_valid_port_range[phy_index].min_index = port_index;
|
||||
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
|
||||
|
||||
if (phy_index != port_index) {
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* See how many additional phys are being added to this logical port.
|
||||
* Note: We have not moved the current phy_index so we will actually
|
||||
* compare the startting phy with itself.
|
||||
* This is expected and required to add the phy to the port. */
|
||||
while (phy_index < SCI_MAX_PHYS) {
|
||||
if ((phy_mask & (1 << phy_index)) == 0)
|
||||
continue;
|
||||
sci_phy_get_sas_address(&ihost->phys[phy_index],
|
||||
&phy_assigned_address);
|
||||
|
||||
if (sci_sas_address_compare(sas_address, phy_assigned_address) != 0) {
|
||||
/*
|
||||
* The phy mask specified that this phy is part of the same port
|
||||
* as the starting phy and it is not so fail this configuration */
|
||||
return SCI_FAILURE_UNSUPPORTED_PORT_CONFIGURATION;
|
||||
}
|
||||
|
||||
port_agent->phy_valid_port_range[phy_index].min_index = port_index;
|
||||
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
|
||||
|
||||
sci_port_add_phy(&ihost->ports[port_index],
|
||||
&ihost->phys[phy_index]);
|
||||
|
||||
assigned_phy_mask |= (1 << phy_index);
|
||||
}
|
||||
|
||||
phy_index++;
|
||||
}
|
||||
|
||||
return sci_port_configuration_agent_validate_ports(ihost, port_agent);
|
||||
}
|
||||
|
||||
static void mpc_agent_timeout(unsigned long data)
|
||||
{
|
||||
u8 index;
|
||||
struct sci_timer *tmr = (struct sci_timer *)data;
|
||||
struct sci_port_configuration_agent *port_agent;
|
||||
struct isci_host *ihost;
|
||||
unsigned long flags;
|
||||
u16 configure_phy_mask;
|
||||
|
||||
port_agent = container_of(tmr, typeof(*port_agent), timer);
|
||||
ihost = container_of(port_agent, typeof(*ihost), port_agent);
|
||||
|
||||
spin_lock_irqsave(&ihost->scic_lock, flags);
|
||||
|
||||
if (tmr->cancel)
|
||||
goto done;
|
||||
|
||||
port_agent->timer_pending = false;
|
||||
|
||||
/* Find the mask of phys that are reported read but as yet unconfigured into a port */
|
||||
configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
|
||||
|
||||
for (index = 0; index < SCI_MAX_PHYS; index++) {
|
||||
struct isci_phy *iphy = &ihost->phys[index];
|
||||
|
||||
if (configure_phy_mask & (1 << index)) {
|
||||
port_agent->link_up_handler(ihost, port_agent,
|
||||
phy_get_non_dummy_port(iphy),
|
||||
iphy);
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&ihost->scic_lock, flags);
|
||||
}
|
||||
|
||||
static void sci_mpc_agent_link_up(struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent,
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy)
|
||||
{
|
||||
/* If the port is NULL then the phy was not assigned to a port.
|
||||
* This is because the phy was not given the same SAS Address as
|
||||
* the other PHYs in the port.
|
||||
*/
|
||||
if (!iport)
|
||||
return;
|
||||
|
||||
port_agent->phy_ready_mask |= (1 << iphy->phy_index);
|
||||
sci_port_link_up(iport, iphy);
|
||||
if ((iport->active_phy_mask & (1 << iphy->phy_index)))
|
||||
port_agent->phy_configured_mask |= (1 << iphy->phy_index);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object that receives the link down
|
||||
* notification.
|
||||
* @port: This is the port object associated with the phy. If the is no
|
||||
* associated port this is an NULL. The port is an invalid
|
||||
* handle only if the phy was never port of this port. This happens when
|
||||
* the phy is not broadcasting the same SAS address as the other phys in the
|
||||
* assigned port.
|
||||
* @phy: This is the phy object which has gone link down.
|
||||
*
|
||||
* This function handles the manual port configuration link down notifications.
|
||||
* Since all ports and phys are associated at initialization time we just turn
|
||||
* around and notifiy the port object of the link down event. If this PHY is
|
||||
* not associated with a port there is no action taken. Is it possible to get a
|
||||
* link down notification from a phy that has no assocoated port?
|
||||
*/
|
||||
static void sci_mpc_agent_link_down(
|
||||
struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent,
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy)
|
||||
{
|
||||
if (iport != NULL) {
|
||||
/*
|
||||
* If we can form a new port from the remainder of the phys
|
||||
* then we want to start the timer to allow the SCI User to
|
||||
* cleanup old devices and rediscover the port before
|
||||
* rebuilding the port with the phys that remain in the ready
|
||||
* state.
|
||||
*/
|
||||
port_agent->phy_ready_mask &= ~(1 << iphy->phy_index);
|
||||
port_agent->phy_configured_mask &= ~(1 << iphy->phy_index);
|
||||
|
||||
/*
|
||||
* Check to see if there are more phys waiting to be
|
||||
* configured into a port. If there are allow the SCI User
|
||||
* to tear down this port, if necessary, and then reconstruct
|
||||
* the port after the timeout.
|
||||
*/
|
||||
if ((port_agent->phy_configured_mask == 0x0000) &&
|
||||
(port_agent->phy_ready_mask != 0x0000) &&
|
||||
!port_agent->timer_pending) {
|
||||
port_agent->timer_pending = true;
|
||||
|
||||
sci_mod_timer(&port_agent->timer,
|
||||
SCIC_SDS_MPC_RECONFIGURATION_TIMEOUT);
|
||||
}
|
||||
|
||||
sci_port_link_down(iport, iphy);
|
||||
}
|
||||
}
|
||||
|
||||
/* verify phys are assigned a valid SAS address for automatic port
|
||||
* configuration mode.
|
||||
*/
|
||||
static enum sci_status
|
||||
sci_apc_agent_validate_phy_configuration(struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent)
|
||||
{
|
||||
u8 phy_index;
|
||||
u8 port_index;
|
||||
struct sci_sas_address sas_address;
|
||||
struct sci_sas_address phy_assigned_address;
|
||||
|
||||
phy_index = 0;
|
||||
|
||||
while (phy_index < SCI_MAX_PHYS) {
|
||||
port_index = phy_index;
|
||||
|
||||
/* Get the assigned SAS Address for the first PHY on the controller. */
|
||||
sci_phy_get_sas_address(&ihost->phys[phy_index],
|
||||
&sas_address);
|
||||
|
||||
while (++phy_index < SCI_MAX_PHYS) {
|
||||
sci_phy_get_sas_address(&ihost->phys[phy_index],
|
||||
&phy_assigned_address);
|
||||
|
||||
/* Verify each of the SAS address are all the same for every PHY */
|
||||
if (sci_sas_address_compare(sas_address, phy_assigned_address) == 0) {
|
||||
port_agent->phy_valid_port_range[phy_index].min_index = port_index;
|
||||
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
|
||||
} else {
|
||||
port_agent->phy_valid_port_range[phy_index].min_index = phy_index;
|
||||
port_agent->phy_valid_port_range[phy_index].max_index = phy_index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sci_port_configuration_agent_validate_ports(ihost, port_agent);
|
||||
}
|
||||
|
||||
static void sci_apc_agent_configure_ports(struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent,
|
||||
struct isci_phy *iphy,
|
||||
bool start_timer)
|
||||
{
|
||||
u8 port_index;
|
||||
enum sci_status status;
|
||||
struct isci_port *iport;
|
||||
enum SCIC_SDS_APC_ACTIVITY apc_activity = SCIC_SDS_APC_SKIP_PHY;
|
||||
|
||||
iport = sci_port_configuration_agent_find_port(ihost, iphy);
|
||||
|
||||
if (iport) {
|
||||
if (sci_port_is_valid_phy_assignment(iport, iphy->phy_index))
|
||||
apc_activity = SCIC_SDS_APC_ADD_PHY;
|
||||
else
|
||||
apc_activity = SCIC_SDS_APC_SKIP_PHY;
|
||||
} else {
|
||||
/*
|
||||
* There is no matching Port for this PHY so lets search through the
|
||||
* Ports and see if we can add the PHY to its own port or maybe start
|
||||
* the timer and wait to see if a wider port can be made.
|
||||
*
|
||||
* Note the break when we reach the condition of the port id == phy id */
|
||||
for (port_index = port_agent->phy_valid_port_range[iphy->phy_index].min_index;
|
||||
port_index <= port_agent->phy_valid_port_range[iphy->phy_index].max_index;
|
||||
port_index++) {
|
||||
|
||||
iport = &ihost->ports[port_index];
|
||||
|
||||
/* First we must make sure that this PHY can be added to this Port. */
|
||||
if (sci_port_is_valid_phy_assignment(iport, iphy->phy_index)) {
|
||||
/*
|
||||
* Port contains a PHY with a greater PHY ID than the current
|
||||
* PHY that has gone link up. This phy can not be part of any
|
||||
* port so skip it and move on. */
|
||||
if (iport->active_phy_mask > (1 << iphy->phy_index)) {
|
||||
apc_activity = SCIC_SDS_APC_SKIP_PHY;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have reached the end of our Port list and have not found
|
||||
* any reason why we should not either add the PHY to the port
|
||||
* or wait for more phys to become active. */
|
||||
if (iport->physical_port_index == iphy->phy_index) {
|
||||
/*
|
||||
* The Port either has no active PHYs.
|
||||
* Consider that if the port had any active PHYs we would have
|
||||
* or active PHYs with
|
||||
* a lower PHY Id than this PHY. */
|
||||
if (apc_activity != SCIC_SDS_APC_START_TIMER) {
|
||||
apc_activity = SCIC_SDS_APC_ADD_PHY;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The current Port has no active PHYs and this PHY could be part
|
||||
* of this Port. Since we dont know as yet setup to start the
|
||||
* timer and see if there is a better configuration. */
|
||||
if (iport->active_phy_mask == 0) {
|
||||
apc_activity = SCIC_SDS_APC_START_TIMER;
|
||||
}
|
||||
} else if (iport->active_phy_mask != 0) {
|
||||
/*
|
||||
* The Port has an active phy and the current Phy can not
|
||||
* participate in this port so skip the PHY and see if
|
||||
* there is a better configuration. */
|
||||
apc_activity = SCIC_SDS_APC_SKIP_PHY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if the start timer operations should instead map to an
|
||||
* add phy operation. This is caused because we have been waiting to
|
||||
* add a phy to a port but could not becuase the automatic port
|
||||
* configuration engine had a choice of possible ports for the phy.
|
||||
* Since we have gone through a timeout we are going to restrict the
|
||||
* choice to the smallest possible port. */
|
||||
if (
|
||||
(start_timer == false)
|
||||
&& (apc_activity == SCIC_SDS_APC_START_TIMER)
|
||||
) {
|
||||
apc_activity = SCIC_SDS_APC_ADD_PHY;
|
||||
}
|
||||
|
||||
switch (apc_activity) {
|
||||
case SCIC_SDS_APC_ADD_PHY:
|
||||
status = sci_port_add_phy(iport, iphy);
|
||||
|
||||
if (status == SCI_SUCCESS) {
|
||||
port_agent->phy_configured_mask |= (1 << iphy->phy_index);
|
||||
}
|
||||
break;
|
||||
|
||||
case SCIC_SDS_APC_START_TIMER:
|
||||
/*
|
||||
* This can occur for either a link down event, or a link
|
||||
* up event where we cannot yet tell the port to which a
|
||||
* phy belongs.
|
||||
*/
|
||||
if (port_agent->timer_pending)
|
||||
sci_del_timer(&port_agent->timer);
|
||||
|
||||
port_agent->timer_pending = true;
|
||||
sci_mod_timer(&port_agent->timer,
|
||||
SCIC_SDS_APC_WAIT_LINK_UP_NOTIFICATION);
|
||||
break;
|
||||
|
||||
case SCIC_SDS_APC_SKIP_PHY:
|
||||
default:
|
||||
/* do nothing the PHY can not be made part of a port at this time. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sci_apc_agent_link_up - handle apc link up events
|
||||
* @scic: This is the controller object that receives the link up
|
||||
* notification.
|
||||
* @sci_port: This is the port object associated with the phy. If the is no
|
||||
* associated port this is an NULL.
|
||||
* @sci_phy: This is the phy object which has gone link up.
|
||||
*
|
||||
* This method handles the automatic port configuration for link up
|
||||
* notifications. Is it possible to get a link down notification from a phy
|
||||
* that has no assocoated port?
|
||||
*/
|
||||
static void sci_apc_agent_link_up(struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent,
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy)
|
||||
{
|
||||
u8 phy_index = iphy->phy_index;
|
||||
|
||||
if (!iport) {
|
||||
/* the phy is not the part of this port */
|
||||
port_agent->phy_ready_mask |= 1 << phy_index;
|
||||
sci_apc_agent_configure_ports(ihost, port_agent, iphy, true);
|
||||
} else {
|
||||
/* the phy is already the part of the port */
|
||||
u32 port_state = iport->sm.current_state_id;
|
||||
|
||||
/* if the PORT'S state is resetting then the link up is from
|
||||
* port hard reset in this case, we need to tell the port
|
||||
* that link up is recieved
|
||||
*/
|
||||
BUG_ON(port_state != SCI_PORT_RESETTING);
|
||||
port_agent->phy_ready_mask |= 1 << phy_index;
|
||||
sci_port_link_up(iport, iphy);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @controller: This is the controller object that receives the link down
|
||||
* notification.
|
||||
* @iport: This is the port object associated with the phy. If the is no
|
||||
* associated port this is an NULL.
|
||||
* @iphy: This is the phy object which has gone link down.
|
||||
*
|
||||
* This method handles the automatic port configuration link down
|
||||
* notifications. not associated with a port there is no action taken. Is it
|
||||
* possible to get a link down notification from a phy that has no assocoated
|
||||
* port?
|
||||
*/
|
||||
static void sci_apc_agent_link_down(
|
||||
struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent,
|
||||
struct isci_port *iport,
|
||||
struct isci_phy *iphy)
|
||||
{
|
||||
port_agent->phy_ready_mask &= ~(1 << iphy->phy_index);
|
||||
|
||||
if (!iport)
|
||||
return;
|
||||
if (port_agent->phy_configured_mask & (1 << iphy->phy_index)) {
|
||||
enum sci_status status;
|
||||
|
||||
status = sci_port_remove_phy(iport, iphy);
|
||||
|
||||
if (status == SCI_SUCCESS)
|
||||
port_agent->phy_configured_mask &= ~(1 << iphy->phy_index);
|
||||
}
|
||||
}
|
||||
|
||||
/* configure the phys into ports when the timer fires */
|
||||
static void apc_agent_timeout(unsigned long data)
|
||||
{
|
||||
u32 index;
|
||||
struct sci_timer *tmr = (struct sci_timer *)data;
|
||||
struct sci_port_configuration_agent *port_agent;
|
||||
struct isci_host *ihost;
|
||||
unsigned long flags;
|
||||
u16 configure_phy_mask;
|
||||
|
||||
port_agent = container_of(tmr, typeof(*port_agent), timer);
|
||||
ihost = container_of(port_agent, typeof(*ihost), port_agent);
|
||||
|
||||
spin_lock_irqsave(&ihost->scic_lock, flags);
|
||||
|
||||
if (tmr->cancel)
|
||||
goto done;
|
||||
|
||||
port_agent->timer_pending = false;
|
||||
|
||||
configure_phy_mask = ~port_agent->phy_configured_mask & port_agent->phy_ready_mask;
|
||||
|
||||
if (!configure_phy_mask)
|
||||
return;
|
||||
|
||||
for (index = 0; index < SCI_MAX_PHYS; index++) {
|
||||
if ((configure_phy_mask & (1 << index)) == 0)
|
||||
continue;
|
||||
|
||||
sci_apc_agent_configure_ports(ihost, port_agent,
|
||||
&ihost->phys[index], false);
|
||||
}
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&ihost->scic_lock, flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************************************************************************
|
||||
* Public port configuration agent routines
|
||||
* ****************************************************************************** */
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* This method will construct the port configuration agent for operation. This
|
||||
* call is universal for both manual port configuration and automatic port
|
||||
* configuration modes.
|
||||
*/
|
||||
void sci_port_configuration_agent_construct(
|
||||
struct sci_port_configuration_agent *port_agent)
|
||||
{
|
||||
u32 index;
|
||||
|
||||
port_agent->phy_configured_mask = 0x00;
|
||||
port_agent->phy_ready_mask = 0x00;
|
||||
|
||||
port_agent->link_up_handler = NULL;
|
||||
port_agent->link_down_handler = NULL;
|
||||
|
||||
port_agent->timer_pending = false;
|
||||
|
||||
for (index = 0; index < SCI_MAX_PORTS; index++) {
|
||||
port_agent->phy_valid_port_range[index].min_index = 0;
|
||||
port_agent->phy_valid_port_range[index].max_index = 0;
|
||||
}
|
||||
}
|
||||
|
||||
enum sci_status sci_port_configuration_agent_initialize(
|
||||
struct isci_host *ihost,
|
||||
struct sci_port_configuration_agent *port_agent)
|
||||
{
|
||||
enum sci_status status;
|
||||
enum sci_port_configuration_mode mode;
|
||||
|
||||
mode = ihost->oem_parameters.controller.mode_type;
|
||||
|
||||
if (mode == SCIC_PORT_MANUAL_CONFIGURATION_MODE) {
|
||||
status = sci_mpc_agent_validate_phy_configuration(
|
||||
ihost, port_agent);
|
||||
|
||||
port_agent->link_up_handler = sci_mpc_agent_link_up;
|
||||
port_agent->link_down_handler = sci_mpc_agent_link_down;
|
||||
|
||||
sci_init_timer(&port_agent->timer, mpc_agent_timeout);
|
||||
} else {
|
||||
status = sci_apc_agent_validate_phy_configuration(
|
||||
ihost, port_agent);
|
||||
|
||||
port_agent->link_up_handler = sci_apc_agent_link_up;
|
||||
port_agent->link_down_handler = sci_apc_agent_link_down;
|
||||
|
||||
sci_init_timer(&port_agent->timer, apc_agent_timeout);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
243
drivers/scsi/isci/probe_roms.c
Normal file
243
drivers/scsi/isci/probe_roms.c
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*/
|
||||
|
||||
/* probe_roms - scan for oem parameters */
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/efi.h>
|
||||
#include <asm/probe_roms.h>
|
||||
|
||||
#include "isci.h"
|
||||
#include "task.h"
|
||||
#include "probe_roms.h"
|
||||
|
||||
static efi_char16_t isci_efivar_name[] = {
|
||||
'R', 's', 't', 'S', 'c', 'u', 'O'
|
||||
};
|
||||
|
||||
struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
|
||||
{
|
||||
void __iomem *oprom = pci_map_biosrom(pdev);
|
||||
struct isci_orom *rom = NULL;
|
||||
size_t len, i;
|
||||
int j;
|
||||
char oem_sig[4];
|
||||
struct isci_oem_hdr oem_hdr;
|
||||
u8 *tmp, sum;
|
||||
|
||||
if (!oprom)
|
||||
return NULL;
|
||||
|
||||
len = pci_biosrom_size(pdev);
|
||||
rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL);
|
||||
if (!rom) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Unable to allocate memory for orom\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < len && rom; i += ISCI_OEM_SIG_SIZE) {
|
||||
memcpy_fromio(oem_sig, oprom + i, ISCI_OEM_SIG_SIZE);
|
||||
|
||||
/* we think we found the OEM table */
|
||||
if (memcmp(oem_sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) == 0) {
|
||||
size_t copy_len;
|
||||
|
||||
memcpy_fromio(&oem_hdr, oprom + i, sizeof(oem_hdr));
|
||||
|
||||
copy_len = min(oem_hdr.len - sizeof(oem_hdr),
|
||||
sizeof(*rom));
|
||||
|
||||
memcpy_fromio(rom,
|
||||
oprom + i + sizeof(oem_hdr),
|
||||
copy_len);
|
||||
|
||||
/* calculate checksum */
|
||||
tmp = (u8 *)&oem_hdr;
|
||||
for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++)
|
||||
sum += *tmp;
|
||||
|
||||
tmp = (u8 *)rom;
|
||||
for (j = 0; j < sizeof(*rom); j++, tmp++)
|
||||
sum += *tmp;
|
||||
|
||||
if (sum != 0) {
|
||||
dev_warn(&pdev->dev,
|
||||
"OEM table checksum failed\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* keep going if that's not the oem param table */
|
||||
if (memcmp(rom->hdr.signature,
|
||||
ISCI_ROM_SIG,
|
||||
ISCI_ROM_SIG_SIZE) != 0)
|
||||
continue;
|
||||
|
||||
dev_info(&pdev->dev,
|
||||
"OEM parameter table found in OROM\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i >= len) {
|
||||
dev_err(&pdev->dev, "oprom parse error\n");
|
||||
devm_kfree(&pdev->dev, rom);
|
||||
rom = NULL;
|
||||
}
|
||||
pci_unmap_biosrom(oprom);
|
||||
|
||||
return rom;
|
||||
}
|
||||
|
||||
enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem,
|
||||
struct isci_orom *orom, int scu_index)
|
||||
{
|
||||
/* check for valid inputs */
|
||||
if (scu_index < 0 || scu_index >= SCI_MAX_CONTROLLERS ||
|
||||
scu_index > orom->hdr.num_elements || !oem)
|
||||
return -EINVAL;
|
||||
|
||||
*oem = orom->ctrl[scu_index];
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw)
|
||||
{
|
||||
struct isci_orom *orom = NULL, *data;
|
||||
int i, j;
|
||||
|
||||
if (request_firmware(&fw, ISCI_FW_NAME, &pdev->dev) != 0)
|
||||
return NULL;
|
||||
|
||||
if (fw->size < sizeof(*orom))
|
||||
goto out;
|
||||
|
||||
data = (struct isci_orom *)fw->data;
|
||||
|
||||
if (strncmp(ISCI_ROM_SIG, data->hdr.signature,
|
||||
strlen(ISCI_ROM_SIG)) != 0)
|
||||
goto out;
|
||||
|
||||
orom = devm_kzalloc(&pdev->dev, fw->size, GFP_KERNEL);
|
||||
if (!orom)
|
||||
goto out;
|
||||
|
||||
memcpy(orom, fw->data, fw->size);
|
||||
|
||||
if (is_c0(pdev))
|
||||
goto out;
|
||||
|
||||
/*
|
||||
* deprecated: override default amp_control for pre-preproduction
|
||||
* silicon revisions
|
||||
*/
|
||||
for (i = 0; i < ARRAY_SIZE(orom->ctrl); i++)
|
||||
for (j = 0; j < ARRAY_SIZE(orom->ctrl[i].phys); j++) {
|
||||
orom->ctrl[i].phys[j].afe_tx_amp_control0 = 0xe7c03;
|
||||
orom->ctrl[i].phys[j].afe_tx_amp_control1 = 0xe7c03;
|
||||
orom->ctrl[i].phys[j].afe_tx_amp_control2 = 0xe7c03;
|
||||
orom->ctrl[i].phys[j].afe_tx_amp_control3 = 0xe7c03;
|
||||
}
|
||||
out:
|
||||
release_firmware(fw);
|
||||
|
||||
return orom;
|
||||
}
|
||||
|
||||
static struct efi *get_efi(void)
|
||||
{
|
||||
#ifdef CONFIG_EFI
|
||||
return &efi;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
struct isci_orom *isci_get_efi_var(struct pci_dev *pdev)
|
||||
{
|
||||
efi_status_t status;
|
||||
struct isci_orom *rom;
|
||||
struct isci_oem_hdr *oem_hdr;
|
||||
u8 *tmp, sum;
|
||||
int j;
|
||||
unsigned long data_len;
|
||||
u8 *efi_data;
|
||||
u32 efi_attrib = 0;
|
||||
|
||||
data_len = 1024;
|
||||
efi_data = devm_kzalloc(&pdev->dev, data_len, GFP_KERNEL);
|
||||
if (!efi_data) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Unable to allocate memory for EFI data\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rom = (struct isci_orom *)(efi_data + sizeof(struct isci_oem_hdr));
|
||||
|
||||
if (get_efi())
|
||||
status = get_efi()->get_variable(isci_efivar_name,
|
||||
&ISCI_EFI_VENDOR_GUID,
|
||||
&efi_attrib,
|
||||
&data_len,
|
||||
efi_data);
|
||||
else
|
||||
status = EFI_NOT_FOUND;
|
||||
|
||||
if (status != EFI_SUCCESS) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Unable to obtain EFI var data for OEM parms\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
oem_hdr = (struct isci_oem_hdr *)efi_data;
|
||||
|
||||
if (memcmp(oem_hdr->sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) != 0) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Invalid OEM header signature\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* calculate checksum */
|
||||
tmp = (u8 *)efi_data;
|
||||
for (j = 0, sum = 0; j < (sizeof(*oem_hdr) + sizeof(*rom)); j++, tmp++)
|
||||
sum += *tmp;
|
||||
|
||||
if (sum != 0) {
|
||||
dev_warn(&pdev->dev,
|
||||
"OEM table checksum failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (memcmp(rom->hdr.signature,
|
||||
ISCI_ROM_SIG,
|
||||
ISCI_ROM_SIG_SIZE) != 0) {
|
||||
dev_warn(&pdev->dev,
|
||||
"Invalid OEM table signature\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rom;
|
||||
}
|
249
drivers/scsi/isci/probe_roms.h
Normal file
249
drivers/scsi/isci/probe_roms.h
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* This file is provided under a dual BSD/GPLv2 license. When using or
|
||||
* redistributing this file, you may do so under either license.
|
||||
*
|
||||
* GPL LICENSE SUMMARY
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* The full GNU General Public License is included in this distribution
|
||||
* in the file called LICENSE.GPL.
|
||||
*
|
||||
* BSD LICENSE
|
||||
*
|
||||
* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Intel Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _ISCI_PROBE_ROMS_H_
|
||||
#define _ISCI_PROBE_ROMS_H_
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/firmware.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/efi.h>
|
||||
#include "isci.h"
|
||||
|
||||
#define SCIC_SDS_PARM_NO_SPEED 0
|
||||
|
||||
/* generation 1 (i.e. 1.5 Gb/s) */
|
||||
#define SCIC_SDS_PARM_GEN1_SPEED 1
|
||||
|
||||
/* generation 2 (i.e. 3.0 Gb/s) */
|
||||
#define SCIC_SDS_PARM_GEN2_SPEED 2
|
||||
|
||||
/* generation 3 (i.e. 6.0 Gb/s) */
|
||||
#define SCIC_SDS_PARM_GEN3_SPEED 3
|
||||
#define SCIC_SDS_PARM_MAX_SPEED SCIC_SDS_PARM_GEN3_SPEED
|
||||
|
||||
/* parameters that can be set by module parameters */
|
||||
struct sci_user_parameters {
|
||||
struct sci_phy_user_params {
|
||||
/**
|
||||
* This field specifies the NOTIFY (ENABLE SPIN UP) primitive
|
||||
* insertion frequency for this phy index.
|
||||
*/
|
||||
u32 notify_enable_spin_up_insertion_frequency;
|
||||
|
||||
/**
|
||||
* This method specifies the number of transmitted DWORDs within which
|
||||
* to transmit a single ALIGN primitive. This value applies regardless
|
||||
* of what type of device is attached or connection state. A value of
|
||||
* 0 indicates that no ALIGN primitives will be inserted.
|
||||
*/
|
||||
u16 align_insertion_frequency;
|
||||
|
||||
/**
|
||||
* This method specifies the number of transmitted DWORDs within which
|
||||
* to transmit 2 ALIGN primitives. This applies for SAS connections
|
||||
* only. A minimum value of 3 is required for this field.
|
||||
*/
|
||||
u16 in_connection_align_insertion_frequency;
|
||||
|
||||
/**
|
||||
* This field indicates the maximum speed generation to be utilized
|
||||
* by phys in the supplied port.
|
||||
* - A value of 1 indicates generation 1 (i.e. 1.5 Gb/s).
|
||||
* - A value of 2 indicates generation 2 (i.e. 3.0 Gb/s).
|
||||
* - A value of 3 indicates generation 3 (i.e. 6.0 Gb/s).
|
||||
*/
|
||||
u8 max_speed_generation;
|
||||
|
||||
} phys[SCI_MAX_PHYS];
|
||||
|
||||
/**
|
||||
* This field specifies the maximum number of direct attached devices
|
||||
* that can have power supplied to them simultaneously.
|
||||
*/
|
||||
u8 max_number_concurrent_device_spin_up;
|
||||
|
||||
/**
|
||||
* This field specifies the number of seconds to allow a phy to consume
|
||||
* power before yielding to another phy.
|
||||
*
|
||||
*/
|
||||
u8 phy_spin_up_delay_interval;
|
||||
|
||||
/**
|
||||
* These timer values specifies how long a link will remain open with no
|
||||
* activity in increments of a microsecond, it can be in increments of
|
||||
* 100 microseconds if the upper most bit is set.
|
||||
*
|
||||
*/
|
||||
u16 stp_inactivity_timeout;
|
||||
u16 ssp_inactivity_timeout;
|
||||
|
||||
/**
|
||||
* These timer values specifies how long a link will remain open in increments
|
||||
* of 100 microseconds.
|
||||
*
|
||||
*/
|
||||
u16 stp_max_occupancy_timeout;
|
||||
u16 ssp_max_occupancy_timeout;
|
||||
|
||||
/**
|
||||
* This timer value specifies how long a link will remain open with no
|
||||
* outbound traffic in increments of a microsecond.
|
||||
*
|
||||
*/
|
||||
u8 no_outbound_task_timeout;
|
||||
|
||||
};
|
||||
|
||||
#define SCIC_SDS_PARM_PHY_MASK_MIN 0x0
|
||||
#define SCIC_SDS_PARM_PHY_MASK_MAX 0xF
|
||||
#define MAX_CONCURRENT_DEVICE_SPIN_UP_COUNT 4
|
||||
|
||||
struct sci_oem_params;
|
||||
int sci_oem_parameters_validate(struct sci_oem_params *oem);
|
||||
|
||||
struct isci_orom;
|
||||
struct isci_orom *isci_request_oprom(struct pci_dev *pdev);
|
||||
enum sci_status isci_parse_oem_parameters(struct sci_oem_params *oem,
|
||||
struct isci_orom *orom, int scu_index);
|
||||
struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw);
|
||||
struct isci_orom *isci_get_efi_var(struct pci_dev *pdev);
|
||||
|
||||
struct isci_oem_hdr {
|
||||
u8 sig[4];
|
||||
u8 rev_major;
|
||||
u8 rev_minor;
|
||||
u16 len;
|
||||
u8 checksum;
|
||||
u8 reserved1;
|
||||
u16 reserved2;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#else
|
||||
#define SCI_MAX_PORTS 4
|
||||
#define SCI_MAX_PHYS 4
|
||||
#define SCI_MAX_CONTROLLERS 2
|
||||
#endif
|
||||
|
||||
#define ISCI_FW_NAME "isci/isci_firmware.bin"
|
||||
|
||||
#define ROMSIGNATURE 0xaa55
|
||||
|
||||
#define ISCI_OEM_SIG "$OEM"
|
||||
#define ISCI_OEM_SIG_SIZE 4
|
||||
#define ISCI_ROM_SIG "ISCUOEMB"
|
||||
#define ISCI_ROM_SIG_SIZE 8
|
||||
|
||||
#define ISCI_EFI_VENDOR_GUID \
|
||||
EFI_GUID(0x193dfefa, 0xa445, 0x4302, 0x99, 0xd8, 0xef, 0x3a, 0xad, \
|
||||
0x1a, 0x04, 0xc6)
|
||||
#define ISCI_EFI_VAR_NAME "RstScuO"
|
||||
|
||||
/* Allowed PORT configuration modes APC Automatic PORT configuration mode is
|
||||
* defined by the OEM configuration parameters providing no PHY_MASK parameters
|
||||
* for any PORT. i.e. There are no phys assigned to any of the ports at start.
|
||||
* MPC Manual PORT configuration mode is defined by the OEM configuration
|
||||
* parameters providing a PHY_MASK value for any PORT. It is assumed that any
|
||||
* PORT with no PHY_MASK is an invalid port and not all PHYs must be assigned.
|
||||
* A PORT_PHY mask that assigns just a single PHY to a port and no other PHYs
|
||||
* being assigned is sufficient to declare manual PORT configuration.
|
||||
*/
|
||||
enum sci_port_configuration_mode {
|
||||
SCIC_PORT_MANUAL_CONFIGURATION_MODE = 0,
|
||||
SCIC_PORT_AUTOMATIC_CONFIGURATION_MODE = 1
|
||||
};
|
||||
|
||||
struct sci_bios_oem_param_block_hdr {
|
||||
uint8_t signature[ISCI_ROM_SIG_SIZE];
|
||||
uint16_t total_block_length;
|
||||
uint8_t hdr_length;
|
||||
uint8_t version;
|
||||
uint8_t preboot_source;
|
||||
uint8_t num_elements;
|
||||
uint16_t element_length;
|
||||
uint8_t reserved[8];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct sci_oem_params {
|
||||
struct {
|
||||
uint8_t mode_type;
|
||||
uint8_t max_concurrent_dev_spin_up;
|
||||
uint8_t do_enable_ssc;
|
||||
uint8_t reserved;
|
||||
} controller;
|
||||
|
||||
struct {
|
||||
uint8_t phy_mask;
|
||||
} ports[SCI_MAX_PORTS];
|
||||
|
||||
struct sci_phy_oem_params {
|
||||
struct {
|
||||
uint32_t high;
|
||||
uint32_t low;
|
||||
} sas_address;
|
||||
|
||||
uint32_t afe_tx_amp_control0;
|
||||
uint32_t afe_tx_amp_control1;
|
||||
uint32_t afe_tx_amp_control2;
|
||||
uint32_t afe_tx_amp_control3;
|
||||
} phys[SCI_MAX_PHYS];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct isci_orom {
|
||||
struct sci_bios_oem_param_block_hdr hdr;
|
||||
struct sci_oem_params ctrl[SCI_MAX_CONTROLLERS];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue