aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm53xx/patches-4.4/810-USB-bcma-use-simpler-devm_gpiod_get.patch
blob: d8647a8e1550f6b9c10ff771dc9d3ee2db4649b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Date: Sat, 2 Jan 2016 11:26:28 +0100
Subject: [PATCH] USB: bcma: use simpler devm_gpiod_get
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
 drivers/usb/host/bcma-hcd.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

--- a/drivers/usb/host/bcma-hcd.c
+++ b/drivers/usb/host/bcma-hcd.c
@@ -568,8 +568,7 @@ static int bcma_hcd_probe(struct bcma_de
 	usb_dev->core = core;
 
 	if (core->dev.of_node)
-		usb_dev->gpio_desc = devm_get_gpiod_from_child(&core->dev, "vcc",
-							       &core->dev.of_node->fwnode);
+		usb_dev->gpio_desc = devm_gpiod_get(&core->dev, "vcc", 0);
 	if (!IS_ERR_OR_NULL(usb_dev->gpio_desc))
 		gpiod_direction_output(usb_dev->gpio_desc, 1);
 
' href='#n239'>239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
--- a/net80211/ieee80211_node.c
+++ b/net80211/ieee80211_node.c
@@ -123,6 +123,9 @@ static void ieee80211_node_table_cleanup
 static void ieee80211_node_table_reset(struct ieee80211_node_table *,
 	struct ieee80211vap *);
 
+static struct ieee80211_node *
+lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap, const u_int8_t *addr);
+
 MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
 
 void
@@ -697,7 +700,7 @@ ieee80211_sta_join(struct ieee80211vap *
 	struct ieee80211com *ic = vap->iv_ic;
 	struct ieee80211_node *ni;
 
-	ni = ieee80211_find_node(&ic->ic_sta, se->se_macaddr);
+	ni = lookup_rxnode(ic, vap, se->se_macaddr);
 	if (ni == NULL) {
 		ni = ieee80211_alloc_node_table(vap, se->se_macaddr);
 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
@@ -1394,6 +1397,53 @@ ieee80211_add_neighbor(struct ieee80211v
 	return ni;
 }
 
+struct ieee80211vap *
+ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac)
+{
+	struct ieee80211vap *vap;
+
+	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+		if (IEEE80211_ADDR_EQ(vap->iv_myaddr, mac))
+			return vap;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(ieee80211_find_rxvap);
+
+static struct ieee80211_node *
+lookup_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
+	const u_int8_t *addr)
+{
+	struct ieee80211_node_table *nt;
+	struct ieee80211_node *ni = NULL;
+	int use_bss = 0;
+	int hash;
+
+	nt = &ic->ic_sta;
+	IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+	hash = IEEE80211_NODE_HASH(addr);
+	LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
+		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, addr)) {
+			/* allow multiple nodes on different vaps */
+			if (vap && (ni->ni_vap != vap))
+				continue;
+
+			ieee80211_ref_node(ni);
+			goto out;
+		}
+	}
+
+	/* no match found */
+	ni = NULL;
+
+out:
+	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
+	return ni;
+#undef IS_PSPOLL
+#undef IS_CTL
+}
+
+
 /*
  * Return the node for the sender of a frame; if the sender is unknown return 
  * NULL. The caller is expected to deal with this. (The frame is sent to all 
@@ -1403,10 +1453,10 @@ ieee80211_add_neighbor(struct ieee80211v
  */
 struct ieee80211_node *
 #ifdef IEEE80211_DEBUG_REFCNT
-ieee80211_find_rxnode_debug(struct ieee80211com *ic,
+ieee80211_find_rxnode_debug(struct ieee80211com *ic, struct ieee80211vap *vap,
 	const struct ieee80211_frame_min *wh, const char *func, int line)
 #else
-ieee80211_find_rxnode(struct ieee80211com *ic,
+ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211vap *vap,
 	const struct ieee80211_frame_min *wh)
 #endif
 {
@@ -1414,9 +1464,8 @@ ieee80211_find_rxnode(struct ieee80211co
 	((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
 #define	IS_PSPOLL(wh) \
 	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
-	struct ieee80211_node_table *nt;
-	struct ieee80211_node *ni;
-	struct ieee80211vap *vap, *avp;
+	struct ieee80211_node *ni = NULL;
+	struct ieee80211vap *avp;
 	const u_int8_t *addr;
 
 	if (IS_CTL(wh) && !IS_PSPOLL(wh) /*&& !IS_RTS(ah)*/)
@@ -1429,32 +1478,25 @@ ieee80211_find_rxnode(struct ieee80211co
 
 	/* XXX check ic_bss first in station mode */
 	/* XXX 4-address frames? */
-	nt = &ic->ic_sta;
-	IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
 	if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) {
-		TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+		if (vap) { /* assume unicast if vap is set, mcast not supported for wds */
 			TAILQ_FOREACH(avp, &vap->iv_wdslinks, iv_wdsnext) {
-				if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac))
+				if (!IEEE80211_ADDR_EQ(addr, avp->wds_mac) ||
+					!IEEE80211_ADDR_EQ(wh->i_addr1, avp->iv_myaddr))
 					continue;
 
 				if (avp->iv_wdsnode)
-					return ieee80211_ref_node(avp->iv_wdsnode);
-				else
-					return NULL;
+					ni = ieee80211_ref_node(avp->iv_wdsnode);
+				return ni;
 			}
+			if (!(vap->iv_flags_ext & IEEE80211_FEXT_WDS))
+				return NULL;
+		} else {
+			return NULL;
 		}
 	}
 
-#ifdef IEEE80211_DEBUG_REFCNT
-	ni = ieee80211_find_node_locked_debug(nt, addr, func, line);
-#else
-	ni = ieee80211_find_node_locked(nt, addr);
-#endif
-	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
-
-	return ni;
-#undef IS_PSPOLL
-#undef IS_CTL
+	return lookup_rxnode(ic, vap, addr);
 }
 #ifdef IEEE80211_DEBUG_REFCNT
 EXPORT_SYMBOL(ieee80211_find_rxnode_debug);
@@ -1479,15 +1521,14 @@ ieee80211_find_txnode(struct ieee80211va
 	struct ieee80211com *ic = vap->iv_ic;
 	struct ieee80211_node_table *nt;
 	struct ieee80211_node *ni = NULL;
+	int hash;
 
-	IEEE80211_LOCK_IRQ(ic);
 	if (vap->iv_opmode == IEEE80211_M_WDS) {
 		if (vap->iv_wdsnode && (vap->iv_state == IEEE80211_S_RUN))
 			return ieee80211_ref_node(vap->iv_wdsnode);
 		else
 			return NULL;
 	}
-	IEEE80211_UNLOCK_IRQ(ic);
 
 	/*
 	 * The destination address should be in the node table
@@ -1505,11 +1546,22 @@ ieee80211_find_txnode(struct ieee80211va
 	/* XXX: Can't hold lock across dup_bss due to recursive locking. */
 	nt = &vap->iv_ic->ic_sta;
 	IEEE80211_NODE_TABLE_LOCK_IRQ(nt);
+	hash = IEEE80211_NODE_HASH(mac);
+	LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
+		if (ni->ni_vap != vap)
+			continue;
+
+		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, mac)) {
 #ifdef IEEE80211_DEBUG_REFCNT
-	ni = ieee80211_find_node_locked_debug(nt, mac, func, line);
+			ieee80211_ref_node_debug(ni, func, line);
 #else
-	ni = ieee80211_find_node_locked(nt, mac);
+			ieee80211_ref_node(ni);
 #endif
+			goto found;
+		}
+	}
+	ni = NULL;
+found:
 	IEEE80211_NODE_TABLE_UNLOCK_IRQ(nt);
 
 	if (ni == NULL) {
@@ -1964,13 +2016,32 @@ remove_worse_nodes(void *arg, struct iee
 		}
 }
 
+static void
+remove_duplicate_nodes(void *arg, struct ieee80211_node *ni)
+{
+	struct ieee80211_node *rni = arg;
+
+	if (ni == rni)
+		return;
+
+	if (ni->ni_vap == rni->ni_vap)
+		return;
+
+	if (!IEEE80211_ADDR_EQ(rni->ni_macaddr, ni->ni_macaddr))
+		return;
+
+	ieee80211_node_leave(ni);
+}
+
 void
 ieee80211_node_join(struct ieee80211_node *ni, int resp)
 {
 	struct ieee80211com *ic = ni->ni_ic;
 	struct ieee80211vap *vap = ni->ni_vap;
+	struct ieee80211_node *tni;
 	int newassoc;
 
+	ieee80211_iterate_nodes(&ic->ic_sta, remove_duplicate_nodes, ni);
 	if (ni->ni_associd == 0) {
 		u_int16_t aid;
 
--- a/net80211/ieee80211_input.c
+++ b/net80211/ieee80211_input.c
@@ -216,16 +216,14 @@ ieee80211_input(struct ieee80211vap * va
 
 	type = -1;			/* undefined */
 
-	if (!vap)
-		goto out;
+	if (!vap || !vap->iv_bss || !vap->iv_dev || !vap->iv_ic)
+		goto discard;
 
 	ic = vap->iv_ic;
-	if (!ic)
-		goto out;
-
 	dev = vap->iv_dev;
-	if (!dev)
-		goto out;
+
+	if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+		goto discard;
 
 	/* initialize ni as in the previous API */
 	if (ni_or_null == NULL) {
@@ -233,9 +231,10 @@ ieee80211_input(struct ieee80211vap * va
                 * guarantee its existence during the following call, hence
                 * briefly grab our own reference. */
 		ni = ieee80211_ref_node(vap->iv_bss);
+		KASSERT(ni != NULL, ("null node"));
+	} else {
+		ni->ni_inact = ni->ni_inact_reload;
 	}
-	KASSERT(ni != NULL, ("null node"));
-	ni->ni_inact = ni->ni_inact_reload;
 
 	KASSERT(skb->len >= sizeof(struct ieee80211_frame_min),
 		("frame length too short: %u", skb->len));
@@ -844,10 +843,11 @@ ieee80211_input(struct ieee80211vap * va
 err:
 	vap->iv_devstats.rx_errors++;
 out:
-	if (skb != NULL)
-		ieee80211_dev_kfree_skb(&skb);
 	if (ni_or_null == NULL)
 		ieee80211_unref_node(&ni);
+discard:
+	if (skb != NULL)
+		ieee80211_dev_kfree_skb(&skb);
 	return type;
 #undef HAS_SEQ
 }
@@ -929,16 +929,23 @@ int
 ieee80211_input_all(struct ieee80211com *ic,
 	struct sk_buff *skb, int rssi, u_int64_t rtsf)
 {
+	struct ieee80211_frame_min *wh = (struct ieee80211_frame_min *) skb->data;
 	struct ieee80211vap *vap;
 	int type = -1;
 
 	/* XXX locking */
 	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
+		struct ieee80211_node *ni = NULL;
 		struct sk_buff *skb1;
 
 		if ((vap->iv_dev->flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
 			continue;
 
+		if ((vap->iv_opmode == IEEE80211_M_HOSTAP) &&
+			!IEEE80211_IS_MULTICAST(wh->i_addr1))
+			continue;
+
+		ni = ieee80211_find_rxnode(ic, vap, wh);
 		if (TAILQ_NEXT(vap, iv_next) != NULL) {
 			skb1 = skb_copy(skb, GFP_ATOMIC);
 			if (skb1 == NULL) {
@@ -950,8 +957,12 @@ ieee80211_input_all(struct ieee80211com 
 			skb1 = skb;
 			skb = NULL;
 		}
-		type = ieee80211_input(vap, NULL, skb1, rssi, rtsf);
+		type = ieee80211_input(vap, ni, skb1, rssi, rtsf);
+		if (ni)
+			ieee80211_unref_node(&ni);
 	}
+
+out:
 	if (skb != NULL)		/* no vaps, reclaim skb */
 		ieee80211_dev_kfree_skb(&skb);
 	return type;
@@ -1146,11 +1157,9 @@ ieee80211_deliver_data(struct ieee80211_
 			 * sending it will not work; just let it be
 			 * delivered normally.
 			 */
-			struct ieee80211_node *ni1 = ieee80211_find_node(
-				&vap->iv_ic->ic_sta, eh->ether_dhost);
+			struct ieee80211_node *ni1 = ieee80211_find_txnode(vap, eh->ether_dhost);
 			if (ni1 != NULL) {
-				if (ni1->ni_vap == vap &&
-				    ieee80211_node_is_authorized(ni1) &&
+				if (ieee80211_node_is_authorized(ni1) &&
 					!ni1->ni_subif &&
 				    ni1 != vap->iv_bss) {
 
@@ -3519,6 +3528,7 @@ ieee80211_recv_mgmt(struct ieee80211vap 
 				 (vap->iv_opmode == IEEE80211_M_WDS)) &&
 				(scan.capinfo & IEEE80211_CAPINFO_ESS))) {
 			struct ieee80211vap *avp = NULL;
+			int do_unref = 0;
 			int found = 0;
 
 			IEEE80211_LOCK_IRQ(vap->iv_ic);
@@ -3550,10 +3560,12 @@ ieee80211_recv_mgmt(struct ieee80211vap 
 					ni->ni_associd |= 0xc000;
 					avp->iv_wdsnode = ieee80211_ref_node(ni);
 					IEEE80211_UNLOCK_IRQ(ic);
-				} else if (vap->iv_opmode == IEEE80211_M_IBSS) {
+				} else if ((vap->iv_opmode == IEEE80211_M_IBSS) &&
+				           IEEE80211_ADDR_EQ(wh->i_addr3, vap->iv_bssid)) {
 					/* Create a new entry in the neighbor table. */
 					ni = ieee80211_add_neighbor(vap, wh, &scan);
 				}
+				do_unref = 1;
 			} else {
 				/*
 				 * Copy data from beacon to neighbor table.
@@ -3592,6 +3604,8 @@ ieee80211_recv_mgmt(struct ieee80211vap 
 				ni->ni_rssi = rssi;
 				ni->ni_rtsf = rtsf;
 				ni->ni_last_rx = jiffies;
+				if (do_unref)
+					ieee80211_unref_node(&ni);
 			}
 		}
 		break;
--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -6589,9 +6589,8 @@ ath_recv_mgmt(struct ieee80211vap * vap,
 
 	sc->sc_recv_mgmt(vap, ni_or_null, skb, subtype, rssi, rtsf);
 
-
 	/* Lookup the new node if any (this grabs a reference to it) */
-	ni = ieee80211_find_rxnode(vap->iv_ic,
+	ni = ieee80211_find_rxnode(vap->iv_ic, vap,
 	         (const struct ieee80211_frame_min *)skb->data);
 	if (ni == NULL) {
 		DPRINTF(sc, ATH_DEBUG_BEACON, "Dropping; node unknown.\n");
@@ -6746,7 +6745,9 @@ ath_rx_poll(struct net_device *dev, int 
 	struct ath_desc *ds;
 	struct ath_rx_status *rs;
 	struct sk_buff *skb = NULL;
+	struct ieee80211vap *vap;
 	struct ieee80211_node *ni;
+	const struct ieee80211_frame_min *wh;
 	unsigned int len;
 	int type;
 	u_int phyerr;
@@ -6901,12 +6902,15 @@ rx_accept:
 		skb_trim(skb, skb->len - IEEE80211_CRC_LEN);
 
 		if (mic_fail) {
+			wh = (const struct ieee80211_frame_min *) skb->data;
+
 			/* Ignore control frames which are reported with mic error */
-		    if ((((struct ieee80211_frame *)skb->data)->i_fc[0] &
+		    if ((wh->i_fc[0] &
 					IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
 				goto drop_micfail;
 
-			ni = ieee80211_find_rxnode(ic, (const struct ieee80211_frame_min *) skb->data);
+			vap = ieee80211_find_rxvap(ic, wh->i_addr1);
+			ni = ieee80211_find_rxnode(ic, vap, wh);
 
 			if (ni && ni->ni_table) {
 				ieee80211_check_mic(ni, skb);
@@ -6968,11 +6972,24 @@ drop_micfail:
 		 * for its use.  If the sender is unknown spam the
 		 * frame; it'll be dropped where it's not wanted.
 		 */
-		if (rs->rs_keyix != HAL_RXKEYIX_INVALID &&
+		wh = (const struct ieee80211_frame_min *) skb->data;
+		if ((rs->rs_keyix != HAL_RXKEYIX_INVALID) &&
 		    (ni = sc->sc_keyixmap[rs->rs_keyix]) != NULL) {
 			/* Fast path: node is present in the key map;
 			 * grab a reference for processing the frame. */
-			ni = ieee80211_ref_node(ni);
+			ieee80211_ref_node(ni);
+			if ((ATH_GET_VAP_ID(wh->i_addr1) !=
+			     ATH_GET_VAP_ID(ni->ni_vap->iv_myaddr)) ||
+				((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) ==
+				 IEEE80211_FC1_DIR_DSTODS)) {
+				/* key cache node lookup is fast, but it can
+				 * lead to problems in multi-bss (foreign vap
+				 * node reference) or wds (wdsap node ref instead
+				 * of base ap node ref).
+				 * use slowpath lookup in both cases
+				 */
+				goto lookup_slowpath;
+			}
 			ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
 			type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
 			ieee80211_unref_node(&ni);
@@ -6981,24 +6998,39 @@ drop_micfail:
 			 * No key index or no entry, do a lookup and
 			 * add the node to the mapping table if possible.
 			 */
-			ni = ieee80211_find_rxnode(ic,
-				(const struct ieee80211_frame_min *)skb->data);
+
+lookup_slowpath:
+			if (IEEE80211_IS_MULTICAST(wh->i_addr1))
+				vap = NULL;
+			else
+				vap = ieee80211_find_rxvap(ic, wh->i_addr1);
+
+			if (vap)
+				ni = ieee80211_find_rxnode(ic, vap, wh);
+			else
+				ni = NULL;
+
 			if (ni != NULL) {
 				ieee80211_keyix_t keyix;
 
 				ATH_RSSI_LPF(ATH_NODE(ni)->an_avgrssi, rs->rs_rssi);
-				type = ieee80211_input(ni->ni_vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
+				type = ieee80211_input(vap, ni, skb, rs->rs_rssi, bf->bf_tsf);
 				/*
 				 * If the station has a key cache slot assigned
 				 * update the key->node mapping table.
 				 */
 				keyix = ni->ni_ucastkey.wk_keyix;
 				if (keyix != IEEE80211_KEYIX_NONE &&
-				    sc->sc_keyixmap[keyix] == NULL)
+				    sc->sc_keyixmap[keyix] == NULL) {
 					sc->sc_keyixmap[keyix] = ieee80211_ref_node(ni);
+				}
 				ieee80211_unref_node(&ni);
-			} else
-				type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
+			} else {
+				if (vap)
+					type = ieee80211_input(vap, NULL, skb, rs->rs_rssi, bf->bf_tsf);
+				else
+					type = ieee80211_input_all(ic, skb, rs->rs_rssi, bf->bf_tsf);
+			}
 		}
 
 		if (sc->sc_diversity) {
--- a/net80211/ieee80211_node.h
+++ b/net80211/ieee80211_node.h
@@ -286,15 +286,18 @@ struct ieee80211_node *ieee80211_find_no
 	const u_int8_t *);
 #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
 
+struct ieee80211vap *
+ieee80211_find_rxvap(struct ieee80211com *ic, const u_int8_t *mac);
+
 /* Returns a ieee80211_node* with refcount incremented, if found */
 #ifdef IEEE80211_DEBUG_REFCNT
-#define	ieee80211_find_rxnode(_nt, _wh) \
-	ieee80211_find_rxnode_debug(_nt, _wh, __func__, __LINE__)
+#define	ieee80211_find_rxnode(_nt, _vap, _wh) \
+	ieee80211_find_rxnode_debug(_nt, _vap, _wh, __func__, __LINE__)
 struct ieee80211_node *ieee80211_find_rxnode_debug(struct ieee80211com *,
-	const struct ieee80211_frame_min *, const char *, int);
+	struct ieee80211vap *, const struct ieee80211_frame_min *, const char *, int);
 #else
 struct ieee80211_node *ieee80211_find_rxnode(struct ieee80211com *,
-	const struct ieee80211_frame_min *);
+	struct ieee80211vap *, const struct ieee80211_frame_min *);
 #endif /* #ifdef IEEE80211_DEBUG_REFCNT */
 
 /* Returns a ieee80211_node* with refcount incremented, if found */