diff options
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c')
| -rw-r--r-- | drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | 182 | 
1 files changed, 31 insertions, 151 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index a5c15cac5e7..a2354d951dd 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c @@ -19,12 +19,8 @@   * For certain dcmd codes, the dongle interprets string data from the host.   ******************************************************************************/ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -  #include <linux/types.h>  #include <linux/netdevice.h> -#include <linux/sched.h> -#include <defs.h>  #include <brcmu_utils.h>  #include <brcmu_wifi.h> @@ -96,8 +92,6 @@ struct brcmf_proto_bdc_header {  struct brcmf_proto {  	u16 reqid; -	u8 pending; -	u32 lastcmd;  	u8 bus_header[BUS_HEADER_LEN];  	struct brcmf_proto_cdc_dcmd msg;  	unsigned char buf[BRCMF_DCMD_MAXLEN + ROUND_UP_MARGIN]; @@ -109,7 +103,7 @@ static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)  	int len = le32_to_cpu(prot->msg.len) +  			sizeof(struct brcmf_proto_cdc_dcmd); -	brcmf_dbg(TRACE, "Enter\n"); +	brcmf_dbg(CDC, "Enter\n");  	/* NOTE : cdc->msg.len holds the desired length of the buffer to be  	 *        returned. Only up to CDC_MAX_MSG_SIZE of this buffer area @@ -119,9 +113,7 @@ static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr)  		len = CDC_MAX_MSG_SIZE;  	/* Send request */ -	return drvr->bus_if->brcmf_bus_txctl(drvr->dev, -					     (unsigned char *)&prot->msg, -					     len); +	return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&prot->msg, len);  }  static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) @@ -129,12 +121,11 @@ static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)  	int ret;  	struct brcmf_proto *prot = drvr->prot; -	brcmf_dbg(TRACE, "Enter\n"); - +	brcmf_dbg(CDC, "Enter\n"); +	len += sizeof(struct brcmf_proto_cdc_dcmd);  	do { -		ret = drvr->bus_if->brcmf_bus_rxctl(drvr->dev, -				(unsigned char *)&prot->msg, -				len + sizeof(struct brcmf_proto_cdc_dcmd)); +		ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&prot->msg, +				      len);  		if (ret < 0)  			break;  	} while (CDC_DCMD_ID(le32_to_cpu(prot->msg.flags)) != id); @@ -152,20 +143,7 @@ brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,  	int ret = 0, retries = 0;  	u32 id, flags; -	brcmf_dbg(TRACE, "Enter\n"); -	brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); - -	/* Respond "bcmerror" and "bcmerrorstr" with local cache */ -	if (cmd == BRCMF_C_GET_VAR && buf) { -		if (!strcmp((char *)buf, "bcmerrorstr")) { -			strncpy((char *)buf, "bcm_error", -				BCME_STRLEN); -			goto done; -		} else if (!strcmp((char *)buf, "bcmerror")) { -			*(int *)buf = drvr->dongle_error; -			goto done; -		} -	} +	brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len);  	memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); @@ -181,7 +159,7 @@ brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,  	ret = brcmf_proto_cdc_msg(drvr);  	if (ret < 0) { -		brcmf_dbg(ERROR, "brcmf_proto_cdc_msg failed w/status %d\n", +		brcmf_err("brcmf_proto_cdc_msg failed w/status %d\n",  			  ret);  		goto done;  	} @@ -198,7 +176,7 @@ retry:  	if ((id < prot->reqid) && (++retries < RETRIES))  		goto retry;  	if (id != prot->reqid) { -		brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n", +		brcmf_err("%s: unexpected request id %d (expected %d)\n",  			  brcmf_ifname(drvr, ifidx), id, prot->reqid);  		ret = -EINVAL;  		goto done; @@ -215,11 +193,8 @@ retry:  	}  	/* Check the ERROR flag */ -	if (flags & CDC_DCMD_ERROR) { +	if (flags & CDC_DCMD_ERROR)  		ret = le32_to_cpu(msg->status); -		/* Cache error from dongle */ -		drvr->dongle_error = ret; -	}  done:  	return ret; @@ -233,8 +208,7 @@ int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,  	int ret = 0;  	u32 flags, id; -	brcmf_dbg(TRACE, "Enter\n"); -	brcmf_dbg(CTL, "cmd %d len %d\n", cmd, len); +	brcmf_dbg(CDC, "Enter, cmd %d len %d\n", cmd, len);  	memset(msg, 0, sizeof(struct brcmf_proto_cdc_dcmd)); @@ -260,93 +234,20 @@ int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,  	id = (flags & CDC_DCMD_ID_MASK) >> CDC_DCMD_ID_SHIFT;  	if (id != prot->reqid) { -		brcmf_dbg(ERROR, "%s: unexpected request id %d (expected %d)\n", +		brcmf_err("%s: unexpected request id %d (expected %d)\n",  			  brcmf_ifname(drvr, ifidx), id, prot->reqid);  		ret = -EINVAL;  		goto done;  	}  	/* Check the ERROR flag */ -	if (flags & CDC_DCMD_ERROR) { +	if (flags & CDC_DCMD_ERROR)  		ret = le32_to_cpu(msg->status); -		/* Cache error from dongle */ -		drvr->dongle_error = ret; -	}  done:  	return ret;  } -int -brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, struct brcmf_dcmd *dcmd, -		  int len) -{ -	struct brcmf_proto *prot = drvr->prot; -	int ret = -1; - -	if (drvr->bus_if->state == BRCMF_BUS_DOWN) { -		brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n"); -		return ret; -	} -	mutex_lock(&drvr->proto_block); - -	brcmf_dbg(TRACE, "Enter\n"); - -	if (len > BRCMF_DCMD_MAXLEN) -		goto done; - -	if (prot->pending == true) { -		brcmf_dbg(TRACE, "CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n", -			  dcmd->cmd, (unsigned long)dcmd->cmd, prot->lastcmd, -			  (unsigned long)prot->lastcmd); -		if (dcmd->cmd == BRCMF_C_SET_VAR || -		    dcmd->cmd == BRCMF_C_GET_VAR) -			brcmf_dbg(TRACE, "iovar cmd=%s\n", (char *)dcmd->buf); - -		goto done; -	} - -	prot->pending = true; -	prot->lastcmd = dcmd->cmd; -	if (dcmd->set) -		ret = brcmf_proto_cdc_set_dcmd(drvr, ifidx, dcmd->cmd, -						   dcmd->buf, len); -	else { -		ret = brcmf_proto_cdc_query_dcmd(drvr, ifidx, dcmd->cmd, -						     dcmd->buf, len); -		if (ret > 0) -			dcmd->used = ret - -					sizeof(struct brcmf_proto_cdc_dcmd); -	} - -	if (ret >= 0) -		ret = 0; -	else { -		struct brcmf_proto_cdc_dcmd *msg = &prot->msg; -		/* len == needed when set/query fails from dongle */ -		dcmd->needed = le32_to_cpu(msg->len); -	} - -	/* Intercept the wme_dp dongle cmd here */ -	if (!ret && dcmd->cmd == BRCMF_C_SET_VAR && -	    !strcmp(dcmd->buf, "wme_dp")) { -		int slen; -		__le32 val = 0; - -		slen = strlen("wme_dp") + 1; -		if (len >= (int)(slen + sizeof(int))) -			memcpy(&val, (char *)dcmd->buf + slen, sizeof(int)); -		drvr->wme_dp = (u8) le32_to_cpu(val); -	} - -	prot->pending = false; - -done: -	mutex_unlock(&drvr->proto_block); - -	return ret; -} -  static bool pkt_sum_needed(struct sk_buff *skb)  {  	return skb->ip_summed == CHECKSUM_PARTIAL; @@ -362,7 +263,7 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,  {  	struct brcmf_proto_bdc_header *h; -	brcmf_dbg(TRACE, "Enter\n"); +	brcmf_dbg(CDC, "Enter\n");  	/* Push BDC header used to convey priority for buses that don't */ @@ -380,19 +281,17 @@ void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx,  	BDC_SET_IF_IDX(h, ifidx);  } -int brcmf_proto_hdrpull(struct device *dev, int *ifidx, +int brcmf_proto_hdrpull(struct brcmf_pub *drvr, u8 *ifidx,  			struct sk_buff *pktbuf)  {  	struct brcmf_proto_bdc_header *h; -	struct brcmf_bus *bus_if = dev_get_drvdata(dev); -	struct brcmf_pub *drvr = bus_if->drvr; -	brcmf_dbg(TRACE, "Enter\n"); +	brcmf_dbg(CDC, "Enter\n");  	/* Pop BDC header used to convey priority for buses that don't */  	if (pktbuf->len < BDC_HEADER_LEN) { -		brcmf_dbg(ERROR, "rx data too short (%d < %d)\n", +		brcmf_err("rx data too short (%d < %d)\n",  			  pktbuf->len, BDC_HEADER_LEN);  		return -EBADE;  	} @@ -401,19 +300,27 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx,  	*ifidx = BDC_GET_IF_IDX(h);  	if (*ifidx >= BRCMF_MAX_IFS) { -		brcmf_dbg(ERROR, "rx data ifnum out of range (%d)\n", *ifidx); +		brcmf_err("rx data ifnum out of range (%d)\n", *ifidx);  		return -EBADE;  	} +	/* The ifidx is the idx to map to matching netdev/ifp. When receiving +	 * events this is easy because it contains the bssidx which maps +	 * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd. +	 * bssidx 1 is used for p2p0 and no data can be received or +	 * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0 +	 */ +	if (*ifidx) +		(*ifidx)++;  	if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) !=  	    BDC_PROTO_VER) { -		brcmf_dbg(ERROR, "%s: non-BDC packet received, flags 0x%x\n", +		brcmf_err("%s: non-BDC packet received, flags 0x%x\n",  			  brcmf_ifname(drvr, *ifidx), h->flags);  		return -EBADE;  	}  	if (h->flags & BDC_FLAG_SUM_GOOD) { -		brcmf_dbg(INFO, "%s: BDC packet received with good rx-csum, flags 0x%x\n", +		brcmf_dbg(CDC, "%s: BDC rcv, good checksum, flags 0x%x\n",  			  brcmf_ifname(drvr, *ifidx), h->flags);  		pkt_set_sum_good(pktbuf, true);  	} @@ -423,6 +330,8 @@ int brcmf_proto_hdrpull(struct device *dev, int *ifidx,  	skb_pull(pktbuf, BDC_HEADER_LEN);  	skb_pull(pktbuf, h->data_offset << 2); +	if (pktbuf->len == 0) +		return -ENODATA;  	return 0;  } @@ -436,7 +345,7 @@ int brcmf_proto_attach(struct brcmf_pub *drvr)  	/* ensure that the msg buf directly follows the cdc msg struct */  	if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) { -		brcmf_dbg(ERROR, "struct brcmf_proto is not correctly defined\n"); +		brcmf_err("struct brcmf_proto is not correctly defined\n");  		goto fail;  	} @@ -458,35 +367,6 @@ void brcmf_proto_detach(struct brcmf_pub *drvr)  	drvr->prot = NULL;  } -int brcmf_proto_init(struct brcmf_pub *drvr) -{ -	int ret = 0; -	char buf[128]; - -	brcmf_dbg(TRACE, "Enter\n"); - -	mutex_lock(&drvr->proto_block); - -	/* Get the device MAC address */ -	strcpy(buf, "cur_etheraddr"); -	ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, -					  buf, sizeof(buf)); -	if (ret < 0) { -		mutex_unlock(&drvr->proto_block); -		return ret; -	} -	memcpy(drvr->mac, buf, ETH_ALEN); - -	mutex_unlock(&drvr->proto_block); - -	ret = brcmf_c_preinit_dcmds(drvr); - -	/* Always assumes wl for now */ -	drvr->iswl = true; - -	return ret; -} -  void brcmf_proto_stop(struct brcmf_pub *drvr)  {  	/* Nothing to do for CDC */  |