aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <swboyd@chromium.org>2018-09-20 14:03:22 -0400
committerWolfram Sang <wsa@the-dreams.de>2018-09-24 18:11:52 -0400
commit6697576788816985f9c79da190abfaad7c9e1738 (patch)
tree2a8e8af967769a58cf93062c0ccece00657c74ee
parent6bf4ca7fbc85d80446ac01c0d1d77db4d91a6d84 (diff)
i2c: i2c-qcom-geni: Properly handle DMA safe buffers
We shouldn't attempt to DMA map the message buffers passed into this driver from the i2c core unless the message we're mapping have been properly setup for DMA. The i2c core indicates such a situation by setting the I2C_M_DMA_SAFE flag, so check for that flag before using DMA mode. We can also bounce the buffer if it isn't already mapped properly by using the i2c_get_dma_safe_msg_buf() APIs, so do that when we want to use DMA for a message. This fixes a problem where the kernel oopses cleaning pages for a buffer that's mapped into the vmalloc space. The pages are returned from request_firmware() and passed down directly to the i2c master to write to the i2c touchscreen device. Mapping vmalloc buffers with dma_map_single() won't work reliably, causing an oops like below: Unable to handle kernel paging request at virtual address ffffffc01391d000 ... Reported-by: Philip Chen <philipchen@chromium.org> Signed-off-by: Stephen Boyd <swboyd@chromium.org> Reviewed-by: Douglas Anderson <dianders@chromium.org> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/busses/i2c-qcom-geni.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 36732eb688a4..9f2eb02481d3 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -367,20 +367,26 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
367 dma_addr_t rx_dma; 367 dma_addr_t rx_dma;
368 enum geni_se_xfer_mode mode; 368 enum geni_se_xfer_mode mode;
369 unsigned long time_left = XFER_TIMEOUT; 369 unsigned long time_left = XFER_TIMEOUT;
370 void *dma_buf;
370 371
371 gi2c->cur = msg; 372 gi2c->cur = msg;
372 mode = msg->len > 32 ? GENI_SE_DMA : GENI_SE_FIFO; 373 mode = GENI_SE_FIFO;
374 dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
375 if (dma_buf)
376 mode = GENI_SE_DMA;
377
373 geni_se_select_mode(&gi2c->se, mode); 378 geni_se_select_mode(&gi2c->se, mode);
374 writel_relaxed(msg->len, gi2c->se.base + SE_I2C_RX_TRANS_LEN); 379 writel_relaxed(msg->len, gi2c->se.base + SE_I2C_RX_TRANS_LEN);
375 geni_se_setup_m_cmd(&gi2c->se, I2C_READ, m_param); 380 geni_se_setup_m_cmd(&gi2c->se, I2C_READ, m_param);
376 if (mode == GENI_SE_DMA) { 381 if (mode == GENI_SE_DMA) {
377 int ret; 382 int ret;
378 383
379 ret = geni_se_rx_dma_prep(&gi2c->se, msg->buf, msg->len, 384 ret = geni_se_rx_dma_prep(&gi2c->se, dma_buf, msg->len,
380 &rx_dma); 385 &rx_dma);
381 if (ret) { 386 if (ret) {
382 mode = GENI_SE_FIFO; 387 mode = GENI_SE_FIFO;
383 geni_se_select_mode(&gi2c->se, mode); 388 geni_se_select_mode(&gi2c->se, mode);
389 i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
384 } 390 }
385 } 391 }
386 392
@@ -393,6 +399,7 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
393 if (gi2c->err) 399 if (gi2c->err)
394 geni_i2c_rx_fsm_rst(gi2c); 400 geni_i2c_rx_fsm_rst(gi2c);
395 geni_se_rx_dma_unprep(&gi2c->se, rx_dma, msg->len); 401 geni_se_rx_dma_unprep(&gi2c->se, rx_dma, msg->len);
402 i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
396 } 403 }
397 return gi2c->err; 404 return gi2c->err;
398} 405}
@@ -403,20 +410,26 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
403 dma_addr_t tx_dma; 410 dma_addr_t tx_dma;
404 enum geni_se_xfer_mode mode; 411 enum geni_se_xfer_mode mode;
405 unsigned long time_left; 412 unsigned long time_left;
413 void *dma_buf;
406 414
407 gi2c->cur = msg; 415 gi2c->cur = msg;
408 mode = msg->len > 32 ? GENI_SE_DMA : GENI_SE_FIFO; 416 mode = GENI_SE_FIFO;
417 dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
418 if (dma_buf)
419 mode = GENI_SE_DMA;
420
409 geni_se_select_mode(&gi2c->se, mode); 421 geni_se_select_mode(&gi2c->se, mode);
410 writel_relaxed(msg->len, gi2c->se.base + SE_I2C_TX_TRANS_LEN); 422 writel_relaxed(msg->len, gi2c->se.base + SE_I2C_TX_TRANS_LEN);
411 geni_se_setup_m_cmd(&gi2c->se, I2C_WRITE, m_param); 423 geni_se_setup_m_cmd(&gi2c->se, I2C_WRITE, m_param);
412 if (mode == GENI_SE_DMA) { 424 if (mode == GENI_SE_DMA) {
413 int ret; 425 int ret;
414 426
415 ret = geni_se_tx_dma_prep(&gi2c->se, msg->buf, msg->len, 427 ret = geni_se_tx_dma_prep(&gi2c->se, dma_buf, msg->len,
416 &tx_dma); 428 &tx_dma);
417 if (ret) { 429 if (ret) {
418 mode = GENI_SE_FIFO; 430 mode = GENI_SE_FIFO;
419 geni_se_select_mode(&gi2c->se, mode); 431 geni_se_select_mode(&gi2c->se, mode);
432 i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
420 } 433 }
421 } 434 }
422 435
@@ -432,6 +445,7 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg,
432 if (gi2c->err) 445 if (gi2c->err)
433 geni_i2c_tx_fsm_rst(gi2c); 446 geni_i2c_tx_fsm_rst(gi2c);
434 geni_se_tx_dma_unprep(&gi2c->se, tx_dma, msg->len); 447 geni_se_tx_dma_unprep(&gi2c->se, tx_dma, msg->len);
448 i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
435 } 449 }
436 return gi2c->err; 450 return gi2c->err;
437} 451}