From b755706cd726e5d465c28c2cd64c618419034981 Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Wed, 7 Dec 2011 11:47:40 -0800 Subject: [PATCH 00001/10698] ARM: OMAP2+: board-generic: Add missing handle_irq callbacks The following commit: 6b2f55d7851aa358d3a99cff344c560c4967f042, is adding the support for the CONFIG_MULTI_IRQ_HANDLER but did not update all the machine descriptors supported in the DT board-generic.c file. It thus break the DT boot on OMAP3 and OMAP4 boards. Add the proper handle_irq callbacks for OMAP3 and OMAP4 generic machine descriptors. Signed-off-by: Benoit Cousson Acked-by: Marc Zyngier Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-generic.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 63b54163b993..e493877957c9 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -103,6 +104,7 @@ DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)") .map_io = omap242x_map_io, .init_early = omap2420_init_early, .init_irq = omap2_init_irq, + .handle_irq = omap2_intc_handle_irq, .init_machine = omap_generic_init, .timer = &omap2_timer, .dt_compat = omap242x_boards_compat, @@ -140,6 +142,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)") .map_io = omap3_map_io, .init_early = omap3430_init_early, .init_irq = omap3_init_irq, + .handle_irq = omap3_intc_handle_irq, .init_machine = omap3_init, .timer = &omap3_timer, .dt_compat = omap3_boards_compat, @@ -158,6 +161,7 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)") .map_io = omap4_map_io, .init_early = omap4430_init_early, .init_irq = gic_init_irq, + .handle_irq = gic_handle_irq, .init_machine = omap4_init, .timer = &omap4_timer, .dt_compat = omap4_boards_compat, -- GitLab From fb49b8c22dbb1c48b9f3906af1308c0fa4d7aa82 Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Tue, 6 Dec 2011 17:49:08 +0100 Subject: [PATCH 00002/10698] arm/dts: OMAP: Remove bootargs node from board files Since 3.2, the CONFIG_ARM_ATAG_DTB_COMPAT config allows an old bootloader to still use ATAG to provide cmdline. Remove chosen/bootargs from the DTS board files. Signed-off-by: Benoit Cousson Cc: Grant Likely Acked-by: Rob Herring Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3-beagle.dts | 9 --------- arch/arm/boot/dts/omap4-panda.dts | 9 --------- arch/arm/boot/dts/omap4-sdp.dts | 9 --------- 3 files changed, 27 deletions(-) diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts index 9486be62bcdd..9f72cd4cf308 100644 --- a/arch/arm/boot/dts/omap3-beagle.dts +++ b/arch/arm/boot/dts/omap3-beagle.dts @@ -13,15 +13,6 @@ / { model = "TI OMAP3 BeagleBoard"; compatible = "ti,omap3-beagle", "ti,omap3"; - /* - * Since the initial device tree board file does not create any - * devices (MMC, network...), the only way to boot is to provide a - * ramdisk. - */ - chosen { - bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug earlyprintk"; - }; - memory { device_type = "memory"; reg = <0x80000000 0x20000000>; /* 512 MB */ diff --git a/arch/arm/boot/dts/omap4-panda.dts b/arch/arm/boot/dts/omap4-panda.dts index c7026578ce7d..9755ad5917f8 100644 --- a/arch/arm/boot/dts/omap4-panda.dts +++ b/arch/arm/boot/dts/omap4-panda.dts @@ -13,15 +13,6 @@ / { model = "TI OMAP4 PandaBoard"; compatible = "ti,omap4-panda", "ti,omap4430", "ti,omap4"; - /* - * Since the initial device tree board file does not create any - * devices (MMC, network...), the only way to boot is to provide a - * ramdisk. - */ - chosen { - bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug"; - }; - memory { device_type = "memory"; reg = <0x80000000 0x40000000>; /* 1 GB */ diff --git a/arch/arm/boot/dts/omap4-sdp.dts b/arch/arm/boot/dts/omap4-sdp.dts index 066e28c90328..63c6b2b2bf42 100644 --- a/arch/arm/boot/dts/omap4-sdp.dts +++ b/arch/arm/boot/dts/omap4-sdp.dts @@ -13,15 +13,6 @@ / { model = "TI OMAP4 SDP board"; compatible = "ti,omap4-sdp", "ti,omap4430", "ti,omap4"; - /* - * Since the initial device tree board file does not create any - * devices (MMC, network...), the only way to boot is to provide a - * ramdisk. - */ - chosen { - bootargs = "root=/dev/ram0 rw console=ttyO2,115200n8 initrd=0x81600000,20M ramdisk_size=20480 no_console_suspend debug"; - }; - memory { device_type = "memory"; reg = <0x80000000 0x40000000>; /* 1 GB */ -- GitLab From 40c0591f0a349ec074357e05c6ab1a3bc951807c Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Thu, 1 Dec 2011 10:21:16 +0100 Subject: [PATCH 00003/10698] ARM: OMAP2+: kconfig: Enable devicetree by default for OMAP2+ systems devicetree will become the mandatory boot method for OMAP2+. In order to avoid cluttering the OMAP code with #ifdef CONFIG_OF, select USE_OF by default for every OMAP2+ systems. Enable PROC_DEVICETREE as well. Signed-off-by: Benoit Cousson Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/Kconfig | 1 - arch/arm/plat-omap/Kconfig | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig index b6625130831d..bdd5b68fba80 100644 --- a/arch/arm/mach-omap2/Kconfig +++ b/arch/arm/mach-omap2/Kconfig @@ -111,7 +111,6 @@ comment "OMAP Board Type" config MACH_OMAP_GENERIC bool "Generic OMAP2+ board" depends on ARCH_OMAP2PLUS - select USE_OF default y help Support for generic TI OMAP2+ boards using Flattened Device Tree. diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index aa59f4247dc5..734009a93857 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -24,6 +24,8 @@ config ARCH_OMAP2PLUS select CLKDEV_LOOKUP select GENERIC_IRQ_CHIP select OMAP_DM_TIMER + select USE_OF + select PROC_DEVICETREE help "Systems based on OMAP2, OMAP3 or OMAP4" -- GitLab From 50a01e6440020877c2f71bc5ac4d818d9b8f31c1 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 19 Dec 2011 15:50:14 +0530 Subject: [PATCH 00004/10698] ARM: OMAP2+: Make cpu_rev static global variable As part of omap revision code cleanup, make cpu_rev variable static global to the file (id.c). This is needed so we can split the SoC detection from SoC feature detection in the following patch. Also move omap3_cpuinfo function a bit as that will be shared by other omap3 like SoCs. Signed-off-by: Vaibhav Hiremath [tony@atomide.com: updated comments] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/id.c | 146 +++++++++++++++++++-------------------- 1 file changed, 72 insertions(+), 74 deletions(-) diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 6c5826605eae..752dcae8f78a 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -29,7 +29,7 @@ #include "control.h" static unsigned int omap_revision; - +static const char *cpu_rev; u32 omap_features; unsigned int omap_rev(void) @@ -166,6 +166,56 @@ static void __init omap24xx_check_revision(void) pr_info("\n"); } +#define OMAP3_SHOW_FEATURE(feat) \ + if (omap3_has_ ##feat()) \ + printk(#feat" "); + +static void __init omap3_cpuinfo(void) +{ + const char *cpu_name; + + /* + * OMAP3430 and OMAP3530 are assumed to be same. + * + * OMAP3525, OMAP3515 and OMAP3503 can be detected only based + * on available features. Upon detection, update the CPU id + * and CPU class bits. + */ + if (cpu_is_omap3630()) { + cpu_name = "OMAP3630"; + } else if (cpu_is_omap3517()) { + /* AM35xx devices */ + cpu_name = (omap3_has_sgx()) ? "AM3517" : "AM3505"; + } else if (cpu_is_ti816x()) { + cpu_name = "TI816X"; + } else if (cpu_is_am335x()) { + cpu_name = "AM335X"; + } else if (cpu_is_ti814x()) { + cpu_name = "TI814X"; + } else if (omap3_has_iva() && omap3_has_sgx()) { + /* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */ + cpu_name = "OMAP3430/3530"; + } else if (omap3_has_iva()) { + cpu_name = "OMAP3525"; + } else if (omap3_has_sgx()) { + cpu_name = "OMAP3515"; + } else { + cpu_name = "OMAP3503"; + } + + /* Print verbose information */ + pr_info("%s ES%s (", cpu_name, cpu_rev); + + OMAP3_SHOW_FEATURE(l2cache); + OMAP3_SHOW_FEATURE(iva); + OMAP3_SHOW_FEATURE(sgx); + OMAP3_SHOW_FEATURE(neon); + OMAP3_SHOW_FEATURE(isp); + OMAP3_SHOW_FEATURE(192mhz_clk); + + printk(")\n"); +} + #define OMAP3_CHECK_FEATURE(status,feat) \ if (((status & OMAP3_ ##feat## _MASK) \ >> OMAP3_ ##feat## _SHIFT) != FEAT_ ##feat## _NONE) { \ @@ -231,7 +281,7 @@ static void __init ti81xx_check_features(void) omap_features = OMAP3_HAS_NEON; } -static void __init omap3_check_revision(const char **cpu_rev) +static void __init omap3_check_revision(void) { u32 cpuid, idcode; u16 hawkeye; @@ -245,7 +295,7 @@ static void __init omap3_check_revision(const char **cpu_rev) cpuid = read_cpuid(CPUID_ID); if ((((cpuid >> 4) & 0xfff) == 0xc08) && ((cpuid & 0xf) == 0x0)) { omap_revision = OMAP3430_REV_ES1_0; - *cpu_rev = "1.0"; + cpu_rev = "1.0"; return; } @@ -266,26 +316,26 @@ static void __init omap3_check_revision(const char **cpu_rev) case 0: /* Take care of early samples */ case 1: omap_revision = OMAP3430_REV_ES2_0; - *cpu_rev = "2.0"; + cpu_rev = "2.0"; break; case 2: omap_revision = OMAP3430_REV_ES2_1; - *cpu_rev = "2.1"; + cpu_rev = "2.1"; break; case 3: omap_revision = OMAP3430_REV_ES3_0; - *cpu_rev = "3.0"; + cpu_rev = "3.0"; break; case 4: omap_revision = OMAP3430_REV_ES3_1; - *cpu_rev = "3.1"; + cpu_rev = "3.1"; break; case 7: /* FALLTHROUGH */ default: /* Use the latest known revision as default */ omap_revision = OMAP3430_REV_ES3_1_2; - *cpu_rev = "3.1.2"; + cpu_rev = "3.1.2"; } break; case 0xb868: @@ -298,13 +348,13 @@ static void __init omap3_check_revision(const char **cpu_rev) switch (rev) { case 0: omap_revision = OMAP3517_REV_ES1_0; - *cpu_rev = "1.0"; + cpu_rev = "1.0"; break; case 1: /* FALLTHROUGH */ default: omap_revision = OMAP3517_REV_ES1_1; - *cpu_rev = "1.1"; + cpu_rev = "1.1"; } break; case 0xb891: @@ -313,60 +363,60 @@ static void __init omap3_check_revision(const char **cpu_rev) switch(rev) { case 0: /* Take care of early samples */ omap_revision = OMAP3630_REV_ES1_0; - *cpu_rev = "1.0"; + cpu_rev = "1.0"; break; case 1: omap_revision = OMAP3630_REV_ES1_1; - *cpu_rev = "1.1"; + cpu_rev = "1.1"; break; case 2: /* FALLTHROUGH */ default: omap_revision = OMAP3630_REV_ES1_2; - *cpu_rev = "1.2"; + cpu_rev = "1.2"; } break; case 0xb81e: switch (rev) { case 0: omap_revision = TI8168_REV_ES1_0; - *cpu_rev = "1.0"; + cpu_rev = "1.0"; break; case 1: /* FALLTHROUGH */ default: omap_revision = TI8168_REV_ES1_1; - *cpu_rev = "1.1"; + cpu_rev = "1.1"; break; } break; case 0xb944: omap_revision = AM335X_REV_ES1_0; - *cpu_rev = "1.0"; + cpu_rev = "1.0"; case 0xb8f2: switch (rev) { case 0: /* FALLTHROUGH */ case 1: omap_revision = TI8148_REV_ES1_0; - *cpu_rev = "1.0"; + cpu_rev = "1.0"; break; case 2: omap_revision = TI8148_REV_ES2_0; - *cpu_rev = "2.0"; + cpu_rev = "2.0"; break; case 3: /* FALLTHROUGH */ default: omap_revision = TI8148_REV_ES2_1; - *cpu_rev = "2.1"; + cpu_rev = "2.1"; break; } break; default: /* Unknown default to latest silicon rev as default */ omap_revision = OMAP3630_REV_ES1_2; - *cpu_rev = "1.2"; + cpu_rev = "1.2"; pr_warn("Warning: unknown chip type; assuming OMAP3630ES1.2\n"); } } @@ -444,63 +494,11 @@ static void __init omap4_check_revision(void) ((omap_rev() >> 12) & 0xf), ((omap_rev() >> 8) & 0xf)); } -#define OMAP3_SHOW_FEATURE(feat) \ - if (omap3_has_ ##feat()) \ - printk(#feat" "); - -static void __init omap3_cpuinfo(const char *cpu_rev) -{ - const char *cpu_name; - - /* - * OMAP3430 and OMAP3530 are assumed to be same. - * - * OMAP3525, OMAP3515 and OMAP3503 can be detected only based - * on available features. Upon detection, update the CPU id - * and CPU class bits. - */ - if (cpu_is_omap3630()) { - cpu_name = "OMAP3630"; - } else if (cpu_is_omap3517()) { - /* AM35xx devices */ - cpu_name = (omap3_has_sgx()) ? "AM3517" : "AM3505"; - } else if (cpu_is_ti816x()) { - cpu_name = "TI816X"; - } else if (cpu_is_am335x()) { - cpu_name = "AM335X"; - } else if (cpu_is_ti814x()) { - cpu_name = "TI814X"; - } else if (omap3_has_iva() && omap3_has_sgx()) { - /* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */ - cpu_name = "OMAP3430/3530"; - } else if (omap3_has_iva()) { - cpu_name = "OMAP3525"; - } else if (omap3_has_sgx()) { - cpu_name = "OMAP3515"; - } else { - cpu_name = "OMAP3503"; - } - - /* Print verbose information */ - pr_info("%s ES%s (", cpu_name, cpu_rev); - - OMAP3_SHOW_FEATURE(l2cache); - OMAP3_SHOW_FEATURE(iva); - OMAP3_SHOW_FEATURE(sgx); - OMAP3_SHOW_FEATURE(neon); - OMAP3_SHOW_FEATURE(isp); - OMAP3_SHOW_FEATURE(192mhz_clk); - - printk(")\n"); -} - /* * Try to detect the exact revision of the omap we're running on */ void __init omap2_check_revision(void) { - const char *cpu_rev; - /* * At this point we have an idea about the processor revision set * earlier with omap2_set_globals_tap(). @@ -508,7 +506,7 @@ void __init omap2_check_revision(void) if (cpu_is_omap24xx()) { omap24xx_check_revision(); } else if (cpu_is_omap34xx()) { - omap3_check_revision(&cpu_rev); + omap3_check_revision(); /* TI81XX doesn't have feature register */ if (!cpu_is_ti81xx()) @@ -516,7 +514,7 @@ void __init omap2_check_revision(void) else ti81xx_check_features(); - omap3_cpuinfo(cpu_rev); + omap3_cpuinfo(); return; } else if (cpu_is_omap44xx()) { omap4_check_revision(); -- GitLab From 4de34f3572882fd0a0e655cda494577c22663215 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Mon, 19 Dec 2011 15:50:15 +0530 Subject: [PATCH 00005/10698] ARM: OMAP2+: split omap2/3/4_check_revision function We need to detect the SoC revision early, but the SoC feature detection can be done later on. In order to allow further clean-up later on, this patch separates the SoC revision check from the SoC feature check. This patch doesn't change functionality or behavior of the code execution; it barely cleans up the code and splits into SoC specific implementation for Rev ID and feature detection. Signed-off-by: Vaibhav Hiremath [tony@atomide.com: updated comments] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/id.c | 46 ++++++--------------------- arch/arm/mach-omap2/io.c | 9 +++++- arch/arm/plat-omap/include/plat/cpu.h | 7 +++- 3 files changed, 23 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c index 752dcae8f78a..92e4d5558b1e 100644 --- a/arch/arm/mach-omap2/id.c +++ b/arch/arm/mach-omap2/id.c @@ -112,7 +112,7 @@ void omap_get_die_id(struct omap_die_id *odi) odi->id_3 = read_tap_reg(OMAP_TAP_DIE_ID_3); } -static void __init omap24xx_check_revision(void) +void __init omap2xxx_check_revision(void) { int i, j; u32 idcode, prod_id; @@ -222,7 +222,7 @@ static void __init omap3_cpuinfo(void) omap_features |= OMAP3_HAS_ ##feat; \ } -static void __init omap3_check_features(void) +void __init omap3xxx_check_features(void) { u32 status; @@ -249,9 +249,11 @@ static void __init omap3_check_features(void) * TODO: Get additional info (where applicable) * e.g. Size of L2 cache. */ + + omap3_cpuinfo(); } -static void __init omap4_check_features(void) +void __init omap4xxx_check_features(void) { u32 si_type; @@ -276,12 +278,13 @@ static void __init omap4_check_features(void) } } -static void __init ti81xx_check_features(void) +void __init ti81xx_check_features(void) { omap_features = OMAP3_HAS_NEON; + omap3_cpuinfo(); } -static void __init omap3_check_revision(void) +void __init omap3xxx_check_revision(void) { u32 cpuid, idcode; u16 hawkeye; @@ -421,7 +424,7 @@ static void __init omap3_check_revision(void) } } -static void __init omap4_check_revision(void) +void __init omap4xxx_check_revision(void) { u32 idcode; u16 hawkeye; @@ -494,37 +497,6 @@ static void __init omap4_check_revision(void) ((omap_rev() >> 12) & 0xf), ((omap_rev() >> 8) & 0xf)); } -/* - * Try to detect the exact revision of the omap we're running on - */ -void __init omap2_check_revision(void) -{ - /* - * At this point we have an idea about the processor revision set - * earlier with omap2_set_globals_tap(). - */ - if (cpu_is_omap24xx()) { - omap24xx_check_revision(); - } else if (cpu_is_omap34xx()) { - omap3_check_revision(); - - /* TI81XX doesn't have feature register */ - if (!cpu_is_ti81xx()) - omap3_check_features(); - else - ti81xx_check_features(); - - omap3_cpuinfo(); - return; - } else if (cpu_is_omap44xx()) { - omap4_check_revision(); - omap4_check_features(); - return; - } else { - pr_err("OMAP revision unknown, please fix!\n"); - } -} - /* * Set up things for map_io and processor detection later on. Gets called * pretty much first thing from board init. For multi-omap, this gets diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 73d617f0dc4a..58bd138e5a98 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -342,7 +342,6 @@ static int _set_hwmod_postsetup_state(struct omap_hwmod *oh, void *data) static void __init omap_common_init_early(void) { - omap2_check_revision(); omap_init_consistent_dma_size(); } @@ -383,6 +382,7 @@ static void __init omap_hwmod_init_postsetup(void) void __init omap2420_init_early(void) { omap2_set_globals_242x(); + omap2xxx_check_revision(); omap_common_init_early(); omap2xxx_voltagedomains_init(); omap242x_powerdomains_init(); @@ -395,6 +395,7 @@ void __init omap2420_init_early(void) void __init omap2430_init_early(void) { omap2_set_globals_243x(); + omap2xxx_check_revision(); omap_common_init_early(); omap2xxx_voltagedomains_init(); omap243x_powerdomains_init(); @@ -413,6 +414,8 @@ void __init omap2430_init_early(void) void __init omap3_init_early(void) { omap2_set_globals_3xxx(); + omap3xxx_check_revision(); + omap3xxx_check_features(); omap_common_init_early(); omap3xxx_voltagedomains_init(); omap3xxx_powerdomains_init(); @@ -445,6 +448,8 @@ void __init am35xx_init_early(void) void __init ti81xx_init_early(void) { omap2_set_globals_ti81xx(); + omap3xxx_check_revision(); + ti81xx_check_features(); omap_common_init_early(); omap3xxx_voltagedomains_init(); omap3xxx_powerdomains_init(); @@ -459,6 +464,8 @@ void __init ti81xx_init_early(void) void __init omap4430_init_early(void) { omap2_set_globals_443x(); + omap4xxx_check_revision(); + omap4xxx_check_features(); omap_common_init_early(); omap44xx_voltagedomains_init(); omap44xx_powerdomains_init(); diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h index 6b51086fce18..428ccb12d168 100644 --- a/arch/arm/plat-omap/include/plat/cpu.h +++ b/arch/arm/plat-omap/include/plat/cpu.h @@ -451,7 +451,12 @@ IS_OMAP_TYPE(3517, 0x3517) #define OMAP447X_CLASS 0x44700044 #define OMAP4470_REV_ES1_0 (OMAP447X_CLASS | (0x10 << 8)) -void omap2_check_revision(void); +void omap2xxx_check_revision(void); +void omap3xxx_check_revision(void); +void omap4xxx_check_revision(void); +void omap3xxx_check_features(void); +void ti81xx_check_features(void); +void omap4xxx_check_features(void); /* * Runtime detection of OMAP3 features -- GitLab From 9a0f05cb36888550d1509d60aa55788615abea44 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 21 Nov 2011 15:13:29 +0100 Subject: [PATCH 00006/10698] perf: Update the mmap control page on mmap() Apparently we didn't update the mmap control page right after mmap(), which leads to surprises when userspace wants to use it. Signed-off-by: Peter Zijlstra Cc: Stephane Eranian Cc: Arun Sharma Link: http://lkml.kernel.org/n/tip-dcpi7164djsexmx6ya7lilrc@git.kernel.org Signed-off-by: Ingo Molnar --- kernel/events/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/events/core.c b/kernel/events/core.c index 2f8f3f103cb4..0ca1f648ac08 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3534,6 +3534,8 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) event->mmap_user = get_current_user(); vma->vm_mm->pinned_vm += event->mmap_locked; + perf_event_update_userpage(event); + unlock: if (!ret) atomic_inc(&event->mmap_count); -- GitLab From 35edc2a5095efb189e60dc32bbb9d2663aec6d24 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sun, 20 Nov 2011 20:36:02 +0100 Subject: [PATCH 00007/10698] perf, arch: Rework perf_event_index() Put the logic to compute the event index into a per pmu method. This is required because the x86 rules are weird and wonderful and don't match the capabilities of the current scheme. AFAIK only powerpc actually has a usable userspace read of the PMCs but I'm not at all sure anybody actually used that. ARM is restored to the default since it currently does not support userspace access at all. And all software events are provided with a method that reports their index as 0 (disabled). Signed-off-by: Peter Zijlstra Cc: Michael Cree Cc: Will Deacon Cc: Deng-Cheng Zhu Cc: Anton Blanchard Cc: Eric B Munson Cc: Heiko Carstens Cc: Paul Mundt Cc: David S. Miller Cc: Richard Kuo Cc: Stephane Eranian Cc: Arun Sharma Link: http://lkml.kernel.org/n/tip-dfydxodki16lylkt3gl2j7cw@git.kernel.org Signed-off-by: Ingo Molnar --- arch/arm/include/asm/perf_event.h | 4 --- arch/frv/include/asm/perf_event.h | 2 -- arch/hexagon/include/asm/perf_event.h | 2 -- arch/powerpc/include/asm/perf_event_server.h | 2 -- arch/powerpc/kernel/perf_event.c | 6 +++++ arch/s390/include/asm/perf_event.h | 1 - arch/x86/include/asm/perf_event.h | 2 -- include/linux/perf_event.h | 6 +++++ kernel/events/core.c | 27 ++++++++++++++++---- kernel/events/hw_breakpoint.c | 7 +++++ 10 files changed, 41 insertions(+), 18 deletions(-) diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h index 0f8e3827a89b..08f94d8fc04c 100644 --- a/arch/arm/include/asm/perf_event.h +++ b/arch/arm/include/asm/perf_event.h @@ -12,10 +12,6 @@ #ifndef __ARM_PERF_EVENT_H__ #define __ARM_PERF_EVENT_H__ -/* ARM performance counters start from 1 (in the cp15 accesses) so use the - * same indexes here for consistency. */ -#define PERF_EVENT_INDEX_OFFSET 1 - /* ARM perf PMU IDs for use by internal perf clients. */ enum arm_perf_pmu_ids { ARM_PERF_PMU_ID_XSCALE1 = 0, diff --git a/arch/frv/include/asm/perf_event.h b/arch/frv/include/asm/perf_event.h index a69e0155d146..c52ea5546b5b 100644 --- a/arch/frv/include/asm/perf_event.h +++ b/arch/frv/include/asm/perf_event.h @@ -12,6 +12,4 @@ #ifndef _ASM_PERF_EVENT_H #define _ASM_PERF_EVENT_H -#define PERF_EVENT_INDEX_OFFSET 0 - #endif /* _ASM_PERF_EVENT_H */ diff --git a/arch/hexagon/include/asm/perf_event.h b/arch/hexagon/include/asm/perf_event.h index 6c2910f91180..8b8526b491c7 100644 --- a/arch/hexagon/include/asm/perf_event.h +++ b/arch/hexagon/include/asm/perf_event.h @@ -19,6 +19,4 @@ #ifndef _ASM_PERF_EVENT_H #define _ASM_PERF_EVENT_H -#define PERF_EVENT_INDEX_OFFSET 0 - #endif /* _ASM_PERF_EVENT_H */ diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index 8f1df1208d23..1a8093fa8f71 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h @@ -61,8 +61,6 @@ struct pt_regs; extern unsigned long perf_misc_flags(struct pt_regs *regs); extern unsigned long perf_instruction_pointer(struct pt_regs *regs); -#define PERF_EVENT_INDEX_OFFSET 1 - /* * Only override the default definitions in include/linux/perf_event.h * if we have hardware PMU support. diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index 10a140f82cb8..d614ab57ccca 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c @@ -1187,6 +1187,11 @@ static int power_pmu_event_init(struct perf_event *event) return err; } +static int power_pmu_event_idx(struct perf_event *event) +{ + return event->hw.idx; +} + struct pmu power_pmu = { .pmu_enable = power_pmu_enable, .pmu_disable = power_pmu_disable, @@ -1199,6 +1204,7 @@ struct pmu power_pmu = { .start_txn = power_pmu_start_txn, .cancel_txn = power_pmu_cancel_txn, .commit_txn = power_pmu_commit_txn, + .event_idx = power_pmu_event_idx, }; /* diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h index a75f168d2718..4eb444edbe49 100644 --- a/arch/s390/include/asm/perf_event.h +++ b/arch/s390/include/asm/perf_event.h @@ -6,4 +6,3 @@ /* Empty, just to avoid compiling error */ -#define PERF_EVENT_INDEX_OFFSET 0 diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 096c975e099f..9b922c136254 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -188,8 +188,6 @@ extern u32 get_ibs_caps(void); #ifdef CONFIG_PERF_EVENTS extern void perf_events_lapic_init(void); -#define PERF_EVENT_INDEX_OFFSET 0 - /* * Abuse bit 3 of the cpu eflags register to indicate proper PEBS IP fixups. * This flag is otherwise unused and ABI specified to be 0, so nobody should diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 08855613ceb3..02545e6df95b 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -680,6 +680,12 @@ struct pmu { * for each successful ->add() during the transaction. */ void (*cancel_txn) (struct pmu *pmu); /* optional */ + + /* + * Will return the value for perf_event_mmap_page::index for this event, + * if no implementation is provided it will default to: event->hw.idx + 1. + */ + int (*event_idx) (struct perf_event *event); /*optional */ }; /** diff --git a/kernel/events/core.c b/kernel/events/core.c index 0ca1f648ac08..3894309c41a2 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3208,10 +3208,6 @@ int perf_event_task_disable(void) return 0; } -#ifndef PERF_EVENT_INDEX_OFFSET -# define PERF_EVENT_INDEX_OFFSET 0 -#endif - static int perf_event_index(struct perf_event *event) { if (event->hw.state & PERF_HES_STOPPED) @@ -3220,7 +3216,7 @@ static int perf_event_index(struct perf_event *event) if (event->state != PERF_EVENT_STATE_ACTIVE) return 0; - return event->hw.idx + 1 - PERF_EVENT_INDEX_OFFSET; + return event->pmu->event_idx(event); } static void calc_timer_values(struct perf_event *event, @@ -4992,6 +4988,11 @@ static int perf_swevent_init(struct perf_event *event) return 0; } +static int perf_swevent_event_idx(struct perf_event *event) +{ + return 0; +} + static struct pmu perf_swevent = { .task_ctx_nr = perf_sw_context, @@ -5001,6 +5002,8 @@ static struct pmu perf_swevent = { .start = perf_swevent_start, .stop = perf_swevent_stop, .read = perf_swevent_read, + + .event_idx = perf_swevent_event_idx, }; #ifdef CONFIG_EVENT_TRACING @@ -5087,6 +5090,8 @@ static struct pmu perf_tracepoint = { .start = perf_swevent_start, .stop = perf_swevent_stop, .read = perf_swevent_read, + + .event_idx = perf_swevent_event_idx, }; static inline void perf_tp_register(void) @@ -5306,6 +5311,8 @@ static struct pmu perf_cpu_clock = { .start = cpu_clock_event_start, .stop = cpu_clock_event_stop, .read = cpu_clock_event_read, + + .event_idx = perf_swevent_event_idx, }; /* @@ -5378,6 +5385,8 @@ static struct pmu perf_task_clock = { .start = task_clock_event_start, .stop = task_clock_event_stop, .read = task_clock_event_read, + + .event_idx = perf_swevent_event_idx, }; static void perf_pmu_nop_void(struct pmu *pmu) @@ -5405,6 +5414,11 @@ static void perf_pmu_cancel_txn(struct pmu *pmu) perf_pmu_enable(pmu); } +static int perf_event_idx_default(struct perf_event *event) +{ + return event->hw.idx + 1; +} + /* * Ensures all contexts with the same task_ctx_nr have the same * pmu_cpu_context too. @@ -5594,6 +5608,9 @@ int perf_pmu_register(struct pmu *pmu, char *name, int type) pmu->pmu_disable = perf_pmu_nop_void; } + if (!pmu->event_idx) + pmu->event_idx = perf_event_idx_default; + list_add_rcu(&pmu->entry, &pmus); ret = 0; unlock: diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c index b7971d6f38bf..b0309f76d777 100644 --- a/kernel/events/hw_breakpoint.c +++ b/kernel/events/hw_breakpoint.c @@ -613,6 +613,11 @@ static void hw_breakpoint_stop(struct perf_event *bp, int flags) bp->hw.state = PERF_HES_STOPPED; } +static int hw_breakpoint_event_idx(struct perf_event *bp) +{ + return 0; +} + static struct pmu perf_breakpoint = { .task_ctx_nr = perf_sw_context, /* could eventually get its own */ @@ -622,6 +627,8 @@ static struct pmu perf_breakpoint = { .start = hw_breakpoint_start, .stop = hw_breakpoint_stop, .read = hw_breakpoint_pmu_read, + + .event_idx = hw_breakpoint_event_idx, }; int __init init_hw_breakpoint(void) -- GitLab From 365a4038486b57bb2bd516706a80f82f250f5306 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 21 Nov 2011 20:58:59 +0100 Subject: [PATCH 00008/10698] perf: Fix mmap_page::offset computation There's multiple reason the counter might be unavailable, change the condition to !->index since perf_event_index() should return 0 for all those cases. Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-1ixr3olci40w8rgv2evv2ldh@git.kernel.org Signed-off-by: Ingo Molnar --- kernel/events/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index 3894309c41a2..05affc3878ff 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3268,7 +3268,7 @@ void perf_event_update_userpage(struct perf_event *event) barrier(); userpg->index = perf_event_index(event); userpg->offset = perf_event_count(event); - if (event->state == PERF_EVENT_STATE_ACTIVE) + if (userpg->index) userpg->offset -= local64_read(&event->hw.prev_count); userpg->time_enabled = enabled + -- GitLab From fe4a330885aee20f233de36085fb15c38094e635 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sun, 20 Nov 2011 20:44:06 +0100 Subject: [PATCH 00009/10698] perf, x86: Implement user-space RDPMC support, to allow fast, user-space access to self-monitoring counters Implement a correct pmu::event_idx for the x86 counter index rules and set CR4.PCE on CPU_STARTING. Signed-off-by: Peter Zijlstra Cc: Stephane Eranian Cc: Arun Sharma Cc: Thomas Gleixner Cc: "H. Peter Anvin" Link: http://lkml.kernel.org/n/tip-mwxab34dibqgzk5zywutfnha@git.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 5adce1040b11..53b569910175 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1210,6 +1210,7 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) break; case CPU_STARTING: + set_in_cr4(X86_CR4_PCE); if (x86_pmu.cpu_starting) x86_pmu.cpu_starting(cpu); break; @@ -1542,6 +1543,18 @@ static int x86_pmu_event_init(struct perf_event *event) return err; } +static int x86_pmu_event_idx(struct perf_event *event) +{ + int idx = event->hw.idx; + + if (x86_pmu.num_counters_fixed && idx >= X86_PMC_IDX_FIXED) { + idx -= X86_PMC_IDX_FIXED; + idx |= 1 << 30; + } + + return idx + 1; +} + static struct pmu pmu = { .pmu_enable = x86_pmu_enable, .pmu_disable = x86_pmu_disable, @@ -1557,6 +1570,8 @@ static struct pmu pmu = { .start_txn = x86_pmu_start_txn, .cancel_txn = x86_pmu_cancel_txn, .commit_txn = x86_pmu_commit_txn, + + .event_idx = x86_pmu_event_idx, }; /* -- GitLab From 0c9d42ed4cee2aa1dfc3a260b741baae8615744f Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Sun, 20 Nov 2011 23:30:47 +0100 Subject: [PATCH 00010/10698] perf, x86: Provide means for disabling userspace RDPMC Allow the disabling of RDPMC via a pmu specific attribute: echo 0 > /sys/bus/event_source/devices/cpu/rdpmc Signed-off-by: Peter Zijlstra Cc: Stephane Eranian Cc: Arun Sharma Link: http://lkml.kernel.org/n/tip-pqeog465zo5hsimtkfz73f27@git.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 55 +++++++++++++++++++++++++++++++- arch/x86/kernel/cpu/perf_event.h | 8 +++++ include/linux/perf_event.h | 1 + kernel/events/core.c | 1 + 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 53b569910175..116b040a73a8 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -1210,7 +1211,8 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) break; case CPU_STARTING: - set_in_cr4(X86_CR4_PCE); + if (x86_pmu.attr_rdpmc) + set_in_cr4(X86_CR4_PCE); if (x86_pmu.cpu_starting) x86_pmu.cpu_starting(cpu); break; @@ -1320,6 +1322,8 @@ static int __init init_hw_perf_events(void) } } + x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */ + pr_info("... version: %d\n", x86_pmu.version); pr_info("... bit width: %d\n", x86_pmu.cntval_bits); pr_info("... generic registers: %d\n", x86_pmu.num_counters); @@ -1555,10 +1559,59 @@ static int x86_pmu_event_idx(struct perf_event *event) return idx + 1; } +static ssize_t get_attr_rdpmc(struct device *cdev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, 40, "%d\n", x86_pmu.attr_rdpmc); +} + +static void change_rdpmc(void *info) +{ + bool enable = !!(unsigned long)info; + + if (enable) + set_in_cr4(X86_CR4_PCE); + else + clear_in_cr4(X86_CR4_PCE); +} + +static ssize_t set_attr_rdpmc(struct device *cdev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long val = simple_strtoul(buf, NULL, 0); + + if (!!val != !!x86_pmu.attr_rdpmc) { + x86_pmu.attr_rdpmc = !!val; + smp_call_function(change_rdpmc, (void *)val, 1); + } + + return count; +} + +static DEVICE_ATTR(rdpmc, S_IRUSR | S_IWUSR, get_attr_rdpmc, set_attr_rdpmc); + +static struct attribute *x86_pmu_attrs[] = { + &dev_attr_rdpmc.attr, + NULL, +}; + +static struct attribute_group x86_pmu_attr_group = { + .attrs = x86_pmu_attrs, +}; + +static const struct attribute_group *x86_pmu_attr_groups[] = { + &x86_pmu_attr_group, + NULL, +}; + static struct pmu pmu = { .pmu_enable = x86_pmu_enable, .pmu_disable = x86_pmu_disable, + .attr_groups = x86_pmu_attr_groups, + .event_init = x86_pmu_event_init, .add = x86_pmu_add, diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h index 8944062f46e2..513d617b93c4 100644 --- a/arch/x86/kernel/cpu/perf_event.h +++ b/arch/x86/kernel/cpu/perf_event.h @@ -307,6 +307,14 @@ struct x86_pmu { struct x86_pmu_quirk *quirks; int perfctr_second_write; + /* + * sysfs attrs + */ + int attr_rdpmc; + + /* + * CPU Hotplug hooks + */ int (*cpu_prepare)(int cpu); void (*cpu_starting)(int cpu); void (*cpu_dying)(int cpu); diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 02545e6df95b..5311b79fe62c 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -615,6 +615,7 @@ struct pmu { struct list_head entry; struct device *dev; + const struct attribute_group **attr_groups; char *name; int type; diff --git a/kernel/events/core.c b/kernel/events/core.c index 05affc3878ff..dcd4049e92fc 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5505,6 +5505,7 @@ static int pmu_dev_alloc(struct pmu *pmu) if (!pmu->dev) goto out; + pmu->dev->groups = pmu->attr_groups; device_initialize(pmu->dev); ret = dev_set_name(pmu->dev, "%s", pmu->name); if (ret) -- GitLab From e3f3541c19c89a4daae39300defba68943301949 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 21 Nov 2011 11:43:53 +0100 Subject: [PATCH 00011/10698] perf: Extend the mmap control page with time (TSC) fields Extend the mmap control page with fields so that userspace can compute time deltas relative to the provided time fields. Currently only implemented for x86 with constant and nonstop TSC. Signed-off-by: Peter Zijlstra Cc: Stephane Eranian Cc: Arun Sharma Link: http://lkml.kernel.org/n/tip-3u1jucza77j3wuvs0x2bic0f@git.kernel.org Signed-off-by: Ingo Molnar --- arch/x86/kernel/cpu/perf_event.c | 14 ++++++++++++++ include/linux/perf_event.h | 4 +++- kernel/events/core.c | 21 ++++++++++++++------- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 116b040a73a8..f8bddb5b0600 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "perf_event.h" @@ -1627,6 +1628,19 @@ static struct pmu pmu = { .event_idx = x86_pmu_event_idx, }; +void perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now) +{ + if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC)) + return; + + if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) + return; + + userpg->time_mult = this_cpu_read(cyc2ns); + userpg->time_shift = CYC2NS_SCALE_FACTOR; + userpg->time_offset = this_cpu_read(cyc2ns_offset) - now; +} + /* * callchain support */ diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 5311b79fe62c..0b91db2522cc 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -291,12 +291,14 @@ struct perf_event_mmap_page { __s64 offset; /* add to hardware event value */ __u64 time_enabled; /* time event active */ __u64 time_running; /* time event on cpu */ + __u32 time_mult, time_shift; + __u64 time_offset; /* * Hole for extension of the self monitor capabilities */ - __u64 __reserved[123]; /* align to 1k */ + __u64 __reserved[121]; /* align to 1k */ /* * Control data for the mmap() data buffer. diff --git a/kernel/events/core.c b/kernel/events/core.c index dcd4049e92fc..3a9c7d81afbf 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -3220,17 +3220,22 @@ static int perf_event_index(struct perf_event *event) } static void calc_timer_values(struct perf_event *event, + u64 *now, u64 *enabled, u64 *running) { - u64 now, ctx_time; + u64 ctx_time; - now = perf_clock(); - ctx_time = event->shadow_ctx_time + now; + *now = perf_clock(); + ctx_time = event->shadow_ctx_time + *now; *enabled = ctx_time - event->tstamp_enabled; *running = ctx_time - event->tstamp_running; } +void __weak perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now) +{ +} + /* * Callers need to ensure there can be no nesting of this function, otherwise * the seqlock logic goes bad. We can not serialize this because the arch @@ -3240,7 +3245,7 @@ void perf_event_update_userpage(struct perf_event *event) { struct perf_event_mmap_page *userpg; struct ring_buffer *rb; - u64 enabled, running; + u64 enabled, running, now; rcu_read_lock(); /* @@ -3252,7 +3257,7 @@ void perf_event_update_userpage(struct perf_event *event) * because of locking issue as we can be called in * NMI context */ - calc_timer_values(event, &enabled, &running); + calc_timer_values(event, &now, &enabled, &running); rb = rcu_dereference(event->rb); if (!rb) goto unlock; @@ -3277,6 +3282,8 @@ void perf_event_update_userpage(struct perf_event *event) userpg->time_running = running + atomic64_read(&event->child_total_time_running); + perf_update_user_clock(userpg, now); + barrier(); ++userpg->lock; preempt_enable(); @@ -3763,7 +3770,7 @@ static void perf_output_read_group(struct perf_output_handle *handle, static void perf_output_read(struct perf_output_handle *handle, struct perf_event *event) { - u64 enabled = 0, running = 0; + u64 enabled = 0, running = 0, now; u64 read_format = event->attr.read_format; /* @@ -3776,7 +3783,7 @@ static void perf_output_read(struct perf_output_handle *handle, * NMI context */ if (read_format & PERF_FORMAT_TOTAL_TIMES) - calc_timer_values(event, &enabled, &running); + calc_timer_values(event, &now, &enabled, &running); if (event->attr.read_format & PERF_FORMAT_GROUP) perf_output_read_group(handle, event, enabled, running); -- GitLab From 08aa0d1f376e9b966568316bd2019b3c1274d885 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Mon, 21 Nov 2011 14:42:47 +0100 Subject: [PATCH 00012/10698] perf tools: Add x86 RDPMC, RDTSC test Implement a simple test for the self-monitoring data from the perf mmap data area control page: 6: x86 rdpmc test: 0: 6053 1: 60053 2: 600059 3: 6000059 4: 60000075 5: 600000247 Ok The counts are expected to increase monotonically - these are recovered via RDPMC, without calling into the kernel. It might be nice to add logic to automagically turn these numbers into OK/FAIL. Signed-off-by: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Stephane Eranian Cc: Arun Sharma Link: http://lkml.kernel.org/n/tip-evf5yii88ljdgmaihccbxxw1@git.kernel.org [ various small improvements ] Signed-off-by: Ingo Molnar --- tools/perf/builtin-test.c | 177 +++++++++++++++++++++++++++++++++++++- 1 file changed, 175 insertions(+), 2 deletions(-) diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 2b9a7f497a20..439b5ed03e64 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -15,6 +15,8 @@ #include "util/thread_map.h" #include "../../include/linux/hw_breakpoint.h" +#include + static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) { bool *visited = symbol__priv(sym); @@ -1296,6 +1298,173 @@ static int test__PERF_RECORD(void) return (err < 0 || errs > 0) ? -1 : 0; } + +#if defined(__x86_64__) || defined(__i386__) + +#define barrier() asm volatile("" ::: "memory") + +static u64 rdpmc(unsigned int counter) +{ + unsigned int low, high; + + asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter)); + + return low | ((u64)high) << 32; +} + +static u64 rdtsc(void) +{ + unsigned int low, high; + + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + + return low | ((u64)high) << 32; +} + +static u64 mmap_read_self(void *addr) +{ + struct perf_event_mmap_page *pc = addr; + u32 seq, idx, time_mult = 0, time_shift = 0; + u64 count, cyc = 0, time_offset = 0, enabled, running, delta; + + do { + seq = pc->lock; + barrier(); + + enabled = pc->time_enabled; + running = pc->time_running; + + if (enabled != running) { + cyc = rdtsc(); + time_mult = pc->time_mult; + time_shift = pc->time_shift; + time_offset = pc->time_offset; + } + + idx = pc->index; + count = pc->offset; + if (idx) + count += rdpmc(idx - 1); + + barrier(); + } while (pc->lock != seq); + + if (enabled != running) { + u64 quot, rem; + + quot = (cyc >> time_shift); + rem = cyc & ((1 << time_shift) - 1); + delta = time_offset + quot * time_mult + + ((rem * time_mult) >> time_shift); + + enabled += delta; + if (idx) + running += delta; + + quot = count / running; + rem = count % running; + count = quot * enabled + (rem * enabled) / running; + } + + return count; +} + +/* + * If the RDPMC instruction faults then signal this back to the test parent task: + */ +static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used) +{ + exit(-1); +} + +static int __test__rdpmc(void) +{ + long page_size = sysconf(_SC_PAGE_SIZE); + volatile int tmp = 0; + u64 i, loops = 1000; + int n; + int fd; + void *addr; + struct perf_event_attr attr = { + .type = PERF_TYPE_HARDWARE, + .config = PERF_COUNT_HW_INSTRUCTIONS, + .exclude_kernel = 1, + }; + u64 delta_sum = 0; + struct sigaction sa; + + sigfillset(&sa.sa_mask); + sa.sa_sigaction = segfault_handler; + sigaction(SIGSEGV, &sa, NULL); + + fprintf(stderr, "\n\n"); + + fd = sys_perf_event_open(&attr, 0, -1, -1, 0); + if (fd < 0) { + die("Error: sys_perf_event_open() syscall returned " + "with %d (%s)\n", fd, strerror(errno)); + } + + addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); + if (addr == (void *)(-1)) { + die("Error: mmap() syscall returned " + "with (%s)\n", strerror(errno)); + } + + for (n = 0; n < 6; n++) { + u64 stamp, now, delta; + + stamp = mmap_read_self(addr); + + for (i = 0; i < loops; i++) + tmp++; + + now = mmap_read_self(addr); + loops *= 10; + + delta = now - stamp; + fprintf(stderr, "%14d: %14Lu\n", n, (long long)delta); + + delta_sum += delta; + } + + munmap(addr, page_size); + close(fd); + + fprintf(stderr, " "); + + if (!delta_sum) + return -1; + + return 0; +} + +static int test__rdpmc(void) +{ + int status = 0; + int wret = 0; + int ret; + int pid; + + pid = fork(); + if (pid < 0) + return -1; + + if (!pid) { + ret = __test__rdpmc(); + + exit(ret); + } + + wret = waitpid(pid, &status, 0); + if (wret < 0 || status) + return -1; + + return 0; +} + +#endif + static struct test { const char *desc; int (*func)(void); @@ -1320,6 +1489,12 @@ static struct test { .desc = "parse events tests", .func = test__parse_events, }, +#if defined(__x86_64__) || defined(__i386__) + { + .desc = "x86 rdpmc test", + .func = test__rdpmc, + }, +#endif { .desc = "Validate PERF_RECORD_* events & perf_sample fields", .func = test__PERF_RECORD, @@ -1412,7 +1587,5 @@ int cmd_test(int argc, const char **argv, const char *prefix __used) if (symbol__init() < 0) return -1; - setup_pager(); - return __cmd_test(argc, argv); } -- GitLab From f7519d8c8290765a9408a52db4ba4a368ff72ca5 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Tue, 20 Dec 2011 22:54:18 +0100 Subject: [PATCH 00013/10698] ARM: OMAP1: ams-delta: register latch dependent devices later In preparation to converting Amstrad Delta on-board latches to basic_mmio_gpio devices, registration of platform devices which depend on latches and will require initialization of their GPIO pins first, should be moved out of .machine_init down to late_initcall level, as the gpio-generic driver is not available until device_initcall time. The latch reset operation, which will be replaced with GPIO initialization, must also be moved to late_initcall for the same reason. Since there was already another, separate arch_initcall function for setting up one of those latch dependent devices, the on-board modem device, reuse that function, i.e., rename it to a name that matches the new purpose, extend with other device setup relocated from .machine_init, and move down to the late_initcall level. While being at it, add missing gpio_free() in case the modem platform device registration fails. Thanks to Tony Lindgren who suggested this approach instead of shifting up the gpio-generic driver initialization. In addition, defer registration of the Amstrad Delta ASoC and serio devices, done from their device driver files, until late_initcall time, as those drivers will depend on their GPIO pins already requested from the board late_init() function until updated to register their GPIO pins themselves. Signed-off-by: Janusz Krzysztofik Acked-by: Mark Brown Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-ams-delta.c | 28 +++++++++++++++++++-------- drivers/input/serio/ams_delta_serio.c | 2 +- sound/soc/omap/ams-delta.c | 2 +- 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index b0f15d234a12..50987c91690f 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -275,11 +275,14 @@ static struct omap1_cam_platform_data ams_delta_camera_platform_data = { }; static struct platform_device *ams_delta_devices[] __initdata = { - &ams_delta_nand_device, &ams_delta_kp_device, + &ams_delta_camera_device, +}; + +static struct platform_device *late_devices[] __initdata = { + &ams_delta_nand_device, &ams_delta_lcd_device, &ams_delta_led_device, - &ams_delta_camera_device, }; static void __init ams_delta_init(void) @@ -307,9 +310,6 @@ static void __init ams_delta_init(void) omap_serial_init(); omap_register_i2c_bus(1, 100, NULL, 0); - /* Clear latch2 (NAND, LCD, modem enable) */ - ams_delta_latch2_write(~0, 0); - omap1_usb_init(&ams_delta_usb_config); omap1_set_camera_info(&ams_delta_camera_platform_data); #ifdef CONFIG_LEDS_TRIGGERS @@ -345,13 +345,18 @@ static struct platform_device ams_delta_modem_device = { }, }; -static int __init ams_delta_modem_init(void) +static int __init late_init(void) { int err; if (!machine_is_ams_delta()) return -ENODEV; + /* Clear latch2 (NAND, LCD, modem enable) */ + ams_delta_latch2_write(~0, 0); + + platform_add_devices(late_devices, ARRAY_SIZE(late_devices)); + omap_cfg_reg(M14_1510_GPIO2); ams_delta_modem_ports[0].irq = gpio_to_irq(AMS_DELTA_GPIO_PIN_MODEM_IRQ); @@ -367,9 +372,16 @@ static int __init ams_delta_modem_init(void) AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC, AMS_DELTA_LATCH2_MODEM_NRESET | AMS_DELTA_LATCH2_MODEM_CODEC); - return platform_device_register(&ams_delta_modem_device); + err = platform_device_register(&ams_delta_modem_device); + if (err) + goto gpio_free; + return 0; + +gpio_free: + gpio_free(AMS_DELTA_GPIO_PIN_MODEM_IRQ); + return err; } -arch_initcall(ams_delta_modem_init); +late_initcall(late_init); static void __init ams_delta_map_io(void) { diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c index d4d08bd9205b..835d37abe62a 100644 --- a/drivers/input/serio/ams_delta_serio.c +++ b/drivers/input/serio/ams_delta_serio.c @@ -165,7 +165,7 @@ static int __init ams_delta_serio_init(void) kfree(ams_delta_serio); return err; } -module_init(ams_delta_serio_init); +late_initcall(ams_delta_serio_init); static void __exit ams_delta_serio_exit(void) { diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c index ccb8a6aa1817..be81bc791b11 100644 --- a/sound/soc/omap/ams-delta.c +++ b/sound/soc/omap/ams-delta.c @@ -636,7 +636,7 @@ static int __init ams_delta_module_init(void) platform_device_put(ams_delta_audio_platform_device); return ret; } -module_init(ams_delta_module_init); +late_initcall(ams_delta_module_init); static void __exit ams_delta_module_exit(void) { -- GitLab From ea9da1c79eb9a28176550d0b8ba9166e6e5f42b8 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 2 Dec 2011 11:55:44 -0800 Subject: [PATCH 00014/10698] UAS: Re-add workqueue items if submission fails. If the original submission (or allocation) of the URBs for a SCSI command fails, the UAS driver sticks the command structure in a workqueue and schedules uas_do_work() to run. That function removes the entire queue before walking across it and attempting to resubmit. Unfortunately, if the second submission fails, we will leak memory (because an allocated URB was not submitted) and possibly leave the SCSI command partially enqueued on some of the stream rings. Fix this by checking whether the second submission failed and re-queueing the command to the UAS workqueue and scheduling it. Signed-off-by: Sarah Sharp Cc: Matthew Wilcox Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 1d10d5b8204c..4bbaf6e150e4 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -125,29 +125,38 @@ struct uas_cmd_info { /* I hate forward declarations, but I actually have a loop */ static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_dev_info *devinfo, gfp_t gfp); +static void uas_do_work(struct work_struct *work); +static DECLARE_WORK(uas_work, uas_do_work); static DEFINE_SPINLOCK(uas_work_lock); static LIST_HEAD(uas_work_list); static void uas_do_work(struct work_struct *work) { struct uas_cmd_info *cmdinfo; + struct uas_cmd_info *temp; struct list_head list; + int err; spin_lock_irq(&uas_work_lock); list_replace_init(&uas_work_list, &list); spin_unlock_irq(&uas_work_lock); - list_for_each_entry(cmdinfo, &list, list) { + list_for_each_entry_safe(cmdinfo, temp, &list, list) { struct scsi_pointer *scp = (void *)cmdinfo; struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp); - uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + if (err) { + list_del(&cmdinfo->list); + spin_lock_irq(&uas_work_lock); + list_add_tail(&cmdinfo->list, &uas_work_list); + spin_unlock_irq(&uas_work_lock); + schedule_work(&uas_work); + } } } -static DECLARE_WORK(uas_work, uas_do_work); - static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu *sense_iu = urb->transfer_buffer; -- GitLab From 9eb445410db99e5f5f660e97a2165a0567bd909e Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 2 Dec 2011 11:55:46 -0800 Subject: [PATCH 00015/10698] UAS: Use unique tags on non-streams devices. UAS can work with either USB 3.0 devices that support bulk streams, or USB 2.0 devices that do not support bulk streams. When we're working with a non-streams device, we need to be able to uniquely identify a SCSI command with a tag in the IU. Devices will barf and abort all queued commands if they find a duplicate tag. uas_queuecommand_lck() sets cmdinfo->stream to zero if the device doesn't support streams, which is later passed into uas_alloc_cmd_urb() as the variable stream. This means the UAS driver was setting the tag in all commands to zero for non-stream devices. So the UAS driver won't currently work with USB 2.0 devices. Use the SCSI command tag instead of the stream ID for the command IU tag. We have to add one to the SCSI command tag because SCSI tags are zero-based, but stream IDs are one-based, and the command tag must match the stream ID that we're queueing the data IUs for. Untagged SCSI commands use stream ID 1. Signed-off-by: Sarah Sharp Cc: Matthew Wilcox Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 4bbaf6e150e4..28d9b1909389 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -343,7 +343,10 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, goto free; iu->iu_id = IU_ID_COMMAND; - iu->tag = cpu_to_be16(stream_id); + if (blk_rq_tagged(cmnd->request)) + iu->tag = cpu_to_be16(cmnd->request->tag + 1); + else + iu->tag = cpu_to_be16(1); iu->prio_attr = UAS_SIMPLE_TAG; iu->len = len; int_to_scsilun(sdev->lun, &iu->lun); -- GitLab From 96c1eb9873caffc507a1951c36b43fdcf3ddeff3 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 2 Dec 2011 11:55:48 -0800 Subject: [PATCH 00016/10698] UAS: Free status URB when we can't find the SCSI tag. In the UAS status URB completion handler, we need to free the URB, no matter what happens. Fix a bug where we would leak the URB (and its buffer) if we couldn't find a SCSI command that is associated with this status phase. Signed-off-by: Sarah Sharp Cc: Matthew Wilcox Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 28d9b1909389..9dd4aaee85cc 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -246,8 +246,10 @@ static void uas_stat_cmplt(struct urb *urb) cmnd = sdev->current_cmnd; else cmnd = scsi_find_tag(sdev, tag); - if (!cmnd) + if (!cmnd) { + usb_free_urb(urb); return; + } switch (iu->iu_id) { case IU_ID_STATUS: -- GitLab From dae51546b6564b06cbae4191d4f2dee7136be3c1 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 19 Dec 2011 17:06:08 +0100 Subject: [PATCH 00017/10698] usb/uas: use unique tags for all LUNs I observed that on a device with multiple LUNs UAS was re-using the same tag number for requests which were issued at the same time to both LUNs. This patch uses scsi_init_shared_tag_map() to use unique tags for all LUNs. With this patch I haven't seen the same tag number during the init sequence anymore. Tag 1 is used for devices which do not adverise command queueing. This patch initilizes the queue before adding the scsi host like the other two user in tree. Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 9dd4aaee85cc..6974f4bed2fd 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -684,6 +684,17 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo) } } +static void uas_free_streams(struct uas_dev_info *devinfo) +{ + struct usb_device *udev = devinfo->udev; + struct usb_host_endpoint *eps[3]; + + eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); + eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); + eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); + usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL); +} + /* * XXX: What I'd like to do here is register a SCSI host for each USB host in * the system. Follow usb-storage's design of registering a SCSI host for @@ -713,18 +724,26 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) shost->max_id = 1; shost->sg_tablesize = udev->bus->sg_tablesize; - result = scsi_add_host(shost, &intf->dev); - if (result) - goto free; - shost->hostdata[0] = (unsigned long)devinfo; - devinfo->intf = intf; devinfo->udev = udev; uas_configure_endpoints(devinfo); + result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 1); + if (result) + goto free; + + result = scsi_add_host(shost, &intf->dev); + if (result) + goto deconfig_eps; + + shost->hostdata[0] = (unsigned long)devinfo; + scsi_scan_host(shost); usb_set_intfdata(intf, shost); return result; + +deconfig_eps: + uas_free_streams(devinfo); free: kfree(devinfo); if (shost) @@ -746,18 +765,11 @@ static int uas_post_reset(struct usb_interface *intf) static void uas_disconnect(struct usb_interface *intf) { - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_endpoint *eps[3]; struct Scsi_Host *shost = usb_get_intfdata(intf); struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; scsi_remove_host(shost); - - eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); - eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); - eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); - usb_free_streams(intf, eps, 3, GFP_KERNEL); - + uas_free_streams(devinfo); kfree(devinfo); } -- GitLab From 22188f4a933c6e86ac67f52028895c795896492e Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 19 Dec 2011 20:22:39 +0100 Subject: [PATCH 00018/10698] usb/uas: use scsi_host_find_tag() to find command from a tag In "usb/uas: use unique tags for all LUNs" we make sure to create unique tags across all LUNs. This patch uses scsi_host_find_tag() to obtain the correct command which is associated with the tag. The following changes are required: - don't use sdev->current_cmnd anymore Since we can have devices which don't support command queueing we must ensure that we can tell the two commands apart. Even if a device supports comand queuing we send the INQUIRY command "untagged" for LUN1 while we can send a tagged command to LUN0 at the same time. devinfo->cmnd is used for stashing the one "untagged" command. - tag number is altered. If stream support is used then the tag number must match the stream number. Therefore we can't use tag 0 and must start at tag 1. In case we have untagged commands (at least the first command) we must be able to distinguish between command tag 0 (which becomes 1) and untagged command (which becomes curently also 1). The following tag numbers are used: 0: never 1: for untagged commands (devinfo->cmnd) 2+: tagged commands. Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 6974f4bed2fd..e2386e8c7678 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -98,6 +98,7 @@ struct uas_dev_info { unsigned cmd_pipe, status_pipe, data_in_pipe, data_out_pipe; unsigned use_streams:1; unsigned uas_sense_old:1; + struct scsi_cmnd *cmnd; }; enum { @@ -178,8 +179,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (sdev->current_cmnd) - sdev->current_cmnd = NULL; cmnd->scsi_done(cmnd); usb_free_urb(urb); } @@ -205,8 +204,6 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (sdev->current_cmnd) - sdev->current_cmnd = NULL; cmnd->scsi_done(cmnd); usb_free_urb(urb); } @@ -230,8 +227,8 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, static void uas_stat_cmplt(struct urb *urb) { struct iu *iu = urb->transfer_buffer; - struct scsi_device *sdev = urb->context; - struct uas_dev_info *devinfo = sdev->hostdata; + struct Scsi_Host *shost = urb->context; + struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; u16 tag; @@ -242,10 +239,10 @@ static void uas_stat_cmplt(struct urb *urb) } tag = be16_to_cpup(&iu->tag) - 1; - if (sdev->current_cmnd) - cmnd = sdev->current_cmnd; + if (tag == 0) + cmnd = devinfo->cmnd; else - cmnd = scsi_find_tag(sdev, tag); + cmnd = scsi_host_find_tag(shost, tag - 1); if (!cmnd) { usb_free_urb(urb); return; @@ -253,6 +250,9 @@ static void uas_stat_cmplt(struct urb *urb) switch (iu->iu_id) { case IU_ID_STATUS: + if (devinfo->cmnd == cmnd) + devinfo->cmnd = NULL; + if (urb->actual_length < 16) devinfo->uas_sense_old = 1; if (devinfo->uas_sense_old) @@ -314,7 +314,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, goto free; usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), - uas_stat_cmplt, cmnd->device); + uas_stat_cmplt, cmnd->device->host); urb->stream_id = stream_id; urb->transfer_flags |= URB_FREE_BUFFER; out: @@ -346,7 +346,7 @@ static struct urb *uas_alloc_cmd_urb(struct uas_dev_info *devinfo, gfp_t gfp, iu->iu_id = IU_ID_COMMAND; if (blk_rq_tagged(cmnd->request)) - iu->tag = cpu_to_be16(cmnd->request->tag + 1); + iu->tag = cpu_to_be16(cmnd->request->tag + 2); else iu->tag = cpu_to_be16(1); iu->prio_attr = UAS_SIMPLE_TAG; @@ -458,13 +458,13 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); - if (!cmdinfo->status_urb && sdev->current_cmnd) + if (devinfo->cmnd) return SCSI_MLQUEUE_DEVICE_BUSY; if (blk_rq_tagged(cmnd->request)) { - cmdinfo->stream = cmnd->request->tag + 1; + cmdinfo->stream = cmnd->request->tag + 2; } else { - sdev->current_cmnd = cmnd; + devinfo->cmnd = cmnd; cmdinfo->stream = 1; } @@ -565,7 +565,7 @@ static int uas_slave_configure(struct scsi_device *sdev) { struct uas_dev_info *devinfo = sdev->hostdata; scsi_set_tag_type(sdev, MSG_ORDERED_TAG); - scsi_activate_tcq(sdev, devinfo->qdepth - 1); + scsi_activate_tcq(sdev, devinfo->qdepth - 2); return 0; } @@ -633,6 +633,7 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo) unsigned i, n_endpoints = intf->cur_altsetting->desc.bNumEndpoints; devinfo->uas_sense_old = 0; + devinfo->cmnd = NULL; for (i = 0; i < n_endpoints; i++) { unsigned char *extra = endpoint[i].extra; @@ -728,7 +729,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->udev = udev; uas_configure_endpoints(devinfo); - result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 1); + result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2); if (result) goto free; -- GitLab From ceb3f91fd53c9fbd7b292fc2754ba4efffeeeedb Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 20 Dec 2011 14:50:26 +0100 Subject: [PATCH 00019/10698] usb/uas: one only one status URB/host on stream-less connection The status/sense URB is allocated on per-command basis. A read/write looks the following way on a stream-less connection: - send cmd tag X, queue status - receive status, oh it is a read for tag X. queue status & read - receive read - receive status, oh I'm done for tag X. Cool call complete and free status urb. This block repeats itself 1:1 for further commands and looks great so far. Lets take a look now what happens if we do allow multiple commands: - send cmd tag X, queue statusX (belongs to the command with the X tag) - send cmd tag Y, queue statusY (belongs to the command with the Y tag) - receive statusX, oh it is a read for tag X. queue statusX & a read - receive read - receive statusY, oh I'm done for tag X. Cool call complete and free statusY. - receive statusX, oh it is a read for tag Y. queue statusY & before we queue the read the the following message can be observed: |sd 0:0:0:0: [sda] sense urb submission failure followed by a second attempt with the same result. In order to address this problem we will use only one status URB for each scsi host in case we don't have stream support (as suggested by Matthew). This URB is requeued until the device removed. Nothing changes on stream based endpoints. Signed-off-by: Sebastian Andrzej Siewior --- drivers/usb/storage/uas.c | 70 +++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index e2386e8c7678..036e96900956 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -99,6 +99,7 @@ struct uas_dev_info { unsigned use_streams:1; unsigned uas_sense_old:1; struct scsi_cmnd *cmnd; + struct urb *status_urb; /* used only if stream support is available */ }; enum { @@ -117,6 +118,7 @@ struct uas_cmd_info { unsigned int state; unsigned int stream; struct urb *cmd_urb; + /* status_urb is used only if stream support isn't available */ struct urb *status_urb; struct urb *data_in_urb; struct urb *data_out_urb; @@ -180,7 +182,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) cmnd->result = sense_iu->status; cmnd->scsi_done(cmnd); - usb_free_urb(urb); } static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) @@ -205,7 +206,6 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) cmnd->result = sense_iu->status; cmnd->scsi_done(cmnd); - usb_free_urb(urb); } static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, @@ -214,7 +214,7 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; int err; - cmdinfo->state = direction | SUBMIT_STATUS_URB; + cmdinfo->state = direction; err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); if (err) { spin_lock(&uas_work_lock); @@ -231,10 +231,12 @@ static void uas_stat_cmplt(struct urb *urb) struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; u16 tag; + int ret; if (urb->status) { dev_err(&urb->dev->dev, "URB BAD STATUS %d\n", urb->status); - usb_free_urb(urb); + if (devinfo->use_streams) + usb_free_urb(urb); return; } @@ -244,7 +246,13 @@ static void uas_stat_cmplt(struct urb *urb) else cmnd = scsi_host_find_tag(shost, tag - 1); if (!cmnd) { - usb_free_urb(urb); + if (devinfo->use_streams) { + usb_free_urb(urb); + return; + } + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + dev_err(&urb->dev->dev, "failed submit status urb\n"); return; } @@ -270,6 +278,15 @@ static void uas_stat_cmplt(struct urb *urb) scmd_printk(KERN_ERR, cmnd, "Bogus IU (%d) received on status pipe\n", iu->iu_id); } + + if (devinfo->use_streams) { + usb_free_urb(urb); + return; + } + + ret = usb_submit_urb(urb, GFP_ATOMIC); + if (ret) + dev_err(&urb->dev->dev, "failed submit status urb\n"); } static void uas_data_cmplt(struct urb *urb) @@ -300,7 +317,7 @@ static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, } static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, - struct scsi_cmnd *cmnd, u16 stream_id) + struct Scsi_Host *shost, u16 stream_id) { struct usb_device *udev = devinfo->udev; struct urb *urb = usb_alloc_urb(0, gfp); @@ -314,7 +331,7 @@ static struct urb *uas_alloc_sense_urb(struct uas_dev_info *devinfo, gfp_t gfp, goto free; usb_fill_bulk_urb(urb, udev, devinfo->status_pipe, iu, sizeof(*iu), - uas_stat_cmplt, cmnd->device->host); + uas_stat_cmplt, shost); urb->stream_id = stream_id; urb->transfer_flags |= URB_FREE_BUFFER; out: @@ -376,8 +393,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (cmdinfo->state & ALLOC_STATUS_URB) { - cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, cmnd, - cmdinfo->stream); + cmdinfo->status_urb = uas_alloc_sense_urb(devinfo, gfp, + cmnd->device->host, cmdinfo->stream); if (!cmdinfo->status_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_STATUS_URB; @@ -486,7 +503,8 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, } if (!devinfo->use_streams) { - cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); + cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB | + ALLOC_STATUS_URB | SUBMIT_STATUS_URB); cmdinfo->stream = 0; } @@ -685,6 +703,29 @@ static void uas_configure_endpoints(struct uas_dev_info *devinfo) } } +static int uas_alloc_status_urb(struct uas_dev_info *devinfo, + struct Scsi_Host *shost) +{ + if (devinfo->use_streams) { + devinfo->status_urb = NULL; + return 0; + } + + devinfo->status_urb = uas_alloc_sense_urb(devinfo, GFP_KERNEL, + shost, 0); + if (!devinfo->status_urb) + goto err_s_urb; + + if (usb_submit_urb(devinfo->status_urb, GFP_KERNEL)) + goto err_submit_urb; + + return 0; +err_submit_urb: + usb_free_urb(devinfo->status_urb); +err_s_urb: + return -ENOMEM; +} + static void uas_free_streams(struct uas_dev_info *devinfo) { struct usb_device *udev = devinfo->udev; @@ -739,10 +780,17 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) shost->hostdata[0] = (unsigned long)devinfo; + result = uas_alloc_status_urb(devinfo, shost); + if (result) + goto err_alloc_status; + scsi_scan_host(shost); usb_set_intfdata(intf, shost); return result; +err_alloc_status: + scsi_remove_host(shost); + shost = NULL; deconfig_eps: uas_free_streams(devinfo); free: @@ -770,6 +818,8 @@ static void uas_disconnect(struct usb_interface *intf) struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; scsi_remove_host(shost); + usb_kill_urb(devinfo->status_urb); + usb_free_urb(devinfo->status_urb); uas_free_streams(devinfo); kfree(devinfo); } -- GitLab From 937eb4bb00588571f223eade260f9b509bf223ab Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Tue, 20 Dec 2011 03:24:21 +0100 Subject: [PATCH 00020/10698] ARM: OMAP1: ams-delta: convert latches to basic_mmio_gpio Once ready, ams-delta specific device drivers currently calling custom ams_delta_latch[12]_write() functions can be updated to call generic gpio_set_value() instead, which will make them less platform dependent. Even more, some custom ams-delta only drivers can perhaps be dropped from the tree after converting selected ams-delta platform devices to follow generic GPIO based device models. The latch_gpios[] table is initially filled with all latch1 and latch2 GPIO pins in order to register and initialize them from the board file until those are handled by respective existing device drivers (leds, nand, lcd, serio, asoc, serial). That table will get almost empty after the transision process is completed, holding only pins not used by any drivers / connected to unused devices, in order to initialize them from the board file for power saving purposes. The new ams_delta_latch_write() function is a unified replacement for those removed ams_delta_latch[12]_write(), and serves as a temporary wrapper over gpio_set_value(), providing the old API for those not yet updated device drivers, and will be removed after all custom drivers are converted or replaced. Signed-off-by: Janusz Krzysztofik Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/Kconfig | 1 + arch/arm/mach-omap1/board-ams-delta.c | 237 +++++++++++++++--- .../plat-omap/include/plat/board-ams-delta.h | 43 +++- 3 files changed, 242 insertions(+), 39 deletions(-) diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 4f8d66f044e7..e14532f236a0 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -155,6 +155,7 @@ config MACH_AMS_DELTA bool "Amstrad E3 (Delta)" depends on ARCH_OMAP1 && ARCH_OMAP15XX select FIQ + select GPIO_GENERIC_PLATFORM help Support for the Amstrad E3 (codename Delta) videophone. Say Y here if you have such a device. diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 50987c91690f..cff2711dc259 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -11,6 +11,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ +#include #include #include #include @@ -40,9 +41,6 @@ #include -static u8 ams_delta_latch1_reg; -static u16 ams_delta_latch2_reg; - static const unsigned int ams_delta_keymap[] = { KEY(0, 0, KEY_F1), /* Advert */ @@ -121,39 +119,32 @@ static const unsigned int ams_delta_keymap[] = { KEY(7, 3, KEY_LEFTCTRL), /* Vol down */ }; -void ams_delta_latch1_write(u8 mask, u8 value) -{ - ams_delta_latch1_reg &= ~mask; - ams_delta_latch1_reg |= value; - *(volatile __u8 *) AMS_DELTA_LATCH1_VIRT = ams_delta_latch1_reg; -} - -void ams_delta_latch2_write(u16 mask, u16 value) -{ - ams_delta_latch2_reg &= ~mask; - ams_delta_latch2_reg |= value; - *(volatile __u16 *) AMS_DELTA_LATCH2_VIRT = ams_delta_latch2_reg; -} +#define LATCH1_PHYS 0x01000000 +#define LATCH1_VIRT 0xEA000000 +#define MODEM_PHYS 0x04000000 +#define MODEM_VIRT 0xEB000000 +#define LATCH2_PHYS 0x08000000 +#define LATCH2_VIRT 0xEC000000 static struct map_desc ams_delta_io_desc[] __initdata = { /* AMS_DELTA_LATCH1 */ { - .virtual = AMS_DELTA_LATCH1_VIRT, - .pfn = __phys_to_pfn(AMS_DELTA_LATCH1_PHYS), + .virtual = LATCH1_VIRT, + .pfn = __phys_to_pfn(LATCH1_PHYS), .length = 0x01000000, .type = MT_DEVICE }, /* AMS_DELTA_LATCH2 */ { - .virtual = AMS_DELTA_LATCH2_VIRT, - .pfn = __phys_to_pfn(AMS_DELTA_LATCH2_PHYS), + .virtual = LATCH2_VIRT, + .pfn = __phys_to_pfn(LATCH2_PHYS), .length = 0x01000000, .type = MT_DEVICE }, /* AMS_DELTA_MODEM */ { - .virtual = AMS_DELTA_MODEM_VIRT, - .pfn = __phys_to_pfn(AMS_DELTA_MODEM_PHYS), + .virtual = MODEM_VIRT, + .pfn = __phys_to_pfn(MODEM_PHYS), .length = 0x01000000, .type = MT_DEVICE } @@ -173,6 +164,190 @@ static struct omap_board_config_kernel ams_delta_config[] __initdata = { { OMAP_TAG_LCD, &ams_delta_lcd_config }, }; +static struct resource latch1_resources[] __initconst = { + [0] = { + .name = "dat", + .start = LATCH1_PHYS, + .end = LATCH1_PHYS + (AMS_DELTA_LATCH1_NGPIO - 1) / 8, + .flags = IORESOURCE_MEM, + }, +}; + +static struct bgpio_pdata latch1_pdata __initconst = { + .base = AMS_DELTA_LATCH1_GPIO_BASE, + .ngpio = AMS_DELTA_LATCH1_NGPIO, +}; + +static struct platform_device latch1_gpio_device = { + .name = "basic-mmio-gpio", + .id = 0, + .resource = latch1_resources, + .num_resources = ARRAY_SIZE(latch1_resources), + .dev = { + .platform_data = &latch1_pdata, + }, +}; + +static struct resource latch2_resources[] __initconst = { + [0] = { + .name = "dat", + .start = LATCH2_PHYS, + .end = LATCH2_PHYS + (AMS_DELTA_LATCH2_NGPIO - 1) / 8, + .flags = IORESOURCE_MEM, + }, +}; + +static struct bgpio_pdata latch2_pdata __initconst = { + .base = AMS_DELTA_LATCH2_GPIO_BASE, + .ngpio = AMS_DELTA_LATCH2_NGPIO, +}; + +static struct platform_device latch2_gpio_device = { + .name = "basic-mmio-gpio", + .id = 1, + .resource = latch2_resources, + .num_resources = ARRAY_SIZE(latch2_resources), + .dev = { + .platform_data = &latch2_pdata, + }, +}; + +static struct gpio latch_gpios[] __initconst = { + { + .gpio = AMS_DELTA_GPIO_PIN_LED_CAMERA, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led_camera", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_LED_ADVERT, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led_advert", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_LED_EMAIL, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led_email", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_LED_HANDSFREE, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led_handsfree", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_LED_VOICEMAIL, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led_voicemail", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_LED_VOICE, + .flags = GPIOF_OUT_INIT_LOW, + .label = "led_voice", + }, + { + .gpio = AMS_DELTA_LATCH1_GPIO_BASE + 6, + .flags = GPIOF_OUT_INIT_LOW, + .label = "dockit1", + }, + { + .gpio = AMS_DELTA_LATCH1_GPIO_BASE + 7, + .flags = GPIOF_OUT_INIT_LOW, + .label = "dockit2", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_LCD_VBLEN, + .flags = GPIOF_OUT_INIT_LOW, + .label = "lcd_vblen", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_LCD_NDISP, + .flags = GPIOF_OUT_INIT_LOW, + .label = "lcd_ndisp", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_NCE, + .flags = GPIOF_OUT_INIT_LOW, + .label = "nand_nce", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_NRE, + .flags = GPIOF_OUT_INIT_LOW, + .label = "nand_nre", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_NWP, + .flags = GPIOF_OUT_INIT_LOW, + .label = "nand_nwp", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_NWE, + .flags = GPIOF_OUT_INIT_LOW, + .label = "nand_nwe", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_ALE, + .flags = GPIOF_OUT_INIT_LOW, + .label = "nand_ale", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_CLE, + .flags = GPIOF_OUT_INIT_LOW, + .label = "nand_cle", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR, + .flags = GPIOF_OUT_INIT_LOW, + .label = "keybrd_pwr", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT, + .flags = GPIOF_OUT_INIT_LOW, + .label = "keybrd_dataout", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_SCARD_RSTIN, + .flags = GPIOF_OUT_INIT_LOW, + .label = "scard_rstin", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_SCARD_CMDVCC, + .flags = GPIOF_OUT_INIT_LOW, + .label = "scard_cmdvcc", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_MODEM_NRESET, + .flags = GPIOF_OUT_INIT_LOW, + .label = "modem_nreset", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_MODEM_CODEC, + .flags = GPIOF_OUT_INIT_LOW, + .label = "modem_codec", + }, + { + .gpio = AMS_DELTA_LATCH2_GPIO_BASE + 14, + .flags = GPIOF_OUT_INIT_LOW, + .label = "hookflash1", + }, + { + .gpio = AMS_DELTA_LATCH2_GPIO_BASE + 15, + .flags = GPIOF_OUT_INIT_LOW, + .label = "hookflash2", + }, +}; + +void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value) +{ + int bit = 0; + u16 bitpos = 1 << bit; + + for (; bit < ngpio; bit++, bitpos = bitpos << 1) { + if (!(mask & bitpos)) + continue; + gpio_set_value(base + bit, (value & bitpos) != 0); + } +} +EXPORT_SYMBOL(ams_delta_latch_write); + static struct resource ams_delta_nand_resources[] = { [0] = { .start = OMAP1_MPUIO_BASE, @@ -275,11 +450,13 @@ static struct omap1_cam_platform_data ams_delta_camera_platform_data = { }; static struct platform_device *ams_delta_devices[] __initdata = { + &latch1_gpio_device, + &latch2_gpio_device, &ams_delta_kp_device, &ams_delta_camera_device, }; -static struct platform_device *late_devices[] __initdata = { +static struct platform_device *late_devices[] __initconst = { &ams_delta_nand_device, &ams_delta_lcd_device, &ams_delta_led_device, @@ -325,8 +502,8 @@ static void __init ams_delta_init(void) static struct plat_serial8250_port ams_delta_modem_ports[] = { { - .membase = IOMEM(AMS_DELTA_MODEM_VIRT), - .mapbase = AMS_DELTA_MODEM_PHYS, + .membase = IOMEM(MODEM_VIRT), + .mapbase = MODEM_PHYS, .irq = -EINVAL, /* changed later */ .flags = UPF_BOOT_AUTOCONF, .irqflags = IRQF_TRIGGER_RISING, @@ -352,8 +529,11 @@ static int __init late_init(void) if (!machine_is_ams_delta()) return -ENODEV; - /* Clear latch2 (NAND, LCD, modem enable) */ - ams_delta_latch2_write(~0, 0); + err = gpio_request_array(latch_gpios, ARRAY_SIZE(latch_gpios)); + if (err) { + pr_err("Couldn't take over latch1/latch2 GPIO pins\n"); + return err; + } platform_add_devices(late_devices, ARRAY_SIZE(late_devices)); @@ -399,6 +579,3 @@ MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)") .init_machine = ams_delta_init, .timer = &omap1_timer, MACHINE_END - -EXPORT_SYMBOL(ams_delta_latch1_write); -EXPORT_SYMBOL(ams_delta_latch2_write); diff --git a/arch/arm/plat-omap/include/plat/board-ams-delta.h b/arch/arm/plat-omap/include/plat/board-ams-delta.h index 51b102dc906b..68ffe328a777 100644 --- a/arch/arm/plat-omap/include/plat/board-ams-delta.h +++ b/arch/arm/plat-omap/include/plat/board-ams-delta.h @@ -28,13 +28,6 @@ #if defined (CONFIG_MACH_AMS_DELTA) -#define AMS_DELTA_LATCH1_PHYS 0x01000000 -#define AMS_DELTA_LATCH1_VIRT 0xEA000000 -#define AMS_DELTA_MODEM_PHYS 0x04000000 -#define AMS_DELTA_MODEM_VIRT 0xEB000000 -#define AMS_DELTA_LATCH2_PHYS 0x08000000 -#define AMS_DELTA_LATCH2_VIRT 0xEC000000 - #define AMS_DELTA_LATCH1_LED_CAMERA 0x01 #define AMS_DELTA_LATCH1_LED_ADVERT 0x02 #define AMS_DELTA_LATCH1_LED_EMAIL 0x04 @@ -66,9 +59,41 @@ #define AMS_DELTA_GPIO_PIN_CONFIG 11 #define AMS_DELTA_GPIO_PIN_NAND_RB 12 +#define AMS_DELTA_GPIO_PIN_LED_CAMERA 232 +#define AMS_DELTA_GPIO_PIN_LED_ADVERT 233 +#define AMS_DELTA_GPIO_PIN_LED_EMAIL 234 +#define AMS_DELTA_GPIO_PIN_LED_HANDSFREE 235 +#define AMS_DELTA_GPIO_PIN_LED_VOICEMAIL 236 +#define AMS_DELTA_GPIO_PIN_LED_VOICE 237 + +#define AMS_DELTA_GPIO_PIN_LCD_VBLEN 240 +#define AMS_DELTA_GPIO_PIN_LCD_NDISP 241 +#define AMS_DELTA_GPIO_PIN_NAND_NCE 242 +#define AMS_DELTA_GPIO_PIN_NAND_NRE 243 +#define AMS_DELTA_GPIO_PIN_NAND_NWP 244 +#define AMS_DELTA_GPIO_PIN_NAND_NWE 245 +#define AMS_DELTA_GPIO_PIN_NAND_ALE 246 +#define AMS_DELTA_GPIO_PIN_NAND_CLE 247 +#define AMS_DELTA_GPIO_PIN_KEYBRD_PWR 248 +#define AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT 249 +#define AMS_DELTA_GPIO_PIN_SCARD_RSTIN 250 +#define AMS_DELTA_GPIO_PIN_SCARD_CMDVCC 251 +#define AMS_DELTA_GPIO_PIN_MODEM_NRESET 252 +#define AMS_DELTA_GPIO_PIN_MODEM_CODEC 253 + +#define AMS_DELTA_LATCH1_GPIO_BASE AMS_DELTA_GPIO_PIN_LED_CAMERA +#define AMS_DELTA_LATCH1_NGPIO 8 +#define AMS_DELTA_LATCH2_GPIO_BASE AMS_DELTA_GPIO_PIN_LCD_VBLEN +#define AMS_DELTA_LATCH2_NGPIO 16 + #ifndef __ASSEMBLY__ -void ams_delta_latch1_write(u8 mask, u8 value); -void ams_delta_latch2_write(u16 mask, u16 value); +void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value); +#define ams_delta_latch1_write(mask, value) \ + ams_delta_latch_write(AMS_DELTA_LATCH1_GPIO_BASE, \ + AMS_DELTA_LATCH1_NGPIO, (mask), (value)) +#define ams_delta_latch2_write(mask, value) \ + ams_delta_latch_write(AMS_DELTA_LATCH2_GPIO_BASE, \ + AMS_DELTA_LATCH2_NGPIO, (mask), (value)) #endif #endif /* CONFIG_MACH_AMS_DELTA */ -- GitLab From 5ca6180fa6d7333fb5fabf30420b0e3cc32dd731 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Tue, 20 Dec 2011 00:08:53 +0100 Subject: [PATCH 00021/10698] ARM: OMAP1: ams-delta: supersede custom led device by leds-gpio Now that the Amstrad Delta on-board latches have been converted to GPIO devices, use the generic driver to control on-board LEDs which hang off those latches. Signed-off-by: Janusz Krzysztofik Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/Kconfig | 1 + arch/arm/mach-omap1/board-ams-delta.c | 87 ++++++++++--------- .../plat-omap/include/plat/board-ams-delta.h | 19 ---- 3 files changed, 49 insertions(+), 58 deletions(-) diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index e14532f236a0..5b1edbae6893 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig @@ -156,6 +156,7 @@ config MACH_AMS_DELTA depends on ARCH_OMAP1 && ARCH_OMAP15XX select FIQ select GPIO_GENERIC_PLATFORM + select LEDS_GPIO_REGISTER help Support for the Amstrad E3 (codename Delta) videophone. Say Y here if you have such a device. diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index cff2711dc259..034d0094e93a 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -164,18 +164,21 @@ static struct omap_board_config_kernel ams_delta_config[] __initdata = { { OMAP_TAG_LCD, &ams_delta_lcd_config }, }; +#define LATCH1_GPIO_BASE 232 +#define LATCH1_NGPIO 8 + static struct resource latch1_resources[] __initconst = { [0] = { .name = "dat", .start = LATCH1_PHYS, - .end = LATCH1_PHYS + (AMS_DELTA_LATCH1_NGPIO - 1) / 8, + .end = LATCH1_PHYS + (LATCH1_NGPIO - 1) / 8, .flags = IORESOURCE_MEM, }, }; static struct bgpio_pdata latch1_pdata __initconst = { - .base = AMS_DELTA_LATCH1_GPIO_BASE, - .ngpio = AMS_DELTA_LATCH1_NGPIO, + .base = LATCH1_GPIO_BASE, + .ngpio = LATCH1_NGPIO, }; static struct platform_device latch1_gpio_device = { @@ -214,42 +217,12 @@ static struct platform_device latch2_gpio_device = { static struct gpio latch_gpios[] __initconst = { { - .gpio = AMS_DELTA_GPIO_PIN_LED_CAMERA, - .flags = GPIOF_OUT_INIT_LOW, - .label = "led_camera", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_LED_ADVERT, - .flags = GPIOF_OUT_INIT_LOW, - .label = "led_advert", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_LED_EMAIL, - .flags = GPIOF_OUT_INIT_LOW, - .label = "led_email", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_LED_HANDSFREE, - .flags = GPIOF_OUT_INIT_LOW, - .label = "led_handsfree", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_LED_VOICEMAIL, - .flags = GPIOF_OUT_INIT_LOW, - .label = "led_voicemail", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_LED_VOICE, - .flags = GPIOF_OUT_INIT_LOW, - .label = "led_voice", - }, - { - .gpio = AMS_DELTA_LATCH1_GPIO_BASE + 6, + .gpio = LATCH1_GPIO_BASE + 6, .flags = GPIOF_OUT_INIT_LOW, .label = "dockit1", }, { - .gpio = AMS_DELTA_LATCH1_GPIO_BASE + 7, + .gpio = LATCH1_GPIO_BASE + 7, .flags = GPIOF_OUT_INIT_LOW, .label = "dockit2", }, @@ -399,9 +372,45 @@ static struct platform_device ams_delta_lcd_device = { .id = -1, }; -static struct platform_device ams_delta_led_device = { - .name = "ams-delta-led", - .id = -1 +static struct gpio_led gpio_leds[] __initconst = { + { + .name = "camera", + .gpio = LATCH1_GPIO_BASE + 0, + .default_state = LEDS_GPIO_DEFSTATE_OFF, +#ifdef CONFIG_LEDS_TRIGGERS + .default_trigger = "ams_delta_camera", +#endif + }, + { + .name = "advert", + .gpio = LATCH1_GPIO_BASE + 1, + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, + { + .name = "email", + .gpio = LATCH1_GPIO_BASE + 2, + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, + { + .name = "handsfree", + .gpio = LATCH1_GPIO_BASE + 3, + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, + { + .name = "voicemail", + .gpio = LATCH1_GPIO_BASE + 4, + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, + { + .name = "voice", + .gpio = LATCH1_GPIO_BASE + 5, + .default_state = LEDS_GPIO_DEFSTATE_OFF, + }, +}; + +static struct gpio_led_platform_data leds_pdata __initconst = { + .leds = gpio_leds, + .num_leds = ARRAY_SIZE(gpio_leds), }; static struct i2c_board_info ams_delta_camera_board_info[] = { @@ -459,7 +468,6 @@ static struct platform_device *ams_delta_devices[] __initdata = { static struct platform_device *late_devices[] __initconst = { &ams_delta_nand_device, &ams_delta_lcd_device, - &ams_delta_led_device, }; static void __init ams_delta_init(void) @@ -493,6 +501,7 @@ static void __init ams_delta_init(void) led_trigger_register_simple("ams_delta_camera", &ams_delta_camera_led_trigger); #endif + gpio_led_register_device(-1, &leds_pdata); platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices)); ams_delta_init_fiq(); diff --git a/arch/arm/plat-omap/include/plat/board-ams-delta.h b/arch/arm/plat-omap/include/plat/board-ams-delta.h index 68ffe328a777..a0f86ca75ddc 100644 --- a/arch/arm/plat-omap/include/plat/board-ams-delta.h +++ b/arch/arm/plat-omap/include/plat/board-ams-delta.h @@ -28,13 +28,6 @@ #if defined (CONFIG_MACH_AMS_DELTA) -#define AMS_DELTA_LATCH1_LED_CAMERA 0x01 -#define AMS_DELTA_LATCH1_LED_ADVERT 0x02 -#define AMS_DELTA_LATCH1_LED_EMAIL 0x04 -#define AMS_DELTA_LATCH1_LED_HANDSFREE 0x08 -#define AMS_DELTA_LATCH1_LED_VOICEMAIL 0x10 -#define AMS_DELTA_LATCH1_LED_VOICE 0x20 - #define AMS_DELTA_LATCH2_LCD_VBLEN 0x0001 #define AMS_DELTA_LATCH2_LCD_NDISP 0x0002 #define AMS_DELTA_LATCH2_NAND_NCE 0x0004 @@ -59,13 +52,6 @@ #define AMS_DELTA_GPIO_PIN_CONFIG 11 #define AMS_DELTA_GPIO_PIN_NAND_RB 12 -#define AMS_DELTA_GPIO_PIN_LED_CAMERA 232 -#define AMS_DELTA_GPIO_PIN_LED_ADVERT 233 -#define AMS_DELTA_GPIO_PIN_LED_EMAIL 234 -#define AMS_DELTA_GPIO_PIN_LED_HANDSFREE 235 -#define AMS_DELTA_GPIO_PIN_LED_VOICEMAIL 236 -#define AMS_DELTA_GPIO_PIN_LED_VOICE 237 - #define AMS_DELTA_GPIO_PIN_LCD_VBLEN 240 #define AMS_DELTA_GPIO_PIN_LCD_NDISP 241 #define AMS_DELTA_GPIO_PIN_NAND_NCE 242 @@ -81,16 +67,11 @@ #define AMS_DELTA_GPIO_PIN_MODEM_NRESET 252 #define AMS_DELTA_GPIO_PIN_MODEM_CODEC 253 -#define AMS_DELTA_LATCH1_GPIO_BASE AMS_DELTA_GPIO_PIN_LED_CAMERA -#define AMS_DELTA_LATCH1_NGPIO 8 #define AMS_DELTA_LATCH2_GPIO_BASE AMS_DELTA_GPIO_PIN_LCD_VBLEN #define AMS_DELTA_LATCH2_NGPIO 16 #ifndef __ASSEMBLY__ void ams_delta_latch_write(int base, int ngpio, u16 mask, u16 value); -#define ams_delta_latch1_write(mask, value) \ - ams_delta_latch_write(AMS_DELTA_LATCH1_GPIO_BASE, \ - AMS_DELTA_LATCH1_NGPIO, (mask), (value)) #define ams_delta_latch2_write(mask, value) \ ams_delta_latch_write(AMS_DELTA_LATCH2_GPIO_BASE, \ AMS_DELTA_LATCH2_NGPIO, (mask), (value)) -- GitLab From f6fc8a6a1a08e520ae58b9abd54152aa101af14a Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Tue, 20 Dec 2011 00:08:54 +0100 Subject: [PATCH 00022/10698] LED: drop leds-ams-delta driver This driver is no longer needed after the Amstrad Delta on-board LED devices have been converted to leds-gpio compatible. Signed-off-by: Janusz Krzysztofik Cc: Richard Purdie Signed-off-by: Tony Lindgren --- drivers/leds/Kconfig | 7 -- drivers/leds/Makefile | 1 - drivers/leds/leds-ams-delta.c | 137 ---------------------------------- 3 files changed, 145 deletions(-) delete mode 100644 drivers/leds/leds-ams-delta.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index ff203a421863..352374630c17 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -74,13 +74,6 @@ config LEDS_S3C24XX This option enables support for LEDs connected to GPIO lines on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440. -config LEDS_AMS_DELTA - tristate "LED Support for the Amstrad Delta (E3)" - depends on LEDS_CLASS - depends on MACH_AMS_DELTA - help - This option enables support for the LEDs on Amstrad Delta (E3). - config LEDS_NET48XX tristate "LED Support for Soekris net48xx series Error LED" depends on LEDS_CLASS diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index e4f6bf568880..f2b75b2c2ee9 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o obj-$(CONFIG_LEDS_LM3530) += leds-lm3530.o obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o -obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o obj-$(CONFIG_LEDS_NET5501) += leds-net5501.o obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o diff --git a/drivers/leds/leds-ams-delta.c b/drivers/leds/leds-ams-delta.c deleted file mode 100644 index 8c00937bf7e7..000000000000 --- a/drivers/leds/leds-ams-delta.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * LEDs driver for Amstrad Delta (E3) - * - * Copyright (C) 2006 Jonathan McDowell - * - * 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 -#include -#include -#include -#include -#include - -/* - * Our context - */ -struct ams_delta_led { - struct led_classdev cdev; - u8 bitmask; -}; - -static void ams_delta_led_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - struct ams_delta_led *led_dev = - container_of(led_cdev, struct ams_delta_led, cdev); - - if (value) - ams_delta_latch1_write(led_dev->bitmask, led_dev->bitmask); - else - ams_delta_latch1_write(led_dev->bitmask, 0); -} - -static struct ams_delta_led ams_delta_leds[] = { - { - .cdev = { - .name = "ams-delta::camera", - .brightness_set = ams_delta_led_set, - }, - .bitmask = AMS_DELTA_LATCH1_LED_CAMERA, - }, - { - .cdev = { - .name = "ams-delta::advert", - .brightness_set = ams_delta_led_set, - }, - .bitmask = AMS_DELTA_LATCH1_LED_ADVERT, - }, - { - .cdev = { - .name = "ams-delta::email", - .brightness_set = ams_delta_led_set, - }, - .bitmask = AMS_DELTA_LATCH1_LED_EMAIL, - }, - { - .cdev = { - .name = "ams-delta::handsfree", - .brightness_set = ams_delta_led_set, - }, - .bitmask = AMS_DELTA_LATCH1_LED_HANDSFREE, - }, - { - .cdev = { - .name = "ams-delta::voicemail", - .brightness_set = ams_delta_led_set, - }, - .bitmask = AMS_DELTA_LATCH1_LED_VOICEMAIL, - }, - { - .cdev = { - .name = "ams-delta::voice", - .brightness_set = ams_delta_led_set, - }, - .bitmask = AMS_DELTA_LATCH1_LED_VOICE, - }, -}; - -static int ams_delta_led_probe(struct platform_device *pdev) -{ - int i, ret; - - for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) { - ams_delta_leds[i].cdev.flags |= LED_CORE_SUSPENDRESUME; - ret = led_classdev_register(&pdev->dev, - &ams_delta_leds[i].cdev); - if (ret < 0) - goto fail; - } - - return 0; -fail: - while (--i >= 0) - led_classdev_unregister(&ams_delta_leds[i].cdev); - return ret; -} - -static int ams_delta_led_remove(struct platform_device *pdev) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ams_delta_leds); i++) - led_classdev_unregister(&ams_delta_leds[i].cdev); - - return 0; -} - -static struct platform_driver ams_delta_led_driver = { - .probe = ams_delta_led_probe, - .remove = ams_delta_led_remove, - .driver = { - .name = "ams-delta-led", - .owner = THIS_MODULE, - }, -}; - -static int __init ams_delta_led_init(void) -{ - return platform_driver_register(&ams_delta_led_driver); -} - -static void __exit ams_delta_led_exit(void) -{ - platform_driver_unregister(&ams_delta_led_driver); -} - -module_init(ams_delta_led_init); -module_exit(ams_delta_led_exit); - -MODULE_AUTHOR("Jonathan McDowell "); -MODULE_DESCRIPTION("Amstrad Delta LED driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ams-delta-led"); -- GitLab From 68f0676699fb0e0b18feb8459c35ecdfe3127b3d Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Tue, 20 Dec 2011 00:08:55 +0100 Subject: [PATCH 00023/10698] MTD: NAND: ams-delta: use GPIO instead of custom I/O Don't use Amstrad Delta custom I/O functions for controlling the device, use GPIO API instead. While being at it, add missing gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB). Signed-off-by: Janusz Krzysztofik Cc: David Woodhouse Reviewed-by: Artem Bityutskiy Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-ams-delta.c | 30 -------- .../plat-omap/include/plat/board-ams-delta.h | 6 -- drivers/mtd/nand/ams-delta.c | 74 +++++++++++++------ 3 files changed, 52 insertions(+), 58 deletions(-) diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 034d0094e93a..cc6f96249e77 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -236,36 +236,6 @@ static struct gpio latch_gpios[] __initconst = { .flags = GPIOF_OUT_INIT_LOW, .label = "lcd_ndisp", }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_NCE, - .flags = GPIOF_OUT_INIT_LOW, - .label = "nand_nce", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_NRE, - .flags = GPIOF_OUT_INIT_LOW, - .label = "nand_nre", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_NWP, - .flags = GPIOF_OUT_INIT_LOW, - .label = "nand_nwp", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_NWE, - .flags = GPIOF_OUT_INIT_LOW, - .label = "nand_nwe", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_ALE, - .flags = GPIOF_OUT_INIT_LOW, - .label = "nand_ale", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_NAND_CLE, - .flags = GPIOF_OUT_INIT_LOW, - .label = "nand_cle", - }, { .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR, .flags = GPIOF_OUT_INIT_LOW, diff --git a/arch/arm/plat-omap/include/plat/board-ams-delta.h b/arch/arm/plat-omap/include/plat/board-ams-delta.h index a0f86ca75ddc..3e578339fe8c 100644 --- a/arch/arm/plat-omap/include/plat/board-ams-delta.h +++ b/arch/arm/plat-omap/include/plat/board-ams-delta.h @@ -30,12 +30,6 @@ #define AMS_DELTA_LATCH2_LCD_VBLEN 0x0001 #define AMS_DELTA_LATCH2_LCD_NDISP 0x0002 -#define AMS_DELTA_LATCH2_NAND_NCE 0x0004 -#define AMS_DELTA_LATCH2_NAND_NRE 0x0008 -#define AMS_DELTA_LATCH2_NAND_NWP 0x0010 -#define AMS_DELTA_LATCH2_NAND_NWE 0x0020 -#define AMS_DELTA_LATCH2_NAND_ALE 0x0040 -#define AMS_DELTA_LATCH2_NAND_CLE 0x0080 #define AMD_DELTA_LATCH2_KEYBRD_PWR 0x0100 #define AMD_DELTA_LATCH2_KEYBRD_DATA 0x0200 #define AMD_DELTA_LATCH2_SCARD_RSTIN 0x0400 diff --git a/drivers/mtd/nand/ams-delta.c b/drivers/mtd/nand/ams-delta.c index 9e6b498c9beb..5769bd234283 100644 --- a/drivers/mtd/nand/ams-delta.c +++ b/drivers/mtd/nand/ams-delta.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include /* @@ -34,8 +34,6 @@ */ static struct mtd_info *ams_delta_mtd = NULL; -#define NAND_MASK (AMS_DELTA_LATCH2_NAND_NRE | AMS_DELTA_LATCH2_NAND_NWE | AMS_DELTA_LATCH2_NAND_CLE | AMS_DELTA_LATCH2_NAND_ALE | AMS_DELTA_LATCH2_NAND_NCE | AMS_DELTA_LATCH2_NAND_NWP) - /* * Define partitions for flash devices */ @@ -68,10 +66,9 @@ static void ams_delta_write_byte(struct mtd_info *mtd, u_char byte) writew(0, io_base + OMAP_MPUIO_IO_CNTL); writew(byte, this->IO_ADDR_W); - ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, 0); + gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 0); ndelay(40); - ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NWE, - AMS_DELTA_LATCH2_NAND_NWE); + gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NWE, 1); } static u_char ams_delta_read_byte(struct mtd_info *mtd) @@ -80,12 +77,11 @@ static u_char ams_delta_read_byte(struct mtd_info *mtd) struct nand_chip *this = mtd->priv; void __iomem *io_base = this->priv; - ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, 0); + gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 0); ndelay(40); writew(~0, io_base + OMAP_MPUIO_IO_CNTL); res = readw(this->IO_ADDR_R); - ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_NRE, - AMS_DELTA_LATCH2_NAND_NRE); + gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NRE, 1); return res; } @@ -132,15 +128,12 @@ static void ams_delta_hwcontrol(struct mtd_info *mtd, int cmd, { if (ctrl & NAND_CTRL_CHANGE) { - unsigned long bits; - - bits = (~ctrl & NAND_NCE) ? AMS_DELTA_LATCH2_NAND_NCE : 0; - bits |= (ctrl & NAND_CLE) ? AMS_DELTA_LATCH2_NAND_CLE : 0; - bits |= (ctrl & NAND_ALE) ? AMS_DELTA_LATCH2_NAND_ALE : 0; - - ams_delta_latch2_write(AMS_DELTA_LATCH2_NAND_CLE | - AMS_DELTA_LATCH2_NAND_ALE | - AMS_DELTA_LATCH2_NAND_NCE, bits); + gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_NCE, + (ctrl & NAND_NCE) == 0); + gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_CLE, + (ctrl & NAND_CLE) != 0); + gpio_set_value(AMS_DELTA_GPIO_PIN_NAND_ALE, + (ctrl & NAND_ALE) != 0); } if (cmd != NAND_CMD_NONE) @@ -152,6 +145,39 @@ static int ams_delta_nand_ready(struct mtd_info *mtd) return gpio_get_value(AMS_DELTA_GPIO_PIN_NAND_RB); } +static struct gpio _mandatory_gpio[] __initconst_or_module = { + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_NCE, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "nand_nce", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_NRE, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "nand_nre", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_NWP, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "nand_nwp", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_NWE, + .flags = GPIOF_OUT_INIT_HIGH, + .label = "nand_nwe", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_ALE, + .flags = GPIOF_OUT_INIT_LOW, + .label = "nand_ale", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_NAND_CLE, + .flags = GPIOF_OUT_INIT_LOW, + .label = "nand_cle", + }, +}; + /* * Main initialization routine */ @@ -223,10 +249,9 @@ static int __devinit ams_delta_init(struct platform_device *pdev) platform_set_drvdata(pdev, io_base); /* Set chip enabled, but */ - ams_delta_latch2_write(NAND_MASK, AMS_DELTA_LATCH2_NAND_NRE | - AMS_DELTA_LATCH2_NAND_NWE | - AMS_DELTA_LATCH2_NAND_NCE | - AMS_DELTA_LATCH2_NAND_NWP); + err = gpio_request_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); + if (err) + goto out_gpio; /* Scan to find existence of the device */ if (nand_scan(ams_delta_mtd, 1)) { @@ -241,7 +266,10 @@ static int __devinit ams_delta_init(struct platform_device *pdev) goto out; out_mtd: + gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); +out_gpio: platform_set_drvdata(pdev, NULL); + gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); iounmap(io_base); out_release_io: release_mem_region(res->start, resource_size(res)); @@ -262,6 +290,8 @@ static int __devexit ams_delta_cleanup(struct platform_device *pdev) /* Release resources, unregister device */ nand_release(ams_delta_mtd); + gpio_free_array(_mandatory_gpio, ARRAY_SIZE(_mandatory_gpio)); + gpio_free(AMS_DELTA_GPIO_PIN_NAND_RB); iounmap(io_base); release_mem_region(res->start, resource_size(res)); -- GitLab From a218d19f6a91c076c7ed8a7c0082f777248c5394 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Tue, 20 Dec 2011 00:08:56 +0100 Subject: [PATCH 00024/10698] omapfb: lcd_ams_delta: drive control lines over GPIO Don't use Amstrad Delta custom I/O functions any longer, use GPIO API instead. Signed-off-by: Janusz Krzysztofik Acked-by: Tomi Valkeinen Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-ams-delta.c | 10 ------- .../plat-omap/include/plat/board-ams-delta.h | 2 -- drivers/video/omap/lcd_ams_delta.c | 27 ++++++++++++++----- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index cc6f96249e77..3aba8f99cc7e 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -226,16 +226,6 @@ static struct gpio latch_gpios[] __initconst = { .flags = GPIOF_OUT_INIT_LOW, .label = "dockit2", }, - { - .gpio = AMS_DELTA_GPIO_PIN_LCD_VBLEN, - .flags = GPIOF_OUT_INIT_LOW, - .label = "lcd_vblen", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_LCD_NDISP, - .flags = GPIOF_OUT_INIT_LOW, - .label = "lcd_ndisp", - }, { .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR, .flags = GPIOF_OUT_INIT_LOW, diff --git a/arch/arm/plat-omap/include/plat/board-ams-delta.h b/arch/arm/plat-omap/include/plat/board-ams-delta.h index 3e578339fe8c..e9ad673be32f 100644 --- a/arch/arm/plat-omap/include/plat/board-ams-delta.h +++ b/arch/arm/plat-omap/include/plat/board-ams-delta.h @@ -28,8 +28,6 @@ #if defined (CONFIG_MACH_AMS_DELTA) -#define AMS_DELTA_LATCH2_LCD_VBLEN 0x0001 -#define AMS_DELTA_LATCH2_LCD_NDISP 0x0002 #define AMD_DELTA_LATCH2_KEYBRD_PWR 0x0100 #define AMD_DELTA_LATCH2_KEYBRD_DATA 0x0200 #define AMD_DELTA_LATCH2_SCARD_RSTIN 0x0400 diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c index 6978ae4ef83a..73b211b92a39 100644 --- a/drivers/video/omap/lcd_ams_delta.c +++ b/drivers/video/omap/lcd_ams_delta.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -98,29 +99,41 @@ static struct lcd_ops ams_delta_lcd_ops = { /* omapfb panel section */ +static struct gpio _gpios[] __initconst_or_module = { + { + .gpio = AMS_DELTA_GPIO_PIN_LCD_VBLEN, + .flags = GPIOF_OUT_INIT_LOW, + .label = "lcd_vblen", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_LCD_NDISP, + .flags = GPIOF_OUT_INIT_LOW, + .label = "lcd_ndisp", + }, +}; + static int ams_delta_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) { - return 0; + return gpio_request_array(_gpios, ARRAY_SIZE(_gpios)); } static void ams_delta_panel_cleanup(struct lcd_panel *panel) { + gpio_free_array(_gpios, ARRAY_SIZE(_gpios)); } static int ams_delta_panel_enable(struct lcd_panel *panel) { - ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP, - AMS_DELTA_LATCH2_LCD_NDISP); - ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN, - AMS_DELTA_LATCH2_LCD_VBLEN); + gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 1); + gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 1); return 0; } static void ams_delta_panel_disable(struct lcd_panel *panel) { - ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN, 0); - ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_NDISP, 0); + gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_VBLEN, 0); + gpio_set_value(AMS_DELTA_GPIO_PIN_LCD_NDISP, 0); } static unsigned long ams_delta_panel_get_caps(struct lcd_panel *panel) -- GitLab From 8d09a1bb3147ddbcf0a9483021ca699c54c54732 Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Tue, 20 Dec 2011 23:10:34 +0100 Subject: [PATCH 00025/10698] input: serio: ams-delta: toggle keyboard power over GPIO Don't use Amstrad Delta custom I/O functions once GPIO interface is available for the underlying hardware. While requesting and initializing GPIO pins used, also take care of one extra pin KEYBRD_DATAOUT which, even if not used by the driver, belongs to the device and affects its functioning. Once done, move the driver initialization back to the device_initcall level, reverting the temporary chane introduced with patch 1/7 "ARM: OMAP1: ams-delta: register latch dependent devices later". That change is no longer required once the driver takes care of registering used GPIO pins, and it's better to initialize the device before others using the latch2 based GPIO pins, otherwise a garbage is reported on boot, perhaps due to random data already captured by the FIQ handler while the keyboard related latch bits are written with random values during initialization of those other latch2 dependent devices. Signed-off-by: Janusz Krzysztofik Acked-by: Dmitry Torokhov [tony@atomide.com: renamed _gpios to ams_delta_gpios] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap1/board-ams-delta.c | 10 ---- .../plat-omap/include/plat/board-ams-delta.h | 2 - drivers/input/serio/ams_delta_serio.c | 56 ++++++++++++------- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c index 3aba8f99cc7e..673cf21a90f8 100644 --- a/arch/arm/mach-omap1/board-ams-delta.c +++ b/arch/arm/mach-omap1/board-ams-delta.c @@ -226,16 +226,6 @@ static struct gpio latch_gpios[] __initconst = { .flags = GPIOF_OUT_INIT_LOW, .label = "dockit2", }, - { - .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR, - .flags = GPIOF_OUT_INIT_LOW, - .label = "keybrd_pwr", - }, - { - .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT, - .flags = GPIOF_OUT_INIT_LOW, - .label = "keybrd_dataout", - }, { .gpio = AMS_DELTA_GPIO_PIN_SCARD_RSTIN, .flags = GPIOF_OUT_INIT_LOW, diff --git a/arch/arm/plat-omap/include/plat/board-ams-delta.h b/arch/arm/plat-omap/include/plat/board-ams-delta.h index e9ad673be32f..027e79eead5e 100644 --- a/arch/arm/plat-omap/include/plat/board-ams-delta.h +++ b/arch/arm/plat-omap/include/plat/board-ams-delta.h @@ -28,8 +28,6 @@ #if defined (CONFIG_MACH_AMS_DELTA) -#define AMD_DELTA_LATCH2_KEYBRD_PWR 0x0100 -#define AMD_DELTA_LATCH2_KEYBRD_DATA 0x0200 #define AMD_DELTA_LATCH2_SCARD_RSTIN 0x0400 #define AMD_DELTA_LATCH2_SCARD_CMDVCC 0x0800 #define AMS_DELTA_LATCH2_MODEM_NRESET 0x1000 diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c index 835d37abe62a..0571e2ec358b 100644 --- a/drivers/input/serio/ams_delta_serio.c +++ b/drivers/input/serio/ams_delta_serio.c @@ -92,8 +92,7 @@ static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id) static int ams_delta_serio_open(struct serio *serio) { /* enable keyboard */ - ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR, - AMD_DELTA_LATCH2_KEYBRD_PWR); + gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 1); return 0; } @@ -101,9 +100,32 @@ static int ams_delta_serio_open(struct serio *serio) static void ams_delta_serio_close(struct serio *serio) { /* disable keyboard */ - ams_delta_latch2_write(AMD_DELTA_LATCH2_KEYBRD_PWR, 0); + gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0); } +static struct gpio ams_delta_gpios[] __initconst_or_module = { + { + .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATA, + .flags = GPIOF_DIR_IN, + .label = "serio-data", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK, + .flags = GPIOF_DIR_IN, + .label = "serio-clock", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR, + .flags = GPIOF_OUT_INIT_LOW, + .label = "serio-power", + }, + { + .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT, + .flags = GPIOF_OUT_INIT_LOW, + .label = "serio-dataout", + }, +}; + static int __init ams_delta_serio_init(void) { int err; @@ -123,19 +145,12 @@ static int __init ams_delta_serio_init(void) strlcpy(ams_delta_serio->phys, "GPIO/serio0", sizeof(ams_delta_serio->phys)); - err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_DATA, "serio-data"); + err = gpio_request_array(ams_delta_gpios, + ARRAY_SIZE(ams_delta_gpios)); if (err) { - pr_err("ams_delta_serio: Couldn't request gpio pin for data\n"); + pr_err("ams_delta_serio: Couldn't request gpio pins\n"); goto serio; } - gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); - - err = gpio_request(AMS_DELTA_GPIO_PIN_KEYBRD_CLK, "serio-clock"); - if (err) { - pr_err("ams_delta_serio: couldn't request gpio pin for clock\n"); - goto gpio_data; - } - gpio_direction_input(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING, @@ -143,7 +158,7 @@ static int __init ams_delta_serio_init(void) if (err < 0) { pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n", gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK)); - goto gpio_clk; + goto gpio; } /* * Since GPIO register handling for keyboard clock pin is performed @@ -157,21 +172,20 @@ static int __init ams_delta_serio_init(void) dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name); return 0; -gpio_clk: - gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); -gpio_data: - gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); +gpio: + gpio_free_array(ams_delta_gpios, + ARRAY_SIZE(ams_delta_gpios)); serio: kfree(ams_delta_serio); return err; } -late_initcall(ams_delta_serio_init); +module_init(ams_delta_serio_init); static void __exit ams_delta_serio_exit(void) { serio_unregister_port(ams_delta_serio); free_irq(OMAP_GPIO_IRQ(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0); - gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_CLK); - gpio_free(AMS_DELTA_GPIO_PIN_KEYBRD_DATA); + gpio_free_array(ams_delta_gpios, + ARRAY_SIZE(ams_delta_gpios)); } module_exit(ams_delta_serio_exit); -- GitLab From 5e13fd354a39d637df9b25edcb2964edf4a7c534 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 13 Dec 2011 17:19:57 +0530 Subject: [PATCH 00026/10698] ath6kl: Use cfg80211_roamed_bss() to report roaming event This is to avoid the scenario where the bss entry of the AP got expired when reporting roaming event to current AP. As the bss entry for the current bss is available in driver, pass this bss to cfg80211. This fixes WARNING: at net/wireless/sme.c:586. This patch depends on the following patch in cfg80211 "cfg80211: Fix race in bss timeout". Reported-by: Kalle Valo Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 37 +++++++++++----------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 6c59a217b1a1..85c24dd01565 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -605,11 +605,13 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, return 0; } -static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, - enum network_type nw_type, - const u8 *bssid, - struct ieee80211_channel *chan, - const u8 *beacon_ie, size_t beacon_ie_len) +static struct cfg80211_bss * +ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, + enum network_type nw_type, + const u8 *bssid, + struct ieee80211_channel *chan, + const u8 *beacon_ie, + size_t beacon_ie_len) { struct ath6kl *ar = vif->ar; struct cfg80211_bss *bss; @@ -638,7 +640,7 @@ static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, */ ie = kmalloc(2 + vif->ssid_len + beacon_ie_len, GFP_KERNEL); if (ie == NULL) - return -ENOMEM; + return NULL; ie[0] = WLAN_EID_SSID; ie[1] = vif->ssid_len; memcpy(ie + 2, vif->ssid, vif->ssid_len); @@ -652,15 +654,9 @@ static int ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, "cfg80211\n", bssid); kfree(ie); } else - ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss " - "entry\n"); - - if (bss == NULL) - return -ENOMEM; + ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); - cfg80211_put_bss(bss); - - return 0; + return bss; } void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, @@ -672,6 +668,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, { struct ieee80211_channel *chan; struct ath6kl *ar = vif->ar; + struct cfg80211_bss *bss; /* capinfo + listen interval */ u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16); @@ -712,8 +709,9 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, chan = ieee80211_get_channel(ar->wiphy, (int) channel); - if (ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan, assoc_info, - beacon_ie_len) < 0) { + bss = ath6kl_add_bss_if_needed(vif, nw_type, bssid, chan, + assoc_info, beacon_ie_len); + if (!bss) { ath6kl_err("could not add cfg80211 bss entry\n"); return; } @@ -722,6 +720,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", nw_type & ADHOC_CREATOR ? "creator" : "joiner"); cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); + cfg80211_put_bss(bss); return; } @@ -732,11 +731,11 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, assoc_req_ie, assoc_req_len, assoc_resp_ie, assoc_resp_len, WLAN_STATUS_SUCCESS, GFP_KERNEL); + cfg80211_put_bss(bss); } else if (vif->sme_state == SME_CONNECTED) { /* inform roam event to cfg80211 */ - cfg80211_roamed(vif->ndev, chan, bssid, - assoc_req_ie, assoc_req_len, - assoc_resp_ie, assoc_resp_len, GFP_KERNEL); + cfg80211_roamed_bss(vif->ndev, bss, assoc_req_ie, assoc_req_len, + assoc_resp_ie, assoc_resp_len, GFP_KERNEL); } } -- GitLab From 6e786cb1e514dc87647beccaa96bd8a255d97a0c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 15 Dec 2011 14:16:00 +0200 Subject: [PATCH 00027/10698] ath6kl: Fix connect command to clear previously used IEs Empty IE buffer means that the new association is not supposed to include extra IEs. Make sure any previously configured (Re)Association Request frame IEs get cleared in such a case. This is based on a patch from Shuibing. Cc: Dai Shuibing Signed-off-by: Jouni Malinen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 85c24dd01565..1a06a04c5106 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -461,13 +461,13 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } } - if (sme->ie && (sme->ie_len > 0)) { - status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len); - if (status) { - up(&ar->sem); - return status; - } - } else + status = ath6kl_set_assoc_req_ies(vif, sme->ie, sme->ie_len); + if (status) { + up(&ar->sem); + return status; + } + + if (sme->ie == NULL || sme->ie_len == 0) ar->connect_ctrl_flags &= ~CONNECT_WPS_FLAG; if (test_bit(CONNECTED, &vif->flags) && -- GitLab From ca1d16a08fc2c26b693e65ad92fa37a4c778e60d Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 16 Dec 2011 14:24:23 +0530 Subject: [PATCH 00028/10698] ath6kl: Avoid taking struct as argument in ath6kl_wmi_set_ip_cmd In this way, caller is free to pass only the value of IP addr to configure. In addition to this, * 'ips' variable data type in struct wmi_set_ip_cmd is changed from __le32 to __be32 in order to match network byte order. * ipv4_is_multicast() is used to validate multicast ip addr. * New argument if_idx is added to supply correct vif index to ath6kl_wmi_cmd_send(). This will be used in the next patch. Signed-off-by: Raja Mani Signed-off-by: Thirumalai Pachamuthu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/wmi.c | 12 +++++++----- drivers/net/wireless/ath/ath6kl/wmi.h | 5 +++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index f6f2aa27fc20..1e31c38abb4f 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2479,15 +2479,16 @@ int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 if_idx, u8 traffic_class, return ret; } -int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) +int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, + __be32 ips0, __be32 ips1) { struct sk_buff *skb; struct wmi_set_ip_cmd *cmd; int ret; /* Multicast address are not valid */ - if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) || - (*((u8 *) &ip_cmd->ips[1]) >= 0xE0)) + if (ipv4_is_multicast(ips0) || + ipv4_is_multicast(ips1)) return -EINVAL; skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd)); @@ -2495,9 +2496,10 @@ int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd) return -ENOMEM; cmd = (struct wmi_set_ip_cmd *) skb->data; - memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd)); + cmd->ips[0] = ips0; + cmd->ips[1] = ips1; - ret = ath6kl_wmi_cmd_send(wmi, 0, skb, WMI_SET_IP_CMDID, + ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_SET_IP_CMDID, NO_SYNC_WMIFLAG); return ret; } diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 42ac311eda4e..96e3cc10cab2 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -1903,7 +1903,7 @@ struct wow_filter { struct wmi_set_ip_cmd { /* IP in network byte order */ - __le32 ips[MAX_IP_ADDRS]; + __be32 ips[MAX_IP_ADDRS]; } __packed; enum ath6kl_wow_filters { @@ -2417,7 +2417,8 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); s32 ath6kl_wmi_get_rate(s8 rate_index); -int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd); +int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx, + __be32 ips0, __be32 ips1); int ath6kl_wmi_set_host_sleep_mode_cmd(struct wmi *wmi, u8 if_idx, enum ath6kl_host_mode host_mode); int ath6kl_wmi_set_wow_mode_cmd(struct wmi *wmi, u8 if_idx, -- GitLab From c08631c6e43e7ce91bca6b2d3466bb22a85fe724 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Fri, 16 Dec 2011 14:24:24 +0530 Subject: [PATCH 00029/10698] ath6kl: Send own IP addr to the firmware during WOW suspend Firmware ARP module requires own IP addr in order to respond to the outside world when the target is in WOW suspend state. At present, firmware ARP module has capability to hold 2 IP addr. So, WOW mode will be disabled if the total IP addr configured in net_dev for our device is greater than firmware limit (MAX_IP_ADDRS) which is 2 at this moment. Signed-off-by: Raja Mani Signed-off-by: Thirumalai Pachamuthu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 33 +++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 1a06a04c5106..45b0d974e4f7 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -15,6 +15,7 @@ */ #include +#include #include "core.h" #include "cfg80211.h" @@ -1729,11 +1730,14 @@ static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev) static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) { + struct in_device *in_dev; + struct in_ifaddr *ifa; struct ath6kl_vif *vif; int ret, pos, left; u32 filter = 0; u16 i; - u8 mask[WOW_MASK_SIZE]; + u8 mask[WOW_MASK_SIZE], index = 0; + __be32 ips[MAX_IP_ADDRS]; vif = ath6kl_vif_first(ar); if (!vif) @@ -1780,6 +1784,33 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) return ret; } + /* Setup own IP addr for ARP agent. */ + in_dev = __in_dev_get_rtnl(vif->ndev); + if (!in_dev) + goto skip_arp; + + ifa = in_dev->ifa_list; + memset(&ips, 0, sizeof(ips)); + + /* Configure IP addr only if IP address count < MAX_IP_ADDRS */ + while (index < MAX_IP_ADDRS && ifa) { + ips[index] = ifa->ifa_local; + ifa = ifa->ifa_next; + index++; + } + + if (ifa) { + ath6kl_err("total IP addr count is exceeding fw limit\n"); + return -EINVAL; + } + + ret = ath6kl_wmi_set_ip_cmd(ar->wmi, vif->fw_vif_idx, ips[0], ips[1]); + if (ret) { + ath6kl_err("fail to setup ip for arp agent\n"); + return ret; + } + +skip_arp: if (wow->disconnect) filter |= WOW_FILTER_OPTION_NWK_DISASSOC; -- GitLab From c0038972b1253ad7f3ab7cc35ed57a830f5c8568 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Fri, 16 Dec 2011 20:53:31 +0200 Subject: [PATCH 00030/10698] ath6kl: handle firmware names more dynamically Currently ath6kl has just hardcoded paths to each firmware file. Change this more dynamic by separating the the directory and file name from each other. That way it's easier to dynamically create full paths to firmware and code looks better. And now it's possible to remove a function needed by devicetree code. While at it add a structure inside struct ath6kl_hw to contain all firmware names. I deliberately omitted board file support as those will be handled later. This is needed for firmware API 3. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 45 ++++++------ drivers/net/wireless/ath/ath6kl/init.c | 95 ++++++++++++++------------ drivers/net/wireless/ath/ath6kl/sdio.c | 16 ++--- drivers/net/wireless/ath/ath6kl/usb.c | 5 +- 4 files changed, 87 insertions(+), 74 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index c863a28f2e0c..267957712564 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -97,45 +97,46 @@ struct ath6kl_fw_ie { u8 data[0]; }; +#define ATH6KL_FW_API2_FILE "fw-2.bin" + /* AR6003 1.0 definitions */ #define AR6003_HW_1_0_VERSION 0x300002ba /* AR6003 2.0 definitions */ #define AR6003_HW_2_0_VERSION 0x30000384 #define AR6003_HW_2_0_PATCH_DOWNLOAD_ADDRESS 0x57e910 -#define AR6003_HW_2_0_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77" -#define AR6003_HW_2_0_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77" -#define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athtcmd_ram.bin" -#define AR6003_HW_2_0_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin" -#define AR6003_HW_2_0_FIRMWARE_2_FILE "ath6k/AR6003/hw2.0/fw-2.bin" +#define AR6003_HW_2_0_FW_DIR "ath6k/AR6003/hw2.0" +#define AR6003_HW_2_0_OTP_FILE "otp.bin.z77" +#define AR6003_HW_2_0_FIRMWARE_FILE "athwlan.bin.z77" +#define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" +#define AR6003_HW_2_0_PATCH_FILE "data.patch.bin" #define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ "ath6k/AR6003/hw2.0/bdata.SD31.bin" /* AR6003 3.0 definitions */ #define AR6003_HW_2_1_1_VERSION 0x30000582 -#define AR6003_HW_2_1_1_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin" -#define AR6003_HW_2_1_1_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin" -#define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE \ - "ath6k/AR6003/hw2.1.1/athtcmd_ram.bin" -#define AR6003_HW_2_1_1_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin" -#define AR6003_HW_2_1_1_FIRMWARE_2_FILE "ath6k/AR6003/hw2.1.1/fw-2.bin" +#define AR6003_HW_2_1_1_FW_DIR "ath6k/AR6003/hw2.1.1" +#define AR6003_HW_2_1_1_OTP_FILE "otp.bin" +#define AR6003_HW_2_1_1_FIRMWARE_FILE "athwlan.bin" +#define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" +#define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin" #define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" /* AR6004 1.0 definitions */ #define AR6004_HW_1_0_VERSION 0x30000623 -#define AR6004_HW_1_0_FIRMWARE_2_FILE "ath6k/AR6004/hw1.0/fw-2.bin" -#define AR6004_HW_1_0_FIRMWARE_FILE "ath6k/AR6004/hw1.0/fw.ram.bin" +#define AR6004_HW_1_0_FW_DIR "ath6k/AR6004/hw1.0" +#define AR6004_HW_1_0_FIRMWARE_FILE "fw.ram.bin" #define AR6004_HW_1_0_BOARD_DATA_FILE "ath6k/AR6004/hw1.0/bdata.bin" #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ "ath6k/AR6004/hw1.0/bdata.DB132.bin" /* AR6004 1.1 definitions */ #define AR6004_HW_1_1_VERSION 0x30000001 -#define AR6004_HW_1_1_FIRMWARE_2_FILE "ath6k/AR6004/hw1.1/fw-2.bin" -#define AR6004_HW_1_1_FIRMWARE_FILE "ath6k/AR6004/hw1.1/fw.ram.bin" +#define AR6004_HW_1_1_FW_DIR "ath6k/AR6004/hw1.1" +#define AR6004_HW_1_1_FIRMWARE_FILE "fw.ram.bin" #define AR6004_HW_1_1_BOARD_DATA_FILE "ath6k/AR6004/hw1.1/bdata.bin" #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ "ath6k/AR6004/hw1.1/bdata.DB132.bin" @@ -575,11 +576,15 @@ struct ath6kl { u32 refclk_hz; u32 uarttx_pin; - const char *fw_otp; - const char *fw; - const char *fw_tcmd; - const char *fw_patch; - const char *fw_api2; + struct ath6kl_hw_fw { + const char *dir; + const char *otp; + const char *fw; + const char *tcmd; + const char *patch; + const char *api2; + } fw; + const char *fw_board; const char *fw_default_board; } hw; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 368ecbd172a3..7b802e99851c 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -47,11 +47,15 @@ static const struct ath6kl_hw hw_list[] = { /* hw2.0 needs override address hardcoded */ .app_start_override_addr = 0x944C00, - .fw_otp = AR6003_HW_2_0_OTP_FILE, - .fw = AR6003_HW_2_0_FIRMWARE_FILE, - .fw_tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, - .fw_patch = AR6003_HW_2_0_PATCH_FILE, - .fw_api2 = AR6003_HW_2_0_FIRMWARE_2_FILE, + .fw = { + .dir = AR6003_HW_2_0_FW_DIR, + .otp = AR6003_HW_2_0_OTP_FILE, + .fw = AR6003_HW_2_0_FIRMWARE_FILE, + .tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, + .patch = AR6003_HW_2_0_PATCH_FILE, + .api2 = ATH6KL_FW_API2_FILE, + }, + .fw_board = AR6003_HW_2_0_BOARD_DATA_FILE, .fw_default_board = AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE, }, @@ -65,11 +69,15 @@ static const struct ath6kl_hw hw_list[] = { .refclk_hz = 26000000, .uarttx_pin = 8, - .fw_otp = AR6003_HW_2_1_1_OTP_FILE, - .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, - .fw_tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, - .fw_patch = AR6003_HW_2_1_1_PATCH_FILE, - .fw_api2 = AR6003_HW_2_1_1_FIRMWARE_2_FILE, + .fw = { + .dir = AR6003_HW_2_1_1_FW_DIR, + .otp = AR6003_HW_2_1_1_OTP_FILE, + .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, + .tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, + .patch = AR6003_HW_2_1_1_PATCH_FILE, + .api2 = ATH6KL_FW_API2_FILE, + }, + .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, .fw_default_board = AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE, }, @@ -84,8 +92,12 @@ static const struct ath6kl_hw hw_list[] = { .refclk_hz = 26000000, .uarttx_pin = 11, - .fw = AR6004_HW_1_0_FIRMWARE_FILE, - .fw_api2 = AR6004_HW_1_0_FIRMWARE_2_FILE, + .fw = { + .dir = AR6004_HW_1_0_FW_DIR, + .fw = AR6004_HW_1_0_FIRMWARE_FILE, + .api2 = ATH6KL_FW_API2_FILE, + }, + .fw_board = AR6004_HW_1_0_BOARD_DATA_FILE, .fw_default_board = AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE, }, @@ -100,8 +112,12 @@ static const struct ath6kl_hw hw_list[] = { .refclk_hz = 40000000, .uarttx_pin = 11, - .fw = AR6004_HW_1_1_FIRMWARE_FILE, - .fw_api2 = AR6004_HW_1_1_FIRMWARE_2_FILE, + .fw = { + .dir = AR6004_HW_1_1_FW_DIR, + .fw = AR6004_HW_1_1_FIRMWARE_FILE, + .api2 = ATH6KL_FW_API2_FILE, + }, + .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, }, @@ -626,21 +642,6 @@ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, } #ifdef CONFIG_OF -static const char *get_target_ver_dir(const struct ath6kl *ar) -{ - switch (ar->version.target_ver) { - case AR6003_HW_1_0_VERSION: - return "ath6k/AR6003/hw1.0"; - case AR6003_HW_2_0_VERSION: - return "ath6k/AR6003/hw2.0"; - case AR6003_HW_2_1_1_VERSION: - return "ath6k/AR6003/hw2.1.1"; - } - ath6kl_warn("%s: unsupported target version 0x%x.\n", __func__, - ar->version.target_ver); - return NULL; -} - /* * Check the device tree for a board-id and use it to construct * the pathname to the firmware file. Used (for now) to find a @@ -663,7 +664,7 @@ static bool check_device_tree(struct ath6kl *ar) continue; } snprintf(board_filename, sizeof(board_filename), - "%s/bdata.%s.bin", get_target_ver_dir(ar), board_id); + "%s/bdata.%s.bin", ar->hw.fw.dir, board_id); ret = ath6kl_get_fw(ar, board_filename, &ar->fw_board, &ar->fw_board_len); @@ -730,19 +731,20 @@ static int ath6kl_fetch_board_file(struct ath6kl *ar) static int ath6kl_fetch_otp_file(struct ath6kl *ar) { - const char *filename; + char filename[100]; int ret; if (ar->fw_otp != NULL) return 0; - if (ar->hw.fw_otp == NULL) { + if (ar->hw.fw.otp == NULL) { ath6kl_dbg(ATH6KL_DBG_BOOT, "no OTP file configured for this hw\n"); return 0; } - filename = ar->hw.fw_otp; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.otp); ret = ath6kl_get_fw(ar, filename, &ar->fw_otp, &ar->fw_otp_len); @@ -757,29 +759,32 @@ static int ath6kl_fetch_otp_file(struct ath6kl *ar) static int ath6kl_fetch_fw_file(struct ath6kl *ar) { - const char *filename; + char filename[100]; int ret; if (ar->fw != NULL) return 0; if (testmode) { - if (ar->hw.fw_tcmd == NULL) { + if (ar->hw.fw.tcmd == NULL) { ath6kl_warn("testmode not supported\n"); return -EOPNOTSUPP; } - filename = ar->hw.fw_tcmd; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.tcmd); set_bit(TESTMODE, &ar->flag); goto get_fw; } - if (WARN_ON(ar->hw.fw == NULL)) + /* FIXME: remove WARN_ON() as we won't support FW API 1 for long */ + if (WARN_ON(ar->hw.fw.fw == NULL)) return -EINVAL; - filename = ar->hw.fw; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.fw); get_fw: ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len); @@ -794,16 +799,17 @@ static int ath6kl_fetch_fw_file(struct ath6kl *ar) static int ath6kl_fetch_patch_file(struct ath6kl *ar) { - const char *filename; + char filename[100]; int ret; if (ar->fw_patch != NULL) return 0; - if (ar->hw.fw_patch == NULL) + if (ar->hw.fw.patch == NULL) return 0; - filename = ar->hw.fw_patch; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.patch); ret = ath6kl_get_fw(ar, filename, &ar->fw_patch, &ar->fw_patch_len); @@ -840,15 +846,16 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) size_t magic_len, len, ie_len; const struct firmware *fw; struct ath6kl_fw_ie *hdr; - const char *filename; + char filename[100]; const u8 *data; int ret, ie_id, i, index, bit; __le32 *val; - if (ar->hw.fw_api2 == NULL) + if (ar->hw.fw.api2 == NULL) return -EOPNOTSUPP; - filename = ar->hw.fw_api2; + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.api2); ret = request_firmware(&fw, filename, ar->dev); if (ret) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 15c3f56caf4f..278a9f30795a 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -1362,19 +1362,19 @@ MODULE_AUTHOR("Atheros Communications, Inc."); MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_FIRMWARE(AR6003_HW_2_0_OTP_FILE); -MODULE_FIRMWARE(AR6003_HW_2_0_FIRMWARE_FILE); -MODULE_FIRMWARE(AR6003_HW_2_0_PATCH_FILE); +MODULE_FIRMWARE(AR6003_HW_2_0_FW_DIR "/" AR6003_HW_2_0_OTP_FILE); +MODULE_FIRMWARE(AR6003_HW_2_0_FW_DIR "/" AR6003_HW_2_0_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6003_HW_2_0_FW_DIR "/" AR6003_HW_2_0_PATCH_FILE); MODULE_FIRMWARE(AR6003_HW_2_0_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE); -MODULE_FIRMWARE(AR6003_HW_2_1_1_OTP_FILE); -MODULE_FIRMWARE(AR6003_HW_2_1_1_FIRMWARE_FILE); -MODULE_FIRMWARE(AR6003_HW_2_1_1_PATCH_FILE); +MODULE_FIRMWARE(AR6003_HW_2_1_1_FW_DIR "/" AR6003_HW_2_1_1_OTP_FILE); +MODULE_FIRMWARE(AR6003_HW_2_1_1_FW_DIR "/" AR6003_HW_2_1_1_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6003_HW_2_1_1_FW_DIR "/" AR6003_HW_2_1_1_PATCH_FILE); MODULE_FIRMWARE(AR6003_HW_2_1_1_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE); -MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_0_FW_DIR "/" AR6004_HW_1_0_FIRMWARE_FILE); MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); -MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE); MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index e3cf397fcafe..bb341796dc81 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -423,9 +423,10 @@ module_exit(ath6kl_usb_exit); MODULE_AUTHOR("Atheros Communications, Inc."); MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices"); MODULE_LICENSE("Dual BSD/GPL"); -MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); + +MODULE_FIRMWARE(AR6004_HW_1_0_FW_DIR "/" AR6004_HW_1_0_FIRMWARE_FILE); MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); -MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE); MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); -- GitLab From 65a8b4cc511b68712799e91137324f2abece7d3e Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Fri, 16 Dec 2011 20:53:41 +0200 Subject: [PATCH 00031/10698] ath6kl: add support for FW API 3 As firmware starting from 3.2.0.12 has some API changes and doesn't work with older versions of ath6kl we need to bump up the API version. This way we don't break anything. Also store which version of API is used and print that during boot: ath6kl: ar6003 hw 2.1.1 sdio fw 3.2.0.13 api 3 Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 3 ++- drivers/net/wireless/ath/ath6kl/init.c | 32 ++++++++++++++------------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 267957712564..c095fafa278f 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -98,6 +98,7 @@ struct ath6kl_fw_ie { }; #define ATH6KL_FW_API2_FILE "fw-2.bin" +#define ATH6KL_FW_API3_FILE "fw-3.bin" /* AR6003 1.0 definitions */ #define AR6003_HW_1_0_VERSION 0x300002ba @@ -582,7 +583,6 @@ struct ath6kl { const char *fw; const char *tcmd; const char *patch; - const char *api2; } fw; const char *fw_board; @@ -608,6 +608,7 @@ struct ath6kl { u8 *fw_patch; size_t fw_patch_len; + unsigned int fw_api; unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN]; struct workqueue_struct *ath6kl_wq; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 7b802e99851c..57e0312c4cb9 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -53,7 +53,6 @@ static const struct ath6kl_hw hw_list[] = { .fw = AR6003_HW_2_0_FIRMWARE_FILE, .tcmd = AR6003_HW_2_0_TCMD_FIRMWARE_FILE, .patch = AR6003_HW_2_0_PATCH_FILE, - .api2 = ATH6KL_FW_API2_FILE, }, .fw_board = AR6003_HW_2_0_BOARD_DATA_FILE, @@ -75,7 +74,6 @@ static const struct ath6kl_hw hw_list[] = { .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, .tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, .patch = AR6003_HW_2_1_1_PATCH_FILE, - .api2 = ATH6KL_FW_API2_FILE, }, .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, @@ -95,7 +93,6 @@ static const struct ath6kl_hw hw_list[] = { .fw = { .dir = AR6004_HW_1_0_FW_DIR, .fw = AR6004_HW_1_0_FIRMWARE_FILE, - .api2 = ATH6KL_FW_API2_FILE, }, .fw_board = AR6004_HW_1_0_BOARD_DATA_FILE, @@ -115,7 +112,6 @@ static const struct ath6kl_hw hw_list[] = { .fw = { .dir = AR6004_HW_1_1_FW_DIR, .fw = AR6004_HW_1_1_FIRMWARE_FILE, - .api2 = ATH6KL_FW_API2_FILE, }, .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, @@ -841,7 +837,7 @@ static int ath6kl_fetch_fw_api1(struct ath6kl *ar) return 0; } -static int ath6kl_fetch_fw_api2(struct ath6kl *ar) +static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) { size_t magic_len, len, ie_len; const struct firmware *fw; @@ -851,11 +847,7 @@ static int ath6kl_fetch_fw_api2(struct ath6kl *ar) int ret, ie_id, i, index, bit; __le32 *val; - if (ar->hw.fw.api2 == NULL) - return -EOPNOTSUPP; - - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw.fw.dir, ar->hw.fw.api2); + snprintf(filename, sizeof(filename), "%s/%s", ar->hw.fw.dir, name); ret = request_firmware(&fw, filename, ar->dev); if (ret) @@ -1025,17 +1017,26 @@ static int ath6kl_fetch_firmwares(struct ath6kl *ar) if (ret) return ret; - ret = ath6kl_fetch_fw_api2(ar); + ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API3_FILE); if (ret == 0) { - ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 2\n"); - return 0; + ar->fw_api = 3; + goto out; + } + + ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API2_FILE); + if (ret == 0) { + ar->fw_api = 2; + goto out; } ret = ath6kl_fetch_fw_api1(ar); if (ret) return ret; - ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api 1\n"); + ar->fw_api = 1; + +out: + ath6kl_dbg(ATH6KL_DBG_BOOT, "using fw api %d\n", ar->fw_api); return 0; } @@ -1488,10 +1489,11 @@ int ath6kl_init_hw_start(struct ath6kl *ar) if (test_and_clear_bit(FIRST_BOOT, &ar->flag)) { - ath6kl_info("%s %s fw %s%s\n", + ath6kl_info("%s %s fw %s api %d%s\n", ar->hw.name, ath6kl_init_get_hif_name(ar->hif_type), ar->wiphy->fw_version, + ar->fw_api, test_bit(TESTMODE, &ar->flag) ? " testmode" : ""); } -- GitLab From e68f67509d92114c55938898643600c23f88b4c1 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Thu, 22 Dec 2011 12:15:27 +0530 Subject: [PATCH 00032/10698] ath6kl: Fix panic when setting a channel cfg80211 could pass a NULL net_device to the driver via the set_channel() callback, when it receives a request to set the device's channel. Not handling this case properly results in this panic: BUG: unable to handle kernel NULL pointer dereference at 0000000000000cb0 IP: [] ath6kl_cfg80211_ready+0x9/0x70 [ath6kl_sdio] Call Trace: [] ath6kl_set_channel+0x27/0x90 [ath6kl_sdio] [] cfg80211_set_freq+0xff/0x1d0 [cfg80211] [] ? nl80211_set_wiphy+0x85/0x660 [cfg80211] [] __nl80211_set_channel.isra.39+0x118/0x140 [cfg80211] [] nl80211_set_wiphy+0x303/0x660 [cfg80211] [] ? rtnl_lock+0x17/0x20 [] ? nl80211_pre_doit+0xb5/0x150 [cfg80211] [] genl_rcv_msg+0x1d5/0x250 [] ? genl_rcv+0x40/0x40 [] netlink_rcv_skb+0xa9/0xd0 [] genl_rcv+0x25/0x40 [] ? might_fault+0x40/0x90 [] netlink_unicast+0x2d9/0x320 [] netlink_sendmsg+0x2c6/0x320 [] ? sock_update_classid+0xb0/0x110 [] sock_sendmsg+0x10e/0x130 [] ? mem_cgroup_update_page_stat+0x193/0x250 [] ? might_fault+0x40/0x90 [] ? might_fault+0x40/0x90 [] ? might_fault+0x89/0x90 [] ? might_fault+0x40/0x90 [] ? verify_iovec+0x56/0xd0 [] __sys_sendmsg+0x396/0x3b0 [] ? up_read+0x23/0x40 [] ? do_page_fault+0x208/0x4e0 [] ? vfsmount_lock_local_unlock+0x21/0x60 [] ? mntput_no_expire+0x30/0xe0 [] ? mntput+0x1f/0x30 [] sys_sendmsg+0x49/0x90 [] system_call_fastpath+0x16/0x1b Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 45b0d974e4f7..d6806be5895b 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2044,7 +2044,18 @@ static int ath6kl_set_channel(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) { - struct ath6kl_vif *vif = netdev_priv(dev); + struct ath6kl_vif *vif; + + /* + * 'dev' could be NULL if a channel change is required for the hardware + * device itself, instead of a particular VIF. + * + * FIXME: To be handled properly when monitor mode is supported. + */ + if (!dev) + return -EBUSY; + + vif = netdev_priv(dev); if (!ath6kl_cfg80211_ready(vif)) return -EIO; -- GitLab From 33e5308d8a0fb857a57c38def36ccf7b14ebf1c1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 27 Dec 2011 11:02:56 +0200 Subject: [PATCH 00033/10698] ath6kl: Add del_station cfg80211_ops hostapd/wpa_supplicant AP mode uses this operation to flush the station entries. Implement this in ath6kl to avoid unnecessary warnings from NL80211_CMD_DEL_STATION failing. Signed-off-by: Jouni Malinen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index d6806be5895b..f74762ed619d 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2300,6 +2300,19 @@ static int ath6kl_del_beacon(struct wiphy *wiphy, struct net_device *dev) return 0; } +static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + +static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, + u8 *mac) +{ + struct ath6kl *ar = ath6kl_priv(dev); + struct ath6kl_vif *vif = netdev_priv(dev); + const u8 *addr = mac ? mac : bcast_addr; + + return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH, + addr, WLAN_REASON_PREV_AUTH_NOT_VALID); +} + static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac, struct station_parameters *params) { @@ -2603,6 +2616,7 @@ static struct cfg80211_ops ath6kl_cfg80211_ops = { .add_beacon = ath6kl_add_beacon, .set_beacon = ath6kl_set_beacon, .del_beacon = ath6kl_del_beacon, + .del_station = ath6kl_del_station, .change_station = ath6kl_change_station, .remain_on_channel = ath6kl_remain_on_channel, .cancel_remain_on_channel = ath6kl_cancel_remain_on_channel, -- GitLab From ba1f6fe393c329230d2589ea508cbf90ff3cc9ce Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 27 Dec 2011 11:03:53 +0200 Subject: [PATCH 00034/10698] ath6kl: Advertise TX/RX support for frames in AP mode This is needed to fix current hostapd/wpa_supplicant AP operations for frame registration. P2P GO mode already advertised these, but AP mode was forgotten and could not be used after the hostapd/wpa_supplicant frame registration changes. Signed-off-by: Jouni Malinen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index f74762ed619d..c756425abf73 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2572,6 +2572,12 @@ ath6kl_mgmt_stypes[NUM_NL80211_IFTYPES] = { .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) }, + [NL80211_IFTYPE_AP] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, [NL80211_IFTYPE_P2P_CLIENT] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), -- GitLab From bc48ad31c5814feb4ff8faca9a8d422279593cb1 Mon Sep 17 00:00:00 2001 From: Rishi Panjwani Date: Tue, 27 Dec 2011 14:28:00 -0800 Subject: [PATCH 00035/10698] ath6kl: Support for TCP checksum offload to firmware The change enables offloading TCP checksum calculation to firmware. There are still some issues with the checksum offload so better to disable it by default until the issues are resolved. To enable TCP checksum offload for tx and rx paths, use the ethtool as follows: ethtool -K tx on ethtool -K rx on To disable TCP checksum offload, for tx and rx paths, use the ethtool as follows: ethtool -K tx off ethtool -K rx off kvalo: indentation changes Signed-off-by: Rishi Panjwani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 2 ++ drivers/net/wireless/ath/ath6kl/main.c | 33 ++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/txrx.c | 38 +++++++++++++++++++++++--- drivers/net/wireless/ath/ath6kl/wmi.h | 3 ++ 4 files changed, 72 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 57e0312c4cb9..e74279372ef8 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1686,6 +1686,8 @@ int ath6kl_core_init(struct ath6kl *ar) set_bit(FIRST_BOOT, &ar->flag); + ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; + ret = ath6kl_init_hw_start(ar); if (ret) { ath6kl_err("Failed to start hardware: %d\n", ret); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index eea3c747653e..f3d0184a5cea 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1020,11 +1020,44 @@ static struct net_device_stats *ath6kl_get_stats(struct net_device *dev) return &vif->net_stats; } +static int ath6kl_set_features(struct net_device *dev, u32 features) +{ + struct ath6kl_vif *vif = netdev_priv(dev); + struct ath6kl *ar = vif->ar; + int err = 0; + + if ((features & NETIF_F_RXCSUM) && + (ar->rx_meta_ver != WMI_META_VERSION_2)) { + ar->rx_meta_ver = WMI_META_VERSION_2; + err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, + vif->fw_vif_idx, + ar->rx_meta_ver, 0, 0); + if (err) { + dev->features = features & ~NETIF_F_RXCSUM; + return err; + } + } else if (!(features & NETIF_F_RXCSUM) && + (ar->rx_meta_ver == WMI_META_VERSION_2)) { + ar->rx_meta_ver = 0; + err = ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi, + vif->fw_vif_idx, + ar->rx_meta_ver, 0, 0); + if (err) { + dev->features = features | NETIF_F_RXCSUM; + return err; + } + + } + + return err; +} + static struct net_device_ops ath6kl_netdev_ops = { .ndo_open = ath6kl_open, .ndo_stop = ath6kl_close, .ndo_start_xmit = ath6kl_data_tx, .ndo_get_stats = ath6kl_get_stats, + .ndo_set_features = ath6kl_set_features, }; void init_netdev(struct net_device *dev) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 506a3031a885..78bd57306f74 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -244,6 +244,10 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) u8 ac = 99 ; /* initialize to unmapped ac */ bool chk_adhoc_ps_mapping = false, more_data = false; int ret; + struct wmi_tx_meta_v2 meta_v2; + void *meta; + u8 csum_start = 0, csum_dest = 0, csum = skb->ip_summed; + u8 meta_ver = 0; ath6kl_dbg(ATH6KL_DBG_WLAN_TX, "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__, @@ -265,6 +269,14 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) } if (test_bit(WMI_ENABLED, &ar->flag)) { + if ((dev->features & NETIF_F_IP_CSUM) && + (csum == CHECKSUM_PARTIAL)) { + csum_start = skb->csum_start - + (skb_network_header(skb) - skb->head) + + sizeof(struct ath6kl_llc_snap_hdr); + csum_dest = skb->csum_offset + csum_start; + } + if (skb_headroom(skb) < dev->needed_headroom) { struct sk_buff *tmp_skb = skb; @@ -281,10 +293,28 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) goto fail_tx; } - if (ath6kl_wmi_data_hdr_add(ar->wmi, skb, DATA_MSGTYPE, - more_data, 0, 0, NULL, - vif->fw_vif_idx)) { - ath6kl_err("wmi_data_hdr_add failed\n"); + if ((dev->features & NETIF_F_IP_CSUM) && + (csum == CHECKSUM_PARTIAL)) { + meta_v2.csum_start = csum_start; + meta_v2.csum_dest = csum_dest; + + /* instruct target to calculate checksum */ + meta_v2.csum_flags = WMI_META_V2_FLAG_CSUM_OFFLOAD; + meta_ver = WMI_META_VERSION_2; + meta = &meta_v2; + } else { + meta_ver = 0; + meta = NULL; + } + + ret = ath6kl_wmi_data_hdr_add(ar->wmi, skb, + DATA_MSGTYPE, more_data, 0, + meta_ver, + meta, vif->fw_vif_idx); + + if (ret) { + ath6kl_warn("failed to add wmi data header:%d\n" + , ret); goto fail_tx; } diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 96e3cc10cab2..9f8425b97db7 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -257,6 +257,9 @@ static inline u8 wmi_data_hdr_get_if_idx(struct wmi_data_hdr *dhdr) #define WMI_META_VERSION_1 0x01 #define WMI_META_VERSION_2 0x02 +/* Flag to signal to FW to calculate TCP checksum */ +#define WMI_META_V2_FLAG_CSUM_OFFLOAD 0x01 + struct wmi_tx_meta_v1 { /* packet ID to identify the tx request */ u8 pkt_id; -- GitLab From 351de2835d6429548feb8cca9a17497ec3474f41 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 29 Dec 2011 16:05:37 +0530 Subject: [PATCH 00036/10698] ath6kl: Remove few unnecessary spin_locks around set_bit() Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/txrx.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 78bd57306f74..fcea82479cde 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -479,9 +479,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, * WMI queue with too many commands the only exception to * this is during testing using endpointping. */ - spin_lock_bh(&ar->lock); set_bit(WMI_CTRL_EP_FULL, &ar->flag); - spin_unlock_bh(&ar->lock); ath6kl_err("wmi ctrl ep is full\n"); return action; } @@ -509,9 +507,7 @@ enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target, action != HTC_SEND_FULL_DROP) { spin_unlock_bh(&ar->list_lock); - spin_lock_bh(&vif->if_lock); set_bit(NETQ_STOPPED, &vif->flags); - spin_unlock_bh(&vif->if_lock); netif_stop_queue(vif->ndev); return action; -- GitLab From a10e2f2f6db8f86eaca1cf3d00269463da4d6434 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Thu, 29 Dec 2011 16:05:38 +0530 Subject: [PATCH 00037/10698] ath6kl: Add a module parameter to enable uart debug To enable firmware debug messages through uart interface, modprobe ath6kl_sdio uart_debug=1. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/init.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index e74279372ef8..a481b6a1715d 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -28,10 +28,12 @@ unsigned int debug_mask; static unsigned int testmode; static bool suspend_cutpower; +static unsigned int uart_debug; module_param(debug_mask, uint, 0644); module_param(testmode, uint, 0644); module_param(suspend_cutpower, bool, 0444); +module_param(uart_debug, uint, 0644); static const struct ath6kl_hw hw_list[] = { { @@ -464,6 +466,13 @@ int ath6kl_configure_target(struct ath6kl *ar) u8 fw_iftype, fw_mode = 0, fw_submode = 0; int i, status; + param = uart_debug; + if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_serial_enable)), (u8 *)¶m, 4)) { + ath6kl_err("bmi_write_memory for uart debug failed\n"); + return -EIO; + } + /* * Note: Even though the firmware interface type is * chosen as BSS_STA for all three interfaces, can -- GitLab From 792ecb33080f4e315695e0fe21cf3a3c2a514dd0 Mon Sep 17 00:00:00 2001 From: Vivek Natarajan Date: Thu, 29 Dec 2011 16:18:39 +0530 Subject: [PATCH 00038/10698] ath6kl: Remove redundant key_index check. Less-than-zero comparison of an unsigned value is never true. kvalo: remove WMI_MIN_KEY_INDEX altogether, it's useless Signed-off-by: Vivek Natarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 11 +++++------ drivers/net/wireless/ath/ath6kl/main.c | 2 +- drivers/net/wireless/ath/ath6kl/wmi.h | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index c756425abf73..2a166cc7cc3c 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -524,8 +524,7 @@ static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, (vif->prwise_crypto == WEP_CRYPT)) { struct ath6kl_key *key = NULL; - if (sme->key_idx < WMI_MIN_KEY_INDEX || - sme->key_idx > WMI_MAX_KEY_INDEX) { + if (sme->key_idx > WMI_MAX_KEY_INDEX) { ath6kl_err("key index %d out of bounds\n", sme->key_idx); up(&ar->sem); @@ -997,7 +996,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, params->key); } - if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + if (key_index > WMI_MAX_KEY_INDEX) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: key index %d out of bounds\n", __func__, key_index); @@ -1115,7 +1114,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, if (!ath6kl_cfg80211_ready(vif)) return -EIO; - if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + if (key_index > WMI_MAX_KEY_INDEX) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: key index %d out of bounds\n", __func__, key_index); @@ -1148,7 +1147,7 @@ static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, if (!ath6kl_cfg80211_ready(vif)) return -EIO; - if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + if (key_index > WMI_MAX_KEY_INDEX) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: key index %d out of bounds\n", __func__, key_index); @@ -1184,7 +1183,7 @@ static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy, if (!ath6kl_cfg80211_ready(vif)) return -EIO; - if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) { + if (key_index > WMI_MAX_KEY_INDEX) { ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: key index %d out of bounds\n", __func__, key_index); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index f3d0184a5cea..f74986d62098 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -363,7 +363,7 @@ static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif) u8 index; u8 keyusage; - for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) { + for (index = 0; index <= WMI_MAX_KEY_INDEX; index++) { if (vif->wep_key_list[index].key_len) { keyusage = GROUP_USAGE; if (index == vif->def_txkey_index) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 9f8425b97db7..2b435994b013 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -649,7 +649,6 @@ enum auth_mode { WPA2_AUTH_CCKM = 0x40, }; -#define WMI_MIN_KEY_INDEX 0 #define WMI_MAX_KEY_INDEX 3 #define WMI_MAX_KEY_LEN 32 -- GitLab From 4f34dacea117029dbad1f0f50d68207b97546d1e Mon Sep 17 00:00:00 2001 From: Thomas Pedersen Date: Fri, 30 Dec 2011 01:57:00 -0800 Subject: [PATCH 00039/10698] ath6kl: send TCMD response through testmode events ath6kl no longer knows what it is transmitting through cfg80211_testmode, and simply passes opaque buffers between userspace and the firmware. Leave the CONT_RX enum for backwards compatibility. kvalo: change ATH6KL_TM_CMD_RX_REPORT to return -EOPNOTSUPP Signed-off-by: Thomas Pedersen Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/testmode.c | 102 ++++----------------- drivers/net/wireless/ath/ath6kl/testmode.h | 6 +- drivers/net/wireless/ath/ath6kl/wmi.c | 6 +- 3 files changed, 23 insertions(+), 91 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/testmode.c b/drivers/net/wireless/ath/ath6kl/testmode.c index 381eb66a605f..f0cd61d6188a 100644 --- a/drivers/net/wireless/ath/ath6kl/testmode.c +++ b/drivers/net/wireless/ath/ath6kl/testmode.c @@ -15,6 +15,7 @@ */ #include "testmode.h" +#include "debug.h" #include @@ -30,7 +31,7 @@ enum ath6kl_tm_attr { enum ath6kl_tm_cmd { ATH6KL_TM_CMD_TCMD = 0, - ATH6KL_TM_CMD_RX_REPORT = 1, + ATH6KL_TM_CMD_RX_REPORT = 1, /* not used anymore */ }; #define ATH6KL_TM_DATA_MAX_LEN 5000 @@ -41,84 +42,33 @@ static const struct nla_policy ath6kl_tm_policy[ATH6KL_TM_ATTR_MAX + 1] = { .len = ATH6KL_TM_DATA_MAX_LEN }, }; -void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len) +void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, size_t buf_len) { - if (down_interruptible(&ar->sem)) - return; - - kfree(ar->tm.rx_report); - - ar->tm.rx_report = kmemdup(buf, buf_len, GFP_KERNEL); - ar->tm.rx_report_len = buf_len; - - up(&ar->sem); - - wake_up(&ar->event_wq); -} - -static int ath6kl_tm_rx_report(struct ath6kl *ar, void *buf, size_t buf_len, - struct sk_buff *skb) -{ - int ret = 0; - long left; - - if (down_interruptible(&ar->sem)) - return -ERESTARTSYS; - - if (!test_bit(WMI_READY, &ar->flag)) { - ret = -EIO; - goto out; - } - - if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) { - ret = -EBUSY; - goto out; - } - - if (ath6kl_wmi_test_cmd(ar->wmi, buf, buf_len) < 0) { - up(&ar->sem); - return -EIO; - } - - left = wait_event_interruptible_timeout(ar->event_wq, - ar->tm.rx_report != NULL, - WMI_TIMEOUT); + struct sk_buff *skb; - if (left == 0) { - ret = -ETIMEDOUT; - goto out; - } else if (left < 0) { - ret = left; - goto out; - } + if (!buf || buf_len == 0) + return; - if (ar->tm.rx_report == NULL || ar->tm.rx_report_len == 0) { - ret = -EINVAL; - goto out; + skb = cfg80211_testmode_alloc_event_skb(ar->wiphy, buf_len, GFP_KERNEL); + if (!skb) { + ath6kl_warn("failed to allocate testmode rx skb!\n"); + return; } - - NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, ar->tm.rx_report_len, - ar->tm.rx_report); - - kfree(ar->tm.rx_report); - ar->tm.rx_report = NULL; - -out: - up(&ar->sem); - - return ret; + NLA_PUT_U32(skb, ATH6KL_TM_ATTR_CMD, ATH6KL_TM_CMD_TCMD); + NLA_PUT(skb, ATH6KL_TM_ATTR_DATA, buf_len, buf); + cfg80211_testmode_event(skb, GFP_KERNEL); + return; nla_put_failure: - ret = -ENOBUFS; - goto out; + kfree_skb(skb); + ath6kl_warn("nla_put failed on testmode rx skb!\n"); } int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) { struct ath6kl *ar = wiphy_priv(wiphy); struct nlattr *tb[ATH6KL_TM_ATTR_MAX + 1]; - int err, buf_len, reply_len; - struct sk_buff *skb; + int err, buf_len; void *buf; err = nla_parse(tb, ATH6KL_TM_ATTR_MAX, data, len, @@ -143,24 +93,6 @@ int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len) break; case ATH6KL_TM_CMD_RX_REPORT: - if (!tb[ATH6KL_TM_ATTR_DATA]) - return -EINVAL; - - buf = nla_data(tb[ATH6KL_TM_ATTR_DATA]); - buf_len = nla_len(tb[ATH6KL_TM_ATTR_DATA]); - - reply_len = nla_total_size(ATH6KL_TM_DATA_MAX_LEN); - skb = cfg80211_testmode_alloc_reply_skb(wiphy, reply_len); - if (!skb) - return -ENOMEM; - - err = ath6kl_tm_rx_report(ar, buf, buf_len, skb); - if (err < 0) { - kfree_skb(skb); - return err; - } - - return cfg80211_testmode_reply(skb); default: return -EOPNOTSUPP; } diff --git a/drivers/net/wireless/ath/ath6kl/testmode.h b/drivers/net/wireless/ath/ath6kl/testmode.h index 43dffcc11fb1..7fd47a62d078 100644 --- a/drivers/net/wireless/ath/ath6kl/testmode.h +++ b/drivers/net/wireless/ath/ath6kl/testmode.h @@ -18,13 +18,13 @@ #ifdef CONFIG_NL80211_TESTMODE -void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, size_t buf_len); +void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, size_t buf_len); int ath6kl_tm_cmd(struct wiphy *wiphy, void *data, int len); #else -static inline void ath6kl_tm_rx_report_event(struct ath6kl *ar, void *buf, - size_t buf_len) +static inline void ath6kl_tm_rx_event(struct ath6kl *ar, void *buf, + size_t buf_len) { } diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 1e31c38abb4f..c6ca660d270a 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -1145,9 +1145,9 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len) return 0; } -static int ath6kl_wmi_tcmd_test_report_rx(struct wmi *wmi, u8 *datap, int len) +static int ath6kl_wmi_test_rx(struct wmi *wmi, u8 *datap, int len) { - ath6kl_tm_rx_report_event(wmi->parent_dev, datap, len); + ath6kl_tm_rx_event(wmi->parent_dev, datap, len); return 0; } @@ -3402,7 +3402,7 @@ int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb) break; case WMI_TEST_EVENTID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TEST_EVENTID\n"); - ret = ath6kl_wmi_tcmd_test_report_rx(wmi, datap, len); + ret = ath6kl_wmi_test_rx(wmi, datap, len); break; case WMI_GET_FIXRATES_CMDID: ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n"); -- GitLab From cd42f4a3b2b1c4cbd997363dc57821953d73fd87 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Thu, 15 Dec 2011 10:48:12 -0800 Subject: [PATCH 00040/10698] HWPOISON: Clean up memory_failure() vs. __memory_failure() There is only one caller of memory_failure(), all other users call __memory_failure() and pass in the flags argument explicitly. The lone user of memory_failure() will soon need to pass flags too. Add flags argument to the callsite in mce.c. Delete the old memory_failure() function, and then rename __memory_failure() without the leading "__". Provide clearer message when action optional memory errors are ignored. Acked-by: Borislav Petkov Signed-off-by: Tony Luck --- arch/x86/kernel/cpu/mcheck/mce.c | 12 ++++++--- drivers/base/memory.c | 2 +- include/linux/mm.h | 3 +-- mm/hwpoison-inject.c | 4 +-- mm/madvise.c | 2 +- mm/memory-failure.c | 46 +++++++++++++++----------------- 6 files changed, 34 insertions(+), 35 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 2af127d4c3d1..1a08ce5f345f 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1046,11 +1046,15 @@ void do_machine_check(struct pt_regs *regs, long error_code) } EXPORT_SYMBOL_GPL(do_machine_check); -/* dummy to break dependency. actual code is in mm/memory-failure.c */ -void __attribute__((weak)) memory_failure(unsigned long pfn, int vector) +#ifndef CONFIG_MEMORY_FAILURE +int memory_failure(unsigned long pfn, int vector, int flags) { - printk(KERN_ERR "Action optional memory failure at %lx ignored\n", pfn); + printk(KERN_ERR "Uncorrected memory error in page 0x%lx ignored\n" + "Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n", pfn); + + return 0; } +#endif /* * Called after mce notification in process context. This code @@ -1068,7 +1072,7 @@ void mce_notify_process(void) unsigned long pfn; mce_notify_irq(); while (mce_ring_get(&pfn)) - memory_failure(pfn, MCE_VECTOR); + memory_failure(pfn, MCE_VECTOR, 0); } static void mce_process_work(struct work_struct *dummy) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 8272d92d22c0..9a924440053f 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -474,7 +474,7 @@ store_hard_offline_page(struct class *class, if (strict_strtoull(buf, 0, &pfn) < 0) return -EINVAL; pfn >>= PAGE_SHIFT; - ret = __memory_failure(pfn, 0, 0); + ret = memory_failure(pfn, 0, 0); return ret ? ret : count; } diff --git a/include/linux/mm.h b/include/linux/mm.h index 4baadd18f4ad..bcc523474724 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1607,8 +1607,7 @@ void vmemmap_populate_print_last(void); enum mf_flags { MF_COUNT_INCREASED = 1 << 0, }; -extern void memory_failure(unsigned long pfn, int trapno); -extern int __memory_failure(unsigned long pfn, int trapno, int flags); +extern int memory_failure(unsigned long pfn, int trapno, int flags); extern void memory_failure_queue(unsigned long pfn, int trapno, int flags); extern int unpoison_memory(unsigned long pfn); extern int sysctl_memory_failure_early_kill; diff --git a/mm/hwpoison-inject.c b/mm/hwpoison-inject.c index c7fc7fd00e32..cc448bb983ba 100644 --- a/mm/hwpoison-inject.c +++ b/mm/hwpoison-inject.c @@ -45,7 +45,7 @@ static int hwpoison_inject(void *data, u64 val) * do a racy check with elevated page count, to make sure PG_hwpoison * will only be set for the targeted owner (or on a free page). * We temporarily take page lock for try_get_mem_cgroup_from_page(). - * __memory_failure() will redo the check reliably inside page lock. + * memory_failure() will redo the check reliably inside page lock. */ lock_page(hpage); err = hwpoison_filter(hpage); @@ -55,7 +55,7 @@ static int hwpoison_inject(void *data, u64 val) inject: printk(KERN_INFO "Injecting memory failure at pfn %lx\n", pfn); - return __memory_failure(pfn, 18, MF_COUNT_INCREASED); + return memory_failure(pfn, 18, MF_COUNT_INCREASED); } static int hwpoison_unpoison(void *data, u64 val) diff --git a/mm/madvise.c b/mm/madvise.c index 74bf193eff04..f5ab745672b7 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -251,7 +251,7 @@ static int madvise_hwpoison(int bhv, unsigned long start, unsigned long end) printk(KERN_INFO "Injecting memory failure for page %lx at %lx\n", page_to_pfn(p), start); /* Ignore return value for now */ - __memory_failure(page_to_pfn(p), 0, MF_COUNT_INCREASED); + memory_failure(page_to_pfn(p), 0, MF_COUNT_INCREASED); } return ret; } diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 06d3479513aa..ab259bb0adc5 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -984,7 +984,25 @@ static void clear_page_hwpoison_huge_page(struct page *hpage) ClearPageHWPoison(hpage + i); } -int __memory_failure(unsigned long pfn, int trapno, int flags) +/** + * memory_failure - Handle memory failure of a page. + * @pfn: Page Number of the corrupted page + * @trapno: Trap number reported in the signal to user space. + * @flags: fine tune action taken + * + * This function is called by the low level machine check code + * of an architecture when it detects hardware memory corruption + * of a page. It tries its best to recover, which includes + * dropping pages, killing processes etc. + * + * The function is primarily of use for corruptions that + * happen outside the current execution context (e.g. when + * detected by a background scrubber) + * + * Must run in process context (e.g. a work queue) with interrupts + * enabled and no spinlocks hold. + */ +int memory_failure(unsigned long pfn, int trapno, int flags) { struct page_state *ps; struct page *p; @@ -1156,29 +1174,7 @@ int __memory_failure(unsigned long pfn, int trapno, int flags) unlock_page(hpage); return res; } -EXPORT_SYMBOL_GPL(__memory_failure); - -/** - * memory_failure - Handle memory failure of a page. - * @pfn: Page Number of the corrupted page - * @trapno: Trap number reported in the signal to user space. - * - * This function is called by the low level machine check code - * of an architecture when it detects hardware memory corruption - * of a page. It tries its best to recover, which includes - * dropping pages, killing processes etc. - * - * The function is primarily of use for corruptions that - * happen outside the current execution context (e.g. when - * detected by a background scrubber) - * - * Must run in process context (e.g. a work queue) with interrupts - * enabled and no spinlocks hold. - */ -void memory_failure(unsigned long pfn, int trapno) -{ - __memory_failure(pfn, trapno, 0); -} +EXPORT_SYMBOL_GPL(memory_failure); #define MEMORY_FAILURE_FIFO_ORDER 4 #define MEMORY_FAILURE_FIFO_SIZE (1 << MEMORY_FAILURE_FIFO_ORDER) @@ -1251,7 +1247,7 @@ static void memory_failure_work_func(struct work_struct *work) spin_unlock_irqrestore(&mf_cpu->lock, proc_flags); if (!gotten) break; - __memory_failure(entry.pfn, entry.trapno, entry.flags); + memory_failure(entry.pfn, entry.trapno, entry.flags); } } -- GitLab From 7329bbeb92740f35d64a8860ae7837ff4db27fe0 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 13 Dec 2011 09:27:58 -0800 Subject: [PATCH 00041/10698] HWPOISON: Add code to handle "action required" errors. Add new flag bit "MF_ACTION_REQUIRED" to be used by machine check code to force a signal with si_code = BUS_MCEERR_AR in the case where the error occurs in processor execution context. Pass the flags argument along call chain: memory_failure() hwpoison_user_mappings() kill_procs() kill_proc() Drop the "_ao" suffix from kill_procs_ao() and kill_proc_ao() since they can now handle "action required" as well as "action optional" errors. Acked-by: Borislav Petkov Signed-off-by: Tony Luck --- include/linux/mm.h | 1 + mm/memory-failure.c | 50 ++++++++++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 21 deletions(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index bcc523474724..bf169ca69812 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1606,6 +1606,7 @@ void vmemmap_populate_print_last(void); enum mf_flags { MF_COUNT_INCREASED = 1 << 0, + MF_ACTION_REQUIRED = 1 << 1, }; extern int memory_failure(unsigned long pfn, int trapno, int flags); extern void memory_failure_queue(unsigned long pfn, int trapno, int flags); diff --git a/mm/memory-failure.c b/mm/memory-failure.c index ab259bb0adc5..95fd307ebb30 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -187,33 +187,40 @@ int hwpoison_filter(struct page *p) EXPORT_SYMBOL_GPL(hwpoison_filter); /* - * Send all the processes who have the page mapped an ``action optional'' - * signal. + * Send all the processes who have the page mapped a signal. + * ``action optional'' if they are not immediately affected by the error + * ``action required'' if error happened in current execution context */ -static int kill_proc_ao(struct task_struct *t, unsigned long addr, int trapno, - unsigned long pfn, struct page *page) +static int kill_proc(struct task_struct *t, unsigned long addr, int trapno, + unsigned long pfn, struct page *page, int flags) { struct siginfo si; int ret; printk(KERN_ERR - "MCE %#lx: Killing %s:%d early due to hardware memory corruption\n", + "MCE %#lx: Killing %s:%d due to hardware memory corruption\n", pfn, t->comm, t->pid); si.si_signo = SIGBUS; si.si_errno = 0; - si.si_code = BUS_MCEERR_AO; si.si_addr = (void *)addr; #ifdef __ARCH_SI_TRAPNO si.si_trapno = trapno; #endif si.si_addr_lsb = compound_trans_order(compound_head(page)) + PAGE_SHIFT; - /* - * Don't use force here, it's convenient if the signal - * can be temporarily blocked. - * This could cause a loop when the user sets SIGBUS - * to SIG_IGN, but hopefully no one will do that? - */ - ret = send_sig_info(SIGBUS, &si, t); /* synchronous? */ + + if ((flags & MF_ACTION_REQUIRED) && t == current) { + si.si_code = BUS_MCEERR_AR; + ret = force_sig_info(SIGBUS, &si, t); + } else { + /* + * Don't use force here, it's convenient if the signal + * can be temporarily blocked. + * This could cause a loop when the user sets SIGBUS + * to SIG_IGN, but hopefully no one will do that? + */ + si.si_code = BUS_MCEERR_AO; + ret = send_sig_info(SIGBUS, &si, t); /* synchronous? */ + } if (ret < 0) printk(KERN_INFO "MCE: Error sending signal to %s:%d: %d\n", t->comm, t->pid, ret); @@ -338,8 +345,9 @@ static void add_to_kill(struct task_struct *tsk, struct page *p, * Also when FAIL is set do a force kill because something went * wrong earlier. */ -static void kill_procs_ao(struct list_head *to_kill, int doit, int trapno, - int fail, struct page *page, unsigned long pfn) +static void kill_procs(struct list_head *to_kill, int doit, int trapno, + int fail, struct page *page, unsigned long pfn, + int flags) { struct to_kill *tk, *next; @@ -363,8 +371,8 @@ static void kill_procs_ao(struct list_head *to_kill, int doit, int trapno, * check for that, but we need to tell the * process anyways. */ - else if (kill_proc_ao(tk->tsk, tk->addr, trapno, - pfn, page) < 0) + else if (kill_proc(tk->tsk, tk->addr, trapno, + pfn, page, flags) < 0) printk(KERN_ERR "MCE %#lx: Cannot send advisory machine check signal to %s:%d\n", pfn, tk->tsk->comm, tk->tsk->pid); @@ -844,7 +852,7 @@ static int page_action(struct page_state *ps, struct page *p, * the pages and send SIGBUS to the processes if the data was dirty. */ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, - int trapno) + int trapno, int flags) { enum ttu_flags ttu = TTU_UNMAP | TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS; struct address_space *mapping; @@ -962,8 +970,8 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, * use a more force-full uncatchable kill to prevent * any accesses to the poisoned memory. */ - kill_procs_ao(&tokill, !!PageDirty(ppage), trapno, - ret != SWAP_SUCCESS, p, pfn); + kill_procs(&tokill, !!PageDirty(ppage), trapno, + ret != SWAP_SUCCESS, p, pfn, flags); return ret; } @@ -1148,7 +1156,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags) * Now take care of user space mappings. * Abort on fail: __delete_from_page_cache() assumes unmapped page. */ - if (hwpoison_user_mappings(p, pfn, trapno) != SWAP_SUCCESS) { + if (hwpoison_user_mappings(p, pfn, trapno, flags) != SWAP_SUCCESS) { printk(KERN_ERR "MCE %#lx: cannot unmap page, give up\n", pfn); res = -EBUSY; goto out; -- GitLab From 85f92694affa7dba7f1978666a69552b5dfc628e Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 13 Dec 2011 09:48:13 -0800 Subject: [PATCH 00042/10698] x86/mce: Create helper function to save addr/misc when needed The MCI_STATUS_MISCV and MCI_STATUS_ADDRV bits in the bank status registers define whether the MISC and ADDR registers respectively contain valid data - provide a helper function to check these bits and read the registers when needed. In addition, processors that support software error recovery (as indicated by the MCG_SER_P bit in the MCG_CAP register) may include some undefined bits in the ADDR register - mask these out. Acked-by: Borislav Petkov Signed-off-by: Tony Luck --- arch/x86/kernel/cpu/mcheck/mce.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 1a08ce5f345f..2f1c200f05e6 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -492,6 +492,27 @@ static void mce_report_event(struct pt_regs *regs) irq_work_queue(&__get_cpu_var(mce_irq_work)); } +/* + * Read ADDR and MISC registers. + */ +static void mce_read_aux(struct mce *m, int i) +{ + if (m->status & MCI_STATUS_MISCV) + m->misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i)); + if (m->status & MCI_STATUS_ADDRV) { + m->addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i)); + + /* + * Mask the reported address by the reported granularity. + */ + if (mce_ser && (m->status & MCI_STATUS_MISCV)) { + u8 shift = MCI_MISC_ADDR_LSB(m->misc); + m->addr >>= shift; + m->addr <<= shift; + } + } +} + DEFINE_PER_CPU(unsigned, mce_poll_count); /* @@ -542,10 +563,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) (m.status & (mce_ser ? MCI_STATUS_S : MCI_STATUS_UC))) continue; - if (m.status & MCI_STATUS_MISCV) - m.misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i)); - if (m.status & MCI_STATUS_ADDRV) - m.addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i)); + mce_read_aux(&m, i); if (!(flags & MCP_TIMESTAMP)) m.tsc = 0; @@ -981,10 +999,7 @@ void do_machine_check(struct pt_regs *regs, long error_code) if (severity == MCE_AR_SEVERITY) kill_it = 1; - if (m.status & MCI_STATUS_MISCV) - m.misc = mce_rdmsrl(MSR_IA32_MCx_MISC(i)); - if (m.status & MCI_STATUS_ADDRV) - m.addr = mce_rdmsrl(MSR_IA32_MCx_ADDR(i)); + mce_read_aux(&m, i); /* * Action optional error. Queue address for later processing. -- GitLab From af104e394e17e328df85c25a9e21448539725b67 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Wed, 14 Dec 2011 15:55:20 -0800 Subject: [PATCH 00043/10698] x86/mce: Add mechanism to safely save information in MCE handler Machine checks on Intel cpus interrupt execution on all cpus, regardless of interrupt masking. We have a need to save some data about the cause of the machine check (physical address) in the machine check handler that can be retrieved later to attempt recovery in a more flexible execution state. Signed-off-by: Tony Luck --- arch/x86/kernel/cpu/mcheck/mce.c | 43 ++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 2f1c200f05e6..e1579c5a71da 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -886,6 +886,49 @@ static void mce_clear_state(unsigned long *toclear) } } +/* + * Need to save faulting physical address associated with a process + * in the machine check handler some place where we can grab it back + * later in mce_notify_process() + */ +#define MCE_INFO_MAX 16 + +struct mce_info { + atomic_t inuse; + struct task_struct *t; + __u64 paddr; +} mce_info[MCE_INFO_MAX]; + +static void mce_save_info(__u64 addr) +{ + struct mce_info *mi; + + for (mi = mce_info; mi < &mce_info[MCE_INFO_MAX]; mi++) { + if (atomic_cmpxchg(&mi->inuse, 0, 1) == 0) { + mi->t = current; + mi->paddr = addr; + return; + } + } + + mce_panic("Too many concurrent recoverable errors", NULL, NULL); +} + +static struct mce_info *mce_find_info(void) +{ + struct mce_info *mi; + + for (mi = mce_info; mi < &mce_info[MCE_INFO_MAX]; mi++) + if (atomic_read(&mi->inuse) && mi->t == current) + return mi; + return NULL; +} + +static void mce_clear_info(struct mce_info *mi) +{ + atomic_set(&mi->inuse, 0); +} + /* * The actual machine check handler. This only handles real * exceptions when something got corrupted coming in through int 18. -- GitLab From a8c321fbf9aeced45519248e5901af8cbc240510 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 3 Jan 2012 11:45:45 -0800 Subject: [PATCH 00044/10698] x86/mce: Handle "action required" errors All non-urgent actions (reporting low severity errors and handling "action-optional" errors) are now handled by a work queue. This means that TIF_MCE_NOTIFY can be used to block execution for a thread experiencing an "action-required" fault until we get all cpus out of the machine check handler (and the thread that hit the fault into mce_notify_process(). We use the new mce_{save,find,clear}_info() API to get information from do_machine_check() to mce_notify_process(), and then use the newly improved memory_failure(..., MF_ACTION_REQUIRED) to handle the error (possibly signalling the process). Update some comments to make the new code flows clearer. Signed-off-by: Tony Luck --- arch/x86/kernel/cpu/mcheck/mce.c | 95 ++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 42 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index e1579c5a71da..56e4e79387c3 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -982,7 +982,9 @@ void do_machine_check(struct pt_regs *regs, long error_code) barrier(); /* - * When no restart IP must always kill or panic. + * When no restart IP might need to kill or panic. + * Assume the worst for now, but if we find the + * severity is MCE_AR_SEVERITY we have other options. */ if (!(m.mcgstatus & MCG_STATUS_RIPV)) kill_it = 1; @@ -1036,12 +1038,6 @@ void do_machine_check(struct pt_regs *regs, long error_code) continue; } - /* - * Kill on action required. - */ - if (severity == MCE_AR_SEVERITY) - kill_it = 1; - mce_read_aux(&m, i); /* @@ -1062,6 +1058,9 @@ void do_machine_check(struct pt_regs *regs, long error_code) } } + /* mce_clear_state will clear *final, save locally for use later */ + m = *final; + if (!no_way_out) mce_clear_state(toclear); @@ -1073,27 +1072,22 @@ void do_machine_check(struct pt_regs *regs, long error_code) no_way_out = worst >= MCE_PANIC_SEVERITY; /* - * If we have decided that we just CAN'T continue, and the user - * has not set tolerant to an insane level, give up and die. - * - * This is mainly used in the case when the system doesn't - * support MCE broadcasting or it has been disabled. + * At insane "tolerant" levels we take no action. Otherwise + * we only die if we have no other choice. For less serious + * issues we try to recover, or limit damage to the current + * process. */ - if (no_way_out && tolerant < 3) - mce_panic("Fatal machine check on current CPU", final, msg); - - /* - * If the error seems to be unrecoverable, something should be - * done. Try to kill as little as possible. If we can kill just - * one task, do that. If the user has set the tolerance very - * high, don't try to do anything at all. - */ - - if (kill_it && tolerant < 3) - force_sig(SIGBUS, current); - - /* notify userspace ASAP */ - set_thread_flag(TIF_MCE_NOTIFY); + if (tolerant < 3) { + if (no_way_out) + mce_panic("Fatal machine check on current CPU", &m, msg); + if (worst == MCE_AR_SEVERITY) { + /* schedule action before return to userland */ + mce_save_info(m.addr); + set_thread_flag(TIF_MCE_NOTIFY); + } else if (kill_it) { + force_sig(SIGBUS, current); + } + } if (worst > 0) mce_report_event(regs); @@ -1107,6 +1101,8 @@ EXPORT_SYMBOL_GPL(do_machine_check); #ifndef CONFIG_MEMORY_FAILURE int memory_failure(unsigned long pfn, int vector, int flags) { + /* mce_severity() should not hand us an ACTION_REQUIRED error */ + BUG_ON(flags & MF_ACTION_REQUIRED); printk(KERN_ERR "Uncorrected memory error in page 0x%lx ignored\n" "Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n", pfn); @@ -1115,27 +1111,44 @@ int memory_failure(unsigned long pfn, int vector, int flags) #endif /* - * Called after mce notification in process context. This code - * is allowed to sleep. Call the high level VM handler to process - * any corrupted pages. - * Assume that the work queue code only calls this one at a time - * per CPU. - * Note we don't disable preemption, so this code might run on the wrong - * CPU. In this case the event is picked up by the scheduled work queue. - * This is merely a fast path to expedite processing in some common - * cases. + * Called in process context that interrupted by MCE and marked with + * TIF_MCE_NOTIFY, just before returning to erroneous userland. + * This code is allowed to sleep. + * Attempt possible recovery such as calling the high level VM handler to + * process any corrupted pages, and kill/signal current process if required. + * Action required errors are handled here. */ void mce_notify_process(void) { unsigned long pfn; - mce_notify_irq(); - while (mce_ring_get(&pfn)) - memory_failure(pfn, MCE_VECTOR, 0); + struct mce_info *mi = mce_find_info(); + + if (!mi) + mce_panic("Lost physical address for unconsumed uncorrectable error", NULL, NULL); + pfn = mi->paddr >> PAGE_SHIFT; + + clear_thread_flag(TIF_MCE_NOTIFY); + + pr_err("Uncorrected hardware memory error in user-access at %llx", + mi->paddr); + if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0) { + pr_err("Memory error not recovered"); + force_sig(SIGBUS, current); + } + mce_clear_info(mi); } +/* + * Action optional processing happens here (picking up + * from the list of faulting pages that do_machine_check() + * placed into the "ring"). + */ static void mce_process_work(struct work_struct *dummy) { - mce_notify_process(); + unsigned long pfn; + + while (mce_ring_get(&pfn)) + memory_failure(pfn, MCE_VECTOR, 0); } #ifdef CONFIG_X86_MCE_INTEL @@ -1225,8 +1238,6 @@ int mce_notify_irq(void) /* Not more than two messages every minute */ static DEFINE_RATELIMIT_STATE(ratelimit, 60*HZ, 2); - clear_thread_flag(TIF_MCE_NOTIFY); - if (test_and_clear_bit(0, &mce_need_notify)) { /* wake processes polling /dev/mcelog */ wake_up_interruptible(&mce_chrdev_wait); -- GitLab From 5f7b88d51e89771f64c15903b96b5933dd0bc6d8 Mon Sep 17 00:00:00 2001 From: Tony Luck Date: Tue, 3 Jan 2012 11:48:04 -0800 Subject: [PATCH 00045/10698] x86/mce: Recognise machine check bank signature for data path error Action required data path signature is defined in table 15-19 of SDM: +-----------------------------------------------------------------------------+ | SRAR Error | Valid | OVER | UC | EN | MISCV | ADDRV | PCC | S | AR | MCACOD | | Data Load | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0x134 | +-----------------------------------------------------------------------------+ Recognise this, and pass MCE_AR_SEVERITY code back to do_machine_check() if we have the action handler configured (CONFIG_MEMORY_FAILURE=y) Acked-by: Borislav Petkov Signed-off-by: Tony Luck --- arch/x86/kernel/cpu/mcheck/mce-severity.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c index 7395d5f4272d..f6c92f99efa0 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c @@ -54,6 +54,7 @@ static struct severity { #define MASK(x, y) .mask = x, .result = y #define MCI_UC_S (MCI_STATUS_UC|MCI_STATUS_S) #define MCI_UC_SAR (MCI_STATUS_UC|MCI_STATUS_S|MCI_STATUS_AR) +#define MCI_ADDR (MCI_STATUS_ADDRV|MCI_STATUS_MISCV) #define MCACOD 0xffff MCESEV( @@ -102,11 +103,24 @@ static struct severity { SER, BITCLR(MCI_STATUS_S) ), - /* AR add known MCACODs here */ MCESEV( PANIC, "Action required with lost events", SER, BITSET(MCI_STATUS_OVER|MCI_UC_SAR) ), + + /* known AR MCACODs: */ +#ifdef CONFIG_MEMORY_FAILURE + MCESEV( + KEEP, "HT thread notices Action required: data load error", + SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|0x0134), + MCGMASK(MCG_STATUS_EIPV, 0) + ), + MCESEV( + AR, "Action required: data load error", + SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR|MCI_ADDR|MCACOD, MCI_UC_SAR|MCI_ADDR|0x0134), + USER + ), +#endif MCESEV( PANIC, "Action required: unknown MCACOD", SER, MASK(MCI_STATUS_OVER|MCI_UC_SAR, MCI_UC_SAR) -- GitLab From a056ab8c7a00a0ffc52e9573bf01257004c2d08c Mon Sep 17 00:00:00 2001 From: Carlos Chinea Date: Fri, 16 Apr 2010 19:01:02 +0300 Subject: [PATCH 00046/10698] HSI: hsi: Introducing HSI framework Adds HSI framework in to the linux kernel. High Speed Synchronous Serial Interface (HSI) is a serial interface mainly used for connecting application engines (APE) with cellular modem engines (CMT) in cellular handsets. HSI provides multiplexing for up to 16 logical channels, low-latency and full duplex communication. Signed-off-by: Carlos Chinea Acked-by: Linus Walleij --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/hsi/Kconfig | 17 ++ drivers/hsi/Makefile | 5 + drivers/hsi/hsi.c | 494 ++++++++++++++++++++++++++++++++++++ drivers/hsi/hsi_boardinfo.c | 62 +++++ drivers/hsi/hsi_core.h | 35 +++ include/linux/hsi/hsi.h | 410 ++++++++++++++++++++++++++++++ 8 files changed, 1026 insertions(+) create mode 100644 drivers/hsi/Kconfig create mode 100644 drivers/hsi/Makefile create mode 100644 drivers/hsi/hsi.c create mode 100644 drivers/hsi/hsi_boardinfo.c create mode 100644 drivers/hsi/hsi_core.h create mode 100644 include/linux/hsi/hsi.h diff --git a/drivers/Kconfig b/drivers/Kconfig index b5e6f243f749..52895081db0b 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -52,6 +52,8 @@ source "drivers/i2c/Kconfig" source "drivers/spi/Kconfig" +source "drivers/hsi/Kconfig" + source "drivers/pps/Kconfig" source "drivers/ptp/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 1b3142127bf5..91077ac6b156 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_ATA) += ata/ obj-$(CONFIG_TARGET_CORE) += target/ obj-$(CONFIG_MTD) += mtd/ obj-$(CONFIG_SPI) += spi/ +obj-y += hsi/ obj-y += net/ obj-$(CONFIG_ATM) += atm/ obj-$(CONFIG_FUSION) += message/ diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig new file mode 100644 index 000000000000..937062e8bcd0 --- /dev/null +++ b/drivers/hsi/Kconfig @@ -0,0 +1,17 @@ +# +# HSI driver configuration +# +menuconfig HSI + tristate "HSI support" + ---help--- + The "High speed synchronous Serial Interface" is + synchronous serial interface used mainly to connect + application engines and cellular modems. + +if HSI + +config HSI_BOARDINFO + bool + default y + +endif # HSI diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile new file mode 100644 index 000000000000..ed94a3a334a4 --- /dev/null +++ b/drivers/hsi/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for HSI +# +obj-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o +obj-$(CONFIG_HSI) += hsi.o diff --git a/drivers/hsi/hsi.c b/drivers/hsi/hsi.c new file mode 100644 index 000000000000..4e2d79b79334 --- /dev/null +++ b/drivers/hsi/hsi.c @@ -0,0 +1,494 @@ +/* + * HSI core. + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Carlos Chinea + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "hsi_core.h" + +static struct device_type hsi_ctrl = { + .name = "hsi_controller", +}; + +static struct device_type hsi_cl = { + .name = "hsi_client", +}; + +static struct device_type hsi_port = { + .name = "hsi_port", +}; + +static ssize_t modalias_show(struct device *dev, + struct device_attribute *a __maybe_unused, char *buf) +{ + return sprintf(buf, "hsi:%s\n", dev_name(dev)); +} + +static struct device_attribute hsi_bus_dev_attrs[] = { + __ATTR_RO(modalias), + __ATTR_NULL, +}; + +static int hsi_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +{ + if (dev->type == &hsi_cl) + add_uevent_var(env, "MODALIAS=hsi:%s", dev_name(dev)); + + return 0; +} + +static int hsi_bus_match(struct device *dev, struct device_driver *driver) +{ + return strcmp(dev_name(dev), driver->name) == 0; +} + +static struct bus_type hsi_bus_type = { + .name = "hsi", + .dev_attrs = hsi_bus_dev_attrs, + .match = hsi_bus_match, + .uevent = hsi_bus_uevent, +}; + +static void hsi_client_release(struct device *dev) +{ + kfree(to_hsi_client(dev)); +} + +static void hsi_new_client(struct hsi_port *port, struct hsi_board_info *info) +{ + struct hsi_client *cl; + unsigned long flags; + + cl = kzalloc(sizeof(*cl), GFP_KERNEL); + if (!cl) + return; + cl->device.type = &hsi_cl; + cl->tx_cfg = info->tx_cfg; + cl->rx_cfg = info->rx_cfg; + cl->device.bus = &hsi_bus_type; + cl->device.parent = &port->device; + cl->device.release = hsi_client_release; + dev_set_name(&cl->device, info->name); + cl->device.platform_data = info->platform_data; + spin_lock_irqsave(&port->clock, flags); + list_add_tail(&cl->link, &port->clients); + spin_unlock_irqrestore(&port->clock, flags); + if (info->archdata) + cl->device.archdata = *info->archdata; + if (device_register(&cl->device) < 0) { + pr_err("hsi: failed to register client: %s\n", info->name); + kfree(cl); + } +} + +static void hsi_scan_board_info(struct hsi_controller *hsi) +{ + struct hsi_cl_info *cl_info; + struct hsi_port *p; + + list_for_each_entry(cl_info, &hsi_board_list, list) + if (cl_info->info.hsi_id == hsi->id) { + p = hsi_find_port_num(hsi, cl_info->info.port); + if (!p) + continue; + hsi_new_client(p, &cl_info->info); + } +} + +static int hsi_remove_client(struct device *dev, void *data __maybe_unused) +{ + struct hsi_client *cl = to_hsi_client(dev); + struct hsi_port *port = to_hsi_port(dev->parent); + unsigned long flags; + + spin_lock_irqsave(&port->clock, flags); + list_del(&cl->link); + spin_unlock_irqrestore(&port->clock, flags); + device_unregister(dev); + + return 0; +} + +static int hsi_remove_port(struct device *dev, void *data __maybe_unused) +{ + device_for_each_child(dev, NULL, hsi_remove_client); + device_unregister(dev); + + return 0; +} + +static void hsi_controller_release(struct device *dev __maybe_unused) +{ +} + +static void hsi_port_release(struct device *dev __maybe_unused) +{ +} + +/** + * hsi_unregister_controller - Unregister an HSI controller + * @hsi: The HSI controller to register + */ +void hsi_unregister_controller(struct hsi_controller *hsi) +{ + device_for_each_child(&hsi->device, NULL, hsi_remove_port); + device_unregister(&hsi->device); +} +EXPORT_SYMBOL_GPL(hsi_unregister_controller); + +/** + * hsi_register_controller - Register an HSI controller and its ports + * @hsi: The HSI controller to register + * + * Returns -errno on failure, 0 on success. + */ +int hsi_register_controller(struct hsi_controller *hsi) +{ + unsigned int i; + int err; + + hsi->device.type = &hsi_ctrl; + hsi->device.bus = &hsi_bus_type; + hsi->device.release = hsi_controller_release; + err = device_register(&hsi->device); + if (err < 0) + return err; + for (i = 0; i < hsi->num_ports; i++) { + hsi->port[i].device.parent = &hsi->device; + hsi->port[i].device.bus = &hsi_bus_type; + hsi->port[i].device.release = hsi_port_release; + hsi->port[i].device.type = &hsi_port; + INIT_LIST_HEAD(&hsi->port[i].clients); + spin_lock_init(&hsi->port[i].clock); + err = device_register(&hsi->port[i].device); + if (err < 0) + goto out; + } + /* Populate HSI bus with HSI clients */ + hsi_scan_board_info(hsi); + + return 0; +out: + hsi_unregister_controller(hsi); + + return err; +} +EXPORT_SYMBOL_GPL(hsi_register_controller); + +/** + * hsi_register_client_driver - Register an HSI client to the HSI bus + * @drv: HSI client driver to register + * + * Returns -errno on failure, 0 on success. + */ +int hsi_register_client_driver(struct hsi_client_driver *drv) +{ + drv->driver.bus = &hsi_bus_type; + + return driver_register(&drv->driver); +} +EXPORT_SYMBOL_GPL(hsi_register_client_driver); + +static inline int hsi_dummy_msg(struct hsi_msg *msg __maybe_unused) +{ + return 0; +} + +static inline int hsi_dummy_cl(struct hsi_client *cl __maybe_unused) +{ + return 0; +} + +/** + * hsi_alloc_controller - Allocate an HSI controller and its ports + * @n_ports: Number of ports on the HSI controller + * @flags: Kernel allocation flags + * + * Return NULL on failure or a pointer to an hsi_controller on success. + */ +struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags) +{ + struct hsi_controller *hsi; + struct hsi_port *port; + unsigned int i; + + if (!n_ports) + return NULL; + + port = kzalloc(sizeof(*port)*n_ports, flags); + if (!port) + return NULL; + hsi = kzalloc(sizeof(*hsi), flags); + if (!hsi) + goto out; + for (i = 0; i < n_ports; i++) { + dev_set_name(&port[i].device, "port%d", i); + port[i].num = i; + port[i].async = hsi_dummy_msg; + port[i].setup = hsi_dummy_cl; + port[i].flush = hsi_dummy_cl; + port[i].start_tx = hsi_dummy_cl; + port[i].stop_tx = hsi_dummy_cl; + port[i].release = hsi_dummy_cl; + mutex_init(&port[i].lock); + } + hsi->num_ports = n_ports; + hsi->port = port; + + return hsi; +out: + kfree(port); + + return NULL; +} +EXPORT_SYMBOL_GPL(hsi_alloc_controller); + +/** + * hsi_free_controller - Free an HSI controller + * @hsi: Pointer to HSI controller + */ +void hsi_free_controller(struct hsi_controller *hsi) +{ + if (!hsi) + return; + + kfree(hsi->port); + kfree(hsi); +} +EXPORT_SYMBOL_GPL(hsi_free_controller); + +/** + * hsi_free_msg - Free an HSI message + * @msg: Pointer to the HSI message + * + * Client is responsible to free the buffers pointed by the scatterlists. + */ +void hsi_free_msg(struct hsi_msg *msg) +{ + if (!msg) + return; + sg_free_table(&msg->sgt); + kfree(msg); +} +EXPORT_SYMBOL_GPL(hsi_free_msg); + +/** + * hsi_alloc_msg - Allocate an HSI message + * @nents: Number of memory entries + * @flags: Kernel allocation flags + * + * nents can be 0. This mainly makes sense for read transfer. + * In that case, HSI drivers will call the complete callback when + * there is data to be read without consuming it. + * + * Return NULL on failure or a pointer to an hsi_msg on success. + */ +struct hsi_msg *hsi_alloc_msg(unsigned int nents, gfp_t flags) +{ + struct hsi_msg *msg; + int err; + + msg = kzalloc(sizeof(*msg), flags); + if (!msg) + return NULL; + + if (!nents) + return msg; + + err = sg_alloc_table(&msg->sgt, nents, flags); + if (unlikely(err)) { + kfree(msg); + msg = NULL; + } + + return msg; +} +EXPORT_SYMBOL_GPL(hsi_alloc_msg); + +/** + * hsi_async - Submit an HSI transfer to the controller + * @cl: HSI client sending the transfer + * @msg: The HSI transfer passed to controller + * + * The HSI message must have the channel, ttype, complete and destructor + * fields set beforehand. If nents > 0 then the client has to initialize + * also the scatterlists to point to the buffers to write to or read from. + * + * HSI controllers relay on pre-allocated buffers from their clients and they + * do not allocate buffers on their own. + * + * Once the HSI message transfer finishes, the HSI controller calls the + * complete callback with the status and actual_len fields of the HSI message + * updated. The complete callback can be called before returning from + * hsi_async. + * + * Returns -errno on failure or 0 on success + */ +int hsi_async(struct hsi_client *cl, struct hsi_msg *msg) +{ + struct hsi_port *port = hsi_get_port(cl); + + if (!hsi_port_claimed(cl)) + return -EACCES; + + WARN_ON_ONCE(!msg->destructor || !msg->complete); + msg->cl = cl; + + return port->async(msg); +} +EXPORT_SYMBOL_GPL(hsi_async); + +/** + * hsi_claim_port - Claim the HSI client's port + * @cl: HSI client that wants to claim its port + * @share: Flag to indicate if the client wants to share the port or not. + * + * Returns -errno on failure, 0 on success. + */ +int hsi_claim_port(struct hsi_client *cl, unsigned int share) +{ + struct hsi_port *port = hsi_get_port(cl); + int err = 0; + + mutex_lock(&port->lock); + if ((port->claimed) && (!port->shared || !share)) { + err = -EBUSY; + goto out; + } + if (!try_module_get(to_hsi_controller(port->device.parent)->owner)) { + err = -ENODEV; + goto out; + } + port->claimed++; + port->shared = !!share; + cl->pclaimed = 1; +out: + mutex_unlock(&port->lock); + + return err; +} +EXPORT_SYMBOL_GPL(hsi_claim_port); + +/** + * hsi_release_port - Release the HSI client's port + * @cl: HSI client which previously claimed its port + */ +void hsi_release_port(struct hsi_client *cl) +{ + struct hsi_port *port = hsi_get_port(cl); + + mutex_lock(&port->lock); + /* Allow HW driver to do some cleanup */ + port->release(cl); + if (cl->pclaimed) + port->claimed--; + BUG_ON(port->claimed < 0); + cl->pclaimed = 0; + if (!port->claimed) + port->shared = 0; + module_put(to_hsi_controller(port->device.parent)->owner); + mutex_unlock(&port->lock); +} +EXPORT_SYMBOL_GPL(hsi_release_port); + +static int hsi_start_rx(struct hsi_client *cl, void *data __maybe_unused) +{ + if (cl->hsi_start_rx) + (*cl->hsi_start_rx)(cl); + + return 0; +} + +static int hsi_stop_rx(struct hsi_client *cl, void *data __maybe_unused) +{ + if (cl->hsi_stop_rx) + (*cl->hsi_stop_rx)(cl); + + return 0; +} + +static int hsi_port_for_each_client(struct hsi_port *port, void *data, + int (*fn)(struct hsi_client *cl, void *data)) +{ + struct hsi_client *cl; + + spin_lock(&port->clock); + list_for_each_entry(cl, &port->clients, link) { + spin_unlock(&port->clock); + (*fn)(cl, data); + spin_lock(&port->clock); + } + spin_unlock(&port->clock); + + return 0; +} + +/** + * hsi_event -Notifies clients about port events + * @port: Port where the event occurred + * @event: The event type + * + * Clients should not be concerned about wake line behavior. However, due + * to a race condition in HSI HW protocol, clients need to be notified + * about wake line changes, so they can implement a workaround for it. + * + * Events: + * HSI_EVENT_START_RX - Incoming wake line high + * HSI_EVENT_STOP_RX - Incoming wake line down + */ +void hsi_event(struct hsi_port *port, unsigned int event) +{ + int (*fn)(struct hsi_client *cl, void *data); + + switch (event) { + case HSI_EVENT_START_RX: + fn = hsi_start_rx; + break; + case HSI_EVENT_STOP_RX: + fn = hsi_stop_rx; + break; + default: + return; + } + hsi_port_for_each_client(port, NULL, fn); +} +EXPORT_SYMBOL_GPL(hsi_event); + +static int __init hsi_init(void) +{ + return bus_register(&hsi_bus_type); +} +postcore_initcall(hsi_init); + +static void __exit hsi_exit(void) +{ + bus_unregister(&hsi_bus_type); +} +module_exit(hsi_exit); + +MODULE_AUTHOR("Carlos Chinea "); +MODULE_DESCRIPTION("High-speed Synchronous Serial Interface (HSI) framework"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/hsi/hsi_boardinfo.c b/drivers/hsi/hsi_boardinfo.c new file mode 100644 index 000000000000..e56bc6da5f98 --- /dev/null +++ b/drivers/hsi/hsi_boardinfo.c @@ -0,0 +1,62 @@ +/* + * HSI clients registration interface + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Carlos Chinea + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include +#include +#include +#include "hsi_core.h" + +/* + * hsi_board_list is only used internally by the HSI framework. + * No one else is allowed to make use of it. + */ +LIST_HEAD(hsi_board_list); +EXPORT_SYMBOL_GPL(hsi_board_list); + +/** + * hsi_register_board_info - Register HSI clients information + * @info: Array of HSI clients on the board + * @len: Length of the array + * + * HSI clients are statically declared and registered on board files. + * + * HSI clients will be automatically registered to the HSI bus once the + * controller and the port where the clients wishes to attach are registered + * to it. + * + * Return -errno on failure, 0 on success. + */ +int __init hsi_register_board_info(struct hsi_board_info const *info, + unsigned int len) +{ + struct hsi_cl_info *cl_info; + + cl_info = kzalloc(sizeof(*cl_info) * len, GFP_KERNEL); + if (!cl_info) + return -ENOMEM; + + for (; len; len--, info++, cl_info++) { + cl_info->info = *info; + list_add_tail(&cl_info->list, &hsi_board_list); + } + + return 0; +} diff --git a/drivers/hsi/hsi_core.h b/drivers/hsi/hsi_core.h new file mode 100644 index 000000000000..ab5c2fb175fd --- /dev/null +++ b/drivers/hsi/hsi_core.h @@ -0,0 +1,35 @@ +/* + * HSI framework internal interfaces, + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Carlos Chinea + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef __LINUX_HSI_CORE_H__ +#define __LINUX_HSI_CORE_H__ + +#include + +struct hsi_cl_info { + struct list_head list; + struct hsi_board_info info; +}; + +extern struct list_head hsi_board_list; + +#endif /* __LINUX_HSI_CORE_H__ */ diff --git a/include/linux/hsi/hsi.h b/include/linux/hsi/hsi.h new file mode 100644 index 000000000000..4b178067f405 --- /dev/null +++ b/include/linux/hsi/hsi.h @@ -0,0 +1,410 @@ +/* + * HSI core header file. + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Carlos Chinea + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef __LINUX_HSI_H__ +#define __LINUX_HSI_H__ + +#include +#include +#include +#include +#include +#include + +/* HSI message ttype */ +#define HSI_MSG_READ 0 +#define HSI_MSG_WRITE 1 + +/* HSI configuration values */ +enum { + HSI_MODE_STREAM = 1, + HSI_MODE_FRAME, +}; + +enum { + HSI_FLOW_SYNC, /* Synchronized flow */ + HSI_FLOW_PIPE, /* Pipelined flow */ +}; + +enum { + HSI_ARB_RR, /* Round-robin arbitration */ + HSI_ARB_PRIO, /* Channel priority arbitration */ +}; + +#define HSI_MAX_CHANNELS 16 + +/* HSI message status codes */ +enum { + HSI_STATUS_COMPLETED, /* Message transfer is completed */ + HSI_STATUS_PENDING, /* Message pending to be read/write (POLL) */ + HSI_STATUS_PROCEEDING, /* Message transfer is ongoing */ + HSI_STATUS_QUEUED, /* Message waiting to be served */ + HSI_STATUS_ERROR, /* Error when message transfer was ongoing */ +}; + +/* HSI port event codes */ +enum { + HSI_EVENT_START_RX, + HSI_EVENT_STOP_RX, +}; + +/** + * struct hsi_config - Configuration for RX/TX HSI modules + * @mode: Bit transmission mode (STREAM or FRAME) + * @channels: Number of channels to use [1..16] + * @speed: Max bit transmission speed (Kbit/s) + * @flow: RX flow type (SYNCHRONIZED or PIPELINE) + * @arb_mode: Arbitration mode for TX frame (Round robin, priority) + */ +struct hsi_config { + unsigned int mode; + unsigned int channels; + unsigned int speed; + union { + unsigned int flow; /* RX only */ + unsigned int arb_mode; /* TX only */ + }; +}; + +/** + * struct hsi_board_info - HSI client board info + * @name: Name for the HSI device + * @hsi_id: HSI controller id where the client sits + * @port: Port number in the controller where the client sits + * @tx_cfg: HSI TX configuration + * @rx_cfg: HSI RX configuration + * @platform_data: Platform related data + * @archdata: Architecture-dependent device data + */ +struct hsi_board_info { + const char *name; + unsigned int hsi_id; + unsigned int port; + struct hsi_config tx_cfg; + struct hsi_config rx_cfg; + void *platform_data; + struct dev_archdata *archdata; +}; + +#ifdef CONFIG_HSI_BOARDINFO +extern int hsi_register_board_info(struct hsi_board_info const *info, + unsigned int len); +#else +static inline int hsi_register_board_info(struct hsi_board_info const *info, + unsigned int len) +{ + return 0; +} +#endif /* CONFIG_HSI_BOARDINFO */ + +/** + * struct hsi_client - HSI client attached to an HSI port + * @device: Driver model representation of the device + * @tx_cfg: HSI TX configuration + * @rx_cfg: HSI RX configuration + * @hsi_start_rx: Called after incoming wake line goes high + * @hsi_stop_rx: Called after incoming wake line goes low + */ +struct hsi_client { + struct device device; + struct hsi_config tx_cfg; + struct hsi_config rx_cfg; + void (*hsi_start_rx)(struct hsi_client *cl); + void (*hsi_stop_rx)(struct hsi_client *cl); + /* private: */ + unsigned int pclaimed:1; + struct list_head link; +}; + +#define to_hsi_client(dev) container_of(dev, struct hsi_client, device) + +static inline void hsi_client_set_drvdata(struct hsi_client *cl, void *data) +{ + dev_set_drvdata(&cl->device, data); +} + +static inline void *hsi_client_drvdata(struct hsi_client *cl) +{ + return dev_get_drvdata(&cl->device); +} + +/** + * struct hsi_client_driver - Driver associated to an HSI client + * @driver: Driver model representation of the driver + */ +struct hsi_client_driver { + struct device_driver driver; +}; + +#define to_hsi_client_driver(drv) container_of(drv, struct hsi_client_driver,\ + driver) + +int hsi_register_client_driver(struct hsi_client_driver *drv); + +static inline void hsi_unregister_client_driver(struct hsi_client_driver *drv) +{ + driver_unregister(&drv->driver); +} + +/** + * struct hsi_msg - HSI message descriptor + * @link: Free to use by the current descriptor owner + * @cl: HSI device client that issues the transfer + * @sgt: Head of the scatterlist array + * @context: Client context data associated to the transfer + * @complete: Transfer completion callback + * @destructor: Destructor to free resources when flushing + * @status: Status of the transfer when completed + * @actual_len: Actual length of data transfered on completion + * @channel: Channel were to TX/RX the message + * @ttype: Transfer type (TX if set, RX otherwise) + * @break_frame: if true HSI will send/receive a break frame. Data buffers are + * ignored in the request. + */ +struct hsi_msg { + struct list_head link; + struct hsi_client *cl; + struct sg_table sgt; + void *context; + + void (*complete)(struct hsi_msg *msg); + void (*destructor)(struct hsi_msg *msg); + + int status; + unsigned int actual_len; + unsigned int channel; + unsigned int ttype:1; + unsigned int break_frame:1; +}; + +struct hsi_msg *hsi_alloc_msg(unsigned int n_frag, gfp_t flags); +void hsi_free_msg(struct hsi_msg *msg); + +/** + * struct hsi_port - HSI port device + * @device: Driver model representation of the device + * @tx_cfg: Current TX path configuration + * @rx_cfg: Current RX path configuration + * @num: Port number + * @shared: Set when port can be shared by different clients + * @claimed: Reference count of clients which claimed the port + * @lock: Serialize port claim + * @async: Asynchronous transfer callback + * @setup: Callback to set the HSI client configuration + * @flush: Callback to clean the HW state and destroy all pending transfers + * @start_tx: Callback to inform that a client wants to TX data + * @stop_tx: Callback to inform that a client no longer wishes to TX data + * @release: Callback to inform that a client no longer uses the port + * @clients: List of hsi_clients using the port. + * @clock: Lock to serialize access to the clients list. + */ +struct hsi_port { + struct device device; + struct hsi_config tx_cfg; + struct hsi_config rx_cfg; + unsigned int num; + unsigned int shared:1; + int claimed; + struct mutex lock; + int (*async)(struct hsi_msg *msg); + int (*setup)(struct hsi_client *cl); + int (*flush)(struct hsi_client *cl); + int (*start_tx)(struct hsi_client *cl); + int (*stop_tx)(struct hsi_client *cl); + int (*release)(struct hsi_client *cl); + struct list_head clients; + spinlock_t clock; +}; + +#define to_hsi_port(dev) container_of(dev, struct hsi_port, device) +#define hsi_get_port(cl) to_hsi_port((cl)->device.parent) + +void hsi_event(struct hsi_port *port, unsigned int event); +int hsi_claim_port(struct hsi_client *cl, unsigned int share); +void hsi_release_port(struct hsi_client *cl); + +static inline int hsi_port_claimed(struct hsi_client *cl) +{ + return cl->pclaimed; +} + +static inline void hsi_port_set_drvdata(struct hsi_port *port, void *data) +{ + dev_set_drvdata(&port->device, data); +} + +static inline void *hsi_port_drvdata(struct hsi_port *port) +{ + return dev_get_drvdata(&port->device); +} + +/** + * struct hsi_controller - HSI controller device + * @device: Driver model representation of the device + * @owner: Pointer to the module owning the controller + * @id: HSI controller ID + * @num_ports: Number of ports in the HSI controller + * @port: Array of HSI ports + */ +struct hsi_controller { + struct device device; + struct module *owner; + unsigned int id; + unsigned int num_ports; + struct hsi_port *port; +}; + +#define to_hsi_controller(dev) container_of(dev, struct hsi_controller, device) + +struct hsi_controller *hsi_alloc_controller(unsigned int n_ports, gfp_t flags); +void hsi_free_controller(struct hsi_controller *hsi); +int hsi_register_controller(struct hsi_controller *hsi); +void hsi_unregister_controller(struct hsi_controller *hsi); + +static inline void hsi_controller_set_drvdata(struct hsi_controller *hsi, + void *data) +{ + dev_set_drvdata(&hsi->device, data); +} + +static inline void *hsi_controller_drvdata(struct hsi_controller *hsi) +{ + return dev_get_drvdata(&hsi->device); +} + +static inline struct hsi_port *hsi_find_port_num(struct hsi_controller *hsi, + unsigned int num) +{ + return (num < hsi->num_ports) ? &hsi->port[num] : NULL; +} + +/* + * API for HSI clients + */ +int hsi_async(struct hsi_client *cl, struct hsi_msg *msg); + +/** + * hsi_id - Get HSI controller ID associated to a client + * @cl: Pointer to a HSI client + * + * Return the controller id where the client is attached to + */ +static inline unsigned int hsi_id(struct hsi_client *cl) +{ + return to_hsi_controller(cl->device.parent->parent)->id; +} + +/** + * hsi_port_id - Gets the port number a client is attached to + * @cl: Pointer to HSI client + * + * Return the port number associated to the client + */ +static inline unsigned int hsi_port_id(struct hsi_client *cl) +{ + return to_hsi_port(cl->device.parent)->num; +} + +/** + * hsi_setup - Configure the client's port + * @cl: Pointer to the HSI client + * + * When sharing ports, clients should either relay on a single + * client setup or have the same setup for all of them. + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_setup(struct hsi_client *cl) +{ + if (!hsi_port_claimed(cl)) + return -EACCES; + return hsi_get_port(cl)->setup(cl); +} + +/** + * hsi_flush - Flush all pending transactions on the client's port + * @cl: Pointer to the HSI client + * + * This function will destroy all pending hsi_msg in the port and reset + * the HW port so it is ready to receive and transmit from a clean state. + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_flush(struct hsi_client *cl) +{ + if (!hsi_port_claimed(cl)) + return -EACCES; + return hsi_get_port(cl)->flush(cl); +} + +/** + * hsi_async_read - Submit a read transfer + * @cl: Pointer to the HSI client + * @msg: HSI message descriptor of the transfer + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_async_read(struct hsi_client *cl, struct hsi_msg *msg) +{ + msg->ttype = HSI_MSG_READ; + return hsi_async(cl, msg); +} + +/** + * hsi_async_write - Submit a write transfer + * @cl: Pointer to the HSI client + * @msg: HSI message descriptor of the transfer + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_async_write(struct hsi_client *cl, struct hsi_msg *msg) +{ + msg->ttype = HSI_MSG_WRITE; + return hsi_async(cl, msg); +} + +/** + * hsi_start_tx - Signal the port that the client wants to start a TX + * @cl: Pointer to the HSI client + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_start_tx(struct hsi_client *cl) +{ + if (!hsi_port_claimed(cl)) + return -EACCES; + return hsi_get_port(cl)->start_tx(cl); +} + +/** + * hsi_stop_tx - Signal the port that the client no longer wants to transmit + * @cl: Pointer to the HSI client + * + * Return -errno on failure, 0 on success + */ +static inline int hsi_stop_tx(struct hsi_client *cl) +{ + if (!hsi_port_claimed(cl)) + return -EACCES; + return hsi_get_port(cl)->stop_tx(cl); +} +#endif /* __LINUX_HSI_H__ */ -- GitLab From 4e69fc22753fcce1d9275b5517ef3646ffeffcf4 Mon Sep 17 00:00:00 2001 From: Andras Domokos Date: Thu, 30 Sep 2010 17:18:53 +0300 Subject: [PATCH 00047/10698] HSI: hsi_char: Add HSI char device driver Add HSI char device driver to the kernel. Signed-off-by: Andras Domokos Signed-off-by: Carlos Chinea --- drivers/hsi/clients/hsi_char.c | 802 +++++++++++++++++++++++++++++++++ include/linux/hsi/hsi_char.h | 63 +++ 2 files changed, 865 insertions(+) create mode 100644 drivers/hsi/clients/hsi_char.c create mode 100644 include/linux/hsi/hsi_char.h diff --git a/drivers/hsi/clients/hsi_char.c b/drivers/hsi/clients/hsi_char.c new file mode 100644 index 000000000000..88a050df2389 --- /dev/null +++ b/drivers/hsi/clients/hsi_char.c @@ -0,0 +1,802 @@ +/* + * HSI character device driver, implements the character device + * interface. + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Andras Domokos + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define HSC_DEVS 16 /* Num of channels */ +#define HSC_MSGS 4 + +#define HSC_RXBREAK 0 + +#define HSC_ID_BITS 6 +#define HSC_PORT_ID_BITS 4 +#define HSC_ID_MASK 3 +#define HSC_PORT_ID_MASK 3 +#define HSC_CH_MASK 0xf + +/* + * We support up to 4 controllers that can have up to 4 + * ports, which should currently be more than enough. + */ +#define HSC_BASEMINOR(id, port_id) \ + ((((id) & HSC_ID_MASK) << HSC_ID_BITS) | \ + (((port_id) & HSC_PORT_ID_MASK) << HSC_PORT_ID_BITS)) + +enum { + HSC_CH_OPEN, + HSC_CH_READ, + HSC_CH_WRITE, + HSC_CH_WLINE, +}; + +enum { + HSC_RX, + HSC_TX, +}; + +struct hsc_client_data; +/** + * struct hsc_channel - hsi_char internal channel data + * @ch: channel number + * @flags: Keeps state of the channel (open/close, reading, writing) + * @free_msgs_list: List of free HSI messages/requests + * @rx_msgs_queue: List of pending RX requests + * @tx_msgs_queue: List of pending TX requests + * @lock: Serialize access to the lists + * @cl: reference to the associated hsi_client + * @cl_data: reference to the client data that this channels belongs to + * @rx_wait: RX requests wait queue + * @tx_wait: TX requests wait queue + */ +struct hsc_channel { + unsigned int ch; + unsigned long flags; + struct list_head free_msgs_list; + struct list_head rx_msgs_queue; + struct list_head tx_msgs_queue; + spinlock_t lock; + struct hsi_client *cl; + struct hsc_client_data *cl_data; + wait_queue_head_t rx_wait; + wait_queue_head_t tx_wait; +}; + +/** + * struct hsc_client_data - hsi_char internal client data + * @cdev: Characther device associated to the hsi_client + * @lock: Lock to serialize open/close access + * @flags: Keeps track of port state (rx hwbreak armed) + * @usecnt: Use count for claiming the HSI port (mutex protected) + * @cl: Referece to the HSI client + * @channels: Array of channels accessible by the client + */ +struct hsc_client_data { + struct cdev cdev; + struct mutex lock; + unsigned long flags; + unsigned int usecnt; + struct hsi_client *cl; + struct hsc_channel channels[HSC_DEVS]; +}; + +/* Stores the major number dynamically allocated for hsi_char */ +static unsigned int hsc_major; +/* Maximum buffer size that hsi_char will accept from userspace */ +static unsigned int max_data_size = 0x1000; +module_param(max_data_size, uint, S_IRUSR | S_IWUSR); +MODULE_PARM_DESC(max_data_size, "max read/write data size [4,8..65536] (^2)"); + +static void hsc_add_tail(struct hsc_channel *channel, struct hsi_msg *msg, + struct list_head *queue) +{ + unsigned long flags; + + spin_lock_irqsave(&channel->lock, flags); + list_add_tail(&msg->link, queue); + spin_unlock_irqrestore(&channel->lock, flags); +} + +static struct hsi_msg *hsc_get_first_msg(struct hsc_channel *channel, + struct list_head *queue) +{ + struct hsi_msg *msg = NULL; + unsigned long flags; + + spin_lock_irqsave(&channel->lock, flags); + + if (list_empty(queue)) + goto out; + + msg = list_first_entry(queue, struct hsi_msg, link); + list_del(&msg->link); +out: + spin_unlock_irqrestore(&channel->lock, flags); + + return msg; +} + +static inline void hsc_msg_free(struct hsi_msg *msg) +{ + kfree(sg_virt(msg->sgt.sgl)); + hsi_free_msg(msg); +} + +static void hsc_free_list(struct list_head *list) +{ + struct hsi_msg *msg, *tmp; + + list_for_each_entry_safe(msg, tmp, list, link) { + list_del(&msg->link); + hsc_msg_free(msg); + } +} + +static void hsc_reset_list(struct hsc_channel *channel, struct list_head *l) +{ + unsigned long flags; + LIST_HEAD(list); + + spin_lock_irqsave(&channel->lock, flags); + list_splice_init(l, &list); + spin_unlock_irqrestore(&channel->lock, flags); + + hsc_free_list(&list); +} + +static inline struct hsi_msg *hsc_msg_alloc(unsigned int alloc_size) +{ + struct hsi_msg *msg; + void *buf; + + msg = hsi_alloc_msg(1, GFP_KERNEL); + if (!msg) + goto out; + buf = kmalloc(alloc_size, GFP_KERNEL); + if (!buf) { + hsi_free_msg(msg); + goto out; + } + sg_init_one(msg->sgt.sgl, buf, alloc_size); + /* Ignore false positive, due to sg pointer handling */ + kmemleak_ignore(buf); + + return msg; +out: + return NULL; +} + +static inline int hsc_msgs_alloc(struct hsc_channel *channel) +{ + struct hsi_msg *msg; + int i; + + for (i = 0; i < HSC_MSGS; i++) { + msg = hsc_msg_alloc(max_data_size); + if (!msg) + goto out; + msg->channel = channel->ch; + list_add_tail(&msg->link, &channel->free_msgs_list); + } + + return 0; +out: + hsc_free_list(&channel->free_msgs_list); + + return -ENOMEM; +} + +static inline unsigned int hsc_msg_len_get(struct hsi_msg *msg) +{ + return msg->sgt.sgl->length; +} + +static inline void hsc_msg_len_set(struct hsi_msg *msg, unsigned int len) +{ + msg->sgt.sgl->length = len; +} + +static void hsc_rx_completed(struct hsi_msg *msg) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); + struct hsc_channel *channel = cl_data->channels + msg->channel; + + if (test_bit(HSC_CH_READ, &channel->flags)) { + hsc_add_tail(channel, msg, &channel->rx_msgs_queue); + wake_up(&channel->rx_wait); + } else { + hsc_add_tail(channel, msg, &channel->free_msgs_list); + } +} + +static void hsc_rx_msg_destructor(struct hsi_msg *msg) +{ + msg->status = HSI_STATUS_ERROR; + hsc_msg_len_set(msg, 0); + hsc_rx_completed(msg); +} + +static void hsc_tx_completed(struct hsi_msg *msg) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); + struct hsc_channel *channel = cl_data->channels + msg->channel; + + if (test_bit(HSC_CH_WRITE, &channel->flags)) { + hsc_add_tail(channel, msg, &channel->tx_msgs_queue); + wake_up(&channel->tx_wait); + } else { + hsc_add_tail(channel, msg, &channel->free_msgs_list); + } +} + +static void hsc_tx_msg_destructor(struct hsi_msg *msg) +{ + msg->status = HSI_STATUS_ERROR; + hsc_msg_len_set(msg, 0); + hsc_tx_completed(msg); +} + +static void hsc_break_req_destructor(struct hsi_msg *msg) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); + + hsi_free_msg(msg); + clear_bit(HSC_RXBREAK, &cl_data->flags); +} + +static void hsc_break_received(struct hsi_msg *msg) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(msg->cl); + struct hsc_channel *channel = cl_data->channels; + int i, ret; + + /* Broadcast HWBREAK on all channels */ + for (i = 0; i < HSC_DEVS; i++, channel++) { + struct hsi_msg *msg2; + + if (!test_bit(HSC_CH_READ, &channel->flags)) + continue; + msg2 = hsc_get_first_msg(channel, &channel->free_msgs_list); + if (!msg2) + continue; + clear_bit(HSC_CH_READ, &channel->flags); + hsc_msg_len_set(msg2, 0); + msg2->status = HSI_STATUS_COMPLETED; + hsc_add_tail(channel, msg2, &channel->rx_msgs_queue); + wake_up(&channel->rx_wait); + } + hsi_flush(msg->cl); + ret = hsi_async_read(msg->cl, msg); + if (ret < 0) + hsc_break_req_destructor(msg); +} + +static int hsc_break_request(struct hsi_client *cl) +{ + struct hsc_client_data *cl_data = hsi_client_drvdata(cl); + struct hsi_msg *msg; + int ret; + + if (test_and_set_bit(HSC_RXBREAK, &cl_data->flags)) + return -EBUSY; + + msg = hsi_alloc_msg(0, GFP_KERNEL); + if (!msg) { + clear_bit(HSC_RXBREAK, &cl_data->flags); + return -ENOMEM; + } + msg->break_frame = 1; + msg->complete = hsc_break_received; + msg->destructor = hsc_break_req_destructor; + ret = hsi_async_read(cl, msg); + if (ret < 0) + hsc_break_req_destructor(msg); + + return ret; +} + +static int hsc_break_send(struct hsi_client *cl) +{ + struct hsi_msg *msg; + int ret; + + msg = hsi_alloc_msg(0, GFP_ATOMIC); + if (!msg) + return -ENOMEM; + msg->break_frame = 1; + msg->complete = hsi_free_msg; + msg->destructor = hsi_free_msg; + ret = hsi_async_write(cl, msg); + if (ret < 0) + hsi_free_msg(msg); + + return ret; +} + +static int hsc_rx_set(struct hsi_client *cl, struct hsc_rx_config *rxc) +{ + struct hsi_config tmp; + int ret; + + if ((rxc->mode != HSI_MODE_STREAM) && (rxc->mode != HSI_MODE_FRAME)) + return -EINVAL; + if ((rxc->channels == 0) || (rxc->channels > HSC_DEVS)) + return -EINVAL; + if (rxc->channels & (rxc->channels - 1)) + return -EINVAL; + if ((rxc->flow != HSI_FLOW_SYNC) && (rxc->flow != HSI_FLOW_PIPE)) + return -EINVAL; + tmp = cl->rx_cfg; + cl->rx_cfg.mode = rxc->mode; + cl->rx_cfg.channels = rxc->channels; + cl->rx_cfg.flow = rxc->flow; + ret = hsi_setup(cl); + if (ret < 0) { + cl->rx_cfg = tmp; + return ret; + } + if (rxc->mode == HSI_MODE_FRAME) + hsc_break_request(cl); + + return ret; +} + +static inline void hsc_rx_get(struct hsi_client *cl, struct hsc_rx_config *rxc) +{ + rxc->mode = cl->rx_cfg.mode; + rxc->channels = cl->rx_cfg.channels; + rxc->flow = cl->rx_cfg.flow; +} + +static int hsc_tx_set(struct hsi_client *cl, struct hsc_tx_config *txc) +{ + struct hsi_config tmp; + int ret; + + if ((txc->mode != HSI_MODE_STREAM) && (txc->mode != HSI_MODE_FRAME)) + return -EINVAL; + if ((txc->channels == 0) || (txc->channels > HSC_DEVS)) + return -EINVAL; + if (txc->channels & (txc->channels - 1)) + return -EINVAL; + if ((txc->arb_mode != HSI_ARB_RR) && (txc->arb_mode != HSI_ARB_PRIO)) + return -EINVAL; + tmp = cl->tx_cfg; + cl->tx_cfg.mode = txc->mode; + cl->tx_cfg.channels = txc->channels; + cl->tx_cfg.speed = txc->speed; + cl->tx_cfg.arb_mode = txc->arb_mode; + ret = hsi_setup(cl); + if (ret < 0) { + cl->tx_cfg = tmp; + return ret; + } + + return ret; +} + +static inline void hsc_tx_get(struct hsi_client *cl, struct hsc_tx_config *txc) +{ + txc->mode = cl->tx_cfg.mode; + txc->channels = cl->tx_cfg.channels; + txc->speed = cl->tx_cfg.speed; + txc->arb_mode = cl->tx_cfg.arb_mode; +} + +static ssize_t hsc_read(struct file *file, char __user *buf, size_t len, + loff_t *ppos __maybe_unused) +{ + struct hsc_channel *channel = file->private_data; + struct hsi_msg *msg; + ssize_t ret; + + if (len == 0) + return 0; + if (!IS_ALIGNED(len, sizeof(u32))) + return -EINVAL; + if (len > max_data_size) + len = max_data_size; + if (channel->ch >= channel->cl->rx_cfg.channels) + return -ECHRNG; + if (test_and_set_bit(HSC_CH_READ, &channel->flags)) + return -EBUSY; + msg = hsc_get_first_msg(channel, &channel->free_msgs_list); + if (!msg) { + ret = -ENOSPC; + goto out; + } + hsc_msg_len_set(msg, len); + msg->complete = hsc_rx_completed; + msg->destructor = hsc_rx_msg_destructor; + ret = hsi_async_read(channel->cl, msg); + if (ret < 0) { + hsc_add_tail(channel, msg, &channel->free_msgs_list); + goto out; + } + + ret = wait_event_interruptible(channel->rx_wait, + !list_empty(&channel->rx_msgs_queue)); + if (ret < 0) { + clear_bit(HSC_CH_READ, &channel->flags); + hsi_flush(channel->cl); + return -EINTR; + } + + msg = hsc_get_first_msg(channel, &channel->rx_msgs_queue); + if (msg) { + if (msg->status != HSI_STATUS_ERROR) { + ret = copy_to_user((void __user *)buf, + sg_virt(msg->sgt.sgl), hsc_msg_len_get(msg)); + if (ret) + ret = -EFAULT; + else + ret = hsc_msg_len_get(msg); + } else { + ret = -EIO; + } + hsc_add_tail(channel, msg, &channel->free_msgs_list); + } +out: + clear_bit(HSC_CH_READ, &channel->flags); + + return ret; +} + +static ssize_t hsc_write(struct file *file, const char __user *buf, size_t len, + loff_t *ppos __maybe_unused) +{ + struct hsc_channel *channel = file->private_data; + struct hsi_msg *msg; + ssize_t ret; + + if ((len == 0) || !IS_ALIGNED(len, sizeof(u32))) + return -EINVAL; + if (len > max_data_size) + len = max_data_size; + if (channel->ch >= channel->cl->tx_cfg.channels) + return -ECHRNG; + if (test_and_set_bit(HSC_CH_WRITE, &channel->flags)) + return -EBUSY; + msg = hsc_get_first_msg(channel, &channel->free_msgs_list); + if (!msg) { + clear_bit(HSC_CH_WRITE, &channel->flags); + return -ENOSPC; + } + if (copy_from_user(sg_virt(msg->sgt.sgl), (void __user *)buf, len)) { + ret = -EFAULT; + goto out; + } + hsc_msg_len_set(msg, len); + msg->complete = hsc_tx_completed; + msg->destructor = hsc_tx_msg_destructor; + ret = hsi_async_write(channel->cl, msg); + if (ret < 0) + goto out; + + ret = wait_event_interruptible(channel->tx_wait, + !list_empty(&channel->tx_msgs_queue)); + if (ret < 0) { + clear_bit(HSC_CH_WRITE, &channel->flags); + hsi_flush(channel->cl); + return -EINTR; + } + + msg = hsc_get_first_msg(channel, &channel->tx_msgs_queue); + if (msg) { + if (msg->status == HSI_STATUS_ERROR) + ret = -EIO; + else + ret = hsc_msg_len_get(msg); + + hsc_add_tail(channel, msg, &channel->free_msgs_list); + } +out: + clear_bit(HSC_CH_WRITE, &channel->flags); + + return ret; +} + +static long hsc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct hsc_channel *channel = file->private_data; + unsigned int state; + struct hsc_rx_config rxc; + struct hsc_tx_config txc; + long ret = 0; + + switch (cmd) { + case HSC_RESET: + hsi_flush(channel->cl); + break; + case HSC_SET_PM: + if (copy_from_user(&state, (void __user *)arg, sizeof(state))) + return -EFAULT; + if (state == HSC_PM_DISABLE) { + if (test_and_set_bit(HSC_CH_WLINE, &channel->flags)) + return -EINVAL; + ret = hsi_start_tx(channel->cl); + } else if (state == HSC_PM_ENABLE) { + if (!test_and_clear_bit(HSC_CH_WLINE, &channel->flags)) + return -EINVAL; + ret = hsi_stop_tx(channel->cl); + } else { + ret = -EINVAL; + } + break; + case HSC_SEND_BREAK: + return hsc_break_send(channel->cl); + case HSC_SET_RX: + if (copy_from_user(&rxc, (void __user *)arg, sizeof(rxc))) + return -EFAULT; + return hsc_rx_set(channel->cl, &rxc); + case HSC_GET_RX: + hsc_rx_get(channel->cl, &rxc); + if (copy_to_user((void __user *)arg, &rxc, sizeof(rxc))) + return -EFAULT; + break; + case HSC_SET_TX: + if (copy_from_user(&txc, (void __user *)arg, sizeof(txc))) + return -EFAULT; + return hsc_tx_set(channel->cl, &txc); + case HSC_GET_TX: + hsc_tx_get(channel->cl, &txc); + if (copy_to_user((void __user *)arg, &txc, sizeof(txc))) + return -EFAULT; + break; + default: + return -ENOIOCTLCMD; + } + + return ret; +} + +static inline void __hsc_port_release(struct hsc_client_data *cl_data) +{ + BUG_ON(cl_data->usecnt == 0); + + if (--cl_data->usecnt == 0) { + hsi_flush(cl_data->cl); + hsi_release_port(cl_data->cl); + } +} + +static int hsc_open(struct inode *inode, struct file *file) +{ + struct hsc_client_data *cl_data; + struct hsc_channel *channel; + int ret = 0; + + pr_debug("open, minor = %d\n", iminor(inode)); + + cl_data = container_of(inode->i_cdev, struct hsc_client_data, cdev); + mutex_lock(&cl_data->lock); + channel = cl_data->channels + (iminor(inode) & HSC_CH_MASK); + + if (test_and_set_bit(HSC_CH_OPEN, &channel->flags)) { + ret = -EBUSY; + goto out; + } + /* + * Check if we have already claimed the port associated to the HSI + * client. If not then try to claim it, else increase its refcount + */ + if (cl_data->usecnt == 0) { + ret = hsi_claim_port(cl_data->cl, 0); + if (ret < 0) + goto out; + hsi_setup(cl_data->cl); + } + cl_data->usecnt++; + + ret = hsc_msgs_alloc(channel); + if (ret < 0) { + __hsc_port_release(cl_data); + goto out; + } + + file->private_data = channel; + mutex_unlock(&cl_data->lock); + + return ret; +out: + mutex_unlock(&cl_data->lock); + + return ret; +} + +static int hsc_release(struct inode *inode __maybe_unused, struct file *file) +{ + struct hsc_channel *channel = file->private_data; + struct hsc_client_data *cl_data = channel->cl_data; + + mutex_lock(&cl_data->lock); + file->private_data = NULL; + if (test_and_clear_bit(HSC_CH_WLINE, &channel->flags)) + hsi_stop_tx(channel->cl); + __hsc_port_release(cl_data); + hsc_reset_list(channel, &channel->rx_msgs_queue); + hsc_reset_list(channel, &channel->tx_msgs_queue); + hsc_reset_list(channel, &channel->free_msgs_list); + clear_bit(HSC_CH_READ, &channel->flags); + clear_bit(HSC_CH_WRITE, &channel->flags); + clear_bit(HSC_CH_OPEN, &channel->flags); + wake_up(&channel->rx_wait); + wake_up(&channel->tx_wait); + mutex_unlock(&cl_data->lock); + + return 0; +} + +static const struct file_operations hsc_fops = { + .owner = THIS_MODULE, + .read = hsc_read, + .write = hsc_write, + .unlocked_ioctl = hsc_ioctl, + .open = hsc_open, + .release = hsc_release, +}; + +static void __devinit hsc_channel_init(struct hsc_channel *channel) +{ + init_waitqueue_head(&channel->rx_wait); + init_waitqueue_head(&channel->tx_wait); + spin_lock_init(&channel->lock); + INIT_LIST_HEAD(&channel->free_msgs_list); + INIT_LIST_HEAD(&channel->rx_msgs_queue); + INIT_LIST_HEAD(&channel->tx_msgs_queue); +} + +static int __devinit hsc_probe(struct device *dev) +{ + const char devname[] = "hsi_char"; + struct hsc_client_data *cl_data; + struct hsc_channel *channel; + struct hsi_client *cl = to_hsi_client(dev); + unsigned int hsc_baseminor; + dev_t hsc_dev; + int ret; + int i; + + cl_data = kzalloc(sizeof(*cl_data), GFP_KERNEL); + if (!cl_data) { + dev_err(dev, "Could not allocate hsc_client_data\n"); + return -ENOMEM; + } + hsc_baseminor = HSC_BASEMINOR(hsi_id(cl), hsi_port_id(cl)); + if (!hsc_major) { + ret = alloc_chrdev_region(&hsc_dev, hsc_baseminor, + HSC_DEVS, devname); + if (ret > 0) + hsc_major = MAJOR(hsc_dev); + } else { + hsc_dev = MKDEV(hsc_major, hsc_baseminor); + ret = register_chrdev_region(hsc_dev, HSC_DEVS, devname); + } + if (ret < 0) { + dev_err(dev, "Device %s allocation failed %d\n", + hsc_major ? "minor" : "major", ret); + goto out1; + } + mutex_init(&cl_data->lock); + hsi_client_set_drvdata(cl, cl_data); + cdev_init(&cl_data->cdev, &hsc_fops); + cl_data->cdev.owner = THIS_MODULE; + cl_data->cl = cl; + for (i = 0, channel = cl_data->channels; i < HSC_DEVS; i++, channel++) { + hsc_channel_init(channel); + channel->ch = i; + channel->cl = cl; + channel->cl_data = cl_data; + } + + /* 1 hsi client -> N char devices (one for each channel) */ + ret = cdev_add(&cl_data->cdev, hsc_dev, HSC_DEVS); + if (ret) { + dev_err(dev, "Could not add char device %d\n", ret); + goto out2; + } + + return 0; +out2: + unregister_chrdev_region(hsc_dev, HSC_DEVS); +out1: + kfree(cl_data); + + return ret; +} + +static int __devexit hsc_remove(struct device *dev) +{ + struct hsi_client *cl = to_hsi_client(dev); + struct hsc_client_data *cl_data = hsi_client_drvdata(cl); + dev_t hsc_dev = cl_data->cdev.dev; + + cdev_del(&cl_data->cdev); + unregister_chrdev_region(hsc_dev, HSC_DEVS); + hsi_client_set_drvdata(cl, NULL); + kfree(cl_data); + + return 0; +} + +static struct hsi_client_driver hsc_driver = { + .driver = { + .name = "hsi_char", + .owner = THIS_MODULE, + .probe = hsc_probe, + .remove = __devexit_p(hsc_remove), + }, +}; + +static int __init hsc_init(void) +{ + int ret; + + if ((max_data_size < 4) || (max_data_size > 0x10000) || + (max_data_size & (max_data_size - 1))) { + pr_err("Invalid max read/write data size"); + return -EINVAL; + } + + ret = hsi_register_client_driver(&hsc_driver); + if (ret) { + pr_err("Error while registering HSI/SSI driver %d", ret); + return ret; + } + + pr_info("HSI/SSI char device loaded\n"); + + return 0; +} +module_init(hsc_init); + +static void __exit hsc_exit(void) +{ + hsi_unregister_client_driver(&hsc_driver); + pr_info("HSI char device removed\n"); +} +module_exit(hsc_exit); + +MODULE_AUTHOR("Andras Domokos "); +MODULE_ALIAS("hsi:hsi_char"); +MODULE_DESCRIPTION("HSI character device"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/hsi/hsi_char.h b/include/linux/hsi/hsi_char.h new file mode 100644 index 000000000000..76160b4f455d --- /dev/null +++ b/include/linux/hsi/hsi_char.h @@ -0,0 +1,63 @@ +/* + * Part of the HSI character device driver. + * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * + * Contact: Andras Domokos + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + + +#ifndef __HSI_CHAR_H +#define __HSI_CHAR_H + +#define HSI_CHAR_MAGIC 'k' +#define HSC_IOW(num, dtype) _IOW(HSI_CHAR_MAGIC, num, dtype) +#define HSC_IOR(num, dtype) _IOR(HSI_CHAR_MAGIC, num, dtype) +#define HSC_IOWR(num, dtype) _IOWR(HSI_CHAR_MAGIC, num, dtype) +#define HSC_IO(num) _IO(HSI_CHAR_MAGIC, num) + +#define HSC_RESET HSC_IO(16) +#define HSC_SET_PM HSC_IO(17) +#define HSC_SEND_BREAK HSC_IO(18) +#define HSC_SET_RX HSC_IOW(19, struct hsc_rx_config) +#define HSC_GET_RX HSC_IOW(20, struct hsc_rx_config) +#define HSC_SET_TX HSC_IOW(21, struct hsc_tx_config) +#define HSC_GET_TX HSC_IOW(22, struct hsc_tx_config) + +#define HSC_PM_DISABLE 0 +#define HSC_PM_ENABLE 1 + +#define HSC_MODE_STREAM 1 +#define HSC_MODE_FRAME 2 +#define HSC_FLOW_SYNC 0 +#define HSC_ARB_RR 0 +#define HSC_ARB_PRIO 1 + +struct hsc_rx_config { + uint32_t mode; + uint32_t flow; + uint32_t channels; +}; + +struct hsc_tx_config { + uint32_t mode; + uint32_t channels; + uint32_t speed; + uint32_t arb_mode; +}; + +#endif /* __HSI_CHAR_H */ -- GitLab From f9e402016de91c2444e46ecfd706880969b1ae9e Mon Sep 17 00:00:00 2001 From: Andras Domokos Date: Wed, 21 Apr 2010 12:04:21 +0300 Subject: [PATCH 00048/10698] HSI: hsi_char: Add HSI char device kernel configuration Add HSI character device kernel configuration Signed-off-by: Andras Domokos Signed-off-by: Carlos Chinea --- drivers/hsi/Kconfig | 2 ++ drivers/hsi/Makefile | 1 + drivers/hsi/clients/Kconfig | 13 +++++++++++++ drivers/hsi/clients/Makefile | 5 +++++ include/linux/Kbuild | 1 + include/linux/hsi/Kbuild | 1 + 6 files changed, 23 insertions(+) create mode 100644 drivers/hsi/clients/Kconfig create mode 100644 drivers/hsi/clients/Makefile create mode 100644 include/linux/hsi/Kbuild diff --git a/drivers/hsi/Kconfig b/drivers/hsi/Kconfig index 937062e8bcd0..d94e38dd80c7 100644 --- a/drivers/hsi/Kconfig +++ b/drivers/hsi/Kconfig @@ -14,4 +14,6 @@ config HSI_BOARDINFO bool default y +source "drivers/hsi/clients/Kconfig" + endif # HSI diff --git a/drivers/hsi/Makefile b/drivers/hsi/Makefile index ed94a3a334a4..9d5d33f90de2 100644 --- a/drivers/hsi/Makefile +++ b/drivers/hsi/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_HSI_BOARDINFO) += hsi_boardinfo.o obj-$(CONFIG_HSI) += hsi.o +obj-y += clients/ diff --git a/drivers/hsi/clients/Kconfig b/drivers/hsi/clients/Kconfig new file mode 100644 index 000000000000..3bacd275f479 --- /dev/null +++ b/drivers/hsi/clients/Kconfig @@ -0,0 +1,13 @@ +# +# HSI clients configuration +# + +comment "HSI clients" + +config HSI_CHAR + tristate "HSI/SSI character driver" + depends on HSI + ---help--- + If you say Y here, you will enable the HSI/SSI character driver. + This driver provides a simple character device interface for + serial communication with the cellular modem over HSI/SSI bus. diff --git a/drivers/hsi/clients/Makefile b/drivers/hsi/clients/Makefile new file mode 100644 index 000000000000..327c0e27c8b0 --- /dev/null +++ b/drivers/hsi/clients/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for HSI clients +# + +obj-$(CONFIG_HSI_CHAR) += hsi_char.o diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 619b5657af77..3171939e6261 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -3,6 +3,7 @@ header-y += can/ header-y += caif/ header-y += dvb/ header-y += hdlc/ +header-y += hsi/ header-y += isdn/ header-y += mmc/ header-y += nfsd/ diff --git a/include/linux/hsi/Kbuild b/include/linux/hsi/Kbuild new file mode 100644 index 000000000000..271a770b4784 --- /dev/null +++ b/include/linux/hsi/Kbuild @@ -0,0 +1 @@ +header-y += hsi_char.h -- GitLab From a4ac73a701288f633fbf2369ffaae4841aa295b3 Mon Sep 17 00:00:00 2001 From: Carlos Chinea Date: Thu, 29 Apr 2010 13:19:06 +0300 Subject: [PATCH 00049/10698] HSI: Add HSI API documentation Add an entry for HSI in the device-drivers section of the kernel documentation. Signed-off-by: Carlos Chinea --- Documentation/DocBook/device-drivers.tmpl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index b638e50cf8f6..5f70f734e8b4 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -437,4 +437,21 @@ X!Idrivers/video/console/fonts.c !Edrivers/i2c/i2c-core.c + + High Speed Synchronous Serial Interface (HSI) + + + High Speed Synchronous Serial Interface (HSI) is a + serial interface mainly used for connecting application + engines (APE) with cellular modem engines (CMT) in cellular + handsets. + + HSI provides multiplexing for up to 16 logical channels, + low-latency and full duplex communication. + + +!Iinclude/linux/hsi/hsi.h +!Edrivers/hsi/hsi.c + + -- GitLab From 43139a61fc68f4b0af7327a0e63f340a7c81c69a Mon Sep 17 00:00:00 2001 From: Andras Domokos Date: Thu, 6 May 2010 15:10:47 +0300 Subject: [PATCH 00050/10698] HSI: hsi_char: Update ioctl-number.txt Added ioctl range for HSI char devices to the documentation Signed-off-by: Andras Domokos Signed-off-by: Carlos Chinea --- Documentation/ioctl/ioctl-number.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt index 54078ed96b37..af76fdef6046 100644 --- a/Documentation/ioctl/ioctl-number.txt +++ b/Documentation/ioctl/ioctl-number.txt @@ -223,6 +223,7 @@ Code Seq#(hex) Include File Comments 'j' 00-3F linux/joystick.h 'k' 00-0F linux/spi/spidev.h conflict! 'k' 00-05 video/kyro.h conflict! +'k' 10-17 linux/hsi/hsi_char.h HSI character device 'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system 'l' 40-7F linux/udf_fs_i.h in development: -- GitLab From 9c636baf8518d0f986004b40669b75506459beac Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Jan 2012 17:19:45 +0000 Subject: [PATCH 00051/10698] sfc: Fix some formatting errors reported by checkpatch Fix the following errors and warnings: ERROR: trailing whitespace ERROR: spaces required around that '=' (ctx:VxV) WARNING: please, no space before tabs Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/bitfield.h | 18 +++++++++--------- drivers/net/ethernet/sfc/efx.c | 16 ++++++++-------- drivers/net/ethernet/sfc/ethtool.c | 4 ++-- drivers/net/ethernet/sfc/falcon_xmac.c | 2 +- drivers/net/ethernet/sfc/mcdi_mac.c | 2 +- drivers/net/ethernet/sfc/mcdi_phy.c | 2 +- drivers/net/ethernet/sfc/mdio_10g.c | 2 +- drivers/net/ethernet/sfc/nic.c | 2 +- drivers/net/ethernet/sfc/qt202x_phy.c | 6 +++--- drivers/net/ethernet/sfc/selftest.c | 2 +- drivers/net/ethernet/sfc/spi.h | 2 +- drivers/net/ethernet/sfc/tenxpress.c | 2 +- 12 files changed, 30 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/sfc/bitfield.h b/drivers/net/ethernet/sfc/bitfield.h index 098ac2ad757d..a2a9f40b90cf 100644 --- a/drivers/net/ethernet/sfc/bitfield.h +++ b/drivers/net/ethernet/sfc/bitfield.h @@ -448,40 +448,40 @@ typedef union efx_oword { EFX_INSERT32(min, max, low, high, EFX_MASK32(high + 1 - low)) #define EFX_SET_OWORD64(oword, low, high, value) do { \ - (oword).u64[0] = (((oword).u64[0] \ + (oword).u64[0] = (((oword).u64[0] \ & ~EFX_INPLACE_MASK64(0, 63, low, high)) \ | EFX_INSERT64(0, 63, low, high, value)); \ - (oword).u64[1] = (((oword).u64[1] \ + (oword).u64[1] = (((oword).u64[1] \ & ~EFX_INPLACE_MASK64(64, 127, low, high)) \ | EFX_INSERT64(64, 127, low, high, value)); \ } while (0) #define EFX_SET_QWORD64(qword, low, high, value) do { \ - (qword).u64[0] = (((qword).u64[0] \ + (qword).u64[0] = (((qword).u64[0] \ & ~EFX_INPLACE_MASK64(0, 63, low, high)) \ | EFX_INSERT64(0, 63, low, high, value)); \ } while (0) #define EFX_SET_OWORD32(oword, low, high, value) do { \ - (oword).u32[0] = (((oword).u32[0] \ + (oword).u32[0] = (((oword).u32[0] \ & ~EFX_INPLACE_MASK32(0, 31, low, high)) \ | EFX_INSERT32(0, 31, low, high, value)); \ - (oword).u32[1] = (((oword).u32[1] \ + (oword).u32[1] = (((oword).u32[1] \ & ~EFX_INPLACE_MASK32(32, 63, low, high)) \ | EFX_INSERT32(32, 63, low, high, value)); \ - (oword).u32[2] = (((oword).u32[2] \ + (oword).u32[2] = (((oword).u32[2] \ & ~EFX_INPLACE_MASK32(64, 95, low, high)) \ | EFX_INSERT32(64, 95, low, high, value)); \ - (oword).u32[3] = (((oword).u32[3] \ + (oword).u32[3] = (((oword).u32[3] \ & ~EFX_INPLACE_MASK32(96, 127, low, high)) \ | EFX_INSERT32(96, 127, low, high, value)); \ } while (0) #define EFX_SET_QWORD32(qword, low, high, value) do { \ - (qword).u32[0] = (((qword).u32[0] \ + (qword).u32[0] = (((qword).u32[0] \ & ~EFX_INPLACE_MASK32(0, 31, low, high)) \ | EFX_INSERT32(0, 31, low, high, value)); \ - (qword).u32[1] = (((qword).u32[1] \ + (qword).u32[1] = (((qword).u32[1] \ & ~EFX_INPLACE_MASK32(32, 63, low, high)) \ | EFX_INSERT32(32, 63, low, high, value)); \ } while (0) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index e43702f33b62..11cc585c36a4 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -44,9 +44,9 @@ const char *efx_loopback_mode_names[] = { [LOOPBACK_GMAC] = "GMAC", [LOOPBACK_XGMII] = "XGMII", [LOOPBACK_XGXS] = "XGXS", - [LOOPBACK_XAUI] = "XAUI", - [LOOPBACK_GMII] = "GMII", - [LOOPBACK_SGMII] = "SGMII", + [LOOPBACK_XAUI] = "XAUI", + [LOOPBACK_GMII] = "GMII", + [LOOPBACK_SGMII] = "SGMII", [LOOPBACK_XGBR] = "XGBR", [LOOPBACK_XFI] = "XFI", [LOOPBACK_XAUI_FAR] = "XAUI_FAR", @@ -55,17 +55,17 @@ const char *efx_loopback_mode_names[] = { [LOOPBACK_XFI_FAR] = "XFI_FAR", [LOOPBACK_GPHY] = "GPHY", [LOOPBACK_PHYXS] = "PHYXS", - [LOOPBACK_PCS] = "PCS", - [LOOPBACK_PMAPMD] = "PMA/PMD", + [LOOPBACK_PCS] = "PCS", + [LOOPBACK_PMAPMD] = "PMA/PMD", [LOOPBACK_XPORT] = "XPORT", [LOOPBACK_XGMII_WS] = "XGMII_WS", - [LOOPBACK_XAUI_WS] = "XAUI_WS", + [LOOPBACK_XAUI_WS] = "XAUI_WS", [LOOPBACK_XAUI_WS_FAR] = "XAUI_WS_FAR", [LOOPBACK_XAUI_WS_NEAR] = "XAUI_WS_NEAR", - [LOOPBACK_GMII_WS] = "GMII_WS", + [LOOPBACK_GMII_WS] = "GMII_WS", [LOOPBACK_XFI_WS] = "XFI_WS", [LOOPBACK_XFI_WS_FAR] = "XFI_WS_FAR", - [LOOPBACK_PHYXS_WS] = "PHYXS_WS", + [LOOPBACK_PHYXS_WS] = "PHYXS_WS", }; const unsigned int efx_reset_type_max = RESET_TYPE_MAX; diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index 29b2ebfef19f..c090de4e66c3 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -68,11 +68,11 @@ static u64 efx_get_atomic_stat(void *field) } #define EFX_ETHTOOL_ULONG_MAC_STAT(field) \ - EFX_ETHTOOL_STAT(field, mac_stats, field, \ + EFX_ETHTOOL_STAT(field, mac_stats, field, \ unsigned long, efx_get_ulong_stat) #define EFX_ETHTOOL_U64_MAC_STAT(field) \ - EFX_ETHTOOL_STAT(field, mac_stats, field, \ + EFX_ETHTOOL_STAT(field, mac_stats, field, \ u64, efx_get_u64_stat) #define EFX_ETHTOOL_UINT_NIC_STAT(name) \ diff --git a/drivers/net/ethernet/sfc/falcon_xmac.c b/drivers/net/ethernet/sfc/falcon_xmac.c index 9516452c079c..57434593f07b 100644 --- a/drivers/net/ethernet/sfc/falcon_xmac.c +++ b/drivers/net/ethernet/sfc/falcon_xmac.c @@ -139,7 +139,7 @@ static bool falcon_xmac_link_ok(struct efx_nic *efx) return (efx->loopback_mode == LOOPBACK_XGMII || falcon_xgxs_link_ok(efx)) && (!(efx->mdio.mmds & (1 << MDIO_MMD_PHYXS)) || - LOOPBACK_INTERNAL(efx) || + LOOPBACK_INTERNAL(efx) || efx_mdio_phyxgxs_lane_sync(efx)); } diff --git a/drivers/net/ethernet/sfc/mcdi_mac.c b/drivers/net/ethernet/sfc/mcdi_mac.c index 50c20777a564..aa4052c500fa 100644 --- a/drivers/net/ethernet/sfc/mcdi_mac.c +++ b/drivers/net/ethernet/sfc/mcdi_mac.c @@ -141,5 +141,5 @@ static bool efx_mcdi_mac_check_fault(struct efx_nic *efx) const struct efx_mac_operations efx_mcdi_mac_operations = { .reconfigure = efx_mcdi_mac_reconfigure, .update_stats = efx_port_dummy_op_void, - .check_fault = efx_mcdi_mac_check_fault, + .check_fault = efx_mcdi_mac_check_fault, }; diff --git a/drivers/net/ethernet/sfc/mcdi_phy.c b/drivers/net/ethernet/sfc/mcdi_phy.c index 6c63ab0710af..3077bf1e7dfe 100644 --- a/drivers/net/ethernet/sfc/mcdi_phy.c +++ b/drivers/net/ethernet/sfc/mcdi_phy.c @@ -741,7 +741,7 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, const struct efx_phy_operations efx_mcdi_phy_ops = { .probe = efx_mcdi_phy_probe, - .init = efx_port_dummy_op_int, + .init = efx_port_dummy_op_int, .reconfigure = efx_mcdi_phy_reconfigure, .poll = efx_mcdi_phy_poll, .fini = efx_port_dummy_op_void, diff --git a/drivers/net/ethernet/sfc/mdio_10g.c b/drivers/net/ethernet/sfc/mdio_10g.c index 7ab385c8136d..9acfd6696ffb 100644 --- a/drivers/net/ethernet/sfc/mdio_10g.c +++ b/drivers/net/ethernet/sfc/mdio_10g.c @@ -228,7 +228,7 @@ void efx_mdio_set_mmds_lpower(struct efx_nic *efx, /** * efx_mdio_set_settings - Set (some of) the PHY settings over MDIO. * @efx: Efx NIC - * @ecmd: New settings + * @ecmd: New settings */ int efx_mdio_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd) { diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 3edfbaf5f022..b1df2f39c8f0 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -1837,7 +1837,7 @@ struct efx_nic_reg_table { REGISTER_REVISION_ ## min_rev, REGISTER_REVISION_ ## max_rev, \ step, rows \ } -#define REGISTER_TABLE(name, min_rev, max_rev) \ +#define REGISTER_TABLE(name, min_rev, max_rev) \ REGISTER_TABLE_DIMENSIONS( \ name, FR_ ## min_rev ## max_rev ## _ ## name, \ min_rev, max_rev, \ diff --git a/drivers/net/ethernet/sfc/qt202x_phy.c b/drivers/net/ethernet/sfc/qt202x_phy.c index 7ad97e397406..8a7caf88ffb6 100644 --- a/drivers/net/ethernet/sfc/qt202x_phy.c +++ b/drivers/net/ethernet/sfc/qt202x_phy.c @@ -47,7 +47,7 @@ #define PMA_PMD_FTX_STATIC_LBN 13 #define PMA_PMD_VEND1_REG 0xc001 #define PMA_PMD_VEND1_LBTXD_LBN 15 -#define PCS_VEND1_REG 0xc000 +#define PCS_VEND1_REG 0xc000 #define PCS_VEND1_LBTXD_LBN 5 void falcon_qt202x_set_led(struct efx_nic *p, int led, int mode) @@ -453,9 +453,9 @@ const struct efx_phy_operations falcon_qt202x_phy_ops = { .probe = qt202x_phy_probe, .init = qt202x_phy_init, .reconfigure = qt202x_phy_reconfigure, - .poll = qt202x_phy_poll, + .poll = qt202x_phy_poll, .fini = efx_port_dummy_op_void, - .remove = qt202x_phy_remove, + .remove = qt202x_phy_remove, .get_settings = qt202x_phy_get_settings, .set_settings = efx_mdio_set_settings, .test_alive = efx_mdio_test_alive, diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 52edd24fcde3..fc62fe2f766f 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -445,7 +445,7 @@ static int efx_end_loopback(struct efx_tx_queue *tx_queue, /* Count the number of tx completions, and decrement the refcnt. Any * skbs not already completed will be free'd when the queue is flushed */ - for (i=0; i < state->packet_count; i++) { + for (i = 0; i < state->packet_count; i++) { skb = state->skbs[i]; if (skb && !skb_shared(skb)) ++tx_done; diff --git a/drivers/net/ethernet/sfc/spi.h b/drivers/net/ethernet/sfc/spi.h index 71f2e3ebe1c7..5431a1bbff5c 100644 --- a/drivers/net/ethernet/sfc/spi.h +++ b/drivers/net/ethernet/sfc/spi.h @@ -68,7 +68,7 @@ static inline bool efx_spi_present(const struct efx_spi_device *spi) int falcon_spi_cmd(struct efx_nic *efx, const struct efx_spi_device *spi, unsigned int command, - int address, const void* in, void *out, size_t len); + int address, const void *in, void *out, size_t len); int falcon_spi_wait_write(struct efx_nic *efx, const struct efx_spi_device *spi); int falcon_spi_read(struct efx_nic *efx, diff --git a/drivers/net/ethernet/sfc/tenxpress.c b/drivers/net/ethernet/sfc/tenxpress.c index 7b0fd89e7b85..d37cb5017129 100644 --- a/drivers/net/ethernet/sfc/tenxpress.c +++ b/drivers/net/ethernet/sfc/tenxpress.c @@ -121,7 +121,7 @@ #define GPHY_XCONTROL_REG 49152 #define GPHY_ISOLATE_LBN 10 #define GPHY_ISOLATE_WIDTH 1 -#define GPHY_DUPLEX_LBN 8 +#define GPHY_DUPLEX_LBN 8 #define GPHY_DUPLEX_WIDTH 1 #define GPHY_LOOPBACK_NEAR_LBN 14 #define GPHY_LOOPBACK_NEAR_WIDTH 1 -- GitLab From e9e01846c7e18a3b5682b54e50f1005949737bd9 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Jan 2012 18:50:29 +0000 Subject: [PATCH 00052/10698] sfc: Avoid assignment in an if-statement, reported by checkpatch Fix the following error: ERROR: do not use assignment in if condition Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 11cc585c36a4..0539a8d88a23 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1069,9 +1069,11 @@ static int efx_init_io(struct efx_nic *efx) * masks event though they reject 46 bit masks. */ while (dma_mask > 0x7fffffffUL) { - if (pci_dma_supported(pci_dev, dma_mask) && - ((rc = pci_set_dma_mask(pci_dev, dma_mask)) == 0)) - break; + if (pci_dma_supported(pci_dev, dma_mask)) { + rc = pci_set_dma_mask(pci_dev, dma_mask); + if (rc == 0) + break; + } dma_mask >>= 1; } if (rc) { -- GitLab From 0beaca2ca0b3c12dabab046f1541b09179ec449c Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Jan 2012 18:54:04 +0000 Subject: [PATCH 00053/10698] sfc: Remove parentheses around return expressions, reported by checkpatch Fix the following error: ERROR: return is not a function, parentheses are not required Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/rx.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index aca349861767..3572c34a79fb 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -98,8 +98,8 @@ static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx, /* Offset is always within one page, so we don't need to consider * the page order. */ - return (((__force unsigned long) buf->dma_addr & (PAGE_SIZE - 1)) + - efx->type->rx_buffer_hash_size); + return ((__force unsigned long) buf->dma_addr & (PAGE_SIZE - 1)) + + efx->type->rx_buffer_hash_size; } static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) { @@ -111,8 +111,7 @@ static u8 *efx_rx_buf_eh(struct efx_nic *efx, struct efx_rx_buffer *buf) if (buf->is_page) return page_address(buf->u.page) + efx_rx_buf_offset(efx, buf); else - return ((u8 *)buf->u.skb->data + - efx->type->rx_buffer_hash_size); + return (u8 *)buf->u.skb->data + efx->type->rx_buffer_hash_size; } static inline u32 efx_rx_buf_hash(const u8 *eh) @@ -122,10 +121,10 @@ static inline u32 efx_rx_buf_hash(const u8 *eh) return __le32_to_cpup((const __le32 *)(eh - 4)); #else const u8 *data = eh - 4; - return ((u32)data[0] | - (u32)data[1] << 8 | - (u32)data[2] << 16 | - (u32)data[3] << 24); + return (u32)data[0] | + (u32)data[1] << 8 | + (u32)data[2] << 16 | + (u32)data[3] << 24; #endif } -- GitLab From 426932909093e4e7729777a0e2beed4b54911361 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Thu, 5 Jan 2012 16:12:25 +0000 Subject: [PATCH 00054/10698] x86-64: Slightly shorten copy_page() %r13 got saved and restored without ever getting touched, so there's no need to do so. Signed-off-by: Jan Beulich Cc: Linus Torvalds Cc: Andrew Morton Link: http://lkml.kernel.org/r/4F05D9F9020000780006AA0D@nat28.tlf.novell.com Signed-off-by: Ingo Molnar --- arch/x86/lib/copy_page_64.S | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/arch/x86/lib/copy_page_64.S b/arch/x86/lib/copy_page_64.S index 01c805ba5359..6b34d04d096a 100644 --- a/arch/x86/lib/copy_page_64.S +++ b/arch/x86/lib/copy_page_64.S @@ -20,14 +20,12 @@ ENDPROC(copy_page_c) ENTRY(copy_page) CFI_STARTPROC - subq $3*8,%rsp - CFI_ADJUST_CFA_OFFSET 3*8 + subq $2*8,%rsp + CFI_ADJUST_CFA_OFFSET 2*8 movq %rbx,(%rsp) CFI_REL_OFFSET rbx, 0 movq %r12,1*8(%rsp) CFI_REL_OFFSET r12, 1*8 - movq %r13,2*8(%rsp) - CFI_REL_OFFSET r13, 2*8 movl $(4096/64)-5,%ecx .p2align 4 @@ -91,10 +89,8 @@ ENTRY(copy_page) CFI_RESTORE rbx movq 1*8(%rsp),%r12 CFI_RESTORE r12 - movq 2*8(%rsp),%r13 - CFI_RESTORE r13 - addq $3*8,%rsp - CFI_ADJUST_CFA_OFFSET -3*8 + addq $2*8,%rsp + CFI_ADJUST_CFA_OFFSET -2*8 ret .Lcopy_page_end: CFI_ENDPROC -- GitLab From 64eeacb7f0317e5f3d6f0f63399ed00b4b2b7dc0 Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 16 Dec 2011 09:31:14 -0800 Subject: [PATCH 00055/10698] iwlwifi: don't process the info from uCode if does not has ownership When enable the testmode from user space and working with uCode, driver does not own the uCode and should not process the notifications or pkts from uCode Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 28 ++++++++++++----------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index b22b2976f899..eda95ae88ef1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1172,20 +1172,22 @@ int iwl_rx_dispatch(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, wake_up_all(&priv->shrd->notif_waitq); } - if (priv->pre_rx_handler) + if (priv->pre_rx_handler && + priv->shrd->ucode_owner == IWL_OWNERSHIP_TM) priv->pre_rx_handler(priv, rxb); - - /* Based on type of command response or notification, - * handle those that need handling via function in - * rx_handlers table. See iwl_setup_rx_handlers() */ - if (priv->rx_handlers[pkt->hdr.cmd]) { - priv->rx_handlers_stats[pkt->hdr.cmd]++; - err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); - } else { - /* No handling needed */ - IWL_DEBUG_RX(priv, - "No handler needed for %s, 0x%02x\n", - get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); + else { + /* Based on type of command response or notification, + * handle those that need handling via function in + * rx_handlers table. See iwl_setup_rx_handlers() */ + if (priv->rx_handlers[pkt->hdr.cmd]) { + priv->rx_handlers_stats[pkt->hdr.cmd]++; + err = priv->rx_handlers[pkt->hdr.cmd] (priv, rxb, cmd); + } else { + /* No handling needed */ + IWL_DEBUG_RX(priv, + "No handler needed for %s, 0x%02x\n", + get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); + } } return err; } -- GitLab From d75140120971964dca1eee9aa5c9ab25bf0f664f Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Fri, 16 Dec 2011 07:31:35 -0800 Subject: [PATCH 00056/10698] iwlwifi: Sanity check for sta_id On my testing, I saw some strange behavior [ 421.739708] iwlwifi 0000:01:00.0: ACTIVATE a non DRIVER active station id 148 addr 00:00:00:00:00:00 [ 421.739719] iwlwifi 0000:01:00.0: iwl_sta_ucode_activate Added STA id 148 addr 00:00:00:00:00:00 to uCode not sure how it happen, but adding the sanity check to prevent memory corruption Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 7353826095f1..8d4353a42568 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -35,9 +35,12 @@ #include "iwl-trans.h" /* priv->shrd->sta_lock must be held */ -static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) +static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { - + if (sta_id >= IWLAGN_STATION_COUNT) { + IWL_ERR(priv, "invalid sta_id %u", sta_id); + return -EINVAL; + } if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) IWL_ERR(priv, "ACTIVATE a non DRIVER active station id %u " "addr %pM\n", @@ -53,6 +56,7 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n", sta_id, priv->stations[sta_id].sta.sta.addr); } + return 0; } static int iwl_process_add_sta_resp(struct iwl_priv *priv, @@ -77,8 +81,7 @@ static int iwl_process_add_sta_resp(struct iwl_priv *priv, switch (pkt->u.add_sta.status) { case ADD_STA_SUCCESS_MSK: IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); - iwl_sta_ucode_activate(priv, sta_id); - ret = 0; + ret = iwl_sta_ucode_activate(priv, sta_id); break; case ADD_STA_NO_ROOM_IN_TABLE: IWL_ERR(priv, "Adding station %d failed, no room in table.\n", -- GitLab From c381be2853bbe4bc1bd6fee88f0a33041de65d06 Mon Sep 17 00:00:00 2001 From: Kenny Hsu Date: Fri, 23 Dec 2011 14:50:48 +0800 Subject: [PATCH 00057/10698] iwlwifi: update testmode command of direct register access In order to make sure the testcommand function of direct register access can be performed even NIC is asleep, replace corresponding handler iwl_read32 and iwl_write32 by using iwl_direct_read32 and iwl_direct_write32. Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 4a5cddd2d56b..2fc20675dc7b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -299,7 +299,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_DIRECT_REG_READ32: - val32 = iwl_read32(bus(priv), ofs); + val32 = iwl_read_direct32(bus(priv), ofs); IWL_INFO(priv, "32bit value to read 0x%x\n", val32); skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); @@ -321,7 +321,7 @@ static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) } else { val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); IWL_INFO(priv, "32bit value to write 0x%x\n", val32); - iwl_write32(bus(priv), ofs, val32); + iwl_write_direct32(bus(priv), ofs, val32); } break; case IWL_TM_CMD_APP2DEV_DIRECT_REG_WRITE8: -- GitLab From 25324caf6e3fc8134444af74fc85182862d520cc Mon Sep 17 00:00:00 2001 From: Kenny Hsu Date: Tue, 27 Dec 2011 08:18:31 -0800 Subject: [PATCH 00058/10698] iwlwifi: enhance testmode command sram_read This patch enables SRAM read function to support entire target memory. Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 7 +++---- drivers/net/wireless/iwlwifi/iwl-testmode.h | 3 +++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 2fc20675dc7b..58575fdc4504 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -733,7 +733,7 @@ static int iwl_testmode_ownership(struct ieee80211_hw *hw, struct nlattr **tb) static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) { struct iwl_priv *priv = hw->priv; - u32 base, ofs, size, maxsize; + u32 ofs, size, maxsize; if (priv->testmode_sram.sram_readed) return -EBUSY; @@ -765,7 +765,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n"); return -ENOSYS; } - if ((ofs + size) > maxsize) { + if ((ofs + size) > (maxsize + SRAM_DATA_SEG_OFFSET)) { IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n"); return -EINVAL; } @@ -776,8 +776,7 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) IWL_DEBUG_INFO(priv, "Error allocating memory\n"); return -ENOMEM; } - base = 0x800000; - _iwl_read_targ_mem_words(bus(priv), base + ofs, + _iwl_read_targ_mem_words(bus(priv), ofs, priv->testmode_sram.buff_addr, priv->testmode_sram.buff_size / 4); priv->testmode_sram.num_chunks = diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 26138f110340..9c6a67ab5c34 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -271,4 +271,7 @@ enum iwl_tm_attr_t { /* Maximum data size of each dump it packet */ #define DUMP_CHUNK_SIZE (PAGE_SIZE - 1024) +/* Address offset of data segment in SRAM */ +#define SRAM_DATA_SEG_OFFSET 0x800000 + #endif -- GitLab From 22b48087ea4df1841c2507173c98e6b4f26fe64d Mon Sep 17 00:00:00 2001 From: Kenny Hsu Date: Tue, 27 Dec 2011 08:27:52 -0800 Subject: [PATCH 00059/10698] iwlwifi: update error dump in testmode command sram_read The error message will be show up by using IWL_ERR insteads of IWl_DEBUG_INFO. Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 58575fdc4504..b56cd900805c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -759,21 +759,21 @@ static int iwl_testmode_sram(struct ieee80211_hw *hw, struct nlattr **tb) maxsize = trans(priv)->ucode_wowlan.data.len; break; case IWL_UCODE_NONE: - IWL_DEBUG_INFO(priv, "Error, uCode does not been loaded\n"); + IWL_ERR(priv, "Error, uCode does not been loaded\n"); return -ENOSYS; default: - IWL_DEBUG_INFO(priv, "Error, unsupported uCode type\n"); + IWL_ERR(priv, "Error, unsupported uCode type\n"); return -ENOSYS; } if ((ofs + size) > (maxsize + SRAM_DATA_SEG_OFFSET)) { - IWL_DEBUG_INFO(priv, "Invalid offset/size: out of range\n"); + IWL_ERR(priv, "Invalid offset/size: out of range\n"); return -EINVAL; } priv->testmode_sram.buff_size = (size / 4) * 4; priv->testmode_sram.buff_addr = kmalloc(priv->testmode_sram.buff_size, GFP_KERNEL); if (priv->testmode_sram.buff_addr == NULL) { - IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + IWL_ERR(priv, "Error allocating memory\n"); return -ENOMEM; } _iwl_read_targ_mem_words(bus(priv), ofs, -- GitLab From aca9b5f34352248a23c4d776afebf171e711090b Mon Sep 17 00:00:00 2001 From: Kenny Hsu Date: Sat, 24 Dec 2011 12:12:12 +0800 Subject: [PATCH 00060/10698] iwlwifi: add testmode cmd IWL_TM_CMD_APP2DEV_GET_FW_INFO Add new testmode command IWL_TM_CMD_APP2DEV_GET_FW_INFO for reporting the following information of existing loaded uCode image. + uCode type + Instruction section size + Data section size Signed-off-by: Kenny Hsu Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-testmode.c | 41 ++++++++++++++++++++- drivers/net/wireless/iwlwifi/iwl-testmode.h | 19 +++++++++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index b56cd900805c..7684c0e2f21a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -115,6 +115,9 @@ struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { [IWL_TM_ATTR_FW_VERSION] = { .type = NLA_U32, }, [IWL_TM_ATTR_DEVICE_ID] = { .type = NLA_U32, }, + [IWL_TM_ATTR_FW_TYPE] = { .type = NLA_U32, }, + [IWL_TM_ATTR_FW_INST_SIZE] = { .type = NLA_U32, }, + [IWL_TM_ATTR_FW_DATA_SIZE] = { .type = NLA_U32, }, }; /* @@ -422,7 +425,7 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) struct sk_buff *skb; unsigned char *rsp_data_ptr = NULL; int status = 0, rsp_data_len = 0; - u32 devid; + u32 devid, inst_size = 0, data_size = 0; switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: @@ -548,6 +551,41 @@ static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) "Error sending msg : %d\n", status); break; + case IWL_TM_CMD_APP2DEV_GET_FW_INFO: + skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20 + 8); + if (!skb) { + IWL_DEBUG_INFO(priv, "Error allocating memory\n"); + return -ENOMEM; + } + switch (priv->shrd->ucode_type) { + case IWL_UCODE_REGULAR: + inst_size = trans(priv)->ucode_rt.code.len; + data_size = trans(priv)->ucode_rt.data.len; + break; + case IWL_UCODE_INIT: + inst_size = trans(priv)->ucode_init.code.len; + data_size = trans(priv)->ucode_init.data.len; + break; + case IWL_UCODE_WOWLAN: + inst_size = trans(priv)->ucode_wowlan.code.len; + data_size = trans(priv)->ucode_wowlan.data.len; + break; + case IWL_UCODE_NONE: + IWL_DEBUG_INFO(priv, "The uCode has not been loaded\n"); + break; + default: + IWL_DEBUG_INFO(priv, "Unsupported uCode type\n"); + break; + } + NLA_PUT_U32(skb, IWL_TM_ATTR_FW_TYPE, priv->shrd->ucode_type); + NLA_PUT_U32(skb, IWL_TM_ATTR_FW_INST_SIZE, inst_size); + NLA_PUT_U32(skb, IWL_TM_ATTR_FW_DATA_SIZE, data_size); + status = cfg80211_testmode_reply(skb); + if (status < 0) + IWL_DEBUG_INFO(priv, + "Error sending msg : %d\n", status); + break; + default: IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); return -ENOSYS; @@ -881,6 +919,7 @@ int iwlagn_mac_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) case IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: case IWL_TM_CMD_APP2DEV_GET_FW_VERSION: case IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: + case IWL_TM_CMD_APP2DEV_GET_FW_INFO: IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); result = iwl_testmode_driver(hw, tb); break; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index 9c6a67ab5c34..cb0cf35f91b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -120,6 +120,8 @@ * @IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW: load Weak On Wireless LAN uCode image * @IWL_TM_CMD_APP2DEV_GET_FW_VERSION: retrieve uCode version * @IWL_TM_CMD_APP2DEV_GET_DEVICE_ID: retrieve ID information in device + * @IWL_TM_CMD_APP2DEV_GET_FW_INFO: + * retrieve informration of existing loaded uCode image * */ enum iwl_tm_cmd_t { @@ -147,7 +149,8 @@ enum iwl_tm_cmd_t { IWL_TM_CMD_APP2DEV_LOAD_WOWLAN_FW = 22, IWL_TM_CMD_APP2DEV_GET_FW_VERSION = 23, IWL_TM_CMD_APP2DEV_GET_DEVICE_ID = 24, - IWL_TM_CMD_MAX = 25, + IWL_TM_CMD_APP2DEV_GET_FW_INFO = 25, + IWL_TM_CMD_MAX = 26, }; /* @@ -237,6 +240,15 @@ enum iwl_tm_cmd_t { * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_DEVICE_ID, * IWL_TM_ATTR_DEVICE_ID for the device ID information * + * @IWL_TM_ATTR_FW_TYPE: + * @IWL_TM_ATTR_FW_INST_SIZE: + * @IWL_TM_ATTR_FW_DATA_SIZE: + * When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_GET_FW_INFO, + * The mandatory fields are: + * IWL_TM_ATTR_FW_TYPE for the uCode type (INIT/RUNTIME/...) + * IWL_TM_ATTR_FW_INST_SIZE for the size of instruction section + * IWL_TM_ATTR_FW_DATA_SIZE for the size of data section + * */ enum iwl_tm_attr_t { IWL_TM_ATTR_NOT_APPLICABLE = 0, @@ -259,7 +271,10 @@ enum iwl_tm_attr_t { IWL_TM_ATTR_SRAM_DUMP = 17, IWL_TM_ATTR_FW_VERSION = 18, IWL_TM_ATTR_DEVICE_ID = 19, - IWL_TM_ATTR_MAX = 20, + IWL_TM_ATTR_FW_TYPE = 20, + IWL_TM_ATTR_FW_INST_SIZE = 21, + IWL_TM_ATTR_FW_DATA_SIZE = 22, + IWL_TM_ATTR_MAX = 23, }; /* uCode trace buffer */ -- GitLab From 4e3182626a914443a5e0fbe014813f03e51a75df Mon Sep 17 00:00:00 2001 From: Wey-Yi Guy Date: Tue, 27 Dec 2011 11:21:32 -0800 Subject: [PATCH 00061/10698] iwlwifi: update Copyright Update Copyright to 2012 Signed-off-by: Wey-Yi Guy --- drivers/net/wireless/iwlwifi/iwl-1000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-2000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-5000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-calib.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-calib.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-hw.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tt.h | 2 +- drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.c | 2 +- drivers/net/wireless/iwlwifi/iwl-agn.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-bus.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-cfg.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-commands.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-core.c | 2 +- drivers/net/wireless/iwlwifi/iwl-core.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-csr.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-debug.h | 2 +- drivers/net/wireless/iwlwifi/iwl-debugfs.c | 2 +- drivers/net/wireless/iwlwifi/iwl-dev.h | 2 +- drivers/net/wireless/iwlwifi/iwl-devtrace.c | 2 +- drivers/net/wireless/iwlwifi/iwl-devtrace.h | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-eeprom.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-fh.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-io.c | 2 +- drivers/net/wireless/iwlwifi/iwl-io.h | 2 +- drivers/net/wireless/iwlwifi/iwl-led.c | 2 +- drivers/net/wireless/iwlwifi/iwl-led.h | 2 +- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 2 +- drivers/net/wireless/iwlwifi/iwl-pci.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-power.c | 2 +- drivers/net/wireless/iwlwifi/iwl-power.h | 2 +- drivers/net/wireless/iwlwifi/iwl-prph.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-scan.c | 2 +- drivers/net/wireless/iwlwifi/iwl-shared.h | 6 +++--- drivers/net/wireless/iwlwifi/iwl-testmode.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-testmode.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 2 +- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-trans.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-trans.h | 4 ++-- drivers/net/wireless/iwlwifi/iwl-ucode.c | 2 +- drivers/net/wireless/iwlwifi/iwl-wifi.h | 4 ++-- 53 files changed, 75 insertions(+), 75 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 1ef7bfc2ab25..cc04cce11567 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 094693328dbb..00db092d8cd0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index b3a365fea7bb..47fd98b3652c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 54b753399e6e..ab62c018fcdb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c index 50ff849c9f67..6aa009827865 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h index 10275ce92bde..9ed6683314a7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h index 123ef5e129d5..d0ec0abd3c89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 64cf439035c3..a8f7689aaacf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 334b5ae8fdd4..b9ba404d15c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h index 6675b3c816d9..203b1c13c491 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c index eda95ae88ef1..f127f913e5a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portionhelp of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 1c6659416621..8ca9570ec365 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index 8d4353a42568..d6aab00272b9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c index b0dff7a753a5..56c6def015a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h index 7282a23e8f1c..86bbf47501c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c664c2726553..a8c6880af34b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index b5c7c5f0a753..7321e7d31406 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index f84fb3c53563..39cbe1a1577c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-bus.h b/drivers/net/wireless/iwlwifi/iwl-bus.h index 940d5038b39c..941b9cb23442 100644 --- a/drivers/net/wireless/iwlwifi/iwl-bus.h +++ b/drivers/net/wireless/iwlwifi/iwl-bus.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-cfg.h b/drivers/net/wireless/iwlwifi/iwl-cfg.h index e1d78257e4a9..957bc00cdaf0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-cfg.h +++ b/drivers/net/wireless/iwlwifi/iwl-cfg.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 265de39d394c..b4779c25a4b3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 7bcfa781e0b9..7d6eef96454a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 7bf76ab94dd2..63f29111da13 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index fbc3095c7b44..5f96ce105f08 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index f8fc2393dd4c..6f7612781e03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 04a3343f4610..f837f32bb71c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index e54a4d11e584..4579d61da25e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 2a2c8de64a04..91f45e71e0a2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2009 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 9b212a8f30bb..4d892211ce4c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2009 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index c1eda9724f42..e27d9f55267b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 9fa937ec35e3..13f2d3928ef8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h index 5bede9d7f955..90208094b8eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/iwlwifi/iwl-fh.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index d57ea6484bbe..83fdff381150 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index aae2eeb331a8..427d065435c8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project. * diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 14dcbfcdc0fd..eca79087afb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h index 2550b3c7dcbf..b02a853103d3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ b/drivers/net/wireless/iwlwifi/iwl-led.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index f980e574e1f9..965d0475affd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-pci.c b/drivers/net/wireless/iwlwifi/iwl-pci.c index fb30ea7ca96b..03702a2e913a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-pci.c +++ b/drivers/net/wireless/iwlwifi/iwl-pci.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 2b188a6025b3..c7394ef2e490 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 5f7b720cf1a4..07a19fce5fdc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index bebdd828f324..a4d11016c3b4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 084aa2c4ccfb..2cd5b4f59931 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h index dc55cc4a8108..e406d49f4189 100644 --- a/drivers/net/wireless/iwlwifi/iwl-shared.h +++ b/drivers/net/wireless/iwlwifi/iwl-shared.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -102,7 +102,7 @@ struct iwl_trans_ops; #define DRV_NAME "iwlwifi" #define IWLWIFI_VERSION "in-tree:" -#define DRV_COPYRIGHT "Copyright(c) 2003-2011 Intel Corporation" +#define DRV_COPYRIGHT "Copyright(c) 2003-2012 Intel Corporation" #define DRV_AUTHOR "" extern struct iwl_mod_params iwlagn_mod_params; diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.c b/drivers/net/wireless/iwlwifi/iwl-testmode.c index 7684c0e2f21a..a56a77b8f926 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.c +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h index cb0cf35f91b5..185b69ef7539 100644 --- a/drivers/net/wireless/iwlwifi/iwl-testmode.h +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2010 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index f6debf91d7b5..0ac9b4d30271 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c index 752493f00406..848c598bfadb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index bd29568177e6..30814b55705e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2012 Intel Corporation. All rights reserved. * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 67d6e324e26f..5e6af4ba9652 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c index 1b20c4fb791b..506c062343b2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index e6bf3f554772..42a9f303f543 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/net/wireless/iwlwifi/iwl-ucode.c b/drivers/net/wireless/iwlwifi/iwl-ucode.c index 36a1b5b25858..2edf0ef65a5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-ucode.c @@ -2,7 +2,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as diff --git a/drivers/net/wireless/iwlwifi/iwl-wifi.h b/drivers/net/wireless/iwlwifi/iwl-wifi.h index 18501101a530..7e6eb20823cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-wifi.h +++ b/drivers/net/wireless/iwlwifi/iwl-wifi.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -30,7 +30,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2012 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without -- GitLab From 3f3c4ee735ff0957a53b9dccae66c8e5ead25b17 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 14:41:59 +0530 Subject: [PATCH 00062/10698] ath6kl: Add a function in wmi to send WMI_MCAST_FILTER_CMDID This will be used to disable/enable multicast receive. Signed-off-by: Vasanthakumar Thiagarajan --- drivers/net/wireless/ath/ath6kl/wmi.c | 17 +++++++++++++++++ drivers/net/wireless/ath/ath6kl/wmi.h | 5 +++++ 2 files changed, 22 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index c6ca660d270a..d3eec0761eaa 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2855,6 +2855,23 @@ int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len) return ret; } +int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on) +{ + struct sk_buff *skb; + struct wmi_mcast_filter_cmd *cmd; + int ret; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_mcast_filter_cmd *) skb->data; + cmd->mcast_all_enable = mc_all_on; + + ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG); + return ret; +} s32 ath6kl_wmi_get_rate(s8 rate_index) { diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index 2b435994b013..dc7045711551 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -1239,6 +1239,10 @@ enum target_event_report_config { NO_DISCONN_EVT_IN_RECONN }; +struct wmi_mcast_filter_cmd { + u8 mcast_all_enable; +} __packed; + /* Command Replies */ /* WMI_GET_CHANNEL_LIST_CMDID reply */ @@ -2434,6 +2438,7 @@ int ath6kl_wmi_del_wow_pattern_cmd(struct wmi *wmi, u8 if_idx, int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); +int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); /* AP mode */ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, -- GitLab From f914edd38920369d8926261f9ab72da6756c3e0c Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 14:42:00 +0530 Subject: [PATCH 00063/10698] ath6kl: Add a function in wmi.c to add/delete a multicast filter Signed-off-by: Vasanthakumar Thiagarajan --- drivers/net/wireless/ath/ath6kl/wmi.c | 28 +++++++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/wmi.h | 7 +++++++ 2 files changed, 35 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index d3eec0761eaa..08fbd9a9be4b 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -2873,6 +2873,34 @@ int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on) return ret; } +int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, + u8 *filter, bool add_filter) +{ + struct sk_buff *skb; + struct wmi_mcast_filter_add_del_cmd *cmd; + int ret; + + if ((filter[0] != 0x33 || filter[1] != 0x33) && + (filter[0] != 0x01 || filter[1] != 0x00 || + filter[2] != 0x5e || filter[3] > 0x7f)) { + ath6kl_warn("invalid multicast filter address\n"); + return -EINVAL; + } + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_mcast_filter_add_del_cmd *) skb->data; + memcpy(cmd->mcast_mac, filter, ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE); + ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb, + add_filter ? WMI_SET_MCAST_FILTER_CMDID : + WMI_DEL_MCAST_FILTER_CMDID, + NO_SYNC_WMIFLAG); + + return ret; +} + s32 ath6kl_wmi_get_rate(s8 rate_index) { if (rate_index == RATE_AUTO) diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index dc7045711551..eae0e4e065c4 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -1243,6 +1243,11 @@ struct wmi_mcast_filter_cmd { u8 mcast_all_enable; } __packed; +#define ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE 6 +struct wmi_mcast_filter_add_del_cmd { + u8 mcast_mac[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; +} __packed; + /* Command Replies */ /* WMI_GET_CHANNEL_LIST_CMDID reply */ @@ -2439,6 +2444,8 @@ int ath6kl_wmi_set_roam_lrssi_cmd(struct wmi *wmi, u8 lrssi); int ath6kl_wmi_force_roam_cmd(struct wmi *wmi, const u8 *bssid); int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); +int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, + u8 *filter, bool add_filter); /* AP mode */ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, -- GitLab From 80abaf9b4c920cab044e185ed4327f801c1ff99d Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 14:42:01 +0530 Subject: [PATCH 00064/10698] ath6kl: Implement ndo_set_rx_mode() There are maximum of seven multicast filter are supported by hw. When the requested number of filters exceeds the maximum supported one, multicast filtering is completely disabled, the requested filters will be configured in firmware and the only multicast frames that host is interested in will be passed to host for further processing otherwise. Signed-off-by: Vasanthakumar Thiagarajan --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 8 ++ drivers/net/wireless/ath/ath6kl/core.h | 9 ++ drivers/net/wireless/ath/ath6kl/main.c | 110 +++++++++++++++++++++ 3 files changed, 127 insertions(+) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 2a166cc7cc3c..14f180eac485 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2818,12 +2818,15 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif) set_bit(WMM_ENABLED, &vif->flags); spin_lock_init(&vif->if_lock); + INIT_LIST_HEAD(&vif->mc_filter); + return 0; } void ath6kl_deinit_if_data(struct ath6kl_vif *vif) { struct ath6kl *ar = vif->ar; + struct ath6kl_mc_filter *mc_filter, *tmp; aggr_module_destroy(vif->aggr_cntxt); @@ -2832,6 +2835,11 @@ void ath6kl_deinit_if_data(struct ath6kl_vif *vif) if (vif->nw_type == ADHOC_NETWORK) ar->ibss_if_active = false; + list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { + list_del(&mc_filter->list); + kfree(mc_filter); + } + unregister_netdevice(vif->ndev); ar->num_vif--; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index c095fafa278f..793c6a58f0fd 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -410,6 +410,13 @@ enum ath6kl_hif_type { ATH6KL_HIF_TYPE_USB, }; +/* Max number of filters that hw supports */ +#define ATH6K_MAX_MC_FILTERS_PER_LIST 7 +struct ath6kl_mc_filter { + struct list_head list; + char hw_addr[ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE]; +}; + /* * Driver's maximum limit, note that some firmwares support only one vif * and the runtime (current) limit must be checked from ar->vif_max. @@ -473,6 +480,8 @@ struct ath6kl_vif { u8 assoc_bss_dtim_period; struct net_device_stats net_stats; struct target_stats target_stats; + + struct list_head mc_filter; }; #define WOW_LIST_ID 0 diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index f74986d62098..cffbc62ee793 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1052,12 +1052,122 @@ static int ath6kl_set_features(struct net_device *dev, u32 features) return err; } +static void ath6kl_set_multicast_list(struct net_device *ndev) +{ + struct ath6kl_vif *vif = netdev_priv(ndev); + bool mc_all_on = false, mc_all_off = false; + int mc_count = netdev_mc_count(ndev); + struct netdev_hw_addr *ha; + bool found; + struct ath6kl_mc_filter *mc_filter, *tmp; + struct list_head mc_filter_new; + int ret; + + if (!test_bit(WMI_READY, &vif->ar->flag) || + !test_bit(WLAN_ENABLED, &vif->flags)) + return; + + mc_all_on = !!(ndev->flags & IFF_PROMISC) || + !!(ndev->flags & IFF_ALLMULTI) || + !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); + + mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0; + + if (mc_all_on || mc_all_off) { + /* Enable/disable all multicast */ + ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n", + mc_all_on ? "enabling" : "disabling"); + ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, + mc_all_on); + if (ret) + ath6kl_warn("Failed to %s multicast receive\n", + mc_all_on ? "enable" : "disable"); + return; + } + + list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { + found = false; + netdev_for_each_mc_addr(ha, ndev) { + if (memcmp(ha->addr, mc_filter->hw_addr, + ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) { + found = true; + break; + } + } + + if (!found) { + /* + * Delete the filter which was previously set + * but not in the new request. + */ + ath6kl_dbg(ATH6KL_DBG_TRC, + "Removing %pM from multicast filter\n", + mc_filter->hw_addr); + ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi, + vif->fw_vif_idx, mc_filter->hw_addr, + false); + if (ret) { + ath6kl_warn("Failed to remove multicast filter:%pM\n", + mc_filter->hw_addr); + return; + } + + list_del(&mc_filter->list); + kfree(mc_filter); + } + } + + INIT_LIST_HEAD(&mc_filter_new); + + netdev_for_each_mc_addr(ha, ndev) { + found = false; + list_for_each_entry(mc_filter, &vif->mc_filter, list) { + if (memcmp(ha->addr, mc_filter->hw_addr, + ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE) == 0) { + found = true; + break; + } + } + + if (!found) { + mc_filter = kzalloc(sizeof(struct ath6kl_mc_filter), + GFP_ATOMIC); + if (!mc_filter) { + WARN_ON(1); + goto out; + } + + memcpy(mc_filter->hw_addr, ha->addr, + ATH6KL_MCAST_FILTER_MAC_ADDR_SIZE); + /* Set the multicast filter */ + ath6kl_dbg(ATH6KL_DBG_TRC, + "Adding %pM to multicast filter list\n", + mc_filter->hw_addr); + ret = ath6kl_wmi_add_del_mcast_filter_cmd(vif->ar->wmi, + vif->fw_vif_idx, mc_filter->hw_addr, + true); + if (ret) { + ath6kl_warn("Failed to add multicast filter :%pM\n", + mc_filter->hw_addr); + kfree(mc_filter); + goto out; + } + + list_add_tail(&mc_filter->list, &mc_filter_new); + } + } + +out: + list_splice_tail(&mc_filter_new, &vif->mc_filter); +} + static struct net_device_ops ath6kl_netdev_ops = { .ndo_open = ath6kl_open, .ndo_stop = ath6kl_close, .ndo_start_xmit = ath6kl_data_tx, .ndo_get_stats = ath6kl_get_stats, .ndo_set_features = ath6kl_set_features, + .ndo_set_rx_mode = ath6kl_set_multicast_list, }; void init_netdev(struct net_device *dev) -- GitLab From 3d6aba260bcd5a5f9d47056cac2e313ce986ad12 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 15:19:02 +0530 Subject: [PATCH 00065/10698] ath6kl: Remove deadcode in main.c In ath6kl_reset_device(), since control can never reach switch..case when the target_type is neither TARGET_TYPE_AR6003 nor TARGET_TYPE_AR6004, remove the default option of switch statement. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index cffbc62ee793..d764768f8f7a 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -347,9 +347,6 @@ void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, case TARGET_TYPE_AR6004: address = AR6004_RESET_CONTROL_ADDRESS; break; - default: - address = AR6003_RESET_CONTROL_ADDRESS; - break; } status = ath6kl_diag_write32(ar, address, data); -- GitLab From 982767b8c94482b4b7f694e2ab2074c95fbf3e0e Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Tue, 3 Jan 2012 15:28:53 +0530 Subject: [PATCH 00066/10698] ath6kl: Change ielen in ath6kl_add_new_sta() from u8 to size_t Otherwise if (ielen <= ATH6KL_MAX_IE) is dead code. It looks safe to change the type of ielen from u8 to size_t instead of removing this if check, this ielen can have the length of more than one ies in future. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index d764768f8f7a..325d316f40ec 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -53,7 +53,7 @@ struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid) } static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, - u8 ielen, u8 keymgmt, u8 ucipher, u8 auth) + size_t ielen, u8 keymgmt, u8 ucipher, u8 auth) { struct ath6kl_sta *sta; u8 free_slot; -- GitLab From 9d82682d45ef7407474e0ae043a587cb33a7fa26 Mon Sep 17 00:00:00 2001 From: Vasanthakumar Thiagarajan Date: Wed, 4 Jan 2012 15:57:19 +0530 Subject: [PATCH 00067/10698] ath6kl: Use a mutex_lock to avoid race in diabling and handling irq Currently this race is handled but in a messy way an atomic variable is being checked in a loop which sleeps upto ms in every iteration. Remove this logic and use a mutex to make sure irq is not disabled when irq handling is in progress. Signed-off-by: Vasanthakumar Thiagarajan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 278a9f30795a..8b36904ec3ec 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -49,11 +49,13 @@ struct ath6kl_sdio { /* scatter request list head */ struct list_head scat_req; + /* Avoids disabling irq while the interrupts being handled */ + struct mutex mtx_irq; + spinlock_t scat_lock; bool scatter_enabled; bool is_disabled; - atomic_t irq_handling; const struct sdio_device_id *id; struct work_struct wr_async_work; struct list_head wr_asyncq; @@ -460,8 +462,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) ath6kl_dbg(ATH6KL_DBG_SDIO, "irq\n"); ar_sdio = sdio_get_drvdata(func); - atomic_set(&ar_sdio->irq_handling, 1); - + mutex_lock(&ar_sdio->mtx_irq); /* * Release the host during interrups so we can pick it back up when * we process commands. @@ -470,7 +471,7 @@ static void ath6kl_sdio_irq_handler(struct sdio_func *func) status = ath6kl_hif_intr_bh_handler(ar_sdio->ar); sdio_claim_host(ar_sdio->func); - atomic_set(&ar_sdio->irq_handling, 0); + mutex_unlock(&ar_sdio->mtx_irq); WARN_ON(status && status != -ECANCELED); } @@ -578,17 +579,14 @@ static void ath6kl_sdio_irq_disable(struct ath6kl *ar) sdio_claim_host(ar_sdio->func); - /* Mask our function IRQ */ - while (atomic_read(&ar_sdio->irq_handling)) { - sdio_release_host(ar_sdio->func); - schedule_timeout(HZ / 10); - sdio_claim_host(ar_sdio->func); - } + mutex_lock(&ar_sdio->mtx_irq); ret = sdio_release_irq(ar_sdio->func); if (ret) ath6kl_err("Failed to release sdio irq: %d\n", ret); + mutex_unlock(&ar_sdio->mtx_irq); + sdio_release_host(ar_sdio->func); } @@ -1253,6 +1251,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, spin_lock_init(&ar_sdio->scat_lock); spin_lock_init(&ar_sdio->wr_async_lock); mutex_init(&ar_sdio->dma_buffer_mutex); + mutex_init(&ar_sdio->mtx_irq); INIT_LIST_HEAD(&ar_sdio->scat_req); INIT_LIST_HEAD(&ar_sdio->bus_req_freeq); -- GitLab From 4269a930548966014dd4186a15c8e023ca4abc29 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 5 Jan 2012 10:39:48 -0800 Subject: [PATCH 00068/10698] ath6kl: make net_device_ops const Signed-off-by: Stephen Hemminger Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 325d316f40ec..8742eaa78186 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1158,7 +1158,7 @@ static void ath6kl_set_multicast_list(struct net_device *ndev) list_splice_tail(&mc_filter_new, &vif->mc_filter); } -static struct net_device_ops ath6kl_netdev_ops = { +static const struct net_device_ops ath6kl_netdev_ops = { .ndo_open = ath6kl_open, .ndo_stop = ath6kl_close, .ndo_start_xmit = ath6kl_data_tx, -- GitLab From 18e83e4cd144e30fb38bf1f714914182c6c8bced Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Jan 2012 19:05:20 +0000 Subject: [PATCH 00069/10698] sfc: Const-qualify static data as appropriate, partly prompted by checkpatch Fix the following warnings: WARNING: struct dev_pm_ops should normally be const WARNING: static const char * array should probably be static const char * const Similarly const-qualify struct i2c_board_info, struct i2c_algo_bit_data, struct efx_ethtool_stat, struct efx_mtd_ops and struct siena_nvram_type_info. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 6 +++--- drivers/net/ethernet/sfc/ethtool.c | 4 ++-- drivers/net/ethernet/sfc/falcon.c | 2 +- drivers/net/ethernet/sfc/falcon_boards.c | 12 ++++++------ drivers/net/ethernet/sfc/mcdi.c | 4 ++-- drivers/net/ethernet/sfc/mtd.c | 8 ++++---- drivers/net/ethernet/sfc/net_driver.h | 4 ++-- drivers/net/ethernet/sfc/selftest.c | 2 +- drivers/net/ethernet/sfc/txc43128_phy.c | 2 +- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 0539a8d88a23..9ca5dcdf5a86 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -38,7 +38,7 @@ /* Loopback mode names (see LOOPBACK_MODE()) */ const unsigned int efx_loopback_mode_max = LOOPBACK_MAX; -const char *efx_loopback_mode_names[] = { +const char *const efx_loopback_mode_names[] = { [LOOPBACK_NONE] = "NONE", [LOOPBACK_DATA] = "DATAPATH", [LOOPBACK_GMAC] = "GMAC", @@ -69,7 +69,7 @@ const char *efx_loopback_mode_names[] = { }; const unsigned int efx_reset_type_max = RESET_TYPE_MAX; -const char *efx_reset_type_names[] = { +const char *const efx_reset_type_names[] = { [RESET_TYPE_INVISIBLE] = "INVISIBLE", [RESET_TYPE_ALL] = "ALL", [RESET_TYPE_WORLD] = "WORLD", @@ -2660,7 +2660,7 @@ static int efx_pm_suspend(struct device *dev) return rc; } -static struct dev_pm_ops efx_pm_ops = { +static const struct dev_pm_ops efx_pm_ops = { .suspend = efx_pm_suspend, .resume = efx_pm_resume, .freeze = efx_pm_freeze, diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index c090de4e66c3..52c9ee4c8aa3 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -91,7 +91,7 @@ static u64 efx_get_atomic_stat(void *field) EFX_ETHTOOL_STAT(tx_##field, tx_queue, field, \ unsigned int, efx_get_uint_stat) -static struct efx_ethtool_stat efx_ethtool_stats[] = { +static const struct efx_ethtool_stat efx_ethtool_stats[] = { EFX_ETHTOOL_U64_MAC_STAT(tx_bytes), EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes), EFX_ETHTOOL_U64_MAC_STAT(tx_bad_bytes), @@ -486,7 +486,7 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, { struct efx_nic *efx = netdev_priv(net_dev); struct efx_mac_stats *mac_stats = &efx->mac_stats; - struct efx_ethtool_stat *stat; + const struct efx_ethtool_stat *stat; struct efx_channel *channel; struct efx_tx_queue *tx_queue; struct rtnl_link_stats64 temp; diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 8ae1ebd35397..5c7548959dd7 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -89,7 +89,7 @@ static int falcon_getscl(void *data) return EFX_OWORD_FIELD(reg, FRF_AB_GPIO0_IN); } -static struct i2c_algo_bit_data falcon_i2c_bit_operations = { +static const struct i2c_algo_bit_data falcon_i2c_bit_operations = { .setsda = falcon_setsda, .setscl = falcon_setscl, .getsda = falcon_getsda, diff --git a/drivers/net/ethernet/sfc/falcon_boards.c b/drivers/net/ethernet/sfc/falcon_boards.c index 6cc16b8cc6f4..2084cc6ede52 100644 --- a/drivers/net/ethernet/sfc/falcon_boards.c +++ b/drivers/net/ethernet/sfc/falcon_boards.c @@ -87,7 +87,7 @@ static const u8 falcon_lm87_common_regs[] = { 0 }; -static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info, +static int efx_init_lm87(struct efx_nic *efx, const struct i2c_board_info *info, const u8 *reg_values) { struct falcon_board *board = falcon_board(efx); @@ -179,7 +179,7 @@ static int efx_check_lm87(struct efx_nic *efx, unsigned mask) #else /* !CONFIG_SENSORS_LM87 */ static inline int -efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info, +efx_init_lm87(struct efx_nic *efx, const struct i2c_board_info *info, const u8 *reg_values) { return 0; @@ -442,7 +442,7 @@ static int sfe4001_check_hw(struct efx_nic *efx) return (status < 0) ? -EIO : -ERANGE; } -static struct i2c_board_info sfe4001_hwmon_info = { +static const struct i2c_board_info sfe4001_hwmon_info = { I2C_BOARD_INFO("max6647", 0x4e), }; @@ -522,7 +522,7 @@ static const u8 sfe4002_lm87_regs[] = { 0 }; -static struct i2c_board_info sfe4002_hwmon_info = { +static const struct i2c_board_info sfe4002_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfe4002_lm87_channel, }; @@ -591,7 +591,7 @@ static const u8 sfn4112f_lm87_regs[] = { 0 }; -static struct i2c_board_info sfn4112f_hwmon_info = { +static const struct i2c_board_info sfn4112f_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfn4112f_lm87_channel, }; @@ -653,7 +653,7 @@ static const u8 sfe4003_lm87_regs[] = { 0 }; -static struct i2c_board_info sfe4003_hwmon_info = { +static const struct i2c_board_info sfe4003_hwmon_info = { I2C_BOARD_INFO("lm87", 0x2e), .platform_data = &sfe4003_lm87_channel, }; diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 81a425397468..b1de400ca24e 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -502,7 +502,7 @@ static void efx_mcdi_process_link_change(struct efx_nic *efx, efx_qword_t *ev) efx_link_status_changed(efx); } -static const char *sensor_names[] = { +static const char *const sensor_names[] = { [MC_CMD_SENSOR_CONTROLLER_TEMP] = "Controller temp. sensor", [MC_CMD_SENSOR_PHY_COMMON_TEMP] = "PHY shared temp. sensor", [MC_CMD_SENSOR_CONTROLLER_COOLING] = "Controller cooling", @@ -518,7 +518,7 @@ static const char *sensor_names[] = { [MC_CMD_SENSOR_IN_12V0] = "12V supply sensor" }; -static const char *sensor_status_names[] = { +static const char *const sensor_status_names[] = { [MC_CMD_SENSOR_STATE_OK] = "OK", [MC_CMD_SENSOR_STATE_WARNING] = "Warning", [MC_CMD_SENSOR_STATE_FATAL] = "Fatal", diff --git a/drivers/net/ethernet/sfc/mtd.c b/drivers/net/ethernet/sfc/mtd.c index bc9dcd6b30d7..13f61fba731f 100644 --- a/drivers/net/ethernet/sfc/mtd.c +++ b/drivers/net/ethernet/sfc/mtd.c @@ -382,7 +382,7 @@ static int falcon_mtd_sync(struct mtd_info *mtd) return rc; } -static struct efx_mtd_ops falcon_mtd_ops = { +static const struct efx_mtd_ops falcon_mtd_ops = { .read = falcon_mtd_read, .erase = falcon_mtd_erase, .write = falcon_mtd_write, @@ -560,7 +560,7 @@ static int siena_mtd_sync(struct mtd_info *mtd) return rc; } -static struct efx_mtd_ops siena_mtd_ops = { +static const struct efx_mtd_ops siena_mtd_ops = { .read = siena_mtd_read, .erase = siena_mtd_erase, .write = siena_mtd_write, @@ -572,7 +572,7 @@ struct siena_nvram_type_info { const char *name; }; -static struct siena_nvram_type_info siena_nvram_types[] = { +static const struct siena_nvram_type_info siena_nvram_types[] = { [MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO] = { 0, "sfc_dummy_phy" }, [MC_CMD_NVRAM_TYPE_MC_FW] = { 0, "sfc_mcfw" }, [MC_CMD_NVRAM_TYPE_MC_FW_BACKUP] = { 0, "sfc_mcfw_backup" }, @@ -593,7 +593,7 @@ static int siena_mtd_probe_partition(struct efx_nic *efx, unsigned int type) { struct efx_mtd_partition *part = &efx_mtd->part[part_id]; - struct siena_nvram_type_info *info; + const struct siena_nvram_type_info *info; size_t size, erase_size; bool protected; int rc; diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index c49502bab6a3..9353ce801752 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -395,12 +395,12 @@ enum efx_led_mode { #define STRING_TABLE_LOOKUP(val, member) \ ((val) < member ## _max) ? member ## _names[val] : "(invalid)" -extern const char *efx_loopback_mode_names[]; +extern const char *const efx_loopback_mode_names[]; extern const unsigned int efx_loopback_mode_max; #define LOOPBACK_MODE(efx) \ STRING_TABLE_LOOKUP((efx)->loopback_mode, efx_loopback_mode) -extern const char *efx_reset_type_names[]; +extern const char *const efx_reset_type_names[]; extern const unsigned int efx_reset_type_max; #define RESET_TYPE(type) \ STRING_TABLE_LOOKUP(type, efx_reset_type) diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index fc62fe2f766f..17ff9b399957 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -50,7 +50,7 @@ static const char payload_msg[] = /* Interrupt mode names */ static const unsigned int efx_interrupt_mode_max = EFX_INT_MODE_MAX; -static const char *efx_interrupt_mode_names[] = { +static const char *const efx_interrupt_mode_names[] = { [EFX_INT_MODE_MSIX] = "MSI-X", [EFX_INT_MODE_MSI] = "MSI", [EFX_INT_MODE_LEGACY] = "legacy", diff --git a/drivers/net/ethernet/sfc/txc43128_phy.c b/drivers/net/ethernet/sfc/txc43128_phy.c index 7c21b334a75b..29bb3f9941c0 100644 --- a/drivers/net/ethernet/sfc/txc43128_phy.c +++ b/drivers/net/ethernet/sfc/txc43128_phy.c @@ -512,7 +512,7 @@ static bool txc43128_phy_poll(struct efx_nic *efx) return efx->link_state.up != was_up; } -static const char *txc43128_test_names[] = { +static const char *const txc43128_test_names[] = { "bist" }; -- GitLab From 783b6bb66d4289826b3d022ad7b8ac3666951bb6 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Thu, 5 Jan 2012 19:09:24 +0000 Subject: [PATCH 00070/10698] sfc: Remove unnecessary inclusion of , prompted by checkpatch Fix the warning: WARNING: Use #include instead of There is no need for selftest.c to include the file at all. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/selftest.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index 17ff9b399957..5226d9857f30 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -19,7 +19,6 @@ #include #include #include -#include #include "net_driver.h" #include "efx.h" #include "nic.h" -- GitLab From 05a9320f7e64b69cbf612a69b7358546519ffc30 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 20 Dec 2011 00:44:06 +0000 Subject: [PATCH 00071/10698] sfc: Update MCDI (firmware interface) definitions Some commands and constants have been renamed; adjust the code accordingly. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/mcdi.c | 15 +- drivers/net/ethernet/sfc/mcdi_mac.c | 16 +- drivers/net/ethernet/sfc/mcdi_pcol.h | 3542 +++++++++++++++----------- drivers/net/ethernet/sfc/mcdi_phy.c | 34 +- drivers/net/ethernet/sfc/mtd.c | 3 +- 5 files changed, 2119 insertions(+), 1491 deletions(-) diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index b1de400ca24e..7c405d16692e 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -604,7 +604,7 @@ void efx_mcdi_process_event(struct efx_channel *channel, void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len) { - u8 outbuf[ALIGN(MC_CMD_GET_VERSION_V1_OUT_LEN, 4)]; + u8 outbuf[ALIGN(MC_CMD_GET_VERSION_OUT_LEN, 4)]; size_t outlength; const __le16 *ver_words; int rc; @@ -616,7 +616,7 @@ void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len) if (rc) goto fail; - if (outlength < MC_CMD_GET_VERSION_V1_OUT_LEN) { + if (outlength < MC_CMD_GET_VERSION_OUT_LEN) { rc = -EIO; goto fail; } @@ -665,7 +665,7 @@ int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, u16 *fw_subtype_list) { - uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LEN]; + uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LENMIN]; size_t outlen; int port_num = efx_port_num(efx); int offset; @@ -678,7 +678,7 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, if (rc) goto fail; - if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LEN) { + if (outlen < MC_CMD_GET_BOARD_CFG_OUT_LENMIN) { rc = -EIO; goto fail; } @@ -691,7 +691,8 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, if (fw_subtype_list) memcpy(fw_subtype_list, outbuf + MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST, - MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN); + MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM * + sizeof(fw_subtype_list[0])); return 0; @@ -779,7 +780,7 @@ int efx_mcdi_nvram_info(struct efx_nic *efx, unsigned int type, *size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_SIZE); *erase_size_out = MCDI_DWORD(outbuf, NVRAM_INFO_OUT_ERASESIZE); *protected_out = !!(MCDI_DWORD(outbuf, NVRAM_INFO_OUT_FLAGS) & - (1 << MC_CMD_NVRAM_PROTECTED_LBN)); + (1 << MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN)); return 0; fail: @@ -1060,7 +1061,7 @@ void efx_mcdi_set_id_led(struct efx_nic *efx, enum efx_led_mode mode) int efx_mcdi_reset_port(struct efx_nic *efx) { - int rc = efx_mcdi_rpc(efx, MC_CMD_PORT_RESET, NULL, 0, NULL, 0, NULL); + int rc = efx_mcdi_rpc(efx, MC_CMD_ENTITY_RESET, NULL, 0, NULL, 0, NULL); if (rc) netif_err(efx, hw, efx->net_dev, "%s: failed rc=%d\n", __func__, rc); diff --git a/drivers/net/ethernet/sfc/mcdi_mac.c b/drivers/net/ethernet/sfc/mcdi_mac.c index aa4052c500fa..85fe24f86396 100644 --- a/drivers/net/ethernet/sfc/mcdi_mac.c +++ b/drivers/net/ethernet/sfc/mcdi_mac.c @@ -84,7 +84,7 @@ int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, u32 addr_hi; u32 addr_lo; - BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_LEN != 0); + BUILD_BUG_ON(MC_CMD_MAC_STATS_OUT_DMA_LEN != 0); addr_lo = ((u64)dma_addr) >> 0; addr_hi = ((u64)dma_addr) >> 32; @@ -93,13 +93,13 @@ int efx_mcdi_mac_stats(struct efx_nic *efx, dma_addr_t dma_addr, MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_ADDR_HI, addr_hi); cmd_ptr = (efx_dword_t *)MCDI_PTR(inbuf, MAC_STATS_IN_CMD); EFX_POPULATE_DWORD_7(*cmd_ptr, - MC_CMD_MAC_STATS_CMD_DMA, !!enable, - MC_CMD_MAC_STATS_CMD_CLEAR, clear, - MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE, 1, - MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE, !!enable, - MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR, 0, - MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT, 1, - MC_CMD_MAC_STATS_CMD_PERIOD_MS, period); + MC_CMD_MAC_STATS_IN_DMA, !!enable, + MC_CMD_MAC_STATS_IN_CLEAR, clear, + MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE, 1, + MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE, !!enable, + MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR, 0, + MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT, 1, + MC_CMD_MAC_STATS_IN_PERIOD_MS, period); MCDI_SET_DWORD(inbuf, MAC_STATS_IN_DMA_LEN, dma_len); rc = efx_mcdi_rpc(efx, MC_CMD_MAC_STATS, inbuf, sizeof(inbuf), diff --git a/drivers/net/ethernet/sfc/mcdi_pcol.h b/drivers/net/ethernet/sfc/mcdi_pcol.h index 41fe06fa0600..0310b9f08c9b 100644 --- a/drivers/net/ethernet/sfc/mcdi_pcol.h +++ b/drivers/net/ethernet/sfc/mcdi_pcol.h @@ -22,6 +22,18 @@ /* The Scheduler has started. */ #define MC_FW_STATE_SCHED (8) +/* Siena MC shared memmory offsets */ +/* The 'doorbell' addresses are hard-wired to alert the MC when written */ +#define MC_SMEM_P0_DOORBELL_OFST 0x000 +#define MC_SMEM_P1_DOORBELL_OFST 0x004 +/* The rest of these are firmware-defined */ +#define MC_SMEM_P0_PDU_OFST 0x008 +#define MC_SMEM_P1_PDU_OFST 0x108 +#define MC_SMEM_PDU_LEN 0x100 +#define MC_SMEM_P0_PTP_TIME_OFST 0x7f0 +#define MC_SMEM_P0_STATUS_OFST 0x7f8 +#define MC_SMEM_P1_STATUS_OFST 0x7fc + /* Values to be written to the per-port status dword in shared * memory on reboot and assert */ #define MC_STATUS_DWORD_REBOOT (0xb007b007) @@ -34,6 +46,8 @@ */ #define MCDI_PCOL_VERSION 1 +/* Unused commands: 0x23, 0x27, 0x30, 0x31 */ + /** * MCDI version 1 * @@ -131,53 +145,6 @@ */ #define FSE_AZ_EV_CODE_MCDI_EVRESPONSE 0xc -#define MCDI_EVENT_DATA_LBN 0 -#define MCDI_EVENT_DATA_WIDTH 32 -#define MCDI_EVENT_CONT_LBN 32 -#define MCDI_EVENT_CONT_WIDTH 1 -#define MCDI_EVENT_LEVEL_LBN 33 -#define MCDI_EVENT_LEVEL_WIDTH 3 -#define MCDI_EVENT_LEVEL_INFO (0) -#define MCDI_EVENT_LEVEL_WARN (1) -#define MCDI_EVENT_LEVEL_ERR (2) -#define MCDI_EVENT_LEVEL_FATAL (3) -#define MCDI_EVENT_SRC_LBN 36 -#define MCDI_EVENT_SRC_WIDTH 8 -#define MCDI_EVENT_CODE_LBN 44 -#define MCDI_EVENT_CODE_WIDTH 8 -#define MCDI_EVENT_CODE_BADSSERT (1) -#define MCDI_EVENT_CODE_PMNOTICE (2) -#define MCDI_EVENT_CODE_CMDDONE (3) -#define MCDI_EVENT_CMDDONE_SEQ_LBN 0 -#define MCDI_EVENT_CMDDONE_SEQ_WIDTH 8 -#define MCDI_EVENT_CMDDONE_DATALEN_LBN 8 -#define MCDI_EVENT_CMDDONE_DATALEN_WIDTH 8 -#define MCDI_EVENT_CMDDONE_ERRNO_LBN 16 -#define MCDI_EVENT_CMDDONE_ERRNO_WIDTH 8 -#define MCDI_EVENT_CODE_LINKCHANGE (4) -#define MCDI_EVENT_LINKCHANGE_LP_CAP_LBN 0 -#define MCDI_EVENT_LINKCHANGE_LP_CAP_WIDTH 16 -#define MCDI_EVENT_LINKCHANGE_SPEED_LBN 16 -#define MCDI_EVENT_LINKCHANGE_SPEED_WIDTH 4 -#define MCDI_EVENT_LINKCHANGE_SPEED_100M 1 -#define MCDI_EVENT_LINKCHANGE_SPEED_1G 2 -#define MCDI_EVENT_LINKCHANGE_SPEED_10G 3 -#define MCDI_EVENT_LINKCHANGE_FCNTL_LBN 20 -#define MCDI_EVENT_LINKCHANGE_FCNTL_WIDTH 4 -#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_LBN 24 -#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_WIDTH 8 -#define MCDI_EVENT_CODE_SENSOREVT (5) -#define MCDI_EVENT_SENSOREVT_MONITOR_LBN 0 -#define MCDI_EVENT_SENSOREVT_MONITOR_WIDTH 8 -#define MCDI_EVENT_SENSOREVT_STATE_LBN 8 -#define MCDI_EVENT_SENSOREVT_STATE_WIDTH 8 -#define MCDI_EVENT_SENSOREVT_VALUE_LBN 16 -#define MCDI_EVENT_SENSOREVT_VALUE_WIDTH 16 -#define MCDI_EVENT_CODE_SCHEDERR (6) -#define MCDI_EVENT_CODE_REBOOT (7) -#define MCDI_EVENT_CODE_MAC_STATS_DMA (8) -#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_LBN 0 -#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_WIDTH 32 /* Non-existent command target */ #define MC_CMD_ERR_ENOENT 2 @@ -198,121 +165,24 @@ #define MC_CMD_ERR_CODE_OFST 0 +/* We define 8 "escape" commands to allow + for command number space extension */ + +#define MC_CMD_CMD_SPACE_ESCAPE_0 0x78 +#define MC_CMD_CMD_SPACE_ESCAPE_1 0x79 +#define MC_CMD_CMD_SPACE_ESCAPE_2 0x7A +#define MC_CMD_CMD_SPACE_ESCAPE_3 0x7B +#define MC_CMD_CMD_SPACE_ESCAPE_4 0x7C +#define MC_CMD_CMD_SPACE_ESCAPE_5 0x7D +#define MC_CMD_CMD_SPACE_ESCAPE_6 0x7E +#define MC_CMD_CMD_SPACE_ESCAPE_7 0x7F + +/* Vectors in the boot ROM */ +/* Point to the copycode entry point. */ +#define MC_BOOTROM_COPYCODE_VEC (0x7f4) +/* Points to the recovery mode entry point. */ +#define MC_BOOTROM_NOFLASH_VEC (0x7f8) -/* MC_CMD_READ32: (debug, variadic out) - * Read multiple 32byte words from MC memory - */ -#define MC_CMD_READ32 0x01 -#define MC_CMD_READ32_IN_LEN 8 -#define MC_CMD_READ32_IN_ADDR_OFST 0 -#define MC_CMD_READ32_IN_NUMWORDS_OFST 4 -#define MC_CMD_READ32_OUT_LEN(_numwords) \ - (4 * (_numwords)) -#define MC_CMD_READ32_OUT_BUFFER_OFST 0 - -/* MC_CMD_WRITE32: (debug, variadic in) - * Write multiple 32byte words to MC memory - */ -#define MC_CMD_WRITE32 0x02 -#define MC_CMD_WRITE32_IN_LEN(_numwords) (((_numwords) * 4) + 4) -#define MC_CMD_WRITE32_IN_ADDR_OFST 0 -#define MC_CMD_WRITE32_IN_BUFFER_OFST 4 -#define MC_CMD_WRITE32_OUT_LEN 0 - -/* MC_CMD_COPYCODE: (debug) - * Copy MC code between two locations and jump - */ -#define MC_CMD_COPYCODE 0x03 -#define MC_CMD_COPYCODE_IN_LEN 16 -#define MC_CMD_COPYCODE_IN_SRC_ADDR_OFST 0 -#define MC_CMD_COPYCODE_IN_DEST_ADDR_OFST 4 -#define MC_CMD_COPYCODE_IN_NUMWORDS_OFST 8 -#define MC_CMD_COPYCODE_IN_JUMP_OFST 12 -/* Control should return to the caller rather than jumping */ -#define MC_CMD_COPYCODE_JUMP_NONE 1 -#define MC_CMD_COPYCODE_OUT_LEN 0 - -/* MC_CMD_SET_FUNC: (debug) - * Select function for function-specific commands. - */ -#define MC_CMD_SET_FUNC 0x04 -#define MC_CMD_SET_FUNC_IN_LEN 4 -#define MC_CMD_SET_FUNC_IN_FUNC_OFST 0 -#define MC_CMD_SET_FUNC_OUT_LEN 0 - -/* MC_CMD_GET_BOOT_STATUS: - * Get the instruction address from which the MC booted. - */ -#define MC_CMD_GET_BOOT_STATUS 0x05 -#define MC_CMD_GET_BOOT_STATUS_IN_LEN 0 -#define MC_CMD_GET_BOOT_STATUS_OUT_LEN 8 -#define MC_CMD_GET_BOOT_STATUS_OUT_BOOT_OFFSET_OFST 0 -#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_OFST 4 -/* Reboot caused by watchdog */ -#define MC_CMD_GET_BOOT_STATUS_FLAGS_WATCHDOG_LBN (0) -#define MC_CMD_GET_BOOT_STATUS_FLAGS_WATCHDOG_WIDTH (1) -/* MC booted from primary flash partition */ -#define MC_CMD_GET_BOOT_STATUS_FLAGS_PRIMARY_LBN (1) -#define MC_CMD_GET_BOOT_STATUS_FLAGS_PRIMARY_WIDTH (1) -/* MC booted from backup flash partition */ -#define MC_CMD_GET_BOOT_STATUS_FLAGS_BACKUP_LBN (2) -#define MC_CMD_GET_BOOT_STATUS_FLAGS_BACKUP_WIDTH (1) - -/* MC_CMD_GET_ASSERTS: (debug, variadic out) - * Get (and optionally clear) the current assertion status. - * - * Only OUT.GLOBAL_FLAGS is guaranteed to exist in the completion - * payload. The other fields will only be present if - * OUT.GLOBAL_FLAGS != NO_FAILS - */ -#define MC_CMD_GET_ASSERTS 0x06 -#define MC_CMD_GET_ASSERTS_IN_LEN 4 -#define MC_CMD_GET_ASSERTS_IN_CLEAR_OFST 0 -#define MC_CMD_GET_ASSERTS_OUT_LEN 140 -/* Assertion status flag */ -#define MC_CMD_GET_ASSERTS_OUT_GLOBAL_FLAGS_OFST 0 -/*! No assertions have failed. */ -#define MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS 1 -/*! A system-level assertion has failed. */ -#define MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL 2 -/*! A thread-level assertion has failed. */ -#define MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL 3 -/*! The system was reset by the watchdog. */ -#define MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED 4 -/* Failing PC value */ -#define MC_CMD_GET_ASSERTS_OUT_SAVED_PC_OFFS_OFST 4 -/* Saved GP regs */ -#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST 8 -#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_LEN 124 -/* Failing thread address */ -#define MC_CMD_GET_ASSERTS_OUT_THREAD_OFFS_OFST 132 - -/* MC_CMD_LOG_CTRL: - * Determine the output stream for various events and messages - */ -#define MC_CMD_LOG_CTRL 0x07 -#define MC_CMD_LOG_CTRL_IN_LEN 8 -#define MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0 -#define MC_CMD_LOG_CTRL_IN_LOG_DEST_UART (1) -#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ (2) -#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ_OFST 4 -#define MC_CMD_LOG_CTRL_OUT_LEN 0 - -/* MC_CMD_GET_VERSION: - * Get version information about the MC firmware - */ -#define MC_CMD_GET_VERSION 0x08 -#define MC_CMD_GET_VERSION_IN_LEN 0 -#define MC_CMD_GET_VERSION_V0_OUT_LEN 4 -#define MC_CMD_GET_VERSION_V1_OUT_LEN 32 -#define MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 -/* Reserved version number to indicate "any" version. */ -#define MC_CMD_GET_VERSION_OUT_FIRMWARE_ANY 0xffffffff -/* The version response of a boot ROM awaiting rescue */ -#define MC_CMD_GET_VERSION_OUT_FIRMWARE_BOOTROM 0xb0070000 -#define MC_CMD_GET_VERSION_V1_OUT_PCOL_OFST 4 -/* 128bit mask of functions supported by the current firmware */ -#define MC_CMD_GET_VERSION_V1_OUT_SUPPORTED_FUNCS_OFST 8 /* The command set exported by the boot ROM (MCDI v0) */ #define MC_CMD_GET_VERSION_V0_SUPPORTED_FUNCS { \ (1 << MC_CMD_READ32) | \ @@ -320,1456 +190,2214 @@ (1 << MC_CMD_COPYCODE) | \ (1 << MC_CMD_GET_VERSION), \ 0, 0, 0 } -#define MC_CMD_GET_VERSION_OUT_VERSION_OFST 24 -/* Vectors in the boot ROM */ -/* Point to the copycode entry point. */ -#define MC_BOOTROM_COPYCODE_VEC (0x7f4) -/* Points to the recovery mode entry point. */ -#define MC_BOOTROM_NOFLASH_VEC (0x7f8) +#define MC_CMD_SENSOR_INFO_OUT_OFFSET_OFST(_x) \ + (MC_CMD_SENSOR_ENTRY_OFST + (_x)) + +#define MC_CMD_DBI_WRITE_IN_ADDRESS_OFST(n) \ + (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST + \ + MC_CMD_DBIWROP_TYPEDEF_ADDRESS_OFST + \ + (n) * MC_CMD_DBIWROP_TYPEDEF_LEN) + +#define MC_CMD_DBI_WRITE_IN_BYTE_MASK_OFST(n) \ + (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST + \ + MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_OFST + \ + (n) * MC_CMD_DBIWROP_TYPEDEF_LEN) + +#define MC_CMD_DBI_WRITE_IN_VALUE_OFST(n) \ + (MC_CMD_DBI_WRITE_IN_DBIWROP_OFST + \ + MC_CMD_DBIWROP_TYPEDEF_VALUE_OFST + \ + (n) * MC_CMD_DBIWROP_TYPEDEF_LEN) + + +/* MCDI_EVENT structuredef */ +#define MCDI_EVENT_LEN 8 +#define MCDI_EVENT_CONT_LBN 32 +#define MCDI_EVENT_CONT_WIDTH 1 +#define MCDI_EVENT_LEVEL_LBN 33 +#define MCDI_EVENT_LEVEL_WIDTH 3 +#define MCDI_EVENT_LEVEL_INFO 0x0 /* enum */ +#define MCDI_EVENT_LEVEL_WARN 0x1 /* enum */ +#define MCDI_EVENT_LEVEL_ERR 0x2 /* enum */ +#define MCDI_EVENT_LEVEL_FATAL 0x3 /* enum */ +#define MCDI_EVENT_DATA_OFST 0 +#define MCDI_EVENT_CMDDONE_SEQ_LBN 0 +#define MCDI_EVENT_CMDDONE_SEQ_WIDTH 8 +#define MCDI_EVENT_CMDDONE_DATALEN_LBN 8 +#define MCDI_EVENT_CMDDONE_DATALEN_WIDTH 8 +#define MCDI_EVENT_CMDDONE_ERRNO_LBN 16 +#define MCDI_EVENT_CMDDONE_ERRNO_WIDTH 8 +#define MCDI_EVENT_LINKCHANGE_LP_CAP_LBN 0 +#define MCDI_EVENT_LINKCHANGE_LP_CAP_WIDTH 16 +#define MCDI_EVENT_LINKCHANGE_SPEED_LBN 16 +#define MCDI_EVENT_LINKCHANGE_SPEED_WIDTH 4 +#define MCDI_EVENT_LINKCHANGE_SPEED_100M 0x1 /* enum */ +#define MCDI_EVENT_LINKCHANGE_SPEED_1G 0x2 /* enum */ +#define MCDI_EVENT_LINKCHANGE_SPEED_10G 0x3 /* enum */ +#define MCDI_EVENT_LINKCHANGE_FCNTL_LBN 20 +#define MCDI_EVENT_LINKCHANGE_FCNTL_WIDTH 4 +#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_LBN 24 +#define MCDI_EVENT_LINKCHANGE_LINK_FLAGS_WIDTH 8 +#define MCDI_EVENT_SENSOREVT_MONITOR_LBN 0 +#define MCDI_EVENT_SENSOREVT_MONITOR_WIDTH 8 +#define MCDI_EVENT_SENSOREVT_STATE_LBN 8 +#define MCDI_EVENT_SENSOREVT_STATE_WIDTH 8 +#define MCDI_EVENT_SENSOREVT_VALUE_LBN 16 +#define MCDI_EVENT_SENSOREVT_VALUE_WIDTH 16 +#define MCDI_EVENT_FWALERT_DATA_LBN 8 +#define MCDI_EVENT_FWALERT_DATA_WIDTH 24 +#define MCDI_EVENT_FWALERT_REASON_LBN 0 +#define MCDI_EVENT_FWALERT_REASON_WIDTH 8 +#define MCDI_EVENT_FWALERT_REASON_SRAM_ACCESS 0x1 /* enum */ +#define MCDI_EVENT_FLR_VF_LBN 0 +#define MCDI_EVENT_FLR_VF_WIDTH 8 +#define MCDI_EVENT_TX_ERR_TXQ_LBN 0 +#define MCDI_EVENT_TX_ERR_TXQ_WIDTH 12 +#define MCDI_EVENT_TX_ERR_TYPE_LBN 12 +#define MCDI_EVENT_TX_ERR_TYPE_WIDTH 4 +#define MCDI_EVENT_TX_ERR_DL_FAIL 0x1 /* enum */ +#define MCDI_EVENT_TX_ERR_NO_EOP 0x2 /* enum */ +#define MCDI_EVENT_TX_ERR_2BIG 0x3 /* enum */ +#define MCDI_EVENT_TX_ERR_INFO_LBN 16 +#define MCDI_EVENT_TX_ERR_INFO_WIDTH 16 +#define MCDI_EVENT_TX_FLUSH_TXQ_LBN 0 +#define MCDI_EVENT_TX_FLUSH_TXQ_WIDTH 12 +#define MCDI_EVENT_PTP_ERR_TYPE_LBN 0 +#define MCDI_EVENT_PTP_ERR_TYPE_WIDTH 8 +#define MCDI_EVENT_PTP_ERR_PLL_LOST 0x1 /* enum */ +#define MCDI_EVENT_PTP_ERR_FILTER 0x2 /* enum */ +#define MCDI_EVENT_PTP_ERR_FIFO 0x3 /* enum */ +#define MCDI_EVENT_PTP_ERR_QUEUE 0x4 /* enum */ +#define MCDI_EVENT_DATA_LBN 0 +#define MCDI_EVENT_DATA_WIDTH 32 +#define MCDI_EVENT_SRC_LBN 36 +#define MCDI_EVENT_SRC_WIDTH 8 +#define MCDI_EVENT_EV_CODE_LBN 60 +#define MCDI_EVENT_EV_CODE_WIDTH 4 +#define MCDI_EVENT_CODE_LBN 44 +#define MCDI_EVENT_CODE_WIDTH 8 +#define MCDI_EVENT_CODE_BADSSERT 0x1 /* enum */ +#define MCDI_EVENT_CODE_PMNOTICE 0x2 /* enum */ +#define MCDI_EVENT_CODE_CMDDONE 0x3 /* enum */ +#define MCDI_EVENT_CODE_LINKCHANGE 0x4 /* enum */ +#define MCDI_EVENT_CODE_SENSOREVT 0x5 /* enum */ +#define MCDI_EVENT_CODE_SCHEDERR 0x6 /* enum */ +#define MCDI_EVENT_CODE_REBOOT 0x7 /* enum */ +#define MCDI_EVENT_CODE_MAC_STATS_DMA 0x8 /* enum */ +#define MCDI_EVENT_CODE_FWALERT 0x9 /* enum */ +#define MCDI_EVENT_CODE_FLR 0xa /* enum */ +#define MCDI_EVENT_CODE_TX_ERR 0xb /* enum */ +#define MCDI_EVENT_CODE_TX_FLUSH 0xc /* enum */ +#define MCDI_EVENT_CODE_PTP_RX 0xd /* enum */ +#define MCDI_EVENT_CODE_PTP_FAULT 0xe /* enum */ +#define MCDI_EVENT_CMDDONE_DATA_OFST 0 +#define MCDI_EVENT_CMDDONE_DATA_LBN 0 +#define MCDI_EVENT_CMDDONE_DATA_WIDTH 32 +#define MCDI_EVENT_LINKCHANGE_DATA_OFST 0 +#define MCDI_EVENT_LINKCHANGE_DATA_LBN 0 +#define MCDI_EVENT_LINKCHANGE_DATA_WIDTH 32 +#define MCDI_EVENT_SENSOREVT_DATA_OFST 0 +#define MCDI_EVENT_SENSOREVT_DATA_LBN 0 +#define MCDI_EVENT_SENSOREVT_DATA_WIDTH 32 +#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_OFST 0 +#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_LBN 0 +#define MCDI_EVENT_MAC_STATS_DMA_GENERATION_WIDTH 32 +#define MCDI_EVENT_TX_ERR_DATA_OFST 0 +#define MCDI_EVENT_TX_ERR_DATA_LBN 0 +#define MCDI_EVENT_TX_ERR_DATA_WIDTH 32 +#define MCDI_EVENT_PTP_SECONDS_OFST 0 +#define MCDI_EVENT_PTP_SECONDS_LBN 0 +#define MCDI_EVENT_PTP_SECONDS_WIDTH 32 +#define MCDI_EVENT_PTP_NANOSECONDS_OFST 0 +#define MCDI_EVENT_PTP_NANOSECONDS_LBN 0 +#define MCDI_EVENT_PTP_NANOSECONDS_WIDTH 32 +#define MCDI_EVENT_PTP_UUID_OFST 0 +#define MCDI_EVENT_PTP_UUID_LBN 0 +#define MCDI_EVENT_PTP_UUID_WIDTH 32 + + +/***********************************/ +/* MC_CMD_READ32 + * Read multiple 32byte words from MC memory. + */ +#define MC_CMD_READ32 0x1 + +/* MC_CMD_READ32_IN msgrequest */ +#define MC_CMD_READ32_IN_LEN 8 +#define MC_CMD_READ32_IN_ADDR_OFST 0 +#define MC_CMD_READ32_IN_NUMWORDS_OFST 4 + +/* MC_CMD_READ32_OUT msgresponse */ +#define MC_CMD_READ32_OUT_LENMIN 4 +#define MC_CMD_READ32_OUT_LENMAX 252 +#define MC_CMD_READ32_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_READ32_OUT_BUFFER_OFST 0 +#define MC_CMD_READ32_OUT_BUFFER_LEN 4 +#define MC_CMD_READ32_OUT_BUFFER_MINNUM 1 +#define MC_CMD_READ32_OUT_BUFFER_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_WRITE32 + * Write multiple 32byte words to MC memory. + */ +#define MC_CMD_WRITE32 0x2 + +/* MC_CMD_WRITE32_IN msgrequest */ +#define MC_CMD_WRITE32_IN_LENMIN 8 +#define MC_CMD_WRITE32_IN_LENMAX 252 +#define MC_CMD_WRITE32_IN_LEN(num) (4+4*(num)) +#define MC_CMD_WRITE32_IN_ADDR_OFST 0 +#define MC_CMD_WRITE32_IN_BUFFER_OFST 4 +#define MC_CMD_WRITE32_IN_BUFFER_LEN 4 +#define MC_CMD_WRITE32_IN_BUFFER_MINNUM 1 +#define MC_CMD_WRITE32_IN_BUFFER_MAXNUM 62 + +/* MC_CMD_WRITE32_OUT msgresponse */ +#define MC_CMD_WRITE32_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_COPYCODE + * Copy MC code between two locations and jump. + */ +#define MC_CMD_COPYCODE 0x3 + +/* MC_CMD_COPYCODE_IN msgrequest */ +#define MC_CMD_COPYCODE_IN_LEN 16 +#define MC_CMD_COPYCODE_IN_SRC_ADDR_OFST 0 +#define MC_CMD_COPYCODE_IN_DEST_ADDR_OFST 4 +#define MC_CMD_COPYCODE_IN_NUMWORDS_OFST 8 +#define MC_CMD_COPYCODE_IN_JUMP_OFST 12 +#define MC_CMD_COPYCODE_JUMP_NONE 0x1 /* enum */ + +/* MC_CMD_COPYCODE_OUT msgresponse */ +#define MC_CMD_COPYCODE_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SET_FUNC + */ +#define MC_CMD_SET_FUNC 0x4 + +/* MC_CMD_SET_FUNC_IN msgrequest */ +#define MC_CMD_SET_FUNC_IN_LEN 4 +#define MC_CMD_SET_FUNC_IN_FUNC_OFST 0 + +/* MC_CMD_SET_FUNC_OUT msgresponse */ +#define MC_CMD_SET_FUNC_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_BOOT_STATUS + */ +#define MC_CMD_GET_BOOT_STATUS 0x5 + +/* MC_CMD_GET_BOOT_STATUS_IN msgrequest */ +#define MC_CMD_GET_BOOT_STATUS_IN_LEN 0 + +/* MC_CMD_GET_BOOT_STATUS_OUT msgresponse */ +#define MC_CMD_GET_BOOT_STATUS_OUT_LEN 8 +#define MC_CMD_GET_BOOT_STATUS_OUT_BOOT_OFFSET_OFST 0 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_OFST 4 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_WATCHDOG_LBN 0 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_WATCHDOG_WIDTH 1 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_PRIMARY_LBN 1 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_PRIMARY_WIDTH 1 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_BACKUP_LBN 2 +#define MC_CMD_GET_BOOT_STATUS_OUT_FLAGS_BACKUP_WIDTH 1 -/* Test execution limits */ -#define MC_TESTEXEC_VARIANT_COUNT 16 -#define MC_TESTEXEC_RESULT_COUNT 7 -/* MC_CMD_SET_TESTVARS: (debug, variadic in) - * Write variant words for test. - * - * The user supplies a bitmap of the variants they wish to set. - * They must ensure that IN.LEN >= 4 + 4 * ffs(BITMAP) - */ -#define MC_CMD_SET_TESTVARS 0x09 -#define MC_CMD_SET_TESTVARS_IN_LEN(_numwords) \ - (4 + 4*(_numwords)) -#define MC_CMD_SET_TESTVARS_IN_ARGS_BITMAP_OFST 0 -/* Up to MC_TESTEXEC_VARIANT_COUNT of 32byte words start here */ -#define MC_CMD_SET_TESTVARS_IN_ARGS_BUFFER_OFST 4 -#define MC_CMD_SET_TESTVARS_OUT_LEN 0 - -/* MC_CMD_GET_TESTRCS: (debug, variadic out) - * Return result words from test. - */ -#define MC_CMD_GET_TESTRCS 0x0a -#define MC_CMD_GET_TESTRCS_IN_LEN 4 -#define MC_CMD_GET_TESTRCS_IN_NUMWORDS_OFST 0 -#define MC_CMD_GET_TESTRCS_OUT_LEN(_numwords) \ - (4 * (_numwords)) -#define MC_CMD_GET_TESTRCS_OUT_BUFFER_OFST 0 - -/* MC_CMD_RUN_TEST: (debug) - * Run the test exported by this firmware image - */ -#define MC_CMD_RUN_TEST 0x0b -#define MC_CMD_RUN_TEST_IN_LEN 0 -#define MC_CMD_RUN_TEST_OUT_LEN 0 - -/* MC_CMD_CSR_READ32: (debug, variadic out) - * Read 32bit words from the indirect memory map - */ -#define MC_CMD_CSR_READ32 0x0c -#define MC_CMD_CSR_READ32_IN_LEN 12 -#define MC_CMD_CSR_READ32_IN_ADDR_OFST 0 -#define MC_CMD_CSR_READ32_IN_STEP_OFST 4 -#define MC_CMD_CSR_READ32_IN_NUMWORDS_OFST 8 -#define MC_CMD_CSR_READ32_OUT_LEN(_numwords) \ - (((_numwords) * 4) + 4) -/* IN.NUMWORDS of 32bit words start here */ -#define MC_CMD_CSR_READ32_OUT_BUFFER_OFST 0 -#define MC_CMD_CSR_READ32_OUT_IREG_STATUS_OFST(_numwords) \ - ((_numwords) * 4) - -/* MC_CMD_CSR_WRITE32: (debug, variadic in) - * Write 32bit dwords to the indirect memory map - */ -#define MC_CMD_CSR_WRITE32 0x0d -#define MC_CMD_CSR_WRITE32_IN_LEN(_numwords) \ - (((_numwords) * 4) + 8) -#define MC_CMD_CSR_WRITE32_IN_ADDR_OFST 0 -#define MC_CMD_CSR_WRITE32_IN_STEP_OFST 4 -/* Multiple 32bit words of data to write start here */ -#define MC_CMD_CSR_WRITE32_IN_BUFFER_OFST 8 -#define MC_CMD_CSR_WRITE32_OUT_LEN 4 -#define MC_CMD_CSR_WRITE32_OUT_STATUS_OFST 0 - -/* MC_CMD_JTAG_WORK: (debug, fpga only) - * Process JTAG work buffer for RBF acceleration. - * - * Host: bit count, (up to) 32 words of data to clock out to JTAG - * (bits 1,0=TMS,TDO for first bit; bits 3,2=TMS,TDO for second bit, etc.) - * MC: bit count, (up to) 32 words of data clocked in from JTAG - * (bit 0=TDI for first bit, bit 1=TDI for second bit, etc.; [31:16] unused) +/***********************************/ +/* MC_CMD_GET_ASSERTS + * Get and clear any assertion status. */ -#define MC_CMD_JTAG_WORK 0x0e +#define MC_CMD_GET_ASSERTS 0x6 -/* MC_CMD_STACKINFO: (debug, variadic out) - * Get stack information - * - * Host: nothing - * MC: (thread ptr, stack size, free space) for each thread in system - */ -#define MC_CMD_STACKINFO 0x0f +/* MC_CMD_GET_ASSERTS_IN msgrequest */ +#define MC_CMD_GET_ASSERTS_IN_LEN 4 +#define MC_CMD_GET_ASSERTS_IN_CLEAR_OFST 0 + +/* MC_CMD_GET_ASSERTS_OUT msgresponse */ +#define MC_CMD_GET_ASSERTS_OUT_LEN 140 +#define MC_CMD_GET_ASSERTS_OUT_GLOBAL_FLAGS_OFST 0 +#define MC_CMD_GET_ASSERTS_FLAGS_NO_FAILS 0x1 /* enum */ +#define MC_CMD_GET_ASSERTS_FLAGS_SYS_FAIL 0x2 /* enum */ +#define MC_CMD_GET_ASSERTS_FLAGS_THR_FAIL 0x3 /* enum */ +#define MC_CMD_GET_ASSERTS_FLAGS_WDOG_FIRED 0x4 /* enum */ +#define MC_CMD_GET_ASSERTS_OUT_SAVED_PC_OFFS_OFST 4 +#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_OFST 8 +#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_LEN 4 +#define MC_CMD_GET_ASSERTS_OUT_GP_REGS_OFFS_NUM 31 +#define MC_CMD_GET_ASSERTS_OUT_THREAD_OFFS_OFST 132 +#define MC_CMD_GET_ASSERTS_OUT_RESERVED_OFST 136 -/* MC_CMD_MDIO_READ: - * MDIO register read + +/***********************************/ +/* MC_CMD_LOG_CTRL + * Configure the output stream for various events and messages. + */ +#define MC_CMD_LOG_CTRL 0x7 + +/* MC_CMD_LOG_CTRL_IN msgrequest */ +#define MC_CMD_LOG_CTRL_IN_LEN 8 +#define MC_CMD_LOG_CTRL_IN_LOG_DEST_OFST 0 +#define MC_CMD_LOG_CTRL_IN_LOG_DEST_UART 0x1 /* enum */ +#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ 0x2 /* enum */ +#define MC_CMD_LOG_CTRL_IN_LOG_DEST_EVQ_OFST 4 + +/* MC_CMD_LOG_CTRL_OUT msgresponse */ +#define MC_CMD_LOG_CTRL_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_VERSION + * Get version information about the MC firmware. + */ +#define MC_CMD_GET_VERSION 0x8 + +/* MC_CMD_GET_VERSION_IN msgrequest */ +#define MC_CMD_GET_VERSION_IN_LEN 0 + +/* MC_CMD_GET_VERSION_V0_OUT msgresponse */ +#define MC_CMD_GET_VERSION_V0_OUT_LEN 4 +#define MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 +#define MC_CMD_GET_VERSION_OUT_FIRMWARE_ANY 0xffffffff /* enum */ +#define MC_CMD_GET_VERSION_OUT_FIRMWARE_BOOTROM 0xb0070000 /* enum */ + +/* MC_CMD_GET_VERSION_OUT msgresponse */ +#define MC_CMD_GET_VERSION_OUT_LEN 32 +/* MC_CMD_GET_VERSION_OUT_FIRMWARE_OFST 0 */ +/* Enum values, see field(s): */ +/* MC_CMD_GET_VERSION_V0_OUT/MC_CMD_GET_VERSION_OUT_FIRMWARE */ +#define MC_CMD_GET_VERSION_OUT_PCOL_OFST 4 +#define MC_CMD_GET_VERSION_OUT_SUPPORTED_FUNCS_OFST 8 +#define MC_CMD_GET_VERSION_OUT_SUPPORTED_FUNCS_LEN 16 +#define MC_CMD_GET_VERSION_OUT_VERSION_OFST 24 +#define MC_CMD_GET_VERSION_OUT_VERSION_LEN 8 +#define MC_CMD_GET_VERSION_OUT_VERSION_LO_OFST 24 +#define MC_CMD_GET_VERSION_OUT_VERSION_HI_OFST 28 + + +/***********************************/ +/* MC_CMD_GET_FPGAREG + * Read multiple bytes from PTP FPGA. + */ +#define MC_CMD_GET_FPGAREG 0x9 + +/* MC_CMD_GET_FPGAREG_IN msgrequest */ +#define MC_CMD_GET_FPGAREG_IN_LEN 8 +#define MC_CMD_GET_FPGAREG_IN_ADDR_OFST 0 +#define MC_CMD_GET_FPGAREG_IN_NUMBYTES_OFST 4 + +/* MC_CMD_GET_FPGAREG_OUT msgresponse */ +#define MC_CMD_GET_FPGAREG_OUT_LENMIN 1 +#define MC_CMD_GET_FPGAREG_OUT_LENMAX 255 +#define MC_CMD_GET_FPGAREG_OUT_LEN(num) (0+1*(num)) +#define MC_CMD_GET_FPGAREG_OUT_BUFFER_OFST 0 +#define MC_CMD_GET_FPGAREG_OUT_BUFFER_LEN 1 +#define MC_CMD_GET_FPGAREG_OUT_BUFFER_MINNUM 1 +#define MC_CMD_GET_FPGAREG_OUT_BUFFER_MAXNUM 255 + + +/***********************************/ +/* MC_CMD_PUT_FPGAREG + * Write multiple bytes to PTP FPGA. + */ +#define MC_CMD_PUT_FPGAREG 0xa + +/* MC_CMD_PUT_FPGAREG_IN msgrequest */ +#define MC_CMD_PUT_FPGAREG_IN_LENMIN 5 +#define MC_CMD_PUT_FPGAREG_IN_LENMAX 255 +#define MC_CMD_PUT_FPGAREG_IN_LEN(num) (4+1*(num)) +#define MC_CMD_PUT_FPGAREG_IN_ADDR_OFST 0 +#define MC_CMD_PUT_FPGAREG_IN_BUFFER_OFST 4 +#define MC_CMD_PUT_FPGAREG_IN_BUFFER_LEN 1 +#define MC_CMD_PUT_FPGAREG_IN_BUFFER_MINNUM 1 +#define MC_CMD_PUT_FPGAREG_IN_BUFFER_MAXNUM 251 + +/* MC_CMD_PUT_FPGAREG_OUT msgresponse */ +#define MC_CMD_PUT_FPGAREG_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_PTP + * Perform PTP operation + */ +#define MC_CMD_PTP 0xb + +/* MC_CMD_PTP_IN msgrequest */ +#define MC_CMD_PTP_IN_LEN 1 +#define MC_CMD_PTP_IN_OP_OFST 0 +#define MC_CMD_PTP_IN_OP_LEN 1 +#define MC_CMD_PTP_OP_ENABLE 0x1 /* enum */ +#define MC_CMD_PTP_OP_DISABLE 0x2 /* enum */ +#define MC_CMD_PTP_OP_TRANSMIT 0x3 /* enum */ +#define MC_CMD_PTP_OP_READ_NIC_TIME 0x4 /* enum */ +#define MC_CMD_PTP_OP_STATUS 0x5 /* enum */ +#define MC_CMD_PTP_OP_ADJUST 0x6 /* enum */ +#define MC_CMD_PTP_OP_SYNCHRONIZE 0x7 /* enum */ +#define MC_CMD_PTP_OP_MANFTEST_BASIC 0x8 /* enum */ +#define MC_CMD_PTP_OP_MANFTEST_PACKET 0x9 /* enum */ +#define MC_CMD_PTP_OP_RESET_STATS 0xa /* enum */ +#define MC_CMD_PTP_OP_DEBUG 0xb /* enum */ +#define MC_CMD_PTP_OP_MAX 0xc /* enum */ + +/* MC_CMD_PTP_IN_ENABLE msgrequest */ +#define MC_CMD_PTP_IN_ENABLE_LEN 16 +#define MC_CMD_PTP_IN_CMD_OFST 0 +#define MC_CMD_PTP_IN_PERIPH_ID_OFST 4 +#define MC_CMD_PTP_IN_ENABLE_QUEUE_OFST 8 +#define MC_CMD_PTP_IN_ENABLE_MODE_OFST 12 +#define MC_CMD_PTP_MODE_V1 0x0 /* enum */ +#define MC_CMD_PTP_MODE_V1_VLAN 0x1 /* enum */ +#define MC_CMD_PTP_MODE_V2 0x2 /* enum */ +#define MC_CMD_PTP_MODE_V2_VLAN 0x3 /* enum */ + +/* MC_CMD_PTP_IN_DISABLE msgrequest */ +#define MC_CMD_PTP_IN_DISABLE_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_TRANSMIT msgrequest */ +#define MC_CMD_PTP_IN_TRANSMIT_LENMIN 13 +#define MC_CMD_PTP_IN_TRANSMIT_LENMAX 255 +#define MC_CMD_PTP_IN_TRANSMIT_LEN(num) (12+1*(num)) +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_TRANSMIT_LENGTH_OFST 8 +#define MC_CMD_PTP_IN_TRANSMIT_PACKET_OFST 12 +#define MC_CMD_PTP_IN_TRANSMIT_PACKET_LEN 1 +#define MC_CMD_PTP_IN_TRANSMIT_PACKET_MINNUM 1 +#define MC_CMD_PTP_IN_TRANSMIT_PACKET_MAXNUM 243 + +/* MC_CMD_PTP_IN_READ_NIC_TIME msgrequest */ +#define MC_CMD_PTP_IN_READ_NIC_TIME_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_STATUS msgrequest */ +#define MC_CMD_PTP_IN_STATUS_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_ADJUST msgrequest */ +#define MC_CMD_PTP_IN_ADJUST_LEN 24 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_ADJUST_FREQ_OFST 8 +#define MC_CMD_PTP_IN_ADJUST_FREQ_LEN 8 +#define MC_CMD_PTP_IN_ADJUST_FREQ_LO_OFST 8 +#define MC_CMD_PTP_IN_ADJUST_FREQ_HI_OFST 12 +#define MC_CMD_PTP_IN_ADJUST_BITS 0x28 /* enum */ +#define MC_CMD_PTP_IN_ADJUST_SECONDS_OFST 16 +#define MC_CMD_PTP_IN_ADJUST_NANOSECONDS_OFST 20 + +/* MC_CMD_PTP_IN_SYNCHRONIZE msgrequest */ +#define MC_CMD_PTP_IN_SYNCHRONIZE_LEN 20 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_SYNCHRONIZE_NUMTIMESETS_OFST 8 +#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_OFST 12 +#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_LEN 8 +#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_LO_OFST 12 +#define MC_CMD_PTP_IN_SYNCHRONIZE_START_ADDR_HI_OFST 16 + +/* MC_CMD_PTP_IN_MANFTEST_BASIC msgrequest */ +#define MC_CMD_PTP_IN_MANFTEST_BASIC_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_MANFTEST_PACKET msgrequest */ +#define MC_CMD_PTP_IN_MANFTEST_PACKET_LEN 12 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_MANFTEST_PACKET_TEST_ENABLE_OFST 8 + +/* MC_CMD_PTP_IN_RESET_STATS msgrequest */ +#define MC_CMD_PTP_IN_RESET_STATS_LEN 8 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ + +/* MC_CMD_PTP_IN_DEBUG msgrequest */ +#define MC_CMD_PTP_IN_DEBUG_LEN 12 +/* MC_CMD_PTP_IN_CMD_OFST 0 */ +/* MC_CMD_PTP_IN_PERIPH_ID_OFST 4 */ +#define MC_CMD_PTP_IN_DEBUG_DEBUG_PARAM_OFST 8 + +/* MC_CMD_PTP_OUT msgresponse */ +#define MC_CMD_PTP_OUT_LEN 0 + +/* MC_CMD_PTP_OUT_TRANSMIT msgresponse */ +#define MC_CMD_PTP_OUT_TRANSMIT_LEN 8 +#define MC_CMD_PTP_OUT_TRANSMIT_SECONDS_OFST 0 +#define MC_CMD_PTP_OUT_TRANSMIT_NANOSECONDS_OFST 4 + +/* MC_CMD_PTP_OUT_READ_NIC_TIME msgresponse */ +#define MC_CMD_PTP_OUT_READ_NIC_TIME_LEN 8 +#define MC_CMD_PTP_OUT_READ_NIC_TIME_SECONDS_OFST 0 +#define MC_CMD_PTP_OUT_READ_NIC_TIME_NANOSECONDS_OFST 4 + +/* MC_CMD_PTP_OUT_STATUS msgresponse */ +#define MC_CMD_PTP_OUT_STATUS_LEN 64 +#define MC_CMD_PTP_OUT_STATUS_CLOCK_FREQ_OFST 0 +#define MC_CMD_PTP_OUT_STATUS_STATS_TX_OFST 4 +#define MC_CMD_PTP_OUT_STATUS_STATS_RX_OFST 8 +#define MC_CMD_PTP_OUT_STATUS_STATS_TS_OFST 12 +#define MC_CMD_PTP_OUT_STATUS_STATS_FM_OFST 16 +#define MC_CMD_PTP_OUT_STATUS_STATS_NFM_OFST 20 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFLOW_OFST 24 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_BAD_OFST 28 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MIN_OFST 32 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MAX_OFST 36 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_LAST_OFST 40 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_PER_MEAN_OFST 44 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MIN_OFST 48 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MAX_OFST 52 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_LAST_OFST 56 +#define MC_CMD_PTP_OUT_STATUS_STATS_PPS_OFF_MEAN_OFST 60 + +/* MC_CMD_PTP_OUT_SYNCHRONIZE msgresponse */ +#define MC_CMD_PTP_OUT_SYNCHRONIZE_LENMIN 20 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_LENMAX 240 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_LEN(num) (0+20*(num)) +#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_OFST 0 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_LEN 20 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MINNUM 1 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_TIMESET_MAXNUM 12 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTSTART_OFST 0 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_SECONDS_OFST 4 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_NANOSECONDS_OFST 8 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_HOSTEND_OFST 12 +#define MC_CMD_PTP_OUT_SYNCHRONIZE_WAITNS_OFST 16 + +/* MC_CMD_PTP_OUT_MANFTEST_BASIC msgresponse */ +#define MC_CMD_PTP_OUT_MANFTEST_BASIC_LEN 8 +#define MC_CMD_PTP_OUT_MANFTEST_BASIC_TEST_RESULT_OFST 0 +#define MC_CMD_PTP_MANF_SUCCESS 0x0 /* enum */ +#define MC_CMD_PTP_MANF_FPGA_LOAD 0x1 /* enum */ +#define MC_CMD_PTP_MANF_FPGA_VERSION 0x2 /* enum */ +#define MC_CMD_PTP_MANF_FPGA_REGISTERS 0x3 /* enum */ +#define MC_CMD_PTP_MANF_OSCILLATOR 0x4 /* enum */ +#define MC_CMD_PTP_MANF_TIMESTAMPS 0x5 /* enum */ +#define MC_CMD_PTP_MANF_PACKET_COUNT 0x6 /* enum */ +#define MC_CMD_PTP_MANF_FILTER_COUNT 0x7 /* enum */ +#define MC_CMD_PTP_MANF_PACKET_ENOUGH 0x8 /* enum */ +#define MC_CMD_PTP_MANF_GPIO_TRIGGER 0x9 /* enum */ +#define MC_CMD_PTP_OUT_MANFTEST_BASIC_TEST_EXTOSC_OFST 4 + +/* MC_CMD_PTP_OUT_MANFTEST_PACKET msgresponse */ +#define MC_CMD_PTP_OUT_MANFTEST_PACKET_LEN 12 +#define MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_RESULT_OFST 0 +#define MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_FPGACOUNT_OFST 4 +#define MC_CMD_PTP_OUT_MANFTEST_PACKET_TEST_FILTERCOUNT_OFST 8 + + +/***********************************/ +/* MC_CMD_CSR_READ32 + * Read 32bit words from the indirect memory map. + */ +#define MC_CMD_CSR_READ32 0xc + +/* MC_CMD_CSR_READ32_IN msgrequest */ +#define MC_CMD_CSR_READ32_IN_LEN 12 +#define MC_CMD_CSR_READ32_IN_ADDR_OFST 0 +#define MC_CMD_CSR_READ32_IN_STEP_OFST 4 +#define MC_CMD_CSR_READ32_IN_NUMWORDS_OFST 8 + +/* MC_CMD_CSR_READ32_OUT msgresponse */ +#define MC_CMD_CSR_READ32_OUT_LENMIN 4 +#define MC_CMD_CSR_READ32_OUT_LENMAX 252 +#define MC_CMD_CSR_READ32_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_CSR_READ32_OUT_BUFFER_OFST 0 +#define MC_CMD_CSR_READ32_OUT_BUFFER_LEN 4 +#define MC_CMD_CSR_READ32_OUT_BUFFER_MINNUM 1 +#define MC_CMD_CSR_READ32_OUT_BUFFER_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_CSR_WRITE32 + * Write 32bit dwords to the indirect memory map. + */ +#define MC_CMD_CSR_WRITE32 0xd + +/* MC_CMD_CSR_WRITE32_IN msgrequest */ +#define MC_CMD_CSR_WRITE32_IN_LENMIN 12 +#define MC_CMD_CSR_WRITE32_IN_LENMAX 252 +#define MC_CMD_CSR_WRITE32_IN_LEN(num) (8+4*(num)) +#define MC_CMD_CSR_WRITE32_IN_ADDR_OFST 0 +#define MC_CMD_CSR_WRITE32_IN_STEP_OFST 4 +#define MC_CMD_CSR_WRITE32_IN_BUFFER_OFST 8 +#define MC_CMD_CSR_WRITE32_IN_BUFFER_LEN 4 +#define MC_CMD_CSR_WRITE32_IN_BUFFER_MINNUM 1 +#define MC_CMD_CSR_WRITE32_IN_BUFFER_MAXNUM 61 + +/* MC_CMD_CSR_WRITE32_OUT msgresponse */ +#define MC_CMD_CSR_WRITE32_OUT_LEN 4 +#define MC_CMD_CSR_WRITE32_OUT_STATUS_OFST 0 + + +/***********************************/ +/* MC_CMD_STACKINFO + * Get stack information. + */ +#define MC_CMD_STACKINFO 0xf + +/* MC_CMD_STACKINFO_IN msgrequest */ +#define MC_CMD_STACKINFO_IN_LEN 0 + +/* MC_CMD_STACKINFO_OUT msgresponse */ +#define MC_CMD_STACKINFO_OUT_LENMIN 12 +#define MC_CMD_STACKINFO_OUT_LENMAX 252 +#define MC_CMD_STACKINFO_OUT_LEN(num) (0+12*(num)) +#define MC_CMD_STACKINFO_OUT_THREAD_INFO_OFST 0 +#define MC_CMD_STACKINFO_OUT_THREAD_INFO_LEN 12 +#define MC_CMD_STACKINFO_OUT_THREAD_INFO_MINNUM 1 +#define MC_CMD_STACKINFO_OUT_THREAD_INFO_MAXNUM 21 + + +/***********************************/ +/* MC_CMD_MDIO_READ + * MDIO register read. */ #define MC_CMD_MDIO_READ 0x10 -#define MC_CMD_MDIO_READ_IN_LEN 16 -#define MC_CMD_MDIO_READ_IN_BUS_OFST 0 -#define MC_CMD_MDIO_READ_IN_PRTAD_OFST 4 -#define MC_CMD_MDIO_READ_IN_DEVAD_OFST 8 -#define MC_CMD_MDIO_READ_IN_ADDR_OFST 12 -#define MC_CMD_MDIO_READ_OUT_LEN 8 -#define MC_CMD_MDIO_READ_OUT_VALUE_OFST 0 -#define MC_CMD_MDIO_READ_OUT_STATUS_OFST 4 - -/* MC_CMD_MDIO_WRITE: - * MDIO register write - */ -#define MC_CMD_MDIO_WRITE 0x11 -#define MC_CMD_MDIO_WRITE_IN_LEN 20 -#define MC_CMD_MDIO_WRITE_IN_BUS_OFST 0 -#define MC_CMD_MDIO_WRITE_IN_PRTAD_OFST 4 -#define MC_CMD_MDIO_WRITE_IN_DEVAD_OFST 8 -#define MC_CMD_MDIO_WRITE_IN_ADDR_OFST 12 -#define MC_CMD_MDIO_WRITE_IN_VALUE_OFST 16 -#define MC_CMD_MDIO_WRITE_OUT_LEN 4 -#define MC_CMD_MDIO_WRITE_OUT_STATUS_OFST 0 -/* By default all the MCDI MDIO operations perform clause45 mode. - * If you want to use clause22 then set DEVAD = MC_CMD_MDIO_CLAUSE22. - */ -#define MC_CMD_MDIO_CLAUSE22 32 +/* MC_CMD_MDIO_READ_IN msgrequest */ +#define MC_CMD_MDIO_READ_IN_LEN 16 +#define MC_CMD_MDIO_READ_IN_BUS_OFST 0 +#define MC_CMD_MDIO_BUS_INTERNAL 0x0 /* enum */ +#define MC_CMD_MDIO_BUS_EXTERNAL 0x1 /* enum */ +#define MC_CMD_MDIO_READ_IN_PRTAD_OFST 4 +#define MC_CMD_MDIO_READ_IN_DEVAD_OFST 8 +#define MC_CMD_MDIO_CLAUSE22 0x20 /* enum */ +#define MC_CMD_MDIO_READ_IN_ADDR_OFST 12 -/* There are two MDIO buses: one for the internal PHY, and one for external - * devices. - */ -#define MC_CMD_MDIO_BUS_INTERNAL 0 -#define MC_CMD_MDIO_BUS_EXTERNAL 1 +/* MC_CMD_MDIO_READ_OUT msgresponse */ +#define MC_CMD_MDIO_READ_OUT_LEN 8 +#define MC_CMD_MDIO_READ_OUT_VALUE_OFST 0 +#define MC_CMD_MDIO_READ_OUT_STATUS_OFST 4 +#define MC_CMD_MDIO_STATUS_GOOD 0x8 /* enum */ -/* The MDIO commands return the raw status bits from the MDIO block. A "good" - * transaction should have the DONE bit set and all other bits clear. + +/***********************************/ +/* MC_CMD_MDIO_WRITE + * MDIO register write. */ -#define MC_CMD_MDIO_STATUS_GOOD 0x08 +#define MC_CMD_MDIO_WRITE 0x11 +/* MC_CMD_MDIO_WRITE_IN msgrequest */ +#define MC_CMD_MDIO_WRITE_IN_LEN 20 +#define MC_CMD_MDIO_WRITE_IN_BUS_OFST 0 +/* MC_CMD_MDIO_BUS_INTERNAL 0x0 */ +/* MC_CMD_MDIO_BUS_EXTERNAL 0x1 */ +#define MC_CMD_MDIO_WRITE_IN_PRTAD_OFST 4 +#define MC_CMD_MDIO_WRITE_IN_DEVAD_OFST 8 +/* MC_CMD_MDIO_CLAUSE22 0x20 */ +#define MC_CMD_MDIO_WRITE_IN_ADDR_OFST 12 +#define MC_CMD_MDIO_WRITE_IN_VALUE_OFST 16 -/* MC_CMD_DBI_WRITE: (debug) - * Write DBI register(s) - * - * Host: address, byte-enables (and VF selection, and cs2 flag), - * value [,address ...] - * MC: nothing +/* MC_CMD_MDIO_WRITE_OUT msgresponse */ +#define MC_CMD_MDIO_WRITE_OUT_LEN 4 +#define MC_CMD_MDIO_WRITE_OUT_STATUS_OFST 0 +/* MC_CMD_MDIO_STATUS_GOOD 0x8 */ + + +/***********************************/ +/* MC_CMD_DBI_WRITE + * Write DBI register(s). */ #define MC_CMD_DBI_WRITE 0x12 -#define MC_CMD_DBI_WRITE_IN_LEN(_numwords) \ - (12 * (_numwords)) -#define MC_CMD_DBI_WRITE_IN_ADDRESS_OFST(_word) \ - (((_word) * 12) + 0) -#define MC_CMD_DBI_WRITE_IN_BYTE_MASK_OFST(_word) \ - (((_word) * 12) + 4) -#define MC_CMD_DBI_WRITE_IN_VALUE_OFST(_word) \ - (((_word) * 12) + 8) -#define MC_CMD_DBI_WRITE_OUT_LEN 0 - -/* MC_CMD_DBI_READ: (debug) - * Read DBI register(s) - * - * Host: address, [,address ...] - * MC: value [,value ...] - * (note: this does not support reading from VFs, but is retained for backwards - * compatibility; see MC_CMD_DBI_READX below) - */ -#define MC_CMD_DBI_READ 0x13 -#define MC_CMD_DBI_READ_IN_LEN(_numwords) \ - (4 * (_numwords)) -#define MC_CMD_DBI_READ_OUT_LEN(_numwords) \ - (4 * (_numwords)) - -/* MC_CMD_PORT_READ32: (debug) + +/* MC_CMD_DBI_WRITE_IN msgrequest */ +#define MC_CMD_DBI_WRITE_IN_LENMIN 12 +#define MC_CMD_DBI_WRITE_IN_LENMAX 252 +#define MC_CMD_DBI_WRITE_IN_LEN(num) (0+12*(num)) +#define MC_CMD_DBI_WRITE_IN_DBIWROP_OFST 0 +#define MC_CMD_DBI_WRITE_IN_DBIWROP_LEN 12 +#define MC_CMD_DBI_WRITE_IN_DBIWROP_MINNUM 1 +#define MC_CMD_DBI_WRITE_IN_DBIWROP_MAXNUM 21 + +/* MC_CMD_DBI_WRITE_OUT msgresponse */ +#define MC_CMD_DBI_WRITE_OUT_LEN 0 + +/* MC_CMD_DBIWROP_TYPEDEF structuredef */ +#define MC_CMD_DBIWROP_TYPEDEF_LEN 12 +#define MC_CMD_DBIWROP_TYPEDEF_ADDRESS_OFST 0 +#define MC_CMD_DBIWROP_TYPEDEF_ADDRESS_LBN 0 +#define MC_CMD_DBIWROP_TYPEDEF_ADDRESS_WIDTH 32 +#define MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_OFST 4 +#define MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_LBN 32 +#define MC_CMD_DBIWROP_TYPEDEF_BYTE_MASK_WIDTH 32 +#define MC_CMD_DBIWROP_TYPEDEF_VALUE_OFST 8 +#define MC_CMD_DBIWROP_TYPEDEF_VALUE_LBN 64 +#define MC_CMD_DBIWROP_TYPEDEF_VALUE_WIDTH 32 + + +/***********************************/ +/* MC_CMD_PORT_READ32 * Read a 32-bit register from the indirect port register map. - * - * The port to access is implied by the Shared memory channel used. */ #define MC_CMD_PORT_READ32 0x14 -#define MC_CMD_PORT_READ32_IN_LEN 4 -#define MC_CMD_PORT_READ32_IN_ADDR_OFST 0 -#define MC_CMD_PORT_READ32_OUT_LEN 8 -#define MC_CMD_PORT_READ32_OUT_VALUE_OFST 0 -#define MC_CMD_PORT_READ32_OUT_STATUS_OFST 4 -/* MC_CMD_PORT_WRITE32: (debug) +/* MC_CMD_PORT_READ32_IN msgrequest */ +#define MC_CMD_PORT_READ32_IN_LEN 4 +#define MC_CMD_PORT_READ32_IN_ADDR_OFST 0 + +/* MC_CMD_PORT_READ32_OUT msgresponse */ +#define MC_CMD_PORT_READ32_OUT_LEN 8 +#define MC_CMD_PORT_READ32_OUT_VALUE_OFST 0 +#define MC_CMD_PORT_READ32_OUT_STATUS_OFST 4 + + +/***********************************/ +/* MC_CMD_PORT_WRITE32 * Write a 32-bit register to the indirect port register map. - * - * The port to access is implied by the Shared memory channel used. */ #define MC_CMD_PORT_WRITE32 0x15 -#define MC_CMD_PORT_WRITE32_IN_LEN 8 -#define MC_CMD_PORT_WRITE32_IN_ADDR_OFST 0 -#define MC_CMD_PORT_WRITE32_IN_VALUE_OFST 4 -#define MC_CMD_PORT_WRITE32_OUT_LEN 4 -#define MC_CMD_PORT_WRITE32_OUT_STATUS_OFST 0 - -/* MC_CMD_PORT_READ128: (debug) - * Read a 128-bit register from indirect port register map - * - * The port to access is implied by the Shared memory channel used. + +/* MC_CMD_PORT_WRITE32_IN msgrequest */ +#define MC_CMD_PORT_WRITE32_IN_LEN 8 +#define MC_CMD_PORT_WRITE32_IN_ADDR_OFST 0 +#define MC_CMD_PORT_WRITE32_IN_VALUE_OFST 4 + +/* MC_CMD_PORT_WRITE32_OUT msgresponse */ +#define MC_CMD_PORT_WRITE32_OUT_LEN 4 +#define MC_CMD_PORT_WRITE32_OUT_STATUS_OFST 0 + + +/***********************************/ +/* MC_CMD_PORT_READ128 + * Read a 128-bit register from the indirect port register map. */ #define MC_CMD_PORT_READ128 0x16 -#define MC_CMD_PORT_READ128_IN_LEN 4 -#define MC_CMD_PORT_READ128_IN_ADDR_OFST 0 -#define MC_CMD_PORT_READ128_OUT_LEN 20 -#define MC_CMD_PORT_READ128_OUT_VALUE_OFST 0 -#define MC_CMD_PORT_READ128_OUT_STATUS_OFST 16 - -/* MC_CMD_PORT_WRITE128: (debug) - * Write a 128-bit register to indirect port register map. - * - * The port to access is implied by the Shared memory channel used. + +/* MC_CMD_PORT_READ128_IN msgrequest */ +#define MC_CMD_PORT_READ128_IN_LEN 4 +#define MC_CMD_PORT_READ128_IN_ADDR_OFST 0 + +/* MC_CMD_PORT_READ128_OUT msgresponse */ +#define MC_CMD_PORT_READ128_OUT_LEN 20 +#define MC_CMD_PORT_READ128_OUT_VALUE_OFST 0 +#define MC_CMD_PORT_READ128_OUT_VALUE_LEN 16 +#define MC_CMD_PORT_READ128_OUT_STATUS_OFST 16 + + +/***********************************/ +/* MC_CMD_PORT_WRITE128 + * Write a 128-bit register to the indirect port register map. */ #define MC_CMD_PORT_WRITE128 0x17 -#define MC_CMD_PORT_WRITE128_IN_LEN 20 -#define MC_CMD_PORT_WRITE128_IN_ADDR_OFST 0 -#define MC_CMD_PORT_WRITE128_IN_VALUE_OFST 4 -#define MC_CMD_PORT_WRITE128_OUT_LEN 4 -#define MC_CMD_PORT_WRITE128_OUT_STATUS_OFST 0 - -/* MC_CMD_GET_BOARD_CFG: - * Returns the MC firmware configuration structure - * - * The FW_SUBTYPE_LIST contains a 16-bit value for each of the 12 types of - * NVRAM area. The values are defined in the firmware/mc/platform/.c file - * for a specific board type, but otherwise have no meaning to the MC; they - * are used by the driver to manage selection of appropriate firmware updates. + +/* MC_CMD_PORT_WRITE128_IN msgrequest */ +#define MC_CMD_PORT_WRITE128_IN_LEN 20 +#define MC_CMD_PORT_WRITE128_IN_ADDR_OFST 0 +#define MC_CMD_PORT_WRITE128_IN_VALUE_OFST 4 +#define MC_CMD_PORT_WRITE128_IN_VALUE_LEN 16 + +/* MC_CMD_PORT_WRITE128_OUT msgresponse */ +#define MC_CMD_PORT_WRITE128_OUT_LEN 4 +#define MC_CMD_PORT_WRITE128_OUT_STATUS_OFST 0 + + +/***********************************/ +/* MC_CMD_GET_BOARD_CFG + * Returns the MC firmware configuration structure. */ #define MC_CMD_GET_BOARD_CFG 0x18 -#define MC_CMD_GET_BOARD_CFG_IN_LEN 0 -#define MC_CMD_GET_BOARD_CFG_OUT_LEN 96 -#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_TYPE_OFST 0 -#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_OFST 4 -#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_LEN 32 -#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT0_OFST 36 -#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT1_OFST 40 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST 44 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_LEN 6 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST 50 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_LEN 6 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT0_OFST 56 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT1_OFST 60 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT0_OFST 64 -#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT1_OFST 68 -#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST 72 -#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN 24 - -/* MC_CMD_DBI_READX: (debug) - * Read DBI register(s) -- extended functionality - * - * Host: vf selection, address, [,vf selection ...] - * MC: value [,value ...] + +/* MC_CMD_GET_BOARD_CFG_IN msgrequest */ +#define MC_CMD_GET_BOARD_CFG_IN_LEN 0 + +/* MC_CMD_GET_BOARD_CFG_OUT msgresponse */ +#define MC_CMD_GET_BOARD_CFG_OUT_LENMIN 96 +#define MC_CMD_GET_BOARD_CFG_OUT_LENMAX 136 +#define MC_CMD_GET_BOARD_CFG_OUT_LEN(num) (72+2*(num)) +#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_TYPE_OFST 0 +#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_OFST 4 +#define MC_CMD_GET_BOARD_CFG_OUT_BOARD_NAME_LEN 32 +#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT0_OFST 36 +#define MC_CMD_CAPABILITIES_SMALL_BUF_TBL_LBN 0x0 /* enum */ +#define MC_CMD_CAPABILITIES_SMALL_BUF_TBL_WIDTH 0x1 /* enum */ +#define MC_CMD_CAPABILITIES_TURBO_LBN 0x1 /* enum */ +#define MC_CMD_CAPABILITIES_TURBO_WIDTH 0x1 /* enum */ +#define MC_CMD_CAPABILITIES_TURBO_ACTIVE_LBN 0x2 /* enum */ +#define MC_CMD_CAPABILITIES_TURBO_ACTIVE_WIDTH 0x1 /* enum */ +#define MC_CMD_CAPABILITIES_PTP_LBN 0x3 /* enum */ +#define MC_CMD_CAPABILITIES_PTP_WIDTH 0x1 /* enum */ +#define MC_CMD_GET_BOARD_CFG_OUT_CAPABILITIES_PORT1_OFST 40 +/* Enum values, see field(s): */ +/* CAPABILITIES_PORT0 */ +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST 44 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_LEN 6 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_OFST 50 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT1_LEN 6 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT0_OFST 56 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_COUNT_PORT1_OFST 60 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT0_OFST 64 +#define MC_CMD_GET_BOARD_CFG_OUT_MAC_STRIDE_PORT1_OFST 68 +#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST 72 +#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN 2 +#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM 12 +#define MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MAXNUM 32 + + +/***********************************/ +/* MC_CMD_DBI_READX + * Read DBI register(s). */ #define MC_CMD_DBI_READX 0x19 -#define MC_CMD_DBI_READX_IN_LEN(_numwords) \ - (8*(_numwords)) -#define MC_CMD_DBI_READX_OUT_LEN(_numwords) \ - (4*(_numwords)) -/* MC_CMD_SET_RAND_SEED: - * Set the 16byte seed for the MC pseudo-random generator +/* MC_CMD_DBI_READX_IN msgrequest */ +#define MC_CMD_DBI_READX_IN_LENMIN 8 +#define MC_CMD_DBI_READX_IN_LENMAX 248 +#define MC_CMD_DBI_READX_IN_LEN(num) (0+8*(num)) +#define MC_CMD_DBI_READX_IN_DBIRDOP_OFST 0 +#define MC_CMD_DBI_READX_IN_DBIRDOP_LEN 8 +#define MC_CMD_DBI_READX_IN_DBIRDOP_LO_OFST 0 +#define MC_CMD_DBI_READX_IN_DBIRDOP_HI_OFST 4 +#define MC_CMD_DBI_READX_IN_DBIRDOP_MINNUM 1 +#define MC_CMD_DBI_READX_IN_DBIRDOP_MAXNUM 31 + +/* MC_CMD_DBI_READX_OUT msgresponse */ +#define MC_CMD_DBI_READX_OUT_LENMIN 4 +#define MC_CMD_DBI_READX_OUT_LENMAX 252 +#define MC_CMD_DBI_READX_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_DBI_READX_OUT_VALUE_OFST 0 +#define MC_CMD_DBI_READX_OUT_VALUE_LEN 4 +#define MC_CMD_DBI_READX_OUT_VALUE_MINNUM 1 +#define MC_CMD_DBI_READX_OUT_VALUE_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_SET_RAND_SEED + * Set the 16byte seed for the MC pseudo-random generator. */ #define MC_CMD_SET_RAND_SEED 0x1a -#define MC_CMD_SET_RAND_SEED_IN_LEN 16 -#define MC_CMD_SET_RAND_SEED_IN_SEED_OFST 0 -#define MC_CMD_SET_RAND_SEED_OUT_LEN 0 -/* MC_CMD_LTSSM_HIST: (debug) - * Retrieve the history of the LTSSM, if the build supports it. - * - * Host: nothing - * MC: variable number of LTSSM values, as bytes - * The history is read-to-clear. +/* MC_CMD_SET_RAND_SEED_IN msgrequest */ +#define MC_CMD_SET_RAND_SEED_IN_LEN 16 +#define MC_CMD_SET_RAND_SEED_IN_SEED_OFST 0 +#define MC_CMD_SET_RAND_SEED_IN_SEED_LEN 16 + +/* MC_CMD_SET_RAND_SEED_OUT msgresponse */ +#define MC_CMD_SET_RAND_SEED_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_LTSSM_HIST + * Retrieve the history of the PCIE LTSSM. */ #define MC_CMD_LTSSM_HIST 0x1b -/* MC_CMD_DRV_ATTACH: - * Inform MCPU that this port is managed on the host (i.e. driver active) +/* MC_CMD_LTSSM_HIST_IN msgrequest */ +#define MC_CMD_LTSSM_HIST_IN_LEN 0 + +/* MC_CMD_LTSSM_HIST_OUT msgresponse */ +#define MC_CMD_LTSSM_HIST_OUT_LENMIN 0 +#define MC_CMD_LTSSM_HIST_OUT_LENMAX 252 +#define MC_CMD_LTSSM_HIST_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_LTSSM_HIST_OUT_DATA_OFST 0 +#define MC_CMD_LTSSM_HIST_OUT_DATA_LEN 4 +#define MC_CMD_LTSSM_HIST_OUT_DATA_MINNUM 0 +#define MC_CMD_LTSSM_HIST_OUT_DATA_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_DRV_ATTACH + * Inform MCPU that this port is managed on the host. */ #define MC_CMD_DRV_ATTACH 0x1c -#define MC_CMD_DRV_ATTACH_IN_LEN 8 -#define MC_CMD_DRV_ATTACH_IN_NEW_STATE_OFST 0 -#define MC_CMD_DRV_ATTACH_IN_UPDATE_OFST 4 -#define MC_CMD_DRV_ATTACH_OUT_LEN 4 -#define MC_CMD_DRV_ATTACH_OUT_OLD_STATE_OFST 0 -/* MC_CMD_NCSI_PROD: (debug) - * Trigger an NC-SI event (and possibly an AEN in response) +/* MC_CMD_DRV_ATTACH_IN msgrequest */ +#define MC_CMD_DRV_ATTACH_IN_LEN 8 +#define MC_CMD_DRV_ATTACH_IN_NEW_STATE_OFST 0 +#define MC_CMD_DRV_ATTACH_IN_UPDATE_OFST 4 + +/* MC_CMD_DRV_ATTACH_OUT msgresponse */ +#define MC_CMD_DRV_ATTACH_OUT_LEN 4 +#define MC_CMD_DRV_ATTACH_OUT_OLD_STATE_OFST 0 + + +/***********************************/ +/* MC_CMD_NCSI_PROD + * Trigger an NC-SI event. */ #define MC_CMD_NCSI_PROD 0x1d -#define MC_CMD_NCSI_PROD_IN_LEN 4 -#define MC_CMD_NCSI_PROD_IN_EVENTS_OFST 0 -#define MC_CMD_NCSI_PROD_LINKCHANGE_LBN 0 -#define MC_CMD_NCSI_PROD_LINKCHANGE_WIDTH 1 -#define MC_CMD_NCSI_PROD_RESET_LBN 1 -#define MC_CMD_NCSI_PROD_RESET_WIDTH 1 -#define MC_CMD_NCSI_PROD_DRVATTACH_LBN 2 -#define MC_CMD_NCSI_PROD_DRVATTACH_WIDTH 1 -#define MC_CMD_NCSI_PROD_OUT_LEN 0 - -/* Enumeration */ -#define MC_CMD_NCSI_PROD_LINKCHANGE 0 -#define MC_CMD_NCSI_PROD_RESET 1 -#define MC_CMD_NCSI_PROD_DRVATTACH 2 - -/* MC_CMD_DEVEL: (debug) - * Reserved for development - */ -#define MC_CMD_DEVEL 0x1e - -/* MC_CMD_SHMUART: (debug) + +/* MC_CMD_NCSI_PROD_IN msgrequest */ +#define MC_CMD_NCSI_PROD_IN_LEN 4 +#define MC_CMD_NCSI_PROD_IN_EVENTS_OFST 0 +#define MC_CMD_NCSI_PROD_LINKCHANGE 0x0 /* enum */ +#define MC_CMD_NCSI_PROD_RESET 0x1 /* enum */ +#define MC_CMD_NCSI_PROD_DRVATTACH 0x2 /* enum */ +#define MC_CMD_NCSI_PROD_IN_LINKCHANGE_LBN 0 +#define MC_CMD_NCSI_PROD_IN_LINKCHANGE_WIDTH 1 +#define MC_CMD_NCSI_PROD_IN_RESET_LBN 1 +#define MC_CMD_NCSI_PROD_IN_RESET_WIDTH 1 +#define MC_CMD_NCSI_PROD_IN_DRVATTACH_LBN 2 +#define MC_CMD_NCSI_PROD_IN_DRVATTACH_WIDTH 1 + +/* MC_CMD_NCSI_PROD_OUT msgresponse */ +#define MC_CMD_NCSI_PROD_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SHMUART * Route UART output to circular buffer in shared memory instead. */ #define MC_CMD_SHMUART 0x1f -#define MC_CMD_SHMUART_IN_FLAG_OFST 0 -#define MC_CMD_SHMUART_IN_LEN 4 -#define MC_CMD_SHMUART_OUT_LEN 0 -/* MC_CMD_PORT_RESET: - * Generic per-port reset. There is no equivalent for per-board reset. - * - * Locks required: None - * Return code: 0, ETIME - */ -#define MC_CMD_PORT_RESET 0x20 -#define MC_CMD_PORT_RESET_IN_LEN 0 -#define MC_CMD_PORT_RESET_OUT_LEN 0 - -/* MC_CMD_RESOURCE_LOCK: - * Generic resource lock/unlock interface. - * - * Locks required: None - * Return code: 0, - * EBUSY (if trylock is contended by other port), - * EDEADLK (if trylock is already acquired by this port) - * EINVAL (if unlock doesn't own the lock) - */ -#define MC_CMD_RESOURCE_LOCK 0x21 -#define MC_CMD_RESOURCE_LOCK_IN_LEN 8 -#define MC_CMD_RESOURCE_LOCK_IN_ACTION_OFST 0 -#define MC_CMD_RESOURCE_LOCK_ACTION_TRYLOCK 1 -#define MC_CMD_RESOURCE_LOCK_ACTION_UNLOCK 0 -#define MC_CMD_RESOURCE_LOCK_IN_RESOURCE_OFST 4 -#define MC_CMD_RESOURCE_LOCK_I2C 2 -#define MC_CMD_RESOURCE_LOCK_PHY 3 -#define MC_CMD_RESOURCE_LOCK_OUT_LEN 0 - -/* MC_CMD_SPI_COMMAND: (variadic in, variadic out) - * Read/Write to/from the SPI device. - * - * Locks required: SPI_LOCK - * Return code: 0, ETIME, EINVAL, EACCES (if SPI_LOCK is not held) - */ -#define MC_CMD_SPI_COMMAND 0x22 -#define MC_CMD_SPI_COMMAND_IN_LEN(_write_bytes) (12 + (_write_bytes)) -#define MC_CMD_SPI_COMMAND_IN_ARGS_OFST 0 -#define MC_CMD_SPI_COMMAND_IN_ARGS_ADDRESS_OFST 0 -#define MC_CMD_SPI_COMMAND_IN_ARGS_READ_BYTES_OFST 4 -#define MC_CMD_SPI_COMMAND_IN_ARGS_CHIP_SELECT_OFST 8 -/* Data to write here */ -#define MC_CMD_SPI_COMMAND_IN_WRITE_BUFFER_OFST 12 -#define MC_CMD_SPI_COMMAND_OUT_LEN(_read_bytes) (_read_bytes) -/* Data read here */ -#define MC_CMD_SPI_COMMAND_OUT_READ_BUFFER_OFST 0 - -/* MC_CMD_I2C_READ_WRITE: (variadic in, variadic out) - * Read/Write to/from the I2C bus. - * - * Locks required: I2C_LOCK - * Return code: 0, ETIME, EINVAL, EACCES (if I2C_LOCK is not held) - */ -#define MC_CMD_I2C_RW 0x23 -#define MC_CMD_I2C_RW_IN_LEN(_write_bytes) (8 + (_write_bytes)) -#define MC_CMD_I2C_RW_IN_ARGS_OFST 0 -#define MC_CMD_I2C_RW_IN_ARGS_ADDR_OFST 0 -#define MC_CMD_I2C_RW_IN_ARGS_READ_BYTES_OFST 4 -/* Data to write here */ -#define MC_CMD_I2C_RW_IN_WRITE_BUFFER_OFSET 8 -#define MC_CMD_I2C_RW_OUT_LEN(_read_bytes) (_read_bytes) -/* Data read here */ -#define MC_CMD_I2C_RW_OUT_READ_BUFFER_OFST 0 - -/* Generic phy capability bitmask */ -#define MC_CMD_PHY_CAP_10HDX_LBN 1 -#define MC_CMD_PHY_CAP_10HDX_WIDTH 1 -#define MC_CMD_PHY_CAP_10FDX_LBN 2 -#define MC_CMD_PHY_CAP_10FDX_WIDTH 1 -#define MC_CMD_PHY_CAP_100HDX_LBN 3 -#define MC_CMD_PHY_CAP_100HDX_WIDTH 1 -#define MC_CMD_PHY_CAP_100FDX_LBN 4 -#define MC_CMD_PHY_CAP_100FDX_WIDTH 1 -#define MC_CMD_PHY_CAP_1000HDX_LBN 5 -#define MC_CMD_PHY_CAP_1000HDX_WIDTH 1 -#define MC_CMD_PHY_CAP_1000FDX_LBN 6 -#define MC_CMD_PHY_CAP_1000FDX_WIDTH 1 -#define MC_CMD_PHY_CAP_10000FDX_LBN 7 -#define MC_CMD_PHY_CAP_10000FDX_WIDTH 1 -#define MC_CMD_PHY_CAP_PAUSE_LBN 8 -#define MC_CMD_PHY_CAP_PAUSE_WIDTH 1 -#define MC_CMD_PHY_CAP_ASYM_LBN 9 -#define MC_CMD_PHY_CAP_ASYM_WIDTH 1 -#define MC_CMD_PHY_CAP_AN_LBN 10 -#define MC_CMD_PHY_CAP_AN_WIDTH 1 - -/* Generic loopback enumeration */ -#define MC_CMD_LOOPBACK_NONE 0 -#define MC_CMD_LOOPBACK_DATA 1 -#define MC_CMD_LOOPBACK_GMAC 2 -#define MC_CMD_LOOPBACK_XGMII 3 -#define MC_CMD_LOOPBACK_XGXS 4 -#define MC_CMD_LOOPBACK_XAUI 5 -#define MC_CMD_LOOPBACK_GMII 6 -#define MC_CMD_LOOPBACK_SGMII 7 -#define MC_CMD_LOOPBACK_XGBR 8 -#define MC_CMD_LOOPBACK_XFI 9 -#define MC_CMD_LOOPBACK_XAUI_FAR 10 -#define MC_CMD_LOOPBACK_GMII_FAR 11 -#define MC_CMD_LOOPBACK_SGMII_FAR 12 -#define MC_CMD_LOOPBACK_XFI_FAR 13 -#define MC_CMD_LOOPBACK_GPHY 14 -#define MC_CMD_LOOPBACK_PHYXS 15 -#define MC_CMD_LOOPBACK_PCS 16 -#define MC_CMD_LOOPBACK_PMAPMD 17 -#define MC_CMD_LOOPBACK_XPORT 18 -#define MC_CMD_LOOPBACK_XGMII_WS 19 -#define MC_CMD_LOOPBACK_XAUI_WS 20 -#define MC_CMD_LOOPBACK_XAUI_WS_FAR 21 -#define MC_CMD_LOOPBACK_XAUI_WS_NEAR 22 -#define MC_CMD_LOOPBACK_GMII_WS 23 -#define MC_CMD_LOOPBACK_XFI_WS 24 -#define MC_CMD_LOOPBACK_XFI_WS_FAR 25 -#define MC_CMD_LOOPBACK_PHYXS_WS 26 - -/* Generic PHY statistics enumeration */ -#define MC_CMD_OUI 0 -#define MC_CMD_PMA_PMD_LINK_UP 1 -#define MC_CMD_PMA_PMD_RX_FAULT 2 -#define MC_CMD_PMA_PMD_TX_FAULT 3 -#define MC_CMD_PMA_PMD_SIGNAL 4 -#define MC_CMD_PMA_PMD_SNR_A 5 -#define MC_CMD_PMA_PMD_SNR_B 6 -#define MC_CMD_PMA_PMD_SNR_C 7 -#define MC_CMD_PMA_PMD_SNR_D 8 -#define MC_CMD_PCS_LINK_UP 9 -#define MC_CMD_PCS_RX_FAULT 10 -#define MC_CMD_PCS_TX_FAULT 11 -#define MC_CMD_PCS_BER 12 -#define MC_CMD_PCS_BLOCK_ERRORS 13 -#define MC_CMD_PHYXS_LINK_UP 14 -#define MC_CMD_PHYXS_RX_FAULT 15 -#define MC_CMD_PHYXS_TX_FAULT 16 -#define MC_CMD_PHYXS_ALIGN 17 -#define MC_CMD_PHYXS_SYNC 18 -#define MC_CMD_AN_LINK_UP 19 -#define MC_CMD_AN_COMPLETE 20 -#define MC_CMD_AN_10GBT_STATUS 21 -#define MC_CMD_CL22_LINK_UP 22 -#define MC_CMD_PHY_NSTATS 23 - -/* MC_CMD_GET_PHY_CFG: - * Report PHY configuration. This guarantees to succeed even if the PHY is in - * a "zombie" state. - * - * Locks required: None - * Return code: 0 +/* MC_CMD_SHMUART_IN msgrequest */ +#define MC_CMD_SHMUART_IN_LEN 4 +#define MC_CMD_SHMUART_IN_FLAG_OFST 0 + +/* MC_CMD_SHMUART_OUT msgresponse */ +#define MC_CMD_SHMUART_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_ENTITY_RESET + * Generic per-port reset. + */ +#define MC_CMD_ENTITY_RESET 0x20 + +/* MC_CMD_ENTITY_RESET_IN msgrequest */ +#define MC_CMD_ENTITY_RESET_IN_LEN 4 +#define MC_CMD_ENTITY_RESET_IN_FLAG_OFST 0 +#define MC_CMD_ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET_LBN 0 +#define MC_CMD_ENTITY_RESET_IN_FUNCTION_RESOURCE_RESET_WIDTH 1 + +/* MC_CMD_ENTITY_RESET_OUT msgresponse */ +#define MC_CMD_ENTITY_RESET_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_PCIE_CREDITS + * Read instantaneous and minimum flow control thresholds. + */ +#define MC_CMD_PCIE_CREDITS 0x21 + +/* MC_CMD_PCIE_CREDITS_IN msgrequest */ +#define MC_CMD_PCIE_CREDITS_IN_LEN 8 +#define MC_CMD_PCIE_CREDITS_IN_POLL_PERIOD_OFST 0 +#define MC_CMD_PCIE_CREDITS_IN_WIPE_OFST 4 + +/* MC_CMD_PCIE_CREDITS_OUT msgresponse */ +#define MC_CMD_PCIE_CREDITS_OUT_LEN 16 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_HDR_OFST 0 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_HDR_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_DATA_OFST 2 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_P_DATA_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_HDR_OFST 4 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_HDR_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_DATA_OFST 6 +#define MC_CMD_PCIE_CREDITS_OUT_CURRENT_NP_DATA_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_HDR_OFST 8 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_HDR_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_DATA_OFST 10 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_P_DATA_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_HDR_OFST 12 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_HDR_LEN 2 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_DATA_OFST 14 +#define MC_CMD_PCIE_CREDITS_OUT_MINIMUM_NP_DATA_LEN 2 + + +/***********************************/ +/* MC_CMD_RXD_MONITOR + * Get histogram of RX queue fill level. + */ +#define MC_CMD_RXD_MONITOR 0x22 + +/* MC_CMD_RXD_MONITOR_IN msgrequest */ +#define MC_CMD_RXD_MONITOR_IN_LEN 12 +#define MC_CMD_RXD_MONITOR_IN_QID_OFST 0 +#define MC_CMD_RXD_MONITOR_IN_POLL_PERIOD_OFST 4 +#define MC_CMD_RXD_MONITOR_IN_WIPE_OFST 8 + +/* MC_CMD_RXD_MONITOR_OUT msgresponse */ +#define MC_CMD_RXD_MONITOR_OUT_LEN 80 +#define MC_CMD_RXD_MONITOR_OUT_QID_OFST 0 +#define MC_CMD_RXD_MONITOR_OUT_RING_FILL_OFST 4 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_FILL_OFST 8 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_1_OFST 12 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_2_OFST 16 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_4_OFST 20 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_8_OFST 24 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_16_OFST 28 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_32_OFST 32 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_64_OFST 36 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_128_OFST 40 +#define MC_CMD_RXD_MONITOR_OUT_RING_LT_256_OFST 44 +#define MC_CMD_RXD_MONITOR_OUT_RING_GE_256_OFST 48 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_1_OFST 52 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_2_OFST 56 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_4_OFST 60 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_8_OFST 64 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_16_OFST 68 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_LT_32_OFST 72 +#define MC_CMD_RXD_MONITOR_OUT_CACHE_GE_32_OFST 76 + + +/***********************************/ +/* MC_CMD_PUTS + * puts(3) implementation over MCDI + */ +#define MC_CMD_PUTS 0x23 + +/* MC_CMD_PUTS_IN msgrequest */ +#define MC_CMD_PUTS_IN_LENMIN 13 +#define MC_CMD_PUTS_IN_LENMAX 255 +#define MC_CMD_PUTS_IN_LEN(num) (12+1*(num)) +#define MC_CMD_PUTS_IN_DEST_OFST 0 +#define MC_CMD_PUTS_IN_UART_LBN 0 +#define MC_CMD_PUTS_IN_UART_WIDTH 1 +#define MC_CMD_PUTS_IN_PORT_LBN 1 +#define MC_CMD_PUTS_IN_PORT_WIDTH 1 +#define MC_CMD_PUTS_IN_DHOST_OFST 4 +#define MC_CMD_PUTS_IN_DHOST_LEN 6 +#define MC_CMD_PUTS_IN_STRING_OFST 12 +#define MC_CMD_PUTS_IN_STRING_LEN 1 +#define MC_CMD_PUTS_IN_STRING_MINNUM 1 +#define MC_CMD_PUTS_IN_STRING_MAXNUM 243 + +/* MC_CMD_PUTS_OUT msgresponse */ +#define MC_CMD_PUTS_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_PHY_CFG + * Report PHY configuration. */ #define MC_CMD_GET_PHY_CFG 0x24 -#define MC_CMD_GET_PHY_CFG_IN_LEN 0 -#define MC_CMD_GET_PHY_CFG_OUT_LEN 72 - -#define MC_CMD_GET_PHY_CFG_OUT_FLAGS_OFST 0 -#define MC_CMD_GET_PHY_CFG_PRESENT_LBN 0 -#define MC_CMD_GET_PHY_CFG_PRESENT_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN 1 -#define MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN 2 -#define MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_LOWPOWER_LBN 3 -#define MC_CMD_GET_PHY_CFG_LOWPOWER_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_POWEROFF_LBN 4 -#define MC_CMD_GET_PHY_CFG_POWEROFF_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_TXDIS_LBN 5 -#define MC_CMD_GET_PHY_CFG_TXDIS_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_BIST_LBN 6 -#define MC_CMD_GET_PHY_CFG_BIST_WIDTH 1 -#define MC_CMD_GET_PHY_CFG_OUT_TYPE_OFST 4 -/* Bitmask of supported capabilities */ -#define MC_CMD_GET_PHY_CFG_OUT_SUPPORTED_CAP_OFST 8 -#define MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12 -#define MC_CMD_GET_PHY_CFG_OUT_PRT_OFST 16 -/* PHY statistics bitmap */ -#define MC_CMD_GET_PHY_CFG_OUT_STATS_MASK_OFST 20 -/* PHY type/name string */ -#define MC_CMD_GET_PHY_CFG_OUT_NAME_OFST 24 -#define MC_CMD_GET_PHY_CFG_OUT_NAME_LEN 20 -#define MC_CMD_GET_PHY_CFG_OUT_MEDIA_TYPE_OFST 44 -#define MC_CMD_MEDIA_XAUI 1 -#define MC_CMD_MEDIA_CX4 2 -#define MC_CMD_MEDIA_KX4 3 -#define MC_CMD_MEDIA_XFP 4 -#define MC_CMD_MEDIA_SFP_PLUS 5 -#define MC_CMD_MEDIA_BASE_T 6 -/* MDIO "MMDS" supported */ -#define MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48 -/* Native clause 22 */ -#define MC_CMD_MMD_CLAUSE22 0 -#define MC_CMD_MMD_CLAUSE45_PMAPMD 1 -#define MC_CMD_MMD_CLAUSE45_WIS 2 -#define MC_CMD_MMD_CLAUSE45_PCS 3 -#define MC_CMD_MMD_CLAUSE45_PHYXS 4 -#define MC_CMD_MMD_CLAUSE45_DTEXS 5 -#define MC_CMD_MMD_CLAUSE45_TC 6 -#define MC_CMD_MMD_CLAUSE45_AN 7 -/* Clause22 proxied over clause45 by PHY */ -#define MC_CMD_MMD_CLAUSE45_C22EXT 29 -#define MC_CMD_MMD_CLAUSE45_VEND1 30 -#define MC_CMD_MMD_CLAUSE45_VEND2 31 -/* PHY stepping version */ -#define MC_CMD_GET_PHY_CFG_OUT_REVISION_OFST 52 -#define MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN 20 - -/* MC_CMD_START_BIST: +/* MC_CMD_GET_PHY_CFG_IN msgrequest */ +#define MC_CMD_GET_PHY_CFG_IN_LEN 0 + +/* MC_CMD_GET_PHY_CFG_OUT msgresponse */ +#define MC_CMD_GET_PHY_CFG_OUT_LEN 72 +#define MC_CMD_GET_PHY_CFG_OUT_FLAGS_OFST 0 +#define MC_CMD_GET_PHY_CFG_OUT_PRESENT_LBN 0 +#define MC_CMD_GET_PHY_CFG_OUT_PRESENT_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN 1 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN 2 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN 3 +#define MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN 4 +#define MC_CMD_GET_PHY_CFG_OUT_POWEROFF_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN 5 +#define MC_CMD_GET_PHY_CFG_OUT_TXDIS_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_LBN 6 +#define MC_CMD_GET_PHY_CFG_OUT_BIST_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_TYPE_OFST 4 +#define MC_CMD_GET_PHY_CFG_OUT_SUPPORTED_CAP_OFST 8 +#define MC_CMD_PHY_CAP_10HDX_LBN 1 +#define MC_CMD_PHY_CAP_10HDX_WIDTH 1 +#define MC_CMD_PHY_CAP_10FDX_LBN 2 +#define MC_CMD_PHY_CAP_10FDX_WIDTH 1 +#define MC_CMD_PHY_CAP_100HDX_LBN 3 +#define MC_CMD_PHY_CAP_100HDX_WIDTH 1 +#define MC_CMD_PHY_CAP_100FDX_LBN 4 +#define MC_CMD_PHY_CAP_100FDX_WIDTH 1 +#define MC_CMD_PHY_CAP_1000HDX_LBN 5 +#define MC_CMD_PHY_CAP_1000HDX_WIDTH 1 +#define MC_CMD_PHY_CAP_1000FDX_LBN 6 +#define MC_CMD_PHY_CAP_1000FDX_WIDTH 1 +#define MC_CMD_PHY_CAP_10000FDX_LBN 7 +#define MC_CMD_PHY_CAP_10000FDX_WIDTH 1 +#define MC_CMD_PHY_CAP_PAUSE_LBN 8 +#define MC_CMD_PHY_CAP_PAUSE_WIDTH 1 +#define MC_CMD_PHY_CAP_ASYM_LBN 9 +#define MC_CMD_PHY_CAP_ASYM_WIDTH 1 +#define MC_CMD_PHY_CAP_AN_LBN 10 +#define MC_CMD_PHY_CAP_AN_WIDTH 1 +#define MC_CMD_GET_PHY_CFG_OUT_CHANNEL_OFST 12 +#define MC_CMD_GET_PHY_CFG_OUT_PRT_OFST 16 +#define MC_CMD_GET_PHY_CFG_OUT_STATS_MASK_OFST 20 +#define MC_CMD_GET_PHY_CFG_OUT_NAME_OFST 24 +#define MC_CMD_GET_PHY_CFG_OUT_NAME_LEN 20 +#define MC_CMD_GET_PHY_CFG_OUT_MEDIA_TYPE_OFST 44 +#define MC_CMD_MEDIA_XAUI 0x1 /* enum */ +#define MC_CMD_MEDIA_CX4 0x2 /* enum */ +#define MC_CMD_MEDIA_KX4 0x3 /* enum */ +#define MC_CMD_MEDIA_XFP 0x4 /* enum */ +#define MC_CMD_MEDIA_SFP_PLUS 0x5 /* enum */ +#define MC_CMD_MEDIA_BASE_T 0x6 /* enum */ +#define MC_CMD_GET_PHY_CFG_OUT_MMD_MASK_OFST 48 +#define MC_CMD_MMD_CLAUSE22 0x0 /* enum */ +#define MC_CMD_MMD_CLAUSE45_PMAPMD 0x1 /* enum */ +#define MC_CMD_MMD_CLAUSE45_WIS 0x2 /* enum */ +#define MC_CMD_MMD_CLAUSE45_PCS 0x3 /* enum */ +#define MC_CMD_MMD_CLAUSE45_PHYXS 0x4 /* enum */ +#define MC_CMD_MMD_CLAUSE45_DTEXS 0x5 /* enum */ +#define MC_CMD_MMD_CLAUSE45_TC 0x6 /* enum */ +#define MC_CMD_MMD_CLAUSE45_AN 0x7 /* enum */ +#define MC_CMD_MMD_CLAUSE45_C22EXT 0x1d /* enum */ +#define MC_CMD_MMD_CLAUSE45_VEND1 0x1e /* enum */ +#define MC_CMD_MMD_CLAUSE45_VEND2 0x1f /* enum */ +#define MC_CMD_GET_PHY_CFG_OUT_REVISION_OFST 52 +#define MC_CMD_GET_PHY_CFG_OUT_REVISION_LEN 20 + + +/***********************************/ +/* MC_CMD_START_BIST * Start a BIST test on the PHY. - * - * Locks required: PHY_LOCK if doing a PHY BIST - * Return code: 0, EINVAL, EACCES (if PHY_LOCK is not held) */ #define MC_CMD_START_BIST 0x25 -#define MC_CMD_START_BIST_IN_LEN 4 -#define MC_CMD_START_BIST_IN_TYPE_OFST 0 -#define MC_CMD_START_BIST_OUT_LEN 0 - -/* Run the PHY's short cable BIST */ -#define MC_CMD_PHY_BIST_CABLE_SHORT 1 -/* Run the PHY's long cable BIST */ -#define MC_CMD_PHY_BIST_CABLE_LONG 2 -/* Run BIST on the currently selected BPX Serdes (XAUI or XFI) */ -#define MC_CMD_BPX_SERDES_BIST 3 -/* Run the MC loopback tests */ -#define MC_CMD_MC_LOOPBACK_BIST 4 -/* Run the PHY's standard BIST */ -#define MC_CMD_PHY_BIST 5 - -/* MC_CMD_POLL_PHY_BIST: (variadic output) - * Poll for BIST completion - * - * Returns a single status code, and optionally some PHY specific - * bist output. The driver should only consume the BIST output - * after validating OUTLEN and PHY_CFG.PHY_TYPE. - * - * If a driver can't successfully parse the BIST output, it should - * still respect the pass/Fail in OUT.RESULT - * - * Locks required: PHY_LOCK if doing a PHY BIST - * Return code: 0, EACCES (if PHY_LOCK is not held) + +/* MC_CMD_START_BIST_IN msgrequest */ +#define MC_CMD_START_BIST_IN_LEN 4 +#define MC_CMD_START_BIST_IN_TYPE_OFST 0 +#define MC_CMD_PHY_BIST_CABLE_SHORT 0x1 /* enum */ +#define MC_CMD_PHY_BIST_CABLE_LONG 0x2 /* enum */ +#define MC_CMD_BPX_SERDES_BIST 0x3 /* enum */ +#define MC_CMD_MC_LOOPBACK_BIST 0x4 /* enum */ +#define MC_CMD_PHY_BIST 0x5 /* enum */ + +/* MC_CMD_START_BIST_OUT msgresponse */ +#define MC_CMD_START_BIST_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_POLL_BIST + * Poll for BIST completion. */ #define MC_CMD_POLL_BIST 0x26 -#define MC_CMD_POLL_BIST_IN_LEN 0 -#define MC_CMD_POLL_BIST_OUT_LEN UNKNOWN -#define MC_CMD_POLL_BIST_OUT_SFT9001_LEN 36 -#define MC_CMD_POLL_BIST_OUT_MRSFP_LEN 8 -#define MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 -#define MC_CMD_POLL_BIST_RUNNING 1 -#define MC_CMD_POLL_BIST_PASSED 2 -#define MC_CMD_POLL_BIST_FAILED 3 -#define MC_CMD_POLL_BIST_TIMEOUT 4 -/* Generic: */ -#define MC_CMD_POLL_BIST_OUT_PRIVATE_OFST 4 -/* SFT9001-specific: */ -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A_OFST 4 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B_OFST 8 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C_OFST 12 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D_OFST 16 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_A_OFST 20 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_B_OFST 24 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_C_OFST 28 -#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_D_OFST 32 -#define MC_CMD_POLL_BIST_SFT9001_PAIR_OK 1 -#define MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN 2 -#define MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT 3 -#define MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT 4 -#define MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY 9 -/* mrsfp "PHY" driver: */ -#define MC_CMD_POLL_BIST_OUT_MRSFP_TEST_OFST 4 -#define MC_CMD_POLL_BIST_MRSFP_TEST_COMPLETE 0 -#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_WRITE 1 -#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_IO_EXP 2 -#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_MODULE 3 -#define MC_CMD_POLL_BIST_MRSFP_TEST_IO_EXP_I2C_CONFIGURE 4 -#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_I2C_NO_CROSSTALK 5 -#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_PRESENCE 6 -#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_I2C_ACCESS 7 -#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_SANE_VALUE 8 - -/* MC_CMD_PHY_SPI: (variadic in, variadic out) - * Read/Write/Erase the PHY SPI device - * - * Locks required: PHY_LOCK - * Return code: 0, ETIME, EINVAL, EACCES (if PHY_LOCK is not held) - */ -#define MC_CMD_PHY_SPI 0x27 -#define MC_CMD_PHY_SPI_IN_LEN(_write_bytes) (12 + (_write_bytes)) -#define MC_CMD_PHY_SPI_IN_ARGS_OFST 0 -#define MC_CMD_PHY_SPI_IN_ARGS_ADDR_OFST 0 -#define MC_CMD_PHY_SPI_IN_ARGS_READ_BYTES_OFST 4 -#define MC_CMD_PHY_SPI_IN_ARGS_ERASE_ALL_OFST 8 -/* Data to write here */ -#define MC_CMD_PHY_SPI_IN_WRITE_BUFFER_OFSET 12 -#define MC_CMD_PHY_SPI_OUT_LEN(_read_bytes) (_read_bytes) -/* Data read here */ -#define MC_CMD_PHY_SPI_OUT_READ_BUFFER_OFST 0 - - -/* MC_CMD_GET_LOOPBACK_MODES: - * Returns a bitmask of loopback modes evailable at each speed. - * - * Locks required: None - * Return code: 0 + +/* MC_CMD_POLL_BIST_IN msgrequest */ +#define MC_CMD_POLL_BIST_IN_LEN 0 + +/* MC_CMD_POLL_BIST_OUT msgresponse */ +#define MC_CMD_POLL_BIST_OUT_LEN 8 +#define MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 +#define MC_CMD_POLL_BIST_RUNNING 0x1 /* enum */ +#define MC_CMD_POLL_BIST_PASSED 0x2 /* enum */ +#define MC_CMD_POLL_BIST_FAILED 0x3 /* enum */ +#define MC_CMD_POLL_BIST_TIMEOUT 0x4 /* enum */ +#define MC_CMD_POLL_BIST_OUT_PRIVATE_OFST 4 + +/* MC_CMD_POLL_BIST_OUT_SFT9001 msgresponse */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_LEN 36 +/* MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 */ +/* Enum values, see field(s): */ +/* MC_CMD_POLL_BIST_OUT/MC_CMD_POLL_BIST_OUT_RESULT */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_A_OFST 4 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_B_OFST 8 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_C_OFST 12 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_LENGTH_D_OFST 16 +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_A_OFST 20 +#define MC_CMD_POLL_BIST_SFT9001_PAIR_OK 0x1 /* enum */ +#define MC_CMD_POLL_BIST_SFT9001_PAIR_OPEN 0x2 /* enum */ +#define MC_CMD_POLL_BIST_SFT9001_INTRA_PAIR_SHORT 0x3 /* enum */ +#define MC_CMD_POLL_BIST_SFT9001_INTER_PAIR_SHORT 0x4 /* enum */ +#define MC_CMD_POLL_BIST_SFT9001_PAIR_BUSY 0x9 /* enum */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_B_OFST 24 +/* Enum values, see field(s): */ +/* CABLE_STATUS_A */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_C_OFST 28 +/* Enum values, see field(s): */ +/* CABLE_STATUS_A */ +#define MC_CMD_POLL_BIST_OUT_SFT9001_CABLE_STATUS_D_OFST 32 +/* Enum values, see field(s): */ +/* CABLE_STATUS_A */ + +/* MC_CMD_POLL_BIST_OUT_MRSFP msgresponse */ +#define MC_CMD_POLL_BIST_OUT_MRSFP_LEN 8 +/* MC_CMD_POLL_BIST_OUT_RESULT_OFST 0 */ +/* Enum values, see field(s): */ +/* MC_CMD_POLL_BIST_OUT/MC_CMD_POLL_BIST_OUT_RESULT */ +#define MC_CMD_POLL_BIST_OUT_MRSFP_TEST_OFST 4 +#define MC_CMD_POLL_BIST_MRSFP_TEST_COMPLETE 0x0 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_WRITE 0x1 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_IO_EXP 0x2 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_OFF_I2C_NO_ACCESS_MODULE 0x3 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_IO_EXP_I2C_CONFIGURE 0x4 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_BUS_SWITCH_I2C_NO_CROSSTALK 0x5 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_PRESENCE 0x6 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_I2C_ACCESS 0x7 /* enum */ +#define MC_CMD_POLL_BIST_MRSFP_TEST_MODULE_ID_SANE_VALUE 0x8 /* enum */ + + +/***********************************/ +/* MC_CMD_FLUSH_RX_QUEUES + * Flush receive queue(s). + */ +#define MC_CMD_FLUSH_RX_QUEUES 0x27 + +/* MC_CMD_FLUSH_RX_QUEUES_IN msgrequest */ +#define MC_CMD_FLUSH_RX_QUEUES_IN_LENMIN 4 +#define MC_CMD_FLUSH_RX_QUEUES_IN_LENMAX 252 +#define MC_CMD_FLUSH_RX_QUEUES_IN_LEN(num) (0+4*(num)) +#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_OFST 0 +#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_LEN 4 +#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MINNUM 1 +#define MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM 63 + +/* MC_CMD_FLUSH_RX_QUEUES_OUT msgresponse */ +#define MC_CMD_FLUSH_RX_QUEUES_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_LOOPBACK_MODES + * Get port's loopback modes. */ #define MC_CMD_GET_LOOPBACK_MODES 0x28 -#define MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0 -#define MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 32 -#define MC_CMD_GET_LOOPBACK_MODES_100M_OFST 0 -#define MC_CMD_GET_LOOPBACK_MODES_1G_OFST 8 -#define MC_CMD_GET_LOOPBACK_MODES_10G_OFST 16 -#define MC_CMD_GET_LOOPBACK_MODES_SUGGESTED_OFST 24 - -/* Flow control enumeration */ -#define MC_CMD_FCNTL_OFF 0 -#define MC_CMD_FCNTL_RESPOND 1 -#define MC_CMD_FCNTL_BIDIR 2 -/* Auto - Use what the link has autonegotiated - * - The driver should modify the advertised capabilities via SET_LINK.CAP - * to control the negotiated flow control mode. - * - Can only be set if the PHY supports PAUSE+ASYM capabilities - * - Never returned by GET_LINK as the value programmed into the MAC - */ -#define MC_CMD_FCNTL_AUTO 3 - -/* Generic mac fault bitmask */ -#define MC_CMD_MAC_FAULT_XGMII_LOCAL_LBN 0 -#define MC_CMD_MAC_FAULT_XGMII_LOCAL_WIDTH 1 -#define MC_CMD_MAC_FAULT_XGMII_REMOTE_LBN 1 -#define MC_CMD_MAC_FAULT_XGMII_REMOTE_WIDTH 1 -#define MC_CMD_MAC_FAULT_SGMII_REMOTE_LBN 2 -#define MC_CMD_MAC_FAULT_SGMII_REMOTE_WIDTH 1 - -/* MC_CMD_GET_LINK: - * Read the unified MAC/PHY link state - * - * Locks required: None - * Return code: 0, ETIME + +/* MC_CMD_GET_LOOPBACK_MODES_IN msgrequest */ +#define MC_CMD_GET_LOOPBACK_MODES_IN_LEN 0 + +/* MC_CMD_GET_LOOPBACK_MODES_OUT msgresponse */ +#define MC_CMD_GET_LOOPBACK_MODES_OUT_LEN 32 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_OFST 0 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_LEN 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_LO_OFST 0 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_100M_HI_OFST 4 +#define MC_CMD_LOOPBACK_NONE 0x0 /* enum */ +#define MC_CMD_LOOPBACK_DATA 0x1 /* enum */ +#define MC_CMD_LOOPBACK_GMAC 0x2 /* enum */ +#define MC_CMD_LOOPBACK_XGMII 0x3 /* enum */ +#define MC_CMD_LOOPBACK_XGXS 0x4 /* enum */ +#define MC_CMD_LOOPBACK_XAUI 0x5 /* enum */ +#define MC_CMD_LOOPBACK_GMII 0x6 /* enum */ +#define MC_CMD_LOOPBACK_SGMII 0x7 /* enum */ +#define MC_CMD_LOOPBACK_XGBR 0x8 /* enum */ +#define MC_CMD_LOOPBACK_XFI 0x9 /* enum */ +#define MC_CMD_LOOPBACK_XAUI_FAR 0xa /* enum */ +#define MC_CMD_LOOPBACK_GMII_FAR 0xb /* enum */ +#define MC_CMD_LOOPBACK_SGMII_FAR 0xc /* enum */ +#define MC_CMD_LOOPBACK_XFI_FAR 0xd /* enum */ +#define MC_CMD_LOOPBACK_GPHY 0xe /* enum */ +#define MC_CMD_LOOPBACK_PHYXS 0xf /* enum */ +#define MC_CMD_LOOPBACK_PCS 0x10 /* enum */ +#define MC_CMD_LOOPBACK_PMAPMD 0x11 /* enum */ +#define MC_CMD_LOOPBACK_XPORT 0x12 /* enum */ +#define MC_CMD_LOOPBACK_XGMII_WS 0x13 /* enum */ +#define MC_CMD_LOOPBACK_XAUI_WS 0x14 /* enum */ +#define MC_CMD_LOOPBACK_XAUI_WS_FAR 0x15 /* enum */ +#define MC_CMD_LOOPBACK_XAUI_WS_NEAR 0x16 /* enum */ +#define MC_CMD_LOOPBACK_GMII_WS 0x17 /* enum */ +#define MC_CMD_LOOPBACK_XFI_WS 0x18 /* enum */ +#define MC_CMD_LOOPBACK_XFI_WS_FAR 0x19 /* enum */ +#define MC_CMD_LOOPBACK_PHYXS_WS 0x1a /* enum */ +#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_OFST 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_LEN 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_LO_OFST 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_1G_HI_OFST 12 +/* Enum values, see field(s): */ +/* 100M */ +#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_OFST 16 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_LEN 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_LO_OFST 16 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_10G_HI_OFST 20 +/* Enum values, see field(s): */ +/* 100M */ +#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_OFST 24 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LEN 8 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_LO_OFST 24 +#define MC_CMD_GET_LOOPBACK_MODES_OUT_SUGGESTED_HI_OFST 28 +/* Enum values, see field(s): */ +/* 100M */ + + +/***********************************/ +/* MC_CMD_GET_LINK + * Read the unified MAC/PHY link state. */ #define MC_CMD_GET_LINK 0x29 -#define MC_CMD_GET_LINK_IN_LEN 0 -#define MC_CMD_GET_LINK_OUT_LEN 28 -/* near-side and link-partner advertised capabilities */ -#define MC_CMD_GET_LINK_OUT_CAP_OFST 0 -#define MC_CMD_GET_LINK_OUT_LP_CAP_OFST 4 -/* Autonegotiated speed in mbit/s. The link may still be down - * even if this reads non-zero */ -#define MC_CMD_GET_LINK_OUT_LINK_SPEED_OFST 8 -#define MC_CMD_GET_LINK_OUT_LOOPBACK_MODE_OFST 12 -#define MC_CMD_GET_LINK_OUT_FLAGS_OFST 16 -/* Whether we have overall link up */ -#define MC_CMD_GET_LINK_LINK_UP_LBN 0 -#define MC_CMD_GET_LINK_LINK_UP_WIDTH 1 -#define MC_CMD_GET_LINK_FULL_DUPLEX_LBN 1 -#define MC_CMD_GET_LINK_FULL_DUPLEX_WIDTH 1 -/* Whether we have link at the layers provided by the BPX */ -#define MC_CMD_GET_LINK_BPX_LINK_LBN 2 -#define MC_CMD_GET_LINK_BPX_LINK_WIDTH 1 -/* Whether the PHY has external link */ -#define MC_CMD_GET_LINK_PHY_LINK_LBN 3 -#define MC_CMD_GET_LINK_PHY_LINK_WIDTH 1 -#define MC_CMD_GET_LINK_OUT_FCNTL_OFST 20 -#define MC_CMD_GET_LINK_OUT_MAC_FAULT_OFST 24 - -/* MC_CMD_SET_LINK: - * Write the unified MAC/PHY link configuration - * - * A loopback speed of "0" is supported, and means - * (choose any available speed) - * - * Locks required: None - * Return code: 0, EINVAL, ETIME + +/* MC_CMD_GET_LINK_IN msgrequest */ +#define MC_CMD_GET_LINK_IN_LEN 0 + +/* MC_CMD_GET_LINK_OUT msgresponse */ +#define MC_CMD_GET_LINK_OUT_LEN 28 +#define MC_CMD_GET_LINK_OUT_CAP_OFST 0 +#define MC_CMD_GET_LINK_OUT_LP_CAP_OFST 4 +#define MC_CMD_GET_LINK_OUT_LINK_SPEED_OFST 8 +#define MC_CMD_GET_LINK_OUT_LOOPBACK_MODE_OFST 12 +/* Enum values, see field(s): */ +/* MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */ +#define MC_CMD_GET_LINK_OUT_FLAGS_OFST 16 +#define MC_CMD_GET_LINK_OUT_LINK_UP_LBN 0 +#define MC_CMD_GET_LINK_OUT_LINK_UP_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN 1 +#define MC_CMD_GET_LINK_OUT_FULL_DUPLEX_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_BPX_LINK_LBN 2 +#define MC_CMD_GET_LINK_OUT_BPX_LINK_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_PHY_LINK_LBN 3 +#define MC_CMD_GET_LINK_OUT_PHY_LINK_WIDTH 1 +#define MC_CMD_GET_LINK_OUT_FCNTL_OFST 20 +#define MC_CMD_FCNTL_OFF 0x0 /* enum */ +#define MC_CMD_FCNTL_RESPOND 0x1 /* enum */ +#define MC_CMD_FCNTL_BIDIR 0x2 /* enum */ +#define MC_CMD_GET_LINK_OUT_MAC_FAULT_OFST 24 +#define MC_CMD_MAC_FAULT_XGMII_LOCAL_LBN 0 +#define MC_CMD_MAC_FAULT_XGMII_LOCAL_WIDTH 1 +#define MC_CMD_MAC_FAULT_XGMII_REMOTE_LBN 1 +#define MC_CMD_MAC_FAULT_XGMII_REMOTE_WIDTH 1 +#define MC_CMD_MAC_FAULT_SGMII_REMOTE_LBN 2 +#define MC_CMD_MAC_FAULT_SGMII_REMOTE_WIDTH 1 +#define MC_CMD_MAC_FAULT_PENDING_RECONFIG_LBN 3 +#define MC_CMD_MAC_FAULT_PENDING_RECONFIG_WIDTH 1 + + +/***********************************/ +/* MC_CMD_SET_LINK + * Write the unified MAC/PHY link configuration. */ #define MC_CMD_SET_LINK 0x2a -#define MC_CMD_SET_LINK_IN_LEN 16 -#define MC_CMD_SET_LINK_IN_CAP_OFST 0 -#define MC_CMD_SET_LINK_IN_FLAGS_OFST 4 -#define MC_CMD_SET_LINK_LOWPOWER_LBN 0 -#define MC_CMD_SET_LINK_LOWPOWER_WIDTH 1 -#define MC_CMD_SET_LINK_POWEROFF_LBN 1 -#define MC_CMD_SET_LINK_POWEROFF_WIDTH 1 -#define MC_CMD_SET_LINK_TXDIS_LBN 2 -#define MC_CMD_SET_LINK_TXDIS_WIDTH 1 -#define MC_CMD_SET_LINK_IN_LOOPBACK_MODE_OFST 8 -#define MC_CMD_SET_LINK_IN_LOOPBACK_SPEED_OFST 12 -#define MC_CMD_SET_LINK_OUT_LEN 0 - -/* MC_CMD_SET_ID_LED: - * Set indentification LED state - * - * Locks required: None - * Return code: 0, EINVAL + +/* MC_CMD_SET_LINK_IN msgrequest */ +#define MC_CMD_SET_LINK_IN_LEN 16 +#define MC_CMD_SET_LINK_IN_CAP_OFST 0 +#define MC_CMD_SET_LINK_IN_FLAGS_OFST 4 +#define MC_CMD_SET_LINK_IN_LOWPOWER_LBN 0 +#define MC_CMD_SET_LINK_IN_LOWPOWER_WIDTH 1 +#define MC_CMD_SET_LINK_IN_POWEROFF_LBN 1 +#define MC_CMD_SET_LINK_IN_POWEROFF_WIDTH 1 +#define MC_CMD_SET_LINK_IN_TXDIS_LBN 2 +#define MC_CMD_SET_LINK_IN_TXDIS_WIDTH 1 +#define MC_CMD_SET_LINK_IN_LOOPBACK_MODE_OFST 8 +/* Enum values, see field(s): */ +/* MC_CMD_GET_LOOPBACK_MODES/MC_CMD_GET_LOOPBACK_MODES_OUT/100M */ +#define MC_CMD_SET_LINK_IN_LOOPBACK_SPEED_OFST 12 + +/* MC_CMD_SET_LINK_OUT msgresponse */ +#define MC_CMD_SET_LINK_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SET_ID_LED + * Set indentification LED state. */ #define MC_CMD_SET_ID_LED 0x2b -#define MC_CMD_SET_ID_LED_IN_LEN 4 -#define MC_CMD_SET_ID_LED_IN_STATE_OFST 0 -#define MC_CMD_LED_OFF 0 -#define MC_CMD_LED_ON 1 -#define MC_CMD_LED_DEFAULT 2 -#define MC_CMD_SET_ID_LED_OUT_LEN 0 - -/* MC_CMD_SET_MAC: - * Set MAC configuration - * - * The MTU is the MTU programmed directly into the XMAC/GMAC - * (inclusive of EtherII, VLAN, bug16011 padding) - * - * Locks required: None - * Return code: 0, EINVAL + +/* MC_CMD_SET_ID_LED_IN msgrequest */ +#define MC_CMD_SET_ID_LED_IN_LEN 4 +#define MC_CMD_SET_ID_LED_IN_STATE_OFST 0 +#define MC_CMD_LED_OFF 0x0 /* enum */ +#define MC_CMD_LED_ON 0x1 /* enum */ +#define MC_CMD_LED_DEFAULT 0x2 /* enum */ + +/* MC_CMD_SET_ID_LED_OUT msgresponse */ +#define MC_CMD_SET_ID_LED_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SET_MAC + * Set MAC configuration. */ #define MC_CMD_SET_MAC 0x2c -#define MC_CMD_SET_MAC_IN_LEN 24 -#define MC_CMD_SET_MAC_IN_MTU_OFST 0 -#define MC_CMD_SET_MAC_IN_DRAIN_OFST 4 -#define MC_CMD_SET_MAC_IN_ADDR_OFST 8 -#define MC_CMD_SET_MAC_IN_REJECT_OFST 16 -#define MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN 0 -#define MC_CMD_SET_MAC_IN_REJECT_UNCST_WIDTH 1 -#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_LBN 1 -#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_WIDTH 1 -#define MC_CMD_SET_MAC_IN_FCNTL_OFST 20 -#define MC_CMD_SET_MAC_OUT_LEN 0 - -/* MC_CMD_PHY_STATS: - * Get generic PHY statistics - * - * This call returns the statistics for a generic PHY in a sparse - * array (indexed by the enumerate). Each value is represented by - * a 32bit number. - * - * If the DMA_ADDR is 0, then no DMA is performed, and the statistics - * may be read directly out of shared memory. If DMA_ADDR != 0, then - * the statistics are dmad to that (page-aligned location) - * - * Locks required: None - * Returns: 0, ETIME - * Response methods: shared memory, event + +/* MC_CMD_SET_MAC_IN msgrequest */ +#define MC_CMD_SET_MAC_IN_LEN 24 +#define MC_CMD_SET_MAC_IN_MTU_OFST 0 +#define MC_CMD_SET_MAC_IN_DRAIN_OFST 4 +#define MC_CMD_SET_MAC_IN_ADDR_OFST 8 +#define MC_CMD_SET_MAC_IN_ADDR_LEN 8 +#define MC_CMD_SET_MAC_IN_ADDR_LO_OFST 8 +#define MC_CMD_SET_MAC_IN_ADDR_HI_OFST 12 +#define MC_CMD_SET_MAC_IN_REJECT_OFST 16 +#define MC_CMD_SET_MAC_IN_REJECT_UNCST_LBN 0 +#define MC_CMD_SET_MAC_IN_REJECT_UNCST_WIDTH 1 +#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_LBN 1 +#define MC_CMD_SET_MAC_IN_REJECT_BRDCST_WIDTH 1 +#define MC_CMD_SET_MAC_IN_FCNTL_OFST 20 +/* MC_CMD_FCNTL_OFF 0x0 */ +/* MC_CMD_FCNTL_RESPOND 0x1 */ +/* MC_CMD_FCNTL_BIDIR 0x2 */ +#define MC_CMD_FCNTL_AUTO 0x3 /* enum */ + +/* MC_CMD_SET_MAC_OUT msgresponse */ +#define MC_CMD_SET_MAC_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_PHY_STATS + * Get generic PHY statistics. */ #define MC_CMD_PHY_STATS 0x2d -#define MC_CMD_PHY_STATS_IN_LEN 8 -#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LO_OFST 0 -#define MC_CMD_PHY_STATS_IN_DMA_ADDR_HI_OFST 4 -#define MC_CMD_PHY_STATS_OUT_DMA_LEN 0 -#define MC_CMD_PHY_STATS_OUT_NO_DMA_LEN (MC_CMD_PHY_NSTATS * 4) - -/* Unified MAC statistics enumeration */ -#define MC_CMD_MAC_GENERATION_START 0 -#define MC_CMD_MAC_TX_PKTS 1 -#define MC_CMD_MAC_TX_PAUSE_PKTS 2 -#define MC_CMD_MAC_TX_CONTROL_PKTS 3 -#define MC_CMD_MAC_TX_UNICAST_PKTS 4 -#define MC_CMD_MAC_TX_MULTICAST_PKTS 5 -#define MC_CMD_MAC_TX_BROADCAST_PKTS 6 -#define MC_CMD_MAC_TX_BYTES 7 -#define MC_CMD_MAC_TX_BAD_BYTES 8 -#define MC_CMD_MAC_TX_LT64_PKTS 9 -#define MC_CMD_MAC_TX_64_PKTS 10 -#define MC_CMD_MAC_TX_65_TO_127_PKTS 11 -#define MC_CMD_MAC_TX_128_TO_255_PKTS 12 -#define MC_CMD_MAC_TX_256_TO_511_PKTS 13 -#define MC_CMD_MAC_TX_512_TO_1023_PKTS 14 -#define MC_CMD_MAC_TX_1024_TO_15XX_PKTS 15 -#define MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS 16 -#define MC_CMD_MAC_TX_GTJUMBO_PKTS 17 -#define MC_CMD_MAC_TX_BAD_FCS_PKTS 18 -#define MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS 19 -#define MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS 20 -#define MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS 21 -#define MC_CMD_MAC_TX_LATE_COLLISION_PKTS 22 -#define MC_CMD_MAC_TX_DEFERRED_PKTS 23 -#define MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS 24 -#define MC_CMD_MAC_TX_NON_TCPUDP_PKTS 25 -#define MC_CMD_MAC_TX_MAC_SRC_ERR_PKTS 26 -#define MC_CMD_MAC_TX_IP_SRC_ERR_PKTS 27 -#define MC_CMD_MAC_RX_PKTS 28 -#define MC_CMD_MAC_RX_PAUSE_PKTS 29 -#define MC_CMD_MAC_RX_GOOD_PKTS 30 -#define MC_CMD_MAC_RX_CONTROL_PKTS 31 -#define MC_CMD_MAC_RX_UNICAST_PKTS 32 -#define MC_CMD_MAC_RX_MULTICAST_PKTS 33 -#define MC_CMD_MAC_RX_BROADCAST_PKTS 34 -#define MC_CMD_MAC_RX_BYTES 35 -#define MC_CMD_MAC_RX_BAD_BYTES 36 -#define MC_CMD_MAC_RX_64_PKTS 37 -#define MC_CMD_MAC_RX_65_TO_127_PKTS 38 -#define MC_CMD_MAC_RX_128_TO_255_PKTS 39 -#define MC_CMD_MAC_RX_256_TO_511_PKTS 40 -#define MC_CMD_MAC_RX_512_TO_1023_PKTS 41 -#define MC_CMD_MAC_RX_1024_TO_15XX_PKTS 42 -#define MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS 43 -#define MC_CMD_MAC_RX_GTJUMBO_PKTS 44 -#define MC_CMD_MAC_RX_UNDERSIZE_PKTS 45 -#define MC_CMD_MAC_RX_BAD_FCS_PKTS 46 -#define MC_CMD_MAC_RX_OVERFLOW_PKTS 47 -#define MC_CMD_MAC_RX_FALSE_CARRIER_PKTS 48 -#define MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS 49 -#define MC_CMD_MAC_RX_ALIGN_ERROR_PKTS 50 -#define MC_CMD_MAC_RX_LENGTH_ERROR_PKTS 51 -#define MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS 52 -#define MC_CMD_MAC_RX_JABBER_PKTS 53 -#define MC_CMD_MAC_RX_NODESC_DROPS 54 -#define MC_CMD_MAC_RX_LANES01_CHAR_ERR 55 -#define MC_CMD_MAC_RX_LANES23_CHAR_ERR 56 -#define MC_CMD_MAC_RX_LANES01_DISP_ERR 57 -#define MC_CMD_MAC_RX_LANES23_DISP_ERR 58 -#define MC_CMD_MAC_RX_MATCH_FAULT 59 -#define MC_CMD_GMAC_DMABUF_START 64 -#define MC_CMD_GMAC_DMABUF_END 95 -/* Insert new members here. */ -#define MC_CMD_MAC_GENERATION_END 96 -#define MC_CMD_MAC_NSTATS (MC_CMD_MAC_GENERATION_END+1) - -/* MC_CMD_MAC_STATS: - * Get unified GMAC/XMAC statistics - * - * This call returns unified statistics maintained by the MC as it - * switches between the GMAC and XMAC. The MC will write out all - * supported stats. The driver should zero initialise the buffer to - * guarantee consistent results. - * - * Locks required: None - * Returns: 0 - * Response methods: shared memory, event - */ -#define MC_CMD_MAC_STATS 0x2e -#define MC_CMD_MAC_STATS_IN_LEN 16 -#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LO_OFST 0 -#define MC_CMD_MAC_STATS_IN_DMA_ADDR_HI_OFST 4 -#define MC_CMD_MAC_STATS_IN_CMD_OFST 8 -#define MC_CMD_MAC_STATS_CMD_DMA_LBN 0 -#define MC_CMD_MAC_STATS_CMD_DMA_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_CLEAR_LBN 1 -#define MC_CMD_MAC_STATS_CMD_CLEAR_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_LBN 2 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_WIDTH 1 -/* Remaining PERIOD* fields only relevant when PERIODIC_CHANGE is set */ -#define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_LBN 3 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_LBN 4 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT_LBN 5 -#define MC_CMD_MAC_STATS_CMD_PERIODIC_NOEVENT_WIDTH 1 -#define MC_CMD_MAC_STATS_CMD_PERIOD_MS_LBN 16 -#define MC_CMD_MAC_STATS_CMD_PERIOD_MS_WIDTH 16 -#define MC_CMD_MAC_STATS_IN_DMA_LEN_OFST 12 - -#define MC_CMD_MAC_STATS_OUT_LEN 0 - -/* Callisto flags */ -#define MC_CMD_SFT9001_ROBUST_LBN 0 -#define MC_CMD_SFT9001_ROBUST_WIDTH 1 -#define MC_CMD_SFT9001_SHORT_REACH_LBN 1 -#define MC_CMD_SFT9001_SHORT_REACH_WIDTH 1 - -/* MC_CMD_SFT9001_GET: - * Read current callisto specific setting - * - * Locks required: None - * Returns: 0, ETIME - */ -#define MC_CMD_SFT9001_GET 0x30 -#define MC_CMD_SFT9001_GET_IN_LEN 0 -#define MC_CMD_SFT9001_GET_OUT_LEN 4 -#define MC_CMD_SFT9001_GET_OUT_FLAGS_OFST 0 -/* MC_CMD_SFT9001_SET: - * Write current callisto specific setting - * - * Locks required: None - * Returns: 0, ETIME, EINVAL +/* MC_CMD_PHY_STATS_IN msgrequest */ +#define MC_CMD_PHY_STATS_IN_LEN 8 +#define MC_CMD_PHY_STATS_IN_DMA_ADDR_OFST 0 +#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LEN 8 +#define MC_CMD_PHY_STATS_IN_DMA_ADDR_LO_OFST 0 +#define MC_CMD_PHY_STATS_IN_DMA_ADDR_HI_OFST 4 + +/* MC_CMD_PHY_STATS_OUT_DMA msgresponse */ +#define MC_CMD_PHY_STATS_OUT_DMA_LEN 0 + +/* MC_CMD_PHY_STATS_OUT_NO_DMA msgresponse */ +#define MC_CMD_PHY_STATS_OUT_NO_DMA_LEN (((MC_CMD_PHY_NSTATS*32))>>3) +#define MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_OFST 0 +#define MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_LEN 4 +#define MC_CMD_PHY_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_PHY_NSTATS +#define MC_CMD_OUI 0x0 /* enum */ +#define MC_CMD_PMA_PMD_LINK_UP 0x1 /* enum */ +#define MC_CMD_PMA_PMD_RX_FAULT 0x2 /* enum */ +#define MC_CMD_PMA_PMD_TX_FAULT 0x3 /* enum */ +#define MC_CMD_PMA_PMD_SIGNAL 0x4 /* enum */ +#define MC_CMD_PMA_PMD_SNR_A 0x5 /* enum */ +#define MC_CMD_PMA_PMD_SNR_B 0x6 /* enum */ +#define MC_CMD_PMA_PMD_SNR_C 0x7 /* enum */ +#define MC_CMD_PMA_PMD_SNR_D 0x8 /* enum */ +#define MC_CMD_PCS_LINK_UP 0x9 /* enum */ +#define MC_CMD_PCS_RX_FAULT 0xa /* enum */ +#define MC_CMD_PCS_TX_FAULT 0xb /* enum */ +#define MC_CMD_PCS_BER 0xc /* enum */ +#define MC_CMD_PCS_BLOCK_ERRORS 0xd /* enum */ +#define MC_CMD_PHYXS_LINK_UP 0xe /* enum */ +#define MC_CMD_PHYXS_RX_FAULT 0xf /* enum */ +#define MC_CMD_PHYXS_TX_FAULT 0x10 /* enum */ +#define MC_CMD_PHYXS_ALIGN 0x11 /* enum */ +#define MC_CMD_PHYXS_SYNC 0x12 /* enum */ +#define MC_CMD_AN_LINK_UP 0x13 /* enum */ +#define MC_CMD_AN_COMPLETE 0x14 /* enum */ +#define MC_CMD_AN_10GBT_STATUS 0x15 /* enum */ +#define MC_CMD_CL22_LINK_UP 0x16 /* enum */ +#define MC_CMD_PHY_NSTATS 0x17 /* enum */ + + +/***********************************/ +/* MC_CMD_MAC_STATS + * Get generic MAC statistics. */ -#define MC_CMD_SFT9001_SET 0x31 -#define MC_CMD_SFT9001_SET_IN_LEN 4 -#define MC_CMD_SFT9001_SET_IN_FLAGS_OFST 0 -#define MC_CMD_SFT9001_SET_OUT_LEN 0 - +#define MC_CMD_MAC_STATS 0x2e -/* MC_CMD_WOL_FILTER_SET: - * Set a WoL filter - * - * Locks required: None - * Returns: 0, EBUSY, EINVAL, ENOSYS +/* MC_CMD_MAC_STATS_IN msgrequest */ +#define MC_CMD_MAC_STATS_IN_LEN 16 +#define MC_CMD_MAC_STATS_IN_DMA_ADDR_OFST 0 +#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LEN 8 +#define MC_CMD_MAC_STATS_IN_DMA_ADDR_LO_OFST 0 +#define MC_CMD_MAC_STATS_IN_DMA_ADDR_HI_OFST 4 +#define MC_CMD_MAC_STATS_IN_CMD_OFST 8 +#define MC_CMD_MAC_STATS_IN_DMA_LBN 0 +#define MC_CMD_MAC_STATS_IN_DMA_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_CLEAR_LBN 1 +#define MC_CMD_MAC_STATS_IN_CLEAR_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE_LBN 2 +#define MC_CMD_MAC_STATS_IN_PERIODIC_CHANGE_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE_LBN 3 +#define MC_CMD_MAC_STATS_IN_PERIODIC_ENABLE_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR_LBN 4 +#define MC_CMD_MAC_STATS_IN_PERIODIC_CLEAR_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT_LBN 5 +#define MC_CMD_MAC_STATS_IN_PERIODIC_NOEVENT_WIDTH 1 +#define MC_CMD_MAC_STATS_IN_PERIOD_MS_LBN 16 +#define MC_CMD_MAC_STATS_IN_PERIOD_MS_WIDTH 16 +#define MC_CMD_MAC_STATS_IN_DMA_LEN_OFST 12 + +/* MC_CMD_MAC_STATS_OUT_DMA msgresponse */ +#define MC_CMD_MAC_STATS_OUT_DMA_LEN 0 + +/* MC_CMD_MAC_STATS_OUT_NO_DMA msgresponse */ +#define MC_CMD_MAC_STATS_OUT_NO_DMA_LEN (((MC_CMD_MAC_NSTATS*64))>>3) +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_OFST 0 +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_LEN 8 +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_LO_OFST 0 +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_HI_OFST 4 +#define MC_CMD_MAC_STATS_OUT_NO_DMA_STATISTICS_NUM MC_CMD_MAC_NSTATS +#define MC_CMD_MAC_GENERATION_START 0x0 /* enum */ +#define MC_CMD_MAC_TX_PKTS 0x1 /* enum */ +#define MC_CMD_MAC_TX_PAUSE_PKTS 0x2 /* enum */ +#define MC_CMD_MAC_TX_CONTROL_PKTS 0x3 /* enum */ +#define MC_CMD_MAC_TX_UNICAST_PKTS 0x4 /* enum */ +#define MC_CMD_MAC_TX_MULTICAST_PKTS 0x5 /* enum */ +#define MC_CMD_MAC_TX_BROADCAST_PKTS 0x6 /* enum */ +#define MC_CMD_MAC_TX_BYTES 0x7 /* enum */ +#define MC_CMD_MAC_TX_BAD_BYTES 0x8 /* enum */ +#define MC_CMD_MAC_TX_LT64_PKTS 0x9 /* enum */ +#define MC_CMD_MAC_TX_64_PKTS 0xa /* enum */ +#define MC_CMD_MAC_TX_65_TO_127_PKTS 0xb /* enum */ +#define MC_CMD_MAC_TX_128_TO_255_PKTS 0xc /* enum */ +#define MC_CMD_MAC_TX_256_TO_511_PKTS 0xd /* enum */ +#define MC_CMD_MAC_TX_512_TO_1023_PKTS 0xe /* enum */ +#define MC_CMD_MAC_TX_1024_TO_15XX_PKTS 0xf /* enum */ +#define MC_CMD_MAC_TX_15XX_TO_JUMBO_PKTS 0x10 /* enum */ +#define MC_CMD_MAC_TX_GTJUMBO_PKTS 0x11 /* enum */ +#define MC_CMD_MAC_TX_BAD_FCS_PKTS 0x12 /* enum */ +#define MC_CMD_MAC_TX_SINGLE_COLLISION_PKTS 0x13 /* enum */ +#define MC_CMD_MAC_TX_MULTIPLE_COLLISION_PKTS 0x14 /* enum */ +#define MC_CMD_MAC_TX_EXCESSIVE_COLLISION_PKTS 0x15 /* enum */ +#define MC_CMD_MAC_TX_LATE_COLLISION_PKTS 0x16 /* enum */ +#define MC_CMD_MAC_TX_DEFERRED_PKTS 0x17 /* enum */ +#define MC_CMD_MAC_TX_EXCESSIVE_DEFERRED_PKTS 0x18 /* enum */ +#define MC_CMD_MAC_TX_NON_TCPUDP_PKTS 0x19 /* enum */ +#define MC_CMD_MAC_TX_MAC_SRC_ERR_PKTS 0x1a /* enum */ +#define MC_CMD_MAC_TX_IP_SRC_ERR_PKTS 0x1b /* enum */ +#define MC_CMD_MAC_RX_PKTS 0x1c /* enum */ +#define MC_CMD_MAC_RX_PAUSE_PKTS 0x1d /* enum */ +#define MC_CMD_MAC_RX_GOOD_PKTS 0x1e /* enum */ +#define MC_CMD_MAC_RX_CONTROL_PKTS 0x1f /* enum */ +#define MC_CMD_MAC_RX_UNICAST_PKTS 0x20 /* enum */ +#define MC_CMD_MAC_RX_MULTICAST_PKTS 0x21 /* enum */ +#define MC_CMD_MAC_RX_BROADCAST_PKTS 0x22 /* enum */ +#define MC_CMD_MAC_RX_BYTES 0x23 /* enum */ +#define MC_CMD_MAC_RX_BAD_BYTES 0x24 /* enum */ +#define MC_CMD_MAC_RX_64_PKTS 0x25 /* enum */ +#define MC_CMD_MAC_RX_65_TO_127_PKTS 0x26 /* enum */ +#define MC_CMD_MAC_RX_128_TO_255_PKTS 0x27 /* enum */ +#define MC_CMD_MAC_RX_256_TO_511_PKTS 0x28 /* enum */ +#define MC_CMD_MAC_RX_512_TO_1023_PKTS 0x29 /* enum */ +#define MC_CMD_MAC_RX_1024_TO_15XX_PKTS 0x2a /* enum */ +#define MC_CMD_MAC_RX_15XX_TO_JUMBO_PKTS 0x2b /* enum */ +#define MC_CMD_MAC_RX_GTJUMBO_PKTS 0x2c /* enum */ +#define MC_CMD_MAC_RX_UNDERSIZE_PKTS 0x2d /* enum */ +#define MC_CMD_MAC_RX_BAD_FCS_PKTS 0x2e /* enum */ +#define MC_CMD_MAC_RX_OVERFLOW_PKTS 0x2f /* enum */ +#define MC_CMD_MAC_RX_FALSE_CARRIER_PKTS 0x30 /* enum */ +#define MC_CMD_MAC_RX_SYMBOL_ERROR_PKTS 0x31 /* enum */ +#define MC_CMD_MAC_RX_ALIGN_ERROR_PKTS 0x32 /* enum */ +#define MC_CMD_MAC_RX_LENGTH_ERROR_PKTS 0x33 /* enum */ +#define MC_CMD_MAC_RX_INTERNAL_ERROR_PKTS 0x34 /* enum */ +#define MC_CMD_MAC_RX_JABBER_PKTS 0x35 /* enum */ +#define MC_CMD_MAC_RX_NODESC_DROPS 0x36 /* enum */ +#define MC_CMD_MAC_RX_LANES01_CHAR_ERR 0x37 /* enum */ +#define MC_CMD_MAC_RX_LANES23_CHAR_ERR 0x38 /* enum */ +#define MC_CMD_MAC_RX_LANES01_DISP_ERR 0x39 /* enum */ +#define MC_CMD_MAC_RX_LANES23_DISP_ERR 0x3a /* enum */ +#define MC_CMD_MAC_RX_MATCH_FAULT 0x3b /* enum */ +#define MC_CMD_GMAC_DMABUF_START 0x40 /* enum */ +#define MC_CMD_GMAC_DMABUF_END 0x5f /* enum */ +#define MC_CMD_MAC_GENERATION_END 0x60 /* enum */ +#define MC_CMD_MAC_NSTATS 0x61 /* enum */ + + +/***********************************/ +/* MC_CMD_SRIOV + * to be documented + */ +#define MC_CMD_SRIOV 0x30 + +/* MC_CMD_SRIOV_IN msgrequest */ +#define MC_CMD_SRIOV_IN_LEN 12 +#define MC_CMD_SRIOV_IN_ENABLE_OFST 0 +#define MC_CMD_SRIOV_IN_VI_BASE_OFST 4 +#define MC_CMD_SRIOV_IN_VF_COUNT_OFST 8 + +/* MC_CMD_SRIOV_OUT msgresponse */ +#define MC_CMD_SRIOV_OUT_LEN 8 +#define MC_CMD_SRIOV_OUT_VI_SCALE_OFST 0 +#define MC_CMD_SRIOV_OUT_VF_TOTAL_OFST 4 + +/* MC_CMD_MEMCPY_RECORD_TYPEDEF structuredef */ +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LEN 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_OFST 0 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_LBN 0 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_NUM_RECORDS_WIDTH 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_OFST 4 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_LBN 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_RID_WIDTH 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_OFST 8 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LEN 8 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LO_OFST 8 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_HI_OFST 12 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_LBN 64 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_TO_ADDR_WIDTH 64 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_OFST 16 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_RID_INLINE 0x100 /* enum */ +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_LBN 128 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_RID_WIDTH 32 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_OFST 20 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LEN 8 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LO_OFST 20 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_HI_OFST 24 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_LBN 160 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_FROM_ADDR_WIDTH 64 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_OFST 28 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_LBN 224 +#define MC_CMD_MEMCPY_RECORD_TYPEDEF_LENGTH_WIDTH 32 + + +/***********************************/ +/* MC_CMD_MEMCPY + * Perform memory copy operation. + */ +#define MC_CMD_MEMCPY 0x31 + +/* MC_CMD_MEMCPY_IN msgrequest */ +#define MC_CMD_MEMCPY_IN_LENMIN 32 +#define MC_CMD_MEMCPY_IN_LENMAX 224 +#define MC_CMD_MEMCPY_IN_LEN(num) (0+32*(num)) +#define MC_CMD_MEMCPY_IN_RECORD_OFST 0 +#define MC_CMD_MEMCPY_IN_RECORD_LEN 32 +#define MC_CMD_MEMCPY_IN_RECORD_MINNUM 1 +#define MC_CMD_MEMCPY_IN_RECORD_MAXNUM 7 + +/* MC_CMD_MEMCPY_OUT msgresponse */ +#define MC_CMD_MEMCPY_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_WOL_FILTER_SET + * Set a WoL filter. */ #define MC_CMD_WOL_FILTER_SET 0x32 -#define MC_CMD_WOL_FILTER_SET_IN_LEN 192 /* 190 rounded up to a word */ -#define MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 -#define MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 - -/* There is a union at offset 8, following defines overlap due to - * this */ -#define MC_CMD_WOL_FILTER_SET_IN_DATA_OFST 8 - -#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST - -#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_IP_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST -#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_IP_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 4) -#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 8) -#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 10) - -#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST -#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 16) -#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 32) -#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 34) - -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 48) -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 176) -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 177) -#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_OFST \ - (MC_CMD_WOL_FILTER_SET_IN_DATA_OFST + 178) - -#define MC_CMD_WOL_FILTER_SET_IN_LINK_MASK_OFST \ - MC_CMD_WOL_FILTER_SET_IN_DATA_OFST -#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_LBN 0 -#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_WIDTH 1 -#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_LBN 1 -#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_WIDTH 1 - -#define MC_CMD_WOL_FILTER_SET_OUT_LEN 4 -#define MC_CMD_WOL_FILTER_SET_OUT_FILTER_ID_OFST 0 - -/* WOL Filter types enumeration */ -#define MC_CMD_WOL_TYPE_MAGIC 0x0 - /* unused 0x1 */ -#define MC_CMD_WOL_TYPE_WIN_MAGIC 0x2 -#define MC_CMD_WOL_TYPE_IPV4_SYN 0x3 -#define MC_CMD_WOL_TYPE_IPV6_SYN 0x4 -#define MC_CMD_WOL_TYPE_BITMAP 0x5 -#define MC_CMD_WOL_TYPE_LINK 0x6 -#define MC_CMD_WOL_TYPE_MAX 0x7 - -#define MC_CMD_FILTER_MODE_SIMPLE 0x0 -#define MC_CMD_FILTER_MODE_STRUCTURED 0xffffffff - -/* MC_CMD_WOL_FILTER_REMOVE: - * Remove a WoL filter - * - * Locks required: None - * Returns: 0, EINVAL, ENOSYS + +/* MC_CMD_WOL_FILTER_SET_IN msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_LEN 192 +#define MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 +#define MC_CMD_FILTER_MODE_SIMPLE 0x0 /* enum */ +#define MC_CMD_FILTER_MODE_STRUCTURED 0xffffffff /* enum */ +#define MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 +#define MC_CMD_WOL_TYPE_MAGIC 0x0 /* enum */ +#define MC_CMD_WOL_TYPE_WIN_MAGIC 0x2 /* enum */ +#define MC_CMD_WOL_TYPE_IPV4_SYN 0x3 /* enum */ +#define MC_CMD_WOL_TYPE_IPV6_SYN 0x4 /* enum */ +#define MC_CMD_WOL_TYPE_BITMAP 0x5 /* enum */ +#define MC_CMD_WOL_TYPE_LINK 0x6 /* enum */ +#define MC_CMD_WOL_TYPE_MAX 0x7 /* enum */ +#define MC_CMD_WOL_FILTER_SET_IN_DATA_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_DATA_LEN 4 +#define MC_CMD_WOL_FILTER_SET_IN_DATA_NUM 46 + +/* MC_CMD_WOL_FILTER_SET_IN_MAGIC msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_LEN 16 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_LEN 8 +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_LO_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_MAGIC_MAC_HI_OFST 12 + +/* MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_LEN 20 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_IP_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_IP_OFST 12 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_OFST 16 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_SRC_PORT_LEN 2 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_OFST 18 +#define MC_CMD_WOL_FILTER_SET_IN_IPV4_SYN_DST_PORT_LEN 2 + +/* MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_LEN 44 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_IP_LEN 16 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_OFST 24 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_IP_LEN 16 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_OFST 40 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_SRC_PORT_LEN 2 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_OFST 42 +#define MC_CMD_WOL_FILTER_SET_IN_IPV6_SYN_DST_PORT_LEN 2 + +/* MC_CMD_WOL_FILTER_SET_IN_BITMAP msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN 187 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_MASK_LEN 48 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_BITMAP_OFST 56 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_BITMAP_LEN 128 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_OFST 184 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LEN_LEN 1 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_OFST 185 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER3_LEN 1 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_OFST 186 +#define MC_CMD_WOL_FILTER_SET_IN_BITMAP_LAYER4_LEN 1 + +/* MC_CMD_WOL_FILTER_SET_IN_LINK msgrequest */ +#define MC_CMD_WOL_FILTER_SET_IN_LINK_LEN 12 +/* MC_CMD_WOL_FILTER_SET_IN_FILTER_MODE_OFST 0 */ +/* MC_CMD_WOL_FILTER_SET_IN_WOL_TYPE_OFST 4 */ +#define MC_CMD_WOL_FILTER_SET_IN_LINK_MASK_OFST 8 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_LBN 0 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_UP_WIDTH 1 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_LBN 1 +#define MC_CMD_WOL_FILTER_SET_IN_LINK_DOWN_WIDTH 1 + +/* MC_CMD_WOL_FILTER_SET_OUT msgresponse */ +#define MC_CMD_WOL_FILTER_SET_OUT_LEN 4 +#define MC_CMD_WOL_FILTER_SET_OUT_FILTER_ID_OFST 0 + + +/***********************************/ +/* MC_CMD_WOL_FILTER_REMOVE + * Remove a WoL filter. */ #define MC_CMD_WOL_FILTER_REMOVE 0x33 -#define MC_CMD_WOL_FILTER_REMOVE_IN_LEN 4 -#define MC_CMD_WOL_FILTER_REMOVE_IN_FILTER_ID_OFST 0 -#define MC_CMD_WOL_FILTER_REMOVE_OUT_LEN 0 +/* MC_CMD_WOL_FILTER_REMOVE_IN msgrequest */ +#define MC_CMD_WOL_FILTER_REMOVE_IN_LEN 4 +#define MC_CMD_WOL_FILTER_REMOVE_IN_FILTER_ID_OFST 0 -/* MC_CMD_WOL_FILTER_RESET: - * Reset (i.e. remove all) WoL filters - * - * Locks required: None - * Returns: 0, ENOSYS +/* MC_CMD_WOL_FILTER_REMOVE_OUT msgresponse */ +#define MC_CMD_WOL_FILTER_REMOVE_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_WOL_FILTER_RESET + * Reset (i.e. remove all) WoL filters. */ #define MC_CMD_WOL_FILTER_RESET 0x34 -#define MC_CMD_WOL_FILTER_RESET_IN_LEN 0 -#define MC_CMD_WOL_FILTER_RESET_OUT_LEN 0 -/* MC_CMD_SET_MCAST_HASH: - * Set the MCASH hash value without otherwise - * reconfiguring the MAC +/* MC_CMD_WOL_FILTER_RESET_IN msgrequest */ +#define MC_CMD_WOL_FILTER_RESET_IN_LEN 4 +#define MC_CMD_WOL_FILTER_RESET_IN_MASK_OFST 0 +#define MC_CMD_WOL_FILTER_RESET_IN_WAKE_FILTERS 0x1 /* enum */ +#define MC_CMD_WOL_FILTER_RESET_IN_LIGHTSOUT_OFFLOADS 0x2 /* enum */ + +/* MC_CMD_WOL_FILTER_RESET_OUT msgresponse */ +#define MC_CMD_WOL_FILTER_RESET_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SET_MCAST_HASH + * Set the MCASH hash value. */ #define MC_CMD_SET_MCAST_HASH 0x35 -#define MC_CMD_SET_MCAST_HASH_IN_LEN 32 -#define MC_CMD_SET_MCAST_HASH_IN_HASH0_OFST 0 -#define MC_CMD_SET_MCAST_HASH_IN_HASH1_OFST 16 -#define MC_CMD_SET_MCAST_HASH_OUT_LEN 0 -/* MC_CMD_NVRAM_TYPES: - * Return bitfield indicating available types of virtual NVRAM partitions - * - * Locks required: none - * Returns: 0 +/* MC_CMD_SET_MCAST_HASH_IN msgrequest */ +#define MC_CMD_SET_MCAST_HASH_IN_LEN 32 +#define MC_CMD_SET_MCAST_HASH_IN_HASH0_OFST 0 +#define MC_CMD_SET_MCAST_HASH_IN_HASH0_LEN 16 +#define MC_CMD_SET_MCAST_HASH_IN_HASH1_OFST 16 +#define MC_CMD_SET_MCAST_HASH_IN_HASH1_LEN 16 + +/* MC_CMD_SET_MCAST_HASH_OUT msgresponse */ +#define MC_CMD_SET_MCAST_HASH_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_NVRAM_TYPES + * Get virtual NVRAM partitions information. */ #define MC_CMD_NVRAM_TYPES 0x36 -#define MC_CMD_NVRAM_TYPES_IN_LEN 0 -#define MC_CMD_NVRAM_TYPES_OUT_LEN 4 -#define MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0 - -/* Supported NVRAM types */ -#define MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0 -#define MC_CMD_NVRAM_TYPE_MC_FW 1 -#define MC_CMD_NVRAM_TYPE_MC_FW_BACKUP 2 -#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 3 -#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1 4 -#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 5 -#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1 6 -#define MC_CMD_NVRAM_TYPE_EXP_ROM 7 -#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0 8 -#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1 9 -#define MC_CMD_NVRAM_TYPE_PHY_PORT0 10 -#define MC_CMD_NVRAM_TYPE_PHY_PORT1 11 -#define MC_CMD_NVRAM_TYPE_LOG 12 - -/* MC_CMD_NVRAM_INFO: - * Read info about a virtual NVRAM partition - * - * Locks required: none - * Returns: 0, EINVAL (bad type) + +/* MC_CMD_NVRAM_TYPES_IN msgrequest */ +#define MC_CMD_NVRAM_TYPES_IN_LEN 0 + +/* MC_CMD_NVRAM_TYPES_OUT msgresponse */ +#define MC_CMD_NVRAM_TYPES_OUT_LEN 4 +#define MC_CMD_NVRAM_TYPES_OUT_TYPES_OFST 0 +#define MC_CMD_NVRAM_TYPE_DISABLED_CALLISTO 0x0 /* enum */ +#define MC_CMD_NVRAM_TYPE_MC_FW 0x1 /* enum */ +#define MC_CMD_NVRAM_TYPE_MC_FW_BACKUP 0x2 /* enum */ +#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT0 0x3 /* enum */ +#define MC_CMD_NVRAM_TYPE_STATIC_CFG_PORT1 0x4 /* enum */ +#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT0 0x5 /* enum */ +#define MC_CMD_NVRAM_TYPE_DYNAMIC_CFG_PORT1 0x6 /* enum */ +#define MC_CMD_NVRAM_TYPE_EXP_ROM 0x7 /* enum */ +#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT0 0x8 /* enum */ +#define MC_CMD_NVRAM_TYPE_EXP_ROM_CFG_PORT1 0x9 /* enum */ +#define MC_CMD_NVRAM_TYPE_PHY_PORT0 0xa /* enum */ +#define MC_CMD_NVRAM_TYPE_PHY_PORT1 0xb /* enum */ +#define MC_CMD_NVRAM_TYPE_LOG 0xc /* enum */ +#define MC_CMD_NVRAM_TYPE_FPGA 0xd /* enum */ + + +/***********************************/ +/* MC_CMD_NVRAM_INFO + * Read info about a virtual NVRAM partition. */ #define MC_CMD_NVRAM_INFO 0x37 -#define MC_CMD_NVRAM_INFO_IN_LEN 4 -#define MC_CMD_NVRAM_INFO_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_INFO_OUT_LEN 24 -#define MC_CMD_NVRAM_INFO_OUT_TYPE_OFST 0 -#define MC_CMD_NVRAM_INFO_OUT_SIZE_OFST 4 -#define MC_CMD_NVRAM_INFO_OUT_ERASESIZE_OFST 8 -#define MC_CMD_NVRAM_INFO_OUT_FLAGS_OFST 12 -#define MC_CMD_NVRAM_PROTECTED_LBN 0 -#define MC_CMD_NVRAM_PROTECTED_WIDTH 1 -#define MC_CMD_NVRAM_INFO_OUT_PHYSDEV_OFST 16 -#define MC_CMD_NVRAM_INFO_OUT_PHYSADDR_OFST 20 - -/* MC_CMD_NVRAM_UPDATE_START: - * Start a group of update operations on a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type), EACCES (if PHY_LOCK required and not held) + +/* MC_CMD_NVRAM_INFO_IN msgrequest */ +#define MC_CMD_NVRAM_INFO_IN_LEN 4 +#define MC_CMD_NVRAM_INFO_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ + +/* MC_CMD_NVRAM_INFO_OUT msgresponse */ +#define MC_CMD_NVRAM_INFO_OUT_LEN 24 +#define MC_CMD_NVRAM_INFO_OUT_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_INFO_OUT_SIZE_OFST 4 +#define MC_CMD_NVRAM_INFO_OUT_ERASESIZE_OFST 8 +#define MC_CMD_NVRAM_INFO_OUT_FLAGS_OFST 12 +#define MC_CMD_NVRAM_INFO_OUT_PROTECTED_LBN 0 +#define MC_CMD_NVRAM_INFO_OUT_PROTECTED_WIDTH 1 +#define MC_CMD_NVRAM_INFO_OUT_PHYSDEV_OFST 16 +#define MC_CMD_NVRAM_INFO_OUT_PHYSADDR_OFST 20 + + +/***********************************/ +/* MC_CMD_NVRAM_UPDATE_START + * Start a group of update operations on a virtual NVRAM partition. */ #define MC_CMD_NVRAM_UPDATE_START 0x38 -#define MC_CMD_NVRAM_UPDATE_START_IN_LEN 4 -#define MC_CMD_NVRAM_UPDATE_START_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_UPDATE_START_OUT_LEN 0 -/* MC_CMD_NVRAM_READ: - * Read data from a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held) +/* MC_CMD_NVRAM_UPDATE_START_IN msgrequest */ +#define MC_CMD_NVRAM_UPDATE_START_IN_LEN 4 +#define MC_CMD_NVRAM_UPDATE_START_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ + +/* MC_CMD_NVRAM_UPDATE_START_OUT msgresponse */ +#define MC_CMD_NVRAM_UPDATE_START_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_NVRAM_READ + * Read data from a virtual NVRAM partition. */ #define MC_CMD_NVRAM_READ 0x39 -#define MC_CMD_NVRAM_READ_IN_LEN 12 -#define MC_CMD_NVRAM_READ_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_READ_IN_OFFSET_OFST 4 -#define MC_CMD_NVRAM_READ_IN_LENGTH_OFST 8 -#define MC_CMD_NVRAM_READ_OUT_LEN(_read_bytes) (_read_bytes) -#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0 - -/* MC_CMD_NVRAM_WRITE: - * Write data to a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held) + +/* MC_CMD_NVRAM_READ_IN msgrequest */ +#define MC_CMD_NVRAM_READ_IN_LEN 12 +#define MC_CMD_NVRAM_READ_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_READ_IN_OFFSET_OFST 4 +#define MC_CMD_NVRAM_READ_IN_LENGTH_OFST 8 + +/* MC_CMD_NVRAM_READ_OUT msgresponse */ +#define MC_CMD_NVRAM_READ_OUT_LENMIN 1 +#define MC_CMD_NVRAM_READ_OUT_LENMAX 255 +#define MC_CMD_NVRAM_READ_OUT_LEN(num) (0+1*(num)) +#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_OFST 0 +#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_LEN 1 +#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MINNUM 1 +#define MC_CMD_NVRAM_READ_OUT_READ_BUFFER_MAXNUM 255 + + +/***********************************/ +/* MC_CMD_NVRAM_WRITE + * Write data to a virtual NVRAM partition. */ #define MC_CMD_NVRAM_WRITE 0x3a -#define MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_WRITE_IN_OFFSET_OFST 4 -#define MC_CMD_NVRAM_WRITE_IN_LENGTH_OFST 8 -#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12 -#define MC_CMD_NVRAM_WRITE_IN_LEN(_write_bytes) (12 + _write_bytes) -#define MC_CMD_NVRAM_WRITE_OUT_LEN 0 - -/* MC_CMD_NVRAM_ERASE: - * Erase sector(s) from a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held) + +/* MC_CMD_NVRAM_WRITE_IN msgrequest */ +#define MC_CMD_NVRAM_WRITE_IN_LENMIN 13 +#define MC_CMD_NVRAM_WRITE_IN_LENMAX 255 +#define MC_CMD_NVRAM_WRITE_IN_LEN(num) (12+1*(num)) +#define MC_CMD_NVRAM_WRITE_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_WRITE_IN_OFFSET_OFST 4 +#define MC_CMD_NVRAM_WRITE_IN_LENGTH_OFST 8 +#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_OFST 12 +#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_LEN 1 +#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MINNUM 1 +#define MC_CMD_NVRAM_WRITE_IN_WRITE_BUFFER_MAXNUM 243 + +/* MC_CMD_NVRAM_WRITE_OUT msgresponse */ +#define MC_CMD_NVRAM_WRITE_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_NVRAM_ERASE + * Erase sector(s) from a virtual NVRAM partition. */ #define MC_CMD_NVRAM_ERASE 0x3b -#define MC_CMD_NVRAM_ERASE_IN_LEN 12 -#define MC_CMD_NVRAM_ERASE_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_ERASE_IN_OFFSET_OFST 4 -#define MC_CMD_NVRAM_ERASE_IN_LENGTH_OFST 8 -#define MC_CMD_NVRAM_ERASE_OUT_LEN 0 - -/* MC_CMD_NVRAM_UPDATE_FINISH: - * Finish a group of update operations on a virtual NVRAM partition - * - * Locks required: PHY_LOCK if type==*PHY* - * Returns: 0, EINVAL (bad type/offset/length), EACCES (if PHY_LOCK required and not held) + +/* MC_CMD_NVRAM_ERASE_IN msgrequest */ +#define MC_CMD_NVRAM_ERASE_IN_LEN 12 +#define MC_CMD_NVRAM_ERASE_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_ERASE_IN_OFFSET_OFST 4 +#define MC_CMD_NVRAM_ERASE_IN_LENGTH_OFST 8 + +/* MC_CMD_NVRAM_ERASE_OUT msgresponse */ +#define MC_CMD_NVRAM_ERASE_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_NVRAM_UPDATE_FINISH + * Finish a group of update operations on a virtual NVRAM partition. */ #define MC_CMD_NVRAM_UPDATE_FINISH 0x3c -#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 8 -#define MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_UPDATE_FINISH_IN_REBOOT_OFST 4 -#define MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0 -/* MC_CMD_REBOOT: +/* MC_CMD_NVRAM_UPDATE_FINISH_IN msgrequest */ +#define MC_CMD_NVRAM_UPDATE_FINISH_IN_LEN 8 +#define MC_CMD_NVRAM_UPDATE_FINISH_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ +#define MC_CMD_NVRAM_UPDATE_FINISH_IN_REBOOT_OFST 4 + +/* MC_CMD_NVRAM_UPDATE_FINISH_OUT msgresponse */ +#define MC_CMD_NVRAM_UPDATE_FINISH_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_REBOOT * Reboot the MC. - * - * The AFTER_ASSERTION flag is intended to be used when the driver notices - * an assertion failure (at which point it is expected to perform a complete - * tear down and reinitialise), to allow both ports to reset the MC once - * in an atomic fashion. - * - * Production mc firmwares are generally compiled with REBOOT_ON_ASSERT=1, - * which means that they will automatically reboot out of the assertion - * handler, so this is in practise an optional operation. It is still - * recommended that drivers execute this to support custom firmwares - * with REBOOT_ON_ASSERT=0. - * - * Locks required: NONE - * Returns: Nothing. You get back a response with ERR=1, DATALEN=0 */ #define MC_CMD_REBOOT 0x3d -#define MC_CMD_REBOOT_IN_LEN 4 -#define MC_CMD_REBOOT_IN_FLAGS_OFST 0 -#define MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION 1 -#define MC_CMD_REBOOT_OUT_LEN 0 -/* MC_CMD_SCHEDINFO: - * Request scheduler info. from the MC. - * - * Locks required: NONE - * Returns: An array of (timeslice,maximum overrun), one for each thread, - * in ascending order of thread address.s +/* MC_CMD_REBOOT_IN msgrequest */ +#define MC_CMD_REBOOT_IN_LEN 4 +#define MC_CMD_REBOOT_IN_FLAGS_OFST 0 +#define MC_CMD_REBOOT_FLAGS_AFTER_ASSERTION 0x1 /* enum */ + +/* MC_CMD_REBOOT_OUT msgresponse */ +#define MC_CMD_REBOOT_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_SCHEDINFO + * Request scheduler info. */ #define MC_CMD_SCHEDINFO 0x3e -#define MC_CMD_SCHEDINFO_IN_LEN 0 +/* MC_CMD_SCHEDINFO_IN msgrequest */ +#define MC_CMD_SCHEDINFO_IN_LEN 0 -/* MC_CMD_SET_REBOOT_MODE: (debug) - * Set the mode for the next MC reboot. - * - * Locks required: NONE - * - * Sets the reboot mode to the specified value. Returns the old mode. +/* MC_CMD_SCHEDINFO_OUT msgresponse */ +#define MC_CMD_SCHEDINFO_OUT_LENMIN 4 +#define MC_CMD_SCHEDINFO_OUT_LENMAX 252 +#define MC_CMD_SCHEDINFO_OUT_LEN(num) (0+4*(num)) +#define MC_CMD_SCHEDINFO_OUT_DATA_OFST 0 +#define MC_CMD_SCHEDINFO_OUT_DATA_LEN 4 +#define MC_CMD_SCHEDINFO_OUT_DATA_MINNUM 1 +#define MC_CMD_SCHEDINFO_OUT_DATA_MAXNUM 63 + + +/***********************************/ +/* MC_CMD_REBOOT_MODE */ #define MC_CMD_REBOOT_MODE 0x3f -#define MC_CMD_REBOOT_MODE_IN_LEN 4 -#define MC_CMD_REBOOT_MODE_IN_VALUE_OFST 0 -#define MC_CMD_REBOOT_MODE_OUT_LEN 4 -#define MC_CMD_REBOOT_MODE_OUT_VALUE_OFST 0 -#define MC_CMD_REBOOT_MODE_NORMAL 0 -#define MC_CMD_REBOOT_MODE_SNAPPER 3 - -/* MC_CMD_DEBUG_LOG: - * Null request/response command (debug) - * - sequence number is always zero - * - only supported on the UART interface - * (the same set of bytes is delivered as an - * event over PCI) - */ -#define MC_CMD_DEBUG_LOG 0x40 -#define MC_CMD_DEBUG_LOG_IN_LEN 0 -#define MC_CMD_DEBUG_LOG_OUT_LEN 0 - -/* Generic sensor enumeration. Note that a dual port NIC - * will EITHER expose PHY_COMMON_TEMP OR PHY0_TEMP and - * PHY1_TEMP depending on whether there is a single sensor - * in the vicinity of the two port, or one per port. - */ -#define MC_CMD_SENSOR_CONTROLLER_TEMP 0 /* degC */ -#define MC_CMD_SENSOR_PHY_COMMON_TEMP 1 /* degC */ -#define MC_CMD_SENSOR_CONTROLLER_COOLING 2 /* bool */ -#define MC_CMD_SENSOR_PHY0_TEMP 3 /* degC */ -#define MC_CMD_SENSOR_PHY0_COOLING 4 /* bool */ -#define MC_CMD_SENSOR_PHY1_TEMP 5 /* degC */ -#define MC_CMD_SENSOR_PHY1_COOLING 6 /* bool */ -#define MC_CMD_SENSOR_IN_1V0 7 /* mV */ -#define MC_CMD_SENSOR_IN_1V2 8 /* mV */ -#define MC_CMD_SENSOR_IN_1V8 9 /* mV */ -#define MC_CMD_SENSOR_IN_2V5 10 /* mV */ -#define MC_CMD_SENSOR_IN_3V3 11 /* mV */ -#define MC_CMD_SENSOR_IN_12V0 12 /* mV */ - - -/* Sensor state */ -#define MC_CMD_SENSOR_STATE_OK 0 -#define MC_CMD_SENSOR_STATE_WARNING 1 -#define MC_CMD_SENSOR_STATE_FATAL 2 -#define MC_CMD_SENSOR_STATE_BROKEN 3 - -/* MC_CMD_SENSOR_INFO: + +/* MC_CMD_REBOOT_MODE_IN msgrequest */ +#define MC_CMD_REBOOT_MODE_IN_LEN 4 +#define MC_CMD_REBOOT_MODE_IN_VALUE_OFST 0 +#define MC_CMD_REBOOT_MODE_NORMAL 0x0 /* enum */ +#define MC_CMD_REBOOT_MODE_SNAPPER 0x3 /* enum */ + +/* MC_CMD_REBOOT_MODE_OUT msgresponse */ +#define MC_CMD_REBOOT_MODE_OUT_LEN 4 +#define MC_CMD_REBOOT_MODE_OUT_VALUE_OFST 0 + + +/***********************************/ +/* MC_CMD_SENSOR_INFO * Returns information about every available sensor. - * - * Each sensor has a single (16bit) value, and a corresponding state. - * The mapping between value and sensor is nominally determined by the - * MC, but in practise is implemented as zero (BROKEN), one (TEMPERATURE), - * or two (VOLTAGE) ranges per sensor per state. - * - * This call returns a mask (32bit) of the sensors that are supported - * by this platform, then an array (indexed by MC_CMD_SENSOR) of byte - * offsets to the per-sensor arrays. Each sensor array has four 16bit - * numbers, min1, max1, min2, max2. - * - * Locks required: None - * Returns: 0 */ #define MC_CMD_SENSOR_INFO 0x41 -#define MC_CMD_SENSOR_INFO_IN_LEN 0 -#define MC_CMD_SENSOR_INFO_OUT_MASK_OFST 0 -#define MC_CMD_SENSOR_INFO_OUT_OFFSET_OFST(_x) \ - (4 + (_x)) -#define MC_CMD_SENSOR_INFO_OUT_MIN1_OFST(_ofst) \ - ((_ofst) + 0) -#define MC_CMD_SENSOR_INFO_OUT_MAX1_OFST(_ofst) \ - ((_ofst) + 2) -#define MC_CMD_SENSOR_INFO_OUT_MIN2_OFST(_ofst) \ - ((_ofst) + 4) -#define MC_CMD_SENSOR_INFO_OUT_MAX2_OFST(_ofst) \ - ((_ofst) + 6) +/* MC_CMD_SENSOR_INFO_IN msgrequest */ +#define MC_CMD_SENSOR_INFO_IN_LEN 0 + +/* MC_CMD_SENSOR_INFO_OUT msgresponse */ +#define MC_CMD_SENSOR_INFO_OUT_LENMIN 12 +#define MC_CMD_SENSOR_INFO_OUT_LENMAX 252 +#define MC_CMD_SENSOR_INFO_OUT_LEN(num) (4+8*(num)) +#define MC_CMD_SENSOR_INFO_OUT_MASK_OFST 0 +#define MC_CMD_SENSOR_CONTROLLER_TEMP 0x0 /* enum */ +#define MC_CMD_SENSOR_PHY_COMMON_TEMP 0x1 /* enum */ +#define MC_CMD_SENSOR_CONTROLLER_COOLING 0x2 /* enum */ +#define MC_CMD_SENSOR_PHY0_TEMP 0x3 /* enum */ +#define MC_CMD_SENSOR_PHY0_COOLING 0x4 /* enum */ +#define MC_CMD_SENSOR_PHY1_TEMP 0x5 /* enum */ +#define MC_CMD_SENSOR_PHY1_COOLING 0x6 /* enum */ +#define MC_CMD_SENSOR_IN_1V0 0x7 /* enum */ +#define MC_CMD_SENSOR_IN_1V2 0x8 /* enum */ +#define MC_CMD_SENSOR_IN_1V8 0x9 /* enum */ +#define MC_CMD_SENSOR_IN_2V5 0xa /* enum */ +#define MC_CMD_SENSOR_IN_3V3 0xb /* enum */ +#define MC_CMD_SENSOR_IN_12V0 0xc /* enum */ +#define MC_CMD_SENSOR_IN_1V2A 0xd /* enum */ +#define MC_CMD_SENSOR_IN_VREF 0xe /* enum */ +#define MC_CMD_SENSOR_ENTRY_OFST 4 +#define MC_CMD_SENSOR_ENTRY_LEN 8 +#define MC_CMD_SENSOR_ENTRY_LO_OFST 4 +#define MC_CMD_SENSOR_ENTRY_HI_OFST 8 +#define MC_CMD_SENSOR_ENTRY_MINNUM 1 +#define MC_CMD_SENSOR_ENTRY_MAXNUM 31 + +/* MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF structuredef */ +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_LEN 8 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_OFST 0 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_LEN 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_LBN 0 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN1_WIDTH 16 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_OFST 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_LEN 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_LBN 16 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX1_WIDTH 16 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_OFST 4 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_LEN 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_LBN 32 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MIN2_WIDTH 16 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_OFST 6 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_LEN 2 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_LBN 48 +#define MC_CMD_SENSOR_INFO_ENTRY_TYPEDEF_MAX2_WIDTH 16 + + +/***********************************/ /* MC_CMD_READ_SENSORS - * Returns the current reading from each sensor - * - * Returns a sparse array of sensor readings (indexed by the sensor - * type) into host memory. Each array element is a dword. - * - * The MC will send a SENSOREVT event every time any sensor changes state. The - * driver is responsible for ensuring that it doesn't miss any events. The board - * will function normally if all sensors are in STATE_OK or state_WARNING. - * Otherwise the board should not be expected to function. + * Returns the current reading from each sensor. */ #define MC_CMD_READ_SENSORS 0x42 -#define MC_CMD_READ_SENSORS_IN_LEN 8 -#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LO_OFST 0 -#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_HI_OFST 4 -#define MC_CMD_READ_SENSORS_OUT_LEN 0 -/* Sensor reading fields */ -#define MC_CMD_READ_SENSOR_VALUE_LBN 0 -#define MC_CMD_READ_SENSOR_VALUE_WIDTH 16 -#define MC_CMD_READ_SENSOR_STATE_LBN 16 -#define MC_CMD_READ_SENSOR_STATE_WIDTH 8 - - -/* MC_CMD_GET_PHY_STATE: - * Report current state of PHY. A "zombie" PHY is a PHY that has failed to - * boot (e.g. due to missing or corrupted firmware). - * - * Locks required: None - * Return code: 0 +/* MC_CMD_READ_SENSORS_IN msgrequest */ +#define MC_CMD_READ_SENSORS_IN_LEN 8 +#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_OFST 0 +#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LEN 8 +#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_LO_OFST 0 +#define MC_CMD_READ_SENSORS_IN_DMA_ADDR_HI_OFST 4 + +/* MC_CMD_READ_SENSORS_OUT msgresponse */ +#define MC_CMD_READ_SENSORS_OUT_LEN 0 + +/* MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF structuredef */ +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_LEN 3 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_OFST 0 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_LEN 2 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_LBN 0 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_VALUE_WIDTH 16 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_OFST 2 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_LEN 1 +#define MC_CMD_SENSOR_STATE_OK 0x0 /* enum */ +#define MC_CMD_SENSOR_STATE_WARNING 0x1 /* enum */ +#define MC_CMD_SENSOR_STATE_FATAL 0x2 /* enum */ +#define MC_CMD_SENSOR_STATE_BROKEN 0x3 /* enum */ +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_LBN 16 +#define MC_CMD_SENSOR_VALUE_ENTRY_TYPEDEF_STATE_WIDTH 8 + + +/***********************************/ +/* MC_CMD_GET_PHY_STATE + * Report current state of PHY. */ #define MC_CMD_GET_PHY_STATE 0x43 -#define MC_CMD_GET_PHY_STATE_IN_LEN 0 -#define MC_CMD_GET_PHY_STATE_OUT_LEN 4 -#define MC_CMD_GET_PHY_STATE_STATE_OFST 0 -/* PHY state enumeration: */ -#define MC_CMD_PHY_STATE_OK 1 -#define MC_CMD_PHY_STATE_ZOMBIE 2 +/* MC_CMD_GET_PHY_STATE_IN msgrequest */ +#define MC_CMD_GET_PHY_STATE_IN_LEN 0 +/* MC_CMD_GET_PHY_STATE_OUT msgresponse */ +#define MC_CMD_GET_PHY_STATE_OUT_LEN 4 +#define MC_CMD_GET_PHY_STATE_OUT_STATE_OFST 0 +#define MC_CMD_PHY_STATE_OK 0x1 /* enum */ +#define MC_CMD_PHY_STATE_ZOMBIE 0x2 /* enum */ -/* 802.1Qbb control. 8 Tx queues that map to priorities 0 - 7. Use all 1s to - * disable 802.Qbb for a given priority. */ + +/***********************************/ +/* MC_CMD_SETUP_8021QBB + * 802.1Qbb control. + */ #define MC_CMD_SETUP_8021QBB 0x44 -#define MC_CMD_SETUP_8021QBB_IN_LEN 32 -#define MC_CMD_SETUP_8021QBB_OUT_LEN 0 -#define MC_CMD_SETUP_8021QBB_IN_TXQS_OFFST 0 +/* MC_CMD_SETUP_8021QBB_IN msgrequest */ +#define MC_CMD_SETUP_8021QBB_IN_LEN 32 +#define MC_CMD_SETUP_8021QBB_IN_TXQS_OFST 0 +#define MC_CMD_SETUP_8021QBB_IN_TXQS_LEN 32 -/* MC_CMD_WOL_FILTER_GET: - * Retrieve ID of any WoL filters - * - * Locks required: None - * Returns: 0, ENOSYS - */ -#define MC_CMD_WOL_FILTER_GET 0x45 -#define MC_CMD_WOL_FILTER_GET_IN_LEN 0 -#define MC_CMD_WOL_FILTER_GET_OUT_LEN 4 -#define MC_CMD_WOL_FILTER_GET_OUT_FILTER_ID_OFST 0 +/* MC_CMD_SETUP_8021QBB_OUT msgresponse */ +#define MC_CMD_SETUP_8021QBB_OUT_LEN 0 -/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD: - * Offload a protocol to NIC for lights-out state - * - * Locks required: None - * Returns: 0, ENOSYS +/***********************************/ +/* MC_CMD_WOL_FILTER_GET + * Retrieve ID of any WoL filters. */ -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD 0x46 +#define MC_CMD_WOL_FILTER_GET 0x45 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LEN 16 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 +/* MC_CMD_WOL_FILTER_GET_IN msgrequest */ +#define MC_CMD_WOL_FILTER_GET_IN_LEN 0 -/* There is a union at offset 4, following defines overlap due to - * this */ -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_OFST 4 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARPMAC_OFST 4 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARPIP_OFST 10 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSMAC_OFST 4 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSSNIPV6_OFST 10 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NSIPV6_OFST 26 +/* MC_CMD_WOL_FILTER_GET_OUT msgresponse */ +#define MC_CMD_WOL_FILTER_GET_OUT_LEN 4 +#define MC_CMD_WOL_FILTER_GET_OUT_FILTER_ID_OFST 0 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN 4 -#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID_OFST 0 +/***********************************/ +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD + * Add a protocol offload to NIC for lights-out state. + */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD 0x46 -/* MC_CMD_REMOVE_LIGHTSOUT_PROTOCOL_OFFLOAD: - * Offload a protocol to NIC for lights-out state - * - * Locks required: None - * Returns: 0, ENOSYS +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN msgrequest */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LENMIN 8 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LENMAX 252 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_LEN(num) (4+4*(num)) +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 +#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP 0x1 /* enum */ +#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS 0x2 /* enum */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_OFST 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_LEN 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_MINNUM 1 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_DATA_MAXNUM 62 + +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP msgrequest */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_LEN 14 +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC_OFST 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_MAC_LEN 6 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_ARP_IP_OFST 10 + +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS msgrequest */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_LEN 42 +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC_OFST 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_MAC_LEN 6 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6_OFST 10 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_SNIPV6_LEN 16 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6_OFST 26 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_IN_NS_IPV6_LEN 16 + +/* MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT msgresponse */ +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_LEN 4 +#define MC_CMD_ADD_LIGHTSOUT_OFFLOAD_OUT_FILTER_ID_OFST 0 + + +/***********************************/ +/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD + * Remove a protocol offload from NIC for lights-out state. */ #define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD 0x47 -#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN 8 -#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN 0 -#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 -#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID_OFST 4 +/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN msgrequest */ +#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_LEN 8 +#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_PROTOCOL_OFST 0 +#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_IN_FILTER_ID_OFST 4 -/* Lights-out offload protocols enumeration */ -#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_ARP 0x1 -#define MC_CMD_LIGHTSOUT_OFFLOAD_PROTOCOL_NS 0x2 +/* MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT msgresponse */ +#define MC_CMD_REMOVE_LIGHTSOUT_OFFLOAD_OUT_LEN 0 -/* MC_CMD_MAC_RESET_RESTORE: - * Restore MAC after block reset - * - * Locks required: None - * Returns: 0 +/***********************************/ +/* MC_CMD_MAC_RESET_RESTORE + * Restore MAC after block reset. */ - #define MC_CMD_MAC_RESET_RESTORE 0x48 -#define MC_CMD_MAC_RESET_RESTORE_IN_LEN 0 -#define MC_CMD_MAC_RESET_RESTORE_OUT_LEN 0 +/* MC_CMD_MAC_RESET_RESTORE_IN msgrequest */ +#define MC_CMD_MAC_RESET_RESTORE_IN_LEN 0 + +/* MC_CMD_MAC_RESET_RESTORE_OUT msgresponse */ +#define MC_CMD_MAC_RESET_RESTORE_OUT_LEN 0 -/* MC_CMD_TEST_ASSERT: - * Deliberately trigger an assert-detonation in the firmware for testing - * purposes (i.e. to allow tests that the driver copes gracefully). - * - * Locks required: None - * Returns: 0 - */ +/***********************************/ +/* MC_CMD_TESTASSERT + */ #define MC_CMD_TESTASSERT 0x49 -#define MC_CMD_TESTASSERT_IN_LEN 0 -#define MC_CMD_TESTASSERT_OUT_LEN 0 -/* MC_CMD_WORKAROUND 0x4a - * - * Enable/Disable a given workaround. The mcfw will return EINVAL if it - * doesn't understand the given workaround number - which should not - * be treated as a hard error by client code. - * - * This op does not imply any semantics about each workaround, that's between - * the driver and the mcfw on a per-workaround basis. - * - * Locks required: None - * Returns: 0, EINVAL +/* MC_CMD_TESTASSERT_IN msgrequest */ +#define MC_CMD_TESTASSERT_IN_LEN 0 + +/* MC_CMD_TESTASSERT_OUT msgresponse */ +#define MC_CMD_TESTASSERT_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_WORKAROUND + * Enable/Disable a given workaround. */ #define MC_CMD_WORKAROUND 0x4a -#define MC_CMD_WORKAROUND_IN_LEN 8 -#define MC_CMD_WORKAROUND_IN_TYPE_OFST 0 -#define MC_CMD_WORKAROUND_BUG17230 1 -#define MC_CMD_WORKAROUND_IN_ENABLED_OFST 4 -#define MC_CMD_WORKAROUND_OUT_LEN 0 - -/* MC_CMD_GET_PHY_MEDIA_INFO: - * Read media-specific data from PHY (e.g. SFP/SFP+ module ID information for - * SFP+ PHYs). - * - * The "media type" can be found via GET_PHY_CFG (GET_PHY_CFG_OUT_MEDIA_TYPE); - * the valid "page number" input values, and the output data, are interpreted - * on a per-type basis. - * - * For SFP+: PAGE=0 or 1 returns a 128-byte block read from module I2C address - * 0xA0 offset 0 or 0x80. - * Anything else: currently undefined. - * - * Locks required: None - * Return code: 0 + +/* MC_CMD_WORKAROUND_IN msgrequest */ +#define MC_CMD_WORKAROUND_IN_LEN 8 +#define MC_CMD_WORKAROUND_IN_TYPE_OFST 0 +#define MC_CMD_WORKAROUND_BUG17230 0x1 /* enum */ +#define MC_CMD_WORKAROUND_IN_ENABLED_OFST 4 + +/* MC_CMD_WORKAROUND_OUT msgresponse */ +#define MC_CMD_WORKAROUND_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_PHY_MEDIA_INFO + * Read media-specific data from PHY. */ #define MC_CMD_GET_PHY_MEDIA_INFO 0x4b -#define MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN 4 -#define MC_CMD_GET_PHY_MEDIA_INFO_IN_PAGE_OFST 0 -#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(_num_bytes) (4 + (_num_bytes)) -#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0 -#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4 - -/* MC_CMD_NVRAM_TEST: - * Test a particular NVRAM partition for valid contents (where "valid" - * depends on the type of partition). - * - * Locks required: None - * Return code: 0 + +/* MC_CMD_GET_PHY_MEDIA_INFO_IN msgrequest */ +#define MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN 4 +#define MC_CMD_GET_PHY_MEDIA_INFO_IN_PAGE_OFST 0 + +/* MC_CMD_GET_PHY_MEDIA_INFO_OUT msgresponse */ +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMIN 5 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX 255 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_LEN(num) (4+1*(num)) +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATALEN_OFST 0 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_OFST 4 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_LEN 1 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MINNUM 1 +#define MC_CMD_GET_PHY_MEDIA_INFO_OUT_DATA_MAXNUM 251 + + +/***********************************/ +/* MC_CMD_NVRAM_TEST + * Test a particular NVRAM partition. */ #define MC_CMD_NVRAM_TEST 0x4c -#define MC_CMD_NVRAM_TEST_IN_LEN 4 -#define MC_CMD_NVRAM_TEST_IN_TYPE_OFST 0 -#define MC_CMD_NVRAM_TEST_OUT_LEN 4 -#define MC_CMD_NVRAM_TEST_OUT_RESULT_OFST 0 -#define MC_CMD_NVRAM_TEST_PASS 0 -#define MC_CMD_NVRAM_TEST_FAIL 1 -#define MC_CMD_NVRAM_TEST_NOTSUPP 2 - -/* MC_CMD_MRSFP_TWEAK: (debug) - * Read status and/or set parameters for the "mrsfp" driver in mr_rusty builds. - * I2C I/O expander bits are always read; if equaliser parameters are supplied, - * they are configured first. - * - * Locks required: None - * Return code: 0, EINVAL + +/* MC_CMD_NVRAM_TEST_IN msgrequest */ +#define MC_CMD_NVRAM_TEST_IN_LEN 4 +#define MC_CMD_NVRAM_TEST_IN_TYPE_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_NVRAM_TYPES/MC_CMD_NVRAM_TYPES_OUT/TYPES */ + +/* MC_CMD_NVRAM_TEST_OUT msgresponse */ +#define MC_CMD_NVRAM_TEST_OUT_LEN 4 +#define MC_CMD_NVRAM_TEST_OUT_RESULT_OFST 0 +#define MC_CMD_NVRAM_TEST_PASS 0x0 /* enum */ +#define MC_CMD_NVRAM_TEST_FAIL 0x1 /* enum */ +#define MC_CMD_NVRAM_TEST_NOTSUPP 0x2 /* enum */ + + +/***********************************/ +/* MC_CMD_MRSFP_TWEAK + * Read status and/or set parameters for the 'mrsfp' driver. */ #define MC_CMD_MRSFP_TWEAK 0x4d -#define MC_CMD_MRSFP_TWEAK_IN_LEN_READ_ONLY 0 -#define MC_CMD_MRSFP_TWEAK_IN_LEN_EQ_CONFIG 16 -#define MC_CMD_MRSFP_TWEAK_IN_TXEQ_LEVEL_OFST 0 /* 0-6 low->high de-emph. */ -#define MC_CMD_MRSFP_TWEAK_IN_TXEQ_DT_CFG_OFST 4 /* 0-8 low->high ref.V */ -#define MC_CMD_MRSFP_TWEAK_IN_RXEQ_BOOST_OFST 8 /* 0-8 low->high boost */ -#define MC_CMD_MRSFP_TWEAK_IN_RXEQ_DT_CFG_OFST 12 /* 0-8 low->high ref.V */ -#define MC_CMD_MRSFP_TWEAK_OUT_LEN 12 -#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_INPUTS_OFST 0 /* input bits */ -#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_OUTPUTS_OFST 4 /* output bits */ -#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OFST 8 /* dirs: 0=out, 1=in */ - -/* MC_CMD_TEST_HACK: (debug (unsurprisingly)) - * Change bits of network port state for test purposes in ways that would never be - * useful in normal operation and so need a special command to change. */ -#define MC_CMD_TEST_HACK 0x2f -#define MC_CMD_TEST_HACK_IN_LEN 8 -#define MC_CMD_TEST_HACK_IN_TXPAD_OFST 0 -#define MC_CMD_TEST_HACK_IN_TXPAD_AUTO 0 /* Let the MC manage things */ -#define MC_CMD_TEST_HACK_IN_TXPAD_ON 1 /* Force on */ -#define MC_CMD_TEST_HACK_IN_TXPAD_OFF 2 /* Force on */ -#define MC_CMD_TEST_HACK_IN_IPG_OFST 4 /* Takes a value in bits */ -#define MC_CMD_TEST_HACK_IN_IPG_AUTO 0 /* The MC picks the value */ -#define MC_CMD_TEST_HACK_OUT_LEN 0 - -/* MC_CMD_SENSOR_SET_LIMS: (debug) (mostly) adjust the sensor limits. This - * is a warranty-voiding operation. - * - * IN: sensor identifier (one of the enumeration starting with MC_CMD_SENSOR_CONTROLLER_TEMP - * followed by 4 32-bit values: min(warning) max(warning), min(fatal), max(fatal). Which - * of these limits are meaningful and what their interpretation is is sensor-specific. - * - * OUT: nothing - * - * Returns: ENOENT if the sensor specified does not exist, EINVAL if the limits are - * out of range. + +/* MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG msgrequest */ +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_LEN 16 +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_TXEQ_LEVEL_OFST 0 +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_TXEQ_DT_CFG_OFST 4 +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_RXEQ_BOOST_OFST 8 +#define MC_CMD_MRSFP_TWEAK_IN_EQ_CONFIG_RXEQ_DT_CFG_OFST 12 + +/* MC_CMD_MRSFP_TWEAK_IN_READ_ONLY msgrequest */ +#define MC_CMD_MRSFP_TWEAK_IN_READ_ONLY_LEN 0 + +/* MC_CMD_MRSFP_TWEAK_OUT msgresponse */ +#define MC_CMD_MRSFP_TWEAK_OUT_LEN 12 +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_INPUTS_OFST 0 +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_OUTPUTS_OFST 4 +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OFST 8 +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_OUT 0x0 /* enum */ +#define MC_CMD_MRSFP_TWEAK_OUT_IOEXP_DIRECTION_IN 0x1 /* enum */ + + +/***********************************/ +/* MC_CMD_SENSOR_SET_LIMS + * Adjusts the sensor limits. */ #define MC_CMD_SENSOR_SET_LIMS 0x4e -#define MC_CMD_SENSOR_SET_LIMS_IN_LEN 20 -#define MC_CMD_SENSOR_SET_LIMS_IN_SENSOR_OFST 0 -#define MC_CMD_SENSOR_SET_LIMS_IN_LOW0_OFST 4 -#define MC_CMD_SENSOR_SET_LIMS_IN_HI0_OFST 8 -#define MC_CMD_SENSOR_SET_LIMS_IN_LOW1_OFST 12 -#define MC_CMD_SENSOR_SET_LIMS_IN_HI1_OFST 16 - -/* Do NOT add new commands beyond 0x4f as part of 3.0 : 0x50 - 0x7f will be - * used for post-3.0 extensions. If you run out of space, look for gaps or - * commands that are unused in the existing range. */ + +/* MC_CMD_SENSOR_SET_LIMS_IN msgrequest */ +#define MC_CMD_SENSOR_SET_LIMS_IN_LEN 20 +#define MC_CMD_SENSOR_SET_LIMS_IN_SENSOR_OFST 0 +/* Enum values, see field(s): */ +/* MC_CMD_SENSOR_INFO/MC_CMD_SENSOR_INFO_OUT/MASK */ +#define MC_CMD_SENSOR_SET_LIMS_IN_LOW0_OFST 4 +#define MC_CMD_SENSOR_SET_LIMS_IN_HI0_OFST 8 +#define MC_CMD_SENSOR_SET_LIMS_IN_LOW1_OFST 12 +#define MC_CMD_SENSOR_SET_LIMS_IN_HI1_OFST 16 + +/* MC_CMD_SENSOR_SET_LIMS_OUT msgresponse */ +#define MC_CMD_SENSOR_SET_LIMS_OUT_LEN 0 + + +/***********************************/ +/* MC_CMD_GET_RESOURCE_LIMITS + */ +#define MC_CMD_GET_RESOURCE_LIMITS 0x4f + +/* MC_CMD_GET_RESOURCE_LIMITS_IN msgrequest */ +#define MC_CMD_GET_RESOURCE_LIMITS_IN_LEN 0 + +/* MC_CMD_GET_RESOURCE_LIMITS_OUT msgresponse */ +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_LEN 16 +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_BUFTBL_OFST 0 +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_EVQ_OFST 4 +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_RXQ_OFST 8 +#define MC_CMD_GET_RESOURCE_LIMITS_OUT_TXQ_OFST 12 + +/* MC_CMD_RESOURCE_SPECIFIER enum */ +#define MC_CMD_RESOURCE_INSTANCE_ANY 0xffffffff /* enum */ +#define MC_CMD_RESOURCE_INSTANCE_NONE 0xfffffffe /* enum */ + #endif /* MCDI_PCOL_H */ diff --git a/drivers/net/ethernet/sfc/mcdi_phy.c b/drivers/net/ethernet/sfc/mcdi_phy.c index 3077bf1e7dfe..7bcad899a936 100644 --- a/drivers/net/ethernet/sfc/mcdi_phy.c +++ b/drivers/net/ethernet/sfc/mcdi_phy.c @@ -116,7 +116,7 @@ static int efx_mcdi_loopback_modes(struct efx_nic *efx, u64 *loopback_modes) goto fail; } - *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_SUGGESTED); + *loopback_modes = MCDI_QWORD(outbuf, GET_LOOPBACK_MODES_OUT_SUGGESTED); return 0; @@ -264,22 +264,22 @@ static u32 efx_get_mcdi_phy_flags(struct efx_nic *efx) /* TODO: Advertise the capabilities supported by this PHY */ supported = 0; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_TXDIS_LBN)) + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_TXDIS_LBN)) supported |= PHY_MODE_TX_DISABLED; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_LOWPOWER_LBN)) + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_LOWPOWER_LBN)) supported |= PHY_MODE_LOW_POWER; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_POWEROFF_LBN)) + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_POWEROFF_LBN)) supported |= PHY_MODE_OFF; mode = efx->phy_mode & supported; flags = 0; if (mode & PHY_MODE_TX_DISABLED) - flags |= (1 << MC_CMD_SET_LINK_TXDIS_LBN); + flags |= (1 << MC_CMD_SET_LINK_IN_TXDIS_LBN); if (mode & PHY_MODE_LOW_POWER) - flags |= (1 << MC_CMD_SET_LINK_LOWPOWER_LBN); + flags |= (1 << MC_CMD_SET_LINK_IN_LOWPOWER_LBN); if (mode & PHY_MODE_OFF) - flags |= (1 << MC_CMD_SET_LINK_POWEROFF_LBN); + flags |= (1 << MC_CMD_SET_LINK_IN_POWEROFF_LBN); return flags; } @@ -436,8 +436,8 @@ void efx_mcdi_phy_decode_link(struct efx_nic *efx, break; } - link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_LINK_UP_LBN)); - link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_FULL_DUPLEX_LBN)); + link_state->up = !!(flags & (1 << MC_CMD_GET_LINK_OUT_LINK_UP_LBN)); + link_state->fd = !!(flags & (1 << MC_CMD_GET_LINK_OUT_FULL_DUPLEX_LBN)); link_state->speed = speed; } @@ -592,7 +592,7 @@ static int efx_mcdi_phy_test_alive(struct efx_nic *efx) if (outlen < MC_CMD_GET_PHY_STATE_OUT_LEN) return -EIO; - if (MCDI_DWORD(outbuf, GET_PHY_STATE_STATE) != MC_CMD_PHY_STATE_OK) + if (MCDI_DWORD(outbuf, GET_PHY_STATE_OUT_STATE) != MC_CMD_PHY_STATE_OK) return -EINVAL; return 0; @@ -680,7 +680,7 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results, u32 mode; int rc; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) { + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) { rc = efx_mcdi_bist(efx, MC_CMD_PHY_BIST, results); if (rc < 0) return rc; @@ -691,15 +691,15 @@ static int efx_mcdi_phy_run_tests(struct efx_nic *efx, int *results, /* If we support both LONG and SHORT, then run each in response to * break or not. Otherwise, run the one we support */ mode = 0; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN)) { + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN)) { if ((flags & ETH_TEST_FL_OFFLINE) && (phy_cfg->flags & - (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN))) + (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))) mode = MC_CMD_PHY_BIST_CABLE_LONG; else mode = MC_CMD_PHY_BIST_CABLE_SHORT; } else if (phy_cfg->flags & - (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN)) + (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN)) mode = MC_CMD_PHY_BIST_CABLE_LONG; if (mode != 0) { @@ -717,14 +717,14 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, { struct efx_mcdi_phy_data *phy_cfg = efx->phy_data; - if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_BIST_LBN)) { + if (phy_cfg->flags & (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_LBN)) { if (index == 0) return "bist"; --index; } - if (phy_cfg->flags & ((1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_SHORT_LBN) | - (1 << MC_CMD_GET_PHY_CFG_BIST_CABLE_LONG_LBN))) { + if (phy_cfg->flags & ((1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_SHORT_LBN) | + (1 << MC_CMD_GET_PHY_CFG_OUT_BIST_CABLE_LONG_LBN))) { if (index == 0) return "cable"; --index; diff --git a/drivers/net/ethernet/sfc/mtd.c b/drivers/net/ethernet/sfc/mtd.c index 13f61fba731f..7f61cd3812d9 100644 --- a/drivers/net/ethernet/sfc/mtd.c +++ b/drivers/net/ethernet/sfc/mtd.c @@ -627,8 +627,7 @@ static int siena_mtd_get_fw_subtypes(struct efx_nic *efx, struct efx_mtd *efx_mtd) { struct efx_mtd_partition *part; - uint16_t fw_subtype_list[MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN / - sizeof(uint16_t)]; + uint16_t fw_subtype_list[MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM]; int rc; rc = efx_mcdi_get_board_cfg(efx, NULL, fw_subtype_list); -- GitLab From fa142b9da3393fd92b398b6bdecf3f21914e309b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 20 Dec 2011 01:15:30 +0000 Subject: [PATCH 00072/10698] sfc: Rename efx_wanted_channels() to efx_wanted_parallelism() This function returns the degree of parallelism wanted, which is not necessarily the total number of channels we want to create. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 9ca5dcdf5a86..5fcc42f7d865 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1146,9 +1146,7 @@ static void efx_fini_io(struct efx_nic *efx) pci_disable_device(efx->pci_dev); } -/* Get number of channels wanted. Each channel will have its own IRQ, - * 1 RX queue and/or 2 TX queues. */ -static int efx_wanted_channels(void) +static int efx_wanted_parallelism(void) { cpumask_var_t core_mask; int count; @@ -1211,7 +1209,7 @@ static int efx_probe_interrupts(struct efx_nic *efx) struct msix_entry xentries[EFX_MAX_CHANNELS]; int n_channels; - n_channels = efx_wanted_channels(); + n_channels = efx_wanted_parallelism(); if (separate_tx_channels) n_channels *= 2; n_channels = min(n_channels, max_channels); -- GitLab From cdb08f8fd8642a6d661c920f565e85cf87a0c9be Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 20 Dec 2011 01:08:05 +0000 Subject: [PATCH 00073/10698] sfc: Set default parallelism to per-core by default The previous default of per-package can be more CPU-efficient, but users generally seem to prefer per-core. It should also allow accelerated RFS to direct packets more precisely, if IRQ affinity is properly spread out. Signed-off-by: Ben Hutchings --- drivers/net/ethernet/sfc/efx.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 5fcc42f7d865..d7301d2e81a7 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -162,7 +162,7 @@ static unsigned int interrupt_mode; * interrupt handling. * * Cards without MSI-X will only target one CPU via legacy or MSI interrupt. - * The default (0) means to assign an interrupt to each package (level II cache) + * The default (0) means to assign an interrupt to each core. */ static unsigned int rss_cpus; module_param(rss_cpus, uint, 0444); @@ -1148,14 +1148,14 @@ static void efx_fini_io(struct efx_nic *efx) static int efx_wanted_parallelism(void) { - cpumask_var_t core_mask; + cpumask_var_t thread_mask; int count; int cpu; if (rss_cpus) return rss_cpus; - if (unlikely(!zalloc_cpumask_var(&core_mask, GFP_KERNEL))) { + if (unlikely(!zalloc_cpumask_var(&thread_mask, GFP_KERNEL))) { printk(KERN_WARNING "sfc: RSS disabled due to allocation failure\n"); return 1; @@ -1163,14 +1163,14 @@ static int efx_wanted_parallelism(void) count = 0; for_each_online_cpu(cpu) { - if (!cpumask_test_cpu(cpu, core_mask)) { + if (!cpumask_test_cpu(cpu, thread_mask)) { ++count; - cpumask_or(core_mask, core_mask, - topology_core_cpumask(cpu)); + cpumask_or(thread_mask, thread_mask, + topology_thread_cpumask(cpu)); } } - free_cpumask_var(core_mask); + free_cpumask_var(thread_mask); return count; } -- GitLab From 12183a20a8baf009bf570ab3db45a27fd6b1fd03 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 21 Dec 2011 23:01:20 +0100 Subject: [PATCH 00074/10698] mtd: nand: fix typo in comment Funny one :) "Heck" fits somehow, too, but I am sure it was meant to be "Check". Signed-off-by: Wolfram Sang Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- drivers/mtd/nand/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 35b4565050f1..8a393f9e6027 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2588,7 +2588,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr, instr->state = MTD_ERASING; while (len) { - /* Heck if we have a bad block, we do not erase bad blocks! */ + /* Check if we have a bad block, we do not erase bad blocks! */ if (nand_block_checkbad(mtd, ((loff_t) page) << chip->page_shift, 0, allowbbt)) { pr_warn("%s: attempt to erase a bad block at page 0x%08x\n", -- GitLab From 9398d1ce09b9009996f7d2468e1d3c785fa6feda Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Wed, 4 Jan 2012 11:18:46 +0800 Subject: [PATCH 00075/10698] mtd: gpmi-nand bugfix: reset the BCH module when it is not MX23 In MX28, if we do not reset the BCH module. The BCH module may becomes unstable when the board reboots for several thousands times. This bug has been catched in customer's production. The patch adds some comments (some from Wolfram Sang), and fixes it now. Also change gpmi_reset_block() to static. Signed-off-by: Huang Shijie Acked-by: Marek Vasut Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Cc: stable@kernel.org [3.1+] --- drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 2a56fc6f399a..c56f8e021b90 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -69,17 +69,19 @@ static int clear_poll_bit(void __iomem *addr, u32 mask) * [1] enable the module. * [2] reset the module. * - * In most of the cases, it's ok. But there is a hardware bug in the BCH block. + * In most of the cases, it's ok. + * But in MX23, there is a hardware bug in the BCH block (see erratum #2847). * If you try to soft reset the BCH block, it becomes unusable until * the next hard reset. This case occurs in the NAND boot mode. When the board * boots by NAND, the ROM of the chip will initialize the BCH blocks itself. * So If the driver tries to reset the BCH again, the BCH will not work anymore. - * You will see a DMA timeout in this case. + * You will see a DMA timeout in this case. The bug has been fixed + * in the following chips, such as MX28. * * To avoid this bug, just add a new parameter `just_enable` for * the mxs_reset_block(), and rewrite it here. */ -int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) +static int gpmi_reset_block(void __iomem *reset_addr, bool just_enable) { int ret; int timeout = 0x400; @@ -206,7 +208,15 @@ int bch_set_geometry(struct gpmi_nand_data *this) if (ret) goto err_out; - ret = gpmi_reset_block(r->bch_regs, true); + /* + * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this + * chip, otherwise it will lock up. So we skip resetting BCH on the MX23. + * On the other hand, the MX28 needs the reset, because one case has been + * seen where the BCH produced ECC errors constantly after 10000 + * consecutive reboots. The latter case has not been seen on the MX23 yet, + * still we don't know if it could happen there as well. + */ + ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); if (ret) goto err_out; -- GitLab From bce41d601e58af12cee1398fe836e6b9a8fb5396 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 10 Jan 2012 15:32:29 +0200 Subject: [PATCH 00076/10698] jffs2: do not initialize variable unnecessarily Remove unnecessary initializer for a local variable. Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse --- fs/jffs2/erase.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a01cdad6aad1..eafb8d37a6fb 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -335,7 +335,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl void *ebuf; uint32_t ofs; size_t retlen; - int ret = -EIO; + int ret; unsigned long *wordebuf; ret = mtd_point(c->mtd, jeb->offset, c->sector_size, &retlen, -- GitLab From 866dc88607aa07f297eec7b504be58ca17d91a26 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 10 Jan 2012 09:53:23 +0530 Subject: [PATCH 00077/10698] ath6kl: Fix SDIO error path sdio_release_host() would be called twice if sdio_set_block_size() fails for some reason, which would result in the following warning. WARNING: at /home/sujith/dev/wireless-testing/drivers/mmc/core/core.c:828 mmc_release_host+0x42/0x50 [mmc_core]() Call Trace: [] warn_slowpath_common+0x7f/0xc0 [] warn_slowpath_null+0x1a/0x20 [] mmc_release_host+0x42/0x50 [mmc_core] [] sdio_release_host+0x1e/0x30 [mmc_core] [] ath6kl_sdio_config+0xc7/0x110 [ath6kl_sdio] [] ath6kl_sdio_probe+0x21c/0x320 [ath6kl_sdio] [] ? mmc_release_host+0x2a/0x50 [mmc_core] [] sdio_bus_probe+0xfa/0x130 [mmc_core] [] driver_probe_device+0x7e/0x1b0 [] __driver_attach+0xab/0xb0 [] ? driver_probe_device+0x1b0/0x1b0 [] ? driver_probe_device+0x1b0/0x1b0 [] bus_for_each_dev+0x64/0xa0 [] driver_attach+0x1e/0x20 [] bus_add_driver+0x1b0/0x280 [] ? 0xffffffffa0064fff [] driver_register+0x76/0x140 [] ? 0xffffffffa0064fff [] sdio_register_driver+0x21/0x30 [mmc_core] [] ath6kl_sdio_init+0x12/0x35 [ath6kl_sdio] [] do_one_initcall+0x42/0x180 [] sys_init_module+0x8f/0x200 [] system_call_fastpath+0x16/0x1b Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/sdio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 8b36904ec3ec..50b19d3aefa7 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -770,7 +770,6 @@ static int ath6kl_sdio_config(struct ath6kl *ar) if (ret) { ath6kl_err("Set sdio block size %d failed: %d)\n", HIF_MBOX_BLOCK_SIZE, ret); - sdio_release_host(func); goto out; } -- GitLab From 4a8ce2fd055f8c117fb6fa6da39af8f62cbffe4b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 10 Jan 2012 09:53:38 +0530 Subject: [PATCH 00078/10698] ath6kl: Remove redundant pointer check 'params' is already used earlier and there is no point in checking for a NULL condition again. Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 31 +++++++++++----------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 14f180eac485..9b26bbaf124e 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -983,6 +983,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, struct ath6kl *ar = ath6kl_priv(ndev); struct ath6kl_vif *vif = netdev_priv(ndev); struct ath6kl_key *key = NULL; + int seq_len; u8 key_usage; u8 key_type; @@ -1011,23 +1012,21 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, else key_usage = GROUP_USAGE; - if (params) { - int seq_len = params->seq_len; - if (params->cipher == WLAN_CIPHER_SUITE_SMS4 && - seq_len > ATH6KL_KEY_SEQ_LEN) { - /* Only first half of the WPI PN is configured */ - seq_len = ATH6KL_KEY_SEQ_LEN; - } - if (params->key_len > WLAN_MAX_KEY_LEN || - seq_len > sizeof(key->seq)) - return -EINVAL; - - key->key_len = params->key_len; - memcpy(key->key, params->key, key->key_len); - key->seq_len = seq_len; - memcpy(key->seq, params->seq, key->seq_len); - key->cipher = params->cipher; + seq_len = params->seq_len; + if (params->cipher == WLAN_CIPHER_SUITE_SMS4 && + seq_len > ATH6KL_KEY_SEQ_LEN) { + /* Only first half of the WPI PN is configured */ + seq_len = ATH6KL_KEY_SEQ_LEN; } + if (params->key_len > WLAN_MAX_KEY_LEN || + seq_len > sizeof(key->seq)) + return -EINVAL; + + key->key_len = params->key_len; + memcpy(key->key, params->key, key->key_len); + key->seq_len = seq_len; + memcpy(key->seq, params->seq, key->seq_len); + key->cipher = params->cipher; switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: -- GitLab From cbec267a5143f70ece4069d18889a442bcb3365b Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 10 Jan 2012 09:53:53 +0530 Subject: [PATCH 00079/10698] ath6kl: Initialize a variable properly This prevents 'comp_pktq' from being used in an incorrect manner. Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/htc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index b01702258faf..2d721903640b 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c @@ -2062,6 +2062,7 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, enum htc_endpoint_id id; int n_fetched = 0; + INIT_LIST_HEAD(&comp_pktq); *num_pkts = 0; /* -- GitLab From 8232736dabd2a0310f76944fa7af0542fe3ded4f Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Tue, 10 Jan 2012 09:54:10 +0530 Subject: [PATCH 00080/10698] ath6kl: Fix listen interval handling This patch addresses a few problems with the commit: "ath6kl: Implement support for listen interval from userspace" * The debugfs file required for reading/writing the listen interval wasn't created. Fix this. * The interface index was being hardcoded to zero. Fix this. * Two separate parameters, "listen_interval_time and listen_interval_beacons" were being used. This fails to work as expected because the FW assigns higher precedence to "listen_interval_beacons" and "listen_interval_time" ends up being never used at all. To handle this, fix the host driver to exclusively use listen interval based on units of beacon intervals. To set the listen interval, a user would now do something like this: echo "10" > /sys/kernel/debug/ieee80211/*/ath6kl/listen_interval kvalo: fix two checkpatch warnings Signed-off-by: Sujith Manoharan Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 +- drivers/net/wireless/ath/ath6kl/core.h | 3 +- drivers/net/wireless/ath/ath6kl/debug.c | 44 +++++++++------------- drivers/net/wireless/ath/ath6kl/main.c | 7 ++-- 4 files changed, 24 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 9b26bbaf124e..1a98c9256c60 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2725,8 +2725,7 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev) clear_bit(SKIP_SCAN, &ar->flag); clear_bit(DESTROY_IN_PROGRESS, &ar->flag); - ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL; - ar->listen_intvl_b = 0; + ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL; ar->tx_pwr = 0; ar->intra_bss = 1; diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 793c6a58f0fd..f4da5e19a365 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -55,7 +55,7 @@ #define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC) #define DISCON_TIMER_INTVAL 10000 /* in msec */ -#define A_DEFAULT_LISTEN_INTERVAL 100 +#define A_DEFAULT_LISTEN_INTERVAL 1 /* beacon intervals */ #define A_MAX_WOW_LISTEN_INTERVAL 1000 /* includes also the null byte */ @@ -534,7 +534,6 @@ struct ath6kl { spinlock_t lock; struct semaphore sem; u16 listen_intvl_b; - u16 listen_intvl_t; u8 lrssi_roam_threshold; struct ath6kl_version version; u32 target_type; diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index eb808b46f94c..fa7243b41442 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -1505,57 +1505,46 @@ static const struct file_operations fops_bgscan_int = { }; static ssize_t ath6kl_listen_int_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) + const char __user *user_buf, + size_t count, loff_t *ppos) { struct ath6kl *ar = file->private_data; - u16 listen_int_t, listen_int_b; + struct ath6kl_vif *vif; + u16 listen_interval; char buf[32]; - char *sptr, *token; ssize_t len; + vif = ath6kl_vif_first(ar); + if (!vif) + return -EIO; + len = min(count, sizeof(buf) - 1); if (copy_from_user(buf, user_buf, len)) return -EFAULT; buf[len] = '\0'; - sptr = buf; - - token = strsep(&sptr, " "); - if (!token) - return -EINVAL; - - if (kstrtou16(token, 0, &listen_int_t)) - return -EINVAL; - - if (kstrtou16(sptr, 0, &listen_int_b)) - return -EINVAL; - - if ((listen_int_t < 15) || (listen_int_t > 5000)) + if (kstrtou16(buf, 0, &listen_interval)) return -EINVAL; - if ((listen_int_b < 1) || (listen_int_b > 50)) + if ((listen_interval < 1) || (listen_interval > 50)) return -EINVAL; - ar->listen_intvl_t = listen_int_t; - ar->listen_intvl_b = listen_int_b; - - ath6kl_wmi_listeninterval_cmd(ar->wmi, 0, ar->listen_intvl_t, + ar->listen_intvl_b = listen_interval; + ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, 0, ar->listen_intvl_b); return count; } static ssize_t ath6kl_listen_int_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) + char __user *user_buf, + size_t count, loff_t *ppos) { struct ath6kl *ar = file->private_data; char buf[32]; int len; - len = scnprintf(buf, sizeof(buf), "%u %u\n", ar->listen_intvl_t, - ar->listen_intvl_b); + len = scnprintf(buf, sizeof(buf), "%u\n", ar->listen_intvl_b); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1710,6 +1699,9 @@ int ath6kl_debug_init(struct ath6kl *ar) debugfs_create_file("bgscan_interval", S_IWUSR, ar->debugfs_phy, ar, &fops_bgscan_int); + debugfs_create_file("listen_interval", S_IRUSR | S_IWUSR, + ar->debugfs_phy, ar, &fops_listen_int); + debugfs_create_file("power_params", S_IWUSR, ar->debugfs_phy, ar, &fops_power_params); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 8742eaa78186..4c26572214c7 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -584,10 +584,11 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, memcpy(vif->bssid, bssid, sizeof(vif->bssid)); vif->bss_ch = channel; - if ((vif->nw_type == INFRA_NETWORK)) + if ((vif->nw_type == INFRA_NETWORK)) { + ar->listen_intvl_b = listen_int; ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, - ar->listen_intvl_t, - ar->listen_intvl_b); + 0, ar->listen_intvl_b); + } netif_wake_queue(vif->ndev); -- GitLab From 8605c6844fb9bdf55471bb87c3ac62d44eb34e04 Mon Sep 17 00:00:00 2001 From: Tang Liang Date: Thu, 8 Dec 2011 17:36:39 +0800 Subject: [PATCH 00081/10698] xen: Utilize the restore_msi_irqs hook. to make a hypercall to restore the vectors in the MSI/MSI-X configuration space. Signed-off-by: Tang Liang Signed-off-by: Konrad Rzeszutek Wilk --- arch/x86/pci/xen.c | 27 +++++++++++++++++++++++++++ include/xen/interface/physdev.h | 7 +++++++ 2 files changed, 34 insertions(+) diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 492ade8c978e..249a5ae17d02 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -324,6 +324,32 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) out: return ret; } + +static void xen_initdom_restore_msi_irqs(struct pci_dev *dev, int irq) +{ + int ret = 0; + + if (pci_seg_supported) { + struct physdev_pci_device restore_ext; + + restore_ext.seg = pci_domain_nr(dev->bus); + restore_ext.bus = dev->bus->number; + restore_ext.devfn = dev->devfn; + ret = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi_ext, + &restore_ext); + if (ret == -ENOSYS) + pci_seg_supported = false; + WARN(ret && ret != -ENOSYS, "restore_msi_ext -> %d\n", ret); + } + if (!pci_seg_supported) { + struct physdev_restore_msi restore; + + restore.bus = dev->bus->number; + restore.devfn = dev->devfn; + ret = HYPERVISOR_physdev_op(PHYSDEVOP_restore_msi, &restore); + WARN(ret && ret != -ENOSYS, "restore_msi -> %d\n", ret); + } +} #endif static void xen_teardown_msi_irqs(struct pci_dev *dev) @@ -446,6 +472,7 @@ int __init pci_xen_initial_domain(void) #ifdef CONFIG_PCI_MSI x86_msi.setup_msi_irqs = xen_initdom_setup_msi_irqs; x86_msi.teardown_msi_irq = xen_teardown_msi_irq; + x86_msi.restore_msi_irqs = xen_initdom_restore_msi_irqs; #endif xen_setup_acpi_sci(); __acpi_register_gsi = acpi_register_gsi_xen; diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index c1080d9c705d..0c28989007fb 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h @@ -145,6 +145,13 @@ struct physdev_manage_pci { uint8_t devfn; }; +#define PHYSDEVOP_restore_msi 19 +struct physdev_restore_msi { + /* IN */ + uint8_t bus; + uint8_t devfn; +}; + #define PHYSDEVOP_manage_pci_add_ext 20 struct physdev_manage_pci_ext { /* IN */ -- GitLab From a96d627abaac899e8bfaf18fd0578b228c9c752f Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 4 Jan 2012 14:23:56 -0500 Subject: [PATCH 00082/10698] pci: Introduce __pci_reset_function_locked to be used when holding device_lock. The use case of this is when a driver wants to call FLR when a device is attached to it using the SysFS "bind" or "unbind" functionality. The call chain when a user does "bind" looks as so: echo "0000:01.07.0" > /sys/bus/pci/drivers/XXXX/bind and ends up calling: driver_bind: device_lock(dev); <=== TAKES LOCK XXXX_probe: .. pci_enable_device() ...__pci_reset_function(), which calls pci_dev_reset(dev, 0): if (!0) { device_lock(dev) <==== DEADLOCK The __pci_reset_function_locked function allows the the drivers 'probe' function to call the "pci_reset_function" while still holding the driver mutex lock. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/pci/pci.c | 25 +++++++++++++++++++++++++ include/linux/pci.h | 1 + 2 files changed, 26 insertions(+) diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 97fff785e97e..192be5dbde56 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -3162,6 +3162,31 @@ int __pci_reset_function(struct pci_dev *dev) } EXPORT_SYMBOL_GPL(__pci_reset_function); +/** + * __pci_reset_function_locked - reset a PCI device function while holding + * the @dev mutex lock. + * @dev: PCI device to reset + * + * Some devices allow an individual function to be reset without affecting + * other functions in the same device. The PCI device must be responsive + * to PCI config space in order to use this function. + * + * The device function is presumed to be unused and the caller is holding + * the device mutex lock when this function is called. + * Resetting the device will make the contents of PCI configuration space + * random, so any caller of this must be prepared to reinitialise the + * device including MSI, bus mastering, BARs, decoding IO and memory spaces, + * etc. + * + * Returns 0 if the device function was successfully reset or negative if the + * device doesn't support resetting a single function. + */ +int __pci_reset_function_locked(struct pci_dev *dev) +{ + return pci_dev_reset(dev, 1); +} +EXPORT_SYMBOL_GPL(__pci_reset_function_locked); + /** * pci_probe_reset_function - check whether the device can be safely reset * @dev: PCI device to reset diff --git a/include/linux/pci.h b/include/linux/pci.h index a16b1df3deff..65c2d8a32b23 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -817,6 +817,7 @@ int pcie_set_readrq(struct pci_dev *dev, int rq); int pcie_get_mps(struct pci_dev *dev); int pcie_set_mps(struct pci_dev *dev, int mps); int __pci_reset_function(struct pci_dev *dev); +int __pci_reset_function_locked(struct pci_dev *dev); int pci_reset_function(struct pci_dev *dev); void pci_update_resource(struct pci_dev *dev, int resno); int __must_check pci_assign_resource(struct pci_dev *dev, int i); -- GitLab From cd9db80e5257682a7f7ab245a2459648b3c8d268 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Wed, 4 Jan 2012 14:30:58 -0500 Subject: [PATCH 00083/10698] xen/pciback: Support pci_reset_function, aka FLR or D3 support. We use the __pci_reset_function_locked to perform the action. Also on attaching ("bind") and detaching ("unbind") we save and restore the configuration states. When the device is disconnected from a guest we use the "pci_reset_function" to also reset the device before being passed to another guest. Signed-off-by: Konrad Rzeszutek Wilk --- drivers/xen/xen-pciback/pci_stub.c | 41 +++++++++++++++++++++++++++--- drivers/xen/xen-pciback/pciback.h | 1 + 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 7944a17f5cbf..6f63b9d954fb 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -85,19 +85,34 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev) static void pcistub_device_release(struct kref *kref) { struct pcistub_device *psdev; + struct xen_pcibk_dev_data *dev_data; psdev = container_of(kref, struct pcistub_device, kref); + dev_data = pci_get_drvdata(psdev->dev); dev_dbg(&psdev->dev->dev, "pcistub_device_release\n"); xen_unregister_device_domain_owner(psdev->dev); - /* Clean-up the device */ + /* Call the reset function which does not take lock as this + * is called from "unbind" which takes a device_lock mutex. + */ + __pci_reset_function_locked(psdev->dev); + if (pci_load_and_free_saved_state(psdev->dev, + &dev_data->pci_saved_state)) { + dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n"); + } else + pci_restore_state(psdev->dev); + + /* Disable the device */ xen_pcibk_reset_device(psdev->dev); + + kfree(dev_data); + pci_set_drvdata(psdev->dev, NULL); + + /* Clean-up the device */ xen_pcibk_config_free_dyn_fields(psdev->dev); xen_pcibk_config_free_dev(psdev->dev); - kfree(pci_get_drvdata(psdev->dev)); - pci_set_drvdata(psdev->dev, NULL); psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; pci_dev_put(psdev->dev); @@ -231,7 +246,17 @@ void pcistub_put_pci_dev(struct pci_dev *dev) /* Cleanup our device * (so it's ready for the next domain) */ + + /* This is OK - we are running from workqueue context + * and want to inhibit the user from fiddling with 'reset' + */ + pci_reset_function(dev); + pci_restore_state(psdev->dev); + + /* This disables the device. */ xen_pcibk_reset_device(found_psdev->dev); + + /* And cleanup up our emulated fields. */ xen_pcibk_config_free_dyn_fields(found_psdev->dev); xen_pcibk_config_reset_dev(found_psdev->dev); @@ -328,6 +353,16 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) if (err) goto config_release; + dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); + __pci_reset_function_locked(dev); + + /* We need the device active to save the state. */ + dev_dbg(&dev->dev, "save state of device\n"); + pci_save_state(dev); + dev_data->pci_saved_state = pci_store_saved_state(dev); + if (!dev_data->pci_saved_state) + dev_err(&dev->dev, "Could not store PCI conf saved state!\n"); + /* Now disable the device (this also ensures some private device * data is setup before we export) */ diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h index e9b4011c5f9a..a7def010eba3 100644 --- a/drivers/xen/xen-pciback/pciback.h +++ b/drivers/xen/xen-pciback/pciback.h @@ -41,6 +41,7 @@ struct xen_pcibk_device { struct xen_pcibk_dev_data { struct list_head config_fields; + struct pci_saved_state *pci_saved_state; unsigned int permissive:1; unsigned int warned_on_write:1; unsigned int enable_intx:1; -- GitLab From e87e06cd8cc09afbbf61de1380913d51bf4dffb3 Mon Sep 17 00:00:00 2001 From: Henning Heinold Date: Fri, 13 Jan 2012 16:38:37 +1100 Subject: [PATCH 00084/10698] arm: tegra: export tegra_chip_uid The crypto driver will need this api to use it in the RNG calculations. In order to build the crypto driver as a module, tegra_chip_uid has to be exported. Acked-by: Olof Johansson Signed-off-by: Henning Heinold Signed-off-by: Varun Wadekar Signed-off-by: Herbert Xu --- arch/arm/mach-tegra/fuse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c index 1fa26d9a1a68..ea49bd93c6b9 100644 --- a/arch/arm/mach-tegra/fuse.c +++ b/arch/arm/mach-tegra/fuse.c @@ -19,6 +19,7 @@ #include #include +#include #include @@ -58,6 +59,7 @@ unsigned long long tegra_chip_uid(void) hi = fuse_readl(FUSE_UID_HIGH); return (hi << 32ull) | lo; } +EXPORT_SYMBOL(tegra_chip_uid); int tegra_sku_id(void) { -- GitLab From f1df57d02a0f83e764b4dc9187f58665d70f190e Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Fri, 13 Jan 2012 16:38:37 +1100 Subject: [PATCH 00085/10698] crypto: driver for Tegra AES hardware driver supports ecb/cbc/ofb/ansi_x9.31rng modes, 128, 192 and 256-bit key sizes Signed-off-by: Varun Wadekar Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 11 + drivers/crypto/Makefile | 1 + drivers/crypto/tegra-aes.c | 1096 ++++++++++++++++++++++++++++++++++++ drivers/crypto/tegra-aes.h | 103 ++++ 4 files changed, 1211 insertions(+) create mode 100644 drivers/crypto/tegra-aes.c create mode 100644 drivers/crypto/tegra-aes.h diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 6d16b4b0d7a0..e707979767fb 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -293,4 +293,15 @@ config CRYPTO_DEV_S5P Select this to offload Samsung S5PV210 or S5PC110 from AES algorithms execution. +config CRYPTO_DEV_TEGRA_AES + tristate "Support for TEGRA AES hw engine" + depends on ARCH_TEGRA + select CRYPTO_AES + help + TEGRA processors have AES module accelerator. Select this if you + want to use the TEGRA module for AES algorithms. + + To compile this driver as a module, choose M here: the module + will be called tegra-aes. + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 53ea50155319..f3e64eadd7af 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o obj-$(CONFIG_CRYPTO_DEV_S5P) += s5p-sss.o +obj-$(CONFIG_CRYPTO_DEV_TEGRA_AES) += tegra-aes.o diff --git a/drivers/crypto/tegra-aes.c b/drivers/crypto/tegra-aes.c new file mode 100644 index 000000000000..422a9766c7c9 --- /dev/null +++ b/drivers/crypto/tegra-aes.c @@ -0,0 +1,1096 @@ +/* + * drivers/crypto/tegra-aes.c + * + * Driver for NVIDIA Tegra AES hardware engine residing inside the + * Bit Stream Engine for Video (BSEV) hardware block. + * + * The programming sequence for this engine is with the help + * of commands which travel via a command queue residing between the + * CPU and the BSEV block. The BSEV engine has an internal RAM (VRAM) + * where the final input plaintext, keys and the IV have to be copied + * before starting the encrypt/decrypt operation. + * + * Copyright (c) 2010, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "tegra-aes.h" + +#define FLAGS_MODE_MASK 0x00FF +#define FLAGS_ENCRYPT BIT(0) +#define FLAGS_CBC BIT(1) +#define FLAGS_GIV BIT(2) +#define FLAGS_RNG BIT(3) +#define FLAGS_OFB BIT(4) +#define FLAGS_NEW_KEY BIT(5) +#define FLAGS_NEW_IV BIT(6) +#define FLAGS_INIT BIT(7) +#define FLAGS_FAST BIT(8) +#define FLAGS_BUSY 9 + +/* + * Defines AES engine Max process bytes size in one go, which takes 1 msec. + * AES engine spends about 176 cycles/16-bytes or 11 cycles/byte + * The duration CPU can use the BSE to 1 msec, then the number of available + * cycles of AVP/BSE is 216K. In this duration, AES can process 216/11 ~= 19KB + * Based on this AES_HW_DMA_BUFFER_SIZE_BYTES is configured to 16KB. + */ +#define AES_HW_DMA_BUFFER_SIZE_BYTES 0x4000 + +/* + * The key table length is 64 bytes + * (This includes first upto 32 bytes key + 16 bytes original initial vector + * and 16 bytes updated initial vector) + */ +#define AES_HW_KEY_TABLE_LENGTH_BYTES 64 + +/* + * The memory being used is divides as follows: + * 1. Key - 32 bytes + * 2. Original IV - 16 bytes + * 3. Updated IV - 16 bytes + * 4. Key schedule - 256 bytes + * + * 1+2+3 constitute the hw key table. + */ +#define AES_HW_IV_SIZE 16 +#define AES_HW_KEYSCHEDULE_LEN 256 +#define AES_IVKEY_SIZE (AES_HW_KEY_TABLE_LENGTH_BYTES + AES_HW_KEYSCHEDULE_LEN) + +/* Define commands required for AES operation */ +enum { + CMD_BLKSTARTENGINE = 0x0E, + CMD_DMASETUP = 0x10, + CMD_DMACOMPLETE = 0x11, + CMD_SETTABLE = 0x15, + CMD_MEMDMAVD = 0x22, +}; + +/* Define sub-commands */ +enum { + SUBCMD_VRAM_SEL = 0x1, + SUBCMD_CRYPTO_TABLE_SEL = 0x3, + SUBCMD_KEY_TABLE_SEL = 0x8, +}; + +/* memdma_vd command */ +#define MEMDMA_DIR_DTOVRAM 0 /* sdram -> vram */ +#define MEMDMA_DIR_VTODRAM 1 /* vram -> sdram */ +#define MEMDMA_DIR_SHIFT 25 +#define MEMDMA_NUM_WORDS_SHIFT 12 + +/* command queue bit shifts */ +enum { + CMDQ_KEYTABLEADDR_SHIFT = 0, + CMDQ_KEYTABLEID_SHIFT = 17, + CMDQ_VRAMSEL_SHIFT = 23, + CMDQ_TABLESEL_SHIFT = 24, + CMDQ_OPCODE_SHIFT = 26, +}; + +/* + * The secure key slot contains a unique secure key generated + * and loaded by the bootloader. This slot is marked as non-accessible + * to the kernel. + */ +#define SSK_SLOT_NUM 4 + +#define AES_NR_KEYSLOTS 8 +#define TEGRA_AES_QUEUE_LENGTH 50 +#define DEFAULT_RNG_BLK_SZ 16 + +/* The command queue depth */ +#define AES_HW_MAX_ICQ_LENGTH 5 + +struct tegra_aes_slot { + struct list_head node; + int slot_num; +}; + +static struct tegra_aes_slot ssk = { + .slot_num = SSK_SLOT_NUM, +}; + +struct tegra_aes_reqctx { + unsigned long mode; +}; + +struct tegra_aes_dev { + struct device *dev; + void __iomem *io_base; + dma_addr_t ivkey_phys_base; + void __iomem *ivkey_base; + struct clk *aes_clk; + struct tegra_aes_ctx *ctx; + int irq; + unsigned long flags; + struct completion op_complete; + u32 *buf_in; + dma_addr_t dma_buf_in; + u32 *buf_out; + dma_addr_t dma_buf_out; + u8 *iv; + u8 dt[DEFAULT_RNG_BLK_SZ]; + int ivlen; + u64 ctr; + spinlock_t lock; + struct crypto_queue queue; + struct tegra_aes_slot *slots; + struct ablkcipher_request *req; + size_t total; + struct scatterlist *in_sg; + size_t in_offset; + struct scatterlist *out_sg; + size_t out_offset; +}; + +static struct tegra_aes_dev *aes_dev; + +struct tegra_aes_ctx { + struct tegra_aes_dev *dd; + unsigned long flags; + struct tegra_aes_slot *slot; + u8 key[AES_MAX_KEY_SIZE]; + size_t keylen; +}; + +static struct tegra_aes_ctx rng_ctx = { + .flags = FLAGS_NEW_KEY, + .keylen = AES_KEYSIZE_128, +}; + +/* keep registered devices data here */ +static struct list_head dev_list; +static DEFINE_SPINLOCK(list_lock); +static DEFINE_MUTEX(aes_lock); + +static void aes_workqueue_handler(struct work_struct *work); +static DECLARE_WORK(aes_work, aes_workqueue_handler); +static struct workqueue_struct *aes_wq; + +extern unsigned long long tegra_chip_uid(void); + +static inline u32 aes_readl(struct tegra_aes_dev *dd, u32 offset) +{ + return readl(dd->io_base + offset); +} + +static inline void aes_writel(struct tegra_aes_dev *dd, u32 val, u32 offset) +{ + writel(val, dd->io_base + offset); +} + +static int aes_start_crypt(struct tegra_aes_dev *dd, u32 in_addr, u32 out_addr, + int nblocks, int mode, bool upd_iv) +{ + u32 cmdq[AES_HW_MAX_ICQ_LENGTH]; + int i, eng_busy, icq_empty, ret; + u32 value; + + /* reset all the interrupt bits */ + aes_writel(dd, 0xFFFFFFFF, TEGRA_AES_INTR_STATUS); + + /* enable error, dma xfer complete interrupts */ + aes_writel(dd, 0x33, TEGRA_AES_INT_ENB); + + cmdq[0] = CMD_DMASETUP << CMDQ_OPCODE_SHIFT; + cmdq[1] = in_addr; + cmdq[2] = CMD_BLKSTARTENGINE << CMDQ_OPCODE_SHIFT | (nblocks-1); + cmdq[3] = CMD_DMACOMPLETE << CMDQ_OPCODE_SHIFT; + + value = aes_readl(dd, TEGRA_AES_CMDQUE_CONTROL); + /* access SDRAM through AHB */ + value &= ~TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD; + value &= ~TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD; + value |= TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD | + TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD | + TEGRA_AES_CMDQ_CTRL_ICMDQEN_FIELD; + aes_writel(dd, value, TEGRA_AES_CMDQUE_CONTROL); + dev_dbg(dd->dev, "cmd_q_ctrl=0x%x", value); + + value = (0x1 << TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT) | + ((dd->ctx->keylen * 8) << + TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT) | + ((u32)upd_iv << TEGRA_AES_SECURE_IV_SELECT_SHIFT); + + if (mode & FLAGS_CBC) { + value |= ((((mode & FLAGS_ENCRYPT) ? 2 : 3) + << TEGRA_AES_SECURE_XOR_POS_SHIFT) | + (((mode & FLAGS_ENCRYPT) ? 2 : 3) + << TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT) | + ((mode & FLAGS_ENCRYPT) ? 1 : 0) + << TEGRA_AES_SECURE_CORE_SEL_SHIFT); + } else if (mode & FLAGS_OFB) { + value |= ((TEGRA_AES_SECURE_XOR_POS_FIELD) | + (2 << TEGRA_AES_SECURE_INPUT_SEL_SHIFT) | + (TEGRA_AES_SECURE_CORE_SEL_FIELD)); + } else if (mode & FLAGS_RNG) { + value |= (((mode & FLAGS_ENCRYPT) ? 1 : 0) + << TEGRA_AES_SECURE_CORE_SEL_SHIFT | + TEGRA_AES_SECURE_RNG_ENB_FIELD); + } else { + value |= (((mode & FLAGS_ENCRYPT) ? 1 : 0) + << TEGRA_AES_SECURE_CORE_SEL_SHIFT); + } + + dev_dbg(dd->dev, "secure_in_sel=0x%x", value); + aes_writel(dd, value, TEGRA_AES_SECURE_INPUT_SELECT); + + aes_writel(dd, out_addr, TEGRA_AES_SECURE_DEST_ADDR); + INIT_COMPLETION(dd->op_complete); + + for (i = 0; i < AES_HW_MAX_ICQ_LENGTH - 1; i++) { + do { + value = aes_readl(dd, TEGRA_AES_INTR_STATUS); + eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD; + icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD; + } while (eng_busy & (!icq_empty)); + aes_writel(dd, cmdq[i], TEGRA_AES_ICMDQUE_WR); + } + + ret = wait_for_completion_timeout(&dd->op_complete, + msecs_to_jiffies(150)); + if (ret == 0) { + dev_err(dd->dev, "timed out (0x%x)\n", + aes_readl(dd, TEGRA_AES_INTR_STATUS)); + return -ETIMEDOUT; + } + + aes_writel(dd, cmdq[AES_HW_MAX_ICQ_LENGTH - 1], TEGRA_AES_ICMDQUE_WR); + return 0; +} + +static void aes_release_key_slot(struct tegra_aes_slot *slot) +{ + if (slot->slot_num == SSK_SLOT_NUM) + return; + + spin_lock(&list_lock); + list_add_tail(&slot->node, &dev_list); + slot = NULL; + spin_unlock(&list_lock); +} + +static struct tegra_aes_slot *aes_find_key_slot(void) +{ + struct tegra_aes_slot *slot = NULL; + struct list_head *new_head; + int empty; + + spin_lock(&list_lock); + empty = list_empty(&dev_list); + if (!empty) { + slot = list_entry(&dev_list, struct tegra_aes_slot, node); + new_head = dev_list.next; + list_del(&dev_list); + dev_list.next = new_head->next; + dev_list.prev = NULL; + } + spin_unlock(&list_lock); + + return slot; +} + +static int aes_set_key(struct tegra_aes_dev *dd) +{ + u32 value, cmdq[2]; + struct tegra_aes_ctx *ctx = dd->ctx; + int eng_busy, icq_empty, dma_busy; + bool use_ssk = false; + + /* use ssk? */ + if (!dd->ctx->slot) { + dev_dbg(dd->dev, "using ssk"); + dd->ctx->slot = &ssk; + use_ssk = true; + } + + /* enable key schedule generation in hardware */ + value = aes_readl(dd, TEGRA_AES_SECURE_CONFIG_EXT); + value &= ~TEGRA_AES_SECURE_KEY_SCH_DIS_FIELD; + aes_writel(dd, value, TEGRA_AES_SECURE_CONFIG_EXT); + + /* select the key slot */ + value = aes_readl(dd, TEGRA_AES_SECURE_CONFIG); + value &= ~TEGRA_AES_SECURE_KEY_INDEX_FIELD; + value |= (ctx->slot->slot_num << TEGRA_AES_SECURE_KEY_INDEX_SHIFT); + aes_writel(dd, value, TEGRA_AES_SECURE_CONFIG); + + if (use_ssk) + return 0; + + /* copy the key table from sdram to vram */ + cmdq[0] = CMD_MEMDMAVD << CMDQ_OPCODE_SHIFT | + MEMDMA_DIR_DTOVRAM << MEMDMA_DIR_SHIFT | + AES_HW_KEY_TABLE_LENGTH_BYTES / sizeof(u32) << + MEMDMA_NUM_WORDS_SHIFT; + cmdq[1] = (u32)dd->ivkey_phys_base; + + aes_writel(dd, cmdq[0], TEGRA_AES_ICMDQUE_WR); + aes_writel(dd, cmdq[1], TEGRA_AES_ICMDQUE_WR); + + do { + value = aes_readl(dd, TEGRA_AES_INTR_STATUS); + eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD; + icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD; + dma_busy = value & TEGRA_AES_DMA_BUSY_FIELD; + } while (eng_busy & (!icq_empty) & dma_busy); + + /* settable command to get key into internal registers */ + value = CMD_SETTABLE << CMDQ_OPCODE_SHIFT | + SUBCMD_CRYPTO_TABLE_SEL << CMDQ_TABLESEL_SHIFT | + SUBCMD_VRAM_SEL << CMDQ_VRAMSEL_SHIFT | + (SUBCMD_KEY_TABLE_SEL | ctx->slot->slot_num) << + CMDQ_KEYTABLEID_SHIFT; + aes_writel(dd, value, TEGRA_AES_ICMDQUE_WR); + + do { + value = aes_readl(dd, TEGRA_AES_INTR_STATUS); + eng_busy = value & TEGRA_AES_ENGINE_BUSY_FIELD; + icq_empty = value & TEGRA_AES_ICQ_EMPTY_FIELD; + } while (eng_busy & (!icq_empty)); + + return 0; +} + +static int tegra_aes_handle_req(struct tegra_aes_dev *dd) +{ + struct crypto_async_request *async_req, *backlog; + struct crypto_ablkcipher *tfm; + struct tegra_aes_ctx *ctx; + struct tegra_aes_reqctx *rctx; + struct ablkcipher_request *req; + unsigned long flags; + int dma_max = AES_HW_DMA_BUFFER_SIZE_BYTES; + int ret = 0, nblocks, total; + int count = 0; + dma_addr_t addr_in, addr_out; + struct scatterlist *in_sg, *out_sg; + + if (!dd) + return -EINVAL; + + spin_lock_irqsave(&dd->lock, flags); + backlog = crypto_get_backlog(&dd->queue); + async_req = crypto_dequeue_request(&dd->queue); + if (!async_req) + clear_bit(FLAGS_BUSY, &dd->flags); + spin_unlock_irqrestore(&dd->lock, flags); + + if (!async_req) + return -ENODATA; + + if (backlog) + backlog->complete(backlog, -EINPROGRESS); + + req = ablkcipher_request_cast(async_req); + + dev_dbg(dd->dev, "%s: get new req\n", __func__); + + if (!req->src || !req->dst) + return -EINVAL; + + /* take mutex to access the aes hw */ + mutex_lock(&aes_lock); + + /* assign new request to device */ + dd->req = req; + dd->total = req->nbytes; + dd->in_offset = 0; + dd->in_sg = req->src; + dd->out_offset = 0; + dd->out_sg = req->dst; + + in_sg = dd->in_sg; + out_sg = dd->out_sg; + + total = dd->total; + + tfm = crypto_ablkcipher_reqtfm(req); + rctx = ablkcipher_request_ctx(req); + ctx = crypto_ablkcipher_ctx(tfm); + rctx->mode &= FLAGS_MODE_MASK; + dd->flags = (dd->flags & ~FLAGS_MODE_MASK) | rctx->mode; + + dd->iv = (u8 *)req->info; + dd->ivlen = crypto_ablkcipher_ivsize(tfm); + + /* assign new context to device */ + ctx->dd = dd; + dd->ctx = ctx; + + if (ctx->flags & FLAGS_NEW_KEY) { + /* copy the key */ + memcpy(dd->ivkey_base, ctx->key, ctx->keylen); + memset(dd->ivkey_base + ctx->keylen, 0, AES_HW_KEY_TABLE_LENGTH_BYTES - ctx->keylen); + aes_set_key(dd); + ctx->flags &= ~FLAGS_NEW_KEY; + } + + if (((dd->flags & FLAGS_CBC) || (dd->flags & FLAGS_OFB)) && dd->iv) { + /* set iv to the aes hw slot + * Hw generates updated iv only after iv is set in slot. + * So key and iv is passed asynchronously. + */ + memcpy(dd->buf_in, dd->iv, dd->ivlen); + + ret = aes_start_crypt(dd, (u32)dd->dma_buf_in, + dd->dma_buf_out, 1, FLAGS_CBC, false); + if (ret < 0) { + dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret); + goto out; + } + } + + while (total) { + dev_dbg(dd->dev, "remain: %d\n", total); + ret = dma_map_sg(dd->dev, in_sg, 1, DMA_TO_DEVICE); + if (!ret) { + dev_err(dd->dev, "dma_map_sg() error\n"); + goto out; + } + + ret = dma_map_sg(dd->dev, out_sg, 1, DMA_FROM_DEVICE); + if (!ret) { + dev_err(dd->dev, "dma_map_sg() error\n"); + dma_unmap_sg(dd->dev, dd->in_sg, + 1, DMA_TO_DEVICE); + goto out; + } + + addr_in = sg_dma_address(in_sg); + addr_out = sg_dma_address(out_sg); + dd->flags |= FLAGS_FAST; + count = min_t(int, sg_dma_len(in_sg), dma_max); + WARN_ON(sg_dma_len(in_sg) != sg_dma_len(out_sg)); + nblocks = DIV_ROUND_UP(count, AES_BLOCK_SIZE); + + ret = aes_start_crypt(dd, addr_in, addr_out, nblocks, + dd->flags, true); + + dma_unmap_sg(dd->dev, out_sg, 1, DMA_FROM_DEVICE); + dma_unmap_sg(dd->dev, in_sg, 1, DMA_TO_DEVICE); + + if (ret < 0) { + dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret); + goto out; + } + dd->flags &= ~FLAGS_FAST; + + dev_dbg(dd->dev, "out: copied %d\n", count); + total -= count; + in_sg = sg_next(in_sg); + out_sg = sg_next(out_sg); + WARN_ON(((total != 0) && (!in_sg || !out_sg))); + } + +out: + mutex_unlock(&aes_lock); + + dd->total = total; + + if (dd->req->base.complete) + dd->req->base.complete(&dd->req->base, ret); + + dev_dbg(dd->dev, "%s: exit\n", __func__); + return ret; +} + +static int tegra_aes_setkey(struct crypto_ablkcipher *tfm, const u8 *key, + unsigned int keylen) +{ + struct tegra_aes_ctx *ctx = crypto_ablkcipher_ctx(tfm); + struct tegra_aes_dev *dd = aes_dev; + struct tegra_aes_slot *key_slot; + + if ((keylen != AES_KEYSIZE_128) && (keylen != AES_KEYSIZE_192) && + (keylen != AES_KEYSIZE_256)) { + dev_err(dd->dev, "unsupported key size\n"); + crypto_ablkcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + dev_dbg(dd->dev, "keylen: %d\n", keylen); + + ctx->dd = dd; + + if (key) { + if (!ctx->slot) { + key_slot = aes_find_key_slot(); + if (!key_slot) { + dev_err(dd->dev, "no empty slot\n"); + return -ENOMEM; + } + + ctx->slot = key_slot; + } + + memcpy(ctx->key, key, keylen); + ctx->keylen = keylen; + } + + ctx->flags |= FLAGS_NEW_KEY; + dev_dbg(dd->dev, "done\n"); + return 0; +} + +static void aes_workqueue_handler(struct work_struct *work) +{ + struct tegra_aes_dev *dd = aes_dev; + int ret; + + ret = clk_enable(dd->aes_clk); + if (ret) + BUG_ON("clock enable failed"); + + /* empty the crypto queue and then return */ + do { + ret = tegra_aes_handle_req(dd); + } while (!ret); + + clk_disable(dd->aes_clk); +} + +static irqreturn_t aes_irq(int irq, void *dev_id) +{ + struct tegra_aes_dev *dd = (struct tegra_aes_dev *)dev_id; + u32 value = aes_readl(dd, TEGRA_AES_INTR_STATUS); + int busy = test_bit(FLAGS_BUSY, &dd->flags); + + if (!busy) { + dev_dbg(dd->dev, "spurious interrupt\n"); + return IRQ_NONE; + } + + dev_dbg(dd->dev, "irq_stat: 0x%x\n", value); + if (value & TEGRA_AES_INT_ERROR_MASK) + aes_writel(dd, TEGRA_AES_INT_ERROR_MASK, TEGRA_AES_INTR_STATUS); + + if (!(value & TEGRA_AES_ENGINE_BUSY_FIELD)) + complete(&dd->op_complete); + else + return IRQ_NONE; + + return IRQ_HANDLED; +} + +static int tegra_aes_crypt(struct ablkcipher_request *req, unsigned long mode) +{ + struct tegra_aes_reqctx *rctx = ablkcipher_request_ctx(req); + struct tegra_aes_dev *dd = aes_dev; + unsigned long flags; + int err = 0; + int busy; + + dev_dbg(dd->dev, "nbytes: %d, enc: %d, cbc: %d, ofb: %d\n", + req->nbytes, !!(mode & FLAGS_ENCRYPT), + !!(mode & FLAGS_CBC), !!(mode & FLAGS_OFB)); + + rctx->mode = mode; + + spin_lock_irqsave(&dd->lock, flags); + err = ablkcipher_enqueue_request(&dd->queue, req); + busy = test_and_set_bit(FLAGS_BUSY, &dd->flags); + spin_unlock_irqrestore(&dd->lock, flags); + + if (!busy) + queue_work(aes_wq, &aes_work); + + return err; +} + +static int tegra_aes_ecb_encrypt(struct ablkcipher_request *req) +{ + return tegra_aes_crypt(req, FLAGS_ENCRYPT); +} + +static int tegra_aes_ecb_decrypt(struct ablkcipher_request *req) +{ + return tegra_aes_crypt(req, 0); +} + +static int tegra_aes_cbc_encrypt(struct ablkcipher_request *req) +{ + return tegra_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_CBC); +} + +static int tegra_aes_cbc_decrypt(struct ablkcipher_request *req) +{ + return tegra_aes_crypt(req, FLAGS_CBC); +} + +static int tegra_aes_ofb_encrypt(struct ablkcipher_request *req) +{ + return tegra_aes_crypt(req, FLAGS_ENCRYPT | FLAGS_OFB); +} + +static int tegra_aes_ofb_decrypt(struct ablkcipher_request *req) +{ + return tegra_aes_crypt(req, FLAGS_OFB); +} + +static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata, + unsigned int dlen) +{ + struct tegra_aes_dev *dd = aes_dev; + struct tegra_aes_ctx *ctx = &rng_ctx; + int ret, i; + u8 *dest = rdata, *dt = dd->dt; + + /* take mutex to access the aes hw */ + mutex_lock(&aes_lock); + + ret = clk_enable(dd->aes_clk); + if (ret) + return ret; + + ctx->dd = dd; + dd->ctx = ctx; + dd->flags = FLAGS_ENCRYPT | FLAGS_RNG; + + memcpy(dd->buf_in, dt, DEFAULT_RNG_BLK_SZ); + + ret = aes_start_crypt(dd, (u32)dd->dma_buf_in, + (u32)dd->dma_buf_out, 1, dd->flags, true); + if (ret < 0) { + dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret); + dlen = ret; + goto out; + } + memcpy(dest, dd->buf_out, dlen); + + /* update the DT */ + for (i = DEFAULT_RNG_BLK_SZ - 1; i >= 0; i--) { + dt[i] += 1; + if (dt[i] != 0) + break; + } + +out: + clk_disable(dd->aes_clk); + mutex_unlock(&aes_lock); + + dev_dbg(dd->dev, "%s: done\n", __func__); + return dlen; +} + +static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed, + unsigned int slen) +{ + struct tegra_aes_dev *dd = aes_dev; + struct tegra_aes_ctx *ctx = &rng_ctx; + struct tegra_aes_slot *key_slot; + struct timespec ts; + int ret = 0; + u64 nsec, tmp[2]; + u8 *dt; + + if (!ctx || !dd) { + dev_err(dd->dev, "ctx=0x%x, dd=0x%x\n", + (unsigned int)ctx, (unsigned int)dd); + return -EINVAL; + } + + if (slen < (DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) { + dev_err(dd->dev, "seed size invalid"); + return -ENOMEM; + } + + /* take mutex to access the aes hw */ + mutex_lock(&aes_lock); + + if (!ctx->slot) { + key_slot = aes_find_key_slot(); + if (!key_slot) { + dev_err(dd->dev, "no empty slot\n"); + mutex_unlock(&aes_lock); + return -ENOMEM; + } + ctx->slot = key_slot; + } + + ctx->dd = dd; + dd->ctx = ctx; + dd->ctr = 0; + + ctx->keylen = AES_KEYSIZE_128; + ctx->flags |= FLAGS_NEW_KEY; + + /* copy the key to the key slot */ + memcpy(dd->ivkey_base, seed + DEFAULT_RNG_BLK_SZ, AES_KEYSIZE_128); + memset(dd->ivkey_base + AES_KEYSIZE_128, 0, AES_HW_KEY_TABLE_LENGTH_BYTES - AES_KEYSIZE_128); + + dd->iv = seed; + dd->ivlen = slen; + + dd->flags = FLAGS_ENCRYPT | FLAGS_RNG; + + ret = clk_enable(dd->aes_clk); + if (ret) + return ret; + + aes_set_key(dd); + + /* set seed to the aes hw slot */ + memcpy(dd->buf_in, dd->iv, DEFAULT_RNG_BLK_SZ); + ret = aes_start_crypt(dd, (u32)dd->dma_buf_in, + dd->dma_buf_out, 1, FLAGS_CBC, false); + if (ret < 0) { + dev_err(dd->dev, "aes_start_crypt fail(%d)\n", ret); + goto out; + } + + if (dd->ivlen >= (2 * DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128)) { + dt = dd->iv + DEFAULT_RNG_BLK_SZ + AES_KEYSIZE_128; + } else { + getnstimeofday(&ts); + nsec = timespec_to_ns(&ts); + do_div(nsec, 1000); + nsec ^= dd->ctr << 56; + dd->ctr++; + tmp[0] = nsec; + tmp[1] = tegra_chip_uid(); + dt = (u8 *)tmp; + } + memcpy(dd->dt, dt, DEFAULT_RNG_BLK_SZ); + +out: + clk_disable(dd->aes_clk); + mutex_unlock(&aes_lock); + + dev_dbg(dd->dev, "%s: done\n", __func__); + return ret; +} + +static int tegra_aes_cra_init(struct crypto_tfm *tfm) +{ + tfm->crt_ablkcipher.reqsize = sizeof(struct tegra_aes_reqctx); + + return 0; +} + +void tegra_aes_cra_exit(struct crypto_tfm *tfm) +{ + struct tegra_aes_ctx *ctx = + crypto_ablkcipher_ctx((struct crypto_ablkcipher *)tfm); + + if (ctx && ctx->slot) + aes_release_key_slot(ctx->slot); +} + +static struct crypto_alg algs[] = { + { + .cra_name = "ecb(aes)", + .cra_driver_name = "ecb-aes-tegra", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_type = &crypto_ablkcipher_type, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .setkey = tegra_aes_setkey, + .encrypt = tegra_aes_ecb_encrypt, + .decrypt = tegra_aes_ecb_decrypt, + }, + }, { + .cra_name = "cbc(aes)", + .cra_driver_name = "cbc-aes-tegra", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_type = &crypto_ablkcipher_type, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_MIN_KEY_SIZE, + .setkey = tegra_aes_setkey, + .encrypt = tegra_aes_cbc_encrypt, + .decrypt = tegra_aes_cbc_decrypt, + } + }, { + .cra_name = "ofb(aes)", + .cra_driver_name = "ofb-aes-tegra", + .cra_priority = 300, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_alignmask = 3, + .cra_type = &crypto_ablkcipher_type, + .cra_u.ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_MIN_KEY_SIZE, + .setkey = tegra_aes_setkey, + .encrypt = tegra_aes_ofb_encrypt, + .decrypt = tegra_aes_ofb_decrypt, + } + }, { + .cra_name = "ansi_cprng", + .cra_driver_name = "rng-aes-tegra", + .cra_flags = CRYPTO_ALG_TYPE_RNG, + .cra_ctxsize = sizeof(struct tegra_aes_ctx), + .cra_type = &crypto_rng_type, + .cra_u.rng = { + .rng_make_random = tegra_aes_get_random, + .rng_reset = tegra_aes_rng_reset, + .seedsize = AES_KEYSIZE_128 + (2 * DEFAULT_RNG_BLK_SZ), + } + } +}; + +static int tegra_aes_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra_aes_dev *dd; + struct resource *res; + int err = -ENOMEM, i = 0, j; + + dd = devm_kzalloc(dev, sizeof(struct tegra_aes_dev), GFP_KERNEL); + if (dd == NULL) { + dev_err(dev, "unable to alloc data struct.\n"); + return err; + } + + dd->dev = dev; + platform_set_drvdata(pdev, dd); + + dd->slots = devm_kzalloc(dev, sizeof(struct tegra_aes_slot) * + AES_NR_KEYSLOTS, GFP_KERNEL); + if (dd->slots == NULL) { + dev_err(dev, "unable to alloc slot struct.\n"); + goto out; + } + + spin_lock_init(&dd->lock); + crypto_init_queue(&dd->queue, TEGRA_AES_QUEUE_LENGTH); + + /* Get the module base address */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "invalid resource type: base\n"); + err = -ENODEV; + goto out; + } + + if (!devm_request_mem_region(&pdev->dev, res->start, + resource_size(res), + dev_name(&pdev->dev))) { + dev_err(&pdev->dev, "Couldn't request MEM resource\n"); + return -ENODEV; + } + + dd->io_base = devm_ioremap(dev, res->start, resource_size(res)); + if (!dd->io_base) { + dev_err(dev, "can't ioremap register space\n"); + err = -ENOMEM; + goto out; + } + + /* Initialize the vde clock */ + dd->aes_clk = clk_get(dev, "vde"); + if (IS_ERR(dd->aes_clk)) { + dev_err(dev, "iclock intialization failed.\n"); + err = -ENODEV; + goto out; + } + + err = clk_set_rate(dd->aes_clk, ULONG_MAX); + if (err) { + dev_err(dd->dev, "iclk set_rate fail(%d)\n", err); + goto out; + } + + /* + * the foll contiguous memory is allocated as follows - + * - hardware key table + * - key schedule + */ + dd->ivkey_base = dma_alloc_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES, + &dd->ivkey_phys_base, + GFP_KERNEL); + if (!dd->ivkey_base) { + dev_err(dev, "can not allocate iv/key buffer\n"); + err = -ENOMEM; + goto out; + } + + dd->buf_in = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + &dd->dma_buf_in, GFP_KERNEL); + if (!dd->buf_in) { + dev_err(dev, "can not allocate dma-in buffer\n"); + err = -ENOMEM; + goto out; + } + + dd->buf_out = dma_alloc_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + &dd->dma_buf_out, GFP_KERNEL); + if (!dd->buf_out) { + dev_err(dev, "can not allocate dma-out buffer\n"); + err = -ENOMEM; + goto out; + } + + init_completion(&dd->op_complete); + aes_wq = alloc_workqueue("tegra_aes_wq", WQ_HIGHPRI | WQ_UNBOUND, 1); + if (!aes_wq) { + dev_err(dev, "alloc_workqueue failed\n"); + goto out; + } + + /* get the irq */ + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!res) { + dev_err(dev, "invalid resource type: base\n"); + err = -ENODEV; + goto out; + } + dd->irq = res->start; + + err = devm_request_irq(dev, dd->irq, aes_irq, IRQF_TRIGGER_HIGH | + IRQF_SHARED, "tegra-aes", dd); + if (err) { + dev_err(dev, "request_irq failed\n"); + goto out; + } + + mutex_init(&aes_lock); + INIT_LIST_HEAD(&dev_list); + + spin_lock_init(&list_lock); + spin_lock(&list_lock); + for (i = 0; i < AES_NR_KEYSLOTS; i++) { + if (i == SSK_SLOT_NUM) + continue; + dd->slots[i].slot_num = i; + INIT_LIST_HEAD(&dd->slots[i].node); + list_add_tail(&dd->slots[i].node, &dev_list); + } + spin_unlock(&list_lock); + + aes_dev = dd; + for (i = 0; i < ARRAY_SIZE(algs); i++) { + INIT_LIST_HEAD(&algs[i].cra_list); + + algs[i].cra_priority = 300; + algs[i].cra_ctxsize = sizeof(struct tegra_aes_ctx); + algs[i].cra_module = THIS_MODULE; + algs[i].cra_init = tegra_aes_cra_init; + algs[i].cra_exit = tegra_aes_cra_exit; + + err = crypto_register_alg(&algs[i]); + if (err) + goto out; + } + + dev_info(dev, "registered"); + return 0; + +out: + for (j = 0; j < i; j++) + crypto_unregister_alg(&algs[j]); + if (dd->ivkey_base) + dma_free_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES, + dd->ivkey_base, dd->ivkey_phys_base); + if (dd->buf_in) + dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + dd->buf_in, dd->dma_buf_in); + if (dd->buf_out) + dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + dd->buf_out, dd->dma_buf_out); + if (IS_ERR(dd->aes_clk)) + clk_put(dd->aes_clk); + if (aes_wq) + destroy_workqueue(aes_wq); + spin_lock(&list_lock); + list_del(&dev_list); + spin_unlock(&list_lock); + + aes_dev = NULL; + + dev_err(dev, "%s: initialization failed.\n", __func__); + return err; +} + +static int __devexit tegra_aes_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct tegra_aes_dev *dd = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < ARRAY_SIZE(algs); i++) + crypto_unregister_alg(&algs[i]); + + cancel_work_sync(&aes_work); + destroy_workqueue(aes_wq); + spin_lock(&list_lock); + list_del(&dev_list); + spin_unlock(&list_lock); + + dma_free_coherent(dev, AES_HW_KEY_TABLE_LENGTH_BYTES, + dd->ivkey_base, dd->ivkey_phys_base); + dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + dd->buf_in, dd->dma_buf_in); + dma_free_coherent(dev, AES_HW_DMA_BUFFER_SIZE_BYTES, + dd->buf_out, dd->dma_buf_out); + clk_put(dd->aes_clk); + aes_dev = NULL; + + return 0; +} + +static struct of_device_id tegra_aes_of_match[] __devinitdata = { + { .compatible = "nvidia,tegra20-aes", }, + { .compatible = "nvidia,tegra30-aes", }, + { }, +}; + +static struct platform_driver tegra_aes_driver = { + .probe = tegra_aes_probe, + .remove = __devexit_p(tegra_aes_remove), + .driver = { + .name = "tegra-aes", + .owner = THIS_MODULE, + .of_match_table = tegra_aes_of_match, + }, +}; + +module_platform_driver(tegra_aes_driver); + +MODULE_DESCRIPTION("Tegra AES/OFB/CPRNG hw acceleration support."); +MODULE_AUTHOR("NVIDIA Corporation"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/crypto/tegra-aes.h b/drivers/crypto/tegra-aes.h new file mode 100644 index 000000000000..6006333a8934 --- /dev/null +++ b/drivers/crypto/tegra-aes.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2010, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __CRYPTODEV_TEGRA_AES_H +#define __CRYPTODEV_TEGRA_AES_H + +#define TEGRA_AES_ICMDQUE_WR 0x1000 +#define TEGRA_AES_CMDQUE_CONTROL 0x1008 +#define TEGRA_AES_INTR_STATUS 0x1018 +#define TEGRA_AES_INT_ENB 0x1040 +#define TEGRA_AES_CONFIG 0x1044 +#define TEGRA_AES_IRAM_ACCESS_CFG 0x10A0 +#define TEGRA_AES_SECURE_DEST_ADDR 0x1100 +#define TEGRA_AES_SECURE_INPUT_SELECT 0x1104 +#define TEGRA_AES_SECURE_CONFIG 0x1108 +#define TEGRA_AES_SECURE_CONFIG_EXT 0x110C +#define TEGRA_AES_SECURE_SECURITY 0x1110 +#define TEGRA_AES_SECURE_HASH_RESULT0 0x1120 +#define TEGRA_AES_SECURE_HASH_RESULT1 0x1124 +#define TEGRA_AES_SECURE_HASH_RESULT2 0x1128 +#define TEGRA_AES_SECURE_HASH_RESULT3 0x112C +#define TEGRA_AES_SECURE_SEC_SEL0 0x1140 +#define TEGRA_AES_SECURE_SEC_SEL1 0x1144 +#define TEGRA_AES_SECURE_SEC_SEL2 0x1148 +#define TEGRA_AES_SECURE_SEC_SEL3 0x114C +#define TEGRA_AES_SECURE_SEC_SEL4 0x1150 +#define TEGRA_AES_SECURE_SEC_SEL5 0x1154 +#define TEGRA_AES_SECURE_SEC_SEL6 0x1158 +#define TEGRA_AES_SECURE_SEC_SEL7 0x115C + +/* interrupt status reg masks and shifts */ +#define TEGRA_AES_ENGINE_BUSY_FIELD BIT(0) +#define TEGRA_AES_ICQ_EMPTY_FIELD BIT(3) +#define TEGRA_AES_DMA_BUSY_FIELD BIT(23) + +/* secure select reg masks and shifts */ +#define TEGRA_AES_SECURE_SEL0_KEYREAD_ENB0_FIELD BIT(0) + +/* secure config ext masks and shifts */ +#define TEGRA_AES_SECURE_KEY_SCH_DIS_FIELD BIT(15) + +/* secure config masks and shifts */ +#define TEGRA_AES_SECURE_KEY_INDEX_SHIFT 20 +#define TEGRA_AES_SECURE_KEY_INDEX_FIELD (0x1F << TEGRA_AES_SECURE_KEY_INDEX_SHIFT) +#define TEGRA_AES_SECURE_BLOCK_CNT_SHIFT 0 +#define TEGRA_AES_SECURE_BLOCK_CNT_FIELD (0xFFFFF << TEGRA_AES_SECURE_BLOCK_CNT_SHIFT) + +/* stream interface select masks and shifts */ +#define TEGRA_AES_CMDQ_CTRL_UCMDQEN_FIELD BIT(0) +#define TEGRA_AES_CMDQ_CTRL_ICMDQEN_FIELD BIT(1) +#define TEGRA_AES_CMDQ_CTRL_SRC_STM_SEL_FIELD BIT(4) +#define TEGRA_AES_CMDQ_CTRL_DST_STM_SEL_FIELD BIT(5) + +/* config register masks and shifts */ +#define TEGRA_AES_CONFIG_ENDIAN_ENB_FIELD BIT(10) +#define TEGRA_AES_CONFIG_MODE_SEL_SHIFT 0 +#define TEGRA_AES_CONFIG_MODE_SEL_FIELD (0x1F << TEGRA_AES_CONFIG_MODE_SEL_SHIFT) + +/* extended config */ +#define TEGRA_AES_SECURE_OFFSET_CNT_SHIFT 24 +#define TEGRA_AES_SECURE_OFFSET_CNT_FIELD (0xFF << TEGRA_AES_SECURE_OFFSET_CNT_SHIFT) +#define TEGRA_AES_SECURE_KEYSCHED_GEN_FIELD BIT(15) + +/* init vector select */ +#define TEGRA_AES_SECURE_IV_SELECT_SHIFT 10 +#define TEGRA_AES_SECURE_IV_SELECT_FIELD BIT(10) + +/* secure engine input */ +#define TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT 28 +#define TEGRA_AES_SECURE_INPUT_ALG_SEL_FIELD (0xF << TEGRA_AES_SECURE_INPUT_ALG_SEL_SHIFT) +#define TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT 16 +#define TEGRA_AES_SECURE_INPUT_KEY_LEN_FIELD (0xFFF << TEGRA_AES_SECURE_INPUT_KEY_LEN_SHIFT) +#define TEGRA_AES_SECURE_RNG_ENB_FIELD BIT(11) +#define TEGRA_AES_SECURE_CORE_SEL_SHIFT 9 +#define TEGRA_AES_SECURE_CORE_SEL_FIELD BIT(9) +#define TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT 7 +#define TEGRA_AES_SECURE_VCTRAM_SEL_FIELD (0x3 << TEGRA_AES_SECURE_VCTRAM_SEL_SHIFT) +#define TEGRA_AES_SECURE_INPUT_SEL_SHIFT 5 +#define TEGRA_AES_SECURE_INPUT_SEL_FIELD (0x3 << TEGRA_AES_SECURE_INPUT_SEL_SHIFT) +#define TEGRA_AES_SECURE_XOR_POS_SHIFT 3 +#define TEGRA_AES_SECURE_XOR_POS_FIELD (0x3 << TEGRA_AES_SECURE_XOR_POS_SHIFT) +#define TEGRA_AES_SECURE_HASH_ENB_FIELD BIT(2) +#define TEGRA_AES_SECURE_ON_THE_FLY_FIELD BIT(0) + +/* interrupt error mask */ +#define TEGRA_AES_INT_ERROR_MASK 0xFFF000 + +#endif -- GitLab From a522ee85ba979e7897a75b1c97db1b0304b68b5c Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 20 Dec 2011 12:20:16 +0200 Subject: [PATCH 00086/10698] crypto: twofish-x86_64-3way - blacklist pentium4 and atom Performance of twofish-x86_64-3way on Intel Pentium 4 and Atom is lower than of twofish-x86_64 module. So blacklist these CPUs. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/twofish_glue_3way.c | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/arch/x86/crypto/twofish_glue_3way.c b/arch/x86/crypto/twofish_glue_3way.c index 7fee8c152f93..0afd134d8c9c 100644 --- a/arch/x86/crypto/twofish_glue_3way.c +++ b/arch/x86/crypto/twofish_glue_3way.c @@ -25,6 +25,7 @@ * */ +#include #include #include #include @@ -637,10 +638,56 @@ static struct crypto_alg blk_xts_alg = { }, }; +static bool is_blacklisted_cpu(void) +{ + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) + return false; + + if (boot_cpu_data.x86 == 0x06 && + (boot_cpu_data.x86_model == 0x1c || + boot_cpu_data.x86_model == 0x26 || + boot_cpu_data.x86_model == 0x36)) { + /* + * On Atom, twofish-3way is slower than original assembler + * implementation. Twofish-3way trades off some performance in + * storing blocks in 64bit registers to allow three blocks to + * be processed parallel. Parallel operation then allows gaining + * more performance than was trade off, on out-of-order CPUs. + * However Atom does not benefit from this parallellism and + * should be blacklisted. + */ + return true; + } + + if (boot_cpu_data.x86 == 0x0f) { + /* + * On Pentium 4, twofish-3way is slower than original assembler + * implementation because excessive uses of 64bit rotate and + * left-shifts (which are really slow on P4) needed to store and + * handle 128bit block in two 64bit registers. + */ + return true; + } + + return false; +} + +static int force; +module_param(force, int, 0); +MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist"); + int __init init(void) { int err; + if (!force && is_blacklisted_cpu()) { + printk(KERN_INFO + "twofish-x86_64-3way: performance on this CPU " + "would be suboptimal: disabling " + "twofish-x86_64-3way.\n"); + return -ENODEV; + } + err = crypto_register_alg(&blk_ecb_alg); if (err) goto ecb_err; -- GitLab From 4c58464b8034cef4317593bf4ccbfc19d5bb3a77 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 20 Dec 2011 12:20:21 +0200 Subject: [PATCH 00087/10698] crypto: blowfish-x86_64 - blacklist Pentium 4 Implementation in blowfish-x86_64 uses 64bit rotations which are slow on P4, making blowfish-x86_64 slower than generic C implementation. Therefore blacklist P4. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/blowfish_glue.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/x86/crypto/blowfish_glue.c b/arch/x86/crypto/blowfish_glue.c index b05aa163d55a..2970110d2cea 100644 --- a/arch/x86/crypto/blowfish_glue.c +++ b/arch/x86/crypto/blowfish_glue.c @@ -25,6 +25,7 @@ * */ +#include #include #include #include @@ -446,10 +447,39 @@ static struct crypto_alg blk_ctr_alg = { }, }; +static bool is_blacklisted_cpu(void) +{ + if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) + return false; + + if (boot_cpu_data.x86 == 0x0f) { + /* + * On Pentium 4, blowfish-x86_64 is slower than generic C + * implementation because use of 64bit rotates (which are really + * slow on P4). Therefore blacklist P4s. + */ + return true; + } + + return false; +} + +static int force; +module_param(force, int, 0); +MODULE_PARM_DESC(force, "Force module load, ignore CPU blacklist"); + static int __init init(void) { int err; + if (!force && is_blacklisted_cpu()) { + printk(KERN_INFO + "blowfish-x86_64: performance on this CPU " + "would be suboptimal: disabling " + "blowfish-x86_64.\n"); + return -ENODEV; + } + err = crypto_register_alg(&bf_alg); if (err) goto bf_err; -- GitLab From 847cb7ef565d31484f426677e0bea081bfd2acd9 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 20 Dec 2011 12:58:06 +0200 Subject: [PATCH 00088/10698] crypto: serpent-sse2 - change transpose_4x4 to only use integer instructions Matrix transpose macro in serpent-sse2 uses mix of SSE2 integer and SSE floating point instructions, which might cause performance penality on some CPUs. This patch replaces transpose_4x4 macro with version that uses only SSE2 integer instructions. Signed-off-by: Jussi Kivilinna Signed-off-by: Herbert Xu --- arch/x86/crypto/serpent-sse2-i586-asm_32.S | 29 +++++++++----------- arch/x86/crypto/serpent-sse2-x86_64-asm_64.S | 29 +++++++++----------- 2 files changed, 26 insertions(+), 32 deletions(-) diff --git a/arch/x86/crypto/serpent-sse2-i586-asm_32.S b/arch/x86/crypto/serpent-sse2-i586-asm_32.S index 4e37677ca851..c00053d42f99 100644 --- a/arch/x86/crypto/serpent-sse2-i586-asm_32.S +++ b/arch/x86/crypto/serpent-sse2-i586-asm_32.S @@ -463,23 +463,20 @@ pand x0, x4; \ pxor x2, x4; -#define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \ - movdqa x2, t3; \ - movdqa x0, t1; \ - unpcklps x3, t3; \ +#define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ movdqa x0, t2; \ - unpcklps x1, t1; \ - unpckhps x1, t2; \ - movdqa t3, x1; \ - unpckhps x3, x2; \ - movdqa t1, x0; \ - movhlps t1, x1; \ - movdqa t2, t1; \ - movlhps t3, x0; \ - movlhps x2, t1; \ - movhlps t2, x2; \ - movdqa x2, x3; \ - movdqa t1, x2; + punpckldq x1, x0; \ + punpckhdq x1, t2; \ + movdqa x2, t1; \ + punpckhdq x3, x2; \ + punpckldq x3, t1; \ + movdqa x0, x1; \ + punpcklqdq t1, x0; \ + punpckhqdq t1, x1; \ + movdqa t2, x3; \ + punpcklqdq x2, t2; \ + punpckhqdq x2, x3; \ + movdqa t2, x2; #define read_blocks(in, x0, x1, x2, x3, t0, t1, t2) \ movdqu (0*4*4)(in), x0; \ diff --git a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S b/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S index 7f24a1540821..3ee1ff04d3e9 100644 --- a/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S +++ b/arch/x86/crypto/serpent-sse2-x86_64-asm_64.S @@ -585,23 +585,20 @@ get_key(i, 1, RK1); \ SBOX ## _2(x0 ## 2, x1 ## 2, x2 ## 2, x3 ## 2, x4 ## 2); \ -#define transpose_4x4(x0, x1, x2, x3, t1, t2, t3) \ - movdqa x2, t3; \ - movdqa x0, t1; \ - unpcklps x3, t3; \ +#define transpose_4x4(x0, x1, x2, x3, t0, t1, t2) \ movdqa x0, t2; \ - unpcklps x1, t1; \ - unpckhps x1, t2; \ - movdqa t3, x1; \ - unpckhps x3, x2; \ - movdqa t1, x0; \ - movhlps t1, x1; \ - movdqa t2, t1; \ - movlhps t3, x0; \ - movlhps x2, t1; \ - movhlps t2, x2; \ - movdqa x2, x3; \ - movdqa t1, x2; + punpckldq x1, x0; \ + punpckhdq x1, t2; \ + movdqa x2, t1; \ + punpckhdq x3, x2; \ + punpckldq x3, t1; \ + movdqa x0, x1; \ + punpcklqdq t1, x0; \ + punpckhqdq t1, x1; \ + movdqa t2, x3; \ + punpcklqdq x2, t2; \ + punpckhqdq x2, x3; \ + movdqa t2, x2; #define read_blocks(in, x0, x1, x2, x3, t0, t1, t2) \ movdqu (0*4*4)(in), x0; \ -- GitLab From d0b03c5fe469ed0f3d7d94372c8bf77c64fcfce8 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 27 Dec 2011 15:01:30 +0100 Subject: [PATCH 00089/10698] hwrng: tx4939 - use devm_request_and_ioremap Reimplement a call to devm_request_mem_region followed by a call to ioremap or ioremap_nocache by a call to devm_request_and_ioremap. The semantic patch that makes this transformation is as follows: (http://coccinelle.lip6.fr/) // @nm@ expression myname; identifier i; @@ struct platform_driver i = { .driver = { .name = myname } }; @@ expression dev,res,size; expression nm.myname; @@ -if (!devm_request_mem_region(dev, res->start, size, - \(res->name\|dev_name(dev)\|myname\))) { - ... - return ...; -} ... when != res->start ( -devm_ioremap(dev,res->start,size) +devm_request_and_ioremap(dev,res) | -devm_ioremap_nocache(dev,res->start,size) +devm_request_and_ioremap(dev,res) ) ... when any when != res->start // Signed-off-by: Julia Lawall Signed-off-by: Herbert Xu --- drivers/char/hw_random/tx4939-rng.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c index 0bc0cb70210b..de473ef3882b 100644 --- a/drivers/char/hw_random/tx4939-rng.c +++ b/drivers/char/hw_random/tx4939-rng.c @@ -115,10 +115,7 @@ static int __init tx4939_rng_probe(struct platform_device *dev) rngdev = devm_kzalloc(&dev->dev, sizeof(*rngdev), GFP_KERNEL); if (!rngdev) return -ENOMEM; - if (!devm_request_mem_region(&dev->dev, r->start, resource_size(r), - dev_name(&dev->dev))) - return -EBUSY; - rngdev->base = devm_ioremap(&dev->dev, r->start, resource_size(r)); + rngdev->base = devm_request_and_ioremap(&dev->dev, r); if (!rngdev->base) return -EBUSY; -- GitLab From d912bb7677f46d78a3cde8a4afd45a3fca4b34e9 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Tue, 1 Nov 2011 13:39:56 +0100 Subject: [PATCH 00090/10698] crypto: Add CRYPTO_ALG_KERN_DRIVER_ONLY flag The added CRYPTO_ALG_KERN_DRIVER_ONLY indicates whether a cipher is only available via a kernel driver. If the cipher implementation might be available by using an instruction set or by porting the kernel code, then it must not be set. Signed-off-by: Nikos Mavrogiannopoulos Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 3 +- drivers/crypto/geode-aes.c | 6 ++-- drivers/crypto/hifn_795x.c | 3 +- drivers/crypto/ixp4xx_crypto.c | 2 ++ drivers/crypto/mv_cesa.c | 12 +++++--- drivers/crypto/n2_core.c | 7 +++-- drivers/crypto/omap-aes.c | 8 ++++-- drivers/crypto/omap-sham.c | 4 +++ drivers/crypto/picoxcell_crypto.c | 46 +++++++++++++++++++++++-------- drivers/crypto/s5p-sss.c | 6 ++-- drivers/crypto/talitos.c | 1 + include/linux/crypto.h | 5 ++++ 12 files changed, 78 insertions(+), 25 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index e73cf2e8110a..e9acadbb1d34 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -2205,7 +2205,8 @@ static struct caam_crypto_alg *caam_alg_alloc(struct device *ctrldev, alg->cra_blocksize = template->blocksize; alg->cra_alignmask = 0; alg->cra_ctxsize = sizeof(struct caam_ctx); - alg->cra_flags = CRYPTO_ALG_ASYNC | template->type; + alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY | + template->type; switch (template->type) { case CRYPTO_ALG_TYPE_ABLKCIPHER: alg->cra_type = &crypto_ablkcipher_type; diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c index 219d09cbb0d1..f3e36c86b6c3 100644 --- a/drivers/crypto/geode-aes.c +++ b/drivers/crypto/geode-aes.c @@ -393,7 +393,8 @@ static struct crypto_alg geode_cbc_alg = { .cra_driver_name = "cbc-aes-geode", .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | - CRYPTO_ALG_NEED_FALLBACK, + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, .cra_init = fallback_init_blk, .cra_exit = fallback_exit_blk, .cra_blocksize = AES_MIN_BLOCK_SIZE, @@ -479,7 +480,8 @@ static struct crypto_alg geode_ecb_alg = { .cra_driver_name = "ecb-aes-geode", .cra_priority = 400, .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER | - CRYPTO_ALG_NEED_FALLBACK, + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, .cra_init = fallback_init_blk, .cra_exit = fallback_exit_blk, .cra_blocksize = AES_MIN_BLOCK_SIZE, diff --git a/drivers/crypto/hifn_795x.c b/drivers/crypto/hifn_795x.c index fe765f49de58..6bd9d1768202 100644 --- a/drivers/crypto/hifn_795x.c +++ b/drivers/crypto/hifn_795x.c @@ -2494,7 +2494,8 @@ static int hifn_alg_alloc(struct hifn_device *dev, struct hifn_alg_template *t) t->drv_name, dev->name); alg->alg.cra_priority = 300; - alg->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC; + alg->alg.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC; alg->alg.cra_blocksize = t->bsize; alg->alg.cra_ctxsize = sizeof(struct hifn_context); alg->alg.cra_alignmask = 0; diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 4c20c5bf6058..a82c11af9f48 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -1449,6 +1449,7 @@ static int __init ixp_module_init(void) /* block ciphers */ cra->cra_type = &crypto_ablkcipher_type; cra->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC; if (!cra->cra_ablkcipher.setkey) cra->cra_ablkcipher.setkey = ablk_setkey; @@ -1461,6 +1462,7 @@ static int __init ixp_module_init(void) /* authenc */ cra->cra_type = &crypto_aead_type; cra->cra_flags = CRYPTO_ALG_TYPE_AEAD | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC; cra->cra_aead.setkey = aead_setkey; cra->cra_aead.setauthsize = aead_setauthsize; diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c index 597235a2f8f9..8ad2883505a5 100644 --- a/drivers/crypto/mv_cesa.c +++ b/drivers/crypto/mv_cesa.c @@ -898,7 +898,8 @@ struct crypto_alg mv_aes_alg_ecb = { .cra_name = "ecb(aes)", .cra_driver_name = "mv-ecb-aes", .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC, .cra_blocksize = 16, .cra_ctxsize = sizeof(struct mv_ctx), .cra_alignmask = 0, @@ -920,7 +921,8 @@ struct crypto_alg mv_aes_alg_cbc = { .cra_name = "cbc(aes)", .cra_driver_name = "mv-cbc-aes", .cra_priority = 300, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct mv_ctx), .cra_alignmask = 0, @@ -952,7 +954,8 @@ struct ahash_alg mv_sha1_alg = { .cra_driver_name = "mv-sha1", .cra_priority = 300, .cra_flags = - CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct mv_tfm_hash_ctx), .cra_init = mv_cra_hash_sha1_init, @@ -976,7 +979,8 @@ struct ahash_alg mv_hmac_sha1_alg = { .cra_driver_name = "mv-hmac-sha1", .cra_priority = 300, .cra_flags = - CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, + CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA1_BLOCK_SIZE, .cra_ctxsize = sizeof(struct mv_tfm_hash_ctx), .cra_init = mv_cra_hash_hmac_sha1_init, diff --git a/drivers/crypto/n2_core.c b/drivers/crypto/n2_core.c index 8944dabc0e3c..67b97c5fd859 100644 --- a/drivers/crypto/n2_core.c +++ b/drivers/crypto/n2_core.c @@ -1402,7 +1402,8 @@ static int __devinit __n2_register_one_cipher(const struct n2_cipher_tmpl *tmpl) snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", tmpl->name); snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s-n2", tmpl->drv_name); alg->cra_priority = N2_CRA_PRIORITY; - alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC; + alg->cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC; alg->cra_blocksize = tmpl->block_size; p->enc_type = tmpl->enc_type; alg->cra_ctxsize = sizeof(struct n2_cipher_context); @@ -1493,7 +1494,9 @@ static int __devinit __n2_register_one_ahash(const struct n2_hash_tmpl *tmpl) snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", tmpl->name); snprintf(base->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s-n2", tmpl->name); base->cra_priority = N2_CRA_PRIORITY; - base->cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_NEED_FALLBACK; + base->cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_NEED_FALLBACK; base->cra_blocksize = tmpl->block_size; base->cra_ctxsize = sizeof(struct n2_hash_ctx); base->cra_module = THIS_MODULE; diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c index 5b970d9e9956..63e57b57a12c 100644 --- a/drivers/crypto/omap-aes.c +++ b/drivers/crypto/omap-aes.c @@ -756,7 +756,9 @@ static struct crypto_alg algs[] = { .cra_name = "ecb(aes)", .cra_driver_name = "ecb-aes-omap", .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct omap_aes_ctx), .cra_alignmask = 0, @@ -776,7 +778,9 @@ static struct crypto_alg algs[] = { .cra_name = "cbc(aes)", .cra_driver_name = "cbc-aes-omap", .cra_priority = 100, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_KERN_DRIVER_ONLY | + CRYPTO_ALG_ASYNC, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct omap_aes_ctx), .cra_alignmask = 0, diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index 6399a8f1938a..a3fd6fc504b1 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -953,6 +953,7 @@ static struct ahash_alg algs[] = { .cra_driver_name = "omap-sha1", .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA1_BLOCK_SIZE, @@ -975,6 +976,7 @@ static struct ahash_alg algs[] = { .cra_driver_name = "omap-md5", .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA1_BLOCK_SIZE, @@ -998,6 +1000,7 @@ static struct ahash_alg algs[] = { .cra_driver_name = "omap-hmac-sha1", .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA1_BLOCK_SIZE, @@ -1022,6 +1025,7 @@ static struct ahash_alg algs[] = { .cra_driver_name = "omap-hmac-md5", .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_AHASH | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = SHA1_BLOCK_SIZE, diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c index 58480d009324..410a03c01ca4 100644 --- a/drivers/crypto/picoxcell_crypto.c +++ b/drivers/crypto/picoxcell_crypto.c @@ -1322,6 +1322,7 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_driver_name = "cbc-aes-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = AES_BLOCK_SIZE, @@ -1349,6 +1350,7 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_driver_name = "ecb-aes-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_ablk_ctx), @@ -1373,7 +1375,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "cbc(des)", .cra_driver_name = "cbc-des-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_ablk_ctx), .cra_type = &crypto_ablkcipher_type, @@ -1398,7 +1402,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "ecb(des)", .cra_driver_name = "ecb-des-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = DES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_ablk_ctx), .cra_type = &crypto_ablkcipher_type, @@ -1422,7 +1428,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "cbc(des3_ede)", .cra_driver_name = "cbc-des3-ede-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_ablk_ctx), .cra_type = &crypto_ablkcipher_type, @@ -1447,7 +1455,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "ecb(des3_ede)", .cra_driver_name = "ecb-des3-ede-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_ablk_ctx), .cra_type = &crypto_ablkcipher_type, @@ -1472,7 +1482,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "authenc(hmac(sha1),cbc(aes))", .cra_driver_name = "authenc-hmac-sha1-cbc-aes-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_aead_ctx), .cra_type = &crypto_aead_type, @@ -1500,7 +1512,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "authenc(hmac(sha256),cbc(aes))", .cra_driver_name = "authenc-hmac-sha256-cbc-aes-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_aead_ctx), .cra_type = &crypto_aead_type, @@ -1527,7 +1541,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "authenc(hmac(md5),cbc(aes))", .cra_driver_name = "authenc-hmac-md5-cbc-aes-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_aead_ctx), .cra_type = &crypto_aead_type, @@ -1554,7 +1570,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "authenc(hmac(sha1),cbc(des3_ede))", .cra_driver_name = "authenc-hmac-sha1-cbc-3des-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_aead_ctx), .cra_type = &crypto_aead_type, @@ -1582,7 +1600,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "authenc(hmac(sha256),cbc(des3_ede))", .cra_driver_name = "authenc-hmac-sha256-cbc-3des-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_aead_ctx), .cra_type = &crypto_aead_type, @@ -1609,7 +1629,9 @@ static struct spacc_alg ipsec_engine_algs[] = { .cra_name = "authenc(hmac(md5),cbc(des3_ede))", .cra_driver_name = "authenc-hmac-md5-cbc-3des-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_AEAD | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_ctxsize = sizeof(struct spacc_aead_ctx), .cra_type = &crypto_aead_type, @@ -1639,7 +1661,9 @@ static struct spacc_alg l2_engine_algs[] = { .cra_name = "f8(kasumi)", .cra_driver_name = "f8-kasumi-picoxcell", .cra_priority = SPACC_CRYPTO_ALG_PRIORITY, - .cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_ASYNC, + .cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = 8, .cra_ctxsize = sizeof(struct spacc_ablk_ctx), .cra_type = &crypto_ablkcipher_type, diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c index 3376bca200fc..bc986f806086 100644 --- a/drivers/crypto/s5p-sss.c +++ b/drivers/crypto/s5p-sss.c @@ -518,7 +518,8 @@ static struct crypto_alg algs[] = { .cra_driver_name = "ecb-aes-s5p", .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | - CRYPTO_ALG_ASYNC, + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s5p_aes_ctx), .cra_alignmask = 0x0f, @@ -538,7 +539,8 @@ static struct crypto_alg algs[] = { .cra_driver_name = "cbc-aes-s5p", .cra_priority = 100, .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | - CRYPTO_ALG_ASYNC, + CRYPTO_ALG_ASYNC | + CRYPTO_ALG_KERN_DRIVER_ONLY, .cra_blocksize = AES_BLOCK_SIZE, .cra_ctxsize = sizeof(struct s5p_aes_ctx), .cra_alignmask = 0x0f, diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 2d8c78901686..dc641c796526 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -2648,6 +2648,7 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev, alg->cra_priority = TALITOS_CRA_PRIORITY; alg->cra_alignmask = 0; alg->cra_ctxsize = sizeof(struct talitos_ctx); + alg->cra_flags |= CRYPTO_ALG_KERN_DRIVER_ONLY; t_alg->dev = dev; diff --git a/include/linux/crypto.h b/include/linux/crypto.h index 8a94217b298e..a8fa6541b86c 100644 --- a/include/linux/crypto.h +++ b/include/linux/crypto.h @@ -75,6 +75,11 @@ */ #define CRYPTO_ALG_INSTANCE 0x00000800 +/* Set this bit if the algorithm provided is hardware accelerated but + * not available to userspace via instruction set or so. + */ +#define CRYPTO_ALG_KERN_DRIVER_ONLY 0x00001000 + /* * Transform masks and values (for crt_flags). */ -- GitLab From e7a2577a410a066ae409f805618f7e84748a537d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 9 Jan 2012 10:40:49 +0100 Subject: [PATCH 00091/10698] crypto: ixp4xx - convert GFP_KERNEL to GFP_ATOMIC The function is called with locks held and thus should not use GFP_KERNEL. The semantic patch that makes this report is available in scripts/coccinelle/locks/call_kern.cocci. More information about semantic patching is available at http://coccinelle.lip6.fr/ Signed-off-by: Julia Lawall Signed-off-by: Herbert Xu --- drivers/crypto/ixp4xx_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index a82c11af9f48..0053d7ebb5ca 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -265,7 +265,7 @@ static int setup_crypt_desc(void) BUILD_BUG_ON(sizeof(struct crypt_ctl) != 64); crypt_virt = dma_alloc_coherent(dev, NPE_QLEN * sizeof(struct crypt_ctl), - &crypt_phys, GFP_KERNEL); + &crypt_phys, GFP_ATOMIC); if (!crypt_virt) return -ENOMEM; memset(crypt_virt, 0, NPE_QLEN * sizeof(struct crypt_ctl)); -- GitLab From e863f9ccc7658883be7b42eb63851aef9da7630c Mon Sep 17 00:00:00 2001 From: Hemant Agrawal Date: Mon, 9 Jan 2012 18:26:44 -0600 Subject: [PATCH 00092/10698] crypto: caam - add sha224 and sha384 variants to existing AEAD algorithms Signed-off-by: Hemant Agrawal Signed-off-by: Kim Phillips Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 115 ++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index e9acadbb1d34..4cd2d84a2a15 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -1843,6 +1843,25 @@ static struct caam_alg_template driver_algs[] = { .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha224),cbc(aes))", + .driver_name = "authenc-hmac-sha224-cbc-aes-caam", + .blocksize = AES_BLOCK_SIZE, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA224 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha256),cbc(aes))", .driver_name = "authenc-hmac-sha256-cbc-aes-caam", @@ -1863,6 +1882,26 @@ static struct caam_alg_template driver_algs[] = { OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha384),cbc(aes))", + .driver_name = "authenc-hmac-sha384-cbc-aes-caam", + .blocksize = AES_BLOCK_SIZE, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = AES_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA384 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC, + }, + { .name = "authenc(hmac(sha512),cbc(aes))", .driver_name = "authenc-hmac-sha512-cbc-aes-caam", @@ -1921,6 +1960,25 @@ static struct caam_alg_template driver_algs[] = { .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha224),cbc(des3_ede))", + .driver_name = "authenc-hmac-sha224-cbc-des3_ede-caam", + .blocksize = DES3_EDE_BLOCK_SIZE, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA224 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha256),cbc(des3_ede))", .driver_name = "authenc-hmac-sha256-cbc-des3_ede-caam", @@ -1941,6 +1999,25 @@ static struct caam_alg_template driver_algs[] = { OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha384),cbc(des3_ede))", + .driver_name = "authenc-hmac-sha384-cbc-des3_ede-caam", + .blocksize = DES3_EDE_BLOCK_SIZE, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES3_EDE_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA384 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha512),cbc(des3_ede))", .driver_name = "authenc-hmac-sha512-cbc-des3_ede-caam", @@ -1999,6 +2076,25 @@ static struct caam_alg_template driver_algs[] = { .class2_alg_type = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA1 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha224),cbc(des))", + .driver_name = "authenc-hmac-sha224-cbc-des-caam", + .blocksize = DES_BLOCK_SIZE, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = SHA224_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA224 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA224 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha256),cbc(des))", .driver_name = "authenc-hmac-sha256-cbc-des-caam", @@ -2019,6 +2115,25 @@ static struct caam_alg_template driver_algs[] = { OP_ALG_AAI_HMAC_PRECOMP, .alg_op = OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HMAC, }, + { + .name = "authenc(hmac(sha384),cbc(des))", + .driver_name = "authenc-hmac-sha384-cbc-des-caam", + .blocksize = DES_BLOCK_SIZE, + .template_aead = { + .setkey = aead_setkey, + .setauthsize = aead_setauthsize, + .encrypt = aead_encrypt, + .decrypt = aead_decrypt, + .givencrypt = aead_givencrypt, + .geniv = "", + .ivsize = DES_BLOCK_SIZE, + .maxauthsize = SHA384_DIGEST_SIZE, + }, + .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, + .class2_alg_type = OP_ALG_ALGSEL_SHA384 | + OP_ALG_AAI_HMAC_PRECOMP, + .alg_op = OP_ALG_ALGSEL_SHA384 | OP_ALG_AAI_HMAC, + }, { .name = "authenc(hmac(sha512),cbc(des))", .driver_name = "authenc-hmac-sha512-cbc-des-caam", -- GitLab From 0113529f37bcd17399403c68736b8ba59c7397b7 Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Mon, 9 Jan 2012 18:26:49 -0600 Subject: [PATCH 00093/10698] crypto: caam - be less noisy on startup sha224 and 384 support extends caam noise to 21 lines. Do the same as commit 5b859b6 "crypto: talitos - be less noisy on startup", but for caam, and display: caam ffe300000.crypto: fsl,sec-v4.0 algorithms registered in /proc/crypto Signed-off-by: Kim Phillips Signed-off-by: Herbert Xu --- drivers/crypto/caam/caamalg.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index 4cd2d84a2a15..534a36469d57 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c @@ -2401,12 +2401,12 @@ static int __init caam_algapi_init(void) dev_warn(ctrldev, "%s alg registration failed\n", t_alg->crypto_alg.cra_driver_name); kfree(t_alg); - } else { + } else list_add_tail(&t_alg->entry, &priv->alg_list); - dev_info(ctrldev, "%s\n", - t_alg->crypto_alg.cra_driver_name); - } } + if (!list_empty(&priv->alg_list)) + dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n", + (char *)of_get_property(dev_node, "compatible", NULL)); return err; } -- GitLab From bfe75c7e67e5f32bf446a48e0502d06d25b51752 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 13 Jan 2012 16:27:38 +0900 Subject: [PATCH 00094/10698] sh: Defer to asm-generic/device.h. Now that the hwblk use cases have been ripped out, we can revert to asm-generic/device.h for the device/platform device arch data structures. Signed-off-by: Paul Mundt --- arch/sh/include/asm/device.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/sh/include/asm/device.h b/arch/sh/include/asm/device.h index a1c9c0daec10..071bcb4d4bfd 100644 --- a/arch/sh/include/asm/device.h +++ b/arch/sh/include/asm/device.h @@ -3,9 +3,10 @@ * * This file is released under the GPLv2 */ +#ifndef __ASM_SH_DEVICE_H +#define __ASM_SH_DEVICE_H -struct dev_archdata { -}; +#include struct platform_device; /* allocate contiguous memory chunk and fill in struct resource */ @@ -14,5 +15,4 @@ int platform_resource_setup_memory(struct platform_device *pdev, void plat_early_device_setup(void); -struct pdev_archdata { -}; +#endif /* __ASM_SH_DEVICE_H */ -- GitLab From 6d7120a713300283a8b73e7d86cd1bab8b9d1971 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 13 Jan 2012 16:42:50 +0900 Subject: [PATCH 00095/10698] video: pvr2fb: Fix up spurious section mismatch warnings. pvr2fb special cases its init/exit routines which causes spurious section mismatches. Set the board_driver array __refdata to silence them. Signed-off-by: Paul Mundt --- drivers/video/pvr2fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index f9975100d56d..3a3fdc62c75b 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -1061,7 +1061,7 @@ static struct pvr2_board { int (*init)(void); void (*exit)(void); char name[16]; -} board_driver[] = { +} board_driver[] __refdata = { #ifdef CONFIG_SH_DREAMCAST { pvr2fb_dc_init, pvr2fb_dc_exit, "Sega DC PVR2" }, #endif -- GitLab From c1762a3fe196483981f91b926f5f6ee18af757f2 Mon Sep 17 00:00:00 2001 From: Thirumalai Pachamuthu Date: Thu, 12 Jan 2012 18:21:39 +0530 Subject: [PATCH 00096/10698] ath6kl: Add support for uAPSD * A new APSD power save queue is added in the station structure. * When a station has APSD capability and goes to power save, the frame designated to the station will be buffered in APSD queue. * When the host receives a frame which the firmware marked as trigger, host delivers the buffered frame from the APSD power save queue. Number of frames to deliver is decided by MAX SP length. * When a station moves from sleep to awake state, all frames buffered in APSD power save queue are sent to the firmware. * When a station is disconnected, all frames bufferes in APSD power save queue are dropped. * When the host queues the first frame to the APSD queue or removes the last frame from the APSD queue, it is indicated to the firmware using WMI_AP_APSD_BUFFERED_TRAFFIC_CMD. kvalo: fix buggy handling of sks queues, made it more obvious the user priority when wmm is disabled, remove unneed else block and combined some variable declarations Signed-off-by: Thirumalai Pachamuthu Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 6 + drivers/net/wireless/ath/ath6kl/core.h | 10 +- drivers/net/wireless/ath/ath6kl/main.c | 9 +- drivers/net/wireless/ath/ath6kl/txrx.c | 249 ++++++++++++++++++--- drivers/net/wireless/ath/ath6kl/wmi.c | 62 ++++- drivers/net/wireless/ath/ath6kl/wmi.h | 41 +++- 6 files changed, 324 insertions(+), 53 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 1a98c9256c60..a13ecec00702 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2253,6 +2253,11 @@ static int ath6kl_ap_beacon(struct wiphy *wiphy, struct net_device *dev, p.dot11_auth_mode = vif->dot11_auth_mode; p.ch = cpu_to_le16(vif->next_chan); + /* Enable uAPSD support by default */ + res = ath6kl_wmi_ap_set_apsd(ar->wmi, vif->fw_vif_idx, true); + if (res < 0) + return res; + if (vif->wdev.iftype == NL80211_IFTYPE_P2P_GO) { p.nw_subtype = SUBTYPE_P2PGO; } else { @@ -2740,6 +2745,7 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev) for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { spin_lock_init(&ar->sta_list[ctr].psq_lock); skb_queue_head_init(&ar->sta_list[ctr].psq); + skb_queue_head_init(&ar->sta_list[ctr].apsdq); } skb_queue_head_init(&ar->mcastpsq); diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index f4da5e19a365..ba3953918e4c 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -44,6 +44,10 @@ #define ATH6KL_MAX_ENDPOINTS 4 #define MAX_NODE_NUM 15 +#define ATH6KL_APSD_ALL_FRAME 0xFFFF +#define ATH6KL_APSD_NUM_OF_AC 0x4 +#define ATH6KL_APSD_FRAME_MASK 0xF + /* Extra bytes for htc header alignment */ #define ATH6KL_HTC_ALIGN_BYTES 3 @@ -146,6 +150,8 @@ struct ath6kl_fw_ie { #define STA_PS_AWAKE BIT(0) #define STA_PS_SLEEP BIT(1) #define STA_PS_POLLED BIT(2) +#define STA_PS_APSD_TRIGGER BIT(3) +#define STA_PS_APSD_EOSP BIT(4) /* HTC TX packet tagging definitions */ #define ATH6KL_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED @@ -282,6 +288,8 @@ struct ath6kl_sta { u8 wpa_ie[ATH6KL_MAX_IE]; struct sk_buff_head psq; spinlock_t psq_lock; + u8 apsd_info; + struct sk_buff_head apsdq; }; struct ath6kl_version { @@ -714,7 +722,7 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel); void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, u8 keymgmt, u8 ucipher, u8 auth, - u8 assoc_req_len, u8 *assoc_info); + u8 assoc_req_len, u8 *assoc_info, u8 apsd_info); void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, u8 assoc_resp_len, u8 *assoc_info, u16 prot_reason_status); diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 4c26572214c7..53f97db4a7a7 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -53,7 +53,8 @@ struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid) } static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, - size_t ielen, u8 keymgmt, u8 ucipher, u8 auth) + size_t ielen, u8 keymgmt, u8 ucipher, u8 auth, + u8 apsd_info) { struct ath6kl_sta *sta; u8 free_slot; @@ -68,6 +69,7 @@ static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie, sta->keymgmt = keymgmt; sta->ucipher = ucipher; sta->auth = auth; + sta->apsd_info = apsd_info; ar->sta_list_index = ar->sta_list_index | (1 << free_slot); ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid); @@ -80,6 +82,7 @@ static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i) /* empty the queued pkts in the PS queue if any */ spin_lock_bh(&sta->psq_lock); skb_queue_purge(&sta->psq); + skb_queue_purge(&sta->apsdq); spin_unlock_bh(&sta->psq_lock); memset(&ar->ap_stats.sta[sta->aid - 1], 0, @@ -425,7 +428,7 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel) void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, u8 keymgmt, u8 ucipher, u8 auth, - u8 assoc_req_len, u8 *assoc_info) + u8 assoc_req_len, u8 *assoc_info, u8 apsd_info) { struct ath6kl *ar = vif->ar; u8 *ies = NULL, *wpa_ie = NULL, *pos; @@ -483,7 +486,7 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr, ath6kl_add_new_sta(ar, mac_addr, aid, wpa_ie, wpa_ie ? 2 + wpa_ie[1] : 0, - keymgmt, ucipher, auth); + keymgmt, ucipher, auth, apsd_info); /* send event to application */ memset(&sinfo, 0, sizeof(sinfo)); diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index fcea82479cde..91bbc1ffa493 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -77,12 +77,120 @@ static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, return ar->node_map[ep_map].ep_id; } +static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn, + struct ath6kl_vif *vif, + struct sk_buff *skb, + u32 *flags) +{ + struct ath6kl *ar = vif->ar; + bool is_apsdq_empty = false; + struct ethhdr *datap = (struct ethhdr *) skb->data; + u8 up, traffic_class, *ip_hdr; + u16 ether_type; + struct ath6kl_llc_snap_hdr *llc_hdr; + + if (conn->sta_flags & STA_PS_APSD_TRIGGER) { + /* + * This tx is because of a uAPSD trigger, determine + * more and EOSP bit. Set EOSP if queue is empty + * or sufficient frames are delivered for this trigger. + */ + spin_lock_bh(&conn->psq_lock); + if (!skb_queue_empty(&conn->apsdq)) + *flags |= WMI_DATA_HDR_FLAGS_MORE; + else if (conn->sta_flags & STA_PS_APSD_EOSP) + *flags |= WMI_DATA_HDR_FLAGS_EOSP; + *flags |= WMI_DATA_HDR_FLAGS_UAPSD; + spin_unlock_bh(&conn->psq_lock); + return false; + } else if (!conn->apsd_info) + return false; + + if (test_bit(WMM_ENABLED, &vif->flags)) { + ether_type = be16_to_cpu(datap->h_proto); + if (is_ethertype(ether_type)) { + /* packet is in DIX format */ + ip_hdr = (u8 *)(datap + 1); + } else { + /* packet is in 802.3 format */ + llc_hdr = (struct ath6kl_llc_snap_hdr *) + (datap + 1); + ether_type = be16_to_cpu(llc_hdr->eth_type); + ip_hdr = (u8 *)(llc_hdr + 1); + } + + if (ether_type == IP_ETHERTYPE) + up = ath6kl_wmi_determine_user_priority( + ip_hdr, 0); + } else { + up = 0; + } + + traffic_class = ath6kl_wmi_get_traffic_class(up); + + if ((conn->apsd_info & (1 << traffic_class)) == 0) + return false; + + /* Queue the frames if the STA is sleeping */ + spin_lock_bh(&conn->psq_lock); + is_apsdq_empty = skb_queue_empty(&conn->apsdq); + skb_queue_tail(&conn->apsdq, skb); + spin_unlock_bh(&conn->psq_lock); + + /* + * If this is the first pkt getting queued + * for this STA, update the PVB for this STA + */ + if (is_apsdq_empty) { + ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, + vif->fw_vif_idx, + conn->aid, 1, 0); + } + *flags |= WMI_DATA_HDR_FLAGS_UAPSD; + + return true; +} + +static bool ath6kl_process_psq(struct ath6kl_sta *conn, + struct ath6kl_vif *vif, + struct sk_buff *skb, + u32 *flags) +{ + bool is_psq_empty = false; + struct ath6kl *ar = vif->ar; + + if (conn->sta_flags & STA_PS_POLLED) { + spin_lock_bh(&conn->psq_lock); + if (!skb_queue_empty(&conn->psq)) + *flags |= WMI_DATA_HDR_FLAGS_MORE; + spin_unlock_bh(&conn->psq_lock); + return false; + } + + /* Queue the frames if the STA is sleeping */ + spin_lock_bh(&conn->psq_lock); + is_psq_empty = skb_queue_empty(&conn->psq); + skb_queue_tail(&conn->psq, skb); + spin_unlock_bh(&conn->psq_lock); + + /* + * If this is the first pkt getting queued + * for this STA, update the PVB for this + * STA. + */ + if (is_psq_empty) + ath6kl_wmi_set_pvb_cmd(ar->wmi, + vif->fw_vif_idx, + conn->aid, 1); + return true; +} + static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, - bool *more_data) + u32 *flags) { struct ethhdr *datap = (struct ethhdr *) skb->data; struct ath6kl_sta *conn = NULL; - bool ps_queued = false, is_psq_empty = false; + bool ps_queued = false; struct ath6kl *ar = vif->ar; if (is_multicast_ether_addr(datap->h_dest)) { @@ -128,7 +236,7 @@ static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, */ spin_lock_bh(&ar->mcastpsq_lock); if (!skb_queue_empty(&ar->mcastpsq)) - *more_data = true; + *flags |= WMI_DATA_HDR_FLAGS_MORE; spin_unlock_bh(&ar->mcastpsq_lock); } } @@ -142,37 +250,13 @@ static bool ath6kl_powersave_ap(struct ath6kl_vif *vif, struct sk_buff *skb, } if (conn->sta_flags & STA_PS_SLEEP) { - if (!(conn->sta_flags & STA_PS_POLLED)) { - /* Queue the frames if the STA is sleeping */ - spin_lock_bh(&conn->psq_lock); - is_psq_empty = skb_queue_empty(&conn->psq); - skb_queue_tail(&conn->psq, skb); - spin_unlock_bh(&conn->psq_lock); - - /* - * If this is the first pkt getting queued - * for this STA, update the PVB for this - * STA. - */ - if (is_psq_empty) - ath6kl_wmi_set_pvb_cmd(ar->wmi, - vif->fw_vif_idx, - conn->aid, 1); - - ps_queued = true; - } else { - /* - * This tx is because of a PsPoll. - * Determine if MoreData bit has to be set. - */ - spin_lock_bh(&conn->psq_lock); - if (!skb_queue_empty(&conn->psq)) - *more_data = true; - spin_unlock_bh(&conn->psq_lock); - } + ps_queued = ath6kl_process_uapsdq(conn, + vif, skb, flags); + if (!(*flags & WMI_DATA_HDR_FLAGS_UAPSD)) + ps_queued = ath6kl_process_psq(conn, + vif, skb, flags); } } - return ps_queued; } @@ -242,12 +326,13 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) u32 map_no = 0; u16 htc_tag = ATH6KL_DATA_PKT_TAG; u8 ac = 99 ; /* initialize to unmapped ac */ - bool chk_adhoc_ps_mapping = false, more_data = false; + bool chk_adhoc_ps_mapping = false; int ret; struct wmi_tx_meta_v2 meta_v2; void *meta; u8 csum_start = 0, csum_dest = 0, csum = skb->ip_summed; u8 meta_ver = 0; + u32 flags = 0; ath6kl_dbg(ATH6KL_DBG_WLAN_TX, "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__, @@ -264,7 +349,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) /* AP mode Power saving processing */ if (vif->nw_type == AP_NETWORK) { - if (ath6kl_powersave_ap(vif, skb, &more_data)) + if (ath6kl_powersave_ap(vif, skb, &flags)) return 0; } @@ -308,7 +393,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) } ret = ath6kl_wmi_data_hdr_add(ar->wmi, skb, - DATA_MSGTYPE, more_data, 0, + DATA_MSGTYPE, flags, 0, meta_ver, meta, vif->fw_vif_idx); @@ -1093,6 +1178,76 @@ static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid, return is_queued; } +static void ath6kl_uapsd_trigger_frame_rx(struct ath6kl_vif *vif, + struct ath6kl_sta *conn) +{ + struct ath6kl *ar = vif->ar; + bool is_apsdq_empty, is_apsdq_empty_at_start; + u32 num_frames_to_deliver, flags; + struct sk_buff *skb = NULL; + + /* + * If the APSD q for this STA is not empty, dequeue and + * send a pkt from the head of the q. Also update the + * More data bit in the WMI_DATA_HDR if there are + * more pkts for this STA in the APSD q. + * If there are no more pkts for this STA, + * update the APSD bitmap for this STA. + */ + + num_frames_to_deliver = (conn->apsd_info >> ATH6KL_APSD_NUM_OF_AC) & + ATH6KL_APSD_FRAME_MASK; + /* + * Number of frames to send in a service period is + * indicated by the station + * in the QOS_INFO of the association request + * If it is zero, send all frames + */ + if (!num_frames_to_deliver) + num_frames_to_deliver = ATH6KL_APSD_ALL_FRAME; + + spin_lock_bh(&conn->psq_lock); + is_apsdq_empty = skb_queue_empty(&conn->apsdq); + spin_unlock_bh(&conn->psq_lock); + is_apsdq_empty_at_start = is_apsdq_empty; + + while ((!is_apsdq_empty) && (num_frames_to_deliver)) { + + spin_lock_bh(&conn->psq_lock); + skb = skb_dequeue(&conn->apsdq); + is_apsdq_empty = skb_queue_empty(&conn->apsdq); + spin_unlock_bh(&conn->psq_lock); + + /* + * Set the STA flag to Trigger delivery, + * so that the frame will go out + */ + conn->sta_flags |= STA_PS_APSD_TRIGGER; + num_frames_to_deliver--; + + /* Last frame in the service period, set EOSP or queue empty */ + if ((is_apsdq_empty) || (!num_frames_to_deliver)) + conn->sta_flags |= STA_PS_APSD_EOSP; + + ath6kl_data_tx(skb, vif->ndev); + conn->sta_flags &= ~(STA_PS_APSD_TRIGGER); + conn->sta_flags &= ~(STA_PS_APSD_EOSP); + } + + if (is_apsdq_empty) { + if (is_apsdq_empty_at_start) + flags = WMI_AP_APSD_NO_DELIVERY_FRAMES; + else + flags = 0; + + ath6kl_wmi_set_apsd_bfrd_traf(ar->wmi, + vif->fw_vif_idx, + conn->aid, 0, flags); + } + + return; +} + void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) { struct ath6kl *ar = target->dev->ar; @@ -1104,6 +1259,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) int status = packet->status; enum htc_endpoint_id ept = packet->endpoint; bool is_amsdu, prev_ps, ps_state = false; + bool trig_state = false; struct ath6kl_sta *conn = NULL; struct sk_buff *skb1 = NULL; struct ethhdr *datap = NULL; @@ -1197,6 +1353,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) WMI_DATA_HDR_PS_MASK); offset = sizeof(struct wmi_data_hdr); + trig_state = !!(le16_to_cpu(dhdr->info3) & WMI_DATA_HDR_TRIG); switch (meta_type) { case 0: @@ -1235,18 +1392,36 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) else conn->sta_flags &= ~STA_PS_SLEEP; + /* Accept trigger only when the station is in sleep */ + if ((conn->sta_flags & STA_PS_SLEEP) && trig_state) + ath6kl_uapsd_trigger_frame_rx(vif, conn); + if (prev_ps ^ !!(conn->sta_flags & STA_PS_SLEEP)) { if (!(conn->sta_flags & STA_PS_SLEEP)) { struct sk_buff *skbuff = NULL; + bool is_apsdq_empty; spin_lock_bh(&conn->psq_lock); - while ((skbuff = skb_dequeue(&conn->psq)) - != NULL) { + while ((skbuff = skb_dequeue(&conn->psq))) { + spin_unlock_bh(&conn->psq_lock); + ath6kl_data_tx(skbuff, vif->ndev); + spin_lock_bh(&conn->psq_lock); + } + + is_apsdq_empty = skb_queue_empty(&conn->apsdq); + while ((skbuff = skb_dequeue(&conn->apsdq))) { spin_unlock_bh(&conn->psq_lock); ath6kl_data_tx(skbuff, vif->ndev); spin_lock_bh(&conn->psq_lock); } spin_unlock_bh(&conn->psq_lock); + + if (!is_apsdq_empty) + ath6kl_wmi_set_apsd_bfrd_traf( + ar->wmi, + vif->fw_vif_idx, + conn->aid, 0, 0); + /* Clear the PVB for this STA */ ath6kl_wmi_set_pvb_cmd(ar->wmi, vif->fw_vif_idx, conn->aid, 0); diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 08fbd9a9be4b..c2420f886ed8 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -180,7 +180,7 @@ static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb, } int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, - u8 msg_type, bool more_data, + u8 msg_type, u32 flags, enum wmi_data_hdr_data_type data_type, u8 meta_ver, void *tx_meta_info, u8 if_idx) { @@ -204,17 +204,19 @@ int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT; data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT; - if (more_data) - data_hdr->info |= - WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT; + if (flags & WMI_DATA_HDR_FLAGS_MORE) + data_hdr->info |= WMI_DATA_HDR_MORE; - data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); - data_hdr->info3 = cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); + if (flags & WMI_DATA_HDR_FLAGS_EOSP) + data_hdr->info3 |= cpu_to_le16(WMI_DATA_HDR_EOSP); + + data_hdr->info2 |= cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT); + data_hdr->info3 |= cpu_to_le16(if_idx & WMI_DATA_HDR_IF_IDX_MASK); return 0; } -static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) +u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) { struct iphdr *ip_hdr = (struct iphdr *) pkt; u8 ip_pri; @@ -236,6 +238,11 @@ static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri) return ip_pri; } +u8 ath6kl_wmi_get_traffic_class(u8 user_priority) +{ + return up_to_ac[user_priority & 0x7]; +} + int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, struct sk_buff *skb, u32 layer2_priority, bool wmm_enabled, @@ -786,12 +793,14 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, ev->u.ap_sta.keymgmt, le16_to_cpu(ev->u.ap_sta.cipher), ev->u.ap_sta.apsd_info); + ath6kl_connect_ap_mode_sta( vif, ev->u.ap_sta.aid, ev->u.ap_sta.mac_addr, ev->u.ap_sta.keymgmt, le16_to_cpu(ev->u.ap_sta.cipher), ev->u.ap_sta.auth, ev->assoc_req_len, - ev->assoc_info + ev->beacon_ie_len); + ev->assoc_info + ev->beacon_ie_len, + ev->u.ap_sta.apsd_info); } return 0; } @@ -2993,6 +3002,43 @@ int ath6kl_wmi_ap_set_mlme(struct wmi *wmip, u8 if_idx, u8 cmd, const u8 *mac, NO_SYNC_WMIFLAG); } +/* This command will be used to enable/disable AP uAPSD feature */ +int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable) +{ + struct wmi_ap_set_apsd_cmd *cmd; + struct sk_buff *skb; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_ap_set_apsd_cmd *)skb->data; + cmd->enable = enable; + + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, WMI_AP_SET_APSD_CMDID, + NO_SYNC_WMIFLAG); +} + +int ath6kl_wmi_set_apsd_bfrd_traf(struct wmi *wmi, u8 if_idx, + u16 aid, u16 bitmap, u32 flags) +{ + struct wmi_ap_apsd_buffered_traffic_cmd *cmd; + struct sk_buff *skb; + + skb = ath6kl_wmi_get_new_buf(sizeof(*cmd)); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_ap_apsd_buffered_traffic_cmd *)skb->data; + cmd->aid = cpu_to_le16(aid); + cmd->bitmap = cpu_to_le16(bitmap); + cmd->flags = cpu_to_le32(flags); + + return ath6kl_wmi_cmd_send(wmi, if_idx, skb, + WMI_AP_APSD_BUFFERED_TRAFFIC_CMDID, + NO_SYNC_WMIFLAG); +} + static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len, struct ath6kl_vif *vif) { diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index eae0e4e065c4..48e9d2641d69 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h @@ -149,8 +149,7 @@ enum wmi_msg_type { #define WMI_DATA_HDR_PS_MASK 0x1 #define WMI_DATA_HDR_PS_SHIFT 5 -#define WMI_DATA_HDR_MORE_MASK 0x1 -#define WMI_DATA_HDR_MORE_SHIFT 5 +#define WMI_DATA_HDR_MORE 0x20 enum wmi_data_hdr_data_type { WMI_DATA_HDR_DATA_TYPE_802_3 = 0, @@ -160,6 +159,13 @@ enum wmi_data_hdr_data_type { WMI_DATA_HDR_DATA_TYPE_ACL, }; +/* Bitmap of data header flags */ +enum wmi_data_hdr_flags { + WMI_DATA_HDR_FLAGS_MORE = 0x1, + WMI_DATA_HDR_FLAGS_EOSP = 0x2, + WMI_DATA_HDR_FLAGS_UAPSD = 0x4, +}; + #define WMI_DATA_HDR_DATA_TYPE_MASK 0x3 #define WMI_DATA_HDR_DATA_TYPE_SHIFT 6 @@ -173,8 +179,12 @@ enum wmi_data_hdr_data_type { #define WMI_DATA_HDR_META_MASK 0x7 #define WMI_DATA_HDR_META_SHIFT 13 +/* Macros for operating on WMI_DATA_HDR (info3) field */ #define WMI_DATA_HDR_IF_IDX_MASK 0xF +#define WMI_DATA_HDR_TRIG 0x10 +#define WMI_DATA_HDR_EOSP 0x10 + struct wmi_data_hdr { s8 rssi; @@ -203,7 +213,8 @@ struct wmi_data_hdr { /* * usage of info3, 16-bit: * b3:b0 - Interface index - * b15:b4 - Reserved + * b4 - uAPSD trigger in rx & EOSP in tx + * b15:b5 - Reserved */ __le16 info3; } __packed; @@ -2116,6 +2127,19 @@ struct wmi_rx_frame_format_cmd { } __packed; /* AP mode events */ +struct wmi_ap_set_apsd_cmd { + u8 enable; +} __packed; + +enum wmi_ap_apsd_buffered_traffic_flags { + WMI_AP_APSD_NO_DELIVERY_FRAMES = 0x1, +}; + +struct wmi_ap_apsd_buffered_traffic_cmd { + __le16 aid; + __le16 bitmap; + __le32 flags; +} __packed; /* WMI_PS_POLL_EVENT */ struct wmi_pspoll_event { @@ -2332,7 +2356,7 @@ enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi); void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id); int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb); int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb, - u8 msg_type, bool more_data, + u8 msg_type, u32 flags, enum wmi_data_hdr_data_type data_type, u8 meta_ver, void *tx_meta_info, u8 if_idx); @@ -2446,7 +2470,16 @@ int ath6kl_wmi_set_roam_mode_cmd(struct wmi *wmi, enum wmi_roam_mode mode); int ath6kl_wmi_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, bool mc_all_on); int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx, u8 *filter, bool add_filter); +/* AP mode uAPSD */ +int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable); + +int ath6kl_wmi_set_apsd_bfrd_traf(struct wmi *wmi, + u8 if_idx, u16 aid, + u16 bitmap, u32 flags); + +u8 ath6kl_wmi_get_traffic_class(u8 user_priority); +u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri); /* AP mode */ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, struct wmi_connect_cmd *p); -- GitLab From e80ec84d9352419a7c0482edfbf1b96eaa4c8b95 Mon Sep 17 00:00:00 2001 From: Raja Mani Date: Thu, 12 Jan 2012 15:01:48 +0530 Subject: [PATCH 00097/10698] ath6kl: Remove useless initialization in ath6kl_read_fwlogs() ath6kl_read_fwlogs() assigns the value zero to the variable 'ret' at the time of declaration. Later, return value of ath6kl_diag_read32() repalces the init value. Hence removing useless zero assignment. Signed-off-by: Raja Mani Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 53f97db4a7a7..0a6d6e2be6e9 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -255,7 +255,7 @@ int ath6kl_read_fwlogs(struct ath6kl *ar) struct ath6kl_dbglog_hdr debug_hdr; struct ath6kl_dbglog_buf debug_buf; u32 address, length, dropped, firstbuf, debug_hdr_addr; - int ret = 0, loop; + int ret, loop; u8 *buf; buf = kmalloc(ATH6KL_FWLOG_PAYLOAD_SIZE, GFP_KERNEL); -- GitLab From 6c303d3ab39f0dc69546f179c424ee1124f50906 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 22 Nov 2011 21:13:48 +0100 Subject: [PATCH 00098/10698] tracing: let trace_signal_generate() report more info, kill overflow_fail/lose_info __send_signal()->trace_signal_generate() doesn't report enough info. The users want to know was the signal actually delivered or not, and they also need the shared/private info. The patch moves trace_signal_generate() at the end of __send_signal() and adds the 2 additional arguments. This also allows us to kill trace_signal_overflow_fail/lose_info, we can simply add the appropriate TRACE_SIGNAL_ "result" codes. Reported-by: Seiji Aguchi Reviewed-by: Seiji Aguchi Acked-by: Steven Rostedt Signed-off-by: Oleg Nesterov --- include/trace/events/signal.h | 85 +++++++++-------------------------- kernel/signal.c | 22 +++++---- 2 files changed, 36 insertions(+), 71 deletions(-) diff --git a/include/trace/events/signal.h b/include/trace/events/signal.h index 17df43464df0..39a8a430d90f 100644 --- a/include/trace/events/signal.h +++ b/include/trace/events/signal.h @@ -23,11 +23,23 @@ } \ } while (0) +#ifndef TRACE_HEADER_MULTI_READ +enum { + TRACE_SIGNAL_DELIVERED, + TRACE_SIGNAL_IGNORED, + TRACE_SIGNAL_ALREADY_PENDING, + TRACE_SIGNAL_OVERFLOW_FAIL, + TRACE_SIGNAL_LOSE_INFO, +}; +#endif + /** * signal_generate - called when a signal is generated * @sig: signal number * @info: pointer to struct siginfo * @task: pointer to struct task_struct + * @group: shared or private + * @result: TRACE_SIGNAL_* * * Current process sends a 'sig' signal to 'task' process with * 'info' siginfo. If 'info' is SEND_SIG_NOINFO or SEND_SIG_PRIV, @@ -37,9 +49,10 @@ */ TRACE_EVENT(signal_generate, - TP_PROTO(int sig, struct siginfo *info, struct task_struct *task), + TP_PROTO(int sig, struct siginfo *info, struct task_struct *task, + int group, int result), - TP_ARGS(sig, info, task), + TP_ARGS(sig, info, task, group, result), TP_STRUCT__entry( __field( int, sig ) @@ -47,6 +60,8 @@ TRACE_EVENT(signal_generate, __field( int, code ) __array( char, comm, TASK_COMM_LEN ) __field( pid_t, pid ) + __field( int, group ) + __field( int, result ) ), TP_fast_assign( @@ -54,11 +69,14 @@ TRACE_EVENT(signal_generate, TP_STORE_SIGINFO(__entry, info); memcpy(__entry->comm, task->comm, TASK_COMM_LEN); __entry->pid = task->pid; + __entry->group = group; + __entry->result = result; ), - TP_printk("sig=%d errno=%d code=%d comm=%s pid=%d", + TP_printk("sig=%d errno=%d code=%d comm=%s pid=%d grp=%d res=%d", __entry->sig, __entry->errno, __entry->code, - __entry->comm, __entry->pid) + __entry->comm, __entry->pid, __entry->group, + __entry->result) ); /** @@ -101,65 +119,6 @@ TRACE_EVENT(signal_deliver, __entry->sa_handler, __entry->sa_flags) ); -DECLARE_EVENT_CLASS(signal_queue_overflow, - - TP_PROTO(int sig, int group, struct siginfo *info), - - TP_ARGS(sig, group, info), - - TP_STRUCT__entry( - __field( int, sig ) - __field( int, group ) - __field( int, errno ) - __field( int, code ) - ), - - TP_fast_assign( - __entry->sig = sig; - __entry->group = group; - TP_STORE_SIGINFO(__entry, info); - ), - - TP_printk("sig=%d group=%d errno=%d code=%d", - __entry->sig, __entry->group, __entry->errno, __entry->code) -); - -/** - * signal_overflow_fail - called when signal queue is overflow - * @sig: signal number - * @group: signal to process group or not (bool) - * @info: pointer to struct siginfo - * - * Kernel fails to generate 'sig' signal with 'info' siginfo, because - * siginfo queue is overflow, and the signal is dropped. - * 'group' is not 0 if the signal will be sent to a process group. - * 'sig' is always one of RT signals. - */ -DEFINE_EVENT(signal_queue_overflow, signal_overflow_fail, - - TP_PROTO(int sig, int group, struct siginfo *info), - - TP_ARGS(sig, group, info) -); - -/** - * signal_lose_info - called when siginfo is lost - * @sig: signal number - * @group: signal to process group or not (bool) - * @info: pointer to struct siginfo - * - * Kernel generates 'sig' signal but loses 'info' siginfo, because siginfo - * queue is overflow. - * 'group' is not 0 if the signal will be sent to a process group. - * 'sig' is always one of non-RT signals. - */ -DEFINE_EVENT(signal_queue_overflow, signal_lose_info, - - TP_PROTO(int sig, int group, struct siginfo *info), - - TP_ARGS(sig, group, info) -); - #endif /* _TRACE_SIGNAL_H */ /* This part must be outside protection */ diff --git a/kernel/signal.c b/kernel/signal.c index c73c4284160e..1bd9e86fda1f 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1054,13 +1054,13 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, struct sigpending *pending; struct sigqueue *q; int override_rlimit; - - trace_signal_generate(sig, info, t); + int ret = 0, result; assert_spin_locked(&t->sighand->siglock); + result = TRACE_SIGNAL_IGNORED; if (!prepare_signal(sig, t, from_ancestor_ns)) - return 0; + goto ret; pending = group ? &t->signal->shared_pending : &t->pending; /* @@ -1068,8 +1068,11 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, * exactly one non-rt signal, so that we can get more * detailed information about the cause of the signal. */ + result = TRACE_SIGNAL_ALREADY_PENDING; if (legacy_queue(pending, sig)) - return 0; + goto ret; + + result = TRACE_SIGNAL_DELIVERED; /* * fast-pathed signals for kernel-internal things like SIGSTOP * or SIGKILL. @@ -1127,14 +1130,15 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, * signal was rt and sent by user using something * other than kill(). */ - trace_signal_overflow_fail(sig, group, info); - return -EAGAIN; + result = TRACE_SIGNAL_OVERFLOW_FAIL; + ret = -EAGAIN; + goto ret; } else { /* * This is a silent loss of information. We still * send the signal, but the *info bits are lost. */ - trace_signal_lose_info(sig, group, info); + result = TRACE_SIGNAL_LOSE_INFO; } } @@ -1142,7 +1146,9 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t, signalfd_notify(t, sig); sigaddset(&pending->signal, sig); complete_signal(sig, t, group); - return 0; +ret: + trace_signal_generate(sig, info, t, group, result); + return ret; } static int send_signal(int sig, struct siginfo *info, struct task_struct *t, -- GitLab From 163566f60bfe6a8176650155e2d98649b0dfabf8 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 22 Nov 2011 21:37:41 +0100 Subject: [PATCH 00099/10698] tracing: send_sigqueue() needs trace_signal_generate() too Add trace_signal_generate() into send_sigqueue(). send_sigqueue() is very similar to __send_signal(), just it uses the preallocated info. It should do the same wrt tracing. Reported-by: Seiji Aguchi Reviewed-by: Seiji Aguchi Acked-by: Steven Rostedt Signed-off-by: Oleg Nesterov --- kernel/signal.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/signal.c b/kernel/signal.c index 1bd9e86fda1f..8511e39813c7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -1591,7 +1591,7 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) int sig = q->info.si_signo; struct sigpending *pending; unsigned long flags; - int ret; + int ret, result; BUG_ON(!(q->flags & SIGQUEUE_PREALLOC)); @@ -1600,6 +1600,7 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) goto ret; ret = 1; /* the signal is ignored */ + result = TRACE_SIGNAL_IGNORED; if (!prepare_signal(sig, t, 0)) goto out; @@ -1611,6 +1612,7 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) */ BUG_ON(q->info.si_code != SI_TIMER); q->info.si_overrun++; + result = TRACE_SIGNAL_ALREADY_PENDING; goto out; } q->info.si_overrun = 0; @@ -1620,7 +1622,9 @@ int send_sigqueue(struct sigqueue *q, struct task_struct *t, int group) list_add_tail(&q->list, &pending->list); sigaddset(&pending->signal, sig); complete_signal(sig, t, group); + result = TRACE_SIGNAL_DELIVERED; out: + trace_signal_generate(sig, &q->info, t, group, result); unlock_task_sighand(t, &flags); ret: return ret; -- GitLab From b85a088f15f2070b7180735a231012843a5ac96c Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 14 Jan 2012 21:44:49 +0300 Subject: [PATCH 00100/10698] crypto: sha512 - use standard ror64() Use standard ror64() instead of hand-written. There is no standard ror64, so create it. The difference is shift value being "unsigned int" instead of uint64_t (for which there is no reason). gcc starts to emit native ROR instructions which it doesn't do for some reason currently. This should make the code faster. Patch survives in-tree crypto test and ping flood with hmac(sha512) on. Signed-off-by: Alexey Dobriyan Signed-off-by: Herbert Xu --- crypto/sha512_generic.c | 13 ++++--------- include/linux/bitops.h | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c index 9ed9f60316e5..20df86f51406 100644 --- a/crypto/sha512_generic.c +++ b/crypto/sha512_generic.c @@ -33,11 +33,6 @@ static inline u64 Maj(u64 x, u64 y, u64 z) return (x & y) | (z & (x | y)); } -static inline u64 RORu64(u64 x, u64 y) -{ - return (x >> y) | (x << (64 - y)); -} - static const u64 sha512_K[80] = { 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, @@ -68,10 +63,10 @@ static const u64 sha512_K[80] = { 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, }; -#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) -#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) -#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) -#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) +#define e0(x) (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39)) +#define e1(x) (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41)) +#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7)) +#define s1(x) (ror64(x,19) ^ ror64(x,61) ^ (x >> 6)) static inline void LOAD_OP(int I, u64 *W, const u8 *input) { diff --git a/include/linux/bitops.h b/include/linux/bitops.h index 3c1063acb2ab..94300fe46cce 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -55,6 +55,26 @@ static inline unsigned long hweight_long(unsigned long w) return sizeof(w) == 4 ? hweight32(w) : hweight64(w); } +/** + * rol64 - rotate a 64-bit value left + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u64 rol64(__u64 word, unsigned int shift) +{ + return (word << shift) | (word >> (64 - shift)); +} + +/** + * ror64 - rotate a 64-bit value right + * @word: value to rotate + * @shift: bits to roll + */ +static inline __u64 ror64(__u64 word, unsigned int shift) +{ + return (word >> shift) | (word << (64 - shift)); +} + /** * rol32 - rotate a 32-bit value left * @word: value to rotate -- GitLab From 210762268466634ddbfaddb48fdf5181ce4b5f2d Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 27 Aug 2011 18:53:03 +0200 Subject: [PATCH 00101/10698] firewire: move fw_device reference counting from drivers to core fw_unit device drivers invariably need to talk to the fw_unit's parent (an fw_device) and grandparent (an fw_card). firewire-core already maintains an fw_card reference for the entire lifetime of an fw_device. Likewise, let firewire-core maintain an fw_device reference for the entire lifetime of an fw_unit so that fw_unit drivers don't have to. Signed-off-by: Stefan Richter --- drivers/firewire/core-device.c | 2 ++ drivers/firewire/core.h | 13 +++++++++++++ include/linux/firewire.h | 12 ------------ sound/firewire/isight.c | 4 +--- sound/firewire/speakers.c | 4 ---- 5 files changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index f3b890da1e87..4c6c7d8cdaf1 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -641,6 +641,7 @@ static void fw_unit_release(struct device *dev) { struct fw_unit *unit = fw_unit(dev); + fw_device_put(fw_parent_device(unit)); kfree(unit); } @@ -692,6 +693,7 @@ static void create_units(struct fw_device *device) if (device_register(&unit->device) < 0) goto skip_unit; + fw_device_get(device); continue; skip_unit: diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index b45be5767529..b5b34952cf16 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h @@ -1,6 +1,7 @@ #ifndef _FIREWIRE_CORE_H #define _FIREWIRE_CORE_H +#include #include #include #include @@ -141,6 +142,18 @@ extern struct rw_semaphore fw_device_rwsem; extern struct idr fw_device_idr; extern int fw_cdev_major; +static inline struct fw_device *fw_device_get(struct fw_device *device) +{ + get_device(&device->device); + + return device; +} + +static inline void fw_device_put(struct fw_device *device) +{ + put_device(&device->device); +} + struct fw_device *fw_device_get_by_devt(dev_t devt); int fw_device_set_broadcast_channel(struct device *dev, void *gen); void fw_node_event(struct fw_card *card, struct fw_node *node, int event); diff --git a/include/linux/firewire.h b/include/linux/firewire.h index 84ccf8e04fa6..6f1d7385e051 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -203,18 +203,6 @@ static inline int fw_device_is_shutdown(struct fw_device *device) return atomic_read(&device->state) == FW_DEVICE_SHUTDOWN; } -static inline struct fw_device *fw_device_get(struct fw_device *device) -{ - get_device(&device->device); - - return device; -} - -static inline void fw_device_put(struct fw_device *device) -{ - put_device(&device->device); -} - int fw_device_enable_phys_dma(struct fw_device *device); /* diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c index 440030818db7..412b65f740d9 100644 --- a/sound/firewire/isight.c +++ b/sound/firewire/isight.c @@ -612,7 +612,6 @@ static void isight_card_free(struct snd_card *card) fw_iso_resources_destroy(&isight->resources); fw_unit_put(isight->unit); - fw_device_put(isight->device); mutex_destroy(&isight->mutex); } @@ -645,7 +644,7 @@ static int isight_probe(struct device *unit_dev) isight->card = card; mutex_init(&isight->mutex); isight->unit = fw_unit_get(unit); - isight->device = fw_device_get(fw_dev); + isight->device = fw_dev; isight->audio_base = get_unit_base(unit); if (!isight->audio_base) { dev_err(&unit->device, "audio unit base not found\n"); @@ -682,7 +681,6 @@ static int isight_probe(struct device *unit_dev) err_unit: fw_unit_put(isight->unit); - fw_device_put(isight->device); mutex_destroy(&isight->mutex); error: snd_card_free(card); diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c index 3fc257da180c..18b9b5607f3c 100644 --- a/sound/firewire/speakers.c +++ b/sound/firewire/speakers.c @@ -656,12 +656,10 @@ static u32 fwspk_read_firmware_version(struct fw_unit *unit) static void fwspk_card_free(struct snd_card *card) { struct fwspk *fwspk = card->private_data; - struct fw_device *dev = fw_parent_device(fwspk->unit); amdtp_out_stream_destroy(&fwspk->stream); cmp_connection_destroy(&fwspk->connection); fw_unit_put(fwspk->unit); - fw_device_put(dev); mutex_destroy(&fwspk->mutex); } @@ -718,7 +716,6 @@ static int __devinit fwspk_probe(struct device *unit_dev) fwspk = card->private_data; fwspk->card = card; mutex_init(&fwspk->mutex); - fw_device_get(fw_dev); fwspk->unit = fw_unit_get(unit); fwspk->device_info = fwspk_detect(fw_dev); if (!fwspk->device_info) { @@ -767,7 +764,6 @@ static int __devinit fwspk_probe(struct device *unit_dev) cmp_connection_destroy(&fwspk->connection); err_unit: fw_unit_put(fwspk->unit); - fw_device_put(fw_dev); mutex_destroy(&fwspk->mutex); error: snd_card_free(card); -- GitLab From 64d2172019dcfe46508593c561c9906de95df567 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 20 Dec 2011 21:32:46 +0100 Subject: [PATCH 00102/10698] firewire: ohci: use dev_printk API All messages are uniformly prefixed by driver name and device name now. Signed-off-by: Stefan Richter --- drivers/firewire/ohci.c | 185 +++++++++++++++++++++++----------------- 1 file changed, 106 insertions(+), 79 deletions(-) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 6628feaa7622..68b3c1b635f6 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -345,7 +345,7 @@ MODULE_PARM_DESC(debug, "Verbose logging (default = 0" ", busReset events = " __stringify(OHCI_PARAM_DEBUG_BUSRESETS) ", or a combination, or all = -1)"); -static void log_irqs(u32 evt) +static void log_irqs(struct fw_ohci *ohci, u32 evt) { if (likely(!(param_debug & (OHCI_PARAM_DEBUG_IRQS | OHCI_PARAM_DEBUG_BUSRESETS)))) @@ -355,7 +355,8 @@ static void log_irqs(u32 evt) !(evt & OHCI1394_busReset)) return; - fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt, + dev_notice(ohci->card.device, + "IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt, evt & OHCI1394_selfIDComplete ? " selfID" : "", evt & OHCI1394_RQPkt ? " AR_req" : "", evt & OHCI1394_RSPkt ? " AR_resp" : "", @@ -394,24 +395,29 @@ static char _p(u32 *s, int shift) return port[*s >> shift & 3]; } -static void log_selfids(int node_id, int generation, int self_id_count, u32 *s) +static void log_selfids(struct fw_ohci *ohci, int generation, int self_id_count) { + u32 *s; + if (likely(!(param_debug & OHCI_PARAM_DEBUG_SELFIDS))) return; - fw_notify("%d selfIDs, generation %d, local node ID %04x\n", - self_id_count, generation, node_id); + dev_notice(ohci->card.device, + "%d selfIDs, generation %d, local node ID %04x\n", + self_id_count, generation, ohci->node_id); - for (; self_id_count--; ++s) + for (s = ohci->self_id_buffer; self_id_count--; ++s) if ((*s & 1 << 23) == 0) - fw_notify("selfID 0: %08x, phy %d [%c%c%c] " + dev_notice(ohci->card.device, + "selfID 0: %08x, phy %d [%c%c%c] " "%s gc=%d %s %s%s%s\n", *s, *s >> 24 & 63, _p(s, 6), _p(s, 4), _p(s, 2), speed[*s >> 14 & 3], *s >> 16 & 63, power[*s >> 8 & 7], *s >> 22 & 1 ? "L" : "", *s >> 11 & 1 ? "c" : "", *s & 2 ? "i" : ""); else - fw_notify("selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c]\n", + dev_notice(ohci->card.device, + "selfID n: %08x, phy %d [%c%c%c%c%c%c%c%c]\n", *s, *s >> 24 & 63, _p(s, 16), _p(s, 14), _p(s, 12), _p(s, 10), _p(s, 8), _p(s, 6), _p(s, 4), _p(s, 2)); @@ -447,7 +453,8 @@ static const char *tcodes[] = { [0xe] = "link internal", [0xf] = "-reserved-", }; -static void log_ar_at_event(char dir, int speed, u32 *header, int evt) +static void log_ar_at_event(struct fw_ohci *ohci, + char dir, int speed, u32 *header, int evt) { int tcode = header[0] >> 4 & 0xf; char specific[12]; @@ -459,8 +466,9 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt) evt = 0x1f; if (evt == OHCI1394_evt_bus_reset) { - fw_notify("A%c evt_bus_reset, generation %d\n", - dir, (header[2] >> 16) & 0xff); + dev_notice(ohci->card.device, + "A%c evt_bus_reset, generation %d\n", + dir, (header[2] >> 16) & 0xff); return; } @@ -479,36 +487,41 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt) switch (tcode) { case 0xa: - fw_notify("A%c %s, %s\n", dir, evts[evt], tcodes[tcode]); + dev_notice(ohci->card.device, + "A%c %s, %s\n", + dir, evts[evt], tcodes[tcode]); break; case 0xe: - fw_notify("A%c %s, PHY %08x %08x\n", - dir, evts[evt], header[1], header[2]); + dev_notice(ohci->card.device, + "A%c %s, PHY %08x %08x\n", + dir, evts[evt], header[1], header[2]); break; case 0x0: case 0x1: case 0x4: case 0x5: case 0x9: - fw_notify("A%c spd %x tl %02x, " - "%04x -> %04x, %s, " - "%s, %04x%08x%s\n", - dir, speed, header[0] >> 10 & 0x3f, - header[1] >> 16, header[0] >> 16, evts[evt], - tcodes[tcode], header[1] & 0xffff, header[2], specific); + dev_notice(ohci->card.device, + "A%c spd %x tl %02x, " + "%04x -> %04x, %s, " + "%s, %04x%08x%s\n", + dir, speed, header[0] >> 10 & 0x3f, + header[1] >> 16, header[0] >> 16, evts[evt], + tcodes[tcode], header[1] & 0xffff, header[2], specific); break; default: - fw_notify("A%c spd %x tl %02x, " - "%04x -> %04x, %s, " - "%s%s\n", - dir, speed, header[0] >> 10 & 0x3f, - header[1] >> 16, header[0] >> 16, evts[evt], - tcodes[tcode], specific); + dev_notice(ohci->card.device, + "A%c spd %x tl %02x, " + "%04x -> %04x, %s, " + "%s%s\n", + dir, speed, header[0] >> 10 & 0x3f, + header[1] >> 16, header[0] >> 16, evts[evt], + tcodes[tcode], specific); } } #else #define param_debug 0 -static inline void log_irqs(u32 evt) {} -static inline void log_selfids(int node_id, int generation, int self_id_count, u32 *s) {} -static inline void log_ar_at_event(char dir, int speed, u32 *header, int evt) {} +static inline void log_irqs(struct fw_ohci *ohci, u32 evt) {} +static inline void log_selfids(struct fw_ohci *ohci, int generation, int self_id_count) {} +static inline void log_ar_at_event(struct fw_ohci *ohci, char dir, int speed, u32 *header, int evt) {} #endif /* CONFIG_FIREWIRE_OHCI_DEBUG */ @@ -555,7 +568,7 @@ static int read_phy_reg(struct fw_ohci *ohci, int addr) if (i >= 3) msleep(1); } - fw_error("failed to read phy reg\n"); + dev_err(ohci->card.device, "failed to read phy reg\n"); return -EBUSY; } @@ -577,7 +590,7 @@ static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val) if (i >= 3) msleep(1); } - fw_error("failed to write phy reg\n"); + dev_err(ohci->card.device, "failed to write phy reg\n"); return -EBUSY; } @@ -676,11 +689,14 @@ static void ar_context_release(struct ar_context *ctx) static void ar_context_abort(struct ar_context *ctx, const char *error_msg) { - if (reg_read(ctx->ohci, CONTROL_CLEAR(ctx->regs)) & CONTEXT_RUN) { - reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); - flush_writes(ctx->ohci); + struct fw_ohci *ohci = ctx->ohci; - fw_error("AR error: %s; DMA stopped\n", error_msg); + if (reg_read(ohci, CONTROL_CLEAR(ctx->regs)) & CONTEXT_RUN) { + reg_write(ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); + flush_writes(ohci); + + dev_err(ohci->card.device, "AR error: %s; DMA stopped\n", + error_msg); } /* FIXME: restart? */ } @@ -850,7 +866,7 @@ static __le32 *handle_ar_packet(struct ar_context *ctx, __le32 *buffer) p.timestamp = status & 0xffff; p.generation = ohci->request_generation; - log_ar_at_event('R', p.speed, p.header, evt); + log_ar_at_event(ohci, 'R', p.speed, p.header, evt); /* * Several controllers, notably from NEC and VIA, forget to @@ -1222,21 +1238,22 @@ static void context_append(struct context *ctx, static void context_stop(struct context *ctx) { + struct fw_ohci *ohci = ctx->ohci; u32 reg; int i; - reg_write(ctx->ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); + reg_write(ohci, CONTROL_CLEAR(ctx->regs), CONTEXT_RUN); ctx->running = false; for (i = 0; i < 1000; i++) { - reg = reg_read(ctx->ohci, CONTROL_SET(ctx->regs)); + reg = reg_read(ohci, CONTROL_SET(ctx->regs)); if ((reg & CONTEXT_ACTIVE) == 0) return; if (i) udelay(10); } - fw_error("Error: DMA context still active (0x%08x)\n", reg); + dev_err(ohci->card.device, "DMA context still active (0x%08x)\n", reg); } struct driver_data { @@ -1416,7 +1433,7 @@ static int handle_at_packet(struct context *context, evt = le16_to_cpu(last->transfer_status) & 0x1f; packet->timestamp = le16_to_cpu(last->res_count); - log_ar_at_event('T', packet->speed, packet->header, evt); + log_ar_at_event(ohci, 'T', packet->speed, packet->header, evt); switch (evt) { case OHCI1394_evt_timeout: @@ -1545,7 +1562,7 @@ static void handle_local_lock(struct fw_ohci *ohci, goto out; } - fw_error("swap not done (CSR lock timeout)\n"); + dev_err(ohci->card.device, "swap not done (CSR lock timeout)\n"); fw_fill_response(&response, packet->header, RCODE_BUSY, NULL, 0); out: @@ -1621,11 +1638,13 @@ static void detect_dead_context(struct fw_ohci *ohci, ctl = reg_read(ohci, CONTROL_SET(regs)); if (ctl & CONTEXT_DEAD) { #ifdef CONFIG_FIREWIRE_OHCI_DEBUG - fw_error("DMA context %s has stopped, error code: %s\n", - name, evts[ctl & 0x1f]); + dev_err(ohci->card.device, + "DMA context %s has stopped, error code: %s\n", + name, evts[ctl & 0x1f]); #else - fw_error("DMA context %s has stopped, error code: %#x\n", - name, ctl & 0x1f); + dev_err(ohci->card.device, + "DMA context %s has stopped, error code: %#x\n", + name, ctl & 0x1f); #endif } } @@ -1777,7 +1796,8 @@ static int find_and_insert_self_id(struct fw_ohci *ohci, int self_id_count) reg = reg_read(ohci, OHCI1394_NodeID); if (!(reg & OHCI1394_NodeID_idValid)) { - fw_notify("node ID not valid, new bus reset in progress\n"); + dev_notice(ohci->card.device, + "node ID not valid, new bus reset in progress\n"); return -EBUSY; } self_id |= ((reg & 0x3f) << 24); /* phy ID */ @@ -1823,11 +1843,12 @@ static void bus_reset_work(struct work_struct *work) reg = reg_read(ohci, OHCI1394_NodeID); if (!(reg & OHCI1394_NodeID_idValid)) { - fw_notify("node ID not valid, new bus reset in progress\n"); + dev_notice(ohci->card.device, + "node ID not valid, new bus reset in progress\n"); return; } if ((reg & OHCI1394_NodeID_nodeNumber) == 63) { - fw_notify("malconfigured bus\n"); + dev_notice(ohci->card.device, "malconfigured bus\n"); return; } ohci->node_id = reg & (OHCI1394_NodeID_busNumber | @@ -1841,7 +1862,7 @@ static void bus_reset_work(struct work_struct *work) reg = reg_read(ohci, OHCI1394_SelfIDCount); if (reg & OHCI1394_SelfIDCount_selfIDError) { - fw_notify("inconsistent self IDs\n"); + dev_notice(ohci->card.device, "inconsistent self IDs\n"); return; } /* @@ -1853,7 +1874,7 @@ static void bus_reset_work(struct work_struct *work) self_id_count = (reg >> 3) & 0xff; if (self_id_count > 252) { - fw_notify("inconsistent self IDs\n"); + dev_notice(ohci->card.device, "inconsistent self IDs\n"); return; } @@ -1871,11 +1892,13 @@ static void bus_reset_work(struct work_struct *work) */ if (cond_le32_to_cpu(ohci->self_id_cpu[i]) == 0xffff008f) { - fw_notify("ignoring spurious self IDs\n"); + dev_notice(ohci->card.device, + "ignoring spurious self IDs\n"); self_id_count = j; break; } else { - fw_notify("inconsistent self IDs\n"); + dev_notice(ohci->card.device, + "inconsistent self IDs\n"); return; } } @@ -1886,13 +1909,14 @@ static void bus_reset_work(struct work_struct *work) if (ohci->quirks & QUIRK_TI_SLLZ059) { self_id_count = find_and_insert_self_id(ohci, self_id_count); if (self_id_count < 0) { - fw_notify("could not construct local self ID\n"); + dev_notice(ohci->card.device, + "could not construct local self ID\n"); return; } } if (self_id_count == 0) { - fw_notify("inconsistent self IDs\n"); + dev_notice(ohci->card.device, "inconsistent self IDs\n"); return; } rmb(); @@ -1913,8 +1937,8 @@ static void bus_reset_work(struct work_struct *work) new_generation = (reg_read(ohci, OHCI1394_SelfIDCount) >> 16) & 0xff; if (new_generation != generation) { - fw_notify("recursive bus reset detected, " - "discarding self ids\n"); + dev_notice(ohci->card.device, + "new bus reset, discarding self ids\n"); return; } @@ -1985,8 +2009,7 @@ static void bus_reset_work(struct work_struct *work) dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE, free_rom, free_rom_bus); - log_selfids(ohci->node_id, generation, - self_id_count, ohci->self_id_buffer); + log_selfids(ohci, generation, self_id_count); fw_core_handle_bus_reset(&ohci->card, ohci->node_id, generation, self_id_count, ohci->self_id_buffer, @@ -2011,7 +2034,7 @@ static irqreturn_t irq_handler(int irq, void *data) */ reg_write(ohci, OHCI1394_IntEventClear, event & ~(OHCI1394_busReset | OHCI1394_postedWriteErr)); - log_irqs(event); + log_irqs(ohci, event); if (event & OHCI1394_selfIDComplete) queue_work(fw_workqueue, &ohci->bus_reset_work); @@ -2053,8 +2076,8 @@ static irqreturn_t irq_handler(int irq, void *data) } if (unlikely(event & OHCI1394_regAccessFail)) - fw_error("Register access failure - " - "please notify linux1394-devel@lists.sf.net\n"); + dev_err(ohci->card.device, + "register access failure - please notify linux1394-devel@lists.sf.net\n"); if (unlikely(event & OHCI1394_postedWriteErr)) { reg_read(ohci, OHCI1394_PostedWriteAddressHi); @@ -2062,12 +2085,13 @@ static irqreturn_t irq_handler(int irq, void *data) reg_write(ohci, OHCI1394_IntEventClear, OHCI1394_postedWriteErr); if (printk_ratelimit()) - fw_error("PCI posted write error\n"); + dev_err(ohci->card.device, "PCI posted write error\n"); } if (unlikely(event & OHCI1394_cycleTooLong)) { if (printk_ratelimit()) - fw_notify("isochronous cycle too long\n"); + dev_notice(ohci->card.device, + "isochronous cycle too long\n"); reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_cycleMaster); } @@ -2080,7 +2104,8 @@ static irqreturn_t irq_handler(int irq, void *data) * them at least two cycles later. (FIXME?) */ if (printk_ratelimit()) - fw_notify("isochronous cycle inconsistent\n"); + dev_notice(ohci->card.device, + "isochronous cycle inconsistent\n"); } if (unlikely(event & OHCI1394_unrecoverableError)) @@ -2207,7 +2232,7 @@ static int ohci_enable(struct fw_card *card, int i, ret; if (software_reset(ohci)) { - fw_error("Failed to reset ohci card.\n"); + dev_err(card->device, "failed to reset ohci card\n"); return -EBUSY; } @@ -2231,7 +2256,7 @@ static int ohci_enable(struct fw_card *card, } if (!lps) { - fw_error("Failed to set Link Power Status\n"); + dev_err(card->device, "failed to set Link Power Status\n"); return -EIO; } @@ -2240,7 +2265,7 @@ static int ohci_enable(struct fw_card *card, if (ret < 0) return ret; if (ret) - fw_notify("local TSB41BA3D phy\n"); + dev_notice(card->device, "local TSB41BA3D phy\n"); else ohci->quirks &= ~QUIRK_TI_SLLZ059; } @@ -2340,7 +2365,8 @@ static int ohci_enable(struct fw_card *card, if (request_irq(dev->irq, irq_handler, pci_dev_msi_enabled(dev) ? 0 : IRQF_SHARED, ohci_driver_name, ohci)) { - fw_error("Failed to allocate interrupt %d.\n", dev->irq); + dev_err(card->device, "failed to allocate interrupt %d\n", + dev->irq); pci_disable_msi(dev); if (config_rom) { @@ -2505,7 +2531,7 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) dma_unmap_single(ohci->card.device, packet->payload_bus, packet->payload_length, DMA_TO_DEVICE); - log_ar_at_event('T', packet->speed, packet->header, 0x20); + log_ar_at_event(ohci, 'T', packet->speed, packet->header, 0x20); driver_data->packet = NULL; packet->ack = RCODE_CANCELLED; packet->callback(packet, &ohci->card, packet->ack); @@ -3459,7 +3485,7 @@ static int __devinit pci_probe(struct pci_dev *dev, err = pci_enable_device(dev); if (err) { - fw_error("Failed to enable OHCI hardware\n"); + dev_err(&dev->dev, "failed to enable OHCI hardware\n"); goto fail_free; } @@ -3474,13 +3500,13 @@ static int __devinit pci_probe(struct pci_dev *dev, err = pci_request_region(dev, 0, ohci_driver_name); if (err) { - fw_error("MMIO resource unavailable\n"); + dev_err(&dev->dev, "MMIO resource unavailable\n"); goto fail_disable; } ohci->registers = pci_iomap(dev, 0, OHCI1394_REGISTER_SIZE); if (ohci->registers == NULL) { - fw_error("Failed to remap registers\n"); + dev_err(&dev->dev, "failed to remap registers\n"); err = -ENXIO; goto fail_iomem; } @@ -3569,9 +3595,10 @@ static int __devinit pci_probe(struct pci_dev *dev, goto fail_contexts; version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; - fw_notify("Added fw-ohci device %s, OHCI v%x.%x, " + dev_notice(&dev->dev, + "added OHCI v%x.%x device as card %d, " "%d IR + %d IT contexts, quirks 0x%x\n", - dev_name(&dev->dev), version >> 16, version & 0xff, + version >> 16, version & 0xff, ohci->card.index, ohci->n_ir, ohci->n_it, ohci->quirks); return 0; @@ -3600,7 +3627,7 @@ static int __devinit pci_probe(struct pci_dev *dev, pmac_ohci_off(dev); fail: if (err == -ENOMEM) - fw_error("Out of memory\n"); + dev_err(&dev->dev, "out of memory\n"); return err; } @@ -3644,7 +3671,7 @@ static void pci_remove(struct pci_dev *dev) kfree(ohci); pmac_ohci_off(dev); - fw_notify("Removed fw-ohci device.\n"); + dev_notice(&dev->dev, "removed fw-ohci device\n"); } #ifdef CONFIG_PM @@ -3658,12 +3685,12 @@ static int pci_suspend(struct pci_dev *dev, pm_message_t state) pci_disable_msi(dev); err = pci_save_state(dev); if (err) { - fw_error("pci_save_state failed\n"); + dev_err(&dev->dev, "pci_save_state failed\n"); return err; } err = pci_set_power_state(dev, pci_choose_state(dev, state)); if (err) - fw_error("pci_set_power_state failed with %d\n", err); + dev_err(&dev->dev, "pci_set_power_state failed with %d\n", err); pmac_ohci_off(dev); return 0; @@ -3679,7 +3706,7 @@ static int pci_resume(struct pci_dev *dev) pci_restore_state(dev); err = pci_enable_device(dev); if (err) { - fw_error("pci_enable_device failed\n"); + dev_err(&dev->dev, "pci_enable_device failed\n"); return err; } -- GitLab From eba9ebaaa26d60e07bc0aea585c13bc1d5a728c1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Tue, 20 Dec 2011 21:34:12 +0100 Subject: [PATCH 00103/10698] firewire: sbp2: use dev_printk API All messages are uniformly prefixed by driver name and device name now. Signed-off-by: Stefan Richter --- drivers/firewire/sbp2.c | 93 ++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/drivers/firewire/sbp2.c b/drivers/firewire/sbp2.c index 68375bc3aef6..32b3296a1c51 100644 --- a/drivers/firewire/sbp2.c +++ b/drivers/firewire/sbp2.c @@ -165,7 +165,6 @@ static void sbp2_queue_work(struct sbp2_logical_unit *lu, unsigned long delay) */ struct sbp2_target { struct fw_unit *unit; - const char *bus_id; struct list_head lu_list; u64 management_agent_address; @@ -181,11 +180,21 @@ struct sbp2_target { int blocked; /* ditto */ }; -static struct fw_device *target_device(struct sbp2_target *tgt) +static struct fw_device *target_parent_device(struct sbp2_target *tgt) { return fw_parent_device(tgt->unit); } +static const struct device *tgt_dev(const struct sbp2_target *tgt) +{ + return &tgt->unit->device; +} + +static const struct device *lu_dev(const struct sbp2_logical_unit *lu) +{ + return &lu->tgt->unit->device; +} + /* Impossible login_id, to detect logout attempt before successful login */ #define INVALID_LOGIN_ID 0x10000 @@ -430,7 +439,8 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, memcpy(status.data, payload + 8, length - 8); if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) { - fw_notify("non-orb related status write, not handled\n"); + dev_notice(lu_dev(lu), + "non-ORB related status write, not handled\n"); fw_send_response(card, request, RCODE_COMPLETE); return; } @@ -451,7 +461,7 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, orb->callback(orb, &status); kref_put(&orb->kref, free_orb); /* orb callback reference */ } else { - fw_error("status write for unknown orb\n"); + dev_err(lu_dev(lu), "status write for unknown ORB\n"); } fw_send_response(card, request, RCODE_COMPLETE); @@ -492,7 +502,7 @@ static void complete_transaction(struct fw_card *card, int rcode, static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, int node_id, int generation, u64 offset) { - struct fw_device *device = target_device(lu->tgt); + struct fw_device *device = target_parent_device(lu->tgt); struct sbp2_pointer orb_pointer; unsigned long flags; @@ -513,7 +523,7 @@ static void sbp2_send_orb(struct sbp2_orb *orb, struct sbp2_logical_unit *lu, static int sbp2_cancel_orbs(struct sbp2_logical_unit *lu) { - struct fw_device *device = target_device(lu->tgt); + struct fw_device *device = target_parent_device(lu->tgt); struct sbp2_orb *orb, *next; struct list_head list; unsigned long flags; @@ -552,7 +562,7 @@ static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, int generation, int function, int lun_or_login_id, void *response) { - struct fw_device *device = target_device(lu->tgt); + struct fw_device *device = target_parent_device(lu->tgt); struct sbp2_management_orb *orb; unsigned int timeout; int retval = -ENOMEM; @@ -612,20 +622,20 @@ static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, retval = -EIO; if (sbp2_cancel_orbs(lu) == 0) { - fw_error("%s: orb reply timed out, rcode=0x%02x\n", - lu->tgt->bus_id, orb->base.rcode); + dev_err(lu_dev(lu), "ORB reply timed out, rcode 0x%02x\n", + orb->base.rcode); goto out; } if (orb->base.rcode != RCODE_COMPLETE) { - fw_error("%s: management write failed, rcode 0x%02x\n", - lu->tgt->bus_id, orb->base.rcode); + dev_err(lu_dev(lu), "management write failed, rcode 0x%02x\n", + orb->base.rcode); goto out; } if (STATUS_GET_RESPONSE(orb->status) != 0 || STATUS_GET_SBP_STATUS(orb->status) != 0) { - fw_error("%s: error status: %d:%d\n", lu->tgt->bus_id, + dev_err(lu_dev(lu), "error status: %d:%d\n", STATUS_GET_RESPONSE(orb->status), STATUS_GET_SBP_STATUS(orb->status)); goto out; @@ -648,7 +658,7 @@ static int sbp2_send_management_orb(struct sbp2_logical_unit *lu, int node_id, static void sbp2_agent_reset(struct sbp2_logical_unit *lu) { - struct fw_device *device = target_device(lu->tgt); + struct fw_device *device = target_parent_device(lu->tgt); __be32 d = 0; fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, @@ -665,7 +675,7 @@ static void complete_agent_reset_write_no_wait(struct fw_card *card, static void sbp2_agent_reset_no_wait(struct sbp2_logical_unit *lu) { - struct fw_device *device = target_device(lu->tgt); + struct fw_device *device = target_parent_device(lu->tgt); struct fw_transaction *t; static __be32 d; @@ -704,7 +714,7 @@ static inline void sbp2_allow_block(struct sbp2_logical_unit *lu) static void sbp2_conditionally_block(struct sbp2_logical_unit *lu) { struct sbp2_target *tgt = lu->tgt; - struct fw_card *card = target_device(tgt)->card; + struct fw_card *card = target_parent_device(tgt)->card; struct Scsi_Host *shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]); unsigned long flags; @@ -728,7 +738,7 @@ static void sbp2_conditionally_block(struct sbp2_logical_unit *lu) static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu) { struct sbp2_target *tgt = lu->tgt; - struct fw_card *card = target_device(tgt)->card; + struct fw_card *card = target_parent_device(tgt)->card; struct Scsi_Host *shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]); unsigned long flags; @@ -753,7 +763,7 @@ static void sbp2_conditionally_unblock(struct sbp2_logical_unit *lu) */ static void sbp2_unblock(struct sbp2_target *tgt) { - struct fw_card *card = target_device(tgt)->card; + struct fw_card *card = target_parent_device(tgt)->card; struct Scsi_Host *shost = container_of((void *)tgt, struct Scsi_Host, hostdata[0]); unsigned long flags; @@ -794,7 +804,7 @@ static int sbp2_lun2int(u16 lun) */ static void sbp2_set_busy_timeout(struct sbp2_logical_unit *lu) { - struct fw_device *device = target_device(lu->tgt); + struct fw_device *device = target_parent_device(lu->tgt); __be32 d = cpu_to_be32(SBP2_CYCLE_LIMIT | SBP2_RETRY_LIMIT); fw_run_transaction(device->card, TCODE_WRITE_QUADLET_REQUEST, @@ -809,7 +819,7 @@ static void sbp2_login(struct work_struct *work) struct sbp2_logical_unit *lu = container_of(work, struct sbp2_logical_unit, work.work); struct sbp2_target *tgt = lu->tgt; - struct fw_device *device = target_device(tgt); + struct fw_device *device = target_parent_device(tgt); struct Scsi_Host *shost; struct scsi_device *sdev; struct sbp2_login_response response; @@ -833,8 +843,8 @@ static void sbp2_login(struct work_struct *work) if (lu->retries++ < 5) { sbp2_queue_work(lu, DIV_ROUND_UP(HZ, 5)); } else { - fw_error("%s: failed to login to LUN %04x\n", - tgt->bus_id, lu->lun); + dev_err(tgt_dev(tgt), "failed to login to LUN %04x\n", + lu->lun); /* Let any waiting I/O fail from now on. */ sbp2_unblock(lu->tgt); } @@ -851,8 +861,8 @@ static void sbp2_login(struct work_struct *work) << 32) | be32_to_cpu(response.command_block_agent.low); lu->login_id = be32_to_cpu(response.misc) & 0xffff; - fw_notify("%s: logged in to LUN %04x (%d retries)\n", - tgt->bus_id, lu->lun, lu->retries); + dev_notice(tgt_dev(tgt), "logged in to LUN %04x (%d retries)\n", + lu->lun, lu->retries); /* set appropriate retry limit(s) in BUSY_TIMEOUT register */ sbp2_set_busy_timeout(lu); @@ -919,7 +929,7 @@ static void sbp2_reconnect(struct work_struct *work) struct sbp2_logical_unit *lu = container_of(work, struct sbp2_logical_unit, work.work); struct sbp2_target *tgt = lu->tgt; - struct fw_device *device = target_device(tgt); + struct fw_device *device = target_parent_device(tgt); int generation, node_id, local_node_id; if (fw_device_is_shutdown(device)) @@ -943,7 +953,7 @@ static void sbp2_reconnect(struct work_struct *work) smp_rmb(); /* get current card generation */ if (generation == device->card->generation || lu->retries++ >= 5) { - fw_error("%s: failed to reconnect\n", tgt->bus_id); + dev_err(tgt_dev(tgt), "failed to reconnect\n"); lu->retries = 0; PREPARE_DELAYED_WORK(&lu->work, sbp2_login); } @@ -957,8 +967,8 @@ static void sbp2_reconnect(struct work_struct *work) smp_wmb(); /* node IDs must not be older than generation */ lu->generation = generation; - fw_notify("%s: reconnected to LUN %04x (%d retries)\n", - tgt->bus_id, lu->lun, lu->retries); + dev_notice(tgt_dev(tgt), "reconnected to LUN %04x (%d retries)\n", + lu->lun, lu->retries); sbp2_agent_reset(lu); sbp2_cancel_orbs(lu); @@ -1068,8 +1078,8 @@ static void sbp2_clamp_management_orb_timeout(struct sbp2_target *tgt) unsigned int timeout = tgt->mgt_orb_timeout; if (timeout > 40000) - fw_notify("%s: %ds mgt_ORB_timeout limited to 40s\n", - tgt->bus_id, timeout / 1000); + dev_notice(tgt_dev(tgt), "%ds mgt_ORB_timeout limited to 40s\n", + timeout / 1000); tgt->mgt_orb_timeout = clamp_val(timeout, 5000, 40000); } @@ -1081,9 +1091,9 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model, unsigned int w = sbp2_param_workarounds; if (w) - fw_notify("Please notify linux1394-devel@lists.sourceforge.net " - "if you need the workarounds parameter for %s\n", - tgt->bus_id); + dev_notice(tgt_dev(tgt), + "Please notify linux1394-devel@lists.sf.net " + "if you need the workarounds parameter\n"); if (w & SBP2_WORKAROUND_OVERRIDE) goto out; @@ -1103,9 +1113,9 @@ static void sbp2_init_workarounds(struct sbp2_target *tgt, u32 model, } out: if (w) - fw_notify("Workarounds for %s: 0x%x " - "(firmware_revision 0x%06x, model_id 0x%06x)\n", - tgt->bus_id, w, firmware_revision, model); + dev_notice(tgt_dev(tgt), "workarounds 0x%x " + "(firmware_revision 0x%06x, model_id 0x%06x)\n", + w, firmware_revision, model); tgt->workarounds = w; } @@ -1133,7 +1143,6 @@ static int sbp2_probe(struct device *dev) dev_set_drvdata(&unit->device, tgt); tgt->unit = unit; INIT_LIST_HEAD(&tgt->lu_list); - tgt->bus_id = dev_name(&unit->device); tgt->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; if (fw_device_enable_phys_dma(device) < 0) @@ -1239,7 +1248,7 @@ static int sbp2_remove(struct device *dev) kfree(lu); } scsi_remove_host(shost); - fw_notify("released %s, target %d:0:0\n", tgt->bus_id, shost->host_no); + dev_notice(dev, "released target %d:0:0\n", shost->host_no); scsi_host_put(shost); return 0; @@ -1325,7 +1334,7 @@ static void complete_command_orb(struct sbp2_orb *base_orb, { struct sbp2_command_orb *orb = container_of(base_orb, struct sbp2_command_orb, base); - struct fw_device *device = target_device(orb->lu->tgt); + struct fw_device *device = target_parent_device(orb->lu->tgt); int result; if (status != NULL) { @@ -1433,7 +1442,7 @@ static int sbp2_scsi_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmd) { struct sbp2_logical_unit *lu = cmd->device->hostdata; - struct fw_device *device = target_device(lu->tgt); + struct fw_device *device = target_parent_device(lu->tgt); struct sbp2_command_orb *orb; int generation, retval = SCSI_MLQUEUE_HOST_BUSY; @@ -1442,7 +1451,7 @@ static int sbp2_scsi_queuecommand(struct Scsi_Host *shost, * transfer direction not handled. */ if (cmd->sc_data_direction == DMA_BIDIRECTIONAL) { - fw_error("Can't handle DMA_BIDIRECTIONAL, rejecting command\n"); + dev_err(lu_dev(lu), "cannot handle bidirectional command\n"); cmd->result = DID_ERROR << 16; cmd->scsi_done(cmd); return 0; @@ -1450,7 +1459,7 @@ static int sbp2_scsi_queuecommand(struct Scsi_Host *shost, orb = kzalloc(sizeof(*orb), GFP_ATOMIC); if (orb == NULL) { - fw_notify("failed to alloc orb\n"); + dev_notice(lu_dev(lu), "failed to alloc ORB\n"); return SCSI_MLQUEUE_HOST_BUSY; } @@ -1550,7 +1559,7 @@ static int sbp2_scsi_abort(struct scsi_cmnd *cmd) { struct sbp2_logical_unit *lu = cmd->device->hostdata; - fw_notify("%s: sbp2_scsi_abort\n", lu->tgt->bus_id); + dev_notice(lu_dev(lu), "sbp2_scsi_abort\n"); sbp2_agent_reset(lu); sbp2_cancel_orbs(lu); -- GitLab From 0b8ecdda1943a05c8e7896f0b5f1addf39269927 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 13 Sep 2011 14:11:09 -0400 Subject: [PATCH 00104/10698] drm/i915: Silence _DSM errors <@ajax> mjg59: how concerned should i be about [drm:intel_dsm_pci_probe] *ERROR* failed to get supported _DSM functions ? <@mjg59> ajax: Entirely unconcerned Signed-off-by: Adam Jackson Acked-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index cb912106d1a2..bae3edf956a4 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c @@ -208,7 +208,7 @@ static bool intel_dsm_pci_probe(struct pci_dev *pdev) ret = intel_dsm(dhandle, INTEL_DSM_FN_SUPPORTED_FUNCTIONS, 0); if (ret < 0) { - DRM_ERROR("failed to get supported _DSM functions\n"); + DRM_DEBUG_KMS("failed to get supported _DSM functions\n"); return false; } -- GitLab From cec2f356d59d9e070413e5966a3c5a1af136d948 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Tue, 10 Jan 2012 15:09:36 -0800 Subject: [PATCH 00105/10698] drm/i915: Only look for matching clocks for LVDS downclock This patch enforces that the downclock clock source is the same as the preferred clock source for LVDS. This fixes a bug where the driver chooses a downclock clock source with a different P than the preferred mode clock source. This happened even if the preferred clock source implemented an acceptable rate for the downclock. The result of this bug is that downclock is disabled. Signed-off-by: Sean Paul Reviewed-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 74 +++++++++++++++------------- 1 file changed, 41 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 29743dee54c2..15f2b52ea704 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -75,7 +75,7 @@ struct intel_limit { intel_range_t dot, vco, n, m, m1, m2, p, p1; intel_p2_t p2; bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, - int, int, intel_clock_t *); + int, int, intel_clock_t *, intel_clock_t *); }; /* FDI */ @@ -83,17 +83,21 @@ struct intel_limit { static bool intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); + int target, int refclk, intel_clock_t *match_clock, + intel_clock_t *best_clock); static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); + int target, int refclk, intel_clock_t *match_clock, + intel_clock_t *best_clock); static bool intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); + int target, int refclk, intel_clock_t *match_clock, + intel_clock_t *best_clock); static bool intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock); + int target, int refclk, intel_clock_t *match_clock, + intel_clock_t *best_clock); static inline u32 /* units of 100MHz */ intel_fdi_link_freq(struct drm_device *dev) @@ -515,7 +519,8 @@ static bool intel_PLL_is_valid(struct drm_device *dev, static bool intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) + int target, int refclk, intel_clock_t *match_clock, + intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; @@ -562,6 +567,9 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, if (!intel_PLL_is_valid(dev, limit, &clock)) continue; + if (match_clock && + clock.p != match_clock->p) + continue; this_err = abs(clock.dot - target); if (this_err < err) { @@ -578,7 +586,8 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, static bool intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) + int target, int refclk, intel_clock_t *match_clock, + intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; @@ -625,6 +634,9 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, if (!intel_PLL_is_valid(dev, limit, &clock)) continue; + if (match_clock && + clock.p != match_clock->p) + continue; this_err = abs(clock.dot - target); if (this_err < err_most) { @@ -642,7 +654,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, static bool intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) + int target, int refclk, intel_clock_t *match_clock, + intel_clock_t *best_clock) { struct drm_device *dev = crtc->dev; intel_clock_t clock; @@ -668,7 +681,8 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, /* DisplayPort has only two frequencies, 162MHz and 270MHz */ static bool intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, - int target, int refclk, intel_clock_t *best_clock) + int target, int refclk, intel_clock_t *match_clock, + intel_clock_t *best_clock) { intel_clock_t clock; if (target < 200000) { @@ -5038,7 +5052,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. */ limit = intel_limit(crtc, refclk); - ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); + ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL, + &clock); if (!ok) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); return -EINVAL; @@ -5048,21 +5063,17 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, intel_crtc_update_cursor(crtc, true); if (is_lvds && dev_priv->lvds_downclock_avail) { + /* + * Ensure we match the reduced clock's P to the target clock. + * If the clocks don't match, we can't switch the display clock + * by using the FP0/FP1. In such case we will disable the LVDS + * downclock feature. + */ has_reduced_clock = limit->find_pll(limit, crtc, dev_priv->lvds_downclock, refclk, + &clock, &reduced_clock); - if (has_reduced_clock && (clock.p != reduced_clock.p)) { - /* - * If the different P is found, it means that we can't - * switch the display clock by using the FP0/FP1. - * In such case we will disable the LVDS downclock - * feature. - */ - DRM_DEBUG_KMS("Different P is found for " - "LVDS clock/downclock\n"); - has_reduced_clock = 0; - } } /* SDVO TV has fixed PLL values depend on its clock range, this mirrors vbios setting. */ @@ -5583,7 +5594,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. */ limit = intel_limit(crtc, refclk); - ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); + ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL, + &clock); if (!ok) { DRM_ERROR("Couldn't find PLL settings for mode!\n"); return -EINVAL; @@ -5593,21 +5605,17 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, intel_crtc_update_cursor(crtc, true); if (is_lvds && dev_priv->lvds_downclock_avail) { + /* + * Ensure we match the reduced clock's P to the target clock. + * If the clocks don't match, we can't switch the display clock + * by using the FP0/FP1. In such case we will disable the LVDS + * downclock feature. + */ has_reduced_clock = limit->find_pll(limit, crtc, dev_priv->lvds_downclock, refclk, + &clock, &reduced_clock); - if (has_reduced_clock && (clock.p != reduced_clock.p)) { - /* - * If the different P is found, it means that we can't - * switch the display clock by using the FP0/FP1. - * In such case we will disable the LVDS downclock - * feature. - */ - DRM_DEBUG_KMS("Different P is found for " - "LVDS clock/downclock\n"); - has_reduced_clock = 0; - } } /* SDVO TV has fixed PLL values depend on its clock range, this mirrors vbios setting. */ -- GitLab From 5a117db77e47e3946d1aaa7ce8deafafd9d76746 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Thu, 5 Jan 2012 09:34:29 -0200 Subject: [PATCH 00106/10698] drm/i915: there is no pipe CxSR on ironlake After checking the specs and discussing with Jesse, turns out CxSR is not available on Ironlake and gen5, and its advertisement on the device description is misleading. Acked-by: Jesse Barnes Signed-off-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8f7187915b0d..057c27225944 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -198,7 +198,7 @@ static const struct intel_device_info intel_pineview_info = { static const struct intel_device_info intel_ironlake_d_info = { .gen = 5, - .need_gfx_hws = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, + .need_gfx_hws = 1, .has_hotplug = 1, .has_bsd_ring = 1, }; -- GitLab From 6b2d590540d219064a53638f485b75203131dfce Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Wed, 4 Jan 2012 14:04:33 -0800 Subject: [PATCH 00107/10698] agp/intel: Add pci id for hostbridge from has/qemu This is needed to run the simulator. Cc: Jesse Barnes Signed-off-by: Ben Widawsky [danvet: added a comment in case people wonder what it's for.] Signed-off-by: Daniel Vetter --- drivers/char/agp/intel-agp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index b427711be4be..962e75dc4781 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -850,6 +850,7 @@ static struct pci_device_id agp_intel_pci_table[] = { .subvendor = PCI_ANY_ID, \ .subdevice = PCI_ANY_ID, \ } + ID(PCI_DEVICE_ID_INTEL_82441), /* for HAS2 support */ ID(PCI_DEVICE_ID_INTEL_82443LX_0), ID(PCI_DEVICE_ID_INTEL_82443BX_0), ID(PCI_DEVICE_ID_INTEL_82443GX_0), -- GitLab From c65d77d83ccffc60f8729b2e7806cac2564ee1b1 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 15 Dec 2011 12:30:36 -0800 Subject: [PATCH 00108/10698] drm/i915: split 9xx refclk & sdvo tv code out Makes the mode set routine a little cleaner and easier to extend. Signed-off-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 74 +++++++++++++++++----------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 15f2b52ea704..b050a7785167 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4982,6 +4982,48 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, return display_bpc != bpc; } +static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + int refclk; + + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && + intel_panel_use_ssc(dev_priv) && num_connectors < 2) { + refclk = dev_priv->lvds_ssc_freq * 1000; + DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", + refclk / 1000); + } else if (!IS_GEN2(dev)) { + refclk = 96000; + } else { + refclk = 48000; + } + + return refclk; +} + +static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode, + intel_clock_t *clock) +{ + /* SDVO TV has fixed PLL values depend on its clock range, + this mirrors vbios setting. */ + if (adjusted_mode->clock >= 100000 + && adjusted_mode->clock < 140500) { + clock->p1 = 2; + clock->p2 = 10; + clock->n = 3; + clock->m1 = 16; + clock->m2 = 8; + } else if (adjusted_mode->clock >= 140500 + && adjusted_mode->clock <= 200000) { + clock->p1 = 1; + clock->p2 = 10; + clock->n = 6; + clock->m1 = 12; + clock->m2 = 8; + } +} + static int i9xx_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -5036,15 +5078,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, num_connectors++; } - if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { - refclk = dev_priv->lvds_ssc_freq * 1000; - DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", - refclk / 1000); - } else if (!IS_GEN2(dev)) { - refclk = 96000; - } else { - refclk = 48000; - } + refclk = i9xx_get_refclk(crtc, num_connectors); /* * Returns a set of divisors for the desired target clock with the given @@ -5075,25 +5109,9 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, &clock, &reduced_clock); } - /* SDVO TV has fixed PLL values depend on its clock range, - this mirrors vbios setting. */ - if (is_sdvo && is_tv) { - if (adjusted_mode->clock >= 100000 - && adjusted_mode->clock < 140500) { - clock.p1 = 2; - clock.p2 = 10; - clock.n = 3; - clock.m1 = 16; - clock.m2 = 8; - } else if (adjusted_mode->clock >= 140500 - && adjusted_mode->clock <= 200000) { - clock.p1 = 1; - clock.p2 = 10; - clock.n = 6; - clock.m1 = 12; - clock.m2 = 8; - } - } + + if (is_sdvo && is_tv) + i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock); if (IS_PINEVIEW(dev)) { fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; -- GitLab From a7516a05311d0e2deb8ce8ae8b8c12a513ca8ca2 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 15 Dec 2011 12:30:37 -0800 Subject: [PATCH 00109/10698] drm/i915: split out pll divider code This cleans up the mode set path a little further, making it easier to extend for future platforms. Signed-off-by: Jesse Barnes [danvet: shut up stupid gcc warning about potential use of un-initlized fp2] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 62 ++++++++++++++++++---------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index b050a7785167..f3e706c2bd31 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5024,6 +5024,40 @@ static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode, } } +static void i9xx_update_pll_dividers(struct drm_crtc *crtc, + intel_clock_t *clock, + intel_clock_t *reduced_clock) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + u32 fp, fp2 = 0; + + if (IS_PINEVIEW(dev)) { + fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2; + if (reduced_clock) + fp2 = (1 << reduced_clock->n) << 16 | + reduced_clock->m1 << 8 | reduced_clock->m2; + } else { + fp = clock->n << 16 | clock->m1 << 8 | clock->m2; + if (reduced_clock) + fp2 = reduced_clock->n << 16 | reduced_clock->m1 << 8 | + reduced_clock->m2; + } + + I915_WRITE(FP0(pipe), fp); + + intel_crtc->lowfreq_avail = false; + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && + reduced_clock && i915_powersave) { + I915_WRITE(FP1(pipe), fp2); + intel_crtc->lowfreq_avail = true; + } else { + I915_WRITE(FP1(pipe), fp); + } +} + static int i9xx_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode, @@ -5037,7 +5071,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, int plane = intel_crtc->plane; int refclk, num_connectors = 0; intel_clock_t clock, reduced_clock; - u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; + u32 dpll, dspcntr, pipeconf; bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false; bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; struct drm_mode_config *mode_config = &dev->mode_config; @@ -5113,17 +5147,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, if (is_sdvo && is_tv) i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock); - if (IS_PINEVIEW(dev)) { - fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; - if (has_reduced_clock) - fp2 = (1 << reduced_clock.n) << 16 | - reduced_clock.m1 << 8 | reduced_clock.m2; - } else { - fp = clock.n << 16 | clock.m1 << 8 | clock.m2; - if (has_reduced_clock) - fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | - reduced_clock.m2; - } + i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ? + &reduced_clock : NULL); dpll = DPLL_VGA_MODE_DIS; @@ -5233,7 +5258,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); drm_mode_debug_printmodeline(mode); - I915_WRITE(FP0(pipe), fp); I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); POSTING_READ(DPLL(pipe)); @@ -5320,17 +5344,11 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, I915_WRITE(DPLL(pipe), dpll); } - intel_crtc->lowfreq_avail = false; - if (is_lvds && has_reduced_clock && i915_powersave) { - I915_WRITE(FP1(pipe), fp2); - intel_crtc->lowfreq_avail = true; - if (HAS_PIPE_CXSR(dev)) { + if (HAS_PIPE_CXSR(dev)) { + if (intel_crtc->lowfreq_avail) { DRM_DEBUG_KMS("enabling CxSR downclocking\n"); pipeconf |= PIPECONF_CXSR_DOWNCLOCK; - } - } else { - I915_WRITE(FP1(pipe), fp); - if (HAS_PIPE_CXSR(dev)) { + } else { DRM_DEBUG_KMS("disabling CxSR downclocking\n"); pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; } -- GitLab From f3953dcb98bad1c3badf451bcf41bf83ae2ce542 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Mon, 28 Nov 2011 16:15:17 -0200 Subject: [PATCH 00110/10698] drm/i915: fix typo in function name Fix function name in comments, a left-over from when i965_reset was renamed to i915_reset. Signed-off-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 057c27225944..7578c08110f7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -603,7 +603,7 @@ static int gen6_do_reset(struct drm_device *dev, u8 flags) } /** - * i965_reset - reset chip after a hang + * i915_reset - reset chip after a hang * @dev: drm device to reset * @flags: reset domains * -- GitLab From 931872fceabacf2d4f8b6fbd51611c167e83164c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 16 Jan 2012 23:01:13 +0000 Subject: [PATCH 00111/10698] drm/i915: Check that plane/pipe is disabled before removing the fb Staring at an error state such as: PGTBL_ER: 0x00000400 Display B: Invalid tiling fence[0] = 05001001 valid, x-tiled, pitch: 512, start: 0x05000000, size: 1048576 Pinned [2]: 00000000 131072 0001 0001 00000000 P uncached 00020000 4096000 0041 0000 00000000 P uncached (name: 1) Plane [1]: CNTR: c0000000 # enabled | gamma STRIDE: 00001400 SIZE: 03ff04ff POS: 00000000 ADDR: 05000000 Suggests that we did not clear the DSPBCNTR prior to unpinning the framebuffer and reusing the GTT space. Impossible! Unless our DPMS bookkeeping ran afoul again... In the meantime add an assertion that the plane is decoupled from the framebuffer prior to release. Signed-off-by: Chris Wilson Acked-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f3e706c2bd31..5fa1476cbfc6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -944,19 +944,24 @@ void assert_pipe(struct drm_i915_private *dev_priv, pipe_name(pipe), state_string(state), state_string(cur_state)); } -static void assert_plane_enabled(struct drm_i915_private *dev_priv, - enum plane plane) +static void assert_plane(struct drm_i915_private *dev_priv, + enum plane plane, bool state) { int reg; u32 val; + bool cur_state; reg = DSPCNTR(plane); val = I915_READ(reg); - WARN(!(val & DISPLAY_PLANE_ENABLE), - "plane %c assertion failure, should be active but is disabled\n", - plane_name(plane)); + cur_state = !!(val & DISPLAY_PLANE_ENABLE); + WARN(cur_state != state, + "plane %c assertion failure (expected %s, current %s)\n", + plane_name(plane), state_string(state), state_string(cur_state)); } +#define assert_plane_enabled(d, p) assert_plane(d, p, true) +#define assert_plane_disabled(d, p) assert_plane(d, p, false) + static void assert_planes_disabled(struct drm_i915_private *dev_priv, enum pipe pipe) { @@ -3335,6 +3340,8 @@ static void intel_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); + assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); + assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); if (crtc->fb) { mutex_lock(&dev->struct_mutex); -- GitLab From 2aded1b6bb83cabe3ee5763e5c3834e36bf4a61f Mon Sep 17 00:00:00 2001 From: Simon Que Date: Thu, 10 Nov 2011 17:50:26 -0800 Subject: [PATCH 00112/10698] drivers: i915: Fix BLC PWM register setup There is an error in i915_read_blc_pwm_ctl, where the register values are not being copied correctly. BLC_PWM_CTL and BLC_PWM_CTL2 are getting mixed up. This patch fixes that so that saveBLC_PWM_CTL2 and not saveBLC_PWM_CTL is copied to the BLC_PWM_CTL2 register. Signed-off-by: Simon Que Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_panel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 04d79fd1dc9d..c935cdaa2154 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -141,8 +141,8 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv) dev_priv->saveBLC_PWM_CTL2 = val; } else if (val == 0) { I915_WRITE(BLC_PWM_PCH_CTL2, - dev_priv->saveBLC_PWM_CTL); - val = dev_priv->saveBLC_PWM_CTL; + dev_priv->saveBLC_PWM_CTL2); + val = dev_priv->saveBLC_PWM_CTL2; } } else { val = I915_READ(BLC_PWM_CTL); -- GitLab From 28c057945ef5d164925db4fccc64207ee58c8681 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 7 Oct 2011 14:38:42 -0400 Subject: [PATCH 00113/10698] drm/i915: Implement plane-disabled assertion for PCH too Signed-off-by: Adam Jackson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 5fa1476cbfc6..d775f954c1b6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -970,8 +970,14 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv, int cur_pipe; /* Planes are fixed to pipes on ILK+ */ - if (HAS_PCH_SPLIT(dev_priv->dev)) + if (HAS_PCH_SPLIT(dev_priv->dev)) { + reg = DSPCNTR(pipe); + val = I915_READ(reg); + WARN((val & DISPLAY_PLANE_ENABLE), + "plane %c assertion failure, should be disabled but not\n", + plane_name(pipe)); return; + } /* Need to check both planes against the pipe */ for (i = 0; i < 2; i++) { -- GitLab From 23c99e775d14f01ba45a5affd2fb51af4328359c Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 7 Oct 2011 14:38:43 -0400 Subject: [PATCH 00114/10698] drm/i915: Fix assert_pch_hdmi_disabled to mention HDMI (not DP) Signed-off-by: Adam Jackson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d775f954c1b6..3e21f3cb7879 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1096,7 +1096,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, { u32 val = I915_READ(reg); WARN(hdmi_pipe_enabled(dev_priv, val, pipe), - "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", + "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); } -- GitLab From 1f182b27d50ae9f5efeb28be5b65302c8a81e711 Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Fri, 7 Oct 2011 14:38:46 -0400 Subject: [PATCH 00115/10698] drm/i915: Remove a comment about PCH from the non-PCH path Signed-off-by: Adam Jackson Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_display.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3e21f3cb7879..ebe71eda9546 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5235,8 +5235,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, /* Set up the display plane register */ dspcntr = DISPPLANE_GAMMA_ENABLE; - /* Ironlake's plane is forced to pipe, bit 24 is to - enable color space conversion */ if (pipe == 0) dspcntr &= ~DISPPLANE_SEL_PIPE_MASK; else -- GitLab From 78da107a7ed14fbc6ef77ff4c41d92b11edc9036 Mon Sep 17 00:00:00 2001 From: "Shimoda, Yoshihiro" Date: Tue, 17 Jan 2012 17:49:38 +0900 Subject: [PATCH 00116/10698] sh: fix the sh_mmcif_plat_data in board-sh7757lcr The board has an eMMC chip, so we cannot remove the chip. In this case, we have to set the MMC_CAP_NONREMOVABLE to the caps parameter. Reported-by: Guennadi Liakhovetski Signed-off-by: Yoshihiro Shimoda Signed-off-by: Paul Mundt --- arch/sh/boards/board-sh7757lcr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c index 0838154dd216..33dc5b6e8e17 100644 --- a/arch/sh/boards/board-sh7757lcr.c +++ b/arch/sh/boards/board-sh7757lcr.c @@ -222,7 +222,8 @@ static struct sh_mmcif_dma sh7757lcr_mmcif_dma = { static struct sh_mmcif_plat_data sh_mmcif_plat = { .dma = &sh7757lcr_mmcif_dma, .sup_pclk = 0x0f, - .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, + .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | + MMC_CAP_NONREMOVABLE, .ocr = MMC_VDD_32_33 | MMC_VDD_33_34, }; -- GitLab From 6919132e7a307b1f181d7655b3ef64cc7581a5ef Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 26 Jul 2011 15:39:44 -0400 Subject: [PATCH 00117/10698] drm/i915/dp: Tweak auxch clock divider for PCH Matches the advice in the Sandybridge documentation. Signed-off-by: Adam Jackson Acked-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index db3b461ad412..add871911a63 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -378,7 +378,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, else aux_clock_divider = 225; /* eDP input clock at 450Mhz */ } else if (HAS_PCH_SPLIT(dev)) - aux_clock_divider = 62; /* IRL input clock fixed at 125Mhz */ + aux_clock_divider = 63; /* IRL input clock fixed at 125Mhz */ else aux_clock_divider = intel_hrawclk(dev) / 2; -- GitLab From 092945e11c5b84f66dd08f0b87fb729715d377bc Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 26 Jul 2011 15:39:45 -0400 Subject: [PATCH 00118/10698] drm/i915/dp: Use auxch precharge value of 5 everywhere The default in the Sandybridge docs is 5, as on Ironlake, and I have no reason to believe 3 would work any better. Signed-off-by: Adam Jackson Acked-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index add871911a63..2f4766385797 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -362,7 +362,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, int recv_bytes; uint32_t status; uint32_t aux_clock_divider; - int try, precharge; + int try, precharge = 5; intel_dp_check_edp(intel_dp); /* The clock divider is based off the hrawclk, @@ -382,11 +382,6 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, else aux_clock_divider = intel_hrawclk(dev) / 2; - if (IS_GEN6(dev)) - precharge = 3; - else - precharge = 5; - /* Try to wait for any previous AUX channel activity */ for (try = 0; try < 3; try++) { status = I915_READ(ch_ctl); -- GitLab From d7e96feab83d29e27d14c60f1fa7c716ef7880cd Mon Sep 17 00:00:00 2001 From: Adam Jackson Date: Tue, 26 Jul 2011 15:39:46 -0400 Subject: [PATCH 00119/10698] drm/i915/dp: Check for AUXCH error before checking for success This is paranoid, but I am entirely willing to believe the hardware could come up with a condition where I get a status with both the 'done' and 'receive error' bits set. Signed-off-by: Adam Jackson Acked-by: Jesse Barnes Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_dp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 2f4766385797..8f1148c04108 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -426,6 +426,10 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, DP_AUX_CH_CTL_DONE | DP_AUX_CH_CTL_TIME_OUT_ERROR | DP_AUX_CH_CTL_RECEIVE_ERROR); + + if (status & (DP_AUX_CH_CTL_TIME_OUT_ERROR | + DP_AUX_CH_CTL_RECEIVE_ERROR)) + continue; if (status & DP_AUX_CH_CTL_DONE) break; } -- GitLab From 493dea2876df144ec57a6a9efbe55db43c7a729e Mon Sep 17 00:00:00 2001 From: Thomas Meyer Date: Tue, 29 Nov 2011 22:08:00 +0100 Subject: [PATCH 00120/10698] drm/i915: Use kcalloc instead of kzalloc to allocate array The advantage of kcalloc is, that will prevent integer overflows which could result from the multiplication of number of elements and size and it is also a bit nicer to read. The semantic patch that makes this change is available in https://lkml.org/lkml/2011/11/25/107 Signed-off-by: Thomas Meyer Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/intel_bios.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 63880e2e5cfd..50656339d922 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -572,7 +572,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv, DRM_DEBUG_KMS("no child dev is parsed from VBT\n"); return; } - dev_priv->child_dev = kzalloc(sizeof(*p_child) * count, GFP_KERNEL); + dev_priv->child_dev = kcalloc(count, sizeof(*p_child), GFP_KERNEL); if (!dev_priv->child_dev) { DRM_DEBUG_KMS("No memory space for child device\n"); return; -- GitLab From b2c606fe1defd1fb79612b48b528b2568c97def7 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 17 Jan 2012 12:50:12 +0100 Subject: [PATCH 00121/10698] drm/i915: kill i915_mem.c Some decent history digging indicates that this was to be used for the GLX_MESA_allocate_memory extension but never actually implemented for any released i915 userspace code. So just rip it out. v2: Fixup the Makefile. Acked-by: Dave Airlie Cc: Keith Whitwell Reviewed-by: Eric Anholt Signed-Off-by: Daniel Vetter --- drivers/gpu/drm/drm_ioctl.c | 2 + drivers/gpu/drm/i915/Makefile | 2 +- drivers/gpu/drm/i915/i915_dma.c | 14 +- drivers/gpu/drm/i915/i915_drv.h | 13 -- drivers/gpu/drm/i915/i915_mem.c | 387 -------------------------------- 5 files changed, 7 insertions(+), 411 deletions(-) delete mode 100644 drivers/gpu/drm/i915/i915_mem.c diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 956fd38d7c9e..2300ab1a2a77 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -37,6 +37,7 @@ #include "drm_core.h" #include "linux/pci.h" +#include "linux/export.h" /** * Get the bus id. @@ -346,3 +347,4 @@ int drm_noop(struct drm_device *dev, void *data, DRM_DEBUG("\n"); return 0; } +EXPORT_SYMBOL(drm_noop); diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 808b255d7fc6..ce7fc77678b4 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -3,7 +3,7 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. ccflags-y := -Iinclude/drm -i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ +i915-y := i915_drv.o i915_dma.o i915_irq.o \ i915_debugfs.o \ i915_suspend.o \ i915_gem.o \ diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 5f4d5893e983..2484c8ff0b81 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -2246,18 +2246,12 @@ void i915_driver_lastclose(struct drm_device * dev) i915_gem_lastclose(dev); - if (dev_priv->agp_heap) - i915_mem_takedown(&(dev_priv->agp_heap)); - i915_dma_cleanup(dev); } void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { - drm_i915_private_t *dev_priv = dev->dev_private; i915_gem_release(dev, file_priv); - if (!drm_core_check_feature(dev, DRIVER_MODESET)) - i915_mem_release(dev, file_priv, dev_priv->agp_heap); } void i915_driver_postclose(struct drm_device *dev, struct drm_file *file) @@ -2276,11 +2270,11 @@ struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), DRM_IOCTL_DEF_DRV(I915_GETPARAM, i915_getparam, DRM_AUTH), DRM_IOCTL_DEF_DRV(I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(I915_ALLOC, i915_mem_alloc, DRM_AUTH), - DRM_IOCTL_DEF_DRV(I915_FREE, i915_mem_free, DRM_AUTH), - DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_ALLOC, drm_noop, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_FREE, drm_noop, DRM_AUTH), + DRM_IOCTL_DEF_DRV(I915_INIT_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), - DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(I915_DESTROY_HEAP, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH), DRM_IOCTL_DEF_DRV(I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 602bc80baabb..3cb88c3e0568 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -329,7 +329,6 @@ typedef struct drm_i915_private { int tex_lru_log_granularity; int allow_batchbuffer; - struct mem_block *agp_heap; unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds; int vblank_pipe; int num_pipe; @@ -1075,18 +1074,6 @@ extern void i915_destroy_error_state(struct drm_device *dev); #endif -/* i915_mem.c */ -extern int i915_mem_alloc(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int i915_mem_free(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int i915_mem_init_heap(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern int i915_mem_destroy_heap(struct drm_device *dev, void *data, - struct drm_file *file_priv); -extern void i915_mem_takedown(struct mem_block **heap); -extern void i915_mem_release(struct drm_device * dev, - struct drm_file *file_priv, struct mem_block *heap); /* i915_gem.c */ int i915_gem_init_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/i915/i915_mem.c b/drivers/gpu/drm/i915/i915_mem.c deleted file mode 100644 index cc8f6d49cf20..000000000000 --- a/drivers/gpu/drm/i915/i915_mem.c +++ /dev/null @@ -1,387 +0,0 @@ -/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*- - */ -/* - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "drmP.h" -#include "drm.h" -#include "i915_drm.h" -#include "i915_drv.h" - -/* This memory manager is integrated into the global/local lru - * mechanisms used by the clients. Specifically, it operates by - * setting the 'in_use' fields of the global LRU to indicate whether - * this region is privately allocated to a client. - * - * This does require the client to actually respect that field. - * - * Currently no effort is made to allocate 'private' memory in any - * clever way - the LRU information isn't used to determine which - * block to allocate, and the ring is drained prior to allocations -- - * in other words allocation is expensive. - */ -static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; - drm_i915_sarea_t *sarea_priv = master_priv->sarea_priv; - struct drm_tex_region *list; - unsigned shift, nr; - unsigned start; - unsigned end; - unsigned i; - int age; - - shift = dev_priv->tex_lru_log_granularity; - nr = I915_NR_TEX_REGIONS; - - start = p->start >> shift; - end = (p->start + p->size - 1) >> shift; - - age = ++sarea_priv->texAge; - list = sarea_priv->texList; - - /* Mark the regions with the new flag and update their age. Move - * them to head of list to preserve LRU semantics. - */ - for (i = start; i <= end; i++) { - list[i].in_use = in_use; - list[i].age = age; - - /* remove_from_list(i) - */ - list[(unsigned)list[i].next].prev = list[i].prev; - list[(unsigned)list[i].prev].next = list[i].next; - - /* insert_at_head(list, i) - */ - list[i].prev = nr; - list[i].next = list[nr].next; - list[(unsigned)list[nr].next].prev = i; - list[nr].next = i; - } -} - -/* Very simple allocator for agp memory, working on a static range - * already mapped into each client's address space. - */ - -static struct mem_block *split_block(struct mem_block *p, int start, int size, - struct drm_file *file_priv) -{ - /* Maybe cut off the start of an existing block */ - if (start > p->start) { - struct mem_block *newblock = kmalloc(sizeof(*newblock), - GFP_KERNEL); - if (!newblock) - goto out; - newblock->start = start; - newblock->size = p->size - (start - p->start); - newblock->file_priv = NULL; - newblock->next = p->next; - newblock->prev = p; - p->next->prev = newblock; - p->next = newblock; - p->size -= newblock->size; - p = newblock; - } - - /* Maybe cut off the end of an existing block */ - if (size < p->size) { - struct mem_block *newblock = kmalloc(sizeof(*newblock), - GFP_KERNEL); - if (!newblock) - goto out; - newblock->start = start + size; - newblock->size = p->size - size; - newblock->file_priv = NULL; - newblock->next = p->next; - newblock->prev = p; - p->next->prev = newblock; - p->next = newblock; - p->size = size; - } - - out: - /* Our block is in the middle */ - p->file_priv = file_priv; - return p; -} - -static struct mem_block *alloc_block(struct mem_block *heap, int size, - int align2, struct drm_file *file_priv) -{ - struct mem_block *p; - int mask = (1 << align2) - 1; - - for (p = heap->next; p != heap; p = p->next) { - int start = (p->start + mask) & ~mask; - if (p->file_priv == NULL && start + size <= p->start + p->size) - return split_block(p, start, size, file_priv); - } - - return NULL; -} - -static struct mem_block *find_block(struct mem_block *heap, int start) -{ - struct mem_block *p; - - for (p = heap->next; p != heap; p = p->next) - if (p->start == start) - return p; - - return NULL; -} - -static void free_block(struct mem_block *p) -{ - p->file_priv = NULL; - - /* Assumes a single contiguous range. Needs a special file_priv in - * 'heap' to stop it being subsumed. - */ - if (p->next->file_priv == NULL) { - struct mem_block *q = p->next; - p->size += q->size; - p->next = q->next; - p->next->prev = p; - kfree(q); - } - - if (p->prev->file_priv == NULL) { - struct mem_block *q = p->prev; - q->size += p->size; - q->next = p->next; - q->next->prev = q; - kfree(p); - } -} - -/* Initialize. How to check for an uninitialized heap? - */ -static int init_heap(struct mem_block **heap, int start, int size) -{ - struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL); - - if (!blocks) - return -ENOMEM; - - *heap = kmalloc(sizeof(**heap), GFP_KERNEL); - if (!*heap) { - kfree(blocks); - return -ENOMEM; - } - - blocks->start = start; - blocks->size = size; - blocks->file_priv = NULL; - blocks->next = blocks->prev = *heap; - - memset(*heap, 0, sizeof(**heap)); - (*heap)->file_priv = (struct drm_file *) -1; - (*heap)->next = (*heap)->prev = blocks; - return 0; -} - -/* Free all blocks associated with the releasing file. - */ -void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv, - struct mem_block *heap) -{ - struct mem_block *p; - - if (!heap || !heap->next) - return; - - for (p = heap->next; p != heap; p = p->next) { - if (p->file_priv == file_priv) { - p->file_priv = NULL; - mark_block(dev, p, 0); - } - } - - /* Assumes a single contiguous range. Needs a special file_priv in - * 'heap' to stop it being subsumed. - */ - for (p = heap->next; p != heap; p = p->next) { - while (p->file_priv == NULL && p->next->file_priv == NULL) { - struct mem_block *q = p->next; - p->size += q->size; - p->next = q->next; - p->next->prev = p; - kfree(q); - } - } -} - -/* Shutdown. - */ -void i915_mem_takedown(struct mem_block **heap) -{ - struct mem_block *p; - - if (!*heap) - return; - - for (p = (*heap)->next; p != *heap;) { - struct mem_block *q = p; - p = p->next; - kfree(q); - } - - kfree(*heap); - *heap = NULL; -} - -static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region) -{ - switch (region) { - case I915_MEM_REGION_AGP: - return &dev_priv->agp_heap; - default: - return NULL; - } -} - -/* IOCTL HANDLERS */ - -int i915_mem_alloc(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_alloc_t *alloc = data; - struct mem_block *block, **heap; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - heap = get_heap(dev_priv, alloc->region); - if (!heap || !*heap) - return -EFAULT; - - /* Make things easier on ourselves: all allocations at least - * 4k aligned. - */ - if (alloc->alignment < 12) - alloc->alignment = 12; - - block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); - - if (!block) - return -ENOMEM; - - mark_block(dev, block, 1); - - if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, - sizeof(int))) { - DRM_ERROR("copy_to_user\n"); - return -EFAULT; - } - - return 0; -} - -int i915_mem_free(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_free_t *memfree = data; - struct mem_block *block, **heap; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - heap = get_heap(dev_priv, memfree->region); - if (!heap || !*heap) - return -EFAULT; - - block = find_block(*heap, memfree->region_offset); - if (!block) - return -EFAULT; - - if (block->file_priv != file_priv) - return -EPERM; - - mark_block(dev, block, 0); - free_block(block); - return 0; -} - -int i915_mem_init_heap(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_init_heap_t *initheap = data; - struct mem_block **heap; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - heap = get_heap(dev_priv, initheap->region); - if (!heap) - return -EFAULT; - - if (*heap) { - DRM_ERROR("heap already initialized?"); - return -EFAULT; - } - - return init_heap(heap, initheap->start, initheap->size); -} - -int i915_mem_destroy_heap(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_destroy_heap_t *destroyheap = data; - struct mem_block **heap; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - heap = get_heap(dev_priv, destroyheap->region); - if (!heap) { - DRM_ERROR("get_heap failed"); - return -EFAULT; - } - - if (!*heap) { - DRM_ERROR("heap not initialized?"); - return -EFAULT; - } - - i915_mem_takedown(heap); - return 0; -} -- GitLab From 3d29b842e58fbca2c13a9f458fddbaa535c6e578 Mon Sep 17 00:00:00 2001 From: Eugeni Dodonov Date: Tue, 17 Jan 2012 14:43:53 -0200 Subject: [PATCH 00122/10698] drm/i915: add a LLC feature flag in device description LLC is not SNB/IVB-specific, so we should check for it in a more generic way. Reviewed-by: Chris Wilson Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Eugeni Dodonov Signed-off-by: Daniel Vetter --- drivers/gpu/drm/i915/i915_debugfs.c | 1 + drivers/gpu/drm/i915/i915_dma.c | 3 +++ drivers/gpu/drm/i915/i915_drv.c | 4 ++++ drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem.c | 4 ++-- include/drm/i915_drm.h | 1 + 6 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 11807989f918..6c3be86274e1 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -83,6 +83,7 @@ static int i915_capabilities(struct seq_file *m, void *data) B(supports_tv); B(has_bsd_ring); B(has_blt_ring); + B(has_llc); #undef B return 0; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 2484c8ff0b81..8122738db91e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -784,6 +784,9 @@ static int i915_getparam(struct drm_device *dev, void *data, case I915_PARAM_HAS_GEN7_SOL_RESET: value = 1; break; + case I915_PARAM_HAS_LLC: + value = HAS_LLC(dev); + break; default: DRM_DEBUG_DRIVER("Unknown parameter %d\n", param->param); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7578c08110f7..1658cfd85aa7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -214,6 +214,7 @@ static const struct intel_device_info intel_sandybridge_d_info = { .need_gfx_hws = 1, .has_hotplug = 1, .has_bsd_ring = 1, .has_blt_ring = 1, + .has_llc = 1, }; static const struct intel_device_info intel_sandybridge_m_info = { @@ -222,6 +223,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { .has_fbc = 1, .has_bsd_ring = 1, .has_blt_ring = 1, + .has_llc = 1, }; static const struct intel_device_info intel_ivybridge_d_info = { @@ -229,6 +231,7 @@ static const struct intel_device_info intel_ivybridge_d_info = { .need_gfx_hws = 1, .has_hotplug = 1, .has_bsd_ring = 1, .has_blt_ring = 1, + .has_llc = 1, }; static const struct intel_device_info intel_ivybridge_m_info = { @@ -237,6 +240,7 @@ static const struct intel_device_info intel_ivybridge_m_info = { .has_fbc = 0, /* FBC is not enabled on Ivybridge mobile yet */ .has_bsd_ring = 1, .has_blt_ring = 1, + .has_llc = 1, }; static const struct pci_device_id pciidlist[] = { /* aka */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3cb88c3e0568..f02a5f525f03 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -255,6 +255,7 @@ struct intel_device_info { u8 supports_tv:1; u8 has_bsd_ring:1; u8 has_blt_ring:1; + u8 has_llc:1; }; enum no_fbc_reason { @@ -969,6 +970,7 @@ struct drm_i915_file_private { #define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) #define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring) +#define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) #define HAS_OVERLAY(dev) (INTEL_INFO(dev)->has_overlay) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index e55badb2d86d..eb98a7f55cfe 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3619,8 +3619,8 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev, obj->base.write_domain = I915_GEM_DOMAIN_CPU; obj->base.read_domains = I915_GEM_DOMAIN_CPU; - if (IS_GEN6(dev) || IS_GEN7(dev)) { - /* On Gen6, we can have the GPU use the LLC (the CPU + if (HAS_LLC(dev)) { + /* On some devices, we can have the GPU use the LLC (the CPU * cache) for about a 10% performance improvement * compared to uncached. Graphics requests other than * display scanout are coherent with the CPU in diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 924f6a454fed..da929bb5b788 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -296,6 +296,7 @@ typedef struct drm_i915_irq_wait { #define I915_PARAM_HAS_EXEC_CONSTANTS 14 #define I915_PARAM_HAS_RELAXED_DELTA 15 #define I915_PARAM_HAS_GEN7_SOL_RESET 16 +#define I915_PARAM_HAS_LLC 17 typedef struct drm_i915_getparam { int param; -- GitLab From 0df1a838d678fc6ab49f983a19e905f6a42297a0 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 17 Jan 2012 20:05:40 +0900 Subject: [PATCH 00123/10698] ARM: mach-shmobile: sh73a0 PINT IRQ base fix Bump up the sh73a0 PINT IRQ base from 768 to 800 to avoid collision with INTCS vectors for IRQ16->IRQ32 at 0x3xxx. Without this fix the sh73a0 IRQ pin handling code collides with the PINT code which results in hangs on Kota2 during boot. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/include/mach/sh73a0.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-shmobile/include/mach/sh73a0.h b/arch/arm/mach-shmobile/include/mach/sh73a0.h index 881d515a9686..cad57578ceed 100644 --- a/arch/arm/mach-shmobile/include/mach/sh73a0.h +++ b/arch/arm/mach-shmobile/include/mach/sh73a0.h @@ -515,8 +515,8 @@ enum { SHDMA_SLAVE_MMCIF_RX, }; -/* PINT interrupts are located at Linux IRQ 768 and up */ -#define SH73A0_PINT0_IRQ(irq) ((irq) + 768) -#define SH73A0_PINT1_IRQ(irq) ((irq) + 800) +/* PINT interrupts are located at Linux IRQ 800 and up */ +#define SH73A0_PINT0_IRQ(irq) ((irq) + 800) +#define SH73A0_PINT1_IRQ(irq) ((irq) + 832) #endif /* __ASM_SH73A0_H__ */ -- GitLab From e2c31b3fdd48274e9deb450e21279e54dfa02ccd Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 17 Jan 2012 20:10:49 +0900 Subject: [PATCH 00124/10698] ARM: mach-shmobile: sh73a0 IRQ sparse alloc fix Fix the sh73a0 external IRQ pin code to properly support CONFIG_SPARSE_IRQ=y by allocating IRQ descriptors for the cascaded IRQs associated with external IRQ pins. Without this fix it is impossible to request IRQ0->IRQ31 on the Kota2 board when sparse IRQs are enabled. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/intc-sh73a0.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c index 1eda6b0b69e3..9857595eaa79 100644 --- a/arch/arm/mach-shmobile/intc-sh73a0.c +++ b/arch/arm/mach-shmobile/intc-sh73a0.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -445,6 +446,7 @@ void __init sh73a0_init_irq(void) setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]); n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k))); + WARN_ON(irq_alloc_desc_at(n, numa_node_id()) != n); irq_set_chip_and_handler_name(n, &intca_gic_irq_chip, handle_level_irq, "level"); set_irq_flags(n, IRQF_VALID); /* yuck */ -- GitLab From 2fde109c2d79e9791250a5d212c13055e9216a55 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 17 Jan 2012 20:14:07 +0900 Subject: [PATCH 00125/10698] ARM: mach-shmobile: IRQ driven GPIO key support for Kota2 Now when GPIO IRQs are supported on sh73a0 modify the Kota2 board code to switch from the polled "gpio-keys-polled" driver to the IRQ driven "gpio-keys" driver. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-kota2.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c index 857ceeec1bb0..c8e7ca23fc06 100644 --- a/arch/arm/mach-shmobile/board-kota2.c +++ b/arch/arm/mach-shmobile/board-kota2.c @@ -143,11 +143,10 @@ static struct gpio_keys_button gpio_buttons[] = { static struct gpio_keys_platform_data gpio_key_info = { .buttons = gpio_buttons, .nbuttons = ARRAY_SIZE(gpio_buttons), - .poll_interval = 250, /* polled for now */ }; static struct platform_device gpio_keys_device = { - .name = "gpio-keys-polled", /* polled for now */ + .name = "gpio-keys", .id = -1, .dev = { .platform_data = &gpio_key_info, -- GitLab From d5bb386d70c8e8e79c7f652a794610e01d79f33e Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Tue, 30 Aug 2011 18:26:44 +0200 Subject: [PATCH 00126/10698] ARM: mach-shmobile: simplify MMCIF DMA configuration Use the simplified method to specify MMCIF DMA slave configuration. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-ag5evm.c | 11 ++--------- arch/arm/mach-shmobile/board-ap4evb.c | 12 ++---------- arch/arm/mach-shmobile/board-mackerel.c | 12 ++---------- 3 files changed, 6 insertions(+), 29 deletions(-) diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c index eff8a96c75ee..729eaee5a151 100644 --- a/arch/arm/mach-shmobile/board-ag5evm.c +++ b/arch/arm/mach-shmobile/board-ag5evm.c @@ -159,19 +159,12 @@ static struct resource sh_mmcif_resources[] = { }, }; -static struct sh_mmcif_dma sh_mmcif_dma = { - .chan_priv_rx = { - .slave_id = SHDMA_SLAVE_MMCIF_RX, - }, - .chan_priv_tx = { - .slave_id = SHDMA_SLAVE_MMCIF_TX, - }, -}; static struct sh_mmcif_plat_data sh_mmcif_platdata = { .sup_pclk = 0, .ocr = MMC_VDD_165_195, .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, - .dma = &sh_mmcif_dma, + .slave_id_tx = SHDMA_SLAVE_MMCIF_TX, + .slave_id_rx = SHDMA_SLAVE_MMCIF_RX, }; static struct platform_device mmc_device = { diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c index aab0a349f759..eeb4d9664584 100644 --- a/arch/arm/mach-shmobile/board-ap4evb.c +++ b/arch/arm/mach-shmobile/board-ap4evb.c @@ -295,15 +295,6 @@ static struct resource sh_mmcif_resources[] = { }, }; -static struct sh_mmcif_dma sh_mmcif_dma = { - .chan_priv_rx = { - .slave_id = SHDMA_SLAVE_MMCIF_RX, - }, - .chan_priv_tx = { - .slave_id = SHDMA_SLAVE_MMCIF_TX, - }, -}; - static struct sh_mmcif_plat_data sh_mmcif_plat = { .sup_pclk = 0, .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, @@ -311,7 +302,8 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = { MMC_CAP_8_BIT_DATA | MMC_CAP_NEEDS_POLL, .get_cd = slot_cn7_get_cd, - .dma = &sh_mmcif_dma, + .slave_id_tx = SHDMA_SLAVE_MMCIF_TX, + .slave_id_rx = SHDMA_SLAVE_MMCIF_RX, }; static struct platform_device sh_mmcif_device = { diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 9b42fbd10f8e..1a955e2a334f 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -1184,15 +1184,6 @@ static struct resource sh_mmcif_resources[] = { }, }; -static struct sh_mmcif_dma sh_mmcif_dma = { - .chan_priv_rx = { - .slave_id = SHDMA_SLAVE_MMCIF_RX, - }, - .chan_priv_tx = { - .slave_id = SHDMA_SLAVE_MMCIF_TX, - }, -}; - static struct sh_mmcif_plat_data sh_mmcif_plat = { .sup_pclk = 0, .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, @@ -1200,7 +1191,8 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = { MMC_CAP_8_BIT_DATA | MMC_CAP_NEEDS_POLL, .get_cd = slot_cn7_get_cd, - .dma = &sh_mmcif_dma, + .slave_id_tx = SHDMA_SLAVE_MMCIF_TX, + .slave_id_rx = SHDMA_SLAVE_MMCIF_RX, }; static struct platform_device sh_mmcif_device = { -- GitLab From 48cfe37cc03f616e6c139796962e7ec677cde8a9 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 21 Dec 2011 14:20:23 -0500 Subject: [PATCH 00127/10698] target: don't allocate bio headroom in iblock We never embedd the bio into a structure, so there is no need to allocate 64 bytes of headroom per bio. Signed-off-by: Christoph Hellwig Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_iblock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index cc8e6b58ef20..628e877381d8 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -129,7 +129,7 @@ static struct se_device *iblock_create_virtdevice( /* * These settings need to be made tunable.. */ - ib_dev->ibd_bio_set = bioset_create(32, 64); + ib_dev->ibd_bio_set = bioset_create(32, 0); if (!ib_dev->ibd_bio_set) { pr_err("IBLOCK: Unable to create bioset()\n"); return ERR_PTR(-ENOMEM); -- GitLab From 9e08e34e3735ae057eb3834da3570995811b7eb9 Mon Sep 17 00:00:00 2001 From: Marco Sanvido Date: Tue, 3 Jan 2012 17:12:57 -0800 Subject: [PATCH 00128/10698] target: Use correct preempted registration sense code The comments quote the right parts of the spec: * d) Establish a unit attention condition for the * initiator port associated with every I_T nexus * that lost its registration other than the I_T * nexus on which the PERSISTENT RESERVE OUT command * was received, with the additional sense code set * to REGISTRATIONS PREEMPTED. and * e) Establish a unit attention condition for the initiator * port associated with every I_T nexus that lost its * persistent reservation and/or registration, with the * additional sense code set to REGISTRATIONS PREEMPTED; but the actual code accidentally uses ASCQ_2AH_RESERVATIONS_PREEMPTED instead of ASCQ_2AH_REGISTRATIONS_PREEMPTED. Fix this. Signed-off-by: Marco Sanvido Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 429ad7291664..d14860ff2508 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -3120,7 +3120,7 @@ static int core_scsi3_pro_preempt( if (!calling_it_nexus) core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A, - ASCQ_2AH_RESERVATIONS_PREEMPTED); + ASCQ_2AH_REGISTRATIONS_PREEMPTED); } spin_unlock(&pr_tmpl->registration_lock); /* @@ -3233,7 +3233,7 @@ static int core_scsi3_pro_preempt( * additional sense code set to REGISTRATIONS PREEMPTED; */ core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A, - ASCQ_2AH_RESERVATIONS_PREEMPTED); + ASCQ_2AH_REGISTRATIONS_PREEMPTED); } spin_unlock(&pr_tmpl->registration_lock); /* -- GitLab From 6816966a8418b980481b4dced7eddd1796b145e8 Mon Sep 17 00:00:00 2001 From: Marco Sanvido Date: Tue, 3 Jan 2012 17:12:58 -0800 Subject: [PATCH 00129/10698] target: Allow PERSISTENT RESERVE IN for non-reservation holder Initiators that aren't the active reservation holder should be able to do a PERSISTENT RESERVE IN command in all cases, so add it to the list of allowed CDBs in core_scsi3_pr_seq_non_holder(). Signed-off-by: Marco Sanvido Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_pr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index d14860ff2508..68c71cd7a88e 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -478,6 +478,7 @@ static int core_scsi3_pr_seq_non_holder( case READ_MEDIA_SERIAL_NUMBER: case REPORT_LUNS: case REQUEST_SENSE: + case PERSISTENT_RESERVE_IN: ret = 0; /*/ Allowed CDBs */ break; default: -- GitLab From 9db9da332250dbe662995703a4dcdd692112f0c3 Mon Sep 17 00:00:00 2001 From: "roland@purestorage.com" Date: Wed, 4 Jan 2012 15:59:58 -0800 Subject: [PATCH 00130/10698] target: Don't zero pages used for data buffers Doing alloc_page(GFP_KERNEL | __GFP_ZERO) to get pages used for data buffers wastes a lot of CPU clearing pages that will be quickly be overwritten by the actual data. However, for emulated control commands such as INQUIRY and so on, the code does assume that the buffer is zeroed. To avoid this CPU overhead, skip the __GFP_ZERO for commands that are actually moving data, ie cmds that have SCF_SCSI_DATA_SG_IO_CDB set. Signed-off-by: Roland Dreier Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index d3ddd1361949..289bc0f125f9 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3516,6 +3516,7 @@ transport_generic_get_mem(struct se_cmd *cmd) u32 length = cmd->data_length; unsigned int nents; struct page *page; + gfp_t zero_flag; int i = 0; nents = DIV_ROUND_UP(length, PAGE_SIZE); @@ -3526,9 +3527,11 @@ transport_generic_get_mem(struct se_cmd *cmd) cmd->t_data_nents = nents; sg_init_table(cmd->t_data_sg, nents); + zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO; + while (length) { u32 page_len = min_t(u32, length, PAGE_SIZE); - page = alloc_page(GFP_KERNEL | __GFP_ZERO); + page = alloc_page(GFP_KERNEL | zero_flag); if (!page) goto out; -- GitLab From 9fbc8909876a2160044e71d376848973b9bfdc3f Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Mon, 9 Jan 2012 17:54:00 -0800 Subject: [PATCH 00131/10698] target: Correct sense key for INVALID FIELD IN {PARAMETER LIST,CDB} According to SPC-4, the sense key for commands that are failed with INVALID FIELD IN PARAMETER LIST and INVALID FIELD IN CDB should be ILLEGAL REQUEST (5h) rather than ABORTED COMMAND (Bh). Without this patch, a tcm_loop LUN incorrectly gives: # sg_raw -r 1 -v /dev/sda 3 1 0 0 ff 0 Sense Information: Fixed format, current; Sense key: Aborted Command Additional sense: Invalid field in cdb Raw sense data (in hex): 70 00 0b 00 00 00 00 0a 00 00 00 00 24 00 00 00 00 00 While a real SCSI disk gives: Sense Information: Fixed format, current; Sense key: Illegal Request Additional sense: Invalid field in cdb Raw sense data (in hex): 70 00 05 00 00 00 00 18 00 00 00 00 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 with the main point being that the real disk gives a sense key of ILLEGAL REQUEST (5h). Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 289bc0f125f9..2869fb7d2c05 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -4451,8 +4451,8 @@ int transport_send_check_condition_and_sense( /* CURRENT ERROR */ buffer[offset] = 0x70; buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ABORTED COMMAND */ - buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; + /* ILLEGAL REQUEST */ + buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; /* INVALID FIELD IN CDB */ buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24; break; @@ -4460,8 +4460,8 @@ int transport_send_check_condition_and_sense( /* CURRENT ERROR */ buffer[offset] = 0x70; buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10; - /* ABORTED COMMAND */ - buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND; + /* ILLEGAL REQUEST */ + buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; /* INVALID FIELD IN PARAMETER LIST */ buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26; break; -- GitLab From 91ec1d3535b2acf12c599045cc19ad9be3c6a47b Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Fri, 13 Jan 2012 12:01:34 -0800 Subject: [PATCH 00132/10698] target: Add workaround for zero-length control CDB handling This patch adds a work-around for handling zero allocation length control CDBs (type SCF_SCSI_CONTROL_SG_IO_CDB) that was causing an OOPs with the following raw calls: # sg_raw -v /dev/sdd 3 0 0 0 0 0 # sg_raw -v /dev/sdd 0x1a 0 1 0 0 0 This patch will follow existing zero-length handling for data I/O and silently return with GOOD status. This addresses the zero length issue, but the proper long-term resolution for handling arbitary allocation lengths will be to refactor out data-phase handling in individual CDB emulation logic within target_core_cdb.c Reported-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 2869fb7d2c05..50d6911d4120 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3759,6 +3759,11 @@ transport_allocate_control_task(struct se_cmd *cmd) struct se_task *task; unsigned long flags; + /* Workaround for handling zero-length control CDBs */ + if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && + !cmd->data_length) + return 0; + task = transport_generic_get_task(cmd, cmd->data_direction); if (!task) return -ENOMEM; @@ -3830,6 +3835,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd) else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) { cmd->t_state = TRANSPORT_COMPLETE; atomic_set(&cmd->t_transport_active, 1); + + if (cmd->t_task_cdb[0] == REQUEST_SENSE) { + u8 ua_asc = 0, ua_ascq = 0; + + core_scsi3_ua_clear_for_request_sense(cmd, + &ua_asc, &ua_ascq); + } + INIT_WORK(&cmd->work, target_complete_ok_work); queue_work(target_completion_wq, &cmd->work); return 0; -- GitLab From e59a41b69a8e116d5ac8c95c4222f5a971f66bbd Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 10 Jan 2012 14:16:57 +0100 Subject: [PATCH 00133/10698] target: avoid multiple outputs in scsi_dump_inquiry() The multiple calls to pr_debug() each with one letter results in a new line. This patch merges the multiple requests into one call per line so we don't have the multiple line cuts. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 50d6911d4120..e186f7db3860 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1255,32 +1255,34 @@ static void core_setup_task_attr_emulation(struct se_device *dev) static void scsi_dump_inquiry(struct se_device *dev) { struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn; + char buf[17]; int i, device_type; /* * Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer */ - pr_debug(" Vendor: "); for (i = 0; i < 8; i++) if (wwn->vendor[i] >= 0x20) - pr_debug("%c", wwn->vendor[i]); + buf[i] = wwn->vendor[i]; else - pr_debug(" "); + buf[i] = ' '; + buf[i] = '\0'; + pr_debug(" Vendor: %s\n", buf); - pr_debug(" Model: "); for (i = 0; i < 16; i++) if (wwn->model[i] >= 0x20) - pr_debug("%c", wwn->model[i]); + buf[i] = wwn->model[i]; else - pr_debug(" "); + buf[i] = ' '; + buf[i] = '\0'; + pr_debug(" Model: %s\n", buf); - pr_debug(" Revision: "); for (i = 0; i < 4; i++) if (wwn->revision[i] >= 0x20) - pr_debug("%c", wwn->revision[i]); + buf[i] = wwn->revision[i]; else - pr_debug(" "); - - pr_debug("\n"); + buf[i] = ' '; + buf[i] = '\0'; + pr_debug(" Revision: %s\n", buf); device_type = dev->transport->get_device_type(dev); pr_debug(" Type: %s ", scsi_device_type(device_type)); -- GitLab From 1dd0a0674530da61cdbfadd88c96949b483a7c19 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 10 Jan 2012 14:16:58 +0100 Subject: [PATCH 00134/10698] target: use save/restore lock primitive in core_dec_lacl_count() It may happen that uasp will free the request in irq conntext, the callchain: uasp_cmd_release() -> transport_generic_free_cmd() -> core_dec_lacl_count() where the last function enables the IRQ. Those irqs are re-disabled later (due to the spin.*irq_restore) but in between we could get hurt. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 0c5992f0d946..00159a4e781f 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -320,11 +320,12 @@ int core_free_device_list_for_node( void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd) { struct se_dev_entry *deve; + unsigned long flags; - spin_lock_irq(&se_nacl->device_list_lock); + spin_lock_irqsave(&se_nacl->device_list_lock, flags); deve = &se_nacl->device_list[se_cmd->orig_fe_lun]; deve->deve_cmds--; - spin_unlock_irq(&se_nacl->device_list_lock); + spin_unlock_irqrestore(&se_nacl->device_list_lock, flags); } void core_update_device_list_access( -- GitLab From 8d9efe539cf78f6a90947d47100e4a86d907750f Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 11 Jan 2012 21:43:38 +0100 Subject: [PATCH 00135/10698] target: fix return code of core_tpg_.*_lun - core_tpg_pre_addlun() returns always ERR_PTR() or the pointer, never NULL. The additional check for NULL in core_dev_add_lun() is not required. - core_tpg_pre_dellun() returns always ERR_PTR() or the pointer, never NULL. The check for NULL in core_dev_del_lun() is wrong. The third argument (int *) is never used, remove it. - core_dev_add_lun() returns always NULL or the pointer, never ERR_PTR. The check for IS_ERR() is not required. (nab: Convert core_dev_add_lun() use err.h macros for failure handling to be consistent with the rest of target_core_fabric_configfs.c callers) Signed-off-by: Sebastian Andrzej Siewior Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 19 ++++++++++--------- drivers/target/target_core_fabric_configfs.c | 4 ++-- drivers/target/target_core_internal.h | 2 +- drivers/target/target_core_tpg.c | 3 +-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 00159a4e781f..de5f4fea7f62 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1295,24 +1295,26 @@ struct se_lun *core_dev_add_lun( { struct se_lun *lun_p; u32 lun_access = 0; + int rc; if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) { pr_err("Unable to export struct se_device while dev_access_obj: %d\n", atomic_read(&dev->dev_access_obj.obj_access_count)); - return NULL; + return ERR_PTR(-EACCES); } lun_p = core_tpg_pre_addlun(tpg, lun); - if ((IS_ERR(lun_p)) || !lun_p) - return NULL; + if (IS_ERR(lun_p)) + return lun_p; if (dev->dev_flags & DF_READ_ONLY) lun_access = TRANSPORT_LUNFLAGS_READ_ONLY; else lun_access = TRANSPORT_LUNFLAGS_READ_WRITE; - if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0) - return NULL; + rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev); + if (rc < 0) + return ERR_PTR(rc); pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from" " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(), @@ -1349,11 +1351,10 @@ int core_dev_del_lun( u32 unpacked_lun) { struct se_lun *lun; - int ret = 0; - lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret); - if (!lun) - return ret; + lun = core_tpg_pre_dellun(tpg, unpacked_lun); + if (IS_ERR(lun)) + return PTR_ERR(lun); core_tpg_post_dellun(tpg, lun); diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 4f77cce22646..9a2ce11e1a6e 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -766,9 +766,9 @@ static int target_fabric_port_link( lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev, lun->unpacked_lun); - if (IS_ERR(lun_p) || !lun_p) { + if (IS_ERR(lun_p)) { pr_err("core_dev_add_lun() failed\n"); - ret = -EINVAL; + ret = PTR_ERR(lun_p); goto out; } diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 26f135e94f6e..45001364788a 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -90,7 +90,7 @@ void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *); struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32); int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *, u32, void *); -struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32, int *); +struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun); int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *); /* target_core_transport.c */ diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index b7668029bb31..06336ecd872d 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -807,8 +807,7 @@ static void core_tpg_shutdown_lun( struct se_lun *core_tpg_pre_dellun( struct se_portal_group *tpg, - u32 unpacked_lun, - int *ret) + u32 unpacked_lun) { struct se_lun *lun; -- GitLab From c1ce4bd56f2846de55043374598fd929ad3b711b Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 16 Jan 2012 16:04:15 -0800 Subject: [PATCH 00136/10698] iscsi-target: Fix reject release handling in iscsit_free_cmd() This patch addresses a bug where iscsit_free_cmd() was incorrectly calling iscsit_release_cmd() for ISCSI_OP_REJECT because iscsi_add_reject*() will overwrite the original iscsi_cmd->iscsi_opcode assignment. This bug was introduced with the following commit: commit 0be67f2ed8f577d2c72d917928394c5885fa9134 Author: Nicholas Bellinger Date: Sun Oct 9 01:48:14 2011 -0700 iscsi-target: Remove SCF_SE_LUN_CMD flag abuses and was manifesting itself as list corruption with the following: [ 131.191092] ------------[ cut here ]------------ [ 131.191092] WARNING: at lib/list_debug.c:53 __list_del_entry+0x8d/0x98() [ 131.191092] Hardware name: VMware Virtual Platform [ 131.191092] list_del corruption. prev->next should be ffff880022d3c100, but was 6b6b6b6b6b6b6b6b [ 131.191092] Modules linked in: tcm_vhost ib_srpt ib_cm ib_sa ib_mad ib_core tcm_qla2xxx qla2xxx tcm_loop tcm_fc libfc scsi_transport_fc crc32c iscsi_target_mod target_core_stgt scsi_tgt target_core_pscsi target_core_file target_core_iblock target_core_mod configfs ipv6 iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi sr_mod cdrom sd_mod e1000 ata_piix libata mptspi mptscsih mptbase [last unloaded: scsi_wait_scan] [ 131.191092] Pid: 2250, comm: iscsi_ttx Tainted: G W 3.2.0-rc4+ #42 [ 131.191092] Call Trace: [ 131.191092] [] warn_slowpath_common+0x80/0x98 [ 131.191092] [] warn_slowpath_fmt+0x41/0x43 [ 131.191092] [] __list_del_entry+0x8d/0x98 [ 131.191092] [] transport_lun_remove_cmd+0x9b/0xb7 [target_core_mod] [ 131.191092] [] transport_generic_free_cmd+0x5d/0x71 [target_core_mod] [ 131.191092] [] iscsit_free_cmd+0x1e/0x27 [iscsi_target_mod] [ 131.191092] [] iscsit_close_connection+0x14d/0x5b2 [iscsi_target_mod] [ 131.191092] [] iscsit_take_action_for_connection_exit+0xdb/0xe0 [iscsi_target_mod] [ 131.191092] [] iscsi_target_tx_thread+0x15cb/0x1608 [iscsi_target_mod] [ 131.191092] [] ? check_preempt_wakeup+0x121/0x185 [ 131.191092] [] ? __dequeue_entity+0x2e/0x33 [ 131.191092] [] ? iscsit_send_text_rsp+0x25f/0x25f [iscsi_target_mod] [ 131.191092] [] ? iscsit_send_text_rsp+0x25f/0x25f [iscsi_target_mod] [ 131.191092] [] ? schedule+0x55/0x57 [ 131.191092] [] kthread+0x7d/0x85 [ 131.191092] [] kernel_thread_helper+0x4/0x10 [ 131.191092] [] ? kthread_worker_fn+0x16d/0x16d [ 131.191092] [] ? gs_change+0x13/0x13 Reported-by: Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_util.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index a05ca1c4f01c..11287e1ece13 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -849,6 +849,17 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd) case ISCSI_OP_SCSI_TMFUNC: transport_generic_free_cmd(&cmd->se_cmd, 1); break; + case ISCSI_OP_REJECT: + /* + * Handle special case for REJECT when iscsi_add_reject*() has + * overwritten the original iscsi_opcode assignment, and the + * associated cmd->se_cmd needs to be released. + */ + if (cmd->se_cmd.se_tfo != NULL) { + transport_generic_free_cmd(&cmd->se_cmd, 1); + break; + } + /* Fall-through */ default: iscsit_release_cmd(cmd); break; -- GitLab From cd931ee62fd0258fc85c76a7c5499fe85e0f3436 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 16 Jan 2012 17:11:54 -0800 Subject: [PATCH 00137/10698] iscsi-target: Fix double list_add with iscsit_alloc_buffs reject This patch fixes a bug where the iscsit_add_reject_from_cmd() call from a failure to iscsit_alloc_buffs() was incorrectly passing add_to_conn=1 and causing a double list_add after iscsi_cmd->i_list had already been added in iscsit_handle_scsi_cmd(). Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index ac44af165b27..6e070e0a8393 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1061,7 +1061,7 @@ static int iscsit_handle_scsi_cmd( if (ret < 0) return iscsit_add_reject_from_cmd( ISCSI_REASON_BOOKMARK_NO_RESOURCES, - 1, 1, buf, cmd); + 1, 0, buf, cmd); /* * Check the CmdSN against ExpCmdSN/MaxCmdSN here if * the Immediate Bit is not set, and no Immediate -- GitLab From f8d48ae52eeec906d7fb42485eb26a5d305bab0a Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 15 Jan 2012 14:30:24 +0300 Subject: [PATCH 00138/10698] iscsi-target: make one-bit bitfields unsigned Signed bitfields are a problem because instead of being 1 or 0 like you'd expect they are 0 and -1. It doesn't cause a problem in this case but sparse complains: drivers/target/iscsi/iscsi_target_core.h:564:56: error: dubious one-bit signed bitfield Signed-off-by: Dan Carpenter Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_core.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index f1a02dad05a0..ebf81fdbb5c5 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -561,8 +561,8 @@ struct iscsi_conn { struct hash_desc conn_tx_hash; /* Used for scheduling TX and RX connection kthreads */ cpumask_var_t conn_cpumask; - int conn_rx_reset_cpumask:1; - int conn_tx_reset_cpumask:1; + unsigned int conn_rx_reset_cpumask:1; + unsigned int conn_tx_reset_cpumask:1; /* list_head of struct iscsi_cmd for this connection */ struct list_head conn_cmd_list; struct list_head immed_queue_list; -- GitLab From e8904dc5008ef92f0f62391d6557f03f921eeb32 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 15 Jan 2012 19:33:30 +0100 Subject: [PATCH 00139/10698] iscsi-target: Fix up a few assignments A statement such as struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); has undefined behaviour since there are two assignments to 'na', strictly speaking (the order in which side-effects from the assignments take place is undefined since there's no intervening sequence point), and it looks unintentional in any case. Signed-off-by: Jesper Juhl Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_erl1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 255c0d67e898..27901e37c125 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -1238,7 +1238,7 @@ void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd) { struct iscsi_conn *conn = cmd->conn; struct iscsi_session *sess = conn->sess; - struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); + struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess); spin_lock_bh(&cmd->dataout_timeout_lock); if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) { @@ -1261,7 +1261,7 @@ void iscsit_start_dataout_timer( struct iscsi_conn *conn) { struct iscsi_session *sess = conn->sess; - struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess); + struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess); if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING) return; -- GitLab From 4949314c7283ea4f9ade182ca599583b89f7edd6 Mon Sep 17 00:00:00 2001 From: Andy Grover Date: Mon, 16 Jan 2012 16:57:08 -0800 Subject: [PATCH 00140/10698] target: Allow control CDBs with data > 1 page We need to handle >1 page control cdbs, so extend the code to do a vmap if bigger than 1 page. It seems like kmap() is still preferable if just a page, fewer TLB shootdowns(?), so keep using that when possible. Rename function pair for their new scope. Signed-off-by: Andy Grover Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_alua.c | 8 ++--- drivers/target/target_core_cdb.c | 28 ++++++++-------- drivers/target/target_core_device.c | 4 +-- drivers/target/target_core_pr.c | 38 +++++++++++----------- drivers/target/target_core_pscsi.c | 4 +-- drivers/target/target_core_transport.c | 45 +++++++++++++++++++------- include/target/target_core_backend.h | 4 +-- include/target/target_core_base.h | 1 + 8 files changed, 78 insertions(+), 54 deletions(-) diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 1b1edd14f4bf..01a2691dfb47 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -78,7 +78,7 @@ int target_emulate_report_target_port_groups(struct se_task *task) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); spin_lock(&su_dev->t10_alua.tg_pt_gps_lock); list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list, @@ -163,7 +163,7 @@ int target_emulate_report_target_port_groups(struct se_task *task) buf[2] = ((rd_len >> 8) & 0xff); buf[3] = (rd_len & 0xff); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); @@ -194,7 +194,7 @@ int target_emulate_set_target_port_groups(struct se_task *task) cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); /* * Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed @@ -351,7 +351,7 @@ int target_emulate_set_target_port_groups(struct se_task *task) } out: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); return 0; diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 2f2235edefff..07a3025d0622 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -83,7 +83,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); if (dev == tpg->tpg_virt_lun0.lun_se_dev) { buf[0] = 0x3f; /* Not connected */ @@ -134,7 +134,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd) buf[4] = 31; /* Set additional length to 31 */ out: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } @@ -716,7 +716,7 @@ int target_emulate_inquiry(struct se_task *task) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = dev->transport->get_device_type(dev); @@ -733,7 +733,7 @@ int target_emulate_inquiry(struct se_task *task) ret = -EINVAL; out_unmap: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); out: if (!ret) { task->task_scsi_status = GOOD; @@ -755,7 +755,7 @@ int target_emulate_readcapacity(struct se_task *task) else blocks = (u32)blocks_long; - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = (blocks >> 24) & 0xff; buf[1] = (blocks >> 16) & 0xff; @@ -771,7 +771,7 @@ int target_emulate_readcapacity(struct se_task *task) if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) put_unaligned_be32(0xFFFFFFFF, &buf[0]); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); @@ -785,7 +785,7 @@ int target_emulate_readcapacity_16(struct se_task *task) unsigned char *buf; unsigned long long blocks = dev->transport->get_blocks(dev); - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = (blocks >> 56) & 0xff; buf[1] = (blocks >> 48) & 0xff; @@ -806,7 +806,7 @@ int target_emulate_readcapacity_16(struct se_task *task) if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws) buf[14] = 0x80; - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); @@ -1019,9 +1019,9 @@ int target_emulate_modesense(struct se_task *task) offset = cmd->data_length; } - rbuf = transport_kmap_first_data_page(cmd); + rbuf = transport_kmap_data_sg(cmd); memcpy(rbuf, buf, offset); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); @@ -1043,7 +1043,7 @@ int target_emulate_request_sense(struct se_task *task) return -ENOSYS; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) { /* @@ -1089,7 +1089,7 @@ int target_emulate_request_sense(struct se_task *task) } end: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); task->task_scsi_status = GOOD; transport_complete_task(task, 1); return 0; @@ -1123,7 +1123,7 @@ int target_emulate_unmap(struct se_task *task) dl = get_unaligned_be16(&cdb[0]); bd_dl = get_unaligned_be16(&cdb[2]); - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); ptr = &buf[offset]; pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" @@ -1147,7 +1147,7 @@ int target_emulate_unmap(struct se_task *task) } err: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); if (!ret) { task->task_scsi_status = GOOD; transport_complete_task(task, 1); diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index de5f4fea7f62..edbcabbf85f7 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -657,7 +657,7 @@ int target_report_luns(struct se_task *se_task) unsigned char *buf; u32 cdb_offset = 0, lun_count = 0, offset = 8, i; - buf = transport_kmap_first_data_page(se_cmd); + buf = (unsigned char *) transport_kmap_data_sg(se_cmd); /* * If no struct se_session pointer is present, this struct se_cmd is @@ -695,7 +695,7 @@ int target_report_luns(struct se_task *se_task) * See SPC3 r07, page 159. */ done: - transport_kunmap_first_data_page(se_cmd); + transport_kunmap_data_sg(se_cmd); lun_count *= 8; buf[0] = ((lun_count >> 24) & 0xff); buf[1] = ((lun_count >> 16) & 0xff); diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index 68c71cd7a88e..b7c779389eea 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -1535,7 +1535,7 @@ static int core_scsi3_decode_spec_i_port( tidh_new->dest_local_nexus = 1; list_add_tail(&tidh_new->dest_list, &tid_dest_list); - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); /* * For a PERSISTENT RESERVE OUT specify initiator ports payload, * first extract TransportID Parameter Data Length, and make sure @@ -1786,7 +1786,7 @@ static int core_scsi3_decode_spec_i_port( } - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); /* * Go ahead and create a registrations from tid_dest_list for the @@ -1834,7 +1834,7 @@ static int core_scsi3_decode_spec_i_port( return 0; out: - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); /* * For the failure case, release everything from tid_dest_list * including *dest_pr_reg and the configfs dependances.. @@ -3411,14 +3411,14 @@ static int core_scsi3_emulate_pro_register_and_move( * will be moved to for the TransportID containing SCSI initiator WWN * information. */ - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); rtpi = (buf[18] & 0xff) << 8; rtpi |= buf[19] & 0xff; tid_len = (buf[20] & 0xff) << 24; tid_len |= (buf[21] & 0xff) << 16; tid_len |= (buf[22] & 0xff) << 8; tid_len |= buf[23] & 0xff; - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); buf = NULL; if ((tid_len + 24) != cmd->data_length) { @@ -3470,7 +3470,7 @@ static int core_scsi3_emulate_pro_register_and_move( return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); proto_ident = (buf[24] & 0x0f); #if 0 pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:" @@ -3504,7 +3504,7 @@ static int core_scsi3_emulate_pro_register_and_move( goto out; } - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); buf = NULL; pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s" @@ -3769,13 +3769,13 @@ static int core_scsi3_emulate_pro_register_and_move( " REGISTER_AND_MOVE\n"); } - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); core_scsi3_put_pr_reg(dest_pr_reg); return 0; out: if (buf) - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); if (dest_se_deve) core_scsi3_lunacl_undepend_item(dest_se_deve); if (dest_node_acl) @@ -3849,7 +3849,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task) scope = (cdb[2] & 0xf0); type = (cdb[2] & 0x0f); - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); /* * From PERSISTENT_RESERVE_OUT parameter list (payload) */ @@ -3867,7 +3867,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task) aptpl = (buf[17] & 0x01); unreg = (buf[17] & 0x02); } - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); buf = NULL; /* @@ -3967,7 +3967,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); @@ -4001,7 +4001,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd) buf[6] = ((add_len >> 8) & 0xff); buf[7] = (add_len & 0xff); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } @@ -4027,7 +4027,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff); @@ -4086,7 +4086,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd) err: spin_unlock(&se_dev->dev_reservation_lock); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } @@ -4110,7 +4110,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = ((add_len << 8) & 0xff); buf[1] = (add_len & 0xff); @@ -4142,7 +4142,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd) buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */ buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */ - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } @@ -4172,7 +4172,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) return -EINVAL; } - buf = transport_kmap_first_data_page(cmd); + buf = transport_kmap_data_sg(cmd); buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff); buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff); @@ -4293,7 +4293,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd) buf[6] = ((add_len >> 8) & 0xff); buf[7] = (add_len & 0xff); - transport_kunmap_first_data_page(cmd); + transport_kunmap_data_sg(cmd); return 0; } diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index d35467d42e12..8d4def30e9e8 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -693,7 +693,7 @@ static int pscsi_transport_complete(struct se_task *task) if (task->task_se_cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) { - unsigned char *buf = transport_kmap_first_data_page(task->task_se_cmd); + unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd); if (cdb[0] == MODE_SENSE_10) { if (!(buf[3] & 0x80)) @@ -703,7 +703,7 @@ static int pscsi_transport_complete(struct se_task *task) buf[2] |= 0x80; } - transport_kunmap_first_data_page(task->task_se_cmd); + transport_kunmap_data_sg(task->task_se_cmd); } } after_mode_sense: diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index e186f7db3860..cf996d81cfcb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -3084,11 +3084,6 @@ static int transport_generic_cmd_sequencer( (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB))) goto out_unsupported_cdb; - /* Let's limit control cdbs to a page, for simplicity's sake. */ - if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) && - size > PAGE_SIZE) - goto out_invalid_cdb_field; - transport_set_supported_SAM_opcode(cmd); return ret; @@ -3492,9 +3487,11 @@ int transport_generic_map_mem_to_cmd( } EXPORT_SYMBOL(transport_generic_map_mem_to_cmd); -void *transport_kmap_first_data_page(struct se_cmd *cmd) +void *transport_kmap_data_sg(struct se_cmd *cmd) { struct scatterlist *sg = cmd->t_data_sg; + struct page **pages; + int i; BUG_ON(!sg); /* @@ -3502,15 +3499,41 @@ void *transport_kmap_first_data_page(struct se_cmd *cmd) * tcm_loop who may be using a contig buffer from the SCSI midlayer for * control CDBs passed as SGLs via transport_generic_map_mem_to_cmd() */ - return kmap(sg_page(sg)) + sg->offset; + if (!cmd->t_data_nents) + return NULL; + else if (cmd->t_data_nents == 1) + return kmap(sg_page(sg)) + sg->offset; + + /* >1 page. use vmap */ + pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL); + if (!pages) + return NULL; + + /* convert sg[] to pages[] */ + for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) { + pages[i] = sg_page(sg); + } + + cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL); + kfree(pages); + if (!cmd->t_data_vmap) + return NULL; + + return cmd->t_data_vmap + cmd->t_data_sg[0].offset; } -EXPORT_SYMBOL(transport_kmap_first_data_page); +EXPORT_SYMBOL(transport_kmap_data_sg); -void transport_kunmap_first_data_page(struct se_cmd *cmd) +void transport_kunmap_data_sg(struct se_cmd *cmd) { - kunmap(sg_page(cmd->t_data_sg)); + if (!cmd->t_data_nents) + return; + else if (cmd->t_data_nents == 1) + kunmap(sg_page(cmd->t_data_sg)); + + vunmap(cmd->t_data_vmap); + cmd->t_data_vmap = NULL; } -EXPORT_SYMBOL(transport_kunmap_first_data_page); +EXPORT_SYMBOL(transport_kunmap_data_sg); static int transport_generic_get_mem(struct se_cmd *cmd) diff --git a/include/target/target_core_backend.h b/include/target/target_core_backend.h index 4866499bdeeb..e5e6ff98f0fa 100644 --- a/include/target/target_core_backend.h +++ b/include/target/target_core_backend.h @@ -59,7 +59,7 @@ int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *); int transport_set_vpd_ident(struct t10_vpd *, unsigned char *); /* core helpers also used by command snooping in pscsi */ -void *transport_kmap_first_data_page(struct se_cmd *); -void transport_kunmap_first_data_page(struct se_cmd *); +void *transport_kmap_data_sg(struct se_cmd *); +void transport_kunmap_data_sg(struct se_cmd *); #endif /* TARGET_CORE_BACKEND_H */ diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index daf532bc721a..dc4e345a0163 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -582,6 +582,7 @@ struct se_cmd { struct scatterlist *t_data_sg; unsigned int t_data_nents; + void *t_data_vmap; struct scatterlist *t_bidi_data_sg; unsigned int t_bidi_data_nents; -- GitLab From 2f9bc894c67dbacae5a6a9875818d2a18a918d18 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 16 Jan 2012 23:33:48 -0800 Subject: [PATCH 00141/10698] iscsi-target: Fix discovery with INADDR_ANY and IN6ADDR_ANY_INIT This patch addresses a bug with sendtargets discovery where INADDR_ANY (0.0.0.0) + IN6ADDR_ANY_INIT ([0:0:0:0:0:0:0:0]) network portals where incorrectly being reported back to initiators instead of the address of the connecting interface. To address this, save local socket ->getname() output during iscsi login setup, and makes iscsit_build_sendtargets_response() return these TargetAddress keys when INADDR_ANY or IN6ADDR_ANY_INIT portals are in use. Reported-by: Dax Kelson Reported-by: Andy Grover Cc: David S. Miller Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 37 ++++++++++++++++++++--- drivers/target/iscsi/iscsi_target_core.h | 2 ++ drivers/target/iscsi/iscsi_target_login.c | 31 ++++++++++++++++--- 3 files changed, 62 insertions(+), 8 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 6e070e0a8393..44262908def5 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3164,6 +3164,30 @@ static int iscsit_send_task_mgt_rsp( return 0; } +static bool iscsit_check_inaddr_any(struct iscsi_np *np) +{ + bool ret = false; + + if (np->np_sockaddr.ss_family == AF_INET6) { + const struct sockaddr_in6 sin6 = { + .sin6_addr = IN6ADDR_ANY_INIT }; + struct sockaddr_in6 *sock_in6 = + (struct sockaddr_in6 *)&np->np_sockaddr; + + if (!memcmp(sock_in6->sin6_addr.s6_addr, + sin6.sin6_addr.s6_addr, 16)) + ret = true; + } else { + struct sockaddr_in * sock_in = + (struct sockaddr_in *)&np->np_sockaddr; + + if (sock_in->sin_addr.s_addr == INADDR_ANY) + ret = true; + } + + return ret; +} + static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) { char *payload = NULL; @@ -3213,12 +3237,17 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) spin_lock(&tpg->tpg_np_lock); list_for_each_entry(tpg_np, &tpg->tpg_gnp_list, tpg_np_list) { + struct iscsi_np *np = tpg_np->tpg_np; + bool inaddr_any = iscsit_check_inaddr_any(np); + len = sprintf(buf, "TargetAddress=" "%s%s%s:%hu,%hu", - (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ? - "[" : "", tpg_np->tpg_np->np_ip, - (tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ? - "]" : "", tpg_np->tpg_np->np_port, + (np->np_sockaddr.ss_family == AF_INET6) ? + "[" : "", (inaddr_any == false) ? + np->np_ip : conn->local_ip, + (np->np_sockaddr.ss_family == AF_INET6) ? + "]" : "", (inaddr_any == false) ? + np->np_port : conn->local_port, tpg->tpgt); len += 1; diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index ebf81fdbb5c5..0ec3b77a0c27 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -508,6 +508,7 @@ struct iscsi_conn { u16 cid; /* Remote TCP Port */ u16 login_port; + u16 local_port; int net_size; u32 auth_id; #define CONNFLAG_SCTP_STRUCT_FILE 0x01 @@ -527,6 +528,7 @@ struct iscsi_conn { unsigned char bad_hdr[ISCSI_HDR_LEN]; #define IPV6_ADDRESS_SPACE 48 unsigned char login_ip[IPV6_ADDRESS_SPACE]; + unsigned char local_ip[IPV6_ADDRESS_SPACE]; int conn_usage_count; int conn_waiting_on_uc; atomic_t check_immediate_queue; diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 373b0cc6abd8..ec47a7c5966e 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -615,8 +615,8 @@ static int iscsi_post_login_handler( } pr_debug("iSCSI Login successful on CID: %hu from %s to" - " %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip, - np->np_port, tpg->tpgt); + " %s:%hu,%hu\n", conn->cid, conn->login_ip, + conn->local_ip, conn->local_port, tpg->tpgt); list_add_tail(&conn->conn_list, &sess->sess_conn_list); atomic_inc(&sess->nconn); @@ -658,7 +658,8 @@ static int iscsi_post_login_handler( sess->session_state = TARG_SESS_STATE_LOGGED_IN; pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n", - conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt); + conn->cid, conn->login_ip, conn->local_ip, conn->local_port, + tpg->tpgt); spin_lock_bh(&sess->conn_lock); list_add_tail(&conn->conn_list, &sess->sess_conn_list); @@ -1020,6 +1021,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c", &sock_in6.sin6_addr.in6_u); conn->login_port = ntohs(sock_in6.sin6_port); + + if (conn->sock->ops->getname(conn->sock, + (struct sockaddr *)&sock_in6, &err, 0) < 0) { + pr_err("sock_ops->getname() failed.\n"); + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, + ISCSI_LOGIN_STATUS_TARGET_ERROR); + goto new_sess_out; + } + snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c", + &sock_in6.sin6_addr.in6_u); + conn->local_port = ntohs(sock_in6.sin6_port); + } else { memset(&sock_in, 0, sizeof(struct sockaddr_in)); @@ -1032,6 +1045,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) } sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr); conn->login_port = ntohs(sock_in.sin_port); + + if (conn->sock->ops->getname(conn->sock, + (struct sockaddr *)&sock_in, &err, 0) < 0) { + pr_err("sock_ops->getname() failed.\n"); + iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, + ISCSI_LOGIN_STATUS_TARGET_ERROR); + goto new_sess_out; + } + sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr); + conn->local_port = ntohs(sock_in.sin_port); } conn->network_transport = np->np_network_transport; @@ -1039,7 +1062,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) pr_debug("Received iSCSI login request from %s on %s Network" " Portal %s:%hu\n", conn->login_ip, (conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP", - np->np_ip, np->np_port); + conn->local_ip, conn->local_port); pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n"); conn->conn_state = TARG_CONN_STATE_IN_LOGIN; -- GitLab From bb1acb2ee038a6c13ee99e0b9fb44dacb4a9de84 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 17 Jan 2012 18:00:56 -0800 Subject: [PATCH 00142/10698] target: Return correct ASC for unimplemented VPD pages My draft of SPC-4 says: If the device server does not implement the requested vital product data page, then the command shall be terminated with CHECK CONDITION status, with the sense key set to ILLEGAL REQUEST, and the additional sense code set to INVALID FIELD IN CDB. Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_cdb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 07a3025d0622..370ad13930a4 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -729,7 +729,7 @@ int target_emulate_inquiry(struct se_task *task) } pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]); - cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE; + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; ret = -EINVAL; out_unmap: -- GitLab From bf0053550aebe56f3bb5dd793e9de69238b5b945 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 17 Jan 2012 18:00:57 -0800 Subject: [PATCH 00143/10698] target: Fail INQUIRY commands with EVPD==0 but PAGE CODE!=0 My draft of SPC-4 says: If the PAGE CODE field is not set to zero when the EVPD bit is set to zero, the command shall be terminated with CHECK CONDITION status, with the sense key set to ILLEGAL REQUEST, and the additional sense code set to INVALID FIELD IN CDB. Signed-off-by: Roland Dreier Cc: Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_cdb.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 370ad13930a4..a9bbf5a5cc27 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -698,6 +698,13 @@ int target_emulate_inquiry(struct se_task *task) int p, ret; if (!(cdb[1] & 0x1)) { + if (cdb[2]) { + pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n", + cdb[2]); + cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD; + return -EINVAL; + } + ret = target_emulate_inquiry_std(cmd); goto out; } -- GitLab From d6f802612af55cc1b3699d119a04dfa2fc8812a0 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 15:05:19 +0200 Subject: [PATCH 00144/10698] ath6kl: use netdev_features_t Commit c8f44affb7 ("net: introduce and use netdev_features_t for device features sets") added netdev_features_t to ndo_set_features. Change ath6kl to use the new type. This fixes a warning: ath6kl/main.c:1170: warning: initialization from incompatible pointer type Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 0a6d6e2be6e9..3a3b2cc9940d 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1021,7 +1021,8 @@ static struct net_device_stats *ath6kl_get_stats(struct net_device *dev) return &vif->net_stats; } -static int ath6kl_set_features(struct net_device *dev, u32 features) +static int ath6kl_set_features(struct net_device *dev, + netdev_features_t features) { struct ath6kl_vif *vif = netdev_priv(dev); struct ath6kl *ar = vif->ar; -- GitLab From 3462735dadb90efd5bed9d2b81222ed7da1390a0 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 15:05:32 +0200 Subject: [PATCH 00145/10698] ath6kl: remove -D__CHECK_ENDIAN__ from Makefile As drivers/net/wireless/ath/Makefile contains the flag to enable endian checks there's no need to have it in ath6kl makefile anymore. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index 707069303550..e24b61799158 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -33,5 +33,3 @@ ath6kl-y += txrx.o ath6kl-y += wmi.o ath6kl-y += sdio.o ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o - -ccflags-y += -D__CHECK_ENDIAN__ -- GitLab From e572602884c4f979cbba4fed413af24797fd01d9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 15:05:46 +0200 Subject: [PATCH 00146/10698] ath6kl: fix uninitialized warning in ath6kl_process_uapsdq() Before I commited patch c1762a3fe ("ath6kl: Add support for uAPSD") I did a minor change how up variable is initialised in ath6kl_process_uapsdq(). But I was sloppy and caused this compiler warning: txrx.c:88:5: warning: 'up' may be used uninitialized in this function Revert my change to fix the warning. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/txrx.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 91bbc1ffa493..dd6337142603 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -85,7 +85,7 @@ static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn, struct ath6kl *ar = vif->ar; bool is_apsdq_empty = false; struct ethhdr *datap = (struct ethhdr *) skb->data; - u8 up, traffic_class, *ip_hdr; + u8 up = 0, traffic_class, *ip_hdr; u16 ether_type; struct ath6kl_llc_snap_hdr *llc_hdr; @@ -122,8 +122,6 @@ static bool ath6kl_process_uapsdq(struct ath6kl_sta *conn, if (ether_type == IP_ETHERTYPE) up = ath6kl_wmi_determine_user_priority( ip_hdr, 0); - } else { - up = 0; } traffic_class = ath6kl_wmi_get_traffic_class(up); -- GitLab From cd23c1c9b8a2de64477a795ab5a9cd5278397f24 Mon Sep 17 00:00:00 2001 From: Alex Yang Date: Tue, 17 Jan 2012 15:32:29 +0200 Subject: [PATCH 00147/10698] ath6kl: add testmode 2 for 6003 ART Add testmode 2 for 6003 ART. When you insmod ath6kl_sdio.ko testmode=2, ath6kl will load ART firmware utf.bin and testscript nullTestFlow.bin. These files should be put in the firmware folder. kvalo: add "ath6kl:" to the title, word wrap the commit log and remove extra line in the code Signed-off-by: Alex Yang Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 8 ++ drivers/net/wireless/ath/ath6kl/init.c | 108 +++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index ba3953918e4c..f53594f2e537 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -125,6 +125,8 @@ struct ath6kl_fw_ie { #define AR6003_HW_2_1_1_OTP_FILE "otp.bin" #define AR6003_HW_2_1_1_FIRMWARE_FILE "athwlan.bin" #define AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" +#define AR6003_HW_2_1_1_UTF_FIRMWARE_FILE "utf.bin" +#define AR6003_HW_2_1_1_TESTSCRIPT_FILE "nullTestFlow.bin" #define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin" #define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ @@ -592,6 +594,7 @@ struct ath6kl { u32 board_addr; u32 refclk_hz; u32 uarttx_pin; + u32 testscript_addr; struct ath6kl_hw_fw { const char *dir; @@ -599,6 +602,8 @@ struct ath6kl { const char *fw; const char *tcmd; const char *patch; + const char *utf; + const char *testscript; } fw; const char *fw_board; @@ -624,6 +629,9 @@ struct ath6kl { u8 *fw_patch; size_t fw_patch_len; + u8 *fw_testscript; + size_t fw_testscript_len; + unsigned int fw_api; unsigned long fw_capabilities[ATH6KL_CAPABILITY_LEN]; diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index e5969c146302..b88f41dc3dfa 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -69,6 +69,7 @@ static const struct ath6kl_hw hw_list[] = { .reserved_ram_size = 512, .refclk_hz = 26000000, .uarttx_pin = 8, + .testscript_addr = 0x57ef74, .fw = { .dir = AR6003_HW_2_1_1_FW_DIR, @@ -76,6 +77,8 @@ static const struct ath6kl_hw hw_list[] = { .fw = AR6003_HW_2_1_1_FIRMWARE_FILE, .tcmd = AR6003_HW_2_1_1_TCMD_FIRMWARE_FILE, .patch = AR6003_HW_2_1_1_PATCH_FILE, + .utf = AR6003_HW_2_1_1_UTF_FIRMWARE_FILE, + .testscript = AR6003_HW_2_1_1_TESTSCRIPT_FILE, }, .fw_board = AR6003_HW_2_1_1_BOARD_DATA_FILE, @@ -620,6 +623,7 @@ void ath6kl_core_cleanup(struct ath6kl *ar) kfree(ar->fw_otp); kfree(ar->fw); kfree(ar->fw_patch); + kfree(ar->fw_testscript); ath6kl_deinit_ieee80211_hw(ar); } @@ -771,14 +775,25 @@ static int ath6kl_fetch_fw_file(struct ath6kl *ar) return 0; if (testmode) { - if (ar->hw.fw.tcmd == NULL) { - ath6kl_warn("testmode not supported\n"); - return -EOPNOTSUPP; - } + ath6kl_dbg(ATH6KL_DBG_BOOT, "testmode %d\n", + testmode); + if (testmode == 2) { + if (ar->hw.fw.utf == NULL) { + ath6kl_warn("testmode 2 not supported\n"); + return -EOPNOTSUPP; + } - snprintf(filename, sizeof(filename), "%s/%s", - ar->hw.fw.dir, ar->hw.fw.tcmd); + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.utf); + } else { + if (ar->hw.fw.tcmd == NULL) { + ath6kl_warn("testmode 1 not supported\n"); + return -EOPNOTSUPP; + } + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.tcmd); + } set_bit(TESTMODE, &ar->flag); goto get_fw; @@ -827,6 +842,34 @@ static int ath6kl_fetch_patch_file(struct ath6kl *ar) return 0; } +static int ath6kl_fetch_testscript_file(struct ath6kl *ar) +{ + char filename[100]; + int ret; + + if (testmode != 2) + return 0; + + if (ar->fw_testscript != NULL) + return 0; + + if (ar->hw.fw.testscript == NULL) + return 0; + + snprintf(filename, sizeof(filename), "%s/%s", + ar->hw.fw.dir, ar->hw.fw.testscript); + + ret = ath6kl_get_fw(ar, filename, &ar->fw_testscript, + &ar->fw_testscript_len); + if (ret) { + ath6kl_err("Failed to get testscript file %s: %d\n", + filename, ret); + return ret; + } + + return 0; +} + static int ath6kl_fetch_fw_api1(struct ath6kl *ar) { int ret; @@ -843,6 +886,10 @@ static int ath6kl_fetch_fw_api1(struct ath6kl *ar) if (ret) return ret; + ret = ath6kl_fetch_testscript_file(ar); + if (ret) + return ret; + return 0; } @@ -1266,6 +1313,50 @@ static int ath6kl_upload_patch(struct ath6kl *ar) return 0; } +static int ath6kl_upload_testscript(struct ath6kl *ar) +{ + u32 address, param; + int ret; + + if (testmode != 2) + return 0; + + if (ar->fw_testscript == NULL) + return 0; + + address = ar->hw.testscript_addr; + + ath6kl_dbg(ATH6KL_DBG_BOOT, "writing testscript to 0x%x (%zd B)\n", + address, ar->fw_testscript_len); + + ret = ath6kl_bmi_write(ar, address, ar->fw_testscript, + ar->fw_testscript_len); + if (ret) { + ath6kl_err("Failed to write testscript file: %d\n", ret); + return ret; + } + + param = address; + ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_ota_testscript)), + (unsigned char *) ¶m, 4); + + param = 4096; + ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_end_ram_reserve_sz)), + (unsigned char *) ¶m, 4); + + param = 1; + ath6kl_bmi_write(ar, + ath6kl_get_hi_item_addr(ar, + HI_ITEM(hi_test_apps_related)), + (unsigned char *) ¶m, 4); + + return 0; +} + static int ath6kl_init_upload(struct ath6kl *ar) { u32 param, options, sleep, address; @@ -1374,6 +1465,11 @@ static int ath6kl_init_upload(struct ath6kl *ar) if (status) return status; + /* Download the test script */ + status = ath6kl_upload_testscript(ar); + if (status) + return status; + /* Restore system sleep */ address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS; status = ath6kl_bmi_reg_write(ar, address, sleep); -- GitLab From c25889e8a6fdfc54618b192a80c94419ddb7949d Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:08:27 +0200 Subject: [PATCH 00148/10698] ath6kl: rename vif init and cleanup functions ath6kl_cfg80211_vif_init/cleanup() follow more closely the style used elsewhere in ath6kl. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 9 ++++----- drivers/net/wireless/ath/ath6kl/cfg80211.h | 2 ++ drivers/net/wireless/ath/ath6kl/core.h | 1 - drivers/net/wireless/ath/ath6kl/init.c | 5 +++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index a13ecec00702..7e92dc9799ac 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1401,7 +1401,7 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); - ath6kl_deinit_if_data(vif); + ath6kl_cfg80211_vif_cleanup(vif); return 0; } @@ -2806,7 +2806,7 @@ int ath6kl_register_ieee80211_hw(struct ath6kl *ar) return 0; } -static int ath6kl_init_if_data(struct ath6kl_vif *vif) +static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) { vif->aggr_cntxt = aggr_init(vif->ndev); if (!vif->aggr_cntxt) { @@ -2827,7 +2827,7 @@ static int ath6kl_init_if_data(struct ath6kl_vif *vif) return 0; } -void ath6kl_deinit_if_data(struct ath6kl_vif *vif) +void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif) { struct ath6kl *ar = vif->ar; struct ath6kl_mc_filter *mc_filter, *tmp; @@ -2880,8 +2880,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, ath6kl_init_control_info(vif); - /* TODO: Pass interface specific pointer instead of ar */ - if (ath6kl_init_if_data(vif)) + if (ath6kl_cfg80211_vif_init(vif)) goto err; if (register_netdevice(ndev)) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index 81f20a572315..aa961694cf99 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h @@ -53,6 +53,8 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, int ath6kl_cfg80211_resume(struct ath6kl *ar); +void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif); + void ath6kl_cfg80211_stop(struct ath6kl_vif *vif); void ath6kl_cfg80211_stop_all(struct ath6kl *ar); diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index f53594f2e537..bdeb254c259c 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -753,7 +753,6 @@ void ath6kl_wakeup_event(void *dev); void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, bool wait_fot_compltn, bool cold_reset); void ath6kl_init_control_info(struct ath6kl_vif *vif); -void ath6kl_deinit_if_data(struct ath6kl_vif *vif); void ath6kl_core_free(struct ath6kl *ar); struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready); diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index b88f41dc3dfa..3cc4e0842add 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -1811,7 +1811,7 @@ int ath6kl_core_init(struct ath6kl *ar) ath6kl_htc_flush_rx_buf(ar->htc_target); ath6kl_cleanup_amsdu_rxbufs(ar); rtnl_lock(); - ath6kl_deinit_if_data(netdev_priv(ndev)); + ath6kl_cfg80211_vif_cleanup(netdev_priv(ndev)); rtnl_unlock(); wiphy_unregister(ar->wiphy); err_debug_init: @@ -1832,6 +1832,7 @@ int ath6kl_core_init(struct ath6kl *ar) return ret; } +/* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) { static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -1877,7 +1878,7 @@ void ath6kl_stop_txrx(struct ath6kl *ar) spin_unlock_bh(&ar->list_lock); ath6kl_cleanup_vif(vif, test_bit(WMI_READY, &ar->flag)); rtnl_lock(); - ath6kl_deinit_if_data(vif); + ath6kl_cfg80211_vif_cleanup(vif); rtnl_unlock(); spin_lock_bh(&ar->list_lock); } -- GitLab From 46d33a21cfa531f4271c3f0b7b87a295f30f9e6a Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:08:40 +0200 Subject: [PATCH 00149/10698] ath6kl: unify cfg80211 init/cleanup functions Group them together and change the naming to follow the common style in ath6kl. No functional changes. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/cfg80211.c | 109 +++++++++++---------- drivers/net/wireless/ath/ath6kl/cfg80211.h | 6 +- drivers/net/wireless/ath/ath6kl/init.c | 4 +- 3 files changed, 62 insertions(+), 57 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 7e92dc9799ac..44fdd39e1701 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -2755,57 +2755,6 @@ struct ath6kl *ath6kl_core_alloc(struct device *dev) return ar; } -int ath6kl_register_ieee80211_hw(struct ath6kl *ar) -{ - struct wiphy *wiphy = ar->wiphy; - int ret; - - wiphy->mgmt_stypes = ath6kl_mgmt_stypes; - - wiphy->max_remain_on_channel_duration = 5000; - - /* set device pointer for wiphy */ - set_wiphy_dev(wiphy, ar->dev); - - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP); - if (ar->p2p) { - wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_CLIENT); - } - - /* max num of ssids that can be probed during scanning */ - wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; - wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ - wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; - wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; - wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - wiphy->cipher_suites = cipher_suites; - wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); - - wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | - WIPHY_WOWLAN_DISCONNECT | - WIPHY_WOWLAN_GTK_REKEY_FAILURE | - WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | - WIPHY_WOWLAN_EAP_IDENTITY_REQ | - WIPHY_WOWLAN_4WAY_HANDSHAKE; - wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; - wiphy->wowlan.pattern_min_len = 1; - wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; - - wiphy->max_sched_scan_ssids = 10; - - ret = wiphy_register(wiphy); - if (ret < 0) { - ath6kl_err("couldn't register wiphy device\n"); - return ret; - } - - return 0; -} - static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) { vif->aggr_cntxt = aggr_init(vif->ndev); @@ -2907,8 +2856,64 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, return NULL; } -void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar) +int ath6kl_cfg80211_init(struct ath6kl *ar) +{ + struct wiphy *wiphy = ar->wiphy; + int ret; + + wiphy->mgmt_stypes = ath6kl_mgmt_stypes; + + wiphy->max_remain_on_channel_duration = 5000; + + /* set device pointer for wiphy */ + set_wiphy_dev(wiphy, ar->dev); + + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP); + if (ar->p2p) { + wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_CLIENT); + } + + /* max num of ssids that can be probed during scanning */ + wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; + wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ + wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; + wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + wiphy->cipher_suites = cipher_suites; + wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + + wiphy->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_EAP_IDENTITY_REQ | + WIPHY_WOWLAN_4WAY_HANDSHAKE; + wiphy->wowlan.n_patterns = WOW_MAX_FILTERS_PER_LIST; + wiphy->wowlan.pattern_min_len = 1; + wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; + + wiphy->max_sched_scan_ssids = 10; + + ret = wiphy_register(wiphy); + if (ret < 0) { + ath6kl_err("couldn't register wiphy device\n"); + return ret; + } + + return 0; +} + +void ath6kl_cfg80211_cleanup(struct ath6kl *ar) { wiphy_unregister(ar->wiphy); + + /* + * FIXME: should be removed as we remove wiphy in + * ath6kl_core_free(). Most likely this causes a use after free. + */ wiphy_free(ar->wiphy); } diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index aa961694cf99..08d97691039c 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h @@ -27,10 +27,7 @@ enum ath6kl_cfg_suspend_mode { struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, enum nl80211_iftype type, u8 fw_vif_idx, u8 nw_type); -int ath6kl_register_ieee80211_hw(struct ath6kl *ar); struct ath6kl *ath6kl_core_alloc(struct device *dev); -void ath6kl_deinit_ieee80211_hw(struct ath6kl *ar); - void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, @@ -58,4 +55,7 @@ void ath6kl_cfg80211_vif_cleanup(struct ath6kl_vif *vif); void ath6kl_cfg80211_stop(struct ath6kl_vif *vif); void ath6kl_cfg80211_stop_all(struct ath6kl *ar); +int ath6kl_cfg80211_init(struct ath6kl *ar); +void ath6kl_cfg80211_cleanup(struct ath6kl *ar); + #endif /* ATH6KL_CFG80211_H */ diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 3cc4e0842add..7e56a6aa70b9 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -625,7 +625,7 @@ void ath6kl_core_cleanup(struct ath6kl *ar) kfree(ar->fw_patch); kfree(ar->fw_testscript); - ath6kl_deinit_ieee80211_hw(ar); + ath6kl_cfg80211_cleanup(ar); } /* firmware upload */ @@ -1722,7 +1722,7 @@ int ath6kl_core_init(struct ath6kl *ar) ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); - ret = ath6kl_register_ieee80211_hw(ar); + ret = ath6kl_cfg80211_init(ar); if (ret) goto err_node_cleanup; -- GitLab From f29af97853599e9537191c4f33f8ac87f3f503a9 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:08:56 +0200 Subject: [PATCH 00150/10698] ath6kl: add ATH6KL_CONF_UART_DEBUG Add ATH6KL_CONF_UART_DEBUG which is set whenever uart_debug module parameter is enabled. This way we can keep the uart_debug parameter static when core.c file is introduced. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/core.h | 1 + drivers/net/wireless/ath/ath6kl/init.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index bdeb254c259c..78c0402e2d33 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -197,6 +197,7 @@ struct ath6kl_fw_ie { #define ATH6KL_CONF_ENABLE_11N BIT(2) #define ATH6KL_CONF_ENABLE_TX_BURST BIT(3) #define ATH6KL_CONF_SUSPEND_CUTPOWER BIT(4) +#define ATH6KL_CONF_UART_DEBUG BIT(5) enum wlan_low_pwr_state { WLAN_POWER_STATE_ON, diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 7e56a6aa70b9..2804921d5d8a 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -469,7 +469,7 @@ int ath6kl_configure_target(struct ath6kl *ar) u8 fw_iftype, fw_mode = 0, fw_submode = 0; int i, status; - param = uart_debug; + param = !!(ar->conf_flags & ATH6KL_CONF_UART_DEBUG); if (ath6kl_bmi_write(ar, ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_serial_enable)), (u8 *)¶m, 4)) { ath6kl_err("bmi_write_memory for uart debug failed\n"); @@ -1775,6 +1775,9 @@ int ath6kl_core_init(struct ath6kl *ar) if (suspend_cutpower) ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER; + if (uart_debug) + ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; + ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | -- GitLab From 482835ce02726652becc36b64522cbabc0adbeee Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 18 Jan 2012 10:24:17 +0100 Subject: [PATCH 00151/10698] sh: sh7757lcr: update to the new MMCIF DMA configuration Specifying MMCIF DMA slave IDs via a struct sh_mmcif_dma instance is deprecated. Update sh7757lcr to specify slave IDs embedded in struct sh_mmcif_plat_data. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Paul Mundt --- arch/sh/boards/board-sh7757lcr.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/sh/boards/board-sh7757lcr.c b/arch/sh/boards/board-sh7757lcr.c index 33dc5b6e8e17..8d2ae109a83a 100644 --- a/arch/sh/boards/board-sh7757lcr.c +++ b/arch/sh/boards/board-sh7757lcr.c @@ -210,21 +210,13 @@ static struct resource sh_mmcif_resources[] = { }, }; -static struct sh_mmcif_dma sh7757lcr_mmcif_dma = { - .chan_priv_tx = { - .slave_id = SHDMA_SLAVE_MMCIF_TX, - }, - .chan_priv_rx = { - .slave_id = SHDMA_SLAVE_MMCIF_RX, - } -}; - static struct sh_mmcif_plat_data sh_mmcif_plat = { - .dma = &sh7757lcr_mmcif_dma, .sup_pclk = 0x0f, .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, .ocr = MMC_VDD_32_33 | MMC_VDD_33_34, + .slave_id_tx = SHDMA_SLAVE_MMCIF_TX, + .slave_id_rx = SHDMA_SLAVE_MMCIF_RX, }; static struct platform_device sh_mmcif_device = { -- GitLab From 833218f16b1fbfdff0dbb9ac477cf0c6e85cd4f5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 18 Jan 2012 01:44:22 -0800 Subject: [PATCH 00152/10698] sh: clock-sh7724: fixup sh_fsi clock settings sh_fsi needs HWBLK_SPU clock on sh7724 Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4a/clock-sh7724.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c index b3c039a5064a..70bd96646f42 100644 --- a/arch/sh/kernel/cpu/sh4a/clock-sh7724.c +++ b/arch/sh/kernel/cpu/sh4a/clock-sh7724.c @@ -343,7 +343,7 @@ static struct clk_lookup lookups[] = { CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[HWBLK_CEU1]), CLKDEV_CON_ID("beu1", &mstp_clks[HWBLK_BEU1]), CLKDEV_CON_ID("2ddmac0", &mstp_clks[HWBLK_2DDMAC]), - CLKDEV_CON_ID("spu0", &mstp_clks[HWBLK_SPU]), + CLKDEV_DEV_ID("sh_fsi.0", &mstp_clks[HWBLK_SPU]), CLKDEV_CON_ID("jpu0", &mstp_clks[HWBLK_JPU]), CLKDEV_DEV_ID("sh-vou.0", &mstp_clks[HWBLK_VOU]), CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU0]), -- GitLab From 45eaa78f757b3b3992ca02c753764665e9fba0a4 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:05 +0200 Subject: [PATCH 00153/10698] ath6kl: create core.c Currently core functions are spread between various files, group all the functions into file and rename the functions to follow the style used elsewhere in the driver. This will make it easier to a separate core module. Also fix a bug where wiphy is freed too early. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/Makefile | 1 + drivers/net/wireless/ath/ath6kl/cfg80211.c | 94 ++----- drivers/net/wireless/ath/ath6kl/cfg80211.h | 4 +- drivers/net/wireless/ath/ath6kl/common.h | 3 - drivers/net/wireless/ath/ath6kl/core.c | 292 +++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/core.h | 9 +- drivers/net/wireless/ath/ath6kl/init.c | 213 +-------------- drivers/net/wireless/ath/ath6kl/sdio.c | 4 +- 8 files changed, 332 insertions(+), 288 deletions(-) create mode 100644 drivers/net/wireless/ath/ath6kl/core.c diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index e24b61799158..854694b26a4b 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -31,5 +31,6 @@ ath6kl-y += init.o ath6kl-y += main.o ath6kl-y += txrx.o ath6kl-y += wmi.o +ath6kl-y += core.o ath6kl-y += sdio.o ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 44fdd39e1701..7ff9806de50b 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -23,10 +23,6 @@ #include "hif-ops.h" #include "testmode.h" -static unsigned int ath6kl_p2p; - -module_param(ath6kl_p2p, uint, 0644); - #define RATETAB_ENT(_rate, _rateid, _flags) { \ .bitrate = (_rate), \ .flags = (_flags), \ @@ -2693,68 +2689,6 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar) ath6kl_cfg80211_stop(vif); } -struct ath6kl *ath6kl_core_alloc(struct device *dev) -{ - struct ath6kl *ar; - struct wiphy *wiphy; - u8 ctr; - - /* create a new wiphy for use with cfg80211 */ - wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl)); - - if (!wiphy) { - ath6kl_err("couldn't allocate wiphy device\n"); - return NULL; - } - - ar = wiphy_priv(wiphy); - ar->p2p = !!ath6kl_p2p; - ar->wiphy = wiphy; - ar->dev = dev; - - ar->vif_max = 1; - - ar->max_norm_iface = 1; - - spin_lock_init(&ar->lock); - spin_lock_init(&ar->mcastpsq_lock); - spin_lock_init(&ar->list_lock); - - init_waitqueue_head(&ar->event_wq); - sema_init(&ar->sem, 1); - - INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue); - INIT_LIST_HEAD(&ar->vif_list); - - clear_bit(WMI_ENABLED, &ar->flag); - clear_bit(SKIP_SCAN, &ar->flag); - clear_bit(DESTROY_IN_PROGRESS, &ar->flag); - - ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL; - ar->tx_pwr = 0; - - ar->intra_bss = 1; - ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; - - ar->state = ATH6KL_STATE_OFF; - - memset((u8 *)ar->sta_list, 0, - AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); - - /* Init the PS queues */ - for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { - spin_lock_init(&ar->sta_list[ctr].psq_lock); - skb_queue_head_init(&ar->sta_list[ctr].psq); - skb_queue_head_init(&ar->sta_list[ctr].apsdq); - } - - skb_queue_head_init(&ar->mcastpsq); - - memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); - - return ar; -} - static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif) { vif->aggr_cntxt = aggr_init(vif->ndev); @@ -2910,10 +2844,30 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) void ath6kl_cfg80211_cleanup(struct ath6kl *ar) { wiphy_unregister(ar->wiphy); +} - /* - * FIXME: should be removed as we remove wiphy in - * ath6kl_core_free(). Most likely this causes a use after free. - */ +struct ath6kl *ath6kl_cfg80211_create(void) +{ + struct ath6kl *ar; + struct wiphy *wiphy; + + /* create a new wiphy for use with cfg80211 */ + wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl)); + + if (!wiphy) { + ath6kl_err("couldn't allocate wiphy device\n"); + return NULL; + } + + ar = wiphy_priv(wiphy); + ar->wiphy = wiphy; + + return ar; +} + +/* Note: ar variable must not be accessed after calling this! */ +void ath6kl_cfg80211_destroy(struct ath6kl *ar) +{ wiphy_free(ar->wiphy); } + diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index 08d97691039c..3c693b7c0efd 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h @@ -27,7 +27,6 @@ enum ath6kl_cfg_suspend_mode { struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, enum nl80211_iftype type, u8 fw_vif_idx, u8 nw_type); -struct ath6kl *ath6kl_core_alloc(struct device *dev); void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, @@ -58,4 +57,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar); int ath6kl_cfg80211_init(struct ath6kl *ar); void ath6kl_cfg80211_cleanup(struct ath6kl *ar); +struct ath6kl *ath6kl_cfg80211_create(void); +void ath6kl_cfg80211_destroy(struct ath6kl *ar); + #endif /* ATH6KL_CFG80211_H */ diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index bfd6597763da..f89f1e180da3 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h @@ -79,8 +79,5 @@ struct ath6kl; enum htc_credit_dist_reason; struct ath6kl_htc_credit_info; -struct ath6kl *ath6kl_core_alloc(struct device *sdev); -int ath6kl_core_init(struct ath6kl *ar); -void ath6kl_core_cleanup(struct ath6kl *ar); struct sk_buff *ath6kl_buf_alloc(int size); #endif /* COMMON_H */ diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c new file mode 100644 index 000000000000..40fad5ec9366 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2004-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "core.h" + +#include + +#include "debug.h" +#include "hif-ops.h" +#include "cfg80211.h" + +unsigned int debug_mask; +static bool suspend_cutpower; +static unsigned int uart_debug; +static unsigned int ath6kl_p2p; + +module_param(debug_mask, uint, 0644); +module_param(suspend_cutpower, bool, 0444); +module_param(uart_debug, uint, 0644); +module_param(ath6kl_p2p, uint, 0644); + +int ath6kl_core_init(struct ath6kl *ar) +{ + struct ath6kl_bmi_target_info targ_info; + struct net_device *ndev; + int ret = 0, i; + + ar->ath6kl_wq = create_singlethread_workqueue("ath6kl"); + if (!ar->ath6kl_wq) + return -ENOMEM; + + ret = ath6kl_bmi_init(ar); + if (ret) + goto err_wq; + + /* + * Turn on power to get hardware (target) version and leave power + * on delibrately as we will boot the hardware anyway within few + * seconds. + */ + ret = ath6kl_hif_power_on(ar); + if (ret) + goto err_bmi_cleanup; + + ret = ath6kl_bmi_get_target_info(ar, &targ_info); + if (ret) + goto err_power_off; + + ar->version.target_ver = le32_to_cpu(targ_info.version); + ar->target_type = le32_to_cpu(targ_info.type); + ar->wiphy->hw_version = le32_to_cpu(targ_info.version); + + ret = ath6kl_init_hw_params(ar); + if (ret) + goto err_power_off; + + ar->htc_target = ath6kl_htc_create(ar); + + if (!ar->htc_target) { + ret = -ENOMEM; + goto err_power_off; + } + + ret = ath6kl_init_fetch_firmwares(ar); + if (ret) + goto err_htc_cleanup; + + /* FIXME: we should free all firmwares in the error cases below */ + + /* Indicate that WMI is enabled (although not ready yet) */ + set_bit(WMI_ENABLED, &ar->flag); + ar->wmi = ath6kl_wmi_init(ar); + if (!ar->wmi) { + ath6kl_err("failed to initialize wmi\n"); + ret = -EIO; + goto err_htc_cleanup; + } + + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); + + ret = ath6kl_cfg80211_init(ar); + if (ret) + goto err_node_cleanup; + + ret = ath6kl_debug_init(ar); + if (ret) { + wiphy_unregister(ar->wiphy); + goto err_node_cleanup; + } + + for (i = 0; i < ar->vif_max; i++) + ar->avail_idx_map |= BIT(i); + + rtnl_lock(); + + /* Add an initial station interface */ + ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0, + INFRA_NETWORK); + + rtnl_unlock(); + + if (!ndev) { + ath6kl_err("Failed to instantiate a network device\n"); + ret = -ENOMEM; + wiphy_unregister(ar->wiphy); + goto err_debug_init; + } + + + ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n", + __func__, ndev->name, ndev, ar); + + /* setup access class priority mappings */ + ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */ + ar->ac_stream_pri_map[WMM_AC_BE] = 1; + ar->ac_stream_pri_map[WMM_AC_VI] = 2; + ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */ + + /* give our connected endpoints some buffers */ + ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep); + ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]); + + /* allocate some buffers that handle larger AMSDU frames */ + ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS); + + ath6kl_cookie_init(ar); + + ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | + ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; + + if (suspend_cutpower) + ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER; + + if (uart_debug) + ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; + + ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | + WIPHY_FLAG_HAVE_AP_SME | + WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | + WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; + + if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) + ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + + ar->wiphy->probe_resp_offload = + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; + + set_bit(FIRST_BOOT, &ar->flag); + + ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; + + ret = ath6kl_init_hw_start(ar); + if (ret) { + ath6kl_err("Failed to start hardware: %d\n", ret); + goto err_rxbuf_cleanup; + } + + /* + * Set mac address which is received in ready event + * FIXME: Move to ath6kl_interface_add() + */ + memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); + + return ret; + +err_rxbuf_cleanup: + ath6kl_htc_flush_rx_buf(ar->htc_target); + ath6kl_cleanup_amsdu_rxbufs(ar); + rtnl_lock(); + ath6kl_cfg80211_vif_cleanup(netdev_priv(ndev)); + rtnl_unlock(); + wiphy_unregister(ar->wiphy); +err_debug_init: + ath6kl_debug_cleanup(ar); +err_node_cleanup: + ath6kl_wmi_shutdown(ar->wmi); + clear_bit(WMI_ENABLED, &ar->flag); + ar->wmi = NULL; +err_htc_cleanup: + ath6kl_htc_cleanup(ar->htc_target); +err_power_off: + ath6kl_hif_power_off(ar); +err_bmi_cleanup: + ath6kl_bmi_cleanup(ar); +err_wq: + destroy_workqueue(ar->ath6kl_wq); + + return ret; +} + +struct ath6kl *ath6kl_core_create(struct device *dev) +{ + struct ath6kl *ar; + u8 ctr; + + ar = ath6kl_cfg80211_create(); + if (!ar) + return NULL; + + ar->p2p = !!ath6kl_p2p; + ar->dev = dev; + + ar->vif_max = 1; + + ar->max_norm_iface = 1; + + spin_lock_init(&ar->lock); + spin_lock_init(&ar->mcastpsq_lock); + spin_lock_init(&ar->list_lock); + + init_waitqueue_head(&ar->event_wq); + sema_init(&ar->sem, 1); + + INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue); + INIT_LIST_HEAD(&ar->vif_list); + + clear_bit(WMI_ENABLED, &ar->flag); + clear_bit(SKIP_SCAN, &ar->flag); + clear_bit(DESTROY_IN_PROGRESS, &ar->flag); + + ar->listen_intvl_b = A_DEFAULT_LISTEN_INTERVAL; + ar->tx_pwr = 0; + + ar->intra_bss = 1; + ar->lrssi_roam_threshold = DEF_LRSSI_ROAM_THRESHOLD; + + ar->state = ATH6KL_STATE_OFF; + + memset((u8 *)ar->sta_list, 0, + AP_MAX_NUM_STA * sizeof(struct ath6kl_sta)); + + /* Init the PS queues */ + for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) { + spin_lock_init(&ar->sta_list[ctr].psq_lock); + skb_queue_head_init(&ar->sta_list[ctr].psq); + skb_queue_head_init(&ar->sta_list[ctr].apsdq); + } + + skb_queue_head_init(&ar->mcastpsq); + + memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3); + + return ar; +} + +void ath6kl_core_cleanup(struct ath6kl *ar) +{ + ath6kl_hif_power_off(ar); + + destroy_workqueue(ar->ath6kl_wq); + + if (ar->htc_target) + ath6kl_htc_cleanup(ar->htc_target); + + ath6kl_cookie_cleanup(ar); + + ath6kl_cleanup_amsdu_rxbufs(ar); + + ath6kl_bmi_cleanup(ar); + + ath6kl_debug_cleanup(ar); + + kfree(ar->fw_board); + kfree(ar->fw_otp); + kfree(ar->fw); + kfree(ar->fw_patch); + kfree(ar->fw_testscript); + + ath6kl_cfg80211_cleanup(ar); +} + +void ath6kl_core_destroy(struct ath6kl *ar) +{ + ath6kl_cfg80211_destroy(ar); +} + diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 78c0402e2d33..67b22e4bbcc2 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -754,11 +754,18 @@ void ath6kl_wakeup_event(void *dev); void ath6kl_reset_device(struct ath6kl *ar, u32 target_type, bool wait_fot_compltn, bool cold_reset); void ath6kl_init_control_info(struct ath6kl_vif *vif); -void ath6kl_core_free(struct ath6kl *ar); struct ath6kl_vif *ath6kl_vif_first(struct ath6kl *ar); void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready); int ath6kl_init_hw_start(struct ath6kl *ar); int ath6kl_init_hw_stop(struct ath6kl *ar); +int ath6kl_init_fetch_firmwares(struct ath6kl *ar); +int ath6kl_init_hw_params(struct ath6kl *ar); + void ath6kl_check_wow_status(struct ath6kl *ar); +struct ath6kl *ath6kl_core_create(struct device *dev); +int ath6kl_core_init(struct ath6kl *ar); +void ath6kl_core_cleanup(struct ath6kl *ar); +void ath6kl_core_destroy(struct ath6kl *ar); + #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 2804921d5d8a..b8252ced0968 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -25,15 +25,9 @@ #include "debug.h" #include "hif-ops.h" -unsigned int debug_mask; static unsigned int testmode; -static bool suspend_cutpower; -static unsigned int uart_debug; -module_param(debug_mask, uint, 0644); module_param(testmode, uint, 0644); -module_param(suspend_cutpower, bool, 0444); -module_param(uart_debug, uint, 0644); static const struct ath6kl_hw hw_list[] = { { @@ -597,37 +591,6 @@ int ath6kl_configure_target(struct ath6kl *ar) return 0; } -void ath6kl_core_free(struct ath6kl *ar) -{ - wiphy_free(ar->wiphy); -} - -void ath6kl_core_cleanup(struct ath6kl *ar) -{ - ath6kl_hif_power_off(ar); - - destroy_workqueue(ar->ath6kl_wq); - - if (ar->htc_target) - ath6kl_htc_cleanup(ar->htc_target); - - ath6kl_cookie_cleanup(ar); - - ath6kl_cleanup_amsdu_rxbufs(ar); - - ath6kl_bmi_cleanup(ar); - - ath6kl_debug_cleanup(ar); - - kfree(ar->fw_board); - kfree(ar->fw_otp); - kfree(ar->fw); - kfree(ar->fw_patch); - kfree(ar->fw_testscript); - - ath6kl_cfg80211_cleanup(ar); -} - /* firmware upload */ static int ath6kl_get_fw(struct ath6kl *ar, const char *filename, u8 **fw, size_t *fw_len) @@ -1065,7 +1028,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) return ret; } -static int ath6kl_fetch_firmwares(struct ath6kl *ar) +int ath6kl_init_fetch_firmwares(struct ath6kl *ar) { int ret; @@ -1485,7 +1448,7 @@ static int ath6kl_init_upload(struct ath6kl *ar) return status; } -static int ath6kl_init_hw_params(struct ath6kl *ar) +int ath6kl_init_hw_params(struct ath6kl *ar) { const struct ath6kl_hw *hw; int i; @@ -1663,178 +1626,6 @@ int ath6kl_init_hw_stop(struct ath6kl *ar) return 0; } -int ath6kl_core_init(struct ath6kl *ar) -{ - struct ath6kl_bmi_target_info targ_info; - struct net_device *ndev; - int ret = 0, i; - - ar->ath6kl_wq = create_singlethread_workqueue("ath6kl"); - if (!ar->ath6kl_wq) - return -ENOMEM; - - ret = ath6kl_bmi_init(ar); - if (ret) - goto err_wq; - - /* - * Turn on power to get hardware (target) version and leave power - * on delibrately as we will boot the hardware anyway within few - * seconds. - */ - ret = ath6kl_hif_power_on(ar); - if (ret) - goto err_bmi_cleanup; - - ret = ath6kl_bmi_get_target_info(ar, &targ_info); - if (ret) - goto err_power_off; - - ar->version.target_ver = le32_to_cpu(targ_info.version); - ar->target_type = le32_to_cpu(targ_info.type); - ar->wiphy->hw_version = le32_to_cpu(targ_info.version); - - ret = ath6kl_init_hw_params(ar); - if (ret) - goto err_power_off; - - ar->htc_target = ath6kl_htc_create(ar); - - if (!ar->htc_target) { - ret = -ENOMEM; - goto err_power_off; - } - - ret = ath6kl_fetch_firmwares(ar); - if (ret) - goto err_htc_cleanup; - - /* FIXME: we should free all firmwares in the error cases below */ - - /* Indicate that WMI is enabled (although not ready yet) */ - set_bit(WMI_ENABLED, &ar->flag); - ar->wmi = ath6kl_wmi_init(ar); - if (!ar->wmi) { - ath6kl_err("failed to initialize wmi\n"); - ret = -EIO; - goto err_htc_cleanup; - } - - ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi); - - ret = ath6kl_cfg80211_init(ar); - if (ret) - goto err_node_cleanup; - - ret = ath6kl_debug_init(ar); - if (ret) { - wiphy_unregister(ar->wiphy); - goto err_node_cleanup; - } - - for (i = 0; i < ar->vif_max; i++) - ar->avail_idx_map |= BIT(i); - - rtnl_lock(); - - /* Add an initial station interface */ - ndev = ath6kl_interface_add(ar, "wlan%d", NL80211_IFTYPE_STATION, 0, - INFRA_NETWORK); - - rtnl_unlock(); - - if (!ndev) { - ath6kl_err("Failed to instantiate a network device\n"); - ret = -ENOMEM; - wiphy_unregister(ar->wiphy); - goto err_debug_init; - } - - - ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n", - __func__, ndev->name, ndev, ar); - - /* setup access class priority mappings */ - ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */ - ar->ac_stream_pri_map[WMM_AC_BE] = 1; - ar->ac_stream_pri_map[WMM_AC_VI] = 2; - ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */ - - /* give our connected endpoints some buffers */ - ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep); - ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]); - - /* allocate some buffers that handle larger AMSDU frames */ - ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS); - - ath6kl_cookie_init(ar); - - ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER | - ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST; - - if (suspend_cutpower) - ar->conf_flags |= ATH6KL_CONF_SUSPEND_CUTPOWER; - - if (uart_debug) - ar->conf_flags |= ATH6KL_CONF_UART_DEBUG; - - ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | - WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | - WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; - - if (test_bit(ATH6KL_FW_CAPABILITY_SCHED_SCAN, ar->fw_capabilities)) - ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; - - ar->wiphy->probe_resp_offload = - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; - - set_bit(FIRST_BOOT, &ar->flag); - - ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; - - ret = ath6kl_init_hw_start(ar); - if (ret) { - ath6kl_err("Failed to start hardware: %d\n", ret); - goto err_rxbuf_cleanup; - } - - /* - * Set mac address which is received in ready event - * FIXME: Move to ath6kl_interface_add() - */ - memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); - - return ret; - -err_rxbuf_cleanup: - ath6kl_htc_flush_rx_buf(ar->htc_target); - ath6kl_cleanup_amsdu_rxbufs(ar); - rtnl_lock(); - ath6kl_cfg80211_vif_cleanup(netdev_priv(ndev)); - rtnl_unlock(); - wiphy_unregister(ar->wiphy); -err_debug_init: - ath6kl_debug_cleanup(ar); -err_node_cleanup: - ath6kl_wmi_shutdown(ar->wmi); - clear_bit(WMI_ENABLED, &ar->flag); - ar->wmi = NULL; -err_htc_cleanup: - ath6kl_htc_cleanup(ar->htc_target); -err_power_off: - ath6kl_hif_power_off(ar); -err_bmi_cleanup: - ath6kl_bmi_cleanup(ar); -err_wq: - destroy_workqueue(ar->ath6kl_wq); - - return ret; -} - /* FIXME: move this to cfg80211.c and rename to ath6kl_cfg80211_vif_stop() */ void ath6kl_cleanup_vif(struct ath6kl_vif *vif, bool wmi_ready) { diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 662b47dc71e5..bef32ecea792 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -1261,7 +1261,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, for (count = 0; count < BUS_REQUEST_MAX_NUM; count++) ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]); - ar = ath6kl_core_alloc(&ar_sdio->func->dev); + ar = ath6kl_core_create(&ar_sdio->func->dev); if (!ar) { ath6kl_err("Failed to alloc ath6kl core\n"); ret = -ENOMEM; @@ -1291,7 +1291,7 @@ static int ath6kl_sdio_probe(struct sdio_func *func, return ret; err_core_alloc: - ath6kl_core_free(ar_sdio->ar); + ath6kl_core_destroy(ar_sdio->ar); err_dma: kfree(ar_sdio->dma_buffer); err_hif: -- GitLab From 5afa5aa79680ee107fef1195c80f5f67c54b6691 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:19 +0200 Subject: [PATCH 00154/10698] ath6kl: get rid of AR_DBG_LVL_CHECK() We don't need it as debug calls already have a log level and compiler should be smart enough to optimise away the code when ath6kl debug code is not enabled. Also it makes it easier to abstract core code to ath6kl_core.ko. In ath6kl_dump_registers() I had to change the debug level from ANY to IRQ as I removed the AR_DBG_LVL_CHECK() check before calling the function. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 35 +++++++++++-------------- drivers/net/wireless/ath/ath6kl/debug.h | 2 -- drivers/net/wireless/ath/ath6kl/hif.c | 5 ++-- drivers/net/wireless/ath/ath6kl/wmi.c | 3 --- 4 files changed, 18 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index fa7243b41442..bd2f1fae72a9 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -82,31 +82,31 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, struct ath6kl_irq_enable_reg *irq_enable_reg) { - ath6kl_dbg(ATH6KL_DBG_ANY, ("<------- Register Table -------->\n")); + ath6kl_dbg(ATH6KL_DBG_IRQ, ("<------- Register Table -------->\n")); if (irq_proc_reg != NULL) { - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Host Int status: 0x%x\n", irq_proc_reg->host_int_status); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "CPU Int status: 0x%x\n", irq_proc_reg->cpu_int_status); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Error Int status: 0x%x\n", irq_proc_reg->error_int_status); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status: 0x%x\n", irq_proc_reg->counter_int_status); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Mbox Frame: 0x%x\n", irq_proc_reg->mbox_frame); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Rx Lookahead Valid: 0x%x\n", irq_proc_reg->rx_lkahd_valid); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Rx Lookahead 0: 0x%x\n", irq_proc_reg->rx_lkahd[0]); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Rx Lookahead 1: 0x%x\n", irq_proc_reg->rx_lkahd[1]); @@ -115,16 +115,16 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, * If the target supports GMBOX hardware, dump some * additional state. */ - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "GMBOX Host Int status 2: 0x%x\n", irq_proc_reg->host_int_status2); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "GMBOX RX Avail: 0x%x\n", irq_proc_reg->gmbox_rx_avail); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "GMBOX lookahead alias 0: 0x%x\n", irq_proc_reg->rx_gmbox_lkahd_alias[0]); - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "GMBOX lookahead alias 1: 0x%x\n", irq_proc_reg->rx_gmbox_lkahd_alias[1]); } @@ -132,13 +132,13 @@ void ath6kl_dump_registers(struct ath6kl_device *dev, } if (irq_enable_reg != NULL) { - ath6kl_dbg(ATH6KL_DBG_ANY, + ath6kl_dbg(ATH6KL_DBG_IRQ, "Int status Enable: 0x%x\n", irq_enable_reg->int_status_en); - ath6kl_dbg(ATH6KL_DBG_ANY, "Counter Int status Enable: 0x%x\n", + ath6kl_dbg(ATH6KL_DBG_IRQ, "Counter Int status Enable: 0x%x\n", irq_enable_reg->cntr_int_status_en); } - ath6kl_dbg(ATH6KL_DBG_ANY, "<------------------------------->\n"); + ath6kl_dbg(ATH6KL_DBG_IRQ, "<------------------------------->\n"); } static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist) @@ -175,9 +175,6 @@ void dump_cred_dist_stats(struct htc_target *target) { struct htc_endpoint_credit_dist *ep_list; - if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_CREDIT)) - return; - list_for_each_entry(ep_list, &target->cred_dist_list, list) dump_cred_dist(ep_list); diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 9853c9c125c1..9dc39754a35f 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -55,8 +55,6 @@ int ath6kl_printk(const char *level, const char *fmt, ...); #define ath6kl_warn(fmt, ...) \ ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__) -#define AR_DBG_LVL_CHECK(mask) (debug_mask & mask) - enum ath6kl_war { ATH6KL_WAR_INVALID_RATE, }; diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index e57da35e59fa..711886860b5d 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c @@ -429,9 +429,8 @@ static int proc_pending_irqs(struct ath6kl_device *dev, bool *done) if (status) goto out; - if (AR_DBG_LVL_CHECK(ATH6KL_DBG_IRQ)) - ath6kl_dump_registers(dev, &dev->irq_proc_reg, - &dev->irq_en_reg); + ath6kl_dump_registers(dev, &dev->irq_proc_reg, + &dev->irq_en_reg); /* Update only those registers that are enabled */ host_int_status = dev->irq_proc_reg.host_int_status & diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index c2420f886ed8..5d678bf372d3 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c @@ -426,9 +426,6 @@ static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len) ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n", evt->num_msg, evt->msg_len, evt->msg_type); - if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI)) - return 0; - for (index = 0; index < evt->num_msg; index++) { size = sizeof(struct wmi_tx_complete_event) + (index * sizeof(struct tx_complete_msg_v1)); -- GitLab From 3b1b7d0985fdb26403678e49938a668ef7f772ea Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:27 +0200 Subject: [PATCH 00155/10698] ath6kl: convert ath6kl_dbg() and ath6kl_dbg_dump() into functions That way it's possible to not export debug_mask outside the upcoming ath6kl_core.ko and that makes it easier to ath6kl_core.ko in the following patch. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/debug.c | 30 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath6kl/debug.h | 25 ++++----------------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index bd2f1fae72a9..4ba6560f0bf3 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -57,6 +57,36 @@ int ath6kl_printk(const char *level, const char *fmt, ...) #ifdef CONFIG_ATH6KL_DEBUG +void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + if (!(debug_mask & mask)) + return; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + ath6kl_printk(KERN_DEBUG, "%pV", &vaf); + + va_end(args); +} + +void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, + const char *msg, const char *prefix, + const void *buf, size_t len) +{ + if (debug_mask & mask) { + if (msg) + ath6kl_dbg(mask, "%s\n", msg); + + print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); + } +} + #define REG_OUTPUT_LEN_PER_LINE 25 #define REGTYPE_STR_LEN 100 diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 9dc39754a35f..872a8ce5d8f3 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -60,28 +60,11 @@ enum ath6kl_war { }; #ifdef CONFIG_ATH6KL_DEBUG -#define ath6kl_dbg(mask, fmt, ...) \ - ({ \ - int rtn; \ - if (debug_mask & mask) \ - rtn = ath6kl_printk(KERN_DEBUG, fmt, ##__VA_ARGS__); \ - else \ - rtn = 0; \ - \ - rtn; \ - }) -static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, - const char *msg, const char *prefix, - const void *buf, size_t len) -{ - if (debug_mask & mask) { - if (msg) - ath6kl_dbg(mask, "%s\n", msg); - - print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); - } -} +void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...); +void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, + const char *msg, const char *prefix, + const void *buf, size_t len); void ath6kl_dump_registers(struct ath6kl_device *dev, struct ath6kl_irq_proc_registers *irq_proc_reg, -- GitLab From d6a434d60e064a5f2bef1c13ca5ed84bfa6b8b4f Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:36 +0200 Subject: [PATCH 00156/10698] ath6kl: create ath6kl_core.ko Now ath6kl is ready for splitting core code to ath6kl_core.ko module. This also makes it possible to link both sdio and usb code to kernel at the same time, which earlier failed miserably. Reported-by: Stephen Rothwell Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/Makefile | 28 ++++++++++++---------- drivers/net/wireless/ath/ath6kl/cfg80211.c | 3 +++ drivers/net/wireless/ath/ath6kl/core.c | 9 +++++++ drivers/net/wireless/ath/ath6kl/debug.c | 3 +++ drivers/net/wireless/ath/ath6kl/hif.c | 5 ++++ drivers/net/wireless/ath/ath6kl/init.c | 3 +++ 6 files changed, 38 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index 854694b26a4b..cbdc31c603f6 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -21,16 +21,18 @@ # Author(s): ="Atheros" #------------------------------------------------------------------------------ -obj-$(CONFIG_ATH6KL) := ath6kl.o -ath6kl-y += debug.o -ath6kl-y += hif.o -ath6kl-y += htc.o -ath6kl-y += bmi.o -ath6kl-y += cfg80211.o -ath6kl-y += init.o -ath6kl-y += main.o -ath6kl-y += txrx.o -ath6kl-y += wmi.o -ath6kl-y += core.o -ath6kl-y += sdio.o -ath6kl-$(CONFIG_NL80211_TESTMODE) += testmode.o +obj-$(CONFIG_ATH6KL) += ath6kl_core.o +ath6kl_core-y += debug.o +ath6kl_core-y += hif.o +ath6kl_core-y += htc.o +ath6kl_core-y += bmi.o +ath6kl_core-y += cfg80211.o +ath6kl_core-y += init.o +ath6kl_core-y += main.o +ath6kl_core-y += txrx.o +ath6kl_core-y += wmi.o +ath6kl_core-y += core.o +ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o + +obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o +ath6kl_sdio-y += sdio.o diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 7ff9806de50b..594d246da8e1 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -16,6 +16,7 @@ #include #include +#include #include "core.h" #include "cfg80211.h" @@ -1935,6 +1936,7 @@ int ath6kl_cfg80211_suspend(struct ath6kl *ar, return 0; } +EXPORT_SYMBOL(ath6kl_cfg80211_suspend); int ath6kl_cfg80211_resume(struct ath6kl *ar) { @@ -1986,6 +1988,7 @@ int ath6kl_cfg80211_resume(struct ath6kl *ar) return 0; } +EXPORT_SYMBOL(ath6kl_cfg80211_resume); #ifdef CONFIG_PM diff --git a/drivers/net/wireless/ath/ath6kl/core.c b/drivers/net/wireless/ath/ath6kl/core.c index 40fad5ec9366..d764afec395b 100644 --- a/drivers/net/wireless/ath/ath6kl/core.c +++ b/drivers/net/wireless/ath/ath6kl/core.c @@ -16,7 +16,9 @@ #include "core.h" +#include #include +#include #include "debug.h" #include "hif-ops.h" @@ -203,6 +205,7 @@ int ath6kl_core_init(struct ath6kl *ar) return ret; } +EXPORT_SYMBOL(ath6kl_core_init); struct ath6kl *ath6kl_core_create(struct device *dev) { @@ -258,6 +261,7 @@ struct ath6kl *ath6kl_core_create(struct device *dev) return ar; } +EXPORT_SYMBOL(ath6kl_core_create); void ath6kl_core_cleanup(struct ath6kl *ar) { @@ -284,9 +288,14 @@ void ath6kl_core_cleanup(struct ath6kl *ar) ath6kl_cfg80211_cleanup(ar); } +EXPORT_SYMBOL(ath6kl_core_cleanup); void ath6kl_core_destroy(struct ath6kl *ar) { ath6kl_cfg80211_destroy(ar); } +EXPORT_SYMBOL(ath6kl_core_destroy); +MODULE_AUTHOR("Qualcomm Atheros"); +MODULE_DESCRIPTION("Core module for AR600x SDIO and USB devices."); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 4ba6560f0bf3..6b546dc66728 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c @@ -54,6 +54,7 @@ int ath6kl_printk(const char *level, const char *fmt, ...) return rtn; } +EXPORT_SYMBOL(ath6kl_printk); #ifdef CONFIG_ATH6KL_DEBUG @@ -74,6 +75,7 @@ void ath6kl_dbg(enum ATH6K_DEBUG_MASK mask, const char *fmt, ...) va_end(args); } +EXPORT_SYMBOL(ath6kl_dbg); void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, const char *msg, const char *prefix, @@ -86,6 +88,7 @@ void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); } } +EXPORT_SYMBOL(ath6kl_dbg_dump); #define REG_OUTPUT_LEN_PER_LINE 25 #define REGTYPE_STR_LEN 100 diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index 711886860b5d..d912da6ab0d1 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c @@ -15,6 +15,8 @@ */ #include "hif.h" +#include + #include "core.h" #include "target.h" #include "hif-ops.h" @@ -59,6 +61,8 @@ int ath6kl_hif_rw_comp_handler(void *context, int status) return 0; } +EXPORT_SYMBOL(ath6kl_hif_rw_comp_handler); + #define REG_DUMP_COUNT_AR6003 60 #define REGISTER_DUMP_LEN_MAX 60 @@ -560,6 +564,7 @@ int ath6kl_hif_intr_bh_handler(struct ath6kl *ar) return status; } +EXPORT_SYMBOL(ath6kl_hif_intr_bh_handler); static int ath6kl_hif_enable_intrs(struct ath6kl_device *dev) { diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index b8252ced0968..167dc41af2de 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c @@ -17,8 +17,10 @@ #include #include +#include #include #include + #include "core.h" #include "cfg80211.h" #include "target.h" @@ -1707,3 +1709,4 @@ void ath6kl_stop_txrx(struct ath6kl *ar) clear_bit(WLAN_ENABLED, &ar->flag); } +EXPORT_SYMBOL(ath6kl_stop_txrx); -- GitLab From 241b128b6b69ad41fc6f12cba45a3c3e64bce673 Mon Sep 17 00:00:00 2001 From: Kalle Valo Date: Tue, 17 Jan 2012 20:09:45 +0200 Subject: [PATCH 00157/10698] ath6kl: add back beginnings of USB support John Linville had to revert the part of USB support which was already in ath6kl due to build problems in commit cb00ec382b ("ath6kl: revert USB support"). Now that I fixed the build problems properly by adding ath6kl_core.ko kernel module it's possible to add back the (incomplete) USB support. This patch is a revert of John's patch and adds back the USB code which as already in ath6kl, only difference being minor changes in Makefile and adapting usb.c to new core function names. Note that USB support in ath6kl is not complete yet. This code only makes it possible to boot firmware but as HTC layer does not yet support USB it's not possible to send any WMI commands nor data packets to the firmware. That will be added soon. Signed-off-by: Kalle Valo --- drivers/net/wireless/ath/ath6kl/Kconfig | 25 +- drivers/net/wireless/ath/ath6kl/Makefile | 3 + drivers/net/wireless/ath/ath6kl/bmi.c | 10 +- drivers/net/wireless/ath/ath6kl/debug.h | 1 + drivers/net/wireless/ath/ath6kl/hif.c | 5 + drivers/net/wireless/ath/ath6kl/htc.c | 10 +- drivers/net/wireless/ath/ath6kl/sdio.c | 2 +- drivers/net/wireless/ath/ath6kl/usb.c | 431 +++++++++++++++++++++++ 8 files changed, 479 insertions(+), 8 deletions(-) create mode 100644 drivers/net/wireless/ath/ath6kl/usb.c diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig index 3d5f8be20eac..d755a5e7ed20 100644 --- a/drivers/net/wireless/ath/ath6kl/Kconfig +++ b/drivers/net/wireless/ath/ath6kl/Kconfig @@ -1,12 +1,29 @@ config ATH6KL - tristate "Atheros ath6kl support" + tristate "Atheros mobile chipsets support" + +config ATH6KL_SDIO + tristate "Atheros ath6kl SDIO support" + depends on ATH6KL depends on MMC depends on CFG80211 ---help--- This module adds support for wireless adapters based on - Atheros AR6003 chipset running over SDIO. If you choose to - build it as a module, it will be called ath6kl. Pls note - that AR6002 and AR6001 are not supported by this driver. + Atheros AR6003 and AR6004 chipsets running over SDIO. If you + choose to build it as a module, it will be called ath6kl_sdio. + Please note that AR6002 and AR6001 are not supported by this + driver. + +config ATH6KL_USB + tristate "Atheros ath6kl USB support" + depends on ATH6KL + depends on USB + depends on CFG80211 + depends on EXPERIMENTAL + ---help--- + This module adds support for wireless adapters based on + Atheros AR6004 chipset running over USB. This is still under + implementation and it isn't functional. If you choose to + build it as a module, it will be called ath6kl_usb. config ATH6KL_DEBUG bool "Atheros ath6kl debugging" diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile index cbdc31c603f6..9ba42fa04962 100644 --- a/drivers/net/wireless/ath/ath6kl/Makefile +++ b/drivers/net/wireless/ath/ath6kl/Makefile @@ -36,3 +36,6 @@ ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o obj-$(CONFIG_ATH6KL_SDIO) += ath6kl_sdio.o ath6kl_sdio-y += sdio.o + +obj-$(CONFIG_ATH6KL_USB) += ath6kl_usb.o +ath6kl_usb-y += usb.o diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c index bce3575c310a..aef00d5a1438 100644 --- a/drivers/net/wireless/ath/ath6kl/bmi.c +++ b/drivers/net/wireless/ath/ath6kl/bmi.c @@ -57,8 +57,14 @@ int ath6kl_bmi_get_target_info(struct ath6kl *ar, return ret; } - ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version, - sizeof(targ_info->version)); + if (ar->hif_type == ATH6KL_HIF_TYPE_USB) { + ret = ath6kl_hif_bmi_read(ar, (u8 *)targ_info, + sizeof(*targ_info)); + } else { + ret = ath6kl_hif_bmi_read(ar, (u8 *)&targ_info->version, + sizeof(targ_info->version)); + } + if (ret) { ath6kl_err("Unable to recv target info: %d\n", ret); return ret; diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index 872a8ce5d8f3..c4be6e50996b 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h @@ -41,6 +41,7 @@ enum ATH6K_DEBUG_MASK { ATH6KL_DBG_BOOT = BIT(18), /* driver init and fw boot */ ATH6KL_DBG_WMI_DUMP = BIT(19), ATH6KL_DBG_SUSPEND = BIT(20), + ATH6KL_DBG_USB = BIT(21), ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */ }; diff --git a/drivers/net/wireless/ath/ath6kl/hif.c b/drivers/net/wireless/ath/ath6kl/hif.c index d912da6ab0d1..e911737ab345 100644 --- a/drivers/net/wireless/ath/ath6kl/hif.c +++ b/drivers/net/wireless/ath/ath6kl/hif.c @@ -693,6 +693,11 @@ int ath6kl_hif_setup(struct ath6kl_device *dev) ath6kl_dbg(ATH6KL_DBG_HIF, "hif block size %d mbox addr 0x%x\n", dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr); + /* usb doesn't support enabling interrupts */ + /* FIXME: remove check once USB support is implemented */ + if (dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) + return 0; + status = ath6kl_hif_disable_intrs(dev); fail_setup: diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c index 073ddff31344..2d721903640b 100644 --- a/drivers/net/wireless/ath/ath6kl/htc.c +++ b/drivers/net/wireless/ath/ath6kl/htc.c @@ -2544,6 +2544,12 @@ int ath6kl_htc_wait_target(struct htc_target *target) struct htc_service_connect_resp resp; int status; + /* FIXME: remove once USB support is implemented */ + if (target->dev->ar->hif_type == ATH6KL_HIF_TYPE_USB) { + ath6kl_err("HTC doesn't support USB yet. Patience!\n"); + return -EOPNOTSUPP; + } + /* we should be getting 1 control message that the target is ready */ packet = htc_wait_for_ctrl_msg(target); @@ -2773,7 +2779,9 @@ void ath6kl_htc_cleanup(struct htc_target *target) { struct htc_packet *packet, *tmp_packet; - ath6kl_hif_cleanup_scatter(target->dev->ar); + /* FIXME: remove check once USB support is implemented */ + if (target->dev->ar->hif_type != ATH6KL_HIF_TYPE_USB) + ath6kl_hif_cleanup_scatter(target->dev->ar); list_for_each_entry_safe(packet, tmp_packet, &target->free_ctrl_txbuf, list) { diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index bef32ecea792..7bb61077c406 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -1330,7 +1330,7 @@ static const struct sdio_device_id ath6kl_sdio_devices[] = { MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices); static struct sdio_driver ath6kl_sdio_driver = { - .name = "ath6kl", + .name = "ath6kl_sdio", .id_table = ath6kl_sdio_devices, .probe = ath6kl_sdio_probe, .remove = ath6kl_sdio_remove, diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c new file mode 100644 index 000000000000..c72567c6d338 --- /dev/null +++ b/drivers/net/wireless/ath/ath6kl/usb.c @@ -0,0 +1,431 @@ +/* + * Copyright (c) 2007-2011 Atheros Communications Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include "debug.h" +#include "core.h" + +/* usb device object */ +struct ath6kl_usb { + struct usb_device *udev; + struct usb_interface *interface; + u8 *diag_cmd_buffer; + u8 *diag_resp_buffer; + struct ath6kl *ar; +}; + +/* diagnostic command defnitions */ +#define ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD 1 +#define ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP 2 +#define ATH6KL_USB_CONTROL_REQ_DIAG_CMD 3 +#define ATH6KL_USB_CONTROL_REQ_DIAG_RESP 4 + +#define ATH6KL_USB_CTRL_DIAG_CC_READ 0 +#define ATH6KL_USB_CTRL_DIAG_CC_WRITE 1 + +struct ath6kl_usb_ctrl_diag_cmd_write { + __le32 cmd; + __le32 address; + __le32 value; + __le32 _pad[1]; +} __packed; + +struct ath6kl_usb_ctrl_diag_cmd_read { + __le32 cmd; + __le32 address; +} __packed; + +struct ath6kl_usb_ctrl_diag_resp_read { + __le32 value; +} __packed; + +#define ATH6KL_USB_MAX_DIAG_CMD (sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)) +#define ATH6KL_USB_MAX_DIAG_RESP (sizeof(struct ath6kl_usb_ctrl_diag_resp_read)) + +static void ath6kl_usb_destroy(struct ath6kl_usb *ar_usb) +{ + usb_set_intfdata(ar_usb->interface, NULL); + + kfree(ar_usb->diag_cmd_buffer); + kfree(ar_usb->diag_resp_buffer); + + kfree(ar_usb); +} + +static struct ath6kl_usb *ath6kl_usb_create(struct usb_interface *interface) +{ + struct ath6kl_usb *ar_usb = NULL; + struct usb_device *dev = interface_to_usbdev(interface); + int status = 0; + + ar_usb = kzalloc(sizeof(struct ath6kl_usb), GFP_KERNEL); + if (ar_usb == NULL) + goto fail_ath6kl_usb_create; + + memset(ar_usb, 0, sizeof(struct ath6kl_usb)); + usb_set_intfdata(interface, ar_usb); + ar_usb->udev = dev; + ar_usb->interface = interface; + + ar_usb->diag_cmd_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_CMD, GFP_KERNEL); + if (ar_usb->diag_cmd_buffer == NULL) { + status = -ENOMEM; + goto fail_ath6kl_usb_create; + } + + ar_usb->diag_resp_buffer = kzalloc(ATH6KL_USB_MAX_DIAG_RESP, + GFP_KERNEL); + if (ar_usb->diag_resp_buffer == NULL) { + status = -ENOMEM; + goto fail_ath6kl_usb_create; + } + +fail_ath6kl_usb_create: + if (status != 0) { + ath6kl_usb_destroy(ar_usb); + ar_usb = NULL; + } + return ar_usb; +} + +static void ath6kl_usb_device_detached(struct usb_interface *interface) +{ + struct ath6kl_usb *ar_usb; + + ar_usb = usb_get_intfdata(interface); + if (ar_usb == NULL) + return; + + ath6kl_stop_txrx(ar_usb->ar); + + ath6kl_core_cleanup(ar_usb->ar); + + ath6kl_usb_destroy(ar_usb); +} + +static int ath6kl_usb_submit_ctrl_out(struct ath6kl_usb *ar_usb, + u8 req, u16 value, u16 index, void *data, + u32 size) +{ + u8 *buf = NULL; + int ret; + + if (size > 0) { + buf = kmalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + + memcpy(buf, data, size); + } + + /* note: if successful returns number of bytes transfered */ + ret = usb_control_msg(ar_usb->udev, + usb_sndctrlpipe(ar_usb->udev, 0), + req, + USB_DIR_OUT | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, buf, + size, 1000); + + if (ret < 0) { + ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", + __func__, ret); + } + + kfree(buf); + + return 0; +} + +static int ath6kl_usb_submit_ctrl_in(struct ath6kl_usb *ar_usb, + u8 req, u16 value, u16 index, void *data, + u32 size) +{ + u8 *buf = NULL; + int ret; + + if (size > 0) { + buf = kmalloc(size, GFP_KERNEL); + if (buf == NULL) + return -ENOMEM; + } + + /* note: if successful returns number of bytes transfered */ + ret = usb_control_msg(ar_usb->udev, + usb_rcvctrlpipe(ar_usb->udev, 0), + req, + USB_DIR_IN | USB_TYPE_VENDOR | + USB_RECIP_DEVICE, value, index, buf, + size, 2 * HZ); + + if (ret < 0) { + ath6kl_dbg(ATH6KL_DBG_USB, "%s failed,result = %d\n", + __func__, ret); + } + + memcpy((u8 *) data, buf, size); + + kfree(buf); + + return 0; +} + +static int ath6kl_usb_ctrl_msg_exchange(struct ath6kl_usb *ar_usb, + u8 req_val, u8 *req_buf, u32 req_len, + u8 resp_val, u8 *resp_buf, u32 *resp_len) +{ + int ret; + + /* send command */ + ret = ath6kl_usb_submit_ctrl_out(ar_usb, req_val, 0, 0, + req_buf, req_len); + + if (ret != 0) + return ret; + + if (resp_buf == NULL) { + /* no expected response */ + return ret; + } + + /* get response */ + ret = ath6kl_usb_submit_ctrl_in(ar_usb, resp_val, 0, 0, + resp_buf, *resp_len); + + return ret; +} + +static int ath6kl_usb_diag_read32(struct ath6kl *ar, u32 address, u32 *data) +{ + struct ath6kl_usb *ar_usb = ar->hif_priv; + struct ath6kl_usb_ctrl_diag_resp_read *resp; + struct ath6kl_usb_ctrl_diag_cmd_read *cmd; + u32 resp_len; + int ret; + + cmd = (struct ath6kl_usb_ctrl_diag_cmd_read *) ar_usb->diag_cmd_buffer; + + memset(cmd, 0, sizeof(*cmd)); + cmd->cmd = ATH6KL_USB_CTRL_DIAG_CC_READ; + cmd->address = cpu_to_le32(address); + resp_len = sizeof(*resp); + + ret = ath6kl_usb_ctrl_msg_exchange(ar_usb, + ATH6KL_USB_CONTROL_REQ_DIAG_CMD, + (u8 *) cmd, + sizeof(struct ath6kl_usb_ctrl_diag_cmd_write), + ATH6KL_USB_CONTROL_REQ_DIAG_RESP, + ar_usb->diag_resp_buffer, &resp_len); + + if (ret) + return ret; + + resp = (struct ath6kl_usb_ctrl_diag_resp_read *) + ar_usb->diag_resp_buffer; + + *data = le32_to_cpu(resp->value); + + return ret; +} + +static int ath6kl_usb_diag_write32(struct ath6kl *ar, u32 address, __le32 data) +{ + struct ath6kl_usb *ar_usb = ar->hif_priv; + struct ath6kl_usb_ctrl_diag_cmd_write *cmd; + + cmd = (struct ath6kl_usb_ctrl_diag_cmd_write *) ar_usb->diag_cmd_buffer; + + memset(cmd, 0, sizeof(struct ath6kl_usb_ctrl_diag_cmd_write)); + cmd->cmd = cpu_to_le32(ATH6KL_USB_CTRL_DIAG_CC_WRITE); + cmd->address = cpu_to_le32(address); + cmd->value = data; + + return ath6kl_usb_ctrl_msg_exchange(ar_usb, + ATH6KL_USB_CONTROL_REQ_DIAG_CMD, + (u8 *) cmd, + sizeof(*cmd), + 0, NULL, NULL); + +} + +static int ath6kl_usb_bmi_read(struct ath6kl *ar, u8 *buf, u32 len) +{ + struct ath6kl_usb *ar_usb = ar->hif_priv; + int ret; + + /* get response */ + ret = ath6kl_usb_submit_ctrl_in(ar_usb, + ATH6KL_USB_CONTROL_REQ_RECV_BMI_RESP, + 0, 0, buf, len); + if (ret != 0) { + ath6kl_err("Unable to read the bmi data from the device: %d\n", + ret); + return ret; + } + + return 0; +} + +static int ath6kl_usb_bmi_write(struct ath6kl *ar, u8 *buf, u32 len) +{ + struct ath6kl_usb *ar_usb = ar->hif_priv; + int ret; + + /* send command */ + ret = ath6kl_usb_submit_ctrl_out(ar_usb, + ATH6KL_USB_CONTROL_REQ_SEND_BMI_CMD, + 0, 0, buf, len); + if (ret != 0) { + ath6kl_err("unable to send the bmi data to the device: %d\n", + ret); + return ret; + } + + return 0; +} + +static int ath6kl_usb_power_on(struct ath6kl *ar) +{ + return 0; +} + +static int ath6kl_usb_power_off(struct ath6kl *ar) +{ + return 0; +} + +static const struct ath6kl_hif_ops ath6kl_usb_ops = { + .diag_read32 = ath6kl_usb_diag_read32, + .diag_write32 = ath6kl_usb_diag_write32, + .bmi_read = ath6kl_usb_bmi_read, + .bmi_write = ath6kl_usb_bmi_write, + .power_on = ath6kl_usb_power_on, + .power_off = ath6kl_usb_power_off, +}; + +/* ath6kl usb driver registered functions */ +static int ath6kl_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(interface); + struct ath6kl *ar; + struct ath6kl_usb *ar_usb = NULL; + int vendor_id, product_id; + int ret = 0; + + usb_get_dev(dev); + + vendor_id = le16_to_cpu(dev->descriptor.idVendor); + product_id = le16_to_cpu(dev->descriptor.idProduct); + + ath6kl_dbg(ATH6KL_DBG_USB, "vendor_id = %04x\n", vendor_id); + ath6kl_dbg(ATH6KL_DBG_USB, "product_id = %04x\n", product_id); + + if (interface->cur_altsetting) + ath6kl_dbg(ATH6KL_DBG_USB, "USB Interface %d\n", + interface->cur_altsetting->desc.bInterfaceNumber); + + + if (dev->speed == USB_SPEED_HIGH) + ath6kl_dbg(ATH6KL_DBG_USB, "USB 2.0 Host\n"); + else + ath6kl_dbg(ATH6KL_DBG_USB, "USB 1.1 Host\n"); + + ar_usb = ath6kl_usb_create(interface); + + if (ar_usb == NULL) { + ret = -ENOMEM; + goto err_usb_put; + } + + ar = ath6kl_core_create(&ar_usb->udev->dev); + if (ar == NULL) { + ath6kl_err("Failed to alloc ath6kl core\n"); + ret = -ENOMEM; + goto err_usb_destroy; + } + + ar->hif_priv = ar_usb; + ar->hif_type = ATH6KL_HIF_TYPE_USB; + ar->hif_ops = &ath6kl_usb_ops; + ar->mbox_info.block_size = 16; + ar->bmi.max_data_size = 252; + + ar_usb->ar = ar; + + ret = ath6kl_core_init(ar); + if (ret) { + ath6kl_err("Failed to init ath6kl core: %d\n", ret); + goto err_core_free; + } + + return ret; + +err_core_free: + ath6kl_core_destroy(ar); +err_usb_destroy: + ath6kl_usb_destroy(ar_usb); +err_usb_put: + usb_put_dev(dev); + + return ret; +} + +static void ath6kl_usb_remove(struct usb_interface *interface) +{ + usb_put_dev(interface_to_usbdev(interface)); + ath6kl_usb_device_detached(interface); +} + +/* table of devices that work with this driver */ +static struct usb_device_id ath6kl_usb_ids[] = { + {USB_DEVICE(0x0cf3, 0x9374)}, + { /* Terminating entry */ }, +}; + +MODULE_DEVICE_TABLE(usb, ath6kl_usb_ids); + +static struct usb_driver ath6kl_usb_driver = { + .name = "ath6kl_usb", + .probe = ath6kl_usb_probe, + .disconnect = ath6kl_usb_remove, + .id_table = ath6kl_usb_ids, +}; + +static int ath6kl_usb_init(void) +{ + usb_register(&ath6kl_usb_driver); + return 0; +} + +static void ath6kl_usb_exit(void) +{ + usb_deregister(&ath6kl_usb_driver); +} + +module_init(ath6kl_usb_init); +module_exit(ath6kl_usb_exit); + +MODULE_AUTHOR("Atheros Communications, Inc."); +MODULE_DESCRIPTION("Driver support for Atheros AR600x USB devices"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_FIRMWARE(AR6004_HW_1_0_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_0_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); +MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); -- GitLab From 0ada2da51800a4914887a9bcf22d563be80e50be Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 18 Jan 2012 17:32:05 -0800 Subject: [PATCH 00158/10698] ARM: mach-shmobile: mackerel: use renesas_usbhs instead of r8a66597_hcd Current renesas_usbhs driver can use both USB host/gadget. This patch removes current r8a66597_hcd driver settings, and adds renesas_usbhs host driver settings for mackerel USB1 port. You can still use this port as "gadget" with small modify. Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-mackerel.c | 73 +++---------------------- 1 file changed, 9 insertions(+), 64 deletions(-) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 9b42fbd10f8e..f0cc307df640 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #include @@ -145,11 +144,6 @@ * 1-2 short | VBUS 5V | Host * open | external VBUS | Function * - * *1 - * CN31 is used as - * CONFIG_USB_R8A66597_HCD Host - * CONFIG_USB_RENESAS_USBHS Function - * * CAUTION * * renesas_usbhs driver can use external interrupt mode @@ -161,15 +155,6 @@ * mackerel can not use external interrupt (IRQ7-PORT167) mode on "USB0", * because Touchscreen is using IRQ7-PORT40. * It is impossible to use IRQ7 demux on this board. - * - * We can use external interrupt mode USB-Function on "USB1". - * USB1 can become Host by r8a66597, and become Function by renesas_usbhs. - * But don't select both drivers in same time. - * These uses same IRQ number for request_irq(), and aren't supporting - * IRQF_SHARED / IORESOURCE_IRQ_SHAREABLE. - * - * Actually these are old/new version of USB driver. - * This mean its register will be broken if it supports shared IRQ, */ /* @@ -676,51 +661,16 @@ static struct platform_device usbhs0_device = { * Use J30 to select between Host and Function. This setting * can however not be detected by software. Hotplug of USBHS1 * is provided via IRQ8. + * + * Current USB1 works as "USB Host". + * - set J30 "short" + * + * If you want to use it as "USB gadget", + * - J30 "open" + * - modify usbhs1_get_id() USBHS_HOST -> USBHS_GADGET + * - add .get_vbus = usbhs_get_vbus in usbhs1_private */ #define IRQ8 evt2irq(0x0300) - -/* USBHS1 USB Host support via r8a66597_hcd */ -static void usb1_host_port_power(int port, int power) -{ - if (!power) /* only power-on is supported for now */ - return; - - /* set VBOUT/PWEN and EXTLP1 in DVSTCTR */ - __raw_writew(__raw_readw(0xE68B0008) | 0x600, 0xE68B0008); -} - -static struct r8a66597_platdata usb1_host_data = { - .on_chip = 1, - .port_power = usb1_host_port_power, -}; - -static struct resource usb1_host_resources[] = { - [0] = { - .name = "USBHS1", - .start = 0xe68b0000, - .end = 0xe68b00e6 - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = evt2irq(0x1ce0) /* USB1_USB1I0 */, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device usb1_host_device = { - .name = "r8a66597_hcd", - .id = 1, - .dev = { - .dma_mask = NULL, /* not use dma */ - .coherent_dma_mask = 0xffffffff, - .platform_data = &usb1_host_data, - }, - .num_resources = ARRAY_SIZE(usb1_host_resources), - .resource = usb1_host_resources, -}; - -/* USBHS1 USB Function support via renesas_usbhs */ - #define USB_PHY_MODE (1 << 4) #define USB_PHY_INT_EN ((1 << 3) | (1 << 2)) #define USB_PHY_ON (1 << 1) @@ -776,7 +726,7 @@ static void usbhs1_hardware_exit(struct platform_device *pdev) static int usbhs1_get_id(struct platform_device *pdev) { - return USBHS_GADGET; + return USBHS_HOST; } static u32 usbhs1_pipe_cfg[] = { @@ -807,7 +757,6 @@ static struct usbhs_private usbhs1_private = { .hardware_exit = usbhs1_hardware_exit, .get_id = usbhs1_get_id, .phy_reset = usbhs_phy_reset, - .get_vbus = usbhs_get_vbus, }, .driver_param = { .buswait_bwait = 4, @@ -1311,7 +1260,6 @@ static struct platform_device *mackerel_devices[] __initdata = { &nor_flash_device, &smc911x_device, &lcdc_device, - &usb1_host_device, &usbhs1_device, &usbhs0_device, &leds_device, @@ -1473,9 +1421,6 @@ static void __init mackerel_init(void) gpio_pull_down(GPIO_PORT167CR); /* VBUS0_1 pull down */ gpio_request(GPIO_FN_IDIN_1_113, NULL); - /* USB phy tweak to make the r8a66597_hcd host driver work */ - __raw_writew(0x8a0a, 0xe6058130); /* USBCR4 */ - /* enable FSI2 port A (ak4643) */ gpio_request(GPIO_FN_FSIAIBT, NULL); gpio_request(GPIO_FN_FSIAILR, NULL); -- GitLab From 6d9b7dd0da1b619ed5f89ff7ab4bc3188c0f7e9f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 18 Jan 2012 16:37:07 -0800 Subject: [PATCH 00159/10698] ARM: mach-shmobile: mackerel: add ak4642 amixer settings on comment current ak4642 needs amixer settings for playing which was not needed on old kernel. This patch show it on comment area Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- arch/arm/mach-shmobile/board-mackerel.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index f0cc307df640..c4a6a9b16d1b 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -192,6 +192,16 @@ * */ +/* + * FSI - AK4642 + * + * it needs amixer settings for playing + * + * amixer set "Headphone" on + * amixer set "HPOUTL Mixer DACH" on + * amixer set "HPOUTR Mixer DACH" on + */ + /* * FIXME !! * -- GitLab From 700920eb5ba4de5417b446c9a8bb008df2b973e0 Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 18 Jan 2012 15:31:45 +0000 Subject: [PATCH 00160/10698] KEYS: Allow special keyrings to be cleared The kernel contains some special internal keyrings, for instance the DNS resolver keyring : 2a93faf1 I----- 1 perm 1f030000 0 0 keyring .dns_resolver: empty It would occasionally be useful to allow the contents of such keyrings to be flushed by root (cache invalidation). Allow a flag to be set on a keyring to mark that someone possessing the sysadmin capability can clear the keyring, even without normal write access to the keyring. Set this flag on the special keyrings created by the DNS resolver, the NFS identity mapper and the CIFS identity mapper. Signed-off-by: David Howells Acked-by: Jeff Layton Acked-by: Steve Dickson Signed-off-by: James Morris --- Documentation/networking/dns_resolver.txt | 4 ++++ Documentation/security/keys.txt | 4 ++++ fs/cifs/cifsacl.c | 1 + fs/nfs/idmap.c | 1 + include/linux/key.h | 1 + net/dns_resolver/dns_key.c | 1 + security/keys/keyctl.c | 15 ++++++++++++++- 7 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Documentation/networking/dns_resolver.txt b/Documentation/networking/dns_resolver.txt index 7f531ad83285..d86adcdae420 100644 --- a/Documentation/networking/dns_resolver.txt +++ b/Documentation/networking/dns_resolver.txt @@ -102,6 +102,10 @@ implemented in the module can be called after doing: If _expiry is non-NULL, the expiry time (TTL) of the result will be returned also. +The kernel maintains an internal keyring in which it caches looked up keys. +This can be cleared by any process that has the CAP_SYS_ADMIN capability by +the use of KEYCTL_KEYRING_CLEAR on the keyring ID. + =============================== READING DNS KEYS FROM USERSPACE diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index 4d75931d2d79..713ec232c562 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt @@ -554,6 +554,10 @@ The keyctl syscall functions are: process must have write permission on the keyring, and it must be a keyring (or else error ENOTDIR will result). + This function can also be used to clear special kernel keyrings if they + are appropriately marked if the user has CAP_SYS_ADMIN capability. The + DNS resolver cache keyring is an example of this. + (*) Link a key into a keyring: diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 72ddf23ef6f7..854749d21bb1 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -556,6 +556,7 @@ init_cifs_idmap(void) /* instruct request_key() to use this special keyring as a cache for * the results it looks up */ + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; root_cred = cred; diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 2c05f1991e1e..a1bbf7780dfc 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -198,6 +198,7 @@ int nfs_idmap_init(void) if (ret < 0) goto failed_put_key; + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; id_resolver_cache = cred; diff --git a/include/linux/key.h b/include/linux/key.h index 183a6af7715d..3ac412855d83 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -155,6 +155,7 @@ struct key { #define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */ #define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */ #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ +#define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ /* the description string * - this is used to match a key against search criteria diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index fa000d26dc60..c73bba326d70 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -281,6 +281,7 @@ static int __init init_dns_resolver(void) /* instruct request_key() to use this special keyring as a cache for * the results it looks up */ + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; dns_resolver_cache = cred; diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 0b3f5d72af1c..6523599e9ac0 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -388,11 +388,24 @@ long keyctl_keyring_clear(key_serial_t ringid) keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE); if (IS_ERR(keyring_ref)) { ret = PTR_ERR(keyring_ref); + + /* Root is permitted to invalidate certain special keyrings */ + if (capable(CAP_SYS_ADMIN)) { + keyring_ref = lookup_user_key(ringid, 0, 0); + if (IS_ERR(keyring_ref)) + goto error; + if (test_bit(KEY_FLAG_ROOT_CAN_CLEAR, + &key_ref_to_ptr(keyring_ref)->flags)) + goto clear; + goto error_put; + } + goto error; } +clear: ret = keyring_clear(key_ref_to_ptr(keyring_ref)); - +error_put: key_ref_put(keyring_ref); error: return ret; -- GitLab From df0793abb929e66606fa25f3875ff1b89de5ad32 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 19 Jan 2012 09:20:09 +0100 Subject: [PATCH 00161/10698] block,cfq: change code order cfq_slice_expired will change saved_workload_slice. It should be called first so saved_workload_slice is correctly set to 0 after workload type is changed. This fixes the code order changed by 54b466e44b1c7. Tested-by: Tetsuo Handa Signed-off-by: Shaohua Li Signed-off-by: Jens Axboe --- block/cfq-iosched.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index ee55019066a1..da21c24dbed3 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -3117,17 +3117,18 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, */ static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) { + enum wl_type_t old_type = cfqq_type(cfqd->active_queue); + cfq_log_cfqq(cfqd, cfqq, "preempt"); + cfq_slice_expired(cfqd, 1); /* * workload type is changed, don't save slice, otherwise preempt * doesn't happen */ - if (cfqq_type(cfqd->active_queue) != cfqq_type(cfqq)) + if (old_type != cfqq_type(cfqq)) cfqq->cfqg->saved_workload_slice = 0; - cfq_slice_expired(cfqd, 1); - /* * Put the new queue at the front of the of the current list, * so we know that it will be selected next. -- GitLab From 05c30b9551f1904d9950ad0d28e65fc4ff3c8a8e Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Thu, 19 Jan 2012 09:20:10 +0100 Subject: [PATCH 00162/10698] block: fix NULL icq_cache reference Vivek reported a kernel crash: [ 94.217015] BUG: unable to handle kernel NULL pointer dereference at 000000000000001c [ 94.218004] IP: [] kmem_cache_free+0x5e/0x200 [ 94.218004] PGD 13abda067 PUD 137d52067 PMD 0 [ 94.218004] Oops: 0000 [#1] SMP DEBUG_PAGEALLOC [ 94.218004] CPU 0 [ 94.218004] Modules linked in: [last unloaded: scsi_wait_scan] [ 94.218004] [ 94.218004] Pid: 0, comm: swapper/0 Not tainted 3.2.0+ #16 Hewlett-Packard HP xw6600 Workstation/0A9Ch [ 94.218004] RIP: 0010:[] [] kmem_cache_free+0x5e/0x200 [ 94.218004] RSP: 0018:ffff88013fc03de0 EFLAGS: 00010006 [ 94.218004] RAX: ffffffff81e0d020 RBX: ffff880138b3c680 RCX: 00000001801c001b [ 94.218004] RDX: 00000000003aac1d RSI: ffff880138b3c680 RDI: ffffffff81142fae [ 94.218004] RBP: ffff88013fc03e10 R08: ffff880137830238 R09: 0000000000000001 [ 94.218004] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 [ 94.218004] R13: ffffea0004e2cf00 R14: ffffffff812f6eb6 R15: 0000000000000246 [ 94.218004] FS: 0000000000000000(0000) GS:ffff88013fc00000(0000) knlGS:0000000000000000 [ 94.218004] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 94.218004] CR2: 000000000000001c CR3: 00000001395ab000 CR4: 00000000000006f0 [ 94.218004] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 94.218004] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 94.218004] Process swapper/0 (pid: 0, threadinfo ffffffff81e00000, task ffffffff81e0d020) [ 94.218004] Stack: [ 94.218004] 0000000000000102 ffff88013fc0db20 ffffffff81e22700 ffff880139500f00 [ 94.218004] 0000000000000001 000000000000000a ffff88013fc03e20 ffffffff812f6eb6 [ 94.218004] ffff88013fc03e90 ffffffff810c8da2 ffffffff81e01fd8 ffff880137830240 [ 94.218004] Call Trace: [ 94.218004] [ 94.218004] [] icq_free_icq_rcu+0x16/0x20 [ 94.218004] [] __rcu_process_callbacks+0x1c2/0x420 [ 94.218004] [] rcu_process_callbacks+0x38/0x250 [ 94.218004] [] __do_softirq+0xce/0x3e0 [ 94.218004] [] ? clockevents_program_event+0x74/0x100 [ 94.218004] [] ? tick_program_event+0x24/0x30 [ 94.218004] [] call_softirq+0x1c/0x30 [ 94.218004] [] do_softirq+0x8d/0xc0 [ 94.218004] [] irq_exit+0xae/0xe0 [ 94.218004] [] smp_apic_timer_interrupt+0x6e/0x99 [ 94.218004] [] apic_timer_interrupt+0x70/0x80 Once a queue is quiesced, it's not supposed to have any elvpriv data or icq's, and elevator switching depends on that. Request alloc path followed the rule for elvpriv data but forgot apply it to icq's leading to the following crash during elevator switch. Fix it by not allocating icq's if ELVPRIV is not set for the request. Reported-by: Vivek Goyal Tested-by: Vivek Goyal Signed-off-by: Shaohua Li Acked-by: Tejun Heo Signed-off-by: Jens Axboe --- block/blk-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index e6c05a97ee2b..636702575118 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -872,13 +872,15 @@ static struct request *get_request(struct request_queue *q, int rw_flags, spin_unlock_irq(q->queue_lock); /* create icq if missing */ - if (unlikely(et->icq_cache && !icq)) + if ((rw_flags & REQ_ELVPRIV) && unlikely(et->icq_cache && !icq)) { icq = ioc_create_icq(q, gfp_mask); + if (!icq) + goto fail_icq; + } - /* rqs are guaranteed to have icq on elv_set_request() if requested */ - if (likely(!et->icq_cache || icq)) - rq = blk_alloc_request(q, icq, rw_flags, gfp_mask); + rq = blk_alloc_request(q, icq, rw_flags, gfp_mask); +fail_icq: if (unlikely(!rq)) { /* * Allocation failed presumably due to memory. Undo anything -- GitLab From 6bebb572404f96d367170fb263603cda7251f932 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Wed, 4 Jan 2012 10:50:09 +0100 Subject: [PATCH 00163/10698] ARM: 7268/1: integrator: defconfig for both AP and CP This updates the Integrator defconfig to include the hardware found on the Integrator/CP: SMC91X, CLCD, MMCI/PL180. Further the sometimes disrupting VGA_CONSOLE is disabled (those who have a VGA card can enable it) and typical default VFAT layouts of the MMC cards are supported by enabling VFAT and CP437 encoding of the file system. After this my default kernels boot successfully on Integrator AP and CP alike. Signed-off-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/configs/integrator_defconfig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig index 1103f62a1964..a8314c3ee84d 100644 --- a/arch/arm/configs/integrator_defconfig +++ b/arch/arm/configs/integrator_defconfig @@ -57,18 +57,24 @@ CONFIG_NETDEVICES=y CONFIG_NET_ETHERNET=y CONFIG_NET_PCI=y CONFIG_E100=y +CONFIG_SMC91X=y # CONFIG_KEYBOARD_ATKBD is not set # CONFIG_SERIO_SERPORT is not set CONFIG_SERIAL_AMBA_PL010=y CONFIG_SERIAL_AMBA_PL010_CONSOLE=y CONFIG_FB=y CONFIG_FB_MODE_HELPERS=y +CONFIG_FB_ARMCLCD=y CONFIG_FB_MATROX=y CONFIG_FB_MATROX_MILLENIUM=y CONFIG_FB_MATROX_MYSTIQUE=y +# CONFIG_VGA_CONSOLE is not set +CONFIG_MMC=y +CONFIG_MMC_ARMMMCI=y CONFIG_RTC_CLASS=y CONFIG_RTC_DRV_PL030=y CONFIG_EXT2_FS=y +CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y CONFIG_CRAMFS=y @@ -78,5 +84,7 @@ CONFIG_ROOT_NFS=y CONFIG_NFSD=y CONFIG_NFSD_V3=y CONFIG_PARTITION_ADVANCED=y +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y -- GitLab From 859dd55d91d977090efbba15c7dfc82e7ed774ef Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 13 Dec 2011 16:52:00 +0100 Subject: [PATCH 00164/10698] ARM: 7215/1: mmc: mmci: Increase max_segs from 16 to 128 A significant increase (10-20%) in performance throughput for USB mass storage is the reason for incrementing the value. By some reason the USB driver allocates buffers which requires a scattergather list to contain a lot more than 16 elements to get optimal performance. This change sets the maximum elements to 128. Tests with large reads and large writes (100 MiB) show that the throughput increase is significant for write (10% for this test) but not for read. Tests are run on a Linux host with ext4 FS on the gadget mass storage device. The sg-len still exceeds 16 for the read tests but the performance gain is low or nothing. Tested-by: Linus Walleij Signed-off-by: Per Forlin Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/mmc/host/mmci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 79e4143ab9df..49f153e6ef7a 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -160,7 +160,7 @@ (MCI_RXFIFOHALFFULLMASK | MCI_RXDATAAVLBLMASK | \ MCI_TXFIFOHALFEMPTYMASK) -#define NR_SG 16 +#define NR_SG 128 struct clk; struct variant_data; -- GitLab From 5074d25dc97ac2d93fca7852563b7e204f03464a Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 13 Dec 2011 16:53:17 +0100 Subject: [PATCH 00165/10698] ARM: 7216/1: mmc: mmci: Do not release spinlock in request_end The patch "mmc: core: move ->request() call from atomic context", is the reason to why this change is possible. This simplifies the error handling code execution path quite a lot and potentially also fixes some error handling hang problems. Tested-by: Linus Walleij Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 0d955ffaf44e..0e04138b1759 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -166,14 +166,8 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) host->mrq = NULL; host->cmd = NULL; - /* - * Need to drop the host lock here; mmc_request_done may call - * back into the driver... - */ - spin_unlock(&host->lock); pm_runtime_put(mmc_dev(host->mmc)); mmc_request_done(host->mmc, mrq); - spin_lock(&host->lock); } static void mmci_set_mask1(struct mmci_host *host, unsigned int mask) -- GitLab From 7d72a1d48af95211677ea83157945a8ef76b0751 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 13 Dec 2011 16:54:55 +0100 Subject: [PATCH 00166/10698] ARM: 7217/1: mmc: mmci: Put power register deviations in variant data Use variant data to store hardware controller deviations concerning power registers to improve readability of the code. Signed-off-by: Sebastian Rasmussen Tested-by: Linus Walleij Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 0e04138b1759..7cc89beee87f 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -53,6 +53,7 @@ static unsigned int fmax = 515633; * @sdio: variant supports SDIO * @st_clkdiv: true if using a ST-specific clock divider algorithm * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register + * @pwrreg_powerup: power up value for MMCIPOWER register */ struct variant_data { unsigned int clkreg; @@ -63,18 +64,21 @@ struct variant_data { bool sdio; bool st_clkdiv; bool blksz_datactrl16; + u32 pwrreg_powerup; }; static struct variant_data variant_arm = { .fifosize = 16 * 4, .fifohalfsize = 8 * 4, .datalength_bits = 16, + .pwrreg_powerup = MCI_PWR_UP, }; static struct variant_data variant_arm_extended_fifo = { .fifosize = 128 * 4, .fifohalfsize = 64 * 4, .datalength_bits = 16, + .pwrreg_powerup = MCI_PWR_UP, }; static struct variant_data variant_u300 = { @@ -83,6 +87,7 @@ static struct variant_data variant_u300 = { .clkreg_enable = MCI_ST_U300_HWFCEN, .datalength_bits = 16, .sdio = true, + .pwrreg_powerup = MCI_PWR_ON, }; static struct variant_data variant_ux500 = { @@ -93,6 +98,7 @@ static struct variant_data variant_ux500 = { .datalength_bits = 24, .sdio = true, .st_clkdiv = true, + .pwrreg_powerup = MCI_PWR_ON, }; static struct variant_data variant_ux500v2 = { @@ -104,6 +110,7 @@ static struct variant_data variant_ux500v2 = { .sdio = true, .st_clkdiv = true, .blksz_datactrl16 = true, + .pwrreg_powerup = MCI_PWR_ON, }; /* @@ -1009,6 +1016,7 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct mmci_host *host = mmc_priv(mmc); + struct variant_data *variant = host->variant; u32 pwr = 0; unsigned long flags; int ret; @@ -1035,11 +1043,15 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (host->plat->vdd_handler) pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, ios->power_mode); - /* The ST version does not have this, fall through to POWER_ON */ - if (host->hw_designer != AMBA_VENDOR_ST) { - pwr |= MCI_PWR_UP; - break; - } + + /* + * The ST Micro variant doesn't have the PL180s MCI_PWR_UP + * and instead uses MCI_PWR_ON so apply whatever value is + * configured in the variant data. + */ + pwr |= variant->pwrreg_powerup; + + break; case MMC_POWER_ON: pwr |= MCI_PWR_ON; break; -- GitLab From 4d1a3a0dc551cfa7304ca46e014231500f3b81a6 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 13 Dec 2011 16:57:07 +0100 Subject: [PATCH 00167/10698] ARM: 7218/1: mmc: mmci: Provide option to configure bus signal direction The ST Micro variant supports bus signal direction indication. A new member in the variant struct is added for this. Moreover the actual signal direction configuration is board specific, thus the amba mmci platform data is extended with a new member to be able provide mmci with these specific board configurations. This patch is based upon a patch from Sebastian Rasmussen. Tested-by: Linus Walleij Signed-off-by: Sebastian Rasmussen Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 21 +++++++++++++++++++++ drivers/mmc/host/mmci.h | 10 ---------- include/linux/amba/mmci.h | 16 ++++++++++++++++ 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 7cc89beee87f..eb11ce61941d 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -54,6 +54,7 @@ static unsigned int fmax = 515633; * @st_clkdiv: true if using a ST-specific clock divider algorithm * @blksz_datactrl16: true if Block size is at b16..b30 position in datactrl register * @pwrreg_powerup: power up value for MMCIPOWER register + * @signal_direction: input/out direction of bus signals can be indicated */ struct variant_data { unsigned int clkreg; @@ -65,6 +66,7 @@ struct variant_data { bool st_clkdiv; bool blksz_datactrl16; u32 pwrreg_powerup; + bool signal_direction; }; static struct variant_data variant_arm = { @@ -88,6 +90,7 @@ static struct variant_data variant_u300 = { .datalength_bits = 16, .sdio = true, .pwrreg_powerup = MCI_PWR_ON, + .signal_direction = true, }; static struct variant_data variant_ux500 = { @@ -99,6 +102,7 @@ static struct variant_data variant_ux500 = { .sdio = true, .st_clkdiv = true, .pwrreg_powerup = MCI_PWR_ON, + .signal_direction = true, }; static struct variant_data variant_ux500v2 = { @@ -111,6 +115,7 @@ static struct variant_data variant_ux500v2 = { .st_clkdiv = true, .blksz_datactrl16 = true, .pwrreg_powerup = MCI_PWR_ON, + .signal_direction = true, }; /* @@ -1057,6 +1062,22 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) break; } + if (variant->signal_direction && ios->power_mode != MMC_POWER_OFF) { + /* + * The ST Micro variant has some additional bits + * indicating signal direction for the signals in + * the SD/MMC bus and feedback-clock usage. + */ + pwr |= host->plat->sigdir; + + if (ios->bus_width == MMC_BUS_WIDTH_4) + pwr &= ~MCI_ST_DATA74DIREN; + else if (ios->bus_width == MMC_BUS_WIDTH_1) + pwr &= (~MCI_ST_DATA74DIREN & + ~MCI_ST_DATA31DIREN & + ~MCI_ST_DATA2DIREN); + } + if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { if (host->hw_designer != AMBA_VENDOR_ST) pwr |= MCI_ROD; diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 49f153e6ef7a..89eb2e3556d3 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -13,16 +13,6 @@ #define MCI_PWR_ON 0x03 #define MCI_OD (1 << 6) #define MCI_ROD (1 << 7) -/* - * The ST Micro version does not have ROD and reuse the voltage registers - * for direction settings - */ -#define MCI_ST_DATA2DIREN (1 << 2) -#define MCI_ST_CMDDIREN (1 << 3) -#define MCI_ST_DATA0DIREN (1 << 4) -#define MCI_ST_DATA31DIREN (1 << 5) -#define MCI_ST_FBCLKEN (1 << 7) -#define MCI_ST_DATA74DIREN (1 << 8) #define MMCICLOCK 0x004 #define MCI_CLK_ENABLE (1 << 8) diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h index 0101e9c17fa1..b51bf5fa85f8 100644 --- a/include/linux/amba/mmci.h +++ b/include/linux/amba/mmci.h @@ -6,6 +6,19 @@ #include + +/* + * These defines is places here due to access is needed from machine + * configuration files. The ST Micro version does not have ROD and + * reuse the voltage registers for direction settings. + */ +#define MCI_ST_DATA2DIREN (1 << 2) +#define MCI_ST_CMDDIREN (1 << 3) +#define MCI_ST_DATA0DIREN (1 << 4) +#define MCI_ST_DATA31DIREN (1 << 5) +#define MCI_ST_FBCLKEN (1 << 7) +#define MCI_ST_DATA74DIREN (1 << 8) + /* Just some dummy forwarding */ struct dma_chan; @@ -31,6 +44,8 @@ struct dma_chan; * @capabilities: the capabilities of the block as implemented in * this platform, signify anything MMC_CAP_* from mmc/host.h * @capabilities2: more capabilities, MMC_CAP2_* from mmc/host.h + * @sigdir: a bit field indicating for what bits in the MMC bus the host + * should enable signal direction indication. * @dma_filter: function used to select an appropriate RX and TX * DMA channel to be used for DMA, if and only if you're deploying the * generic DMA engine @@ -54,6 +69,7 @@ struct mmci_platform_data { bool cd_invert; unsigned long capabilities; unsigned long capabilities2; + u32 sigdir; bool (*dma_filter)(struct dma_chan *chan, void *filter_param); void *dma_rx_param; void *dma_tx_param; -- GitLab From bc521818e28042bb6018d91c353d24fb01ccb162 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 13 Dec 2011 16:57:55 +0100 Subject: [PATCH 00168/10698] ARM: 7219/1: mmc: mmci: Change vdd_handler to a generic ios_handler The purpose of the vdd_handler does not make sense. We remove it and use a generic approach instead. A new ios_handler is added, the purpose of which e.g. can be to control GPIO pins to a levelshifter. Previously the vdd_handler was also used for making additional changes to the power register bits. This option is superfluous and is therefore removed. Adaptaptions from the old vdd_handler to the new ios_handler is done for mach-ux500 board, which was the only one using the vdd_handler. This patch is based upon a patch from Sebastian Rasmussen. Tested-by: Linus Walleij Signed-off-by: Sebastian Rasmussen Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- arch/arm/mach-ux500/board-mop500-sdi.c | 21 ++++++++------------- drivers/mmc/host/mmci.c | 8 ++++---- include/linux/amba/mmci.h | 6 +++--- 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-sdi.c b/arch/arm/mach-ux500/board-mop500-sdi.c index 23be34b3bb6e..4049bd7f061f 100644 --- a/arch/arm/mach-ux500/board-mop500-sdi.c +++ b/arch/arm/mach-ux500/board-mop500-sdi.c @@ -31,21 +31,13 @@ * SDI 0 (MicroSD slot) */ -/* MMCIPOWER bits */ -#define MCI_DATA2DIREN (1 << 2) -#define MCI_CMDDIREN (1 << 3) -#define MCI_DATA0DIREN (1 << 4) -#define MCI_DATA31DIREN (1 << 5) -#define MCI_FBCLKEN (1 << 7) - /* GPIO pins used by the sdi0 level shifter */ static int sdi0_en = -1; static int sdi0_vsel = -1; -static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd, - unsigned char power_mode) +static int mop500_sdi0_ios_handler(struct device *dev, struct mmc_ios *ios) { - switch (power_mode) { + switch (ios->power_mode) { case MMC_POWER_UP: case MMC_POWER_ON: /* @@ -65,8 +57,7 @@ static u32 mop500_sdi0_vdd_handler(struct device *dev, unsigned int vdd, break; } - return MCI_FBCLKEN | MCI_CMDDIREN | MCI_DATA0DIREN | - MCI_DATA2DIREN | MCI_DATA31DIREN; + return 0; } #ifdef CONFIG_STE_DMA40 @@ -90,13 +81,17 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = { #endif static struct mmci_platform_data mop500_sdi0_data = { - .vdd_handler = mop500_sdi0_vdd_handler, + .ios_handler = mop500_sdi0_ios_handler, .ocr_mask = MMC_VDD_29_30, .f_max = 50000000, .capabilities = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED, .gpio_wp = -1, + .sigdir = MCI_ST_FBCLKEN | + MCI_ST_CMDDIREN | + MCI_ST_DATA0DIREN | + MCI_ST_DATA2DIREN, #ifdef CONFIG_STE_DMA40 .dma_filter = stedma40_filter, .dma_rx_param = &mop500_sdi0_dma_cfg_rx, diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index eb11ce61941d..0af1507d15c0 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1026,6 +1026,10 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) unsigned long flags; int ret; + if (host->plat->ios_handler && + host->plat->ios_handler(mmc_dev(mmc), ios)) + dev_err(mmc_dev(mmc), "platform ios_handler failed\n"); + switch (ios->power_mode) { case MMC_POWER_OFF: if (host->vcc) @@ -1045,10 +1049,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) return; } } - if (host->plat->vdd_handler) - pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, - ios->power_mode); - /* * The ST Micro variant doesn't have the PL180s MCI_PWR_UP * and instead uses MCI_PWR_ON so apply whatever value is diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h index b51bf5fa85f8..32a89cf5ec45 100644 --- a/include/linux/amba/mmci.h +++ b/include/linux/amba/mmci.h @@ -31,7 +31,8 @@ struct dma_chan; * @ocr_mask: available voltages on the 4 pins from the block, this * is ignored if a regulator is used, see the MMC_VDD_* masks in * mmc/host.h - * @vdd_handler: a callback function to translate a MMC_VDD_* + * @ios_handler: a callback function to act on specfic ios changes, + * used for example to control a levelshifter * mask into a value to be binary (or set some other custom bits * in MMCIPWR) or:ed and written into the MMCIPWR register of the * block. May also control external power based on the power_mode. @@ -61,8 +62,7 @@ struct dma_chan; struct mmci_platform_data { unsigned int f_max; unsigned int ocr_mask; - u32 (*vdd_handler)(struct device *, unsigned int vdd, - unsigned char power_mode); + int (*ios_handler)(struct device *, struct mmc_ios *); unsigned int (*status)(struct device *); int gpio_wp; int gpio_cd; -- GitLab From 48fa700388bec2ba79e9c8cc087f39c800a6fff5 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 13 Dec 2011 16:59:34 +0100 Subject: [PATCH 00169/10698] ARM: 7221/1: mmc: mmci: Change from using legacy suspend This patch switch from using the legacy suspend/resume to the new way of registering PM callbacks. No functional change is done. Tested-by: Linus Walleij Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 0af1507d15c0..544995b3cb95 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -1456,10 +1456,11 @@ static int __devexit mmci_remove(struct amba_device *dev) return 0; } -#ifdef CONFIG_PM -static int mmci_suspend(struct amba_device *dev, pm_message_t state) +#ifdef CONFIG_SUSPEND +static int mmci_suspend(struct device *dev) { - struct mmc_host *mmc = amba_get_drvdata(dev); + struct amba_device *adev = to_amba_device(dev); + struct mmc_host *mmc = amba_get_drvdata(adev); int ret = 0; if (mmc) { @@ -1473,9 +1474,10 @@ static int mmci_suspend(struct amba_device *dev, pm_message_t state) return ret; } -static int mmci_resume(struct amba_device *dev) +static int mmci_resume(struct device *dev) { - struct mmc_host *mmc = amba_get_drvdata(dev); + struct amba_device *adev = to_amba_device(dev); + struct mmc_host *mmc = amba_get_drvdata(adev); int ret = 0; if (mmc) { @@ -1488,11 +1490,12 @@ static int mmci_resume(struct amba_device *dev) return ret; } -#else -#define mmci_suspend NULL -#define mmci_resume NULL #endif +static const struct dev_pm_ops mmci_dev_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(mmci_suspend, mmci_resume) +}; + static struct amba_id mmci_ids[] = { { .id = 0x00041180, @@ -1538,11 +1541,10 @@ MODULE_DEVICE_TABLE(amba, mmci_ids); static struct amba_driver mmci_driver = { .drv = { .name = DRIVER_NAME, + .pm = &mmci_dev_pm_ops, }, .probe = mmci_probe, .remove = __devexit_p(mmci_remove), - .suspend = mmci_suspend, - .resume = mmci_resume, .id_table = mmci_ids, }; -- GitLab From 2cd976c46472e34460349ed43a217e34f90bad55 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 13 Dec 2011 17:01:11 +0100 Subject: [PATCH 00170/10698] ARM: 7223/1: mmc: mmci: Fixup use of runtime PM and use autosuspend Added use of runtime PM autosuspend feature, with a fixed timeout of 50 ms. This will prevent adding a latency, although very minor, for _every_ request. Moreover the runtime_get_sync is now also used in set_ios and suspend since the runtime resourses are needed here as well. Tested-by: Linus Walleij Signed-off-by: Ulf Hansson Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 544995b3cb95..6a21fc0bf3d8 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -178,8 +178,10 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) host->mrq = NULL; host->cmd = NULL; - pm_runtime_put(mmc_dev(host->mmc)); mmc_request_done(host->mmc, mrq); + + pm_runtime_mark_last_busy(mmc_dev(host->mmc)); + pm_runtime_put_autosuspend(mmc_dev(host->mmc)); } static void mmci_set_mask1(struct mmci_host *host, unsigned int mask) @@ -1026,6 +1028,8 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) unsigned long flags; int ret; + pm_runtime_get_sync(mmc_dev(mmc)); + if (host->plat->ios_handler && host->plat->ios_handler(mmc_dev(mmc), ios)) dev_err(mmc_dev(mmc), "platform ios_handler failed\n"); @@ -1046,7 +1050,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * power should be rare so we print an error * and return here. */ - return; + goto out; } } /* @@ -1100,6 +1104,10 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } spin_unlock_irqrestore(&host->lock, flags); + + out: + pm_runtime_mark_last_busy(mmc_dev(mmc)); + pm_runtime_put_autosuspend(mmc_dev(mmc)); } static int mmci_get_ro(struct mmc_host *mmc) @@ -1372,6 +1380,8 @@ static int __devinit mmci_probe(struct amba_device *dev, mmci_dma_setup(host); + pm_runtime_set_autosuspend_delay(&dev->dev, 50); + pm_runtime_use_autosuspend(&dev->dev); pm_runtime_put(&dev->dev); mmc_add_host(mmc); @@ -1467,8 +1477,10 @@ static int mmci_suspend(struct device *dev) struct mmci_host *host = mmc_priv(mmc); ret = mmc_suspend_host(mmc); - if (ret == 0) + if (ret == 0) { + pm_runtime_get_sync(dev); writel(0, host->base + MMCIMASK0); + } } return ret; @@ -1484,6 +1496,7 @@ static int mmci_resume(struct device *dev) struct mmci_host *host = mmc_priv(mmc); writel(MCI_IRQENABLE, host->base + MMCIMASK0); + pm_runtime_put(dev); ret = mmc_resume_host(mmc); } -- GitLab From 7258db7efe7d9c5eb80151554faa1fa7411d6e3e Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 13 Dec 2011 17:05:28 +0100 Subject: [PATCH 00171/10698] ARM: 7227/1: mmc: mmci: Prepare for SDIO before setting up DMA job Move the SDIO preparation to be done before the DMA job is setup. This makes it possible to do DMA for SDIO transfers as well as the earlier supported pio mode. Signed-off-by: Ulf Hansson Signed-off-by: Stefan Nilsson XK Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 6a21fc0bf3d8..b09ccb7223e5 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -615,6 +615,11 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) if (data->flags & MMC_DATA_READ) datactrl |= MCI_DPSM_DIRECTION; + /* The ST Micro variants has a special bit to enable SDIO */ + if (variant->sdio && host->mmc->card) + if (mmc_card_sdio(host->mmc->card)) + datactrl |= MCI_ST_DPSM_SDIOEN; + /* * Attempt to use DMA operation mode, if this * should fail, fall back to PIO mode @@ -643,11 +648,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) irqmask = MCI_TXFIFOHALFEMPTYMASK; } - /* The ST Micro variants has a special bit to enable SDIO */ - if (variant->sdio && host->mmc->card) - if (mmc_card_sdio(host->mmc->card)) - datactrl |= MCI_ST_DPSM_SDIOEN; - writel(datactrl, base + MMCIDATACTRL); writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); mmci_set_mask1(host, irqmask); -- GitLab From 393e5e24165d0bef60489ecd0baef085e9af2e5a Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 13 Dec 2011 17:08:04 +0100 Subject: [PATCH 00172/10698] ARM: 7230/1: mmc: mmci: Fix PIO read for small SDIO packets Corrects a bug in MMCI host driver which silently causes small reads (< 4 bytes as only used in SDIO) from PL-18X to fail. Signed-off-by: Stefan Nilsson XK Signed-off-by: Ulf Hansson Signed-off-by: Fredrik Soderstedt Signed-off-by: Russell King --- drivers/mmc/host/mmci.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index b09ccb7223e5..1f8832699cdf 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -794,7 +794,24 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema if (count <= 0) break; - readsl(base + MMCIFIFO, ptr, count >> 2); + /* + * SDIO especially may want to send something that is + * not divisible by 4 (as opposed to card sectors + * etc). Therefore make sure to always read the last bytes + * while only doing full 32-bit reads towards the FIFO. + */ + if (unlikely(count & 0x3)) { + if (count < 4) { + unsigned char buf[4]; + readsl(base + MMCIFIFO, buf, 1); + memcpy(ptr, buf, count); + } else { + readsl(base + MMCIFIFO, ptr, count >> 2); + count &= ~0x3; + } + } else { + readsl(base + MMCIFIFO, ptr, count >> 2); + } ptr += count; remain -= count; -- GitLab From ec00466944bb10d4c91d889d11cc90055115df8f Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Tue, 27 Dec 2011 17:16:47 +0900 Subject: [PATCH 00173/10698] ARM: EXYNOS: add G2D to mach-nuri Signed-off-by: Kamil Debski Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 1 + arch/arm/mach-exynos/mach-nuri.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 5d602f68a0e8..abfa9c5213e7 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -273,6 +273,7 @@ config MACH_NURI select S5P_DEV_FIMC1 select S5P_DEV_FIMC2 select S5P_DEV_FIMC3 + select S5P_DEV_G2D select S5P_DEV_MFC select S5P_DEV_USB_EHCI select S5P_SETUP_MIPIPHY diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c index b895ec031105..165c87638895 100644 --- a/arch/arm/mach-exynos/mach-nuri.c +++ b/arch/arm/mach-exynos/mach-nuri.c @@ -1259,6 +1259,7 @@ static struct platform_device *nuri_devices[] __initdata = { &s3c_device_i2c3, &i2c9_gpio, &s3c_device_adc, + &s5p_device_g2d, &s3c_device_rtc, &s5p_device_mfc, &s5p_device_mfc_l, -- GitLab From 2cd11b09a3a0ba2f247bf740e2213b912760a1b2 Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Tue, 27 Dec 2011 17:16:50 +0900 Subject: [PATCH 00174/10698] ARM: EXYNOS: add G2D to mach-universal Signed-off-by: Kamil Debski Signed-off-by: Kyungmin Park Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 1 + arch/arm/mach-exynos/mach-universal_c210.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index abfa9c5213e7..e7830fd4bc31 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -230,6 +230,7 @@ config MACH_UNIVERSAL_C210 select S5P_DEV_FIMC1 select S5P_DEV_FIMC2 select S5P_DEV_FIMC3 + select S5P_DEV_G2D select S5P_DEV_CSIS0 select S5P_DEV_FIMD0 select S3C_DEV_HSMMC diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c index 37ac93e8d6d9..dd7510170e5a 100644 --- a/arch/arm/mach-exynos/mach-universal_c210.c +++ b/arch/arm/mach-exynos/mach-universal_c210.c @@ -960,6 +960,7 @@ static struct platform_device *universal_devices[] __initdata = { &s5p_device_fimc1, &s5p_device_fimc2, &s5p_device_fimc3, + &s5p_device_g2d, &mmc0_fixed_voltage, &s3c_device_hsmmc0, &s3c_device_hsmmc2, -- GitLab From 62d30f86f1f76e11819fb06c1597c7e7f1d620c2 Mon Sep 17 00:00:00 2001 From: Sangwook Lee Date: Thu, 3 Nov 2011 16:14:14 +0900 Subject: [PATCH 00175/10698] ARM: EXYNOS: Enable Bluetooth on ORIGEN This patch enables Bluetooth support on ORIGEN board. Signed-off-by: Sangwook Lee Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/mach-origen.c | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 0679b8ad2d1e..7bf8133502b3 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -235,6 +236,7 @@ static struct regulator_init_data __initdata max8997_ldo9_data = { .min_uV = 2800000, .max_uV = 2800000, .apply_uV = 1, + .always_on = 1, .valid_ops_mask = REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = 1, @@ -278,6 +280,7 @@ static struct regulator_init_data __initdata max8997_ldo14_data = { .min_uV = 1800000, .max_uV = 1800000, .apply_uV = 1, + .always_on = 1, .valid_ops_mask = REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = 1, @@ -293,6 +296,7 @@ static struct regulator_init_data __initdata max8997_ldo17_data = { .min_uV = 3300000, .max_uV = 3300000, .apply_uV = 1, + .always_on = 1, .valid_ops_mask = REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = 1, @@ -602,6 +606,23 @@ static struct s3c_fb_platdata origen_lcd_pdata __initdata = { .setup_gpio = exynos4_fimd0_gpio_setup_24bpp, }; +/* Bluetooth rfkill gpio platform data */ +struct rfkill_gpio_platform_data origen_bt_pdata = { + .reset_gpio = EXYNOS4_GPX2(2), + .shutdown_gpio = -1, + .type = RFKILL_TYPE_BLUETOOTH, + .name = "origen-bt", +}; + +/* Bluetooth Platform device */ +static struct platform_device origen_device_bluetooth = { + .name = "rfkill_gpio", + .id = -1, + .dev = { + .platform_data = &origen_bt_pdata, + }, +}; + static struct platform_device *origen_devices[] __initdata = { &s3c_device_hsmmc2, &s3c_device_hsmmc0, @@ -630,6 +651,7 @@ static struct platform_device *origen_devices[] __initdata = { &exynos4_device_pd[PD_MFC], &origen_device_gpiokeys, &origen_lcd_hv070wsa, + &origen_device_bluetooth, }; /* LCD Backlight data */ @@ -643,6 +665,16 @@ static struct platform_pwm_backlight_data origen_bl_data = { .pwm_period_ns = 1000, }; +static void __init origen_bt_setup(void) +{ + gpio_request(EXYNOS4_GPA0(0), "GPIO BT_UART"); + /* 4 UART Pins configuration */ + s3c_gpio_cfgrange_nopull(EXYNOS4_GPA0(0), 4, S3C_GPIO_SFN(2)); + /* Setup BT Reset, this gpio will be requesed by rfkill-gpio */ + s3c_gpio_cfgpin(EXYNOS4_GPX2(2), S3C_GPIO_OUTPUT); + s3c_gpio_setpull(EXYNOS4_GPX2(2), S3C_GPIO_PULL_NONE); +} + static void s5p_tv_setup(void) { /* Direct HPD to HDMI chip */ @@ -703,6 +735,8 @@ static void __init origen_machine_init(void) s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev; samsung_bl_set(&origen_bl_gpio_info, &origen_bl_data); + + origen_bt_setup(); } MACHINE_START(ORIGEN, "ORIGEN") -- GitLab From 84207d83adc9a9b97d45d9cefaaf0ca766891b92 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Thu, 29 Dec 2011 16:46:16 +0900 Subject: [PATCH 00176/10698] ARM: EXYNOS: Enable G2D on ORIGEN This patch enables G2D support on ORIGEN board. Signed-off-by: Sachin Kamat Signed-off-by: Kukjin Kim --- arch/arm/mach-exynos/Kconfig | 1 + arch/arm/mach-exynos/mach-origen.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index e7830fd4bc31..bd4600eaa7d8 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -305,6 +305,7 @@ config MACH_ORIGEN select S5P_DEV_FIMC2 select S5P_DEV_FIMC3 select S5P_DEV_FIMD0 + select S5P_DEV_G2D select S5P_DEV_I2C_HDMIPHY select S5P_DEV_MFC select S5P_DEV_TV diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c index 7bf8133502b3..e1d87b9a33e3 100644 --- a/arch/arm/mach-exynos/mach-origen.c +++ b/arch/arm/mach-exynos/mach-origen.c @@ -635,6 +635,7 @@ static struct platform_device *origen_devices[] __initdata = { &s5p_device_fimc2, &s5p_device_fimc3, &s5p_device_fimd0, + &s5p_device_g2d, &s5p_device_hdmi, &s5p_device_i2c_hdmiphy, &s5p_device_mfc, -- GitLab From 66211f98d611056bf5fe918bbda37c636688574e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 29 Dec 2011 18:05:29 +0900 Subject: [PATCH 00177/10698] ARM: S3C64XX: Support GPIO LEDs on Cragganmore Cragganmore has a bank of 8 LEDs connected to the memory mapped GPIO bank, mostly intended for low level diagnostics. Register these with the LED subsystem for runtime use. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/Kconfig | 1 + arch/arm/mach-s3c64xx/mach-crag6410.c | 51 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/arch/arm/mach-s3c64xx/Kconfig b/arch/arm/mach-s3c64xx/Kconfig index dd20c66cd700..dc451232cf47 100644 --- a/arch/arm/mach-s3c64xx/Kconfig +++ b/arch/arm/mach-s3c64xx/Kconfig @@ -296,5 +296,6 @@ config MACH_WLF_CRAGG_6410 select S3C64XX_DEV_SPI0 select SAMSUNG_GPIO_EXTRA128 select I2C + select LEDS_GPIO_REGISTER help Machine support for the Wolfson Cragganmore S3C6410 variant. diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 8077f650eb0e..9da2d78f12f2 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -698,6 +699,54 @@ static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = { .cfg_gpio = crag6410_cfg_sdhci0, }; +static const struct gpio_led gpio_leds[] = { + { + .name = "d13:green:", + .gpio = MMGPIO_GPIO_BASE + 0, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "d14:green:", + .gpio = MMGPIO_GPIO_BASE + 1, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "d15:green:", + .gpio = MMGPIO_GPIO_BASE + 2, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "d16:green:", + .gpio = MMGPIO_GPIO_BASE + 3, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "d17:green:", + .gpio = MMGPIO_GPIO_BASE + 4, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "d18:green:", + .gpio = MMGPIO_GPIO_BASE + 5, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "d19:green:", + .gpio = MMGPIO_GPIO_BASE + 6, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, + { + .name = "d20:green:", + .gpio = MMGPIO_GPIO_BASE + 7, + .default_state = LEDS_GPIO_DEFSTATE_ON, + }, +}; + +static const struct gpio_led_platform_data gpio_leds_pdata = { + .leds = gpio_leds, + .num_leds = ARRAY_SIZE(gpio_leds), +}; + static void __init crag6410_machine_init(void) { /* Open drain IRQs need pullups */ @@ -730,6 +779,8 @@ static void __init crag6410_machine_init(void) platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices)); + gpio_led_register_device(-1, &gpio_leds_pdata); + regulator_has_full_constraints(); s3c64xx_pm_init(); -- GitLab From 6e2f2b4a4bf7b351df0ada2a0d626478a4f82b8e Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 30 Dec 2011 10:00:07 +0900 Subject: [PATCH 00178/10698] ARM: S3C64XX: Fix build of Cragganmore after SPI changes Commit 875a59 (ARM: SAMSUNG: Consolidation of SPI platform devices to plat-samsung) replaced the function s3c64xx_spi_set_info() with s3c64xx_spiN_set_platdata() but did not update all the machines, with Cragganmore being left. Fix that. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-crag6410.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 9da2d78f12f2..97bd8574d4c9 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -776,6 +776,7 @@ static void __init crag6410_machine_init(void) i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1)); samsung_keypad_set_platdata(&crag6410_keypad_data); + s3c64xx_spi0_set_platdata(NULL, 0, 1); platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices)); -- GitLab From fb7f60f3ff46cdcee15aed089edd6c298a1b80de Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 30 Dec 2011 13:44:31 +0900 Subject: [PATCH 00179/10698] ARM: S3C64XX: Enable power management for disk on Cragganmore We can happily let the MMC stack do power management for the MMC card that is our main disk on Cragganmore so let's enable it. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-crag6410.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 97bd8574d4c9..894a5092a0dd 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -697,6 +698,7 @@ static struct s3c_sdhci_platdata crag6410_hsmmc0_pdata = { .max_width = 4, .cd_type = S3C_SDHCI_CD_INTERNAL, .cfg_gpio = crag6410_cfg_sdhci0, + .host_caps = MMC_CAP_POWER_OFF_CARD, }; static const struct gpio_led gpio_leds[] = { -- GitLab From a9294cdc17d4f9d16eac3bc42afba9e96c6ad4e4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 30 Dec 2011 13:44:36 +0900 Subject: [PATCH 00180/10698] ARM: S3C64XX: Enable power management for WiFi on Cragganmore Allow the SDHCI stack to runtime power manage the WiFi card on Cragganmore for better power optimisation. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-crag6410.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 894a5092a0dd..7539a2999178 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -683,6 +683,7 @@ static void __init crag6410_map_io(void) static struct s3c_sdhci_platdata crag6410_hsmmc2_pdata = { .max_width = 4, .cd_type = S3C_SDHCI_CD_PERMANENT, + .host_caps = MMC_CAP_POWER_OFF_CARD, }; static void crag6410_cfg_sdhci0(struct platform_device *dev, int width) -- GitLab From cda2349a9b63fc51f3ca2953020e0f5ea9e2965c Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Jan 2012 11:04:56 +0900 Subject: [PATCH 00181/10698] ARM: S3C64XX: Add hookup for Tomatin module on Cragganmore The Tomatin module carries a WM0010 audio DSP. Provide basic hookup for this, though additional platform data will be needed to fully integrate with the driver. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/mach-crag6410-module.c | 27 +++++++++++++++++++- arch/arm/mach-s3c64xx/mach-crag6410.c | 11 +++++++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c index cd3c97e2ee75..b4ed351e701d 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -21,8 +22,25 @@ #include #include +#include + #include +static struct s3c64xx_spi_csinfo wm0010_spi_csinfo = { + .set_level = gpio_set_value, + .line = S3C64XX_GPC(3), +}; + +static struct spi_board_info wm1253_devs[] = { + [0] = { + .modalias = "wm0010", + .bus_num = 0, + .chip_select = 0, + .mode = SPI_MODE_0, + .controller_data = &wm0010_spi_csinfo, + }, +}; + static struct wm5100_pdata wm5100_pdata = { .ldo_ena = S3C64XX_GPN(7), .irq_flags = IRQF_TRIGGER_HIGH, @@ -158,6 +176,8 @@ static __devinitdata const struct { const char *name; const struct i2c_board_info *i2c_devs; int num_i2c_devs; + const struct spi_board_info *spi_devs; + int num_spi_devs; } gf_mods[] = { { .id = 0x01, .name = "1250-EV1 Springbank" }, { .id = 0x02, .name = "1251-EV1 Jura" }, @@ -165,7 +185,8 @@ static __devinitdata const struct { { .id = 0x11, .name = "6249-EV2 Glenfarclas", }, { .id = 0x21, .name = "1275-EV1 Mortlach" }, { .id = 0x25, .name = "1274-EV1 Glencadam" }, - { .id = 0x31, .name = "1253-EV1 Tomatin", }, + { .id = 0x31, .name = "1253-EV1 Tomatin", + .spi_devs = wm1253_devs, .num_spi_devs = ARRAY_SIZE(wm1253_devs) }, { .id = 0x39, .name = "1254-EV1 Dallas Dhu", .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) }, { .id = 0x3a, .name = "1259-EV1 Tobermory", @@ -197,12 +218,16 @@ static __devinit int wlf_gf_module_probe(struct i2c_client *i2c, if (i < ARRAY_SIZE(gf_mods)) { dev_info(&i2c->dev, "%s revision %d\n", gf_mods[i].name, rev + 1); + for (j = 0; j < gf_mods[i].num_i2c_devs; j++) { if (!i2c_new_device(i2c->adapter, &(gf_mods[i].i2c_devs[j]))) dev_err(&i2c->dev, "Failed to register dev: %d\n", ret); } + + spi_register_board_info(gf_mods[i].spi_devs, + gf_mods[i].num_spi_devs); } else { dev_warn(&i2c->dev, "Unknown module ID 0x%x revision %d\n", id, rev + 1); diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c index 7539a2999178..f93caad1dd9b 100644 --- a/arch/arm/mach-s3c64xx/mach-crag6410.c +++ b/arch/arm/mach-s3c64xx/mach-crag6410.c @@ -576,11 +576,19 @@ static struct s3c2410_platform_i2c i2c0_pdata = { .frequency = 400000, }; +static struct regulator_consumer_supply pvdd_1v2_consumers[] __initdata = { + REGULATOR_SUPPLY("DCVDD", "spi0.0"), + REGULATOR_SUPPLY("AVDD", "spi0.0"), +}; + static struct regulator_init_data pvdd_1v2 __initdata = { .constraints = { .name = "PVDD_1V2", - .always_on = 1, + .valid_ops_mask = REGULATOR_CHANGE_STATUS, }, + + .consumer_supplies = pvdd_1v2_consumers, + .num_consumer_supplies = ARRAY_SIZE(pvdd_1v2_consumers), }; static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = { @@ -594,6 +602,7 @@ static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = { REGULATOR_SUPPLY("AVDD2", "1-001a"), REGULATOR_SUPPLY("DCVDD", "1-001a"), REGULATOR_SUPPLY("AVDD", "1-001a"), + REGULATOR_SUPPLY("DBVDD", "spi0.0"), }; static struct regulator_init_data pvdd_1v8 __initdata = { -- GitLab From 2abf13c9ffdcde537fc54b83f1bcd50cc758beca Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Sat, 24 Dec 2011 11:38:27 +0900 Subject: [PATCH 00182/10698] ARM: S3C64XX: Add basic cpuidle driver Add a very basic cpuidle driver for S3C64xx which merely drives the CPU into IDLE mode. We could do this with pm_idle but the more modern idiom is to use cpuidle and the intention is to go further and support STOP and DEEP-STOP states in conjunction with the pm_domain framework. The actual state entry code was lifted from Tomasz Figa's work on spica. Signed-off-by: Mark Brown Signed-off-by: Kukjin Kim --- arch/arm/mach-s3c64xx/Makefile | 1 + arch/arm/mach-s3c64xx/cpuidle.c | 91 +++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 arch/arm/mach-s3c64xx/cpuidle.c diff --git a/arch/arm/mach-s3c64xx/Makefile b/arch/arm/mach-s3c64xx/Makefile index 1822ac2eba31..610fe2807ed7 100644 --- a/arch/arm/mach-s3c64xx/Makefile +++ b/arch/arm/mach-s3c64xx/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_CPU_S3C6410) += s3c6410.o # PM obj-$(CONFIG_PM) += pm.o irq-pm.o sleep.o +obj-$(CONFIG_CPU_IDLE) += cpuidle.o # DMA support diff --git a/arch/arm/mach-s3c64xx/cpuidle.c b/arch/arm/mach-s3c64xx/cpuidle.c new file mode 100644 index 000000000000..625d2c7b4540 --- /dev/null +++ b/arch/arm/mach-s3c64xx/cpuidle.c @@ -0,0 +1,91 @@ +/* linux/arch/arm/mach-s3c64xx/cpuidle.c + * + * Copyright (c) 2011 Wolfson Microelectronics, plc + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +static int s3c64xx_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + struct timeval before, after; + unsigned long tmp; + int idle_time; + + local_irq_disable(); + do_gettimeofday(&before); + + /* Setup PWRCFG to enter idle mode */ + tmp = __raw_readl(S3C64XX_PWR_CFG); + tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK; + tmp |= S3C64XX_PWRCFG_CFG_WFI_IDLE; + __raw_writel(tmp, S3C64XX_PWR_CFG); + + cpu_do_idle(); + + do_gettimeofday(&after); + local_irq_enable(); + idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC + + (after.tv_usec - before.tv_usec); + + dev->last_residency = idle_time; + return index; +} + +static struct cpuidle_state s3c64xx_cpuidle_set[] = { + [0] = { + .enter = s3c64xx_enter_idle, + .exit_latency = 1, + .target_residency = 100000, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "IDLE", + .desc = "System active, ARM gated", + }, +}; + +static struct cpuidle_driver s3c64xx_cpuidle_driver = { + .name = "s3c64xx_cpuidle", + .owner = THIS_MODULE, + .state_count = ARRAY_SIZE(s3c64xx_cpuidle_set), +}; + +static struct cpuidle_device s3c64xx_cpuidle_device = { + .state_count = ARRAY_SIZE(s3c64xx_cpuidle_set), +}; + +static int __init s3c64xx_init_cpuidle(void) +{ + int ret; + + memcpy(s3c64xx_cpuidle_driver.states, s3c64xx_cpuidle_set, + sizeof(s3c64xx_cpuidle_set)); + cpuidle_register_driver(&s3c64xx_cpuidle_driver); + + ret = cpuidle_register_device(&s3c64xx_cpuidle_device); + if (ret) { + pr_err("Failed to register cpuidle device: %d\n", ret); + return ret; + } + + return 0; +} +device_initcall(s3c64xx_init_cpuidle); -- GitLab From f0c28b0075cad861f4b93c526c6446169d136466 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Sat, 14 Jan 2012 16:56:43 +0800 Subject: [PATCH 00183/10698] devfreq: exynos4_bus: Use dev_get_drvdata at appropriate places Signed-off-by: Axel Lin Signed-off-by: MyungJoo Ham --- drivers/devfreq/exynos4_bus.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c index 6460577d6701..489ccfa93a96 100644 --- a/drivers/devfreq/exynos4_bus.c +++ b/drivers/devfreq/exynos4_bus.c @@ -622,9 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, static int exynos4_bus_target(struct device *dev, unsigned long *_freq) { int err = 0; - struct platform_device *pdev = container_of(dev, struct platform_device, - dev); - struct busfreq_data *data = platform_get_drvdata(pdev); + struct busfreq_data *data = dev_get_drvdata(dev); struct opp *opp = devfreq_recommended_opp(dev, _freq); unsigned long old_freq = opp_get_freq(data->curr_opp); unsigned long freq = opp_get_freq(opp); @@ -689,9 +687,7 @@ static int exynos4_get_busier_dmc(struct busfreq_data *data) static int exynos4_bus_get_dev_status(struct device *dev, struct devfreq_dev_status *stat) { - struct platform_device *pdev = container_of(dev, struct platform_device, - dev); - struct busfreq_data *data = platform_get_drvdata(pdev); + struct busfreq_data *data = dev_get_drvdata(dev); int busier_dmc; int cycles_x2 = 2; /* 2 x cycles */ void __iomem *addr; @@ -739,9 +735,7 @@ static int exynos4_bus_get_dev_status(struct device *dev, static void exynos4_bus_exit(struct device *dev) { - struct platform_device *pdev = container_of(dev, struct platform_device, - dev); - struct busfreq_data *data = platform_get_drvdata(pdev); + struct busfreq_data *data = dev_get_drvdata(dev); devfreq_unregister_opp_notifier(dev, data->devfreq); } @@ -1087,9 +1081,7 @@ static __devexit int exynos4_busfreq_remove(struct platform_device *pdev) static int exynos4_busfreq_resume(struct device *dev) { - struct platform_device *pdev = container_of(dev, struct platform_device, - dev); - struct busfreq_data *data = platform_get_drvdata(pdev); + struct busfreq_data *data = dev_get_drvdata(dev); busfreq_mon_reset(data); return 0; -- GitLab From e0d44e8ab06885a5bb980f3d6d4cf64ad430d406 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Mon, 16 Jan 2012 14:53:08 +0800 Subject: [PATCH 00184/10698] devfreq: Remove MODULE_ALIAS for exynos4 busfreq driver This driver can only be built-in, it does not make sense to add modalias for it (in addition to being incorrect, the platform modalias needs to be prefixed with "platform:"). Signed-off-by: Axel Lin Signed-off-by: MyungJoo Ham --- drivers/devfreq/exynos4_bus.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c index 489ccfa93a96..590d6865e388 100644 --- a/drivers/devfreq/exynos4_bus.c +++ b/drivers/devfreq/exynos4_bus.c @@ -1124,4 +1124,3 @@ module_exit(exynos4_busfreq_exit); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("EXYNOS4 busfreq driver with devfreq framework"); MODULE_AUTHOR("MyungJoo Ham "); -MODULE_ALIAS("exynos4-busfreq"); -- GitLab From a95e1f5dbca385908aa4087bb98470b0e0ac58d8 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Wed, 11 Jan 2012 17:44:28 +0900 Subject: [PATCH 00185/10698] PM / devfreq: fixed syntax errors. If devfreq.h was included without CONFIG_PM_DEVFREQ, there has been a compiler error with an additional semicolon added. This patch removes that errorneous semicolon. Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park --- include/linux/devfreq.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index 98ce8124b1cc..f7eb7d06df7e 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -200,12 +200,12 @@ struct devfreq_simple_ondemand_data { static struct devfreq *devfreq_add_device(struct device *dev, struct devfreq_dev_profile *profile, struct devfreq_governor *governor, - void *data); + void *data) { return NULL; } -static int devfreq_remove_device(struct devfreq *devfreq); +static int devfreq_remove_device(struct devfreq *devfreq) { return 0; } -- GitLab From 6530b9dea1b7f33eaf79ba625e3a99f2455f3eb1 Mon Sep 17 00:00:00 2001 From: MyungJoo Ham Date: Fri, 9 Dec 2011 16:42:19 +0900 Subject: [PATCH 00186/10698] PM / devfreq: add min/max_freq limit requested by users. The frequency requested to devfreq device driver from devfreq governors is restricted by min_freq and max_freq input. Signed-off-by: MyungJoo Ham Signed-off-by: Kyungmin Park --- drivers/devfreq/devfreq.c | 70 +++++++++++++++++++++++ drivers/devfreq/governor_performance.c | 5 +- drivers/devfreq/governor_powersave.c | 2 +- drivers/devfreq/governor_simpleondemand.c | 12 +++- drivers/devfreq/governor_userspace.c | 15 ++++- include/linux/devfreq.h | 5 ++ 6 files changed, 101 insertions(+), 8 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index c189b82f5ece..a129a7b6bfd1 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -501,12 +501,82 @@ static ssize_t show_central_polling(struct device *dev, !to_devfreq(dev)->governor->no_central_polling); } +static ssize_t store_min_freq(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct devfreq *df = to_devfreq(dev); + unsigned long value; + int ret; + unsigned long max; + + ret = sscanf(buf, "%lu", &value); + if (ret != 1) + goto out; + + mutex_lock(&df->lock); + max = df->max_freq; + if (value && max && value > max) { + ret = -EINVAL; + goto unlock; + } + + df->min_freq = value; + update_devfreq(df); + ret = count; +unlock: + mutex_unlock(&df->lock); +out: + return ret; +} + +static ssize_t show_min_freq(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%lu\n", to_devfreq(dev)->min_freq); +} + +static ssize_t store_max_freq(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct devfreq *df = to_devfreq(dev); + unsigned long value; + int ret; + unsigned long min; + + ret = sscanf(buf, "%lu", &value); + if (ret != 1) + goto out; + + mutex_lock(&df->lock); + min = df->min_freq; + if (value && min && value < min) { + ret = -EINVAL; + goto unlock; + } + + df->max_freq = value; + update_devfreq(df); + ret = count; +unlock: + mutex_unlock(&df->lock); +out: + return ret; +} + +static ssize_t show_max_freq(struct device *dev, struct device_attribute *attr, + char *buf) +{ + return sprintf(buf, "%lu\n", to_devfreq(dev)->max_freq); +} + static struct device_attribute devfreq_attrs[] = { __ATTR(governor, S_IRUGO, show_governor, NULL), __ATTR(cur_freq, S_IRUGO, show_freq, NULL), __ATTR(central_polling, S_IRUGO, show_central_polling, NULL), __ATTR(polling_interval, S_IRUGO | S_IWUSR, show_polling_interval, store_polling_interval), + __ATTR(min_freq, S_IRUGO | S_IWUSR, show_min_freq, store_min_freq), + __ATTR(max_freq, S_IRUGO | S_IWUSR, show_max_freq, store_max_freq), { }, }; diff --git a/drivers/devfreq/governor_performance.c b/drivers/devfreq/governor_performance.c index c0596b291761..574a06b1b1de 100644 --- a/drivers/devfreq/governor_performance.c +++ b/drivers/devfreq/governor_performance.c @@ -18,7 +18,10 @@ static int devfreq_performance_func(struct devfreq *df, * target callback should be able to get floor value as * said in devfreq.h */ - *freq = UINT_MAX; + if (!df->max_freq) + *freq = UINT_MAX; + else + *freq = df->max_freq; return 0; } diff --git a/drivers/devfreq/governor_powersave.c b/drivers/devfreq/governor_powersave.c index 2483a85a266f..d742d4a82d6a 100644 --- a/drivers/devfreq/governor_powersave.c +++ b/drivers/devfreq/governor_powersave.c @@ -18,7 +18,7 @@ static int devfreq_powersave_func(struct devfreq *df, * target callback should be able to get ceiling value as * said in devfreq.h */ - *freq = 0; + *freq = df->min_freq; return 0; } diff --git a/drivers/devfreq/governor_simpleondemand.c b/drivers/devfreq/governor_simpleondemand.c index efad8dcf9028..a2e3eae79011 100644 --- a/drivers/devfreq/governor_simpleondemand.c +++ b/drivers/devfreq/governor_simpleondemand.c @@ -25,6 +25,7 @@ static int devfreq_simple_ondemand_func(struct devfreq *df, unsigned int dfso_upthreshold = DFSO_UPTHRESHOLD; unsigned int dfso_downdifferential = DFSO_DOWNDIFFERENCTIAL; struct devfreq_simple_ondemand_data *data = df->data; + unsigned long max = (df->max_freq) ? df->max_freq : UINT_MAX; if (err) return err; @@ -41,7 +42,7 @@ static int devfreq_simple_ondemand_func(struct devfreq *df, /* Assume MAX if it is going to be divided by zero */ if (stat.total_time == 0) { - *freq = UINT_MAX; + *freq = max; return 0; } @@ -54,13 +55,13 @@ static int devfreq_simple_ondemand_func(struct devfreq *df, /* Set MAX if it's busy enough */ if (stat.busy_time * 100 > stat.total_time * dfso_upthreshold) { - *freq = UINT_MAX; + *freq = max; return 0; } /* Set MAX if we do not know the initial frequency */ if (stat.current_frequency == 0) { - *freq = UINT_MAX; + *freq = max; return 0; } @@ -79,6 +80,11 @@ static int devfreq_simple_ondemand_func(struct devfreq *df, b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2)); *freq = (unsigned long) b; + if (df->min_freq && *freq < df->min_freq) + *freq = df->min_freq; + if (df->max_freq && *freq > df->max_freq) + *freq = df->max_freq; + return 0; } diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c index 4f8b563da782..0681246fc89d 100644 --- a/drivers/devfreq/governor_userspace.c +++ b/drivers/devfreq/governor_userspace.c @@ -25,10 +25,19 @@ static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq) { struct userspace_data *data = df->data; - if (!data->valid) + if (data->valid) { + unsigned long adjusted_freq = data->user_frequency; + + if (df->max_freq && adjusted_freq > df->max_freq) + adjusted_freq = df->max_freq; + + if (df->min_freq && adjusted_freq < df->min_freq) + adjusted_freq = df->min_freq; + + *freq = adjusted_freq; + } else { *freq = df->previous_freq; /* No user freq specified yet */ - else - *freq = data->user_frequency; + } return 0; } diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h index f7eb7d06df7e..5862475d05f8 100644 --- a/include/linux/devfreq.h +++ b/include/linux/devfreq.h @@ -124,6 +124,8 @@ struct devfreq_governor { * touch this. * @being_removed a flag to mark that this object is being removed in * order to prevent trying to remove the object multiple times. + * @min_freq Limit minimum frequency requested by user (0: none) + * @max_freq Limit maximum frequency requested by user (0: none) * * This structure stores the devfreq information for a give device. * @@ -149,6 +151,9 @@ struct devfreq { void *data; /* private data for governors */ bool being_removed; + + unsigned long min_freq; + unsigned long max_freq; }; #if defined(CONFIG_PM_DEVFREQ) -- GitLab From f4a0391dfa91155bd961673b31eb42d9d45c799d Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Thu, 5 Jan 2012 12:49:54 -0200 Subject: [PATCH 00187/10698] ima: fix Kconfig dependencies Fix the following build warning: warning: (IMA) selects TCG_TPM which has unmet direct dependencies (HAS_IOMEM && EXPERIMENTAL) Suggested-by: Rajiv Andrade Signed-off-by: Fabio Estevam Signed-off-by: Rajiv Andrade Cc: Signed-off-by: Mimi Zohar --- drivers/char/tpm/Kconfig | 1 - security/integrity/ima/Kconfig | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 7fc75e47e6d0..a048199ce866 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -5,7 +5,6 @@ menuconfig TCG_TPM tristate "TPM Hardware Support" depends on HAS_IOMEM - depends on EXPERIMENTAL select SECURITYFS ---help--- If you have a TPM security chip in your system, which diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 4f554f20dc97..063298a797e8 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -9,7 +9,7 @@ config IMA select CRYPTO_HMAC select CRYPTO_MD5 select CRYPTO_SHA1 - select TCG_TPM if !S390 && !UML + select TCG_TPM if HAS_IOMEM && !UML select TCG_TIS if TCG_TPM help The Trusted Computing Group(TCG) runtime Integrity -- GitLab From 4c2c392763a682354fac65b6a569adec4e4b5387 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Tue, 18 Oct 2011 14:16:28 +0300 Subject: [PATCH 00188/10698] ima: policy for RAMFS Don't measure ramfs files. Signed-off-by: Dmitry Kasatkin Signed-off-by: Mimi Zohar --- security/integrity/ima/ima_policy.c | 1 + 1 file changed, 1 insertion(+) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index d661afbe474c..1b422bc56264 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -62,6 +62,7 @@ static struct ima_measure_rule_entry default_rules[] = { {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, + {.action = DONT_MEASURE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC}, {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, -- GitLab From 3e175ca4cab37b1eb99f7cf032142a1e5cdb3d97 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 18 Sep 2011 11:27:30 +0100 Subject: [PATCH 00189/10698] ARM: cache-l2x0.c: consistently use u32 __u32 exists to avoid namespace clashes with userspace programs. It should not be used outside header files, so convert to use u32 instead. Also, don't mix uint32_t and __u32 - use the same type throughout the file for consistency. Acked-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/include/asm/hardware/cache-l2x0.h | 6 +++--- arch/arm/mm/cache-l2x0.c | 22 +++++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/include/asm/hardware/cache-l2x0.h b/arch/arm/include/asm/hardware/cache-l2x0.h index 7df239bcdf27..c4c87bc12231 100644 --- a/arch/arm/include/asm/hardware/cache-l2x0.h +++ b/arch/arm/include/asm/hardware/cache-l2x0.h @@ -103,11 +103,11 @@ #define L2X0_ADDR_FILTER_EN 1 #ifndef __ASSEMBLY__ -extern void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask); +extern void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask); #if defined(CONFIG_CACHE_L2X0) && defined(CONFIG_OF) -extern int l2x0_of_init(__u32 aux_val, __u32 aux_mask); +extern int l2x0_of_init(u32 aux_val, u32 aux_mask); #else -static inline int l2x0_of_init(__u32 aux_val, __u32 aux_mask) +static inline int l2x0_of_init(u32 aux_val, u32 aux_mask) { return -ENODEV; } diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c index b1e192ba8c24..a53fd2aaa2f4 100644 --- a/arch/arm/mm/cache-l2x0.c +++ b/arch/arm/mm/cache-l2x0.c @@ -30,13 +30,13 @@ static void __iomem *l2x0_base; static DEFINE_RAW_SPINLOCK(l2x0_lock); -static uint32_t l2x0_way_mask; /* Bitmask of active ways */ -static uint32_t l2x0_size; +static u32 l2x0_way_mask; /* Bitmask of active ways */ +static u32 l2x0_size; struct l2x0_regs l2x0_saved_regs; struct l2x0_of_data { - void (*setup)(const struct device_node *, __u32 *, __u32 *); + void (*setup)(const struct device_node *, u32 *, u32 *); void (*save)(void); void (*resume)(void); }; @@ -288,7 +288,7 @@ static void l2x0_disable(void) raw_spin_unlock_irqrestore(&l2x0_lock, flags); } -static void l2x0_unlock(__u32 cache_id) +static void l2x0_unlock(u32 cache_id) { int lockregs; int i; @@ -307,11 +307,11 @@ static void l2x0_unlock(__u32 cache_id) } } -void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) +void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask) { - __u32 aux; - __u32 cache_id; - __u32 way_size = 0; + u32 aux; + u32 cache_id; + u32 way_size = 0; int ways; const char *type; @@ -388,7 +388,7 @@ void __init l2x0_init(void __iomem *base, __u32 aux_val, __u32 aux_mask) #ifdef CONFIG_OF static void __init l2x0_of_setup(const struct device_node *np, - __u32 *aux_val, __u32 *aux_mask) + u32 *aux_val, u32 *aux_mask) { u32 data[2] = { 0, 0 }; u32 tag = 0; @@ -422,7 +422,7 @@ static void __init l2x0_of_setup(const struct device_node *np, } static void __init pl310_of_setup(const struct device_node *np, - __u32 *aux_val, __u32 *aux_mask) + u32 *aux_val, u32 *aux_mask) { u32 data[3] = { 0, 0, 0 }; u32 tag[3] = { 0, 0, 0 }; @@ -548,7 +548,7 @@ static const struct of_device_id l2x0_ids[] __initconst = { {} }; -int __init l2x0_of_init(__u32 aux_val, __u32 aux_mask) +int __init l2x0_of_init(u32 aux_val, u32 aux_mask) { struct device_node *np; struct l2x0_of_data *data; -- GitLab From e76f4750f4c06c8b891ae7bc4c10074de08a9d41 Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 23 Nov 2011 17:44:05 +0000 Subject: [PATCH 00190/10698] ARM: debug: arrange Kconfig options more logically Arrange the Kconfig options in rough alphabetical order, and place the default 'none' and 'icedcc' options at the end. This prefers the platform specific debug option rather than the 'none' option, which is what we actually want. Acked-by: Will Deacon Signed-off-by: Russell King --- arch/arm/Kconfig.debug | 156 ++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index e0d236d7ff73..03646c4c13d1 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -81,25 +81,6 @@ choice prompt "Kernel low-level debugging port" depends on DEBUG_LL - config DEBUG_LL_UART_NONE - bool "No low-level debugging UART" - help - Say Y here if your platform doesn't provide a UART option - below. This relies on your platform choosing the right UART - definition internally in order for low-level debugging to - work. - - config DEBUG_ICEDCC - bool "Kernel low-level debugging via EmbeddedICE DCC channel" - help - Say Y here if you want the debug print routines to direct - their output to the EmbeddedICE macrocell's DCC channel using - co-processor 14. This is known to work on the ARM9 style ICE - channel and on the XScale with the PEEDI. - - Note that the system will appear to hang during boot if there - is nothing connected to read from the DCC. - config AT91_DEBUG_LL_DBGU0 bool "Kernel low-level debugging on rm9200, 9260/9g20, 9261/9g10 and 9rl" depends on HAVE_AT91_DBGU0 @@ -108,20 +89,6 @@ choice bool "Kernel low-level debugging on 9263, 9g45 and cap9" depends on HAVE_AT91_DBGU1 - config DEBUG_FOOTBRIDGE_COM1 - bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1" - depends on FOOTBRIDGE - help - Say Y here if you want the debug print routines to direct - their output to the 8250 at PCI COM1. - - config DEBUG_DC21285_PORT - bool "Kernel low-level debugging messages via footbridge serial port" - depends on FOOTBRIDGE - help - Say Y here if you want the debug print routines to direct - their output to the serial port in the DC21285 (Footbridge). - config DEBUG_CLPS711X_UART1 bool "Kernel low-level debugging messages via UART1" depends on ARCH_CLPS711X @@ -136,6 +103,20 @@ choice Say Y here if you want the debug print routines to direct their output to the second serial port on these devices. + config DEBUG_DC21285_PORT + bool "Kernel low-level debugging messages via footbridge serial port" + depends on FOOTBRIDGE + help + Say Y here if you want the debug print routines to direct + their output to the serial port in the DC21285 (Footbridge). + + config DEBUG_FOOTBRIDGE_COM1 + bool "Kernel low-level debugging messages via footbridge 8250 at PCI COM1" + depends on FOOTBRIDGE + help + Say Y here if you want the debug print routines to direct + their output to the 8250 at PCI COM1. + config DEBUG_HIGHBANK_UART bool "Kernel low-level debugging messages via Highbank UART" depends on ARCH_HIGHBANK @@ -206,38 +187,42 @@ choice Say Y here if you want kernel low-level debugging support on i.MX6Q. - config DEBUG_S3C_UART0 - depends on PLAT_SAMSUNG - bool "Use S3C UART 0 for low-level debug" + config DEBUG_MSM_UART1 + bool "Kernel low-level debugging messages via MSM UART1" + depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 help Say Y here if you want the debug print routines to direct - their output to UART 0. The port must have been initialised - by the boot-loader before use. - - The uncompressor code port configuration is now handled - by CONFIG_S3C_LOWLEVEL_UART_PORT. + their output to the first serial port on MSM devices. - config DEBUG_S3C_UART1 - depends on PLAT_SAMSUNG - bool "Use S3C UART 1 for low-level debug" + config DEBUG_MSM_UART2 + bool "Kernel low-level debugging messages via MSM UART2" + depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 help Say Y here if you want the debug print routines to direct - their output to UART 1. The port must have been initialised - by the boot-loader before use. + their output to the second serial port on MSM devices. - The uncompressor code port configuration is now handled - by CONFIG_S3C_LOWLEVEL_UART_PORT. + config DEBUG_MSM_UART3 + bool "Kernel low-level debugging messages via MSM UART3" + depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 + help + Say Y here if you want the debug print routines to direct + their output to the third serial port on MSM devices. - config DEBUG_S3C_UART2 - depends on PLAT_SAMSUNG - bool "Use S3C UART 2 for low-level debug" + config DEBUG_MSM8660_UART + bool "Kernel low-level debugging messages via MSM 8660 UART" + depends on ARCH_MSM8X60 + select MSM_HAS_DEBUG_UART_HS help Say Y here if you want the debug print routines to direct - their output to UART 2. The port must have been initialised - by the boot-loader before use. + their output to the serial port on MSM 8660 devices. - The uncompressor code port configuration is now handled - by CONFIG_S3C_LOWLEVEL_UART_PORT. + config DEBUG_MSM8960_UART + bool "Kernel low-level debugging messages via MSM 8960 UART" + depends on ARCH_MSM8960 + select MSM_HAS_DEBUG_UART_HS + help + Say Y here if you want the debug print routines to direct + their output to the serial port on MSM 8960 devices. config DEBUG_REALVIEW_STD_PORT bool "RealView Default UART" @@ -255,42 +240,57 @@ choice their output to the standard serial port on the RealView PB1176 platform. - config DEBUG_MSM_UART1 - bool "Kernel low-level debugging messages via MSM UART1" - depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 + config DEBUG_S3C_UART0 + depends on PLAT_SAMSUNG + bool "Use S3C UART 0 for low-level debug" help Say Y here if you want the debug print routines to direct - their output to the first serial port on MSM devices. + their output to UART 0. The port must have been initialised + by the boot-loader before use. - config DEBUG_MSM_UART2 - bool "Kernel low-level debugging messages via MSM UART2" - depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 + The uncompressor code port configuration is now handled + by CONFIG_S3C_LOWLEVEL_UART_PORT. + + config DEBUG_S3C_UART1 + depends on PLAT_SAMSUNG + bool "Use S3C UART 1 for low-level debug" help Say Y here if you want the debug print routines to direct - their output to the second serial port on MSM devices. + their output to UART 1. The port must have been initialised + by the boot-loader before use. - config DEBUG_MSM_UART3 - bool "Kernel low-level debugging messages via MSM UART3" - depends on ARCH_MSM7X00A || ARCH_MSM7X30 || ARCH_QSD8X50 + The uncompressor code port configuration is now handled + by CONFIG_S3C_LOWLEVEL_UART_PORT. + + config DEBUG_S3C_UART2 + depends on PLAT_SAMSUNG + bool "Use S3C UART 2 for low-level debug" help Say Y here if you want the debug print routines to direct - their output to the third serial port on MSM devices. + their output to UART 2. The port must have been initialised + by the boot-loader before use. - config DEBUG_MSM8660_UART - bool "Kernel low-level debugging messages via MSM 8660 UART" - depends on ARCH_MSM8X60 - select MSM_HAS_DEBUG_UART_HS + The uncompressor code port configuration is now handled + by CONFIG_S3C_LOWLEVEL_UART_PORT. + + config DEBUG_LL_UART_NONE + bool "No low-level debugging UART" help - Say Y here if you want the debug print routines to direct - their output to the serial port on MSM 8660 devices. + Say Y here if your platform doesn't provide a UART option + below. This relies on your platform choosing the right UART + definition internally in order for low-level debugging to + work. - config DEBUG_MSM8960_UART - bool "Kernel low-level debugging messages via MSM 8960 UART" - depends on ARCH_MSM8960 - select MSM_HAS_DEBUG_UART_HS + config DEBUG_ICEDCC + bool "Kernel low-level debugging via EmbeddedICE DCC channel" help Say Y here if you want the debug print routines to direct - their output to the serial port on MSM 8960 devices. + their output to the EmbeddedICE macrocell's DCC channel using + co-processor 14. This is known to work on the ARM9 style ICE + channel and on the XScale with the PEEDI. + + Note that the system will appear to hang during boot if there + is nothing connected to read from the DCC. endchoice -- GitLab From ac9ef6cf9196107115930e9fc66207199ef395b3 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 20 Jan 2012 12:08:44 +0100 Subject: [PATCH 00191/10698] ALSA: hda - Use bint for enable_msi option The new bint module option type suits well with this one. Signed-off-by: Takashi Iwai --- sound/pci/hda/hda_intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index fb35474c1203..9cbde2fc7b17 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -94,7 +94,7 @@ MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization."); module_param(single_cmd, bool, 0444); MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs " "(for debugging only)."); -module_param(enable_msi, int, 0444); +module_param(enable_msi, bint, 0444); MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)"); #ifdef CONFIG_SND_HDA_PATCH_LOADER module_param_array(patch, charp, NULL, 0444); -- GitLab From 6219929f5f82708309b3054ec7db6cb6e3ee47d5 Mon Sep 17 00:00:00 2001 From: Laxman Dewangan Date: Mon, 9 Jan 2012 20:27:41 +0530 Subject: [PATCH 00192/10698] regulator: TPS62360: Add tps62360 regulator driver The regulator module consists of 1 DCDC. The output voltage is configurable and is meant for supply power to the core voltage of Soc. Signed-off-by: Laxman Dewangan Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 10 + drivers/regulator/Makefile | 1 + drivers/regulator/tps62360-regulator.c | 472 +++++++++++++++++++++++++ include/linux/regulator/tps62360.h | 57 +++ 4 files changed, 540 insertions(+) create mode 100644 drivers/regulator/tps62360-regulator.c create mode 100644 include/linux/regulator/tps62360.h diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 7a61b17ddd04..b9ad3d8e03c7 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -328,6 +328,16 @@ config REGULATOR_TPS65910 help This driver supports TPS65910 voltage regulator chips. +config REGULATOR_TPS62360 + tristate "TI TPS62360 Power Regulator" + depends on I2C + select REGMAP_I2C + help + This driver supports TPS62360 voltage regulator chip. This + regulator is meant for processor core supply. This chip is + high-frequency synchronous step down dc-dc converter optimized + for battery-powered portable applications. + config REGULATOR_AAT2870 tristate "AnalogicTech AAT2870 Regulators" depends on MFD_AAT2870_CORE diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 503bac87715e..1668b2e667ce 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -47,6 +47,7 @@ obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o +obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG diff --git a/drivers/regulator/tps62360-regulator.c b/drivers/regulator/tps62360-regulator.c new file mode 100644 index 000000000000..f778ef067696 --- /dev/null +++ b/drivers/regulator/tps62360-regulator.c @@ -0,0 +1,472 @@ +/* + * tps62360.c -- TI tps62360 + * + * Driver for processor core supply tps62360 and tps62361B + * + * Copyright (c) 2012, NVIDIA Corporation. + * + * Author: Laxman Dewangan + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Register definitions */ +#define REG_VSET0 0 +#define REG_VSET1 1 +#define REG_VSET2 2 +#define REG_VSET3 3 +#define REG_CONTROL 4 +#define REG_TEMP 5 +#define REG_RAMPCTRL 6 +#define REG_CHIPID 8 + +enum chips {TPS62360, TPS62361}; + +#define TPS62360_BASE_VOLTAGE 770 +#define TPS62360_N_VOLTAGES 64 + +#define TPS62361_BASE_VOLTAGE 500 +#define TPS62361_N_VOLTAGES 128 + +/* tps 62360 chip information */ +struct tps62360_chip { + const char *name; + struct device *dev; + struct regulator_desc desc; + struct i2c_client *client; + struct regulator_dev *rdev; + struct regmap *regmap; + int chip_id; + int vsel0_gpio; + int vsel1_gpio; + int voltage_base; + u8 voltage_reg_mask; + bool en_internal_pulldn; + bool en_force_pwm; + bool en_discharge; + bool valid_gpios; + int lru_index[4]; + int curr_vset_vsel[4]; + int curr_vset_id; +}; + +/* + * find_voltage_set_register: Find new voltage configuration register + * (VSET) id. + * The finding of the new VSET register will be based on the LRU mechanism. + * Each VSET register will have different voltage configured . This + * Function will look if any of the VSET register have requested voltage set + * or not. + * - If it is already there then it will make that register as most + * recently used and return as found so that caller need not to set + * the VSET register but need to set the proper gpios to select this + * VSET register. + * - If requested voltage is not found then it will use the least + * recently mechanism to get new VSET register for new configuration + * and will return not_found so that caller need to set new VSET + * register and then gpios (both). + */ +static bool find_voltage_set_register(struct tps62360_chip *tps, + int req_vsel, int *vset_reg_id) +{ + int i; + bool found = false; + int new_vset_reg = tps->lru_index[3]; + int found_index = 3; + for (i = 0; i < 4; ++i) { + if (tps->curr_vset_vsel[tps->lru_index[i]] == req_vsel) { + new_vset_reg = tps->lru_index[i]; + found_index = i; + found = true; + goto update_lru_index; + } + } + +update_lru_index: + for (i = found_index; i > 0; i--) + tps->lru_index[i] = tps->lru_index[i - 1]; + + tps->lru_index[0] = new_vset_reg; + *vset_reg_id = new_vset_reg; + return found; +} + +static int tps62360_dcdc_get_voltage(struct regulator_dev *dev) +{ + struct tps62360_chip *tps = rdev_get_drvdata(dev); + int vsel; + unsigned int data; + int ret; + + ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data); + if (ret < 0) { + dev_err(tps->dev, "%s: Error in reading register %d\n", + __func__, REG_VSET0 + tps->curr_vset_id); + return ret; + } + vsel = (int)data & tps->voltage_reg_mask; + return (tps->voltage_base + vsel * 10) * 1000; +} + +static int tps62360_dcdc_set_voltage(struct regulator_dev *dev, + int min_uV, int max_uV, unsigned *selector) +{ + struct tps62360_chip *tps = rdev_get_drvdata(dev); + int vsel; + int ret; + bool found = false; + int new_vset_id = tps->curr_vset_id; + + if (max_uV < min_uV) + return -EINVAL; + + if (min_uV > + ((tps->voltage_base + (tps->desc.n_voltages - 1) * 10) * 1000)) + return -EINVAL; + + if (max_uV < tps->voltage_base * 1000) + return -EINVAL; + + vsel = DIV_ROUND_UP(min_uV - (tps->voltage_base * 1000), 10000); + if (selector) + *selector = (vsel & tps->voltage_reg_mask); + + /* + * If gpios are available to select the VSET register then least + * recently used register for new configuration. + */ + if (tps->valid_gpios) + found = find_voltage_set_register(tps, vsel, &new_vset_id); + + if (!found) { + ret = regmap_update_bits(tps->regmap, REG_VSET0 + new_vset_id, + tps->voltage_reg_mask, vsel); + if (ret < 0) { + dev_err(tps->dev, "%s: Error in updating register %d\n", + __func__, REG_VSET0 + new_vset_id); + return ret; + } + tps->curr_vset_id = new_vset_id; + tps->curr_vset_vsel[new_vset_id] = vsel; + } + + /* Select proper VSET register vio gpios */ + if (tps->valid_gpios) { + gpio_set_value_cansleep(tps->vsel0_gpio, + new_vset_id & 0x1); + gpio_set_value_cansleep(tps->vsel1_gpio, + (new_vset_id >> 1) & 0x1); + } + return 0; +} + +static int tps62360_dcdc_list_voltage(struct regulator_dev *dev, + unsigned selector) +{ + struct tps62360_chip *tps = rdev_get_drvdata(dev); + + if ((selector < 0) || (selector >= tps->desc.n_voltages)) + return -EINVAL; + return (tps->voltage_base + selector * 10) * 1000; +} + +static struct regulator_ops tps62360_dcdc_ops = { + .get_voltage = tps62360_dcdc_get_voltage, + .set_voltage = tps62360_dcdc_set_voltage, + .list_voltage = tps62360_dcdc_list_voltage, +}; + +static int tps62360_init_force_pwm(struct tps62360_chip *tps, + struct tps62360_regulator_platform_data *pdata, + int vset_id) +{ + unsigned int data; + int ret; + ret = regmap_read(tps->regmap, REG_VSET0 + vset_id, &data); + if (ret < 0) { + dev_err(tps->dev, "%s() fails in writing reg %d\n", + __func__, REG_VSET0 + vset_id); + return ret; + } + tps->curr_vset_vsel[vset_id] = data & tps->voltage_reg_mask; + if (pdata->en_force_pwm) + data |= BIT(7); + else + data &= ~BIT(7); + ret = regmap_write(tps->regmap, REG_VSET0 + vset_id, data); + if (ret < 0) + dev_err(tps->dev, "%s() fails in writing reg %d\n", + __func__, REG_VSET0 + vset_id); + return ret; +} + +static int tps62360_init_dcdc(struct tps62360_chip *tps, + struct tps62360_regulator_platform_data *pdata) +{ + int ret; + int i; + + /* Initailize internal pull up/down control */ + if (tps->en_internal_pulldn) + ret = regmap_write(tps->regmap, REG_CONTROL, 0xE0); + else + ret = regmap_write(tps->regmap, REG_CONTROL, 0x0); + if (ret < 0) { + dev_err(tps->dev, "%s() fails in writing reg %d\n", + __func__, REG_CONTROL); + return ret; + } + + /* Initailize force PWM mode */ + if (tps->valid_gpios) { + for (i = 0; i < 4; ++i) { + ret = tps62360_init_force_pwm(tps, pdata, i); + if (ret < 0) + return ret; + } + } else { + ret = tps62360_init_force_pwm(tps, pdata, tps->curr_vset_id); + if (ret < 0) + return ret; + } + + /* Reset output discharge path to reduce power consumption */ + ret = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), 0); + if (ret < 0) + dev_err(tps->dev, "%s() fails in updating reg %d\n", + __func__, REG_RAMPCTRL); + return ret; +} + +static const struct regmap_config tps62360_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + +static int __devinit tps62360_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct tps62360_regulator_platform_data *pdata; + struct regulator_dev *rdev; + struct tps62360_chip *tps; + int ret; + int i; + + pdata = client->dev.platform_data; + if (!pdata) { + dev_err(&client->dev, "%s() Err: Platform data not found\n", + __func__); + return -EIO; + } + + tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL); + if (!tps) { + dev_err(&client->dev, "%s() Err: Memory allocation fails\n", + __func__); + return -ENOMEM; + } + + tps->en_force_pwm = pdata->en_force_pwm; + tps->en_discharge = pdata->en_discharge; + tps->en_internal_pulldn = pdata->en_internal_pulldn; + tps->vsel0_gpio = pdata->vsel0_gpio; + tps->vsel1_gpio = pdata->vsel1_gpio; + tps->client = client; + tps->dev = &client->dev; + tps->name = id->name; + tps->voltage_base = (id->driver_data == TPS62360) ? + TPS62360_BASE_VOLTAGE : TPS62361_BASE_VOLTAGE; + tps->voltage_reg_mask = (id->driver_data == TPS62360) ? 0x3F : 0x7F; + + tps->desc.name = id->name; + tps->desc.id = 0; + tps->desc.n_voltages = (id->driver_data == TPS62360) ? + TPS62360_N_VOLTAGES : TPS62361_N_VOLTAGES; + tps->desc.ops = &tps62360_dcdc_ops; + tps->desc.type = REGULATOR_VOLTAGE; + tps->desc.owner = THIS_MODULE; + tps->regmap = regmap_init_i2c(client, &tps62360_regmap_config); + if (IS_ERR(tps->regmap)) { + ret = PTR_ERR(tps->regmap); + dev_err(&client->dev, "%s() Err: Failed to allocate register" + "map: %d\n", __func__, ret); + return ret; + } + i2c_set_clientdata(client, tps); + + tps->curr_vset_id = (pdata->vsel1_def_state & 1) * 2 + + (pdata->vsel0_def_state & 1); + tps->lru_index[0] = tps->curr_vset_id; + tps->valid_gpios = false; + + if (gpio_is_valid(tps->vsel0_gpio) && gpio_is_valid(tps->vsel1_gpio)) { + ret = gpio_request(tps->vsel0_gpio, "tps62360-vsel0"); + if (ret) { + dev_err(&client->dev, + "Err: Could not obtain vsel0 GPIO %d: %d\n", + tps->vsel0_gpio, ret); + goto err_gpio0; + } + ret = gpio_direction_output(tps->vsel0_gpio, + pdata->vsel0_def_state); + if (ret) { + dev_err(&client->dev, "Err: Could not set direction of" + "vsel0 GPIO %d: %d\n", tps->vsel0_gpio, ret); + gpio_free(tps->vsel0_gpio); + goto err_gpio0; + } + + ret = gpio_request(tps->vsel1_gpio, "tps62360-vsel1"); + if (ret) { + dev_err(&client->dev, + "Err: Could not obtain vsel1 GPIO %d: %d\n", + tps->vsel1_gpio, ret); + goto err_gpio1; + } + ret = gpio_direction_output(tps->vsel1_gpio, + pdata->vsel1_def_state); + if (ret) { + dev_err(&client->dev, "Err: Could not set direction of" + "vsel1 GPIO %d: %d\n", tps->vsel1_gpio, ret); + gpio_free(tps->vsel1_gpio); + goto err_gpio1; + } + tps->valid_gpios = true; + + /* + * Initialize the lru index with vset_reg id + * The index 0 will be most recently used and + * set with the tps->curr_vset_id */ + for (i = 0; i < 4; ++i) + tps->lru_index[i] = i; + tps->lru_index[0] = tps->curr_vset_id; + tps->lru_index[tps->curr_vset_id] = 0; + } + + ret = tps62360_init_dcdc(tps, pdata); + if (ret < 0) { + dev_err(tps->dev, "%s() Err: Init fails with = %d\n", + __func__, ret); + goto err_init; + } + + /* Register the regulators */ + rdev = regulator_register(&tps->desc, &client->dev, + &pdata->reg_init_data, tps, NULL); + if (IS_ERR(rdev)) { + dev_err(tps->dev, "%s() Err: Failed to register %s\n", + __func__, id->name); + ret = PTR_ERR(rdev); + goto err_init; + } + + tps->rdev = rdev; + return 0; + +err_init: + if (gpio_is_valid(tps->vsel1_gpio)) + gpio_free(tps->vsel1_gpio); +err_gpio1: + if (gpio_is_valid(tps->vsel0_gpio)) + gpio_free(tps->vsel0_gpio); +err_gpio0: + regmap_exit(tps->regmap); + return ret; +} + +/** + * tps62360_remove - tps62360 driver i2c remove handler + * @client: i2c driver client device structure + * + * Unregister TPS driver as an i2c client device driver + */ +static int __devexit tps62360_remove(struct i2c_client *client) +{ + struct tps62360_chip *tps = i2c_get_clientdata(client); + + if (gpio_is_valid(tps->vsel1_gpio)) + gpio_free(tps->vsel1_gpio); + + if (gpio_is_valid(tps->vsel0_gpio)) + gpio_free(tps->vsel0_gpio); + + regulator_unregister(tps->rdev); + regmap_exit(tps->regmap); + return 0; +} + +static void tps62360_shutdown(struct i2c_client *client) +{ + struct tps62360_chip *tps = i2c_get_clientdata(client); + int st; + + if (!tps->en_discharge) + return; + + /* Configure the output discharge path */ + st = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), BIT(2)); + if (st < 0) + dev_err(tps->dev, "%s() fails in updating reg %d\n", + __func__, REG_RAMPCTRL); +} + +static const struct i2c_device_id tps62360_id[] = { + {.name = "tps62360", .driver_data = TPS62360}, + {.name = "tps62361", .driver_data = TPS62361}, + {}, +}; + +MODULE_DEVICE_TABLE(i2c, tps62360_id); + +static struct i2c_driver tps62360_i2c_driver = { + .driver = { + .name = "tps62360", + .owner = THIS_MODULE, + }, + .probe = tps62360_probe, + .remove = __devexit_p(tps62360_remove), + .shutdown = tps62360_shutdown, + .id_table = tps62360_id, +}; + +static int __init tps62360_init(void) +{ + return i2c_add_driver(&tps62360_i2c_driver); +} +subsys_initcall(tps62360_init); + +static void __exit tps62360_cleanup(void) +{ + i2c_del_driver(&tps62360_i2c_driver); +} +module_exit(tps62360_cleanup); + +MODULE_AUTHOR("Laxman Dewangan "); +MODULE_DESCRIPTION("TPS62360 voltage regulator driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/regulator/tps62360.h b/include/linux/regulator/tps62360.h new file mode 100644 index 000000000000..6a5c1b2c751e --- /dev/null +++ b/include/linux/regulator/tps62360.h @@ -0,0 +1,57 @@ +/* + * tps62360.h -- TI tps62360 + * + * Interface for regulator driver for TI TPS62360 Processor core supply + * + * Copyright (C) 2012 NVIDIA Corporation + + * Author: Laxman Dewangan + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef __LINUX_REGULATOR_TPS62360_H +#define __LINUX_REGULATOR_TPS62360_H + +#include + +/* + * struct tps62360_regulator_platform_data - tps62360 regulator platform data. + * + * @reg_init_data: The regulator init data. + * @en_force_pwm: Enable force pwm or not. + * @en_discharge: Enable discharge the output capacitor via internal + * register. + * @en_internal_pulldn: internal pull down enable or not. + * @vsel0_gpio: Gpio number for vsel0. It should be -1 if this is tied with + * fixed logic. + * @vsel1_gpio: Gpio number for vsel1. It should be -1 if this is tied with + * fixed logic. + * @vsel0_def_state: Default state of vsel0. 1 if it is high else 0. + * @vsel1_def_state: Default state of vsel1. 1 if it is high else 0. + */ +struct tps62360_regulator_platform_data { + struct regulator_init_data reg_init_data; + bool en_force_pwm; + bool en_discharge; + bool en_internal_pulldn; + int vsel0_gpio; + int vsel1_gpio; + int vsel0_def_state; + int vsel1_def_state; +}; + +#endif /* __LINUX_REGULATOR_TPS62360_H */ -- GitLab From 9767ec7fe8d9bf00e764f1d0ca0176988255be11 Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Mon, 9 Jan 2012 19:10:25 +0900 Subject: [PATCH 00193/10698] regulator: Add S5M8767A regulator driver S5M8767A is a cost-effective PMIC which is designed for mobile applications. It includes high efficient 9 Buck converters, 28 LDOs. Especially, S5M8767A is optimized for Multi-core SOCs. And during DVFS operation, S5M8767A output stable voltage. This patch implement regulator driver for S5M8767A. Signed-off-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 834 ++++++++++++++++++++++++++++++++++++ 1 file changed, 834 insertions(+) create mode 100644 drivers/regulator/s5m8767.c diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c new file mode 100644 index 000000000000..b3d356f5e271 --- /dev/null +++ b/drivers/regulator/s5m8767.c @@ -0,0 +1,834 @@ +/* + * s5m8767.c + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd + * http://www.samsung.com + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct s5m8767_info { + struct device *dev; + struct s5m87xx_dev *iodev; + int num_regulators; + struct regulator_dev **rdev; + + int ramp_delay; + bool buck2_ramp; + bool buck3_ramp; + bool buck4_ramp; + + bool buck2_gpiodvs; + bool buck3_gpiodvs; + bool buck4_gpiodvs; + u8 buck2_vol[8]; + u8 buck3_vol[8]; + u8 buck4_vol[8]; + int buck_gpios[3]; + int buck_gpioindex; +}; + +struct s5m_voltage_desc { + int max; + int min; + int step; +}; + +static const struct s5m_voltage_desc buck_voltage_val1 = { + .max = 2225000, + .min = 650000, + .step = 6250, +}; + +static const struct s5m_voltage_desc buck_voltage_val2 = { + .max = 1600000, + .min = 600000, + .step = 6250, +}; + +static const struct s5m_voltage_desc buck_voltage_val3 = { + .max = 3000000, + .min = 750000, + .step = 12500, +}; + +static const struct s5m_voltage_desc ldo_voltage_val1 = { + .max = 3950000, + .min = 800000, + .step = 50000, +}; + +static const struct s5m_voltage_desc ldo_voltage_val2 = { + .max = 2375000, + .min = 800000, + .step = 25000, +}; + +static const struct s5m_voltage_desc *reg_voltage_map[] = { + [S5M8767_LDO1] = &ldo_voltage_val2, + [S5M8767_LDO2] = &ldo_voltage_val2, + [S5M8767_LDO3] = &ldo_voltage_val1, + [S5M8767_LDO4] = &ldo_voltage_val1, + [S5M8767_LDO5] = &ldo_voltage_val1, + [S5M8767_LDO6] = &ldo_voltage_val2, + [S5M8767_LDO7] = &ldo_voltage_val2, + [S5M8767_LDO8] = &ldo_voltage_val2, + [S5M8767_LDO9] = &ldo_voltage_val1, + [S5M8767_LDO10] = &ldo_voltage_val1, + [S5M8767_LDO11] = &ldo_voltage_val1, + [S5M8767_LDO12] = &ldo_voltage_val1, + [S5M8767_LDO13] = &ldo_voltage_val1, + [S5M8767_LDO14] = &ldo_voltage_val1, + [S5M8767_LDO15] = &ldo_voltage_val2, + [S5M8767_LDO16] = &ldo_voltage_val1, + [S5M8767_LDO17] = &ldo_voltage_val1, + [S5M8767_LDO18] = &ldo_voltage_val1, + [S5M8767_LDO19] = &ldo_voltage_val1, + [S5M8767_LDO20] = &ldo_voltage_val1, + [S5M8767_LDO21] = &ldo_voltage_val1, + [S5M8767_LDO22] = &ldo_voltage_val1, + [S5M8767_LDO23] = &ldo_voltage_val1, + [S5M8767_LDO24] = &ldo_voltage_val1, + [S5M8767_LDO25] = &ldo_voltage_val1, + [S5M8767_LDO26] = &ldo_voltage_val1, + [S5M8767_LDO27] = &ldo_voltage_val1, + [S5M8767_LDO28] = &ldo_voltage_val1, + [S5M8767_BUCK1] = &buck_voltage_val1, + [S5M8767_BUCK2] = &buck_voltage_val2, + [S5M8767_BUCK3] = &buck_voltage_val2, + [S5M8767_BUCK4] = &buck_voltage_val2, + [S5M8767_BUCK5] = &buck_voltage_val1, + [S5M8767_BUCK6] = &buck_voltage_val1, + [S5M8767_BUCK7] = NULL, + [S5M8767_BUCK8] = NULL, + [S5M8767_BUCK9] = &buck_voltage_val3, +}; + +static inline int s5m8767_get_reg_id(struct regulator_dev *rdev) +{ + return rdev_get_id(rdev); +} + +static int s5m8767_list_voltage(struct regulator_dev *rdev, + unsigned int selector) +{ + const struct s5m_voltage_desc *desc; + int reg_id = s5m8767_get_reg_id(rdev); + int val; + + if (reg_id >= ARRAY_SIZE(reg_voltage_map) || reg_id < 0) + return -EINVAL; + + desc = reg_voltage_map[reg_id]; + if (desc == NULL) + return -EINVAL; + + val = desc->min + desc->step * selector; + if (val > desc->max) + return -EINVAL; + + return val; +} + +static int s5m8767_get_register(struct regulator_dev *rdev, int *reg) +{ + int reg_id = s5m8767_get_reg_id(rdev); + + switch (reg_id) { + case S5M8767_LDO1 ... S5M8767_LDO2: + *reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1); + break; + case S5M8767_LDO3 ... S5M8767_LDO28: + *reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3); + break; + case S5M8767_BUCK1: + *reg = S5M8767_REG_BUCK1CTRL1; + break; + case S5M8767_BUCK2 ... S5M8767_BUCK4: + *reg = S5M8767_REG_BUCK2CTRL + (reg_id - S5M8767_BUCK2) * 9; + break; + case S5M8767_BUCK5: + *reg = S5M8767_REG_BUCK5CTRL1; + break; + case S5M8767_BUCK6 ... S5M8767_BUCK9: + *reg = S5M8767_REG_BUCK6CTRL1 + (reg_id - S5M8767_BUCK6) * 2; + break; + default: + return -EINVAL; + } + + return 0; +} + +static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) +{ + struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); + int ret, reg; + int mask = 0xc0, pattern = 0xc0; + u8 val; + + ret = s5m8767_get_register(rdev, ®); + if (ret == -EINVAL) + return 1; + else if (ret) + return ret; + + ret = s5m_reg_read(s5m8767->iodev, reg, &val); + if (ret) + return ret; + + return (val & mask) == pattern; +} + +static int s5m8767_reg_enable(struct regulator_dev *rdev) +{ + struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); + int ret, reg; + int mask = 0xc0, pattern = 0xc0; + + ret = s5m8767_get_register(rdev, ®); + if (ret) + return ret; + + return s5m_reg_update(s5m8767->iodev, reg, pattern, mask); +} + +static int s5m8767_reg_disable(struct regulator_dev *rdev) +{ + struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); + int ret, reg; + int mask = 0xc0, pattern = 0xc0; + + ret = s5m8767_get_register(rdev, ®); + if (ret) + return ret; + + return s5m_reg_update(s5m8767->iodev, reg, ~pattern, mask); +} + +static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg) +{ + int reg_id = s5m8767_get_reg_id(rdev); + int reg; + + switch (reg_id) { + case S5M8767_LDO1 ... S5M8767_LDO2: + reg = S5M8767_REG_LDO1CTRL + (reg_id - S5M8767_LDO1); + break; + case S5M8767_LDO3 ... S5M8767_LDO28: + reg = S5M8767_REG_LDO3CTRL + (reg_id - S5M8767_LDO3); + break; + case S5M8767_BUCK1: + reg = S5M8767_REG_BUCK1CTRL2; + break; + case S5M8767_BUCK2: + reg = S5M8767_REG_BUCK2DVS1; + break; + case S5M8767_BUCK3: + reg = S5M8767_REG_BUCK3DVS1; + break; + case S5M8767_BUCK4: + reg = S5M8767_REG_BUCK4DVS1; + break; + case S5M8767_BUCK5: + reg = S5M8767_REG_BUCK5CTRL2; + break; + case S5M8767_BUCK6 ... S5M8767_BUCK9: + reg = S5M8767_REG_BUCK6CTRL2 + (reg_id - S5M8767_BUCK6) * 2; + break; + default: + return -EINVAL; + } + + *_reg = reg; + + return 0; +} + +static int s5m8767_get_voltage_sel(struct regulator_dev *rdev) +{ + struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); + int reg, mask = 0xff, ret; + int reg_id = s5m8767_get_reg_id(rdev); + u8 val; + + ret = s5m8767_get_voltage_register(rdev, ®); + if (ret) + return ret; + + switch (reg_id) { + case S5M8767_LDO1 ... S5M8767_LDO28: + mask = 0x3f; + break; + case S5M8767_BUCK2: + if (s5m8767->buck2_gpiodvs) + reg += s5m8767->buck_gpioindex; + break; + case S5M8767_BUCK3: + if (s5m8767->buck3_gpiodvs) + reg += s5m8767->buck_gpioindex; + break; + case S5M8767_BUCK4: + if (s5m8767->buck4_gpiodvs) + reg += s5m8767->buck_gpioindex; + break; + } + + ret = s5m_reg_read(s5m8767->iodev, reg, &val); + if (ret) + return ret; + + val &= mask; + + return val; +} + +static inline int s5m8767_convert_voltage( + const struct s5m_voltage_desc *desc, + int min_vol, int max_vol) +{ + int out_vol = 0; + + if (desc == NULL) + return -EINVAL; + + if (max_vol < desc->min || min_vol > desc->max) + return -EINVAL; + + out_vol = (min_vol - desc->min) / desc->step; + + if (desc->min + desc->step * out_vol > max_vol) + return -EINVAL; + + return out_vol; +} + +static int s5m8767_set_voltage(struct regulator_dev *rdev, + int min_uV, int max_uV, unsigned *selector) +{ + struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); + int min_vol = min_uV, max_vol = max_uV; + const struct s5m_voltage_desc *desc; + int reg_id = s5m8767_get_reg_id(rdev); + int reg, mask, ret; + int i; + u8 val; + + switch (reg_id) { + case S5M8767_LDO1 ... S5M8767_LDO28: + mask = 0x3f; + break; + case S5M8767_BUCK1 ... S5M8767_BUCK6: + mask = 0xff; + break; + case S5M8767_BUCK7 ... S5M8767_BUCK8: + return -EINVAL; + case S5M8767_BUCK9: + mask = 0xff; + break; + default: + return -EINVAL; + } + + desc = reg_voltage_map[reg_id]; + + i = s5m8767_convert_voltage(desc, min_vol, max_vol); + if (i < 0) + return i; + + ret = s5m8767_get_voltage_register(rdev, ®); + if (ret) + return ret; + + s5m_reg_read(s5m8767->iodev, reg, &val); + val = val & mask; + + ret = s5m_reg_write(s5m8767->iodev, reg, val); + *selector = i; + + return ret; +} + +static inline void s5m8767_set_high(struct s5m8767_info *s5m8767) +{ + int temp_index = s5m8767->buck_gpioindex; + + gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); + gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); + gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); +} + +static inline void s5m8767_set_low(struct s5m8767_info *s5m8767) +{ + int temp_index = s5m8767->buck_gpioindex; + + gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); + gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); + gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); +} + +static int s5m8767_set_voltage_buck(struct regulator_dev *rdev, + int min_uV, int max_uV, unsigned *selector) +{ + struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); + int reg_id = s5m8767_get_reg_id(rdev); + const struct s5m_voltage_desc *desc; + int new_val, old_val, i = 0; + int min_vol = min_uV, max_vol = max_uV; + + if (reg_id < S5M8767_BUCK1 || reg_id > S5M8767_BUCK6) + return -EINVAL; + + switch (reg_id) { + case S5M8767_BUCK1: + return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); + case S5M8767_BUCK2 ... S5M8767_BUCK4: + break; + case S5M8767_BUCK5 ... S5M8767_BUCK6: + return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); + case S5M8767_BUCK9: + return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); + } + + desc = reg_voltage_map[reg_id]; + new_val = s5m8767_convert_voltage(desc, min_vol, max_vol); + if (new_val < 0) + return new_val; + + switch (reg_id) { + case S5M8767_BUCK2: + if (s5m8767->buck2_gpiodvs) { + while (s5m8767->buck2_vol[i] != new_val) + i++; + } else + return s5m8767_set_voltage(rdev, min_uV, + max_uV, selector); + break; + case S5M8767_BUCK3: + if (s5m8767->buck3_gpiodvs) { + while (s5m8767->buck3_vol[i] != new_val) + i++; + } else + return s5m8767_set_voltage(rdev, min_uV, + max_uV, selector); + break; + case S5M8767_BUCK4: + if (s5m8767->buck3_gpiodvs) { + while (s5m8767->buck4_vol[i] != new_val) + i++; + } else + return s5m8767_set_voltage(rdev, min_uV, + max_uV, selector); + break; + } + + old_val = s5m8767->buck_gpioindex; + s5m8767->buck_gpioindex = i; + + if (i > old_val) + s5m8767_set_high(s5m8767); + else + s5m8767_set_low(s5m8767); + + *selector = new_val; + return 0; +} + +static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, + unsigned int old_sel, + unsigned int new_sel) +{ + struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); + const struct s5m_voltage_desc *desc; + int reg_id = s5m8767_get_reg_id(rdev); + int mask; + int new_val, old_val; + + switch (reg_id) { + case S5M8767_LDO1 ... S5M8767_LDO28: + mask = 0x3f; + break; + case S5M8767_BUCK1 ... S5M8767_BUCK6: + mask = 0xff; + break; + case S5M8767_BUCK7 ... S5M8767_BUCK8: + return -EINVAL; + case S5M8767_BUCK9: + mask = 0xff; + break; + default: + return -EINVAL; + } + desc = reg_voltage_map[reg_id]; + + new_val = s5m8767_convert_voltage(desc, new_sel, new_sel); + if (new_val < 0) + return new_val; + + old_val = s5m8767_convert_voltage(desc, old_sel, old_sel); + if (old_val < 0) + return old_val; + + if (old_sel < new_sel) + return DIV_ROUND_UP(desc->step * (new_val - old_val), + s5m8767->ramp_delay); + else + return 0; +} + +static struct regulator_ops s5m8767_ldo_ops = { + .list_voltage = s5m8767_list_voltage, + .is_enabled = s5m8767_reg_is_enabled, + .enable = s5m8767_reg_enable, + .disable = s5m8767_reg_disable, + .get_voltage_sel = s5m8767_get_voltage_sel, + .set_voltage = s5m8767_set_voltage, + .set_voltage_time_sel = s5m8767_set_voltage_time_sel, +}; + +static struct regulator_ops s5m8767_buck_ops = { + .list_voltage = s5m8767_list_voltage, + .is_enabled = s5m8767_reg_is_enabled, + .enable = s5m8767_reg_enable, + .disable = s5m8767_reg_disable, + .get_voltage_sel = s5m8767_get_voltage_sel, + .set_voltage = s5m8767_set_voltage_buck, + .set_voltage_time_sel = s5m8767_set_voltage_time_sel, +}; + +#define regulator_desc_ldo(num) { \ + .name = "LDO"#num, \ + .id = S5M8767_LDO##num, \ + .ops = &s5m8767_ldo_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ +} +#define regulator_desc_buck(num) { \ + .name = "BUCK"#num, \ + .id = S5M8767_BUCK##num, \ + .ops = &s5m8767_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ +} + +static struct regulator_desc regulators[] = { + regulator_desc_ldo(1), + regulator_desc_ldo(2), + regulator_desc_ldo(3), + regulator_desc_ldo(4), + regulator_desc_ldo(5), + regulator_desc_ldo(6), + regulator_desc_ldo(7), + regulator_desc_ldo(8), + regulator_desc_ldo(9), + regulator_desc_ldo(10), + regulator_desc_ldo(11), + regulator_desc_ldo(12), + regulator_desc_ldo(13), + regulator_desc_ldo(14), + regulator_desc_ldo(15), + regulator_desc_ldo(16), + regulator_desc_ldo(17), + regulator_desc_ldo(18), + regulator_desc_ldo(19), + regulator_desc_ldo(20), + regulator_desc_ldo(21), + regulator_desc_ldo(22), + regulator_desc_ldo(23), + regulator_desc_ldo(24), + regulator_desc_ldo(25), + regulator_desc_ldo(26), + regulator_desc_ldo(27), + regulator_desc_ldo(28), + regulator_desc_buck(1), + regulator_desc_buck(2), + regulator_desc_buck(3), + regulator_desc_buck(4), + regulator_desc_buck(5), + regulator_desc_buck(6), + regulator_desc_buck(7), + regulator_desc_buck(8), + regulator_desc_buck(9), +}; + +static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) +{ + struct s5m87xx_dev *iodev = dev_get_drvdata(pdev->dev.parent); + struct s5m_platform_data *pdata = dev_get_platdata(iodev->dev); + struct regulator_dev **rdev; + struct s5m8767_info *s5m8767; + struct i2c_client *i2c; + int i, ret, size, reg; + + if (!pdata) { + dev_err(pdev->dev.parent, "Platform data not supplied\n"); + return -ENODEV; + } + + s5m8767 = devm_kzalloc(&pdev->dev, sizeof(struct s5m8767_info), + GFP_KERNEL); + if (!s5m8767) + return -ENOMEM; + + size = sizeof(struct regulator_dev *) * (S5M8767_REG_MAX - 2); + s5m8767->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); + if (!s5m8767->rdev) + return -ENOMEM; + + rdev = s5m8767->rdev; + s5m8767->dev = &pdev->dev; + s5m8767->iodev = iodev; + s5m8767->num_regulators = S5M8767_REG_MAX - 2; + platform_set_drvdata(pdev, s5m8767); + i2c = s5m8767->iodev->i2c; + + s5m8767->buck_gpioindex = pdata->buck_default_idx; + s5m8767->buck2_gpiodvs = pdata->buck2_gpiodvs; + s5m8767->buck3_gpiodvs = pdata->buck3_gpiodvs; + s5m8767->buck4_gpiodvs = pdata->buck4_gpiodvs; + s5m8767->buck_gpios[0] = pdata->buck_gpios[0]; + s5m8767->buck_gpios[1] = pdata->buck_gpios[1]; + s5m8767->buck_gpios[2] = pdata->buck_gpios[2]; + s5m8767->ramp_delay = pdata->buck_ramp_delay; + s5m8767->buck2_ramp = pdata->buck2_ramp_enable; + s5m8767->buck3_ramp = pdata->buck3_ramp_enable; + s5m8767->buck4_ramp = pdata->buck4_ramp_enable; + + for (i = 0; i < 8; i++) { + if (s5m8767->buck2_gpiodvs) { + s5m8767->buck2_vol[i] = + s5m8767_convert_voltage( + &buck_voltage_val2, + pdata->buck2_voltage[i], + pdata->buck2_voltage[i] + + buck_voltage_val2.step); + } + + if (s5m8767->buck3_gpiodvs) { + s5m8767->buck3_vol[i] = + s5m8767_convert_voltage( + &buck_voltage_val2, + pdata->buck3_voltage[i], + pdata->buck3_voltage[i] + + buck_voltage_val2.step); + } + + if (s5m8767->buck4_gpiodvs) { + s5m8767->buck4_vol[i] = + s5m8767_convert_voltage( + &buck_voltage_val2, + pdata->buck4_voltage[i], + pdata->buck4_voltage[i] + + buck_voltage_val2.step); + } + } + + if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || + pdata->buck4_gpiodvs) { + if (gpio_is_valid(pdata->buck_gpios[0]) && + gpio_is_valid(pdata->buck_gpios[1]) && + gpio_is_valid(pdata->buck_gpios[2])) { + ret = gpio_request(pdata->buck_gpios[0], + "S5M8767 SET1"); + if (ret == -EBUSY) + dev_warn(&pdev->dev, "Duplicated gpio request for SET1\n"); + + ret = gpio_request(pdata->buck_gpios[1], + "S5M8767 SET2"); + if (ret == -EBUSY) + dev_warn(&pdev->dev, "Duplicated gpio request for SET2\n"); + + ret = gpio_request(pdata->buck_gpios[2], + "S5M8767 SET3"); + if (ret == -EBUSY) + dev_warn(&pdev->dev, "Duplicated gpio request for SET3\n"); + /* SET1 GPIO */ + gpio_direction_output(pdata->buck_gpios[0], + (s5m8767->buck_gpioindex >> 2) & 0x1); + /* SET2 GPIO */ + gpio_direction_output(pdata->buck_gpios[1], + (s5m8767->buck_gpioindex >> 1) & 0x1); + /* SET3 GPIO */ + gpio_direction_output(pdata->buck_gpios[2], + (s5m8767->buck_gpioindex >> 0) & 0x1); + ret = 0; + } else { + dev_err(&pdev->dev, "GPIO NOT VALID\n"); + ret = -EINVAL; + return ret; + } + } + + if (pdata->buck2_gpiodvs) { + if (pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) { + dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n"); + ret = -EINVAL; + return ret; + } + } + + if (pdata->buck3_gpiodvs) { + if (pdata->buck2_gpiodvs || pdata->buck4_gpiodvs) { + dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n"); + ret = -EINVAL; + return ret; + } + } + + if (pdata->buck4_gpiodvs) { + if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs) { + dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n"); + ret = -EINVAL; + return ret; + } + } + + s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, + (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); + s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, + (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); + s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, + (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1); + + /* Initialize GPIO DVS registers */ + for (i = 0; i < 8; i++) { + if (s5m8767->buck2_gpiodvs) { + s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS1 + i, + s5m8767->buck2_vol[i]); + } + + if (s5m8767->buck3_gpiodvs) { + s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS1 + i, + s5m8767->buck3_vol[i]); + } + + if (s5m8767->buck4_gpiodvs) { + s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS1 + i, + s5m8767->buck4_vol[i]); + } + } + s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, 0x78, 0xff); + s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, 0x58, 0xff); + s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, 0x78, 0xff); + + if (s5m8767->buck2_ramp) + s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08); + + if (s5m8767->buck3_ramp) + s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x04, 0x04); + + if (s5m8767->buck4_ramp) + s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x02, 0x02); + + if (s5m8767->buck2_ramp || s5m8767->buck3_ramp + || s5m8767->buck4_ramp) { + switch (s5m8767->ramp_delay) { + case 15: + s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + 0xc0, 0xf0); + case 25: + s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + 0xd0, 0xf0); + case 50: + s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + 0xe0, 0xf0); + case 100: + s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + 0xf0, 0xf0); + default: + s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, + 0x90, 0xf0); + } + } + + for (i = 0; i < pdata->num_regulators; i++) { + const struct s5m_voltage_desc *desc; + int id = pdata->regulators[i].id; + + desc = reg_voltage_map[id]; + if (desc) + regulators[id].n_voltages = + (desc->max - desc->min) / desc->step + 1; + + rdev[i] = regulator_register(®ulators[id], s5m8767->dev, + pdata->regulators[i].initdata, s5m8767); + if (IS_ERR(rdev[i])) { + ret = PTR_ERR(rdev[i]); + dev_err(s5m8767->dev, "regulator init failed for %d\n", + id); + rdev[i] = NULL; + goto err; + } + } + + return 0; +err: + for (i = 0; i < s5m8767->num_regulators; i++) + if (rdev[i]) + regulator_unregister(rdev[i]); + + return ret; +} + +static int __devexit s5m8767_pmic_remove(struct platform_device *pdev) +{ + struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev); + struct regulator_dev **rdev = s5m8767->rdev; + int i; + + for (i = 0; i < s5m8767->num_regulators; i++) + if (rdev[i]) + regulator_unregister(rdev[i]); + + return 0; +} + +static const struct platform_device_id s5m8767_pmic_id[] = { + { "s5m8767-pmic", 0}, + { }, +}; +MODULE_DEVICE_TABLE(platform, s5m8767_pmic_id); + +static struct platform_driver s5m8767_pmic_driver = { + .driver = { + .name = "s5m8767-pmic", + .owner = THIS_MODULE, + }, + .probe = s5m8767_pmic_probe, + .remove = __devexit_p(s5m8767_pmic_remove), + .id_table = s5m8767_pmic_id, +}; + +static int __init s5m8767_pmic_init(void) +{ + return platform_driver_register(&s5m8767_pmic_driver); +} +subsys_initcall(s5m8767_pmic_init); + +static void __exit s5m8767_pmic_exit(void) +{ + platform_driver_unregister(&s5m8767_pmic_driver); +} +module_exit(s5m8767_pmic_exit); + +/* Module information */ +MODULE_AUTHOR("Sangbeom Kim "); +MODULE_DESCRIPTION("SAMSUNG S5M8767 Regulator Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:s5m8767-pmic"); -- GitLab From 047ec220a49f96ab0f8bd0bc574368e2cae8f1f7 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 12 Jan 2012 14:57:09 +0800 Subject: [PATCH 00194/10698] regulator: s5m8767: Add missing breaks Signed-off-by: Axel Lin Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index b3d356f5e271..40610126ab28 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -742,15 +742,19 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev) case 15: s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0xc0, 0xf0); + break; case 25: s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0xd0, 0xf0); + break; case 50: s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0xe0, 0xf0); + break; case 100: s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0xf0, 0xf0); + break; default: s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x90, 0xf0); -- GitLab From c835e1c00eda6f8f6c6bce49b2d89208f3a184dc Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 12 Jan 2012 14:58:25 +0800 Subject: [PATCH 00195/10698] regulator: s5m8767: Remove redundant MODULE_ALIAS The MODULE_DEVICE_TABLE will setup the modalias, thus adding a MODULE_ALIAS for an entry already in s5m8767_pmic_id is redundant. Signed-off-by: Axel Lin Acked-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/s5m8767.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 40610126ab28..caf0117b471f 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -835,4 +835,3 @@ module_exit(s5m8767_pmic_exit); MODULE_AUTHOR("Sangbeom Kim "); MODULE_DESCRIPTION("SAMSUNG S5M8767 Regulator Driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:s5m8767-pmic"); -- GitLab From 38e968380b27d6c0f4b68bdd6e3161f8a7effe38 Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Fri, 13 Jan 2012 16:30:31 +0100 Subject: [PATCH 00196/10698] regulators/db8500: split off shared dbx500 code As we progress with DB5500 and future voltage domain regulators based on very similar hardware as found in the DB8500 PRCMU, it makes sense to split off the generic parts and introduce some generic debug code for the DBx500 regulators. This patch accoplish a basic abstraction of the DBx500 voltage domain regulators. Signed-off-by: Bengt Jonsson Signed-off-by: Linus Walleij Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 4 + drivers/regulator/Makefile | 1 + drivers/regulator/db8500-prcmu.c | 118 ++++----------- drivers/regulator/dbx500-prcmu.c | 241 +++++++++++++++++++++++++++++++ drivers/regulator/dbx500-prcmu.h | 63 ++++++++ 5 files changed, 341 insertions(+), 86 deletions(-) create mode 100644 drivers/regulator/dbx500-prcmu.c create mode 100644 drivers/regulator/dbx500-prcmu.h diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index b9ad3d8e03c7..c7e49b140be9 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -299,9 +299,13 @@ config REGULATOR_AB8500 This driver supports the regulators found on the ST-Ericsson mixed signal AB8500 PMIC +config REGULATOR_DBX500_PRCMU + bool + config REGULATOR_DB8500_PRCMU bool "ST-Ericsson DB8500 Voltage Domain Regulators" depends on MFD_DB8500_PRCMU + select REGULATOR_DBX500_PRCMU help This driver supports the voltage domain regulators controlled by the DB8500 PRCMU diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 1668b2e667ce..bf5951352484 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o +obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 515443fcd26b..4bd25e75efa0 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c @@ -18,74 +18,11 @@ #include #include #include - -/* - * power state reference count - */ -static int power_state_active_cnt; /* will initialize to zero */ -static DEFINE_SPINLOCK(power_state_active_lock); - -static void power_state_active_enable(void) -{ - unsigned long flags; - - spin_lock_irqsave(&power_state_active_lock, flags); - power_state_active_cnt++; - spin_unlock_irqrestore(&power_state_active_lock, flags); -} - -static int power_state_active_disable(void) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&power_state_active_lock, flags); - if (power_state_active_cnt <= 0) { - pr_err("power state: unbalanced enable/disable calls\n"); - ret = -EINVAL; - goto out; - } - - power_state_active_cnt--; -out: - spin_unlock_irqrestore(&power_state_active_lock, flags); - return ret; -} - -/* - * Exported interface for CPUIdle only. This function is called when interrupts - * are turned off. Hence, no locking. - */ -int power_state_active_is_enabled(void) -{ - return (power_state_active_cnt > 0); -} - -/** - * struct db8500_regulator_info - db8500 regulator information - * @dev: device pointer - * @desc: regulator description - * @rdev: regulator device pointer - * @is_enabled: status of the regulator - * @epod_id: id for EPOD (power domain) - * @is_ramret: RAM retention switch for EPOD (power domain) - * @operating_point: operating point (only for vape, to be removed) - * - */ -struct db8500_regulator_info { - struct device *dev; - struct regulator_desc desc; - struct regulator_dev *rdev; - bool is_enabled; - u16 epod_id; - bool is_ramret; - bool exclude_from_power_state; - unsigned int operating_point; -}; +#include "dbx500-prcmu.h" static int db8500_regulator_enable(struct regulator_dev *rdev) { - struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); if (info == NULL) return -EINVAL; @@ -93,16 +30,18 @@ static int db8500_regulator_enable(struct regulator_dev *rdev) dev_vdbg(rdev_get_dev(rdev), "regulator-%s-enable\n", info->desc.name); - info->is_enabled = true; - if (!info->exclude_from_power_state) - power_state_active_enable(); + if (!info->is_enabled) { + info->is_enabled = true; + if (!info->exclude_from_power_state) + power_state_active_enable(); + } return 0; } static int db8500_regulator_disable(struct regulator_dev *rdev) { - struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); int ret = 0; if (info == NULL) @@ -111,16 +50,18 @@ static int db8500_regulator_disable(struct regulator_dev *rdev) dev_vdbg(rdev_get_dev(rdev), "regulator-%s-disable\n", info->desc.name); - info->is_enabled = false; - if (!info->exclude_from_power_state) - ret = power_state_active_disable(); + if (info->is_enabled) { + info->is_enabled = false; + if (!info->exclude_from_power_state) + ret = power_state_active_disable(); + } return ret; } static int db8500_regulator_is_enabled(struct regulator_dev *rdev) { - struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); if (info == NULL) return -EINVAL; @@ -197,7 +138,7 @@ static int disable_epod(u16 epod_id, bool ramret) */ static int db8500_regulator_switch_enable(struct regulator_dev *rdev) { - struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); int ret; if (info == NULL) @@ -221,7 +162,7 @@ static int db8500_regulator_switch_enable(struct regulator_dev *rdev) static int db8500_regulator_switch_disable(struct regulator_dev *rdev) { - struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); int ret; if (info == NULL) @@ -245,7 +186,7 @@ static int db8500_regulator_switch_disable(struct regulator_dev *rdev) static int db8500_regulator_switch_is_enabled(struct regulator_dev *rdev) { - struct db8500_regulator_info *info = rdev_get_drvdata(rdev); + struct dbx500_regulator_info *info = rdev_get_drvdata(rdev); if (info == NULL) return -EINVAL; @@ -266,8 +207,8 @@ static struct regulator_ops db8500_regulator_switch_ops = { /* * Regulator information */ -static struct db8500_regulator_info -db8500_regulator_info[DB8500_NUM_REGULATORS] = { +static struct dbx500_regulator_info +dbx500_regulator_info[DB8500_NUM_REGULATORS] = { [DB8500_REGULATOR_VAPE] = { .desc = { .name = "db8500-vape", @@ -476,12 +417,12 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) int i, err; /* register all regulators */ - for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) { - struct db8500_regulator_info *info; + for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) { + struct dbx500_regulator_info *info; struct regulator_init_data *init_data = &db8500_init_data[i]; /* assign per-regulator data */ - info = &db8500_regulator_info[i]; + info = &dbx500_regulator_info[i]; info->dev = &pdev->dev; /* register with the regulator framework */ @@ -494,7 +435,7 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) /* if failing, unregister all earlier regulators */ while (--i >= 0) { - info = &db8500_regulator_info[i]; + info = &dbx500_regulator_info[i]; regulator_unregister(info->rdev); } return err; @@ -503,17 +444,22 @@ static int __devinit db8500_regulator_probe(struct platform_device *pdev) dev_dbg(rdev_get_dev(info->rdev), "regulator-%s-probed\n", info->desc.name); } + err = ux500_regulator_debug_init(pdev, + dbx500_regulator_info, + ARRAY_SIZE(dbx500_regulator_info)); - return 0; + return err; } static int __exit db8500_regulator_remove(struct platform_device *pdev) { int i; - for (i = 0; i < ARRAY_SIZE(db8500_regulator_info); i++) { - struct db8500_regulator_info *info; - info = &db8500_regulator_info[i]; + ux500_regulator_debug_exit(); + + for (i = 0; i < ARRAY_SIZE(dbx500_regulator_info); i++) { + struct dbx500_regulator_info *info; + info = &dbx500_regulator_info[i]; dev_vdbg(rdev_get_dev(info->rdev), "regulator-%s-remove\n", info->desc.name); diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c new file mode 100644 index 000000000000..f2e5ecdc5864 --- /dev/null +++ b/drivers/regulator/dbx500-prcmu.c @@ -0,0 +1,241 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * License Terms: GNU General Public License v2 + * Authors: Sundar Iyer for ST-Ericsson + * Bengt Jonsson for ST-Ericsson + * + * UX500 common part of Power domain regulators + */ + +#include +#include +#include +#include +#include +#include + +#include "dbx500-prcmu.h" + +/* + * power state reference count + */ +static int power_state_active_cnt; /* will initialize to zero */ +static DEFINE_SPINLOCK(power_state_active_lock); + +int power_state_active_get(void) +{ + unsigned long flags; + int cnt; + + spin_lock_irqsave(&power_state_active_lock, flags); + cnt = power_state_active_cnt; + spin_unlock_irqrestore(&power_state_active_lock, flags); + + return cnt; +} + +void power_state_active_enable(void) +{ + unsigned long flags; + + spin_lock_irqsave(&power_state_active_lock, flags); + power_state_active_cnt++; + spin_unlock_irqrestore(&power_state_active_lock, flags); +} + +int power_state_active_disable(void) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&power_state_active_lock, flags); + if (power_state_active_cnt <= 0) { + pr_err("power state: unbalanced enable/disable calls\n"); + ret = -EINVAL; + goto out; + } + + power_state_active_cnt--; +out: + spin_unlock_irqrestore(&power_state_active_lock, flags); + return ret; +} + +#ifdef CONFIG_REGULATOR_DEBUG + +static struct ux500_regulator_debug { + struct dentry *dir; + struct dentry *status_file; + struct dentry *power_state_cnt_file; + struct dbx500_regulator_info *regulator_array; + int num_regulators; + u8 *state_before_suspend; + u8 *state_after_suspend; +} rdebug; + +void ux500_regulator_suspend_debug(void) +{ + int i; + for (i = 0; i < rdebug.num_regulators; i++) + rdebug.state_before_suspend[i] = + rdebug.regulator_array[i].is_enabled; +} + +void ux500_regulator_resume_debug(void) +{ + int i; + for (i = 0; i < rdebug.num_regulators; i++) + rdebug.state_after_suspend[i] = + rdebug.regulator_array[i].is_enabled; +} + +static int ux500_regulator_power_state_cnt_print(struct seq_file *s, void *p) +{ + struct device *dev = s->private; + int err; + + /* print power state count */ + err = seq_printf(s, "ux500-regulator power state count: %i\n", + power_state_active_get()); + if (err < 0) + dev_err(dev, "seq_printf overflow\n"); + + return 0; +} + +static int ux500_regulator_power_state_cnt_open(struct inode *inode, + struct file *file) +{ + return single_open(file, ux500_regulator_power_state_cnt_print, + inode->i_private); +} + +static const struct file_operations ux500_regulator_power_state_cnt_fops = { + .open = ux500_regulator_power_state_cnt_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +static int ux500_regulator_status_print(struct seq_file *s, void *p) +{ + struct device *dev = s->private; + int err; + int i; + + /* print dump header */ + err = seq_printf(s, "ux500-regulator status:\n"); + if (err < 0) + dev_err(dev, "seq_printf overflow\n"); + + err = seq_printf(s, "%31s : %8s : %8s\n", "current", + "before", "after"); + if (err < 0) + dev_err(dev, "seq_printf overflow\n"); + + for (i = 0; i < rdebug.num_regulators; i++) { + struct dbx500_regulator_info *info; + /* Access per-regulator data */ + info = &rdebug.regulator_array[i]; + + /* print status */ + err = seq_printf(s, "%20s : %8s : %8s : %8s\n", info->desc.name, + info->is_enabled ? "enabled" : "disabled", + rdebug.state_before_suspend[i] ? "enabled" : "disabled", + rdebug.state_after_suspend[i] ? "enabled" : "disabled"); + if (err < 0) + dev_err(dev, "seq_printf overflow\n"); + } + + return 0; +} + +static int ux500_regulator_status_open(struct inode *inode, struct file *file) +{ + return single_open(file, ux500_regulator_status_print, + inode->i_private); +} + +static const struct file_operations ux500_regulator_status_fops = { + .open = ux500_regulator_status_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .owner = THIS_MODULE, +}; + +int __attribute__((weak)) dbx500_regulator_testcase( + struct dbx500_regulator_info *regulator_info, + int num_regulators) +{ + return 0; +} + +int __devinit +ux500_regulator_debug_init(struct platform_device *pdev, + struct dbx500_regulator_info *regulator_info, + int num_regulators) +{ + /* create directory */ + rdebug.dir = debugfs_create_dir("ux500-regulator", NULL); + if (!rdebug.dir) + goto exit_no_debugfs; + + /* create "status" file */ + rdebug.status_file = debugfs_create_file("status", + S_IRUGO, rdebug.dir, &pdev->dev, + &ux500_regulator_status_fops); + if (!rdebug.status_file) + goto exit_destroy_dir; + + /* create "power-state-count" file */ + rdebug.power_state_cnt_file = debugfs_create_file("power-state-count", + S_IRUGO, rdebug.dir, &pdev->dev, + &ux500_regulator_power_state_cnt_fops); + if (!rdebug.power_state_cnt_file) + goto exit_destroy_status; + + rdebug.regulator_array = regulator_info; + rdebug.num_regulators = num_regulators; + + rdebug.state_before_suspend = kzalloc(num_regulators, GFP_KERNEL); + if (!rdebug.state_before_suspend) { + dev_err(&pdev->dev, + "could not allocate memory for saving state\n"); + goto exit_destroy_power_state; + } + + rdebug.state_after_suspend = kzalloc(num_regulators, GFP_KERNEL); + if (!rdebug.state_after_suspend) { + dev_err(&pdev->dev, + "could not allocate memory for saving state\n"); + goto exit_free; + } + + dbx500_regulator_testcase(regulator_info, num_regulators); + return 0; + +exit_free: + kfree(rdebug.state_before_suspend); +exit_destroy_power_state: + debugfs_remove(rdebug.power_state_cnt_file); +exit_destroy_status: + debugfs_remove(rdebug.status_file); +exit_destroy_dir: + debugfs_remove(rdebug.dir); +exit_no_debugfs: + dev_err(&pdev->dev, "failed to create debugfs entries.\n"); + return -ENOMEM; +} + +int __devexit ux500_regulator_debug_exit(void) +{ + debugfs_remove_recursive(rdebug.dir); + kfree(rdebug.state_after_suspend); + kfree(rdebug.state_before_suspend); + + return 0; +} +#endif diff --git a/drivers/regulator/dbx500-prcmu.h b/drivers/regulator/dbx500-prcmu.h new file mode 100644 index 000000000000..e763883a44f4 --- /dev/null +++ b/drivers/regulator/dbx500-prcmu.h @@ -0,0 +1,63 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * + * Author: Bengt Jonsson for ST-Ericsson, + * Jonas Aaberg for ST-Ericsson + * + * License Terms: GNU General Public License v2 + * + */ + +#ifndef DBX500_REGULATOR_H +#define DBX500_REGULATOR_H + +#include + +/** + * struct dbx500_regulator_info - dbx500 regulator information + * @dev: device pointer + * @desc: regulator description + * @rdev: regulator device pointer + * @is_enabled: status of the regulator + * @epod_id: id for EPOD (power domain) + * @is_ramret: RAM retention switch for EPOD (power domain) + * @operating_point: operating point (only for vape, to be removed) + * + */ +struct dbx500_regulator_info { + struct device *dev; + struct regulator_desc desc; + struct regulator_dev *rdev; + bool is_enabled; + u16 epod_id; + bool is_ramret; + bool exclude_from_power_state; + unsigned int operating_point; +}; + +void power_state_active_enable(void); +int power_state_active_disable(void); + + +#ifdef CONFIG_REGULATOR_DEBUG +int ux500_regulator_debug_init(struct platform_device *pdev, + struct dbx500_regulator_info *regulator_info, + int num_regulators); + +int ux500_regulator_debug_exit(void); +#else + +static inline int ux500_regulator_debug_init(struct platform_device *pdev, + struct dbx500_regulator_info *regulator_info, + int num_regulators) +{ + return 0; +} + +static inline int ux500_regulator_debug_exit(void) +{ + return 0; +} + +#endif +#endif -- GitLab From 62aa492582cd6ce9f5e797ac3197239e63de1df9 Mon Sep 17 00:00:00 2001 From: Sangbeom Kim Date: Fri, 13 Jan 2012 10:13:13 +0900 Subject: [PATCH 00197/10698] regulator: Add S5M8767 configuration This patch add Samsung S5M8767A pmic configuration. Signed-off-by: Sangbeom Kim Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 8 ++++++++ drivers/regulator/Makefile | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index c7e49b140be9..4792d661f0bf 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -136,6 +136,14 @@ config REGULATOR_MAX8998 via I2C bus. The provided regulator is suitable for S3C6410 and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages. +config REGULATOR_S5M8767 + tristate "Samsung S5M8767A voltage regulator" + depends on MFD_S5M_CORE + help + This driver supports a Samsung S5M8767A voltage output regulator + via I2C bus. S5M8767A have 9 Bucks and 28 LDOs output and + supports DVS mode with 8bits of output voltage control. + config REGULATOR_TWL4030 bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC" depends on TWL4030_CORE diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index bf5951352484..66be54a3e680 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -50,5 +50,7 @@ obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o +obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o + ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG -- GitLab From a493077f1883a627d6ba2659b0a82888e58d31dd Mon Sep 17 00:00:00 2001 From: AnilKumar Ch Date: Wed, 11 Jan 2012 16:11:49 +0530 Subject: [PATCH 00198/10698] regulator: tps65217: Add tps65217 regulator driver This patch adds tps65217 PMIC as a regulator The regulator module consists of 3 DCDCs and 4 LDOs. The output voltages are configurable and are meant to supply power to the main processor and other components Signed-off-by: AnilKumar Ch Signed-off-by: Mark Brown --- drivers/regulator/Kconfig | 9 + drivers/regulator/Makefile | 1 + drivers/regulator/tps65217-regulator.c | 493 +++++++++++++++++++++++++ 3 files changed, 503 insertions(+) create mode 100644 drivers/regulator/tps65217-regulator.c diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4792d661f0bf..376824b865a4 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -275,6 +275,15 @@ config REGULATOR_TPS6507X three step-down converters and two general-purpose LDO voltage regulators. It supports TI's software based Class-2 SmartReflex implementation. +config REGULATOR_TPS65217 + tristate "TI TPS65217 Power regulators" + depends on MFD_TPS65217 + help + This driver supports TPS65217 voltage regulator chips. TPS65217 + provides three step-down converters and four general-purpose LDO + voltage regulators. It supports software based voltage control + for different voltage domains + config REGULATOR_TPS65912 tristate "TI TPS65912 Power regulator" depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI) diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 66be54a3e680..4cbf8c55f8a9 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -40,6 +40,7 @@ obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o +obj-$(CONFIG_REGULATOR_TPS65217) += tps65217-regulator.o obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c new file mode 100644 index 000000000000..66655668f965 --- /dev/null +++ b/drivers/regulator/tps65217-regulator.c @@ -0,0 +1,493 @@ +/* + * tps65217-regulator.c + * + * Regulator driver for TPS65217 PMIC + * + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation 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 +#include +#include +#include +#include +#include + +#include +#include +#include + +#define TPS65217_REGULATOR(_name, _id, _ops, _n) \ + { \ + .name = _name, \ + .id = _id, \ + .ops = &_ops, \ + .n_voltages = _n, \ + .type = REGULATOR_VOLTAGE, \ + .owner = THIS_MODULE, \ + } \ + +#define TPS65217_INFO(_nm, _min, _max, _f1, _f2, _t, _n, _em, _vr, _vm) \ + { \ + .name = _nm, \ + .min_uV = _min, \ + .max_uV = _max, \ + .vsel_to_uv = _f1, \ + .uv_to_vsel = _f2, \ + .table = _t, \ + .table_len = _n, \ + .enable_mask = _em, \ + .set_vout_reg = _vr, \ + .set_vout_mask = _vm, \ + } + +static const int LDO1_VSEL_table[] = { + 1000000, 1100000, 1200000, 1250000, + 1300000, 1350000, 1400000, 1500000, + 1600000, 1800000, 2500000, 2750000, + 2800000, 3000000, 3100000, 3300000, +}; + +static int tps65217_vsel_to_uv1(unsigned int vsel) +{ + int uV = 0; + + if (vsel > 63) + return -EINVAL; + + if (vsel <= 24) + uV = vsel * 25000 + 900000; + else if (vsel <= 52) + uV = (vsel - 24) * 50000 + 1500000; + else if (vsel < 56) + uV = (vsel - 52) * 100000 + 2900000; + else + uV = 3300000; + + return uV; +} + +static int tps65217_uv_to_vsel1(int uV, unsigned int *vsel) +{ + if ((uV < 0) && (uV > 3300000)) + return -EINVAL; + + if (uV <= 1500000) + *vsel = (uV - 875001) / 25000; + else if (uV <= 2900000) + *vsel = 24 + (uV - 1450001) / 50000; + else if (uV < 3300000) + *vsel = 52 + (uV - 2800001) / 100000; + else + *vsel = 56; + + return 0; +} + +static int tps65217_vsel_to_uv2(unsigned int vsel) +{ + int uV = 0; + + if (vsel > 31) + return -EINVAL; + + if (vsel <= 8) + uV = vsel * 50000 + 1500000; + else if (vsel <= 13) + uV = (vsel - 8) * 100000 + 1900000; + else + uV = (vsel - 13) * 50000 + 2400000; + + return uV; +} + +static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel) +{ + if ((uV < 0) && (uV > 3300000)) + return -EINVAL; + + if (uV <= 1900000) + *vsel = (uV - 1450001) / 50000; + else if (uV <= 2400000) + *vsel = 8 + (uV - 1800001) / 100000; + else + *vsel = 13 + (uV - 2350001) / 50000; + + return 0; +} + +static struct tps_info tps65217_pmic_regs[] = { + TPS65217_INFO("DCDC1", 900000, 1800000, tps65217_vsel_to_uv1, + tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC1_EN, + TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK), + TPS65217_INFO("DCDC2", 900000, 3300000, tps65217_vsel_to_uv1, + tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC2_EN, + TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK), + TPS65217_INFO("DCDC3", 900000, 1500000, tps65217_vsel_to_uv1, + tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC3_EN, + TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK), + TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL, LDO1_VSEL_table, + 16, TPS65217_ENABLE_LDO1_EN, TPS65217_REG_DEFLDO1, + TPS65217_DEFLDO1_LDO1_MASK), + TPS65217_INFO("LDO2", 900000, 3300000, tps65217_vsel_to_uv1, + tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_LDO2_EN, + TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK), + TPS65217_INFO("LDO3", 1800000, 3300000, tps65217_vsel_to_uv2, + tps65217_uv_to_vsel2, NULL, 32, + TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN, + TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK), + TPS65217_INFO("LDO4", 1800000, 3300000, tps65217_vsel_to_uv2, + tps65217_uv_to_vsel2, NULL, 32, + TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN, + TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK), +}; + +static int tps65217_pmic_dcdc_is_enabled(struct regulator_dev *dev) +{ + int ret; + struct tps65217 *tps = rdev_get_drvdata(dev); + unsigned int data, dcdc = rdev_get_id(dev); + + if (dcdc < TPS65217_DCDC_1 || dcdc > TPS65217_DCDC_3) + return -EINVAL; + + ret = tps65217_reg_read(tps, TPS65217_REG_ENABLE, &data); + if (ret) + return ret; + + return (data & tps->info[dcdc]->enable_mask) ? 1 : 0; +} + +static int tps65217_pmic_ldo_is_enabled(struct regulator_dev *dev) +{ + int ret; + struct tps65217 *tps = rdev_get_drvdata(dev); + unsigned int data, ldo = rdev_get_id(dev); + + if (ldo < TPS65217_LDO_1 || ldo > TPS65217_LDO_4) + return -EINVAL; + + ret = tps65217_reg_read(tps, TPS65217_REG_ENABLE, &data); + if (ret) + return ret; + + return (data & tps->info[ldo]->enable_mask) ? 1 : 0; +} + +static int tps65217_pmic_dcdc_enable(struct regulator_dev *dev) +{ + struct tps65217 *tps = rdev_get_drvdata(dev); + unsigned int dcdc = rdev_get_id(dev); + + if (dcdc < TPS65217_DCDC_1 || dcdc > TPS65217_DCDC_3) + return -EINVAL; + + /* Enable the regulator and password protection is level 1 */ + return tps65217_set_bits(tps, TPS65217_REG_ENABLE, + tps->info[dcdc]->enable_mask, + tps->info[dcdc]->enable_mask, + TPS65217_PROTECT_L1); +} + +static int tps65217_pmic_dcdc_disable(struct regulator_dev *dev) +{ + struct tps65217 *tps = rdev_get_drvdata(dev); + unsigned int dcdc = rdev_get_id(dev); + + if (dcdc < TPS65217_DCDC_1 || dcdc > TPS65217_DCDC_3) + return -EINVAL; + + /* Disable the regulator and password protection is level 1 */ + return tps65217_clear_bits(tps, TPS65217_REG_ENABLE, + tps->info[dcdc]->enable_mask, TPS65217_PROTECT_L1); +} + +static int tps65217_pmic_ldo_enable(struct regulator_dev *dev) +{ + struct tps65217 *tps = rdev_get_drvdata(dev); + unsigned int ldo = rdev_get_id(dev); + + if (ldo < TPS65217_LDO_1 || ldo > TPS65217_LDO_4) + return -EINVAL; + + /* Enable the regulator and password protection is level 1 */ + return tps65217_set_bits(tps, TPS65217_REG_ENABLE, + tps->info[ldo]->enable_mask, + tps->info[ldo]->enable_mask, + TPS65217_PROTECT_L1); +} + +static int tps65217_pmic_ldo_disable(struct regulator_dev *dev) +{ + struct tps65217 *tps = rdev_get_drvdata(dev); + unsigned int ldo = rdev_get_id(dev); + + if (ldo < TPS65217_LDO_1 || ldo > TPS65217_LDO_4) + return -EINVAL; + + /* Disable the regulator and password protection is level 1 */ + return tps65217_clear_bits(tps, TPS65217_REG_ENABLE, + tps->info[ldo]->enable_mask, TPS65217_PROTECT_L1); +} + +static int tps65217_pmic_dcdc_get_voltage_sel(struct regulator_dev *dev) +{ + int ret; + struct tps65217 *tps = rdev_get_drvdata(dev); + unsigned int selector, dcdc = rdev_get_id(dev); + + if (dcdc < TPS65217_DCDC_1 || dcdc > TPS65217_DCDC_3) + return -EINVAL; + + ret = tps65217_reg_read(tps, tps->info[dcdc]->set_vout_reg, &selector); + if (ret) + return ret; + + selector &= tps->info[dcdc]->set_vout_mask; + + return selector; +} + +static int tps65217_pmic_dcdc_set_voltage(struct regulator_dev *dev, + int min_uV, int max_uV, unsigned *selector) +{ + int ret; + struct tps65217 *tps = rdev_get_drvdata(dev); + unsigned int dc