Browse Source

msm: camera: cpas: Enable camnoc slave error irq

Enable camnoc slave error irq to identify address decode
errors. Also change the camnoc irq clear logic. The change
also avoids dumping error logger info. Also remove
any error logging in client callbacks for slave error
if the client intends to not handle it.

CRs-Fixed: 3175797
Change-Id: Iec2c0c3b50a52a4c61ce2d5f6f263327625a8267
Signed-off-by: Karthik Anantha Ram <[email protected]>
Karthik Anantha Ram 3 năm trước cách đây
mục cha
commit
0b86e7f627

+ 11 - 2
drivers/cam_cpas/cam_cpas_hw.h

@@ -263,6 +263,9 @@ struct cam_cpas_monitor {
  * @num_camnoc_axi_ports: Total number of camnoc axi ports found in device tree
  * @registered_clients: Number of Clients registered currently
  * @streamon_clients: Number of Clients that are in start state currently
+ * @slave_err_irq_idx: Index of slave error in irq error data structure,
+ *                     avoids iterating the entire structure to find this
+ *                     idx in irq th
  * @regbase_index: Register base indices for CPAS register base IDs
  * @ahb_bus_client: AHB Bus client info
  * @axi_port: AXI port info for a specific axi index
@@ -276,9 +279,12 @@ struct cam_cpas_monitor {
  * @applied_camnoc_axi_rate: applied camnoc axi clock rate
  * @monitor_head: Monitor array head
  * @monitor_entries: cpas monitor array
+ * @camnoc_info: Pointer to camnoc header info
  * @full_state_dump: Whether to enable full cpas state dump or not
  * @smart_qos_dump: Whether to dump smart qos information on update
- * @camnoc_info: Pointer to camnoc header info
+ * @slave_err_irq_en: Whether slave error irq is enabled to detect memory
+ *                    config issues
+ * @smmu_fault_handled: Handled address decode error, on fault at SMMU
  */
 struct cam_cpas {
 	struct cam_cpas_hw_caps hw_caps;
@@ -290,6 +296,7 @@ struct cam_cpas {
 	uint32_t num_camnoc_axi_ports;
 	uint32_t registered_clients;
 	uint32_t streamon_clients;
+	uint32_t slave_err_irq_idx;
 	int32_t regbase_index[CAM_CPAS_REG_MAX];
 	struct cam_cpas_bus_client ahb_bus_client;
 	struct cam_cpas_axi_port axi_port[CAM_CPAS_MAX_AXI_PORTS];
@@ -303,9 +310,11 @@ struct cam_cpas {
 	uint64_t applied_camnoc_axi_rate;
 	atomic64_t  monitor_head;
 	struct cam_cpas_monitor monitor_entries[CAM_CPAS_MONITOR_MAX_ENTRIES];
+	void *camnoc_info;
 	bool full_state_dump;
 	bool smart_qos_dump;
-	void *camnoc_info;
+	bool slave_err_irq_en;
+	bool smmu_fault_handled;
 };
 
 int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops);

+ 109 - 102
drivers/cam_cpas/cpas_top/cam_cpastop_hw.c

@@ -45,7 +45,7 @@ struct cam_cpas_camnoc_qchannel *qchannel_info;
 
 
 #define CAMNOC_SLAVE_MAX_ERR_CODE 7
-static const char * const camnoc_salve_err_code[] = {
+static const char * const camnoc_slave_err_code[] = {
 	"Target Error",              /* err code 0 */
 	"Address decode error",      /* err code 1 */
 	"Unsupported request",       /* err code 2 */
@@ -417,94 +417,17 @@ static int cam_cpastop_handle_errlogger(struct cam_cpas *cpas_core,
 		return -EINVAL;
 	}
 
-	slave_err->mainctrl.value = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
-		camnoc_info->err_logger->mainctrl);
-
-	slave_err->errvld.value = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
-		camnoc_info->err_logger->errvld);
-
 	slave_err->errlog0_low.value = cam_io_r_mb(
 		soc_info->reg_map[camnoc_index].mem_base +
 		camnoc_info->err_logger->errlog0_low);
 
-	slave_err->errlog0_high.value = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
-		camnoc_info->err_logger->errlog0_high);
-
-	slave_err->errlog1_low.value = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
-		camnoc_info->err_logger->errlog1_low);
-
-	slave_err->errlog1_high.value = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
-		camnoc_info->err_logger->errlog1_high);
-
-	slave_err->errlog2_low.value = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
-		camnoc_info->err_logger->errlog2_low);
-
-	slave_err->errlog2_high.value = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
-		camnoc_info->err_logger->errlog2_high);
-
-	slave_err->errlog3_low.value = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
-		camnoc_info->err_logger->errlog3_low);
-
-	slave_err->errlog3_high.value = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
-		camnoc_info->err_logger->errlog3_high);
-
-	CAM_ERR_RATE_LIMIT(CAM_CPAS,
-		"Possible memory configuration issue, fault at SMMU raised as CAMNOC SLAVE_IRQ");
-
-	CAM_ERR_RATE_LIMIT(CAM_CPAS,
-		"mainctrl[0x%x 0x%x] errvld[0x%x 0x%x] stall_en=%d, fault_en=%d, err_vld=%d",
-		camnoc_info->err_logger->mainctrl,
-		slave_err->mainctrl.value,
-		camnoc_info->err_logger->errvld,
-		slave_err->errvld.value,
-		slave_err->mainctrl.stall_en,
-		slave_err->mainctrl.fault_en,
-		slave_err->errvld.err_vld);
-
 	err_code_index = slave_err->errlog0_low.err_code;
 	if (err_code_index > CAMNOC_SLAVE_MAX_ERR_CODE)
 		err_code_index = CAMNOC_SLAVE_MAX_ERR_CODE;
 
 	CAM_ERR_RATE_LIMIT(CAM_CPAS,
-		"errlog0 low[0x%x 0x%x] high[0x%x 0x%x] loginfo_vld=%d, word_error=%d, non_secure=%d, device=%d, opc=%d, err_code=%d(%s) sizef=%d, addr_space=%d, len1=%d",
-		camnoc_info->err_logger->errlog0_low,
-		slave_err->errlog0_low.value,
-		camnoc_info->err_logger->errlog0_high,
-		slave_err->errlog0_high.value,
-		slave_err->errlog0_low.loginfo_vld,
-		slave_err->errlog0_low.word_error,
-		slave_err->errlog0_low.non_secure,
-		slave_err->errlog0_low.device,
-		slave_err->errlog0_low.opc,
-		slave_err->errlog0_low.err_code,
-		camnoc_salve_err_code[err_code_index],
-		slave_err->errlog0_low.sizef,
-		slave_err->errlog0_low.addr_space,
-		slave_err->errlog0_high.len1);
-
-	CAM_ERR_RATE_LIMIT(CAM_CPAS,
-		"errlog1_low[0x%x 0x%x]  errlog1_high[0x%x 0x%x] errlog2_low[0x%x 0x%x]  errlog2_high[0x%x 0x%x] errlog3_low[0x%x 0x%x]  errlog3_high[0x%x 0x%x]",
-		camnoc_info->err_logger->errlog1_low,
-		slave_err->errlog1_low.value,
-		camnoc_info->err_logger->errlog1_high,
-		slave_err->errlog1_high.value,
-		camnoc_info->err_logger->errlog2_low,
-		slave_err->errlog2_low.value,
-		camnoc_info->err_logger->errlog2_high,
-		slave_err->errlog2_high.value,
-		camnoc_info->err_logger->errlog3_low,
-		slave_err->errlog3_low.value,
-		camnoc_info->err_logger->errlog3_high,
-		slave_err->errlog3_high.value);
+		"Possible memory configuration issue, fault at SMMU raised as CAMNOC SLAVE_IRQ err_code=%d(%s)",
+		slave_err->errlog0_low.err_code, camnoc_slave_err_code[err_code_index]);
 
 	return 0;
 }
@@ -604,10 +527,55 @@ static void cam_cpastop_check_test_irq(struct cam_hw_info *cpas_hw, uint32_t irq
 }
 #endif
 
-static int cam_cpastop_reset_irq(struct cam_hw_info *cpas_hw)
+static void cam_cpastop_enable_camnoc_irqs(
+	struct cam_hw_info *cpas_hw)
 {
 	int i;
+	struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
+
+	cpas_core->smmu_fault_handled = false;
+
+	/* clear and enable all errors */
+	for (i = 0; i < camnoc_info->irq_err_size; i++) {
+		if (camnoc_info->irq_err[i].enable) {
+			cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC,
+				&camnoc_info->irq_err[i].err_clear);
+			cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC,
+				&camnoc_info->irq_err[i].err_enable);
+		}
+	}
+
+	/* On poweron reset enable all error irqs applicable for the target */
+	cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC,
+		&camnoc_info->irq_sbm->sbm_enable);
+}
+
+static void cam_cpastop_handle_camnoc_irqs(
+	uint32_t irq_status, struct cam_hw_info *cpas_hw)
+{
+	int i;
+	uint32_t updated_sbm_mask = 0;
+	struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
 
+	for (i = 0; i < camnoc_info->irq_err_size; i++) {
+		if ((camnoc_info->irq_err[i].enable) &&
+			(camnoc_info->irq_err[i].sbm_port & irq_status)) {
+			/* Clear the error status */
+			cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC,
+				&camnoc_info->irq_err[i].err_clear);
+			updated_sbm_mask |= camnoc_info->irq_err[i].sbm_port;
+		}
+	}
+
+	/* Disable all serviced irqs */
+	cam_io_w(((~updated_sbm_mask) & (camnoc_info->irq_sbm->sbm_enable.value)),
+		soc_info->reg_map[CAM_CPAS_REG_CAMNOC].mem_base +
+		camnoc_info->irq_sbm->sbm_enable.offset);
+}
+
+static int cam_cpastop_reset_irq(uint32_t irq_status,
+	struct cam_hw_info *cpas_hw)
+{
 #if (defined(CONFIG_CAM_TEST_IRQ_LINE) && defined(CONFIG_CAM_TEST_IRQ_LINE_AT_PROBE))
 	static int counter;
 	bool wait_for_irq = false;
@@ -630,19 +598,12 @@ static int cam_cpastop_reset_irq(struct cam_hw_info *cpas_hw)
 
 	cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC,
 		&camnoc_info->irq_sbm->sbm_clear);
-	for (i = 0; i < camnoc_info->irq_err_size; i++) {
-		if (camnoc_info->irq_err[i].enable)
-			cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC,
-				&camnoc_info->irq_err[i].err_clear);
-	}
 
-	cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC,
-		&camnoc_info->irq_sbm->sbm_enable);
-	for (i = 0; i < camnoc_info->irq_err_size; i++) {
-		if (camnoc_info->irq_err[i].enable)
-			cam_cpas_util_reg_update(cpas_hw, CAM_CPAS_REG_CAMNOC,
-				&camnoc_info->irq_err[i].err_enable);
-	}
+	if (irq_status)
+		cam_cpastop_handle_camnoc_irqs(irq_status, cpas_hw);
+	else
+		/* poweron reset */
+		cam_cpastop_enable_camnoc_irqs(cpas_hw);
 
 #if (defined(CONFIG_CAM_TEST_IRQ_LINE) && defined(CONFIG_CAM_TEST_IRQ_LINE_AT_PROBE))
 	if (wait_for_irq) {
@@ -656,7 +617,7 @@ static int cam_cpastop_reset_irq(struct cam_hw_info *cpas_hw)
 }
 
 static void cam_cpastop_notify_clients(struct cam_cpas *cpas_core,
-	struct cam_cpas_irq_data *irq_data)
+	struct cam_cpas_irq_data *irq_data, bool force_notify)
 {
 	int i;
 	struct cam_cpas_client *cpas_client;
@@ -679,7 +640,7 @@ static void cam_cpastop_notify_clients(struct cam_cpas *cpas_core,
 					cpas_client->data.client_handle,
 					cpas_client->data.userdata,
 					irq_data);
-				if (error_handled)
+				if (error_handled && !force_notify)
 					break;
 			}
 		}
@@ -758,7 +719,7 @@ static void cam_cpastop_work(struct work_struct *work)
 				break;
 			}
 
-			cam_cpastop_notify_clients(cpas_core, &irq_data);
+			cam_cpastop_notify_clients(cpas_core, &irq_data, false);
 
 			payload->irq_status &=
 				~camnoc_info->irq_err[i].sbm_port;
@@ -782,6 +743,7 @@ static irqreturn_t cam_cpastop_handle_irq(int irq_num, void *data)
 	struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
 	int camnoc_index = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC];
 	struct cam_cpas_work_payload *payload;
+	struct cam_cpas_irq_data irq_data;
 
 	if (!atomic_inc_not_zero(&cpas_core->irq_count)) {
 		CAM_ERR(CAM_CPAS, "CPAS off");
@@ -792,8 +754,8 @@ static irqreturn_t cam_cpastop_handle_irq(int irq_num, void *data)
 	if (!payload)
 		goto done;
 
-	payload->irq_status = cam_io_r_mb(
-		soc_info->reg_map[camnoc_index].mem_base +
+	/* Read irq status */
+	payload->irq_status = cam_io_r_mb(soc_info->reg_map[camnoc_index].mem_base +
 		camnoc_info->irq_sbm->sbm_status.offset);
 
 	CAM_DBG(CAM_CPAS, "IRQ callback, irq_status=0x%x", payload->irq_status);
@@ -802,13 +764,46 @@ static irqreturn_t cam_cpastop_handle_irq(int irq_num, void *data)
 	cam_cpastop_check_test_irq(cpas_hw, payload->irq_status);
 #endif
 
+	/* Clear irq */
+	cam_cpastop_reset_irq(payload->irq_status, cpas_hw);
+
+	/* Check for slave error irq */
+	if ((cpas_core->slave_err_irq_en) && (payload->irq_status  &
+		camnoc_info->irq_err[cpas_core->slave_err_irq_idx].sbm_port)) {
+		struct cam_camnoc_irq_slave_err_data *slave_err = &irq_data.u.slave_err;
+
+		irq_data.irq_type = (enum cam_camnoc_irq_type)
+			camnoc_info->irq_err[cpas_core->slave_err_irq_idx].irq_type;
+		slave_err->errlog0_low.value = cam_io_r_mb(
+			soc_info->reg_map[camnoc_index].mem_base +
+			camnoc_info->err_logger->errlog0_low);
+
+		/* Validate address decode error */
+		if (slave_err->errlog0_low.err_code == CAM_CAMNOC_ADDRESS_DECODE_ERROR) {
+			/* Notify clients about potential page fault */
+			if (!cpas_core->smmu_fault_handled) {
+				cam_cpastop_notify_clients(cpas_core, &irq_data, true);
+				CAM_ERR_RATE_LIMIT(CAM_CPAS,
+					"Fault at SMMU raised as CAMNOC SLAVE IRQ, address decode error");
+			}
+
+			cpas_core->smmu_fault_handled = true;
+			/* Skip bh if no other irq is set */
+			payload->irq_status &=
+				~camnoc_info->irq_err[cpas_core->slave_err_irq_idx].sbm_port;
+			if (!payload->irq_status) {
+				kfree(payload);
+				goto done;
+			}
+		}
+	}
+
 	payload->hw = cpas_hw;
 	INIT_WORK((struct work_struct *)&payload->work, cam_cpastop_work);
 
-	cam_cpastop_reset_irq(cpas_hw);
-
 	payload->workq_scheduled_ts = ktime_get();
 	queue_work(cpas_core->work_queue, &payload->work);
+
 done:
 	atomic_dec(&cpas_core->irq_count);
 	wake_up(&cpas_core->irq_count_wq);
@@ -860,7 +855,7 @@ static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw)
 		camnoc_info->errata_wa_list;
 	struct cam_cpas_hw_errata_wa *errata_wa;
 
-	cam_cpastop_reset_irq(cpas_hw);
+	cam_cpastop_reset_irq(0x0, cpas_hw);
 	for (i = 0; i < camnoc_info->specific_size; i++) {
 		if (camnoc_info->specific[i].enable) {
 			CAM_DBG(CAM_CPAS, "Updating QoS settings for %d %s",
@@ -1026,7 +1021,7 @@ static int cam_cpastop_qchannel_handshake(struct cam_hw_info *cpas_hw,
 static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw,
 	struct cam_cpas_hw_caps *hw_caps)
 {
-	int rc = 0;
+	int rc = 0, i;
 	struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
 	struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
 	qchannel_info = NULL;
@@ -1127,6 +1122,18 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw,
 	}
 
 	cpas_core->camnoc_info = camnoc_info;
+
+	/* Check if slave error irq is enabled */
+	for (i = 0; i < camnoc_info->irq_err_size; i++) {
+		if (camnoc_info->irq_err[i].irq_type == CAM_CAMNOC_HW_IRQ_SLAVE_ERROR) {
+			if (camnoc_info->irq_err[i].enable) {
+				cpas_core->slave_err_irq_en = true;
+				cpas_core->slave_err_irq_idx = i;
+				break;
+			}
+		}
+	}
+
 	return 0;
 }
 

+ 3 - 2
drivers/cam_cpas/cpas_top/cpastop_v780_100.h

@@ -12,7 +12,8 @@ static struct cam_camnoc_irq_sbm cam_cpas_v780_100_irq_sbm = {
 		.access_type = CAM_REG_TYPE_READ_WRITE,
 		.enable = true,
 		.offset = 0x240,  /* CAM_NOC_SBM_FAULTINEN0_LOW */
-		.value = 0x2 |    /* SBM_FAULTINEN0_LOW_PORT1_MASK */
+		.value = 0x01 | /* SBM_FAULTINEN0_LOW_PORT0_MASK */
+			0x02 |    /* SBM_FAULTINEN0_LOW_PORT1_MASK */
 			0x04 |    /* SBM_FAULTINEN0_LOW_PORT2_MASK */
 			0x08 |    /* SBM_FAULTINEN0_LOW_PORT3_MASK */
 			0x10 |    /* SBM_FAULTINEN0_LOW_PORT4_MASK */
@@ -35,7 +36,7 @@ static struct cam_camnoc_irq_err
 	cam_cpas_v780_100_irq_err[] = {
 	{
 		.irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR,
-		.enable = false,
+		.enable = true,
 		.sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */
 		.err_enable = {
 			.access_type = CAM_REG_TYPE_READ_WRITE,

+ 3 - 2
drivers/cam_cpas/cpas_top/cpastop_v880_100.h

@@ -12,7 +12,8 @@ static struct cam_camnoc_irq_sbm cam_cpas_v880_100_irq_sbm = {
 		.access_type = CAM_REG_TYPE_READ_WRITE,
 		.enable = true,
 		.offset = 0x240,  /* CAM_NOC_SBM_FAULTINEN0_LOW */
-		.value = 0x02 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */
+		.value = 0x01 |/* SBM_FAULTINEN0_LOW_PORT0_MASK */
+			0x02 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */
 			0x04 |    /* SBM_FAULTINEN0_LOW_PORT2_MASK */
 			0x08 |    /* SBM_FAULTINEN0_LOW_PORT3_MASK */
 			0x10 |    /* SBM_FAULTINEN0_LOW_PORT4_MASK */
@@ -35,7 +36,7 @@ static struct cam_camnoc_irq_err
 	cam_cpas_v880_100_irq_err[] = {
 	{
 		.irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR,
-		.enable = false,
+		.enable = true,
 		.sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */
 		.err_enable = {
 			.access_type = CAM_REG_TYPE_READ_WRITE,

+ 28 - 9
drivers/cam_cpas/include/cam_cpas_api.h

@@ -159,6 +159,21 @@ enum cam_cpas_hw_version {
 	CAM_CPAS_TITAN_MAX
 };
 
+/**
+ * enum cam_camnoc_slave_error_codes - Enum for camnoc slave error codes
+ *
+ */
+enum cam_camnoc_slave_error_codes {
+	CAM_CAMNOC_TARGET_ERROR,
+	CAM_CAMNOC_ADDRESS_DECODE_ERROR,
+	CAM_CAMNOC_UNSUPPORTED_REQUEST_ERROR,
+	CAM_CAMNOC_DISCONNECTED_TARGET_ERROR,
+	CAM_CAMNOC_SECURITY_VIOLATION,
+	CAM_CAMNOC_HIDDEN_SECURITY_VIOLATION,
+	CAM_CAMNOC_TIME_OUT,
+	CAM_CAMNOC_UNUSED,
+};
+
 /**
  * enum cam_camnoc_irq_type - Enum for camnoc irq types
  *
@@ -416,6 +431,17 @@ struct cam_cpas_irq_data {
 	} u;
 };
 
+/*
+ * CPAS client callback
+ *
+ * @client_handle : CPAS client handle
+ * @userdata      : User data given at the time of register
+ * @irq_data      : Event data
+ */
+typedef bool (*cam_cpas_client_cb_func)(
+	uint32_t client_handle, void *userdata,
+	struct cam_cpas_irq_data *irq_data);
+
 /**
  * struct cam_cpas_register_params : Register params for cpas client
  *
@@ -430,11 +456,7 @@ struct cam_cpas_irq_data {
  *                      an argument while callback.
  * @cam_cpas_callback : Input callback pointer for triggering the
  *                      callbacks from CPAS driver.
- *                      @client_handle : CPAS client handle
- *                      @userdata    : User data given at the time of register
- *                      @event_type  : event type
- *                      @event_data  : event data
- * @client_handle       : Output Unique handle generated for this register
+ * @client_handle     : Output Unique handle generated for this register
  *
  */
 struct cam_cpas_register_params {
@@ -442,10 +464,7 @@ struct cam_cpas_register_params {
 	uint32_t        cell_index;
 	struct device  *dev;
 	void           *userdata;
-	bool          (*cam_cpas_client_cb)(
-			uint32_t                  client_handle,
-			void                     *userdata,
-			struct cam_cpas_irq_data *irq_data);
+	cam_cpas_client_cb_func cam_cpas_client_cb;
 	uint32_t        client_handle;
 };
 

+ 0 - 1
drivers/cam_icp/icp_hw/icp_proc/icp_v2_hw/cam_icp_v2_core.c

@@ -78,7 +78,6 @@ static bool cam_icp_v2_cpas_cb(uint32_t handle, void *user_data,
 			irq_data->u.enc_err.encerr_status.value);
 		ret = true;
 	default:
-		CAM_ERR(CAM_ICP, "unhandled irq_type=%d", irq_data->irq_type);
 		break;
 	}