[PATCH v5 2/2] ACPI: Add Intel MID SPI early console support.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



DesignWare SPI UART is used as one of the debug ports on Low Power Intel
Architecture (LPIA) platforms.  This patch is introduced to support this
debugging console reported by ACPI DBGP/DBG2.  The original MID SPI
early console stuff is also refined to co-exist with the new ACPI usage
model.

To use this facility on LPIA platforms, you need to enable the following
kernel configurations:
  CONFIG_EARLY_PRINTK_ACPI=y
  CONFIG_EARLY_PRINTK_INTEL_MID_SPI=y
Then you need to append the following kernel parameter to the kernel
command line in the boot loader configuration file:
  earlyprintk=acpi

Signed-off-by: Lv Zheng <lv.zheng@xxxxxxxxx>
Reviewed-by: Feng Tang <feng.tang@xxxxxxxxx>
---
 Documentation/kernel-parameters.txt        |    1 +
 arch/x86/Kconfig.debug                     |   23 +++
 arch/x86/include/asm/mrst.h                |    2 +-
 arch/x86/kernel/early_printk.c             |   12 +-
 arch/x86/platform/mrst/early_printk_mrst.c |  186 +----------------------
 drivers/platform/x86/Makefile              |    2 +
 drivers/platform/x86/early/Makefile        |    5 +
 drivers/platform/x86/early/intel_mid_spi.c |  220 ++++++++++++++++++++++++++++
 include/acpi/actbl2.h                      |    1 +
 include/linux/intel_mid_early.h            |   12 ++
 10 files changed, 283 insertions(+), 181 deletions(-)
 create mode 100644 drivers/platform/x86/early/Makefile
 create mode 100644 drivers/platform/x86/early/intel_mid_spi.c
 create mode 100644 include/linux/intel_mid_early.h

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index f656765..003ffd9 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -762,6 +762,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			earlyprintk=vga
 			earlyprintk=serial[,ttySn[,baudrate]]
 			earlyprintk=ttySn[,baudrate]
+			earlyprintk=mrst
 			earlyprintk=dbgp[debugController#]
 			earlyprintk=acpi[debugController#]
 
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 5778082..4a26e2d 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -43,9 +43,32 @@ config EARLY_PRINTK
 	  with klogd/syslogd or the X server. You should normally N here,
 	  unless you want to debug such a crash.
 
+config EARLY_PRINTK_INTEL_MID_SPI
+	bool "Early printk for Intel MID SPI UART port"
+	depends on EARLY_PRINTK
+	---help---
+	  Write kernel log output directly into the MID SPI UART debug port.
+
+	  Intel MID platforms are using DesignWare SPI UART as its debug
+	  console.  This option does not introduce actual early console into
+	  the kernel binary, but is required by a real early console
+	  implementation (EARLY_PRINTK_INTEL_MID or EARLY_PRINTK_ACPI).
+	  You should normally N here unless you need to do kernel booting
+	  development.
+
 config EARLY_PRINTK_INTEL_MID
 	bool "Early printk for Intel MID platform support"
 	depends on EARLY_PRINTK && X86_INTEL_MID
+	select EARLY_PRINTK_INTEL_MID_SPI
+	---help---
+	  Write kernel log output directly into the MID SPI UART debug port.
+
+	  Intel MID platforms are always equipped with SPI debug ports and
+	  USB OTG debug ports. To enable these debugging facilities, you
+	  need to pass "earlyprintk=mrst" parameter to the kernel through
+	  boot loaders.  Please see "Documentation/kernel-parameter.txt" for
+	  details.  You should normally N here unless you need to do kernel
+	  booting development.
 
 config EARLY_PRINTK_DBGP
 	bool "Early printk via EHCI debug port"
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
index fc18bf3..8ab0655 100644
--- a/arch/x86/include/asm/mrst.h
+++ b/arch/x86/include/asm/mrst.h
@@ -12,6 +12,7 @@
 #define _ASM_X86_MRST_H
 
 #include <linux/sfi.h>
+#include <linux/intel_mid_early.h>
 
 extern int pci_mrst_init(void);
 extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
@@ -63,7 +64,6 @@ extern enum mrst_timer_options mrst_timer_options;
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX	8
 
-extern struct console early_mrst_console;
 extern void mrst_early_console_init(void);
 
 extern struct console early_hsu_console;
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index bf5b596..9b5ee96 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -205,6 +205,16 @@ static inline void early_console_register(struct console *con, int keep_early)
 
 int __init __acpi_early_console_start(struct acpi_debug_port *info)
 {
+#ifdef CONFIG_EARLY_PRINTK_INTEL_MID_SPI
+	if (info->port_type == ACPI_DBG2_SERIAL_PORT
+	    && info->port_subtype == ACPI_DBG2_INTEL_MID_SPI
+	    && info->register_count > 0) {
+		mid_spi_early_console_init((u32)(info->registers[0].address));
+		early_console_register(&mid_spi_early_console,
+				       acpi_early_console_keep(info));
+	}
+#endif
+
 	return 0;
 }
 #endif
@@ -256,7 +266,7 @@ static int __init setup_early_printk(char *buf)
 #ifdef CONFIG_EARLY_PRINTK_INTEL_MID
 		if (!strncmp(buf, "mrst", 4)) {
 			mrst_early_console_init();
-			early_console_register(&early_mrst_console, keep);
+			early_console_register(&mid_spi_early_console, keep);
 		}
 
 		if (!strncmp(buf, "hsu", 3)) {
diff --git a/arch/x86/platform/mrst/early_printk_mrst.c b/arch/x86/platform/mrst/early_printk_mrst.c
index 028454f..7afbf18 100644
--- a/arch/x86/platform/mrst/early_printk_mrst.c
+++ b/arch/x86/platform/mrst/early_printk_mrst.c
@@ -29,82 +29,8 @@
 #include <asm/pgtable.h>
 #include <asm/mrst.h>
 
-#define MRST_SPI_TIMEOUT		0x200000
 #define MRST_REGBASE_SPI0		0xff128000
 #define MRST_REGBASE_SPI1		0xff128400
-#define MRST_CLK_SPI0_REG		0xff11d86c
-
-/* Bit fields in CTRLR0 */
-#define SPI_DFS_OFFSET			0
-
-#define SPI_FRF_OFFSET			4
-#define SPI_FRF_SPI			0x0
-#define SPI_FRF_SSP			0x1
-#define SPI_FRF_MICROWIRE		0x2
-#define SPI_FRF_RESV			0x3
-
-#define SPI_MODE_OFFSET			6
-#define SPI_SCPH_OFFSET			6
-#define SPI_SCOL_OFFSET			7
-#define SPI_TMOD_OFFSET			8
-#define	SPI_TMOD_TR			0x0		/* xmit & recv */
-#define SPI_TMOD_TO			0x1		/* xmit only */
-#define SPI_TMOD_RO			0x2		/* recv only */
-#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
-
-#define SPI_SLVOE_OFFSET		10
-#define SPI_SRL_OFFSET			11
-#define SPI_CFS_OFFSET			12
-
-/* Bit fields in SR, 7 bits */
-#define SR_MASK				0x7f		/* cover 7 bits */
-#define SR_BUSY				(1 << 0)
-#define SR_TF_NOT_FULL			(1 << 1)
-#define SR_TF_EMPT			(1 << 2)
-#define SR_RF_NOT_EMPT			(1 << 3)
-#define SR_RF_FULL			(1 << 4)
-#define SR_TX_ERR			(1 << 5)
-#define SR_DCOL				(1 << 6)
-
-struct dw_spi_reg {
-	u32	ctrl0;
-	u32	ctrl1;
-	u32	ssienr;
-	u32	mwcr;
-	u32	ser;
-	u32	baudr;
-	u32	txfltr;
-	u32	rxfltr;
-	u32	txflr;
-	u32	rxflr;
-	u32	sr;
-	u32	imr;
-	u32	isr;
-	u32	risr;
-	u32	txoicr;
-	u32	rxoicr;
-	u32	rxuicr;
-	u32	msticr;
-	u32	icr;
-	u32	dmacr;
-	u32	dmatdlr;
-	u32	dmardlr;
-	u32	idr;
-	u32	version;
-
-	/* Currently operates as 32 bits, though only the low 16 bits matter */
-	u32	dr;
-} __packed;
-
-#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
-#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
-
-/* Default use SPI0 register for mrst, we will detect Penwell and use SPI1 */
-static unsigned long mrst_spi_paddr = MRST_REGBASE_SPI0;
-
-static u32 *pclk_spi0;
-/* Always contains an accessible address, start with 0 */
-static struct dw_spi_reg *pspi;
 
 static struct kmsg_dumper dw_dumper;
 static int dumper_registered;
@@ -116,77 +42,21 @@ static void dw_kmsg_dump(struct kmsg_dumper *dumper,
 	size_t len;
 
 	/* When run to this, we'd better re-init the HW */
-	mrst_early_console_init();
+	mid_spi_early_console_reset();
 
 	while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len))
-		early_mrst_console.write(&early_mrst_console, line, len);
-}
-
-/* Set the ratio rate to 115200, 8n1, IRQ disabled */
-static void max3110_write_config(void)
-{
-	u16 config;
-
-	config = 0xc001;
-	dw_writel(pspi, dr, config);
-}
-
-/* Translate char to a eligible word and send to max3110 */
-static void max3110_write_data(char c)
-{
-	u16 data;
-
-	data = 0x8000 | c;
-	dw_writel(pspi, dr, data);
+		mid_spi_early_console.write(&mid_spi_early_console, line, len);
 }
 
 void mrst_early_console_init(void)
 {
-	u32 ctrlr0 = 0;
-	u32 spi0_cdiv;
-	u32 freq; /* Freqency info only need be searched once */
-
-	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
-	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-							MRST_CLK_SPI0_REG);
-	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
-	freq = 100000000 / (spi0_cdiv + 1);
+	/* Default use SPI0 register for mrst */
+	unsigned long spi_paddr = MRST_REGBASE_SPI0;
 
+	/* Detect Penwell and use SPI1 */
 	if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL)
-		mrst_spi_paddr = MRST_REGBASE_SPI1;
-
-	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
-						mrst_spi_paddr);
-
-	/* Disable SPI controller */
-	dw_writel(pspi, ssienr, 0);
-
-	/* Set control param, 8 bits, transmit only mode */
-	ctrlr0 = dw_readl(pspi, ctrl0);
-
-	ctrlr0 &= 0xfcc0;
-	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
-		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
-	dw_writel(pspi, ctrl0, ctrlr0);
-
-	/*
-	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
-	 * calculate the clk dividor to make the clock a little slower
-	 * than real baud rate.
-	 */
-	dw_writel(pspi, baudr, freq/100000);
-
-	/* Disable all INT for early phase */
-	dw_writel(pspi, imr, 0x0);
-
-	/* Set the cs to spi-uart */
-	dw_writel(pspi, ser, 0x2);
-
-	/* Enable the HW, the last step for HW init */
-	dw_writel(pspi, ssienr, 0x1);
-
-	/* Set the default configuration */
-	max3110_write_config();
+		spi_paddr = MRST_REGBASE_SPI1;
+	mid_spi_early_console_init(spi_paddr);
 
 	/* Register the kmsg dumper */
 	if (!dumper_registered) {
@@ -196,48 +66,6 @@ void mrst_early_console_init(void)
 	}
 }
 
-/* Slave select should be called in the read/write function */
-static void early_mrst_spi_putc(char c)
-{
-	unsigned int timeout;
-	u32 sr;
-
-	timeout = MRST_SPI_TIMEOUT;
-	/* Early putc needs to make sure the TX FIFO is not full */
-	while (--timeout) {
-		sr = dw_readl(pspi, sr);
-		if (!(sr & SR_TF_NOT_FULL))
-			cpu_relax();
-		else
-			break;
-	}
-
-	if (!timeout)
-		pr_warning("MRST earlycon: timed out\n");
-	else
-		max3110_write_data(c);
-}
-
-/* Early SPI only uses polling mode */
-static void early_mrst_spi_write(struct console *con, const char *str, unsigned n)
-{
-	int i;
-
-	for (i = 0; i < n && *str; i++) {
-		if (*str == '\n')
-			early_mrst_spi_putc('\r');
-		early_mrst_spi_putc(*str);
-		str++;
-	}
-}
-
-struct console early_mrst_console = {
-	.name =		"earlymrst",
-	.write =	early_mrst_spi_write,
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
-};
-
 /*
  * Following is the early console based on Medfield HSU (High
  * Speed UART) device.
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index bf7e4f9..6e4ff46 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -50,3 +50,5 @@ obj-$(CONFIG_INTEL_MID_POWER_BUTTON)	+= intel_mid_powerbtn.o
 obj-$(CONFIG_INTEL_OAKTRAIL)	+= intel_oaktrail.o
 obj-$(CONFIG_SAMSUNG_Q10)	+= samsung-q10.o
 obj-$(CONFIG_APPLE_GMUX)	+= apple-gmux.o
+
+obj-$(CONFIG_EARLY_PRINTK)	+= early/
diff --git a/drivers/platform/x86/early/Makefile b/drivers/platform/x86/early/Makefile
new file mode 100644
index 0000000..5d9408c
--- /dev/null
+++ b/drivers/platform/x86/early/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for linux/drivers/platform/x86/early
+# x86 Platform-Specific Early Printk Support
+#
+obj-$(CONFIG_EARLY_PRINTK_INTEL_MID_SPI)	+= intel_mid_spi.o
diff --git a/drivers/platform/x86/early/intel_mid_spi.c b/drivers/platform/x86/early/intel_mid_spi.c
new file mode 100644
index 0000000..fa5a1a2
--- /dev/null
+++ b/drivers/platform/x86/early/intel_mid_spi.c
@@ -0,0 +1,220 @@
+/*
+ * intel_mid_spi.c - SPI UART early consoles for Intel MID platforms
+ *
+ * Copyright (c) 2008-2012, Intel 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; version 2
+ * of the License.
+ */
+
+/*
+ * This file is originally implemented by Feng Tang <feng.tang@xxxxxxxxx>.
+ * It is moved here to co-exist with CONFIG_EARLY_PRINTK_ACPI.
+ * Any questions you should contact the original author.
+ */
+
+#include <linux/serial_reg.h>
+#include <linux/serial_mfd.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/intel_mid_early.h>
+#include <asm/fixmap.h>
+
+#define DW_SPI_TIMEOUT			0x200000
+#define DW_SPI0_CLK_REG			0xff11d86c
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET			0
+
+#define SPI_FRF_OFFSET			4
+#define SPI_FRF_SPI			0x0
+#define SPI_FRF_SSP			0x1
+#define SPI_FRF_MICROWIRE		0x2
+#define SPI_FRF_RESV			0x3
+
+#define SPI_MODE_OFFSET			6
+#define SPI_SCPH_OFFSET			6
+#define SPI_SCOL_OFFSET			7
+#define SPI_TMOD_OFFSET			8
+#define	SPI_TMOD_TR			0x0		/* xmit & recv */
+#define SPI_TMOD_TO			0x1		/* xmit only */
+#define SPI_TMOD_RO			0x2		/* recv only */
+#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET		10
+#define SPI_SRL_OFFSET			11
+#define SPI_CFS_OFFSET			12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK				0x7f		/* cover 7 bits */
+#define SR_BUSY				(1 << 0)
+#define SR_TF_NOT_FULL			(1 << 1)
+#define SR_TF_EMPT			(1 << 2)
+#define SR_RF_NOT_EMPT			(1 << 3)
+#define SR_RF_FULL			(1 << 4)
+#define SR_TX_ERR			(1 << 5)
+#define SR_DCOL				(1 << 6)
+
+struct dw_spi_reg {
+	u32	ctrl0;
+	u32	ctrl1;
+	u32	ssienr;
+	u32	mwcr;
+	u32	ser;
+	u32	baudr;
+	u32	txfltr;
+	u32	rxfltr;
+	u32	txflr;
+	u32	rxflr;
+	u32	sr;
+	u32	imr;
+	u32	isr;
+	u32	risr;
+	u32	txoicr;
+	u32	rxoicr;
+	u32	rxuicr;
+	u32	msticr;
+	u32	icr;
+	u32	dmacr;
+	u32	dmatdlr;
+	u32	dmardlr;
+	u32	idr;
+	u32	version;
+
+	/* Currently operates as 32 bits, though only the low 16 bits matter */
+	u32	dr;
+} __packed;
+
+#define dw_readl(dw, name)		__raw_readl(&(dw)->name)
+#define dw_writel(dw, name, val)	__raw_writel((val), &(dw)->name)
+
+static u32 *pclk_spi0;
+/* Always contains an accessible address, start with 0 */
+static struct dw_spi_reg *pspi;
+static int dw_spi_initialized;
+static u32 dw_spi_regbase;
+
+/* Translate char to a eligible word and send to max3110 */
+static void max3110_write_data(char c)
+{
+	u16 data;
+
+	data = 0x8000 | c;
+	dw_writel(pspi, dr, data);
+}
+
+/* Set the ratio rate to 115200, 8n1, IRQ disabled */
+static void max3110_write_config(void)
+{
+	u16 config;
+
+	config = 0xc001;
+	dw_writel(pspi, dr, config);
+}
+
+int mid_spi_early_console_reset(void)
+{
+	u32 ctrlr0 = 0;
+	u32 spi0_cdiv;
+	u32 freq; /* Freqency info only need be searched once */
+
+	/* Base clk is 100 MHz, the actual clk = 100M / (clk_divider + 1) */
+	pclk_spi0 = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						      DW_SPI0_CLK_REG);
+	spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
+	freq = 100000000 / (spi0_cdiv + 1);
+
+	pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
+						 dw_spi_regbase);
+
+	/* Disable SPI controller */
+	dw_writel(pspi, ssienr, 0);
+
+	/* Set control param, 8 bits, transmit only mode */
+	ctrlr0 = dw_readl(pspi, ctrl0);
+
+	ctrlr0 &= 0xfcc0;
+	ctrlr0 |= 0xf | (SPI_FRF_SPI << SPI_FRF_OFFSET)
+		      | (SPI_TMOD_TO << SPI_TMOD_OFFSET);
+	dw_writel(pspi, ctrl0, ctrlr0);
+
+	/*
+	 * Change the spi0 clk to comply with 115200 bps, use 100000 to
+	 * calculate the clk dividor to make the clock a little slower
+	 * than real baud rate.
+	 */
+	dw_writel(pspi, baudr, freq/100000);
+
+	/* Disable all INT for early phase */
+	dw_writel(pspi, imr, 0x0);
+
+	/* Set the cs to spi-uart */
+	dw_writel(pspi, ser, 0x2);
+
+	/* Enable the HW, the last step for HW init */
+	dw_writel(pspi, ssienr, 0x1);
+
+	/* Set the default configuration */
+	max3110_write_config();
+
+	return 0;
+}
+EXPORT_SYMBOL(mid_spi_early_console_reset);
+
+/* Slave select should be called in the read/write function */
+static void dw_early_spi_putc(char c)
+{
+	unsigned int timeout;
+	u32 sr;
+
+	timeout = DW_SPI_TIMEOUT;
+	/* Early putc needs to make sure the TX FIFO is not full */
+	while (--timeout) {
+		sr = dw_readl(pspi, sr);
+		if (!(sr & SR_TF_NOT_FULL))
+			cpu_relax();
+		else
+			break;
+	}
+
+	if (!timeout)
+		pr_warn("mid-spi-early: timed out\n");
+	else
+		max3110_write_data(c);
+}
+
+/* Early SPI only uses polling mode */
+static void dw_early_spi_write(struct console *con,
+			       const char *str, unsigned n)
+{
+	int i;
+
+	for (i = 0; i < n && *str; i++) {
+		if (*str == '\n')
+			dw_early_spi_putc('\r');
+		dw_early_spi_putc(*str);
+		str++;
+	}
+}
+
+struct console mid_spi_early_console = {
+	.name =		"earlymidspi",
+	.write =	dw_early_spi_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+void __init mid_spi_early_console_init(u32 spi_paddr)
+{
+	if (dw_spi_initialized)
+		return;
+	dw_spi_regbase = spi_paddr;
+	mid_spi_early_console_reset();
+	dw_spi_initialized = 1;
+}
+
diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h
index 1b2b356..ffa9d62 100644
--- a/include/acpi/actbl2.h
+++ b/include/acpi/actbl2.h
@@ -341,6 +341,7 @@ struct acpi_dbg2_device {
 
 #define ACPI_DBG2_16550_COMPATIBLE  0x0000
 #define ACPI_DBG2_16550_SUBSET      0x0001
+#define ACPI_DBG2_INTEL_MID_SPI     0x0002
 
 #define ACPI_DBG2_1394_STANDARD     0x0000
 
diff --git a/include/linux/intel_mid_early.h b/include/linux/intel_mid_early.h
new file mode 100644
index 0000000..edba232
--- /dev/null
+++ b/include/linux/intel_mid_early.h
@@ -0,0 +1,12 @@
+#ifndef LINUX_INTEL_MID_EARLY_H
+#define LINUX_INTEL_MID_EARLY_H
+
+#include <linux/console.h>
+
+extern struct console mid_spi_early_console;
+
+extern void mid_spi_early_console_init(u32 spi_paddr);
+extern int mid_spi_early_console_reset(void);
+
+#endif /* LINUX_INTEL_MID_EARLY_H */
+
-- 
1.7.10

--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux