Re: macb broken on HiFive Unleashed

2021-03-13 Thread Emil Renner Berthing
Hi Andreas

On Wed, 10 Mar 2021 at 20:55, Andreas Schwab  wrote:
> On Mär 09 2021, claudiu.bez...@microchip.com wrote:
> > I don't have a SiFive HiFive Unleashed to investigate this. Can you check
> > if reverting commits on macb driver b/w 5.10 and 5.11 solves your issues:
> >
> > git log --oneline v5.10..v5.11 -- drivers/net/ethernet/cadence/
> > 1d0d561ad1d7 net: macb: Correct usage of MACB_CAPS_CLK_HW_CHG flag
> > 1d608d2e0d51 Revert "macb: support the two tx descriptors on at91rm9200"
> > 700d566e8171 net: macb: add support for sama7g5 emac interface
> > ec771de654e4 net: macb: add support for sama7g5 gem interface
> > f4de93f03ed8 net: macb: unprepare clocks in case of failure
> > 38493da4e6a8 net: macb: add function to disable all macb clocks
> > daafa1d33cc9 net: macb: add capability to not set the clock rate
> > edac63861db7 net: macb: add userio bits as platform configuration
> > 9e6cad531c9d net: macb: Fix passing zero to 'PTR_ERR'
> > 0012eeb370f8 net: macb: fix NULL dereference due to no pcs_config method
> > e4e143e26ce8 net: macb: add support for high speed interface
>
> Unfortunately, that didn't help.

Sorry, for being late to test this, but I just compiled and booted
5.11.6 and ethernet works just fine for me:
https://esmil.dk/hfu-5.11.6.txt

As you can see I haven't updated OpenSBI or u-boot in a while, don't
know if that makes a difference. You can fetch the config is used
here:
https://esmil.dk/hfu-5.11.6.config

/Emil


Re: [PATCH] spi: rockchip: avoid objtool warning

2021-02-25 Thread Emil Renner Berthing
On Thu, 25 Feb 2021 at 13:55, Arnd Bergmann  wrote:
>
> From: Arnd Bergmann 
>
> Building this file with clang leads to a an unreachable code path
> causing a warning from objtool:
>
> drivers/spi/spi-rockchip.o: warning: objtool: 
> rockchip_spi_transfer_one()+0x2e0: sibling call from callable instruction 
> with modified stack frame
>
> Use BUG() instead of unreachable() to avoid the undefined behavior
> if it does happen.
>
> Fixes: 65498c6ae241 ("spi: rockchip: support 4bit words")
> Signed-off-by: Arnd Bergmann 

Acked-by: Emil Renner Berthing 

> ---
>  drivers/spi/spi-rockchip.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
> index 936ef54e0903..972beac1169a 100644
> --- a/drivers/spi/spi-rockchip.c
> +++ b/drivers/spi/spi-rockchip.c
> @@ -521,7 +521,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
>  * ctlr->bits_per_word_mask, so this shouldn't
>  * happen
>  */
> -   unreachable();
> +   BUG();
> }
>
> if (use_dma) {
> --
> 2.29.2
>


[tip: irq/core] genirq: Use new tasklet API for resend_tasklet

2021-02-15 Thread tip-bot2 for Emil Renner Berthing
The following commit has been merged into the irq/core branch of tip:

Commit-ID: c260954177c4f1926b423823bca5728f19b40d67
Gitweb:
https://git.kernel.org/tip/c260954177c4f1926b423823bca5728f19b40d67
Author:Emil Renner Berthing 
AuthorDate:Sat, 23 Jan 2021 19:24:56 +01:00
Committer: Thomas Gleixner 
CommitterDate: Thu, 28 Jan 2021 11:18:04 +01:00

genirq: Use new tasklet API for resend_tasklet

This converts the resend_tasklet to use the new API in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

The new API changes the argument passed to the callback function, but
fortunately the argument isn't used so it is straight forward to use
DECLARE_TASKLET() rather than DECLARE_TASKLET_OLD().

Signed-off-by: Emil Renner Berthing 
Signed-off-by: Thomas Gleixner 
Link: https://lore.kernel.org/r/20210123182456.6521-1-es...@mailme.dk

---
 kernel/irq/resend.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 8ccd32a..bd1d85c 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -27,7 +27,7 @@ static DECLARE_BITMAP(irqs_resend, IRQ_BITMAP_BITS);
 /*
  * Run software resends of IRQ's
  */
-static void resend_irqs(unsigned long arg)
+static void resend_irqs(struct tasklet_struct *unused)
 {
struct irq_desc *desc;
int irq;
@@ -45,7 +45,7 @@ static void resend_irqs(unsigned long arg)
 }
 
 /* Tasklet to handle resend: */
-static DECLARE_TASKLET_OLD(resend_tasklet, resend_irqs);
+static DECLARE_TASKLET(resend_tasklet, resend_irqs);
 
 static int irq_sw_resend(struct irq_desc *desc)
 {


[PATCH] mmc: cb710: Use new tasklet API

2021-02-08 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/cb710-mmc.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c
index e84ed84ea4cc..6d623b2681c3 100644
--- a/drivers/mmc/host/cb710-mmc.c
+++ b/drivers/mmc/host/cb710-mmc.c
@@ -646,14 +646,14 @@ static int cb710_mmc_irq_handler(struct cb710_slot *slot)
return 1;
 }
 
-static void cb710_mmc_finish_request_tasklet(unsigned long data)
+static void cb710_mmc_finish_request_tasklet(struct tasklet_struct *t)
 {
-   struct mmc_host *mmc = (void *)data;
-   struct cb710_mmc_reader *reader = mmc_priv(mmc);
+   struct cb710_mmc_reader *reader = from_tasklet(reader, t,
+  finish_req_tasklet);
struct mmc_request *mrq = reader->mrq;
 
reader->mrq = NULL;
-   mmc_request_done(mmc, mrq);
+   mmc_request_done(mmc_from_priv(reader), mrq);
 }
 
 static const struct mmc_host_ops cb710_mmc_host = {
@@ -718,8 +718,8 @@ static int cb710_mmc_init(struct platform_device *pdev)
 
reader = mmc_priv(mmc);
 
-   tasklet_init(&reader->finish_req_tasklet,
-   cb710_mmc_finish_request_tasklet, (unsigned long)mmc);
+   tasklet_setup(&reader->finish_req_tasklet,
+ cb710_mmc_finish_request_tasklet);
spin_lock_init(&reader->irq_lock);
cb710_dump_regs(chip, CB710_DUMP_REGS_MMC);
 
-- 
2.30.0



[PATCH] net: wan: farsync: use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

The new API changes the argument passed to callback functions,
but fortunately it is unused so it is straight forward to use
DECLARE_TASKLET rather than DECLARE_TASLKLET_OLD.

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/wan/farsync.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index b50cf11d197d..686a25d3b512 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -566,11 +566,11 @@ MODULE_DEVICE_TABLE(pci, fst_pci_dev_id);
 
 static void do_bottom_half_tx(struct fst_card_info *card);
 static void do_bottom_half_rx(struct fst_card_info *card);
-static void fst_process_tx_work_q(unsigned long work_q);
-static void fst_process_int_work_q(unsigned long work_q);
+static void fst_process_tx_work_q(struct tasklet_struct *unused);
+static void fst_process_int_work_q(struct tasklet_struct *unused);
 
-static DECLARE_TASKLET_OLD(fst_tx_task, fst_process_tx_work_q);
-static DECLARE_TASKLET_OLD(fst_int_task, fst_process_int_work_q);
+static DECLARE_TASKLET(fst_tx_task, fst_process_tx_work_q);
+static DECLARE_TASKLET(fst_int_task, fst_process_int_work_q);
 
 static struct fst_card_info *fst_card_array[FST_MAX_CARDS];
 static spinlock_t fst_work_q_lock;
@@ -600,7 +600,7 @@ fst_q_work_item(u64 * queue, int card_index)
 }
 
 static void
-fst_process_tx_work_q(unsigned long /*void **/work_q)
+fst_process_tx_work_q(struct tasklet_struct *unused)
 {
unsigned long flags;
u64 work_txq;
@@ -630,7 +630,7 @@ fst_process_tx_work_q(unsigned long /*void **/work_q)
 }
 
 static void
-fst_process_int_work_q(unsigned long /*void **/work_q)
+fst_process_int_work_q(struct tasklet_struct *unused)
 {
unsigned long flags;
u64 work_intq;
-- 
2.30.0



[PATCH 3/9] mmc: dw_mmc: Use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/dw_mmc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index a5244435556b..2f4de30f650b 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1952,9 +1952,9 @@ static bool dw_mci_clear_pending_data_complete(struct 
dw_mci *host)
return true;
 }
 
-static void dw_mci_tasklet_func(unsigned long priv)
+static void dw_mci_tasklet_func(struct tasklet_struct *t)
 {
-   struct dw_mci *host = (struct dw_mci *)priv;
+   struct dw_mci *host = from_tasklet(host, t, tasklet);
struct mmc_data *data;
struct mmc_command *cmd;
struct mmc_request *mrq;
@@ -3308,7 +3308,7 @@ int dw_mci_probe(struct dw_mci *host)
else
host->fifo_reg = host->regs + DATA_240A_OFFSET;
 
-   tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host);
+   tasklet_setup(&host->tasklet, dw_mci_tasklet_func);
ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt,
   host->irq_flags, "dw-mci", host);
if (ret)
-- 
2.30.0



[PATCH 4/9] mmc: omap: Use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/omap.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 6aa0537f1f84..5e5af34090f1 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -878,9 +878,9 @@ static void mmc_omap_cover_timer(struct timer_list *t)
tasklet_schedule(&slot->cover_tasklet);
 }
 
-static void mmc_omap_cover_handler(unsigned long param)
+static void mmc_omap_cover_handler(struct tasklet_struct *t)
 {
-   struct mmc_omap_slot *slot = (struct mmc_omap_slot *)param;
+   struct mmc_omap_slot *slot = from_tasklet(slot, t, cover_tasklet);
int cover_open = mmc_omap_cover_is_open(slot);
 
mmc_detect_change(slot->mmc, 0);
@@ -1269,8 +1269,7 @@ static int mmc_omap_new_slot(struct mmc_omap_host *host, 
int id)
 
if (slot->pdata->get_cover_state != NULL) {
timer_setup(&slot->cover_timer, mmc_omap_cover_timer, 0);
-   tasklet_init(&slot->cover_tasklet, mmc_omap_cover_handler,
-(unsigned long)slot);
+   tasklet_setup(&slot->cover_tasklet, mmc_omap_cover_handler);
}
 
r = mmc_add_host(mmc);
-- 
2.30.0



[PATCH 7/9] mmc: uniphier-sd: Use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/uniphier-sd.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c
index a6cd16771d4e..2413b6750cec 100644
--- a/drivers/mmc/host/uniphier-sd.c
+++ b/drivers/mmc/host/uniphier-sd.c
@@ -81,9 +81,9 @@ static void uniphier_sd_dma_endisable(struct tmio_mmc_host 
*host, int enable)
 }
 
 /* external DMA engine */
-static void uniphier_sd_external_dma_issue(unsigned long arg)
+static void uniphier_sd_external_dma_issue(struct tasklet_struct *t)
 {
-   struct tmio_mmc_host *host = (void *)arg;
+   struct tmio_mmc_host *host = from_tasklet(host, t, dma_issue);
struct uniphier_sd_priv *priv = uniphier_sd_priv(host);
 
uniphier_sd_dma_endisable(host, 1);
@@ -190,8 +190,7 @@ static void uniphier_sd_external_dma_request(struct 
tmio_mmc_host *host,
host->chan_rx = chan;
host->chan_tx = chan;
 
-   tasklet_init(&host->dma_issue, uniphier_sd_external_dma_issue,
-(unsigned long)host);
+   tasklet_setup(&host->dma_issue, uniphier_sd_external_dma_issue);
 }
 
 static void uniphier_sd_external_dma_release(struct tmio_mmc_host *host)
@@ -228,9 +227,9 @@ static const struct tmio_mmc_dma_ops 
uniphier_sd_external_dma_ops = {
.dataend = uniphier_sd_external_dma_dataend,
 };
 
-static void uniphier_sd_internal_dma_issue(unsigned long arg)
+static void uniphier_sd_internal_dma_issue(struct tasklet_struct *t)
 {
-   struct tmio_mmc_host *host = (void *)arg;
+   struct tmio_mmc_host *host = from_tasklet(host, t, dma_issue);
unsigned long flags;
 
spin_lock_irqsave(&host->lock, flags);
@@ -309,8 +308,7 @@ static void uniphier_sd_internal_dma_request(struct 
tmio_mmc_host *host,
 
host->chan_tx = (void *)0xdeadbeaf;
 
-   tasklet_init(&host->dma_issue, uniphier_sd_internal_dma_issue,
-(unsigned long)host);
+   tasklet_setup(&host->dma_issue, uniphier_sd_internal_dma_issue);
 }
 
 static void uniphier_sd_internal_dma_release(struct tmio_mmc_host *host)
-- 
2.30.0



[PATCH 8/9] mmc: via-sdmmc: Use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/via-sdmmc.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c
index 9b755ea0fa03..4f4c0813f9fd 100644
--- a/drivers/mmc/host/via-sdmmc.c
+++ b/drivers/mmc/host/via-sdmmc.c
@@ -959,14 +959,12 @@ static void via_sdc_timeout(struct timer_list *t)
spin_unlock_irqrestore(&sdhost->lock, flags);
 }
 
-static void via_sdc_tasklet_finish(unsigned long param)
+static void via_sdc_tasklet_finish(struct tasklet_struct *t)
 {
-   struct via_crdr_mmc_host *host;
+   struct via_crdr_mmc_host *host = from_tasklet(host, t, finish_tasklet);
unsigned long flags;
struct mmc_request *mrq;
 
-   host = (struct via_crdr_mmc_host *)param;
-
spin_lock_irqsave(&host->lock, flags);
 
del_timer(&host->timer);
@@ -1050,8 +1048,7 @@ static void via_init_mmc_host(struct via_crdr_mmc_host 
*host)
 
INIT_WORK(&host->carddet_work, via_sdc_card_detect);
 
-   tasklet_init(&host->finish_tasklet, via_sdc_tasklet_finish,
-(unsigned long)host);
+   tasklet_setup(&host->finish_tasklet, via_sdc_tasklet_finish);
 
addrbase = host->sdhc_mmiobase;
writel(0x0, addrbase + VIA_CRDR_SDINTMASK);
-- 
2.30.0



[PATCH 9/9] mmc: wbsd: Use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/wbsd.c | 35 +++
 1 file changed, 15 insertions(+), 20 deletions(-)

diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c
index cd63ea865b77..67ecd342fe5f 100644
--- a/drivers/mmc/host/wbsd.c
+++ b/drivers/mmc/host/wbsd.c
@@ -987,9 +987,9 @@ static inline struct mmc_data *wbsd_get_data(struct 
wbsd_host *host)
return host->mrq->cmd->data;
 }
 
-static void wbsd_tasklet_card(unsigned long param)
+static void wbsd_tasklet_card(struct tasklet_struct *t)
 {
-   struct wbsd_host *host = (struct wbsd_host *)param;
+   struct wbsd_host *host = from_tasklet(host, t, card_tasklet);
u8 csr;
int delay = -1;
 
@@ -1036,9 +1036,9 @@ static void wbsd_tasklet_card(unsigned long param)
mmc_detect_change(host->mmc, msecs_to_jiffies(delay));
 }
 
-static void wbsd_tasklet_fifo(unsigned long param)
+static void wbsd_tasklet_fifo(struct tasklet_struct *t)
 {
-   struct wbsd_host *host = (struct wbsd_host *)param;
+   struct wbsd_host *host = from_tasklet(host, t, fifo_tasklet);
struct mmc_data *data;
 
spin_lock(&host->lock);
@@ -1067,9 +1067,9 @@ static void wbsd_tasklet_fifo(unsigned long param)
spin_unlock(&host->lock);
 }
 
-static void wbsd_tasklet_crc(unsigned long param)
+static void wbsd_tasklet_crc(struct tasklet_struct *t)
 {
-   struct wbsd_host *host = (struct wbsd_host *)param;
+   struct wbsd_host *host = from_tasklet(host, t, crc_tasklet);
struct mmc_data *data;
 
spin_lock(&host->lock);
@@ -1091,9 +1091,9 @@ static void wbsd_tasklet_crc(unsigned long param)
spin_unlock(&host->lock);
 }
 
-static void wbsd_tasklet_timeout(unsigned long param)
+static void wbsd_tasklet_timeout(struct tasklet_struct *t)
 {
-   struct wbsd_host *host = (struct wbsd_host *)param;
+   struct wbsd_host *host = from_tasklet(host, t, timeout_tasklet);
struct mmc_data *data;
 
spin_lock(&host->lock);
@@ -1115,9 +1115,9 @@ static void wbsd_tasklet_timeout(unsigned long param)
spin_unlock(&host->lock);
 }
 
-static void wbsd_tasklet_finish(unsigned long param)
+static void wbsd_tasklet_finish(struct tasklet_struct *t)
 {
-   struct wbsd_host *host = (struct wbsd_host *)param;
+   struct wbsd_host *host = from_tasklet(host, t, finish_tasklet);
struct mmc_data *data;
 
spin_lock(&host->lock);
@@ -1449,16 +1449,11 @@ static int wbsd_request_irq(struct wbsd_host *host, int 
irq)
/*
 * Set up tasklets. Must be done before requesting interrupt.
 */
-   tasklet_init(&host->card_tasklet, wbsd_tasklet_card,
-   (unsigned long)host);
-   tasklet_init(&host->fifo_tasklet, wbsd_tasklet_fifo,
-   (unsigned long)host);
-   tasklet_init(&host->crc_tasklet, wbsd_tasklet_crc,
-   (unsigned long)host);
-   tasklet_init(&host->timeout_tasklet, wbsd_tasklet_timeout,
-   (unsigned long)host);
-   tasklet_init(&host->finish_tasklet, wbsd_tasklet_finish,
-   (unsigned long)host);
+   tasklet_setup(&host->card_tasklet, wbsd_tasklet_card);
+   tasklet_setup(&host->fifo_tasklet, wbsd_tasklet_fifo);
+   tasklet_setup(&host->crc_tasklet, wbsd_tasklet_crc);
+   tasklet_setup(&host->timeout_tasklet, wbsd_tasklet_timeout);
+   tasklet_setup(&host->finish_tasklet, wbsd_tasklet_finish);
 
/*
 * Allocate interrupt.
-- 
2.30.0



[PATCH 5/9] mmc: s3cmci: Use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/s3cmci.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index a33a7823c265..0ca6f6d30b75 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -540,9 +540,9 @@ static void do_pio_write(struct s3cmci_host *host)
enable_imask(host, S3C2410_SDIIMSK_TXFIFOHALF);
 }
 
-static void pio_tasklet(unsigned long data)
+static void pio_tasklet(struct tasklet_struct *t)
 {
-   struct s3cmci_host *host = (struct s3cmci_host *) data;
+   struct s3cmci_host *host = from_tasklet(host, t, pio_tasklet);
 
s3cmci_disable_irq(host, true);
 
@@ -1532,7 +1532,7 @@ static int s3cmci_probe(struct platform_device *pdev)
host->pdata = pdev->dev.platform_data;
 
spin_lock_init(&host->complete_lock);
-   tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
+   tasklet_setup(&host->pio_tasklet, pio_tasklet);
 
if (host->is2440) {
host->sdiimsk   = S3C2440_SDIIMSK;
-- 
2.30.0



[PATCH 6/9] mmc: tifm_sd: Use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/tifm_sd.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c
index fd8b72d3e02c..9fdf7ea06e3f 100644
--- a/drivers/mmc/host/tifm_sd.c
+++ b/drivers/mmc/host/tifm_sd.c
@@ -731,9 +731,9 @@ static void tifm_sd_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
mmc_request_done(mmc, mrq);
 }
 
-static void tifm_sd_end_cmd(unsigned long data)
+static void tifm_sd_end_cmd(struct tasklet_struct *t)
 {
-   struct tifm_sd *host = (struct tifm_sd*)data;
+   struct tifm_sd *host = from_tasklet(host, t, finish_tasklet);
struct tifm_dev *sock = host->dev;
struct mmc_host *mmc = tifm_get_drvdata(sock);
struct mmc_request *mrq;
@@ -968,8 +968,7 @@ static int tifm_sd_probe(struct tifm_dev *sock)
 */
mmc->max_busy_timeout = TIFM_MMCSD_REQ_TIMEOUT_MS;
 
-   tasklet_init(&host->finish_tasklet, tifm_sd_end_cmd,
-(unsigned long)host);
+   tasklet_setup(&host->finish_tasklet, tifm_sd_end_cmd);
timer_setup(&host->timer, tifm_sd_abort, 0);
 
mmc->ops = &tifm_sd_ops;
-- 
2.30.0



[PATCH 2/9] mmc: au1xmmc: Use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/au1xmmc.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c
index bd00515fbaba..0acc237843f7 100644
--- a/drivers/mmc/host/au1xmmc.c
+++ b/drivers/mmc/host/au1xmmc.c
@@ -253,9 +253,9 @@ static void au1xmmc_finish_request(struct au1xmmc_host 
*host)
mmc_request_done(host->mmc, mrq);
 }
 
-static void au1xmmc_tasklet_finish(unsigned long param)
+static void au1xmmc_tasklet_finish(struct tasklet_struct *t)
 {
-   struct au1xmmc_host *host = (struct au1xmmc_host *) param;
+   struct au1xmmc_host *host = from_tasklet(host, t, finish_task);
au1xmmc_finish_request(host);
 }
 
@@ -363,9 +363,9 @@ static void au1xmmc_data_complete(struct au1xmmc_host 
*host, u32 status)
au1xmmc_finish_request(host);
 }
 
-static void au1xmmc_tasklet_data(unsigned long param)
+static void au1xmmc_tasklet_data(struct tasklet_struct *t)
 {
-   struct au1xmmc_host *host = (struct au1xmmc_host *)param;
+   struct au1xmmc_host *host = from_tasklet(host, t, data_task);
 
u32 status = __raw_readl(HOST_STATUS(host));
au1xmmc_data_complete(host, status);
@@ -1037,11 +1037,9 @@ static int au1xmmc_probe(struct platform_device *pdev)
if (host->platdata)
mmc->caps &= ~(host->platdata->mask_host_caps);
 
-   tasklet_init(&host->data_task, au1xmmc_tasklet_data,
-   (unsigned long)host);
+   tasklet_setup(&host->data_task, au1xmmc_tasklet_data);
 
-   tasklet_init(&host->finish_task, au1xmmc_tasklet_finish,
-   (unsigned long)host);
+   tasklet_setup(&host->finish_task, au1xmmc_tasklet_finish);
 
if (has_dbdma()) {
ret = au1xmmc_dbdma_init(host);
-- 
2.30.0



[PATCH 0/9] drivers: mmc: Update trivial tasklet_init() callers

2021-02-04 Thread Emil Renner Berthing
This updates callers of tasklet_init() in drivers/mmc to the new API
in commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

All changes are made by coccinelle using the following semantic patch:

@ match @
type T;
T *container;
identifier tasklet;
identifier callback;
@@
tasklet_init(&container->tasklet, callback, (unsigned long)container);

@ patch1 depends on match @
type match.T;
identifier match.tasklet;
identifier match.callback;
identifier data;
identifier container;
@@
-void callback(unsigned long data)
+void callback(struct tasklet_struct *t)
{
...
-   T *container = \( (T *)data \| (void *)data \);
+   T *container = from_tasklet(container, t, tasklet);
...
}

@ patch2 depends on match @
type match.T;
identifier match.tasklet;
identifier match.callback;
identifier data;
identifier container;
@@
-void callback(unsigned long data)
+void callback(struct tasklet_struct *t)
{
...
-   T *container;
+   T *container = from_tasklet(container, t, tasklet);
...
-   container = \( (T *)data \| (void *)data \);
...
}

@ depends on (patch1 || patch2) @
match.T *container;
identifier match.tasklet;
identifier match.callback;
@@
-   tasklet_init(&container->tasklet, callback, (unsigned long)container);
+   tasklet_setup(&container->tasklet, callback);


Emil Renner Berthing (9):
  mmc: atmel-mci: Use new tasklet API
  mmc: au1xmmc: Use new tasklet API
  mmc: dw_mmc: Use new tasklet API
  mmc: omap: Use new tasklet API
  mmc: s3cmci: Use new tasklet API
  mmc: tifm_sd: Use new tasklet API
  mmc: uniphier-sd: Use new tasklet API
  mmc: via-sdmmc: Use new tasklet API
  mmc: wbsd: Use new tasklet API

 drivers/mmc/host/atmel-mci.c   |  6 +++---
 drivers/mmc/host/au1xmmc.c | 14 ++
 drivers/mmc/host/dw_mmc.c  |  6 +++---
 drivers/mmc/host/omap.c|  7 +++
 drivers/mmc/host/s3cmci.c  |  6 +++---
 drivers/mmc/host/tifm_sd.c |  7 +++
 drivers/mmc/host/uniphier-sd.c | 14 ++
 drivers/mmc/host/via-sdmmc.c   |  9 +++--
 drivers/mmc/host/wbsd.c| 35 +++---
 9 files changed, 45 insertions(+), 59 deletions(-)

-- 
2.30.0



[PATCH 1/9] mmc: atmel-mci: Use new tasklet API

2021-02-04 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/mmc/host/atmel-mci.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 632412066eda..807177c953f3 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -1719,9 +1719,9 @@ static void atmci_detect_change(struct timer_list *t)
}
 }
 
-static void atmci_tasklet_func(unsigned long priv)
+static void atmci_tasklet_func(struct tasklet_struct *t)
 {
-   struct atmel_mci*host = (struct atmel_mci *)priv;
+   struct atmel_mci*host = from_tasklet(host, t, tasklet);
struct mmc_request  *mrq = host->mrq;
struct mmc_data *data = host->data;
enum atmel_mci_statestate = host->state;
@@ -2496,7 +2496,7 @@ static int atmci_probe(struct platform_device *pdev)
 
host->mapbase = regs->start;
 
-   tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)host);
+   tasklet_setup(&host->tasklet, atmci_tasklet_func);
 
ret = request_irq(irq, atmci_interrupt, 0, dev_name(&pdev->dev), host);
if (ret) {
-- 
2.30.0



[PATCH 6/9] net: usb: lan78xx: use new tasklet API

2021-01-30 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/usb/lan78xx.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index bf243edeb064..e81c5699c952 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -3375,9 +3375,9 @@ static void lan78xx_rx_bh(struct lan78xx_net *dev)
netif_wake_queue(dev->net);
 }
 
-static void lan78xx_bh(unsigned long param)
+static void lan78xx_bh(struct tasklet_struct *t)
 {
-   struct lan78xx_net *dev = (struct lan78xx_net *)param;
+   struct lan78xx_net *dev = from_tasklet(dev, t, bh);
struct sk_buff *skb;
struct skb_data *entry;
 
@@ -3655,7 +3655,7 @@ static int lan78xx_probe(struct usb_interface *intf,
skb_queue_head_init(&dev->txq_pend);
mutex_init(&dev->phy_mutex);
 
-   tasklet_init(&dev->bh, lan78xx_bh, (unsigned long)dev);
+   tasklet_setup(&dev->bh, lan78xx_bh);
INIT_DELAYED_WORK(&dev->wq, lan78xx_delayedwork);
init_usb_anchor(&dev->deferred);
 
-- 
2.30.0



[PATCH 5/9] net: usb: hso: use new tasklet API

2021-01-30 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/usb/hso.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index ef6dd012b8c4..31d51346786a 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -1213,9 +1213,10 @@ static void hso_std_serial_read_bulk_callback(struct urb 
*urb)
  * This needs to be a tasklet otherwise we will
  * end up recursively calling this function.
  */
-static void hso_unthrottle_tasklet(unsigned long data)
+static void hso_unthrottle_tasklet(struct tasklet_struct *t)
 {
-   struct hso_serial *serial = (struct hso_serial *)data;
+   struct hso_serial *serial = from_tasklet(serial, t,
+unthrottle_tasklet);
unsigned long flags;
 
spin_lock_irqsave(&serial->serial_lock, flags);
@@ -1264,9 +1265,8 @@ static int hso_serial_open(struct tty_struct *tty, struct 
file *filp)
serial->rx_state = RX_IDLE;
/* Force default termio settings */
_hso_serial_set_termios(tty, NULL);
-   tasklet_init(&serial->unthrottle_tasklet,
-hso_unthrottle_tasklet,
-(unsigned long)serial);
+   tasklet_setup(&serial->unthrottle_tasklet,
+ hso_unthrottle_tasklet);
result = hso_start_serial_device(serial->parent, GFP_KERNEL);
if (result) {
hso_stop_serial_device(serial->parent);
-- 
2.30.0



[PATCH 7/9] net: usb: pegasus: use new tasklet API

2021-01-30 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/usb/pegasus.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 32e1335c94ad..9a907182569c 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -553,12 +553,11 @@ static void read_bulk_callback(struct urb *urb)
tasklet_schedule(&pegasus->rx_tl);
 }
 
-static void rx_fixup(unsigned long data)
+static void rx_fixup(struct tasklet_struct *t)
 {
-   pegasus_t *pegasus;
+   pegasus_t *pegasus = from_tasklet(pegasus, t, rx_tl);
int status;
 
-   pegasus = (pegasus_t *) data;
if (pegasus->flags & PEGASUS_UNPLUG)
return;
 
@@ -1129,7 +1128,7 @@ static int pegasus_probe(struct usb_interface *intf,
goto out1;
}
 
-   tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
+   tasklet_setup(&pegasus->rx_tl, rx_fixup);
 
INIT_DELAYED_WORK(&pegasus->carrier_check, check_carrier);
 
-- 
2.30.0



[PATCH 8/9] net: usb: r8152: use new tasklet API

2021-01-30 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/usb/r8152.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 67cd6986634f..0d7d2938e21d 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -2393,11 +2393,9 @@ static void tx_bottom(struct r8152 *tp)
} while (res == 0);
 }
 
-static void bottom_half(unsigned long data)
+static void bottom_half(struct tasklet_struct *t)
 {
-   struct r8152 *tp;
-
-   tp = (struct r8152 *)data;
+   struct r8152 *tp = from_tasklet(tp, t, tx_tl);
 
if (test_bit(RTL8152_UNPLUG, &tp->flags))
return;
@@ -6714,7 +6712,7 @@ static int rtl8152_probe(struct usb_interface *intf,
mutex_init(&tp->control);
INIT_DELAYED_WORK(&tp->schedule, rtl_work_func_t);
INIT_DELAYED_WORK(&tp->hw_phy_work, rtl_hw_phy_work_func_t);
-   tasklet_init(&tp->tx_tl, bottom_half, (unsigned long)tp);
+   tasklet_setup(&tp->tx_tl, bottom_half);
tasklet_disable(&tp->tx_tl);
 
netdev->netdev_ops = &rtl8152_netdev_ops;
-- 
2.30.0



[PATCH 9/9] net: usb: rtl8150: use new tasklet API

2021-01-30 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/usb/rtl8150.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index bf8a60533f3e..7656f2a3afd9 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -577,9 +577,9 @@ static void free_skb_pool(rtl8150_t *dev)
dev_kfree_skb(dev->rx_skb_pool[i]);
 }
 
-static void rx_fixup(unsigned long data)
+static void rx_fixup(struct tasklet_struct *t)
 {
-   struct rtl8150 *dev = (struct rtl8150 *)data;
+   struct rtl8150 *dev = from_tasklet(dev, t, tl);
struct sk_buff *skb;
int status;
 
@@ -878,7 +878,7 @@ static int rtl8150_probe(struct usb_interface *intf,
return -ENOMEM;
}
 
-   tasklet_init(&dev->tl, rx_fixup, (unsigned long)dev);
+   tasklet_setup(&dev->tl, rx_fixup);
spin_lock_init(&dev->rx_pool_lock);
 
dev->udev = udev;
-- 
2.30.0



[PATCH 3/9] ifb: use new tasklet API

2021-01-30 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/ifb.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index fa63d4dee0ba..ab7022582154 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -59,9 +59,9 @@ static netdev_tx_t ifb_xmit(struct sk_buff *skb, struct 
net_device *dev);
 static int ifb_open(struct net_device *dev);
 static int ifb_close(struct net_device *dev);
 
-static void ifb_ri_tasklet(unsigned long _txp)
+static void ifb_ri_tasklet(struct tasklet_struct *t)
 {
-   struct ifb_q_private *txp = (struct ifb_q_private *)_txp;
+   struct ifb_q_private *txp = from_tasklet(txp, t, ifb_tasklet);
struct netdev_queue *txq;
struct sk_buff *skb;
 
@@ -170,8 +170,7 @@ static int ifb_dev_init(struct net_device *dev)
__skb_queue_head_init(&txp->tq);
u64_stats_init(&txp->rsync);
u64_stats_init(&txp->tsync);
-   tasklet_init(&txp->ifb_tasklet, ifb_ri_tasklet,
-(unsigned long)txp);
+   tasklet_setup(&txp->ifb_tasklet, ifb_ri_tasklet);
netif_tx_start_queue(netdev_get_tx_queue(dev, i));
}
return 0;
-- 
2.30.0



[PATCH 2/9] caif_virtio: use new tasklet API

2021-01-30 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/caif/caif_virtio.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c
index 47a6d62b7511..106f089eb2a8 100644
--- a/drivers/net/caif/caif_virtio.c
+++ b/drivers/net/caif/caif_virtio.c
@@ -598,9 +598,9 @@ static netdev_tx_t cfv_netdev_tx(struct sk_buff *skb, 
struct net_device *netdev)
return NETDEV_TX_OK;
 }
 
-static void cfv_tx_release_tasklet(unsigned long drv)
+static void cfv_tx_release_tasklet(struct tasklet_struct *t)
 {
-   struct cfv_info *cfv = (struct cfv_info *)drv;
+   struct cfv_info *cfv = from_tasklet(cfv, t, tx_release_tasklet);
cfv_release_used_buf(cfv->vq_tx);
 }
 
@@ -716,9 +716,7 @@ static int cfv_probe(struct virtio_device *vdev)
cfv->ctx.head = USHRT_MAX;
netif_napi_add(netdev, &cfv->napi, cfv_rx_poll, CFV_DEFAULT_QUOTA);
 
-   tasklet_init(&cfv->tx_release_tasklet,
-cfv_tx_release_tasklet,
-(unsigned long)cfv);
+   tasklet_setup(&cfv->tx_release_tasklet, cfv_tx_release_tasklet);
 
/* Carrier is off until netdevice is opened */
netif_carrier_off(netdev);
-- 
2.30.0



[PATCH 4/9] ppp: use new tasklet API

2021-01-30 Thread Emil Renner Berthing
This converts the async and synctty drivers to use the new tasklet API n
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/ppp/ppp_async.c   | 8 
 drivers/net/ppp/ppp_synctty.c | 8 
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/net/ppp/ppp_async.c b/drivers/net/ppp/ppp_async.c
index 29a0917a81e6..2b66cf301b0e 100644
--- a/drivers/net/ppp/ppp_async.c
+++ b/drivers/net/ppp/ppp_async.c
@@ -101,7 +101,7 @@ static void ppp_async_input(struct asyncppp *ap, const 
unsigned char *buf,
char *flags, int count);
 static int ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd,
   unsigned long arg);
-static void ppp_async_process(unsigned long arg);
+static void ppp_async_process(struct tasklet_struct *t);
 
 static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
   int len, int inbound);
@@ -179,7 +179,7 @@ ppp_asynctty_open(struct tty_struct *tty)
ap->lcp_fcs = -1;
 
skb_queue_head_init(&ap->rqueue);
-   tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap);
+   tasklet_setup(&ap->tsk, ppp_async_process);
 
refcount_set(&ap->refcnt, 1);
init_completion(&ap->dead);
@@ -488,9 +488,9 @@ ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, 
unsigned long arg)
  * to the ppp_generic code, and to tell the ppp_generic code
  * if we can accept more output now.
  */
-static void ppp_async_process(unsigned long arg)
+static void ppp_async_process(struct tasklet_struct *t)
 {
-   struct asyncppp *ap = (struct asyncppp *) arg;
+   struct asyncppp *ap = from_tasklet(ap, t, tsk);
struct sk_buff *skb;
 
/* process received packets */
diff --git a/drivers/net/ppp/ppp_synctty.c b/drivers/net/ppp/ppp_synctty.c
index 0f338752c38b..86ee5149f4f2 100644
--- a/drivers/net/ppp/ppp_synctty.c
+++ b/drivers/net/ppp/ppp_synctty.c
@@ -90,7 +90,7 @@ static struct sk_buff* ppp_sync_txmunge(struct syncppp *ap, 
struct sk_buff *);
 static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb);
 static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd,
  unsigned long arg);
-static void ppp_sync_process(unsigned long arg);
+static void ppp_sync_process(struct tasklet_struct *t);
 static int ppp_sync_push(struct syncppp *ap);
 static void ppp_sync_flush_output(struct syncppp *ap);
 static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
@@ -177,7 +177,7 @@ ppp_sync_open(struct tty_struct *tty)
ap->raccm = ~0U;
 
skb_queue_head_init(&ap->rqueue);
-   tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap);
+   tasklet_setup(&ap->tsk, ppp_sync_process);
 
refcount_set(&ap->refcnt, 1);
init_completion(&ap->dead_cmp);
@@ -480,9 +480,9 @@ ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd, 
unsigned long arg)
  * to the ppp_generic code, and to tell the ppp_generic code
  * if we can accept more output now.
  */
-static void ppp_sync_process(unsigned long arg)
+static void ppp_sync_process(struct tasklet_struct *t)
 {
-   struct syncppp *ap = (struct syncppp *) arg;
+   struct syncppp *ap = from_tasklet(ap, t, tsk);
struct sk_buff *skb;
 
/* process received packets */
-- 
2.30.0



[PATCH 0/9] drivers: net: update tasklet_init callers

2021-01-30 Thread Emil Renner Berthing
This updates the remaining callers of tasklet_init() in drivers/net
to the new API introduced in 
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

All changes are done by coccinelle using the following semantic patch.
Coccinelle needs a little help parsing drivers/net/arcnet/arcnet.c

@ match @
type T;
T *container;
identifier tasklet;
identifier callback;
@@
tasklet_init(&container->tasklet, callback, (unsigned long)container);

@ patch1 depends on match @
type match.T;
identifier match.tasklet;
identifier match.callback;
identifier data;
identifier container;
@@
-void callback(unsigned long data)
+void callback(struct tasklet_struct *t)
{
...
-   T *container = (T *)data;
+   T *container = from_tasklet(container, t, tasklet);
...
}

@ patch2 depends on match @
type match.T;
identifier match.tasklet;
identifier match.callback;
identifier data;
identifier container;
@@
-void callback(unsigned long data)
+void callback(struct tasklet_struct *t)
{
...
-   T *container;
+   T *container = from_tasklet(container, t, tasklet);
...
-   container = (T *)data;
...
}

@ depends on (patch1 || patch2) @
match.T *container;
identifier match.tasklet;
identifier match.callback;
@@
-   tasklet_init(&container->tasklet, callback, (unsigned long)container);
+   tasklet_setup(&container->tasklet, callback);


Emil Renner Berthing (9):
  arcnet: use new tasklet API
  caif_virtio: use new tasklet API
  ifb: use new tasklet API
  ppp: use new tasklet API
  net: usb: hso: use new tasklet API
  net: usb: lan78xx: use new tasklet API
  net: usb: pegasus: use new tasklet API
  net: usb: r8152: use new tasklet API
  net: usb: rtl8150: use new tasklet API

 drivers/net/arcnet/arcnet.c|  7 +++
 drivers/net/caif/caif_virtio.c |  8 +++-
 drivers/net/ifb.c  |  7 +++
 drivers/net/ppp/ppp_async.c|  8 
 drivers/net/ppp/ppp_synctty.c  |  8 
 drivers/net/usb/hso.c  | 10 +-
 drivers/net/usb/lan78xx.c  |  6 +++---
 drivers/net/usb/pegasus.c  |  7 +++
 drivers/net/usb/r8152.c|  8 +++-
 drivers/net/usb/rtl8150.c  |  6 +++---
 10 files changed, 34 insertions(+), 41 deletions(-)

-- 
2.30.0



[PATCH 1/9] arcnet: use new tasklet API

2021-01-30 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/arcnet/arcnet.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index e04efc0a5c97..69d8920e394b 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -393,9 +393,9 @@ static void arcnet_timer(struct timer_list *t)
}
 }
 
-static void arcnet_reply_tasklet(unsigned long data)
+static void arcnet_reply_tasklet(struct tasklet_struct *t)
 {
-   struct arcnet_local *lp = (struct arcnet_local *)data;
+   struct arcnet_local *lp = from_tasklet(lp, t, reply_tasklet);
 
struct sk_buff *ackskb, *skb;
struct sock_exterr_skb *serr;
@@ -483,8 +483,7 @@ int arcnet_open(struct net_device *dev)
arc_cont(D_PROTO, "\n");
}
 
-   tasklet_init(&lp->reply_tasklet, arcnet_reply_tasklet,
-(unsigned long)lp);
+   tasklet_setup(&lp->reply_tasklet, arcnet_reply_tasklet);
 
arc_printk(D_INIT, dev, "arcnet_open: resetting card.\n");
 
-- 
2.30.0



[PATCH] net: usb: cdc_ncm: use new API for bh tasklet

2021-01-30 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

It is unfortunate that we need to add a pointer to the driver context to
get back to the usbnet device, but the space will be reclaimed once
there are no more users of the old API left and we can remove the data
value and flag from the tasklet struct.

Signed-off-by: Emil Renner Berthing 
---
Let me know if you know of a better way to get the usbnet device from
the cdc_ncn_ctx context.

 drivers/net/usb/cdc_ncm.c   | 12 +++-
 include/linux/usb/cdc_ncm.h |  2 ++
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 291e76d32abe..4087c9e33781 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -61,7 +61,7 @@ static bool prefer_mbim;
 module_param(prefer_mbim, bool, 0644);
 MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM 
functions");
 
-static void cdc_ncm_txpath_bh(unsigned long param);
+static void cdc_ncm_txpath_bh(struct tasklet_struct *t);
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
 static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
 static struct usb_driver cdc_ncm_driver;
@@ -813,9 +813,11 @@ int cdc_ncm_bind_common(struct usbnet *dev, struct 
usb_interface *intf, u8 data_
if (!ctx)
return -ENOMEM;
 
+   ctx->dev = dev;
+
hrtimer_init(&ctx->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
ctx->tx_timer.function = &cdc_ncm_tx_timer_cb;
-   tasklet_init(&ctx->bh, cdc_ncm_txpath_bh, (unsigned long)dev);
+   tasklet_setup(&ctx->bh, cdc_ncm_txpath_bh);
atomic_set(&ctx->stop, 0);
spin_lock_init(&ctx->mtx);
 
@@ -1472,10 +1474,10 @@ static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct 
hrtimer *timer)
return HRTIMER_NORESTART;
 }
 
-static void cdc_ncm_txpath_bh(unsigned long param)
+static void cdc_ncm_txpath_bh(struct tasklet_struct *t)
 {
-   struct usbnet *dev = (struct usbnet *)param;
-   struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
+   struct cdc_ncm_ctx *ctx = from_tasklet(ctx, t, bh);
+   struct usbnet *dev = ctx->dev;
 
spin_lock_bh(&ctx->mtx);
if (ctx->tx_timer_pending != 0) {
diff --git a/include/linux/usb/cdc_ncm.h b/include/linux/usb/cdc_ncm.h
index 0ce4377545f8..f7cb3ddce7fb 100644
--- a/include/linux/usb/cdc_ncm.h
+++ b/include/linux/usb/cdc_ncm.h
@@ -98,6 +98,8 @@ struct cdc_ncm_ctx {
struct hrtimer tx_timer;
struct tasklet_struct bh;
 
+   struct usbnet *dev;
+
const struct usb_cdc_ncm_desc *func_desc;
const struct usb_cdc_mbim_desc *mbim_desc;
const struct usb_cdc_mbim_extended_desc *mbim_extended_desc;
-- 
2.30.0



[PATCH 1/2] net: atm: pppoatm: use tasklet_init to initialize wakeup tasklet

2021-01-27 Thread Emil Renner Berthing
Previously a temporary tasklet structure was initialized on the stack
using DECLARE_TASKLET_OLD() and then copied over and modified. Nothing
else in the kernel seems to use this pattern, so let's just call
tasklet_init() like everyone else.

Signed-off-by: Emil Renner Berthing 
---
 net/atm/pppoatm.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 579b66da1d95..5f06af098390 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -389,11 +389,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void 
__user *arg)
struct atm_backend_ppp be;
struct pppoatm_vcc *pvcc;
int err;
-   /*
-* Each PPPoATM instance has its own tasklet - this is just a
-* prototypical one used to initialize them
-*/
-   static const DECLARE_TASKLET_OLD(tasklet_proto, pppoatm_wakeup_sender);
+
if (copy_from_user(&be, arg, sizeof be))
return -EFAULT;
if (be.encaps != PPPOATM_ENCAPS_AUTODETECT &&
@@ -415,8 +411,8 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void 
__user *arg)
pvcc->chan.ops = &pppoatm_ops;
pvcc->chan.mtu = atmvcc->qos.txtp.max_sdu - PPP_HDRLEN -
(be.encaps == e_vc ? 0 : LLC_LEN);
-   pvcc->wakeup_tasklet = tasklet_proto;
-   pvcc->wakeup_tasklet.data = (unsigned long) &pvcc->chan;
+   tasklet_init(&pvcc->wakeup_tasklet, pppoatm_wakeup_sender,
+(unsigned long)&pvcc->chan);
err = ppp_register_channel(&pvcc->chan);
if (err != 0) {
kfree(pvcc);
-- 
2.30.0



[PATCH 2/2] net: atm: pppoatm: use new API for wakeup tasklet

2021-01-27 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 net/atm/pppoatm.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c
index 5f06af098390..3e4f17d335fe 100644
--- a/net/atm/pppoatm.c
+++ b/net/atm/pppoatm.c
@@ -101,9 +101,11 @@ static inline struct pppoatm_vcc *chan_to_pvcc(const 
struct ppp_channel *chan)
  * doesn't want to be called in interrupt context, so we do it from
  * a tasklet
  */
-static void pppoatm_wakeup_sender(unsigned long arg)
+static void pppoatm_wakeup_sender(struct tasklet_struct *t)
 {
-   ppp_output_wakeup((struct ppp_channel *) arg);
+   struct pppoatm_vcc *pvcc = from_tasklet(pvcc, t, wakeup_tasklet);
+
+   ppp_output_wakeup(&pvcc->chan);
 }
 
 static void pppoatm_release_cb(struct atm_vcc *atmvcc)
@@ -411,8 +413,7 @@ static int pppoatm_assign_vcc(struct atm_vcc *atmvcc, void 
__user *arg)
pvcc->chan.ops = &pppoatm_ops;
pvcc->chan.mtu = atmvcc->qos.txtp.max_sdu - PPP_HDRLEN -
(be.encaps == e_vc ? 0 : LLC_LEN);
-   tasklet_init(&pvcc->wakeup_tasklet, pppoatm_wakeup_sender,
-(unsigned long)&pvcc->chan);
+   tasklet_setup(&pvcc->wakeup_tasklet, pppoatm_wakeup_sender);
err = ppp_register_channel(&pvcc->chan);
if (err != 0) {
kfree(pvcc);
-- 
2.30.0



[PATCH v2] vt: keyboard, use new API for keyboard_tasklet

2021-01-27 Thread Emil Renner Berthing
This converts the keyboard_tasklet to use the new API in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

The new API changes the argument passed to the callback function, but
fortunately the argument isn't used so it is straight forward to use
DECLARE_TASKLET_DISABLED() rather than DECLARE_TASKLET_DISABLED_OLD().

Signed-off-by: Emil Renner Berthing 
---
v2: Rebased on Greg's tty/tty-next tree.
---
 drivers/tty/vt/keyboard.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 9f2eaa104ebc..77638629c562 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -131,8 +131,8 @@ static const unsigned char max_vals[] = {
 
 static const int NR_TYPES = ARRAY_SIZE(max_vals);
 
-static void kbd_bh(unsigned long dummy);
-static DECLARE_TASKLET_DISABLED_OLD(keyboard_tasklet, kbd_bh);
+static void kbd_bh(struct tasklet_struct *unused);
+static DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh);
 
 static struct input_handler kbd_handler;
 static DEFINE_SPINLOCK(kbd_event_lock);
@@ -1245,7 +1245,7 @@ void vt_kbd_con_stop(int console)
  * handle the scenario when keyboard handler is not registered yet
  * but we already getting updates from the VT to update led state.
  */
-static void kbd_bh(unsigned long dummy)
+static void kbd_bh(struct tasklet_struct *unused)
 {
unsigned int leds;
unsigned long flags;
-- 
2.30.0



Re: [PATCH] rtlwifi: use tasklet_setup to initialize rx_work_tasklet

2021-01-27 Thread Emil Renner Berthing
On Wed, 27 Jan 2021 at 16:33, Kalle Valo  wrote:
> ...
> Forgot to mention that I can remove the Fixes tags during commit, so no
> need to resend just because of those.

Cool, thanks.

> > I can definitely see how you can reasonably disagree, but I would not
> > be comfortable having code that only works because the calling
> > conventions of all relevant architectures happen to put the first
> > unsigned long argument and the first pointer argument in the same
> > register.
>
> If there's a bug this patch fixes please explain it clearly in the
> commit log. But as I read it (though I admit very quickly) I understood
> this is just cleanup.

Sorry, I'll try again.

So the tasklet_struct looks like this:
struct tasklet_struct {
  ..
  bool use_callback;
  union {
void (*func)(unsigned long);
void (*callback)(struct tasklet_struct *);
  };
  unsigned long data;
};

..and the use_callback flag is used like this:
if (t->use_callback)
  t->callback(t);
else
  t->func(t->data);

Now commit d3ccc14dfe95 changed the _rtl_rx_work to be of the new
callback, not func, type. But it didn't actually set the use_callback
flag, and just typecast the _rtl_rx_work function pointer and assigned
it to the func member. So _rtl_rx_work is still called as
t->func(t->data) even though it was rewritten to be called as
t->callback(t).
Now 6b8c7574a5f8 set t->data = (unsigned long)t, so calling
t->func(t->data) will probably work on most architectures because:

a) "unsigned long" and "struct tasklet_struct *" has the same width on
all Linux-capable architectures and
b) calling t->func(t->data) will put the value from t->data into the
same register as the function
void _rtl_rx_work(struct tasklet_struct *t)
  expects to find the pointer t in the C calling conventions used by
all relevant architectures.

I guess it's debatable weather this is a bug or just ugly code.

/Emil


Re: [PATCH] rtlwifi: use tasklet_setup to initialize rx_work_tasklet

2021-01-27 Thread Emil Renner Berthing
On Wed, 27 Jan 2021 at 16:20, Kalle Valo  wrote:
>
> Willem de Bruijn  writes:
>
> > On Wed, Jan 27, 2021 at 5:23 AM Emil Renner Berthing  
> > wrote:
> >>
> >> In commit d3ccc14dfe95 most of the tasklets in this driver was
> >> updated to the new API. However for the rx_work_tasklet only the
> >> type of the callback was changed from
> >>   void _rtl_rx_work(unsigned long data)
> >> to
> >>   void _rtl_rx_work(struct tasklet_struct *t).
> >>
> >> The initialization of rx_work_tasklet was still open-coded and the
> >> function pointer just cast into the old type, and hence nothing sets
> >> rx_work_tasklet.use_callback = true and the callback was still called as
> >>
> >>   t->func(t->data);
> >>
> >> with uninitialized/zero t->data.
> >>
> >> Commit 6b8c7574a5f8 changed the casting of _rtl_rx_work a bit and
> >> initialized t->data to a pointer to the tasklet cast to an unsigned
> >> long.
> >>
> >> This way calling t->func(t->data) might actually work through all the
> >> casting, but it still doesn't update the code to use the new tasklet
> >> API.
> >>
> >> Let's use the new tasklet_setup to initialize rx_work_tasklet properly
> >> and set rx_work_tasklet.use_callback = true so that the callback is
> >> called as
> >>
> >>   t->callback(t);
> >>
> >> without all the casting.
> >>
> >> Fixes: 6b8c7574a5f8 ("rtlwifi: fix build warning")
> >> Fixes: d3ccc14dfe95 ("rtlwifi/rtw88: convert tasklets to use new
> >> tasklet_setup() API")
> >> Signed-off-by: Emil Renner Berthing 
> >
> > Since the current code works, this could target net-next
>
> This should go to wireless-drivers-next, not net-next.
>
> > without Fixes tags.
>
> Correct, no need for Fixes tag as there's no bug to fix. This is only
> cleanup AFAICS.

I can definitely see how you can reasonably disagree, but I would not
be comfortable having code that only works because the calling
conventions of all relevant architectures happen to put the first
unsigned long argument and the first pointer argument in the same
register.
If you want to be conservative I'd much rather revert all the changes
around rx_work_tasklet including the new type of the _rtl_rx_work
callback, so we don't have to rely on calling conventions matching up.

In any case: as long as this fix eventually ends up upstream I'm fine.

/Emil


[PATCH] drm/i915/gt: use new tasklet API in execlist selftest

2021-01-26 Thread Emil Renner Berthing
This converts the execlist selftest to use the new tasklet API in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
Hi Chris,

I seem to have missed some tasklist manipulation in the execlist
selftest.  Feel free to squash this into my previous patch
("drm/i915/gt: use new tasklet API for execution list")
or leave it like this. Whatever is fine by me.

/Emil
---
 drivers/gpu/drm/i915/gt/selftest_execlists.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c 
b/drivers/gpu/drm/i915/gt/selftest_execlists.c
index 264b5ebdb021..ba55cd018f5b 100644
--- a/drivers/gpu/drm/i915/gt/selftest_execlists.c
+++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c
@@ -609,7 +609,7 @@ static int live_hold_reset(void *arg)
}
tasklet_disable(&engine->execlists.tasklet);
 
-   engine->execlists.tasklet.func(engine->execlists.tasklet.data);
+   engine->execlists.tasklet.callback(&engine->execlists.tasklet);
GEM_BUG_ON(execlists_active(&engine->execlists) != rq);
 
i915_request_get(rq);
@@ -4610,7 +4610,7 @@ static int reset_virtual_engine(struct intel_gt *gt,
}
tasklet_disable(&engine->execlists.tasklet);
 
-   engine->execlists.tasklet.func(engine->execlists.tasklet.data);
+   engine->execlists.tasklet.callback(&engine->execlists.tasklet);
GEM_BUG_ON(execlists_active(&engine->execlists) != rq);
 
/* Fake a preemption event; failed of course */
-- 
2.30.0



[PATCH] rtlwifi: use tasklet_setup to initialize rx_work_tasklet

2021-01-26 Thread Emil Renner Berthing
In commit d3ccc14dfe95 most of the tasklets in this driver was
updated to the new API. However for the rx_work_tasklet only the
type of the callback was changed from
  void _rtl_rx_work(unsigned long data)
to
  void _rtl_rx_work(struct tasklet_struct *t).

The initialization of rx_work_tasklet was still open-coded and the
function pointer just cast into the old type, and hence nothing sets
rx_work_tasklet.use_callback = true and the callback was still called as

  t->func(t->data);

with uninitialized/zero t->data.

Commit 6b8c7574a5f8 changed the casting of _rtl_rx_work a bit and
initialized t->data to a pointer to the tasklet cast to an unsigned
long.

This way calling t->func(t->data) might actually work through all the
casting, but it still doesn't update the code to use the new tasklet
API.

Let's use the new tasklet_setup to initialize rx_work_tasklet properly
and set rx_work_tasklet.use_callback = true so that the callback is
called as

  t->callback(t);

without all the casting.

Fixes: 6b8c7574a5f8 ("rtlwifi: fix build warning")
Fixes: d3ccc14dfe95 ("rtlwifi/rtw88: convert tasklets to use new 
tasklet_setup() API")
Signed-off-by: Emil Renner Berthing 
---
 drivers/net/wireless/realtek/rtlwifi/usb.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c 
b/drivers/net/wireless/realtek/rtlwifi/usb.c
index d62b87f010c9..6c5e242b1bc5 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -310,8 +310,7 @@ static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
init_usb_anchor(&rtlusb->rx_cleanup_urbs);
 
skb_queue_head_init(&rtlusb->rx_queue);
-   rtlusb->rx_work_tasklet.func = (void(*))_rtl_rx_work;
-   rtlusb->rx_work_tasklet.data = (unsigned long)&rtlusb->rx_work_tasklet;
+   tasklet_setup(&rtlusb->rx_work_tasklet, _rtl_rx_work);
 
return 0;
 }
-- 
2.30.0



Re: [PATCH v2] drm/i915/gt: use new tasklet API for execution list

2021-01-26 Thread Emil Renner Berthing
On Tue, 26 Jan 2021 at 16:13, Chris Wilson  wrote:
> Quoting Emil Renner Berthing (2021-01-26 15:01:55)
> > This converts the driver to use the new tasklet API introduced in
> > commit 12cc923f1ccc ("tasklet: Introduce new initialization API")
> >
> > Signed-off-by: Emil Renner Berthing 
> >
> > ---
> > v2: Rebased on drm-intel-next
>
> Ta. Saves me having to do the fixup.
>
> Reviewed-by: Chris Wilson 
>
> Will be applied to drm-intel-gt-next which is scheduled for inclusion in
> 5.13. It should apply against the 5.12 merge window if there's a tree
> through which you want to migrate the tasklet API faster.

That's fine by me, thanks!

/Emil


[PATCH v2] drm/i915/gt: use new tasklet API for execution list

2021-01-26 Thread Emil Renner Berthing
This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 

---
v2: Rebased on drm-intel-next

Tested on my Dell XPS 13 9300.
---
 drivers/gpu/drm/i915/gt/intel_engine_cs.c |  4 +--
 .../drm/i915/gt/intel_execlists_submission.c  | 25 ---
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c |  9 +++
 3 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index fa76602f9852..48a8caa28f65 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -1234,14 +1234,14 @@ void __intel_engine_flush_submission(struct 
intel_engine_cs *engine, bool sync)
 {
struct tasklet_struct *t = &engine->execlists.tasklet;
 
-   if (!t->func)
+   if (!t->callback)
return;
 
local_bh_disable();
if (tasklet_trylock(t)) {
/* Must wait for any GPU reset in progress. */
if (__tasklet_is_enabled(t))
-   t->func(t->data);
+   t->callback(t);
tasklet_unlock(t);
}
local_bh_enable();
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c 
b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index d7d5a58990bb..3dfae03c6d6a 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -2376,9 +2376,9 @@ static bool preempt_timeout(const struct intel_engine_cs 
*const engine)
  * Check the unread Context Status Buffers and manage the submission of new
  * contexts to the ELSP accordingly.
  */
-static void execlists_submission_tasklet(unsigned long data)
+static void execlists_submission_tasklet(struct tasklet_struct *t)
 {
-   struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
+   struct intel_engine_cs * const engine = from_tasklet(engine, t, 
execlists.tasklet);
struct i915_request *post[2 * EXECLIST_MAX_PORTS];
struct i915_request **inactive;
 
@@ -2956,9 +2956,9 @@ static void execlists_reset_rewind(struct intel_engine_cs 
*engine, bool stalled)
rcu_read_unlock();
 }
 
-static void nop_submission_tasklet(unsigned long data)
+static void nop_submission_tasklet(struct tasklet_struct *t)
 {
-   struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
+   struct intel_engine_cs * const engine = from_tasklet(engine, t, 
execlists.tasklet);
 
/* The driver is wedged; don't process any more events. */
WRITE_ONCE(engine->execlists.queue_priority_hint, INT_MIN);
@@ -3043,7 +3043,7 @@ static void execlists_reset_cancel(struct intel_engine_cs 
*engine)
execlists->queue = RB_ROOT_CACHED;
 
GEM_BUG_ON(__tasklet_is_enabled(&execlists->tasklet));
-   execlists->tasklet.func = nop_submission_tasklet;
+   execlists->tasklet.callback = nop_submission_tasklet;
 
spin_unlock_irqrestore(&engine->active.lock, flags);
rcu_read_unlock();
@@ -3104,7 +3104,7 @@ static void execlists_set_default_submission(struct 
intel_engine_cs *engine)
 {
engine->submit_request = execlists_submit_request;
engine->schedule = i915_schedule;
-   engine->execlists.tasklet.func = execlists_submission_tasklet;
+   engine->execlists.tasklet.callback = execlists_submission_tasklet;
 
engine->reset.prepare = execlists_reset_prepare;
engine->reset.rewind = execlists_reset_rewind;
@@ -3228,8 +3228,7 @@ int intel_execlists_submission_setup(struct 
intel_engine_cs *engine)
struct intel_uncore *uncore = engine->uncore;
u32 base = engine->mmio_base;
 
-   tasklet_init(&engine->execlists.tasklet,
-execlists_submission_tasklet, (unsigned long)engine);
+   tasklet_setup(&engine->execlists.tasklet, execlists_submission_tasklet);
timer_setup(&engine->execlists.timer, execlists_timeslice, 0);
timer_setup(&engine->execlists.preempt, execlists_preempt, 0);
 
@@ -3471,9 +3470,9 @@ static intel_engine_mask_t virtual_submission_mask(struct 
virtual_engine *ve)
return mask;
 }
 
-static void virtual_submission_tasklet(unsigned long data)
+static void virtual_submission_tasklet(struct tasklet_struct *t)
 {
-   struct virtual_engine * const ve = (struct virtual_engine *)data;
+   struct virtual_engine * const ve = from_tasklet(ve, t, 
base.execlists.tasklet);
const int prio = READ_ONCE(ve->base.execlists.queue_priority_hint);
intel_engine_mask_t mask;
unsigned int n;
@@ -3683,9 +3682,7 @@ intel_execlists_create_virtual(struct intel_engine_cs 
**siblings,
 
INIT_LIST_HEAD(virtual_

Re: [PATCH] kgdb: use new API for breakpoint tasklet

2021-01-25 Thread Emil Renner Berthing
On Mon, 25 Jan 2021 at 12:03, Daniel Thompson
 wrote:
>
> On Sat, Jan 23, 2021 at 07:42:37PM +0100, Emil Renner Berthing wrote:
> > This converts the kgdb_tasklet_breakpoint to use the new API in
> > commit 12cc923f1ccc ("tasklet: Introduce new initialization API")
> >
> > The new API changes the argument passed to the callback function, but
> > fortunately the argument isn't used so it is straight forward to use
> > DECLARE_TASKLET() rather than DECLARE_TASKLET_OLD().
>
> This patch overlaps with a more ambitious patch from Davidlohr.
> Perhaps you can join in with the other thread since the discussion
> there is unresolved. See:
> https://lkml.org/lkml/2021/1/14/1320

Ah, that's cool. Getting rid of tasklets is much better than merely
trying to get rid of the old tasklet API. Please ignore this patch
then.

/Emil
>
> Daniel.
>
>
> >
> > Signed-off-by: Emil Renner Berthing 
> > ---
> >  kernel/debug/debug_core.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
> > index af6e8b4fb359..98d44c2bb0a4 100644
> > --- a/kernel/debug/debug_core.c
> > +++ b/kernel/debug/debug_core.c
> > @@ -1090,13 +1090,13 @@ static void kgdb_unregister_callbacks(void)
> >   * such as is the case with kgdboe, where calling a breakpoint in the
> >   * I/O driver itself would be fatal.
> >   */
> > -static void kgdb_tasklet_bpt(unsigned long ing)
> > +static void kgdb_tasklet_bpt(struct tasklet_struct *unused)
> >  {
> >   kgdb_breakpoint();
> >   atomic_set(&kgdb_break_tasklet_var, 0);
> >  }
> >
> > -static DECLARE_TASKLET_OLD(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt);
> > +static DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt);
> >
> >  void kgdb_schedule_breakpoint(void)
> >  {
> > --
> > 2.30.0
> >


[PATCH] vt: keyboard, use new API for keyboard_tasklet

2021-01-23 Thread Emil Renner Berthing
This converts the keyboard_tasklet to use the new API in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

The new API changes the argument passed to the callback function, but
fortunately the argument isn't used so it is straight forward to use
DECLARE_TASKLET_DISABLED() rather than DECLARE_TASKLET_DISABLED_OLD().

Signed-off-by: Emil Renner Berthing 
---
 drivers/tty/vt/keyboard.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 52922d21a49f..6c85f024bec4 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -1233,7 +1233,7 @@ void vt_kbd_con_stop(int console)
  * handle the scenario when keyboard handler is not registered yet
  * but we already getting updates from the VT to update led state.
  */
-static void kbd_bh(unsigned long dummy)
+static void kbd_bh(struct tasklet_struct *unused)
 {
unsigned int leds;
unsigned long flags;
@@ -1249,7 +1249,7 @@ static void kbd_bh(unsigned long dummy)
}
 }
 
-DECLARE_TASKLET_DISABLED_OLD(keyboard_tasklet, kbd_bh);
+DECLARE_TASKLET_DISABLED(keyboard_tasklet, kbd_bh);
 
 #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
 defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC) ||\
-- 
2.30.0



[PATCH] kernel/backtracetest: use new API for backtrace tasklet

2021-01-23 Thread Emil Renner Berthing
This converts the backtrace_tasklet to use the new API in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

The new API changes the argument passed to the callback function, but
fortunately the argument isn't used so it is straight forward to use
DECLARE_TASKLET() rather than DECLARE_TASKLET_OLD().

Signed-off-by: Emil Renner Berthing 
---
 kernel/backtracetest.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/backtracetest.c b/kernel/backtracetest.c
index 370217dd7e39..70a3da716f01 100644
--- a/kernel/backtracetest.c
+++ b/kernel/backtracetest.c
@@ -23,13 +23,13 @@ static void backtrace_test_normal(void)
 
 static DECLARE_COMPLETION(backtrace_work);
 
-static void backtrace_test_irq_callback(unsigned long data)
+static void backtrace_test_irq_callback(struct tasklet_struct *unused)
 {
dump_stack();
complete(&backtrace_work);
 }
 
-static DECLARE_TASKLET_OLD(backtrace_tasklet, &backtrace_test_irq_callback);
+static DECLARE_TASKLET(backtrace_tasklet, backtrace_test_irq_callback);
 
 static void backtrace_test_irq(void)
 {
-- 
2.30.0



[PATCH] kgdb: use new API for breakpoint tasklet

2021-01-23 Thread Emil Renner Berthing
This converts the kgdb_tasklet_breakpoint to use the new API in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

The new API changes the argument passed to the callback function, but
fortunately the argument isn't used so it is straight forward to use
DECLARE_TASKLET() rather than DECLARE_TASKLET_OLD().

Signed-off-by: Emil Renner Berthing 
---
 kernel/debug/debug_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index af6e8b4fb359..98d44c2bb0a4 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -1090,13 +1090,13 @@ static void kgdb_unregister_callbacks(void)
  * such as is the case with kgdboe, where calling a breakpoint in the
  * I/O driver itself would be fatal.
  */
-static void kgdb_tasklet_bpt(unsigned long ing)
+static void kgdb_tasklet_bpt(struct tasklet_struct *unused)
 {
kgdb_breakpoint();
atomic_set(&kgdb_break_tasklet_var, 0);
 }
 
-static DECLARE_TASKLET_OLD(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt);
+static DECLARE_TASKLET(kgdb_tasklet_breakpoint, kgdb_tasklet_bpt);
 
 void kgdb_schedule_breakpoint(void)
 {
-- 
2.30.0



[PATCH] genirq: use new tasklet API for resend_tasklet

2021-01-23 Thread Emil Renner Berthing
From: Emil Renner Berthing 

This converts the resend_tasklet to use the new API in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

The new API changes the argument passed to the callback function, but
fortunately the argument isn't used so it is straight forward to use
DECLARE_TASKLET() rather than DECLARE_TASKLET_OLD().

Signed-off-by: Emil Renner Berthing 
---
 kernel/irq/resend.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/irq/resend.c b/kernel/irq/resend.c
index 8ccd32a0cc80..bd1d85c610aa 100644
--- a/kernel/irq/resend.c
+++ b/kernel/irq/resend.c
@@ -27,7 +27,7 @@ static DECLARE_BITMAP(irqs_resend, IRQ_BITMAP_BITS);
 /*
  * Run software resends of IRQ's
  */
-static void resend_irqs(unsigned long arg)
+static void resend_irqs(struct tasklet_struct *unused)
 {
struct irq_desc *desc;
int irq;
@@ -45,7 +45,7 @@ static void resend_irqs(unsigned long arg)
 }
 
 /* Tasklet to handle resend: */
-static DECLARE_TASKLET_OLD(resend_tasklet, resend_irqs);
+static DECLARE_TASKLET(resend_tasklet, resend_irqs);
 
 static int irq_sw_resend(struct irq_desc *desc)
 {
-- 
2.30.0



[PATCH] drm/i915/gt: use new tasklet API for execution list

2021-01-23 Thread Emil Renner Berthing
From: Emil Renner Berthing 

This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 

---
Tested on my Dell XPS 13 9300.

 drivers/gpu/drm/i915/gt/intel_engine_cs.c |  4 +--
 drivers/gpu/drm/i915/gt/intel_lrc.c   | 27 +--
 drivers/gpu/drm/i915/gt/selftest_lrc.c|  4 +--
 .../gpu/drm/i915/gt/uc/intel_guc_submission.c |  6 ++---
 4 files changed, 19 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 0b31670343f5..a97a80ca0ba7 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -1193,7 +1193,7 @@ void intel_engine_flush_submission(struct intel_engine_cs 
*engine)
 {
struct tasklet_struct *t = &engine->execlists.tasklet;
 
-   if (!t->func)
+   if (!t->callback)
return;
 
/* Synchronise and wait for the tasklet on another CPU */
@@ -1204,7 +1204,7 @@ void intel_engine_flush_submission(struct intel_engine_cs 
*engine)
if (tasklet_trylock(t)) {
/* Must wait for any GPU reset in progress. */
if (__tasklet_is_enabled(t))
-   t->func(t->data);
+   t->callback(t);
tasklet_unlock(t);
}
local_bh_enable();
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c 
b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 26c7d0a50585..20aa0ec09507 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -3194,9 +3194,9 @@ static bool preempt_timeout(const struct intel_engine_cs 
*const engine)
  * Check the unread Context Status Buffers and manage the submission of new
  * contexts to the ELSP accordingly.
  */
-static void execlists_submission_tasklet(unsigned long data)
+static void execlists_submission_tasklet(struct tasklet_struct *t)
 {
-   struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
+   struct intel_engine_cs * const engine = from_tasklet(engine, t, 
execlists.tasklet);
bool timeout = preempt_timeout(engine);
 
process_csb(engine);
@@ -4401,9 +4401,9 @@ static void execlists_reset_rewind(struct intel_engine_cs 
*engine, bool stalled)
spin_unlock_irqrestore(&engine->active.lock, flags);
 }
 
-static void nop_submission_tasklet(unsigned long data)
+static void nop_submission_tasklet(struct tasklet_struct *t)
 {
-   struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
+   struct intel_engine_cs * const engine = from_tasklet(engine, t, 
execlists.tasklet);
 
/* The driver is wedged; don't process any more events. */
WRITE_ONCE(engine->execlists.queue_priority_hint, INT_MIN);
@@ -4487,7 +4487,7 @@ static void execlists_reset_cancel(struct intel_engine_cs 
*engine)
execlists->queue = RB_ROOT_CACHED;
 
GEM_BUG_ON(__tasklet_is_enabled(&execlists->tasklet));
-   execlists->tasklet.func = nop_submission_tasklet;
+   execlists->tasklet.callback = nop_submission_tasklet;
 
spin_unlock_irqrestore(&engine->active.lock, flags);
 }
@@ -4503,7 +4503,7 @@ static void execlists_reset_finish(struct intel_engine_cs 
*engine)
 */
GEM_BUG_ON(!reset_in_progress(execlists));
if (!RB_EMPTY_ROOT(&execlists->queue.rb_root))
-   execlists->tasklet.func(execlists->tasklet.data);
+   execlists->tasklet.callback(&execlists->tasklet);
 
if (__tasklet_enable(&execlists->tasklet))
/* And kick in case we missed a new request submission. */
@@ -5093,7 +5093,7 @@ void intel_execlists_set_default_submission(struct 
intel_engine_cs *engine)
 {
engine->submit_request = execlists_submit_request;
engine->schedule = i915_schedule;
-   engine->execlists.tasklet.func = execlists_submission_tasklet;
+   engine->execlists.tasklet.callback = execlists_submission_tasklet;
 
engine->reset.prepare = execlists_reset_prepare;
engine->reset.rewind = execlists_reset_rewind;
@@ -5220,8 +5220,7 @@ int intel_execlists_submission_setup(struct 
intel_engine_cs *engine)
struct intel_uncore *uncore = engine->uncore;
u32 base = engine->mmio_base;
 
-   tasklet_init(&engine->execlists.tasklet,
-execlists_submission_tasklet, (unsigned long)engine);
+   tasklet_setup(&engine->execlists.tasklet, execlists_submission_tasklet);
timer_setup(&engine->execlists.timer, execlists_timeslice, 0);
timer_setup(&engine->execlists.preempt, execlists_preempt, 0);
 
@@ -5670,9 +5669,9 @@ static intel_engine_mask_t virtual_submission_mask(struct 
virtual_engine *ve)
return ma

[PATCH 1/2] net: usbnet: initialize tasklet using tasklet_init

2021-01-23 Thread Emil Renner Berthing
From: Emil Renner Berthing 

Initialize tasklet using tasklet_init() rather than open-coding it.

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/usb/usbnet.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 1447da1d5729..26455c76588f 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1673,8 +1673,7 @@ usbnet_probe (struct usb_interface *udev, const struct 
usb_device_id *prod)
skb_queue_head_init (&dev->txq);
skb_queue_head_init (&dev->done);
skb_queue_head_init(&dev->rxq_pause);
-   dev->bh.func = usbnet_bh_tasklet;
-   dev->bh.data = (unsigned long)&dev->delay;
+   tasklet_init(&dev->bh, usbnet_bh_tasklet, (unsigned long)&dev->delay);
INIT_WORK (&dev->kevent, usbnet_deferred_kevent);
init_usb_anchor(&dev->deferred);
timer_setup(&dev->delay, usbnet_bh, 0);
-- 
2.30.0



[PATCH 2/2] net: usbnet: use new tasklet API

2021-01-23 Thread Emil Renner Berthing
From: Emil Renner Berthing 

This converts the driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

Signed-off-by: Emil Renner Berthing 
---
 drivers/net/usb/usbnet.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 26455c76588f..e3f1b419a98f 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1539,11 +1539,11 @@ static void usbnet_bh (struct timer_list *t)
}
 }
 
-static void usbnet_bh_tasklet(unsigned long data)
+static void usbnet_bh_tasklet(struct tasklet_struct *t)
 {
-   struct timer_list *t = (struct timer_list *)data;
+   struct usbnet *dev = from_tasklet(dev, t, bh);
 
-   usbnet_bh(t);
+   usbnet_bh(&dev->delay);
 }
 
 
@@ -1673,7 +1673,7 @@ usbnet_probe (struct usb_interface *udev, const struct 
usb_device_id *prod)
skb_queue_head_init (&dev->txq);
skb_queue_head_init (&dev->done);
skb_queue_head_init(&dev->rxq_pause);
-   tasklet_init(&dev->bh, usbnet_bh_tasklet, (unsigned long)&dev->delay);
+   tasklet_setup(&dev->bh, usbnet_bh_tasklet);
INIT_WORK (&dev->kevent, usbnet_deferred_kevent);
init_usb_anchor(&dev->deferred);
timer_setup(&dev->delay, usbnet_bh, 0);
-- 
2.30.0



[PATCH 0/2] net: usbnet: convert to new tasklet API

2021-01-23 Thread Emil Renner Berthing
From: Emil Renner Berthing 

This converts the usbnet driver to use the new tasklet API introduced in
commit 12cc923f1ccc ("tasklet: Introduce new initialization API")

It is split into two commits for ease of reviewing.

Emil Renner Berthing (2):
  net: usbnet: use tasklet_init
  net: usbnet: use new tasklet API

 drivers/net/usb/usbnet.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

-- 
2.30.0



Re: [PATCH v1 2/2] riscv: Clean up module relocations

2020-08-05 Thread Emil Renner Berthing
On Thu, 30 Jul 2020 at 20:53, Luke Nelson  wrote:
>
> Thanks for the patch!
>
> > Also RISC-V has a number of instruction pairs to
> > generate 32bit immediates or jump/call offsets. Eg.:
> >
> > lui   rd, hi20
> > addi  rd, rd, lo12
>
> On RV64, both hi20 from lui and lo12 from addi are sign-extended to 64 bits.
> This means that there are some 32-bit signed offsets (in the range
> [2^31-2^11, 2^31-1])
> that are not encodable using (lui+addi), (auipc+jalr), etc. (see
> discussion at [1]).
>
> The following note is from the ISA manual:
> >>> Note that the set of address offsets that can be formed by pairing LUI 
> >>> with LD,
> >>> AUIPC with JALR, etc. in RV64I is [−2^31−2^11, 2^31−2^11−1].

Good point!

> The existing code and the new code both seem buggy if the offset happens to
> be a 32-bit int but falls outside of the encodable range.
>
> > +   if (offset != (s32)offset) {
> > [...]
> > +   if (offset != (s32)offset) {
> > [...]
>
> These checks should probably be replaced with something similar to
> what's used in the RV64 BPF JIT here: [2],
> except that this code should check if using RV32 or RV64, since the
> encodable range differs for each.

Yeah, I decided to leave these checks as they are to not change
everything at once, but I'll see if I can improve on those in the next
version.

> > My hope is that we can eventually factor out the code to generate
> > immediates and instructions so it can be reused both here, in the
> > jump-label code and in the bpf-jit code, but let's take it
> > one step at a time.
>
> This sounds great! Having fewer copies of RISC-V encoding logic around will
> hopefully decrease the likelihood of bugs :) Some other archs already
> have shared
> infrastructure for doing instruction encoding (e.g., in
> arch/arm64/kernel/insn.c);
> we should consider doing something similar for RISC-V.

Exactly this. I've even tried to copy the naming from arm64 as well.
I'll send a 2nd version of this after -rc1.

>
> - Luke Nelson
>
> [1]: 
> https://groups.google.com/a/groups.riscv.org/forum/#!topic/isa-dev/bwWFhBnnZFQ
> [2]: 
> https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git/commit/?id=489553dd13a88d8a882db10622ba8b9b58582ce4


[PATCH] riscv: Grab text_mutex before patching jump-labels

2020-07-23 Thread Emil Renner Berthing
Like other arch's we use patch_text_nosync or equivalent
to patch the jump-labels, but also like other arch's we
need to hold the text_mutex before calling that.

Signed-off-by: Emil Renner Berthing 
---

Fixes: b6e0878a4ec8 ("riscv: Add jump-label implementation")
..that is already in riscv/for-next.

Palmer: Sorry, I didn't notice this before. Feel free to
squash this into the commit above if you like.
---
 arch/riscv/kernel/jump_label.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/kernel/jump_label.c b/arch/riscv/kernel/jump_label.c
index 1bab1abc1aa5..20e09056d141 100644
--- a/arch/riscv/kernel/jump_label.c
+++ b/arch/riscv/kernel/jump_label.c
@@ -4,8 +4,10 @@
  *
  * Based on arch/arm64/kernel/jump_label.c
  */
-#include 
 #include 
+#include 
+#include 
+#include 
 #include 
 #include 
 
@@ -33,7 +35,9 @@ void arch_jump_label_transform(struct jump_entry *entry,
insn = RISCV_INSN_NOP;
}
 
+   mutex_lock(&text_mutex);
patch_text_nosync(addr, &insn, sizeof(insn));
+   mutex_unlock(&text_mutex);
 }
 
 void arch_jump_label_transform_static(struct jump_entry *entry,
-- 
2.27.0



[PATCH v1 1/2] riscv: Avoid unaligned access when relocating modules

2020-07-22 Thread Emil Renner Berthing
With the C-extension regular 32bit instructions are not
necessarily aligned on 4-byte boundaries. RISC-V instructions
are in fact an ordered list of 16bit native-endian
"parcels", so access the instruction as such.

This should also make the code work in case someone builds
a big-endian RISC-V machine.

Fix rcv -> rvc typo while we're at it.

Signed-off-by: Emil Renner Berthing 
---
 arch/riscv/kernel/module.c | 155 +++--
 1 file changed, 79 insertions(+), 76 deletions(-)

diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index 104fba889cf7..05b2162d96be 100644
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -13,68 +13,86 @@
 #include 
 #include 
 
-static int apply_r_riscv_32_rela(struct module *me, u32 *location, Elf_Addr v)
+static int riscv_insn_rmw(u8 *location, u32 keep, u32 set)
+{
+   u16 *parcel = (u16 *)location;
+   u32 insn = (u32)parcel[0] | (u32)parcel[1] << 16;
+
+   insn &= keep;
+   insn |= set;
+
+   parcel[0] = insn;
+   parcel[1] = insn >> 16;
+   return 0;
+}
+
+static int riscv_insn_rvc_rmw(u8 *location, u16 keep, u16 set)
+{
+   u16 *parcel = (u16 *)location;
+
+   *parcel = (*parcel & keep) | set;
+   return 0;
+}
+
+static int apply_r_riscv_32_rela(struct module *me, u8 *location, Elf_Addr v)
 {
if (v != (u32)v) {
pr_err("%s: value %016llx out of range for 32-bit field\n",
   me->name, (long long)v);
return -EINVAL;
}
-   *location = v;
+   *(u32 *)location = v;
return 0;
 }
 
-static int apply_r_riscv_64_rela(struct module *me, u32 *location, Elf_Addr v)
+static int apply_r_riscv_64_rela(struct module *me, u8 *location, Elf_Addr v)
 {
*(u64 *)location = v;
return 0;
 }
 
-static int apply_r_riscv_branch_rela(struct module *me, u32 *location,
+static int apply_r_riscv_branch_rela(struct module *me, u8 *location,
 Elf_Addr v)
 {
-   ptrdiff_t offset = (void *)v - (void *)location;
+   ptrdiff_t offset = (u8 *)v - location;
u32 imm12 = (offset & 0x1000) << (31 - 12);
u32 imm11 = (offset & 0x800) >> (11 - 7);
u32 imm10_5 = (offset & 0x7e0) << (30 - 10);
u32 imm4_1 = (offset & 0x1e) << (11 - 4);
 
-   *location = (*location & 0x1fff07f) | imm12 | imm11 | imm10_5 | imm4_1;
-   return 0;
+   return riscv_insn_rmw(location, 0x1fff07f, imm12 | imm11 | imm10_5 | 
imm4_1);
 }
 
-static int apply_r_riscv_jal_rela(struct module *me, u32 *location,
+static int apply_r_riscv_jal_rela(struct module *me, u8 *location,
  Elf_Addr v)
 {
-   ptrdiff_t offset = (void *)v - (void *)location;
+   ptrdiff_t offset = (u8 *)v - location;
u32 imm20 = (offset & 0x10) << (31 - 20);
u32 imm19_12 = (offset & 0xff000);
u32 imm11 = (offset & 0x800) << (20 - 11);
u32 imm10_1 = (offset & 0x7fe) << (30 - 10);
 
-   *location = (*location & 0xfff) | imm20 | imm19_12 | imm11 | imm10_1;
-   return 0;
+   return riscv_insn_rmw(location, 0xfff, imm20 | imm19_12 | imm11 | 
imm10_1);
 }
 
-static int apply_r_riscv_rcv_branch_rela(struct module *me, u32 *location,
+static int apply_r_riscv_rvc_branch_rela(struct module *me, u8 *location,
 Elf_Addr v)
 {
-   ptrdiff_t offset = (void *)v - (void *)location;
+   ptrdiff_t offset = (u8 *)v - location;
u16 imm8 = (offset & 0x100) << (12 - 8);
u16 imm7_6 = (offset & 0xc0) >> (6 - 5);
u16 imm5 = (offset & 0x20) >> (5 - 2);
u16 imm4_3 = (offset & 0x18) << (12 - 5);
u16 imm2_1 = (offset & 0x6) << (12 - 10);
 
-   *(u16 *)location = (*(u16 *)location & 0xe383) |
-   imm8 | imm7_6 | imm5 | imm4_3 | imm2_1;
-   return 0;
+   return riscv_insn_rvc_rmw(location, 0xe383,
+   imm8 | imm7_6 | imm5 | imm4_3 | imm2_1);
 }
 
-static int apply_r_riscv_rvc_jump_rela(struct module *me, u32 *location,
+static int apply_r_riscv_rvc_jump_rela(struct module *me, u8 *location,
   Elf_Addr v)
 {
-   ptrdiff_t offset = (void *)v - (void *)location;
+   ptrdiff_t offset = (u8 *)v - location;
u16 imm11 = (offset & 0x800) << (12 - 11);
u16 imm10 = (offset & 0x400) >> (10 - 8);
u16 imm9_8 = (offset & 0x300) << (12 - 11);
@@ -84,16 +102,14 @@ static int apply_r_riscv_rvc_jump_rela(struct module *me, 
u32 *location,
u16 imm4 = (offset & 0x10) << (12 - 5);
u16 imm3_1 = (offset & 0xe) << (12 - 10);
 
-   *(u16 *)location = (*(u16 *)location & 0xe003) |
-

[PATCH v1 2/2] riscv: Clean up module relocations

2020-07-22 Thread Emil Renner Berthing
Factor out generation of different types of immediates.

Also RISC-V has a number of instruction pairs to
generate 32bit immediates or jump/call offsets. Eg.:

lui   rd, hi20
addi  rd, rd, lo12

..where hi20 is the upper 20bits to load into register rd
and lo12 is the lower 12bits. However lo12 is interpreted
as a signed 12bit value. Hence the old code calculates
hi20 and lo12 for 32bit immediates imm like this:

hi20 = (imm + 0x800) & 0xf000;
lo12 = (imm - hi20) & 0xfff;

This patch simplifies it to:

hi20 = (imm + 0x800) & 0xf000;
lo12 = imm & 0xfff;

..which amounts to the same: imm - hi20 may be become
negative/underflow, but it doesn't change the lower 12 bits.

Signed-off-by: Emil Renner Berthing 
---

My hope is that we can eventually factor out the code to generate
immediates and instructions so it can be reused both here, in the
jump-label code and in the bpf-jit code, but let's take it
one step at a time.

/Emil

 arch/riscv/kernel/module.c | 290 +
 1 file changed, 163 insertions(+), 127 deletions(-)

diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index 05b2162d96be..7a8056a1 100644
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -2,8 +2,10 @@
 /*
  *
  *  Copyright (C) 2017 Zihao Yu
+ *  Copyright (C) 2020 Emil Renner Berthing
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -13,24 +15,91 @@
 #include 
 #include 
 
-static int riscv_insn_rmw(u8 *location, u32 keep, u32 set)
+#define RISCV_INSN_I_IMM_MASK 0xfff0U
+#define RISCV_INSN_S_IMM_MASK 0xfe000f80U
+#define RISCV_INSN_B_IMM_MASK 0xfe000f80U
+#define RISCV_INSN_U_IMM_MASK 0xf000U
+#define RISCV_INSN_J_IMM_MASK 0xf000U
+
+#define RISCV_INSN_CI_IMM_MASK  0x107cU
+#define RISCV_INSN_CSS_IMM_MASK 0x1f80U
+#define RISCV_INSN_CIW_IMM_MASK 0x1fe0U
+#define RISCV_INSN_CL_IMM_MASK  0x1c60U
+#define RISCV_INSN_CS_IMM_MASK  0x1c60U
+#define RISCV_INSN_CB_IMM_MASK  0x1c7cU
+#define RISCV_INSN_CJ_IMM_MASK  0x1ffcU
+
+static u32 riscv_insn_i_imm(u32 imm)
+{
+   return (imm & GENMASK(11, 0)) << 20;
+}
+
+static u32 riscv_insn_s_imm(u32 imm)
+{
+   return (imm & GENMASK( 4, 0)) << ( 7 - 0) |
+  (imm & GENMASK(11, 5)) << (25 - 5);
+}
+
+static u32 riscv_insn_b_imm(u32 imm)
+{
+   return (imm & GENMASK(11, 11)) >> (11 -  7) |
+  (imm & GENMASK( 4,  1)) << ( 8 -  1) |
+  (imm & GENMASK(10,  5)) << (25 -  5) |
+  (imm & GENMASK(12, 12)) << (31 - 12);
+}
+
+static u32 riscv_insn_u_imm(u32 imm)
+{
+   return imm & GENMASK(31, 12);
+}
+
+static u32 riscv_insn_j_imm(u32 imm)
+{
+   return (imm & GENMASK(19, 12)) << (12 - 12) |
+  (imm & GENMASK(11, 11)) << (20 - 11) |
+  (imm & GENMASK(10,  1)) << (21 -  1) |
+  (imm & GENMASK(20, 20)) << (31 - 20);
+}
+
+static u16 riscv_insn_rvc_branch_imm(u16 imm)
+{
+   return (imm & GENMASK(5, 5)) >> ( 5 - 2) |
+  (imm & GENMASK(2, 1)) << ( 3 - 1) |
+  (imm & GENMASK(7, 6)) >> ( 6 - 5) |
+  (imm & GENMASK(4, 3)) << (10 - 3) |
+  (imm & GENMASK(8, 8)) << (12 - 8);
+}
+
+static u16 riscv_insn_rvc_jump_imm(u16 imm)
+{
+   return (imm & GENMASK( 5,  5)) >> ( 5 -  2) |
+  (imm & GENMASK( 3,  1)) << ( 3 -  1) |
+  (imm & GENMASK( 7,  7)) >> ( 7 -  6) |
+  (imm & GENMASK( 6,  6)) << ( 7 -  6) |
+  (imm & GENMASK(10, 10)) >> (10 -  8) |
+  (imm & GENMASK( 9,  8)) << ( 9 -  8) |
+  (imm & GENMASK( 4,  4)) << (11 -  4) |
+  (imm & GENMASK(11, 11)) << (12 - 11);
+}
+
+static int riscv_insn_rmw(u8 *location, u32 mask, u32 value)
 {
u16 *parcel = (u16 *)location;
u32 insn = (u32)parcel[0] | (u32)parcel[1] << 16;
 
-   insn &= keep;
-   insn |= set;
+   insn &= ~mask;
+   insn |= value;
 
parcel[0] = insn;
parcel[1] = insn >> 16;
return 0;
 }
 
-static int riscv_insn_rvc_rmw(u8 *location, u16 keep, u16 set)
+static int riscv_insn_rvc_rmw(u8 *location, u16 mask, u16 value)
 {
u16 *parcel = (u16 *)location;
 
-   *parcel = (*parcel & keep) | set;
+   *parcel = (*parcel & ~mask) | value;
return 0;
 }
 
@@ -55,55 +124,40 @@ static int apply_r_riscv_branch_rela(struct module *me, u8 
*location,
 Elf_Addr v)
 {
ptrdiff_t offset = (u8 *)v - location;
-   u32 imm12 = (offset & 0x1000) << (31 - 12);
-   u32 imm11 = (offset & 0x800) >> (11 - 7);
-   u32 imm10_5 = (offset & 0x7e0) << (30 - 10);
-   u32 imm4_1 =

Re: [PATCH v2 3/3] spi: rockchip: Fix error in SPI slave pio read

2020-07-22 Thread Emil Renner Berthing
On Wed, 22 Jul 2020 at 10:38, Jon Lin  wrote:
>
> The RXFLR is possible larger than rx_left in Rockchip SPI, fix it.
>
> Signed-off-by: Jon Lin 
> Reviewed-by: Heiko Stuebner 

In addition to my review and test you should probably also add
Fixes: 01b59ce5dac8 ("spi: rockchip: use irq rather than polling")
..so this will be picked up in the stable trees

/Emil

> ---
>  drivers/spi/spi-rockchip.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
> index a451dacab5cf..75a8a9428ff8 100644
> --- a/drivers/spi/spi-rockchip.c
> +++ b/drivers/spi/spi-rockchip.c
> @@ -291,7 +291,7 @@ static void rockchip_spi_pio_writer(struct rockchip_spi 
> *rs)
>  static void rockchip_spi_pio_reader(struct rockchip_spi *rs)
>  {
> u32 words = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
> -   u32 rx_left = rs->rx_left - words;
> +   u32 rx_left = (rs->rx_left > words) ? rs->rx_left - words : 0;
>
> /* the hardware doesn't allow us to change fifo threshold
>  * level while spi is enabled, so instead make sure to leave
> --
> 2.17.1
>
>
>
>
> ___
> Linux-rockchip mailing list
> linux-rockc...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip


Re: [PATCH v2 1/3] spi: rockchip: Config spi rx dma burst size depend on xfer length

2020-07-22 Thread Emil Renner Berthing
On Wed, 22 Jul 2020 at 10:41, Jon Lin  wrote:
>
> The burst length can be adjusted according to the transmission
> length to improve the transmission rate
>
> Signed-off-by: Jon Lin 

For the whole series you can add
Reviewed-by: Emil Renner Berthing 
Tested-by: Emil Renner Berthing 

> ---
>  drivers/spi/spi-rockchip.c | 19 +--
>  1 file changed, 17 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
> index 9b8a5e1233c0..63593a5b87fa 100644
> --- a/drivers/spi/spi-rockchip.c
> +++ b/drivers/spi/spi-rockchip.c
> @@ -384,6 +384,19 @@ static void rockchip_spi_dma_txcb(void *data)
> spi_finalize_current_transfer(ctlr);
>  }
>
> +static u32 rockchip_spi_calc_burst_size(u32 data_len)
> +{
> +   u32 i;
> +
> +   /* burst size: 1, 2, 4, 8 */
> +   for (i = 1; i < 8; i <<= 1) {
> +   if (data_len & i)
> +   break;
> +   }
> +
> +   return i;
> +}
> +
>  static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
> struct spi_controller *ctlr, struct spi_transfer *xfer)
>  {
> @@ -397,7 +410,8 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi 
> *rs,
> .direction = DMA_DEV_TO_MEM,
> .src_addr = rs->dma_addr_rx,
> .src_addr_width = rs->n_bytes,
> -   .src_maxburst = 1,
> +   .src_maxburst = 
> rockchip_spi_calc_burst_size(xfer->len /
> +
> rs->n_bytes),
> };
>
> dmaengine_slave_config(ctlr->dma_rx, &rxconf);
> @@ -525,7 +539,8 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
> writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + 
> ROCKCHIP_SPI_RXFTLR);
>
> writel_relaxed(rs->fifo_len / 2, rs->regs + ROCKCHIP_SPI_DMATDLR);
> -   writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMARDLR);
> +   writel_relaxed(rockchip_spi_calc_burst_size(xfer->len / rs->n_bytes) 
> - 1,
> +  rs->regs + ROCKCHIP_SPI_DMARDLR);
> writel_relaxed(dmacr, rs->regs + ROCKCHIP_SPI_DMACR);
>
> /* the hardware only supports an even clock divisor, so
> --
> 2.17.1
>
>
>
>
> ___
> Linux-rockchip mailing list
> linux-rockc...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip


Re: [PATCH] riscv: Select ARCH_HAS_DEBUG_VM_PGTABLE

2020-07-20 Thread Emil Renner Berthing
On Tue, 21 Jul 2020 at 06:04, Palmer Dabbelt  wrote:
>
> On Tue, 14 Jul 2020 20:20:54 PDT (-0700), anshuman.khand...@arm.com wrote:
> >
> >
> > On 07/15/2020 02:56 AM, Emil Renner Berthing wrote:
> >> This allows the pgtable tests to be built.
> >>
> >> Signed-off-by: Emil Renner Berthing 
> >> ---
> >>
> >> The tests seem to succeed both in Qemu and on the HiFive Unleashed
> >>
> >> Both with and without the recent additions in
> >> https://lore.kernel.org/linux-riscv/1594610587-4172-1-git-send-email-anshuman.khand...@arm.com/
> >
> > That's great, thanks for testing.
>
> Actually, looking at this I'm not sure it actually helps us any.  This changes
> the behavior of two functions.  Pulling out the relevant sections, I see:
>
> unsigned int __sw_hweight32(unsigned int w)
> {
> #ifdef CONFIG_ARCH_HAS_FAST_MULTIPLIER
> w -= (w >> 1) & 0x;
> w =  (w & 0x) + ((w >> 2) & 0x);
> w =  (w + (w >> 4)) & 0x0f0f0f0f;
> return (w * 0x01010101) >> 24;
> #else
> unsigned int res = w - ((w >> 1) & 0x);
> res = (res & 0x) + ((res >> 2) & 0x);
> res = (res + (res >> 4)) & 0x0F0F0F0F;
> res = res + (res >> 8);
> return (res + (res >> 16)) & 0x00FF;
> #endif
> }
>
> and
>
> unsigned long memchr_inv(unsigned long value64)
> {
> #if defined(CONFIG_ARCH_HAS_FAST_MULTIPLIER) && BITS_PER_LONG == 64
> value64 *= 0x0101010101010101ULL;
> #elif defined(CONFIG_ARCH_HAS_FAST_MULTIPLIER)
> value64 *= 0x01010101;
> value64 |= value64 << 32;
> #else
> value64 |= value64 << 8;
> value64 |= value64 << 16;
> value64 |= value64 << 32;
> #endif
> return value64;
> }
>
> GCC optimizer the multiplication out of the first one:
>
> __sw_hweight32:
> li  a4,1431654400
> srliw   a5,a0,1
> addia4,a4,1365
> and a5,a5,a4
> subwa0,a0,a5
> li  a5,858992640
> srliw   a4,a0,2
> addia5,a5,819
> and a0,a5,a0
> and a5,a5,a4
> addwa5,a0,a5
> srliw   a0,a5,4
> addwa0,a0,a5
> li  a5,252645376
> addia5,a5,-241
> and a5,a5,a0
> srliw   a0,a5,8
> addwa5,a0,a5
> srliw   a0,a5,16
> addwa0,a0,a5
> andia0,a0,0xff
> ret
>
> __sw_hweight32:
> li  a5,1431654400
> srliw   a4,a0,1
> addia5,a5,1365
> and a5,a5,a4
> subwa0,a0,a5
> li  a5,858992640
> srliw   a4,a0,2
> addia5,a5,819
> and a0,a5,a0
> and a5,a5,a4
> addwa5,a0,a5
> srliw   a0,a5,4
> addwa5,a0,a5
> li  a0,252645376
> addia0,a0,-241
> and a5,a0,a5
> slliw   a0,a5,8
> addwa0,a0,a5
> slliw   a5,a0,16
> addwa0,a0,a5
> srliw   a0,a0,24
> ret
>
> so that doesn't matter.  The second one is really a wash:
>
> memchr_inv:
> ld  a5,.LC0
> mul a0,a0,a5
> ret
> .rodata
> .LC0:
> .dword  72340172838076673
>
> vs
>
> memchr_inv:
> sllia5,a0,8
> or  a5,a5,a0
> sllia0,a5,16
> or  a0,a0,a5
> sllia5,a0,32
> or  a0,a5,a0
> ret
>
> It's unlikely that load ends up relaxed, so it's going to be two instructions.
> That means we have 4 cycles to forward the load and multiply, for a cache hit.
> IIRC the multiplier on the existing hardware isn't that fast -- GCC lists it 
> as
> imul as 10 cycles, but I remember it being more like 5 so that might just be 
> an
> architecture-inaccurate tuning in the generic pipeline model.  This is out of
> the inner loop, so it's probably not all that important anyway.  The result
> isn't used for a while so on a bigger machine it's probably worth picking the
> smaller code path, but it seems like a very small thing to optimize for either
> way.
>
> I'm actually a bit surprised about this.  Do you have benchmarks that indicate
> ARCH_HAS_FAST_MULTIPLIER is actually faster?  Otherwise I guess I'm going to
> reject this, as it's really more
> ARCH_HAS_FAST_MULTIPLIER_AND_FAST_LARGE_CONSTANTS than just
> ARCH_HAS_FAST_MULTIPLIER.

Hi Palmer,

I think you meant this reply for
https://lore.kernel.org/linux-riscv/c5d82526-233a-15d5-90df-ca0c25a53...@eswin.com/T/#t

/Emil


Re: [PATCH] asm-generic/mmiowb: Allow mmiowb_set_pending() when preemptible()

2020-07-16 Thread Emil Renner Berthing
On Thu, 16 Jul 2020 at 13:28, Will Deacon  wrote:
>
> Although mmiowb() is concerned only with serialising MMIO writes occuring
> in contexts where a spinlock is held, the call to mmiowb_set_pending()
> from the MMIO write accessors can occur in preemptible contexts, such
> as during driver probe() functions where ordering between CPUs is not
> usually a concern, assuming that the task migration path provides the
> necessary ordering guarantees.
>
> Unfortunately, the default implementation of mmiowb_set_pending() is not
> preempt-safe, as it makes use of a a per-cpu variable to track its
> internal state. This has been reported to generate the following splat
> on riscv:
>
>  | BUG: using smp_processor_id() in preemptible [] code: swapper/0/1
>  | caller is regmap_mmio_write32le+0x1c/0x46
>  | CPU: 3 PID: 1 Comm: swapper/0 Not tainted 5.8.0-rc3-hfu+ #1
>  | Call Trace:
>  |  walk_stackframe+0x0/0x7a
>  |  dump_stack+0x6e/0x88
>  |  regmap_mmio_write32le+0x18/0x46
>  |  check_preemption_disabled+0xa4/0xaa
>  |  regmap_mmio_write32le+0x18/0x46
>  |  regmap_mmio_write+0x26/0x44
>  |  regmap_write+0x28/0x48
>  |  sifive_gpio_probe+0xc0/0x1da
>
> Although it's possible to fix the driver in this case, other splats have
> been seen from other drivers, including the infamous 8250 UART, and so
> it's better to address this problem in the mmiowb core itself.
>
> Fix mmiowb_set_pending() by using the raw_cpu_ptr() to get at the mmiowb
> state and then only updating the 'mmiowb_pending' field if we are not
> preemptible (i.e. we have a non-zero nesting count).
>
> Cc: Arnd Bergmann 
> Cc: Paul Walmsley 
> Cc: Guo Ren 
> Cc: Michael Ellerman 
> Reported-by: Palmer Dabbelt 

Nice. This fixes the problems I saw both in Qemu and on the HiFive Unleashed.

Btw. I was the one who originally stumbled upon this problem and send
the mail to linux-riscv that Palmer CC'ed you on, so I think this
ought to be
Reported-by: Emil Renner Berthing 

In any case you can add
Tested-by: Emil Renner Berthing 

> Signed-off-by: Will Deacon 
> ---
>
> I can queue this in the arm64 tree as a fix, as I already have some other
> fixes targetting -rc6.
>
>  include/asm-generic/mmiowb.h | 6 --
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/include/asm-generic/mmiowb.h b/include/asm-generic/mmiowb.h
> index 9439ff037b2d..5698fca3bf56 100644
> --- a/include/asm-generic/mmiowb.h
> +++ b/include/asm-generic/mmiowb.h
> @@ -27,7 +27,7 @@
>  #include 
>
>  DECLARE_PER_CPU(struct mmiowb_state, __mmiowb_state);
> -#define __mmiowb_state()   this_cpu_ptr(&__mmiowb_state)
> +#define __mmiowb_state()   raw_cpu_ptr(&__mmiowb_state)
>  #else
>  #define __mmiowb_state()   arch_mmiowb_state()
>  #endif /* arch_mmiowb_state */
> @@ -35,7 +35,9 @@ DECLARE_PER_CPU(struct mmiowb_state, __mmiowb_state);
>  static inline void mmiowb_set_pending(void)
>  {
> struct mmiowb_state *ms = __mmiowb_state();
> -   ms->mmiowb_pending = ms->nesting_count;
> +
> +   if (likely(ms->nesting_count))
> +   ms->mmiowb_pending = ms->nesting_count;
>  }
>
>  static inline void mmiowb_spin_lock(void)
> --
> 2.27.0.389.gc38d7665816-goog
>
>
> ___
> linux-riscv mailing list
> linux-ri...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-riscv


Re: [PATCH v3 0/4] Dedicated CLINT timer driver

2020-07-15 Thread Emil Renner Berthing
On Wed, 15 Jul 2020 at 09:15, Anup Patel  wrote:
> The current RISC-V timer driver is convoluted and implements two
> distinct timers:
>  1. S-mode timer: This is for Linux RISC-V S-mode with MMU. The
> clocksource is implemented using TIME CSR and clockevent device
> is implemented using SBI Timer calls.
>  2. M-mode timer: This is for Linux RISC-V M-mode without MMU. The
> clocksource is implemented using CLINT MMIO time register and
> clockevent device is implemented using CLINT MMIO timecmp registers.
>
> This patchset removes clint related code from RISC-V timer driver and
> arch/riscv directory. Instead, the series adds a dedicated MMIO based
> CLINT driver under drivers/clocksource directory which can be used by
> Linux RISC-V M-mode (i.e NoMMU Linux RISC-V).
>
> The patchset is based up Linux-5.8-rc5 and can be found at riscv_clint_v3
> branch of: https://github.com/avpatel/linux.git
>
> This series is tested on:
>  1. QEMU RV64 virt machine using Linux RISC-V S-mode
>  2. QEMU RV32 virt machine using Linux RISC-V S-mode
>  3. QEMU RV64 virt machine using Linux RISC-V M-mode (i.e. NoMMU)
>
> Changes since v2:
>  - Rebased series on Linux-5.8-rc5
>  - Squashed PATCH3 onto PATCH2 to preserve GIT bisectability
>  - Moved PATCH4 before PATCH2 to preserve GIT bisectability
>  - Replaced CLINT dt-bindings text document with YAML schema
>  - Use SiFive CLINT compatible string as per SiFive IP block versioning
>
> Changes since v1:
>  - Rebased series on Linux-5.8-rc2
>  - Added pr_warn() for case where ipi_ops not available in PATCH1
>  - Updated ipi_inject() prototype to use "struct cpumask *" in PATCH1
>  - Updated CLINT_TIMER kconfig option to depend on RISCV_M_MODE in PATCH4
>  - Added riscv,clint0 compatible string in DT bindings document
>
> Anup Patel (4):
>   RISC-V: Add mechanism to provide custom IPI operations
>   clocksource/drivers: Add CLINT timer driver
>   RISC-V: Remove CLINT related code from timer and arch
>   dt-bindings: timer: Add CLINT bindings
>
>  .../bindings/timer/sifive,clint.yaml  |  58 +
>  arch/riscv/Kconfig|   2 +-
>  arch/riscv/include/asm/clint.h|  39 ---
>  arch/riscv/include/asm/smp.h  |  19 ++
>  arch/riscv/include/asm/timex.h|  28 +--
>  arch/riscv/kernel/Makefile|   2 +-
>  arch/riscv/kernel/clint.c |  44 
>  arch/riscv/kernel/sbi.c   |  14 ++
>  arch/riscv/kernel/setup.c |   2 -
>  arch/riscv/kernel/smp.c   |  44 ++--
>  arch/riscv/kernel/smpboot.c   |   4 +-
>  drivers/clocksource/Kconfig   |  12 +-
>  drivers/clocksource/Makefile  |   1 +
>  drivers/clocksource/timer-clint.c | 229 ++
>  drivers/clocksource/timer-riscv.c |  17 +-
>  include/linux/cpuhotplug.h|   1 +
>  16 files changed, 369 insertions(+), 147 deletions(-)
>  create mode 100644 Documentation/devicetree/bindings/timer/sifive,clint.yaml
>  delete mode 100644 arch/riscv/include/asm/clint.h
>  delete mode 100644 arch/riscv/kernel/clint.c
>  create mode 100644 drivers/clocksource/timer-clint.c

If it makes any difference I tested this both in Qemu and on the
HiFive Unleashed,
but I don't have a working no-mmu setup.

Tested-by: Emil Renner Berhing 

/Emil


[PATCH] riscv: Select ARCH_HAS_DEBUG_VM_PGTABLE

2020-07-14 Thread Emil Renner Berthing
This allows the pgtable tests to be built.

Signed-off-by: Emil Renner Berthing 
---

The tests seem to succeed both in Qemu and on the HiFive Unleashed

Both with and without the recent additions in
https://lore.kernel.org/linux-riscv/1594610587-4172-1-git-send-email-anshuman.khand...@arm.com/

 Documentation/features/debug/debug-vm-pgtable/arch-support.txt | 2 +-
 arch/riscv/Kconfig | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt 
b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt
index c527d05c0459..c9a764c3c795 100644
--- a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt
+++ b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt
@@ -23,7 +23,7 @@
 |openrisc: | TODO |
 |  parisc: | TODO |
 | powerpc: |  ok  |
-|   riscv: | TODO |
+|   riscv: |  ok  |
 |s390: |  ok  |
 |  sh: | TODO |
 |   sparc: | TODO |
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 3230c1d48562..b4e674b1e857 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -15,6 +15,7 @@ config RISCV
select ARCH_CLOCKSOURCE_INIT
select ARCH_HAS_BINFMT_FLAT
select ARCH_HAS_DEBUG_VIRTUAL if MMU
+   select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DEBUG_WX
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE
-- 
2.27.0



[PATCH v3 2/2] riscv: Add jump-label implementation

2020-07-14 Thread Emil Renner Berthing
Add jump-label implementation based on the ARM64 version
and add CONFIG_JUMP_LABEL=y to the defconfigs.

Signed-off-by: Emil Renner Berthing 
Reviewed-by: Björn Töpel 
Tested-by: Björn Töpel 
---
Tested on the HiFive Unleashed board.

Changes since v2:
- Add missing asm/asm.h include.
  Reported-by: kernel test robot 

Changes since v1:
- WARN and give up gracefully if the jump offset cannot be
  represented in a JAL instruction.
- Add missing braces.
- Add CONFIG_JUMP_LABEL=y to defconfigs.

All suggested by Björn Töpel.

Changes since RFC:
- Use RISCV_PTR and RISCV_LGPTR macros to match struct jump_table
  also in 32bit kernels.
- Remove unneeded branch ? 1 : 0, thanks Björn
- Fix \n\n instead of \n\t mistake

 .../core/jump-labels/arch-support.txt |  2 +-
 arch/riscv/Kconfig|  2 +
 arch/riscv/configs/defconfig  |  1 +
 arch/riscv/configs/nommu_k210_defconfig   |  1 +
 arch/riscv/configs/nommu_virt_defconfig   |  1 +
 arch/riscv/configs/rv32_defconfig |  1 +
 arch/riscv/include/asm/jump_label.h   | 60 +++
 arch/riscv/kernel/Makefile|  2 +
 arch/riscv/kernel/jump_label.c| 49 +++
 9 files changed, 118 insertions(+), 1 deletion(-)
 create mode 100644 arch/riscv/include/asm/jump_label.h
 create mode 100644 arch/riscv/kernel/jump_label.c

diff --git a/Documentation/features/core/jump-labels/arch-support.txt 
b/Documentation/features/core/jump-labels/arch-support.txt
index 632a1c7aefa2..760243d18ed7 100644
--- a/Documentation/features/core/jump-labels/arch-support.txt
+++ b/Documentation/features/core/jump-labels/arch-support.txt
@@ -23,7 +23,7 @@
 |openrisc: | TODO |
 |  parisc: |  ok  |
 | powerpc: |  ok  |
-|   riscv: | TODO |
+|   riscv: |  ok  |
 |s390: |  ok  |
 |  sh: | TODO |
 |   sparc: |  ok  |
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index c6d4f7771bff..3beb844c5951 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -48,6 +48,8 @@ config RISCV
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
select HANDLE_DOMAIN_IRQ
select HAVE_ARCH_AUDITSYSCALL
+   select HAVE_ARCH_JUMP_LABEL
+   select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if MMU && 64BIT
select HAVE_ARCH_KGDB
select HAVE_ARCH_KGDB_QXFER_PKT
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 4da4886246a4..d58c93efb603 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
 CONFIG_SOC_SIFIVE=y
 CONFIG_SOC_VIRT=y
 CONFIG_SMP=y
+CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_NET=y
diff --git a/arch/riscv/configs/nommu_k210_defconfig 
b/arch/riscv/configs/nommu_k210_defconfig
index b48138e329ea..cd1df62b13c7 100644
--- a/arch/riscv/configs/nommu_k210_defconfig
+++ b/arch/riscv/configs/nommu_k210_defconfig
@@ -33,6 +33,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_CMDLINE="earlycon console=ttySIF0"
 CONFIG_CMDLINE_FORCE=y
+CONFIG_JUMP_LABEL=y
 # CONFIG_BLOCK is not set
 CONFIG_BINFMT_FLAT=y
 # CONFIG_COREDUMP is not set
diff --git a/arch/riscv/configs/nommu_virt_defconfig 
b/arch/riscv/configs/nommu_virt_defconfig
index cf74e179bf90..f27596e9663e 100644
--- a/arch/riscv/configs/nommu_virt_defconfig
+++ b/arch/riscv/configs/nommu_virt_defconfig
@@ -30,6 +30,7 @@ CONFIG_MAXPHYSMEM_2GB=y
 CONFIG_SMP=y
 CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x1000,115200n8 
console=ttyS0"
 CONFIG_CMDLINE_FORCE=y
+CONFIG_JUMP_LABEL=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 # CONFIG_MSDOS_PARTITION is not set
diff --git a/arch/riscv/configs/rv32_defconfig 
b/arch/riscv/configs/rv32_defconfig
index 05bbf5240569..3a55f0e00d6c 100644
--- a/arch/riscv/configs/rv32_defconfig
+++ b/arch/riscv/configs/rv32_defconfig
@@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
 CONFIG_SOC_VIRT=y
 CONFIG_ARCH_RV32I=y
 CONFIG_SMP=y
+CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_NET=y
diff --git a/arch/riscv/include/asm/jump_label.h 
b/arch/riscv/include/asm/jump_label.h
new file mode 100644
index ..38af2ec7b9bf
--- /dev/null
+++ b/arch/riscv/include/asm/jump_label.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Emil Renner Berthing
+ *
+ * Based on arch/arm64/include/asm/jump_label.h
+ */
+#ifndef __ASM_JUMP_LABEL_H
+#define __ASM_JUMP_LABEL_H
+
+#ifndef __ASSEMBLY__
+
+#include 
+#include 
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+  bool branch)
+{
+   asm_volatile_goto(
+   "   .option push\n\t"
+   "   .option norelax 

[PATCH v3 1/2] riscv: Support R_RISCV_ADD64 and R_RISCV_SUB64 relocs

2020-07-14 Thread Emil Renner Berthing
These are needed for the __jump_table in modules using
static keys/jump-labels with the layout from
HAVE_ARCH_JUMP_LABEL_RELATIVE on 64bit kernels.

Signed-off-by: Emil Renner Berthing 
Reviewed-by: Björn Töpel 
Tested-by: Björn Töpel 
---
Tested on the HiFive Unleashed board.

No changes since v2.

This patch is new in v2. It fixes an error loading modules
containing static keys found by Björn Töpel.

 arch/riscv/kernel/module.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index 7191342c54da..104fba889cf7 100644
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -263,6 +263,13 @@ static int apply_r_riscv_add32_rela(struct module *me, u32 
*location,
return 0;
 }
 
+static int apply_r_riscv_add64_rela(struct module *me, u32 *location,
+   Elf_Addr v)
+{
+   *(u64 *)location += (u64)v;
+   return 0;
+}
+
 static int apply_r_riscv_sub32_rela(struct module *me, u32 *location,
Elf_Addr v)
 {
@@ -270,6 +277,13 @@ static int apply_r_riscv_sub32_rela(struct module *me, u32 
*location,
return 0;
 }
 
+static int apply_r_riscv_sub64_rela(struct module *me, u32 *location,
+   Elf_Addr v)
+{
+   *(u64 *)location -= (u64)v;
+   return 0;
+}
+
 static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
Elf_Addr v) = {
[R_RISCV_32]= apply_r_riscv_32_rela,
@@ -290,7 +304,9 @@ static int (*reloc_handlers_rela[]) (struct module *me, u32 
*location,
[R_RISCV_RELAX] = apply_r_riscv_relax_rela,
[R_RISCV_ALIGN] = apply_r_riscv_align_rela,
[R_RISCV_ADD32] = apply_r_riscv_add32_rela,
+   [R_RISCV_ADD64] = apply_r_riscv_add64_rela,
[R_RISCV_SUB32] = apply_r_riscv_sub32_rela,
+   [R_RISCV_SUB64] = apply_r_riscv_sub64_rela,
 };
 
 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
-- 
2.27.0



[PATCH v2 2/2] riscv: Add jump-label implementation

2020-07-08 Thread Emil Renner Berthing
Add jump-label implementation based on the ARM64 version
and add CONFIG_JUMP_LABEL=y to the defconfigs.

Signed-off-by: Emil Renner Berthing 
Reviewed-by: Björn Töpel 
---

Tested on the HiFive Unleashed board.

Changes since v1:
- WARN and give up gracefully if the jump offset cannot be
  represented in a JAL instruction.
- Add missing braces.
- Add CONFIG_JUMP_LABEL=y to defconfigs.

All suggested by Björn Töpel.

Changes since RFC:
- Use RISCV_PTR and RISCV_LGPTR macros to match struct jump_table
  also in 32bit kernels.
- Remove unneeded branch ? 1 : 0, thanks Björn
- Fix \n\n instead of \n\t mistake

 .../core/jump-labels/arch-support.txt |  2 +-
 arch/riscv/Kconfig|  2 +
 arch/riscv/configs/defconfig  |  1 +
 arch/riscv/configs/nommu_k210_defconfig   |  1 +
 arch/riscv/configs/nommu_virt_defconfig   |  1 +
 arch/riscv/configs/rv32_defconfig |  1 +
 arch/riscv/include/asm/jump_label.h   | 59 +++
 arch/riscv/kernel/Makefile|  2 +
 arch/riscv/kernel/jump_label.c| 49 +++
 9 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 arch/riscv/include/asm/jump_label.h
 create mode 100644 arch/riscv/kernel/jump_label.c

diff --git a/Documentation/features/core/jump-labels/arch-support.txt 
b/Documentation/features/core/jump-labels/arch-support.txt
index 632a1c7aefa2..760243d18ed7 100644
--- a/Documentation/features/core/jump-labels/arch-support.txt
+++ b/Documentation/features/core/jump-labels/arch-support.txt
@@ -23,7 +23,7 @@
 |openrisc: | TODO |
 |  parisc: |  ok  |
 | powerpc: |  ok  |
-|   riscv: | TODO |
+|   riscv: |  ok  |
 |s390: |  ok  |
 |  sh: | TODO |
 |   sparc: |  ok  |
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index fd639937e251..d2f5c53fdc19 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -46,6 +46,8 @@ config RISCV
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
select HANDLE_DOMAIN_IRQ
select HAVE_ARCH_AUDITSYSCALL
+   select HAVE_ARCH_JUMP_LABEL
+   select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if MMU && 64BIT
select HAVE_ARCH_KGDB
select HAVE_ARCH_KGDB_QXFER_PKT
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 4da4886246a4..d58c93efb603 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
 CONFIG_SOC_SIFIVE=y
 CONFIG_SOC_VIRT=y
 CONFIG_SMP=y
+CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_NET=y
diff --git a/arch/riscv/configs/nommu_k210_defconfig 
b/arch/riscv/configs/nommu_k210_defconfig
index b48138e329ea..cd1df62b13c7 100644
--- a/arch/riscv/configs/nommu_k210_defconfig
+++ b/arch/riscv/configs/nommu_k210_defconfig
@@ -33,6 +33,7 @@ CONFIG_SMP=y
 CONFIG_NR_CPUS=2
 CONFIG_CMDLINE="earlycon console=ttySIF0"
 CONFIG_CMDLINE_FORCE=y
+CONFIG_JUMP_LABEL=y
 # CONFIG_BLOCK is not set
 CONFIG_BINFMT_FLAT=y
 # CONFIG_COREDUMP is not set
diff --git a/arch/riscv/configs/nommu_virt_defconfig 
b/arch/riscv/configs/nommu_virt_defconfig
index cf74e179bf90..f27596e9663e 100644
--- a/arch/riscv/configs/nommu_virt_defconfig
+++ b/arch/riscv/configs/nommu_virt_defconfig
@@ -30,6 +30,7 @@ CONFIG_MAXPHYSMEM_2GB=y
 CONFIG_SMP=y
 CONFIG_CMDLINE="root=/dev/vda rw earlycon=uart8250,mmio,0x1000,115200n8 
console=ttyS0"
 CONFIG_CMDLINE_FORCE=y
+CONFIG_JUMP_LABEL=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 # CONFIG_MSDOS_PARTITION is not set
diff --git a/arch/riscv/configs/rv32_defconfig 
b/arch/riscv/configs/rv32_defconfig
index 05bbf5240569..3a55f0e00d6c 100644
--- a/arch/riscv/configs/rv32_defconfig
+++ b/arch/riscv/configs/rv32_defconfig
@@ -17,6 +17,7 @@ CONFIG_BPF_SYSCALL=y
 CONFIG_SOC_VIRT=y
 CONFIG_ARCH_RV32I=y
 CONFIG_SMP=y
+CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_NET=y
diff --git a/arch/riscv/include/asm/jump_label.h 
b/arch/riscv/include/asm/jump_label.h
new file mode 100644
index ..d5fb342bfccf
--- /dev/null
+++ b/arch/riscv/include/asm/jump_label.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Emil Renner Berthing
+ *
+ * Based on arch/arm64/include/asm/jump_label.h
+ */
+#ifndef __ASM_JUMP_LABEL_H
+#define __ASM_JUMP_LABEL_H
+
+#ifndef __ASSEMBLY__
+
+#include 
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+  bool branch)
+{
+   asm_volatile_goto(
+   "   .option push\n\t"
+   "   .option norelax \n\t"
+   "   .option norvc   \n\t"
+   "1: nop   

[PATCH v2 1/2] riscv: Support R_RISCV_ADD64 and R_RISCV_SUB64 relocs

2020-07-08 Thread Emil Renner Berthing
These are needed for the __jump_table in modules using
static keys/jump-labels with the layout from
HAVE_ARCH_JUMP_LABEL_RELATIVE on 64bit kernels.

Signed-off-by: Emil Renner Berthing 
---

Tested on the HiFive Unleashed board.

This patch is new in v2. It fixes an error loading modules
containing static keys found by Björn Töpel.

 arch/riscv/kernel/module.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/arch/riscv/kernel/module.c b/arch/riscv/kernel/module.c
index 7191342c54da..104fba889cf7 100644
--- a/arch/riscv/kernel/module.c
+++ b/arch/riscv/kernel/module.c
@@ -263,6 +263,13 @@ static int apply_r_riscv_add32_rela(struct module *me, u32 
*location,
return 0;
 }
 
+static int apply_r_riscv_add64_rela(struct module *me, u32 *location,
+   Elf_Addr v)
+{
+   *(u64 *)location += (u64)v;
+   return 0;
+}
+
 static int apply_r_riscv_sub32_rela(struct module *me, u32 *location,
Elf_Addr v)
 {
@@ -270,6 +277,13 @@ static int apply_r_riscv_sub32_rela(struct module *me, u32 
*location,
return 0;
 }
 
+static int apply_r_riscv_sub64_rela(struct module *me, u32 *location,
+   Elf_Addr v)
+{
+   *(u64 *)location -= (u64)v;
+   return 0;
+}
+
 static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
Elf_Addr v) = {
[R_RISCV_32]= apply_r_riscv_32_rela,
@@ -290,7 +304,9 @@ static int (*reloc_handlers_rela[]) (struct module *me, u32 
*location,
[R_RISCV_RELAX] = apply_r_riscv_relax_rela,
[R_RISCV_ALIGN] = apply_r_riscv_align_rela,
[R_RISCV_ADD32] = apply_r_riscv_add32_rela,
+   [R_RISCV_ADD64] = apply_r_riscv_add64_rela,
[R_RISCV_SUB32] = apply_r_riscv_sub32_rela,
+   [R_RISCV_SUB64] = apply_r_riscv_sub64_rela,
 };
 
 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
-- 
2.27.0



Re: [PATCH v1] riscv: Add jump-label implementation

2020-07-08 Thread Emil Renner Berthing
On Wed, 8 Jul 2020 at 09:42, Björn Töpel  wrote:
>
> On Tue, 7 Jul 2020 at 17:08, Emil Renner Berthing  wrote:
> >
> > Add jump-label implementation based on the ARM64 version.
> >
> > Tested on the HiFive Unleashed board.
> >
>
> I took your patch for a spin on qemu. The boot selftest
> (CONFIG_STATIC_KEYS_SELFTEST=y) passes, but the module test
> (CONFIG_TEST_STATIC_KEYS=m) does not.
>
> When I run the in "test tools/testing/selftests/static_keys" (this
> simply loads the test_static_key_base.ko and test_static_keys.ko
> modules) I get:
>
> [  134.090464] test_static_keys: Unknown relocation type 36
>
> 36 is the relocation type R_RISCV_ADD64, which is not handled in
> arch/riscv/kernel/module.c.
>
> If you dump the relocation entries for test_static_keys.ko
> (riscv64-linux-gnu-objdump -r test_static_keys.ko), you'll see that:
>
> RELOCATION RECORDS FOR [__jump_table]:
> OFFSET   TYPE  VALUE
>  R_RISCV_ADD32 .L1^B1
>  R_RISCV_SUB32 .L0
> 0004 R_RISCV_ADD32 .L3
> 0004 R_RISCV_SUB32 .L0
> 0008 R_RISCV_ADD64 old_true_key+0x0001
> 0008 R_RISCV_SUB64 .L0
> ...
>
> It would be great if you could add a patch for that as well (separate,
> same series). R_RISCV_ADD64 *and* R_RISCV_SUB64 are currently
> unhandled by module.c.

On it! I'll also add the CONFIG_JUMP_LABEL to defconfig to the next version.
>
> Cheers,
> Björn
>
> > Signed-off-by: Emil Renner Berthing 
> > ---
> >
> > Changes since RFC:
> > - Use RISCV_PTR and RISCV_LGPTR macros to match struct jump_table
> >   also in 32bit kernels.
> > - Remove unneeded branch ? 1 : 0, thanks Björn
> > - Fix \n\n instead of \n\t mistake
> >
> >  .../core/jump-labels/arch-support.txt |  2 +-
> >  arch/riscv/Kconfig|  2 +
> >  arch/riscv/include/asm/jump_label.h   | 59 +++
> >  arch/riscv/kernel/Makefile|  2 +
> >  arch/riscv/kernel/jump_label.c| 44 ++
> >  5 files changed, 108 insertions(+), 1 deletion(-)
> >  create mode 100644 arch/riscv/include/asm/jump_label.h
> >  create mode 100644 arch/riscv/kernel/jump_label.c
> >
> > diff --git a/Documentation/features/core/jump-labels/arch-support.txt 
> > b/Documentation/features/core/jump-labels/arch-support.txt
> > index 632a1c7aefa2..760243d18ed7 100644
> > --- a/Documentation/features/core/jump-labels/arch-support.txt
> > +++ b/Documentation/features/core/jump-labels/arch-support.txt
> > @@ -23,7 +23,7 @@
> >  |openrisc: | TODO |
> >  |  parisc: |  ok  |
> >  | powerpc: |  ok  |
> > -|   riscv: | TODO |
> > +|   riscv: |  ok  |
> >  |s390: |  ok  |
> >  |  sh: | TODO |
> >  |   sparc: |  ok  |
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index fd639937e251..d2f5c53fdc19 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -46,6 +46,8 @@ config RISCV
> > select GENERIC_TIME_VSYSCALL if MMU && 64BIT
> > select HANDLE_DOMAIN_IRQ
> > select HAVE_ARCH_AUDITSYSCALL
> > +   select HAVE_ARCH_JUMP_LABEL
> > +   select HAVE_ARCH_JUMP_LABEL_RELATIVE
> > select HAVE_ARCH_KASAN if MMU && 64BIT
> > select HAVE_ARCH_KGDB
> > select HAVE_ARCH_KGDB_QXFER_PKT
> > diff --git a/arch/riscv/include/asm/jump_label.h 
> > b/arch/riscv/include/asm/jump_label.h
> > new file mode 100644
> > index ..d5fb342bfccf
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/jump_label.h
> > @@ -0,0 +1,59 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Emil Renner Berthing
> > + *
> > + * Based on arch/arm64/include/asm/jump_label.h
> > + */
> > +#ifndef __ASM_JUMP_LABEL_H
> > +#define __ASM_JUMP_LABEL_H
> > +
> > +#ifndef __ASSEMBLY__
> > +
> > +#include 
> > +
> > +#define JUMP_LABEL_NOP_SIZE 4
> > +
> > +static __always_inline bool arch_static_branch(struct static_key *key,
> > +  bool branch)
> > +{
> > +   asm_volatile_goto(
> > +   "   .option push\n\t"
> > +   "   .option norelax \n\t"
> > +   "   .option norvc 

Re: [PATCH v1] riscv: Add jump-label implementation

2020-07-08 Thread Emil Renner Berthing
On Wed, 8 Jul 2020 at 08:28, Björn Töpel  wrote:
> On Tue, 7 Jul 2020 at 17:08, Emil Renner Berthing  wrote:
> >
> > Add jump-label implementation based on the ARM64 version.
> >
>
> Thanks for working on this!
>
> > Tested on the HiFive Unleashed board.
> >
> > Signed-off-by: Emil Renner Berthing 
> > ---
> >
> > Changes since RFC:
> > - Use RISCV_PTR and RISCV_LGPTR macros to match struct jump_table
> >   also in 32bit kernels.
> > - Remove unneeded branch ? 1 : 0, thanks Björn
> > - Fix \n\n instead of \n\t mistake
> >
> >  .../core/jump-labels/arch-support.txt |  2 +-
> >  arch/riscv/Kconfig|  2 +
> >  arch/riscv/include/asm/jump_label.h   | 59 +++
> >  arch/riscv/kernel/Makefile|  2 +
> >  arch/riscv/kernel/jump_label.c| 44 ++
> >  5 files changed, 108 insertions(+), 1 deletion(-)
> >  create mode 100644 arch/riscv/include/asm/jump_label.h
> >  create mode 100644 arch/riscv/kernel/jump_label.c
> >
> > diff --git a/Documentation/features/core/jump-labels/arch-support.txt 
> > b/Documentation/features/core/jump-labels/arch-support.txt
> > index 632a1c7aefa2..760243d18ed7 100644
> > --- a/Documentation/features/core/jump-labels/arch-support.txt
> > +++ b/Documentation/features/core/jump-labels/arch-support.txt
> > @@ -23,7 +23,7 @@
> >  |openrisc: | TODO |
> >  |  parisc: |  ok  |
> >  | powerpc: |  ok  |
> > -|   riscv: | TODO |
> > +|   riscv: |  ok  |
> >  |s390: |  ok  |
> >  |  sh: | TODO |
> >  |   sparc: |  ok  |
> > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > index fd639937e251..d2f5c53fdc19 100644
> > --- a/arch/riscv/Kconfig
> > +++ b/arch/riscv/Kconfig
> > @@ -46,6 +46,8 @@ config RISCV
> > select GENERIC_TIME_VSYSCALL if MMU && 64BIT
> > select HANDLE_DOMAIN_IRQ
> > select HAVE_ARCH_AUDITSYSCALL
> > +   select HAVE_ARCH_JUMP_LABEL
> > +   select HAVE_ARCH_JUMP_LABEL_RELATIVE
> > select HAVE_ARCH_KASAN if MMU && 64BIT
> > select HAVE_ARCH_KGDB
> > select HAVE_ARCH_KGDB_QXFER_PKT
> > diff --git a/arch/riscv/include/asm/jump_label.h 
> > b/arch/riscv/include/asm/jump_label.h
> > new file mode 100644
> > index ..d5fb342bfccf
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/jump_label.h
> > @@ -0,0 +1,59 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (C) 2020 Emil Renner Berthing
> > + *
> > + * Based on arch/arm64/include/asm/jump_label.h
> > + */
> > +#ifndef __ASM_JUMP_LABEL_H
> > +#define __ASM_JUMP_LABEL_H
> > +
> > +#ifndef __ASSEMBLY__
> > +
> > +#include 
> > +
> > +#define JUMP_LABEL_NOP_SIZE 4
> > +
> > +static __always_inline bool arch_static_branch(struct static_key *key,
> > +  bool branch)
> > +{
> > +   asm_volatile_goto(
> > +   "   .option push\n\t"
> > +   "   .option norelax \n\t"
> > +   "   .option norvc   \n\t"
> > +   "1: nop \n\t"
> > +   "   .option pop \n\t"
> > +   "   .pushsection__jump_table, \"aw\"\n\t"
> > +   "   .align  " RISCV_LGPTR " \n\t"
> > +   "   .long   1b - ., %l[label] - .   \n\t"
> > +   "   " RISCV_PTR "   %0 - .  \n\t"
> > +   "   .popsection \n\t"
> > +   :  :  "i"(&((char *)key)[branch]) :  : label);
> > +
> > +   return false;
> > +label:
> > +   return true;
> > +}
> > +
> > +static __always_inline bool arch_static_branch_jump(struct static_key *key,
> > +   bool branch)
> > +{
> > +   asm_volatile_goto(
> > +   "   .option push\n\t"
> > +   "   .option norelax \n\t"
> > +   "   .option norv

[PATCH v1] riscv: Add jump-label implementation

2020-07-07 Thread Emil Renner Berthing
Add jump-label implementation based on the ARM64 version.

Tested on the HiFive Unleashed board.

Signed-off-by: Emil Renner Berthing 
---

Changes since RFC:
- Use RISCV_PTR and RISCV_LGPTR macros to match struct jump_table
  also in 32bit kernels.
- Remove unneeded branch ? 1 : 0, thanks Björn
- Fix \n\n instead of \n\t mistake

 .../core/jump-labels/arch-support.txt |  2 +-
 arch/riscv/Kconfig|  2 +
 arch/riscv/include/asm/jump_label.h   | 59 +++
 arch/riscv/kernel/Makefile|  2 +
 arch/riscv/kernel/jump_label.c| 44 ++
 5 files changed, 108 insertions(+), 1 deletion(-)
 create mode 100644 arch/riscv/include/asm/jump_label.h
 create mode 100644 arch/riscv/kernel/jump_label.c

diff --git a/Documentation/features/core/jump-labels/arch-support.txt 
b/Documentation/features/core/jump-labels/arch-support.txt
index 632a1c7aefa2..760243d18ed7 100644
--- a/Documentation/features/core/jump-labels/arch-support.txt
+++ b/Documentation/features/core/jump-labels/arch-support.txt
@@ -23,7 +23,7 @@
 |openrisc: | TODO |
 |  parisc: |  ok  |
 | powerpc: |  ok  |
-|   riscv: | TODO |
+|   riscv: |  ok  |
 |s390: |  ok  |
 |  sh: | TODO |
 |   sparc: |  ok  |
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index fd639937e251..d2f5c53fdc19 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -46,6 +46,8 @@ config RISCV
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
select HANDLE_DOMAIN_IRQ
select HAVE_ARCH_AUDITSYSCALL
+   select HAVE_ARCH_JUMP_LABEL
+   select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if MMU && 64BIT
select HAVE_ARCH_KGDB
select HAVE_ARCH_KGDB_QXFER_PKT
diff --git a/arch/riscv/include/asm/jump_label.h 
b/arch/riscv/include/asm/jump_label.h
new file mode 100644
index ..d5fb342bfccf
--- /dev/null
+++ b/arch/riscv/include/asm/jump_label.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Emil Renner Berthing
+ *
+ * Based on arch/arm64/include/asm/jump_label.h
+ */
+#ifndef __ASM_JUMP_LABEL_H
+#define __ASM_JUMP_LABEL_H
+
+#ifndef __ASSEMBLY__
+
+#include 
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+  bool branch)
+{
+   asm_volatile_goto(
+   "   .option push\n\t"
+   "   .option norelax \n\t"
+   "   .option norvc   \n\t"
+   "1: nop \n\t"
+   "   .option pop \n\t"
+   "   .pushsection__jump_table, \"aw\"\n\t"
+   "   .align  " RISCV_LGPTR " \n\t"
+   "   .long   1b - ., %l[label] - .   \n\t"
+   "   " RISCV_PTR "   %0 - .  \n\t"
+   "   .popsection \n\t"
+   :  :  "i"(&((char *)key)[branch]) :  : label);
+
+   return false;
+label:
+   return true;
+}
+
+static __always_inline bool arch_static_branch_jump(struct static_key *key,
+   bool branch)
+{
+   asm_volatile_goto(
+   "   .option push\n\t"
+   "   .option norelax \n\t"
+   "   .option norvc   \n\t"
+   "1: jal zero, %l[label] \n\t"
+   "   .option pop \n\t"
+   "   .pushsection__jump_table, \"aw\"\n\t"
+   "   .align  " RISCV_LGPTR " \n\t"
+   "   .long   1b - ., %l[label] - .   \n\t"
+   "   " RISCV_PTR "   %0 - .  \n\t"
+   "   .popsection \n\t"
+   :  :  "i"(&((char *)key)[branch]) :  : label);
+
+   return false;
+label:
+   return true;
+}
+
+#endif  /* __ASSEMBLY__ */
+#endif /* __ASM_JUMP_LABEL_H */
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index b355cf485671..a5287ab9f7f2 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -53,4 +53,6 @@ endif
 obj-$(CONFIG_HOTPLUG_CPU)  += cpu-hotplug.o
 obj-$(CONFIG_KGDB) += kgdb.o
 
+obj-$(CONFIG_JUMP_LABEL)   +

Re: [RFC] riscv: Add jump-label implementation

2020-07-04 Thread Emil Renner Berthing
On Sat, 4 Jul 2020 at 13:23, Björn Töpel  wrote:
> On Fri, 3 Jul 2020 at 17:43, Emil Renner Berthing  wrote:
> > On Thu, 2 Jul 2020 at 22:07, Emil Renner Berthing  wrote:
> > >
> > > Add basic jump-label implementation heavily based
> > > on the ARM64 version.
> > >
> > > Tested on the HiFive Unleashed.
> > >
> > > Signed-off-by: Emil Renner Berthing 
> > > ---
> > >
> > > This seems to work on my HiFive Unleashed. At least boots, runs fine
> > > and the static key self-tests doesn't complain, but I'm sure I've missed
> > > something, so I'm sending this as an RFC.
> > >
> > > /Emil
> > >
> > >  .../core/jump-labels/arch-support.txt |  2 +-
> > >  arch/riscv/Kconfig|  2 +
> > >  arch/riscv/include/asm/jump_label.h   | 59 +++
> > >  arch/riscv/kernel/Makefile|  2 +
> > >  arch/riscv/kernel/jump_label.c| 44 ++
> > >  5 files changed, 108 insertions(+), 1 deletion(-)
> > >  create mode 100644 arch/riscv/include/asm/jump_label.h
> > >  create mode 100644 arch/riscv/kernel/jump_label.c
> > >
> > > diff --git a/Documentation/features/core/jump-labels/arch-support.txt 
> > > b/Documentation/features/core/jump-labels/arch-support.txt
> > > index 632a1c7aefa2..760243d18ed7 100644
> > > --- a/Documentation/features/core/jump-labels/arch-support.txt
> > > +++ b/Documentation/features/core/jump-labels/arch-support.txt
> > > @@ -23,7 +23,7 @@
> > >  |openrisc: | TODO |
> > >  |  parisc: |  ok  |
> > >  | powerpc: |  ok  |
> > > -|   riscv: | TODO |
> > > +|   riscv: |  ok  |
> > >  |s390: |  ok  |
> > >  |  sh: | TODO |
> > >  |   sparc: |  ok  |
> > > diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> > > index fd639937e251..d2f5c53fdc19 100644
> > > --- a/arch/riscv/Kconfig
> > > +++ b/arch/riscv/Kconfig
> > > @@ -46,6 +46,8 @@ config RISCV
> > > select GENERIC_TIME_VSYSCALL if MMU && 64BIT
> > > select HANDLE_DOMAIN_IRQ
> > > select HAVE_ARCH_AUDITSYSCALL
> > > +   select HAVE_ARCH_JUMP_LABEL
> > > +   select HAVE_ARCH_JUMP_LABEL_RELATIVE
> > >     select HAVE_ARCH_KASAN if MMU && 64BIT
> > > select HAVE_ARCH_KGDB
> > > select HAVE_ARCH_KGDB_QXFER_PKT
> > > diff --git a/arch/riscv/include/asm/jump_label.h 
> > > b/arch/riscv/include/asm/jump_label.h
> > > new file mode 100644
> > > index ..29be6d351866
> > > --- /dev/null
> > > +++ b/arch/riscv/include/asm/jump_label.h
> > > @@ -0,0 +1,59 @@
> > > +/* SPDX-License-Identifier: GPL-2.0-only */
> > > +/*
> > > + * Copyright (C) 2020 Emil Renner Berthing
> > > + *
> > > + * Based on arch/arm64/include/asm/jump_label.h
> > > + */
> > > +#ifndef __ASM_JUMP_LABEL_H
> > > +#define __ASM_JUMP_LABEL_H
> > > +
> > > +#ifndef __ASSEMBLY__
> > > +
> > > +#include 
> > > +
> > > +#define JUMP_LABEL_NOP_SIZE 4
> > > +
> > > +static __always_inline bool arch_static_branch(struct static_key *key,
> > > +  bool branch)
> > > +{
> > > +   asm_volatile_goto(
> > > +   "   .option push\n\n"
> > > +   "   .option norelax \n\n"
> > > +   "   .option norvc   \n\n"
> > > +   "1: nop \n\t"
> > > +   "   .option pop \n\n"
> > > +   "   .pushsection__jump_table, \"aw\"\n\t"
> > > +   "   .align  3   \n\t"
> > > +   "   .long   1b - ., %l[l_yes] - .   \n\t"
> > > +   "   .quad   %0 - .  \n\t"
> >
> > With HAVE_ARCH_JUMP_LABEL_RELATIVE we get
> > struct jump_entry {
> >   s32 code;
> >   s32 target;
> >   long key;
> > }
> > ..so this .quad and the one below should be replaced by the RISCV_PTR
> 

Re: [RFC] riscv: Add jump-label implementation

2020-07-03 Thread Emil Renner Berthing
On Thu, 2 Jul 2020 at 22:07, Emil Renner Berthing  wrote:
>
> Add basic jump-label implementation heavily based
> on the ARM64 version.
>
> Tested on the HiFive Unleashed.
>
> Signed-off-by: Emil Renner Berthing 
> ---
>
> This seems to work on my HiFive Unleashed. At least boots, runs fine
> and the static key self-tests doesn't complain, but I'm sure I've missed
> something, so I'm sending this as an RFC.
>
> /Emil
>
>  .../core/jump-labels/arch-support.txt |  2 +-
>  arch/riscv/Kconfig|  2 +
>  arch/riscv/include/asm/jump_label.h   | 59 +++
>  arch/riscv/kernel/Makefile|  2 +
>  arch/riscv/kernel/jump_label.c| 44 ++
>  5 files changed, 108 insertions(+), 1 deletion(-)
>  create mode 100644 arch/riscv/include/asm/jump_label.h
>  create mode 100644 arch/riscv/kernel/jump_label.c
>
> diff --git a/Documentation/features/core/jump-labels/arch-support.txt 
> b/Documentation/features/core/jump-labels/arch-support.txt
> index 632a1c7aefa2..760243d18ed7 100644
> --- a/Documentation/features/core/jump-labels/arch-support.txt
> +++ b/Documentation/features/core/jump-labels/arch-support.txt
> @@ -23,7 +23,7 @@
>  |openrisc: | TODO |
>  |  parisc: |  ok  |
>  | powerpc: |  ok  |
> -|   riscv: | TODO |
> +|   riscv: |  ok  |
>  |s390: |  ok  |
>  |  sh: | TODO |
>  |   sparc: |  ok  |
> diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
> index fd639937e251..d2f5c53fdc19 100644
> --- a/arch/riscv/Kconfig
> +++ b/arch/riscv/Kconfig
> @@ -46,6 +46,8 @@ config RISCV
> select GENERIC_TIME_VSYSCALL if MMU && 64BIT
> select HANDLE_DOMAIN_IRQ
> select HAVE_ARCH_AUDITSYSCALL
> +   select HAVE_ARCH_JUMP_LABEL
> +   select HAVE_ARCH_JUMP_LABEL_RELATIVE
> select HAVE_ARCH_KASAN if MMU && 64BIT
> select HAVE_ARCH_KGDB
> select HAVE_ARCH_KGDB_QXFER_PKT
> diff --git a/arch/riscv/include/asm/jump_label.h 
> b/arch/riscv/include/asm/jump_label.h
> new file mode 100644
> index 0000..29be6d351866
> --- /dev/null
> +++ b/arch/riscv/include/asm/jump_label.h
> @@ -0,0 +1,59 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (C) 2020 Emil Renner Berthing
> + *
> + * Based on arch/arm64/include/asm/jump_label.h
> + */
> +#ifndef __ASM_JUMP_LABEL_H
> +#define __ASM_JUMP_LABEL_H
> +
> +#ifndef __ASSEMBLY__
> +
> +#include 
> +
> +#define JUMP_LABEL_NOP_SIZE 4
> +
> +static __always_inline bool arch_static_branch(struct static_key *key,
> +  bool branch)
> +{
> +   asm_volatile_goto(
> +   "   .option push\n\n"
> +   "   .option norelax \n\n"
> +   "   .option norvc   \n\n"
> +   "1: nop \n\t"
> +   "   .option pop \n\n"
> +   "   .pushsection__jump_table, \"aw\"\n\t"
> +   "   .align  3   \n\t"
> +   "   .long   1b - ., %l[l_yes] - .   \n\t"
> +   "   .quad   %0 - .  \n\t"

With HAVE_ARCH_JUMP_LABEL_RELATIVE we get
struct jump_entry {
  s32 code;
  s32 target;
  long key;
}
..so this .quad and the one below should be replaced by the RISCV_PTR
macro to match the struct in 32bit kernels.

> +   "   .popsection \n\t"
> +   :  :  "i"(&((char *)key)[branch ? 1 : 0]) :  : l_yes);
> +
> +   return false;
> +l_yes:
> +   return true;
> +}
> +
> +static __always_inline bool arch_static_branch_jump(struct static_key *key,
> +   bool branch)
> +{
> +   asm_volatile_goto(
> +   "   .option push\n\n"
> +   "   .option norelax \n\n"
> +   "   .option norvc   \n\n"
> +   "1: jal zero, %l[l_yes] \n\t"
> +   "   .option pop \n\n"
> +   "   .pushsection__jump_table, \"aw\"\n\t"
> +   "   .align 

[RFC] riscv: Add jump-label implementation

2020-07-02 Thread Emil Renner Berthing
Add basic jump-label implementation heavily based
on the ARM64 version.

Tested on the HiFive Unleashed.

Signed-off-by: Emil Renner Berthing 
---

This seems to work on my HiFive Unleashed. At least boots, runs fine
and the static key self-tests doesn't complain, but I'm sure I've missed
something, so I'm sending this as an RFC.

/Emil

 .../core/jump-labels/arch-support.txt |  2 +-
 arch/riscv/Kconfig|  2 +
 arch/riscv/include/asm/jump_label.h   | 59 +++
 arch/riscv/kernel/Makefile|  2 +
 arch/riscv/kernel/jump_label.c| 44 ++
 5 files changed, 108 insertions(+), 1 deletion(-)
 create mode 100644 arch/riscv/include/asm/jump_label.h
 create mode 100644 arch/riscv/kernel/jump_label.c

diff --git a/Documentation/features/core/jump-labels/arch-support.txt 
b/Documentation/features/core/jump-labels/arch-support.txt
index 632a1c7aefa2..760243d18ed7 100644
--- a/Documentation/features/core/jump-labels/arch-support.txt
+++ b/Documentation/features/core/jump-labels/arch-support.txt
@@ -23,7 +23,7 @@
 |openrisc: | TODO |
 |  parisc: |  ok  |
 | powerpc: |  ok  |
-|   riscv: | TODO |
+|   riscv: |  ok  |
 |s390: |  ok  |
 |  sh: | TODO |
 |   sparc: |  ok  |
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index fd639937e251..d2f5c53fdc19 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -46,6 +46,8 @@ config RISCV
select GENERIC_TIME_VSYSCALL if MMU && 64BIT
select HANDLE_DOMAIN_IRQ
select HAVE_ARCH_AUDITSYSCALL
+   select HAVE_ARCH_JUMP_LABEL
+   select HAVE_ARCH_JUMP_LABEL_RELATIVE
select HAVE_ARCH_KASAN if MMU && 64BIT
select HAVE_ARCH_KGDB
select HAVE_ARCH_KGDB_QXFER_PKT
diff --git a/arch/riscv/include/asm/jump_label.h 
b/arch/riscv/include/asm/jump_label.h
new file mode 100644
index ..29be6d351866
--- /dev/null
+++ b/arch/riscv/include/asm/jump_label.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2020 Emil Renner Berthing
+ *
+ * Based on arch/arm64/include/asm/jump_label.h
+ */
+#ifndef __ASM_JUMP_LABEL_H
+#define __ASM_JUMP_LABEL_H
+
+#ifndef __ASSEMBLY__
+
+#include 
+
+#define JUMP_LABEL_NOP_SIZE 4
+
+static __always_inline bool arch_static_branch(struct static_key *key,
+  bool branch)
+{
+   asm_volatile_goto(
+   "   .option push\n\n"
+   "   .option norelax \n\n"
+   "   .option norvc   \n\n"
+   "1: nop \n\t"
+   "   .option pop \n\n"
+   "   .pushsection__jump_table, \"aw\"\n\t"
+   "   .align  3   \n\t"
+   "   .long   1b - ., %l[l_yes] - .   \n\t"
+   "   .quad   %0 - .  \n\t"
+   "   .popsection \n\t"
+   :  :  "i"(&((char *)key)[branch ? 1 : 0]) :  : l_yes);
+
+   return false;
+l_yes:
+   return true;
+}
+
+static __always_inline bool arch_static_branch_jump(struct static_key *key,
+   bool branch)
+{
+   asm_volatile_goto(
+   "   .option push\n\n"
+   "   .option norelax \n\n"
+   "   .option norvc   \n\n"
+   "1: jal zero, %l[l_yes] \n\t"
+   "   .option pop \n\n"
+   "   .pushsection__jump_table, \"aw\"\n\t"
+   "   .align  3   \n\t"
+   "   .long   1b - ., %l[l_yes] - .   \n\t"
+   "   .quad   %0 - .  \n\t"
+   "   .popsection \n\t"
+   :  :  "i"(&((char *)key)[branch ? 1 : 0]) :  : l_yes);
+
+   return false;
+l_yes:
+   return true;
+}
+
+#endif  /* __ASSEMBLY__ */
+#endif /* __ASM_JUMP_LABEL_H */
diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
index b355cf485671..a5287ab9f7f2 100644
--- a/arch/riscv/kernel/Makefile
+++ b/arch/riscv/kernel/Makefile
@@ -53,4 +53,6 @@ endif
 obj-$(CONFIG_HOTPLUG_CPU)  += cpu-hotplug.o
 obj-$(CONFIG_KGDB) += kgdb.o
 
+obj-$(CONFIG_JUMP_LABEL)   

Re: [PATCH v0 1/1] spi: spi-rockchip: add support for spi slave_mode

2020-05-10 Thread Emil Renner Berthing
Hi Chris,

On Sat, 9 May 2020 at 02:10, Chris Ruehl  wrote:
>
> Hi Emil,
>
> thanks for the review and your comments
>
> On 8/5/2020 9:13 pm, Emil Renner Berthing wrote:
> > Hi Chris,
> >
> > On Fri, 8 May 2020 at 10:47, Chris Ruehl  wrote:
> >> This patch aim to add spi slave mode support to the rockchip driver.
> >> Fix the wrong usage of num_cs set fix to ROCKCHIP_SPI_MAX_CS_NUM,
> >> instead use max_native_cs flag to set the limit of native chip-select.
> >> Enable use_gpio_descriptors to have cs_gpiod for gpio based chip-selects.
> >>
> >> Signed-off-by: Chris Ruehl 
> >> ---
> >>   drivers/spi/spi-rockchip.c | 46 +-
> >>   1 file changed, 41 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
> >> index 70ef63e0b6b8..9c1ff52c0f85 100644
> >> --- a/drivers/spi/spi-rockchip.c
> >> +++ b/drivers/spi/spi-rockchip.c
> >> @@ -183,6 +183,9 @@ struct rockchip_spi {
> >>  u8 rsd;
> >>
> >>  bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
> >> +
> >> +   bool slave_mode;
> >> +   bool slave_abort;
> >>   };
> >>
> >>   static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable)
> >> @@ -359,7 +362,7 @@ static void rockchip_spi_dma_rxcb(void *data)
> >>  struct rockchip_spi *rs = spi_master_get_devdata(master);
> >>  int state = atomic_fetch_andnot(RXDMA, &rs->state);
> >>
> >> -   if (state & TXDMA)
> >> +   if (state & TXDMA && !rs->slave_abort)
> >>  return;
> >>
> >>  spi_enable_chip(rs, false);
> >> @@ -372,7 +375,7 @@ static void rockchip_spi_dma_txcb(void *data)
> >>  struct rockchip_spi *rs = spi_master_get_devdata(master);
> >>  int state = atomic_fetch_andnot(TXDMA, &rs->state);
> >>
> >> -   if (state & RXDMA)
> >> +   if (state & RXDMA && !rs->slave_abort)
> >>  return;
> >>
> >>  /* Wait until the FIFO data completely. */
> >> @@ -466,6 +469,10 @@ static void rockchip_spi_config(struct rockchip_spi 
> >> *rs,
> >>  u32 cr1;
> >>  u32 dmacr = 0;
> >>
> >> +   if (rs->slavemode)
> >> +   cr0 |= CR0_OPM_SLAVE << CR0_OPM_OFFSET;
> >> +   rs->slave_abort = false;
> >> +
> >>  cr0 |= rs->rsd << CR0_RSD_OFFSET;
> >>  cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
> >>  if (spi->mode & SPI_LSB_FIRST)
> >> @@ -535,6 +542,16 @@ static size_t rockchip_spi_max_transfer_size(struct 
> >> spi_device *spi)
> >>  return ROCKCHIP_SPI_MAX_TRANLEN;
> >>   }
> >>
> >> +static int rockchip_spi_slave_abort(struct spi_master *master)
> >> +{
> >> +   struct rockchip_spi *rs = spi_master_get_devdata(master);
> >> +
> >> +   rs->slave_abort = true;
> >> +   complete(master);
> >> +
> >> +   return 0;
> >> +}
> >> +
> >>   static int rockchip_spi_transfer_one(
> >>  struct spi_master *master,
> >>  struct spi_device *spi,
> >> @@ -589,14 +606,25 @@ static int rockchip_spi_probe(struct platform_device 
> >> *pdev)
> >>  struct spi_master *master;
> >>  struct resource *mem;
> >>  u32 rsd_nsecs;
> >> +   bool slave_mode;
> >> +   u32 num_cs = 1;
> >> +
> >> +   slave_mode = of_property_read_bool(np, "spi-slave");
> >> +
> >> +   if (slave_mode)
> >> +   master = spi_alloc_slave(&pdev->dev,
> >> +   sizeof(struct rockchip_spi));
> >> +   else
> >> +   master = spi_alloc_master(&pdev->dev,
> >> +   sizeof(struct rockchip_spi));
> >>
> >> -   master = spi_alloc_master(&pdev->dev, sizeof(struct rockchip_spi));
> >>  if (!master)
> >>  return -ENOMEM;
> >>
> >>  platform_set_drvdata(pdev, master);
> >>
> >>  rs = spi_master_get_devdata(master);
> >> +   rs->slave_mode = slave_mode;
> > This entr

Re: [PATCH v0 1/1] spi: spi-rockchip: add support for spi slave_mode

2020-05-08 Thread Emil Renner Berthing
Hi Chris,

On Fri, 8 May 2020 at 15:13, Emil Renner Berthing
 wrote:
> If you do something like this you won't need the temporary num_cs variable:
>
> if (of_property_read_u32(np, "num-cs", &master->num_chipselect))
> master->num_chipselect = 1;

Sorry, that should be of_property_read_u16, since num_chipselect is a u16.

/Emil


Re: [PATCH v0 1/1] spi: spi-rockchip: add support for spi slave_mode

2020-05-08 Thread Emil Renner Berthing
Hi Chris,

On Fri, 8 May 2020 at 10:47, Chris Ruehl  wrote:
>
> This patch aim to add spi slave mode support to the rockchip driver.
> Fix the wrong usage of num_cs set fix to ROCKCHIP_SPI_MAX_CS_NUM,
> instead use max_native_cs flag to set the limit of native chip-select.
> Enable use_gpio_descriptors to have cs_gpiod for gpio based chip-selects.
>
> Signed-off-by: Chris Ruehl 
> ---
>  drivers/spi/spi-rockchip.c | 46 +-
>  1 file changed, 41 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
> index 70ef63e0b6b8..9c1ff52c0f85 100644
> --- a/drivers/spi/spi-rockchip.c
> +++ b/drivers/spi/spi-rockchip.c
> @@ -183,6 +183,9 @@ struct rockchip_spi {
> u8 rsd;
>
> bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
> +
> +   bool slave_mode;
> +   bool slave_abort;
>  };
>
>  static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable)
> @@ -359,7 +362,7 @@ static void rockchip_spi_dma_rxcb(void *data)
> struct rockchip_spi *rs = spi_master_get_devdata(master);
> int state = atomic_fetch_andnot(RXDMA, &rs->state);
>
> -   if (state & TXDMA)
> +   if (state & TXDMA && !rs->slave_abort)
> return;
>
> spi_enable_chip(rs, false);
> @@ -372,7 +375,7 @@ static void rockchip_spi_dma_txcb(void *data)
> struct rockchip_spi *rs = spi_master_get_devdata(master);
> int state = atomic_fetch_andnot(TXDMA, &rs->state);
>
> -   if (state & RXDMA)
> +   if (state & RXDMA && !rs->slave_abort)
> return;
>
> /* Wait until the FIFO data completely. */
> @@ -466,6 +469,10 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
> u32 cr1;
> u32 dmacr = 0;
>
> +   if (rs->slavemode)
> +   cr0 |= CR0_OPM_SLAVE << CR0_OPM_OFFSET;
> +   rs->slave_abort = false;
> +
> cr0 |= rs->rsd << CR0_RSD_OFFSET;
> cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
> if (spi->mode & SPI_LSB_FIRST)
> @@ -535,6 +542,16 @@ static size_t rockchip_spi_max_transfer_size(struct 
> spi_device *spi)
> return ROCKCHIP_SPI_MAX_TRANLEN;
>  }
>
> +static int rockchip_spi_slave_abort(struct spi_master *master)
> +{
> +   struct rockchip_spi *rs = spi_master_get_devdata(master);
> +
> +   rs->slave_abort = true;
> +   complete(master);
> +
> +   return 0;
> +}
> +
>  static int rockchip_spi_transfer_one(
> struct spi_master *master,
> struct spi_device *spi,
> @@ -589,14 +606,25 @@ static int rockchip_spi_probe(struct platform_device 
> *pdev)
> struct spi_master *master;
> struct resource *mem;
> u32 rsd_nsecs;
> +   bool slave_mode;
> +   u32 num_cs = 1;
> +
> +   slave_mode = of_property_read_bool(np, "spi-slave");
> +
> +   if (slave_mode)
> +   master = spi_alloc_slave(&pdev->dev,
> +   sizeof(struct rockchip_spi));
> +   else
> +   master = spi_alloc_master(&pdev->dev,
> +   sizeof(struct rockchip_spi));
>
> -   master = spi_alloc_master(&pdev->dev, sizeof(struct rockchip_spi));
> if (!master)
> return -ENOMEM;
>
> platform_set_drvdata(pdev, master);
>
> rs = spi_master_get_devdata(master);
> +   rs->slave_mode = slave_mode;

This entry doesn't seem to be read from any of your code, and even it
it was, the same information is available in master->slave, so I don't
see why you need it in the rockchip_spi struct.

Also spi_master is just #defined to spi_controller in spi.h, so maybe
consider changing all 'struct spi_master *master' to 'struct
spi_controller *ctrl' now that the driver supports both modes.

>
> /* Get basic io resource and map it */
> mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> @@ -676,7 +704,16 @@ static int rockchip_spi_probe(struct platform_device 
> *pdev)
> master->auto_runtime_pm = true;
> master->bus_num = pdev->id;
> master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_LSB_FIRST;
> -   master->num_chipselect = ROCKCHIP_SPI_MAX_CS_NUM;
> +   if (slave_mode) {
> +   master->mode_bits |= SPI_NO_CS;
> +   master->slave_abort = rockchip_spi_slave_abort;
> +   } else {
> +   of_property_read_u32(np, "num-cs", &num_cs);
> +   master->num_chipselect = num_cs;

If you do something like this you won't need the temporary num_cs variable:

if (of_property_read_u32(np, "num-cs", &master->num_chipselect))
master->num_chipselect = 1;

Also it seems like you're changing the default from
ROCKCHIP_SPI_MAX_CS_NUM to 1 if there is no num-cs property. Did you
check that all boards either have the num-cs property defined or only
needs num_chipselect = 1?

> +   master->use_gpio_descriptors = true;
> +   master->max_native_cs = RO

Re: Asus C101P Chromeboot fails to boot with Linux 5.2

2019-07-12 Thread Emil Renner Berthing
Hi Alex,

On Fri, 12 Jul 2019 at 17:02, Alex Dewar  wrote:
> When I try to boot the screen just gets flooded with messages like this:
> http://users.sussex.ac.uk/~ad374/boot_fail.jpg

Those seem to be only audit messages. You can try booting with audit=0
on the kernel command line to get rid of those messages, so you have a
better chance of catching the real issue. (Or conclude that audit is
what is broken.)

/Emil


Re: Applied "spi: rockchip: turn down tx dma bursts" to the spi tree

2019-06-05 Thread Emil Renner Berthing
On Wed, 5 Jun 2019 at 21:55, Mark Brown  wrote:
>
> On Wed, Jun 05, 2019 at 09:36:44PM +0200, Emil Renner Berthing wrote:
> > On Wed, 8 May 2019 at 12:34, Mark Brown  wrote:
>
> > >spi: rockchip: turn down tx dma bursts
>
> > I've tried looking in the for-next and for-5.x branches here, and I
> > can't seem to find this patch.
> > Am I missing something?
>
> > It fixes a problem introduced in 4.19, so it'd be nice if it could
> > make it to stable trees eventually.
>
> 47300728fb213486a830565d2af49da967c9d16a is in my tree.  When it reaches
> Linus' tree send a request to Greg for it to be backported if none of
> the stable automation picks it up.

You're absolutely right, sorry about the noise.

Thanks.
/Emil


Re: Applied "spi: rockchip: turn down tx dma bursts" to the spi tree

2019-06-05 Thread Emil Renner Berthing
Hi Mark

On Wed, 8 May 2019 at 12:34, Mark Brown  wrote:
>
> The patch
>
>spi: rockchip: turn down tx dma bursts
>
> has been applied to the spi tree at
>
>https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git
>
> All being well this means that it will be integrated into the linux-next
> tree (usually sometime in the next 24 hours) and sent to Linus during
> the next merge window (or sooner if it is a bug fix), however if
> problems are discovered then the patch may be dropped or reverted.

I've tried looking in the for-next and for-5.x branches here, and I
can't seem to find this patch.
Am I missing something?

It fixes a problem introduced in 4.19, so it'd be nice if it could
make it to stable trees eventually.

/Emil


[PATCH] spi: rockchip: turn down tx dma bursts

2019-04-12 Thread Emil Renner Berthing
This fixes tx and bi-directional dma transfers on rk3399-gru-kevin.

It seems the SPI fifo must have room for 2 bursts when the dma_tx_req
signal is generated or it might skip some words. This in turn makes
the rx dma channel never complete for bi-directional transfers.

Fix it by setting tx burst length to fifo_len / 4 and the dma
watermark to fifo_len / 2.

However the rk3399 TRM says (sic):
"DMAC support incrementing-address burst and fixed-address burst. But in
the case of access SPI and UART at byte or halfword size, DMAC only
support fixed-address burst and the address must be aligned to word."

So this relies on fifo_len being a multiple of 16 such that the
burst length (= fifo_len / 4) is a multiple of 4 and the addresses
will be word-aligned.

Fixes: dcfc861d24ec ("spi: rockchip: adjust dma watermark and burstlen")
Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 3912526ead66..19f6a76f1c07 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -425,7 +425,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
.direction = DMA_MEM_TO_DEV,
.dst_addr = rs->dma_addr_tx,
.dst_addr_width = rs->n_bytes,
-   .dst_maxburst = rs->fifo_len / 2,
+   .dst_maxburst = rs->fifo_len / 4,
};
 
dmaengine_slave_config(master->dma_tx, &txconf);
@@ -526,7 +526,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
else
writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + 
ROCKCHIP_SPI_RXFTLR);
 
-   writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_DMATDLR);
+   writel_relaxed(rs->fifo_len / 2, rs->regs + ROCKCHIP_SPI_DMATDLR);
writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMARDLR);
writel_relaxed(dmacr, rs->regs + ROCKCHIP_SPI_DMACR);
 
-- 
2.21.0



Re: [BUG] Rockchip SPI: long burst writes produce unexpected result

2019-04-07 Thread Emil Renner Berthing
Hi Vicente,

On Sat, 6 Apr 2019 at 19:35, Vicente Bergas  wrote:
>
> Hi,
> i have been experiencing issues writing to NOR-Flash SPI Memories
> from two RK3399-based platforms: gru-kevin and sapphire board.
> For kevin, this resulted in a bricked device because that memory
> is the only boot device.
> Fortunately an external programmer is available.
>
> In order to isolate where the issue can be, several tests have been
> done, after which it makes me think the issue is related to the
> Rockchip SPI driver.
>
> 4KB burst reads work fine.
> The issue is only observed on the write burst length.
>
> Test user user/kernel kernelRK3399
> Num  spaceinterface   space   SoC   Status Notes
> 
> 1flashrom linux_mtd   MTD/RKspi RKspi   Fail
> 2flashrom linux_spi   RKspi RKspi   Fail
> 3flashrom linux_spi   spi_gpio  GPIOOK
> 4custom   linux_spi   spi_gpio  GPIOOK   260-byte burst writes
> 5custom   linux_spi   RKspi RKspi   Fail 260-byte burst writes
> 6custom   linux_spi   RKspi RKspi   OK 1-byte burst writes
> 7custom   linux_spi   RKspi RKspi   OK47-byte burst writes
> 8custom   linux_spi   RKspi RKspi   Fail  48-byte burst writes
>
> 3, 4) Unaccetably slow, device tree is
>   spi_gpio {
> compatible = "spi-gpio";
> #address-cells = <1>;
> #size-cells = <0>;
> cs-gpios   = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>;
> sck-gpios  = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
> mosi-gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>;
> miso-gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_HIGH>;
> num-chipselects = <1>;
> spidev@0 {
>   compatible = "spidev";
>   reg = <0>;
>   spi-max-frequency = <5000>;
> };
>   };
> 2, 5, 6, 7, 8) device tree is
>   &spi1 {

Since you say reverting the "set min/max speed" patch fixes your issues
could you try raising the spi clock like this and see if it works for you?

+   assigned-clocks = <&cru SCLK_SPI1>;
+   assigned-clock-rates = <4>;

Of course the driver shouldn't let you configure the spi-controller in a way
that makes it skip bytes, but if this works for you then I still think
you're better off explicitly setting the spi clock speed rather than having
the driver raise it for you. At least while it does it without
checking for errors
or having a way to lower it again as outlined in the commit message.

> status = "okay";
> spidev@0 {
>   compatible = "spidev";
>   reg = <0>;
>   spi-max-frequency = <5000>;
> };
>   };
> ...

/Emil


Re: [PATCH v3 2/2] tty: serial: add driver for the SiFive UART

2018-11-15 Thread Emil Renner Berthing
Hi Paul,

Thanks for the patch!

On Sat, 20 Oct 2018 at 12:12, Paul Walmsley  wrote:
> +/*
> + *
> + */

Interesting comment ;)

> +static int __init sifive_serial_console_setup(struct console *co, char 
> *options)

Unfortunately I get this error unless I remove the __init:
...
  GEN .version
  CHK include/generated/compile.h
  AR  built-in.a
  LD  vmlinux.o
  MODPOST vmlinux.o
WARNING: vmlinux.o(.data+0x14e48): Section mismatch in reference from
the variable .LANCHOR0 to the function
.init.text:sifive_serial_console_setup()
The variable .LANCHOR0 references
the function __init sifive_serial_console_setup()
If the reference is valid then annotate the
variable with __init* or __refdata (see linux/init.h) or name the variable:
*_template, *_timer, *_sht, *_ops, *_probe, *_probe_one, *_console

FATAL: modpost: Section mismatches detected.
Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.
make[1]: *** [scripts/Makefile.modpost:98: vmlinux.o] Error 1
make: *** [Makefile:1040: vmlinux] Error 2

I have
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
CONFIG_SERIAL_SIFIVE=y
CONFIG_SERIAL_SIFIVE_CONSOLE=y
and it happens both on v4.20-rc2 and v4.19.
Without the __init everything seems to work fine though.

> +#else
> +
> +#define SIFIVE_SERIAL_CONSOLE  NULL
> +
> +static inline void __ssp_add_console_port(struct sifive_serial_port *ssp)
> +{}
> +static void __ssp_remove_console_port(struct sifive_serial_port *ssp)
> +{}

Missing "inline"?

> +static int __init sifive_serial_init(void)
> +{
> +   int r;

If you're sending a v4 anyway, here and in the the probe function
using int ret; for this kind of variable is a common idiom and
hence easier to read.

/Emil


Re: [RFC PATCH] spi: add driver for the SiFive SPI controller

2018-11-13 Thread Emil Renner Berthing
Hi Mark,
On Tue, 13 Nov 2018 at 19:35, Mark Brown  wrote:
> On Mon, Nov 12, 2018 at 03:27:36PM +0100, Emil Renner Berthing wrote:
>
> > I know the discussions about the sifive devicetree compatible
> > strings haven't come to a conclusion, so I'm sending this as
> > an RFC to get some feedback on the rest of the code.
>
> I've not seen any of these discussions or earlier versions of this
> driver so I've no idea what's going on here :(

No, sorry. This has been discussed on linux-riscv for other drivers
like the uart. See my last answer.

> > +Optional properties:
> > +- sifive,fifo-depth  : Depth of hardware queues; defaults to 8
> > +- sifive,max-bits-per-word   : Maximum bits per word; defaults to 8
> > +
>
> If the hardware isn't fixed yet making these enumerable from the
> hardware would be good...

Agreed, but unfortunately this is already in the FU540-C000 chip on
the HiFive Unleashed board sold by SiFive.

> > @@ -0,0 +1,442 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/*
> > + * SiFive SPI controller driver (master mode only)
> > + *
>
> Please make the entire comment a C++ one to make this look more
> intentinal.

Will do.

> > +/* for consistency we need this symbol */
> > +#ifdef REG_FMT
> > +#undef REG_FMT
> > +#endif
>
> We do?  For consistency with what?

Below all the register offsets are defined as
REG_. This is is a pattern I
copied from other drivers, but here we have a
register called "fmt" - hence REG_FMT.
If you have a better pattern that doesn't clash
with REG_FMT please let me know.

> > +static void sifive_spi_init(struct sifive_spi *spi)
> > +{
>
> > + /* Set CS/SCK Delays and Inactive Time to defaults */
> > +
> > + /* Exit specialized memory-mapped SPI flash mode */
>
> ...or not?

Right. Will add that or just delete the comment.

> > + /* Set frame format */
> > + cr = FMT_LEN(t->bits_per_word);
> > + switch (mode) {
> > + case SPI_NBITS_QUAD:
> > + cr |= FMT_PROTO_QUAD;
> > + break;
>
> Some namespacing on the driver #defines would be a bit safer against the
> possibility of collision with future changes in headers.

Right.

> > +static void sifive_spi_wait(struct sifive_spi *spi, u32 bit, int poll)
> > +{
> > + if (poll) {
> > + u32 cr;
> > + do cr = sifive_spi_read(spi, REG_IP);
> > + while (!(cr & bit));
>
> Please add some braces, indentation or something to make it more clear
> that the read is part of a do/while loop - right now it's not
> immediately obvious that this is correct.

Good point. Will do.

> > +static int sifive_spi_transfer_one(struct spi_master *master,
> > + struct spi_device *device, struct spi_transfer *t)
> > +{
> > + struct sifive_spi *spi = spi_master_get_devdata(master);
> > + int poll = sifive_spi_prep_transfer(spi, device, t);
> > +
> > + sifive_spi_execute(spi, t, poll);
> > +
>
> Why not just inline the execute function here?  It's the only caller
> AFAICT.

Yeah, it is. Will do.

> > +static void sifive_spi_set_cs(struct spi_device *device, bool is_high)
> > +{
> > + struct sifive_spi *spi = spi_master_get_devdata(device->master);
> > +
> > + /* Reverse polarity is handled by SCMR/CPOL. Not inverted CS. */
> > + if (device->mode & SPI_CS_HIGH)
> > + is_high = !is_high;
>
> spi_set_cs() will handle CS_HIGH for you.
>
> > + master->bits_per_word_mask = SPI_BPW_MASK(8);
>
> I thought the device supported other bits per word values?

It does, but the driver doesn't yet. When bits per word is < 8
we need to shift the bits in each byte to be "left-aligned"
(unless SPI_LSB_FIRST is set).

> > + /* If mmc_spi sees a dma_mask, it starts using dma mapped buffers.
> > +  * Probably it should rely on the SPI core auto mapping instead.
> > +  */
> > + pdev->dev.dma_mask = NULL;
>
> If this is a problem please fix it in the MMC core, don't bodge it like
> this.

Gotcha. Will remove this.

> > +static const struct of_device_id sifive_spi_of_match[] = {
> > + { .compatible = "sifive,spi0", },
> > + {}
> > +};
> > +MODULE_DEVICE_TABLE(of, sifive_spi_of_match);
>
> spi0 is a *weird* compatible name.

Exactly. Hence the discussion about the compatible strings.
Once this discussion comes to a conclusion I'll update this.

Thank you for the review!
/Emil


[RFC PATCH] spi: add driver for the SiFive SPI controller

2018-11-12 Thread Emil Renner Berthing
From: Palmer Dabbelt 

Add driver for the SiFive SPI controller
on the HiFive Unleashed board.

Signed-off-by: Palmer Dabbelt 
Signed-off-by: Emil Renner Berthing 
---
 .../devicetree/bindings/spi/spi-sifive.txt|  29 ++
 drivers/spi/Kconfig   |   6 +
 drivers/spi/Makefile  |   1 +
 drivers/spi/spi-sifive.c  | 442 ++
 4 files changed, 478 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/spi/spi-sifive.txt
 create mode 100644 drivers/spi/spi-sifive.c

Hi all,

I know the discussions about the sifive devicetree compatible
strings haven't come to a conclusion, so I'm sending this as
an RFC to get some feedback on the rest of the code.

Compared to the original[1] I've done the following:

- Update register names and bit fields to the ones in the
  FU540-C000 documentation.

- Change the optional devicetree property from "sifive,buffer-size"
  to "sifive,fifo-depth". The string "fifo-depth" seems to have more
  hits in the existing devicetree bindings and is IMHO a little more
  descriptive.

- Change the optional devicetree property from "sifive,bits-per-word"
  to "sifive,max-bits-per-word". For a long time I wondered why the
  SPI word size was a property on the controller and not the device.
  This change makes the meaning a little more clear.

- Be honest about only supporting 8bit SPI words in the driver.
  Without SPI_LSB_FIRST and bits_per_word < 8 we need some code
  to shift the bits in each byte which is not yet there.

- Program the csdef, csid and sckmode registers from prepare_message
  rather than transfer_one. This way we only do it once pr. message
  rather than every transfer.

- Drop the irq field from driver data. With devm_request_irq we
  don't need to remember it after requesting the irq.

- Drop hz = t->speed_hz ? t->speed_hz : device->max_speed_hz;
  The SPI framework handles this for us, so we can just always
  use t->speed_hz.

- Fix most checkpatch warnings.

[1]: 
https://github.com/riscv/riscv-linux/commit/801805694740ad0895e21d10b8f124d138beefbb

/Emil


diff --git a/Documentation/devicetree/bindings/spi/spi-sifive.txt 
b/Documentation/devicetree/bindings/spi/spi-sifive.txt
new file mode 100644
index ..96339afcc74f
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/spi-sifive.txt
@@ -0,0 +1,29 @@
+SiFive SPI controller Device Tree Bindings
+--
+
+Required properties:
+- compatible   : Should be "sifive,spi0"
+- reg  : Physical base address and size of SPI registers map
+ A second (optional) range can indicate memory mapped 
flash
+- interrupts   : Must contain one entry
+- interrupt-parent : Must be core interrupt controller
+- clocks   : Must reference the frequency given to the controller
+- #address-cells   : Must be '1', indicating which CS to use
+- #size-cells  : Must be '0'
+
+Optional properties:
+- sifive,fifo-depth: Depth of hardware queues; defaults to 8
+- sifive,max-bits-per-word : Maximum bits per word; defaults to 8
+
+Example:
+   spi: spi@1004 {
+   compatible = "sifive,spi0";
+   reg = <0x0 0x1004 0x0 0x1000 0x0 0x2000 0x0 0x1000>;
+   interrupt-parent = <&plic>;
+   interrupts = <51>;
+   clocks = <&tlclk>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   sifive,fifo-depth = <8>;
+   sifive,max-bits-per-word = <8>;
+   };
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 7d3a5c94727e..50bfadd24c32 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -615,6 +615,12 @@ config SPI_SH_HSPI
help
  SPI driver for SuperH HSPI blocks.
 
+config SPI_SIFIVE
+   tristate "SiFive SPI controller"
+   depends on HAS_IOMEM
+   help
+ This exposes the SPI controller IP from SiFive.
+
 config SPI_SIRF
tristate "CSR SiRFprimaII SPI controller"
depends on SIRF_DMA
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 3575205c5c27..76216f1861df 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -90,6 +90,7 @@ obj-$(CONFIG_SPI_SH)  += spi-sh.o
 obj-$(CONFIG_SPI_SH_HSPI)  += spi-sh-hspi.o
 obj-$(CONFIG_SPI_SH_MSIOF) += spi-sh-msiof.o
 obj-$(CONFIG_SPI_SH_SCI)   += spi-sh-sci.o
+obj-$(CONFIG_SPI_SIFIVE)   += spi-sifive.o
 obj-$(CONFIG_SPI_SIRF) += spi-sirf.o
 obj-$(CONFIG_SPI_SLAVE_MT27XX)  += spi-slave-mt27xx.o
 obj-$(CONFIG_SPI_SPRD) += spi-sprd.o
diff --git a/drivers/spi/spi-sifive.c b/drivers/spi/sp

[PATCH v1 02/14] spi: rockchip: use designated init for dma config

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

Use C99 designated initializers for dma slave config
structures. This also makes sure uninitialized fields
are zeroed so we don't need an explicit memset.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 26 ++
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 7e54e1a69cc8..87d1b9837d94 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -442,12 +442,8 @@ static void rockchip_spi_dma_txcb(void *data)
 static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
 {
unsigned long flags;
-   struct dma_slave_config rxconf, txconf;
struct dma_async_tx_descriptor *rxdesc, *txdesc;
 
-   memset(&rxconf, 0, sizeof(rxconf));
-   memset(&txconf, 0, sizeof(txconf));
-
spin_lock_irqsave(&rs->lock, flags);
rs->state &= ~RXBUSY;
rs->state &= ~TXBUSY;
@@ -455,10 +451,13 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi 
*rs)
 
rxdesc = NULL;
if (rs->rx) {
-   rxconf.direction = DMA_DEV_TO_MEM;
-   rxconf.src_addr = rs->dma_rx.addr;
-   rxconf.src_addr_width = rs->n_bytes;
-   rxconf.src_maxburst = 1;
+   struct dma_slave_config rxconf = {
+   .direction = DMA_DEV_TO_MEM,
+   .src_addr = rs->dma_rx.addr,
+   .src_addr_width = rs->n_bytes,
+   .src_maxburst = 1,
+   };
+
dmaengine_slave_config(rs->dma_rx.ch, &rxconf);
 
rxdesc = dmaengine_prep_slave_sg(
@@ -474,10 +473,13 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi 
*rs)
 
txdesc = NULL;
if (rs->tx) {
-   txconf.direction = DMA_MEM_TO_DEV;
-   txconf.dst_addr = rs->dma_tx.addr;
-   txconf.dst_addr_width = rs->n_bytes;
-   txconf.dst_maxburst = rs->fifo_len / 2;
+   struct dma_slave_config txconf = {
+   .direction = DMA_MEM_TO_DEV,
+   .dst_addr = rs->dma_tx.addr,
+   .dst_addr_width = rs->n_bytes,
+   .dst_maxburst = rs->fifo_len / 2,
+   };
+
dmaengine_slave_config(rs->dma_tx.ch, &txconf);
 
txdesc = dmaengine_prep_slave_sg(
-- 
2.19.1



[PATCH v1 03/14] spi: rockchip: always use SPI mode

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

The hardware supports 3 different variants of SPI
and there were some code around it, but nothing
to actually set it to anything but "Motorola SPI".
Just drop that code and always use that mode.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 17 -
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 87d1b9837d94..7fac4253075e 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -156,12 +156,6 @@
 
 #define ROCKCHIP_SPI_MAX_CS_NUM2
 
-enum rockchip_ssi_type {
-   SSI_MOTO_SPI = 0,
-   SSI_TI_SSP,
-   SSI_NS_MICROWIRE,
-};
-
 struct rockchip_spi_dma_data {
struct dma_chan *ch;
dma_addr_t addr;
@@ -179,8 +173,6 @@ struct rockchip_spi {
u32 fifo_len;
/* max bus freq supported */
u32 max_freq;
-   /* supported slave numbers */
-   enum rockchip_ssi_type type;
 
u16 mode;
u8 tmode;
@@ -525,14 +517,14 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
u32 dmacr = 0;
int rsd = 0;
 
-   u32 cr0 = (CR0_BHT_8BIT << CR0_BHT_OFFSET)
-   | (CR0_SSD_ONE << CR0_SSD_OFFSET)
-   | (CR0_EM_BIG << CR0_EM_OFFSET);
+   u32 cr0 = CR0_FRF_SPI  << CR0_FRF_OFFSET
+   | CR0_BHT_8BIT << CR0_BHT_OFFSET
+   | CR0_SSD_ONE  << CR0_SSD_OFFSET
+   | CR0_EM_BIG   << CR0_EM_OFFSET;
 
cr0 |= (rs->n_bytes << CR0_DFS_OFFSET);
cr0 |= ((rs->mode & 0x3) << CR0_SCPH_OFFSET);
cr0 |= (rs->tmode << CR0_XFM_OFFSET);
-   cr0 |= (rs->type << CR0_FRF_OFFSET);
 
if (rs->use_dma) {
if (rs->tx)
@@ -709,7 +701,6 @@ static int rockchip_spi_probe(struct platform_device *pdev)
 
spi_enable_chip(rs, false);
 
-   rs->type = SSI_MOTO_SPI;
rs->master = master;
rs->dev = &pdev->dev;
rs->max_freq = clk_get_rate(rs->spiclk);
-- 
2.19.1



[PATCH v1 04/14] spi: rockchip: use atomic_t state

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

The state field is currently only used to make sure
only the last of the tx and rx dma callbacks issue
an spi_finalize_current_transfer.
Rather than using a spinlock we can get away
with just turning the state field into an atomic_t.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 75 +-
 1 file changed, 25 insertions(+), 50 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 7fac4253075e..1c813797f963 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -142,8 +142,9 @@
 #define RF_DMA_EN  (1 << 0)
 #define TF_DMA_EN  (1 << 1)
 
-#define RXBUSY (1 << 0)
-#define TXBUSY (1 << 1)
+/* Driver state flags */
+#define RXDMA  (1 << 0)
+#define TXDMA  (1 << 1)
 
 /* sclk_out: spi master internal logic in rk3x can support 50Mhz */
 #define MAX_SCLK_OUT   5000
@@ -169,6 +170,9 @@ struct rockchip_spi {
struct clk *apb_pclk;
 
void __iomem *regs;
+
+   atomic_t state;
+
/*depth of the FIFO buffer */
u32 fifo_len;
/* max bus freq supported */
@@ -187,10 +191,6 @@ struct rockchip_spi {
void *rx;
void *rx_end;
 
-   u32 state;
-   /* protect state */
-   spinlock_t lock;
-
bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
 
bool use_dma;
@@ -302,28 +302,21 @@ static int rockchip_spi_prepare_message(struct spi_master 
*master,
 static void rockchip_spi_handle_err(struct spi_master *master,
struct spi_message *msg)
 {
-   unsigned long flags;
struct rockchip_spi *rs = spi_master_get_devdata(master);
 
-   spin_lock_irqsave(&rs->lock, flags);
-
/*
 * For DMA mode, we need terminate DMA channel and flush
 * fifo for the next transfer if DMA thansfer timeout.
 * handle_err() was called by core if transfer failed.
 * Maybe it is reasonable for error handling here.
 */
-   if (rs->use_dma) {
-   if (rs->state & RXBUSY) {
-   dmaengine_terminate_async(rs->dma_rx.ch);
-   flush_fifo(rs);
-   }
+   if (atomic_read(&rs->state) & TXDMA)
+   dmaengine_terminate_async(rs->dma_tx.ch);
 
-   if (rs->state & TXBUSY)
-   dmaengine_terminate_async(rs->dma_tx.ch);
+   if (atomic_read(&rs->state) & RXDMA) {
+   dmaengine_terminate_async(rs->dma_rx.ch);
+   flush_fifo(rs);
}
-
-   spin_unlock_irqrestore(&rs->lock, flags);
 }
 
 static int rockchip_spi_unprepare_message(struct spi_master *master,
@@ -398,48 +391,36 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi 
*rs)
 
 static void rockchip_spi_dma_rxcb(void *data)
 {
-   unsigned long flags;
struct rockchip_spi *rs = data;
+   int state = atomic_fetch_andnot(RXDMA, &rs->state);
 
-   spin_lock_irqsave(&rs->lock, flags);
-
-   rs->state &= ~RXBUSY;
-   if (!(rs->state & TXBUSY)) {
-   spi_enable_chip(rs, false);
-   spi_finalize_current_transfer(rs->master);
-   }
+   if (state & TXDMA)
+   return;
 
-   spin_unlock_irqrestore(&rs->lock, flags);
+   spi_enable_chip(rs, false);
+   spi_finalize_current_transfer(rs->master);
 }
 
 static void rockchip_spi_dma_txcb(void *data)
 {
-   unsigned long flags;
struct rockchip_spi *rs = data;
+   int state = atomic_fetch_andnot(TXDMA, &rs->state);
+
+   if (state & RXDMA)
+   return;
 
/* Wait until the FIFO data completely. */
wait_for_idle(rs);
 
-   spin_lock_irqsave(&rs->lock, flags);
-
-   rs->state &= ~TXBUSY;
-   if (!(rs->state & RXBUSY)) {
-   spi_enable_chip(rs, false);
-   spi_finalize_current_transfer(rs->master);
-   }
-
-   spin_unlock_irqrestore(&rs->lock, flags);
+   spi_enable_chip(rs, false);
+   spi_finalize_current_transfer(rs->master);
 }
 
 static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
 {
-   unsigned long flags;
struct dma_async_tx_descriptor *rxdesc, *txdesc;
 
-   spin_lock_irqsave(&rs->lock, flags);
-   rs->state &= ~RXBUSY;
-   rs->state &= ~TXBUSY;
-   spin_unlock_irqrestore(&rs->lock, flags);
+   atomic_set(&rs->state, 0);
 
rxdesc = NULL;
if (rs->rx) {
@@ -490,9 +471,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
 
 

[PATCH v1 06/14] spi: rockchip: read transfer info directly

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

Just read transfer info directly from the spi device
and transfer structures rather than storing it in
driver data first.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 70 +-
 1 file changed, 24 insertions(+), 46 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 5729e6071729..5edc51820d35 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -178,12 +178,8 @@ struct rockchip_spi {
/* max bus freq supported */
u32 max_freq;
 
-   u16 mode;
-   u8 tmode;
-   u8 bpw;
u8 n_bytes;
u32 rsd_nsecs;
-   unsigned len;
u32 speed;
 
const void *tx;
@@ -194,8 +190,6 @@ struct rockchip_spi {
bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
 
bool use_dma;
-   struct sg_table tx_sg;
-   struct sg_table rx_sg;
struct rockchip_spi_dma_data dma_rx;
struct rockchip_spi_dma_data dma_tx;
 };
@@ -282,17 +276,6 @@ static void rockchip_spi_set_cs(struct spi_device *spi, 
bool enable)
rs->cs_asserted[spi->chip_select] = cs_asserted;
 }
 
-static int rockchip_spi_prepare_message(struct spi_master *master,
-   struct spi_message *msg)
-{
-   struct rockchip_spi *rs = spi_master_get_devdata(master);
-   struct spi_device *spi = msg->spi;
-
-   rs->mode = spi->mode;
-
-   return 0;
-}
-
 static void rockchip_spi_handle_err(struct spi_master *master,
struct spi_message *msg)
 {
@@ -397,14 +380,15 @@ static void rockchip_spi_dma_txcb(void *data)
spi_finalize_current_transfer(rs->master);
 }
 
-static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
+static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
+   struct spi_transfer *xfer)
 {
struct dma_async_tx_descriptor *rxdesc, *txdesc;
 
atomic_set(&rs->state, 0);
 
rxdesc = NULL;
-   if (rs->rx) {
+   if (xfer->rx_buf) {
struct dma_slave_config rxconf = {
.direction = DMA_DEV_TO_MEM,
.src_addr = rs->dma_rx.addr,
@@ -416,7 +400,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
 
rxdesc = dmaengine_prep_slave_sg(
rs->dma_rx.ch,
-   rs->rx_sg.sgl, rs->rx_sg.nents,
+   xfer->rx_sg.sgl, xfer->rx_sg.nents,
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
if (!rxdesc)
return -EINVAL;
@@ -426,7 +410,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
}
 
txdesc = NULL;
-   if (rs->tx) {
+   if (xfer->tx_buf) {
struct dma_slave_config txconf = {
.direction = DMA_MEM_TO_DEV,
.dst_addr = rs->dma_tx.addr,
@@ -438,7 +422,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
 
txdesc = dmaengine_prep_slave_sg(
rs->dma_tx.ch,
-   rs->tx_sg.sgl, rs->tx_sg.nents,
+   xfer->tx_sg.sgl, xfer->tx_sg.nents,
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
if (!txdesc) {
if (rxdesc)
@@ -469,7 +453,8 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
return 1;
 }
 
-static void rockchip_spi_config(struct rockchip_spi *rs)
+static void rockchip_spi_config(struct rockchip_spi *rs,
+   struct spi_device *spi, struct spi_transfer *xfer)
 {
u32 div = 0;
u32 dmacr = 0;
@@ -481,13 +466,19 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
| CR0_EM_BIG   << CR0_EM_OFFSET;
 
cr0 |= (rs->n_bytes << CR0_DFS_OFFSET);
-   cr0 |= ((rs->mode & 0x3) << CR0_SCPH_OFFSET);
-   cr0 |= (rs->tmode << CR0_XFM_OFFSET);
+   cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
+
+   if (xfer->rx_buf && xfer->tx_buf)
+   cr0 |= CR0_XFM_TR << CR0_XFM_OFFSET;
+   else if (xfer->rx_buf)
+   cr0 |= CR0_XFM_RO << CR0_XFM_OFFSET;
+   else
+   cr0 |= CR0_XFM_TO << CR0_XFM_OFFSET;
 
if (rs->use_dma) {
-   if (rs->tx)
+   if (xfer->tx_buf)
dmacr |= TF_DMA_EN;
-   if (rs->rx)
+   if (xfer->rx_buf)
dmacr |= RF_DMA_EN;
}
 
@@ -521,11 +512,11 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
 
if (rs->n_bytes == 1)
- 

[PATCH v1 14/14] spi: rockchip: support lsb-first mode

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

Add missing support for lsb-first mode.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 9e47e81553a1..3912526ead66 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -476,6 +476,8 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
 
cr0 |= rs->rsd << CR0_RSD_OFFSET;
cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
+   if (spi->mode & SPI_LSB_FIRST)
+   cr0 |= CR0_FBM_LSB << CR0_FBM_OFFSET;
 
if (xfer->rx_buf && xfer->tx_buf)
cr0 |= CR0_XFM_TR << CR0_XFM_OFFSET;
@@ -681,7 +683,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
 
master->auto_runtime_pm = true;
master->bus_num = pdev->id;
-   master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
+   master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP | SPI_LSB_FIRST;
master->num_chipselect = ROCKCHIP_SPI_MAX_CS_NUM;
master->dev.of_node = pdev->dev.of_node;
master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8) | 
SPI_BPW_MASK(4);
-- 
2.19.1



[PATCH v1 07/14] spi: rockchip: don't store dma channels twice

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

The spi master (aka spi controller) structure already
has two fields for storing the rx and tx dma channels.
Just use them rather than duplicating them in driver data.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 76 +-
 1 file changed, 34 insertions(+), 42 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 5edc51820d35..f3fe6d4cf6f6 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -157,11 +157,6 @@
 
 #define ROCKCHIP_SPI_MAX_CS_NUM2
 
-struct rockchip_spi_dma_data {
-   struct dma_chan *ch;
-   dma_addr_t addr;
-};
-
 struct rockchip_spi {
struct device *dev;
struct spi_master *master;
@@ -170,6 +165,8 @@ struct rockchip_spi {
struct clk *apb_pclk;
 
void __iomem *regs;
+   dma_addr_t dma_addr_rx;
+   dma_addr_t dma_addr_tx;
 
atomic_t state;
 
@@ -190,8 +187,6 @@ struct rockchip_spi {
bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
 
bool use_dma;
-   struct rockchip_spi_dma_data dma_rx;
-   struct rockchip_spi_dma_data dma_tx;
 };
 
 static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable)
@@ -287,10 +282,10 @@ static void rockchip_spi_handle_err(struct spi_master 
*master,
spi_enable_chip(rs, false);
 
if (atomic_read(&rs->state) & TXDMA)
-   dmaengine_terminate_async(rs->dma_tx.ch);
+   dmaengine_terminate_async(master->dma_tx);
 
if (atomic_read(&rs->state) & RXDMA)
-   dmaengine_terminate_async(rs->dma_rx.ch);
+   dmaengine_terminate_async(master->dma_rx);
 }
 
 static void rockchip_spi_pio_writer(struct rockchip_spi *rs)
@@ -381,7 +376,7 @@ static void rockchip_spi_dma_txcb(void *data)
 }
 
 static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
-   struct spi_transfer *xfer)
+   struct spi_master *master, struct spi_transfer *xfer)
 {
struct dma_async_tx_descriptor *rxdesc, *txdesc;
 
@@ -391,15 +386,15 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi 
*rs,
if (xfer->rx_buf) {
struct dma_slave_config rxconf = {
.direction = DMA_DEV_TO_MEM,
-   .src_addr = rs->dma_rx.addr,
+   .src_addr = rs->dma_addr_rx,
.src_addr_width = rs->n_bytes,
.src_maxburst = 1,
};
 
-   dmaengine_slave_config(rs->dma_rx.ch, &rxconf);
+   dmaengine_slave_config(master->dma_rx, &rxconf);
 
rxdesc = dmaengine_prep_slave_sg(
-   rs->dma_rx.ch,
+   master->dma_rx,
xfer->rx_sg.sgl, xfer->rx_sg.nents,
DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
if (!rxdesc)
@@ -413,20 +408,20 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi 
*rs,
if (xfer->tx_buf) {
struct dma_slave_config txconf = {
.direction = DMA_MEM_TO_DEV,
-   .dst_addr = rs->dma_tx.addr,
+   .dst_addr = rs->dma_addr_tx,
.dst_addr_width = rs->n_bytes,
.dst_maxburst = rs->fifo_len / 2,
};
 
-   dmaengine_slave_config(rs->dma_tx.ch, &txconf);
+   dmaengine_slave_config(master->dma_tx, &txconf);
 
txdesc = dmaengine_prep_slave_sg(
-   rs->dma_tx.ch,
+   master->dma_tx,
xfer->tx_sg.sgl, xfer->tx_sg.nents,
DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
if (!txdesc) {
if (rxdesc)
-   dmaengine_terminate_sync(rs->dma_rx.ch);
+   dmaengine_terminate_sync(master->dma_rx);
return -EINVAL;
}
 
@@ -438,7 +433,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
if (rxdesc) {
atomic_or(RXDMA, &rs->state);
dmaengine_submit(rxdesc);
-   dma_async_issue_pending(rs->dma_rx.ch);
+   dma_async_issue_pending(master->dma_rx);
}
 
spi_enable_chip(rs, true);
@@ -446,7 +441,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
if (txdesc) {
atomic_or(TXDMA, &rs->state);
dmaengine_submit(txdesc);
-   dma_async_issue_pending(rs->dma_tx.ch);
+   dma_async_issue_pending(master->dma_tx);
}
 
/* 1 means the transfer 

[PATCH v1 09/14] spi: rockchip: simplify use_dma logic

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

We only need to know if we're using dma when setting
up the transfer, so just use a local variable for
that.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 45a1479c1a29..ba60cbcd45c2 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -184,8 +184,6 @@ struct rockchip_spi {
void *rx_end;
 
bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
-
-   bool use_dma;
 };
 
 static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable)
@@ -450,7 +448,8 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
 }
 
 static void rockchip_spi_config(struct rockchip_spi *rs,
-   struct spi_device *spi, struct spi_transfer *xfer)
+   struct spi_device *spi, struct spi_transfer *xfer,
+   bool use_dma)
 {
u32 div = 0;
u32 dmacr = 0;
@@ -471,7 +470,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
else
cr0 |= CR0_XFM_TO << CR0_XFM_OFFSET;
 
-   if (rs->use_dma) {
+   if (use_dma) {
if (xfer->tx_buf)
dmacr |= TF_DMA_EN;
if (xfer->rx_buf)
@@ -537,6 +536,7 @@ static int rockchip_spi_transfer_one(
struct spi_transfer *xfer)
 {
struct rockchip_spi *rs = spi_master_get_devdata(master);
+   bool use_dma;
 
WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) &&
(readl_relaxed(rs->regs + ROCKCHIP_SPI_SR) & SR_BUSY));
@@ -559,15 +559,11 @@ static int rockchip_spi_transfer_one(
rs->rx = xfer->rx_buf;
rs->rx_end = rs->rx + xfer->len;
 
-   /* we need prepare dma before spi was enabled */
-   if (master->can_dma && master->can_dma(master, spi, xfer))
-   rs->use_dma = true;
-   else
-   rs->use_dma = false;
+   use_dma = master->can_dma ? master->can_dma(master, spi, xfer) : false;
 
-   rockchip_spi_config(rs, spi, xfer);
+   rockchip_spi_config(rs, spi, xfer, use_dma);
 
-   if (rs->use_dma)
+   if (use_dma)
return rockchip_spi_prepare_dma(rs, master, xfer);
 
return rockchip_spi_pio_transfer(rs);
-- 
2.19.1



[PATCH v1 10/14] spi: rockchip: set min/max speed

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

The driver previously checked each transfer if the
requested speed was higher than possible with the
current spi clock rate and raised the clock rate
accordingly.

However, there is no check to see if the spi clock
was actually set that high and no way to dynamically
lower the spi clock rate again.

So it seems any potiential users of this functionality
are better off just setting the spi clock rate at init
using the assigned-clock-rates devicetree property.

Removing this dynamic spi clock rate raising allows
us let the spi framework handle min/max speeds
for us.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 52 +++---
 1 file changed, 20 insertions(+), 32 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index ba60cbcd45c2..d1b3ba2b1532 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -115,6 +115,10 @@
 /* Bit fields in SER, 2bit */
 #define SER_MASK   0x3
 
+/* Bit fields in BAUDR */
+#define BAUDR_SCKDV_MIN2
+#define BAUDR_SCKDV_MAX65534
+
 /* Bit fields in SR, 5bit */
 #define SR_MASK0x1f
 #define SR_BUSY(1 << 0)
@@ -147,7 +151,7 @@
 #define TXDMA  (1 << 1)
 
 /* sclk_out: spi master internal logic in rk3x can support 50Mhz */
-#define MAX_SCLK_OUT   5000
+#define MAX_SCLK_OUT   5000U
 
 /*
  * SPI_CTRLR1 is 16-bits, so we should support lengths of 0x + 1. However,
@@ -171,12 +175,11 @@ struct rockchip_spi {
 
/*depth of the FIFO buffer */
u32 fifo_len;
-   /* max bus freq supported */
-   u32 max_freq;
+   /* frequency of spiclk */
+   u32 freq;
 
u8 n_bytes;
u32 rsd_nsecs;
-   u32 speed;
 
const void *tx;
const void *tx_end;
@@ -191,11 +194,6 @@ static inline void spi_enable_chip(struct rockchip_spi 
*rs, bool enable)
writel_relaxed((enable ? 1U : 0U), rs->regs + ROCKCHIP_SPI_SSIENR);
 }
 
-static inline void spi_set_clk(struct rockchip_spi *rs, u16 div)
-{
-   writel_relaxed(div, rs->regs + ROCKCHIP_SPI_BAUDR);
-}
-
 static inline void wait_for_idle(struct rockchip_spi *rs)
 {
unsigned long timeout = jiffies + msecs_to_jiffies(5);
@@ -451,7 +449,6 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
struct spi_device *spi, struct spi_transfer *xfer,
bool use_dma)
 {
-   u32 div = 0;
u32 dmacr = 0;
int rsd = 0;
 
@@ -477,30 +474,17 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
dmacr |= RF_DMA_EN;
}
 
-   if (WARN_ON(rs->speed > MAX_SCLK_OUT))
-   rs->speed = MAX_SCLK_OUT;
-
-   /* the minimum divisor is 2 */
-   if (rs->max_freq < 2 * rs->speed) {
-   clk_set_rate(rs->spiclk, 2 * rs->speed);
-   rs->max_freq = clk_get_rate(rs->spiclk);
-   }
-
-   /* div doesn't support odd number */
-   div = DIV_ROUND_UP(rs->max_freq, rs->speed);
-   div = (div + 1) & 0xfffe;
-
/* Rx sample delay is expressed in parent clock cycles (max 3) */
-   rsd = DIV_ROUND_CLOSEST(rs->rsd_nsecs * (rs->max_freq >> 8),
+   rsd = DIV_ROUND_CLOSEST(rs->rsd_nsecs * (rs->freq >> 8),
10 >> 8);
if (!rsd && rs->rsd_nsecs) {
pr_warn_once("rockchip-spi: %u Hz are too slow to express %u ns 
delay\n",
-rs->max_freq, rs->rsd_nsecs);
+rs->freq, rs->rsd_nsecs);
} else if (rsd > 3) {
rsd = 3;
pr_warn_once("rockchip-spi: %u Hz are too fast to express %u ns 
delay, clamping at %u ns\n",
-rs->max_freq, rs->rsd_nsecs,
-rsd * 10U / rs->max_freq);
+rs->freq, rs->rsd_nsecs,
+rsd * 10U / rs->freq);
}
cr0 |= rsd << CR0_RSD_OFFSET;
 
@@ -520,9 +504,12 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMARDLR);
writel_relaxed(dmacr, rs->regs + ROCKCHIP_SPI_DMACR);
 
-   spi_set_clk(rs, div);
-
-   dev_dbg(rs->dev, "cr0 0x%x, div %d\n", cr0, div);
+   /* the hardware only supports an even clock divisor, so
+* round divisor = spiclk / speed up to nearest even number
+* so that the resulting speed is <= the requested speed
+*/
+   writel_relaxed(2 * DIV_ROUND_UP(rs->

[PATCH v1 08/14] spi: rockchip: remove master pointer from dev data

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

In almost all cases we already have a pointer to the
spi master structure where we have the driver data.

The only exceptions are the dma callbacks which are
easily fixed by passing them the master and using
spi_master_get_devdata to retrieve the driver data.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 21 ++---
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index f3fe6d4cf6f6..45a1479c1a29 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -159,7 +159,6 @@
 
 struct rockchip_spi {
struct device *dev;
-   struct spi_master *master;
 
struct clk *spiclk;
struct clk *apb_pclk;
@@ -350,19 +349,21 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi 
*rs)
 
 static void rockchip_spi_dma_rxcb(void *data)
 {
-   struct rockchip_spi *rs = data;
+   struct spi_master *master = data;
+   struct rockchip_spi *rs = spi_master_get_devdata(master);
int state = atomic_fetch_andnot(RXDMA, &rs->state);
 
if (state & TXDMA)
return;
 
spi_enable_chip(rs, false);
-   spi_finalize_current_transfer(rs->master);
+   spi_finalize_current_transfer(master);
 }
 
 static void rockchip_spi_dma_txcb(void *data)
 {
-   struct rockchip_spi *rs = data;
+   struct spi_master *master = data;
+   struct rockchip_spi *rs = spi_master_get_devdata(master);
int state = atomic_fetch_andnot(TXDMA, &rs->state);
 
if (state & RXDMA)
@@ -372,7 +373,7 @@ static void rockchip_spi_dma_txcb(void *data)
wait_for_idle(rs);
 
spi_enable_chip(rs, false);
-   spi_finalize_current_transfer(rs->master);
+   spi_finalize_current_transfer(master);
 }
 
 static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
@@ -401,7 +402,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
return -EINVAL;
 
rxdesc->callback = rockchip_spi_dma_rxcb;
-   rxdesc->callback_param = rs;
+   rxdesc->callback_param = master;
}
 
txdesc = NULL;
@@ -426,7 +427,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs,
}
 
txdesc->callback = rockchip_spi_dma_txcb;
-   txdesc->callback_param = rs;
+   txdesc->callback_param = master;
}
 
/* rx must be started before tx due to spi instinct */
@@ -633,7 +634,6 @@ static int rockchip_spi_probe(struct platform_device *pdev)
 
spi_enable_chip(rs, false);
 
-   rs->master = master;
rs->dev = &pdev->dev;
rs->max_freq = clk_get_rate(rs->spiclk);
 
@@ -746,9 +746,8 @@ static int rockchip_spi_suspend(struct device *dev)
 {
int ret;
struct spi_master *master = dev_get_drvdata(dev);
-   struct rockchip_spi *rs = spi_master_get_devdata(master);
 
-   ret = spi_master_suspend(rs->master);
+   ret = spi_master_suspend(master);
if (ret < 0)
return ret;
 
@@ -773,7 +772,7 @@ static int rockchip_spi_resume(struct device *dev)
if (ret < 0)
return ret;
 
-   ret = spi_master_resume(rs->master);
+   ret = spi_master_resume(master);
if (ret < 0) {
clk_disable_unprepare(rs->spiclk);
clk_disable_unprepare(rs->apb_pclk);
-- 
2.19.1



[PATCH v1 13/14] spi: rockchip: support 4bit words

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

The hardware supports 4, 8 and 16bit spi words,
so add the missing support for 4bit words.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 41 +++---
 1 file changed, 29 insertions(+), 12 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 1297f081818d..9e47e81553a1 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -54,6 +54,9 @@
 
 /* Bit fields in CTRLR0 */
 #define CR0_DFS_OFFSET 0
+#define CR0_DFS_4BIT   0x0
+#define CR0_DFS_8BIT   0x1
+#define CR0_DFS_16BIT  0x2
 
 #define CR0_CFS_OFFSET 2
 
@@ -464,15 +467,14 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
struct spi_device *spi, struct spi_transfer *xfer,
bool use_dma)
 {
-   u32 dmacr = 0;
-
u32 cr0 = CR0_FRF_SPI  << CR0_FRF_OFFSET
| CR0_BHT_8BIT << CR0_BHT_OFFSET
| CR0_SSD_ONE  << CR0_SSD_OFFSET
| CR0_EM_BIG   << CR0_EM_OFFSET;
+   u32 cr1;
+   u32 dmacr = 0;
 
cr0 |= rs->rsd << CR0_RSD_OFFSET;
-   cr0 |= (rs->n_bytes << CR0_DFS_OFFSET);
cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
 
if (xfer->rx_buf && xfer->tx_buf)
@@ -482,6 +484,27 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
else if (use_dma)
cr0 |= CR0_XFM_TO << CR0_XFM_OFFSET;
 
+   switch (xfer->bits_per_word) {
+   case 4:
+   cr0 |= CR0_DFS_4BIT << CR0_DFS_OFFSET;
+   cr1 = xfer->len - 1;
+   break;
+   case 8:
+   cr0 |= CR0_DFS_8BIT << CR0_DFS_OFFSET;
+   cr1 = xfer->len - 1;
+   break;
+   case 16:
+   cr0 |= CR0_DFS_16BIT << CR0_DFS_OFFSET;
+   cr1 = xfer->len / 2 - 1;
+   break;
+   default:
+   /* we only whitelist 4, 8 and 16 bit words in
+* master->bits_per_word_mask, so this shouldn't
+* happen
+*/
+   unreachable();
+   }
+
if (use_dma) {
if (xfer->tx_buf)
dmacr |= TF_DMA_EN;
@@ -490,13 +513,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
}
 
writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
-
-   if (rs->n_bytes == 1)
-   writel_relaxed(xfer->len - 1, rs->regs + ROCKCHIP_SPI_CTRLR1);
-   else if (rs->n_bytes == 2)
-   writel_relaxed((xfer->len / 2) - 1, rs->regs + 
ROCKCHIP_SPI_CTRLR1);
-   else
-   writel_relaxed((xfer->len * 2) - 1, rs->regs + 
ROCKCHIP_SPI_CTRLR1);
+   writel_relaxed(cr1, rs->regs + ROCKCHIP_SPI_CTRLR1);
 
/* unfortunately setting the fifo threshold level to generate an
 * interrupt exactly when the fifo is full doesn't seem to work,
@@ -545,7 +562,7 @@ static int rockchip_spi_transfer_one(
return -EINVAL;
}
 
-   rs->n_bytes = xfer->bits_per_word >> 3;
+   rs->n_bytes = xfer->bits_per_word <= 8 ? 1 : 2;
 
use_dma = master->can_dma ? master->can_dma(master, spi, xfer) : false;
 
@@ -667,7 +684,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP;
master->num_chipselect = ROCKCHIP_SPI_MAX_CS_NUM;
master->dev.of_node = pdev->dev.of_node;
-   master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8);
+   master->bits_per_word_mask = SPI_BPW_MASK(16) | SPI_BPW_MASK(8) | 
SPI_BPW_MASK(4);
master->min_speed_hz = rs->freq / BAUDR_SCKDV_MAX;
master->max_speed_hz = min(rs->freq / BAUDR_SCKDV_MIN, MAX_SCLK_OUT);
 
-- 
2.19.1



[PATCH v1 11/14] spi: rockchip: precompute rx sample delay

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

Now that we no longer potentially change spi clock
at runtime we can precompute the rx sample delay
at probe time rather than for each transfer.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 36 ++--
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index d1b3ba2b1532..5fe6099ff366 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -94,6 +94,7 @@
 #define CR0_BHT_8BIT   0x1
 
 #define CR0_RSD_OFFSET 14
+#define CR0_RSD_MAX0x3
 
 #define CR0_FRF_OFFSET 16
 #define CR0_FRF_SPI0x0
@@ -179,7 +180,7 @@ struct rockchip_spi {
u32 freq;
 
u8 n_bytes;
-   u32 rsd_nsecs;
+   u8 rsd;
 
const void *tx;
const void *tx_end;
@@ -450,13 +451,13 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
bool use_dma)
 {
u32 dmacr = 0;
-   int rsd = 0;
 
u32 cr0 = CR0_FRF_SPI  << CR0_FRF_OFFSET
| CR0_BHT_8BIT << CR0_BHT_OFFSET
| CR0_SSD_ONE  << CR0_SSD_OFFSET
| CR0_EM_BIG   << CR0_EM_OFFSET;
 
+   cr0 |= rs->rsd << CR0_RSD_OFFSET;
cr0 |= (rs->n_bytes << CR0_DFS_OFFSET);
cr0 |= (spi->mode & 0x3U) << CR0_SCPH_OFFSET;
 
@@ -474,20 +475,6 @@ static void rockchip_spi_config(struct rockchip_spi *rs,
dmacr |= RF_DMA_EN;
}
 
-   /* Rx sample delay is expressed in parent clock cycles (max 3) */
-   rsd = DIV_ROUND_CLOSEST(rs->rsd_nsecs * (rs->freq >> 8),
-   10 >> 8);
-   if (!rsd && rs->rsd_nsecs) {
-   pr_warn_once("rockchip-spi: %u Hz are too slow to express %u ns 
delay\n",
-rs->freq, rs->rsd_nsecs);
-   } else if (rsd > 3) {
-   rsd = 3;
-   pr_warn_once("rockchip-spi: %u Hz are too fast to express %u ns 
delay, clamping at %u ns\n",
-rs->freq, rs->rsd_nsecs,
-rsd * 10U / rs->freq);
-   }
-   cr0 |= rsd << CR0_RSD_OFFSET;
-
writel_relaxed(cr0, rs->regs + ROCKCHIP_SPI_CTRLR0);
 
if (rs->n_bytes == 1)
@@ -620,8 +607,21 @@ static int rockchip_spi_probe(struct platform_device *pdev)
rs->freq = clk_get_rate(rs->spiclk);
 
if (!of_property_read_u32(pdev->dev.of_node, "rx-sample-delay-ns",
- &rsd_nsecs))
-   rs->rsd_nsecs = rsd_nsecs;
+ &rsd_nsecs)) {
+   /* rx sample delay is expressed in parent clock cycles (max 3) 
*/
+   u32 rsd = DIV_ROUND_CLOSEST(rsd_nsecs * (rs->freq >> 8),
+   10 >> 8);
+   if (!rsd) {
+   dev_warn(rs->dev, "%u Hz are too slow to express %u ns 
delay\n",
+   rs->freq, rsd_nsecs);
+   } else if (rsd > CR0_RSD_MAX) {
+   rsd = CR0_RSD_MAX;
+   dev_warn(rs->dev, "%u Hz are too fast to express %u ns 
delay, clamping at %u ns\n",
+   rs->freq, rsd_nsecs,
+   CR0_RSD_MAX * 10U / rs->freq);
+   }
+   rs->rsd = rsd;
+   }
 
rs->fifo_len = get_fifo_len(rs);
if (!rs->fifo_len) {
-- 
2.19.1



[PATCH v1 05/14] spi: rockchip: disable spi on error

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

Successful transfers leave the spi disabled, so if
we just make sure to disable the spi on error
there should be no need to disable the spi from
master->unprepare_message.

This also flushes the tx and rx fifos,
so no need to do that manually.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 30 +-
 1 file changed, 5 insertions(+), 25 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 1c813797f963..5729e6071729 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -210,12 +210,6 @@ static inline void spi_set_clk(struct rockchip_spi *rs, 
u16 div)
writel_relaxed(div, rs->regs + ROCKCHIP_SPI_BAUDR);
 }
 
-static inline void flush_fifo(struct rockchip_spi *rs)
-{
-   while (readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR))
-   readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
-}
-
 static inline void wait_for_idle(struct rockchip_spi *rs)
 {
unsigned long timeout = jiffies + msecs_to_jiffies(5);
@@ -304,29 +298,16 @@ static void rockchip_spi_handle_err(struct spi_master 
*master,
 {
struct rockchip_spi *rs = spi_master_get_devdata(master);
 
-   /*
-* For DMA mode, we need terminate DMA channel and flush
-* fifo for the next transfer if DMA thansfer timeout.
-* handle_err() was called by core if transfer failed.
-* Maybe it is reasonable for error handling here.
+   /* stop running spi transfer
+* this also flushes both rx and tx fifos
 */
+   spi_enable_chip(rs, false);
+
if (atomic_read(&rs->state) & TXDMA)
dmaengine_terminate_async(rs->dma_tx.ch);
 
-   if (atomic_read(&rs->state) & RXDMA) {
+   if (atomic_read(&rs->state) & RXDMA)
dmaengine_terminate_async(rs->dma_rx.ch);
-   flush_fifo(rs);
-   }
-}
-
-static int rockchip_spi_unprepare_message(struct spi_master *master,
- struct spi_message *msg)
-{
-   struct rockchip_spi *rs = spi_master_get_devdata(master);
-
-   spi_enable_chip(rs, false);
-
-   return 0;
 }
 
 static void rockchip_spi_pio_writer(struct rockchip_spi *rs)
@@ -705,7 +686,6 @@ static int rockchip_spi_probe(struct platform_device *pdev)
 
master->set_cs = rockchip_spi_set_cs;
master->prepare_message = rockchip_spi_prepare_message;
-   master->unprepare_message = rockchip_spi_unprepare_message;
master->transfer_one = rockchip_spi_transfer_one;
master->max_transfer_size = rockchip_spi_max_transfer_size;
master->handle_err = rockchip_spi_handle_err;
-- 
2.19.1



[PATCH v1 12/14] spi: rockchip: use irq rather than polling

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

Register an interrupt handler to fill/empty the
tx and rx fifos rather than busy-looping.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 155 ++---
 1 file changed, 92 insertions(+), 63 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 5fe6099ff366..1297f081818d 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -172,6 +172,11 @@ struct rockchip_spi {
dma_addr_t dma_addr_rx;
dma_addr_t dma_addr_tx;
 
+   const void *tx;
+   void *rx;
+   unsigned int tx_left;
+   unsigned int rx_left;
+
atomic_t state;
 
/*depth of the FIFO buffer */
@@ -182,11 +187,6 @@ struct rockchip_spi {
u8 n_bytes;
u8 rsd;
 
-   const void *tx;
-   const void *tx_end;
-   void *rx;
-   void *rx_end;
-
bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
 };
 
@@ -222,24 +222,6 @@ static u32 get_fifo_len(struct rockchip_spi *rs)
return (fifo == 31) ? 0 : fifo;
 }
 
-static inline u32 tx_max(struct rockchip_spi *rs)
-{
-   u32 tx_left, tx_room;
-
-   tx_left = (rs->tx_end - rs->tx) / rs->n_bytes;
-   tx_room = rs->fifo_len - readl_relaxed(rs->regs + ROCKCHIP_SPI_TXFLR);
-
-   return min(tx_left, tx_room);
-}
-
-static inline u32 rx_max(struct rockchip_spi *rs)
-{
-   u32 rx_left = (rs->rx_end - rs->rx) / rs->n_bytes;
-   u32 rx_room = (u32)readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
-
-   return min(rx_left, rx_room);
-}
-
 static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
 {
struct spi_master *master = spi->master;
@@ -277,6 +259,9 @@ static void rockchip_spi_handle_err(struct spi_master 
*master,
 */
spi_enable_chip(rs, false);
 
+   /* make sure all interrupts are masked */
+   writel_relaxed(0, rs->regs + ROCKCHIP_SPI_IMR);
+
if (atomic_read(&rs->state) & TXDMA)
dmaengine_terminate_async(master->dma_tx);
 
@@ -286,14 +271,17 @@ static void rockchip_spi_handle_err(struct spi_master 
*master,
 
 static void rockchip_spi_pio_writer(struct rockchip_spi *rs)
 {
-   u32 max = tx_max(rs);
-   u32 txw = 0;
+   u32 tx_free = rs->fifo_len - readl_relaxed(rs->regs + 
ROCKCHIP_SPI_TXFLR);
+   u32 words = min(rs->tx_left, tx_free);
+
+   rs->tx_left -= words;
+   for (; words; words--) {
+   u32 txw;
 
-   while (max--) {
if (rs->n_bytes == 1)
-   txw = *(u8 *)(rs->tx);
+   txw = *(u8 *)rs->tx;
else
-   txw = *(u16 *)(rs->tx);
+   txw = *(u16 *)rs->tx;
 
writel_relaxed(txw, rs->regs + ROCKCHIP_SPI_TXDR);
rs->tx += rs->n_bytes;
@@ -302,46 +290,72 @@ static void rockchip_spi_pio_writer(struct rockchip_spi 
*rs)
 
 static void rockchip_spi_pio_reader(struct rockchip_spi *rs)
 {
-   u32 max = rx_max(rs);
-   u32 rxw;
+   u32 words = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFLR);
+   u32 rx_left = rs->rx_left - words;
+
+   /* the hardware doesn't allow us to change fifo threshold
+* level while spi is enabled, so instead make sure to leave
+* enough words in the rx fifo to get the last interrupt
+* exactly when all words have been received
+*/
+   if (rx_left) {
+   u32 ftl = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXFTLR) + 1;
+
+   if (rx_left < ftl) {
+   rx_left = ftl;
+   words = rs->rx_left - rx_left;
+   }
+   }
+
+   rs->rx_left = rx_left;
+   for (; words; words--) {
+   u32 rxw = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
+
+   if (!rs->rx)
+   continue;
 
-   while (max--) {
-   rxw = readl_relaxed(rs->regs + ROCKCHIP_SPI_RXDR);
if (rs->n_bytes == 1)
-   *(u8 *)(rs->rx) = (u8)rxw;
+   *(u8 *)rs->rx = (u8)rxw;
else
-   *(u16 *)(rs->rx) = (u16)rxw;
+   *(u16 *)rs->rx = (u16)rxw;
rs->rx += rs->n_bytes;
}
 }
 
-static int rockchip_spi_pio_transfer(struct rockchip_spi *rs)
+static irqreturn_t rockchip_spi_isr(int irq, void *dev_id)
 {
-   int remain = 0;
+   struct spi_master *master = dev_id;
+   struct rockchip_spi *rs = spi_master_get_devdata(master);
 
-   spi_enable_chip(rs, true);
+   if (rs->tx_left)
+   rockchip_spi_pio_writer(rs);
 
-   do {
-   if (rs->tx) {
-   remain = rs->tx_end - rs->tx;
-   rockchip_spi_pio_writer(rs);
-   }
+  

[PATCH v1 00/14] Rockchip SPI cleanup and use interrupts

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

Hi,

I took another look at the rockchip spi driver and ended up
with more cleanups and implementing an interrupt handler
to fill/empty the tx and rx fifos rather than busy-looping.

I have two question though:

The driver sets the SPI_LOOP flag in master->mode_bits,
but never checks if the flag is set on an spi device.
That looks suspicious to me, but I'm not exactly sure what
that flag means, so it might be ok?

The driver registers a master->max_transfer_size function
to always return 0x, but also checks each transfer
for xfer->len > 0x.
I thought that was redundant, but it turns out I can
trigger it with a simple
dd if=/dev/mtd0 of=/dev/null bs=[something > 0x]
Is that a bug or have I just not understood what
master->max_transfer_size is supposed to do?

/Emil

Emil Renner Berthing (14):
  spi: rockchip: make spi_enable_chip take bool
  spi: rockchip: use designated init for dma config
  spi: rockchip: always use SPI mode
  spi: rockchip: use atomic_t state
  spi: rockchip: disable spi on error
  spi: rockchip: read transfer info directly
  spi: rockchip: don't store dma channels twice
  spi: rockchip: remove master pointer from dev data
  spi: rockchip: simplify use_dma logic
  spi: rockchip: set min/max speed
  spi: rockchip: precompute rx sample delay
  spi: rockchip: use irq rather than polling
  spi: rockchip: support 4bit words
  spi: rockchip: support lsb-first mode

 drivers/spi/spi-rockchip.c | 579 +
 1 file changed, 264 insertions(+), 315 deletions(-)

-- 
2.19.1



[PATCH v1 01/14] spi: rockchip: make spi_enable_chip take bool

2018-10-31 Thread Emil Renner Berthing
From: Emil Renner Berthing 

The spi_enable_chip function takes a boolean
argument. Change the type to reflect that.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 51ef632bca52..7e54e1a69cc8 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -208,9 +208,9 @@ struct rockchip_spi {
struct rockchip_spi_dma_data dma_tx;
 };
 
-static inline void spi_enable_chip(struct rockchip_spi *rs, int enable)
+static inline void spi_enable_chip(struct rockchip_spi *rs, bool enable)
 {
-   writel_relaxed((enable ? 1 : 0), rs->regs + ROCKCHIP_SPI_SSIENR);
+   writel_relaxed((enable ? 1U : 0U), rs->regs + ROCKCHIP_SPI_SSIENR);
 }
 
 static inline void spi_set_clk(struct rockchip_spi *rs, u16 div)
@@ -339,7 +339,7 @@ static int rockchip_spi_unprepare_message(struct spi_master 
*master,
 {
struct rockchip_spi *rs = spi_master_get_devdata(master);
 
-   spi_enable_chip(rs, 0);
+   spi_enable_chip(rs, false);
 
return 0;
 }
@@ -379,7 +379,7 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi 
*rs)
 {
int remain = 0;
 
-   spi_enable_chip(rs, 1);
+   spi_enable_chip(rs, true);
 
do {
if (rs->tx) {
@@ -399,7 +399,7 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi 
*rs)
if (rs->tx)
wait_for_idle(rs);
 
-   spi_enable_chip(rs, 0);
+   spi_enable_chip(rs, false);
 
return 0;
 }
@@ -413,7 +413,7 @@ static void rockchip_spi_dma_rxcb(void *data)
 
rs->state &= ~RXBUSY;
if (!(rs->state & TXBUSY)) {
-   spi_enable_chip(rs, 0);
+   spi_enable_chip(rs, false);
spi_finalize_current_transfer(rs->master);
}
 
@@ -432,7 +432,7 @@ static void rockchip_spi_dma_txcb(void *data)
 
rs->state &= ~TXBUSY;
if (!(rs->state & RXBUSY)) {
-   spi_enable_chip(rs, 0);
+   spi_enable_chip(rs, false);
spi_finalize_current_transfer(rs->master);
}
 
@@ -503,7 +503,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
dma_async_issue_pending(rs->dma_rx.ch);
}
 
-   spi_enable_chip(rs, 1);
+   spi_enable_chip(rs, true);
 
if (txdesc) {
spin_lock_irqsave(&rs->lock, flags);
@@ -705,7 +705,7 @@ static int rockchip_spi_probe(struct platform_device *pdev)
goto err_disable_apbclk;
}
 
-   spi_enable_chip(rs, 0);
+   spi_enable_chip(rs, false);
 
rs->type = SSI_MOTO_SPI;
rs->master = master;
-- 
2.19.1



[PATCH 1/7] spi: rockchip: initialize dma_slave_config properly

2018-10-10 Thread Emil Renner Berthing
From: Huibin Hong 

The rxconf and txconf structs are allocated on the
stack, so make sure we zero them before filling out
the relevant fields.

Signed-off-by: Huibin Hong 
Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index fdcf3076681b..185bbdce62b1 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -445,6 +445,9 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
struct dma_slave_config rxconf, txconf;
struct dma_async_tx_descriptor *rxdesc, *txdesc;
 
+   memset(&rxconf, 0, sizeof(rxconf));
+   memset(&txconf, 0, sizeof(txconf));
+
spin_lock_irqsave(&rs->lock, flags);
rs->state &= ~RXBUSY;
rs->state &= ~TXBUSY;
-- 
2.19.1



[PATCH 0/7] Enable spi dma on Rockchip RK3399

2018-10-10 Thread Emil Renner Berthing
Hi all,

The first three patches in this series enable spi dma on rk3399,
while the remaining patches are meant to be decreasingly obvious
cleanups to the rockchip spi driver.

Unfortunately I only have rk3399-gru-kevin hardware to test
this on, so it would be nice if someone would test this on
other rockchips.

/Emil

Emil Renner Berthing (5):
  arm64: dts: rockchip: add rk3399 SPI DMAs
  spi: rockchip: remove unneeded dma_caps
  spi: rockchip: mark use_dma as bool
  spi: rockchip: directly use direction constants
  spi: rockchip: simplify spi enable logic

Huibin Hong (2):
  spi: rockchip: initialize dma_slave_config properly
  spi: rockchip: adjust dma watermark and burstlen

 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 10 
 drivers/spi/spi-rockchip.c   | 62 +---
 2 files changed, 32 insertions(+), 40 deletions(-)

-- 
2.19.1



[PATCH 3/7] arm64: dts: rockchip: add rk3399 SPI DMAs

2018-10-10 Thread Emil Renner Berthing
Add spi dma channels as specified by the rk3399 TRM.

Signed-off-by: Emil Renner Berthing 
---
 arch/arm64/boot/dts/rockchip/rk3399.dtsi | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi 
b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index c88e603396f6..c11b5ae6f1ad 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -653,6 +653,8 @@
clocks = <&cru SCLK_SPI0>, <&cru PCLK_SPI0>;
clock-names = "spiclk", "apb_pclk";
interrupts = ;
+   dmas = <&dmac_peri 10>, <&dmac_peri 11>;
+   dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&spi0_clk &spi0_tx &spi0_rx &spi0_cs0>;
#address-cells = <1>;
@@ -666,6 +668,8 @@
clocks = <&cru SCLK_SPI1>, <&cru PCLK_SPI1>;
clock-names = "spiclk", "apb_pclk";
interrupts = ;
+   dmas = <&dmac_peri 12>, <&dmac_peri 13>;
+   dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&spi1_clk &spi1_tx &spi1_rx &spi1_cs0>;
#address-cells = <1>;
@@ -679,6 +683,8 @@
clocks = <&cru SCLK_SPI2>, <&cru PCLK_SPI2>;
clock-names = "spiclk", "apb_pclk";
interrupts = ;
+   dmas = <&dmac_peri 14>, <&dmac_peri 15>;
+   dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&spi2_clk &spi2_tx &spi2_rx &spi2_cs0>;
#address-cells = <1>;
@@ -692,6 +698,8 @@
clocks = <&cru SCLK_SPI4>, <&cru PCLK_SPI4>;
clock-names = "spiclk", "apb_pclk";
interrupts = ;
+   dmas = <&dmac_peri 18>, <&dmac_peri 19>;
+   dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&spi4_clk &spi4_tx &spi4_rx &spi4_cs0>;
#address-cells = <1>;
@@ -705,6 +713,8 @@
clocks = <&cru SCLK_SPI5>, <&cru PCLK_SPI5>;
clock-names = "spiclk", "apb_pclk";
interrupts = ;
+   dmas = <&dmac_bus 8>, <&dmac_bus 9>;
+   dma-names = "tx", "rx";
pinctrl-names = "default";
pinctrl-0 = <&spi5_clk &spi5_tx &spi5_rx &spi5_cs0>;
power-domains = <&power RK3399_PD_SDIOAUDIO>;
-- 
2.19.1



[PATCH 5/7] spi: rockchip: mark use_dma as bool

2018-10-10 Thread Emil Renner Berthing
The driver data has a u32 field use_dma which is
only ever used as a boolean, so change its type
to reflect that.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 85358f96f78f..1d8bf45304a5 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -202,7 +202,7 @@ struct rockchip_spi {
 
bool cs_asserted[ROCKCHIP_SPI_MAX_CS_NUM];
 
-   u32 use_dma;
+   bool use_dma;
struct sg_table tx_sg;
struct sg_table rx_sg;
struct rockchip_spi_dma_data dma_rx;
@@ -631,9 +631,9 @@ static int rockchip_spi_transfer_one(
 
/* we need prepare dma before spi was enabled */
if (master->can_dma && master->can_dma(master, spi, xfer))
-   rs->use_dma = 1;
+   rs->use_dma = true;
else
-   rs->use_dma = 0;
+   rs->use_dma = false;
 
rockchip_spi_config(rs);
 
-- 
2.19.1



[PATCH 7/7] spi: rockchip: simplify spi enable logic

2018-10-10 Thread Emil Renner Berthing
Let the dma/non-dma code paths handle the spi enable
flag themselves. This removes some logic to determine
if the flag should be turned on before or after dma
and also don't leave the spi enabled if the dma path
fails.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 28 +---
 1 file changed, 9 insertions(+), 19 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 1044849a352d..51ef632bca52 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -379,6 +379,8 @@ static int rockchip_spi_pio_transfer(struct rockchip_spi 
*rs)
 {
int remain = 0;
 
+   spi_enable_chip(rs, 1);
+
do {
if (rs->tx) {
remain = rs->tx_end - rs->tx;
@@ -501,6 +503,8 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
dma_async_issue_pending(rs->dma_rx.ch);
}
 
+   spi_enable_chip(rs, 1);
+
if (txdesc) {
spin_lock_irqsave(&rs->lock, flags);
rs->state |= TXBUSY;
@@ -509,7 +513,8 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
dma_async_issue_pending(rs->dma_tx.ch);
}
 
-   return 0;
+   /* 1 means the transfer is in progress */
+   return 1;
 }
 
 static void rockchip_spi_config(struct rockchip_spi *rs)
@@ -592,7 +597,6 @@ static int rockchip_spi_transfer_one(
struct spi_device *spi,
struct spi_transfer *xfer)
 {
-   int ret = 0;
struct rockchip_spi *rs = spi_master_get_devdata(master);
 
WARN_ON(readl_relaxed(rs->regs + ROCKCHIP_SPI_SSIENR) &&
@@ -636,24 +640,10 @@ static int rockchip_spi_transfer_one(
 
rockchip_spi_config(rs);
 
-   if (rs->use_dma) {
-   if (rs->tmode == CR0_XFM_RO) {
-   /* rx: dma must be prepared first */
-   ret = rockchip_spi_prepare_dma(rs);
-   spi_enable_chip(rs, 1);
-   } else {
-   /* tx or tr: spi must be enabled first */
-   spi_enable_chip(rs, 1);
-   ret = rockchip_spi_prepare_dma(rs);
-   }
-   /* successful DMA prepare means the transfer is in progress */
-   ret = ret ? ret : 1;
-   } else {
-   spi_enable_chip(rs, 1);
-   ret = rockchip_spi_pio_transfer(rs);
-   }
+   if (rs->use_dma)
+   return rockchip_spi_prepare_dma(rs);
 
-   return ret;
+   return rockchip_spi_pio_transfer(rs);
 }
 
 static bool rockchip_spi_can_dma(struct spi_master *master,
-- 
2.19.1



[PATCH 6/7] spi: rockchip: directly use direction constants

2018-10-10 Thread Emil Renner Berthing
The dma direction for the tx and rx dma channels never
change, so just use the constants directly rather
than storing them in device data.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 11 ---
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 1d8bf45304a5..1044849a352d 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -164,7 +164,6 @@ enum rockchip_ssi_type {
 
 struct rockchip_spi_dma_data {
struct dma_chan *ch;
-   enum dma_transfer_direction direction;
dma_addr_t addr;
 };
 
@@ -454,7 +453,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
 
rxdesc = NULL;
if (rs->rx) {
-   rxconf.direction = rs->dma_rx.direction;
+   rxconf.direction = DMA_DEV_TO_MEM;
rxconf.src_addr = rs->dma_rx.addr;
rxconf.src_addr_width = rs->n_bytes;
rxconf.src_maxburst = 1;
@@ -463,7 +462,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
rxdesc = dmaengine_prep_slave_sg(
rs->dma_rx.ch,
rs->rx_sg.sgl, rs->rx_sg.nents,
-   rs->dma_rx.direction, DMA_PREP_INTERRUPT);
+   DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT);
if (!rxdesc)
return -EINVAL;
 
@@ -473,7 +472,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
 
txdesc = NULL;
if (rs->tx) {
-   txconf.direction = rs->dma_tx.direction;
+   txconf.direction = DMA_MEM_TO_DEV;
txconf.dst_addr = rs->dma_tx.addr;
txconf.dst_addr_width = rs->n_bytes;
txconf.dst_maxburst = rs->fifo_len / 2;
@@ -482,7 +481,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi *rs)
txdesc = dmaengine_prep_slave_sg(
rs->dma_tx.ch,
rs->tx_sg.sgl, rs->tx_sg.nents,
-   rs->dma_tx.direction, DMA_PREP_INTERRUPT);
+   DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT);
if (!txdesc) {
if (rxdesc)
dmaengine_terminate_sync(rs->dma_rx.ch);
@@ -778,8 +777,6 @@ static int rockchip_spi_probe(struct platform_device *pdev)
if (rs->dma_tx.ch && rs->dma_rx.ch) {
rs->dma_tx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_TXDR);
rs->dma_rx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_RXDR);
-   rs->dma_tx.direction = DMA_MEM_TO_DEV;
-   rs->dma_rx.direction = DMA_DEV_TO_MEM;
 
master->can_dma = rockchip_spi_can_dma;
master->dma_tx = rs->dma_tx.ch;
-- 
2.19.1



[PATCH 4/7] spi: rockchip: remove unneeded dma_caps

2018-10-10 Thread Emil Renner Berthing
We no longer need the dma_caps since the dma driver
already clamps the burst length to the hardware limit,
so don't request and store dma_caps in device data.

Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index ede3002215cd..85358f96f78f 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -207,7 +207,6 @@ struct rockchip_spi {
struct sg_table rx_sg;
struct rockchip_spi_dma_data dma_rx;
struct rockchip_spi_dma_data dma_tx;
-   struct dma_slave_caps dma_caps;
 };
 
 static inline void spi_enable_chip(struct rockchip_spi *rs, int enable)
@@ -777,7 +776,6 @@ static int rockchip_spi_probe(struct platform_device *pdev)
}
 
if (rs->dma_tx.ch && rs->dma_rx.ch) {
-   dma_get_slave_caps(rs->dma_rx.ch, &(rs->dma_caps));
rs->dma_tx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_TXDR);
rs->dma_rx.addr = (dma_addr_t)(mem->start + ROCKCHIP_SPI_RXDR);
rs->dma_tx.direction = DMA_MEM_TO_DEV;
-- 
2.19.1



[PATCH 2/7] spi: rockchip: adjust dma watermark and burstlen

2018-10-10 Thread Emil Renner Berthing
From: Huibin Hong 

Signal tx dma when spi fifo is less than half full,
and limit tx bursts to half the fifo length.

Clamp rx burst length to 1 to avoid alignment issues.

Signed-off-by: Huibin Hong 
Signed-off-by: Emil Renner Berthing 
---
 drivers/spi/spi-rockchip.c | 12 +++-
 1 file changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 185bbdce62b1..ede3002215cd 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -458,10 +458,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi 
*rs)
rxconf.direction = rs->dma_rx.direction;
rxconf.src_addr = rs->dma_rx.addr;
rxconf.src_addr_width = rs->n_bytes;
-   if (rs->dma_caps.max_burst > 4)
-   rxconf.src_maxburst = 4;
-   else
-   rxconf.src_maxburst = 1;
+   rxconf.src_maxburst = 1;
dmaengine_slave_config(rs->dma_rx.ch, &rxconf);
 
rxdesc = dmaengine_prep_slave_sg(
@@ -480,10 +477,7 @@ static int rockchip_spi_prepare_dma(struct rockchip_spi 
*rs)
txconf.direction = rs->dma_tx.direction;
txconf.dst_addr = rs->dma_tx.addr;
txconf.dst_addr_width = rs->n_bytes;
-   if (rs->dma_caps.max_burst > 4)
-   txconf.dst_maxburst = 4;
-   else
-   txconf.dst_maxburst = 1;
+   txconf.dst_maxburst = rs->fifo_len / 2;
dmaengine_slave_config(rs->dma_tx.ch, &txconf);
 
txdesc = dmaengine_prep_slave_sg(
@@ -581,7 +575,7 @@ static void rockchip_spi_config(struct rockchip_spi *rs)
writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_TXFTLR);
writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_RXFTLR);
 
-   writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMATDLR);
+   writel_relaxed(rs->fifo_len / 2 - 1, rs->regs + ROCKCHIP_SPI_DMATDLR);
writel_relaxed(0, rs->regs + ROCKCHIP_SPI_DMARDLR);
writel_relaxed(dmacr, rs->regs + ROCKCHIP_SPI_DMACR);
 
-- 
2.19.1



Re: [PATCH] mfd: cros-ec: copy the whole event when msg->version is 0

2018-09-28 Thread Emil Renner Berthing
On Fri, 28 Sep 2018 at 14:15, Neil Armstrong  wrote:
> On 27/09/2018 11:24, Emil Karlson wrote:
> > Commit 57e94c8b974db2d83c60e1139c89a70806abbea0 caused cros-ec keyboard 
> > events
> > be truncated on many chromebooks so that Left and Right keys on Column 12 
> > were
> > always 0. This commit fixes the issue by restoring the old semantics when 
> > the
> > protocol version is 0.
>
> OK for me, can someone confirms it fixes the issue ??

Both this patch and the updated version fixes the same issue for me on
rk3399-gru-kevin.

/Emil

> Thanks,
> Neil
>
> > ---
> >  drivers/platform/chrome/cros_ec_proto.c | 8 +++-
> >  1 file changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/platform/chrome/cros_ec_proto.c 
> > b/drivers/platform/chrome/cros_ec_proto.c
> > index 398393ab5df8..457e4940dba4 100644
> > --- a/drivers/platform/chrome/cros_ec_proto.c
> > +++ b/drivers/platform/chrome/cros_ec_proto.c
> > @@ -519,8 +519,14 @@ static int get_next_event_xfer(struct cros_ec_device 
> > *ec_dev,
> >
> >   ret = cros_ec_cmd_xfer(ec_dev, msg);
> >   if (ret > 0) {
> > + unsigned int copy_size;
> > +
> >   ec_dev->event_size = ret - 1;
> > - memcpy(&ec_dev->event_data, msg->data, ec_dev->event_size);
> > + if (!version)
> > + copy_size = sizeof(struct ec_response_get_next_event);
> > + else
> > + copy_size = ec_dev->event_size;
> > + memcpy(&ec_dev->event_data, msg->data, copy_size);
> >   }
> >
> >   return ret;
> >
>


Re: [PATCH 2/3] Documentation: bindings: add usb3-host-disable and usb3-host-port for Rockchip USB Type-C PHY

2018-02-13 Thread Emil Renner Berthing
On 12 February 2018 at 23:29, Rob Herring  wrote:
> On Mon, Feb 12, 2018 at 3:26 PM, Brian Norris  
> wrote:
>> Hi,
>>
>> On Mon, Feb 12, 2018 at 10:43:41AM -0600, Rob Herring wrote:
>>> On Thu, Feb 8, 2018 at 3:23 PM, Enric Balletbo Serra
>>>  wrote:
>>> > 2018-02-08 18:52 GMT+01:00 Rob Herring :
>>> >> On Thu, Feb 8, 2018 at 9:20 AM, Enric Balletbo i Serra
>>> >>  wrote:
>>> >>> --- a/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>>> >>> +++ b/Documentation/devicetree/bindings/phy/phy-rockchip-typec.txt
>>> >>> @@ -36,6 +36,12 @@ offset, enable bit, write mask bit.
>>> >>>   - rockchip,uphy-dp-sel : the register of type-c phy enable DP function
>>> >>> for type-c phy0, it must be <0x6268 19 19>;
>>> >>> for type-c phy1, it must be <0x6268 3 19>;
>>> >>> + - rockchip,usb3-host-disable : the register of type-c phy disable 
>>> >>> usb3 host
>>> >>> +   for type-c phy0, it must be <0x2434 0 16>;
>>> >>> +   for type-c phy1, it must be <0x2444 0 16>;
>>> >>> + - rockchip,usb3-host-port : the register of type-c phy usb3 port 
>>> >>> number
>>> >>> +   for type-c phy0, it must be <0x2434 12 28>;
>>> >>> +   for type-c phy1, it must be <0x2444 12 28>;
>>> >>
>>> >> When does this list stop? Adding properties for various register
>>> >> fields doesn't scale. This information should be in the driver and
>>> >> based on the compatible string if necessary.
>>> >>
>>> >
>>> > I see, seams reasonable to me, is this applicable to the new ones only
>>> > or I should get rid of all the proprieties like this from the DT
>>> > (including the old ones)?
>>>
>>> We're already kind of stuck with the existing ones. So it depends if
>>> people want to phase them out or not.
>>
>> FWIW, any Chrome{device} using these sort of bindings is perfectly
>> capable of handling changed bindings (we ship DTBs with the kernel). But
>> that's not typically how mainline covers binding deprecation.
>
> If it's CrOS only that's using these, then it's really up to you all.
> I guess it depends if many folks are trying to run mainline on CrOS
> devices and don't necessarily keep things in sync.

For what it's worth I run mainline on my Chromebook Plus (rk3399-gru-kevin),
but in order to have a somewhat working setup you need to run
4.16-rc1 + various patches from the rockchip mailing list which means
you have to keep up with the latest mainline (both kernel and devicetree)
anyway. So I'm all in favour of cleaning up the devicetree.

>> If we're going to start recommending not putting these offsets in the
>> DT, I'd vote for deprecating them, for consistency. (Otherwise, we'll
>> keep running into this same question.) We only documented the RK3399
>> ("rockchip,rk3399-typec-phy") binding, so all users should have the same
>> offsets. I dunno if/how we pick a time for eventually removing the
>> bindings entirely.
>
> Yes, makes sense.
>
> Rob
>
> ___
> Linux-rockchip mailing list
> linux-rockc...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-rockchip


  1   2   >