[PATCH 0/8] sa1100fb updates

STALE3178d

Revision v1 of 3 in this series.

13 messages, 3 authors, 2017-11-27 · open the first message on its own page

[PATCH 0/8] sa1100fb updates

From: linux@armlinux.org.uk (Russell King - ARM Linux)
Date: 2017-09-29 10:50:04

Hi Bart,

This series updates the sa1100fb fbdev driver's initialisation paths
to be more robust.  In doing these updates, I realised that we omitted
to free some memory which was allocated for the framebuffer if
initialisation fails - something that was hidden due to the complex
cleanup that the driver performs.  Switching to managed resources made
this more obvious.

Tested on H3600 iPAQ and Assabet.

 drivers/video/fbdev/sa1100fb.c | 75 +++++++++++++++---------------------------
 drivers/video/fbdev/sa1100fb.h |  2 ++
 2 files changed, 29 insertions(+), 48 deletions(-)

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

[PATCH 1/8] video: sa1100fb: use devm_kzalloc()

From: Russell King <hidden>
Date: 2017-09-29 10:50:56

Use devm_kzalloc() when allocating the private data for the framebuffer
device.

Signed-off-by: Russell King <redacted>
---
 drivers/video/fbdev/sa1100fb.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index fc2aaa5aca23..05a80e08dcde 100644
--- a/drivers/video/fbdev/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -1132,12 +1132,11 @@ static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev)
 	struct sa1100fb_info *fbi;
 	unsigned i;
 
-	fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
-		      GFP_KERNEL);
+	fbi = devm_kzalloc(dev, sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
+			   GFP_KERNEL);
 	if (!fbi)
 		return NULL;
 
-	memset(fbi, 0, sizeof(struct sa1100fb_info));
 	fbi->dev = dev;
 
 	strcpy(fbi->fb.fix.id, SA1100_NAME);
@@ -1292,7 +1291,6 @@ static int sa1100fb_probe(struct platform_device *pdev)
 		iounmap(fbi->base);
 	if (fbi->clk)
 		clk_put(fbi->clk);
-	kfree(fbi);
 	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
-- 
2.7.4

[PATCH 2/8] video: sa1100fb: use devm_clk_get()

From: Russell King <hidden>
Date: 2017-09-29 10:51:01

Use devm_clk_get() to get the clock for the LCD.

Signed-off-by: Russell King <redacted>
---
 drivers/video/fbdev/sa1100fb.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index 05a80e08dcde..1562d7607dd2 100644
--- a/drivers/video/fbdev/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -1230,10 +1230,9 @@ static int sa1100fb_probe(struct platform_device *pdev)
 	if (!fbi)
 		goto failed;
 
-	fbi->clk = clk_get(&pdev->dev, NULL);
+	fbi->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(fbi->clk)) {
 		ret = PTR_ERR(fbi->clk);
-		fbi->clk = NULL;
 		goto failed;
 	}
 
@@ -1289,8 +1288,6 @@ static int sa1100fb_probe(struct platform_device *pdev)
  failed:
 	if (fbi)
 		iounmap(fbi->base);
-	if (fbi->clk)
-		clk_put(fbi->clk);
 	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
-- 
2.7.4

[PATCH 3/8] video: sa1100fb: use devm_ioremap_resource()

From: Russell King <hidden>
Date: 2017-09-29 10:51:07

Use devm_ioremap_resource() to map the LCD controller memory region,
and remove the unnecessary cleanup for this.

Signed-off-by: Russell King <redacted>
---
 drivers/video/fbdev/sa1100fb.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index 1562d7607dd2..ab83970dbfd9 100644
--- a/drivers/video/fbdev/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -1217,29 +1217,28 @@ static int sa1100fb_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	irq = platform_get_irq(pdev, 0);
-	if (irq < 0 || !res)
+	if (irq < 0)
 		return -EINVAL;
 
-	if (!request_mem_region(res->start, resource_size(res), "LCD"))
-		return -EBUSY;
-
 	fbi = sa1100fb_init_fbinfo(&pdev->dev);
 	ret = -ENOMEM;
 	if (!fbi)
 		goto failed;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	fbi->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(fbi->base)) {
+		ret = PTR_ERR(fbi->base);
+		goto failed;
+	}
+
 	fbi->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(fbi->clk)) {
 		ret = PTR_ERR(fbi->clk);
 		goto failed;
 	}
 
-	fbi->base = ioremap(res->start, resource_size(res));
-	if (!fbi->base)
-		goto failed;
-
 	/* Initialize video memory */
 	ret = sa1100fb_map_video_memory(fbi);
 	if (ret)
@@ -1286,9 +1285,6 @@ static int sa1100fb_probe(struct platform_device *pdev)
  err_free_irq:
 	free_irq(irq, fbi);
  failed:
-	if (fbi)
-		iounmap(fbi->base);
-	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
 
-- 
2.7.4

[PATCH 4/8] video: sa1100fb: use devm_request_irq()

From: Russell King <hidden>
Date: 2017-09-29 10:51:12

Use devm_request_irq() to request the interrupt (a little earlier too)
so we can avoid having to manually clean this up.

Signed-off-by: Russell King <redacted>
---
 drivers/video/fbdev/sa1100fb.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index ab83970dbfd9..a48fdb676f3e 100644
--- a/drivers/video/fbdev/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -1239,22 +1239,23 @@ static int sa1100fb_probe(struct platform_device *pdev)
 		goto failed;
 	}
 
-	/* Initialize video memory */
-	ret = sa1100fb_map_video_memory(fbi);
-	if (ret)
-		goto failed;
-
-	ret = request_irq(irq, sa1100fb_handle_irq, 0, "LCD", fbi);
+	ret = devm_request_irq(&pdev->dev, irq, sa1100fb_handle_irq, 0,
+			       "LCD", fbi);
 	if (ret) {
 		dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
 		goto failed;
 	}
 
+	/* Initialize video memory */
+	ret = sa1100fb_map_video_memory(fbi);
+	if (ret)
+		goto failed;
+
 	if (machine_is_shannon()) {
 		ret = gpio_request_one(SHANNON_GPIO_DISP_EN,
 			GPIOF_OUT_INIT_LOW, "display enable");
 		if (ret)
-			goto err_free_irq;
+			goto failed;
 	}
 
 	/*
@@ -1282,8 +1283,6 @@ static int sa1100fb_probe(struct platform_device *pdev)
  err_reg_fb:
 	if (machine_is_shannon())
 		gpio_free(SHANNON_GPIO_DISP_EN);
- err_free_irq:
-	free_irq(irq, fbi);
  failed:
 	return ret;
 }
-- 
2.7.4

[PATCH 5/8] video: sa1100fb: use devm_gpio_request_one()

From: Russell King <hidden>
Date: 2017-09-29 10:51:17

Switch to using devm_gpio_request_one() to request the shannon gpio
and move the request before the video memory allocation, so we request
all device managed resources before this large allocation attempt.

Signed-off-by: Russell King <redacted>
---
 drivers/video/fbdev/sa1100fb.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index a48fdb676f3e..7fa6c8f74ec6 100644
--- a/drivers/video/fbdev/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -1246,18 +1246,18 @@ static int sa1100fb_probe(struct platform_device *pdev)
 		goto failed;
 	}
 
-	/* Initialize video memory */
-	ret = sa1100fb_map_video_memory(fbi);
-	if (ret)
-		goto failed;
-
 	if (machine_is_shannon()) {
-		ret = gpio_request_one(SHANNON_GPIO_DISP_EN,
+		ret = devm_gpio_request_one(&pdev->dev, SHANNON_GPIO_DISP_EN,
 			GPIOF_OUT_INIT_LOW, "display enable");
 		if (ret)
 			goto failed;
 	}
 
+	/* Initialize video memory */
+	ret = sa1100fb_map_video_memory(fbi);
+	if (ret)
+		goto failed;
+
 	/*
 	 * This makes sure that our colour bitfield
 	 * descriptors are correctly initialised.
@@ -1268,7 +1268,7 @@ static int sa1100fb_probe(struct platform_device *pdev)
 
 	ret = register_framebuffer(&fbi->fb);
 	if (ret < 0)
-		goto err_reg_fb;
+		goto failed;
 
 #ifdef CONFIG_CPU_FREQ
 	fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
@@ -1280,9 +1280,6 @@ static int sa1100fb_probe(struct platform_device *pdev)
 	/* This driver cannot be unloaded at the moment */
 	return 0;
 
- err_reg_fb:
-	if (machine_is_shannon())
-		gpio_free(SHANNON_GPIO_DISP_EN);
  failed:
 	return ret;
 }
-- 
2.7.4

[PATCH 6/8] video: sa1100fb: clean up failure path

From: Russell King <hidden>
Date: 2017-09-29 10:51:22

We merely return from the failed path, so remove all the gotos and use
return statements instead.

Signed-off-by: Russell King <redacted>
---
 drivers/video/fbdev/sa1100fb.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index 7fa6c8f74ec6..16a974471c02 100644
--- a/drivers/video/fbdev/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -1222,41 +1222,36 @@ static int sa1100fb_probe(struct platform_device *pdev)
 		return -EINVAL;
 
 	fbi = sa1100fb_init_fbinfo(&pdev->dev);
-	ret = -ENOMEM;
 	if (!fbi)
-		goto failed;
+		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	fbi->base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(fbi->base)) {
-		ret = PTR_ERR(fbi->base);
-		goto failed;
-	}
+	if (IS_ERR(fbi->base))
+		return PTR_ERR(fbi->base);
 
 	fbi->clk = devm_clk_get(&pdev->dev, NULL);
-	if (IS_ERR(fbi->clk)) {
-		ret = PTR_ERR(fbi->clk);
-		goto failed;
-	}
+	if (IS_ERR(fbi->clk))
+		return PTR_ERR(fbi->clk);
 
 	ret = devm_request_irq(&pdev->dev, irq, sa1100fb_handle_irq, 0,
 			       "LCD", fbi);
 	if (ret) {
 		dev_err(&pdev->dev, "request_irq failed: %d\n", ret);
-		goto failed;
+		return ret;
 	}
 
 	if (machine_is_shannon()) {
 		ret = devm_gpio_request_one(&pdev->dev, SHANNON_GPIO_DISP_EN,
 			GPIOF_OUT_INIT_LOW, "display enable");
 		if (ret)
-			goto failed;
+			return ret;
 	}
 
 	/* Initialize video memory */
 	ret = sa1100fb_map_video_memory(fbi);
 	if (ret)
-		goto failed;
+		return ret;
 
 	/*
 	 * This makes sure that our colour bitfield
-- 
2.7.4

[PATCH 7/8] video: sa1100fb: fix video memory allocation leak

From: Russell King <hidden>
Date: 2017-09-29 10:51:28

Don't leak the video memory allocation if register_framebuffer() fails.

Signed-off-by: Russell King <redacted>
---
 drivers/video/fbdev/sa1100fb.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index 16a974471c02..56d514b5d252 100644
--- a/drivers/video/fbdev/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -1262,8 +1262,11 @@ static int sa1100fb_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, fbi);
 
 	ret = register_framebuffer(&fbi->fb);
-	if (ret < 0)
-		goto failed;
+	if (ret < 0) {
+		dma_free_wc(fbi->dev, fbi->map_size, fbi->map_cpu,
+			    fbi->map_dma);
+		return ret;
+	}
 
 #ifdef CONFIG_CPU_FREQ
 	fbi->freq_transition.notifier_call = sa1100fb_freq_transition;
@@ -1274,9 +1277,6 @@ static int sa1100fb_probe(struct platform_device *pdev)
 
 	/* This driver cannot be unloaded at the moment */
 	return 0;
-
- failed:
-	return ret;
 }
 
 static struct platform_driver sa1100fb_driver = {
-- 
2.7.4

[PATCH 8/8] video: sa1100fb: move pseudo palette into sa1100fb_info structure

From: Russell King <hidden>
Date: 2017-09-29 10:51:33

Move the pseudo palette inside the driver private data structure so we
don't have to play tricks to cater for it.

Signed-off-by: Russell King <redacted>
---
 drivers/video/fbdev/sa1100fb.c | 9 +++------
 drivers/video/fbdev/sa1100fb.h | 2 ++
 2 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/video/fbdev/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c
index 56d514b5d252..15ae50063296 100644
--- a/drivers/video/fbdev/sa1100fb.c
+++ b/drivers/video/fbdev/sa1100fb.c
@@ -323,13 +323,11 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
 		 * according to the RGB bitfield information.
 		 */
 		if (regno < 16) {
-			u32 *pal = fbi->fb.pseudo_palette;
-
 			val  = chan_to_field(red, &fbi->fb.var.red);
 			val |= chan_to_field(green, &fbi->fb.var.green);
 			val |= chan_to_field(blue, &fbi->fb.var.blue);
 
-			pal[regno] = val;
+			fbi->pseudo_palette[regno] = val;
 			ret = 0;
 		}
 		break;
@@ -1132,8 +1130,7 @@ static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev)
 	struct sa1100fb_info *fbi;
 	unsigned i;
 
-	fbi = devm_kzalloc(dev, sizeof(struct sa1100fb_info) + sizeof(u32) * 16,
-			   GFP_KERNEL);
+	fbi = devm_kzalloc(dev, sizeof(struct sa1100fb_info), GFP_KERNEL);
 	if (!fbi)
 		return NULL;
 
@@ -1158,7 +1155,7 @@ static struct sa1100fb_info *sa1100fb_init_fbinfo(struct device *dev)
 	fbi->fb.fbops		= &sa1100fb_ops;
 	fbi->fb.flags		= FBINFO_DEFAULT;
 	fbi->fb.monspecs	= monspecs;
-	fbi->fb.pseudo_palette	= (fbi + 1);
+	fbi->fb.pseudo_palette	= fbi->pseudo_palette;
 
 	fbi->rgb[RGB_4]		= &rgb_4;
 	fbi->rgb[RGB_8]		= &rgb_8;
diff --git a/drivers/video/fbdev/sa1100fb.h b/drivers/video/fbdev/sa1100fb.h
index 0139d13377a5..7a1a9ca33cec 100644
--- a/drivers/video/fbdev/sa1100fb.h
+++ b/drivers/video/fbdev/sa1100fb.h
@@ -69,6 +69,8 @@ struct sa1100fb_info {
 
 	const struct sa1100fb_mach_info *inf;
 	struct clk *clk;
+
+	u32 pseudo_palette[16];
 };
 
 #define TO_INF(ptr,member)	container_of(ptr,struct sa1100fb_info,member)
-- 
2.7.4

[PATCH 0/8] sa1100fb updates

From: Bartlomiej Zolnierkiewicz <hidden>
Date: 2017-10-17 13:32:30

On Friday, September 29, 2017 11:50:04 AM Russell King - ARM Linux wrote:
Hi Bart,
Hi Russell,
This series updates the sa1100fb fbdev driver's initialisation paths
to be more robust.  In doing these updates, I realised that we omitted
to free some memory which was allocated for the framebuffer if
initialisation fails - something that was hidden due to the complex
cleanup that the driver performs.  Switching to managed resources made
this more obvious.

Tested on H3600 iPAQ and Assabet.

 drivers/video/fbdev/sa1100fb.c | 75 +++++++++++++++---------------------------
 drivers/video/fbdev/sa1100fb.h |  2 ++
 2 files changed, 29 insertions(+), 48 deletions(-)
I queued all patches for 4.15, thanks!

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

[PATCH 0/8] sa1100fb updates

From: linux@armlinux.org.uk (Russell King - ARM Linux)
Date: 2017-11-27 17:11:45

On Tue, Oct 17, 2017 at 03:32:30PM +0200, Bartlomiej Zolnierkiewicz wrote:
On Friday, September 29, 2017 11:50:04 AM Russell King - ARM Linux wrote:
quoted
Hi Bart,
Hi Russell,
quoted
This series updates the sa1100fb fbdev driver's initialisation paths
to be more robust.  In doing these updates, I realised that we omitted
to free some memory which was allocated for the framebuffer if
initialisation fails - something that was hidden due to the complex
cleanup that the driver performs.  Switching to managed resources made
this more obvious.

Tested on H3600 iPAQ and Assabet.

 drivers/video/fbdev/sa1100fb.c | 75 +++++++++++++++---------------------------
 drivers/video/fbdev/sa1100fb.h |  2 ++
 2 files changed, 29 insertions(+), 48 deletions(-)
I queued all patches for 4.15, thanks!
Now that 4.15-rc1 is out, something tells me that was not actually
the case.  Any ideas what happened?

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up

[PATCH 0/8] sa1100fb updates

From: Bartlomiej Zolnierkiewicz <hidden>
Date: 2017-11-27 17:30:11

On Monday, November 27, 2017 05:11:45 PM Russell King - ARM Linux wrote:
On Tue, Oct 17, 2017 at 03:32:30PM +0200, Bartlomiej Zolnierkiewicz wrote:
quoted
On Friday, September 29, 2017 11:50:04 AM Russell King - ARM Linux wrote:
quoted
Hi Bart,
Hi Russell,
quoted
This series updates the sa1100fb fbdev driver's initialisation paths
to be more robust.  In doing these updates, I realised that we omitted
to free some memory which was allocated for the framebuffer if
initialisation fails - something that was hidden due to the complex
cleanup that the driver performs.  Switching to managed resources made
this more obvious.

Tested on H3600 iPAQ and Assabet.

 drivers/video/fbdev/sa1100fb.c | 75 +++++++++++++++---------------------------
 drivers/video/fbdev/sa1100fb.h |  2 ++
 2 files changed, 29 insertions(+), 48 deletions(-)
I queued all patches for 4.15, thanks!
Now that 4.15-rc1 is out, something tells me that was not actually
the case.  Any ideas what happened?
Could you please explain the issue that you are seeing a bit more?

For me it looks all fine:

$ git log --oneline v4.15-rc1 drivers/video/fbdev/sa1100fb.c
cb6bc3f video: sa1100fb: move pseudo palette into sa1100fb_info structure
0ab7658 video: sa1100fb: fix video memory allocation leak
c244f8e video: sa1100fb: clean up failure path
5634cba video: sa1100fb: use devm_gpio_request_one()
f6fc8c9 video: sa1100fb: use devm_request_irq()
df6b228 video: sa1100fb: use devm_ioremap_resource()
e43064c video: sa1100fb: use devm_clk_get()
ba1d36b video: sa1100fb: use devm_kzalloc()
...

Best regards,
--
Bartlomiej Zolnierkiewicz
Samsung R&D Institute Poland
Samsung Electronics

[PATCH 0/8] sa1100fb updates

From: linux@armlinux.org.uk (Russell King - ARM Linux)
Date: 2017-11-27 17:40:28

On Mon, Nov 27, 2017 at 06:30:11PM +0100, Bartlomiej Zolnierkiewicz wrote:
On Monday, November 27, 2017 05:11:45 PM Russell King - ARM Linux wrote:
quoted
On Tue, Oct 17, 2017 at 03:32:30PM +0200, Bartlomiej Zolnierkiewicz wrote:
quoted
On Friday, September 29, 2017 11:50:04 AM Russell King - ARM Linux wrote:
quoted
Hi Bart,
Hi Russell,
quoted
This series updates the sa1100fb fbdev driver's initialisation paths
to be more robust.  In doing these updates, I realised that we omitted
to free some memory which was allocated for the framebuffer if
initialisation fails - something that was hidden due to the complex
cleanup that the driver performs.  Switching to managed resources made
this more obvious.

Tested on H3600 iPAQ and Assabet.

 drivers/video/fbdev/sa1100fb.c | 75 +++++++++++++++---------------------------
 drivers/video/fbdev/sa1100fb.h |  2 ++
 2 files changed, 29 insertions(+), 48 deletions(-)
I queued all patches for 4.15, thanks!
Now that 4.15-rc1 is out, something tells me that was not actually
the case.  Any ideas what happened?
Could you please explain the issue that you are seeing a bit more?

For me it looks all fine:

$ git log --oneline v4.15-rc1 drivers/video/fbdev/sa1100fb.c
cb6bc3f video: sa1100fb: move pseudo palette into sa1100fb_info structure
0ab7658 video: sa1100fb: fix video memory allocation leak
c244f8e video: sa1100fb: clean up failure path
5634cba video: sa1100fb: use devm_gpio_request_one()
f6fc8c9 video: sa1100fb: use devm_request_irq()
df6b228 video: sa1100fb: use devm_ioremap_resource()
e43064c video: sa1100fb: use devm_clk_get()
ba1d36b video: sa1100fb: use devm_kzalloc()
...
Looks like I hadn't rebased that particular branch, so they were still
showing up in my origin.. git log.  Sorry about the false warning.

This is the problem of carrying close to 400 patches in separate
branches, and git log origin.. not able to show the commits that the
selection are based upon.

-- 
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help