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

Commit 2858fdd0 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: ipa: add TAG process"

parents 4ed65771 d827f41a
Loading
Loading
Loading
Loading
+80 −8
Original line number Diff line number Diff line
@@ -27,6 +27,8 @@
#include <linux/interrupt.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
#include <linux/netdevice.h>
#include <linux/delay.h>
#include "ipa_i.h"
#include "ipa_rm_i.h"

@@ -141,6 +143,9 @@ struct ipa_ioc_nat_alloc_mem32 {
};
#endif

static void ipa_start_tag_process(struct work_struct *work);
static DECLARE_WORK(ipa_tag_work, ipa_start_tag_process);

static struct ipa_plat_drv_res ipa_res = {0, };
static struct of_device_id ipa_plat_drv_match[] = {
	{
@@ -1581,6 +1586,52 @@ void ipa_disable_clks(void)
	if (msm_bus_scale_client_update_request(ipa_ctx->ipa_bus_hdl, 0))
		WARN_ON(1);
}
/**
 * ipa_start_tag_process() - Send TAG packet and wait for it to come back
 *
 * This function is called prior to clock gating when active client counter
 * is 1. TAG process ensures that there are no packets inside IPA HW that
 * were not submitted to peer's BAM. During TAG process all aggregation frames
 * are (force) closed.
 *
 * Return codes:
 * None
 */
static void ipa_start_tag_process(struct work_struct *work)
{
	int res;

	IPADBG("starting TAG process\n");
	mutex_lock(&ipa_ctx->ipa_active_clients_lock);
	ipa_ctx->start_tag_process_again = false;
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);

	/* close aggregation frames on all pipes */
	res = ipa_tag_aggr_force_close(-1);
	if (res) {
		IPAERR("ipa_tag_aggr_force_close failed %d\n", res);
		return;
	}

	mutex_lock(&ipa_ctx->ipa_active_clients_lock);
	ipa_ctx->ipa_active_clients--;
	if (ipa_ctx->ipa_active_clients == 0) {
		/* check if during tag process a client used IPA */
		if (ipa_ctx->start_tag_process_again) {
			IPADBG("Starting TAG process again\n");
			ipa_ctx->ipa_active_clients = 1;
			mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
			queue_work(ipa_ctx->power_mgmt_wq, &ipa_tag_work);
			return;
		}
		ipa_disable_clks();
	}
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);

	IPADBG("TAG process done\n");
	return;
}

/**
* ipa_inc_client_enable_clks() - Increase active clients counter, and
* enable ipa clocks if necessary
@@ -1626,8 +1677,12 @@ bail:
}

/**
* ipa_dec_client_disable_clks() - Decrease active clients counter, and
* disable ipa clocks if necessary
 * ipa_dec_client_disable_clks() - Decrease active clients counter
 *
 * In case that there are no active clients this function also starts
 * TAG process. When TAG progress ends ipa clocks will be gated.
 * start_tag_process_again flag is set during this function to signal TAG
 * process to start again as there was another client that may send data to ipa
 *
 * Return codes:
 * None
@@ -1635,10 +1690,16 @@ bail:
void ipa_dec_client_disable_clks(void)
{
	mutex_lock(&ipa_ctx->ipa_active_clients_lock);
	ipa_ctx->start_tag_process_again = true;
	ipa_ctx->ipa_active_clients--;
	IPADBG("active clients = %d\n", ipa_ctx->ipa_active_clients);
	if (ipa_ctx->ipa_active_clients == 0)
		ipa_disable_clks();
	if (ipa_ctx->ipa_active_clients == 0) {
		/* when TAG process ends, active clients will be decreased */
		ipa_ctx->ipa_active_clients = 1;
		mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
		queue_work(ipa_ctx->power_mgmt_wq, &ipa_tag_work);
		return;
	}
	mutex_unlock(&ipa_ctx->ipa_active_clients_lock);
}

@@ -2214,6 +2275,15 @@ static int ipa_init(const struct ipa_plat_drv_res *resource_p,
			MAJOR(ipa_ctx->dev_num),
			MINOR(ipa_ctx->dev_num));

	/* Create workqueue for power management */
	ipa_ctx->power_mgmt_wq =
		create_singlethread_workqueue("ipa_power_mgmt");
	if (!ipa_ctx->power_mgmt_wq) {
		IPAERR("failed to create wq\n");
		result = -ENOMEM;
		goto fail_power_mgmt_wq;
	}

	/* Initialize IPA RM (resource manager) */
	result = ipa_rm_initialize();
	if (result) {
@@ -2273,6 +2343,8 @@ fail_ipa_interrupts_init:
fail_create_apps_resource:
	ipa_rm_exit();
fail_ipa_rm_init:
	destroy_workqueue(ipa_ctx->power_mgmt_wq);
fail_power_mgmt_wq:
	cdev_del(&ipa_ctx->cdev);
fail_cdev_add:
	device_destroy(ipa_ctx->class, ipa_ctx->dev_num);
+7 −5
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ int ipa_disable_data_path(u32 clnt_hdl)
	struct ipa_ep_context *ep = &ipa_ctx->ep[clnt_hdl];
	struct ipa_ep_cfg_holb holb_cfg;
	struct ipa_ep_cfg_ctrl ep_cfg_ctrl;
	u32 aggr_init;
	int res = 0;

	IPADBG("Disabling data path\n");
@@ -86,10 +87,11 @@ int ipa_disable_data_path(u32 clnt_hdl)
	}

	udelay(IPA_PKT_FLUSH_TO_US);
	if (IPA_CLIENT_IS_CONS(ep->client) &&
			ep->cfg.aggr.aggr_en == IPA_ENABLE_AGGR &&
			ep->cfg.aggr.aggr_time_limit)
		msleep(ep->cfg.aggr.aggr_time_limit);
	aggr_init = ipa_read_reg(ipa_ctx->mmio,
			IPA_ENDP_INIT_AGGR_N_OFST_v2_0(clnt_hdl));
	if (((aggr_init & IPA_ENDP_INIT_AGGR_N_AGGR_EN_BMSK) >>
	    IPA_ENDP_INIT_AGGR_N_AGGR_EN_SHFT) == IPA_ENABLE_AGGR)
		ipa_tag_aggr_force_close(clnt_hdl);

	return res;
}
+19 −0
Original line number Diff line number Diff line
@@ -1641,6 +1641,25 @@ begin:
		}
		IPA_STATS_EXCP_CNT(status->exception,
				ipa_ctx->stats.rx_excp_pkts);
		if (status->status_mask & IPA_HW_PKT_STATUS_MASK_TAG_VALID) {
			struct completion *comp;
			IPADBG("TAG packet arrived\n");
			if (status->tag_f_2 != IPA_COOKIE) {
				IPAERR("TAG arrived with wrong cookie\n");
				skb_pull(skb, IPA_PKT_STATUS_SIZE);
				continue;
			}
			skb_pull(skb, IPA_PKT_STATUS_SIZE);
			if (skb->len < sizeof(comp)) {
				IPAERR("TAG arrived without packet\n");
				return rc;
			}

			memcpy(&comp, skb->data, sizeof(comp));
			skb_pull(skb, sizeof(comp));
			complete(comp);
			continue;
		}
		if (status->endp_dest_idx >= IPA_NUM_PIPES ||
			status->endp_src_idx >= IPA_NUM_PIPES ||
			status->pkt_len > IPA_GENERIC_AGGR_BYTE_LIMIT * 1024) {
+45 −17
Original line number Diff line number Diff line
@@ -28,12 +28,12 @@
#define IPA_HDR_INIT_LOCAL        (9)
#define IPA_HDR_INIT_SYSTEM      (10)
#define IPA_DECIPH_SETUP         (11)
#define IPA_INSERT_NAT_RULE   (12)
#define IPA_DELETE_NAT_RULE   (13)
#define IPA_REGISTER_WRITE       (12)
#define IPA_NAT_DMA              (14)
#define IPA_IP_PACKET_TAG        (15)
#define IPA_IP_PACKET_INIT       (16)
#define IPA_DMA_SHARED_MEM       (19)
#define IPA_IP_PACKET_TAG_STATUS (20)

/**
 * struct ipa_flt_rule_hw_hdr - HW header of IPA filter rule
@@ -187,6 +187,22 @@ struct ipa_a5_mux_hdr {
	u32 metadata;
};

/**
 * struct ipa_register_write - IPA_REGISTER_WRITE command payload
 * @rsvd: reserved
 * @skip_pipeline_clear: 0 to wait until IPA pipeline is clear
 * @offset: offset from IPA base address
 * @value: value to write to register
 * @value_mask: mask specifying which value bits to write to the register
 */
struct ipa_register_write {
	u32 rsvd:15;
	u32 skip_pipeline_clear:1;
	u32 offset:16;
	u32 value:32;
	u32 value_mask:32;
};

/**
 * struct ipa_nat_dma - IPA_NAT_DMA command payload
 * @table_index: NAT table index
@@ -262,6 +278,18 @@ struct ipa_ip_packet_tag {
	u32 tag;
};

/**
 * struct ipa_ip_packet_tag_status - IPA_IP_PACKET_TAG_STATUS command payload
 * @rsvd: reserved
 * @tag_f_1: tag value returned within status
 * @tag_f_2: tag value returned within status
 */
struct ipa_ip_packet_tag_status {
	u32 rsvd:16;
	u32 tag_f_1:16;
	u32 tag_f_2:32;
};

/*! @brief Struct for the the IPA UL packet status header */
struct ipa_hw_pkt_status {
	u32 status_opcode:8;
+7 −0
Original line number Diff line number Diff line
@@ -640,6 +640,8 @@ struct ipa_controller;
 * @ip4_flt_tbl_lcl: where ip4 flt tables reside 1-local; 0-system
 * @ip6_flt_tbl_lcl: where ip6 flt tables reside 1-local; 0-system
 * @empty_rt_tbl_mem: empty routing tables memory
 * @power_mgmt_wq: workqueue for power management
 * @start_tag_process_again: indicates whether to start tag process again
 * @pipe_mem_pool: pipe memory pool
 * @dma_pool: special purpose DMA pool
 * @ipa_hw_type: type of IPA HW type (e.g. IPA 1.0, IPA 1.1 etc')
@@ -698,6 +700,8 @@ struct ipa_context {
	struct dma_pool *dma_pool;
	struct mutex ipa_active_clients_lock;
	int ipa_active_clients;
	struct workqueue_struct *power_mgmt_wq;
	bool start_tag_process_again;
	u32 clnt_hdl_cmd;
	u32 clnt_hdl_data_in;
	u32 clnt_hdl_data_out;
@@ -942,5 +946,8 @@ int ipa_suspend_resource_no_block(enum ipa_rm_resource_name name);
int ipa_suspend_resource_sync(enum ipa_rm_resource_name name);
int ipa_resume_resource(enum ipa_rm_resource_name name);
bool ipa_should_pipe_be_suspended(enum ipa_client_type client);
int ipa_tag_aggr_force_close(int pipe_num);



#endif /* _IPA_I_H_ */
Loading