Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c5141b0f authored by Houston Hoffman's avatar Houston Hoffman Committed by Akash Patel
Browse files

qcacld-3.0: Runtime PM handling for htc messages

Check runtime pm status while sending messages.
Update runtime pm when sending messages to hif.
Update runtime pm when messages are tx completed.

Change-Id: I27840f57ff87d6d27b1e3611e7fe1f2cd933ddd0
CRs-Fixed: 935300
parent 466cb5b6
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2011-2015 The Linux Foundation. All rights reserved.
 * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved.
 *
 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
 *
@@ -504,6 +504,7 @@ ol_tx_completion_handler(ol_txrx_pdev_handle pdev,
		tx_desc->status = status;
		netbuf = tx_desc->netbuf;

		cdf_runtime_pm_put();
		cdf_nbuf_trace_update(netbuf, trace_str);
		/* Per SDU update of byte count */
		byte_cnt += cdf_nbuf_len(netbuf);
+14 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2014, 2016 The Linux Foundation. All rights reserved.
 *
 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
 *
@@ -61,10 +61,19 @@ typedef struct _HTC_TX_PACKET_INFO {
	A_UINT32 Flags;         /* internal use */
} HTC_TX_PACKET_INFO;

#define HTC_TX_PACKET_TAG_ALL          0        /* a tag of zero is reserved and used to flush ALL packets */
#define HTC_TX_PACKET_TAG_INTERNAL     1        /* internal tags start here */
#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */
#define HTC_TX_PACKET_TAG_BUNDLED      HTC_TX_PACKET_TAG_USER_DEFINED + 1       /* indicate this is bundled TX packet */
/**
 * HTC_TX_PACKET_TAG_XXX - #defines for tagging packets for special handling
 * HTC_TX_PACKET_TAG_ALL: zero is reserved and used to flush ALL packets
 * HTC_TX_PACKET_TAG_INTERNAL: internal tags start here
 * HTC_TX_PACKET_TAG_USER_DEFINED: user-defined tags start here
 * HTC_TX_PACKET_TAG_BUNDLED: indicate this is a bundled tx packet
 * HTC_TX_PACKET_TAG_AUTO_PM: indicate a power management wmi command
 */
#define HTC_TX_PACKET_TAG_ALL          0
#define HTC_TX_PACKET_TAG_INTERNAL     1
#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9)
#define HTC_TX_PACKET_TAG_BUNDLED      (HTC_TX_PACKET_TAG_USER_DEFINED + 1)
#define HTC_TX_PACKET_TAG_AUTO_PM      (HTC_TX_PACKET_TAG_USER_DEFINED + 2)

#define HTC_TX_PACKET_FLAG_FIXUP_NETBUF (1 << 0)

+122 −10
Original line number Diff line number Diff line
@@ -597,6 +597,60 @@ static A_STATUS htc_issue_packets(HTC_TARGET *target,
	return status;
}

#ifdef FEATURE_RUNTIME_PM
/**
 * extract_htc_pm_packtes(): move pm packets from endpoint into queue
 * @endpoint: which enpoint to extract packets from
 * @queue: a queue to store extracted packets in.
 *
 * remove pm packets from the endpoint's tx queue.
 * queue them into a queue
 */
static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
				HTC_PACKET_QUEUE *queue)
{
	HTC_PACKET *packet;

	/* only WMI endpoint has power management packets */
	if (endpoint->service_id != WMI_CONTROL_SVC)
		return;

	ITERATE_OVER_LIST_ALLOW_REMOVE(&endpoint->TxQueue.QueueHead, packet,
			HTC_PACKET, ListLink) {
		if (packet->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_AUTO_PM) {
			HTC_PACKET_REMOVE(&endpoint->TxQueue, packet);
			HTC_PACKET_ENQUEUE(queue, packet);
		}
	} ITERATE_END
}

/**
 * queue_htc_pm_packets(): queue pm packets with priority
 * @endpoint: enpoint to queue packets to
 * @queue: queue of pm packets to enque
 *
 * suspend resume packets get special treatment & priority.
 * need to queue them at the front of the queue.
 */
static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
				 HTC_PACKET_QUEUE *queue)
{
	if (endpoint->service_id != WMI_CONTROL_SVC)
		return;

	HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&endpoint->TxQueue, queue);
}
#else
static void extract_htc_pm_packets(HTC_ENDPOINT *endpoint,
		HTC_PACKET_QUEUE *queue)
{}

static void queue_htc_pm_packets(HTC_ENDPOINT *endpoint,
		HTC_PACKET_QUEUE *queue)
{}
#endif


/* get HTC send packets from the TX queue on an endpoint, based on available credits */
void get_htc_send_packets_credit_based(HTC_TARGET *target,
				       HTC_ENDPOINT *pEndpoint,
@@ -607,24 +661,43 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target,
	A_UINT8 sendFlags;
	HTC_PACKET *pPacket;
	unsigned int transferLength;
	HTC_PACKET_QUEUE *tx_queue;
	HTC_PACKET_QUEUE pm_queue;
	bool do_pm_get = false;

	/****** NOTE : the TX lock is held when this function is called *****************/
	AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+get_htc_send_packets_credit_based\n"));

	INIT_HTC_PACKET_QUEUE(&pm_queue);
	extract_htc_pm_packets(pEndpoint, &pm_queue);
	if (HTC_QUEUE_EMPTY(&pm_queue)) {
		tx_queue = &pEndpoint->TxQueue;
		do_pm_get = true;
	} else {
		tx_queue = &pm_queue;
	}

	/* loop until we can grab as many packets out of the queue as we can */
	while (true) {
		if (do_pm_get && hif_pm_runtime_get(target->hif_dev)) {
			/* bus suspended, runtime resume issued */
			CDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
			break;
		}

		sendFlags = 0;
		/* get packet at head, but don't remove it */
		pPacket = htc_get_pkt_at_head(&pEndpoint->TxQueue);
		pPacket = htc_get_pkt_at_head(tx_queue);
		if (pPacket == NULL) {
			if (do_pm_get)
				hif_pm_runtime_put(target->hif_dev);
			break;
		}

		AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
				(" Got head packet:%p , Queue Depth: %d\n",
				 pPacket,
				 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
				 HTC_PACKET_QUEUE_DEPTH(tx_queue)));

		transferLength = pPacket->ActualLength + HTC_HDR_LENGTH;

@@ -676,6 +749,8 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target,
						 pEndpoint->TxCredits,
						 creditsRequired));
#endif
				if (do_pm_get)
					hif_pm_runtime_put(target->hif_dev);
				break;
			}

@@ -694,8 +769,7 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target,
					htc_credit_record(HTC_REQUEST_CREDIT,
							  pEndpoint->TxCredits,
							  HTC_PACKET_QUEUE_DEPTH
								  (&pEndpoint->
								  TxQueue));
								  (tx_queue));
					UNLOCK_HTC_CREDIT(target);
				}

@@ -710,7 +784,7 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target,
		}

		/* now we can fully dequeue */
		pPacket = htc_packet_dequeue(&pEndpoint->TxQueue);
		pPacket = htc_packet_dequeue(tx_queue);
		if (pPacket) {
			/* save the number of credits this packet consumed */
			pPacket->PktInfo.AsTx.CreditsUsed = creditsRequired;
@@ -722,7 +796,11 @@ void get_htc_send_packets_credit_based(HTC_TARGET *target,
		}
	}

	AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets_credit_based \n"));
	if (!HTC_QUEUE_EMPTY(&pm_queue))
		queue_htc_pm_packets(pEndpoint, &pm_queue);

	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
			("-get_htc_send_packets_credit_based\n"));

}

@@ -732,23 +810,43 @@ void get_htc_send_packets(HTC_TARGET *target,
{

	HTC_PACKET *pPacket;
	HTC_PACKET_QUEUE *tx_queue;
	HTC_PACKET_QUEUE pm_queue;
	bool do_pm_get;

	/****** NOTE : the TX lock is held when this function is called *****************/
	AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
			("+get_htc_send_packets %d resources\n", Resources));

	INIT_HTC_PACKET_QUEUE(&pm_queue);
	extract_htc_pm_packets(pEndpoint, &pm_queue);
	if (HTC_QUEUE_EMPTY(&pm_queue)) {
		tx_queue = &pEndpoint->TxQueue;
		do_pm_get = true;
	} else {
		tx_queue = &pm_queue;
	}

	/* loop until we can grab as many packets out of the queue as we can */
	while (Resources > 0) {
		int num_frags;

		pPacket = htc_packet_dequeue(&pEndpoint->TxQueue);
		if (do_pm_get && hif_pm_runtime_get(target->hif_dev)) {
			/* bus suspended, runtime resume issued */
			CDF_ASSERT(HTC_PACKET_QUEUE_DEPTH(pQueue) == 0);
			break;
		}

		pPacket = htc_packet_dequeue(tx_queue);
		if (pPacket == NULL) {
			if (do_pm_get)
				hif_pm_runtime_put(target->hif_dev);
			break;
		}
		AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
				(" Got packet:%p , New Queue Depth: %d\n",
				 pPacket,
				 HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue)));
				 HTC_PACKET_QUEUE_DEPTH(tx_queue)));
		/* For non-credit path the sequence number is already embedded
		 * in the constructed HTC header
		 */
@@ -779,6 +877,9 @@ void get_htc_send_packets(HTC_TARGET *target,
		Resources -= num_frags;
	}

	if (!HTC_QUEUE_EMPTY(&pm_queue))
		queue_htc_pm_packets(pEndpoint, &pm_queue);

	AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-get_htc_send_packets\n"));

}
@@ -991,9 +1092,14 @@ static HTC_SEND_QUEUE_RESULT htc_try_send(HTC_TARGET *target,
		/* send what we can */
		result = htc_issue_packets(target, pEndpoint, &sendQueue);
		if (result) {
			int i;
			AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
				("htc_issue_packets, failed status:%d put it back to head of callersSendQueue",
				 result));

			for (i = HTC_PACKET_QUEUE_DEPTH(&sendQueue); i > 0; i--)
				hif_pm_runtime_put(target->hif_dev);

			HTC_PACKET_QUEUE_TRANSFER_TO_HEAD(&pEndpoint->TxQueue,
							  &sendQueue);
			LOCK_HTC_TX(target);
@@ -1264,6 +1370,9 @@ A_STATUS htc_send_data_pkt(HTC_HANDLE HTCHandle, cdf_nbuf_t netbuf, int Epid,
		}
	}

	if (hif_pm_runtime_get(target->hif_dev))
		return A_ERROR;

	pHtcHdr = (HTC_FRAME_HDR *) cdf_nbuf_get_frag_vaddr(netbuf, 0);
	AR_DEBUG_ASSERT(pHtcHdr);

@@ -1609,6 +1718,9 @@ CDF_STATUS htc_tx_completion_handler(void *Context,
			netbuf = NULL;
			break;
		}
		if (pPacket->PktInfo.AsTx.Tag != HTC_TX_PACKET_TAG_AUTO_PM)
			hif_pm_runtime_put(target->hif_dev);

		if (pPacket->PktInfo.AsTx.Tag == HTC_TX_PACKET_TAG_BUNDLED) {
			HTC_PACKET *pPacketTemp;
			HTC_PACKET_QUEUE *pQueueSave =
+5 −0
Original line number Diff line number Diff line
@@ -3654,6 +3654,8 @@ CDF_STATUS wma_resume_req(tp_wma_handle wma, enum cdf_suspend_type type)
	/* unpause the vdev if left paused and hif_pci_suspend fails */
	wma_unpause_vdev(wma);

	wmi_set_runtime_pm_inprogress(wma->wmi_handle, false);

	return CDF_STATUS_SUCCESS;
}

@@ -4172,6 +4174,9 @@ static void wma_notify_suspend_req_procesed(tp_wma_handle wma,
 */
CDF_STATUS wma_suspend_req(tp_wma_handle wma, enum cdf_suspend_type type)
{
	if (type == CDF_RUNTIME_SUSPEND)
		wmi_set_runtime_pm_inprogress(wma->wmi_handle, true);

	if (wma_is_wow_applicable(wma)) {
		WMA_LOGE("WOW Suspend");
		wma_apply_lphb(wma);
+58 −3
Original line number Diff line number Diff line
/*
 * Copyright (c) 2015 The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
 *
 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
 *
@@ -766,6 +766,30 @@ static inline void wma_log_cmd_id(WMI_CMD_ID cmd_id)
}
#endif

/**
 * wmi_is_runtime_pm_cmd() - check if a cmd is part of the suspend resume sequence
 * @cmd: command to check
 *
 * Return: true if the command is part of the suspend resume sequence.
 */
bool wmi_is_runtime_pm_cmd(WMI_CMD_ID cmd_id)
{
	switch (cmd_id) {
	case WMI_WOW_ENABLE_CMDID:
	case WMI_PDEV_SUSPEND_CMDID:
	case WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID:
	case WMI_WOW_ADD_WAKE_PATTERN_CMDID:
	case WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID:
	case WMI_PDEV_RESUME_CMDID:
	case WMI_WOW_DEL_WAKE_PATTERN_CMDID:
	case WMI_D0_WOW_ENABLE_DISABLE_CMDID:
		return true;

	default:
		return false;
	}
}

/* WMI command API */
int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len,
			 WMI_CMD_ID cmd_id)
@@ -773,8 +797,12 @@ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len,
	HTC_PACKET *pkt;
	A_STATUS status;
	struct ol_softc *scn;
	uint16_t htc_tag = 0;

	if (cdf_atomic_read(&wmi_handle->is_target_suspended) &&
	if (wmi_get_runtime_pm_inprogress(wmi_handle)) {
		if (wmi_is_runtime_pm_cmd(cmd_id))
			htc_tag = HTC_TX_PACKET_TAG_AUTO_PM;
	} else if (cdf_atomic_read(&wmi_handle->is_target_suspended) &&
	    ((WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID != cmd_id) &&
	     (WMI_PDEV_RESUME_CMDID != cmd_id))) {
		pr_err("%s: Target is suspended  could not send WMI command\n",
@@ -830,7 +858,7 @@ int wmi_unified_cmd_send(wmi_unified_t wmi_handle, wmi_buf_t buf, int len,
			       NULL,
			       cdf_nbuf_data(buf), len + sizeof(WMI_CMD_HDR),
	                       /* htt_host_data_dl_len(buf)+20 */
			       wmi_handle->wmi_endpoint_id, 0 /*htc_tag */ );
			       wmi_handle->wmi_endpoint_id, htc_tag);

	SET_HTC_PACKET_NET_BUF_CONTEXT(pkt, buf);

@@ -1160,6 +1188,21 @@ void wmi_rx_event_work(struct work_struct *work)

/* WMI Initialization functions */

#ifdef FEATURE_RUNTIME_PM
/**
 * wmi_runtime_pm_init() - initialize runtime pm wmi variables
 * @wmi_handle: wmi context
 */
void wmi_runtime_pm_init(struct wmi_unified *wmi_handle)
{
	cdf_atomic_init(&wmi_handle->runtime_pm_inprogress);
}
#else
void wmi_runtime_pm_init(struct wmi_unified *wmi_handle)
{
}
#endif

void *wmi_unified_attach(ol_scn_t scn_handle,
			 wma_process_fw_event_handler_cbk func)
{
@@ -1176,6 +1219,7 @@ void *wmi_unified_attach(ol_scn_t scn_handle,
	wmi_handle->scn_handle = scn_handle;
	cdf_atomic_init(&wmi_handle->pending_cmds);
	cdf_atomic_init(&wmi_handle->is_target_suspended);
	wmi_runtime_pm_init(wmi_handle);
	cdf_spinlock_init(&wmi_handle->eventq_lock);
	cdf_nbuf_queue_init(&wmi_handle->event_queue);
#ifdef CONFIG_CNSS
@@ -1335,3 +1379,14 @@ void wmi_set_target_suspend(wmi_unified_t wmi_handle, A_BOOL val)
	cdf_atomic_set(&wmi_handle->is_target_suspended, val);
}

#ifdef FEATURE_RUNTIME_PM
void wmi_set_runtime_pm_inprogress(wmi_unified_t wmi_handle, A_BOOL val)
{
	cdf_atomic_set(&wmi_handle->runtime_pm_inprogress, val);
}

inline bool wmi_get_runtime_pm_inprogress(wmi_unified_t wmi_handle)
{
	return cdf_atomic_read(&wmi_handle->runtime_pm_inprogress);
}
#endif
Loading