Просмотр исходного кода

msm: camera: common: Page Fault notification to userspace

Upon Page Fault, smmu driver invokes faulted client's callback
which looks for faulted buffer and context. The client driver
can be ISP, ICP, JPEG, IFE CDM and CPAS CDM. The driver then
fills PF msg struct, logs related info, and notify PF msg to
userspace. Userspace is expected to abort and calls to shut
down kernel drivers. When Titan powers on next session, CAMSS
undergoes async reset.
This change also ensures the page fault related changes added
to TFE, OPE, CRE do not break the drivers compilation.

CRs-Fixed: 3156671
Change-Id: Icd6c8c9a38cac206fe8260d374d03964fb280879
Signed-off-by: sokchetra eung <[email protected]>
sokchetra eung 3 лет назад
Родитель
Сommit
c52c83e7ce
31 измененных файлов с 1035 добавлено и 864 удалено
  1. 67 34
      drivers/cam_cdm/cam_cdm_core_common.c
  2. 3 2
      drivers/cam_cdm/cam_cdm_intf_api.h
  3. 21 3
      drivers/cam_core/cam_context.c
  4. 19 19
      drivers/cam_core/cam_context.h
  5. 164 12
      drivers/cam_core/cam_context_utils.c
  6. 5 3
      drivers/cam_core/cam_context_utils.h
  7. 89 45
      drivers/cam_core/cam_hw_mgr_intf.h
  8. 23 21
      drivers/cam_cre/cam_cre_context.c
  9. 24 7
      drivers/cam_cre/cam_cre_dev.c
  10. 12 73
      drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.c
  11. 2 1
      drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.h
  12. 7 1
      drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
  13. 25 25
      drivers/cam_icp/cam_icp_context.c
  14. 24 7
      drivers/cam_icp/cam_icp_subdev.c
  15. 21 79
      drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
  16. 79 98
      drivers/cam_isp/cam_isp_context.c
  17. 23 6
      drivers/cam_isp/cam_isp_dev.c
  18. 64 87
      drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
  19. 4 1
      drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h
  20. 19 89
      drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c
  21. 22 21
      drivers/cam_jpeg/cam_jpeg_context.c
  22. 24 7
      drivers/cam_jpeg/cam_jpeg_dev.c
  23. 14 72
      drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
  24. 21 27
      drivers/cam_ope/cam_ope_context.c
  25. 23 7
      drivers/cam_ope/cam_ope_subdev.c
  26. 50 87
      drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c
  27. 1 1
      drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h
  28. 12 4
      drivers/cam_smmu/cam_smmu_api.c
  29. 27 17
      drivers/cam_smmu/cam_smmu_api.h
  30. 124 4
      drivers/cam_utils/cam_packet_util.c
  31. 22 4
      drivers/cam_utils/cam_packet_util.h

+ 67 - 34
drivers/cam_cdm/cam_cdm_core_common.c

@@ -193,6 +193,17 @@ int cam_cdm_find_free_client_slot(struct cam_cdm *hw)
 	return -EBUSY;
 }
 
+static int cam_cdm_get_last_client_idx(struct cam_cdm *core)
+{
+	int i, last_client = 0;
+
+	for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) {
+		if (core->clients[i])
+			last_client = i;
+	}
+
+	return last_client;
+}
 
 void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 	enum cam_cdm_cb_status status, void *data)
@@ -200,6 +211,9 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 	int i;
 	struct cam_cdm *core = NULL;
 	struct cam_cdm_client *client = NULL;
+	struct cam_cdm_bl_cb_request_entry *node = NULL;
+	struct cam_hw_dump_pf_args pf_args = {0};
+	int client_idx, last_client;
 
 	if (!cdm_hw) {
 		CAM_ERR(CAM_CDM, "CDM Notify called with NULL hw info");
@@ -207,10 +221,9 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 	}
 	core = (struct cam_cdm *)cdm_hw->core_info;
 
-	if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
-		int client_idx;
-		struct cam_cdm_bl_cb_request_entry *node =
-			(struct cam_cdm_bl_cb_request_entry *)data;
+	switch (status) {
+	case CAM_CDM_CB_STATUS_BL_SUCCESS:
+		node = (struct cam_cdm_bl_cb_request_entry *)data;
 
 		client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl);
 		client = core->clients[client_idx];
@@ -226,7 +239,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 				client->data.identifier, node->cookie);
 			client->data.cam_cdm_callback(node->client_hdl,
 				node->userdata, CAM_CDM_CB_STATUS_BL_SUCCESS,
-				node->cookie);
+				(void *)(&node->cookie));
 			CAM_DBG(CAM_CDM, "Exit client cb cookie=%d",
 				node->cookie);
 		} else {
@@ -235,15 +248,13 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 		}
 		mutex_unlock(&client->lock);
 		cam_cdm_put_client_refcount(client);
-		return;
-	} else if (status == CAM_CDM_CB_STATUS_HW_RESET_DONE ||
-			status == CAM_CDM_CB_STATUS_HW_FLUSH ||
-			status == CAM_CDM_CB_STATUS_HW_RESUBMIT ||
-			status == CAM_CDM_CB_STATUS_INVALID_BL_CMD ||
-			status == CAM_CDM_CB_STATUS_HW_ERROR) {
-		int client_idx;
-		struct cam_cdm_bl_cb_request_entry *node =
-			(struct cam_cdm_bl_cb_request_entry *)data;
+		break;
+	case CAM_CDM_CB_STATUS_HW_RESET_DONE:
+	case CAM_CDM_CB_STATUS_HW_FLUSH:
+	case CAM_CDM_CB_STATUS_HW_RESUBMIT:
+	case CAM_CDM_CB_STATUS_INVALID_BL_CMD:
+	case CAM_CDM_CB_STATUS_HW_ERROR:
+		node = (struct cam_cdm_bl_cb_request_entry *)data;
 
 		client_idx = CAM_CDM_GET_CLIENT_IDX(node->client_hdl);
 		client = core->clients[client_idx];
@@ -259,7 +270,7 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 				client->handle,
 				client->data.userdata,
 				status,
-				node->cookie);
+				(void *)(&node->cookie));
 		} else {
 			CAM_ERR(CAM_CDM,
 				"No cb registered for client: name %s, hdl=%x",
@@ -267,34 +278,56 @@ void cam_cdm_notify_clients(struct cam_hw_info *cdm_hw,
 		}
 		mutex_unlock(&client->lock);
 		cam_cdm_put_client_refcount(client);
-		return;
-	}
-
-	for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) {
-		if (core->clients[i] != NULL) {
+		break;
+	case CAM_CDM_CB_STATUS_PAGEFAULT:
+		last_client = cam_cdm_get_last_client_idx(core);
+		pf_args.pf_smmu_info = (struct cam_smmu_pf_info *)data;
+		pf_args.handle_sec_pf = true;
+		for (i = 0; i < CAM_PER_CDM_MAX_REGISTERED_CLIENTS; i++) {
 			client = core->clients[i];
+			if (!client)
+				continue;
 			cam_cdm_get_client_refcount(client);
-			mutex_lock(&client->lock);
-			CAM_DBG(CAM_CDM, "Found client slot %d", i);
 			if (client->data.cam_cdm_callback) {
-				if (status == CAM_CDM_CB_STATUS_PAGEFAULT) {
-					unsigned long iova =
-						(unsigned long)data;
-
-					client->data.cam_cdm_callback(
-						client->handle,
-						client->data.userdata,
-						CAM_CDM_CB_STATUS_PAGEFAULT,
-						(iova & 0xFFFFFFFF));
+				if (i == last_client)
+					/*
+					 * If the fault causing client is not found,
+					 * make the last client of this CDM sends PF
+					 * notification to userspace. This avoids multiple
+					 * PF notifications and ensures at least one
+					 * notification is sent.
+					 */
+					pf_args.pf_context_info.force_send_pf_evt = true;
+				mutex_lock(&client->lock);
+				CAM_DBG(CAM_CDM, "Found client slot %d name %s",
+					i, client->data.identifier);
+				client->data.cam_cdm_callback(
+					client->handle,
+					client->data.userdata,
+					status,
+					&pf_args);
+				if (pf_args.pf_context_info.ctx_found ||
+					pf_args.pf_context_info.force_send_pf_evt) {
+					if (pf_args.pf_context_info.ctx_found)
+						CAM_ERR(CAM_CDM,
+							"Page Fault found on client: [%s][%u]",
+							client->data.identifier,
+							client->data.cell_index);
+					mutex_unlock(&client->lock);
+					cam_cdm_put_client_refcount(client);
+					break;
 				}
+				mutex_unlock(&client->lock);
 			} else {
-				CAM_ERR(CAM_CDM,
-					"No cb registered for client hdl=%x",
+				CAM_ERR(CAM_CDM, "No cb registered for client hdl=%x",
 					client->handle);
 			}
-			mutex_unlock(&client->lock);
 			cam_cdm_put_client_refcount(client);
 		}
+
+		break;
+	default:
+		CAM_ERR(CAM_CDM, "Invalid cdm cb status: %u", status);
 	}
 }
 

+ 3 - 2
drivers/cam_cdm/cam_cdm_intf_api.h

@@ -75,7 +75,8 @@ enum cam_cdm_bl_fifo_queue {
  *                     @handle : CDM Client handle
  *                     @userdata : Private data given at the time of acquire
  *                     @status : Callback status
- *                     @cookie : Cookie if the callback is gen irq status
+ *                     @cookie : Cookie if the callback is gen irq status or
+ *                               pf_args if it is page fault
  * @base_array_cnt : Input number of ioremapped address pair pointing
  *                     in base_array, needed only if selected cdm is a virtual.
  * @base_array : Input pointer to ioremapped address pair arrary
@@ -96,7 +97,7 @@ struct cam_cdm_acquire_data {
 	enum cam_cdm_id id;
 	void *userdata;
 	void (*cam_cdm_callback)(uint32_t handle, void *userdata,
-		enum cam_cdm_cb_status status, uint64_t cookie);
+		enum cam_cdm_cb_status status, void *cookie);
 	uint32_t base_array_cnt;
 	struct cam_soc_reg_map *base_array[CAM_SOC_MAX_BLOCK];
 	enum cam_cdm_bl_fifo_queue priority;

+ 21 - 3
drivers/cam_core/cam_context.c

@@ -11,6 +11,7 @@
 #include "cam_context.h"
 #include "cam_debug_util.h"
 #include "cam_node.h"
+#include "cam_context_utils.h"
 
 static int cam_context_handle_hw_event(void *context, uint32_t evt_id,
 	void *evt_data)
@@ -311,11 +312,28 @@ int cam_context_mini_dump_from_hw(struct cam_context *ctx,
 	return rc;
 }
 
-int cam_context_dump_pf_info(struct cam_context *ctx,
-	struct cam_smmu_pf_info *pf_info)
+int cam_context_dump_pf_info(void *data, void *args)
 {
+	struct cam_context *ctx = data;
+	struct cam_hw_dump_pf_args *pf_args = args;
 	int rc = 0;
 
+	if (!pf_args) {
+		CAM_ERR(CAM_CORE, "PF args is NULL");
+		return -EINVAL;
+	}
+
+	if (!ctx) {
+		CAM_ERR(CAM_CORE, "Context is NULL");
+		if (pf_args->pf_context_info.force_send_pf_evt) {
+			rc = cam_context_send_pf_evt(ctx, pf_args);
+			if (rc)
+				CAM_ERR(CAM_CORE,
+					"Failed to notify PF event to userspace rc: %d", rc);
+		}
+		return -EINVAL;
+	}
+
 	if (!ctx->state_machine) {
 		CAM_ERR(CAM_CORE, "Context is not ready");
 		return -EINVAL;
@@ -326,7 +344,7 @@ int cam_context_dump_pf_info(struct cam_context *ctx,
 		(ctx->state < CAM_CTX_STATE_MAX)) {
 		if (ctx->state_machine[ctx->state].pagefault_ops) {
 			rc = ctx->state_machine[ctx->state].pagefault_ops(
-				ctx, pf_info);
+				ctx, pf_args);
 		} else {
 			CAM_WARN(CAM_CORE, "No dump ctx in dev %d, state %d",
 				ctx->dev_hdl, ctx->state);

+ 19 - 19
drivers/cam_core/cam_context.h

@@ -70,22 +70,22 @@ enum cam_context_state {
  *
  */
 struct cam_ctx_request {
-	struct list_head               list;
-	uint32_t                       status;
-	uint64_t                       request_id;
-	void                          *req_priv;
-	struct cam_hw_update_entry    *hw_update_entries;
-	uint32_t                       num_hw_update_entries;
-	struct cam_hw_fence_map_entry *in_map_entries;
-	uint32_t                       num_in_map_entries;
-	struct cam_hw_fence_map_entry *out_map_entries;
-	uint32_t                       num_out_map_entries;
-	atomic_t                       num_in_acked;
-	uint32_t                       num_out_acked;
-	uint32_t                       index;
-	int                            flushed;
-	struct cam_context            *ctx;
-	struct cam_hw_mgr_dump_pf_data pf_data;
+	struct list_head                  list;
+	uint32_t                          status;
+	uint64_t                          request_id;
+	void                             *req_priv;
+	struct cam_hw_update_entry       *hw_update_entries;
+	uint32_t                          num_hw_update_entries;
+	struct cam_hw_fence_map_entry    *in_map_entries;
+	uint32_t                          num_in_map_entries;
+	struct cam_hw_fence_map_entry    *out_map_entries;
+	uint32_t                          num_out_map_entries;
+	atomic_t                          num_in_acked;
+	uint32_t                          num_out_acked;
+	uint32_t                          index;
+	int                               flushed;
+	struct cam_context               *ctx;
+	struct cam_hw_mgr_pf_request_info pf_data;
 };
 
 /**
@@ -406,11 +406,11 @@ int cam_context_mini_dump_from_hw(struct cam_context *ctx,
  * @brief:        Handle dump active request request command
  *
  * @ctx:          Object pointer for cam_context
- * @pf_info:      Smmu page fault info
+ * @pf_args:      pf args to dump pf info to hw
  *
  */
-int cam_context_dump_pf_info(struct cam_context *ctx,
-	struct cam_smmu_pf_info *pf_info);
+int cam_context_dump_pf_info(void *ctx,
+	void *pf_args);
 
 /**
  * cam_context_handle_acquire_dev()

+ 164 - 12
drivers/cam_core/cam_context_utils.c

@@ -16,6 +16,7 @@
 #include "cam_mem_mgr.h"
 #include "cam_node.h"
 #include "cam_req_mgr_util.h"
+#include "cam_req_mgr_dev.h"
 #include "cam_sync_api.h"
 #include "cam_trace.h"
 #include "cam_debug_util.h"
@@ -510,7 +511,7 @@ int32_t cam_context_prepare_dev_to_hw(struct cam_context *ctx,
 	req->num_out_acked          = 0;
 	req->flushed                = 0;
 	atomic_set(&req->num_in_acked, 0);
-	memset(&req->pf_data, 0, sizeof(struct cam_hw_mgr_dump_pf_data));
+	memset(&req->pf_data, 0, sizeof(struct cam_hw_mgr_pf_request_info));
 
 	remain_len = cam_context_parse_config_cmd(ctx, cmd, &packet);
 	if (IS_ERR(packet)) {
@@ -1193,12 +1194,169 @@ end:
 	return rc;
 }
 
+static void cam_context_util_translate_pf_info_to_string(struct cam_req_mgr_pf_err_msg *pf_msg,
+	char **pf_evt_str, char **pf_type_str, char **pf_stage_str)
+{
+	switch (pf_msg->pf_evt) {
+	case CAM_REQ_MGR_PF_EVT_BUF_NOT_FOUND:
+		*pf_evt_str = "PF Evt: faulting buffer not found";
+		break;
+	case CAM_REQ_MGR_PF_EVT_BUF_FOUND_IO_CFG:
+		*pf_evt_str = "PF Evt: faulting IO Config buffer";
+		break;
+	case CAM_REQ_MGR_PF_EVT_BUF_FOUND_REF_BUF:
+		*pf_evt_str = "PF Evt: faulting Ref buffer";
+		break;
+	case CAM_REQ_MGR_PF_EVT_BUF_FOUND_CDM:
+		*pf_evt_str = "PF Evt: faulting CDM buffer";
+		break;
+	case CAM_REQ_MGR_PF_EVT_BUF_FOUND_SHARED:
+		*pf_evt_str = "PF Evt: faulting shared memory buffer";
+		break;
+	default:
+		CAM_ERR(CAM_CTXT, "Invalid PF Evt %u", pf_msg->pf_evt);
+		*pf_evt_str = "PF Evt: Unknown";
+	}
+
+	switch (pf_msg->pf_type) {
+	case CAM_REQ_MGR_PF_TYPE_NULL:
+		*pf_type_str = "PF Type: faulting addr is NULL";
+		break;
+	case CAM_REQ_MGR_PF_TYPE_OUT_OF_BOUND:
+		*pf_type_str = "PF Type: faulting addr out of bounds";
+		break;
+	case CAM_REQ_MGR_PF_TYPE_MAPPED_REGION:
+		*pf_type_str = "PF Type: faulting addr within mapped region";
+		break;
+	default:
+		CAM_ERR(CAM_CTXT, "Invalid PF Type %u", pf_msg->pf_type);
+		*pf_type_str = "PF Type: Unknown";
+	}
+
+	switch (pf_msg->pf_stage) {
+	case CAM_REQ_MGR_STAGE1_FAULT:
+		*pf_stage_str = "PF Stage: stage 1 (non-secure)";
+		break;
+	case CAM_REQ_MGR_STAGE2_FAULT:
+		*pf_stage_str = "PF Stage: stage 2 (secure)";
+		break;
+	default:
+		CAM_ERR(CAM_CTXT, "Invalid PF Stage %u", pf_msg->pf_stage);
+		*pf_stage_str = "PF Stage: Unknown";
+	}
+}
+
+static void cam_context_get_pf_evt(struct cam_context *ctx,
+	struct cam_context_pf_info  *pf_context_info, struct cam_req_mgr_pf_err_msg *pf_msg,
+	char *log_info, size_t *len, uint32_t buf_size)
+{
+	if (pf_context_info->mem_type != CAM_FAULT_BUF_NOT_FOUND) {
+		pf_msg->buf_hdl = pf_context_info->buf_hdl;
+		pf_msg->offset = pf_context_info->offset;
+		pf_msg->far_delta = pf_context_info->delta;
+		pf_msg->req_id = pf_context_info->req_id;
+
+		CAM_ERR_BUF(CAM_CTXT, log_info, buf_size, len,
+			"buf_hdl: 0x%x, offset: 0x%x, req_id: %llu, delta: 0x%llx",
+			pf_msg->buf_hdl, pf_msg->offset, pf_msg->req_id,
+			pf_msg->far_delta);
+
+		if (pf_context_info->mem_type == CAM_FAULT_PATCH_BUF) {
+			pf_msg->patch_id = pf_context_info->patch_idx;
+			if (pf_context_info->mem_flag & CAM_MEM_FLAG_CMD_BUF_TYPE)
+				pf_msg->pf_evt = CAM_REQ_MGR_PF_EVT_BUF_FOUND_CDM;
+			else if (pf_context_info->mem_flag & CAM_MEM_FLAG_HW_SHARED_ACCESS)
+				pf_msg->pf_evt = CAM_REQ_MGR_PF_EVT_BUF_FOUND_SHARED;
+			else
+				pf_msg->pf_evt = CAM_REQ_MGR_PF_EVT_BUF_FOUND_REF_BUF;
+
+			CAM_ERR_BUF(CAM_CTXT, log_info, buf_size, len,
+				"Faulted patch found in patch index: %u",
+				pf_msg->patch_id);
+		} else
+			pf_msg->pf_evt = CAM_REQ_MGR_PF_EVT_BUF_FOUND_IO_CFG;
+
+	} else
+		pf_msg->pf_evt = CAM_REQ_MGR_PF_EVT_BUF_NOT_FOUND;
+
+}
+
+int32_t cam_context_send_pf_evt(struct cam_context *ctx,
+	struct cam_hw_dump_pf_args *pf_args)
+{
+	struct cam_req_mgr_message           req_msg = {0};
+	struct cam_req_mgr_pf_err_msg       *pf_msg = &req_msg.u.pf_err_msg;
+	struct cam_context_pf_info          *pf_context_info;
+	struct cam_smmu_pf_info             *pf_smmu_info;
+	char log_info[512];
+	int rc = 0;
+	size_t buf_size = 0, len = 0;
+	char *pf_evt_str, *pf_type_str, *pf_stage_str;
+
+	if (!pf_args) {
+		CAM_ERR(CAM_CTXT, "Invalid input PF args");
+		return -EINVAL;
+	}
+
+	buf_size = sizeof(log_info);
+	pf_msg->pf_evt = CAM_REQ_MGR_PF_EVT_BUF_NOT_FOUND;
+	pf_context_info = &(pf_args->pf_context_info);
+	pf_smmu_info = pf_args->pf_smmu_info;
+
+	if (ctx) {
+		req_msg.session_hdl = ctx->session_hdl;
+		pf_msg->device_hdl = ctx->dev_hdl;
+		pf_msg->link_hdl = ctx->link_hdl;
+		pf_msg->port_id = pf_context_info->resource_type;
+
+		CAM_ERR_BUF(CAM_CTXT, log_info, buf_size, &len,
+			"Faulted ctx: [%s][%d] session_hdl: 0x%x, device_hdl: 0x%x, link_hdl: 0x%x, port_id: 0x%x",
+			ctx->dev_name, ctx->ctx_id, req_msg.session_hdl, pf_msg->device_hdl,
+			pf_msg->link_hdl, pf_msg->port_id);
+
+		cam_context_get_pf_evt(ctx, pf_context_info, pf_msg, log_info, &len, buf_size);
+	} else
+		CAM_ERR_BUF(CAM_CTXT, log_info, buf_size, &len, "Faulted ctx NOT found");
+
+	if (pf_smmu_info->iova == 0)
+		pf_msg->pf_type = CAM_REQ_MGR_PF_TYPE_NULL;
+	else if (pf_smmu_info->in_map_region)
+		pf_msg->pf_type = CAM_REQ_MGR_PF_TYPE_MAPPED_REGION;
+	else
+		pf_msg->pf_type = CAM_REQ_MGR_PF_TYPE_OUT_OF_BOUND;
+
+	pf_msg->pf_stage = pf_smmu_info->is_secure;
+	pf_msg->bid = pf_smmu_info->bid;
+	pf_msg->pid = pf_smmu_info->pid;
+	pf_msg->mid = pf_smmu_info->mid;
+
+	cam_context_util_translate_pf_info_to_string(pf_msg, &pf_evt_str,
+		&pf_type_str, &pf_stage_str);
+
+	CAM_ERR_BUF(CAM_CTXT, log_info, buf_size, &len,
+		"%s, %s, %s",
+		pf_evt_str, pf_type_str, pf_stage_str);
+
+	CAM_ERR_BUF(CAM_CTXT, log_info, buf_size, &len,
+		"bid: %u, pid: %u, mid: %u",
+		pf_msg->bid, pf_msg->pid, pf_msg->mid);
+
+	CAM_ERR(CAM_CTXT, "PF INFO: %s", log_info);
+
+	rc = cam_req_mgr_notify_message(&req_msg,
+		V4L_EVENT_CAM_REQ_MGR_PF_ERROR,
+		V4L_EVENT_CAM_REQ_MGR_EVENT);
+
+	return rc;
+}
+
 int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx,
-	struct cam_hw_mgr_dump_pf_data *pf_data, bool *mem_found, bool *ctx_found,
-	uint32_t  *resource_type, struct cam_smmu_pf_info *pf_info)
+	struct cam_hw_dump_pf_args *pf_args,
+	struct cam_hw_mgr_pf_request_info *pf_req_info)
 {
 	int rc = 0;
 	struct cam_hw_cmd_args cmd_args;
+	struct cam_hw_cmd_pf_args pf_cmd_args;
 
 	if (!ctx) {
 		CAM_ERR(CAM_CTXT, "Invalid input params %pK ", ctx);
@@ -1214,17 +1372,11 @@ int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx,
 	}
 
 	if (ctx->hw_mgr_intf->hw_cmd) {
+		pf_cmd_args.pf_args = pf_args;
+		pf_cmd_args.pf_req_info = pf_req_info;
 		cmd_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
 		cmd_args.cmd_type = CAM_HW_MGR_CMD_DUMP_PF_INFO;
-		cmd_args.u.pf_args.pf_data = *pf_data;
-		cmd_args.u.pf_args.iova = pf_info->iova;
-		cmd_args.u.pf_args.buf_info = pf_info->buf_info;
-		cmd_args.u.pf_args.mem_found = mem_found;
-		cmd_args.u.pf_args.ctx_found = ctx_found;
-		cmd_args.u.pf_args.resource_type = resource_type;
-		cmd_args.u.pf_args.bid = pf_info->bid;
-		cmd_args.u.pf_args.pid = pf_info->pid;
-		cmd_args.u.pf_args.mid = pf_info->mid;
+		cmd_args.u.pf_cmd_args = &pf_cmd_args;
 		ctx->hw_mgr_intf->hw_cmd(ctx->hw_mgr_intf->hw_mgr_priv,
 			&cmd_args);
 	}

+ 5 - 3
drivers/cam_core/cam_context_utils.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CAM_CONTEXT_UTILS_H_
@@ -27,10 +28,11 @@ int32_t cam_context_flush_dev_to_hw(struct cam_context *ctx,
 int32_t cam_context_flush_ctx_to_hw(struct cam_context *ctx);
 int32_t cam_context_flush_req_to_hw(struct cam_context *ctx,
 	struct cam_flush_dev_cmd *cmd);
+int32_t cam_context_send_pf_evt(struct cam_context *ctx,
+	struct cam_hw_dump_pf_args *pf_args);
 int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx,
-	struct cam_hw_mgr_dump_pf_data *pf_data, bool *mem_found, bool *ctx_found,
-	uint32_t  *resource_type,
-	struct cam_smmu_pf_info *pf_info);
+	struct cam_hw_dump_pf_args *pf_args,
+	struct cam_hw_mgr_pf_request_info *pf_req_info);
 int32_t cam_context_dump_hw_acq_info(struct cam_context *ctx);
 int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
 	struct cam_dump_req_cmd *cmd);

+ 89 - 45
drivers/cam_core/cam_hw_mgr_intf.h

@@ -41,6 +41,17 @@ enum cam_context_dump_id {
 	CAM_CTX_DUMP_TYPE_MAX,
 };
 
+/**
+ * enum cam_faulted_mem_type -
+ *    page fault buffer type found in packet
+ *
+ */
+enum cam_faulted_mem_type {
+	CAM_FAULT_BUF_NOT_FOUND,
+	CAM_FAULT_IO_CFG_BUF,
+	CAM_FAULT_PATCH_BUF
+};
+
 #define CAM_CTX_EVT_ID_SUCCESS 0
 #define CAM_CTX_EVT_ID_ERROR   1
 #define CAM_CTX_EVT_ID_CANCEL  2
@@ -51,7 +62,7 @@ typedef int (*cam_hw_event_cb_func)(void *context, uint32_t evt_id,
 
 /* hardware page fault callback function type */
 typedef int (*cam_hw_pagefault_cb_func)(void *context,
-	struct cam_smmu_pf_info *pf_info);
+	void *pf_args);
 
 /* ctx dump callback function type */
 typedef int (*cam_ctx_info_dump_cb_func)(void *context,
@@ -138,6 +149,10 @@ struct cam_hw_acquire_stream_caps {
  * @context_data:          Context data pointer for the callback function
  * @ctx_id:                Core context id
  * @event_cb:              Callback function array
+ * @sec_pf_evt_cb:         Callback function for secondary page fault from HW to ctx.
+ *                         It's the callback that pertains to a PF not directly on
+ *                         this HW. But a different block to which this HW is
+ *                         associated or is a client of
  * @num_acq:               Total number of acquire in the payload
  * @acquire_info:          Acquired resource array pointer
  * @ctxt_to_hw_map:        HW context (returned)
@@ -157,6 +172,7 @@ struct cam_hw_acquire_args {
 	void                        *context_data;
 	uint32_t                     ctx_id;
 	cam_hw_event_cb_func         event_cb;
+	cam_hw_pagefault_cb_func     sec_pf_evt_cb;
 	uint32_t                     num_acq;
 	uint32_t                     acquire_info_size;
 	uintptr_t                    acquire_info;
@@ -212,12 +228,12 @@ struct cam_hw_stop_args {
 
 
 /**
- * struct cam_hw_mgr_dump_pf_data - page fault debug data
+ * struct cam_hw_mgr_pf_request_info - page fault debug data
  *
  * @packet:     pointer to packet
  * @req:        pointer to req (HW specific)
  */
-struct cam_hw_mgr_dump_pf_data {
+struct cam_hw_mgr_pf_request_info {
 	void    *packet;
 	void    *req;
 };
@@ -244,23 +260,23 @@ struct cam_hw_mgr_dump_pf_data {
  *
  */
 struct cam_hw_prepare_update_args {
-	struct cam_packet              *packet;
-	size_t                          remain_len;
-	void                           *ctxt_to_hw_map;
-	uint32_t                        max_hw_update_entries;
-	struct cam_hw_update_entry     *hw_update_entries;
-	uint32_t                        num_hw_update_entries;
-	uint32_t                        max_out_map_entries;
-	struct cam_hw_fence_map_entry  *out_map_entries;
-	uint32_t                        num_out_map_entries;
-	uint32_t                        max_in_map_entries;
-	struct cam_hw_fence_map_entry  *in_map_entries;
-	uint32_t                        num_in_map_entries;
-	struct cam_cmd_buf_desc         reg_dump_buf_desc[
-					CAM_REG_DUMP_MAX_BUF_ENTRIES];
-	uint32_t                        num_reg_dump_buf;
-	void                           *priv;
-	struct cam_hw_mgr_dump_pf_data *pf_data;
+	struct cam_packet                      *packet;
+	size_t                                  remain_len;
+	void                                   *ctxt_to_hw_map;
+	uint32_t                                max_hw_update_entries;
+	struct cam_hw_update_entry             *hw_update_entries;
+	uint32_t                                num_hw_update_entries;
+	uint32_t                                max_out_map_entries;
+	struct cam_hw_fence_map_entry          *out_map_entries;
+	uint32_t                                num_out_map_entries;
+	uint32_t                                max_in_map_entries;
+	struct cam_hw_fence_map_entry          *in_map_entries;
+	uint32_t                                num_in_map_entries;
+	struct cam_cmd_buf_desc                 reg_dump_buf_desc[
+						CAM_REG_DUMP_MAX_BUF_ENTRIES];
+	uint32_t                                num_reg_dump_buf;
+	void                                   *priv;
+	struct cam_hw_mgr_pf_request_info      *pf_data;
 };
 
 /**
@@ -339,31 +355,59 @@ struct cam_hw_flush_args {
 };
 
 /**
- * struct cam_hw_dump_pf_args - Payload for dump pf info command
- *
- * @pf_data:               Debug data for page fault
- * @iova:                  Page fault address
- * @buf_info:              Info about memory buffer where page
- *                               fault occurred
- * @mem_found:             If fault memory found in current
- *                               request
- * @ctx_found              If fault pid found in context acquired hardware
- * @resource_type          Resource type of the port which caused pf
- * @bid:                   Indicate the bus id
- * @pid:                   Indicates unique hw group ports
- * @mid:                   Indicates port id of the camera hw
+ * struct cam_context_pf_info - Page Fault related info to the faulted context
+ *
+ * @mem_type:              Faulted memory type found in packet
+ * @resource_type:         Resource type of the port which caused page fault
+ * @buf_hdl:               Faulted memory handle
+ * @offset:                Offset for faulted buf_hdl
+ * @req_id:                request id for the faulted request
+ * @delta:                 Delta size between faulted address and buffer
+ *                         Or closest-mapped buffer
+ *                         (if faulted addr isn't found to be in any buffer)
+ * @patch_idx:             Index to which patch in the packet is faulted
+ * @mem_flag:              Memory flag of the faulted buffer
+ * @ctx_found:             If fault pid found in context acquired hardware
+ * @force_send_pf_evt:     Must send page fault notification to UMD even if
+ *                         current ctx is not the faulted ctx
+ */
+struct cam_context_pf_info {
+	enum cam_faulted_mem_type mem_type;
+	uint32_t                  resource_type;
+	int32_t                   buf_hdl;
+	uint32_t                  offset;
+	unsigned long             delta;
+	uint32_t                  patch_idx;
+	uint32_t                  mem_flag;
+	uint64_t                  req_id;
+	bool                      ctx_found;
+	bool                      force_send_pf_evt;
+};
+
+/**
+ * struct cam_hw_dump_pf_args - General payload contains all PF relateed info.
  *
+ * @pf_smmu_info:          Page fault info from SMMU driver
+ * @pf_context_info:       Page fault info related to faulted context or
+ *                         faulted request.
+ * @handle_sec_pf:         Indicates if this PF args comes from HW level
  */
 struct cam_hw_dump_pf_args {
-	struct cam_hw_mgr_dump_pf_data  pf_data;
-	unsigned long                   iova;
-	uint32_t                        buf_info;
-	bool                           *mem_found;
-	bool                           *ctx_found;
-	uint32_t                       *resource_type;
-	uint32_t                        bid;
-	uint32_t                        pid;
-	uint32_t                        mid;
+	struct cam_smmu_pf_info    *pf_smmu_info;
+	struct cam_context_pf_info  pf_context_info;
+	bool                        handle_sec_pf;
+};
+
+/**
+ * struct cam_hw_cmd_pf_args - page fault command payload to hw manager.
+ * @pf_args:            Page Fault related info.
+ * @cmd_pf_req_info:    Command payload related to request info. Used to
+ *                      submit to HW for PF processing.
+ *
+ */
+struct cam_hw_cmd_pf_args {
+	struct cam_hw_dump_pf_args          *pf_args;
+	struct cam_hw_mgr_pf_request_info   *pf_req_info;
 };
 
 /**
@@ -408,15 +452,15 @@ enum cam_hw_mgr_command {
  * @ctxt_to_hw_map:        HW context from the acquire
  * @cmd_type               HW command type
  * @internal_args          Arguments for internal command
- * @pf_args                Arguments for Dump PF info command
+ * @pf_cmd_args            Arguments for Dump PF info command
  *
  */
 struct cam_hw_cmd_args {
 	void                               *ctxt_to_hw_map;
 	uint32_t                            cmd_type;
 	union {
-		void                       *internal_args;
-		struct cam_hw_dump_pf_args  pf_args;
+		void                           *internal_args;
+		struct cam_hw_cmd_pf_args      *pf_cmd_args;
 	} u;
 };
 

+ 23 - 21
drivers/cam_cre/cam_cre_context.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/debugfs.h>
@@ -131,22 +132,18 @@ static int __cam_cre_ctx_handle_buf_done_in_ready(void *ctx,
 	return cam_context_buf_done_from_hw(ctx, done, evt_id);
 }
 
-static int cam_cre_context_dump_active_request(void *data,
-	struct cam_smmu_pf_info *pf_info)
+static int cam_cre_context_dump_active_request(void *data, void *args)
 {
 
-	struct cam_context *ctx = (struct cam_context *)data;
-	struct cam_ctx_request          *req = NULL;
-	struct cam_ctx_request          *req_temp = NULL;
-	struct cam_hw_mgr_dump_pf_data  *pf_dbg_entry = NULL;
-	uint32_t  resource_type = 0;
+	struct cam_context         *ctx = (struct cam_context *)data;
+	struct cam_ctx_request     *req = NULL;
+	struct cam_ctx_request     *req_temp = NULL;
+	struct cam_hw_dump_pf_args *pf_args = (struct cam_hw_dump_pf_args *)args;
 	int rc = 0;
-	int closest_port;
-	bool b_mem_found = false, b_ctx_found = false;
 
-
-	if (!ctx) {
-		CAM_ERR(CAM_CRE, "Invalid ctx");
+	if (!ctx || !pf_args) {
+		CAM_ERR(CAM_CRE, "Invalid ctx %pK or pf arguments %pK",
+			ctx, pf_args);
 		return -EINVAL;
 	}
 
@@ -155,19 +152,24 @@ static int cam_cre_context_dump_active_request(void *data,
 
 	list_for_each_entry_safe(req, req_temp,
 			&ctx->active_req_list, list) {
-		pf_dbg_entry = &(req->pf_data);
-		closest_port = -1;
-		CAM_INFO(CAM_CRE, "req_id : %lld ", req->request_id);
 
-		rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry->packet,
-			&b_mem_found, &b_ctx_found, &resource_type, pf_info);
+		CAM_INFO(CAM_CRE, "Active req_id: %llu ctx_id: %u",
+			req->request_id, ctx->ctx_id);
+
+		rc = cam_context_dump_pf_info_to_hw(ctx, pf_args, &req->pf_data);
 		if (rc)
-			CAM_ERR(CAM_CRE, "Failed to dump pf info");
+			CAM_ERR(CAM_CRE, "Failed to dump pf info ctx_id: %u state: %d",
+				ctx->ctx_id, ctx->state);
+	}
 
-		if (b_mem_found)
-			CAM_ERR(CAM_CRE, "Found page fault in req %lld %d",
-				req->request_id, rc);
+	if (pf_args->pf_context_info.ctx_found) {
+		/* Send PF notification to UMD if PF found on current CTX */
+		rc = cam_context_send_pf_evt(ctx, pf_args);
+		if (rc)
+			CAM_ERR(CAM_CRE,
+				"Failed to notify PF event to userspace rc: %d", rc);
 	}
+
 	return rc;
 }
 

+ 24 - 7
drivers/cam_cre/cam_cre_dev.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/delay.h>
@@ -16,6 +17,7 @@
 #include "cam_debug_util.h"
 #include "cam_smmu_api.h"
 #include "camera_main.h"
+#include "cam_context_utils.h"
 
 #define CAM_CRE_DEV_NAME "cam-cre"
 
@@ -31,20 +33,35 @@ struct cam_cre_subdev {
 static struct cam_cre_subdev g_cre_dev;
 
 static void cam_cre_dev_iommu_fault_handler(
-	struct cam_smmu_pf_info *pf_info)
+	struct cam_smmu_pf_info *pf_smmu_info)
 {
-	int i = 0;
+	int i, rc;
 	struct cam_node *node = NULL;
+	struct cam_hw_dump_pf_args pf_args = {0};
 
-	if (!pf_info || !pf_info->token) {
-		CAM_ERR(CAM_ISP, "invalid token in page handler cb");
+	if (!pf_smmu_info || !pf_smmu_info->token) {
+		CAM_ERR(CAM_CRE, "invalid token in page handler cb");
 		return;
 	}
 
-	node = (struct cam_node *)pf_info->token;
+	node = (struct cam_node *)pf_smmu_info->token;
 
-	for (i = 0; i < node->ctx_size; i++)
-		cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info);
+	pf_args.pf_smmu_info = pf_smmu_info;
+
+	for (i = 0; i < node->ctx_size; i++) {
+		cam_context_dump_pf_info(&(node->ctx_list[i]), &pf_args);
+		if (pf_args.pf_context_info.ctx_found)
+			/* found ctx and packet of the faulted address */
+			break;
+	}
+
+	if (i == node->ctx_size) {
+		/* Faulted ctx not found. Report PF to userspace */
+		rc = cam_context_send_pf_evt(NULL, &pf_args);
+		if (rc)
+			CAM_ERR(CAM_CRE,
+				"Failed to notify PF event to userspace rc: %d", rc);
+	}
 }
 
 static int cam_cre_subdev_open(struct v4l2_subdev *sd,

+ 12 - 73
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.c

@@ -3,6 +3,7 @@
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
+
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
@@ -2390,76 +2391,20 @@ config_err:
 	return rc;
 }
 
-static void cam_cre_mgr_print_io_bufs(struct cam_packet *packet,
-	int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info,
-	bool *mem_found)
+static void cam_cre_mgr_dump_pf_data(struct cam_cre_hw_mgr  *hw_mgr,
+	struct cam_hw_cmd_pf_args *pf_cmd_args)
 {
-	dma_addr_t iova_addr;
-	size_t     src_buf_size;
-	int        i;
-	int        j;
-	int        rc = 0;
-	int32_t    mmu_hdl;
-
-	struct cam_buf_io_cfg  *io_cfg = NULL;
-
-	if (mem_found)
-		*mem_found = false;
-
-	io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
-		packet->io_configs_offset / 4);
-
-	for (i = 0; i < packet->num_io_configs; i++) {
-		for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
-			if (!io_cfg[i].mem_handle[j])
-				break;
-
-			if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
-				pf_buf_info) {
-				CAM_INFO(CAM_CRE,
-					"Found PF at port: %d mem %x fd: %x",
-					io_cfg[i].resource_type,
-					io_cfg[i].mem_handle[j],
-					pf_buf_info);
-				if (mem_found)
-					*mem_found = true;
-			}
-
-			CAM_INFO(CAM_CRE, "port: %d f: %d format: %d dir %d",
-				io_cfg[i].resource_type,
-				io_cfg[i].fence,
-				io_cfg[i].format,
-				io_cfg[i].direction);
-
-			mmu_hdl = cam_mem_is_secure_buf(
-				io_cfg[i].mem_handle[j]) ? sec_mmu_hdl :
-				iommu_hdl;
-			rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
-				mmu_hdl, &iova_addr, &src_buf_size, NULL);
-			if (rc < 0) {
-				CAM_ERR(CAM_UTIL,
-					"get src buf address fail rc %d mem %x",
-					rc, io_cfg[i].mem_handle[j]);
-				continue;
-			}
+	struct cam_packet          *packet;
+	struct cam_hw_dump_pf_args *pf_args;
 
-			CAM_INFO(CAM_CRE,
-				"pln %d dir %d w %d h %d s %u sh %u sz %zu addr 0x%llx off 0x%x memh %x",
-				j, io_cfg[i].direction,
-				io_cfg[i].planes[j].width,
-				io_cfg[i].planes[j].height,
-				io_cfg[i].planes[j].plane_stride,
-				io_cfg[i].planes[j].slice_height,
-				src_buf_size, iova_addr,
-				io_cfg[i].offsets[j],
-				io_cfg[i].mem_handle[j]);
+	packet = pf_cmd_args->pf_req_info->packet;
+	pf_args = pf_cmd_args->pf_args;
 
-			iova_addr += io_cfg[i].offsets[j];
+	cam_packet_util_dump_io_bufs(packet, hw_mgr->iommu_hdl,
+		hw_mgr->iommu_sec_hdl, pf_args, false);
 
-		}
-	}
-	cam_packet_dump_patch_info(packet, cre_hw_mgr->iommu_hdl,
-		cre_hw_mgr->iommu_sec_hdl);
+	cam_packet_util_dump_patch_info(packet, hw_mgr->iommu_hdl,
+		hw_mgr->iommu_sec_hdl, pf_args);
 }
 
 static int cam_cre_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
@@ -2475,13 +2420,7 @@ static int cam_cre_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 
 	switch (hw_cmd_args->cmd_type) {
 	case CAM_HW_MGR_CMD_DUMP_PF_INFO:
-		cam_cre_mgr_print_io_bufs(
-			hw_cmd_args->u.pf_args.pf_data.packet,
-			hw_mgr->iommu_hdl,
-			hw_mgr->iommu_sec_hdl,
-			hw_cmd_args->u.pf_args.buf_info,
-			hw_cmd_args->u.pf_args.mem_found);
-
+		cam_cre_mgr_dump_pf_data(hw_mgr, hw_cmd_args->u.pf_cmd_args);
 		break;
 	default:
 		CAM_ERR(CAM_CRE, "Invalid cmd");

+ 2 - 1
drivers/cam_cre/cam_cre_hw_mgr/cam_cre_hw_mgr.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef CAM_CRE_HW_MGR_H
@@ -288,7 +289,7 @@ struct cam_cre_request {
 	struct    cre_io_buf *io_buf[CRE_MAX_BATCH_SIZE][CRE_MAX_IO_BUFS];
 	struct    cam_cre_clk_bw_request clk_info;
 	struct    cam_cre_clk_bw_req_internal_v2 clk_info_v2;
-	struct    cam_hw_mgr_dump_pf_data hang_data;
+	struct    cam_hw_mgr_pf_request_info hang_data;
 	ktime_t   submit_timestamp;
 };
 

+ 7 - 1
drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include "cam_fd_hw_core.h"
@@ -23,8 +24,13 @@ static uint32_t cam_fd_cdm_write_reg_val_pair(uint32_t *buffer,
 }
 
 static void cam_fd_hw_util_cdm_callback(uint32_t handle, void *userdata,
-	enum cam_cdm_cb_status status, uint64_t cookie)
+	enum cam_cdm_cb_status status, void *cookie_arg)
 {
+	uint64_t cookie = 0;
+
+	if (status != CAM_CDM_CB_STATUS_PAGEFAULT)
+		cookie = *(uint64_t *) cookie_arg;
+
 	trace_cam_cdm_cb("FD", status);
 	CAM_DBG(CAM_FD, "CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
 		handle, userdata, status, cookie);

+ 25 - 25
drivers/cam_icp/cam_icp_context.c

@@ -25,47 +25,47 @@
 
 static const char icp_dev_name[] = "cam-icp";
 
-static int cam_icp_context_dump_active_request(void *data,
-	struct cam_smmu_pf_info *pf_info)
+static int cam_icp_context_dump_active_request(void *data, void *args)
 {
-	struct cam_context *ctx = (struct cam_context *)data;
-	struct cam_ctx_request          *req = NULL;
-	struct cam_ctx_request          *req_temp = NULL;
-	struct cam_hw_mgr_dump_pf_data  *pf_dbg_entry = NULL;
-	uint32_t  resource_type = 0;
+	struct cam_context         *ctx = (struct cam_context *)data;
+	struct cam_ctx_request     *req = NULL;
+	struct cam_ctx_request     *req_temp = NULL;
+	struct cam_hw_dump_pf_args *pf_args = (struct cam_hw_dump_pf_args *)args;
 	int rc = 0;
-	bool b_mem_found = false, b_ctx_found = false;
 
-	if (!ctx) {
-		CAM_ERR(CAM_ICP, "Invalid ctx");
+	if (!ctx || !pf_args) {
+		CAM_ERR(CAM_ICP, "Invalid ctx %pK or pf args %pK",
+			ctx, pf_args);
 		return -EINVAL;
 	}
 
-	if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) {
-		CAM_ERR(CAM_ICP, "Invalid state icp ctx %d state %d",
-			ctx->ctx_id, ctx->state);
-		goto end;
-	}
-
 	CAM_INFO(CAM_ICP, "iommu fault for icp ctx %d state %d",
 		ctx->ctx_id, ctx->state);
 
 	list_for_each_entry_safe(req, req_temp,
 			&ctx->active_req_list, list) {
-		pf_dbg_entry = &(req->pf_data);
-		CAM_INFO(CAM_ICP, "req_id : %lld", req->request_id);
+		CAM_INFO(CAM_ICP, "Active req_id: %llu ctx_id: %u",
+			req->request_id, ctx->ctx_id);
 
-		rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry,
-			&b_mem_found, &b_ctx_found, &resource_type, pf_info);
+		rc = cam_context_dump_pf_info_to_hw(ctx, pf_args, &req->pf_data);
 		if (rc)
-			CAM_ERR(CAM_ICP, "Failed to dump pf info");
+			CAM_ERR(CAM_ICP, "Failed to dump pf info ctx_id: %u state: %d",
+				ctx->ctx_id, ctx->state);
+	}
 
-		if (b_mem_found)
-			CAM_ERR(CAM_ICP, "Found page fault in req %lld %d",
-				req->request_id, rc);
+	/*
+	 * Faulted ctx found. Since IPE/BPS instances are shared among contexts,
+	 * faulted ctx is found if and only if the context contains
+	 * faulted buffer
+	 */
+	if (pf_args->pf_context_info.ctx_found) {
+		/* Send PF notification to UMD if PF found on current CTX */
+		rc = cam_context_send_pf_evt(ctx, pf_args);
+		if (rc)
+			CAM_ERR(CAM_ICP,
+				"Failed to notify PF event to userspace rc: %d", rc);
 	}
 
-end:
 	return rc;
 }
 

+ 24 - 7
drivers/cam_icp/cam_icp_subdev.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/delay.h>
@@ -31,6 +32,7 @@
 #include "cam_smmu_api.h"
 #include "camera_main.h"
 #include "cam_common_util.h"
+#include "cam_context_utils.h"
 
 #define CAM_ICP_DEV_NAME        "cam-icp"
 
@@ -68,20 +70,35 @@ static int cam_icp_dev_err_inject_cb(void *err_param)
 	return -ENODEV;
 }
 
-static void cam_icp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info)
+static void cam_icp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_smmu_info)
 {
-	int i = 0;
+	int i, rc;
 	struct cam_node *node = NULL;
+	struct cam_hw_dump_pf_args pf_args = {0};
 
-	if (!pf_info || !pf_info->token) {
-		CAM_ERR(CAM_ISP, "invalid token in page handler cb");
+	if (!pf_smmu_info || !pf_smmu_info->token) {
+		CAM_ERR(CAM_ICP, "invalid token in page handler cb");
 		return;
 	}
 
-	node = (struct cam_node *)pf_info->token;
+	node = (struct cam_node *)pf_smmu_info->token;
 
-	for (i = 0; i < node->ctx_size; i++)
-		cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info);
+	pf_args.pf_smmu_info = pf_smmu_info;
+
+	for (i = 0; i < node->ctx_size; i++) {
+		cam_context_dump_pf_info(&(node->ctx_list[i]), &pf_args);
+		if (pf_args.pf_context_info.ctx_found)
+			/* found ctx and packet of the faulted address */
+			break;
+	}
+
+	if (i == node->ctx_size) {
+		/* Faulted ctx not found. Report PF to userspace */
+		rc = cam_context_send_pf_evt(NULL, &pf_args);
+		if (rc)
+			CAM_ERR(CAM_ICP,
+				"Failed to notify PF event to userspace rc: %d", rc);
+	}
 }
 
 static void cam_icp_dev_mini_dump_cb(void *priv, void *args)

+ 21 - 79
drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c

@@ -37,7 +37,6 @@
 #include "hfi_session_defs.h"
 #include "hfi_sys_defs.h"
 #include "cam_req_mgr_workq.h"
-#include "cam_mem_mgr.h"
 #include "a5_core.h"
 #include "lx7_core.h"
 #include "hfi_sys_defs.h"
@@ -5480,77 +5479,6 @@ static int cam_icp_mgr_update_hfi_frame_process(
 	return rc;
 }
 
-static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet,
-	int32_t iommu_hdl, int32_t sec_mmu_hdl, uint32_t pf_buf_info,
-	bool *mem_found)
-{
-	dma_addr_t iova_addr;
-	size_t     src_buf_size;
-	int        i;
-	int        j;
-	int        rc = 0;
-	int32_t    mmu_hdl;
-
-	struct cam_buf_io_cfg  *io_cfg = NULL;
-
-	if (mem_found)
-		*mem_found = false;
-
-	io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
-		packet->io_configs_offset / 4);
-
-	for (i = 0; i < packet->num_io_configs; i++) {
-		for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
-			if (!io_cfg[i].mem_handle[j])
-				break;
-
-			if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) ==
-				pf_buf_info) {
-				CAM_INFO(CAM_ICP,
-					"Found PF at port: %d mem %x fd: %x",
-					io_cfg[i].resource_type,
-					io_cfg[i].mem_handle[j],
-					pf_buf_info);
-				if (mem_found)
-					*mem_found = true;
-			}
-
-			CAM_INFO(CAM_ICP, "port: %d f: %u format: %d dir %d",
-				io_cfg[i].resource_type,
-				io_cfg[i].fence,
-				io_cfg[i].format,
-				io_cfg[i].direction);
-
-			mmu_hdl = cam_mem_is_secure_buf(
-				io_cfg[i].mem_handle[j]) ? sec_mmu_hdl :
-				iommu_hdl;
-			rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
-				mmu_hdl, &iova_addr, &src_buf_size, NULL);
-			if (rc < 0) {
-				CAM_ERR(CAM_UTIL,
-					"get src buf address fail rc %d", rc);
-				continue;
-			}
-
-			CAM_INFO(CAM_ICP,
-				"pln %d dir %d w %d h %d s %u sh %u sz %zu addr 0x%llx off 0x%x memh %x",
-				j, io_cfg[i].direction,
-				io_cfg[i].planes[j].width,
-				io_cfg[i].planes[j].height,
-				io_cfg[i].planes[j].plane_stride,
-				io_cfg[i].planes[j].slice_height,
-				src_buf_size, iova_addr,
-				io_cfg[i].offsets[j],
-				io_cfg[i].mem_handle[j]);
-
-			iova_addr += io_cfg[i].offsets[j];
-
-		}
-	}
-	cam_packet_dump_patch_info(packet, icp_hw_mgr.iommu_hdl,
-		icp_hw_mgr.iommu_sec_hdl);
-}
-
 static int cam_icp_mgr_config_stream_settings(
 	void *hw_mgr_priv, void *hw_stream_settings)
 {
@@ -6930,6 +6858,26 @@ void cam_icp_mgr_destroy_wq(void)
 	cam_req_mgr_workq_destroy(&icp_hw_mgr.cmd_work);
 }
 
+static void cam_icp_mgr_dump_pf_data(struct cam_icp_hw_mgr *hw_mgr,
+	struct cam_hw_cmd_pf_args *pf_cmd_args)
+{
+	struct cam_packet          *packet;
+	struct cam_hw_dump_pf_args *pf_args;
+
+	packet = pf_cmd_args->pf_req_info->packet;
+	pf_args = pf_cmd_args->pf_args;
+
+	/*
+	 * res_id_support is false since ICP doesn't have knowledge
+	 * of res_id. FW submits packet to HW
+	 */
+	cam_packet_util_dump_io_bufs(packet, hw_mgr->iommu_hdl,
+		hw_mgr->iommu_sec_hdl, pf_args, false);
+
+	cam_packet_util_dump_patch_info(packet, hw_mgr->iommu_hdl,
+		hw_mgr->iommu_sec_hdl, pf_args);
+}
+
 static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 {
 	int rc = 0;
@@ -6943,13 +6891,7 @@ static int cam_icp_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
 
 	switch (hw_cmd_args->cmd_type) {
 	case CAM_HW_MGR_CMD_DUMP_PF_INFO:
-		cam_icp_mgr_print_io_bufs(
-			hw_cmd_args->u.pf_args.pf_data.packet,
-			hw_mgr->iommu_hdl,
-			hw_mgr->iommu_sec_hdl,
-			hw_cmd_args->u.pf_args.buf_info,
-			hw_cmd_args->u.pf_args.mem_found);
-
+		cam_icp_mgr_dump_pf_data(hw_mgr, hw_cmd_args->u.pf_cmd_args);
 		break;
 	default:
 		CAM_ERR(CAM_ICP, "Invalid cmd");

+ 79 - 98
drivers/cam_isp/cam_isp_context.c

@@ -33,7 +33,7 @@ static struct cam_isp_ctx_debug isp_ctx_debug;
 	max_entries, (ret))
 
 static int cam_isp_context_dump_requests(void *data,
-	struct cam_smmu_pf_info *pf_info);
+	void *pf_args);
 
 static int cam_isp_context_hw_recovery(void *priv, void *data);
 
@@ -953,7 +953,7 @@ static int __cam_isp_ctx_enqueue_init_request(
 			req_isp_old->num_cfg += req_isp_new->num_cfg;
 
 			memcpy(&req_old->pf_data, &req->pf_data,
-				sizeof(struct cam_hw_mgr_dump_pf_data));
+				sizeof(struct cam_hw_mgr_pf_request_info));
 
 			if (req_isp_new->hw_update_data.num_reg_dump_buf) {
 				req_update_new = &req_isp_new->hw_update_data;
@@ -6092,6 +6092,7 @@ static int __cam_isp_ctx_acquire_dev_in_available(struct cam_context *ctx,
 	memset(&param, 0, sizeof(param));
 	param.context_data = ctx;
 	param.event_cb = ctx->irq_cb_intf;
+	param.sec_pf_evt_cb = cam_context_dump_pf_info;
 	param.num_acq = cmd->num_resources;
 	param.acquire_info = (uintptr_t) isp_res;
 
@@ -6259,6 +6260,7 @@ static int __cam_isp_ctx_acquire_hw_v1(struct cam_context *ctx,
 	memset(&param, 0, sizeof(param));
 	param.context_data = ctx;
 	param.event_cb = ctx->irq_cb_intf;
+	param.sec_pf_evt_cb = cam_context_dump_pf_info;
 	param.num_acq = CAM_API_COMPAT_CONSTANT;
 	param.acquire_info_size = cmd->data_size;
 	param.acquire_info = (uint64_t) acquire_hw_info;
@@ -6411,6 +6413,7 @@ static int __cam_isp_ctx_acquire_hw_v2(struct cam_context *ctx,
 	memset(&param, 0, sizeof(param));
 	param.context_data = ctx;
 	param.event_cb = ctx->irq_cb_intf;
+	param.sec_pf_evt_cb = cam_context_dump_pf_info;
 	param.num_acq = CAM_API_COMPAT_CONSTANT;
 	param.acquire_info_size = cmd->data_size;
 	param.acquire_info = (uint64_t) acquire_hw_info;
@@ -7556,68 +7559,70 @@ static int cam_isp_context_hw_recovery(void *priv, void *data)
 	return rc;
 }
 
-static int cam_isp_context_dump_requests(void *data,
-	struct cam_smmu_pf_info *pf_info)
+static void cam_isp_context_find_faulted_context(struct cam_context *ctx,
+	struct list_head *req_list, struct cam_hw_dump_pf_args *pf_args, bool *found)
 {
-
-	struct cam_context *ctx = (struct cam_context *)data;
 	struct cam_ctx_request *req = NULL;
 	struct cam_ctx_request *req_temp = NULL;
-	struct cam_isp_ctx_req *req_isp  = NULL;
-	struct cam_isp_prepare_hw_update_data *hw_update_data = NULL;
-	struct cam_hw_mgr_dump_pf_data *pf_dbg_entry = NULL;
-	struct cam_req_mgr_message       req_msg = {0};
-	struct cam_isp_context          *ctx_isp;
-	uint32_t  resource_type = 0;
-	bool mem_found = false, ctx_found = false, send_error = false;
-	int rc = 0;
-
-	struct cam_isp_context *isp_ctx =
-		(struct cam_isp_context *)ctx->ctx_priv;
-
-	if (!isp_ctx) {
-		CAM_ERR(CAM_ISP, "Invalid isp ctx");
-		return -EINVAL;
-	}
-
-	CAM_INFO(CAM_ISP, "iommu fault handler for isp ctx %d state %d",
-		ctx->ctx_id, ctx->state);
+	int rc;
 
-	list_for_each_entry_safe(req, req_temp,
-		&ctx->active_req_list, list) {
-		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
-		hw_update_data = &req_isp->hw_update_data;
-		pf_dbg_entry = &(req->pf_data);
-		CAM_INFO(CAM_ISP, "Active List: req_id : %lld ",
-			req->request_id);
+	*found = false;
+	list_for_each_entry_safe(req, req_temp, req_list, list) {
+		CAM_INFO(CAM_ISP, "List req_id: %llu ctx id: %u",
+			req->request_id, ctx->ctx_id);
 
-		rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry,
-			&mem_found, &ctx_found, &resource_type, pf_info);
+		rc = cam_context_dump_pf_info_to_hw(ctx, pf_args, &req->pf_data);
 		if (rc)
 			CAM_ERR(CAM_ISP, "Failed to dump pf info");
+		/*
+		 * Found faulted buffer. Even if faulted ctx is found, but
+		 * continue to search for faulted buffer
+		 */
+		if (pf_args->pf_context_info.mem_type != CAM_FAULT_BUF_NOT_FOUND) {
+			*found = true;
+			break;
+		}
+	}
+}
+
+static int cam_isp_context_dump_requests(void *data, void *args)
+{
+	struct cam_context         *ctx = (struct cam_context *)data;
+	struct cam_isp_context     *ctx_isp;
+	struct cam_hw_dump_pf_args *pf_args = (struct cam_hw_dump_pf_args *)args;
+	int rc = 0;
+	bool found;
 
-		if (ctx_found)
-			send_error = true;
+	if (!ctx || !pf_args) {
+		CAM_ERR(CAM_ISP, "Invalid ctx %pK or pf args %pK",
+			ctx, pf_args);
+		return -EINVAL;
 	}
 
-	CAM_INFO(CAM_ISP, "Iterating over wait_list of isp ctx %d state %d",
-			ctx->ctx_id, ctx->state);
+	ctx_isp = (struct cam_isp_context *)ctx->ctx_priv;
+	if (!ctx_isp) {
+		CAM_ERR(CAM_ISP, "Invalid isp ctx");
+		return -EINVAL;
+	}
 
-	list_for_each_entry_safe(req, req_temp,
-		&ctx->wait_req_list, list) {
-		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
-		hw_update_data = &req_isp->hw_update_data;
-		pf_dbg_entry = &(req->pf_data);
-		CAM_INFO(CAM_ISP, "Wait List: req_id : %lld ", req->request_id);
+	if (pf_args->handle_sec_pf)
+		goto end;
 
-		rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry,
-			&mem_found, &ctx_found, &resource_type, pf_info);
-		if (rc)
-			CAM_ERR(CAM_ISP, "Failed to dump pf info");
+	CAM_INFO(CAM_ISP,
+		"Iterating over active list for isp ctx %d state %d",
+		ctx->ctx_id, ctx->state);
+	cam_isp_context_find_faulted_context(ctx, &ctx->active_req_list,
+		pf_args, &found);
+	if (found)
+		goto end;
 
-		if (ctx_found)
-			send_error = true;
-	}
+	CAM_INFO(CAM_ISP,
+		"Iterating over waiting list of isp ctx %d state %d",
+		ctx->ctx_id, ctx->state);
+	cam_isp_context_find_faulted_context(ctx, &ctx->wait_req_list,
+		pf_args, &found);
+	if (found)
+		goto end;
 
 	/*
 	 * In certain scenarios we observe both overflow and SMMU pagefault
@@ -7627,61 +7632,37 @@ static int cam_isp_context_dump_requests(void *data,
 	 * and all the subsequent requests to the pending list while handling
 	 * overflow error.
 	 */
-
 	CAM_INFO(CAM_ISP,
 		"Iterating over pending req list of isp ctx %d state %d",
 		ctx->ctx_id, ctx->state);
+	cam_isp_context_find_faulted_context(ctx, &ctx->pending_req_list,
+		pf_args, &found);
+	if (found)
+		goto end;
 
-	list_for_each_entry_safe(req, req_temp,
-		&ctx->pending_req_list, list) {
-		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
-		hw_update_data = &req_isp->hw_update_data;
-		pf_dbg_entry = &(req->pf_data);
-		CAM_INFO(CAM_ISP, "Pending List: req_id : %lld ",
-			req->request_id);
-
-		rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry,
-			&mem_found, &ctx_found, &resource_type, pf_info);
-		if (rc)
-			CAM_ERR(CAM_ISP, "Failed to dump pf info");
-
-		if (ctx_found)
-			send_error = true;
-	}
-
-	if (resource_type) {
-		ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
-		CAM_ERR(CAM_ISP,
+end:
+	if (pf_args->pf_context_info.resource_type) {
+		ctx_isp = (struct cam_isp_context *)ctx->ctx_priv;
+		CAM_INFO(CAM_ISP,
 			"Page fault on resource:%s (0x%x) ctx id:%d frame id:%d reported id:%lld applied id:%lld",
-			__cam_isp_resource_handle_id_to_type(
-			ctx_isp->isp_device_type, resource_type),
-			resource_type, ctx->ctx_id, ctx_isp->frame_id,
+			__cam_isp_resource_handle_id_to_type(ctx_isp->isp_device_type,
+				pf_args->pf_context_info.resource_type),
+			pf_args->pf_context_info.resource_type, ctx->ctx_id, ctx_isp->frame_id,
 			ctx_isp->reported_req_id, ctx_isp->last_applied_req_id);
 	}
 
-	if (send_error) {
-		CAM_INFO(CAM_ISP,
-			"page fault notifying to umd ctx %u session_hdl:%d device_hdl:%d link_hdl:%d",
-			ctx->ctx_id, ctx->session_hdl,
-			ctx->dev_hdl, ctx->link_hdl);
-
-		req_msg.session_hdl = ctx->session_hdl;
-		req_msg.u.err_msg.device_hdl = ctx->dev_hdl;
-		req_msg.u.err_msg.error_type =
-			CAM_REQ_MGR_ERROR_TYPE_PAGE_FAULT;
-		req_msg.u.err_msg.link_hdl = ctx->link_hdl;
-		req_msg.u.err_msg.request_id = 0;
-		req_msg.u.err_msg.resource_size = 0x0;
-		req_msg.u.err_msg.error_code = CAM_REQ_MGR_ISP_UNREPORTED_ERROR;
-
-		if (cam_req_mgr_notify_message(&req_msg,
-				V4L_EVENT_CAM_REQ_MGR_ERROR,
-				V4L_EVENT_CAM_REQ_MGR_EVENT))
-			CAM_ERR(CAM_ISP,
-				"could not send page fault notification ctx %u session_hdl:%d device_hdl:%d link_hdl:%d",
-				ctx->ctx_id, ctx->session_hdl,
-				ctx->dev_hdl, ctx->link_hdl);
-	}
+	/*
+	 * Send PF notification to UMD if PF found on current CTX
+	 * or it is forced to send PF notification to UMD even if no
+	 * faulted context found
+	 */
+	if (pf_args->pf_context_info.ctx_found ||
+			pf_args->pf_context_info.force_send_pf_evt)
+		rc = cam_context_send_pf_evt(ctx, pf_args);
+	if (rc)
+		CAM_ERR(CAM_ISP,
+			"Failed to notify PF event to userspace rc: %d", rc);
+
 	return rc;
 }
 

+ 23 - 6
drivers/cam_isp/cam_isp_dev.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/delay.h>
@@ -20,6 +21,7 @@
 #include "cam_smmu_api.h"
 #include "camera_main.h"
 #include "cam_common_util.h"
+#include "cam_context_utils.h"
 
 static struct cam_isp_dev g_isp_dev;
 
@@ -38,20 +40,35 @@ static int cam_isp_dev_err_inject_cb(void *err_param)
 	return -ENODEV;
 }
 
-static void cam_isp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_info)
+static void cam_isp_dev_iommu_fault_handler(struct cam_smmu_pf_info *pf_smmu_info)
 {
-	int i = 0;
+	int i, rc;
 	struct cam_node *node = NULL;
+	struct cam_hw_dump_pf_args pf_args = {0};
 
-	if (!pf_info || !pf_info->token) {
+	if (!pf_smmu_info || !pf_smmu_info->token) {
 		CAM_ERR(CAM_ISP, "invalid token in page handler cb");
 		return;
 	}
 
-	node = (struct cam_node *)pf_info->token;
+	node = (struct cam_node *)pf_smmu_info->token;
 
-	for (i = 0; i < node->ctx_size; i++)
-		cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info);
+	pf_args.pf_smmu_info = pf_smmu_info;
+
+	for (i = 0; i < node->ctx_size; i++) {
+		cam_context_dump_pf_info(&(node->ctx_list[i]), &pf_args);
+		if (pf_args.pf_context_info.ctx_found)
+			/* Faulted ctx found */
+			break;
+	}
+
+	if (i == node->ctx_size) {
+		/* Faulted ctx not found. Report PF to userspace */
+		rc = cam_context_send_pf_evt(NULL, &pf_args);
+		if (rc)
+			CAM_ERR(CAM_ISP,
+				"Failed to notify PF event to userspace rc: %d", rc);
+	}
 }
 
 static const struct of_device_id cam_isp_dt_match[] = {

+ 64 - 87
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -4619,11 +4619,13 @@ err:
 }
 
 void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
-	enum cam_cdm_cb_status status, uint64_t cookie)
+	enum cam_cdm_cb_status status, void *cookie)
 {
 	struct cam_isp_prepare_hw_update_data   *hw_update_data = NULL;
 	struct cam_ife_hw_mgr_ctx               *ctx = NULL;
+	struct cam_hw_dump_pf_args              *pf_args = NULL;
 	int                                      reg_dump_done;
+	uint64_t                                 req_id;
 
 	if (!userdata) {
 		CAM_ERR(CAM_ISP, "Invalid args");
@@ -4634,13 +4636,14 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
 	hw_update_data = ctx->cdm_userdata.hw_update_data;
 
 	if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
+		req_id = *(uint64_t *)cookie;
 		complete_all(&ctx->config_done_complete);
 		reg_dump_done = atomic_read(&ctx->cdm_done);
 		atomic_set(&ctx->cdm_done, 1);
-		ctx->last_cdm_done_req = cookie;
+		ctx->last_cdm_done_req = req_id;
 		if ((g_ife_hw_mgr.debug_cfg.per_req_reg_dump) &&
 			(!reg_dump_done)) {
-			if (ctx->cdm_userdata.request_id == cookie) {
+			if (ctx->cdm_userdata.request_id == req_id) {
 				cam_ife_mgr_handle_reg_dump(ctx,
 					hw_update_data->reg_dump_buf_desc,
 					hw_update_data->num_reg_dump_buf,
@@ -4648,17 +4651,21 @@ void cam_ife_cam_cdm_callback(uint32_t handle, void *userdata,
 					NULL, false);
 			} else {
 				CAM_INFO(CAM_ISP, "CDM delay, Skip dump req: %llu, cdm_req: %llu",
-					cookie, ctx->cdm_userdata.request_id);
+					req_id, ctx->cdm_userdata.request_id);
 			}
 		}
 		CAM_DBG(CAM_ISP,
-			"CDM hdl=0x%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d cdm_req=%llu",
-			 handle, userdata, status, cookie, ctx->ctx_index,
+			"CDM hdl=0x%x, udata=%pK, status=%d, cookie=%u ctx_index=%d cdm_req=%llu",
+			 handle, userdata, status, req_id, ctx->ctx_index,
 			 ctx->cdm_userdata.request_id);
+	} else if (status == CAM_CDM_CB_STATUS_PAGEFAULT) {
+		pf_args = (struct cam_hw_dump_pf_args *)cookie;
+		if (ctx->common.sec_pf_evt_cb)
+			ctx->common.sec_pf_evt_cb(ctx->common.cb_priv, cookie);
 	} else {
 		CAM_WARN(CAM_ISP,
-			"Called by CDM hdl=0x%x, udata=%pK, status=%d, cookie=%llu, cdm_req=%llu",
-			 handle, userdata, status, cookie, ctx->cdm_userdata.request_id);
+			"Called by CDM hdl=0x%x, udata=%pK, status=%d, cdm_req=%llu",
+			 handle, userdata, status, ctx->cdm_userdata.request_id);
 	}
 }
 
@@ -4964,6 +4971,7 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args)
 	ife_ctx->common.event_cb = acquire_args->event_cb;
 	ife_ctx->hw_mgr = ife_hw_mgr;
 	ife_ctx->cdm_ops =  cam_cdm_publish_ops();
+	ife_ctx->common.sec_pf_evt_cb = acquire_args->sec_pf_evt_cb;
 
 	acquire_hw_info =
 		(struct cam_isp_acquire_hw_info *)acquire_args->acquire_info;
@@ -11277,71 +11285,40 @@ static int cam_ife_mgr_sof_irq_debug(
 	return rc;
 }
 
-static void cam_ife_mgr_print_io_bufs(struct cam_ife_hw_mgr  *hw_mgr,
-		uint32_t res_id, struct cam_packet *packet,
-		bool    *ctx_found, struct cam_ife_hw_mgr_ctx *ctx)
+static inline void cam_ife_hw_mgr_stop_bus_rd_for_res(struct cam_ife_hw_mgr_ctx *ctx,
+	uint32_t res_id)
 {
+	struct cam_isp_hw_mgr_res *isp_hw_res;
 
-	struct cam_buf_io_cfg  *io_cfg = NULL;
-	int32_t      mmu_hdl, iommu_hdl, sec_mmu_hdl;
-	dma_addr_t   iova_addr;
-	size_t        src_buf_size;
-	int  i, j, rc = 0;
-
-	iommu_hdl = hw_mgr->mgr_common.img_iommu_hdl;
-	sec_mmu_hdl = hw_mgr->mgr_common.img_iommu_hdl_secure;
-
-	io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
-		packet->io_configs_offset / 4);
-
-	for (i = 0; i < packet->num_io_configs; i++) {
-		if (io_cfg[i].resource_type != res_id)
-			continue;
-		else
+	list_for_each_entry(isp_hw_res, &ctx->res_list_ife_in_rd, list) {
+		if (isp_hw_res->res_id == res_id) {
+			CAM_ERR(CAM_ISP, "Stopping IFE/SFE bus rd res id 0x%x", res_id);
+			cam_ife_hw_mgr_stop_hw_res(isp_hw_res);
 			break;
 		}
+	}
+}
 
-		if (i == packet->num_io_configs) {
-			*ctx_found = false;
-			CAM_ERR(CAM_ISP,
-				"getting io port for mid resource id failed ctx id:%d req id:%lld res id:0x%x",
-				ctx->ctx_index, packet->header.request_id,
-				res_id);
-			return;
-		}
-
-		for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
-			if (!io_cfg[i].mem_handle[j])
-				break;
-
-			CAM_INFO(CAM_ISP, "port: 0x%x f: %u format: %d dir %d",
-				io_cfg[i].resource_type,
-				io_cfg[i].fence,
-				io_cfg[i].format,
-				io_cfg[i].direction);
-
-			mmu_hdl = cam_mem_is_secure_buf(
-				io_cfg[i].mem_handle[j]) ? sec_mmu_hdl :
-				iommu_hdl;
-			rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
-				mmu_hdl, &iova_addr, &src_buf_size, NULL);
-			if (rc < 0) {
-				CAM_ERR(CAM_ISP,
-					"get src buf address fail mem_handle 0x%x",
-					io_cfg[i].mem_handle[j]);
-				continue;
-			}
+static void cam_ife_hw_mgr_stop_pf_hw_res(struct cam_ife_hw_mgr_ctx *ctx,
+	uint32_t res_id, uint32_t hw_type)
+{
+	struct cam_isp_hw_mgr_res *isp_hw_res;
 
-			CAM_INFO(CAM_ISP,
-				"pln %d w %d h %d s %u size %zu addr 0x%llx end_addr 0x%llx offset %x memh %x",
-				j, io_cfg[i].planes[j].width,
-				io_cfg[i].planes[j].height,
-				io_cfg[i].planes[j].plane_stride,
-				src_buf_size, iova_addr,
-				iova_addr + src_buf_size,
-				io_cfg[i].offsets[j],
-				io_cfg[i].mem_handle[j]);
-		}
+	if (hw_type == CAM_ISP_HW_TYPE_VFE) {
+		if (cam_ife_hw_mgr_is_ife_out_port(res_id)) {
+			isp_hw_res = &ctx->res_list_ife_out[res_id & 0xFF];
+			CAM_ERR(CAM_ISP, "Stopping IFE out resource res id 0x%x", res_id);
+			cam_ife_hw_mgr_stop_hw_res(isp_hw_res);
+		} else
+			cam_ife_hw_mgr_stop_bus_rd_for_res(ctx, res_id);
+	} else if (hw_type == CAM_ISP_HW_TYPE_SFE) {
+		if (cam_ife_hw_mgr_is_sfe_out_port(res_id)) {
+			isp_hw_res = &ctx->res_list_sfe_out[res_id & 0XFF];
+			CAM_ERR(CAM_ISP, "Stopping SFE out resource res id 0x%x", res_id);
+			cam_ife_hw_mgr_stop_hw_res(isp_hw_res);
+		} else
+			cam_ife_hw_mgr_stop_bus_rd_for_res(ctx, res_id);
+	}
 }
 
 static int cam_ife_hw_mgr_dump_bus_info(
@@ -11358,8 +11335,7 @@ static int cam_ife_hw_mgr_dump_bus_info(
 		&event_info, sizeof(struct cam_isp_hw_event_info));
 }
 
-static void cam_ife_mgr_pf_dump(
-	struct cam_ife_hw_mgr_ctx   *ctx)
+static void cam_ife_mgr_pf_dump(struct cam_ife_hw_mgr_ctx *ctx)
 {
 	struct cam_isp_hw_mgr_res      *hw_mgr_res;
 	struct cam_hw_intf             *hw_intf;
@@ -11407,8 +11383,8 @@ static void cam_ife_mgr_pf_dump_mid_info(
 	struct cam_isp_hw_get_res_for_mid   get_res;
 	int                                 rc = 0;
 
-	packet  = hw_cmd_args->u.pf_args.pf_data.packet;
-	get_res.mid = hw_cmd_args->u.pf_args.mid;
+	packet = hw_cmd_args->u.pf_cmd_args->pf_req_info->packet;
+	get_res.mid = hw_cmd_args->u.pf_cmd_args->pf_args->pf_smmu_info->mid;
 	cmd_update.cmd_type = CAM_ISP_HW_CMD_GET_RES_FOR_MID;
 	cmd_update.data = (void *) &get_res;
 
@@ -11423,7 +11399,7 @@ static void cam_ife_mgr_pf_dump_mid_info(
 		return;
 	}
 
-	*(hw_cmd_args->u.pf_args.resource_type) = get_res.out_res_id;
+	hw_cmd_args->u.pf_cmd_args->pf_args->pf_context_info.resource_type = get_res.out_res_id;
 	ctx->flags.pf_mid_found = true;
 	ctx->pf_info.mid = get_res.mid;
 	ctx->pf_info.out_port_id = get_res.out_res_id;
@@ -11439,22 +11415,20 @@ static void cam_ife_mgr_dump_pf_data(
 	struct cam_ife_hw_mgr_ctx          *ctx;
 	struct cam_packet                  *packet;
 	struct cam_isp_hw_intf_data        *hw_intf_data;
-	uint32_t                           *resource_type;
+	struct cam_hw_dump_pf_args         *pf_args;
 	bool                               *ctx_found;
 	int                                 i, j;
 
 	ctx = (struct cam_ife_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map;
 
-	packet  = hw_cmd_args->u.pf_args.pf_data.packet;
-	ctx_found = hw_cmd_args->u.pf_args.ctx_found;
-	resource_type = hw_cmd_args->u.pf_args.resource_type;
+	packet  = hw_cmd_args->u.pf_cmd_args->pf_req_info->packet;
+	pf_args = hw_cmd_args->u.pf_cmd_args->pf_args;
+	ctx_found = &(pf_args->pf_context_info.ctx_found);
 
-	if ((*ctx_found) && (*resource_type))
-		goto outportlog;
-
-	if (ctx->flags.pf_mid_found)
+	if ((*ctx_found) && (ctx->flags.pf_mid_found))
 		goto outportlog;
 
+	/* Determine if the current context is the faulted context based on pid */
 	for (i = 0; i < ctx->num_base; i++) {
 		if (ctx->base[i].hw_type == CAM_ISP_HW_TYPE_VFE)
 			hw_intf_data = g_ife_hw_mgr.ife_devices[ctx->base[i].idx];
@@ -11475,17 +11449,20 @@ static void cam_ife_mgr_dump_pf_data(
 		}
 
 		for (j = 0; j < hw_intf_data->num_hw_pid; j++) {
-			if (hw_intf_data->hw_pid[j] == hw_cmd_args->u.pf_args.pid) {
+			if (hw_intf_data->hw_pid[j] == pf_args->pf_smmu_info->pid) {
 				*ctx_found = true;
 				CAM_ERR(CAM_ISP, "PF found for %s%d pid: %u",
 					ctx->base[i].hw_type == CAM_ISP_HW_TYPE_VFE ? "VFE" : "SFE",
-					ctx->base[i].idx, hw_cmd_args->u.pf_args.pid);
+					ctx->base[i].idx, pf_args->pf_smmu_info->pid);
 				cam_ife_mgr_pf_dump_mid_info(ctx, hw_cmd_args, hw_intf_data);
 
-				/* If MID found - dump client info */
-				if (ctx->flags.pf_mid_found)
+				/* If MID found - stop hw res and dump client info */
+				if (ctx->flags.pf_mid_found) {
+					cam_ife_hw_mgr_stop_pf_hw_res(ctx, ctx->pf_info.out_port_id,
+						ctx->base[i].hw_type);
 					cam_ife_hw_mgr_dump_bus_info(ctx->pf_info.out_port_id,
 						hw_intf_data);
+				}
 				break;
 			}
 		}
@@ -11497,13 +11474,13 @@ static void cam_ife_mgr_dump_pf_data(
 	if (g_ife_hw_mgr.hw_pid_support && (i == ctx->num_base || !*ctx_found))
 		CAM_INFO(CAM_ISP,
 			"This context does not cause pf:pid:%d ctx_id:%d",
-			hw_cmd_args->u.pf_args.pid, ctx->ctx_index);
+			pf_args->pf_smmu_info->pid, ctx->ctx_index);
 
 	cam_ife_mgr_pf_dump(ctx);
 
 outportlog:
-	cam_ife_mgr_print_io_bufs(hw_mgr, *resource_type, packet,
-		ctx_found, ctx);
+	cam_packet_util_dump_io_bufs(packet, hw_mgr->mgr_common.img_iommu_hdl,
+		hw_mgr->mgr_common.img_iommu_hdl_secure, pf_args, true);
 }
 
 int cam_isp_config_csid_rup_aup(

+ 4 - 1
drivers/cam_isp/isp_hw_mgr/cam_isp_hw_mgr.h

@@ -21,7 +21,9 @@
  *                         acquire device
  * @cb_priv:               first argument for the call back function
  *                         set during acquire device
- * @mini_dump_cb           Callback for mini dump
+ * @mini_dump_cb:          Callback for mini dump
+ * @sec_pf_evt_cb:         Callback interface to ISP context for CDM page fault
+ *                         set during device acquire
  *
  */
 struct cam_isp_hw_mgr_ctx {
@@ -29,6 +31,7 @@ struct cam_isp_hw_mgr_ctx {
 	cam_hw_event_cb_func            event_cb;
 	void                           *cb_priv;
 	cam_ctx_mini_dump_cb_func       mini_dump_cb;
+	cam_hw_pagefault_cb_func        sec_pf_evt_cb;
 };
 
 /**

+ 19 - 89
drivers/cam_isp/isp_hw_mgr/cam_tfe_hw_mgr.c

@@ -1665,7 +1665,7 @@ err:
 }
 
 void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata,
-	enum cam_cdm_cb_status status, uint64_t cookie)
+	enum cam_cdm_cb_status status, void *cookie)
 {
 	struct cam_isp_prepare_hw_update_data *hw_update_data = NULL;
 	struct cam_tfe_hw_mgr_ctx *ctx = NULL;
@@ -1686,7 +1686,7 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata,
 		(struct cam_tfe_hw_mgr_ctx *)hw_update_data->isp_mgr_ctx;
 		complete_all(&ctx->config_done_complete);
 		atomic_set(&ctx->cdm_done, 1);
-		ctx->last_cdm_done_req = cookie;
+		ctx->last_cdm_done_req = *(uint64_t *)cookie;
 		if (g_tfe_hw_mgr.debug_cfg.per_req_reg_dump)
 			cam_tfe_mgr_handle_reg_dump(ctx,
 				hw_update_data->reg_dump_buf_desc,
@@ -1695,7 +1695,7 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata,
 				NULL, false);
 		CAM_DBG(CAM_ISP,
 			"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu ctx_index=%d",
-			 handle, userdata, status, cookie, ctx->ctx_index);
+			 handle, userdata, status, *(uint64_t *)cookie, ctx->ctx_index);
 	} else if (status == CAM_CDM_CB_STATUS_PAGEFAULT ||
 		status == CAM_CDM_CB_STATUS_INVALID_BL_CMD ||
 		status == CAM_CDM_CB_STATUS_HW_ERROR) {
@@ -1727,13 +1727,15 @@ void cam_tfe_cam_cdm_callback(uint32_t handle, void *userdata,
 			cam_cdm_util_dump_cmd_buf(buf_start, buf_end);
 		}
 		if (ctx->packet != NULL)
-			cam_packet_dump_patch_info(ctx->packet,
+			cam_packet_util_dump_patch_info(ctx->packet,
 				g_tfe_hw_mgr.mgr_common.img_iommu_hdl,
-				g_tfe_hw_mgr.mgr_common.img_iommu_hdl_secure);
+				g_tfe_hw_mgr.mgr_common.img_iommu_hdl_secure,
+				NULL);
+
 	} else {
 		CAM_WARN(CAM_ISP,
 			"Called by CDM hdl=%x, udata=%pK, status=%d, cookie=%llu",
-			 handle, userdata, status, cookie);
+			 handle, userdata, status, *(uint64_t *)cookie);
 	}
 }
 
@@ -4578,79 +4580,6 @@ static int cam_tfe_mgr_sof_irq_debug(
 	return rc;
 }
 
-static void cam_tfe_mgr_print_io_bufs(struct cam_tfe_hw_mgr  *hw_mgr,
-		uint32_t res_id, struct cam_packet *packet,
-		bool    *ctx_found, struct cam_tfe_hw_mgr_ctx *ctx)
-{
-
-	struct cam_buf_io_cfg  *io_cfg = NULL;
-	int32_t      mmu_hdl, iommu_hdl, sec_mmu_hdl;
-	dma_addr_t   iova_addr;
-	size_t        src_buf_size;
-	int  i, j, rc = 0;
-
-	iommu_hdl = hw_mgr->mgr_common.img_iommu_hdl;
-	sec_mmu_hdl = hw_mgr->mgr_common.img_iommu_hdl_secure;
-
-	io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
-		packet->io_configs_offset / 4);
-
-	for (i = 0; i < packet->num_io_configs; i++) {
-		if (io_cfg[i].resource_type != res_id)
-			continue;
-		else
-			break;
-	}
-
-	if (i == packet->num_io_configs) {
-		CAM_ERR(CAM_ISP,
-			"getting io port for mid resource id failed ctx id:%d req id:%lld res id:0x%x",
-			ctx->ctx_index, packet->header.request_id,
-			res_id);
-		return;
-	}
-
-	for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
-		if (!io_cfg[i].mem_handle[j])
-			break;
-
-		CAM_INFO(CAM_ISP, "port: 0x%x f: %u format: %d dir %d",
-			io_cfg[i].resource_type,
-			io_cfg[i].fence,
-			io_cfg[i].format,
-			io_cfg[i].direction);
-
-		mmu_hdl = cam_mem_is_secure_buf(
-			io_cfg[i].mem_handle[j]) ? sec_mmu_hdl :
-			iommu_hdl;
-		rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
-			mmu_hdl, &iova_addr, &src_buf_size, NULL);
-		if (rc < 0) {
-			CAM_ERR(CAM_ISP,
-				"get src buf address fail mem_handle 0x%x",
-				io_cfg[i].mem_handle[j]);
-			continue;
-		}
-		if ((iova_addr & 0xFFFFFFFF) != iova_addr) {
-			CAM_ERR(CAM_ISP, "Invalid mapped address");
-			rc = -EINVAL;
-			continue;
-		}
-
-		CAM_INFO(CAM_ISP,
-			"pln %d w %d h %d s %u size 0x%x addr 0x%x end_addr 0x%x offset %x memh %x",
-			j, io_cfg[i].planes[j].width,
-			io_cfg[i].planes[j].height,
-			io_cfg[i].planes[j].plane_stride,
-			(unsigned int)src_buf_size,
-			(unsigned int)iova_addr,
-			(unsigned int)iova_addr +
-			(unsigned int)src_buf_size,
-			io_cfg[i].offsets[j],
-			io_cfg[i].mem_handle[j]);
-	}
-}
-
 static void cam_tfe_mgr_pf_dump(uint32_t res_id,
 	struct cam_tfe_hw_mgr_ctx *ctx)
 {
@@ -4727,6 +4656,7 @@ static void cam_tfe_mgr_dump_pf_data(
 	struct cam_isp_hw_get_cmd_update     cmd_update;
 	struct cam_isp_hw_get_res_for_mid    get_res;
 	struct cam_packet                   *packet;
+	struct cam_hw_cmd_pf_args           *pf_cmd_args;
 	uint32_t  *resource_type;
 	uint32_t   hw_id;
 	bool      *ctx_found, hw_id_found = false;
@@ -4734,9 +4664,10 @@ static void cam_tfe_mgr_dump_pf_data(
 
 	ctx = (struct cam_tfe_hw_mgr_ctx *)hw_cmd_args->ctxt_to_hw_map;
 
-	packet  = hw_cmd_args->u.pf_args.pf_data.packet;
-	ctx_found = hw_cmd_args->u.pf_args.ctx_found;
-	resource_type = hw_cmd_args->u.pf_args.resource_type;
+	pf_cmd_args = hw_cmd_args->u.pf_cmd_args;
+	packet  = pf_cmd_args->pf_req_info->packet;
+	ctx_found = &pf_cmd_args->pf_args->pf_context_info.ctx_found;
+	resource_type = &pf_cmd_args->pf_args->pf_context_info.resource_type;
 
 	if ((*ctx_found) && (*resource_type))
 		goto outportlog;
@@ -4747,7 +4678,7 @@ static void cam_tfe_mgr_dump_pf_data(
 
 		for (j = 0; j < g_tfe_hw_mgr.tfe_devices[i]->num_hw_pid; j++) {
 			if (g_tfe_hw_mgr.tfe_devices[i]->hw_pid[j] ==
-				hw_cmd_args->u.pf_args.pid) {
+				pf_cmd_args->pf_args->pf_smmu_info->pid) {
 				hw_id_found = true;
 				hw_id = i;
 				break;
@@ -4760,7 +4691,7 @@ static void cam_tfe_mgr_dump_pf_data(
 	if (i == CAM_TFE_HW_NUM_MAX) {
 		CAM_INFO(CAM_ISP,
 			"PID:%d  is not matching with any TFE HW PIDs ctx id:%d",
-			hw_cmd_args->u.pf_args.pid,  ctx->ctx_index);
+			pf_cmd_args->pf_args->pf_smmu_info->pid,  ctx->ctx_index);
 		return;
 	}
 
@@ -4774,7 +4705,7 @@ static void cam_tfe_mgr_dump_pf_data(
 	if (!(*ctx_found)) {
 		CAM_INFO(CAM_ISP,
 			"This context does not cause pf:pid:%d hw id:%d ctx_id:%d",
-			hw_cmd_args->u.pf_args.pid, hw_id, ctx->ctx_index);
+			pf_cmd_args->pf_args->pf_smmu_info->pid, hw_id, ctx->ctx_index);
 		return;
 	}
 
@@ -4793,7 +4724,7 @@ static void cam_tfe_mgr_dump_pf_data(
 		return;
 	}
 
-	get_res.mid = hw_cmd_args->u.pf_args.mid;
+	get_res.mid = pf_cmd_args->pf_args->pf_smmu_info->mid;
 	cmd_update.res = hw_mgr_res->hw_res[0];
 	cmd_update.cmd_type = CAM_ISP_HW_CMD_GET_RES_FOR_MID;
 	cmd_update.data = (void *) &get_res;
@@ -4818,9 +4749,8 @@ static void cam_tfe_mgr_dump_pf_data(
 	cam_tfe_mgr_pf_dump(get_res.out_res_id, ctx);
 
 outportlog:
-	cam_tfe_mgr_print_io_bufs(hw_mgr, *resource_type, packet,
-		ctx_found, ctx);
-
+	cam_packet_util_dump_io_bufs(packet, hw_mgr->mgr_common.img_iommu_hdl,
+		hw_mgr->mgr_common.img_iommu_hdl_secure, pf_cmd_args->pf_args, true);
 
 }
 

+ 22 - 21
drivers/cam_jpeg/cam_jpeg_context.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/debugfs.h>
@@ -17,22 +18,18 @@
 
 static const char jpeg_dev_name[] = "cam-jpeg";
 
-static int cam_jpeg_context_dump_active_request(void *data,
-	struct cam_smmu_pf_info *pf_info)
+static int cam_jpeg_context_dump_active_request(void *data, void *args)
 {
 
-	struct cam_context *ctx = (struct cam_context *)data;
-	struct cam_ctx_request          *req = NULL;
-	struct cam_ctx_request          *req_temp = NULL;
-	struct cam_hw_mgr_dump_pf_data  *pf_dbg_entry = NULL;
-	uint32_t  resource_type = 0;
+	struct cam_context         *ctx = (struct cam_context *)data;
+	struct cam_ctx_request     *req = NULL;
+	struct cam_ctx_request     *req_temp = NULL;
+	struct cam_hw_dump_pf_args *pf_args = (struct cam_hw_dump_pf_args *)args;
 	int rc = 0;
-	int closest_port;
-	bool b_mem_found = false, b_ctx_found = false;
 
-
-	if (!ctx) {
-		CAM_ERR(CAM_JPEG, "Invalid ctx");
+	if (!ctx || !pf_args) {
+		CAM_ERR(CAM_JPEG, "Invalid ctx %pK or pf args %pK",
+			ctx, pf_args);
 		return -EINVAL;
 	}
 
@@ -41,19 +38,23 @@ static int cam_jpeg_context_dump_active_request(void *data,
 
 	list_for_each_entry_safe(req, req_temp,
 			&ctx->active_req_list, list) {
-		pf_dbg_entry = &(req->pf_data);
-		closest_port = -1;
-		CAM_INFO(CAM_JPEG, "req_id : %lld ", req->request_id);
+		CAM_INFO(CAM_JPEG, "Active req_id: %lld, ctx_id: %u",
+			req->request_id, ctx->ctx_id);
 
-		rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry,
-			&b_mem_found, &b_ctx_found, &resource_type, pf_info);
+		rc = cam_context_dump_pf_info_to_hw(ctx, pf_args, &req->pf_data);
 		if (rc)
-			CAM_ERR(CAM_JPEG, "Failed to dump pf info");
+			CAM_ERR(CAM_JPEG, "Failed to dump pf info ctx_id: %u state: %d",
+				ctx->ctx_id, ctx->state);
+	}
 
-		if (b_mem_found)
-			CAM_ERR(CAM_JPEG, "Found page fault in req %lld %d",
-				req->request_id, rc);
+	if (pf_args->pf_context_info.ctx_found) {
+		/* Send PF notification to UMD if PF found on current CTX */
+		rc = cam_context_send_pf_evt(ctx, pf_args);
+		if (rc)
+			CAM_ERR(CAM_JPEG,
+				"Failed to notify PF event to userspace rc: %d", rc);
 	}
+
 	return rc;
 }
 

+ 24 - 7
drivers/cam_jpeg/cam_jpeg_dev.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/delay.h>
@@ -17,6 +18,7 @@
 #include "cam_smmu_api.h"
 #include "camera_main.h"
 #include "cam_common_util.h"
+#include "cam_context_utils.h"
 
 #define CAM_JPEG_DEV_NAME "cam-jpeg"
 
@@ -39,20 +41,35 @@ static int cam_jpeg_dev_err_inject_cb(void *err_param)
 }
 
 static void cam_jpeg_dev_iommu_fault_handler(
-	struct cam_smmu_pf_info *pf_info)
+	struct cam_smmu_pf_info *pf_smmu_info)
 {
-	int i = 0;
+	int i, rc;
 	struct cam_node *node = NULL;
+	struct cam_hw_dump_pf_args pf_args = {0};
 
-	if (!pf_info || !pf_info->token) {
-		CAM_ERR(CAM_ISP, "invalid token in page handler cb");
+	if (!pf_smmu_info || !pf_smmu_info->token) {
+		CAM_ERR(CAM_JPEG, "invalid token in page handler cb");
 		return;
 	}
 
-	node = (struct cam_node *)pf_info->token;
+	node = (struct cam_node *)pf_smmu_info->token;
 
-	for (i = 0; i < node->ctx_size; i++)
-		cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info);
+	pf_args.pf_smmu_info = pf_smmu_info;
+
+	for (i = 0; i < node->ctx_size; i++) {
+		cam_context_dump_pf_info(&(node->ctx_list[i]), &pf_args);
+		if (pf_args.pf_context_info.ctx_found)
+			/* found ctx and packet of the faulted address */
+			break;
+	}
+
+	if (i == node->ctx_size) {
+		/* Faulted ctx not found. But report PF to UMD anyway*/
+		rc = cam_context_send_pf_evt(NULL, &pf_args);
+		if (rc)
+			CAM_ERR(CAM_JPEG,
+				"Failed to notify PF event to userspace rc: %d", rc);
+	}
 }
 
 static void cam_jpeg_dev_mini_dump_cb(void *priv, void *args)

+ 14 - 72
drivers/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c

@@ -1931,23 +1931,20 @@ static void cam_jpeg_mgr_dump_pf_data(
 	struct cam_jpeg_hw_mgr  *hw_mgr,
 	struct cam_hw_cmd_args  *hw_cmd_args)
 {
-	struct cam_jpeg_hw_ctx_data    *ctx_data;
-	struct cam_packet              *packet;
-	struct cam_jpeg_match_pid_args  jpeg_pid_mid_args;
-	struct cam_buf_io_cfg          *io_cfg = NULL;
-	uint32_t                        dev_type;
-	dma_addr_t   iova_addr;
-	size_t       src_buf_size;
-	int          i, j;
-	int32_t    mmu_hdl;
-	bool      hw_pid_support = true;
-	int rc = 0;
+	struct cam_jpeg_hw_ctx_data   *ctx_data;
+	struct cam_packet             *packet;
+	struct cam_jpeg_match_pid_args jpeg_pid_mid_args;
+	struct cam_hw_dump_pf_args    *pf_args;
+	uint32_t                       dev_type;
+	bool                           hw_pid_support = true;
+	int                            rc = 0;
 
 	ctx_data = (struct cam_jpeg_hw_ctx_data  *)hw_cmd_args->ctxt_to_hw_map;
-	packet  = hw_cmd_args->u.pf_args.pf_data.packet;
+	pf_args = hw_cmd_args->u.pf_cmd_args->pf_args;
+	packet  = hw_cmd_args->u.pf_cmd_args->pf_req_info->packet;
 
-	jpeg_pid_mid_args.fault_mid = hw_cmd_args->u.pf_args.mid;
-	jpeg_pid_mid_args.pid = hw_cmd_args->u.pf_args.pid;
+	jpeg_pid_mid_args.fault_mid = pf_args->pf_smmu_info->mid;
+	jpeg_pid_mid_args.pid = pf_args->pf_smmu_info->pid;
 	dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
 
 	if (!hw_mgr->num_pid[dev_type]) {
@@ -1968,66 +1965,11 @@ static void cam_jpeg_mgr_dump_pf_data(
 		CAM_INFO(CAM_JPEG, "This context data is not matched with pf pid and mid");
 		return;
 	}
+	pf_args->pf_context_info.resource_type = jpeg_pid_mid_args.match_res;
 
 iodump:
-	io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
-		packet->io_configs_offset / 4);
-
-	for (i = 0; i < packet->num_io_configs; i++) {
-		if (hw_pid_support) {
-			if (io_cfg[i].resource_type !=
-				jpeg_pid_mid_args.match_res)
-				continue;
-
-			if (i == packet->num_io_configs) {
-				CAM_ERR(CAM_JPEG,
-					"getting io port for mid resource id failed  req id:%lld res id:0x%x",
-					packet->header.request_id,
-					jpeg_pid_mid_args.match_res);
-				return;
-			}
-		}
-
-		for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
-			if (!io_cfg[i].mem_handle[j])
-				break;
-
-			CAM_INFO(CAM_JPEG, "port: %d f: %u format: %d dir %d",
-				io_cfg[i].resource_type,
-				io_cfg[i].fence,
-				io_cfg[i].format,
-				io_cfg[i].direction);
-
-			mmu_hdl = cam_mem_is_secure_buf(
-				io_cfg[i].mem_handle[j]) ? hw_mgr->iommu_sec_hdl :
-				hw_mgr->iommu_hdl;
-			rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
-				mmu_hdl, &iova_addr, &src_buf_size, NULL);
-			if (rc < 0) {
-				CAM_ERR(CAM_UTIL, "get src buf address fail");
-				continue;
-			}
-			if ((iova_addr & 0xFFFFFFFF) != iova_addr) {
-				CAM_ERR(CAM_JPEG, "Invalid mapped address");
-				rc = -EINVAL;
-				continue;
-			}
-
-			CAM_INFO(CAM_JPEG,
-				"pln %u w %u h %u stride %u slice %u size %d addr 0x%x offset 0x%x memh %x",
-				j, io_cfg[i].planes[j].width,
-				io_cfg[i].planes[j].height,
-				io_cfg[i].planes[j].plane_stride,
-				io_cfg[i].planes[j].slice_height,
-				(int32_t)src_buf_size,
-				(unsigned int)iova_addr,
-				io_cfg[i].offsets[j],
-				io_cfg[i].mem_handle[j]);
-		}
-
-		if (hw_pid_support)
-			return;
-	}
+	cam_packet_util_dump_io_bufs(packet, hw_mgr->iommu_hdl, hw_mgr->iommu_sec_hdl,
+		pf_args, hw_pid_support);
 }
 
 static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args)

+ 21 - 27
drivers/cam_ope/cam_ope_context.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/debugfs.h>
@@ -23,49 +24,42 @@
 
 static const char ope_dev_name[] = "cam-ope";
 
-static int cam_ope_context_dump_active_request(void *data,
-	struct cam_smmu_pf_info *pf_info)
+static int cam_ope_context_dump_active_request(void *data, void *args)
 {
-	struct cam_context *ctx = (struct cam_context *)data;
-	struct cam_ctx_request          *req = NULL;
-	struct cam_ctx_request          *req_temp = NULL;
-	struct cam_hw_mgr_dump_pf_data  *pf_dbg_entry = NULL;
-	uint32_t  resource_type = 0;
+	struct cam_context         *ctx = (struct cam_context *)data;
+	struct cam_ctx_request     *req = NULL;
+	struct cam_ctx_request     *req_temp = NULL;
+	struct cam_hw_dump_pf_args *pf_args = (struct cam_hw_dump_pf_args *)args;
 	int rc = 0;
-	bool b_mem_found = false, b_ctx_found = false;
 
-	if (!ctx) {
-		CAM_ERR(CAM_OPE, "Invalid ctx");
+	if (!ctx || !pf_args) {
+		CAM_ERR(CAM_OPE, "Invalid ctx %pK or pf args %pK",
+			ctx, pf_args);
 		return -EINVAL;
 	}
 
-	mutex_lock(&ctx->ctx_mutex);
-	if (ctx->state < CAM_CTX_ACQUIRED || ctx->state > CAM_CTX_ACTIVATED) {
-		CAM_ERR(CAM_OPE, "Invalid state ope ctx %d state %d",
-			ctx->ctx_id, ctx->state);
-		goto end;
-	}
-
 	CAM_INFO(CAM_OPE, "iommu fault for ope ctx %d state %d",
 		ctx->ctx_id, ctx->state);
 
 	list_for_each_entry_safe(req, req_temp,
 			&ctx->active_req_list, list) {
-		pf_dbg_entry = &(req->pf_data);
-		CAM_INFO(CAM_OPE, "req_id : %lld", req->request_id);
+		CAM_INFO(CAM_OPE, "Active req_id: %llu ctx_id: %u",
+			req->request_id, ctx->ctx_id);
 
-		rc = cam_context_dump_pf_info_to_hw(ctx, pf_dbg_entry,
-			&b_mem_found, &b_ctx_found, &resource_type, pf_info);
+		rc = cam_context_dump_pf_info_to_hw(ctx, pf_args, &req->pf_data);
 		if (rc)
-			CAM_ERR(CAM_OPE, "Failed to dump pf info");
+			CAM_ERR(CAM_OPE, "Failed to dump pf info ctx_id: %u state: %d",
+				ctx->ctx_id, ctx->state);
+	}
 
-		if (b_mem_found)
-			CAM_ERR(CAM_OPE, "Found page fault in req %lld %d",
-				req->request_id, rc);
+	if (pf_args->pf_context_info.ctx_found) {
+		/* Send PF notification to UMD if PF found on current CTX */
+		rc = cam_context_send_pf_evt(ctx, pf_args);
+		if (rc)
+			CAM_ERR(CAM_OPE,
+				"Failed to notify PF event to userspace rc: %d", rc);
 	}
 
-end:
-	mutex_unlock(&ctx->ctx_mutex);
 	return rc;
 }
 

+ 23 - 7
drivers/cam_ope/cam_ope_subdev.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #include <linux/delay.h>
@@ -30,6 +31,7 @@
 #include "cam_debug_util.h"
 #include "cam_smmu_api.h"
 #include "camera_main.h"
+#include "cam_context_utils.h"
 
 #define OPE_DEV_NAME        "cam-ope"
 
@@ -46,20 +48,34 @@ struct cam_ope_subdev {
 static struct cam_ope_subdev g_ope_dev;
 
 static void cam_ope_dev_iommu_fault_handler(
-	struct cam_smmu_pf_info *pf_info)
+	struct cam_smmu_pf_info *pf_smmu_info)
 {
-	int i = 0;
+	int i, rc;
 	struct cam_node *node = NULL;
+	struct cam_hw_dump_pf_args pf_args = {0};
 
-	if (!pf_info || !pf_info->token) {
-		CAM_ERR(CAM_ISP, "invalid token in page handler cb");
+	if (!pf_smmu_info || !pf_smmu_info->token) {
+		CAM_ERR(CAM_OPE, "invalid token in page handler cb");
 		return;
 	}
 
-	node = (struct cam_node *)pf_info->token;
+	node = (struct cam_node *)pf_smmu_info->token;
+	pf_args.pf_smmu_info = pf_smmu_info;
 
-	for (i = 0; i < node->ctx_size; i++)
-		cam_context_dump_pf_info(&(node->ctx_list[i]), pf_info);
+	for (i = 0; i < node->ctx_size; i++) {
+		cam_context_dump_pf_info(&(node->ctx_list[i]), &pf_args);
+		if (pf_args.pf_context_info.ctx_found)
+			/* found ctx and packet of the faulted address */
+			break;
+	}
+
+	if (i == node->ctx_size) {
+		/* Faulted ctx not found. But report PF to UMD anyway*/
+		rc = cam_context_send_pf_evt(NULL, &pf_args);
+		if (rc)
+			CAM_ERR(CAM_OPE,
+				"Failed to notify PF event to userspace rc: %d", rc);
+	}
 }
 
 static int cam_ope_subdev_open(struct v4l2_subdev *sd,

+ 50 - 87
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.c

@@ -1596,7 +1596,7 @@ static int cam_ope_mgr_ope_clk_update(struct cam_ope_hw_mgr *hw_mgr,
 }
 
 static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
-	enum cam_cdm_cb_status status, uint64_t cookie)
+	enum cam_cdm_cb_status status, void *cookie)
 {
 	int rc = 0;
 	struct cam_ope_ctx *ctx;
@@ -1604,6 +1604,7 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
 	struct cam_hw_done_event_data buf_data;
 	struct timespec64 ts;
 	uint32_t evt_id = CAM_CTX_EVT_ID_SUCCESS;
+	uint64_t req_id = 0;
 	bool dump_flag = true;
 	int i;
 
@@ -1612,29 +1613,32 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
 		return;
 	}
 
-	if (cookie >= CAM_CTX_REQ_MAX) {
-		CAM_ERR(CAM_OPE, "Invalid reqIdx = %llu", cookie);
+	if (status != CAM_CDM_CB_STATUS_PAGEFAULT)
+		req_id = *(uint64_t *)cookie;
+
+	if (req_id >= CAM_CTX_REQ_MAX) {
+		CAM_ERR(CAM_OPE, "Invalid reqIdx = %u", req_id);
 		return;
 	}
 
 	ctx = userdata;
 	mutex_lock(&ctx->ctx_mutex);
 
-	if (!test_bit(cookie, ctx->bitmap)) {
-		CAM_ERR(CAM_OPE, "Req not present reqIdx = %d for ctx_id = %d",
-			cookie, ctx->ctx_id);
+	if (!test_bit(req_id, ctx->bitmap)) {
+		CAM_ERR(CAM_OPE, "Req not present reqIdx = %u for ctx_id = %d",
+			req_id, ctx->ctx_id);
 		goto end;
 	}
 
-	ope_req = ctx->req_list[cookie];
+	ope_req = ctx->req_list[req_id];
 
 	ktime_get_boottime_ts64(&ts);
 	ope_hw_mgr->last_callback_time = (uint64_t)((ts.tv_sec * 1000000000) +
 		ts.tv_nsec);
 
 	CAM_DBG(CAM_REQ,
-		"hdl=%x, udata=%pK, status=%d, cookie=%d",
-		handle, userdata, status, cookie);
+		"hdl=%x, udata=%pK, status=%d, cookie=%u",
+		handle, userdata, status, req_id);
 	CAM_DBG(CAM_REQ, "req_id= %llu ctx_id= %d lcb=%llu",
 		ope_req->request_id, ctx->ctx_id,
 		ope_hw_mgr->last_callback_time);
@@ -1648,8 +1652,8 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
 
 	if (status == CAM_CDM_CB_STATUS_BL_SUCCESS) {
 		CAM_DBG(CAM_OPE,
-			"hdl=%x, udata=%pK, status=%d, cookie=%d  req_id=%llu ctx_id=%d",
-			handle, userdata, status, cookie,
+			"hdl=%x, udata=%pK, status=%d, cookie=%u  req_id=%llu ctx_id=%d",
+			handle, userdata, status, req_id,
 			ope_req->request_id, ctx->ctx_id);
 		cam_ope_req_timer_reset(ctx);
 		cam_ope_device_timer_reset(ope_hw_mgr);
@@ -1662,8 +1666,8 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
 			goto end;
 	} else {
 		CAM_INFO(CAM_OPE,
-			"CDM hdl=%x, udata=%pK, status=%d, cookie=%d req_id = %llu ctx_id=%d",
-			 handle, userdata, status, cookie,
+			"CDM hdl=%x, udata=%pK, status=%d, cookie=%u req_id = %llu ctx_id=%d",
+			 handle, userdata, status, req_id,
 			 ope_req->request_id, ctx->ctx_id);
 		CAM_INFO(CAM_OPE, "Rst of CDM and OPE for error reqid = %lld",
 			ope_req->request_id);
@@ -1672,10 +1676,10 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
 			cam_ope_dump_req_data(ope_req);
 			dump_flag = false;
 
-			CAM_INFO(CAM_OPE, "bach_size: %d", ctx->req_list[cookie]->num_batch);
-			for (i = 0; i < ctx->req_list[cookie]->num_batch; i++)
+			CAM_INFO(CAM_OPE, "bach_size: %d", ctx->req_list[req_id]->num_batch);
+			for (i = 0; i < ctx->req_list[req_id]->num_batch; i++)
 				CAM_INFO(CAM_OPE, "i: %d num_stripes: %d",
-					i, ctx->req_list[cookie]->num_stripes[i]);
+					i, ctx->req_list[req_id]->num_stripes[i]);
 		}
 		rc = cam_ope_mgr_reset_hw();
 		evt_id = CAM_CTX_EVT_ID_ERROR;
@@ -1699,12 +1703,12 @@ static void cam_ope_ctx_cdm_callback(uint32_t handle, void *userdata,
 
 	buf_data.request_id = ope_req->request_id;
 	ope_req->request_id = 0;
-	cam_free_clear((void *)ctx->req_list[cookie]->cdm_cmd);
-	ctx->req_list[cookie]->cdm_cmd = NULL;
-	cam_ope_free_io_config(ctx->req_list[cookie]);
-	cam_free_clear((void *)ctx->req_list[cookie]);
-	ctx->req_list[cookie] = NULL;
-	clear_bit(cookie, ctx->bitmap);
+	cam_free_clear((void *)ctx->req_list[req_id]->cdm_cmd);
+	ctx->req_list[req_id]->cdm_cmd = NULL;
+	cam_ope_free_io_config(ctx->req_list[req_id]);
+	cam_free_clear((void *)ctx->req_list[req_id]);
+	ctx->req_list[req_id] = NULL;
+	clear_bit(req_id, ctx->bitmap);
 	ctx->ctxt_event_cb(ctx->context_priv, evt_id, &buf_data);
 
 end:
@@ -4095,14 +4099,12 @@ static void cam_ope_mgr_dump_pf_data(
 	struct cam_ope_request         *ope_request;
 	struct ope_io_buf              *io_buf = NULL;
 	struct cam_ope_match_pid_args  ope_pid_mid_args;
+	struct cam_hw_dump_pf_args     *pf_args;
 
-	dma_addr_t   iova_addr;
 	int          device_idx;
 	bool         *ctx_found;
 	bool         io_buf_found = false;
-	size_t       src_buf_size;
 	int          i, j;
-	int32_t      mmu_hdl;
 	bool         hw_pid_support = true;
 	bool         hw_id_found = false;
 	uint32_t     *resource_type;
@@ -4110,13 +4112,15 @@ static void cam_ope_mgr_dump_pf_data(
 	int          rc = 0;
 
 	ctx_data    = (struct cam_ope_ctx *)hw_cmd_args->ctxt_to_hw_map;
-	packet      = hw_cmd_args->u.pf_args.pf_data.packet;
-	ope_request = hw_cmd_args->u.pf_args.pf_data.req;
+	pf_args = hw_cmd_args->u.pf_cmd_args->pf_args;
+	packet  = hw_cmd_args->u.pf_cmd_args->pf_req_info->packet;
+
+	ope_request = hw_cmd_args->u.pf_cmd_args->pf_req_info->req;
 
-	ope_pid_mid_args.fault_mid = hw_cmd_args->u.pf_args.mid;
-	ope_pid_mid_args.fault_pid = hw_cmd_args->u.pf_args.pid;
-	ctx_found = hw_cmd_args->u.pf_args.ctx_found;
-	resource_type = hw_cmd_args->u.pf_args.resource_type;
+	ope_pid_mid_args.fault_mid =  pf_args->pf_smmu_info->mid;
+	ope_pid_mid_args.fault_pid = pf_args->pf_smmu_info->pid;
+	ctx_found = &(pf_args->pf_context_info.ctx_found);
+	resource_type = &(pf_args->pf_context_info.resource_type);
 
 	if (ctx_data->pf_mid_found)
 		goto stripedump;
@@ -4133,7 +4137,7 @@ static void cam_ope_mgr_dump_pf_data(
 			continue;
 		for (j = 0; j < ope_hw_mgr->ope_dev_data[i]->num_hw_pid; j++) {
 			if (ope_hw_mgr->ope_dev_data[i]->hw_pid[j] ==
-					hw_cmd_args->u.pf_args.pid) {
+					pf_args->pf_smmu_info->pid) {
 				hw_id_found = true;
 				device_idx = i;
 				*ctx_found = true;
@@ -4147,7 +4151,7 @@ static void cam_ope_mgr_dump_pf_data(
 	if (i == ope_hw_mgr->num_ope) {
 		CAM_INFO(CAM_OPE,
 			"PID:%d  is not matching with any OPE HW PIDs ctx id:%d",
-			hw_cmd_args->u.pf_args.pid, ctx_data->ctx_id);
+			pf_args->pf_smmu_info->pid, ctx_data->ctx_id);
 		return;
 	}
 
@@ -4189,67 +4193,26 @@ stripedump:
 		if (io_buf_found)
 			break;
 	}
+
 iodump:
-	for (i = 0; i < packet->num_io_configs; i++) {
-		if (hw_pid_support) {
-			if (io_cfg[i].resource_type !=
-				*resource_type)
-				continue;
-		}
+	cam_packet_util_dump_io_bufs(packet, hw_mgr->iommu_hdl,
+		hw_mgr->iommu_sec_hdl, pf_args, hw_pid_support);
 
+	if (io_buf_found) {
 		for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
-			if (!io_cfg[i].mem_handle[j])
+			if (j >= OPE_MAX_PLANES) {
+				CAM_INFO(CAM_OPE, "Invalid plane idx: %d", j);
 				break;
-			CAM_INFO(CAM_OPE, "port: %d f: %u format: %d dir %d",
-				io_cfg[i].resource_type,
-				io_cfg[i].fence,
-				io_cfg[i].format,
-				io_cfg[i].direction);
-
-			mmu_hdl = cam_mem_is_secure_buf(
-					io_cfg[i].mem_handle[j]) ?
-					hw_mgr->iommu_sec_hdl :
-					hw_mgr->iommu_hdl;
-			rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
-					mmu_hdl, &iova_addr, &src_buf_size, NULL);
-			if (rc < 0) {
-				CAM_ERR(CAM_UTIL, "get src buf address fail");
-				continue;
-			}
-			if ((iova_addr & 0xFFFFFFFF) != iova_addr) {
-				CAM_ERR(CAM_OPE, "Invalid mapped address");
-				rc = -EINVAL;
-				continue;
 			}
 
-			CAM_INFO(CAM_OPE,
-				"pln %u w %u h %u stride %u slice %u size %zu addr 0x%llx offset 0x%x memh %x",
-				j, io_cfg[i].planes[j].width,
-				io_cfg[i].planes[j].height,
-				io_cfg[i].planes[j].plane_stride,
-				io_cfg[i].planes[j].slice_height,
-				src_buf_size, iova_addr,
-				io_cfg[i].offsets[j],
-				io_cfg[i].mem_handle[j]);
-
-			if (io_buf_found) {
-				if (j >= OPE_MAX_PLANES) {
-					CAM_ERR(CAM_OPE, "Invalid plane idx: %d", j);
-					break;
-				}
-
-				for (stripe_num = 0; stripe_num < io_buf->num_stripes[j];
-						stripe_num++) {
-					CAM_INFO(CAM_OPE,
-						"pln_num %d stripe_num %d width %d height %d stride %d iovaddr 0x%llx",
-						j, stripe_num, io_buf->s_io[j][stripe_num].width,
-						io_buf->s_io[j][stripe_num].height,
-						io_buf->s_io[j][stripe_num].stride,
-						io_buf->s_io[j][stripe_num].iova_addr);
-				}
+			for (stripe_num = 0; stripe_num < io_buf->num_stripes[j]; stripe_num++) {
+				CAM_INFO(CAM_OPE,
+					"pln_num %d stripe_num %d width %d height %d stride %d iovaddr 0x%llx",
+					j, stripe_num, io_buf->s_io[j][stripe_num].width,
+					io_buf->s_io[j][stripe_num].height,
+					io_buf->s_io[j][stripe_num].stride,
+					io_buf->s_io[j][stripe_num].iova_addr);
 			}
 		}
-		if (hw_pid_support)
-			return;
 	}
 }

+ 1 - 1
drivers/cam_ope/ope_hw_mgr/cam_ope_hw_mgr.h

@@ -412,7 +412,7 @@ struct cam_ope_request {
 	struct cam_cdm_bl_request *cdm_cmd;
 	struct cam_ope_clk_bw_request clk_info;
 	struct cam_ope_clk_bw_req_internal_v2 clk_info_v2;
-	struct cam_hw_mgr_dump_pf_data hang_data;
+	struct cam_hw_mgr_pf_request_info hang_data;
 	ktime_t submit_timestamp;
 };
 

+ 12 - 4
drivers/cam_smmu/cam_smmu_api.c

@@ -353,7 +353,7 @@ static void cam_smmu_print_table(void);
 
 static int cam_smmu_probe(struct platform_device *pdev);
 
-static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr);
+static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr, bool *in_map_region);
 
 static void cam_smmu_update_monitor_array(
 	struct cam_context_bank_info *cb_info,
@@ -542,8 +542,9 @@ static void cam_smmu_page_fault_work(struct work_struct *work)
 	int j;
 	int idx;
 	struct cam_smmu_work_payload *payload;
-	uint32_t buf_info;
+	uint32_t buf_info = 0;
 	struct cam_smmu_pf_info pf_info;
+	bool in_map = false;
 
 	mutex_lock(&iommu_cb_set.payload_list_lock);
 	if (list_empty(&iommu_cb_set.payload_list)) {
@@ -562,7 +563,10 @@ static void cam_smmu_page_fault_work(struct work_struct *work)
 
 	/* Dereference the payload to call the handler */
 	idx = payload->idx;
-	buf_info = cam_smmu_find_closest_mapping(idx, (void *)payload->iova);
+	/* If fault address is null, found closest buffer is inaccurate */
+	if (payload->iova)
+		buf_info = cam_smmu_find_closest_mapping(idx, (void *)payload->iova, &in_map);
+
 	if (buf_info != 0)
 		CAM_INFO(CAM_SMMU, "closest buf 0x%x idx %d", buf_info, idx);
 
@@ -571,6 +575,8 @@ static void cam_smmu_page_fault_work(struct work_struct *work)
 	pf_info.iova  = payload->iova;
 	pf_info.flags = payload->flags;
 	pf_info.buf_info = buf_info;
+	pf_info.is_secure = iommu_cb_set.cb_info[idx].is_secure;
+	pf_info.in_map_region = in_map;
 
 	for (j = 0; j < CAM_SMMU_CB_MAX; j++) {
 		if ((iommu_cb_set.cb_info[idx].handler[j])) {
@@ -675,7 +681,7 @@ static void cam_smmu_print_table(void)
 	}
 }
 
-static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr)
+static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr, bool *in_map_region)
 {
 	struct cam_dma_buff_info *mapping, *closest_mapping =  NULL;
 	unsigned long start_addr, end_addr, current_addr;
@@ -684,6 +690,7 @@ static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr)
 	long delta = 0, lowest_delta = 0;
 
 	current_addr = (unsigned long)vaddr;
+	*in_map_region = false;
 	list_for_each_entry(mapping,
 			&iommu_cb_set.cb_info[idx].smmu_buf_list, list) {
 		start_addr = (unsigned long)mapping->paddr;
@@ -691,6 +698,7 @@ static uint32_t cam_smmu_find_closest_mapping(int idx, void *vaddr)
 
 		if (start_addr <= current_addr && current_addr <= end_addr) {
 			closest_mapping = mapping;
+			*in_map_region = true;
 			CAM_INFO(CAM_SMMU,
 				"Found va 0x%lx in:0x%lx-0x%lx, fd %d i_ino %lu cb:%s",
 				current_addr, start_addr,

+ 27 - 17
drivers/cam_smmu/cam_smmu_api.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
 #ifndef _CAM_SMMU_API_H_
@@ -17,6 +18,11 @@
 #include <linux/mutex.h>
 #include <linux/msm_ion.h>
 
+#define CAM_SMMU_GET_IOVA_DELTA(val1, val2)                                \
+({                                                                         \
+	(val1) > (val2) ? (val1) - (val2) : (val2) - (val1);               \
+})
+
 /*Enum for possible CAM SMMU operations */
 enum cam_smmu_ops_param {
 	CAM_SMMU_ATTACH,
@@ -46,27 +52,31 @@ enum cam_smmu_region_id {
 /**
  * @brief          : cam_smmu_pf_info
  *
- * @param domain   : Iommu domain received in iommu page fault handler
- * @param dev      : Device received in iommu page fault handler
- * @param iova     : IOVA where page fault occurred
- * @param flags    : Flags received in iommu page fault handler
- * @param token    : Userdata given during callback registration
- * @param buf_info : Closest mapped buffer info
- * @bid            : bus id
- * @pid            : unique id for hw group of ports
- * @mid            : port id of hw
+ * @param domain           : Iommu domain received in iommu page fault handler
+ * @param dev              : Device received in iommu page fault handler
+ * @param iova             : IOVA where page fault occurred
+ * @param flags            : Flags received in iommu page fault handler
+ * @param token            : Userdata given during callback registration
+ * @param buf_info         : Closest mapped buffer info
+ * @param bid              : bus id
+ * @param pid              : unique id for hw group of ports
+ * @param mid              : port id of hw
+ * @param is_secure        : Faulted memory in secure or non-secure region
+ * @param in_map_region    : Faulted memory fall in mapped region or not
  */
 
 struct cam_smmu_pf_info {
-	struct iommu_domain *domain;
+	struct iommu_domain  *domain;
 	struct device        *dev;
-	unsigned long        iova;
-	int                  flags;
-	void                *token;
-	uint32_t             buf_info;
-	uint32_t             bid;
-	uint32_t             pid;
-	uint32_t             mid;
+	unsigned long         iova;
+	int                   flags;
+	void                 *token;
+	uint32_t              buf_info;
+	uint32_t              bid;
+	uint32_t              pid;
+	uint32_t              mid;
+	bool                  is_secure;
+	bool                  in_map_region;
 };
 
 /**

+ 124 - 4
drivers/cam_utils/cam_packet_util.c

@@ -166,10 +166,11 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
 	return rc;
 }
 
-void cam_packet_dump_patch_info(struct cam_packet *packet,
-	int32_t iommu_hdl, int32_t sec_mmu_hdl)
+void cam_packet_util_dump_patch_info(struct cam_packet *packet,
+	int32_t iommu_hdl, int32_t sec_iommu_hdl, struct cam_hw_dump_pf_args *pf_args)
 {
 	struct cam_patch_desc *patch_desc = NULL;
+	struct cam_context_pf_info *pf_context_info  = NULL;
 	dma_addr_t iova_addr;
 	size_t     dst_buf_len;
 	size_t     src_buf_size;
@@ -177,19 +178,29 @@ void cam_packet_dump_patch_info(struct cam_packet *packet,
 	int32_t    hdl;
 	uintptr_t  cpu_addr = 0;
 	uint32_t  *dst_cpu_addr;
-	uint32_t   flags;
+	uint32_t   flags, buf_fd;
 	uint32_t   value = 0;
 
+	if (!packet) {
+		CAM_ERR(CAM_UTIL, "Invalid packet");
+		return;
+	}
+
 	patch_desc = (struct cam_patch_desc *)
 			((uint32_t *) &packet->payload +
 			packet->patch_offset/4);
 
+	if (pf_args) {
+		pf_context_info = &(pf_args->pf_context_info);
+		buf_fd = pf_args->pf_smmu_info->buf_info;
+	}
+
 	CAM_INFO(CAM_UTIL, "Total num of patches : %d",
 		packet->num_patches);
 
 	for (i = 0; i < packet->num_patches; i++) {
 		hdl = cam_mem_is_secure_buf(patch_desc[i].src_buf_hdl) ?
-			sec_mmu_hdl : iommu_hdl;
+			sec_iommu_hdl : iommu_hdl;
 		rc = cam_mem_get_io_buf(patch_desc[i].src_buf_hdl,
 			hdl, &iova_addr, &src_buf_size, &flags);
 		if (rc < 0) {
@@ -199,6 +210,24 @@ void cam_packet_dump_patch_info(struct cam_packet *packet,
 			return;
 		}
 
+		if (pf_args &&
+			GET_FD_FROM_HANDLE(patch_desc[i].src_buf_hdl) == buf_fd &&
+			pf_context_info->mem_type == CAM_FAULT_BUF_NOT_FOUND) {
+			/* found PF at this hdl */
+			pf_context_info->mem_type = CAM_FAULT_PATCH_BUF;
+			pf_context_info->patch_idx = i;
+			pf_context_info->buf_hdl = patch_desc[i].src_buf_hdl;
+			pf_context_info->offset = patch_desc[i].src_offset;
+			pf_context_info->mem_flag = flags;
+			pf_context_info->delta =
+				CAM_SMMU_GET_IOVA_DELTA(pf_args->pf_smmu_info->iova, iova_addr);
+			pf_context_info->req_id = packet->header.request_id;
+			pf_context_info->ctx_found = true;
+
+			CAM_ERR(CAM_UTIL, "Found PF at patch: %d src buf hdl: 0x%llx",
+				i, patch_desc[i].src_buf_hdl);
+		}
+
 		rc = cam_mem_get_cpu_buf(patch_desc[i].dst_buf_hdl,
 			&cpu_addr, &dst_buf_len);
 		if (rc < 0 || !cpu_addr || (dst_buf_len == 0)) {
@@ -382,6 +411,97 @@ int cam_packet_util_process_patches(struct cam_packet *packet,
 	return rc;
 }
 
+void cam_packet_util_dump_io_bufs(struct cam_packet *packet,
+	int32_t iommu_hdl, int32_t sec_mmu_hdl,
+	struct cam_hw_dump_pf_args *pf_args, bool res_id_support)
+{
+	struct cam_buf_io_cfg      *io_cfg;
+	struct cam_context_pf_info *pf_context_info;
+	int32_t        mmu_hdl, buf_fd;
+	dma_addr_t     iova_addr;
+	size_t         src_buf_size;
+	int            i, j, rc = 0;
+	uint32_t       resource_type;
+
+	if (!packet) {
+		CAM_ERR(CAM_UTIL, "Invalid packet");
+		return;
+	}
+
+	io_cfg = (struct cam_buf_io_cfg *)((uint32_t *)&packet->payload +
+		packet->io_configs_offset / 4);
+
+	buf_fd = pf_args->pf_smmu_info->buf_info;
+	pf_context_info = &(pf_args->pf_context_info);
+	resource_type = pf_context_info->resource_type;
+
+	for (i = 0; i < packet->num_io_configs; i++) {
+		if (res_id_support && io_cfg[i].resource_type !=
+			pf_context_info->resource_type)
+			continue;
+
+		for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) {
+			if (!io_cfg[i].mem_handle[j])
+				break;
+
+			CAM_INFO(CAM_UTIL, "port: 0x%x f: %u format: %d dir %d",
+				io_cfg[i].resource_type,
+				io_cfg[i].fence,
+				io_cfg[i].format,
+				io_cfg[i].direction);
+
+			mmu_hdl = cam_mem_is_secure_buf(
+				io_cfg[i].mem_handle[j]) ? sec_mmu_hdl :
+				iommu_hdl;
+			rc = cam_mem_get_io_buf(io_cfg[i].mem_handle[j],
+				mmu_hdl, &iova_addr, &src_buf_size, NULL);
+			if (rc < 0) {
+				CAM_ERR(CAM_UTIL,
+					"get src buf address fail mem_handle 0x%x",
+					io_cfg[i].mem_handle[j]);
+				continue;
+			}
+			if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == buf_fd) {
+				pf_context_info->mem_type = CAM_FAULT_IO_CFG_BUF;
+				pf_context_info->buf_hdl = io_cfg[i].mem_handle[j];
+				pf_context_info->offset = io_cfg[i].offsets[j];
+				pf_context_info->resource_type = io_cfg[i].resource_type;
+				pf_context_info->delta =
+					CAM_SMMU_GET_IOVA_DELTA(pf_args->pf_smmu_info->iova,
+						iova_addr);
+				pf_context_info->req_id = packet->header.request_id;
+				pf_context_info->ctx_found = true;
+
+				resource_type = pf_context_info->resource_type;
+				CAM_INFO(CAM_UTIL,
+					"Found PF at port: 0x%x mem 0x%x fd: %d plane id: %d delta: %llu",
+					io_cfg[i].resource_type,
+					io_cfg[i].mem_handle[j],
+					buf_fd,
+					j, pf_context_info->delta);
+			}
+			CAM_INFO(CAM_UTIL,
+				"pln %d w %d h %d s %u size %zu addr 0x%llx end_addr 0x%llx offset %u memh 0x%x",
+				j, io_cfg[i].planes[j].width,
+				io_cfg[i].planes[j].height,
+				io_cfg[i].planes[j].plane_stride,
+				src_buf_size, iova_addr,
+				iova_addr + src_buf_size,
+				io_cfg[i].offsets[j],
+				io_cfg[i].mem_handle[j]);
+		}
+
+		if (res_id_support)
+			return;
+	}
+
+	if (res_id_support)
+		CAM_ERR(CAM_UTIL,
+			"getting io port for mid resource id failed req id: %llu res id: 0x%x",
+			packet->header.request_id, resource_type);
+
+}
+
 int cam_packet_util_process_generic_cmd_buffer(
 	struct cam_cmd_buf_desc *cmd_buf,
 	cam_packet_generic_blob_handler blob_handler_cb, void *user_data)

+ 22 - 4
drivers/cam_utils/cam_packet_util.h

@@ -8,7 +8,7 @@
 #define _CAM_PACKET_UTIL_H_
 
 #include <media/cam_defs.h>
-
+#include "cam_hw_mgr_intf.h"
 /**
  * @brief                  KMD scratch buffer information
  *
@@ -88,7 +88,7 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
 	struct cam_kmd_buf_info *kmd_buf_info);
 
 /**
- * cam_packet_dump_patch_info()
+ * cam_packet_util_dump_patch_info()
  *
  * @brief:              Dump patch info in case of page fault
  *
@@ -96,10 +96,11 @@ int cam_packet_util_get_kmd_buffer(struct cam_packet *packet,
  * @iommu_hdl:          IOMMU handle of the HW Device that received the packet
  * @sec_iommu_hdl:      Secure IOMMU handle of the HW Device that
  *                      received the packet
+ * @pf_args:            Page fault arguments
  *
  */
-void cam_packet_dump_patch_info(struct cam_packet *packet,
-	int32_t iommu_hdl, int32_t sec_mmu_hdl);
+void cam_packet_util_dump_patch_info(struct cam_packet *packet,
+	int32_t iommu_hdl, int32_t sec_iommu_hdl, struct cam_hw_dump_pf_args *pf_args);
 
 /**
  * cam_packet_util_process_patches()
@@ -120,6 +121,23 @@ void cam_packet_dump_patch_info(struct cam_packet *packet,
 int cam_packet_util_process_patches(struct cam_packet *packet,
 	int32_t iommu_hdl, int32_t sec_mmu_hdl, bool exp_mem);
 
+/**
+ * cam_packet_util_dump_io_bufs()
+ *
+ * @brief:              Search for faulted io buffer in packet and print io buffers info
+ *
+ * @packet:             Input packet containing io buffers
+ * @iommu_hdl:          IOMMU handle of the HW Device that received the packet
+ * @sec_iommu_hdl:      Secure IOMMU handle of the HW Device that
+ *                      received the packet
+ * @pf_args:            Pault Fault related info
+ * @res_id_support:     if the specific device has knowledge of the resource id for hw
+ */
+
+void cam_packet_util_dump_io_bufs(struct cam_packet *packet,
+	int32_t iommu_hdl, int32_t sec_mmu_hdl,
+	struct cam_hw_dump_pf_args *pf_args, bool res_id_support);
+
 /**
  * cam_packet_util_process_generic_cmd_buffer()
  *