Franky Lin committed 5c80606

net: wireless: bcmdhd: Fix dhd_txcomplete() dead lock

For TX packet dhd_prot_hdrpull does nothing other than pull the prot
header from the skb. Use a NULL ifdix pointer to indicate a handling
of tx packet and skip most of the header parsing routine - we don't
need it for TX packet and we can skip extra unnecessary PROP_TXSTATUS
parsing. It will resloved dead lock case because we just exit
dhd_prot_hdrpull for TX path.

Change-Id: Ic41e1c549036baeb0fabfb0be4b8331a4bf60682
Signed-off-by: Dmitry Shmidt <>

Comments (0)

Files changed (2)


 #ifdef BDC
 	struct bdc_header *h;
+	uint8 data_offset = 0;
 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 	h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf);
+#if defined(NDIS630)
+	h->dataOffset = 0;
+	if (!ifidx) {
+		/* for tx packet, skip the analysis and just exit */
+		data_offset = h->dataOffset;
+		PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN);
+		goto exit;
+	}
 	if ((*ifidx = BDC_GET_IF_IDX(h)) >= DHD_MAX_IFS) {
 		DHD_ERROR(("%s: rx data ifnum out of range (%d)\n",
 		           __FUNCTION__, *ifidx));
 		return BCME_ERROR;
-#if defined(NDIS630)
-	h->dataOffset = 0;
 	if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != BDC_PROTO_VER) {
 		DHD_ERROR(("%s: non-BDC packet received, flags = 0x%x\n",
 		           dhd_ifname(dhd, *ifidx), h->flags));
 	PKTSETPRIO(pktbuf, (h->priority & BDC_PRIORITY_MASK));
+	data_offset = h->dataOffset;
 	PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN);
 #endif /* BDC */
 #endif /* PROP_TXSTATUS */
 #if !defined(NDIS630)
 		PKTPULL(dhd->osh, pktbuf, (h->dataOffset << 2));


 dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success)
-	uint ifidx;
 	dhd_info_t *dhd = (dhd_info_t *)(dhdp->info);
 	struct ether_header *eh;
 	uint16 type;
 	uint len;
-	dhd_prot_hdrpull(dhdp, &ifidx, txp, NULL, NULL);
+	dhd_prot_hdrpull(dhdp, NULL, txp, NULL, NULL);
 	eh = (struct ether_header *)PKTDATA(dhdp->osh, txp);
 	type  = ntoh16(eh->ether_type);