diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index fc2e8b362d..a34ac11478 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -1758,9 +1758,11 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de bool short_resp = false; bool read_done = false; u32 dlen, diff, rlen; - unsigned char *buff; + unsigned char *buff = NULL; char cmd; const struct mipi_dsi_msg *msg; + u32 buffer_sz = 0, header_offset = 0; + u8 *head = NULL; if (!cmd_desc) { DSI_CTRL_ERR(dsi_ctrl, "Invalid command\n"); @@ -1774,6 +1776,11 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de short_resp = true; rd_pkt_size = msg->rx_len; total_read_len = 4; + /* + * buffer size: header + data + * No 32 bits alignment issue, thus offset is 0 + */ + buffer_sz = 4; } else { short_resp = false; current_read_len = 10; @@ -1783,8 +1790,22 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de rd_pkt_size = current_read_len; total_read_len = current_read_len + 6; + /* + * buffer size: header + data + footer, rounded up to 4 bytes. + * Out of bound can occur if rx_len is not aligned to size 4. + */ + buffer_sz = 4 + msg->rx_len + 2; + buffer_sz = ALIGN(buffer_sz, 4); + if (buffer_sz < 16) + buffer_sz = 16; } - buff = msg->rx_buf; + + buff = kzalloc(buffer_sz, GFP_KERNEL); + if (!buff) { + rc = -ENOMEM; + goto error; + } + head = buff; while (!read_done) { rc = dsi_set_max_return_size(dsi_ctrl, cmd_desc, rd_pkt_size); @@ -1846,13 +1867,15 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de } } + buff = head; + if (hw_read_cnt < 16 && !short_resp) - buff = msg->rx_buf + (16 - hw_read_cnt); + header_offset = (16 - hw_read_cnt); else - buff = msg->rx_buf; + header_offset = 0; /* parse the data read from panel */ - cmd = buff[0]; + cmd = buff[header_offset]; switch (cmd) { case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT: DSI_CTRL_ERR(dsi_ctrl, "Rx ACK_ERROR 0x%x\n", cmd); @@ -1860,15 +1883,15 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de break; case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE: case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_1BYTE: - rc = dsi_parse_short_read1_resp(msg, buff); + rc = dsi_parse_short_read1_resp(msg, &buff[header_offset]); break; case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_2BYTE: case MIPI_DSI_RX_DCS_SHORT_READ_RESPONSE_2BYTE: - rc = dsi_parse_short_read2_resp(msg, buff); + rc = dsi_parse_short_read2_resp(msg, &buff[header_offset]); break; case MIPI_DSI_RX_GENERIC_LONG_READ_RESPONSE: case MIPI_DSI_RX_DCS_LONG_READ_RESPONSE: - rc = dsi_parse_long_read_resp(msg, buff); + rc = dsi_parse_long_read_resp(msg, &buff[header_offset]); break; default: DSI_CTRL_WARN(dsi_ctrl, "Invalid response: 0x%x\n", cmd); @@ -1876,6 +1899,7 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl, struct dsi_cmd_desc *cmd_de } error: + kfree(buff); return rc; }