diff options
author | Adrian Salido <salidoa@google.com> | 2023-02-24 18:23:58 -0800 |
---|---|---|
committer | Ken Huang <kenbshuang@google.com> | 2023-03-01 14:43:26 +0800 |
commit | f49bb252bd7fca78a7d819c1f697e742e6be6966 (patch) | |
tree | f96a88200f2c0379df6242163d98784dbee83770 | |
parent | 175613b9ec11b15784346ac503df307c0b820ede (diff) | |
download | display-f49bb252bd7fca78a7d819c1f697e742e6be6966.tar.gz |
drm: samsung: dsim: cleanup dsim command packet prepare
Fix the following problems:
* Completion structs may not be reset properly leading to
improperly waiting on stale completions.
* Packet go commands are not being logged in event log
* Payload FIFO size check may include PH only packets
Bug: 259135990
Test: suspend/resume and check dynamic debug logs
Change-Id: I4d84c37ab8872a47baae02c7d9f3bc6240149475
Signed-off-by: Adrian Salido <salidoa@google.com>
-rw-r--r-- | samsung/exynos_drm_dsim.c | 116 |
1 files changed, 61 insertions, 55 deletions
diff --git a/samsung/exynos_drm_dsim.c b/samsung/exynos_drm_dsim.c index f26c4be..7ce6ce0 100644 --- a/samsung/exynos_drm_dsim.c +++ b/samsung/exynos_drm_dsim.c @@ -1952,53 +1952,60 @@ dsim_write_payload(struct dsim_device *dsim, const u8* buf, size_t len) } } -static void __dsim_cmd_write_locked(struct dsim_device *dsim, const struct mipi_dsi_msg *msg, - bool is_long) +static void __dsim_cmd_write_locked(struct dsim_device *dsim, const struct mipi_dsi_packet *packet) { - struct mipi_dsi_packet packet; - WARN_ON(!mutex_is_locked(&dsim->cmd_lock)); - mipi_dsi_create_packet(&packet, msg); + if (packet->payload_length > 0) + dsim_write_payload(dsim, packet->payload, packet->payload_length); + dsim_reg_wr_tx_header(dsim->id, packet->header[0], packet->header[1], packet->header[2], + false); - if (is_long) - dsim_write_payload(dsim, packet.payload, packet.payload_length); - dsim_reg_wr_tx_header(dsim->id, packet.header[0], packet.header[1], - packet.header[2], false); - - dsim_debug(dsim, "header(0x%x 0x%x 0x%x) size(%lu) ph fifo(%d)\n", - packet.header[0], packet.header[1], packet.header[2], - packet.size, dsim_reg_get_ph_cnt(dsim->id)); + dsim_debug(dsim, "header(0x%x 0x%x 0x%x) size(%lu) ph fifo(%d)\n", packet->header[0], + packet->header[1], packet->header[2], packet->size, + dsim_reg_get_ph_cnt(dsim->id)); } -static void dsim_cmd_packetgo_queue_locked(struct dsim_device *dsim, const struct mipi_dsi_msg *msg, - bool is_long) +static void dsim_cmd_packetgo_queue_locked(struct dsim_device *dsim, + const struct mipi_dsi_packet *packet) { /* if this is the first packet being queued, enable packet go feature */ if (!dsim->total_pend_ph) __dsim_cmd_packetgo_enable_locked(dsim, true); dsim->total_pend_ph++; - dsim->total_pend_pl += ALIGN(msg->tx_len, 4); + dsim->total_pend_pl += ALIGN(packet->payload_length, 4); - __dsim_cmd_write_locked(dsim, msg, is_long); + __dsim_cmd_write_locked(dsim, packet); dsim_debug(dsim, "total pending packet header(%u) payload(%u)\n", dsim->total_pend_ph, dsim->total_pend_pl); } -static int dsim_cmd_packetgo_flush_locked(struct dsim_device *dsim, bool is_long) +static void __dsim_cmd_prepare(struct dsim_device *dsim) +{ + WARN_ON(!mutex_is_locked(&dsim->cmd_lock)); + + dsim_reg_clear_int(dsim->id, DSIM_INTSRC_SFR_PH_FIFO_EMPTY | DSIM_INTSRC_SFR_PL_FIFO_EMPTY); + + reinit_completion(&dsim->ph_wr_comp); + reinit_completion(&dsim->pl_wr_comp); +} + +static int dsim_cmd_packetgo_flush_locked(struct dsim_device *dsim) { int ret; /* this should only be called with pending packets */ WARN_ON(!dsim->total_pend_ph); + __dsim_cmd_prepare(dsim); + dsim_reg_ready_packetgo(dsim->id, true); dsim_debug(dsim, "packet go ready (ph: %d, pl: %d)\n", dsim->total_pend_ph, dsim->total_pend_pl); - ret = dsim_wait_for_cmd_fifo_empty(dsim, is_long); + ret = dsim_wait_for_cmd_fifo_empty(dsim, dsim->total_pend_pl > 0); if (ret) dsim_warn(dsim, "packetgo failed on wait for cmd fifo empty (%d)\n", ret); @@ -2009,22 +2016,15 @@ static int dsim_cmd_packetgo_flush_locked(struct dsim_device *dsim, bool is_long } static int dsim_write_single_cmd_locked(struct dsim_device *dsim, - const struct mipi_dsi_msg *msg, bool is_long) + const struct mipi_dsi_packet *packet) { - const u8 *tx_buf = msg->tx_buf; - - WARN_ON(!mutex_is_locked(&dsim->cmd_lock)); WARN_ON(dsim_cmd_packetgo_is_enabled(dsim)); - DPU_EVENT_LOG_CMD(dsim, msg->type, tx_buf[0], msg->tx_len); + __dsim_cmd_prepare(dsim); - dsim_reg_clear_int(dsim->id, DSIM_INTSRC_SFR_PH_FIFO_EMPTY); + __dsim_cmd_write_locked(dsim, packet); - reinit_completion(is_long ? &dsim->pl_wr_comp : &dsim->ph_wr_comp); - - __dsim_cmd_write_locked(dsim, msg, is_long); - - return dsim_wait_for_cmd_fifo_empty(dsim, is_long); + return dsim_wait_for_cmd_fifo_empty(dsim, packet->payload_length > 0); } /* @@ -2088,22 +2088,30 @@ static void need_wait_vblank(struct dsim_device *dsim) static int dsim_write_data_locked(struct dsim_device *dsim, const struct mipi_dsi_msg *msg) { int ret = 0; - u16 flags = msg->flags; - bool is_long; - bool is_empty_msg; + const u16 flags = msg->flags; bool is_last; + struct mipi_dsi_packet packet = { .size = 0 }; WARN_ON(!mutex_is_locked(&dsim->cmd_lock)); + if (msg->tx_len > 0) { + const u8 *tx_buf = msg->tx_buf; + + ret = mipi_dsi_create_packet(&packet, msg); + if (ret) { + dsim_err(dsim, "unable to create dsi packet (%d)\n", ret); + return 0; + } + + DPU_EVENT_LOG_CMD(dsim, msg->type, tx_buf[0], msg->tx_len); + } DPU_ATRACE_BEGIN(__func__); - is_empty_msg = !msg->tx_buf || msg->tx_len == 0; - is_long = mipi_dsi_packet_format_is_long(msg->type); if (dsim->config.mode == DSIM_VIDEO_MODE) { if (flags & (EXYNOS_DSI_MSG_FORCE_BATCH | EXYNOS_DSI_MSG_FORCE_FLUSH)) dsim_warn(dsim, "force batching is attempted in video mode\n"); - if (!is_empty_msg) - ret = dsim_write_single_cmd_locked(dsim, msg, is_long); + if (packet.size) + ret = dsim_write_single_cmd_locked(dsim, &packet); goto err; } @@ -2113,8 +2121,8 @@ static int dsim_write_data_locked(struct dsim_device *dsim, const struct mipi_ds goto err; } - if (((dsim->total_pend_pl + msg->tx_len) > MAX_PL_FIFO) || - (dsim->total_pend_ph == MAX_PH_FIFO)) { + if (((dsim->total_pend_pl + packet.payload_length) > MAX_PL_FIFO) || + (dsim->total_pend_ph >= MAX_PH_FIFO)) { dsim_err(dsim, "fifo would be full. ph(%u) pl(%lu) max(%d/%d)\n", dsim->total_pend_ph, dsim->total_pend_pl + msg->tx_len, @@ -2127,14 +2135,15 @@ static int dsim_write_data_locked(struct dsim_device *dsim, const struct mipi_ds if (flags & EXYNOS_DSI_MSG_FORCE_FLUSH) { dsim->force_batching = false; - WARN_ON(!is_empty_msg); + /* force batching should happen only with empty msg */ + WARN_ON(packet.size); } - if (!is_last && !is_empty_msg && - (((dsim->total_pend_ph + 1) == MAX_PH_FIFO) || - ((dsim->total_pend_pl + msg->tx_len) > PL_FIFO_THRESHOLD))) { - dsim_warn(dsim, "warning. changed last command. pend pl/pl(%u,%u)\n", - dsim->total_pend_ph, dsim->total_pend_pl); + if (!is_last && packet.size && + (((dsim->total_pend_ph + 1) >= MAX_PH_FIFO) || + ((dsim->total_pend_pl + packet.payload_length) > PL_FIFO_THRESHOLD))) { + dsim_warn(dsim, "warning. changed last command. pend pl/pl(%u,%u) new pl(%zu)\n", + dsim->total_pend_ph, dsim->total_pend_pl, packet.payload_length); is_last = true; } @@ -2143,21 +2152,18 @@ static int dsim_write_data_locked(struct dsim_device *dsim, const struct mipi_ds if (is_last) { if (dsim_cmd_packetgo_is_enabled(dsim)) { - reinit_completion(is_long ? - &dsim->pl_wr_comp : &dsim->ph_wr_comp); - - if (!is_empty_msg) - dsim_cmd_packetgo_queue_locked(dsim, msg, is_long); + if (packet.size > 0) + dsim_cmd_packetgo_queue_locked(dsim, &packet); if (!(flags & EXYNOS_DSI_MSG_IGNORE_VBLANK)) need_wait_vblank(dsim); - ret = dsim_cmd_packetgo_flush_locked(dsim, is_long); - } else if (!is_empty_msg) { - ret = dsim_write_single_cmd_locked(dsim, msg, is_long); + ret = dsim_cmd_packetgo_flush_locked(dsim); + } else if (packet.size > 0) { + ret = dsim_write_single_cmd_locked(dsim, &packet); } - } else if (!is_empty_msg) { - dsim_cmd_packetgo_queue_locked(dsim, msg, is_long); + } else if (packet.size > 0) { + dsim_cmd_packetgo_queue_locked(dsim, &packet); } err: |