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

Commit 97603680 authored by Akash Asthana's avatar Akash Asthana
Browse files

serial: Propagate missing UART fix 4.19 to 5.4



    msm_geni_serial: Use the common driver API for dma_alloc
    msm: msm-geni-se: Make DFS clock table specific to SE of QUP
    serial: msm_geni_serial: Don't depend on clock freq table to set baud
	rate
    msm-geni-serial: Correct the interrupt polling logic in uart
    serial: msm_geni_serial: Improve IPC logging in UART driver
    serial: msm_geni_serial: drop port->lock before tty_flip_buffer_push()
	call
    serial: msm_geni_serial: No need to stop_tx/rx on UART shutdown
    serial: msm_geni_serial: Do not check_transfers_inflight() post
	port_close
    serial: msm_geni_serial: Enable IRQ from port startup
    serial: msm_geni_serial: Fix geni_wait_for_cmd_done timeouts
    serial: msm_geni_serial: Do not drop port->lock in polling mode

Also, fix stackoverflow issue seen after propagating above changes.

Console TX is getting stuck in recursive call and leading to
stackoverflow issue.

Steps that leads to bad recursion call:
1) msm_geni_serial_handle_tx calls for stop_tx if all the data are sent and
acknowledged.
2) stop_tx issue cancel command if the main sequencer is still
active.
3) As part of cancel command execution msm_geni_serial_handle_tx is called
again that takes us to step 1 and goes in a loop.

To fix above scenario remove the stop_tx call from geni_serial_handle_tx
because if the data is transmited and acknowledged main sequencer should
automatically go to inactive state.

Ideally we should never enter into this situation the first place because
after receiving CMD_DONE we expect that sequencer will go IDLE/inactive.
So, probably this can be a race btw updation of CMD_DONE and GENI_STATUS
register because after adding some more IPC logs in the above code path we
are not hitting this issue. It might be adding required delay.

Change-Id: I85cfe87170ea347c4b8d98c858cc762da413624f
Signed-off-by: default avatarPrudhvi Yarlagadda <pyarlaga@codeaurora.org>
Signed-off-by: default avatarChandana Kishori Chiluveru <cchiluve@codeaurora.org>
Signed-off-by: default avatarMukesh Kumar Savaliya <msavaliy@codeaurora.org>
Signed-off-by: default avatarAkash Asthana <akashast@codeaurora.org>
parent ead4c53f
Loading
Loading
Loading
Loading
+12 −16
Original line number Diff line number Diff line
@@ -68,8 +68,6 @@ struct bus_vectors {
 * @bus_bw_set_noc:	Clock plan for DDR path.
 * @cur_bus_bw_idx:	Current index within the bus clock plan.
 * @cur_bus_bw_idx_noc:	Current index within the DDR path clock plan.
 * @num_clk_levels:	Number of valid clock levels in clk_perf_tbl.
 * @clk_perf_tbl:	Table of clock frequency input to Serial Engine clock.
 * @log_ctx:		Logging context to hold the debug information.
 * @vectors:		Structure to store Master End and Slave End IDs for
			QUPv3 clock and DDR path bus BW request.
@@ -101,8 +99,6 @@ struct geni_se_device {
	unsigned long *bus_bw_set_noc;
	int cur_bus_bw_idx;
	int cur_bus_bw_idx_noc;
	unsigned int num_clk_levels;
	unsigned long *clk_perf_tbl;
	void *log_ctx;
	struct bus_vectors *vectors;
	int num_paths;
@@ -1118,31 +1114,31 @@ int geni_se_clk_tbl_get(struct se_geni_rsc *rsc, unsigned long **tbl)
	mutex_lock(&geni_se_dev->geni_dev_lock);
	*tbl = NULL;

	if (geni_se_dev->clk_perf_tbl) {
		*tbl = geni_se_dev->clk_perf_tbl;
		ret = geni_se_dev->num_clk_levels;
	if (rsc->clk_perf_tbl) {
		*tbl = rsc->clk_perf_tbl;
		ret = rsc->num_clk_levels;
		goto exit_se_clk_tbl_get;
	}

	geni_se_dev->clk_perf_tbl = kzalloc(sizeof(*geni_se_dev->clk_perf_tbl) *
	rsc->clk_perf_tbl = kzalloc(sizeof(*rsc->clk_perf_tbl) *
						MAX_CLK_PERF_LEVEL, GFP_KERNEL);
	if (!geni_se_dev->clk_perf_tbl) {
	if (!rsc->clk_perf_tbl) {
		ret = -ENOMEM;
		goto exit_se_clk_tbl_get;
	}

	for (i = 0; i < MAX_CLK_PERF_LEVEL; i++) {
		geni_se_dev->clk_perf_tbl[i] = clk_round_rate(rsc->se_clk,
		rsc->clk_perf_tbl[i] = clk_round_rate(rsc->se_clk,
								prev_freq + 1);
		if (geni_se_dev->clk_perf_tbl[i] == prev_freq) {
			geni_se_dev->clk_perf_tbl[i] = 0;
		if (rsc->clk_perf_tbl[i] == prev_freq) {
			rsc->clk_perf_tbl[i] = 0;
			break;
		}
		prev_freq = geni_se_dev->clk_perf_tbl[i];
		prev_freq = rsc->clk_perf_tbl[i];
	}
	geni_se_dev->num_clk_levels = i;
	*tbl = geni_se_dev->clk_perf_tbl;
	ret = geni_se_dev->num_clk_levels;
	rsc->num_clk_levels = i;
	*tbl = rsc->clk_perf_tbl;
	ret = rsc->num_clk_levels;
exit_se_clk_tbl_get:
	mutex_unlock(&geni_se_dev->geni_dev_lock);
	return ret;
+651 −313

File changed.

Preview size limit exceeded, changes collapsed.

+12 −1
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ enum se_protocol_types {
 * @geni_pinctrl:	Handle to the pinctrl configuration.
 * @geni_gpio_active:	Handle to the default/active pinctrl state.
 * @geni_gpi_sleep:	Handle to the sleep pinctrl state.
 * @num_clk_levels:	Number of valid clock levels in clk_perf_tbl.
 * @clk_perf_tbl:	Table of clock frequency input to Serial Engine clock.
 */
struct se_geni_rsc {
	struct device *ctrl_dev;
@@ -67,6 +69,8 @@ struct se_geni_rsc {
	struct pinctrl_state *geni_gpio_active;
	struct pinctrl_state *geni_gpio_sleep;
	int	clk_freq_out;
	unsigned int num_clk_levels;
	unsigned long *clk_perf_tbl;
};

#define PINCTRL_DEFAULT	"default"
@@ -324,6 +328,7 @@ struct se_geni_rsc {
#define TX_EOT			(BIT(1))
#define TX_SBE			(BIT(2))
#define TX_RESET_DONE		(BIT(3))
#define TX_GENI_CANCEL_IRQ	(BIT(14))

/* SE_DMA_RX_IRQ_STAT Register fields */
#define RX_DMA_DONE		(BIT(0))
@@ -332,9 +337,15 @@ struct se_geni_rsc {
#define RX_RESET_DONE		(BIT(3))
#define RX_FLUSH_DONE		(BIT(4))
#define RX_GENI_GP_IRQ		(GENMASK(10, 5))
#define RX_GENI_CANCEL_IRQ	(BIT(11))
#define RX_GENI_CANCEL_IRQ	(BIT(14))
#define RX_GENI_GP_IRQ_EXT	(GENMASK(13, 12))

/* DMA DEBUG Register fields */
#define DMA_TX_ACTIVE		(BIT(0))
#define DMA_RX_ACTIVE		(BIT(1))
#define DMA_TX_STATE		(GENMASK(7, 4))
#define DMA_RX_STATE		(GENMASK(11, 8))

#define DEFAULT_BUS_WIDTH	(4)

/* GSI TRE fields */