Re: [PATCH V8 1/1] i2c: i2c-qcom-geni: Add shutdown callback for i2c

2021-04-20 Thread rojay

Hi Stephen,

On 2021-02-24 12:36, Stephen Boyd wrote:

Quoting ro...@codeaurora.org (2021-02-18 06:15:17)

Hi Stephen,

On 2021-01-13 12:24, Stephen Boyd wrote:
> Quoting Roja Rani Yarubandi (2021-01-08 07:05:45)
>> diff --git a/drivers/i2c/busses/i2c-qcom-geni.c
>> b/drivers/i2c/busses/i2c-qcom-geni.c
>> index 214b4c913a13..c3f584795911 100644
>> --- a/drivers/i2c/busses/i2c-qcom-geni.c
>> +++ b/drivers/i2c/busses/i2c-qcom-geni.c
>> @@ -375,6 +375,32 @@ static void geni_i2c_tx_msg_cleanup(struct
>> geni_i2c_dev *gi2c,
>> }
>>  }
>>
>> +static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c)
>> +{
>> +   int ret;
>> +   u32 geni_status;
>> +   struct i2c_msg *cur;
>> +
>> +   /* Resume device, as runtime suspend can happen anytime during
>> transfer */
>> +   ret = pm_runtime_get_sync(gi2c->se.dev);
>> +   if (ret < 0) {
>> +   dev_err(gi2c->se.dev, "Failed to resume device: %d\n",
>> ret);
>> +   return;
>> +   }
>> +
>> +   geni_status = readl_relaxed(gi2c->se.base + SE_GENI_STATUS);
>> +   if (geni_status & M_GENI_CMD_ACTIVE) {
>> +   cur = gi2c->cur;
>
> Why don't we need to hold the spinlock gi2c::lock here?
>

I am not seeing any race here. May I know which race are you 
suspecting

here?


Sorry there are long delays between posting and replies to my review
comments. It takes me some time to remember what we're talking about
because this patch has dragged on for many months.



Sorry for the delayed responses.


So my understanding is that gi2c::lock protects the 'cur' pointer. I
imagine this scenario might go bad

  CPU0  CPU1
    
  geni_i2c_stop_xfer()
   ...  geni_i2c_rx_one_msg()
 gi2c->cur = cur1;
   cur = gi2c->cur;
   ...   geni_i2c_tx_one_msg()
 gi2c->cur = cur2;
   geni_i2c_abort_xfer()

   if (cur->flags & I2C_M_RD)


It's almost like we should combine the geni_i2c_abort_xfer() logic with
the rx/tx message cleanup functions so that it's all done under one
lock. Unfortunately it's complicated by the fact that there are various
completion waiting timeouts involved. Fun!



Thanks for the explanation. Fixed this possible race by protecting 
gi2c->cur
and calling geni_i2c_abort_xfer() with adding another parameter to 
differentiate

from which sequence is the geni_i2c_abort_xfer() called and handle the
spin_lock/spin_unlock accordingly inside geni_i2c_abort_xfer()

But even after all that, I don't see how the geni_i2c_stop_xfer() puts 
a

stop to future calls to geni_i2c_rx_one_msg() or geni_i2c_tx_one_msg().


Now handled this by adding a bool variable "stop_xfer" in geni_i2c_dev 
struct,
used to put stop to upcoming geni_i2c_rx_one_msg() and 
geni_i2c_tx_one_msg() calls

once we receive the shutdown call.


The hardware isn't disabled from what I can tell. The irq isn't
disabled, the clks aren't turned off, etc. What is to stop an i2c 
device

from trying to use the bus after this shutdown function is called? If
anything, this function looks like a "flush", where we flush out any
pending transfer. Where's the "plug" operation that prevents any future
operations from following this call?



We are turning off clocks and disabling irq in 
geni_i2c_runtime_suspend().


IIUC about shutdown sequence, during "remove" we will unplug the device 
with opposite
calls to "probe's" plug operations example i2c_del_adapter(). For 
"shutdown", as system

is going to shutdown, there is no need of unplug operations to be done.


BTW, I see this is merged upstream. That's great, but it seems broken.
Please fix it or revert it out.



>> +   geni_i2c_abort_xfer(gi2c);
>> +   if (cur->flags & I2C_M_RD)
>> +   geni_i2c_rx_msg_cleanup(gi2c, cur);
>> +   else
>> +   geni_i2c_tx_msg_cleanup(gi2c, cur);
>> +   }
>> +
>> +   pm_runtime_put_sync_suspend(gi2c->se.dev);
>> +}
>> +
>>  static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct
>> i2c_msg *msg,
>> u32 m_param)
>>  {


Thanks,
Roja


Re: [PATCH 3/3] i2c: i2c-qcom-geni: Add support for 'assigned-performance-states'

2021-04-01 Thread rojay

On 2021-02-12 14:51, ro...@codeaurora.org wrote:

On 2021-01-20 19:01, Ulf Hansson wrote:
On Tue, 19 Jan 2021 at 12:05, Viresh Kumar  
wrote:


On 19-01-21, 12:02, Ulf Hansson wrote:
> As a matter of fact this was quite recently discussed [1], which also
> pointed out some issues when using the "required-opps" in combination,
> but perhaps that got resolved? Viresh?

Perhaps we never did anything there ..


Okay. Looks like we should pick up that discussion again, to conclude
on how to move forward.



Soft Reminder!



Request Viresh, Uffe to discuss on the way forward.



--
viresh


Kind regards
Uffe


- Roja


Re: [PATCH V3 1/2] soc: qcom-geni-se: Cleanup the code to remove proxy votes

2021-03-24 Thread rojay

On 2021-03-23 15:00, Greg KH wrote:

On Mon, Mar 22, 2021 at 04:34:28PM +0530, Roja Rani Yarubandi wrote:

This reverts commit 048eb908a1f2 ("soc: qcom-geni-se: Add interconnect
support to fix earlycon crash")

ICC core and platforms drivers supports sync_state feature with
commit 7d3b0b0d8184 ("interconnect: qcom: Use icc_sync_state") which
ensures that the default ICC BW votes from the bootloader is not
removed until all it's consumers are probes.

The proxy votes were needed in case other QUP child drivers
I2C, SPI probes before UART, they can turn off the QUP-CORE clock
which is shared resources for all QUP driver, this causes unclocked
access to HW from earlycon.

Given above support from ICC there is no longer need to maintain
proxy votes on QUP-CORE ICC node from QUP wrapper driver for early
console usecase, the default votes won't be removed until real
console is probed.

Signed-off-by: Roja Rani Yarubandi 
Signed-off-by: Akash Asthana 
Reviewed-by: Matthias Kaehlcke 


Should this have a "Fixes:" tag, and also be cc: sta...@vger.kernel.org
so that it will be properly backported?

If so, please add and resend.



Okay, will add and resend.


thanks,

greg k-h


Re: [PATCH V2 1/2] soc: qcom-geni-se: Cleanup the code to remove proxy votes

2021-03-22 Thread rojay

On 2021-03-18 22:43, Matthias Kaehlcke wrote:

On Thu, Mar 18, 2021 at 04:40:08PM +0530, Roja Rani Yarubandi wrote:

ICC core and platforms drivers supports sync_state feature, which
ensures that the default ICC BW votes from the bootloader is not
removed until all it's consumers are probes.

The proxy votes were needed in case other QUP child drivers
I2C, SPI probes before UART, they can turn off the QUP-CORE clock
which is shared resources for all QUP driver, this causes unclocked
access to HW from earlycon.

Given above support from ICC there is no longer need to maintain
proxy votes on QUP-CORE ICC node from QUP wrapper driver for early
console usecase, the default votes won't be removed until real
console is probed.

Signed-off-by: Roja Rani Yarubandi 
Signed-off-by: Akash Asthana 


I suggest to mention that this is essentially a revert of commit
048eb908a1f2 ("soc: qcom-geni-se: Add interconnect support to fix
earlycon crash"). This makes the life of reviewers easier and it's
also good to have the reference in the git history.



Ok.


You could also mention commit 7d3b0b0d8184 ("interconnect: qcom:
Use icc_sync_state") in the intro.



Ok.


I tried to test by first reproducing the original issue without
'sync_state' in the ICC, but wasn't successful, probably something
changed in the boot/ICC timing in the meantime ¯\_(ツ)_/¯.



Need to remove runtime auto suspend support from SPI/I2C as well, as it 
was

masking the issue by delaying to turn off the resources by 250ms.


Reviewed-by: Matthias Kaehlcke 


Re: [PATCH V8 1/1] i2c: i2c-qcom-geni: Add shutdown callback for i2c

2021-02-18 Thread rojay

Hi Stephen,

On 2021-01-13 12:24, Stephen Boyd wrote:

Quoting Roja Rani Yarubandi (2021-01-08 07:05:45)
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index 214b4c913a13..c3f584795911 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -375,6 +375,32 @@ static void geni_i2c_tx_msg_cleanup(struct 
geni_i2c_dev *gi2c,

}
 }

+static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c)
+{
+   int ret;
+   u32 geni_status;
+   struct i2c_msg *cur;
+
+   /* Resume device, as runtime suspend can happen anytime during 
transfer */

+   ret = pm_runtime_get_sync(gi2c->se.dev);
+   if (ret < 0) {
+   dev_err(gi2c->se.dev, "Failed to resume device: %d\n", 
ret);

+   return;
+   }
+
+   geni_status = readl_relaxed(gi2c->se.base + SE_GENI_STATUS);
+   if (geni_status & M_GENI_CMD_ACTIVE) {
+   cur = gi2c->cur;


Why don't we need to hold the spinlock gi2c::lock here?



I am not seeing any race here. May I know which race are you suspecting 
here?



+   geni_i2c_abort_xfer(gi2c);
+   if (cur->flags & I2C_M_RD)
+   geni_i2c_rx_msg_cleanup(gi2c, cur);
+   else
+   geni_i2c_tx_msg_cleanup(gi2c, cur);
+   }
+
+   pm_runtime_put_sync_suspend(gi2c->se.dev);
+}
+
 static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct 
i2c_msg *msg,

u32 m_param)
 {


Re: [PATCH 3/3] i2c: i2c-qcom-geni: Add support for 'assigned-performance-states'

2021-02-12 Thread rojay

On 2021-01-20 19:01, Ulf Hansson wrote:
On Tue, 19 Jan 2021 at 12:05, Viresh Kumar  
wrote:


On 19-01-21, 12:02, Ulf Hansson wrote:
> As a matter of fact this was quite recently discussed [1], which also
> pointed out some issues when using the "required-opps" in combination,
> but perhaps that got resolved? Viresh?

Perhaps we never did anything there ..


Okay. Looks like we should pick up that discussion again, to conclude
on how to move forward.



Soft Reminder!



--
viresh


Kind regards
Uffe


- Roja


Re: [PATCH V7 2/2] i2c: i2c-qcom-geni: Add shutdown callback for i2c

2021-01-08 Thread rojay

Hi Wolfram,

On 2021-01-05 20:57, Wolfram Sang wrote:

+   geni_status = readl_relaxed(gi2c->se.base + SE_GENI_STATUS);
+   if (!(geni_status & M_GENI_CMD_ACTIVE))
+   goto out;
+
+   cur = gi2c->cur;
+   geni_i2c_abort_xfer(gi2c);
+   if (cur->flags & I2C_M_RD)
+   geni_i2c_rx_msg_cleanup(gi2c, cur);
+   else
+   geni_i2c_tx_msg_cleanup(gi2c, cur);
+out:
+   pm_runtime_put_sync_suspend(gi2c->se.dev);
+}


The use of 'goto' is not needed here IMHO. I think:

if (geni_status & M_GENI_CMD_ACTIVE) {
do_the_stuff
}

pm_runtime_put_sync_suspend(...);

is more readable, in fact.



In context to the previous comment [1], I have implemented this way.
But, yeah anything is fine for me.


Also, I don't think we really need the 'cur'
variable and just use 'gi2c->cur' but that's very minor and you can 
keep

it if you like it.



In geni_i2c_abort_xfer() function gi2c->cur will be made NULL, so 
copying it before to "cur" is needed here.



Reset looks good!


[1] 
https://patchwork.kernel.org/project/linux-arm-msm/patch/20200820103522.26242-3-ro...@codeaurora.org/#23560541


Thanks,
Roja


Re: [RESEND PATCH V6 1/2] i2c: i2c-qcom-geni: Store DMA mapping data in geni_i2c_dev struct

2020-12-21 Thread rojay

On 2020-12-09 18:29, Akash Asthana wrote:

Hi Roja,

On 12/3/2020 4:01 PM, Roja Rani Yarubandi wrote:

Store DMA mapping data in geni_i2c_dev struct to enhance DMA mapping
data scope. For example during shutdown callback to unmap DMA mapping,
this stored DMA mapping data can be used to call geni_se_tx_dma_unprep
and geni_se_rx_dma_unprep functions.

Add two helper functions geni_i2c_rx_msg_cleanup and
geni_i2c_tx_msg_cleanup to unwrap the things after rx/tx FIFO/DMA
transfers, so that the same can be used in geni_i2c_stop_xfer()
function during shutdown callback.

Signed-off-by: Roja Rani Yarubandi 
---
Changes in V5:
  - As per Stephen's comments separated this patch from shutdown
callback patch, gi2c->cur = NULL is not removed from
geni_i2c_abort_xfer(), and made a copy of gi2c->cur and passed
to cleanup functions.

Changes in V6:
  - Added spin_lock/unlock in geni_i2c_rx_msg_cleanup() and
geni_i2c_tx_msg_cleanup() functions.

  drivers/i2c/busses/i2c-qcom-geni.c | 69 
+++---

  1 file changed, 53 insertions(+), 16 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index dce75b85253c..bfbc80f65006 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -86,6 +86,9 @@ struct geni_i2c_dev {
u32 clk_freq_out;
const struct geni_i2c_clk_fld *clk_fld;
int suspended;
+   void *dma_buf;
+   size_t xfer_len;
+   dma_addr_t dma_addr;
  };
struct geni_i2c_err_log {
@@ -348,14 +351,49 @@ static void geni_i2c_tx_fsm_rst(struct 
geni_i2c_dev *gi2c)

dev_err(gi2c->se.dev, "Timeout resetting TX_FSM\n");
  }
  +static void geni_i2c_rx_msg_cleanup(struct geni_i2c_dev *gi2c,
+struct i2c_msg *cur)
+{
+   struct geni_se *se = >se;
+   unsigned long flags;
+
+   spin_lock_irqsave(>lock, flags);
+   gi2c->cur_rd = 0;
+   if (gi2c->dma_buf) {
+   if (gi2c->err)
+   geni_i2c_rx_fsm_rst(gi2c);


Which race we are trying to avoid here by holding spinlock?



Thought that race might occur with "cur" here.


We cannot call any sleeping API by holding spinlock,
geni_i2c_rx_fsm_rst calls *wait-for-completion*, which is a sleeping
call.



Fixed this.


+   geni_se_rx_dma_unprep(se, gi2c->dma_addr, gi2c->xfer_len);
+   i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err);
+   }
+   spin_unlock_irqrestore(>lock, flags);
+}
+
+static void geni_i2c_tx_msg_cleanup(struct geni_i2c_dev *gi2c,
+struct i2c_msg *cur)
+{
+   struct geni_se *se = >se;
+   unsigned long flags;
+
+   spin_lock_irqsave(>lock, flags);
+   gi2c->cur_wr = 0;
+   if (gi2c->dma_buf) {
+   if (gi2c->err)
+   geni_i2c_tx_fsm_rst(gi2c);


Same here

Regards,

Akash


+   geni_se_tx_dma_unprep(se, gi2c->dma_addr, gi2c->xfer_len);
+   i2c_put_dma_safe_msg_buf(gi2c->dma_buf, cur, !gi2c->err);
+   }
+   spin_unlock_irqrestore(>lock, flags);
+}
+
  static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct 
i2c_msg *msg,

u32 m_param)
  {
-   dma_addr_t rx_dma;
+   dma_addr_t rx_dma = 0;
unsigned long time_left;
void *dma_buf = NULL;
struct geni_se *se = >se;
size_t len = msg->len;
+   struct i2c_msg *cur;
if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
@@ -372,19 +410,18 @@ static int geni_i2c_rx_one_msg(struct 
geni_i2c_dev *gi2c, struct i2c_msg *msg,

geni_se_select_mode(se, GENI_SE_FIFO);
i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
dma_buf = NULL;
+   } else {
+   gi2c->xfer_len = len;
+   gi2c->dma_addr = rx_dma;
+   gi2c->dma_buf = dma_buf;
}
  + cur = gi2c->cur;
time_left = wait_for_completion_timeout(>done, XFER_TIMEOUT);
if (!time_left)
geni_i2c_abort_xfer(gi2c);
  - gi2c->cur_rd = 0;
-   if (dma_buf) {
-   if (gi2c->err)
-   geni_i2c_rx_fsm_rst(gi2c);
-   geni_se_rx_dma_unprep(se, rx_dma, len);
-   i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
-   }
+   geni_i2c_rx_msg_cleanup(gi2c, cur);
return gi2c->err;
  }
@@ -392,11 +429,12 @@ static int geni_i2c_rx_one_msg(struct 
geni_i2c_dev *gi2c, struct i2c_msg *msg,
  static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct 
i2c_msg *msg,

u32 m_param)
  {
-   dma_addr_t tx_dma;
+   dma_addr_t tx_dma = 0;
unsigned long time_left;
void *dma_buf = NULL;
struct geni_se *se = >se;
size_t len = msg->len;
+   struct i2c_msg *cur;
if 

Re: [PATCH V5 3/3] i2c: i2c-qcom-geni: Add shutdown callback for i2c

2020-10-30 Thread rojay

Hi Stephen,

On 2020-10-03 07:09, Stephen Boyd wrote:

Quoting Roja Rani Yarubandi (2020-10-01 01:44:25)
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index aee2a1dd2c62..56d3fbfe7eb6 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -380,6 +380,36 @@ static void geni_i2c_tx_msg_cleanup(struct 
geni_i2c_dev *gi2c,

}
 }

+static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c)
+{
+   int ret;
+   u32 geni_status;
+   unsigned long flags;
+   struct i2c_msg *cur;
+
+   /* Resume device, runtime suspend can happen anytime during 
transfer */

+   ret = pm_runtime_get_sync(gi2c->se.dev);
+   if (ret < 0) {
+   dev_err(gi2c->se.dev, "Failed to resume device: %d\n", 
ret);

+   return;
+   }
+
+   spin_lock_irqsave(>lock, flags);


We grab the lock here.


+   geni_status = readl_relaxed(gi2c->se.base + SE_GENI_STATUS);
+   if (!(geni_status & M_GENI_CMD_ACTIVE))
+   goto out;
+
+   cur = gi2c->cur;
+   geni_i2c_abort_xfer(gi2c);


But it looks like this function takes the lock again? Did you test this
with lockdep enabled? It should hang even without lockdep, so it seems
like this path of code has not been tested.



Tested with lockdep enabled, and fixed the unsafe lock order issue here.
And to be more proper moved spin_lock/unlock to cleanup functions.


+   if (cur->flags & I2C_M_RD)
+   geni_i2c_rx_msg_cleanup(gi2c, cur);
+   else
+   geni_i2c_tx_msg_cleanup(gi2c, cur);
+   spin_unlock_irqrestore(>lock, flags);
+out:
+   pm_runtime_put_sync_suspend(gi2c->se.dev);
+}
+
 static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct 
i2c_msg *msg,

u32 m_param)
 {


Re: [PATCH V4] i2c: i2c-qcom-geni: Add shutdown callback for i2c

2020-09-21 Thread rojay

Hi Stephen,

On 2020-09-18 01:53, Stephen Boyd wrote:

Quoting Roja Rani Yarubandi (2020-09-17 05:25:58)
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index dead5db3315a..b0d8043c8cb2 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -86,6 +86,10 @@ struct geni_i2c_dev {
u32 clk_freq_out;
const struct geni_i2c_clk_fld *clk_fld;
int suspended;
+   void *dma_buf;
+   size_t xfer_len;
+   dma_addr_t tx_dma;
+   dma_addr_t rx_dma;


Do we need both tx_dma and rx_dma? Seems that we use cur->flags to
figure out if the transfer is tx or rx so we could have juat dma_buf 
and

dma_addr here?



Okay.


 };

 struct geni_i2c_err_log {
@@ -307,7 +311,6 @@ static void geni_i2c_abort_xfer(struct 
geni_i2c_dev *gi2c)


spin_lock_irqsave(>lock, flags);
geni_i2c_err(gi2c, GENI_TIMEOUT);
-   gi2c->cur = NULL;


This looks concerning. We're moving this out from under the spinlock.
The irq handler in this driver seems to hold the spinlock all the time
while processing and this function grabs it here to keep cur consistent
when aborting the transfer due to a timeout. Otherwise it looks like 
the

irqhandler can race with this and try to complete the transfer while
it's being torn down here.


geni_se_abort_m_cmd(>se);
spin_unlock_irqrestore(>lock, flags);
do {
@@ -349,10 +352,62 @@ static void geni_i2c_tx_fsm_rst(struct 
geni_i2c_dev *gi2c)

dev_err(gi2c->se.dev, "Timeout resetting TX_FSM\n");
 }

+static void geni_i2c_rx_msg_cleanup(struct geni_i2c_dev *gi2c)


So maybe pass cur to this function?



Sorry, i did not understand why to pass cur to this function?


+{
+   struct geni_se *se = >se;
+
+   gi2c->cur_rd = 0;
+   if (gi2c->dma_buf) {
+   if (gi2c->err)
+   geni_i2c_rx_fsm_rst(gi2c);
+   geni_se_rx_dma_unprep(se, gi2c->rx_dma, 
gi2c->xfer_len);
+   i2c_put_dma_safe_msg_buf(gi2c->dma_buf, gi2c->cur, 
!gi2c->err);

+   }
+}
+
+static void geni_i2c_tx_msg_cleanup(struct geni_i2c_dev *gi2c)


And this one?


+{
+   struct geni_se *se = >se;
+
+   gi2c->cur_wr = 0;
+   if (gi2c->dma_buf) {
+   if (gi2c->err)
+   geni_i2c_tx_fsm_rst(gi2c);
+   geni_se_tx_dma_unprep(se, gi2c->tx_dma, 
gi2c->xfer_len);
+   i2c_put_dma_safe_msg_buf(gi2c->dma_buf, gi2c->cur, 
!gi2c->err);

+   }
+}
+
+static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c)
+{
+   int ret;
+   u32 geni_status;
+
+   /* Resume device, as runtime suspend can happen anytime during 
transfer */

+   ret = pm_runtime_get_sync(gi2c->se.dev);
+   if (ret < 0) {
+   dev_err(gi2c->se.dev, "Failed to resume device: %d\n", 
ret);

+   return;
+   }
+
+   geni_status = readl_relaxed(gi2c->se.base + SE_GENI_STATUS);


And this probably needs to hold the lock?


+   if (!(geni_status & M_GENI_CMD_ACTIVE))
+   goto out;
+
+   geni_i2c_abort_xfer(gi2c);
+   if (gi2c->cur->flags & I2C_M_RD)
+   geni_i2c_rx_msg_cleanup(gi2c);
+   else
+   geni_i2c_tx_msg_cleanup(gi2c);
+   gi2c->cur = NULL;


until here?



Okay.


+out:
+   pm_runtime_put_sync_suspend(gi2c->se.dev);
+}
+
 static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct 
i2c_msg *msg,

u32 m_param)
 {
-   dma_addr_t rx_dma;
+   dma_addr_t rx_dma = 0;
unsigned long time_left;
void *dma_buf = NULL;
struct geni_se *se = >se;
@@ -372,6 +427,10 @@ static int geni_i2c_rx_one_msg(struct 
geni_i2c_dev *gi2c, struct i2c_msg *msg,

geni_se_select_mode(se, GENI_SE_FIFO);
i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
dma_buf = NULL;
+   } else {
+   gi2c->xfer_len = len;
+   gi2c->rx_dma = rx_dma;
+   gi2c->dma_buf = dma_buf;
}

geni_se_setup_m_cmd(se, I2C_READ, m_param);
@@ -380,13 +439,7 @@ static int geni_i2c_rx_one_msg(struct 
geni_i2c_dev *gi2c, struct i2c_msg *msg,

if (!time_left)
geni_i2c_abort_xfer(gi2c);

-   gi2c->cur_rd = 0;
-   if (dma_buf) {
-   if (gi2c->err)
-   geni_i2c_rx_fsm_rst(gi2c);
-   geni_se_rx_dma_unprep(se, rx_dma, len);
-   i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
-   }
+   geni_i2c_rx_msg_cleanup(gi2c);

return gi2c->err;
 }


It may make sense to extract the cleanup stuff into another patch. Then
have a patch after that which does the shutdown hook. So three patches
total.



Okay, I will make separate patches, one for cleanup and another for 
shutdown hook.


diff --git a/drivers/soc/qcom/qcom-geni-se.c 
b/drivers/soc/qcom/qcom-geni-se.c

index d0e4f520cff8..0216b38c1e9a 100644

Re: [PATCH V3] i2c: i2c-qcom-geni: Add shutdown callback for i2c

2020-09-17 Thread rojay

Hi Stephen,

On 2020-09-09 01:00, Stephen Boyd wrote:

Why is dri-devel on here? And linaro-mm-sig?



Ok, I will remove these lists.


Quoting Roja Rani Yarubandi (2020-09-07 06:07:31)
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index dead5db3315a..b3609760909f 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
 struct geni_i2c_err_log {
@@ -384,7 +387,8 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev 
*gi2c, struct i2c_msg *msg,

if (dma_buf) {
if (gi2c->err)
geni_i2c_rx_fsm_rst(gi2c);
-   geni_se_rx_dma_unprep(se, rx_dma, len);
+   geni_se_rx_dma_unprep(se, gi2c->rx_dma, len);
+   gi2c->rx_dma = (dma_addr_t)NULL;
i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
}

@@ -394,12 +398,12 @@ static int geni_i2c_rx_one_msg(struct 
geni_i2c_dev *gi2c, struct i2c_msg *msg,
 static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct 
i2c_msg *msg,

u32 m_param)
 {
-   dma_addr_t tx_dma;
unsigned long time_left;
void *dma_buf = NULL;
struct geni_se *se = >se;
size_t len = msg->len;

+   gi2c->xfer_len = len;
if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);

@@ -410,7 +414,7 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev 
*gi2c, struct i2c_msg *msg,


writel_relaxed(len, se->base + SE_I2C_TX_TRANS_LEN);

-   if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, _dma)) 
{
+   if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, 
>tx_dma)) {

geni_se_select_mode(se, GENI_SE_FIFO);
i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
dma_buf = NULL;
@@ -429,7 +433,8 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev 
*gi2c, struct i2c_msg *msg,

if (dma_buf) {
if (gi2c->err)
geni_i2c_tx_fsm_rst(gi2c);
-   geni_se_tx_dma_unprep(se, tx_dma, len);
+   geni_se_tx_dma_unprep(se, gi2c->tx_dma, len);
+   gi2c->tx_dma = (dma_addr_t)NULL;
i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
}

@@ -479,6 +484,51 @@ static int geni_i2c_xfer(struct i2c_adapter 
*adap,

return ret;
 }

+static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c)
+{
+   int ret;
+   u32 dma;
+   u32 val;
+   u32 geni_status;
+   struct geni_se *se = >se;
+
+   ret = pm_runtime_get_sync(gi2c->se.dev);
+   if (ret < 0) {
+   dev_err(gi2c->se.dev, "Failed to resume device: %d\n", 
ret);


Is this print really necessary? Doesn't PM core already print this sort
of information?



PM core will not print any such information.
Here we wanted to know our driver's pm runtime resume is successful.


+   return;
+   }
+
+   geni_status = readl_relaxed(gi2c->se.base + SE_GENI_STATUS);
+   if (geni_status & M_GENI_CMD_ACTIVE) {


Please try to de-indent all this.



Okay.


if (!(geni_status & M_GENI_CMD_ACTIVE))
goto out;


+   geni_i2c_abort_xfer(gi2c);
+   dma = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
+   if (dma) {


if (!dma)
goto out;

+   val = readl_relaxed(gi2c->se.base + 
SE_DMA_DEBUG_REG0);

+   if (val & DMA_TX_ACTIVE) {
+   gi2c->cur_wr = 0;
+   if (gi2c->err)
+   geni_i2c_tx_fsm_rst(gi2c);
+   if (gi2c->tx_dma) {
+   geni_se_tx_dma_unprep(se,
+gi2c->tx_dma, 
gi2c->xfer_len);
+   gi2c->tx_dma = 
(dma_addr_t)NULL;


Almost nobody does this. In fact, grep shows me one hit in the kernel.
If nobody else is doing it something is probably wrong. When would dma
mode be active and tx_dma not be set to something that should be
stopped? If it really is necessary I suppose we should assign this to
DMA_MAPPING_ERROR instead of casting NULL. Then the check above for
tx_dma being valid can be dropped because geni_se_tx_dma_unprep()
already checks for a valid mapping before doing anything. But really, 
we

should probably be tracking the dma buffer mapped to the CPU as well as
the dma address that was used for the mapping. Not storing both is a
problem, see below.



You are correct, setting gi2c->tx_dma to NULL and check for tx_dma is
not required. Will correct this.


+   }
+   } else if (val & DMA_RX_ACTIVE) {
+   gi2c->cur_rd = 0;
+   if (gi2c->err)
+   

Re: [PATCH V2 2/2] i2c: i2c-qcom-geni: Add shutdown callback for i2c

2020-09-07 Thread rojay

On 2020-08-26 17:26, Akash Asthana wrote:

Hi Roja,

On 8/20/2020 4:05 PM, Roja Rani Yarubandi wrote:

If the hardware is still accessing memory after SMMU translation
is disabled (as part of smmu shutdown callback), then the
IOVAs (I/O virtual address) which it was using will go on the bus
as the physical addresses which will result in unknown crashes
like NoC/interconnect errors.

So, implement shutdown callback to i2c driver to unmap DMA mappings
during system "reboot" or "shutdown".

Signed-off-by: Roja Rani Yarubandi 
---
Changes in V2:
  - As per Stephen's comments added seperate function for stop 
transfer,

fixed minor nitpicks.

  drivers/i2c/busses/i2c-qcom-geni.c | 43 
++

  include/linux/qcom-geni-se.h   |  5 
  2 files changed, 48 insertions(+)

diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index 1fda5c7c2cfc..d07f2f33bb75 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -486,6 +486,28 @@ static int geni_i2c_xfer(struct i2c_adapter 
*adap,

return ret;
  }
  +static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c)
+{
+   u32 val;
+   struct geni_se *se = >se;
+
+   val = readl_relaxed(gi2c->se.base + SE_DMA_DEBUG_REG0);
+   if (val & DMA_TX_ACTIVE) {
+   geni_i2c_abort_xfer(gi2c);
+   gi2c->cur_wr = 0;
+   if (gi2c->err)
+   geni_i2c_tx_fsm_rst(gi2c);
+   geni_se_tx_dma_unprep(se, gi2c->tx_dma, gi2c->xfer_len);
+   }

should be 'else if', because TX and RX can't happen parallel.

+   if (val & DMA_RX_ACTIVE) {
+   geni_i2c_abort_xfer(gi2c);
+   gi2c->cur_rd = 0;
+   if (gi2c->err)
+   geni_i2c_rx_fsm_rst(gi2c);
+   geni_se_rx_dma_unprep(se, gi2c->rx_dma, gi2c->xfer_len);
+   }
+}
+
  static u32 geni_i2c_func(struct i2c_adapter *adap)
  {
  	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & 
~I2C_FUNC_SMBUS_QUICK);
@@ -617,6 +639,26 @@ static int geni_i2c_remove(struct platform_device 
*pdev)

return 0;
  }
  +static void geni_i2c_shutdown(struct platform_device *pdev)
+{
+   int ret;
+   u32 dma;
+   struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
+   struct geni_se *se = >se;
+
+   ret = pm_runtime_get_sync(gi2c->se.dev);
+   if (ret < 0) {
+   dev_err(gi2c->se.dev, "Failed to resume device: %d\n", ret);
+   return;
+   }
+
+   dma = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);


Wrt to current issue context it may be suffice to stop just DMA mode
transfers but why not stop all mode of active transfer during shutdown
in a generic way.

Regards,

Akash



Okay, I will include FIFO transfer case also in stop_xfer


+   if (dma)
+   geni_i2c_stop_xfer(gi2c);
+
+   pm_runtime_put_sync_suspend(gi2c->se.dev);
+}
+
  static int __maybe_unused geni_i2c_runtime_suspend(struct device 
*dev)

  {
int ret;
@@ -677,6 +719,7 @@ MODULE_DEVICE_TABLE(of, geni_i2c_dt_match);
  static struct platform_driver geni_i2c_driver = {
.probe  = geni_i2c_probe,
.remove = geni_i2c_remove,
+   .shutdown = geni_i2c_shutdown,
.driver = {
.name = "geni_i2c",
.pm = _i2c_pm_ops,
diff --git a/include/linux/qcom-geni-se.h 
b/include/linux/qcom-geni-se.h

index dd464943f717..c3c016496d98 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -77,6 +77,7 @@ struct geni_se {
  #define SE_DMA_RX_FSM_RST 0xd58
  #define SE_HW_PARAM_0 0xe24
  #define SE_HW_PARAM_1 0xe28
+#define SE_DMA_DEBUG_REG0  0xe40
/* GENI_FORCE_DEFAULT_REG fields */
  #define FORCE_DEFAULT BIT(0)
@@ -207,6 +208,10 @@ struct geni_se {
  #define RX_GENI_CANCEL_IRQBIT(11)
  #define RX_GENI_GP_IRQ_EXTGENMASK(13, 12)
  +/* SE_DMA_DEBUG_REG0 Register fields */
+#define DMA_TX_ACTIVE  BIT(0)
+#define DMA_RX_ACTIVE  BIT(1)
+
  /* SE_HW_PARAM_0 fields */
  #define TX_FIFO_WIDTH_MSK GENMASK(29, 24)
  #define TX_FIFO_WIDTH_SHFT24


Re: [PATCH V2 1/2] i2c: i2c-qcom-geni: Store DMA mapping data in geni_i2c_dev struct

2020-09-07 Thread rojay

On 2020-08-26 17:25, Akash Asthana wrote:

Hi Roja,

On 8/20/2020 4:05 PM, Roja Rani Yarubandi wrote:

Store DMA mapping data in geni_i2c_dev struct to enhance DMA mapping
data scope. For example during shutdown callback to unmap DMA mapping,
this stored DMA mapping data can be used to call geni_se_tx_dma_unprep
and geni_se_rx_dma_unprep functions.

Signed-off-by: Roja Rani Yarubandi 
---
Changes in V2:
  - As per Stephen's comments, changed commit text, fixed minor 
nitpicks.


  drivers/i2c/busses/i2c-qcom-geni.c | 7 +++
  1 file changed, 7 insertions(+)

diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index 7f130829bf01..1fda5c7c2cfc 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -86,6 +86,9 @@ struct geni_i2c_dev {
u32 clk_freq_out;
const struct geni_i2c_clk_fld *clk_fld;
int suspended;
+   dma_addr_t tx_dma;
+   dma_addr_t rx_dma;
+   size_t xfer_len;
  };
struct geni_i2c_err_log {
@@ -358,6 +361,7 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev 
*gi2c, struct i2c_msg *msg,

struct geni_se *se = >se;
size_t len = msg->len;
  + gi2c->xfer_len = msg->len;


nit: gi2c->xfer = len, for tx_one_msg as well.

Regards,

Akash



Okay


if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
  @@ -384,6 +388,7 @@ static int geni_i2c_rx_one_msg(struct 
geni_i2c_dev *gi2c, struct i2c_msg *msg,

if (dma_buf) {
if (gi2c->err)
geni_i2c_rx_fsm_rst(gi2c);
+   gi2c->rx_dma = rx_dma;
geni_se_rx_dma_unprep(se, rx_dma, len);
i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
}
@@ -400,6 +405,7 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev 
*gi2c, struct i2c_msg *msg,

struct geni_se *se = >se;
size_t len = msg->len;
  + gi2c->xfer_len = msg->len;
if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);
  @@ -429,6 +435,7 @@ static int geni_i2c_tx_one_msg(struct 
geni_i2c_dev *gi2c, struct i2c_msg *msg,

if (dma_buf) {
if (gi2c->err)
geni_i2c_tx_fsm_rst(gi2c);
+   gi2c->tx_dma = tx_dma;
geni_se_tx_dma_unprep(se, tx_dma, len);
i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
}


Re: [PATCH V2 2/2] i2c: i2c-qcom-geni: Add shutdown callback for i2c

2020-08-28 Thread rojay

On 2020-08-21 05:52, Stephen Boyd wrote:

Quoting Roja Rani Yarubandi (2020-08-20 03:35:22)

If the hardware is still accessing memory after SMMU translation
is disabled (as part of smmu shutdown callback), then the
IOVAs (I/O virtual address) which it was using will go on the bus
as the physical addresses which will result in unknown crashes
like NoC/interconnect errors.

So, implement shutdown callback to i2c driver to unmap DMA mappings
during system "reboot" or "shutdown".

Signed-off-by: Roja Rani Yarubandi 
---


I'd still put a Fixes tag because it's fixing the driver when someone
runs shutdown.



Okay, will add fixes tag.


Changes in V2:
 - As per Stephen's comments added seperate function for stop 
transfer,

   fixed minor nitpicks.

 drivers/i2c/busses/i2c-qcom-geni.c | 43 
++

 include/linux/qcom-geni-se.h   |  5 
 2 files changed, 48 insertions(+)

diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index 1fda5c7c2cfc..d07f2f33bb75 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -486,6 +486,28 @@ static int geni_i2c_xfer(struct i2c_adapter 
*adap,

return ret;
 }

+static void geni_i2c_stop_xfer(struct geni_i2c_dev *gi2c)
+{
+   u32 val;
+   struct geni_se *se = >se;
+
+   val = readl_relaxed(gi2c->se.base + SE_DMA_DEBUG_REG0);
+   if (val & DMA_TX_ACTIVE) {
+   geni_i2c_abort_xfer(gi2c);
+   gi2c->cur_wr = 0;
+   if (gi2c->err)
+   geni_i2c_tx_fsm_rst(gi2c);
+   geni_se_tx_dma_unprep(se, gi2c->tx_dma, 
gi2c->xfer_len);

+   }
+   if (val & DMA_RX_ACTIVE) {
+   geni_i2c_abort_xfer(gi2c);
+   gi2c->cur_rd = 0;
+   if (gi2c->err)
+   geni_i2c_rx_fsm_rst(gi2c);
+   geni_se_rx_dma_unprep(se, gi2c->rx_dma, 
gi2c->xfer_len);

+   }
+}
+
 static u32 geni_i2c_func(struct i2c_adapter *adap)
 {
return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & 
~I2C_FUNC_SMBUS_QUICK);
@@ -617,6 +639,26 @@ static int geni_i2c_remove(struct platform_device 
*pdev)

return 0;
 }

+static void geni_i2c_shutdown(struct platform_device *pdev)
+{
+   int ret;
+   u32 dma;
+   struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
+   struct geni_se *se = >se;
+
+   ret = pm_runtime_get_sync(gi2c->se.dev);
+   if (ret < 0) {
+   dev_err(gi2c->se.dev, "Failed to resume device: %d\n", 
ret);

+   return;
+   }
+
+   dma = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
+   if (dma)
+   geni_i2c_stop_xfer(gi2c);


Any reason the if (dma) check isn't inside geni_i2c_stop_xfer()?
Checking for dma and then bailing out early should work and keep the
logic in one function. Then the pm_runtime_sync() call could go in 
there

too and if (!dma) goto out. This assumes that we're going to call
geni_i2c_stop_xfer() from somewhere else, like if a transfer times out
or something?



Okay, will do the changes.


+
+   pm_runtime_put_sync_suspend(gi2c->se.dev);
+}
+
 static int __maybe_unused geni_i2c_runtime_suspend(struct device 
*dev)

 {
int ret;


Re: [PATCH V2 1/2] i2c: i2c-qcom-geni: Store DMA mapping data in geni_i2c_dev struct

2020-08-28 Thread rojay

On 2020-08-21 05:48, Stephen Boyd wrote:

Quoting Roja Rani Yarubandi (2020-08-20 03:35:21)

Store DMA mapping data in geni_i2c_dev struct to enhance DMA mapping
data scope. For example during shutdown callback to unmap DMA mapping,
this stored DMA mapping data can be used to call geni_se_tx_dma_unprep
and geni_se_rx_dma_unprep functions.

Signed-off-by: Roja Rani Yarubandi 
---


Can this be squashed with the next patch? I don't see how this stands 
on

its own.


Okay.


Re: [PATCH 2/2] i2c: i2c-qcom-geni: Add shutdown callback for i2c

2020-08-20 Thread rojay

On 2020-08-19 09:13, Stephen Boyd wrote:

Quoting Roja Rani Yarubandi (2020-08-14 02:55:40)

If the hardware is still accessing memory after SMMU translation
is disabled(as part of smmu shutdown callback), then the


Put a space before (



Ok.


IOVAs(I/O virtual address) which it was using will go on the bus


Put a space before (


as the physical addresses which will result in unknown crashes
like NoC/interconnect errors.

So, adding shutdown callback to i2c driver to unmap DMA mappings
during system "reboot" or "shutdown".



Deserves a Fixes: tag if it's fixing a problem, which it looks like it
is.



It is not fixing a problem. We are anticipating a problem and 
implementing

Shutdown callback.


Signed-off-by: Roja Rani Yarubandi 
---
 drivers/i2c/busses/i2c-qcom-geni.c | 36 
++

 include/linux/qcom-geni-se.h   |  5 +


I'd prefer this is squashed with the previous patch. The first patch
doesn't really stand on its own anyway.



Sorry, I did not understand.
First patch can be compiled independently.


 2 files changed, 41 insertions(+)

diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index 53ca41f76080..749c225f95c4 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -613,6 +613,41 @@ static int geni_i2c_remove(struct platform_device 
*pdev)

return 0;
 }

+static void geni_i2c_shutdown(struct platform_device *pdev)
+{
+   int ret;
+   struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev);
+   struct geni_se *se = >se;
+   u32 dma;
+   u32 dma_dbg_reg;


Typically this is just called 'val'.



Ok.


+
+   ret = pm_runtime_get_sync(gi2c->se.dev);
+   if (ret < 0) {
+   dev_err(gi2c->se.dev, "Failed to resume device:%d\n", 
ret);


Maybe just write: "Failed to resume device\n"? Not sure anyone cares
what the error code is. And if they did, it would be connected to the
colon so it will be hard to read. Add a space after colon if you want 
to

keep the return value please.



Ok, will add space after colon.


+   return;
+   }
+
+   dma = readl_relaxed(se->base + SE_GENI_DMA_MODE_EN);
+   if (dma) {
+   dma_dbg_reg = readl_relaxed(gi2c->se.base + 
SE_DMA_DEBUG_REG0);

+   if (dma_dbg_reg & DMA_TX_ACTIVE) {
+   geni_i2c_abort_xfer(gi2c);
+   gi2c->cur_wr = 0;
+   if (gi2c->err)
+   geni_i2c_tx_fsm_rst(gi2c);
+   geni_se_tx_dma_unprep(se, gi2c->tx_dma, 
gi2c->xfer_len);

+   }
+   if (dma_dbg_reg & DMA_RX_ACTIVE) {
+   geni_i2c_abort_xfer(gi2c);
+   gi2c->cur_rd = 0;
+   if (gi2c->err)
+   geni_i2c_rx_fsm_rst(gi2c);
+   geni_se_rx_dma_unprep(se, gi2c->rx_dma, 
gi2c->xfer_len);

+   }


Can this be a function? It sort of seems like we should be doing the
same sort of stuff if we're canceling a DMA transaction in flight.



Ok. Will make the changes.


+   }
+   pm_runtime_put_sync_suspend(gi2c->se.dev);
+}
+
 static int __maybe_unused geni_i2c_runtime_suspend(struct device 
*dev)

 {
int ret;
diff --git a/include/linux/qcom-geni-se.h 
b/include/linux/qcom-geni-se.h

index dd464943f717..acad69be747d 100644
--- a/include/linux/qcom-geni-se.h
+++ b/include/linux/qcom-geni-se.h
@@ -77,6 +77,7 @@ struct geni_se {
 #define SE_DMA_RX_FSM_RST  0xd58
 #define SE_HW_PARAM_0  0xe24
 #define SE_HW_PARAM_1  0xe28
+#define SE_DMA_DEBUG_REG0  0xe40

 /* GENI_FORCE_DEFAULT_REG fields */
 #define FORCE_DEFAULT  BIT(0)
@@ -207,6 +208,10 @@ struct geni_se {
 #define RX_GENI_CANCEL_IRQ BIT(11)
 #define RX_GENI_GP_IRQ_EXT GENMASK(13, 12)

+/* DMA DEBUG Register fields */


Please follow other style, ie. SE_DMA_DEBUG_REG0 fields



Ok.


+#define DMA_TX_ACTIVE  BIT(0)
+#define DMA_RX_ACTIVE  BIT(1)
+
 /* SE_HW_PARAM_0 fields */
 #define TX_FIFO_WIDTH_MSK  GENMASK(29, 24)
 #define TX_FIFO_WIDTH_SHFT 24


Re: [PATCH 1/2] i2c: i2c-qcom-geni: Add tx_dma, rx_dma and xfer_len to geni_i2c_dev struct

2020-08-20 Thread rojay

Hi Stephen,

Thanks for reviewing the patches.

On 2020-08-19 09:09, Stephen Boyd wrote:

Quoting Roja Rani Yarubandi (2020-08-14 02:55:39)

Adding tx_dma, rx_dma and xfer length in geni_i2c_dev struct to
store DMA mapping data to enhance its scope. For example during
shutdown callback to unmap DMA mapping, these new struct members
can be used as part of geni_se_tx_dma_unprep and
geni_se_rx_dma_unprep calls.


Please read about how to write commit text from kernel docs[1]. Hint,
use imperative mood.



Ok, will update the commit text.



Signed-off-by: Roja Rani Yarubandi 
---
 drivers/i2c/busses/i2c-qcom-geni.c | 23 +--
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/drivers/i2c/busses/i2c-qcom-geni.c 
b/drivers/i2c/busses/i2c-qcom-geni.c

index 7f130829bf01..53ca41f76080 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -86,6 +86,9 @@ struct geni_i2c_dev {
u32 clk_freq_out;
const struct geni_i2c_clk_fld *clk_fld;
int suspended;
+   dma_addr_t tx_dma;
+   dma_addr_t rx_dma;
+   u32 xfer_len;


Why not size_t?



Will change it to size_t.


 };

 struct geni_i2c_err_log {
@@ -352,12 +355,11 @@ static void geni_i2c_tx_fsm_rst(struct 
geni_i2c_dev *gi2c)
 static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct 
i2c_msg *msg,

u32 m_param)
 {
-   dma_addr_t rx_dma;
unsigned long time_left;
void *dma_buf = NULL;
struct geni_se *se = >se;
-   size_t len = msg->len;

+   gi2c->xfer_len = msg->len;


I'd prefer to keep the local variable and then have

len = gi2c->xfer_len = msg->len;



Ok, will keep the local variable.


if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);

@@ -366,9 +368,10 @@ static int geni_i2c_rx_one_msg(struct 
geni_i2c_dev *gi2c, struct i2c_msg *msg,

else
geni_se_select_mode(se, GENI_SE_FIFO);

-   writel_relaxed(len, se->base + SE_I2C_RX_TRANS_LEN);
+   writel_relaxed(gi2c->xfer_len, se->base + 
SE_I2C_RX_TRANS_LEN);


So that all this doesn't have to change.



-   if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, len, _dma)) 
{
+   if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, 
gi2c->xfer_len,

+  >rx_dma)) {
geni_se_select_mode(se, GENI_SE_FIFO);
i2c_put_dma_safe_msg_buf(dma_buf, msg, false);
dma_buf = NULL;
@@ -384,7 +387,7 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev 
*gi2c, struct i2c_msg *msg,

if (dma_buf) {
if (gi2c->err)
geni_i2c_rx_fsm_rst(gi2c);
-   geni_se_rx_dma_unprep(se, rx_dma, len);
+   geni_se_rx_dma_unprep(se, gi2c->rx_dma, 
gi2c->xfer_len);

i2c_put_dma_safe_msg_buf(dma_buf, msg, !gi2c->err);
}

@@ -394,12 +397,11 @@ static int geni_i2c_rx_one_msg(struct 
geni_i2c_dev *gi2c, struct i2c_msg *msg,
 static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct 
i2c_msg *msg,

u32 m_param)
 {
-   dma_addr_t tx_dma;
unsigned long time_left;
void *dma_buf = NULL;
struct geni_se *se = >se;
-   size_t len = msg->len;

+   gi2c->xfer_len = msg->len;


Same comment.



Ok.


if (!of_machine_is_compatible("lenovo,yoga-c630"))
dma_buf = i2c_get_dma_safe_msg_buf(msg, 32);



[1]
https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes


Thanks,
Roja