Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH 2/9] brcmfmac: remove (ab)use of NL80211_NUM_ACS
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1372249222-4858-1-git-send-email-arend@broadcom.com>

Used NL80211_NUM_ACS to indicate the BCMC fifo used in the driver
which has the same value now, but it is a bad idea relying on that.

Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 41f902d..e4fd13a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -1851,7 +1851,7 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
 	fws = container_of(worker, struct brcmf_fws_info, fws_dequeue_work);
 
 	brcmf_fws_lock(fws->drvr, flags);
-	for (fifo = NL80211_NUM_ACS; fifo >= 0 && !fws->bus_flow_blocked;
+	for (fifo = BRCMF_FWS_FIFO_BCMC; fifo >= 0 && !fws->bus_flow_blocked;
 	     fifo--) {
 		while ((fws->fifo_credit[fifo]) || ((!fws->bcmc_credit_check) &&
 		       (fifo == BRCMF_FWS_FIFO_BCMC))) {
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 8/9] brcmfmac: reduce firmware-signalling locking scope in rx path
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1372249222-4858-1-git-send-email-arend@broadcom.com>

In the receive path a spinlock is taken upon parsing the TLV signal
header. This moves to locking to the TLV handling functions where
it protects the data structures.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c |   77 +++++++++++++-------
 1 file changed, 51 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 9c6d182..386fbfc 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -905,10 +905,26 @@ static int brcmf_fws_rssi_indicate(struct brcmf_fws_info *fws, s8 rssi)
 	return 0;
 }
 
+/* using macro so sparse checking does not complain
+ * about locking imbalance.
+ */
+#define brcmf_fws_lock(drvr, flags)				\
+do {								\
+	flags = 0;						\
+	spin_lock_irqsave(&((drvr)->fws_spinlock), (flags));	\
+} while (0)
+
+/* using macro so sparse checking does not complain
+ * about locking imbalance.
+ */
+#define brcmf_fws_unlock(drvr, flags) \
+	spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
+
 static
 int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
 {
 	struct brcmf_fws_mac_descriptor *entry, *existing;
+	ulong flags;
 	u8 mac_handle;
 	u8 ifidx;
 	u8 *addr;
@@ -922,8 +938,10 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
 		if (entry->occupied) {
 			brcmf_dbg(TRACE, "deleting %s mac %pM\n",
 				  entry->name, addr);
+			brcmf_fws_lock(fws->drvr, flags);
 			brcmf_fws_macdesc_cleanup(fws, entry, -1);
 			brcmf_fws_macdesc_deinit(entry);
+			brcmf_fws_unlock(fws->drvr, flags);
 		} else
 			fws->stats.mac_update_failed++;
 		return 0;
@@ -932,11 +950,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
 	existing = brcmf_fws_macdesc_lookup(fws, addr);
 	if (IS_ERR(existing)) {
 		if (!entry->occupied) {
+			brcmf_fws_lock(fws->drvr, flags);
 			entry->mac_handle = mac_handle;
 			brcmf_fws_macdesc_init(entry, addr, ifidx);
 			brcmf_fws_macdesc_set_name(fws, entry);
 			brcmu_pktq_init(&entry->psq, BRCMF_FWS_PSQ_PREC_COUNT,
 					BRCMF_FWS_PSQ_LEN);
+			brcmf_fws_unlock(fws->drvr, flags);
 			brcmf_dbg(TRACE, "add %s mac %pM\n", entry->name, addr);
 		} else {
 			fws->stats.mac_update_failed++;
@@ -944,11 +964,13 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
 	} else {
 		if (entry != existing) {
 			brcmf_dbg(TRACE, "copy mac %s\n", existing->name);
+			brcmf_fws_lock(fws->drvr, flags);
 			memcpy(entry, existing,
 			       offsetof(struct brcmf_fws_mac_descriptor, psq));
 			entry->mac_handle = mac_handle;
 			brcmf_fws_macdesc_deinit(existing);
 			brcmf_fws_macdesc_set_name(fws, entry);
+			brcmf_fws_unlock(fws->drvr, flags);
 			brcmf_dbg(TRACE, "relocate %s mac %pM\n", entry->name,
 				  addr);
 		} else {
@@ -964,7 +986,9 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
 					    u8 type, u8 *data)
 {
 	struct brcmf_fws_mac_descriptor *entry;
+	ulong flags;
 	u8 mac_handle;
+	int ret;
 
 	mac_handle = data[0];
 	entry = &fws->desc.nodes[mac_handle & 0x1F];
@@ -972,26 +996,30 @@ static int brcmf_fws_macdesc_state_indicate(struct brcmf_fws_info *fws,
 		fws->stats.mac_ps_update_failed++;
 		return -ESRCH;
 	}
+	brcmf_fws_lock(fws->drvr, flags);
 	/* a state update should wipe old credits */
 	entry->requested_credit = 0;
 	entry->requested_packet = 0;
 	if (type == BRCMF_FWS_TYPE_MAC_OPEN) {
 		entry->state = BRCMF_FWS_STATE_OPEN;
-		return BRCMF_FWS_RET_OK_SCHEDULE;
+		ret = BRCMF_FWS_RET_OK_SCHEDULE;
 	} else {
 		entry->state = BRCMF_FWS_STATE_CLOSE;
 		brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BK, false);
 		brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_BE, false);
 		brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VI, false);
 		brcmf_fws_tim_update(fws, entry, BRCMF_FWS_FIFO_AC_VO, true);
+		ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
 	}
-	return BRCMF_FWS_RET_OK_NOSCHEDULE;
+	brcmf_fws_unlock(fws->drvr, flags);
+	return ret;
 }
 
 static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
 					      u8 type, u8 *data)
 {
 	struct brcmf_fws_mac_descriptor *entry;
+	ulong flags;
 	u8 ifidx;
 	int ret;
 
@@ -1010,17 +1038,24 @@ static int brcmf_fws_interface_state_indicate(struct brcmf_fws_info *fws,
 
 	brcmf_dbg(TRACE, "%s (%d): %s\n", brcmf_fws_get_tlv_name(type), type,
 		  entry->name);
+	brcmf_fws_lock(fws->drvr, flags);
 	switch (type) {
 	case BRCMF_FWS_TYPE_INTERFACE_OPEN:
 		entry->state = BRCMF_FWS_STATE_OPEN;
-		return BRCMF_FWS_RET_OK_SCHEDULE;
+		ret = BRCMF_FWS_RET_OK_SCHEDULE;
+		break;
 	case BRCMF_FWS_TYPE_INTERFACE_CLOSE:
 		entry->state = BRCMF_FWS_STATE_CLOSE;
-		return BRCMF_FWS_RET_OK_NOSCHEDULE;
+		ret = BRCMF_FWS_RET_OK_NOSCHEDULE;
+		break;
 	default:
 		ret = -EINVAL;
-		break;
+		brcmf_fws_unlock(fws->drvr, flags);
+		goto fail;
 	}
+	brcmf_fws_unlock(fws->drvr, flags);
+	return ret;
+
 fail:
 	fws->stats.if_update_failed++;
 	return ret;
@@ -1030,6 +1065,7 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
 				      u8 *data)
 {
 	struct brcmf_fws_mac_descriptor *entry;
+	ulong flags;
 
 	entry = &fws->desc.nodes[data[1] & 0x1F];
 	if (!entry->occupied) {
@@ -1043,12 +1079,14 @@ static int brcmf_fws_request_indicate(struct brcmf_fws_info *fws, u8 type,
 	brcmf_dbg(TRACE, "%s (%d): %s cnt %d bmp %d\n",
 		  brcmf_fws_get_tlv_name(type), type, entry->name,
 		  data[0], data[2]);
+	brcmf_fws_lock(fws->drvr, flags);
 	if (type == BRCMF_FWS_TYPE_MAC_REQUEST_CREDIT)
 		entry->requested_credit = data[0];
 	else
 		entry->requested_packet = data[0];
 
 	entry->ac_bitmap = data[2];
+	brcmf_fws_unlock(fws->drvr, flags);
 	return BRCMF_FWS_RET_OK_SCHEDULE;
 }
 
@@ -1345,6 +1383,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
 static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
 					     u8 *data)
 {
+	ulong flags;
 	int i;
 
 	if (fws->fcmode != BRCMF_FWS_FCMODE_EXPLICIT_CREDIT) {
@@ -1353,16 +1392,19 @@ static int brcmf_fws_fifocreditback_indicate(struct brcmf_fws_info *fws,
 	}
 
 	brcmf_dbg(DATA, "enter: data %pM\n", data);
+	brcmf_fws_lock(fws->drvr, flags);
 	for (i = 0; i < BRCMF_FWS_FIFO_COUNT; i++)
 		brcmf_fws_return_credits(fws, i, data[i]);
 
 	brcmf_dbg(DATA, "map: credit %x delay %x\n", fws->fifo_credit_map,
 		  fws->fifo_delay_map);
+	brcmf_fws_unlock(fws->drvr, flags);
 	return BRCMF_FWS_RET_OK_SCHEDULE;
 }
 
 static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
 {
+	ulong lflags;
 	__le32 status_le;
 	u32 status;
 	u32 hslot;
@@ -1376,7 +1418,10 @@ static int brcmf_fws_txstatus_indicate(struct brcmf_fws_info *fws, u8 *data)
 	hslot = brcmf_txstatus_get_field(status, HSLOT);
 	genbit = brcmf_txstatus_get_field(status, GENERATION);
 
-	return brcmf_fws_txs_process(fws, flags, hslot, genbit);
+	brcmf_fws_lock(fws->drvr, lflags);
+	brcmf_fws_txs_process(fws, flags, hslot, genbit);
+	brcmf_fws_unlock(fws->drvr, lflags);
+	return BRCMF_FWS_RET_OK_NOSCHEDULE;
 }
 
 static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
@@ -1389,21 +1434,6 @@ static int brcmf_fws_dbg_seqnum_check(struct brcmf_fws_info *fws, u8 *data)
 	return 0;
 }
 
-/* using macro so sparse checking does not complain
- * about locking imbalance.
- */
-#define brcmf_fws_lock(drvr, flags)				\
-do {								\
-	flags = 0;						\
-	spin_lock_irqsave(&((drvr)->fws_spinlock), (flags));	\
-} while (0)
-
-/* using macro so sparse checking does not complain
- * about locking imbalance.
- */
-#define brcmf_fws_unlock(drvr, flags) \
-	spin_unlock_irqrestore(&((drvr)->fws_spinlock), (flags))
-
 static int brcmf_fws_notify_credit_map(struct brcmf_if *ifp,
 				       const struct brcmf_event_msg *e,
 				       void *data)
@@ -1454,7 +1484,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
 		      struct sk_buff *skb)
 {
 	struct brcmf_fws_info *fws = drvr->fws;
-	ulong flags;
 	u8 *signal_data;
 	s16 data_len;
 	u8 type;
@@ -1474,9 +1503,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
 		return 0;
 	}
 
-	/* lock during tlv parsing */
-	brcmf_fws_lock(drvr, flags);
-
 	fws->stats.header_pulls++;
 	data_len = signal_len;
 	signal_data = skb->data;
@@ -1570,7 +1596,6 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
 	if (skb->len == 0)
 		fws->stats.header_only_pkt++;
 
-	brcmf_fws_unlock(drvr, flags);
 	return 0;
 }
 
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 6/9] brcmfmac: tag packet in the netdev transmit callback
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1372249222-4858-1-git-send-email-arend@broadcom.com>

Transmit packets needs to be tagged in order to receive a tx status
feedback from the firmware. Determine the tag in the netdev transmit
callback instead of determining the tag just before transfer to the
device. This reduces the number of exception flows and hence makes
the driver code simpler.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c |  130 ++++++++------------
 1 file changed, 48 insertions(+), 82 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index e4fd13a..2b078a1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -1575,21 +1575,14 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
 	return 0;
 }
 
-static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
+static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
 				   struct sk_buff *p)
 {
 	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
 	struct brcmf_fws_mac_descriptor *entry = skcb->mac;
-	int rc = 0;
-	bool first_time;
-	int hslot = BRCMF_FWS_HANGER_MAXITEMS;
-	u8 free_ctr;
 	u8 flags;
 
-	first_time = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED;
-
 	brcmf_skb_if_flags_set_field(p, TRANSMIT, 1);
-	brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
 	brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation);
 	flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
 	if (brcmf_skb_if_flags_get_field(p, REQUESTED)) {
@@ -1600,80 +1593,36 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
 		flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
 	}
 	brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
-	if (first_time) {
-		/* obtaining free slot may fail, but that will be caught
-		 * by the hanger push. This assures the packet has a BDC
-		 * header upon return.
-		 */
-		hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
-		free_ctr = entry->seq[fifo];
-		brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
-		brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr);
-		rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
-		if (rc)
-			brcmf_err("hanger push failed: rc=%d\n", rc);
-	}
-
-	if (rc == 0)
-		brcmf_fws_hdrpush(fws, p);
-
-	return rc;
+	brcmf_fws_hdrpush(fws, p);
 }
 
-static void
-brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
-		       struct sk_buff *skb, int fifo)
+static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
+				   struct sk_buff *skb, int fifo)
 {
-	/*
-	put the packet back to the head of queue
-
-	- suppressed packet goes back to suppress sub-queue
-	- pull out the header, if new or delayed packet
-
-	Note: hslot is used only when header removal is done.
-	*/
 	struct brcmf_fws_mac_descriptor *entry;
-	enum brcmf_fws_skb_state state;
 	struct sk_buff *pktout;
+	int qidx, hslot;
 	int rc = 0;
-	int hslot;
 
-	state = brcmf_skbcb(skb)->state;
 	entry = brcmf_skbcb(skb)->mac;
-	hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
-
-	if (entry != NULL) {
-		if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) {
-			/* wl-header is saved for suppressed packets */
-			pktout = brcmu_pktq_penq_head(&entry->psq, 2 * fifo + 1,
-						      skb);
-			if (pktout == NULL) {
-				brcmf_err("suppress queue full\n");
-				rc = -ENOSPC;
-			}
-		} else {
-			/* delay-q packets are going to delay-q */
-			pktout = brcmu_pktq_penq_head(&entry->psq,
-						      2 * fifo, skb);
-			if (pktout == NULL) {
-				brcmf_err("delay queue full\n");
-				rc = -ENOSPC;
-			}
-
-			/* free the hanger slot */
-			brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &pktout,
-						true);
-
-			/* decrement sequence count */
-			entry->seq[fifo]--;
+	if (entry->occupied) {
+		qidx = 2 *fifo;
+		if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_SUPPRESSED)
+			qidx++;
+
+		pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb);
+		if (pktout == NULL) {
+			brcmf_err("%s queue %d full\n", entry->name, qidx);
+			rc = -ENOSPC;
 		}
 	} else {
-		brcmf_err("no mac entry linked\n");
+		brcmf_err("%s entry removed\n", entry->name);
 		rc = -ENOENT;
 	}
 
 	if (rc) {
 		fws->stats.rollback_failed++;
+		hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
 		brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
 				      hslot, 0);
 	} else {
@@ -1720,15 +1669,10 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
 	if (IS_ERR(entry))
 		return PTR_ERR(entry);
 
-	rc = brcmf_fws_precommit_skb(fws, fifo, skb);
-	if (rc < 0) {
-		fws->stats.generic_error++;
-		goto rollback;
-	}
-
-	brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags,
-		  skcb->htod);
+	brcmf_fws_precommit_skb(fws, fifo, skb);
 	rc = brcmf_bus_txdata(bus, skb);
+	brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
+		  skcb->if_flags, skcb->htod, rc);
 	if (rc < 0) {
 		brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
 		goto rollback;
@@ -1737,7 +1681,6 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
 	entry->transit_count++;
 	if (entry->suppressed)
 		entry->suppr_transit_count++;
-	entry->seq[fifo]++;
 	fws->stats.pkt2bus++;
 	fws->stats.send_pkts[fifo]++;
 	if (brcmf_skb_if_flags_get_field(skb, REQUESTED))
@@ -1750,6 +1693,24 @@ rollback:
 	return rc;
 }
 
+static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p,
+				  int fifo)
+{
+	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
+	int rc, hslot;
+
+	hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
+	brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
+	brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]);
+	brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
+	rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
+	if (!rc)
+		skcb->mac->seq[fifo]++;
+	else
+		fws->stats.generic_error++;
+	return rc;
+}
+
 int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
 {
 	struct brcmf_pub *drvr = ifp->drvr;
@@ -1778,22 +1739,27 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
 
 	/* set control buffer information */
 	skcb->if_flags = 0;
-	skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
 	skcb->state = BRCMF_FWS_SKBSTATE_NEW;
 	brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
 	if (!multicast)
 		fifo = brcmf_fws_prio2fifo[skb->priority];
 
-	brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name,
-		  eh->h_dest, multicast, fifo);
-
 	brcmf_fws_lock(drvr, flags);
-	brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
 	if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
 		fws->borrow_defer_timestamp = jiffies +
 					      BRCMF_FWS_BORROW_DEFER_PERIOD;
+
+	skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
+	brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name,
+		  eh->h_dest, multicast, fifo);
+	if (!brcmf_fws_assign_htod(fws, skb, fifo)) {
+		brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
+		brcmf_fws_schedule_deq(fws);
+	} else {
+		brcmf_err("drop skb: no hanger slot\n");
+		brcmu_pkt_buf_free_skb(skb);
+	}
 	brcmf_fws_unlock(drvr, flags);
-	brcmf_fws_schedule_deq(fws);
 	return 0;
 }
 
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 7/9] brcmfmac: cleanup debug messages in brcmf_fws_hdrpush()
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1372249222-4858-1-git-send-email-arend@broadcom.com>

Trivial cleanup of debug messages.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c |    9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 2b078a1..9c6d182 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -796,9 +796,8 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
 	u8 fillers;
 	__le32 pkttag = cpu_to_le32(brcmf_skbcb(skb)->htod);
 
-	brcmf_dbg(TRACE, "enter: ea=%pM, ifidx=%u (%u), pkttag=0x%08X, hslot=%d\n",
-		  entry->ea, entry->interface_id,
-		  brcmf_skb_if_flags_get_field(skb, INDEX),
+	brcmf_dbg(TRACE, "enter: %s, idx=%d pkttag=0x%08X, hslot=%d\n",
+		  entry->name, brcmf_skb_if_flags_get_field(skb, INDEX),
 		  le32_to_cpu(pkttag), (le32_to_cpu(pkttag) >> 8) & 0xffff);
 	if (entry->send_tim_signal)
 		data_offset += 2 + BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
@@ -822,8 +821,8 @@ static int brcmf_fws_hdrpush(struct brcmf_fws_info *fws, struct sk_buff *skb)
 		wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN;
 		wlh[2] = entry->mac_handle;
 		wlh[3] = entry->traffic_pending_bmp;
-		brcmf_dbg(TRACE, "adding TIM info: %02X:%02X:%02X:%02X\n",
-			  wlh[0], wlh[1], wlh[2], wlh[3]);
+		brcmf_dbg(TRACE, "adding TIM info: handle %d bmp 0x%X\n",
+			  entry->mac_handle, entry->traffic_pending_bmp);
 		wlh += BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN + 2;
 		entry->traffic_lastreported_bmp = entry->traffic_pending_bmp;
 	}
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 9/9] brcmfmac: remove code and comment for older kernel support
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1372249222-4858-1-git-send-email-arend@broadcom.com>

In the code of the receive path some code was dealing with how
things were done in older kernels. Not really needed for an
upstream driver.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   29 ++------------------
 1 file changed, 2 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 8c402e7..8e89755 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -281,8 +281,6 @@ void brcmf_txflowblock(struct device *dev, bool state)
 
 void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
 {
-	unsigned char *eth;
-	uint len;
 	struct sk_buff *skb, *pnext;
 	struct brcmf_if *ifp;
 	struct brcmf_bus *bus_if = dev_get_drvdata(dev);
@@ -306,33 +304,12 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
 			continue;
 		}
 
-		/* Get the protocol, maintain skb around eth_type_trans()
-		 * The main reason for this hack is for the limitation of
-		 * Linux 2.4 where 'eth_type_trans' uses the
-		 * 'net->hard_header_len'
-		 * to perform skb_pull inside vs ETH_HLEN. Since to avoid
-		 * coping of the packet coming from the network stack to add
-		 * BDC, Hardware header etc, during network interface
-		 * registration
-		 * we set the 'net->hard_header_len' to ETH_HLEN + extra space
-		 * required
-		 * for BDC, Hardware header etc. and not just the ETH_HLEN
-		 */
-		eth = skb->data;
-		len = skb->len;
-
 		skb->dev = ifp->ndev;
 		skb->protocol = eth_type_trans(skb, skb->dev);
 
 		if (skb->pkt_type == PACKET_MULTICAST)
 			ifp->stats.multicast++;
 
-		skb->data = eth;
-		skb->len = len;
-
-		/* Strip header, count, deliver upward */
-		skb_pull(skb, ETH_HLEN);
-
 		/* Process special event packets */
 		brcmf_fweh_process_skb(drvr, skb);
 
@@ -348,10 +325,8 @@ void brcmf_rx_frames(struct device *dev, struct sk_buff_head *skb_list)
 			netif_rx(skb);
 		else
 			/* If the receive is not processed inside an ISR,
-			 * the softirqd must be woken explicitly to service
-			 * the NET_RX_SOFTIRQ.  In 2.6 kernels, this is handled
-			 * by netif_rx_ni(), but in earlier kernels, we need
-			 * to do it manually.
+			 * the softirqd must be woken explicitly to service the
+			 * NET_RX_SOFTIRQ. This is handled by netif_rx_ni().
 			 */
 			netif_rx_ni(skb);
 	}
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 5/9] brcmfmac: add broken scatter-gather DMA support
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Franky Lin, Arend van Spriel
In-Reply-To: <1372249222-4858-1-git-send-email-arend@broadcom.com>

From: Franky Lin <frankyl@broadcom.com>

DMA engine of some old SDIO host controllers require block size alignment for
data length of each scatterlist item. This patch introduces an intermediate
buffer list to support this kind of platform. It decreases the throughput
because of an extra memcpy in critical data path. So don't turn this on unless
it's necessary.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c |   78 +++++++++++++++++++---
 include/linux/platform_data/brcmfmac-sdio.h      |    5 ++
 2 files changed, 72 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 70cd0e9..e3f3c48 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -331,10 +331,11 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 			     bool write, u32 addr, struct sk_buff_head *pktlist)
 {
 	unsigned int req_sz, func_blk_sz, sg_cnt, sg_data_sz, pkt_offset;
-	unsigned int max_blks, max_req_sz;
+	unsigned int max_blks, max_req_sz, orig_offset, dst_offset;
 	unsigned short max_seg_sz, seg_sz;
-	unsigned char *pkt_data;
-	struct sk_buff *pkt_next = NULL;
+	unsigned char *pkt_data, *orig_data, *dst_data;
+	struct sk_buff *pkt_next = NULL, *local_pkt_next;
+	struct sk_buff_head local_list, *target_list;
 	struct mmc_request mmc_req;
 	struct mmc_command mmc_cmd;
 	struct mmc_data mmc_dat;
@@ -371,6 +372,32 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 					   req_sz);
 	}
 
+	target_list = pktlist;
+	/* for host with broken sg support, prepare a page aligned list */
+	__skb_queue_head_init(&local_list);
+	if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
+		req_sz = 0;
+		skb_queue_walk(pktlist, pkt_next)
+			req_sz += pkt_next->len;
+		req_sz = ALIGN(req_sz, sdiodev->func[fn]->cur_blksize);
+		while (req_sz > PAGE_SIZE) {
+			pkt_next = brcmu_pkt_buf_get_skb(PAGE_SIZE);
+			if (pkt_next == NULL) {
+				ret = -ENOMEM;
+				goto exit;
+			}
+			__skb_queue_tail(&local_list, pkt_next);
+			req_sz -= PAGE_SIZE;
+		}
+		pkt_next = brcmu_pkt_buf_get_skb(req_sz);
+		if (pkt_next == NULL) {
+			ret = -ENOMEM;
+			goto exit;
+		}
+		__skb_queue_tail(&local_list, pkt_next);
+		target_list = &local_list;
+	}
+
 	host = sdiodev->func[fn]->card->host;
 	func_blk_sz = sdiodev->func[fn]->cur_blksize;
 	/* Blocks per command is limited by host count, host transfer
@@ -380,13 +407,15 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 	max_req_sz = min_t(unsigned int, host->max_req_size,
 			   max_blks * func_blk_sz);
 	max_seg_sz = min_t(unsigned short, host->max_segs, SG_MAX_SINGLE_ALLOC);
-	max_seg_sz = min_t(unsigned short, max_seg_sz, pktlist->qlen);
-	seg_sz = pktlist->qlen;
+	max_seg_sz = min_t(unsigned short, max_seg_sz, target_list->qlen);
+	seg_sz = target_list->qlen;
 	pkt_offset = 0;
-	pkt_next = pktlist->next;
+	pkt_next = target_list->next;
 
-	if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL))
-		return -ENOMEM;
+	if (sg_alloc_table(&st, max_seg_sz, GFP_KERNEL)) {
+		ret = -ENOMEM;
+		goto exit;
+	}
 
 	while (seg_sz) {
 		req_sz = 0;
@@ -396,7 +425,7 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 		memset(&mmc_dat, 0, sizeof(struct mmc_data));
 		sgl = st.sgl;
 		/* prep sg table */
-		while (pkt_next != (struct sk_buff *)pktlist) {
+		while (pkt_next != (struct sk_buff *)target_list) {
 			pkt_data = pkt_next->data + pkt_offset;
 			sg_data_sz = pkt_next->len - pkt_offset;
 			if (sg_data_sz > host->max_seg_size)
@@ -423,8 +452,8 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 		if (req_sz % func_blk_sz != 0) {
 			brcmf_err("sg request length %u is not %u aligned\n",
 				  req_sz, func_blk_sz);
-			sg_free_table(&st);
-			return -ENOTBLK;
+			ret = -ENOTBLK;
+			goto exit;
 		}
 		mmc_dat.sg = st.sgl;
 		mmc_dat.sg_len = sg_cnt;
@@ -457,7 +486,34 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 		}
 	}
 
+	if (sdiodev->pdata && sdiodev->pdata->broken_sg_support && !write) {
+		local_pkt_next = local_list.next;
+		orig_offset = 0;
+		skb_queue_walk(pktlist, pkt_next) {
+			dst_offset = 0;
+			do {
+				req_sz = local_pkt_next->len - orig_offset;
+				req_sz = min_t(uint, pkt_next->len - dst_offset,
+					       req_sz);
+				orig_data = local_pkt_next->data + orig_offset;
+				dst_data = pkt_next->data + dst_offset;
+				memcpy(dst_data, orig_data, req_sz);
+				orig_offset += req_sz;
+				dst_offset += req_sz;
+				if (orig_offset == local_pkt_next->len) {
+					orig_offset = 0;
+					local_pkt_next = local_pkt_next->next;
+				}
+				if (dst_offset == pkt_next->len)
+					break;
+			} while (!skb_queue_empty(&local_list));
+		}
+	}
+
+exit:
 	sg_free_table(&st);
+	while ((pkt_next = __skb_dequeue(&local_list)) != NULL)
+		brcmu_pkt_buf_free_skb(pkt_next);
 
 	return ret;
 }
diff --git a/include/linux/platform_data/brcmfmac-sdio.h b/include/linux/platform_data/brcmfmac-sdio.h
index 1ade657..b717499 100644
--- a/include/linux/platform_data/brcmfmac-sdio.h
+++ b/include/linux/platform_data/brcmfmac-sdio.h
@@ -90,6 +90,10 @@ void __init brcmfmac_init_pdata(void)
  * oob_irq_nr, oob_irq_flags: the OOB interrupt information. The values are
  * used for registering the irq using request_irq function.
  *
+ * broken_sg_support: flag for broken sg list support of SDIO host controller.
+ * Set this to true if the SDIO host controller has higher align requirement
+ * than 32 bytes for each scatterlist item.
+ *
  * power_on: This function is called by the brcmfmac when the module gets
  * loaded. This can be particularly useful for low power devices. The platform
  * spcific routine may for example decide to power up the complete device.
@@ -116,6 +120,7 @@ struct brcmfmac_sdio_platform_data {
 	bool oob_irq_supported;
 	unsigned int oob_irq_nr;
 	unsigned long oob_irq_flags;
+	bool broken_sg_support;
 	void (*power_on)(void);
 	void (*power_off)(void);
 	void (*reset)(void);
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 0/9] brcmfmac: platform data change and cleanup
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel

Testing the recently added scatter-gather support in SDIO on an
OMAP4 Panda showed DMA failures. This is due to alignment requirements
for that particular piece of hardware. Added flag to the platform data
to use a backup mechanism.

Other cleanup was done in firmware-signalling and some comment referring
to v2.4 kernel support triggered cleanup in rx path.

Arend van Spriel (6):
  brcmfmac: simplify transmit path
  brcmfmac: remove (ab)use of NL80211_NUM_ACS
  brcmfmac: tag packet in the netdev transmit callback
  brcmfmac: cleanup debug messages in brcmf_fws_hdrpush()
  brcmfmac: reduce firmware-signalling locking scope in rx path
  brcmfmac: remove code and comment for older kernel support

Franky Lin (3):
  brcmfmac: remove SDIO_REQ_ASYNC flag
  brcmfmac: use unified dongle address preparation function
  brcmfmac: add broken scatter-gather DMA support

 drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c   |  165 +++++++------
 .../net/wireless/brcm80211/brcmfmac/dhd_linux.c    |   29 +--
 drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c |  260 ++++++++------------
 .../net/wireless/brcm80211/brcmfmac/sdio_host.h    |    5 -
 include/linux/platform_data/brcmfmac-sdio.h        |    5 +
 5 files changed, 204 insertions(+), 260 deletions(-)

-- 
1.7.10.4



^ permalink raw reply

* [PATCH 3/9] brcmfmac: remove SDIO_REQ_ASYNC flag
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Franky Lin, Arend van Spriel
In-Reply-To: <1372249222-4858-1-git-send-email-arend@broadcom.com>

From: Franky Lin <frankyl@broadcom.com>

Remove SDIO_REQ_ASYNC from brcmfmac since it is not being used.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c    |   14 +++-----------
 drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h |    2 --
 2 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 3f8e69c..c9c5ad2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -453,15 +453,11 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 }
 
 static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
-				     uint flags, uint width, u32 *addr)
+				     uint width, u32 *addr)
 {
 	uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
 	int err = 0;
 
-	/* Async not implemented yet */
-	if (flags & SDIO_REQ_ASYNC)
-		return -ENOTSUPP;
-
 	if (bar0 != sdiodev->sbwad) {
 		err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
 		if (err)
@@ -512,7 +508,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		  fn, addr, pkt->len);
 
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-	err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
+	err = brcmf_sdcard_recv_prepare(sdiodev, fn, width, &addr);
 	if (err)
 		goto done;
 
@@ -536,7 +532,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		  fn, addr, pktq->qlen);
 
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-	err = brcmf_sdcard_recv_prepare(sdiodev, fn, flags, width, &addr);
+	err = brcmf_sdcard_recv_prepare(sdiodev, fn, width, &addr);
 	if (err)
 		goto done;
 
@@ -581,10 +577,6 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 	brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pkt->len);
 
-	/* Async not implemented yet */
-	if (flags & SDIO_REQ_ASYNC)
-		return -ENOTSUPP;
-
 	if (bar0 != sdiodev->sbwad) {
 		err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
 		if (err)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 793df66..69c03fe 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -229,8 +229,6 @@ brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 #define SDIO_REQ_4BYTE	0x1
 /* Fixed address (FIFO) (vs. incrementing address) */
 #define SDIO_REQ_FIXED	0x2
-/* Async request (vs. sync request) */
-#define SDIO_REQ_ASYNC	0x4
 
 /* Read/write to memory block (F1, no FIFO) via CMD53 (sync only).
  *   rw:       read or write (0/1)
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 4/9] brcmfmac: use unified dongle address preparation function
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Franky Lin, Arend van Spriel
In-Reply-To: <1372249222-4858-1-git-send-email-arend@broadcom.com>

From: Franky Lin <frankyl@broadcom.com>

Introduce a unified dongle backplane address preparation function
brcmf_sdio_addrprep to replace duplicate address prep code.

Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Reviewed-by: Arend van Spriel <arend@broadcom.com>
Signed-off-by: Franky Lin <frankyl@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c   |   79 +++++++-------------
 .../net/wireless/brcm80211/brcmfmac/sdio_host.h    |    3 -
 2 files changed, 27 insertions(+), 55 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index c9c5ad2..70cd0e9 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -162,7 +162,7 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev)
 	return 0;
 }
 
-int
+static int
 brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
 {
 	int err = 0, i;
@@ -193,12 +193,33 @@ brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address)
 	return err;
 }
 
+static int
+brcmf_sdio_addrprep(struct brcmf_sdio_dev *sdiodev, uint width, u32 *addr)
+{
+	uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
+	int err = 0;
+
+	if (bar0 != sdiodev->sbwad) {
+		err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
+		if (err)
+			return err;
+
+		sdiodev->sbwad = bar0;
+	}
+
+	*addr &= SBSDIO_SB_OFT_ADDR_MASK;
+
+	if (width == 4)
+		*addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+
+	return 0;
+}
+
 int
 brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
 			void *data, bool write)
 {
 	u8 func_num, reg_size;
-	u32 bar;
 	s32 retry = 0;
 	int ret;
 
@@ -218,18 +239,7 @@ brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr,
 		func_num = SDIO_FUNC_1;
 		reg_size = 4;
 
-		/* Set the window for SB core register */
-		bar = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
-		if (bar != sdiodev->sbwad) {
-			ret = brcmf_sdcard_set_sbaddr_window(sdiodev, bar);
-			if (ret != 0) {
-				memset(data, 0xFF, reg_size);
-				return ret;
-			}
-			sdiodev->sbwad = bar;
-		}
-		addr &= SBSDIO_SB_OFT_ADDR_MASK;
-		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+		brcmf_sdio_addrprep(sdiodev, reg_size, &addr);
 	}
 
 	do {
@@ -452,28 +462,6 @@ static int brcmf_sdio_buffrw(struct brcmf_sdio_dev *sdiodev, uint fn,
 	return ret;
 }
 
-static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn,
-				     uint width, u32 *addr)
-{
-	uint bar0 = *addr & ~SBSDIO_SB_OFT_ADDR_MASK;
-	int err = 0;
-
-	if (bar0 != sdiodev->sbwad) {
-		err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
-		if (err)
-			return err;
-
-		sdiodev->sbwad = bar0;
-	}
-
-	*addr &= SBSDIO_SB_OFT_ADDR_MASK;
-
-	if (width == 4)
-		*addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
-
-	return 0;
-}
-
 int
 brcmf_sdcard_recv_buf(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		      uint flags, u8 *buf, uint nbytes)
@@ -508,7 +496,7 @@ brcmf_sdcard_recv_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		  fn, addr, pkt->len);
 
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-	err = brcmf_sdcard_recv_prepare(sdiodev, fn, width, &addr);
+	err = brcmf_sdio_addrprep(sdiodev, width, &addr);
 	if (err)
 		goto done;
 
@@ -532,7 +520,7 @@ int brcmf_sdcard_recv_chain(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		  fn, addr, pktq->qlen);
 
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-	err = brcmf_sdcard_recv_prepare(sdiodev, fn, width, &addr);
+	err = brcmf_sdio_addrprep(sdiodev, width, &addr);
 	if (err)
 		goto done;
 
@@ -570,33 +558,20 @@ brcmf_sdcard_send_pkt(struct brcmf_sdio_dev *sdiodev, u32 addr, uint fn,
 		      uint flags, struct sk_buff *pkt)
 {
 	uint width;
-	uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK;
 	int err = 0;
 	struct sk_buff_head pkt_list;
 
 	brcmf_dbg(SDIO, "fun = %d, addr = 0x%x, size = %d\n",
 		  fn, addr, pkt->len);
 
-	if (bar0 != sdiodev->sbwad) {
-		err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0);
-		if (err)
-			goto done;
-
-		sdiodev->sbwad = bar0;
-	}
-
-	addr &= SBSDIO_SB_OFT_ADDR_MASK;
-
 	width = (flags & SDIO_REQ_4BYTE) ? 4 : 2;
-	if (width == 4)
-		addr |= SBSDIO_SB_ACCESS_2_4B_FLAG;
+	brcmf_sdio_addrprep(sdiodev, width, &addr);
 
 	skb_queue_head_init(&pkt_list);
 	skb_queue_tail(&pkt_list, pkt);
 	err = brcmf_sdio_buffrw(sdiodev, fn, true, addr, &pkt_list);
 	skb_dequeue_tail(&pkt_list);
 
-done:
 	return err;
 }
 
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 69c03fe..09786a5 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -249,9 +249,6 @@ extern int brcmf_sdcard_abort(struct brcmf_sdio_dev *sdiodev, uint fn);
 extern int brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev);
 extern int brcmf_sdio_remove(struct brcmf_sdio_dev *sdiodev);
 
-extern int brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev,
-					  u32 address);
-
 /* attach, return handler on success, NULL if failed.
  *  The handler shall be provided by all subsequent calls. No local cache
  *  cfghdl points to the starting address of pci device mapped memory
-- 
1.7.10.4



^ permalink raw reply related

* [PATCH 1/9] brcmfmac: simplify transmit path
From: Arend van Spriel @ 2013-06-26 12:20 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1372249222-4858-1-git-send-email-arend@broadcom.com>

When getting a transmit packet from the networking layer simply
enqueue the packet unconditional and have it handled by the dequeue
worker. The transfer of the packet to the bus-specific driver part
is now done from one context.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Franky (Zhenhui) Lin <frankyl@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
 drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c |   54 ++------------------
 1 file changed, 5 insertions(+), 49 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index 13e75c4..41f902d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -1707,37 +1707,6 @@ static int brcmf_fws_borrow_credit(struct brcmf_fws_info *fws)
 	return -ENAVAIL;
 }
 
-static int brcmf_fws_consume_credit(struct brcmf_fws_info *fws, int fifo,
-				    struct sk_buff *skb)
-{
-	struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
-	int *credit = &fws->fifo_credit[fifo];
-
-	if (fifo != BRCMF_FWS_FIFO_AC_BE)
-		fws->borrow_defer_timestamp = jiffies +
-					      BRCMF_FWS_BORROW_DEFER_PERIOD;
-
-	if (!(*credit)) {
-		/* Try to borrow a credit from other queue */
-		if (fifo != BRCMF_FWS_FIFO_AC_BE ||
-		    (brcmf_fws_borrow_credit(fws) != 0)) {
-			brcmf_dbg(DATA, "ac=%d, credits depleted\n", fifo);
-			return -ENAVAIL;
-		}
-	} else {
-		(*credit)--;
-		if (!(*credit))
-			fws->fifo_credit_map &= ~(1 << fifo);
-	}
-
-	brcmf_fws_macdesc_use_req_credit(entry, skb);
-
-	brcmf_dbg(DATA, "ac=%d, credits=%02d:%02d:%02d:%02d\n", fifo,
-		  fws->fifo_credit[0], fws->fifo_credit[1],
-		  fws->fifo_credit[2], fws->fifo_credit[3]);
-	return 0;
-}
-
 static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
 				struct sk_buff *skb)
 {
@@ -1819,25 +1788,12 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
 		  eh->h_dest, multicast, fifo);
 
 	brcmf_fws_lock(drvr, flags);
-	/* multicast credit support is conditional, setting
-	 * flag to false to assure credit is consumed below.
-	 */
-	if (fws->bcmc_credit_check)
-		multicast = false;
-
-	if (skcb->mac->suppressed ||
-	    fws->bus_flow_blocked ||
-	    brcmf_fws_macdesc_closed(fws, skcb->mac, fifo) ||
-	    brcmu_pktq_mlen(&skcb->mac->psq, 3 << (fifo * 2)) ||
-	    (!multicast &&
-	     brcmf_fws_consume_credit(fws, fifo, skb) < 0)) {
-		/* enqueue the packet in delayQ */
-		drvr->fws->fifo_delay_map |= 1 << fifo;
-		brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
-	} else {
-		brcmf_fws_commit_skb(fws, fifo, skb);
-	}
+	brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
+	if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
+		fws->borrow_defer_timestamp = jiffies +
+					      BRCMF_FWS_BORROW_DEFER_PERIOD;
 	brcmf_fws_unlock(drvr, flags);
+	brcmf_fws_schedule_deq(fws);
 	return 0;
 }
 
-- 
1.7.10.4



^ permalink raw reply related

* Re: [PATCH] cfg80211/mac80211: fix doc compilation warnings
From: Michael Opdenacker @ 2013-06-26 12:23 UTC (permalink / raw)
  To: Johannes Berg; +Cc: davem, linux-wireless, linux-kernel
In-Reply-To: <1372232238.8157.2.camel@jlt4.sipsolutions.net>

Hi Johannes,

Thank you for your review!

On 06/26/2013 09:37 AM, Johannes Berg wrote:
> On Tue, 2013-06-25 at 21:48 +0200, Michael Opdenacker wrote:
>> This patch fixes countless "No description found for parameter"
>> warnings generating documentation (running "make htmldocs"),
>> because the comments do not match the actual prototypes in the code.
>>
>> This issue didn't exist in 3.9. It may we worth fixing in 3.10
>> (if it's not too late).
> I think it's way late. Besides, all of this is already fixed in -next
> trees.
Cool! That's good news :)
>
>
>> @@ -4153,6 +4153,7 @@ void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
>>   * cfg80211_crit_proto_stopped() - indicate critical protocol stopped by driver.
>>   *
>>   * @wdev: the wireless device for which critical protocol is stopped.
>> + * @gfp: the type of memory to allocate (see kmalloc).
> This is also wrong, the allocation flags don't really change the *type*
> of memory, but only *how* it is allocated.
I agree, but I chose to stick to the description I found 5 times in
include/linux/slab.h. I shouldn't have followed bad examples...

I'll submit another patch ;)

Thanks again,

Michael.

-- 
Michael Opdenacker, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
+33 484 258 098


^ permalink raw reply

* [PATCH V2 6/9] brcmfmac: tag packet in the netdev transmit callback
From: Arend van Spriel @ 2013-06-26 12:35 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless, Arend van Spriel
In-Reply-To: <1372249222-4858-7-git-send-email-arend@broadcom.com>

Transmit packets needs to be tagged in order to receive a tx status
feedback from the firmware. Determine the tag in the netdev transmit
callback instead of determining the tag just before transfer to the
device. This reduces the number of exception flows and hence makes
the driver code simpler.

Reviewed-by: Hante Meuleman <meuleman@broadcom.com>
Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com>
Signed-off-by: Arend van Spriel <arend@broadcom.com>
---
Found a checkpatch warning after sending the patch. This patch
replaces the previous patch with message ID:

Message-ID: <1372249222-4858-7-git-send-email-arend@broadcom.com>

---
 drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c |  130 ++++++++------------
 1 file changed, 48 insertions(+), 82 deletions(-)

diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index e4fd13a..44b3192 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -1575,21 +1575,14 @@ int brcmf_fws_hdrpull(struct brcmf_pub *drvr, int ifidx, s16 signal_len,
 	return 0;
 }
 
-static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
+static void brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
 				   struct sk_buff *p)
 {
 	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
 	struct brcmf_fws_mac_descriptor *entry = skcb->mac;
-	int rc = 0;
-	bool first_time;
-	int hslot = BRCMF_FWS_HANGER_MAXITEMS;
-	u8 free_ctr;
 	u8 flags;
 
-	first_time = skcb->state != BRCMF_FWS_SKBSTATE_SUPPRESSED;
-
 	brcmf_skb_if_flags_set_field(p, TRANSMIT, 1);
-	brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
 	brcmf_skb_htod_tag_set_field(p, GENERATION, entry->generation);
 	flags = BRCMF_FWS_HTOD_FLAG_PKTFROMHOST;
 	if (brcmf_skb_if_flags_get_field(p, REQUESTED)) {
@@ -1600,80 +1593,36 @@ static int brcmf_fws_precommit_skb(struct brcmf_fws_info *fws, int fifo,
 		flags |= BRCMF_FWS_HTOD_FLAG_PKT_REQUESTED;
 	}
 	brcmf_skb_htod_tag_set_field(p, FLAGS, flags);
-	if (first_time) {
-		/* obtaining free slot may fail, but that will be caught
-		 * by the hanger push. This assures the packet has a BDC
-		 * header upon return.
-		 */
-		hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
-		free_ctr = entry->seq[fifo];
-		brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
-		brcmf_skb_htod_tag_set_field(p, FREERUN, free_ctr);
-		rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
-		if (rc)
-			brcmf_err("hanger push failed: rc=%d\n", rc);
-	}
-
-	if (rc == 0)
-		brcmf_fws_hdrpush(fws, p);
-
-	return rc;
+	brcmf_fws_hdrpush(fws, p);
 }
 
-static void
-brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
-		       struct sk_buff *skb, int fifo)
+static void brcmf_fws_rollback_toq(struct brcmf_fws_info *fws,
+				   struct sk_buff *skb, int fifo)
 {
-	/*
-	put the packet back to the head of queue
-
-	- suppressed packet goes back to suppress sub-queue
-	- pull out the header, if new or delayed packet
-
-	Note: hslot is used only when header removal is done.
-	*/
 	struct brcmf_fws_mac_descriptor *entry;
-	enum brcmf_fws_skb_state state;
 	struct sk_buff *pktout;
+	int qidx, hslot;
 	int rc = 0;
-	int hslot;
 
-	state = brcmf_skbcb(skb)->state;
 	entry = brcmf_skbcb(skb)->mac;
-	hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
-
-	if (entry != NULL) {
-		if (state == BRCMF_FWS_SKBSTATE_SUPPRESSED) {
-			/* wl-header is saved for suppressed packets */
-			pktout = brcmu_pktq_penq_head(&entry->psq, 2 * fifo + 1,
-						      skb);
-			if (pktout == NULL) {
-				brcmf_err("suppress queue full\n");
-				rc = -ENOSPC;
-			}
-		} else {
-			/* delay-q packets are going to delay-q */
-			pktout = brcmu_pktq_penq_head(&entry->psq,
-						      2 * fifo, skb);
-			if (pktout == NULL) {
-				brcmf_err("delay queue full\n");
-				rc = -ENOSPC;
-			}
-
-			/* free the hanger slot */
-			brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &pktout,
-						true);
-
-			/* decrement sequence count */
-			entry->seq[fifo]--;
+	if (entry->occupied) {
+		qidx = 2 * fifo;
+		if (brcmf_skbcb(skb)->state == BRCMF_FWS_SKBSTATE_SUPPRESSED)
+			qidx++;
+
+		pktout = brcmu_pktq_penq_head(&entry->psq, qidx, skb);
+		if (pktout == NULL) {
+			brcmf_err("%s queue %d full\n", entry->name, qidx);
+			rc = -ENOSPC;
 		}
 	} else {
-		brcmf_err("no mac entry linked\n");
+		brcmf_err("%s entry removed\n", entry->name);
 		rc = -ENOENT;
 	}
 
 	if (rc) {
 		fws->stats.rollback_failed++;
+		hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
 		brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED,
 				      hslot, 0);
 	} else {
@@ -1720,15 +1669,10 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
 	if (IS_ERR(entry))
 		return PTR_ERR(entry);
 
-	rc = brcmf_fws_precommit_skb(fws, fifo, skb);
-	if (rc < 0) {
-		fws->stats.generic_error++;
-		goto rollback;
-	}
-
-	brcmf_dbg(DATA, "%s flags %X htod %X\n", entry->name, skcb->if_flags,
-		  skcb->htod);
+	brcmf_fws_precommit_skb(fws, fifo, skb);
 	rc = brcmf_bus_txdata(bus, skb);
+	brcmf_dbg(DATA, "%s flags %X htod %X bus_tx %d\n", entry->name,
+		  skcb->if_flags, skcb->htod, rc);
 	if (rc < 0) {
 		brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
 		goto rollback;
@@ -1737,7 +1681,6 @@ static int brcmf_fws_commit_skb(struct brcmf_fws_info *fws, int fifo,
 	entry->transit_count++;
 	if (entry->suppressed)
 		entry->suppr_transit_count++;
-	entry->seq[fifo]++;
 	fws->stats.pkt2bus++;
 	fws->stats.send_pkts[fifo]++;
 	if (brcmf_skb_if_flags_get_field(skb, REQUESTED))
@@ -1750,6 +1693,24 @@ rollback:
 	return rc;
 }
 
+static int brcmf_fws_assign_htod(struct brcmf_fws_info *fws, struct sk_buff *p,
+				  int fifo)
+{
+	struct brcmf_skbuff_cb *skcb = brcmf_skbcb(p);
+	int rc, hslot;
+
+	hslot = brcmf_fws_hanger_get_free_slot(&fws->hanger);
+	brcmf_skb_htod_tag_set_field(p, HSLOT, hslot);
+	brcmf_skb_htod_tag_set_field(p, FREERUN, skcb->mac->seq[fifo]);
+	brcmf_skb_htod_tag_set_field(p, FIFO, fifo);
+	rc = brcmf_fws_hanger_pushpkt(&fws->hanger, p, hslot);
+	if (!rc)
+		skcb->mac->seq[fifo]++;
+	else
+		fws->stats.generic_error++;
+	return rc;
+}
+
 int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
 {
 	struct brcmf_pub *drvr = ifp->drvr;
@@ -1778,22 +1739,27 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
 
 	/* set control buffer information */
 	skcb->if_flags = 0;
-	skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
 	skcb->state = BRCMF_FWS_SKBSTATE_NEW;
 	brcmf_skb_if_flags_set_field(skb, INDEX, ifp->ifidx);
 	if (!multicast)
 		fifo = brcmf_fws_prio2fifo[skb->priority];
 
-	brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name,
-		  eh->h_dest, multicast, fifo);
-
 	brcmf_fws_lock(drvr, flags);
-	brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
 	if (fifo != BRCMF_FWS_FIFO_AC_BE && fifo < BRCMF_FWS_FIFO_BCMC)
 		fws->borrow_defer_timestamp = jiffies +
 					      BRCMF_FWS_BORROW_DEFER_PERIOD;
+
+	skcb->mac = brcmf_fws_macdesc_find(fws, ifp, eh->h_dest);
+	brcmf_dbg(DATA, "%s mac %pM multi %d fifo %d\n", skcb->mac->name,
+		  eh->h_dest, multicast, fifo);
+	if (!brcmf_fws_assign_htod(fws, skb, fifo)) {
+		brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_DELAYED, fifo, skb);
+		brcmf_fws_schedule_deq(fws);
+	} else {
+		brcmf_err("drop skb: no hanger slot\n");
+		brcmu_pkt_buf_free_skb(skb);
+	}
 	brcmf_fws_unlock(drvr, flags);
-	brcmf_fws_schedule_deq(fws);
 	return 0;
 }
 
-- 
1.7.10.4



^ permalink raw reply related

* Re: pull request: bluetooth 2013-06-23
From: Gustavo Padovan @ 2013-06-26 12:47 UTC (permalink / raw)
  To: Pavel Machek
  Cc: Marcel Holtmann, linville, linux-wireless, linux-bluetooth,
	linux-kernel, Rafael J. Wysocki
In-Reply-To: <20130626115255.GA7940@amd.pavel.ucw.cz>

* Pavel Machek <pavel@ucw.cz> [2013-06-26 13:52:55 +0200]:

> On Tue 2013-06-25 22:00:39, Gustavo Padovan wrote:
> > Hi Marcel,
> > 
> > * Marcel Holtmann <marcel@holtmann.org> [2013-06-25 13:49:19 -0700]:
> > 
> > > Hi Pavel,
> > > 
> > > >> Jaganath Kanakkassery (1):
> > > >>      Bluetooth: Fix invalid length check in l2cap_information_rsp()
> > > > 
> > > > Could we add the "3.10 vs. thinkpad x60" patch that fixes regression?
> > > > It is from Johan Hedberg…
> > > 
> > > that one went into net-next tree. It is scheduled for 3.11 right now.
> > > 
> > > After 3.10 is out, maybe it can go into -stable, but otherwise I think it is bit late now. Unless someone wants to cherry-pick it.
> > 
> > That patch is actually in 3.10 already, it was included in the last pull
> > request and John took it to wireless.git.
> 
> Is it? I tried pulling yesterday (some updates) and today (no
> changes), am on:

Dave already pulled it so it should land in mainline anytime soon.

	Gustavo

^ permalink raw reply

* rtl8192cu: slow path warning
From: Richard GENOUD @ 2013-06-26 14:22 UTC (permalink / raw)
  To: Larry Finger; +Cc: Chaoming Li, John W. Linville, linux-wireless, linux-kernel
In-Reply-To: <20130611123814.GA9854@lnx-rg>

On [mar., 11.06.2013 14:38:15], Richard GENOUD wrote:
> Hi,
> 
> I've got an usb wireless adapter TP-Link TL-WN725N
> http://www.tp-link.com/ca/products/details/?categoryid=241&model=TL-WN725N
> It is based on the rtl8192cu chip.
> I'm running a recent kernel (3.10-rc5) on a arm-based board (at91sam9g35-ek).
> and last linux-firmwares (2892af0)
> 
> Here is the log:
> ***Insert the TP-Link key
> [   22.710937] usb 1-2.3: new high-speed USB device number 3 using atmel-ehci
> [   22.828125] rtl8192cu: Chip version 0x10
> [   22.921875] rtl8192cu: MAC address: a0:f3:c1:1a:28:5f
> [   22.929687] rtl8192cu: Board Type 0
> [   22.929687] rtlwifi: rx_max_size 15360, rx_urb_num 8, in_ep 1
> [   22.937500] rtl8192cu: Loading firmware rtlwifi/rtl8192cufw.bin
> [   22.953125] ieee80211 phy0: Selected rate control algorithm 'rtl_rc'
> [   22.968750] rtlwifi: wireless switch is on
> 
> # ip link set wlan0 up
> [   34.656250] rtl8192cu: MAC auto ON okay!
> [   34.695312] rtl8192cu: Tx queue select: 0x05
> # iw dev wlan0 scan
> BSS 00:1c:10:69:90:fe (on wlan0)
> 	TSF: 1046528539 usec (0d, 00:17:26)
> 	freq: 2412
> 	beacon interval: 100
> 	capability: ESS ShortSlotTime (0x0401)
> 	signal: -58.00 dBm
> 	last seen: 500 ms ago
> 	Information elements from Probe Response frame:
> 	SSID: test
> 	Supported rates: 1.0* 2.0* 5.5* 11.0* 6.0 9.0 12.0 18.0 
> 	DS Parameter set: channel 1
> 	TIM: DTIM Count 1 DTIM Period 2 Bitmap Control 0x0 Bitmap[0] 0x0
> 	ERP: Barker_Preamble_Mode
> 	Extended supported rates: 24.0 36.0 48.0 54.0 
> # iw wlan0 connect test
> [   51.851562] wlan0: authenticate with 00:1c:10:69:90:fe
> [   51.859375] wlan0: Allocated STA 00:1c:10:69:90:fe
> [   51.867187] wlan0: Inserted STA 00:1c:10:69:90:fe
> [   51.875000] wlan0: direct probe to 00:1c:10:69:90:fe (try 1/3)
> # [   52.078125] wlan0: direct probe to 00:1c:10:69:90:fe (try 2/3)
> [   52.281250] wlan0: direct probe to 00:1c:10:69:90:fe (try 3/3)
> [   52.484375] wlan0: authentication with 00:1c:10:69:90:fe timed out
> [   52.484375] wlan0: Removed STA 00:1c:10:69:90:fe
> [   52.492187] wlan0: Destroyed STA 00:1c:10:69:90:fe
> 
> # iw wlan0 connect test
> # [   70.718750] wlan0: authenticate with 00:1c:10:69:90:fe
> [   70.718750] wlan0: Allocated STA 00:1c:10:69:90:fe
> [   70.742187] wlan0: Inserted STA 00:1c:10:69:90:fe
> [   70.742187] wlan0: send auth to 00:1c:10:69:90:fe (try 1/3)
> [   70.757812] wlan0: authenticated
> [   70.757812] wlan0: moving STA 00:1c:10:69:90:fe to state 2
> [   70.765625] rtl8192cu 1-2.3:1.0 wlan0: disabling HT as WMM/QoS is not supported by the AP
> [   70.773437] rtl8192cu 1-2.3:1.0 wlan0: disabling VHT as WMM/QoS is not supported by the AP
> [   70.789062] wlan0: associate with 00:1c:10:69:90:fe (try 1/3)
> [   70.804687] wlan0: RX AssocResp from 00:1c:10:69:90:fe (capab=0x401 status=0 aid=1)
> [   70.812500] wlan0: moving STA 00:1c:10:69:90:fe to state 3
> [   70.820312] wlan0: moving STA 00:1c:10:69:90:fe to state 4
> [   70.828125] wlan0: associated
> [   71.187500] ------------[ cut here ]------------
> [   71.187500] WARNING: at kernel/workqueue.c:1365 __queue_work+0x180/0x1f8()
> [   71.187500] CPU: 0 PID: 593 Comm: kworker/0:2 Not tainted 3.10.0-rc5-00133-g691a986 #6
> [   71.187500] Workqueue: rtl92c_usb rtl_watchdog_wq_callback
> [   71.187500] [<c000d2a0>] (unwind_backtrace+0x0/0xf0) from [<c000ba34>] (show_stack+0x10/0x14)
> [   71.187500] [<c000ba34>] (show_stack+0x10/0x14) from [<c00150fc>] (warn_slowpath_common+0x48/0x64)
> [   71.187500] [<c00150fc>] (warn_slowpath_common+0x48/0x64) from [<c00151e0>] (warn_slowpath_null+0x1c/0x24)
> [   71.187500] [<c00151e0>] (warn_slowpath_null+0x1c/0x24) from [<c0029878>] (__queue_work+0x180/0x1f8)
> [   71.187500] [<c0029878>] (__queue_work+0x180/0x1f8) from [<c0029ee8>] (queue_work_on+0x44/0x50)
> [   71.187500] [<c0029ee8>] (queue_work_on+0x44/0x50) from [<c01fd850>] (rtl_watchdog_wq_callback+0x290/0x4e0)
> [   71.187500] [<c01fd850>] (rtl_watchdog_wq_callback+0x290/0x4e0) from [<c002a138>] (process_one_work+0x110/0x358)
> [   71.187500] [<c002a138>] (process_one_work+0x110/0x358) from [<c002a728>] (worker_thread+0xf4/0x308)
> [   71.187500] [<c002a728>] (worker_thread+0xf4/0x308) from [<c002f8b4>] (kthread+0xa4/0xb0)
> [   71.187500] [<c002f8b4>] (kthread+0xa4/0xb0) from [<c00091b0>] (ret_from_fork+0x14/0x24)
> [   71.187500] ---[ end trace 5f274d456b3a4c7f ]---
Hi,

Using 3.10-rc7, I'm still seeing the warning, BUT ONLY on the first
connection.

[   40.312500] usb 2-2: default language 0x0409
[   40.312500] usb 2-2: udev 2, busnum 2, minor = 129
[   40.320312] usb 2-2: New USB device found, idVendor=0bda, idProduct=8176
[   40.328125] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[   40.328125] usb 2-2: Product: 802.11n WLAN Adapter
[   40.335937] usb 2-2: Manufacturer: Realtek
[   40.343750] usb 2-2: SerialNumber: 00e04c000001
[   40.343750] usb 2-2: usb_probe_device
[   40.351562] usb 2-2: configuration #1 chosen from 1 choice
[   40.351562] usb 2-2: adding 2-2:1.0 (config #1, interface 0)
[   40.500000] cfg80211: Calling CRDA to update world regulatory domain
[   40.648437] rtl8192cu 2-2:1.0: usb_probe_interface
[   40.656250] rtl8192cu 2-2:1.0: usb_probe_interface - got id
[   40.664062] rtl8192cu: Chip version 0x10
[   40.757812] rtl8192cu: MAC address: a0:f3:c1:1e:02:a0
[   40.765625] rtl8192cu: Board Type 0
[   40.773437] rtlwifi: rx_max_size 15360, rx_urb_num 8, in_ep 1
[   40.773437] rtl8192cu: Loading firmware rtlwifi/rtl8192cufw.bin
[   40.781250] usbcore: registered new interface driver rtl8192cu
[   40.835937] ieee80211 phy0: Selected rate control algorithm 'rtl_rc'
[   40.843750] rtlwifi: wireless switch is on
# ip link set wlan0 up
[   59.921875] rtl8192cu: MAC auto ON okay!
[   59.960937] rtl8192cu: Tx queue select: 0x05
# iw wlan0 connect test
[   75.390625] wlan0: authenticate with f8:1a:67:1a:df:88
[   75.421875] wlan0: send auth to f8:1a:67:1a:df:88 (try 1/3)
[   75.437500] wlan0: authenticated
[   75.453125] wlan0: associate with f8:1a:67:1a:df:88 (try 1/3)
[   75.460937] wlan0: RX AssocResp from f8:1a:67:1a:df:88 (capab=0x401 status=0 aid=2)
[   75.468750] wlan0: associated
[   76.375000] ------------[ cut here ]------------
[   76.375000] WARNING: at kernel/workqueue.c:1365 __queue_work+0x168/0x200()
[   76.375000] Modules linked in: rtl8192cu rtl8192c_common rtlwifi mac80211 cfg80211 rfkill ehci_atmel ehci_hcd atmel_usba_udc udc_core ohci_hcd
[   76.375000] CPU: 0 PID: 308 Comm: kworker/0:1 Not tainted 3.10.0-rc7 #36
[   76.375000] Workqueue: rtl92c_usb rtl_watchdog_wq_callback [rtlwifi]
[   76.375000] [<c000d9bc>] (unwind_backtrace+0x0/0xf0) from [<c000b9ec>] (show_stack+0x10/0x14)
[   76.375000] [<c000b9ec>] (show_stack+0x10/0x14) from [<c0015c00>] (warn_slowpath_common+0x4c/0x68)
[   76.375000] [<c0015c00>] (warn_slowpath_common+0x4c/0x68) from [<c0015c38>] (warn_slowpath_null+0x1c/0x24)
[   76.375000] [<c0015c38>] (warn_slowpath_null+0x1c/0x24) from [<c0029e40>] (__queue_work+0x168/0x200)
[   76.375000] [<c0029e40>] (__queue_work+0x168/0x200) from [<c0029f2c>] (queue_work_on+0x44/0x50)
[   76.375000] [<c0029f2c>] (queue_work_on+0x44/0x50) from [<bf09bb54>] (rtl_watchdog_wq_callback+0x320/0x404 [rtlwifi])
[   76.375000] [<bf09bb54>] (rtl_watchdog_wq_callback+0x320/0x404 [rtlwifi]) from [<c002b168>] (process_one_work+0x10c/0x354)
[   76.375000] [<c002b168>] (process_one_work+0x10c/0x354) from [<c002b784>] (worker_thread+0x130/0x380)
[   76.375000] [<c002b784>] (worker_thread+0x130/0x380) from [<c0030330>] (kthread+0xa4/0xb0)
[   76.375000] [<c0030330>] (kthread+0xa4/0xb0) from [<c00092f0>] (ret_from_fork+0x14/0x24)
[   76.375000] ---[ end trace e116b4b3d671f3d2 ]---

# iw wlan0 disconnect 
[   86.289062] wlan0: deauthenticating from f8:1a:67:1a:df:88 by local choice (reason=3)
[   86.312500] cfg80211: Calling CRDA to update world regulatory domain
# iw wlan0 connect test
[   91.671875] wlan0: authenticate with f8:1a:67:1a:df:88
[   91.687500] wlan0: send auth to f8:1a:67:1a:df:88 (try 1/3)
[   91.695312] wlan0: authenticated
[   91.710937] wlan0: associate with f8:1a:67:1a:df:88 (try 1/3)
[   91.718750] wlan0: RX AssocResp from f8:1a:67:1a:df:88 (capab=0x401 status=0 aid=1)
[   91.726562] wlan0: associated

# iw wlan0 disconnect 
[   98.929687] wlan0: deauthenticating from f8:1a:67:1a:df:88 by local choice (reason=3)
[   98.953125] cfg80211: Calling CRDA to update world regulatory domain
# iw wlan0 connect test
[  101.554687] wlan0: authenticate with f8:1a:67:1a:df:88
[  101.578125] wlan0: send auth to f8:1a:67:1a:df:88 (try 1/3)
[  101.585937] wlan0: authenticated
[  101.593750] wlan0: associate with f8:1a:67:1a:df:88 (try 1/3)
[  101.625000] wlan0: RX AssocResp from f8:1a:67:1a:df:88 (capab=0x401 status=0 aid=1)
[  101.632812] wlan0: associated
[  114.523437] wlan0: Connection to AP f8:1a:67:1a:df:88 lost
[  114.546875] cfg80211: Calling CRDA to update world regulatory domain


Best regards,
Richard.

^ permalink raw reply

* Re: [PATCH v4 1/2] cfg80211/nl80211: rename packet pattern related structures and enums
From: Johannes Berg @ 2013-06-26 15:04 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-wireless, Luis R. Rodriguez, Jouni Malinen,
	Vasanthakumar Thiagarajan, Senthil Balasubramanian,
	Luciano Coelho, Amitkumar Karwar
In-Reply-To: <1372212237-5687-1-git-send-email-bzhao@marvell.com>

On Tue, 2013-06-25 at 19:03 -0700, Bing Zhao wrote:
> From: Amitkumar Karwar <akarwar@marvell.com>
> 
> Currently packet patterns and it's enum/structures are used only
> for WoWLAN feature. As we intend to reuse them for new feature
> packet coalesce, they are renamed in this patch.

This looks good, applied.

johannes


^ permalink raw reply

* Re: [PATCH v4 2/2] cfg80211/nl80211: Add packet coalesce support
From: Johannes Berg @ 2013-06-26 15:13 UTC (permalink / raw)
  To: Bing Zhao
  Cc: linux-wireless, Luis R. Rodriguez, Jouni Malinen,
	Vasanthakumar Thiagarajan, Senthil Balasubramanian,
	Luciano Coelho, Amitkumar Karwar
In-Reply-To: <1372212237-5687-2-git-send-email-bzhao@marvell.com>

On Tue, 2013-06-25 at 19:03 -0700, Bing Zhao wrote:

> +/**
> + * struct cfg80211_coalesce - Packet coalescing settings
> + *
> + * This structure defines coalescing settings.
> + * @rules: array of coalesce rules
> + * @n_rules: number of rules
> + */
> +struct cfg80211_coalesce {
> +	struct cfg80211_coalesce_rules **rules;

I don't really see why this should be a double pointer? The
coalesce_rules struct is small enough that you could just allocate an
array of that, no?

>  /**
> + * struct wiphy_coalesce_support - coalesce support data
> + * @n_rules: maximum number of coalesce rules
> + * @n_patterns: number of supported patterns
> + *	(see nl80211.h for the pattern definition)
> + * @pattern_max_len: maximum length of each pattern
> + * @pattern_min_len: minimum length of each pattern
> + * @max_pkt_offset: maximum Rx packet offset

Should there be any limits on the timer? Will the firmware actually work
if I set it to (useless) values like 2^32-1 msecs?

Also -- is n_patterns per rule, or global? It seems global, but in the
rules you can have multiple patterns per rule?

> +/**
>   * enum nl80211_commands - supported nl80211 commands
>   *
>   * @NL80211_CMD_UNSPEC: unspecified command to catch errors
> @@ -648,6 +673,10 @@
>   * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can
>   *	return back to normal.
>   *
> + * @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules.
> + *
> + * @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules.

I'd prefer no space between the two :)

> +struct nl80211_coalesce_rule_support {
> +	__u32 max_rules;
> +	struct nl80211_pattern_support pat;

(timing stuff would also go here, I suppose)

> +static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
> +				       struct nlattr *rule,
> +				       struct cfg80211_coalesce_rules *new_rule)
> +{
> +	int err, i;
> +	const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
> +	struct nlattr *tb[NUM_NL80211_ATTR_COALESCE_RULE], *pat;
> +	int rem, pat_len, mask_len, pkt_offset, n_patterns = 0;
> +	struct nlattr *pat_tb[NUM_NL80211_PKTPAT];
> +
> +	err = nla_parse(tb, NL80211_ATTR_COALESCE_RULE_MAX, nla_data(rule),
> +			nla_len(rule), nl80211_coalesce_policy);
> +	if (err)
> +		return err;
> +
> +	memset(new_rule, 0, sizeof(*new_rule));
> +	new_rule->delay = nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_DELAY]);

no check that it actually exists?

> +	new_rule->condition =
> +		nla_get_u32(tb[NL80211_ATTR_COALESCE_RULE_CONDITION]);

ditto. easy to crash, no?

> +static int nl80211_set_coalesce(struct sk_buff *skb, struct genl_info *info)
> +{
> +	struct cfg80211_registered_device *rdev = info->user_ptr[0];
> +	const struct wiphy_coalesce_support *coalesce = rdev->wiphy.coalesce;
> +	struct cfg80211_coalesce_rules new_rule = {};
> +	struct cfg80211_coalesce_rules *nrule;
> +	struct cfg80211_coalesce *new_coalesce;
> +	int err, rem_rule;
> +	struct nlattr *rule;
> +
> +	if (!rdev->wiphy.coalesce)
> +		return -EOPNOTSUPP;
> +	if (!rdev->ops->set_coalesce)
> +		return -EOPNOTSUPP;

could combine the conditions :)

> +	new_coalesce = kzalloc(sizeof(*new_coalesce), GFP_KERNEL);
> +	new_coalesce->rules = kcalloc(coalesce->n_rules,
> +					sizeof(void *), GFP_KERNEL);

*kaboom*

> +	cfg80211_rdev_free_coalesce(rdev->coalesce);
> +	rdev->coalesce = new_coalesce;
> +
> +	err = rdev->ops->set_coalesce(&rdev->wiphy, rdev->coalesce);
> +	if (err)
> +		goto error;
> +
> +	return 0;
> +error:
> +	cfg80211_rdev_free_coalesce(new_coalesce);

*kaboom* if it ever fails, and you then do get_coalesce -- should
probably assign only after setting the new value successfully?

johannes


^ permalink raw reply

* [PATCH] iw: reorder some code in iw_connect to avoid a potential memory leak
From: John W. Linville @ 2013-06-26 15:07 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, John W. Linville

From: "John W. Linville" <linville@tuxdriver.com>

>From Coverity run on version 3.10:

iw-3.10/connect.c:104:leaked_storage –
	Variable "conn_argv" going out of scope leaks the storage it points to.

Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
 connect.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/connect.c b/connect.c
index 74e4578..fb3b2fe 100644
--- a/connect.c
+++ b/connect.c
@@ -94,15 +94,15 @@ static int iw_connect(struct nl80211_state *state, struct nl_cb *cb,
 		argv++;
 	}
 
+	err = __prepare_listen_events(state);
+	if (err)
+		return err;
+
 	conn_argc = 3 + argc;
 	conn_argv = calloc(conn_argc, sizeof(*conn_argv));
 	if (!conn_argv)
 		return -ENOMEM;
 
-	err = __prepare_listen_events(state);
-	if (err)
-		return err;
-
 	conn_argv[0] = dev;
 	conn_argv[1] = "connect";
 	conn_argv[2] = "establish";
-- 
1.8.1.4


^ permalink raw reply related

* [PATCH] iw: fix incorrect bit shifting in print_ht_mcs
From: John W. Linville @ 2013-06-26 15:07 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, John W. Linville

From: "John W. Linville" <linville@tuxdriver.com>

>From a Coverity run on version 3.10:

iw-3.10/util.c:569:result_independent_of_operands –
	"mcs[10] >> 8" is 0 regardless of the values of its operands. This occurs as the bitwise first operand of '&'.

This seems more like what was intended...

Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
 util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/util.c b/util.c
index d8b76ee..e3d0c27 100644
--- a/util.c
+++ b/util.c
@@ -574,7 +574,7 @@ void print_ht_mcs(const __u8 *mcs)
 	unsigned int tx_max_num_spatial_streams, max_rx_supp_data_rate;
 	bool tx_mcs_set_defined, tx_mcs_set_equal, tx_unequal_modulation;
 
-	max_rx_supp_data_rate = ((mcs[10] >> 8) & ((mcs[11] & 0x3) << 8));
+	max_rx_supp_data_rate = (mcs[10] & ((mcs[11] & 0x3) << 8));
 	tx_mcs_set_defined = !!(mcs[12] & (1 << 0));
 	tx_mcs_set_equal = !(mcs[12] & (1 << 1));
 	tx_max_num_spatial_streams = ((mcs[12] >> 2) & 3) + 1;
-- 
1.8.1.4


^ permalink raw reply related

* Re: [PATCH v12 1/2] cfg80211: add 'flags' to cfg80211_rx_mgmt()
From: Johannes Berg @ 2013-06-26 15:17 UTC (permalink / raw)
  To: Vladimir Kondratiev
  Cc: linux-wireless, Luis R . Rodriguez, John W . Linville,
	Jouni Malinen, Arend van Spriel, Ilan Peer
In-Reply-To: <1372167756-17928-2-git-send-email-qca_vkondrat@qca.qualcomm.com>

On Tue, 2013-06-25 at 16:42 +0300, Vladimir Kondratiev wrote:

> +++ b/include/uapi/linux/nl80211.h
> @@ -1436,6 +1436,8 @@ enum nl80211_commands {
>   *	allowed to be used with the first @NL80211_CMD_SET_STATION command to
>   *	update a TDLS peer STA entry.
>   *
> + * @NL80211_ATTR_RXMGMT_FLAGS: flags for cfg80211_rx_mgmt, u32

That's a little insufficient, don't you think? cfg80211_rx_mgmt()
doesn't even really make sense to userspace, you should point to the
nl80211 event and maybe even reference this new attribute in the command
description.

> +/**
> + * enum nl80211_rxmgmt_flags - flags for cfg80211_rx_mgmt
> + *
> + * @NL80211_RXMGMT_FLAG_REPLIED: frame was replied by device/driver.
> + */
> +enum nl80211_rxmgmt_flags {
> +	NL80211_RXMGMT_FLAG_REPLIED = (1 << 0),

No need for parentheses.

>  bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_mbm,
> -		      const u8 *buf, size_t len, gfp_t gfp)
> +		      const u8 *buf, size_t len, u32 flags, gfp_t gfp)

I'm starting to wonder if this function has too many arguments?
Thoughts? Maybe it should get a struct or so? Not really sure ... could
just be a worthwhile cleanup afterwards?

johannes


^ permalink raw reply

* Re: [PATCH] iw: fix incorrect bit shifting in print_ht_mcs
From: Johannes Berg @ 2013-06-26 15:24 UTC (permalink / raw)
  To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <1372259260-7061-1-git-send-email-linville@tuxdriver.com>

On Wed, 2013-06-26 at 11:07 -0400, John W. Linville wrote:
> From: "John W. Linville" <linville@tuxdriver.com>
> 
> From a Coverity run on version 3.10:
> 
> iw-3.10/util.c:569:result_independent_of_operands –
> 	"mcs[10] >> 8" is 0 regardless of the values of its operands. This occurs as the bitwise first operand of '&'.
> 
> This seems more like what was intended...

Applied both, thanks.

johannes


^ permalink raw reply

* Re: [PATCH v12 2/2] cfg80211: P2P find phase offload
From: Johannes Berg @ 2013-06-26 15:31 UTC (permalink / raw)
  To: Vladimir Kondratiev
  Cc: linux-wireless, Luis R . Rodriguez, John W . Linville,
	Jouni Malinen, Arend van Spriel, Ilan Peer
In-Reply-To: <1372167756-17928-3-git-send-email-qca_vkondrat@qca.qualcomm.com>

Looking good ... :)

On Tue, 2013-06-25 at 16:42 +0300, Vladimir Kondratiev wrote:

> + * @channels: channels to operate on
> + *     may be NULL, in this case driver suppose to scan for all
> social
> + *     channels; or channel set should be non-empty (n_channels > 0)

Does that make sense, or should cfg80211 just build the channel list in
the case the user didn't specify anything, rather than leave it NULL? It
seems that every driver implementing it really needs the list, and
having multiple drivers create it seems wasteful?

> +static int nl80211_stop_p2p_find(struct sk_buff *skb, struct genl_info *info)
> +{
> +	struct cfg80211_registered_device *rdev = info->user_ptr[0];
> +	struct wireless_dev *wdev = info->user_ptr[1];
> +
> +	if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
> +		return -EOPNOTSUPP;
> +
> +	if (!rdev->ops->start_p2p_find || !rdev->ops->stop_p2p_find)
> +		return -EOPNOTSUPP;
> +
> +	rdev_stop_p2p_find(rdev, wdev);

You don't track whether this p2p find is ongoing, so userspace can abort
it many times. I think it would be worth documenting that, and also that
in that case cfg80211_p2p_find_notify_end() probably shouldn't be
called?

johannes


^ permalink raw reply

* Re: rtl8192cu: slow path warning
From: Larry Finger @ 2013-06-26 15:54 UTC (permalink / raw)
  To: Richard GENOUD
  Cc: Chaoming Li, John W. Linville, linux-wireless, linux-kernel
In-Reply-To: <20130626142241.GA13107@lnx-rg>

[-- Attachment #1: Type: text/plain, Size: 3743 bytes --]

On 06/26/2013 09:22 AM, Richard GENOUD wrote:
> Using 3.10-rc7, I'm still seeing the warning, BUT ONLY on the first
> connection.
>
> [   40.312500] usb 2-2: default language 0x0409
> [   40.312500] usb 2-2: udev 2, busnum 2, minor = 129
> [   40.320312] usb 2-2: New USB device found, idVendor=0bda, idProduct=8176
> [   40.328125] usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
> [   40.328125] usb 2-2: Product: 802.11n WLAN Adapter
> [   40.335937] usb 2-2: Manufacturer: Realtek
> [   40.343750] usb 2-2: SerialNumber: 00e04c000001
> [   40.343750] usb 2-2: usb_probe_device
> [   40.351562] usb 2-2: configuration #1 chosen from 1 choice
> [   40.351562] usb 2-2: adding 2-2:1.0 (config #1, interface 0)
> [   40.500000] cfg80211: Calling CRDA to update world regulatory domain
> [   40.648437] rtl8192cu 2-2:1.0: usb_probe_interface
> [   40.656250] rtl8192cu 2-2:1.0: usb_probe_interface - got id
> [   40.664062] rtl8192cu: Chip version 0x10
> [   40.757812] rtl8192cu: MAC address: a0:f3:c1:1e:02:a0
> [   40.765625] rtl8192cu: Board Type 0
> [   40.773437] rtlwifi: rx_max_size 15360, rx_urb_num 8, in_ep 1
> [   40.773437] rtl8192cu: Loading firmware rtlwifi/rtl8192cufw.bin
> [   40.781250] usbcore: registered new interface driver rtl8192cu
> [   40.835937] ieee80211 phy0: Selected rate control algorithm 'rtl_rc'
> [   40.843750] rtlwifi: wireless switch is on
> # ip link set wlan0 up
> [   59.921875] rtl8192cu: MAC auto ON okay!
> [   59.960937] rtl8192cu: Tx queue select: 0x05
> # iw wlan0 connect test
> [   75.390625] wlan0: authenticate with f8:1a:67:1a:df:88
> [   75.421875] wlan0: send auth to f8:1a:67:1a:df:88 (try 1/3)
> [   75.437500] wlan0: authenticated
> [   75.453125] wlan0: associate with f8:1a:67:1a:df:88 (try 1/3)
> [   75.460937] wlan0: RX AssocResp from f8:1a:67:1a:df:88 (capab=0x401 status=0 aid=2)
> [   75.468750] wlan0: associated
> [   76.375000] ------------[ cut here ]------------
> [   76.375000] WARNING: at kernel/workqueue.c:1365 __queue_work+0x168/0x200()
> [   76.375000] Modules linked in: rtl8192cu rtl8192c_common rtlwifi mac80211 cfg80211 rfkill ehci_atmel ehci_hcd atmel_usba_udc udc_core ohci_hcd
> [   76.375000] CPU: 0 PID: 308 Comm: kworker/0:1 Not tainted 3.10.0-rc7 #36
> [   76.375000] Workqueue: rtl92c_usb rtl_watchdog_wq_callback [rtlwifi]
> [   76.375000] [<c000d9bc>] (unwind_backtrace+0x0/0xf0) from [<c000b9ec>] (show_stack+0x10/0x14)
> [   76.375000] [<c000b9ec>] (show_stack+0x10/0x14) from [<c0015c00>] (warn_slowpath_common+0x4c/0x68)
> [   76.375000] [<c0015c00>] (warn_slowpath_common+0x4c/0x68) from [<c0015c38>] (warn_slowpath_null+0x1c/0x24)
> [   76.375000] [<c0015c38>] (warn_slowpath_null+0x1c/0x24) from [<c0029e40>] (__queue_work+0x168/0x200)
> [   76.375000] [<c0029e40>] (__queue_work+0x168/0x200) from [<c0029f2c>] (queue_work_on+0x44/0x50)
> [   76.375000] [<c0029f2c>] (queue_work_on+0x44/0x50) from [<bf09bb54>] (rtl_watchdog_wq_callback+0x320/0x404 [rtlwifi])
> [   76.375000] [<bf09bb54>] (rtl_watchdog_wq_callback+0x320/0x404 [rtlwifi]) from [<c002b168>] (process_one_work+0x10c/0x354)
> [   76.375000] [<c002b168>] (process_one_work+0x10c/0x354) from [<c002b784>] (worker_thread+0x130/0x380)
> [   76.375000] [<c002b784>] (worker_thread+0x130/0x380) from [<c0030330>] (kthread+0xa4/0xb0)
> [   76.375000] [<c0030330>] (kthread+0xa4/0xb0) from [<c00092f0>] (ret_from_fork+0x14/0x24)
> [   76.375000] ---[ end trace e116b4b3d671f3d2 ]---

The WARNING is the result of a workqueue not being initialized for the USB driver.

Please try the attached patch. As you have posted on a public mailing list, May 
I assume that it will be OK to use your address in Reported-by/Tested-by lines 
in the patch submission?

Thanks,

Larry


[-- Attachment #2: rtl8192cu_init_work --]
[-- Type: text/plain, Size: 1754 bytes --]

Index: wireless-testing-save/drivers/net/wireless/rtlwifi/pci.c
===================================================================
--- wireless-testing-save.orig/drivers/net/wireless/rtlwifi/pci.c
+++ wireless-testing-save/drivers/net/wireless/rtlwifi/pci.c
@@ -1008,7 +1008,7 @@ static void _rtl_pci_prepare_bcn_tasklet
 	return;
 }
 
-static void rtl_lps_change_work_callback(struct work_struct *work)
+void rtl_lps_change_work_callback(struct work_struct *work)
 {
 	struct rtl_works *rtlworks =
 	    container_of(work, struct rtl_works, lps_change_work);
Index: wireless-testing-save/drivers/net/wireless/rtlwifi/ps.h
===================================================================
--- wireless-testing-save.orig/drivers/net/wireless/rtlwifi/ps.h
+++ wireless-testing-save/drivers/net/wireless/rtlwifi/ps.h
@@ -49,5 +49,6 @@ void rtl_swlps_rf_awake(struct ieee80211
 void rtl_swlps_rf_sleep(struct ieee80211_hw *hw);
 void rtl_p2p_ps_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
 void rtl_p2p_info(struct ieee80211_hw *hw, void *data, unsigned int len);
+void rtl_lps_change_work_callback(struct work_struct *work);
 
 #endif
Index: wireless-testing-save/drivers/net/wireless/rtlwifi/usb.c
===================================================================
--- wireless-testing-save.orig/drivers/net/wireless/rtlwifi/usb.c
+++ wireless-testing-save/drivers/net/wireless/rtlwifi/usb.c
@@ -1070,6 +1070,8 @@ int rtl_usb_probe(struct usb_interface *
 	spin_lock_init(&rtlpriv->locks.usb_lock);
 	INIT_WORK(&rtlpriv->works.fill_h2c_cmd,
 		  rtl_fill_h2c_cmd_work_callback);
+	INIT_WORK(&rtlpriv->works.lps_change_work,
+		  rtl_lps_change_work_callback);
 
 	rtlpriv->usb_data_index = 0;
 	init_completion(&rtlpriv->firmware_loading_complete);

^ permalink raw reply

* Re: Fwd: Re: TP-Link 8200ND - rtl8192cu module not loading / working
From: Larry Finger @ 2013-06-26 16:14 UTC (permalink / raw)
  To: shiki.biomernok; +Cc: linux-wireless
In-Reply-To: <51CAD0B8.3010303@gmail.com>

On 06/26/2013 06:30 AM, shiki.biomernok wrote:
> Hello everyone!
>
> CC'ing my original message that I sent to Larry.
> It's been a while, but I've been busy and I couldn't fiddle with the wireless
> device.
>
> Basically it's a 8192cu device. Larry suspected it's not, but I think he saw the
> advertisement displayed on top of the TP-Link page.
> I even mailed TP-Link, and here is the reply:
>
>     The chipset is Realtek RTL8192CU and you can download the driver
>     from
>
> http://www.realtek.com/downloads/downloadsView.aspx?Langid=1&PNid=21&PFid=48&Level=5&Conn=4&DownTypeID=3&GetDown=false&Downloads=true.
>
>     Thank you.
>
> Tested with many kernels, but none of them worked.
> Ubuntu 13.04 (both stock + updated), Fedora (Schrodinger-1), Fedora Beta
> (Schrodinger), openSUSE (normal+tumbleweed).
> I even tried the latest kernels since 3.10-rc4. (latest I tried is -rc7)
>
> Basically this device *should* work with the 8192cu driver, but it just won't.
> If you just plug it in, nothing happens.
> You have to first:
> $ modprobe 8192cu
> $ echo 2357 0100 > /sys/bus/usb/drivers/rtl8192cu/new_id
>
> Then it lights up, it shows up in NM-Applet. But it won't work.
> I tried enabling the realtek debug option at the kernel driver, but it didn't help.
> Even with that, I only see the authentication failed messages.
>
> Dmesg shows the errors: http://pastebin.com/QCfXYCZ1
>
>
> Hope you guys can come up with some tips/ideas.
> Ps.: I hope you don't mind the CC Larry.

No, that is what I told you to do.

A patch has been submitted to add that device to the USB_DEVICE table. It is 
included in the wireless-testing git tree, but it is not in the mainline code 
(yet). After that patch was applied, the device worked for that reported.

I noticed that you are getting an oops from iwlwifi, and an ehci-hcd error. Are 
you also exploring these problems?

If possible, could you use the wireless-testing repo? That will get you the 
latest code for all wireless drivers, and the USB code will match mainline.

Larry



^ permalink raw reply

* Re: [v3.10-rc2] iwlwifi regression
From: Jörg Otte @ 2013-06-26 16:16 UTC (permalink / raw)
  To: linux-wireless; +Cc: Linux Kernel Mailing List, Johannes Berg, Linus Torvalds
In-Reply-To: <CADDKRnBf4i8ZQ4EXC15Sa6z9CZ55w0vBDnXG26sjWgdO9zH45w@mail.gmail.com>

2013/5/25 Jörg Otte <jrg.otte@gmail.com>:
> If iwlwifi/iwldvm are built into the kernel (no loadable modules)
> following error is written to console and syslog since v3.10-rc:
>
> iwlwifi 0000:08:00.0: failed to load module iwldvm (error -38), is
> dynamic loading enabled?
>
> reverting
> commit 1618b2b02a3a0ee7a6863fed4b0d22e697e7e97c
> Author: Johannes Berg <johannes.berg@intel.com>
> Date:   Thu Apr 4 10:35:23 2013 +0200
>     iwlwifi: print warning on request_module failure
>
> fixes the problem for me.
>
> Jörg
>
> I'm not subscribed,please CC me in answeres

We have rc-7 now and it's still not fixed. What is the problem?

Thanks, Jörg

^ permalink raw reply

* Re: [v3.10-rc2] iwlwifi regression
From: Sedat Dilek @ 2013-06-26 16:37 UTC (permalink / raw)
  To: Jörg Otte
  Cc: linux-wireless, Linux Kernel Mailing List, Johannes Berg,
	Linus Torvalds
In-Reply-To: <CADDKRnCP_s2hL2wr8TsKeToNRt5nXF3NBYAqkmCCUPX8HbY_yQ@mail.gmail.com>

On Wed, Jun 26, 2013 at 6:16 PM, Jörg Otte <jrg.otte@gmail.com> wrote:
> 2013/5/25 Jörg Otte <jrg.otte@gmail.com>:
>> If iwlwifi/iwldvm are built into the kernel (no loadable modules)
>> following error is written to console and syslog since v3.10-rc:
>>
>> iwlwifi 0000:08:00.0: failed to load module iwldvm (error -38), is
>> dynamic loading enabled?
>>
>> reverting
>> commit 1618b2b02a3a0ee7a6863fed4b0d22e697e7e97c
>> Author: Johannes Berg <johannes.berg@intel.com>
>> Date:   Thu Apr 4 10:35:23 2013 +0200
>>     iwlwifi: print warning on request_module failure
>>
>> fixes the problem for me.
>>
>> Jörg
>>
>> I'm not subscribed,please CC me in answeres
>
> We have rc-7 now and it's still not fixed. What is the problem?
>

The patch is pending in wireless.git and is not in mainline, right.
AFAICS there was a recent pull request... so should be in rc8.

commit 8edf3fd6eb0649b0f19363baf23bca39c6fbdba4
"iwlwifi: don't print module loading error if not modular"

- Sedat -

http://git.kernel.org/cgit/linux/kernel/git/linville/wireless.git/commit/?id=8edf3fd6eb0649b0f19363baf23bca39c6fbdba4

> Thanks, Jörg
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox