Merge branches 'devel-cleanup', 'devel-serial' and 'devel-board' into omap-for-linus
This commit is contained in:
commit
9c7bc451e4
|
@ -196,7 +196,7 @@ csrow3.
|
|||
The representation of the above is reflected in the directory tree
|
||||
in EDAC's sysfs interface. Starting in directory
|
||||
/sys/devices/system/edac/mc each memory controller will be represented
|
||||
by its own 'mcX' directory, where 'X" is the index of the MC.
|
||||
by its own 'mcX' directory, where 'X' is the index of the MC.
|
||||
|
||||
|
||||
..../edac/mc/
|
||||
|
@ -207,7 +207,7 @@ by its own 'mcX' directory, where 'X" is the index of the MC.
|
|||
....
|
||||
|
||||
Under each 'mcX' directory each 'csrowX' is again represented by a
|
||||
'csrowX', where 'X" is the csrow index:
|
||||
'csrowX', where 'X' is the csrow index:
|
||||
|
||||
|
||||
.../mc/mc0/
|
||||
|
@ -232,7 +232,7 @@ EDAC control and attribute files.
|
|||
|
||||
|
||||
In 'mcX' directories are EDAC control and attribute files for
|
||||
this 'X" instance of the memory controllers:
|
||||
this 'X' instance of the memory controllers:
|
||||
|
||||
|
||||
Counter reset control file:
|
||||
|
@ -343,7 +343,7 @@ Sdram memory scrubbing rate:
|
|||
'csrowX' DIRECTORIES
|
||||
|
||||
In the 'csrowX' directories are EDAC control and attribute files for
|
||||
this 'X" instance of csrow:
|
||||
this 'X' instance of csrow:
|
||||
|
||||
|
||||
Total Uncorrectable Errors count attribute file:
|
||||
|
|
|
@ -144,6 +144,7 @@ tcp_adv_win_scale - INTEGER
|
|||
Count buffering overhead as bytes/2^tcp_adv_win_scale
|
||||
(if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
|
||||
if it is <= 0.
|
||||
Possible values are [-31, 31], inclusive.
|
||||
Default: 2
|
||||
|
||||
tcp_allowed_congestion_control - STRING
|
||||
|
|
|
@ -5839,6 +5839,8 @@ M: Chris Metcalf <cmetcalf@tilera.com>
|
|||
W: http://www.tilera.com/scm/
|
||||
S: Supported
|
||||
F: arch/tile/
|
||||
F: drivers/char/hvc_tile.c
|
||||
F: drivers/net/tile/
|
||||
|
||||
TLAN NETWORK DRIVER
|
||||
M: Samuel Chessman <chessman@tux.org>
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,7 +1,7 @@
|
|||
VERSION = 2
|
||||
PATCHLEVEL = 6
|
||||
SUBLEVEL = 37
|
||||
EXTRAVERSION = -rc3
|
||||
EXTRAVERSION = -rc4
|
||||
NAME = Flesh-Eating Bats with Fangs
|
||||
|
||||
# *DOCUMENTATION*
|
||||
|
|
|
@ -152,20 +152,11 @@ config MACH_NOKIA770
|
|||
config MACH_AMS_DELTA
|
||||
bool "Amstrad E3 (Delta)"
|
||||
depends on ARCH_OMAP1 && ARCH_OMAP15XX
|
||||
select FIQ
|
||||
help
|
||||
Support for the Amstrad E3 (codename Delta) videophone. Say Y here
|
||||
if you have such a device.
|
||||
|
||||
config AMS_DELTA_FIQ
|
||||
bool "Fast Interrupt Request (FIQ) support for the E3"
|
||||
depends on MACH_AMS_DELTA
|
||||
select FIQ
|
||||
help
|
||||
Provide a FIQ handler for the E3.
|
||||
This allows for fast handling of interrupts generated
|
||||
by the clock line of the E3 mailboard (or a PS/2 keyboard)
|
||||
connected to the GPIO based external keyboard port.
|
||||
|
||||
config MACH_OMAP_GENERIC
|
||||
bool "Generic OMAP board"
|
||||
depends on ARCH_OMAP1 && (ARCH_OMAP15XX || ARCH_OMAP16XX)
|
||||
|
|
|
@ -39,8 +39,8 @@ obj-$(CONFIG_MACH_OMAP_PALMTE) += board-palmte.o
|
|||
obj-$(CONFIG_MACH_OMAP_PALMZ71) += board-palmz71.o
|
||||
obj-$(CONFIG_MACH_OMAP_PALMTT) += board-palmtt.o
|
||||
obj-$(CONFIG_MACH_NOKIA770) += board-nokia770.o
|
||||
obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o
|
||||
obj-$(CONFIG_AMS_DELTA_FIQ) += ams-delta-fiq.o ams-delta-fiq-handler.o
|
||||
obj-$(CONFIG_MACH_AMS_DELTA) += board-ams-delta.o ams-delta-fiq.o \
|
||||
ams-delta-fiq-handler.o
|
||||
obj-$(CONFIG_MACH_SX1) += board-sx1.o board-sx1-mmc.o
|
||||
obj-$(CONFIG_MACH_HERALD) += board-htcherald.o
|
||||
|
||||
|
|
|
@ -308,9 +308,7 @@ static void __init ams_delta_init(void)
|
|||
#endif
|
||||
platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));
|
||||
|
||||
#ifdef CONFIG_AMS_DELTA_FIQ
|
||||
ams_delta_init_fiq();
|
||||
#endif
|
||||
|
||||
omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);
|
||||
}
|
||||
|
|
|
@ -54,9 +54,11 @@ static inline void omap_serial_outp(struct plat_serial8250_port *p, int offset,
|
|||
*/
|
||||
static void __init omap_serial_reset(struct plat_serial8250_port *p)
|
||||
{
|
||||
omap_serial_outp(p, UART_OMAP_MDR1, 0x07); /* disable UART */
|
||||
omap_serial_outp(p, UART_OMAP_MDR1,
|
||||
UART_OMAP_MDR1_DISABLE); /* disable UART */
|
||||
omap_serial_outp(p, UART_OMAP_SCR, 0x08); /* TX watermark */
|
||||
omap_serial_outp(p, UART_OMAP_MDR1, 0x00); /* enable UART */
|
||||
omap_serial_outp(p, UART_OMAP_MDR1,
|
||||
UART_OMAP_MDR1_16X_MODE); /* enable UART */
|
||||
|
||||
if (!cpu_is_omap15xx()) {
|
||||
omap_serial_outp(p, UART_OMAP_SYSC, 0x01);
|
||||
|
|
|
@ -174,6 +174,11 @@ config MACH_OMAP3517EVM
|
|||
default y
|
||||
select OMAP_PACKAGE_CBB
|
||||
|
||||
config MACH_CRANEBOARD
|
||||
bool "AM3517/05 CRANE board"
|
||||
depends on ARCH_OMAP3
|
||||
select OMAP_PACKAGE_CBB
|
||||
|
||||
config MACH_OMAP3_PANDORA
|
||||
bool "OMAP3 Pandora"
|
||||
depends on ARCH_OMAP3
|
||||
|
|
|
@ -144,12 +144,12 @@ obj-$(CONFIG_MACH_NOKIA_RX51) += board-rx51.o \
|
|||
board-rx51-peripherals.o \
|
||||
board-rx51-video.o \
|
||||
hsmmc.o
|
||||
obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom2.o \
|
||||
obj-$(CONFIG_MACH_OMAP_ZOOM2) += board-zoom.o \
|
||||
board-zoom-peripherals.o \
|
||||
board-flash.o \
|
||||
hsmmc.o \
|
||||
board-zoom-debugboard.o
|
||||
obj-$(CONFIG_MACH_OMAP_ZOOM3) += board-zoom3.o \
|
||||
obj-$(CONFIG_MACH_OMAP_ZOOM3) += board-zoom.o \
|
||||
board-zoom-peripherals.o \
|
||||
board-flash.o \
|
||||
hsmmc.o \
|
||||
|
@ -174,6 +174,8 @@ obj-$(CONFIG_MACH_OMAP4_PANDA) += board-omap4panda.o \
|
|||
|
||||
obj-$(CONFIG_MACH_OMAP3517EVM) += board-am3517evm.o
|
||||
|
||||
obj-$(CONFIG_MACH_CRANEBOARD) += board-am3517crane.o
|
||||
|
||||
obj-$(CONFIG_MACH_SBC3530) += board-omap3stalker.o \
|
||||
hsmmc.o
|
||||
# Platform specific device init code
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Support for AM3517/05 Craneboard
|
||||
* http://www.mistralsolutions.com/products/craneboard.php
|
||||
*
|
||||
* Copyright (C) 2010 Mistral Solutions Pvt Ltd. <www.mistralsolutions.com>
|
||||
* Author: R.Srinath <srinath@mistralsolutions.com>
|
||||
*
|
||||
* Based on mach-omap2/board-am3517evm.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation version 2.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
|
||||
* whether express or implied; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
||||
#include <plat/board.h>
|
||||
#include <plat/common.h>
|
||||
|
||||
#include "mux.h"
|
||||
|
||||
/* Board initialization */
|
||||
static struct omap_board_config_kernel am3517_crane_config[] __initdata = {
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OMAP_MUX
|
||||
static struct omap_board_mux board_mux[] __initdata = {
|
||||
{ .reg_offset = OMAP_MUX_TERMINATOR },
|
||||
};
|
||||
#else
|
||||
#define board_mux NULL
|
||||
#endif
|
||||
|
||||
static void __init am3517_crane_init_irq(void)
|
||||
{
|
||||
omap_board_config = am3517_crane_config;
|
||||
omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
|
||||
|
||||
omap2_init_common_hw(NULL, NULL);
|
||||
omap_init_irq();
|
||||
omap_gpio_init();
|
||||
}
|
||||
|
||||
static void __init am3517_crane_init(void)
|
||||
{
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
|
||||
omap_serial_init();
|
||||
}
|
||||
|
||||
MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
|
||||
.boot_params = 0x80000100,
|
||||
.map_io = omap3_map_io,
|
||||
.reserve = omap_reserve,
|
||||
.init_irq = am3517_crane_init_irq,
|
||||
.init_machine = am3517_crane_init,
|
||||
.timer = &omap_timer,
|
||||
MACHINE_END
|
|
@ -136,16 +136,9 @@ static struct mtd_partition igep2_onenand_partitions[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static int igep2_onenand_setup(void __iomem *onenand_base, int freq)
|
||||
{
|
||||
/* nothing is required to be setup for onenand as of now */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct omap_onenand_platform_data igep2_onenand_data = {
|
||||
.parts = igep2_onenand_partitions,
|
||||
.nr_parts = ARRAY_SIZE(igep2_onenand_partitions),
|
||||
.onenand_setup = igep2_onenand_setup,
|
||||
.dma_channel = -1, /* disable DMA in OMAP OneNAND driver */
|
||||
};
|
||||
|
||||
|
@ -159,35 +152,34 @@ static struct platform_device igep2_onenand_device = {
|
|||
|
||||
static void __init igep2_flash_init(void)
|
||||
{
|
||||
u8 cs = 0;
|
||||
u8 onenandcs = GPMC_CS_NUM + 1;
|
||||
u8 cs = 0;
|
||||
u8 onenandcs = GPMC_CS_NUM + 1;
|
||||
|
||||
while (cs < GPMC_CS_NUM) {
|
||||
u32 ret = 0;
|
||||
for (cs = 0; cs < GPMC_CS_NUM; cs++) {
|
||||
u32 ret;
|
||||
ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
|
||||
|
||||
/* Check if NAND/oneNAND is configured */
|
||||
if ((ret & 0xC00) == 0x800)
|
||||
/* NAND found */
|
||||
pr_err("IGEP v2: Unsupported NAND found\n");
|
||||
pr_err("IGEP2: Unsupported NAND found\n");
|
||||
else {
|
||||
ret = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
|
||||
if ((ret & 0x3F) == (ONENAND_MAP >> 24))
|
||||
/* ONENAND found */
|
||||
onenandcs = cs;
|
||||
}
|
||||
cs++;
|
||||
}
|
||||
|
||||
if (onenandcs > GPMC_CS_NUM) {
|
||||
pr_err("IGEP v2: Unable to find configuration in GPMC\n");
|
||||
pr_err("IGEP2: Unable to find configuration in GPMC\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (onenandcs < GPMC_CS_NUM) {
|
||||
igep2_onenand_data.cs = onenandcs;
|
||||
if (platform_device_register(&igep2_onenand_device) < 0)
|
||||
pr_err("IGEP v2: Unable to register OneNAND device\n");
|
||||
}
|
||||
igep2_onenand_data.cs = onenandcs;
|
||||
|
||||
if (platform_device_register(&igep2_onenand_device) < 0)
|
||||
pr_err("IGEP2: Unable to register OneNAND device\n");
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -254,9 +246,6 @@ static inline void __init igep2_init_smsc911x(void)
|
|||
static inline void __init igep2_init_smsc911x(void) { }
|
||||
#endif
|
||||
|
||||
static struct omap_board_config_kernel igep2_config[] __initdata = {
|
||||
};
|
||||
|
||||
static struct regulator_consumer_supply igep2_vmmc1_supply = {
|
||||
.supply = "vmmc",
|
||||
};
|
||||
|
@ -493,8 +482,6 @@ static struct platform_device *igep2_devices[] __initdata = {
|
|||
|
||||
static void __init igep2_init_irq(void)
|
||||
{
|
||||
omap_board_config = igep2_config;
|
||||
omap_board_config_size = ARRAY_SIZE(igep2_config);
|
||||
omap2_init_common_hw(m65kxxxxam_sdrc_params, m65kxxxxam_sdrc_params);
|
||||
omap_init_irq();
|
||||
omap_gpio_init();
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Texas Instruments Inc.
|
||||
* Copyright (C) 2009-2010 Texas Instruments Inc.
|
||||
* Mikkel Christensen <mlc@ti.com>
|
||||
* Felipe Balbi <balbi@ti.com>
|
||||
*
|
||||
* Modified from mach-omap2/board-ldp.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
|
@ -12,22 +15,57 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include <mach/board-zoom.h>
|
||||
|
||||
#include <plat/common.h>
|
||||
#include <plat/board.h>
|
||||
#include <plat/usb.h>
|
||||
|
||||
#include <mach/board-zoom.h>
|
||||
|
||||
#include "board-flash.h"
|
||||
#include "mux.h"
|
||||
#include "sdram-micron-mt46h32m32lf-6.h"
|
||||
#include "sdram-hynix-h8mbx00u0mer-0em.h"
|
||||
|
||||
static struct omap_board_config_kernel zoom_config[] __initdata = {
|
||||
#define ZOOM3_EHCI_RESET_GPIO 64
|
||||
|
||||
static void __init omap_zoom_init_irq(void)
|
||||
{
|
||||
if (machine_is_omap_zoom2())
|
||||
omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
|
||||
mt46h32m32lf6_sdrc_params);
|
||||
else if (machine_is_omap_zoom3())
|
||||
omap2_init_common_hw(h8mbx00u0mer0em_sdrc_params,
|
||||
h8mbx00u0mer0em_sdrc_params);
|
||||
|
||||
omap_init_irq();
|
||||
omap_gpio_init();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OMAP_MUX
|
||||
static struct omap_board_mux board_mux[] __initdata = {
|
||||
/* WLAN IRQ - GPIO 162 */
|
||||
OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
|
||||
/* WLAN POWER ENABLE - GPIO 101 */
|
||||
OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
|
||||
/* WLAN SDIO: MMC3 CMD */
|
||||
OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
|
||||
/* WLAN SDIO: MMC3 CLK */
|
||||
OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
/* WLAN SDIO: MMC3 DAT[0-3] */
|
||||
OMAP3_MUX(ETK_D3, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
OMAP3_MUX(ETK_D4, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
OMAP3_MUX(ETK_D5, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
OMAP3_MUX(ETK_D6, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
{ .reg_offset = OMAP_MUX_TERMINATOR },
|
||||
};
|
||||
#else
|
||||
#define board_mux NULL
|
||||
#endif
|
||||
|
||||
static struct mtd_partition zoom_nand_partitions[] = {
|
||||
/* All the partition sizes are listed in terms of NAND block size */
|
||||
|
@ -70,59 +108,41 @@ static struct mtd_partition zoom_nand_partitions[] = {
|
|||
},
|
||||
};
|
||||
|
||||
static void __init omap_zoom_init_irq(void)
|
||||
{
|
||||
omap_board_config = zoom_config;
|
||||
omap_board_config_size = ARRAY_SIZE(zoom_config);
|
||||
omap2_init_common_hw(h8mbx00u0mer0em_sdrc_params,
|
||||
h8mbx00u0mer0em_sdrc_params);
|
||||
omap_init_irq();
|
||||
omap_gpio_init();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OMAP_MUX
|
||||
static struct omap_board_mux board_mux[] __initdata = {
|
||||
/* WLAN IRQ - GPIO 162 */
|
||||
OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
|
||||
/* WLAN POWER ENABLE - GPIO 101 */
|
||||
OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
|
||||
/* WLAN SDIO: MMC3 CMD */
|
||||
OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
|
||||
/* WLAN SDIO: MMC3 CLK */
|
||||
OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
/* WLAN SDIO: MMC3 DAT[0-3] */
|
||||
OMAP3_MUX(ETK_D3, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
OMAP3_MUX(ETK_D4, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
OMAP3_MUX(ETK_D5, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
OMAP3_MUX(ETK_D6, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
{ .reg_offset = OMAP_MUX_TERMINATOR },
|
||||
};
|
||||
#else
|
||||
#define board_mux NULL
|
||||
#endif
|
||||
|
||||
static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
|
||||
.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
|
||||
.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
|
||||
.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
|
||||
.phy_reset = true,
|
||||
.reset_gpio_port[0] = -EINVAL,
|
||||
.reset_gpio_port[1] = 64,
|
||||
.reset_gpio_port[1] = ZOOM3_EHCI_RESET_GPIO,
|
||||
.reset_gpio_port[2] = -EINVAL,
|
||||
};
|
||||
|
||||
static void __init omap_zoom_init(void)
|
||||
{
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
|
||||
zoom_peripherals_init();
|
||||
board_nand_init(zoom_nand_partitions,
|
||||
ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
|
||||
zoom_debugboard_init();
|
||||
if (machine_is_omap_zoom2()) {
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
|
||||
} else if (machine_is_omap_zoom3()) {
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
|
||||
omap_mux_init_gpio(ZOOM3_EHCI_RESET_GPIO, OMAP_PIN_OUTPUT);
|
||||
usb_ehci_init(&ehci_pdata);
|
||||
}
|
||||
|
||||
omap_mux_init_gpio(64, OMAP_PIN_OUTPUT);
|
||||
usb_ehci_init(&ehci_pdata);
|
||||
board_nand_init(zoom_nand_partitions,
|
||||
ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
|
||||
zoom_debugboard_init();
|
||||
zoom_peripherals_init();
|
||||
}
|
||||
|
||||
MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
|
||||
.boot_params = 0x80000100,
|
||||
.map_io = omap3_map_io,
|
||||
.reserve = omap_reserve,
|
||||
.init_irq = omap_zoom_init_irq,
|
||||
.init_machine = omap_zoom_init,
|
||||
.timer = &omap_timer,
|
||||
MACHINE_END
|
||||
|
||||
MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
|
||||
.boot_params = 0x80000100,
|
||||
.map_io = omap3_map_io,
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2009 Texas Instruments Inc.
|
||||
* Mikkel Christensen <mlc@ti.com>
|
||||
*
|
||||
* Modified from mach-omap2/board-ldp.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/mach/arch.h>
|
||||
|
||||
#include <plat/common.h>
|
||||
#include <plat/board.h>
|
||||
|
||||
#include <mach/board-zoom.h>
|
||||
|
||||
#include "board-flash.h"
|
||||
#include "mux.h"
|
||||
#include "sdram-micron-mt46h32m32lf-6.h"
|
||||
|
||||
static void __init omap_zoom2_init_irq(void)
|
||||
{
|
||||
omap2_init_common_hw(mt46h32m32lf6_sdrc_params,
|
||||
mt46h32m32lf6_sdrc_params);
|
||||
omap_init_irq();
|
||||
omap_gpio_init();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OMAP_MUX
|
||||
static struct omap_board_mux board_mux[] __initdata = {
|
||||
/* WLAN IRQ - GPIO 162 */
|
||||
OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
|
||||
/* WLAN POWER ENABLE - GPIO 101 */
|
||||
OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
|
||||
/* WLAN SDIO: MMC3 CMD */
|
||||
OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLUP),
|
||||
/* WLAN SDIO: MMC3 CLK */
|
||||
OMAP3_MUX(ETK_CLK, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
/* WLAN SDIO: MMC3 DAT[0-3] */
|
||||
OMAP3_MUX(ETK_D3, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
OMAP3_MUX(ETK_D4, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
OMAP3_MUX(ETK_D5, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
OMAP3_MUX(ETK_D6, OMAP_MUX_MODE2 | OMAP_PIN_INPUT_PULLUP),
|
||||
{ .reg_offset = OMAP_MUX_TERMINATOR },
|
||||
};
|
||||
#else
|
||||
#define board_mux NULL
|
||||
#endif
|
||||
|
||||
static struct mtd_partition zoom_nand_partitions[] = {
|
||||
/* All the partition sizes are listed in terms of NAND block size */
|
||||
{
|
||||
.name = "X-Loader-NAND",
|
||||
.offset = 0,
|
||||
.size = 4 * (64 * 2048), /* 512KB, 0x80000 */
|
||||
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
||||
},
|
||||
{
|
||||
.name = "U-Boot-NAND",
|
||||
.offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
|
||||
.size = 10 * (64 * 2048), /* 1.25MB, 0x140000 */
|
||||
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
||||
},
|
||||
{
|
||||
.name = "Boot Env-NAND",
|
||||
.offset = MTDPART_OFS_APPEND, /* Offset = 0x1c0000 */
|
||||
.size = 2 * (64 * 2048), /* 256KB, 0x40000 */
|
||||
},
|
||||
{
|
||||
.name = "Kernel-NAND",
|
||||
.offset = MTDPART_OFS_APPEND, /* Offset = 0x0200000*/
|
||||
.size = 240 * (64 * 2048), /* 30M, 0x1E00000 */
|
||||
},
|
||||
{
|
||||
.name = "system",
|
||||
.offset = MTDPART_OFS_APPEND, /* Offset = 0x2000000 */
|
||||
.size = 3328 * (64 * 2048), /* 416M, 0x1A000000 */
|
||||
},
|
||||
{
|
||||
.name = "userdata",
|
||||
.offset = MTDPART_OFS_APPEND, /* Offset = 0x1C000000*/
|
||||
.size = 256 * (64 * 2048), /* 32M, 0x2000000 */
|
||||
},
|
||||
{
|
||||
.name = "cache",
|
||||
.offset = MTDPART_OFS_APPEND, /* Offset = 0x1E000000*/
|
||||
.size = 256 * (64 * 2048), /* 32M, 0x2000000 */
|
||||
},
|
||||
};
|
||||
|
||||
static void __init omap_zoom2_init(void)
|
||||
{
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
|
||||
zoom_peripherals_init();
|
||||
board_nand_init(zoom_nand_partitions,
|
||||
ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
|
||||
zoom_debugboard_init();
|
||||
}
|
||||
|
||||
MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
|
||||
.boot_params = 0x80000100,
|
||||
.map_io = omap3_map_io,
|
||||
.reserve = omap_reserve,
|
||||
.init_irq = omap_zoom2_init_irq,
|
||||
.init_machine = omap_zoom2_init,
|
||||
.timer = &omap_timer,
|
||||
MACHINE_END
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/irq.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/console.h>
|
||||
|
||||
#include <asm/mach/time.h>
|
||||
#include <asm/mach/irq.h>
|
||||
|
@ -118,6 +119,10 @@ static void omap2_enter_full_retention(void)
|
|||
if (omap_irq_pending())
|
||||
goto no_sleep;
|
||||
|
||||
/* Block console output in case it is on one of the OMAP UARTs */
|
||||
if (try_acquire_console_sem())
|
||||
goto no_sleep;
|
||||
|
||||
omap_uart_prepare_idle(0);
|
||||
omap_uart_prepare_idle(1);
|
||||
omap_uart_prepare_idle(2);
|
||||
|
@ -131,6 +136,8 @@ static void omap2_enter_full_retention(void)
|
|||
omap_uart_resume_idle(1);
|
||||
omap_uart_resume_idle(0);
|
||||
|
||||
release_console_sem();
|
||||
|
||||
no_sleep:
|
||||
if (omap2_pm_debug) {
|
||||
unsigned long long tmp;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/console.h>
|
||||
|
||||
#include <plat/sram.h>
|
||||
#include <plat/clockdomain.h>
|
||||
|
@ -385,6 +386,12 @@ void omap_sram_idle(void)
|
|||
omap3_enable_io_chain();
|
||||
}
|
||||
|
||||
/* Block console output in case it is on one of the OMAP UARTs */
|
||||
if (per_next_state < PWRDM_POWER_ON ||
|
||||
core_next_state < PWRDM_POWER_ON)
|
||||
if (try_acquire_console_sem())
|
||||
goto console_still_active;
|
||||
|
||||
/* PER */
|
||||
if (per_next_state < PWRDM_POWER_ON) {
|
||||
omap_uart_prepare_idle(2);
|
||||
|
@ -463,6 +470,9 @@ void omap_sram_idle(void)
|
|||
omap_uart_resume_idle(3);
|
||||
}
|
||||
|
||||
release_console_sem();
|
||||
|
||||
console_still_active:
|
||||
/* Disable IO-PAD and IO-CHAIN wakeup */
|
||||
if (omap3_has_io_wakeup() &&
|
||||
(per_next_state < PWRDM_POWER_ON ||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/serial_8250.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/console.h>
|
||||
|
||||
#ifdef CONFIG_SERIAL_OMAP
|
||||
#include <plat/omap-serial.h>
|
||||
|
@ -168,9 +169,9 @@ static inline void serial_write_reg(struct omap_uart_state *uart, int offset,
|
|||
|
||||
static inline void __init omap_uart_reset(struct omap_uart_state *uart)
|
||||
{
|
||||
serial_write_reg(uart, UART_OMAP_MDR1, 0x07);
|
||||
serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
|
||||
serial_write_reg(uart, UART_OMAP_SCR, 0x08);
|
||||
serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
|
||||
serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_16X_MODE);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
|
||||
|
@ -218,7 +219,7 @@ static void omap_uart_save_context(struct omap_uart_state *uart)
|
|||
return;
|
||||
|
||||
lcr = serial_read_reg(uart, UART_LCR);
|
||||
serial_write_reg(uart, UART_LCR, 0xBF);
|
||||
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
uart->dll = serial_read_reg(uart, UART_DLL);
|
||||
uart->dlh = serial_read_reg(uart, UART_DLM);
|
||||
serial_write_reg(uart, UART_LCR, lcr);
|
||||
|
@ -226,7 +227,7 @@ static void omap_uart_save_context(struct omap_uart_state *uart)
|
|||
uart->sysc = serial_read_reg(uart, UART_OMAP_SYSC);
|
||||
uart->scr = serial_read_reg(uart, UART_OMAP_SCR);
|
||||
uart->wer = serial_read_reg(uart, UART_OMAP_WER);
|
||||
serial_write_reg(uart, UART_LCR, 0x80);
|
||||
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
|
||||
uart->mcr = serial_read_reg(uart, UART_MCR);
|
||||
serial_write_reg(uart, UART_LCR, lcr);
|
||||
|
||||
|
@ -246,32 +247,35 @@ static void omap_uart_restore_context(struct omap_uart_state *uart)
|
|||
uart->context_valid = 0;
|
||||
|
||||
if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
|
||||
omap_uart_mdr1_errataset(uart, 0x07, 0xA0);
|
||||
omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_DISABLE, 0xA0);
|
||||
else
|
||||
serial_write_reg(uart, UART_OMAP_MDR1, 0x7);
|
||||
serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
|
||||
serial_write_reg(uart, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE);
|
||||
|
||||
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
efr = serial_read_reg(uart, UART_EFR);
|
||||
serial_write_reg(uart, UART_EFR, UART_EFR_ECB);
|
||||
serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
|
||||
serial_write_reg(uart, UART_IER, 0x0);
|
||||
serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
|
||||
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
serial_write_reg(uart, UART_DLL, uart->dll);
|
||||
serial_write_reg(uart, UART_DLM, uart->dlh);
|
||||
serial_write_reg(uart, UART_LCR, 0x0); /* Operational mode */
|
||||
serial_write_reg(uart, UART_IER, uart->ier);
|
||||
serial_write_reg(uart, UART_LCR, 0x80);
|
||||
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_A);
|
||||
serial_write_reg(uart, UART_MCR, uart->mcr);
|
||||
serial_write_reg(uart, UART_LCR, 0xBF); /* Config B mode */
|
||||
serial_write_reg(uart, UART_LCR, UART_LCR_CONF_MODE_B);
|
||||
serial_write_reg(uart, UART_EFR, efr);
|
||||
serial_write_reg(uart, UART_LCR, UART_LCR_WLEN8);
|
||||
serial_write_reg(uart, UART_OMAP_SCR, uart->scr);
|
||||
serial_write_reg(uart, UART_OMAP_WER, uart->wer);
|
||||
serial_write_reg(uart, UART_OMAP_SYSC, uart->sysc);
|
||||
|
||||
if (uart->errata & UART_ERRATA_i202_MDR1_ACCESS)
|
||||
omap_uart_mdr1_errataset(uart, 0x00, 0xA1);
|
||||
omap_uart_mdr1_errataset(uart, UART_OMAP_MDR1_16X_MODE, 0xA1);
|
||||
else
|
||||
/* UART 16x mode */
|
||||
serial_write_reg(uart, UART_OMAP_MDR1, 0x00);
|
||||
serial_write_reg(uart, UART_OMAP_MDR1,
|
||||
UART_OMAP_MDR1_16X_MODE);
|
||||
}
|
||||
#else
|
||||
static inline void omap_uart_save_context(struct omap_uart_state *uart) {}
|
||||
|
@ -406,7 +410,7 @@ void omap_uart_resume_idle(int num)
|
|||
struct omap_uart_state *uart;
|
||||
|
||||
list_for_each_entry(uart, &uart_list, node) {
|
||||
if (num == uart->num) {
|
||||
if (num == uart->num && uart->can_sleep) {
|
||||
omap_uart_enable_clocks(uart);
|
||||
|
||||
/* Check for IO pad wakeup */
|
||||
|
@ -807,6 +811,8 @@ void __init omap_serial_init_port(int port)
|
|||
|
||||
oh->dev_attr = uart;
|
||||
|
||||
acquire_console_sem(); /* in case the earlycon is on the UART */
|
||||
|
||||
/*
|
||||
* Because of early UART probing, UART did not get idled
|
||||
* on init. Now that omap_device is ready, ensure full idle
|
||||
|
@ -831,6 +837,8 @@ void __init omap_serial_init_port(int port)
|
|||
omap_uart_block_sleep(uart);
|
||||
uart->timeout = DEFAULT_TIMEOUT;
|
||||
|
||||
release_console_sem();
|
||||
|
||||
if ((cpu_is_omap34xx() && uart->padconf) ||
|
||||
(uart->wk_en && uart->wk_mask)) {
|
||||
device_init_wakeup(&od->pdev.dev, true);
|
||||
|
|
|
@ -77,13 +77,13 @@ static int __devinit h1940bt_probe(struct platform_device *pdev)
|
|||
|
||||
/* Configures BT serial port GPIOs */
|
||||
s3c_gpio_cfgpin(S3C2410_GPH(0), S3C2410_GPH0_nCTS0);
|
||||
s3c_gpio_cfgpull(S3C2410_GPH(0), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPH(0), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_cfgpin(S3C2410_GPH(1), S3C2410_GPIO_OUTPUT);
|
||||
s3c_gpio_cfgpull(S3C2410_GPH(1), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPH(1), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_cfgpin(S3C2410_GPH(2), S3C2410_GPH2_TXD0);
|
||||
s3c_gpio_cfgpull(S3C2410_GPH(2), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPH(2), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0);
|
||||
s3c_gpio_cfgpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE);
|
||||
|
||||
|
||||
rfk = rfkill_alloc(DRV_NAME, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
|
||||
|
|
|
@ -168,12 +168,11 @@ static struct irq_chip s3c2416_irq_dma = {
|
|||
|
||||
static void s3c2416_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
s3c2416_irq_demux(IRQ_S3C2443_UART3, 3);
|
||||
s3c2416_irq_demux(IRQ_S3C2443_RX3, 3);
|
||||
}
|
||||
|
||||
#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
|
||||
#define SUBMSK_UART3 (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
|
||||
|
||||
#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
|
||||
|
||||
static void s3c2416_irq_uart3_mask(unsigned int irqno)
|
||||
{
|
||||
|
|
|
@ -166,12 +166,11 @@ static struct irq_chip s3c2443_irq_dma = {
|
|||
|
||||
static void s3c2443_irq_demux_uart3(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
s3c2443_irq_demux(IRQ_S3C2443_UART3, 3);
|
||||
s3c2443_irq_demux(IRQ_S3C2443_RX3, 3);
|
||||
}
|
||||
|
||||
#define INTMSK_UART3 (1UL << (IRQ_S3C2443_UART3 - IRQ_EINT0))
|
||||
#define SUBMSK_UART3 (0xf << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
|
||||
|
||||
#define SUBMSK_UART3 (0x7 << (IRQ_S3C2443_RX3 - S3C2410_IRQSUB(0)))
|
||||
|
||||
static void s3c2443_irq_uart3_mask(unsigned int irqno)
|
||||
{
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
#include <video/platform_lcd.h>
|
||||
|
||||
#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
|
||||
#define UCON S3C2410_UCON_DEFAULT
|
||||
#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
|
||||
#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
#include <video/platform_lcd.h>
|
||||
|
||||
#define UCON (S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK)
|
||||
#define UCON S3C2410_UCON_DEFAULT
|
||||
#define ULCON (S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB)
|
||||
#define UFCON (S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE)
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <linux/i2c.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/serial_core.h>
|
||||
#include <linux/sysdev.h>
|
||||
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
|
|
@ -567,38 +567,127 @@ static struct platform_device *qhd_devices[] __initdata = {
|
|||
|
||||
/* FSI */
|
||||
#define IRQ_FSI evt2irq(0x1840)
|
||||
static int __fsi_set_rate(struct clk *clk, long rate, int enable)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
static int fsi_set_rate(int is_porta, int rate)
|
||||
if (rate <= 0)
|
||||
return ret;
|
||||
|
||||
if (enable) {
|
||||
ret = clk_set_rate(clk, rate);
|
||||
if (0 == ret)
|
||||
ret = clk_enable(clk);
|
||||
} else {
|
||||
clk_disable(clk);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __fsi_set_round_rate(struct clk *clk, long rate, int enable)
|
||||
{
|
||||
return __fsi_set_rate(clk, clk_round_rate(clk, rate), enable);
|
||||
}
|
||||
|
||||
static int fsi_ak4642_set_rate(struct device *dev, int rate, int enable)
|
||||
{
|
||||
struct clk *fsia_ick;
|
||||
struct clk *fsiack;
|
||||
int ret = -EIO;
|
||||
|
||||
fsia_ick = clk_get(dev, "icka");
|
||||
if (IS_ERR(fsia_ick))
|
||||
return PTR_ERR(fsia_ick);
|
||||
|
||||
/*
|
||||
* FSIACK is connected to AK4642,
|
||||
* and use external clock pin from it.
|
||||
* it is parent of fsia_ick now.
|
||||
*/
|
||||
fsiack = clk_get_parent(fsia_ick);
|
||||
if (!fsiack)
|
||||
goto fsia_ick_out;
|
||||
|
||||
/*
|
||||
* we get 1/1 divided clock by setting same rate to fsiack and fsia_ick
|
||||
*
|
||||
** FIXME **
|
||||
* Because the freq_table of external clk (fsiack) are all 0,
|
||||
* the return value of clk_round_rate became 0.
|
||||
* So, it use __fsi_set_rate here.
|
||||
*/
|
||||
ret = __fsi_set_rate(fsiack, rate, enable);
|
||||
if (ret < 0)
|
||||
goto fsiack_out;
|
||||
|
||||
ret = __fsi_set_round_rate(fsia_ick, rate, enable);
|
||||
if ((ret < 0) && enable)
|
||||
__fsi_set_round_rate(fsiack, rate, 0); /* disable FSI ACK */
|
||||
|
||||
fsiack_out:
|
||||
clk_put(fsiack);
|
||||
|
||||
fsia_ick_out:
|
||||
clk_put(fsia_ick);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fsi_hdmi_set_rate(struct device *dev, int rate, int enable)
|
||||
{
|
||||
struct clk *fsib_clk;
|
||||
struct clk *fdiv_clk = &sh7372_fsidivb_clk;
|
||||
long fsib_rate = 0;
|
||||
long fdiv_rate = 0;
|
||||
int ackmd_bpfmd;
|
||||
int ret;
|
||||
|
||||
/* set_rate is not needed if port A */
|
||||
if (is_porta)
|
||||
return 0;
|
||||
|
||||
fsib_clk = clk_get(NULL, "fsib_clk");
|
||||
if (IS_ERR(fsib_clk))
|
||||
return -EINVAL;
|
||||
|
||||
switch (rate) {
|
||||
case 44100:
|
||||
clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 11283000));
|
||||
ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
|
||||
fsib_rate = rate * 256;
|
||||
ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
|
||||
break;
|
||||
case 48000:
|
||||
clk_set_rate(fsib_clk, clk_round_rate(fsib_clk, 85428000));
|
||||
clk_set_rate(fdiv_clk, clk_round_rate(fdiv_clk, 12204000));
|
||||
ret = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
|
||||
fsib_rate = 85428000; /* around 48kHz x 256 x 7 */
|
||||
fdiv_rate = rate * 256;
|
||||
ackmd_bpfmd = SH_FSI_ACKMD_256 | SH_FSI_BPFMD_64;
|
||||
break;
|
||||
default:
|
||||
pr_err("unsupported rate in FSI2 port B\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* FSI B setting */
|
||||
fsib_clk = clk_get(dev, "ickb");
|
||||
if (IS_ERR(fsib_clk))
|
||||
return -EIO;
|
||||
|
||||
ret = __fsi_set_round_rate(fsib_clk, fsib_rate, enable);
|
||||
clk_put(fsib_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* FSI DIV setting */
|
||||
ret = __fsi_set_round_rate(fdiv_clk, fdiv_rate, enable);
|
||||
if (ret < 0) {
|
||||
/* disable FSI B */
|
||||
if (enable)
|
||||
__fsi_set_round_rate(fsib_clk, fsib_rate, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ackmd_bpfmd;
|
||||
}
|
||||
|
||||
static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (is_porta)
|
||||
ret = fsi_ak4642_set_rate(dev, rate, enable);
|
||||
else
|
||||
ret = fsi_hdmi_set_rate(dev, rate, enable);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -880,6 +969,11 @@ static int __init hdmi_init_pm_clock(void)
|
|||
goto out;
|
||||
}
|
||||
|
||||
ret = clk_enable(&sh7372_pllc2_clk);
|
||||
if (ret < 0) {
|
||||
pr_err("Cannot enable pllc2 clock\n");
|
||||
goto out;
|
||||
}
|
||||
pr_debug("PLLC2 set frequency %lu\n", rate);
|
||||
|
||||
ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
|
||||
|
@ -896,23 +990,11 @@ out:
|
|||
|
||||
device_initcall(hdmi_init_pm_clock);
|
||||
|
||||
#define FSIACK_DUMMY_RATE 48000
|
||||
static int __init fsi_init_pm_clock(void)
|
||||
{
|
||||
struct clk *fsia_ick;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* FSIACK is connected to AK4642,
|
||||
* and the rate is depend on playing sound rate.
|
||||
* So, set dummy rate (= 48k) here
|
||||
*/
|
||||
ret = clk_set_rate(&sh7372_fsiack_clk, FSIACK_DUMMY_RATE);
|
||||
if (ret < 0) {
|
||||
pr_err("Cannot set FSIACK dummy rate: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fsia_ick = clk_get(&fsi_device.dev, "icka");
|
||||
if (IS_ERR(fsia_ick)) {
|
||||
ret = PTR_ERR(fsia_ick);
|
||||
|
@ -921,16 +1003,9 @@ static int __init fsi_init_pm_clock(void)
|
|||
}
|
||||
|
||||
ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk);
|
||||
if (ret < 0) {
|
||||
pr_err("Cannot set FSI-A parent: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = clk_set_rate(fsia_ick, FSIACK_DUMMY_RATE);
|
||||
if (ret < 0)
|
||||
pr_err("Cannot set FSI-A rate: %d\n", ret);
|
||||
pr_err("Cannot set FSI-A parent: %d\n", ret);
|
||||
|
||||
out:
|
||||
clk_put(fsia_ick);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -229,21 +229,13 @@ static int pllc2_set_rate(struct clk *clk, unsigned long rate)
|
|||
if (idx < 0)
|
||||
return idx;
|
||||
|
||||
if (rate == clk->parent->rate) {
|
||||
pllc2_disable(clk);
|
||||
return 0;
|
||||
}
|
||||
if (rate == clk->parent->rate)
|
||||
return -EINVAL;
|
||||
|
||||
value = __raw_readl(PLLC2CR) & ~(0x3f << 24);
|
||||
|
||||
if (value & 0x80000000)
|
||||
pllc2_disable(clk);
|
||||
|
||||
__raw_writel((value & ~0x80000000) | ((idx + 19) << 24), PLLC2CR);
|
||||
|
||||
if (value & 0x80000000)
|
||||
return pllc2_enable(clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -452,10 +444,8 @@ static int fsidiv_enable(struct clk *clk)
|
|||
unsigned long value;
|
||||
|
||||
value = __raw_readl(clk->mapping->base) >> 16;
|
||||
if (value < 2) {
|
||||
fsidiv_disable(clk);
|
||||
return -ENOENT;
|
||||
}
|
||||
if (value < 2)
|
||||
return -EIO;
|
||||
|
||||
__raw_writel((value << 16) | 0x3, clk->mapping->base);
|
||||
|
||||
|
@ -466,17 +456,12 @@ static int fsidiv_set_rate(struct clk *clk, unsigned long rate)
|
|||
{
|
||||
int idx;
|
||||
|
||||
if (clk->parent->rate == rate) {
|
||||
fsidiv_disable(clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
idx = (clk->parent->rate / rate) & 0xffff;
|
||||
if (idx < 2)
|
||||
return -ENOENT;
|
||||
return -EINVAL;
|
||||
|
||||
__raw_writel(idx << 16, clk->mapping->base);
|
||||
return fsidiv_enable(clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk_ops fsidiv_clk_ops = {
|
||||
|
@ -607,8 +592,6 @@ static struct clk_lookup lookups[] = {
|
|||
CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
|
||||
CLKDEV_CON_ID("fmsi_clk", &div6_clks[DIV6_FMSI]),
|
||||
CLKDEV_CON_ID("fmso_clk", &div6_clks[DIV6_FMSO]),
|
||||
CLKDEV_CON_ID("fsia_clk", &div6_reparent_clks[DIV6_FSIA]),
|
||||
CLKDEV_CON_ID("fsib_clk", &div6_reparent_clks[DIV6_FSIB]),
|
||||
CLKDEV_CON_ID("sub_clk", &div6_clks[DIV6_SUB]),
|
||||
CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_SPU]),
|
||||
CLKDEV_CON_ID("vou_clk", &div6_clks[DIV6_VOU]),
|
||||
|
@ -645,8 +628,8 @@ static struct clk_lookup lookups[] = {
|
|||
CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
|
||||
CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
|
||||
CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
|
||||
CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP323]), /* USB0 */
|
||||
CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP323]), /* USB0 */
|
||||
CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */
|
||||
CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */
|
||||
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
|
||||
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
|
||||
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
|
||||
|
|
|
@ -31,20 +31,8 @@
|
|||
*/
|
||||
#define OMAP_SERIAL_NAME "ttyO"
|
||||
|
||||
#define OMAP_MDR1_DISABLE 0x07
|
||||
#define OMAP_MDR1_MODE13X 0x03
|
||||
#define OMAP_MDR1_MODE16X 0x00
|
||||
#define OMAP_MODE13X_SPEED 230400
|
||||
|
||||
/*
|
||||
* LCR = 0XBF: Switch to Configuration Mode B.
|
||||
* In configuration mode b allow access
|
||||
* to EFR,DLL,DLH.
|
||||
* Reference OMAP TRM Chapter 17
|
||||
* Section: 1.4.3 Mode Selection
|
||||
*/
|
||||
#define OMAP_UART_LCR_CONF_MDB 0XBF
|
||||
|
||||
/* WER = 0x7F
|
||||
* Enable module level wakeup in WER reg
|
||||
*/
|
||||
|
|
|
@ -145,6 +145,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
|
|||
/* omap3 based boards using UART3 */
|
||||
DEBUG_LL_OMAP3(3, cm_t35);
|
||||
DEBUG_LL_OMAP3(3, cm_t3517);
|
||||
DEBUG_LL_OMAP3(3, craneboard);
|
||||
DEBUG_LL_OMAP3(3, igep0020);
|
||||
DEBUG_LL_OMAP3(3, igep0030);
|
||||
DEBUG_LL_OMAP3(3, nokia_rx51);
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
/* Require clock free running */
|
||||
#define PXA_FLAG_DISABLE_CLOCK_GATING (1<<0)
|
||||
|
||||
/* Board design supports 8-bit data on SD/SDIO BUS */
|
||||
#define PXA_FLAG_SD_8_BIT_CAPABLE_SLOT (1<<2)
|
||||
|
||||
/*
|
||||
* struct pxa_sdhci_platdata() - Platform device data for PXA SDHCI
|
||||
* @max_speed: the maximum speed supported
|
||||
|
|
|
@ -29,8 +29,8 @@ void s3c24xx_spi_gpiocfg_bus0_gpe11_12_13(struct s3c2410_spi_info *spi,
|
|||
} else {
|
||||
s3c_gpio_cfgpin(S3C2410_GPE(13), S3C2410_GPIO_INPUT);
|
||||
s3c_gpio_cfgpin(S3C2410_GPE(11), S3C2410_GPIO_INPUT);
|
||||
s3c_gpio_cfgpull(S3C2410_GPE(11), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_cfgpull(S3C2410_GPE(12), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_cfgpull(S3C2410_GPE(13), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPE(11), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPE(12), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPE(13), S3C_GPIO_PULL_NONE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,8 +31,8 @@ void s3c24xx_spi_gpiocfg_bus1_gpd8_9_10(struct s3c2410_spi_info *spi,
|
|||
} else {
|
||||
s3c_gpio_cfgpin(S3C2410_GPD(8), S3C2410_GPIO_INPUT);
|
||||
s3c_gpio_cfgpin(S3C2410_GPD(9), S3C2410_GPIO_INPUT);
|
||||
s3c_gpio_cfgpull(S3C2410_GPD(10), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_cfgpull(S3C2410_GPD(9), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_cfgpull(S3C2410_GPD(8), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPD(10), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPD(9), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPD(8), S3C_GPIO_PULL_NONE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@ void s3c24xx_spi_gpiocfg_bus1_gpg5_6_7(struct s3c2410_spi_info *spi,
|
|||
} else {
|
||||
s3c_gpio_cfgpin(S3C2410_GPG(7), S3C2410_GPIO_INPUT);
|
||||
s3c_gpio_cfgpin(S3C2410_GPG(5), S3C2410_GPIO_INPUT);
|
||||
s3c_gpio_cfgpull(S3C2410_GPG(5), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_cfgpull(S3C2410_GPG(6), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_cfgpull(S3C2410_GPG(7), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPG(5), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPG(6), S3C_GPIO_PULL_NONE);
|
||||
s3c_gpio_setpull(S3C2410_GPG(7), S3C_GPIO_PULL_NONE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,7 +92,7 @@ static void pte_free_rcu_callback(struct rcu_head *head)
|
|||
|
||||
static void pte_free_submit(struct pte_freelist_batch *batch)
|
||||
{
|
||||
call_rcu(&batch->rcu, pte_free_rcu_callback);
|
||||
call_rcu_sched(&batch->rcu, pte_free_rcu_callback);
|
||||
}
|
||||
|
||||
void pgtable_free_tlb(struct mmu_gather *tlb, void *table, unsigned shift)
|
||||
|
|
|
@ -95,7 +95,6 @@ EXPORT_SYMBOL_GPL(s390_handle_mcck);
|
|||
static int notrace s390_revalidate_registers(struct mci *mci)
|
||||
{
|
||||
int kill_task;
|
||||
u64 tmpclock;
|
||||
u64 zero;
|
||||
void *fpt_save_area, *fpt_creg_save_area;
|
||||
|
||||
|
@ -214,11 +213,10 @@ static int notrace s390_revalidate_registers(struct mci *mci)
|
|||
: "0", "cc");
|
||||
#endif
|
||||
/* Revalidate clock comparator register */
|
||||
asm volatile(
|
||||
" stck 0(%1)\n"
|
||||
" sckc 0(%1)"
|
||||
: "=m" (tmpclock) : "a" (&(tmpclock)) : "cc", "memory");
|
||||
|
||||
if (S390_lowcore.clock_comparator == -1)
|
||||
set_clock_comparator(S390_lowcore.mcck_clock);
|
||||
else
|
||||
set_clock_comparator(S390_lowcore.clock_comparator);
|
||||
/* Check if old PSW is valid */
|
||||
if (!mci->wp)
|
||||
/*
|
||||
|
|
|
@ -29,17 +29,21 @@ static void __udelay_disabled(unsigned long long usecs)
|
|||
{
|
||||
unsigned long mask, cr0, cr0_saved;
|
||||
u64 clock_saved;
|
||||
u64 end;
|
||||
|
||||
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
|
||||
end = get_clock() + (usecs << 12);
|
||||
clock_saved = local_tick_disable();
|
||||
set_clock_comparator(get_clock() + (usecs << 12));
|
||||
__ctl_store(cr0_saved, 0, 0);
|
||||
cr0 = (cr0_saved & 0xffff00e0) | 0x00000800;
|
||||
__ctl_load(cr0 , 0, 0);
|
||||
mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_EXT;
|
||||
lockdep_off();
|
||||
trace_hardirqs_on();
|
||||
__load_psw_mask(mask);
|
||||
local_irq_disable();
|
||||
do {
|
||||
set_clock_comparator(end);
|
||||
trace_hardirqs_on();
|
||||
__load_psw_mask(mask);
|
||||
local_irq_disable();
|
||||
} while (get_clock() < end);
|
||||
lockdep_on();
|
||||
__ctl_load(cr0_saved, 0, 0);
|
||||
local_tick_enable(clock_saved);
|
||||
|
|
|
@ -329,6 +329,18 @@ endmenu # Tilera-specific configuration
|
|||
|
||||
menu "Bus options"
|
||||
|
||||
config PCI
|
||||
bool "PCI support"
|
||||
default y
|
||||
select PCI_DOMAINS
|
||||
---help---
|
||||
Enable PCI root complex support, so PCIe endpoint devices can
|
||||
be attached to the Tile chip. Many, but not all, PCI devices
|
||||
are supported under Tilera's root complex driver.
|
||||
|
||||
config PCI_DOMAINS
|
||||
bool
|
||||
|
||||
config NO_IOMEM
|
||||
def_bool !PCI
|
||||
|
||||
|
|
|
@ -137,4 +137,56 @@ static inline void finv_buffer(void *buffer, size_t size)
|
|||
mb_incoherent();
|
||||
}
|
||||
|
||||
/*
|
||||
* Flush & invalidate a VA range that is homed remotely on a single core,
|
||||
* waiting until the memory controller holds the flushed values.
|
||||
*/
|
||||
static inline void finv_buffer_remote(void *buffer, size_t size)
|
||||
{
|
||||
char *p;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Flush and invalidate the buffer out of the local L1/L2
|
||||
* and request the home cache to flush and invalidate as well.
|
||||
*/
|
||||
__finv_buffer(buffer, size);
|
||||
|
||||
/*
|
||||
* Wait for the home cache to acknowledge that it has processed
|
||||
* all the flush-and-invalidate requests. This does not mean
|
||||
* that the flushed data has reached the memory controller yet,
|
||||
* but it does mean the home cache is processing the flushes.
|
||||
*/
|
||||
__insn_mf();
|
||||
|
||||
/*
|
||||
* Issue a load to the last cache line, which can't complete
|
||||
* until all the previously-issued flushes to the same memory
|
||||
* controller have also completed. If we weren't striping
|
||||
* memory, that one load would be sufficient, but since we may
|
||||
* be, we also need to back up to the last load issued to
|
||||
* another memory controller, which would be the point where
|
||||
* we crossed an 8KB boundary (the granularity of striping
|
||||
* across memory controllers). Keep backing up and doing this
|
||||
* until we are before the beginning of the buffer, or have
|
||||
* hit all the controllers.
|
||||
*/
|
||||
for (i = 0, p = (char *)buffer + size - 1;
|
||||
i < (1 << CHIP_LOG_NUM_MSHIMS()) && p >= (char *)buffer;
|
||||
++i) {
|
||||
const unsigned long STRIPE_WIDTH = 8192;
|
||||
|
||||
/* Force a load instruction to issue. */
|
||||
*(volatile char *)p;
|
||||
|
||||
/* Jump to end of previous stripe. */
|
||||
p -= STRIPE_WIDTH;
|
||||
p = (char *)((unsigned long)p | (STRIPE_WIDTH - 1));
|
||||
}
|
||||
|
||||
/* Wait for the loads (and thus flushes) to have completed. */
|
||||
__insn_mf();
|
||||
}
|
||||
|
||||
#endif /* _ASM_TILE_CACHEFLUSH_H */
|
||||
|
|
|
@ -55,9 +55,6 @@ extern void iounmap(volatile void __iomem *addr);
|
|||
#define ioremap_writethrough(physaddr, size) ioremap(physaddr, size)
|
||||
#define ioremap_fullcache(physaddr, size) ioremap(physaddr, size)
|
||||
|
||||
void __iomem *ioport_map(unsigned long port, unsigned int len);
|
||||
extern inline void ioport_unmap(void __iomem *addr) {}
|
||||
|
||||
#define mmiowb()
|
||||
|
||||
/* Conversion between virtual and physical mappings. */
|
||||
|
@ -189,12 +186,22 @@ static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
|
|||
* we never run, uses them unconditionally.
|
||||
*/
|
||||
|
||||
static inline int ioport_panic(void)
|
||||
static inline long ioport_panic(void)
|
||||
{
|
||||
panic("inb/outb and friends do not exist on tile");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void __iomem *ioport_map(unsigned long port, unsigned int len)
|
||||
{
|
||||
return (void __iomem *) ioport_panic();
|
||||
}
|
||||
|
||||
static inline void ioport_unmap(void __iomem *addr)
|
||||
{
|
||||
ioport_panic();
|
||||
}
|
||||
|
||||
static inline u8 inb(unsigned long addr)
|
||||
{
|
||||
return ioport_panic();
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_TILE_PCI_BRIDGE_H
|
||||
#define _ASM_TILE_PCI_BRIDGE_H
|
||||
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
struct device_node;
|
||||
struct pci_controller;
|
||||
|
||||
/*
|
||||
* pci_io_base returns the memory address at which you can access
|
||||
* the I/O space for PCI bus number `bus' (or NULL on error).
|
||||
*/
|
||||
extern void __iomem *pci_bus_io_base(unsigned int bus);
|
||||
extern unsigned long pci_bus_io_base_phys(unsigned int bus);
|
||||
extern unsigned long pci_bus_mem_base_phys(unsigned int bus);
|
||||
|
||||
/* Allocate a new PCI host bridge structure */
|
||||
extern struct pci_controller *pcibios_alloc_controller(void);
|
||||
|
||||
/* Helper function for setting up resources */
|
||||
extern void pci_init_resource(struct resource *res, unsigned long start,
|
||||
unsigned long end, int flags, char *name);
|
||||
|
||||
/* Get the PCI host controller for a bus */
|
||||
extern struct pci_controller *pci_bus_to_hose(int bus);
|
||||
|
||||
/*
|
||||
* Structure of a PCI controller (host bridge)
|
||||
*/
|
||||
struct pci_controller {
|
||||
int index; /* PCI domain number */
|
||||
struct pci_bus *root_bus;
|
||||
|
||||
int first_busno;
|
||||
int last_busno;
|
||||
|
||||
int hv_cfg_fd[2]; /* config{0,1} fds for this PCIe controller */
|
||||
int hv_mem_fd; /* fd to Hypervisor for MMIO operations */
|
||||
|
||||
struct pci_ops *ops;
|
||||
|
||||
int irq_base; /* Base IRQ from the Hypervisor */
|
||||
int plx_gen1; /* flag for PLX Gen 1 configuration */
|
||||
|
||||
/* Address ranges that are routed to this controller/bridge. */
|
||||
struct resource mem_resources[3];
|
||||
};
|
||||
|
||||
static inline struct pci_controller *pci_bus_to_host(struct pci_bus *bus)
|
||||
{
|
||||
return bus->sysdata;
|
||||
}
|
||||
|
||||
extern void setup_indirect_pci_nomap(struct pci_controller *hose,
|
||||
void __iomem *cfg_addr, void __iomem *cfg_data);
|
||||
extern void setup_indirect_pci(struct pci_controller *hose,
|
||||
u32 cfg_addr, u32 cfg_data);
|
||||
extern void setup_grackle(struct pci_controller *hose);
|
||||
|
||||
extern unsigned char common_swizzle(struct pci_dev *, unsigned char *);
|
||||
|
||||
/*
|
||||
* The following code swizzles for exactly one bridge. The routine
|
||||
* common_swizzle below handles multiple bridges. But there are a
|
||||
* some boards that don't follow the PCI spec's suggestion so we
|
||||
* break this piece out separately.
|
||||
*/
|
||||
static inline unsigned char bridge_swizzle(unsigned char pin,
|
||||
unsigned char idsel)
|
||||
{
|
||||
return (((pin-1) + idsel) % 4) + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* The following macro is used to lookup irqs in a standard table
|
||||
* format for those PPC systems that do not already have PCI
|
||||
* interrupts properly routed.
|
||||
*/
|
||||
/* FIXME - double check this */
|
||||
#define PCI_IRQ_TABLE_LOOKUP ({ \
|
||||
long _ctl_ = -1; \
|
||||
if (idsel >= min_idsel && idsel <= max_idsel && pin <= irqs_per_slot) \
|
||||
_ctl_ = pci_irq_table[idsel - min_idsel][pin-1]; \
|
||||
_ctl_; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Scan the buses below a given PCI host bridge and assign suitable
|
||||
* resources to all devices found.
|
||||
*/
|
||||
extern int pciauto_bus_scan(struct pci_controller *, int);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
extern unsigned long pci_address_to_pio(phys_addr_t address);
|
||||
#else
|
||||
static inline unsigned long pci_address_to_pio(phys_addr_t address)
|
||||
{
|
||||
return (unsigned long)-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_TILE_PCI_BRIDGE_H */
|
|
@ -15,7 +15,29 @@
|
|||
#ifndef _ASM_TILE_PCI_H
|
||||
#define _ASM_TILE_PCI_H
|
||||
|
||||
#include <asm/pci-bridge.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
/*
|
||||
* Structure of a PCI controller (host bridge)
|
||||
*/
|
||||
struct pci_controller {
|
||||
int index; /* PCI domain number */
|
||||
struct pci_bus *root_bus;
|
||||
|
||||
int first_busno;
|
||||
int last_busno;
|
||||
|
||||
int hv_cfg_fd[2]; /* config{0,1} fds for this PCIe controller */
|
||||
int hv_mem_fd; /* fd to Hypervisor for MMIO operations */
|
||||
|
||||
struct pci_ops *ops;
|
||||
|
||||
int irq_base; /* Base IRQ from the Hypervisor */
|
||||
int plx_gen1; /* flag for PLX Gen 1 configuration */
|
||||
|
||||
/* Address ranges that are routed to this controller/bridge. */
|
||||
struct resource mem_resources[3];
|
||||
};
|
||||
|
||||
/*
|
||||
* The hypervisor maps the entirety of CPA-space as bus addresses, so
|
||||
|
@ -24,57 +46,13 @@
|
|||
*/
|
||||
#define PCI_DMA_BUS_IS_PHYS 1
|
||||
|
||||
struct pci_controller *pci_bus_to_hose(int bus);
|
||||
unsigned char __init common_swizzle(struct pci_dev *dev, unsigned char *pinp);
|
||||
int __init tile_pci_init(void);
|
||||
void pci_iounmap(struct pci_dev *dev, void __iomem *addr);
|
||||
|
||||
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max);
|
||||
static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
|
||||
|
||||
void __devinit pcibios_fixup_bus(struct pci_bus *bus);
|
||||
|
||||
int __devinit _tile_cfg_read(struct pci_controller *hose,
|
||||
int bus,
|
||||
int slot,
|
||||
int function,
|
||||
int offset,
|
||||
int size,
|
||||
u32 *val);
|
||||
int __devinit _tile_cfg_write(struct pci_controller *hose,
|
||||
int bus,
|
||||
int slot,
|
||||
int function,
|
||||
int offset,
|
||||
int size,
|
||||
u32 val);
|
||||
|
||||
/*
|
||||
* These are used to to config reads and writes in the early stages of
|
||||
* setup before the driver infrastructure has been set up enough to be
|
||||
* able to do config reads and writes.
|
||||
*/
|
||||
#define early_cfg_read(where, size, value) \
|
||||
_tile_cfg_read(controller, \
|
||||
current_bus, \
|
||||
pci_slot, \
|
||||
pci_fn, \
|
||||
where, \
|
||||
size, \
|
||||
value)
|
||||
|
||||
#define early_cfg_write(where, size, value) \
|
||||
_tile_cfg_write(controller, \
|
||||
current_bus, \
|
||||
pci_slot, \
|
||||
pci_fn, \
|
||||
where, \
|
||||
size, \
|
||||
value)
|
||||
|
||||
|
||||
|
||||
#define PCICFG_BYTE 1
|
||||
#define PCICFG_WORD 2
|
||||
#define PCICFG_DWORD 4
|
||||
|
||||
#define TILE_NUM_PCIE 2
|
||||
|
||||
#define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index)
|
||||
|
@ -88,33 +66,33 @@ static inline int pci_proc_domain(struct pci_bus *bus)
|
|||
}
|
||||
|
||||
/*
|
||||
* I/O space is currently not supported.
|
||||
* pcibios_assign_all_busses() tells whether or not the bus numbers
|
||||
* should be reassigned, in case the BIOS didn't do it correctly, or
|
||||
* in case we don't have a BIOS and we want to let Linux do it.
|
||||
*/
|
||||
static inline int pcibios_assign_all_busses(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define TILE_PCIE_LOWER_IO 0x0
|
||||
#define TILE_PCIE_UPPER_IO 0x10000
|
||||
#define TILE_PCIE_PCIE_IO_SIZE 0x0000FFFF
|
||||
|
||||
#define _PAGE_NO_CACHE 0
|
||||
#define _PAGE_GUARDED 0
|
||||
|
||||
|
||||
#define pcibios_assign_all_busses() pci_assign_all_buses
|
||||
extern int pci_assign_all_buses;
|
||||
|
||||
/*
|
||||
* No special bus mastering setup handling.
|
||||
*/
|
||||
static inline void pcibios_set_master(struct pci_dev *dev)
|
||||
{
|
||||
/* No special bus mastering setup handling */
|
||||
}
|
||||
|
||||
#define PCIBIOS_MIN_MEM 0
|
||||
#define PCIBIOS_MIN_IO TILE_PCIE_LOWER_IO
|
||||
#define PCIBIOS_MIN_IO 0
|
||||
|
||||
/*
|
||||
* This flag tells if the platform is TILEmpower that needs
|
||||
* special configuration for the PLX switch chip.
|
||||
*/
|
||||
extern int blade_pci;
|
||||
extern int tile_plx_gen1;
|
||||
|
||||
/* Use any cpu for PCI. */
|
||||
#define cpumask_of_pcibus(bus) cpu_online_mask
|
||||
|
||||
/* implement the pci_ DMA API in terms of the generic device dma_ one */
|
||||
#include <asm-generic/pci-dma-compat.h>
|
||||
|
@ -122,7 +100,4 @@ extern int blade_pci;
|
|||
/* generic pci stuff */
|
||||
#include <asm-generic/pci.h>
|
||||
|
||||
/* Use any cpu for PCI. */
|
||||
#define cpumask_of_pcibus(bus) cpu_online_mask
|
||||
|
||||
#endif /* _ASM_TILE_PCI_H */
|
||||
|
|
|
@ -292,8 +292,18 @@ extern int kstack_hash;
|
|||
/* Are we using huge pages in the TLB for kernel data? */
|
||||
extern int kdata_huge;
|
||||
|
||||
/* Support standard Linux prefetching. */
|
||||
#define ARCH_HAS_PREFETCH
|
||||
#define prefetch(x) __builtin_prefetch(x)
|
||||
#define PREFETCH_STRIDE CHIP_L2_LINE_SIZE()
|
||||
|
||||
/* Bring a value into the L1D, faulting the TLB if necessary. */
|
||||
#ifdef __tilegx__
|
||||
#define prefetch_L1(x) __insn_prefetch_l1_fault((void *)(x))
|
||||
#else
|
||||
#define prefetch_L1(x) __insn_prefetch_L1((void *)(x))
|
||||
#endif
|
||||
|
||||
#else /* __ASSEMBLY__ */
|
||||
|
||||
/* Do some slow action (e.g. read a slow SPR). */
|
||||
|
|
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file drivers/xgbe/impl.h
|
||||
* Implementation details for the NetIO library.
|
||||
*/
|
||||
|
||||
#ifndef __DRV_XGBE_IMPL_H__
|
||||
#define __DRV_XGBE_IMPL_H__
|
||||
|
||||
#include <hv/netio_errors.h>
|
||||
#include <hv/netio_intf.h>
|
||||
#include <hv/drv_xgbe_intf.h>
|
||||
|
||||
|
||||
/** How many groups we have (log2). */
|
||||
#define LOG2_NUM_GROUPS (12)
|
||||
/** How many groups we have. */
|
||||
#define NUM_GROUPS (1 << LOG2_NUM_GROUPS)
|
||||
|
||||
/** Number of output requests we'll buffer per tile. */
|
||||
#define EPP_REQS_PER_TILE (32)
|
||||
|
||||
/** Words used in an eDMA command without checksum acceleration. */
|
||||
#define EDMA_WDS_NO_CSUM 8
|
||||
/** Words used in an eDMA command with checksum acceleration. */
|
||||
#define EDMA_WDS_CSUM 10
|
||||
/** Total available words in the eDMA command FIFO. */
|
||||
#define EDMA_WDS_TOTAL 128
|
||||
|
||||
|
||||
/*
|
||||
* FIXME: These definitions are internal and should have underscores!
|
||||
* NOTE: The actual numeric values here are intentional and allow us to
|
||||
* optimize the concept "if small ... else if large ... else ...", by
|
||||
* checking for the low bit being set, and then for non-zero.
|
||||
* These are used as array indices, so they must have the values (0, 1, 2)
|
||||
* in some order.
|
||||
*/
|
||||
#define SIZE_SMALL (1) /**< Small packet queue. */
|
||||
#define SIZE_LARGE (2) /**< Large packet queue. */
|
||||
#define SIZE_JUMBO (0) /**< Jumbo packet queue. */
|
||||
|
||||
/** The number of "SIZE_xxx" values. */
|
||||
#define NETIO_NUM_SIZES 3
|
||||
|
||||
|
||||
/*
|
||||
* Default numbers of packets for IPP drivers. These values are chosen
|
||||
* such that CIPP1 will not overflow its L2 cache.
|
||||
*/
|
||||
|
||||
/** The default number of small packets. */
|
||||
#define NETIO_DEFAULT_SMALL_PACKETS 2750
|
||||
/** The default number of large packets. */
|
||||
#define NETIO_DEFAULT_LARGE_PACKETS 2500
|
||||
/** The default number of jumbo packets. */
|
||||
#define NETIO_DEFAULT_JUMBO_PACKETS 250
|
||||
|
||||
|
||||
/** Log2 of the size of a memory arena. */
|
||||
#define NETIO_ARENA_SHIFT 24 /* 16 MB */
|
||||
/** Size of a memory arena. */
|
||||
#define NETIO_ARENA_SIZE (1 << NETIO_ARENA_SHIFT)
|
||||
|
||||
|
||||
/** A queue of packets.
|
||||
*
|
||||
* This structure partially defines a queue of packets waiting to be
|
||||
* processed. The queue as a whole is written to by an interrupt handler and
|
||||
* read by non-interrupt code; this data structure is what's touched by the
|
||||
* interrupt handler. The other part of the queue state, the read offset, is
|
||||
* kept in user space, not in hypervisor space, so it is in a separate data
|
||||
* structure.
|
||||
*
|
||||
* The read offset (__packet_receive_read in the user part of the queue
|
||||
* structure) points to the next packet to be read. When the read offset is
|
||||
* equal to the write offset, the queue is empty; therefore the queue must
|
||||
* contain one more slot than the required maximum queue size.
|
||||
*
|
||||
* Here's an example of all 3 state variables and what they mean. All
|
||||
* pointers move left to right.
|
||||
*
|
||||
* @code
|
||||
* I I V V V V I I I I
|
||||
* 0 1 2 3 4 5 6 7 8 9 10
|
||||
* ^ ^ ^ ^
|
||||
* | | |
|
||||
* | | __last_packet_plus_one
|
||||
* | __buffer_write
|
||||
* __packet_receive_read
|
||||
* @endcode
|
||||
*
|
||||
* This queue has 10 slots, and thus can hold 9 packets (_last_packet_plus_one
|
||||
* = 10). The read pointer is at 2, and the write pointer is at 6; thus,
|
||||
* there are valid, unread packets in slots 2, 3, 4, and 5. The remaining
|
||||
* slots are invalid (do not contain a packet).
|
||||
*/
|
||||
typedef struct {
|
||||
/** Byte offset of the next notify packet to be written: zero for the first
|
||||
* packet on the queue, sizeof (netio_pkt_t) for the second packet on the
|
||||
* queue, etc. */
|
||||
volatile uint32_t __packet_write;
|
||||
|
||||
/** Offset of the packet after the last valid packet (i.e., when any
|
||||
* pointer is incremented to this value, it wraps back to zero). */
|
||||
uint32_t __last_packet_plus_one;
|
||||
}
|
||||
__netio_packet_queue_t;
|
||||
|
||||
|
||||
/** A queue of buffers.
|
||||
*
|
||||
* This structure partially defines a queue of empty buffers which have been
|
||||
* obtained via requests to the IPP. (The elements of the queue are packet
|
||||
* handles, which are transformed into a full netio_pkt_t when the buffer is
|
||||
* retrieved.) The queue as a whole is written to by an interrupt handler and
|
||||
* read by non-interrupt code; this data structure is what's touched by the
|
||||
* interrupt handler. The other parts of the queue state, the read offset and
|
||||
* requested write offset, are kept in user space, not in hypervisor space, so
|
||||
* they are in a separate data structure.
|
||||
*
|
||||
* The read offset (__buffer_read in the user part of the queue structure)
|
||||
* points to the next buffer to be read. When the read offset is equal to the
|
||||
* write offset, the queue is empty; therefore the queue must contain one more
|
||||
* slot than the required maximum queue size.
|
||||
*
|
||||
* The requested write offset (__buffer_requested_write in the user part of
|
||||
* the queue structure) points to the slot which will hold the next buffer we
|
||||
* request from the IPP, once we get around to sending such a request. When
|
||||
* the requested write offset is equal to the write offset, no requests for
|
||||
* new buffers are outstanding; when the requested write offset is one greater
|
||||
* than the read offset, no more requests may be sent.
|
||||
*
|
||||
* Note that, unlike the packet_queue, the buffer_queue places incoming
|
||||
* buffers at decreasing addresses. This makes the check for "is it time to
|
||||
* wrap the buffer pointer" cheaper in the assembly code which receives new
|
||||
* buffers, and means that the value which defines the queue size,
|
||||
* __last_buffer, is different than in the packet queue. Also, the offset
|
||||
* used in the packet_queue is already scaled by the size of a packet; here we
|
||||
* use unscaled slot indices for the offsets. (These differences are
|
||||
* historical, and in the future it's possible that the packet_queue will look
|
||||
* more like this queue.)
|
||||
*
|
||||
* @code
|
||||
* Here's an example of all 4 state variables and what they mean. Remember:
|
||||
* all pointers move right to left.
|
||||
*
|
||||
* V V V I I R R V V V
|
||||
* 0 1 2 3 4 5 6 7 8 9
|
||||
* ^ ^ ^ ^
|
||||
* | | | |
|
||||
* | | | __last_buffer
|
||||
* | | __buffer_write
|
||||
* | __buffer_requested_write
|
||||
* __buffer_read
|
||||
* @endcode
|
||||
*
|
||||
* This queue has 10 slots, and thus can hold 9 buffers (_last_buffer = 9).
|
||||
* The read pointer is at 2, and the write pointer is at 6; thus, there are
|
||||
* valid, unread buffers in slots 2, 1, 0, 9, 8, and 7. The requested write
|
||||
* pointer is at 4; thus, requests have been made to the IPP for buffers which
|
||||
* will be placed in slots 6 and 5 when they arrive. Finally, the remaining
|
||||
* slots are invalid (do not contain a buffer).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** Ordinal number of the next buffer to be written: 0 for the first slot in
|
||||
* the queue, 1 for the second slot in the queue, etc. */
|
||||
volatile uint32_t __buffer_write;
|
||||
|
||||
/** Ordinal number of the last buffer (i.e., when any pointer is decremented
|
||||
* below zero, it is reloaded with this value). */
|
||||
uint32_t __last_buffer;
|
||||
}
|
||||
__netio_buffer_queue_t;
|
||||
|
||||
|
||||
/**
|
||||
* An object for providing Ethernet packets to a process.
|
||||
*/
|
||||
typedef struct __netio_queue_impl_t
|
||||
{
|
||||
/** The queue of packets waiting to be received. */
|
||||
__netio_packet_queue_t __packet_receive_queue;
|
||||
/** The intr bit mask that IDs this device. */
|
||||
unsigned int __intr_id;
|
||||
/** Offset to queues of empty buffers, one per size. */
|
||||
uint32_t __buffer_queue[NETIO_NUM_SIZES];
|
||||
/** The address of the first EPP tile, or -1 if no EPP. */
|
||||
/* ISSUE: Actually this is always "0" or "~0". */
|
||||
uint32_t __epp_location;
|
||||
/** The queue ID that this queue represents. */
|
||||
unsigned int __queue_id;
|
||||
/** Number of acknowledgements received. */
|
||||
volatile uint32_t __acks_received;
|
||||
/** Last completion number received for packet_sendv. */
|
||||
volatile uint32_t __last_completion_rcv;
|
||||
/** Number of packets allowed to be outstanding. */
|
||||
uint32_t __max_outstanding;
|
||||
/** First VA available for packets. */
|
||||
void* __va_0;
|
||||
/** First VA in second range available for packets. */
|
||||
void* __va_1;
|
||||
/** Padding to align the "__packets" field to the size of a netio_pkt_t. */
|
||||
uint32_t __padding[3];
|
||||
/** The packets themselves. */
|
||||
netio_pkt_t __packets[0];
|
||||
}
|
||||
netio_queue_impl_t;
|
||||
|
||||
|
||||
/**
|
||||
* An object for managing the user end of a NetIO queue.
|
||||
*/
|
||||
typedef struct __netio_queue_user_impl_t
|
||||
{
|
||||
/** The next incoming packet to be read. */
|
||||
uint32_t __packet_receive_read;
|
||||
/** The next empty buffers to be read, one index per size. */
|
||||
uint8_t __buffer_read[NETIO_NUM_SIZES];
|
||||
/** Where the empty buffer we next request from the IPP will go, one index
|
||||
* per size. */
|
||||
uint8_t __buffer_requested_write[NETIO_NUM_SIZES];
|
||||
/** PCIe interface flag. */
|
||||
uint8_t __pcie;
|
||||
/** Number of packets left to be received before we send a credit update. */
|
||||
uint32_t __receive_credit_remaining;
|
||||
/** Value placed in __receive_credit_remaining when it reaches zero. */
|
||||
uint32_t __receive_credit_interval;
|
||||
/** First fast I/O routine index. */
|
||||
uint32_t __fastio_index;
|
||||
/** Number of acknowledgements expected. */
|
||||
uint32_t __acks_outstanding;
|
||||
/** Last completion number requested. */
|
||||
uint32_t __last_completion_req;
|
||||
/** File descriptor for driver. */
|
||||
int __fd;
|
||||
}
|
||||
netio_queue_user_impl_t;
|
||||
|
||||
|
||||
#define NETIO_GROUP_CHUNK_SIZE 64 /**< Max # groups in one IPP request */
|
||||
#define NETIO_BUCKET_CHUNK_SIZE 64 /**< Max # buckets in one IPP request */
|
||||
|
||||
|
||||
/** Internal structure used to convey packet send information to the
|
||||
* hypervisor. FIXME: Actually, it's not used for that anymore, but
|
||||
* netio_packet_send() still uses it internally.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t flags; /**< Packet flags (__NETIO_SEND_FLG_xxx) */
|
||||
uint16_t transfer_size; /**< Size of packet */
|
||||
uint32_t va; /**< VA of start of packet */
|
||||
__netio_pkt_handle_t handle; /**< Packet handle */
|
||||
uint32_t csum0; /**< First checksum word */
|
||||
uint32_t csum1; /**< Second checksum word */
|
||||
}
|
||||
__netio_send_cmd_t;
|
||||
|
||||
|
||||
/** Flags used in two contexts:
|
||||
* - As the "flags" member in the __netio_send_cmd_t, above; used only
|
||||
* for netio_pkt_send_{prepare,commit}.
|
||||
* - As part of the flags passed to the various send packet fast I/O calls.
|
||||
*/
|
||||
|
||||
/** Need acknowledgement on this packet. Note that some code in the
|
||||
* normal send_pkt fast I/O handler assumes that this is equal to 1. */
|
||||
#define __NETIO_SEND_FLG_ACK 0x1
|
||||
|
||||
/** Do checksum on this packet. (Only used with the __netio_send_cmd_t;
|
||||
* normal packet sends use a special fast I/O index to denote checksumming,
|
||||
* and multi-segment sends test the checksum descriptor.) */
|
||||
#define __NETIO_SEND_FLG_CSUM 0x2
|
||||
|
||||
/** Get a completion on this packet. Only used with multi-segment sends. */
|
||||
#define __NETIO_SEND_FLG_COMPLETION 0x4
|
||||
|
||||
/** Position of the number-of-extra-segments value in the flags word.
|
||||
Only used with multi-segment sends. */
|
||||
#define __NETIO_SEND_FLG_XSEG_SHIFT 3
|
||||
|
||||
/** Width of the number-of-extra-segments value in the flags word. */
|
||||
#define __NETIO_SEND_FLG_XSEG_WIDTH 2
|
||||
|
||||
#endif /* __DRV_XGBE_IMPL_H__ */
|
|
@ -0,0 +1,615 @@
|
|||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file drv_xgbe_intf.h
|
||||
* Interface to the hypervisor XGBE driver.
|
||||
*/
|
||||
|
||||
#ifndef __DRV_XGBE_INTF_H__
|
||||
#define __DRV_XGBE_INTF_H__
|
||||
|
||||
/**
|
||||
* An object for forwarding VAs and PAs to the hypervisor.
|
||||
* @ingroup types
|
||||
*
|
||||
* This allows the supervisor to specify a number of areas of memory to
|
||||
* store packet buffers.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** The physical address of the memory. */
|
||||
HV_PhysAddr pa;
|
||||
/** Page table entry for the memory. This is only used to derive the
|
||||
* memory's caching mode; the PA bits are ignored. */
|
||||
HV_PTE pte;
|
||||
/** The virtual address of the memory. */
|
||||
HV_VirtAddr va;
|
||||
/** Size (in bytes) of the memory area. */
|
||||
int size;
|
||||
|
||||
}
|
||||
netio_ipp_address_t;
|
||||
|
||||
/** The various pread/pwrite offsets into the hypervisor-level driver.
|
||||
* @ingroup types
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/** Inform the Linux driver of the address of the NetIO arena memory.
|
||||
* This offset is actually only used to convey information from netio
|
||||
* to the Linux driver; it never makes it from there to the hypervisor.
|
||||
* Write-only; takes a uint32_t specifying the VA address. */
|
||||
NETIO_FIXED_ADDR = 0x5000000000000000ULL,
|
||||
|
||||
/** Inform the Linux driver of the size of the NetIO arena memory.
|
||||
* This offset is actually only used to convey information from netio
|
||||
* to the Linux driver; it never makes it from there to the hypervisor.
|
||||
* Write-only; takes a uint32_t specifying the VA size. */
|
||||
NETIO_FIXED_SIZE = 0x5100000000000000ULL,
|
||||
|
||||
/** Register current tile with IPP. Write then read: write, takes a
|
||||
* netio_input_config_t, read returns a pointer to a netio_queue_impl_t. */
|
||||
NETIO_IPP_INPUT_REGISTER_OFF = 0x6000000000000000ULL,
|
||||
|
||||
/** Unregister current tile from IPP. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_INPUT_UNREGISTER_OFF = 0x6100000000000000ULL,
|
||||
|
||||
/** Start packets flowing. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_INPUT_INIT_OFF = 0x6200000000000000ULL,
|
||||
|
||||
/** Stop packets flowing. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_INPUT_UNINIT_OFF = 0x6300000000000000ULL,
|
||||
|
||||
/** Configure group (typically we group on VLAN). Write-only: takes an
|
||||
* array of netio_group_t's, low 24 bits of the offset is the base group
|
||||
* number times the size of a netio_group_t. */
|
||||
NETIO_IPP_INPUT_GROUP_CFG_OFF = 0x6400000000000000ULL,
|
||||
|
||||
/** Configure bucket. Write-only: takes an array of netio_bucket_t's, low
|
||||
* 24 bits of the offset is the base bucket number times the size of a
|
||||
* netio_bucket_t. */
|
||||
NETIO_IPP_INPUT_BUCKET_CFG_OFF = 0x6500000000000000ULL,
|
||||
|
||||
/** Get/set a parameter. Read or write: read or write data is the parameter
|
||||
* value, low 32 bits of the offset is a __netio_getset_offset_t. */
|
||||
NETIO_IPP_PARAM_OFF = 0x6600000000000000ULL,
|
||||
|
||||
/** Get fast I/O index. Read-only; returns a 4-byte base index value. */
|
||||
NETIO_IPP_GET_FASTIO_OFF = 0x6700000000000000ULL,
|
||||
|
||||
/** Configure hijack IP address. Packets with this IPv4 dest address
|
||||
* go to bucket NETIO_NUM_BUCKETS - 1. Write-only: takes an IP address
|
||||
* in some standard form. FIXME: Define the form! */
|
||||
NETIO_IPP_INPUT_HIJACK_CFG_OFF = 0x6800000000000000ULL,
|
||||
|
||||
/**
|
||||
* Offsets beyond this point are reserved for the supervisor (although that
|
||||
* enforcement must be done by the supervisor driver itself).
|
||||
*/
|
||||
NETIO_IPP_USER_MAX_OFF = 0x6FFFFFFFFFFFFFFFULL,
|
||||
|
||||
/** Register I/O memory. Write-only, takes a netio_ipp_address_t. */
|
||||
NETIO_IPP_IOMEM_REGISTER_OFF = 0x7000000000000000ULL,
|
||||
|
||||
/** Unregister I/O memory. Write-only, takes a netio_ipp_address_t. */
|
||||
NETIO_IPP_IOMEM_UNREGISTER_OFF = 0x7100000000000000ULL,
|
||||
|
||||
/* Offsets greater than 0x7FFFFFFF can't be used directly from Linux
|
||||
* userspace code due to limitations in the pread/pwrite syscalls. */
|
||||
|
||||
/** Drain LIPP buffers. */
|
||||
NETIO_IPP_DRAIN_OFF = 0xFA00000000000000ULL,
|
||||
|
||||
/** Supply a netio_ipp_address_t to be used as shared memory for the
|
||||
* LEPP command queue. */
|
||||
NETIO_EPP_SHM_OFF = 0xFB00000000000000ULL,
|
||||
|
||||
/* 0xFC... is currently unused. */
|
||||
|
||||
/** Stop IPP/EPP tiles. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_STOP_SHIM_OFF = 0xFD00000000000000ULL,
|
||||
|
||||
/** Start IPP/EPP tiles. Write-only, takes a dummy argument. */
|
||||
NETIO_IPP_START_SHIM_OFF = 0xFE00000000000000ULL,
|
||||
|
||||
/** Supply packet arena. Write-only, takes an array of
|
||||
* netio_ipp_address_t values. */
|
||||
NETIO_IPP_ADDRESS_OFF = 0xFF00000000000000ULL,
|
||||
} netio_hv_offset_t;
|
||||
|
||||
/** Extract the base offset from an offset */
|
||||
#define NETIO_BASE_OFFSET(off) ((off) & 0xFF00000000000000ULL)
|
||||
/** Extract the local offset from an offset */
|
||||
#define NETIO_LOCAL_OFFSET(off) ((off) & 0x00FFFFFFFFFFFFFFULL)
|
||||
|
||||
|
||||
/**
|
||||
* Get/set offset.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t addr:48; /**< Class-specific address */
|
||||
unsigned int class:8; /**< Class (e.g., NETIO_PARAM) */
|
||||
unsigned int opcode:8; /**< High 8 bits of NETIO_IPP_PARAM_OFF */
|
||||
}
|
||||
bits; /**< Bitfields */
|
||||
uint64_t word; /**< Aggregated value to use as the offset */
|
||||
}
|
||||
__netio_getset_offset_t;
|
||||
|
||||
/**
|
||||
* Fast I/O index offsets (must be contiguous).
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
NETIO_FASTIO_ALLOCATE = 0, /**< Get empty packet buffer */
|
||||
NETIO_FASTIO_FREE_BUFFER = 1, /**< Give buffer back to IPP */
|
||||
NETIO_FASTIO_RETURN_CREDITS = 2, /**< Give credits to IPP */
|
||||
NETIO_FASTIO_SEND_PKT_NOCK = 3, /**< Send a packet, no checksum */
|
||||
NETIO_FASTIO_SEND_PKT_CK = 4, /**< Send a packet, with checksum */
|
||||
NETIO_FASTIO_SEND_PKT_VEC = 5, /**< Send a vector of packets */
|
||||
NETIO_FASTIO_SENDV_PKT = 6, /**< Sendv one packet */
|
||||
NETIO_FASTIO_NUM_INDEX = 7, /**< Total number of fast I/O indices */
|
||||
} netio_fastio_index_t;
|
||||
|
||||
/** 3-word return type for Fast I/O call. */
|
||||
typedef struct
|
||||
{
|
||||
int err; /**< Error code. */
|
||||
uint32_t val0; /**< Value. Meaning depends upon the specific call. */
|
||||
uint32_t val1; /**< Value. Meaning depends upon the specific call. */
|
||||
} netio_fastio_rv3_t;
|
||||
|
||||
/** 0-argument fast I/O call */
|
||||
int __netio_fastio0(uint32_t fastio_index);
|
||||
/** 1-argument fast I/O call */
|
||||
int __netio_fastio1(uint32_t fastio_index, uint32_t arg0);
|
||||
/** 3-argument fast I/O call, 2-word return value */
|
||||
netio_fastio_rv3_t __netio_fastio3_rv3(uint32_t fastio_index, uint32_t arg0,
|
||||
uint32_t arg1, uint32_t arg2);
|
||||
/** 4-argument fast I/O call */
|
||||
int __netio_fastio4(uint32_t fastio_index, uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3);
|
||||
/** 6-argument fast I/O call */
|
||||
int __netio_fastio6(uint32_t fastio_index, uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5);
|
||||
/** 9-argument fast I/O call */
|
||||
int __netio_fastio9(uint32_t fastio_index, uint32_t arg0, uint32_t arg1,
|
||||
uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5,
|
||||
uint32_t arg6, uint32_t arg7, uint32_t arg8);
|
||||
|
||||
/** Allocate an empty packet.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param size Size of the packet to allocate.
|
||||
*/
|
||||
#define __netio_fastio_allocate(fastio_index, size) \
|
||||
__netio_fastio1((fastio_index) + NETIO_FASTIO_ALLOCATE, size)
|
||||
|
||||
/** Free a buffer.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param handle Handle for the packet to free.
|
||||
*/
|
||||
#define __netio_fastio_free_buffer(fastio_index, handle) \
|
||||
__netio_fastio1((fastio_index) + NETIO_FASTIO_FREE_BUFFER, handle)
|
||||
|
||||
/** Increment our receive credits.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param credits Number of credits to add.
|
||||
*/
|
||||
#define __netio_fastio_return_credits(fastio_index, credits) \
|
||||
__netio_fastio1((fastio_index) + NETIO_FASTIO_RETURN_CREDITS, credits)
|
||||
|
||||
/** Send packet, no checksum.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param ackflag Nonzero if we want an ack.
|
||||
* @param size Size of the packet.
|
||||
* @param va Virtual address of start of packet.
|
||||
* @param handle Packet handle.
|
||||
*/
|
||||
#define __netio_fastio_send_pkt_nock(fastio_index, ackflag, size, va, handle) \
|
||||
__netio_fastio4((fastio_index) + NETIO_FASTIO_SEND_PKT_NOCK, ackflag, \
|
||||
size, va, handle)
|
||||
|
||||
/** Send packet, calculate checksum.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param ackflag Nonzero if we want an ack.
|
||||
* @param size Size of the packet.
|
||||
* @param va Virtual address of start of packet.
|
||||
* @param handle Packet handle.
|
||||
* @param csum0 Shim checksum header.
|
||||
* @param csum1 Checksum seed.
|
||||
*/
|
||||
#define __netio_fastio_send_pkt_ck(fastio_index, ackflag, size, va, handle, \
|
||||
csum0, csum1) \
|
||||
__netio_fastio6((fastio_index) + NETIO_FASTIO_SEND_PKT_CK, ackflag, \
|
||||
size, va, handle, csum0, csum1)
|
||||
|
||||
|
||||
/** Format for the "csum0" argument to the __netio_fastio_send routines
|
||||
* and LEPP. Note that this is currently exactly identical to the
|
||||
* ShimProtocolOffloadHeader.
|
||||
*/
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int start_byte:7; /**< The first byte to be checksummed */
|
||||
unsigned int count:14; /**< Number of bytes to be checksummed. */
|
||||
unsigned int destination_byte:7; /**< The byte to write the checksum to. */
|
||||
unsigned int reserved:4; /**< Reserved. */
|
||||
} bits; /**< Decomposed method of access. */
|
||||
unsigned int word; /**< To send out the IDN. */
|
||||
} __netio_checksum_header_t;
|
||||
|
||||
|
||||
/** Sendv packet with 1 or 2 segments.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param flags Ack/csum/notify flags in low 3 bits; number of segments minus
|
||||
* 1 in next 2 bits; expected checksum in high 16 bits.
|
||||
* @param confno Confirmation number to request, if notify flag set.
|
||||
* @param csum0 Checksum descriptor; if zero, no checksum.
|
||||
* @param va_F Virtual address of first segment.
|
||||
* @param va_L Virtual address of last segment, if 2 segments.
|
||||
* @param len_F_L Length of first segment in low 16 bits; length of last
|
||||
* segment, if 2 segments, in high 16 bits.
|
||||
*/
|
||||
#define __netio_fastio_sendv_pkt_1_2(fastio_index, flags, confno, csum0, \
|
||||
va_F, va_L, len_F_L) \
|
||||
__netio_fastio6((fastio_index) + NETIO_FASTIO_SENDV_PKT, flags, confno, \
|
||||
csum0, va_F, va_L, len_F_L)
|
||||
|
||||
/** Send packet on PCIe interface.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param flags Ack/csum/notify flags in low 3 bits.
|
||||
* @param confno Confirmation number to request, if notify flag set.
|
||||
* @param csum0 Checksum descriptor; Hard wired 0, not needed for PCIe.
|
||||
* @param va_F Virtual address of the packet buffer.
|
||||
* @param va_L Virtual address of last segment, if 2 segments. Hard wired 0.
|
||||
* @param len_F_L Length of the packet buffer in low 16 bits.
|
||||
*/
|
||||
#define __netio_fastio_send_pcie_pkt(fastio_index, flags, confno, csum0, \
|
||||
va_F, va_L, len_F_L) \
|
||||
__netio_fastio6((fastio_index) + PCIE_FASTIO_SENDV_PKT, flags, confno, \
|
||||
csum0, va_F, va_L, len_F_L)
|
||||
|
||||
/** Sendv packet with 3 or 4 segments.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param flags Ack/csum/notify flags in low 3 bits; number of segments minus
|
||||
* 1 in next 2 bits; expected checksum in high 16 bits.
|
||||
* @param confno Confirmation number to request, if notify flag set.
|
||||
* @param csum0 Checksum descriptor; if zero, no checksum.
|
||||
* @param va_F Virtual address of first segment.
|
||||
* @param va_L Virtual address of last segment (third segment if 3 segments,
|
||||
* fourth segment if 4 segments).
|
||||
* @param len_F_L Length of first segment in low 16 bits; length of last
|
||||
* segment in high 16 bits.
|
||||
* @param va_M0 Virtual address of "middle 0" segment; this segment is sent
|
||||
* second when there are three segments, and third if there are four.
|
||||
* @param va_M1 Virtual address of "middle 1" segment; this segment is sent
|
||||
* second when there are four segments.
|
||||
* @param len_M0_M1 Length of middle 0 segment in low 16 bits; length of middle
|
||||
* 1 segment, if 4 segments, in high 16 bits.
|
||||
*/
|
||||
#define __netio_fastio_sendv_pkt_3_4(fastio_index, flags, confno, csum0, va_F, \
|
||||
va_L, len_F_L, va_M0, va_M1, len_M0_M1) \
|
||||
__netio_fastio9((fastio_index) + NETIO_FASTIO_SENDV_PKT, flags, confno, \
|
||||
csum0, va_F, va_L, len_F_L, va_M0, va_M1, len_M0_M1)
|
||||
|
||||
/** Send vector of packets.
|
||||
* @param fastio_index Fast I/O index.
|
||||
* @param seqno Number of packets transmitted so far on this interface;
|
||||
* used to decide which packets should be acknowledged.
|
||||
* @param nentries Number of entries in vector.
|
||||
* @param va Virtual address of start of vector entry array.
|
||||
* @return 3-word netio_fastio_rv3_t structure. The structure's err member
|
||||
* is an error code, or zero if no error. The val0 member is the
|
||||
* updated value of seqno; it has been incremented by 1 for each
|
||||
* packet sent. That increment may be less than nentries if an
|
||||
* error occured, or if some of the entries in the vector contain
|
||||
* handles equal to NETIO_PKT_HANDLE_NONE. The val1 member is the
|
||||
* updated value of nentries; it has been decremented by 1 for each
|
||||
* vector entry processed. Again, that decrement may be less than
|
||||
* nentries (leaving the returned value positive) if an error
|
||||
* occurred.
|
||||
*/
|
||||
#define __netio_fastio_send_pkt_vec(fastio_index, seqno, nentries, va) \
|
||||
__netio_fastio3_rv3((fastio_index) + NETIO_FASTIO_SEND_PKT_VEC, seqno, \
|
||||
nentries, va)
|
||||
|
||||
|
||||
/** An egress DMA command for LEPP. */
|
||||
typedef struct
|
||||
{
|
||||
/** Is this a TSO transfer?
|
||||
*
|
||||
* NOTE: This field is always 0, to distinguish it from
|
||||
* lepp_tso_cmd_t. It must come first!
|
||||
*/
|
||||
uint8_t tso : 1;
|
||||
|
||||
/** Unused padding bits. */
|
||||
uint8_t _unused : 3;
|
||||
|
||||
/** Should this packet be sent directly from caches instead of DRAM,
|
||||
* using hash-for-home to locate the packet data?
|
||||
*/
|
||||
uint8_t hash_for_home : 1;
|
||||
|
||||
/** Should we compute a checksum? */
|
||||
uint8_t compute_checksum : 1;
|
||||
|
||||
/** Is this the final buffer for this packet?
|
||||
*
|
||||
* A single packet can be split over several input buffers (a "gather"
|
||||
* operation). This flag indicates that this is the last buffer
|
||||
* in a packet.
|
||||
*/
|
||||
uint8_t end_of_packet : 1;
|
||||
|
||||
/** Should LEPP advance 'comp_busy' when this DMA is fully finished? */
|
||||
uint8_t send_completion : 1;
|
||||
|
||||
/** High bits of Client Physical Address of the start of the buffer
|
||||
* to be egressed.
|
||||
*
|
||||
* NOTE: Only 6 bits are actually needed here, as CPAs are
|
||||
* currently 38 bits. So two bits could be scavenged from this.
|
||||
*/
|
||||
uint8_t cpa_hi;
|
||||
|
||||
/** The number of bytes to be egressed. */
|
||||
uint16_t length;
|
||||
|
||||
/** Low 32 bits of Client Physical Address of the start of the buffer
|
||||
* to be egressed.
|
||||
*/
|
||||
uint32_t cpa_lo;
|
||||
|
||||
/** Checksum information (only used if 'compute_checksum'). */
|
||||
__netio_checksum_header_t checksum_data;
|
||||
|
||||
} lepp_cmd_t;
|
||||
|
||||
|
||||
/** A chunk of physical memory for a TSO egress. */
|
||||
typedef struct
|
||||
{
|
||||
/** The low bits of the CPA. */
|
||||
uint32_t cpa_lo;
|
||||
/** The high bits of the CPA. */
|
||||
uint16_t cpa_hi : 15;
|
||||
/** Should this packet be sent directly from caches instead of DRAM,
|
||||
* using hash-for-home to locate the packet data?
|
||||
*/
|
||||
uint16_t hash_for_home : 1;
|
||||
/** The length in bytes. */
|
||||
uint16_t length;
|
||||
} lepp_frag_t;
|
||||
|
||||
|
||||
/** An LEPP command that handles TSO. */
|
||||
typedef struct
|
||||
{
|
||||
/** Is this a TSO transfer?
|
||||
*
|
||||
* NOTE: This field is always 1, to distinguish it from
|
||||
* lepp_cmd_t. It must come first!
|
||||
*/
|
||||
uint8_t tso : 1;
|
||||
|
||||
/** Unused padding bits. */
|
||||
uint8_t _unused : 7;
|
||||
|
||||
/** Size of the header[] array in bytes. It must be in the range
|
||||
* [40, 127], which are the smallest header for a TCP packet over
|
||||
* Ethernet and the maximum possible prepend size supported by
|
||||
* hardware, respectively. Note that the array storage must be
|
||||
* padded out to a multiple of four bytes so that the following
|
||||
* LEPP command is aligned properly.
|
||||
*/
|
||||
uint8_t header_size;
|
||||
|
||||
/** Byte offset of the IP header in header[]. */
|
||||
uint8_t ip_offset;
|
||||
|
||||
/** Byte offset of the TCP header in header[]. */
|
||||
uint8_t tcp_offset;
|
||||
|
||||
/** The number of bytes to use for the payload of each packet,
|
||||
* except of course the last one, which may not have enough bytes.
|
||||
* This means that each Ethernet packet except the last will have a
|
||||
* size of header_size + payload_size.
|
||||
*/
|
||||
uint16_t payload_size;
|
||||
|
||||
/** The length of the 'frags' array that follows this struct. */
|
||||
uint16_t num_frags;
|
||||
|
||||
/** The actual frags. */
|
||||
lepp_frag_t frags[0 /* Variable-sized; num_frags entries. */];
|
||||
|
||||
/*
|
||||
* The packet header template logically follows frags[],
|
||||
* but you can't declare that in C.
|
||||
*
|
||||
* uint32_t header[header_size_in_words_rounded_up];
|
||||
*/
|
||||
|
||||
} lepp_tso_cmd_t;
|
||||
|
||||
|
||||
/** An LEPP completion ring entry. */
|
||||
typedef void* lepp_comp_t;
|
||||
|
||||
|
||||
/** Maximum number of frags for one TSO command. This is adapted from
|
||||
* linux's "MAX_SKB_FRAGS", and presumably over-estimates by one, for
|
||||
* our page size of exactly 65536. We add one for a "body" fragment.
|
||||
*/
|
||||
#define LEPP_MAX_FRAGS (65536 / HV_PAGE_SIZE_SMALL + 2 + 1)
|
||||
|
||||
/** Total number of bytes needed for an lepp_tso_cmd_t. */
|
||||
#define LEPP_TSO_CMD_SIZE(num_frags, header_size) \
|
||||
(sizeof(lepp_tso_cmd_t) + \
|
||||
(num_frags) * sizeof(lepp_frag_t) + \
|
||||
(((header_size) + 3) & -4))
|
||||
|
||||
/** The size of the lepp "cmd" queue. */
|
||||
#define LEPP_CMD_QUEUE_BYTES \
|
||||
(((CHIP_L2_CACHE_SIZE() - 2 * CHIP_L2_LINE_SIZE()) / \
|
||||
(sizeof(lepp_cmd_t) + sizeof(lepp_comp_t))) * sizeof(lepp_cmd_t))
|
||||
|
||||
/** The largest possible command that can go in lepp_queue_t::cmds[]. */
|
||||
#define LEPP_MAX_CMD_SIZE LEPP_TSO_CMD_SIZE(LEPP_MAX_FRAGS, 128)
|
||||
|
||||
/** The largest possible value of lepp_queue_t::cmd_{head, tail} (inclusive).
|
||||
*/
|
||||
#define LEPP_CMD_LIMIT \
|
||||
(LEPP_CMD_QUEUE_BYTES - LEPP_MAX_CMD_SIZE)
|
||||
|
||||
/** The maximum number of completions in an LEPP queue. */
|
||||
#define LEPP_COMP_QUEUE_SIZE \
|
||||
((LEPP_CMD_LIMIT + sizeof(lepp_cmd_t) - 1) / sizeof(lepp_cmd_t))
|
||||
|
||||
/** Increment an index modulo the queue size. */
|
||||
#define LEPP_QINC(var) \
|
||||
(var = __insn_mnz(var - (LEPP_COMP_QUEUE_SIZE - 1), var + 1))
|
||||
|
||||
/** A queue used to convey egress commands from the client to LEPP. */
|
||||
typedef struct
|
||||
{
|
||||
/** Index of first completion not yet processed by user code.
|
||||
* If this is equal to comp_busy, there are no such completions.
|
||||
*
|
||||
* NOTE: This is only read/written by the user.
|
||||
*/
|
||||
unsigned int comp_head;
|
||||
|
||||
/** Index of first completion record not yet completed.
|
||||
* If this is equal to comp_tail, there are no such completions.
|
||||
* This index gets advanced (modulo LEPP_QUEUE_SIZE) whenever
|
||||
* a command with the 'completion' bit set is finished.
|
||||
*
|
||||
* NOTE: This is only written by LEPP, only read by the user.
|
||||
*/
|
||||
volatile unsigned int comp_busy;
|
||||
|
||||
/** Index of the first empty slot in the completion ring.
|
||||
* Entries from this up to but not including comp_head (in ring order)
|
||||
* can be filled in with completion data.
|
||||
*
|
||||
* NOTE: This is only read/written by the user.
|
||||
*/
|
||||
unsigned int comp_tail;
|
||||
|
||||
/** Byte index of first command enqueued for LEPP but not yet processed.
|
||||
*
|
||||
* This is always divisible by sizeof(void*) and always <= LEPP_CMD_LIMIT.
|
||||
*
|
||||
* NOTE: LEPP advances this counter as soon as it no longer needs
|
||||
* the cmds[] storage for this entry, but the transfer is not actually
|
||||
* complete (i.e. the buffer pointed to by the command is no longer
|
||||
* needed) until comp_busy advances.
|
||||
*
|
||||
* If this is equal to cmd_tail, the ring is empty.
|
||||
*
|
||||
* NOTE: This is only written by LEPP, only read by the user.
|
||||
*/
|
||||
volatile unsigned int cmd_head;
|
||||
|
||||
/** Byte index of first empty slot in the command ring. This field can
|
||||
* be incremented up to but not equal to cmd_head (because that would
|
||||
* mean the ring is empty).
|
||||
*
|
||||
* This is always divisible by sizeof(void*) and always <= LEPP_CMD_LIMIT.
|
||||
*
|
||||
* NOTE: This is read/written by the user, only read by LEPP.
|
||||
*/
|
||||
volatile unsigned int cmd_tail;
|
||||
|
||||
/** A ring of variable-sized egress DMA commands.
|
||||
*
|
||||
* NOTE: Only written by the user, only read by LEPP.
|
||||
*/
|
||||
char cmds[LEPP_CMD_QUEUE_BYTES]
|
||||
__attribute__((aligned(CHIP_L2_LINE_SIZE())));
|
||||
|
||||
/** A ring of user completion data.
|
||||
* NOTE: Only read/written by the user.
|
||||
*/
|
||||
lepp_comp_t comps[LEPP_COMP_QUEUE_SIZE]
|
||||
__attribute__((aligned(CHIP_L2_LINE_SIZE())));
|
||||
} lepp_queue_t;
|
||||
|
||||
|
||||
/** An internal helper function for determining the number of entries
|
||||
* available in a ring buffer, given that there is one sentinel.
|
||||
*/
|
||||
static inline unsigned int
|
||||
_lepp_num_free_slots(unsigned int head, unsigned int tail)
|
||||
{
|
||||
/*
|
||||
* One entry is reserved for use as a sentinel, to distinguish
|
||||
* "empty" from "full". So we compute
|
||||
* (head - tail - 1) % LEPP_QUEUE_SIZE, but without using a slow % operation.
|
||||
*/
|
||||
return (head - tail - 1) + ((head <= tail) ? LEPP_COMP_QUEUE_SIZE : 0);
|
||||
}
|
||||
|
||||
|
||||
/** Returns how many new comp entries can be enqueued. */
|
||||
static inline unsigned int
|
||||
lepp_num_free_comp_slots(const lepp_queue_t* q)
|
||||
{
|
||||
return _lepp_num_free_slots(q->comp_head, q->comp_tail);
|
||||
}
|
||||
|
||||
static inline int
|
||||
lepp_qsub(int v1, int v2)
|
||||
{
|
||||
int delta = v1 - v2;
|
||||
return delta + ((delta >> 31) & LEPP_COMP_QUEUE_SIZE);
|
||||
}
|
||||
|
||||
|
||||
/** FIXME: Check this from linux, via a new "pwrite()" call. */
|
||||
#define LIPP_VERSION 1
|
||||
|
||||
|
||||
/** We use exactly two bytes of alignment padding. */
|
||||
#define LIPP_PACKET_PADDING 2
|
||||
|
||||
/** The minimum size of a "small" buffer (including the padding). */
|
||||
#define LIPP_SMALL_PACKET_SIZE 128
|
||||
|
||||
/*
|
||||
* NOTE: The following two values should total to less than around
|
||||
* 13582, to keep the total size used for "lipp_state_t" below 64K.
|
||||
*/
|
||||
|
||||
/** The maximum number of "small" buffers.
|
||||
* This is enough for 53 network cpus with 128 credits. Note that
|
||||
* if these are exhausted, we will fall back to using large buffers.
|
||||
*/
|
||||
#define LIPP_SMALL_BUFFERS 6785
|
||||
|
||||
/** The maximum number of "large" buffers.
|
||||
* This is enough for 53 network cpus with 128 credits.
|
||||
*/
|
||||
#define LIPP_LARGE_BUFFERS 6785
|
||||
|
||||
#endif /* __DRV_XGBE_INTF_H__ */
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Error codes returned from NetIO routines.
|
||||
*/
|
||||
|
||||
#ifndef __NETIO_ERRORS_H__
|
||||
#define __NETIO_ERRORS_H__
|
||||
|
||||
/**
|
||||
* @addtogroup error
|
||||
*
|
||||
* @brief The error codes returned by NetIO functions.
|
||||
*
|
||||
* NetIO functions return 0 (defined as ::NETIO_NO_ERROR) on success, and
|
||||
* a negative value if an error occurs.
|
||||
*
|
||||
* In cases where a NetIO function failed due to a error reported by
|
||||
* system libraries, the error code will be the negation of the
|
||||
* system errno at the time of failure. The @ref netio_strerror()
|
||||
* function will deliver error strings for both NetIO and system error
|
||||
* codes.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** The set of all NetIO errors. */
|
||||
typedef enum
|
||||
{
|
||||
/** Operation successfully completed. */
|
||||
NETIO_NO_ERROR = 0,
|
||||
|
||||
/** A packet was successfully retrieved from an input queue. */
|
||||
NETIO_PKT = 0,
|
||||
|
||||
/** Largest NetIO error number. */
|
||||
NETIO_ERR_MAX = -701,
|
||||
|
||||
/** The tile is not registered with the IPP. */
|
||||
NETIO_NOT_REGISTERED = -701,
|
||||
|
||||
/** No packet was available to retrieve from the input queue. */
|
||||
NETIO_NOPKT = -702,
|
||||
|
||||
/** The requested function is not implemented. */
|
||||
NETIO_NOT_IMPLEMENTED = -703,
|
||||
|
||||
/** On a registration operation, the target queue already has the maximum
|
||||
* number of tiles registered for it, and no more may be added. On a
|
||||
* packet send operation, the output queue is full and nothing more can
|
||||
* be queued until some of the queued packets are actually transmitted. */
|
||||
NETIO_QUEUE_FULL = -704,
|
||||
|
||||
/** The calling process or thread is not bound to exactly one CPU. */
|
||||
NETIO_BAD_AFFINITY = -705,
|
||||
|
||||
/** Cannot allocate memory on requested controllers. */
|
||||
NETIO_CANNOT_HOME = -706,
|
||||
|
||||
/** On a registration operation, the IPP specified is not configured
|
||||
* to support the options requested; for instance, the application
|
||||
* wants a specific type of tagged headers which the configured IPP
|
||||
* doesn't support. Or, the supplied configuration information is
|
||||
* not self-consistent, or is out of range; for instance, specifying
|
||||
* both NETIO_RECV and NETIO_NO_RECV, or asking for more than
|
||||
* NETIO_MAX_SEND_BUFFERS to be preallocated. On a VLAN or bucket
|
||||
* configure operation, the number of items, or the base item, was
|
||||
* out of range.
|
||||
*/
|
||||
NETIO_BAD_CONFIG = -707,
|
||||
|
||||
/** Too many tiles have registered to transmit packets. */
|
||||
NETIO_TOOMANY_XMIT = -708,
|
||||
|
||||
/** Packet transmission was attempted on a queue which was registered
|
||||
with transmit disabled. */
|
||||
NETIO_UNREG_XMIT = -709,
|
||||
|
||||
/** This tile is already registered with the IPP. */
|
||||
NETIO_ALREADY_REGISTERED = -710,
|
||||
|
||||
/** The Ethernet link is down. The application should try again later. */
|
||||
NETIO_LINK_DOWN = -711,
|
||||
|
||||
/** An invalid memory buffer has been specified. This may be an unmapped
|
||||
* virtual address, or one which does not meet alignment requirements.
|
||||
* For netio_input_register(), this error may be returned when multiple
|
||||
* processes specify different memory regions to be used for NetIO
|
||||
* buffers. That can happen if these processes specify explicit memory
|
||||
* regions with the ::NETIO_FIXED_BUFFER_VA flag, or if tmc_cmem_init()
|
||||
* has not been called by a common ancestor of the processes.
|
||||
*/
|
||||
NETIO_FAULT = -712,
|
||||
|
||||
/** Cannot combine user-managed shared memory and cache coherence. */
|
||||
NETIO_BAD_CACHE_CONFIG = -713,
|
||||
|
||||
/** Smallest NetIO error number. */
|
||||
NETIO_ERR_MIN = -713,
|
||||
|
||||
#ifndef __DOXYGEN__
|
||||
/** Used internally to mean that no response is needed; never returned to
|
||||
* an application. */
|
||||
NETIO_NO_RESPONSE = 1
|
||||
#endif
|
||||
} netio_error_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* __NETIO_ERRORS_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -15,3 +15,4 @@ obj-$(CONFIG_SMP) += smpboot.o smp.o tlb.o
|
|||
obj-$(CONFIG_MODULES) += module.o
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
|
|
|
@ -0,0 +1,621 @@
|
|||
/*
|
||||
* Copyright 2010 Tilera Corporation. All Rights Reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation, version 2.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
|
||||
* NON INFRINGEMENT. See the GNU General Public License for
|
||||
* more details.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/capability.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <asm/processor.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/hv_driver.h>
|
||||
#include <hv/drv_pcie_rc_intf.h>
|
||||
|
||||
|
||||
/*
|
||||
* Initialization flow and process
|
||||
* -------------------------------
|
||||
*
|
||||
* This files containes the routines to search for PCI buses,
|
||||
* enumerate the buses, and configure any attached devices.
|
||||
*
|
||||
* There are two entry points here:
|
||||
* 1) tile_pci_init
|
||||
* This sets up the pci_controller structs, and opens the
|
||||
* FDs to the hypervisor. This is called from setup_arch() early
|
||||
* in the boot process.
|
||||
* 2) pcibios_init
|
||||
* This probes the PCI bus(es) for any attached hardware. It's
|
||||
* called by subsys_initcall. All of the real work is done by the
|
||||
* generic Linux PCI layer.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This flag tells if the platform is TILEmpower that needs
|
||||
* special configuration for the PLX switch chip.
|
||||
*/
|
||||
int __write_once tile_plx_gen1;
|
||||
|
||||
static struct pci_controller controllers[TILE_NUM_PCIE];
|
||||
static int num_controllers;
|
||||
|
||||
static struct pci_ops tile_cfg_ops;
|
||||
|
||||
|
||||
/*
|
||||
* We don't need to worry about the alignment of resources.
|
||||
*/
|
||||
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
|
||||
resource_size_t size, resource_size_t align)
|
||||
{
|
||||
return res->start;
|
||||
}
|
||||
EXPORT_SYMBOL(pcibios_align_resource);
|
||||
|
||||
/*
|
||||
* Open a FD to the hypervisor PCI device.
|
||||
*
|
||||
* controller_id is the controller number, config type is 0 or 1 for
|
||||
* config0 or config1 operations.
|
||||
*/
|
||||
static int __init tile_pcie_open(int controller_id, int config_type)
|
||||
{
|
||||
char filename[32];
|
||||
int fd;
|
||||
|
||||
sprintf(filename, "pcie/%d/config%d", controller_id, config_type);
|
||||
|
||||
fd = hv_dev_open((HV_VirtAddr)filename, 0);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Get the IRQ numbers from the HV and set up the handlers for them.
|
||||
*/
|
||||
static int __init tile_init_irqs(int controller_id,
|
||||
struct pci_controller *controller)
|
||||
{
|
||||
char filename[32];
|
||||
int fd;
|
||||
int ret;
|
||||
int x;
|
||||
struct pcie_rc_config rc_config;
|
||||
|
||||
sprintf(filename, "pcie/%d/ctl", controller_id);
|
||||
fd = hv_dev_open((HV_VirtAddr)filename, 0);
|
||||
if (fd < 0) {
|
||||
pr_err("PCI: hv_dev_open(%s) failed\n", filename);
|
||||
return -1;
|
||||
}
|
||||
ret = hv_dev_pread(fd, 0, (HV_VirtAddr)(&rc_config),
|
||||
sizeof(rc_config), PCIE_RC_CONFIG_MASK_OFF);
|
||||
hv_dev_close(fd);
|
||||
if (ret != sizeof(rc_config)) {
|
||||
pr_err("PCI: wanted %zd bytes, got %d\n",
|
||||
sizeof(rc_config), ret);
|
||||
return -1;
|
||||
}
|
||||
/* Record irq_base so that we can map INTx to IRQ # later. */
|
||||
controller->irq_base = rc_config.intr;
|
||||
|
||||
for (x = 0; x < 4; x++)
|
||||
tile_irq_activate(rc_config.intr + x,
|
||||
TILE_IRQ_HW_CLEAR);
|
||||
|
||||
if (rc_config.plx_gen1)
|
||||
controller->plx_gen1 = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* First initialization entry point, called from setup_arch().
|
||||
*
|
||||
* Find valid controllers and fill in pci_controller structs for each
|
||||
* of them.
|
||||
*
|
||||
* Returns the number of controllers discovered.
|
||||
*/
|
||||
int __init tile_pci_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
pr_info("PCI: Searching for controllers...\n");
|
||||
|
||||
/* Do any configuration we need before using the PCIe */
|
||||
|
||||
for (i = 0; i < TILE_NUM_PCIE; i++) {
|
||||
int hv_cfg_fd0 = -1;
|
||||
int hv_cfg_fd1 = -1;
|
||||
int hv_mem_fd = -1;
|
||||
char name[32];
|
||||
struct pci_controller *controller;
|
||||
|
||||
/*
|
||||
* Open the fd to the HV. If it fails then this
|
||||
* device doesn't exist.
|
||||
*/
|
||||
hv_cfg_fd0 = tile_pcie_open(i, 0);
|
||||
if (hv_cfg_fd0 < 0)
|
||||
continue;
|
||||
hv_cfg_fd1 = tile_pcie_open(i, 1);
|
||||
if (hv_cfg_fd1 < 0) {
|
||||
pr_err("PCI: Couldn't open config fd to HV "
|
||||
"for controller %d\n", i);
|
||||
goto err_cont;
|
||||
}
|
||||
|
||||
sprintf(name, "pcie/%d/mem", i);
|
||||
hv_mem_fd = hv_dev_open((HV_VirtAddr)name, 0);
|
||||
if (hv_mem_fd < 0) {
|
||||
pr_err("PCI: Could not open mem fd to HV!\n");
|
||||
goto err_cont;
|
||||
}
|
||||
|
||||
pr_info("PCI: Found PCI controller #%d\n", i);
|
||||
|
||||
controller = &controllers[num_controllers];
|
||||
|
||||
if (tile_init_irqs(i, controller)) {
|
||||
pr_err("PCI: Could not initialize "
|
||||
"IRQs, aborting.\n");
|
||||
goto err_cont;
|
||||
}
|
||||
|
||||
controller->index = num_controllers;
|
||||
controller->hv_cfg_fd[0] = hv_cfg_fd0;
|
||||
controller->hv_cfg_fd[1] = hv_cfg_fd1;
|
||||
controller->hv_mem_fd = hv_mem_fd;
|
||||
controller->first_busno = 0;
|
||||
controller->last_busno = 0xff;
|
||||
controller->ops = &tile_cfg_ops;
|
||||
|
||||
num_controllers++;
|
||||
continue;
|
||||
|
||||
err_cont:
|
||||
if (hv_cfg_fd0 >= 0)
|
||||
hv_dev_close(hv_cfg_fd0);
|
||||
if (hv_cfg_fd1 >= 0)
|
||||
hv_dev_close(hv_cfg_fd1);
|
||||
if (hv_mem_fd >= 0)
|
||||
hv_dev_close(hv_mem_fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Before using the PCIe, see if we need to do any platform-specific
|
||||
* configuration, such as the PLX switch Gen 1 issue on TILEmpower.
|
||||
*/
|
||||
for (i = 0; i < num_controllers; i++) {
|
||||
struct pci_controller *controller = &controllers[i];
|
||||
|
||||
if (controller->plx_gen1)
|
||||
tile_plx_gen1 = 1;
|
||||
}
|
||||
|
||||
return num_controllers;
|
||||
}
|
||||
|
||||
/*
|
||||
* (pin - 1) converts from the PCI standard's [1:4] convention to
|
||||
* a normal [0:3] range.
|
||||
*/
|
||||
static int tile_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
|
||||
{
|
||||
struct pci_controller *controller =
|
||||
(struct pci_controller *)dev->sysdata;
|
||||
return (pin - 1) + controller->irq_base;
|
||||
}
|
||||
|
||||
|
||||
static void __init fixup_read_and_payload_sizes(void)
|
||||
{
|
||||
struct pci_dev *dev = NULL;
|
||||
int smallest_max_payload = 0x1; /* Tile maxes out at 256 bytes. */
|
||||
int max_read_size = 0x2; /* Limit to 512 byte reads. */
|
||||
u16 new_values;
|
||||
|
||||
/* Scan for the smallest maximum payload size. */
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
int pcie_caps_offset;
|
||||
u32 devcap;
|
||||
int max_payload;
|
||||
|
||||
pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
|
||||
if (pcie_caps_offset == 0)
|
||||
continue;
|
||||
|
||||
pci_read_config_dword(dev, pcie_caps_offset + PCI_EXP_DEVCAP,
|
||||
&devcap);
|
||||
max_payload = devcap & PCI_EXP_DEVCAP_PAYLOAD;
|
||||
if (max_payload < smallest_max_payload)
|
||||
smallest_max_payload = max_payload;
|
||||
}
|
||||
|
||||
/* Now, set the max_payload_size for all devices to that value. */
|
||||
new_values = (max_read_size << 12) | (smallest_max_payload << 5);
|
||||
while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
|
||||
int pcie_caps_offset;
|
||||
u16 devctl;
|
||||
|
||||
pcie_caps_offset = pci_find_capability(dev, PCI_CAP_ID_EXP);
|
||||
if (pcie_caps_offset == 0)
|
||||
continue;
|
||||
|
||||
pci_read_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
|
||||
&devctl);
|
||||
devctl &= ~(PCI_EXP_DEVCTL_PAYLOAD | PCI_EXP_DEVCTL_READRQ);
|
||||
devctl |= new_values;
|
||||
pci_write_config_word(dev, pcie_caps_offset + PCI_EXP_DEVCTL,
|
||||
devctl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Second PCI initialization entry point, called by subsys_initcall.
|
||||
*
|
||||
* The controllers have been set up by the time we get here, by a call to
|
||||
* tile_pci_init.
|
||||
*/
|
||||
static int __init pcibios_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
pr_info("PCI: Probing PCI hardware\n");
|
||||
|
||||
/*
|
||||
* Delay a bit in case devices aren't ready. Some devices are
|
||||
* known to require at least 20ms here, but we use a more
|
||||
* conservative value.
|
||||
*/
|
||||
mdelay(250);
|
||||
|
||||
/* Scan all of the recorded PCI controllers. */
|
||||
for (i = 0; i < num_controllers; i++) {
|
||||
struct pci_controller *controller = &controllers[i];
|
||||
struct pci_bus *bus;
|
||||
|
||||
pr_info("PCI: initializing controller #%d\n", i);
|
||||
|
||||
/*
|
||||
* This comes from the generic Linux PCI driver.
|
||||
*
|
||||
* It reads the PCI tree for this bus into the Linux
|
||||
* data structures.
|
||||
*
|
||||
* This is inlined in linux/pci.h and calls into
|
||||
* pci_scan_bus_parented() in probe.c.
|
||||
*/
|
||||
bus = pci_scan_bus(0, controller->ops, controller);
|
||||
controller->root_bus = bus;
|
||||
controller->last_busno = bus->subordinate;
|
||||
|
||||
}
|
||||
|
||||
/* Do machine dependent PCI interrupt routing */
|
||||
pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
|
||||
|
||||
/*
|
||||
* This comes from the generic Linux PCI driver.
|
||||
*
|
||||
* It allocates all of the resources (I/O memory, etc)
|
||||
* associated with the devices read in above.
|
||||
*/
|
||||
|
||||
pci_assign_unassigned_resources();
|
||||
|
||||
/* Configure the max_read_size and max_payload_size values. */
|
||||
fixup_read_and_payload_sizes();
|
||||
|
||||
/* Record the I/O resources in the PCI controller structure. */
|
||||
for (i = 0; i < num_controllers; i++) {
|
||||
struct pci_bus *root_bus = controllers[i].root_bus;
|
||||
struct pci_bus *next_bus;
|
||||
struct pci_dev *dev;
|
||||
|
||||
list_for_each_entry(dev, &root_bus->devices, bus_list) {
|
||||
/* Find the PCI host controller, ie. the 1st bridge. */
|
||||
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
|
||||
(PCI_SLOT(dev->devfn) == 0)) {
|
||||
next_bus = dev->subordinate;
|
||||
controllers[i].mem_resources[0] =
|
||||
*next_bus->resource[0];
|
||||
controllers[i].mem_resources[1] =
|
||||
*next_bus->resource[1];
|
||||
controllers[i].mem_resources[2] =
|
||||
*next_bus->resource[2];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(pcibios_init);
|
||||
|
||||
/*
|
||||
* No bus fixups needed.
|
||||
*/
|
||||
void __devinit pcibios_fixup_bus(struct pci_bus *bus)
|
||||
{
|
||||
/* Nothing needs to be done. */
|
||||
}
|
||||
|
||||
/*
|
||||
* This can be called from the generic PCI layer, but doesn't need to
|
||||
* do anything.
|
||||
*/
|
||||
char __devinit *pcibios_setup(char *str)
|
||||
{
|
||||
/* Nothing needs to be done. */
|
||||
return str;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is called from the generic Linux layer.
|
||||
*/
|
||||
void __init pcibios_update_irq(struct pci_dev *dev, int irq)
|
||||
{
|
||||
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable memory and/or address decoding, as appropriate, for the
|
||||
* device described by the 'dev' struct.
|
||||
*
|
||||
* This is called from the generic PCI layer, and can be called
|
||||
* for bridges or endpoints.
|
||||
*/
|
||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
{
|
||||
u16 cmd, old_cmd;
|
||||
u8 header_type;
|
||||
int i;
|
||||
struct resource *r;
|
||||
|
||||
pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type);
|
||||
|
||||
pci_read_config_word(dev, PCI_COMMAND, &cmd);
|
||||
old_cmd = cmd;
|
||||
if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
|
||||
/*
|
||||
* For bridges, we enable both memory and I/O decoding
|
||||
* in call cases.
|
||||
*/
|
||||
cmd |= PCI_COMMAND_IO;
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
} else {
|
||||
/*
|
||||
* For endpoints, we enable memory and/or I/O decoding
|
||||
* only if they have a memory resource of that type.
|
||||
*/
|
||||
for (i = 0; i < 6; i++) {
|
||||
r = &dev->resource[i];
|
||||
if (r->flags & IORESOURCE_UNSET) {
|
||||
pr_err("PCI: Device %s not available "
|
||||
"because of resource collisions\n",
|
||||
pci_name(dev));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (r->flags & IORESOURCE_IO)
|
||||
cmd |= PCI_COMMAND_IO;
|
||||
if (r->flags & IORESOURCE_MEM)
|
||||
cmd |= PCI_COMMAND_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We only write the command if it changed.
|
||||
*/
|
||||
if (cmd != old_cmd)
|
||||
pci_write_config_word(dev, PCI_COMMAND, cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
|
||||
{
|
||||
unsigned long start = pci_resource_start(dev, bar);
|
||||
unsigned long len = pci_resource_len(dev, bar);
|
||||
unsigned long flags = pci_resource_flags(dev, bar);
|
||||
|
||||
if (!len)
|
||||
return NULL;
|
||||
if (max && len > max)
|
||||
len = max;
|
||||
|
||||
if (!(flags & IORESOURCE_MEM)) {
|
||||
pr_info("PCI: Trying to map invalid resource %#lx\n", flags);
|
||||
start = 0;
|
||||
}
|
||||
|
||||
return (void __iomem *)start;
|
||||
}
|
||||
EXPORT_SYMBOL(pci_iomap);
|
||||
|
||||
|
||||
/****************************************************************
|
||||
*
|
||||
* Tile PCI config space read/write routines
|
||||
*
|
||||
****************************************************************/
|
||||
|
||||
/*
|
||||
* These are the normal read and write ops
|
||||
* These are expanded with macros from pci_bus_read_config_byte() etc.
|
||||
*
|
||||
* devfn is the combined PCI slot & function.
|
||||
*
|
||||
* offset is in bytes, from the start of config space for the
|
||||
* specified bus & slot.
|
||||
*/
|
||||
|
||||
static int __devinit tile_cfg_read(struct pci_bus *bus,
|
||||
unsigned int devfn,
|
||||
int offset,
|
||||
int size,
|
||||
u32 *val)
|
||||
{
|
||||
struct pci_controller *controller = bus->sysdata;
|
||||
int busnum = bus->number & 0xff;
|
||||
int slot = (devfn >> 3) & 0x1f;
|
||||
int function = devfn & 0x7;
|
||||
u32 addr;
|
||||
int config_mode = 1;
|
||||
|
||||
/*
|
||||
* There is no bridge between the Tile and bus 0, so we
|
||||
* use config0 to talk to bus 0.
|
||||
*
|
||||
* If we're talking to a bus other than zero then we
|
||||
* must have found a bridge.
|
||||
*/
|
||||
if (busnum == 0) {
|
||||
/*
|
||||
* We fake an empty slot for (busnum == 0) && (slot > 0),
|
||||
* since there is only one slot on bus 0.
|
||||
*/
|
||||
if (slot) {
|
||||
*val = 0xFFFFFFFF;
|
||||
return 0;
|
||||
}
|
||||
config_mode = 0;
|
||||
}
|
||||
|
||||
addr = busnum << 20; /* Bus in 27:20 */
|
||||
addr |= slot << 15; /* Slot (device) in 19:15 */
|
||||
addr |= function << 12; /* Function is in 14:12 */
|
||||
addr |= (offset & 0xFFF); /* byte address in 0:11 */
|
||||
|
||||
return hv_dev_pread(controller->hv_cfg_fd[config_mode], 0,
|
||||
(HV_VirtAddr)(val), size, addr);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* See tile_cfg_read() for relevent comments.
|
||||
* Note that "val" is the value to write, not a pointer to that value.
|
||||
*/
|
||||
static int __devinit tile_cfg_write(struct pci_bus *bus,
|
||||
unsigned int devfn,
|
||||
int offset,
|
||||
int size,
|
||||
u32 val)
|
||||
{
|
||||
struct pci_controller *controller = bus->sysdata;
|
||||
int busnum = bus->number & 0xff;
|
||||
int slot = (devfn >> 3) & 0x1f;
|
||||
int function = devfn & 0x7;
|
||||
u32 addr;
|
||||
int config_mode = 1;
|
||||
HV_VirtAddr valp = (HV_VirtAddr)&val;
|
||||
|
||||
/*
|
||||
* For bus 0 slot 0 we use config 0 accesses.
|
||||
*/
|
||||
if (busnum == 0) {
|
||||
/*
|
||||
* We fake an empty slot for (busnum == 0) && (slot > 0),
|
||||
* since there is only one slot on bus 0.
|
||||
*/
|
||||
if (slot)
|
||||
return 0;
|
||||
config_mode = 0;
|
||||
}
|
||||
|
||||
addr = busnum << 20; /* Bus in 27:20 */
|
||||
addr |= slot << 15; /* Slot (device) in 19:15 */
|
||||
addr |= function << 12; /* Function is in 14:12 */
|
||||
addr |= (offset & 0xFFF); /* byte address in 0:11 */
|
||||
|
||||
#ifdef __BIG_ENDIAN
|
||||
/* Point to the correct part of the 32-bit "val". */
|
||||
valp += 4 - size;
|
||||
#endif
|
||||
|
||||
return hv_dev_pwrite(controller->hv_cfg_fd[config_mode], 0,
|
||||
valp, size, addr);
|
||||
}
|
||||
|
||||
|
||||
static struct pci_ops tile_cfg_ops = {
|
||||
.read = tile_cfg_read,
|
||||
.write = tile_cfg_write,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* In the following, each PCI controller's mem_resources[1]
|
||||
* represents its (non-prefetchable) PCI memory resource.
|
||||
* mem_resources[0] and mem_resources[2] refer to its PCI I/O and
|
||||
* prefetchable PCI memory resources, respectively.
|
||||
* For more details, see pci_setup_bridge() in setup-bus.c.
|
||||
* By comparing the target PCI memory address against the
|
||||
* end address of controller 0, we can determine the controller
|
||||
* that should accept the PCI memory access.
|
||||
*/
|
||||
#define TILE_READ(size, type) \
|
||||
type _tile_read##size(unsigned long addr) \
|
||||
{ \
|
||||
type val; \
|
||||
int idx = 0; \
|
||||
if (addr > controllers[0].mem_resources[1].end && \
|
||||
addr > controllers[0].mem_resources[2].end) \
|
||||
idx = 1; \
|
||||
if (hv_dev_pread(controllers[idx].hv_mem_fd, 0, \
|
||||
(HV_VirtAddr)(&val), sizeof(type), addr)) \
|
||||
pr_err("PCI: read %zd bytes at 0x%lX failed\n", \
|
||||
sizeof(type), addr); \
|
||||
return val; \
|
||||
} \
|
||||
EXPORT_SYMBOL(_tile_read##size)
|
||||
|
||||
TILE_READ(b, u8);
|
||||
TILE_READ(w, u16);
|
||||
TILE_READ(l, u32);
|
||||
TILE_READ(q, u64);
|
||||
|
||||
#define TILE_WRITE(size, type) \
|
||||
void _tile_write##size(type val, unsigned long addr) \
|
||||
{ \
|
||||
int idx = 0; \
|
||||
if (addr > controllers[0].mem_resources[1].end && \
|
||||
addr > controllers[0].mem_resources[2].end) \
|
||||
idx = 1; \
|
||||
if (hv_dev_pwrite(controllers[idx].hv_mem_fd, 0, \
|
||||
(HV_VirtAddr)(&val), sizeof(type), addr)) \
|
||||
pr_err("PCI: write %zd bytes at 0x%lX failed\n", \
|
||||
sizeof(type), addr); \
|
||||
} \
|
||||
EXPORT_SYMBOL(_tile_write##size)
|
||||
|
||||
TILE_WRITE(b, u8);
|
||||
TILE_WRITE(w, u16);
|
||||
TILE_WRITE(l, u32);
|
||||
TILE_WRITE(q, u64);
|
|
@ -840,7 +840,7 @@ static int __init topology_init(void)
|
|||
for_each_online_node(i)
|
||||
register_one_node(i);
|
||||
|
||||
for_each_present_cpu(i)
|
||||
for (i = 0; i < smp_height * smp_width; ++i)
|
||||
register_cpu(&cpu_devices[i], i);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -18,12 +18,24 @@
|
|||
|
||||
void *memchr(const void *s, int c, size_t n)
|
||||
{
|
||||
const uint32_t *last_word_ptr;
|
||||
const uint32_t *p;
|
||||
const char *last_byte_ptr;
|
||||
uintptr_t s_int;
|
||||
uint32_t goal, before_mask, v, bits;
|
||||
char *ret;
|
||||
|
||||
if (__builtin_expect(n == 0, 0)) {
|
||||
/* Don't dereference any memory if the array is empty. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get an aligned pointer. */
|
||||
const uintptr_t s_int = (uintptr_t) s;
|
||||
const uint32_t *p = (const uint32_t *)(s_int & -4);
|
||||
s_int = (uintptr_t) s;
|
||||
p = (const uint32_t *)(s_int & -4);
|
||||
|
||||
/* Create four copies of the byte for which we are looking. */
|
||||
const uint32_t goal = 0x01010101 * (uint8_t) c;
|
||||
goal = 0x01010101 * (uint8_t) c;
|
||||
|
||||
/* Read the first word, but munge it so that bytes before the array
|
||||
* will not match goal.
|
||||
|
@ -31,23 +43,14 @@ void *memchr(const void *s, int c, size_t n)
|
|||
* Note that this shift count expression works because we know
|
||||
* shift counts are taken mod 32.
|
||||
*/
|
||||
const uint32_t before_mask = (1 << (s_int << 3)) - 1;
|
||||
uint32_t v = (*p | before_mask) ^ (goal & before_mask);
|
||||
before_mask = (1 << (s_int << 3)) - 1;
|
||||
v = (*p | before_mask) ^ (goal & before_mask);
|
||||
|
||||
/* Compute the address of the last byte. */
|
||||
const char *const last_byte_ptr = (const char *)s + n - 1;
|
||||
last_byte_ptr = (const char *)s + n - 1;
|
||||
|
||||
/* Compute the address of the word containing the last byte. */
|
||||
const uint32_t *const last_word_ptr =
|
||||
(const uint32_t *)((uintptr_t) last_byte_ptr & -4);
|
||||
|
||||
uint32_t bits;
|
||||
char *ret;
|
||||
|
||||
if (__builtin_expect(n == 0, 0)) {
|
||||
/* Don't dereference any memory if the array is empty. */
|
||||
return NULL;
|
||||
}
|
||||
last_word_ptr = (const uint32_t *)((uintptr_t) last_byte_ptr & -4);
|
||||
|
||||
while ((bits = __insn_seqb(v, goal)) == 0) {
|
||||
if (__builtin_expect(p == last_word_ptr, 0)) {
|
||||
|
|
|
@ -167,23 +167,30 @@ void arch_write_lock_slow(arch_rwlock_t *rwlock, u32 val)
|
|||
* when we compare them.
|
||||
*/
|
||||
u32 my_ticket_;
|
||||
|
||||
/* Take out the next ticket; this will also stop would-be readers. */
|
||||
if (val & 1)
|
||||
val = get_rwlock(rwlock);
|
||||
rwlock->lock = __insn_addb(val, 1 << WR_NEXT_SHIFT);
|
||||
|
||||
/* Extract my ticket value from the original word. */
|
||||
my_ticket_ = val >> WR_NEXT_SHIFT;
|
||||
u32 iterations = 0;
|
||||
|
||||
/*
|
||||
* Wait until the "current" field matches our ticket, and
|
||||
* there are no remaining readers.
|
||||
* Wait until there are no readers, then bump up the next
|
||||
* field and capture the ticket value.
|
||||
*/
|
||||
for (;;) {
|
||||
if (!(val & 1)) {
|
||||
if ((val >> RD_COUNT_SHIFT) == 0)
|
||||
break;
|
||||
rwlock->lock = val;
|
||||
}
|
||||
delay_backoff(iterations++);
|
||||
val = __insn_tns((int *)&rwlock->lock);
|
||||
}
|
||||
|
||||
/* Take out the next ticket and extract my ticket value. */
|
||||
rwlock->lock = __insn_addb(val, 1 << WR_NEXT_SHIFT);
|
||||
my_ticket_ = val >> WR_NEXT_SHIFT;
|
||||
|
||||
/* Wait until the "current" field matches our ticket. */
|
||||
for (;;) {
|
||||
u32 curr_ = val >> WR_CURR_SHIFT;
|
||||
u32 readers = val >> RD_COUNT_SHIFT;
|
||||
u32 delta = ((my_ticket_ - curr_) & WR_MASK) + !!readers;
|
||||
u32 delta = ((my_ticket_ - curr_) & WR_MASK);
|
||||
if (likely(delta == 0))
|
||||
break;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ config X86
|
|||
select HAVE_UNSTABLE_SCHED_CLOCK
|
||||
select HAVE_IDE
|
||||
select HAVE_OPROFILE
|
||||
select HAVE_PERF_EVENTS if (!M386 && !M486)
|
||||
select HAVE_PERF_EVENTS
|
||||
select HAVE_IRQ_WORK
|
||||
select HAVE_IOREMAP_PROT
|
||||
select HAVE_KPROBES
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
#define FAM10H_MMIO_CONF_ENABLE (1<<0)
|
||||
#define FAM10H_MMIO_CONF_BUSRANGE_MASK 0xf
|
||||
#define FAM10H_MMIO_CONF_BUSRANGE_SHIFT 2
|
||||
#define FAM10H_MMIO_CONF_BASE_MASK 0xfffffff
|
||||
#define FAM10H_MMIO_CONF_BASE_MASK 0xfffffffULL
|
||||
#define FAM10H_MMIO_CONF_BASE_SHIFT 20
|
||||
#define MSR_FAM10H_NODE_ID 0xc001100c
|
||||
|
||||
|
|
|
@ -824,27 +824,27 @@ static __always_inline void arch_spin_unlock(struct arch_spinlock *lock)
|
|||
#define __PV_IS_CALLEE_SAVE(func) \
|
||||
((struct paravirt_callee_save) { func })
|
||||
|
||||
static inline unsigned long arch_local_save_flags(void)
|
||||
static inline notrace unsigned long arch_local_save_flags(void)
|
||||
{
|
||||
return PVOP_CALLEE0(unsigned long, pv_irq_ops.save_fl);
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_restore(unsigned long f)
|
||||
static inline notrace void arch_local_irq_restore(unsigned long f)
|
||||
{
|
||||
PVOP_VCALLEE1(pv_irq_ops.restore_fl, f);
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_disable(void)
|
||||
static inline notrace void arch_local_irq_disable(void)
|
||||
{
|
||||
PVOP_VCALLEE0(pv_irq_ops.irq_disable);
|
||||
}
|
||||
|
||||
static inline void arch_local_irq_enable(void)
|
||||
static inline notrace void arch_local_irq_enable(void)
|
||||
{
|
||||
PVOP_VCALLEE0(pv_irq_ops.irq_enable);
|
||||
}
|
||||
|
||||
static inline unsigned long arch_local_irq_save(void)
|
||||
static inline notrace unsigned long arch_local_irq_save(void)
|
||||
{
|
||||
unsigned long f;
|
||||
|
||||
|
|
|
@ -199,6 +199,8 @@ union uvh_apicid {
|
|||
#define UVH_APICID 0x002D0E00L
|
||||
#define UV_APIC_PNODE_SHIFT 6
|
||||
|
||||
#define UV_APICID_HIBIT_MASK 0xffff0000
|
||||
|
||||
/* Local Bus from cpu's perspective */
|
||||
#define LOCAL_BUS_BASE 0x1c00000
|
||||
#define LOCAL_BUS_SIZE (4 * 1024 * 1024)
|
||||
|
@ -491,8 +493,10 @@ static inline void uv_set_cpu_scir_bits(int cpu, unsigned char value)
|
|||
}
|
||||
}
|
||||
|
||||
extern unsigned int uv_apicid_hibits;
|
||||
static unsigned long uv_hub_ipi_value(int apicid, int vector, int mode)
|
||||
{
|
||||
apicid |= uv_apicid_hibits;
|
||||
return (1UL << UVH_IPI_INT_SEND_SHFT) |
|
||||
((apicid) << UVH_IPI_INT_APIC_ID_SHFT) |
|
||||
(mode << UVH_IPI_INT_DELIVERY_MODE_SHFT) |
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* SGI UV MMR definitions
|
||||
*
|
||||
* Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved.
|
||||
* Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _ASM_X86_UV_UV_MMRS_H
|
||||
|
@ -753,6 +753,23 @@ union uvh_lb_bau_sb_descriptor_base_u {
|
|||
} s;
|
||||
};
|
||||
|
||||
/* ========================================================================= */
|
||||
/* UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK */
|
||||
/* ========================================================================= */
|
||||
#define UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK 0x320130UL
|
||||
#define UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK_32 0x009f0
|
||||
|
||||
#define UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK_BIT_ENABLES_SHFT 0
|
||||
#define UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK_BIT_ENABLES_MASK 0x00000000ffffffffUL
|
||||
|
||||
union uvh_lb_target_physical_apic_id_mask_u {
|
||||
unsigned long v;
|
||||
struct uvh_lb_target_physical_apic_id_mask_s {
|
||||
unsigned long bit_enables : 32; /* RW */
|
||||
unsigned long rsvd_32_63 : 32; /* */
|
||||
} s;
|
||||
};
|
||||
|
||||
/* ========================================================================= */
|
||||
/* UVH_NODE_ID */
|
||||
/* ========================================================================= */
|
||||
|
|
|
@ -17,15 +17,16 @@
|
|||
#include <linux/nmi.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/* For reliability, we're prepared to waste bits here. */
|
||||
static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly;
|
||||
|
||||
u64 hw_nmi_get_sample_period(void)
|
||||
{
|
||||
return (u64)(cpu_khz) * 1000 * 60;
|
||||
}
|
||||
|
||||
#ifdef ARCH_HAS_NMI_WATCHDOG
|
||||
|
||||
/* For reliability, we're prepared to waste bits here. */
|
||||
static DECLARE_BITMAP(backtrace_mask, NR_CPUS) __read_mostly;
|
||||
|
||||
void arch_trigger_all_cpu_backtrace(void)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -44,6 +44,8 @@ static u64 gru_start_paddr, gru_end_paddr;
|
|||
static union uvh_apicid uvh_apicid;
|
||||
int uv_min_hub_revision_id;
|
||||
EXPORT_SYMBOL_GPL(uv_min_hub_revision_id);
|
||||
unsigned int uv_apicid_hibits;
|
||||
EXPORT_SYMBOL_GPL(uv_apicid_hibits);
|
||||
static DEFINE_SPINLOCK(uv_nmi_lock);
|
||||
|
||||
static inline bool is_GRU_range(u64 start, u64 end)
|
||||
|
@ -85,6 +87,23 @@ static void __init early_get_apic_pnode_shift(void)
|
|||
uvh_apicid.s.pnode_shift = UV_APIC_PNODE_SHIFT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add an extra bit as dictated by bios to the destination apicid of
|
||||
* interrupts potentially passing through the UV HUB. This prevents
|
||||
* a deadlock between interrupts and IO port operations.
|
||||
*/
|
||||
static void __init uv_set_apicid_hibit(void)
|
||||
{
|
||||
union uvh_lb_target_physical_apic_id_mask_u apicid_mask;
|
||||
unsigned long *mmr;
|
||||
|
||||
mmr = early_ioremap(UV_LOCAL_MMR_BASE |
|
||||
UVH_LB_TARGET_PHYSICAL_APIC_ID_MASK, sizeof(*mmr));
|
||||
apicid_mask.v = *mmr;
|
||||
early_iounmap(mmr, sizeof(*mmr));
|
||||
uv_apicid_hibits = apicid_mask.s.bit_enables & UV_APICID_HIBIT_MASK;
|
||||
}
|
||||
|
||||
static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
int nodeid;
|
||||
|
@ -102,6 +121,7 @@ static int __init uv_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
|||
__get_cpu_var(x2apic_extra_bits) =
|
||||
nodeid << (uvh_apicid.s.pnode_shift - 1);
|
||||
uv_system_type = UV_NON_UNIQUE_APIC;
|
||||
uv_set_apicid_hibit();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
@ -155,6 +175,7 @@ static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_ri
|
|||
int pnode;
|
||||
|
||||
pnode = uv_apicid_to_pnode(phys_apicid);
|
||||
phys_apicid |= uv_apicid_hibits;
|
||||
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
|
||||
(phys_apicid << UVH_IPI_INT_APIC_ID_SHFT) |
|
||||
((start_rip << UVH_IPI_INT_VECTOR_SHFT) >> 12) |
|
||||
|
@ -236,7 +257,7 @@ static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask)
|
|||
int cpu = cpumask_first(cpumask);
|
||||
|
||||
if ((unsigned)cpu < nr_cpu_ids)
|
||||
return per_cpu(x86_cpu_to_apicid, cpu);
|
||||
return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
|
||||
else
|
||||
return BAD_APICID;
|
||||
}
|
||||
|
@ -255,7 +276,7 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
|
|||
if (cpumask_test_cpu(cpu, cpu_online_mask))
|
||||
break;
|
||||
}
|
||||
return per_cpu(x86_cpu_to_apicid, cpu);
|
||||
return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
|
||||
}
|
||||
|
||||
static unsigned int x2apic_get_apic_id(unsigned long x)
|
||||
|
|
|
@ -381,6 +381,20 @@ static void release_pmc_hardware(void) {}
|
|||
|
||||
#endif
|
||||
|
||||
static bool check_hw_exists(void)
|
||||
{
|
||||
u64 val, val_new = 0;
|
||||
int ret = 0;
|
||||
|
||||
val = 0xabcdUL;
|
||||
ret |= checking_wrmsrl(x86_pmu.perfctr, val);
|
||||
ret |= rdmsrl_safe(x86_pmu.perfctr, &val_new);
|
||||
if (ret || val != val_new)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void reserve_ds_buffers(void);
|
||||
static void release_ds_buffers(void);
|
||||
|
||||
|
@ -1372,6 +1386,12 @@ void __init init_hw_perf_events(void)
|
|||
|
||||
pmu_check_apic();
|
||||
|
||||
/* sanity check that the hardware exists or is emulated */
|
||||
if (!check_hw_exists()) {
|
||||
pr_cont("Broken PMU hardware detected, software events only.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pr_cont("%s PMU driver.\n", x86_pmu.name);
|
||||
|
||||
if (x86_pmu.quirks)
|
||||
|
|
|
@ -395,7 +395,7 @@ sysenter_past_esp:
|
|||
* A tiny bit of offset fixup is necessary - 4*4 means the 4 words
|
||||
* pushed above; +8 corresponds to copy_thread's esp0 setting.
|
||||
*/
|
||||
pushl_cfi (TI_sysenter_return-THREAD_SIZE_asm+8+4*4)(%esp)
|
||||
pushl_cfi ((TI_sysenter_return)-THREAD_SIZE_asm+8+4*4)(%esp)
|
||||
CFI_REL_OFFSET eip, 0
|
||||
|
||||
pushl_cfi %eax
|
||||
|
|
|
@ -295,6 +295,7 @@ ENDPROC(native_usergs_sysret64)
|
|||
.endm
|
||||
|
||||
/* save partial stack frame */
|
||||
.pushsection .kprobes.text, "ax"
|
||||
ENTRY(save_args)
|
||||
XCPT_FRAME
|
||||
cld
|
||||
|
@ -334,6 +335,7 @@ ENTRY(save_args)
|
|||
ret
|
||||
CFI_ENDPROC
|
||||
END(save_args)
|
||||
.popsection
|
||||
|
||||
ENTRY(save_rest)
|
||||
PARTIAL_FRAME 1 REST_SKIP+8
|
||||
|
|
|
@ -433,6 +433,10 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args)
|
|||
dr6_p = (unsigned long *)ERR_PTR(args->err);
|
||||
dr6 = *dr6_p;
|
||||
|
||||
/* If it's a single step, TRAP bits are random */
|
||||
if (dr6 & DR_STEP)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
/* Do an early return if no trap bits are set in DR6 */
|
||||
if ((dr6 & DR_TRAP_BITS) == 0)
|
||||
return NOTIFY_DONE;
|
||||
|
|
|
@ -25,7 +25,6 @@ struct pci_hostbridge_probe {
|
|||
};
|
||||
|
||||
static u64 __cpuinitdata fam10h_pci_mmconf_base;
|
||||
static int __cpuinitdata fam10h_pci_mmconf_base_status;
|
||||
|
||||
static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = {
|
||||
{ 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 },
|
||||
|
@ -44,10 +43,12 @@ static int __cpuinit cmp_range(const void *x1, const void *x2)
|
|||
return start1 - start2;
|
||||
}
|
||||
|
||||
/*[47:0] */
|
||||
/* need to avoid (0xfd<<32) and (0xfe<<32), ht used space */
|
||||
#define MMCONF_UNIT (1ULL << FAM10H_MMIO_CONF_BASE_SHIFT)
|
||||
#define MMCONF_MASK (~(MMCONF_UNIT - 1))
|
||||
#define MMCONF_SIZE (MMCONF_UNIT << 8)
|
||||
/* need to avoid (0xfd<<32), (0xfe<<32), and (0xff<<32), ht used space */
|
||||
#define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32)
|
||||
#define BASE_VALID(b) ((b != (0xfdULL << 32)) && (b != (0xfeULL << 32)))
|
||||
#define BASE_VALID(b) ((b) + MMCONF_SIZE <= (0xfdULL<<32) || (b) >= (1ULL<<40))
|
||||
static void __cpuinit get_fam10h_pci_mmconf_base(void)
|
||||
{
|
||||
int i;
|
||||
|
@ -64,12 +65,11 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
|
|||
struct range range[8];
|
||||
|
||||
/* only try to get setting from BSP */
|
||||
/* -1 or 1 */
|
||||
if (fam10h_pci_mmconf_base_status)
|
||||
if (fam10h_pci_mmconf_base)
|
||||
return;
|
||||
|
||||
if (!early_pci_allowed())
|
||||
goto fail;
|
||||
return;
|
||||
|
||||
found = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(pci_probes); i++) {
|
||||
|
@ -91,7 +91,7 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
|
|||
}
|
||||
|
||||
if (!found)
|
||||
goto fail;
|
||||
return;
|
||||
|
||||
/* SYS_CFG */
|
||||
address = MSR_K8_SYSCFG;
|
||||
|
@ -99,16 +99,16 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
|
|||
|
||||
/* TOP_MEM2 is not enabled? */
|
||||
if (!(val & (1<<21))) {
|
||||
tom2 = 0;
|
||||
tom2 = 1ULL << 32;
|
||||
} else {
|
||||
/* TOP_MEM2 */
|
||||
address = MSR_K8_TOP_MEM2;
|
||||
rdmsrl(address, val);
|
||||
tom2 = val & (0xffffULL<<32);
|
||||
tom2 = max(val & 0xffffff800000ULL, 1ULL << 32);
|
||||
}
|
||||
|
||||
if (base <= tom2)
|
||||
base = tom2 + (1ULL<<32);
|
||||
base = (tom2 + 2 * MMCONF_UNIT - 1) & MMCONF_MASK;
|
||||
|
||||
/*
|
||||
* need to check if the range is in the high mmio range that is
|
||||
|
@ -123,11 +123,11 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
|
|||
if (!(reg & 3))
|
||||
continue;
|
||||
|
||||
start = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
|
||||
start = (u64)(reg & 0xffffff00) << 8; /* 39:16 on 31:8*/
|
||||
reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3));
|
||||
end = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/
|
||||
end = ((u64)(reg & 0xffffff00) << 8) | 0xffff; /* 39:16 on 31:8*/
|
||||
|
||||
if (!end)
|
||||
if (end < tom2)
|
||||
continue;
|
||||
|
||||
range[hi_mmio_num].start = start;
|
||||
|
@ -143,32 +143,27 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void)
|
|||
|
||||
if (range[hi_mmio_num - 1].end < base)
|
||||
goto out;
|
||||
if (range[0].start > base)
|
||||
if (range[0].start > base + MMCONF_SIZE)
|
||||
goto out;
|
||||
|
||||
/* need to find one window */
|
||||
base = range[0].start - (1ULL << 32);
|
||||
base = (range[0].start & MMCONF_MASK) - MMCONF_UNIT;
|
||||
if ((base > tom2) && BASE_VALID(base))
|
||||
goto out;
|
||||
base = range[hi_mmio_num - 1].end + (1ULL << 32);
|
||||
if ((base > tom2) && BASE_VALID(base))
|
||||
base = (range[hi_mmio_num - 1].end + MMCONF_UNIT) & MMCONF_MASK;
|
||||
if (BASE_VALID(base))
|
||||
goto out;
|
||||
/* need to find window between ranges */
|
||||
if (hi_mmio_num > 1)
|
||||
for (i = 0; i < hi_mmio_num - 1; i++) {
|
||||
if (range[i + 1].start > (range[i].end + (1ULL << 32))) {
|
||||
base = range[i].end + (1ULL << 32);
|
||||
if ((base > tom2) && BASE_VALID(base))
|
||||
goto out;
|
||||
}
|
||||
for (i = 1; i < hi_mmio_num; i++) {
|
||||
base = (range[i - 1].end + MMCONF_UNIT) & MMCONF_MASK;
|
||||
val = range[i].start & MMCONF_MASK;
|
||||
if (val >= base + MMCONF_SIZE && BASE_VALID(base))
|
||||
goto out;
|
||||
}
|
||||
|
||||
fail:
|
||||
fam10h_pci_mmconf_base_status = -1;
|
||||
return;
|
||||
|
||||
out:
|
||||
fam10h_pci_mmconf_base = base;
|
||||
fam10h_pci_mmconf_base_status = 1;
|
||||
}
|
||||
|
||||
void __cpuinit fam10h_check_enable_mmcfg(void)
|
||||
|
@ -190,11 +185,10 @@ void __cpuinit fam10h_check_enable_mmcfg(void)
|
|||
|
||||
/* only trust the one handle 256 buses, if acpi=off */
|
||||
if (!acpi_pci_disabled || busnbits >= 8) {
|
||||
u64 base;
|
||||
base = val & (0xffffULL << 32);
|
||||
if (fam10h_pci_mmconf_base_status <= 0) {
|
||||
u64 base = val & MMCONF_MASK;
|
||||
|
||||
if (!fam10h_pci_mmconf_base) {
|
||||
fam10h_pci_mmconf_base = base;
|
||||
fam10h_pci_mmconf_base_status = 1;
|
||||
return;
|
||||
} else if (fam10h_pci_mmconf_base == base)
|
||||
return;
|
||||
|
@ -206,8 +200,10 @@ void __cpuinit fam10h_check_enable_mmcfg(void)
|
|||
* with 256 buses
|
||||
*/
|
||||
get_fam10h_pci_mmconf_base();
|
||||
if (fam10h_pci_mmconf_base_status <= 0)
|
||||
if (!fam10h_pci_mmconf_base) {
|
||||
pci_probe &= ~PCI_CHECK_ENABLE_AMD_MMCONF;
|
||||
return;
|
||||
}
|
||||
|
||||
printk(KERN_INFO "Enable MMCONFIG on AMD Family 10h\n");
|
||||
val &= ~((FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT) |
|
||||
|
|
|
@ -223,7 +223,7 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
|
|||
|
||||
static void __cpuinit calculate_tlb_offset(void)
|
||||
{
|
||||
int cpu, node, nr_node_vecs;
|
||||
int cpu, node, nr_node_vecs, idx = 0;
|
||||
/*
|
||||
* we are changing tlb_vector_offset for each CPU in runtime, but this
|
||||
* will not cause inconsistency, as the write is atomic under X86. we
|
||||
|
@ -239,7 +239,7 @@ static void __cpuinit calculate_tlb_offset(void)
|
|||
nr_node_vecs = NUM_INVALIDATE_TLB_VECTORS/nr_online_nodes;
|
||||
|
||||
for_each_online_node(node) {
|
||||
int node_offset = (node % NUM_INVALIDATE_TLB_VECTORS) *
|
||||
int node_offset = (idx % NUM_INVALIDATE_TLB_VECTORS) *
|
||||
nr_node_vecs;
|
||||
int cpu_offset = 0;
|
||||
for_each_cpu(cpu, cpumask_of_node(node)) {
|
||||
|
@ -248,6 +248,7 @@ static void __cpuinit calculate_tlb_offset(void)
|
|||
cpu_offset++;
|
||||
cpu_offset = cpu_offset % nr_node_vecs;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1455,7 +1455,7 @@ static void __init uv_init_uvhub(int uvhub, int vector)
|
|||
* the below initialization can't be in firmware because the
|
||||
* messaging IRQ will be determined by the OS
|
||||
*/
|
||||
apicid = uvhub_to_first_apicid(uvhub);
|
||||
apicid = uvhub_to_first_apicid(uvhub) | uv_apicid_hibits;
|
||||
uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
|
||||
((apicid << 32) | vector));
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ static void uv_rtc_send_IPI(int cpu)
|
|||
|
||||
apicid = cpu_physical_id(cpu);
|
||||
pnode = uv_apicid_to_pnode(apicid);
|
||||
apicid |= uv_apicid_hibits;
|
||||
val = (1UL << UVH_IPI_INT_SEND_SHFT) |
|
||||
(apicid << UVH_IPI_INT_APIC_ID_SHFT) |
|
||||
(X86_PLATFORM_IPI_VECTOR << UVH_IPI_INT_VECTOR_SHFT);
|
||||
|
@ -107,6 +108,7 @@ static int uv_intr_pending(int pnode)
|
|||
static int uv_setup_intr(int cpu, u64 expires)
|
||||
{
|
||||
u64 val;
|
||||
unsigned long apicid = cpu_physical_id(cpu) | uv_apicid_hibits;
|
||||
int pnode = uv_cpu_to_pnode(cpu);
|
||||
|
||||
uv_write_global_mmr64(pnode, UVH_RTC1_INT_CONFIG,
|
||||
|
@ -117,7 +119,7 @@ static int uv_setup_intr(int cpu, u64 expires)
|
|||
UVH_EVENT_OCCURRED0_RTC1_MASK);
|
||||
|
||||
val = (X86_PLATFORM_IPI_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
|
||||
((u64)cpu_physical_id(cpu) << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);
|
||||
((u64)apicid << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);
|
||||
|
||||
/* Set configuration */
|
||||
uv_write_global_mmr64(pnode, UVH_RTC1_INT_CONFIG, val);
|
||||
|
|
|
@ -1200,8 +1200,6 @@ asmlinkage void __init xen_start_kernel(void)
|
|||
/* Allocate and initialize top and mid mfn levels for p2m structure */
|
||||
xen_build_mfn_list_list();
|
||||
|
||||
init_mm.pgd = pgd;
|
||||
|
||||
/* keep using Xen gdt for now; no urgent need to change it */
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
|
|
|
@ -2133,44 +2133,83 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
|
|||
return pgd;
|
||||
}
|
||||
#else /* !CONFIG_X86_64 */
|
||||
static RESERVE_BRK_ARRAY(pmd_t, level2_kernel_pgt, PTRS_PER_PMD);
|
||||
static RESERVE_BRK_ARRAY(pmd_t, initial_kernel_pmd, PTRS_PER_PMD);
|
||||
static RESERVE_BRK_ARRAY(pmd_t, swapper_kernel_pmd, PTRS_PER_PMD);
|
||||
|
||||
static __init void xen_write_cr3_init(unsigned long cr3)
|
||||
{
|
||||
unsigned long pfn = PFN_DOWN(__pa(swapper_pg_dir));
|
||||
|
||||
BUG_ON(read_cr3() != __pa(initial_page_table));
|
||||
BUG_ON(cr3 != __pa(swapper_pg_dir));
|
||||
|
||||
/*
|
||||
* We are switching to swapper_pg_dir for the first time (from
|
||||
* initial_page_table) and therefore need to mark that page
|
||||
* read-only and then pin it.
|
||||
*
|
||||
* Xen disallows sharing of kernel PMDs for PAE
|
||||
* guests. Therefore we must copy the kernel PMD from
|
||||
* initial_page_table into a new kernel PMD to be used in
|
||||
* swapper_pg_dir.
|
||||
*/
|
||||
swapper_kernel_pmd =
|
||||
extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
|
||||
memcpy(swapper_kernel_pmd, initial_kernel_pmd,
|
||||
sizeof(pmd_t) * PTRS_PER_PMD);
|
||||
swapper_pg_dir[KERNEL_PGD_BOUNDARY] =
|
||||
__pgd(__pa(swapper_kernel_pmd) | _PAGE_PRESENT);
|
||||
set_page_prot(swapper_kernel_pmd, PAGE_KERNEL_RO);
|
||||
|
||||
set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
|
||||
xen_write_cr3(cr3);
|
||||
pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, pfn);
|
||||
|
||||
pin_pagetable_pfn(MMUEXT_UNPIN_TABLE,
|
||||
PFN_DOWN(__pa(initial_page_table)));
|
||||
set_page_prot(initial_page_table, PAGE_KERNEL);
|
||||
set_page_prot(initial_kernel_pmd, PAGE_KERNEL);
|
||||
|
||||
pv_mmu_ops.write_cr3 = &xen_write_cr3;
|
||||
}
|
||||
|
||||
__init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
|
||||
unsigned long max_pfn)
|
||||
{
|
||||
pmd_t *kernel_pmd;
|
||||
|
||||
level2_kernel_pgt = extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
|
||||
initial_kernel_pmd =
|
||||
extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
|
||||
|
||||
max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
|
||||
xen_start_info->nr_pt_frames * PAGE_SIZE +
|
||||
512*1024);
|
||||
|
||||
kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
|
||||
memcpy(level2_kernel_pgt, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
|
||||
memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
|
||||
|
||||
xen_map_identity_early(level2_kernel_pgt, max_pfn);
|
||||
xen_map_identity_early(initial_kernel_pmd, max_pfn);
|
||||
|
||||
memcpy(swapper_pg_dir, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
|
||||
set_pgd(&swapper_pg_dir[KERNEL_PGD_BOUNDARY],
|
||||
__pgd(__pa(level2_kernel_pgt) | _PAGE_PRESENT));
|
||||
memcpy(initial_page_table, pgd, sizeof(pgd_t) * PTRS_PER_PGD);
|
||||
initial_page_table[KERNEL_PGD_BOUNDARY] =
|
||||
__pgd(__pa(initial_kernel_pmd) | _PAGE_PRESENT);
|
||||
|
||||
set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
|
||||
set_page_prot(swapper_pg_dir, PAGE_KERNEL_RO);
|
||||
set_page_prot(initial_kernel_pmd, PAGE_KERNEL_RO);
|
||||
set_page_prot(initial_page_table, PAGE_KERNEL_RO);
|
||||
set_page_prot(empty_zero_page, PAGE_KERNEL_RO);
|
||||
|
||||
pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
|
||||
|
||||
xen_write_cr3(__pa(swapper_pg_dir));
|
||||
|
||||
pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE, PFN_DOWN(__pa(swapper_pg_dir)));
|
||||
pin_pagetable_pfn(MMUEXT_PIN_L3_TABLE,
|
||||
PFN_DOWN(__pa(initial_page_table)));
|
||||
xen_write_cr3(__pa(initial_page_table));
|
||||
|
||||
memblock_x86_reserve_range(__pa(xen_start_info->pt_base),
|
||||
__pa(xen_start_info->pt_base +
|
||||
xen_start_info->nr_pt_frames * PAGE_SIZE),
|
||||
"XEN PAGETABLES");
|
||||
|
||||
return swapper_pg_dir;
|
||||
return initial_page_table;
|
||||
}
|
||||
#endif /* CONFIG_X86_64 */
|
||||
|
||||
|
@ -2304,7 +2343,11 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
|
|||
.write_cr2 = xen_write_cr2,
|
||||
|
||||
.read_cr3 = xen_read_cr3,
|
||||
#ifdef CONFIG_X86_32
|
||||
.write_cr3 = xen_write_cr3_init,
|
||||
#else
|
||||
.write_cr3 = xen_write_cr3,
|
||||
#endif
|
||||
|
||||
.flush_tlb_user = xen_flush_tlb,
|
||||
.flush_tlb_kernel = xen_flush_tlb,
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <xen/interface/callback.h>
|
||||
#include <xen/interface/memory.h>
|
||||
#include <xen/interface/physdev.h>
|
||||
#include <xen/interface/memory.h>
|
||||
#include <xen/features.h>
|
||||
|
||||
#include "xen-ops.h"
|
||||
|
|
|
@ -645,7 +645,7 @@ static int throtl_dispatch_tg(struct throtl_data *td, struct throtl_grp *tg,
|
|||
{
|
||||
unsigned int nr_reads = 0, nr_writes = 0;
|
||||
unsigned int max_nr_reads = throtl_grp_quantum*3/4;
|
||||
unsigned int max_nr_writes = throtl_grp_quantum - nr_reads;
|
||||
unsigned int max_nr_writes = throtl_grp_quantum - max_nr_reads;
|
||||
struct bio *bio;
|
||||
|
||||
/* Try to dispatch 75% READS and 25% WRITES */
|
||||
|
|
|
@ -1341,7 +1341,7 @@ static struct request *set_next_request(void)
|
|||
{
|
||||
struct request_queue *q;
|
||||
int cnt = FD_MAX_UNITS;
|
||||
struct request *rq;
|
||||
struct request *rq = NULL;
|
||||
|
||||
/* Find next queue we can dispatch from */
|
||||
fdc_queue = fdc_queue + 1;
|
||||
|
|
|
@ -1399,7 +1399,7 @@ static struct request *set_next_request(void)
|
|||
{
|
||||
struct request_queue *q;
|
||||
int old_pos = fdc_queue;
|
||||
struct request *rq;
|
||||
struct request *rq = NULL;
|
||||
|
||||
do {
|
||||
q = unit[fdc_queue].disk->queue;
|
||||
|
|
|
@ -66,6 +66,7 @@ MODULE_VERSION("3.6.26");
|
|||
MODULE_LICENSE("GPL");
|
||||
|
||||
static DEFINE_MUTEX(cciss_mutex);
|
||||
static struct proc_dir_entry *proc_cciss;
|
||||
|
||||
#include "cciss_cmd.h"
|
||||
#include "cciss.h"
|
||||
|
@ -363,8 +364,6 @@ static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
|
|||
#define ENG_GIG_FACTOR (ENG_GIG/512)
|
||||
#define ENGAGE_SCSI "engage scsi"
|
||||
|
||||
static struct proc_dir_entry *proc_cciss;
|
||||
|
||||
static void cciss_seq_show_header(struct seq_file *seq)
|
||||
{
|
||||
ctlr_info_t *h = seq->private;
|
||||
|
|
|
@ -65,7 +65,7 @@ enum blkif_state {
|
|||
|
||||
struct blk_shadow {
|
||||
struct blkif_request req;
|
||||
unsigned long request;
|
||||
struct request *request;
|
||||
unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
|
||||
};
|
||||
|
||||
|
@ -136,7 +136,7 @@ static void add_id_to_freelist(struct blkfront_info *info,
|
|||
unsigned long id)
|
||||
{
|
||||
info->shadow[id].req.id = info->shadow_free;
|
||||
info->shadow[id].request = 0;
|
||||
info->shadow[id].request = NULL;
|
||||
info->shadow_free = id;
|
||||
}
|
||||
|
||||
|
@ -245,14 +245,11 @@ static int blkif_ioctl(struct block_device *bdev, fmode_t mode,
|
|||
}
|
||||
|
||||
/*
|
||||
* blkif_queue_request
|
||||
* Generate a Xen blkfront IO request from a blk layer request. Reads
|
||||
* and writes are handled as expected. Since we lack a loose flush
|
||||
* request, we map flushes into a full ordered barrier.
|
||||
*
|
||||
* request block io
|
||||
*
|
||||
* id: for guest use only.
|
||||
* operation: BLKIF_OP_{READ,WRITE,PROBE}
|
||||
* buffer: buffer to read/write into. this should be a
|
||||
* virtual address in the guest os.
|
||||
* @req: a request struct
|
||||
*/
|
||||
static int blkif_queue_request(struct request *req)
|
||||
{
|
||||
|
@ -281,7 +278,7 @@ static int blkif_queue_request(struct request *req)
|
|||
/* Fill out a communications ring structure. */
|
||||
ring_req = RING_GET_REQUEST(&info->ring, info->ring.req_prod_pvt);
|
||||
id = get_id_from_freelist(info);
|
||||
info->shadow[id].request = (unsigned long)req;
|
||||
info->shadow[id].request = req;
|
||||
|
||||
ring_req->id = id;
|
||||
ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req);
|
||||
|
@ -290,6 +287,18 @@ static int blkif_queue_request(struct request *req)
|
|||
ring_req->operation = rq_data_dir(req) ?
|
||||
BLKIF_OP_WRITE : BLKIF_OP_READ;
|
||||
|
||||
if (req->cmd_flags & (REQ_FLUSH | REQ_FUA)) {
|
||||
/*
|
||||
* Ideally we could just do an unordered
|
||||
* flush-to-disk, but all we have is a full write
|
||||
* barrier at the moment. However, a barrier write is
|
||||
* a superset of FUA, so we can implement it the same
|
||||
* way. (It's also a FLUSH+FUA, since it is
|
||||
* guaranteed ordered WRT previous writes.)
|
||||
*/
|
||||
ring_req->operation = BLKIF_OP_WRITE_BARRIER;
|
||||
}
|
||||
|
||||
ring_req->nr_segments = blk_rq_map_sg(req->q, req, info->sg);
|
||||
BUG_ON(ring_req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST);
|
||||
|
||||
|
@ -634,7 +643,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
|
|||
|
||||
bret = RING_GET_RESPONSE(&info->ring, i);
|
||||
id = bret->id;
|
||||
req = (struct request *)info->shadow[id].request;
|
||||
req = info->shadow[id].request;
|
||||
|
||||
blkif_completion(&info->shadow[id]);
|
||||
|
||||
|
@ -647,6 +656,16 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id)
|
|||
printk(KERN_WARNING "blkfront: %s: write barrier op failed\n",
|
||||
info->gd->disk_name);
|
||||
error = -EOPNOTSUPP;
|
||||
}
|
||||
if (unlikely(bret->status == BLKIF_RSP_ERROR &&
|
||||
info->shadow[id].req.nr_segments == 0)) {
|
||||
printk(KERN_WARNING "blkfront: %s: empty write barrier op failed\n",
|
||||
info->gd->disk_name);
|
||||
error = -EOPNOTSUPP;
|
||||
}
|
||||
if (unlikely(error)) {
|
||||
if (error == -EOPNOTSUPP)
|
||||
error = 0;
|
||||
info->feature_flush = 0;
|
||||
xlvbd_flush(info);
|
||||
}
|
||||
|
@ -899,7 +918,7 @@ static int blkif_recover(struct blkfront_info *info)
|
|||
/* Stage 3: Find pending requests and requeue them. */
|
||||
for (i = 0; i < BLK_RING_SIZE; i++) {
|
||||
/* Not in use? */
|
||||
if (copy[i].request == 0)
|
||||
if (!copy[i].request)
|
||||
continue;
|
||||
|
||||
/* Grab a request slot and copy shadow state into it. */
|
||||
|
@ -916,9 +935,7 @@ static int blkif_recover(struct blkfront_info *info)
|
|||
req->seg[j].gref,
|
||||
info->xbdev->otherend_id,
|
||||
pfn_to_mfn(info->shadow[req->id].frame[j]),
|
||||
rq_data_dir(
|
||||
(struct request *)
|
||||
info->shadow[req->id].request));
|
||||
rq_data_dir(info->shadow[req->id].request));
|
||||
info->shadow[req->id].req = *req;
|
||||
|
||||
info->ring.req_prod_pvt++;
|
||||
|
@ -1067,14 +1084,8 @@ static void blkfront_connect(struct blkfront_info *info)
|
|||
*/
|
||||
info->feature_flush = 0;
|
||||
|
||||
/*
|
||||
* The driver doesn't properly handled empty flushes, so
|
||||
* lets disable barrier support for now.
|
||||
*/
|
||||
#if 0
|
||||
if (!err && barrier)
|
||||
info->feature_flush = REQ_FLUSH;
|
||||
#endif
|
||||
info->feature_flush = REQ_FLUSH | REQ_FUA;
|
||||
|
||||
err = xlvbd_alloc_gendisk(sectors, info, binfo, sector_size);
|
||||
if (err) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/acpi.h>
|
||||
#include "tpm.h"
|
||||
|
||||
#define TPM_HEADER_SIZE 10
|
||||
|
@ -78,6 +79,26 @@ enum tis_defaults {
|
|||
static LIST_HEAD(tis_chips);
|
||||
static DEFINE_SPINLOCK(tis_lock);
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
static int is_itpm(struct pnp_dev *dev)
|
||||
{
|
||||
struct acpi_device *acpi = pnp_acpi_device(dev);
|
||||
struct acpi_hardware_id *id;
|
||||
|
||||
list_for_each_entry(id, &acpi->pnp.ids, list) {
|
||||
if (!strcmp("INTC0102", id->id))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int is_itpm(struct pnp_dev *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int check_locality(struct tpm_chip *chip, int l)
|
||||
{
|
||||
if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
|
||||
|
@ -472,6 +493,9 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
|
|||
"1.2 TPM (device-id 0x%X, rev-id %d)\n",
|
||||
vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
|
||||
|
||||
if (is_itpm(to_pnp_dev(dev)))
|
||||
itpm = 1;
|
||||
|
||||
if (itpm)
|
||||
dev_info(dev, "Intel iTPM workaround enabled\n");
|
||||
|
||||
|
|
|
@ -10,16 +10,16 @@ obj-$(CONFIG_EDAC) := edac_stub.o
|
|||
obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
|
||||
obj-$(CONFIG_EDAC_MCE) += edac_mce.o
|
||||
|
||||
edac_core-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
|
||||
edac_core-objs += edac_module.o edac_device_sysfs.o
|
||||
edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
|
||||
edac_core-y += edac_module.o edac_device_sysfs.o
|
||||
|
||||
ifdef CONFIG_PCI
|
||||
edac_core-objs += edac_pci.o edac_pci_sysfs.o
|
||||
edac_core-y += edac_pci.o edac_pci_sysfs.o
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_EDAC_MCE_INJ) += mce_amd_inj.o
|
||||
|
||||
edac_mce_amd-objs := mce_amd.o
|
||||
edac_mce_amd-y := mce_amd.o
|
||||
obj-$(CONFIG_EDAC_DECODE_MCE) += edac_mce_amd.o
|
||||
|
||||
obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o
|
||||
|
|
|
@ -139,7 +139,7 @@ static int __init edac_init_mce_inject(void)
|
|||
return 0;
|
||||
|
||||
err_sysfs_create:
|
||||
while (i-- >= 0)
|
||||
while (--i >= 0)
|
||||
sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
|
||||
|
||||
kobject_del(mce_kobj);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/firewire.h>
|
||||
#include <linux/firewire-constants.h>
|
||||
|
@ -26,8 +27,14 @@
|
|||
#include <asm/unaligned.h>
|
||||
#include <net/arp.h>
|
||||
|
||||
#define FWNET_MAX_FRAGMENTS 25 /* arbitrary limit */
|
||||
#define FWNET_ISO_PAGE_COUNT (PAGE_SIZE < 16 * 1024 ? 4 : 2)
|
||||
/* rx limits */
|
||||
#define FWNET_MAX_FRAGMENTS 30 /* arbitrary, > TX queue depth */
|
||||
#define FWNET_ISO_PAGE_COUNT (PAGE_SIZE < 16*1024 ? 4 : 2)
|
||||
|
||||
/* tx limits */
|
||||
#define FWNET_MAX_QUEUED_DATAGRAMS 20 /* < 64 = number of tlabels */
|
||||
#define FWNET_MIN_QUEUED_DATAGRAMS 10 /* should keep AT DMA busy enough */
|
||||
#define FWNET_TX_QUEUE_LEN FWNET_MAX_QUEUED_DATAGRAMS /* ? */
|
||||
|
||||
#define IEEE1394_BROADCAST_CHANNEL 31
|
||||
#define IEEE1394_ALL_NODES (0xffc0 | 0x003f)
|
||||
|
@ -169,15 +176,8 @@ struct fwnet_device {
|
|||
struct fw_address_handler handler;
|
||||
u64 local_fifo;
|
||||
|
||||
/* List of packets to be sent */
|
||||
struct list_head packet_list;
|
||||
/*
|
||||
* List of packets that were broadcasted. When we get an ISO interrupt
|
||||
* one of them has been sent
|
||||
*/
|
||||
struct list_head broadcasted_list;
|
||||
/* List of packets that have been sent but not yet acked */
|
||||
struct list_head sent_list;
|
||||
/* Number of tx datagrams that have been queued but not yet acked */
|
||||
int queued_datagrams;
|
||||
|
||||
struct list_head peer_list;
|
||||
struct fw_card *card;
|
||||
|
@ -195,7 +195,7 @@ struct fwnet_peer {
|
|||
unsigned pdg_size; /* pd_list size */
|
||||
|
||||
u16 datagram_label; /* outgoing datagram label */
|
||||
unsigned max_payload; /* includes RFC2374_FRAG_HDR_SIZE overhead */
|
||||
u16 max_payload; /* includes RFC2374_FRAG_HDR_SIZE overhead */
|
||||
int node_id;
|
||||
int generation;
|
||||
unsigned speed;
|
||||
|
@ -203,22 +203,18 @@ struct fwnet_peer {
|
|||
|
||||
/* This is our task struct. It's used for the packet complete callback. */
|
||||
struct fwnet_packet_task {
|
||||
/*
|
||||
* ptask can actually be on dev->packet_list, dev->broadcasted_list,
|
||||
* or dev->sent_list depending on its current state.
|
||||
*/
|
||||
struct list_head pt_link;
|
||||
struct fw_transaction transaction;
|
||||
struct rfc2734_header hdr;
|
||||
struct sk_buff *skb;
|
||||
struct fwnet_device *dev;
|
||||
|
||||
int outstanding_pkts;
|
||||
unsigned max_payload;
|
||||
u64 fifo_addr;
|
||||
u16 dest_node;
|
||||
u16 max_payload;
|
||||
u8 generation;
|
||||
u8 speed;
|
||||
u8 enqueued;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -650,8 +646,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
|
|||
net->stats.rx_packets++;
|
||||
net->stats.rx_bytes += skb->len;
|
||||
}
|
||||
if (netif_queue_stopped(net))
|
||||
netif_wake_queue(net);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -660,8 +654,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
|
|||
net->stats.rx_dropped++;
|
||||
|
||||
dev_kfree_skb_any(skb);
|
||||
if (netif_queue_stopped(net))
|
||||
netif_wake_queue(net);
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -793,15 +785,10 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,
|
|||
* Datagram is not complete, we're done for the
|
||||
* moment.
|
||||
*/
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
return 0;
|
||||
retval = 0;
|
||||
fail:
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
if (netif_queue_stopped(net))
|
||||
netif_wake_queue(net);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -901,11 +888,19 @@ static void fwnet_free_ptask(struct fwnet_packet_task *ptask)
|
|||
kmem_cache_free(fwnet_packet_task_cache, ptask);
|
||||
}
|
||||
|
||||
/* Caller must hold dev->lock. */
|
||||
static void dec_queued_datagrams(struct fwnet_device *dev)
|
||||
{
|
||||
if (--dev->queued_datagrams == FWNET_MIN_QUEUED_DATAGRAMS)
|
||||
netif_wake_queue(dev->netdev);
|
||||
}
|
||||
|
||||
static int fwnet_send_packet(struct fwnet_packet_task *ptask);
|
||||
|
||||
static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
|
||||
{
|
||||
struct fwnet_device *dev = ptask->dev;
|
||||
struct sk_buff *skb = ptask->skb;
|
||||
unsigned long flags;
|
||||
bool free;
|
||||
|
||||
|
@ -914,10 +909,14 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
|
|||
ptask->outstanding_pkts--;
|
||||
|
||||
/* Check whether we or the networking TX soft-IRQ is last user. */
|
||||
free = (ptask->outstanding_pkts == 0 && !list_empty(&ptask->pt_link));
|
||||
free = (ptask->outstanding_pkts == 0 && ptask->enqueued);
|
||||
if (free)
|
||||
dec_queued_datagrams(dev);
|
||||
|
||||
if (ptask->outstanding_pkts == 0)
|
||||
list_del(&ptask->pt_link);
|
||||
if (ptask->outstanding_pkts == 0) {
|
||||
dev->netdev->stats.tx_packets++;
|
||||
dev->netdev->stats.tx_bytes += skb->len;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
|
@ -926,7 +925,6 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
|
|||
u16 fg_off;
|
||||
u16 datagram_label;
|
||||
u16 lf;
|
||||
struct sk_buff *skb;
|
||||
|
||||
/* Update the ptask to point to the next fragment and send it */
|
||||
lf = fwnet_get_hdr_lf(&ptask->hdr);
|
||||
|
@ -953,7 +951,7 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
|
|||
datagram_label = fwnet_get_hdr_dgl(&ptask->hdr);
|
||||
break;
|
||||
}
|
||||
skb = ptask->skb;
|
||||
|
||||
skb_pull(skb, ptask->max_payload);
|
||||
if (ptask->outstanding_pkts > 1) {
|
||||
fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG,
|
||||
|
@ -970,6 +968,31 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask)
|
|||
fwnet_free_ptask(ptask);
|
||||
}
|
||||
|
||||
static void fwnet_transmit_packet_failed(struct fwnet_packet_task *ptask)
|
||||
{
|
||||
struct fwnet_device *dev = ptask->dev;
|
||||
unsigned long flags;
|
||||
bool free;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
|
||||
/* One fragment failed; don't try to send remaining fragments. */
|
||||
ptask->outstanding_pkts = 0;
|
||||
|
||||
/* Check whether we or the networking TX soft-IRQ is last user. */
|
||||
free = ptask->enqueued;
|
||||
if (free)
|
||||
dec_queued_datagrams(dev);
|
||||
|
||||
dev->netdev->stats.tx_dropped++;
|
||||
dev->netdev->stats.tx_errors++;
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
if (free)
|
||||
fwnet_free_ptask(ptask);
|
||||
}
|
||||
|
||||
static void fwnet_write_complete(struct fw_card *card, int rcode,
|
||||
void *payload, size_t length, void *data)
|
||||
{
|
||||
|
@ -977,11 +1000,12 @@ static void fwnet_write_complete(struct fw_card *card, int rcode,
|
|||
|
||||
ptask = data;
|
||||
|
||||
if (rcode == RCODE_COMPLETE)
|
||||
if (rcode == RCODE_COMPLETE) {
|
||||
fwnet_transmit_packet_done(ptask);
|
||||
else
|
||||
} else {
|
||||
fw_error("fwnet_write_complete: failed: %x\n", rcode);
|
||||
/* ??? error recovery */
|
||||
fwnet_transmit_packet_failed(ptask);
|
||||
}
|
||||
}
|
||||
|
||||
static int fwnet_send_packet(struct fwnet_packet_task *ptask)
|
||||
|
@ -1039,9 +1063,11 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
|
|||
spin_lock_irqsave(&dev->lock, flags);
|
||||
|
||||
/* If the AT tasklet already ran, we may be last user. */
|
||||
free = (ptask->outstanding_pkts == 0 && list_empty(&ptask->pt_link));
|
||||
free = (ptask->outstanding_pkts == 0 && !ptask->enqueued);
|
||||
if (!free)
|
||||
list_add_tail(&ptask->pt_link, &dev->broadcasted_list);
|
||||
ptask->enqueued = true;
|
||||
else
|
||||
dec_queued_datagrams(dev);
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
|
@ -1056,9 +1082,11 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask)
|
|||
spin_lock_irqsave(&dev->lock, flags);
|
||||
|
||||
/* If the AT tasklet already ran, we may be last user. */
|
||||
free = (ptask->outstanding_pkts == 0 && list_empty(&ptask->pt_link));
|
||||
free = (ptask->outstanding_pkts == 0 && !ptask->enqueued);
|
||||
if (!free)
|
||||
list_add_tail(&ptask->pt_link, &dev->sent_list);
|
||||
ptask->enqueued = true;
|
||||
else
|
||||
dec_queued_datagrams(dev);
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
|
@ -1224,6 +1252,15 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
|
|||
struct fwnet_peer *peer;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
|
||||
/* Can this happen? */
|
||||
if (netif_queue_stopped(dev->netdev)) {
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
ptask = kmem_cache_alloc(fwnet_packet_task_cache, GFP_ATOMIC);
|
||||
if (ptask == NULL)
|
||||
goto fail;
|
||||
|
@ -1242,9 +1279,6 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
|
|||
proto = hdr_buf.h_proto;
|
||||
dg_size = skb->len;
|
||||
|
||||
/* serialize access to peer, including peer->datagram_label */
|
||||
spin_lock_irqsave(&dev->lock, flags);
|
||||
|
||||
/*
|
||||
* Set the transmission type for the packet. ARP packets and IP
|
||||
* broadcast packets are sent via GASP.
|
||||
|
@ -1266,7 +1300,7 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
|
|||
|
||||
peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid));
|
||||
if (!peer || peer->fifo == FWNET_NO_FIFO_ADDR)
|
||||
goto fail_unlock;
|
||||
goto fail;
|
||||
|
||||
generation = peer->generation;
|
||||
dest_node = peer->node_id;
|
||||
|
@ -1320,18 +1354,21 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
|
|||
max_payload += RFC2374_FRAG_HDR_SIZE;
|
||||
}
|
||||
|
||||
if (++dev->queued_datagrams == FWNET_MAX_QUEUED_DATAGRAMS)
|
||||
netif_stop_queue(dev->netdev);
|
||||
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
ptask->max_payload = max_payload;
|
||||
INIT_LIST_HEAD(&ptask->pt_link);
|
||||
ptask->enqueued = 0;
|
||||
|
||||
fwnet_send_packet(ptask);
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
fail_unlock:
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
fail:
|
||||
spin_unlock_irqrestore(&dev->lock, flags);
|
||||
|
||||
if (ptask)
|
||||
kmem_cache_free(fwnet_packet_task_cache, ptask);
|
||||
|
||||
|
@ -1377,7 +1414,7 @@ static void fwnet_init_dev(struct net_device *net)
|
|||
net->addr_len = FWNET_ALEN;
|
||||
net->hard_header_len = FWNET_HLEN;
|
||||
net->type = ARPHRD_IEEE1394;
|
||||
net->tx_queue_len = 10;
|
||||
net->tx_queue_len = FWNET_TX_QUEUE_LEN;
|
||||
}
|
||||
|
||||
/* caller must hold fwnet_device_mutex */
|
||||
|
@ -1457,14 +1494,9 @@ static int fwnet_probe(struct device *_dev)
|
|||
dev->broadcast_rcv_context = NULL;
|
||||
dev->broadcast_xmt_max_payload = 0;
|
||||
dev->broadcast_xmt_datagramlabel = 0;
|
||||
|
||||
dev->local_fifo = FWNET_NO_FIFO_ADDR;
|
||||
|
||||
INIT_LIST_HEAD(&dev->packet_list);
|
||||
INIT_LIST_HEAD(&dev->broadcasted_list);
|
||||
INIT_LIST_HEAD(&dev->sent_list);
|
||||
dev->queued_datagrams = 0;
|
||||
INIT_LIST_HEAD(&dev->peer_list);
|
||||
|
||||
dev->card = card;
|
||||
dev->netdev = net;
|
||||
|
||||
|
@ -1522,7 +1554,7 @@ static int fwnet_remove(struct device *_dev)
|
|||
struct fwnet_peer *peer = dev_get_drvdata(_dev);
|
||||
struct fwnet_device *dev = peer->dev;
|
||||
struct net_device *net;
|
||||
struct fwnet_packet_task *ptask, *pt_next;
|
||||
int i;
|
||||
|
||||
mutex_lock(&fwnet_device_mutex);
|
||||
|
||||
|
@ -1540,21 +1572,9 @@ static int fwnet_remove(struct device *_dev)
|
|||
dev->card);
|
||||
fw_iso_context_destroy(dev->broadcast_rcv_context);
|
||||
}
|
||||
list_for_each_entry_safe(ptask, pt_next,
|
||||
&dev->packet_list, pt_link) {
|
||||
dev_kfree_skb_any(ptask->skb);
|
||||
kmem_cache_free(fwnet_packet_task_cache, ptask);
|
||||
}
|
||||
list_for_each_entry_safe(ptask, pt_next,
|
||||
&dev->broadcasted_list, pt_link) {
|
||||
dev_kfree_skb_any(ptask->skb);
|
||||
kmem_cache_free(fwnet_packet_task_cache, ptask);
|
||||
}
|
||||
list_for_each_entry_safe(ptask, pt_next,
|
||||
&dev->sent_list, pt_link) {
|
||||
dev_kfree_skb_any(ptask->skb);
|
||||
kmem_cache_free(fwnet_packet_task_cache, ptask);
|
||||
}
|
||||
for (i = 0; dev->queued_datagrams && i < 5; i++)
|
||||
ssleep(1);
|
||||
WARN_ON(dev->queued_datagrams);
|
||||
list_del(&dev->dev_link);
|
||||
|
||||
free_netdev(net);
|
||||
|
|
|
@ -497,12 +497,14 @@ static unsigned long chipset_ids[] = {
|
|||
0
|
||||
};
|
||||
|
||||
#ifdef MODULE
|
||||
static struct pci_device_id i5k_amb_ids[] __devinitdata = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) },
|
||||
{ 0, }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(pci, i5k_amb_ids);
|
||||
#endif
|
||||
|
||||
static int __devinit i5k_amb_probe(struct platform_device *pdev)
|
||||
{
|
||||
|
|
|
@ -186,7 +186,7 @@ static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int lis3lv02d_i2c_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
||||
|
@ -213,12 +213,9 @@ static int lis3lv02d_i2c_resume(struct device *dev)
|
|||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define lis3lv02d_i2c_suspend NULL
|
||||
#define lis3lv02d_i2c_resume NULL
|
||||
#define lis3lv02d_i2c_shutdown NULL
|
||||
#endif
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
static int lis3_i2c_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = container_of(dev, struct i2c_client, dev);
|
||||
|
@ -236,6 +233,7 @@ static int lis3_i2c_runtime_resume(struct device *dev)
|
|||
lis3lv02d_poweron(lis3);
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PM_RUNTIME */
|
||||
|
||||
static const struct i2c_device_id lis3lv02d_id[] = {
|
||||
{"lis3lv02d", 0 },
|
||||
|
|
|
@ -214,7 +214,6 @@ config SERIO_AMS_DELTA
|
|||
tristate "Amstrad Delta (E3) mailboard support"
|
||||
depends on MACH_AMS_DELTA
|
||||
default y
|
||||
select AMS_DELTA_FIQ
|
||||
---help---
|
||||
Say Y here if you have an E3 and want to use its mailboard,
|
||||
or any standard AT keyboard connected to the mailboard port.
|
||||
|
|
|
@ -1627,7 +1627,7 @@ __setup("icn=", icn_setup);
|
|||
static int __init icn_init(void)
|
||||
{
|
||||
char *p;
|
||||
char rev[10];
|
||||
char rev[20];
|
||||
|
||||
memset(&dev, 0, sizeof(icn_dev));
|
||||
dev.memaddr = (membase & 0x0ffc000);
|
||||
|
@ -1637,9 +1637,10 @@ static int __init icn_init(void)
|
|||
spin_lock_init(&dev.devlock);
|
||||
|
||||
if ((p = strchr(revision, ':'))) {
|
||||
strcpy(rev, p + 1);
|
||||
strncpy(rev, p + 1, 20);
|
||||
p = strchr(rev, '$');
|
||||
*p = 0;
|
||||
if (p)
|
||||
*p = 0;
|
||||
} else
|
||||
strcpy(rev, " ??? ");
|
||||
printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,
|
||||
|
|
|
@ -1559,7 +1559,7 @@ void mmc_stop_host(struct mmc_host *host)
|
|||
|
||||
if (host->caps & MMC_CAP_DISABLE)
|
||||
cancel_delayed_work(&host->disable);
|
||||
cancel_delayed_work(&host->detect);
|
||||
cancel_delayed_work_sync(&host->detect);
|
||||
mmc_flush_scheduled_work();
|
||||
|
||||
/* clear pm flags now and let card drivers set them as needed */
|
||||
|
|
|
@ -375,7 +375,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||
struct mmc_card *oldcard)
|
||||
{
|
||||
struct mmc_card *card;
|
||||
int err, ddr = MMC_SDR_MODE;
|
||||
int err, ddr = 0;
|
||||
u32 cid[4];
|
||||
unsigned int max_dtr;
|
||||
|
||||
|
@ -562,7 +562,11 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
|
|||
1 << bus_width, ddr);
|
||||
err = 0;
|
||||
} else {
|
||||
mmc_card_set_ddr_mode(card);
|
||||
if (ddr)
|
||||
mmc_card_set_ddr_mode(card);
|
||||
else
|
||||
ddr = MMC_SDR_MODE;
|
||||
|
||||
mmc_set_bus_width_ddr(card->host, bus_width, ddr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -547,9 +547,11 @@ static void mmc_sdio_detect(struct mmc_host *host)
|
|||
BUG_ON(!host->card);
|
||||
|
||||
/* Make sure card is powered before detecting it */
|
||||
err = pm_runtime_get_sync(&host->card->dev);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
if (host->caps & MMC_CAP_POWER_OFF_CARD) {
|
||||
err = pm_runtime_get_sync(&host->card->dev);
|
||||
if (err < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
mmc_claim_host(host);
|
||||
|
||||
|
@ -560,6 +562,20 @@ static void mmc_sdio_detect(struct mmc_host *host)
|
|||
|
||||
mmc_release_host(host);
|
||||
|
||||
/*
|
||||
* Tell PM core it's OK to power off the card now.
|
||||
*
|
||||
* The _sync variant is used in order to ensure that the card
|
||||
* is left powered off in case an error occurred, and the card
|
||||
* is going to be removed.
|
||||
*
|
||||
* Since there is no specific reason to believe a new user
|
||||
* is about to show up at this point, the _sync variant is
|
||||
* desirable anyway.
|
||||
*/
|
||||
if (host->caps & MMC_CAP_POWER_OFF_CARD)
|
||||
pm_runtime_put_sync(&host->card->dev);
|
||||
|
||||
out:
|
||||
if (err) {
|
||||
mmc_sdio_remove(host);
|
||||
|
@ -568,9 +584,6 @@ out:
|
|||
mmc_detach_bus(host);
|
||||
mmc_release_host(host);
|
||||
}
|
||||
|
||||
/* Tell PM core that we're done */
|
||||
pm_runtime_put(&host->card->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -718,16 +731,21 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
|
|||
card = host->card;
|
||||
|
||||
/*
|
||||
* Let runtime PM core know our card is active
|
||||
* Enable runtime PM only if supported by host+card+board
|
||||
*/
|
||||
err = pm_runtime_set_active(&card->dev);
|
||||
if (err)
|
||||
goto remove;
|
||||
if (host->caps & MMC_CAP_POWER_OFF_CARD) {
|
||||
/*
|
||||
* Let runtime PM core know our card is active
|
||||
*/
|
||||
err = pm_runtime_set_active(&card->dev);
|
||||
if (err)
|
||||
goto remove;
|
||||
|
||||
/*
|
||||
* Enable runtime PM for this card
|
||||
*/
|
||||
pm_runtime_enable(&card->dev);
|
||||
/*
|
||||
* Enable runtime PM for this card
|
||||
*/
|
||||
pm_runtime_enable(&card->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* The number of functions on the card is encoded inside
|
||||
|
@ -745,9 +763,10 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr)
|
|||
goto remove;
|
||||
|
||||
/*
|
||||
* Enable Runtime PM for this func
|
||||
* Enable Runtime PM for this func (if supported)
|
||||
*/
|
||||
pm_runtime_enable(&card->sdio_func[i]->dev);
|
||||
if (host->caps & MMC_CAP_POWER_OFF_CARD)
|
||||
pm_runtime_enable(&card->sdio_func[i]->dev);
|
||||
}
|
||||
|
||||
mmc_release_host(host);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
|
||||
#include "sdio_cis.h"
|
||||
|
@ -132,9 +133,11 @@ static int sdio_bus_probe(struct device *dev)
|
|||
* it should call pm_runtime_put_noidle() in its probe routine and
|
||||
* pm_runtime_get_noresume() in its remove routine.
|
||||
*/
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set the default block size so the driver is sure it's something
|
||||
* sensible. */
|
||||
|
@ -151,7 +154,8 @@ static int sdio_bus_probe(struct device *dev)
|
|||
return 0;
|
||||
|
||||
disable_runtimepm:
|
||||
pm_runtime_put_noidle(dev);
|
||||
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
|
||||
pm_runtime_put_noidle(dev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
@ -160,12 +164,14 @@ static int sdio_bus_remove(struct device *dev)
|
|||
{
|
||||
struct sdio_driver *drv = to_sdio_driver(dev->driver);
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
/* Make sure card is powered before invoking ->remove() */
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) {
|
||||
ret = pm_runtime_get_sync(dev);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
drv->remove(func);
|
||||
|
||||
|
@ -178,10 +184,12 @@ static int sdio_bus_remove(struct device *dev)
|
|||
}
|
||||
|
||||
/* First, undo the increment made directly above */
|
||||
pm_runtime_put_noidle(dev);
|
||||
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
|
||||
pm_runtime_put_noidle(dev);
|
||||
|
||||
/* Then undo the runtime PM settings in sdio_bus_probe() */
|
||||
pm_runtime_put_noidle(dev);
|
||||
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
|
||||
pm_runtime_put_noidle(dev);
|
||||
|
||||
out:
|
||||
return ret;
|
||||
|
@ -191,6 +199,8 @@ out:
|
|||
|
||||
static int sdio_bus_pm_prepare(struct device *dev)
|
||||
{
|
||||
struct sdio_func *func = dev_to_sdio_func(dev);
|
||||
|
||||
/*
|
||||
* Resume an SDIO device which was suspended at run time at this
|
||||
* point, in order to allow standard SDIO suspend/resume paths
|
||||
|
@ -212,7 +222,8 @@ static int sdio_bus_pm_prepare(struct device *dev)
|
|||
* since there is little point in failing system suspend if a
|
||||
* device can't be resumed.
|
||||
*/
|
||||
pm_runtime_resume(dev);
|
||||
if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
|
||||
pm_runtime_resume(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1002,7 +1002,7 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
|
|||
* Monitor a 0->1 transition first
|
||||
*/
|
||||
if (mmc_slot(host).features & HSMMC_HAS_UPDATED_RESET) {
|
||||
while ((!(OMAP_HSMMC_READ(host, SYSCTL) & bit))
|
||||
while ((!(OMAP_HSMMC_READ(host->base, SYSCTL) & bit))
|
||||
&& (i++ < limit))
|
||||
cpu_relax();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/sdhci-pltfm.h>
|
||||
#include <mach/hardware.h>
|
||||
#include "sdhci.h"
|
||||
#include "sdhci-pltfm.h"
|
||||
#include "sdhci-esdhc.h"
|
||||
|
@ -112,6 +113,13 @@ static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pd
|
|||
clk_enable(clk);
|
||||
pltfm_host->clk = clk;
|
||||
|
||||
if (cpu_is_mx35() || cpu_is_mx51())
|
||||
host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
|
||||
|
||||
/* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
|
||||
if (cpu_is_mx25() || cpu_is_mx35())
|
||||
host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -133,10 +141,8 @@ static struct sdhci_ops sdhci_esdhc_ops = {
|
|||
};
|
||||
|
||||
struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
|
||||
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_NO_MULTIBLOCK
|
||||
| SDHCI_QUIRK_BROKEN_ADMA,
|
||||
.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
|
||||
/* ADMA has issues. Might be fixable */
|
||||
/* NO_MULTIBLOCK might be MX35 only (Errata: ENGcm07207) */
|
||||
.ops = &sdhci_esdhc_ops,
|
||||
.init = esdhc_pltfm_init,
|
||||
.exit = esdhc_pltfm_exit,
|
||||
|
|
|
@ -149,11 +149,11 @@ static const struct sdhci_pci_fixes sdhci_cafe = {
|
|||
* ADMA operation is disabled for Moorestown platform due to
|
||||
* hardware bugs.
|
||||
*/
|
||||
static int mrst_hc1_probe(struct sdhci_pci_chip *chip)
|
||||
static int mrst_hc_probe(struct sdhci_pci_chip *chip)
|
||||
{
|
||||
/*
|
||||
* slots number is fixed here for MRST as SDIO3 is never used and has
|
||||
* hardware bugs.
|
||||
* slots number is fixed here for MRST as SDIO3/5 are never used and
|
||||
* have hardware bugs.
|
||||
*/
|
||||
chip->num_slots = 1;
|
||||
return 0;
|
||||
|
@ -163,9 +163,9 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc0 = {
|
|||
.quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
|
||||
};
|
||||
|
||||
static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1 = {
|
||||
static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = {
|
||||
.quirks = SDHCI_QUIRK_BROKEN_ADMA | SDHCI_QUIRK_NO_HISPD_BIT,
|
||||
.probe = mrst_hc1_probe,
|
||||
.probe = mrst_hc_probe,
|
||||
};
|
||||
|
||||
static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = {
|
||||
|
@ -538,7 +538,15 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
|
|||
.device = PCI_DEVICE_ID_INTEL_MRST_SD1,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = (kernel_ulong_t)&sdhci_intel_mrst_hc1,
|
||||
.driver_data = (kernel_ulong_t)&sdhci_intel_mrst_hc1_hc2,
|
||||
},
|
||||
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_INTEL,
|
||||
.device = PCI_DEVICE_ID_INTEL_MRST_SD2,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = (kernel_ulong_t)&sdhci_intel_mrst_hc1_hc2,
|
||||
},
|
||||
|
||||
{
|
||||
|
@ -637,6 +645,7 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
|
|||
{
|
||||
struct sdhci_pci_chip *chip;
|
||||
struct sdhci_pci_slot *slot;
|
||||
mmc_pm_flag_t slot_pm_flags;
|
||||
mmc_pm_flag_t pm_flags = 0;
|
||||
int i, ret;
|
||||
|
||||
|
@ -657,7 +666,11 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
|
|||
return ret;
|
||||
}
|
||||
|
||||
pm_flags |= slot->host->mmc->pm_flags;
|
||||
slot_pm_flags = slot->host->mmc->pm_flags;
|
||||
if (slot_pm_flags & MMC_PM_WAKE_SDIO_IRQ)
|
||||
sdhci_enable_irq_wakeups(slot->host);
|
||||
|
||||
pm_flags |= slot_pm_flags;
|
||||
}
|
||||
|
||||
if (chip->fixes && chip->fixes->suspend) {
|
||||
|
@ -671,8 +684,10 @@ static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
|
|||
|
||||
pci_save_state(pdev);
|
||||
if (pm_flags & MMC_PM_KEEP_POWER) {
|
||||
if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
|
||||
if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
|
||||
pci_pme_active(pdev, true);
|
||||
pci_enable_wake(pdev, PCI_D3hot, 1);
|
||||
}
|
||||
pci_set_power_state(pdev, PCI_D3hot);
|
||||
} else {
|
||||
pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
|
||||
|
|
|
@ -141,6 +141,10 @@ static int __devinit sdhci_pxa_probe(struct platform_device *pdev)
|
|||
if (pdata->quirks)
|
||||
host->quirks |= pdata->quirks;
|
||||
|
||||
/* If slot design supports 8 bit data, indicate this to MMC. */
|
||||
if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
|
||||
host->mmc->caps |= MMC_CAP_8_BIT_DATA;
|
||||
|
||||
ret = sdhci_add_host(host);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add host\n");
|
||||
|
|
|
@ -1185,18 +1185,32 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
|||
if (host->ops->platform_send_init_74_clocks)
|
||||
host->ops->platform_send_init_74_clocks(host, ios->power_mode);
|
||||
|
||||
/*
|
||||
* If your platform has 8-bit width support but is not a v3 controller,
|
||||
* or if it requires special setup code, you should implement that in
|
||||
* platform_8bit_width().
|
||||
*/
|
||||
if (host->ops->platform_8bit_width)
|
||||
host->ops->platform_8bit_width(host, ios->bus_width);
|
||||
else {
|
||||
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
|
||||
if (ios->bus_width == MMC_BUS_WIDTH_8) {
|
||||
ctrl &= ~SDHCI_CTRL_4BITBUS;
|
||||
if (host->version >= SDHCI_SPEC_300)
|
||||
ctrl |= SDHCI_CTRL_8BITBUS;
|
||||
} else {
|
||||
if (host->version >= SDHCI_SPEC_300)
|
||||
ctrl &= ~SDHCI_CTRL_8BITBUS;
|
||||
if (ios->bus_width == MMC_BUS_WIDTH_4)
|
||||
ctrl |= SDHCI_CTRL_4BITBUS;
|
||||
else
|
||||
ctrl &= ~SDHCI_CTRL_4BITBUS;
|
||||
}
|
||||
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
|
||||
}
|
||||
|
||||
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
|
||||
|
||||
if (ios->bus_width == MMC_BUS_WIDTH_8)
|
||||
ctrl |= SDHCI_CTRL_8BITBUS;
|
||||
else
|
||||
ctrl &= ~SDHCI_CTRL_8BITBUS;
|
||||
|
||||
if (ios->bus_width == MMC_BUS_WIDTH_4)
|
||||
ctrl |= SDHCI_CTRL_4BITBUS;
|
||||
else
|
||||
ctrl &= ~SDHCI_CTRL_4BITBUS;
|
||||
|
||||
if ((ios->timing == MMC_TIMING_SD_HS ||
|
||||
ios->timing == MMC_TIMING_MMC_HS)
|
||||
&& !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT))
|
||||
|
@ -1681,6 +1695,16 @@ int sdhci_resume_host(struct sdhci_host *host)
|
|||
|
||||
EXPORT_SYMBOL_GPL(sdhci_resume_host);
|
||||
|
||||
void sdhci_enable_irq_wakeups(struct sdhci_host *host)
|
||||
{
|
||||
u8 val;
|
||||
val = sdhci_readb(host, SDHCI_WAKE_UP_CONTROL);
|
||||
val |= SDHCI_WAKE_ON_INT;
|
||||
sdhci_writeb(host, val, SDHCI_WAKE_UP_CONTROL);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL_GPL(sdhci_enable_irq_wakeups);
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
/*****************************************************************************\
|
||||
|
@ -1845,11 +1869,19 @@ int sdhci_add_host(struct sdhci_host *host)
|
|||
mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_300;
|
||||
else
|
||||
mmc->f_min = host->max_clk / SDHCI_MAX_DIV_SPEC_200;
|
||||
|
||||
mmc->f_max = host->max_clk;
|
||||
mmc->caps |= MMC_CAP_SDIO_IRQ;
|
||||
|
||||
/*
|
||||
* A controller may support 8-bit width, but the board itself
|
||||
* might not have the pins brought out. Boards that support
|
||||
* 8-bit width must set "mmc->caps |= MMC_CAP_8_BIT_DATA;" in
|
||||
* their platform code before calling sdhci_add_host(), and we
|
||||
* won't assume 8-bit width for hosts without that CAP.
|
||||
*/
|
||||
if (!(host->quirks & SDHCI_QUIRK_FORCE_1_BIT_DATA))
|
||||
mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
|
||||
mmc->caps |= MMC_CAP_4_BIT_DATA;
|
||||
|
||||
if (caps & SDHCI_CAN_DO_HISPD)
|
||||
mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
#define SDHCI_CTRL_ADMA1 0x08
|
||||
#define SDHCI_CTRL_ADMA32 0x10
|
||||
#define SDHCI_CTRL_ADMA64 0x18
|
||||
#define SDHCI_CTRL_8BITBUS 0x20
|
||||
#define SDHCI_CTRL_8BITBUS 0x20
|
||||
|
||||
#define SDHCI_POWER_CONTROL 0x29
|
||||
#define SDHCI_POWER_ON 0x01
|
||||
|
@ -87,6 +87,9 @@
|
|||
#define SDHCI_BLOCK_GAP_CONTROL 0x2A
|
||||
|
||||
#define SDHCI_WAKE_UP_CONTROL 0x2B
|
||||
#define SDHCI_WAKE_ON_INT 0x01
|
||||
#define SDHCI_WAKE_ON_INSERT 0x02
|
||||
#define SDHCI_WAKE_ON_REMOVE 0x04
|
||||
|
||||
#define SDHCI_CLOCK_CONTROL 0x2C
|
||||
#define SDHCI_DIVIDER_SHIFT 8
|
||||
|
@ -152,6 +155,7 @@
|
|||
#define SDHCI_CLOCK_BASE_SHIFT 8
|
||||
#define SDHCI_MAX_BLOCK_MASK 0x00030000
|
||||
#define SDHCI_MAX_BLOCK_SHIFT 16
|
||||
#define SDHCI_CAN_DO_8BIT 0x00040000
|
||||
#define SDHCI_CAN_DO_ADMA2 0x00080000
|
||||
#define SDHCI_CAN_DO_ADMA1 0x00100000
|
||||
#define SDHCI_CAN_DO_HISPD 0x00200000
|
||||
|
@ -212,6 +216,8 @@ struct sdhci_ops {
|
|||
unsigned int (*get_max_clock)(struct sdhci_host *host);
|
||||
unsigned int (*get_min_clock)(struct sdhci_host *host);
|
||||
unsigned int (*get_timeout_clock)(struct sdhci_host *host);
|
||||
int (*platform_8bit_width)(struct sdhci_host *host,
|
||||
int width);
|
||||
void (*platform_send_init_74_clocks)(struct sdhci_host *host,
|
||||
u8 power_mode);
|
||||
unsigned int (*get_ro)(struct sdhci_host *host);
|
||||
|
@ -317,6 +323,7 @@ extern void sdhci_remove_host(struct sdhci_host *host, int dead);
|
|||
#ifdef CONFIG_PM
|
||||
extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state);
|
||||
extern int sdhci_resume_host(struct sdhci_host *host);
|
||||
extern void sdhci_enable_irq_wakeups(struct sdhci_host *host);
|
||||
#endif
|
||||
|
||||
#endif /* __SDHCI_HW_H */
|
||||
|
|
|
@ -425,7 +425,7 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
|
|||
struct usb_device *usb_dev = interface_to_usbdev(intf);
|
||||
struct mmc_host *mmc;
|
||||
struct ushc_data *ushc;
|
||||
int ret = -ENOMEM;
|
||||
int ret;
|
||||
|
||||
mmc = mmc_alloc_host(sizeof(struct ushc_data), &intf->dev);
|
||||
if (mmc == NULL)
|
||||
|
@ -462,11 +462,15 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
|
|||
mmc->max_blk_count = 511;
|
||||
|
||||
ushc->int_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (ushc->int_urb == NULL)
|
||||
if (ushc->int_urb == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
ushc->int_data = kzalloc(sizeof(struct ushc_int_data), GFP_KERNEL);
|
||||
if (ushc->int_data == NULL)
|
||||
if (ushc->int_data == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
usb_fill_int_urb(ushc->int_urb, ushc->usb_dev,
|
||||
usb_rcvintpipe(usb_dev,
|
||||
intf->cur_altsetting->endpoint[0].desc.bEndpointAddress),
|
||||
|
@ -475,11 +479,15 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
|
|||
intf->cur_altsetting->endpoint[0].desc.bInterval);
|
||||
|
||||
ushc->cbw_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (ushc->cbw_urb == NULL)
|
||||
if (ushc->cbw_urb == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
ushc->cbw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL);
|
||||
if (ushc->cbw == NULL)
|
||||
if (ushc->cbw == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
ushc->cbw->signature = USHC_CBW_SIGNATURE;
|
||||
|
||||
usb_fill_bulk_urb(ushc->cbw_urb, ushc->usb_dev, usb_sndbulkpipe(usb_dev, 2),
|
||||
|
@ -487,15 +495,21 @@ static int ushc_probe(struct usb_interface *intf, const struct usb_device_id *id
|
|||
cbw_callback, ushc);
|
||||
|
||||
ushc->data_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (ushc->data_urb == NULL)
|
||||
if (ushc->data_urb == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ushc->csw_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||
if (ushc->csw_urb == NULL)
|
||||
if (ushc->csw_urb == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
ushc->csw = kzalloc(sizeof(struct ushc_cbw), GFP_KERNEL);
|
||||
if (ushc->csw == NULL)
|
||||
if (ushc->csw == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
usb_fill_bulk_urb(ushc->csw_urb, ushc->usb_dev, usb_rcvbulkpipe(usb_dev, 6),
|
||||
ushc->csw, sizeof(struct ushc_csw),
|
||||
csw_callback, ushc);
|
||||
|
|
|
@ -787,16 +787,15 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
|
|||
* erased, so it became unstable and corrupted, and should be
|
||||
* erased.
|
||||
*/
|
||||
return 0;
|
||||
err = 0;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
goto out_unlock;
|
||||
|
||||
if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) {
|
||||
mutex_unlock(&ubi->buf_mutex);
|
||||
return 0;
|
||||
}
|
||||
if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size))
|
||||
goto out_unlock;
|
||||
|
||||
ubi_err("PEB %d contains corrupted VID header, and the data does not "
|
||||
"contain all 0xFF, this may be a non-UBI PEB or a severe VID "
|
||||
|
@ -806,8 +805,11 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
|
|||
pnum, ubi->leb_start, ubi->leb_size);
|
||||
ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
|
||||
ubi->peb_buf1, ubi->leb_size, 1);
|
||||
err = 1;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&ubi->buf_mutex);
|
||||
return 1;
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2543,10 +2543,10 @@ config PCH_GBE
|
|||
depends on PCI
|
||||
select MII
|
||||
---help---
|
||||
This is a gigabit ethernet driver for Topcliff PCH.
|
||||
Topcliff PCH is the platform controller hub that is used in Intel's
|
||||
This is a gigabit ethernet driver for EG20T PCH.
|
||||
EG20T PCH is the platform controller hub that is used in Intel's
|
||||
general embedded platform.
|
||||
Topcliff PCH has Gigabit Ethernet interface.
|
||||
EG20T PCH has Gigabit Ethernet interface.
|
||||
Using this interface, it is able to access system devices connected
|
||||
to Gigabit Ethernet.
|
||||
This driver enables Gigabit Ethernet function.
|
||||
|
@ -2945,6 +2945,18 @@ source "drivers/s390/net/Kconfig"
|
|||
|
||||
source "drivers/net/caif/Kconfig"
|
||||
|
||||
config TILE_NET
|
||||
tristate "Tilera GBE/XGBE network driver support"
|
||||
depends on TILE
|
||||
default y
|
||||
select CRC32
|
||||
help
|
||||
This is a standard Linux network device driver for the
|
||||
on-chip Tilera Gigabit Ethernet and XAUI interfaces.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called tile_net.
|
||||
|
||||
config XEN_NETDEV_FRONTEND
|
||||
tristate "Xen network device frontend driver"
|
||||
depends on XEN
|
||||
|
|
|
@ -301,3 +301,4 @@ obj-$(CONFIG_CAIF) += caif/
|
|||
|
||||
obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
|
||||
obj-$(CONFIG_PCH_GBE) += pch_gbe/
|
||||
obj-$(CONFIG_TILE_NET) += tile/
|
||||
|
|
|
@ -155,10 +155,10 @@ static void au1000_enable_mac(struct net_device *dev, int force_reset)
|
|||
spin_lock_irqsave(&aup->lock, flags);
|
||||
|
||||
if (force_reset || (!aup->mac_enabled)) {
|
||||
writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
|
||||
writel(MAC_EN_CLOCK_ENABLE, aup->enable);
|
||||
au_sync_delay(2);
|
||||
writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
|
||||
| MAC_EN_CLOCK_ENABLE), &aup->enable);
|
||||
| MAC_EN_CLOCK_ENABLE), aup->enable);
|
||||
au_sync_delay(2);
|
||||
|
||||
aup->mac_enabled = 1;
|
||||
|
@ -503,9 +503,9 @@ static void au1000_reset_mac_unlocked(struct net_device *dev)
|
|||
|
||||
au1000_hard_stop(dev);
|
||||
|
||||
writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
|
||||
writel(MAC_EN_CLOCK_ENABLE, aup->enable);
|
||||
au_sync_delay(2);
|
||||
writel(0, &aup->enable);
|
||||
writel(0, aup->enable);
|
||||
au_sync_delay(2);
|
||||
|
||||
aup->tx_full = 0;
|
||||
|
@ -1119,7 +1119,7 @@ static int __devinit au1000_probe(struct platform_device *pdev)
|
|||
/* set a random MAC now in case platform_data doesn't provide one */
|
||||
random_ether_addr(dev->dev_addr);
|
||||
|
||||
writel(0, &aup->enable);
|
||||
writel(0, aup->enable);
|
||||
aup->mac_enabled = 0;
|
||||
|
||||
pd = pdev->dev.platform_data;
|
||||
|
|
|
@ -816,40 +816,48 @@ static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev)
|
|||
}
|
||||
|
||||
/*
|
||||
* Collect up to maxaddrs worth of a netdevice's unicast addresses into an
|
||||
* array of addrss pointers and return the number collected.
|
||||
* Collect up to maxaddrs worth of a netdevice's unicast addresses, starting
|
||||
* at a specified offset within the list, into an array of addrss pointers and
|
||||
* return the number collected.
|
||||
*/
|
||||
static inline int collect_netdev_uc_list_addrs(const struct net_device *dev,
|
||||
const u8 **addr,
|
||||
unsigned int maxaddrs)
|
||||
static inline unsigned int collect_netdev_uc_list_addrs(const struct net_device *dev,
|
||||
const u8 **addr,
|
||||
unsigned int offset,
|
||||
unsigned int maxaddrs)
|
||||
{
|
||||
unsigned int index = 0;
|
||||
unsigned int naddr = 0;
|
||||
const struct netdev_hw_addr *ha;
|
||||
|
||||
for_each_dev_addr(dev, ha) {
|
||||
addr[naddr++] = ha->addr;
|
||||
if (naddr >= maxaddrs)
|
||||
break;
|
||||
}
|
||||
for_each_dev_addr(dev, ha)
|
||||
if (index++ >= offset) {
|
||||
addr[naddr++] = ha->addr;
|
||||
if (naddr >= maxaddrs)
|
||||
break;
|
||||
}
|
||||
return naddr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Collect up to maxaddrs worth of a netdevice's multicast addresses into an
|
||||
* array of addrss pointers and return the number collected.
|
||||
* Collect up to maxaddrs worth of a netdevice's multicast addresses, starting
|
||||
* at a specified offset within the list, into an array of addrss pointers and
|
||||
* return the number collected.
|
||||
*/
|
||||
static inline int collect_netdev_mc_list_addrs(const struct net_device *dev,
|
||||
const u8 **addr,
|
||||
unsigned int maxaddrs)
|
||||
static inline unsigned int collect_netdev_mc_list_addrs(const struct net_device *dev,
|
||||
const u8 **addr,
|
||||
unsigned int offset,
|
||||
unsigned int maxaddrs)
|
||||
{
|
||||
unsigned int index = 0;
|
||||
unsigned int naddr = 0;
|
||||
const struct netdev_hw_addr *ha;
|
||||
|
||||
netdev_for_each_mc_addr(ha, dev) {
|
||||
addr[naddr++] = ha->addr;
|
||||
if (naddr >= maxaddrs)
|
||||
break;
|
||||
}
|
||||
netdev_for_each_mc_addr(ha, dev)
|
||||
if (index++ >= offset) {
|
||||
addr[naddr++] = ha->addr;
|
||||
if (naddr >= maxaddrs)
|
||||
break;
|
||||
}
|
||||
return naddr;
|
||||
}
|
||||
|
||||
|
@ -862,16 +870,20 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
|
|||
u64 mhash = 0;
|
||||
u64 uhash = 0;
|
||||
bool free = true;
|
||||
u16 filt_idx[7];
|
||||
unsigned int offset, naddr;
|
||||
const u8 *addr[7];
|
||||
int ret, naddr = 0;
|
||||
int ret;
|
||||
const struct port_info *pi = netdev_priv(dev);
|
||||
|
||||
/* first do the secondary unicast addresses */
|
||||
naddr = collect_netdev_uc_list_addrs(dev, addr, ARRAY_SIZE(addr));
|
||||
if (naddr > 0) {
|
||||
for (offset = 0; ; offset += naddr) {
|
||||
naddr = collect_netdev_uc_list_addrs(dev, addr, offset,
|
||||
ARRAY_SIZE(addr));
|
||||
if (naddr == 0)
|
||||
break;
|
||||
|
||||
ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
|
||||
naddr, addr, filt_idx, &uhash, sleep);
|
||||
naddr, addr, NULL, &uhash, sleep);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -879,12 +891,17 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
|
|||
}
|
||||
|
||||
/* next set up the multicast addresses */
|
||||
naddr = collect_netdev_mc_list_addrs(dev, addr, ARRAY_SIZE(addr));
|
||||
if (naddr > 0) {
|
||||
for (offset = 0; ; offset += naddr) {
|
||||
naddr = collect_netdev_mc_list_addrs(dev, addr, offset,
|
||||
ARRAY_SIZE(addr));
|
||||
if (naddr == 0)
|
||||
break;
|
||||
|
||||
ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
|
||||
naddr, addr, filt_idx, &mhash, sleep);
|
||||
naddr, addr, NULL, &mhash, sleep);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
free = false;
|
||||
}
|
||||
|
||||
return t4vf_set_addr_hash(pi->adapter, pi->viid, uhash != 0,
|
||||
|
|
|
@ -1014,48 +1014,72 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
|
|||
unsigned int naddr, const u8 **addr, u16 *idx,
|
||||
u64 *hash, bool sleep_ok)
|
||||
{
|
||||
int i, ret;
|
||||
int offset, ret = 0;
|
||||
unsigned nfilters = 0;
|
||||
unsigned int rem = naddr;
|
||||
struct fw_vi_mac_cmd cmd, rpl;
|
||||
struct fw_vi_mac_exact *p;
|
||||
size_t len16;
|
||||
|
||||
if (naddr > ARRAY_SIZE(cmd.u.exact))
|
||||
if (naddr > FW_CLS_TCAM_NUM_ENTRIES)
|
||||
return -EINVAL;
|
||||
len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
|
||||
u.exact[naddr]), 16);
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
|
||||
FW_CMD_REQUEST |
|
||||
FW_CMD_WRITE |
|
||||
(free ? FW_CMD_EXEC : 0) |
|
||||
FW_VI_MAC_CMD_VIID(viid));
|
||||
cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
|
||||
FW_CMD_LEN16(len16));
|
||||
for (offset = 0; offset < naddr; /**/) {
|
||||
unsigned int fw_naddr = (rem < ARRAY_SIZE(cmd.u.exact)
|
||||
? rem
|
||||
: ARRAY_SIZE(cmd.u.exact));
|
||||
size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
|
||||
u.exact[fw_naddr]), 16);
|
||||
struct fw_vi_mac_exact *p;
|
||||
int i;
|
||||
|
||||
for (i = 0, p = cmd.u.exact; i < naddr; i++, p++) {
|
||||
p->valid_to_idx =
|
||||
cpu_to_be16(FW_VI_MAC_CMD_VALID |
|
||||
FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
|
||||
memcpy(p->macaddr, addr[i], sizeof(p->macaddr));
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
|
||||
FW_CMD_REQUEST |
|
||||
FW_CMD_WRITE |
|
||||
(free ? FW_CMD_EXEC : 0) |
|
||||
FW_VI_MAC_CMD_VIID(viid));
|
||||
cmd.freemacs_to_len16 =
|
||||
cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
|
||||
FW_CMD_LEN16(len16));
|
||||
|
||||
for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) {
|
||||
p->valid_to_idx = cpu_to_be16(
|
||||
FW_VI_MAC_CMD_VALID |
|
||||
FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
|
||||
memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
|
||||
}
|
||||
|
||||
|
||||
ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl,
|
||||
sleep_ok);
|
||||
if (ret && ret != -ENOMEM)
|
||||
break;
|
||||
|
||||
for (i = 0, p = rpl.u.exact; i < fw_naddr; i++, p++) {
|
||||
u16 index = FW_VI_MAC_CMD_IDX_GET(
|
||||
be16_to_cpu(p->valid_to_idx));
|
||||
|
||||
if (idx)
|
||||
idx[offset+i] =
|
||||
(index >= FW_CLS_TCAM_NUM_ENTRIES
|
||||
? 0xffff
|
||||
: index);
|
||||
if (index < FW_CLS_TCAM_NUM_ENTRIES)
|
||||
nfilters++;
|
||||
else if (hash)
|
||||
*hash |= (1ULL << hash_mac_addr(addr[offset+i]));
|
||||
}
|
||||
|
||||
free = false;
|
||||
offset += fw_naddr;
|
||||
rem -= fw_naddr;
|
||||
}
|
||||
|
||||
ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl, sleep_ok);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0, p = rpl.u.exact; i < naddr; i++, p++) {
|
||||
u16 index = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx));
|
||||
|
||||
if (idx)
|
||||
idx[i] = (index >= FW_CLS_TCAM_NUM_ENTRIES
|
||||
? 0xffff
|
||||
: index);
|
||||
if (index < FW_CLS_TCAM_NUM_ENTRIES)
|
||||
ret++;
|
||||
else if (hash)
|
||||
*hash |= (1 << hash_mac_addr(addr[i]));
|
||||
}
|
||||
/*
|
||||
* If there were no errors or we merely ran out of room in our MAC
|
||||
* address arena, return the number of filters actually written.
|
||||
*/
|
||||
if (ret == 0 || ret == -ENOMEM)
|
||||
ret = nfilters;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -400,6 +400,7 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
|
|||
skb_arr_rq1[index] = netdev_alloc_skb(dev,
|
||||
EHEA_L_PKT_SIZE);
|
||||
if (!skb_arr_rq1[index]) {
|
||||
ehea_info("Unable to allocate enough skb in the array\n");
|
||||
pr->rq1_skba.os_skbs = fill_wqes - i;
|
||||
break;
|
||||
}
|
||||
|
@ -422,13 +423,20 @@ static void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
|
|||
struct net_device *dev = pr->port->netdev;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pr->rq1_skba.len; i++) {
|
||||
if (nr_rq1a > pr->rq1_skba.len) {
|
||||
ehea_error("NR_RQ1A bigger than skb array len\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < nr_rq1a; i++) {
|
||||
skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
|
||||
if (!skb_arr_rq1[i])
|
||||
if (!skb_arr_rq1[i]) {
|
||||
ehea_info("No enough memory to allocate skb array\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Ring doorbell */
|
||||
ehea_update_rq1a(pr->qp, nr_rq1a);
|
||||
ehea_update_rq1a(pr->qp, i);
|
||||
}
|
||||
|
||||
static int ehea_refill_rq_def(struct ehea_port_res *pr,
|
||||
|
@ -735,8 +743,10 @@ static int ehea_proc_rwqes(struct net_device *dev,
|
|||
|
||||
skb = netdev_alloc_skb(dev,
|
||||
EHEA_L_PKT_SIZE);
|
||||
if (!skb)
|
||||
if (!skb) {
|
||||
ehea_info("Not enough memory to allocate skb\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
|
||||
cqe->num_bytes_transfered - 4);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 1999 - 2010 Intel Corporation.
|
||||
* Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
|
||||
* Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
|
||||
*
|
||||
* This code was derived from the Intel e1000e Linux driver.
|
||||
*
|
||||
|
@ -2464,8 +2464,8 @@ static void __exit pch_gbe_exit_module(void)
|
|||
module_init(pch_gbe_init_module);
|
||||
module_exit(pch_gbe_exit_module);
|
||||
|
||||
MODULE_DESCRIPTION("OKI semiconductor PCH Gigabit ethernet Driver");
|
||||
MODULE_AUTHOR("OKI semiconductor, <masa-korg@dsn.okisemi.com>");
|
||||
MODULE_DESCRIPTION("EG20T PCH Gigabit ethernet Driver");
|
||||
MODULE_AUTHOR("OKI SEMICONDUCTOR, <toshiharu-linux@dsn.okisemi.com>");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(DRV_VERSION);
|
||||
MODULE_DEVICE_TABLE(pci, pch_gbe_pcidev_id);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue