[PATCH V1 03/26] spi: tegra114: fix for unpacked mode transfers

2019-03-26 Thread Sowjanya Komatineni
Fixes: computation of actual bytes to fill/receive in/from FIFO in unpacked
mode when transfer length is not a multiple of requested bits per word.

unpacked mode transfers fails when the transfer includes partial bytes in
the last word.

Total words to be written/read to/from FIFO is computed based on transfer
length and bits per word. Unpacked mode includes 0 padding bytes for partial
words to align with bits per word and these extra bytes are also accounted
for calculating bytes left to transfer in the current driver.

This causes extra bytes access of tx/rx buffers along with buffer index
position crossing actual length where remain_len becomes negative and due to
unsigned type, negative value is a 32 bit representation of signed value
and transferred bytes never meets the actual transfer length resulting in
transfer timeout and a hang.

This patch fixes this with proper computation of the actual bytes to fill in
FIFO during transmit and the actual bytes to read from FIFO during receive
ignoring 0 padded bytes.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 43 ---
 1 file changed, 36 insertions(+), 7 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 82431115b7c0..fdba302eb3b6 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -307,10 +307,16 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
x |= (u32)(*tx_buf++) << (i * 8);
tegra_spi_writel(tspi, x, SPI_TX_FIFO);
}
+
+   tspi->cur_tx_pos += written_words * tspi->bytes_per_word;
} else {
+   unsigned int write_bytes;
max_n_32bit = min(tspi->curr_dma_words,  tx_empty_count);
written_words = max_n_32bit;
nbytes = written_words * tspi->bytes_per_word;
+   if (nbytes > t->len - tspi->cur_pos)
+   nbytes = t->len - tspi->cur_pos;
+   write_bytes = nbytes;
for (count = 0; count < max_n_32bit; count++) {
u32 x = 0;
 
@@ -319,8 +325,10 @@ static unsigned tegra_spi_fill_tx_fifo_from_client_txbuf(
x |= (u32)(*tx_buf++) << (i * 8);
tegra_spi_writel(tspi, x, SPI_TX_FIFO);
}
+
+   tspi->cur_tx_pos += write_bytes;
}
-   tspi->cur_tx_pos += written_words * tspi->bytes_per_word;
+
return written_words;
 }
 
@@ -344,20 +352,27 @@ static unsigned int 
tegra_spi_read_rx_fifo_to_client_rxbuf(
for (i = 0; len && (i < 4); i++, len--)
*rx_buf++ = (x >> i*8) & 0xFF;
}
-   tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
read_words += tspi->curr_dma_words;
+   tspi->cur_rx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
} else {
u32 rx_mask = ((u32)1 << t->bits_per_word) - 1;
+   u8 bytes_per_word = tspi->bytes_per_word;
+   unsigned int read_bytes;
 
+   len = rx_full_count * bytes_per_word;
+   if (len > t->len - tspi->cur_pos)
+   len = t->len - tspi->cur_pos;
+   read_bytes = len;
for (count = 0; count < rx_full_count; count++) {
u32 x = tegra_spi_readl(tspi, SPI_RX_FIFO) & rx_mask;
 
-   for (i = 0; (i < tspi->bytes_per_word); i++)
+   for (i = 0; len && (i < bytes_per_word); i++, len--)
*rx_buf++ = (x >> (i*8)) & 0xFF;
}
-   tspi->cur_rx_pos += rx_full_count * tspi->bytes_per_word;
read_words += rx_full_count;
+   tspi->cur_rx_pos += read_bytes;
}
+
return read_words;
 }
 
@@ -372,12 +387,17 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
unsigned len = tspi->curr_dma_words * tspi->bytes_per_word;
 
memcpy(tspi->tx_dma_buf, t->tx_buf + tspi->cur_pos, len);
+   tspi->cur_tx_pos += tspi->curr_dma_words * tspi->bytes_per_word;
} else {
unsigned int i;
unsigned int count;
u8 *tx_buf = (u8 *)t->tx_buf + tspi->cur_tx_pos;
unsigned consume = tspi->curr_dma_words * tspi->bytes_per_word;
+   unsigned int write_bytes;
 
+   if (consume > t->len - tspi->cur_pos)
+   consume = t->len - tspi->cur_pos;
+   write_bytes = consume;
for (count = 0; count < tspi->curr_dma_words; count++) {
u32 x = 0;
 
@@ -386,8 +406,9 @@ static void tegra_spi_copy_client_txbuf_to_spi_txbuf(
x |= (u32)(*tx_buf++) << (i * 8);
tspi->tx_dma_buf[count] = x;

[PATCH V1 11/26] spi: tegra114: reset controller on probe

2019-03-26 Thread Sowjanya Komatineni
Fixes: SPI driver can be built as module so perform SPI controller reset
on probe to make sure it is in valid state before initiating transfer.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 32 ++--
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 5523936b21f5..0e228f1e910e 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -1157,27 +1157,19 @@ static int tegra_spi_probe(struct platform_device *pdev)
 
spi_irq = platform_get_irq(pdev, 0);
tspi->irq = spi_irq;
-   ret = request_threaded_irq(tspi->irq, tegra_spi_isr,
-   tegra_spi_isr_thread, IRQF_ONESHOT,
-   dev_name(>dev), tspi);
-   if (ret < 0) {
-   dev_err(>dev, "Failed to register ISR for IRQ %d\n",
-   tspi->irq);
-   goto exit_free_master;
-   }
 
tspi->clk = devm_clk_get(>dev, "spi");
if (IS_ERR(tspi->clk)) {
dev_err(>dev, "can not get clock\n");
ret = PTR_ERR(tspi->clk);
-   goto exit_free_irq;
+   goto exit_free_master;
}
 
tspi->rst = devm_reset_control_get_exclusive(>dev, "spi");
if (IS_ERR(tspi->rst)) {
dev_err(>dev, "can not get reset\n");
ret = PTR_ERR(tspi->rst);
-   goto exit_free_irq;
+   goto exit_free_master;
}
 
tspi->max_buf_size = SPI_FIFO_DEPTH << 2;
@@ -1185,7 +1177,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
 
ret = tegra_spi_init_dma_param(tspi, true);
if (ret < 0)
-   goto exit_free_irq;
+   goto exit_free_master;
ret = tegra_spi_init_dma_param(tspi, false);
if (ret < 0)
goto exit_rx_dma_free;
@@ -1207,18 +1199,32 @@ static int tegra_spi_probe(struct platform_device *pdev)
dev_err(>dev, "pm runtime get failed, e = %d\n", ret);
goto exit_pm_disable;
}
+
+   reset_control_assert(tspi->rst);
+   udelay(2);
+   reset_control_deassert(tspi->rst);
tspi->def_command1_reg  = SPI_M_S;
tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
pm_runtime_put(>dev);
+   ret = request_threaded_irq(tspi->irq, tegra_spi_isr,
+  tegra_spi_isr_thread, IRQF_ONESHOT,
+  dev_name(>dev), tspi);
+   if (ret < 0) {
+   dev_err(>dev, "Failed to register ISR for IRQ %d\n",
+   tspi->irq);
+   goto exit_pm_disable;
+   }
 
master->dev.of_node = pdev->dev.of_node;
ret = devm_spi_register_master(>dev, master);
if (ret < 0) {
dev_err(>dev, "can not register to master err %d\n", ret);
-   goto exit_pm_disable;
+   goto exit_free_irq;
}
return ret;
 
+exit_free_irq:
+   free_irq(spi_irq, tspi);
 exit_pm_disable:
pm_runtime_disable(>dev);
if (!pm_runtime_status_suspended(>dev))
@@ -1226,8 +1232,6 @@ static int tegra_spi_probe(struct platform_device *pdev)
tegra_spi_deinit_dma_param(tspi, false);
 exit_rx_dma_free:
tegra_spi_deinit_dma_param(tspi, true);
-exit_free_irq:
-   free_irq(spi_irq, tspi);
 exit_free_master:
spi_master_put(master);
return ret;
-- 
2.7.4



[PATCH V1 06/26] spi: tegra114: terminate dma and reset on transfer timeout

2019-03-26 Thread Sowjanya Komatineni
Fixes: terminate DMA and perform controller reset on transfer timeout
to clear the FIFO's and errors.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 716587b663a3..0d20fc489134 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -871,7 +871,16 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
if (WARN_ON(ret == 0)) {
dev_err(tspi->dev,
"spi transfer timeout, err %d\n", ret);
+   if (tspi->is_curr_dma_xfer &&
+   (tspi->cur_direction & DATA_DIR_TX))
+   dmaengine_terminate_all(tspi->tx_dma_chan);
+   if (tspi->is_curr_dma_xfer &&
+   (tspi->cur_direction & DATA_DIR_RX))
+   dmaengine_terminate_all(tspi->rx_dma_chan);
ret = -EIO;
+   reset_control_assert(tspi->rst);
+   udelay(2);
+   reset_control_deassert(tspi->rst);
goto complete_xfer;
}
 
-- 
2.7.4



[PATCH V1 10/26] spi: tegra114: avoid reset call in atomic context

2019-03-26 Thread Sowjanya Komatineni
Fixes: move SPI controller reset out of spin lock.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 268a790a663e..5523936b21f5 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -976,11 +976,12 @@ static irqreturn_t handle_cpu_based_xfer(struct 
tegra_spi_data *tspi)
tspi->command1_reg, tspi->dma_control_reg);
tegra_spi_dump_regs(tspi);
tegra_spi_flush_fifos(tspi);
+   complete(>xfer_completion);
+   spin_unlock_irqrestore(>lock, flags);
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
-   complete(>xfer_completion);
-   goto exit;
+   return IRQ_HANDLED;
}
 
if (tspi->cur_direction & DATA_DIR_RX)
@@ -1050,11 +1051,11 @@ static irqreturn_t handle_dma_based_xfer(struct 
tegra_spi_data *tspi)
tspi->command1_reg, tspi->dma_control_reg);
tegra_spi_dump_regs(tspi);
tegra_spi_flush_fifos(tspi);
+   complete(>xfer_completion);
+   spin_unlock_irqrestore(>lock, flags);
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
-   complete(>xfer_completion);
-   spin_unlock_irqrestore(>lock, flags);
return IRQ_HANDLED;
}
 
-- 
2.7.4



[PATCH V1 05/26] spi: tegra114: use unpacked mode for below 4 byte transfers

2019-03-26 Thread Sowjanya Komatineni
Fixes: use unpacked mode when transfer length is less than 4 bytes.

Packed mode expects minimum transfer length of 4 bytes.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index dc63536dbda4..716587b663a3 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -259,7 +259,8 @@ static unsigned tegra_spi_calculate_curr_xfer_param(
 
tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8);
 
-   if (bits_per_word == 8 || bits_per_word == 16 || bits_per_word == 32) {
+   if ((bits_per_word == 8 || bits_per_word == 16 ||
+bits_per_word == 32) && t->len > 3) {
tspi->is_packed = 1;
tspi->words_per_32bit = 32/bits_per_word;
} else {
-- 
2.7.4



[PATCH V1 09/26] spi: tegra114: dump SPI registers during timeout

2019-03-26 Thread Sowjanya Komatineni
This patch dumps SPI registers on DMA or transfer timeout for debug
purpose.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index b7e71676a506..268a790a663e 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -858,6 +858,20 @@ static void tegra_spi_transfer_delay(int delay)
udelay(delay % 1000);
 }
 
+static void tegra_spi_dump_regs(struct tegra_spi_data *tspi)
+{
+   dev_dbg(tspi->dev, " SPI REGISTER DUMP \n");
+   dev_dbg(tspi->dev, "Command1:0x%08x | Command2:0x%08x\n",
+   tegra_spi_readl(tspi, SPI_COMMAND1),
+   tegra_spi_readl(tspi, SPI_COMMAND2));
+   dev_dbg(tspi->dev, "DMA_CTL: 0x%08x | DMA_BLK: 0x%08x\n",
+   tegra_spi_readl(tspi, SPI_DMA_CTL),
+   tegra_spi_readl(tspi, SPI_DMA_BLK));
+   dev_dbg(tspi->dev, "TRANS_STAT:  0x%08x | FIFO_STATUS: 0x%08x\n",
+   tegra_spi_readl(tspi, SPI_TRANS_STATUS),
+   tegra_spi_readl(tspi, SPI_FIFO_STATUS));
+}
+
 static int tegra_spi_transfer_one_message(struct spi_master *master,
struct spi_message *msg)
 {
@@ -904,6 +918,7 @@ static int tegra_spi_transfer_one_message(struct spi_master 
*master,
(tspi->cur_direction & DATA_DIR_RX))
dmaengine_terminate_all(tspi->rx_dma_chan);
ret = -EIO;
+   tegra_spi_dump_regs(tspi);
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
@@ -913,6 +928,7 @@ static int tegra_spi_transfer_one_message(struct spi_master 
*master,
 
if (tspi->tx_status ||  tspi->rx_status) {
dev_err(tspi->dev, "Error in Transfer\n");
+   tegra_spi_dump_regs(tspi);
ret = -EIO;
goto complete_xfer;
}
@@ -958,6 +974,7 @@ static irqreturn_t handle_cpu_based_xfer(struct 
tegra_spi_data *tspi)
tspi->status_reg);
dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg);
+   tegra_spi_dump_regs(tspi);
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
@@ -1031,6 +1048,7 @@ static irqreturn_t handle_dma_based_xfer(struct 
tegra_spi_data *tspi)
tspi->status_reg);
dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg);
+   tegra_spi_dump_regs(tspi);
tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
-- 
2.7.4



[PATCH V1 12/26] spi: tegra114: add SPI_LSB_FIRST support

2019-03-26 Thread Sowjanya Komatineni
Tegra SPI controller supports lsb first mode. Default is MSB bit first
and on selection of SPI_LSB_FIRST through SPI mode transmission happens
with LSB bit first.

This patch adds SPI_LSB_FIRST flag to mode_bits and also configures it
on request.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 0e228f1e910e..d39f7b05b824 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -750,6 +750,11 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device 
*spi,
else if (req_mode == SPI_MODE_3)
command1 |= SPI_CONTROL_MODE_3;
 
+   if (spi->mode & SPI_LSB_FIRST)
+   command1 |= SPI_LSBIT_FE;
+   else
+   command1 &= ~SPI_LSBIT_FE;
+
if (tspi->cs_control) {
if (tspi->cs_control != spi)
tegra_spi_writel(tspi, command1, SPI_COMMAND1);
@@ -1137,7 +1142,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
master->max_speed_hz = 2500; /* 25MHz */
 
/* the spi->mode bits understood by this driver: */
-   master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+   master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
master->setup = tegra_spi_setup;
master->transfer_one_message = tegra_spi_transfer_one_message;
master->num_chipselect = MAX_CHIP_SELECT;
-- 
2.7.4



[PATCH V1 17/26] spi: tegra114: add support for interrupt mask

2019-03-26 Thread Sowjanya Komatineni
This patch creates tegra_spi_soc_data structure to maintain and implement
SPI HW feature differences between different Tegra chips and also creates
a separate compatible string for T124/T210/T186.

Tegra210 and later has a separate interrupt mask register SPI_INTR_MASK
for enabling or disabling interrupts while Tegra124 and prior uses
interrupt enable bits in SPI_DMA_CTL register.

This patch creates flag has_intr_mask_reg in tegra_spi_soc_data to
identify this and implements accordingly.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 53 +-
 1 file changed, 48 insertions(+), 5 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 9b9d4b9e1f3e..68fee474580b 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -149,6 +149,8 @@
 
 #define SPI_TX_FIFO0x108
 #define SPI_RX_FIFO0x188
+#define SPI_INTR_MASK  0x18c
+#define SPI_INTR_ALL_MASK  (0x1fUL << 25)
 #define MAX_CHIP_SELECT4
 #define SPI_FIFO_DEPTH 64
 #define DATA_DIR_TX(1 << 0)
@@ -161,6 +163,10 @@
 #define MAX_HOLD_CYCLES16
 #define SPI_DEFAULT_SPEED  2500
 
+struct tegra_spi_soc_data {
+   bool has_intr_mask_reg;
+};
+
 struct tegra_spi_data {
struct device   *dev;
struct spi_master   *master;
@@ -211,6 +217,7 @@ struct tegra_spi_data {
u32 *tx_dma_buf;
dma_addr_t  tx_dma_phys;
struct dma_async_tx_descriptor  *tx_dma_desc;
+   const struct tegra_spi_soc_data *soc_data;
 };
 
 static int tegra_spi_runtime_suspend(struct device *dev);
@@ -554,11 +561,13 @@ static int tegra_spi_start_dma_based_transfer(
dma_burst = 8;
}
 
-   if (tspi->cur_direction & DATA_DIR_TX)
-   val |= SPI_IE_TX;
+   if (!tspi->soc_data->has_intr_mask_reg) {
+   if (tspi->cur_direction & DATA_DIR_TX)
+   val |= SPI_IE_TX;
 
-   if (tspi->cur_direction & DATA_DIR_RX)
-   val |= SPI_IE_RX;
+   if (tspi->cur_direction & DATA_DIR_RX)
+   val |= SPI_IE_RX;
+   }
 
tegra_spi_writel(tspi, val, SPI_DMA_CTL);
tspi->dma_control_reg = val;
@@ -848,6 +857,12 @@ static int tegra_spi_setup(struct spi_device *spi)
return ret;
}
 
+   if (tspi->soc_data->has_intr_mask_reg) {
+   val = tegra_spi_readl(tspi, SPI_INTR_MASK);
+   val &= ~SPI_INTR_ALL_MASK;
+   tegra_spi_writel(tspi, val, SPI_INTR_MASK);
+   }
+
spin_lock_irqsave(>lock, flags);
val = tspi->def_command1_reg;
if (spi->mode & SPI_CS_HIGH)
@@ -1126,8 +1141,29 @@ static irqreturn_t tegra_spi_isr(int irq, void 
*context_data)
return IRQ_WAKE_THREAD;
 }
 
+static struct tegra_spi_soc_data tegra114_spi_soc_data = {
+   .has_intr_mask_reg = false,
+};
+
+static struct tegra_spi_soc_data tegra124_spi_soc_data = {
+   .has_intr_mask_reg = false,
+};
+
+static struct tegra_spi_soc_data tegra210_spi_soc_data = {
+   .has_intr_mask_reg = true,
+};
+
 static const struct of_device_id tegra_spi_of_match[] = {
-   { .compatible = "nvidia,tegra114-spi", },
+   {
+   .compatible = "nvidia,tegra114-spi",
+   .data   = _spi_soc_data,
+   }, {
+   .compatible = "nvidia,tegra124-spi",
+   .data   = _spi_soc_data,
+   }, {
+   .compatible = "nvidia,tegra210-spi",
+   .data   = _spi_soc_data,
+   },
{}
 };
 MODULE_DEVICE_TABLE(of, tegra_spi_of_match);
@@ -1168,6 +1204,13 @@ static int tegra_spi_probe(struct platform_device *pdev)
tspi->dev = >dev;
spin_lock_init(>lock);
 
+   tspi->soc_data = of_device_get_match_data(>dev);
+   if (!tspi->soc_data) {
+   dev_err(>dev, "unsupported tegra\n");
+   ret = -ENODEV;
+   goto exit_free_master;
+   }
+
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
tspi->base = devm_ioremap_resource(>dev, r);
if (IS_ERR(tspi->base)) {
-- 
2.7.4



[PATCH V1 14/26] spi: tegra114: add 3 wire transfer mode support

2019-03-26 Thread Sowjanya Komatineni
This patch adds 3 wire transfer support to SPI mode list and also
implements it.

3 wire or Bi-directional mode uses only one serial data pin for
the transfer. SPI in master mode uses MOSI data line only and MISO
data line is not used by the SPI.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 335c594d5b74..01efb615a196 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -755,6 +755,11 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device 
*spi,
else
command1 &= ~SPI_LSBIT_FE;
 
+   if (spi->mode & SPI_3WIRE)
+   command1 |= SPI_BIDIROE;
+   else
+   command1 &= ~SPI_BIDIROE;
+
if (tspi->cs_control) {
if (tspi->cs_control != spi)
tegra_spi_writel(tspi, command1, SPI_COMMAND1);
@@ -1148,7 +1153,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
 
/* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
-   SPI_TX_DUAL | SPI_RX_DUAL;
+   SPI_TX_DUAL | SPI_RX_DUAL | SPI_3WIRE;
master->setup = tegra_spi_setup;
master->transfer_one_message = tegra_spi_transfer_one_message;
master->num_chipselect = MAX_CHIP_SELECT;
-- 
2.7.4



[PATCH V1 19/26] DT bindings: spi: add spi client device properties

2019-03-26 Thread Sowjanya Komatineni
This patch adds below cs timing properties to allow SPI master configuring
setup, hold and time interval between two SPI transactions to meet specific
SPI client device requirements.
 CS setup time
 CS hold time
 CS inactive delay
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1;
t=1553666253; bh=TbJVgRAIkjok3TkKNkfcvYc4WGyZhOpiH6sUZvadGrQ=;
h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer:
 In-Reply-To:References:X-NVConfidentiality:MIME-Version:
 Content-Type;
b=Tud9guY5XCzkjKA2k2n0+xO/vTfMTNhH1e0viAyYmlgoG/j+uSBAAmOeZucVUlmEa
 rwqxlSm+rkYMUfgSWqmJXqEjgRIAqMhA32FOJmhgpblGwYUR22hnbdhbk4TcqMNsIO
 mXBgiIq3sOB7dKCDIv4+YSUreRrnXrvrDN0NE9zN7D+AQWYLF5dI4v+UDalNYJU2hz
 TusNrURxuHgtpModvYVQRPgPDv+nJ2QE6L7yZH/M6XP7jYprtQHWnHAiMwqqSXBcrf
 8vlhV96anQSaGkioOUTp8ThlHSwBKLRFHRofVlrhT53K0xvTCvVst4aHvA1aq3QPw0
 sVr25yohIPq7w==

Signed-off-by: Sowjanya Komatineni 
---
 Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt 
b/Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt
index 9ba7c5a273b4..6167c5234b64 100644
--- a/Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt
+++ b/Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt
@@ -23,6 +23,13 @@ Required properties:
 Recommended properties:
 - spi-max-frequency: Definition as per
  Documentation/devicetree/bindings/spi/spi-bus.txt
+
+spi-client device controller properties:
+- nvidia,cs-setup-clk-count: CS setup timing parameter.
+- nvidia,cs-hold-clk-count: CS hold timing parameter.
+- nvidia,cs-inactive-cycles: CS inactive delay in terms of clock between
+  transfers.
+
 Example:
 
 spi@7000d600 {
-- 
2.7.4



[PATCH V1 20/26] spi: tegra114: add support for tuning HW CS timing

2019-03-26 Thread Sowjanya Komatineni
Some slaves may need certain CS setup time, hold time, CS inactive
delay between the packets. Tegra SPI controller supports configuring
these CS timing parameters and are applicable when using HW CS.

This patch adds support for configuring these HW CS timing parameters
through device tree properties.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 61 +++---
 1 file changed, 57 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 86c34f02d13a..e01962344bde 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -95,8 +95,10 @@
(reg = (((val) & 0x1) << ((cs) * 8 + 5)) |  \
((reg) & ~(1 << ((cs) * 8 + 5
 #define SPI_SET_CYCLES_BETWEEN_PACKETS(reg, cs, val)   \
-   (reg = (((val) & 0xF) << ((cs) * 8)) |  \
-   ((reg) & ~(0xF << ((cs) * 8
+   (reg = (((val) & 0x1F) << ((cs) * 8)) | \
+   ((reg) & ~(0x1F << ((cs) * 8
+#define MAX_SETUP_HOLD_CYCLES  16
+#define MAX_INACTIVE_CYCLES32
 
 #define SPI_TRANS_STATUS   0x010
 #define SPI_BLK_CNT(val)   (((val) >> 0) & 0x)
@@ -169,6 +171,9 @@ struct tegra_spi_soc_data {
 
 struct tegra_spi_client_data {
bool is_hw_based_cs;
+   int cs_setup_clk_count;
+   int cs_hold_clk_count;
+   int cs_inactive_cycles;
 };
 
 struct tegra_spi_data {
@@ -210,6 +215,8 @@ struct tegra_spi_data {
u32 command1_reg;
u32 dma_control_reg;
u32 def_command1_reg;
+   u32 spi_cs_timing1;
+   u32 spi_cs_timing2;
 
struct completion   xfer_completion;
struct spi_transfer *curr_xfer;
@@ -727,6 +734,43 @@ static void tegra_spi_deinit_dma_param(struct 
tegra_spi_data *tspi,
dma_release_channel(dma_chan);
 }
 
+static void tegra_spi_set_hw_cs_timing(struct spi_device *spi)
+{
+   struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
+   struct tegra_spi_client_data *cdata = spi->controller_data;
+   u32 setup_dly;
+   u32 hold_dly;
+   u32 setup_hold;
+   u32 spi_cs_timing;
+   u32 inactive_cycles;
+   u8 cs_state;
+
+   setup_dly = min(cdata->cs_setup_clk_count, MAX_SETUP_HOLD_CYCLES);
+   hold_dly = min(cdata->cs_hold_clk_count, MAX_SETUP_HOLD_CYCLES);
+   setup_hold = SPI_SETUP_HOLD(setup_dly - 1, hold_dly - 1);
+   spi_cs_timing = SPI_CS_SETUP_HOLD(tspi->spi_cs_timing1,
+ spi->chip_select,
+ setup_hold);
+   if (tspi->spi_cs_timing1 != spi_cs_timing) {
+   tspi->spi_cs_timing1 = spi_cs_timing;
+   tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING1);
+   }
+
+   spi_cs_timing = tspi->spi_cs_timing2;
+   inactive_cycles = min(cdata->cs_inactive_cycles, MAX_INACTIVE_CYCLES);
+   if (inactive_cycles)
+   inactive_cycles--;
+   cs_state = inactive_cycles ? 0 : 1;
+   SPI_SET_CS_ACTIVE_BETWEEN_PACKETS(spi_cs_timing, spi->chip_select,
+ cs_state);
+   SPI_SET_CYCLES_BETWEEN_PACKETS(spi_cs_timing, spi->chip_select,
+  inactive_cycles);
+   if (tspi->spi_cs_timing2 != spi_cs_timing) {
+   tspi->spi_cs_timing2 = spi_cs_timing;
+   tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING2);
+   }
+}
+
 static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
struct spi_transfer *t, bool is_first_of_msg,
bool is_single_xfer)
@@ -784,8 +828,10 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device 
*spi,
tegra_spi_writel(tspi, command1, SPI_COMMAND1);
 
tspi->use_hw_based_cs = false;
-   if (cdata && cdata->is_hw_based_cs && is_single_xfer)
+   if (cdata && cdata->is_hw_based_cs && is_single_xfer) {
tspi->use_hw_based_cs = true;
+   tegra_spi_set_hw_cs_timing(spi);
+   }
 
if (!tspi->use_hw_based_cs) {
command1 |= SPI_CS_SW_HW;
@@ -871,7 +917,12 @@ static struct tegra_spi_client_data
 
if (of_property_read_bool(slave_np, "nvidia,enable-hw-based-cs"))
cdata->is_hw_based_cs = true;
-
+   of_property_read_u32(slave_np, "nvidia,cs-setup-clk-count",
+>cs_setup_clk_count);
+   of_property_read_u32(slave_np, "nvidia,cs-hold-clk-count",
+>cs_hold_clk_count);
+   

[PATCH V1 21/26] DT bindings: spi: add tx/rx clock delay SPI client properties

2019-03-26 Thread Sowjanya Komatineni
This patch adds Tegra SPI master tx and rx clock delay properties.

TX/RX clock delays may vary depending on the platform design trace lengths
for each client on the Tegra SPI bus. These properties helps to tune the
clock delays.

Signed-off-by: Sowjanya Komatineni 
---
 .../devicetree/bindings/spi/nvidia,tegra114-spi.txt  | 16 
 1 file changed, 16 insertions(+)

diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt 
b/Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt
index 6167c5234b64..2b84b7b726ce 100644
--- a/Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt
+++ b/Documentation/devicetree/bindings/spi/nvidia,tegra114-spi.txt
@@ -29,6 +29,12 @@ spi-client device controller properties:
 - nvidia,cs-hold-clk-count: CS hold timing parameter.
 - nvidia,cs-inactive-cycles: CS inactive delay in terms of clock between
   transfers.
+- nvidia,tx-clk-tap-delay: Delays the clock going out to the external device
+  with this tap value. This property is used to tune the outgoing data from
+  Tegra SPI master with respect to outgoing Tegra SPI master clock.
+- nvidia,rx-clk-tap-delay: Delays the clock coming in from the external device
+  with this tap value. This property is used to adjust the Tegra SPI master
+  clock with respect to the data from the SPI slave device.
 
 Example:
 
@@ -45,4 +51,14 @@ spi@7000d600 {
reset-names = "spi";
dmas = < 16>, < 16>;
dma-names = "rx", "tx";
+
+   @ {
+   ...
+   ...
+   nvidia,cs-setup-clk-count = <10>;
+   nvidia,cs-hold-clk-count = <10>;
+   nvidia,rx-clk-tap-delay = <0>;
+   nvidia,tx-clk-tap-delay = <16>;
+   ...
+   };
 };
-- 
2.7.4



[PATCH V1 23/26] spi: tegra114: add support for gpio based cs

2019-03-26 Thread Sowjanya Komatineni
This patch adds supports for chip select control using GPIO if valid
CS gpio exists rather than controlling from the SPI controller.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 57 ++
 1 file changed, 57 insertions(+)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 725d60364ec6..9b216e9d6079 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -178,6 +179,10 @@ struct tegra_spi_client_data {
int rx_clk_tap_delay;
 };
 
+struct tegra_spi_client_state {
+   bool cs_gpio_valid;
+};
+
 struct tegra_spi_data {
struct device   *dev;
struct spi_master   *master;
@@ -781,6 +786,7 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device 
*spi,
 {
struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
struct tegra_spi_client_data *cdata = spi->controller_data;
+   struct tegra_spi_client_state *cstate = spi->controller_state;
u32 speed = t->speed_hz;
u8 bits_per_word = t->bits_per_word;
u32 command1;
@@ -849,6 +855,12 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device 
*spi,
command1 &= ~(SPI_CS_SW_HW | SPI_CS_SW_VAL);
}
 
+   if (cstate->cs_gpio_valid) {
+   int val = (spi->mode & SPI_CS_HIGH) ? 1 : 0;
+
+   gpio_set_value(spi->cs_gpio, val);
+   }
+
if (tspi->last_used_cs != spi->chip_select) {
if (cdata && cdata->tx_clk_tap_delay)
tx_tap = cdata->tx_clk_tap_delay;
@@ -950,7 +962,12 @@ static struct tegra_spi_client_data
 static void tegra_spi_cleanup(struct spi_device *spi)
 {
struct tegra_spi_client_data *cdata = spi->controller_data;
+   struct tegra_spi_client_state *cstate = spi->controller_state;
 
+   spi->controller_state = NULL;
+   if (cstate && cstate->cs_gpio_valid)
+   gpio_free(spi->cs_gpio);
+   kfree(cstate);
spi->controller_data = NULL;
if (spi->dev.of_node)
kfree(cdata);
@@ -960,6 +977,7 @@ static int tegra_spi_setup(struct spi_device *spi)
 {
struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
struct tegra_spi_client_data *cdata = spi->controller_data;
+   struct tegra_spi_client_state *cstate = spi->controller_state;
u32 val;
unsigned long flags;
int ret;
@@ -970,11 +988,41 @@ static int tegra_spi_setup(struct spi_device *spi)
spi->mode & SPI_CPHA ? "" : "~",
spi->max_speed_hz);
 
+   if (!cstate) {
+   cstate = kzalloc(sizeof(*cstate), GFP_KERNEL);
+   if (!cstate)
+   return -ENOMEM;
+   spi->controller_state = cstate;
+   }
+
if (!cdata) {
cdata = tegra_spi_parse_cdata_dt(spi);
spi->controller_data = cdata;
}
 
+   if (spi->master->cs_gpios && gpio_is_valid(spi->cs_gpio)) {
+   if (!cstate->cs_gpio_valid) {
+   int gpio_flag = GPIOF_OUT_INIT_HIGH;
+
+   if (spi->mode & SPI_CS_HIGH)
+   gpio_flag = GPIOF_OUT_INIT_LOW;
+
+   ret = gpio_request_one(spi->cs_gpio, gpio_flag,
+  "cs_gpio");
+   if (ret < 0) {
+   dev_err(>dev,
+   "GPIO request failed: %d\n", ret);
+   tegra_spi_cleanup(spi);
+   return ret;
+   }
+   cstate->cs_gpio_valid = true;
+   } else {
+   int val = (spi->mode & SPI_CS_HIGH) ? 0 : 1;
+
+   gpio_set_value(spi->cs_gpio, val);
+   }
+   }
+
ret = pm_runtime_get_sync(tspi->dev);
if (ret < 0) {
dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
@@ -1034,9 +1082,11 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
struct tegra_spi_data *tspi = spi_master_get_devdata(master);
struct spi_transfer *xfer;
struct spi_device *spi = msg->spi;
+   struct tegra_spi_client_state *cstate = spi->controller_state;
int single_xfer;
int ret;
bool skip = false;
+   int cs_val;
 
msg->status = 0;
msg->actual_length = 0;
@@ -1093,7 +1143,10 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
msg->actual_length += xfer->len;
 
 complete_xfer:
+   cs_val = (spi->mode & SPI_CS_HIGH) ? 0 : 1;
if (ret < 0 || skip) {
+ 

[PATCH V1 26/26] spi: tegra114: add support for LSBYTE_FIRST

2019-03-26 Thread Sowjanya Komatineni
Some SPI devices expects SPI transfers to be in Least significant byte
first order and some devices expect Most significant byte first order.

This patch adds SPI_LSBYTE_FIRST to supported mode list and implements
configuration accordingly.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index e1669ab3b0fe..a2e809af96da 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -827,6 +827,11 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device 
*spi,
else
command1 &= ~SPI_LSBIT_FE;
 
+   if (spi->mode & SPI_LSBYTE_FIRST)
+   command1 |= SPI_LSBYTE_FE;
+   else
+   command1 &= ~SPI_LSBYTE_FE;
+
if (spi->mode & SPI_3WIRE)
command1 |= SPI_BIDIROE;
else
@@ -1393,7 +1398,8 @@ static int tegra_spi_probe(struct platform_device *pdev)
 
/* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
-   SPI_TX_DUAL | SPI_RX_DUAL | SPI_3WIRE;
+   SPI_TX_DUAL | SPI_RX_DUAL | SPI_3WIRE |
+   SPI_LSBYTE_FIRST;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->setup = tegra_spi_setup;
master->cleanup = tegra_spi_cleanup;
-- 
2.7.4



[PATCH V1 24/26] spi: tegra114: de-assert CS before SPI mode is reset to its default

2019-03-26 Thread Sowjanya Komatineni
With SW CS, during transfer completion CS is de-asserted by writing the
default command1 register value to SPI_COMMAND1 register. With this both
mode and CS state are set at the same time and if current transfer mode
is different to default SPI mode and if mode change happens prior to CS
de-assert, clock polarity can change while CS is active before transfer
finishes.

This causes Slave to see spurious clock edges resulting in data mismatch.

This patch fixes this by de-asserting CS before writing SPI_COMMAND1 to
its default value so through out the transfer it will be in same SPI mode.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 18 ++
 1 file changed, 18 insertions(+)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 9b216e9d6079..e1669ab3b0fe 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -1147,6 +1147,12 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
if (ret < 0 || skip) {
if (cstate->cs_gpio_valid)
gpio_set_value(spi->cs_gpio, cs_val);
+   if (cs_val && !tspi->use_hw_based_cs)
+   tspi->command1_reg |= SPI_CS_SW_VAL;
+   else
+   tspi->command1_reg &= ~SPI_CS_SW_VAL;
+   tegra_spi_writel(tspi, tspi->command1_reg,
+SPI_COMMAND1);
tegra_spi_writel(tspi, tspi->def_command1_reg,
SPI_COMMAND1);
tegra_spi_transfer_delay(xfer->delay_usecs);
@@ -1158,6 +1164,12 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
else {
if (cstate->cs_gpio_valid)
gpio_set_value(spi->cs_gpio, cs_val);
+   if (cs_val && !tspi->use_hw_based_cs)
+   tspi->command1_reg |= SPI_CS_SW_VAL;
+   else
+   tspi->command1_reg &= ~SPI_CS_SW_VAL;
+   tegra_spi_writel(tspi, tspi->command1_reg,
+SPI_COMMAND1);
tegra_spi_writel(tspi, tspi->def_command1_reg,
SPI_COMMAND1);
tegra_spi_transfer_delay(xfer->delay_usecs);
@@ -1165,6 +1177,12 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
} else if (xfer->cs_change) {
if (cstate->cs_gpio_valid)
gpio_set_value(spi->cs_gpio, cs_val);
+   if (cs_val && !tspi->use_hw_based_cs)
+   tspi->command1_reg |= SPI_CS_SW_VAL;
+   else
+   tspi->command1_reg &= ~SPI_CS_SW_VAL;
+   tegra_spi_writel(tspi, tspi->command1_reg,
+SPI_COMMAND1);
tegra_spi_writel(tspi, tspi->def_command1_reg,
SPI_COMMAND1);
tegra_spi_transfer_delay(xfer->delay_usecs);
-- 
2.7.4



[PATCH V1 25/26] spi: expand mode and mode_bits support

2019-03-26 Thread Sowjanya Komatineni
mode and mode_bits is declared as u16 and all bits are used.

This patch changes mode and mode_bits to be u32 to allow for more mode
configurations.

Some SPI Master controllers support configuring Least significant byte
first or Most significant byte first order for transfers. Also some SPI
slave devices expect bytes to be in Least significant first order and
some devices expect Most significant first order.

This patch creates SPI_LSBYTE_FIRST mode for this purpose.

Signed-off-by: Sowjanya Komatineni 
---
 include/linux/spi/spi.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h
index a0975cf76cf6..0032aa47dea0 100644
--- a/include/linux/spi/spi.h
+++ b/include/linux/spi/spi.h
@@ -143,7 +143,7 @@ struct spi_device {
u32 max_speed_hz;
u8  chip_select;
u8  bits_per_word;
-   u16 mode;
+   u32 mode;
 #defineSPI_CPHA0x01/* clock phase */
 #defineSPI_CPOL0x02/* clock polarity */
 #defineSPI_MODE_0  (0|0)   /* (original MicroWire) 
*/
@@ -164,6 +164,7 @@ struct spi_device {
 #defineSPI_TX_OCTAL0x2000  /* transmit with 8 
wires */
 #defineSPI_RX_OCTAL0x4000  /* receive with 8 wires 
*/
 #defineSPI_3WIRE_HIZ   0x8000  /* high impedance 
turnaround */
+#define SPI_LSBYTE_FIRST   0x1 /* per-word bytes-on-wire */
int irq;
void*controller_state;
void*controller_data;
@@ -439,7 +440,7 @@ struct spi_controller {
u16 dma_alignment;
 
/* spi_device.mode flags understood by this controller driver */
-   u16 mode_bits;
+   u32 mode_bits;
 
/* bitmask of supported bits_per_word for transfers */
u32 bits_per_word_mask;
-- 
2.7.4



[PATCH V1 13/26] spi: tegra114: add dual mode support

2019-03-26 Thread Sowjanya Komatineni
This patch adds support for dual mode SPI transfer.

Dual mode uses both MOSI and MISO lines in parallel where the data
is interleaved on MOSI and MISO lines increasing the throughput.

Packet from Tx FIFO is transmitted on both MOSI and MISO lines and
packet to Rx FIFO is received from both MOSI and MISO lines. Even
bits are transmitted or received on the MOSI data line and odd bits
are transmitted or received on the MISO data line.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index d39f7b05b824..335c594d5b74 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -787,6 +787,11 @@ static int tegra_spi_start_transfer_one(struct spi_device 
*spi,
 
total_fifo_words = tegra_spi_calculate_curr_xfer_param(spi, tspi, t);
 
+   if (t->rx_nbits == SPI_NBITS_DUAL || t->tx_nbits == SPI_NBITS_DUAL)
+   command1 |= SPI_BOTH_EN_BIT;
+   else
+   command1 &= ~SPI_BOTH_EN_BIT;
+
if (tspi->is_packed)
command1 |= SPI_PACKED;
else
@@ -1142,7 +1147,8 @@ static int tegra_spi_probe(struct platform_device *pdev)
master->max_speed_hz = 2500; /* 25MHz */
 
/* the spi->mode bits understood by this driver: */
-   master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;
+   master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
+   SPI_TX_DUAL | SPI_RX_DUAL;
master->setup = tegra_spi_setup;
master->transfer_one_message = tegra_spi_transfer_one_message;
master->num_chipselect = MAX_CHIP_SELECT;
-- 
2.7.4



[PATCH V1 18/26] spi: tegra114: add support for hw based cs

2019-03-26 Thread Sowjanya Komatineni
This patch adds support for HW based CS control.

Tegra SPI controller supports both HW and SW based CS control
transfers.

Tegra SPI driver default uses SW CS control for transfers and HW CS
control can be enabled through SPI client device node DT property
nvidia,enable-hw-based-cs and is used only for single transfers.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 71 +-
 1 file changed, 64 insertions(+), 7 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 68fee474580b..86c34f02d13a 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -167,6 +167,10 @@ struct tegra_spi_soc_data {
bool has_intr_mask_reg;
 };
 
+struct tegra_spi_client_data {
+   bool is_hw_based_cs;
+};
+
 struct tegra_spi_data {
struct device   *dev;
struct spi_master   *master;
@@ -193,6 +197,7 @@ struct tegra_spi_data {
unsigneddma_buf_size;
unsignedmax_buf_size;
boolis_curr_dma_xfer;
+   booluse_hw_based_cs;
 
struct completion   rx_dma_complete;
struct completion   tx_dma_complete;
@@ -723,9 +728,11 @@ static void tegra_spi_deinit_dma_param(struct 
tegra_spi_data *tspi,
 }
 
 static u32 tegra_spi_setup_transfer_one(struct spi_device *spi,
-   struct spi_transfer *t, bool is_first_of_msg)
+   struct spi_transfer *t, bool is_first_of_msg,
+   bool is_single_xfer)
 {
struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
+   struct tegra_spi_client_data *cdata = spi->controller_data;
u32 speed = t->speed_hz;
u8 bits_per_word = t->bits_per_word;
u32 command1;
@@ -776,11 +783,19 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device 
*spi,
} else
tegra_spi_writel(tspi, command1, SPI_COMMAND1);
 
-   command1 |= SPI_CS_SW_HW;
-   if (spi->mode & SPI_CS_HIGH)
-   command1 |= SPI_CS_SW_VAL;
-   else
-   command1 &= ~SPI_CS_SW_VAL;
+   tspi->use_hw_based_cs = false;
+   if (cdata && cdata->is_hw_based_cs && is_single_xfer)
+   tspi->use_hw_based_cs = true;
+
+   if (!tspi->use_hw_based_cs) {
+   command1 |= SPI_CS_SW_HW;
+   if (spi->mode & SPI_CS_HIGH)
+   command1 |= SPI_CS_SW_VAL;
+   else
+   command1 &= ~SPI_CS_SW_VAL;
+   } else {
+   command1 &= ~(SPI_CS_SW_HW | SPI_CS_SW_VAL);
+   }
 
tegra_spi_writel(tspi, 0, SPI_COMMAND2);
} else {
@@ -838,9 +853,41 @@ static int tegra_spi_start_transfer_one(struct spi_device 
*spi,
return ret;
 }
 
+static struct tegra_spi_client_data
+   *tegra_spi_parse_cdata_dt(struct spi_device *spi)
+{
+   struct tegra_spi_client_data *cdata;
+   struct device_node *slave_np;
+
+   slave_np = spi->dev.of_node;
+   if (!slave_np) {
+   dev_dbg(>dev, "device node not found\n");
+   return NULL;
+   }
+
+   cdata = kzalloc(sizeof(*cdata), GFP_KERNEL);
+   if (!cdata)
+   return NULL;
+
+   if (of_property_read_bool(slave_np, "nvidia,enable-hw-based-cs"))
+   cdata->is_hw_based_cs = true;
+
+   return cdata;
+}
+
+static void tegra_spi_cleanup(struct spi_device *spi)
+{
+   struct tegra_spi_client_data *cdata = spi->controller_data;
+
+   spi->controller_data = NULL;
+   if (spi->dev.of_node)
+   kfree(cdata);
+}
+
 static int tegra_spi_setup(struct spi_device *spi)
 {
struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master);
+   struct tegra_spi_client_data *cdata = spi->controller_data;
u32 val;
unsigned long flags;
int ret;
@@ -851,9 +898,15 @@ static int tegra_spi_setup(struct spi_device *spi)
spi->mode & SPI_CPHA ? "" : "~",
spi->max_speed_hz);
 
+   if (!cdata) {
+   cdata = tegra_spi_parse_cdata_dt(spi);
+   spi->controller_data = cdata;
+   }
+
ret = pm_runtime_get_sync(tspi->dev);
if (ret < 0) {
dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret);
+   tegra_spi_cleanup(spi);
return ret;
}
 
@@ -909,18 +962,21 @@ static int tegra_spi_transfer_one_message(struct 
spi_master *master,
struct tegra_spi_data *tspi = spi_master_get_devdata(master);
struct spi_transfer *xfer;
struct spi_device *spi = msg->spi;
+   int single_xfer;

[PATCH V1 15/26] spi: tegra114: set supported bits_per_word

2019-03-26 Thread Sowjanya Komatineni
Tegra SPI supports 4 through 32 bits per word.

This patch sets bits_per_word_mask accordingly to support transfer
with these bits per word.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 01efb615a196..94acef0f5ea5 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -1154,6 +1154,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
/* the spi->mode bits understood by this driver: */
master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST |
SPI_TX_DUAL | SPI_RX_DUAL | SPI_3WIRE;
+   master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32);
master->setup = tegra_spi_setup;
master->transfer_one_message = tegra_spi_transfer_one_message;
master->num_chipselect = MAX_CHIP_SELECT;
-- 
2.7.4



[PATCH V1 22/26] spi: tegra114: add support for tuning clock delay

2019-03-26 Thread Sowjanya Komatineni
Tegra SPI controller has TX_CLK_TAP_DELAY and RX_CLK_TAP_DELAY in
COMMAND2 register to tune delay of the clock going out to external
device during transmit and also for the clock coming in from external
device during receive.

TX/RX clock tap delays may vary based on the trace lengths of the
platform design for each of the slaves on the SPI bus.

This patch adds support for configuring TX/RX clock delays specified
through device tree properties.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 27 ++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index e01962344bde..725d60364ec6 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -174,6 +174,8 @@ struct tegra_spi_client_data {
int cs_setup_clk_count;
int cs_hold_clk_count;
int cs_inactive_cycles;
+   int tx_clk_tap_delay;
+   int rx_clk_tap_delay;
 };
 
 struct tegra_spi_data {
@@ -215,8 +217,10 @@ struct tegra_spi_data {
u32 command1_reg;
u32 dma_control_reg;
u32 def_command1_reg;
+   u32 def_command2_reg;
u32 spi_cs_timing1;
u32 spi_cs_timing2;
+   u8  last_used_cs;
 
struct completion   xfer_completion;
struct spi_transfer *curr_xfer;
@@ -780,7 +784,9 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device 
*spi,
u32 speed = t->speed_hz;
u8 bits_per_word = t->bits_per_word;
u32 command1;
+   u32 command2;
int req_mode;
+   u32 tx_tap = 0, rx_tap = 0;
 
if (speed != tspi->cur_speed) {
clk_set_rate(tspi->clk, speed);
@@ -843,7 +849,18 @@ static u32 tegra_spi_setup_transfer_one(struct spi_device 
*spi,
command1 &= ~(SPI_CS_SW_HW | SPI_CS_SW_VAL);
}
 
-   tegra_spi_writel(tspi, 0, SPI_COMMAND2);
+   if (tspi->last_used_cs != spi->chip_select) {
+   if (cdata && cdata->tx_clk_tap_delay)
+   tx_tap = cdata->tx_clk_tap_delay;
+   if (cdata && cdata->rx_clk_tap_delay)
+   rx_tap = cdata->rx_clk_tap_delay;
+   command2 = SPI_TX_TAP_DELAY(tx_tap) |
+  SPI_RX_TAP_DELAY(rx_tap);
+   if (command2 != tspi->def_command2_reg)
+   tegra_spi_writel(tspi, command2, SPI_COMMAND2);
+   tspi->last_used_cs = spi->chip_select;
+   }
+
} else {
command1 = tspi->command1_reg;
command1 &= ~SPI_BIT_LENGTH(~0);
@@ -923,6 +940,10 @@ static struct tegra_spi_client_data
 >cs_hold_clk_count);
of_property_read_u32(slave_np, "nvidia,cs-inactive-cycles",
 >cs_inactive_cycles);
+   of_property_read_u32(slave_np, "nvidia,tx-clk-tap-delay",
+>tx_clk_tap_delay);
+   of_property_read_u32(slave_np, "nvidia,rx-clk-tap-delay",
+>rx_clk_tap_delay);
return cdata;
 }
 
@@ -1379,6 +1400,8 @@ static int tegra_spi_probe(struct platform_device *pdev)
tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1);
tspi->spi_cs_timing1 = tegra_spi_readl(tspi, SPI_CS_TIMING1);
tspi->spi_cs_timing2 = tegra_spi_readl(tspi, SPI_CS_TIMING2);
+   tspi->def_command2_reg = tegra_spi_readl(tspi, SPI_COMMAND2);
+   tspi->last_used_cs = master->num_chipselect + 1;
pm_runtime_put(>dev);
ret = request_threaded_irq(tspi->irq, tegra_spi_isr,
   tegra_spi_isr_thread, IRQF_ONESHOT,
@@ -1451,6 +1474,8 @@ static int tegra_spi_resume(struct device *dev)
return ret;
}
tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1);
+   tegra_spi_writel(tspi, tspi->def_command2_reg, SPI_COMMAND2);
+   tspi->last_used_cs = master->num_chipselect + 1;
pm_runtime_put(dev);
 
return spi_master_resume(master);
-- 
2.7.4



[PATCH V1 16/26] spi: tegra114: set bus number based on id

2019-03-26 Thread Sowjanya Komatineni
This patch sets the SPI device id from the device tree as the
bus number.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 94acef0f5ea5..9b9d4b9e1f3e 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -1138,6 +1138,7 @@ static int tegra_spi_probe(struct platform_device *pdev)
struct tegra_spi_data   *tspi;
struct resource *r;
int ret, spi_irq;
+   int bus_num;
 
master = spi_alloc_master(>dev, sizeof(*tspi));
if (!master) {
@@ -1159,6 +1160,9 @@ static int tegra_spi_probe(struct platform_device *pdev)
master->transfer_one_message = tegra_spi_transfer_one_message;
master->num_chipselect = MAX_CHIP_SELECT;
master->auto_runtime_pm = true;
+   bus_num = of_alias_get_id(pdev->dev.of_node, "spi");
+   if (bus_num >= 0)
+   master->bus_num = bus_num;
 
tspi->master = master;
tspi->dev = >dev;
-- 
2.7.4



[PATCH V1 08/26] spi: tegra114: configure dma burst size to fifo trig level

2019-03-26 Thread Sowjanya Komatineni
Fixes: Configure DMA burst size to be same as SPI TX/RX trigger levels
to avoid mismatch.

SPI FIFO trigger levels are calculated based on the transfer length.
So this patch moves DMA slave configuration to happen before start
of DMAs.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 52 ++
 1 file changed, 30 insertions(+), 22 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 477828051aba..b7e71676a506 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -530,6 +530,8 @@ static int tegra_spi_start_dma_based_transfer(
u32 val;
unsigned int len;
int ret = 0;
+   u8 dma_burst;
+   struct dma_slave_config dma_sconfig = {0};
 
val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1);
tegra_spi_writel(tspi, val, SPI_DMA_BLK);
@@ -541,12 +543,16 @@ static int tegra_spi_start_dma_based_transfer(
len = tspi->curr_dma_words * 4;
 
/* Set attention level based on length of transfer */
-   if (len & 0xF)
+   if (len & 0xF) {
val |= SPI_TX_TRIG_1 | SPI_RX_TRIG_1;
-   else if (((len) >> 4) & 0x1)
+   dma_burst = 1;
+   } else if (((len) >> 4) & 0x1) {
val |= SPI_TX_TRIG_4 | SPI_RX_TRIG_4;
-   else
+   dma_burst = 4;
+   } else {
val |= SPI_TX_TRIG_8 | SPI_RX_TRIG_8;
+   dma_burst = 8;
+   }
 
if (tspi->cur_direction & DATA_DIR_TX)
val |= SPI_IE_TX;
@@ -557,7 +563,18 @@ static int tegra_spi_start_dma_based_transfer(
tegra_spi_writel(tspi, val, SPI_DMA_CTL);
tspi->dma_control_reg = val;
 
+   dma_sconfig.device_fc = true;
if (tspi->cur_direction & DATA_DIR_TX) {
+   dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO;
+   dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   dma_sconfig.dst_maxburst = dma_burst;
+   ret = dmaengine_slave_config(tspi->tx_dma_chan, _sconfig);
+   if (ret < 0) {
+   dev_err(tspi->dev,
+   "DMA slave config failed: %d\n", ret);
+   return ret;
+   }
+
tegra_spi_copy_client_txbuf_to_spi_txbuf(tspi, t);
ret = tegra_spi_start_tx_dma(tspi, len);
if (ret < 0) {
@@ -568,6 +585,16 @@ static int tegra_spi_start_dma_based_transfer(
}
 
if (tspi->cur_direction & DATA_DIR_RX) {
+   dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO;
+   dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   dma_sconfig.src_maxburst = dma_burst;
+   ret = dmaengine_slave_config(tspi->rx_dma_chan, _sconfig);
+   if (ret < 0) {
+   dev_err(tspi->dev,
+   "DMA slave config failed: %d\n", ret);
+   return ret;
+   }
+
/* Make the dma buffer to read by dma */
dma_sync_single_for_device(tspi->dev, tspi->rx_dma_phys,
tspi->dma_buf_size, DMA_FROM_DEVICE);
@@ -628,7 +655,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data 
*tspi,
u32 *dma_buf;
dma_addr_t dma_phys;
int ret;
-   struct dma_slave_config dma_sconfig;
 
dma_chan = dma_request_slave_channel_reason(tspi->dev,
dma_to_memory ? "rx" : "tx");
@@ -649,19 +675,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data 
*tspi,
}
 
if (dma_to_memory) {
-   dma_sconfig.src_addr = tspi->phys + SPI_RX_FIFO;
-   dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-   dma_sconfig.src_maxburst = 0;
-   } else {
-   dma_sconfig.dst_addr = tspi->phys + SPI_TX_FIFO;
-   dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
-   dma_sconfig.dst_maxburst = 0;
-   }
-
-   ret = dmaengine_slave_config(dma_chan, _sconfig);
-   if (ret)
-   goto scrub;
-   if (dma_to_memory) {
tspi->rx_dma_chan = dma_chan;
tspi->rx_dma_buf = dma_buf;
tspi->rx_dma_phys = dma_phys;
@@ -671,11 +684,6 @@ static int tegra_spi_init_dma_param(struct tegra_spi_data 
*tspi,
tspi->tx_dma_phys = dma_phys;
}
return 0;
-
-scrub:
-   dma_free_coherent(tspi->dev, tspi->dma_buf_size, dma_buf, dma_phys);
-   dma_release_channel(dma_chan);
-   return ret;
 }
 
 static void tegra_spi_deinit_dma_param(struct tegra_spi_data *tspi,
-- 
2.7.4



[PATCH V1 07/26] spi: tegra114: flush fifos

2019-03-26 Thread Sowjanya Komatineni
Fixes: Flush TX and RX FIFOs before start of new transfer and on FIFO
overflow or underrun errors.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 39 ++-
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 0d20fc489134..477828051aba 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -500,22 +500,37 @@ static int tegra_spi_start_rx_dma(struct tegra_spi_data 
*tspi, int len)
return 0;
 }
 
-static int tegra_spi_start_dma_based_transfer(
-   struct tegra_spi_data *tspi, struct spi_transfer *t)
+static int tegra_spi_flush_fifos(struct tegra_spi_data *tspi)
 {
-   u32 val;
-   unsigned int len;
-   int ret = 0;
+   unsigned long timeout = jiffies + HZ;
u32 status;
 
-   /* Make sure that Rx and Tx fifo are empty */
status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
if ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
-   dev_err(tspi->dev, "Rx/Tx fifo are not empty status 0x%08x\n",
-   (unsigned)status);
-   return -EIO;
+   status |= SPI_RX_FIFO_FLUSH | SPI_TX_FIFO_FLUSH;
+   tegra_spi_writel(tspi, status, SPI_FIFO_STATUS);
+   while ((status & SPI_FIFO_EMPTY) != SPI_FIFO_EMPTY) {
+   status = tegra_spi_readl(tspi, SPI_FIFO_STATUS);
+   if (time_after(jiffies, timeout)) {
+   dev_err(tspi->dev,
+   "timeout waiting for fifo flush\n");
+   return -EIO;
+   }
+
+   udelay(1);
+   }
}
 
+   return 0;
+}
+
+static int tegra_spi_start_dma_based_transfer(
+   struct tegra_spi_data *tspi, struct spi_transfer *t)
+{
+   u32 val;
+   unsigned int len;
+   int ret = 0;
+
val = SPI_DMA_BLK_SET(tspi->curr_dma_words - 1);
tegra_spi_writel(tspi, val, SPI_DMA_BLK);
 
@@ -781,6 +796,9 @@ static int tegra_spi_start_transfer_one(struct spi_device 
*spi,
dev_dbg(tspi->dev, "The def 0x%x and written 0x%x\n",
tspi->def_command1_reg, (unsigned)command1);
 
+   ret = tegra_spi_flush_fifos(tspi);
+   if (ret < 0)
+   return ret;
if (total_fifo_words > SPI_FIFO_DEPTH)
ret = tegra_spi_start_dma_based_transfer(tspi, t);
else
@@ -878,6 +896,7 @@ static int tegra_spi_transfer_one_message(struct spi_master 
*master,
(tspi->cur_direction & DATA_DIR_RX))
dmaengine_terminate_all(tspi->rx_dma_chan);
ret = -EIO;
+   tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
@@ -931,6 +950,7 @@ static irqreturn_t handle_cpu_based_xfer(struct 
tegra_spi_data *tspi)
tspi->status_reg);
dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg);
+   tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
@@ -1003,6 +1023,7 @@ static irqreturn_t handle_dma_based_xfer(struct 
tegra_spi_data *tspi)
tspi->status_reg);
dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n",
tspi->command1_reg, tspi->dma_control_reg);
+   tegra_spi_flush_fifos(tspi);
reset_control_assert(tspi->rst);
udelay(2);
reset_control_deassert(tspi->rst);
-- 
2.7.4



[PATCH V1 01/26] spi: tegra114: fix PIO transfer

2019-03-26 Thread Sowjanya Komatineni
Fixes: Use PIO bit in SPI_COMMAND1 register for PIO mode.

Current driver uses DMA_EN instead of PIO bit.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index a76acedd7e2f..5a21bc808bb6 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -570,8 +570,9 @@ static int tegra_spi_start_cpu_based_transfer(
 
tspi->is_curr_dma_xfer = false;
 
-   val |= SPI_DMA_EN;
-   tegra_spi_writel(tspi, val, SPI_DMA_CTL);
+   val = tspi->command1_reg;
+   val |= SPI_PIO;
+   tegra_spi_writel(tspi, val, SPI_COMMAND1);
return 0;
 }
 
-- 
2.7.4



[PATCH V1 02/26] spi: tegra114: clear packed bit for unpacked mode

2019-03-26 Thread Sowjanya Komatineni
Fixes: Clear packed bit when not using packed mode.

Packed bit is not cleared when not using packed mode. This results
in transfer timeouts for the unpacked mode transfers followed by the
packed mode transfers.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index 5a21bc808bb6..82431115b7c0 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -731,6 +731,8 @@ static int tegra_spi_start_transfer_one(struct spi_device 
*spi,
 
if (tspi->is_packed)
command1 |= SPI_PACKED;
+   else
+   command1 &= ~SPI_PACKED;
 
command1 &= ~(SPI_CS_SEL_MASK | SPI_TX_EN | SPI_RX_EN);
tspi->cur_direction = 0;
-- 
2.7.4



[PATCH V1 04/26] spi: tegra114: use packed mode for 32 bits per word

2019-03-26 Thread Sowjanya Komatineni
Fixes: Use packed mode for 32 bits per word transfers to increase
performance as each packet is a full 32-bit word.

Signed-off-by: Sowjanya Komatineni 
---
 drivers/spi/spi-tegra114.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c
index fdba302eb3b6..dc63536dbda4 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -259,7 +259,7 @@ static unsigned tegra_spi_calculate_curr_xfer_param(
 
tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8);
 
-   if (bits_per_word == 8 || bits_per_word == 16) {
+   if (bits_per_word == 8 || bits_per_word == 16 || bits_per_word == 32) {
tspi->is_packed = 1;
tspi->words_per_32bit = 32/bits_per_word;
} else {
-- 
2.7.4



Re: [PATCH V31 25/25] debugfs: Disable open() when kernel is locked down

2019-03-26 Thread Greg KH
On Tue, Mar 26, 2019 at 10:29:41PM -0700, Andy Lutomirski wrote:
> 
> 
> > On Mar 26, 2019, at 10:06 PM, Greg KH  wrote:
> > 
> >> On Tue, Mar 26, 2019 at 09:29:14PM -0700, Andy Lutomirski wrote:
> >>> On Tue, Mar 26, 2019 at 5:31 PM Greg KH  
> >>> wrote:
> >>> 
>  On Tue, Mar 26, 2019 at 12:20:24PM -0700, Andy Lutomirski wrote:
>  On Tue, Mar 26, 2019 at 11:28 AM Matthew Garrett
>   wrote:
> > 
> > From: Matthew Garrett 
> > 
> > debugfs has not been meaningfully audited in terms of ensuring that
> > userland cannot trample over the kernel. At Greg's request, disable
> > access to it entirely when the kernel is locked down. This is done at
> > open() time rather than init time as the kernel lockdown status may be
> > made stricter at runtime.
>  
>  Ugh.  Some of those files are very useful.  Could this perhaps still
>  allow O_RDONLY if we're in INTEGRITY mode?
> >>> 
> >>> Useful for what?  Debugging, sure, but for "normal operation", no kernel
> >>> functionality should ever require debugfs.  If it does, that's a bug and
> >>> should be fixed.
> >>> 
> >> 
> >> I semi-regularly read files in debugfs to diagnose things, and I think
> >> it would be good for this to work on distro kernels.
> > 
> > Doing that for debugging is wonderful.  People who want this type of
> > "lock down" are trading potential security for diagnositic ability.
> > 
> 
> I think you may be missing the point of splitting lockdown to separate 
> integrity and confidentiality.  Can you actually think of a case where 
> *reading* a debugfs file can take over a kernel?

Reading a debugfs file can expose loads of things that can help take
over a kernel, or at least make it easier.  Pointer addresses, internal
system state, loads of other fun things.  And before 4.14 or so, it was
pretty trivial to use it to oops the kernel as well (not an issue here
anymore, but people are right to be nervous).

Personally, I think these are all just "confidentiality" type things,
but who really knows given the wild-west nature of debugfs (which is as
designed).  And given that I think this patch series just crazy anyway,
I really don't care :)

thanks,

greg k-h


Re: [PATCH V31 25/25] debugfs: Disable open() when kernel is locked down

2019-03-26 Thread Andy Lutomirski



> On Mar 26, 2019, at 10:06 PM, Greg KH  wrote:
> 
>> On Tue, Mar 26, 2019 at 09:29:14PM -0700, Andy Lutomirski wrote:
>>> On Tue, Mar 26, 2019 at 5:31 PM Greg KH  wrote:
>>> 
 On Tue, Mar 26, 2019 at 12:20:24PM -0700, Andy Lutomirski wrote:
 On Tue, Mar 26, 2019 at 11:28 AM Matthew Garrett
  wrote:
> 
> From: Matthew Garrett 
> 
> debugfs has not been meaningfully audited in terms of ensuring that
> userland cannot trample over the kernel. At Greg's request, disable
> access to it entirely when the kernel is locked down. This is done at
> open() time rather than init time as the kernel lockdown status may be
> made stricter at runtime.
 
 Ugh.  Some of those files are very useful.  Could this perhaps still
 allow O_RDONLY if we're in INTEGRITY mode?
>>> 
>>> Useful for what?  Debugging, sure, but for "normal operation", no kernel
>>> functionality should ever require debugfs.  If it does, that's a bug and
>>> should be fixed.
>>> 
>> 
>> I semi-regularly read files in debugfs to diagnose things, and I think
>> it would be good for this to work on distro kernels.
> 
> Doing that for debugging is wonderful.  People who want this type of
> "lock down" are trading potential security for diagnositic ability.
> 

I think you may be missing the point of splitting lockdown to separate 
integrity and confidentiality.  Can you actually think of a case where 
*reading* a debugfs file can take over a kernel?

Re: [PATCH 03/17] fpga: dfl: fme: support 512bit data width PR

2019-03-26 Thread Wu Hao
On Mon, Mar 25, 2019 at 05:58:36PM -0500, Scott Wood wrote:
> On Mon, 2019-03-25 at 17:53 -0500, Scott Wood wrote:
> > On Mon, 2019-03-25 at 11:07 +0800, Wu Hao wrote:
> > > In early partial reconfiguration private feature, it only
> > > supports 32bit data width when writing data to hardware for
> > > PR. 512bit data width PR support is an important optimization
> > > for some specific solutions (e.g. XEON with FPGA integrated),
> > > it allows driver to use AVX512 instruction to improve the
> > > performance of partial reconfiguration. e.g. programming one
> > > 100MB bitstream image via this 512bit data width PR hardware
> > > only takes ~300ms, but 32bit revision requires ~3s per test
> > > result.
> > > 
> > > Please note now this optimization is only done on revision 2
> > > of this PR private feature which is only used in integrated
> > > solution that AVX512 is always supported.
> > > 
> > > Signed-off-by: Ananda Ravuri 
> > > Signed-off-by: Xu Yilun 
> > > Signed-off-by: Wu Hao 
> > > ---
> > >  drivers/fpga/dfl-fme-main.c |  3 ++
> > >  drivers/fpga/dfl-fme-mgr.c  | 75 +-
> > > --
> > > -
> > >  drivers/fpga/dfl-fme-pr.c   | 45 ---
> > >  drivers/fpga/dfl-fme.h  |  2 ++
> > >  drivers/fpga/dfl.h  |  5 +++
> > >  5 files changed, 99 insertions(+), 31 deletions(-)
> > > 
> > > diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
> > > index 086ad24..076d74f 100644
> > > --- a/drivers/fpga/dfl-fme-main.c
> > > +++ b/drivers/fpga/dfl-fme-main.c
> > > @@ -21,6 +21,8 @@
> > >  #include "dfl.h"
> > >  #include "dfl-fme.h"
> > >  
> > > +#define DRV_VERSION  "0.8"
> > 
> > What is this going to be used for?  Under what circumstances will the
> > driver version be bumped?  What does it have to do with 512-bit writes?

This patchset adds more features to this driver, so i would like to add
a DRV_VERSION there as an initial one. In the future, if some new features
or extensions for existing features (e.g. new revision of a private feature)
are added we need to bump this version.

> > 
> > > +#if defined(CONFIG_X86) && defined(CONFIG_AS_AVX512)
> > > +
> > > +#include 
> > > +
> > > +static inline void copy512(void *src, void __iomem *dst)
> > > +{
> > > + kernel_fpu_begin();
> > > +
> > > + asm volatile("vmovdqu64 (%0), %%zmm0;"
> > > +  "vmovntdq %%zmm0, (%1);"
> > > +  :
> > > +  : "r"(src), "r"(dst));
> > > +
> > > + kernel_fpu_end();
> > > +}
> > 
> > Shouldn't there be some sort of check that AVX512 is actually supported
> > on the running system?
> > 
> > Also, src should be const, and the asm statement should have a memory
> > clobber.
> > 
> > > +#else
> > > +static inline void copy512(void *src, void __iomem *dst)
> > > +{
> > > + WARN_ON_ONCE(1);
> > > +}
> > > +#endif
> > 
> > Likewise, this will be called if a revision 2 device is used on non-x86
> > (or on x86 with an old binutils).  The driver should fall back to 32-bit
> > in such cases.
> 
> Sorry, I missed the comment about revision 2 only being on integrated
> devices -- but will that always be the case?  Seems worthwhile to check for
> AVX512 support anyway.  And there's still the possibility of being built
> with an old binutils such that CONFIG_AS_AVX512 is not set, or running on a
> kernel where avx512 was disabled via a boot option.
> 
> What about future revisions >= 2?  Currently the driver will treat them as
> if they were revision < 2.  Is that intended?

Yes, it's intended. Currently we don't have any hardware with revisions > 2,
and support new revisions may need new code. :)  e.g. currently revision is
used to tell 32bit vs 512bit PR, but in future revisions, it may have new
capability registers for this purpose.

Thanks
Hao

> 
> -Scott
> 


[PATCH] trace/page_ref: print out the page migratetype name

2019-03-26 Thread Huang Shijie
Print out the page migratetype name which is more readable.

Signed-off-by: Huang Shijie 
---
 include/trace/events/page_ref.h | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/include/trace/events/page_ref.h b/include/trace/events/page_ref.h
index 5d2ea93956ce..94df979c2d6b 100644
--- a/include/trace/events/page_ref.h
+++ b/include/trace/events/page_ref.h
@@ -36,11 +36,12 @@ DECLARE_EVENT_CLASS(page_ref_mod_template,
__entry->val = v;
),
 
-   TP_printk("pfn=0x%lx flags=%s count=%d mapcount=%d mapping=%p mt=%d 
val=%d",
+   TP_printk("pfn=0x%lx flags=%s count=%d mapcount=%d mapping=%p mt=%s 
val=%d",
__entry->pfn,
show_page_flags(__entry->flags & ((1UL << NR_PAGEFLAGS) - 1)),
__entry->count,
-   __entry->mapcount, __entry->mapping, __entry->mt,
+   __entry->mapcount, __entry->mapping,
+   migratetype_names[__entry->mt],
__entry->val)
 );
 
@@ -86,11 +87,12 @@ DECLARE_EVENT_CLASS(page_ref_mod_and_test_template,
__entry->ret = ret;
),
 
-   TP_printk("pfn=0x%lx flags=%s count=%d mapcount=%d mapping=%p mt=%d 
val=%d ret=%d",
+   TP_printk("pfn=0x%lx flags=%s count=%d mapcount=%d mapping=%p mt=%s 
val=%d ret=%d",
__entry->pfn,
show_page_flags(__entry->flags & ((1UL << NR_PAGEFLAGS) - 1)),
__entry->count,
-   __entry->mapcount, __entry->mapping, __entry->mt,
+   __entry->mapcount, __entry->mapping,
+   migratetype_names[__entry->mt],
__entry->val, __entry->ret)
 );
 
-- 
2.17.1



Zdravstvujte Vas interesuyut klientskie bazy dannyh?

2019-03-26 Thread linux-kernel
Zdravstvujte Vas interesuyut klientskie bazy dannyh?




[PATCH v7 7/7] cros_ec: differentiate SCP from EC by feature bit.

2019-03-26 Thread Peter Shih
From: Pi-Hsun Shih 

Since a SCP and EC would both exist on a system, and use the cros_ec_dev
driver, we need to differentiate between them for the userspace, or they
would both be registered at /dev/cros_ec, causing a conflict.

Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - No change.

Changes from v5:
 - No change.

Changes from v4:
 - No change.

Changes from v3:
 - No change.

Changes from v2:
 - No change.

Changes from v1:
 - New patch extracted from Patch 5.
---
 drivers/mfd/cros_ec_dev.c| 10 ++
 include/linux/mfd/cros_ec.h  |  1 +
 include/linux/mfd/cros_ec_commands.h |  2 ++
 3 files changed, 13 insertions(+)

diff --git a/drivers/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c
index d275deaecb12..da2f2145d31d 100644
--- a/drivers/mfd/cros_ec_dev.c
+++ b/drivers/mfd/cros_ec_dev.c
@@ -418,6 +418,16 @@ static int ec_device_probe(struct platform_device *pdev)
device_initialize(>class_dev);
cdev_init(>cdev, );
 
+   /* check whether this is actually a SCP rather than an EC */
+   if (cros_ec_check_features(ec, EC_FEATURE_SCP)) {
+   dev_info(dev, "SCP detected.\n");
+   /*
+* Help userspace differentiating ECs from SCP,
+* regardless of the probing order.
+*/
+   ec_platform->ec_name = CROS_EC_DEV_SCP_NAME;
+   }
+
/*
 * Add the class device
 * Link to the character device for creating the /dev entry
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 8f2a8918bfa3..a971399bad82 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -24,6 +24,7 @@
 
 #define CROS_EC_DEV_NAME "cros_ec"
 #define CROS_EC_DEV_PD_NAME "cros_pd"
+#define CROS_EC_DEV_SCP_NAME "cros_scp"
 
 /*
  * The EC is unresponsive for a time after a reboot command.  Add a
diff --git a/include/linux/mfd/cros_ec_commands.h 
b/include/linux/mfd/cros_ec_commands.h
index fc91082d4c35..3e5da6e93b2f 100644
--- a/include/linux/mfd/cros_ec_commands.h
+++ b/include/linux/mfd/cros_ec_commands.h
@@ -856,6 +856,8 @@ enum ec_feature_code {
EC_FEATURE_RTC = 27,
/* EC supports CEC commands */
EC_FEATURE_CEC = 35,
+   /* The MCU exposes a SCP */
+   EC_FEATURE_SCP = 39,
 };
 
 #define EC_FEATURE_MASK_0(event_code) (1UL << (event_code % 32))
-- 
2.21.0.392.gf8f6787159e-goog



[PATCH v7 5/7] dt-bindings: Add binding for cros-ec-rpmsg.

2019-03-26 Thread Peter Shih
From: Pi-Hsun Shih 

Add a DT binding documentation for ChromeOS EC driver over rpmsg.

Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - No change.

Changes from v5:
 - New patch.
---
 Documentation/devicetree/bindings/mfd/cros-ec.txt | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mfd/cros-ec.txt 
b/Documentation/devicetree/bindings/mfd/cros-ec.txt
index 6245c9b1a68b..4860eabd0f72 100644
--- a/Documentation/devicetree/bindings/mfd/cros-ec.txt
+++ b/Documentation/devicetree/bindings/mfd/cros-ec.txt
@@ -3,7 +3,7 @@ ChromeOS Embedded Controller
 Google's ChromeOS EC is a Cortex-M device which talks to the AP and
 implements various function such as keyboard and battery charging.
 
-The EC can be connect through various means (I2C, SPI, LPC) and the
+The EC can be connect through various means (I2C, SPI, LPC, RPMSG) and the
 compatible string used depends on the interface. Each connection method has
 its own driver which connects to the top level interface-agnostic EC driver.
 Other Linux driver (such as cros-ec-keyb for the matrix keyboard) connect to
@@ -17,6 +17,9 @@ Required properties (SPI):
 - compatible: "google,cros-ec-spi"
 - reg: SPI chip select
 
+Required properties (RPMSG):
+- compatible: "google,cros-ec-rpmsg"
+
 Optional properties (SPI):
 - google,cros-ec-spi-pre-delay: Some implementations of the EC need a little
   time to wake up from sleep before they can receive SPI transfers at a high
-- 
2.21.0.392.gf8f6787159e-goog



[PATCH v7 6/7] platform/chrome: cros_ec: add EC host command support using rpmsg.

2019-03-26 Thread Peter Shih
From: Pi-Hsun Shih 

Add EC host command support through rpmsg.

Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - Make data for response aligned to 4 bytes.

Changes from v5:
 - Change commit title.
 - Add documents for some structs, and fix all warning from
   scripts/kernel-doc.
 - Miscellaneous fixes based on feedback.

Changes from v4:
 - Change from work queue to completion.
 - Change from matching using rpmsg id to device tree compatible, to
   support EC subdevices.

Changes from v3:
 - Add host event support by adding an extra bytes at the start of IPC
   message to indicate the type of the message (host event or host
   command), since there's no additional irq that can be used for host
   event.

Changes from v2:
 - Wait for ipi ack instead of depends on the behavior in mtk-rpmsg.

Changes from v1:
 - Code format fix based on feedback for cros_ec_rpmsg.c.
 - Extract feature detection for SCP into separate patch (Patch 6).
---
 drivers/platform/chrome/Kconfig |   9 +
 drivers/platform/chrome/Makefile|   1 +
 drivers/platform/chrome/cros_ec_rpmsg.c | 265 
 3 files changed, 275 insertions(+)
 create mode 100644 drivers/platform/chrome/cros_ec_rpmsg.c

diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 9186d81a51cc..5c48aa6da2f8 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -59,6 +59,15 @@ config CROS_EC_I2C
  a checksum. Failing accesses will be retried three times to
  improve reliability.
 
+config CROS_EC_RPMSG
+   tristate "ChromeOS Embedded Controller (rpmsg)"
+   depends on MFD_CROS_EC && RPMSG && OF
+   help
+ If you say Y here, you get support for talking to the ChromeOS EC
+ through rpmsg. This uses a simple byte-level protocol with a
+ checksum. Also since there's no addition EC-to-host interrupt, this
+ use a byte in message to distinguish host event from host command.
+
 config CROS_EC_SPI
tristate "ChromeOS Embedded Controller (SPI)"
depends on MFD_CROS_EC && SPI
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 1e2f0029b597..4b69d795720d 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_CHROMEOS_LAPTOP)   += chromeos_laptop.o
 obj-$(CONFIG_CHROMEOS_PSTORE)  += chromeos_pstore.o
 obj-$(CONFIG_CHROMEOS_TBMC)+= chromeos_tbmc.o
 obj-$(CONFIG_CROS_EC_I2C)  += cros_ec_i2c.o
+obj-$(CONFIG_CROS_EC_RPMSG)+= cros_ec_rpmsg.o
 obj-$(CONFIG_CROS_EC_SPI)  += cros_ec_spi.o
 cros_ec_lpcs-objs  := cros_ec_lpc.o cros_ec_lpc_reg.o
 cros_ec_lpcs-$(CONFIG_CROS_EC_LPC_MEC) += cros_ec_lpc_mec.o
diff --git a/drivers/platform/chrome/cros_ec_rpmsg.c 
b/drivers/platform/chrome/cros_ec_rpmsg.c
new file mode 100644
index ..2ecae806cfc5
--- /dev/null
+++ b/drivers/platform/chrome/cros_ec_rpmsg.c
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright 2018 Google LLC.
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define EC_MSG_TIMEOUT_MS 200
+#define HOST_COMMAND_MARK 1
+#define HOST_EVENT_MARK 2
+
+/**
+ * struct cros_ec_rpmsg_response - rpmsg message format from from EC.
+ *
+ * @type:  The type of message, should be either HOST_COMMAND_MARK or
+ * HOST_EVENT_MARK, representing that the message is a response to
+ * host command, or a host event.
+ * @data:  ec_host_response for host command.
+ */
+struct cros_ec_rpmsg_response {
+   u8 type;
+   u8 data[] __aligned(4);
+};
+
+/**
+ * struct cros_ec_rpmsg - information about a EC over rpmsg.
+ *
+ * @rpdev: rpmsg device we are connected to
+ * @xfer_ack:  completion for host command transfer.
+ * @host_event_work:   Work struct for pending host event.
+ */
+struct cros_ec_rpmsg {
+   struct rpmsg_device *rpdev;
+   struct completion xfer_ack;
+   struct work_struct host_event_work;
+};
+
+/**
+ * cros_ec_cmd_xfer_rpmsg - Transfer a message over rpmsg and receive the reply
+ *
+ * @ec_dev: ChromeOS EC device
+ * @ec_msg: Message to transfer
+ *
+ * This is only used for old EC proto version, and is not supported for this
+ * driver.
+ *
+ * Return: number of bytes of the reply on success or negative error code.
+ */
+static int cros_ec_cmd_xfer_rpmsg(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *ec_msg)
+{
+   return -EINVAL;
+}
+
+/**
+ * cros_ec_pkt_xfer_rpmsg - Transfer a packet over rpmsg and receive the reply
+ *
+ * @ec_dev: ChromeOS EC device
+ * @ec_msg: Message to transfer
+ *
+ * Return: number of bytes of the reply on success or negative error code.
+ */
+static int cros_ec_pkt_xfer_rpmsg(struct cros_ec_device *ec_dev,
+ struct cros_ec_command *ec_msg)

[PATCH v7 4/7] rpmsg: add rpmsg support for mt8183 SCP.

2019-03-26 Thread Peter Shih
From: Pi-Hsun Shih 

Add a simple rpmsg support for mt8183 SCP, that use IPI / IPC directly.

Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - Decouple mtk_rpmsg from mtk_scp by putting all necessary informations
   (name service IPI id, register/unregister/send functions) into a
   struct, and pass it to the mtk_rpmsg_create_rproc_subdev function.

Changes from v5:
 - CONFIG_MTK_SCP now selects CONFIG_RPMSG_MTK_SCP, and the dummy
   implementation for mtk_rpmsg_{create,destroy}_rproc_subdev when
   CONFIG_RPMSG_MTK_SCP is not defined is removed.

Changes from v4:
 - Match and fill the device tree node to the created rpmsg subdevice,
   so the rpmsg subdevice can utilize the properties and subnodes on
   device tree (This is similar to what drivers/rpmsg/qcom_smd.c does).

Changes from v3:
 - Change from unprepare to stop, to stop the rpmsg driver before the
   rproc is stopped, avoiding problem that some rpmsg would fail after
   rproc is stopped.
 - Add missing spin_lock_init, and use destroy_ept instead of kref_put.

Changes from v2:
 - Unregiser IPI handler on unprepare.
 - Lock the channel list on operations.
 - Move SCP_IPI_NS_SERVICE to 0xFF.

Changes from v1:
 - Do cleanup properly in mtk_rpmsg.c, which also removes the problem of
   short-lived work items.
 - Fix several issues checkpatch found.
---
 drivers/remoteproc/Kconfig|   1 +
 drivers/remoteproc/mtk_common.h   |   2 +
 drivers/remoteproc/mtk_scp.c  |  38 ++-
 drivers/remoteproc/mtk_scp_ipi.c  |   1 +
 drivers/rpmsg/Kconfig |   9 +
 drivers/rpmsg/Makefile|   1 +
 drivers/rpmsg/mtk_rpmsg.c | 396 ++
 include/linux/platform_data/mtk_scp.h |   4 +-
 include/linux/rpmsg/mtk_rpmsg.h   |  30 ++
 9 files changed, 477 insertions(+), 5 deletions(-)
 create mode 100644 drivers/rpmsg/mtk_rpmsg.c
 create mode 100644 include/linux/rpmsg/mtk_rpmsg.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index 92bd20d6b9cd..01182936f4fa 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -25,6 +25,7 @@ config IMX_REMOTEPROC
 config MTK_SCP
tristate "Mediatek SCP support"
depends on ARCH_MEDIATEK
+   select RPMSG_MTK_SCP
help
  Say y here to support Mediatek's System Companion Processor (SCP) via
  the remote processor framework.
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
index 7504ae1bc0ef..19a907810271 100644
--- a/drivers/remoteproc/mtk_common.h
+++ b/drivers/remoteproc/mtk_common.h
@@ -54,6 +54,8 @@ struct mtk_scp {
void __iomem *cpu_addr;
phys_addr_t phys_addr;
size_t dram_size;
+
+   struct rproc_subdev *rpmsg_subdev;
 };
 
 /**
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index ca45cb729bd3..2c4847fcae10 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "mtk_common.h"
 #include "remoteproc_internal.h"
@@ -472,6 +473,31 @@ static int scp_map_memory_region(struct mtk_scp *scp)
return 0;
 }
 
+static struct mtk_rpmsg_info mtk_scp_rpmsg_info = {
+   .send_ipi = scp_ipi_send,
+   .register_ipi = scp_ipi_register,
+   .unregister_ipi = scp_ipi_unregister,
+   .ns_ipi_id = SCP_IPI_NS_SERVICE,
+};
+
+static void scp_add_rpmsg_subdev(struct mtk_scp *scp)
+{
+   scp->rpmsg_subdev =
+   mtk_rpmsg_create_rproc_subdev(to_platform_device(scp->dev),
+ _scp_rpmsg_info);
+   if (scp->rpmsg_subdev)
+   rproc_add_subdev(scp->rproc, scp->rpmsg_subdev);
+}
+
+static void scp_remove_rpmsg_subdev(struct mtk_scp *scp)
+{
+   if (scp->rpmsg_subdev) {
+   rproc_remove_subdev(scp->rproc, scp->rpmsg_subdev);
+   mtk_rpmsg_destroy_rproc_subdev(scp->rpmsg_subdev);
+   scp->rpmsg_subdev = NULL;
+   }
+}
+
 static int scp_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -553,22 +579,25 @@ static int scp_probe(struct platform_device *pdev)
init_waitqueue_head(>run.wq);
init_waitqueue_head(>ack_wq);
 
+   scp_add_rpmsg_subdev(scp);
+
ret = devm_request_threaded_irq(dev, platform_get_irq(pdev, 0), NULL,
scp_irq_handler, IRQF_ONESHOT,
pdev->name, scp);
 
if (ret) {
dev_err(dev, "failed to request irq\n");
-   goto destroy_mutex;
+   goto remove_subdev;
}
 
ret = rproc_add(rproc);
if (ret)
-   goto destroy_mutex;
+   goto remove_subdev;
 
-   return ret;
+   return 0;
 
-destroy_mutex:
+remove_subdev:
+   scp_remove_rpmsg_subdev(scp);
mutex_destroy(>lock);
 free_rproc:
rproc_free(rproc);
@@ -580,6 +609,7 @@ static 

[PATCH v7 1/7] dt-bindings: Add a binding for Mediatek SCP

2019-03-26 Thread Peter Shih
From: Erin Lo 

Add a DT binding documentation of SCP for the
MT8183 SoC from Mediatek.

Signed-off-by: Erin Lo 
Signed-off-by: Pi-Hsun Shih 
Reviewed-by: Rob Herring 
---
Changes from v6:
 - No change.

Changes from v5:
 - Remove dependency on CONFIG_RPMSG_MTK_SCP.

Changes from v4:
 - Add detail of more properties.
 - Document the usage of mtk,rpmsg-name in subnode from the new design.

Changes from v3:
 - No change.

Changes from v2:
 - No change. I realized that for this patch series, there's no need to
   add anything under the mt8183-scp node (neither the mt8183-rpmsg or
   the cros-ec-rpmsg) for them to work, since mt8183-rpmsg is added
   directly as a rproc_subdev by code, and cros-ec-rpmsg is dynamically
   created by SCP name service.

Changes from v1:
 - No change.
---
 .../bindings/remoteproc/mtk,scp.txt   | 36 +++
 1 file changed, 36 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/remoteproc/mtk,scp.txt

diff --git a/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt 
b/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt
new file mode 100644
index ..3ba668bab14b
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/mtk,scp.txt
@@ -0,0 +1,36 @@
+Mediatek SCP Bindings
+
+
+This binding provides support for ARM Cortex M4 Co-processor found on some
+Mediatek SoCs.
+
+Required properties:
+- compatible   Should be "mediatek,mt8183-scp"
+- reg  Should contain the address ranges for the two memory
+   regions, SRAM and CFG.
+- reg-namesContains the corresponding names for the two memory
+   regions. These should be named "sram" & "cfg".
+- clocks   Clock for co-processor (See: 
../clock/clock-bindings.txt)
+- clock-names  Contains the corresponding name for the clock. This
+   should be named "main".
+
+Subnodes
+
+
+Subnodes of the SCP represent rpmsg devices. The names of the devices are not
+important. The properties of these nodes are defined by the individual bindings
+for the rpmsg devices - but must contain the following property:
+
+- mtk,rpmsg-name   Contains the name for the rpmsg device. Used to match
+   the subnode to rpmsg device announced by SCP.
+
+Example:
+
+   scp: scp@1050 {
+   compatible = "mediatek,mt8183-scp";
+   reg = <0 0x1050 0 0x8>,
+ <0 0x105c 0 0x5000>;
+   reg-names = "sram", "cfg";
+   clocks = < CLK_INFRA_SCPSYS>;
+   clock-names = "main";
+   };
-- 
2.21.0.392.gf8f6787159e-goog



[PATCH v7 3/7] remoteproc: mt8183: add reserved memory manager API

2019-03-26 Thread Peter Shih
From: Erin Lo 

Add memory table mapping API for other driver to lookup
reserved physical and virtual memory

Signed-off-by: Erin Lo 
Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - No change.

Changes from v5:
 - No change.

Changes from v4:
 - New patch.
---
 drivers/remoteproc/mtk_scp.c  | 111 ++
 include/linux/platform_data/mtk_scp.h |  20 +
 2 files changed, 131 insertions(+)

diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
index a84d69ae6c53..ca45cb729bd3 100644
--- a/drivers/remoteproc/mtk_scp.c
+++ b/drivers/remoteproc/mtk_scp.c
@@ -331,6 +331,113 @@ void *scp_mapping_dm_addr(struct platform_device *pdev, 
u32 mem_addr)
 }
 EXPORT_SYMBOL_GPL(scp_mapping_dm_addr);
 
+#if SCP_RESERVED_MEM
+phys_addr_t scp_mem_base_phys;
+phys_addr_t scp_mem_base_virt;
+phys_addr_t scp_mem_size;
+
+static struct scp_reserve_mblock scp_reserve_mblock[] = {
+   {
+   .num = SCP_ISP_MEM_ID,
+   .start_phys = 0x0,
+   .start_virt = 0x0,
+   .size = 0x140,  /*20MB*/
+   },
+};
+
+static int scp_reserve_mem_init(struct mtk_scp *scp)
+{
+   enum scp_reserve_mem_id_t id;
+   phys_addr_t accumlate_memory_size = 0;
+
+   scp_mem_base_phys = (phys_addr_t) (scp->phys_addr + MAX_CODE_SIZE);
+   scp_mem_size = (phys_addr_t) (scp->dram_size - MAX_CODE_SIZE);
+
+   dev_info(scp->dev,
+"phys:0x%llx - 0x%llx (0x%llx)\n",
+scp_mem_base_phys,
+scp_mem_base_phys + scp_mem_size,
+scp_mem_size);
+   accumlate_memory_size = 0;
+   for (id = 0; id < SCP_NUMS_MEM_ID; id++) {
+   scp_reserve_mblock[id].start_phys =
+   scp_mem_base_phys + accumlate_memory_size;
+   accumlate_memory_size += scp_reserve_mblock[id].size;
+   dev_info(scp->dev,
+"[reserve_mem:%d]: phys:0x%llx - 0x%llx (0x%llx)\n",
+id, scp_reserve_mblock[id].start_phys,
+scp_reserve_mblock[id].start_phys +
+scp_reserve_mblock[id].size,
+scp_reserve_mblock[id].size);
+   }
+   return 0;
+}
+
+static int scp_reserve_memory_ioremap(struct mtk_scp *scp)
+{
+   enum scp_reserve_mem_id_t id;
+   phys_addr_t accumlate_memory_size = 0;
+
+   scp_mem_base_virt = (phys_addr_t)(size_t)ioremap_wc(scp_mem_base_phys,
+   scp_mem_size);
+
+   dev_info(scp->dev,
+"virt:0x%llx - 0x%llx (0x%llx)\n",
+   (phys_addr_t)scp_mem_base_virt,
+   (phys_addr_t)scp_mem_base_virt + (phys_addr_t)scp_mem_size,
+   scp_mem_size);
+   for (id = 0; id < SCP_NUMS_MEM_ID; id++) {
+   scp_reserve_mblock[id].start_virt =
+   scp_mem_base_virt + accumlate_memory_size;
+   accumlate_memory_size += scp_reserve_mblock[id].size;
+   }
+   /* the reserved memory should be larger then expected memory
+* or scp_reserve_mblock does not match dts
+*/
+   WARN_ON(accumlate_memory_size > scp_mem_size);
+#ifdef DEBUG
+   for (id = 0; id < NUMS_MEM_ID; id++) {
+   dev_info(scp->dev,
+"[mem_reserve-%d] 
phys:0x%llx,virt:0x%llx,size:0x%llx\n",
+id,
+scp_get_reserve_mem_phys(id),
+scp_get_reserve_mem_virt(id),
+scp_get_reserve_mem_size(id));
+   }
+#endif
+   return 0;
+}
+phys_addr_t scp_get_reserve_mem_phys(enum scp_reserve_mem_id_t id)
+{
+   if (id >= SCP_NUMS_MEM_ID) {
+   pr_err("[SCP] no reserve memory for %d", id);
+   return 0;
+   } else
+   return scp_reserve_mblock[id].start_phys;
+}
+EXPORT_SYMBOL_GPL(scp_get_reserve_mem_phys);
+
+phys_addr_t scp_get_reserve_mem_virt(enum scp_reserve_mem_id_t id)
+{
+   if (id >= SCP_NUMS_MEM_ID) {
+   pr_err("[SCP] no reserve memory for %d", id);
+   return 0;
+   } else
+   return scp_reserve_mblock[id].start_virt;
+}
+EXPORT_SYMBOL_GPL(scp_get_reserve_mem_virt);
+
+phys_addr_t scp_get_reserve_mem_size(enum scp_reserve_mem_id_t id)
+{
+   if (id >= SCP_NUMS_MEM_ID) {
+   pr_err("[SCP] no reserve memory for %d", id);
+   return 0;
+   } else
+   return scp_reserve_mblock[id].size;
+}
+EXPORT_SYMBOL_GPL(scp_get_reserve_mem_size);
+#endif
+
 static int scp_map_memory_region(struct mtk_scp *scp)
 {
struct device_node *node;
@@ -358,6 +465,10 @@ static int scp_map_memory_region(struct mtk_scp *scp)
return -EBUSY;
}
 
+#if SCP_RESERVED_MEM
+   scp_reserve_mem_init(scp);
+   scp_reserve_memory_ioremap(scp);
+#endif
return 0;
 }
 
diff --git 

[PATCH v7 2/7] remoteproc/mediatek: add SCP support for mt8183

2019-03-26 Thread Peter Shih
From: Erin Lo 

Provide a basic driver to control Cortex M4 co-processor

Signed-off-by: Erin Lo 
Signed-off-by: Nicolas Boichat 
Signed-off-by: Pi-Hsun Shih 
---
Changes from v6:
 - No change.

Changes from v5:
 - Changed some space to tab.

Changes from v4:
 - Rename most function from mtk_scp_* to scp_*.
 - Change the irq to threaded handler.
 - Load ELF file instead of plain binary file as firmware by default
   (Squashed patch 6 in v4 into this patch).

Changes from v3:
 - Fix some issue found by checkpatch.
 - Make writes aligned in scp_ipi_send.

Changes from v2:
 - Squash patch 3 from v2 (separate the ipi interface) into this patch.
 - Remove unused name argument from scp_ipi_register.
 - Add scp_ipi_unregister for proper cleanup.
 - Move IPI ids in sync with firmware.
 - Add mb() in proper place, and correctly clear the run->signaled.

Changes from v1:
 - Extract functions and rename variables in mtk_scp.c.
---
 drivers/remoteproc/Kconfig|   9 +
 drivers/remoteproc/Makefile   |   1 +
 drivers/remoteproc/mtk_common.h   |  75 
 drivers/remoteproc/mtk_scp.c  | 496 ++
 drivers/remoteproc/mtk_scp_ipi.c  | 162 +
 include/linux/platform_data/mtk_scp.h | 135 +++
 6 files changed, 878 insertions(+)
 create mode 100644 drivers/remoteproc/mtk_common.h
 create mode 100644 drivers/remoteproc/mtk_scp.c
 create mode 100644 drivers/remoteproc/mtk_scp_ipi.c
 create mode 100644 include/linux/platform_data/mtk_scp.h

diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig
index f0abd2608044..92bd20d6b9cd 100644
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -22,6 +22,15 @@ config IMX_REMOTEPROC
 
  It's safe to say N here.
 
+config MTK_SCP
+   tristate "Mediatek SCP support"
+   depends on ARCH_MEDIATEK
+   help
+ Say y here to support Mediatek's System Companion Processor (SCP) via
+ the remote processor framework.
+
+ It's safe to say N here.
+
 config OMAP_REMOTEPROC
tristate "OMAP remoteproc support"
depends on ARCH_OMAP4 || SOC_OMAP5
diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile
index ce5d061e92be..16b3e5e7a81c 100644
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -10,6 +10,7 @@ remoteproc-y  += remoteproc_sysfs.o
 remoteproc-y   += remoteproc_virtio.o
 remoteproc-y   += remoteproc_elf_loader.o
 obj-$(CONFIG_IMX_REMOTEPROC)   += imx_rproc.o
+obj-$(CONFIG_MTK_SCP)  += mtk_scp.o mtk_scp_ipi.o
 obj-$(CONFIG_OMAP_REMOTEPROC)  += omap_remoteproc.o
 obj-$(CONFIG_WKUP_M3_RPROC)+= wkup_m3_rproc.o
 obj-$(CONFIG_DA8XX_REMOTEPROC) += da8xx_remoteproc.o
diff --git a/drivers/remoteproc/mtk_common.h b/drivers/remoteproc/mtk_common.h
new file mode 100644
index ..7504ae1bc0ef
--- /dev/null
+++ b/drivers/remoteproc/mtk_common.h
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#ifndef __RPROC_MTK_COMMON_H
+#define __RPROC_MTK_COMMON_H
+
+#include 
+#include 
+#include 
+#include 
+
+#define MT8183_SW_RSTN 0x0
+#define MT8183_SW_RSTN_BIT BIT(0)
+#define MT8183_SCP_TO_HOST 0x1C
+#define MT8183_SCP_IPC_INT_BIT BIT(0)
+#define MT8183_SCP_WDT_INT_BIT BIT(8)
+#define MT8183_HOST_TO_SCP 0x28
+#define MT8183_HOST_IPC_INT_BITBIT(0)
+#define MT8183_SCP_SRAM_PDN0x402C
+
+#define SCP_FW_VER_LEN 32
+
+struct scp_run {
+   u32 signaled;
+   s8 fw_ver[SCP_FW_VER_LEN];
+   u32 dec_capability;
+   u32 enc_capability;
+   wait_queue_head_t wq;
+};
+
+struct scp_ipi_desc {
+   scp_ipi_handler_t handler;
+   void *priv;
+};
+
+struct mtk_scp {
+   struct device *dev;
+   struct rproc *rproc;
+   struct clk *clk;
+   void __iomem *reg_base;
+   void __iomem *sram_base;
+   size_t sram_size;
+
+   struct share_obj *recv_buf;
+   struct share_obj *send_buf;
+   struct scp_run run;
+   struct mutex lock; /* for protecting mtk_scp data structure */
+   struct scp_ipi_desc ipi_desc[SCP_IPI_MAX];
+   bool ipi_id_ack[SCP_IPI_MAX];
+   wait_queue_head_t ack_wq;
+
+   void __iomem *cpu_addr;
+   phys_addr_t phys_addr;
+   size_t dram_size;
+};
+
+/**
+ * struct share_obj - SRAM buffer shared with
+ *   AP and SCP
+ *
+ * @id:IPI id
+ * @len:   share buffer length
+ * @share_buf: share buffer data
+ */
+struct share_obj {
+   s32 id;
+   u32 len;
+   u8 share_buf[288];
+};
+
+void scp_memcpy_aligned(void *dst, const void *src, unsigned int len);
+
+#endif
diff --git a/drivers/remoteproc/mtk_scp.c b/drivers/remoteproc/mtk_scp.c
new file mode 100644
index ..a84d69ae6c53
--- /dev/null
+++ 

Re: [PATCH 5.0 00/52] 5.0.5-stable review

2019-03-26 Thread Greg Kroah-Hartman
On Wed, Mar 27, 2019 at 09:36:06AM +0530, Naresh Kamboju wrote:
> On Tue, 26 Mar 2019 at 12:09, Greg Kroah-Hartman
>  wrote:
> >
> > This is the start of the stable review cycle for the 5.0.5 release.
> > There are 52 patches in this series, all will be posted as a response
> > to this one.  If anyone has any issues with these being applied, please
> > let me know.
> >
> > Responses should be made by Thu Mar 28 04:26:38 UTC 2019.
> > Anything received after that time might be too late.
> >
> > The whole patch series can be found in one patch at:
> > 
> > https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.0.5-rc1.gz
> > or in the git tree and branch at:
> > 
> > git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git 
> > linux-5.0.y
> > and the diffstat can be found below.
> >
> > thanks,
> >
> > greg k-h
> >
> 
> Results from Linaro’s test farm.
> No regressions on arm64, arm, x86_64, and i386.

Thank you for testing all of these and letting me know.

greg k-h


Re: [PATCH V31 25/25] debugfs: Disable open() when kernel is locked down

2019-03-26 Thread Greg KH
On Tue, Mar 26, 2019 at 09:29:14PM -0700, Andy Lutomirski wrote:
> On Tue, Mar 26, 2019 at 5:31 PM Greg KH  wrote:
> >
> > On Tue, Mar 26, 2019 at 12:20:24PM -0700, Andy Lutomirski wrote:
> > > On Tue, Mar 26, 2019 at 11:28 AM Matthew Garrett
> > >  wrote:
> > > >
> > > > From: Matthew Garrett 
> > > >
> > > > debugfs has not been meaningfully audited in terms of ensuring that
> > > > userland cannot trample over the kernel. At Greg's request, disable
> > > > access to it entirely when the kernel is locked down. This is done at
> > > > open() time rather than init time as the kernel lockdown status may be
> > > > made stricter at runtime.
> > >
> > > Ugh.  Some of those files are very useful.  Could this perhaps still
> > > allow O_RDONLY if we're in INTEGRITY mode?
> >
> > Useful for what?  Debugging, sure, but for "normal operation", no kernel
> > functionality should ever require debugfs.  If it does, that's a bug and
> > should be fixed.
> >
> 
> I semi-regularly read files in debugfs to diagnose things, and I think
> it would be good for this to work on distro kernels.

Doing that for debugging is wonderful.  People who want this type of
"lock down" are trading potential security for diagnositic ability.

good luck!

greg k-h


RE: [PATCH] input: keyboard: snvs: make sure irq is handled correctly

2019-03-26 Thread Anson Huang
Hi, Dmitry

Best Regards!
Anson Huang

> -Original Message-
> From: dmitry.torok...@gmail.com [mailto:dmitry.torok...@gmail.com]
> Sent: 2019年3月27日 12:29
> To: Anson Huang 
> Cc: Fabio Estevam ; linux-in...@vger.kernel.org;
> linux-kernel@vger.kernel.org; dl-linux-imx 
> Subject: Re: [PATCH] input: keyboard: snvs: make sure irq is handled
> correctly
> 
> Hi Anson,
> 
> On Wed, Mar 27, 2019 at 02:47:06AM +, Anson Huang wrote:
> > SNVS IRQ is requested before necessary driver data initialized, if
> > there is a pending IRQ during driver probe phase, kernel NULL pointer
> > panic will occur in IRQ handler. To avoid such scenario, need to move
> > the IRQ request to after driver data initialization done. This patch
> > is inspired by NXP's internal kernel tree.
> >
> > Fixes: d3dc6e232215 ("input: keyboard: imx: add snvs power key
> > driver")
> > Signed-off-by: Anson Huang 
> > ---
> >  drivers/input/keyboard/snvs_pwrkey.c | 17 -
> >  1 file changed, 8 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/input/keyboard/snvs_pwrkey.c
> > b/drivers/input/keyboard/snvs_pwrkey.c
> > index effb632..6ff41fd 100644
> > --- a/drivers/input/keyboard/snvs_pwrkey.c
> > +++ b/drivers/input/keyboard/snvs_pwrkey.c
> > @@ -148,15 +148,6 @@ static int imx_snvs_pwrkey_probe(struct
> platform_device *pdev)
> > return error;
> > }
> >
> > -   error = devm_request_irq(>dev, pdata->irq,
> > -  imx_snvs_pwrkey_interrupt,
> > -  0, pdev->name, pdev);
> > -
> > -   if (error) {
> > -   dev_err(>dev, "interrupt not available.\n");
> > -   return error;
> > -   }
> > -
> > error = input_register_device(input);
> > if (error < 0) {
> > dev_err(>dev, "failed to register input device\n");
> @@ -166,6
> > +157,14 @@ static int imx_snvs_pwrkey_probe(struct platform_device
> *pdev)
> > pdata->input = input;
> > platform_set_drvdata(pdev, pdata);
> >
> > +   error = devm_request_irq(>dev, pdata->irq,
> > +imx_snvs_pwrkey_interrupt,
> > +0, pdev->name, pdev);
> > +   if (error) {
> > +   dev_err(>dev, "interrupt not available.\n");
> > +   return error;
> > +   }
> 
> Instead of moving devm_request_irq() around could you simply move
> pdata->input = input assignment higher? It is perfectly fine to try
> calling input_event() on input device that is allocated but not yet 
> registered.

OK, make sense.

> 
> > +
> > device_init_wakeup(>dev, pdata->wakeup);
> 
> Unrelated suggestion:
> 
> Can you try calling dev_pm_set_wake_irq(>dev, pdata->irq) here and
> I think you will be able to get rid of suspend/resume methods in the driver.

OK, I will look into it, and send another patch to improve this.

Thanks.
Anson

> 
> Thanks.
> 
> --
> Dmitry


[PATCH] clocksource/drivers/timer-ti-dm: Remove omap_dm_timer_set_load_start

2019-03-26 Thread Nathan Chancellor
Commit 008258d995a6 ("clocksource/drivers/timer-ti-dm: Make
omap_dm_timer_set_load_start() static") made omap_dm_time_set_load_start
static because its prototype was not defined in a header. Unfortunately,
this causes a build warning on multi_v7_defconfig because this function
is not used anywhere in this translation unit:

drivers/clocksource/timer-ti-dm.c:589:12: error: unused function
'omap_dm_timer_set_load_start' [-Werror,-Wunused-function]

In fact, omap_dm_timer_set_load_start hasn't been used anywhere since
commit f190be7f39a5 ("staging: tidspbridge: remove driver") and the
prototype was removed in commit 592ea6bd1fad ("clocksource: timer-ti-dm:
Make unexported functions static"), which is probably where this should
have happened.

Fixes: 592ea6bd1fad ("clocksource: timer-ti-dm: Make unexported functions 
static")
Fixes: 008258d995a6 ("clocksource/drivers/timer-ti-dm: Make 
omap_dm_timer_set_load_start() static")
Signed-off-by: Nathan Chancellor 
---

My apologies if this has already been sent, I didn't see anything in tip
or on LKML.

 drivers/clocksource/timer-ti-dm.c | 28 
 1 file changed, 28 deletions(-)

diff --git a/drivers/clocksource/timer-ti-dm.c 
b/drivers/clocksource/timer-ti-dm.c
index 3352da6ed61f..ee8ec5a8cb16 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -585,34 +585,6 @@ static int omap_dm_timer_set_load(struct omap_dm_timer 
*timer, int autoreload,
return 0;
 }
 
-/* Optimized set_load which removes costly spin wait in timer_start */
-static int omap_dm_timer_set_load_start(struct omap_dm_timer *timer,
-   int autoreload, unsigned int load)
-{
-   u32 l;
-
-   if (unlikely(!timer))
-   return -EINVAL;
-
-   omap_dm_timer_enable(timer);
-
-   l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
-   if (autoreload) {
-   l |= OMAP_TIMER_CTRL_AR;
-   omap_dm_timer_write_reg(timer, OMAP_TIMER_LOAD_REG, load);
-   } else {
-   l &= ~OMAP_TIMER_CTRL_AR;
-   }
-   l |= OMAP_TIMER_CTRL_ST;
-
-   __omap_dm_timer_load_start(timer, l, load, timer->posted);
-
-   /* Save the context */
-   timer->context.tclr = l;
-   timer->context.tldr = load;
-   timer->context.tcrr = load;
-   return 0;
-}
 static int omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable,
   unsigned int match)
 {
-- 
2.21.0



Re: [PATCH v19,RESEND 16/27] x86/sgx: Add the Linux SGX Enclave Driver

2019-03-26 Thread Jarkko Sakkinen
On Tue, Mar 26, 2019 at 12:01:31PM +, Huang, Kai wrote:
> On Wed, 2019-03-20 at 18:21 +0200, Jarkko Sakkinen wrote:
> > Intel Software Guard eXtensions (SGX) is a set of CPU instructions that
> > can be used by applications to set aside private regions of code and
> > data. The code outside the enclave is disallowed to access the memory
> > inside the enclave by the CPU access control.
> > 
> > This commit adds the Linux SGX Enclave Driver that provides an ioctl API
> > to manage enclaves. The address range for an enclave, commonly referred
> > as ELRANGE in the documentation (e.g. Intel SDM), is reserved with
> > mmap() against /dev/sgx. After that a set ioctls is used to build
> > the enclave to the ELRANGE.
> > 
> > Signed-off-by: Jarkko Sakkinen 
> > Co-developed-by: Sean Christopherson 
> > Signed-off-by: Sean Christopherson 
> > Co-developed-by: Serge Ayoun 
> > Signed-off-by: Serge Ayoun 
> > Co-developed-by: Shay Katz-zamir 
> > Signed-off-by: Shay Katz-zamir 
> > Co-developed-by: Suresh Siddha 
> > Signed-off-by: Suresh Siddha 
> > ---
> >  Documentation/ioctl/ioctl-number.txt|   1 +
> >  arch/x86/Kconfig|  17 +-
> >  arch/x86/include/uapi/asm/sgx.h |  59 ++
> >  arch/x86/kernel/cpu/sgx/Makefile|   5 +-
> >  arch/x86/kernel/cpu/sgx/driver/Makefile |   3 +
> >  arch/x86/kernel/cpu/sgx/driver/driver.h |  38 ++
> >  arch/x86/kernel/cpu/sgx/driver/ioctl.c  | 795 
> >  arch/x86/kernel/cpu/sgx/driver/main.c   | 290 +
> >  arch/x86/kernel/cpu/sgx/encl.c  | 358 +++
> >  arch/x86/kernel/cpu/sgx/encl.h  |  88 +++
> >  arch/x86/kernel/cpu/sgx/encls.c |   1 +
> >  arch/x86/kernel/cpu/sgx/main.c  |   3 +
> >  arch/x86/kernel/cpu/sgx/sgx.h   |   1 +
> >  13 files changed, 1657 insertions(+), 2 deletions(-)
> >  create mode 100644 arch/x86/include/uapi/asm/sgx.h
> >  create mode 100644 arch/x86/kernel/cpu/sgx/driver/Makefile
> >  create mode 100644 arch/x86/kernel/cpu/sgx/driver/driver.h
> >  create mode 100644 arch/x86/kernel/cpu/sgx/driver/ioctl.c
> >  create mode 100644 arch/x86/kernel/cpu/sgx/driver/main.c
> >  create mode 100644 arch/x86/kernel/cpu/sgx/encl.c
> >  create mode 100644 arch/x86/kernel/cpu/sgx/encl.h
> 
> Shouldn't the driver be located somewhere under drivers/, but not under 
> arch/x86?
> 
> I don't think x86 maintainers should have the burden to review every code 
> change made to SGX driver?

Not sure I got your angle. It is x86 tied code.

$ git grep tristate arch/x86/ | wc -l
22

/Jarkko


[PATCH v13 11/11] thermal: intel: intel_soc_dts_iosf: Utilize for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Utilize for_each_set_clump8 macro, and the bitmap_set_value8 and
bitmap_get_value8 functions, where appropriate. In addition, remove the
now unnecessary temp_mask and temp_shift members of the
intel_soc_dts_sensor_entry structure.

Suggested-by: Andy Shevchenko 
Tested-by: Andy Shevchenko 
Signed-off-by: William Breathitt Gray 
---
 drivers/thermal/intel/intel_soc_dts_iosf.c | 29 +-
 drivers/thermal/intel/intel_soc_dts_iosf.h |  2 --
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c 
b/drivers/thermal/intel/intel_soc_dts_iosf.c
index e0813dfaa278..2aa16b5262e9 100644
--- a/drivers/thermal/intel/intel_soc_dts_iosf.c
+++ b/drivers/thermal/intel/intel_soc_dts_iosf.c
@@ -15,6 +15,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include 
 #include 
 #include 
 #include 
@@ -111,6 +112,7 @@ static int update_trip_temp(struct 
intel_soc_dts_sensor_entry *dts,
 {
int status;
u32 temp_out;
+   unsigned long update_ptps;
u32 out;
u32 store_ptps;
u32 store_ptmc;
@@ -129,8 +131,9 @@ static int update_trip_temp(struct 
intel_soc_dts_sensor_entry *dts,
if (status)
return status;
 
-   out = (store_ptps & ~(0xFF << (thres_index * 8)));
-   out |= (temp_out & 0xFF) << (thres_index * 8);
+   update_ptps = store_ptps;
+   bitmap_set_value8(_ptps, temp_out & 0xFF, thres_index * 8);
+   out = update_ptps;
status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_PTPS, out);
if (status)
@@ -232,6 +235,7 @@ static int sys_get_curr_temp(struct thermal_zone_device 
*tzd,
u32 out;
struct intel_soc_dts_sensor_entry *dts;
struct intel_soc_dts_sensors *sensors;
+   unsigned long temp_raw;
 
dts = tzd->devdata;
sensors = dts->sensors;
@@ -240,7 +244,8 @@ static int sys_get_curr_temp(struct thermal_zone_device 
*tzd,
if (status)
return status;
 
-   out = (out & dts->temp_mask) >> dts->temp_shift;
+   temp_raw = out;
+   out = bitmap_get_value8(_raw, dts->id * 8);
out -= SOC_DTS_TJMAX_ENCODING;
*temp = sensors->tj_max - out * 1000;
 
@@ -290,10 +295,13 @@ static int add_dts_thermal_zone(int id, struct 
intel_soc_dts_sensor_entry *dts,
 {
char name[10];
int trip_count = 0;
+   int writable_trip_count = 0;
int trip_mask = 0;
u32 store_ptps;
int ret;
-   int i;
+   unsigned long i;
+   unsigned long trip;
+   unsigned long ptps;
 
/* Store status to restor on exit */
ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
@@ -302,11 +310,10 @@ static int add_dts_thermal_zone(int id, struct 
intel_soc_dts_sensor_entry *dts,
goto err_ret;
 
dts->id = id;
-   dts->temp_mask = 0x00FF << (id * 8);
-   dts->temp_shift = id * 8;
if (notification_support) {
trip_count = min(SOC_MAX_DTS_TRIPS, trip_cnt);
-   trip_mask = BIT(trip_count - read_only_trip_cnt) - 1;
+   writable_trip_count = trip_count - read_only_trip_cnt;
+   trip_mask = GENMASK(writable_trip_count - 1, 0);
}
 
/* Check if the writable trip we provide is not used by BIOS */
@@ -315,11 +322,9 @@ static int add_dts_thermal_zone(int id, struct 
intel_soc_dts_sensor_entry *dts,
if (ret)
trip_mask = 0;
else {
-   for (i = 0; i < trip_count; ++i) {
-   if (trip_mask & BIT(i))
-   if (store_ptps & (0xff << (i * 8)))
-   trip_mask &= ~BIT(i);
-   }
+   ptps = store_ptps;
+   for_each_set_clump8(i, trip, , writable_trip_count * 8)
+   trip_mask &= ~BIT(i / 8);
}
dts->trip_mask = trip_mask;
dts->trip_count = trip_count;
diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.h 
b/drivers/thermal/intel/intel_soc_dts_iosf.h
index 625e37bf93dc..d0362d7acdef 100644
--- a/drivers/thermal/intel/intel_soc_dts_iosf.h
+++ b/drivers/thermal/intel/intel_soc_dts_iosf.h
@@ -33,8 +33,6 @@ struct intel_soc_dts_sensors;
 
 struct intel_soc_dts_sensor_entry {
int id;
-   u32 temp_mask;
-   u32 temp_shift;
u32 store_status;
u32 trip_mask;
u32 trip_count;
-- 
2.21.0



[PATCH v13 10/11] gpio: 74x164: Utilize the for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Replace verbose implementation in set_multiple callback with
for_each_set_clump8 macro to simplify code and improve clarity.

Suggested-by: Andy Shevchenko 
Cc: Geert Uytterhoeven 
Cc: Phil Reid 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-74x164.c | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c
index fb7b620763a2..0bbf1162bb31 100644
--- a/drivers/gpio/gpio-74x164.c
+++ b/drivers/gpio/gpio-74x164.c
@@ -9,6 +9,7 @@
  *  published by the Free Software Foundation.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -75,20 +76,18 @@ static void gen_74x164_set_multiple(struct gpio_chip *gc, 
unsigned long *mask,
unsigned long *bits)
 {
struct gen_74x164_chip *chip = gpiochip_get_data(gc);
-   unsigned int i, idx, shift;
-   u8 bank, bankmask;
+   unsigned long offset;
+   unsigned long bankmask;
+   size_t bank;
+   unsigned long bitmask;
 
mutex_lock(>lock);
-   for (i = 0, bank = chip->registers - 1; i < chip->registers;
-i++, bank--) {
-   idx = i / sizeof(*mask);
-   shift = i % sizeof(*mask) * BITS_PER_BYTE;
-   bankmask = mask[idx] >> shift;
-   if (!bankmask)
-   continue;
+   for_each_set_clump8(offset, bankmask, mask, chip->registers * 8) {
+   bank = (chip->registers - 1) - (offset / 8);
+   bitmask = bitmap_get_value8(bits, offset) & bankmask;
 
chip->buffer[bank] &= ~bankmask;
-   chip->buffer[bank] |= bankmask & (bits[idx] >> shift);
+   chip->buffer[bank] |= bitmask;
}
__gen_74x164_write_config(chip);
mutex_unlock(>lock);
-- 
2.21.0



[PATCH v13 09/11] gpio: uniphier: Utilize for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Replace verbose implementation in set_multiple callback with
for_each_set_clump8 macro to simplify code and improve clarity. An
improvement in this case is that banks that are not masked will now be
skipped.

Cc: Masahiro Yamada 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-uniphier.c | 16 ++--
 1 file changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/gpio/gpio-uniphier.c b/drivers/gpio/gpio-uniphier.c
index 0f662b297a95..d79c34e9b23b 100644
--- a/drivers/gpio/gpio-uniphier.c
+++ b/drivers/gpio/gpio-uniphier.c
@@ -15,9 +15,6 @@
 #include 
 #include 
 
-#define UNIPHIER_GPIO_BANK_MASK\
-   GENMASK((UNIPHIER_GPIO_LINES_PER_BANK) - 1, 0)
-
 #define UNIPHIER_GPIO_IRQ_MAX_NUM  24
 
 #define UNIPHIER_GPIO_PORT_DATA0x0 /* data */
@@ -147,15 +144,14 @@ static void uniphier_gpio_set(struct gpio_chip *chip,
 static void uniphier_gpio_set_multiple(struct gpio_chip *chip,
   unsigned long *mask, unsigned long *bits)
 {
-   unsigned int bank, shift, bank_mask, bank_bits;
-   int i;
+   unsigned long i;
+   unsigned long bank_mask;
+   unsigned long bank;
+   unsigned long bank_bits;
 
-   for (i = 0; i < chip->ngpio; i += UNIPHIER_GPIO_LINES_PER_BANK) {
+   for_each_set_clump8(i, bank_mask, mask, chip->ngpio) {
bank = i / UNIPHIER_GPIO_LINES_PER_BANK;
-   shift = i % BITS_PER_LONG;
-   bank_mask = (mask[BIT_WORD(i)] >> shift) &
-   UNIPHIER_GPIO_BANK_MASK;
-   bank_bits = bits[BIT_WORD(i)] >> shift;
+   bank_bits = bitmap_get_value8(bits, i);
 
uniphier_gpio_bank_write(chip, bank, UNIPHIER_GPIO_PORT_DATA,
 bank_mask, bank_bits);
-- 
2.21.0



[PATCH v13 08/11] gpio: pcie-idio-24: Utilize for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-pcie-idio-24.c | 109 ---
 1 file changed, 40 insertions(+), 69 deletions(-)

diff --git a/drivers/gpio/gpio-pcie-idio-24.c b/drivers/gpio/gpio-pcie-idio-24.c
index 52f1647a46fd..924ec916b358 100644
--- a/drivers/gpio/gpio-pcie-idio-24.c
+++ b/drivers/gpio/gpio-pcie-idio-24.c
@@ -198,52 +198,34 @@ static int idio_24_gpio_get_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
-   size_t i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
-   unsigned long port_state;
+   unsigned long offset;
+   unsigned long gpio_mask;
void __iomem *ports[] = {
>reg->out0_7, >reg->out8_15,
>reg->out16_23, >reg->in0_7,
>reg->in8_15, >reg->in16_23,
};
+   size_t index;
+   unsigned long port_state;
const unsigned long out_mode_mask = BIT(1);
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports) + 1; i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
+   for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
+   index = offset / 8;
 
/* read bits from current gpio port (port 6 is TTL GPIO) */
-   if (i < 6)
-   port_state = ioread8(ports[i]);
+   if (index < 6)
+   port_state = ioread8(ports[index]);
else if (ioread8(>reg->ctl) & out_mode_mask)
port_state = ioread8(>reg->ttl_out0_7);
else
port_state = ioread8(>reg->ttl_in0_7);
 
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   port_state &= gpio_mask;
+
+   bitmap_set_value8(bits, port_state, offset);
}
 
return 0;
@@ -294,59 +276,48 @@ static void idio_24_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct idio_24_gpio *const idio24gpio = gpiochip_get_data(chip);
-   size_t i;
-   unsigned long bits_offset;
+   unsigned long offset;
unsigned long gpio_mask;
-   const unsigned int gpio_reg_size = 8;
-   const unsigned long port_mask = GENMASK(gpio_reg_size, 0);
-   unsigned long flags;
-   unsigned int out_state;
void __iomem *ports[] = {
>reg->out0_7, >reg->out8_15,
>reg->out16_23
};
+   size_t index;
+   unsigned long bitmask;
+   unsigned long flags;
+   unsigned long out_state;
const unsigned long out_mode_mask = BIT(1);
-   const unsigned int ttl_offset = 48;
-   const size_t ttl_i = BIT_WORD(ttl_offset);
-   const unsigned int word_offset = ttl_offset % BITS_PER_LONG;
-   const unsigned long ttl_mask = (mask[ttl_i] >> word_offset) & port_mask;
-   const unsigned long ttl_bits = (bits[ttl_i] >> word_offset) & ttl_mask;
-
-   /* set bits are processed a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* check if any set bits for current port */
-   gpio_mask = (*mask >> bits_offset) & port_mask;
-   if (!gpio_mask) {
-   /* no set bits for this port so move on to next port */
-   continue;
-   }
 
-   raw_spin_lock_irqsave(>lock, flags);
+   for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
+   index = offset / 8;
 
-   /* process output lines */
-   out_state = ioread8(ports[i]) & 

[PATCH v13 07/11] gpio: pci-idio-16: Utilize for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-pci-idio-16.c | 75 -
 1 file changed, 27 insertions(+), 48 deletions(-)

diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c
index 6b7349783223..a67388db28ad 100644
--- a/drivers/gpio/gpio-pci-idio-16.c
+++ b/drivers/gpio/gpio-pci-idio-16.c
@@ -108,45 +108,23 @@ static int idio_16_gpio_get_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
-   size_t i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
-   unsigned long port_state;
+   unsigned long offset;
+   unsigned long gpio_mask;
void __iomem *ports[] = {
>reg->out0_7, >reg->out8_15,
>reg->in0_7, >reg->in8_15,
};
+   void __iomem *port_addr;
+   unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
+   for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
+   port_addr = ports[offset / 8];
+   port_state = ioread8(port_addr) & gpio_mask;
 
-   /* read bits from current gpio port */
-   port_state = ioread8(ports[i]);
-
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, port_state, offset);
}
 
return 0;
@@ -186,30 +164,31 @@ static void idio_16_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct idio_16_gpio *const idio16gpio = gpiochip_get_data(chip);
+   unsigned long offset;
+   unsigned long gpio_mask;
+   void __iomem *ports[] = {
+   >reg->out0_7, >reg->out8_15,
+   };
+   size_t index;
+   void __iomem *port_addr;
+   unsigned long bitmask;
unsigned long flags;
-   unsigned int out_state;
+   unsigned long out_state;
 
-   raw_spin_lock_irqsave(>lock, flags);
+   for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
+   index = offset / 8;
+   port_addr = ports[index];
 
-   /* process output lines 0-7 */
-   if (*mask & 0xFF) {
-   out_state = ioread8(>reg->out0_7) & ~*mask;
-   out_state |= *mask & *bits;
-   iowrite8(out_state, >reg->out0_7);
-   }
+   bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
+
+   raw_spin_lock_irqsave(>lock, flags);
 
-   /* shift to next output line word */
-   *mask >>= 8;
+   out_state = ioread8(port_addr) & ~gpio_mask;
+   out_state |= bitmask;
+   iowrite8(out_state, port_addr);
 
-   /* process output lines 8-15 */
-   if (*mask & 0xFF) {
-   *bits >>= 8;
-   out_state = ioread8(>reg->out8_15) & ~*mask;
-   out_state |= *mask & *bits;
-   iowrite8(out_state, >reg->out8_15);
+   raw_spin_unlock_irqrestore(>lock, flags);
}
-
-   raw_spin_unlock_irqrestore(>lock, flags);
 }
 
 static void idio_16_irq_ack(struct irq_data *data)
-- 
2.21.0



[PATCH v13 06/11] gpio: ws16c48: Utilize for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-ws16c48.c | 73 ++---
 1 file changed, 20 insertions(+), 53 deletions(-)

diff --git a/drivers/gpio/gpio-ws16c48.c b/drivers/gpio/gpio-ws16c48.c
index 5cf3697bfb15..ee30417d6394 100644
--- a/drivers/gpio/gpio-ws16c48.c
+++ b/drivers/gpio/gpio-ws16c48.c
@@ -134,42 +134,19 @@ static int ws16c48_gpio_get_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
-   const unsigned int gpio_reg_size = 8;
-   size_t i;
-   const size_t num_ports = chip->ngpio / gpio_reg_size;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
+   unsigned long offset;
+   unsigned long gpio_mask;
+   unsigned int port_addr;
unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < num_ports; i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
+   for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) {
+   port_addr = ws16c48gpio->base + offset / 8;
+   port_state = inb(port_addr) & gpio_mask;
 
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
-
-   /* read bits from current gpio port */
-   port_state = inb(ws16c48gpio->base + i);
-
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, port_state, offset);
}
 
return 0;
@@ -203,39 +180,29 @@ static void ws16c48_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct ws16c48_gpio *const ws16c48gpio = gpiochip_get_data(chip);
-   unsigned int i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int port;
-   unsigned int iomask;
-   unsigned int bitmask;
+   unsigned long offset;
+   unsigned long gpio_mask;
+   size_t index;
+   unsigned int port_addr;
+   unsigned long bitmask;
unsigned long flags;
 
-   /* set bits are evaluated a gpio register size at a time */
-   for (i = 0; i < chip->ngpio; i += gpio_reg_size) {
-   /* no more set bits in this mask word; skip to the next word */
-   if (!mask[BIT_WORD(i)]) {
-   i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size;
-   continue;
-   }
-
-   port = i / gpio_reg_size;
+   for_each_set_clump8(offset, gpio_mask, mask, chip->ngpio) {
+   index = offset / 8;
+   port_addr = ws16c48gpio->base + index;
 
/* mask out GPIO configured for input */
-   iomask = mask[BIT_WORD(i)] & ~ws16c48gpio->io_state[port];
-   bitmask = iomask & bits[BIT_WORD(i)];
+   gpio_mask &= ~ws16c48gpio->io_state[index];
+   bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
 
raw_spin_lock_irqsave(>lock, flags);
 
/* update output state data and set device gpio register */
-   ws16c48gpio->out_state[port] &= ~iomask;
-   ws16c48gpio->out_state[port] |= bitmask;
-   outb(ws16c48gpio->out_state[port], ws16c48gpio->base + port);
+   ws16c48gpio->out_state[index] &= ~gpio_mask;
+   ws16c48gpio->out_state[index] |= bitmask;
+   outb(ws16c48gpio->out_state[index], port_addr);
 
raw_spin_unlock_irqrestore(>lock, flags);
-
-   /* prepare for next gpio register set */
-   mask[BIT_WORD(i)] >>= gpio_reg_size;
-   bits[BIT_WORD(i)] >>= gpio_reg_size;
}
 }
 
-- 
2.21.0



[PATCH v13 05/11] gpio: gpio-mm: Utilize for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-gpio-mm.c | 73 +++--
 1 file changed, 21 insertions(+), 52 deletions(-)

diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c
index 8c150fd68d9d..0cef50d14c5a 100644
--- a/drivers/gpio/gpio-gpio-mm.c
+++ b/drivers/gpio/gpio-gpio-mm.c
@@ -172,46 +172,25 @@ static int gpiomm_gpio_get(struct gpio_chip *chip, 
unsigned int offset)
return !!(port_state & mask);
 }
 
+static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+
 static int gpiomm_gpio_get_multiple(struct gpio_chip *chip, unsigned long 
*mask,
unsigned long *bits)
 {
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
-   size_t i;
-   static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
+   unsigned long offset;
+   unsigned long gpio_mask;
+   unsigned int port_addr;
unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
-
-   /* read bits from current gpio port */
-   port_state = inb(gpiommgpio->base + ports[i]);
+   for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
+   port_addr = gpiommgpio->base + ports[offset / 8];
+   port_state = inb(port_addr) & gpio_mask;
 
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, port_state, offset);
}
 
return 0;
@@ -242,37 +221,27 @@ static void gpiomm_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct gpiomm_gpio *const gpiommgpio = gpiochip_get_data(chip);
-   unsigned int i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int port;
-   unsigned int out_port;
-   unsigned int bitmask;
+   unsigned long offset;
+   unsigned long gpio_mask;
+   size_t index;
+   unsigned int port_addr;
+   unsigned long bitmask;
unsigned long flags;
 
-   /* set bits are evaluated a gpio register size at a time */
-   for (i = 0; i < chip->ngpio; i += gpio_reg_size) {
-   /* no more set bits in this mask word; skip to the next word */
-   if (!mask[BIT_WORD(i)]) {
-   i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size;
-   continue;
-   }
+   for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
+   index = offset / 8;
+   port_addr = gpiommgpio->base + ports[index];
 
-   port = i / gpio_reg_size;
-   out_port = (port > 2) ? port + 1 : port;
-   bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)];
+   bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
 
spin_lock_irqsave(>lock, flags);
 
/* update output state data and set device gpio register */
-   gpiommgpio->out_state[port] &= ~mask[BIT_WORD(i)];
-   gpiommgpio->out_state[port] |= bitmask;
-   outb(gpiommgpio->out_state[port], gpiommgpio->base + out_port);
+   gpiommgpio->out_state[index] &= ~gpio_mask;
+   gpiommgpio->out_state[index] |= bitmask;
+   outb(gpiommgpio->out_state[index], port_addr);
 
spin_unlock_irqrestore(>lock, flags);
-
-   /* prepare for next gpio register set */
-   mask[BIT_WORD(i)] >>= gpio_reg_size;
-   bits[BIT_WORD(i)] >>= gpio_reg_size;
}
 }
 
-- 
2.21.0



[PATCH v13 04/11] gpio: 104-idi-48: Utilize for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-104-idi-48.c | 36 +++---
 1 file changed, 7 insertions(+), 29 deletions(-)

diff --git a/drivers/gpio/gpio-104-idi-48.c b/drivers/gpio/gpio-104-idi-48.c
index 88dc6f2449f6..9b43964b0412 100644
--- a/drivers/gpio/gpio-104-idi-48.c
+++ b/drivers/gpio/gpio-104-idi-48.c
@@ -93,42 +93,20 @@ static int idi_48_gpio_get_multiple(struct gpio_chip *chip, 
unsigned long *mask,
unsigned long *bits)
 {
struct idi_48_gpio *const idi48gpio = gpiochip_get_data(chip);
-   size_t i;
+   unsigned long offset;
+   unsigned long gpio_mask;
static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
+   unsigned int port_addr;
unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
+   for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
+   port_addr = idi48gpio->base + ports[offset / 8];
+   port_state = inb(port_addr) & gpio_mask;
 
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
-
-   /* read bits from current gpio port */
-   port_state = inb(idi48gpio->base + ports[i]);
-
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, port_state, offset);
}
 
return 0;
-- 
2.21.0



[PATCH v13 03/11] gpio: 104-dio-48e: Utilize for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Replace verbose implementation in get_multiple/set_multiple callbacks
with for_each_set_clump8 macro to simplify code and improve clarity.

Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 drivers/gpio/gpio-104-dio-48e.c | 73 ++---
 1 file changed, 21 insertions(+), 52 deletions(-)

diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index 92c8f944bf64..2fc6d2b11d25 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -183,46 +183,25 @@ static int dio48e_gpio_get(struct gpio_chip *chip, 
unsigned offset)
return !!(port_state & mask);
 }
 
+static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
+
 static int dio48e_gpio_get_multiple(struct gpio_chip *chip, unsigned long 
*mask,
unsigned long *bits)
 {
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
-   size_t i;
-   static const size_t ports[] = { 0, 1, 2, 4, 5, 6 };
-   const unsigned int gpio_reg_size = 8;
-   unsigned int bits_offset;
-   size_t word_index;
-   unsigned int word_offset;
-   unsigned long word_mask;
-   const unsigned long port_mask = GENMASK(gpio_reg_size - 1, 0);
+   unsigned long offset;
+   unsigned long gpio_mask;
+   unsigned int port_addr;
unsigned long port_state;
 
/* clear bits array to a clean slate */
bitmap_zero(bits, chip->ngpio);
 
-   /* get bits are evaluated a gpio port register at a time */
-   for (i = 0; i < ARRAY_SIZE(ports); i++) {
-   /* gpio offset in bits array */
-   bits_offset = i * gpio_reg_size;
-
-   /* word index for bits array */
-   word_index = BIT_WORD(bits_offset);
-
-   /* gpio offset within current word of bits array */
-   word_offset = bits_offset % BITS_PER_LONG;
-
-   /* mask of get bits for current gpio within current word */
-   word_mask = mask[word_index] & (port_mask << word_offset);
-   if (!word_mask) {
-   /* no get bits in this port so skip to next one */
-   continue;
-   }
-
-   /* read bits from current gpio port */
-   port_state = inb(dio48egpio->base + ports[i]);
+   for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
+   port_addr = dio48egpio->base + ports[offset / 8];
+   port_state = inb(port_addr) & gpio_mask;
 
-   /* store acquired bits at respective bits array offset */
-   bits[word_index] |= (port_state << word_offset) & word_mask;
+   bitmap_set_value8(bits, port_state, offset);
}
 
return 0;
@@ -252,37 +231,27 @@ static void dio48e_gpio_set_multiple(struct gpio_chip 
*chip,
unsigned long *mask, unsigned long *bits)
 {
struct dio48e_gpio *const dio48egpio = gpiochip_get_data(chip);
-   unsigned int i;
-   const unsigned int gpio_reg_size = 8;
-   unsigned int port;
-   unsigned int out_port;
-   unsigned int bitmask;
+   unsigned long offset;
+   unsigned long gpio_mask;
+   size_t index;
+   unsigned int port_addr;
+   unsigned long bitmask;
unsigned long flags;
 
-   /* set bits are evaluated a gpio register size at a time */
-   for (i = 0; i < chip->ngpio; i += gpio_reg_size) {
-   /* no more set bits in this mask word; skip to the next word */
-   if (!mask[BIT_WORD(i)]) {
-   i = (BIT_WORD(i) + 1) * BITS_PER_LONG - gpio_reg_size;
-   continue;
-   }
+   for_each_set_clump8(offset, gpio_mask, mask, ARRAY_SIZE(ports) * 8) {
+   index = offset / 8;
+   port_addr = dio48egpio->base + ports[index];
 
-   port = i / gpio_reg_size;
-   out_port = (port > 2) ? port + 1 : port;
-   bitmask = mask[BIT_WORD(i)] & bits[BIT_WORD(i)];
+   bitmask = bitmap_get_value8(bits, offset) & gpio_mask;
 
raw_spin_lock_irqsave(>lock, flags);
 
/* update output state data and set device gpio register */
-   dio48egpio->out_state[port] &= ~mask[BIT_WORD(i)];
-   dio48egpio->out_state[port] |= bitmask;
-   outb(dio48egpio->out_state[port], dio48egpio->base + out_port);
+   dio48egpio->out_state[index] &= ~gpio_mask;
+   dio48egpio->out_state[index] |= bitmask;
+   outb(dio48egpio->out_state[index], port_addr);
 
raw_spin_unlock_irqrestore(>lock, flags);
-
-   /* prepare for next gpio register set */
-   mask[BIT_WORD(i)] >>= gpio_reg_size;
-   bits[BIT_WORD(i)] >>= gpio_reg_size;
}
 }
 
-- 
2.21.0



[PATCH v13 02/11] lib/test_bitmap.c: Add for_each_set_clump8 test cases

2019-03-26 Thread William Breathitt Gray
The introduction of the for_each_set_clump8 macro warrants test cases to
verify the implementation. This patch adds test case checks for whether
an out-of-bounds clump index is returned, a zero clump is returned, or
the returned clump value differs from the expected clump value.

Cc: Rasmus Villemoes 
Acked-by: Andrew Morton 
Reviewed-by: Andy Shevchenko 
Reviewed-by: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 lib/test_bitmap.c | 65 +++
 1 file changed, 65 insertions(+)

diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c
index 6cd7d0740005..8d1f268069c1 100644
--- a/lib/test_bitmap.c
+++ b/lib/test_bitmap.c
@@ -88,6 +88,36 @@ __check_eq_u32_array(const char *srcfile, unsigned int line,
return true;
 }
 
+static bool __init __check_eq_clump8(const char *srcfile, unsigned int line,
+   const unsigned int offset,
+   const unsigned int size,
+   const unsigned char *const clump_exp,
+   const unsigned long *const clump)
+{
+   unsigned long exp;
+
+   if (offset >= size) {
+   pr_warn("[%s:%u] bit offset for clump out-of-bounds: expected 
less than %u, got %u\n",
+   srcfile, line, size, offset);
+   return false;
+   }
+
+   exp = clump_exp[offset / 8];
+   if (!exp) {
+   pr_warn("[%s:%u] bit offset for zero clump: expected nonzero 
clump, got bit offset %u with clump value 0",
+   srcfile, line, offset);
+   return false;
+   }
+
+   if (*clump != exp) {
+   pr_warn("[%s:%u] expected clump value of 0x%lX, got clump value 
of 0x%lX",
+   srcfile, line, exp, *clump);
+   return false;
+   }
+
+   return true;
+}
+
 #define __expect_eq(suffix, ...)   \
({  \
int result = 0; \
@@ -104,6 +134,7 @@ __check_eq_u32_array(const char *srcfile, unsigned int line,
 #define expect_eq_bitmap(...)  __expect_eq(bitmap, ##__VA_ARGS__)
 #define expect_eq_pbl(...) __expect_eq(pbl, ##__VA_ARGS__)
 #define expect_eq_u32_array(...)   __expect_eq(u32_array, ##__VA_ARGS__)
+#define expect_eq_clump8(...)  __expect_eq(clump8, ##__VA_ARGS__)
 
 static void __init test_zero_clear(void)
 {
@@ -361,6 +392,39 @@ static void noinline __init test_mem_optimisations(void)
}
 }
 
+static const unsigned char clump_exp[] __initconst = {
+   0x01,   /* 1 bit set */
+   0x02,   /* non-edge 1 bit set */
+   0x00,   /* zero bits set */
+   0x38,   /* 3 bits set across 4-bit boundary */
+   0x38,   /* Repeated clump */
+   0x0F,   /* 4 bits set */
+   0xFF,   /* all bits set */
+   0x05,   /* non-adjacent 2 bits set */
+};
+
+static void __init test_for_each_set_clump8(void)
+{
+#define CLUMP_EXP_NUMBITS 64
+   DECLARE_BITMAP(bits, CLUMP_EXP_NUMBITS);
+   unsigned int start;
+   unsigned long clump;
+
+   /* set bitmap to test case */
+   bitmap_zero(bits, CLUMP_EXP_NUMBITS);
+   bitmap_set(bits, 0, 1); /* 0x01 */
+   bitmap_set(bits, 9, 1); /* 0x02 */
+   bitmap_set(bits, 27, 3);/* 0x28 */
+   bitmap_set(bits, 35, 3);/* 0x28 */
+   bitmap_set(bits, 40, 4);/* 0x0F */
+   bitmap_set(bits, 48, 8);/* 0xFF */
+   bitmap_set(bits, 56, 1);/* 0x05 - part 1 */
+   bitmap_set(bits, 58, 1);/* 0x05 - part 2 */
+
+   for_each_set_clump8(start, clump, bits, CLUMP_EXP_NUMBITS)
+   expect_eq_clump8(start, CLUMP_EXP_NUMBITS, clump_exp, );
+}
+
 static int __init test_bitmap_init(void)
 {
test_zero_clear();
@@ -369,6 +433,7 @@ static int __init test_bitmap_init(void)
test_bitmap_arr32();
test_bitmap_parselist();
test_mem_optimisations();
+   test_for_each_set_clump8();
 
if (failed_tests == 0)
pr_info("all %u tests passed\n", total_tests);
-- 
2.21.0



Re: Bad file pattern in MAINTAINERS section 'KEYS-TRUSTED'

2019-03-26 Thread Jarkko Sakkinen
On Tue, Mar 26, 2019 at 09:59:40AM -0500, Denis Kenzior wrote:
> Hi James,
> 
> On 03/26/2019 09:25 AM, James Bottomley wrote:
> > Looking at the contents of linux/keys/trusted.h, it looks like the
> > wrong decision to move it.  The contents are way too improperly named
> > and duplicative to be in a standard header.  It's mostly actually TPM
> > code including a redefinition of the tpm_buf structure, so it doesn't
> > even seem to be necessary for trusted keys.
> The reason this was done was because asym_tpm.c needed a bunch of the same
> functionality already provided by trusted.c, e.g. TSS_authmac and friends.
> 
> > 
> > If you want to fix this as a bug, I'd move it back again, but long term
> > I think it should simply be combined with trusted.c because nothing
> > else can include it sanely anyway.
> 
> Ideally I'd like to see the TPM subsystem expose these functions using some
> proper API / library abstraction.  David Howells had an RFC patch set that
> tried to address some of this a while back.  Not sure if that went anywhere.

I think it'd be best to expose tpm_buf API to outside and allow trusted
keys code to construct the TPM commands. It is a single consumer use
(e.g. not like PCR operations where it does make sense to consolidate
to the TPM subsystem).

/Jarkko


[PATCH v13 01/11] bitops: Introduce the for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
This macro iterates for each 8-bit group of bits (clump) with set bits,
within a bitmap memory region. For each iteration, "start" is set to the
bit offset of the found clump, while the respective clump value is
stored to the location pointed by "clump". Additionally, the
bitmap_get_value8 and bitmap_set_value8 functions are introduced to
respectively get and set an 8-bit value in a bitmap memory region.

Suggested-by: Andy Shevchenko 
Suggested-by: Rasmus Villemoes 
Suggested-by: Lukas Wunner 
Cc: Arnd Bergmann 
Cc: Andrew Morton 
Cc: Andy Shevchenko 
Cc: Linus Walleij 
Signed-off-by: William Breathitt Gray 
---
 include/asm-generic/bitops/find.h | 11 ++
 include/linux/bitops.h|  5 +++
 lib/find_bit.c| 58 +++
 3 files changed, 74 insertions(+)

diff --git a/include/asm-generic/bitops/find.h 
b/include/asm-generic/bitops/find.h
index 8a1ee10014de..b0a99035f64f 100644
--- a/include/asm-generic/bitops/find.h
+++ b/include/asm-generic/bitops/find.h
@@ -80,4 +80,15 @@ extern unsigned long find_first_zero_bit(const unsigned long 
*addr,
 
 #endif /* CONFIG_GENERIC_FIND_FIRST_BIT */
 
+unsigned long bitmap_get_value8(const unsigned long *addr, unsigned long 
start);
+
+void bitmap_set_value8(unsigned long *addr, unsigned long value,
+  unsigned long start);
+
+unsigned long find_next_clump8(unsigned long *clump, const unsigned long *addr,
+  unsigned long size, unsigned long offset);
+
+#define find_first_clump8(clump, bits, size) \
+   find_next_clump8((clump), (bits), (size), 0)
+
 #endif /*_ASM_GENERIC_BITOPS_FIND_H_ */
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index 602af23b98c7..1d9b5efb9bd4 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -40,6 +40,11 @@ extern unsigned long __sw_hweight64(__u64 w);
 (bit) < (size);\
 (bit) = find_next_zero_bit((addr), (size), (bit) + 1))
 
+#define for_each_set_clump8(start, clump, bits, size) \
+   for ((start) = find_first_clump8(&(clump), (bits), (size)); \
+(start) < (size); \
+(start) = find_next_clump8(&(clump), (bits), (size), (start) + 8))
+
 static inline int get_bitmask_order(unsigned int count)
 {
int order;
diff --git a/lib/find_bit.c b/lib/find_bit.c
index ee3df93ba69a..71a4e0a31e40 100644
--- a/lib/find_bit.c
+++ b/lib/find_bit.c
@@ -218,3 +218,61 @@ EXPORT_SYMBOL(find_next_bit_le);
 #endif
 
 #endif /* __BIG_ENDIAN */
+
+/**
+ * bitmap_get_value8 - get an 8-bit value within a memory region
+ * @addr: address to the bitmap memory region
+ * @start: bit offset of the 8-bit value; must be a multiple of 8
+ *
+ * Returns the 8-bit value located at the @start bit offset within the @addr
+ * memory region.
+ */
+unsigned long bitmap_get_value8(const unsigned long *addr, unsigned long start)
+{
+   const size_t idx = BIT_WORD(start);
+   const unsigned long offset = start % BITS_PER_LONG;
+
+   return (addr[idx] >> offset) & 0xFF;
+}
+EXPORT_SYMBOL(bitmap_get_value8);
+
+/**
+ * bitmap_set_value8 - set an 8-bit value within a memory region
+ * @addr: address to the bitmap memory region
+ * @value: the 8-bit value; values wider than 8 bits may clobber bitmap
+ * @start: bit offset of the 8-bit value; must be a multiple of 8
+ */
+void bitmap_set_value8(unsigned long *addr, unsigned long value,
+  unsigned long start)
+{
+   const size_t idx = BIT_WORD(start);
+   const unsigned long offset = start % BITS_PER_LONG;
+
+   addr[idx] &= ~(0xFF << offset);
+   addr[idx] |= value << offset;
+}
+EXPORT_SYMBOL(bitmap_set_value8);
+
+/**
+ * find_next_clump8 - find next 8-bit clump with set bits in a memory region
+ * @clump: location to store copy of found clump
+ * @addr: address to base the search on
+ * @size: bitmap size in number of bits
+ * @offset: bit offset at which to start searching
+ *
+ * Returns the bit offset for the next set clump; the found clump value is
+ * copied to the location pointed by @clump. If no bits are set, returns @size.
+ */
+unsigned long find_next_clump8(unsigned long *clump, const unsigned long *addr,
+  unsigned long size, unsigned long offset)
+{
+   offset = find_next_bit(addr, size, offset);
+   if (offset == size)
+   return size;
+
+   offset = round_down(offset, 8);
+   *clump = bitmap_get_value8(addr, offset);
+
+   return offset;
+}
+EXPORT_SYMBOL(find_next_clump8);
-- 
2.21.0



[PATCH v13 00/11] Introduce the for_each_set_clump8 macro

2019-03-26 Thread William Breathitt Gray
Changes in v13:
  - Reimplement find_next_clump8 to leverage find_next_bit
  - Restrict bitmap_get_value8/bitmap_set_value8 start argument to
values that are multiples of 8; this prevents cases where a clump
lands between word boundaries
  - Trim const qualifiers from bitmap_get_value8, bitmap_set_value8, and
find_next_clump8; this should help improve readability of the code
  - Redefine parameter list for bitmap_get_value8, bitmap_set_value8,
and find_next_clump8 to use unsigned long in order to match the
find_next_bit data types and naming conventions

While adding GPIO get_multiple/set_multiple callback support for various
drivers, I noticed a pattern of looping manifesting that would be useful
standardized as a macro.

This patchset introduces the for_each_set_clump8 macro and utilizes it
in several GPIO drivers. The for_each_set_clump macro8 facilitates a
for-loop syntax that iterates over a memory region entire groups of set
bits at a time.

For example, suppose you would like to iterate over a 32-bit integer 8
bits at a time, skipping over 8-bit groups with no set bit, where
 represents the current 8-bit group:

Example:1010   00110011
First loop: 1010   
Second loop:1010   00110011
Third loop:    00110011

Each iteration of the loop returns the next 8-bit group that has at
least one set bit.

The for_each_set_clump8 macro has four parameters:

* start: set to the bit offset of the current clump
* clump: set to the current clump value
* bits: bitmap to search within
* size: bitmap size in number of bits

In this version of the patchset, the for_each_set_clump macro has been
reimplemented and simplified based on the suggestions provided by Rasmus
Villemoes and Andy Shevchenko in the version 4 submission.

In particular, the function of the for_each_set_clump macro has been
restricted to handle only 8-bit clumps; the drivers that use the
for_each_set_clump macro only handle 8-bit ports so a generic
for_each_set_clump implementation is not necessary. Thus, a solution for
large clumps (i.e. those larger than the width of a bitmap word) can be
postponed until a driver appears that actually requires such a generic
for_each_set_clump implementation.

For what it's worth, a semi-generic for_each_set_clump (i.e. for clumps
smaller than the width of a bitmap word) can be implemented by simply
replacing the hardcoded '8' and '0xFF' instances with respective
variables. I have not yet had a need for such an implementation, and
since it falls short of a true generic for_each_set_clump function, I
have decided to forgo such an implementation for now.

In addition, the bitmap_get_value8 and bitmap_set_value8 functions are
introduced to get and set 8-bit values respectively. Their use is based
on the behavior suggested in the patchset version 4 review.

William Breathitt Gray (11):
  bitops: Introduce the for_each_set_clump8 macro
  lib/test_bitmap.c: Add for_each_set_clump8 test cases
  gpio: 104-dio-48e: Utilize for_each_set_clump8 macro
  gpio: 104-idi-48: Utilize for_each_set_clump8 macro
  gpio: gpio-mm: Utilize for_each_set_clump8 macro
  gpio: ws16c48: Utilize for_each_set_clump8 macro
  gpio: pci-idio-16: Utilize for_each_set_clump8 macro
  gpio: pcie-idio-24: Utilize for_each_set_clump8 macro
  gpio: uniphier: Utilize for_each_set_clump8 macro
  gpio: 74x164: Utilize the for_each_set_clump8 macro
  thermal: intel: intel_soc_dts_iosf: Utilize for_each_set_clump8 macro

 drivers/gpio/gpio-104-dio-48e.c|  73 --
 drivers/gpio/gpio-104-idi-48.c |  36 ++-
 drivers/gpio/gpio-74x164.c |  19 ++--
 drivers/gpio/gpio-gpio-mm.c|  73 --
 drivers/gpio/gpio-pci-idio-16.c|  75 +-
 drivers/gpio/gpio-pcie-idio-24.c   | 109 -
 drivers/gpio/gpio-uniphier.c   |  16 ++-
 drivers/gpio/gpio-ws16c48.c|  73 --
 drivers/thermal/intel/intel_soc_dts_iosf.c |  29 +++---
 drivers/thermal/intel/intel_soc_dts_iosf.h |   2 -
 include/asm-generic/bitops/find.h  |  11 +++
 include/linux/bitops.h |   5 +
 lib/find_bit.c |  58 +++
 lib/test_bitmap.c  |  65 
 14 files changed, 307 insertions(+), 337 deletions(-)

-- 
2.21.0



Re: Bad file pattern in MAINTAINERS section 'KEYS-TRUSTED'

2019-03-26 Thread Jarkko Sakkinen
On Tue, Mar 26, 2019 at 07:25:17AM -0700, James Bottomley wrote:
> On Tue, 2019-03-26 at 08:10 -0400, Mimi Zohar wrote:
> > Hi Jarrko,
> > 
> > On Tue, 2019-03-26 at 13:37 +0200, Jarkko Sakkinen wrote:
> > > Mimi,
> > > 
> > > Can you fix this and I can ack and send PR through my tree?
> > 
> > Making the "trusted.h" include file public was part of David's "KEYS:
> > Support TPM-wrapped key and crypto ops" patch set.  I wasn't involved
> > in reviewing or upstreaming this patch set.  As I recall, it was
> > upstreamed rather quickly without much review.  As it is TPM related,
> > it should have at least been posted on the linux-integrity mailing
> > list.  I have no idea if "trusted.h" should have been made public.
> > 
> > I'm not sure just "fixing" the MAINTAINERS file is the right
> > solution.  I was hoping to look at it later this week.  Perhaps you
> > and James could take a look?
> 
> Looking at the contents of linux/keys/trusted.h, it looks like the
> wrong decision to move it.  The contents are way too improperly named
> and duplicative to be in a standard header.  It's mostly actually TPM
> code including a redefinition of the tpm_buf structure, so it doesn't
> even seem to be necessary for trusted keys.
> 
> If you want to fix this as a bug, I'd move it back again, but long term
> I think it should simply be combined with trusted.c because nothing
> else can include it sanely anyway.


Fully agree with the long term plan.

I think it would be better to take the TPM2 trusted keys code from the
driver to the keyring subsystem once TPM1 trusted keys code has been
converted to use tpm_buf.

I don't also know any good reason for the core TPM driver to be compiled
as a module. It is just makes the kernel build configuration more
awkward. Would be nice to get the TPM callable from any subsystem
without fuzz. There is no a production use case for "TPM as an LKM"
(obviously drivers for different types of TPM hardware must and will
be compilable as LKM's).


/Jarkko


Re: [PATCH 03/17] fpga: dfl: fme: support 512bit data width PR

2019-03-26 Thread Wu Hao
On Tue, Mar 26, 2019 at 04:22:34PM -0500, Scott Wood wrote:
> On Tue, 2019-03-26 at 14:33 -0500, Alan Tull wrote:
> > On Mon, Mar 25, 2019 at 5:58 PM Scott Wood  wrote:
> > 
> > Hi Scott,
> > 
> > > On Mon, 2019-03-25 at 17:53 -0500, Scott Wood wrote:
> > > > On Mon, 2019-03-25 at 11:07 +0800, Wu Hao wrote:
> > > > > +#if defined(CONFIG_X86) && defined(CONFIG_AS_AVX512)
> > > > > +
> > > > > +#include 
> > > > > +
> > > > > +static inline void copy512(void *src, void __iomem *dst)
> > > > > +{
> > > > > +   kernel_fpu_begin();
> > > > > +
> > > > > +   asm volatile("vmovdqu64 (%0), %%zmm0;"
> > > > > +"vmovntdq %%zmm0, (%1);"
> > > > > +:
> > > > > +: "r"(src), "r"(dst));
> > > > > +
> > > > > +   kernel_fpu_end();
> > > > > +}
> > > > 
> > > > Shouldn't there be some sort of check that AVX512 is actually
> > > > supported
> > > > on the running system?
> > > > 
> > > > Also, src should be const, and the asm statement should have a memory
> > > > clobber.

Yes, I will fix this in the next version.

> > > > 
> > > > > +#else
> > > > > +static inline void copy512(void *src, void __iomem *dst)
> > > > > +{
> > > > > +   WARN_ON_ONCE(1);
> > > > > +}
> > > > > +#endif
> > > > 
> > > > Likewise, this will be called if a revision 2 device is used on non-
> > > > x86
> > > > (or on x86 with an old binutils).  The driver should fall back to 32-
> > > > bit
> > > > in such cases.

Unfortunately revision 2 is only for integrated FPGA solution, and it doesn't
support any fallback solution (original 32bit data partial reconfiguration is
not supported any more), so driver has to WARN in such path.

> > > 
> > > Sorry, I missed the comment about revision 2 only being on integrated
> > > devices -- but will that always be the case?  Seems worthwhile to check
> > > for
> > > AVX512 support anyway.  And there's still the possibility of being built
> > > with an old binutils such that CONFIG_AS_AVX512 is not set, or running
> > > on a
> > > kernel where avx512 was disabled via a boot option.
> > 
> > The code checks for CONFIG_AS_AVX512 above.
> 
> That just indicates that binutils supports it.  Plus, the code does not
> check for CONFIG_AS_AVX512 when deciding whether to set pr_datawidth to 64
> (and thus call copy512), so you'll get a WARN_ON rather than falling back to
> 32-bit.
> 
> > What boot option are you referring to?
> 
> clearcpuid=304

Just tried it, my system was down after running above AVX512 with this option.

I agree that it needs to add some check code to make sure it's safe to run
such instructions. I will add some cpu_feature_enabled() check in the next
version.

Thanks a lot for the review and comments.

Hao

> 
> -Scott
> 


Re: [PATCH] Input: elan_i2c - Add i2c_reset in sysfs for ELAN touchpad recovery

2019-03-26 Thread Dmitry Torokhov
Hi KT,

On Sat, Feb 02, 2019 at 03:54:56PM +0800, KT Liao wrote:
> Roger from SUSE reported the touchpad on Lenovo yoga2 crush sometimes.
> He found that rmmod/modprobe elan_i2c will recover the issue.
> He add the workaround on SUSE and solve the problem.
> Recently, the workaround fails in kernel 4.20 becasue IRQ mismatch.
> genirq: Flags mismatch irq 0. 2002 (ELAN0600:00) vs. 00015a00 (timer)
> I can't reproduce the issue in SUSE with the same kernel.
> And it's a 5 years old laptop, ELAN can't find the module for testing.
> Instead of IRQ debugging IRQ, I tried another approach.
> I added i2c_reset in sysfs to avoid IRQ requesting in probe.

How will users discover this flag? I do not think this is the best
approach. Can we detect that the touchpad firmware crashed from the
kernel and reset automatically?

Thanks.

> 
> Signed-off-by: KT Liao 
> Acked-by: Roger Whittaker 
> ---
>  drivers/input/mouse/elan_i2c_core.c | 25 +
>  1 file changed, 25 insertions(+)
> 
> diff --git a/drivers/input/mouse/elan_i2c_core.c 
> b/drivers/input/mouse/elan_i2c_core.c
> index 2690a4b..388b1f0 100644
> --- a/drivers/input/mouse/elan_i2c_core.c
> +++ b/drivers/input/mouse/elan_i2c_core.c
> @@ -670,6 +670,29 @@ static ssize_t calibrate_store(struct device *dev,
>   return retval ?: count;
>  }
>  
> +static ssize_t i2c_reset_store(struct device *dev,
> +struct device_attribute *attr,
> +const char *buf, size_t count)
> +{
> + struct i2c_client *client = to_i2c_client(dev);
> + struct elan_tp_data *data = i2c_get_clientdata(client);
> + int retval;
> +
> + retval = mutex_lock_interruptible(>sysfs_mutex);
> + if (retval)
> + return retval;
> +
> + disable_irq(client->irq);
> +
> + retval = elan_initialize(data);
> + if (retval)
> + dev_err(dev, "failed to re-initialize touchpad: %d\n", retval);
> +
> + enable_irq(client->irq);
> + mutex_unlock(>sysfs_mutex);
> + return retval ?: count;
> +}
> +
>  static ssize_t elan_sysfs_read_mode(struct device *dev,
>   struct device_attribute *attr,
>   char *buf)
> @@ -702,6 +725,7 @@ static DEVICE_ATTR(mode, S_IRUGO, elan_sysfs_read_mode, 
> NULL);
>  static DEVICE_ATTR(update_fw, S_IWUSR, NULL, elan_sysfs_update_fw);
>  
>  static DEVICE_ATTR_WO(calibrate);
> +static DEVICE_ATTR_WO(i2c_reset);
>  
>  static struct attribute *elan_sysfs_entries[] = {
>   _attr_product_id.attr,
> @@ -710,6 +734,7 @@ static struct attribute *elan_sysfs_entries[] = {
>   _attr_iap_version.attr,
>   _attr_fw_checksum.attr,
>   _attr_calibrate.attr,
> + _attr_i2c_reset.attr,
>   _attr_mode.attr,
>   _attr_update_fw.attr,
>   NULL,
> -- 
> 2.7.4
> 

-- 
Dmitry


Re: [RFC PATCH] x86/entry/64: randomize kernel stack offset upon syscall

2019-03-26 Thread Andy Lutomirski
On Tue, Mar 26, 2019 at 3:35 AM Reshetova, Elena
 wrote:
>
> > On Mon, Mar 18, 2019 at 1:16 PM Andy Lutomirski  wrote:
> > > On Mon, Mar 18, 2019 at 2:41 AM Elena Reshetova
> > >  wrote:
> > > > Performance:
> > > >
> > > > 1) lmbench: ./lat_syscall -N 100 null
> > > > base: Simple syscall: 0.1774 microseconds
> > > > random_offset (rdtsc): Simple syscall: 0.1803 microseconds
> > > > random_offset (rdrand): Simple syscall: 0.3702 microseconds
> > > >
> > > > 2)  Andy's tests, misc-tests: ./timing_test_64 10M sys_enosys
> > > > base: 1000 loops in 1.62224s = 162.22 nsec 
> > > > / loop
> > > > random_offset (rdtsc): 1000 loops in 1.64660s = 164.66 nsec 
> > > > / loop
> > > > random_offset (rdrand): 1000 loops in 3.51315s = 351.32 nsec / 
> > > > loop
> > > >
> > >
> > > Egads!  RDTSC is nice and fast but probably fairly easy to defeat.
> > > RDRAND is awful.  I had hoped for better.
> >
> > RDRAND can also fail.
> >
> > > So perhaps we need a little percpu buffer that collects 64 bits of
> > > randomness at a time, shifts out the needed bits, and refills the
> > > buffer when we run out.
> >
> > I'd like to avoid saving the _exact_ details of where the next offset
> > will be, but if nothing else works, this should be okay. We can use 8
> > bits at a time and call prandom_u32() every 4th call. Something like
> > prandom_bytes(), but where it doesn't throw away the unused bytes.
>
> Actually I think this would make the end result even worse security-wise
> than simply using rdtsc() on every syscall. Saving the randomness in percpu
> buffer, which is probably easily accessible and can be probed if needed,
> would supply attacker with much more knowledge about the next 3-4
> random offsets that what he would get if we use "weak" rdtsc. Given
> that for a successful exploit, an attacker would need to have stack aligned
> once only, having a knowledge of 3-4 next offsets sounds like a present to an
> exploit writer...  Additionally it creates complexity around the code that I
> have issues justifying with "security" argument because of above...
>
> I have the patch now with alloca() and rdtsc() working, I can post it
> (albeit it is very simple), but I am really hesitating on adding the percpu
> buffer randomness storage to it...
>

Hmm.  I guess it depends on what types of attack you care about.  I
bet that, if you do a bunch of iterations of mfence;rdtsc;syscall,
you'll discover that the offset between the user rdtsc and the
syscall's rdtsc has several values that occur with high probability.

--Andy


Re: linux-next: build failure after merge of the sound-asoc tree

2019-03-26 Thread Michael Ellerman
Mark Brown  writes:
> On Tue, Mar 26, 2019 at 01:33:49PM +1100, Stephen Rothwell wrote:
>
>> After merging the sound-asoc tree, today's linux-next build (powerpc
>> allyesconfig) failed like this:
>
>> sound/soc/codecs/tlv320aic32x4-clk.c: In function 'clk_aic32x4_pll_prepare':
>> include/linux/kernel.h:979:32: error: dereferencing pointer to incomplete 
>> type 'struct clk_hw'
>>   BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \
>> ^~
>
> Hrm, seems PowerPC is still not using the common clock API - is there
> any plan for that?  There are some ASoC PowerPC uses so it's going to be
> a bit of an issue as we expand our use of the clock API.

I don't know anything about the common clock API. What would it involve
for powerpc to use it?

cheers


Re: [PATCH] Input: elan_i2c - Add many hardware ID for lenovo laptop

2019-03-26 Thread Dmitry Torokhov
On Wed, Mar 13, 2019 at 08:17:43PM +0800, KT Liao wrote:
> There are many Lenovo laptop which need elan_i2c support.
> Elan collects the list ands add to add to elan_acpi_id[]
> 
> Signed-off-by: KT Liao 

Applied, thank you.

-- 
Dmitry


Re: [PATCH RESEND v3] tpm: fix an invalid condition in tpm_common_poll

2019-03-26 Thread Jarkko Sakkinen
On Tue, Mar 26, 2019 at 08:58:28AM -0700, Tadeusz Struk wrote:
> Hi Jarkko,
> On 3/25/19 7:09 AM, Jarkko Sakkinen wrote:
> > It is still missing the comment I asked to add. Otherwise, it is good.
> > 
> 
> Sorry, I didn't see your email with the suggestion earlier.
> To be honest I'm not sure if this comment adds much value, or if it is
> even correct. The poll doesn't "succeed" or "fail". It just returns
> a mask indicating if there is any data to read or if the user can write.
> 
> Isn't the commit message + 'git blame' enough to remember why it was
> done this way?

Comments in the code have also their time and place especially when
doing code reviews. Usually I like to have something in a site where
there has been a race even if it was for fairly trivial reason. If you
want to refine the comment to be more to the point, that is perfectly
fine.

/Jarkko


Re: [PATCH] input: keyboard: snvs: make sure irq is handled correctly

2019-03-26 Thread dmitry.torok...@gmail.com
Hi Anson,

On Wed, Mar 27, 2019 at 02:47:06AM +, Anson Huang wrote:
> SNVS IRQ is requested before necessary driver data initialized,
> if there is a pending IRQ during driver probe phase, kernel
> NULL pointer panic will occur in IRQ handler. To avoid such
> scenario, need to move the IRQ request to after driver data
> initialization done. This patch is inspired by NXP's internal
> kernel tree.
> 
> Fixes: d3dc6e232215 ("input: keyboard: imx: add snvs power key driver")
> Signed-off-by: Anson Huang 
> ---
>  drivers/input/keyboard/snvs_pwrkey.c | 17 -
>  1 file changed, 8 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/input/keyboard/snvs_pwrkey.c 
> b/drivers/input/keyboard/snvs_pwrkey.c
> index effb632..6ff41fd 100644
> --- a/drivers/input/keyboard/snvs_pwrkey.c
> +++ b/drivers/input/keyboard/snvs_pwrkey.c
> @@ -148,15 +148,6 @@ static int imx_snvs_pwrkey_probe(struct platform_device 
> *pdev)
>   return error;
>   }
>  
> - error = devm_request_irq(>dev, pdata->irq,
> -imx_snvs_pwrkey_interrupt,
> -0, pdev->name, pdev);
> -
> - if (error) {
> - dev_err(>dev, "interrupt not available.\n");
> - return error;
> - }
> -
>   error = input_register_device(input);
>   if (error < 0) {
>   dev_err(>dev, "failed to register input device\n");
> @@ -166,6 +157,14 @@ static int imx_snvs_pwrkey_probe(struct platform_device 
> *pdev)
>   pdata->input = input;
>   platform_set_drvdata(pdev, pdata);
>  
> + error = devm_request_irq(>dev, pdata->irq,
> +  imx_snvs_pwrkey_interrupt,
> +  0, pdev->name, pdev);
> + if (error) {
> + dev_err(>dev, "interrupt not available.\n");
> + return error;
> + }

Instead of moving devm_request_irq() around could you simply move
pdata->input = input assignment higher? It is perfectly fine to try
calling input_event() on input device that is allocated but not yet
registered.

> +
>   device_init_wakeup(>dev, pdata->wakeup);

Unrelated suggestion:

Can you try calling dev_pm_set_wake_irq(>dev, pdata->irq) here and
I think you will be able to get rid of suspend/resume methods in the
driver.

Thanks.

-- 
Dmitry


Re: [PATCH V31 25/25] debugfs: Disable open() when kernel is locked down

2019-03-26 Thread Andy Lutomirski
On Tue, Mar 26, 2019 at 5:31 PM Greg KH  wrote:
>
> On Tue, Mar 26, 2019 at 12:20:24PM -0700, Andy Lutomirski wrote:
> > On Tue, Mar 26, 2019 at 11:28 AM Matthew Garrett
> >  wrote:
> > >
> > > From: Matthew Garrett 
> > >
> > > debugfs has not been meaningfully audited in terms of ensuring that
> > > userland cannot trample over the kernel. At Greg's request, disable
> > > access to it entirely when the kernel is locked down. This is done at
> > > open() time rather than init time as the kernel lockdown status may be
> > > made stricter at runtime.
> >
> > Ugh.  Some of those files are very useful.  Could this perhaps still
> > allow O_RDONLY if we're in INTEGRITY mode?
>
> Useful for what?  Debugging, sure, but for "normal operation", no kernel
> functionality should ever require debugfs.  If it does, that's a bug and
> should be fixed.
>

I semi-regularly read files in debugfs to diagnose things, and I think
it would be good for this to work on distro kernels.


Re: [PATCH 5.0 00/52] 5.0.5-stable review

2019-03-26 Thread Naresh Kamboju
On Tue, 26 Mar 2019 at 12:09, Greg Kroah-Hartman
 wrote:
>
> This is the start of the stable review cycle for the 5.0.5 release.
> There are 52 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu Mar 28 04:26:38 UTC 2019.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> 
> https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.0.5-rc1.gz
> or in the git tree and branch at:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git 
> linux-5.0.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
>

Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.

Summary


kernel: 5.0.5-rc1
git repo: 
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git branch: linux-5.0.y
git commit: ebcb1bb407e721935a9b63a86b17bacb9a1bbe84
git describe: v5.0.4-53-gebcb1bb407e7
Test details: 
https://qa-reports.linaro.org/lkft/linux-stable-rc-5.0-oe/build/v5.0.4-53-gebcb1bb407e7


No regressions (compared to build v5.0.4)

No fixes (compared to build v5.0.4)

Ran 23108 total tests in the following environments and test suites.

Environments
--
- dragonboard-410c
- hi6220-hikey
- i386
- juno-r2
- qemu_arm
- qemu_arm64
- qemu_i386
- qemu_x86_64
- x15
- x86

Test Suites
---
* boot
* install-android-platform-tools-r2600
* kselftest
* libhugetlbfs
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-cpuhotplug-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-ipc-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* ltp-timers-tests
* perf
* spectre-meltdown-checker-test
* ltp-fs-tests
* ltp-open-posix-tests
* kselftest-vsyscall-mode-native
* kselftest-vsyscall-mode-none

-- 
Linaro LKFT
https://lkft.linaro.org


Re: [PATCH 4.19 00/45] 4.19.32-stable review

2019-03-26 Thread Naresh Kamboju
On Tue, 26 Mar 2019 at 12:06, Greg Kroah-Hartman
 wrote:
>
> This is the start of the stable review cycle for the 4.19.32 release.
> There are 45 patches in this series, all will be posted as a response
> to this one.  If anyone has any issues with these being applied, please
> let me know.
>
> Responses should be made by Thu Mar 28 04:26:41 UTC 2019.
> Anything received after that time might be too late.
>
> The whole patch series can be found in one patch at:
> 
> https://www.kernel.org/pub/linux/kernel/v4.x/stable-review/patch-4.19.32-rc1.gz
> or in the git tree and branch at:
> 
> git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git 
> linux-4.19.y
> and the diffstat can be found below.
>
> thanks,
>
> greg k-h
>

Results from Linaro’s test farm.
No regressions on arm64, arm, x86_64, and i386.

Summary


kernel: 4.19.32-rc1
git repo: 
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git
git branch: linux-4.19.y
git commit: 91ed293142f4947a4c5c2af1fc80aa91b3782642
git describe: v4.19.31-46-g91ed293142f4
Test details: 
https://qa-reports.linaro.org/lkft/linux-stable-rc-4.19-oe/build/v4.19.31-46-g91ed293142f4


No regressions (compared to build v4.19.31)

No fixes (compared to build v4.19.31)

Ran 23114 total tests in the following environments and test suites.

Environments
--
- dragonboard-410c - arm64
- hi6220-hikey - arm64
- i386
- juno-r2 - arm64
- qemu_arm
- qemu_arm64
- qemu_i386
- qemu_x86_64
- x15 - arm
- x86_64

Test Suites
---
* boot
* install-android-platform-tools-r2600
* kselftest
* libhugetlbfs
* ltp-cap_bounds-tests
* ltp-commands-tests
* ltp-containers-tests
* ltp-cpuhotplug-tests
* ltp-cve-tests
* ltp-dio-tests
* ltp-fcntl-locktests-tests
* ltp-filecaps-tests
* ltp-fs-tests
* ltp-fs_bind-tests
* ltp-fs_perms_simple-tests
* ltp-fsx-tests
* ltp-hugetlb-tests
* ltp-io-tests
* ltp-math-tests
* ltp-mm-tests
* ltp-nptl-tests
* ltp-pty-tests
* ltp-sched-tests
* ltp-securebits-tests
* ltp-syscalls-tests
* ltp-timers-tests
* perf
* spectre-meltdown-checker-test
* ltp-ipc-tests
* ltp-open-posix-tests
* kselftest-vsyscall-mode-native
* kselftest-vsyscall-mode-none

-- 
Linaro LKFT
https://lkft.linaro.org


Re: possible deadlock in acct_pin_kill

2019-03-26 Thread syzbot

syzbot has bisected this bug to:

commit e950564b97fd0f541b02eb207685d0746f5ecf29
Author: Miklos Szeredi 
Date:   Tue Jul 24 13:01:55 2018 +

vfs: don't evict uninitialized inode

bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=1212314320
start commit:   da5322e6 Merge tag 'selinux-pr-20181115' of git://git.kern..
git tree:   upstream
final crash:https://syzkaller.appspot.com/x/report.txt?x=1112314320
console output: https://syzkaller.appspot.com/x/log.txt?x=1612314320
kernel config:  https://syzkaller.appspot.com/x/.config?x=d86f24333880b605
dashboard link: https://syzkaller.appspot.com/bug?extid=2a73a6ea9507b7112141
syz repro:  https://syzkaller.appspot.com/x/repro.syz?x=1229853340
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=17ff545d40

Reported-by: syzbot+2a73a6ea9507b7112...@syzkaller.appspotmail.com
Fixes: e950564b97fd ("vfs: don't evict uninitialized inode")

For information about bisection process see: https://goo.gl/tpsmEJ#bisection


linux-next: Tree for Mar 27

2019-03-26 Thread Stephen Rothwell
Hi all,

Changes since 20190326:

The bpf-next tree gained a conflict against the net tree.

The sound-asoc tree lost its build failure but gained another for which
I reverted 3 commits.

The drm-intel tree gained a build failure for which I reverted some
comits.

Non-merge commits (relative to Linus' tree): 3198
 2776 files changed, 86711 insertions(+), 44562 deletions(-)



I have created today's linux-next tree at
git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
(patches at http://www.kernel.org/pub/linux/kernel/next/ ).  If you
are tracking the linux-next tree using git, you should not use "git pull"
to do so as that will try to merge the new linux-next release with the
old one.  You should use "git fetch" and checkout or reset to the new
master.

You can see which trees have been included by looking in the Next/Trees
file in the source.  There are also quilt-import.log and merge.log
files in the Next directory.  Between each merge, the tree was built
with a ppc64_defconfig for powerpc, an allmodconfig for x86_64, a
multi_v7_defconfig for arm and a native build of tools/perf. After
the final fixups (if any), I do an x86_64 modules_install followed by
builds for x86_64 allnoconfig, powerpc allnoconfig (32 and 64 bit),
ppc44x_defconfig, allyesconfig and pseries_le_defconfig and i386, sparc
and sparc64 defconfig. And finally, a simple boot test of the powerpc
pseries_le_defconfig kernel in qemu (with and without kvm enabled).

Below is a summary of the state of the merge.

I am currently merging 299 trees (counting Linus' and 70 trees of bug
fix patches pending for the current merge release).

Stats about the size of the tree over time can be seen at
http://neuling.org/linux-next-size.html .

Status of my local build tests will be at
http://kisskb.ellerman.id.au/linux-next .  If maintainers want to give
advice about cross compilers/configs that work, we are always open to add
more builds.

Thanks to Randy Dunlap for doing many randconfig builds.  And to Paul
Gortmaker for triage and bug fixes.

-- 
Cheers,
Stephen Rothwell

$ git checkout master
$ git reset --hard stable
Merging origin/master (65ae689329c5 Merge tag 'for-5.1-rc2-tag' of 
git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux)
Merging fixes/master (b352face4ca9 adfs: mark expected switch fall-throughs)
Merging kspp-gustavo/for-next/kspp (1f7ae812f87e x86/syscalls: Mark expected 
switch fall-throughs)
Merging kbuild-current/fixes (688931a5ad4e kbuild: skip sub-make for in-tree 
build with GNU Make 4.x)
Merging arc-current/for-curr (172fe06c57b8 ARC: ioc: diasble ioc if HIGHMEM/PAE 
iso panic)
Merging arm-current/fixes (d410a8a49e3e ARM: 8849/1: NOMMU: Fix encodings for 
PMSAv8's PRBAR4/PRLAR4)
Merging arm64-fixes/for-next/fixes (e5a5af771861 arm64: remove obsolete 
selection of MULTI_IRQ_HANDLER)
Merging m68k-current/for-linus (28713169d879 m68k: Add -ffreestanding to CFLAGS)
Merging powerpc-fixes/fixes (92edf8df0ff2 powerpc/security: Fix spectre_v2 
reporting)
Merging sparc/master (7d762d69145a afs: Fix manually set volume location server 
list)
Merging fscrypt-current/for-stable (ae64f9bd1d36 Linux 4.15-rc2)
Merging net/master (8c838f53e149 dpaa2-eth: fix race condition with bql frame 
accounting)
Merging bpf/master (f52c97d9df98 bpf, doc: fix BTF docs reflow of bullet list)
Merging ipsec/master (01ce31c57b3f vti4: removed duplicate log message.)
Merging netfilter/master (5f543a54eec0 net: hns3: fix for not calculating tx bd 
num correctly)
Merging ipvs/master (b2e3d68d1251 netfilter: nft_compat: destroy function must 
not have side effects)
Merging wireless-drivers/master (526949e877f4 rxrpc: avoid clang 
-Wuninitialized warning)
Merging mac80211/master (d235c48b40d3 net: dsa: mv88e6xxx: power serdes on/off 
for 10G interfaces on 6390X)
Merging rdma-fixes/for-rc (8c2ffd917477 Linux 5.1-rc2)
Merging sound-current/for-linus (e2a829b3da01 ALSA: hda/realtek - Fix speakers 
on Acer Predator Helios 500 Ryzen laptops)
Merging sound-asoc-fixes/for-linus (3c87e7364daa Merge branch 'asoc-5.1' into 
asoc-linus)
Merging regmap-fixes/for-linus (9e98c678c2d6 Linux 5.1-rc1)
Merging regulator-fixes/for-linus (6b0c8dbad170 Merge branch 'regulator-5.1' 
into regulator-linus)
Merging spi-fixes/for-linus (7c8e7c47b3f2 Merge branch 'spi-5.1' into spi-linus)
Merging pci-current/for-linus (0fa635aec9ab PCI/LINK: Deduplicate bandwidth 
reports for multi-function devices)
Merging driver-core.current/driver-core-linus (cd1b772d4881 driver core: remove 
BUS_ATTR())
Merging tty.current/tty-linus (93bcefd4c6ba serial: sh-sci: Fix setting 
SCSCR_TIE while transferring data)
Merging usb.current/usb-linus (3d54d10c6afe usb: mtu3: fix EXTCON dependency)
Merging usb-gadget-fixes/fixes (072684e8c58d USB: gadget: f_hid: fix deadlock 
in f_hidg_write())
Merging usb-serial-fixes/usb-linus (2908b076f519 USB: serial: mos7720: fix 
mos_parport refcount imb

[PATCHv1 5/7] vfio/mdev: Follow correct remove sequence

2019-03-26 Thread Parav Pandit
mdev_remove_sysfs_files() should follow exact mirror sequence of a
create, similar to what is followed in error unwinding path of
mdev_create_sysfs_files().

Fixes: 6a62c1dfb5c7 ("vfio/mdev: Re-order sysfs attribute creation")
Reviewed-by: Maxim Levitsky 
Signed-off-by: Parav Pandit 
---
 drivers/vfio/mdev/mdev_sysfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index 5193a0e..cbf94b8 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -280,7 +280,7 @@ int  mdev_create_sysfs_files(struct device *dev, struct 
mdev_type *type)
 
 void mdev_remove_sysfs_files(struct device *dev, struct mdev_type *type)
 {
+   sysfs_remove_files(>kobj, mdev_device_attrs);
sysfs_remove_link(>kobj, "mdev_type");
sysfs_remove_link(type->devices_kobj, dev_name(dev));
-   sysfs_remove_files(>kobj, mdev_device_attrs);
 }
-- 
1.8.3.1



[PATCHv1 7/7] vfio/mdev: Fix race conditions with mdev device life cycle APIs

2019-03-26 Thread Parav Pandit
Below race condition and call trace exist with current device life cycle
sequence.

1. In following sequence, child devices created while removing mdev parent
device can be left out, or it may lead to race of removing half
initialized child mdev devices.

issue-1:

   cpu-0 cpu-1
   - -
  mdev_unregister_device()
 device_for_each_child()
mdev_device_remove_cb()
mdev_device_remove()
create_store()
  mdev_device_create()   [...]
   device_register()
  parent_remove_sysfs_files()
  /* BUG: device added by cpu-0
   * whose parent is getting removed.
   */

issue-2:

   cpu-0 cpu-1
   - -
create_store()
  mdev_device_create()   [...]
   device_register()

   [...]  mdev_unregister_device()
 device_for_each_child()
mdev_device_remove_cb()
mdev_device_remove()

   mdev_create_sysfs_files()
   /* BUG: create is adding
* sysfs files for a device
* which is undergoing removal.
*/
 parent_remove_sysfs_files()

2. Below crash is observed when user initiated remove is in progress
and mdev_unregister_driver() completes parent unregistration.

   cpu-0 cpu-1
   - -
remove_store()
   mdev_device_remove()
   active = false;
  mdev_unregister_device()
remove type
   [...]
   mdev_remove_ops() crashes.

This is similar race like create() racing with mdev_unregister_device().

mtty mtty: MDEV: Registered
iommu: Adding device 83b8f4f2-509f-382f-3c1e-e6bfe0fa1001 to group 57
vfio_mdev 83b8f4f2-509f-382f-3c1e-e6bfe0fa1001: MDEV: group_id = 57
mtty mtty: MDEV: Unregistering
mtty_dev: Unloaded!
BUG: unable to handle kernel paging request at c027d668
PGD af9818067 P4D af9818067 PUD af981a067 PMD 8583c3067 PTE 0
Oops:  [#1] SMP PTI
CPU: 15 PID: 3517 Comm: bash Kdump: loaded Not tainted 5.0.0-rc7-vdevbus+ #2
Hardware name: Supermicro SYS-6028U-TR4+/X10DRU-i+, BIOS 2.0b 08/09/2016
RIP: 0010:mdev_device_remove_ops+0x1a/0x50 [mdev]
Call Trace:
 mdev_device_remove+0xef/0x130 [mdev]
 remove_store+0x77/0xa0 [mdev]
 kernfs_fop_write+0x113/0x1a0
 __vfs_write+0x33/0x1b0
 ? rcu_read_lock_sched_held+0x64/0x70
 ? rcu_sync_lockdep_assert+0x2a/0x50
 ? __sb_start_write+0x121/0x1b0
 ? vfs_write+0x17c/0x1b0
 vfs_write+0xad/0x1b0
 ? trace_hardirqs_on_thunk+0x1a/0x1c
 ksys_write+0x55/0xc0
 do_syscall_64+0x5a/0x210

Therefore, mdev core is improved to overcome above issues.

Wait for any ongoing mdev create() and remove() to finish before
unregistering parent device using srcu. This continues to allow multiple
create and remove to progress in parallel. At the same time guard parent
removal while parent is being access by create() and remove callbacks.

mdev_device_remove() is refactored to not block on srcu when device is
removed as part of parent removal.

Fixes: 7b96953bc640 ("vfio: Mediated device Core driver")
Signed-off-by: Parav Pandit 
---
 drivers/vfio/mdev/mdev_core.c| 83 ++--
 drivers/vfio/mdev/mdev_private.h |  6 +++
 2 files changed, 77 insertions(+), 12 deletions(-)

diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index aefcf34..fa233c8 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -84,6 +84,7 @@ static void mdev_release_parent(struct kref *kref)
  ref);
struct device *dev = parent->dev;
 
+   cleanup_srcu_struct(>unreg_srcu);
kfree(parent);
put_device(dev);
 }
@@ -147,10 +148,30 @@ static int mdev_device_remove_ops(struct mdev_device 
*mdev, bool force_remove)
return 0;
 }
 
+static int mdev_device_remove_common(struct mdev_device *mdev,
+bool force_remove)
+{
+   struct mdev_type *type;
+   int ret;
+
+   type = to_mdev_type(mdev->type_kobj);
+
+   ret = mdev_device_remove_ops(mdev, force_remove);
+   if (ret && !force_remove) {
+   mutex_lock(_list_lock);
+   mdev->active = true;
+   mutex_unlock(_list_lock);
+   return ret;
+   }
+   mdev_remove_sysfs_files(>dev, type);
+   device_unregister(>dev);
+   return ret;
+}
+
 static int mdev_device_remove_cb(struct device *dev, void *data)
 {
if (dev_is_mdev(dev))
-   

[PATCHv1 6/7] vfio/mdev: Fix aborting mdev child device removal if one fails

2019-03-26 Thread Parav Pandit
device_for_each_child() stops executing callback function for remaining
child devices, if callback hits an error.
Each child mdev device is independent of each other.
While unregistering parent device, mdev core must remove all child mdev
devices.
Therefore, mdev_device_remove_cb() always returns success so that
device_for_each_child doesn't abort if one child removal hits error.

While at it, improve remove and unregister functions for below simplicity.

There isn't need to pass forced flag pointer during mdev parent
removal which invokes mdev_device_remove(). So simplify the flow.

mdev_device_remove() is called from two paths.
1. mdev_unregister_driver()
 mdev_device_remove_cb()
   mdev_device_remove()
2. remove_store()
 mdev_device_remove()

When device is removed by user using remote_store(), device under
removal is mdev device.
When device is removed during parent device removal using generic child
iterator, mdev check is already done using dev_is_mdev().

Hence, remove the unnecessary loop in mdev_device_remove().

Fixes: 7b96953bc640 ("vfio: Mediated device Core driver")
Reviewed-by: Maxim Levitsky 
Signed-off-by: Parav Pandit 
---
 drivers/vfio/mdev/mdev_core.c | 23 +--
 1 file changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 836d319..aefcf34 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -149,10 +149,10 @@ static int mdev_device_remove_ops(struct mdev_device 
*mdev, bool force_remove)
 
 static int mdev_device_remove_cb(struct device *dev, void *data)
 {
-   if (!dev_is_mdev(dev))
-   return 0;
+   if (dev_is_mdev(dev))
+   mdev_device_remove(dev, true);
 
-   return mdev_device_remove(dev, data ? *(bool *)data : true);
+   return 0;
 }
 
 /*
@@ -240,7 +240,6 @@ int mdev_register_device(struct device *dev, const struct 
mdev_parent_ops *ops)
 void mdev_unregister_device(struct device *dev)
 {
struct mdev_parent *parent;
-   bool force_remove = true;
 
mutex_lock(_list_lock);
parent = __find_parent_device(dev);
@@ -254,8 +253,7 @@ void mdev_unregister_device(struct device *dev)
list_del(>next);
class_compat_remove_link(mdev_bus_compat_class, dev, NULL);
 
-   device_for_each_child(dev, (void *)_remove,
- mdev_device_remove_cb);
+   device_for_each_child(dev, NULL, mdev_device_remove_cb);
 
parent_remove_sysfs_files(parent);
 
@@ -348,24 +346,13 @@ int mdev_device_create(struct kobject *kobj,
 
 int mdev_device_remove(struct device *dev, bool force_remove)
 {
-   struct mdev_device *mdev, *tmp;
+   struct mdev_device *mdev;
struct mdev_parent *parent;
struct mdev_type *type;
int ret;
 
mdev = to_mdev_device(dev);
-
mutex_lock(_list_lock);
-   list_for_each_entry(tmp, _list, next) {
-   if (tmp == mdev)
-   break;
-   }
-
-   if (tmp != mdev) {
-   mutex_unlock(_list_lock);
-   return -ENODEV;
-   }
-
if (!mdev->active) {
mutex_unlock(_list_lock);
return -EAGAIN;
-- 
1.8.3.1



[PATCHv1 1/7] vfio/mdev: Avoid release parent reference during error path

2019-03-26 Thread Parav Pandit
During mdev parent registration in mdev_register_device(),
if parent device is duplicate, it releases the reference of existing
parent device.
This is incorrect. Existing parent device should not be touched.

Fixes: 7b96953bc640 ("vfio: Mediated device Core driver")
Reviewed By: Kirti Wankhede 
Reviewed-by: Maxim Levitsky 
Signed-off-by: Parav Pandit 
---
 drivers/vfio/mdev/mdev_core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index b96fedc..1299d2e 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -181,6 +181,7 @@ int mdev_register_device(struct device *dev, const struct 
mdev_parent_ops *ops)
/* Check for duplicate */
parent = __find_parent_device(dev);
if (parent) {
+   parent = NULL;
ret = -EEXIST;
goto add_dev_err;
}
-- 
1.8.3.1



[PATCHv1 4/7] vfio/mdev: Avoid masking error code to EBUSY

2019-03-26 Thread Parav Pandit
Instead of masking return error to -EBUSY, return actual error
returned by the driver.

Reviewed-by: Maxim Levitsky 
Signed-off-by: Parav Pandit 
---
 drivers/vfio/mdev/mdev_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 00ca613..836d319 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -141,7 +141,7 @@ static int mdev_device_remove_ops(struct mdev_device *mdev, 
bool force_remove)
 */
ret = parent->ops->remove(mdev);
if (ret && !force_remove)
-   return -EBUSY;
+   return ret;
 
sysfs_remove_groups(>dev.kobj, parent->ops->mdev_attr_groups);
return 0;
-- 
1.8.3.1



[PATCHv1 2/7] vfio/mdev: Removed unused kref

2019-03-26 Thread Parav Pandit
Remove unused kref from the mdev_device structure.

Fixes: 7b96953bc640 ("vfio: Mediated device Core driver")
Reviewed By: Kirti Wankhede 
Reviewed-by: Maxim Levitsky 
Signed-off-by: Parav Pandit 
---
 drivers/vfio/mdev/mdev_core.c| 1 -
 drivers/vfio/mdev/mdev_private.h | 1 -
 2 files changed, 2 deletions(-)

diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 1299d2e..00ca613 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -311,7 +311,6 @@ int mdev_device_create(struct kobject *kobj,
mutex_unlock(_list_lock);
 
mdev->parent = parent;
-   kref_init(>ref);
 
mdev->dev.parent  = dev;
mdev->dev.bus = _bus_type;
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index 379758c..ddcf9c7 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -30,7 +30,6 @@ struct mdev_device {
struct mdev_parent *parent;
guid_t uuid;
void *driver_data;
-   struct kref ref;
struct list_head next;
struct kobject *type_kobj;
bool active;
-- 
1.8.3.1



[PATCHv1 3/7] vfio/mdev: Drop redundant extern for exported symbols

2019-03-26 Thread Parav Pandit
There is no need use 'extern' for exported functions.

Reviewed-by: Maxim Levitsky 
Signed-off-by: Parav Pandit 
---
 include/linux/mdev.h | 21 ++---
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index d7aee90..4924d80 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -118,21 +118,20 @@ struct mdev_driver {
 
 #define to_mdev_driver(drv)container_of(drv, struct mdev_driver, driver)
 
-extern void *mdev_get_drvdata(struct mdev_device *mdev);
-extern void mdev_set_drvdata(struct mdev_device *mdev, void *data);
-extern const guid_t *mdev_uuid(struct mdev_device *mdev);
+void *mdev_get_drvdata(struct mdev_device *mdev);
+void mdev_set_drvdata(struct mdev_device *mdev, void *data);
+const guid_t *mdev_uuid(struct mdev_device *mdev);
 
 extern struct bus_type mdev_bus_type;
 
-extern int  mdev_register_device(struct device *dev,
-const struct mdev_parent_ops *ops);
-extern void mdev_unregister_device(struct device *dev);
+int mdev_register_device(struct device *dev, const struct mdev_parent_ops 
*ops);
+void mdev_unregister_device(struct device *dev);
 
-extern int  mdev_register_driver(struct mdev_driver *drv, struct module 
*owner);
-extern void mdev_unregister_driver(struct mdev_driver *drv);
+int mdev_register_driver(struct mdev_driver *drv, struct module *owner);
+void mdev_unregister_driver(struct mdev_driver *drv);
 
-extern struct device *mdev_parent_dev(struct mdev_device *mdev);
-extern struct device *mdev_dev(struct mdev_device *mdev);
-extern struct mdev_device *mdev_from_dev(struct device *dev);
+struct device *mdev_parent_dev(struct mdev_device *mdev);
+struct device *mdev_dev(struct mdev_device *mdev);
+struct mdev_device *mdev_from_dev(struct device *dev);
 
 #endif /* MDEV_H */
-- 
1.8.3.1



[PATCHv1 0/7] vfio/mdev: Improve vfio/mdev core module

2019-03-26 Thread Parav Pandit
As we would like to use mdev subsystem for wider use case as
discussed in [1], [2] apart from an offline discussion.
This use case is also discussed with wider forum in [4] in track
'Lightweight NIC HW functions for container offload use cases'.

This series is prep-work and improves vfio/mdev module in following ways.

Patch-1 Fixes releasing parent dev reference during error unwinding
mdev parent registration.
Patch-2 Simplifies mdev device for unused kref.
Patch-3 Drops redundant extern prefix of exported symbols.
Patch-4 Returns right error code from vendor driver.
Patch-5 Fixes to use right sysfs remove sequence.
Patch-6 Fixes removing all child devices if one of them fails.
Patch-7 Fixes conditions with mdev device life cycle APIs

This series is tested using
(a) mtty with VM using vfio_mdev driver for positive tests.
(b) mtty with vfio_mdev with error race condition cases of create,
remove and unloading of mtty driver.
(c) mlx5 core driver using RFC patches [3] and internal patches.
Internal patches are large and cannot be combined with this
prep-work patches. It will posted once prep-work completes.

[1] https://www.spinics.net/lists/netdev/msg556978.html
[2] https://lkml.org/lkml/2019/3/7/696
[3] https://lkml.org/lkml/2019/3/8/819
[4] https://netdevconf.org/0x13/session.html?workshop-hardware-offload

---
Changelog:
---

v0->v1:
 - Dropped device placement on bus sequence patch for this series
 - Addressed below comments from Alex, Kirti, Maxim.
 - Added Review-by tag for already reviewed patches.
 - Dropped incorrect patch of put_device().
 - Corrected Fixes commit tag for sysfs remove sequence fix
 - Split last 8th patch to smaller refactor and fixes patch
 - Following coding style commenting format
 - Fixed accidental delete of mutex_lock in mdev_unregister_device
 - Renamed remove helped to mdev_device_remove_common().
 - Rebased for uuid/guid change


Parav Pandit (7):
  vfio/mdev: Avoid release parent reference during error path
  vfio/mdev: Removed unused kref
  vfio/mdev: Drop redundant extern for exported symbols
  vfio/mdev: Avoid masking error code to EBUSY
  vfio/mdev: Follow correct remove sequence
  vfio/mdev: Fix aborting mdev child device removal if one fails
  vfio/mdev: Fix race conditions with mdev device life cycle APIs

 drivers/vfio/mdev/mdev_core.c| 102 ---
 drivers/vfio/mdev/mdev_private.h |   7 ++-
 drivers/vfio/mdev/mdev_sysfs.c   |   2 +-
 include/linux/mdev.h |  21 
 4 files changed, 91 insertions(+), 41 deletions(-)

-- 
1.8.3.1



Re: [PATCH 06/10] mm: vmscan: demote anon DRAM pages to PMEM node

2019-03-26 Thread Yang Shi




On 3/26/19 5:35 PM, Keith Busch wrote:

On Mon, Mar 25, 2019 at 12:49:21PM -0700, Yang Shi wrote:

On 3/24/19 3:20 PM, Keith Busch wrote:

How do these pages eventually get to swap when migration fails? Looks
like that's skipped.

Yes, they will be just put back to LRU. Actually, I don't expect it would be
very often to have migration fail at this stage (but I have no test data to
support this hypothesis) since the pages have been isolated from LRU, so
other reclaim path should not find them anymore.

If it is locked by someone else right before migration, it is likely
referenced again, so putting back to LRU sounds not bad.

A potential improvement is to have sync migration for kswapd.

Well, it's not that migration fails only if the page is recently
referenced. Migration would fail if there isn't available memory in
the migration node, so this implementation carries an expectation that
migration nodes have higher free capacity than source nodes. And since
your attempting THP's without ever splitting them, that also requires
lower fragmentation for a successful migration.


Yes, it is possible. However, migrate_pages() already has logic to 
handle such case. If the target node has not enough space for migrating 
THP in a whole, it would split THP then retry with base pages.


Swapping THP has been optimized to swap in a whole too. It would try to 
add THP into swap cache in a whole, split THP if the attempt fails, then 
add base pages into swap cache.


So, I think we can leave this to migrate_pages() without splitting in 
advance all the time.


Thanks,
Yang



Applications, however, may allocate and pin pages directly out of that
migration node to the point it does not have so much free capacity or
physical continuity, so we probably shouldn't assume it's the only way
to reclaim pages.




RE: [PATCH 8/8] vfio/mdev: Improve the create/remove sequence

2019-03-26 Thread Parav Pandit
Hi Alex,

> -Original Message-
> From: Alex Williamson 
> Sent: Tuesday, March 26, 2019 10:27 AM
> To: Kirti Wankhede 
> Cc: Parav Pandit ; k...@vger.kernel.org; linux-
> ker...@vger.kernel.org; Neo Jia 
> Subject: Re: [PATCH 8/8] vfio/mdev: Improve the create/remove sequence
> 
> On Tue, 26 Mar 2019 12:36:22 +0530
> Kirti Wankhede  wrote:
> 
> > On 3/23/2019 4:50 AM, Parav Pandit wrote:
> > > There are five problems with current code structure.
> > > 1. mdev device is placed on the mdev bus before it is created in the
> > > vendor driver. Once a device is placed on the mdev bus without
> > > creating its supporting underlying vendor device, an open() can get
> > > triggered by userspace on partially initialized device.
> > > Below ladder diagram highlight it.
> > >
> > >   cpu-0   cpu-1
> > >   -   -
> > >create_store()
> > >  mdev_create_device()
> > >device_register()
> > >   ...
> > >  vfio_mdev_probe()
> > >  ...creates char device
> > > vfio_mdev_open()
> > >   parent->ops->open(mdev)
> > > vfio_ap_mdev_open()
> > >   matrix_mdev = NULL
> > > [...]
> > > parent->ops->create()
> > >   vfio_ap_mdev_create()
> > > mdev_set_drvdata(mdev, matrix_mdev);
> > > /* Valid pointer set above */
> > >
> >
> > VFIO interface uses sysfs path of device or PCI device's BDF where it
> > checks sysfs file for that device exist.
> > In case of VFIO mdev device, above situation will never happen as open
> > will only get called if sysfs entry for that device exist.
> >
> > If you don't use VFIO interface then this situation can arise. In that
> > case probe() can be used for very basic initialization then create
> > actual char device from create().
> >
> >
> > > 2. Current creation sequence is,
> > >parent->ops_create()
> > >groups_register()
> > >
> > > Remove sequence is,
> > >parent->ops->remove()
> > >groups_unregister()
> > > However, remove sequence should be exact mirror of creation sequence.
> > > Once this is achieved, all users of the mdev will be terminated
> > > first before removing underlying vendor device.
> > > (Follow standard linux driver model).
> > > At that point vendor's remove() ops shouldn't failed because device
> > > is taken off the bus that should terminate the users.
> > >
> >
> > If VMM or user space application is using mdev device,
> > parent->ops->remove() can return failure. In that case sysfs files
> > shouldn't be removed. Hence above sequence is followed for remove.
> >
> > Standard linux driver model doesn't allow remove() to fail, but in of
> > mdev framework, interface is defined to handle such error case.
> >
> >
> > > 3. Additionally any new mdev driver that wants to work on mdev
> > > device during probe() routine registered using
> > > mdev_register_driver() needs to get stable mdev structure.
> > >
> >
> > Things that you are trying to handle with mdev structure from probe(),
> > couldn't that be moved to create()?
> >
> >
> > > 4. In following sequence, child devices created while removing mdev
> > > parent device can be left out, or it may lead to race of removing
> > > half initialized child mdev devices.
> > >
> > > issue-1:
> > > 
> > >cpu-0 cpu-1
> > >- -
> > >   mdev_unregister_device()
> > >  device_for_each_child()
> > > mdev_device_remove_cb()
> > > mdev_device_remove()
> > > create_store()
> > >   mdev_device_create()   [...]
> > >device_register()
> > >   parent_remove_sysfs_files()
> > >   /* BUG: device added by cpu-0
> > >* whose parent is getting removed.
> > >*/
> > >
> > > issue-2:
> > > 
> > >cpu-0 cpu-1
> > >- -
> > > create_store()
> > >   mdev_device_create()   [...]
> > >device_register()
> > >
> > >[...]  mdev_unregister_device()
> > >  device_for_each_child()
> > > mdev_device_remove_cb()
> > > mdev_device_remove()
> > >
> > >mdev_create_sysfs_files()
> > >/* BUG: create is adding
> > > * sysfs files for a device
> > > * which is undergoing removal.
> > > */
> > >  

linux-next: build failure after merge of the drm-intel tree

2019-03-26 Thread Stephen Rothwell
Hi all,

After merging the drm-intel tree, today's linux-next build (i386
defconfig) failed like this:

In file included from drivers/gpu/drm/i915/intel_guc.h:28:0,
 from drivers/gpu/drm/i915/intel_uc.h:27,
 from drivers/gpu/drm/i915/intel_uc.c:25:
drivers/gpu/drm/i915/intel_uncore.h: In function '__raw_uncore_read64':
drivers/gpu/drm/i915/intel_uncore.h:257:9: error: implicit declaration of 
function 'readq'; did you mean 'readl'? [-Werror=implicit-function-declaration]
  return read##s__(uncore->regs + i915_mmio_reg_offset(reg)); \
 ^
drivers/gpu/drm/i915/intel_uncore.h:269:1: note: in expansion of macro 
'__raw_read'
 __raw_read(64, q)
 ^~
drivers/gpu/drm/i915/intel_uncore.h: In function '__raw_uncore_write64':
drivers/gpu/drm/i915/intel_uncore.h:264:2: error: implicit declaration of 
function 'writeq'; did you mean 'writel'? 
[-Werror=implicit-function-declaration]
  write##s__(val, uncore->regs + i915_mmio_reg_offset(reg)); \
  ^
drivers/gpu/drm/i915/intel_uncore.h:274:1: note: in expansion of macro 
'__raw_write'
 __raw_write(64, q)
 ^~~

Caused by commit

  6cc5ca768825 ("drm/i915: rename raw reg access functions")

I have reverted that commit and the following ones in the tree up to

  9511cb6481af ("drm/i915: Adding missing '; ' to ENGINE_INSTANCES")

-- 
Cheers,
Stephen Rothwell


pgp5SPRlS_Vpq.pgp
Description: OpenPGP digital signature


Re: [RFC PATCH 0/10] Another Approach to Use PMEM as NUMA Node

2019-03-26 Thread Yang Shi




On 3/26/19 11:37 AM, Michal Hocko wrote:

On Tue 26-03-19 11:33:17, Yang Shi wrote:


On 3/26/19 6:58 AM, Michal Hocko wrote:

On Sat 23-03-19 12:44:25, Yang Shi wrote:

With Dave Hansen's patches merged into Linus's tree

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=c221c0b0308fd01d9fb33a16f64d2fd95f8830a4

PMEM could be hot plugged as NUMA node now. But, how to use PMEM as NUMA node
effectively and efficiently is still a question.

There have been a couple of proposals posted on the mailing list [1] [2].

The patchset is aimed to try a different approach from this proposal [1]
to use PMEM as NUMA nodes.

The approach is designed to follow the below principles:

1. Use PMEM as normal NUMA node, no special gfp flag, zone, zonelist, etc.

2. DRAM first/by default. No surprise to existing applications and default
running. PMEM will not be allocated unless its node is specified explicitly
by NUMA policy. Some applications may be not very sensitive to memory latency,
so they could be placed on PMEM nodes then have hot pages promote to DRAM
gradually.

Why are you pushing yourself into the corner right at the beginning? If
the PMEM is exported as a regular NUMA node then the only difference
should be performance characteristics (module durability which shouldn't
play any role in this particular case, right?). Applications which are
already sensitive to memory access should better use proper binding already.
Some NUMA topologies might have quite a large interconnect penalties
already. So this doesn't sound like an argument to me, TBH.

The major rationale behind this is we assume the most applications should be
sensitive to memory access, particularly for meeting the SLA. The
applications run on the machine may be agnostic to us, they may be sensitive
or non-sensitive. But, assuming they are sensitive to memory access sounds
safer from SLA point of view. Then the "cold" pages could be demoted to PMEM
nodes by kernel's memory reclaim or other tools without impairing the SLA.

If the applications are not sensitive to memory access, they could be bound
to PMEM or allowed to use PMEM (nice to have allocation on DRAM) explicitly,
then the "hot" pages could be promoted to DRAM.

Again, how is this different from NUMA in general?


It is still NUMA, users still can see all the NUMA nodes.

Introduced default allocation node mask (please refer to patch #1) to 
control the memory placement. Typically, the node mask just includes 
DRAM nodes. PMEM nodes are excluded by the node mask for memory allocation.


The node mask could be override by user per the discussion with Dan.

Thanks,
Yang




Re: [PATCH] ARM: dts: imx6qdl: Specify IMX6QDL_CLK_IPG as "ipg" clock for SDMA

2019-03-26 Thread Andrey Smirnov
On Mon, Mar 25, 2019 at 3:49 AM Fabio Estevam  wrote:
>
> Hi Andrey,
>
> On Mon, Mar 25, 2019 at 2:01 AM Andrey Smirnov  
> wrote:
>
> > diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
> > index 9f9aa6e7ed0e..354feba077b2 100644
> > --- a/arch/arm/boot/dts/imx6qdl.dtsi
> > +++ b/arch/arm/boot/dts/imx6qdl.dtsi
> > @@ -949,7 +949,7 @@
> > compatible = "fsl,imx6q-sdma", 
> > "fsl,imx35-sdma";
> > reg = <0x020ec000 0x4000>;
> > interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>;
> > -   clocks = < IMX6QDL_CLK_SDMA>,
> > +   clocks = < IMX6QDL_CLK_IPG>,
>
> This problem affects other i.MX SoCs, such as i,MX6SX as originally
> reported here:
> https://patchwork.kernel.org/patch/10864867/
>
> So I think we need either a  dtsi fix for the other i.MX SoCs or maybe
> a fix in the SDMA driver?

I think it is worth fixing in DT, regardless if we do anything about
SDMA driver or not. I'll add fixes for 6SX and 7D in v2.

Thanks,
Andrey Smirnov


[PATCH] input: keyboard: snvs: make sure irq is handled correctly

2019-03-26 Thread Anson Huang
SNVS IRQ is requested before necessary driver data initialized,
if there is a pending IRQ during driver probe phase, kernel
NULL pointer panic will occur in IRQ handler. To avoid such
scenario, need to move the IRQ request to after driver data
initialization done. This patch is inspired by NXP's internal
kernel tree.

Fixes: d3dc6e232215 ("input: keyboard: imx: add snvs power key driver")
Signed-off-by: Anson Huang 
---
 drivers/input/keyboard/snvs_pwrkey.c | 17 -
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/drivers/input/keyboard/snvs_pwrkey.c 
b/drivers/input/keyboard/snvs_pwrkey.c
index effb632..6ff41fd 100644
--- a/drivers/input/keyboard/snvs_pwrkey.c
+++ b/drivers/input/keyboard/snvs_pwrkey.c
@@ -148,15 +148,6 @@ static int imx_snvs_pwrkey_probe(struct platform_device 
*pdev)
return error;
}
 
-   error = devm_request_irq(>dev, pdata->irq,
-  imx_snvs_pwrkey_interrupt,
-  0, pdev->name, pdev);
-
-   if (error) {
-   dev_err(>dev, "interrupt not available.\n");
-   return error;
-   }
-
error = input_register_device(input);
if (error < 0) {
dev_err(>dev, "failed to register input device\n");
@@ -166,6 +157,14 @@ static int imx_snvs_pwrkey_probe(struct platform_device 
*pdev)
pdata->input = input;
platform_set_drvdata(pdev, pdata);
 
+   error = devm_request_irq(>dev, pdata->irq,
+imx_snvs_pwrkey_interrupt,
+0, pdev->name, pdev);
+   if (error) {
+   dev_err(>dev, "interrupt not available.\n");
+   return error;
+   }
+
device_init_wakeup(>dev, pdata->wakeup);
 
return 0;
-- 
2.7.4



Re: [PATCH v3 3/4] driver core: add dev_print_hex_dump() logging function.

2019-03-26 Thread Greg Kroah-Hartman
On Tue, Mar 26, 2019 at 06:48:06PM -0700, Ronald Tschalär wrote:
> This is the dev_xxx() analog to print_hex_dump(), using dev_printk()
> instead of straight printk() to match other dev_xxx() logging functions.
> ---
>  drivers/base/core.c| 43 ++
>  include/linux/device.h | 15 +++
>  2 files changed, 58 insertions(+)

No signed-off-by?

Anyway, no, please do not do this.  Please do not dump large hex values
like this to the kernel log, it does not help anyone.

You can do this while debugging, sure, but not for "real" kernel code.

Worst case, just create a debugfs file for your device that you can read
the binary data from if you really need it.  For any "normal" operation,
this is not something that you should ever need.

thanks,

greg k-h


[PATCH v5 1/1] mm: introduce put_user_page*(), placeholder versions

2019-03-26 Thread john . hubbard
From: John Hubbard 

Introduces put_user_page(), which simply calls put_page().
This provides a way to update all get_user_pages*() callers,
so that they call put_user_page(), instead of put_page().

Also introduces put_user_pages(), and a few dirty/locked variations,
as a replacement for release_pages(), and also as a replacement
for open-coded loops that release multiple pages.
These may be used for subsequent performance improvements,
via batching of pages to be released.

This is the first step of fixing a problem (also described in [1] and
[2]) with interactions between get_user_pages ("gup") and filesystems.

Problem description: let's start with a bug report. Below, is what happens
sometimes, under memory pressure, when a driver pins some pages via gup,
and then marks those pages dirty, and releases them. Note that the gup
documentation actually recommends that pattern. The problem is that the
filesystem may do a writeback while the pages were gup-pinned, and then the
filesystem believes that the pages are clean. So, when the driver later
marks the pages as dirty, that conflicts with the filesystem's page
tracking and results in a BUG(), like this one that I experienced:

kernel BUG at /build/linux-fQ94TU/linux-4.4.0/fs/ext4/inode.c:1899!
backtrace:
ext4_writepage
__writepage
write_cache_pages
ext4_writepages
do_writepages
__writeback_single_inode
writeback_sb_inodes
__writeback_inodes_wb
wb_writeback
wb_workfn
process_one_work
worker_thread
kthread
ret_from_fork

...which is due to the file system asserting that there are still buffer
heads attached:

({  \
BUG_ON(!PagePrivate(page)); \
((struct buffer_head *)page_private(page)); \
})

Dave Chinner's description of this is very clear:

"The fundamental issue is that ->page_mkwrite must be called on every
write access to a clean file backed page, not just the first one.
How long the GUP reference lasts is irrelevant, if the page is clean
and you need to dirty it, you must call ->page_mkwrite before it is
marked writeable and dirtied. Every. Time."

This is just one symptom of the larger design problem: real filesystems
that actually write to a backing device, do not actually support
get_user_pages() being called on their pages, and letting hardware write
directly to those pages--even though that pattern has been going on since
about 2005 or so.

The steps are to fix it are:

1) (This patch): provide put_user_page*() routines, intended to be used
   for releasing pages that were pinned via get_user_pages*().

2) Convert all of the call sites for get_user_pages*(), to
   invoke put_user_page*(), instead of put_page(). This involves dozens of
   call sites, and will take some time.

3) After (2) is complete, use get_user_pages*() and put_user_page*() to
   implement tracking of these pages. This tracking will be separate from
   the existing struct page refcounting.

4) Use the tracking and identification of these pages, to implement
   special handling (especially in writeback paths) when the pages are
   backed by a filesystem.

[1] https://lwn.net/Articles/774411/ : "DMA and get_user_pages()"
[2] https://lwn.net/Articles/753027/ : "The Trouble with get_user_pages()"

Cc: Al Viro 
Cc: Christoph Hellwig 
Cc: Christopher Lameter 
Cc: Dan Williams 
Cc: Dave Chinner 
Cc: Ira Weiny 
Cc: Jan Kara 
Cc: Jason Gunthorpe 
Cc: Jerome Glisse 
Cc: Matthew Wilcox 
Cc: Michal Hocko 
Cc: Mike Rapoport 
Cc: Ralph Campbell 

Reviewed-by: Jan Kara 
Reviewed-by: Mike Rapoport # docs
Reviewed-by: Ira Weiny 
Reviewed-by: Jérôme Glisse 
Reviewed-by: Christoph Lameter 
Tested-by: Ira Weiny 
Signed-off-by: John Hubbard 
---
 include/linux/mm.h |  24 +++
 mm/gup.c   | 105 +
 2 files changed, 129 insertions(+)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index 76769749b5a5..a216c738d2f2 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -994,6 +994,30 @@ static inline void put_page(struct page *page)
__put_page(page);
 }
 
+/**
+ * put_user_page() - release a gup-pinned page
+ * @page:pointer to page to be released
+ *
+ * Pages that were pinned via get_user_pages*() must be released via
+ * either put_user_page(), or one of the put_user_pages*() routines
+ * below. This is so that eventually, pages that are pinned via
+ * get_user_pages*() can be separately tracked and uniquely handled. In
+ * particular, interactions with RDMA and filesystems need special
+ * handling.
+ *
+ * put_user_page() and put_page() are not interchangeable, despite this early
+ * implementation that makes them look the same. put_user_page() calls must
+ * be perfectly matched up with get_user_page() calls.
+ */
+static inline void 

[PATCH v5 0/1] mm: introduce put_user_page*(), placeholder versions

2019-03-26 Thread john . hubbard
From: John Hubbard 

Hi Andrew and all,

Can we please apply this for Linux 5.2?

I'm adding a Reviewed-by from Christopher Lameter (thanks!), and an updated
comment about a race condition (from Kirill's review feedback), and can now
make the following statement more confidently:

We seem to have pretty solid consensus on the concept and details of the
put_user_pages() approach.

Therefore, here is the first patch--only. This allows us to begin
converting the get_user_pages() call sites to use put_user_page(), instead
of put_page(). This is in order to implement tracking of get_user_page()
pages.

Normally I'd include a user of this code, but in this case, I think we have
examples of how it will work in the RFC and related discussions [1]. What
matters more at this point is unblocking the ability to start fixing up
various subsystems, through git trees other than linux-mm. For example, the
Infiniband example conversion now needs to pick up some prerequisite
patches via the RDMA tree. It seems likely that other call sites may need
similar attention, and so having put_user_pages() available would really
make this go more quickly.

Previous cover letter follows:
==

A discussion of the overall problem is below.

As mentioned in patch 0001, the steps are to fix the problem are:

1) Provide put_user_page*() routines, intended to be used
   for releasing pages that were pinned via get_user_pages*().

2) Convert all of the call sites for get_user_pages*(), to
   invoke put_user_page*(), instead of put_page(). This involves dozens of
   call sites, and will take some time.

3) After (2) is complete, use get_user_pages*() and put_user_page*() to
   implement tracking of these pages. This tracking will be separate from
   the existing struct page refcounting.

4) Use the tracking and identification of these pages, to implement
   special handling (especially in writeback paths) when the pages are
   backed by a filesystem.

Overview


Some kernel components (file systems, device drivers) need to access
memory that is specified via process virtual address. For a long time, the
API to achieve that was get_user_pages ("GUP") and its variations. However,
GUP has critical limitations that have been overlooked; in particular, GUP
does not interact correctly with filesystems in all situations. That means
that file-backed memory + GUP is a recipe for potential problems, some of
which have already occurred in the field.

GUP was first introduced for Direct IO (O_DIRECT), allowing filesystem code
to get the struct page behind a virtual address and to let storage hardware
perform a direct copy to or from that page. This is a short-lived access
pattern, and as such, the window for a concurrent writeback of GUP'd page
was small enough that there were not (we think) any reported problems.
Also, userspace was expected to understand and accept that Direct IO was
not synchronized with memory-mapped access to that data, nor with any
process address space changes such as munmap(), mremap(), etc.

Over the years, more GUP uses have appeared (virtualization, device
drivers, RDMA) that can keep the pages they get via GUP for a long period
of time (seconds, minutes, hours, days, ...). This long-term pinning makes
an underlying design problem more obvious.

In fact, there are a number of key problems inherent to GUP:

Interactions with file systems
==

File systems expect to be able to write back data, both to reclaim pages,
and for data integrity. Allowing other hardware (NICs, GPUs, etc) to gain
write access to the file memory pages means that such hardware can dirty
the pages, without the filesystem being aware. This can, in some cases
(depending on filesystem, filesystem options, block device, block device
options, and other variables), lead to data corruption, and also to kernel
bugs of the form:

kernel BUG at /build/linux-fQ94TU/linux-4.4.0/fs/ext4/inode.c:1899!
backtrace:
ext4_writepage
__writepage
write_cache_pages
ext4_writepages
do_writepages
__writeback_single_inode
writeback_sb_inodes
__writeback_inodes_wb
wb_writeback
wb_workfn
process_one_work
worker_thread
kthread
ret_from_fork

...which is due to the file system asserting that there are still buffer
heads attached:

({  \
BUG_ON(!PagePrivate(page)); \
((struct buffer_head *)page_private(page)); \
})

Dave Chinner's description of this is very clear:

"The fundamental issue is that ->page_mkwrite must be called on every
write access to a clean file backed page, not just the first one.
How long the GUP reference lasts is irrelevant, if the page is clean
and you need to dirty it, you must call ->page_mkwrite before it is
marked writeable and dirtied. 

Re: [PATCH V31 25/25] debugfs: Disable open() when kernel is locked down

2019-03-26 Thread Greg KH
On Tue, Mar 26, 2019 at 07:06:36PM -0700, Matthew Garrett wrote:
> On Tue, Mar 26, 2019 at 5:31 PM Greg KH  wrote:
> > On Tue, Mar 26, 2019 at 11:27:41AM -0700, Matthew Garrett wrote:
> > > From: Matthew Garrett 
> > >
> > > debugfs has not been meaningfully audited in terms of ensuring that
> > > userland cannot trample over the kernel. At Greg's request, disable
> > > access to it entirely when the kernel is locked down. This is done at
> > > open() time rather than init time as the kernel lockdown status may be
> > > made stricter at runtime.
> 
> (snip)
> 
> > Why allow all this, why not just abort the registering of the filesystem
> > with the vfs core so it can't even be mounted?
> 
> As mentioned in the commit message, because the lockdown state can be
> made stricter at runtime - blocking at mount time would be
> inconsistent if the machine is locked down afterwards. We could
> potentially assert that it's the admin's responsibility to ensure that
> debugfs isn't mounted at the point of policy being made stricter?

Ugh, I can not read, sorry, neverind.

The patch is fine as-is.

greg k-h


Re: [PATCH v2 00/11] LSM documentation update

2019-03-26 Thread James Morris
On Tue, 26 Feb 2019, Denis Efremov wrote:

> Recent "New LSM Hooks" discussion has led me to the
> thought that it might be a good idea to slightly
> update the current documentation. The patchset adds
> nothing new to the documentation, only fixes the old
> description of hooks to reflect their current state.
> 
> V2 adds the clarification on arguments for some hooks.
> The format of the documentation is also slightly updated
> for better html. However, there are still 10 hooks without
> documentation at all. I think that this should be fixed
> separatedly.

Applied to
git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security.git 
next-general

Thanks!

-- 
James Morris




Re: [PATCH] HID: intel-ish-hid: ISH firmware loader client driver

2019-03-26 Thread Srinivas Pandruvada
On Tue, 2019-03-26 at 18:39 -0600, Nick Crews wrote:
> Hi Rushikesh, I know I've been reviewing this on Chromium, but I have
> some more larges-scale design thoughts.
Hi Nick.

Does this fundamentally change, the way it is done here or can wait for
subsequent revisions later?

Thanks,
Srinivas

> 
> > > diff --git a/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
> > > b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
> > > new file mode 100644
> > > index 000..85d71d3
> > > --- /dev/null
> > > +++ b/drivers/hid/intel-ish-hid/ishtp-fw-loader.c
> > > @@ -0,0 +1,1103 @@
> > > +// SPDX-License-Identifier: GPL-2.0
> > > +/*
> > > + * ISH-TP client driver for ISH firmware loading
> > > + *
> > > + * Copyright (c) 2018, Intel Corporation.
> > 
> > Year 2019.
> > 
> > > + */
> > > +
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +#include 
> > > +
> > > +/* ISH TX/RX ring buffer pool size */
> > > +#define LOADER_CL_RX_RING_SIZE   1
> > > +#define LOADER_CL_TX_RING_SIZE   1
> > > +
> > > +/*
> > > + * ISH Shim firmware loader reserves 4 Kb buffer in SRAM. The
> > > buffer
> > > is
> > > + * used to temporarily hold the data transferred from host to
> > > Shim
> > > firmware
> > > + * loader. Reason for the odd size of 3968 bytes? Each IPC
> > > transfer
> > > is 128
> > > + * bytes (= 4 bytes header + 124 bytes payload). So the 4 Kb
> > > buffer
> > > can
> > > + * hold maximum of 32 IPC transfers, which means we can have a
> > > max
> > > payload
> > > + * of 3968 bytes (= 32 x 124 payload).
> > > + */
> > > +#define LOADER_SHIM_IPC_BUF_SIZE 3968
> > > +
> > > +/**
> > > + * enum ish_loader_commands -ISH loader host commands.
> > > + * LOADER_CMD_XFER_QUERY Query the Shim firmware loader for
> > > capabilities
> > > + * LOADER_CMD_XFER_FRAGMENT  Transfer one firmware image
> > > framgment
> > > at a
> > > + *   time. The command may be executed
> > > multiple
> > > + *   times until the entire firmware
> > > image
> > > is
> > > + *   downloaded to SRAM.
> > > + * LOADER_CMD_START  Start executing the main firmware.
> > > + */
> > > +enum ish_loader_commands {
> > > + LOADER_CMD_XFER_QUERY = 0,
> > > + LOADER_CMD_XFER_FRAGMENT,
> > > + LOADER_CMD_START,
> > > +};
> > > +
> > > +/* Command bit mask */
> > > +#define  CMD_MASKGENMASK(6,
> > > 0)
> > > +#define  IS_RESPONSE BIT(7)
> > > +
> > > +/*
> > > + * ISH firmware max delay for one transmit failure is 1 Hz,
> > > + * and firmware will retry 2 times, so 3 Hz is used for timeout.
> > > + */
> > > +#define ISHTP_SEND_TIMEOUT   (3 * HZ)
> > > +
> > > +/*
> > > + * Loader transfer modes:
> > > + *
> > > + * LOADER_XFER_MODE_ISHTP mode uses the existing ISH-TP
> > > mechanims to
> > > + * transfer data. This may use IPC or DMA if supported in
> > > firmware.
> > > + * The buffer size is limited to 4 Kb by the IPC/ISH-TP protocol
> > > for
> > > + * both IPC & DMA (legacy).
> > > + *
> > > + * LOADER_XFER_MODE_DIRECT_DMA - firmware loading is a bit
> > > different
> > > + * from the sensor data streaming. Here we download a large
> > > (300+
> > > Kb)
> > > + * image directly to ISH SRAM memory. There is limited benefit
> > > of
> > > + * DMA'ing 300 Kb image in 4 Kb chucks limit. Hence, we
> > > introduce
> > > + * this "direct dma" mode, where we do not use ISH-TP for DMA,
> > > but
> > > + * instead manage the DMA directly in kernel driver and Shim
> > > firmware
> > > + * loader (allocate buf, break in chucks and transfer). This
> > > allows
> > > + * to overcome 4 Kb limit, and optimize the data flow path in
> > > firmware.
> > > + */
> > > +#define LOADER_XFER_MODE_DIRECT_DMA  BIT(0)
> > > +#define LOADER_XFER_MODE_ISHTP   BIT(1)
> > > +
> > > +/* ISH Transport Loader client unique GUID */
> > > +static const guid_t loader_ishtp_guid =
> > > + GUID_INIT(0xc804d06a, 0x55bd, 0x4ea7,
> > > +   0xad, 0xed, 0x1e, 0x31, 0x22, 0x8c, 0x76, 0xdc);
> > > +
> > > +#define FILENAME_SIZE256
> > > +
> > > +/*
> > > + * The firmware loading latency will be minimum if we can DMA
> > > the
> > > + * entire ISH firmware image in one go. This requires that we
> > > allocate
> > > + * a large DMA buffer in kernel, which could be problematic on
> > > some
> > > + * platforms. So here we limit the DMA buf size via a
> > > module_param.
> > > + * We default to 4 pages, but a customer can set it to higher
> > > limit
> > > if
> > > + * deemed appropriate for his platform.
> > > + */
> > > +static int dma_buf_size_limit = 4 * PAGE_SIZE;
> > > +
> > > +/**
> > > + * struct loader_msg_hdr - Header for ISH Loader commands.
> > > + * @command: LOADER_CMD* commands. Bit 7 is the
> > > response.
> > > + * @status:  Command 

RE: [PATCHv4 00/28] PCI: refactor Mobiveil driver and add PCIe Gen4 driver for NXP Layerscape SoCs

2019-03-26 Thread Z.q. Hou
Hi Lorenzo,

Thanks for your comments!

> -Original Message-
> From: Lorenzo Pieralisi 
> Sent: 2019年3月27日 1:38
> To: Z.q. Hou 
> Cc: linux-...@vger.kernel.org; linux-arm-ker...@lists.infradead.org;
> devicet...@vger.kernel.org; linux-kernel@vger.kernel.org;
> bhelg...@google.com; robh...@kernel.org; mark.rutl...@arm.com;
> l.subrahma...@mobiveil.co.in; shawn...@kernel.org; Leo Li
> ; catalin.mari...@arm.com; will.dea...@arm.com;
> Mingkai Hu ; M.h. Lian ;
> Xiaowei Bao 
> Subject: Re: [PATCHv4 00/28] PCI: refactor Mobiveil driver and add PCIe Gen4
> driver for NXP Layerscape SoCs
> 
> On Mon, Mar 11, 2019 at 09:29:54AM +, Z.q. Hou wrote:
> > From: Hou Zhiqiang 
> >
> > This patch set is aim to refactor the Mobiveil driver and add PCIe
> > support for NXP Layerscape series SoCs integrated Mobiveil's PCIe Gen4
> > controller.
> >
> > Hou Zhiqiang (28):
> >   PCI: mobiveil: uniform the register accessors
> >   PCI: mobiveil: format the code without function change
> >   PCI: mobiveil: correct the returned error number
> >   PCI: mobiveil: remove flag MSI_FLAG_MULTI_PCI_MSI
> >   PCI: mobiveil: correct PCI base address in MEM/IO outbound windows
> >   PCI: mobiveil: replace the resource list iteration function
> >   PCI: mobiveil: use WIN_NUM_0 explicitly for CFG outbound window
> >   PCI: mobiveil: use the 1st inbound window for MEM inbound
> transactions
> >   PCI: mobiveil: correct inbound/outbound window setup routines
> >   PCI: mobiveil: fix the INTx process error
> >   PCI: mobiveil: only fix up the Class Code field
> >   PCI: mobiveil: move out the link up waiting from mobiveil_host_init
> >   PCI: mobiveil: move irq chained handler setup out of DT parse
> >   PCI: mobiveil: initialize Primary/Secondary/Subordinate bus number
> >   dt-bindings: pci: mobiveil: change gpio_slave and apb_csr to optional
> >   PCI: mobiveil: refactor Mobiveil PCIe Host Bridge IP driver
> >   PCI: mobiveil: fix the checking of valid device
> >   PCI: mobiveil: add link up condition check
> >   PCI: mobiveil: continue to initialize the host upon no PCIe link
> >   PCI: mobiveil: disabled IB and OB windows set by bootloader
> >   PCI: mobiveil: add Byte and Half-Word width register accessors
> >   PCI: mobiveil: make mobiveil_host_init can be used to re-init host
> >   dt-bindings: pci: Add NXP Layerscape SoCs PCIe Gen4 controller
> >   PCI: mobiveil: add PCIe Gen4 RC driver for NXP Layerscape SoCs
> >   PCI: mobiveil: ls_pcie_g4: add Workaround for A-011577
> >   PCI: mobiveil: ls_pcie_g4: add Workaround for A-011451
> >   arm64: dts: freescale: lx2160a: add pcie DT nodes
> >   arm64: defconfig: Enable CONFIG_PCI_LAYERSCAPE_GEN4
> >
> >  .../bindings/pci/layerscape-pci-gen4.txt  |  52 ++
> >  .../devicetree/bindings/pci/mobiveil-pcie.txt |   2 +
> >  MAINTAINERS   |  10 +-
> >  .../arm64/boot/dts/freescale/fsl-lx2160a.dtsi | 163 
> >  arch/arm64/configs/defconfig  |   1 +
> >  drivers/pci/controller/Kconfig|  11 +-
> >  drivers/pci/controller/Makefile   |   2 +-
> >  drivers/pci/controller/mobiveil/Kconfig   |  34 +
> >  drivers/pci/controller/mobiveil/Makefile  |   5 +
> >  .../controller/mobiveil/pci-layerscape-gen4.c | 306 +++
> > .../controller/mobiveil/pcie-mobiveil-host.c  | 640 +
> > .../controller/mobiveil/pcie-mobiveil-plat.c  |  54 ++
> >  .../pci/controller/mobiveil/pcie-mobiveil.c   | 246 +
> >  .../pci/controller/mobiveil/pcie-mobiveil.h   | 229 +
> >  drivers/pci/controller/pcie-mobiveil.c| 861 --
> >  15 files changed, 1743 insertions(+), 873 deletions(-)  create mode
> > 100644 Documentation/devicetree/bindings/pci/layerscape-pci-gen4.txt
> >  create mode 100644 drivers/pci/controller/mobiveil/Kconfig
> >  create mode 100644 drivers/pci/controller/mobiveil/Makefile
> >  create mode 100644
> > drivers/pci/controller/mobiveil/pci-layerscape-gen4.c
> >  create mode 100644
> > drivers/pci/controller/mobiveil/pcie-mobiveil-host.c
> >  create mode 100644
> > drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c
> >  create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.c
> >  create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.h
> >  delete mode 100644 drivers/pci/controller/pcie-mobiveil.c
> 
> This patch series is a mixture of fixes, refactoring and development and to be
> frank it is a bit hard to review. Keeping in mind all the review comments
> already received and that I expect you to integrate, do you mind splitting it 
> in
> logical series each one serving a specific purpose (eg fixes, Layerscape 
> support,
> etc.) ?
> 
> Let's start with posting and merging the fixes first.

Thanks for your suggestion, and will split them.

> 
> Thank you very much.
> 
> Lorenzo

Thanks,
Zhiqiang


Re: [PATCH V31 25/25] debugfs: Disable open() when kernel is locked down

2019-03-26 Thread Matthew Garrett
On Tue, Mar 26, 2019 at 5:31 PM Greg KH  wrote:
> On Tue, Mar 26, 2019 at 11:27:41AM -0700, Matthew Garrett wrote:
> > From: Matthew Garrett 
> >
> > debugfs has not been meaningfully audited in terms of ensuring that
> > userland cannot trample over the kernel. At Greg's request, disable
> > access to it entirely when the kernel is locked down. This is done at
> > open() time rather than init time as the kernel lockdown status may be
> > made stricter at runtime.

(snip)

> Why allow all this, why not just abort the registering of the filesystem
> with the vfs core so it can't even be mounted?

As mentioned in the commit message, because the lockdown state can be
made stricter at runtime - blocking at mount time would be
inconsistent if the machine is locked down afterwards. We could
potentially assert that it's the admin's responsibility to ensure that
debugfs isn't mounted at the point of policy being made stricter?


RE: [PATCHv4 16/28] PCI: mobiveil: refactor Mobiveil PCIe Host Bridge IP driver

2019-03-26 Thread Z.q. Hou
Hi Lorenzo,

Thanks for your comments!

> -Original Message-
> From: Lorenzo Pieralisi 
> Sent: 2019年3月27日 1:34
> To: Z.q. Hou 
> Cc: linux-...@vger.kernel.org; linux-arm-ker...@lists.infradead.org;
> devicet...@vger.kernel.org; linux-kernel@vger.kernel.org;
> bhelg...@google.com; robh...@kernel.org; mark.rutl...@arm.com;
> l.subrahma...@mobiveil.co.in; shawn...@kernel.org; Leo Li
> ; catalin.mari...@arm.com; will.dea...@arm.com;
> Mingkai Hu ; M.h. Lian ;
> Xiaowei Bao 
> Subject: Re: [PATCHv4 16/28] PCI: mobiveil: refactor Mobiveil PCIe Host
> Bridge IP driver
> 
> On Mon, Mar 11, 2019 at 09:32:04AM +, Z.q. Hou wrote:
> > From: Hou Zhiqiang 
> >
> > As the Mobiveil PCIe controller support RC DAUL mode, and to make
> > platforms which integrated the Mobiveil PCIe IP more easy to add their
> > drivers, this patch moved the Mobiveil driver to a new directory
> > 'drivers/pci/controller/mobiveil' and refactored it according to the
> > abstraction of RC (EP driver will be added later).
> 
> I do not want to create a subdirectory for every controller that can work in
> RC so drop this patch, more so given that it will be required "later", we
> will create a directory when and if we actually have to.

Please don't drop this patch, Xiaowei Bao has sent v1 of the EP mode driver, 
which is depends on this patch.

> Thanks,
> Lorenzo
> 
> > Signed-off-by: Hou Zhiqiang 
> > Reviewed-by: Minghuan Lian 
> > Reviewed-by: Subrahmanya Lingappa 
> > ---
> > V4:
> >  - no change
> >
> >  MAINTAINERS   |   2 +-
> >  drivers/pci/controller/Kconfig|  11 +-
> >  drivers/pci/controller/Makefile   |   2 +-
> >  drivers/pci/controller/mobiveil/Kconfig   |  24 +
> >  drivers/pci/controller/mobiveil/Makefile  |   4 +
> >  .../pcie-mobiveil-host.c} | 528 +++---
> >  .../controller/mobiveil/pcie-mobiveil-plat.c  |  54 ++
> >  .../pci/controller/mobiveil/pcie-mobiveil.c   | 228 
> >  .../pci/controller/mobiveil/pcie-mobiveil.h   | 187 +++
> >  9 files changed, 587 insertions(+), 453 deletions(-)  create mode
> > 100644 drivers/pci/controller/mobiveil/Kconfig
> >  create mode 100644 drivers/pci/controller/mobiveil/Makefile
> >  rename drivers/pci/controller/{pcie-mobiveil.c =>
> > mobiveil/pcie-mobiveil-host.c} (55%)  create mode 100644
> > drivers/pci/controller/mobiveil/pcie-mobiveil-plat.c
> >  create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.c
> >  create mode 100644 drivers/pci/controller/mobiveil/pcie-mobiveil.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS index
> > 1e64279f338a..1013e74b14f2 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -11877,7 +11877,7 @@ M:  Subrahmanya Lingappa
> 
> >  L: linux-...@vger.kernel.org
> >  S: Supported
> >  F: Documentation/devicetree/bindings/pci/mobiveil-pcie.txt
> > -F: drivers/pci/controller/pcie-mobiveil.c
> > +F: drivers/pci/controller/mobiveil/pcie-mobiveil*
> >
> >  PCI DRIVER FOR MVEBU (Marvell Armada 370 and Armada XP SOC
> support)
> >  M: Thomas Petazzoni 
> > diff --git a/drivers/pci/controller/Kconfig
> > b/drivers/pci/controller/Kconfig index 6671946dbf66..0e981ed00a75
> > 100644
> > --- a/drivers/pci/controller/Kconfig
> > +++ b/drivers/pci/controller/Kconfig
> > @@ -241,16 +241,6 @@ config PCIE_MEDIATEK
> >   Say Y here if you want to enable PCIe controller support on
> >   MediaTek SoCs.
> >
> > -config PCIE_MOBIVEIL
> > -   bool "Mobiveil AXI PCIe controller"
> > -   depends on ARCH_ZYNQMP || COMPILE_TEST
> > -   depends on OF
> > -   depends on PCI_MSI_IRQ_DOMAIN
> > -   help
> > - Say Y here if you want to enable support for the Mobiveil AXI PCIe
> > - Soft IP. It has up to 8 outbound and inbound windows
> > - for address translation and it is a PCIe Gen4 IP.
> > -
> >  config PCIE_TANGO_SMP8759
> > bool "Tango SMP8759 PCIe controller (DANGEROUS)"
> > depends on ARCH_TANGO && PCI_MSI && OF @@ -281,4 +271,5 @@
> config
> > VMD
> >   module will be called vmd.
> >
> >  source "drivers/pci/controller/dwc/Kconfig"
> > +source "drivers/pci/controller/mobiveil/Kconfig"
> >  endmenu
> > diff --git a/drivers/pci/controller/Makefile
> > b/drivers/pci/controller/Makefile index d56a507495c5..b79a615041a0
> > 100644
> > --- a/drivers/pci/controller/Makefile
> > +++ b/drivers/pci/controller/Makefile
> > @@ -26,11 +26,11 @@ obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
> >  obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-rockchip-ep.o
> >  obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o
> >  obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
> > -obj-$(CONFIG_PCIE_MOBIVEIL) += pcie-mobiveil.o
> >  obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o
> >  obj-$(CONFIG_VMD) += vmd.o
> >  # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
> >  obj-y  += dwc/
> > +obj-y  += mobiveil/
> >
> >
> >  # The following drivers are for devices that use the 

Re: [PATCH v2 0/4] Add new features for the Spreadtrum serial controller

2019-03-26 Thread Baolin Wang
On Wed, 27 Mar 2019 at 08:59, Greg KH  wrote:
>
> On Tue, Mar 26, 2019 at 06:41:31PM +0800, Baolin Wang wrote:
> > Hi Greg,
> >
> > On Mon, 4 Mar 2019 at 16:59, Baolin Wang  wrote:
> > >
> > > This patch set fixes the baud rate calculation formula issue, as well as
> > > adding power management support and DMA mode support for the Spreadtrum
> > > serial controller.
> > >
> > > Changes from v1:
> > >  - The patch 1 of V1 was applied, so remove the baud rate fix from this 
> > > patch set.
> > >  - Add reviewed tag from Rob for patch 1.
> > >  - Fix the incorrect names' order in patch 3.
> >
> > Could you apply this patch set if no objection from you? Thanks.
>
> It's in my to-review queue, sorry, will get to it soon...

Thanks :)

--
Baolin Wang
Best Regards


[PATCH v5 2/2] staging: mt7621-mmc: Initialize completions a single time during probe

2019-03-26 Thread George Hilliard
The module was initializing completions whenever it was going to wait on
them, and not when the completion was allocated.  This is incorrect
according to the completion docs:

Calling init_completion() on the same completion object twice is
most likely a bug [...]

Re-initialization is also unnecessary because the module never uses
complete_all().  Fix this by only ever initializing the completion a
single time, and log if the completions are not consumed as intended
(this is not a fatal problem, but should not go unnoticed).

Signed-off-by: George Hilliard 
---
v2: rewrite of v1
v3: Remove BUG_ON() calls
v4: Indent style fixup
v5: *Correct* whitespace fixup

 drivers/staging/mt7621-mmc/sd.c | 18 ++
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/staging/mt7621-mmc/sd.c b/drivers/staging/mt7621-mmc/sd.c
index e346167754bd..9a4b27562cd0 100644
--- a/drivers/staging/mt7621-mmc/sd.c
+++ b/drivers/staging/mt7621-mmc/sd.c
@@ -466,7 +466,11 @@ static unsigned int msdc_command_start(struct msdc_host   
*host,
host->cmd = cmd;
host->cmd_rsp = resp;
 
-   init_completion(>cmd_done);
+   // The completion should have been consumed by the previous command
+   // response handler, because the mmc requests should be serialized
+   if (completion_done(>cmd_done))
+   dev_err(mmc_dev(host->mmc),
+   "previous command was not handled\n");
 
sdr_set_bits(host->base + MSDC_INTEN, wints);
sdc_send_cmd(rawcmd, cmd->arg);
@@ -488,7 +492,6 @@ static unsigned int msdc_command_resp(struct msdc_host   
*host,
MSDC_INT_ACMD19_DONE;
 
BUG_ON(in_interrupt());
-   //init_completion(>cmd_done);
//sdr_set_bits(host->base + MSDC_INTEN, wints);
 
spin_unlock(>lock);
@@ -670,7 +673,13 @@ static int msdc_do_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
//msdc_clr_fifo(host);  /* no need */
 
msdc_dma_on();  /* enable DMA mode first!! */
-   init_completion(>xfer_done);
+
+   // The completion should have been consumed by the previous
+   // xfer response handler, because the mmc requests should be
+   // serialized
+   if (completion_done(>cmd_done))
+   dev_err(mmc_dev(host->mmc),
+   "previous transfer was not handled\n");
 
/* start the command first*/
if (msdc_command_start(host, cmd, CMD_TIMEOUT) != 0)
@@ -696,7 +705,6 @@ static int msdc_do_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
/* for read, the data coming too fast, then CRC error
 *  start DMA no business with CRC.
 */
-   //init_completion(>xfer_done);
msdc_dma_start(host);
 
spin_unlock(>lock);
@@ -1687,6 +1695,8 @@ static int msdc_drv_probe(struct platform_device *pdev)
}
msdc_init_gpd_bd(host, >dma);
 
+   init_completion(>cmd_done);
+   init_completion(>xfer_done);
INIT_DELAYED_WORK(>card_delaywork, msdc_tasklet_card);
spin_lock_init(>lock);
msdc_init_hw(host);
-- 
2.21.0



RE: [PATCH 3.18 132/134] rcu: Do RCU GP kthread self-wakeup from softirq and interrupt

2019-03-26 Thread Zhang, Jun
Hello,Paul

I use a new NUC (made in 2017) to test, meet the same hang. System run very 
slowly.

But I use my PC (made before 2015), test V3.18.136+ patch for 12 hours, still 
well.

Maybe V3.18.y don't support some new devices.


-Original Message-
From: Paul E. McKenney [mailto:paul...@linux.ibm.com] 
Sent: Tuesday, March 26, 2019 23:56
To: He, Bo 
Cc: Greg Kroah-Hartman ; 
linux-kernel@vger.kernel.org; sta...@vger.kernel.org; Zhang, Jun 
; Xiao, Jin ; Bai, Jie A 

Subject: Re: [PATCH 3.18 132/134] rcu: Do RCU GP kthread self-wakeup from 
softirq and interrupt

On Tue, Mar 26, 2019 at 08:43:45AM +, He, Bo wrote:
> Hi, Paul:
>   I have tried on my PC and not hit any hang issue with RCU torture test 
> for one hour, the configurations are like:
> OS: ubuntu 16.04
> kenrel: 3.18.136 + 3.18 rcu patch
> CPU:  Intel(R) Xeon(R) CPU E3-1225 V2 @ 3.20GHz

Sounds good, please proceed!

Thanx, Paul

> -Original Message-
> From: Paul E. McKenney 
> Sent: Tuesday, March 26, 2019 12:00 AM
> To: Greg Kroah-Hartman 
> Cc: He, Bo ; linux-kernel@vger.kernel.org; 
> sta...@vger.kernel.org; Zhang, Jun ; Xiao, Jin 
> ; Bai, Jie A 
> Subject: Re: [PATCH 3.18 132/134] rcu: Do RCU GP kthread self-wakeup 
> from softirq and interrupt
> 
> On Sat, Mar 23, 2019 at 07:33:15AM +0100, Greg Kroah-Hartman wrote:
> > On Fri, Mar 22, 2019 at 04:00:17PM +, He, Bo wrote:
> > > Hi, Greg:
> > >   Can you hold on the 3.18-stable branch, it seems there are some issue, 
> > > please see the comments from Paul:
> > > 
> > > Comments from Paul:
> > > I subjected all of the others to light rcutorture testing, which 
> > > they passed.  This v3.18 patch hung, however.  Trying it again 
> > > with stock
> > > v3.18 got the same hang, so I believe we can exonerate the patch and give 
> > > it a good firm "maybe" on 3.18.
> > > 
> > > Worth paying special attention to further test results from 3.18.x, 
> > > though!
> > 
> > Ok, I've dropped this from the 3.18.y queue now, thanks.
> 
> Bo, if you know of a "y" for 3.18.y that would likely pass rcutorture 
> testing, please let me know.
> 
>   Thanx, Paul
> 



[PATCH v5 1/2] staging: mt7621-mmc: Remove obsolete Kconfig flags

2019-03-26 Thread George Hilliard
These values are not referred to anywhere else in the kernel. Card
detect is controlled by the device tree property "mediatek,cd-poll",
and there is no driver support for eMMC whatsoever.

Signed-off-by: George Hilliard 
---
v2: Rewrite of v1
v3: [Not present]
v4: Resubmit of v2
v5: No change from v4

 drivers/staging/mt7621-mmc/Kconfig | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/staging/mt7621-mmc/Kconfig 
b/drivers/staging/mt7621-mmc/Kconfig
index 1eb79cd6e22f..01f231dd8511 100644
--- a/drivers/staging/mt7621-mmc/Kconfig
+++ b/drivers/staging/mt7621-mmc/Kconfig
@@ -6,11 +6,3 @@ config MTK_AEE_KDUMP
bool "MTK AEE KDUMP"
depends on MTK_MMC
 
-config MTK_MMC_CD_POLL
-   bool "Card Detect with Polling"
-   depends on MTK_MMC
-
-config MTK_MMC_EMMC_8BIT
-   bool "eMMC 8-bit support"
-   depends on MTK_MMC && RALINK_MT7628
-
-- 
2.21.0



[PATCH v5 0/2] staging: mt7621-mmc: correctness fixes

2019-03-26 Thread George Hilliard
Now formatted according to checkpatch.pl, not my own semi-coherent sense
of what the kernel style should be.  No functionality changes.

George




Re: [PATCH v2] x86/boot: Use EFI setup data if provided

2019-03-26 Thread b...@redhat.com
Hi Junichi,

On 03/26/19 at 02:57pm, Borislav Petkov wrote:
> On Mon, Mar 25, 2019 at 11:10:01PM +, Junichi Nomura wrote:
> > efi_get_rsdp_addr() and kexec_get_rsdp_addr() could be implemented
> > like this (sorry about the pseudo code):
> 
> This doesn't look like what I suggested:
> 
> > So efi_get_rsdp_addr() needs to be refactored in such a way so that at
> > least the loop towards the end gets carved out into a separate function
> > - __efi_get_rsdp_addr() or so - which gets config_tables, nr_tables and
> > size as arguments and finds the RSDP address in the kexec-ed kernel.
> 
> You need to carve out the loop at the end and make it into a separate
> __efi_get_rsdp_addr() function which gets the physical or the virtual
> address.

I guess Boris is suggesting code like below. Please correct me if I am
wrong.

static acpi_physical_address _efi_get_rsdp_addr(efi_config_table tbl, ...)
{
/* Get EFI tables from systab. */
for (i = 0; i < nr_tables; i++) {
...
}
return rsdp_addr;
}

static acpi_physical_address efi_get_rsdp_addr(void)
{
...
/* Get systab from boot params. */  
...
/* Handle EFI bitness properly */
...
return _efi_get_rsdp_addr();
}


static acpi_physical_address kexec_get_rsdp_addr(void)
{
if (!is_kexec_booted)
return 0;

efi_get_setup_data_addr();
...
/* Handle EFI bitness properly */
...
return _efi_get_rsdp_addr();
}

acpi_physical_address get_rsdp_addr(void)
{
acpi_physical_address pa;

pa = get_acpi_rsdp();

if (!pa)
pa = boot_params->acpi_rsdp_addr;


/**
/*I think here we should check if it's kexec booted firstly.
 * Skip it if not kexec. this can avoid the wrong kexec virt
 * addr parsing./
if (!pa)
pa = kexec_get_rdsp_addr(); <--- new function

if (!pa)
pa = efi_get_rsdp_addr();

if (!pa)
pa = bios_get_rsdp_addr();

return pa;
}


[PATCH v3 4/4] Input: add Apple SPI keyboard and trackpad driver.

2019-03-26 Thread Ronald Tschalär
The keyboard and trackpad on recent MacBook's (since 8,1) and
MacBookPro's (13,* and 14,*) are attached to an SPI controller instead
of USB, as previously. The higher level protocol is not publicly
documented and hence has been reverse engineered. As a consequence there
are still a number of unknown fields and commands. However, the known
parts have been working well and received extensive testing and use.

In order for this driver to work, the proper SPI drivers need to be
loaded too; for MB8,1 these are spi_pxa2xx_platform and spi_pxa2xx_pci;
for all others they are spi_pxa2xx_platform and intel_lpss_pci. For this
reason enabling this driver in the config implies enabling the above
drivers.

CC: Federico Lorenzi 
CC: Lukas Wunner 
CC: Andy Shevchenko 
Link: https://bugzilla.kernel.org/show_bug.cgi?id=99891
Link: https://bugzilla.kernel.org/show_bug.cgi?id=108331
Signed-off-by: Ronald Tschalär 
---
 drivers/input/keyboard/Kconfig|   15 +
 drivers/input/keyboard/Makefile   |1 +
 drivers/input/keyboard/applespi.c | 1988 +
 3 files changed, 2004 insertions(+)
 create mode 100644 drivers/input/keyboard/applespi.c

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index a878351f1643..d0a9e7fa2508 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -70,6 +70,21 @@ config KEYBOARD_AMIGA
 config ATARI_KBD_CORE
bool
 
+config KEYBOARD_APPLESPI
+   tristate "Apple SPI keyboard and trackpad"
+   depends on ACPI && EFI
+   depends on SPI
+   depends on X86 || COMPILE_TEST
+   imply SPI_PXA2XX
+   imply SPI_PXA2XX_PCI
+   imply MFD_INTEL_LPSS_PCI
+   help
+ Say Y here if you are running Linux on any Apple MacBook8,1 or later,
+ or any MacBookPro13,* or MacBookPro14,*.
+
+ To compile this driver as a module, choose M here: the
+ module will be called applespi.
+
 config KEYBOARD_ATARI
tristate "Atari keyboard"
depends on ATARI
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
index 182e92985dbf..9283fee2505a 100644
--- a/drivers/input/keyboard/Makefile
+++ b/drivers/input/keyboard/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_KEYBOARD_ADP5520)+= 
adp5520-keys.o
 obj-$(CONFIG_KEYBOARD_ADP5588) += adp5588-keys.o
 obj-$(CONFIG_KEYBOARD_ADP5589) += adp5589-keys.o
 obj-$(CONFIG_KEYBOARD_AMIGA)   += amikbd.o
+obj-$(CONFIG_KEYBOARD_APPLESPI)+= applespi.o
 obj-$(CONFIG_KEYBOARD_ATARI)   += atakbd.o
 obj-$(CONFIG_KEYBOARD_ATKBD)   += atkbd.o
 obj-$(CONFIG_KEYBOARD_BCM) += bcm-keypad.o
diff --git a/drivers/input/keyboard/applespi.c 
b/drivers/input/keyboard/applespi.c
new file mode 100644
index ..39e38d98869e
--- /dev/null
+++ b/drivers/input/keyboard/applespi.c
@@ -0,0 +1,1988 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MacBook (Pro) SPI keyboard and touchpad driver
+ *
+ * Copyright (c) 2015-2018 Federico Lorenzi
+ * Copyright (c) 2017-2018 Ronald Tschalär
+ */
+
+/*
+ * The keyboard and touchpad controller on the MacBookAir6, MacBookPro12,
+ * MacBook8 and newer can be driven either by USB or SPI. However the USB
+ * pins are only connected on the MacBookAir6 and 7 and the MacBookPro12.
+ * All others need this driver. The interface is selected using ACPI methods:
+ *
+ * * UIEN ("USB Interface Enable"): If invoked with argument 1, disables SPI
+ *   and enables USB. If invoked with argument 0, disables USB.
+ * * UIST ("USB Interface Status"): Returns 1 if USB is enabled, 0 otherwise.
+ * * SIEN ("SPI Interface Enable"): If invoked with argument 1, disables USB
+ *   and enables SPI. If invoked with argument 0, disables SPI.
+ * * SIST ("SPI Interface Status"): Returns 1 if SPI is enabled, 0 otherwise.
+ * * ISOL: Resets the four GPIO pins used for SPI. Intended to be invoked with
+ *   argument 1, then once more with argument 0.
+ *
+ * UIEN and UIST are only provided on models where the USB pins are connected.
+ *
+ * SPI-based Protocol
+ * --
+ *
+ * The device and driver exchange messages (struct message); each message is
+ * encapsulated in one or more packets (struct spi_packet). There are two types
+ * of exchanges: reads, and writes. A read is signaled by a GPE, upon which one
+ * message can be read from the device. A write exchange consists of writing a
+ * command message, immediately reading a short status packet, and then, upon
+ * receiving a GPE, reading the response message. Write exchanges cannot be
+ * interleaved, i.e. a new write exchange must not be started till the previous
+ * write exchange is complete. Whether a received message is part of a read or
+ * write exchange is indicated in the encapsulating packet's flags field.
+ *
+ * A single message may be too large to fit in a single packet (which has a
+ * fixed, 256-byte size). In that case it will be split over multiple,
+ * 

[PATCH v3 1/4] drm/bridge: sil_sii8620: depend on INPUT instead of selecting it.

2019-03-26 Thread Ronald Tschalär
commit d6abe6df706c66d803e6dd4fe98c1b6b7f125a56 (drm/bridge:
sil_sii8620: do not have a dependency of RC_CORE) added a dependency on
INPUT. However, this causes problems with other drivers, in particular
an input driver that depends on MFD_INTEL_LPSS_PCI (to be added in a
future commit):

  drivers/clk/Kconfig:9:error: recursive dependency detected!
  drivers/clk/Kconfig:9:symbol COMMON_CLK is selected by MFD_INTEL_LPSS
  drivers/mfd/Kconfig:566:  symbol MFD_INTEL_LPSS is selected by 
MFD_INTEL_LPSS_PCI
  drivers/mfd/Kconfig:580:  symbol MFD_INTEL_LPSS_PCI is implied by 
KEYBOARD_APPLESPI
  drivers/input/keyboard/Kconfig:73:symbol KEYBOARD_APPLESPI depends on 
INPUT
  drivers/input/Kconfig:8:  symbol INPUT is selected by DRM_SIL_SII8620
  drivers/gpu/drm/bridge/Kconfig:83:symbol DRM_SIL_SII8620 depends on 
DRM_BRIDGE
  drivers/gpu/drm/bridge/Kconfig:1: symbol DRM_BRIDGE is selected by 
DRM_PL111
  drivers/gpu/drm/pl111/Kconfig:1:  symbol DRM_PL111 depends on COMMON_CLK

According to the docs, select should only be used for non-visible
symbols. Furthermore almost all other references to INPUT throughout the
kernel config are depends, not selects. Hence this change.

CC: Inki Dae 
CC: Andrzej Hajda 
Signed-off-by: Ronald Tschalär 
---
 drivers/gpu/drm/bridge/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index 2fee47b0d50b..eabedc83f25c 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -83,9 +83,9 @@ config DRM_PARADE_PS8622
 config DRM_SIL_SII8620
tristate "Silicon Image SII8620 HDMI/MHL bridge"
depends on OF
+   depends on INPUT
select DRM_KMS_HELPER
imply EXTCON
-   select INPUT
select RC_CORE
help
  Silicon Image SII8620 HDMI/MHL bridge chip driver.
-- 
2.20.1



  1   2   3   4   5   6   7   8   9   10   >