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

Commit 8f8bcd4e authored by Dilip Kota's avatar Dilip Kota Committed by Matt Wagantall
Browse files

msm_serial_hs: IPC logs per device



Route the IPC logs of each UART port to
seperate file. This will make debugging easier
when two or more UART ports are enabled.

Change the debug level at runtime:
==================================
cd sys/devices/ctrl_num(eg:1234).uart
echo <log_level> > debug_mask

Logs of individual UART port:
=============================
sys/kernel/debug/ipc_logging/ctrl_num.uart/log_cont

Change-Id: I9292ff55e62d35045a5cb3304b1d75734eaa5389
Signed-off-by: default avatarDilip Kota <dkota@codeaurora.org>
parent 66d3a89b
Loading
Loading
Loading
Loading
+117 −59
Original line number Diff line number Diff line
@@ -70,9 +70,9 @@
#define UART_SPS_CONS_PERIPHERAL 0
#define UART_SPS_PROD_PERIPHERAL 1

static void *ipc_msm_hs_log_ctxt;
#define IPC_MSM_HS_LOG_PAGES 5
#define UART_DMA_DESC_NR 8
#define BUF_DUMP_SIZE 20

/* If the debug_mask gets set to FATAL_LEV,
 * a fatal error has happened and further IPC logging
@@ -86,30 +86,26 @@ enum {
	DBG_LEV = 4U,
};

/* Default IPC log level INFO */
static int hs_serial_debug_mask = INFO_LEV;
module_param_named(debug_mask, hs_serial_debug_mask,
		   int, S_IRUGO | S_IWUSR | S_IWGRP);

#define MSM_HS_DBG(x...) do { \
	if (hs_serial_debug_mask >= DBG_LEV) { \
		if (ipc_msm_hs_log_ctxt) \
			ipc_log_string(ipc_msm_hs_log_ctxt, x); \
	if (msm_uport->ipc_debug_mask >= DBG_LEV) { \
		if (msm_uport->ipc_msm_hs_log_ctxt) \
			ipc_log_string(msm_uport->ipc_msm_hs_log_ctxt, x); \
	} \
} while (0)

#define MSM_HS_INFO(x...) do { \
	if (hs_serial_debug_mask >= INFO_LEV) {\
		if (ipc_msm_hs_log_ctxt) \
			ipc_log_string(ipc_msm_hs_log_ctxt, x); \
	if (msm_uport->ipc_debug_mask >= INFO_LEV) {\
		if (msm_uport->ipc_msm_hs_log_ctxt) \
			ipc_log_string(msm_uport->ipc_msm_hs_log_ctxt, x); \
	} \
} while (0)

/* warnings and errors show up on console always */
#define MSM_HS_WARN(x...) do { \
	pr_warn(x); \
	if (ipc_msm_hs_log_ctxt && hs_serial_debug_mask >= WARN_LEV) \
		ipc_log_string(ipc_msm_hs_log_ctxt, x); \
	if (msm_uport->ipc_msm_hs_log_ctxt && \
			msm_uport->ipc_debug_mask >= WARN_LEV) \
		ipc_log_string(msm_uport->ipc_msm_hs_log_ctxt, x); \
} while (0)

/* ERROR condition in the driver sets the hs_serial_debug_mask
@@ -118,9 +114,10 @@ module_param_named(debug_mask, hs_serial_debug_mask,
 */
#define MSM_HS_ERR(x...) do { \
	pr_err(x); \
	if (ipc_msm_hs_log_ctxt && hs_serial_debug_mask >= ERR_LEV) { \
		ipc_log_string(ipc_msm_hs_log_ctxt, x); \
		hs_serial_debug_mask = FATAL_LEV; \
	if (msm_uport->ipc_msm_hs_log_ctxt && \
			msm_uport->ipc_debug_mask >= ERR_LEV) { \
		ipc_log_string(msm_uport->ipc_msm_hs_log_ctxt, x); \
		msm_uport->ipc_debug_mask = FATAL_LEV; \
	} \
} while (0)

@@ -250,6 +247,8 @@ struct msm_hs_port {
	atomic_t ioctl_count;
	bool obs; /* out of band sleep flag */
	atomic_t client_req_state;
	void *ipc_msm_hs_log_ctxt;
	int ipc_debug_mask;
};

static struct of_device_id msm_hs_match_table[] = {
@@ -422,7 +421,7 @@ static struct msm_hs_port *get_matching_hs_port(struct platform_device *pdev)

	if ((!msm_uport) || (msm_uport->uport.line != pdev->id
	   && msm_uport->uport.line != pdata->userid)) {
		MSM_HS_ERR("uport line number mismatch!");
		pr_err("uport line number mismatch!");
		WARN_ON(1);
		return NULL;
	}
@@ -462,10 +461,12 @@ static ssize_t set_clock(struct device *dev, struct device_attribute *attr,
		state = buf[0] - '0';
		switch (state) {
		case 0:
			MSM_HS_DBG("%s: Request clock OFF\n", __func__);
			msm_hs_request_clock_off(&msm_uport->uport);
			ret = count;
			break;
		case 1:
			MSM_HS_DBG("%s: Request clock ON\n", __func__);
			msm_hs_request_clock_on(&msm_uport->uport);
			ret = count;
			break;
@@ -478,6 +479,46 @@ static ssize_t set_clock(struct device *dev, struct device_attribute *attr,

static DEVICE_ATTR(clock, S_IWUSR | S_IRUGO, show_clock, set_clock);

static ssize_t show_debug_mask(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	ssize_t ret = 0;
	struct platform_device *pdev = container_of(dev, struct
						    platform_device, dev);
	struct msm_hs_port *msm_uport = get_matching_hs_port(pdev);

	/* This check should not fail */
	if (msm_uport)
		ret = snprintf(buf, sizeof(int), "%u\n",
					msm_uport->ipc_debug_mask);
	return ret;
}

static ssize_t set_debug_mask(struct device *dev,
			struct device_attribute *attr,
			const char *buf, size_t count)
{
	struct platform_device *pdev = container_of(dev, struct
						    platform_device, dev);
	struct msm_hs_port *msm_uport = get_matching_hs_port(pdev);

	/* This check should not fail */
	if (msm_uport) {
		msm_uport->ipc_debug_mask = buf[0] - '0';
		if (msm_uport->ipc_debug_mask < FATAL_LEV ||
				msm_uport->ipc_debug_mask > DBG_LEV) {
			/* set to default level */
			msm_uport->ipc_debug_mask = INFO_LEV;
			MSM_HS_ERR("Range is 0 to 4;Set to default level 3\n");
			return -EINVAL;
		}
	}
	return count;
}

static DEVICE_ATTR(debug_mask, S_IWUSR | S_IRUGO, show_debug_mask,
							set_debug_mask);

static inline bool is_use_low_power_wakeup(struct msm_hs_port *msm_uport)
{
	return msm_uport->wakeup.irq > 0;
@@ -528,12 +569,13 @@ static int sps_rx_disconnect(struct sps_pipe *sps_pipe_handler)
	return sps_disconnect(sps_pipe_handler);
}

static void hex_dump_ipc(char *prefix, char *string, int size)
static void hex_dump_ipc(struct msm_hs_port *msm_uport,
			char *prefix, char *string, int size)
{
	unsigned char linebuf[512];
	unsigned char firstbuf[40], lastbuf[40];

	if ((hs_serial_debug_mask != DBG_LEV) && (size > 20)) {
	if ((msm_uport->ipc_debug_mask != DBG_LEV) && (size > BUF_DUMP_SIZE)) {
		hex_dump_to_buffer(string, 10, 16, 1,
				firstbuf, sizeof(firstbuf), 1);
		hex_dump_to_buffer(string + (size - 10), 10, 16, 1,
@@ -661,7 +703,7 @@ static int msm_hs_remove(struct platform_device *pdev)
	struct device *dev;

	if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
		MSM_HS_ERR("Invalid plaform device ID = %d\n", pdev->id);
		pr_err("Invalid plaform device ID = %d\n", pdev->id);
		return -EINVAL;
	}

@@ -671,6 +713,7 @@ static int msm_hs_remove(struct platform_device *pdev)

	dev = msm_uport->uport.dev;
	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_clock.attr);
	sysfs_remove_file(&pdev->dev.kobj, &dev_attr_debug_mask.attr);
	debugfs_remove(msm_uport->loopback_dir);

	dma_free_coherent(msm_uport->uport.dev,
@@ -1360,7 +1403,9 @@ static void msm_hs_submit_tx_locked(struct uart_port *uport)
	if (tx_count > left)
		tx_count = left;
	MSM_HS_INFO("%s(): [UART_TX]<%d>\n", __func__, tx_count);
	hex_dump_ipc("HSUART write: ", &tx_buf->buf[tx_buf->tail], tx_count);
	hex_dump_ipc(msm_uport, "HSUART write: ",
		&tx_buf->buf[tx_buf->tail], tx_count);

	src_addr = tx->dma_base + tx_buf->tail;
	/* Mask the src_addr to align on a cache
	 * and add those bytes to tx_count */
@@ -1676,7 +1721,7 @@ static void msm_serial_hs_rx_work(struct kthread_work *work)
		rx_count = msm_uport->rx.iovec[msm_uport->rx.rx_inx].size;

		MSM_HS_INFO("%s():[UART_RX]<%d>\n", __func__, rx_count);
		hex_dump_ipc("HSUART Read: ",
		hex_dump_ipc(msm_uport, "HSUART Read: ",
				(msm_uport->rx.buffer +
				(msm_uport->rx.rx_inx * UARTDM_RX_BUF_SIZE)),
				rx_count);
@@ -2303,6 +2348,7 @@ static void msm_hs_unconfig_uart_gpios(struct uart_port *uport)
	struct platform_device *pdev = to_platform_device(uport->dev);
	const struct msm_serial_hs_platform_data *pdata =
					pdev->dev.platform_data;
	struct msm_hs_port *msm_uport = UARTDM_TO_MSM(uport);

	if (pdata) {
		if (gpio_is_valid(pdata->uart_tx_gpio))
@@ -2670,7 +2716,7 @@ struct msm_serial_hs_platform_data

	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	if (!pdata) {
		MSM_HS_ERR("unable to allocate memory for platform data\n");
		pr_err("unable to allocate memory for platform data\n");
		return ERR_PTR(-ENOMEM);
	}

@@ -2679,25 +2725,25 @@ struct msm_serial_hs_platform_data
	pdata->uart_tx_gpio = of_get_named_gpio(node,
					"qcom,tx-gpio", 0);
	if (pdata->uart_tx_gpio < 0)
		MSM_HS_DBG("uart_tx_gpio is not available\n");
		pr_err("uart_tx_gpio is not available\n");

	/* UART RX GPIO */
	pdata->uart_rx_gpio = of_get_named_gpio(node,
					"qcom,rx-gpio", 0);
	if (pdata->uart_rx_gpio < 0)
		MSM_HS_DBG("uart_rx_gpio is not available\n");
		pr_err("uart_rx_gpio is not available\n");

	/* UART CTS GPIO */
	pdata->uart_cts_gpio = of_get_named_gpio(node,
					"qcom,cts-gpio", 0);
	if (pdata->uart_cts_gpio < 0)
		MSM_HS_DBG("uart_cts_gpio is not available\n");
		pr_err("uart_cts_gpio is not available\n");

	/* UART RFR GPIO */
	pdata->uart_rfr_gpio = of_get_named_gpio(node,
					"qcom,rfr-gpio", 0);
	if (pdata->uart_rfr_gpio < 0)
		MSM_HS_DBG("uart_rfr_gpio is not available\n");
		pr_err("uart_rfr_gpio is not available\n");

	pdata->no_suspend_delay = of_property_read_bool(node,
				"qcom,no-suspend-delay");
@@ -2705,7 +2751,7 @@ struct msm_serial_hs_platform_data
	pdata->obs = of_property_read_bool(node,
				"qcom,msm-obs");
	if (pdata->obs)
		MSM_HS_DBG("%s:Out of Band sleep flag is set\n", __func__);
		pr_err("%s:Out of Band sleep flag is set\n", __func__);

	pdata->inject_rx_on_wakeup = of_property_read_bool(node,
				"qcom,inject-rx-on-wakeup");
@@ -2714,7 +2760,7 @@ struct msm_serial_hs_platform_data
		ret = of_property_read_u32(node, "qcom,rx-char-to-inject",
						&rx_to_inject);
		if (ret < 0) {
			MSM_HS_ERR("Error: Rx_char_to_inject not specified.\n");
			pr_err("Error: Rx_char_to_inject not specified.\n");
			return ERR_PTR(ret);
		}
		pdata->rx_to_inject = (u8)rx_to_inject;
@@ -2723,30 +2769,30 @@ struct msm_serial_hs_platform_data
	ret = of_property_read_u32(node, "qcom,bam-tx-ep-pipe-index",
				&pdata->bam_tx_ep_pipe_index);
	if (ret < 0) {
		MSM_HS_ERR("Error: Getting UART BAM TX EP Pipe Index.\n");
		pr_err("Error: Getting UART BAM TX EP Pipe Index.\n");
		return ERR_PTR(ret);
	}

	if (!(pdata->bam_tx_ep_pipe_index >= BAM_PIPE_MIN &&
		pdata->bam_tx_ep_pipe_index <= BAM_PIPE_MAX)) {
		MSM_HS_ERR("Error: Invalid UART BAM TX EP Pipe Index.\n");
		pr_err("Error: Invalid UART BAM TX EP Pipe Index.\n");
		return ERR_PTR(-EINVAL);
	}

	ret = of_property_read_u32(node, "qcom,bam-rx-ep-pipe-index",
					&pdata->bam_rx_ep_pipe_index);
	if (ret < 0) {
		MSM_HS_ERR("Error: Getting UART BAM RX EP Pipe Index.\n");
		pr_err("Error: Getting UART BAM RX EP Pipe Index.\n");
		return ERR_PTR(ret);
	}

	if (!(pdata->bam_rx_ep_pipe_index >= BAM_PIPE_MIN &&
		pdata->bam_rx_ep_pipe_index <= BAM_PIPE_MAX)) {
		MSM_HS_ERR("Error: Invalid UART BAM RX EP Pipe Index.\n");
		pr_err("Error: Invalid UART BAM RX EP Pipe Index.\n");
		return ERR_PTR(-EINVAL);
	}

	MSM_HS_DBG("tx_ep_pipe_index:%d rx_ep_pipe_index:%d\n"
	pr_debug("tx_ep_pipe_index:%d rx_ep_pipe_index:%d\n"
		"tx_gpio:%d rx_gpio:%d rfr_gpio:%d cts_gpio:%d",
		pdata->bam_tx_ep_pipe_index, pdata->bam_rx_ep_pipe_index,
		pdata->uart_tx_gpio, pdata->uart_rx_gpio, pdata->uart_cts_gpio,
@@ -3008,7 +3054,7 @@ static void msm_hs_pm_suspend(struct device *dev)
	MSM_HS_DBG("%s(): return suspend\n", __func__);
	return;
err_suspend:
	MSM_HS_ERR("%s(): invalid uport", __func__);
	pr_err("%s(): invalid uport", __func__);
	return;
}

@@ -3040,7 +3086,7 @@ static int msm_hs_pm_resume(struct device *dev)
	MSM_HS_DBG("%s(): return resume\n", __func__);
	return 0;
err_resume:
	MSM_HS_ERR("%s(): invalid uport", __func__);
	pr_err("%s(): invalid uport", __func__);
	return 0;
}

@@ -3164,14 +3210,15 @@ static int msm_hs_probe(struct platform_device *pdev)
	}

	if (pdev->id < 0 || pdev->id >= UARTDM_NR) {
		MSM_HS_ERR("Invalid plaform device ID = %d\n", pdev->id);
		dev_err(&pdev->dev, "Invalid plaform device ID = %d\n",
								pdev->id);
		return -EINVAL;
	}

	msm_uport = devm_kzalloc(&pdev->dev, sizeof(struct msm_hs_port),
			GFP_KERNEL);
	if (!msm_uport) {
		MSM_HS_ERR("Memory allocation failed\n");
		dev_err(&pdev->dev, "Memory allocation failed\n");
		return -ENOMEM;
	}

@@ -3187,29 +3234,29 @@ static int msm_hs_probe(struct platform_device *pdev)
	core_resource = platform_get_resource_byname(pdev,
				IORESOURCE_MEM, "core_mem");
	if (!core_resource) {
		MSM_HS_ERR("Invalid core HSUART Resources.\n");
		dev_err(&pdev->dev, "Invalid core HSUART Resources.\n");
		return -ENXIO;
	}
	bam_resource = platform_get_resource_byname(pdev,
				IORESOURCE_MEM, "bam_mem");
	if (!bam_resource) {
		MSM_HS_ERR("Invalid BAM HSUART Resources.\n");
		dev_err(&pdev->dev, "Invalid BAM HSUART Resources.\n");
		return -ENXIO;
	}
	core_irqres = platform_get_irq_byname(pdev, "core_irq");
	if (core_irqres < 0) {
		MSM_HS_ERR("Invalid core irqres Resources.\n");
		dev_err(&pdev->dev, "Invalid core irqres Resources.\n");
		return -ENXIO;
	}
	bam_irqres = platform_get_irq_byname(pdev, "bam_irq");
	if (bam_irqres < 0) {
		MSM_HS_ERR("Invalid bam irqres Resources.\n");
		dev_err(&pdev->dev, "Invalid bam irqres Resources.\n");
		return -ENXIO;
	}
	wakeup_irqres = platform_get_irq_byname(pdev, "wakeup_irq");
	if (wakeup_irqres < 0) {
		wakeup_irqres = -1;
		MSM_HS_DBG("Wakeup irq not specified.\n");
		pr_info("Wakeup irq not specified.\n");
	}

	uport->mapbase = core_resource->start;
@@ -3217,17 +3264,32 @@ static int msm_hs_probe(struct platform_device *pdev)
	uport->membase = ioremap(uport->mapbase,
				resource_size(core_resource));
	if (unlikely(!uport->membase)) {
		MSM_HS_ERR("UART Resource ioremap Failed.\n");
		dev_err(&pdev->dev, "UART Resource ioremap Failed.\n");
		return -ENOMEM;
	}
	msm_uport->bam_mem = bam_resource->start;
	msm_uport->bam_base = ioremap(msm_uport->bam_mem,
				resource_size(bam_resource));
	if (unlikely(!msm_uport->bam_base)) {
		MSM_HS_ERR("UART BAM Resource ioremap Failed.\n");
		dev_err(&pdev->dev, "UART BAM Resource ioremap Failed.\n");
		iounmap(uport->membase);
		return -ENOMEM;
	}
	msm_uport->ipc_msm_hs_log_ctxt =
			ipc_log_context_create(IPC_MSM_HS_LOG_PAGES,
					dev_name(msm_uport->uport.dev), 0);
	pr_debug("%s: Device name is %s\n", __func__,
				dev_name(msm_uport->uport.dev));
	if (!msm_uport->ipc_msm_hs_log_ctxt) {
		dev_err(&pdev->dev, "%s: error creating logging context",
								__func__);
	} else {
		msm_uport->ipc_debug_mask = INFO_LEV;
		ret = sysfs_create_file(&pdev->dev.kobj,
				&dev_attr_debug_mask.attr);
		if (unlikely(ret))
			MSM_HS_WARN("%s: Failed to create dev. attr", __func__);
	}

	uport->irq = core_irqres;
	msm_uport->bam_irq = bam_irqres;
@@ -3375,29 +3437,24 @@ static int __init msm_serial_hs_init(void)
{
	int ret;

	ipc_msm_hs_log_ctxt = ipc_log_context_create(IPC_MSM_HS_LOG_PAGES,
							"msm_serial_hs", 0);
	if (!ipc_msm_hs_log_ctxt)
		MSM_HS_WARN("%s: error creating logging context", __func__);

	ret = uart_register_driver(&msm_hs_driver);
	if (unlikely(ret)) {
		MSM_HS_ERR("%s failed to load\n", __func__);
		pr_err("%s failed to load\n", __func__);
		return ret;
	}
	debug_base = debugfs_create_dir("msm_serial_hs", NULL);
	if (IS_ERR_OR_NULL(debug_base))
		pr_info("msm_serial_hs: Cannot create debugfs dir\n");
		pr_err("msm_serial_hs: Cannot create debugfs dir\n");

	ret = platform_driver_register(&msm_serial_hs_platform_driver);
	if (ret) {
		MSM_HS_ERR("%s failed to load\n", __func__);
		pr_err("%s failed to load\n", __func__);
		debugfs_remove_recursive(debug_base);
		uart_unregister_driver(&msm_hs_driver);
		return ret;
	}

	MSM_HS_INFO("msm_serial_hs module loaded\n");
	pr_info("msm_serial_hs module loaded\n");
	return ret;
}

@@ -3496,11 +3553,12 @@ static void msm_hs_shutdown(struct uart_port *uport)
	msm_uport->wakeup.freed = true;

	msm_hs_unconfig_uart_gpios(uport);
	MSM_HS_INFO("%s:UART port closed successfully\n", __func__);
}

static void __exit msm_serial_hs_exit(void)
{
	MSM_HS_INFO("msm_serial_hs module removed\n");
	pr_info("msm_serial_hs module removed\n");
	debugfs_remove_recursive(debug_base);
	platform_driver_unregister(&msm_serial_hs_platform_driver);
	uart_unregister_driver(&msm_hs_driver);