Commit 81c484376353251ba13b7ea987a15a896b3d106a
Committed by
Heiko Schocher
1 parent
c4e5990ad2
Exists in
smarc_8mq_lf_v2020.04
and in
18 other branches
i2c: stm32f7_i2c: fix data abort
As "v" is a local variable in stm32_i2c_choose_solution() "v" has to be copied into "s" to avoid data abort in stm32_i2c_compute_timing(). Signed-off-by: Christophe Kerello <christophe.kerello@st.com> Reviewed-by: Patrick DELAUNAY <patrick.delaunay@st.com> Signed-off-by: Patrice Chotard <patrice.chotard@st.com>
Showing 1 changed file with 11 additions and 10 deletions Side-by-side Diff
drivers/i2c/stm32f7_i2c.c
... | ... | @@ -571,6 +571,7 @@ |
571 | 571 | u32 dnf_delay; |
572 | 572 | u32 tsync; |
573 | 573 | u16 l, h; |
574 | + bool sol_found = false; | |
574 | 575 | int ret = 0; |
575 | 576 | |
576 | 577 | af_delay_min = setup->analog_filter ? |
577 | 578 | |
... | ... | @@ -619,14 +620,15 @@ |
619 | 620 | clk_error_prev = clk_error; |
620 | 621 | v->scll = l; |
621 | 622 | v->sclh = h; |
622 | - s = v; | |
623 | + sol_found = true; | |
624 | + memcpy(s, v, sizeof(*s)); | |
623 | 625 | } |
624 | 626 | } |
625 | 627 | } |
626 | 628 | } |
627 | 629 | } |
628 | 630 | |
629 | - if (!s) { | |
631 | + if (!sol_found) { | |
630 | 632 | pr_err("%s: no solution at all\n", __func__); |
631 | 633 | ret = -EPERM; |
632 | 634 | } |
... | ... | @@ -638,7 +640,7 @@ |
638 | 640 | struct stm32_i2c_setup *setup, |
639 | 641 | struct stm32_i2c_timings *output) |
640 | 642 | { |
641 | - struct stm32_i2c_timings *v, *_v, *s; | |
643 | + struct stm32_i2c_timings *v, *_v, s; | |
642 | 644 | struct list_head solutions; |
643 | 645 | int ret; |
644 | 646 | |
645 | 647 | |
646 | 648 | |
... | ... | @@ -669,21 +671,20 @@ |
669 | 671 | return -EINVAL; |
670 | 672 | } |
671 | 673 | |
672 | - s = NULL; | |
673 | 674 | INIT_LIST_HEAD(&solutions); |
674 | 675 | ret = stm32_i2c_compute_solutions(setup, &solutions); |
675 | 676 | if (ret) |
676 | 677 | goto exit; |
677 | 678 | |
678 | - ret = stm32_i2c_choose_solution(setup, &solutions, s); | |
679 | + ret = stm32_i2c_choose_solution(setup, &solutions, &s); | |
679 | 680 | if (ret) |
680 | 681 | goto exit; |
681 | 682 | |
682 | - output->presc = s->presc; | |
683 | - output->scldel = s->scldel; | |
684 | - output->sdadel = s->sdadel; | |
685 | - output->scll = s->scll; | |
686 | - output->sclh = s->sclh; | |
683 | + output->presc = s.presc; | |
684 | + output->scldel = s.scldel; | |
685 | + output->sdadel = s.sdadel; | |
686 | + output->scll = s.scll; | |
687 | + output->sclh = s.sclh; | |
687 | 688 | |
688 | 689 | debug("%s: Presc: %i, scldel: %i, sdadel: %i, scll: %i, sclh: %i\n", |
689 | 690 | __func__, output->presc, |