qcacmn: Add error handling in case of hif_send_head failure

In case of SDIO/USB TX bundling if there is hif_send_head failure
packets are not added back to Endpoint tx queue and resulting in
packet drop.

Add packet back to tx queue if hif_send_head send failure
for bundled packet.

Change-Id: Id613a414f0caa71a33c79186ae726550cb710c4a
CRs-Fixed: 2468882
diff --git a/htc/htc_send.c b/htc/htc_send.c
index 57106b7..3ac1295 100644
--- a/htc/htc_send.c
+++ b/htc/htc_send.c
@@ -334,9 +334,36 @@
 			       pEndpoint->UL_PipeID,
 			       pEndpoint->Id, data_len,
 			       bundleBuf, data_attr);
-	if (status != QDF_STATUS_SUCCESS) {
-		qdf_print("%s:hif_send_head failed(len=%zu).", __func__,
-			  data_len);
+	if (qdf_unlikely(QDF_IS_STATUS_ERROR(status))) {
+		HTC_PACKET_QUEUE requeue;
+
+		qdf_print("hif_send_head failed(len=%zu).", data_len);
+		INIT_HTC_PACKET_QUEUE(&requeue);
+		LOCK_HTC_TX(target);
+		pEndpoint->ul_outstanding_cnt--;
+		HTC_PACKET_REMOVE(&pEndpoint->TxLookupQueue, pPacketTx);
+
+		if (pPacketTx->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) {
+			HTC_PACKET *temp_packet;
+			HTC_PACKET_QUEUE *packet_queue =
+				(HTC_PACKET_QUEUE *)pPacketTx->pContext;
+
+			HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(packet_queue,
+							      temp_packet) {
+				HTC_PACKET_ENQUEUE(&requeue, temp_packet);
+			} HTC_PACKET_QUEUE_ITERATE_END;
+
+			UNLOCK_HTC_TX(target);
+			free_htc_bundle_packet(target, pPacketTx);
+			LOCK_HTC_TX(target);
+
+		} else {
+			HTC_PACKET_ENQUEUE(&requeue, pPacketTx);
+		}
+
+		HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
+						  &requeue);
+		UNLOCK_HTC_TX(target);
 	}
 	return status;
 }