|
@@ -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;
|
|
|
}
|
|
|
|