From colin at cozybit.com  Fri Jan  2 22:00:20 2009
From: colin at cozybit.com (Colin McCabe)
Date: Fri,  2 Jan 2009 19:00:20 -0800
Subject: [PATCH v2 0/3] libertas: driver for GSPI devices
Message-ID: <1230951623-26998-1-git-send-email-colin@cozybit.com>


This patch series adds suport for GSPI devices to libertas.
These devices are found in some embedded systems. We used a blackfin-based
board for development.

Thanks to everyone who took a look at version 1 of the patch.

Changes in v2: 
* Store the host IRQ setting in spi->irq rather than creating a new variable
for this purpose.
* Add TODO comment to declaration of card->gpio_cs.
(We do intend to get rid of gpio_cs eventually, but it will require some
changes to the generic SPI layer, which could take a while.)
* When loading the module, check to see if the firmware is already loaded. If
so, skip firmware load.
* Speed up module load time slightly.
* Add if_spi_e2h to handle libertas card events.
* Include relevant Kconfig change.

thanks... and
Happy New Year.

Colin


From colin at cozybit.com  Fri Jan  2 22:00:21 2009
From: colin at cozybit.com (Colin McCabe)
Date: Fri,  2 Jan 2009 19:00:21 -0800
Subject: [PATCH v2 1/3] libertas: Fix alignment issues in libertas core
In-Reply-To: <1230951623-26998-1-git-send-email-colin@cozybit.com>
References: <1230951623-26998-1-git-send-email-colin@cozybit.com>
Message-ID: <1230951623-26998-2-git-send-email-colin@cozybit.com>

When loading fields from packed structs, use get_unaligned_le16 and
get_unaligned_le32 instead of le16_to_cpu and le32_to_cpu.
This doesn't matter on x86, but it is important for some other CPUs.

Also, mark all packed structs as packed. Generally, any data structure
that comes over the wire from the WLAN firmware should be a packed struct.

Signed-off-by: Colin McCabe <colin at cozybit.com>
Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
---
 drivers/net/wireless/libertas/11d.c        |   19 ++++---
 drivers/net/wireless/libertas/assoc.c      |   11 ++--
 drivers/net/wireless/libertas/cmd.c        |   87 +++++++++++++++------------
 drivers/net/wireless/libertas/cmdresp.c    |   54 +++++++++++------
 drivers/net/wireless/libertas/debugfs.c    |    7 +-
 drivers/net/wireless/libertas/ethtool.c    |   19 ++++---
 drivers/net/wireless/libertas/hostcmd.h    |   89 ++++++++++++++--------------
 drivers/net/wireless/libertas/main.c       |   12 +++-
 drivers/net/wireless/libertas/persistcfg.c |    5 +-
 drivers/net/wireless/libertas/rx.c         |    1 +
 drivers/net/wireless/libertas/scan.c       |   11 ++--
 drivers/net/wireless/libertas/tx.c         |    7 ++-
 drivers/net/wireless/libertas/wext.c       |    7 +-
 13 files changed, 186 insertions(+), 143 deletions(-)

diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c
index 4bc46a6..c0e4a3c 100644
--- a/drivers/net/wireless/libertas/11d.c
+++ b/drivers/net/wireless/libertas/11d.c
@@ -1,6 +1,7 @@
 /**
   * This file contains functions for 802.11D.
   */
+#include <asm/unaligned.h>
 #include <linux/ctype.h>
 #include <linux/kernel.h>
 #include <linux/wireless.h>
@@ -515,7 +516,7 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
 		cmd->size =
 		    cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
 		lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
-			le16_to_cpu(cmd->size));
+			get_unaligned_le16(&cmd->size));
 		goto done;
 	}
 
@@ -532,15 +533,16 @@ int lbs_cmd_802_11d_domain_info(struct lbs_private *priv,
 		       nr_subband * sizeof(struct ieeetypes_subbandset));
 
 		cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) +
-					     le16_to_cpu(domain->header.len) +
-					     sizeof(struct mrvlietypesheader) +
-					     S_DS_GEN);
+				     get_unaligned_le16(&domain->header.len) +
+				     sizeof(struct mrvlietypesheader) +
+				     S_DS_GEN);
 	} else {
 		cmd->size =
 		    cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN);
 	}
 
-	lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, le16_to_cpu(cmd->size));
+	lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd,
+		    get_unaligned_le16(&cmd->size));
 
 done:
 	lbs_deb_enter(LBS_DEB_11D);
@@ -557,16 +559,17 @@ int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp)
 {
 	struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp;
 	struct mrvlietypes_domainparamset *domain = &domaininfo->domain;
-	u16 action = le16_to_cpu(domaininfo->action);
+	u16 action = get_unaligned_le16(&domaininfo->action);
 	s16 ret = 0;
 	u8 nr_subband = 0;
 
 	lbs_deb_enter(LBS_DEB_11D);
 
 	lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp,
-		(int)le16_to_cpu(resp->size));
+		(int)get_unaligned_le16(&resp->size));
 
-	nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) /
+	nr_subband = (get_unaligned_le16(&domain->header.len) -
+				COUNTRY_CODE_LEN) /
 		      sizeof(struct ieeetypes_subbandset);
 
 	lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband);
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index a9aedf3..c43a14f 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -1,5 +1,6 @@
 /* Copyright (C) 2006, Red Hat, Inc. */
 
+#include <asm/unaligned.h>
 #include <linux/types.h>
 #include <linux/etherdevice.h>
 #include <linux/ieee80211.h>
@@ -264,7 +265,7 @@ static int lbs_adhoc_join(struct lbs_private *priv,
 	cmd.bss.ssparamset.ibssparamset.atimwindow = cpu_to_le16(bss->atimwindow);
 
 	if (assoc_req->secinfo.wep_enabled) {
-		u16 tmp = le16_to_cpu(cmd.bss.capability);
+		u16 tmp = get_unaligned_le16(&cmd.bss.capability);
 		tmp |= WLAN_CAPABILITY_PRIVACY;
 		cmd.bss.capability = cpu_to_le16(tmp);
 	}
@@ -1707,7 +1708,7 @@ int lbs_ret_80211_associate(struct lbs_private *priv,
 	 *                                    association response from the AP)
 	 */
 
-	status_code = le16_to_cpu(passocrsp->statuscode);
+	status_code = get_unaligned_le16(&passocrsp->statuscode);
 	switch (status_code) {
 	case 0x00:
 		break;
@@ -1739,7 +1740,7 @@ int lbs_ret_80211_associate(struct lbs_private *priv,
 	}
 
 	lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", (void *)&resp->params,
-		le16_to_cpu(resp->size) - S_DS_GEN);
+		get_unaligned_le16(&resp->size) - S_DS_GEN);
 
 	/* Send a Media Connected event, according to the Spec */
 	priv->connect_status = LBS_CONNECTED;
@@ -1773,8 +1774,8 @@ done:
 static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp)
 {
 	int ret = 0;
-	u16 command = le16_to_cpu(resp->command);
-	u16 result = le16_to_cpu(resp->result);
+	u16 command = get_unaligned_le16(&resp->command);
+	u16 result = get_unaligned_le16(&resp->result);
 	struct cmd_ds_802_11_ad_hoc_result *adhoc_resp;
 	union iwreq_data wrqu;
 	struct bss_descriptor *bss;
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index ac73050..7c77d00 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -3,6 +3,7 @@
   * It prepares command and sends it to firmware when it is ready.
   */
 
+#include <asm/unaligned.h>
 #include <net/iw_handler.h>
 #include <net/lib80211.h>
 #include <linux/kfifo.h>
@@ -34,7 +35,8 @@ int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
 	struct cmd_header *buf = (void *)extra;
 	uint16_t copy_len;
 
-	copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size));
+	copy_len = min(get_unaligned_le16(&buf->size),
+			get_unaligned_le16(&resp->size));
 	memcpy(buf, resp, copy_len);
 	return 0;
 }
@@ -98,11 +100,11 @@ int lbs_update_hw_spec(struct lbs_private *priv)
 	if (ret)
 		goto out;
 
-	priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo);
+	priv->fwcapinfo = get_unaligned_le32(&cmd.fwcapinfo);
 
 	/* The firmware release is in an interesting format: the patch
 	 * level is in the most significant nibble ... so fix that: */
-	priv->fwrelease = le32_to_cpu(cmd.fwrelease);
+	priv->fwrelease = get_unaligned_le32(&cmd.fwrelease);
 	priv->fwrelease = (priv->fwrelease << 8) |
 		(priv->fwrelease >> 24 & 0xff);
 
@@ -124,7 +126,7 @@ int lbs_update_hw_spec(struct lbs_private *priv)
 	 * only ever be 8-bit, even though the field size is 16-bit.  Some firmware
 	 * returns non-zero high 8 bits here.
 	 */
-	priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF;
+	priv->regioncode = get_unaligned_le16(&cmd.regioncode) & 0xFF;
 
 	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
 		/* use the region code to search for the index */
@@ -253,7 +255,7 @@ int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv,
 	ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd);
 
 	if (!ret)
-		*timeout = le16_to_cpu(cmd.timeout);
+		*timeout = get_unaligned_le16(&cmd.timeout);
 
 	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return 0;
@@ -285,16 +287,17 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
 	if (!ret) {
 		lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, "
 			    "calcontrol 0x%x extsleepclk 0x%x\n",
-			    le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset),
-			    le16_to_cpu(cmd.stabletime), cmd.calcontrol,
-			    cmd.externalsleepclk);
-
-		sp->sp_error = le16_to_cpu(cmd.error);
-		sp->sp_offset = le16_to_cpu(cmd.offset);
-		sp->sp_stabletime = le16_to_cpu(cmd.stabletime);
+			    get_unaligned_le16(&cmd.error),
+			    get_unaligned_le16(&cmd.offset),
+			    get_unaligned_le16(&cmd.stabletime),
+			    cmd.calcontrol, cmd.externalsleepclk);
+
+		sp->sp_error = get_unaligned_le16(&cmd.error);
+		sp->sp_offset = get_unaligned_le16(&cmd.offset);
+		sp->sp_stabletime = get_unaligned_le16(&cmd.stabletime);
 		sp->sp_calcontrol = cmd.calcontrol;
 		sp->sp_extsleepclk = cmd.externalsleepclk;
-		sp->sp_reserved = le16_to_cpu(cmd.reserved);
+		sp->sp_reserved = get_unaligned_le16(&cmd.reserved);
 	}
 
 	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
@@ -385,7 +388,7 @@ int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action,
 
 	ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd);
 	if (!ret && cmd_action == CMD_ACT_GET)
-		*enable = le16_to_cpu(cmd.enable);
+		*enable = get_unaligned_le16(&cmd.enable);
 
 	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
 	return ret;
@@ -455,10 +458,14 @@ int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action,
 		while (buf_ptr < resp_end) {
 			struct MrvlIEtype_keyParamSet *keyparam = buf_ptr;
 			struct enc_key *key;
-			uint16_t param_set_len = le16_to_cpu(keyparam->length);
-			uint16_t key_len = le16_to_cpu(keyparam->keylen);
-			uint16_t key_flags = le16_to_cpu(keyparam->keyinfo);
-			uint16_t key_type = le16_to_cpu(keyparam->keytypeid);
+			uint16_t param_set_len =
+				get_unaligned_le16(&keyparam->length);
+			uint16_t key_len =
+				get_unaligned_le16(&keyparam->keylen);
+			uint16_t key_flags =
+				get_unaligned_le16(&keyparam->keyinfo);
+			uint16_t key_type =
+				get_unaligned_le16(&keyparam->keytypeid);
 			void *end;
 
 			end = (void *)keyparam + sizeof(keyparam->type)
@@ -533,7 +540,8 @@ int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val)
 	}
 
 	lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n",
-		    le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val);
+		    get_unaligned_le16(&cmd.oid),
+		    get_unaligned_le16(&cmd.bufsize), val);
 
 	ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd);
 
@@ -567,7 +575,7 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
 	if (ret)
 		goto out;
 
-	switch (le16_to_cpu(cmd.bufsize)) {
+	switch (get_unaligned_le16(&cmd.bufsize)) {
 	case sizeof(u8):
 		if (oid == SNMP_MIB_OID_BSS_TYPE) {
 			if (cmd.value[0] == 2)
@@ -582,7 +590,7 @@ int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val)
 		break;
 	default:
 		lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n",
-		            oid, le16_to_cpu(cmd.bufsize));
+				oid, get_unaligned_le16(&cmd.bufsize));
 		break;
 	}
 
@@ -615,7 +623,7 @@ int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel,
 
 	ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd);
 	if (ret == 0) {
-		*curlevel = le16_to_cpu(cmd.curlevel);
+		*curlevel = get_unaligned_le16(&cmd.curlevel);
 		if (minlevel)
 			*minlevel = cmd.minlevel;
 		if (maxlevel)
@@ -719,8 +727,8 @@ int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv,
 	cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto);
 	ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd);
 	if (!ret && cmd_action == CMD_ACT_GET) {
-		priv->ratebitmap = le16_to_cpu(cmd.bitmap);
-		priv->enablehwauto = le16_to_cpu(cmd.enablehwauto);
+		priv->ratebitmap = get_unaligned_le16(&cmd.bitmap);
+		priv->enablehwauto = get_unaligned_le16(&cmd.enablehwauto);
 	}
 
 	lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
@@ -800,7 +808,7 @@ int lbs_get_channel(struct lbs_private *priv)
 	if (ret)
 		goto out;
 
-	ret = le16_to_cpu(cmd.channel);
+	ret = get_unaligned_le16(&cmd.channel);
 	lbs_deb_cmd("current radio channel is %d\n", ret);
 
 out:
@@ -851,7 +859,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel)
 	if (ret)
 		goto out;
 
-	priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel);
+	priv->curbssparams.channel = (uint8_t)get_unaligned_le16(&cmd.channel);
 	lbs_deb_cmd("channel switch from %d to %d\n", old_channel,
 		priv->curbssparams.channel);
 
@@ -890,7 +898,7 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
 
 	offval = (struct lbs_offset_value *)pdata_buf;
 
-	switch (le16_to_cpu(cmdptr->command)) {
+	switch (get_unaligned_le16(&cmdptr->command)) {
 	case CMD_MAC_REG_ACCESS:
 		{
 			struct cmd_ds_mac_reg_access *macreg;
@@ -1151,7 +1159,8 @@ static void lbs_queue_cmd(struct lbs_private *priv,
 	cmdnode->result = 0;
 
 	/* Exit_PS command needs to be queued in the header always. */
-	if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) {
+	if (get_unaligned_le16(&cmdnode->cmdbuf->command) ==
+		    CMD_802_11_PS_MODE) {
 		struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1];
 
 		if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) {
@@ -1170,7 +1179,7 @@ static void lbs_queue_cmd(struct lbs_private *priv,
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 
 	lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n",
-		     le16_to_cpu(cmdnode->cmdbuf->command));
+		     get_unaligned_le16(&cmdnode->cmdbuf->command));
 
 done:
 	lbs_deb_leave(LBS_DEB_HOST);
@@ -1195,8 +1204,8 @@ static void lbs_submit_command(struct lbs_private *priv,
 	priv->cur_cmd_retcode = 0;
 	spin_unlock_irqrestore(&priv->driver_lock, flags);
 
-	cmdsize = le16_to_cpu(cmd->size);
-	command = le16_to_cpu(cmd->command);
+	cmdsize = get_unaligned_le16(&cmd->size);
+	command = get_unaligned_le16(&cmd->command);
 
 	/* These commands take longer */
 	if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE ||
@@ -1204,7 +1213,7 @@ static void lbs_submit_command(struct lbs_private *priv,
 		timeo = 5 * HZ;
 
 	lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n",
-		     command, le16_to_cpu(cmd->seqnum), cmdsize);
+		     command, get_unaligned_le16(&cmd->seqnum), cmdsize);
 	lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize);
 
 	ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize);
@@ -1462,7 +1471,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
 
 #define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
 			cmdptr->size =
-			    cpu_to_le16(le16_to_cpu(gpio->header.len)
+			    cpu_to_le16(get_unaligned_le16(&gpio->header.len)
 				+ S_DS_GEN
 				+ ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
 			gpio->header.len = gpio->header.len;
@@ -1687,19 +1696,21 @@ int lbs_execute_next_command(struct lbs_private *priv)
 	if (cmdnode) {
 		cmd = cmdnode->cmdbuf;
 
-		if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) {
+		if (is_command_allowed_in_ps(
+				get_unaligned_le16(&cmd->command))) {
 			if ((priv->psstate == PS_STATE_SLEEP) ||
 			    (priv->psstate == PS_STATE_PRE_SLEEP)) {
 				lbs_deb_host(
 				       "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n",
-				       le16_to_cpu(cmd->command),
+				       get_unaligned_le16(&cmd->command),
 				       priv->psstate);
 				ret = -1;
 				goto done;
 			}
 			lbs_deb_host("EXEC_NEXT_CMD: OK to send command "
-				     "0x%04x in psstate %d\n",
-				     le16_to_cpu(cmd->command), priv->psstate);
+					"0x%04x in psstate %d\n",
+					get_unaligned_le16(&cmd->command),
+					priv->psstate);
 		} else if (priv->psstate != PS_STATE_FULL_POWER) {
 			/*
 			 * 1. Non-PS command:
@@ -1769,7 +1780,7 @@ int lbs_execute_next_command(struct lbs_private *priv)
 		}
 		list_del(&cmdnode->list);
 		lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
-			    le16_to_cpu(cmd->command));
+			    get_unaligned_le16(&cmd->command));
 		lbs_submit_command(priv, cmdnode);
 	} else {
 		/*
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index bcf2a97..14f54ad 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -2,6 +2,7 @@
   * This file contains the handling of command
   * responses as well as events generated by firmware.
   */
+#include <asm/unaligned.h>
 #include <linux/delay.h>
 #include <linux/if_arp.h>
 #include <linux/netdevice.h>
@@ -115,8 +116,10 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
 		{
 			struct cmd_ds_mac_reg_access *reg = &resp->params.macreg;
 
-			priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
-			priv->offsetvalue.value = le32_to_cpu(reg->value);
+			priv->offsetvalue.offset =
+				(u32)get_unaligned_le16(&reg->offset);
+			priv->offsetvalue.value =
+				get_unaligned_le32(&reg->value);
 			break;
 		}
 
@@ -124,7 +127,8 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
 		{
 			struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg;
 
-			priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
+			priv->offsetvalue.offset =
+				(u32)get_unaligned_le16(&reg->offset);
 			priv->offsetvalue.value = reg->value;
 			break;
 		}
@@ -133,7 +137,8 @@ static int lbs_ret_reg_access(struct lbs_private *priv,
 		{
 			struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg;
 
-			priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset);
+			priv->offsetvalue.offset =
+				(u32)get_unaligned_le16(&reg->offset);
 			priv->offsetvalue.value = reg->value;
 			break;
 		}
@@ -154,11 +159,15 @@ static int lbs_ret_802_11_rssi(struct lbs_private *priv,
 	lbs_deb_enter(LBS_DEB_CMD);
 
 	/* store the non average value */
-	priv->SNR[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->SNR);
-	priv->NF[TYPE_BEACON][TYPE_NOAVG] = le16_to_cpu(rssirsp->noisefloor);
+	priv->SNR[TYPE_BEACON][TYPE_NOAVG] =
+		get_unaligned_le16(&rssirsp->SNR);
+	priv->NF[TYPE_BEACON][TYPE_NOAVG] =
+		get_unaligned_le16(&rssirsp->noisefloor);
 
-	priv->SNR[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgSNR);
-	priv->NF[TYPE_BEACON][TYPE_AVG] = le16_to_cpu(rssirsp->avgnoisefloor);
+	priv->SNR[TYPE_BEACON][TYPE_AVG] =
+		get_unaligned_le16(&rssirsp->avgSNR);
+	priv->NF[TYPE_BEACON][TYPE_AVG] =
+		get_unaligned_le16(&rssirsp->avgnoisefloor);
 
 	priv->RSSI[TYPE_BEACON][TYPE_NOAVG] =
 	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
@@ -185,8 +194,10 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
 	lbs_deb_enter(LBS_DEB_CMD);
 
 	if (bcn_ctrl->action == CMD_ACT_GET) {
-		priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable);
-		priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period);
+		priv->beacon_enable =
+			(u8) get_unaligned_le16(&bcn_ctrl->beacon_enable);
+		priv->beacon_period =
+			get_unaligned_le16(&bcn_ctrl->beacon_period);
 	}
 
 	lbs_deb_enter(LBS_DEB_CMD);
@@ -199,7 +210,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
 	struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response;
 	int ret = 0;
 	unsigned long flags;
-	uint16_t respcmd = le16_to_cpu(resp->command);
+	uint16_t respcmd = get_unaligned_le16(&resp->command);
 
 	lbs_deb_enter(LBS_DEB_HOST);
 
@@ -276,7 +287,7 @@ static inline int handle_cmd_response(struct lbs_private *priv,
 
 	default:
 		lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n",
-			   le16_to_cpu(resp->command));
+			   get_unaligned_le16(&resp->command));
 		break;
 	}
 	lbs_deb_leave(LBS_DEB_HOST);
@@ -304,17 +315,19 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
 	}
 
 	resp = (void *)data;
-	curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command);
-	respcmd = le16_to_cpu(resp->command);
-	result = le16_to_cpu(resp->result);
+	curcmd = get_unaligned_le16(&priv->cur_cmd->cmdbuf->command);
+	respcmd = get_unaligned_le16(&resp->command);
+	result = get_unaligned_le16(&resp->result);
 
 	lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n",
-		     respcmd, le16_to_cpu(resp->seqnum), len);
+		     respcmd, get_unaligned_le16(&resp->seqnum), len);
 	lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len);
 
 	if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) {
 		lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n",
-			    le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum));
+			    get_unaligned_le16(&resp->seqnum),
+			    get_unaligned_le16(&priv->cur_cmd->cmdbuf->
+					       seqnum));
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		ret = -1;
 		goto done;
@@ -330,8 +343,9 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
 	if (resp->result == cpu_to_le16(0x0004)) {
 		/* 0x0004 means -EAGAIN. Drop the response, let it time out
 		   and be resubmitted */
-		lbs_pr_info("Firmware returns DEFER to command %x. Will let it time out...\n",
-			    le16_to_cpu(resp->command));
+		lbs_pr_info("Firmware returns DEFER to command %x. "
+			    "Will let it time out...\n",
+			    get_unaligned_le16(&resp->command));
 		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		ret = -1;
 		goto done;
@@ -351,7 +365,7 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len)
 
 	if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) {
 		struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1];
-		u16 action = le16_to_cpu(psmode->action);
+		u16 action = get_unaligned_le16(&psmode->action);
 
 		lbs_deb_host(
 		       "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n",
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index de3c6ed..d1ed78c 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -1,3 +1,4 @@
+#include <asm/unaligned.h>
 #include <linux/module.h>
 #include <linux/dcache.h>
 #include <linux/debugfs.h>
@@ -195,7 +196,7 @@ static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size)
 			return NULL;
 		if (tlv_h->type == cpu_to_le16(tlv_type))
 			return tlv_h;
-		length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h);
+		length = get_unaligned_le16(&tlv_h->len) + sizeof(*tlv_h);
 		pos += length;
 		tlv += length;
 	}
@@ -238,7 +239,7 @@ static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask,
 	if (got) {
 		value = got->value;
 		freq  = got->freq;
-		events = le16_to_cpu(subscribed->events);
+		events = get_unaligned_le16(&subscribed->events);
 
 		pos += snprintf(buf, len, "%d %d %d\n", value, freq,
 				!!(events & event_mask));
@@ -296,7 +297,7 @@ static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask,
 	if (ret)
 		goto out_events;
 
-	curr_mask = le16_to_cpu(events->events);
+	curr_mask = get_unaligned_le16(&events->events);
 
 	if (new_mask)
 		new_mask = curr_mask | event_mask;
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 73b414f..807f2ae 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -1,3 +1,4 @@
+#include <asm/unaligned.h>
 #include <linux/netdevice.h>
 #include <linux/ethtool.h>
 #include <linux/delay.h>
@@ -90,14 +91,16 @@ static void lbs_ethtool_get_stats(struct net_device *dev,
 		return;
 	}
 
-	priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
-	priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
-	priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
-	priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
-	priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
-	priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
-	priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
-	priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
+	priv->mstats.fwd_drop_rbt = get_unaligned_le32(&mesh_access.data[0]);
+	priv->mstats.fwd_drop_ttl = get_unaligned_le32(&mesh_access.data[1]);
+	priv->mstats.fwd_drop_noroute =
+		get_unaligned_le32(&mesh_access.data[2]);
+	priv->mstats.fwd_drop_nobuf = get_unaligned_le32(&mesh_access.data[3]);
+	priv->mstats.fwd_unicast_cnt =
+		get_unaligned_le32(&mesh_access.data[4]);
+	priv->mstats.fwd_bcast_cnt = get_unaligned_le32(&mesh_access.data[5]);
+	priv->mstats.drop_blind = get_unaligned_le32(&mesh_access.data[6]);
+	priv->mstats.tx_failed_cnt = get_unaligned_le32(&mesh_access.data[7]);
 
 	data[0] = priv->mstats.fwd_drop_rbt;
 	data[1] = priv->mstats.fwd_drop_ttl;
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index e173b1b..c6d5771 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -32,7 +32,7 @@ struct txpd {
 	u8 pktdelay_2ms;
 	/* reserved */
 	u8 reserved1;
-};
+} __attribute__ ((packed));
 
 /* RxPD Descriptor */
 struct rxpd {
@@ -63,7 +63,7 @@ struct rxpd {
 	/* Pkt Priority */
 	u8 priority;
 	u8 reserved[3];
-};
+} __attribute__ ((packed));
 
 struct cmd_header {
 	__le16 command;
@@ -107,7 +107,7 @@ struct cmd_ds_gen {
 	__le16 seqnum;
 	__le16 result;
 	void *cmdresp[0];
-};
+} __attribute__ ((packed));
 
 #define S_DS_GEN sizeof(struct cmd_ds_gen)
 
@@ -163,7 +163,7 @@ struct cmd_ds_802_11_subscribe_event {
 	 * bump this up a bit.
 	 */
 	uint8_t tlv[128];
-};
+} __attribute__ ((packed));
 
 /*
  * This scan handle Country Information IE(802.11d compliant)
@@ -180,7 +180,7 @@ struct cmd_ds_802_11_scan {
 	mrvlietypes_chanlistparamset_t ChanListParamSet;
 	mrvlietypes_ratesparamset_t OpRateSet;
 #endif
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_scan_rsp {
 	struct cmd_header hdr;
@@ -188,7 +188,7 @@ struct cmd_ds_802_11_scan_rsp {
 	__le16 bssdescriptsize;
 	uint8_t nr_sets;
 	uint8_t bssdesc_and_tlvbuffer[0];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_get_log {
 	struct cmd_header hdr;
@@ -206,33 +206,33 @@ struct cmd_ds_802_11_get_log {
 	__le32 fcserror;
 	__le32 txframe;
 	__le32 wepundecryptable;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_control {
 	struct cmd_header hdr;
 	__le16 action;
 	u16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_multicast_adr {
 	struct cmd_header hdr;
 	__le16 action;
 	__le16 nr_of_adrs;
 	u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_authenticate {
 	u8 macaddr[ETH_ALEN];
 	u8 authtype;
 	u8 reserved[10];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_deauthenticate {
 	struct cmd_header hdr;
 
 	u8 macaddr[ETH_ALEN];
 	__le16 reasoncode;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_associate {
 	u8 peerstaaddr[6];
@@ -251,7 +251,7 @@ struct cmd_ds_802_11_associate {
 
 struct cmd_ds_802_11_associate_rsp {
 	struct ieeetypes_assocrsp assocRsp;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_set_wep {
 	struct cmd_header hdr;
@@ -265,7 +265,7 @@ struct cmd_ds_802_11_set_wep {
 	/* 40, 128bit or TXWEP */
 	uint8_t keytype[4];
 	uint8_t keymaterial[4][16];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_3_get_stat {
 	__le32 xmitok;
@@ -274,7 +274,7 @@ struct cmd_ds_802_3_get_stat {
 	__le32 rcverror;
 	__le32 rcvnobuffer;
 	__le32 rcvcrcerror;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_get_stat {
 	__le32 txfragmentcnt;
@@ -294,7 +294,7 @@ struct cmd_ds_802_11_get_stat {
 	__le32 txbeacon;
 	__le32 rxbeacon;
 	__le32 wepundecryptable;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_snmp_mib {
 	struct cmd_header hdr;
@@ -303,58 +303,58 @@ struct cmd_ds_802_11_snmp_mib {
 	__le16 oid;
 	__le16 bufsize;
 	u8 value[128];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_reg_map {
 	__le16 buffersize;
 	u8 regmap[128];
 	__le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_bbp_reg_map {
 	__le16 buffersize;
 	u8 regmap[128];
 	__le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_rf_reg_map {
 	__le16 buffersize;
 	u8 regmap[64];
 	__le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_reg_access {
 	__le16 action;
 	__le16 offset;
 	__le32 value;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_bbp_reg_access {
 	__le16 action;
 	__le16 offset;
 	u8 value;
 	u8 reserved[3];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_rf_reg_access {
 	__le16 action;
 	__le16 offset;
 	u8 value;
 	u8 reserved[3];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_radio_control {
 	struct cmd_header hdr;
 
 	__le16 action;
 	__le16 control;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_beacon_control {
 	__le16 action;
 	__le16 beacon_enable;
 	__le16 beacon_period;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_sleep_params {
 	struct cmd_header hdr;
@@ -379,7 +379,7 @@ struct cmd_ds_802_11_sleep_params {
 
 	/* reserved field, should be set to zero */
 	__le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_inactivity_timeout {
 	struct cmd_header hdr;
@@ -389,7 +389,7 @@ struct cmd_ds_802_11_inactivity_timeout {
 
 	/* Inactivity timeout in msec */
 	__le16 timeout;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rf_channel {
 	struct cmd_header hdr;
@@ -399,7 +399,7 @@ struct cmd_ds_802_11_rf_channel {
 	__le16 rftype;      /* unused */
 	__le16 reserved;    /* unused */
 	u8 channellist[32]; /* unused */
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rssi {
 	/* weighting factor */
@@ -408,21 +408,21 @@ struct cmd_ds_802_11_rssi {
 	__le16 reserved_0;
 	__le16 reserved_1;
 	__le16 reserved_2;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rssi_rsp {
 	__le16 SNR;
 	__le16 noisefloor;
 	__le16 avgSNR;
 	__le16 avgnoisefloor;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_mac_address {
 	struct cmd_header hdr;
 
 	__le16 action;
 	u8 macadd[ETH_ALEN];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rf_tx_power {
 	struct cmd_header hdr;
@@ -431,7 +431,7 @@ struct cmd_ds_802_11_rf_tx_power {
 	__le16 curlevel;
 	s8 maxlevel;
 	s8 minlevel;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rf_antenna {
 	__le16 action;
@@ -439,33 +439,33 @@ struct cmd_ds_802_11_rf_antenna {
 	/* Number of antennas or 0xffff(diversity) */
 	__le16 antennamode;
 
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_monitor_mode {
 	__le16 action;
 	__le16 mode;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_set_boot2_ver {
 	struct cmd_header hdr;
 
 	__le16 action;
 	__le16 version;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_fw_wake_method {
 	struct cmd_header hdr;
 
 	__le16 action;
 	__le16 method;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_sleep_period {
 	struct cmd_header hdr;
 
 	__le16 action;
 	__le16 period;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_ps_mode {
 	__le16 action;
@@ -473,7 +473,7 @@ struct cmd_ds_802_11_ps_mode {
 	__le16 multipledtim;
 	__le16 reserved;
 	__le16 locallisteninterval;
-};
+} __attribute__ ((packed));
 
 struct cmd_confirm_sleep {
 	struct cmd_header hdr;
@@ -483,7 +483,7 @@ struct cmd_confirm_sleep {
 	__le16 multipledtim;
 	__le16 reserved;
 	__le16 locallisteninterval;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_data_rate {
 	struct cmd_header hdr;
@@ -491,14 +491,14 @@ struct cmd_ds_802_11_data_rate {
 	__le16 action;
 	__le16 reserved;
 	u8 rates[MAX_RATES];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rate_adapt_rateset {
 	struct cmd_header hdr;
 	__le16 action;
 	__le16 enablehwauto;
 	__le16 bitmap;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_ad_hoc_start {
 	struct cmd_header hdr;
@@ -520,7 +520,7 @@ struct cmd_ds_802_11_ad_hoc_result {
 
 	u8 pad[3];
 	u8 bssid[ETH_ALEN];
-};
+} __attribute__ ((packed));
 
 struct adhoc_bssdesc {
 	u8 bssid[ETH_ALEN];
@@ -578,7 +578,7 @@ struct MrvlIEtype_keyParamSet {
 
 	/* key material of size keylen */
 	u8 key[32];
-};
+} __attribute__ ((packed));
 
 #define MAX_WOL_RULES 		16
 
@@ -590,7 +590,7 @@ struct host_wol_rule {
 	__le16 reserve;
 	__be32 sig_mask;
 	__be32 signature;
-};
+} __attribute__ ((packed));
 
 struct wol_config {
 	uint8_t action;
@@ -598,8 +598,7 @@ struct wol_config {
 	uint8_t no_rules_in_cmd;
 	uint8_t result;
 	struct host_wol_rule rule[MAX_WOL_RULES];
-};
-
+} __attribute__ ((packed));
 
 struct cmd_ds_host_sleep {
 	struct cmd_header hdr;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 6fb5935..3b8cb29 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -4,6 +4,7 @@
   * thread etc..
   */
 
+#include <asm/unaligned.h>
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
@@ -232,7 +233,8 @@ static ssize_t lbs_anycast_get(struct device *dev,
 	if (ret)
 		return ret;
 
-	return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
+	return snprintf(buf, 12, "0x%X\n",
+			get_unaligned_le32(&mesh_access.data[0]));
 }
 
 /**
@@ -844,7 +846,8 @@ static int lbs_thread(void *data)
 			if (++priv->nr_retries > 3) {
 				lbs_pr_info("Excessive timeouts submitting "
 					"command 0x%04x\n",
-					le16_to_cpu(cmdnode->cmdbuf->command));
+					get_unaligned_le16(&cmdnode->cmdbuf->
+							   command));
 				lbs_complete_command(priv, cmdnode, -ETIMEDOUT);
 				priv->nr_retries = 0;
 				if (priv->reset_card)
@@ -854,7 +857,8 @@ static int lbs_thread(void *data)
 				priv->dnld_sent = DNLD_RES_RECEIVED;
 				lbs_pr_info("requeueing command 0x%04x due "
 					"to timeout (#%d)\n",
-					le16_to_cpu(cmdnode->cmdbuf->command),
+					get_unaligned_le16(&cmdnode->cmdbuf->
+							   command),
 					priv->nr_retries);
 
 				/* Stick it back at the _top_ of the pending queue
@@ -1057,7 +1061,7 @@ static void command_timer_fn(unsigned long data)
 		goto out;
 
 	lbs_pr_info("command 0x%04x timed out\n",
-		le16_to_cpu(priv->cur_cmd->cmdbuf->command));
+		get_unaligned_le16(&priv->cur_cmd->cmdbuf->command));
 
 	priv->cmd_timed_out = 1;
 	wake_up_interruptible(&priv->waitq);
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c
index 56e2401..a098ee5 100644
--- a/drivers/net/wireless/libertas/persistcfg.c
+++ b/drivers/net/wireless/libertas/persistcfg.c
@@ -1,3 +1,4 @@
+#include <asm/unaligned.h>
 #include <linux/moduleparam.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
@@ -48,7 +49,7 @@ static ssize_t bootflag_get(struct device *dev,
 	if (ret)
 		return ret;
 
-	return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag));
+	return snprintf(buf, 12, "%d\n", get_unaligned_le32(&defs.bootflag));
 }
 
 /**
@@ -143,7 +144,7 @@ static ssize_t channel_get(struct device *dev,
 	if (ret)
 		return ret;
 
-	return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel));
+	return snprintf(buf, 12, "%d\n", get_unaligned_le16(&defs.channel));
 }
 
 /**
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 079e6aa..5798373 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -1,6 +1,7 @@
 /**
   * This file contains the handling of RX in wlan driver.
   */
+#include <asm/unaligned.h>
 #include <linux/etherdevice.h>
 #include <linux/types.h>
 
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index b0a2bdd..78e6af4 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -4,10 +4,10 @@
   * IOCTL handlers as well as command preperation and response routines
   *  for sending scan commands to the firmware.
   */
+#include <asm/unaligned.h>
 #include <linux/types.h>
 #include <linux/etherdevice.h>
 #include <linux/if_arp.h>
-#include <asm/unaligned.h>
 #include <net/lib80211.h>
 
 #include "host.h"
@@ -331,7 +331,7 @@ static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype,
 		    tlv - scan_cmd->tlvbuffer);
 
 	ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr,
-			le16_to_cpu(scan_cmd->hdr.size),
+			get_unaligned_le16(&scan_cmd->hdr.size),
 			lbs_ret_80211_scan, 0);
 
 out:
@@ -641,7 +641,8 @@ static int lbs_process_bss(struct bss_descriptor *bss,
 
 		case WLAN_EID_IBSS_PARAMS:
 			pibss = (struct ieeetypes_ibssparamset *) pos;
-			bss->atimwindow = le16_to_cpu(pibss->atimwindow);
+			bss->atimwindow =
+				get_unaligned_le16(&pibss->atimwindow);
 			memmove(&bss->ssparamset.ibssparamset, pibss,
 				sizeof(struct ieeetypes_ibssparamset));
 			lbs_deb_scan("got IBSS IE\n");
@@ -1132,10 +1133,10 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
 		goto done;
 	}
 
-	bytesleft = le16_to_cpu(scanresp->bssdescriptsize);
+	bytesleft = get_unaligned_le16(&scanresp->bssdescriptsize);
 	lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft);
 
-	scanrespsize = le16_to_cpu(resp->size);
+	scanrespsize = get_unaligned_le16(&resp->size);
 	lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets);
 
 	bssinfo = scanresp->bssdesc_and_tlvbuffer;
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index a4972fe..213a1a7 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -1,6 +1,7 @@
 /**
   * This file contains the handling of TX in wlan driver.
   */
+#include <asm/unaligned.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 
@@ -137,9 +138,11 @@ int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
 
-	lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
+	lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr,
+		    get_unaligned_le16(&txpd->tx_packet_length));
 
-	memcpy(&txpd[1], p802x_hdr, le16_to_cpu(txpd->tx_packet_length));
+	memcpy(&txpd[1], p802x_hdr,
+	       get_unaligned_le16(&txpd->tx_packet_length));
 
 	spin_lock_irqsave(&priv->driver_lock, flags);
 	priv->tx_pending_len = pkt_len + sizeof(struct txpd);
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 0d98343..e305a36 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -1,6 +1,7 @@
 /**
   * This file contains ioctl functions
   */
+#include <asm/unaligned.h>
 #include <linux/ctype.h>
 #include <linux/delay.h>
 #include <linux/if.h>
@@ -836,7 +837,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 	log.hdr.size = cpu_to_le16(sizeof(log));
 	lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
 
-	tx_retries = le32_to_cpu(log.retry);
+	tx_retries = get_unaligned_le32(&log.retry);
 
 	if (tx_retries > 75)
 		tx_qual = (90 - tx_retries) * POOR / 15;
@@ -852,9 +853,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 		    (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
 	quality = min(quality, tx_qual);
 
-	priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable);
+	priv->wstats.discard.code = get_unaligned_le32(&log.wepundecryptable);
 	priv->wstats.discard.retries = tx_retries;
-	priv->wstats.discard.misc = le32_to_cpu(log.ackfailure);
+	priv->wstats.discard.misc = get_unaligned_le32(&log.ackfailure);
 
 	/* Calculate quality */
 	priv->wstats.qual.qual = min_t(u8, quality, 100);
-- 
1.5.6.3



From colin at cozybit.com  Fri Jan  2 22:00:22 2009
From: colin at cozybit.com (Colin McCabe)
Date: Fri,  2 Jan 2009 19:00:22 -0800
Subject: [PATCH v2 2/3] libertas: Update libertas core with GSPI constants
In-Reply-To: <1230951623-26998-2-git-send-email-colin@cozybit.com>
References: <1230951623-26998-1-git-send-email-colin@cozybit.com>
	<1230951623-26998-2-git-send-email-colin@cozybit.com>
Message-ID: <1230951623-26998-3-git-send-email-colin@cozybit.com>

Add GSPI constants to libertas core.

Fix misleading comment in lbs_setup_firmware.

Signed-off-by: Colin McCabe <colin at cozybit.com>
Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
---
 drivers/net/wireless/libertas/host.h    |    1 +
 drivers/net/wireless/libertas/hostcmd.h |    8 ++++++++
 drivers/net/wireless/libertas/main.c    |    5 ++---
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 277ff19..d4457ef 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -66,6 +66,7 @@
 #define CMD_802_11_LED_GPIO_CTRL		0x004e
 #define CMD_802_11_EEPROM_ACCESS		0x0059
 #define CMD_802_11_BAND_CONFIG			0x0058
+#define CMD_GSPI_BUS_CONFIG			0x005a
 #define CMD_802_11D_DOMAIN_INFO			0x005b
 #define CMD_802_11_KEY_MATERIAL			0x005e
 #define CMD_802_11_SLEEP_PARAMS			0x0066
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index c6d5771..3c15611 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -221,6 +221,14 @@ struct cmd_ds_mac_multicast_adr {
 	u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
 } __attribute__ ((packed));
 
+struct cmd_ds_gspi_bus_config {
+	struct cmd_header hdr;
+	__le16 action;
+	__le16 bus_delay_mode;
+	__le16 host_time_delay_to_read_port;
+	__le16 host_time_delay_to_read_register;
+} __attribute__ ((packed));
+
 struct cmd_ds_802_11_authenticate {
 	u8 macaddr[ETH_ALEN];
 	u8 authtype;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 3b8cb29..69f7479 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1011,9 +1011,8 @@ void lbs_resume(struct lbs_private *priv)
 EXPORT_SYMBOL_GPL(lbs_resume);
 
 /**
- *  @brief This function downloads firmware image, gets
- *  HW spec from firmware and set basic parameters to
- *  firmware.
+ * @brief This function gets the HW spec from the firmware and sets
+ *        some basic parameters.
  *
  *  @param priv    A pointer to struct lbs_private structure
  *  @return 	   0 or -1
-- 
1.5.6.3



From colin at cozybit.com  Fri Jan  2 22:00:23 2009
From: colin at cozybit.com (Colin McCabe)
Date: Fri,  2 Jan 2009 19:00:23 -0800
Subject: [PATCH v2 3/3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <1230951623-26998-3-git-send-email-colin@cozybit.com>
References: <1230951623-26998-1-git-send-email-colin@cozybit.com>
	<1230951623-26998-2-git-send-email-colin@cozybit.com>
	<1230951623-26998-3-git-send-email-colin@cozybit.com>
Message-ID: <1230951623-26998-4-git-send-email-colin@cozybit.com>

Add initial support for libertas devices using a GSPI interface.  This has
been tested with the 8686.  At this time, as far as we know, GSPI firmware for
this device is not publicly distributable, but we expect this to change.

GSPI is intended to be used on embedded systems. Board-specific parameters are
required (see libertas_spi.h).

Signed-off-by: Colin McCabe <colin at cozybit.com>
Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
---
 drivers/net/wireless/Kconfig           |    6 +
 drivers/net/wireless/libertas/Makefile |    2 +
 drivers/net/wireless/libertas/defs.h   |    2 +
 drivers/net/wireless/libertas/if_spi.c | 1216 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/libertas/if_spi.h |  208 ++++++
 include/linux/spi/libertas_spi.h       |   25 +
 6 files changed, 1459 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/wireless/libertas/if_spi.c
 create mode 100644 drivers/net/wireless/libertas/if_spi.h
 create mode 100644 include/linux/spi/libertas_spi.h

diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index ea543fc..6f9ee26 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -151,6 +151,12 @@ config LIBERTAS_SDIO
 	---help---
 	  A driver for Marvell Libertas 8385 and 8686 SDIO devices.
 
+config LIBERTAS_SPI
+	tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
+	depends on LIBERTAS && SPI
+	---help---
+	  A driver for Marvell Libertas 8686 SPI devices.
+
 config LIBERTAS_DEBUG
 	bool "Enable full debugging output in the Libertas module."
 	depends on LIBERTAS
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index 02080a3..0b69185 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -4,8 +4,10 @@ libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o	\
 usb8xxx-objs += if_usb.o
 libertas_cs-objs += if_cs.o
 libertas_sdio-objs += if_sdio.o
+libertas_spi-objs += if_spi.o
 
 obj-$(CONFIG_LIBERTAS)     += libertas.o
 obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
 obj-$(CONFIG_LIBERTAS_CS)  += libertas_cs.o
 obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
+obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index b7744d6..0d1494f 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -41,6 +41,7 @@
 #define LBS_DEB_HEX	0x00200000
 #define LBS_DEB_SDIO	0x00400000
 #define LBS_DEB_SYSFS	0x00800000
+#define LBS_DEB_SPI	0x01000000
 
 extern unsigned int lbs_debug;
 
@@ -84,6 +85,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \
 #define lbs_deb_thread(fmt, args...)    LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
 #define lbs_deb_sdio(fmt, args...)      LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
 #define lbs_deb_sysfs(fmt, args...)     LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
+#define lbs_deb_spi(fmt, args...)       LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
 
 #define lbs_pr_info(format, args...) \
 	printk(KERN_INFO DRV_NAME": " format, ## args)
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
new file mode 100644
index 0000000..6092574
--- /dev/null
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -0,0 +1,1216 @@
+/*
+ *	linux/drivers/net/wireless/libertas/if_spi.c
+ *
+ *	Driver for Marvell SPI WLAN cards.
+ *
+ *	Copyright 2008 Analog Devices Inc.
+ *
+ *	Authors:
+ *	Andrey Yurovsky <andrey at cozybit.com>
+ *	Colin McCabe <colin at cozybit.com>
+ *
+ *	Inspired by if_sdio.c, Copyright 2007-2008 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/jiffies.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/spi/libertas_spi.h>
+#include <linux/spi/spi.h>
+
+#include "host.h"
+#include "decl.h"
+#include "defs.h"
+#include "dev.h"
+#include "if_spi.h"
+
+struct if_spi_packet {
+	struct list_head		list;
+	u16				blen;
+	u8				buffer[0] __attribute__((aligned(4)));
+};
+
+struct if_spi_card {
+	struct spi_device		*spi;
+	struct lbs_private		*priv;
+
+	char				helper_fw_name[FIRMWARE_NAME_MAX];
+	char				main_fw_name[FIRMWARE_NAME_MAX];
+
+	/* The card ID and card revision, as reported by the hardware. */
+	u16				card_id;
+	u8				card_rev;
+
+	/* Pin number for our GPIO chip-select. */
+	/* TODO: Once the generic SPI layer has some additional features, we
+	 * should take this out and use the normal chip select here.
+	 * We need support for chip select delays, and not dropping chipselect
+	 * after each word. */
+	int				gpio_cs;
+
+	/* The last time that we initiated an SPU operation */
+	unsigned long			prev_xfer_time;
+
+	int				use_dummy_writes;
+	unsigned long			spu_port_delay;
+	unsigned long			spu_reg_delay;
+
+	/* Handles all SPI communication (except for FW load) */
+	struct task_struct		*spi_thread;
+	int				run_thread;
+
+	/* Used to wake up the spi_thread */
+	struct semaphore		spi_ready;
+	struct semaphore		spi_thread_terminated;
+
+	u8				cmd_buffer[IF_SPI_CMD_BUF_SIZE];
+
+	/* A buffer of incoming packets from libertas core.
+	 * Since we can't sleep in hw_host_to_card, we have to buffer
+	 * them. */
+	struct list_head		cmd_packet_list;
+	struct list_head		data_packet_list;
+
+	/* Protects cmd_packet_list and data_packet_list */
+	spinlock_t			buffer_lock;
+};
+
+static void free_if_spi_card(struct if_spi_card *card)
+{
+	struct list_head *cursor, *next;
+	struct if_spi_packet *packet;
+
+	BUG_ON(card->run_thread);
+	list_for_each_safe(cursor, next, &card->cmd_packet_list) {
+		packet = container_of(cursor, struct if_spi_packet, list);
+		list_del(&packet->list);
+		kfree(packet);
+	}
+	list_for_each_safe(cursor, next, &card->data_packet_list) {
+		packet = container_of(cursor, struct if_spi_packet, list);
+		list_del(&packet->list);
+		kfree(packet);
+	}
+	spi_set_drvdata(card->spi, NULL);
+	kfree(card);
+}
+
+static struct chip_ident chip_id_to_device_name[] = {
+	{ .chip_id = 0x04, .name = 8385 },
+	{ .chip_id = 0x0b, .name = 8686 },
+};
+
+/*
+ * SPI Interface Unit Routines
+ *
+ * The SPU sits between the host and the WLAN module.
+ * All communication with the firmware is through SPU transactions.
+ *
+ * First we have to put a SPU register name on the bus. Then we can
+ * either read from or write to that register.
+ *
+ * For 16-bit transactions, byte order on the bus is big-endian.
+ * We don't have to worry about that here, though.
+ * The translation takes place in the SPI routines.
+ */
+
+static void spu_transaction_init(struct if_spi_card *card)
+{
+	if (!time_after(jiffies, card->prev_xfer_time + 1)) {
+		/* Unfortunately, the SPU requires a delay between successive
+		 * transactions. If our last transaction was more than a jiffy
+		 * ago, we have obviously already delayed enough.
+		 * If not, we have to busy-wait to be on the safe side. */
+		ndelay(400);
+	}
+	gpio_set_value(card->gpio_cs, 0); /* assert CS */
+}
+
+static void spu_transaction_finish(struct if_spi_card *card)
+{
+	gpio_set_value(card->gpio_cs, 1); /* drop CS */
+	card->prev_xfer_time = jiffies;
+}
+
+/* Write out a byte buffer to an SPI register,
+ * using a series of 16-bit transfers. */
+static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
+{
+	int n;
+	int err = 0;
+	u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK;
+
+	/* You must give an even number of bytes to the SPU, even if it
+	 * doesn't care about the last one.  */
+	BUG_ON(len & 0x1);
+
+	spu_transaction_init(card);
+
+	/* write SPU register index */
+	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
+	if (err)
+		goto out;
+
+	for (n = 0; n < len; n += sizeof(u16)) {
+		err = spi_write(card->spi, buf + n, sizeof(u16));
+		if (err)
+			goto out;
+	}
+
+out:
+	spu_transaction_finish(card);
+	return err;
+}
+
+static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val)
+{
+	return spu_write(card, reg, (u8 *)&val, sizeof(u16));
+}
+
+static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val)
+{
+	/* The lower 16 bits are written first. */
+	u16 out[2];
+	out[0] = val & 0xffff;
+	out[1] = (val & 0xffff0000) >> 16;
+	return spu_write(card, reg, (u8 *)&out, sizeof(u32));
+}
+
+static inline int spu_reg_is_port_reg(u16 reg)
+{
+	switch (reg) {
+	case IF_SPI_IO_RDWRPORT_REG:
+	case IF_SPI_CMD_RDWRPORT_REG:
+	case IF_SPI_DATA_RDWRPORT_REG:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
+{
+	unsigned int i, delay;
+	int n, err = 0;
+	u16 zero = 0;
+	u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK;
+
+	/* You must take an even number of bytes from the SPU, even if you
+	 * don't care about the last one.  */
+	BUG_ON(len & 0x1);
+
+	spu_transaction_init(card);
+
+	/* write SPU register index */
+	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
+	if (err)
+		return err;
+
+	delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay :
+						card->spu_reg_delay;
+	if (card->use_dummy_writes) {
+		/* Clock in dummy cycles while the SPU fills the FIFO */
+		for (i = 0; i < delay / 16; ++i) {
+			err = spi_write(card->spi, (u8 *)&zero, sizeof(u16));
+			if (err)
+				return err;
+		}
+	} else {
+		/* Busy-wait while the SPU fills the FIFO */
+		ndelay(100 + (delay * 10));
+	}
+
+	/* read in data */
+	for (n = 0; n < len; n += sizeof(u16)) {
+		err = spi_read(card->spi, buf + n, sizeof(u16));
+		if (err)
+			goto out;
+	}
+
+out:
+	spu_transaction_finish(card);
+	return err;
+}
+
+/* Read 16 bits from an SPI register */
+static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
+{
+	return spu_read(card, reg, (u8 *)val, sizeof(u16));
+}
+
+/* Read 32 bits from an SPI register.
+ * The low 16 bits are read first. */
+static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
+{
+	u16 buf[2];
+	int err;
+	err = spu_read(card, reg, (u8 *)buf, sizeof(u32));
+	if (!err)
+		*val = buf[0] | (buf[1] << 16);
+	return err;
+}
+
+/* Keep reading 16 bits from an SPI register until you get the correct result.
+ *
+ * If mask = 0, the correct result is any non-zero number.
+ * If mask != 0, the correct result is any number where
+ * number & target_mask == target
+ *
+ * Returns -ETIMEDOUT if a second passes without the correct result. */
+static int spu_wait_for_u16(struct if_spi_card *card, u16 reg,
+			u16 target_mask, u16 target)
+{
+	int err;
+	unsigned long timeout = jiffies + 5*HZ;
+	while (1) {
+		u16 val;
+		err = spu_read_u16(card, reg, &val);
+		if (err)
+			return err;
+		if (target_mask) {
+			if ((val & target_mask) == target)
+				return 0;
+		} else {
+			if (val)
+				return 0;
+		}
+		udelay(100);
+		if (time_after(jiffies, timeout)) {
+			lbs_pr_err("%s: timeout with val=%02x, "
+			       "target_mask=%02x, target=%02x\n",
+			       __func__, val, target_mask, target);
+			return -ETIMEDOUT;
+		}
+	}
+}
+
+/* Read 16 bits from an SPI register until you receive a specific value.
+ * Returns -ETIMEDOUT if a 4 tries pass without success. */
+static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target)
+{
+	int err, try;
+	for (try = 0; try < 4; ++try) {
+		u32 val = 0;
+		err = spu_read_u32(card, reg, &val);
+		if (err)
+			return err;
+		if (val == target)
+			return 0;
+		mdelay(100);
+	}
+	return -ETIMEDOUT;
+}
+
+static int spu_set_interrupt_mode(struct if_spi_card *card,
+			   int suppress_host_int,
+			   int auto_int)
+{
+	int err = 0;
+
+	/* We can suppress a host interrupt by clearing the appropriate
+	 * bit in the "host interrupt status mask" register */
+	if (suppress_host_int) {
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
+		if (err)
+			return err;
+	} else {
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG,
+			      IF_SPI_HISM_TX_DOWNLOAD_RDY |
+			      IF_SPI_HISM_RX_UPLOAD_RDY |
+			      IF_SPI_HISM_CMD_DOWNLOAD_RDY |
+			      IF_SPI_HISM_CARDEVENT |
+			      IF_SPI_HISM_CMD_UPLOAD_RDY);
+		if (err)
+			return err;
+	}
+
+	/* If auto-interrupts are on, the completion of certain transactions
+	 * will trigger an interrupt automatically. If auto-interrupts
+	 * are off, we need to set the "Card Interrupt Cause" register to
+	 * trigger a card interrupt. */
+	if (auto_int) {
+		err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG,
+				IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO |
+				IF_SPI_HICT_RX_UPLOAD_OVER_AUTO |
+				IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO |
+				IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO);
+		if (err)
+			return err;
+	} else {
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
+		if (err)
+			return err;
+	}
+	return err;
+}
+
+static int spu_get_chip_revision(struct if_spi_card *card,
+				  u16 *card_id, u8 *card_rev)
+{
+	int err = 0;
+	u32 dev_ctrl;
+	err = spu_read_u32(card, IF_SPI_DEVICEID_CTRL_REG, &dev_ctrl);
+	if (err)
+		return err;
+	*card_id = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dev_ctrl);
+	*card_rev = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dev_ctrl);
+	return err;
+}
+
+static int spu_set_bus_mode(struct if_spi_card *card, u16 mode)
+{
+	int err = 0;
+	u16 rval;
+	/* set bus mode */
+	err = spu_write_u16(card, IF_SPI_SPU_BUS_MODE_REG, mode);
+	if (err)
+		return err;
+	/* Check that we were able to read back what we just wrote. */
+	err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval);
+	if (err)
+		return err;
+	if (rval != mode) {
+		lbs_pr_err("Can't read bus mode register.\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int spu_init(struct if_spi_card *card, int use_dummy_writes)
+{
+	int err = 0;
+	u32 delay;
+
+	/* We have to start up in timed delay mode so that we can safely
+	 * read the Delay Read Register. */
+	card->use_dummy_writes = 0;
+	err = spu_set_bus_mode(card,
+				IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
+				IF_SPI_BUS_MODE_DELAY_METHOD_TIMED |
+				IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
+	if (err)
+		return err;
+	card->spu_port_delay = 1000;
+	card->spu_reg_delay = 1000;
+	err = spu_read_u32(card, IF_SPI_DELAY_READ_REG, &delay);
+	if (err)
+		return err;
+	card->spu_port_delay = delay & 0x0000ffff;
+	card->spu_reg_delay = (delay & 0xffff0000) >> 16;
+
+	/* If dummy clock delay mode has been requested, switch to it now */
+	if (use_dummy_writes) {
+		card->use_dummy_writes = 1;
+		err = spu_set_bus_mode(card,
+				IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
+				IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK |
+				IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
+		if (err)
+			return err;
+	}
+
+	lbs_deb_spi("Initialized SPU unit. "
+		    "spu_port_delay=0x%04lx, spu_reg_delay=0x%04lx\n",
+		    card->spu_port_delay, card->spu_reg_delay);
+	return err;
+}
+
+/*
+ * Firmware Loading
+ */
+
+static int if_spi_prog_helper_firmware(struct if_spi_card *card)
+{
+	int err = 0;
+	const struct firmware *firmware = NULL;
+	int bytes_remaining;
+	const u8 *fw;
+	u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
+	struct spi_device *spi = card->spi;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	err = spu_set_interrupt_mode(card, 1, 0);
+	if (err)
+		goto out;
+	/* Get helper firmware image */
+	err = request_firmware(&firmware, card->helper_fw_name, &spi->dev);
+	if (err) {
+		lbs_pr_err("request_firmware failed with err = %d\n", err);
+		goto out;
+	}
+	bytes_remaining = firmware->size;
+	fw = firmware->data;
+
+	/* Load helper firmware image */
+	while (bytes_remaining > 0) {
+		/* Scratch pad 1 should contain the number of bytes we
+		 * want to download to the firmware */
+		err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
+					HELPER_FW_LOAD_CHUNK_SZ);
+		if (err)
+			goto release_firmware;
+
+		err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+					IF_SPI_HIST_CMD_DOWNLOAD_RDY,
+					IF_SPI_HIST_CMD_DOWNLOAD_RDY);
+		if (err)
+			goto release_firmware;
+
+		/* Feed the data into the command read/write port reg
+		 * in chunks of 64 bytes */
+		memset(temp, 0, sizeof(temp));
+		memcpy(temp, fw,
+		       min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ));
+		mdelay(10);
+		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
+					temp, HELPER_FW_LOAD_CHUNK_SZ);
+		if (err)
+			goto release_firmware;
+
+		/* Interrupt the boot code */
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
+		if (err)
+			goto release_firmware;
+		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
+				       IF_SPI_CIC_CMD_DOWNLOAD_OVER);
+		if (err)
+			goto release_firmware;
+		bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
+		fw += HELPER_FW_LOAD_CHUNK_SZ;
+	}
+
+	/* Once the helper / single stage firmware download is complete,
+	 * write 0 to scratch pad 1 and interrupt the
+	 * bootloader. This completes the helper download. */
+	err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
+	if (err)
+		goto release_firmware;
+	err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
+	if (err)
+		goto release_firmware;
+	err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
+				IF_SPI_CIC_CMD_DOWNLOAD_OVER);
+		goto release_firmware;
+
+	lbs_deb_spi("waiting for helper to boot...\n");
+
+release_firmware:
+	release_firmware(firmware);
+out:
+	if (err)
+		lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
+	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+	return err;
+}
+
+/* Returns the length of the next packet the firmware expects us to send
+ * Sets crc_err if the previous transfer had a CRC error. */
+static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
+						int *crc_err)
+{
+	u16 len;
+	int err = 0;
+
+	/* wait until the host interrupt status register indicates
+	 * that we are ready to download */
+	err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+				IF_SPI_HIST_CMD_DOWNLOAD_RDY,
+				IF_SPI_HIST_CMD_DOWNLOAD_RDY);
+	if (err) {
+		lbs_pr_err("timed out waiting for host_int_status\n");
+		return err;
+	}
+
+	/* Ask the device how many bytes of firmware it wants. */
+	err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
+	if (err)
+		return err;
+
+	if (len > IF_SPI_CMD_BUF_SIZE) {
+		lbs_pr_err("firmware load device requested a larger "
+			   "tranfer than we are prepared to "
+			   "handle. (len = %d)\n", len);
+		return -EIO;
+	}
+	if (len & 0x1) {
+		lbs_deb_spi("%s: crc error\n", __func__);
+		len &= ~0x1;
+		*crc_err = 1;
+	} else
+		*crc_err = 0;
+
+	return len;
+}
+
+static int if_spi_prog_main_firmware(struct if_spi_card *card)
+{
+	int len, prev_len;
+	int bytes, crc_err = 0, err = 0;
+	const struct firmware *firmware = NULL;
+	const u8 *fw;
+	struct spi_device *spi = card->spi;
+	u16 num_crc_errs;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	err = spu_set_interrupt_mode(card, 1, 0);
+	if (err)
+		goto out;
+
+	/* Get firmware image */
+	err = request_firmware(&firmware, card->main_fw_name, &spi->dev);
+	if (err) {
+		lbs_pr_err("%s: can't get firmware '%s' from kernel. "
+			"err = %d\n", __func__, card->main_fw_name, err);
+		goto out;
+	}
+
+	err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
+	if (err) {
+		lbs_pr_err("%s: timed out waiting for initial "
+			   "scratch reg = 0\n", __func__);
+		goto release_firmware;
+	}
+
+	num_crc_errs = 0;
+	prev_len = 0;
+	bytes = firmware->size;
+	fw = firmware->data;
+	while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
+		if (len < 0) {
+			err = len;
+			goto release_firmware;
+		}
+		if (bytes < 0) {
+			/* If there are no more bytes left, we would normally
+			 * expect to have terminated with len = 0 */
+			lbs_pr_err("Firmware load wants more bytes "
+				   "than we have to offer.\n");
+			break;
+		}
+		if (crc_err) {
+			/* Previous transfer failed. */
+			if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) {
+				lbs_pr_err("Too many CRC errors encountered "
+					   "in firmware load.\n");
+				err = -EIO;
+				goto release_firmware;
+			}
+		} else {
+			/* Previous transfer succeeded. Advance counters. */
+			bytes -= prev_len;
+			fw += prev_len;
+		}
+		if (bytes < len) {
+			memset(card->cmd_buffer, 0, len);
+			memcpy(card->cmd_buffer, fw, bytes);
+		} else
+			memcpy(card->cmd_buffer, fw, len);
+
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
+		if (err)
+			goto release_firmware;
+		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
+				card->cmd_buffer, len);
+		if (err)
+			goto release_firmware;
+		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
+					IF_SPI_CIC_CMD_DOWNLOAD_OVER);
+		if (err)
+			goto release_firmware;
+		prev_len = len;
+	}
+	if (bytes > prev_len) {
+		lbs_pr_err("firmware load wants fewer bytes than "
+			   "we have to offer.\n");
+	}
+
+	/* Confirm firmware download */
+	err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG,
+					SUCCESSFUL_FW_DOWNLOAD_MAGIC);
+	if (err) {
+		lbs_pr_err("failed to confirm the firmware download\n");
+		goto release_firmware;
+	}
+
+release_firmware:
+	release_firmware(firmware);
+
+out:
+	if (err)
+		lbs_pr_err("failed to load firmware (err=%d)\n", err);
+	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+	return err;
+}
+
+/*
+ * SPI Transfer Thread
+ *
+ * The SPI thread handles all SPI transfers, so there is no need for a lock.
+ */
+
+/* Move a command from the card to the host */
+static int if_spi_c2h_cmd(struct if_spi_card *card)
+{
+	struct lbs_private *priv = card->priv;
+	unsigned long flags;
+	int err = 0;
+	u16 len;
+	u8 i;
+
+	/* We need a buffer big enough to handle whatever people send to
+	 * hw_host_to_card */
+	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE);
+	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE);
+
+	/* It's just annoying if the buffer size isn't a multiple of 4, because
+	 * then we might have len <  IF_SPI_CMD_BUF_SIZE  but 
+	 * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */
+	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0);
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	/* How many bytes are there to read? */
+	err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len);
+	if (err)
+		goto out;
+	if (!len) {
+		lbs_pr_err("%s: error: card has no data for host\n",
+			   __func__);
+		err = -EINVAL;
+		goto out;
+	} else if (len > IF_SPI_CMD_BUF_SIZE) {
+		lbs_pr_err("%s: error: response packet too large: "
+			   "%d bytes, but maximum is %d\n",
+			   __func__, len, IF_SPI_CMD_BUF_SIZE);
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* Read the data from the WLAN module into our command buffer */
+	err = spu_read(card, IF_SPI_CMD_RDWRPORT_REG,
+				card->cmd_buffer, ALIGN(len, 4));
+	if (err)
+		goto out;
+
+	spin_lock_irqsave(&priv->driver_lock, flags);
+	i = (priv->resp_idx == 0) ? 1 : 0;
+	BUG_ON(priv->resp_len[i]);
+	priv->resp_len[i] = len;
+	memcpy(priv->resp_buf[i], card->cmd_buffer, len);
+	lbs_notify_command_response(priv, i);
+	spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+out:
+	if (err)
+		lbs_pr_err("%s: err=%d\n", __func__, err);
+	lbs_deb_leave(LBS_DEB_SPI);
+	return err;
+}
+
+/* Move data from the card to the host */
+static int if_spi_c2h_data(struct if_spi_card *card)
+{
+	struct sk_buff *skb;
+	char *data;
+	u16 len;
+	int err = 0;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	/* How many bytes are there to read? */
+	err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
+	if (err)
+		goto out;
+	if (!len) {
+		lbs_pr_err("%s: error: card has no data for host\n",
+			   __func__);
+		err = -EINVAL;
+		goto out;
+	} else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
+		lbs_pr_err("%s: error: card has %d bytes of data, but "
+			   "our maximum skb size is %u\n",
+			   __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* TODO: should we allocate a smaller skb if we have less data? */
+	skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+	if (!skb) {
+		err = -ENOBUFS;
+		goto out;
+	}
+	skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
+	data = skb_put(skb, len);
+
+	/* Read the data from the WLAN module into our skb... */
+	err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4));
+	if (err)
+		goto free_skb;
+
+	/* pass the SKB to libertas */
+	err = lbs_process_rxed_packet(card->priv, skb);
+	if (err)
+		goto free_skb;
+
+	/* success */
+	goto out;
+
+free_skb:
+	dev_kfree_skb(skb);
+out:
+	if (err)
+		lbs_pr_err("%s: err=%d\n", __func__, err);
+	lbs_deb_leave(LBS_DEB_SPI);
+	return err;
+}
+
+/* Move data or a command from the host to the card. */
+static void if_spi_h2c(struct if_spi_card *card,
+			struct if_spi_packet *packet, int type)
+{
+	int err = 0;
+	u16 int_type, port_reg;
+
+	switch (type) {
+	case MVMS_DAT:
+		int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
+		port_reg = IF_SPI_DATA_RDWRPORT_REG;
+		break;
+	case MVMS_CMD:
+		int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
+		port_reg = IF_SPI_CMD_RDWRPORT_REG;
+		break;
+	default:
+		lbs_pr_err("can't transfer buffer of type %d\n", type);
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* Write the data to the card */
+	err = spu_write(card, port_reg, packet->buffer, packet->blen);
+	if (err)
+		goto out;
+
+out:
+	kfree(packet);
+
+	if (err)
+		lbs_pr_err("%s: error %d\n", __func__, err);
+}
+
+/* Inform the host about a card event */
+static void if_spi_e2h(struct if_spi_card *card)
+{
+	int err = 0;
+	unsigned long flags;
+	u32 cause;
+	struct lbs_private *priv = card->priv;
+
+	err = spu_read_u32(card, IF_SPI_SCRATCH_3_REG, &cause);
+	if (err)
+		goto out;
+
+	spin_lock_irqsave(&priv->driver_lock, flags);
+	lbs_queue_event(priv, cause & 0xff);
+	spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+out:
+	if (err)
+		lbs_pr_err("%s: error %d\n", __func__, err);
+}
+
+static int lbs_spi_thread(void *data)
+{
+	int err;
+	struct if_spi_card *card = data;
+	u16 hiStatus;
+	unsigned long flags;
+	struct if_spi_packet *packet;
+
+	while (1) {
+		/* Wait to be woken up by one of two things.  First, our ISR
+		 * could tell us that something happened on the WLAN.
+		 * Secondly, libertas could call hw_host_to_card with more
+		 * data, which we might be able to send.
+		 */
+		do {
+			err = down_interruptible(&card->spi_ready);
+			if (!card->run_thread) {
+				up(&card->spi_thread_terminated);
+				do_exit(0);
+			}
+		} while (err == EINTR);
+
+		/* Read the host interrupt status register to see what we
+		 * can do. */
+		err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+					&hiStatus);
+		if (err) {
+			lbs_pr_err("I/O error\n");
+			goto err;
+		}
+
+		if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY)
+			err = if_spi_c2h_cmd(card);
+			if (err)
+				goto err;
+		if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY)
+			err = if_spi_c2h_data(card);
+			if (err)
+				goto err;
+		if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) {
+			/* This means two things. First of all,
+			 * if there was a previous command sent, the card has
+			 * successfully received it.
+			 * Secondly, it is now ready to download another
+			 * command.
+			 */
+			lbs_host_to_card_done(card->priv);
+
+			/* Do we have any command packets from the host to
+			 * send? */
+			packet = NULL;
+			spin_lock_irqsave(&card->buffer_lock, flags);
+			if (!list_empty(&card->cmd_packet_list)) {
+				packet = (struct if_spi_packet *)(card->
+						cmd_packet_list.next);
+				list_del(&packet->list);
+			}
+			spin_unlock_irqrestore(&card->buffer_lock, flags);
+
+			if (packet)
+				if_spi_h2c(card, packet, MVMS_CMD);
+		}
+		if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
+			/* Do we have any data packets from the host to
+			 * send? */
+			packet = NULL;
+			spin_lock_irqsave(&card->buffer_lock, flags);
+			if (!list_empty(&card->data_packet_list)) {
+				packet = (struct if_spi_packet *)(card->
+						data_packet_list.next);
+				list_del(&packet->list);
+			}
+			spin_unlock_irqrestore(&card->buffer_lock, flags);
+
+			if (packet)
+				if_spi_h2c(card, packet, MVMS_DAT);
+		}
+		if (hiStatus & IF_SPI_HIST_CARD_EVENT) {
+			if_spi_e2h(card);
+		}
+
+		/* TODO: implement IF_SPI_HIST_CARD_EVENT
+		 * Eventually this should feed into lbs_queue_event */
+
+err:
+		if (err)
+			lbs_pr_err("%s: got error %d\n", __func__, err);
+	}
+}
+
+/* Block until lbs_spi_thread thread has terminated */
+static void if_spi_terminate_spi_thread(struct if_spi_card *card)
+{
+	/* It would be nice to use kthread_stop here, but that function
+	 * can't wake threads waiting for a semaphore. */
+	card->run_thread = 0;
+	up(&card->spi_ready);
+	down(&card->spi_thread_terminated);
+}
+
+/*
+ * Host to Card
+ *
+ * Called from Libertas to transfer some data to the WLAN device
+ * We can't sleep here. */
+static int if_spi_host_to_card(struct lbs_private *priv,
+				u8 type, u8 *buf, u16 nb)
+{
+	int err = 0;
+	unsigned long flags;
+	struct if_spi_card *card = priv->card;
+	struct if_spi_packet *packet;
+	u16 blen;
+
+	lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
+
+	if (nb == 0) {
+		lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
+		err = -EINVAL;
+		goto out;
+	}
+	blen = ALIGN(nb, 4);
+	packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
+	if (!packet) {
+		err = -ENOMEM;
+		goto out;
+	}
+	packet->blen = blen;
+	memcpy(packet->buffer, buf, nb);
+	memset(packet->buffer + nb, 0, blen - nb);
+
+	switch (type) {
+	case MVMS_CMD:
+		priv->dnld_sent = DNLD_CMD_SENT;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		list_add_tail(&packet->list, &card->cmd_packet_list);
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
+		break;
+	case MVMS_DAT:
+		priv->dnld_sent = DNLD_DATA_SENT;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		list_add_tail(&packet->list, &card->data_packet_list);
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
+		break;
+	default:
+		lbs_pr_err("can't transfer buffer of type %d", type);
+		err = -EINVAL;
+		break;
+	}
+
+	/* Wake up the spi thread */
+	up(&card->spi_ready);
+out:
+	lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
+	return err;
+}
+
+/*
+ * Host Interrupts
+ *
+ * Service incoming interrupts from the WLAN device. We can't sleep here, so
+ * don't try to talk on the SPI bus, just wake up the SPI thread.
+ */
+static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
+{
+	struct if_spi_card *card = dev_id;
+
+	up(&card->spi_ready);
+	return IRQ_HANDLED;
+}
+
+/*
+ * SPI callbacks
+ */
+
+static int if_spi_calculate_fw_names(u16 card_id,
+			      char *helper_fw, char *main_fw)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
+		if (card_id == chip_id_to_device_name[i].chip_id)
+			break;
+	}
+	if (i == ARRAY_SIZE(chip_id_to_device_name)) {
+		lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
+		return -EAFNOSUPPORT;
+	}
+	snprintf(helper_fw, FIRMWARE_NAME_MAX, "spi%d_helper.bin",
+		 chip_id_to_device_name[i].name);
+	snprintf(main_fw, FIRMWARE_NAME_MAX, "spi%d.bin",
+		 chip_id_to_device_name[i].name);
+	return 0;
+}
+
+static int __devinit if_spi_probe(struct spi_device *spi)
+{
+	struct if_spi_card *card;
+	struct lbs_private *priv = NULL;
+	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
+	int err = 0;
+	u32 scratch;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	/* Allocate card structure to represent this specific device */
+	card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL);
+	if (!card) {
+		err = -ENOMEM;
+		goto out;
+	}
+	spi_set_drvdata(spi, card);
+	card->spi = spi;
+	card->gpio_cs = pdata->gpio_cs;
+	card->prev_xfer_time = jiffies;
+
+	sema_init(&card->spi_ready, 0);
+	sema_init(&card->spi_thread_terminated, 0);
+	INIT_LIST_HEAD(&card->cmd_packet_list);
+	INIT_LIST_HEAD(&card->data_packet_list);
+	spin_lock_init(&card->buffer_lock);
+
+	/* set up GPIO CS line. TODO: use  regular CS line */
+	err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select");
+	if (err)
+		goto free_card;
+	err = gpio_direction_output(card->gpio_cs, 1);
+	if (err)
+		goto free_gpio;
+
+	/* Initialize the SPI Interface Unit */
+	err = spu_init(card, pdata->use_dummy_writes);
+	if (err)
+		goto free_gpio;
+	err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
+	if (err)
+		goto free_gpio;
+
+	/* Firmware load */
+	err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
+	if (err)
+		goto free_gpio;
+	if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
+		lbs_deb_spi("Firmware is already loaded for "
+			    "Marvell WLAN 802.11 adapter\n");
+	else {
+		err = if_spi_calculate_fw_names(card->card_id,
+				card->helper_fw_name, card->main_fw_name);
+		if (err)
+			goto free_gpio;
+
+		lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
+				"(chip_id = 0x%04x, chip_rev = 0x%02x) "
+				"attached to SPI bus_num %d, chip_select %d. "
+				"spi->max_speed_hz=%d\n",
+				card->card_id, card->card_rev,
+				spi->master->bus_num, spi->chip_select,
+				spi->max_speed_hz);
+		err = if_spi_prog_helper_firmware(card);
+		if (err)
+			goto free_gpio;
+		err = if_spi_prog_main_firmware(card);
+		if (err)
+			goto free_gpio;
+		lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
+	}
+
+	err = spu_set_interrupt_mode(card, 0, 1);
+	if (err)
+		goto free_gpio;
+
+	/* Register our card with libertas.
+	 * This will call alloc_etherdev */
+	priv = lbs_add_card(card, &spi->dev);
+	if (!priv) {
+		err = -ENOMEM;
+		goto free_gpio;
+	}
+	card->priv = priv;
+	priv->card = card;
+	priv->hw_host_to_card = if_spi_host_to_card;
+	priv->fw_ready = 1;
+	priv->ps_supported = 1;
+
+	/* Initialize interrupt handling stuff. */
+	card->run_thread = 1;
+	card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread");
+	if (IS_ERR(card->spi_thread)) {
+		card->run_thread = 0;
+		err = PTR_ERR(card->spi_thread);
+		lbs_pr_err("error creating SPI thread: err=%d\n", err);
+		goto remove_card;
+	}
+	err = request_irq(spi->irq, if_spi_host_interrupt,
+			IRQF_TRIGGER_FALLING, "libertas_spi", card);
+	if (err) {
+		lbs_pr_err("can't get host irq line-- request_irq failed\n");
+		goto terminate_thread;
+	}
+
+	/* Start the card.
+	 * This will call register_netdev, and we'll start
+	 * getting interrupts... */
+	err = lbs_start_card(priv);
+	if (err)
+		goto release_irq;
+
+	lbs_deb_spi("Finished initializing WLAN module.\n");
+
+	/* successful exit */
+	goto out;
+
+release_irq:
+	free_irq(spi->irq, card);
+terminate_thread:
+	if_spi_terminate_spi_thread(card);
+remove_card:
+	lbs_remove_card(priv); /* will call free_netdev */
+free_gpio:
+	gpio_free(card->gpio_cs);
+free_card:
+	free_if_spi_card(card);
+out:
+	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
+	return err;
+}
+
+static int __devexit libertas_spi_remove(struct spi_device *spi)
+{
+	struct if_spi_card *card = spi_get_drvdata(spi);
+	struct lbs_private *priv = card->priv;
+
+	lbs_deb_spi("libertas_spi_remove\n");
+	lbs_deb_enter(LBS_DEB_SPI);
+	priv->surpriseremoved = 1;
+
+	lbs_stop_card(priv);
+	free_irq(spi->irq, card);
+	if_spi_terminate_spi_thread(card);
+	lbs_remove_card(priv); /* will call free_netdev */
+	gpio_free(card->gpio_cs);
+	free_if_spi_card(card);
+	lbs_deb_leave(LBS_DEB_SPI);
+	return 0;
+}
+
+static struct spi_driver libertas_spi_driver = {
+	.probe	= if_spi_probe,
+	.remove = __devexit_p(libertas_spi_remove),
+	.driver = {
+		.name	= "libertas_spi",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+};
+
+/*
+ * Module functions
+ */
+
+static int __init if_spi_init_module(void)
+{
+	int ret = 0;
+	lbs_deb_enter(LBS_DEB_SPI);
+	printk(KERN_INFO "libertas_spi: Libertas SPI driver\n");
+	ret = spi_register_driver(&libertas_spi_driver);
+	lbs_deb_leave(LBS_DEB_SPI);
+	return ret;
+}
+
+static void __exit if_spi_exit_module(void)
+{
+	lbs_deb_enter(LBS_DEB_SPI);
+	spi_unregister_driver(&libertas_spi_driver);
+	lbs_deb_leave(LBS_DEB_SPI);
+}
+
+module_init(if_spi_init_module);
+module_exit(if_spi_exit_module);
+
+MODULE_DESCRIPTION("Libertas SPI WLAN Driver");
+MODULE_AUTHOR("Andrey Yurovsky <andrey at cozybit.com>, "
+	      "Colin McCabe <colin at cozybit.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h
new file mode 100644
index 0000000..2103869
--- /dev/null
+++ b/drivers/net/wireless/libertas/if_spi.h
@@ -0,0 +1,208 @@
+/*
+ *	linux/drivers/net/wireless/libertas/if_spi.c
+ *
+ *	Driver for Marvell SPI WLAN cards.
+ *
+ *	Copyright 2008 Analog Devices Inc.
+ *
+ *	Authors:
+ *	Andrey Yurovsky <andrey at cozybit.com>
+ *	Colin McCabe <colin at cozybit.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef _LBS_IF_SPI_H_
+#define _LBS_IF_SPI_H_
+
+#define IPFIELD_ALIGN_OFFSET 2
+#define IF_SPI_CMD_BUF_SIZE 2400
+
+/***************** Firmware *****************/
+struct chip_ident {
+	u16 chip_id;
+	u16 name;
+};
+
+#define MAX_MAIN_FW_LOAD_CRC_ERR 10
+
+/* Chunk size when loading the helper firmware */
+#define HELPER_FW_LOAD_CHUNK_SZ 64
+
+/* Value to write to indicate end of helper firmware dnld */
+#define FIRMWARE_DNLD_OK 0x0000
+
+/* Value to check once the main firmware is downloaded */
+#define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888
+
+/***************** SPI Interface Unit *****************/
+/* Masks used in SPI register read/write operations */
+#define IF_SPI_READ_OPERATION_MASK 0x0
+#define IF_SPI_WRITE_OPERATION_MASK 0x8000
+
+/* SPI register offsets. 4-byte aligned. */
+#define IF_SPI_DEVICEID_CTRL_REG 0x00	/* DeviceID controller reg */
+#define IF_SPI_IO_READBASE_REG 0x04 	/* Read I/O base reg */
+#define IF_SPI_IO_WRITEBASE_REG 0x08	/* Write I/O base reg */
+#define IF_SPI_IO_RDWRPORT_REG 0x0C	/* Read/Write I/O port reg */
+
+#define IF_SPI_CMD_READBASE_REG 0x10	/* Read command base reg */
+#define IF_SPI_CMD_WRITEBASE_REG 0x14	/* Write command base reg */
+#define IF_SPI_CMD_RDWRPORT_REG 0x18	/* Read/Write command port reg */
+
+#define IF_SPI_DATA_READBASE_REG 0x1C	/* Read data base reg */
+#define IF_SPI_DATA_WRITEBASE_REG 0x20	/* Write data base reg */
+#define IF_SPI_DATA_RDWRPORT_REG 0x24	/* Read/Write data port reg */
+
+#define IF_SPI_SCRATCH_1_REG 0x28	/* Scratch reg 1 */
+#define IF_SPI_SCRATCH_2_REG 0x2C	/* Scratch reg 2 */
+#define IF_SPI_SCRATCH_3_REG 0x30	/* Scratch reg 3 */
+#define IF_SPI_SCRATCH_4_REG 0x34	/* Scratch reg 4 */
+
+#define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */
+#define IF_SPI_TX_FRAME_STATUS_REG 0x3C	/* Tx frame status reg */
+
+#define IF_SPI_HOST_INT_CTRL_REG 0x40	/* Host interrupt controller reg */
+
+#define IF_SPI_CARD_INT_CAUSE_REG 0x44	/* Card interrupt cause reg */
+#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */
+#define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */
+#define IF_SPI_CARD_INT_STATUS_MASK_REG	0x50 /* Card interrupt status mask */
+
+#define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */
+
+#define IF_SPI_HOST_INT_CAUSE_REG 0x58	/* Host interrupt cause reg */
+#define IF_SPI_HOST_INT_STATUS_REG 0x5C	/* Host interrupt status reg */
+#define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */
+#define IF_SPI_HOST_INT_STATUS_MASK_REG	0x64 /* Host interrupt status mask */
+#define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */
+
+#define IF_SPI_DELAY_READ_REG 0x6C	/* Delay read reg */
+#define IF_SPI_SPU_BUS_MODE_REG 0x70	/* SPU BUS mode reg */
+
+/***************** IF_SPI_DEVICEID_CTRL_REG *****************/
+#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16)
+#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff)
+
+/***************** IF_SPI_HOST_INT_CTRL_REG *****************/
+/** Host Interrupt Control bit : Wake up */
+#define IF_SPI_HICT_WAKE_UP				(1<<0)
+/** Host Interrupt Control bit : WLAN ready */
+#define IF_SPI_HICT_WLAN_READY				(1<<1)
+/*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY		(1<<2) */
+/*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY		(1<<3) */
+/*#define IF_SPI_HICT_IRQSRC_WLAN			(1<<4) */
+/** Host Interrupt Control bit : Tx auto download */
+#define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO		(1<<5)
+/** Host Interrupt Control bit : Rx auto upload */
+#define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO			(1<<6)
+/** Host Interrupt Control bit : Command auto download */
+#define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO		(1<<7)
+/** Host Interrupt Control bit : Command auto upload */
+#define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO		(1<<8)
+
+/***************** IF_SPI_CARD_INT_CAUSE_REG *****************/
+/** Card Interrupt Case bit : Tx download over */
+#define IF_SPI_CIC_TX_DOWNLOAD_OVER			(1<<0)
+/** Card Interrupt Case bit : Rx upload over */
+#define IF_SPI_CIC_RX_UPLOAD_OVER			(1<<1)
+/** Card Interrupt Case bit : Command download over */
+#define IF_SPI_CIC_CMD_DOWNLOAD_OVER			(1<<2)
+/** Card Interrupt Case bit : Host event */
+#define IF_SPI_CIC_HOST_EVENT				(1<<3)
+/** Card Interrupt Case bit : Command upload over */
+#define IF_SPI_CIC_CMD_UPLOAD_OVER			(1<<4)
+/** Card Interrupt Case bit : Power down */
+#define IF_SPI_CIC_POWER_DOWN				(1<<5)
+
+/***************** IF_SPI_CARD_INT_STATUS_REG *****************/
+#define IF_SPI_CIS_TX_DOWNLOAD_OVER			(1<<0)
+#define IF_SPI_CIS_RX_UPLOAD_OVER			(1<<1)
+#define IF_SPI_CIS_CMD_DOWNLOAD_OVER			(1<<2)
+#define IF_SPI_CIS_HOST_EVENT				(1<<3)
+#define IF_SPI_CIS_CMD_UPLOAD_OVER			(1<<4)
+#define IF_SPI_CIS_POWER_DOWN				(1<<5)
+
+/***************** IF_SPI_HOST_INT_CAUSE_REG *****************/
+#define IF_SPI_HICU_TX_DOWNLOAD_RDY			(1<<0)
+#define IF_SPI_HICU_RX_UPLOAD_RDY			(1<<1)
+#define IF_SPI_HICU_CMD_DOWNLOAD_RDY			(1<<2)
+#define IF_SPI_HICU_CARD_EVENT				(1<<3)
+#define IF_SPI_HICU_CMD_UPLOAD_RDY			(1<<4)
+#define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW			(1<<5)
+#define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW		(1<<6)
+#define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW		(1<<7)
+#define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW		(1<<8)
+#define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW		(1<<9)
+#define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW		(1<<10)
+
+/***************** IF_SPI_HOST_INT_STATUS_REG *****************/
+/** Host Interrupt Status bit : Tx download ready */
+#define IF_SPI_HIST_TX_DOWNLOAD_RDY			(1<<0)
+/** Host Interrupt Status bit : Rx upload ready */
+#define IF_SPI_HIST_RX_UPLOAD_RDY			(1<<1)
+/** Host Interrupt Status bit : Command download ready */
+#define IF_SPI_HIST_CMD_DOWNLOAD_RDY			(1<<2)
+/** Host Interrupt Status bit : Card event */
+#define IF_SPI_HIST_CARD_EVENT				(1<<3)
+/** Host Interrupt Status bit : Command upload ready */
+#define IF_SPI_HIST_CMD_UPLOAD_RDY			(1<<4)
+/** Host Interrupt Status bit : I/O write FIFO overflow */
+#define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW			(1<<5)
+/** Host Interrupt Status bit : I/O read FIFO underflow */
+#define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW			(1<<6)
+/** Host Interrupt Status bit : Data write FIFO overflow */
+#define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW		(1<<7)
+/** Host Interrupt Status bit : Data read FIFO underflow */
+#define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW		(1<<8)
+/** Host Interrupt Status bit : Command write FIFO overflow */
+#define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW		(1<<9)
+/** Host Interrupt Status bit : Command read FIFO underflow */
+#define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW		(1<<10)
+
+/***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/
+/** Host Interrupt Status Mask bit : Tx download ready */
+#define IF_SPI_HISM_TX_DOWNLOAD_RDY			(1<<0)
+/** Host Interrupt Status Mask bit : Rx upload ready */
+#define IF_SPI_HISM_RX_UPLOAD_RDY			(1<<1)
+/** Host Interrupt Status Mask bit : Command download ready */
+#define IF_SPI_HISM_CMD_DOWNLOAD_RDY			(1<<2)
+/** Host Interrupt Status Mask bit : Card event */
+#define IF_SPI_HISM_CARDEVENT				(1<<3)
+/** Host Interrupt Status Mask bit : Command upload ready */
+#define IF_SPI_HISM_CMD_UPLOAD_RDY			(1<<4)
+/** Host Interrupt Status Mask bit : I/O write FIFO overflow */
+#define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW			(1<<5)
+/** Host Interrupt Status Mask bit : I/O read FIFO underflow */
+#define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW		(1<<6)
+/** Host Interrupt Status Mask bit : Data write FIFO overflow */
+#define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW		(1<<7)
+/** Host Interrupt Status Mask bit : Data write FIFO underflow */
+#define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW		(1<<8)
+/** Host Interrupt Status Mask bit : Command write FIFO overflow */
+#define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW		(1<<9)
+/** Host Interrupt Status Mask bit : Command write FIFO underflow */
+#define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW		(1<<10)
+
+/***************** IF_SPI_SPU_BUS_MODE_REG *****************/
+/* SCK edge on which the WLAN module outputs data on MISO */
+#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8
+#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0
+
+/* In a SPU read operation, there is a delay between writing the SPU
+ * register name and getting back data from the WLAN module.
+ * This can be specified in terms of nanoseconds or in terms of dummy
+ * clock cycles which the master must output before receiving a response. */
+#define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4
+#define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0
+
+/* Some different modes of SPI operation */
+#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00
+#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01
+#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02
+#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03
+
+#endif
diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h
new file mode 100644
index 0000000..ada71b4
--- /dev/null
+++ b/include/linux/spi/libertas_spi.h
@@ -0,0 +1,25 @@
+/*
+ * board-specific data for the libertas_spi driver.
+ *
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+#ifndef _LIBERTAS_SPI_H_
+#define _LIBERTAS_SPI_H_
+struct libertas_spi_platform_data {
+	/* There are two ways to read data from the WLAN module's SPI
+	 * interface. Setting 0 or 1 here controls which one is used.
+	 *
+	 * Usually you want to set use_dummy_writes = 1.
+	 * However, if that doesn't work or if you are using a slow SPI clock
+	 * speed, you may want to use 0 here. */
+	u16 use_dummy_writes;
+
+	/* GPIO number to use as chip select */
+	u16 gpio_cs;
+};
+#endif
-- 
1.5.6.3



From dcbw at redhat.com  Mon Jan  5 15:30:28 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 05 Jan 2009 15:30:28 -0500
Subject: Problems with GSPI
In-Reply-To: <1229763382.7168.11.camel@localhost.localdomain>
References: <1229255279.6933.15.camel@localhost.localdomain>
	<1229722755.25922.14.camel@localhost.localdomain>
	<1229728794.11445.28.camel@localhost.localdomain>
	<1229735568.24075.37.camel@localhost.localdomain>
	<1229763382.7168.11.camel@localhost.localdomain>
Message-ID: <1231187428.20228.51.camel@localhost.localdomain>

On Sat, 2008-12-20 at 09:56 +0100, Erwin Authried wrote:
> Am Freitag, den 19.12.2008, 20:12 -0500 schrieb Dan Williams:
> > On Sat, 2008-12-20 at 00:19 +0100, Erwin Authried wrote:
> > > Am Freitag, den 19.12.2008, 16:39 -0500 schrieb Dan Williams:
> > > > On Sun, 2008-12-14 at 12:47 +0100, Erwin Authried wrote:
> > > > > Hi,
> > > > > 
> > > > > I'm using the 88W8686 in GSPI mode, and I have created a if_gspi module
> > > > > to be able to use the libertas driver instead of Marvell's original
> > > > > driver. I tried ad-hoc mode first, and that seems to work fine, I'm
> > > > > getting event interrupts when a link is lost or re-established. In
> > > > > managed mode, I can establish a WEP connection using iwconfig, and I'm
> > > > > getting an interrupt when the link to the AP is lost. I'm not getting
> > > > > any further event interrupts when the link comes back or goes down
> > > > > again, however. With wpa supplicant, everything works fine, but I'd
> > > > > still like to know if it's normal that no events are received in managed
> > > > > mode, except the first event when the link goes down. I'm using firmware
> > > > > version gspi 9.70.3p37, but I have seen the same problem with older
> > > > > firmware and the original Marvell driver as well. I'd like to know if
> > > > > there's the same problem is there with SD and CF.
> > > > 
> > > > Any chance you could try one of the GSPI patches that just got posted?
> > > I can't use those patches directly because my hardware uses a CPLD that
> > > does the serial/parallel conversion. But the comments in the source give
> > > some insight on the correct usage of the registers.
> > > 
> > > > We should try to converge on a single GSPI driver so that we can
> > > > actually try to track down stuff like this.  
> > > I'm thinking about creating a SPI driver for my hardware to make that
> > > possible. 
> > > 
> > > > In response to the actual
> > > > question though, when you say "the link comes back", do you mean that
> > > > the reconnection process initiated by wpa_supplicant is successful and
> > > > eventually reports CONNECTED?  Can you post some wpa_supplicant logs
> > > > with "-dddt" full debugging?  AFAIK MAC events should still be
> > > > generated, though the firmware is sometimes dodgy.  I'd suspect
> > > > something odd in your GSPI code about clearing the interrupt register
> > > > correctly, or handling the event correctly when the event packet comes
> > > > back from the card.  
> > > 
> > > With "the link comes back" I mean that I turn the AP on again. I believe
> > 
> > Ok, so you turn off the AP and turn it back on again?  If that's the
> > case, then no, we don't expect the driver/firmware to reconnect
> > automatically.  That's what the supplicant does through scanning and
> > reconnection.  The driver/firmware won't necessarily continually try to
> > reconnect, because there's no idea when the AP might come back.  When
> > the connection drops, the supplicant will terminate the association in
> > the driver, and enter the scan loop, where it will periodically scan for
> > the highest priority access point and when it's found, try to reconnect.
> > You won't necessarily get unsolicited MAC association events when you
> > turn the AP back on because the association has been torn down already.
> > Roaming/reassoc is done by the supplicant.
> > 
> > So I think what you're seeing is expected.
> > 
> > Dan
> 
> Dan,
> thanks a lot for the explanation. That means that even with WEP only I
> can't work without supplicant, because any short connection loss would
> terminate the connection permanently, right? When I am using ad-hoc
> mode, I get an event everytime the link goes up or down, thus I thought
> that there must be some bug in managed mode.

Correct, once the connection goes down something in userspace is
expected to handle the disconnection, either by attempting a
reassoc/reauth, or by trying a different AP.

Adhoc mode obviously doesn't use a central authority like a base
station, and therefore doesn't have any authentication/association,
being completely peer-to-peer.  Thus link up/link down doesn't really
mean anything here, because no external events (short of unplugging the
card) will actually cause the connection to drop.

Dan




From dcbw at redhat.com  Mon Jan  5 15:31:53 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 05 Jan 2009 15:31:53 -0500
Subject: Changing ESSID in ad-hoc mode make kernel bug
In-Reply-To: <91112.53563.qm@web70802.mail.kr3.yahoo.com>
References: <91112.53563.qm@web70802.mail.kr3.yahoo.com>
Message-ID: <1231187513.20228.53.camel@localhost.localdomain>

On Fri, 2008-10-17 at 09:02 +0900, Jeong-Hwan Seo wrote:
> Hi all, 
> 
> I found some problems in libertas driver.
> The initial command setting essid succeeds.
> But following command changing essid makes kernel bug.
> 
> I find that it happens only in adhoc mode.
> 
> operation : 
> # iwconfig eth0 mode ad-hoc
> # iwconfig eth0 essid HI
> # iwconfig eth0 essid HELLO
> 
> BUG: scheduling while atomic: iwconfig/801/0x00000002
> [<c002a2e0>] (dump_stack+0x0/0x14) from [<c00395ec>]
> (__schedule_bug+0x4c/0x58)
> [<c00395a0>] (__schedule_bug+0x0/0x58) from
> [<c02845f4>] (schedule+0x74/0x314)
>  r4:c7a39240
> [<c0284580>] (schedule+0x0/0x314) from [<c0186744>]
> (__lbs_cmd+0x11c/0x210)
> [<c0186628>] (__lbs_cmd+0x0/0x210) from [<c0181ed8>]
> (lbs_get_wireless_stats+0x1a8/0x350)
> [<c0181d30>] (lbs_get_wireless_stats+0x0/0x350) from
> [<c025d018>] (get_wireless_stats+0x2c/0x38)
>  r8:00000001 r7:4001e000 r6:000000a2 r5:c7a4d2e0
> r4:c709c000
> [<c025cfec>] (get_wireless_stats+0x0/0x38) from
> [<c025ded0>] (wireless_seq_show+0x38/0x108)
> [<c025de98>] (wireless_seq_show+0x0/0x108) from
> [<c00ac874>] (seq_read+0x240/0x394)
> [<c00ac634>] (seq_read+0x0/0x394) from [<c00c4894>]
> (proc_reg_read+0xb4/0xc8)
> [<c00c47e0>] (proc_reg_read+0x0/0xc8) from
> [<c008eefc>] (vfs_read+0xb0/0xd8)
> [<c008ee4c>] (vfs_read+0x0/0xd8) from [<c008f2d8>]
> (sys_read+0x44/0x70)
>  r6:00000000 r5:fffffff7 r4:c782a8a0
> [<c008f294>] (sys_read+0x0/0x70) from [<c0025ae0>]
> (ret_fast_syscall+0x0/0x2c)
>  r7:00000003 r6:000003ff r5:00015008 r4:00015008
> 
> After Bug message : 
> # iwconfig
> lo        no wireless extensions.
> 
> eth0      IEEE 802.11b/g  ESSID:"HELLO"
>           Mode:Ad-Hoc  Frequency:2.412 GHz  Cell:
> 02:2D:2D:60:D2:55
>           Bit Rate:0 kb/s   Tx-Power=18 dBm
>           Retry limit:8   RTS thr=2347 B   Fragment
> thr=2346 B
>           Encryption key:off
>           Power Management:off
>           Link Quality=0/100  Signal level=-11 dBm 
> Noise level=-11 dBm
>           Rx invalid nwid:0  Rx invalid crypt:0  Rx
> invalid frag:0
>           Tx excessive retries:0  Invalid misc:0  
> Missed beacon:0
> 
> I investigated the libertas code and I found
> something.
> lbs_get_wireless_stats calls lbs_cmd_with_response
> lbs_cmd_with_response(__lbs_cmd) calls
> wait_event_interruptible
> During wait_event_interruptible(schedule()), kernel
> bug is checked.
> Finally, __schedule_bug function prints
> "BUG:Scheduling while atomic".

I'll have to look into that.  Thanks for the report.  It may be that
2.6.27 has fixed this issue, but it may also be the case that it hasn't.
What firmware version are you running by the way?

Dan

> I tested it under 2.6.26 version with Marvell sd8686
> chipset.
> I will appreciate your help.
> ===================================
> Jase.
> SW center Samsung Electronics CO., LTD.
> Mobile : 010-7322-5759 TEL : 031-279-8028
> E-mail : jh2931.seo at samsung.com
> seomarine at yahoo.com
> ===================================
> 
> 
> 
>       ________________________________________________________ 
> 180? ??? ??! ?? - ??! ??? ??! ????? ???? ???? ??? ?? ? ????.
> http://kr.content.mail.yahoo.com/cgland
> 
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From dcbw at redhat.com  Mon Jan  5 15:40:24 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 05 Jan 2009 15:40:24 -0500
Subject: Reloading problem
In-Reply-To: <946091.54320.qm@web70801.mail.kr3.yahoo.com>
References: <946091.54320.qm@web70801.mail.kr3.yahoo.com>
Message-ID: <1231188024.20228.61.camel@localhost.localdomain>

On Fri, 2008-10-17 at 18:55 +0900, Jeong-Hwan Seo wrote:
> Hi everybody.
> I already read post about reloading problem of
> libertas driver module.
> (Reloading of libertas driver module make kernel
> broken.)
> Has anybody found solution about the problem?
> 
> This is log messages about the problem
> =======================================================================================
> # insmod libertas_sdio.ko
> libertas_sdio: Libertas SDIO driver
> libertas_sdio: Copyright Pierre Ossman
> firmware: requesting helper_sd.bin
> firmware: requesting sd8686.bin
> libertas: 00:50:43:02:fe:01, fw 9.70.2p1, cap
> 0x0000030b
> libertas: eth0: Marvell WLAN 802.11 adapter
> # rmmod libertas_sdio
> # insmod libertas_sdio.ko
> libertas_sdio: Libertas SDIO driver
> libertas_sdio: Copyright Pierre Ossman
> firmware: requesting helper_sd.bin
> firmware: requesting sd8686.bin
> Unable to handle kernel NULL pointer dereference at
> virtual address 00000b18
> pgd = c0004000
> [00000b18] *pgd=00000000
> Internal error: Oops: 17 [#1] PREEMPT
> Modules linked in: libertas_sdio(+) [last unloaded:
> libertas_sdio]
> CPU: 0    Not tainted  (2.6.26-00186-g76fe58a-dirty
> #50)
> PC is at lbs_host_to_card_done+0x70/0x134
> LR is at lbs_host_to_card_done+0x70/0x134
> pc : [<c017c6b0>]    lr : [<c017c6b0>]    psr:
> 80000193
> sp : c7111f38  ip : c7111f38  fp : c7111f4c
> r10: 00000000  r9 : 00000002  r8 : 00400001
> r7 : c03b1878  r6 : c7111f5c  r5 : 00000000  r4 :
> 80000113
> r3 : 00000000  r2 : c7110000  r1 : 00000001  r0 :
> 00000001
> Flags: Nzcv  IRQs off  FIQs on  Mode SVC_32  ISA ARM 
> Segment kernel
> Control: 00c5387f  Table: 57100008  DAC: 00000017
> Process ksdiorqd (pid: 802, stack limit = 0xc7110260)
> Stack: (0xc7111f38 to 0xc7112000)
> 1f20:                                                 
>      00000002 c70e0000
> 1f40: c7111f8c c7111f50 bf00125c c017c64c 00000000
> 00000195 00000000 00000000
> 1f60: 00000000 00000000 c7989000 c7a41e00 c7a41e00
> 00000001 00000002 00000000
> 1f80: c7111fd4 c7111f90 c01d56bc bf001168 00000000
> c7111fa7 00000002 c7110000
> 1fa0: 00000001 020392ac c7111fd4 c7110000 c7989000
> c01d55c4 00000000 00000000
> 1fc0: 00000000 00000000 c7111ff4 c7111fd8 c0054df8
> c01d55d0 00000000 00000000
> 1fe0: 00000000 00000000 00000000 c7111ff8 c0042ca0
> c0054da8 c0000bd8 c0000b70
> Backtrace:
> [<c017c640>] (lbs_host_to_card_done+0x0/0x134) from
> [<bf00125c>] (if_sdio_interrupt+0x100/0x958
> [libertas_sdio])
>  r5:c70e0000 r4:00000002
> [<bf00115c>] (if_sdio_interrupt+0x0/0x958
> [libertas_sdio]) from [<c01d56bc>]
> (sdio_irq_thread+0xf8/0x1f8)
> [<c01d55c4>] (sdio_irq_thread+0x0/0x1f8) from
> [<c0054df8>] (kthread+0x5c/0x94)
> 
> 
> What I find out is card->priv is NULL pointer.
> In, if_sdio.c if_sdio_interrupt calls
> lbs_host_tocard_done(card->priv)
> Here, card->priv is NULL pointer.
> And, when kernel try to access priv it crashes.
> I hope somebody could solve this problem.

Hmm... try disabling interrupts right after flush_scheduled_work() in
if_sdio_remove(), with something like:

	sdio_writeb(func, 0x00, IF_SDIO_H_INT_MASK, &ret);

Could be that interrupts don't get disabled on module removal, and thus
are enabled before the module wants to handle them.

Dan




From andrey at cozybit.com  Tue Jan  6 17:13:57 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Tue, 6 Jan 2009 14:13:57 -0800
Subject: firmware for GSPI '8686 available
Message-ID: <45e8e6c40901061413n1a984e58n8e1643caa1fd481e@mail.gmail.com>

Marvell will make the 88W8686 GSPI firmware available for public
download on their website in the next weeks.  In the meantime we've
uploaded it to our website:
http://cozybit.com/projects/gspi8686

Please note that you must accept Marvell's license before downloading the files.

We encourage you to use this firmware to test the patch set that Colin
submitted on Jan 2nd.

Thanks,

  -Andrey


From johannes at sipsolutions.net  Tue Jan  6 17:25:24 2009
From: johannes at sipsolutions.net (Johannes Berg)
Date: Tue, 06 Jan 2009 23:25:24 +0100
Subject: firmware for GSPI '8686 available
In-Reply-To: <45e8e6c40901061413n1a984e58n8e1643caa1fd481e@mail.gmail.com>
	(sfid-20090106_231408_425727_CFACAE07)
References: <45e8e6c40901061413n1a984e58n8e1643caa1fd481e@mail.gmail.com>
	(sfid-20090106_231408_425727_CFACAE07)
Message-ID: <1231280724.3767.15.camel@johannes>

On Tue, 2009-01-06 at 14:13 -0800, Andrey Yurovsky wrote:
> Marvell will make the 88W8686 GSPI firmware available for public
> download on their website in the next weeks.  In the meantime we've
> uploaded it to our website:
> http://cozybit.com/projects/gspi8686
> 
> Please note that you must accept Marvell's license before downloading the files.

That license seems suitable for inclusion into the linux-firmware
repository, would that be doable?

johannes
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
Url : http://lists.infradead.org/pipermail/libertas-dev/attachments/20090106/2ebd7152/attachment.bin 

From javier at cozybit.com  Tue Jan  6 17:36:34 2009
From: javier at cozybit.com (Javier Cardona)
Date: Tue, 6 Jan 2009 14:36:34 -0800
Subject: firmware for GSPI '8686 available
In-Reply-To: <1231280724.3767.15.camel@johannes>
References: <45e8e6c40901061413n1a984e58n8e1643caa1fd481e@mail.gmail.com>
	<1231280724.3767.15.camel@johannes>
Message-ID: <445f43ac0901061436t29cd66acy8ad35181e4430ce6@mail.gmail.com>

Johannes,

On Tue, Jan 6, 2009 at 2:25 PM, Johannes Berg <johannes at sipsolutions.net> wrote:
> On Tue, 2009-01-06 at 14:13 -0800, Andrey Yurovsky wrote:
>> Marvell will make the 88W8686 GSPI firmware available for public
>> download on their website in the next weeks.  In the meantime we've
>> uploaded it to our website:
>> http://cozybit.com/projects/gspi8686
>>
>> Please note that you must accept Marvell's license before downloading the files.
>
> That license seems suitable for inclusion into the linux-firmware
> repository, would that be doable?

A lawyer could tell.  Not us ;)

Javier

-- 
Javier Cardona
cozybit Inc.


From netrolller.3d at gmail.com  Tue Jan  6 17:52:56 2009
From: netrolller.3d at gmail.com (=?ISO-8859-1?Q?Stefanik_G=E1bor?=)
Date: Tue, 6 Jan 2009 23:52:56 +0100
Subject: firmware for GSPI '8686 available
In-Reply-To: <45e8e6c40901061413n1a984e58n8e1643caa1fd481e@mail.gmail.com>
References: <45e8e6c40901061413n1a984e58n8e1643caa1fd481e@mail.gmail.com>
Message-ID: <69e28c910901061452r75ef5b27yce3dd32f5d1e19f4@mail.gmail.com>

On Tue, Jan 6, 2009 at 11:13 PM, Andrey Yurovsky <andrey at cozybit.com> wrote:
> Marvell will make the 88W8686 GSPI firmware available for public
> download on their website in the next weeks.  In the meantime we've
> uploaded it to our website:
> http://cozybit.com/projects/gspi8686
>
> Please note that you must accept Marvell's license before downloading the files.
>
> We encourage you to use this firmware to test the patch set that Colin
> submitted on Jan 2nd.
>
> Thanks,
>
>  -Andrey
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

That license looks like it is not really a valid click-wrap -
similarly to the GPL, acceptance is not required for having copies,
since it only covers redistribution.

-- 
Vista: [V]iruses, [I]ntruders, [S]pyware, [T]rojans and [A]dware. :-)


From hs4233 at mail.mn-solutions.de  Wed Jan  7 03:38:23 2009
From: hs4233 at mail.mn-solutions.de (Holger Schurig)
Date: Wed, 7 Jan 2009 09:38:23 +0100
Subject: [PATCH v2 3/3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <1230951623-26998-4-git-send-email-colin@cozybit.com>
References: <1230951623-26998-1-git-send-email-colin@cozybit.com>
	<1230951623-26998-3-git-send-email-colin@cozybit.com>
	<1230951623-26998-4-git-send-email-colin@cozybit.com>
Message-ID: <200901070938.23256.hs4233@mail.mn-solutions.de>

> Add initial support for libertas devices using a GSPI
> interface.  This has been tested with the 8686.  At this time,
> as far as we know, GSPI firmware for this device is not
> publicly distributable, but we expect this to change.

Can you somewhere download a Windows CE driver that contains the 
firmware in it?  If yes, then you could use my 
firmware-extractor (with some little patches). I'm fine with 
patching support for GSPI into it if you send things in.

(See "fwcutter" in this tree:)

http://git.infradead.org/users/schurig/libertas-tools.git


From andrey at cozybit.com  Wed Jan  7 12:28:28 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Wed, 7 Jan 2009 09:28:28 -0800
Subject: [PATCH v2 3/3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <200901070938.23256.hs4233@mail.mn-solutions.de>
References: <1230951623-26998-1-git-send-email-colin@cozybit.com>
	<1230951623-26998-3-git-send-email-colin@cozybit.com>
	<1230951623-26998-4-git-send-email-colin@cozybit.com>
	<200901070938.23256.hs4233@mail.mn-solutions.de>
Message-ID: <45e8e6c40901070928k6f885b69o19c9b7abd7af21ef@mail.gmail.com>

Hi Holger.  The firmware is available for download on its own now
(please see the email I sent yesterday) and Marvell will make it
available on their website in the near future, so I don't think that
pulling it out of a driver is necessary.

On Wed, Jan 7, 2009 at 12:38 AM, Holger Schurig
<hs4233 at mail.mn-solutions.de> wrote:
>> Add initial support for libertas devices using a GSPI
>> interface.  This has been tested with the 8686.  At this time,
>> as far as we know, GSPI firmware for this device is not
>> publicly distributable, but we expect this to change.
>
> Can you somewhere download a Windows CE driver that contains the
> firmware in it?  If yes, then you could use my
> firmware-extractor (with some little patches). I'm fine with
> patching support for GSPI into it if you send things in.
>
> (See "fwcutter" in this tree:)
>
> http://git.infradead.org/users/schurig/libertas-tools.git
>


From andrey at cozybit.com  Wed Jan  7 19:58:59 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Wed, 7 Jan 2009 16:58:59 -0800
Subject: libertas: BUG: unable to handle paging request
Message-ID: <45e8e6c40901071658j6a22fcc7gedcc41d73a61ff2a@mail.gmail.com>

Hello.  I noticed that the libertas driver causes a kernel oops in
more recent wireless-testing kernels (I am bisecting right now to
narrow this down).  To reproduce, load the driver and run iwconfig,
causing lbs_get_freq() to be called.

So far I know that this problem doesn't exist at the 2.6.28-rc2 tag
(commit 0173a3265b228da319ceb9c1ec6a5682fd1b2d92)  but I have seen it
in -rc7 and up through today's wireless-testing.  It seems that
there's a regression somewhere after -rc2.  I've reproduced this with
the USB hardware as well as an SDIO board.

[  118.571205] BUG: unable to handle kernel paging request at 00001e01
[  118.578500] IP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
[  118.585417] *pde = 00000000
[  118.588877] Oops: 0000 [#1]
[  118.592092] last sysfs file: /sys/block/ram9/range
[  118.592385] Modules linked in: usb8xxx libertas lib80211
[  118.592385]
[  118.592385] Pid: 2317, comm: iwconfig Not tainted (2.6.28-wl #65) Uknown
[  118.592385] EIP: 0060:[<c81fddda>] EFLAGS: 00010293 CPU: 0
[  118.592385] EIP is at lbs_get_freq+0x1a/0x160 [libertas]
[  118.592385] EAX: 00000000 EBX: 00000000 ECX: c6891ef8 EDX: c6891e98
[  118.592385] ESI: c6891ef8 EDI: c6891ef8 EBP: c7295000 ESP: c6891e10
[  118.592385]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
[  118.592385] Process iwconfig (pid: 2317, ti=c6890000 task=c7349880
task.ti=c6890000)
[  118.592385] Stack:
[  118.592385]  c8201b4b c6891ef8 00000010 ffffffa1 00008b05 c038aa20
00000000 c03c691c
[  118.592385]  00000000 c04bc7e0 c0301287 b7f01d70 c68ce000 c6895000
c04c8260 00000c04
[  118.592385]  c68c7b7c 00000000 c7295000 c6891ee8 c0300325 c6891ee8
c7295000 c6891ee8
[  118.592385] Call Trace:
[  118.592385]  [<c8201b4b>] lbs_get_name+0x2b/0xb0 [libertas]
[  118.592385]  [<c038aa20>] ioctl_standard_call+0x60/0x3a0
[  118.592385]  [<c0301287>] netif_receive_skb+0x1d7/0x3e0
[  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
[  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
[  118.592385]  [<c038a687>] wext_handle_ioctl+0x157/0x230
[  118.592385]  [<c81fddc0>] lbs_get_freq+0x0/0x160 [libertas]
[  118.592385]  [<c03034c4>] dev_ioctl+0x304/0x4f0
[  118.592385]  [<c02ffdd2>] net_rx_action+0x92/0x140
[  118.592385]  [<c027ca89>] pty_write+0x39/0x60
[  118.592385]  [<c02f4280>] sock_ioctl+0x0/0x260
[  118.592385]  [<c017e27f>] vfs_ioctl+0x1f/0x70
[  118.592385]  [<c017e65b>] do_vfs_ioctl+0x24b/0x490
[  118.592385]  [<c011654e>] update_curr+0x13e/0x190
[  118.592385]  [<c0117fab>] set_next_entity+0x2b/0x70
[  118.592385]  [<c0397c64>] schedule+0x1b4/0x350
[  118.592385]  [<c017e906>] sys_ioctl+0x66/0x70
[  118.592385]  [<c0103cd2>] syscall_call+0x7/0xb
[  118.592385] Code: e9 38 ff ff ff 8d b6 00 00 00 00 8d bf 00 00 00
00 56 89 ce 53 83 ec 0c 8b 98 a4 01 00 00 a1 80 19 22 c8 83 e0 21 83
f8 21 74 42 <0f> b6 8b 01 1e 00 00 31 d2 89 d8 e8 a6 fe ff ff 85 c0 0f
84 cd
[  118.592385] EIP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
SS:ESP 0068:c6891e10
[  118.594153] ---[ end trace f426cd49b2b378f4 ]---


From andrey at cozybit.com  Wed Jan  7 21:37:58 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Wed, 7 Jan 2009 18:37:58 -0800
Subject: libertas: BUG: unable to handle paging request
In-Reply-To: <45e8e6c40901071658j6a22fcc7gedcc41d73a61ff2a@mail.gmail.com>
References: <45e8e6c40901071658j6a22fcc7gedcc41d73a61ff2a@mail.gmail.com>
Message-ID: <45e8e6c40901071837o56dba8f1w6db5c7e982f698da@mail.gmail.com>

The commit that caused this regression is
29726d85d7b98558a8bc8e69b859bf12e1347f9f "netdevice libertas: Fix
directly reference of netdev->priv" by Wang Chen.  It probably causes
a problem with netdev->priv's offset and then we get a pointer
dereference problem when lbs_get_freq() tries to use its priv data.

  -Andrey

On Wed, Jan 7, 2009 at 4:58 PM, Andrey Yurovsky <andrey at cozybit.com> wrote:
> Hello.  I noticed that the libertas driver causes a kernel oops in
> more recent wireless-testing kernels (I am bisecting right now to
> narrow this down).  To reproduce, load the driver and run iwconfig,
> causing lbs_get_freq() to be called.
>
> So far I know that this problem doesn't exist at the 2.6.28-rc2 tag
> (commit 0173a3265b228da319ceb9c1ec6a5682fd1b2d92)  but I have seen it
> in -rc7 and up through today's wireless-testing.  It seems that
> there's a regression somewhere after -rc2.  I've reproduced this with
> the USB hardware as well as an SDIO board.
>
> [  118.571205] BUG: unable to handle kernel paging request at 00001e01
> [  118.578500] IP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
> [  118.585417] *pde = 00000000
> [  118.588877] Oops: 0000 [#1]
> [  118.592092] last sysfs file: /sys/block/ram9/range
> [  118.592385] Modules linked in: usb8xxx libertas lib80211
> [  118.592385]
> [  118.592385] Pid: 2317, comm: iwconfig Not tainted (2.6.28-wl #65) Uknown
> [  118.592385] EIP: 0060:[<c81fddda>] EFLAGS: 00010293 CPU: 0
> [  118.592385] EIP is at lbs_get_freq+0x1a/0x160 [libertas]
> [  118.592385] EAX: 00000000 EBX: 00000000 ECX: c6891ef8 EDX: c6891e98
> [  118.592385] ESI: c6891ef8 EDI: c6891ef8 EBP: c7295000 ESP: c6891e10
> [  118.592385]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
> [  118.592385] Process iwconfig (pid: 2317, ti=c6890000 task=c7349880
> task.ti=c6890000)
> [  118.592385] Stack:
> [  118.592385]  c8201b4b c6891ef8 00000010 ffffffa1 00008b05 c038aa20
> 00000000 c03c691c
> [  118.592385]  00000000 c04bc7e0 c0301287 b7f01d70 c68ce000 c6895000
> c04c8260 00000c04
> [  118.592385]  c68c7b7c 00000000 c7295000 c6891ee8 c0300325 c6891ee8
> c7295000 c6891ee8
> [  118.592385] Call Trace:
> [  118.592385]  [<c8201b4b>] lbs_get_name+0x2b/0xb0 [libertas]
> [  118.592385]  [<c038aa20>] ioctl_standard_call+0x60/0x3a0
> [  118.592385]  [<c0301287>] netif_receive_skb+0x1d7/0x3e0
> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
> [  118.592385]  [<c038a687>] wext_handle_ioctl+0x157/0x230
> [  118.592385]  [<c81fddc0>] lbs_get_freq+0x0/0x160 [libertas]
> [  118.592385]  [<c03034c4>] dev_ioctl+0x304/0x4f0
> [  118.592385]  [<c02ffdd2>] net_rx_action+0x92/0x140
> [  118.592385]  [<c027ca89>] pty_write+0x39/0x60
> [  118.592385]  [<c02f4280>] sock_ioctl+0x0/0x260
> [  118.592385]  [<c017e27f>] vfs_ioctl+0x1f/0x70
> [  118.592385]  [<c017e65b>] do_vfs_ioctl+0x24b/0x490
> [  118.592385]  [<c011654e>] update_curr+0x13e/0x190
> [  118.592385]  [<c0117fab>] set_next_entity+0x2b/0x70
> [  118.592385]  [<c0397c64>] schedule+0x1b4/0x350
> [  118.592385]  [<c017e906>] sys_ioctl+0x66/0x70
> [  118.592385]  [<c0103cd2>] syscall_call+0x7/0xb
> [  118.592385] Code: e9 38 ff ff ff 8d b6 00 00 00 00 8d bf 00 00 00
> 00 56 89 ce 53 83 ec 0c 8b 98 a4 01 00 00 a1 80 19 22 c8 83 e0 21 83
> f8 21 74 42 <0f> b6 8b 01 1e 00 00 31 d2 89 d8 e8 a6 fe ff ff 85 c0 0f
> 84 cd
> [  118.592385] EIP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
> SS:ESP 0068:c6891e10
> [  118.594153] ---[ end trace f426cd49b2b378f4 ]---
>


From andrey at cozybit.com  Wed Jan  7 22:45:53 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Wed, 7 Jan 2009 19:45:53 -0800
Subject: libertas: BUG: unable to handle paging request
In-Reply-To: <45e8e6c40901071837o56dba8f1w6db5c7e982f698da@mail.gmail.com>
References: <45e8e6c40901071658j6a22fcc7gedcc41d73a61ff2a@mail.gmail.com>
	<45e8e6c40901071837o56dba8f1w6db5c7e982f698da@mail.gmail.com>
Message-ID: <45e8e6c40901071945u27a8de0aqbf2b50f0075a32f3@mail.gmail.com>

Hmm, I do see the problem start at
29726d85d7b98558a8bc8e69b859bf12e1347f9f and after, but I don't think
that I'm right with my analysis, especially since the OOPS happens in
wext.c and the functions there (namely lbs_get_freq) use netdev->priv
directly.  I apologize for the noise but there is still something
wrong here that I'm trying to understand better.

  -Andrey

On Wed, Jan 7, 2009 at 6:37 PM, Andrey Yurovsky <andrey at cozybit.com> wrote:
> The commit that caused this regression is
> 29726d85d7b98558a8bc8e69b859bf12e1347f9f "netdevice libertas: Fix
> directly reference of netdev->priv" by Wang Chen.  It probably causes
> a problem with netdev->priv's offset and then we get a pointer
> dereference problem when lbs_get_freq() tries to use its priv data.
>
>  -Andrey
>
> On Wed, Jan 7, 2009 at 4:58 PM, Andrey Yurovsky <andrey at cozybit.com> wrote:
>> Hello.  I noticed that the libertas driver causes a kernel oops in
>> more recent wireless-testing kernels (I am bisecting right now to
>> narrow this down).  To reproduce, load the driver and run iwconfig,
>> causing lbs_get_freq() to be called.
>>
>> So far I know that this problem doesn't exist at the 2.6.28-rc2 tag
>> (commit 0173a3265b228da319ceb9c1ec6a5682fd1b2d92)  but I have seen it
>> in -rc7 and up through today's wireless-testing.  It seems that
>> there's a regression somewhere after -rc2.  I've reproduced this with
>> the USB hardware as well as an SDIO board.
>>
>> [  118.571205] BUG: unable to handle kernel paging request at 00001e01
>> [  118.578500] IP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
>> [  118.585417] *pde = 00000000
>> [  118.588877] Oops: 0000 [#1]
>> [  118.592092] last sysfs file: /sys/block/ram9/range
>> [  118.592385] Modules linked in: usb8xxx libertas lib80211
>> [  118.592385]
>> [  118.592385] Pid: 2317, comm: iwconfig Not tainted (2.6.28-wl #65) Uknown
>> [  118.592385] EIP: 0060:[<c81fddda>] EFLAGS: 00010293 CPU: 0
>> [  118.592385] EIP is at lbs_get_freq+0x1a/0x160 [libertas]
>> [  118.592385] EAX: 00000000 EBX: 00000000 ECX: c6891ef8 EDX: c6891e98
>> [  118.592385] ESI: c6891ef8 EDI: c6891ef8 EBP: c7295000 ESP: c6891e10
>> [  118.592385]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
>> [  118.592385] Process iwconfig (pid: 2317, ti=c6890000 task=c7349880
>> task.ti=c6890000)
>> [  118.592385] Stack:
>> [  118.592385]  c8201b4b c6891ef8 00000010 ffffffa1 00008b05 c038aa20
>> 00000000 c03c691c
>> [  118.592385]  00000000 c04bc7e0 c0301287 b7f01d70 c68ce000 c6895000
>> c04c8260 00000c04
>> [  118.592385]  c68c7b7c 00000000 c7295000 c6891ee8 c0300325 c6891ee8
>> c7295000 c6891ee8
>> [  118.592385] Call Trace:
>> [  118.592385]  [<c8201b4b>] lbs_get_name+0x2b/0xb0 [libertas]
>> [  118.592385]  [<c038aa20>] ioctl_standard_call+0x60/0x3a0
>> [  118.592385]  [<c0301287>] netif_receive_skb+0x1d7/0x3e0
>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
>> [  118.592385]  [<c038a687>] wext_handle_ioctl+0x157/0x230
>> [  118.592385]  [<c81fddc0>] lbs_get_freq+0x0/0x160 [libertas]
>> [  118.592385]  [<c03034c4>] dev_ioctl+0x304/0x4f0
>> [  118.592385]  [<c02ffdd2>] net_rx_action+0x92/0x140
>> [  118.592385]  [<c027ca89>] pty_write+0x39/0x60
>> [  118.592385]  [<c02f4280>] sock_ioctl+0x0/0x260
>> [  118.592385]  [<c017e27f>] vfs_ioctl+0x1f/0x70
>> [  118.592385]  [<c017e65b>] do_vfs_ioctl+0x24b/0x490
>> [  118.592385]  [<c011654e>] update_curr+0x13e/0x190
>> [  118.592385]  [<c0117fab>] set_next_entity+0x2b/0x70
>> [  118.592385]  [<c0397c64>] schedule+0x1b4/0x350
>> [  118.592385]  [<c017e906>] sys_ioctl+0x66/0x70
>> [  118.592385]  [<c0103cd2>] syscall_call+0x7/0xb
>> [  118.592385] Code: e9 38 ff ff ff 8d b6 00 00 00 00 8d bf 00 00 00
>> 00 56 89 ce 53 83 ec 0c 8b 98 a4 01 00 00 a1 80 19 22 c8 83 e0 21 83
>> f8 21 74 42 <0f> b6 8b 01 1e 00 00 31 d2 89 d8 e8 a6 fe ff ff 85 c0 0f
>> 84 cd
>> [  118.592385] EIP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
>> SS:ESP 0068:c6891e10
>> [  118.594153] ---[ end trace f426cd49b2b378f4 ]---
>>
>


From dcbw at redhat.com  Thu Jan  8 11:31:13 2009
From: dcbw at redhat.com (Dan Williams)
Date: Thu, 08 Jan 2009 11:31:13 -0500
Subject: firmware for GSPI '8686 available
In-Reply-To: <45e8e6c40901061413n1a984e58n8e1643caa1fd481e@mail.gmail.com>
References: <45e8e6c40901061413n1a984e58n8e1643caa1fd481e@mail.gmail.com>
Message-ID: <1231432273.21643.31.camel@localhost.localdomain>

On Tue, 2009-01-06 at 14:13 -0800, Andrey Yurovsky wrote:
> Marvell will make the 88W8686 GSPI firmware available for public
> download on their website in the next weeks.  In the meantime we've
> uploaded it to our website:
> http://cozybit.com/projects/gspi8686
> 
> Please note that you must accept Marvell's license before downloading the files.
> 
> We encourage you to use this firmware to test the patch set that Colin
> submitted on Jan 2nd.

I'm already pushing firmware for the following devices to Woodhouse's
linux-firmware tree:

mwl8k/fmimage_8687.fw
mwl8k/helper_8687.fw
libertas/gspi8686_v9.bin
libertas/sd8385.bin
libertas/sd8686_v9.bin
libertas/cf8385_helper.bin
libertas/sd8686_v8_helper.bin
libertas/cf8385.bin
libertas/usb8388_v9.bin
libertas/usb8388_v5.bin
libertas/sd8686_v8.bin
libertas/sd8686_v9_helper.bin
libertas/gspi8686_v9_helper.bin
libertas/sd8385_helper.bin

Pending one final sign-off from Manas, it'll be up and live.

Dan




From dcbw at redhat.com  Thu Jan  8 11:56:41 2009
From: dcbw at redhat.com (Dan Williams)
Date: Thu, 08 Jan 2009 11:56:41 -0500
Subject: [PATCH v2 2/3] libertas: Update libertas core with GSPI constants
In-Reply-To: <1230951623-26998-3-git-send-email-colin@cozybit.com>
References: <1230951623-26998-1-git-send-email-colin@cozybit.com>
	<1230951623-26998-2-git-send-email-colin@cozybit.com>
	<1230951623-26998-3-git-send-email-colin@cozybit.com>
Message-ID: <1231433801.21643.44.camel@localhost.localdomain>

On Fri, 2009-01-02 at 19:00 -0800, Colin McCabe wrote:
> Add GSPI constants to libertas core.
> 
> Fix misleading comment in lbs_setup_firmware.
> 
> Signed-off-by: Colin McCabe <colin at cozybit.com>
> Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>

Acked-by: Dan Williams <dcbw at redhat.com>

> ---
>  drivers/net/wireless/libertas/host.h    |    1 +
>  drivers/net/wireless/libertas/hostcmd.h |    8 ++++++++
>  drivers/net/wireless/libertas/main.c    |    5 ++---
>  3 files changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
> index 277ff19..d4457ef 100644
> --- a/drivers/net/wireless/libertas/host.h
> +++ b/drivers/net/wireless/libertas/host.h
> @@ -66,6 +66,7 @@
>  #define CMD_802_11_LED_GPIO_CTRL		0x004e
>  #define CMD_802_11_EEPROM_ACCESS		0x0059
>  #define CMD_802_11_BAND_CONFIG			0x0058
> +#define CMD_GSPI_BUS_CONFIG			0x005a
>  #define CMD_802_11D_DOMAIN_INFO			0x005b
>  #define CMD_802_11_KEY_MATERIAL			0x005e
>  #define CMD_802_11_SLEEP_PARAMS			0x0066
> diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
> index c6d5771..3c15611 100644
> --- a/drivers/net/wireless/libertas/hostcmd.h
> +++ b/drivers/net/wireless/libertas/hostcmd.h
> @@ -221,6 +221,14 @@ struct cmd_ds_mac_multicast_adr {
>  	u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
>  } __attribute__ ((packed));
>  
> +struct cmd_ds_gspi_bus_config {
> +	struct cmd_header hdr;
> +	__le16 action;
> +	__le16 bus_delay_mode;
> +	__le16 host_time_delay_to_read_port;
> +	__le16 host_time_delay_to_read_register;
> +} __attribute__ ((packed));
> +
>  struct cmd_ds_802_11_authenticate {
>  	u8 macaddr[ETH_ALEN];
>  	u8 authtype;
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index 3b8cb29..69f7479 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -1011,9 +1011,8 @@ void lbs_resume(struct lbs_private *priv)
>  EXPORT_SYMBOL_GPL(lbs_resume);
>  
>  /**
> - *  @brief This function downloads firmware image, gets
> - *  HW spec from firmware and set basic parameters to
> - *  firmware.
> + * @brief This function gets the HW spec from the firmware and sets
> + *        some basic parameters.
>   *
>   *  @param priv    A pointer to struct lbs_private structure
>   *  @return 	   0 or -1



From dcbw at redhat.com  Thu Jan  8 12:17:25 2009
From: dcbw at redhat.com (Dan Williams)
Date: Thu, 08 Jan 2009 12:17:25 -0500
Subject: [PATCH v2 3/3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <1230951623-26998-4-git-send-email-colin@cozybit.com>
References: <1230951623-26998-1-git-send-email-colin@cozybit.com>
	<1230951623-26998-2-git-send-email-colin@cozybit.com>
	<1230951623-26998-3-git-send-email-colin@cozybit.com>
	<1230951623-26998-4-git-send-email-colin@cozybit.com>
Message-ID: <1231435046.21643.53.camel@localhost.localdomain>

On Fri, 2009-01-02 at 19:00 -0800, Colin McCabe wrote:
> Add initial support for libertas devices using a GSPI interface.  This has
> been tested with the 8686.  At this time, as far as we know, GSPI firmware for
> this device is not publicly distributable, but we expect this to change.
> 
> GSPI is intended to be used on embedded systems. Board-specific parameters are
> required (see libertas_spi.h).

One thing we found we *really* wanted with SDIO was the ability to reset
the card completely, is there any ability to do that with the SPI
interface, or do you need to rely on board-specific methods to do that?

More below...

> Signed-off-by: Colin McCabe <colin at cozybit.com>
> Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
> ---
>  drivers/net/wireless/Kconfig           |    6 +
>  drivers/net/wireless/libertas/Makefile |    2 +
>  drivers/net/wireless/libertas/defs.h   |    2 +
>  drivers/net/wireless/libertas/if_spi.c | 1216 ++++++++++++++++++++++++++++++++
>  drivers/net/wireless/libertas/if_spi.h |  208 ++++++
>  include/linux/spi/libertas_spi.h       |   25 +
>  6 files changed, 1459 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/wireless/libertas/if_spi.c
>  create mode 100644 drivers/net/wireless/libertas/if_spi.h
>  create mode 100644 include/linux/spi/libertas_spi.h
> 
> diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
> index ea543fc..6f9ee26 100644
> --- a/drivers/net/wireless/Kconfig
> +++ b/drivers/net/wireless/Kconfig
> @@ -151,6 +151,12 @@ config LIBERTAS_SDIO
>  	---help---
>  	  A driver for Marvell Libertas 8385 and 8686 SDIO devices.
>  
> +config LIBERTAS_SPI
> +	tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
> +	depends on LIBERTAS && SPI
> +	---help---
> +	  A driver for Marvell Libertas 8686 SPI devices.
> +
>  config LIBERTAS_DEBUG
>  	bool "Enable full debugging output in the Libertas module."
>  	depends on LIBERTAS
> diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
> index 02080a3..0b69185 100644
> --- a/drivers/net/wireless/libertas/Makefile
> +++ b/drivers/net/wireless/libertas/Makefile
> @@ -4,8 +4,10 @@ libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o	\
>  usb8xxx-objs += if_usb.o
>  libertas_cs-objs += if_cs.o
>  libertas_sdio-objs += if_sdio.o
> +libertas_spi-objs += if_spi.o
>  
>  obj-$(CONFIG_LIBERTAS)     += libertas.o
>  obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
>  obj-$(CONFIG_LIBERTAS_CS)  += libertas_cs.o
>  obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
> +obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o
> diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
> index b7744d6..0d1494f 100644
> --- a/drivers/net/wireless/libertas/defs.h
> +++ b/drivers/net/wireless/libertas/defs.h
> @@ -41,6 +41,7 @@
>  #define LBS_DEB_HEX	0x00200000
>  #define LBS_DEB_SDIO	0x00400000
>  #define LBS_DEB_SYSFS	0x00800000
> +#define LBS_DEB_SPI	0x01000000
>  
>  extern unsigned int lbs_debug;
>  
> @@ -84,6 +85,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \
>  #define lbs_deb_thread(fmt, args...)    LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
>  #define lbs_deb_sdio(fmt, args...)      LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
>  #define lbs_deb_sysfs(fmt, args...)     LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
> +#define lbs_deb_spi(fmt, args...)       LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
>  
>  #define lbs_pr_info(format, args...) \
>  	printk(KERN_INFO DRV_NAME": " format, ## args)
> diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
> new file mode 100644
> index 0000000..6092574
> --- /dev/null
> +++ b/drivers/net/wireless/libertas/if_spi.c
> @@ -0,0 +1,1216 @@
> +/*
> + *	linux/drivers/net/wireless/libertas/if_spi.c
> + *
> + *	Driver for Marvell SPI WLAN cards.
> + *
> + *	Copyright 2008 Analog Devices Inc.
> + *
> + *	Authors:
> + *	Andrey Yurovsky <andrey at cozybit.com>
> + *	Colin McCabe <colin at cozybit.com>
> + *
> + *	Inspired by if_sdio.c, Copyright 2007-2008 Pierre Ossman
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/moduleparam.h>
> +#include <linux/firmware.h>
> +#include <linux/gpio.h>
> +#include <linux/jiffies.h>
> +#include <linux/kthread.h>
> +#include <linux/list.h>
> +#include <linux/netdevice.h>
> +#include <linux/spi/libertas_spi.h>
> +#include <linux/spi/spi.h>
> +
> +#include "host.h"
> +#include "decl.h"
> +#include "defs.h"
> +#include "dev.h"
> +#include "if_spi.h"
> +
> +struct if_spi_packet {
> +	struct list_head		list;
> +	u16				blen;
> +	u8				buffer[0] __attribute__((aligned(4)));
> +};
> +
> +struct if_spi_card {
> +	struct spi_device		*spi;
> +	struct lbs_private		*priv;
> +
> +	char				helper_fw_name[FIRMWARE_NAME_MAX];
> +	char				main_fw_name[FIRMWARE_NAME_MAX];
> +
> +	/* The card ID and card revision, as reported by the hardware. */
> +	u16				card_id;
> +	u8				card_rev;
> +
> +	/* Pin number for our GPIO chip-select. */
> +	/* TODO: Once the generic SPI layer has some additional features, we
> +	 * should take this out and use the normal chip select here.
> +	 * We need support for chip select delays, and not dropping chipselect
> +	 * after each word. */
> +	int				gpio_cs;
> +
> +	/* The last time that we initiated an SPU operation */
> +	unsigned long			prev_xfer_time;
> +
> +	int				use_dummy_writes;
> +	unsigned long			spu_port_delay;
> +	unsigned long			spu_reg_delay;
> +
> +	/* Handles all SPI communication (except for FW load) */
> +	struct task_struct		*spi_thread;
> +	int				run_thread;
> +
> +	/* Used to wake up the spi_thread */
> +	struct semaphore		spi_ready;
> +	struct semaphore		spi_thread_terminated;

Are these really using semaphore semantics, or would a mutex be more
appropriate here?  A ton of stuff got converted to mutexes a while back,
so if you don't actually need the specific semaphore behavior mutexes
might be a clearer choice.

> +	u8				cmd_buffer[IF_SPI_CMD_BUF_SIZE];
> +
> +	/* A buffer of incoming packets from libertas core.
> +	 * Since we can't sleep in hw_host_to_card, we have to buffer
> +	 * them. */
> +	struct list_head		cmd_packet_list;
> +	struct list_head		data_packet_list;
> +
> +	/* Protects cmd_packet_list and data_packet_list */
> +	spinlock_t			buffer_lock;
> +};
> +
> +static void free_if_spi_card(struct if_spi_card *card)
> +{
> +	struct list_head *cursor, *next;
> +	struct if_spi_packet *packet;
> +
> +	BUG_ON(card->run_thread);
> +	list_for_each_safe(cursor, next, &card->cmd_packet_list) {
> +		packet = container_of(cursor, struct if_spi_packet, list);
> +		list_del(&packet->list);
> +		kfree(packet);
> +	}
> +	list_for_each_safe(cursor, next, &card->data_packet_list) {
> +		packet = container_of(cursor, struct if_spi_packet, list);
> +		list_del(&packet->list);
> +		kfree(packet);
> +	}
> +	spi_set_drvdata(card->spi, NULL);
> +	kfree(card);
> +}
> +
> +static struct chip_ident chip_id_to_device_name[] = {
> +	{ .chip_id = 0x04, .name = 8385 },
> +	{ .chip_id = 0x0b, .name = 8686 },
> +};
> +
> +/*
> + * SPI Interface Unit Routines
> + *
> + * The SPU sits between the host and the WLAN module.
> + * All communication with the firmware is through SPU transactions.
> + *
> + * First we have to put a SPU register name on the bus. Then we can
> + * either read from or write to that register.
> + *
> + * For 16-bit transactions, byte order on the bus is big-endian.
> + * We don't have to worry about that here, though.
> + * The translation takes place in the SPI routines.
> + */
> +
> +static void spu_transaction_init(struct if_spi_card *card)
> +{
> +	if (!time_after(jiffies, card->prev_xfer_time + 1)) {
> +		/* Unfortunately, the SPU requires a delay between successive
> +		 * transactions. If our last transaction was more than a jiffy
> +		 * ago, we have obviously already delayed enough.
> +		 * If not, we have to busy-wait to be on the safe side. */
> +		ndelay(400);
> +	}
> +	gpio_set_value(card->gpio_cs, 0); /* assert CS */
> +}
> +
> +static void spu_transaction_finish(struct if_spi_card *card)
> +{
> +	gpio_set_value(card->gpio_cs, 1); /* drop CS */
> +	card->prev_xfer_time = jiffies;
> +}
> +
> +/* Write out a byte buffer to an SPI register,
> + * using a series of 16-bit transfers. */
> +static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
> +{
> +	int n;
> +	int err = 0;
> +	u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK;
> +
> +	/* You must give an even number of bytes to the SPU, even if it
> +	 * doesn't care about the last one.  */
> +	BUG_ON(len & 0x1);
> +
> +	spu_transaction_init(card);
> +
> +	/* write SPU register index */
> +	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
> +	if (err)
> +		goto out;
> +
> +	for (n = 0; n < len; n += sizeof(u16)) {
> +		err = spi_write(card->spi, buf + n, sizeof(u16));
> +		if (err)
> +			goto out;
> +	}
> +
> +out:
> +	spu_transaction_finish(card);
> +	return err;
> +}
> +
> +static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val)
> +{
> +	return spu_write(card, reg, (u8 *)&val, sizeof(u16));
> +}
> +
> +static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val)
> +{
> +	/* The lower 16 bits are written first. */
> +	u16 out[2];
> +	out[0] = val & 0xffff;
> +	out[1] = (val & 0xffff0000) >> 16;
> +	return spu_write(card, reg, (u8 *)&out, sizeof(u32));
> +}
> +
> +static inline int spu_reg_is_port_reg(u16 reg)
> +{
> +	switch (reg) {
> +	case IF_SPI_IO_RDWRPORT_REG:
> +	case IF_SPI_CMD_RDWRPORT_REG:
> +	case IF_SPI_DATA_RDWRPORT_REG:
> +		return 1;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
> +{
> +	unsigned int i, delay;
> +	int n, err = 0;
> +	u16 zero = 0;
> +	u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK;
> +
> +	/* You must take an even number of bytes from the SPU, even if you
> +	 * don't care about the last one.  */
> +	BUG_ON(len & 0x1);
> +
> +	spu_transaction_init(card);
> +
> +	/* write SPU register index */
> +	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
> +	if (err)

Do you really want 'goto out' here instead of 'return' so that
spu_transaction_finish() gets called?

> +		return err;
> +
> +	delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay :
> +						card->spu_reg_delay;
> +	if (card->use_dummy_writes) {
> +		/* Clock in dummy cycles while the SPU fills the FIFO */
> +		for (i = 0; i < delay / 16; ++i) {
> +			err = spi_write(card->spi, (u8 *)&zero, sizeof(u16));
> +			if (err)
> +				return err;

Same here.

> +		}
> +	} else {
> +		/* Busy-wait while the SPU fills the FIFO */
> +		ndelay(100 + (delay * 10));
> +	}
> +
> +	/* read in data */
> +	for (n = 0; n < len; n += sizeof(u16)) {
> +		err = spi_read(card->spi, buf + n, sizeof(u16));
> +		if (err)
> +			goto out;
> +	}
> +
> +out:
> +	spu_transaction_finish(card);
> +	return err;
> +}
> +
> +/* Read 16 bits from an SPI register */
> +static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
> +{
> +	return spu_read(card, reg, (u8 *)val, sizeof(u16));
> +}
> +
> +/* Read 32 bits from an SPI register.
> + * The low 16 bits are read first. */
> +static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
> +{
> +	u16 buf[2];
> +	int err;
> +	err = spu_read(card, reg, (u8 *)buf, sizeof(u32));
> +	if (!err)
> +		*val = buf[0] | (buf[1] << 16);
> +	return err;
> +}
> +
> +/* Keep reading 16 bits from an SPI register until you get the correct result.
> + *
> + * If mask = 0, the correct result is any non-zero number.
> + * If mask != 0, the correct result is any number where
> + * number & target_mask == target
> + *
> + * Returns -ETIMEDOUT if a second passes without the correct result. */
> +static int spu_wait_for_u16(struct if_spi_card *card, u16 reg,
> +			u16 target_mask, u16 target)
> +{
> +	int err;
> +	unsigned long timeout = jiffies + 5*HZ;
> +	while (1) {
> +		u16 val;
> +		err = spu_read_u16(card, reg, &val);
> +		if (err)
> +			return err;
> +		if (target_mask) {
> +			if ((val & target_mask) == target)
> +				return 0;
> +		} else {
> +			if (val)
> +				return 0;
> +		}
> +		udelay(100);
> +		if (time_after(jiffies, timeout)) {
> +			lbs_pr_err("%s: timeout with val=%02x, "
> +			       "target_mask=%02x, target=%02x\n",
> +			       __func__, val, target_mask, target);
> +			return -ETIMEDOUT;
> +		}
> +	}
> +}
> +
> +/* Read 16 bits from an SPI register until you receive a specific value.
> + * Returns -ETIMEDOUT if a 4 tries pass without success. */
> +static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target)
> +{
> +	int err, try;
> +	for (try = 0; try < 4; ++try) {
> +		u32 val = 0;
> +		err = spu_read_u32(card, reg, &val);
> +		if (err)
> +			return err;
> +		if (val == target)
> +			return 0;
> +		mdelay(100);
> +	}
> +	return -ETIMEDOUT;
> +}
> +
> +static int spu_set_interrupt_mode(struct if_spi_card *card,
> +			   int suppress_host_int,
> +			   int auto_int)
> +{
> +	int err = 0;
> +
> +	/* We can suppress a host interrupt by clearing the appropriate
> +	 * bit in the "host interrupt status mask" register */
> +	if (suppress_host_int) {
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
> +		if (err)
> +			return err;
> +	} else {
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG,
> +			      IF_SPI_HISM_TX_DOWNLOAD_RDY |
> +			      IF_SPI_HISM_RX_UPLOAD_RDY |
> +			      IF_SPI_HISM_CMD_DOWNLOAD_RDY |
> +			      IF_SPI_HISM_CARDEVENT |
> +			      IF_SPI_HISM_CMD_UPLOAD_RDY);
> +		if (err)
> +			return err;
> +	}
> +
> +	/* If auto-interrupts are on, the completion of certain transactions
> +	 * will trigger an interrupt automatically. If auto-interrupts
> +	 * are off, we need to set the "Card Interrupt Cause" register to
> +	 * trigger a card interrupt. */
> +	if (auto_int) {
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG,
> +				IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO |
> +				IF_SPI_HICT_RX_UPLOAD_OVER_AUTO |
> +				IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO |
> +				IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO);
> +		if (err)
> +			return err;
> +	} else {
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
> +		if (err)
> +			return err;
> +	}
> +	return err;
> +}
> +
> +static int spu_get_chip_revision(struct if_spi_card *card,
> +				  u16 *card_id, u8 *card_rev)
> +{
> +	int err = 0;
> +	u32 dev_ctrl;
> +	err = spu_read_u32(card, IF_SPI_DEVICEID_CTRL_REG, &dev_ctrl);
> +	if (err)
> +		return err;
> +	*card_id = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dev_ctrl);
> +	*card_rev = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dev_ctrl);
> +	return err;
> +}
> +
> +static int spu_set_bus_mode(struct if_spi_card *card, u16 mode)
> +{
> +	int err = 0;
> +	u16 rval;
> +	/* set bus mode */
> +	err = spu_write_u16(card, IF_SPI_SPU_BUS_MODE_REG, mode);
> +	if (err)
> +		return err;
> +	/* Check that we were able to read back what we just wrote. */
> +	err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval);
> +	if (err)
> +		return err;
> +	if (rval != mode) {
> +		lbs_pr_err("Can't read bus mode register.\n");
> +		return -EIO;
> +	}
> +	return 0;
> +}
> +
> +static int spu_init(struct if_spi_card *card, int use_dummy_writes)
> +{
> +	int err = 0;
> +	u32 delay;
> +
> +	/* We have to start up in timed delay mode so that we can safely
> +	 * read the Delay Read Register. */
> +	card->use_dummy_writes = 0;
> +	err = spu_set_bus_mode(card,
> +				IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
> +				IF_SPI_BUS_MODE_DELAY_METHOD_TIMED |
> +				IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
> +	if (err)
> +		return err;
> +	card->spu_port_delay = 1000;
> +	card->spu_reg_delay = 1000;
> +	err = spu_read_u32(card, IF_SPI_DELAY_READ_REG, &delay);
> +	if (err)
> +		return err;
> +	card->spu_port_delay = delay & 0x0000ffff;
> +	card->spu_reg_delay = (delay & 0xffff0000) >> 16;
> +
> +	/* If dummy clock delay mode has been requested, switch to it now */
> +	if (use_dummy_writes) {
> +		card->use_dummy_writes = 1;
> +		err = spu_set_bus_mode(card,
> +				IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
> +				IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK |
> +				IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
> +		if (err)
> +			return err;
> +	}
> +
> +	lbs_deb_spi("Initialized SPU unit. "
> +		    "spu_port_delay=0x%04lx, spu_reg_delay=0x%04lx\n",
> +		    card->spu_port_delay, card->spu_reg_delay);
> +	return err;
> +}
> +
> +/*
> + * Firmware Loading
> + */
> +
> +static int if_spi_prog_helper_firmware(struct if_spi_card *card)
> +{
> +	int err = 0;
> +	const struct firmware *firmware = NULL;
> +	int bytes_remaining;
> +	const u8 *fw;
> +	u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
> +	struct spi_device *spi = card->spi;
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	err = spu_set_interrupt_mode(card, 1, 0);
> +	if (err)
> +		goto out;
> +	/* Get helper firmware image */
> +	err = request_firmware(&firmware, card->helper_fw_name, &spi->dev);
> +	if (err) {
> +		lbs_pr_err("request_firmware failed with err = %d\n", err);
> +		goto out;
> +	}
> +	bytes_remaining = firmware->size;
> +	fw = firmware->data;
> +
> +	/* Load helper firmware image */
> +	while (bytes_remaining > 0) {
> +		/* Scratch pad 1 should contain the number of bytes we
> +		 * want to download to the firmware */
> +		err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
> +					HELPER_FW_LOAD_CHUNK_SZ);
> +		if (err)
> +			goto release_firmware;
> +
> +		err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
> +					IF_SPI_HIST_CMD_DOWNLOAD_RDY,
> +					IF_SPI_HIST_CMD_DOWNLOAD_RDY);
> +		if (err)
> +			goto release_firmware;
> +
> +		/* Feed the data into the command read/write port reg
> +		 * in chunks of 64 bytes */
> +		memset(temp, 0, sizeof(temp));
> +		memcpy(temp, fw,
> +		       min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ));
> +		mdelay(10);
> +		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
> +					temp, HELPER_FW_LOAD_CHUNK_SZ);
> +		if (err)
> +			goto release_firmware;
> +
> +		/* Interrupt the boot code */
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
> +		if (err)
> +			goto release_firmware;
> +		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
> +				       IF_SPI_CIC_CMD_DOWNLOAD_OVER);
> +		if (err)
> +			goto release_firmware;
> +		bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
> +		fw += HELPER_FW_LOAD_CHUNK_SZ;
> +	}
> +
> +	/* Once the helper / single stage firmware download is complete,
> +	 * write 0 to scratch pad 1 and interrupt the
> +	 * bootloader. This completes the helper download. */
> +	err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
> +	if (err)
> +		goto release_firmware;
> +	err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
> +	if (err)
> +		goto release_firmware;
> +	err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
> +				IF_SPI_CIC_CMD_DOWNLOAD_OVER);
> +		goto release_firmware;
> +
> +	lbs_deb_spi("waiting for helper to boot...\n");
> +
> +release_firmware:
> +	release_firmware(firmware);
> +out:
> +	if (err)
> +		lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
> +	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
> +	return err;
> +}
> +
> +/* Returns the length of the next packet the firmware expects us to send
> + * Sets crc_err if the previous transfer had a CRC error. */
> +static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
> +						int *crc_err)
> +{
> +	u16 len;
> +	int err = 0;
> +
> +	/* wait until the host interrupt status register indicates
> +	 * that we are ready to download */
> +	err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
> +				IF_SPI_HIST_CMD_DOWNLOAD_RDY,
> +				IF_SPI_HIST_CMD_DOWNLOAD_RDY);
> +	if (err) {
> +		lbs_pr_err("timed out waiting for host_int_status\n");
> +		return err;
> +	}
> +
> +	/* Ask the device how many bytes of firmware it wants. */
> +	err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
> +	if (err)
> +		return err;
> +
> +	if (len > IF_SPI_CMD_BUF_SIZE) {
> +		lbs_pr_err("firmware load device requested a larger "
> +			   "tranfer than we are prepared to "
> +			   "handle. (len = %d)\n", len);
> +		return -EIO;
> +	}
> +	if (len & 0x1) {
> +		lbs_deb_spi("%s: crc error\n", __func__);
> +		len &= ~0x1;
> +		*crc_err = 1;
> +	} else
> +		*crc_err = 0;
> +
> +	return len;
> +}
> +
> +static int if_spi_prog_main_firmware(struct if_spi_card *card)
> +{
> +	int len, prev_len;
> +	int bytes, crc_err = 0, err = 0;
> +	const struct firmware *firmware = NULL;
> +	const u8 *fw;
> +	struct spi_device *spi = card->spi;
> +	u16 num_crc_errs;
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	err = spu_set_interrupt_mode(card, 1, 0);
> +	if (err)
> +		goto out;
> +
> +	/* Get firmware image */
> +	err = request_firmware(&firmware, card->main_fw_name, &spi->dev);
> +	if (err) {
> +		lbs_pr_err("%s: can't get firmware '%s' from kernel. "
> +			"err = %d\n", __func__, card->main_fw_name, err);
> +		goto out;
> +	}
> +
> +	err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
> +	if (err) {
> +		lbs_pr_err("%s: timed out waiting for initial "
> +			   "scratch reg = 0\n", __func__);
> +		goto release_firmware;
> +	}
> +
> +	num_crc_errs = 0;
> +	prev_len = 0;
> +	bytes = firmware->size;
> +	fw = firmware->data;
> +	while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
> +		if (len < 0) {
> +			err = len;
> +			goto release_firmware;
> +		}
> +		if (bytes < 0) {
> +			/* If there are no more bytes left, we would normally
> +			 * expect to have terminated with len = 0 */
> +			lbs_pr_err("Firmware load wants more bytes "
> +				   "than we have to offer.\n");
> +			break;
> +		}
> +		if (crc_err) {
> +			/* Previous transfer failed. */
> +			if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) {
> +				lbs_pr_err("Too many CRC errors encountered "
> +					   "in firmware load.\n");
> +				err = -EIO;
> +				goto release_firmware;
> +			}
> +		} else {
> +			/* Previous transfer succeeded. Advance counters. */
> +			bytes -= prev_len;
> +			fw += prev_len;
> +		}
> +		if (bytes < len) {
> +			memset(card->cmd_buffer, 0, len);
> +			memcpy(card->cmd_buffer, fw, bytes);
> +		} else
> +			memcpy(card->cmd_buffer, fw, len);
> +
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
> +		if (err)
> +			goto release_firmware;
> +		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
> +				card->cmd_buffer, len);
> +		if (err)
> +			goto release_firmware;
> +		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
> +					IF_SPI_CIC_CMD_DOWNLOAD_OVER);
> +		if (err)
> +			goto release_firmware;
> +		prev_len = len;
> +	}
> +	if (bytes > prev_len) {
> +		lbs_pr_err("firmware load wants fewer bytes than "
> +			   "we have to offer.\n");
> +	}
> +
> +	/* Confirm firmware download */
> +	err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG,
> +					SUCCESSFUL_FW_DOWNLOAD_MAGIC);
> +	if (err) {
> +		lbs_pr_err("failed to confirm the firmware download\n");
> +		goto release_firmware;
> +	}
> +
> +release_firmware:
> +	release_firmware(firmware);
> +
> +out:
> +	if (err)
> +		lbs_pr_err("failed to load firmware (err=%d)\n", err);
> +	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
> +	return err;
> +}
> +
> +/*
> + * SPI Transfer Thread
> + *
> + * The SPI thread handles all SPI transfers, so there is no need for a lock.
> + */
> +
> +/* Move a command from the card to the host */
> +static int if_spi_c2h_cmd(struct if_spi_card *card)
> +{
> +	struct lbs_private *priv = card->priv;
> +	unsigned long flags;
> +	int err = 0;
> +	u16 len;
> +	u8 i;
> +
> +	/* We need a buffer big enough to handle whatever people send to
> +	 * hw_host_to_card */
> +	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE);
> +	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE);
> +
> +	/* It's just annoying if the buffer size isn't a multiple of 4, because
> +	 * then we might have len <  IF_SPI_CMD_BUF_SIZE  but 
> +	 * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */
> +	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0);
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	/* How many bytes are there to read? */
> +	err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len);
> +	if (err)
> +		goto out;
> +	if (!len) {
> +		lbs_pr_err("%s: error: card has no data for host\n",
> +			   __func__);
> +		err = -EINVAL;
> +		goto out;
> +	} else if (len > IF_SPI_CMD_BUF_SIZE) {
> +		lbs_pr_err("%s: error: response packet too large: "
> +			   "%d bytes, but maximum is %d\n",
> +			   __func__, len, IF_SPI_CMD_BUF_SIZE);
> +		err = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* Read the data from the WLAN module into our command buffer */
> +	err = spu_read(card, IF_SPI_CMD_RDWRPORT_REG,
> +				card->cmd_buffer, ALIGN(len, 4));
> +	if (err)
> +		goto out;
> +
> +	spin_lock_irqsave(&priv->driver_lock, flags);
> +	i = (priv->resp_idx == 0) ? 1 : 0;
> +	BUG_ON(priv->resp_len[i]);
> +	priv->resp_len[i] = len;
> +	memcpy(priv->resp_buf[i], card->cmd_buffer, len);
> +	lbs_notify_command_response(priv, i);
> +	spin_unlock_irqrestore(&priv->driver_lock, flags);
> +
> +out:
> +	if (err)
> +		lbs_pr_err("%s: err=%d\n", __func__, err);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +	return err;
> +}
> +
> +/* Move data from the card to the host */
> +static int if_spi_c2h_data(struct if_spi_card *card)
> +{
> +	struct sk_buff *skb;
> +	char *data;
> +	u16 len;
> +	int err = 0;
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	/* How many bytes are there to read? */
> +	err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
> +	if (err)
> +		goto out;
> +	if (!len) {
> +		lbs_pr_err("%s: error: card has no data for host\n",
> +			   __func__);
> +		err = -EINVAL;
> +		goto out;
> +	} else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
> +		lbs_pr_err("%s: error: card has %d bytes of data, but "
> +			   "our maximum skb size is %u\n",
> +			   __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
> +		err = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* TODO: should we allocate a smaller skb if we have less data? */
> +	skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
> +	if (!skb) {
> +		err = -ENOBUFS;
> +		goto out;
> +	}
> +	skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
> +	data = skb_put(skb, len);
> +
> +	/* Read the data from the WLAN module into our skb... */
> +	err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4));
> +	if (err)
> +		goto free_skb;
> +
> +	/* pass the SKB to libertas */
> +	err = lbs_process_rxed_packet(card->priv, skb);
> +	if (err)
> +		goto free_skb;
> +
> +	/* success */
> +	goto out;
> +
> +free_skb:
> +	dev_kfree_skb(skb);
> +out:
> +	if (err)
> +		lbs_pr_err("%s: err=%d\n", __func__, err);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +	return err;
> +}
> +
> +/* Move data or a command from the host to the card. */
> +static void if_spi_h2c(struct if_spi_card *card,
> +			struct if_spi_packet *packet, int type)
> +{
> +	int err = 0;
> +	u16 int_type, port_reg;
> +
> +	switch (type) {
> +	case MVMS_DAT:
> +		int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
> +		port_reg = IF_SPI_DATA_RDWRPORT_REG;
> +		break;
> +	case MVMS_CMD:
> +		int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
> +		port_reg = IF_SPI_CMD_RDWRPORT_REG;
> +		break;
> +	default:
> +		lbs_pr_err("can't transfer buffer of type %d\n", type);
> +		err = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* Write the data to the card */
> +	err = spu_write(card, port_reg, packet->buffer, packet->blen);
> +	if (err)
> +		goto out;
> +
> +out:
> +	kfree(packet);
> +
> +	if (err)
> +		lbs_pr_err("%s: error %d\n", __func__, err);
> +}
> +
> +/* Inform the host about a card event */
> +static void if_spi_e2h(struct if_spi_card *card)
> +{
> +	int err = 0;
> +	unsigned long flags;
> +	u32 cause;
> +	struct lbs_private *priv = card->priv;
> +
> +	err = spu_read_u32(card, IF_SPI_SCRATCH_3_REG, &cause);
> +	if (err)
> +		goto out;
> +
> +	spin_lock_irqsave(&priv->driver_lock, flags);
> +	lbs_queue_event(priv, cause & 0xff);
> +	spin_unlock_irqrestore(&priv->driver_lock, flags);
> +
> +out:
> +	if (err)
> +		lbs_pr_err("%s: error %d\n", __func__, err);
> +}
> +
> +static int lbs_spi_thread(void *data)
> +{
> +	int err;
> +	struct if_spi_card *card = data;
> +	u16 hiStatus;
> +	unsigned long flags;
> +	struct if_spi_packet *packet;
> +
> +	while (1) {
> +		/* Wait to be woken up by one of two things.  First, our ISR
> +		 * could tell us that something happened on the WLAN.
> +		 * Secondly, libertas could call hw_host_to_card with more
> +		 * data, which we might be able to send.
> +		 */
> +		do {
> +			err = down_interruptible(&card->spi_ready);
> +			if (!card->run_thread) {
> +				up(&card->spi_thread_terminated);
> +				do_exit(0);
> +			}
> +		} while (err == EINTR);
> +
> +		/* Read the host interrupt status register to see what we
> +		 * can do. */
> +		err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
> +					&hiStatus);
> +		if (err) {
> +			lbs_pr_err("I/O error\n");
> +			goto err;
> +		}
> +
> +		if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY)
> +			err = if_spi_c2h_cmd(card);
> +			if (err)
> +				goto err;
> +		if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY)
> +			err = if_spi_c2h_data(card);
> +			if (err)
> +				goto err;
> +		if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) {
> +			/* This means two things. First of all,
> +			 * if there was a previous command sent, the card has
> +			 * successfully received it.
> +			 * Secondly, it is now ready to download another
> +			 * command.
> +			 */
> +			lbs_host_to_card_done(card->priv);
> +
> +			/* Do we have any command packets from the host to
> +			 * send? */
> +			packet = NULL;
> +			spin_lock_irqsave(&card->buffer_lock, flags);
> +			if (!list_empty(&card->cmd_packet_list)) {
> +				packet = (struct if_spi_packet *)(card->
> +						cmd_packet_list.next);
> +				list_del(&packet->list);
> +			}
> +			spin_unlock_irqrestore(&card->buffer_lock, flags);
> +
> +			if (packet)
> +				if_spi_h2c(card, packet, MVMS_CMD);
> +		}
> +		if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
> +			/* Do we have any data packets from the host to
> +			 * send? */
> +			packet = NULL;
> +			spin_lock_irqsave(&card->buffer_lock, flags);
> +			if (!list_empty(&card->data_packet_list)) {
> +				packet = (struct if_spi_packet *)(card->
> +						data_packet_list.next);
> +				list_del(&packet->list);
> +			}
> +			spin_unlock_irqrestore(&card->buffer_lock, flags);
> +
> +			if (packet)
> +				if_spi_h2c(card, packet, MVMS_DAT);
> +		}
> +		if (hiStatus & IF_SPI_HIST_CARD_EVENT) {
> +			if_spi_e2h(card);
> +		}
> +
> +		/* TODO: implement IF_SPI_HIST_CARD_EVENT
> +		 * Eventually this should feed into lbs_queue_event */

This comment can go as it looks like you've handled it already :)

> +err:
> +		if (err)
> +			lbs_pr_err("%s: got error %d\n", __func__, err);
> +	}
> +}
> +
> +/* Block until lbs_spi_thread thread has terminated */
> +static void if_spi_terminate_spi_thread(struct if_spi_card *card)
> +{
> +	/* It would be nice to use kthread_stop here, but that function
> +	 * can't wake threads waiting for a semaphore. */
> +	card->run_thread = 0;
> +	up(&card->spi_ready);
> +	down(&card->spi_thread_terminated);
> +}
> +
> +/*
> + * Host to Card
> + *
> + * Called from Libertas to transfer some data to the WLAN device
> + * We can't sleep here. */
> +static int if_spi_host_to_card(struct lbs_private *priv,
> +				u8 type, u8 *buf, u16 nb)
> +{
> +	int err = 0;
> +	unsigned long flags;
> +	struct if_spi_card *card = priv->card;
> +	struct if_spi_packet *packet;
> +	u16 blen;
> +
> +	lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
> +
> +	if (nb == 0) {
> +		lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
> +		err = -EINVAL;
> +		goto out;
> +	}
> +	blen = ALIGN(nb, 4);
> +	packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
> +	if (!packet) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +	packet->blen = blen;
> +	memcpy(packet->buffer, buf, nb);
> +	memset(packet->buffer + nb, 0, blen - nb);
> +
> +	switch (type) {
> +	case MVMS_CMD:
> +		priv->dnld_sent = DNLD_CMD_SENT;
> +		spin_lock_irqsave(&card->buffer_lock, flags);
> +		list_add_tail(&packet->list, &card->cmd_packet_list);
> +		spin_unlock_irqrestore(&card->buffer_lock, flags);
> +		break;
> +	case MVMS_DAT:
> +		priv->dnld_sent = DNLD_DATA_SENT;
> +		spin_lock_irqsave(&card->buffer_lock, flags);
> +		list_add_tail(&packet->list, &card->data_packet_list);
> +		spin_unlock_irqrestore(&card->buffer_lock, flags);
> +		break;
> +	default:
> +		lbs_pr_err("can't transfer buffer of type %d", type);
> +		err = -EINVAL;
> +		break;
> +	}
> +
> +	/* Wake up the spi thread */
> +	up(&card->spi_ready);
> +out:
> +	lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
> +	return err;
> +}
> +
> +/*
> + * Host Interrupts
> + *
> + * Service incoming interrupts from the WLAN device. We can't sleep here, so
> + * don't try to talk on the SPI bus, just wake up the SPI thread.
> + */
> +static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
> +{
> +	struct if_spi_card *card = dev_id;
> +
> +	up(&card->spi_ready);
> +	return IRQ_HANDLED;
> +}
> +
> +/*
> + * SPI callbacks
> + */
> +
> +static int if_spi_calculate_fw_names(u16 card_id,
> +			      char *helper_fw, char *main_fw)
> +{
> +	int i;
> +	for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
> +		if (card_id == chip_id_to_device_name[i].chip_id)
> +			break;
> +	}
> +	if (i == ARRAY_SIZE(chip_id_to_device_name)) {
> +		lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
> +		return -EAFNOSUPPORT;
> +	}
> +	snprintf(helper_fw, FIRMWARE_NAME_MAX, "spi%d_helper.bin",
> +		 chip_id_to_device_name[i].name);
> +	snprintf(main_fw, FIRMWARE_NAME_MAX, "spi%d.bin",
> +		 chip_id_to_device_name[i].name);

Could you look for firmware in the "libertas/" directory, and could we
make the prefix of the firmware be "gspi" to match the actual Marvell
firmware names?

The firmware (at least for gspi8686) is in the process of getting pushed
to the linux-firmware tree, and I'd like to consolidate libertas
firmware into the libertas/ subdirectory for all libertas interface
drivers.

Dan

> +	return 0;
> +}
> +
> +static int __devinit if_spi_probe(struct spi_device *spi)
> +{
> +	struct if_spi_card *card;
> +	struct lbs_private *priv = NULL;
> +	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
> +	int err = 0;
> +	u32 scratch;
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	/* Allocate card structure to represent this specific device */
> +	card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL);
> +	if (!card) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +	spi_set_drvdata(spi, card);
> +	card->spi = spi;
> +	card->gpio_cs = pdata->gpio_cs;
> +	card->prev_xfer_time = jiffies;
> +
> +	sema_init(&card->spi_ready, 0);
> +	sema_init(&card->spi_thread_terminated, 0);
> +	INIT_LIST_HEAD(&card->cmd_packet_list);
> +	INIT_LIST_HEAD(&card->data_packet_list);
> +	spin_lock_init(&card->buffer_lock);
> +
> +	/* set up GPIO CS line. TODO: use  regular CS line */
> +	err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select");
> +	if (err)
> +		goto free_card;
> +	err = gpio_direction_output(card->gpio_cs, 1);
> +	if (err)
> +		goto free_gpio;
> +
> +	/* Initialize the SPI Interface Unit */
> +	err = spu_init(card, pdata->use_dummy_writes);
> +	if (err)
> +		goto free_gpio;
> +	err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
> +	if (err)
> +		goto free_gpio;
> +
> +	/* Firmware load */
> +	err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
> +	if (err)
> +		goto free_gpio;
> +	if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
> +		lbs_deb_spi("Firmware is already loaded for "
> +			    "Marvell WLAN 802.11 adapter\n");
> +	else {
> +		err = if_spi_calculate_fw_names(card->card_id,
> +				card->helper_fw_name, card->main_fw_name);
> +		if (err)
> +			goto free_gpio;
> +
> +		lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
> +				"(chip_id = 0x%04x, chip_rev = 0x%02x) "
> +				"attached to SPI bus_num %d, chip_select %d. "
> +				"spi->max_speed_hz=%d\n",
> +				card->card_id, card->card_rev,
> +				spi->master->bus_num, spi->chip_select,
> +				spi->max_speed_hz);
> +		err = if_spi_prog_helper_firmware(card);
> +		if (err)
> +			goto free_gpio;
> +		err = if_spi_prog_main_firmware(card);
> +		if (err)
> +			goto free_gpio;
> +		lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
> +	}
> +
> +	err = spu_set_interrupt_mode(card, 0, 1);
> +	if (err)
> +		goto free_gpio;
> +
> +	/* Register our card with libertas.
> +	 * This will call alloc_etherdev */
> +	priv = lbs_add_card(card, &spi->dev);
> +	if (!priv) {
> +		err = -ENOMEM;
> +		goto free_gpio;
> +	}
> +	card->priv = priv;
> +	priv->card = card;
> +	priv->hw_host_to_card = if_spi_host_to_card;
> +	priv->fw_ready = 1;
> +	priv->ps_supported = 1;
> +
> +	/* Initialize interrupt handling stuff. */
> +	card->run_thread = 1;
> +	card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread");
> +	if (IS_ERR(card->spi_thread)) {
> +		card->run_thread = 0;
> +		err = PTR_ERR(card->spi_thread);
> +		lbs_pr_err("error creating SPI thread: err=%d\n", err);
> +		goto remove_card;
> +	}
> +	err = request_irq(spi->irq, if_spi_host_interrupt,
> +			IRQF_TRIGGER_FALLING, "libertas_spi", card);
> +	if (err) {
> +		lbs_pr_err("can't get host irq line-- request_irq failed\n");
> +		goto terminate_thread;
> +	}
> +
> +	/* Start the card.
> +	 * This will call register_netdev, and we'll start
> +	 * getting interrupts... */
> +	err = lbs_start_card(priv);
> +	if (err)
> +		goto release_irq;
> +
> +	lbs_deb_spi("Finished initializing WLAN module.\n");
> +
> +	/* successful exit */
> +	goto out;
> +
> +release_irq:
> +	free_irq(spi->irq, card);
> +terminate_thread:
> +	if_spi_terminate_spi_thread(card);
> +remove_card:
> +	lbs_remove_card(priv); /* will call free_netdev */
> +free_gpio:
> +	gpio_free(card->gpio_cs);
> +free_card:
> +	free_if_spi_card(card);
> +out:
> +	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
> +	return err;
> +}
> +
> +static int __devexit libertas_spi_remove(struct spi_device *spi)
> +{
> +	struct if_spi_card *card = spi_get_drvdata(spi);
> +	struct lbs_private *priv = card->priv;
> +
> +	lbs_deb_spi("libertas_spi_remove\n");
> +	lbs_deb_enter(LBS_DEB_SPI);
> +	priv->surpriseremoved = 1;
> +
> +	lbs_stop_card(priv);
> +	free_irq(spi->irq, card);
> +	if_spi_terminate_spi_thread(card);
> +	lbs_remove_card(priv); /* will call free_netdev */
> +	gpio_free(card->gpio_cs);
> +	free_if_spi_card(card);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +	return 0;
> +}
> +
> +static struct spi_driver libertas_spi_driver = {
> +	.probe	= if_spi_probe,
> +	.remove = __devexit_p(libertas_spi_remove),
> +	.driver = {
> +		.name	= "libertas_spi",
> +		.bus	= &spi_bus_type,
> +		.owner	= THIS_MODULE,
> +	},
> +};
> +
> +/*
> + * Module functions
> + */
> +
> +static int __init if_spi_init_module(void)
> +{
> +	int ret = 0;
> +	lbs_deb_enter(LBS_DEB_SPI);
> +	printk(KERN_INFO "libertas_spi: Libertas SPI driver\n");
> +	ret = spi_register_driver(&libertas_spi_driver);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +	return ret;
> +}
> +
> +static void __exit if_spi_exit_module(void)
> +{
> +	lbs_deb_enter(LBS_DEB_SPI);
> +	spi_unregister_driver(&libertas_spi_driver);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +}
> +
> +module_init(if_spi_init_module);
> +module_exit(if_spi_exit_module);
> +
> +MODULE_DESCRIPTION("Libertas SPI WLAN Driver");
> +MODULE_AUTHOR("Andrey Yurovsky <andrey at cozybit.com>, "
> +	      "Colin McCabe <colin at cozybit.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h
> new file mode 100644
> index 0000000..2103869
> --- /dev/null
> +++ b/drivers/net/wireless/libertas/if_spi.h
> @@ -0,0 +1,208 @@
> +/*
> + *	linux/drivers/net/wireless/libertas/if_spi.c
> + *
> + *	Driver for Marvell SPI WLAN cards.
> + *
> + *	Copyright 2008 Analog Devices Inc.
> + *
> + *	Authors:
> + *	Andrey Yurovsky <andrey at cozybit.com>
> + *	Colin McCabe <colin at cozybit.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + */
> +
> +#ifndef _LBS_IF_SPI_H_
> +#define _LBS_IF_SPI_H_
> +
> +#define IPFIELD_ALIGN_OFFSET 2
> +#define IF_SPI_CMD_BUF_SIZE 2400
> +
> +/***************** Firmware *****************/
> +struct chip_ident {
> +	u16 chip_id;
> +	u16 name;
> +};
> +
> +#define MAX_MAIN_FW_LOAD_CRC_ERR 10
> +
> +/* Chunk size when loading the helper firmware */
> +#define HELPER_FW_LOAD_CHUNK_SZ 64
> +
> +/* Value to write to indicate end of helper firmware dnld */
> +#define FIRMWARE_DNLD_OK 0x0000
> +
> +/* Value to check once the main firmware is downloaded */
> +#define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888
> +
> +/***************** SPI Interface Unit *****************/
> +/* Masks used in SPI register read/write operations */
> +#define IF_SPI_READ_OPERATION_MASK 0x0
> +#define IF_SPI_WRITE_OPERATION_MASK 0x8000
> +
> +/* SPI register offsets. 4-byte aligned. */
> +#define IF_SPI_DEVICEID_CTRL_REG 0x00	/* DeviceID controller reg */
> +#define IF_SPI_IO_READBASE_REG 0x04 	/* Read I/O base reg */
> +#define IF_SPI_IO_WRITEBASE_REG 0x08	/* Write I/O base reg */
> +#define IF_SPI_IO_RDWRPORT_REG 0x0C	/* Read/Write I/O port reg */
> +
> +#define IF_SPI_CMD_READBASE_REG 0x10	/* Read command base reg */
> +#define IF_SPI_CMD_WRITEBASE_REG 0x14	/* Write command base reg */
> +#define IF_SPI_CMD_RDWRPORT_REG 0x18	/* Read/Write command port reg */
> +
> +#define IF_SPI_DATA_READBASE_REG 0x1C	/* Read data base reg */
> +#define IF_SPI_DATA_WRITEBASE_REG 0x20	/* Write data base reg */
> +#define IF_SPI_DATA_RDWRPORT_REG 0x24	/* Read/Write data port reg */
> +
> +#define IF_SPI_SCRATCH_1_REG 0x28	/* Scratch reg 1 */
> +#define IF_SPI_SCRATCH_2_REG 0x2C	/* Scratch reg 2 */
> +#define IF_SPI_SCRATCH_3_REG 0x30	/* Scratch reg 3 */
> +#define IF_SPI_SCRATCH_4_REG 0x34	/* Scratch reg 4 */
> +
> +#define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */
> +#define IF_SPI_TX_FRAME_STATUS_REG 0x3C	/* Tx frame status reg */
> +
> +#define IF_SPI_HOST_INT_CTRL_REG 0x40	/* Host interrupt controller reg */
> +
> +#define IF_SPI_CARD_INT_CAUSE_REG 0x44	/* Card interrupt cause reg */
> +#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */
> +#define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */
> +#define IF_SPI_CARD_INT_STATUS_MASK_REG	0x50 /* Card interrupt status mask */
> +
> +#define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */
> +
> +#define IF_SPI_HOST_INT_CAUSE_REG 0x58	/* Host interrupt cause reg */
> +#define IF_SPI_HOST_INT_STATUS_REG 0x5C	/* Host interrupt status reg */
> +#define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */
> +#define IF_SPI_HOST_INT_STATUS_MASK_REG	0x64 /* Host interrupt status mask */
> +#define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */
> +
> +#define IF_SPI_DELAY_READ_REG 0x6C	/* Delay read reg */
> +#define IF_SPI_SPU_BUS_MODE_REG 0x70	/* SPU BUS mode reg */
> +
> +/***************** IF_SPI_DEVICEID_CTRL_REG *****************/
> +#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16)
> +#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff)
> +
> +/***************** IF_SPI_HOST_INT_CTRL_REG *****************/
> +/** Host Interrupt Control bit : Wake up */
> +#define IF_SPI_HICT_WAKE_UP				(1<<0)
> +/** Host Interrupt Control bit : WLAN ready */
> +#define IF_SPI_HICT_WLAN_READY				(1<<1)
> +/*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY		(1<<2) */
> +/*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY		(1<<3) */
> +/*#define IF_SPI_HICT_IRQSRC_WLAN			(1<<4) */
> +/** Host Interrupt Control bit : Tx auto download */
> +#define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO		(1<<5)
> +/** Host Interrupt Control bit : Rx auto upload */
> +#define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO			(1<<6)
> +/** Host Interrupt Control bit : Command auto download */
> +#define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO		(1<<7)
> +/** Host Interrupt Control bit : Command auto upload */
> +#define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO		(1<<8)
> +
> +/***************** IF_SPI_CARD_INT_CAUSE_REG *****************/
> +/** Card Interrupt Case bit : Tx download over */
> +#define IF_SPI_CIC_TX_DOWNLOAD_OVER			(1<<0)
> +/** Card Interrupt Case bit : Rx upload over */
> +#define IF_SPI_CIC_RX_UPLOAD_OVER			(1<<1)
> +/** Card Interrupt Case bit : Command download over */
> +#define IF_SPI_CIC_CMD_DOWNLOAD_OVER			(1<<2)
> +/** Card Interrupt Case bit : Host event */
> +#define IF_SPI_CIC_HOST_EVENT				(1<<3)
> +/** Card Interrupt Case bit : Command upload over */
> +#define IF_SPI_CIC_CMD_UPLOAD_OVER			(1<<4)
> +/** Card Interrupt Case bit : Power down */
> +#define IF_SPI_CIC_POWER_DOWN				(1<<5)
> +
> +/***************** IF_SPI_CARD_INT_STATUS_REG *****************/
> +#define IF_SPI_CIS_TX_DOWNLOAD_OVER			(1<<0)
> +#define IF_SPI_CIS_RX_UPLOAD_OVER			(1<<1)
> +#define IF_SPI_CIS_CMD_DOWNLOAD_OVER			(1<<2)
> +#define IF_SPI_CIS_HOST_EVENT				(1<<3)
> +#define IF_SPI_CIS_CMD_UPLOAD_OVER			(1<<4)
> +#define IF_SPI_CIS_POWER_DOWN				(1<<5)
> +
> +/***************** IF_SPI_HOST_INT_CAUSE_REG *****************/
> +#define IF_SPI_HICU_TX_DOWNLOAD_RDY			(1<<0)
> +#define IF_SPI_HICU_RX_UPLOAD_RDY			(1<<1)
> +#define IF_SPI_HICU_CMD_DOWNLOAD_RDY			(1<<2)
> +#define IF_SPI_HICU_CARD_EVENT				(1<<3)
> +#define IF_SPI_HICU_CMD_UPLOAD_RDY			(1<<4)
> +#define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW			(1<<5)
> +#define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW		(1<<6)
> +#define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW		(1<<7)
> +#define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW		(1<<8)
> +#define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW		(1<<9)
> +#define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW		(1<<10)
> +
> +/***************** IF_SPI_HOST_INT_STATUS_REG *****************/
> +/** Host Interrupt Status bit : Tx download ready */
> +#define IF_SPI_HIST_TX_DOWNLOAD_RDY			(1<<0)
> +/** Host Interrupt Status bit : Rx upload ready */
> +#define IF_SPI_HIST_RX_UPLOAD_RDY			(1<<1)
> +/** Host Interrupt Status bit : Command download ready */
> +#define IF_SPI_HIST_CMD_DOWNLOAD_RDY			(1<<2)
> +/** Host Interrupt Status bit : Card event */
> +#define IF_SPI_HIST_CARD_EVENT				(1<<3)
> +/** Host Interrupt Status bit : Command upload ready */
> +#define IF_SPI_HIST_CMD_UPLOAD_RDY			(1<<4)
> +/** Host Interrupt Status bit : I/O write FIFO overflow */
> +#define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW			(1<<5)
> +/** Host Interrupt Status bit : I/O read FIFO underflow */
> +#define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW			(1<<6)
> +/** Host Interrupt Status bit : Data write FIFO overflow */
> +#define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW		(1<<7)
> +/** Host Interrupt Status bit : Data read FIFO underflow */
> +#define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW		(1<<8)
> +/** Host Interrupt Status bit : Command write FIFO overflow */
> +#define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW		(1<<9)
> +/** Host Interrupt Status bit : Command read FIFO underflow */
> +#define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW		(1<<10)
> +
> +/***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/
> +/** Host Interrupt Status Mask bit : Tx download ready */
> +#define IF_SPI_HISM_TX_DOWNLOAD_RDY			(1<<0)
> +/** Host Interrupt Status Mask bit : Rx upload ready */
> +#define IF_SPI_HISM_RX_UPLOAD_RDY			(1<<1)
> +/** Host Interrupt Status Mask bit : Command download ready */
> +#define IF_SPI_HISM_CMD_DOWNLOAD_RDY			(1<<2)
> +/** Host Interrupt Status Mask bit : Card event */
> +#define IF_SPI_HISM_CARDEVENT				(1<<3)
> +/** Host Interrupt Status Mask bit : Command upload ready */
> +#define IF_SPI_HISM_CMD_UPLOAD_RDY			(1<<4)
> +/** Host Interrupt Status Mask bit : I/O write FIFO overflow */
> +#define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW			(1<<5)
> +/** Host Interrupt Status Mask bit : I/O read FIFO underflow */
> +#define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW		(1<<6)
> +/** Host Interrupt Status Mask bit : Data write FIFO overflow */
> +#define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW		(1<<7)
> +/** Host Interrupt Status Mask bit : Data write FIFO underflow */
> +#define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW		(1<<8)
> +/** Host Interrupt Status Mask bit : Command write FIFO overflow */
> +#define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW		(1<<9)
> +/** Host Interrupt Status Mask bit : Command write FIFO underflow */
> +#define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW		(1<<10)
> +
> +/***************** IF_SPI_SPU_BUS_MODE_REG *****************/
> +/* SCK edge on which the WLAN module outputs data on MISO */
> +#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8
> +#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0
> +
> +/* In a SPU read operation, there is a delay between writing the SPU
> + * register name and getting back data from the WLAN module.
> + * This can be specified in terms of nanoseconds or in terms of dummy
> + * clock cycles which the master must output before receiving a response. */
> +#define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4
> +#define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0
> +
> +/* Some different modes of SPI operation */
> +#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00
> +#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01
> +#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02
> +#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03
> +
> +#endif
> diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h
> new file mode 100644
> index 0000000..ada71b4
> --- /dev/null
> +++ b/include/linux/spi/libertas_spi.h
> @@ -0,0 +1,25 @@
> +/*
> + * board-specific data for the libertas_spi driver.
> + *
> + * Copyright 2008 Analog Devices Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + */
> +#ifndef _LIBERTAS_SPI_H_
> +#define _LIBERTAS_SPI_H_
> +struct libertas_spi_platform_data {
> +	/* There are two ways to read data from the WLAN module's SPI
> +	 * interface. Setting 0 or 1 here controls which one is used.
> +	 *
> +	 * Usually you want to set use_dummy_writes = 1.
> +	 * However, if that doesn't work or if you are using a slow SPI clock
> +	 * speed, you may want to use 0 here. */
> +	u16 use_dummy_writes;
> +
> +	/* GPIO number to use as chip select */
> +	u16 gpio_cs;
> +};
> +#endif



From colin at cozybit.com  Thu Jan  8 12:42:26 2009
From: colin at cozybit.com (Colin McCabe)
Date: Thu, 8 Jan 2009 09:42:26 -0800
Subject: [PATCH v2 3/3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <1231435046.21643.53.camel@localhost.localdomain>
References: <1230951623-26998-1-git-send-email-colin@cozybit.com>
	<1230951623-26998-2-git-send-email-colin@cozybit.com>
	<1230951623-26998-3-git-send-email-colin@cozybit.com>
	<1230951623-26998-4-git-send-email-colin@cozybit.com>
	<1231435046.21643.53.camel@localhost.localdomain>
Message-ID: <314b98fa0901080942w67e16b0ex14bafac2d6d511d6@mail.gmail.com>

On Thu, Jan 8, 2009 at 9:17 AM, Dan Williams <dcbw at redhat.com> wrote:
> On Fri, 2009-01-02 at 19:00 -0800, Colin McCabe wrote:
>> Add initial support for libertas devices using a GSPI interface.  This has
>> been tested with the 8686.  At this time, as far as we know, GSPI firmware for
>> this device is not publicly distributable, but we expect this to change.
>>
>> GSPI is intended to be used on embedded systems. Board-specific parameters are
>> required (see libertas_spi.h).
>
> One thing we found we *really* wanted with SDIO was the ability to reset
> the card completely, is there any ability to do that with the SPI
> interface, or do you need to rely on board-specific methods to do that?

I've been looking at the SPU specification, and I can't see any way to
reset the whole module (i.e. power cycle) through the SPU.

>> +
>> +     /* Handles all SPI communication (except for FW load) */
>> +     struct task_struct              *spi_thread;
>> +     int                             run_thread;
>> +
>> +     /* Used to wake up the spi_thread */
>> +     struct semaphore                spi_ready;
>> +     struct semaphore                spi_thread_terminated;
>
> Are these really using semaphore semantics, or would a mutex be more
> appropriate here?  A ton of stuff got converted to mutexes a while back,
> so if you don't actually need the specific semaphore behavior mutexes
> might be a clearer choice.

We want semaphore semantics here, because (to quote mutex.c),
"Unlocking of a not locked mutex is not allowed."
This is important because an interrupt could come in just after
hw_host_to_card is called (for example).

>> +     int n, err = 0;
>> +     u16 zero = 0;
>> +     u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK;
>> +
>> +     /* You must take an even number of bytes from the SPU, even if you
>> +      * don't care about the last one.  */
>> +     BUG_ON(len & 0x1);
>> +
>> +     spu_transaction_init(card);
>> +
>> +     /* write SPU register index */
>> +     err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
>> +     if (err)
>
> Do you really want 'goto out' here instead of 'return' so that
> spu_transaction_finish() gets called?

Hmm, good call.

>> +static int if_spi_calculate_fw_names(u16 card_id,
>> +                           char *helper_fw, char *main_fw)
>> +{
>> +     int i;
>> +     for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
>> +             if (card_id == chip_id_to_device_name[i].chip_id)
>> +                     break;
>> +     }
>> +     if (i == ARRAY_SIZE(chip_id_to_device_name)) {
>> +             lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
>> +             return -EAFNOSUPPORT;
>> +     }
>> +     snprintf(helper_fw, FIRMWARE_NAME_MAX, "spi%d_helper.bin",
>> +              chip_id_to_device_name[i].name);
>> +     snprintf(main_fw, FIRMWARE_NAME_MAX, "spi%d.bin",
>> +              chip_id_to_device_name[i].name);
>
> Could you look for firmware in the "libertas/" directory, and could we
> make the prefix of the firmware be "gspi" to match the actual Marvell
> firmware names?
>
> The firmware (at least for gspi8686) is in the process of getting pushed
> to the linux-firmware tree, and I'd like to consolidate libertas
> firmware into the libertas/ subdirectory for all libertas interface
> drivers.
>
> Dan

Ok, sounds good.

Colin


From andrey at cozybit.com  Thu Jan  8 14:41:53 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Thu, 8 Jan 2009 11:41:53 -0800
Subject: libertas: BUG: unable to handle paging request
In-Reply-To: <20090107225735.J84155@bowser.eecs.harvard.edu>
References: <45e8e6c40901071658j6a22fcc7gedcc41d73a61ff2a@mail.gmail.com>
	<45e8e6c40901071837o56dba8f1w6db5c7e982f698da@mail.gmail.com>
	<45e8e6c40901071945u27a8de0aqbf2b50f0075a32f3@mail.gmail.com>
	<20090107225735.J84155@bowser.eecs.harvard.edu>
Message-ID: <45e8e6c40901081141s1f0b7be7g36095a4da1819d9@mail.gmail.com>

Hi Dario.  In my case I see the oops when iwconfig issues the
SIOCGIWFREQ icotl and thus lbs_get_freq() is executed.  Pulling out
the CMD_802_11_GET_LOG doesn't change anything in this respect.

Right now I am trying to understand why the functions in wext.c access
priv with:

struct lbs_private *priv = dev->priv;

while the rest of the driver uses the netdev macros, for example:

struct lbs_private *priv = netdev_priv(to_net_dev(dev));

after the commit in question, or

struct lbs_private *priv = to_net_dev(dev)->priv;

before the commit in question.  Converting the WEXT callbacks to use
the netdev macros doesn't seem to solve the problem.  Thanks,

  -Andrey

On Wed, Jan 7, 2009 at 8:01 PM, Dario Vlah <dario at eecs.harvard.edu> wrote:
> Hi Andrey,
>
> I ran into some trouble with the GET_LOG command on the jax10 device, which
> happens to be called by iwconfig.  Could that be related?  What if you
> disable the GET_LOG call?
>
> In my case issuing that command results in the firmware returning bogus
> values such as negative buffer sizes which end up crashing the kernel.
>
> --dario
>
> On Wed, 7 Jan 2009, Andrey Yurovsky wrote:
>
>> Hmm, I do see the problem start at
>> 29726d85d7b98558a8bc8e69b859bf12e1347f9f and after, but I don't think
>> that I'm right with my analysis, especially since the OOPS happens in
>> wext.c and the functions there (namely lbs_get_freq) use netdev->priv
>> directly.  I apologize for the noise but there is still something
>> wrong here that I'm trying to understand better.
>>
>>  -Andrey
>>
>> On Wed, Jan 7, 2009 at 6:37 PM, Andrey Yurovsky <andrey at cozybit.com>
>> wrote:
>>>
>>> The commit that caused this regression is
>>> 29726d85d7b98558a8bc8e69b859bf12e1347f9f "netdevice libertas: Fix
>>> directly reference of netdev->priv" by Wang Chen.  It probably causes
>>> a problem with netdev->priv's offset and then we get a pointer
>>> dereference problem when lbs_get_freq() tries to use its priv data.
>>>
>>>  -Andrey
>>>
>>> On Wed, Jan 7, 2009 at 4:58 PM, Andrey Yurovsky <andrey at cozybit.com>
>>> wrote:
>>>>
>>>> Hello.  I noticed that the libertas driver causes a kernel oops in
>>>> more recent wireless-testing kernels (I am bisecting right now to
>>>> narrow this down).  To reproduce, load the driver and run iwconfig,
>>>> causing lbs_get_freq() to be called.
>>>>
>>>> So far I know that this problem doesn't exist at the 2.6.28-rc2 tag
>>>> (commit 0173a3265b228da319ceb9c1ec6a5682fd1b2d92)  but I have seen it
>>>> in -rc7 and up through today's wireless-testing.  It seems that
>>>> there's a regression somewhere after -rc2.  I've reproduced this with
>>>> the USB hardware as well as an SDIO board.
>>>>
>>>> [  118.571205] BUG: unable to handle kernel paging request at 00001e01
>>>> [  118.578500] IP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
>>>> [  118.585417] *pde = 00000000
>>>> [  118.588877] Oops: 0000 [#1]
>>>> [  118.592092] last sysfs file: /sys/block/ram9/range
>>>> [  118.592385] Modules linked in: usb8xxx libertas lib80211
>>>> [  118.592385]
>>>> [  118.592385] Pid: 2317, comm: iwconfig Not tainted (2.6.28-wl #65)
>>>> Uknown
>>>> [  118.592385] EIP: 0060:[<c81fddda>] EFLAGS: 00010293 CPU: 0
>>>> [  118.592385] EIP is at lbs_get_freq+0x1a/0x160 [libertas]
>>>> [  118.592385] EAX: 00000000 EBX: 00000000 ECX: c6891ef8 EDX: c6891e98
>>>> [  118.592385] ESI: c6891ef8 EDI: c6891ef8 EBP: c7295000 ESP: c6891e10
>>>> [  118.592385]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
>>>> [  118.592385] Process iwconfig (pid: 2317, ti=c6890000 task=c7349880
>>>> task.ti=c6890000)
>>>> [  118.592385] Stack:
>>>> [  118.592385]  c8201b4b c6891ef8 00000010 ffffffa1 00008b05 c038aa20
>>>> 00000000 c03c691c
>>>> [  118.592385]  00000000 c04bc7e0 c0301287 b7f01d70 c68ce000 c6895000
>>>> c04c8260 00000c04
>>>> [  118.592385]  c68c7b7c 00000000 c7295000 c6891ee8 c0300325 c6891ee8
>>>> c7295000 c6891ee8
>>>> [  118.592385] Call Trace:
>>>> [  118.592385]  [<c8201b4b>] lbs_get_name+0x2b/0xb0 [libertas]
>>>> [  118.592385]  [<c038aa20>] ioctl_standard_call+0x60/0x3a0
>>>> [  118.592385]  [<c0301287>] netif_receive_skb+0x1d7/0x3e0
>>>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
>>>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
>>>> [  118.592385]  [<c038a687>] wext_handle_ioctl+0x157/0x230
>>>> [  118.592385]  [<c81fddc0>] lbs_get_freq+0x0/0x160 [libertas]
>>>> [  118.592385]  [<c03034c4>] dev_ioctl+0x304/0x4f0
>>>> [  118.592385]  [<c02ffdd2>] net_rx_action+0x92/0x140
>>>> [  118.592385]  [<c027ca89>] pty_write+0x39/0x60
>>>> [  118.592385]  [<c02f4280>] sock_ioctl+0x0/0x260
>>>> [  118.592385]  [<c017e27f>] vfs_ioctl+0x1f/0x70
>>>> [  118.592385]  [<c017e65b>] do_vfs_ioctl+0x24b/0x490
>>>> [  118.592385]  [<c011654e>] update_curr+0x13e/0x190
>>>> [  118.592385]  [<c0117fab>] set_next_entity+0x2b/0x70
>>>> [  118.592385]  [<c0397c64>] schedule+0x1b4/0x350
>>>> [  118.592385]  [<c017e906>] sys_ioctl+0x66/0x70
>>>> [  118.592385]  [<c0103cd2>] syscall_call+0x7/0xb
>>>> [  118.592385] Code: e9 38 ff ff ff 8d b6 00 00 00 00 8d bf 00 00 00
>>>> 00 56 89 ce 53 83 ec 0c 8b 98 a4 01 00 00 a1 80 19 22 c8 83 e0 21 83
>>>> f8 21 74 42 <0f> b6 8b 01 1e 00 00 31 d2 89 d8 e8 a6 fe ff ff 85 c0 0f
>>>> 84 cd
>>>> [  118.592385] EIP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
>>>> SS:ESP 0068:c6891e10
>>>> [  118.594153] ---[ end trace f426cd49b2b378f4 ]---
>>>>
>>>
>>
>> _______________________________________________
>> libertas-dev mailing list
>> libertas-dev at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/libertas-dev
>>
>


From dcbw at redhat.com  Thu Jan  8 17:35:12 2009
From: dcbw at redhat.com (Dan Williams)
Date: Thu, 08 Jan 2009 17:35:12 -0500
Subject: libertas: BUG: unable to handle paging request
In-Reply-To: <45e8e6c40901081141s1f0b7be7g36095a4da1819d9@mail.gmail.com>
References: <45e8e6c40901071658j6a22fcc7gedcc41d73a61ff2a@mail.gmail.com>
	<45e8e6c40901071837o56dba8f1w6db5c7e982f698da@mail.gmail.com>
	<45e8e6c40901071945u27a8de0aqbf2b50f0075a32f3@mail.gmail.com>
	<20090107225735.J84155@bowser.eecs.harvard.edu>
	<45e8e6c40901081141s1f0b7be7g36095a4da1819d9@mail.gmail.com>
Message-ID: <1231454112.24797.1.camel@localhost.localdomain>

On Thu, 2009-01-08 at 11:41 -0800, Andrey Yurovsky wrote:
> Hi Dario.  In my case I see the oops when iwconfig issues the
> SIOCGIWFREQ icotl and thus lbs_get_freq() is executed.  Pulling out
> the CMD_802_11_GET_LOG doesn't change anything in this respect.
> 
> Right now I am trying to understand why the functions in wext.c access
> priv with:
> 
> struct lbs_private *priv = dev->priv;

They probably just got forgotten or something during the conversion.
They should be using the same methods as everything else, really, since
it's just a netdev and they are trying to access the private driver
data.

Dan

> while the rest of the driver uses the netdev macros, for example:
> 
> struct lbs_private *priv = netdev_priv(to_net_dev(dev));
> 
> after the commit in question, or
> 
> struct lbs_private *priv = to_net_dev(dev)->priv;
> 
> before the commit in question.  Converting the WEXT callbacks to use
> the netdev macros doesn't seem to solve the problem.  Thanks,
> 
>   -Andrey
> 
> On Wed, Jan 7, 2009 at 8:01 PM, Dario Vlah <dario at eecs.harvard.edu> wrote:
> > Hi Andrey,
> >
> > I ran into some trouble with the GET_LOG command on the jax10 device, which
> > happens to be called by iwconfig.  Could that be related?  What if you
> > disable the GET_LOG call?
> >
> > In my case issuing that command results in the firmware returning bogus
> > values such as negative buffer sizes which end up crashing the kernel.
> >
> > --dario
> >
> > On Wed, 7 Jan 2009, Andrey Yurovsky wrote:
> >
> >> Hmm, I do see the problem start at
> >> 29726d85d7b98558a8bc8e69b859bf12e1347f9f and after, but I don't think
> >> that I'm right with my analysis, especially since the OOPS happens in
> >> wext.c and the functions there (namely lbs_get_freq) use netdev->priv
> >> directly.  I apologize for the noise but there is still something
> >> wrong here that I'm trying to understand better.
> >>
> >>  -Andrey
> >>
> >> On Wed, Jan 7, 2009 at 6:37 PM, Andrey Yurovsky <andrey at cozybit.com>
> >> wrote:
> >>>
> >>> The commit that caused this regression is
> >>> 29726d85d7b98558a8bc8e69b859bf12e1347f9f "netdevice libertas: Fix
> >>> directly reference of netdev->priv" by Wang Chen.  It probably causes
> >>> a problem with netdev->priv's offset and then we get a pointer
> >>> dereference problem when lbs_get_freq() tries to use its priv data.
> >>>
> >>>  -Andrey
> >>>
> >>> On Wed, Jan 7, 2009 at 4:58 PM, Andrey Yurovsky <andrey at cozybit.com>
> >>> wrote:
> >>>>
> >>>> Hello.  I noticed that the libertas driver causes a kernel oops in
> >>>> more recent wireless-testing kernels (I am bisecting right now to
> >>>> narrow this down).  To reproduce, load the driver and run iwconfig,
> >>>> causing lbs_get_freq() to be called.
> >>>>
> >>>> So far I know that this problem doesn't exist at the 2.6.28-rc2 tag
> >>>> (commit 0173a3265b228da319ceb9c1ec6a5682fd1b2d92)  but I have seen it
> >>>> in -rc7 and up through today's wireless-testing.  It seems that
> >>>> there's a regression somewhere after -rc2.  I've reproduced this with
> >>>> the USB hardware as well as an SDIO board.
> >>>>
> >>>> [  118.571205] BUG: unable to handle kernel paging request at 00001e01
> >>>> [  118.578500] IP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
> >>>> [  118.585417] *pde = 00000000
> >>>> [  118.588877] Oops: 0000 [#1]
> >>>> [  118.592092] last sysfs file: /sys/block/ram9/range
> >>>> [  118.592385] Modules linked in: usb8xxx libertas lib80211
> >>>> [  118.592385]
> >>>> [  118.592385] Pid: 2317, comm: iwconfig Not tainted (2.6.28-wl #65)
> >>>> Uknown
> >>>> [  118.592385] EIP: 0060:[<c81fddda>] EFLAGS: 00010293 CPU: 0
> >>>> [  118.592385] EIP is at lbs_get_freq+0x1a/0x160 [libertas]
> >>>> [  118.592385] EAX: 00000000 EBX: 00000000 ECX: c6891ef8 EDX: c6891e98
> >>>> [  118.592385] ESI: c6891ef8 EDI: c6891ef8 EBP: c7295000 ESP: c6891e10
> >>>> [  118.592385]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
> >>>> [  118.592385] Process iwconfig (pid: 2317, ti=c6890000 task=c7349880
> >>>> task.ti=c6890000)
> >>>> [  118.592385] Stack:
> >>>> [  118.592385]  c8201b4b c6891ef8 00000010 ffffffa1 00008b05 c038aa20
> >>>> 00000000 c03c691c
> >>>> [  118.592385]  00000000 c04bc7e0 c0301287 b7f01d70 c68ce000 c6895000
> >>>> c04c8260 00000c04
> >>>> [  118.592385]  c68c7b7c 00000000 c7295000 c6891ee8 c0300325 c6891ee8
> >>>> c7295000 c6891ee8
> >>>> [  118.592385] Call Trace:
> >>>> [  118.592385]  [<c8201b4b>] lbs_get_name+0x2b/0xb0 [libertas]
> >>>> [  118.592385]  [<c038aa20>] ioctl_standard_call+0x60/0x3a0
> >>>> [  118.592385]  [<c0301287>] netif_receive_skb+0x1d7/0x3e0
> >>>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
> >>>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
> >>>> [  118.592385]  [<c038a687>] wext_handle_ioctl+0x157/0x230
> >>>> [  118.592385]  [<c81fddc0>] lbs_get_freq+0x0/0x160 [libertas]
> >>>> [  118.592385]  [<c03034c4>] dev_ioctl+0x304/0x4f0
> >>>> [  118.592385]  [<c02ffdd2>] net_rx_action+0x92/0x140
> >>>> [  118.592385]  [<c027ca89>] pty_write+0x39/0x60
> >>>> [  118.592385]  [<c02f4280>] sock_ioctl+0x0/0x260
> >>>> [  118.592385]  [<c017e27f>] vfs_ioctl+0x1f/0x70
> >>>> [  118.592385]  [<c017e65b>] do_vfs_ioctl+0x24b/0x490
> >>>> [  118.592385]  [<c011654e>] update_curr+0x13e/0x190
> >>>> [  118.592385]  [<c0117fab>] set_next_entity+0x2b/0x70
> >>>> [  118.592385]  [<c0397c64>] schedule+0x1b4/0x350
> >>>> [  118.592385]  [<c017e906>] sys_ioctl+0x66/0x70
> >>>> [  118.592385]  [<c0103cd2>] syscall_call+0x7/0xb
> >>>> [  118.592385] Code: e9 38 ff ff ff 8d b6 00 00 00 00 8d bf 00 00 00
> >>>> 00 56 89 ce 53 83 ec 0c 8b 98 a4 01 00 00 a1 80 19 22 c8 83 e0 21 83
> >>>> f8 21 74 42 <0f> b6 8b 01 1e 00 00 31 d2 89 d8 e8 a6 fe ff ff 85 c0 0f
> >>>> 84 cd
> >>>> [  118.592385] EIP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
> >>>> SS:ESP 0068:c6891e10
> >>>> [  118.594153] ---[ end trace f426cd49b2b378f4 ]---
> >>>>
> >>>
> >>
> >> _______________________________________________
> >> libertas-dev mailing list
> >> libertas-dev at lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/libertas-dev
> >>
> >
> 
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From andrey at cozybit.com  Thu Jan  8 17:41:30 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Thu, 8 Jan 2009 14:41:30 -0800
Subject: libertas: BUG: unable to handle paging request
In-Reply-To: <1231454112.24797.1.camel@localhost.localdomain>
References: <45e8e6c40901071658j6a22fcc7gedcc41d73a61ff2a@mail.gmail.com>
	<45e8e6c40901071837o56dba8f1w6db5c7e982f698da@mail.gmail.com>
	<45e8e6c40901071945u27a8de0aqbf2b50f0075a32f3@mail.gmail.com>
	<20090107225735.J84155@bowser.eecs.harvard.edu>
	<45e8e6c40901081141s1f0b7be7g36095a4da1819d9@mail.gmail.com>
	<1231454112.24797.1.camel@localhost.localdomain>
Message-ID: <45e8e6c40901081441r59112db3i9d5e47dc5fd15f08@mail.gmail.com>

Ok, also the interface layers (ex: if_usb.c and if_sdio.c) were missed
in that patch as well.  I'm still getting the OOPS after making
everyone use the macros consistently so I think there's something else
going on that's corrupting our priv data.

On Thu, Jan 8, 2009 at 2:35 PM, Dan Williams <dcbw at redhat.com> wrote:
> On Thu, 2009-01-08 at 11:41 -0800, Andrey Yurovsky wrote:
>> Hi Dario.  In my case I see the oops when iwconfig issues the
>> SIOCGIWFREQ icotl and thus lbs_get_freq() is executed.  Pulling out
>> the CMD_802_11_GET_LOG doesn't change anything in this respect.
>>
>> Right now I am trying to understand why the functions in wext.c access
>> priv with:
>>
>> struct lbs_private *priv = dev->priv;
>
> They probably just got forgotten or something during the conversion.
> They should be using the same methods as everything else, really, since
> it's just a netdev and they are trying to access the private driver
> data.
>
> Dan
>
>> while the rest of the driver uses the netdev macros, for example:
>>
>> struct lbs_private *priv = netdev_priv(to_net_dev(dev));
>>
>> after the commit in question, or
>>
>> struct lbs_private *priv = to_net_dev(dev)->priv;
>>
>> before the commit in question.  Converting the WEXT callbacks to use
>> the netdev macros doesn't seem to solve the problem.  Thanks,
>>
>>   -Andrey
>>
>> On Wed, Jan 7, 2009 at 8:01 PM, Dario Vlah <dario at eecs.harvard.edu> wrote:
>> > Hi Andrey,
>> >
>> > I ran into some trouble with the GET_LOG command on the jax10 device, which
>> > happens to be called by iwconfig.  Could that be related?  What if you
>> > disable the GET_LOG call?
>> >
>> > In my case issuing that command results in the firmware returning bogus
>> > values such as negative buffer sizes which end up crashing the kernel.
>> >
>> > --dario
>> >
>> > On Wed, 7 Jan 2009, Andrey Yurovsky wrote:
>> >
>> >> Hmm, I do see the problem start at
>> >> 29726d85d7b98558a8bc8e69b859bf12e1347f9f and after, but I don't think
>> >> that I'm right with my analysis, especially since the OOPS happens in
>> >> wext.c and the functions there (namely lbs_get_freq) use netdev->priv
>> >> directly.  I apologize for the noise but there is still something
>> >> wrong here that I'm trying to understand better.
>> >>
>> >>  -Andrey
>> >>
>> >> On Wed, Jan 7, 2009 at 6:37 PM, Andrey Yurovsky <andrey at cozybit.com>
>> >> wrote:
>> >>>
>> >>> The commit that caused this regression is
>> >>> 29726d85d7b98558a8bc8e69b859bf12e1347f9f "netdevice libertas: Fix
>> >>> directly reference of netdev->priv" by Wang Chen.  It probably causes
>> >>> a problem with netdev->priv's offset and then we get a pointer
>> >>> dereference problem when lbs_get_freq() tries to use its priv data.
>> >>>
>> >>>  -Andrey
>> >>>
>> >>> On Wed, Jan 7, 2009 at 4:58 PM, Andrey Yurovsky <andrey at cozybit.com>
>> >>> wrote:
>> >>>>
>> >>>> Hello.  I noticed that the libertas driver causes a kernel oops in
>> >>>> more recent wireless-testing kernels (I am bisecting right now to
>> >>>> narrow this down).  To reproduce, load the driver and run iwconfig,
>> >>>> causing lbs_get_freq() to be called.
>> >>>>
>> >>>> So far I know that this problem doesn't exist at the 2.6.28-rc2 tag
>> >>>> (commit 0173a3265b228da319ceb9c1ec6a5682fd1b2d92)  but I have seen it
>> >>>> in -rc7 and up through today's wireless-testing.  It seems that
>> >>>> there's a regression somewhere after -rc2.  I've reproduced this with
>> >>>> the USB hardware as well as an SDIO board.
>> >>>>
>> >>>> [  118.571205] BUG: unable to handle kernel paging request at 00001e01
>> >>>> [  118.578500] IP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
>> >>>> [  118.585417] *pde = 00000000
>> >>>> [  118.588877] Oops: 0000 [#1]
>> >>>> [  118.592092] last sysfs file: /sys/block/ram9/range
>> >>>> [  118.592385] Modules linked in: usb8xxx libertas lib80211
>> >>>> [  118.592385]
>> >>>> [  118.592385] Pid: 2317, comm: iwconfig Not tainted (2.6.28-wl #65)
>> >>>> Uknown
>> >>>> [  118.592385] EIP: 0060:[<c81fddda>] EFLAGS: 00010293 CPU: 0
>> >>>> [  118.592385] EIP is at lbs_get_freq+0x1a/0x160 [libertas]
>> >>>> [  118.592385] EAX: 00000000 EBX: 00000000 ECX: c6891ef8 EDX: c6891e98
>> >>>> [  118.592385] ESI: c6891ef8 EDI: c6891ef8 EBP: c7295000 ESP: c6891e10
>> >>>> [  118.592385]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
>> >>>> [  118.592385] Process iwconfig (pid: 2317, ti=c6890000 task=c7349880
>> >>>> task.ti=c6890000)
>> >>>> [  118.592385] Stack:
>> >>>> [  118.592385]  c8201b4b c6891ef8 00000010 ffffffa1 00008b05 c038aa20
>> >>>> 00000000 c03c691c
>> >>>> [  118.592385]  00000000 c04bc7e0 c0301287 b7f01d70 c68ce000 c6895000
>> >>>> c04c8260 00000c04
>> >>>> [  118.592385]  c68c7b7c 00000000 c7295000 c6891ee8 c0300325 c6891ee8
>> >>>> c7295000 c6891ee8
>> >>>> [  118.592385] Call Trace:
>> >>>> [  118.592385]  [<c8201b4b>] lbs_get_name+0x2b/0xb0 [libertas]
>> >>>> [  118.592385]  [<c038aa20>] ioctl_standard_call+0x60/0x3a0
>> >>>> [  118.592385]  [<c0301287>] netif_receive_skb+0x1d7/0x3e0
>> >>>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
>> >>>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
>> >>>> [  118.592385]  [<c038a687>] wext_handle_ioctl+0x157/0x230
>> >>>> [  118.592385]  [<c81fddc0>] lbs_get_freq+0x0/0x160 [libertas]
>> >>>> [  118.592385]  [<c03034c4>] dev_ioctl+0x304/0x4f0
>> >>>> [  118.592385]  [<c02ffdd2>] net_rx_action+0x92/0x140
>> >>>> [  118.592385]  [<c027ca89>] pty_write+0x39/0x60
>> >>>> [  118.592385]  [<c02f4280>] sock_ioctl+0x0/0x260
>> >>>> [  118.592385]  [<c017e27f>] vfs_ioctl+0x1f/0x70
>> >>>> [  118.592385]  [<c017e65b>] do_vfs_ioctl+0x24b/0x490
>> >>>> [  118.592385]  [<c011654e>] update_curr+0x13e/0x190
>> >>>> [  118.592385]  [<c0117fab>] set_next_entity+0x2b/0x70
>> >>>> [  118.592385]  [<c0397c64>] schedule+0x1b4/0x350
>> >>>> [  118.592385]  [<c017e906>] sys_ioctl+0x66/0x70
>> >>>> [  118.592385]  [<c0103cd2>] syscall_call+0x7/0xb
>> >>>> [  118.592385] Code: e9 38 ff ff ff 8d b6 00 00 00 00 8d bf 00 00 00
>> >>>> 00 56 89 ce 53 83 ec 0c 8b 98 a4 01 00 00 a1 80 19 22 c8 83 e0 21 83
>> >>>> f8 21 74 42 <0f> b6 8b 01 1e 00 00 31 d2 89 d8 e8 a6 fe ff ff 85 c0 0f
>> >>>> 84 cd
>> >>>> [  118.592385] EIP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
>> >>>> SS:ESP 0068:c6891e10
>> >>>> [  118.594153] ---[ end trace f426cd49b2b378f4 ]---
>> >>>>
>> >>>
>> >>
>> >> _______________________________________________
>> >> libertas-dev mailing list
>> >> libertas-dev at lists.infradead.org
>> >> http://lists.infradead.org/mailman/listinfo/libertas-dev
>> >>
>> >
>>
>> _______________________________________________
>> libertas-dev mailing list
>> libertas-dev at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/libertas-dev
>
>


From tharvey at irobot.com  Thu Jan  8 20:09:08 2009
From: tharvey at irobot.com (Tim Harvey)
Date: Thu, 08 Jan 2009 17:09:08 -0800
Subject: SDIO performance
Message-ID: <4966A3B4.1040502@irobot.com>

Greetings,

Back in May of last year I was doing some evaluation of a couple of 
Marvell Libertas 88w8686 modules on an i.MX31 host running 2.6.22 using 
the libertas driver from compat-wireless.  I found at the time that the 
max throughput I could achieve was about 1.1mbps at 11M and it was 
suggested that the fact that the i.MX31's SDIO host controller driver 
did not support MMC_CAP_SDIO_IRQ and could only support 1bit transfers.  
Recently I've taken another look at the same sdio modules but this time 
running on an OMAP3 beagleboard host running 2.6.27 using the libertas 
driver from mainline.  This time I find that I can only achieve about 
0.8mbps at 11M.  

I've verified that the OMAP3's MMC/SDIO host controller driver supports 
4-bit mode yet it does not support MMC_CAP_SDIO_IRQ.  Its been suggested 
to me on #libertas that the linux core sdio driver is not very efficient 
and that also the libertas if_sdio.c support steps down to 1-bit mode 
for most transfers.  Even still 1bit SDIO has a data transfer rate of 
10MB/sec so I'm still surprised at this <1mbps performance.

Can anyone else using libertas-sdio tell me what hardware they are using 
(host and module) and what software they are using (kernel version + any 
relevant patches and libertas firmware) and what throughputs they can 
achieve?

I'm going to be digging into the if_sdio.c component and try to 
understand the linux core sdio subsystem to see if I can find any hope 
of speeding things up
 - any pointers would be greatly appreciated.

I've seen the recent patches to support GSPI devices and I wonder what 
kind of throughput has been acheived on those?

Also, as about 8mo's have passed since I looked for hardware supported 
by the libertas driver, are there any recent USB dongle devices 
supported out there?  The information on 
http://linuxwireless.org/en/users/Drivers/libertas hasn't changed in 
quite some time and I'm not sure if its up-to-date.

Thanks,

Tim


From kalle.valo at iki.fi  Fri Jan  9 03:05:27 2009
From: kalle.valo at iki.fi (Kalle Valo)
Date: Fri, 09 Jan 2009 10:05:27 +0200
Subject: [PATCH v2 3/3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <1231435046.21643.53.camel@localhost.localdomain> (Dan Williams's
	message of "Thu\, 08 Jan 2009 12\:17\:25 -0500")
References: <1230951623-26998-1-git-send-email-colin@cozybit.com>
	<1230951623-26998-2-git-send-email-colin@cozybit.com>
	<1230951623-26998-3-git-send-email-colin@cozybit.com>
	<1230951623-26998-4-git-send-email-colin@cozybit.com>
	<1231435046.21643.53.camel@localhost.localdomain>
Message-ID: <87ljtk29bs.fsf@litku.valot.fi>

Dan Williams <dcbw at redhat.com> writes:

> On Fri, 2009-01-02 at 19:00 -0800, Colin McCabe wrote:
>> Add initial support for libertas devices using a GSPI interface.  This has
>> been tested with the 8686.  At this time, as far as we know, GSPI firmware for
>> this device is not publicly distributable, but we expect this to change.
>> 
>> GSPI is intended to be used on embedded systems. Board-specific parameters are
>> required (see libertas_spi.h).
>
> One thing we found we *really* wanted with SDIO was the ability to reset
> the card completely, is there any ability to do that with the SPI
> interface, or do you need to rely on board-specific methods to do that?

For stlc45xx (which currently uses SPI) where's a separate power gpio
line. To reset it, put the line down, wait a bit and put it back up. I
would guess that to be a common practise, at least in the embedded
world.

-- 
Kalle Valo


From stwogood at siconix.com  Fri Jan  9 10:46:37 2009
From: stwogood at siconix.com (Simon Twogood)
Date: Fri, 9 Jan 2009 08:46:37 -0700
Subject: SDIO performance
In-Reply-To: <4966A3B4.1040502@irobot.com>
References: <4966A3B4.1040502@irobot.com>
Message-ID: <98DDD9EA-8EC5-48EF-9ECB-4F67C8099BEA@siconix.com>

Hi Tim,

Using an Atmel AT91SAM9263 system-on-a-chip and Linux 2.6.27 I have be  
able to get speeds of roughly 0.8 MB/s. As a comparison, I was able to  
get 3.6 MB/s using the wired ethernet adapter on the same board.

My tests were far from perfect though, as I was just trying to get a  
rough idea of what kind of speeds I could get.

Simon


On 8-Jan-09, at 6:09 PM, Tim Harvey wrote:

> Greetings,
>
> Back in May of last year I was doing some evaluation of a couple of
> Marvell Libertas 88w8686 modules on an i.MX31 host running 2.6.22  
> using
> the libertas driver from compat-wireless.  I found at the time that  
> the
> max throughput I could achieve was about 1.1mbps at 11M and it was
> suggested that the fact that the i.MX31's SDIO host controller driver
> did not support MMC_CAP_SDIO_IRQ and could only support 1bit  
> transfers.
> Recently I've taken another look at the same sdio modules but this  
> time
> running on an OMAP3 beagleboard host running 2.6.27 using the libertas
> driver from mainline.  This time I find that I can only achieve about
> 0.8mbps at 11M.
>
> I've verified that the OMAP3's MMC/SDIO host controller driver  
> supports
> 4-bit mode yet it does not support MMC_CAP_SDIO_IRQ.  Its been  
> suggested
> to me on #libertas that the linux core sdio driver is not very  
> efficient
> and that also the libertas if_sdio.c support steps down to 1-bit mode
> for most transfers.  Even still 1bit SDIO has a data transfer rate of
> 10MB/sec so I'm still surprised at this <1mbps performance.
>
> Can anyone else using libertas-sdio tell me what hardware they are  
> using
> (host and module) and what software they are using (kernel version +  
> any
> relevant patches and libertas firmware) and what throughputs they can
> achieve?
>
> I'm going to be digging into the if_sdio.c component and try to
> understand the linux core sdio subsystem to see if I can find any hope
> of speeding things up
> - any pointers would be greatly appreciated.
>
> I've seen the recent patches to support GSPI devices and I wonder what
> kind of throughput has been acheived on those?
>
> Also, as about 8mo's have passed since I looked for hardware supported
> by the libertas driver, are there any recent USB dongle devices
> supported out there?  The information on
> http://linuxwireless.org/en/users/Drivers/libertas hasn't changed in
> quite some time and I'm not sure if its up-to-date.
>
> Thanks,
>
> Tim
>
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From dcbw at redhat.com  Fri Jan  9 11:30:39 2009
From: dcbw at redhat.com (Dan Williams)
Date: Fri, 09 Jan 2009 11:30:39 -0500
Subject: SDIO performance
In-Reply-To: <98DDD9EA-8EC5-48EF-9ECB-4F67C8099BEA@siconix.com>
References: <4966A3B4.1040502@irobot.com>
	<98DDD9EA-8EC5-48EF-9ECB-4F67C8099BEA@siconix.com>
Message-ID: <1231518639.30057.11.camel@dhcp-18-190-61-35.dyn.mit.edu>

On Fri, 2009-01-09 at 08:46 -0700, Simon Twogood wrote:
> Hi Tim,
> 
> Using an Atmel AT91SAM9263 system-on-a-chip and Linux 2.6.27 I have be  
> able to get speeds of roughly 0.8 MB/s. As a comparison, I was able to  
> get 3.6 MB/s using the wired ethernet adapter on the same board.
> 
> My tests were far from perfect though, as I was just trying to get a  
> rough idea of what kind of speeds I could get.

I was getting about 450K/s around 2.6.26 time with a Fujitsu Lifebook
P1510 using the standard Ricoh SD controller.  Haven't done throughput
tests for a while.  But there certainly could be issues with if_sdio.c
or the core libertas stack, probably contention issues with the various
driver locks, but if you somebody could dig a bit further that would be
great.  As stated there could also be issues with the SDIO stack itself,
it seems to be quite sensitive to the specific controller used and the
quality of that controller.  All the machines I've got to develop on use
Ricoh R5Cxx controllers, which usually don't suck too much.

Dan

> Simon
> 
> 
> On 8-Jan-09, at 6:09 PM, Tim Harvey wrote:
> 
> > Greetings,
> >
> > Back in May of last year I was doing some evaluation of a couple of
> > Marvell Libertas 88w8686 modules on an i.MX31 host running 2.6.22  
> > using
> > the libertas driver from compat-wireless.  I found at the time that  
> > the
> > max throughput I could achieve was about 1.1mbps at 11M and it was
> > suggested that the fact that the i.MX31's SDIO host controller driver
> > did not support MMC_CAP_SDIO_IRQ and could only support 1bit  
> > transfers.
> > Recently I've taken another look at the same sdio modules but this  
> > time
> > running on an OMAP3 beagleboard host running 2.6.27 using the libertas
> > driver from mainline.  This time I find that I can only achieve about
> > 0.8mbps at 11M.
> >
> > I've verified that the OMAP3's MMC/SDIO host controller driver  
> > supports
> > 4-bit mode yet it does not support MMC_CAP_SDIO_IRQ.  Its been  
> > suggested
> > to me on #libertas that the linux core sdio driver is not very  
> > efficient
> > and that also the libertas if_sdio.c support steps down to 1-bit mode
> > for most transfers.  Even still 1bit SDIO has a data transfer rate of
> > 10MB/sec so I'm still surprised at this <1mbps performance.
> >
> > Can anyone else using libertas-sdio tell me what hardware they are  
> > using
> > (host and module) and what software they are using (kernel version +  
> > any
> > relevant patches and libertas firmware) and what throughputs they can
> > achieve?
> >
> > I'm going to be digging into the if_sdio.c component and try to
> > understand the linux core sdio subsystem to see if I can find any hope
> > of speeding things up
> > - any pointers would be greatly appreciated.
> >
> > I've seen the recent patches to support GSPI devices and I wonder what
> > kind of throughput has been acheived on those?
> >
> > Also, as about 8mo's have passed since I looked for hardware supported
> > by the libertas driver, are there any recent USB dongle devices
> > supported out there?  The information on
> > http://linuxwireless.org/en/users/Drivers/libertas hasn't changed in
> > quite some time and I'm not sure if its up-to-date.
> >
> > Thanks,
> >
> > Tim
> >
> > _______________________________________________
> > libertas-dev mailing list
> > libertas-dev at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/libertas-dev
> 
> 
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From colin at cozybit.com  Fri Jan  9 13:11:16 2009
From: colin at cozybit.com (Colin McCabe)
Date: Fri, 9 Jan 2009 10:11:16 -0800
Subject: SDIO performance
In-Reply-To: <4966A3B4.1040502@irobot.com>
References: <4966A3B4.1040502@irobot.com>
Message-ID: <314b98fa0901091011h17e326b2we402f07f87e2066a@mail.gmail.com>

On Thu, Jan 8, 2009 at 5:09 PM, Tim Harvey <tharvey at irobot.com> wrote:

> I've seen the recent patches to support GSPI devices and I wonder what
> kind of throughput has been acheived on those?

I have a blackfin BF548 evaulation board, running an SPI bus at 30 MHz.
I have gotten performance from if_spi.c as high as 3-4 Mbits / sec
(measured with iperf.)

Colin


From colin at cozybit.com  Fri Jan  9 17:58:09 2009
From: colin at cozybit.com (Colin McCabe)
Date: Fri,  9 Jan 2009 14:58:09 -0800
Subject: [PATCH v3] libertas: if_spi, driver for libertas GSPI devices
Message-ID: <1231541889-7999-1-git-send-email-colin@cozybit.com>

Add initial support for libertas devices using a GSPI interface.  This has
been tested with the 8686.

GSPI is intended to be used on embedded systems. Board-specific parameters are
required (see libertas_spi.h).

Thanks to everyone who took a look at the earlier versions of the patch.

Changes in v3:
* Get rid of out-of-date TODO comment about if_spi_e2h
* Look for firmware images in libertas/gspi8XXX_hlp.bin and 
libertas/gspi8XXX.bin 
* Fix spi_read / spi_write error handling in spu_read / spu_write
* Consolidate multiple spi_read / spi_write operations into one to
improve performance
* Add dependency on GENERIC_GPIO

Changes in v2:
* Store the host IRQ setting in spi->irq rather than creating a new variable
for this purpose.
* Add TODO comment to declaration of card->gpio_cs.
(We do intend to get rid of gpio_cs eventually, but it will require some
changes to the generic SPI layer, which could take a while.)
* When loading the module, check to see if the firmware is already loaded. If
so, skip firmware load.
* Speed up module load time slightly.
* Add if_spi_e2h to handle libertas card events.
* Include relevant Kconfig change.

Cheers.
Colin
Signed-off-by: Colin McCabe <colin at cozybit.com>
Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
---
 drivers/net/wireless/Kconfig           |    6 +
 drivers/net/wireless/libertas/Makefile |    2 +
 drivers/net/wireless/libertas/defs.h   |    2 +
 drivers/net/wireless/libertas/if_spi.c | 1204 ++++++++++++++++++++++++++++++++
 drivers/net/wireless/libertas/if_spi.h |  208 ++++++
 include/linux/spi/libertas_spi.h       |   25 +
 6 files changed, 1447 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/wireless/libertas/if_spi.c
 create mode 100644 drivers/net/wireless/libertas/if_spi.h
 create mode 100644 include/linux/spi/libertas_spi.h

diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index ea543fc..6f9ee26 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -151,6 +151,12 @@ config LIBERTAS_SDIO
 	---help---
 	  A driver for Marvell Libertas 8385 and 8686 SDIO devices.
 
+config LIBERTAS_SPI
+	tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
+	depends on LIBERTAS && SPI && GENERIC_GPIO
+	---help---
+	  A driver for Marvell Libertas 8686 SPI devices.
+
 config LIBERTAS_DEBUG
 	bool "Enable full debugging output in the Libertas module."
 	depends on LIBERTAS
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index 02080a3..0b69185 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -4,8 +4,10 @@ libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o	\
 usb8xxx-objs += if_usb.o
 libertas_cs-objs += if_cs.o
 libertas_sdio-objs += if_sdio.o
+libertas_spi-objs += if_spi.o
 
 obj-$(CONFIG_LIBERTAS)     += libertas.o
 obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
 obj-$(CONFIG_LIBERTAS_CS)  += libertas_cs.o
 obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
+obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index b7744d6..0d1494f 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -41,6 +41,7 @@
 #define LBS_DEB_HEX	0x00200000
 #define LBS_DEB_SDIO	0x00400000
 #define LBS_DEB_SYSFS	0x00800000
+#define LBS_DEB_SPI	0x01000000
 
 extern unsigned int lbs_debug;
 
@@ -84,6 +85,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \
 #define lbs_deb_thread(fmt, args...)    LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
 #define lbs_deb_sdio(fmt, args...)      LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
 #define lbs_deb_sysfs(fmt, args...)     LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
+#define lbs_deb_spi(fmt, args...)       LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
 
 #define lbs_pr_info(format, args...) \
 	printk(KERN_INFO DRV_NAME": " format, ## args)
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
new file mode 100644
index 0000000..86b984e
--- /dev/null
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -0,0 +1,1204 @@
+/*
+ *	linux/drivers/net/wireless/libertas/if_spi.c
+ *
+ *	Driver for Marvell SPI WLAN cards.
+ *
+ *	Copyright 2008 Analog Devices Inc.
+ *
+ *	Authors:
+ *	Andrey Yurovsky <andrey at cozybit.com>
+ *	Colin McCabe <colin at cozybit.com>
+ *
+ *	Inspired by if_sdio.c, Copyright 2007-2008 Pierre Ossman
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/moduleparam.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/jiffies.h>
+#include <linux/kthread.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/spi/libertas_spi.h>
+#include <linux/spi/spi.h>
+
+#include "host.h"
+#include "decl.h"
+#include "defs.h"
+#include "dev.h"
+#include "if_spi.h"
+
+struct if_spi_packet {
+	struct list_head		list;
+	u16				blen;
+	u8				buffer[0] __attribute__((aligned(4)));
+};
+
+struct if_spi_card {
+	struct spi_device		*spi;
+	struct lbs_private		*priv;
+
+	char				helper_fw_name[FIRMWARE_NAME_MAX];
+	char				main_fw_name[FIRMWARE_NAME_MAX];
+
+	/* The card ID and card revision, as reported by the hardware. */
+	u16				card_id;
+	u8				card_rev;
+
+	/* Pin number for our GPIO chip-select. */
+	/* TODO: Once the generic SPI layer has some additional features, we
+	 * should take this out and use the normal chip select here.
+	 * We need support for chip select delays, and not dropping chipselect
+	 * after each word. */
+	int				gpio_cs;
+
+	/* The last time that we initiated an SPU operation */
+	unsigned long			prev_xfer_time;
+
+	int				use_dummy_writes;
+	unsigned long			spu_port_delay;
+	unsigned long			spu_reg_delay;
+
+	/* Handles all SPI communication (except for FW load) */
+	struct task_struct		*spi_thread;
+	int				run_thread;
+
+	/* Used to wake up the spi_thread */
+	struct semaphore		spi_ready;
+	struct semaphore		spi_thread_terminated;
+
+	u8				cmd_buffer[IF_SPI_CMD_BUF_SIZE];
+
+	/* A buffer of incoming packets from libertas core.
+	 * Since we can't sleep in hw_host_to_card, we have to buffer
+	 * them. */
+	struct list_head		cmd_packet_list;
+	struct list_head		data_packet_list;
+
+	/* Protects cmd_packet_list and data_packet_list */
+	spinlock_t			buffer_lock;
+};
+
+static void free_if_spi_card(struct if_spi_card *card)
+{
+	struct list_head *cursor, *next;
+	struct if_spi_packet *packet;
+
+	BUG_ON(card->run_thread);
+	list_for_each_safe(cursor, next, &card->cmd_packet_list) {
+		packet = container_of(cursor, struct if_spi_packet, list);
+		list_del(&packet->list);
+		kfree(packet);
+	}
+	list_for_each_safe(cursor, next, &card->data_packet_list) {
+		packet = container_of(cursor, struct if_spi_packet, list);
+		list_del(&packet->list);
+		kfree(packet);
+	}
+	spi_set_drvdata(card->spi, NULL);
+	kfree(card);
+}
+
+static struct chip_ident chip_id_to_device_name[] = {
+	{ .chip_id = 0x04, .name = 8385 },
+	{ .chip_id = 0x0b, .name = 8686 },
+};
+
+/*
+ * SPI Interface Unit Routines
+ *
+ * The SPU sits between the host and the WLAN module.
+ * All communication with the firmware is through SPU transactions.
+ *
+ * First we have to put a SPU register name on the bus. Then we can
+ * either read from or write to that register.
+ *
+ * For 16-bit transactions, byte order on the bus is big-endian.
+ * We don't have to worry about that here, though.
+ * The translation takes place in the SPI routines.
+ */
+
+static void spu_transaction_init(struct if_spi_card *card)
+{
+	if (!time_after(jiffies, card->prev_xfer_time + 1)) {
+		/* Unfortunately, the SPU requires a delay between successive
+		 * transactions. If our last transaction was more than a jiffy
+		 * ago, we have obviously already delayed enough.
+		 * If not, we have to busy-wait to be on the safe side. */
+		ndelay(400);
+	}
+	gpio_set_value(card->gpio_cs, 0); /* assert CS */
+}
+
+static void spu_transaction_finish(struct if_spi_card *card)
+{
+	gpio_set_value(card->gpio_cs, 1); /* drop CS */
+	card->prev_xfer_time = jiffies;
+}
+
+/* Write out a byte buffer to an SPI register,
+ * using a series of 16-bit transfers. */
+static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
+{
+	int err = 0;
+	u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK;
+
+	/* You must give an even number of bytes to the SPU, even if it
+	 * doesn't care about the last one.  */
+	BUG_ON(len & 0x1);
+
+	spu_transaction_init(card);
+
+	/* write SPU register index */
+	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
+	if (err)
+		goto out;
+
+	err = spi_write(card->spi, buf, len);
+
+out:
+	spu_transaction_finish(card);
+	return err;
+}
+
+static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val)
+{
+	return spu_write(card, reg, (u8 *)&val, sizeof(u16));
+}
+
+static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val)
+{
+	/* The lower 16 bits are written first. */
+	u16 out[2];
+	out[0] = val & 0xffff;
+	out[1] = (val & 0xffff0000) >> 16;
+	return spu_write(card, reg, (u8 *)&out, sizeof(u32));
+}
+
+static inline int spu_reg_is_port_reg(u16 reg)
+{
+	switch (reg) {
+	case IF_SPI_IO_RDWRPORT_REG:
+	case IF_SPI_CMD_RDWRPORT_REG:
+	case IF_SPI_DATA_RDWRPORT_REG:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
+{
+	unsigned int i, delay;
+	int err = 0;
+	u16 zero = 0;
+	u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK;
+
+	/* You must take an even number of bytes from the SPU, even if you
+	 * don't care about the last one.  */
+	BUG_ON(len & 0x1);
+
+	spu_transaction_init(card);
+
+	/* write SPU register index */
+	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
+	if (err)
+		goto out;
+
+	delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay :
+						card->spu_reg_delay;
+	if (card->use_dummy_writes) {
+		/* Clock in dummy cycles while the SPU fills the FIFO */
+		for (i = 0; i < delay / 16; ++i) {
+			err = spi_write(card->spi, (u8 *)&zero, sizeof(u16));
+			if (err)
+				return err;
+		}
+	} else {
+		/* Busy-wait while the SPU fills the FIFO */
+		ndelay(100 + (delay * 10));
+	}
+
+	/* read in data */
+	err = spi_read(card->spi, buf, len);
+
+out:
+	spu_transaction_finish(card);
+	return err;
+}
+
+/* Read 16 bits from an SPI register */
+static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
+{
+	return spu_read(card, reg, (u8 *)val, sizeof(u16));
+}
+
+/* Read 32 bits from an SPI register.
+ * The low 16 bits are read first. */
+static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
+{
+	u16 buf[2];
+	int err;
+	err = spu_read(card, reg, (u8 *)buf, sizeof(u32));
+	if (!err)
+		*val = buf[0] | (buf[1] << 16);
+	return err;
+}
+
+/* Keep reading 16 bits from an SPI register until you get the correct result.
+ *
+ * If mask = 0, the correct result is any non-zero number.
+ * If mask != 0, the correct result is any number where
+ * number & target_mask == target
+ *
+ * Returns -ETIMEDOUT if a second passes without the correct result. */
+static int spu_wait_for_u16(struct if_spi_card *card, u16 reg,
+			u16 target_mask, u16 target)
+{
+	int err;
+	unsigned long timeout = jiffies + 5*HZ;
+	while (1) {
+		u16 val;
+		err = spu_read_u16(card, reg, &val);
+		if (err)
+			return err;
+		if (target_mask) {
+			if ((val & target_mask) == target)
+				return 0;
+		} else {
+			if (val)
+				return 0;
+		}
+		udelay(100);
+		if (time_after(jiffies, timeout)) {
+			lbs_pr_err("%s: timeout with val=%02x, "
+			       "target_mask=%02x, target=%02x\n",
+			       __func__, val, target_mask, target);
+			return -ETIMEDOUT;
+		}
+	}
+}
+
+/* Read 16 bits from an SPI register until you receive a specific value.
+ * Returns -ETIMEDOUT if a 4 tries pass without success. */
+static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target)
+{
+	int err, try;
+	for (try = 0; try < 4; ++try) {
+		u32 val = 0;
+		err = spu_read_u32(card, reg, &val);
+		if (err)
+			return err;
+		if (val == target)
+			return 0;
+		mdelay(100);
+	}
+	return -ETIMEDOUT;
+}
+
+static int spu_set_interrupt_mode(struct if_spi_card *card,
+			   int suppress_host_int,
+			   int auto_int)
+{
+	int err = 0;
+
+	/* We can suppress a host interrupt by clearing the appropriate
+	 * bit in the "host interrupt status mask" register */
+	if (suppress_host_int) {
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
+		if (err)
+			return err;
+	} else {
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG,
+			      IF_SPI_HISM_TX_DOWNLOAD_RDY |
+			      IF_SPI_HISM_RX_UPLOAD_RDY |
+			      IF_SPI_HISM_CMD_DOWNLOAD_RDY |
+			      IF_SPI_HISM_CARDEVENT |
+			      IF_SPI_HISM_CMD_UPLOAD_RDY);
+		if (err)
+			return err;
+	}
+
+	/* If auto-interrupts are on, the completion of certain transactions
+	 * will trigger an interrupt automatically. If auto-interrupts
+	 * are off, we need to set the "Card Interrupt Cause" register to
+	 * trigger a card interrupt. */
+	if (auto_int) {
+		err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG,
+				IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO |
+				IF_SPI_HICT_RX_UPLOAD_OVER_AUTO |
+				IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO |
+				IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO);
+		if (err)
+			return err;
+	} else {
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
+		if (err)
+			return err;
+	}
+	return err;
+}
+
+static int spu_get_chip_revision(struct if_spi_card *card,
+				  u16 *card_id, u8 *card_rev)
+{
+	int err = 0;
+	u32 dev_ctrl;
+	err = spu_read_u32(card, IF_SPI_DEVICEID_CTRL_REG, &dev_ctrl);
+	if (err)
+		return err;
+	*card_id = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dev_ctrl);
+	*card_rev = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dev_ctrl);
+	return err;
+}
+
+static int spu_set_bus_mode(struct if_spi_card *card, u16 mode)
+{
+	int err = 0;
+	u16 rval;
+	/* set bus mode */
+	err = spu_write_u16(card, IF_SPI_SPU_BUS_MODE_REG, mode);
+	if (err)
+		return err;
+	/* Check that we were able to read back what we just wrote. */
+	err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval);
+	if (err)
+		return err;
+	if (rval != mode) {
+		lbs_pr_err("Can't read bus mode register.\n");
+		return -EIO;
+	}
+	return 0;
+}
+
+static int spu_init(struct if_spi_card *card, int use_dummy_writes)
+{
+	int err = 0;
+	u32 delay;
+
+	/* We have to start up in timed delay mode so that we can safely
+	 * read the Delay Read Register. */
+	card->use_dummy_writes = 0;
+	err = spu_set_bus_mode(card,
+				IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
+				IF_SPI_BUS_MODE_DELAY_METHOD_TIMED |
+				IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
+	if (err)
+		return err;
+	card->spu_port_delay = 1000;
+	card->spu_reg_delay = 1000;
+	err = spu_read_u32(card, IF_SPI_DELAY_READ_REG, &delay);
+	if (err)
+		return err;
+	card->spu_port_delay = delay & 0x0000ffff;
+	card->spu_reg_delay = (delay & 0xffff0000) >> 16;
+
+	/* If dummy clock delay mode has been requested, switch to it now */
+	if (use_dummy_writes) {
+		card->use_dummy_writes = 1;
+		err = spu_set_bus_mode(card,
+				IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
+				IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK |
+				IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
+		if (err)
+			return err;
+	}
+
+	lbs_deb_spi("Initialized SPU unit. "
+		    "spu_port_delay=0x%04lx, spu_reg_delay=0x%04lx\n",
+		    card->spu_port_delay, card->spu_reg_delay);
+	return err;
+}
+
+/*
+ * Firmware Loading
+ */
+
+static int if_spi_prog_helper_firmware(struct if_spi_card *card)
+{
+	int err = 0;
+	const struct firmware *firmware = NULL;
+	int bytes_remaining;
+	const u8 *fw;
+	u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
+	struct spi_device *spi = card->spi;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	err = spu_set_interrupt_mode(card, 1, 0);
+	if (err)
+		goto out;
+	/* Get helper firmware image */
+	err = request_firmware(&firmware, card->helper_fw_name, &spi->dev);
+	if (err) {
+		lbs_pr_err("request_firmware failed with err = %d\n", err);
+		goto out;
+	}
+	bytes_remaining = firmware->size;
+	fw = firmware->data;
+
+	/* Load helper firmware image */
+	while (bytes_remaining > 0) {
+		/* Scratch pad 1 should contain the number of bytes we
+		 * want to download to the firmware */
+		err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
+					HELPER_FW_LOAD_CHUNK_SZ);
+		if (err)
+			goto release_firmware;
+
+		err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+					IF_SPI_HIST_CMD_DOWNLOAD_RDY,
+					IF_SPI_HIST_CMD_DOWNLOAD_RDY);
+		if (err)
+			goto release_firmware;
+
+		/* Feed the data into the command read/write port reg
+		 * in chunks of 64 bytes */
+		memset(temp, 0, sizeof(temp));
+		memcpy(temp, fw,
+		       min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ));
+		mdelay(10);
+		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
+					temp, HELPER_FW_LOAD_CHUNK_SZ);
+		if (err)
+			goto release_firmware;
+
+		/* Interrupt the boot code */
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
+		if (err)
+			goto release_firmware;
+		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
+				       IF_SPI_CIC_CMD_DOWNLOAD_OVER);
+		if (err)
+			goto release_firmware;
+		bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
+		fw += HELPER_FW_LOAD_CHUNK_SZ;
+	}
+
+	/* Once the helper / single stage firmware download is complete,
+	 * write 0 to scratch pad 1 and interrupt the
+	 * bootloader. This completes the helper download. */
+	err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
+	if (err)
+		goto release_firmware;
+	err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
+	if (err)
+		goto release_firmware;
+	err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
+				IF_SPI_CIC_CMD_DOWNLOAD_OVER);
+		goto release_firmware;
+
+	lbs_deb_spi("waiting for helper to boot...\n");
+
+release_firmware:
+	release_firmware(firmware);
+out:
+	if (err)
+		lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
+	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+	return err;
+}
+
+/* Returns the length of the next packet the firmware expects us to send
+ * Sets crc_err if the previous transfer had a CRC error. */
+static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
+						int *crc_err)
+{
+	u16 len;
+	int err = 0;
+
+	/* wait until the host interrupt status register indicates
+	 * that we are ready to download */
+	err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+				IF_SPI_HIST_CMD_DOWNLOAD_RDY,
+				IF_SPI_HIST_CMD_DOWNLOAD_RDY);
+	if (err) {
+		lbs_pr_err("timed out waiting for host_int_status\n");
+		return err;
+	}
+
+	/* Ask the device how many bytes of firmware it wants. */
+	err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
+	if (err)
+		return err;
+
+	if (len > IF_SPI_CMD_BUF_SIZE) {
+		lbs_pr_err("firmware load device requested a larger "
+			   "tranfer than we are prepared to "
+			   "handle. (len = %d)\n", len);
+		return -EIO;
+	}
+	if (len & 0x1) {
+		lbs_deb_spi("%s: crc error\n", __func__);
+		len &= ~0x1;
+		*crc_err = 1;
+	} else
+		*crc_err = 0;
+
+	return len;
+}
+
+static int if_spi_prog_main_firmware(struct if_spi_card *card)
+{
+	int len, prev_len;
+	int bytes, crc_err = 0, err = 0;
+	const struct firmware *firmware = NULL;
+	const u8 *fw;
+	struct spi_device *spi = card->spi;
+	u16 num_crc_errs;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	err = spu_set_interrupt_mode(card, 1, 0);
+	if (err)
+		goto out;
+
+	/* Get firmware image */
+	err = request_firmware(&firmware, card->main_fw_name, &spi->dev);
+	if (err) {
+		lbs_pr_err("%s: can't get firmware '%s' from kernel. "
+			"err = %d\n", __func__, card->main_fw_name, err);
+		goto out;
+	}
+
+	err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
+	if (err) {
+		lbs_pr_err("%s: timed out waiting for initial "
+			   "scratch reg = 0\n", __func__);
+		goto release_firmware;
+	}
+
+	num_crc_errs = 0;
+	prev_len = 0;
+	bytes = firmware->size;
+	fw = firmware->data;
+	while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
+		if (len < 0) {
+			err = len;
+			goto release_firmware;
+		}
+		if (bytes < 0) {
+			/* If there are no more bytes left, we would normally
+			 * expect to have terminated with len = 0 */
+			lbs_pr_err("Firmware load wants more bytes "
+				   "than we have to offer.\n");
+			break;
+		}
+		if (crc_err) {
+			/* Previous transfer failed. */
+			if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) {
+				lbs_pr_err("Too many CRC errors encountered "
+					   "in firmware load.\n");
+				err = -EIO;
+				goto release_firmware;
+			}
+		} else {
+			/* Previous transfer succeeded. Advance counters. */
+			bytes -= prev_len;
+			fw += prev_len;
+		}
+		if (bytes < len) {
+			memset(card->cmd_buffer, 0, len);
+			memcpy(card->cmd_buffer, fw, bytes);
+		} else
+			memcpy(card->cmd_buffer, fw, len);
+
+		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
+		if (err)
+			goto release_firmware;
+		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
+				card->cmd_buffer, len);
+		if (err)
+			goto release_firmware;
+		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
+					IF_SPI_CIC_CMD_DOWNLOAD_OVER);
+		if (err)
+			goto release_firmware;
+		prev_len = len;
+	}
+	if (bytes > prev_len) {
+		lbs_pr_err("firmware load wants fewer bytes than "
+			   "we have to offer.\n");
+	}
+
+	/* Confirm firmware download */
+	err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG,
+					SUCCESSFUL_FW_DOWNLOAD_MAGIC);
+	if (err) {
+		lbs_pr_err("failed to confirm the firmware download\n");
+		goto release_firmware;
+	}
+
+release_firmware:
+	release_firmware(firmware);
+
+out:
+	if (err)
+		lbs_pr_err("failed to load firmware (err=%d)\n", err);
+	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
+	return err;
+}
+
+/*
+ * SPI Transfer Thread
+ *
+ * The SPI thread handles all SPI transfers, so there is no need for a lock.
+ */
+
+/* Move a command from the card to the host */
+static int if_spi_c2h_cmd(struct if_spi_card *card)
+{
+	struct lbs_private *priv = card->priv;
+	unsigned long flags;
+	int err = 0;
+	u16 len;
+	u8 i;
+
+	/* We need a buffer big enough to handle whatever people send to
+	 * hw_host_to_card */
+	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE);
+	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE);
+
+	/* It's just annoying if the buffer size isn't a multiple of 4, because
+	 * then we might have len <  IF_SPI_CMD_BUF_SIZE but
+	 * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */
+	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0);
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	/* How many bytes are there to read? */
+	err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len);
+	if (err)
+		goto out;
+	if (!len) {
+		lbs_pr_err("%s: error: card has no data for host\n",
+			   __func__);
+		err = -EINVAL;
+		goto out;
+	} else if (len > IF_SPI_CMD_BUF_SIZE) {
+		lbs_pr_err("%s: error: response packet too large: "
+			   "%d bytes, but maximum is %d\n",
+			   __func__, len, IF_SPI_CMD_BUF_SIZE);
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* Read the data from the WLAN module into our command buffer */
+	err = spu_read(card, IF_SPI_CMD_RDWRPORT_REG,
+				card->cmd_buffer, ALIGN(len, 4));
+	if (err)
+		goto out;
+
+	spin_lock_irqsave(&priv->driver_lock, flags);
+	i = (priv->resp_idx == 0) ? 1 : 0;
+	BUG_ON(priv->resp_len[i]);
+	priv->resp_len[i] = len;
+	memcpy(priv->resp_buf[i], card->cmd_buffer, len);
+	lbs_notify_command_response(priv, i);
+	spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+out:
+	if (err)
+		lbs_pr_err("%s: err=%d\n", __func__, err);
+	lbs_deb_leave(LBS_DEB_SPI);
+	return err;
+}
+
+/* Move data from the card to the host */
+static int if_spi_c2h_data(struct if_spi_card *card)
+{
+	struct sk_buff *skb;
+	char *data;
+	u16 len;
+	int err = 0;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	/* How many bytes are there to read? */
+	err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
+	if (err)
+		goto out;
+	if (!len) {
+		lbs_pr_err("%s: error: card has no data for host\n",
+			   __func__);
+		err = -EINVAL;
+		goto out;
+	} else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
+		lbs_pr_err("%s: error: card has %d bytes of data, but "
+			   "our maximum skb size is %u\n",
+			   __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* TODO: should we allocate a smaller skb if we have less data? */
+	skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
+	if (!skb) {
+		err = -ENOBUFS;
+		goto out;
+	}
+	skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
+	data = skb_put(skb, len);
+
+	/* Read the data from the WLAN module into our skb... */
+	err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4));
+	if (err)
+		goto free_skb;
+
+	/* pass the SKB to libertas */
+	err = lbs_process_rxed_packet(card->priv, skb);
+	if (err)
+		goto free_skb;
+
+	/* success */
+	goto out;
+
+free_skb:
+	dev_kfree_skb(skb);
+out:
+	if (err)
+		lbs_pr_err("%s: err=%d\n", __func__, err);
+	lbs_deb_leave(LBS_DEB_SPI);
+	return err;
+}
+
+/* Move data or a command from the host to the card. */
+static void if_spi_h2c(struct if_spi_card *card,
+			struct if_spi_packet *packet, int type)
+{
+	int err = 0;
+	u16 int_type, port_reg;
+
+	switch (type) {
+	case MVMS_DAT:
+		int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
+		port_reg = IF_SPI_DATA_RDWRPORT_REG;
+		break;
+	case MVMS_CMD:
+		int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
+		port_reg = IF_SPI_CMD_RDWRPORT_REG;
+		break;
+	default:
+		lbs_pr_err("can't transfer buffer of type %d\n", type);
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* Write the data to the card */
+	err = spu_write(card, port_reg, packet->buffer, packet->blen);
+	if (err)
+		goto out;
+
+out:
+	kfree(packet);
+
+	if (err)
+		lbs_pr_err("%s: error %d\n", __func__, err);
+}
+
+/* Inform the host about a card event */
+static void if_spi_e2h(struct if_spi_card *card)
+{
+	int err = 0;
+	unsigned long flags;
+	u32 cause;
+	struct lbs_private *priv = card->priv;
+
+	err = spu_read_u32(card, IF_SPI_SCRATCH_3_REG, &cause);
+	if (err)
+		goto out;
+
+	spin_lock_irqsave(&priv->driver_lock, flags);
+	lbs_queue_event(priv, cause & 0xff);
+	spin_unlock_irqrestore(&priv->driver_lock, flags);
+
+out:
+	if (err)
+		lbs_pr_err("%s: error %d\n", __func__, err);
+}
+
+static int lbs_spi_thread(void *data)
+{
+	int err;
+	struct if_spi_card *card = data;
+	u16 hiStatus;
+	unsigned long flags;
+	struct if_spi_packet *packet;
+
+	while (1) {
+		/* Wait to be woken up by one of two things.  First, our ISR
+		 * could tell us that something happened on the WLAN.
+		 * Secondly, libertas could call hw_host_to_card with more
+		 * data, which we might be able to send.
+		 */
+		do {
+			err = down_interruptible(&card->spi_ready);
+			if (!card->run_thread) {
+				up(&card->spi_thread_terminated);
+				do_exit(0);
+			}
+		} while (err == EINTR);
+
+		/* Read the host interrupt status register to see what we
+		 * can do. */
+		err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+					&hiStatus);
+		if (err) {
+			lbs_pr_err("I/O error\n");
+			goto err;
+		}
+
+		if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY)
+			err = if_spi_c2h_cmd(card);
+			if (err)
+				goto err;
+		if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY)
+			err = if_spi_c2h_data(card);
+			if (err)
+				goto err;
+		if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) {
+			/* This means two things. First of all,
+			 * if there was a previous command sent, the card has
+			 * successfully received it.
+			 * Secondly, it is now ready to download another
+			 * command.
+			 */
+			lbs_host_to_card_done(card->priv);
+
+			/* Do we have any command packets from the host to
+			 * send? */
+			packet = NULL;
+			spin_lock_irqsave(&card->buffer_lock, flags);
+			if (!list_empty(&card->cmd_packet_list)) {
+				packet = (struct if_spi_packet *)(card->
+						cmd_packet_list.next);
+				list_del(&packet->list);
+			}
+			spin_unlock_irqrestore(&card->buffer_lock, flags);
+
+			if (packet)
+				if_spi_h2c(card, packet, MVMS_CMD);
+		}
+		if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
+			/* Do we have any data packets from the host to
+			 * send? */
+			packet = NULL;
+			spin_lock_irqsave(&card->buffer_lock, flags);
+			if (!list_empty(&card->data_packet_list)) {
+				packet = (struct if_spi_packet *)(card->
+						data_packet_list.next);
+				list_del(&packet->list);
+			}
+			spin_unlock_irqrestore(&card->buffer_lock, flags);
+
+			if (packet)
+				if_spi_h2c(card, packet, MVMS_DAT);
+		}
+		if (hiStatus & IF_SPI_HIST_CARD_EVENT)
+			if_spi_e2h(card);
+
+err:
+		if (err)
+			lbs_pr_err("%s: got error %d\n", __func__, err);
+	}
+}
+
+/* Block until lbs_spi_thread thread has terminated */
+static void if_spi_terminate_spi_thread(struct if_spi_card *card)
+{
+	/* It would be nice to use kthread_stop here, but that function
+	 * can't wake threads waiting for a semaphore. */
+	card->run_thread = 0;
+	up(&card->spi_ready);
+	down(&card->spi_thread_terminated);
+}
+
+/*
+ * Host to Card
+ *
+ * Called from Libertas to transfer some data to the WLAN device
+ * We can't sleep here. */
+static int if_spi_host_to_card(struct lbs_private *priv,
+				u8 type, u8 *buf, u16 nb)
+{
+	int err = 0;
+	unsigned long flags;
+	struct if_spi_card *card = priv->card;
+	struct if_spi_packet *packet;
+	u16 blen;
+
+	lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
+
+	if (nb == 0) {
+		lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
+		err = -EINVAL;
+		goto out;
+	}
+	blen = ALIGN(nb, 4);
+	packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
+	if (!packet) {
+		err = -ENOMEM;
+		goto out;
+	}
+	packet->blen = blen;
+	memcpy(packet->buffer, buf, nb);
+	memset(packet->buffer + nb, 0, blen - nb);
+
+	switch (type) {
+	case MVMS_CMD:
+		priv->dnld_sent = DNLD_CMD_SENT;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		list_add_tail(&packet->list, &card->cmd_packet_list);
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
+		break;
+	case MVMS_DAT:
+		priv->dnld_sent = DNLD_DATA_SENT;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		list_add_tail(&packet->list, &card->data_packet_list);
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
+		break;
+	default:
+		lbs_pr_err("can't transfer buffer of type %d", type);
+		err = -EINVAL;
+		break;
+	}
+
+	/* Wake up the spi thread */
+	up(&card->spi_ready);
+out:
+	lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
+	return err;
+}
+
+/*
+ * Host Interrupts
+ *
+ * Service incoming interrupts from the WLAN device. We can't sleep here, so
+ * don't try to talk on the SPI bus, just wake up the SPI thread.
+ */
+static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
+{
+	struct if_spi_card *card = dev_id;
+
+	up(&card->spi_ready);
+	return IRQ_HANDLED;
+}
+
+/*
+ * SPI callbacks
+ */
+
+static int if_spi_calculate_fw_names(u16 card_id,
+			      char *helper_fw, char *main_fw)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
+		if (card_id == chip_id_to_device_name[i].chip_id)
+			break;
+	}
+	if (i == ARRAY_SIZE(chip_id_to_device_name)) {
+		lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
+		return -EAFNOSUPPORT;
+	}
+	snprintf(helper_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d_hlp.bin",
+		 chip_id_to_device_name[i].name);
+	snprintf(main_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d.bin",
+		 chip_id_to_device_name[i].name);
+	return 0;
+}
+
+static int __devinit if_spi_probe(struct spi_device *spi)
+{
+	struct if_spi_card *card;
+	struct lbs_private *priv = NULL;
+	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
+	int err = 0;
+	u32 scratch;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	/* Allocate card structure to represent this specific device */
+	card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL);
+	if (!card) {
+		err = -ENOMEM;
+		goto out;
+	}
+	spi_set_drvdata(spi, card);
+	card->spi = spi;
+	card->gpio_cs = pdata->gpio_cs;
+	card->prev_xfer_time = jiffies;
+
+	sema_init(&card->spi_ready, 0);
+	sema_init(&card->spi_thread_terminated, 0);
+	INIT_LIST_HEAD(&card->cmd_packet_list);
+	INIT_LIST_HEAD(&card->data_packet_list);
+	spin_lock_init(&card->buffer_lock);
+
+	/* set up GPIO CS line. TODO: use  regular CS line */
+	err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select");
+	if (err)
+		goto free_card;
+	err = gpio_direction_output(card->gpio_cs, 1);
+	if (err)
+		goto free_gpio;
+
+	/* Initialize the SPI Interface Unit */
+	err = spu_init(card, pdata->use_dummy_writes);
+	if (err)
+		goto free_gpio;
+	err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
+	if (err)
+		goto free_gpio;
+
+	/* Firmware load */
+	err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
+	if (err)
+		goto free_gpio;
+	if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
+		lbs_deb_spi("Firmware is already loaded for "
+			    "Marvell WLAN 802.11 adapter\n");
+	else {
+		err = if_spi_calculate_fw_names(card->card_id,
+				card->helper_fw_name, card->main_fw_name);
+		if (err)
+			goto free_gpio;
+
+		lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
+				"(chip_id = 0x%04x, chip_rev = 0x%02x) "
+				"attached to SPI bus_num %d, chip_select %d. "
+				"spi->max_speed_hz=%d\n",
+				card->card_id, card->card_rev,
+				spi->master->bus_num, spi->chip_select,
+				spi->max_speed_hz);
+		err = if_spi_prog_helper_firmware(card);
+		if (err)
+			goto free_gpio;
+		err = if_spi_prog_main_firmware(card);
+		if (err)
+			goto free_gpio;
+		lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
+	}
+
+	err = spu_set_interrupt_mode(card, 0, 1);
+	if (err)
+		goto free_gpio;
+
+	/* Register our card with libertas.
+	 * This will call alloc_etherdev */
+	priv = lbs_add_card(card, &spi->dev);
+	if (!priv) {
+		err = -ENOMEM;
+		goto free_gpio;
+	}
+	card->priv = priv;
+	priv->card = card;
+	priv->hw_host_to_card = if_spi_host_to_card;
+	priv->fw_ready = 1;
+	priv->ps_supported = 1;
+
+	/* Initialize interrupt handling stuff. */
+	card->run_thread = 1;
+	card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread");
+	if (IS_ERR(card->spi_thread)) {
+		card->run_thread = 0;
+		err = PTR_ERR(card->spi_thread);
+		lbs_pr_err("error creating SPI thread: err=%d\n", err);
+		goto remove_card;
+	}
+	err = request_irq(spi->irq, if_spi_host_interrupt,
+			IRQF_TRIGGER_FALLING, "libertas_spi", card);
+	if (err) {
+		lbs_pr_err("can't get host irq line-- request_irq failed\n");
+		goto terminate_thread;
+	}
+
+	/* Start the card.
+	 * This will call register_netdev, and we'll start
+	 * getting interrupts... */
+	err = lbs_start_card(priv);
+	if (err)
+		goto release_irq;
+
+	lbs_deb_spi("Finished initializing WLAN module.\n");
+
+	/* successful exit */
+	goto out;
+
+release_irq:
+	free_irq(spi->irq, card);
+terminate_thread:
+	if_spi_terminate_spi_thread(card);
+remove_card:
+	lbs_remove_card(priv); /* will call free_netdev */
+free_gpio:
+	gpio_free(card->gpio_cs);
+free_card:
+	free_if_spi_card(card);
+out:
+	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
+	return err;
+}
+
+static int __devexit libertas_spi_remove(struct spi_device *spi)
+{
+	struct if_spi_card *card = spi_get_drvdata(spi);
+	struct lbs_private *priv = card->priv;
+
+	lbs_deb_spi("libertas_spi_remove\n");
+	lbs_deb_enter(LBS_DEB_SPI);
+	priv->surpriseremoved = 1;
+
+	lbs_stop_card(priv);
+	free_irq(spi->irq, card);
+	if_spi_terminate_spi_thread(card);
+	lbs_remove_card(priv); /* will call free_netdev */
+	gpio_free(card->gpio_cs);
+	free_if_spi_card(card);
+	lbs_deb_leave(LBS_DEB_SPI);
+	return 0;
+}
+
+static struct spi_driver libertas_spi_driver = {
+	.probe	= if_spi_probe,
+	.remove = __devexit_p(libertas_spi_remove),
+	.driver = {
+		.name	= "libertas_spi",
+		.bus	= &spi_bus_type,
+		.owner	= THIS_MODULE,
+	},
+};
+
+/*
+ * Module functions
+ */
+
+static int __init if_spi_init_module(void)
+{
+	int ret = 0;
+	lbs_deb_enter(LBS_DEB_SPI);
+	printk(KERN_INFO "libertas_spi: Libertas SPI driver\n");
+	ret = spi_register_driver(&libertas_spi_driver);
+	lbs_deb_leave(LBS_DEB_SPI);
+	return ret;
+}
+
+static void __exit if_spi_exit_module(void)
+{
+	lbs_deb_enter(LBS_DEB_SPI);
+	spi_unregister_driver(&libertas_spi_driver);
+	lbs_deb_leave(LBS_DEB_SPI);
+}
+
+module_init(if_spi_init_module);
+module_exit(if_spi_exit_module);
+
+MODULE_DESCRIPTION("Libertas SPI WLAN Driver");
+MODULE_AUTHOR("Andrey Yurovsky <andrey at cozybit.com>, "
+	      "Colin McCabe <colin at cozybit.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h
new file mode 100644
index 0000000..2103869
--- /dev/null
+++ b/drivers/net/wireless/libertas/if_spi.h
@@ -0,0 +1,208 @@
+/*
+ *	linux/drivers/net/wireless/libertas/if_spi.c
+ *
+ *	Driver for Marvell SPI WLAN cards.
+ *
+ *	Copyright 2008 Analog Devices Inc.
+ *
+ *	Authors:
+ *	Andrey Yurovsky <andrey at cozybit.com>
+ *	Colin McCabe <colin at cozybit.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#ifndef _LBS_IF_SPI_H_
+#define _LBS_IF_SPI_H_
+
+#define IPFIELD_ALIGN_OFFSET 2
+#define IF_SPI_CMD_BUF_SIZE 2400
+
+/***************** Firmware *****************/
+struct chip_ident {
+	u16 chip_id;
+	u16 name;
+};
+
+#define MAX_MAIN_FW_LOAD_CRC_ERR 10
+
+/* Chunk size when loading the helper firmware */
+#define HELPER_FW_LOAD_CHUNK_SZ 64
+
+/* Value to write to indicate end of helper firmware dnld */
+#define FIRMWARE_DNLD_OK 0x0000
+
+/* Value to check once the main firmware is downloaded */
+#define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888
+
+/***************** SPI Interface Unit *****************/
+/* Masks used in SPI register read/write operations */
+#define IF_SPI_READ_OPERATION_MASK 0x0
+#define IF_SPI_WRITE_OPERATION_MASK 0x8000
+
+/* SPI register offsets. 4-byte aligned. */
+#define IF_SPI_DEVICEID_CTRL_REG 0x00	/* DeviceID controller reg */
+#define IF_SPI_IO_READBASE_REG 0x04 	/* Read I/O base reg */
+#define IF_SPI_IO_WRITEBASE_REG 0x08	/* Write I/O base reg */
+#define IF_SPI_IO_RDWRPORT_REG 0x0C	/* Read/Write I/O port reg */
+
+#define IF_SPI_CMD_READBASE_REG 0x10	/* Read command base reg */
+#define IF_SPI_CMD_WRITEBASE_REG 0x14	/* Write command base reg */
+#define IF_SPI_CMD_RDWRPORT_REG 0x18	/* Read/Write command port reg */
+
+#define IF_SPI_DATA_READBASE_REG 0x1C	/* Read data base reg */
+#define IF_SPI_DATA_WRITEBASE_REG 0x20	/* Write data base reg */
+#define IF_SPI_DATA_RDWRPORT_REG 0x24	/* Read/Write data port reg */
+
+#define IF_SPI_SCRATCH_1_REG 0x28	/* Scratch reg 1 */
+#define IF_SPI_SCRATCH_2_REG 0x2C	/* Scratch reg 2 */
+#define IF_SPI_SCRATCH_3_REG 0x30	/* Scratch reg 3 */
+#define IF_SPI_SCRATCH_4_REG 0x34	/* Scratch reg 4 */
+
+#define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */
+#define IF_SPI_TX_FRAME_STATUS_REG 0x3C	/* Tx frame status reg */
+
+#define IF_SPI_HOST_INT_CTRL_REG 0x40	/* Host interrupt controller reg */
+
+#define IF_SPI_CARD_INT_CAUSE_REG 0x44	/* Card interrupt cause reg */
+#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */
+#define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */
+#define IF_SPI_CARD_INT_STATUS_MASK_REG	0x50 /* Card interrupt status mask */
+
+#define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */
+
+#define IF_SPI_HOST_INT_CAUSE_REG 0x58	/* Host interrupt cause reg */
+#define IF_SPI_HOST_INT_STATUS_REG 0x5C	/* Host interrupt status reg */
+#define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */
+#define IF_SPI_HOST_INT_STATUS_MASK_REG	0x64 /* Host interrupt status mask */
+#define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */
+
+#define IF_SPI_DELAY_READ_REG 0x6C	/* Delay read reg */
+#define IF_SPI_SPU_BUS_MODE_REG 0x70	/* SPU BUS mode reg */
+
+/***************** IF_SPI_DEVICEID_CTRL_REG *****************/
+#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16)
+#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff)
+
+/***************** IF_SPI_HOST_INT_CTRL_REG *****************/
+/** Host Interrupt Control bit : Wake up */
+#define IF_SPI_HICT_WAKE_UP				(1<<0)
+/** Host Interrupt Control bit : WLAN ready */
+#define IF_SPI_HICT_WLAN_READY				(1<<1)
+/*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY		(1<<2) */
+/*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY		(1<<3) */
+/*#define IF_SPI_HICT_IRQSRC_WLAN			(1<<4) */
+/** Host Interrupt Control bit : Tx auto download */
+#define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO		(1<<5)
+/** Host Interrupt Control bit : Rx auto upload */
+#define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO			(1<<6)
+/** Host Interrupt Control bit : Command auto download */
+#define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO		(1<<7)
+/** Host Interrupt Control bit : Command auto upload */
+#define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO		(1<<8)
+
+/***************** IF_SPI_CARD_INT_CAUSE_REG *****************/
+/** Card Interrupt Case bit : Tx download over */
+#define IF_SPI_CIC_TX_DOWNLOAD_OVER			(1<<0)
+/** Card Interrupt Case bit : Rx upload over */
+#define IF_SPI_CIC_RX_UPLOAD_OVER			(1<<1)
+/** Card Interrupt Case bit : Command download over */
+#define IF_SPI_CIC_CMD_DOWNLOAD_OVER			(1<<2)
+/** Card Interrupt Case bit : Host event */
+#define IF_SPI_CIC_HOST_EVENT				(1<<3)
+/** Card Interrupt Case bit : Command upload over */
+#define IF_SPI_CIC_CMD_UPLOAD_OVER			(1<<4)
+/** Card Interrupt Case bit : Power down */
+#define IF_SPI_CIC_POWER_DOWN				(1<<5)
+
+/***************** IF_SPI_CARD_INT_STATUS_REG *****************/
+#define IF_SPI_CIS_TX_DOWNLOAD_OVER			(1<<0)
+#define IF_SPI_CIS_RX_UPLOAD_OVER			(1<<1)
+#define IF_SPI_CIS_CMD_DOWNLOAD_OVER			(1<<2)
+#define IF_SPI_CIS_HOST_EVENT				(1<<3)
+#define IF_SPI_CIS_CMD_UPLOAD_OVER			(1<<4)
+#define IF_SPI_CIS_POWER_DOWN				(1<<5)
+
+/***************** IF_SPI_HOST_INT_CAUSE_REG *****************/
+#define IF_SPI_HICU_TX_DOWNLOAD_RDY			(1<<0)
+#define IF_SPI_HICU_RX_UPLOAD_RDY			(1<<1)
+#define IF_SPI_HICU_CMD_DOWNLOAD_RDY			(1<<2)
+#define IF_SPI_HICU_CARD_EVENT				(1<<3)
+#define IF_SPI_HICU_CMD_UPLOAD_RDY			(1<<4)
+#define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW			(1<<5)
+#define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW		(1<<6)
+#define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW		(1<<7)
+#define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW		(1<<8)
+#define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW		(1<<9)
+#define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW		(1<<10)
+
+/***************** IF_SPI_HOST_INT_STATUS_REG *****************/
+/** Host Interrupt Status bit : Tx download ready */
+#define IF_SPI_HIST_TX_DOWNLOAD_RDY			(1<<0)
+/** Host Interrupt Status bit : Rx upload ready */
+#define IF_SPI_HIST_RX_UPLOAD_RDY			(1<<1)
+/** Host Interrupt Status bit : Command download ready */
+#define IF_SPI_HIST_CMD_DOWNLOAD_RDY			(1<<2)
+/** Host Interrupt Status bit : Card event */
+#define IF_SPI_HIST_CARD_EVENT				(1<<3)
+/** Host Interrupt Status bit : Command upload ready */
+#define IF_SPI_HIST_CMD_UPLOAD_RDY			(1<<4)
+/** Host Interrupt Status bit : I/O write FIFO overflow */
+#define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW			(1<<5)
+/** Host Interrupt Status bit : I/O read FIFO underflow */
+#define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW			(1<<6)
+/** Host Interrupt Status bit : Data write FIFO overflow */
+#define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW		(1<<7)
+/** Host Interrupt Status bit : Data read FIFO underflow */
+#define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW		(1<<8)
+/** Host Interrupt Status bit : Command write FIFO overflow */
+#define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW		(1<<9)
+/** Host Interrupt Status bit : Command read FIFO underflow */
+#define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW		(1<<10)
+
+/***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/
+/** Host Interrupt Status Mask bit : Tx download ready */
+#define IF_SPI_HISM_TX_DOWNLOAD_RDY			(1<<0)
+/** Host Interrupt Status Mask bit : Rx upload ready */
+#define IF_SPI_HISM_RX_UPLOAD_RDY			(1<<1)
+/** Host Interrupt Status Mask bit : Command download ready */
+#define IF_SPI_HISM_CMD_DOWNLOAD_RDY			(1<<2)
+/** Host Interrupt Status Mask bit : Card event */
+#define IF_SPI_HISM_CARDEVENT				(1<<3)
+/** Host Interrupt Status Mask bit : Command upload ready */
+#define IF_SPI_HISM_CMD_UPLOAD_RDY			(1<<4)
+/** Host Interrupt Status Mask bit : I/O write FIFO overflow */
+#define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW			(1<<5)
+/** Host Interrupt Status Mask bit : I/O read FIFO underflow */
+#define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW		(1<<6)
+/** Host Interrupt Status Mask bit : Data write FIFO overflow */
+#define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW		(1<<7)
+/** Host Interrupt Status Mask bit : Data write FIFO underflow */
+#define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW		(1<<8)
+/** Host Interrupt Status Mask bit : Command write FIFO overflow */
+#define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW		(1<<9)
+/** Host Interrupt Status Mask bit : Command write FIFO underflow */
+#define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW		(1<<10)
+
+/***************** IF_SPI_SPU_BUS_MODE_REG *****************/
+/* SCK edge on which the WLAN module outputs data on MISO */
+#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8
+#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0
+
+/* In a SPU read operation, there is a delay between writing the SPU
+ * register name and getting back data from the WLAN module.
+ * This can be specified in terms of nanoseconds or in terms of dummy
+ * clock cycles which the master must output before receiving a response. */
+#define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4
+#define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0
+
+/* Some different modes of SPI operation */
+#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00
+#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01
+#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02
+#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03
+
+#endif
diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h
new file mode 100644
index 0000000..ada71b4
--- /dev/null
+++ b/include/linux/spi/libertas_spi.h
@@ -0,0 +1,25 @@
+/*
+ * board-specific data for the libertas_spi driver.
+ *
+ * Copyright 2008 Analog Devices Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+#ifndef _LIBERTAS_SPI_H_
+#define _LIBERTAS_SPI_H_
+struct libertas_spi_platform_data {
+	/* There are two ways to read data from the WLAN module's SPI
+	 * interface. Setting 0 or 1 here controls which one is used.
+	 *
+	 * Usually you want to set use_dummy_writes = 1.
+	 * However, if that doesn't work or if you are using a slow SPI clock
+	 * speed, you may want to use 0 here. */
+	u16 use_dummy_writes;
+
+	/* GPIO number to use as chip select */
+	u16 gpio_cs;
+};
+#endif
-- 
1.5.6.3



From andrey at cozybit.com  Fri Jan  9 19:34:06 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Fri, 9 Jan 2009 16:34:06 -0800
Subject: libertas: BUG: unable to handle paging request
In-Reply-To: <45e8e6c40901081441r59112db3i9d5e47dc5fd15f08@mail.gmail.com>
References: <45e8e6c40901071658j6a22fcc7gedcc41d73a61ff2a@mail.gmail.com>
	<45e8e6c40901071837o56dba8f1w6db5c7e982f698da@mail.gmail.com>
	<45e8e6c40901071945u27a8de0aqbf2b50f0075a32f3@mail.gmail.com>
	<20090107225735.J84155@bowser.eecs.harvard.edu>
	<45e8e6c40901081141s1f0b7be7g36095a4da1819d9@mail.gmail.com>
	<1231454112.24797.1.camel@localhost.localdomain>
	<45e8e6c40901081441r59112db3i9d5e47dc5fd15f08@mail.gmail.com>
Message-ID: <45e8e6c40901091634t66b5ebebr76caeebdab20ecf9@mail.gmail.com>

I've found the part of commit 29726d85d7b98558a8bc8e69b859bf12e1347f9f
that breaks libertas.  The netdev macros portion of the patch is
indeed harmless but the OOPS happens when I don't back out the last
portion of the patch, described as:

"Different to readonly reference of netdev->priv, in this driver,
netdev->pri was changed. I use netdev->ml_priv to replace
netdev->priv."

The resulting lines in the patch are as follows and if I revert them
the driver works again.  I am not familiar with ml_priv ("mid-layer
private") and what we're trying to accomplish by the above so, short
of reverting this portion of the patch, can someone place chime in on
what's going on here?  The result is that our priv data gets corrupted
and then, when it's used by WEXT callbacks, we cause a kernel oops.

@@ -1378,7 +1378,7 @@ static int lbs_add_mesh(struct lbs_private *priv)
                ret = -ENOMEM;
                goto done;
        }
-       mesh_dev->priv = priv;
+       mesh_dev->ml_priv = priv;
        priv->mesh_dev = mesh_dev;

        mesh_dev->open = lbs_dev_open;
@@ -1591,7 +1591,7 @@ static int lbs_rtap_hard_start_xmit(struct
sk_buff *skb, struct net_device *dev)

 static struct net_device_stats *lbs_rtap_get_stats(struct net_device *dev)
 {
-       struct lbs_private *priv = dev->priv;
+       struct lbs_private *priv = dev->ml_priv;
        lbs_deb_enter(LBS_DEB_NET);
        return &priv->stats;
 }
@@ -1632,7 +1632,7 @@ static int lbs_add_rtap(struct lbs_private *priv)
        rtap_dev->stop = lbs_rtap_stop;
        rtap_dev->get_stats = lbs_rtap_get_stats;
        rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit;
-       rtap_dev->priv = priv;
+       rtap_dev->ml_priv = priv;
        SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);

        ret = register_netdev(rtap_dev);


On Thu, Jan 8, 2009 at 2:41 PM, Andrey Yurovsky <andrey at cozybit.com> wrote:
> Ok, also the interface layers (ex: if_usb.c and if_sdio.c) were missed
> in that patch as well.  I'm still getting the OOPS after making
> everyone use the macros consistently so I think there's something else
> going on that's corrupting our priv data.
>
> On Thu, Jan 8, 2009 at 2:35 PM, Dan Williams <dcbw at redhat.com> wrote:
>> On Thu, 2009-01-08 at 11:41 -0800, Andrey Yurovsky wrote:
>>> Hi Dario.  In my case I see the oops when iwconfig issues the
>>> SIOCGIWFREQ icotl and thus lbs_get_freq() is executed.  Pulling out
>>> the CMD_802_11_GET_LOG doesn't change anything in this respect.
>>>
>>> Right now I am trying to understand why the functions in wext.c access
>>> priv with:
>>>
>>> struct lbs_private *priv = dev->priv;
>>
>> They probably just got forgotten or something during the conversion.
>> They should be using the same methods as everything else, really, since
>> it's just a netdev and they are trying to access the private driver
>> data.
>>
>> Dan
>>
>>> while the rest of the driver uses the netdev macros, for example:
>>>
>>> struct lbs_private *priv = netdev_priv(to_net_dev(dev));
>>>
>>> after the commit in question, or
>>>
>>> struct lbs_private *priv = to_net_dev(dev)->priv;
>>>
>>> before the commit in question.  Converting the WEXT callbacks to use
>>> the netdev macros doesn't seem to solve the problem.  Thanks,
>>>
>>>   -Andrey
>>>
>>> On Wed, Jan 7, 2009 at 8:01 PM, Dario Vlah <dario at eecs.harvard.edu> wrote:
>>> > Hi Andrey,
>>> >
>>> > I ran into some trouble with the GET_LOG command on the jax10 device, which
>>> > happens to be called by iwconfig.  Could that be related?  What if you
>>> > disable the GET_LOG call?
>>> >
>>> > In my case issuing that command results in the firmware returning bogus
>>> > values such as negative buffer sizes which end up crashing the kernel.
>>> >
>>> > --dario
>>> >
>>> > On Wed, 7 Jan 2009, Andrey Yurovsky wrote:
>>> >
>>> >> Hmm, I do see the problem start at
>>> >> 29726d85d7b98558a8bc8e69b859bf12e1347f9f and after, but I don't think
>>> >> that I'm right with my analysis, especially since the OOPS happens in
>>> >> wext.c and the functions there (namely lbs_get_freq) use netdev->priv
>>> >> directly.  I apologize for the noise but there is still something
>>> >> wrong here that I'm trying to understand better.
>>> >>
>>> >>  -Andrey
>>> >>
>>> >> On Wed, Jan 7, 2009 at 6:37 PM, Andrey Yurovsky <andrey at cozybit.com>
>>> >> wrote:
>>> >>>
>>> >>> The commit that caused this regression is
>>> >>> 29726d85d7b98558a8bc8e69b859bf12e1347f9f "netdevice libertas: Fix
>>> >>> directly reference of netdev->priv" by Wang Chen.  It probably causes
>>> >>> a problem with netdev->priv's offset and then we get a pointer
>>> >>> dereference problem when lbs_get_freq() tries to use its priv data.
>>> >>>
>>> >>>  -Andrey
>>> >>>
>>> >>> On Wed, Jan 7, 2009 at 4:58 PM, Andrey Yurovsky <andrey at cozybit.com>
>>> >>> wrote:
>>> >>>>
>>> >>>> Hello.  I noticed that the libertas driver causes a kernel oops in
>>> >>>> more recent wireless-testing kernels (I am bisecting right now to
>>> >>>> narrow this down).  To reproduce, load the driver and run iwconfig,
>>> >>>> causing lbs_get_freq() to be called.
>>> >>>>
>>> >>>> So far I know that this problem doesn't exist at the 2.6.28-rc2 tag
>>> >>>> (commit 0173a3265b228da319ceb9c1ec6a5682fd1b2d92)  but I have seen it
>>> >>>> in -rc7 and up through today's wireless-testing.  It seems that
>>> >>>> there's a regression somewhere after -rc2.  I've reproduced this with
>>> >>>> the USB hardware as well as an SDIO board.
>>> >>>>
>>> >>>> [  118.571205] BUG: unable to handle kernel paging request at 00001e01
>>> >>>> [  118.578500] IP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
>>> >>>> [  118.585417] *pde = 00000000
>>> >>>> [  118.588877] Oops: 0000 [#1]
>>> >>>> [  118.592092] last sysfs file: /sys/block/ram9/range
>>> >>>> [  118.592385] Modules linked in: usb8xxx libertas lib80211
>>> >>>> [  118.592385]
>>> >>>> [  118.592385] Pid: 2317, comm: iwconfig Not tainted (2.6.28-wl #65)
>>> >>>> Uknown
>>> >>>> [  118.592385] EIP: 0060:[<c81fddda>] EFLAGS: 00010293 CPU: 0
>>> >>>> [  118.592385] EIP is at lbs_get_freq+0x1a/0x160 [libertas]
>>> >>>> [  118.592385] EAX: 00000000 EBX: 00000000 ECX: c6891ef8 EDX: c6891e98
>>> >>>> [  118.592385] ESI: c6891ef8 EDI: c6891ef8 EBP: c7295000 ESP: c6891e10
>>> >>>> [  118.592385]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 0068
>>> >>>> [  118.592385] Process iwconfig (pid: 2317, ti=c6890000 task=c7349880
>>> >>>> task.ti=c6890000)
>>> >>>> [  118.592385] Stack:
>>> >>>> [  118.592385]  c8201b4b c6891ef8 00000010 ffffffa1 00008b05 c038aa20
>>> >>>> 00000000 c03c691c
>>> >>>> [  118.592385]  00000000 c04bc7e0 c0301287 b7f01d70 c68ce000 c6895000
>>> >>>> c04c8260 00000c04
>>> >>>> [  118.592385]  c68c7b7c 00000000 c7295000 c6891ee8 c0300325 c6891ee8
>>> >>>> c7295000 c6891ee8
>>> >>>> [  118.592385] Call Trace:
>>> >>>> [  118.592385]  [<c8201b4b>] lbs_get_name+0x2b/0xb0 [libertas]
>>> >>>> [  118.592385]  [<c038aa20>] ioctl_standard_call+0x60/0x3a0
>>> >>>> [  118.592385]  [<c0301287>] netif_receive_skb+0x1d7/0x3e0
>>> >>>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
>>> >>>> [  118.592385]  [<c0300325>] __dev_get_by_name+0x75/0x90
>>> >>>> [  118.592385]  [<c038a687>] wext_handle_ioctl+0x157/0x230
>>> >>>> [  118.592385]  [<c81fddc0>] lbs_get_freq+0x0/0x160 [libertas]
>>> >>>> [  118.592385]  [<c03034c4>] dev_ioctl+0x304/0x4f0
>>> >>>> [  118.592385]  [<c02ffdd2>] net_rx_action+0x92/0x140
>>> >>>> [  118.592385]  [<c027ca89>] pty_write+0x39/0x60
>>> >>>> [  118.592385]  [<c02f4280>] sock_ioctl+0x0/0x260
>>> >>>> [  118.592385]  [<c017e27f>] vfs_ioctl+0x1f/0x70
>>> >>>> [  118.592385]  [<c017e65b>] do_vfs_ioctl+0x24b/0x490
>>> >>>> [  118.592385]  [<c011654e>] update_curr+0x13e/0x190
>>> >>>> [  118.592385]  [<c0117fab>] set_next_entity+0x2b/0x70
>>> >>>> [  118.592385]  [<c0397c64>] schedule+0x1b4/0x350
>>> >>>> [  118.592385]  [<c017e906>] sys_ioctl+0x66/0x70
>>> >>>> [  118.592385]  [<c0103cd2>] syscall_call+0x7/0xb
>>> >>>> [  118.592385] Code: e9 38 ff ff ff 8d b6 00 00 00 00 8d bf 00 00 00
>>> >>>> 00 56 89 ce 53 83 ec 0c 8b 98 a4 01 00 00 a1 80 19 22 c8 83 e0 21 83
>>> >>>> f8 21 74 42 <0f> b6 8b 01 1e 00 00 31 d2 89 d8 e8 a6 fe ff ff 85 c0 0f
>>> >>>> 84 cd
>>> >>>> [  118.592385] EIP: [<c81fddda>] lbs_get_freq+0x1a/0x160 [libertas]
>>> >>>> SS:ESP 0068:c6891e10
>>> >>>> [  118.594153] ---[ end trace f426cd49b2b378f4 ]---
>>> >>>>
>>> >>>
>>> >>
>>> >> _______________________________________________
>>> >> libertas-dev mailing list
>>> >> libertas-dev at lists.infradead.org
>>> >> http://lists.infradead.org/mailman/listinfo/libertas-dev
>>> >>
>>> >
>>>
>>> _______________________________________________
>>> libertas-dev mailing list
>>> libertas-dev at lists.infradead.org
>>> http://lists.infradead.org/mailman/listinfo/libertas-dev
>>
>>
>


From andrey at cozybit.com  Fri Jan  9 19:55:07 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Fri, 09 Jan 2009 16:55:07 -0800 (PST)
Subject: [RFC] libertas: revert switch from priv to ml_priv
Message-ID: <4967f1eb.14098e0a.2b44.ffffd9a6@mx.google.com>

This patch reverts a part of commit 29726d85d7b98558a8bc8e69b859bf12e1347f9f
which changed some instances of priv to ml_priv and seems to have resulted in 
corruption of libertas' priv data which in turn causes a kernel oops when, for
example, priv data is accessed and derefferenced in WEXT callbacks.

I would appreciate some feedback about this, especially from folks who can
explain what this portion of the patch was trying to accomplish.  In the mean
time this makes libertas usable again without reverting the other parts of the
patch that dealt with using the netdev macros.  Thanks,

Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 69f7479..5fefe38 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -496,7 +496,7 @@ static int lbs_dev_open(struct net_device *dev)
  */
 static int lbs_mesh_stop(struct net_device *dev)
 {
-	struct lbs_private *priv = dev->ml_priv;
+	struct lbs_private *priv = netdev_priv(dev);
 
 	lbs_deb_enter(LBS_DEB_MESH);
 	spin_lock_irq(&priv->driver_lock);
@@ -1440,7 +1440,7 @@ static int lbs_add_mesh(struct lbs_private *priv)
 		ret = -ENOMEM;
 		goto done;
 	}
-	mesh_dev->ml_priv = priv;
+	mesh_dev->priv = priv;
 	priv->mesh_dev = mesh_dev;
 
 	mesh_dev->open = lbs_dev_open;
@@ -1653,7 +1653,7 @@ static int lbs_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 static struct net_device_stats *lbs_rtap_get_stats(struct net_device *dev)
 {
-	struct lbs_private *priv = dev->ml_priv;
+	struct lbs_private *priv = netdev_priv(dev);
 	lbs_deb_enter(LBS_DEB_NET);
 	return &priv->stats;
 }
@@ -1694,7 +1694,7 @@ static int lbs_add_rtap(struct lbs_private *priv)
 	rtap_dev->stop = lbs_rtap_stop;
 	rtap_dev->get_stats = lbs_rtap_get_stats;
 	rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit;
-	rtap_dev->ml_priv = priv;
+	rtap_dev->priv = priv;
 	SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
 
 	ret = register_netdev(rtap_dev);




From jic23 at cam.ac.uk  Sun Jan 11 14:50:41 2009
From: jic23 at cam.ac.uk (Jonathan Cameron)
Date: Sun, 11 Jan 2009 19:50:41 +0000
Subject: Bug? 2.6.29-rc1 on cat /proc/net/wireless
Message-ID: <496A4D91.1090605@cam.ac.uk>

Sorry all if this has already been fixed, but with 2.6.29-rc1 +
Colin McCabe's alignment fix of the other day (can't see the
relevance but that's what I'm running) just got the following
with an sdio connected 8686. I'll try tracking this one down
tomorrow if I don't hear anything.

cat /proc/net/wireless
BUG: scheduling while atomic: cat/1272/0x00000002
Modules linked in: max1363 ring_sw iio_trig_periodic_rtc industrialio rtc_pxa27x rtc_core libertas_sdio libertas lib80211 pxamci mmc_core
[<c00227c8>] (dump_stack+0x0/0x14) from [<c00318f4>] (__schedule_bug+0x4c/0x58)
[<c00318a8>] (__schedule_bug+0x0/0x58) from [<c020c61c>] (__sched_text_start+0x64/0x308)
 r4:c1116000
[<c020c5b8>] (__sched_text_start+0x0/0x308) from [<bf025b3c>] (__lbs_cmd+0xd8/0x154 [libertas])
[<bf025a64>] (__lbs_cmd+0x0/0x154 [libertas]) from [<bf021eec>] (lbs_get_wireless_stats+0xec/0x26c [libertas])
[<bf021e00>] (lbs_get_wireless_stats+0x0/0x26c [libertas]) from [<c020a0b4>] (get_wireless_stats+0x30/0x3c)
[<c020a084>] (get_wireless_stats+0x0/0x3c) from [<c020a24c>] (wireless_seq_show+0x38/0x110)
[<c020a214>] (wireless_seq_show+0x0/0x110) from [<c00a668c>] (seq_read+0x2ac/0x404)
 r5:c1117ee8 r4:c1194000
[<c00a63e0>] (seq_read+0x0/0x404) from [<c00c6ec4>] (proc_reg_read+0xac/0xc0)
[<c00c6e18>] (proc_reg_read+0x0/0xc0) from [<c008d2f0>] (vfs_read+0xc8/0x14c)
[<c008d228>] (vfs_read+0x0/0x14c) from [<c008d620>] (sys_read+0x4c/0x74)
 r7:00000000 r6:c1117f78 r5:c1387c80 r4:c1387ca0
[<c008d5d4>] (sys_read+0x0/0x74) from [<c001ef00>] (ret_fast_syscall+0x0/0x2c)
 r8:c001f0a4 r7:00000003 r6:00000003 r5:bea33c64 r4:00001000
Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE
 face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | 22
  eth0: 0002   95.  -36.  -81.       0    363      0   1179 236246        0



From dcbw at redhat.com  Mon Jan 12 09:53:37 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 12 Jan 2009 09:53:37 -0500
Subject: [PATCH v3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <1231541889-7999-1-git-send-email-colin@cozybit.com>
References: <1231541889-7999-1-git-send-email-colin@cozybit.com>
Message-ID: <1231772017.23907.3.camel@localhost.localdomain>

On Fri, 2009-01-09 at 14:58 -0800, Colin McCabe wrote:
> Add initial support for libertas devices using a GSPI interface.  This has
> been tested with the 8686.
> 
> GSPI is intended to be used on embedded systems. Board-specific parameters are
> required (see libertas_spi.h).

Were you able to take a look at the alignment patches and see if just
using 'packed' worked, rather than having everything use
get_unaligned_*?

Dan




From jic23 at cam.ac.uk  Mon Jan 12 10:00:06 2009
From: jic23 at cam.ac.uk (Jonathan Cameron)
Date: Mon, 12 Jan 2009 15:00:06 +0000
Subject: Bug? 2.6.29-rc1 on cat /proc/net/wireless
In-Reply-To: <496A4D91.1090605@cam.ac.uk>
References: <496A4D91.1090605@cam.ac.uk>
Message-ID: <496B5AF6.6030302@cam.ac.uk>

Jonathan Cameron wrote:
> Sorry all if this has already been fixed, but with 2.6.29-rc1 +
> Colin McCabe's alignment fix of the other day (can't see the
> relevance but that's what I'm running) just got the following
> with an sdio connected 8686. I'll try tracking this one down
> tomorrow if I don't hear anything.
> 
> cat /proc/net/wireless
> BUG: scheduling while atomic: cat/1272/0x00000002
> Modules linked in: max1363 ring_sw iio_trig_periodic_rtc industrialio rtc_pxa27x rtc_core libertas_sdio libertas lib80211 pxamci mmc_core
> [<c00227c8>] (dump_stack+0x0/0x14) from [<c00318f4>] (__schedule_bug+0x4c/0x58)
> [<c00318a8>] (__schedule_bug+0x0/0x58) from [<c020c61c>] (__sched_text_start+0x64/0x308)
>  r4:c1116000
> [<c020c5b8>] (__sched_text_start+0x0/0x308) from [<bf025b3c>] (__lbs_cmd+0xd8/0x154 [libertas])
> [<bf025a64>] (__lbs_cmd+0x0/0x154 [libertas]) from [<bf021eec>] (lbs_get_wireless_stats+0xec/0x26c [libertas])
> [<bf021e00>] (lbs_get_wireless_stats+0x0/0x26c [libertas]) from [<c020a0b4>] (get_wireless_stats+0x30/0x3c)
> [<c020a084>] (get_wireless_stats+0x0/0x3c) from [<c020a24c>] (wireless_seq_show+0x38/0x110)
> [<c020a214>] (wireless_seq_show+0x0/0x110) from [<c00a668c>] (seq_read+0x2ac/0x404)
>  r5:c1117ee8 r4:c1194000
> [<c00a63e0>] (seq_read+0x0/0x404) from [<c00c6ec4>] (proc_reg_read+0xac/0xc0)
> [<c00c6e18>] (proc_reg_read+0x0/0xc0) from [<c008d2f0>] (vfs_read+0xc8/0x14c)
> [<c008d228>] (vfs_read+0x0/0x14c) from [<c008d620>] (sys_read+0x4c/0x74)
>  r7:00000000 r6:c1117f78 r5:c1387c80 r4:c1387ca0
> [<c008d5d4>] (sys_read+0x0/0x74) from [<c001ef00>] (ret_fast_syscall+0x0/0x2c)
>  r8:c001f0a4 r7:00000003 r6:00000003 r5:bea33c64 r4:00001000
> Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE
>  face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | 22
>   eth0: 0002   95.  -36.  -81.       0    363      0   1179 236246        0
> 
A bit of googling suggests this has been a much discussed problem in other drivers.

How about the following patch as a work around? Bit messy at the mo, but I want
to check people are happy with basic form before cleaning up (and confirming
everything relevant has been set!)

Basically does the same as various other wireless drivers and actually gives you
the values from the last time it was queried rather than current.

--

diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index b1326e6..e51e1c5 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -1345,7 +1345,7 @@ void lbs_set_mac_control(struct lbs_private *priv)
  *  @param cmd_action	command action: GET or SET
  *  @param wait_option	wait option: wait response or not
  *  @param cmd_oid	cmd oid: treated as sub command
- *  @param pdata_buf	A pointer to informaion buffer
+ *  @param pdata_buf	A pointer to information buffer
  *  @return 		0 or -1
  */
 int lbs_prepare_and_send_command(struct lbs_private *priv,
@@ -1487,6 +1487,13 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
 		ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
 		break;
 
+	case CMD_802_11_GET_LOG:
+		cmdptr->command = cpu_to_le16(CMD_802_11_GET_LOG);
+		cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) +
+					    S_DS_GEN);
+		ret = 0;
+		break;
+
 	case CMD_GET_TSF:
 		cmdptr->command = cpu_to_le16(CMD_GET_TSF);
 		cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
@@ -1496,6 +1503,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
 	case CMD_802_11_BEACON_CTRL:
 		ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
 		break;
+
 	default:
 		lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
 		ret = -1;
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
index 14f54ad..af18b5d 100644
--- a/drivers/net/wireless/libertas/cmdresp.c
+++ b/drivers/net/wireless/libertas/cmdresp.c
@@ -200,7 +200,21 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
 			get_unaligned_le16(&bcn_ctrl->beacon_period);
 	}
 
+	lbs_deb_leave(LBS_DEB_CMD);
+	return 0;
+}
+
+static int lbs_ret_802_11_get_log(struct lbs_private * priv,
+					struct cmd_ds_command *resp)
+{
+	struct cmd_ds_802_11_get_log *log = &resp->params.log;
+
 	lbs_deb_enter(LBS_DEB_CMD);
+	priv->wstats.discard.retries = get_unaligned_le32(&log->retry);
+	priv->wstats.discard.code = get_unaligned_le32(&log->wepundecryptable);
+	priv->wstats.discard.misc = get_unaligned_le32(&log->ackfailure);
+	lbs_deb_leave(LBS_DEB_CMD);
+
 	return 0;
 }
 
@@ -284,7 +298,9 @@ static inline int handle_cmd_response(struct lbs_private *priv,
 	case CMD_RET(CMD_802_11_BEACON_CTRL):
 		ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
 		break;
-
+	case CMD_RET(CMD_802_11_GET_LOG):
+		ret = lbs_ret_802_11_get_log(priv, resp);
+		break;
 	default:
 		lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n",
 			   get_unaligned_le16(&resp->command));
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index c6d5771..00423f7 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -736,6 +736,7 @@ struct cmd_ds_command {
 
 	/* command Body */
 	union {
+		struct cmd_ds_802_11_get_log log;
 		struct cmd_ds_802_11_ps_mode psmode;
 		struct cmd_ds_802_11_associate associate;
 		struct cmd_ds_802_11_authenticate auth;
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index e1700a1..8c7201f 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -789,7 +789,6 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 	int stats_valid = 0;
 	u8 rssi;
 	u32 tx_retries;
-	struct cmd_ds_802_11_get_log log;
 
 	lbs_deb_enter(LBS_DEB_WEXT);
 
@@ -805,12 +804,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
 	     priv->NF[TYPE_BEACON][TYPE_NOAVG]);
 
-	if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
+	if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0)
 		priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
-	} else {
+	else
 		priv->wstats.qual.noise =
 		    CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
-	}
 
 	lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
 	lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise);
@@ -831,13 +829,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 	quality = rssi_qual;
 
 	/* Quality by TX errors */
-	priv->wstats.discard.retries = priv->stats.tx_errors;
+	/* Previously this line was here, but the value was overwritten
+	 * a few lines later.
+	 * priv->wstats.discard.retries = priv->stats.tx_errors; */
 
-	memset(&log, 0, sizeof(log));
-	log.hdr.size = cpu_to_le16(sizeof(log));
-	lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
-
-	tx_retries = get_unaligned_le32(&log.retry);
+	tx_retries = priv->wstats.discard.retries;
 
 	if (tx_retries > 75)
 		tx_qual = (90 - tx_retries) * POOR / 15;
@@ -847,16 +843,12 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 		tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
 	else if (tx_retries > 50)
 		tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
-		    15 + GOOD;
+			15 + GOOD;
 	else
 		tx_qual = (50 - tx_retries) *
-		    (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
+			(PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
 	quality = min(quality, tx_qual);
 
-	priv->wstats.discard.code = get_unaligned_le32(&log.wepundecryptable);
-	priv->wstats.discard.retries = tx_retries;
-	priv->wstats.discard.misc = get_unaligned_le32(&log.ackfailure);
-
 	/* Calculate quality */
 	priv->wstats.qual.qual = min_t(u8, quality, 100);
 	priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
@@ -865,6 +857,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
 	/* update stats asynchronously for future calls */
 	lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
 					0, 0, NULL);
+
+	lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
+				     0, 0, NULL);
 out:
 	if (!stats_valid) {
 		priv->wstats.miss.beacon = 0;


From linville at tuxdriver.com  Mon Jan 12 10:12:44 2009
From: linville at tuxdriver.com (John W. Linville)
Date: Mon, 12 Jan 2009 10:12:44 -0500
Subject: Bug? 2.6.29-rc1 on cat /proc/net/wireless
In-Reply-To: <496B5AF6.6030302@cam.ac.uk>
References: <496A4D91.1090605@cam.ac.uk> <496B5AF6.6030302@cam.ac.uk>
Message-ID: <20090112151243.GB31525@tuxdriver.com>

I guess this looks OK -- any comments from the libertas guys?

Do you get the same BUG w/o Colin's patch?  Did you try any other
bisection?

Thanks,

John

On Mon, Jan 12, 2009 at 03:00:06PM +0000, Jonathan Cameron wrote:
> Jonathan Cameron wrote:
> > Sorry all if this has already been fixed, but with 2.6.29-rc1 +
> > Colin McCabe's alignment fix of the other day (can't see the
> > relevance but that's what I'm running) just got the following
> > with an sdio connected 8686. I'll try tracking this one down
> > tomorrow if I don't hear anything.
> > 
> > cat /proc/net/wireless
> > BUG: scheduling while atomic: cat/1272/0x00000002
> > Modules linked in: max1363 ring_sw iio_trig_periodic_rtc industrialio rtc_pxa27x rtc_core libertas_sdio libertas lib80211 pxamci mmc_core
> > [<c00227c8>] (dump_stack+0x0/0x14) from [<c00318f4>] (__schedule_bug+0x4c/0x58)
> > [<c00318a8>] (__schedule_bug+0x0/0x58) from [<c020c61c>] (__sched_text_start+0x64/0x308)
> >  r4:c1116000
> > [<c020c5b8>] (__sched_text_start+0x0/0x308) from [<bf025b3c>] (__lbs_cmd+0xd8/0x154 [libertas])
> > [<bf025a64>] (__lbs_cmd+0x0/0x154 [libertas]) from [<bf021eec>] (lbs_get_wireless_stats+0xec/0x26c [libertas])
> > [<bf021e00>] (lbs_get_wireless_stats+0x0/0x26c [libertas]) from [<c020a0b4>] (get_wireless_stats+0x30/0x3c)
> > [<c020a084>] (get_wireless_stats+0x0/0x3c) from [<c020a24c>] (wireless_seq_show+0x38/0x110)
> > [<c020a214>] (wireless_seq_show+0x0/0x110) from [<c00a668c>] (seq_read+0x2ac/0x404)
> >  r5:c1117ee8 r4:c1194000
> > [<c00a63e0>] (seq_read+0x0/0x404) from [<c00c6ec4>] (proc_reg_read+0xac/0xc0)
> > [<c00c6e18>] (proc_reg_read+0x0/0xc0) from [<c008d2f0>] (vfs_read+0xc8/0x14c)
> > [<c008d228>] (vfs_read+0x0/0x14c) from [<c008d620>] (sys_read+0x4c/0x74)
> >  r7:00000000 r6:c1117f78 r5:c1387c80 r4:c1387ca0
> > [<c008d5d4>] (sys_read+0x0/0x74) from [<c001ef00>] (ret_fast_syscall+0x0/0x2c)
> >  r8:c001f0a4 r7:00000003 r6:00000003 r5:bea33c64 r4:00001000
> > Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE
> >  face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | 22
> >   eth0: 0002   95.  -36.  -81.       0    363      0   1179 236246        0
> > 
> A bit of googling suggests this has been a much discussed problem in other drivers.
> 
> How about the following patch as a work around? Bit messy at the mo, but I want
> to check people are happy with basic form before cleaning up (and confirming
> everything relevant has been set!)
> 
> Basically does the same as various other wireless drivers and actually gives you
> the values from the last time it was queried rather than current.
> 
> --
> 
> diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
> index b1326e6..e51e1c5 100644
> --- a/drivers/net/wireless/libertas/cmd.c
> +++ b/drivers/net/wireless/libertas/cmd.c
> @@ -1345,7 +1345,7 @@ void lbs_set_mac_control(struct lbs_private *priv)
>   *  @param cmd_action	command action: GET or SET
>   *  @param wait_option	wait option: wait response or not
>   *  @param cmd_oid	cmd oid: treated as sub command
> - *  @param pdata_buf	A pointer to informaion buffer
> + *  @param pdata_buf	A pointer to information buffer
>   *  @return 		0 or -1
>   */
>  int lbs_prepare_and_send_command(struct lbs_private *priv,
> @@ -1487,6 +1487,13 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
>  		ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf);
>  		break;
>  
> +	case CMD_802_11_GET_LOG:
> +		cmdptr->command = cpu_to_le16(CMD_802_11_GET_LOG);
> +		cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_get_log) +
> +					    S_DS_GEN);
> +		ret = 0;
> +		break;
> +
>  	case CMD_GET_TSF:
>  		cmdptr->command = cpu_to_le16(CMD_GET_TSF);
>  		cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) +
> @@ -1496,6 +1503,7 @@ int lbs_prepare_and_send_command(struct lbs_private *priv,
>  	case CMD_802_11_BEACON_CTRL:
>  		ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action);
>  		break;
> +
>  	default:
>  		lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no);
>  		ret = -1;
> diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c
> index 14f54ad..af18b5d 100644
> --- a/drivers/net/wireless/libertas/cmdresp.c
> +++ b/drivers/net/wireless/libertas/cmdresp.c
> @@ -200,7 +200,21 @@ static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv,
>  			get_unaligned_le16(&bcn_ctrl->beacon_period);
>  	}
>  
> +	lbs_deb_leave(LBS_DEB_CMD);
> +	return 0;
> +}
> +
> +static int lbs_ret_802_11_get_log(struct lbs_private * priv,
> +					struct cmd_ds_command *resp)
> +{
> +	struct cmd_ds_802_11_get_log *log = &resp->params.log;
> +
>  	lbs_deb_enter(LBS_DEB_CMD);
> +	priv->wstats.discard.retries = get_unaligned_le32(&log->retry);
> +	priv->wstats.discard.code = get_unaligned_le32(&log->wepundecryptable);
> +	priv->wstats.discard.misc = get_unaligned_le32(&log->ackfailure);
> +	lbs_deb_leave(LBS_DEB_CMD);
> +
>  	return 0;
>  }
>  
> @@ -284,7 +298,9 @@ static inline int handle_cmd_response(struct lbs_private *priv,
>  	case CMD_RET(CMD_802_11_BEACON_CTRL):
>  		ret = lbs_ret_802_11_bcn_ctrl(priv, resp);
>  		break;
> -
> +	case CMD_RET(CMD_802_11_GET_LOG):
> +		ret = lbs_ret_802_11_get_log(priv, resp);
> +		break;
>  	default:
>  		lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n",
>  			   get_unaligned_le16(&resp->command));
> diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
> index c6d5771..00423f7 100644
> --- a/drivers/net/wireless/libertas/hostcmd.h
> +++ b/drivers/net/wireless/libertas/hostcmd.h
> @@ -736,6 +736,7 @@ struct cmd_ds_command {
>  
>  	/* command Body */
>  	union {
> +		struct cmd_ds_802_11_get_log log;
>  		struct cmd_ds_802_11_ps_mode psmode;
>  		struct cmd_ds_802_11_associate associate;
>  		struct cmd_ds_802_11_authenticate auth;
> diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
> index e1700a1..8c7201f 100644
> --- a/drivers/net/wireless/libertas/wext.c
> +++ b/drivers/net/wireless/libertas/wext.c
> @@ -789,7 +789,6 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
>  	int stats_valid = 0;
>  	u8 rssi;
>  	u32 tx_retries;
> -	struct cmd_ds_802_11_get_log log;
>  
>  	lbs_deb_enter(LBS_DEB_WEXT);
>  
> @@ -805,12 +804,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
>  	    CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG],
>  	     priv->NF[TYPE_BEACON][TYPE_NOAVG]);
>  
> -	if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
> +	if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0)
>  		priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
> -	} else {
> +	else
>  		priv->wstats.qual.noise =
>  		    CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]);
> -	}
>  
>  	lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level);
>  	lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise);
> @@ -831,13 +829,11 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
>  	quality = rssi_qual;
>  
>  	/* Quality by TX errors */
> -	priv->wstats.discard.retries = priv->stats.tx_errors;
> +	/* Previously this line was here, but the value was overwritten
> +	 * a few lines later.
> +	 * priv->wstats.discard.retries = priv->stats.tx_errors; */
>  
> -	memset(&log, 0, sizeof(log));
> -	log.hdr.size = cpu_to_le16(sizeof(log));
> -	lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log);
> -
> -	tx_retries = get_unaligned_le32(&log.retry);
> +	tx_retries = priv->wstats.discard.retries;
>  
>  	if (tx_retries > 75)
>  		tx_qual = (90 - tx_retries) * POOR / 15;
> @@ -847,16 +843,12 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
>  		tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
>  	else if (tx_retries > 50)
>  		tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
> -		    15 + GOOD;
> +			15 + GOOD;
>  	else
>  		tx_qual = (50 - tx_retries) *
> -		    (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
> +			(PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
>  	quality = min(quality, tx_qual);
>  
> -	priv->wstats.discard.code = get_unaligned_le32(&log.wepundecryptable);
> -	priv->wstats.discard.retries = tx_retries;
> -	priv->wstats.discard.misc = get_unaligned_le32(&log.ackfailure);
> -
>  	/* Calculate quality */
>  	priv->wstats.qual.qual = min_t(u8, quality, 100);
>  	priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
> @@ -865,6 +857,9 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
>  	/* update stats asynchronously for future calls */
>  	lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0,
>  					0, 0, NULL);
> +
> +	lbs_prepare_and_send_command(priv, CMD_802_11_GET_LOG, 0,
> +				     0, 0, NULL);
>  out:
>  	if (!stats_valid) {
>  		priv->wstats.miss.beacon = 0;
> 

-- 
John W. Linville		Linux should be at the core
linville at tuxdriver.com			of your literate lifestyle.


From dcbw at redhat.com  Mon Jan 12 10:19:22 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 12 Jan 2009 10:19:22 -0500
Subject: Bug? 2.6.29-rc1 on cat /proc/net/wireless
In-Reply-To: <496A4D91.1090605@cam.ac.uk>
References: <496A4D91.1090605@cam.ac.uk>
Message-ID: <1231773562.23907.9.camel@localhost.localdomain>

On Sun, 2009-01-11 at 19:50 +0000, Jonathan Cameron wrote:
> Sorry all if this has already been fixed, but with 2.6.29-rc1 +
> Colin McCabe's alignment fix of the other day (can't see the
> relevance but that's what I'm running) just got the following
> with an sdio connected 8686. I'll try tracking this one down
> tomorrow if I don't hear anything.

It looks like the 'proc' handling has changed recently, which causes
'cat /proc/net/wireless' to exhibit this bug because Libertas may sleep
while asking the hardware for the dropped packet and retry statistics
(CMD_802_11_GET_LOG) in get_wireless_stats().  Apparently sleeping in
get_wireless_stats() was never really allowed (it just didn't complain),
so we'll have to use cached stats, or just not return discard/retry
stats at all (like mac80211).

Dan

> cat /proc/net/wireless
> BUG: scheduling while atomic: cat/1272/0x00000002
> Modules linked in: max1363 ring_sw iio_trig_periodic_rtc industrialio rtc_pxa27x rtc_core libertas_sdio libertas lib80211 pxamci mmc_core
> [<c00227c8>] (dump_stack+0x0/0x14) from [<c00318f4>] (__schedule_bug+0x4c/0x58)
> [<c00318a8>] (__schedule_bug+0x0/0x58) from [<c020c61c>] (__sched_text_start+0x64/0x308)
>  r4:c1116000
> [<c020c5b8>] (__sched_text_start+0x0/0x308) from [<bf025b3c>] (__lbs_cmd+0xd8/0x154 [libertas])
> [<bf025a64>] (__lbs_cmd+0x0/0x154 [libertas]) from [<bf021eec>] (lbs_get_wireless_stats+0xec/0x26c [libertas])
> [<bf021e00>] (lbs_get_wireless_stats+0x0/0x26c [libertas]) from [<c020a0b4>] (get_wireless_stats+0x30/0x3c)
> [<c020a084>] (get_wireless_stats+0x0/0x3c) from [<c020a24c>] (wireless_seq_show+0x38/0x110)
> [<c020a214>] (wireless_seq_show+0x0/0x110) from [<c00a668c>] (seq_read+0x2ac/0x404)
>  r5:c1117ee8 r4:c1194000
> [<c00a63e0>] (seq_read+0x0/0x404) from [<c00c6ec4>] (proc_reg_read+0xac/0xc0)
> [<c00c6e18>] (proc_reg_read+0x0/0xc0) from [<c008d2f0>] (vfs_read+0xc8/0x14c)
> [<c008d228>] (vfs_read+0x0/0x14c) from [<c008d620>] (sys_read+0x4c/0x74)
>  r7:00000000 r6:c1117f78 r5:c1387c80 r4:c1387ca0
> [<c008d5d4>] (sys_read+0x0/0x74) from [<c001ef00>] (ret_fast_syscall+0x0/0x2c)
>  r8:c001f0a4 r7:00000003 r6:00000003 r5:bea33c64 r4:00001000
> Inter-| sta-|   Quality        |   Discarded packets               | Missed | WE
>  face | tus | link level noise |  nwid  crypt   frag  retry   misc | beacon | 22
>   eth0: 0002   95.  -36.  -81.       0    363      0   1179 236246        0
> 
> 
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From andrey at cozybit.com  Mon Jan 12 14:04:18 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Mon, 12 Jan 2009 11:04:18 -0800
Subject: [PATCH v3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <1231772017.23907.3.camel@localhost.localdomain>
References: <1231541889-7999-1-git-send-email-colin@cozybit.com>
	<1231772017.23907.3.camel@localhost.localdomain>
Message-ID: <45e8e6c40901121104r1f55894dy35d7528e8174f036@mail.gmail.com>

Hi Dan, Johannes was correct -- the explicit get_unaligned_ was not
needed and using packed was required.  Unfortunately our patch got
merged before we had a chance to send a version including just the
packing, so I'm preparing a patch that reverts the calls to
get_unaligned_* ...this is, however, independent of the actual
if_spi.c driver patch.

On Mon, Jan 12, 2009 at 6:53 AM, Dan Williams <dcbw at redhat.com> wrote:
> On Fri, 2009-01-09 at 14:58 -0800, Colin McCabe wrote:
>> Add initial support for libertas devices using a GSPI interface.  This has
>> been tested with the 8686.
>>
>> GSPI is intended to be used on embedded systems. Board-specific parameters are
>> required (see libertas_spi.h).
>
> Were you able to take a look at the alignment patches and see if just
> using 'packed' worked, rather than having everything use
> get_unaligned_*?
>
> Dan
>
>
>


From dcbw at redhat.com  Mon Jan 12 14:36:58 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 12 Jan 2009 14:36:58 -0500
Subject: [PATCH v3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <1231541889-7999-1-git-send-email-colin@cozybit.com>
References: <1231541889-7999-1-git-send-email-colin@cozybit.com>
Message-ID: <1231789019.28887.8.camel@localhost.localdomain>

On Fri, 2009-01-09 at 14:58 -0800, Colin McCabe wrote:
> Add initial support for libertas devices using a GSPI interface.  This has
> been tested with the 8686.
> 
> GSPI is intended to be used on embedded systems. Board-specific parameters are
> required (see libertas_spi.h).
> 
> Thanks to everyone who took a look at the earlier versions of the patch.

Thanks!  Looks good.

Acked-by: Dan Williams <dcbw at redhat.com>

> Changes in v3:
> * Get rid of out-of-date TODO comment about if_spi_e2h
> * Look for firmware images in libertas/gspi8XXX_hlp.bin and 
> libertas/gspi8XXX.bin 
> * Fix spi_read / spi_write error handling in spu_read / spu_write
> * Consolidate multiple spi_read / spi_write operations into one to
> improve performance
> * Add dependency on GENERIC_GPIO
> 
> Changes in v2:
> * Store the host IRQ setting in spi->irq rather than creating a new variable
> for this purpose.
> * Add TODO comment to declaration of card->gpio_cs.
> (We do intend to get rid of gpio_cs eventually, but it will require some
> changes to the generic SPI layer, which could take a while.)
> * When loading the module, check to see if the firmware is already loaded. If
> so, skip firmware load.
> * Speed up module load time slightly.
> * Add if_spi_e2h to handle libertas card events.
> * Include relevant Kconfig change.
> 
> Cheers.
> Colin
> Signed-off-by: Colin McCabe <colin at cozybit.com>
> Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
> ---
>  drivers/net/wireless/Kconfig           |    6 +
>  drivers/net/wireless/libertas/Makefile |    2 +
>  drivers/net/wireless/libertas/defs.h   |    2 +
>  drivers/net/wireless/libertas/if_spi.c | 1204 ++++++++++++++++++++++++++++++++
>  drivers/net/wireless/libertas/if_spi.h |  208 ++++++
>  include/linux/spi/libertas_spi.h       |   25 +
>  6 files changed, 1447 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/net/wireless/libertas/if_spi.c
>  create mode 100644 drivers/net/wireless/libertas/if_spi.h
>  create mode 100644 include/linux/spi/libertas_spi.h
> 
> diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
> index ea543fc..6f9ee26 100644
> --- a/drivers/net/wireless/Kconfig
> +++ b/drivers/net/wireless/Kconfig
> @@ -151,6 +151,12 @@ config LIBERTAS_SDIO
>  	---help---
>  	  A driver for Marvell Libertas 8385 and 8686 SDIO devices.
>  
> +config LIBERTAS_SPI
> +	tristate "Marvell Libertas 8686 SPI 802.11b/g cards"
> +	depends on LIBERTAS && SPI && GENERIC_GPIO
> +	---help---
> +	  A driver for Marvell Libertas 8686 SPI devices.
> +
>  config LIBERTAS_DEBUG
>  	bool "Enable full debugging output in the Libertas module."
>  	depends on LIBERTAS
> diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
> index 02080a3..0b69185 100644
> --- a/drivers/net/wireless/libertas/Makefile
> +++ b/drivers/net/wireless/libertas/Makefile
> @@ -4,8 +4,10 @@ libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o	\
>  usb8xxx-objs += if_usb.o
>  libertas_cs-objs += if_cs.o
>  libertas_sdio-objs += if_sdio.o
> +libertas_spi-objs += if_spi.o
>  
>  obj-$(CONFIG_LIBERTAS)     += libertas.o
>  obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
>  obj-$(CONFIG_LIBERTAS_CS)  += libertas_cs.o
>  obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o
> +obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o
> diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
> index b7744d6..0d1494f 100644
> --- a/drivers/net/wireless/libertas/defs.h
> +++ b/drivers/net/wireless/libertas/defs.h
> @@ -41,6 +41,7 @@
>  #define LBS_DEB_HEX	0x00200000
>  #define LBS_DEB_SDIO	0x00400000
>  #define LBS_DEB_SYSFS	0x00800000
> +#define LBS_DEB_SPI	0x01000000
>  
>  extern unsigned int lbs_debug;
>  
> @@ -84,6 +85,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \
>  #define lbs_deb_thread(fmt, args...)    LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
>  #define lbs_deb_sdio(fmt, args...)      LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
>  #define lbs_deb_sysfs(fmt, args...)     LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args)
> +#define lbs_deb_spi(fmt, args...)       LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args)
>  
>  #define lbs_pr_info(format, args...) \
>  	printk(KERN_INFO DRV_NAME": " format, ## args)
> diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
> new file mode 100644
> index 0000000..86b984e
> --- /dev/null
> +++ b/drivers/net/wireless/libertas/if_spi.c
> @@ -0,0 +1,1204 @@
> +/*
> + *	linux/drivers/net/wireless/libertas/if_spi.c
> + *
> + *	Driver for Marvell SPI WLAN cards.
> + *
> + *	Copyright 2008 Analog Devices Inc.
> + *
> + *	Authors:
> + *	Andrey Yurovsky <andrey at cozybit.com>
> + *	Colin McCabe <colin at cozybit.com>
> + *
> + *	Inspired by if_sdio.c, Copyright 2007-2008 Pierre Ossman
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +
> +#include <linux/moduleparam.h>
> +#include <linux/firmware.h>
> +#include <linux/gpio.h>
> +#include <linux/jiffies.h>
> +#include <linux/kthread.h>
> +#include <linux/list.h>
> +#include <linux/netdevice.h>
> +#include <linux/spi/libertas_spi.h>
> +#include <linux/spi/spi.h>
> +
> +#include "host.h"
> +#include "decl.h"
> +#include "defs.h"
> +#include "dev.h"
> +#include "if_spi.h"
> +
> +struct if_spi_packet {
> +	struct list_head		list;
> +	u16				blen;
> +	u8				buffer[0] __attribute__((aligned(4)));
> +};
> +
> +struct if_spi_card {
> +	struct spi_device		*spi;
> +	struct lbs_private		*priv;
> +
> +	char				helper_fw_name[FIRMWARE_NAME_MAX];
> +	char				main_fw_name[FIRMWARE_NAME_MAX];
> +
> +	/* The card ID and card revision, as reported by the hardware. */
> +	u16				card_id;
> +	u8				card_rev;
> +
> +	/* Pin number for our GPIO chip-select. */
> +	/* TODO: Once the generic SPI layer has some additional features, we
> +	 * should take this out and use the normal chip select here.
> +	 * We need support for chip select delays, and not dropping chipselect
> +	 * after each word. */
> +	int				gpio_cs;
> +
> +	/* The last time that we initiated an SPU operation */
> +	unsigned long			prev_xfer_time;
> +
> +	int				use_dummy_writes;
> +	unsigned long			spu_port_delay;
> +	unsigned long			spu_reg_delay;
> +
> +	/* Handles all SPI communication (except for FW load) */
> +	struct task_struct		*spi_thread;
> +	int				run_thread;
> +
> +	/* Used to wake up the spi_thread */
> +	struct semaphore		spi_ready;
> +	struct semaphore		spi_thread_terminated;
> +
> +	u8				cmd_buffer[IF_SPI_CMD_BUF_SIZE];
> +
> +	/* A buffer of incoming packets from libertas core.
> +	 * Since we can't sleep in hw_host_to_card, we have to buffer
> +	 * them. */
> +	struct list_head		cmd_packet_list;
> +	struct list_head		data_packet_list;
> +
> +	/* Protects cmd_packet_list and data_packet_list */
> +	spinlock_t			buffer_lock;
> +};
> +
> +static void free_if_spi_card(struct if_spi_card *card)
> +{
> +	struct list_head *cursor, *next;
> +	struct if_spi_packet *packet;
> +
> +	BUG_ON(card->run_thread);
> +	list_for_each_safe(cursor, next, &card->cmd_packet_list) {
> +		packet = container_of(cursor, struct if_spi_packet, list);
> +		list_del(&packet->list);
> +		kfree(packet);
> +	}
> +	list_for_each_safe(cursor, next, &card->data_packet_list) {
> +		packet = container_of(cursor, struct if_spi_packet, list);
> +		list_del(&packet->list);
> +		kfree(packet);
> +	}
> +	spi_set_drvdata(card->spi, NULL);
> +	kfree(card);
> +}
> +
> +static struct chip_ident chip_id_to_device_name[] = {
> +	{ .chip_id = 0x04, .name = 8385 },
> +	{ .chip_id = 0x0b, .name = 8686 },
> +};
> +
> +/*
> + * SPI Interface Unit Routines
> + *
> + * The SPU sits between the host and the WLAN module.
> + * All communication with the firmware is through SPU transactions.
> + *
> + * First we have to put a SPU register name on the bus. Then we can
> + * either read from or write to that register.
> + *
> + * For 16-bit transactions, byte order on the bus is big-endian.
> + * We don't have to worry about that here, though.
> + * The translation takes place in the SPI routines.
> + */
> +
> +static void spu_transaction_init(struct if_spi_card *card)
> +{
> +	if (!time_after(jiffies, card->prev_xfer_time + 1)) {
> +		/* Unfortunately, the SPU requires a delay between successive
> +		 * transactions. If our last transaction was more than a jiffy
> +		 * ago, we have obviously already delayed enough.
> +		 * If not, we have to busy-wait to be on the safe side. */
> +		ndelay(400);
> +	}
> +	gpio_set_value(card->gpio_cs, 0); /* assert CS */
> +}
> +
> +static void spu_transaction_finish(struct if_spi_card *card)
> +{
> +	gpio_set_value(card->gpio_cs, 1); /* drop CS */
> +	card->prev_xfer_time = jiffies;
> +}
> +
> +/* Write out a byte buffer to an SPI register,
> + * using a series of 16-bit transfers. */
> +static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
> +{
> +	int err = 0;
> +	u16 reg_out = reg | IF_SPI_WRITE_OPERATION_MASK;
> +
> +	/* You must give an even number of bytes to the SPU, even if it
> +	 * doesn't care about the last one.  */
> +	BUG_ON(len & 0x1);
> +
> +	spu_transaction_init(card);
> +
> +	/* write SPU register index */
> +	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
> +	if (err)
> +		goto out;
> +
> +	err = spi_write(card->spi, buf, len);
> +
> +out:
> +	spu_transaction_finish(card);
> +	return err;
> +}
> +
> +static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val)
> +{
> +	return spu_write(card, reg, (u8 *)&val, sizeof(u16));
> +}
> +
> +static inline int spu_write_u32(struct if_spi_card *card, u16 reg, u32 val)
> +{
> +	/* The lower 16 bits are written first. */
> +	u16 out[2];
> +	out[0] = val & 0xffff;
> +	out[1] = (val & 0xffff0000) >> 16;
> +	return spu_write(card, reg, (u8 *)&out, sizeof(u32));
> +}
> +
> +static inline int spu_reg_is_port_reg(u16 reg)
> +{
> +	switch (reg) {
> +	case IF_SPI_IO_RDWRPORT_REG:
> +	case IF_SPI_CMD_RDWRPORT_REG:
> +	case IF_SPI_DATA_RDWRPORT_REG:
> +		return 1;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
> +{
> +	unsigned int i, delay;
> +	int err = 0;
> +	u16 zero = 0;
> +	u16 reg_out = reg | IF_SPI_READ_OPERATION_MASK;
> +
> +	/* You must take an even number of bytes from the SPU, even if you
> +	 * don't care about the last one.  */
> +	BUG_ON(len & 0x1);
> +
> +	spu_transaction_init(card);
> +
> +	/* write SPU register index */
> +	err = spi_write(card->spi, (u8 *)&reg_out, sizeof(u16));
> +	if (err)
> +		goto out;
> +
> +	delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay :
> +						card->spu_reg_delay;
> +	if (card->use_dummy_writes) {
> +		/* Clock in dummy cycles while the SPU fills the FIFO */
> +		for (i = 0; i < delay / 16; ++i) {
> +			err = spi_write(card->spi, (u8 *)&zero, sizeof(u16));
> +			if (err)
> +				return err;
> +		}
> +	} else {
> +		/* Busy-wait while the SPU fills the FIFO */
> +		ndelay(100 + (delay * 10));
> +	}
> +
> +	/* read in data */
> +	err = spi_read(card->spi, buf, len);
> +
> +out:
> +	spu_transaction_finish(card);
> +	return err;
> +}
> +
> +/* Read 16 bits from an SPI register */
> +static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
> +{
> +	return spu_read(card, reg, (u8 *)val, sizeof(u16));
> +}
> +
> +/* Read 32 bits from an SPI register.
> + * The low 16 bits are read first. */
> +static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
> +{
> +	u16 buf[2];
> +	int err;
> +	err = spu_read(card, reg, (u8 *)buf, sizeof(u32));
> +	if (!err)
> +		*val = buf[0] | (buf[1] << 16);
> +	return err;
> +}
> +
> +/* Keep reading 16 bits from an SPI register until you get the correct result.
> + *
> + * If mask = 0, the correct result is any non-zero number.
> + * If mask != 0, the correct result is any number where
> + * number & target_mask == target
> + *
> + * Returns -ETIMEDOUT if a second passes without the correct result. */
> +static int spu_wait_for_u16(struct if_spi_card *card, u16 reg,
> +			u16 target_mask, u16 target)
> +{
> +	int err;
> +	unsigned long timeout = jiffies + 5*HZ;
> +	while (1) {
> +		u16 val;
> +		err = spu_read_u16(card, reg, &val);
> +		if (err)
> +			return err;
> +		if (target_mask) {
> +			if ((val & target_mask) == target)
> +				return 0;
> +		} else {
> +			if (val)
> +				return 0;
> +		}
> +		udelay(100);
> +		if (time_after(jiffies, timeout)) {
> +			lbs_pr_err("%s: timeout with val=%02x, "
> +			       "target_mask=%02x, target=%02x\n",
> +			       __func__, val, target_mask, target);
> +			return -ETIMEDOUT;
> +		}
> +	}
> +}
> +
> +/* Read 16 bits from an SPI register until you receive a specific value.
> + * Returns -ETIMEDOUT if a 4 tries pass without success. */
> +static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target)
> +{
> +	int err, try;
> +	for (try = 0; try < 4; ++try) {
> +		u32 val = 0;
> +		err = spu_read_u32(card, reg, &val);
> +		if (err)
> +			return err;
> +		if (val == target)
> +			return 0;
> +		mdelay(100);
> +	}
> +	return -ETIMEDOUT;
> +}
> +
> +static int spu_set_interrupt_mode(struct if_spi_card *card,
> +			   int suppress_host_int,
> +			   int auto_int)
> +{
> +	int err = 0;
> +
> +	/* We can suppress a host interrupt by clearing the appropriate
> +	 * bit in the "host interrupt status mask" register */
> +	if (suppress_host_int) {
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
> +		if (err)
> +			return err;
> +	} else {
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG,
> +			      IF_SPI_HISM_TX_DOWNLOAD_RDY |
> +			      IF_SPI_HISM_RX_UPLOAD_RDY |
> +			      IF_SPI_HISM_CMD_DOWNLOAD_RDY |
> +			      IF_SPI_HISM_CARDEVENT |
> +			      IF_SPI_HISM_CMD_UPLOAD_RDY);
> +		if (err)
> +			return err;
> +	}
> +
> +	/* If auto-interrupts are on, the completion of certain transactions
> +	 * will trigger an interrupt automatically. If auto-interrupts
> +	 * are off, we need to set the "Card Interrupt Cause" register to
> +	 * trigger a card interrupt. */
> +	if (auto_int) {
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG,
> +				IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO |
> +				IF_SPI_HICT_RX_UPLOAD_OVER_AUTO |
> +				IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO |
> +				IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO);
> +		if (err)
> +			return err;
> +	} else {
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0);
> +		if (err)
> +			return err;
> +	}
> +	return err;
> +}
> +
> +static int spu_get_chip_revision(struct if_spi_card *card,
> +				  u16 *card_id, u8 *card_rev)
> +{
> +	int err = 0;
> +	u32 dev_ctrl;
> +	err = spu_read_u32(card, IF_SPI_DEVICEID_CTRL_REG, &dev_ctrl);
> +	if (err)
> +		return err;
> +	*card_id = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dev_ctrl);
> +	*card_rev = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dev_ctrl);
> +	return err;
> +}
> +
> +static int spu_set_bus_mode(struct if_spi_card *card, u16 mode)
> +{
> +	int err = 0;
> +	u16 rval;
> +	/* set bus mode */
> +	err = spu_write_u16(card, IF_SPI_SPU_BUS_MODE_REG, mode);
> +	if (err)
> +		return err;
> +	/* Check that we were able to read back what we just wrote. */
> +	err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval);
> +	if (err)
> +		return err;
> +	if (rval != mode) {
> +		lbs_pr_err("Can't read bus mode register.\n");
> +		return -EIO;
> +	}
> +	return 0;
> +}
> +
> +static int spu_init(struct if_spi_card *card, int use_dummy_writes)
> +{
> +	int err = 0;
> +	u32 delay;
> +
> +	/* We have to start up in timed delay mode so that we can safely
> +	 * read the Delay Read Register. */
> +	card->use_dummy_writes = 0;
> +	err = spu_set_bus_mode(card,
> +				IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
> +				IF_SPI_BUS_MODE_DELAY_METHOD_TIMED |
> +				IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
> +	if (err)
> +		return err;
> +	card->spu_port_delay = 1000;
> +	card->spu_reg_delay = 1000;
> +	err = spu_read_u32(card, IF_SPI_DELAY_READ_REG, &delay);
> +	if (err)
> +		return err;
> +	card->spu_port_delay = delay & 0x0000ffff;
> +	card->spu_reg_delay = (delay & 0xffff0000) >> 16;
> +
> +	/* If dummy clock delay mode has been requested, switch to it now */
> +	if (use_dummy_writes) {
> +		card->use_dummy_writes = 1;
> +		err = spu_set_bus_mode(card,
> +				IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING |
> +				IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK |
> +				IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA);
> +		if (err)
> +			return err;
> +	}
> +
> +	lbs_deb_spi("Initialized SPU unit. "
> +		    "spu_port_delay=0x%04lx, spu_reg_delay=0x%04lx\n",
> +		    card->spu_port_delay, card->spu_reg_delay);
> +	return err;
> +}
> +
> +/*
> + * Firmware Loading
> + */
> +
> +static int if_spi_prog_helper_firmware(struct if_spi_card *card)
> +{
> +	int err = 0;
> +	const struct firmware *firmware = NULL;
> +	int bytes_remaining;
> +	const u8 *fw;
> +	u8 temp[HELPER_FW_LOAD_CHUNK_SZ];
> +	struct spi_device *spi = card->spi;
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	err = spu_set_interrupt_mode(card, 1, 0);
> +	if (err)
> +		goto out;
> +	/* Get helper firmware image */
> +	err = request_firmware(&firmware, card->helper_fw_name, &spi->dev);
> +	if (err) {
> +		lbs_pr_err("request_firmware failed with err = %d\n", err);
> +		goto out;
> +	}
> +	bytes_remaining = firmware->size;
> +	fw = firmware->data;
> +
> +	/* Load helper firmware image */
> +	while (bytes_remaining > 0) {
> +		/* Scratch pad 1 should contain the number of bytes we
> +		 * want to download to the firmware */
> +		err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG,
> +					HELPER_FW_LOAD_CHUNK_SZ);
> +		if (err)
> +			goto release_firmware;
> +
> +		err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
> +					IF_SPI_HIST_CMD_DOWNLOAD_RDY,
> +					IF_SPI_HIST_CMD_DOWNLOAD_RDY);
> +		if (err)
> +			goto release_firmware;
> +
> +		/* Feed the data into the command read/write port reg
> +		 * in chunks of 64 bytes */
> +		memset(temp, 0, sizeof(temp));
> +		memcpy(temp, fw,
> +		       min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ));
> +		mdelay(10);
> +		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
> +					temp, HELPER_FW_LOAD_CHUNK_SZ);
> +		if (err)
> +			goto release_firmware;
> +
> +		/* Interrupt the boot code */
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
> +		if (err)
> +			goto release_firmware;
> +		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
> +				       IF_SPI_CIC_CMD_DOWNLOAD_OVER);
> +		if (err)
> +			goto release_firmware;
> +		bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ;
> +		fw += HELPER_FW_LOAD_CHUNK_SZ;
> +	}
> +
> +	/* Once the helper / single stage firmware download is complete,
> +	 * write 0 to scratch pad 1 and interrupt the
> +	 * bootloader. This completes the helper download. */
> +	err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK);
> +	if (err)
> +		goto release_firmware;
> +	err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
> +	if (err)
> +		goto release_firmware;
> +	err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
> +				IF_SPI_CIC_CMD_DOWNLOAD_OVER);
> +		goto release_firmware;
> +
> +	lbs_deb_spi("waiting for helper to boot...\n");
> +
> +release_firmware:
> +	release_firmware(firmware);
> +out:
> +	if (err)
> +		lbs_pr_err("failed to load helper firmware (err=%d)\n", err);
> +	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
> +	return err;
> +}
> +
> +/* Returns the length of the next packet the firmware expects us to send
> + * Sets crc_err if the previous transfer had a CRC error. */
> +static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card,
> +						int *crc_err)
> +{
> +	u16 len;
> +	int err = 0;
> +
> +	/* wait until the host interrupt status register indicates
> +	 * that we are ready to download */
> +	err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG,
> +				IF_SPI_HIST_CMD_DOWNLOAD_RDY,
> +				IF_SPI_HIST_CMD_DOWNLOAD_RDY);
> +	if (err) {
> +		lbs_pr_err("timed out waiting for host_int_status\n");
> +		return err;
> +	}
> +
> +	/* Ask the device how many bytes of firmware it wants. */
> +	err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
> +	if (err)
> +		return err;
> +
> +	if (len > IF_SPI_CMD_BUF_SIZE) {
> +		lbs_pr_err("firmware load device requested a larger "
> +			   "tranfer than we are prepared to "
> +			   "handle. (len = %d)\n", len);
> +		return -EIO;
> +	}
> +	if (len & 0x1) {
> +		lbs_deb_spi("%s: crc error\n", __func__);
> +		len &= ~0x1;
> +		*crc_err = 1;
> +	} else
> +		*crc_err = 0;
> +
> +	return len;
> +}
> +
> +static int if_spi_prog_main_firmware(struct if_spi_card *card)
> +{
> +	int len, prev_len;
> +	int bytes, crc_err = 0, err = 0;
> +	const struct firmware *firmware = NULL;
> +	const u8 *fw;
> +	struct spi_device *spi = card->spi;
> +	u16 num_crc_errs;
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	err = spu_set_interrupt_mode(card, 1, 0);
> +	if (err)
> +		goto out;
> +
> +	/* Get firmware image */
> +	err = request_firmware(&firmware, card->main_fw_name, &spi->dev);
> +	if (err) {
> +		lbs_pr_err("%s: can't get firmware '%s' from kernel. "
> +			"err = %d\n", __func__, card->main_fw_name, err);
> +		goto out;
> +	}
> +
> +	err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0);
> +	if (err) {
> +		lbs_pr_err("%s: timed out waiting for initial "
> +			   "scratch reg = 0\n", __func__);
> +		goto release_firmware;
> +	}
> +
> +	num_crc_errs = 0;
> +	prev_len = 0;
> +	bytes = firmware->size;
> +	fw = firmware->data;
> +	while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) {
> +		if (len < 0) {
> +			err = len;
> +			goto release_firmware;
> +		}
> +		if (bytes < 0) {
> +			/* If there are no more bytes left, we would normally
> +			 * expect to have terminated with len = 0 */
> +			lbs_pr_err("Firmware load wants more bytes "
> +				   "than we have to offer.\n");
> +			break;
> +		}
> +		if (crc_err) {
> +			/* Previous transfer failed. */
> +			if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) {
> +				lbs_pr_err("Too many CRC errors encountered "
> +					   "in firmware load.\n");
> +				err = -EIO;
> +				goto release_firmware;
> +			}
> +		} else {
> +			/* Previous transfer succeeded. Advance counters. */
> +			bytes -= prev_len;
> +			fw += prev_len;
> +		}
> +		if (bytes < len) {
> +			memset(card->cmd_buffer, 0, len);
> +			memcpy(card->cmd_buffer, fw, bytes);
> +		} else
> +			memcpy(card->cmd_buffer, fw, len);
> +
> +		err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0);
> +		if (err)
> +			goto release_firmware;
> +		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG,
> +				card->cmd_buffer, len);
> +		if (err)
> +			goto release_firmware;
> +		err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG ,
> +					IF_SPI_CIC_CMD_DOWNLOAD_OVER);
> +		if (err)
> +			goto release_firmware;
> +		prev_len = len;
> +	}
> +	if (bytes > prev_len) {
> +		lbs_pr_err("firmware load wants fewer bytes than "
> +			   "we have to offer.\n");
> +	}
> +
> +	/* Confirm firmware download */
> +	err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG,
> +					SUCCESSFUL_FW_DOWNLOAD_MAGIC);
> +	if (err) {
> +		lbs_pr_err("failed to confirm the firmware download\n");
> +		goto release_firmware;
> +	}
> +
> +release_firmware:
> +	release_firmware(firmware);
> +
> +out:
> +	if (err)
> +		lbs_pr_err("failed to load firmware (err=%d)\n", err);
> +	lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err);
> +	return err;
> +}
> +
> +/*
> + * SPI Transfer Thread
> + *
> + * The SPI thread handles all SPI transfers, so there is no need for a lock.
> + */
> +
> +/* Move a command from the card to the host */
> +static int if_spi_c2h_cmd(struct if_spi_card *card)
> +{
> +	struct lbs_private *priv = card->priv;
> +	unsigned long flags;
> +	int err = 0;
> +	u16 len;
> +	u8 i;
> +
> +	/* We need a buffer big enough to handle whatever people send to
> +	 * hw_host_to_card */
> +	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE);
> +	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE);
> +
> +	/* It's just annoying if the buffer size isn't a multiple of 4, because
> +	 * then we might have len <  IF_SPI_CMD_BUF_SIZE but
> +	 * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */
> +	BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0);
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	/* How many bytes are there to read? */
> +	err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len);
> +	if (err)
> +		goto out;
> +	if (!len) {
> +		lbs_pr_err("%s: error: card has no data for host\n",
> +			   __func__);
> +		err = -EINVAL;
> +		goto out;
> +	} else if (len > IF_SPI_CMD_BUF_SIZE) {
> +		lbs_pr_err("%s: error: response packet too large: "
> +			   "%d bytes, but maximum is %d\n",
> +			   __func__, len, IF_SPI_CMD_BUF_SIZE);
> +		err = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* Read the data from the WLAN module into our command buffer */
> +	err = spu_read(card, IF_SPI_CMD_RDWRPORT_REG,
> +				card->cmd_buffer, ALIGN(len, 4));
> +	if (err)
> +		goto out;
> +
> +	spin_lock_irqsave(&priv->driver_lock, flags);
> +	i = (priv->resp_idx == 0) ? 1 : 0;
> +	BUG_ON(priv->resp_len[i]);
> +	priv->resp_len[i] = len;
> +	memcpy(priv->resp_buf[i], card->cmd_buffer, len);
> +	lbs_notify_command_response(priv, i);
> +	spin_unlock_irqrestore(&priv->driver_lock, flags);
> +
> +out:
> +	if (err)
> +		lbs_pr_err("%s: err=%d\n", __func__, err);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +	return err;
> +}
> +
> +/* Move data from the card to the host */
> +static int if_spi_c2h_data(struct if_spi_card *card)
> +{
> +	struct sk_buff *skb;
> +	char *data;
> +	u16 len;
> +	int err = 0;
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	/* How many bytes are there to read? */
> +	err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len);
> +	if (err)
> +		goto out;
> +	if (!len) {
> +		lbs_pr_err("%s: error: card has no data for host\n",
> +			   __func__);
> +		err = -EINVAL;
> +		goto out;
> +	} else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) {
> +		lbs_pr_err("%s: error: card has %d bytes of data, but "
> +			   "our maximum skb size is %u\n",
> +			   __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
> +		err = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* TODO: should we allocate a smaller skb if we have less data? */
> +	skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE);
> +	if (!skb) {
> +		err = -ENOBUFS;
> +		goto out;
> +	}
> +	skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
> +	data = skb_put(skb, len);
> +
> +	/* Read the data from the WLAN module into our skb... */
> +	err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4));
> +	if (err)
> +		goto free_skb;
> +
> +	/* pass the SKB to libertas */
> +	err = lbs_process_rxed_packet(card->priv, skb);
> +	if (err)
> +		goto free_skb;
> +
> +	/* success */
> +	goto out;
> +
> +free_skb:
> +	dev_kfree_skb(skb);
> +out:
> +	if (err)
> +		lbs_pr_err("%s: err=%d\n", __func__, err);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +	return err;
> +}
> +
> +/* Move data or a command from the host to the card. */
> +static void if_spi_h2c(struct if_spi_card *card,
> +			struct if_spi_packet *packet, int type)
> +{
> +	int err = 0;
> +	u16 int_type, port_reg;
> +
> +	switch (type) {
> +	case MVMS_DAT:
> +		int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
> +		port_reg = IF_SPI_DATA_RDWRPORT_REG;
> +		break;
> +	case MVMS_CMD:
> +		int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
> +		port_reg = IF_SPI_CMD_RDWRPORT_REG;
> +		break;
> +	default:
> +		lbs_pr_err("can't transfer buffer of type %d\n", type);
> +		err = -EINVAL;
> +		goto out;
> +	}
> +
> +	/* Write the data to the card */
> +	err = spu_write(card, port_reg, packet->buffer, packet->blen);
> +	if (err)
> +		goto out;
> +
> +out:
> +	kfree(packet);
> +
> +	if (err)
> +		lbs_pr_err("%s: error %d\n", __func__, err);
> +}
> +
> +/* Inform the host about a card event */
> +static void if_spi_e2h(struct if_spi_card *card)
> +{
> +	int err = 0;
> +	unsigned long flags;
> +	u32 cause;
> +	struct lbs_private *priv = card->priv;
> +
> +	err = spu_read_u32(card, IF_SPI_SCRATCH_3_REG, &cause);
> +	if (err)
> +		goto out;
> +
> +	spin_lock_irqsave(&priv->driver_lock, flags);
> +	lbs_queue_event(priv, cause & 0xff);
> +	spin_unlock_irqrestore(&priv->driver_lock, flags);
> +
> +out:
> +	if (err)
> +		lbs_pr_err("%s: error %d\n", __func__, err);
> +}
> +
> +static int lbs_spi_thread(void *data)
> +{
> +	int err;
> +	struct if_spi_card *card = data;
> +	u16 hiStatus;
> +	unsigned long flags;
> +	struct if_spi_packet *packet;
> +
> +	while (1) {
> +		/* Wait to be woken up by one of two things.  First, our ISR
> +		 * could tell us that something happened on the WLAN.
> +		 * Secondly, libertas could call hw_host_to_card with more
> +		 * data, which we might be able to send.
> +		 */
> +		do {
> +			err = down_interruptible(&card->spi_ready);
> +			if (!card->run_thread) {
> +				up(&card->spi_thread_terminated);
> +				do_exit(0);
> +			}
> +		} while (err == EINTR);
> +
> +		/* Read the host interrupt status register to see what we
> +		 * can do. */
> +		err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
> +					&hiStatus);
> +		if (err) {
> +			lbs_pr_err("I/O error\n");
> +			goto err;
> +		}
> +
> +		if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY)
> +			err = if_spi_c2h_cmd(card);
> +			if (err)
> +				goto err;
> +		if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY)
> +			err = if_spi_c2h_data(card);
> +			if (err)
> +				goto err;
> +		if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY) {
> +			/* This means two things. First of all,
> +			 * if there was a previous command sent, the card has
> +			 * successfully received it.
> +			 * Secondly, it is now ready to download another
> +			 * command.
> +			 */
> +			lbs_host_to_card_done(card->priv);
> +
> +			/* Do we have any command packets from the host to
> +			 * send? */
> +			packet = NULL;
> +			spin_lock_irqsave(&card->buffer_lock, flags);
> +			if (!list_empty(&card->cmd_packet_list)) {
> +				packet = (struct if_spi_packet *)(card->
> +						cmd_packet_list.next);
> +				list_del(&packet->list);
> +			}
> +			spin_unlock_irqrestore(&card->buffer_lock, flags);
> +
> +			if (packet)
> +				if_spi_h2c(card, packet, MVMS_CMD);
> +		}
> +		if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
> +			/* Do we have any data packets from the host to
> +			 * send? */
> +			packet = NULL;
> +			spin_lock_irqsave(&card->buffer_lock, flags);
> +			if (!list_empty(&card->data_packet_list)) {
> +				packet = (struct if_spi_packet *)(card->
> +						data_packet_list.next);
> +				list_del(&packet->list);
> +			}
> +			spin_unlock_irqrestore(&card->buffer_lock, flags);
> +
> +			if (packet)
> +				if_spi_h2c(card, packet, MVMS_DAT);
> +		}
> +		if (hiStatus & IF_SPI_HIST_CARD_EVENT)
> +			if_spi_e2h(card);
> +
> +err:
> +		if (err)
> +			lbs_pr_err("%s: got error %d\n", __func__, err);
> +	}
> +}
> +
> +/* Block until lbs_spi_thread thread has terminated */
> +static void if_spi_terminate_spi_thread(struct if_spi_card *card)
> +{
> +	/* It would be nice to use kthread_stop here, but that function
> +	 * can't wake threads waiting for a semaphore. */
> +	card->run_thread = 0;
> +	up(&card->spi_ready);
> +	down(&card->spi_thread_terminated);
> +}
> +
> +/*
> + * Host to Card
> + *
> + * Called from Libertas to transfer some data to the WLAN device
> + * We can't sleep here. */
> +static int if_spi_host_to_card(struct lbs_private *priv,
> +				u8 type, u8 *buf, u16 nb)
> +{
> +	int err = 0;
> +	unsigned long flags;
> +	struct if_spi_card *card = priv->card;
> +	struct if_spi_packet *packet;
> +	u16 blen;
> +
> +	lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
> +
> +	if (nb == 0) {
> +		lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
> +		err = -EINVAL;
> +		goto out;
> +	}
> +	blen = ALIGN(nb, 4);
> +	packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
> +	if (!packet) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +	packet->blen = blen;
> +	memcpy(packet->buffer, buf, nb);
> +	memset(packet->buffer + nb, 0, blen - nb);
> +
> +	switch (type) {
> +	case MVMS_CMD:
> +		priv->dnld_sent = DNLD_CMD_SENT;
> +		spin_lock_irqsave(&card->buffer_lock, flags);
> +		list_add_tail(&packet->list, &card->cmd_packet_list);
> +		spin_unlock_irqrestore(&card->buffer_lock, flags);
> +		break;
> +	case MVMS_DAT:
> +		priv->dnld_sent = DNLD_DATA_SENT;
> +		spin_lock_irqsave(&card->buffer_lock, flags);
> +		list_add_tail(&packet->list, &card->data_packet_list);
> +		spin_unlock_irqrestore(&card->buffer_lock, flags);
> +		break;
> +	default:
> +		lbs_pr_err("can't transfer buffer of type %d", type);
> +		err = -EINVAL;
> +		break;
> +	}
> +
> +	/* Wake up the spi thread */
> +	up(&card->spi_ready);
> +out:
> +	lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
> +	return err;
> +}
> +
> +/*
> + * Host Interrupts
> + *
> + * Service incoming interrupts from the WLAN device. We can't sleep here, so
> + * don't try to talk on the SPI bus, just wake up the SPI thread.
> + */
> +static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
> +{
> +	struct if_spi_card *card = dev_id;
> +
> +	up(&card->spi_ready);
> +	return IRQ_HANDLED;
> +}
> +
> +/*
> + * SPI callbacks
> + */
> +
> +static int if_spi_calculate_fw_names(u16 card_id,
> +			      char *helper_fw, char *main_fw)
> +{
> +	int i;
> +	for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) {
> +		if (card_id == chip_id_to_device_name[i].chip_id)
> +			break;
> +	}
> +	if (i == ARRAY_SIZE(chip_id_to_device_name)) {
> +		lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id);
> +		return -EAFNOSUPPORT;
> +	}
> +	snprintf(helper_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d_hlp.bin",
> +		 chip_id_to_device_name[i].name);
> +	snprintf(main_fw, FIRMWARE_NAME_MAX, "libertas/gspi%d.bin",
> +		 chip_id_to_device_name[i].name);
> +	return 0;
> +}
> +
> +static int __devinit if_spi_probe(struct spi_device *spi)
> +{
> +	struct if_spi_card *card;
> +	struct lbs_private *priv = NULL;
> +	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
> +	int err = 0;
> +	u32 scratch;
> +
> +	lbs_deb_enter(LBS_DEB_SPI);
> +
> +	/* Allocate card structure to represent this specific device */
> +	card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL);
> +	if (!card) {
> +		err = -ENOMEM;
> +		goto out;
> +	}
> +	spi_set_drvdata(spi, card);
> +	card->spi = spi;
> +	card->gpio_cs = pdata->gpio_cs;
> +	card->prev_xfer_time = jiffies;
> +
> +	sema_init(&card->spi_ready, 0);
> +	sema_init(&card->spi_thread_terminated, 0);
> +	INIT_LIST_HEAD(&card->cmd_packet_list);
> +	INIT_LIST_HEAD(&card->data_packet_list);
> +	spin_lock_init(&card->buffer_lock);
> +
> +	/* set up GPIO CS line. TODO: use  regular CS line */
> +	err = gpio_request(card->gpio_cs, "if_spi_gpio_chip_select");
> +	if (err)
> +		goto free_card;
> +	err = gpio_direction_output(card->gpio_cs, 1);
> +	if (err)
> +		goto free_gpio;
> +
> +	/* Initialize the SPI Interface Unit */
> +	err = spu_init(card, pdata->use_dummy_writes);
> +	if (err)
> +		goto free_gpio;
> +	err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
> +	if (err)
> +		goto free_gpio;
> +
> +	/* Firmware load */
> +	err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
> +	if (err)
> +		goto free_gpio;
> +	if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
> +		lbs_deb_spi("Firmware is already loaded for "
> +			    "Marvell WLAN 802.11 adapter\n");
> +	else {
> +		err = if_spi_calculate_fw_names(card->card_id,
> +				card->helper_fw_name, card->main_fw_name);
> +		if (err)
> +			goto free_gpio;
> +
> +		lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
> +				"(chip_id = 0x%04x, chip_rev = 0x%02x) "
> +				"attached to SPI bus_num %d, chip_select %d. "
> +				"spi->max_speed_hz=%d\n",
> +				card->card_id, card->card_rev,
> +				spi->master->bus_num, spi->chip_select,
> +				spi->max_speed_hz);
> +		err = if_spi_prog_helper_firmware(card);
> +		if (err)
> +			goto free_gpio;
> +		err = if_spi_prog_main_firmware(card);
> +		if (err)
> +			goto free_gpio;
> +		lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
> +	}
> +
> +	err = spu_set_interrupt_mode(card, 0, 1);
> +	if (err)
> +		goto free_gpio;
> +
> +	/* Register our card with libertas.
> +	 * This will call alloc_etherdev */
> +	priv = lbs_add_card(card, &spi->dev);
> +	if (!priv) {
> +		err = -ENOMEM;
> +		goto free_gpio;
> +	}
> +	card->priv = priv;
> +	priv->card = card;
> +	priv->hw_host_to_card = if_spi_host_to_card;
> +	priv->fw_ready = 1;
> +	priv->ps_supported = 1;
> +
> +	/* Initialize interrupt handling stuff. */
> +	card->run_thread = 1;
> +	card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread");
> +	if (IS_ERR(card->spi_thread)) {
> +		card->run_thread = 0;
> +		err = PTR_ERR(card->spi_thread);
> +		lbs_pr_err("error creating SPI thread: err=%d\n", err);
> +		goto remove_card;
> +	}
> +	err = request_irq(spi->irq, if_spi_host_interrupt,
> +			IRQF_TRIGGER_FALLING, "libertas_spi", card);
> +	if (err) {
> +		lbs_pr_err("can't get host irq line-- request_irq failed\n");
> +		goto terminate_thread;
> +	}
> +
> +	/* Start the card.
> +	 * This will call register_netdev, and we'll start
> +	 * getting interrupts... */
> +	err = lbs_start_card(priv);
> +	if (err)
> +		goto release_irq;
> +
> +	lbs_deb_spi("Finished initializing WLAN module.\n");
> +
> +	/* successful exit */
> +	goto out;
> +
> +release_irq:
> +	free_irq(spi->irq, card);
> +terminate_thread:
> +	if_spi_terminate_spi_thread(card);
> +remove_card:
> +	lbs_remove_card(priv); /* will call free_netdev */
> +free_gpio:
> +	gpio_free(card->gpio_cs);
> +free_card:
> +	free_if_spi_card(card);
> +out:
> +	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
> +	return err;
> +}
> +
> +static int __devexit libertas_spi_remove(struct spi_device *spi)
> +{
> +	struct if_spi_card *card = spi_get_drvdata(spi);
> +	struct lbs_private *priv = card->priv;
> +
> +	lbs_deb_spi("libertas_spi_remove\n");
> +	lbs_deb_enter(LBS_DEB_SPI);
> +	priv->surpriseremoved = 1;
> +
> +	lbs_stop_card(priv);
> +	free_irq(spi->irq, card);
> +	if_spi_terminate_spi_thread(card);
> +	lbs_remove_card(priv); /* will call free_netdev */
> +	gpio_free(card->gpio_cs);
> +	free_if_spi_card(card);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +	return 0;
> +}
> +
> +static struct spi_driver libertas_spi_driver = {
> +	.probe	= if_spi_probe,
> +	.remove = __devexit_p(libertas_spi_remove),
> +	.driver = {
> +		.name	= "libertas_spi",
> +		.bus	= &spi_bus_type,
> +		.owner	= THIS_MODULE,
> +	},
> +};
> +
> +/*
> + * Module functions
> + */
> +
> +static int __init if_spi_init_module(void)
> +{
> +	int ret = 0;
> +	lbs_deb_enter(LBS_DEB_SPI);
> +	printk(KERN_INFO "libertas_spi: Libertas SPI driver\n");
> +	ret = spi_register_driver(&libertas_spi_driver);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +	return ret;
> +}
> +
> +static void __exit if_spi_exit_module(void)
> +{
> +	lbs_deb_enter(LBS_DEB_SPI);
> +	spi_unregister_driver(&libertas_spi_driver);
> +	lbs_deb_leave(LBS_DEB_SPI);
> +}
> +
> +module_init(if_spi_init_module);
> +module_exit(if_spi_exit_module);
> +
> +MODULE_DESCRIPTION("Libertas SPI WLAN Driver");
> +MODULE_AUTHOR("Andrey Yurovsky <andrey at cozybit.com>, "
> +	      "Colin McCabe <colin at cozybit.com>");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h
> new file mode 100644
> index 0000000..2103869
> --- /dev/null
> +++ b/drivers/net/wireless/libertas/if_spi.h
> @@ -0,0 +1,208 @@
> +/*
> + *	linux/drivers/net/wireless/libertas/if_spi.c
> + *
> + *	Driver for Marvell SPI WLAN cards.
> + *
> + *	Copyright 2008 Analog Devices Inc.
> + *
> + *	Authors:
> + *	Andrey Yurovsky <andrey at cozybit.com>
> + *	Colin McCabe <colin at cozybit.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + */
> +
> +#ifndef _LBS_IF_SPI_H_
> +#define _LBS_IF_SPI_H_
> +
> +#define IPFIELD_ALIGN_OFFSET 2
> +#define IF_SPI_CMD_BUF_SIZE 2400
> +
> +/***************** Firmware *****************/
> +struct chip_ident {
> +	u16 chip_id;
> +	u16 name;
> +};
> +
> +#define MAX_MAIN_FW_LOAD_CRC_ERR 10
> +
> +/* Chunk size when loading the helper firmware */
> +#define HELPER_FW_LOAD_CHUNK_SZ 64
> +
> +/* Value to write to indicate end of helper firmware dnld */
> +#define FIRMWARE_DNLD_OK 0x0000
> +
> +/* Value to check once the main firmware is downloaded */
> +#define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888
> +
> +/***************** SPI Interface Unit *****************/
> +/* Masks used in SPI register read/write operations */
> +#define IF_SPI_READ_OPERATION_MASK 0x0
> +#define IF_SPI_WRITE_OPERATION_MASK 0x8000
> +
> +/* SPI register offsets. 4-byte aligned. */
> +#define IF_SPI_DEVICEID_CTRL_REG 0x00	/* DeviceID controller reg */
> +#define IF_SPI_IO_READBASE_REG 0x04 	/* Read I/O base reg */
> +#define IF_SPI_IO_WRITEBASE_REG 0x08	/* Write I/O base reg */
> +#define IF_SPI_IO_RDWRPORT_REG 0x0C	/* Read/Write I/O port reg */
> +
> +#define IF_SPI_CMD_READBASE_REG 0x10	/* Read command base reg */
> +#define IF_SPI_CMD_WRITEBASE_REG 0x14	/* Write command base reg */
> +#define IF_SPI_CMD_RDWRPORT_REG 0x18	/* Read/Write command port reg */
> +
> +#define IF_SPI_DATA_READBASE_REG 0x1C	/* Read data base reg */
> +#define IF_SPI_DATA_WRITEBASE_REG 0x20	/* Write data base reg */
> +#define IF_SPI_DATA_RDWRPORT_REG 0x24	/* Read/Write data port reg */
> +
> +#define IF_SPI_SCRATCH_1_REG 0x28	/* Scratch reg 1 */
> +#define IF_SPI_SCRATCH_2_REG 0x2C	/* Scratch reg 2 */
> +#define IF_SPI_SCRATCH_3_REG 0x30	/* Scratch reg 3 */
> +#define IF_SPI_SCRATCH_4_REG 0x34	/* Scratch reg 4 */
> +
> +#define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */
> +#define IF_SPI_TX_FRAME_STATUS_REG 0x3C	/* Tx frame status reg */
> +
> +#define IF_SPI_HOST_INT_CTRL_REG 0x40	/* Host interrupt controller reg */
> +
> +#define IF_SPI_CARD_INT_CAUSE_REG 0x44	/* Card interrupt cause reg */
> +#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */
> +#define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */
> +#define IF_SPI_CARD_INT_STATUS_MASK_REG	0x50 /* Card interrupt status mask */
> +
> +#define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */
> +
> +#define IF_SPI_HOST_INT_CAUSE_REG 0x58	/* Host interrupt cause reg */
> +#define IF_SPI_HOST_INT_STATUS_REG 0x5C	/* Host interrupt status reg */
> +#define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */
> +#define IF_SPI_HOST_INT_STATUS_MASK_REG	0x64 /* Host interrupt status mask */
> +#define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */
> +
> +#define IF_SPI_DELAY_READ_REG 0x6C	/* Delay read reg */
> +#define IF_SPI_SPU_BUS_MODE_REG 0x70	/* SPU BUS mode reg */
> +
> +/***************** IF_SPI_DEVICEID_CTRL_REG *****************/
> +#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16)
> +#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff)
> +
> +/***************** IF_SPI_HOST_INT_CTRL_REG *****************/
> +/** Host Interrupt Control bit : Wake up */
> +#define IF_SPI_HICT_WAKE_UP				(1<<0)
> +/** Host Interrupt Control bit : WLAN ready */
> +#define IF_SPI_HICT_WLAN_READY				(1<<1)
> +/*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY		(1<<2) */
> +/*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY		(1<<3) */
> +/*#define IF_SPI_HICT_IRQSRC_WLAN			(1<<4) */
> +/** Host Interrupt Control bit : Tx auto download */
> +#define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO		(1<<5)
> +/** Host Interrupt Control bit : Rx auto upload */
> +#define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO			(1<<6)
> +/** Host Interrupt Control bit : Command auto download */
> +#define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO		(1<<7)
> +/** Host Interrupt Control bit : Command auto upload */
> +#define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO		(1<<8)
> +
> +/***************** IF_SPI_CARD_INT_CAUSE_REG *****************/
> +/** Card Interrupt Case bit : Tx download over */
> +#define IF_SPI_CIC_TX_DOWNLOAD_OVER			(1<<0)
> +/** Card Interrupt Case bit : Rx upload over */
> +#define IF_SPI_CIC_RX_UPLOAD_OVER			(1<<1)
> +/** Card Interrupt Case bit : Command download over */
> +#define IF_SPI_CIC_CMD_DOWNLOAD_OVER			(1<<2)
> +/** Card Interrupt Case bit : Host event */
> +#define IF_SPI_CIC_HOST_EVENT				(1<<3)
> +/** Card Interrupt Case bit : Command upload over */
> +#define IF_SPI_CIC_CMD_UPLOAD_OVER			(1<<4)
> +/** Card Interrupt Case bit : Power down */
> +#define IF_SPI_CIC_POWER_DOWN				(1<<5)
> +
> +/***************** IF_SPI_CARD_INT_STATUS_REG *****************/
> +#define IF_SPI_CIS_TX_DOWNLOAD_OVER			(1<<0)
> +#define IF_SPI_CIS_RX_UPLOAD_OVER			(1<<1)
> +#define IF_SPI_CIS_CMD_DOWNLOAD_OVER			(1<<2)
> +#define IF_SPI_CIS_HOST_EVENT				(1<<3)
> +#define IF_SPI_CIS_CMD_UPLOAD_OVER			(1<<4)
> +#define IF_SPI_CIS_POWER_DOWN				(1<<5)
> +
> +/***************** IF_SPI_HOST_INT_CAUSE_REG *****************/
> +#define IF_SPI_HICU_TX_DOWNLOAD_RDY			(1<<0)
> +#define IF_SPI_HICU_RX_UPLOAD_RDY			(1<<1)
> +#define IF_SPI_HICU_CMD_DOWNLOAD_RDY			(1<<2)
> +#define IF_SPI_HICU_CARD_EVENT				(1<<3)
> +#define IF_SPI_HICU_CMD_UPLOAD_RDY			(1<<4)
> +#define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW			(1<<5)
> +#define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW		(1<<6)
> +#define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW		(1<<7)
> +#define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW		(1<<8)
> +#define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW		(1<<9)
> +#define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW		(1<<10)
> +
> +/***************** IF_SPI_HOST_INT_STATUS_REG *****************/
> +/** Host Interrupt Status bit : Tx download ready */
> +#define IF_SPI_HIST_TX_DOWNLOAD_RDY			(1<<0)
> +/** Host Interrupt Status bit : Rx upload ready */
> +#define IF_SPI_HIST_RX_UPLOAD_RDY			(1<<1)
> +/** Host Interrupt Status bit : Command download ready */
> +#define IF_SPI_HIST_CMD_DOWNLOAD_RDY			(1<<2)
> +/** Host Interrupt Status bit : Card event */
> +#define IF_SPI_HIST_CARD_EVENT				(1<<3)
> +/** Host Interrupt Status bit : Command upload ready */
> +#define IF_SPI_HIST_CMD_UPLOAD_RDY			(1<<4)
> +/** Host Interrupt Status bit : I/O write FIFO overflow */
> +#define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW			(1<<5)
> +/** Host Interrupt Status bit : I/O read FIFO underflow */
> +#define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW			(1<<6)
> +/** Host Interrupt Status bit : Data write FIFO overflow */
> +#define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW		(1<<7)
> +/** Host Interrupt Status bit : Data read FIFO underflow */
> +#define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW		(1<<8)
> +/** Host Interrupt Status bit : Command write FIFO overflow */
> +#define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW		(1<<9)
> +/** Host Interrupt Status bit : Command read FIFO underflow */
> +#define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW		(1<<10)
> +
> +/***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/
> +/** Host Interrupt Status Mask bit : Tx download ready */
> +#define IF_SPI_HISM_TX_DOWNLOAD_RDY			(1<<0)
> +/** Host Interrupt Status Mask bit : Rx upload ready */
> +#define IF_SPI_HISM_RX_UPLOAD_RDY			(1<<1)
> +/** Host Interrupt Status Mask bit : Command download ready */
> +#define IF_SPI_HISM_CMD_DOWNLOAD_RDY			(1<<2)
> +/** Host Interrupt Status Mask bit : Card event */
> +#define IF_SPI_HISM_CARDEVENT				(1<<3)
> +/** Host Interrupt Status Mask bit : Command upload ready */
> +#define IF_SPI_HISM_CMD_UPLOAD_RDY			(1<<4)
> +/** Host Interrupt Status Mask bit : I/O write FIFO overflow */
> +#define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW			(1<<5)
> +/** Host Interrupt Status Mask bit : I/O read FIFO underflow */
> +#define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW		(1<<6)
> +/** Host Interrupt Status Mask bit : Data write FIFO overflow */
> +#define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW		(1<<7)
> +/** Host Interrupt Status Mask bit : Data write FIFO underflow */
> +#define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW		(1<<8)
> +/** Host Interrupt Status Mask bit : Command write FIFO overflow */
> +#define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW		(1<<9)
> +/** Host Interrupt Status Mask bit : Command write FIFO underflow */
> +#define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW		(1<<10)
> +
> +/***************** IF_SPI_SPU_BUS_MODE_REG *****************/
> +/* SCK edge on which the WLAN module outputs data on MISO */
> +#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8
> +#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0
> +
> +/* In a SPU read operation, there is a delay between writing the SPU
> + * register name and getting back data from the WLAN module.
> + * This can be specified in terms of nanoseconds or in terms of dummy
> + * clock cycles which the master must output before receiving a response. */
> +#define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4
> +#define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0
> +
> +/* Some different modes of SPI operation */
> +#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00
> +#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01
> +#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02
> +#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03
> +
> +#endif
> diff --git a/include/linux/spi/libertas_spi.h b/include/linux/spi/libertas_spi.h
> new file mode 100644
> index 0000000..ada71b4
> --- /dev/null
> +++ b/include/linux/spi/libertas_spi.h
> @@ -0,0 +1,25 @@
> +/*
> + * board-specific data for the libertas_spi driver.
> + *
> + * Copyright 2008 Analog Devices Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or (at
> + * your option) any later version.
> + */
> +#ifndef _LIBERTAS_SPI_H_
> +#define _LIBERTAS_SPI_H_
> +struct libertas_spi_platform_data {
> +	/* There are two ways to read data from the WLAN module's SPI
> +	 * interface. Setting 0 or 1 here controls which one is used.
> +	 *
> +	 * Usually you want to set use_dummy_writes = 1.
> +	 * However, if that doesn't work or if you are using a slow SPI clock
> +	 * speed, you may want to use 0 here. */
> +	u16 use_dummy_writes;
> +
> +	/* GPIO number to use as chip select */
> +	u16 gpio_cs;
> +};
> +#endif



From dcbw at redhat.com  Mon Jan 12 14:37:52 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 12 Jan 2009 14:37:52 -0500
Subject: [PATCH v3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <45e8e6c40901121104r1f55894dy35d7528e8174f036@mail.gmail.com>
References: <1231541889-7999-1-git-send-email-colin@cozybit.com>
	<1231772017.23907.3.camel@localhost.localdomain>
	<45e8e6c40901121104r1f55894dy35d7528e8174f036@mail.gmail.com>
Message-ID: <1231789072.28887.11.camel@localhost.localdomain>

On Mon, 2009-01-12 at 11:04 -0800, Andrey Yurovsky wrote:
> Hi Dan, Johannes was correct -- the explicit get_unaligned_ was not
> needed and using packed was required.  Unfortunately our patch got
> merged before we had a chance to send a version including just the
> packing, so I'm preparing a patch that reverts the calls to
> get_unaligned_* ...this is, however, independent of the actual
> if_spi.c driver patch.

Yes, they are independent.  Alternatively, you could just ask John to
revert the patch, and then provide a new patch with just the 'packed'
bits, which might be cleaner in the git history.

Dan




From andrey at cozybit.com  Mon Jan 12 14:42:05 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Mon, 12 Jan 2009 11:42:05 -0800
Subject: [PATCH v3] libertas: if_spi, driver for libertas GSPI devices
In-Reply-To: <1231789072.28887.11.camel@localhost.localdomain>
References: <1231541889-7999-1-git-send-email-colin@cozybit.com>
	<1231772017.23907.3.camel@localhost.localdomain>
	<45e8e6c40901121104r1f55894dy35d7528e8174f036@mail.gmail.com>
	<1231789072.28887.11.camel@localhost.localdomain>
Message-ID: <45e8e6c40901121142k1fc6869cl2d6bd058fbacf972@mail.gmail.com>

Hi Dan, that sounds better: I've asked John to please go ahead and
revert it and we'll send a new version that just packs all of the
structs.  Thanks!

  -Andrey

On Mon, Jan 12, 2009 at 11:37 AM, Dan Williams <dcbw at redhat.com> wrote:
> On Mon, 2009-01-12 at 11:04 -0800, Andrey Yurovsky wrote:
>> Hi Dan, Johannes was correct -- the explicit get_unaligned_ was not
>> needed and using packed was required.  Unfortunately our patch got
>> merged before we had a chance to send a version including just the
>> packing, so I'm preparing a patch that reverts the calls to
>> get_unaligned_* ...this is, however, independent of the actual
>> if_spi.c driver patch.
>
> Yes, they are independent.  Alternatively, you could just ask John to
> revert the patch, and then provide a new patch with just the 'packed'
> bits, which might be cleaner in the git history.
>
> Dan
>
>
>


From andrey at cozybit.com  Mon Jan 12 16:14:27 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Mon, 12 Jan 2009 13:14:27 -0800 (PST)
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
Message-ID: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>

Data structures that come over the wire from the WLAN firmware must be packed.
This fixes alignment problems on the blackfin architecture and, reportedly, on
the AVR32.

This is a replacement for the previous version of this patch which had also
explicitly used get_unaligned_ macros.  As Johannes Berg pointed out, these 
macros were unnecessary.

Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
Signed-off-by: Colin McCabe <colin at cozybit.com>
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index 2d8533c..a899aeb 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -32,7 +32,7 @@ struct txpd {
 	u8 pktdelay_2ms;
 	/* reserved */
 	u8 reserved1;
-};
+} __attribute__ ((packed));
 
 /* RxPD Descriptor */
 struct rxpd {
@@ -63,7 +63,7 @@ struct rxpd {
 	/* Pkt Priority */
 	u8 priority;
 	u8 reserved[3];
-};
+} __attribute__ ((packed));
 
 struct cmd_header {
 	__le16 command;
@@ -97,7 +97,7 @@ struct enc_key {
 struct lbs_offset_value {
 	u32 offset;
 	u32 value;
-};
+} __attribute__ ((packed));
 
 /* Define general data structure */
 /* cmd_DS_GEN */
@@ -107,7 +107,7 @@ struct cmd_ds_gen {
 	__le16 seqnum;
 	__le16 result;
 	void *cmdresp[0];
-};
+} __attribute__ ((packed));
 
 #define S_DS_GEN sizeof(struct cmd_ds_gen)
 
@@ -163,7 +163,7 @@ struct cmd_ds_802_11_subscribe_event {
 	 * bump this up a bit.
 	 */
 	uint8_t tlv[128];
-};
+} __attribute__ ((packed));
 
 /*
  * This scan handle Country Information IE(802.11d compliant)
@@ -180,7 +180,7 @@ struct cmd_ds_802_11_scan {
 	mrvlietypes_chanlistparamset_t ChanListParamSet;
 	mrvlietypes_ratesparamset_t OpRateSet;
 #endif
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_scan_rsp {
 	struct cmd_header hdr;
@@ -188,7 +188,7 @@ struct cmd_ds_802_11_scan_rsp {
 	__le16 bssdescriptsize;
 	uint8_t nr_sets;
 	uint8_t bssdesc_and_tlvbuffer[0];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_get_log {
 	struct cmd_header hdr;
@@ -206,20 +206,20 @@ struct cmd_ds_802_11_get_log {
 	__le32 fcserror;
 	__le32 txframe;
 	__le32 wepundecryptable;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_control {
 	struct cmd_header hdr;
 	__le16 action;
 	u16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_multicast_adr {
 	struct cmd_header hdr;
 	__le16 action;
 	__le16 nr_of_adrs;
 	u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_gspi_bus_config {
 	struct cmd_header hdr;
@@ -233,14 +233,14 @@ struct cmd_ds_802_11_authenticate {
 	u8 macaddr[ETH_ALEN];
 	u8 authtype;
 	u8 reserved[10];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_deauthenticate {
 	struct cmd_header hdr;
 
 	u8 macaddr[ETH_ALEN];
 	__le16 reasoncode;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_associate {
 	u8 peerstaaddr[6];
@@ -259,7 +259,7 @@ struct cmd_ds_802_11_associate {
 
 struct cmd_ds_802_11_associate_rsp {
 	struct ieeetypes_assocrsp assocRsp;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_set_wep {
 	struct cmd_header hdr;
@@ -273,7 +273,7 @@ struct cmd_ds_802_11_set_wep {
 	/* 40, 128bit or TXWEP */
 	uint8_t keytype[4];
 	uint8_t keymaterial[4][16];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_3_get_stat {
 	__le32 xmitok;
@@ -282,7 +282,7 @@ struct cmd_ds_802_3_get_stat {
 	__le32 rcverror;
 	__le32 rcvnobuffer;
 	__le32 rcvcrcerror;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_get_stat {
 	__le32 txfragmentcnt;
@@ -302,7 +302,7 @@ struct cmd_ds_802_11_get_stat {
 	__le32 txbeacon;
 	__le32 rxbeacon;
 	__le32 wepundecryptable;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_snmp_mib {
 	struct cmd_header hdr;
@@ -311,58 +311,58 @@ struct cmd_ds_802_11_snmp_mib {
 	__le16 oid;
 	__le16 bufsize;
 	u8 value[128];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_reg_map {
 	__le16 buffersize;
 	u8 regmap[128];
 	__le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_bbp_reg_map {
 	__le16 buffersize;
 	u8 regmap[128];
 	__le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_rf_reg_map {
 	__le16 buffersize;
 	u8 regmap[64];
 	__le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_mac_reg_access {
 	__le16 action;
 	__le16 offset;
 	__le32 value;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_bbp_reg_access {
 	__le16 action;
 	__le16 offset;
 	u8 value;
 	u8 reserved[3];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_rf_reg_access {
 	__le16 action;
 	__le16 offset;
 	u8 value;
 	u8 reserved[3];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_radio_control {
 	struct cmd_header hdr;
 
 	__le16 action;
 	__le16 control;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_beacon_control {
 	__le16 action;
 	__le16 beacon_enable;
 	__le16 beacon_period;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_sleep_params {
 	struct cmd_header hdr;
@@ -387,7 +387,7 @@ struct cmd_ds_802_11_sleep_params {
 
 	/* reserved field, should be set to zero */
 	__le16 reserved;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_inactivity_timeout {
 	struct cmd_header hdr;
@@ -397,7 +397,7 @@ struct cmd_ds_802_11_inactivity_timeout {
 
 	/* Inactivity timeout in msec */
 	__le16 timeout;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rf_channel {
 	struct cmd_header hdr;
@@ -407,7 +407,7 @@ struct cmd_ds_802_11_rf_channel {
 	__le16 rftype;      /* unused */
 	__le16 reserved;    /* unused */
 	u8 channellist[32]; /* unused */
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rssi {
 	/* weighting factor */
@@ -416,21 +416,21 @@ struct cmd_ds_802_11_rssi {
 	__le16 reserved_0;
 	__le16 reserved_1;
 	__le16 reserved_2;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rssi_rsp {
 	__le16 SNR;
 	__le16 noisefloor;
 	__le16 avgSNR;
 	__le16 avgnoisefloor;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_mac_address {
 	struct cmd_header hdr;
 
 	__le16 action;
 	u8 macadd[ETH_ALEN];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rf_tx_power {
 	struct cmd_header hdr;
@@ -439,7 +439,7 @@ struct cmd_ds_802_11_rf_tx_power {
 	__le16 curlevel;
 	s8 maxlevel;
 	s8 minlevel;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rf_antenna {
 	__le16 action;
@@ -447,33 +447,33 @@ struct cmd_ds_802_11_rf_antenna {
 	/* Number of antennas or 0xffff(diversity) */
 	__le16 antennamode;
 
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_monitor_mode {
 	__le16 action;
 	__le16 mode;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_set_boot2_ver {
 	struct cmd_header hdr;
 
 	__le16 action;
 	__le16 version;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_fw_wake_method {
 	struct cmd_header hdr;
 
 	__le16 action;
 	__le16 method;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_sleep_period {
 	struct cmd_header hdr;
 
 	__le16 action;
 	__le16 period;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_ps_mode {
 	__le16 action;
@@ -481,7 +481,7 @@ struct cmd_ds_802_11_ps_mode {
 	__le16 multipledtim;
 	__le16 reserved;
 	__le16 locallisteninterval;
-};
+} __attribute__ ((packed));
 
 struct cmd_confirm_sleep {
 	struct cmd_header hdr;
@@ -491,7 +491,7 @@ struct cmd_confirm_sleep {
 	__le16 multipledtim;
 	__le16 reserved;
 	__le16 locallisteninterval;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_data_rate {
 	struct cmd_header hdr;
@@ -499,14 +499,14 @@ struct cmd_ds_802_11_data_rate {
 	__le16 action;
 	__le16 reserved;
 	u8 rates[MAX_RATES];
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_rate_adapt_rateset {
 	struct cmd_header hdr;
 	__le16 action;
 	__le16 enablehwauto;
 	__le16 bitmap;
-};
+} __attribute__ ((packed));
 
 struct cmd_ds_802_11_ad_hoc_start {
 	struct cmd_header hdr;
@@ -528,7 +528,7 @@ struct cmd_ds_802_11_ad_hoc_result {
 
 	u8 pad[3];
 	u8 bssid[ETH_ALEN];
-};
+} __attribute__ ((packed));
 
 struct adhoc_bssdesc {
 	u8 bssid[ETH_ALEN];
@@ -586,7 +586,7 @@ struct MrvlIEtype_keyParamSet {
 
 	/* key material of size keylen */
 	u8 key[32];
-};
+} __attribute__ ((packed));
 
 #define MAX_WOL_RULES 		16
 
@@ -598,7 +598,7 @@ struct host_wol_rule {
 	__le16 reserve;
 	__be32 sig_mask;
 	__be32 signature;
-};
+} __attribute__ ((packed));
 
 struct wol_config {
 	uint8_t action;
@@ -606,8 +606,7 @@ struct wol_config {
 	uint8_t no_rules_in_cmd;
 	uint8_t result;
 	struct host_wol_rule rule[MAX_WOL_RULES];
-};
-
+} __attribute__ ((packed));
 
 struct cmd_ds_host_sleep {
 	struct cmd_header hdr;




From dcbw at redhat.com  Fri Jan 16 16:05:28 2009
From: dcbw at redhat.com (Dan Williams)
Date: Fri, 16 Jan 2009 16:05:28 -0500
Subject: Libertas firmware
Message-ID: <1232139928.26487.67.camel@174-147-64-233.pools.spcsdns.net>

Hi,

I've gotten the final sign-off to push the following Marvell firmware to
the linux-firmware git tree.  We now have standard firmware which we can
point the drivers at, and use as a baseline for debugging issues that
might be firmware related.

Going forward, we'll work to ensure that the driver works correctly with
the standard firmware.  The first question usually asked is "what
firmware version", which will now be replaced by "does this happen with
the standard firmware" :)

File: cf8385.bin
File: cf8385_helper.bin
File: gspi8686_v9.bin
File: gspi8686_v9_helper.bin
File: sd8385.bin
File: sd8385_helper.bin
File: sd8686_v8.bin
File: sd8686_v8_helper.bin
File: sd8686_v9.bin
File: sd8686_v9_helper.bin
File: usb8388_v5.bin
File: usb8388_v9.bin

(all 8385 firmware is version 5.x)

Dan




From dario at eecs.harvard.edu  Fri Jan 16 18:12:49 2009
From: dario at eecs.harvard.edu (Dario Vlah)
Date: Fri, 16 Jan 2009 18:12:49 -0500 (EST)
Subject: [PATCH] libertas: Fix Marvell rate table
Message-ID: <20090116155539.T49441@bowser.eecs.harvard.edu>

Hi,

The rate table in tx.c seems to be slightly off for g rates.  Here is a 
patch.

--dario




diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index dac4626..a6bf4a5 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -30,21 +31,21 @@ static u32 convert_radiotap_rate_to_mv(u8 rate)
  	case 22:		/*  11 Mbps */
  		return 3 | (1 << 4);
  	case 12:		/*   6 Mbps */
-		return 4 | (1 << 4);
-	case 18:		/*   9 Mbps */
  		return 5 | (1 << 4);
-	case 24:		/*  12 Mbps */
+	case 18:		/*   9 Mbps */
  		return 6 | (1 << 4);
-	case 36:		/*  18 Mbps */
+	case 24:		/*  12 Mbps */
  		return 7 | (1 << 4);
-	case 48:		/*  24 Mbps */
+	case 36:		/*  18 Mbps */
  		return 8 | (1 << 4);
-	case 72:		/*  36 Mbps */
+	case 48:		/*  24 Mbps */
  		return 9 | (1 << 4);
-	case 96:		/*  48 Mbps */
+	case 72:		/*  36 Mbps */
  		return 10 | (1 << 4);
-	case 108:		/*  54 Mbps */
+	case 96:		/*  48 Mbps */
  		return 11 | (1 << 4);
+	case 108:		/*  54 Mbps */
+		return 12 | (1 << 4);
  	}
  	return 0;
  }


From javier at cozybit.com  Sat Jan 17 11:38:55 2009
From: javier at cozybit.com (Javier Cardona)
Date: Sat, 17 Jan 2009 08:38:55 -0800
Subject: Libertas firmware
In-Reply-To: <1232139928.26487.67.camel@174-147-64-233.pools.spcsdns.net>
References: <1232139928.26487.67.camel@174-147-64-233.pools.spcsdns.net>
Message-ID: <445f43ac0901170838p7531fc65k621146a8b5a5d4be@mail.gmail.com>

Dan,

On Fri, Jan 16, 2009 at 1:05 PM, Dan Williams <dcbw at redhat.com> wrote:
> I've gotten the final sign-off to push the following Marvell firmware to
> the linux-firmware git tree.  We now have standard firmware which we can
> point the drivers at, and use as a baseline for debugging issues that
> might be firmware related.

This is fantastic news.  It will greatly simplify the lives of people
using the driver.
One question, though: where can we find the full version number for each file?

Thank you!

Javier


-- 
Javier Cardona
cozybit Inc.


From dcbw at redhat.com  Mon Jan 19 11:12:27 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 19 Jan 2009 11:12:27 -0500
Subject: Libertas firmware
In-Reply-To: <445f43ac0901170838p7531fc65k621146a8b5a5d4be@mail.gmail.com>
References: <1232139928.26487.67.camel@174-147-64-233.pools.spcsdns.net>
	<445f43ac0901170838p7531fc65k621146a8b5a5d4be@mail.gmail.com>
Message-ID: <1232381547.17497.7.camel@localhost.localdomain>

On Sat, 2009-01-17 at 08:38 -0800, Javier Cardona wrote:
> Dan,
> 
> On Fri, Jan 16, 2009 at 1:05 PM, Dan Williams <dcbw at redhat.com> wrote:
> > I've gotten the final sign-off to push the following Marvell firmware to
> > the linux-firmware git tree.  We now have standard firmware which we can
> > point the drivers at, and use as a baseline for debugging issues that
> > might be firmware related.
> 
> This is fantastic news.  It will greatly simplify the lives of people
> using the driver.
> One question, though: where can we find the full version number for each file?

I can get them, but the numbers I have were for the download tarball
that the firmware was included in, not necessarily for the firmware
itself.  Perhaps that's sufficient.  I can go get those numbers for you
again if you like, but there's not a good way to store the numbers in
the linux-firmware tree except in a lookaside file, which has its own
downsides.  But it's probably useful to have them somewhere.

Dan




From dcbw at redhat.com  Mon Jan 19 11:13:30 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 19 Jan 2009 11:13:30 -0500
Subject: [PATCH] libertas: Fix Marvell rate table
In-Reply-To: <20090116155539.T49441@bowser.eecs.harvard.edu>
References: <20090116155539.T49441@bowser.eecs.harvard.edu>
Message-ID: <1232381610.17497.9.camel@localhost.localdomain>

On Fri, 2009-01-16 at 18:12 -0500, Dario Vlah wrote:
> Hi,
> 
> The rate table in tx.c seems to be slightly off for g rates.  Here is a 
> patch.

Could you sign off on the patch per kernel commit requirements?
Basically, certify that the work is your original work and that you have
permission to post the patch to the kernel, by adding your
Signed-off-by: tag like so:

Signed-off-by: Bill Smith <smith at somewhere.com>

Dan

> --dario
> 
> 
> 
> 
> diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
> index dac4626..a6bf4a5 100644
> --- a/drivers/net/wireless/libertas/tx.c
> +++ b/drivers/net/wireless/libertas/tx.c
> @@ -30,21 +31,21 @@ static u32 convert_radiotap_rate_to_mv(u8 rate)
>   	case 22:		/*  11 Mbps */
>   		return 3 | (1 << 4);
>   	case 12:		/*   6 Mbps */
> -		return 4 | (1 << 4);
> -	case 18:		/*   9 Mbps */
>   		return 5 | (1 << 4);
> -	case 24:		/*  12 Mbps */
> +	case 18:		/*   9 Mbps */
>   		return 6 | (1 << 4);
> -	case 36:		/*  18 Mbps */
> +	case 24:		/*  12 Mbps */
>   		return 7 | (1 << 4);
> -	case 48:		/*  24 Mbps */
> +	case 36:		/*  18 Mbps */
>   		return 8 | (1 << 4);
> -	case 72:		/*  36 Mbps */
> +	case 48:		/*  24 Mbps */
>   		return 9 | (1 << 4);
> -	case 96:		/*  48 Mbps */
> +	case 72:		/*  36 Mbps */
>   		return 10 | (1 << 4);
> -	case 108:		/*  54 Mbps */
> +	case 96:		/*  48 Mbps */
>   		return 11 | (1 << 4);
> +	case 108:		/*  54 Mbps */
> +		return 12 | (1 << 4);
>   	}
>   	return 0;
>   }
> 
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From dario at eecs.harvard.edu  Mon Jan 19 12:08:28 2009
From: dario at eecs.harvard.edu (Dario Vlah)
Date: Mon, 19 Jan 2009 12:08:28 -0500 (EST)
Subject: [PATCH] libertas: Fix Marvell rate table
In-Reply-To: <1232381610.17497.9.camel@localhost.localdomain>
References: <20090116155539.T49441@bowser.eecs.harvard.edu>
	<1232381610.17497.9.camel@localhost.localdomain>
Message-ID: <20090119120117.Q30924@bowser.eecs.harvard.edu>

On Mon, 19 Jan 2009, Dan Williams wrote:

> Could you sign off on the patch per kernel commit requirements?

Certainly, here it is.

--dario

Signed-off-by: Dario Vlah <dario at eecs.harvard.edu>
--
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index dac4626..a6bf4a5 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -30,21 +31,21 @@ static u32 convert_radiotap_rate_to_mv(u8 rate)
  	case 22:		/*  11 Mbps */
  		return 3 | (1 << 4);
  	case 12:		/*   6 Mbps */
-		return 4 | (1 << 4);
-	case 18:		/*   9 Mbps */
  		return 5 | (1 << 4);
-	case 24:		/*  12 Mbps */
+	case 18:		/*   9 Mbps */
  		return 6 | (1 << 4);
-	case 36:		/*  18 Mbps */
+	case 24:		/*  12 Mbps */
  		return 7 | (1 << 4);
-	case 48:		/*  24 Mbps */
+	case 36:		/*  18 Mbps */
  		return 8 | (1 << 4);
-	case 72:		/*  36 Mbps */
+	case 48:		/*  24 Mbps */
  		return 9 | (1 << 4);
-	case 96:		/*  48 Mbps */
+	case 72:		/*  36 Mbps */
  		return 10 | (1 << 4);
-	case 108:		/*  54 Mbps */
+	case 96:		/*  48 Mbps */
  		return 11 | (1 << 4);
+	case 108:		/*  54 Mbps */
+		return 12 | (1 << 4);
  	}
  	return 0;
  }


From chaenel at free.fr  Thu Jan 22 13:02:14 2009
From: chaenel at free.fr (Cyril HAENEL)
Date: Thu, 22 Jan 2009 19:02:14 +0100
Subject: Libertas with if_cs.c on ARM processor
Message-ID: <4978B4A6.102@free.fr>

Hi all,

I am not sure I am on the right place, but I don't know where to ask my 
question.

I built a custom board based on the AT91SAM9260 ARM processor. My wifi 
card is based on the marvell 8385 chip, and is connected to the 
processor with compact flash bus.
The card is detected but the board freeze when I try to load the helper 
in the card. The problem comes from the /WAIT signal, after some 
read/write on the bus the 8385 put this signal low for ever, and the 
processor wait for ever....

I looked in detail on the scope, and I seen that the 8385 put the /wait 
signal low when its chip selects CE1 and CE2 are not active !!
So I seen it puts the /wait signal low when /IORD and /IOWR are low. 
Because /IORD and /IOWR are multiplexed with other signal on the 
AT91SAM9260, it is possible these signals goes low simultaneously. It's 
seems the 8385 is affected by this situation, even if it is not 
chip-selected.

Is someone have a 8385 cf module working on a AT91SAM926x board ? If 
yes, how have you connected these signals ?

Regards,
Cyril

-- 

Cyril Haenel
Registered Linux User #332632



From ryan at bluewatersys.com  Thu Jan 22 14:37:31 2009
From: ryan at bluewatersys.com (Ryan Mallon)
Date: Fri, 23 Jan 2009 08:37:31 +1300
Subject: Libertas with if_cs.c on ARM processor
In-Reply-To: <4978B4A6.102@free.fr>
References: <4978B4A6.102@free.fr>
Message-ID: <4978CAFB.1090609@bluewatersys.com>

Cyril HAENEL wrote:
> Hi all,
> 
> I am not sure I am on the right place, but I don't know where to ask my 
> question.
> 
> I built a custom board based on the AT91SAM9260 ARM processor. My wifi 
> card is based on the marvell 8385 chip, and is connected to the 
> processor with compact flash bus.
> The card is detected but the board freeze when I try to load the helper 
> in the card. The problem comes from the /WAIT signal, after some 
> read/write on the bus the 8385 put this signal low for ever, and the 
> processor wait for ever....
> 
> I looked in detail on the scope, and I seen that the 8385 put the /wait 
> signal low when its chip selects CE1 and CE2 are not active !!
> So I seen it puts the /wait signal low when /IORD and /IOWR are low. 
> Because /IORD and /IOWR are multiplexed with other signal on the 
> AT91SAM9260, it is possible these signals goes low simultaneously. It's 
> seems the 8385 is affected by this situation, even if it is not 
> chip-selected.
> 
> Is someone have a 8385 cf module working on a AT91SAM926x board ? If 
> yes, how have you connected these signals ?

Hi,

First off, I'm a software engineer, so forgive me if my explanation is a
little off :-). We have the Marvell 8385 compact flash (Winstron Wifi
module) working on an AT91SAM9260 based board. Our memory bus is 1.8v so
there are buffers for the conversion from 3v3 on the compact flash
signals and also pullups on the pc_wait_n, pc_rst, pc_reg and pc_rdy
signals to 3v3.

Also, check that your kernel is putting all of the pins in their correct
alternative function mode for compact flash.

~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

       Ryan Mallon                              Unit 5, Amuri Park
       Phone: +64 3 3779127                     404 Barbadoes St
       Fax:   +64 3 3779135                     PO Box 13 889
       Email: ryan at bluewatersys.com             Christchurch, 8013
       Web:   http://www.bluewatersys.com       New Zealand
       Freecall Australia  1800 148 751         USA 1800 261 2934


From chaenel at free.fr  Fri Jan 23 02:35:18 2009
From: chaenel at free.fr (Cyril HAENEL)
Date: Fri, 23 Jan 2009 08:35:18 +0100
Subject: Libertas with if_cs.c on ARM processor
In-Reply-To: <4978CAFB.1090609@bluewatersys.com>
References: <4978B4A6.102@free.fr> <4978CAFB.1090609@bluewatersys.com>
Message-ID: <49797336.5050806@free.fr>



Ryan Mallon a ?crit :
> Cyril HAENEL wrote:
>   
>> Hi all,
>>
>> I am not sure I am on the right place, but I don't know where to ask my 
>> question.
>>
>> I built a custom board based on the AT91SAM9260 ARM processor. My wifi 
>> card is based on the marvell 8385 chip, and is connected to the 
>> processor with compact flash bus.
>> The card is detected but the board freeze when I try to load the helper 
>> in the card. The problem comes from the /WAIT signal, after some 
>> read/write on the bus the 8385 put this signal low for ever, and the 
>> processor wait for ever....
>>
>> I looked in detail on the scope, and I seen that the 8385 put the /wait 
>> signal low when its chip selects CE1 and CE2 are not active !!
>> So I seen it puts the /wait signal low when /IORD and /IOWR are low. 
>> Because /IORD and /IOWR are multiplexed with other signal on the 
>> AT91SAM9260, it is possible these signals goes low simultaneously. It's 
>> seems the 8385 is affected by this situation, even if it is not 
>> chip-selected.
>>
>> Is someone have a 8385 cf module working on a AT91SAM926x board ? If 
>> yes, how have you connected these signals ?
>>     
>
> Hi,
>
> First off, I'm a software engineer, so forgive me if my explanation is a
> little off :-). We have the Marvell 8385 compact flash (Winstron Wifi
> module) working on an AT91SAM9260 based board. Our memory bus is 1.8v so
> there are buffers for the conversion from 3v3 on the compact flash
> signals and also pullups on the pc_wait_n, pc_rst, pc_reg and pc_rdy
> signals to 3v3.
>
> Also, check that your kernel is putting all of the pins in their correct
> alternative function mode for compact flash.
>
> ~Ryan
>
>   
Ryan, thank you for your answer.
On my board, mem bus is 3.3V and the wifi card is definitively mounted 
on the board, thus I have no buffer, all signals are directly connected 
on the card, exactly as figure 20.5 on page 152 of the at91sam9260 
datasheet, but without the buffers.

On your board the mem bus is 16 bits or 32 bits ? Because in 16 bits 
mode (my bus is 16 bits), normally NBS3 (multiplexed with CFIOW) should 
be not used when accessing other memory zone than the pcmci memory zone. 
And I can see this signal at zero level even when the pcmcia memory zone 
is not acceded.

Regards,
Cyril

-- 

Cyril Haenel
Registered Linux User #332632



From chaenel at free.fr  Fri Jan 23 08:33:07 2009
From: chaenel at free.fr (Cyril HAENEL)
Date: Fri, 23 Jan 2009 14:33:07 +0100
Subject: Libertas with if_cs.c on ARM processor
In-Reply-To: <4978CAFB.1090609@bluewatersys.com>
References: <4978B4A6.102@free.fr> <4978CAFB.1090609@bluewatersys.com>
Message-ID: <4979C713.5000900@free.fr>



Ryan Mallon a ?crit :
> Cyril HAENEL wrote:
>   
>> Hi all,
>>
>> I am not sure I am on the right place, but I don't know where to ask my 
>> question.
>>
>> I built a custom board based on the AT91SAM9260 ARM processor. My wifi 
>> card is based on the marvell 8385 chip, and is connected to the 
>> processor with compact flash bus.
>> The card is detected but the board freeze when I try to load the helper 
>> in the card. The problem comes from the /WAIT signal, after some 
>> read/write on the bus the 8385 put this signal low for ever, and the 
>> processor wait for ever....
>>
>> I looked in detail on the scope, and I seen that the 8385 put the /wait 
>> signal low when its chip selects CE1 and CE2 are not active !!
>> So I seen it puts the /wait signal low when /IORD and /IOWR are low. 
>> Because /IORD and /IOWR are multiplexed with other signal on the 
>> AT91SAM9260, it is possible these signals goes low simultaneously. It's 
>> seems the 8385 is affected by this situation, even if it is not 
>> chip-selected.
>>
>> Is someone have a 8385 cf module working on a AT91SAM926x board ? If 
>> yes, how have you connected these signals ?
>>     
>
> Hi,
>
> First off, I'm a software engineer, so forgive me if my explanation is a
> little off :-). We have the Marvell 8385 compact flash (Winstron Wifi
> module) working on an AT91SAM9260 based board. Our memory bus is 1.8v so
> there are buffers for the conversion from 3v3 on the compact flash
> signals and also pullups on the pc_wait_n, pc_rst, pc_reg and pc_rdy
> signals to 3v3.
>
> Also, check that your kernel is putting all of the pins in their correct
> alternative function mode for compact flash.
>
> ~Ryan
>
>   
I added 2 logic gates between the processor and the 8385 to always have 
/IORD and /IOWR high when the 8385 is not chip-selected. It works well now.

But I think I found a bug in the libertas driver :

In if_cs_probe, we have :

[...]
    /* Load the firmware early, before calling into libertas.ko */
    ret = if_cs_prog_helper(card);
    if (ret == 0)
        ret = if_cs_prog_real(card);
    if (ret)
        goto out2;
[...]

At the end of the if_cs_prog_real function we have :

[...]
    ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a);
    if (ret < 0)
        lbs_pr_err("firmware download failed\n");

err_release:
    release_firmware(fw);

done:
    lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret);
    return ret;

In my case ret value is 28 because if_cs_poll_while_fw_download() takes 
28 read loop to have IF_CS_SCRATCH register value equal to 0x5A.

But in if_cs_probe() function, 28 is considered as an error, and give me 
on my console :

libertas_cs: probe of 0.0 failed with error 28

Regards

-- 

Cyril Haenel
Registered Linux User #332632



From lawrence.auster at att.net  Fri Jan 23 13:04:03 2009
From: lawrence.auster at att.net (Lawrence Auster)
Date: Fri, 23 Jan 2009 19:04:03 +0100
Subject: Is Israel a Democracy? -- The problem with intellectually insecure
	whites -- Should Christians Support Israeli Terrorism in Gaza?
Message-ID: <20090123180414.UZCK26080.hrndva-omta04.mail.rr.com@rpetu>

The Jewish State of Israel has no constitution, nor does it name its borders. Israel's hidden constitution is Judaism. Israel's undeclared borders range from the Nile to the Euphrates rivers. Israel's desired jurisdiction extends over the entire Earth.

It could not be more clear that the Jewish State follows a foreign policy which obeys Jewish Law as iterated in the Hebrew Bible, the Talmud, Maimonedes, the Cabalah, and the many commentaries and refinements of same. The Jews are genociding the native inhabitants of Palestine, just as their religion advises, and because
their religion teaches them to do so. They treat non-Jews as if non-humans, just as their religion requires them to do. They make perpetual war on every nation on Earth, just as their genocidal Jewish God has instructed.

The Jews of Israel are simply being Jews. Jews are an existential threat to the human race.

Israel contains one third of the Jews of the World. It is not some aberration of the Jewish spirit, but the condensation and concentration of the perverse Jewish mentality, which malady also pervades the remaining two thirds of Jewry, who almost unanimously support the Jewish State, and who certainly do unanimously support
the Jewish People and its consistent and constant crimes against the human race. Israel is Jewry and the danger of Israel is the danger of the Jewish People to all others, as the Jews have demonstrated each and every day of their existence.

The Jews, the entire Jewish People of 15 million, will not relent until they have wiped out all non-Jews in "Greater Israel". They will not stop destroying all other cultures, nations, religions, ethnicities, races, competition, etc. until they are either stopped, or succeed in their ancient quest to destroy the human race.

What Israel is doing is not some reaction to outside forces, nor was the formation of Israel a response to the Holocaust. Israel is simply following the plan laid out in the Jews' religious texts. The Jews have openly planned to take Palestine and genocide the native population of Palestine for some 2,500 years before the
Holocaust. The Jews have openly complained that "anti-Semitism" is a threat that gives them the right to genocide the Palestinians, not merely since the advent of Nazism, but for some 2,500 years.

The Jewish religion is the Constitution of the Jewish State of Israel, and, to a greater or lesser extent, the constitution of the nature of every Jew alive. The borders of Israel are the range the Jew roams over the entire World. The perverse Jewish mentality is inbred by a Jew's exposure to his parents and to his community. Judaism
passes in the spit and slobber of Jewish mother telling her Jewish child that he is a "Jew", as much as Judaism passes in the poison and pain of a Talmudic tractate. The secular Jews did not suddenly come to life after the Enlightenment and the Jewish Reformation a body of vampires that appeared ex nihilo, in vacuo, mostly
atheistical and undetached from formally practiced Judaism. Judaism is the Jew. It is a mindset that transcends and supercedes religion. It is a belief set, a way of life, a perception of one's self and one's relation to the World that makes a Jew, a Jew, and a danger to all of humanity.

In fact, the religious shell of Judaism is like the stretched and infected skin of a lycanthropic pustule. When you lance it to cure the infection, the virus only becomes more contagious and spills directly on the non-Jew.

The secular Jew is a deliberate product of the hyper-religious Jew, a monster created out of the hewed corpses of the fanatically religious Jew, a Golem which is conjured up to enter the World of the non-Jew and poison its blood, and boil its brain with a rabid lunacy that bites and spreads, until the infected community feeds on
itself and fills the fields with rotting bloating bodies, where once human beings tilled the soil and tended to their families. The religious Jew created the secular Jew as an army of Esthers who seduce with open thighs, broad smiles, and a Siren call that lures in the non-Jew to cast his skull upon the jagged rocks and color the seas
with his blood, sickened and blinded by the venereal disease of Judaism in secular form.

Israel is not a secular democracy. It is a religious mockery. It is a rabid bat flying to the ends of the Earth, to end the Earth. No one will be free nor safe until the disease is quarantined and dies out.

Source: http://www.ziopedia.org/articles/israel/how_can_israel_claim_to_be_a_%27democracy%27_when_it_has_no_constitution_nor_borders?/`

--------------------

The problem with intellectually insecure whites
By Kevin MacDonald
January 19, 2009

America will soon have a white minority. This is a much desired state of affairs for the hostile elites who hold political power and shape public opinion. But it certainly creates some management issues ? at least in the long run. After all, it?s difficult to come up with an historical example of a nation with a solid ethnic majority (90%
white in 1950) that has voluntarily decided to cede political and cultural power. Such transformations are typically accomplished by military invasions, great battles, and untold suffering.

And it?s not as if everyone is doing it. Only Western nations view their own demographic and cultural eclipse as a moral imperative. Indeed, as I have noted previously, it is striking that racial nationalism has triumphed in Israel at the same time that the Jewish intellectual and political movements and the organized Jewish
community have been the most active and effective force for a non-white America. Indeed, a poll in 2008 found that Avigdor Lieberman was the second most popular politician in Israel. Lieberman has advocated expulsion of Arabs from Israel and has declared himself a follower of Vladimir Jabotinsky, the leading pioneer of racial
Zionism. The most popular politician in the poll was Benjamin Netanyahu ? another admirer of Jabotinsky. Prime Minister Ehud Olmert and Foreign Minister Tzipi Livni are also Jabotinskyists.

The racial Zionists are now carrying out yet another orgy of mass murder after a starvation-inducing blockade and the usual triggering assault designed to provoke Palestinian retaliation ? which then becomes the cover for claims that Israel is merely defending itself against terrorism. This monstrosity was approved by
overwhelming majorities of both Houses of Congress. The craven Bush administration did its part by abstaining from a UN resolution designed by the US Secretary of State as a result of a personal appeal by the Israeli Prime Minister. This is yet another accomplishment of the Israel Lobby, but one they would rather not have
discussed in public. People might get the impression that the Lobby really does dictate US foreign policy in the Mideast. Obviously, such thoughts are only entertained by anti-Semites.

But I digress.

In managing the eclipse of white America, one strategy of the mainstream media is to simply ignore the issue. Christopher Donovan  (?For the media, the less whites think about their coming minority status, the better?) has noted that the media, and in particular, the New York Times, are quite uninterested in doing stories that
discuss what white people think about this state of affairs.

It?s not surprising that the New York Times ? the Jewish-owned flagship of anti-white, pro-multicultural media ? ignores the issue. The issue is also missing from so-called conservative media even though one would think that conservatives would find the eclipse of white America to be an important issue. Certainly, their audiences
would find it interesting.

Now we have an article ?The End of White America? written by Hua Hsu, an Assistant Professor of English at Vassar College. The article is a rather depressing display of what passes for intellectual discourse on the most important question confronting white people in America.

Hsu begins by quoting a passage in F. Scott Fitzgerald?s The Great Gatsby in which a character, Tom Buchanan, states: ?Have you read The Rise of the Colored Empires by this man Goddard?? ? Well, it?s a fine book, and everybody ought to read it. The idea is if we don?t look out the white race will be?will be utterly submerged.
It?s all scientific stuff; it?s been proved.?

Buchanan?s comment is a thinly veiled reference to Lothrop Stoddard?s The Rising Tide of Color which Hsu describes as ?rationalized hatred? presented in a scholarly, gentlemanly, and scientific tone. (This wording that will certainly help him when he comes up for tenure.) As Hsu notes, Stoddard had a doctorate from Harvard
and was a member of many academic associations. His book was published by a major publisher. It was therefore ?precisely the kind of book that a 1920s man of Buchanan?s profile ? wealthy, Ivy League?educated, at once pretentious and intellectually insecure ? might have been expected to bring up in casual conversation.?

Let?s ponder that a bit. The simple reality is that in the year 2009 an Ivy League-educated person, "at once pretentious and intellectually insecure,"  would just as glibly assert the same sort of nonsense as Hsu. To wit:

The coming white minority does not mean that the racial hierarchy of American culture will suddenly become inverted, as in 1995?s White Man?s Burden, an awful thought experiment of a film, starring John Travolta, that envisions an upside-down world in which whites are subjugated to their high-class black oppressors. There will
be dislocations and resentments along the way, but the demographic shifts of the next 40 years are likely to reduce the power of racial hierarchies over everyone?s lives, producing a culture that?s more likely than any before to treat its inhabitants as individuals, rather than members of a caste or identity group.

The fact is that no one can say for certain what multicultural America without a white majority will be like. There is no scientific or historical basis for claims like ?the demographic shifts of the next 40 years are likely to reduce the power of racial hierarchies over everyone?s lives, producing a culture that?s more likely than any before
to treat its inhabitants as individuals, rather than members of a caste or identity group.?

Indeed, there is no evidence at all that we are proceeding to a color blind future. The election results continue to show that white people are coalescing in the Republican Party, while the Democrats are increasingly the party of a non-white soon-to-be majority.

Is it so hard to believe that when this coalition achieves a majority that it will further compromise the interests of whites far beyond contemporary concerns such as immigration policy and affirmative action? Hsu anticipates a colorblind world, but affirmative action means that blacks and other minorities are certainly not treated as
individuals. And it means that whites ? especially white males ? are losing out on opportunities they would have had without these policies and without the massive non-white immigration of the last few decades.

Given the intractability of changing intelligence and other traits required for success in the contemporary economy, it is unlikely that 40 more years of affirmative action will attain the outcomes desired by the minority lobbies. Indeed, in Obama's America, blacks are rioting in Oakland over perceived racial injustices, and from 2002
?2007, black juvenile homicide victims increased 31%, while black juvenile homicide perpetrators increased 43%. Hence,  the reasonable outlook is for a continuing need for affirmative action and for racial activism in these groups, even after whites become a minority.

Whites will also lose out because of large-scale importation of relatively talented immigrants from East Asia. Indeed, as I noted over a decade ago, "The United States is well on the road to being dominated by an Asian technocratic elite and a Jewish business, professional, and media elite."

Hsu shows that there already is considerable anxiety among whites about the future. An advertizing executive says, ?I think white people feel like they?re under siege right now ? like it?s not okay to be white right now, especially if you?re a white male. ... People are stressed out about it. ?We used to be in control! We?re losing
control?? Another says, "There?s a lot of fear and a lot of resentment."

It's hard to see why these feelings won't increase in the future.

A huge problem for white people is lack of intellectual and cultural confidence. Hsu quotes Christian (Stuff White People Like) Lander saying, "I get it: as a straight white male, I?m the worst thing on Earth." A professor comments that for his students "to be white is to be culturally broke. The classic thing white students say when
you ask them to talk about who they are is, ?I don?t have a culture.? They might be privileged, they might be loaded socioeconomically, but they feel bankrupt when it comes to culture ? They feel disadvantaged, and they feel marginalized."

This lack of cultural confidence is no accident. For nearly 100 years whites have been subjected to a culture of critique emanating from the most prestigious academic and media institutions. And, as Hsu points out, the most vibrant and influential aspect of American popular culture is hip-hop?a product of the African American
urban culture.

The only significant group of white people with any cultural confidence centers itself around country music, NASCAR, and the small town values of traditional white America. For this group of whites ? and only this group ? there is  "a racial pride that dares not speak its name, and that defines itself through cultural cues instead?a
suspicion of intellectual elites and city dwellers, a preference for folksiness and plainness of speech (whether real or feigned), and the association of a working-class white minority with 'the real America.'?

This is what I term implicit whiteness ? implicit because explicit assertions of white identity have been banned by the anti-white elites that dominate our politics and culture. It is a culture that, as Hsu notes, "cannot speak its name."

But that implies that the submerged white identity of the white working class and the lack of cultural confidence exhibited by the rest of white America are imposed from outside. Although there may well be characteristics of whites that facilitate this process, this suppression of white identity and interests is certainly not the natural
outcome of modernization or any other force internal to whites as a people. In my opinion, it is the result of the successful erection of a culture of critique in the West dominated by Jewish intellectual and political movements.

The result is that educated, intellectually insecure white people these days are far more likely to believe in the utopian future described by Hsu than in hard and cautious thinking about what the future might have in store for them.

It's worth dwelling a bit on the intellectual insecurity of the whites who mindlessly utter the mantras of multiculturalism that they have soaked up from the school system and from the media. Most people do not have much confidence in their intellectual ability and look to elite opinion to shape their beliefs. As I noted elsewhere,

A critical component of the success of the culture of critique is that it achieved control of the most prestigious and influential institutions of the West, and it became a consensus among the elites, Jewish and non-Jewish alike. Once this happened, it is not surprising that this culture became widely accepted among people of very
different levels of education and among people of different social classes.

Most people are quite insecure about their intellectual ability. But they know that the professors at Harvard, and the editorial page of the New York Times and the Washington Post, and even conservative commentators like Rush Limbaugh and Sean Hannity are all on page when it comes to racial and ethnic issues. This is a
formidable array, to the point that you almost have to be a crank to dissent from this consensus.

I think one of the greatest triumphs of the left has been to get people to believe that people who assert white identity and interests or who make unflattering portrayals of organized Jewish movements are morally degenerate, stupid, and perhaps psychiatrically disturbed. Obviously, all of these adjectives designate low status.

The reality is that the multicultural emperor has no clothes and, because of its support for racial Zionism and the racialism of ethnic minorities in America, it is massively hypocritical to boot. The New York Times, the academic left, and the faux conservatives that dominate elite discourse on race and ethnicity are intellectually
bankrupt and can only remain in power by ruthlessly suppressing or ignoring the scientific findings.

This is particularly a problem for college-educated whites. Like Fitzgerald's Tom Buchanan, such people have a strong need to feel that their ideas are respectable and part of the mainstream. But the respectable mainstream gives them absolutely nothing with which to validate themselves except perhaps the idea that the world
will be a better place when people like them no longer have power. Hsu quotes the pathetic Christian Lander: "?Like, I?m aware of all the horrible crimes that my demographic has done in the world. ... And there?s a bunch of white people who are desperate ? desperate ? to say, ?You know what? My skin?s white, but I?m not one
of the white people who?s destroying the world.??

As a zombie leftist during the 1960s and 1970s, I know what that feeling of desperation is like ? what it's like to be a self-hating white. We must get to the point where college-educated whites proudly and confidently say they are white and that they do not want to become a minority in America.

This reminds me of the recent docudrama Milk, which depicts the life of gay activist Harvey Milk. Milk is sure be nominated for an Oscar as Best Picture because it lovingly illustrates a triumph of the cultural left. But is has an important message that should resonate with the millions of whites who have been deprived of their
confidence and their culture: Be explicit. Just as Harvey Milk advocated being openly gay even in the face of dire consequences, whites need to tell their family and their friends that they have an identity as a white person and believe that whites have legitimate interests as white people. They must accept the consequences
when they are harassed, fired from their jobs, or put in prison for such beliefs. They must run for political office as openly pro-white.

Milk shows that homosexuals were fired from their jobs and arrested for congregating in public. Now it's the Southern Poverty Law Center and the rest of the leftist intellectual and political establishment that harasses and attempts to get people fired. But it's the same situation with the roles reversed. No revolution was ever
accomplished without some martyrs. The revolution that restores the legitimacy of white identity and the legitimacy of white interests will be no exception.

But it is a revolution that is absolutely necessary. The white majority is foolish indeed to entrust its future to a utopian hope that racial and ethnic identifications will disappear and that they won?t continue to influence public policy in ways that compromise the interests of whites.

It does not take an overactive imagination to see that coalitions of minority groups could compromise the interests of formerly dominant whites. We already see numerous examples in which coalitions of minority groups attempt to influence public policy, including immigration policy, against the interests of the whites. Placing
ourselves in a position of vulnerability would be extremely risky, given the deep sense of historical grievance fostered by many ethnic activists and organized ethnic lobbies.

This is especially the case with Jews. Jewish organisations have been unanimous in condemning Western societies, Western traditions, and Christianity, for past crimes against Jews. Similar sentiments are typical of a great many African Americans and Latinos, and especially among the ethnic activists from these groups. The
?God damn America? sermon by President Obama's pastor comes to mind as a recent notorious example.

The precedent of the early decades of the Soviet Union should give pause to anyone who believes that surrendering ethnic hegemony does not carry risks. The Bolshevik revolution had a pronounced ethnic angle: To a very great extent, Jews and other non-Russians ruled over the Russian people, with disastrous
consequences for the Russians and other ethnic groups that were not able to become part of the power structure. Jews formed a hostile elite within this power structure ? as they will in the future white-minority America; Jews were ?Stalin?s willing executioners.?

Two passages from my review of Yuri Slezkine's The Jewish Century seem particularly appropriate here. The first passage reminds me of the many American Jews who adopt a veneer of support for leftist versions of social justice and racial tolerance while nevertheless managing to support racial Zionism and the mass murder,
torture, and incarceration of the Palestinian people in one of the largest prison systems the world has ever seen. Such people may be very different when they become a hostile elite in a white-minority America.

Many of the commentators on Jewish Bolsheviks noted the ?transformation? of Jews [after the Bolshevik Revolution]. In the words of [a] Jewish commentator, G. A. Landau, ?cruelty, sadism, and violence had seemed alien to a nation so far removed from physical activity.? And another Jewish commentator, Ia. A. Bromberg, noted
that:

the formerly oppressed lover of liberty had turned into a tyrant of  ?unheard-of-despotic arbitrariness??. The convinced and unconditional opponent of the death penalty not just for political crimes but for the most heinous offenses, who could not, as it were, watch a chicken being killed, has been transformed outwardly into a
leather-clad person with a revolver and, in fact, lost all human likeness. ...

After the Revolution, ... there was active suppression of any remnants of the older order and their descendants. ... The mass murder of peasants and nationalists was combined with the systematic exclusion of the previously existing non-Jewish middle class. The wife of a Leningrad University professor noted, ?in all the
institutions, only workers and Israelites are admitted; the life of the intelligentsia is very hard? (p. 243). Even at the end of the 1930s, prior to the Russification that accompanied World War II, ?the Russian Federation?was still doing penance for its imperial past while also serving as an example of an ethnicity-free society? (p. 276).
While all other nationalities, including Jews, were allowed and encouraged to keep their ethnic identities, the revolution remained an anti-majoritarian movement.

The difference from the Soviet Union may well be that in white-minority America it will not be workers and Israelites who are favored, but non-whites and Israelites. Whites may dream that they are entering the post-racial utopia imagined by their erstwhile intellectual superiors. But it is quite possible that they are entering into a
racial dystopia of unimaginable cruelty in which whites will be systematically excluded in favor of the new elites recruited from the soon-to-be majority. It's happened before.

Kevin MacDonald is a professor of psychology at California State University?Long Beach.

Permanent URL with hyperlinks:

http://www.theoccidentalobserver.net/articles/MacDonald-Hsu.html

-----------


Should Christians Support Israeli Terrorism in Gaza?

A timely discussion between Rev. Ted Pike and Dr. David Duke, one especially important for the Christians in our audience

http://www.davidduke.com/mp3/dukeradio090122DukeandPikeonGaza.mp3

In this vital discussion, Rev. Pike and Dr. Duke explore the Pro-Israel attitude of some Christian evangelical organizations, and why their position not only goes directly against Christian morality and decency,  but actually is directly opposite of that expressed by Christian Scriptures. Today, Many Christians are instructed that Jews
and today?s Israel has a special covenant? with God. In fact, the New Testament in the clearest of language states that the Jews ?continued not in my covenant, and I considered them not, saith the Lord.? Here?s the quote that Christians aren?t supposed to notice.:

8:10 Not according to the covenant that I made with their fathers, in the day when I took them by the hand out of the land of Egypt; because they continued not in my covenant, and I regarded them not, saith the Lord. (Hebrews 8:10)

They also don?t seem to notice that a 2000 year old Judaic war against Christianity that has been waged since time of Jesus Christ and still goes on today with the most powerful Jewish organizations attempting to destroy European and American traditions, that has even become a war on our Christmas traditions.

Dr. Duke and Ted Pike also speak about how over a hundred thousand Christian Palestinians have suffered with their families from anti-Christian Israel! Christian support of Israel has resulted in the very birthplace of Jesus Christ, go from 90 percent Palestinian Christians to 35 percent today because of Israeli terror and
occupation. They ask, ?How could any Christian in good conscience support the anti-Christian state of Israel, bombing the homes, killing and maiming, torturing and oppressing fellow Christian men, women and children??

This is a vital show for every Christian reader and listener of DavidDuke.com. Next time, you hear someone say, ?God tells us that we must support Israel? you will have the clear Christian answer that just the opposite is true!

For documentation on this be sure to read some of the well-footnoted, sample chapters of Jewish Supremacism and My Awakening.

Source :
http://www.davidduke.com/general/should-christians-support-israeli-terrorism-in-gaza_7282.html


-------------------------------------

You or someone using your email adress is currently subscribed to the Lawrence Auster
Newletter. If you wish to unsubscribe from our mailing list, please let us know by calling to 1 212 865 1284

Thanks,

Lawrence Auster,
238 W 101 St Apt. 3B
New York, NY  10025
Contact: lawrence.auster at att.net
-------------------------------------


From ryan at bluewatersys.com  Sat Jan 24 03:37:24 2009
From: ryan at bluewatersys.com (Ryan Mallon)
Date: Sat, 24 Jan 2009 21:37:24 +1300
Subject: [PATCH] libertas: fix CF firmware loading for some cards
In-Reply-To: <1232729733.2577.13.camel@localhost.localdomain>
References: <1232729733.2577.13.camel@localhost.localdomain>
Message-ID: <497AD344.5080900@bluewatersys.com>

Dan Williams wrote:
> if_cs_poll_while_fw_download() returned the number of iterations
> remaining on success, which in turn got returned as the value from
> if_cs_prog_real() and if_cs_prog_helper().  But since if_cs_probe()
> interprets non-zero return values from firmware load functions as an
> error, this sometimes caused spurious firmware load failures.
> 
> Signed-off-by: Dan Williams <dcbw at redhat.com>
> ---
> 
> diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
> index 842a08d..8f8934a 100644
> --- a/drivers/net/wireless/libertas/if_cs.c
> +++ b/drivers/net/wireless/libertas/if_cs.c
> @@ -151,7 +151,7 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
>  	for (i = 0; i < 100000; i++) {
>  		u8 val = if_cs_read8(card, addr);
>  		if (val == reg)
> -			return i;
> +			return 0;
>  		udelay(5);
>  	}
>  	return -ETIME;
> 
> 

Hmmm, I posted this same patch here a couple of months ago
(http://lists.infradead.org/pipermail/libertas-dev/2008-October/002019.html),
did I get something wrong in the submission process, or did it just get
lost in the woodwork? Anyway:

Tested-by: Ryan Mallon <ryan at bluewatersys.com>
Acked-by: Ryan Mallon <ryan at bluewatersys.com>

~Ryan



From dcbw at redhat.com  Fri Jan 23 14:54:22 2009
From: dcbw at redhat.com (Dan Williams)
Date: Fri, 23 Jan 2009 14:54:22 -0500
Subject: [PATCH] libertas: fix CF firmware loading for some cards
In-Reply-To: <497AD344.5080900@bluewatersys.com>
References: <1232729733.2577.13.camel@localhost.localdomain>
	<497AD344.5080900@bluewatersys.com>
Message-ID: <1232740462.2577.48.camel@localhost.localdomain>

On Sat, 2009-01-24 at 21:37 +1300, Ryan Mallon wrote:
> Dan Williams wrote:
> > if_cs_poll_while_fw_download() returned the number of iterations
> > remaining on success, which in turn got returned as the value from
> > if_cs_prog_real() and if_cs_prog_helper().  But since if_cs_probe()
> > interprets non-zero return values from firmware load functions as an
> > error, this sometimes caused spurious firmware load failures.
> > 
> > Signed-off-by: Dan Williams <dcbw at redhat.com>
> > ---
> > 
> > diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
> > index 842a08d..8f8934a 100644
> > --- a/drivers/net/wireless/libertas/if_cs.c
> > +++ b/drivers/net/wireless/libertas/if_cs.c
> > @@ -151,7 +151,7 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r
> >  	for (i = 0; i < 100000; i++) {
> >  		u8 val = if_cs_read8(card, addr);
> >  		if (val == reg)
> > -			return i;
> > +			return 0;
> >  		udelay(5);
> >  	}
> >  	return -ETIME;
> > 
> > 
> 
> Hmmm, I posted this same patch here a couple of months ago
> (http://lists.infradead.org/pipermail/libertas-dev/2008-October/002019.html),
> did I get something wrong in the submission process, or did it just get
> lost in the woodwork? Anyway:

Apparently I didn't read enough down that thread to find the second
patch; I only found the one that changed if_cs_prog_helper() and
if_cs_prog_real().  My mistake, this patch is yours.

John; when you apply, please credit Ryan.

Dan




From svenmauren at vr-web.de  Fri Jan 23 16:11:41 2009
From: svenmauren at vr-web.de (Sven Barth)
Date: Fri, 23 Jan 2009 22:11:41 +0100
Subject: Problems with SD8686 SDIO on HTC Shift
Message-ID: <497A328D.90502@vr-web.de>

Hello together!

I'm currently trying to get Linux running on my HTC Shift (a UMPC with 
an Intel CPU). It has a Marvell SD8686 wifi module connected with SDIO. 
I'm currently using Arch Linux with Kernel 2.6.28, compat-wireless from 
01/16/2006 and the firmware from linux-firmware git. Every time I 
modprobe the libertas modules I get a timeout when the command 0x001e 
(CMD_802_11_RF_TX_POWER) should be send to the wifi-module. After 
"excessive timeouts" the module "coredumps" (part of dmesg from modprobe 
of libertas till end is attached). This problem happens with both 
firmware versions (v8 & v9) from linux-firmware.

According to this guide 
http://pof.eslack.org/blog/2008/04/14/linux-on-htc-shift/ the wifi 
module was at least working with the old driver, which was used around 
kernel 2.6.19 (Kubuntu 8.04).

It would be really nice to get wifi up and running, cause without it, I 
can't really use Linux in every day life on the Shift (so I'd have to 
stick with power-consumingVista ;) ).

Thank you in advance for your help and support.

Regards,
Sven Barth
-------------- next part --------------
mmc1: new SDIO card at address 0001
lib80211: common routines for IEEE802.11 drivers
lib80211_crypt: registered algorithm 'NULL'
libertas_sdio: Libertas SDIO driver
libertas_sdio: Copyright Pierre Ossman
libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin
libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin
libertas: f3961cc6, fw 9.70.3p18, cap 0x00000303
libertas: command 0x001e timed out
libertas: requeueing command 0x001e due to timeout (#1)
libertas: command 0x001e timed out
libertas: requeueing command 0x001e due to timeout (#2)
libertas: command 0x001e timed out
libertas: requeueing command 0x001e due to timeout (#3)
mmc1: Timeout waiting for hardware interrupt.
sdhci: ============== REGISTER DUMP ==============
sdhci: Sys addr: 0x3385c6e8 | Version:  0x00000111
sdhci: Blk size: 0x00007014 | Blk cnt:  0x00000001
sdhci: Argument: 0x92000014 | Trn mode: 0x00000003
sdhci: Present:  0x01f70506 | Host ctl: 0x00000003
sdhci: Power:    0x0000000f | Blk gap:  0x00000000
sdhci: Wake-up:  0x00000000 | Clock:    0x00000007
sdhci: Timeout:  0x0000000c | Int stat: 0x00000000
sdhci: Int enab: 0x00ff01fb | Sig enab: 0x00ff01fb
sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
sdhci: Caps:     0x01e011a1 | Max curr: 0x00000080
sdhci: ===========================================
libertas: command 0x001e timed out
libertas: Excessive timeouts submitting command 0x001e
libertas: PREP_CMD: command 0x001e failed: -110
------------[ cut here ]------------
kernel BUG at mm/slub.c:2743!
invalid opcode: 0000 [#1] PREEMPT SMP 
last sysfs file: /sys/class/power_supply/BAT0/charge_full
Modules linked in: libertas_sdio(+) libertas lib80211 mmc_block i915 drm ipv6 fuse uvcvideo compat_ioctl32 videodev v4l1_compat psmouse i2c_i801 pcspkr iTCO_wdt iTCO_vendor_support i2c_core serio_raw sdhci_pci sdhci sg mmc_core video output uhci_hcd ehci_hcd usbcore intel_agp agpgart thermal snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device evdev processor fan joydev button battery ac htcpen snd_hda_intel snd_hwdep snd_pcm_oss snd_pcm snd_timer snd_page_alloc snd_mixer_oss snd soundcore rtc_cmos rtc_core rtc_lib ext3 jbd mbcache sd_mod ata_piix ata_generic pata_acpi libata scsi_mod

Pid: 16540, comm: modprobe Not tainted (2.6.28-ARCH #1) Shift
EIP: 0060:[<c018efaa>] EFLAGS: 00010246 CPU: 0
EIP is at kfree+0xda/0xe0
EAX: 40040000 EBX: f39c0500 ECX: 00000058 EDX: c1673800
ESI: f39c0500 EDI: 00000000 EBP: 00000000 ESP: f3961d00
 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process modprobe (pid: 16540, ti=f3960000 task=f6a36800 task.ti=f3960000)
Stack:
 00000000 c017132d f3980000 f39c0500 00000000 00000000 f86266ac f3961d60
 f8626f8c f3961d5c 00000038 00000010 f390af44 f3961d50 f68e0600 00000000
 f82ef99c f8a9fc90 f6a3e000 00000000 f39630c0 00000000 00000000 0000000b
Call Trace:
 [<c017132d>] put_page+0x5d/0x110
 [<f86266ac>] if_sdio_probe+0x58c/0x870 [libertas_sdio]
 [<f823746f>] sdio_bus_probe+0x9f/0xc0 [mmc_core]
 [<c027e756>] driver_probe_device+0x86/0x1a0
 [<c011ff45>] default_spin_lock_flags+0x5/0x10
 [<c032bdce>] _spin_lock_irqsave+0x3e/0x60
 [<c027e8f9>] __driver_attach+0x89/0x90
 [<f8237370>] sdio_bus_remove+0x0/0x60 [mmc_core]
 [<c027e084>] bus_for_each_dev+0x44/0x70
 [<f8237370>] sdio_bus_remove+0x0/0x60 [mmc_core]
 [<c027e5e6>] driver_attach+0x16/0x20
 [<c027e870>] __driver_attach+0x0/0x90
 [<c027da17>] bus_add_driver+0x1a7/0x220
 [<f8237370>] sdio_bus_remove+0x0/0x60 [mmc_core]
 [<c027ea8c>] driver_register+0x5c/0x130
 [<c0329112>] printk+0x17/0x1d
 [<f827e000>] if_sdio_init_module+0x0/0x28 [libertas_sdio]
 [<c0101126>] do_one_initcall+0x36/0x1c0
 [<c0182630>] __vunmap+0xb0/0xe0
 [<c0158337>] load_module+0x1577/0x1950
 [<f8237d80>] sdio_writeb+0x0/0x50 [mmc_core]
 [<c015885b>] sys_init_module+0x8b/0x1b0
 [<c0103f13>] sysenter_do_call+0x12/0x33
Code: 8b 01 8b 51 0c 89 04 93 89 19 eb c2 f6 c4 60 74 1a 8b 5c 24 08 89 d0 8b 74 24 0c 8b 7c 24 10 8b 6c 24 14 83 c4 18 e9 26 23 fe ff <0f> 0b eb fe 66 90 83 e8 60 e9 18 ff ff ff 90 8d b4 26 00 00 00 
EIP: [<c018efaa>] kfree+0xda/0xe0 SS:ESP 0068:f3961d00
---[ end trace f44bcfd847cbebcd ]---

From shawn.t.rutledge at gmail.com  Fri Jan 23 17:44:54 2009
From: shawn.t.rutledge at gmail.com (Shawn Rutledge)
Date: Fri, 23 Jan 2009 15:44:54 -0700
Subject: SDIO Marvel 8686 card
Message-ID: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>

I was googling a couple days ago to see whether there is any
open-source SDIO wifi card.  I found this:

http://bsdimp.blogspot.com/2007/05/found-cheap-sdio-80211b-card.html

and some other clue somewhere that there might be an open-source
driver; and then found some on ebay:

http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=370146807227

so I ordered a couple.  Now I'm trying to find the firmware,
sd8385_helper.bin and sd8385.bin.

http://wireless.kernel.org/en/users/Drivers/libertas

says it can be gotten from the Marvell site somewhere.  Any ideas more
specifically?  Lemme guess... it's not redistributable?

This page

http://wiki.openezx.org/WLAN

says it "comes with the 2.4 code"... hmm would that be the GPL release
from Motorola, happened to include the firmware?

Hmm looks like the Blackfin Linux project is using that chip too:

http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_id=328&tracker_item_id=4214


From andrey at cozybit.com  Fri Jan 23 17:52:40 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Fri, 23 Jan 2009 14:52:40 -0800
Subject: SDIO Marvel 8686 card
In-Reply-To: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>
References: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>
Message-ID: <45e8e6c40901231452r23e133aega7182d48d4981ded@mail.gmail.com>

To download the '8686 firmware, download Marvell's driver from their
site.  Click "drivers", select "Fedora / 2.6 kernel" from the OS list,
and download the '8686 SYSKIT driver.  The firmware lives in its own
directory in the .zip file.  Dan Williams also recently posted a note
saying that the firmware for these cards is coming to the
linux-firmware tree (that should include the '8385 FW).

On Fri, Jan 23, 2009 at 2:44 PM, Shawn Rutledge
<shawn.t.rutledge at gmail.com> wrote:
> I was googling a couple days ago to see whether there is any
> open-source SDIO wifi card.  I found this:
>
> http://bsdimp.blogspot.com/2007/05/found-cheap-sdio-80211b-card.html
>
> and some other clue somewhere that there might be an open-source
> driver; and then found some on ebay:
>
> http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=370146807227
>
> so I ordered a couple.  Now I'm trying to find the firmware,
> sd8385_helper.bin and sd8385.bin.
>
> http://wireless.kernel.org/en/users/Drivers/libertas
>
> says it can be gotten from the Marvell site somewhere.  Any ideas more
> specifically?  Lemme guess... it's not redistributable?
>
> This page
>
> http://wiki.openezx.org/WLAN
>
> says it "comes with the 2.4 code"... hmm would that be the GPL release
> from Motorola, happened to include the firmware?
>
> Hmm looks like the Blackfin Linux project is using that chip too:
>
> http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_id=328&tracker_item_id=4214
>
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev
>


From dcbw at redhat.com  Fri Jan 23 17:51:43 2009
From: dcbw at redhat.com (Dan Williams)
Date: Fri, 23 Jan 2009 17:51:43 -0500
Subject: Problems with SD8686 SDIO on HTC Shift
In-Reply-To: <497A328D.90502@vr-web.de>
References: <497A328D.90502@vr-web.de>
Message-ID: <1232751103.447.6.camel@localhost.localdomain>

On Fri, 2009-01-23 at 22:11 +0100, Sven Barth wrote:
> Hello together!
> 
> I'm currently trying to get Linux running on my HTC Shift (a UMPC with 
> an Intel CPU). It has a Marvell SD8686 wifi module connected with SDIO. 
> I'm currently using Arch Linux with Kernel 2.6.28, compat-wireless from 
> 01/16/2006 and the firmware from linux-firmware git. Every time I 

^^^ I hope you mean 01/16/2008 :)

What SDIO controller is in these things?

> modprobe the libertas modules I get a timeout when the command 0x001e 
> (CMD_802_11_RF_TX_POWER) should be send to the wifi-module. After 
> "excessive timeouts" the module "coredumps" (part of dmesg from modprobe 
> of libertas till end is attached). This problem happens with both 
> firmware versions (v8 & v9) from linux-firmware.

Can you try commenting out the part that gets TX power in
lbs_setup_firmware() in main.c and see how that proceeds?

Dan

> According to this guide 
> http://pof.eslack.org/blog/2008/04/14/linux-on-htc-shift/ the wifi 
> module was at least working with the old driver, which was used around 
> kernel 2.6.19 (Kubuntu 8.04).
> 
> It would be really nice to get wifi up and running, cause without it, I 
> can't really use Linux in every day life on the Shift (so I'd have to 
> stick with power-consumingVista ;) ).
> 
> Thank you in advance for your help and support.
> 
> Regards,
> Sven Barth
> plain text document attachment (dmesg-htc-shift)
> mmc1: new SDIO card at address 0001
> lib80211: common routines for IEEE802.11 drivers
> lib80211_crypt: registered algorithm 'NULL'
> libertas_sdio: Libertas SDIO driver
> libertas_sdio: Copyright Pierre Ossman
> libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin
> libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin
> libertas: f3961cc6, fw 9.70.3p18, cap 0x00000303
> libertas: command 0x001e timed out
> libertas: requeueing command 0x001e due to timeout (#1)
> libertas: command 0x001e timed out
> libertas: requeueing command 0x001e due to timeout (#2)
> libertas: command 0x001e timed out
> libertas: requeueing command 0x001e due to timeout (#3)
> mmc1: Timeout waiting for hardware interrupt.
> sdhci: ============== REGISTER DUMP ==============
> sdhci: Sys addr: 0x3385c6e8 | Version:  0x00000111
> sdhci: Blk size: 0x00007014 | Blk cnt:  0x00000001
> sdhci: Argument: 0x92000014 | Trn mode: 0x00000003
> sdhci: Present:  0x01f70506 | Host ctl: 0x00000003
> sdhci: Power:    0x0000000f | Blk gap:  0x00000000
> sdhci: Wake-up:  0x00000000 | Clock:    0x00000007
> sdhci: Timeout:  0x0000000c | Int stat: 0x00000000
> sdhci: Int enab: 0x00ff01fb | Sig enab: 0x00ff01fb
> sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
> sdhci: Caps:     0x01e011a1 | Max curr: 0x00000080
> sdhci: ===========================================
> libertas: command 0x001e timed out
> libertas: Excessive timeouts submitting command 0x001e
> libertas: PREP_CMD: command 0x001e failed: -110
> ------------[ cut here ]------------
> kernel BUG at mm/slub.c:2743!
> invalid opcode: 0000 [#1] PREEMPT SMP 
> last sysfs file: /sys/class/power_supply/BAT0/charge_full
> Modules linked in: libertas_sdio(+) libertas lib80211 mmc_block i915 drm ipv6 fuse uvcvideo compat_ioctl32 videodev v4l1_compat psmouse i2c_i801 pcspkr iTCO_wdt iTCO_vendor_support i2c_core serio_raw sdhci_pci sdhci sg mmc_core video output uhci_hcd ehci_hcd usbcore intel_agp agpgart thermal snd_seq_oss snd_seq_midi_event snd_seq snd_seq_device evdev processor fan joydev button battery ac htcpen snd_hda_intel snd_hwdep snd_pcm_oss snd_pcm snd_timer snd_page_alloc snd_mixer_oss snd soundcore rtc_cmos rtc_core rtc_lib ext3 jbd mbcache sd_mod ata_piix ata_generic pata_acpi libata scsi_mod
> 
> Pid: 16540, comm: modprobe Not tainted (2.6.28-ARCH #1) Shift
> EIP: 0060:[<c018efaa>] EFLAGS: 00010246 CPU: 0
> EIP is at kfree+0xda/0xe0
> EAX: 40040000 EBX: f39c0500 ECX: 00000058 EDX: c1673800
> ESI: f39c0500 EDI: 00000000 EBP: 00000000 ESP: f3961d00
>  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
> Process modprobe (pid: 16540, ti=f3960000 task=f6a36800 task.ti=f3960000)
> Stack:
>  00000000 c017132d f3980000 f39c0500 00000000 00000000 f86266ac f3961d60
>  f8626f8c f3961d5c 00000038 00000010 f390af44 f3961d50 f68e0600 00000000
>  f82ef99c f8a9fc90 f6a3e000 00000000 f39630c0 00000000 00000000 0000000b
> Call Trace:
>  [<c017132d>] put_page+0x5d/0x110
>  [<f86266ac>] if_sdio_probe+0x58c/0x870 [libertas_sdio]
>  [<f823746f>] sdio_bus_probe+0x9f/0xc0 [mmc_core]
>  [<c027e756>] driver_probe_device+0x86/0x1a0
>  [<c011ff45>] default_spin_lock_flags+0x5/0x10
>  [<c032bdce>] _spin_lock_irqsave+0x3e/0x60
>  [<c027e8f9>] __driver_attach+0x89/0x90
>  [<f8237370>] sdio_bus_remove+0x0/0x60 [mmc_core]
>  [<c027e084>] bus_for_each_dev+0x44/0x70
>  [<f8237370>] sdio_bus_remove+0x0/0x60 [mmc_core]
>  [<c027e5e6>] driver_attach+0x16/0x20
>  [<c027e870>] __driver_attach+0x0/0x90
>  [<c027da17>] bus_add_driver+0x1a7/0x220
>  [<f8237370>] sdio_bus_remove+0x0/0x60 [mmc_core]
>  [<c027ea8c>] driver_register+0x5c/0x130
>  [<c0329112>] printk+0x17/0x1d
>  [<f827e000>] if_sdio_init_module+0x0/0x28 [libertas_sdio]
>  [<c0101126>] do_one_initcall+0x36/0x1c0
>  [<c0182630>] __vunmap+0xb0/0xe0
>  [<c0158337>] load_module+0x1577/0x1950
>  [<f8237d80>] sdio_writeb+0x0/0x50 [mmc_core]
>  [<c015885b>] sys_init_module+0x8b/0x1b0
>  [<c0103f13>] sysenter_do_call+0x12/0x33
> Code: 8b 01 8b 51 0c 89 04 93 89 19 eb c2 f6 c4 60 74 1a 8b 5c 24 08 89 d0 8b 74 24 0c 8b 7c 24 10 8b 6c 24 14 83 c4 18 e9 26 23 fe ff <0f> 0b eb fe 66 90 83 e8 60 e9 18 ff ff ff 90 8d b4 26 00 00 00 
> EIP: [<c018efaa>] kfree+0xda/0xe0 SS:ESP 0068:f3961d00
> ---[ end trace f44bcfd847cbebcd ]---
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From dcbw at redhat.com  Fri Jan 23 18:14:48 2009
From: dcbw at redhat.com (Dan Williams)
Date: Fri, 23 Jan 2009 18:14:48 -0500
Subject: SDIO Marvel 8686 card
In-Reply-To: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>
References: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>
Message-ID: <1232752489.447.20.camel@173-115-86-193.pools.spcsdns.net>

On Fri, 2009-01-23 at 15:44 -0700, Shawn Rutledge wrote:
> I was googling a couple days ago to see whether there is any
> open-source SDIO wifi card.  I found this:
> 
> http://bsdimp.blogspot.com/2007/05/found-cheap-sdio-80211b-card.html

The 8686 is actually an 802.11 b/g part.  I'd be quite surprised to see
that card advertised as an 802.11b-only part.  But anyway...  I've never
seen a consumer-level 8686 SDIO card.

> and some other clue somewhere that there might be an open-source
> driver; and then found some on ebay:
> 
> http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=370146807227

Yeah, looking up the FCC ID shows it's a Marvell chip, but the image is
too fuzzy to figure out what actual part # and hardware revision it is.

In any case, 8385 SDIO should work with a little effort.  I'll try to
grab a few of these and fix up the driver.  More testing on your side
would be great too.

> so I ordered a couple.  Now I'm trying to find the firmware,
> sd8385_helper.bin and sd8385.bin.
> 
> http://wireless.kernel.org/en/users/Drivers/libertas

> says it can be gotten from the Marvell site somewhere.  Any ideas more
> specifically?  Lemme guess... it's not redistributable?

The firmware is now redistributable and can be found here:

http://git.kernel.org/?p=linux/kernel/git/dwmw2/linux-firmware.git;a=tree;f=libertas;h=73683868101e26d187baaa7bd6685d1450d34f7c;hb=HEAD

Dan




From dcbw at redhat.com  Fri Jan 23 18:18:28 2009
From: dcbw at redhat.com (Dan Williams)
Date: Fri, 23 Jan 2009 18:18:28 -0500
Subject: SDIO Marvel 8686 card
In-Reply-To: <45e8e6c40901231452r23e133aega7182d48d4981ded@mail.gmail.com>
References: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>
	<45e8e6c40901231452r23e133aega7182d48d4981ded@mail.gmail.com>
Message-ID: <1232752708.447.22.camel@173-115-86-193.pools.spcsdns.net>

On Fri, 2009-01-23 at 14:52 -0800, Andrey Yurovsky wrote:
> To download the '8686 firmware, download Marvell's driver from their
> site.  Click "drivers", select "Fedora / 2.6 kernel" from the OS list,
> and download the '8686 SYSKIT driver.  The firmware lives in its own
> directory in the .zip file.  Dan Williams also recently posted a note
> saying that the firmware for these cards is coming to the
> linux-firmware tree (that should include the '8385 FW).

It already got sucked in...

Dan


> On Fri, Jan 23, 2009 at 2:44 PM, Shawn Rutledge
> <shawn.t.rutledge at gmail.com> wrote:
> > I was googling a couple days ago to see whether there is any
> > open-source SDIO wifi card.  I found this:
> >
> > http://bsdimp.blogspot.com/2007/05/found-cheap-sdio-80211b-card.html
> >
> > and some other clue somewhere that there might be an open-source
> > driver; and then found some on ebay:
> >
> > http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=370146807227
> >
> > so I ordered a couple.  Now I'm trying to find the firmware,
> > sd8385_helper.bin and sd8385.bin.
> >
> > http://wireless.kernel.org/en/users/Drivers/libertas
> >
> > says it can be gotten from the Marvell site somewhere.  Any ideas more
> > specifically?  Lemme guess... it's not redistributable?
> >
> > This page
> >
> > http://wiki.openezx.org/WLAN
> >
> > says it "comes with the 2.4 code"... hmm would that be the GPL release
> > from Motorola, happened to include the firmware?
> >
> > Hmm looks like the Blackfin Linux project is using that chip too:
> >
> > http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_id=328&tracker_item_id=4214
> >
> > _______________________________________________
> > libertas-dev mailing list
> > libertas-dev at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/libertas-dev
> >
> 
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From shawn.t.rutledge at gmail.com  Fri Jan 23 18:20:40 2009
From: shawn.t.rutledge at gmail.com (Shawn Rutledge)
Date: Fri, 23 Jan 2009 16:20:40 -0700
Subject: SDIO Marvel 8686 card
In-Reply-To: <1232752489.447.20.camel@173-115-86-193.pools.spcsdns.net>
References: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>
	<1232752489.447.20.camel@173-115-86-193.pools.spcsdns.net>
Message-ID: <d9a6586e0901231520x7d546f29o4dd9458410ee99be@mail.gmail.com>

On Fri, Jan 23, 2009 at 4:14 PM, Dan Williams <dcbw at redhat.com> wrote:
> On Fri, 2009-01-23 at 15:44 -0700, Shawn Rutledge wrote:
>> I was googling a couple days ago to see whether there is any
>> open-source SDIO wifi card.  I found this:
>>
>> http://bsdimp.blogspot.com/2007/05/found-cheap-sdio-80211b-card.html
>
> The 8686 is actually an 802.11 b/g part.  I'd be quite surprised to see
> that card advertised as an 802.11b-only part.  But anyway...  I've never
> seen a consumer-level 8686 SDIO card.

OK that makes sense.

>
>> and some other clue somewhere that there might be an open-source
>> driver; and then found some on ebay:
>>
>> http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=370146807227
>
> Yeah, looking up the FCC ID shows it's a Marvell chip, but the image is
> too fuzzy to figure out what actual part # and hardware revision it is.

On the front:
FCC ID:PA4050449
IC ID:1016B-050449

001NYDA1546
001GZDA1260
ETC094LPD0184

On the back:
R-LARN-05-0103
PN: 3F8508
there is a MAC and some numbers underneath:
8810 5Z00 01

> In any case, 8385 SDIO should work with a little effort.  I'll try to
> grab a few of these and fix up the driver.  More testing on your side
> would be great too.

OK cool.


From shawn.t.rutledge at gmail.com  Fri Jan 23 18:32:24 2009
From: shawn.t.rutledge at gmail.com (Shawn Rutledge)
Date: Fri, 23 Jan 2009 16:32:24 -0700
Subject: SDIO Marvel 8686 card
In-Reply-To: <45e8e6c40901231452r23e133aega7182d48d4981ded@mail.gmail.com>
References: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>
	<45e8e6c40901231452r23e133aega7182d48d4981ded@mail.gmail.com>
Message-ID: <d9a6586e0901231532s294b8430r22aed27ad1c10ea2@mail.gmail.com>

On Fri, Jan 23, 2009 at 3:52 PM, Andrey Yurovsky <andrey at cozybit.com> wrote:
> To download the '8686 firmware, download Marvell's driver from their
> site.  Click "drivers", select "Fedora / 2.6 kernel" from the OS list,
> and download the '8686 SYSKIT driver.  The firmware lives in its own
> directory in the .zip file.  Dan Williams also recently posted a note
> saying that the firmware for these cards is coming to the
> linux-firmware tree (that should include the '8385 FW).

Thanks that was too easy.  :-)

Earlier I was getting an error that it did not recognize the type of
card, so I modified if_sdio.c like this:

static int if_sdio_probe(struct sdio_func *func,
                const struct sdio_device_id *id)
{
        struct if_sdio_card *card;
        struct lbs_private *priv;
        int ret, i;
        unsigned int model;
        struct if_sdio_packet *packet;

        lbs_deb_enter(LBS_DEB_SDIO);

        for (i = 0;i < func->card->num_info;i++) {
                lbs_pr_err("looking at func->card->info[%d]: %s\n", i,
func->card->info[i]);
                if (sscanf(func->card->info[i],
                                "802.11 SDIO ID: %x", &model) == 1)
                        break;
                if (sscanf(func->card->info[i],
                                "ID: %x", &model) == 1)
                        break;
               if (!strcmp(func->card->info[i], "Kodak WiFi card 3F8508")) {
                        lbs_pr_err("Identified Kodak card\n");
                       model = 4;
                       break;
               }
               if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
                       model = 4;
                       break;
               }
        }


I installed the firmware from the Marvell tarball (renamed the files):

[acer][04:02:56 PM] ll /lib/firmware/
....
-rw-r--r--  1 root root   2516 2009-01-23 16:00 sd8385_helper.bin
-rw-r--r--  1 root root 122916 2009-01-23 16:00 sd8686.bin
....

and I think udev's firmware.sh script finds it, but I have messages like this:

Jan 23 16:01:28 [kernel] libertas: looking at func->card->info[0]:
Eastman Kodak Company
Jan 23 16:01:28 [kernel] libertas: looking at func->card->info[1]:
Kodak WiFi card 3F8508
Jan 23 16:01:28 [kernel] libertas: failed to load helper firmware
Jan 23 16:01:28 [kernel] libertas_sdio: probe of mmc0:0001:1 failed
with error -84

I'm using Gentoo's version of kernel 2.6.27 on an Acer laptop that has
an SD slot.


From dcbw at redhat.com  Fri Jan 23 18:34:02 2009
From: dcbw at redhat.com (Dan Williams)
Date: Fri, 23 Jan 2009 18:34:02 -0500
Subject: SDIO Marvel 8686 card
In-Reply-To: <d9a6586e0901231520x7d546f29o4dd9458410ee99be@mail.gmail.com>
References: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>
	<1232752489.447.20.camel@173-115-86-193.pools.spcsdns.net>
	<d9a6586e0901231520x7d546f29o4dd9458410ee99be@mail.gmail.com>
Message-ID: <1232753642.447.27.camel@173-115-86-193.pools.spcsdns.net>

On Fri, 2009-01-23 at 16:20 -0700, Shawn Rutledge wrote:
> On Fri, Jan 23, 2009 at 4:14 PM, Dan Williams <dcbw at redhat.com> wrote:
> > On Fri, 2009-01-23 at 15:44 -0700, Shawn Rutledge wrote:
> >> I was googling a couple days ago to see whether there is any
> >> open-source SDIO wifi card.  I found this:
> >>
> >> http://bsdimp.blogspot.com/2007/05/found-cheap-sdio-80211b-card.html
> >
> > The 8686 is actually an 802.11 b/g part.  I'd be quite surprised to see
> > that card advertised as an 802.11b-only part.  But anyway...  I've never
> > seen a consumer-level 8686 SDIO card.
> 
> OK that makes sense.
> 
> >
> >> and some other clue somewhere that there might be an open-source
> >> driver; and then found some on ebay:
> >>
> >> http://cgi.ebay.com/ws/eBayISAPI.dll?ViewItem&item=370146807227
> >
> > Yeah, looking up the FCC ID shows it's a Marvell chip, but the image is
> > too fuzzy to figure out what actual part # and hardware revision it is.
> 
> On the front:
> FCC ID:PA4050449
> IC ID:1016B-050449

Ah; sorry, I meant the image submitted to the FCC.  I'm less convinced
that the thing is an 8385 now, since there's conflicting information out
there.  The picture here:

http://i31.photobucket.com/albums/c381/Funkus/KodakCard.jpg

talks about the chip being an 88w8010, but the 8010 is the RF
transceiver only, and not the MAC itself.  There's got to be more to the
card...

> 001NYDA1546
> 001GZDA1260
> ETC094LPD0184
> 
> On the back:
> R-LARN-05-0103
> PN: 3F8508
> there is a MAC and some numbers underneath:
> 8810 5Z00 01
> 
> > In any case, 8385 SDIO should work with a little effort.  I'll try to
> > grab a few of these and fix up the driver.  More testing on your side
> > would be great too.
> 
> OK cool.

So if it really *is* an 88w8385 inside, then it's hopeful that it'll be
supported.  But if it's something before that, probably less likely,
depending on the firmware version it requires.

dan




From dcbw at redhat.com  Fri Jan 23 18:43:30 2009
From: dcbw at redhat.com (Dan Williams)
Date: Fri, 23 Jan 2009 18:43:30 -0500
Subject: SDIO Marvel 8686 card
In-Reply-To: <d9a6586e0901231532s294b8430r22aed27ad1c10ea2@mail.gmail.com>
References: <d9a6586e0901231444m52a3ffa5vddf9ff55d0c64913@mail.gmail.com>
	<45e8e6c40901231452r23e133aega7182d48d4981ded@mail.gmail.com>
	<d9a6586e0901231532s294b8430r22aed27ad1c10ea2@mail.gmail.com>
Message-ID: <1232754210.447.30.camel@173-115-86-193.pools.spcsdns.net>

On Fri, 2009-01-23 at 16:32 -0700, Shawn Rutledge wrote:
> On Fri, Jan 23, 2009 at 3:52 PM, Andrey Yurovsky <andrey at cozybit.com> wrote:
> > To download the '8686 firmware, download Marvell's driver from their
> > site.  Click "drivers", select "Fedora / 2.6 kernel" from the OS list,
> > and download the '8686 SYSKIT driver.  The firmware lives in its own
> > directory in the .zip file.  Dan Williams also recently posted a note
> > saying that the firmware for these cards is coming to the
> > linux-firmware tree (that should include the '8385 FW).
> 
> Thanks that was too easy.  :-)
> 
> Earlier I was getting an error that it did not recognize the type of
> card, so I modified if_sdio.c like this:
> 
> static int if_sdio_probe(struct sdio_func *func,
>                 const struct sdio_device_id *id)
> {
>         struct if_sdio_card *card;
>         struct lbs_private *priv;
>         int ret, i;
>         unsigned int model;
>         struct if_sdio_packet *packet;
> 
>         lbs_deb_enter(LBS_DEB_SDIO);
> 
>         for (i = 0;i < func->card->num_info;i++) {
>                 lbs_pr_err("looking at func->card->info[%d]: %s\n", i,
> func->card->info[i]);
>                 if (sscanf(func->card->info[i],
>                                 "802.11 SDIO ID: %x", &model) == 1)
>                         break;
>                 if (sscanf(func->card->info[i],
>                                 "ID: %x", &model) == 1)
>                         break;
>                if (!strcmp(func->card->info[i], "Kodak WiFi card 3F8508")) {
>                         lbs_pr_err("Identified Kodak card\n");
>                        model = 4;
>                        break;
>                }
>                if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
>                        model = 4;
>                        break;
>                }
>         }
> 
> 
> I installed the firmware from the Marvell tarball (renamed the files):
> 
> [acer][04:02:56 PM] ll /lib/firmware/
> ....
> -rw-r--r--  1 root root   2516 2009-01-23 16:00 sd8385_helper.bin
> -rw-r--r--  1 root root 122916 2009-01-23 16:00 sd8686.bin

The firmware needs to be matched, so use sd8385_helper.bin and
sd8385.bin together.

If you do IRC, join #libertas on irc.freenode.net.

Dan

> 
> and I think udev's firmware.sh script finds it, but I have messages like this:
> 
> Jan 23 16:01:28 [kernel] libertas: looking at func->card->info[0]:
> Eastman Kodak Company
> Jan 23 16:01:28 [kernel] libertas: looking at func->card->info[1]:
> Kodak WiFi card 3F8508
> Jan 23 16:01:28 [kernel] libertas: failed to load helper firmware
> Jan 23 16:01:28 [kernel] libertas_sdio: probe of mmc0:0001:1 failed
> with error -84
> 
> I'm using Gentoo's version of kernel 2.6.27 on an Acer laptop that has
> an SD slot.
> 
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From svenmauren at vr-web.de  Sat Jan 24 06:53:29 2009
From: svenmauren at vr-web.de (Sven Barth)
Date: Sat, 24 Jan 2009 12:53:29 +0100
Subject: Problems with SD8686 SDIO on HTC Shift
Message-ID: <497B0139.2000906@vr-web.de>

Hello Dan!

Thanks for your answer.

Yes, I did indeed mean 2008. ^^

The SDIO Controller seems to be a no-name one (at least if I found the 
right one). I used "lspci -vvv"  and the output is attached.
I also found some output about the SDIO controller in dmesg (see 
attached file). Might the problems reported there be the source of the 
timeout problems?

I also removed the part about TX_POWER from main.c, but now the module 
hangs with CMD_MAC_CONTROL (0x0028) (another clue, that the source of 
the problems is the SDIO controller?)


Thanks for your help.

Regards,
Sven
-------------- next part --------------
// I think this is about the SDIO Controller
sdhci: Secure Digital Host Controller Interface driver
sdhci: Copyright(c) Pierre Ossman
sdhci-pci 0000:01:06.0: SDHCI controller found [1947:4743] (rev 9)
sdhci-pci 0000:01:06.0: PCI INT A -> GSI 20 (level, low) -> IRQ 20
sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
input: PC Speaker as /class/input/input7
mmc0: Unknown controller version (17). You may experience problems.
sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
mmc0: SDHCI controller on PCI [0000:01:06.0] using DMA
sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
mmc1: Unknown controller version (17). You may experience problems.
sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
mmc1: SDHCI controller on PCI [0000:01:06.0] using DMA

// without TX_POWER cmd
libertas_sdio: Libertas SDIO driver
libertas_sdio: Copyright Pierre Ossman
libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin
libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin
libertas: f3cbdcce, fw 8.70.8p1, cap 0x00000303
libertas: command 0x0028 timed out
libertas: requeueing command 0x0028 due to timeout (#1)
libertas: command 0x0028 timed out
libertas: requeueing command 0x0028 due to timeout (#2)
libertas: command 0x0028 timed out
libertas: requeueing command 0x0028 due to timeout (#3)
mmc1: Timeout waiting for hardware interrupt.
sdhci: ============== REGISTER DUMP ==============
sdhci: Sys addr: 0x33c2f488 | Version:  0x00000111
sdhci: Blk size: 0x00007010 | Blk cnt:  0x00000001
sdhci: Argument: 0x92000010 | Trn mode: 0x00000003
sdhci: Present:  0x01f70506 | Host ctl: 0x00000003
sdhci: Power:    0x0000000f | Blk gap:  0x00000000
sdhci: Wake-up:  0x00000000 | Clock:    0x00000007
sdhci: Timeout:  0x0000000c | Int stat: 0x00000000
sdhci: Int enab: 0x00ff01fb | Sig enab: 0x00ff01fb
sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
sdhci: Caps:     0x01e011a1 | Max curr: 0x00000080
sdhci: ===========================================
libertas: command 0x0028 timed out
libertas: Excessive timeouts submitting command 0x0028
// modprobe libertas_sdio keeps hanging after "excessive timeouts" till I press Ctrl+c
// this comes after I canceled modprobe
libertas: eth0: Marvell WLAN 802.11 adapter
-------------- next part --------------
01:06.0 SD Host controller: Device 1947:4743 (rev 09)
	Subsystem: Device 2211:4433
	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
	Latency: 64 (250ns min, 3000ns max), Cache Line Size: 32 bytes
	Interrupt: pin A routed to IRQ 20
	Region 0: Memory at fe8ffc00 (32-bit, non-prefetchable) [size=512]
	Region 1: Memory at fe8ff800 (32-bit, non-prefetchable) [size=512]
	Capabilities: [80] #00 [0000]
	Kernel driver in use: sdhci-pci
	Kernel modules: sdhci-pci


From dcbw at redhat.com  Sat Jan 24 09:36:33 2009
From: dcbw at redhat.com (Dan Williams)
Date: Sat, 24 Jan 2009 09:36:33 -0500
Subject: Problems with SD8686 SDIO on HTC Shift
In-Reply-To: <497B0139.2000906@vr-web.de>
References: <497B0139.2000906@vr-web.de>
Message-ID: <1232807793.2870.29.camel@localhost.localdomain>

On Sat, 2009-01-24 at 12:53 +0100, Sven Barth wrote:
> Hello Dan!
> 
> Thanks for your answer.
> 
> Yes, I did indeed mean 2008. ^^
> 
> The SDIO Controller seems to be a no-name one (at least if I found the 
> right one). I used "lspci -vvv"  and the output is attached.
> I also found some output about the SDIO controller in dmesg (see 
> attached file). Might the problems reported there be the source of the 
> timeout problems?

Certainly could be.  The controller has historically been the major
source of problems for people with the libertas driver so far.  The
kernel's SDIO stack is fairly clean and doesn't try to hack around bad
hardware a lot since it wasn't known quite how bad the hardware was at
the time it was written.  Some controllers actually do need PIO mode
instead of DMA mode, others can't actually do 4-bit transfers but claim
to be able to do so (which means they aren't actually spec compliant I
think), that sort of thing.  You may have to work around some of these
issues in the SDIO stack for your particular controller.

> I also removed the part about TX_POWER from main.c, but now the module 
> hangs with CMD_MAC_CONTROL (0x0028) (another clue, that the source of 
> the problems is the SDIO controller?)

Yeah; it appears that the only command that actually works is
CMD_GET_HW_SPEC, all subsequent commands fail.  I know that the version
8 firmware (which you're using as seen below) works fine with
CMD_MAC_CONTROL on Ricoh controllers, and others have had success with
it on other controllers too.  So I think at the moment, the controller
is suspect.

Pierre: any thoughts on the stack messages and what might be going on
here?

Dan

> 
> Thanks for your help.
> 
> Regards,
> Sven
> plain text document attachment (dmesg-htc-shift-2)
> // I think this is about the SDIO Controller
> sdhci: Secure Digital Host Controller Interface driver
> sdhci: Copyright(c) Pierre Ossman
> sdhci-pci 0000:01:06.0: SDHCI controller found [1947:4743] (rev 9)
> sdhci-pci 0000:01:06.0: PCI INT A -> GSI 20 (level, low) -> IRQ 20
> sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
> input: PC Speaker as /class/input/input7
> mmc0: Unknown controller version (17). You may experience problems.
> sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
> mmc0: SDHCI controller on PCI [0000:01:06.0] using DMA
> sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
> mmc1: Unknown controller version (17). You may experience problems.
> sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
> mmc1: SDHCI controller on PCI [0000:01:06.0] using DMA
> 
> // without TX_POWER cmd
> libertas_sdio: Libertas SDIO driver
> libertas_sdio: Copyright Pierre Ossman
> libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin
> libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin
> libertas: f3cbdcce, fw 8.70.8p1, cap 0x00000303
> libertas: command 0x0028 timed out
> libertas: requeueing command 0x0028 due to timeout (#1)
> libertas: command 0x0028 timed out
> libertas: requeueing command 0x0028 due to timeout (#2)
> libertas: command 0x0028 timed out
> libertas: requeueing command 0x0028 due to timeout (#3)
> mmc1: Timeout waiting for hardware interrupt.
> sdhci: ============== REGISTER DUMP ==============
> sdhci: Sys addr: 0x33c2f488 | Version:  0x00000111
> sdhci: Blk size: 0x00007010 | Blk cnt:  0x00000001
> sdhci: Argument: 0x92000010 | Trn mode: 0x00000003
> sdhci: Present:  0x01f70506 | Host ctl: 0x00000003
> sdhci: Power:    0x0000000f | Blk gap:  0x00000000
> sdhci: Wake-up:  0x00000000 | Clock:    0x00000007
> sdhci: Timeout:  0x0000000c | Int stat: 0x00000000
> sdhci: Int enab: 0x00ff01fb | Sig enab: 0x00ff01fb
> sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
> sdhci: Caps:     0x01e011a1 | Max curr: 0x00000080
> sdhci: ===========================================
> libertas: command 0x0028 timed out
> libertas: Excessive timeouts submitting command 0x0028
> // modprobe libertas_sdio keeps hanging after "excessive timeouts" till I press Ctrl+c
> // this comes after I canceled modprobe
> libertas: eth0: Marvell WLAN 802.11 adapter
> plain text document attachment (lspci-sd-host)
> 01:06.0 SD Host controller: Device 1947:4743 (rev 09)
> 	Subsystem: Device 2211:4433
> 	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
> 	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
> 	Latency: 64 (250ns min, 3000ns max), Cache Line Size: 32 bytes
> 	Interrupt: pin A routed to IRQ 20
> 	Region 0: Memory at fe8ffc00 (32-bit, non-prefetchable) [size=512]
> 	Region 1: Memory at fe8ff800 (32-bit, non-prefetchable) [size=512]
> 	Capabilities: [80] #00 [0000]
> 	Kernel driver in use: sdhci-pci
> 	Kernel modules: sdhci-pci
> 
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev



From svenmauren at vr-web.de  Sat Jan 24 15:31:10 2009
From: svenmauren at vr-web.de (Sven Barth)
Date: Sat, 24 Jan 2009 21:31:10 +0100
Subject: Problems with SD8686 SDIO on HTC Shift
In-Reply-To: <1232807793.2870.29.camel@localhost.localdomain>
References: <497B0139.2000906@vr-web.de>
	<1232807793.2870.29.camel@localhost.localdomain>
Message-ID: <497B7A8E.1080803@vr-web.de>

Hello Dan!

Thanks again for your answer.

Do you know where or how I could find out what workarounds my controller 
needs to work well? And what do I need to rebuild the mmc/sdhci modules? 
Are they provided in a extra package like compat-wireless or do I need 
the source of my kernel release? Can I only build the needed modules or 
do I need to build the hole kernel?

Hmm... just a thought: According to the page I mentioned in my first 
mail the wifi did work in Ubuntu 8.04 which used kernel 2.6.24-16 till 
19 (again I used a wrong number in my first mail ^^). So the SDIO module 
had to work, too. I will dig around in the source code of the module (I 
downloaded the source from marvell) to find some useful information 
about the SDIO controller. (So I think I answered my first question by 
myself :) )


Regards,
Sven

Dan Williams schrieb:
> On Sat, 2009-01-24 at 12:53 +0100, Sven Barth wrote:
>   
>> Hello Dan!
>>
>> Thanks for your answer.
>>
>> Yes, I did indeed mean 2008. ^^
>>
>> The SDIO Controller seems to be a no-name one (at least if I found the 
>> right one). I used "lspci -vvv"  and the output is attached.
>> I also found some output about the SDIO controller in dmesg (see 
>> attached file). Might the problems reported there be the source of the 
>> timeout problems?
>>     
>
> Certainly could be.  The controller has historically been the major
> source of problems for people with the libertas driver so far.  The
> kernel's SDIO stack is fairly clean and doesn't try to hack around bad
> hardware a lot since it wasn't known quite how bad the hardware was at
> the time it was written.  Some controllers actually do need PIO mode
> instead of DMA mode, others can't actually do 4-bit transfers but claim
> to be able to do so (which means they aren't actually spec compliant I
> think), that sort of thing.  You may have to work around some of these
> issues in the SDIO stack for your particular controller.
>
>   
>> I also removed the part about TX_POWER from main.c, but now the module 
>> hangs with CMD_MAC_CONTROL (0x0028) (another clue, that the source of 
>> the problems is the SDIO controller?)
>>     
>
> Yeah; it appears that the only command that actually works is
> CMD_GET_HW_SPEC, all subsequent commands fail.  I know that the version
> 8 firmware (which you're using as seen below) works fine with
> CMD_MAC_CONTROL on Ricoh controllers, and others have had success with
> it on other controllers too.  So I think at the moment, the controller
> is suspect.
>
> Pierre: any thoughts on the stack messages and what might be going on
> here?
>
> Dan
>
>   
>> Thanks for your help.
>>
>> Regards,
>> Sven
>> plain text document attachment (dmesg-htc-shift-2)
>> // I think this is about the SDIO Controller
>> sdhci: Secure Digital Host Controller Interface driver
>> sdhci: Copyright(c) Pierre Ossman
>> sdhci-pci 0000:01:06.0: SDHCI controller found [1947:4743] (rev 9)
>> sdhci-pci 0000:01:06.0: PCI INT A -> GSI 20 (level, low) -> IRQ 20
>> sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
>> input: PC Speaker as /class/input/input7
>> mmc0: Unknown controller version (17). You may experience problems.
>> sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
>> mmc0: SDHCI controller on PCI [0000:01:06.0] using DMA
>> sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
>> mmc1: Unknown controller version (17). You may experience problems.
>> sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
>> mmc1: SDHCI controller on PCI [0000:01:06.0] using DMA
>>
>> // without TX_POWER cmd
>> libertas_sdio: Libertas SDIO driver
>> libertas_sdio: Copyright Pierre Ossman
>> libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin
>> libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin
>> libertas: f3cbdcce, fw 8.70.8p1, cap 0x00000303
>> libertas: command 0x0028 timed out
>> libertas: requeueing command 0x0028 due to timeout (#1)
>> libertas: command 0x0028 timed out
>> libertas: requeueing command 0x0028 due to timeout (#2)
>> libertas: command 0x0028 timed out
>> libertas: requeueing command 0x0028 due to timeout (#3)
>> mmc1: Timeout waiting for hardware interrupt.
>> sdhci: ============== REGISTER DUMP ==============
>> sdhci: Sys addr: 0x33c2f488 | Version:  0x00000111
>> sdhci: Blk size: 0x00007010 | Blk cnt:  0x00000001
>> sdhci: Argument: 0x92000010 | Trn mode: 0x00000003
>> sdhci: Present:  0x01f70506 | Host ctl: 0x00000003
>> sdhci: Power:    0x0000000f | Blk gap:  0x00000000
>> sdhci: Wake-up:  0x00000000 | Clock:    0x00000007
>> sdhci: Timeout:  0x0000000c | Int stat: 0x00000000
>> sdhci: Int enab: 0x00ff01fb | Sig enab: 0x00ff01fb
>> sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
>> sdhci: Caps:     0x01e011a1 | Max curr: 0x00000080
>> sdhci: ===========================================
>> libertas: command 0x0028 timed out
>> libertas: Excessive timeouts submitting command 0x0028
>> // modprobe libertas_sdio keeps hanging after "excessive timeouts" till I press Ctrl+c
>> // this comes after I canceled modprobe
>> libertas: eth0: Marvell WLAN 802.11 adapter
>> plain text document attachment (lspci-sd-host)
>> 01:06.0 SD Host controller: Device 1947:4743 (rev 09)
>> 	Subsystem: Device 2211:4433
>> 	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
>> 	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
>> 	Latency: 64 (250ns min, 3000ns max), Cache Line Size: 32 bytes
>> 	Interrupt: pin A routed to IRQ 20
>> 	Region 0: Memory at fe8ffc00 (32-bit, non-prefetchable) [size=512]
>> 	Region 1: Memory at fe8ff800 (32-bit, non-prefetchable) [size=512]
>> 	Capabilities: [80] #00 [0000]
>> 	Kernel driver in use: sdhci-pci
>> 	Kernel modules: sdhci-pci
>>
>> _______________________________________________
>> libertas-dev mailing list
>> libertas-dev at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/libertas-dev
>>     
>
>
>   



From lawrence.auster at att.net  Sun Jan 25 12:51:18 2009
From: lawrence.auster at att.net (Lawrence Auster)
Date: Sun, 25 Jan 2009 18:51:18 +0100
Subject: Jewish Lobby Gives Obama His Marching Orders
Message-ID: <20090125175132.FUDG3899.hrndva-omta01.mail.rr.com@3lyw4>

Jewish Lobby Gives Obama His Marching Orders
By Michael Collins Piper

THE POWERFUL JEWISH LOBBY in Washington is already issuing marching orders to President-elect Barack Obama. One of the most influential voices of the lobby has published an array of ?working papers? designed to tell the president how he must maintain the ?special relationship? between the United States and Israel, increase pressure on a variety of Arab and Muslim states that are perceived as dangers to Israel, and generally assure that Israel?s interests will always be first and foremost in the conduct of U.S. foreign policy, not only in the Middle East but around the globe.

The Jewish Institute for National Security Affairs (JINSA), a particularly vocal force in the Jewish lobby, published an entire edition of its Journal of International Security Affairs (dated fall 2008), sending the official word to Obama. JINSA was founded by one Stephen Bryen who?along with a host of other well known names connected to JINSA?was once investigated by the FBI on charges of espionage for Israel.

A variety of articles in the journal addressing ?Middle East Policy and the Next President? and ?Iran, Iraq and Beyond,? make it clear that JINSA?best known as a nest of the infamous ?neo-conservatives? who misdirected U.S. foreign policy during the outgoing Bush administration, sparking the war in Iraq and continuing to clamor for action against Iran?wants Obama to pursue Bush-style policies.

AIPAC is particularly obsessed with using U.S. military and economic power to force Arab and Muslim nations to ?reform? from within. Talk of ?democracy? flows freely within AIPAC?s assorted essays, demanding that Israel?s neighbors conform to the Western version of democracy. But when the Palestinian people voted the Hamas movement into power in the Palestinian Authority in the occupied West Bank and the Gaza strip, AIPAC and other elements in the Jewish lobby immediately began calling for the United States to reject that freely elected government.

Now, of course, Hamas is largely only in control of the beleaguered Gaza?which many refer to as ?ghetto?? and the Palestinian statehood movement has been eviscerated, at least for now. This makes AIPAC and the lobby for Israel quite happy, for Israel has long encouraged U.S. policies?and helped create conditions?that have the effect of ?divide and conquer? in the Arab and Muslim world.

Israel is not like any other nation in the world, in that it seems to thrive best (and enjoys the benefits of) having its neighbors quarreling among themselves and rent within. Other nations prefer neighbors that are peaceful and internally secure. Israel wants its neighbors in chaos, because this prevents them from waging war against Israel, either individually or united. And although in the wake of the debacle in Iraq, which led many Israelis and their allies in the United States to suddenly proclaim that the Iraq war should never have been waged, the fact is that Israel and its U.S.-based agents-in-place were the prime movers behind that war and it was Israeli intelligence that was providing what critics now recognize was the ?bad intelligence? that led the Bush administration to ?mistakenly? conclude that Iraq was working toward an assembly of nuclear weapons to rival that of Israel.

The Israelis and their American spokesmen evidently now believe that if they tell the ?big lie? often enough?the lie that Israel?s interests played no part in orchestrating the debacle in Iraq?that it will make Americans forget that Israel was the foremost advocate of the war in the first place.

However, the evisceration of Iraq by the United States is part and parcel of a long-standing Israeli national security policy aimed toward ?balkanizing? the Muslim world.

Yet, AIPAC, in its journal, is now working to perpetuate the myth of Iraqi nuclear weapons and suggesting that Iraq?s weapons were transported into Syria, another nation which has been on the ?wish list for war? of Israel and its lobby in America. And AIPAC makes it clear that the destruction of Iran?s nuclear development program is a ?must.?

AIPAC is not the only Israeli lobby unit sending the message to the new president. Commentary magazine, long affiliated with the American Jewish Committee, has?in recent issues?been trumpeting a similar bellicose refrain directed at Obama. The editorial director of the Jewish lobby journal is John Podhoretz, a longtime close personal and political associate of the ubiquitous William Kristol, editor of the Weekly Standard magazine, which is the most infamous voice of the neo-conservative, hard-line pro-Israel elements operating in the media, in the think tanks, and in official policy making and national security and intelligence circles in Washington.

Their fathers, Irving Kristol and Norman Podhoretz, are two of the founding fathers of the neoconservative network, both Trotskyite Marxists who announced their ?conversion? to conservatism during the latter days of the Cold War, banging the drum for intensified U.S. support for Israel.

A complete overview of the neo-conservative power structure and its rather bizarre origins in the days when American Jewish communists like Kristol and Podhoretz turned on the Soviet Union when then- Soviet chief Josef Stalin began moving against Jewish and Zionist elements inside Russia can be found in The High Priests of War and The Judas Goats, two works by this author.

Whether President Obama intends real change, as he promised, or whether he will advance the Israeli agenda (which saw its power expand exponentially in the Republican administration of George W. Bush) remains to be seen. But ?the lobby? is making its voice heard and Obama knows that he better not ignore it.

A journalist specializing in media critique, Michael Collins Piper is the author of The High Priests of War, The New Jerusalem, Dirty Secrets, The Judas Goats, The Golem, Target Traficant and My First Days in the White House All are available from AFP.

Source : http://www.americanfreepress.net/html/jewish_lobby_164.html

-------------------------------------------------------------------------------------------------

Obama -- The Judas Goat
1/25/2009
By David Duke

Judas Goat\ A goat that leads other goats or sheep to slaughter. Also, one who entices into danger and betrays others. The name is an allusion to Judas Iscariot, who betrayed Jesus for 30 pieces of slaughter. (From Merriam Webster?s Dictionary)

Barack Hussein Obama is a Judas Goat.

Extremist Jews guided Barack Hussein Obama?s career from day one, even all the way back to Harvard Law School.  Radical Zionist hitman, David Axelrod previously orchestrated the Jewish-financed and organized defeat of perceived anti-Zionist Sen. Charles Percy. He is the man who ran Obama?s campaign for President and who is his chief handler. Obama?s campaign was overwhelmingly financed by the most powerful Zionist bankers in the world. His campaign?s largest contribution source was the Zionist international banking firm of Goldman Sachs. (FEC campaign records). In both Obama?s Senate and Presidential campaign he prostrated himself before AIPAC (American Israel Public Affairs Committee) promising even more money and blood for Israel?s terrorism than even the supine John McCain, and even more money and blood than the previous Shabbez Goy in the White House, George Bush. Before the Israeli terrorism and mass murder in Gaza, he went to Israel and said that he supported Israel?s planned murderous terrorism against the men, women and children of Gaza.

His first act as President-elect was to appoint a rabid Zionist, Israeli dual citizen who served in the Israeli Army as his Chief of Staff, Rahm Emmanuel. As thousands of women and children in Gaza were killed or maimed, Obama remained silent. Within a few days as President Obama supported indiscriminate American missile strikes in villages of our ally Pakistan, a clear continuation of Bush?s policies.  He completely supports the theft of trillions of American taxpayer dollars to the Zionist international bankers. Eighty percent of American Jews voted for Obama, and all the main leaders of the Jewish Supremacist state of Israel have proclaimed Obama as the perfect man for U.S. President.

What better for the Zionists to have their own servant perceived as a clean break from the Jewish extremist-controlled Bush administration? What better than for the Zionists than to have their Shabbez Goy be treated by the world?s press and even by much of the anti-Zionist community as a man of ?real change?? What better for the Zionists than for the world to think that Obama will be a change from the Zionist-controlled policies when he willing to do anything that Israel demands? What better for the Zionist murderers to have their craven puppet be looked at by the whole world as a man of honor and integrity and fairness.

In the slaughterhouse, the Judas Goat is often painted with bright colors, adorned with strong, sweet scents to lure the sheep to their pens and to their death. Obama, the Judas Goat of our time, is looked upon by millions of Zionist-propagandized sheep as the man who will lead them to salvation.

Instead, he leads America, Palestine and the world to the bloody altar of Jewish Supremacism.

Any supposed anti-Zionist who praises Barack Obama is actually aiding this Judas Goat to lead us all to slaughter. Every person who truly opposes Jewish extremism must speak out and expose the Judas Goat named Barack Obama!

-- Dr. David Duke

Former Member of the House of Representatives

State of Louisiana

United States of America

It is up to you the people of the United States who can still think freely,  and up to all of the people of the world who are able to see through the deceptions of the Zionist-influenced Global media  -- to get this simple, powerful message to everyone on earth. Email this message to your friends, post it on forums and websites and put links to it on every website, facebook or other media in the world. Go and seek out media and Internet sites not controlled by Zionist power. Make youtube videos of this message, (use the short audio and find good illustrative pictures) and post it untill your fingers are worn and tired, print it and mail it to newspapers or any media outlet that has still not fallen under the propaganda of the Zionists. Let the world know the truth. Person by person, in the USA, Canada, UK, France, Germany, Italy, japan, Russia, China, Africa, Palestine, South America and across the whole world this Judas Goat must be exposed for what he is, so that when begins to do his evil for Israel, the whole world will know exactly what is going on and resist!

Source : http://www.davidduke.com/general/obama-the-judas-goat_7317.html


------------------------

Why is the President of Israel, the terrorist who just oversaw the Zionist mass murder and maiming of thousands of Palestinians so happy
that Obama is President of the USA?
by David Duke


Read the excerpt from the Israeli News about how President Perez and Israel think that Obama?s becoming U.S. President is great day
for Israel.

"Israel?s President Shimon Peres ecstatic over the election of Obama"
Ronen Medzini Israel News Jan. 21

?Today is a great day not only for the United States of America, but for the entire world,? President Shimon Peres wrote in a letter
addressed to Barack Obama on the day of his inauguration as president of the United States.

?Obama was elected by the United States, but as a matter of fact, he was chosen by the whole of humankind,?

Why is Peres so ecstatic?

Why shouldn?t he be, he knows that Obama is completely in the grip of the extremist Jewish Zionists in America, and he knows that the
greater Obama?s popularity and idol worship, the more Obama can do for the International Zionist Cause.

Any thinking and caring human being who realizes that the Zionist-controlled American foreign policy has been a disaster for the robbed
and murdered people of Palestine, Lebanon, Iraq and a catastrophe for the 50,000 American wounded in Iraq and Afghanistan, as well
as an economic catastrophe for the hardworking Americans who pay trillions to finance these wars for Israel -- must wake up the fact that
supporting Obama and increasing his popularity  will only aid Zionist terrorism, war, and their murder and oppression of the Palestinians. It
will also hasten the economic suffering of billions of people around the world as his popularity enables him to more easily aid the Zionist
International Bankers steal the wealth of the United States, Europe and the world.  Obama is totally in the bloodstained and green ink-
stained hands of the Zionists. The hard truth is that the more good will and support Obama has also gives more power to support the
Zionist agenda!

Mark my words. The Obama Presidency will be disaster for America and for the world.

Obama was put into office by the Zionists. His top two cohorts for years have been the radical Jews David Axelrod and Rahm
Emmanuel. Both have long records of radical Zionism and have been attack dogs against anyone perceived as having the slightest
opposition to Israel. One such victim was Sen. Charles Percy, who both men worked to defeat and destroy because he dared to only be
99 percent rather than 100 percent pro-Israel. Rahm Emmanuel, a dual citizen of Israel who went to fight for Israel, he has a long
pedigree of Jewish extremism. His father served in the Irgun Terrorist Gang and he himself is named after an Irgun terrorist.

Zionist leaders in Chicago actually call Obama ?the first Jewish President? and boast that Jews were key players in Obama?s every step
up the ladder to President.

from the very earliest days, extremist Jews were the largest contributors to his campaign. In the beginning of his Presidential bid, three
Hollywood Jews that constantly make movies about Jewish suffering, but never about the Zionist terrorism and theft against the
Palestinian people, Steven Spielberg, David Geffen, and Jeffrey Katzenberg raised 1.2 million for Obama in a single Hollywood party.

By the time Obama?s campaign was in full swing, he had huge support from the criminal Zionist International Banking firms such as
Goldman Sachs and Lehman brothers. Goldman Sachs was Obama?s biggest single contributor, and his vast war chest came not from
American manufacturing firms like GM or even American oil companies, (not one was in his top twenty) it was overwhelmingly dominated
by Zionist international bankers, the same ones whose thievery and fraud are giving the world this economic depression.

For those looking for meaningful social and political change, do you really think it will come from this man who has already been bought
heart, head and soul by the most powerful czars of the international financial establishment and the biggest globalists in the world?

I know that many are desperate for change, so desperate that you want to believe anything. But in the face of these facts can?t you see
that Obama will be even more dangerous to freedom and justice than even George Bush and his band of Neocons were. What better
way to wipe out George Bush?s hated legacy and make the world believe that America has really changed than with the election of
Obama. But, all the real Zionist power, Zionist media power, and Zionist financial power in America is still in place, even stronger than
ever.

Many Americans and others around the world who want to do good are now telling us how wonderful Obama will be as president. What
a great change it will be from the old policies. This is because of the Zionist-Controlled media hype, promoting Obama. The fact is that
these poor sods are ignorantly helping the radical Zionist agenda in Israel and around the world.

Every day that you don?t help expose Obama for the Zionist servant that he actually is, his popularity will be a greater danger to peace
and freedom.

If the Zionist terrorist Shimon Perez is happy about the coronation of Obama, then why in the hell should you be?

?David Duke

Source : http://www.davidduke.com/general/7303_7303.html
-------------------------------------

You or someone using your email adress is currently subscribed to the Lawrence Auster
Newletter. If you wish to unsubscribe from our mailing list, please let us know by calling "to 1 212 865 1284

Thanks,

Lawrence Auster,
238 W 101 St Apt. 3B
New York, NY  10025
Contact: lawrence.auster at att.net
-------------------------------------



From mike at compulab.co.il  Mon Jan 26 09:58:42 2009
From: mike at compulab.co.il (Mike Rapoport)
Date: Mon, 26 Jan 2009 16:58:42 +0200
Subject: Libertas with if_spi on pxa270
Message-ID: <497DCFA2.3070508@compulab.co.il>

Hi,

Have anybody tried to use 8686 with G-SPI on PXA270?
I've merged libertas-related changes from wireless-testing tree on top of
2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
get from the if_spi was "libertas: Can't read bus mode register." :(


-- 
Sincerely yours,
Mike.



From dcbw at redhat.com  Mon Jan 26 10:07:59 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 26 Jan 2009 10:07:59 -0500
Subject: Problems with SD8686 SDIO on HTC Shift
In-Reply-To: <497B7A8E.1080803@vr-web.de>
References: <497B0139.2000906@vr-web.de>
	<1232807793.2870.29.camel@localhost.localdomain>
	<497B7A8E.1080803@vr-web.de>
Message-ID: <1232982479.5605.28.camel@localhost.localdomain>

On Sat, 2009-01-24 at 21:31 +0100, Sven Barth wrote:
> Hello Dan!
> 
> Thanks again for your answer.
> 
> Do you know where or how I could find out what workarounds my controller 

No; this is usually either known from hardware quirks, or people figure
it out by doing stuff like disabling 4-bit transfers and seeing if that
fixes the problem.

> needs to work well? And what do I need to rebuild the mmc/sdhci modules?

You'll need the kernel source for the SDIO stuff.

> Are they provided in a extra package like compat-wireless or do I need 
> the source of my kernel release? Can I only build the needed modules or 
> do I need to build the hole kernel?

You don't need to rebuild the entire kernel just to test; once you have
the kernel source and the kernel development headers installed, you can
just jump into the module directory in the kernel source, and do:

make -C /path/to/kernel/headers SUBDIRS=`pwd` modules

and it'll build only the modules in that directory.  For example, on
Fedora:

cd drivers/mmc/host
make -C /lib/modules/2.6.27.5-41.fc9.i686/build SUBDIRS=`pwd` modules

would build all the SDHC modules that are turned on in the kernel config
which my currently running kernel was built with.

> Hmm... just a thought: According to the page I mentioned in my first 
> mail the wifi did work in Ubuntu 8.04 which used kernel 2.6.24-16 till 
> 19 (again I used a wrong number in my first mail ^^). So the SDIO module 
> had to work, too. I will dig around in the source code of the module (I 
> downloaded the source from marvell) to find some useful information 
> about the SDIO controller. (So I think I answered my first question by 
> myself :) )

If it worked at one time, it may be a problem with the libertas driver,
but it would be good to know *exactly* what kernel, SDIO stack bits,
libertas driver, and libertas firmware it was working with.  That gives
us a baseline to figure out where things went wrong.

Dan

> 
> Regards,
> Sven
> 
> Dan Williams schrieb:
> > On Sat, 2009-01-24 at 12:53 +0100, Sven Barth wrote:
> >   
> >> Hello Dan!
> >>
> >> Thanks for your answer.
> >>
> >> Yes, I did indeed mean 2008. ^^
> >>
> >> The SDIO Controller seems to be a no-name one (at least if I found the 
> >> right one). I used "lspci -vvv"  and the output is attached.
> >> I also found some output about the SDIO controller in dmesg (see 
> >> attached file). Might the problems reported there be the source of the 
> >> timeout problems?
> >>     
> >
> > Certainly could be.  The controller has historically been the major
> > source of problems for people with the libertas driver so far.  The
> > kernel's SDIO stack is fairly clean and doesn't try to hack around bad
> > hardware a lot since it wasn't known quite how bad the hardware was at
> > the time it was written.  Some controllers actually do need PIO mode
> > instead of DMA mode, others can't actually do 4-bit transfers but claim
> > to be able to do so (which means they aren't actually spec compliant I
> > think), that sort of thing.  You may have to work around some of these
> > issues in the SDIO stack for your particular controller.
> >
> >   
> >> I also removed the part about TX_POWER from main.c, but now the module 
> >> hangs with CMD_MAC_CONTROL (0x0028) (another clue, that the source of 
> >> the problems is the SDIO controller?)
> >>     
> >
> > Yeah; it appears that the only command that actually works is
> > CMD_GET_HW_SPEC, all subsequent commands fail.  I know that the version
> > 8 firmware (which you're using as seen below) works fine with
> > CMD_MAC_CONTROL on Ricoh controllers, and others have had success with
> > it on other controllers too.  So I think at the moment, the controller
> > is suspect.
> >
> > Pierre: any thoughts on the stack messages and what might be going on
> > here?
> >
> > Dan
> >
> >   
> >> Thanks for your help.
> >>
> >> Regards,
> >> Sven
> >> plain text document attachment (dmesg-htc-shift-2)
> >> // I think this is about the SDIO Controller
> >> sdhci: Secure Digital Host Controller Interface driver
> >> sdhci: Copyright(c) Pierre Ossman
> >> sdhci-pci 0000:01:06.0: SDHCI controller found [1947:4743] (rev 9)
> >> sdhci-pci 0000:01:06.0: PCI INT A -> GSI 20 (level, low) -> IRQ 20
> >> sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
> >> input: PC Speaker as /class/input/input7
> >> mmc0: Unknown controller version (17). You may experience problems.
> >> sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
> >> mmc0: SDHCI controller on PCI [0000:01:06.0] using DMA
> >> sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
> >> mmc1: Unknown controller version (17). You may experience problems.
> >> sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
> >> mmc1: SDHCI controller on PCI [0000:01:06.0] using DMA
> >>
> >> // without TX_POWER cmd
> >> libertas_sdio: Libertas SDIO driver
> >> libertas_sdio: Copyright Pierre Ossman
> >> libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin
> >> libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin
> >> libertas: f3cbdcce, fw 8.70.8p1, cap 0x00000303
> >> libertas: command 0x0028 timed out
> >> libertas: requeueing command 0x0028 due to timeout (#1)
> >> libertas: command 0x0028 timed out
> >> libertas: requeueing command 0x0028 due to timeout (#2)
> >> libertas: command 0x0028 timed out
> >> libertas: requeueing command 0x0028 due to timeout (#3)
> >> mmc1: Timeout waiting for hardware interrupt.
> >> sdhci: ============== REGISTER DUMP ==============
> >> sdhci: Sys addr: 0x33c2f488 | Version:  0x00000111
> >> sdhci: Blk size: 0x00007010 | Blk cnt:  0x00000001
> >> sdhci: Argument: 0x92000010 | Trn mode: 0x00000003
> >> sdhci: Present:  0x01f70506 | Host ctl: 0x00000003
> >> sdhci: Power:    0x0000000f | Blk gap:  0x00000000
> >> sdhci: Wake-up:  0x00000000 | Clock:    0x00000007
> >> sdhci: Timeout:  0x0000000c | Int stat: 0x00000000
> >> sdhci: Int enab: 0x00ff01fb | Sig enab: 0x00ff01fb
> >> sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
> >> sdhci: Caps:     0x01e011a1 | Max curr: 0x00000080
> >> sdhci: ===========================================
> >> libertas: command 0x0028 timed out
> >> libertas: Excessive timeouts submitting command 0x0028
> >> // modprobe libertas_sdio keeps hanging after "excessive timeouts" till I press Ctrl+c
> >> // this comes after I canceled modprobe
> >> libertas: eth0: Marvell WLAN 802.11 adapter
> >> plain text document attachment (lspci-sd-host)
> >> 01:06.0 SD Host controller: Device 1947:4743 (rev 09)
> >> 	Subsystem: Device 2211:4433
> >> 	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
> >> 	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
> >> 	Latency: 64 (250ns min, 3000ns max), Cache Line Size: 32 bytes
> >> 	Interrupt: pin A routed to IRQ 20
> >> 	Region 0: Memory at fe8ffc00 (32-bit, non-prefetchable) [size=512]
> >> 	Region 1: Memory at fe8ff800 (32-bit, non-prefetchable) [size=512]
> >> 	Capabilities: [80] #00 [0000]
> >> 	Kernel driver in use: sdhci-pci
> >> 	Kernel modules: sdhci-pci
> >>
> >> _______________________________________________
> >> libertas-dev mailing list
> >> libertas-dev at lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/libertas-dev
> >>     
> >
> >
> >   
> 



From dcbw at redhat.com  Mon Jan 26 10:07:59 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 26 Jan 2009 10:07:59 -0500
Subject: Problems with SD8686 SDIO on HTC Shift
In-Reply-To: <497B7A8E.1080803@vr-web.de>
References: <497B0139.2000906@vr-web.de>
	<1232807793.2870.29.camel@localhost.localdomain>
	<497B7A8E.1080803@vr-web.de>
Message-ID: <1232982479.5605.28.camel@localhost.localdomain>

On Sat, 2009-01-24 at 21:31 +0100, Sven Barth wrote:
> Hello Dan!
> 
> Thanks again for your answer.
> 
> Do you know where or how I could find out what workarounds my controller 

No; this is usually either known from hardware quirks, or people figure
it out by doing stuff like disabling 4-bit transfers and seeing if that
fixes the problem.

> needs to work well? And what do I need to rebuild the mmc/sdhci modules?

You'll need the kernel source for the SDIO stuff.

> Are they provided in a extra package like compat-wireless or do I need 
> the source of my kernel release? Can I only build the needed modules or 
> do I need to build the hole kernel?

You don't need to rebuild the entire kernel just to test; once you have
the kernel source and the kernel development headers installed, you can
just jump into the module directory in the kernel source, and do:

make -C /path/to/kernel/headers SUBDIRS=`pwd` modules

and it'll build only the modules in that directory.  For example, on
Fedora:

cd drivers/mmc/host
make -C /lib/modules/2.6.27.5-41.fc9.i686/build SUBDIRS=`pwd` modules

would build all the SDHC modules that are turned on in the kernel config
which my currently running kernel was built with.

> Hmm... just a thought: According to the page I mentioned in my first 
> mail the wifi did work in Ubuntu 8.04 which used kernel 2.6.24-16 till 
> 19 (again I used a wrong number in my first mail ^^). So the SDIO module 
> had to work, too. I will dig around in the source code of the module (I 
> downloaded the source from marvell) to find some useful information 
> about the SDIO controller. (So I think I answered my first question by 
> myself :) )

If it worked at one time, it may be a problem with the libertas driver,
but it would be good to know *exactly* what kernel, SDIO stack bits,
libertas driver, and libertas firmware it was working with.  That gives
us a baseline to figure out where things went wrong.

Dan

> 
> Regards,
> Sven
> 
> Dan Williams schrieb:
> > On Sat, 2009-01-24 at 12:53 +0100, Sven Barth wrote:
> >   
> >> Hello Dan!
> >>
> >> Thanks for your answer.
> >>
> >> Yes, I did indeed mean 2008. ^^
> >>
> >> The SDIO Controller seems to be a no-name one (at least if I found the 
> >> right one). I used "lspci -vvv"  and the output is attached.
> >> I also found some output about the SDIO controller in dmesg (see 
> >> attached file). Might the problems reported there be the source of the 
> >> timeout problems?
> >>     
> >
> > Certainly could be.  The controller has historically been the major
> > source of problems for people with the libertas driver so far.  The
> > kernel's SDIO stack is fairly clean and doesn't try to hack around bad
> > hardware a lot since it wasn't known quite how bad the hardware was at
> > the time it was written.  Some controllers actually do need PIO mode
> > instead of DMA mode, others can't actually do 4-bit transfers but claim
> > to be able to do so (which means they aren't actually spec compliant I
> > think), that sort of thing.  You may have to work around some of these
> > issues in the SDIO stack for your particular controller.
> >
> >   
> >> I also removed the part about TX_POWER from main.c, but now the module 
> >> hangs with CMD_MAC_CONTROL (0x0028) (another clue, that the source of 
> >> the problems is the SDIO controller?)
> >>     
> >
> > Yeah; it appears that the only command that actually works is
> > CMD_GET_HW_SPEC, all subsequent commands fail.  I know that the version
> > 8 firmware (which you're using as seen below) works fine with
> > CMD_MAC_CONTROL on Ricoh controllers, and others have had success with
> > it on other controllers too.  So I think at the moment, the controller
> > is suspect.
> >
> > Pierre: any thoughts on the stack messages and what might be going on
> > here?
> >
> > Dan
> >
> >   
> >> Thanks for your help.
> >>
> >> Regards,
> >> Sven
> >> plain text document attachment (dmesg-htc-shift-2)
> >> // I think this is about the SDIO Controller
> >> sdhci: Secure Digital Host Controller Interface driver
> >> sdhci: Copyright(c) Pierre Ossman
> >> sdhci-pci 0000:01:06.0: SDHCI controller found [1947:4743] (rev 9)
> >> sdhci-pci 0000:01:06.0: PCI INT A -> GSI 20 (level, low) -> IRQ 20
> >> sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
> >> input: PC Speaker as /class/input/input7
> >> mmc0: Unknown controller version (17). You may experience problems.
> >> sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
> >> mmc0: SDHCI controller on PCI [0000:01:06.0] using DMA
> >> sdhci-pci 0000:01:06.0: Invalid iomem size. You may experience problems.
> >> mmc1: Unknown controller version (17). You may experience problems.
> >> sdhci-pci 0000:01:06.0: Will use DMA mode even though HW doesn't fully claim to support it.
> >> mmc1: SDHCI controller on PCI [0000:01:06.0] using DMA
> >>
> >> // without TX_POWER cmd
> >> libertas_sdio: Libertas SDIO driver
> >> libertas_sdio: Copyright Pierre Ossman
> >> libertas_sdio mmc1:0001:1: firmware: requesting sd8686_helper.bin
> >> libertas_sdio mmc1:0001:1: firmware: requesting sd8686.bin
> >> libertas: f3cbdcce, fw 8.70.8p1, cap 0x00000303
> >> libertas: command 0x0028 timed out
> >> libertas: requeueing command 0x0028 due to timeout (#1)
> >> libertas: command 0x0028 timed out
> >> libertas: requeueing command 0x0028 due to timeout (#2)
> >> libertas: command 0x0028 timed out
> >> libertas: requeueing command 0x0028 due to timeout (#3)
> >> mmc1: Timeout waiting for hardware interrupt.
> >> sdhci: ============== REGISTER DUMP ==============
> >> sdhci: Sys addr: 0x33c2f488 | Version:  0x00000111
> >> sdhci: Blk size: 0x00007010 | Blk cnt:  0x00000001
> >> sdhci: Argument: 0x92000010 | Trn mode: 0x00000003
> >> sdhci: Present:  0x01f70506 | Host ctl: 0x00000003
> >> sdhci: Power:    0x0000000f | Blk gap:  0x00000000
> >> sdhci: Wake-up:  0x00000000 | Clock:    0x00000007
> >> sdhci: Timeout:  0x0000000c | Int stat: 0x00000000
> >> sdhci: Int enab: 0x00ff01fb | Sig enab: 0x00ff01fb
> >> sdhci: AC12 err: 0x00000000 | Slot int: 0x00000000
> >> sdhci: Caps:     0x01e011a1 | Max curr: 0x00000080
> >> sdhci: ===========================================
> >> libertas: command 0x0028 timed out
> >> libertas: Excessive timeouts submitting command 0x0028
> >> // modprobe libertas_sdio keeps hanging after "excessive timeouts" till I press Ctrl+c
> >> // this comes after I canceled modprobe
> >> libertas: eth0: Marvell WLAN 802.11 adapter
> >> plain text document attachment (lspci-sd-host)
> >> 01:06.0 SD Host controller: Device 1947:4743 (rev 09)
> >> 	Subsystem: Device 2211:4433
> >> 	Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx-
> >> 	Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
> >> 	Latency: 64 (250ns min, 3000ns max), Cache Line Size: 32 bytes
> >> 	Interrupt: pin A routed to IRQ 20
> >> 	Region 0: Memory at fe8ffc00 (32-bit, non-prefetchable) [size=512]
> >> 	Region 1: Memory at fe8ff800 (32-bit, non-prefetchable) [size=512]
> >> 	Capabilities: [80] #00 [0000]
> >> 	Kernel driver in use: sdhci-pci
> >> 	Kernel modules: sdhci-pci
> >>
> >> _______________________________________________
> >> libertas-dev mailing list
> >> libertas-dev at lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/libertas-dev
> >>     
> >
> >
> >   
> 



From dcbw at redhat.com  Mon Jan 26 10:29:51 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 26 Jan 2009 10:29:51 -0500
Subject: Libertas with if_spi on pxa270
In-Reply-To: <497DCFA2.3070508@compulab.co.il>
References: <497DCFA2.3070508@compulab.co.il>
Message-ID: <1232983791.6319.9.camel@localhost.localdomain>

On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
> Hi,
> 
> Have anybody tried to use 8686 with G-SPI on PXA270?
> I've merged libertas-related changes from wireless-testing tree on top of
> 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
> get from the if_spi was "libertas: Can't read bus mode register." :(

Have you set up the Chip Select stuff correctly for your board (see
gpio_cs in the platform data)?  That seems to be board-dependent and
there's not a good generic way of doing this in the current kernel
sources.

That error is the first error that will get reported when the driver
actually tries to talk to the card, which requires that the Chip Select
stuff be set up correctly.  If you think you've got that already set up,
can you manually inspect whether or not the libertas device has actually
been selected on the board?

Dan




From mike at compulab.co.il  Mon Jan 26 11:24:47 2009
From: mike at compulab.co.il (Mike Rapoport)
Date: Mon, 26 Jan 2009 18:24:47 +0200
Subject: Libertas with if_spi on pxa270
In-Reply-To: <1232983791.6319.9.camel@localhost.localdomain>
References: <497DCFA2.3070508@compulab.co.il>
	<1232983791.6319.9.camel@localhost.localdomain>
Message-ID: <497DE3CF.6080609@compulab.co.il>



Dan Williams wrote:
> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
>> Hi,
>>
>> Have anybody tried to use 8686 with G-SPI on PXA270?
>> I've merged libertas-related changes from wireless-testing tree on top of
>> 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
>> get from the if_spi was "libertas: Can't read bus mode register." :(
> 
> Have you set up the Chip Select stuff correctly for your board (see
> gpio_cs in the platform data)?  That seems to be board-dependent and
> there's not a good generic way of doing this in the current kernel
> sources.
> 
> That error is the first error that will get reported when the driver
> actually tries to talk to the card, which requires that the Chip Select
> stuff be set up correctly.  If you think you've got that already set up,
> can you manually inspect whether or not the libertas device has actually
> been selected on the board?

The first thing I've done was to recheck GPIO setup and platform_data for all
SPI related stuff.
I've even inserted GPIO setup function at the very beginning of if_spi_probe.
The Marvell proprietary driver works well on the same board and exactly same
GPIOs setup.

> Dan
> 
> 

-- 
Sincerely yours,
Mike.



From dcbw at redhat.com  Mon Jan 26 11:39:00 2009
From: dcbw at redhat.com (Dan Williams)
Date: Mon, 26 Jan 2009 11:39:00 -0500
Subject: Libertas with if_spi on pxa270
In-Reply-To: <497DE3CF.6080609@compulab.co.il>
References: <497DCFA2.3070508@compulab.co.il>
	<1232983791.6319.9.camel@localhost.localdomain>
	<497DE3CF.6080609@compulab.co.il>
Message-ID: <1232987940.6319.35.camel@localhost.localdomain>

On Mon, 2009-01-26 at 18:24 +0200, Mike Rapoport wrote:
> 
> Dan Williams wrote:
> > On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
> >> Hi,
> >>
> >> Have anybody tried to use 8686 with G-SPI on PXA270?
> >> I've merged libertas-related changes from wireless-testing tree on top of
> >> 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
> >> get from the if_spi was "libertas: Can't read bus mode register." :(
> > 
> > Have you set up the Chip Select stuff correctly for your board (see
> > gpio_cs in the platform data)?  That seems to be board-dependent and
> > there's not a good generic way of doing this in the current kernel
> > sources.
> > 
> > That error is the first error that will get reported when the driver
> > actually tries to talk to the card, which requires that the Chip Select
> > stuff be set up correctly.  If you think you've got that already set up,
> > can you manually inspect whether or not the libertas device has actually
> > been selected on the board?
> 
> The first thing I've done was to recheck GPIO setup and platform_data for all
> SPI related stuff.
> I've even inserted GPIO setup function at the very beginning of if_spi_probe.
> The Marvell proprietary driver works well on the same board and exactly same
> GPIOs setup.

Ok, Colin McCabe will probably need to get involved here then since he
wrote those bits :)

Dan




From u.luckas at road.de  Mon Jan 26 12:13:23 2009
From: u.luckas at road.de (Uli Luckas)
Date: Mon, 26 Jan 2009 18:13:23 +0100
Subject: Libertas with if_spi on pxa270
In-Reply-To: <1232983791.6319.9.camel@localhost.localdomain>
References: <497DCFA2.3070508@compulab.co.il>
	<1232983791.6319.9.camel@localhost.localdomain>
Message-ID: <200901261813.23477.u.luckas@road.de>

On Monday, 26. January 2009, Dan Williams wrote:
> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
> > Hi,
> >
> > Have anybody tried to use 8686 with G-SPI on PXA270?
> > I've merged libertas-related changes from wireless-testing tree on top of
> > 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I
> > could get from the if_spi was "libertas: Can't read bus mode register."
> > :(
>
> Have you set up the Chip Select stuff correctly for your board (see
> gpio_cs in the platform data)?  That seems to be board-dependent and
> there's not a good generic way of doing this in the current kernel
> sources.
>
> That error is the first error that will get reported when the driver
> actually tries to talk to the card, which requires that the Chip Select
> stuff be set up correctly.  If you think you've got that already set up,
> can you manually inspect whether or not the libertas device has actually
> been selected on the board?
>
> Dan
>
Judging from the blackfin board setup code, we need to switch the controller 
to 16 bits/word. This seems to not be possible with the pxa spi driver.
For testing it might help to replace the spi_read/spi_write calls with local 
implementations of a spi_read16/spi_write16 funtion which sets the 
bits_per_word in struct spi_transfer.
I also wonder, which value to use for mode in my struct spi_board_info.

Uli


-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien


From andrey at cozybit.com  Mon Jan 26 14:13:00 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Mon, 26 Jan 2009 11:13:00 -0800
Subject: Libertas with if_spi on pxa270
In-Reply-To: <200901261813.23477.u.luckas@road.de>
References: <497DCFA2.3070508@compulab.co.il>
	<1232983791.6319.9.camel@localhost.localdomain>
	<200901261813.23477.u.luckas@road.de>
Message-ID: <45e8e6c40901261113q5bda40c0r798209e3bfcd57fd@mail.gmail.com>

That's correct -- the '8686 requires that you run the controller in
16-bit mode (or fake it accordingly).  I added notes about this to the
libertas wiki page:
http://wireless.kernel.org/en/users/Drivers/libertas
The bus mode register read is the driver's first actual SPI access.
Once you have that working, chances are good that the rest will work.
The vendor driver implements its own SPI stack instead of using the
kernel's so that's probably why it works on your specific board.

On Mon, Jan 26, 2009 at 9:13 AM, Uli Luckas <u.luckas at road.de> wrote:
> On Monday, 26. January 2009, Dan Williams wrote:
>> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
>> > Hi,
>> >
>> > Have anybody tried to use 8686 with G-SPI on PXA270?
>> > I've merged libertas-related changes from wireless-testing tree on top of
>> > 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I
>> > could get from the if_spi was "libertas: Can't read bus mode register."
>> > :(
>>
>> Have you set up the Chip Select stuff correctly for your board (see
>> gpio_cs in the platform data)?  That seems to be board-dependent and
>> there's not a good generic way of doing this in the current kernel
>> sources.
>>
>> That error is the first error that will get reported when the driver
>> actually tries to talk to the card, which requires that the Chip Select
>> stuff be set up correctly.  If you think you've got that already set up,
>> can you manually inspect whether or not the libertas device has actually
>> been selected on the board?
>>
>> Dan
>>
> Judging from the blackfin board setup code, we need to switch the controller
> to 16 bits/word. This seems to not be possible with the pxa spi driver.
> For testing it might help to replace the spi_read/spi_write calls with local
> implementations of a spi_read16/spi_write16 funtion which sets the
> bits_per_word in struct spi_transfer.
> I also wonder, which value to use for mode in my struct spi_board_info.
>
> Uli
>
>
> --
>
> ------- ROAD ...the handyPC Company - - -  ) ) )
>
> Uli Luckas
> Head of Software Development
>
> ROAD GmbH
> Bennigsenstr. 14 | 12159 Berlin | Germany
> fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
> url: www.road.de
>
> Amtsgericht Charlottenburg: HRB 96688 B
> Managing director: Hans-Peter Constien
>
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev
>



-- 
Andrey Yurovsky
cozybit Inc.


From mike at compulab.co.il  Tue Jan 27 06:51:40 2009
From: mike at compulab.co.il (Mike Rapoport)
Date: Tue, 27 Jan 2009 13:51:40 +0200
Subject: Libertas with if_spi on pxa270
In-Reply-To: <1232987940.6319.35.camel@localhost.localdomain>
References: <497DCFA2.3070508@compulab.co.il>	
	<1232983791.6319.9.camel@localhost.localdomain>	
	<497DE3CF.6080609@compulab.co.il>
	<1232987940.6319.35.camel@localhost.localdomain>
Message-ID: <497EF54C.8070907@compulab.co.il>

Dan,

Dan Williams wrote:
> On Mon, 2009-01-26 at 18:24 +0200, Mike Rapoport wrote:
>> Dan Williams wrote:
>>> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
>>>> Hi,
>>>>
>>>> Have anybody tried to use 8686 with G-SPI on PXA270?
>>>> I've merged libertas-related changes from wireless-testing tree on top of
>>>> 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
>>>> get from the if_spi was "libertas: Can't read bus mode register." :(
>>> Have you set up the Chip Select stuff correctly for your board (see
>>> gpio_cs in the platform data)?  That seems to be board-dependent and
>>> there's not a good generic way of doing this in the current kernel
>>> sources.
>>>
>>> That error is the first error that will get reported when the driver
>>> actually tries to talk to the card, which requires that the Chip Select
>>> stuff be set up correctly.  If you think you've got that already set up,
>>> can you manually inspect whether or not the libertas device has actually
>>> been selected on the board?
>> The first thing I've done was to recheck GPIO setup and platform_data for all
>> SPI related stuff.
>> I've even inserted GPIO setup function at the very beginning of if_spi_probe.
>> The Marvell proprietary driver works well on the same board and exactly same
>> GPIOs setup.
> 
> Ok, Colin McCabe will probably need to get involved here then since he
> wrote those bits :)

You were right about possible problems with my board setup. The 8686 requires
SPI clock pin to be high at power up to start with G-SPI rather than SDIO. That
part was missing from my board setup.
Still I needed to alter the if_spi.c to make it work. First of all, I think it
makes sence to add

	spi->bits_per_word = 16;
	spi_setup(spi);

at the beginning of if_spi_probe.
Another thing, it's possible worth adding ability to call platform specific
init/exit functions supplied with libertas_spi_platform_data.

After the driver begun to work I've noted that it's performance is not as good
as I expected. The reason for it is that PXA SPI requires buffers to be 8-byte
aligned to use DMA. And, indeed, changing alignment from 4 to 8 throughout the
if_spi.c gave me x2 boost in large file transfer rate. I've thought about adding
a LIBERTAS_SPI_DMA_ALIGN option to drivers/net/wireless/Kconfig to allow
platforms to select required DMA alignment.

If it sounds reasonable, I can send a patch with the proposed changes.

> Dan
> 
> 

-- 
Sincerely yours,
Mike.



From colin at cozybit.com  Tue Jan 27 12:43:35 2009
From: colin at cozybit.com (Colin McCabe)
Date: Tue, 27 Jan 2009 09:43:35 -0800
Subject: Libertas with if_spi on pxa270
In-Reply-To: <497EF54C.8070907@compulab.co.il>
References: <497DCFA2.3070508@compulab.co.il>
	<1232983791.6319.9.camel@localhost.localdomain>
	<497DE3CF.6080609@compulab.co.il>
	<1232987940.6319.35.camel@localhost.localdomain>
	<497EF54C.8070907@compulab.co.il>
Message-ID: <314b98fa0901270943pd2031c6y87d11dac77e60c4b@mail.gmail.com>

On Tue, Jan 27, 2009 at 3:51 AM, Mike Rapoport <mike at compulab.co.il> wrote:
> Dan,
>
> Dan Williams wrote:
>> On Mon, 2009-01-26 at 18:24 +0200, Mike Rapoport wrote:
>>> Dan Williams wrote:
>>>> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
>>>>> Hi,
>>>>>
>>>>> Have anybody tried to use 8686 with G-SPI on PXA270?
>>>>> I've merged libertas-related changes from wireless-testing tree on top of
>>>>> 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
>>>>> get from the if_spi was "libertas: Can't read bus mode register." :(
>>>> Have you set up the Chip Select stuff correctly for your board (see
>>>> gpio_cs in the platform data)?  That seems to be board-dependent and
>>>> there's not a good generic way of doing this in the current kernel
>>>> sources.
>>>>
>>>> That error is the first error that will get reported when the driver
>>>> actually tries to talk to the card, which requires that the Chip Select
>>>> stuff be set up correctly.  If you think you've got that already set up,
>>>> can you manually inspect whether or not the libertas device has actually
>>>> been selected on the board?
>>> The first thing I've done was to recheck GPIO setup and platform_data for all
>>> SPI related stuff.
>>> I've even inserted GPIO setup function at the very beginning of if_spi_probe.
>>> The Marvell proprietary driver works well on the same board and exactly same
>>> GPIOs setup.
>>
>> Ok, Colin McCabe will probably need to get involved here then since he
>> wrote those bits :)
>
> You were right about possible problems with my board setup. The 8686 requires
> SPI clock pin to be high at power up to start with G-SPI rather than SDIO. That
> part was missing from my board setup.

Good catch. Our board had pull-up resistors on SCLK, MISO, and CS, so
we never experienced this.

> Still I needed to alter the if_spi.c to make it work. First of all, I think it
> makes sence to add
>
>        spi->bits_per_word = 16;
>        spi_setup(spi);
>
> at the beginning of if_spi_probe.

I would be more in favor of something like
BUG_ON(spi->bits_per_word != 16).
rather than silently overriding the configuration given in the
board-specific files.

regards,
Colin

> Another thing, it's possible worth adding ability to call platform specific
> init/exit functions supplied with libertas_spi_platform_data.
>
> After the driver begun to work I've noted that it's performance is not as good
> as I expected. The reason for it is that PXA SPI requires buffers to be 8-byte
> aligned to use DMA. And, indeed, changing alignment from 4 to 8 throughout the
> if_spi.c gave me x2 boost in large file transfer rate. I've thought about adding
> a LIBERTAS_SPI_DMA_ALIGN option to drivers/net/wireless/Kconfig to allow
> platforms to select required DMA alignment.
>
> If it sounds reasonable, I can send a patch with the proposed changes.
>
>> Dan
>>
>>
>
> --
> Sincerely yours,
> Mike.
>
>


From dcbw at redhat.com  Tue Jan 27 13:50:32 2009
From: dcbw at redhat.com (Dan Williams)
Date: Tue, 27 Jan 2009 13:50:32 -0500
Subject: Libertas with if_spi on pxa270
In-Reply-To: <497EF54C.8070907@compulab.co.il>
References: <497DCFA2.3070508@compulab.co.il>
	<1232983791.6319.9.camel@localhost.localdomain>
	<497DE3CF.6080609@compulab.co.il>
	<1232987940.6319.35.camel@localhost.localdomain>
	<497EF54C.8070907@compulab.co.il>
Message-ID: <1233082232.25367.13.camel@localhost.localdomain>

On Tue, 2009-01-27 at 13:51 +0200, Mike Rapoport wrote:
> Dan,
> 
> Dan Williams wrote:
> > On Mon, 2009-01-26 at 18:24 +0200, Mike Rapoport wrote:
> >> Dan Williams wrote:
> >>> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
> >>>> Hi,
> >>>>
> >>>> Have anybody tried to use 8686 with G-SPI on PXA270?
> >>>> I've merged libertas-related changes from wireless-testing tree on top of
> >>>> 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
> >>>> get from the if_spi was "libertas: Can't read bus mode register." :(
> >>> Have you set up the Chip Select stuff correctly for your board (see
> >>> gpio_cs in the platform data)?  That seems to be board-dependent and
> >>> there's not a good generic way of doing this in the current kernel
> >>> sources.
> >>>
> >>> That error is the first error that will get reported when the driver
> >>> actually tries to talk to the card, which requires that the Chip Select
> >>> stuff be set up correctly.  If you think you've got that already set up,
> >>> can you manually inspect whether or not the libertas device has actually
> >>> been selected on the board?
> >> The first thing I've done was to recheck GPIO setup and platform_data for all
> >> SPI related stuff.
> >> I've even inserted GPIO setup function at the very beginning of if_spi_probe.
> >> The Marvell proprietary driver works well on the same board and exactly same
> >> GPIOs setup.
> > 
> > Ok, Colin McCabe will probably need to get involved here then since he
> > wrote those bits :)
> 
> You were right about possible problems with my board setup. The 8686 requires
> SPI clock pin to be high at power up to start with G-SPI rather than SDIO. That
> part was missing from my board setup.
> Still I needed to alter the if_spi.c to make it work. First of all, I think it
> makes sence to add
> 
> 	spi->bits_per_word = 16;
> 	spi_setup(spi);
> 
> at the beginning of if_spi_probe.

Is that a restriction of/optimization for the SPI controller?  See below
if it is...  It seems like the SPI layer in the kernel has a bit of
maturation to do.

> Another thing, it's possible worth adding ability to call platform specific
> init/exit functions supplied with libertas_spi_platform_data.
> 
> After the driver begun to work I've noted that it's performance is not as good
> as I expected. The reason for it is that PXA SPI requires buffers to be 8-byte
> aligned to use DMA. And, indeed, changing alignment from 4 to 8 throughout the
> if_spi.c gave me x2 boost in large file transfer rate. I've thought about adding
> a LIBERTAS_SPI_DMA_ALIGN option to drivers/net/wireless/Kconfig to allow
> platforms to select required DMA alignment.

The alignment issue is a controller specific issue and should be quirked
in the SPI controller code (where the restriction really lies),
hopefully not in the libertas code itself.

Colin must/may have had a reason to only use 4-byte alignment; perhaps
his controller requires it.  But that re-inforces the point that if the
controller has the quirks, they should be handled in the controller code
as much as possible.

Dan




From andrey at cozybit.com  Tue Jan 27 14:00:49 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Tue, 27 Jan 2009 11:00:49 -0800
Subject: Libertas with if_spi on pxa270
In-Reply-To: <1233082232.25367.13.camel@localhost.localdomain>
References: <497DCFA2.3070508@compulab.co.il>
	<1232983791.6319.9.camel@localhost.localdomain>
	<497DE3CF.6080609@compulab.co.il>
	<1232987940.6319.35.camel@localhost.localdomain>
	<497EF54C.8070907@compulab.co.il>
	<1233082232.25367.13.camel@localhost.localdomain>
Message-ID: <45e8e6c40901271100pd6f4c32n11e74a1f1fc2fe04@mail.gmail.com>

On Tue, Jan 27, 2009 at 10:50 AM, Dan Williams <dcbw at redhat.com> wrote:
> On Tue, 2009-01-27 at 13:51 +0200, Mike Rapoport wrote:
>> Dan,
>>
>> Dan Williams wrote:
>> > On Mon, 2009-01-26 at 18:24 +0200, Mike Rapoport wrote:
>> >> Dan Williams wrote:
>> >>> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
>> >>>> Hi,
>> >>>>
>> >>>> Have anybody tried to use 8686 with G-SPI on PXA270?
>> >>>> I've merged libertas-related changes from wireless-testing tree on top of
>> >>>> 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
>> >>>> get from the if_spi was "libertas: Can't read bus mode register." :(
>> >>> Have you set up the Chip Select stuff correctly for your board (see
>> >>> gpio_cs in the platform data)?  That seems to be board-dependent and
>> >>> there's not a good generic way of doing this in the current kernel
>> >>> sources.
>> >>>
>> >>> That error is the first error that will get reported when the driver
>> >>> actually tries to talk to the card, which requires that the Chip Select
>> >>> stuff be set up correctly.  If you think you've got that already set up,
>> >>> can you manually inspect whether or not the libertas device has actually
>> >>> been selected on the board?
>> >> The first thing I've done was to recheck GPIO setup and platform_data for all
>> >> SPI related stuff.
>> >> I've even inserted GPIO setup function at the very beginning of if_spi_probe.
>> >> The Marvell proprietary driver works well on the same board and exactly same
>> >> GPIOs setup.
>> >
>> > Ok, Colin McCabe will probably need to get involved here then since he
>> > wrote those bits :)
>>
>> You were right about possible problems with my board setup. The 8686 requires
>> SPI clock pin to be high at power up to start with G-SPI rather than SDIO. That
>> part was missing from my board setup.
>> Still I needed to alter the if_spi.c to make it work. First of all, I think it
>> makes sence to add
>>
>>       spi->bits_per_word = 16;
>>       spi_setup(spi);
>>
>> at the beginning of if_spi_probe.
>
> Is that a restriction of/optimization for the SPI controller?  See below
> if it is...  It seems like the SPI layer in the kernel has a bit of
> maturation to do.

Yeah, it's likely a CPU architecture / DMA issue (alignment for
transfers between system memory and the controller) so it will be
different for ARM vs. Blackfin, etc.

>> Another thing, it's possible worth adding ability to call platform specific
>> init/exit functions supplied with libertas_spi_platform_data.
>>
>> After the driver begun to work I've noted that it's performance is not as good
>> as I expected. The reason for it is that PXA SPI requires buffers to be 8-byte
>> aligned to use DMA. And, indeed, changing alignment from 4 to 8 throughout the
>> if_spi.c gave me x2 boost in large file transfer rate. I've thought about adding
>> a LIBERTAS_SPI_DMA_ALIGN option to drivers/net/wireless/Kconfig to allow
>> platforms to select required DMA alignment.
>
> The alignment issue is a controller specific issue and should be quirked
> in the SPI controller code (where the restriction really lies),
> hopefully not in the libertas code itself.
>
> Colin must/may have had a reason to only use 4-byte alignment; perhaps
> his controller requires it.  But that re-inforces the point that if the
> controller has the quirks, they should be handled in the controller code
> as much as possible.

4-byte alignment is the 'minimum' required for the card's firmware.
For what it's worth, I tried swapping it out for 8-byte alignment as
Mike used and it didn't have any negative (or positive) side effects
on the Blackfin, and it of course still works with the firmware.  I
suppose that we could use 8-byte alignment as a more general case but
I agree that it would be better to solve this in the controller code
if possible.

  -Andrey


From u.luckas at road.de  Tue Jan 27 14:44:01 2009
From: u.luckas at road.de (Uli Luckas)
Date: Tue, 27 Jan 2009 20:44:01 +0100
Subject: Libertas with if_spi on pxa270
In-Reply-To: <497EF54C.8070907@compulab.co.il>
References: <497DCFA2.3070508@compulab.co.il>
	<1232987940.6319.35.camel@localhost.localdomain>
	<497EF54C.8070907@compulab.co.il>
Message-ID: <200901272044.01760.u.luckas@road.de>

On Tuesday, 27. January 2009, Mike Rapoport wrote:
> Dan,
>
> Dan Williams wrote:
> > On Mon, 2009-01-26 at 18:24 +0200, Mike Rapoport wrote:
> >> Dan Williams wrote:
> >>> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
> >>>> Hi,
> >>>>
> >>>> Have anybody tried to use 8686 with G-SPI on PXA270?
> >>>> I've merged libertas-related changes from wireless-testing tree on top
> >>>> of 2.6.29-rc2, added a "libertas_spi" device to my platform code, but
> >>>> all I could get from the if_spi was "libertas: Can't read bus mode
> >>>> register." :(
> >>>
> >>> Have you set up the Chip Select stuff correctly for your board (see
> >>> gpio_cs in the platform data)?  That seems to be board-dependent and
> >>> there's not a good generic way of doing this in the current kernel
> >>> sources.
> >>>
> >>> That error is the first error that will get reported when the driver
> >>> actually tries to talk to the card, which requires that the Chip Select
> >>> stuff be set up correctly.  If you think you've got that already set
> >>> up, can you manually inspect whether or not the libertas device has
> >>> actually been selected on the board?
> >>
> >> The first thing I've done was to recheck GPIO setup and platform_data
> >> for all SPI related stuff.
> >> I've even inserted GPIO setup function at the very beginning of
> >> if_spi_probe. The Marvell proprietary driver works well on the same
> >> board and exactly same GPIOs setup.
> >
> > Ok, Colin McCabe will probably need to get involved here then since he
> > wrote those bits :)
>
> You were right about possible problems with my board setup. The 8686
> requires SPI clock pin to be high at power up to start with G-SPI rather
> than SDIO. That part was missing from my board setup.
> Still I needed to alter the if_spi.c to make it work. 
>
Does that mean, you got it working on PXA? Mine won't work.
On pxa270, kernel 2.6.27.3 + "gspi patch" + "16bit/word spi mode" I get the 
following log:

Jan 26 19:39:44 [kernel] [  242.422220] libertas_spi: Libertas SPI driver
Jan 26 19:39:44 [kernel] [  242.425066] firmware: requesting 
libertas/gspi8686_hlp.bin
Jan 26 19:39:45 [kernel] [  243.089646] firmware: requesting 
libertas/gspi8686.bin
Jan 26 19:39:49 [kernel] [  247.049868] libertas: command 0x0003 timed out
Jan 26 19:39:49 [kernel] [  247.049937] libertas: requeueing command 0x0003 
due to timeout (#1)
Jan 26 19:39:49 [kernel] [  247.051820] libertas: Received result 0 to command 
3 after 1 retries
Jan 26 19:39:49 [kernel] [  247.051989] libertas: 00:15:af:3a:8a:9a, fw 
9.70.10p0, cap 0x00000303
Jan 26 19:39:49 [kernel] [  247.057863] libertas: Received CMD_RESP with 
invalid sequence 1 (expected 2)
Jan 26 19:39:52 [kernel] [  250.049932] libertas: command 0x0028 timed out
Jan 26 19:39:52 [kernel] [  250.050016] libertas: requeueing command 0x0028 
due to timeout (#1)
Jan 26 19:39:52 [kernel] [  250.051814] libertas: Received result 0 to command 
28 after 1 retries
Jan 26 19:39:52 [kernel] [  250.053530] libertas: Received CMD_RESP with 
invalid sequence 2 (expected 3)
Jan 26 19:39:55 [kernel] [  253.049850] libertas: command 0x001d timed out
Jan 26 19:39:55 [kernel] [  253.049919] libertas: requeueing command 0x001d 
due to timeout (#1)
Jan 26 19:39:55 [kernel] [  253.051795] libertas: Received result 0 to command 
1d after 1 retries
Jan 26 19:39:55 [kernel] [  253.053982] libertas: Received CMD_RESP with 
invalid sequence 3 (expected 4)
Jan 26 19:39:58 [kernel] [  256.049914] libertas: command 0x00a3 timed out
Jan 26 19:39:58 [kernel] [  256.050000] libertas: requeueing command 0x00a3 
due to timeout (#1)
Jan 26 19:39:58 [kernel] [  256.052128] libertas: Received result 2 to command 
a3 after 1 retries
Jan 26 19:39:58 [kernel] [  256.052278] libertas: PREP_CMD: command 0x00a3 
failed: 2
Jan 26 19:39:58 [kernel] [  256.054505] libertas: Received CMD_RESP with 
invalid sequence 4 (expected 5)
Jan 26 19:40:01 [kernel] [  259.049833] libertas: command 0x00a3 timed out
Jan 26 19:40:01 [kernel] [  259.049901] libertas: requeueing command 0x00a3 
due to timeout (#1)
Jan 26 19:40:01 [kernel] [  259.052018] libertas: Received result 2 to command 
a3 after 1 retries
Jan 26 19:40:01 [kernel] [  259.052146] libertas: PREP_CMD: command 0x00a3 
failed: 2
Jan 26 19:40:01 [kernel] [  259.052205] libertas: eth0: Marvell WLAN 802.11 
adapter

Any idea what could be going wrong here?

Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien


From mike at compulab.co.il  Wed Jan 28 01:47:15 2009
From: mike at compulab.co.il (Mike Rapoport)
Date: Wed, 28 Jan 2009 08:47:15 +0200
Subject: Libertas with if_spi on pxa270
In-Reply-To: <200901272044.01760.u.luckas@road.de>
References: <497DCFA2.3070508@compulab.co.il>
	<1232987940.6319.35.camel@localhost.localdomain>
	<497EF54C.8070907@compulab.co.il>
	<200901272044.01760.u.luckas@road.de>
Message-ID: <497FFF73.30700@compulab.co.il>



Uli Luckas wrote:
> On Tuesday, 27. January 2009, Mike Rapoport wrote:
>> Dan,
>>
>>
> Does that mean, you got it working on PXA? Mine won't work.
> On pxa270, kernel 2.6.27.3 + "gspi patch" + "16bit/word spi mode" I get the 
> following log:
> 
> Jan 26 19:39:44 [kernel] [  242.422220] libertas_spi: Libertas SPI driver
> Jan 26 19:39:44 [kernel] [  242.425066] firmware: requesting 
> libertas/gspi8686_hlp.bin
> Jan 26 19:39:45 [kernel] [  243.089646] firmware: requesting 
> libertas/gspi8686.bin
> Jan 26 19:39:49 [kernel] [  247.049868] libertas: command 0x0003 timed out
> Jan 26 19:39:49 [kernel] [  247.049937] libertas: requeueing command 0x0003 
> due to timeout (#1)
> Jan 26 19:39:49 [kernel] [  247.051820] libertas: Received result 0 to command 
> 3 after 1 retries
> Jan 26 19:39:49 [kernel] [  247.051989] libertas: 00:15:af:3a:8a:9a, fw 
> 9.70.10p0, cap 0x00000303
> Jan 26 19:39:49 [kernel] [  247.057863] libertas: Received CMD_RESP with 
> invalid sequence 1 (expected 2)
> Jan 26 19:39:52 [kernel] [  250.049932] libertas: command 0x0028 timed out
> Jan 26 19:39:52 [kernel] [  250.050016] libertas: requeueing command 0x0028 
> due to timeout (#1)
> Jan 26 19:39:52 [kernel] [  250.051814] libertas: Received result 0 to command 
> 28 after 1 retries
> Jan 26 19:39:52 [kernel] [  250.053530] libertas: Received CMD_RESP with 
> invalid sequence 2 (expected 3)
> Jan 26 19:39:55 [kernel] [  253.049850] libertas: command 0x001d timed out
> Jan 26 19:39:55 [kernel] [  253.049919] libertas: requeueing command 0x001d 
> due to timeout (#1)
> Jan 26 19:39:55 [kernel] [  253.051795] libertas: Received result 0 to command 
> 1d after 1 retries
> Jan 26 19:39:55 [kernel] [  253.053982] libertas: Received CMD_RESP with 
> invalid sequence 3 (expected 4)
> Jan 26 19:39:58 [kernel] [  256.049914] libertas: command 0x00a3 timed out
> Jan 26 19:39:58 [kernel] [  256.050000] libertas: requeueing command 0x00a3 
> due to timeout (#1)
> Jan 26 19:39:58 [kernel] [  256.052128] libertas: Received result 2 to command 
> a3 after 1 retries
> Jan 26 19:39:58 [kernel] [  256.052278] libertas: PREP_CMD: command 0x00a3 
> failed: 2
> Jan 26 19:39:58 [kernel] [  256.054505] libertas: Received CMD_RESP with 
> invalid sequence 4 (expected 5)
> Jan 26 19:40:01 [kernel] [  259.049833] libertas: command 0x00a3 timed out
> Jan 26 19:40:01 [kernel] [  259.049901] libertas: requeueing command 0x00a3 
> due to timeout (#1)
> Jan 26 19:40:01 [kernel] [  259.052018] libertas: Received result 2 to command 
> a3 after 1 retries
> Jan 26 19:40:01 [kernel] [  259.052146] libertas: PREP_CMD: command 0x00a3 
> failed: 2
> Jan 26 19:40:01 [kernel] [  259.052205] libertas: eth0: Marvell WLAN 802.11 
> adapter

> Any idea what could be going wrong here?


From bogus@does.not.exist.com  Wed Jan 21 16:30:48 2009
From: bogus@does.not.exist.com ()
Date: Wed, 21 Jan 2009 21:30:48 -0000
Subject: No subject
Message-ID: <mailman.0.1233125247.2996.libertas-dev@lists.infradead.org>

are not supported by G-SPI firmware. Can you actually use eth0 after the
libertas_spi is loaded?


> Uli
> 

-- 
Sincerely yours,
Mike.



From mike at compulab.co.il  Wed Jan 28 02:25:32 2009
From: mike at compulab.co.il (Mike Rapoport)
Date: Wed, 28 Jan 2009 09:25:32 +0200
Subject: Libertas with if_spi on pxa270
In-Reply-To: <1233082232.25367.13.camel@localhost.localdomain>
References: <497DCFA2.3070508@compulab.co.il>	
	<1232983791.6319.9.camel@localhost.localdomain>	
	<497DE3CF.6080609@compulab.co.il>	
	<1232987940.6319.35.camel@localhost.localdomain>	
	<497EF54C.8070907@compulab.co.il>
	<1233082232.25367.13.camel@localhost.localdomain>
Message-ID: <4980086C.5020403@compulab.co.il>



Dan Williams wrote:
> On Tue, 2009-01-27 at 13:51 +0200, Mike Rapoport wrote:
>> Dan,
>>
>> Dan Williams wrote:
>>> On Mon, 2009-01-26 at 18:24 +0200, Mike Rapoport wrote:
>>>> Dan Williams wrote:
>>>>> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
>>>>>> Hi,
>>>>>>
>>>>>> Have anybody tried to use 8686 with G-SPI on PXA270?
>>>>>> I've merged libertas-related changes from wireless-testing tree on top of
>>>>>> 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
>>>>>> get from the if_spi was "libertas: Can't read bus mode register." :(
>>>>> Have you set up the Chip Select stuff correctly for your board (see
>>>>> gpio_cs in the platform data)?  That seems to be board-dependent and
>>>>> there's not a good generic way of doing this in the current kernel
>>>>> sources.
>>>>>
>>>>> That error is the first error that will get reported when the driver
>>>>> actually tries to talk to the card, which requires that the Chip Select
>>>>> stuff be set up correctly.  If you think you've got that already set up,
>>>>> can you manually inspect whether or not the libertas device has actually
>>>>> been selected on the board?
>>>> The first thing I've done was to recheck GPIO setup and platform_data for all
>>>> SPI related stuff.
>>>> I've even inserted GPIO setup function at the very beginning of if_spi_probe.
>>>> The Marvell proprietary driver works well on the same board and exactly same
>>>> GPIOs setup.
>>> Ok, Colin McCabe will probably need to get involved here then since he
>>> wrote those bits :)
>> You were right about possible problems with my board setup. The 8686 requires
>> SPI clock pin to be high at power up to start with G-SPI rather than SDIO. That
>> part was missing from my board setup.
>> Still I needed to alter the if_spi.c to make it work. First of all, I think it
>> makes sence to add
>>
>> 	spi->bits_per_word = 16;
>> 	spi_setup(spi);
>>
>> at the beginning of if_spi_probe.
> 
> Is that a restriction of/optimization for the SPI controller?  See below
> if it is...  It seems like the SPI layer in the kernel has a bit of
> maturation to do.
> 
>> Another thing, it's possible worth adding ability to call platform specific
>> init/exit functions supplied with libertas_spi_platform_data.
>>
>> After the driver begun to work I've noted that it's performance is not as good
>> as I expected. The reason for it is that PXA SPI requires buffers to be 8-byte
>> aligned to use DMA. And, indeed, changing alignment from 4 to 8 throughout the
>> if_spi.c gave me x2 boost in large file transfer rate. I've thought about adding
>> a LIBERTAS_SPI_DMA_ALIGN option to drivers/net/wireless/Kconfig to allow
>> platforms to select required DMA alignment.
> 
> The alignment issue is a controller specific issue and should be quirked
> in the SPI controller code (where the restriction really lies),
> hopefully not in the libertas code itself.

Currently PXA SPI controller driver reverts to PIO mode when the buffer it gets
is not 8-byte aligned, so from it's point of view there's no issue here :)
It's possible to alter the SPI controller driver to use it's own properly
aligned buffers for DMA and copy the data it gets from the client into these
buffers. However, this approach also impacts overall performance.
Yet another possibility is to add something like 'get_dma_alignment' to SPI
layer and use the returned value for buffers alignment, but if_spi_packet uses
compile-time alignment attribute and I can't see how is it possible to make it
dynamic.

I think that since the G-SPI interface is used only on embedded systems and the
kernel configuration is created by the system vendor, adding a config option
that sets DMA alignment is not that bad after all.

> Colin must/may have had a reason to only use 4-byte alignment; perhaps
> his controller requires it.  But that re-inforces the point that if the
> controller has the quirks, they should be handled in the controller code
> as much as possible.
> 
> Dan
> 
> 

-- 
Sincerely yours,
Mike.



From mike at compulab.co.il  Wed Jan 28 02:25:52 2009
From: mike at compulab.co.il (Mike Rapoport)
Date: Wed, 28 Jan 2009 09:25:52 +0200
Subject: Libertas with if_spi on pxa270
In-Reply-To: <314b98fa0901270943pd2031c6y87d11dac77e60c4b@mail.gmail.com>
References: <497DCFA2.3070508@compulab.co.il>	
	<1232983791.6319.9.camel@localhost.localdomain>	
	<497DE3CF.6080609@compulab.co.il>	
	<1232987940.6319.35.camel@localhost.localdomain>	
	<497EF54C.8070907@compulab.co.il>
	<314b98fa0901270943pd2031c6y87d11dac77e60c4b@mail.gmail.com>
Message-ID: <49800880.7040902@compulab.co.il>



Colin McCabe wrote:
> On Tue, Jan 27, 2009 at 3:51 AM, Mike Rapoport <mike at compulab.co.il> wrote:
>> Dan,
>>
>> Dan Williams wrote:
>>> On Mon, 2009-01-26 at 18:24 +0200, Mike Rapoport wrote:
>>>> Dan Williams wrote:
>>>>> On Mon, 2009-01-26 at 16:58 +0200, Mike Rapoport wrote:
>>>>>> Hi,
>>>>>>
>>>>>> Have anybody tried to use 8686 with G-SPI on PXA270?
>>>>>> I've merged libertas-related changes from wireless-testing tree on top of
>>>>>> 2.6.29-rc2, added a "libertas_spi" device to my platform code, but all I could
>>>>>> get from the if_spi was "libertas: Can't read bus mode register." :(
>>>>> Have you set up the Chip Select stuff correctly for your board (see
>>>>> gpio_cs in the platform data)?  That seems to be board-dependent and
>>>>> there's not a good generic way of doing this in the current kernel
>>>>> sources.
>>>>>
>>>>> That error is the first error that will get reported when the driver
>>>>> actually tries to talk to the card, which requires that the Chip Select
>>>>> stuff be set up correctly.  If you think you've got that already set up,
>>>>> can you manually inspect whether or not the libertas device has actually
>>>>> been selected on the board?
>>>> The first thing I've done was to recheck GPIO setup and platform_data for all
>>>> SPI related stuff.
>>>> I've even inserted GPIO setup function at the very beginning of if_spi_probe.
>>>> The Marvell proprietary driver works well on the same board and exactly same
>>>> GPIOs setup.
>>> Ok, Colin McCabe will probably need to get involved here then since he
>>> wrote those bits :)
>> You were right about possible problems with my board setup. The 8686 requires
>> SPI clock pin to be high at power up to start with G-SPI rather than SDIO. That
>> part was missing from my board setup.
> 
> Good catch. Our board had pull-up resistors on SCLK, MISO, and CS, so
> we never experienced this.
> 
>> Still I needed to alter the if_spi.c to make it work. First of all, I think it
>> makes sence to add
>>
>>        spi->bits_per_word = 16;
>>        spi_setup(spi);
>>
>> at the beginning of if_spi_probe.
> 
> I would be more in favor of something like
> BUG_ON(spi->bits_per_word != 16).
> rather than silently overriding the configuration given in the
> board-specific files.

Currently the only way to set bits_per_word for PXA SPI implementation is using
spi_setup. If we introduce platform-specific init, I can call spi_setup from the
platform-specific init function, at least until this issue with PXA SPI
controller driver is resolved.

> regards,
> Colin
> 
>> Another thing, it's possible worth adding ability to call platform specific
>> init/exit functions supplied with libertas_spi_platform_data.
>>
>> After the driver begun to work I've noted that it's performance is not as good
>> as I expected. The reason for it is that PXA SPI requires buffers to be 8-byte
>> aligned to use DMA. And, indeed, changing alignment from 4 to 8 throughout the
>> if_spi.c gave me x2 boost in large file transfer rate. I've thought about adding
>> a LIBERTAS_SPI_DMA_ALIGN option to drivers/net/wireless/Kconfig to allow
>> platforms to select required DMA alignment.
>>
>> If it sounds reasonable, I can send a patch with the proposed changes.
>>
>>> Dan
>>>
>>>
>> --
>> Sincerely yours,
>> Mike.
>>
>>
> 

-- 
Sincerely yours,
Mike.



From eauth at softsys.co.at  Wed Jan 28 03:34:31 2009
From: eauth at softsys.co.at (Erwin Authried)
Date: Wed, 28 Jan 2009 09:34:31 +0100
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
In-Reply-To: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
References: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
Message-ID: <1233131671.17900.220.camel@justakiss.home.at>

is it really necessary to pack all structures in hostcmd.h? The "packed"
attribute makes the code larger and slower. I have changed the order in
the lbs_private structure in dev.h a little bit so that resp_buf is on a
32-bit boundary. Then, I have removed most of the packed attributes in
hostcmd.h (where all 16 or 32-bit Variables are on 16/32 bit boundaries
anyway). The libertas module is a bit smaller, and I haven't seen any
problem.

-Erwin 

Am Montag, den 12.01.2009, 13:14 -0800 schrieb Andrey Yurovsky:
> Data structures that come over the wire from the WLAN firmware must be packed.
> This fixes alignment problems on the blackfin architecture and, reportedly, on
> the AVR32.
> 
> This is a replacement for the previous version of this patch which had also
> explicitly used get_unaligned_ macros.  As Johannes Berg pointed out, these 
> macros were unnecessary.
> 
> Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
> Signed-off-by: Colin McCabe <colin at cozybit.com>
> diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
> index 2d8533c..a899aeb 100644
> --- a/drivers/net/wireless/libertas/hostcmd.h
> +++ b/drivers/net/wireless/libertas/hostcmd.h
> @@ -32,7 +32,7 @@ struct txpd {
>  	u8 pktdelay_2ms;
>  	/* reserved */
>  	u8 reserved1;
> -};
> +} __attribute__ ((packed));
>  
>  /* RxPD Descriptor */
>  struct rxpd {
> @@ -63,7 +63,7 @@ struct rxpd {
>  	/* Pkt Priority */
>  	u8 priority;
>  	u8 reserved[3];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_header {
>  	__le16 command;
> @@ -97,7 +97,7 @@ struct enc_key {
>  struct lbs_offset_value {
>  	u32 offset;
>  	u32 value;
> -};
> +} __attribute__ ((packed));
>  
>  /* Define general data structure */
>  /* cmd_DS_GEN */
> @@ -107,7 +107,7 @@ struct cmd_ds_gen {
>  	__le16 seqnum;
>  	__le16 result;
>  	void *cmdresp[0];
> -};
> +} __attribute__ ((packed));
>  
>  #define S_DS_GEN sizeof(struct cmd_ds_gen)
>  
> @@ -163,7 +163,7 @@ struct cmd_ds_802_11_subscribe_event {
>  	 * bump this up a bit.
>  	 */
>  	uint8_t tlv[128];
> -};
> +} __attribute__ ((packed));
>  
>  /*
>   * This scan handle Country Information IE(802.11d compliant)
> @@ -180,7 +180,7 @@ struct cmd_ds_802_11_scan {
>  	mrvlietypes_chanlistparamset_t ChanListParamSet;
>  	mrvlietypes_ratesparamset_t OpRateSet;
>  #endif
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_scan_rsp {
>  	struct cmd_header hdr;
> @@ -188,7 +188,7 @@ struct cmd_ds_802_11_scan_rsp {
>  	__le16 bssdescriptsize;
>  	uint8_t nr_sets;
>  	uint8_t bssdesc_and_tlvbuffer[0];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_get_log {
>  	struct cmd_header hdr;
> @@ -206,20 +206,20 @@ struct cmd_ds_802_11_get_log {
>  	__le32 fcserror;
>  	__le32 txframe;
>  	__le32 wepundecryptable;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_mac_control {
>  	struct cmd_header hdr;
>  	__le16 action;
>  	u16 reserved;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_mac_multicast_adr {
>  	struct cmd_header hdr;
>  	__le16 action;
>  	__le16 nr_of_adrs;
>  	u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_gspi_bus_config {
>  	struct cmd_header hdr;
> @@ -233,14 +233,14 @@ struct cmd_ds_802_11_authenticate {
>  	u8 macaddr[ETH_ALEN];
>  	u8 authtype;
>  	u8 reserved[10];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_deauthenticate {
>  	struct cmd_header hdr;
>  
>  	u8 macaddr[ETH_ALEN];
>  	__le16 reasoncode;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_associate {
>  	u8 peerstaaddr[6];
> @@ -259,7 +259,7 @@ struct cmd_ds_802_11_associate {
>  
>  struct cmd_ds_802_11_associate_rsp {
>  	struct ieeetypes_assocrsp assocRsp;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_set_wep {
>  	struct cmd_header hdr;
> @@ -273,7 +273,7 @@ struct cmd_ds_802_11_set_wep {
>  	/* 40, 128bit or TXWEP */
>  	uint8_t keytype[4];
>  	uint8_t keymaterial[4][16];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_3_get_stat {
>  	__le32 xmitok;
> @@ -282,7 +282,7 @@ struct cmd_ds_802_3_get_stat {
>  	__le32 rcverror;
>  	__le32 rcvnobuffer;
>  	__le32 rcvcrcerror;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_get_stat {
>  	__le32 txfragmentcnt;
> @@ -302,7 +302,7 @@ struct cmd_ds_802_11_get_stat {
>  	__le32 txbeacon;
>  	__le32 rxbeacon;
>  	__le32 wepundecryptable;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_snmp_mib {
>  	struct cmd_header hdr;
> @@ -311,58 +311,58 @@ struct cmd_ds_802_11_snmp_mib {
>  	__le16 oid;
>  	__le16 bufsize;
>  	u8 value[128];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_mac_reg_map {
>  	__le16 buffersize;
>  	u8 regmap[128];
>  	__le16 reserved;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_bbp_reg_map {
>  	__le16 buffersize;
>  	u8 regmap[128];
>  	__le16 reserved;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_rf_reg_map {
>  	__le16 buffersize;
>  	u8 regmap[64];
>  	__le16 reserved;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_mac_reg_access {
>  	__le16 action;
>  	__le16 offset;
>  	__le32 value;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_bbp_reg_access {
>  	__le16 action;
>  	__le16 offset;
>  	u8 value;
>  	u8 reserved[3];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_rf_reg_access {
>  	__le16 action;
>  	__le16 offset;
>  	u8 value;
>  	u8 reserved[3];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_radio_control {
>  	struct cmd_header hdr;
>  
>  	__le16 action;
>  	__le16 control;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_beacon_control {
>  	__le16 action;
>  	__le16 beacon_enable;
>  	__le16 beacon_period;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_sleep_params {
>  	struct cmd_header hdr;
> @@ -387,7 +387,7 @@ struct cmd_ds_802_11_sleep_params {
>  
>  	/* reserved field, should be set to zero */
>  	__le16 reserved;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_inactivity_timeout {
>  	struct cmd_header hdr;
> @@ -397,7 +397,7 @@ struct cmd_ds_802_11_inactivity_timeout {
>  
>  	/* Inactivity timeout in msec */
>  	__le16 timeout;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_rf_channel {
>  	struct cmd_header hdr;
> @@ -407,7 +407,7 @@ struct cmd_ds_802_11_rf_channel {
>  	__le16 rftype;      /* unused */
>  	__le16 reserved;    /* unused */
>  	u8 channellist[32]; /* unused */
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_rssi {
>  	/* weighting factor */
> @@ -416,21 +416,21 @@ struct cmd_ds_802_11_rssi {
>  	__le16 reserved_0;
>  	__le16 reserved_1;
>  	__le16 reserved_2;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_rssi_rsp {
>  	__le16 SNR;
>  	__le16 noisefloor;
>  	__le16 avgSNR;
>  	__le16 avgnoisefloor;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_mac_address {
>  	struct cmd_header hdr;
>  
>  	__le16 action;
>  	u8 macadd[ETH_ALEN];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_rf_tx_power {
>  	struct cmd_header hdr;
> @@ -439,7 +439,7 @@ struct cmd_ds_802_11_rf_tx_power {
>  	__le16 curlevel;
>  	s8 maxlevel;
>  	s8 minlevel;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_rf_antenna {
>  	__le16 action;
> @@ -447,33 +447,33 @@ struct cmd_ds_802_11_rf_antenna {
>  	/* Number of antennas or 0xffff(diversity) */
>  	__le16 antennamode;
>  
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_monitor_mode {
>  	__le16 action;
>  	__le16 mode;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_set_boot2_ver {
>  	struct cmd_header hdr;
>  
>  	__le16 action;
>  	__le16 version;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_fw_wake_method {
>  	struct cmd_header hdr;
>  
>  	__le16 action;
>  	__le16 method;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_sleep_period {
>  	struct cmd_header hdr;
>  
>  	__le16 action;
>  	__le16 period;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_ps_mode {
>  	__le16 action;
> @@ -481,7 +481,7 @@ struct cmd_ds_802_11_ps_mode {
>  	__le16 multipledtim;
>  	__le16 reserved;
>  	__le16 locallisteninterval;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_confirm_sleep {
>  	struct cmd_header hdr;
> @@ -491,7 +491,7 @@ struct cmd_confirm_sleep {
>  	__le16 multipledtim;
>  	__le16 reserved;
>  	__le16 locallisteninterval;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_data_rate {
>  	struct cmd_header hdr;
> @@ -499,14 +499,14 @@ struct cmd_ds_802_11_data_rate {
>  	__le16 action;
>  	__le16 reserved;
>  	u8 rates[MAX_RATES];
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_rate_adapt_rateset {
>  	struct cmd_header hdr;
>  	__le16 action;
>  	__le16 enablehwauto;
>  	__le16 bitmap;
> -};
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_802_11_ad_hoc_start {
>  	struct cmd_header hdr;
> @@ -528,7 +528,7 @@ struct cmd_ds_802_11_ad_hoc_result {
>  
>  	u8 pad[3];
>  	u8 bssid[ETH_ALEN];
> -};
> +} __attribute__ ((packed));
>  
>  struct adhoc_bssdesc {
>  	u8 bssid[ETH_ALEN];
> @@ -586,7 +586,7 @@ struct MrvlIEtype_keyParamSet {
>  
>  	/* key material of size keylen */
>  	u8 key[32];
> -};
> +} __attribute__ ((packed));
>  
>  #define MAX_WOL_RULES 		16
>  
> @@ -598,7 +598,7 @@ struct host_wol_rule {
>  	__le16 reserve;
>  	__be32 sig_mask;
>  	__be32 signature;
> -};
> +} __attribute__ ((packed));
>  
>  struct wol_config {
>  	uint8_t action;
> @@ -606,8 +606,7 @@ struct wol_config {
>  	uint8_t no_rules_in_cmd;
>  	uint8_t result;
>  	struct host_wol_rule rule[MAX_WOL_RULES];
> -};
> -
> +} __attribute__ ((packed));
>  
>  struct cmd_ds_host_sleep {
>  	struct cmd_header hdr;
> 
> 
> 
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev
-- 
Dipl.-Ing. Erwin Authried
Softwareentwicklung und Systemdesign



From u.luckas at road.de  Wed Jan 28 04:29:37 2009
From: u.luckas at road.de (Uli Luckas)
Date: Wed, 28 Jan 2009 10:29:37 +0100
Subject: Libertas with if_spi on pxa270
In-Reply-To: <497FFF73.30700@compulab.co.il>
References: <497DCFA2.3070508@compulab.co.il>
	<200901272044.01760.u.luckas@road.de>
	<497FFF73.30700@compulab.co.il>
Message-ID: <200901281029.37751.u.luckas@road.de>

On Wednesday, 28. January 2009, Mike Rapoport wrote:
> Uli Luckas wrote:
> > On Tuesday, 27. January 2009, Mike Rapoport wrote:
> >> Dan,
> >
> > Does that mean, you got it working on PXA? Mine won't work.
> > On pxa270, kernel 2.6.27.3 + "gspi patch" + "16bit/word spi mode" I get
> > the following log:
> >
> > Jan 26 19:39:44 [kernel] [  242.422220] libertas_spi: Libertas SPI driver
> > Jan 26 19:39:44 [kernel] [  242.425066] firmware: requesting
> > libertas/gspi8686_hlp.bin
> > Jan 26 19:39:45 [kernel] [  243.089646] firmware: requesting
> > libertas/gspi8686.bin
> > Jan 26 19:39:49 [kernel] [  247.049868] libertas: command 0x0003 timed
> > out Jan 26 19:39:49 [kernel] [  247.049937] libertas: requeueing command
> > 0x0003 due to timeout (#1)
> > Jan 26 19:39:49 [kernel] [  247.051820] libertas: Received result 0 to
> > command 3 after 1 retries
> > Jan 26 19:39:49 [kernel] [  247.051989] libertas: 00:15:af:3a:8a:9a, fw
> > 9.70.10p0, cap 0x00000303
> > Jan 26 19:39:49 [kernel] [  247.057863] libertas: Received CMD_RESP with
> > invalid sequence 1 (expected 2)
> > Jan 26 19:39:52 [kernel] [  250.049932] libertas: command 0x0028 timed
> > out Jan 26 19:39:52 [kernel] [  250.050016] libertas: requeueing command
> > 0x0028 due to timeout (#1)
> > Jan 26 19:39:52 [kernel] [  250.051814] libertas: Received result 0 to
> > command 28 after 1 retries
> > Jan 26 19:39:52 [kernel] [  250.053530] libertas: Received CMD_RESP with
> > invalid sequence 2 (expected 3)
> > Jan 26 19:39:55 [kernel] [  253.049850] libertas: command 0x001d timed
> > out Jan 26 19:39:55 [kernel] [  253.049919] libertas: requeueing command
> > 0x001d due to timeout (#1)
> > Jan 26 19:39:55 [kernel] [  253.051795] libertas: Received result 0 to
> > command 1d after 1 retries
> > Jan 26 19:39:55 [kernel] [  253.053982] libertas: Received CMD_RESP with
> > invalid sequence 3 (expected 4)
> > Jan 26 19:39:58 [kernel] [  256.049914] libertas: command 0x00a3 timed
> > out Jan 26 19:39:58 [kernel] [  256.050000] libertas: requeueing command
> > 0x00a3 due to timeout (#1)
> > Jan 26 19:39:58 [kernel] [  256.052128] libertas: Received result 2 to
> > command a3 after 1 retries
> > Jan 26 19:39:58 [kernel] [  256.052278] libertas: PREP_CMD: command
> > 0x00a3 failed: 2
> > Jan 26 19:39:58 [kernel] [  256.054505] libertas: Received CMD_RESP with
> > invalid sequence 4 (expected 5)
> > Jan 26 19:40:01 [kernel] [  259.049833] libertas: command 0x00a3 timed
> > out Jan 26 19:40:01 [kernel] [  259.049901] libertas: requeueing command
> > 0x00a3 due to timeout (#1)
> > Jan 26 19:40:01 [kernel] [  259.052018] libertas: Received result 2 to
> > command a3 after 1 retries
> > Jan 26 19:40:01 [kernel] [  259.052146] libertas: PREP_CMD: command
> > 0x00a3 failed: 2
> > Jan 26 19:40:01 [kernel] [  259.052205] libertas: eth0: Marvell WLAN
> > 802.11 adapter
> >
> > Any idea what could be going wrong here?
>
> From what I can tell, libertas initialization is successful. The failed
> commands are not supported by G-SPI firmware. 
I am using the firmware from the linux-firmware git tree. If this firmware 
does not support some of the commands, then everyone should see these 
messages.

What about the "Received CMD_RESP with invalid sequence n (expected n+1)" 
messages? Is anyone else seeing those? Are they part of my problem? Or do 
they hint at a seperate problem, maybe triggered by the 'real' problem?

> Can you actually use eth0 after the libertas_spi is loaded?
>
'ifconfig eth0 up' works, 'iwlist eth0 scan' does not work. I get many more 
messages like the ones quoted above and after quite a while the scan fails.
I've not tried to assoicate to an AP yet.

thanks,
Uli

-- 

------- ROAD ...the handyPC Company - - -  ) ) )

Uli Luckas
Head of Software Development

ROAD GmbH
Bennigsenstr. 14 | 12159 Berlin | Germany
fon: +49 (30) 230069 - 62 | fax: +49 (30) 230069 - 69
url: www.road.de

Amtsgericht Charlottenburg: HRB 96688 B
Managing director: Hans-Peter Constien


From mike at compulab.co.il  Wed Jan 28 04:54:09 2009
From: mike at compulab.co.il (Mike Rapoport)
Date: Wed, 28 Jan 2009 11:54:09 +0200
Subject: Libertas with if_spi on pxa270
In-Reply-To: <200901281029.37751.u.luckas@road.de>
References: <497DCFA2.3070508@compulab.co.il>
	<200901272044.01760.u.luckas@road.de>
	<497FFF73.30700@compulab.co.il>
	<200901281029.37751.u.luckas@road.de>
Message-ID: <49802B41.2010004@compulab.co.il>

Uli Luckas wrote:
>>> Does that mean, you got it working on PXA? Mine won't work.
>>> On pxa270, kernel 2.6.27.3 + "gspi patch" + "16bit/word spi mode" I get
>>> the following log:
>>>

[ snip ]

>>>
>>> Any idea what could be going wrong here?
>> From what I can tell, libertas initialization is successful. The failed
>> commands are not supported by G-SPI firmware. 
> I am using the firmware from the linux-firmware git tree. If this firmware 
> does not support some of the commands, then everyone should see these 
> messages.
> 
> What about the "Received CMD_RESP with invalid sequence n (expected n+1)" 
> messages? Is anyone else seeing those? Are they part of my problem? Or do 
> they hint at a seperate problem, maybe triggered by the 'real' problem?

I'm using 2.6.29-rc2 + "git diff-tree v2.6.29-rc2 wireless-testing/master --
drivers/net/wireless/libertas" + "16bit/word spi mode" and

With 9.70.3p37 firmware from Marvell. I get:

# modprobe  libertas_spi
lib80211: common routines for IEEE802.11 drivers
libertas_spi: Libertas SPI driver
libertas_spi spi2.0: firmware: requesting libertas/gspi8686_hlp.bin
libertas_spi spi2.0: firmware: requesting libertas/gspi8686.bin
libertas: 00:19:88:05:b1:59, fw 9.70.3p37, cap 0x00000303
eth1 (libertas_spi): not using net_device_ops yet
libertas: PREP_CMD: command 0x00a3 failed: 2
libertas: PREP_CMD: command 0x00a3 failed: 2
libertas: eth1: Marvell WLAN 802.11 adapter

and I never saw "Received CMD_RESP with invalid sequence n (expected n+1)".

With gspi8686_v9.bin and gspi8686_v9_helper.bin from linux-firmware I get

# modprobe libertas_spi
lib80211: common routines for IEEE802.11 drivers
libertas_spi: Libertas SPI driver
libertas_spi spi2.0: firmware: requesting libertas/gspi8686_hlp.bin
libertas_spi spi2.0: firmware: requesting libertas/gspi8686.bin
libertas: spu_wait_for_u16: timeout with val=00, target_mask=00, target=00
libertas: if_spi_prog_main_firmware: timed out waiting for initial scratch reg = 0
libertas: failed to load firmware (err=-110)
libertas_spi: probe of spi2.0 failed with error -110


>> Can you actually use eth0 after the libertas_spi is loaded?
>>
> 'ifconfig eth0 up' works, 'iwlist eth0 scan' does not work. I get many more 
> messages like the ones quoted above and after quite a while the scan fails.
> I've not tried to assoicate to an AP yet.
> 
> thanks,
> Uli
> 

-- 
Sincerely yours,
Mike.



From erlindawilliams27 at yahoo.com  Wed Jan 28 09:30:57 2009
From: erlindawilliams27 at yahoo.com (Madam Erlinda Williams)
Date: Wed, 28 Jan 2009 15:30:57 +0100
Subject: See that this money  is distributed to charity organizations
Message-ID: <E1LSBRR-0008Cb-9k@srv214.hosteur.com>

Dear Blessed One,

Greetings to you blessed one. As you read through my message, I do not want you to feel pity or sorry for me, for I believe someday, somehow, we will all surely die, this is about mine, and a last wish. My name is Madam Erlinda Williams, a Citizen of the united kingdom, I am a 53 years old woman, I am diagnosed of Cancer of the Larynx and it is terminal, medical science can not do anything for me at this stage. I believe in miracles because I believe in GOD, however I prefer to pass on at this stage since I am bed ridden and in constant pain. Before this happened my business and concern for making money was all I lived for, I never really cared about other values in life. But since my present situation, I have found a new desire to assist helpless families.

I have been helping orphans in orphanage/motherless homs. I have once donated some money to orphans in war ravaged Eritrea,Somalia, Sudan and some East European Countries. Having known my condition I decided to entrust my last funds I have deposited in Europe( USD$ 6.7 MILLION) to either a philanthropic or devoted individual that will use his judgement to distribute the money to charity organizations, orhanages and feel free to reimburse yourself when you have the money with a total of 35% for your assistance also for any cost you incur during the process of collecting and distributing the money to charity organizations. I have left the hospital and presently at home, I have since lost my ability to talk and my doctors have told me that I have only few months to live.

It is my last wish to see this money distributed to charity organizations, because I don't have any child and my relatives and friends has plundered so much of my wealth since my illness, I cannot live with the agony of entrusting this huge responsibility to any of them anymre. Please, I beg you in the name of God to help me collect the deposit and distribute it amongst charity organizations anbd orhnage homes. Since my health is retrogressing by the minute, you will have to send your: POSTAL ADDRESS, CONTACT PHONE NUMBER AND FAX and a little details about yourself, because I got your address from Chamber of Commerce of your country after a thorough search. With the information, I will make arrangement to prepare the authorization through an Attorney for you to get possession of the Deposit. I will give you the name and contact of the Deposit company where the money is lodged,thereafter, so you can claim the funds, Until I hear from you, I pray that this letter bring you and your family good tidings.

Please Send your urgent reply to my direct email address for confidential reasons(madamerlinda at gmail.com)

Looking forward to hearing from you soonest. 

Regards,
Madam Erlinda Williams






From andrey at cozybit.com  Wed Jan 28 10:45:50 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Wed, 28 Jan 2009 07:45:50 -0800
Subject: Libertas with if_spi on pxa270
In-Reply-To: <49802B41.2010004@compulab.co.il>
References: <497DCFA2.3070508@compulab.co.il>
	<200901272044.01760.u.luckas@road.de> <497FFF73.30700@compulab.co.il>
	<200901281029.37751.u.luckas@road.de>
	<49802B41.2010004@compulab.co.il>
Message-ID: <45e8e6c40901280745i72d140dfhf04afc5d9c4e75ee@mail.gmail.com>

On Wed, Jan 28, 2009 at 1:54 AM, Mike Rapoport <mike at compulab.co.il> wrote:
> Uli Luckas wrote:
>>>> Does that mean, you got it working on PXA? Mine won't work.
>>>> On pxa270, kernel 2.6.27.3 + "gspi patch" + "16bit/word spi mode" I get
>>>> the following log:
>>>>
>
> [ snip ]
>
>>>>
>>>> Any idea what could be going wrong here?
>>> From what I can tell, libertas initialization is successful. The failed
>>> commands are not supported by G-SPI firmware.
>> I am using the firmware from the linux-firmware git tree. If this firmware
>> does not support some of the commands, then everyone should see these
>> messages.
>>
>> What about the "Received CMD_RESP with invalid sequence n (expected n+1)"
>> messages? Is anyone else seeing those? Are they part of my problem? Or do
>> they hint at a seperate problem, maybe triggered by the 'real' problem?
>
> I'm using 2.6.29-rc2 + "git diff-tree v2.6.29-rc2 wireless-testing/master --
> drivers/net/wireless/libertas" + "16bit/word spi mode" and
>
> With 9.70.3p37 firmware from Marvell. I get:
>
> # modprobe  libertas_spi
> lib80211: common routines for IEEE802.11 drivers
> libertas_spi: Libertas SPI driver
> libertas_spi spi2.0: firmware: requesting libertas/gspi8686_hlp.bin
> libertas_spi spi2.0: firmware: requesting libertas/gspi8686.bin
> libertas: 00:19:88:05:b1:59, fw 9.70.3p37, cap 0x00000303
> eth1 (libertas_spi): not using net_device_ops yet
> libertas: PREP_CMD: command 0x00a3 failed: 2
> libertas: PREP_CMD: command 0x00a3 failed: 2
> libertas: eth1: Marvell WLAN 802.11 adapter

Command 0x00A3 is a mesh setup command.  At this time, we don't have a
good way to tell if a chip/firmware supports mesh or not, so libertas
core tries these commands anyway and they fail.  Please ignore them
for now, though I suggest that we perhaps work around this in the same
way that power save support is currently indicated by the interface
driver (that is, if_spi.c could tell libertas that no GSPI devices
support mesh, because they don't).

> With gspi8686_v9.bin and gspi8686_v9_helper.bin from linux-firmware I get
>
> # modprobe libertas_spi
> lib80211: common routines for IEEE802.11 drivers
> libertas_spi: Libertas SPI driver
> libertas_spi spi2.0: firmware: requesting libertas/gspi8686_hlp.bin
> libertas_spi spi2.0: firmware: requesting libertas/gspi8686.bin
> libertas: spu_wait_for_u16: timeout with val=00, target_mask=00, target=00
> libertas: if_spi_prog_main_firmware: timed out waiting for initial scratch reg = 0
> libertas: failed to load firmware (err=-110)
> libertas_spi: probe of spi2.0 failed with error -110

Very strange.  I tried both Marvell's 'p37 firmware and the firmware
from the linux-firmware tree and had identical results on the Blackfin
boards.  Are you sure that the only thing that you changed is the
firmware image set?  That is, both the helper and main firmware files
(but named as libertas_spi expects them, shown above)?  I'm not aware
of any serious differences in the two firmware versions.

>>> Can you actually use eth0 after the libertas_spi is loaded?
>>>
>> 'ifconfig eth0 up' works, 'iwlist eth0 scan' does not work. I get many more
>> messages like the ones quoted above and after quite a while the scan fails.
>> I've not tried to assoicate to an AP yet.


From andrey at cozybit.com  Wed Jan 28 10:49:51 2009
From: andrey at cozybit.com (Andrey Yurovsky)
Date: Wed, 28 Jan 2009 07:49:51 -0800
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
In-Reply-To: <1233131671.17900.220.camel@justakiss.home.at>
References: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
	<1233131671.17900.220.camel@justakiss.home.at>
Message-ID: <45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>

On Wed, Jan 28, 2009 at 12:34 AM, Erwin Authried <eauth at softsys.co.at> wrote:
> is it really necessary to pack all structures in hostcmd.h? The "packed"
> attribute makes the code larger and slower. I have changed the order in
> the lbs_private structure in dev.h a little bit so that resp_buf is on a
> 32-bit boundary. Then, I have removed most of the packed attributes in
> hostcmd.h (where all 16 or 32-bit Variables are on 16/32 bit boundaries
> anyway). The libertas module is a bit smaller, and I haven't seen any
> problem.

Thanks Erwin.  What CPU or CPUs have you tested your changes on?  In
our case, the Blackfin (and, reportedly, the AVR32) needed us to
guarantee alignment whereas ARM and x86 worked fine as things were
before.  Also although it's less efficient, we can now add commands
more safely if we use the packed attribute consistently rather than
counting bytes, and there's a good chance that more host command
structures will be added in the near future.

> Am Montag, den 12.01.2009, 13:14 -0800 schrieb Andrey Yurovsky:
>> Data structures that come over the wire from the WLAN firmware must be packed.
>> This fixes alignment problems on the blackfin architecture and, reportedly, on
>> the AVR32.
>>
>> This is a replacement for the previous version of this patch which had also
>> explicitly used get_unaligned_ macros.  As Johannes Berg pointed out, these
>> macros were unnecessary.
>>
>> Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
>> Signed-off-by: Colin McCabe <colin at cozybit.com>
>> diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
>> index 2d8533c..a899aeb 100644
>> --- a/drivers/net/wireless/libertas/hostcmd.h
>> +++ b/drivers/net/wireless/libertas/hostcmd.h
>> @@ -32,7 +32,7 @@ struct txpd {
>>       u8 pktdelay_2ms;
>>       /* reserved */
>>       u8 reserved1;
>> -};
>> +} __attribute__ ((packed));
>>
>>  /* RxPD Descriptor */
>>  struct rxpd {
>> @@ -63,7 +63,7 @@ struct rxpd {
>>       /* Pkt Priority */
>>       u8 priority;
>>       u8 reserved[3];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_header {
>>       __le16 command;
>> @@ -97,7 +97,7 @@ struct enc_key {
>>  struct lbs_offset_value {
>>       u32 offset;
>>       u32 value;
>> -};
>> +} __attribute__ ((packed));
>>
>>  /* Define general data structure */
>>  /* cmd_DS_GEN */
>> @@ -107,7 +107,7 @@ struct cmd_ds_gen {
>>       __le16 seqnum;
>>       __le16 result;
>>       void *cmdresp[0];
>> -};
>> +} __attribute__ ((packed));
>>
>>  #define S_DS_GEN sizeof(struct cmd_ds_gen)
>>
>> @@ -163,7 +163,7 @@ struct cmd_ds_802_11_subscribe_event {
>>        * bump this up a bit.
>>        */
>>       uint8_t tlv[128];
>> -};
>> +} __attribute__ ((packed));
>>
>>  /*
>>   * This scan handle Country Information IE(802.11d compliant)
>> @@ -180,7 +180,7 @@ struct cmd_ds_802_11_scan {
>>       mrvlietypes_chanlistparamset_t ChanListParamSet;
>>       mrvlietypes_ratesparamset_t OpRateSet;
>>  #endif
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_scan_rsp {
>>       struct cmd_header hdr;
>> @@ -188,7 +188,7 @@ struct cmd_ds_802_11_scan_rsp {
>>       __le16 bssdescriptsize;
>>       uint8_t nr_sets;
>>       uint8_t bssdesc_and_tlvbuffer[0];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_get_log {
>>       struct cmd_header hdr;
>> @@ -206,20 +206,20 @@ struct cmd_ds_802_11_get_log {
>>       __le32 fcserror;
>>       __le32 txframe;
>>       __le32 wepundecryptable;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_mac_control {
>>       struct cmd_header hdr;
>>       __le16 action;
>>       u16 reserved;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_mac_multicast_adr {
>>       struct cmd_header hdr;
>>       __le16 action;
>>       __le16 nr_of_adrs;
>>       u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_gspi_bus_config {
>>       struct cmd_header hdr;
>> @@ -233,14 +233,14 @@ struct cmd_ds_802_11_authenticate {
>>       u8 macaddr[ETH_ALEN];
>>       u8 authtype;
>>       u8 reserved[10];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_deauthenticate {
>>       struct cmd_header hdr;
>>
>>       u8 macaddr[ETH_ALEN];
>>       __le16 reasoncode;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_associate {
>>       u8 peerstaaddr[6];
>> @@ -259,7 +259,7 @@ struct cmd_ds_802_11_associate {
>>
>>  struct cmd_ds_802_11_associate_rsp {
>>       struct ieeetypes_assocrsp assocRsp;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_set_wep {
>>       struct cmd_header hdr;
>> @@ -273,7 +273,7 @@ struct cmd_ds_802_11_set_wep {
>>       /* 40, 128bit or TXWEP */
>>       uint8_t keytype[4];
>>       uint8_t keymaterial[4][16];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_3_get_stat {
>>       __le32 xmitok;
>> @@ -282,7 +282,7 @@ struct cmd_ds_802_3_get_stat {
>>       __le32 rcverror;
>>       __le32 rcvnobuffer;
>>       __le32 rcvcrcerror;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_get_stat {
>>       __le32 txfragmentcnt;
>> @@ -302,7 +302,7 @@ struct cmd_ds_802_11_get_stat {
>>       __le32 txbeacon;
>>       __le32 rxbeacon;
>>       __le32 wepundecryptable;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_snmp_mib {
>>       struct cmd_header hdr;
>> @@ -311,58 +311,58 @@ struct cmd_ds_802_11_snmp_mib {
>>       __le16 oid;
>>       __le16 bufsize;
>>       u8 value[128];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_mac_reg_map {
>>       __le16 buffersize;
>>       u8 regmap[128];
>>       __le16 reserved;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_bbp_reg_map {
>>       __le16 buffersize;
>>       u8 regmap[128];
>>       __le16 reserved;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_rf_reg_map {
>>       __le16 buffersize;
>>       u8 regmap[64];
>>       __le16 reserved;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_mac_reg_access {
>>       __le16 action;
>>       __le16 offset;
>>       __le32 value;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_bbp_reg_access {
>>       __le16 action;
>>       __le16 offset;
>>       u8 value;
>>       u8 reserved[3];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_rf_reg_access {
>>       __le16 action;
>>       __le16 offset;
>>       u8 value;
>>       u8 reserved[3];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_radio_control {
>>       struct cmd_header hdr;
>>
>>       __le16 action;
>>       __le16 control;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_beacon_control {
>>       __le16 action;
>>       __le16 beacon_enable;
>>       __le16 beacon_period;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_sleep_params {
>>       struct cmd_header hdr;
>> @@ -387,7 +387,7 @@ struct cmd_ds_802_11_sleep_params {
>>
>>       /* reserved field, should be set to zero */
>>       __le16 reserved;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_inactivity_timeout {
>>       struct cmd_header hdr;
>> @@ -397,7 +397,7 @@ struct cmd_ds_802_11_inactivity_timeout {
>>
>>       /* Inactivity timeout in msec */
>>       __le16 timeout;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_rf_channel {
>>       struct cmd_header hdr;
>> @@ -407,7 +407,7 @@ struct cmd_ds_802_11_rf_channel {
>>       __le16 rftype;      /* unused */
>>       __le16 reserved;    /* unused */
>>       u8 channellist[32]; /* unused */
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_rssi {
>>       /* weighting factor */
>> @@ -416,21 +416,21 @@ struct cmd_ds_802_11_rssi {
>>       __le16 reserved_0;
>>       __le16 reserved_1;
>>       __le16 reserved_2;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_rssi_rsp {
>>       __le16 SNR;
>>       __le16 noisefloor;
>>       __le16 avgSNR;
>>       __le16 avgnoisefloor;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_mac_address {
>>       struct cmd_header hdr;
>>
>>       __le16 action;
>>       u8 macadd[ETH_ALEN];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_rf_tx_power {
>>       struct cmd_header hdr;
>> @@ -439,7 +439,7 @@ struct cmd_ds_802_11_rf_tx_power {
>>       __le16 curlevel;
>>       s8 maxlevel;
>>       s8 minlevel;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_rf_antenna {
>>       __le16 action;
>> @@ -447,33 +447,33 @@ struct cmd_ds_802_11_rf_antenna {
>>       /* Number of antennas or 0xffff(diversity) */
>>       __le16 antennamode;
>>
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_monitor_mode {
>>       __le16 action;
>>       __le16 mode;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_set_boot2_ver {
>>       struct cmd_header hdr;
>>
>>       __le16 action;
>>       __le16 version;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_fw_wake_method {
>>       struct cmd_header hdr;
>>
>>       __le16 action;
>>       __le16 method;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_sleep_period {
>>       struct cmd_header hdr;
>>
>>       __le16 action;
>>       __le16 period;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_ps_mode {
>>       __le16 action;
>> @@ -481,7 +481,7 @@ struct cmd_ds_802_11_ps_mode {
>>       __le16 multipledtim;
>>       __le16 reserved;
>>       __le16 locallisteninterval;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_confirm_sleep {
>>       struct cmd_header hdr;
>> @@ -491,7 +491,7 @@ struct cmd_confirm_sleep {
>>       __le16 multipledtim;
>>       __le16 reserved;
>>       __le16 locallisteninterval;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_data_rate {
>>       struct cmd_header hdr;
>> @@ -499,14 +499,14 @@ struct cmd_ds_802_11_data_rate {
>>       __le16 action;
>>       __le16 reserved;
>>       u8 rates[MAX_RATES];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_rate_adapt_rateset {
>>       struct cmd_header hdr;
>>       __le16 action;
>>       __le16 enablehwauto;
>>       __le16 bitmap;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_802_11_ad_hoc_start {
>>       struct cmd_header hdr;
>> @@ -528,7 +528,7 @@ struct cmd_ds_802_11_ad_hoc_result {
>>
>>       u8 pad[3];
>>       u8 bssid[ETH_ALEN];
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct adhoc_bssdesc {
>>       u8 bssid[ETH_ALEN];
>> @@ -586,7 +586,7 @@ struct MrvlIEtype_keyParamSet {
>>
>>       /* key material of size keylen */
>>       u8 key[32];
>> -};
>> +} __attribute__ ((packed));
>>
>>  #define MAX_WOL_RULES                16
>>
>> @@ -598,7 +598,7 @@ struct host_wol_rule {
>>       __le16 reserve;
>>       __be32 sig_mask;
>>       __be32 signature;
>> -};
>> +} __attribute__ ((packed));
>>
>>  struct wol_config {
>>       uint8_t action;
>> @@ -606,8 +606,7 @@ struct wol_config {
>>       uint8_t no_rules_in_cmd;
>>       uint8_t result;
>>       struct host_wol_rule rule[MAX_WOL_RULES];
>> -};
>> -
>> +} __attribute__ ((packed));
>>
>>  struct cmd_ds_host_sleep {
>>       struct cmd_header hdr;
>>
>>
>>
>> _______________________________________________
>> libertas-dev mailing list
>> libertas-dev at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/libertas-dev
> --
> Dipl.-Ing. Erwin Authried
> Softwareentwicklung und Systemdesign
>
>



-- 
Andrey Yurovsky
cozybit Inc.


From dcbw at redhat.com  Wed Jan 28 11:41:52 2009
From: dcbw at redhat.com (Dan Williams)
Date: Wed, 28 Jan 2009 11:41:52 -0500
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
In-Reply-To: <45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>
References: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
	<1233131671.17900.220.camel@justakiss.home.at>
	<45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>
Message-ID: <1233160912.20207.15.camel@localhost.localdomain>

On Wed, 2009-01-28 at 07:49 -0800, Andrey Yurovsky wrote:
> On Wed, Jan 28, 2009 at 12:34 AM, Erwin Authried <eauth at softsys.co.at> wrote:
> > is it really necessary to pack all structures in hostcmd.h? The "packed"
> > attribute makes the code larger and slower. I have changed the order in
> > the lbs_private structure in dev.h a little bit so that resp_buf is on a
> > 32-bit boundary. Then, I have removed most of the packed attributes in
> > hostcmd.h (where all 16 or 32-bit Variables are on 16/32 bit boundaries
> > anyway). The libertas module is a bit smaller, and I haven't seen any
> > problem.
> 
> Thanks Erwin.  What CPU or CPUs have you tested your changes on?  In
> our case, the Blackfin (and, reportedly, the AVR32) needed us to
> guarantee alignment whereas ARM and x86 worked fine as things were
> before.  Also although it's less efficient, we can now add commands
> more safely if we use the packed attribute consistently rather than
> counting bytes, and there's a good chance that more host command
> structures will be added in the near future.

The less possibility there is for accidentally screwing up one of the
alignment-sensitive architectures, the better.  If the speed and
codesize differences were significant, then maybe, but I think in this
case, maintainability and reliability outweigh that.  Nobody likes it
when somebody else breaks their product.

Dan

> > Am Montag, den 12.01.2009, 13:14 -0800 schrieb Andrey Yurovsky:
> >> Data structures that come over the wire from the WLAN firmware must be packed.
> >> This fixes alignment problems on the blackfin architecture and, reportedly, on
> >> the AVR32.
> >>
> >> This is a replacement for the previous version of this patch which had also
> >> explicitly used get_unaligned_ macros.  As Johannes Berg pointed out, these
> >> macros were unnecessary.
> >>
> >> Signed-off-by: Andrey Yurovsky <andrey at cozybit.com>
> >> Signed-off-by: Colin McCabe <colin at cozybit.com>
> >> diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
> >> index 2d8533c..a899aeb 100644
> >> --- a/drivers/net/wireless/libertas/hostcmd.h
> >> +++ b/drivers/net/wireless/libertas/hostcmd.h
> >> @@ -32,7 +32,7 @@ struct txpd {
> >>       u8 pktdelay_2ms;
> >>       /* reserved */
> >>       u8 reserved1;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  /* RxPD Descriptor */
> >>  struct rxpd {
> >> @@ -63,7 +63,7 @@ struct rxpd {
> >>       /* Pkt Priority */
> >>       u8 priority;
> >>       u8 reserved[3];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_header {
> >>       __le16 command;
> >> @@ -97,7 +97,7 @@ struct enc_key {
> >>  struct lbs_offset_value {
> >>       u32 offset;
> >>       u32 value;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  /* Define general data structure */
> >>  /* cmd_DS_GEN */
> >> @@ -107,7 +107,7 @@ struct cmd_ds_gen {
> >>       __le16 seqnum;
> >>       __le16 result;
> >>       void *cmdresp[0];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  #define S_DS_GEN sizeof(struct cmd_ds_gen)
> >>
> >> @@ -163,7 +163,7 @@ struct cmd_ds_802_11_subscribe_event {
> >>        * bump this up a bit.
> >>        */
> >>       uint8_t tlv[128];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  /*
> >>   * This scan handle Country Information IE(802.11d compliant)
> >> @@ -180,7 +180,7 @@ struct cmd_ds_802_11_scan {
> >>       mrvlietypes_chanlistparamset_t ChanListParamSet;
> >>       mrvlietypes_ratesparamset_t OpRateSet;
> >>  #endif
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_scan_rsp {
> >>       struct cmd_header hdr;
> >> @@ -188,7 +188,7 @@ struct cmd_ds_802_11_scan_rsp {
> >>       __le16 bssdescriptsize;
> >>       uint8_t nr_sets;
> >>       uint8_t bssdesc_and_tlvbuffer[0];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_get_log {
> >>       struct cmd_header hdr;
> >> @@ -206,20 +206,20 @@ struct cmd_ds_802_11_get_log {
> >>       __le32 fcserror;
> >>       __le32 txframe;
> >>       __le32 wepundecryptable;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_mac_control {
> >>       struct cmd_header hdr;
> >>       __le16 action;
> >>       u16 reserved;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_mac_multicast_adr {
> >>       struct cmd_header hdr;
> >>       __le16 action;
> >>       __le16 nr_of_adrs;
> >>       u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_gspi_bus_config {
> >>       struct cmd_header hdr;
> >> @@ -233,14 +233,14 @@ struct cmd_ds_802_11_authenticate {
> >>       u8 macaddr[ETH_ALEN];
> >>       u8 authtype;
> >>       u8 reserved[10];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_deauthenticate {
> >>       struct cmd_header hdr;
> >>
> >>       u8 macaddr[ETH_ALEN];
> >>       __le16 reasoncode;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_associate {
> >>       u8 peerstaaddr[6];
> >> @@ -259,7 +259,7 @@ struct cmd_ds_802_11_associate {
> >>
> >>  struct cmd_ds_802_11_associate_rsp {
> >>       struct ieeetypes_assocrsp assocRsp;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_set_wep {
> >>       struct cmd_header hdr;
> >> @@ -273,7 +273,7 @@ struct cmd_ds_802_11_set_wep {
> >>       /* 40, 128bit or TXWEP */
> >>       uint8_t keytype[4];
> >>       uint8_t keymaterial[4][16];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_3_get_stat {
> >>       __le32 xmitok;
> >> @@ -282,7 +282,7 @@ struct cmd_ds_802_3_get_stat {
> >>       __le32 rcverror;
> >>       __le32 rcvnobuffer;
> >>       __le32 rcvcrcerror;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_get_stat {
> >>       __le32 txfragmentcnt;
> >> @@ -302,7 +302,7 @@ struct cmd_ds_802_11_get_stat {
> >>       __le32 txbeacon;
> >>       __le32 rxbeacon;
> >>       __le32 wepundecryptable;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_snmp_mib {
> >>       struct cmd_header hdr;
> >> @@ -311,58 +311,58 @@ struct cmd_ds_802_11_snmp_mib {
> >>       __le16 oid;
> >>       __le16 bufsize;
> >>       u8 value[128];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_mac_reg_map {
> >>       __le16 buffersize;
> >>       u8 regmap[128];
> >>       __le16 reserved;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_bbp_reg_map {
> >>       __le16 buffersize;
> >>       u8 regmap[128];
> >>       __le16 reserved;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_rf_reg_map {
> >>       __le16 buffersize;
> >>       u8 regmap[64];
> >>       __le16 reserved;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_mac_reg_access {
> >>       __le16 action;
> >>       __le16 offset;
> >>       __le32 value;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_bbp_reg_access {
> >>       __le16 action;
> >>       __le16 offset;
> >>       u8 value;
> >>       u8 reserved[3];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_rf_reg_access {
> >>       __le16 action;
> >>       __le16 offset;
> >>       u8 value;
> >>       u8 reserved[3];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_radio_control {
> >>       struct cmd_header hdr;
> >>
> >>       __le16 action;
> >>       __le16 control;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_beacon_control {
> >>       __le16 action;
> >>       __le16 beacon_enable;
> >>       __le16 beacon_period;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_sleep_params {
> >>       struct cmd_header hdr;
> >> @@ -387,7 +387,7 @@ struct cmd_ds_802_11_sleep_params {
> >>
> >>       /* reserved field, should be set to zero */
> >>       __le16 reserved;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_inactivity_timeout {
> >>       struct cmd_header hdr;
> >> @@ -397,7 +397,7 @@ struct cmd_ds_802_11_inactivity_timeout {
> >>
> >>       /* Inactivity timeout in msec */
> >>       __le16 timeout;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_rf_channel {
> >>       struct cmd_header hdr;
> >> @@ -407,7 +407,7 @@ struct cmd_ds_802_11_rf_channel {
> >>       __le16 rftype;      /* unused */
> >>       __le16 reserved;    /* unused */
> >>       u8 channellist[32]; /* unused */
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_rssi {
> >>       /* weighting factor */
> >> @@ -416,21 +416,21 @@ struct cmd_ds_802_11_rssi {
> >>       __le16 reserved_0;
> >>       __le16 reserved_1;
> >>       __le16 reserved_2;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_rssi_rsp {
> >>       __le16 SNR;
> >>       __le16 noisefloor;
> >>       __le16 avgSNR;
> >>       __le16 avgnoisefloor;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_mac_address {
> >>       struct cmd_header hdr;
> >>
> >>       __le16 action;
> >>       u8 macadd[ETH_ALEN];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_rf_tx_power {
> >>       struct cmd_header hdr;
> >> @@ -439,7 +439,7 @@ struct cmd_ds_802_11_rf_tx_power {
> >>       __le16 curlevel;
> >>       s8 maxlevel;
> >>       s8 minlevel;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_rf_antenna {
> >>       __le16 action;
> >> @@ -447,33 +447,33 @@ struct cmd_ds_802_11_rf_antenna {
> >>       /* Number of antennas or 0xffff(diversity) */
> >>       __le16 antennamode;
> >>
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_monitor_mode {
> >>       __le16 action;
> >>       __le16 mode;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_set_boot2_ver {
> >>       struct cmd_header hdr;
> >>
> >>       __le16 action;
> >>       __le16 version;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_fw_wake_method {
> >>       struct cmd_header hdr;
> >>
> >>       __le16 action;
> >>       __le16 method;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_sleep_period {
> >>       struct cmd_header hdr;
> >>
> >>       __le16 action;
> >>       __le16 period;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_ps_mode {
> >>       __le16 action;
> >> @@ -481,7 +481,7 @@ struct cmd_ds_802_11_ps_mode {
> >>       __le16 multipledtim;
> >>       __le16 reserved;
> >>       __le16 locallisteninterval;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_confirm_sleep {
> >>       struct cmd_header hdr;
> >> @@ -491,7 +491,7 @@ struct cmd_confirm_sleep {
> >>       __le16 multipledtim;
> >>       __le16 reserved;
> >>       __le16 locallisteninterval;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_data_rate {
> >>       struct cmd_header hdr;
> >> @@ -499,14 +499,14 @@ struct cmd_ds_802_11_data_rate {
> >>       __le16 action;
> >>       __le16 reserved;
> >>       u8 rates[MAX_RATES];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_rate_adapt_rateset {
> >>       struct cmd_header hdr;
> >>       __le16 action;
> >>       __le16 enablehwauto;
> >>       __le16 bitmap;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_802_11_ad_hoc_start {
> >>       struct cmd_header hdr;
> >> @@ -528,7 +528,7 @@ struct cmd_ds_802_11_ad_hoc_result {
> >>
> >>       u8 pad[3];
> >>       u8 bssid[ETH_ALEN];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct adhoc_bssdesc {
> >>       u8 bssid[ETH_ALEN];
> >> @@ -586,7 +586,7 @@ struct MrvlIEtype_keyParamSet {
> >>
> >>       /* key material of size keylen */
> >>       u8 key[32];
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  #define MAX_WOL_RULES                16
> >>
> >> @@ -598,7 +598,7 @@ struct host_wol_rule {
> >>       __le16 reserve;
> >>       __be32 sig_mask;
> >>       __be32 signature;
> >> -};
> >> +} __attribute__ ((packed));
> >>
> >>  struct wol_config {
> >>       uint8_t action;
> >> @@ -606,8 +606,7 @@ struct wol_config {
> >>       uint8_t no_rules_in_cmd;
> >>       uint8_t result;
> >>       struct host_wol_rule rule[MAX_WOL_RULES];
> >> -};
> >> -
> >> +} __attribute__ ((packed));
> >>
> >>  struct cmd_ds_host_sleep {
> >>       struct cmd_header hdr;
> >>
> >>
> >>
> >> _______________________________________________
> >> libertas-dev mailing list
> >> libertas-dev at lists.infradead.org
> >> http://lists.infradead.org/mailman/listinfo/libertas-dev
> > --
> > Dipl.-Ing. Erwin Authried
> > Softwareentwicklung und Systemdesign
> >
> >
> 
> 
> 



From eauth at softsys.co.at  Wed Jan 28 13:47:46 2009
From: eauth at softsys.co.at (Erwin Authried)
Date: Wed, 28 Jan 2009 19:47:46 +0100
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
In-Reply-To: <45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>
References: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
	<1233131671.17900.220.camel@justakiss.home.at>
	<45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>
Message-ID: <1233168466.17900.261.camel@justakiss.home.at>

Am Mittwoch, den 28.01.2009, 07:49 -0800 schrieb Andrey Yurovsky:
> On Wed, Jan 28, 2009 at 12:34 AM, Erwin Authried <eauth at softsys.co.at> wrote:
> > is it really necessary to pack all structures in hostcmd.h? The "packed"
> > attribute makes the code larger and slower. I have changed the order in
> > the lbs_private structure in dev.h a little bit so that resp_buf is on a
> > 32-bit boundary. Then, I have removed most of the packed attributes in
> > hostcmd.h (where all 16 or 32-bit Variables are on 16/32 bit boundaries
> > anyway). The libertas module is a bit smaller, and I haven't seen any
> > problem.
> 
> Thanks Erwin.  What CPU or CPUs have you tested your changes on?  In
> our case, the Blackfin (and, reportedly, the AVR32) needed us to
> guarantee alignment whereas ARM and x86 worked fine as things were
> before.  Also although it's less efficient, we can now add commands
> more safely if we use the packed attribute consistently rather than
> counting bytes, and there's a good chance that more host command
> structures will be added in the near future.

I have tested with ARM7TDMI (AT91FR40162), there is no aligment trap.
The cpu simply ignores the lowest address bits and produces wrong
assignments when the alignment isn't correct.

-Erwin

> 
> > Am Montag, den 12.01.2009, 13:14 -0800 schrieb Andrey Yurovsky:
> >> Data structures that come over the wire from the WLAN firmware must be packed.
> >> This fixes alignment problems on the blackfin architecture and, reportedly, on
> >> the AVR32.
> >>
> >> This is a replacement for the previous version of this patch which had also
> >> explicitly used get_unaligned_ macros.  As Johannes Berg pointed out, these
> >> macros were unnecessary.
> >>
-- 
Dipl.-Ing. Erwin Authried
Softwareentwicklung und Systemdesign



From colin at cozybit.com  Wed Jan 28 17:48:28 2009
From: colin at cozybit.com (Colin McCabe)
Date: Wed, 28 Jan 2009 14:48:28 -0800
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
In-Reply-To: <1233168466.17900.261.camel@justakiss.home.at>
References: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
	<1233131671.17900.220.camel@justakiss.home.at>
	<45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>
	<1233168466.17900.261.camel@justakiss.home.at>
Message-ID: <314b98fa0901281448t1a9322dat25d0aeb5c0bc885@mail.gmail.com>

The argument for specifying struct layout explicitly is pretty clear.
If we relied on gcc to get it right "by accident," we would find that
gcc upgrades and minor code changes would break the driver in
mysterious ways.

I'm surprised that gcc generates poorer code when the layout is
specified explicitly, since after all, it should be the same layout.
Have you tried using __attribute__ ((aligned (8))) or similar?

regards,
Colin


On Wed, Jan 28, 2009 at 10:47 AM, Erwin Authried <eauth at softsys.co.at> wrote:
> Am Mittwoch, den 28.01.2009, 07:49 -0800 schrieb Andrey Yurovsky:
>> On Wed, Jan 28, 2009 at 12:34 AM, Erwin Authried <eauth at softsys.co.at> wrote:
>> > is it really necessary to pack all structures in hostcmd.h? The "packed"
>> > attribute makes the code larger and slower. I have changed the order in
>> > the lbs_private structure in dev.h a little bit so that resp_buf is on a
>> > 32-bit boundary. Then, I have removed most of the packed attributes in
>> > hostcmd.h (where all 16 or 32-bit Variables are on 16/32 bit boundaries
>> > anyway). The libertas module is a bit smaller, and I haven't seen any
>> > problem.
>>
>> Thanks Erwin.  What CPU or CPUs have you tested your changes on?  In
>> our case, the Blackfin (and, reportedly, the AVR32) needed us to
>> guarantee alignment whereas ARM and x86 worked fine as things were
>> before.  Also although it's less efficient, we can now add commands
>> more safely if we use the packed attribute consistently rather than
>> counting bytes, and there's a good chance that more host command
>> structures will be added in the near future.
>
> I have tested with ARM7TDMI (AT91FR40162), there is no aligment trap.
> The cpu simply ignores the lowest address bits and produces wrong
> assignments when the alignment isn't correct.
>
> -Erwin
>
>>
>> > Am Montag, den 12.01.2009, 13:14 -0800 schrieb Andrey Yurovsky:
>> >> Data structures that come over the wire from the WLAN firmware must be packed.
>> >> This fixes alignment problems on the blackfin architecture and, reportedly, on
>> >> the AVR32.
>> >>
>> >> This is a replacement for the previous version of this patch which had also
>> >> explicitly used get_unaligned_ macros.  As Johannes Berg pointed out, these
>> >> macros were unnecessary.
>> >>
> --
> Dipl.-Ing. Erwin Authried
> Softwareentwicklung und Systemdesign
>
>
> _______________________________________________
> libertas-dev mailing list
> libertas-dev at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/libertas-dev
>


From eauth at softsys.co.at  Wed Jan 28 18:47:00 2009
From: eauth at softsys.co.at (Erwin Authried)
Date: Thu, 29 Jan 2009 00:47:00 +0100
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
In-Reply-To: <314b98fa0901281448t1a9322dat25d0aeb5c0bc885@mail.gmail.com>
References: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
	<1233131671.17900.220.camel@justakiss.home.at>
	<45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>
	<1233168466.17900.261.camel@justakiss.home.at>
	<314b98fa0901281448t1a9322dat25d0aeb5c0bc885@mail.gmail.com>
Message-ID: <1233186420.7078.34.camel@localhost.localdomain>

Am Mittwoch, den 28.01.2009, 14:48 -0800 schrieb Colin McCabe:
> The argument for specifying struct layout explicitly is pretty clear.
> If we relied on gcc to get it right "by accident," we would find that
> gcc upgrades and minor code changes would break the driver in
> mysterious ways.
you are probably right, it's a bit fragile, and there's no warranty
that different/new architectures have the same rules for alignment of
structures.

> 
> I'm surprised that gcc generates poorer code when the layout is
> specified explicitly, since after all, it should be the same layout.
> Have you tried using __attribute__ ((aligned (8))) or similar?
> 
it's not surprising because with the packed attribute gcc doesn't make
any assumptions about the the alignment of the start of the structure.
For example, if you compare the code for the following simple structure:

struct a {
  int i;
};

struct b {
  int i;
} __attribute__ ((packed));

the following code is generated when "i" is accessed via a pointer to
the structure:

* without packed attribute:
	ldr	r0, [r0, #0]

* with the packed attribute:
	ldrb	r3, [r0, #0]
	ldrb	r2, [r0, #1]
	ldrb	r1, [r0, #2]
	orr	r3, r3, r2, asl #8
	ldrb	r0, [r0, #3]
	orr	r3, r3, r1, asl #16
	orr	r0, r3, r0, asl #24

As you see, there are seven(!) instructions instead of just one for
reading a 32-bit variable when the packed attribute is used! 

-Erwin

> regards,
> Colin
> 
> 
> On Wed, Jan 28, 2009 at 10:47 AM, Erwin Authried <eauth at softsys.co.at> wrote:
> > Am Mittwoch, den 28.01.2009, 07:49 -0800 schrieb Andrey Yurovsky:
> >> On Wed, Jan 28, 2009 at 12:34 AM, Erwin Authried <eauth at softsys.co.at> wrote:
> >> > is it really necessary to pack all structures in hostcmd.h? The "packed"
> >> > attribute makes the code larger and slower. I have changed the order in
> >> > the lbs_private structure in dev.h a little bit so that resp_buf is on a
> >> > 32-bit boundary. Then, I have removed most of the packed attributes in
> >> > hostcmd.h (where all 16 or 32-bit Variables are on 16/32 bit boundaries
> >> > anyway). The libertas module is a bit smaller, and I haven't seen any
> >> > problem.
> >>
> >> Thanks Erwin.  What CPU or CPUs have you tested your changes on?  In
> >> our case, the Blackfin (and, reportedly, the AVR32) needed us to
> >> guarantee alignment whereas ARM and x86 worked fine as things were
> >> before.  Also although it's less efficient, we can now add commands
> >> more safely if we use the packed attribute consistently rather than
> >> counting bytes, and there's a good chance that more host command
> >> structures will be added in the near future.
> >
> > I have tested with ARM7TDMI (AT91FR40162), there is no aligment trap.
> > The cpu simply ignores the lowest address bits and produces wrong
> > assignments when the alignment isn't correct.
> >
> > -Erwin
> >
> >>
> >> > Am Montag, den 12.01.2009, 13:14 -0800 schrieb Andrey Yurovsky:
> >> >> Data structures that come over the wire from the WLAN firmware must be packed.
> >> >> This fixes alignment problems on the blackfin architecture and, reportedly, on
> >> >> the AVR32.
> >> >>
> >> >> This is a replacement for the previous version of this patch which had also
> >> >> explicitly used get_unaligned_ macros.  As Johannes Berg pointed out, these
> >> >> macros were unnecessary.
> >> >>
> > --
> > Dipl.-Ing. Erwin Authried
> > Softwareentwicklung und Systemdesign
> >
> >
> > _______________________________________________
> > libertas-dev mailing list
> > libertas-dev at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/libertas-dev
> >



From colin at cozybit.com  Wed Jan 28 18:59:42 2009
From: colin at cozybit.com (Colin McCabe)
Date: Wed, 28 Jan 2009 15:59:42 -0800
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
In-Reply-To: <1233186420.7078.34.camel@localhost.localdomain>
References: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
	<1233131671.17900.220.camel@justakiss.home.at>
	<45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>
	<1233168466.17900.261.camel@justakiss.home.at>
	<314b98fa0901281448t1a9322dat25d0aeb5c0bc885@mail.gmail.com>
	<1233186420.7078.34.camel@localhost.localdomain>
Message-ID: <314b98fa0901281559q766eb0f2y40306d8ccc82adc4@mail.gmail.com>

On Wed, Jan 28, 2009 at 3:47 PM, Erwin Authried <eauth at softsys.co.at> wrote:
> Am Mittwoch, den 28.01.2009, 14:48 -0800 schrieb Colin McCabe:
>> The argument for specifying struct layout explicitly is pretty clear.
>> If we relied on gcc to get it right "by accident," we would find that
>> gcc upgrades and minor code changes would break the driver in
>> mysterious ways.
> you are probably right, it's a bit fragile, and there's no warranty
> that different/new architectures have the same rules for alignment of
> structures.
>
>>
>> I'm surprised that gcc generates poorer code when the layout is
>> specified explicitly, since after all, it should be the same layout.
>> Have you tried using __attribute__ ((aligned (8))) or similar?
>>
> it's not surprising because with the packed attribute gcc doesn't make
> any assumptions about the the alignment of the start of the structure.
> For example, if you compare the code for the following simple structure:
>
> struct a {
>  int i;
> };
>
> struct b {
>  int i;
> } __attribute__ ((packed));

That's very insightful.

I wonder if there is an __attribute__ or pragma that would force gcc
to do the right thing here.
Can you put __attribute__((aligned)) on a member of a packed struct? I
might have to test that out later...

Colin


>
> the following code is generated when "i" is accessed via a pointer to
> the structure:
>
> * without packed attribute:
>        ldr     r0, [r0, #0]
>
> * with the packed attribute:
>        ldrb    r3, [r0, #0]
>        ldrb    r2, [r0, #1]
>        ldrb    r1, [r0, #2]
>        orr     r3, r3, r2, asl #8
>        ldrb    r0, [r0, #3]
>        orr     r3, r3, r1, asl #16
>        orr     r0, r3, r0, asl #24
>
> As you see, there are seven(!) instructions instead of just one for
> reading a 32-bit variable when the packed attribute is used!
>
> -Erwin
>
>> regards,
>> Colin
>>
>>
>> On Wed, Jan 28, 2009 at 10:47 AM, Erwin Authried <eauth at softsys.co.at> wrote:
>> > Am Mittwoch, den 28.01.2009, 07:49 -0800 schrieb Andrey Yurovsky:
>> >> On Wed, Jan 28, 2009 at 12:34 AM, Erwin Authried <eauth at softsys.co.at> wrote:
>> >> > is it really necessary to pack all structures in hostcmd.h? The "packed"
>> >> > attribute makes the code larger and slower. I have changed the order in
>> >> > the lbs_private structure in dev.h a little bit so that resp_buf is on a
>> >> > 32-bit boundary. Then, I have removed most of the packed attributes in
>> >> > hostcmd.h (where all 16 or 32-bit Variables are on 16/32 bit boundaries
>> >> > anyway). The libertas module is a bit smaller, and I haven't seen any
>> >> > problem.
>> >>
>> >> Thanks Erwin.  What CPU or CPUs have you tested your changes on?  In
>> >> our case, the Blackfin (and, reportedly, the AVR32) needed us to
>> >> guarantee alignment whereas ARM and x86 worked fine as things were
>> >> before.  Also although it's less efficient, we can now add commands
>> >> more safely if we use the packed attribute consistently rather than
>> >> counting bytes, and there's a good chance that more host command
>> >> structures will be added in the near future.
>> >
>> > I have tested with ARM7TDMI (AT91FR40162), there is no aligment trap.
>> > The cpu simply ignores the lowest address bits and produces wrong
>> > assignments when the alignment isn't correct.
>> >
>> > -Erwin
>> >
>> >>
>> >> > Am Montag, den 12.01.2009, 13:14 -0800 schrieb Andrey Yurovsky:
>> >> >> Data structures that come over the wire from the WLAN firmware must be packed.
>> >> >> This fixes alignment problems on the blackfin architecture and, reportedly, on
>> >> >> the AVR32.
>> >> >>
>> >> >> This is a replacement for the previous version of this patch which had also
>> >> >> explicitly used get_unaligned_ macros.  As Johannes Berg pointed out, these
>> >> >> macros were unnecessary.
>> >> >>
>> > --
>> > Dipl.-Ing. Erwin Authried
>> > Softwareentwicklung und Systemdesign
>> >
>> >
>> > _______________________________________________
>> > libertas-dev mailing list
>> > libertas-dev at lists.infradead.org
>> > http://lists.infradead.org/mailman/listinfo/libertas-dev
>> >
>
>


From ryan at bluewatersys.com  Wed Jan 28 20:11:59 2009
From: ryan at bluewatersys.com (Ryan Mallon)
Date: Thu, 29 Jan 2009 14:11:59 +1300
Subject: Marvel 8686 in adhoc mode
Message-ID: <4981025F.1070802@bluewatersys.com>

Can anybody tell me if the Libertas driver will support the Marvell
88W8686 chip in adhoc mode at 54Mbps. If so, which kernel version was
this supported introduced at?

Thanks,
~Ryan

-- 
Bluewater Systems Ltd - ARM Technology Solution Centre

       Ryan Mallon                              Unit 5, Amuri Park
       Phone: +64 3 3779127                     404 Barbadoes St
       Fax:   +64 3 3779135                     PO Box 13 889
       Email: ryan at bluewatersys.com             Christchurch, 8013
       Web:   http://www.bluewatersys.com       New Zealand
       Freecall Australia  1800 148 751         USA 1800 261 2934


From mike at compulab.co.il  Thu Jan 29 02:40:55 2009
From: mike at compulab.co.il (Mike Rapoport)
Date: Thu, 29 Jan 2009 09:40:55 +0200
Subject: Libertas with if_spi on pxa270
In-Reply-To: <45e8e6c40901280745i72d140dfhf04afc5d9c4e75ee@mail.gmail.com>
References: <497DCFA2.3070508@compulab.co.il>	
	<200901272044.01760.u.luckas@road.de>
	<497FFF73.30700@compulab.co.il>	
	<200901281029.37751.u.luckas@road.de>	
	<49802B41.2010004@compulab.co.il>
	<45e8e6c40901280745i72d140dfhf04afc5d9c4e75ee@mail.gmail.com>
Message-ID: <49815D87.60707@compulab.co.il>



Andrey Yurovsky wrote:
> On Wed, Jan 28, 2009 at 1:54 AM, Mike Rapoport <mike at compulab.co.il> wrote:
> 
> Very strange.  I tried both Marvell's 'p37 firmware and the firmware
> from the linux-firmware tree and had identical results on the Blackfin
> boards.  Are you sure that the only thing that you changed is the
> firmware image set?  That is, both the helper and main firmware files
> (but named as libertas_spi expects them, shown above)?  I'm not aware
> of any serious differences in the two firmware versions.

It was my fault. Apparently downloading firmware blob from gitweb screwed the
things up. After I cloned the entire linux-firmware tree everything was Ok.

>>>> Can you actually use eth0 after the libertas_spi is loaded?
>>>>
>>> 'ifconfig eth0 up' works, 'iwlist eth0 scan' does not work. I get many more
>>> messages like the ones quoted above and after quite a while the scan fails.
>>> I've not tried to assoicate to an AP yet.
> 

-- 
Sincerely yours,
Mike.



From eauth at softsys.co.at  Thu Jan 29 02:59:45 2009
From: eauth at softsys.co.at (Erwin Authried)
Date: Thu, 29 Jan 2009 08:59:45 +0100
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
In-Reply-To: <314b98fa0901281559q766eb0f2y40306d8ccc82adc4@mail.gmail.com>
References: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
	<1233131671.17900.220.camel@justakiss.home.at>
	<45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>
	<1233168466.17900.261.camel@justakiss.home.at>
	<314b98fa0901281448t1a9322dat25d0aeb5c0bc885@mail.gmail.com>
	<1233186420.7078.34.camel@localhost.localdomain>
	<314b98fa0901281559q766eb0f2y40306d8ccc82adc4@mail.gmail.com>
Message-ID: <1233215985.17900.282.camel@justakiss.home.at>

Am Mittwoch, den 28.01.2009, 15:59 -0800 schrieb Colin McCabe:
> On Wed, Jan 28, 2009 at 3:47 PM, Erwin Authried <eauth at softsys.co.at> wrote:
> > Am Mittwoch, den 28.01.2009, 14:48 -0800 schrieb Colin McCabe:
> >> The argument for specifying struct layout explicitly is pretty clear.
> >> If we relied on gcc to get it right "by accident," we would find that
> >> gcc upgrades and minor code changes would break the driver in
> >> mysterious ways.
> > you are probably right, it's a bit fragile, and there's no warranty
> > that different/new architectures have the same rules for alignment of
> > structures.
> >
> >>
> >> I'm surprised that gcc generates poorer code when the layout is
> >> specified explicitly, since after all, it should be the same layout.
> >> Have you tried using __attribute__ ((aligned (8))) or similar?
> >>
> > it's not surprising because with the packed attribute gcc doesn't make
> > any assumptions about the the alignment of the start of the structure.
> > For example, if you compare the code for the following simple structure:
> >
> > struct a {
> >  int i;
> > };
> >
> > struct b {
> >  int i;
> > } __attribute__ ((packed));
> 
> That's very insightful.
> 
> I wonder if there is an __attribute__ or pragma that would force gcc
> to do the right thing here.
> Can you put __attribute__((aligned)) on a member of a packed struct? I
> might have to test that out later...
> 
> Colin

Colin,
great idea! I did a short test, the "aligned" attribute on the first
struct member seems to do the job!
This way, gcc knows that the struct is aligned and optimizes access to
all members of the struct. We only have to make sure that the buffer for
the struct is aligned.

struct a {
  int i  __attribute__ ((aligned));
  char x,y,z;
  int j;
} __attribute__ ((packed));

-Erwin




From chaenel at free.fr  Thu Jan 29 09:49:25 2009
From: chaenel at free.fr (Cyril HAENEL)
Date: Thu, 29 Jan 2009 15:49:25 +0100
Subject: Something new with sleep command ?
Message-ID: <4981C1F5.4090309@free.fr>

Hi all,

I have not seriously read all libertas list messages for at least 5-6 month.
I just want to know if there is something new about the power managment 
of wifi card 8385 based ? I know it exists a command to request the 8385 
to sleep and have a very small current consumption. Someone know if this 
command is available on not ?

I wish you a good day,
Regards,
Cyril


-- 

Cyril Haenel
Registered Linux User #332632



From dontemailhere at mail.burberrykr.com  Thu Jan 29 12:55:39 2009
From: dontemailhere at mail.burberrykr.com (Angel Nieves)
Date: Fri, 30 Jan 2009 02:55:39 +0900
Subject: Doctor Listing in the USA
Message-ID: <OFA6551AAF.FD15AB15-ON4925754D.00627AD7@burberry.com>

Currently in Practice:  MDs in the USA 

Coverage in many different areas of medicine such as Endocrinology, Pathology, Urology, Neurology, Plastic Surgery, Psychiatry, Cardiology and much more 

you can sort by many different fields 

This week only you pay only: $391


### If you purchase this week you will get all 4 lists below for free *****

==> Optometrists

++> Visiting Nurses & RN's

<> Massage Therapists

--> Acupuncturists

Email us at:: Nicholson at mylistsource.com
  
for only this week --------   you got a problem with this email? go here please send an email to disable at mylistsource.com


From dcbw at redhat.com  Thu Jan 29 19:04:34 2009
From: dcbw at redhat.com (Dan Williams)
Date: Thu, 29 Jan 2009 19:04:34 -0500
Subject: [PATCH v2] libertas: Fix alignment issues in libertas core
In-Reply-To: <1233215985.17900.282.camel@justakiss.home.at>
References: <496bb2b3.14098e0a.5beb.4b09@mx.google.com>
	<1233131671.17900.220.camel@justakiss.home.at>
	<45e8e6c40901280749u44b8bb1avdbb76cd4368ddbe2@mail.gmail.com>
	<1233168466.17900.261.camel@justakiss.home.at>
	<314b98fa0901281448t1a9322dat25d0aeb5c0bc885@mail.gmail.com>
	<1233186420.7078.34.camel@localhost.localdomain>
	<314b98fa0901281559q766eb0f2y40306d8ccc82adc4@mail.gmail.com>
	<1233215985.17900.282.camel@justakiss.home.at>
Message-ID: <1233273874.4085.22.camel@localhost.localdomain>

On Thu, 2009-01-29 at 08:59 +0100, Erwin Authried wrote:
> Am Mittwoch, den 28.01.2009, 15:59 -0800 schrieb Colin McCabe:
> > On Wed, Jan 28, 2009 at 3:47 PM, Erwin Authried <eauth at softsys.co.at> wrote:
> > > Am Mittwoch, den 28.01.2009, 14:48 -0800 schrieb Colin McCabe:
> > >> The argument for specifying struct layout explicitly is pretty clear.
> > >> If we relied on gcc to get it right "by accident," we would find that
> > >> gcc upgrades and minor code changes would break the driver in
> > >> mysterious ways.
> > > you are probably right, it's a bit fragile, and there's no warranty
> > > that different/new architectures have the same rules for alignment of
> > > structures.
> > >
> > >>
> > >> I'm surprised that gcc generates poorer code when the layout is
> > >> specified explicitly, since after all, it should be the same layout.
> > >> Have you tried using __attribute__ ((aligned (8))) or similar?
> > >>
> > > it's not surprising because with the packed attribute gcc doesn't make
> > > any assumptions about the the alignment of the start of the structure.
> > > For example, if you compare the code for the following simple structure:
> > >
> > > struct a {
> > >  int i;
> > > };
> > >
> > > struct b {
> > >  int i;
> > > } __attribute__ ((packed));
> > 
> > That's very insightful.
> > 
> > I wonder if there is an __attribute__ or pragma that would force gcc
> > to do the right thing here.
> > Can you put __attribute__((aligned)) on a member of a packed struct? I
> > might have to test that out later...
> > 
> > Colin
> 
> Colin,
> great idea! I did a short test, the "aligned" attribute on the first
> struct member seems to do the job!
> This way, gcc knows that the struct is aligned and optimizes access to
> all members of the struct. We only have to make sure that the buffer for
> the struct is aligned.
> 
> struct a {
>   int i  __attribute__ ((aligned));
>   char x,y,z;
>   int j;
> } __attribute__ ((packed));

This is going to be ugly as sin.  Could somebody ask people who know how
this should work and whether the ((aligned)) thing is the right
approach?  That could be done with a mail to lkml to see what people
suggest.  I can't believe the libertas driver is the first driver to run
into this issue.

Dan




From dcbw at redhat.com  Thu Jan 29 19:18:26 2009
From: dcbw at redhat.com (Dan Williams)
Date: Thu, 29 Jan 2009 19:18:26 -0500
Subject: Something new with sleep command ?
In-Reply-To: <4981C1F5.4090309@free.fr>
References: <4981C1F5.4090309@free.fr>
Message-ID: <1233274706.4085.35.camel@localhost.localdomain>

On Thu, 2009-01-29 at 15:49 +0100, Cyril HAENEL wrote:
> Hi all,
> 
> I have not seriously read all libertas list messages for at least 5-6 month.
> I just want to know if there is something new about the power managment 
> of wifi card 8385 based ? I know it exists a command to request the 8385 
> to sleep and have a very small current consumption. Someone know if this 
> command is available on not ?

Yes, this command exists.  No, I don't think that command has been
changed in any way in the past year.  The commands I can think of are
CMD_802_11_SLEEP_PARAMS and CMD_802_11_SLEEP_PERIOD.  SLEEP_PERIOD isn't
used anywhere, and SLEEP_PARAMS is only available via debugfs.

The only thing I can think of is the SIOCSIWTXPOW changes recently
(0112c9e9e8d47f1d1e6ce1323675cb43ca6aae86 and
3ed6e0803b4fe95107f6cb5a432587d03cd4d17a from wireless-testing), but
those should only get triggered if you manually change txpower with
iwconfig.  They aren't called by default.

Dan



From lawrence.auster at att.net  Thu Jan 29 19:23:29 2009
From: lawrence.auster at att.net (Lawrence Auster)
Date: Fri, 30 Jan 2009 01:23:29 +0100
Subject: America is a Jewish Colony: Update on =?ISO-8859-1?Q?Olmert=92s?=
	bragging about his humiliation of Bush and America
Message-ID: <20090130002342.HEVE15713.eastrmmtao101.cox.net@eastrmimpo02.cox.net>

America is a Jewish Colony: Olmert reveals it all

On Monday January 12, 2009, the leader of the Jews-only state in Palestine Ehud olmert revealed to a Jewish audience in Ashkelon that he had insisted George Bush should tell Condoleezza Rice to vote against a United Nations? resolution calling for a ceasefire to the Jews? attack on Gaza. Olmert did not inadvertently humiliate the president of the United States of America; the secretary of state, Condoleezza Rice; congress; and the American people, by divulging this information. On the contrary. He was boasting about his power to humiliate the president and thus the American people.

The global Jewish Empire: a global Zionist conspiracy.
There are a handful of commentators in the western world who have been compiling the evidence that America, the world?s greatest democracy and military hyper-power, has been taken over by a Jewish elite which acts on behalf of the Jews-only state in Palestine. America?s ruling Jewish elite?s most well known operatives are the Jewish lobby and the Jewish neocons. These Israel-firsters have been corrupting the Bush regime into implementing policies which promote the interests of the racist state even though they have become increasing catastrophic, economically, militarily, politically, and morally, for America and the American people. After Al Qaeda?s attacks on New York and the Pentagon, zionists imported the Jews? decades-old war against terrorism into America and ever since the Bush regime has been implementing this disastrous zionist doctrine.

Hardline warmongering zionists in the Jews-only state, America, and the rest of the western world, (including most recently, India) have been setting the global political agenda: an invasion of Afghanistan, an invasion of Iraq, an invasion of Lebanon, continued ethnic cleansing of Palestinians, and an attack on iran to trigger a regional, perhaps even a global, war to boost the Jews-only state?s military dominance of the greater middle east.

The mainstream media in the western world is dominated by zionists who use their paper publications, tv, and films, to issue the most blatant zionist propaganda which many westerners welcome because of the disgusting Islamophobia in which it is wrapped. Jewish power in America is now so blatant that Jewish extremists are commissioned to publish articles in the country?s most prestigious newspapers advocating world war three. It has to be asked: what normal, sane, decent person around the world wants another world war? The only people insane enough to demand world war three are hysterical, paranoid, warmongering, Jews.

The irony of the politically kosher worldview which pervades the western world is that the Jewish propagandists who go out of their way to ridicule the idea of a global Jewish conspiracy are themselves advocates of a global Islamic conspiracy. In this hollywood concoction Al Qaeda, Osma bin Laden, Hezbollah, Hamas, Iran, Saddam?s Iraq, etc, etc, have all been secretly working together to exterminate the Jews and overthrow western civilization. Such fantastic drivel is being spewed out solely to cover up the global Jewish conspiracy.

Any decent, open-minded, person observing geopolitics since the foundation of the Jews-only state in Palestine, would have been all too well aware of the way that America has been colonized by Jewish neocons. What is so remarkable about this feat is not so much that a tiny minority could colonize a global hyperpower but that this minority could keep the colonization out of the public realm for so long even though the facts themselves have been screaming out to anyone who could be bothered to listen.

In the politically kosher western world, anti-zionist propositions are usually ostracized but mostly ridiculed or denounced in passing. However, when one of the Jewish leaders at the centre of this global zionist conspiracy gives a clear cut example of his treatment of the president of the United States as a whipping boy, the deniers are put in an embarrassing position. This is especially so since Olmert?s order to Bush was in the best interests of the Jews-only state but was in the president?s (and America?s) worst possible interests because it provoked the rest of the world to despise him, and America, even more for his continued warmongering. So, the question arises, how are mainstream commentators going to confront such a shocking and indisputable revelation? Here?s a spectacular firework display of the truth about Jewish control over America so are they now going to pretend they can?t see the fireworks? In the recent past western politicians wholeheartedly supported the Jewish fantasy that saddam possessed nuclear weapons. Is the world just going to continue upholding the latest Jewish fantasy that iran is close to getting closer to acquiring nukes whilst, at the same time, pretending that the Jews don?t have them? This article looks at commentators? response to Olmert?s sudden revelation.

What Olmert said.
Statement.
Many mainstream American publications covered the story of Olmert?s abusive and humiliating treatment of Bush. Although they quoted from his speech the vast majority used only a few selective quotes and often quoted from different parts of his speech. It is only when the entire speech is heard that the intensity of Olmert?s taunting of Bush becomes clear. The American media thus seemed to limit the quotes it used partly in order to avoid undermining the authority of the president of the United States but also to protect the racist state by preventing Americans from appreciating just how vicious Olmert?s attack on Bush had been.

The three quotes following provide a fullish account of Olmert?s speech. "According to Olmert, he called the White House upon hearing of the upcoming UN Security Council resolution. "I said, 'Get me President Bush on the phone.' They said he was in the middle of giving a speech in Philadelphia. I said I didn't care: 'I need to talk to him now.' He got off the podium and spoke to me," Olmert said, according to multiple media reports. As a result of his conversation with President Bush, Olmert claimed, the president called Rice and forced her to abstain from voting on the measure, which she herself had helped author. "He gave an order to the secretary of state and she did not vote in favor of it, a resolution she cooked up, phrased, organized, and maneuvered for. She was left pretty shamed and abstained on a resolution she arranged," Olmert said." (Daniel Luban ?Olmert's Claims Revive Israel Lobby Controversy? http://www.antiwar.com/ips/luban.php?articleid=14061 January 14, 2009); "According to Olmert, he told Bush that the US should not vote for the resolution, and Bush then directed Rice to abstain. "She was left pretty embarrassed," Olmert said. Like Olmert's aides, an official in the Prime Minister's Office said "the Prime Minister's comments on Monday were a correct account of what took place."" (Herb Keinon, Allison Hoffman ?'PM stands by his version in diplo spat'? http://www.jpost.com/servlet/Satellite?cid=1231866576464&pagename=JPost%2FJPArticle%2FPrinter January 14, 2009); "So, here, in Olmert's words, is what happened next. "In the night between Thursday and Friday, when the secretary of state wanted to lead the vote on a cease-fire at the Security Council, we did not want her to vote in favor. I said, 'Get me President Bush on the phone.' They said he was in the middle of giving a speech in Philadelphia. I said I didn't care. 'I need to talk to him now.' He got off the podium and spoke to me." According to Olmert, Bush was clueless. "He said: 'Listen. I don't know about it. I didn't see it. I'm not familiar with the phrasing.? I told him the United States could not vote in favor. It cannot vote in favor of such a resolution. He immediately called the secretary of state and told her not to vote in favor."" (Patrick J. Buchanan ?Is Ehud's Poodle Acting Up?? http://www.antiwar.com/pat/?articleid=14091 January 17, 2009).

U.S. State Department response.
America?s state department was angry with Olmert but whether this was because it didn?t like the president being humiliated or because they were furious he?d given the game away is not clear. "The U.S. State Department fiercely denied claims made by Ehud Olmert about his influence over President George W. Bush, in an incident that has stirred up old debates about the role of the Israeli government and the so-called "Israel lobby" in formulating Middle East policy in Washington." (Daniel Luban ?Olmert's Claims Revive Israel Lobby Controversy? http://www.antiwar.com/ips/luban.php?articleid=14061 January 14, 2009).

Olmert not backing down.
"The State Department immediately contradicted Olmert?s claims, insisting that "the government of Israel does not make US policy." Spokesman Sean McCormack also suggested that Israel might want to "clarify or correct the record" with respect to the comments. Rice has dismissed Olmert?s claims as "fiction." The comments have sparked no small concern in Israel, where the fear is that Olmert?s claims to be able to order the President of the United States around will only increase public opposition in America to Israel?s influence on its foreign policy. Yet spokesmen for Olmert say that the prime minister stands behind his version of events." (?Olmert Stands Behind Rice-Shaming Claim: Rice Calls Prime Minister's Comments "Fiction"? http://news.antiwar.com/2009/01/14/olmert-stands-behind-rice-shaming-claim/ January 14, 2009).

Haaretz suggests Olmert closer to the truth than Rice.
"Inquiries with people uninvolved in the spat between Prime Minister Ehud Olmert and U.S. Secretary of State Condoleezza Rice reveal that his version of the lead-up to America's vote on last week's Security Council resolution is closer to the truth than hers. The whole story would have ended well had Olmert behaved like a responsible adult and restrained his own impulses. Even his close associates admit that he would have done better to skip the public boasting about how he persuaded Bush to overrule Rice. Quite aside from the fact that this embarrassed the U.S. administration, Olmert's associates understand all too well that this story merely provides fresh ammunition to those who claim the Jews are the ones who really control America." (Akiva Eldar ?Inquiries show Olmert version of UN Gaza vote spat closer to truth than Rice's? http://www.haaretz.com/hasen/spages/1055966.html January 01, 2009).

How have America?s commentators reacted to Olmert confession?
In the past, American commentators have adamantly refused to discuss Jewish economic, cultural, or political, power in America. Indeed, their silence is yet another piece of evidence as to the existence of such power. So, will Olmert?s confession set them free to challenge the Jews? colonization of America and its calamitous consequences for the country (and many other countries around the world)? Or will they just go on living comfortably in the zionist fantasy world created for them by America?s Jewish ruling elite?

Juan Cole picks up on Olmert?s confession to propose that Jewish nazis are exercising their power in America not merely through Bribery but Blackmail.
Cole covered the outburst in detail and speculated that zionist power in America might derive from Mossad?s acquisition of material with which it could blackmail Bush. For a political commentator such as Cole, a high profile member of America?s defunct wasp establishment, to have to resort to such a wacky, fringe, idea is unusual to say the least. But then again what alternative does he have since he won?t talk about America?s ruling Jewish elite, the colossal economic power acquired by the Jewish elite, nor the zionists near total domination of congress and the American media.

Steven C Clemons.
Clemons personalizes Olmert?s statement so that it is merely a kick in the face for the president and Condoleezza Rice rather than a statement of shame about the gross subservience of America?s much vaunted democratic system and the ignominious position of the American people whose political leaders care more about protecting the Jews-only state in Palestine than looking after their own citizens. "No matter what one may think of Condoleezza Rice's diplomatic record, which I think is better than many liberal critics gauge, the fact that Israel Prime Minister Ehud Olmert gave her a kick in the teeth as she departs her office is obnoxious and harmful all around. Shaming a US President and Secretary of State may not change the course in policy and may not shift America's general approach to the region, at least for the time being, but it does take the fizz out of the unique relationship." (Steven C Clemons ?Defending Condi: Olmert Shames Himself in Kick-in-the-Teeth Attack on Rice? http://www.thewashingtonnote.com/archives/2009/01/defending_condi/ January 12, 2009). Clemons has no interest in questioning the political significance of America?s democracy, reputed by common opinion to be the best in the world, even though its president and members of congress are mere vassals to a rogue state, a hive of Jewish racists, in the middle east.

Philip Weiss.
"Clemons gets it right re Olmert and Condi, that it's a disgraceful attack. I missed the humiliation in this. Israel often treats our executive like the help, because Israelis know they have power in Washington. It's similar to Ehud Barak treating Bill Clinton like a peer in 2000, and Yitzhak Shamir lying to George Bush about not building more settlements, in '91. They always get away with it, because of the lobby. No wonder the fury at J Street has been coordinated by the Israeli embassy. They have so much to lose." (Philip Weiss ?Where is Hillary on cease-fire?? http://www.philipweiss.org/mondoweiss/2009/01/where-is-hillary-on-ceasefire-.html January 13, 2009). Here?s one Jewish writer making a determined effort to learn the truth about American politics.

Xymphora points out Kouchner?s Zionist Treachery.
"Juan Cole, who seems to be letting his freak flag fly recently, has an excellent detailed posting on the automatic control that the Israeli government has over the American government, exemplified by Olmert picking up the phone and ordering Bush around to the extent that the United States changed its mind and abstained, rather than voted for, the latest UN cease-fire resolution.  This was a public slap in the face for Rice, who actually helped draft the resolution, and Olmert is crowing about it.  Note the behind-the-scenes trickery of the Jew Kouchner, who valiantly worked for his homeland, Israel, naturally, not France, to try to block the resolution. Cole concludes by raising the most important issue of all, the consideration of which is necessitated by the lack of any obvious motive for Bush to act as he did, the conspiracy theory that the mysterious hold of Zionism over American politicians is connected to blackmail.  Israeli intelligence, with the aid of the secret cadre of dual-loyalty American Jews, gathers dossiers of information on characters like Bush, people who have a lot of embarrassments in their pasts, and holds it over them.  Other than direct payments of cash, which probably explains Cheney, this is by far the most plausible theory for why American politicians consistently and blatantly act against American interests (sorry Noam). I wonder what the Israeli dossier on Obama looks like?" (Xymphora ?The mysterious hold of Zionism over American politicians? http://xymphora.blogspot.com/2009/01/mysterious-hold-of-zionism-over.html January 13, 2009).

Matthew Yglesias.
"The State Department has some not-terribly-convincing denials out. But one way or another it seems both telling and unseemly that Olmert is going around bragging about this." (Matthew Yglesias ?Olmert Claims to Control US Foreign Policy? http://yglesias.thinkprogress.org/archives/2009/01/olmert_claims_to_control_us_foreign_policy.php January 13, 2009). Olmert should be applauded for telling the truth not criticized for bragging. Now that the truth is out why doesn?t Yglesias spend his time outlining its fundamental political implications and ramifications?

Paul Craig Roberts.
The inimitable Paul Craig Roberts is a unique and fearless commentator: a former politician who speaks truth to power. "Israeli politicians have been bragging for decades about the control they exercise over the US government. In his final press conference, President Bush, deluded to the very end, said that the whole world respects America. In fact, when the world looks at America, what it sees is an Israeli colony. What is happening to the Palestinians herded into the Gaza Ghetto is happening because of American money and weapons. It is just as much an attack by the United States as an attack by Israel. The US government is complicit in the war crimes. "Our" president was a puppet for a cabal led by Dick Cheney and a handful of Jewish neoconservatives, who took control of the Pentagon, the State Department, the National Security Council, the CIA, and "Homeland Security." From these power positions, the neocon cabal used lies and deception to invade Afghanistan and Iraq, pointless wars that have cost Americans $3 trillion, while millions of Americans lose their jobs, their pensions, and their access to health care." (Paul Craig Roberts ?The White House Moron Stumbles to the Finish: The Humiliation of America? http://www.counterpunch.com/roberts01142009.html January 14, 2009).

Steven Spiegel.
"Middle East expert Steven Spiegel described the episode as "the worst faux pas by an Israeli prime minister in history. You really do wonder what the prime minister was thinking, if it's true, you'd really want to keep it as quiet as possible, and if it's not true, why would you want to make up a story that would embarrass both the Bush administration and the Israeli government and draw criticism from those who are antagonistic to Israel?" asked Spiegel, director of the Center for Middle East Development at UCLA. "No matter how you play it, exaggeration, falsehood, whole truth, the whole thing makes them all look bad," Spiegel told The Jerusalem Post." (Herb Keinon, Allison Hoffman ?'PM stands by his version in diplo spat'? http://www.jpost.com/servlet/Satellite?cid=1231866576464&pagename=JPost%2FJPArticle%2FPrinter January 14, 2009).

Justin Raimondo.
In the past, Raimondo has been edging towards stating that the Jews-only state in Palestine, with the aid of its political agents in America, controls America?s foreign policies. It might have been thought he would have taken Olmert?s statement as a great opportunity to highlight this fundamental reality of American politics. At first it seems he would. "It (Olmert?s statement) tells us who is used to giving orders, and who is accustomed to obedience." (Justin Raimondo ?Israel versus America: Is the 'special relationship' over? http://www.antiwar.com/justin/?articleid=14075 January 16, 2009). But he doesn?t. "What Gaza signals is a new turn for the Israelis, a clean break, if you will, with their status as an American puppet in the Middle East. They are clearly going off on their own, intent on waging a war of unmitigated aggression against all their neighbors." (Justin Raimondo ?Israel versus America: Is the 'special relationship' over? http://www.antiwar.com/justin/?articleid=14075 January 16, 2009). When given the opportunity he ducks it. The apartheid state has always been an American puppet but is now going off on its own. Such an argument would make sense if America had stopped giving the racist state vast annual tribute payments and stopped providing it with endless quantities of weapons and munitions with which to slaughter innocent civilians. Oh well, seems like Raimondo?s back in the closet.

Patrick J. Buchanan.
Over the last couple of decades, Buchanan has been one of the few mainstream American politicians who have criticized the Jews-only state and Jewish power in America and has suffered the consequences. And yet he?s been quite restrained about Olmert?s confession. "With Bush and Rice leaving office in hours, and Olmert in weeks, the story may seem to lack significance. Yet, public gloating by an Israeli prime minister that he can order a U.S. president off a podium and instruct him to reverse and humiliate his secretary of state may cause even Ehud's poodle to rise up on its hind legs one day and bite its master. Taking such liberties with a superpower that, for Israel's benefit, has shoveled out $150 billion and subordinated its own interests in the Arab and Islamic world would seem a hubristic and stupid thing to do." (Patrick J. Buchanan ?Is Ehud's Poodle Acting Up?? http://www.antiwar.com/pat/?articleid=14091 January 17, 2009).

Brian Cloughley.
Cloughley enters the fray, "And the President of the United States of America jumps to obey the Israeli prime minister." (Brian Cloughley ?The Power of AIPAC: Who Runs America?? http://www.counterpunch.com/cloughley01162009.html January 16-18, 2009).

However, the reason that America?s ruling Jewish elite is nigh on impervious is because those on the left refuse to challenge it. Cloughley points out that members of congress are funded by Jews but doesn?t generalize beyond this to expose America?s ruling Jewish elite. "There is one thing certain: the US Congress is going to continue its unconditional support for Israel, no matter what war crimes are committed by its disgusting thugs-in-uniform. The Reps need the money, after all, which they get through political action committees which are generously funded by American Jews. And they are scared to political death by the threat that pro-Israel agencies will destroy them politically if they dare say a word against Israel. There are very few Representatives of the people of America who would dare challenge Israel, or who might possibly criticize Israel, or who have the courage to condemn atrocities committed by Israel." (Brian Cloughley ?The Power of AIPAC: Who Runs America?? http://www.counterpunch.com/cloughley01162009.html January 16-18, 2009).

He criticizes the American media for not telling the truth. "Not many Americans know anything about the hideous barbarity in Gaza, because US cable networks and newspapers rarely carry pictures of disfigured blood-splashed children who have been killed, maimed or orphaned by the Israelis. But here in Europe we have access to some TV channels and newspapers that are very different from the pliant pro-Zion patsies of the major news outlets across the Atlantic." (Brian Cloughley ?The Power of AIPAC: Who Runs America?? http://www.counterpunch.com/cloughley01162009.html January 16-18, 2009). But he fails to tell the truth by not denouncing the zionist owned and controlled American media. The media in any country is a reflection of that society?s ruling class. No ruling class rules without the help of a cheerleading media. The reason that America?s mainstream media supports the Jews-only state is because it is owned and staffed primarily by members of America?s ruling Jewish elite.

Tony Karon.
As far as is known Karon has made no comment about Olmert?s confession. However, the confession places Karon?s comments about Rice?s supervision of the Jewish war against lebanon in 2006 in a different light. "It was clear, at the time, that the neophyte Olmert was outsourcing his decision-making to Condi Rice. I wrote at the time of the sense that Israel was waging a proxy war for the Bush Administration, a sense confirmed at the time by the hawkish dean of Israeli military correspondents, Ze?ev Schiff, who wrote at the height of the conflict: "U.S. Secretary of State Condoleezza Rice is the figure leading the strategy of changing the situation in Lebanon, not Prime Minister Ehud Olmert or Defense Minister Amir Peretz. She has so far managed to withstand international pressure in favor of a cease-fire, even though this will allow Hezbollah to retain its status as a militia armed by Iran and Syria." (Tony Karon ?Olmert: His Own Shlemiel, or Bush?s?? http://tonykaron.com/2008/01/31/olmert-his-own-shlemiel-or-bushs/ January 31, 2008). If Olmert was capable of humiliating Rice over the United nations? resolution over Gaza is it likely that, two years earlier, he?d allowed her to run the show slaughtering Lebanese civilians?


George Bush, the Jews? whipping Boy.
What has not been pointed out by commentators on Olmert?s confession was that he was referencing a statement made by Ariel Sharon a few years earlier. In september 2001, Sharon had publicly humiliated Bush by calling him a Chamberlain. "Don't repeat the terrible mistake of 1938 when the enlightened democracies of Europe decided to sacrifice Czechoslovakia for a convenient temporary solution. Do not try to placate the Arabs at our expense ... Israel will not be Czechoslovakia. Israel will fight terror." (?Israel consumed by victim culture? Guardian 5.10.2001). A few days later, Sharon compounded the humiliation, "Every time we do something, you (Shimon Peres) tell me Americans will do this and will do that. I want to tell you something very clear. Don?t worry about American pressure on Israel; we, the Jewish people, control America and the Americans know it." (Zionist Prime Minister Ariel Sharon October 3, 2001 IAP News).

Olmert?s Jewish audience would have picked up on this reference and understood that Olmert was trying to cloak himself with Sharon?s mantle as one of the Jews? most belligerent warmongers (although whether they believed Olmert deserved such a comparison is another matter).

Olmert?s humiliation of Bush could not be a more fitting finale to Bush?s presidency. His presidency began not so much on september 11, 2001 with Al Qaeda?s attacks on New York and the Pentagon but with Sharon?s success in forcing him to accept the likudnik interpretation of this event. The Bush regime did not respond to this event by implementing policies to protect and promote American interests. On the contrary, Sharon, and the Jewish neocons/lobby in America, pushed the Bush regime into implementing policies that boosted the interests of the Jews-only state in Palestine even though these policies would have a catastrophic impact on America?s interests. In other words, the president of the United States failed to interpret this critical event, even though it happened in his own country, because he was overwhelmed by the narrative put forward by the leader of a shitty little country on the other side of the planet and by Jewish neocons in America loyal to that country. Al Qaeda attacked America because of its unconditional support for the Jews-only state. Bush and America could have realized that such unconditional support was against America?s interests, but the rogue state and its Jewish agents in America pressured the president into adopting even more extreme zionist policies which put America interests at even greater risk.

Al Qaeda?s payback on America was a major turning point in American history but Americans had nothing to do with the direction in which their own country then moved. "Common wisdom has it that after 9/11, a new era of geo-politics was ushered in, defined by what is usually called the Bush doctrine: pre-emptive wars, attacks on terrorist infrastructure (read: entire countries), an insistence that all the enemy understands is force. In fact, it would be more accurate to call this rigid worldview the Likud doctrine. What happened on September 11, 2001 is that the Likud doctrine, previously targeted against Palestinians, was picked up by the most powerful nation on earth and applied on a global scale. Call it the Likudisation of the world: the real legacy of 9/11." (Naomi Klein ?The Likud doctrine? The Guardian http://www.guardian.co.uk/russia/article/0,2763,1301504,00.html September 10, 2004); "But the idea of a super-power behaving in a similar way, responding to terrorist threats or guerrilla incursions by flattening another country just to preserve its own deterrent credibility, is odd in the extreme. It is one thing for the US unconditionally to underwrite Israelis? behaviour (though in neither country?s interest, as some Israeli commentators at least have remarked). But for the US to imitate Israel wholesale, to import that tiny country?s self-destructive, intemperate response to any hostility or opposition and to make it the leitmotif of American foreign policy: that is simply bizarre. Bush?s Middle Eastern policy now tracks so closely to the Israeli precedent that it is very difficult to see daylight between the two. It is this surreal turn of events that helps explain the confusion and silence of American liberal thinking on the subject (as well, perhaps, as Tony Blair?s syntactically sympathetic me-tooism). Historically, liberals have been unsympathetic to ?wars of choice? when undertaken or proposed by their own government. War, in the liberal imagination (and not only the liberal one), is a last resort, not a first option. But the United States now has an Israeli-style foreign policy and America?s liberal intellectuals overwhelmingly support it." (Tony Judt ?Bush?s Useful Idiots? http://www.lrb.co.uk/v28/n18/judt01_.html September 21 2006).

An American president who calls for a Palestinian state (the first to do so) but fails to deliver it, despite the successive, nonstop, diplomatic efforts of Colin Powell and Condoleezza Rice, America?s massive funding of the apartheid state, and the widespread international support for such a goal, is clearly subservient to zionist power and influence. Brent Scowcroft was one of the few to confront such fundamental realities of American political life when he stated that Ariel Sharon had Bush wrapped around his little finger. It is a remarkable testimony to Americans? capability for living in their highly leveraged zionist fantasy world that they ignored Scowcroft?s insider remark and continued their patriotic bleats about how America is the most powerful country in the world with the world?s sole military hyper-power.

For a number of other blatant examples of how Sharon continually beat up Bush and got him to support extreme zionist policies which have had the most devastating economic, political, and military, consequences for America please see ?America is a Jewish Colony: Bush is Sharon?s Muppet?
http://themundiclub.blogspot.com/2009/01/america-is-jewish-colony-bush-is.html

It is hardly surprising then that the Bush presidency should end so ignominiously when another hysterical, paranoid, warmonger from the Jewish nazi state boasted to the whole world that, in effect, Bush was nothing but his whipping boy. Why should Olmert fear retribution for his gross humiliation of Bush and the American people when they can?t harm Jewish power in America?

 URL: http://themundiclub.blogspot.com/2009/01/america-is-jewish-colony-olmert-reveals.html


-


America is a Jewish Colony: Update on Olmerts bragging about his humiliation of Bush and America [http://atheonews.blogspot.com/2009/01/america-is-jewish-colony-update-on.html]
By Bob Finch

How have America?s commentators reacted to Olmert?s confession?

Abraham Foxman defends Olmert

Abraham Foxman, national director of the Jewish fascist organization the Anti-Defamation League, defended Olmert by likening the incident to a private squabble between two friends. "I have no problem with what Olmert did," said Abraham Foxman, national director of the Anti-Defamation League. "I
think the mistake was to talk about it in public. This is what friendships are about. He was not interfering in political issues. You have a relationship, and if you don?t like what is being done, then you go to the boss and tell him." (Nathan Guttman Olmerts Boast of
Shaming Rice Provokes Diplomatic Furor [http://www.forward.com/articles/14957/] January 15, 2009).

This is just blatant spin. A person does not publicly boast about revealing his friend?s stupidity (i.e. Bush didn?t know the content of the resolution); he doesn?t enjoy boasting about humiliating a friend (Bush); nor relish shaming another friend (Rice).

Foxman is trying to diminish the seriousness of Olmert?s major political gaffe. He wants to prevent the incident from becoming a full scale political controversy which might enable more Americans to learn about the Jews? death grip over the Bush regime and American political system. He doesn?t
want the American public questioning the power that the Jews-only state has over America, a military hyperpower. Such a controversy might end up destroying the taboos the Jewish lobby has so carefully nurtured in America over the last six decades. It could harm the zionist state?s chances of
dominating future American administrations. Foxman wants the American public to continue to believe in the zionist-nurtured fantasy that America is the greatest nation on Earth rather than a pathetic puppet which makes massive annual tribute payments, and supplies endless quantities of weapons, to
its masters on the other side of the planet.

Douglas Bloomfield defends Olmert

"Douglas Bloomfield, a former chief lobbyist for the Washington-based pro-Israel lobby the American Israel Public Affairs Committee, dismissed the episode as "a spitting match between two lame ducks." "This reinforces the perception that the Israeli prime minister and Israeli leaders have easy
access to the leaders of the U.S.," Bloomfield said. "It is a fact that the Israeli prime minister can get the president on the phone. Not every prime minister in the world can do that. It is no secret that Israel tried to influence the U.S. regarding U.N. votes. It reinforces what the rivals of
Israel say about the enormous clout Israel has in Washington, and I see nothing wrong with that." But Bloomfield added, "It is a mistake to talk about it."" (Nathan Guttman Olmerts Boast of Shaming Rice Provokes Diplomatic Furor
[http://www.forward.com/articles/14957/]). Bloomfield defends Olmert but believes he was wrong to make such an incident public. The problem is not that Olmert treats the American president as his whipping boy but that he tells everyone about it.

William Pfaff

"Olmert told an Israeli audience that, last Friday, upon hearing of Rice?s position, he immediately telephoned George W. Bush. Told that Bush was delivering an address in Philadelphia, Olmert replied, "I?m not interested," demanding to speak to Bush. Bush then left his Philadelphia podium and,
according to Olmert, the Israeli prime minister instructed the American president that "the U.S. cannot possibly vote in favor of this resolution." Bush then telephoned Rice and ordered her to abstain from the vote. That?s Olmert?s story, or Israeli megalomania, presented to the Israelis with
pride, but unlikely to be received by Americans with pleasure." (William Pfaff Whos in Charge, Obama, the Pentagon or Israel? [http://www.truthdig.com/report/item/20090115_whos_in_charge_obama_the_pentagon_or_israel/] January 15, 2009). Pfaff couldn?t be more coy. The
president of Israel publicly brags about humiliating the president of the world?s military hyper-power but, according to Pfaff, the only negative outcome is that it is "unlikely to be received by Americans with pleasure." Where?s Pfaff?s raging denunciation of Olmert?s insult to his president? Or
does he really know who controls America and doesn?t want to be the one to spill the beans?

David Bromwich

"American politicians exhibit an identification with Israel that is now in excess of the measurable effects of the Israel lobby. The blindness of the identification has led the US to respond with keen sensitivity to Israeli requests for assistance and moral support, and to underestimate the
suffering caused by the Gaza blockade and by the settlements and checkpoints and the wall on the West Bank. Yet grant the potency of the lobby and the identification ? even so, the arrogance with which Israel dictates policy is hard to comprehend on the usual index of motives. Ehud Olmert boasted
to a crowd in Ashkelon on 12 January that with one phone call to Bush, he forced Condoleezza Rice to abstain from voting for the UN ceasefire resolution she herself had prepared. The depth, the efficacy and the immediacy of the influence are treated by Olmert as an open secret." (David Bromwich
LRB contributors react to events in Gaza [http://www.lrb.co.uk/web/15/01/2009/mult04_.html]January 15, 2009). In other words, Jewish extremists haven?t colonized America, Americans just identify themselves with whatever the Jewish nazis decide to do. Quite why Americans would want to
give away billions of dollars in non-refundable loans, weapons and munitions, and then be reviled by the rest of the world when the Jews use these loans and weapons to carry out gross acts of barbarism, is nonsensical. But then advocating such nonsense is much easier than highlighting how the Jews
have turned America into a huge warehouse from which they take whatever they need to boost the Jews? regional supremacism in the middle east.

The American public?s response to Olmert?s statement

It might have been expected that there would be a huge public uproar that the president had been so mercilessly humiliated by what, to Americans, must seem like the pip-squeak leader of a pip-squeak country. But where were American patriots? mass displays of raging anger towards Olmert and the
zionist state? Janet Jackson?s superbowl nipple display elicited a far greater scale of public indignation than Olmert?s humiliation of Bush.

This astounding non-reaction may have been brought about by two factors. Firstly, America?s Zionist dominated media refused to make a political issue out of the incident. The serious publications/broadcasters didn?t want to discuss it and the tabloids refused to hype it up. Secondly no patriotic
American politician wanted to treat the issue seriously let alone hype it for political gain.

A good example of the non-Zionist Jewish reaction is Phillip Weiss. His first reaction to the incident was that he didn?t notice the humiliation! "Clemons gets it right re Olmert and Condi, that it's a disgraceful attack. I missed the humiliation in this. Israel often treats our executive like the
help, because Israelis know they have power in Washington. It's similar to Ehud Barak treating Bill Clinton like a peer in 2000, and Yitzhak Shamir lying to George Bush about not building more settlements, in '91. They always get away with it, because of the lobby. No wonder the fury at J Street
has been coordinated by the Israeli embassy. They have so much to lose." (Philip Weiss Where is Hillary on cease-fire? [http://www.philipweiss.org/mondoweiss/2009/01/where-is-hillary-on-ceasefire-.html] January 13, 2009). Weiss knows that Jewish leaders bully American presidents so
to him it was nothing unusual and thus nothing to get unduly worked up about. It was just like the head of the household ticking off the domestic! But as an American it might have been thought he should have felt some animosity toward Olmert and the racist state for humiliating what is supposedly
his president and his country.

Then there are the Israel-firsters. They whip up American patriotism solely for the benefit of the Jews-only state. (For example the Ziocons fostered American patriotism for the war in Iraq which was beneficial to the Jews-only state but not America). This type of person would have felt proud that
his tribe?s political leader had the chutzpah to humiliate an American president. Instead of condemning Olmert they defended him. Instead of being outraged they feigned indifference. Instead of turning the incident into a political controversy they sought to marginalize it. The last thing they
wanted was to expose Jewish power over American politicians, and thus the dominance of the squatter state over the world?s military hyper-power. It might undermine American patriots? grandiose fantasies about the importance of their country and cast doubts in their minds about its relationship to
the Zionist state.

Thus the American public?s non-reaction to the Olmert incident can be explained in terms of the dominance of the Israel-firsters who want to maintain Jewish dominance over America. There were no patriotic American political leaders and no patriotic American commentators to politicize this
revealing political story because most of them are Ziocons i.e. traitors to America.

American patriots are proud of America?s military might, technological progress, and economic success. Some even go so far as talking about America?s destiny to make the world a better place. And yet the vast mass of them were indifferent to the political humiliation of their president. They
seemed oblivious that Olmert had not merely humiliated their president but exposed the servility of the American political system which gives billions of dollars a year in tribute payments to the rogue state. They seemed oblivious of America losing its global political reputation by giving the
Jews-only state unconditional political and diplomatic support even when it ruthlessly pursues racist policies and carries out the most barbaric onslaughts against unarmed civilians.

American patriotism seems to be expressed only when America?s ruling Jewish elite conjures it up because it suits their interests or those of the Jews-only state. American patriots are just mindless cheerleaders in a choreography written for them by their invisible Jewish masters.

[http://www.counterpunch.com/nader01202009.html]

Another important revelation arising out of Olmert?s bragging about his control over Bush was that he had no fear of retribution from the Bush regime. A few days before Olmert?s confession, the American congress had passed a resolution which wholly supported the Jews? slaughter of Palestinian
civilians in Gaza even though the rest of the world opposed such a slaughter and despised America for giving the Jews blanket support. "The latest illustration of this Washington puppet show, backed by the most modern weapons and billions of taxpayer dollars annually sent to Israel, was the
grotesquely one-sided Resolutions whisked through the Senate and the House of Representatives. While a massive bombing and invasion of Gaza was underway, the resolution blaming Hamas for all the civilian casualties and devastation, 99% of it inflicted on Palestinians, zoomed through the Senate by
voice vote and through the House by a vote of 390 to 5 with 22 legislators voting present. There is more dissent against this destruction of Gaza among the Israeli people, the Knesset, the Israeli media, and Jewish-Americans than among the dittoheads on Capitol Hill." (Ralph Nader Punishing
the Palestinians: State Terrorism Against Gaza [http://www.counterpunch.com/nader01202009.html] January 20, 2009).

Olmert knew not merely that Bush was at the end of his presidency but that congress wouldn?t allow the Bush regime to retaliate against him for what he?d said. He clearly knew that congress is more devoted to Jewish presidents than to its own presidents. The American congress should be called the
American knesset because Jewish leaders have frequently got away with humiliating American presidents. Uri avnery sought, indirectly, to counter any political damage that could ensue from the incident by reiterating the politically conventional viewpoint that Israel is just an American colonial
outpost. "The Israeli Barak understands that if the American Barack gets angry, that would mean disaster. Conclusion: the horrors of Gaza must stop before the inauguration. This week that determined all political and military decisions. Not "the number of rockets", not "victory", not "breaking
Hamas"." (Uri Avnery Livni's Smile: The Boss Has Gone Mad [http://www.counterpunch.com/avnery01192009.html] January 19, 2009). But avnery?s statement is just spin because he knows that if obama ever criticized the Jews-only state, let alone threatened to reduce America?s massive
tribute payments, or supplies of munitions, to the rogue state, he would immediately come under serious political flak from congress. It is the president of the United States who is terrified of Jewish political leaders not the other way around. Avnery?s seemingly commonsensical statement is just
Jewish hasbara to cover up the current global balance of power in which the Jews-only state, the Jewish lobby in America, the zionist dominated American media, and the American knesset, have dominant political influence over the American president.

The American congress should be the most patriotic institution in America but it has been transformed into a legislature whose rightful home would be somewhere on the west bank. Members of congress are loyal to their Jewish financial paymasters and are thus not only traitorous to the American
electorate but to the American president. They would criticize, perhaps even impeach, their own president but they would never dare to make the slightest criticism of a Jewish leader or the Jewish state. Whenever the crunch comes, the American knesset backs Jewish leaders against their own
president.

Where?s Olmert?s gratitude to Bush?

There are many reasons why the Jews could militarily pulverise Gaza reducing large parts of it to rubble and slaughtering thousands of innocent Palestinian civilians.

Firstly, the Bush regime, like its predecessors, provided massive tribute payments to the Jews-only state in Palestine which meant the war would not put a financial strain on the Jewish government?s budget or on the Jewish economy.

Secondly, the Bush regime supplied the Jews-only state with whatever munitions it wanted. "The supply of American weapons used in the massacres was authorized previously by such a margin. These included the Hellfire missile which sucks the air out of lungs, ruptures livers and amputates arms and
legs without the necessity of shrapnel: a "major advance," according to the specialist literature. As a senator, then president-elect, Obama raised no objection to these state-of-the-art [sic] weapons being rushed to Israel, worth $22 billion in 2008, in time for the long-planned assault on Gaza's
fenced and helpless population." (John Pilger Come On Down for Your Freedom Medals [http://www.antiwar.com/pilger/?articleid=14110] January 22, 2009); "Frida Berrigan, a senior research associate with the Arms Trade Resource Center at the World Policy Institute, points out that the
bulk of Israel's current arsenal is composed of military equipment supplied under U.S. assistance programs. Israel, she said, has been supplied with 226 F-16 fighter planes and attack jets, more than 700 M60 battle tanks, 6,000 armored personnel carriers and scores of transport planes, attack
helicopters and utility and training aircraft, bombs and tactical missiles of all kinds." (Thalif Deen Hamas Fights on Uneven Battlefield [http://www.antiwar.com/ips/deen.php?articleid=14124] January 23, 2009). This open-ended supply of weapons and munitions had a critical impact on
the Jews? military strategy. The Jews-only state adopted a military policy of grossly disproportionate retaliation against its adversaries because it could call upon an unlimited supply of munitions from its American warehouse. If the Zionists had to rely solely on their own financial resources
they would never have pursued such a psychotic military policy.

Thirdly, the Zionists knew they could act as barbarically as they wanted against Palestinian civilians because the Bush regime would give them all the political and diplomatic protection they needed from the anger of the rest of the world. There would be no chance of the United Nations or the
Security Council agreeing on sanctions against the Jewish state because the Bush regime would just veto the proposal.

Finally, over the last eight years the Bush regime has provided the Jews-only state with a huge range of services. It has launched proxy Zionist wars against Afghanistan and Iraq. Bush more or less handed the West Bank to the squatter state. He continually protected the Jewish state in the united
nations. And, in 2006, he deflected global condemnations of the Jews? slaughter of Lebanese civilians onto himself and America.

It might have been expected then that Olmert would have been hugely grateful to Bush for his enormous financial, political, and military, generosity towards the Jews-only state. And yet despite Bush?s assiduous dedication to the cause of Jewish racism, Olmert still treated him with contempt. This
wasn?t chutzpah so much as the ingratitude that a master bestows upon his slave. If Olmert was really the leader of an American outpost in the Middle East he?d have been overjoyed by the vast help that the Bush regime had provided. The fact that he treated Bush so contemptuously rather than
lavished praise upon him shows that the Jewish state is dominant over America and, correspondingly, that the global Jewish empire treats America as its colony.

Olmert?s outburst showed his willingness to humiliate Bush, congress, and the American people. It showed that Jewish dominance of the American knesset is so overwhelming that members of congress would not condemn an attack on their own president. It showed that the American knesset would protect
Olmert from any retribution by the Bush regime. It showed that Olmert, with the support of the American knesset and the Zionist dominated American media, felt powerful enough to humiliate the American president without suffering any American patriotic outrage that would hurt the interests of the
racist state. And it showed the sheer ingratitude that Jewish leaders have towards their American minions no matter what these muppets do for their Jewish masters. Americans have sacrificed their wealth, their dignity, their political principles, and their decency, for the sake of supporting the
barbaric Jews-only state and yet Zionist leaders still prefer to humiliate American presidents and the American people rather than showing any gratitude. The Jews have not merely colonized America they have colonized the minds of the American people. Americans have become laughably docile in
comparison to the hugely resilient, courageous, and unconquerable, Palestinians.

Source [http://themundiclub.blogspot.com/2009/01/america-is-jewish-colony-update-on.html]


-----

The next session of Congress will include 44 Jewish lawmakers, a new record

It is well known that American Jews are disproportionately represented in the mass media, the entertainment business, and the financial industry. As recently as December 19th, 2008, Joel Stein, a Jewish columnist for the Los Angeles Times, starkly reaffirmed and orgiastically celebrated their
dominance of the entertainment industry in his column [http://www.latimes.com/entertainment/news/celebrity/la-oe-stein19-2008dec19,0,2313474.column].

However, a recently-released report [http://pewforum.org/] by the Pew Forum for Religion and Public Life, which included a breakdown of the faiths and denominations of the members of the incoming 111th Congress, shows that Jews are also disproportionate in Congress as well, constituting 8.4
percent of its membership, as opposed to just 1.7 percent of the overall population. The Pew report is available HERE [http://pewforum.org/docs/?DocID=379]; the 15-page appendix listing all individual members of Congress is HERE [http://pewforum.org/newassets/images/reports/congress/appendix.pdf].

And, as expected, some Jewish members of Congress are more financially beholden to Israel than others. Click HERE [http://www.wrmea.com/archives/November_2008/pdfs/nov08pac-charts.pdf] to find out about pro-Israel PAC contributions to members of Congress through 2007-08. Then compare to the names
listed below.

The list is alphabetized by state, then further alphabetized by member?s last name within each state. Click on the highlighted name to go directly to the member?s official Congressional website.

(1). U.S. Senators

? Barbara Boxer [http://boxer.senate.gov/] (D-CA)
? Dianne Feinstein [http://feinstein.senate.gov/] (D-CA)
? Joseph Lieberman [http://lieberman.senate.gov/] (I-CT)
? Benjamin L. Cardin [http://www.cardin.senate.gov/] (D-MD)
? Carl Levin [http://levin.senate.gov/] (D-MI)
? *Norm Coleman [http://coleman.senate.gov/public/] (R)/Al Franken (D) (MN)
? Frank Lautenberg [http://lautenberg.senate.gov/] (D-NJ)
? Charles Schumer [http://schumer.senate.gov/] (D-NY)
? Ron Wyden [http://wyden.senate.gov/] (D-OR)
? Arlen Specter [http://specter.senate.gov/] (D-PA)
? Bernard Sanders [http://sanders.senate.gov/] (I-VT)
? Russ Feingold [http://feingold.senate.gov/] (D-WI)
? Herb Kohl [http://kohl.senate.gov/] (D-WI)

* Minnesota Senate race not yet settled as of this post.

(2). U.S. Representatives

? Gabrielle Giffords [http://giffords.house.gov/] (D-AZ)
? Howard Berman [http://www.house.gov/berman] (D-CA)
? Susan Davis [http://www.house.gov/susandavis] (D-CA)
? Bob Filner [http://www.house.gov/filner] (D-CA)
? Jane Harman [http://www.house.gov/harman] (D-CA)
? Adam B. Schiff [http://schiff.house.gov/] (D-CA)
? Brad Sherman [http://www.house.gov/sherman] (D-CA)
? Henry Waxman [http://www.house.gov/waxman] (D-CA)
? (Q) Jared Polis [http://polis.house.gov/] (D-CO)
? Alan Grayson [http://grayson.house.gov/] (D-FL)
? Ron Klein [http://klein.house.gov/] (D-FL)
? Debbie Wasserman-Schultz [http://wassermanschultz.house.gov/] (D-FL)
? Robert Wexler [http://wexler.house.gov/] (D-FL)
? *Rahm Emanuel (D-IL)
? Jan Schakowsky [http://www.house.gov/schakowsky] (D-IL)
? John Yarmuth [http://yarmuth.house.gov/] (D-KY)
? (Q) Barney Frank [http://www.house.gov/frank] (D-MA)
? Sander M. Levin [http://www.house.gov/levin] (D-MI)
? Shelley Berkley [http://berkley.house.gov/] (D-NV)
? Paul W. Hodes [http://hodes.house.gov/] (D-NH)
? John Adler [http://adler.house.gov/] (D-NJ)
? Steven R. Rothman [http://rothman.house.gov/] (D-NJ)
? Gary Ackerman [http://www.house.gov/ackerman] (D-NY)
? Eliot L. Engel [http://engel.house.gov/] (D-NY)
? Steve Israel [http://israel.house.gov/] (D-NY)
? Nita M. Lowey [http://lowey.house.gov/] (D-NY)
? Jerrold Nadler [http://www.house.gov/nadler] (D-NY)
? Anthony Weiner [http://weiner.house.gov/] (D-NY)
? Allyson Y. Schwartz [http://schwartz.house.gov/] (D-PA)
? Steve Cohen [http://cohen.house.gov/] (D-TN)
? Eric Cantor [http://cantor.house.gov/] (R-VA)
? Steve Kagen [http://kagen.house.gov/] (D-WI)

*Rahm Emanuel to leave Congress effective January 20th. Successor to be determined in the March 3rd special primary election [http://newsblogs.chicagotribune.com/clout_st/2009/01/race-officially.html].

Q = Openly gay. Documentation of Jared Polis? homosexuality HERE [http://www.denverpost.com/ci_7739308].

You?ll note that of all the Jews in Congress, only two are Republican. This reflects the larger national pattern of Jews voting Democratic. The preponderance is persistent and overwhelming; 78 percent [http://www.jewishvirtuallibrary.org/jsource/US-Israel/jewvote.html] of Jews voted for Obama in
2008. As a matter of fact, since the Jewish Presidential vote was first tracked in 1916, only once has a majority of Jews voted for a Republican, Warren Harding in 1920.



Source: http://www.davidduke.com/general/the-next-session-of-congress-will-include-44-jewish-lawmakers-a-new-record_7386.html



-------------------------------------
You or someone using your email adress is currently subscribed to the Lawrence Auster
Newletter. If you wish to unsubscribe from our mailing list, please let us know by calling "to 1 212 865 1284

Thanks,

Lawrence Auster,
238 W 101 St Apt. 3B
New York, NY  10025
Contact: lawrence.auster at att.net
-------------------------------------


From dcbw at redhat.com  Thu Jan 29 19:35:48 2009
From: dcbw at redhat.com (Dan Williams)
Date: Thu, 29 Jan 2009 19:35:48 -0500
Subject: Marvel 8686 in adhoc mode
In-Reply-To: <4981025F.1070802@bluewatersys.com>
References: <4981025F.1070802@bluewatersys.com>
Message-ID: <1233275748.4085.44.camel@localhost.localdomain>

On Thu, 2009-01-29 at 14:11 +1300, Ryan Mallon wrote:
> Can anybody tell me if the Libertas driver will support the Marvell
> 88W8686 chip in adhoc mode at 54Mbps. If so, which kernel version was
> this supported introduced at?

There's nothing I can find that says it *can't*, though I haven't tried
it personally.

The driver defaults are used when the driver starts up, which I assume
means adaptive ratesetting defaults are in-force, but that's up to the
firmware.

Setting the rate with iwconfig (SIOCSIWRATE) will set power rate
adaptation on firmware < v9 (nobody has gotten around to adding the v9+
command for that yet), then set TX rate adaptation using
CMD_802_11_ADAPT_RATESET, which controls the max TX rate.  That patch
has been in since 2.6.28 I think.

Dan




