All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support
@ 2012-02-09 20:08 Arend van Spriel
  2012-02-09 20:08 ` [PATCH 01/15] brcm80211: update the maintainers listed for brcm80211 drivers Arend van Spriel
                   ` (15 more replies)
  0 siblings, 16 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

This patch series contains patches for a couple of issue in brcmsmac. The A-MPDU
endless retry fix is a long standing issue that exists in previous kernels. So
it should go to 3.3 kernel.

For the brcmfmac driver support has been added for USB chipsets. Firmware has
been submitted for bcm43235, bcm43236, and bcm43238 chipsets.

Arend van Spriel (14):
  brcm80211: update the maintainers listed for brcm80211 drivers
  brcm80211: smac: fix unintended fallthru in wlc_phy_radio_init_2057()
  brcm80211: smac: remove redundant assignments from
    txpwrctrl_pwr_setup_nphy
  brcm80211: smac: fix endless retry of A-MPDU transmissions
  brcm80211: smac: remove smatch warnings from brcmsmac code
  brcm80211: fmac: resolve smatch issues in brcmfmac code
  brcm80211: fmac: use specific types in struct brcmf_bus
  brcm80211: fmac: move module entry points to dhd_linux.c
  brcm80211: fmac: only return success in brcmf_sdbrcm_bus_init() when
    true
  brcm80211: fmac: update bus state in common driver part
  brcm80211: fmac: change allocation flag in brcmf_enq_event() function
  brcm80211: fmac: use spinlock calls saving irq flags in
    brcmf_enq_event()
  brcm80211: fmac: add USB support for bcm43235/6/8 chipsets
  brcm80211: fmac: make sdio firmware filename specific

Franky Lin (1):
  brcm80211: fmac: make sure cancel_work_sync only called after
    INIT_WORK

 MAINTAINERS                                        |    1 -
 drivers/net/wireless/brcm80211/Kconfig             |   17 +-
 drivers/net/wireless/brcm80211/brcmfmac/Makefile   |    6 +-
 .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |   14 +-
 drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |   17 +-
 .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   59 +-
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   32 +-
 drivers/net/wireless/brcm80211/brcmfmac/usb.c      | 1623 ++++++++++++++++++++
 drivers/net/wireless/brcm80211/brcmfmac/usb.h      |   84 +
 drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h  |   75 +
 .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |   13 +-
 drivers/net/wireless/brcm80211/brcmsmac/ampdu.c    |    6 +-
 .../net/wireless/brcm80211/brcmsmac/mac80211_if.c  |    4 +-
 drivers/net/wireless/brcm80211/brcmsmac/main.c     |    1 -
 .../net/wireless/brcm80211/brcmsmac/phy/phy_n.c    |   28 +-
 drivers/net/wireless/brcm80211/brcmsmac/srom.c     |   14 +-
 16 files changed, 1905 insertions(+), 89 deletions(-)
 create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/usb.c
 create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/usb.h
 create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h

-- 
1.7.5.4



^ permalink raw reply	[flat|nested] 26+ messages in thread

* [PATCH 01/15] brcm80211: update the maintainers listed for brcm80211 drivers
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
@ 2012-02-09 20:08 ` Arend van Spriel
  2012-02-10  7:26   ` Rafał Miłecki
  2012-02-09 20:08 ` [PATCH 02/15] brcm80211: smac: fix unintended fallthru in wlc_phy_radio_init_2057() Arend van Spriel
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

Henry Ptasinski is not working on the brcm80211 driver so taking
his name/email out of the MAINTAINERS file.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 MAINTAINERS |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index ea653fd..50b85eba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1575,7 +1575,6 @@ F:	drivers/net/ethernet/broadcom/tg3.*
 
 BROADCOM BRCM80211 IEEE802.11n WIRELESS DRIVER
 M:	Brett Rudley <brudley@broadcom.com>
-M:	Henry Ptasinski <henryp@broadcom.com>
 M:	Roland Vossen <rvossen@broadcom.com>
 M:	Arend van Spriel <arend@broadcom.com>
 M:	Franky (Zhenhui) Lin <frankyl@broadcom.com>
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 02/15] brcm80211: smac: fix unintended fallthru in wlc_phy_radio_init_2057()
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
  2012-02-09 20:08 ` [PATCH 01/15] brcm80211: update the maintainers listed for brcm80211 drivers Arend van Spriel
@ 2012-02-09 20:08 ` Arend van Spriel
  2012-02-09 20:08 ` [PATCH 03/15] brcm80211: smac: remove redundant assignments from txpwrctrl_pwr_setup_nphy Arend van Spriel
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

The radio initialization for 2057 rev 5 was using the incorrect
register table for the initialization. This patch fixes that.

Reported-by: Larry Finger <Larry.Finger@lwfinger.net>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Alwin Beukers <alwin@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmsmac/phy/phy_n.c    |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
index ec7450d..c27ec7a 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
@@ -19989,12 +19989,11 @@ static void wlc_phy_radio_init_2057(struct brcms_phy *pi)
 		switch (pi->pubpi.radiorev) {
 		case 5:
 
-			if (pi->pubpi.radiover == 0x0)
+			if (NREV_IS(pi->pubpi.phy_rev, 8))
 				regs_2057_ptr = regs_2057_rev5;
-			else if (pi->pubpi.radiover == 0x1)
+			else if (NREV_IS(pi->pubpi.phy_rev, 9))
 				regs_2057_ptr = regs_2057_rev5v1;
-			else
-				break;
+			break;
 
 		case 7:
 
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 03/15] brcm80211: smac: remove redundant assignments from txpwrctrl_pwr_setup_nphy
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
  2012-02-09 20:08 ` [PATCH 01/15] brcm80211: update the maintainers listed for brcm80211 drivers Arend van Spriel
  2012-02-09 20:08 ` [PATCH 02/15] brcm80211: smac: fix unintended fallthru in wlc_phy_radio_init_2057() Arend van Spriel
@ 2012-02-09 20:08 ` Arend van Spriel
  2012-02-09 20:08 ` [PATCH 04/15] brcm80211: smac: fix endless retry of A-MPDU transmissions Arend van Spriel
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

The function wlc_phy_txpwrctrl_pwr_setup_nphy() does assign a local
variable target_pwr_qtrdbm in several code paths, but in the end all
code paths are coming to an assignment of that variable which does
override all previous. So those early and redundant assignments have
been removed.

Reported-by: Larry Finger <Larry.Finger@lwfinger.net>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Alwin Beukers <alwin@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmsmac/phy/phy_n.c    |   21 +-------------------
 1 files changed, 1 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
index c27ec7a..9595ecd 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c
@@ -17824,8 +17824,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
 	if (pi->sh->sromrev < 4) {
 		idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
 		idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
-		target_pwr_qtrdbm[0] = 13 * 4;
-		target_pwr_qtrdbm[1] = 13 * 4;
 		a1[0] = -424;
 		a1[1] = -424;
 		b0[0] = 5612;
@@ -17839,10 +17837,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
 		case WL_CHAN_FREQ_RANGE_2G:
 			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
 			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
-			target_pwr_qtrdbm[0] =
-				pi->nphy_pwrctrl_info[0].max_pwr_2g;
-			target_pwr_qtrdbm[1] =
-				pi->nphy_pwrctrl_info[1].max_pwr_2g;
 			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_a1;
 			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_2g_a1;
 			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_2g_b0;
@@ -17853,10 +17847,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
 		case WL_CHAN_FREQ_RANGE_5GL:
 			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
 			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
-			target_pwr_qtrdbm[0] =
-				pi->nphy_pwrctrl_info[0].max_pwr_5gl;
-			target_pwr_qtrdbm[1] =
-				pi->nphy_pwrctrl_info[1].max_pwr_5gl;
 			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1;
 			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1;
 			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0;
@@ -17867,10 +17857,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
 		case WL_CHAN_FREQ_RANGE_5GM:
 			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
 			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
-			target_pwr_qtrdbm[0] =
-				pi->nphy_pwrctrl_info[0].max_pwr_5gm;
-			target_pwr_qtrdbm[1] =
-				pi->nphy_pwrctrl_info[1].max_pwr_5gm;
 			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_a1;
 			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gm_a1;
 			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gm_b0;
@@ -17881,10 +17867,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
 		case WL_CHAN_FREQ_RANGE_5GH:
 			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_5g;
 			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_5g;
-			target_pwr_qtrdbm[0] =
-				pi->nphy_pwrctrl_info[0].max_pwr_5gh;
-			target_pwr_qtrdbm[1] =
-				pi->nphy_pwrctrl_info[1].max_pwr_5gh;
 			a1[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1;
 			a1[1] = pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1;
 			b0[0] = pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0;
@@ -17895,8 +17877,6 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
 		default:
 			idle_tssi[0] = pi->nphy_pwrctrl_info[0].idle_tssi_2g;
 			idle_tssi[1] = pi->nphy_pwrctrl_info[1].idle_tssi_2g;
-			target_pwr_qtrdbm[0] = 13 * 4;
-			target_pwr_qtrdbm[1] = 13 * 4;
 			a1[0] = -424;
 			a1[1] = -424;
 			b0[0] = 5612;
@@ -17907,6 +17887,7 @@ static void wlc_phy_txpwrctrl_pwr_setup_nphy(struct brcms_phy *pi)
 		}
 	}
 
+	/* use the provided transmit power */
 	target_pwr_qtrdbm[0] = (s8) pi->tx_power_max;
 	target_pwr_qtrdbm[1] = (s8) pi->tx_power_max;
 
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 04/15] brcm80211: smac: fix endless retry of A-MPDU transmissions
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (2 preceding siblings ...)
  2012-02-09 20:08 ` [PATCH 03/15] brcm80211: smac: remove redundant assignments from txpwrctrl_pwr_setup_nphy Arend van Spriel
@ 2012-02-09 20:08 ` Arend van Spriel
  2012-02-09 20:08 ` [PATCH 05/15] brcm80211: smac: remove smatch warnings from brcmsmac code Arend van Spriel
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel, Stanislaw Gruszka

The A-MPDU code checked against a retry limit, but it was using
the wrong variable to do so. This patch fixes this to assure
proper retry mechanism.

This problem had a side-effect causing the mac80211 flush callback
to remain waiting forever as well. That side effect has been fixed
by commit by Stanislaw Gruszka:

commit f96b08a7e6f69c0f0a576554df3df5b1b519c479
Date:   Tue Jan 17 12:38:50 2012 +0100

    brcmsmac: fix tx queue flush infinite loop

    Reference:
    https://bugzilla.kernel.org/show_bug.cgi?id=42576

Cc: Stanislaw Gruszka <sgruszka@redhat.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Alwin Beukers <alwin@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmsmac/ampdu.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
index d89dcb1..c1ce831 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/ampdu.c
@@ -1051,17 +1051,13 @@ brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 		}
 		/* either retransmit or send bar if ack not recd */
 		if (!ack_recd) {
-			struct ieee80211_tx_rate *txrate =
-			    tx_info->status.rates;
-			if (retry && (txrate[0].count < (int)retry_limit)) {
+			if (retry && (ini->txretry[index] < (int)retry_limit)) {
 				ini->txretry[index]++;
 				ini->tx_in_transit--;
 				/*
 				 * Use high prededence for retransmit to
 				 * give some punch
 				 */
-				/* brcms_c_txq_enq(wlc, scb, p,
-				 * BRCMS_PRIO_TO_PREC(tid)); */
 				brcms_c_txq_enq(wlc, scb, p,
 						BRCMS_PRIO_TO_HI_PREC(tid));
 			} else {
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 05/15] brcm80211: smac: remove smatch warnings from brcmsmac code
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (3 preceding siblings ...)
  2012-02-09 20:08 ` [PATCH 04/15] brcm80211: smac: fix endless retry of A-MPDU transmissions Arend van Spriel
@ 2012-02-09 20:08 ` Arend van Spriel
  2012-02-09 20:09 ` [PATCH 06/15] brcm80211: fmac: resolve smatch issues in brcmfmac code Arend van Spriel
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:08 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

The patch fixes following smatch warnings:

main.c +2902 brcms_b_read_objmem(11) info: ignoring unreachable code.
mac80211_if.c +1146 brcms_suspend(8) error: we previously assumed 'wl'
could be null (see line 1145)
srom.c +641 _initvars_srom_pci(16) error: potential null dereference
'entry'.  (kzalloc returns null)

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Alwin Beukers <alwin@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmsmac/mac80211_if.c  |    4 ++--
 drivers/net/wireless/brcm80211/brcmsmac/main.c     |    1 -
 drivers/net/wireless/brcm80211/brcmsmac/srom.c     |   14 ++++++++++++--
 3 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c842797..fec0f10 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -1136,8 +1136,8 @@ static int brcms_suspend(struct bcma_device *pdev)
 	hw = bcma_get_drvdata(pdev);
 	wl = hw->priv;
 	if (!wl) {
-		wiphy_err(wl->wiphy,
-			  "brcms_suspend: bcma_get_drvdata failed\n");
+		pr_err("%s: %s: no driver private struct!\n", KBUILD_MODNAME,
+		       __func__);
 		return -ENODEV;
 	}
 
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index fb712ca..86186fa 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -2901,7 +2901,6 @@ brcms_b_read_objmem(struct brcms_hardware *wlc_hw, uint offset, u32 sel)
 		objoff += 2;
 
 	return bcma_read16(core, objoff);
-;
 }
 
 static void
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
index 5637436..b96f4b9 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/srom.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
@@ -621,7 +621,7 @@ static inline void cpu_to_le16_buf(u16 *buf, uint nwords)
 /*
  * convert binary srom data into linked list of srom variable items.
  */
-static void
+static int
 _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
 {
 	struct brcms_srom_list_head *entry;
@@ -638,6 +638,9 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
 
 	/* first store the srom revision */
 	entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
 	entry->varid = BRCMS_SROM_REV;
 	entry->var_type = BRCMS_SROM_UNUMBER;
 	entry->uval = sromrev;
@@ -715,6 +718,8 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
 
 		entry = kzalloc(sizeof(struct brcms_srom_list_head) +
 				extra_space, GFP_KERNEL);
+		if (!entry)
+			return -ENOMEM;
 		entry->varid = id;
 		entry->var_type = type;
 		if (flags & SRFL_ETHADDR) {
@@ -754,6 +759,8 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
 			entry =
 			    kzalloc(sizeof(struct brcms_srom_list_head),
 				    GFP_KERNEL);
+			if (!entry)
+				return -ENOMEM;
 			entry->varid = srv->varid+p;
 			entry->var_type = BRCMS_SROM_UNUMBER;
 			entry->uval = val;
@@ -761,6 +768,7 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
 		}
 		pb += psz;
 	}
+	return 0;
 }
 
 /*
@@ -906,7 +914,9 @@ int srom_var_init(struct si_pub *sih)
 		INIT_LIST_HEAD(&sii->var_list);
 
 		/* parse SROM into name=value pairs. */
-		_initvars_srom_pci(sromrev, srom, &sii->var_list);
+		err = _initvars_srom_pci(sromrev, srom, &sii->var_list);
+		if (err)
+			srom_free_vars(sih);
 	}
 
 errout:
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 06/15] brcm80211: fmac: resolve smatch issues in brcmfmac code
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (4 preceding siblings ...)
  2012-02-09 20:08 ` [PATCH 05/15] brcm80211: smac: remove smatch warnings from brcmsmac code Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-09 20:09 ` [PATCH 07/15] brcm80211: fmac: make sure cancel_work_sync only called after INIT_WORK Arend van Spriel
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

This patch resolves the following smatch issues:

wl_cfg80211.c +1377 brcmf_cfg80211_connect(65) warn: min_t truncates
here '(sme->ssid_len)' (4294967295 vs 9223372036854775807)
dhd_sdio.c +1275 brcmf_sdbrcm_rxglom(156) warn: min_t truncates here
'(pfirst->len)' (2147483647 vs 4294967295)
dhd_sdio.c +1457 brcmf_sdbrcm_rxglom(338) warn: min_t truncates here
'(pfirst->len)' (2147483647 vs 4294967295)
bcmsdh_sdmmc.c +300 brcmf_sdioh_request_buffer(10) warn: variable
dereferenced before check 'pkt' (see line 295)

Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |    3 ++-
 .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |    2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index ac71ade..b698a76 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -294,13 +294,14 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
 			       struct sk_buff *pkt)
 {
 	int status;
-	uint pkt_len = pkt->len;
+	uint pkt_len;
 	bool fifo = (fix_inc == SDIOH_DATA_FIX);
 
 	brcmf_dbg(TRACE, "Enter\n");
 
 	if (pkt == NULL)
 		return -EINVAL;
+	pkt_len = pkt->len;
 
 	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
 	if (brcmf_pm_resume_error(sdiodev))
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 74c95a5..e95a883 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -1376,7 +1376,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev,
 	memset(&join_params, 0, sizeof(join_params));
 	join_params_size = sizeof(join_params.ssid_le);
 
-	ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), sme->ssid_len);
+	ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), (u32)sme->ssid_len);
 	memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len);
 	memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len);
 	join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len);
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 07/15] brcm80211: fmac: make sure cancel_work_sync only called after INIT_WORK
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (5 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 06/15] brcm80211: fmac: resolve smatch issues in brcmfmac code Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-09 20:09 ` [PATCH 08/15] brcm80211: fmac: use specific types in struct brcmf_bus Arend van Spriel
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Franky Lin, Arend van Spriel

From: Franky Lin <frankyl@broadcom.com>

INIT_WORK only gets called after brcmf_proto_attach returns
success. This dependency should be annotated in brcmf_detach to
avoid any error.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index db2df1f..eff0073 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -1109,13 +1109,13 @@ void brcmf_detach(struct device *dev)
 		if (drvr->iflist[i])
 			brcmf_del_if(drvr, i);
 
-	cancel_work_sync(&drvr->setmacaddr_work);
-	cancel_work_sync(&drvr->multicast_work);
-
 	brcmf_bus_detach(drvr);
 
-	if (drvr->prot)
+	if (drvr->prot) {
+		cancel_work_sync(&drvr->setmacaddr_work);
+		cancel_work_sync(&drvr->multicast_work);
 		brcmf_proto_detach(drvr);
+	}
 
 	bus_if->drvr = NULL;
 	kfree(drvr);
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 08/15] brcm80211: fmac: use specific types in struct brcmf_bus
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (6 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 07/15] brcm80211: fmac: make sure cancel_work_sync only called after INIT_WORK Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-09 20:09 ` [PATCH 09/15] brcm80211: fmac: move module entry points to dhd_linux.c Arend van Spriel
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

The fields bus_priv and drvr are defined as void pointer. It is
preferred to have specific types for compiler type checking. To
prepare for other bus types the bus_priv field is defined as a
union containing the sdio bus private structure reference.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |    4 ++--
 drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |    7 +++++--
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   10 +++++-----
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index b698a76..1d2b74d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -489,7 +489,7 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func,
 		sdiodev->func[0] = func->card->sdio_func[0];
 		sdiodev->func[1] = func;
 		sdiodev->bus_if = bus_if;
-		bus_if->bus_priv = sdiodev;
+		bus_if->bus_priv.sdio = sdiodev;
 		bus_if->type = SDIO_BUS;
 		bus_if->align = BRCMF_SDALIGN;
 		dev_set_drvdata(&func->card->dev, sdiodev);
@@ -530,7 +530,7 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func)
 
 	if (func->num == 2) {
 		bus_if = dev_get_drvdata(&func->dev);
-		sdiodev = bus_if->bus_priv;
+		sdiodev = bus_if->bus_priv.sdio;
 		brcmf_dbg(TRACE, "F2 found, calling brcmf_sdio_remove...\n");
 		brcmf_sdio_remove(sdiodev);
 		dev_set_drvdata(&func->card->dev, NULL);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index ad9be24..567a966 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -39,8 +39,11 @@ struct dngl_stats {
 /* interface structure between common and bus layer */
 struct brcmf_bus {
 	u8 type;		/* bus type */
-	void *bus_priv;		/* pointer to bus private structure */
-	void *drvr;		/* pointer to driver pub structure brcmf_pub */
+	union {
+		/* pointer to sdio private structure */
+		struct brcmf_sdio_dev *sdio;
+	} bus_priv;
+	struct brcmf_pub *drvr;	/* pointer to driver pub structure brcmf_pub */
 	enum brcmf_bus_state state;
 	uint maxctl;		/* Max size rxctl request from proto to bus */
 	bool drvr_up;		/* Status flag of driver up/down */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 6e4b5e8..b20029e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -2277,7 +2277,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev)
 	uint retries;
 	int err;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 	struct brcmf_sdio *bus = sdiodev->bus;
 
 	brcmf_dbg(TRACE, "Enter\n");
@@ -2627,7 +2627,7 @@ static int brcmf_sdbrcm_bus_txdata(struct device *dev, struct sk_buff *pkt)
 	int ret = -EBADE;
 	uint datalen, prec;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 	struct brcmf_sdio *bus = sdiodev->bus;
 
 	brcmf_dbg(TRACE, "Enter\n");
@@ -2869,7 +2869,7 @@ brcmf_sdbrcm_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
 	u8 doff = 0;
 	int ret = -1;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 	struct brcmf_sdio *bus = sdiodev->bus;
 
 	brcmf_dbg(TRACE, "Enter\n");
@@ -2978,7 +2978,7 @@ brcmf_sdbrcm_bus_rxctl(struct device *dev, unsigned char *msg, uint msglen)
 	uint rxlen = 0;
 	bool pending;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 	struct brcmf_sdio *bus = sdiodev->bus;
 
 	brcmf_dbg(TRACE, "Enter\n");
@@ -3389,7 +3389,7 @@ brcmf_sdbrcm_download_firmware(struct brcmf_sdio *bus)
 static int brcmf_sdbrcm_bus_init(struct device *dev)
 {
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
-	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv;
+	struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
 	struct brcmf_sdio *bus = sdiodev->bus;
 	unsigned long timeout;
 	uint retries = 0;
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 09/15] brcm80211: fmac: move module entry points to dhd_linux.c
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (7 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 08/15] brcm80211: fmac: use specific types in struct brcmf_bus Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-09 23:50   ` Julian Calaby
  2012-02-09 20:09 ` [PATCH 10/15] brcm80211: fmac: only return success in brcmf_sdbrcm_bus_init() when true Arend van Spriel
                   ` (6 subsequent siblings)
  15 siblings, 1 reply; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

The module_init/exit functions are moved to dhd_linux.c to prepare
for supporting multiple host interface types.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |    7 +----
 drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |    6 +++++
 .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   24 ++++++++++++++++++++
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
index 1d2b74d..83ca3cc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
@@ -597,14 +597,14 @@ static struct sdio_driver brcmf_sdmmc_driver = {
 #endif	/* CONFIG_PM_SLEEP */
 };
 
-static void __exit brcmf_sdio_exit(void)
+void brcmf_sdio_exit(void)
 {
 	brcmf_dbg(TRACE, "Enter\n");
 
 	sdio_unregister_driver(&brcmf_sdmmc_driver);
 }
 
-static int __init brcmf_sdio_init(void)
+int brcmf_sdio_init(void)
 {
 	int ret;
 
@@ -617,6 +617,3 @@ static int __init brcmf_sdio_init(void)
 
 	return ret;
 }
-
-module_init(brcmf_sdio_init);
-module_exit(brcmf_sdio_exit);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index 567a966..bc575b4 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -105,4 +105,10 @@ extern int brcmf_bus_start(struct device *dev);
 
 extern int brcmf_add_if(struct device *dev, int ifidx,
 			char *name, u8 *mac_addr);
+
+#ifdef CONFIG_BRCMFMAC_SDIO
+extern void brcmf_sdio_exit(void);
+extern int brcmf_sdio_init(void);
+#endif
+
 #endif				/* _BRCMF_BUS_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index eff0073..ff7fc0e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -1183,3 +1183,27 @@ exit:
 	return ret;
 }
 #endif				/* DEBUG */
+
+static int __init brcmfmac_init(void)
+{
+	int ret = 0;
+
+#ifdef CONFIG_BRCMFMAC_SDIO
+	ret = brcmf_sdio_init();
+	if (ret)
+		goto fail;
+#endif
+
+fail:
+	return ret;
+}
+
+static void __exit brcmfmac_exit(void)
+{
+#ifdef CONFIG_BRCMFMAC_SDIO
+	brcmf_sdio_exit();
+#endif
+}
+
+module_init(brcmfmac_init);
+module_exit(brcmfmac_exit);
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 10/15] brcm80211: fmac: only return success in brcmf_sdbrcm_bus_init() when true
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (8 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 09/15] brcm80211: fmac: move module entry points to dhd_linux.c Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-09 20:09 ` [PATCH 11/15] brcm80211: fmac: update bus state in common driver part Arend van Spriel
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

The function brcmf_sdbrcm_bus_init() always returned success except for
firmware download failure. However, also when enabling SDIO function 2
is failing the function should return failure. This patch fixes that.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index b20029e..47a192d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -3467,13 +3467,12 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
 
 		/* Set bus state according to enable result */
 		bus_if->state = BRCMF_BUS_DATA;
-	}
-
-	else {
+	} else {
 		/* Disable F2 again */
 		enable = SDIO_FUNC_ENABLE_1;
 		brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0,
 				       SDIO_CCCR_IOEx, enable, NULL);
+		ret = -ENODEV;
 	}
 
 	/* Restore previous clock setting */
@@ -3481,7 +3480,7 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
 			       SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
 
 	/* If we didn't come up, turn off backplane clock */
-	if (bus_if->state != BRCMF_BUS_DATA)
+	if (!ret)
 		brcmf_sdbrcm_clkctl(bus, CLK_NONE, false);
 
 exit:
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 11/15] brcm80211: fmac: update bus state in common driver part
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (9 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 10/15] brcm80211: fmac: only return success in brcmf_sdbrcm_bus_init() when true Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-09 20:09 ` [PATCH 12/15] brcm80211: fmac: change allocation flag in brcmf_enq_event() function Arend van Spriel
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

The bus state is updated in the sdio bus init function, but it is
better to do it when the brcmf_bus_start() function is completed
successfully. The brcmf_netdev_open() function will return -EAGAIN
until the state is updated instead of calling brcmf_bus_start() to
avoid reentering that function.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   19 ++++++++-----------
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |    3 ---
 2 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index ff7fc0e..68da756 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -796,18 +796,19 @@ static int brcmf_netdev_open(struct net_device *ndev)
 {
 	struct brcmf_if *ifp = netdev_priv(ndev);
 	struct brcmf_pub *drvr = ifp->drvr;
+	struct brcmf_bus *bus_if = drvr->bus_if;
 	u32 toe_ol;
 	s32 ret = 0;
 
 	brcmf_dbg(TRACE, "ifidx %d\n", ifp->idx);
 
 	if (ifp->idx == 0) {	/* do it only for primary eth0 */
-		/* try to bring up bus */
-		ret = brcmf_bus_start(drvr->dev);
-		if (ret != 0) {
-			brcmf_dbg(ERROR, "failed with code %d\n", ret);
-			return -1;
+		/* If bus is not ready, can't continue */
+		if (bus_if->state != BRCMF_BUS_DATA) {
+			brcmf_dbg(ERROR, "failed bus is not ready\n");
+			return -EAGAIN;
 		}
+
 		atomic_set(&drvr->pend_8021x_cnt, 0);
 
 		memcpy(ndev->dev_addr, drvr->mac, ETH_ALEN);
@@ -979,12 +980,6 @@ int brcmf_bus_start(struct device *dev)
 		return ret;
 	}
 
-	/* If bus is not ready, can't come up */
-	if (bus_if->state != BRCMF_BUS_DATA) {
-		brcmf_dbg(ERROR, "failed bus is not ready\n");
-		return -ENODEV;
-	}
-
 	brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
 		      iovbuf, sizeof(iovbuf));
 	brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf,
@@ -1021,6 +1016,8 @@ int brcmf_bus_start(struct device *dev)
 	if (ret < 0)
 		return ret;
 
+	/* signal bus ready */
+	bus_if->state = BRCMF_BUS_DATA;
 	return 0;
 }
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 47a192d..253fc20 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -3464,9 +3464,6 @@ static int brcmf_sdbrcm_bus_init(struct device *dev)
 
 		brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1,
 				       SBSDIO_WATERMARK, 8, &err);
-
-		/* Set bus state according to enable result */
-		bus_if->state = BRCMF_BUS_DATA;
 	} else {
 		/* Disable F2 again */
 		enable = SDIO_FUNC_ENABLE_1;
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 12/15] brcm80211: fmac: change allocation flag in brcmf_enq_event() function
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (10 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 11/15] brcm80211: fmac: update bus state in common driver part Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-09 20:09 ` [PATCH 13/15] brcm80211: fmac: use spinlock calls saving irq flags in brcmf_enq_event() Arend van Spriel
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

As the function is called from atomic context it should not do the
kzalloc call with GFP_KERNEL.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Kan Yan <kanyan@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index e95a883..285fa19 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -3297,7 +3297,9 @@ static struct brcmf_cfg80211_event_q *brcmf_deq_event(
 }
 
 /*
-** push event to tail of the queue
+*	push event to tail of the queue
+*
+*	remark: this function may not sleep as it is called in atomic context.
 */
 
 static s32
@@ -3307,7 +3309,7 @@ brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
 	struct brcmf_cfg80211_event_q *e;
 	s32 err = 0;
 
-	e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_KERNEL);
+	e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_ATOMIC);
 	if (!e)
 		return -ENOMEM;
 
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 13/15] brcm80211: fmac: use spinlock calls saving irq flags in brcmf_enq_event()
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (11 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 12/15] brcm80211: fmac: change allocation flag in brcmf_enq_event() function Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-09 20:09 ` [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets Arend van Spriel
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

This function is executed within irq context. The call spin_unlock_irq
does enable interrupts which is not desired in the irq context. This patch
replaces them using the spin_loc_irqsave and spin_unlock_irqrestore
functions.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Kan Yan <kanyan@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/wl_cfg80211.c  |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 285fa19..15d7f00 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -3308,6 +3308,7 @@ brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
 {
 	struct brcmf_cfg80211_event_q *e;
 	s32 err = 0;
+	ulong flags;
 
 	e = kzalloc(sizeof(struct brcmf_cfg80211_event_q), GFP_ATOMIC);
 	if (!e)
@@ -3316,9 +3317,9 @@ brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event,
 	e->etype = event;
 	memcpy(&e->emsg, msg, sizeof(struct brcmf_event_msg));
 
-	spin_lock_irq(&cfg_priv->evt_q_lock);
+	spin_lock_irqsave(&cfg_priv->evt_q_lock, flags);
 	list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list);
-	spin_unlock_irq(&cfg_priv->evt_q_lock);
+	spin_unlock_irqrestore(&cfg_priv->evt_q_lock, flags);
 
 	return err;
 }
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (12 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 13/15] brcm80211: fmac: use spinlock calls saving irq flags in brcmf_enq_event() Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-23 18:10   ` Rafał Miłecki
  2012-02-09 20:09 ` [PATCH 15/15] brcm80211: fmac: make sdio firmware filename specific Arend van Spriel
  2012-02-22 17:12 ` [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
  15 siblings, 1 reply; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel, M. Lambert

This patch extends the use of the brcmfmac driver with support for
chipsets with a USB host interface. The first chipsets supported are
the bcm43235, bcm43236, and bcm43238 for which firmware has been
submitted.

This driver change has been successfully built for x86, x86_64,
ppc64, arm_le, and mips_be.

It has been tested successfully on x86 and x86_64.

Cc: M. Lambert <lambertm@westman.wave.ca>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Kan Yan <kanyan@broadcom.com>
Reviewed-by: Alwin Beukers <alwin@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/Kconfig             |   17 +-
 drivers/net/wireless/brcm80211/brcmfmac/Makefile   |    6 +-
 drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |    6 +-
 .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |    8 +
 drivers/net/wireless/brcm80211/brcmfmac/usb.c      | 1623 ++++++++++++++++++++
 drivers/net/wireless/brcm80211/brcmfmac/usb.h      |   84 +
 drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h  |   75 +
 7 files changed, 1812 insertions(+), 7 deletions(-)
 create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/usb.c
 create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/usb.h
 create mode 100644 drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h

diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index cd6375d..c510453 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -26,16 +26,25 @@ config BRCMFMAC
 	  it'll be called brcmfmac.ko.
 
 config BRCMFMAC_SDIO
-	bool "SDIO bus interface support for FullMAC"
+	bool "SDIO bus interface support for FullMAC driver"
 	depends on MMC
 	depends on BRCMFMAC
 	select FW_LOADER
 	default y
 	---help---
 	  This option enables the SDIO bus interface support for Broadcom
-	  FullMAC WLAN driver.
-	  Say Y if you want to use brcmfmac for a compatible SDIO interface
-	  wireless card.
+	  IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
+	  use the driver for a SDIO wireless card.
+
+config BRCMFMAC_USB
+	bool "USB bus interface support for FullMAC driver"
+	depends on USB
+	depends on BRCMFMAC
+	select FW_LOADER
+	---help---
+	  This option enables the USB bus interface support for Broadcom
+	  IEEE802.11n embedded FullMAC WLAN driver. Say Y if you want to
+	  use the driver for an USB wireless card.
 
 config BRCMDBG
 	bool "Broadcom driver debug functions"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 9ca9ea1..abb4803 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -19,6 +19,8 @@ ccflags-y += \
 	-Idrivers/net/wireless/brcm80211/brcmfmac	\
 	-Idrivers/net/wireless/brcm80211/include
 
+ccflags-y += -D__CHECK_ENDIAN__
+
 obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
 brcmfmac-objs += \
 		wl_cfg80211.o \
@@ -30,5 +32,5 @@ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
 		bcmsdh.o \
 		bcmsdh_sdmmc.o \
 		sdio_chip.o
-
-ccflags-y += -D__CHECK_ENDIAN__
+brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
+		usb.o
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index bc575b4..b7671b3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -40,8 +40,8 @@ struct dngl_stats {
 struct brcmf_bus {
 	u8 type;		/* bus type */
 	union {
-		/* pointer to sdio private structure */
 		struct brcmf_sdio_dev *sdio;
+		struct brcmf_usbdev *usb;
 	} bus_priv;
 	struct brcmf_pub *drvr;	/* pointer to driver pub structure brcmf_pub */
 	enum brcmf_bus_state state;
@@ -110,5 +110,9 @@ extern int brcmf_add_if(struct device *dev, int ifidx,
 extern void brcmf_sdio_exit(void);
 extern int brcmf_sdio_init(void);
 #endif
+#ifdef CONFIG_BRCMFMAC_USB
+extern void brcmf_usb_exit(void);
+extern int brcmf_usb_init(void);
+#endif
 
 #endif				/* _BRCMF_BUS_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 68da756..c4da058 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -1190,6 +1190,11 @@ static int __init brcmfmac_init(void)
 	if (ret)
 		goto fail;
 #endif
+#ifdef CONFIG_BRCMFMAC_USB
+	ret = brcmf_usb_init();
+	if (ret)
+		goto fail;
+#endif
 
 fail:
 	return ret;
@@ -1200,6 +1205,9 @@ static void __exit brcmfmac_exit(void)
 #ifdef CONFIG_BRCMFMAC_SDIO
 	brcmf_sdio_exit();
 #endif
+#ifdef CONFIG_BRCMFMAC_USB
+	brcmf_usb_exit();
+#endif
 }
 
 module_init(brcmfmac_init);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
new file mode 100644
index 0000000..934ed78
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -0,0 +1,1623 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/kthread.h>
+#include <linux/slab.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/ethtool.h>
+#include <linux/fcntl.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/firmware.h>
+#include <linux/usb.h>
+#include <net/cfg80211.h>
+
+#include <defs.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <dhd_bus.h>
+#include <dhd_dbg.h>
+
+#include "usb_rdl.h"
+#include "usb.h"
+
+#define IOCTL_RESP_TIMEOUT  2000
+
+#define BRCMF_USB_SYNC_TIMEOUT		300	/* ms */
+#define BRCMF_USB_DLIMAGE_SPINWAIT	100	/* in unit of ms */
+#define BRCMF_USB_DLIMAGE_LIMIT		500	/* spinwait limit (ms) */
+
+#define BRCMF_POSTBOOT_ID		0xA123  /* ID to detect if dongle
+						   has boot up */
+#define BRCMF_USB_RESETCFG_SPINWAIT	1	/* wait after resetcfg (ms) */
+
+#define BRCMF_USB_NRXQ	50
+#define BRCMF_USB_NTXQ	50
+
+#define CONFIGDESC(usb)         (&((usb)->actconfig)->desc)
+#define IFPTR(usb, idx)         ((usb)->actconfig->interface[(idx)])
+#define IFALTS(usb, idx)        (IFPTR((usb), (idx))->altsetting[0])
+#define IFDESC(usb, idx)        IFALTS((usb), (idx)).desc
+#define IFEPDESC(usb, idx, ep)  (IFALTS((usb), (idx)).endpoint[(ep)]).desc
+
+#define CONTROL_IF              0
+#define BULK_IF                 0
+
+#define BRCMF_USB_CBCTL_WRITE	0
+#define BRCMF_USB_CBCTL_READ	1
+#define BRCMF_USB_MAX_PKT_SIZE	1600
+
+#define BRCMF_USB_FW_NAME	"brcm/brcmfmac-usb.bin"
+
+enum usbdev_suspend_state {
+	USBOS_SUSPEND_STATE_DEVICE_ACTIVE = 0, /* Device is busy, won't allow
+						  suspend */
+	USBOS_SUSPEND_STATE_SUSPEND_PENDING,	/* Device is idle, can be
+						 * suspended. Wating PM to
+						 * suspend the device
+						 */
+	USBOS_SUSPEND_STATE_SUSPENDED	/* Device suspended */
+};
+
+struct brcmf_usb_probe_info {
+	void *usbdev_info;
+	struct usb_device *usb; /* USB device pointer from OS */
+	uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
+	int intr_size; /* Size of interrupt message */
+	int interval;  /* Interrupt polling interval */
+	int vid;
+	int pid;
+	enum usb_device_speed device_speed;
+	enum usbdev_suspend_state suspend_state;
+	struct usb_interface *intf;
+};
+static struct brcmf_usb_probe_info usbdev_probe_info;
+
+struct brcmf_usb_image {
+	void *data;
+	u32 len;
+};
+static struct brcmf_usb_image g_image = { NULL, 0 };
+
+struct intr_transfer_buf {
+	u32 notification;
+	u32 reserved;
+};
+
+struct brcmf_usbdev_info {
+	struct brcmf_usbdev bus_pub; /* MUST BE FIRST */
+	spinlock_t qlock;
+	struct list_head rx_freeq;
+	struct list_head rx_postq;
+	struct list_head tx_freeq;
+	struct list_head tx_postq;
+	enum usbdev_suspend_state suspend_state;
+	uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
+
+	bool activity;
+	int rx_low_watermark;
+	int tx_low_watermark;
+	int tx_high_watermark;
+	bool txoff;
+	bool rxoff;
+	bool txoverride;
+
+	struct brcmf_usbreq *tx_reqs;
+	struct brcmf_usbreq *rx_reqs;
+
+	u8 *image;	/* buffer for combine fw and nvram */
+	int image_len;
+
+	wait_queue_head_t wait;
+	bool waitdone;
+	int sync_urb_status;
+
+	struct usb_device *usbdev;
+	struct device *dev;
+	enum usb_device_speed  device_speed;
+
+	int ctl_in_pipe, ctl_out_pipe;
+	struct urb *ctl_urb; /* URB for control endpoint */
+	struct usb_ctrlrequest ctl_write;
+	struct usb_ctrlrequest ctl_read;
+	u32 ctl_urb_actual_length;
+	int ctl_urb_status;
+	int ctl_completed;
+	wait_queue_head_t ioctl_resp_wait;
+	wait_queue_head_t ctrl_wait;
+	ulong ctl_op;
+
+	bool rxctl_deferrespok;
+
+	struct urb *bulk_urb; /* used for FW download */
+	struct urb *intr_urb; /* URB for interrupt endpoint */
+	int intr_size;          /* Size of interrupt message */
+	int interval;           /* Interrupt polling interval */
+	struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */
+
+	struct brcmf_usb_probe_info probe_info;
+
+};
+
+static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
+				struct brcmf_usbreq  *req);
+
+MODULE_AUTHOR("Broadcom Corporation");
+MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac usb driver.");
+MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac usb cards");
+MODULE_LICENSE("Dual BSD/GPL");
+
+static struct brcmf_usbdev *brcmf_usb_get_buspub(struct device *dev)
+{
+	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+	return bus_if->bus_priv.usb;
+}
+
+static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev)
+{
+	return brcmf_usb_get_buspub(dev)->devinfo;
+}
+
+#if 0
+static void
+brcmf_usb_txflowcontrol(struct brcmf_usbdev_info *devinfo, bool onoff)
+{
+	dhd_txflowcontrol(devinfo->bus_pub.netdev, 0, onoff);
+}
+#endif
+
+static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo,
+	 uint *condition, bool *pending)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	int timeout = IOCTL_RESP_TIMEOUT;
+
+	/* Convert timeout in millsecond to jiffies */
+	timeout = msecs_to_jiffies(timeout);
+	/* Wait until control frame is available */
+	add_wait_queue(&devinfo->ioctl_resp_wait, &wait);
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	smp_mb();
+	while (!(*condition) && (!signal_pending(current) && timeout)) {
+		timeout = schedule_timeout(timeout);
+		/* Wait until control frame is available */
+		smp_mb();
+	}
+
+	if (signal_pending(current))
+		*pending = true;
+
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&devinfo->ioctl_resp_wait, &wait);
+
+	return timeout;
+}
+
+static int brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo)
+{
+	if (waitqueue_active(&devinfo->ioctl_resp_wait))
+		wake_up_interruptible(&devinfo->ioctl_resp_wait);
+
+	return 0;
+}
+
+static void
+brcmf_usb_ctl_complete(struct brcmf_usbdev_info *devinfo, int type, int status)
+{
+
+	if (unlikely(devinfo == NULL))
+		return;
+
+	if (type == BRCMF_USB_CBCTL_READ) {
+		if (status == 0)
+			devinfo->bus_pub.stats.rx_ctlpkts++;
+		else
+			devinfo->bus_pub.stats.rx_ctlerrs++;
+	} else if (type == BRCMF_USB_CBCTL_WRITE) {
+		if (status == 0)
+			devinfo->bus_pub.stats.tx_ctlpkts++;
+		else
+			devinfo->bus_pub.stats.tx_ctlerrs++;
+	}
+
+	devinfo->ctl_urb_status = status;
+	devinfo->ctl_completed = true;
+	brcmf_usb_ioctl_resp_wake(devinfo);
+}
+
+static void
+brcmf_usb_ctlread_complete(struct urb *urb)
+{
+	struct brcmf_usbdev_info *devinfo =
+		(struct brcmf_usbdev_info *)urb->context;
+
+	devinfo->ctl_urb_actual_length = urb->actual_length;
+	brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_READ,
+		urb->status);
+}
+
+static void
+brcmf_usb_ctlwrite_complete(struct urb *urb)
+{
+	struct brcmf_usbdev_info *devinfo =
+		(struct brcmf_usbdev_info *)urb->context;
+
+	brcmf_usb_ctl_complete(devinfo, BRCMF_USB_CBCTL_WRITE,
+		urb->status);
+}
+
+static int brcmf_usb_pnp(struct brcmf_usbdev_info *devinfo, uint state)
+{
+	return 0;
+}
+
+static int
+brcmf_usb_send_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
+{
+	int ret;
+	u16 size;
+
+	if (devinfo == NULL || buf == NULL ||
+	    len == 0 || devinfo->ctl_urb == NULL)
+		return -EINVAL;
+
+	/* If the USB/HSIC bus in sleep state, wake it up */
+	if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED)
+		if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
+			brcmf_dbg(ERROR, "Could not Resume the bus!\n");
+			return -EIO;
+		}
+
+	devinfo->activity = true;
+	size = len;
+	devinfo->ctl_write.wLength = cpu_to_le16p(&size);
+	devinfo->ctl_urb->transfer_buffer_length = size;
+	devinfo->ctl_urb_status = 0;
+	devinfo->ctl_urb_actual_length = 0;
+
+	usb_fill_control_urb(devinfo->ctl_urb,
+		devinfo->usbdev,
+		devinfo->ctl_out_pipe,
+		(unsigned char *) &devinfo->ctl_write,
+		buf, size,
+		(usb_complete_t)brcmf_usb_ctlwrite_complete,
+		devinfo);
+
+	ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
+	if (ret < 0)
+		brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
+
+	return ret;
+}
+
+static int
+brcmf_usb_recv_ctl(struct brcmf_usbdev_info *devinfo, u8 *buf, int len)
+{
+	int ret;
+	u16 size;
+
+	if ((devinfo == NULL) || (buf == NULL) || (len == 0)
+		|| (devinfo->ctl_urb == NULL))
+		return -EINVAL;
+
+	size = len;
+	devinfo->ctl_read.wLength = cpu_to_le16p(&size);
+	devinfo->ctl_urb->transfer_buffer_length = size;
+
+	if (devinfo->rxctl_deferrespok) {
+		/* BMAC model */
+		devinfo->ctl_read.bRequestType = USB_DIR_IN
+			| USB_TYPE_VENDOR | USB_RECIP_INTERFACE;
+		devinfo->ctl_read.bRequest = DL_DEFER_RESP_OK;
+	} else {
+		/* full dongle model */
+		devinfo->ctl_read.bRequestType = USB_DIR_IN
+			| USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+		devinfo->ctl_read.bRequest = 1;
+	}
+
+	usb_fill_control_urb(devinfo->ctl_urb,
+		devinfo->usbdev,
+		devinfo->ctl_in_pipe,
+		(unsigned char *) &devinfo->ctl_read,
+		buf, size,
+		(usb_complete_t)brcmf_usb_ctlread_complete,
+		devinfo);
+
+	ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
+	if (ret < 0)
+		brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
+
+	return ret;
+}
+
+static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)
+{
+	int err = 0;
+	int timeout = 0;
+	bool pending;
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+
+	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
+		/* TODO: handle suspend/resume */
+		return -EIO;
+	}
+
+	if (test_and_set_bit(0, &devinfo->ctl_op))
+		return -EIO;
+
+	err = brcmf_usb_send_ctl(devinfo, buf, len);
+	if (err) {
+		brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
+		return err;
+	}
+
+	devinfo->ctl_completed = false;
+	timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed,
+					    &pending);
+	clear_bit(0, &devinfo->ctl_op);
+	if (!timeout) {
+		brcmf_dbg(ERROR, "Txctl wait timed out\n");
+		err = -EIO;
+	}
+	return err;
+}
+
+static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)
+{
+	int err = 0;
+	int timeout = 0;
+	bool pending;
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+
+	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
+		/* TODO: handle suspend/resume */
+		return -EIO;
+	}
+	if (test_and_set_bit(0, &devinfo->ctl_op))
+		return -EIO;
+
+	err = brcmf_usb_recv_ctl(devinfo, buf, len);
+	if (err) {
+		brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len);
+		return err;
+	}
+	devinfo->ctl_completed = false;
+	timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed,
+					    &pending);
+	err = devinfo->ctl_urb_status;
+	clear_bit(0, &devinfo->ctl_op);
+	if (!timeout) {
+		brcmf_dbg(ERROR, "rxctl wait timed out\n");
+		err = -EIO;
+	}
+	if (!err)
+		return devinfo->ctl_urb_actual_length;
+	else
+		return err;
+}
+
+static struct brcmf_usbreq *brcmf_usb_deq(struct brcmf_usbdev_info *devinfo,
+					  struct list_head *q)
+{
+	unsigned long flags;
+	struct brcmf_usbreq  *req;
+	spin_lock_irqsave(&devinfo->qlock, flags);
+	if (list_empty(q)) {
+		spin_unlock_irqrestore(&devinfo->qlock, flags);
+		return NULL;
+	}
+	req = list_entry(q->next, struct brcmf_usbreq, list);
+	list_del_init(q->next);
+	spin_unlock_irqrestore(&devinfo->qlock, flags);
+	return req;
+
+}
+
+static void brcmf_usb_enq(struct brcmf_usbdev_info *devinfo,
+			  struct list_head *q, struct brcmf_usbreq *req)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&devinfo->qlock, flags);
+	list_add_tail(&req->list, q);
+	spin_unlock_irqrestore(&devinfo->qlock, flags);
+}
+
+static struct brcmf_usbreq *
+brcmf_usbdev_qinit(struct list_head *q, int qsize)
+{
+	int i;
+	struct brcmf_usbreq *req, *reqs;
+
+	reqs = kzalloc(sizeof(struct brcmf_usbreq) * qsize, GFP_ATOMIC);
+	if (reqs == NULL) {
+		brcmf_dbg(ERROR, "fail to allocate memory!\n");
+		return NULL;
+	}
+	req = reqs;
+
+	for (i = 0; i < qsize; i++) {
+		req->urb = usb_alloc_urb(0, GFP_ATOMIC);
+		if (!req->urb)
+			goto fail;
+
+		INIT_LIST_HEAD(&req->list);
+		list_add_tail(&req->list, q);
+		req++;
+	}
+	return reqs;
+fail:
+	brcmf_dbg(ERROR, "fail!\n");
+	while (!list_empty(q)) {
+		req = list_entry(q->next, struct brcmf_usbreq, list);
+		if (req && req->urb)
+			usb_free_urb(req->urb);
+		list_del(q->next);
+	}
+	return NULL;
+
+}
+
+static void brcmf_usb_free_q(struct list_head *q, bool pending)
+{
+	struct brcmf_usbreq *req, *next;
+	int i = 0;
+	list_for_each_entry_safe(req, next, q, list) {
+		if (!req || !req->urb) {
+			brcmf_dbg(ERROR, "bad req\n");
+			break;
+		}
+		i++;
+		if (pending) {
+			usb_kill_urb(req->urb);
+		} else {
+			usb_free_urb(req->urb);
+			list_del_init(&req->list);
+		}
+	}
+}
+
+static void brcmf_usb_del_fromq(struct brcmf_usbdev_info *devinfo,
+				struct brcmf_usbreq *req)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&devinfo->qlock, flags);
+	list_del_init(&req->list);
+	spin_unlock_irqrestore(&devinfo->qlock, flags);
+}
+
+
+static void brcmf_usb_tx_complete(struct urb *urb)
+{
+	struct brcmf_usbreq *req = (struct brcmf_usbreq *)urb->context;
+	struct brcmf_usbdev_info *devinfo = req->devinfo;
+
+	brcmf_usb_del_fromq(devinfo, req);
+	if (urb->status == 0)
+		devinfo->bus_pub.stats.tx_packets++;
+	else
+		devinfo->bus_pub.stats.tx_errors++;
+
+	dev_kfree_skb(req->skb);
+	req->skb = NULL;
+	brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);
+
+}
+
+static void brcmf_usb_rx_complete(struct urb *urb)
+{
+	struct brcmf_usbreq  *req = (struct brcmf_usbreq *)urb->context;
+	struct brcmf_usbdev_info *devinfo = req->devinfo;
+	struct sk_buff *skb;
+	int ifidx = 0;
+
+	brcmf_usb_del_fromq(devinfo, req);
+	skb = req->skb;
+	req->skb = NULL;
+
+	if (urb->status == 0) {
+		devinfo->bus_pub.stats.rx_packets++;
+	} else {
+		devinfo->bus_pub.stats.rx_errors++;
+		dev_kfree_skb(skb);
+		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
+		return;
+	}
+
+	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP) {
+		skb_put(skb, urb->actual_length);
+		if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
+			brcmf_dbg(ERROR, "rx protocol error\n");
+			brcmu_pkt_buf_free_skb(skb);
+			devinfo->bus_pub.bus->dstats.rx_errors++;
+		} else {
+			brcmf_rx_packet(devinfo->dev, ifidx, skb);
+			brcmf_usb_rx_refill(devinfo, req);
+		}
+	} else {
+		dev_kfree_skb(skb);
+	}
+	return;
+
+}
+
+static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
+				struct brcmf_usbreq  *req)
+{
+	struct sk_buff *skb;
+	int ret;
+
+	if (!req || !devinfo)
+		return;
+
+	skb = dev_alloc_skb(devinfo->bus_pub.bus_mtu);
+	if (!skb) {
+		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
+		return;
+	}
+	req->skb = skb;
+
+	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,
+			  skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
+			  req);
+	req->urb->transfer_flags |= URB_ZERO_PACKET;
+	req->devinfo = devinfo;
+
+	ret = usb_submit_urb(req->urb, GFP_ATOMIC);
+	if (ret == 0) {
+		brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);
+	} else {
+		dev_kfree_skb(req->skb);
+		req->skb = NULL;
+		brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
+	}
+	return;
+}
+
+static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)
+{
+	struct brcmf_usbreq *req;
+
+	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
+		brcmf_dbg(ERROR, "bus is not up\n");
+		return;
+	}
+	while ((req = brcmf_usb_deq(devinfo, &devinfo->rx_freeq)) != NULL)
+		brcmf_usb_rx_refill(devinfo, req);
+}
+
+static void
+brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
+{
+	struct brcmf_bus *bcmf_bus = devinfo->bus_pub.bus;
+	int old_state;
+
+
+	if (devinfo->bus_pub.state == state)
+		return;
+
+	old_state = devinfo->bus_pub.state;
+	brcmf_dbg(TRACE, "dbus state change from %d to to %d\n",
+		  old_state, state);
+
+	/* Don't update state if it's PnP firmware re-download */
+	if (state != BCMFMAC_USB_STATE_PNP_FWDL) /* TODO */
+		devinfo->bus_pub.state = state;
+
+	if ((old_state  == BCMFMAC_USB_STATE_SLEEP)
+		&& (state == BCMFMAC_USB_STATE_UP)) {
+		brcmf_usb_rx_fill_all(devinfo);
+	}
+
+	/* update state of upper layer */
+	if (state == BCMFMAC_USB_STATE_DOWN) {
+		brcmf_dbg(INFO, "DBUS is down\n");
+		bcmf_bus->state = BRCMF_BUS_DOWN;
+	} else {
+		brcmf_dbg(INFO, "DBUS current state=%d\n", state);
+	}
+}
+
+static void
+brcmf_usb_intr_complete(struct urb *urb)
+{
+	struct brcmf_usbdev_info *devinfo =
+			(struct brcmf_usbdev_info *)urb->context;
+	bool killed;
+
+	if (devinfo == NULL)
+		return;
+
+	if (unlikely(urb->status)) {
+		if (devinfo->suspend_state ==
+			USBOS_SUSPEND_STATE_SUSPEND_PENDING)
+			killed = true;
+
+		if ((urb->status == -ENOENT && (!killed))
+			|| urb->status == -ESHUTDOWN ||
+			urb->status == -ENODEV) {
+			brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
+		}
+	}
+
+	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN) {
+		brcmf_dbg(ERROR, "intr cb when DBUS down, ignoring\n");
+		return;
+	}
+
+	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
+		usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
+}
+
+static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
+{
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+	struct brcmf_usbreq  *req;
+	int ret;
+
+	if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) {
+		/* TODO: handle suspend/resume */
+		return -EIO;
+	}
+
+	req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);
+	if (!req) {
+		brcmf_dbg(ERROR, "no req to send\n");
+		return -ENOMEM;
+	}
+	if (!req->urb) {
+		brcmf_dbg(ERROR, "no urb for req %p\n", req);
+		return -ENOBUFS;
+	}
+
+	req->skb = skb;
+	req->devinfo = devinfo;
+	usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
+			  skb->data, skb->len, brcmf_usb_tx_complete, req);
+	req->urb->transfer_flags |= URB_ZERO_PACKET;
+	ret = usb_submit_urb(req->urb, GFP_ATOMIC);
+	if (!ret) {
+		brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
+	} else {
+		req->skb = NULL;
+		brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);
+	}
+
+	return ret;
+}
+
+
+static int brcmf_usb_up(struct device *dev)
+{
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+	u16 ifnum;
+
+	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_UP)
+		return 0;
+
+	if (devinfo == NULL)
+		return -EINVAL;
+
+	/* If the USB/HSIC bus in sleep state, wake it up */
+	if (devinfo->suspend_state == USBOS_SUSPEND_STATE_SUSPENDED) {
+		if (brcmf_usb_pnp(devinfo, BCMFMAC_USB_PNP_RESUME) != 0) {
+			brcmf_dbg(ERROR, "Could not Resume the bus!\n");
+			return -EIO;
+		}
+	}
+	devinfo->activity = true;
+
+	/* Success, indicate devinfo is fully up */
+	brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_UP);
+
+	if (devinfo->intr_urb) {
+		int ret;
+
+		usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev,
+			devinfo->intr_pipe,
+			&devinfo->intr,
+			devinfo->intr_size,
+			(usb_complete_t)brcmf_usb_intr_complete,
+			devinfo,
+			devinfo->interval);
+
+		ret = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
+		if (ret) {
+			brcmf_dbg(ERROR, "USB_SUBMIT_URB failed with status %d\n",
+				  ret);
+			return -EINVAL;
+		}
+	}
+
+	if (devinfo->ctl_urb) {
+		devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0);
+		devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0);
+
+		ifnum = IFDESC(devinfo->usbdev, CONTROL_IF).bInterfaceNumber;
+
+		/* CTL Write */
+		devinfo->ctl_write.bRequestType =
+			USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+		devinfo->ctl_write.bRequest = 0;
+		devinfo->ctl_write.wValue = cpu_to_le16(0);
+		devinfo->ctl_write.wIndex = cpu_to_le16p(&ifnum);
+
+		/* CTL Read */
+		devinfo->ctl_read.bRequestType =
+			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+		devinfo->ctl_read.bRequest = 1;
+		devinfo->ctl_read.wValue = cpu_to_le16(0);
+		devinfo->ctl_read.wIndex = cpu_to_le16p(&ifnum);
+	}
+	brcmf_usb_rx_fill_all(devinfo);
+	return 0;
+}
+
+static void brcmf_usb_down(struct device *dev)
+{
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
+
+	if (devinfo == NULL)
+		return;
+
+	brcmf_dbg(TRACE, "enter\n");
+	if (devinfo->bus_pub.state == BCMFMAC_USB_STATE_DOWN)
+		return;
+
+	brcmf_usb_state_change(devinfo, BCMFMAC_USB_STATE_DOWN);
+	if (devinfo->intr_urb)
+		usb_kill_urb(devinfo->intr_urb);
+
+	if (devinfo->ctl_urb)
+		usb_kill_urb(devinfo->ctl_urb);
+
+	if (devinfo->bulk_urb)
+		usb_kill_urb(devinfo->bulk_urb);
+	brcmf_usb_free_q(&devinfo->tx_postq, true);
+
+	brcmf_usb_free_q(&devinfo->rx_postq, true);
+}
+
+static int
+brcmf_usb_sync_wait(struct brcmf_usbdev_info *devinfo, u16 time)
+{
+	int ret;
+	int err = 0;
+	int ms = time;
+
+	ret = wait_event_interruptible_timeout(devinfo->wait,
+		devinfo->waitdone == true, (ms * HZ / 1000));
+
+	if ((devinfo->waitdone == false) || (devinfo->sync_urb_status)) {
+		brcmf_dbg(ERROR, "timeout(%d) or urb err=%d\n",
+			  ret, devinfo->sync_urb_status);
+		err = -EINVAL;
+	}
+	devinfo->waitdone = false;
+	return err;
+}
+
+static void
+brcmf_usb_sync_complete(struct urb *urb)
+{
+	struct brcmf_usbdev_info *devinfo =
+			(struct brcmf_usbdev_info *)urb->context;
+
+	devinfo->waitdone = true;
+	wake_up_interruptible(&devinfo->wait);
+	devinfo->sync_urb_status = urb->status;
+}
+
+static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
+			     void *buffer, int buflen)
+{
+	int ret = 0;
+	char *tmpbuf;
+	u16 size;
+
+	if ((!devinfo) || (devinfo->ctl_urb == NULL))
+		return false;
+
+	tmpbuf = kmalloc(buflen, GFP_ATOMIC);
+	if (!tmpbuf)
+		return false;
+
+	size = buflen;
+	devinfo->ctl_urb->transfer_buffer_length = size;
+
+	devinfo->ctl_read.wLength = cpu_to_le16p(&size);
+	devinfo->ctl_read.bRequestType = USB_DIR_IN | USB_TYPE_VENDOR |
+		USB_RECIP_INTERFACE;
+	devinfo->ctl_read.bRequest = cmd;
+
+	usb_fill_control_urb(devinfo->ctl_urb,
+		devinfo->usbdev,
+		usb_rcvctrlpipe(devinfo->usbdev, 0),
+		(unsigned char *) &devinfo->ctl_read,
+		(void *) tmpbuf, size,
+		(usb_complete_t)brcmf_usb_sync_complete, devinfo);
+
+	ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
+	if (ret < 0) {
+		brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
+		kfree(tmpbuf);
+		return false;
+	}
+
+	ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
+	memcpy(buffer, tmpbuf, buflen);
+	kfree(tmpbuf);
+
+	return (ret == 0);
+}
+
+static bool
+brcmf_usb_dlneeded(struct brcmf_usbdev_info *devinfo)
+{
+	struct bootrom_id_le id;
+	u32 chipid, chiprev;
+
+	brcmf_dbg(TRACE, "enter\n");
+
+	if (devinfo == NULL)
+		return false;
+
+	/* Check if firmware downloaded already by querying runtime ID */
+	id.chip = cpu_to_le32(0xDEAD);
+	brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
+		sizeof(struct bootrom_id_le));
+
+	chipid = le32_to_cpu(id.chip);
+	chiprev = le32_to_cpu(id.chiprev);
+
+	if ((chipid & 0x4300) == 0x4300)
+		brcmf_dbg(INFO, "chip %x rev 0x%x\n", chipid, chiprev);
+	else
+		brcmf_dbg(INFO, "chip %d rev 0x%x\n", chipid, chiprev);
+	if (chipid == BRCMF_POSTBOOT_ID) {
+		brcmf_dbg(INFO, "firmware already downloaded\n");
+		brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
+			sizeof(struct bootrom_id_le));
+		return false;
+	} else {
+		devinfo->bus_pub.attrib.devid = chipid;
+		devinfo->bus_pub.attrib.chiprev = chiprev;
+	}
+	return true;
+}
+
+static int
+brcmf_usb_resetcfg(struct brcmf_usbdev_info *devinfo)
+{
+	struct bootrom_id_le id;
+	u16 wait = 0, wait_time;
+
+	brcmf_dbg(TRACE, "enter\n");
+
+	if (devinfo == NULL)
+		return -EINVAL;
+
+	/* Give dongle chance to boot */
+	wait_time = BRCMF_USB_DLIMAGE_SPINWAIT;
+	while (wait < BRCMF_USB_DLIMAGE_LIMIT) {
+		mdelay(wait_time);
+		wait += wait_time;
+		id.chip = cpu_to_le32(0xDEAD);       /* Get the ID */
+		brcmf_usb_dl_cmd(devinfo, DL_GETVER, &id,
+			sizeof(struct bootrom_id_le));
+		if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID))
+			break;
+	}
+
+	if (id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID)) {
+		brcmf_dbg(INFO, "download done %d ms postboot chip 0x%x/rev 0x%x\n",
+			  wait, le32_to_cpu(id.chip), le32_to_cpu(id.chiprev));
+
+		brcmf_usb_dl_cmd(devinfo, DL_RESETCFG, &id,
+			sizeof(struct bootrom_id_le));
+
+		/* XXX this wait may not be necessary */
+		mdelay(BRCMF_USB_RESETCFG_SPINWAIT);
+		return 0;
+	} else {
+		brcmf_dbg(ERROR, "Cannot talk to Dongle. Firmware is not UP, %d ms\n",
+			  wait);
+		return -EINVAL;
+	}
+}
+
+
+static int
+brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len)
+{
+	int ret;
+
+	if ((devinfo == NULL) || (devinfo->bulk_urb == NULL))
+		return -EINVAL;
+
+	/* Prepare the URB */
+	usb_fill_bulk_urb(devinfo->bulk_urb, devinfo->usbdev,
+			  devinfo->tx_pipe, buffer, len,
+			  (usb_complete_t)brcmf_usb_sync_complete, devinfo);
+
+	devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET;
+
+	ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC);
+	if (ret) {
+		brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
+		return ret;
+	}
+	ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
+	return ret;
+}
+
+static int
+brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen)
+{
+	unsigned int sendlen, sent, dllen;
+	char *bulkchunk = NULL, *dlpos;
+	struct rdl_state_le state;
+	u32 rdlstate, rdlbytes;
+	int err = 0;
+	brcmf_dbg(TRACE, "fw %p, len %d\n", fw, fwlen);
+
+	bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC);
+	if (bulkchunk == NULL) {
+		err = -ENOMEM;
+		goto fail;
+	}
+
+	/* 1) Prepare USB boot loader for runtime image */
+	brcmf_usb_dl_cmd(devinfo, DL_START, &state,
+			 sizeof(struct rdl_state_le));
+
+	rdlstate = le32_to_cpu(state.state);
+	rdlbytes = le32_to_cpu(state.bytes);
+
+	/* 2) Check we are in the Waiting state */
+	if (rdlstate != DL_WAITING) {
+		brcmf_dbg(ERROR, "Failed to DL_START\n");
+		err = -EINVAL;
+		goto fail;
+	}
+	sent = 0;
+	dlpos = fw;
+	dllen = fwlen;
+
+	/* Get chip id and rev */
+	while (rdlbytes != dllen) {
+		/* Wait until the usb device reports it received all
+		 * the bytes we sent */
+		if ((rdlbytes == sent) && (rdlbytes != dllen)) {
+			if ((dllen-sent) < RDL_CHUNK)
+				sendlen = dllen-sent;
+			else
+				sendlen = RDL_CHUNK;
+
+			/* simply avoid having to send a ZLP by ensuring we
+			 * never have an even
+			 * multiple of 64
+			 */
+			if (!(sendlen % 64))
+				sendlen -= 4;
+
+			/* send data */
+			memcpy(bulkchunk, dlpos, sendlen);
+			if (brcmf_usb_dl_send_bulk(devinfo, bulkchunk,
+						   sendlen)) {
+				brcmf_dbg(ERROR, "send_bulk failed\n");
+				err = -EINVAL;
+				goto fail;
+			}
+
+			dlpos += sendlen;
+			sent += sendlen;
+		}
+		if (!brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
+				      sizeof(struct rdl_state_le))) {
+			brcmf_dbg(ERROR, "DL_GETSTATE Failed xxxx\n");
+			err = -EINVAL;
+			goto fail;
+		}
+
+		rdlstate = le32_to_cpu(state.state);
+		rdlbytes = le32_to_cpu(state.bytes);
+
+		/* restart if an error is reported */
+		if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC) {
+			brcmf_dbg(ERROR, "Bad Hdr or Bad CRC state %d\n",
+				  rdlstate);
+			err = -EINVAL;
+			goto fail;
+		}
+	}
+
+fail:
+	kfree(bulkchunk);
+	brcmf_dbg(TRACE, "err=%d\n", err);
+	return err;
+}
+
+static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)
+{
+	int err;
+
+	brcmf_dbg(TRACE, "enter\n");
+
+	if (devinfo == NULL)
+		return -EINVAL;
+
+	if (devinfo->bus_pub.attrib.devid == 0xDEAD)
+		return -EINVAL;
+
+	err = brcmf_usb_dl_writeimage(devinfo, fw, len);
+	if (err == 0)
+		devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_DONE;
+	else
+		devinfo->bus_pub.state = BCMFMAC_USB_STATE_DL_PENDING;
+	brcmf_dbg(TRACE, "exit: err=%d\n", err);
+
+	return err;
+}
+
+static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
+{
+	struct rdl_state_le state;
+
+	brcmf_dbg(TRACE, "enter\n");
+	if (!devinfo)
+		return -EINVAL;
+
+	if (devinfo->bus_pub.attrib.devid == 0xDEAD)
+		return -EINVAL;
+
+	/* Check we are runnable */
+	brcmf_usb_dl_cmd(devinfo, DL_GETSTATE, &state,
+		sizeof(struct rdl_state_le));
+
+	/* Start the image */
+	if (state.state == cpu_to_le32(DL_RUNNABLE)) {
+		if (!brcmf_usb_dl_cmd(devinfo, DL_GO, &state,
+			sizeof(struct rdl_state_le)))
+			return -ENODEV;
+		if (brcmf_usb_resetcfg(devinfo))
+			return -ENODEV;
+		/* The Dongle may go for re-enumeration. */
+	} else {
+		brcmf_dbg(ERROR, "Dongle not runnable\n");
+		return -EINVAL;
+	}
+	brcmf_dbg(TRACE, "exit\n");
+	return 0;
+}
+
+static bool brcmf_usb_chip_support(int chipid, int chiprev)
+{
+	switch(chipid) {
+	case 43235:
+	case 43236:
+	case 43238:
+		return (chiprev == 3);
+	default:
+		break;
+	}
+	return false;
+}
+
+static int
+brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
+{
+	struct brcmf_usb_attrib *attr;
+	int err;
+
+	brcmf_dbg(TRACE, "enter\n");
+	if (devinfo == NULL)
+		return -ENODEV;
+
+	attr = &devinfo->bus_pub.attrib;
+
+	if (!brcmf_usb_chip_support(attr->devid, attr->chiprev)) {
+		brcmf_dbg(ERROR, "unsupported chip %d rev %d\n",
+			  attr->devid, attr->chiprev);
+		return -EINVAL;
+	}
+
+	if (!devinfo->image) {
+		brcmf_dbg(ERROR, "No firmware!\n");
+		return -ENOENT;
+	}
+
+	err = brcmf_usb_dlstart(devinfo,
+		devinfo->image, devinfo->image_len);
+	if (err == 0)
+		err = brcmf_usb_dlrun(devinfo);
+	return err;
+}
+
+
+static void brcmf_usb_detach(const struct brcmf_usbdev *bus_pub)
+{
+	struct brcmf_usbdev_info *devinfo =
+		(struct brcmf_usbdev_info *)bus_pub;
+
+	brcmf_dbg(TRACE, "devinfo %p\n", devinfo);
+
+	/* store the image globally */
+	g_image.data = devinfo->image;
+	g_image.len = devinfo->image_len;
+
+	/* free the URBS */
+	brcmf_usb_free_q(&devinfo->rx_freeq, false);
+	brcmf_usb_free_q(&devinfo->tx_freeq, false);
+
+	usb_free_urb(devinfo->intr_urb);
+	usb_free_urb(devinfo->ctl_urb);
+	usb_free_urb(devinfo->bulk_urb);
+
+	kfree(devinfo->tx_reqs);
+	kfree(devinfo->rx_reqs);
+	kfree(devinfo);
+}
+
+#define TRX_MAGIC       0x30524448      /* "HDR0" */
+#define TRX_VERSION     1               /* Version 1 */
+#define TRX_MAX_LEN     0x3B0000        /* Max length */
+#define TRX_NO_HEADER   1               /* Do not write TRX header */
+#define TRX_MAX_OFFSET  3               /* Max number of individual files */
+#define TRX_UNCOMP_IMAGE        0x20    /* Trx contains uncompressed image */
+
+struct trx_header_le {
+	__le32 magic;		/* "HDR0" */
+	__le32 len;		/* Length of file including header */
+	__le32 crc32;		/* CRC from flag_version to end of file */
+	__le32 flag_version;	/* 0:15 flags, 16:31 version */
+	__le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of
+					 * header */
+};
+
+static int check_file(const u8 *headers)
+{
+	struct trx_header_le *trx;
+	int actual_len = -1;
+
+	/* Extract trx header */
+	trx = (struct trx_header_le *) headers;
+	if (trx->magic != cpu_to_le32(TRX_MAGIC))
+		return -1;
+
+	headers += sizeof(struct trx_header_le);
+
+	if (le32_to_cpu(trx->flag_version) & TRX_UNCOMP_IMAGE) {
+		actual_len = le32_to_cpu(trx->offsets[TRX_OFFSETS_DLFWLEN_IDX]);
+		return actual_len + sizeof(struct trx_header_le);
+	}
+	return -1;
+}
+
+static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
+{
+	s8 *fwname;
+	const struct firmware *fw;
+	int err;
+
+	devinfo->image = g_image.data;
+	devinfo->image_len = g_image.len;
+
+	/*
+	 * if we have an image we can leave here.
+	 */
+	if (devinfo->image)
+		return 0;
+
+	fwname = BRCMF_USB_FW_NAME;
+
+	err = request_firmware(&fw, fwname, devinfo->dev);
+	if (!fw) {
+		brcmf_dbg(ERROR, "fail to request firmware %s\n", fwname);
+		return err;
+	}
+	if (check_file(fw->data) < 0) {
+		brcmf_dbg(ERROR, "invalid firmware %s\n", fwname);
+		return -EINVAL;
+	}
+
+	devinfo->image = kmalloc(fw->size, GFP_ATOMIC); /* plus nvram */
+	if (!devinfo->image)
+		return -ENOMEM;
+
+	memcpy(devinfo->image, fw->data, fw->size);
+	devinfo->image_len = fw->size;
+
+	release_firmware(fw);
+	return 0;
+}
+
+
+static
+struct brcmf_usbdev *brcmf_usb_attach(int nrxq, int ntxq, struct device *dev)
+{
+	struct brcmf_usbdev_info *devinfo;
+
+	devinfo = kzalloc(sizeof(struct brcmf_usbdev_info), GFP_ATOMIC);
+	if (devinfo == NULL)
+		return NULL;
+
+	devinfo->bus_pub.nrxq = nrxq;
+	devinfo->rx_low_watermark = nrxq / 2;
+	devinfo->bus_pub.devinfo = devinfo;
+	devinfo->bus_pub.ntxq = ntxq;
+
+	/* flow control when too many tx urbs posted */
+	devinfo->tx_low_watermark = ntxq / 4;
+	devinfo->tx_high_watermark = devinfo->tx_low_watermark * 3;
+	devinfo->dev = dev;
+	devinfo->usbdev = usbdev_probe_info.usb;
+	devinfo->tx_pipe = usbdev_probe_info.tx_pipe;
+	devinfo->rx_pipe = usbdev_probe_info.rx_pipe;
+	devinfo->rx_pipe2 = usbdev_probe_info.rx_pipe2;
+	devinfo->intr_pipe = usbdev_probe_info.intr_pipe;
+
+	devinfo->interval = usbdev_probe_info.interval;
+	devinfo->intr_size = usbdev_probe_info.intr_size;
+
+	memcpy(&devinfo->probe_info, &usbdev_probe_info,
+		sizeof(struct brcmf_usb_probe_info));
+	devinfo->bus_pub.bus_mtu = BRCMF_USB_MAX_PKT_SIZE;
+
+	/* Initialize other structure content */
+	init_waitqueue_head(&devinfo->ioctl_resp_wait);
+
+	/* Initialize the spinlocks */
+	spin_lock_init(&devinfo->qlock);
+
+	INIT_LIST_HEAD(&devinfo->rx_freeq);
+	INIT_LIST_HEAD(&devinfo->rx_postq);
+
+	INIT_LIST_HEAD(&devinfo->tx_freeq);
+	INIT_LIST_HEAD(&devinfo->tx_postq);
+
+	devinfo->rx_reqs = brcmf_usbdev_qinit(&devinfo->rx_freeq, nrxq);
+	if (!devinfo->rx_reqs)
+		goto error;
+
+	devinfo->tx_reqs = brcmf_usbdev_qinit(&devinfo->tx_freeq, ntxq);
+	if (!devinfo->tx_reqs)
+		goto error;
+
+	devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!devinfo->intr_urb) {
+		brcmf_dbg(ERROR, "usb_alloc_urb (intr) failed\n");
+		goto error;
+	}
+	devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!devinfo->ctl_urb) {
+		brcmf_dbg(ERROR, "usb_alloc_urb (ctl) failed\n");
+		goto error;
+	}
+	devinfo->rxctl_deferrespok = 0;
+
+	devinfo->bulk_urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!devinfo->bulk_urb) {
+		brcmf_dbg(ERROR, "usb_alloc_urb (bulk) failed\n");
+		goto error;
+	}
+
+	init_waitqueue_head(&devinfo->wait);
+	if (!brcmf_usb_dlneeded(devinfo))
+		return &devinfo->bus_pub;
+
+	brcmf_dbg(TRACE, "start fw downloading\n");
+	if (brcmf_usb_get_fw(devinfo))
+		goto error;
+
+	if (brcmf_usb_fw_download(devinfo))
+		goto error;
+
+	return &devinfo->bus_pub;
+
+error:
+	brcmf_dbg(ERROR, "failed!\n");
+	brcmf_usb_detach(&devinfo->bus_pub);
+	return NULL;
+}
+
+static int brcmf_usb_probe_cb(struct device *dev, const char *desc,
+				u32 bustype, u32 hdrlen)
+{
+	struct brcmf_bus *bus = NULL;
+	struct brcmf_usbdev *bus_pub = NULL;
+	int ret;
+
+
+	bus_pub = brcmf_usb_attach(BRCMF_USB_NRXQ, BRCMF_USB_NTXQ, dev);
+	if (!bus_pub) {
+		ret = -ENODEV;
+		goto fail;
+	}
+
+	bus = kzalloc(sizeof(struct brcmf_bus), GFP_ATOMIC);
+	if (!bus) {
+		ret = -ENOMEM;
+		goto fail;
+	}
+
+	bus_pub->bus = bus;
+	bus->brcmf_bus_txdata = brcmf_usb_tx;
+	bus->brcmf_bus_init = brcmf_usb_up;
+	bus->brcmf_bus_stop = brcmf_usb_down;
+	bus->brcmf_bus_txctl = brcmf_usb_tx_ctlpkt;
+	bus->brcmf_bus_rxctl = brcmf_usb_rx_ctlpkt;
+	bus->type = bustype;
+	bus->bus_priv.usb = bus_pub;
+	dev_set_drvdata(dev, bus);
+
+	/* Attach to the common driver interface */
+	ret = brcmf_attach(hdrlen, dev);
+	if (ret) {
+		brcmf_dbg(ERROR, "dhd_attach failed\n");
+		goto fail;
+	}
+
+	ret = brcmf_bus_start(dev);
+	if (ret == -ENOLINK) {
+		brcmf_dbg(ERROR, "dongle is not responding\n");
+		brcmf_detach(dev);
+		goto fail;
+	}
+
+	/* add interface and open for business */
+	ret = brcmf_add_if(dev, 0, "wlan%d", NULL);
+	if (ret) {
+		brcmf_dbg(ERROR, "Add primary net device interface failed!!\n");
+		brcmf_detach(dev);
+		goto fail;
+	}
+
+	return 0;
+fail:
+	/* Release resources in reverse order */
+	if (bus_pub)
+		brcmf_usb_detach(bus_pub);
+	kfree(bus);
+	return ret;
+}
+
+static void
+brcmf_usb_disconnect_cb(struct brcmf_usbdev *bus_pub)
+{
+	if (!bus_pub)
+		return;
+	brcmf_dbg(TRACE, "enter: bus_pub %p\n", bus_pub);
+
+	brcmf_detach(bus_pub->devinfo->dev);
+	kfree(bus_pub->bus);
+	brcmf_usb_detach(bus_pub);
+
+}
+
+static int
+brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	int ep;
+	struct usb_endpoint_descriptor *endpoint;
+	int ret = 0;
+	struct usb_device *usb = interface_to_usbdev(intf);
+	int num_of_eps;
+	u8 endpoint_num;
+
+	brcmf_dbg(TRACE, "enter\n");
+
+	usbdev_probe_info.usb = usb;
+	usbdev_probe_info.intf = intf;
+
+	if (id != NULL) {
+		usbdev_probe_info.vid = id->idVendor;
+		usbdev_probe_info.pid = id->idProduct;
+	}
+
+	usb_set_intfdata(intf, &usbdev_probe_info);
+
+	/* Check that the device supports only one configuration */
+	if (usb->descriptor.bNumConfigurations != 1) {
+		ret = -1;
+		goto fail;
+	}
+
+	if (usb->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) {
+		ret = -1;
+		goto fail;
+	}
+
+	/*
+	 * Only the BDC interface configuration is supported:
+	 *	Device class: USB_CLASS_VENDOR_SPEC
+	 *	if0 class: USB_CLASS_VENDOR_SPEC
+	 *	if0/ep0: control
+	 *	if0/ep1: bulk in
+	 *	if0/ep2: bulk out (ok if swapped with bulk in)
+	 */
+	if (CONFIGDESC(usb)->bNumInterfaces != 1) {
+		ret = -1;
+		goto fail;
+	}
+
+	/* Check interface */
+	if (IFDESC(usb, CONTROL_IF).bInterfaceClass != USB_CLASS_VENDOR_SPEC ||
+	    IFDESC(usb, CONTROL_IF).bInterfaceSubClass != 2 ||
+	    IFDESC(usb, CONTROL_IF).bInterfaceProtocol != 0xff) {
+		brcmf_dbg(ERROR, "invalid control interface: class %d, subclass %d, proto %d\n",
+			  IFDESC(usb, CONTROL_IF).bInterfaceClass,
+			  IFDESC(usb, CONTROL_IF).bInterfaceSubClass,
+			  IFDESC(usb, CONTROL_IF).bInterfaceProtocol);
+		ret = -1;
+		goto fail;
+	}
+
+	/* Check control endpoint */
+	endpoint = &IFEPDESC(usb, CONTROL_IF, 0);
+	if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+		!= USB_ENDPOINT_XFER_INT) {
+		brcmf_dbg(ERROR, "invalid control endpoint %d\n",
+			  endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK);
+		ret = -1;
+		goto fail;
+	}
+
+	endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	usbdev_probe_info.intr_pipe = usb_rcvintpipe(usb, endpoint_num);
+
+	usbdev_probe_info.rx_pipe = 0;
+	usbdev_probe_info.rx_pipe2 = 0;
+	usbdev_probe_info.tx_pipe = 0;
+	num_of_eps = IFDESC(usb, BULK_IF).bNumEndpoints - 1;
+
+	/* Check data endpoints and get pipes */
+	for (ep = 1; ep <= num_of_eps; ep++) {
+		endpoint = &IFEPDESC(usb, BULK_IF, ep);
+		if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+		    USB_ENDPOINT_XFER_BULK) {
+			brcmf_dbg(ERROR, "invalid data endpoint %d\n", ep);
+			ret = -1;
+			goto fail;
+		}
+
+		endpoint_num = endpoint->bEndpointAddress &
+			       USB_ENDPOINT_NUMBER_MASK;
+		if ((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
+			== USB_DIR_IN) {
+			if (!usbdev_probe_info.rx_pipe) {
+				usbdev_probe_info.rx_pipe =
+					usb_rcvbulkpipe(usb, endpoint_num);
+			} else {
+				usbdev_probe_info.rx_pipe2 =
+					usb_rcvbulkpipe(usb, endpoint_num);
+			}
+		} else {
+			usbdev_probe_info.tx_pipe =
+					usb_sndbulkpipe(usb, endpoint_num);
+		}
+	}
+
+	/* Allocate interrupt URB and data buffer */
+	/* RNDIS says 8-byte intr, our old drivers used 4-byte */
+	if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16))
+		usbdev_probe_info.intr_size = 8;
+	else
+		usbdev_probe_info.intr_size = 4;
+
+	usbdev_probe_info.interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
+
+	usbdev_probe_info.device_speed = usb->speed;
+	if (usb->speed == USB_SPEED_HIGH)
+		brcmf_dbg(INFO, "Broadcom high speed USB wireless device detected\n");
+	else
+		brcmf_dbg(INFO, "Broadcom full speed USB wireless device detected\n");
+
+	ret = brcmf_usb_probe_cb(&usb->dev, "", USB_BUS, 0);
+	if (ret)
+		goto fail;
+
+	/* Success */
+	return 0;
+
+fail:
+	brcmf_dbg(ERROR, "failed with errno %d\n", ret);
+	usb_set_intfdata(intf, NULL);
+	return ret;
+
+}
+
+static void
+brcmf_usb_disconnect(struct usb_interface *intf)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+
+	brcmf_dbg(TRACE, "enter\n");
+	brcmf_usb_disconnect_cb(brcmf_usb_get_buspub(&usb->dev));
+	usb_set_intfdata(intf, NULL);
+}
+
+/*
+ *	only need to signal the bus being down and update the suspend state.
+ */
+static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
+
+	brcmf_dbg(TRACE, "enter\n");
+	devinfo->bus_pub.state = BCMFMAC_USB_STATE_DOWN;
+	devinfo->suspend_state = USBOS_SUSPEND_STATE_SUSPENDED;
+	return 0;
+}
+
+/*
+ *	mark suspend state active and crank up the bus.
+ */
+static int brcmf_usb_resume(struct usb_interface *intf)
+{
+	struct usb_device *usb = interface_to_usbdev(intf);
+	struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
+
+	brcmf_dbg(TRACE, "enter\n");
+	devinfo->suspend_state = USBOS_SUSPEND_STATE_DEVICE_ACTIVE;
+	brcmf_bus_start(&usb->dev);
+	return 0;
+}
+
+#define BRCMF_USB_VENDOR_ID_BROADCOM	0x0a5c
+#define BRCMF_USB_DEVICE_ID_43236	0xbd17
+#define BRCMF_USB_DEVICE_ID_BCMFW	0x0bdc
+
+static struct usb_device_id brcmf_usb_devid_table[] = {
+	{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) },
+	/* special entry for device with firmware loaded and running */
+	{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);
+MODULE_FIRMWARE(BRCMF_USB_FW_NAME);
+
+/* TODO: suspend and resume entries */
+static struct usb_driver brcmf_usbdrvr = {
+	.name = KBUILD_MODNAME,
+	.probe = brcmf_usb_probe,
+	.disconnect = brcmf_usb_disconnect,
+	.id_table = brcmf_usb_devid_table,
+	.suspend = brcmf_usb_suspend,
+	.resume = brcmf_usb_resume,
+	.supports_autosuspend = 1
+};
+
+void brcmf_usb_exit(void)
+{
+	usb_deregister(&brcmf_usbdrvr);
+	kfree(g_image.data);
+	g_image.data = NULL;
+	g_image.len = 0;
+}
+
+int brcmf_usb_init(void)
+{
+	return usb_register(&brcmf_usbdrvr);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.h b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
new file mode 100644
index 0000000..b31da7b
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifndef BRCMFMAC_USB_H
+#define BRCMFMAC_USB_H
+
+enum brcmf_usb_state {
+	BCMFMAC_USB_STATE_DL_PENDING,
+	BCMFMAC_USB_STATE_DL_DONE,
+	BCMFMAC_USB_STATE_UP,
+	BCMFMAC_USB_STATE_DOWN,
+	BCMFMAC_USB_STATE_PNP_FWDL,
+	BCMFMAC_USB_STATE_DISCONNECT,
+	BCMFMAC_USB_STATE_SLEEP
+};
+
+enum brcmf_usb_pnp_state {
+	BCMFMAC_USB_PNP_DISCONNECT,
+	BCMFMAC_USB_PNP_SLEEP,
+	BCMFMAC_USB_PNP_RESUME,
+};
+
+struct brcmf_stats {
+	u32 tx_errors;
+	u32 tx_packets;
+	u32 tx_multicast;
+	u32 tx_ctlpkts;
+	u32 tx_ctlerrs;
+	u32 tx_dropped;
+	u32 tx_flushed;
+	u32 rx_errors;
+	u32 rx_packets;
+	u32 rx_multicast;
+	u32 rx_ctlpkts;
+	u32 rx_ctlerrs;
+	u32 rx_dropped;
+	u32 rx_flushed;
+
+};
+
+struct brcmf_usb_attrib {
+	int bustype;
+	int vid;
+	int pid;
+	int devid;
+	int chiprev; /* chip revsion number */
+	int mtu;
+	int nchan; /* Data Channels */
+	int has_2nd_bulk_in_ep;
+};
+
+struct brcmf_usbdev_info;
+
+struct brcmf_usbdev {
+	struct brcmf_bus *bus;
+	struct brcmf_usbdev_info *devinfo;
+	enum brcmf_usb_state state;
+	struct brcmf_stats stats;
+	int ntxq, nrxq, rxsize;
+	u32 bus_mtu;
+	struct brcmf_usb_attrib attrib;
+};
+
+/* IO Request Block (IRB) */
+struct brcmf_usbreq {
+	struct list_head list;
+	struct brcmf_usbdev_info *devinfo;
+	struct urb *urb;
+	struct sk_buff  *skb;
+};
+
+#endif /* BRCMFMAC_USB_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
new file mode 100644
index 0000000..0a35c51
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _USB_RDL_H
+#define _USB_RDL_H
+
+/* Control messages: bRequest values */
+#define DL_GETSTATE	0	/* returns the rdl_state_t struct */
+#define DL_CHECK_CRC	1	/* currently unused */
+#define DL_GO		2	/* execute downloaded image */
+#define DL_START	3	/* initialize dl state */
+#define DL_REBOOT	4	/* reboot the device in 2 seconds */
+#define DL_GETVER	5	/* returns the bootrom_id_t struct */
+#define DL_GO_PROTECTED	6	/* execute the downloaded code and set reset
+				 * event to occur in 2 seconds.  It is the
+				 * responsibility of the downloaded code to
+				 * clear this event
+				 */
+#define DL_EXEC		7	/* jump to a supplied address */
+#define DL_RESETCFG	8	/* To support single enum on dongle
+				 * - Not used by bootloader
+				 */
+#define DL_DEFER_RESP_OK 9	/* Potentially defer the response to setup
+				 * if resp unavailable
+				 */
+
+/* states */
+#define DL_WAITING	0	/* waiting to rx first pkt */
+#define DL_READY	1	/* hdr was good, waiting for more of the
+				 * compressed image */
+#define DL_BAD_HDR	2	/* hdr was corrupted */
+#define DL_BAD_CRC	3	/* compressed image was corrupted */
+#define DL_RUNNABLE	4	/* download was successful,waiting for go cmd */
+#define DL_START_FAIL	5	/* failed to initialize correctly */
+#define DL_NVRAM_TOOBIG	6	/* host specified nvram data exceeds DL_NVRAM
+				 * value */
+#define DL_IMAGE_TOOBIG	7	/* download image too big (exceeds DATA_START
+				 *  for rdl) */
+
+struct rdl_state_le {
+	__le32 state;
+	__le32 bytes;
+};
+
+struct bootrom_id_le {
+	__le32 chip;	/* Chip id */
+	__le32 chiprev;	/* Chip rev */
+	__le32 ramsize;	/* Size of  RAM */
+	__le32 remapbase;	/* Current remap base address */
+	__le32 boardtype;	/* Type of board */
+	__le32 boardrev;	/* Board revision */
+};
+
+#define RDL_CHUNK	1500  /* size of each dl transfer */
+
+#define TRX_OFFSETS_DLFWLEN_IDX	0
+#define TRX_OFFSETS_JUMPTO_IDX	1
+#define TRX_OFFSETS_NVM_LEN_IDX	2
+
+#define TRX_OFFSETS_DLBASE_IDX  0
+
+#endif  /* _USB_RDL_H */
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* [PATCH 15/15] brcm80211: fmac: make sdio firmware filename specific
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (13 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets Arend van Spriel
@ 2012-02-09 20:09 ` Arend van Spriel
  2012-02-22 17:12 ` [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
  15 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-09 20:09 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Arend van Spriel

The sdio driver part uses firmware name brcmfmac.bin. With addition
of usb this name is too generic. This patch renames the filename
to brcmfmac-sdio.bin.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Alwin Beukers <alwin@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 253fc20..0b467b0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -309,10 +309,10 @@ struct rte_console {
 /* Flags for SDH calls */
 #define F2SYNC	(SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
 
-#define BRCMFMAC_FW_NAME	"brcm/brcmfmac.bin"
-#define BRCMFMAC_NV_NAME	"brcm/brcmfmac.txt"
-MODULE_FIRMWARE(BRCMFMAC_FW_NAME);
-MODULE_FIRMWARE(BRCMFMAC_NV_NAME);
+#define BRCMF_SDIO_FW_NAME	"brcm/brcmfmac-sdio.bin"
+#define BRCMF_SDIO_NV_NAME	"brcm/brcmfmac-sdio.txt"
+MODULE_FIRMWARE(BRCMF_SDIO_FW_NAME);
+MODULE_FIRMWARE(BRCMF_SDIO_NV_NAME);
 
 #define BRCMF_IDLE_IMMEDIATE	(-1)	/* Enter idle immediately */
 #define BRCMF_IDLE_ACTIVE	0	/* Do not request any SD clock change
@@ -3202,7 +3202,7 @@ static int brcmf_sdbrcm_download_code_file(struct brcmf_sdio *bus)
 
 	brcmf_dbg(INFO, "Enter\n");
 
-	ret = request_firmware(&bus->firmware, BRCMFMAC_FW_NAME,
+	ret = request_firmware(&bus->firmware, BRCMF_SDIO_FW_NAME,
 			       &bus->sdiodev->func[2]->dev);
 	if (ret) {
 		brcmf_dbg(ERROR, "Fail to request firmware %d\n", ret);
@@ -3299,7 +3299,7 @@ static int brcmf_sdbrcm_download_nvram(struct brcmf_sdio *bus)
 	char *bufp;
 	int ret;
 
-	ret = request_firmware(&bus->firmware, BRCMFMAC_NV_NAME,
+	ret = request_firmware(&bus->firmware, BRCMF_SDIO_NV_NAME,
 			       &bus->sdiodev->func[2]->dev);
 	if (ret) {
 		brcmf_dbg(ERROR, "Fail to request nvram %d\n", ret);
-- 
1.7.5.4



^ permalink raw reply related	[flat|nested] 26+ messages in thread

* Re: [PATCH 09/15] brcm80211: fmac: move module entry points to dhd_linux.c
  2012-02-09 20:09 ` [PATCH 09/15] brcm80211: fmac: move module entry points to dhd_linux.c Arend van Spriel
@ 2012-02-09 23:50   ` Julian Calaby
  2012-02-10  9:11     ` Arend van Spriel
  0 siblings, 1 reply; 26+ messages in thread
From: Julian Calaby @ 2012-02-09 23:50 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linville, linux-wireless

Hi,

Quick query:

On Fri, Feb 10, 2012 at 07:09, Arend van Spriel <arend@broadcom.com> wrote:
> The module_init/exit functions are moved to dhd_linux.c to prepare
> for supporting multiple host interface types.
>
> Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
> Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
> Signed-off-by: Arend van Spriel <arend@broadcom.com>
> ---
>  .../net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c |    7 +----
>  drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h  |    6 +++++
>  .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   24 ++++++++++++++++++++
>  3 files changed, 32 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
> index eff0073..ff7fc0e 100644
> --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
> +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
> @@ -1183,3 +1183,27 @@ exit:
>        return ret;
>  }
>  #endif                         /* DEBUG */
> +
> +static int __init brcmfmac_init(void)
> +{
> +       int ret = 0;
> +
> +#ifdef CONFIG_BRCMFMAC_SDIO
> +       ret = brcmf_sdio_init();
> +       if (ret)
> +               goto fail;
> +#endif

I assume that the USB driver init will be added here as a separate #ifdef block.

If this is the case, doesn't this mean that on a system with both the
USB and SDIO drivers enabled in .config, you won't be able to load the
USB driver without the SDIO driver or vice-versa?

The model that most other drivers I've seen use is to have
bus-specific modules and a common code module.

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/
.Plan: http://sites.google.com/site/juliancalaby/

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 01/15] brcm80211: update the maintainers listed for brcm80211 drivers
  2012-02-09 20:08 ` [PATCH 01/15] brcm80211: update the maintainers listed for brcm80211 drivers Arend van Spriel
@ 2012-02-10  7:26   ` Rafał Miłecki
  0 siblings, 0 replies; 26+ messages in thread
From: Rafał Miłecki @ 2012-02-10  7:26 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linville, linux-wireless

2012/2/9 Arend van Spriel <arend@broadcom.com>:
> Henry Ptasinski is not working on the brcm80211 driver so taking
> his name/email out of the MAINTAINERS file.

/me votes for creating some brcm80211 ML finally

-- 
Rafał

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 09/15] brcm80211: fmac: move module entry points to dhd_linux.c
  2012-02-09 23:50   ` Julian Calaby
@ 2012-02-10  9:11     ` Arend van Spriel
  0 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-10  9:11 UTC (permalink / raw)
  To: Julian Calaby; +Cc: linville, linux-wireless

On 02/10/2012 12:50 AM, Julian Calaby wrote:
> Hi,
> 
> Quick query:
> 
> On Fri, Feb 10, 2012 at 07:09, Arend van Spriel <arend@broadcom.com> wrote:
>> The module_init/exit functions are moved to dhd_linux.c to prepare
>> for supporting multiple host interface types.
>>
> 
> I assume that the USB driver init will be added here as a separate #ifdef block.

Correct.

> If this is the case, doesn't this mean that on a system with both the
> USB and SDIO drivers enabled in .config, you won't be able to load the
> USB driver without the SDIO driver or vice-versa?

True.

> The model that most other drivers I've seen use is to have
> bus-specific modules and a common code module.
> 
> Thanks,
> 

I've seen both flavors. We discussed it internally and both flavors have
a price regarding system resources. Being curious by nature and open to
discussion I invite kernel developers to spew their arguments for 1)
separate modules and 2) kconfig option.

Gr. AvS


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support
  2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
                   ` (14 preceding siblings ...)
  2012-02-09 20:09 ` [PATCH 15/15] brcm80211: fmac: make sdio firmware filename specific Arend van Spriel
@ 2012-02-22 17:12 ` Arend van Spriel
  2012-02-22 19:14   ` John W. Linville
  15 siblings, 1 reply; 26+ messages in thread
From: Arend van Spriel @ 2012-02-22 17:12 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless

On 02/09/2012 09:08 PM, Arend van Spriel wrote:
> This patch series contains patches for a couple of issue in brcmsmac. The A-MPDU
> endless retry fix is a long standing issue that exists in previous kernels. So
> it should go to 3.3 kernel.
>
> For the brcmfmac driver support has been added for USB chipsets. Firmware has
> been submitted for bcm43235, bcm43236, and bcm43238 chipsets.
>

Hi John,

I send this patch series a while ago. I wanted to be sure whether they 
are scheduled to be taken in or is there some issue with it that we need 
to address, eg. indentation ;-) I looked in my email archive for 
community response and did not see any obvious show stopper there.

One patch in the series is same as I attached to redhat bug 787649 (see 
[1]).

Regards,
AvS

[1] https://bugzilla.redhat.com/show_bug.cgi?id=787649


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support
  2012-02-22 17:12 ` [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
@ 2012-02-22 19:14   ` John W. Linville
  0 siblings, 0 replies; 26+ messages in thread
From: John W. Linville @ 2012-02-22 19:14 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linux-wireless

On Wed, Feb 22, 2012 at 06:12:11PM +0100, Arend van Spriel wrote:
> On 02/09/2012 09:08 PM, Arend van Spriel wrote:
> >This patch series contains patches for a couple of issue in brcmsmac. The A-MPDU
> >endless retry fix is a long standing issue that exists in previous kernels. So
> >it should go to 3.3 kernel.
> >
> >For the brcmfmac driver support has been added for USB chipsets. Firmware has
> >been submitted for bcm43235, bcm43236, and bcm43238 chipsets.
> >
> 
> Hi John,
> 
> I send this patch series a while ago. I wanted to be sure whether
> they are scheduled to be taken in or is there some issue with it
> that we need to address, eg. indentation ;-) I looked in my email
> archive for community response and did not see any obvious show
> stopper there.
> 
> One patch in the series is same as I attached to redhat bug 787649
> (see [1]).
> 
> Regards,
> AvS
> 
> [1] https://bugzilla.redhat.com/show_bug.cgi?id=787649

I apologize to you and the other contributors.  I've been embroiled
in something elsewhere that has been occupying a lot of my time over
the past week or two.  I hope to be getting back to more regular
-next merging soon.

I appreciate your patience!

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets
  2012-02-09 20:09 ` [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets Arend van Spriel
@ 2012-02-23 18:10   ` Rafał Miłecki
  2012-02-23 18:46     ` Rafał Miłecki
  0 siblings, 1 reply; 26+ messages in thread
From: Rafał Miłecki @ 2012-02-23 18:10 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linville, linux-wireless, M. Lambert

2012/2/9 Arend van Spriel <arend@broadcom.com>:
> This patch extends the use of the brcmfmac driver with support for
> chipsets with a USB host interface. The first chipsets supported are
> the bcm43235, bcm43236, and bcm43238 for which firmware has been
> submitted.

Can you say something more about the firmware? AFAICS brcm directory
in linux-firmware.git contains:
brcmfmac43236b.bin
brcmfmac4329.bin
brcmfmac4330.bin


> +#define BRCMF_USB_FW_NAME      "brcm/brcmfmac-usb.bin"

However your driver seems to require *only* brcmfmac-usb.bin firmware file...

-- 
Rafał

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets
  2012-02-23 18:10   ` Rafał Miłecki
@ 2012-02-23 18:46     ` Rafał Miłecki
  2012-02-23 21:20       ` Arend van Spriel
  0 siblings, 1 reply; 26+ messages in thread
From: Rafał Miłecki @ 2012-02-23 18:46 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linville, linux-wireless, M. Lambert

W dniu 23 lutego 2012 19:10 użytkownik Rafał Miłecki <zajec5@gmail.com> napisał:
> 2012/2/9 Arend van Spriel <arend@broadcom.com>:
>> This patch extends the use of the brcmfmac driver with support for
>> chipsets with a USB host interface. The first chipsets supported are
>> the bcm43235, bcm43236, and bcm43238 for which firmware has been
>> submitted.
>
> Can you say something more about the firmware? AFAICS brcm directory
> in linux-firmware.git contains:
> brcmfmac43236b.bin
> brcmfmac4329.bin
> brcmfmac4330.bin
>
>
>> +#define BRCMF_USB_FW_NAME      "brcm/brcmfmac-usb.bin"
>
> However your driver seems to require *only* brcmfmac-usb.bin firmware file...

The only file passing usb.c::check_file test seems to be
brcmfmac43236b.bin. I guess you meant this file name in usb.c.

-- 
Rafał

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets
  2012-02-23 18:46     ` Rafał Miłecki
@ 2012-02-23 21:20       ` Arend van Spriel
  2012-02-24  6:16         ` Rafał Miłecki
  0 siblings, 1 reply; 26+ messages in thread
From: Arend van Spriel @ 2012-02-23 21:20 UTC (permalink / raw)
  To: Rafał Miłecki; +Cc: linville, linux-wireless, M. Lambert

On 02/23/2012 07:46 PM, Rafał Miłecki wrote:
> W dniu 23 lutego 2012 19:10 użytkownik Rafał Miłecki<zajec5@gmail.com>  napisał:
>> 2012/2/9 Arend van Spriel<arend@broadcom.com>:
>>> This patch extends the use of the brcmfmac driver with support for
>>> chipsets with a USB host interface. The first chipsets supported are
>>> the bcm43235, bcm43236, and bcm43238 for which firmware has been
>>> submitted.
>>
>> Can you say something more about the firmware? AFAICS brcm directory
>> in linux-firmware.git contains:
>> brcmfmac43236b.bin
>> brcmfmac4329.bin
>> brcmfmac4330.bin
>>
>>
>>> +#define BRCMF_USB_FW_NAME      "brcm/brcmfmac-usb.bin"
>>
>> However your driver seems to require *only* brcmfmac-usb.bin firmware file...
>
> The only file passing usb.c::check_file test seems to be
> brcmfmac43236b.bin. I guess you meant this file name in usb.c.
>

Yes. bcm4329 and bcm4330 are SDIO cards. I will update the information 
on linuxwireless.

Gr. AvS


^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets
  2012-02-23 21:20       ` Arend van Spriel
@ 2012-02-24  6:16         ` Rafał Miłecki
  2012-02-24  9:47           ` Arend van Spriel
  0 siblings, 1 reply; 26+ messages in thread
From: Rafał Miłecki @ 2012-02-24  6:16 UTC (permalink / raw)
  To: Arend van Spriel; +Cc: linville, linux-wireless, M. Lambert

W dniu 23 lutego 2012 22:20 użytkownik Arend van Spriel
<arend@broadcom.com> napisał:
> On 02/23/2012 07:46 PM, Rafał Miłecki wrote:
>>
>> W dniu 23 lutego 2012 19:10 użytkownik Rafał Miłecki<zajec5@gmail.com>
>>  napisał:
>>>
>>> 2012/2/9 Arend van Spriel<arend@broadcom.com>:
>>>>
>>>> This patch extends the use of the brcmfmac driver with support for
>>>> chipsets with a USB host interface. The first chipsets supported are
>>>> the bcm43235, bcm43236, and bcm43238 for which firmware has been
>>>> submitted.
>>>
>>>
>>> Can you say something more about the firmware? AFAICS brcm directory
>>> in linux-firmware.git contains:
>>> brcmfmac43236b.bin
>>> brcmfmac4329.bin
>>> brcmfmac4330.bin
>>>
>>>
>>>> +#define BRCMF_USB_FW_NAME      "brcm/brcmfmac-usb.bin"
>>>
>>>
>>> However your driver seems to require *only* brcmfmac-usb.bin firmware
>>> file...
>>
>>
>> The only file passing usb.c::check_file test seems to be
>> brcmfmac43236b.bin. I guess you meant this file name in usb.c.
>>
>
> Yes. bcm4329 and bcm4330 are SDIO cards. I will update the information on
> linuxwireless.

I'm afraid we don't understand each other. The problem is that
filename of firmware submitted to the linux-firmware.git doesn't match
filename requested by brcmfmac/usb.c.

brcmfmac43236b.bin != brcmfmac-usb.bin

-- 
Rafał

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets
  2012-02-24  6:16         ` Rafał Miłecki
@ 2012-02-24  9:47           ` Arend van Spriel
  0 siblings, 0 replies; 26+ messages in thread
From: Arend van Spriel @ 2012-02-24  9:47 UTC (permalink / raw)
  To: Rafał Miłecki; +Cc: linville, linux-wireless, M. Lambert

On 02/24/2012 07:16 AM, Rafał Miłecki wrote:
> W dniu 23 lutego 2012 22:20 użytkownik Arend van Spriel
> <arend@broadcom.com>  napisał:
>> On 02/23/2012 07:46 PM, Rafał Miłecki wrote:
>>>
>>> W dniu 23 lutego 2012 19:10 użytkownik Rafał Miłecki<zajec5@gmail.com>
>>>   napisał:
>>>>
>>>> 2012/2/9 Arend van Spriel<arend@broadcom.com>:
>>>>>
>>>>> This patch extends the use of the brcmfmac driver with support for
>>>>> chipsets with a USB host interface. The first chipsets supported are
>>>>> the bcm43235, bcm43236, and bcm43238 for which firmware has been
>>>>> submitted.
>>>>
>>>>
>>>> Can you say something more about the firmware? AFAICS brcm directory
>>>> in linux-firmware.git contains:
>>>> brcmfmac43236b.bin
>>>> brcmfmac4329.bin
>>>> brcmfmac4330.bin
>>>>
>>>>
>>>>> +#define BRCMF_USB_FW_NAME      "brcm/brcmfmac-usb.bin"
>>>>
>>>>
>>>> However your driver seems to require *only* brcmfmac-usb.bin firmware
>>>> file...
>>>
>>>
>>> The only file passing usb.c::check_file test seems to be
>>> brcmfmac43236b.bin. I guess you meant this file name in usb.c.
>>>
>>
>> Yes. bcm4329 and bcm4330 are SDIO cards. I will update the information on
>> linuxwireless.
>
> I'm afraid we don't understand each other. The problem is that
> filename of firmware submitted to the linux-firmware.git doesn't match
> filename requested by brcmfmac/usb.c.
>
> brcmfmac43236b.bin != brcmfmac-usb.bin
>

I do understand and the instruction on linux-wireless says:

cp brcm/brcmfmac43236b.bin /lib/firmware/brcm/brcmfmac/brcmfmac-usb.bin

et voila, they match. However, I can follow the reasoning you gave in 
your patch albeit unlikely that someone inserts two wireless dongles in 
system.

Gr. AvS


^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2012-02-24  9:47 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-02-09 20:08 [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
2012-02-09 20:08 ` [PATCH 01/15] brcm80211: update the maintainers listed for brcm80211 drivers Arend van Spriel
2012-02-10  7:26   ` Rafał Miłecki
2012-02-09 20:08 ` [PATCH 02/15] brcm80211: smac: fix unintended fallthru in wlc_phy_radio_init_2057() Arend van Spriel
2012-02-09 20:08 ` [PATCH 03/15] brcm80211: smac: remove redundant assignments from txpwrctrl_pwr_setup_nphy Arend van Spriel
2012-02-09 20:08 ` [PATCH 04/15] brcm80211: smac: fix endless retry of A-MPDU transmissions Arend van Spriel
2012-02-09 20:08 ` [PATCH 05/15] brcm80211: smac: remove smatch warnings from brcmsmac code Arend van Spriel
2012-02-09 20:09 ` [PATCH 06/15] brcm80211: fmac: resolve smatch issues in brcmfmac code Arend van Spriel
2012-02-09 20:09 ` [PATCH 07/15] brcm80211: fmac: make sure cancel_work_sync only called after INIT_WORK Arend van Spriel
2012-02-09 20:09 ` [PATCH 08/15] brcm80211: fmac: use specific types in struct brcmf_bus Arend van Spriel
2012-02-09 20:09 ` [PATCH 09/15] brcm80211: fmac: move module entry points to dhd_linux.c Arend van Spriel
2012-02-09 23:50   ` Julian Calaby
2012-02-10  9:11     ` Arend van Spriel
2012-02-09 20:09 ` [PATCH 10/15] brcm80211: fmac: only return success in brcmf_sdbrcm_bus_init() when true Arend van Spriel
2012-02-09 20:09 ` [PATCH 11/15] brcm80211: fmac: update bus state in common driver part Arend van Spriel
2012-02-09 20:09 ` [PATCH 12/15] brcm80211: fmac: change allocation flag in brcmf_enq_event() function Arend van Spriel
2012-02-09 20:09 ` [PATCH 13/15] brcm80211: fmac: use spinlock calls saving irq flags in brcmf_enq_event() Arend van Spriel
2012-02-09 20:09 ` [PATCH 14/15] brcm80211: fmac: add USB support for bcm43235/6/8 chipsets Arend van Spriel
2012-02-23 18:10   ` Rafał Miłecki
2012-02-23 18:46     ` Rafał Miłecki
2012-02-23 21:20       ` Arend van Spriel
2012-02-24  6:16         ` Rafał Miłecki
2012-02-24  9:47           ` Arend van Spriel
2012-02-09 20:09 ` [PATCH 15/15] brcm80211: fmac: make sdio firmware filename specific Arend van Spriel
2012-02-22 17:12 ` [PATCH 00/15] brcm80211: resolve brcmsmac issues and brcmfmac usb support Arend van Spriel
2012-02-22 19:14   ` John W. Linville

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.