* [PATCH RFC 3/3] ssb: add support for ssb over sdio
From: Albert Herranz @ 2009-09-07 18:47 UTC (permalink / raw)
To: bcm43xx-dev; +Cc: linux-wireless
[-- Attachment #1: Type: text/plain, Size: 12 bytes --]
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0118-ssb-add-support-for-ssb-over-sdio.patch --]
[-- Type: text/x-patch; name="0118-ssb-add-support-for-ssb-over-sdio.patch", Size: 28041 bytes --]
From c0f5e5002b69d5cc226a0c31d791bccefc2c92e3 Mon Sep 17 00:00:00 2001
From: Albert Herranz <albert_herranz@yahoo.es>
Date: Tue, 18 Aug 2009 21:39:06 +0200
Subject: [PATCH] ssb: add support for ssb over sdio
Add support for communicating with a Sonics Silicon Backplane through a
SDIO interface, as found in the Nintendo Wii WLAN daughter card.
The Nintendo Wii WLAN card includes a custom Broadcom 4318 chip with
a SDIO host interface.
Signed-off-by: Albert Herranz <albert_herranz@yahoo.es>
---
drivers/ssb/Kconfig | 14 +
drivers/ssb/Makefile | 1 +
drivers/ssb/main.c | 58 +++++-
drivers/ssb/scan.c | 11 +
drivers/ssb/sdio.c | 611 +++++++++++++++++++++++++++++++++++++++++++++
drivers/ssb/ssb_private.h | 40 +++
include/linux/ssb/ssb.h | 32 +++
7 files changed, 766 insertions(+), 1 deletions(-)
create mode 100644 drivers/ssb/sdio.c
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index 540a294..2d8cc45 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -66,6 +66,20 @@ config SSB_PCMCIAHOST
If unsure, say N
+config SSB_SDIOHOST_POSSIBLE
+ bool
+ depends on SSB && (MMC = y || MMC = SSB)
+ default y
+
+config SSB_SDIOHOST
+ bool "Support for SSB on SDIO-bus host"
+ depends on SSB_SDIOHOST_POSSIBLE
+ help
+ Support for a Sonics Silicon Backplane on top
+ of a SDIO device.
+
+ If unsure, say N
+
config SSB_SILENT
bool "No SSB kernel messages"
depends on SSB && EMBEDDED
diff --git a/drivers/ssb/Makefile b/drivers/ssb/Makefile
index cfbb74f..656e58b 100644
--- a/drivers/ssb/Makefile
+++ b/drivers/ssb/Makefile
@@ -6,6 +6,7 @@ ssb-$(CONFIG_SSB_SPROM) += sprom.o
# host support
ssb-$(CONFIG_SSB_PCIHOST) += pci.o pcihost_wrapper.o
ssb-$(CONFIG_SSB_PCMCIAHOST) += pcmcia.o
+ssb-$(CONFIG_SSB_SDIOHOST) += sdio.o
# built-in drivers
ssb-y += driver_chipcommon.o
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index 65a1ed9..cfbfd5b 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -17,6 +17,7 @@
#include <linux/ssb/ssb_driver_gige.h>
#include <linux/dma-mapping.h>
#include <linux/pci.h>
+#include <linux/mmc/sdio_func.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
@@ -88,6 +89,25 @@ found:
}
#endif /* CONFIG_SSB_PCMCIAHOST */
+#ifdef CONFIG_SSB_SDIOHOST
+struct ssb_bus *ssb_sdio_func_to_bus(struct sdio_func *func)
+{
+ struct ssb_bus *bus;
+
+ ssb_buses_lock();
+ list_for_each_entry(bus, &buses, list) {
+ if (bus->bustype == SSB_BUSTYPE_SDIO &&
+ bus->sdio_func == func)
+ goto found;
+ }
+ bus = NULL;
+found:
+ ssb_buses_unlock();
+
+ return bus;
+}
+#endif /* CONFIG_SSB_SDIOHOST */
+
int ssb_for_each_bus_call(unsigned long data,
int (*func)(struct ssb_bus *bus, unsigned long data))
{
@@ -469,6 +489,12 @@ static int ssb_devices_register(struct ssb_bus *bus)
dev->parent = &bus->host_pcmcia->dev;
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+#ifdef CONFIG_SSB_SDIO
+ sdev->irq = bus->sdio_func->dev.irq;
+ dev->parent = &bus->sdio_func->dev;
+#endif
+ break;
case SSB_BUSTYPE_SSB:
dev->dma_mask = &dev->coherent_dma_mask;
break;
@@ -724,12 +750,18 @@ static int ssb_bus_register(struct ssb_bus *bus,
err = ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 1);
if (err)
goto out;
+
+ /* Init SDIO-host device (if any), before the scan */
+ err = ssb_sdio_init(bus);
+ if (err)
+ goto err_disable_xtal;
+
ssb_buses_lock();
bus->busnumber = next_busnumber;
/* Scan for devices (cores) */
err = ssb_bus_scan(bus, baseaddr);
if (err)
- goto err_disable_xtal;
+ goto err_sdio_exit;
/* Init PCI-host device (if any) */
err = ssb_pci_init(bus);
@@ -776,6 +808,8 @@ err_pci_exit:
ssb_pci_exit(bus);
err_unmap:
ssb_iounmap(bus);
+err_sdio_exit:
+ ssb_sdio_exit(bus);
err_disable_xtal:
ssb_buses_unlock();
ssb_pci_xtal(bus, SSB_GPIO_XTAL | SSB_GPIO_PLL, 0);
@@ -825,6 +859,28 @@ int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
EXPORT_SYMBOL(ssb_bus_pcmciabus_register);
#endif /* CONFIG_SSB_PCMCIAHOST */
+#ifdef CONFIG_SSB_SDIOHOST
+int ssb_bus_sdiobus_register(struct ssb_bus *bus, struct sdio_func *func,
+ unsigned int quirks)
+{
+ int err;
+
+ bus->bustype = SSB_BUSTYPE_SDIO;
+ bus->sdio_func = func;
+ bus->ops = &ssb_sdio_ops;
+ bus->quirks = quirks;
+
+ err = ssb_bus_register(bus, ssb_sdio_get_invariants, ~0);
+ if (!err) {
+ ssb_printk(KERN_INFO PFX "Sonics Silicon Backplane found on "
+ "SDIO device %s\n", sdio_func_id(func));
+ }
+
+ return err;
+}
+EXPORT_SYMBOL(ssb_bus_sdiobus_register);
+#endif /* CONFIG_SSB_PCMCIAHOST */
+
int ssb_bus_ssbbus_register(struct ssb_bus *bus,
unsigned long baseaddr,
ssb_invariants_func_t get_invariants)
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c
index 63ee5cf..b74212d 100644
--- a/drivers/ssb/scan.c
+++ b/drivers/ssb/scan.c
@@ -175,6 +175,9 @@ static u32 scan_read32(struct ssb_bus *bus, u8 current_coreidx,
} else
ssb_pcmcia_switch_segment(bus, 0);
break;
+ case SSB_BUSTYPE_SDIO:
+ offset += current_coreidx * SSB_CORE_SIZE;
+ return ssb_sdio_scan_read32(bus, offset);
}
return readl(bus->mmio + offset);
}
@@ -188,6 +191,8 @@ static int scan_switchcore(struct ssb_bus *bus, u8 coreidx)
return ssb_pci_switch_coreidx(bus, coreidx);
case SSB_BUSTYPE_PCMCIA:
return ssb_pcmcia_switch_coreidx(bus, coreidx);
+ case SSB_BUSTYPE_SDIO:
+ return ssb_sdio_scan_switch_coreidx(bus, coreidx);
}
return 0;
}
@@ -206,6 +211,8 @@ void ssb_iounmap(struct ssb_bus *bus)
SSB_BUG_ON(1); /* Can't reach this code. */
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ break;
}
bus->mmio = NULL;
bus->mapped_device = NULL;
@@ -230,6 +237,10 @@ static void __iomem *ssb_ioremap(struct ssb_bus *bus,
SSB_BUG_ON(1); /* Can't reach this code. */
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ /* Nothing to ioremap in the SDIO case, just fake it */
+ mmio = (void __iomem *)baseaddr;
+ break;
}
return mmio;
diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c
new file mode 100644
index 0000000..0c01c94
--- /dev/null
+++ b/drivers/ssb/sdio.c
@@ -0,0 +1,611 @@
+/*
+ * Sonics Silicon Backplane
+ * SDIO-Hostbus related functions
+ *
+ * Copyright 2009 Albert Herranz <albert_herranz@yahoo.es>
+ *
+ * Based on drivers/ssb/pcmcia.c
+ * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2007-2008 Michael Buesch <mb@bu3sch.de>
+ *
+ * Licensed under the GNU/GPL. See COPYING for details.
+ *
+ */
+
+#define pr_fmt(fmt) "ssb-sdio: " fmt
+
+#include <linux/ssb/ssb.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/etherdevice.h>
+#include <linux/mmc/sdio_func.h>
+
+#include "ssb_private.h"
+
+/* Define the following to 1 to enable a printk on each coreswitch. */
+#define SSB_VERBOSE_SDIOCORESWITCH_DEBUG 1
+
+
+/* Hardware invariants CIS tuples */
+#define SSB_SDIO_CIS 0x80
+#define SSB_SDIO_CIS_SROMREV 0x00
+#define SSB_SDIO_CIS_ID 0x01
+#define SSB_SDIO_CIS_BOARDREV 0x02
+#define SSB_SDIO_CIS_PA 0x03
+#define SSB_SDIO_CIS_PA_PA0B0_LO 0
+#define SSB_SDIO_CIS_PA_PA0B0_HI 1
+#define SSB_SDIO_CIS_PA_PA0B1_LO 2
+#define SSB_SDIO_CIS_PA_PA0B1_HI 3
+#define SSB_SDIO_CIS_PA_PA0B2_LO 4
+#define SSB_SDIO_CIS_PA_PA0B2_HI 5
+#define SSB_SDIO_CIS_PA_ITSSI 6
+#define SSB_SDIO_CIS_PA_MAXPOW 7
+#define SSB_SDIO_CIS_OEMNAME 0x04
+#define SSB_SDIO_CIS_CCODE 0x05
+#define SSB_SDIO_CIS_ANTENNA 0x06
+#define SSB_SDIO_CIS_ANTGAIN 0x07
+#define SSB_SDIO_CIS_BFLAGS 0x08
+#define SSB_SDIO_CIS_LEDS 0x09
+
+#define CISTPL_FUNCE_LAN_NODE_ID 0x04 /* same as in PCMCIA */
+
+
+/*
+ * Function 1 miscellaneous registers.
+ *
+ * Definitions match src/include/sbsdio.h from the
+ * Android Open Source Project
+ * http://android.git.kernel.org/?p=platform/system/wlan/broadcom.git
+ *
+ */
+#define SBSDIO_FUNC1_SBADDRLOW 0x1000a /* SB Address window Low (b15) */
+#define SBSDIO_FUNC1_SBADDRMID 0x1000b /* SB Address window Mid (b23-b16) */
+#define SBSDIO_FUNC1_SBADDRHIGH 0x1000c /* SB Address window High (b24-b31) */
+
+/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */
+#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid address bits in SBADDRLOW */
+#define SBSDIO_SBADDRMID_MASK 0xff /* Valid address bits in SBADDRMID */
+#define SBSDIO_SBADDRHIGH_MASK 0xff /* Valid address bits in SBADDRHIGH */
+
+#define SBSDIO_SB_OFT_ADDR_MASK 0x7FFF /* sb offset addr is <= 15 bits, 32k */
+
+/* REVISIT: this flag doesn't seem to matter */
+#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x8000 /* forces 32-bit SB access */
+
+
+/*
+ * Address map within the SDIO function address space (128K).
+ *
+ * Start End Description
+ * ------- ------- ------------------------------------------
+ * 0x00000 0x0ffff selected backplane address window (64K)
+ * 0x10000 0x1ffff backplane control registers (max 64K)
+ *
+ * The current address window is configured by writing to registers
+ * SBADDRLOW, SBADDRMID and SBADDRHIGH.
+ *
+ * In order to access the contents of a 32-bit Silicon Backplane address
+ * the backplane address window must be first loaded with the highest
+ * 16 bits of the target address. Then, an access must be done to the
+ * SDIO function address space using the lower 15 bits of the address.
+ * Bit 15 of the address must be set when doing 32 bit accesses.
+ *
+ * 10987654321098765432109876543210
+ * WWWWWWWWWWWWWWWWW SB Address Window
+ * OOOOOOOOOOOOOOOO Offset within SB Address Window
+ * a 32-bit access flag
+ */
+
+
+/*
+ * SSB I/O via SDIO.
+ *
+ * NOTE: SDIO address @addr is 17 bits long (SDIO address space is 128K).
+ */
+
+static struct device *ssb_sdio_dev(struct ssb_bus *bus)
+{
+ return &bus->sdio_func->dev;
+}
+
+/* host claimed */
+static int ssb_sdio_writeb(struct ssb_bus *bus, unsigned int addr, u8 val)
+{
+ int error = 0;
+
+ sdio_writeb(bus->sdio_func, val, addr, &error);
+ if (unlikely(error))
+ dev_dbg(ssb_sdio_dev(bus), "%08X <- %02x, error %d\n",
+ addr, val, error);
+ return error;
+}
+
+#if 0
+static u8 ssb_sdio_readb(struct ssb_bus *bus, unsigned int addr)
+{
+ u8 val;
+ int error = 0;
+
+ val = sdio_readb(bus->sdio_func, addr, &error);
+ if (unlikely(error))
+ dev_dbg(ssb_sdio_dev(bus), "%08X -> %02x, error %d\n",
+ addr, val, error);
+ return val;
+}
+#endif
+
+/* host claimed */
+static int ssb_sdio_set_sbaddr_window(struct ssb_bus *bus, u32 address)
+{
+ int error;
+
+ error = ssb_sdio_writeb(bus, SBSDIO_FUNC1_SBADDRLOW,
+ (address >> 8) & SBSDIO_SBADDRLOW_MASK);
+ if (error)
+ goto out;
+ error = ssb_sdio_writeb(bus, SBSDIO_FUNC1_SBADDRMID,
+ (address >> 16) & SBSDIO_SBADDRMID_MASK);
+ if (error)
+ goto out;
+ error = ssb_sdio_writeb(bus, SBSDIO_FUNC1_SBADDRHIGH,
+ (address >> 24) & SBSDIO_SBADDRHIGH_MASK);
+ if (error)
+ goto out;
+ bus->sbaddr = address;
+out:
+ if (error)
+ dev_dbg(ssb_sdio_dev(bus), "failed to set address window"
+ " to 0x%08x, error %d\n", address, error);
+ return error;
+}
+
+/* for enumeration use only */
+u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset)
+{
+ u32 val;
+ int error;
+
+ sdio_claim_host(bus->sdio_func);
+ val = sdio_readl(bus->sdio_func, offset, &error);
+ sdio_release_host(bus->sdio_func);
+ if (unlikely(error))
+ dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %08x, error %d\n",
+ bus->sbaddr >> 16, offset, val, error);
+ return val;
+}
+
+/* for enumeration use only */
+int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
+{
+ u32 sbaddr;
+ int error;
+
+ sbaddr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
+ sdio_claim_host(bus->sdio_func);
+ error = ssb_sdio_set_sbaddr_window(bus, sbaddr);
+ sdio_release_host(bus->sdio_func);
+ if (error) {
+ dev_err(ssb_sdio_dev(bus), "failed to switch to core %u,"
+ " error %d\n", coreidx, error);
+ goto out;
+ }
+out:
+ return error;
+}
+
+/* host must be already claimed */
+int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev)
+{
+ u8 coreidx = dev->core_index;
+ u32 sbaddr;
+ int error = 0;
+
+ sbaddr = (coreidx * SSB_CORE_SIZE) + SSB_ENUM_BASE;
+ if (unlikely(bus->sbaddr != sbaddr)) {
+#if SSB_VERBOSE_SDIOCORESWITCH_DEBUG
+ dev_info(ssb_sdio_dev(bus),
+ "switching to %s core, index %d\n",
+ ssb_core_name(dev->id.coreid), coreidx);
+#endif
+ error = ssb_sdio_set_sbaddr_window(bus, sbaddr);
+ if (error) {
+ dev_dbg(ssb_sdio_dev(bus), "failed to switch to"
+ " core %u, error %d\n", coreidx, error);
+ goto out;
+ }
+ bus->mapped_device = dev;
+ }
+
+out:
+ return error;
+}
+
+static u8 ssb_sdio_read8(struct ssb_device *dev, u16 offset)
+{
+ struct ssb_bus *bus = dev->bus;
+ u8 val = 0xff;
+ int error = 0;
+
+ sdio_claim_host(bus->sdio_func);
+ if (unlikely(ssb_sdio_switch_core(bus, dev)))
+ goto out;
+ offset |= bus->sbaddr & 0xffff;
+ offset &= SBSDIO_SB_OFT_ADDR_MASK;
+ val = sdio_readb(bus->sdio_func, offset, &error);
+ if (error) {
+ dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %02x, error %d\n",
+ bus->sbaddr >> 16, offset, val, error);
+ }
+out:
+ sdio_release_host(bus->sdio_func);
+ return val;
+}
+
+static u16 ssb_sdio_read16(struct ssb_device *dev, u16 offset)
+{
+ struct ssb_bus *bus = dev->bus;
+ u16 val = 0xffff;
+ int error = 0;
+
+ sdio_claim_host(bus->sdio_func);
+ if (unlikely(ssb_sdio_switch_core(bus, dev)))
+ goto out;
+ offset |= bus->sbaddr & 0xffff;
+ offset &= SBSDIO_SB_OFT_ADDR_MASK;
+ val = sdio_readw(bus->sdio_func, offset, &error);
+ if (error) {
+ dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %04x, error %d\n",
+ bus->sbaddr >> 16, offset, val, error);
+ }
+out:
+ sdio_release_host(bus->sdio_func);
+ return val;
+}
+
+static u32 ssb_sdio_read32(struct ssb_device *dev, u16 offset)
+{
+ struct ssb_bus *bus = dev->bus;
+ u32 val = 0xffffffff;
+ int error = 0;
+
+ sdio_claim_host(bus->sdio_func);
+ if (unlikely(ssb_sdio_switch_core(bus, dev)))
+ goto out;
+ offset |= bus->sbaddr & 0xffff;
+ offset &= SBSDIO_SB_OFT_ADDR_MASK;
+ offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */
+ val = sdio_readl(bus->sdio_func, offset, &error);
+ if (error) {
+ dev_dbg(ssb_sdio_dev(bus), "%04X:%04X > %08x, error %d\n",
+ bus->sbaddr >> 16, offset, val, error);
+ }
+out:
+ sdio_release_host(bus->sdio_func);
+ return val;
+}
+
+#ifdef CONFIG_SSB_BLOCKIO
+static void ssb_sdio_block_read(struct ssb_device *dev, void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ size_t saved_count = count;
+ struct ssb_bus *bus = dev->bus;
+ int error = 0;
+
+ sdio_claim_host(bus->sdio_func);
+ if (unlikely(ssb_sdio_switch_core(bus, dev))) {
+ error = -EIO;
+ memset(buffer, 0xff, count);
+ goto err_out;
+ }
+ offset |= bus->sbaddr & 0xffff;
+ offset &= SBSDIO_SB_OFT_ADDR_MASK;
+
+ switch (reg_width) {
+ case sizeof(u8): {
+ /* REVISIT: untested code path */
+ error = sdio_readsb(bus->sdio_func, buffer, offset, count);
+ break;
+ }
+ case sizeof(u16): {
+ /* REVISIT: untested code path */
+ SSB_WARN_ON(count & 1);
+ error = sdio_readsb(bus->sdio_func, buffer, offset, count);
+ break;
+ }
+ case sizeof(u32): {
+ SSB_WARN_ON(count & 3);
+ offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */
+ error = sdio_readsb(bus->sdio_func, buffer, offset, count);
+ break;
+ }
+ default:
+ SSB_WARN_ON(1);
+ }
+ if (!error)
+ goto out;
+
+err_out:
+ dev_dbg(ssb_sdio_dev(bus), "%04X:%04X (width=%u, len=%u), error %d\n",
+ bus->sbaddr >> 16, offset, reg_width, saved_count, error);
+out:
+ sdio_release_host(bus->sdio_func);
+}
+#endif /* CONFIG_SSB_BLOCKIO */
+
+static void ssb_sdio_write8(struct ssb_device *dev, u16 offset, u8 val)
+{
+ struct ssb_bus *bus = dev->bus;
+ int error = 0;
+
+ sdio_claim_host(bus->sdio_func);
+ if (unlikely(ssb_sdio_switch_core(bus, dev)))
+ goto out;
+ offset |= bus->sbaddr & 0xffff;
+ offset &= SBSDIO_SB_OFT_ADDR_MASK;
+ sdio_writeb(bus->sdio_func, val, offset, &error);
+ if (error) {
+ dev_dbg(ssb_sdio_dev(bus), "%04X:%04X < %02x, error %d\n",
+ bus->sbaddr >> 16, offset, val, error);
+ }
+out:
+ sdio_release_host(bus->sdio_func);
+}
+
+static void ssb_sdio_write16(struct ssb_device *dev, u16 offset, u16 val)
+{
+ struct ssb_bus *bus = dev->bus;
+ int error = 0;
+
+ sdio_claim_host(bus->sdio_func);
+ if (unlikely(ssb_sdio_switch_core(bus, dev)))
+ goto out;
+ offset |= bus->sbaddr & 0xffff;
+ offset &= SBSDIO_SB_OFT_ADDR_MASK;
+ sdio_writew(bus->sdio_func, val, offset, &error);
+ if (error) {
+ dev_dbg(ssb_sdio_dev(bus), "%04X:%04X < %04x, error %d\n",
+ bus->sbaddr >> 16, offset, val, error);
+ }
+out:
+ sdio_release_host(bus->sdio_func);
+}
+
+static void ssb_sdio_write32(struct ssb_device *dev, u16 offset, u32 val)
+{
+ struct ssb_bus *bus = dev->bus;
+ int error = 0;
+
+ sdio_claim_host(bus->sdio_func);
+ if (unlikely(ssb_sdio_switch_core(bus, dev)))
+ goto out;
+ offset |= bus->sbaddr & 0xffff;
+ offset &= SBSDIO_SB_OFT_ADDR_MASK;
+ offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */
+ sdio_writel(bus->sdio_func, val, offset, &error);
+ if (error) {
+ dev_dbg(ssb_sdio_dev(bus), "%04X:%04X < %08x, error %d\n",
+ bus->sbaddr >> 16, offset, val, error);
+ }
+ if (bus->quirks & SSB_QUIRK_SDIO_READ_AFTER_WRITE32) {
+ /*
+ * The Nintendo Wii WLAN card needs a dummy read after each
+ * write, otherwise we get garbage on subsequent reads.
+ */
+ sdio_readl(bus->sdio_func, 0, &error);
+ }
+out:
+ sdio_release_host(bus->sdio_func);
+}
+
+#ifdef CONFIG_SSB_BLOCKIO
+static void ssb_sdio_block_write(struct ssb_device *dev, const void *buffer,
+ size_t count, u16 offset, u8 reg_width)
+{
+ size_t saved_count = count;
+ struct ssb_bus *bus = dev->bus;
+ int error = 0;
+
+ sdio_claim_host(bus->sdio_func);
+ if (unlikely(ssb_sdio_switch_core(bus, dev))) {
+ error = -EIO;
+ memset((void *)buffer, 0xff, count);
+ goto err_out;
+ }
+ offset |= bus->sbaddr & 0xffff;
+ offset &= SBSDIO_SB_OFT_ADDR_MASK;
+
+ switch (reg_width) {
+ case sizeof(u8):
+ /* REVISIT: untested code path */
+ error = sdio_writesb(bus->sdio_func, offset,
+ (void *)buffer, count);
+ break;
+ case sizeof(u16):
+ /* REVISIT: untested code path */
+ SSB_WARN_ON(count & 1);
+ error = sdio_writesb(bus->sdio_func, offset,
+ (void *)buffer, count);
+ break;
+ case sizeof(u32):
+ SSB_WARN_ON(count & 3);
+ offset |= SBSDIO_SB_ACCESS_2_4B_FLAG; /* 32 bit data access */
+ error = sdio_writesb(bus->sdio_func, offset,
+ (void *)buffer, count);
+ break;
+ default:
+ SSB_WARN_ON(1);
+ }
+ if (!error)
+ goto out;
+
+err_out:
+ dev_dbg(ssb_sdio_dev(bus), "%04X:%04X (width=%u, len=%u), error %d\n",
+ bus->sbaddr >> 16, offset, reg_width, saved_count, error);
+out:
+ sdio_release_host(bus->sdio_func);
+}
+
+#endif /* CONFIG_SSB_BLOCKIO */
+
+/* Not "static", as it's used in main.c */
+const struct ssb_bus_ops ssb_sdio_ops = {
+ .read8 = ssb_sdio_read8,
+ .read16 = ssb_sdio_read16,
+ .read32 = ssb_sdio_read32,
+ .write8 = ssb_sdio_write8,
+ .write16 = ssb_sdio_write16,
+ .write32 = ssb_sdio_write32,
+#ifdef CONFIG_SSB_BLOCKIO
+ .block_read = ssb_sdio_block_read,
+ .block_write = ssb_sdio_block_write,
+#endif
+};
+
+#define GOTO_ERROR_ON(condition, description) do { \
+ if (unlikely(condition)) { \
+ error_description = description; \
+ goto error; \
+ } \
+ } while (0)
+
+int ssb_sdio_get_invariants(struct ssb_bus *bus,
+ struct ssb_init_invariants *iv)
+{
+ struct ssb_sprom *sprom = &iv->sprom;
+ struct ssb_boardinfo *bi = &iv->boardinfo;
+ const char *error_description = "none";
+ struct sdio_func_tuple *tuple;
+ void *mac;
+
+ memset(sprom, 0xFF, sizeof(*sprom));
+ sprom->boardflags_lo = 0;
+ sprom->boardflags_hi = 0;
+
+ tuple = bus->sdio_func->tuples;
+ while (tuple) {
+ switch (tuple->code) {
+ case 0x22: /* extended function */
+ switch (tuple->data[0]) {
+ case CISTPL_FUNCE_LAN_NODE_ID:
+ GOTO_ERROR_ON((tuple->size != 7) &&
+ (tuple->data[1] != 6),
+ "mac tpl size");
+ /* fetch the MAC address. */
+ mac = tuple->data + 2;
+ memcpy(sprom->il0mac, mac, ETH_ALEN);
+ memcpy(sprom->et1mac, mac, ETH_ALEN);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 0x80: /* vendor specific tuple */
+ switch (tuple->data[0]) {
+ case SSB_SDIO_CIS_SROMREV:
+ GOTO_ERROR_ON(tuple->size != 2,
+ "sromrev tpl size");
+ sprom->revision = tuple->data[1];
+ break;
+ case SSB_SDIO_CIS_ID:
+ GOTO_ERROR_ON((tuple->size != 5) &&
+ (tuple->size != 7),
+ "id tpl size");
+ bi->vendor = tuple->data[1] |
+ (tuple->data[2]<<8);
+ break;
+ case SSB_SDIO_CIS_BOARDREV:
+ GOTO_ERROR_ON(tuple->size != 2,
+ "boardrev tpl size");
+ sprom->board_rev = tuple->data[1];
+ break;
+ case SSB_SDIO_CIS_PA:
+ GOTO_ERROR_ON((tuple->size != 9) &&
+ (tuple->size != 10),
+ "pa tpl size");
+ sprom->pa0b0 = tuple->data[1] |
+ ((u16)tuple->data[2] << 8);
+ sprom->pa0b1 = tuple->data[3] |
+ ((u16)tuple->data[4] << 8);
+ sprom->pa0b2 = tuple->data[5] |
+ ((u16)tuple->data[6] << 8);
+ sprom->itssi_a = tuple->data[7];
+ sprom->itssi_bg = tuple->data[7];
+ sprom->maxpwr_a = tuple->data[8];
+ sprom->maxpwr_bg = tuple->data[8];
+ break;
+ case SSB_SDIO_CIS_OEMNAME:
+ /* Not present */
+ break;
+ case SSB_SDIO_CIS_CCODE:
+ GOTO_ERROR_ON(tuple->size != 2,
+ "ccode tpl size");
+ sprom->country_code = tuple->data[1];
+ break;
+ case SSB_SDIO_CIS_ANTENNA:
+ GOTO_ERROR_ON(tuple->size != 2,
+ "ant tpl size");
+ sprom->ant_available_a = tuple->data[1];
+ sprom->ant_available_bg = tuple->data[1];
+ break;
+ case SSB_SDIO_CIS_ANTGAIN:
+ GOTO_ERROR_ON(tuple->size != 2,
+ "antg tpl size");
+ sprom->antenna_gain.ghz24.a0 = tuple->data[1];
+ sprom->antenna_gain.ghz24.a1 = tuple->data[1];
+ sprom->antenna_gain.ghz24.a2 = tuple->data[1];
+ sprom->antenna_gain.ghz24.a3 = tuple->data[1];
+ sprom->antenna_gain.ghz5.a0 = tuple->data[1];
+ sprom->antenna_gain.ghz5.a1 = tuple->data[1];
+ sprom->antenna_gain.ghz5.a2 = tuple->data[1];
+ sprom->antenna_gain.ghz5.a3 = tuple->data[1];
+ break;
+ case SSB_SDIO_CIS_BFLAGS:
+ GOTO_ERROR_ON((tuple->size != 3) &&
+ (tuple->size != 5),
+ "bfl tpl size");
+ sprom->boardflags_lo = tuple->data[1] |
+ ((u16)tuple->data[2] << 8);
+ break;
+ case SSB_SDIO_CIS_LEDS:
+ GOTO_ERROR_ON(tuple->size != 5,
+ "leds tpl size");
+ sprom->gpio0 = tuple->data[1];
+ sprom->gpio1 = tuple->data[2];
+ sprom->gpio2 = tuple->data[3];
+ sprom->gpio3 = tuple->data[4];
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ tuple = tuple->next;
+ }
+
+ return 0;
+error:
+ dev_err(ssb_sdio_dev(bus), "failed to fetch device invariants: %s\n",
+ error_description);
+ return -ENODEV;
+}
+
+void ssb_sdio_exit(struct ssb_bus *bus)
+{
+ if (bus->bustype != SSB_BUSTYPE_SDIO)
+ return;
+}
+
+int ssb_sdio_init(struct ssb_bus *bus)
+{
+ if (bus->bustype != SSB_BUSTYPE_SDIO)
+ goto out;
+
+ bus->sbaddr = ~0;
+ bus->sprom_size = 0;
+
+out:
+ return 0;
+}
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h
index 57fa482..2543356 100644
--- a/drivers/ssb/ssb_private.h
+++ b/drivers/ssb/ssb_private.h
@@ -114,6 +114,46 @@ static inline int ssb_pcmcia_init(struct ssb_bus *bus)
}
#endif /* CONFIG_SSB_PCMCIAHOST */
+/* sdio.c */
+#ifdef CONFIG_SSB_SDIOHOST
+extern int ssb_sdio_get_invariants(struct ssb_bus *bus,
+ struct ssb_init_invariants *iv);
+
+extern u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset);
+extern int ssb_sdio_switch_core(struct ssb_bus *bus, struct ssb_device *dev);
+extern int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx);
+extern int ssb_sdio_hardware_setup(struct ssb_bus *bus);
+extern void ssb_sdio_exit(struct ssb_bus *bus);
+extern int ssb_sdio_init(struct ssb_bus *bus);
+
+extern const struct ssb_bus_ops ssb_sdio_ops;
+#else /* CONFIG_SSB_SDIOHOST */
+static inline u32 ssb_sdio_scan_read32(struct ssb_bus *bus, u16 offset)
+{
+ return 0;
+}
+static inline int ssb_sdio_switch_core(struct ssb_bus *bus,
+ struct ssb_device *dev)
+{
+ return 0;
+}
+static inline int ssb_sdio_scan_switch_coreidx(struct ssb_bus *bus, u8 coreidx)
+{
+ return 0;
+}
+static inline int ssb_sdio_hardware_setup(struct ssb_bus *bus)
+{
+ return 0;
+}
+static inline void ssb_sdio_exit(struct ssb_bus *bus)
+{
+}
+static inline int ssb_sdio_init(struct ssb_bus *bus)
+{
+ return 0;
+}
+#endif /* CONFIG_SSB_SDIOHOST */
+
/* scan.c */
extern const char *ssb_core_name(u16 coreid);
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h
index 17ffc1f..771da21 100644
--- a/include/linux/ssb/ssb.h
+++ b/include/linux/ssb/ssb.h
@@ -238,6 +238,7 @@ enum ssb_bustype {
SSB_BUSTYPE_SSB, /* This SSB bus is the system bus */
SSB_BUSTYPE_PCI, /* SSB is connected to PCI bus */
SSB_BUSTYPE_PCMCIA, /* SSB is connected to PCMCIA bus */
+ SSB_BUSTYPE_SDIO, /* SSB is connected to SDIO bus */
};
/* board_vendor */
@@ -283,6 +284,17 @@ struct ssb_bus {
/* Pointer to the PCMCIA device (only if bustype == SSB_BUSTYPE_PCMCIA). */
struct pcmcia_device *host_pcmcia;
+ unsigned int quirks;
+
+/* card requires performing a read after writing a 32-bit value */
+#define SSB_QUIRK_SDIO_READ_AFTER_WRITE32 (1<<0)
+
+ /* Pointer to the SDIO device (only if bustype == SSB_BUSTYPE_SDIO). */
+ struct sdio_func *sdio_func;
+
+ /* Current SSB base address window for SDIO. */
+ u32 sbaddr;
+
#ifdef CONFIG_SSB_SPROM
/* Mutex to protect the SPROM writing. */
struct mutex sprom_mutex;
@@ -366,6 +378,12 @@ extern int ssb_bus_pcmciabus_register(struct ssb_bus *bus,
struct pcmcia_device *pcmcia_dev,
unsigned long baseaddr);
#endif /* CONFIG_SSB_PCMCIAHOST */
+#ifdef CONFIG_SSB_SDIOHOST
+extern int ssb_bus_sdiobus_register(struct ssb_bus *bus,
+ struct sdio_func *sdio_func,
+ unsigned int quirks);
+#endif /* CONFIG_SSB_SDIOHOST */
+
extern void ssb_bus_unregister(struct ssb_bus *bus);
@@ -465,6 +483,8 @@ static inline int ssb_dma_mapping_error(struct ssb_device *dev, dma_addr_t addr)
return pci_dma_mapping_error(dev->bus->host_pci, addr);
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ /* FALL THROUGH */
case SSB_BUSTYPE_SSB:
return dma_mapping_error(dev->dev, addr);
default:
@@ -483,6 +503,8 @@ static inline dma_addr_t ssb_dma_map_single(struct ssb_device *dev, void *p,
return pci_map_single(dev->bus->host_pci, p, size, dir);
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ /* FALL THROUGH */
case SSB_BUSTYPE_SSB:
return dma_map_single(dev->dev, p, size, dir);
default:
@@ -502,6 +524,8 @@ static inline void ssb_dma_unmap_single(struct ssb_device *dev, dma_addr_t dma_a
return;
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ /* FALL THROUGH */
case SSB_BUSTYPE_SSB:
dma_unmap_single(dev->dev, dma_addr, size, dir);
return;
@@ -524,6 +548,8 @@ static inline void ssb_dma_sync_single_for_cpu(struct ssb_device *dev,
return;
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ /* FALL THROUGH */
case SSB_BUSTYPE_SSB:
dma_sync_single_for_cpu(dev->dev, dma_addr, size, dir);
return;
@@ -546,6 +572,8 @@ static inline void ssb_dma_sync_single_for_device(struct ssb_device *dev,
return;
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ /* FALL THROUGH */
case SSB_BUSTYPE_SSB:
dma_sync_single_for_device(dev->dev, dma_addr, size, dir);
return;
@@ -570,6 +598,8 @@ static inline void ssb_dma_sync_single_range_for_cpu(struct ssb_device *dev,
return;
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ /* FALL THROUGH */
case SSB_BUSTYPE_SSB:
dma_sync_single_range_for_cpu(dev->dev, dma_addr, offset,
size, dir);
@@ -595,6 +625,8 @@ static inline void ssb_dma_sync_single_range_for_device(struct ssb_device *dev,
return;
#endif
break;
+ case SSB_BUSTYPE_SDIO:
+ /* FALL THROUGH */
case SSB_BUSTYPE_SSB:
dma_sync_single_range_for_device(dev->dev, dma_addr, offset,
size, dir);
--
1.6.0.4
^ permalink raw reply related
* Re: [PATCH RFC 1/3] sdio: recognize io card without powercycle
From: Michael Buesch @ 2009-09-07 18:55 UTC (permalink / raw)
To: Albert Herranz; +Cc: bcm43xx-dev, linux-mmc, linux-wireless
In-Reply-To: <369914.76148.qm@web28315.mail.ukl.yahoo.com>
On Monday 07 September 2009 20:46:58 Albert Herranz wrote:
>
>
Please submit this to the SDIO maintainer.
--
Greetings, Michael.
^ permalink raw reply
* Re: [PATCH RFC 2/3] sdio: pass unknown cis tuples to sdio drivers
From: Michael Buesch @ 2009-09-07 18:55 UTC (permalink / raw)
To: Albert Herranz; +Cc: bcm43xx-dev, linux-mmc, linux-wireless
In-Reply-To: <80555.93921.qm@web28308.mail.ukl.yahoo.com>
On Monday 07 September 2009 20:47:12 Albert Herranz wrote:
>
>
Please also submit to the SDIO maintainer.
--
Greetings, Michael.
^ permalink raw reply
* Re: [PATCH RFC 3/3] ssb: add support for ssb over sdio
From: Michael Buesch @ 2009-09-07 18:57 UTC (permalink / raw)
To: Albert Herranz; +Cc: bcm43xx-dev, linux-wireless
In-Reply-To: <143541.29987.qm@web28309.mail.ukl.yahoo.com>
On Monday 07 September 2009 20:47:27 Albert Herranz wrote:
>
>
(next time please inline the patch)
Thanks a lot for the patch. I'll do more cleanups on it and submit it to john later.
--
Greetings, Michael.
^ permalink raw reply
* Re: [PATCH RFC 1/3] sdio: recognize io card without powercycle
From: Michael Buesch @ 2009-09-07 19:05 UTC (permalink / raw)
To: Chris Ball; +Cc: Albert Herranz, bcm43xx-dev, linux-mmc, linux-wireless
In-Reply-To: <m3hbvey40u.fsf@pullcord.laptop.org>
On Monday 07 September 2009 20:59:45 Chris Ball wrote:
> Hi Michael,
>
> > Please submit this to the SDIO maintainer.
>
> MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
> S: Orphan
> L: linux-mmc@vger.kernel.org
> F: drivers/mmc/
> F: include/linux/mmc/
>
> So, these patches are in the right place.
So who is going to pick it up? Just sending them to a random list is not
going to magically merge them into the kernel.
--
Greetings, Michael.
^ permalink raw reply
* Re: [PATCH RFC 1/3] sdio: recognize io card without powercycle
From: Ehud Gavron @ 2009-09-07 19:10 UTC (permalink / raw)
To: Michael Buesch
Cc: Chris Ball, linux-wireless, Albert Herranz, linux-mmc,
bcm43xx-dev
In-Reply-To: <200909072105.31439.mb@bu3sch.de>
Michael Buesch wrote:
> On Monday 07 September 2009 20:59:45 Chris Ball wrote:
>
>> Hi Michael,
>>
>> > Please submit this to the SDIO maintainer.
>>
>> MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
>> S: Orphan
>> L: linux-mmc@vger.kernel.org
>> F: drivers/mmc/
>> F: include/linux/mmc/
>>
>> So, these patches are in the right place.
>>
>
> So who is going to pick it up? Just sending them to a random list is not
> going to magically merge them into the kernel.
>
>
This wouldn't happen if you were more human.
Did you see Stefanik crying at the bottom the stairway last night?
E
^ permalink raw reply
* Re: [PATCH RFC 1/3] sdio: recognize io card without powercycle
From: Chris Ball @ 2009-09-07 18:59 UTC (permalink / raw)
To: Michael Buesch; +Cc: Albert Herranz, bcm43xx-dev, linux-mmc, linux-wireless
In-Reply-To: <200909072055.24589.mb@bu3sch.de>
Hi Michael,
> Please submit this to the SDIO maintainer.
MULTIMEDIA CARD (MMC), SECURE DIGITAL (SD) AND SDIO SUBSYSTEM
S: Orphan
L: linux-mmc@vger.kernel.org
F: drivers/mmc/
F: include/linux/mmc/
So, these patches are in the right place.
- Chris.
--
Chris Ball <cjb@laptop.org>
One Laptop Per Child
^ permalink raw reply
* Re: iw: strange output
From: Johannes Berg @ 2009-09-07 20:55 UTC (permalink / raw)
To: Gábor Stefanik; +Cc: Holger Schurig, linux-wireless
In-Reply-To: <69e28c910909071108t1956b0dfj7f96cac84d9088d6@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 406 bytes --]
On Mon, 2009-09-07 at 20:08 +0200, Gábor Stefanik wrote:
> > P.S.: when I'm using nl80211 driver for wpa_supplicant, I seem
> > to be associated, but no ping goes throught.
>
> I can also confirm that. It appears to be a regression from the "big
> state machine monster is no more" change.
Works fine here in a whole bunch of cases, you're both going to have to
be more specific.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH V2] MAINTAINERS: Add Atheros Linux wireless drivers home page
From: Luis R. Rodriguez @ 2009-09-07 21:31 UTC (permalink / raw)
To: Joe Perches
Cc: linux-kernel, devel, Len Widra, linux-wireless, Nick Kossifidis,
Bob Copeland, Greg KH, Stephen Chen, Andrew Morton,
Senthil Balasubramanian, Jiri Slaby, Jouni Malinen,
Sujith Manoharan, Vasanthakumar Thiagarajan
In-Reply-To: <1252348470.3394.30.camel@Joe-Laptop.home>
On Mon, Sep 7, 2009 at 11:34 AM, Joe Perches<joe@perches.com> wrote:
> On Sun, 2009-09-06 at 12:26 -0700, Luis R. Rodriguez wrote:
>> On Sun, Sep 6, 2009 at 10:59 AM, Joe Perches<joe@perches.com> wrote:
>> > On Thu, 2009-09-03 at 15:54 -0700, Luis R. Rodriguez wrote:
>> >> I'm pleased to announce the new home page to Atheros Linux wireless drivers:
>> >> http://wireless.kernel.org/en/users/Drivers/Atheros
>> > Perhaps add this to MAINTAINERS?
>> Fine by me, except ath5k and ath9k also have their own respective page
>> so those can also be added.
>
> (cc's trimmed and maintainers added)
>
> Perhaps this instead:
>
> Signed-off-by: Joe Perches <joe@perches.com>
Acked-by: Luis R. Rodriguez
think you have to send this to John.
Luis
^ permalink raw reply
* Re: compat-wireless-old for ARM
From: Luis R. Rodriguez @ 2009-09-07 21:36 UTC (permalink / raw)
To: AMAR SAHUKAR; +Cc: linux-wireless
In-Reply-To: <b55cabb00909070639s4a6f3c1cl8c3e2eccceaf81e8@mail.gmail.com>
On Mon, Sep 7, 2009 at 6:39 AM, AMAR SAHUKAR<amarsahu7@gmail.com> wrote:
> Hi,
> I wanted to know the procedure to follow for installing
> compat-wireless-old on ARM platform. I am using a Netgear WG111V3 usb dongle
> which uses a rtl8187 chipset. I will be pleased if you can help me with
> this.
compat-wireless-old has not been updated for ages. Today is possible
to bring compat-wireless (instead of compat-wireless-old) down to
older kernels we previously could not since we no longer are using the
netdevice multiqueue support. I was able to bring compat-wireless down
to 2.6.25 -- at least compile-wise, there is also code present to help
bring it down to older kernels, we just need someone to test/help
finish the rest.
Luis
^ permalink raw reply
* Re: [ath5k-devel] [PATCH/RFC] ath5k: clear rx queue on reset
From: Luis R. Rodriguez @ 2009-09-07 22:23 UTC (permalink / raw)
To: Bob Copeland, Matt Smith; +Cc: ath5k-devel, linux-wireless, jirislaby
In-Reply-To: <43e72e890909071522i461ca821m703f6e2eeb2d0385@mail.gmail.com>
On Mon, Sep 7, 2009 at 3:22 PM, Luis R. Rodriguez<lrodriguez@atheros.com> wrote:
> Cc'ing Matt just for his information.
>
> Note: this e-mail is on a public mailing list.
>
> On Mon, Sep 7, 2009 at 5:45 AM, Bob Copeland<me@bobcopeland.com> wrote:
>>
>> When changing channels or otherwise resetting the card, dump
>> any queued rx buffers so that we don't use the wrong channel
>> information when reporting the packets. This should fix the
>> remaining instances of this warning:
>>
>> WARNING: at /build/buildd-linux-2.6_2.6.30-1-i386-06t6n0/linux-2.6-2.6.30/debian/build/source_i386_none/drivers/net/wireless/ath5k/base.c:1096 ath5k_hw_to_driver_rix+0x52/0x58 [ath5k]()
>> Hardware name: MacBook1,1
>> invalid hw_rix: 1b
>> Modules linked in: i915 drm i2c_algo_bit binfmt_misc uvcvideo videodev v4l1_compat btusb rfcomm l2cap bluetooth ppdev parport_pc lp parport acpi_cpufreq cpufreq_powersave cpufreq_conservative cpufreq_userspace cpufreq_stats ext4 jbd2 crc16 ext2 fuse arc4 ecb ath5k mac80211 cfg80211 firewire_sbp2 loop joydev applesmc led_class input_polldev snd_hda_codec_idt isight_firmware pcspkr i2c_i801 i2c_core rng_core appletouch evdev iTCO_wdt snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_seq snd_timer snd_seq_device tpm_infineon tpm tpm_bios video output battery processor ac button snd soundcore snd_page_alloc intel_agp agpgart ext3 jbd mbcache usbhid dm_mirror dm_region_hash dm_log dm_snapshot dm_mod sd_mod crc_t10dif ide_cd_mod cdrom ata_piix ata_generic libata scsi_mod firewire_ohci firewire_core crc_itu_t ehci_hcd uhci_hcd ide_pci_generic piix ide_core sky2 usbcore thermal fan thermal_sys hid_apple hid
>> Pid: 5218, comm: euphoria Tainted: G W 2.6.30-1-686 #1
>> Call Trace:
>> [<c0126ff8>] ? warn_slowpath_common+0x5e/0x8a
>> [<c0127056>] ? warn_slowpath_fmt+0x26/0x2a
>> [<f86c139b>] ? ath5k_hw_to_driver_rix+0x52/0x58 [ath5k]
>> [<f86c1899>] ? ath5k_tasklet_rx+0x2b7/0x42e [ath5k]
>> [<c012e618>] ? __mod_timer+0xc9/0xd3
>> [<c012abcf>] ? tasklet_action+0x63/0xa8
>> [<c012b0d7>] ? __do_softirq+0x8e/0x135
>> [<c012b1ac>] ? do_softirq+0x2e/0x38
>> [<c012b28f>] ? irq_exit+0x26/0x53
>> [<c01105c6>] ? smp_apic_timer_interrupt+0x6c/0x76
>> [<c0103966>] ? apic_timer_interrupt+0x2a/0x30
>> [<c01100d8>] ? lapic_suspend+0x47/0x15c
>> [<f8ab68df>] ? drm_clflush_pages+0x3b/0x68 [drm]
>> [<f8b0ad19>] ? i915_gem_execbuffer+0x6cf/0xbdd [i915]
>> [<f8b08b88>] ? i915_gem_busy_ioctl+0x73/0x7a [i915]
>> [<f8ab7667>] ? drm_ioctl+0x1ca/0x24b [drm]
>> [<f8b0a64a>] ? i915_gem_execbuffer+0x0/0xbdd [i915]
>> [<c011cc82>] ? update_curr+0x58/0x178
>> [<c0138b88>] ? hrtimer_forward+0x10c/0x124
>> [<c013d424>] ? getnstimeofday+0x4d/0xca
>> [<c0197064>] ? vfs_ioctl+0x49/0x5f
>> [<c01974be>] ? do_vfs_ioctl+0x444/0x47f
>> [<c01052e6>] ? timer_interrupt+0x32/0x38
>> [<c015a9e5>] ? handle_IRQ_event+0x4e/0x101
>> [<c015bbdf>] ? handle_edge_irq+0xc6/0xe6
>> [<c019753a>] ? sys_ioctl+0x41/0x58
>> [<c0103014>] ? sysenter_do_call+0x12/0x28
>> ---[ end trace 56450801255ccacd ]---
>>
>> Signed-off-by: Bob Copeland <me@bobcopeland.com>
>> ---
>>
>> Luis, what do you think of this for the time being?
>>
>> I also tried just calling the tasklet so that we don't lose this
>> information. This makes the locking a bit more complicated since
>> reset can run in process or softirq context and I didn't quite get
>> it working right, though it would be a worthy avenue to persue.
>
> I wonder if we can just use process context for our bottom halves. Of
> course that's another topic though, but good to know using the rx
> tasklet was tried and that using it requires some more work.
>
>> This seems to work ok though -- it artificially dropped about 50
>> packets while running iperf in parallel with continual scans for
>> 10 minutes, but I still got decent iperf numbers.
>
> I'd really rather we try to keep the frames instead of dropping them
> and since the number of frames on the wrong channel are scarce it
> seems better to drop just those frames instead of all pending frames
> for now.
That is without issuing a warning - as we are already handling it, are
aware of the issue and plan on resolving it somehow.
Luis
^ permalink raw reply
* Re: [ath5k-devel] [PATCH/RFC] ath5k: clear rx queue on reset
From: Luis R. Rodriguez @ 2009-09-07 22:22 UTC (permalink / raw)
To: Bob Copeland, Matt Smith; +Cc: ath5k-devel, linux-wireless, jirislaby
In-Reply-To: <20090907124548.GA5351@hash.localnet>
Cc'ing Matt just for his information.
Note: this e-mail is on a public mailing list.
On Mon, Sep 7, 2009 at 5:45 AM, Bob Copeland<me@bobcopeland.com> wrote:
>
> When changing channels or otherwise resetting the card, dump
> any queued rx buffers so that we don't use the wrong channel
> information when reporting the packets. This should fix the
> remaining instances of this warning:
>
> WARNING: at /build/buildd-linux-2.6_2.6.30-1-i386-06t6n0/linux-2.6-2.6.30/debian/build/source_i386_none/drivers/net/wireless/ath5k/base.c:1096 ath5k_hw_to_driver_rix+0x52/0x58 [ath5k]()
> Hardware name: MacBook1,1
> invalid hw_rix: 1b
> Modules linked in: i915 drm i2c_algo_bit binfmt_misc uvcvideo videodev v4l1_compat btusb rfcomm l2cap bluetooth ppdev parport_pc lp parport acpi_cpufreq cpufreq_powersave cpufreq_conservative cpufreq_userspace cpufreq_stats ext4 jbd2 crc16 ext2 fuse arc4 ecb ath5k mac80211 cfg80211 firewire_sbp2 loop joydev applesmc led_class input_polldev snd_hda_codec_idt isight_firmware pcspkr i2c_i801 i2c_core rng_core appletouch evdev iTCO_wdt snd_hda_intel snd_hda_codec snd_hwdep snd_pcm snd_seq snd_timer snd_seq_device tpm_infineon tpm tpm_bios video output battery processor ac button snd soundcore snd_page_alloc intel_agp agpgart ext3 jbd mbcache usbhid dm_mirror dm_region_hash dm_log dm_snapshot dm_mod sd_mod crc_t10dif ide_cd_mod cdrom ata_piix ata_generic libata scsi_mod firewire_ohci firewire_core crc_itu_t ehci_hcd uhci_hcd ide_pci_generic piix ide_core sky2 usbcore thermal fan thermal_sys hid_apple hid
> Pid: 5218, comm: euphoria Tainted: G W 2.6.30-1-686 #1
> Call Trace:
> [<c0126ff8>] ? warn_slowpath_common+0x5e/0x8a
> [<c0127056>] ? warn_slowpath_fmt+0x26/0x2a
> [<f86c139b>] ? ath5k_hw_to_driver_rix+0x52/0x58 [ath5k]
> [<f86c1899>] ? ath5k_tasklet_rx+0x2b7/0x42e [ath5k]
> [<c012e618>] ? __mod_timer+0xc9/0xd3
> [<c012abcf>] ? tasklet_action+0x63/0xa8
> [<c012b0d7>] ? __do_softirq+0x8e/0x135
> [<c012b1ac>] ? do_softirq+0x2e/0x38
> [<c012b28f>] ? irq_exit+0x26/0x53
> [<c01105c6>] ? smp_apic_timer_interrupt+0x6c/0x76
> [<c0103966>] ? apic_timer_interrupt+0x2a/0x30
> [<c01100d8>] ? lapic_suspend+0x47/0x15c
> [<f8ab68df>] ? drm_clflush_pages+0x3b/0x68 [drm]
> [<f8b0ad19>] ? i915_gem_execbuffer+0x6cf/0xbdd [i915]
> [<f8b08b88>] ? i915_gem_busy_ioctl+0x73/0x7a [i915]
> [<f8ab7667>] ? drm_ioctl+0x1ca/0x24b [drm]
> [<f8b0a64a>] ? i915_gem_execbuffer+0x0/0xbdd [i915]
> [<c011cc82>] ? update_curr+0x58/0x178
> [<c0138b88>] ? hrtimer_forward+0x10c/0x124
> [<c013d424>] ? getnstimeofday+0x4d/0xca
> [<c0197064>] ? vfs_ioctl+0x49/0x5f
> [<c01974be>] ? do_vfs_ioctl+0x444/0x47f
> [<c01052e6>] ? timer_interrupt+0x32/0x38
> [<c015a9e5>] ? handle_IRQ_event+0x4e/0x101
> [<c015bbdf>] ? handle_edge_irq+0xc6/0xe6
> [<c019753a>] ? sys_ioctl+0x41/0x58
> [<c0103014>] ? sysenter_do_call+0x12/0x28
> ---[ end trace 56450801255ccacd ]---
>
> Signed-off-by: Bob Copeland <me@bobcopeland.com>
> ---
>
> Luis, what do you think of this for the time being?
>
> I also tried just calling the tasklet so that we don't lose this
> information. This makes the locking a bit more complicated since
> reset can run in process or softirq context and I didn't quite get
> it working right, though it would be a worthy avenue to persue.
I wonder if we can just use process context for our bottom halves. Of
course that's another topic though, but good to know using the rx
tasklet was tried and that using it requires some more work.
> This seems to work ok though -- it artificially dropped about 50
> packets while running iperf in parallel with continual scans for
> 10 minutes, but I still got decent iperf numbers.
I'd really rather we try to keep the frames instead of dropping them
and since the number of frames on the wrong channel are scarce it
seems better to drop just those frames instead of all pending frames
for now. If we get to actually process all pending frames prior to a
reset / channel change we then eventually won't loose the other stray
frames. The solution I'd like to see is to avoid those stray frames in
the first place.
I'm expecting to review avoiding dropping stale frames a little more
next week at work with Matt, will let you know how that goes.
Luis
> drivers/net/wireless/ath/ath5k/base.c | 53 ++++++++++++++++++++------------
> 1 files changed, 33 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
> index 9c6ab53..1f62325 100644
> --- a/drivers/net/wireless/ath/ath5k/base.c
> +++ b/drivers/net/wireless/ath/ath5k/base.c
> @@ -548,6 +548,8 @@ ath5k_pci_probe(struct pci_dev *pdev,
>
> sc->iobase = mem; /* So we can unmap it on detach */
> sc->common.cachelsz = csz << 2; /* convert to bytes */
> + sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz);
> +
> sc->opmode = NL80211_IFTYPE_STATION;
> sc->bintval = 1000;
> mutex_init(&sc->lock);
> @@ -1221,6 +1223,32 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
> return 0;
> }
>
> +/*
> + * Clear out any unprocessed RX buffers and reset the buffers to
> + * their initial state.
> + */
> +static int
> +ath5k_rxbuf_init(struct ath5k_softc *sc)
> +{
> + int ret;
> + struct ath5k_buf *bf;
> +
> + spin_lock_bh(&sc->rxbuflock);
> + sc->rxlink = NULL;
> + list_for_each_entry(bf, &sc->rxbuf, list) {
> + ret = ath5k_rxbuf_setup(sc, bf);
> + if (ret)
> + goto err;
> + }
> + bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
> + ath5k_hw_set_rxdp(sc->ah, bf->daddr);
> + ret = 0;
> +err:
> + spin_unlock_bh(&sc->rxbuflock);
> + return ret;
> +}
> +
> +
> static int
> ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
> struct ath5k_txq *txq)
> @@ -1606,32 +1634,17 @@ static int
> ath5k_rx_start(struct ath5k_softc *sc)
> {
> struct ath5k_hw *ah = sc->ah;
> - struct ath5k_buf *bf;
> int ret;
>
> - sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz);
> -
> - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n",
> - sc->common.cachelsz, sc->rxbufsize);
> -
> - spin_lock_bh(&sc->rxbuflock);
> - sc->rxlink = NULL;
> - list_for_each_entry(bf, &sc->rxbuf, list) {
> - ret = ath5k_rxbuf_setup(sc, bf);
> - if (ret != 0) {
> - spin_unlock_bh(&sc->rxbuflock);
> - goto err;
> - }
> - }
> - bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list);
> - ath5k_hw_set_rxdp(ah, bf->daddr);
> - spin_unlock_bh(&sc->rxbuflock);
> + ret = ath5k_rxbuf_init(sc);
> + if (ret)
> + goto err;
>
> ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */
> ath5k_mode_setup(sc); /* set filters, etc. */
> ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */
>
> - return 0;
> + ret = 0;
> err:
> return ret;
> }
> @@ -1650,7 +1663,7 @@ ath5k_rx_stop(struct ath5k_softc *sc)
>
> ath5k_debug_printrxbuffs(sc, ah);
>
> - sc->rxlink = NULL; /* just in case */
> + ath5k_rxbuf_init(sc); /* clear rx buffers */
> }
>
> static unsigned int
> --
> 1.6.2.5
>
> --
> Bob Copeland %% www.bobcopeland.com
>
> _______________________________________________
> ath5k-devel mailing list
> ath5k-devel@lists.ath5k.org
> https://lists.ath5k.org/mailman/listinfo/ath5k-devel
>
^ permalink raw reply
* Stop using tasklets for bottom halves
From: Luis R. Rodriguez @ 2009-09-07 22:58 UTC (permalink / raw)
To: Steven Rostedt, Ingo Molnar, Michael Buesch, John W. Linville
Cc: linux-wireless, linux-kernel, netdev, Matt Smith, Kevin Hayes,
Bob Copeland, Jouni Malinen, Ivan Seskar, ic.felix
A while ago I had read about an effort to consider removing tasklets
[1] or at least trying to not use them. I'm unaware of the progress in
this respect but since reading that article have always tried to
evaluate whether or not we need tasklets on wireless drivers. I have
also wondered whether work in irq context in other parts of the kernel
can be moved to process context, a curious example being timers. I'll
personally be trying to using only process context on bottom halves on
future drivers but I figured it may be a good time to ask how serious
was avoiding tasklets or using wrappers in the future to avoid irq
context is or is it advised. Do we have a general agreement this is a
good step forward to take? Has anyone made tests or changes on a
specific driver from irq context to process context and proven there
are no significant advantages of using irq context where you would
have expected it?
Wireless in particular should IMHO not require taskets for anything
time sensitive that I can think about except perhaps changing channels
quickly and to do that appropriately also process pending RX frames
prior to a switch. It remains to be seen experimentally whether or not
using a workqueue for RX processing would affect the time to switch
channels negatively but I doubt it would be significant. I hope to
test that with ath9k_htc.
What about gigabit or 10 Gigabit Ethernet drivers ? Do they face any
challenges which would yet need to be proven would not face issues
when processing bottom halves in process context?
[1] http://lwn.net/Articles/239633/
Luis
^ permalink raw reply
* Re: [ath5k-devel] [PATCH/RFC] ath5k: clear rx queue on reset
From: Bob Copeland @ 2009-09-07 23:07 UTC (permalink / raw)
To: Luis R. Rodriguez; +Cc: Matt Smith, ath5k-devel, linux-wireless, jirislaby
In-Reply-To: <43e72e890909071523q2994b123i15eb1b6991dc073a@mail.gmail.com>
On Mon, Sep 7, 2009 at 6:23 PM, Luis R. Rodriguez<lrodriguez@atheros.com> wrote:
> On Mon, Sep 7, 2009 at 3:22 PM, Luis R. Rodriguez<lrodriguez@atheros.com> wrote:
>> Cc'ing Matt just for his information.
>>
>> I'd really rather we try to keep the frames instead of dropping them
>> and since the number of frames on the wrong channel are scarce it
>> seems better to drop just those frames instead of all pending frames
>> for now.
Ok, sounds like a better plan. In fact we could keep and report those
frames with a base rate (we do that now) but one problem with that is we
might think we got a beacon on a channel that we really didn't, and
that could confuse the regulatory system.
--
Bob Copeland %% www.bobcopeland.com
^ permalink raw reply
* Re: Stop using tasklets for bottom halves
From: Stephen Hemminger @ 2009-09-08 0:14 UTC (permalink / raw)
To: Luis R. Rodriguez
Cc: Steven Rostedt, Ingo Molnar, Michael Buesch, John W. Linville,
linux-wireless, linux-kernel, netdev, Matt Smith, Kevin Hayes,
Bob Copeland, Jouni Malinen, Ivan Seskar, ic.felix
In-Reply-To: <43e72e890909071558s637b45c7i10807587dc40e8c4@mail.gmail.com>
On Mon, 7 Sep 2009 15:58:50 -0700
"Luis R. Rodriguez" <mcgrof@gmail.com> wrote:
> A while ago I had read about an effort to consider removing tasklets
> [1] or at least trying to not use them. I'm unaware of the progress in
> this respect but since reading that article have always tried to
> evaluate whether or not we need tasklets on wireless drivers. I have
> also wondered whether work in irq context in other parts of the kernel
> can be moved to process context, a curious example being timers. I'll
> personally be trying to using only process context on bottom halves on
> future drivers but I figured it may be a good time to ask how serious
> was avoiding tasklets or using wrappers in the future to avoid irq
> context is or is it advised. Do we have a general agreement this is a
> good step forward to take? Has anyone made tests or changes on a
> specific driver from irq context to process context and proven there
> are no significant advantages of using irq context where you would
> have expected it?
>
> Wireless in particular should IMHO not require taskets for anything
> time sensitive that I can think about except perhaps changing channels
> quickly and to do that appropriately also process pending RX frames
> prior to a switch. It remains to be seen experimentally whether or not
> using a workqueue for RX processing would affect the time to switch
> channels negatively but I doubt it would be significant. I hope to
> test that with ath9k_htc.
>
> What about gigabit or 10 Gigabit Ethernet drivers ? Do they face any
> challenges which would yet need to be proven would not face issues
> when processing bottom halves in process context?
>
> [1] http://lwn.net/Articles/239633/
>
> Luis
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
Why not use NAPI, which is soft irq? Almost all 1G and 10G drivers
use NAPI.
Process context is too slow.
--
^ permalink raw reply
* Re: Stop using tasklets for bottom halves
From: Steven Rostedt @ 2009-09-08 2:17 UTC (permalink / raw)
To: Stephen Hemminger
Cc: Luis R. Rodriguez, Ingo Molnar, Michael Buesch, John W. Linville,
linux-wireless, linux-kernel, netdev, Matt Smith, Kevin Hayes,
Bob Copeland, Jouni Malinen, Ivan Seskar, ic.felix
In-Reply-To: <20090907171406.6a4b6116@nehalam>
On Mon, 2009-09-07 at 17:14 -0700, Stephen Hemminger wrote:
> On Mon, 7 Sep 2009 15:58:50 -0700
> "Luis R. Rodriguez" <mcgrof@gmail.com> wrote:
>
> > A while ago I had read about an effort to consider removing tasklets
> > [1] or at least trying to not use them. I'm unaware of the progress in
> > this respect but since reading that article have always tried to
> > evaluate whether or not we need tasklets on wireless drivers. I have
> > also wondered whether work in irq context in other parts of the kernel
> > can be moved to process context, a curious example being timers. I'll
> > personally be trying to using only process context on bottom halves on
> > future drivers but I figured it may be a good time to ask how serious
> > was avoiding tasklets or using wrappers in the future to avoid irq
> > context is or is it advised. Do we have a general agreement this is a
> > good step forward to take? Has anyone made tests or changes on a
> > specific driver from irq context to process context and proven there
> > are no significant advantages of using irq context where you would
> > have expected it?
> >
> > Wireless in particular should IMHO not require taskets for anything
> > time sensitive that I can think about except perhaps changing channels
> > quickly and to do that appropriately also process pending RX frames
> > prior to a switch. It remains to be seen experimentally whether or not
> > using a workqueue for RX processing would affect the time to switch
> > channels negatively but I doubt it would be significant. I hope to
> > test that with ath9k_htc.
> >
> > What about gigabit or 10 Gigabit Ethernet drivers ? Do they face any
> > challenges which would yet need to be proven would not face issues
> > when processing bottom halves in process context?
> >
> > [1] http://lwn.net/Articles/239633/
> >
> > Luis
> > --
> > To unsubscribe from this list: send the line "unsubscribe netdev" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
>
> Why not use NAPI, which is soft irq? Almost all 1G and 10G drivers
> use NAPI.
>
> Process context is too slow.
Well, I'm hoping to prove the opposite. I'm working on some stuff that I
plan to present at Linux Plumbers. I've been too distracted by other
things, but hopefully I'll have some good numbers to present by then.
-- Steve
^ permalink raw reply
* Re: Stop using tasklets for bottom halves
From: Luis R. Rodriguez @ 2009-09-08 4:16 UTC (permalink / raw)
To: rostedt
Cc: Stephen Hemminger, Ingo Molnar, Michael Buesch, John W. Linville,
linux-wireless, linux-kernel, netdev, Matt Smith, Kevin Hayes,
Bob Copeland, Jouni Malinen, Ivan Seskar, ic.felix
In-Reply-To: <1252376254.21261.2052.camel@gandalf.stny.rr.com>
On Mon, Sep 7, 2009 at 7:17 PM, Steven Rostedt<rostedt@goodmis.org> wrote:
> On Mon, 2009-09-07 at 17:14 -0700, Stephen Hemminger wrote:
>> On Mon, 7 Sep 2009 15:58:50 -0700
>> "Luis R. Rodriguez" <mcgrof@gmail.com> wrote:
>>
>> > A while ago I had read about an effort to consider removing tasklets
>> > [1] or at least trying to not use them. I'm unaware of the progress in
>> > this respect but since reading that article have always tried to
>> > evaluate whether or not we need tasklets on wireless drivers. I have
>> > also wondered whether work in irq context in other parts of the kernel
>> > can be moved to process context, a curious example being timers. I'll
>> > personally be trying to using only process context on bottom halves on
>> > future drivers but I figured it may be a good time to ask how serious
>> > was avoiding tasklets or using wrappers in the future to avoid irq
>> > context is or is it advised. Do we have a general agreement this is a
>> > good step forward to take? Has anyone made tests or changes on a
>> > specific driver from irq context to process context and proven there
>> > are no significant advantages of using irq context where you would
>> > have expected it?
>> >
>> > Wireless in particular should IMHO not require taskets for anything
>> > time sensitive that I can think about except perhaps changing channels
>> > quickly and to do that appropriately also process pending RX frames
>> > prior to a switch. It remains to be seen experimentally whether or not
>> > using a workqueue for RX processing would affect the time to switch
>> > channels negatively but I doubt it would be significant. I hope to
>> > test that with ath9k_htc.
>> >
>> > What about gigabit or 10 Gigabit Ethernet drivers ? Do they face any
>> > challenges which would yet need to be proven would not face issues
>> > when processing bottom halves in process context?
>> >
>> > [1] http://lwn.net/Articles/239633/
>> >
>> > Luis
>> > --
>> > To unsubscribe from this list: send the line "unsubscribe netdev" in
>> > the body of a message to majordomo@vger.kernel.org
>> > More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>> Why not use NAPI, which is soft irq? Almost all 1G and 10G drivers
>> use NAPI.
>>
>> Process context is too slow.
>
> Well, I'm hoping to prove the opposite. I'm working on some stuff that I
> plan to present at Linux Plumbers. I've been too distracted by other
> things, but hopefully I'll have some good numbers to present by then.
What day in specific was this planned for at Plumbers?
Luis
^ permalink raw reply
* Re: Stop using tasklets for bottom halves
From: Michael Buesch @ 2009-09-08 4:50 UTC (permalink / raw)
To: rostedt
Cc: Stephen Hemminger, Luis R. Rodriguez, Ingo Molnar,
John W. Linville, linux-wireless, linux-kernel, netdev,
Matt Smith, Kevin Hayes, Bob Copeland, Jouni Malinen, Ivan Seskar,
ic.felix
In-Reply-To: <1252376254.21261.2052.camel@gandalf.stny.rr.com>
On Tuesday 08 September 2009 04:17:34 Steven Rostedt wrote:
> > Process context is too slow.
>
> Well, I'm hoping to prove the opposite. I'm working on some stuff that I
> plan to present at Linux Plumbers. I've been too distracted by other
> things, but hopefully I'll have some good numbers to present by then.
I recently converted the b43 driver to threaded interrupt handlers and
a workqueue based TX mechanism. (My motivation was porting b43 to the SDIO bus that
needs to sleep, so requires process context).
There are two things that I noticed. When looking at the "idle" percentage in "top"
it regressed quite a bit when using threaded IRQ handlers. It shows about 8% less
idle. This is with threaded IRQs patched in, but without WQ TX mechanism. Applying
the WQ TX mechanism does not show any noticeable effect in "top".
I'm not quite sure where the 8% slowdown on threaded IRQ handlers come from. I'm not
really certain that it's _really_ a regression and not just a statistics accounting quirk.
Why does threaded IRQs slow down stuff and threaded TX does not at all? That does not
make sense at all to me.
I think there's no real reason for process context being slow in general. It's just that
we have additional context switches. But these are fast on Linux.
--
Greetings, Michael.
^ permalink raw reply
* Re: Stop using tasklets for bottom halves
From: Michael Buesch @ 2009-09-08 5:08 UTC (permalink / raw)
To: rostedt
Cc: Stephen Hemminger, Luis R. Rodriguez, Ingo Molnar,
John W. Linville, linux-wireless, linux-kernel, netdev,
Matt Smith, Kevin Hayes, Bob Copeland, Jouni Malinen, Ivan Seskar,
ic.felix
In-Reply-To: <200909080650.43181.mb@bu3sch.de>
On Tuesday 08 September 2009 06:50:41 Michael Buesch wrote:
> On Tuesday 08 September 2009 04:17:34 Steven Rostedt wrote:
> > > Process context is too slow.
> >
> > Well, I'm hoping to prove the opposite. I'm working on some stuff that I
> > plan to present at Linux Plumbers. I've been too distracted by other
> > things, but hopefully I'll have some good numbers to present by then.
>
> I recently converted the b43 driver to threaded interrupt handlers and
> a workqueue based TX mechanism. (My motivation was porting b43 to the SDIO bus that
> needs to sleep, so requires process context).
>
> There are two things that I noticed. When looking at the "idle" percentage in "top"
> it regressed quite a bit when using threaded IRQ handlers. It shows about 8% less
> idle. This is with threaded IRQs patched in, but without WQ TX mechanism. Applying
> the WQ TX mechanism does not show any noticeable effect in "top".
>
> I'm not quite sure where the 8% slowdown on threaded IRQ handlers come from. I'm not
> really certain that it's _really_ a regression and not just a statistics accounting quirk.
> Why does threaded IRQs slow down stuff and threaded TX does not at all? That does not
> make sense at all to me.
>
> I think there's no real reason for process context being slow in general. It's just that
> we have additional context switches. But these are fast on Linux.
>
Ok, I just did another test. I used a workqueue instead of the standard kernel threaded
IRQ infrastructure. Now the slowdown is only about 4% in "top". Maybe that shows room
for improvement in the threaded IRQ implementation...
B43 does call mac80211's "irqsafe" TX-status and RX functions. They schedule
additional tasklets. That is not required, however. Maybe I should remove that stuff and
retry my tests. That should also improve stuff a bit.
And yes, I notice that "top" is actually crap for testing performance issues. :)
--
Greetings, Michael.
^ permalink raw reply
* RE: compat-wireless-old for ARM
From: Marcel @ 2009-09-08 6:10 UTC (permalink / raw)
To: 'Luis R. Rodriguez', 'AMAR SAHUKAR'; +Cc: linux-wireless
In-Reply-To: <43e72e890909071436ub99bddbx3dd531d09f322b4a@mail.gmail.com>
Hello Luis,
Do you think it should be viable to bring it down to kernel 2.6.22
using armeb?
If so, I can help to test since I am very interested in ath5k.
Regards
Marcel
-----Original Message-----
From: linux-wireless-owner@vger.kernel.org
[mailto:linux-wireless-owner@vger.kernel.org] On Behalf Of Luis R. Rodriguez
Sent: den 7 september 2009 23:37
To: AMAR SAHUKAR
Cc: linux-wireless@vger.kernel.org
Subject: Re: compat-wireless-old for ARM
On Mon, Sep 7, 2009 at 6:39 AM, AMAR SAHUKAR<amarsahu7@gmail.com> wrote:
> Hi,
> I wanted to know the procedure to follow for installing
> compat-wireless-old on ARM platform. I am using a Netgear WG111V3 usb
dongle
> which uses a rtl8187 chipset. I will be pleased if you can help me with
> this.
compat-wireless-old has not been updated for ages. Today is possible
to bring compat-wireless (instead of compat-wireless-old) down to
older kernels we previously could not since we no longer are using the
netdevice multiqueue support. I was able to bring compat-wireless down
to 2.6.25 -- at least compile-wise, there is also code present to help
bring it down to older kernels, we just need someone to test/help
finish the rest.
Luis
--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* Re: compat-wireless-old for ARM
From: Luis R. Rodriguez @ 2009-09-08 6:41 UTC (permalink / raw)
To: Marcel; +Cc: AMAR SAHUKAR, linux-wireless
In-Reply-To: <70EB52E9BF7F43BBBBC899826FD0D3C4@inin.local>
On Mon, Sep 7, 2009 at 11:10 PM, Marcel<marcelcastrobr@gmail.com> wrote:
> Hello Luis,
> Do you think it should be viable to bring it down to kernel 2.6.22
> using armeb?
What's armeb?
It should be possible for sure to bring it down to even 2.6.21, maybe
even more. There is already code for 2.6.21..2.6.24, the gaps are all
that just need to be accounted for as well as testing.
> If so, I can help to test since I am very interested in ath5k.
Great!
Luis
^ permalink raw reply
* Re: Atheros Linux wireless drivers home page - and two new driver projects
From: Denis Kirjanov @ 2009-09-08 6:50 UTC (permalink / raw)
To: michael
Cc: Xavier Bestel, devel, b_yogesh_snowy, Dan Williams,
Stefan Lippers-Hollmann, Len Widra, linux-wireless, linux-kernel,
Stephen Chen, Jouni Malinen, Nick Kossifidis, Paul Fertser,
Harald Welte, Bob Copeland, Witold Sowa, Michael Renzmann,
Werner Almesberger
In-Reply-To: <4AA24FAB.20700@panicking.kicks-ass.org>
Good time of day.
Do I need to use wireless-testing tree ?
On Sat, Sep 5, 2009 at 3:46 PM, michael<michael@panicking.kicks-ass.org> wrote:
> Hi,
>
> Xavier Bestel wrote:
>>
>> Le vendredi 04 septembre 2009 à 09:51 -0700, Luis R. Rodriguez a écrit :
>>>
>>> On Fri, Sep 4, 2009 at 9:18 AM, Xavier Bestel<xavier.bestel@free.fr>
>>> wrote:
>>>>
>>>> On Fri, 2009-09-04 at 12:06 -0400, Pavel Roskin wrote:
>>>>>
>>>>> On Fri, 2009-09-04 at 13:53 +0200, Xavier Bestel wrote:
>>>>>>
>>>>>> On Thu, 2009-09-03 at 15:54 -0700, Luis R. Rodriguez wrote:
>>>>>>>
>>>>>>> I'm pleased to announce the new home page to Atheros Linux wireless
>>>>>>> drivers:
>>>>>>>
>>>>>>> http://wireless.kernel.org/en/users/Drivers/Atheros
>>>>>>
>>>>>> ath5k is marked as not master-mode capable. I thought this had been
>>>>>> fixed for 2.6.31 ?
>>>>>
>>>>> The above page makes no such statements. I have fixed
>>>>> http://wireless.kernel.org/en/users/Drivers/ath5k
>>>>
>>>> Right, thanks.
>>>>
>>>>> https://madwifi-project.org/wiki/UserDocs/ath5kAccessPoint still needs
>>>>> a
>>>>> lot of work, or maybe it should be removed as obsolete.
>>>>
>>>> Yes, I miss access-point functionality in NetworkManager :)
>>>
>>> BTW a GSoC project this year was to add AP support to Network Manager.
>>> As far I can tell the Witold Sowa finished this so you should be able
>>> to test this.
>>
>> Awesome.
>>
>>> Witold, can you update the wiki page on this project with details as
>>> to how people can test this?
>>>
>>>
>>> http://wireless.kernel.org/en/developers/GSoC/2009/Add_AP_Support_to_Network_Manager
>>>
>>> Luis
>>>
>
> Is there any plan to support the ar6k athereos wifi card?
>
> Michael
>
>>
>>
>>
>> _______________________________________________
>> devel mailing list
>> devel@linuxdriverproject.org
>> http://driverdev.linuxdriverproject.org/mailman/listinfo/devel
>>
>
> _______________________________________________
> devel mailing list
> devel@linuxdriverproject.org
> http://driverdev.linuxdriverproject.org/mailman/listinfo/devel
>
--
Regards,
Denis
^ permalink raw reply
* Re: Stop using tasklets for bottom halves
From: Ingo Molnar @ 2009-09-08 7:10 UTC (permalink / raw)
To: Michael Buesch
Cc: rostedt, Stephen Hemminger, Luis R. Rodriguez, John W. Linville,
linux-wireless, linux-kernel, netdev, Matt Smith, Kevin Hayes,
Bob Copeland, Jouni Malinen, Ivan Seskar, ic.felix
In-Reply-To: <200909080650.43181.mb@bu3sch.de>
* Michael Buesch <mb@bu3sch.de> wrote:
> There are two things that I noticed. When looking at the "idle"
> percentage in "top" it regressed quite a bit when using threaded
> IRQ handlers. It shows about 8% less idle. This is with threaded
> IRQs patched in, but without WQ TX mechanism. Applying the WQ TX
> mechanism does not show any noticeable effect in "top".
>
> I'm not quite sure where the 8% slowdown on threaded IRQ handlers
> come from. I'm not really certain that it's _really_ a regression
> and not just a statistics accounting quirk. Why does threaded IRQs
> slow down stuff and threaded TX does not at all? That does not
> make sense at all to me.
Do you have an x86 box to test it on?
If yes then perfcounters can be used for _much_ more precise
measurements that you can trust. Do something like this:
perf stat -a --repeat 3 sleep 1
The '-a/--all' option will measure all CPUs - everything: IRQ
context, irqs-off region, etc. That output will be comparable before
your threaded patch and after the patch.
Here's an example. I started one infinite loop on a testbox, which
is using 100% of a single CPU. The system-wide stats look like this:
# perf stat -a --repeat 3 sleep 1
Performance counter stats for 'sleep 1' (3 runs):
16003.320239 task-clock-msecs # 15.993 CPUs ( +- 0.044% )
94 context-switches # 0.000 M/sec ( +- 11.373% )
3 CPU-migrations # 0.000 M/sec ( +- 25.000% )
170 page-faults # 0.000 M/sec ( +- 0.518% )
3294001334 cycles # 205.832 M/sec ( +- 0.896% )
1088670782 instructions # 0.331 IPC ( +- 0.905% )
1720926 cache-references # 0.108 M/sec ( +- 1.880% )
61253 cache-misses # 0.004 M/sec ( +- 4.401% )
1.000623219 seconds time elapsed ( +- 0.002% )
the instructions count or the cycle count will go up or down,
precisely according to how the threaded handlers. These stats are
not time sampled but 'real', so they reflect reality and show
whether your workload had to spend more (or less) cycles /
instructions /etc.
I started a second loop in addition to the first one, and perf stat
now gives me this output:
# perf stat -a --repeat 3 sleep 1
Performance counter stats for 'sleep 1' (3 runs):
16003.289509 task-clock-msecs # 15.994 CPUs ( +- 0.046% )
88 context-switches # 0.000 M/sec ( +- 15.933% )
2 CPU-migrations # 0.000 M/sec ( +- 14.286% )
188 page-faults # 0.000 M/sec ( +- 9.414% )
6481963224 cycles # 405.039 M/sec ( +- 0.011% )
2152924468 instructions # 0.332 IPC ( +- 0.054% )
397564 cache-references # 0.025 M/sec ( +- 1.217% )
59835 cache-misses # 0.004 M/sec ( +- 3.732% )
1.000576354 seconds time elapsed ( +- 0.005% )
Compare the two results:
before:
6481963224 cycles # 405.039 M/sec ( +- 0.011% )
2152924468 instructions # 0.332 IPC ( +- 0.054% )
after:
3294001334 cycles # 205.832 M/sec ( +- 0.896% )
1088670782 instructions # 0.331 IPC ( +- 0.905% )
The cycles/sec doubled - as expected. You could do the same with
your test and not have to rely in the very imprecise (and often
misleading) 'top' statistics for kernel development.
The IPC (instructions per cycle) factor stayed roughly constant -
showing that both workloads can push the same amount of instructions
when normalized to a single CPU. If a workload becomes very
cache-missy or executes a lot of system calls then the IPC factor
goes down - if it becomes more optimal 'tight' code then the IPC
factor goes up.)
(The cache-miss rate was very low in both cases - it's a simple
infinite loop i tested.)
Furthermore the error bars in the rightmost column help you know
whether any difference in results is statistically significant, or
within the noise level.
Hope this helps,
Ingo
^ permalink raw reply
* Possible WEP encryption error with wpa_supplicant -Dnl80211
From: Holger Schurig @ 2009-09-08 8:16 UTC (permalink / raw)
To: linux-wireless
Here are some details on my ping problem: I seem to be associated
successfully to an Cisco 1231 AP, but no pings are going through
if I use nl80211.
----------------------------------- test.conf
ctrl_interface=/var/run/wpa_supplicant
network={
ssid="TEST"
key_mgmt=NONE
wep_key0="99999"
}
------------------------------------- test.sh
#!/bin/sh
ifconfig eth1 10.2.1.2 netmask 255.255.255.0 up
./wpa_supplicant \
-D nl80211 \
-i eth1 \
-c test.conf \
-P /var/run/wpa_supplicant.eth1.pid \
-C /var/run/wpa_supplicant
---------------------------------------------
# ./TEST.sh
CTRL-EVENT-SCAN-RESULTS
Trying to authenticate with 00:13:19:80:da:30 (SSID='TEST' freq=2412 MHz)
Trying to associate with 00:13:19:80:da:30 (SSID='TEST' freq=2412 MHz)
Associated with 00:13:19:80:da:30
CTRL-EVENT-CONNECTED - Connection to 00:1b:53:11:dc:40 completed (auth) [id=0 id_str=]
$ ping -c 5 10.2.1.1
PING 10.2.1.1 (10.2.1.1) 56(84) bytes of data.
>From 10.2.1.2 icmp_seq=1 Destination Host Unreachable
>From 10.2.1.2 icmp_seq=2 Destination Host Unreachable
>From 10.2.1.2 icmp_seq=3 Destination Host Unreachable
>From 10.2.1.2 icmp_seq=4 Destination Host Unreachable
>From 10.2.1.2 icmp_seq=5 Destination Host Unreachable
--- 10.2.1.1 ping statistics ---
5 packets transmitted, 0 received, +5 errors, 100% packet loss, time 4023ms, pipe 3
While this was happening, I used another wireless card monitor
the channel. I then saw ARP packets, but AFAIK they haven't been
encrypted:
Frame 319 (85 bytes on wire, 85 bytes captured)
Arrival Time: Sep 8, 2009 09:07:34.529847000
[Time delta from previous packet: 0.012281000 seconds]
[Time since reference or first frame: 5.988251000 seconds]
Frame Number: 319
Packet Length: 85 bytes
Capture Length: 85 bytes
[Frame is marked: False]
[Protocols in frame: radiotap:wlan:llc:arp]
Radiotap Header v0, Length 25
Header revision: 0
Header pad: 0
Header length: 25
Present flags: 0x0000086f
.... .... .... .... .... .... .... ...1 = TSFT: True
.... .... .... .... .... .... .... ..1. = Flags: True
.... .... .... .... .... .... .... .1.. = Rate: True
.... .... .... .... .... .... .... 1... = Channel: True
.... .... .... .... .... .... ...0 .... = FHSS: False
.... .... .... .... .... .... ..1. .... = DBM Antenna Signal: True
.... .... .... .... .... .... .1.. .... = DBM Antenna Noise: True
.... .... .... .... .... .... 0... .... = Lock Quality: False
.... .... .... .... .... ...0 .... .... = TX Attenuation: False
.... .... .... .... .... ..0. .... .... = DB TX Attenuation: False
.... .... .... .... .... .0.. .... .... = DBM TX Attenuation: False
.... .... .... .... .... 1... .... .... = Antenna: True
.... .... .... .... ...0 .... .... .... = DB Antenna Signal: False
.... .... .... .... ..0. .... .... .... = DB Antenna Noise: False
.... .... .... .... .0.. .... .... .... = FCS in header: False
0... .... .... .... .... .... .... .... = Ext: False
MAC timestamp: 0
Flags: 0x00
.... ...0 = CFP: False
.... ..0. = Preamble: Long
.... .0.. = WEP: False
.... 0... = Fragmentation: False
...0 .... = FCS at end: False
..0. .... = Data Pad: False
Data Rate: 11.0 Mb/s
Channel: 2412 (chan 1)
Channel type: 802.11b (0x00a0)
SSI Signal: -17 dBm
SSI Noise: 0 dBm
Antenna: 2
IEEE 802.11
Type/Subtype: Data (32)
Frame Control: 0x0108 (Normal)
Version: 0
Type: Data frame (2)
Subtype: 0
Flags: 0x1
DS status: Frame from STA to DS via an AP (To DS: 1 From DS: 0) (0x01)
.... .0.. = More Fragments: This is the last fragment
.... 0... = Retry: Frame is not being retransmitted
...0 .... = PWR MGT: STA will stay up
..0. .... = More Data: No data buffered
.0.. .... = Protected flag: Data is not protected
0... .... = Order flag: Not strictly ordered
Duration: 213
BSS Id: 00:1b:53:11:dc:40 (00:1b:53:11:dc:40)
Source address: Proxim_a0:6d:40 (00:20:a6:a0:6d:40)
Destination address: Broadcast (ff:ff:ff:ff:ff:ff)
Fragment number: 0
Sequence number: 120
Logical-Link Control
DSAP: SNAP (0xaa)
IG Bit: Individual
SSAP: SNAP (0xaa)
CR Bit: Command
Control field: U, func=UI (0x03)
000. 00.. = Command: Unnumbered Information (0x00)
.... ..11 = Frame type: Unnumbered frame (0x03)
Organization Code: Encapsulated Ethernet (0x000000)
Type: ARP (0x0806)
Address Resolution Protocol (request)
Hardware type: Ethernet (0x0001)
Protocol type: IP (0x0800)
Hardware size: 6
Protocol size: 4
Opcode: request (0x0001)
Sender MAC address: Proxim_a0:6d:40 (00:20:a6:a0:6d:40)
Sender IP address: 10.2.1.2 (10.2.1.2)
Target MAC address: 00:00:00_00:00:00 (00:00:00:00:00:00)
Target IP address: 10.2.1.1 (10.2.1.1)
After removing all kernel modules and reloading them again (ath5k,
mac80211, ath, cfg80211) and replacing the "-D nl80211" with "-D wext",
the ping works.
# ./TEST.sh
ioctl[SIOCGIWSCAN]: Resource temporarily unavailable
ioctl[SIOCSIWSCAN]: Device or resource busy
Failed to initiate AP scan.
CTRL-EVENT-SCAN-RESULTS
Trying to associate with 00:1b:53:11:dc:40 (SSID='TEST' freq=2412 MHz)
CTRL-EVENT-SCAN-RESULTS
Trying to associate with 00:13:19:80:da:30 (SSID='TEST' freq=2412 MHz)
Associated with 00:13:19:80:da:30
CTRL-EVENT-CONNECTED - Connection to 00:13:19:80:da:30 completed (auth) [id=0 id_str=]
--
http://www.holgerschurig.de
^ permalink raw reply
* Re: Possible WEP encryption error with wpa_supplicant -Dnl80211
From: Holger Schurig @ 2009-09-08 8:27 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <200909081016.37204.hs4233@mail.mn-solutions.de>
> IEEE 802.11
> Type/Subtype: Data (32)
> Frame Control: 0x0108 (Normal)
> Version: 0
> Type: Data frame (2)
> Subtype: 0
> Flags: 0x1
> DS status: Frame from STA to DS via an AP (To DS: 1 From DS: 0) (0x01)
> .... .0.. = More Fragments: This is the last fragment
> .... 0... = Retry: Frame is not being retransmitted
> ...0 .... = PWR MGT: STA will stay up
> ..0. .... = More Data: No data buffered
> .0.. .... = Protected flag: Data is not protected
> 0... .... = Order flag: Not strictly ordered
> Duration: 213
> BSS Id: 00:1b:53:11:dc:40 (00:1b:53:11:dc:40)
> Source address: Proxim_a0:6d:40 (00:20:a6:a0:6d:40)
> Destination address: Broadcast (ff:ff:ff:ff:ff:ff)
> Fragment number: 0
> Sequence number: 120
When I run wpa_supplicant with -D wext, I see this additional
field while monitoring:
WEP parameters
Initialization Vector: 0x222e52
Key Index: 0
WEP ICV: 0x9dc1791b (not verified)
--
http://www.holgerschurig.de
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox