[PATCH v2 16/16] ASoC: fsl_ssi: Use ssi->streams instead of reading register

2018-01-10 Thread Nicolin Chen
Since ssi->streams is being updated along with SCR register and
its SSIEN bit, it's simpler to use it instead.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 0754eeb..52ddce1 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -796,11 +796,6 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
unsigned int sample_size = params_width(hw_params);
u32 wl = SSI_SxCCR_WL(sample_size);
int ret;
-   u32 scr;
-   int enabled;
-
-   regmap_read(regs, REG_SSI_SCR, );
-   enabled = scr & SSI_SCR_SSIEN;
 
/*
 * SSI is properly configured if it is enabled and running in
@@ -808,7 +803,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->synchronous)
+   if (ssi->streams && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
-- 
2.7.4



[PATCH v2 15/16] ASoC: fsl_ssi: Move DT related code to a separate probe()

2018-01-10 Thread Nicolin Chen
This patch cleans up probe() function by moving all Device Tree
related code into a separate function. It allows the probe() to
be Device Tree independent. This will be very useful for future
integration of imx-ssi driver which has similar functionalities
while exists only because it supports non-DT cases.

This patch also moves symmetric_channels of AC97 from the probe
to the structure snd_soc_dai_driver for simplification.

Additionally, since PowerPC and AC97 use the same pdev pointer
to register a platform device, this patch also unifies related
code.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 204 +---
 1 file changed, 108 insertions(+), 96 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 716603c..0754eeb 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -234,8 +234,12 @@ struct fsl_ssi_soc_data {
  *
  * @fiq_params: FIQ stream filtering parameters
  *
- * @pdev: Pointer to pdev when using fsl-ssi as sound card (ppc only)
- *TODO: Should be replaced with simple-sound-card
+ * @card_pdev: Platform_device pointer when using fsl-ssi as sound card
+ * (PowerPC or AC97 only)
+ * @card_name: Platform_device name when using fsl-ssi as sound card
+ * (PowerPC or AC97 only)
+ * @card_idx: The index of SSI when registering a sound card
+ * (PowerPC or AC97 only)
  *
  * @dbg_stats: Debugging statistics
  *
@@ -279,7 +283,9 @@ struct fsl_ssi {
 
struct imx_pcm_fiq_params fiq_params;
 
-   struct platform_device *pdev;
+   struct platform_device *card_pdev;
+   char card_name[32];
+   u32 card_idx;
 
struct fsl_ssi_dbg dbg_stats;
 
@@ -1123,6 +1129,7 @@ static const struct snd_soc_component_driver 
fsl_ssi_component = {
 
 static struct snd_soc_dai_driver fsl_ssi_ac97_dai = {
.bus_control = true,
+   .symmetric_channels = 1,
.probe = fsl_ssi_dai_probe,
.playback = {
.stream_name = "AC97 Playback",
@@ -1274,9 +1281,7 @@ static void make_lowercase(char *s)
 static int fsl_ssi_imx_probe(struct platform_device *pdev,
 struct fsl_ssi *ssi, void __iomem *iomem)
 {
-   struct device_node *np = pdev->dev.of_node;
struct device *dev = >dev;
-   u32 dmas[4];
int ret;
 
/* Backward compatible for a DT without ipg clock name assigned */
@@ -1310,14 +1315,8 @@ static int fsl_ssi_imx_probe(struct platform_device 
*pdev,
ssi->dma_params_tx.addr = ssi->ssi_phys + REG_SSI_STX0;
ssi->dma_params_rx.addr = ssi->ssi_phys + REG_SSI_SRX0;
 
-   /* Set to dual FIFO mode according to the SDMA sciprt */
-   ret = of_property_read_u32_array(np, "dmas", dmas, 4);
-   if (ssi->use_dma && !ret && dmas[2] == IMX_DMATYPE_SSI_DUAL) {
-   ssi->use_dual_fifo = true;
-   /*
-* Use even numbers to avoid channel swap due to SDMA
-* script design
-*/
+   /* Use even numbers to avoid channel swap due to SDMA script design */
+   if (ssi->use_dual_fifo) {
ssi->dma_params_tx.maxburst &= ~0x1;
ssi->dma_params_rx.maxburst &= ~0x1;
}
@@ -1358,42 +1357,103 @@ static void fsl_ssi_imx_clean(struct platform_device 
*pdev, struct fsl_ssi *ssi)
clk_disable_unprepare(ssi->clk);
 }
 
-static int fsl_ssi_probe(struct platform_device *pdev)
+static int fsl_ssi_probe_from_dt(struct fsl_ssi *ssi)
 {
-   struct snd_soc_dai_driver *cpu_dai_drv;
-   struct fsl_ssi *ssi;
-   int ret = 0;
-   struct device_node *np = pdev->dev.of_node;
-   struct device *dev = >dev;
+   struct device *dev = ssi->dev;
+   struct device_node *np = dev->of_node;
const struct of_device_id *of_id;
const char *p, *sprop;
const uint32_t *iprop;
-   struct resource *res;
-   void __iomem *iomem;
-   char name[64];
-   struct regmap_config regconfig = fsl_ssi_regconfig;
+   u32 dmas[4];
+   int ret;
 
of_id = of_match_device(fsl_ssi_ids, dev);
if (!of_id || !of_id->data)
return -EINVAL;
 
-   ssi = devm_kzalloc(dev, sizeof(*ssi), GFP_KERNEL);
-   if (!ssi)
-   return -ENOMEM;
-
ssi->soc = of_id->data;
-   ssi->dev = dev;
+
+   ret = of_property_match_string(np, "clock-names", "ipg");
+   /* Get error code if not found */
+   ssi->has_ipg_clk_name = ret >= 0;
 
/* Check if being used in AC97 mode */
sprop = of_get_property(np, "fsl,mode", NULL);
-   if (sprop) {
-   if (!strcmp(sprop, "ac97-slave"))
-   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
+   if (sprop && !strcmp(sprop, "ac97-slave")) {
+   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
+
+   ret = 

[PATCH v2 14/16] ASoC: fsl_ssi: Remove cpu_dai_drv from fsl_ssi structure

2018-01-10 Thread Nicolin Chen
The cpu_dai_drv is only used for symmetric_rates. So this patch replaces
it with a synchronous boolean flag.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 32 
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 213962a..716603c 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -208,11 +208,11 @@ struct fsl_ssi_soc_data {
  *
  * @regs: Pointer to the regmap registers
  * @irq: IRQ of this SSI
- * @cpu_dai_drv: CPU DAI driver for this device
  *
  * @dai_fmt: DAI configuration this device is currently used with
  * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @i2s_net: I2S and Network mode configurations of SCR register
+ * @synchronous: Use synchronous mode - both of TX and RX use STCK and SFCK
  * @use_dma: DMA is used or FIQ with stream filter
  * @use_dual_fifo: DMA with support for dual FIFO mode
  * @has_ipg_clk_name: If "ipg" is in the clock name list of device tree
@@ -253,11 +253,11 @@ struct fsl_ssi_soc_data {
 struct fsl_ssi {
struct regmap *regs;
int irq;
-   struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
u8 streams;
u8 i2s_net;
+   bool synchronous;
bool use_dma;
bool use_dual_fifo;
bool has_ipg_clk_name;
@@ -668,7 +668,6 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
bool tx2, tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
struct regmap *regs = ssi->regs;
-   int synchronous = ssi->cpu_dai_drv.symmetric_rates, ret;
u32 pm = 999, div2, psr, stccr, mask, afreq, factor, i;
unsigned long clkrate, baudrate, tmprate;
unsigned int slots = params_channels(hw_params);
@@ -676,6 +675,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
u64 sub, savesub = 10;
unsigned int freq;
bool baudclk_is_used;
+   int ret;
 
/* Override slots and slot_width if being specifically set... */
if (ssi->slots)
@@ -754,7 +754,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream 
*substream,
mask = SSI_SxCCR_PM_MASK | SSI_SxCCR_DIV2 | SSI_SxCCR_PSR;
 
/* STCCR is used for RX in synchronous mode */
-   tx2 = tx || synchronous;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), mask, stccr);
 
if (!baudclk_is_used) {
@@ -802,7 +802,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
 * that should set separate configurations for STCCR and SRCCR
 * despite running in the synchronous mode.
 */
-   if (enabled && ssi->cpu_dai_drv.symmetric_rates)
+   if (enabled && ssi->synchronous)
return 0;
 
if (fsl_ssi_is_i2s_master(ssi)) {
@@ -834,7 +834,7 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-   tx2 = tx || ssi->cpu_dai_drv.symmetric_rates;
+   tx2 = tx || ssi->synchronous;
regmap_update_bits(regs, REG_SSI_SxCCR(tx2), SSI_SxCCR_WL_MASK, wl);
 
return 0;
@@ -959,7 +959,7 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, 
unsigned int fmt)
srcr = strcr;
 
/* Set SYN mode and clear RXDIR bit when using SYN or AC97 mode */
-   if (ssi->cpu_dai_drv.symmetric_rates || fsl_ssi_is_ac97(ssi)) {
+   if (ssi->synchronous || fsl_ssi_is_ac97(ssi)) {
srcr &= ~SSI_SRCR_RXDIR;
scr |= SSI_SCR_SYN;
}
@@ -1360,6 +1360,7 @@ static void fsl_ssi_imx_clean(struct platform_device 
*pdev, struct fsl_ssi *ssi)
 
 static int fsl_ssi_probe(struct platform_device *pdev)
 {
+   struct snd_soc_dai_driver *cpu_dai_drv;
struct fsl_ssi *ssi;
int ret = 0;
struct device_node *np = pdev->dev.of_node;
@@ -1394,14 +1395,12 @@ static int fsl_ssi_probe(struct platform_device *pdev)
ssi->use_dma = !of_property_read_bool(np, "fsl,fiq-stream-filter");
 
if (fsl_ssi_is_ac97(ssi)) {
-   memcpy(>cpu_dai_drv, _ssi_ac97_dai,
-  sizeof(fsl_ssi_ac97_dai));
+   cpu_dai_drv = _ssi_ac97_dai;
fsl_ac97_data = ssi;
} else {
-   memcpy(>cpu_dai_drv, _ssi_dai_template,
-  sizeof(fsl_ssi_dai_template));
+   cpu_dai_drv = _ssi_dai_template;
}
-   ssi->cpu_dai_drv.name = dev_name(dev);
+   cpu_dai_drv->name = dev_name(dev);
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
iomem = devm_ioremap_resource(dev, res);
@@ -1439,11 +1438,12 @@ static int fsl_ssi_probe(struct platform_device *pdev)
/* Set software limitations for synchronous mode */
if 

[PATCH v2 13/16] ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()

2018-01-10 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() is a helper function being called from
fsl_ssi_set_dai_fmt() as an ASoC operation and fsl_ssi_hw_init()
mainly for AC97 format initialization.

This patch cleans the _fsl_ssi_set_dai_fmt() in following ways:
* Removing *dev pointer in the parameters as it's included in the
  *ssi pointer of struct fsl_ssi.
* Using regmap_update_bits() instead of regmap_read() with masking
  the value manually.
* Removing TXBIT0 configurations since this bit is set to 1 as its
  reset value and there is no use case so far to unset it. And it
  is safe to remove since regmap_update_bits() won't touch it.
* Moving baudclk check to the switch-case routine to skip the I2S
  master check. And moving SxCCR.DC settings after baudclk check.
* Adding format settings for SND_SOC_DAIFMT_AC97 like others.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 70 ++---
 1 file changed, 31 insertions(+), 39 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 178c192..213962a 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -855,42 +855,27 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream 
*substream,
return 0;
 }
 
-static int _fsl_ssi_set_dai_fmt(struct device *dev,
-   struct fsl_ssi *ssi, unsigned int fmt)
+static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt)
 {
-   struct regmap *regs = ssi->regs;
-   u32 strcr = 0, stcr, srcr, scr, mask;
+   u32 strcr = 0, scr = 0, stcr, srcr, mask;
 
ssi->dai_fmt = fmt;
 
-   if (fsl_ssi_is_i2s_master(ssi) && IS_ERR(ssi->baudclk)) {
-   dev_err(dev, "missing baudclk for master mode\n");
-   return -EINVAL;
-   }
-
-   regmap_read(regs, REG_SSI_SCR, );
-   scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
scr |= SSI_SCR_SYNC_TX_FS;
 
-   mask = SSI_STCR_TXBIT0 | SSI_STCR_TFDIR | SSI_STCR_TXDIR |
-  SSI_STCR_TSCKP | SSI_STCR_TFSI | SSI_STCR_TFSL | SSI_STCR_TEFS;
-   regmap_read(regs, REG_SSI_STCR, );
-   regmap_read(regs, REG_SSI_SRCR, );
-   stcr &= ~mask;
-   srcr &= ~mask;
-
/* Use Network mode as default */
ssi->i2s_net = SSI_SCR_NET;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
-   regmap_update_bits(regs, REG_SSI_STCCR,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
-   regmap_update_bits(regs, REG_SSI_SRCCR,
-  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFS:
case SND_SOC_DAIFMT_CBS_CFS:
+   if (IS_ERR(ssi->baudclk)) {
+   dev_err(ssi->dev,
+   "missing baudclk for master mode\n");
+   return -EINVAL;
+   }
ssi->i2s_net |= SSI_SCR_I2S_MODE_MASTER;
break;
case SND_SOC_DAIFMT_CBM_CFM:
@@ -900,30 +885,34 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
+   regmap_update_bits(ssi->regs, REG_SSI_STCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+   regmap_update_bits(ssi->regs, REG_SSI_SRCCR,
+  SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2));
+
/* Data on rising edge of bclk, frame low, 1clk before data */
-   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_LEFT_J:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TXBIT0 | SSI_STCR_TSCKP;
+   strcr |= SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_DSP_A:
/* Data on rising edge of bclk, frame high, 1clk before data */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP |
-SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TEFS;
break;
case SND_SOC_DAIFMT_DSP_B:
/* Data on rising edge of bclk, frame high */
-   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP | SSI_STCR_TXBIT0;
+   strcr |= SSI_STCR_TFSL | SSI_STCR_TSCKP;
break;
case SND_SOC_DAIFMT_AC97:
/* Data on falling edge of bclk, frame high, 1clk before data */
-   ssi->i2s_net |= SSI_SCR_I2S_MODE_NORMAL;
+   strcr |= 

[PATCH v2 12/16] ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()

2018-01-10 Thread Nicolin Chen
AC97 configures most of registers earlier to start a communication
with CODECs in order to successfully initialize CODEC. Currently,
_fsl_ssi_set_dai_fmt() and fsl_ssi_setup_ac97() are called to get
all SSI registers properly set.

Since now the driver has a fsl_ssi_hw_init() to handle all register
initial settings, this patch moves those register settings of AC97
to the fsl_ssi_hw_init() as well.

Meanwhile it applies _fsl_ssi_set_dai_fmt() call to AC97 only since
other formats would be configured via normal set_dai_fmt() directly.

This patch also adds fsl_ssi_hw_clean() to cleanup control bits for
AC97 in the platform remote() function.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 26 --
 1 file changed, 20 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 36e370e..178c192 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -982,9 +982,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
-   fsl_ssi_setup_ac97(ssi);
-
return 0;
 }
 
@@ -1250,10 +1247,28 @@ static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
regmap_update_bits(ssi->regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
 
+   /* AC97 should start earlier to communicate with CODECs */
+   if (fsl_ssi_is_ac97(ssi)) {
+   _fsl_ssi_set_dai_fmt(ssi->dev, ssi, ssi->dai_fmt);
+   fsl_ssi_setup_ac97(ssi);
+   }
+
return 0;
 }
 
 /**
+ * Clear SSI registers
+ */
+static void fsl_ssi_hw_clean(struct fsl_ssi *ssi)
+{
+   /* Disable registers for AC97 */
+   if (fsl_ssi_is_ac97(ssi)) {
+   regmap_write(ssi->regs, REG_SSI_SCR, 0);
+   regmap_write(ssi->regs, REG_SSI_SACNT, 0);
+   regmap_write(ssi->regs, REG_SSI_SOR, 0);
+   }
+}
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1535,9 +1550,6 @@ static int fsl_ssi_probe(struct platform_device *pdev)
}
 
 done:
-   if (ssi->dai_fmt)
-   _fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
-
/* Initially configures SSI registers */
fsl_ssi_hw_init(ssi);
 
@@ -1582,6 +1594,8 @@ static int fsl_ssi_remove(struct platform_device *pdev)
 {
struct fsl_ssi *ssi = dev_get_drvdata(>dev);
 
+   fsl_ssi_hw_clean(ssi);
+
fsl_ssi_debugfs_remove(>dbg_stats);
 
if (ssi->pdev)
-- 
2.7.4



[PATCH v2 11/16] ASoC: fsl_ssi: Move one-time configurations to probe()

2018-01-10 Thread Nicolin Chen
The probe() could handle some one-time configurations since
they will not be changed once being configured.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 39 ++-
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 2c179a7..36e370e 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -860,7 +860,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 {
struct regmap *regs = ssi->regs;
u32 strcr = 0, stcr, srcr, scr, mask;
-   u8 wm;
 
ssi->dai_fmt = fmt;
 
@@ -869,8 +868,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
return -EINVAL;
}
 
-   fsl_ssi_setup_regvals(ssi);
-
regmap_read(regs, REG_SSI_SCR, );
scr &= ~(SSI_SCR_SYN | SSI_SCR_I2S_MODE_MASK);
/* Synchronize frame sync clock for TE to avoid data slipping */
@@ -985,16 +982,6 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
regmap_write(regs, REG_SSI_SRCR, srcr);
regmap_write(regs, REG_SSI_SCR, scr);
 
-   wm = ssi->fifo_watermark;
-
-   regmap_write(regs, REG_SSI_SFCSR,
-SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
-SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
-
-   if (ssi->use_dual_fifo)
-   regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
 
@@ -1244,6 +1231,29 @@ static struct snd_ac97_bus_ops fsl_ssi_ac97_ops = {
 };
 
 /**
+ * Initialize SSI registers
+ */
+static int fsl_ssi_hw_init(struct fsl_ssi *ssi)
+{
+   u32 wm = ssi->fifo_watermark;
+
+   /* Initialize regvals */
+   fsl_ssi_setup_regvals(ssi);
+
+   /* Set watermarks */
+   regmap_write(ssi->regs, REG_SSI_SFCSR,
+SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
+SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
+
+   /* Enable Dual FIFO mode */
+   if (ssi->use_dual_fifo)
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
+
+   return 0;
+}
+
+/**
  * Make every character in a string lower-case
  */
 static void make_lowercase(char *s)
@@ -1528,6 +1538,9 @@ static int fsl_ssi_probe(struct platform_device *pdev)
if (ssi->dai_fmt)
_fsl_ssi_set_dai_fmt(dev, ssi, ssi->dai_fmt);
 
+   /* Initially configures SSI registers */
+   fsl_ssi_hw_init(ssi);
+
if (fsl_ssi_is_ac97(ssi)) {
u32 ssi_idx;
 
-- 
2.7.4



[PATCH v2 10/16] ASoC: fsl_ssi: Use snd_soc_init_dma_data instead

2018-01-10 Thread Nicolin Chen
Since there is a helper function, use it to help readability.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index e75b57d..2c179a7 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1105,10 +1105,9 @@ static int fsl_ssi_dai_probe(struct snd_soc_dai *dai)
 {
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(dai);
 
-   if (ssi->soc->imx && ssi->use_dma) {
-   dai->playback_dma_data = >dma_params_tx;
-   dai->capture_dma_data = >dma_params_rx;
-   }
+   if (ssi->soc->imx && ssi->use_dma)
+   snd_soc_dai_init_dma_data(dai, >dma_params_tx,
+ >dma_params_rx);
 
return 0;
 }
-- 
2.7.4



[PATCH v2 09/16] ASoC: fsl_ssi: Set xFEN0 and xFEN1 together

2018-01-10 Thread Nicolin Chen
It'd be safer to enable both FIFOs for TX or RX at the same time.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 4399a22..e75b57d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -586,6 +586,11 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
if (fsl_ssi_is_ac97(ssi))
vals[RX].scr = vals[TX].scr = 0;
 
+   if (ssi->use_dual_fifo) {
+   vals[RX].srcr |= SSI_SRCR_RFEN1;
+   vals[TX].stcr |= SSI_STCR_TFEN1;
+   }
+
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
vals[TX].sier |= SSI_SIER_TDMAE;
@@ -986,14 +991,9 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
 SSI_SFCSR_TFWM0(wm) | SSI_SFCSR_RFWM0(wm) |
 SSI_SFCSR_TFWM1(wm) | SSI_SFCSR_RFWM1(wm));
 
-   if (ssi->use_dual_fifo) {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  SSI_SRCR_RFEN1, SSI_SRCR_RFEN1);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  SSI_STCR_TFEN1, SSI_STCR_TFEN1);
+   if (ssi->use_dual_fifo)
regmap_update_bits(regs, REG_SSI_SCR,
   SSI_SCR_TCH_EN, SSI_SCR_TCH_EN);
-   }
 
if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_AC97)
fsl_ssi_setup_ac97(ssi);
-- 
2.7.4



[PATCH v2 08/16] ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()

2018-01-10 Thread Nicolin Chen
This patch cleans fsl_ssi_setup_regvals() by following changes:
1) Moving DBG bits to the first lines.
2) Setting SSIE, RE/TE as default and cleaning it for AC97

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 17 ++---
 1 file changed, 6 insertions(+), 11 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index b449b8b..4399a22 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -575,18 +575,16 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
 {
struct fsl_ssi_regvals *vals = ssi->regvals;
 
-   vals[RX].sier = SSI_SIER_RFF0_EN;
+   vals[RX].sier = SSI_SIER_RFF0_EN | FSLSSI_SIER_DBG_RX_FLAGS;
vals[RX].srcr = SSI_SRCR_RFEN0;
-   vals[RX].scr = 0;
-   vals[TX].sier = SSI_SIER_TFE0_EN;
+   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
+   vals[TX].sier = SSI_SIER_TFE0_EN | FSLSSI_SIER_DBG_TX_FLAGS;
vals[TX].stcr = SSI_STCR_TFEN0;
-   vals[TX].scr = 0;
+   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
 
/* AC97 has already enabled SSIEN, RE and TE, so ignore them */
-   if (!fsl_ssi_is_ac97(ssi)) {
-   vals[RX].scr = SSI_SCR_SSIEN | SSI_SCR_RE;
-   vals[TX].scr = SSI_SCR_SSIEN | SSI_SCR_TE;
-   }
+   if (fsl_ssi_is_ac97(ssi))
+   vals[RX].scr = vals[TX].scr = 0;
 
if (ssi->use_dma) {
vals[RX].sier |= SSI_SIER_RDMAE;
@@ -595,9 +593,6 @@ static void fsl_ssi_setup_regvals(struct fsl_ssi *ssi)
vals[RX].sier |= SSI_SIER_RIE;
vals[TX].sier |= SSI_SIER_TIE;
}
-
-   vals[RX].sier |= FSLSSI_SIER_DBG_RX_FLAGS;
-   vals[TX].sier |= FSLSSI_SIER_DBG_TX_FLAGS;
 }
 
 static void fsl_ssi_setup_ac97(struct fsl_ssi *ssi)
-- 
2.7.4



[PATCH v2 06/16] ASoC: fsl_ssi: Clean up helper functions of trigger()

2018-01-10 Thread Nicolin Chen
The trigger() calls fsl_ssi_tx_config() and fsl_ssi_rx_config(),
and both of them jump to fsl_ssi_config(). And fsl_ssi_config()
later calls another fsl_ssi_rxtx_config().

However, the whole routine, especially fsl_ssi_config() function,
is too complicated because of the folowing reasons:
1) It has to handle the concern of the opposite stream.
2) It has to handle cases of offline configurations support.
3) It has to handle enable and disable operations while they're
   mostly different.

Since the enable and disable routines have more differences than
TX and RX rountines, this patch simplifies these helper functions
with the following changes:
- Changing to two helper functions of enable and disable instead
  of TX and RX.
- Removing fsl_ssi_rxtx_config() by separately integrating it to
  two newly introduced enable & disable functions.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 256 +++-
 1 file changed, 122 insertions(+), 134 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 263c067..09a571a 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -378,31 +378,83 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
 }
 
 /**
- * Enable or disable all rx/tx config flags at once
+ * Set SCR, SIER, STCR and SRCR registers with cached values in regvals
+ *
+ * Notes:
+ * 1) For offline_config SoCs, enable all necessary bits of both streams
+ *when 1st stream starts, even if the opposite stream will not start
+ * 2) It also clears FIFO before setting regvals; SOR is safe to set online
  */
-static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool enable)
+static void fsl_ssi_config_enable(struct fsl_ssi *ssi, bool tx)
 {
-   struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *vals = ssi->regvals;
+   bool dir = tx ? TX : RX;
+   u32 sier, srcr, stcr;
 
-   if (enable) {
-   regmap_update_bits(regs, REG_SSI_SIER,
-  vals[RX].sier | vals[TX].sier,
-  vals[RX].sier | vals[TX].sier);
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  vals[RX].srcr | vals[TX].srcr,
-  vals[RX].srcr | vals[TX].srcr);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr,
-  vals[RX].stcr | vals[TX].stcr);
+   /* Clear dirty data in the FIFO; It also prevents channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
+
+   /*
+* On offline_config SoCs, SxCR and SIER are already configured when
+* the previous stream started. So skip all SxCR and SIER settings
+* to prevent online reconfigurations, then jump to set SCR directly
+*/
+   if (ssi->soc->offline_config && ssi->streams)
+   goto enable_scr;
+
+   if (ssi->soc->offline_config) {
+   /*
+* Online reconfiguration not supported, so enable all bits for
+* both streams at once to avoid necessity of reconfigurations
+*/
+   srcr = vals[RX].srcr | vals[TX].srcr;
+   stcr = vals[RX].stcr | vals[TX].stcr;
+   sier = vals[RX].sier | vals[TX].sier;
} else {
-   regmap_update_bits(regs, REG_SSI_SRCR,
-  vals[RX].srcr | vals[TX].srcr, 0);
-   regmap_update_bits(regs, REG_SSI_STCR,
-  vals[RX].stcr | vals[TX].stcr, 0);
-   regmap_update_bits(regs, REG_SSI_SIER,
-  vals[RX].sier | vals[TX].sier, 0);
+   /* Otherwise, only set bits for the current stream */
+   srcr = vals[dir].srcr;
+   stcr = vals[dir].stcr;
+   sier = vals[dir].sier;
}
+
+   /* Configure SRCR, STCR and SIER at once */
+   regmap_update_bits(ssi->regs, REG_SSI_SRCR, srcr, srcr);
+   regmap_update_bits(ssi->regs, REG_SSI_STCR, stcr, stcr);
+   regmap_update_bits(ssi->regs, REG_SSI_SIER, sier, sier);
+
+enable_scr:
+   /*
+* Start DMA before setting TE to avoid FIFO underrun
+* which may cause a channel slip or a channel swap
+*
+* TODO: FIQ cases might also need this upon testing
+*/
+   if (ssi->use_dma && tx) {
+   int try = 100;
+   u32 sfcsr;
+
+   /* Enable SSI first to send TX DMA request */
+   regmap_update_bits(ssi->regs, REG_SSI_SCR,
+  SSI_SCR_SSIEN, SSI_SCR_SSIEN);
+
+   /* Busy wait until TX FIFO not empty -- DMA working */
+   do {
+   

[PATCH v2 07/16] ASoC: fsl_ssi: Add DAIFMT define for AC97

2018-01-10 Thread Nicolin Chen
The _fsl_ssi_set_dai_fmt() bypasses an undefined format for AC97
mode. However, it's not really necessary if AC97 has its complete
format defined.

So this patch adds a DAIFMT macro of complete format including a
clock direction and polarity.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 09a571a..b449b8b 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -86,6 +86,16 @@
 SNDRV_PCM_FMTBIT_S24_LE)
 #endif
 
+/*
+ * In AC97 mode, TXDIR bit is forced to 0 and TFDIR bit is forced to 1:
+ *  - SSI inputs external bit clock and outputs frame sync clock -- CBM_CFS
+ *  - Also have NB_NF to mark these two clocks will not be inverted
+ */
+#define FSLSSI_AC97_DAIFMT \
+   (SND_SOC_DAIFMT_AC97 | \
+SND_SOC_DAIFMT_CBM_CFS | \
+SND_SOC_DAIFMT_NB_NF)
+
 #define FSLSSI_SIER_DBG_RX_FLAGS \
(SSI_SIER_RFF0_EN | \
 SSI_SIER_RLS_EN | \
@@ -959,8 +969,7 @@ static int _fsl_ssi_set_dai_fmt(struct device *dev,
scr &= ~SSI_SCR_SYS_CLK_EN;
break;
default:
-   if (!fsl_ssi_is_ac97(ssi))
-   return -EINVAL;
+   return -EINVAL;
}
 
stcr |= strcr;
@@ -1367,7 +1376,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
sprop = of_get_property(np, "fsl,mode", NULL);
if (sprop) {
if (!strcmp(sprop, "ac97-slave"))
-   ssi->dai_fmt = SND_SOC_DAIFMT_AC97;
+   ssi->dai_fmt = FSLSSI_AC97_DAIFMT;
}
 
/* Select DMA or FIQ */
-- 
2.7.4



[PATCH v2 05/16] ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()

2018-01-10 Thread Nicolin Chen
The FIFO clear helper function is just one line of code now.
So it could be cleaned up by removing it and calling regmap
directly.

Meanwhile, FIFO clear could be applied to all use cases, not
confined to AC97. So this patch also moves FIFO clear in the
trigger() to fsl_ssi_config() and removes the AC97 check.

Note that SOR register is safe from offline_config HW limit.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 31 +--
 1 file changed, 9 insertions(+), 22 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index f026386..263c067 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -406,17 +406,6 @@ static void fsl_ssi_rxtx_config(struct fsl_ssi *ssi, bool 
enable)
 }
 
 /**
- * Clear remaining data in the FIFO to avoid dirty data or channel slipping
- */
-static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool is_rx)
-{
-   bool tx = !is_rx;
-
-   regmap_update_bits(ssi->regs, REG_SSI_SOR,
-  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
-}
-
-/**
  * Exclude bits that are used by the opposite stream
  *
  * When both streams are active, disabling some bits for the current stream
@@ -442,7 +431,8 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
-   bool dir = (>regvals[TX] == vals) ? TX : RX;
+   bool tx = >regvals[TX] == vals;
+   bool dir = tx ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
bool aactive;
@@ -484,7 +474,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 
/* Online configure single direction while SSI is running */
if (enable) {
-   fsl_ssi_fifo_clear(ssi, vals->scr & SSI_SCR_RE);
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
 
regmap_update_bits(regs, REG_SSI_SRCR, vals->srcr, vals->srcr);
regmap_update_bits(regs, REG_SSI_STCR, vals->stcr, vals->stcr);
@@ -506,6 +498,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
regmap_update_bits(regs, REG_SSI_SRCR, srcr, 0);
regmap_update_bits(regs, REG_SSI_STCR, stcr, 0);
regmap_update_bits(regs, REG_SSI_SIER, sier, 0);
+
+   /* Clear FIFO to prevent dirty data or channel slipping */
+   regmap_update_bits(ssi->regs, REG_SSI_SOR,
+  SSI_SOR_xX_CLR(tx), SSI_SOR_xX_CLR(tx));
}
 
 config_done:
@@ -1086,7 +1082,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi *ssi = snd_soc_dai_get_drvdata(rtd->cpu_dai);
-   struct regmap *regs = ssi->regs;
 
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -,14 +1106,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream 
*substream, int cmd,
return -EINVAL;
}
 
-   /* Clear corresponding FIFO */
-   if (fsl_ssi_is_ac97(ssi)) {
-   if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_TX_CLR);
-   else
-   regmap_write(regs, REG_SSI_SOR, SSI_SOR_RX_CLR);
-   }
-
return 0;
 }
 
-- 
2.7.4



[PATCH v2 04/16] ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro

2018-01-10 Thread Nicolin Chen
The define of fsl_ssi_disable_val is not so clear as it mixes two
steps of calculations together. And those parameter names are also
a bit long to read.

Since it just tries to exclude the shared bits from the regvals of
current stream while the opposite stream is active, it's better to
use something like ssi_excl_shared_bits.

This patch also bisects fsl_ssi_disable_val into two macros of two
corresponding steps and then shortens its parameter names. It also
updates callers in the fsl_ssi_config() accordingly.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 54 -
 1 file changed, 22 insertions(+), 32 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index aa14a5d..f026386 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -417,24 +417,24 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 }
 
 /**
- * Calculate the bits that have to be disabled for the current stream that is
- * getting disabled. This keeps the bits enabled that are necessary for the
- * second stream to work if 'stream_active' is true.
+ * Exclude bits that are used by the opposite stream
  *
- * Detailed calculation:
- * These are the values that need to be active after disabling. For non-active
- * second stream, this is 0:
- * vals_stream * !!stream_active
+ * When both streams are active, disabling some bits for the current stream
+ * might break the other stream if these bits are used by it.
  *
- * The following computes the overall differences between the setup for the
- * to-disable stream and the active stream, a simple XOR:
- * vals_disable ^ (vals_stream * !!(stream_active))
+ * @vals : regvals of the current stream
+ * @avals: regvals of the opposite stream
+ * @aactive: active state of the opposite stream
  *
- * The full expression adds a mask on all values we care about
+ *  1) XOR vals and avals to get the differences if the other stream is active;
+ * Otherwise, return current vals if the other stream is not active
+ *  2) AND the result of 1) with the current vals
  */
-#define fsl_ssi_disable_val(vals_disable, vals_stream, stream_active) \
-   ((vals_disable) & \
-((vals_disable) ^ ((vals_stream) * (u32)!!(stream_active
+#define _ssi_xor_shared_bits(vals, avals, aactive) \
+   ((vals) ^ ((avals) * (aactive)))
+
+#define ssi_excl_shared_bits(vals, avals, aactive) \
+   ((vals) & _ssi_xor_shared_bits(vals, avals, aactive))
 
 /**
  * Enable or disable SSI configuration.
@@ -445,16 +445,10 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
bool dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
-   int nr_active_streams;
-   int keep_active;
-
-   nr_active_streams = !!(ssi->streams & BIT(TX)) +
-   !!(ssi->streams & BIT(RX));
+   bool aactive;
 
-   if (nr_active_streams - 1 > 0)
-   keep_active = 1;
-   else
-   keep_active = 0;
+   /* Check if the opposite stream is active */
+   aactive = ssi->streams & BIT(!dir);
 
/* Get the opposite direction to keep its values untouched */
if (>regvals[RX] == vals)
@@ -467,8 +461,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   u32 scr = fsl_ssi_disable_val(vals->scr, avals->scr,
- keep_active);
+   u32 scr = ssi_excl_shared_bits(vals->scr, avals->scr, aactive);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
 
@@ -483,7 +476,7 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
 * 2) Disable all remaining bits of both streams when last stream ends
 */
if (ssi->soc->offline_config) {
-   if ((enable && !nr_active_streams) || (!enable && !keep_active))
+   if ((enable && !ssi->streams) || (!enable && !aactive))
fsl_ssi_rxtx_config(ssi, enable);
 
goto config_done;
@@ -505,12 +498,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool 
enable,
 * To keep the other stream safe, exclude shared bits between
 * both streams, and get safe bits to disable current stream
 */
-   sier = fsl_ssi_disable_val(vals->sier, avals->sier,
-  keep_active);
-   srcr = fsl_ssi_disable_val(vals->srcr, avals->srcr,
-  keep_active);
-   stcr = fsl_ssi_disable_val(vals->stcr, avals->stcr,
- 

[PATCH v2 03/16] ASoC: fsl_ssi: Maintain a mask of active streams

2018-01-10 Thread Nicolin Chen
Checking TE and RE bits in SCR register doesn't work for AC97 mode
which enables SSIEN, TE and RE in the fsl_ssi_setup_ac97() that's
called during probe().

So when running into the trigger(), it will always get the result
of both TE and RE being enabled already, even if actually there is
no active stream.

This patch fixes this issue by adding a variable to log the active
streams manually.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index 491b660..aa14a5d 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -201,6 +201,7 @@ struct fsl_ssi_soc_data {
  * @cpu_dai_drv: CPU DAI driver for this device
  *
  * @dai_fmt: DAI configuration this device is currently used with
+ * @streams: Mask of current active streams: BIT(TX) and BIT(RX)
  * @i2s_net: I2S and Network mode configurations of SCR register
  * @use_dma: DMA is used or FIQ with stream filter
  * @use_dual_fifo: DMA with support for dual FIFO mode
@@ -245,6 +246,7 @@ struct fsl_ssi {
struct snd_soc_dai_driver cpu_dai_drv;
 
unsigned int dai_fmt;
+   u8 streams;
u8 i2s_net;
bool use_dma;
bool use_dual_fifo;
@@ -440,15 +442,14 @@ static void fsl_ssi_fifo_clear(struct fsl_ssi *ssi, bool 
is_rx)
 static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
   struct fsl_ssi_regvals *vals)
 {
+   bool dir = (>regvals[TX] == vals) ? TX : RX;
struct regmap *regs = ssi->regs;
struct fsl_ssi_regvals *avals;
int nr_active_streams;
-   u32 scr;
int keep_active;
 
-   regmap_read(regs, REG_SSI_SCR, );
-
-   nr_active_streams = !!(scr & SSI_SCR_TE) + !!(scr & SSI_SCR_RE);
+   nr_active_streams = !!(ssi->streams & BIT(TX)) +
+   !!(ssi->streams & BIT(RX));
 
if (nr_active_streams - 1 > 0)
keep_active = 1;
@@ -470,6 +471,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
  keep_active);
/* Safely disable SCR register for the stream */
regmap_update_bits(regs, REG_SSI_SCR, scr, 0);
+
+   /* Log the disabled stream to the mask */
+   ssi->streams &= ~BIT(dir);
}
 
/*
@@ -545,6 +549,9 @@ static void fsl_ssi_config(struct fsl_ssi *ssi, bool enable,
}
/* Enable all remaining bits */
regmap_update_bits(regs, REG_SSI_SCR, vals->scr, vals->scr);
+
+   /* Log the enabled stream to the mask */
+   ssi->streams |= BIT(dir);
}
 }
 
-- 
2.7.4



[PATCH v2 02/16] ASoC: fsl_ssi: Clean up set_dai_tdm_slot()

2018-01-10 Thread Nicolin Chen
This patch replaces the register read with ssi->i2s_net for
simplification. It also removes masking SSIEN from scr value
since it's handled later by regmap_update_bits() to set this
scr value back.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c8bd353..491b660 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -1051,9 +1051,7 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
}
 
/* The slot number should be >= 2 if using Network mode or I2S mode */
-   regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_I2S_MODE_MASK | SSI_SCR_NET;
-   if (val && slots < 2) {
+   if (ssi->i2s_net && slots < 2) {
dev_err(dai->dev, "slot number should be >= 2 in I2S or NET\n");
return -EINVAL;
}
@@ -1063,9 +1061,8 @@ static int fsl_ssi_set_dai_tdm_slot(struct snd_soc_dai 
*dai, u32 tx_mask,
regmap_update_bits(regs, REG_SSI_SRCCR,
   SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots));
 
-   /* Save SSIEN bit of the SCR register */
+   /* Save the SCR register value */
regmap_read(regs, REG_SSI_SCR, );
-   val &= SSI_SCR_SSIEN;
/* Temporarily enable SSI to allow SxMSKs to be configurable */
regmap_update_bits(regs, REG_SSI_SCR, SSI_SCR_SSIEN, SSI_SCR_SSIEN);
 
-- 
2.7.4



[PATCH v2 00/16] ASoC: fsl_ssi: Clean up - program flow level

2018-01-10 Thread Nicolin Chen
==Change log==
v2
 * Reworked the series by taking suggestions from Maciej
  + Added PATCH-01 to keep all ssi->i2s_net updated
  + Replaced bool tx with bool dir in PATCH-03 and PATCH-06
  + Moved all initial register configurations from dai probe() to
platform probe() so as to let AC97 CODEC successfully probe.
 * Added Tested-by from Caleb for TDM test cases.

==Background==
The fsl_ssi driver was designed for PPC originally and then it has
been updated to support different modes for i.MX Series, including
SDMA, I2S Master mode, AC97 and older i.MXs with FIQ, by different
contributors for different use cases in different coding styles.

Additionally, in order to fix/work-around hardware bugs and design
flaws, the driver made a lot of compromise so now its program flow
looks very complicated and it's getting hard to maintain or update.

So I am going to clean up the driver on both coding style level and
program flow level.

==Introduction==
This series of patches is the second set to clean up fsl_ssi driver
in the program flow level. Any patch here may impact a fundamental
test case like playback or record.

==Verification==
This series of patches require fully tested. I have done such tests
on i.MX6SoloX with WM8962 using imx_v6_v7_defconfig as:
 - Playback via I2S Master and Slave mode
 - Record via I2S Master and Slave mode
 - Simultaneous playback and record via I2S Master and Slave mode
 - Background playback with foreground record (starting at different
   time) via I2S Master and Slave mode
 - Background record with foreground playback (starting at different
   time) via I2S Master and Slave mode
 * All tests above by hacking offline_config to true in imx51.

Caleb has tested v1 with TDM lookback tests on i.MX6.

Example of uncovered tests: AC97, PowerPC and FIQ.

Nicolin Chen (16):
  ASoC: fsl_ssi: Keep ssi->i2s_net updated
  ASoC: fsl_ssi: Clean up set_dai_tdm_slot()
  ASoC: fsl_ssi: Maintain a mask of active streams
  ASoC: fsl_ssi: Rename fsl_ssi_disable_val macro
  ASoC: fsl_ssi: Clear FIFO directly in fsl_ssi_config()
  ASoC: fsl_ssi: Clean up helper functions of trigger()
  ASoC: fsl_ssi: Add DAIFMT define for AC97
  ASoC: fsl_ssi: Clean up fsl_ssi_setup_regvals()
  ASoC: fsl_ssi: Set xFEN0 and xFEN1 together
  ASoC: fsl_ssi: Use snd_soc_init_dma_data instead
  ASoC: fsl_ssi: Move one-time configurations to probe()
  ASoC: fsl_ssi: Setup AC97 in fsl_ssi_hw_init()
  ASoC: fsl_ssi: Clean up _fsl_ssi_set_dai_fmt()
  ASoC: fsl_ssi: Remove cpu_dai_drv from fsl_ssi structure
  ASoC: fsl_ssi: Move DT related code to a separate probe()
  ASoC: fsl_ssi: Use ssi->streams instead of reading register

 sound/soc/fsl/fsl_ssi.c | 740 
 1 file changed, 369 insertions(+), 371 deletions(-)

-- 
2.7.4



[PATCH v2 01/16] ASoC: fsl_ssi: Keep ssi->i2s_net updated

2018-01-10 Thread Nicolin Chen
The hw_params() overwrites i2s_net settings for special cases like
mono-channel support, however, it doesn't update ssi->i2s_net as
set_dai_fmt() does.

This patch removes the local i2s_net variable and directly updates
ssi->i2s_net in the hw_params() so that the driver can simply look
up the ssi->i2s_net instead of reading the register.

Signed-off-by: Nicolin Chen 
Tested-by: Caleb Crome 
---
 sound/soc/fsl/fsl_ssi.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index aecd00f..c8bd353 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -834,16 +834,16 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream 
*substream,
}
 
if (!fsl_ssi_is_ac97(ssi)) {
-   u8 i2s_net;
/* Normal + Network mode to send 16-bit data in 32-bit frames */
if (fsl_ssi_is_i2s_cbm_cfs(ssi) && sample_size == 16)
-   i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
-   else
-   i2s_net = ssi->i2s_net;
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL | SSI_SCR_NET;
+
+   /* Use Normal mode to send mono data at 1st slot of 2 slots */
+   if (channels == 1)
+   ssi->i2s_net = SSI_SCR_I2S_MODE_NORMAL;
 
regmap_update_bits(regs, REG_SSI_SCR,
-  SSI_SCR_I2S_NET_MASK,
-  channels == 1 ? 0 : i2s_net);
+  SSI_SCR_I2S_NET_MASK, ssi->i2s_net);
}
 
/* In synchronous mode, the SSI uses STCCR for capture */
-- 
2.7.4



Re: powerpc/kernel: Print actual address of regs when oopsing

2018-01-10 Thread Michael Ellerman
On Thu, 2018-01-11 at 02:21:35 UTC, Michael Ellerman wrote:
> When we oops or otherwise call show_regs() we print the address of the
> regs structure. Being able to see the address is fairly useful,
> firstly to verify that the regs pointer is not completely bogus, and
> secondly it allows you to dump the regs and surrounding memory with a
> debugger if you have one.
> 
> In the normal case the regs will be located somewhere on the stack, so
> printing their location discloses no further information than printing
> the stack pointer does already.
> 
> So switch to %px and print the actual address, not the hashed value.
> 
> Signed-off-by: Michael Ellerman 

Applied to powerpc fixes.

https://git.kernel.org/powerpc/c/182dc9c7f217146d69d9c0b75c150c

cheers


Re: [01/11] powerpc/pseries: Add H_GET_CPU_CHARACTERISTICS flags & wrapper

2018-01-10 Thread Michael Ellerman
On Mon, 2018-01-08 at 16:54:43 UTC, Michael Ellerman wrote:
> From: Michael Neuling 
> 
> A new hypervisor call has been defined to communicate various
> characteristics of the CPU to guests. Add definitions for the hcall
> number, flags and a wrapper function.
> 
> Signed-off-by: Michael Neuling 
> Signed-off-by: Michael Ellerman 

Series applied to powerpc fixes.

https://git.kernel.org/powerpc/c/191eccb1580939fb0d47deb405b82a

cheers


Re: [v3, 1/1] powerpc/pseries: Make RAS IRQ explicitly dependent on DLPAR WQ

2018-01-10 Thread Michael Ellerman
On Wed, 2018-01-03 at 21:12:52 UTC, Jose Ricardo Ziviani wrote:
> The hotplug engine uses its own workqueue to handle IRQ requests, the
> problem is that such workqueue is initialized after init_ras_IRQ, which
> will cause a kernel panic if any hotplug interruption is issued in that
> period of time.
> 
> This patch makes RAS IRQ registration explicitly dependent on DLPAR
> workqueue and adds a check to make sure that the workqueue is not
> initialized more than once.
> 
> Reported-by: Min Deng 
> Reported-by: Daniel Henrique Barboza 
> Tested-by: Jose Ricardo Ziviani 
> Signed-off-by: Michael Ellerman 
> Reviewed-by: David Gibson 

Applied to powerpc fixes, thanks.

https://git.kernel.org/powerpc/c/e2d5915293ffdff977ddcfc12b817b

cheers


[PATCH] powerpc/kernel: Print actual address of regs when oopsing

2018-01-10 Thread Michael Ellerman
When we oops or otherwise call show_regs() we print the address of the
regs structure. Being able to see the address is fairly useful,
firstly to verify that the regs pointer is not completely bogus, and
secondly it allows you to dump the regs and surrounding memory with a
debugger if you have one.

In the normal case the regs will be located somewhere on the stack, so
printing their location discloses no further information than printing
the stack pointer does already.

So switch to %px and print the actual address, not the hashed value.

Signed-off-by: Michael Ellerman 
---
 arch/powerpc/kernel/process.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 5acb5a176dbe..72be0c32e902 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -1403,7 +1403,7 @@ void show_regs(struct pt_regs * regs)
 
printk("NIP:  "REG" LR: "REG" CTR: "REG"\n",
   regs->nip, regs->link, regs->ctr);
-   printk("REGS: %p TRAP: %04lx   %s  (%s)\n",
+   printk("REGS: %px TRAP: %04lx   %s  (%s)\n",
   regs, regs->trap, print_tainted(), init_utsname()->release);
printk("MSR:  "REG" ", regs->msr);
print_msr_bits(regs->msr);
-- 
2.14.3



Re: Spectre+Meltdown

2018-01-10 Thread Li Yang
On Mon, Jan 8, 2018 at 2:17 AM, Christian Zigotzky
 wrote:
> Hi All,
>
> Thanks a lot for your replies.
>
> @NXP developers: Could you please tell us some information?

We have done some investigation but it is not ready to be published
yet.  You can get more information from your support channel right
now.

>
> Thanks,
> Christian
>
>
>
> On 08 January 2018 at 02:14AM, Michal Suchanek wrote:
>>
>> On 7 January 2018 at 19:54, Olof Johansson  wrote:
>>>
>>> On Sun, Jan 7, 2018 at 5:04 AM, Christian Zigotzky
>>>  wrote:

 Hello Michael,

 Thanks for your reply. We are using P.A. Semi and Freescale CPUs.

 @Olof
 Do you have some infos for us?
>>>
>>> I'm low on spare time to experiment and explore what might be exposed
>>> or not, and I no longer have any proprietary microarchitecture
>>> documentation of the core.
>>>
>>> I suggest reaching out to your supplier of the silicon for commercial
>>> support and information, or just going with what I'm sure will be
>>> architecturally generic solutions to the problem when IBM has them
>>> ready.
>>
>> The solution for IBM POWER involves patching the firmware as well as
>> Linux. Without knowledge of the architecture specifics it is not
>> possible to tell if other cores are affected and if the measures
>> implemented by IBM can be used. In fact they probably rely on
>> 64s-specific instructions and are in part implemented in 64s-specific
>> assembly files.
>>
>> So this will not work without support for the specific core either by
>> the vendor or somebody who has knowledge of the architecture details.
>>
>> Thanks
>>
>> Michal
>>
>


Re: [PATCH RESEND 1/1] KVM: PPC: Book3S: Add MMIO emulation for VMX instructions

2018-01-10 Thread joserz
On Thu, Jan 11, 2018 at 09:36:58AM +1100, Paul Mackerras wrote:
> On Mon, Jan 08, 2018 at 04:29:31PM -0200, Jose Ricardo Ziviani wrote:
> > This patch provides the MMIO load/store vector indexed
> > X-Form emulation.
> > 
> > Instructions implemented: lvx, stvx
> > 
> > Signed-off-by: Jose Ricardo Ziviani 
> 
> What testing has been done of this patch?  In particular, what
> combinations of endianness of host and guest have been tested?  For a
> cross-endian situation (endianness of guest different from host) you
> would need to load the two halves of the VMX register image in
> reversed order (note that lvx/stvx are different from lxvd2x/stxvd2x
> and lxvw4x/stxvw4x in this respect), and I don't see that being done.

Hello! Thank you for reviewing it.

Yes, I tested it with both in little endian mode. You're absolutely
right, I'll review the cross-endian scenario that's not covered indeed.

> 
> Also, lvx/stvx mask off the bottom 4 bits of the EA, and I don't see
> that being done.
> 
> [snip]
> 
> > diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> > index 1915e86cef6f..7d0f60359ee0 100644
> > --- a/arch/powerpc/kvm/powerpc.c
> > +++ b/arch/powerpc/kvm/powerpc.c
> > @@ -832,23 +832,7 @@ void kvm_arch_irq_bypass_del_producer(struct 
> > irq_bypass_consumer *cons,
> > kvm->arch.kvm_ops->irq_bypass_del_producer(cons, prod);
> >  }
> >  
> > -#ifdef CONFIG_VSX
> > -static inline int kvmppc_get_vsr_dword_offset(int index)
> > -{
> > -   int offset;
> > -
> > -   if ((index != 0) && (index != 1))
> > -   return -1;
> > -
> > -#ifdef __BIG_ENDIAN
> > -   offset =  index;
> > -#else
> > -   offset = 1 - index;
> > -#endif
> > -
> > -   return offset;
> > -}
> > -
> 
> Why does this function need to be moved down in the file?

The main reason is that I need it too but I need it available with
ALTIVEC(1) support, so I changed the guard to ALTIVEC and moved it down
closer to other related functions under the same guard. But I can move
it back if you prefer.

(1)AFAIK it's possible to have ALTIVEC enabled but VSX disabled, not the
other way around.

> 
> > +#ifdef CONFIG_ALTIVEC
> >  static inline int kvmppc_get_vsr_word_offset(int index)
> >  {
> > int offset;
> > @@ -864,6 +848,40 @@ static inline int kvmppc_get_vsr_word_offset(int index)
> > return offset;
> >  }
> >  
> > +static inline void kvmppc_set_vmx_dword(struct kvm_vcpu *vcpu,
> > +   u64 gpr)
> > +{
> > +   int index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;
> > +   u64 hi = gpr >> 32;
> > +   u64 lo = gpr & 0x;
> > +
> > +   if (vcpu->arch.mmio_vmx_copy_nums == 1) {
> > +   VCPU_VSX_VR(vcpu, index).u[kvmppc_get_vsr_word_offset(2)] = hi;
> > +   VCPU_VSX_VR(vcpu, index).u[kvmppc_get_vsr_word_offset(3)] = lo;
> > +   } else if (vcpu->arch.mmio_vmx_copy_nums == 2) {
> > +   VCPU_VSX_VR(vcpu, index).u[kvmppc_get_vsr_word_offset(0)] = hi;
> > +   VCPU_VSX_VR(vcpu, index).u[kvmppc_get_vsr_word_offset(1)] = lo;
> > +   }
> 
> This splitting of the value into hi/lo words looks to me like you're
> assuming a big-endian byte ordering.  It looks like it will end up
> swapping the words in each half of the register on a little-endian
> host (regardless of the endianness of the guest).

Yep! I focused on VCPU_VSX_VR code to fill the vector correctly but
missed the 64-bit value splitting. I'll fix it and improve the testing,
considering other endian scenario.

> 
> > +}
> > +#endif /* CONFIG_ALTIVEC */
> > +
> > +#ifdef CONFIG_VSX
> > +static inline int kvmppc_get_vsr_dword_offset(int index)
> > +{
> > +   int offset;
> > +
> > +   if ((index != 0) && (index != 1))
> > +   return -1;
> > +
> > +#ifdef __BIG_ENDIAN
> > +   offset =  index;
> > +#else
> > +   offset = 1 - index;
> > +#endif
> > +
> > +   return offset;
> > +}
> > +
> >  static inline void kvmppc_set_vsr_dword(struct kvm_vcpu *vcpu,
> > u64 gpr)
> >  {
> > @@ -1027,6 +1045,11 @@ static void kvmppc_complete_mmio_load(struct 
> > kvm_vcpu *vcpu,
> > KVMPPC_VSX_COPY_DWORD_LOAD_DUMP)
> > kvmppc_set_vsr_dword_dump(vcpu, gpr);
> > break;
> > +#endif
> > +#ifdef CONFIG_ALTIVEC
> > +   case KVM_MMIO_REG_VMX:
> > +   kvmppc_set_vmx_dword(vcpu, gpr);
> > +   break;
> >  #endif
> > default:
> > BUG();
> > @@ -1307,6 +1330,99 @@ static int kvmppc_emulate_mmio_vsx_loadstore(struct 
> > kvm_vcpu *vcpu,
> >  }
> >  #endif /* CONFIG_VSX */
> >  
> > +#ifdef CONFIG_ALTIVEC
> > +/* handle quadword load access in two halves */
> > +int kvmppc_handle_load128_by2x64(struct kvm_run *run, struct kvm_vcpu 
> > *vcpu,
> > +   unsigned int rt, int is_default_endian)
> > +{
> > +   enum emulation_result emulated = EMULATE_DONE;
> > +
> > +   while (vcpu->arch.mmio_vmx_copy_nums) {
> > +   emulated = __kvmppc_handle_load(run, vcpu, rt, 8,
> > +   is_default_endian, 

Re: [PATCH] soc/fsl/guts: Add a NULL check for devm_kasprintf()

2018-01-10 Thread Li Yang
On Sun, Jan 7, 2018 at 9:06 PM, Y.b. Lu  wrote:
>> -Original Message-
>> From: Fabio Estevam [mailto:feste...@gmail.com]
>> Sent: 2018年1月6日 21:23
>> To: Leo Li 
>> Cc: linuxppc-dev@lists.ozlabs.org; Y.b. Lu ; Fabio
>> Estevam 
>> Subject: [PATCH] soc/fsl/guts: Add a NULL check for devm_kasprintf()
>>
>> From: Fabio Estevam 
>>
>> devm_kasprintf() may fail, so we should better add a NULL check and
>> propagate an error on failure.
>>
>> Signed-off-by: Fabio Estevam 
>
> [Y.b. Lu] It makes sense.
> Acked-by: Yangbo Lu 

Merged.  Thanks.

>
>> ---
>>  drivers/soc/fsl/guts.c | 6 ++
>>  1 file changed, 6 insertions(+)
>>
>> diff --git a/drivers/soc/fsl/guts.c b/drivers/soc/fsl/guts.c index
>> d89a6a8..82251b4 100644
>> --- a/drivers/soc/fsl/guts.c
>> +++ b/drivers/soc/fsl/guts.c
>> @@ -167,10 +167,16 @@ static int fsl_guts_probe(struct platform_device
>> *pdev)
>>   } else {
>>   soc_dev_attr.family = devm_kasprintf(dev, GFP_KERNEL, "QorIQ");
>>   }
>> + if (!soc_dev_attr.family)
>> + return -ENOMEM;
>>   soc_dev_attr.soc_id = devm_kasprintf(dev, GFP_KERNEL,
>>"svr:0x%08x", svr);
>> + if (!soc_dev_attr.soc_id)
>> + return -ENOMEM;
>>   soc_dev_attr.revision = devm_kasprintf(dev, GFP_KERNEL, "%d.%d",
>>  (svr >>  4) & 0xf, svr & 0xf);
>> + if (!soc_dev_attr.revision)
>> + return -ENOMEM;
>>
>>   soc_dev = soc_device_register(_dev_attr);
>>   if (IS_ERR(soc_dev))
>> --
>> 2.7.4
>


Re: [PATCH RESEND 1/1] KVM: PPC: Book3S: Add MMIO emulation for VMX instructions

2018-01-10 Thread Paul Mackerras
On Mon, Jan 08, 2018 at 04:29:31PM -0200, Jose Ricardo Ziviani wrote:
> This patch provides the MMIO load/store vector indexed
> X-Form emulation.
> 
> Instructions implemented: lvx, stvx
> 
> Signed-off-by: Jose Ricardo Ziviani 

What testing has been done of this patch?  In particular, what
combinations of endianness of host and guest have been tested?  For a
cross-endian situation (endianness of guest different from host) you
would need to load the two halves of the VMX register image in
reversed order (note that lvx/stvx are different from lxvd2x/stxvd2x
and lxvw4x/stxvw4x in this respect), and I don't see that being done.

Also, lvx/stvx mask off the bottom 4 bits of the EA, and I don't see
that being done.

[snip]

> diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
> index 1915e86cef6f..7d0f60359ee0 100644
> --- a/arch/powerpc/kvm/powerpc.c
> +++ b/arch/powerpc/kvm/powerpc.c
> @@ -832,23 +832,7 @@ void kvm_arch_irq_bypass_del_producer(struct 
> irq_bypass_consumer *cons,
>   kvm->arch.kvm_ops->irq_bypass_del_producer(cons, prod);
>  }
>  
> -#ifdef CONFIG_VSX
> -static inline int kvmppc_get_vsr_dword_offset(int index)
> -{
> - int offset;
> -
> - if ((index != 0) && (index != 1))
> - return -1;
> -
> -#ifdef __BIG_ENDIAN
> - offset =  index;
> -#else
> - offset = 1 - index;
> -#endif
> -
> - return offset;
> -}
> -

Why does this function need to be moved down in the file?

> +#ifdef CONFIG_ALTIVEC
>  static inline int kvmppc_get_vsr_word_offset(int index)
>  {
>   int offset;
> @@ -864,6 +848,40 @@ static inline int kvmppc_get_vsr_word_offset(int index)
>   return offset;
>  }
>  
> +static inline void kvmppc_set_vmx_dword(struct kvm_vcpu *vcpu,
> + u64 gpr)
> +{
> + int index = vcpu->arch.io_gpr & KVM_MMIO_REG_MASK;
> + u64 hi = gpr >> 32;
> + u64 lo = gpr & 0x;
> +
> + if (vcpu->arch.mmio_vmx_copy_nums == 1) {
> + VCPU_VSX_VR(vcpu, index).u[kvmppc_get_vsr_word_offset(2)] = hi;
> + VCPU_VSX_VR(vcpu, index).u[kvmppc_get_vsr_word_offset(3)] = lo;
> + } else if (vcpu->arch.mmio_vmx_copy_nums == 2) {
> + VCPU_VSX_VR(vcpu, index).u[kvmppc_get_vsr_word_offset(0)] = hi;
> + VCPU_VSX_VR(vcpu, index).u[kvmppc_get_vsr_word_offset(1)] = lo;
> + }

This splitting of the value into hi/lo words looks to me like you're
assuming a big-endian byte ordering.  It looks like it will end up
swapping the words in each half of the register on a little-endian
host (regardless of the endianness of the guest).

> +}
> +#endif /* CONFIG_ALTIVEC */
> +
> +#ifdef CONFIG_VSX
> +static inline int kvmppc_get_vsr_dword_offset(int index)
> +{
> + int offset;
> +
> + if ((index != 0) && (index != 1))
> + return -1;
> +
> +#ifdef __BIG_ENDIAN
> + offset =  index;
> +#else
> + offset = 1 - index;
> +#endif
> +
> + return offset;
> +}
> +
>  static inline void kvmppc_set_vsr_dword(struct kvm_vcpu *vcpu,
>   u64 gpr)
>  {
> @@ -1027,6 +1045,11 @@ static void kvmppc_complete_mmio_load(struct kvm_vcpu 
> *vcpu,
>   KVMPPC_VSX_COPY_DWORD_LOAD_DUMP)
>   kvmppc_set_vsr_dword_dump(vcpu, gpr);
>   break;
> +#endif
> +#ifdef CONFIG_ALTIVEC
> + case KVM_MMIO_REG_VMX:
> + kvmppc_set_vmx_dword(vcpu, gpr);
> + break;
>  #endif
>   default:
>   BUG();
> @@ -1307,6 +1330,99 @@ static int kvmppc_emulate_mmio_vsx_loadstore(struct 
> kvm_vcpu *vcpu,
>  }
>  #endif /* CONFIG_VSX */
>  
> +#ifdef CONFIG_ALTIVEC
> +/* handle quadword load access in two halves */
> +int kvmppc_handle_load128_by2x64(struct kvm_run *run, struct kvm_vcpu *vcpu,
> + unsigned int rt, int is_default_endian)
> +{
> + enum emulation_result emulated = EMULATE_DONE;
> +
> + while (vcpu->arch.mmio_vmx_copy_nums) {
> + emulated = __kvmppc_handle_load(run, vcpu, rt, 8,
> + is_default_endian, 0);
> + if (emulated != EMULATE_DONE)
> + break;
> +
> + vcpu->arch.mmio_vmx_copy_nums--;
> + }
> + return emulated;
> +}
> +
> +static inline int kvmppc_get_vmx_data(struct kvm_vcpu *vcpu, int rs, u64 
> *val)
> +{
> +
> + if (vcpu->arch.mmio_vmx_copy_nums == 1) {
> + *val = VCPU_VSX_VR(vcpu, rs).u[kvmppc_get_vsr_word_offset(2)];
> + *val = (*val << 32) | VCPU_VSX_VR(vcpu, rs).
> + u[kvmppc_get_vsr_word_offset(3)];
> + return 0;
> + } else if (vcpu->arch.mmio_vmx_copy_nums == 2) {
> + *val = VCPU_VSX_VR(vcpu, rs).u[kvmppc_get_vsr_word_offset(0)];
> + *val = (*val << 32) | VCPU_VSX_VR(vcpu, rs).
> + u[kvmppc_get_vsr_word_offset(1)];
> + return 0;
> + }
> + return -1;
> +}

Once again, the way this puts two word values together to get a

Re: [PATCH] PCI: Add #defines for Completion Timeout Disable feature

2018-01-10 Thread Bjorn Helgaas
On Fri, Dec 15, 2017 at 04:57:11PM -0600, Bjorn Helgaas wrote:
> From: Bjorn Helgaas 
> 
> Add #defines for the Completion Timeout Disable feature and use them.  No
> functional change intended.
> 
> Signed-off-by: Bjorn Helgaas 

Applied with Michael's ack to pci/misc for v4.16.

> ---
>  arch/powerpc/platforms/powernv/eeh-powernv.c |6 +++---
>  include/uapi/linux/pci_regs.h|2 ++
>  2 files changed, 5 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c 
> b/arch/powerpc/platforms/powernv/eeh-powernv.c
> index 4650fb294e7a..2f7cd0ef3cdc 100644
> --- a/arch/powerpc/platforms/powernv/eeh-powernv.c
> +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
> @@ -1654,14 +1654,14 @@ static int pnv_eeh_restore_vf_config(struct pci_dn 
> *pdn)
>   eeh_ops->write_config(pdn, edev->pcie_cap + PCI_EXP_DEVCTL,
> 2, devctl);
>  
> - /* Disable Completion Timeout */
> + /* Disable Completion Timeout if possible */
>   eeh_ops->read_config(pdn, edev->pcie_cap + PCI_EXP_DEVCAP2,
>4, );
> - if (cap2 & 0x10) {
> + if (cap2 & PCI_EXP_DEVCAP2_COMP_TMOUT_DIS) {
>   eeh_ops->read_config(pdn,
>edev->pcie_cap + PCI_EXP_DEVCTL2,
>4, );
> - cap2 |= 0x10;
> + cap2 |= PCI_EXP_DEVCTL2_COMP_TMOUT_DIS;
>   eeh_ops->write_config(pdn,
> edev->pcie_cap + PCI_EXP_DEVCTL2,
> 4, cap2);
> diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
> index 70c2b2ade048..9dc67643fc18 100644
> --- a/include/uapi/linux/pci_regs.h
> +++ b/include/uapi/linux/pci_regs.h
> @@ -622,6 +622,7 @@
>   * safely.
>   */
>  #define PCI_EXP_DEVCAP2  36  /* Device Capabilities 2 */
> +#define  PCI_EXP_DEVCAP2_COMP_TMOUT_DIS  0x0010 /* Completion 
> Timeout Disable supported */
>  #define  PCI_EXP_DEVCAP2_ARI 0x0020 /* Alternative Routing-ID */
>  #define  PCI_EXP_DEVCAP2_ATOMIC_ROUTE0x0040 /* Atomic Op routing 
> */
>  #define PCI_EXP_DEVCAP2_ATOMIC_COMP640x0100 /* Atomic 64-bit 
> compare */
> @@ -631,6 +632,7 @@
>  #define  PCI_EXP_DEVCAP2_OBFF_WAKE   0x0008 /* Re-use WAKE# for OBFF */
>  #define PCI_EXP_DEVCTL2  40  /* Device Control 2 */
>  #define  PCI_EXP_DEVCTL2_COMP_TIMEOUT0x000f  /* Completion Timeout 
> Value */
> +#define  PCI_EXP_DEVCTL2_COMP_TMOUT_DIS  0x0010  /* Completion Timeout 
> Disable */
>  #define  PCI_EXP_DEVCTL2_ARI 0x0020  /* Alternative Routing-ID */
>  #define PCI_EXP_DEVCTL2_ATOMIC_REQ   0x0040  /* Set Atomic requests */
>  #define PCI_EXP_DEVCTL2_ATOMIC_EGRESS_BLOCK 0x0080 /* Block atomic egress */
> 


DPAA Ethernet traffice troubles with Linux kernel

2018-01-10 Thread mad skateman
Hi linux devs,

Like mentioned in this thread
https://lists.ozlabs.org/pipermail/linuxppc-dev/2018-January/167630.html
i also experience the exact same issues.
I am also trying to find out why the network traffic is not flowing
the way it should (out for example ).

My linux knowledge is very basic but i hope i can contribute anyway.

I am using the AmigaOne X5000 with a P5020
Most detailed technical information regarding this issue can be found
in the Thread by Jamie Krueger mentioned above.

In this screenshot, the ETH0 and ETH1 seem up and running (probed) ..
even due to the FSL_DPAA_MAC error messages that DMESG shows.
http://www.skateman.nl/wp-content/uploads/2018/01/Screenshot-at-2018-01-08-21_22_06_ETH_NIC_ERROR.png

http://www.skateman.nl/wp-content/uploads/2018/01/Screenshot-at-2018-01-08-22_16_28.png

I was able to use some tooling like ETHTOOL to adjust some settings
and check if the interface responded. This all seems fine.

Hope that someone can find a fix, so the Ethernet adapter can be used.

Thanks!!


Re: [PATCH 10/13] ocxl: Add Makefile and Kconfig

2018-01-10 Thread Frederic Barrat



Le 10/01/2018 à 00:21, Michael Ellerman a écrit :

Would also be great to add something describing the relationship to CAPI and 
cxl. Otherwise people will be confused about whether they need this one or the 
other one or both.


OK, I'll add something.

  Fred



Re: [PATCH 08/22] swiotlb: wire up ->dma_supported in swiotlb_dma_ops

2018-01-10 Thread Robin Murphy

On 10/01/18 15:35, Christoph Hellwig wrote:

On Wed, Jan 10, 2018 at 12:16:15PM +, Robin Murphy wrote:

On 10/01/18 08:09, Christoph Hellwig wrote:

To properly reject too small DMA masks based on the addressability of the
bounce buffer.


I reckon this is self-evident enough that it should simply be squashed into
the previous patch.


x86 didn't wire it up before, so I want a clear blaimpoint for this
change instead of mixing it up.
That almost makes sense, if x86 were using this generic swiotlb_dma_ops 
already. AFAICS it's only ia64, unicore and tile who end up using it, 
and they all had swiotlb_dma_supported hooked up to begin with. Am I 
missing something?


If regressions are going to happen, they'll surely point at whichever 
commit pulls the ops into the relevant arch code - there doesn't seem to 
be a great deal of value in having a piecemeal history of said ops 
*before* that point.


Robin.


Re: [PATCH 21/22] arm64: replace ZONE_DMA with ZONE_DMA32

2018-01-10 Thread Robin Murphy

On 10/01/18 15:55, Christoph Hellwig wrote:

On Wed, Jan 10, 2018 at 04:55:17PM +0100, Christoph Hellwig wrote:

On Wed, Jan 10, 2018 at 12:58:14PM +, Robin Murphy wrote:

On 10/01/18 08:09, Christoph Hellwig wrote:

arm64 uses ZONE_DMA for allocations below 32-bits.  These days we
name the zone for that ZONE_DMA32, which will allow to use the
dma-direct and generic swiotlb code as-is, so rename it.


I do wonder if we could also "upgrade" GFP_DMA to GFP_DMA32 somehow when
!ZONE_DMA - there are almost certainly arm64 drivers out there using a
combination of GFP_DMA and streaming mappings which will no longer get the
guaranteed 32-bit addresses they expect after this. I'm not sure quite how
feasible that is, though :/


I can't find anything obvious in the tree. The alternative would be
to keep ZONE_DMA and set ARCH_ZONE_DMA_BITS.


That said, I do agree that this is an appropriate change (the legacy of
GFP_DMA is obviously horrible), so, provided we get plenty of time to find
and fix the fallout when it lands:

Reviewed-by: Robin Murphy 


I was hoping to get this into 4.15.  What would be proper time to
fix the fallout?


Err, 4.16 of course.


Hee hee - cramming it into 4.15 is exactly what I wouldn't want to do, 
even if Linus would accept it :)


Landing it this merge window for 4.16-rc1 sounds good if we can manage that.

Robin.


Re: [PATCH 10/22] swiotlb: refactor coherent buffer allocation

2018-01-10 Thread Robin Murphy

On 10/01/18 15:46, Christoph Hellwig wrote:

On Wed, Jan 10, 2018 at 12:22:18PM +, Robin Murphy wrote:

+   if (phys_addr == SWIOTLB_MAP_ERROR)
+   goto out_warn;
   -/* Confirm address can be DMA'd by device */
-   if (dev_addr + size - 1 > dma_mask) {
-   printk("hwdev DMA mask = 0x%016Lx, dev_addr = 
0x%016Lx\n",
-  (unsigned long long)dma_mask,
-  (unsigned long long)dev_addr);
+   *dma_handle = swiotlb_phys_to_dma(dev, phys_addr);


nit: this should probably go after the dma_coherent_ok() check (as with the
original logic).


But the originall logic also needs the dma_addr_t for the
dma_coherent_ok check:

dev_addr = swiotlb_phys_to_dma(hwdev, paddr);
/* Confirm address can be DMA'd by device */
if (dev_addr + size - 1 > dma_mask) {
...
goto err_warn;
}

or do you mean assining to *dma_handle?  The dma_handle is not
valid for a failure return, so I don't think this should matter.


Yeah, only the assignment - as I said, it's just a stylistic nit; no big 
deal either way.



+   if (ret) {
+   *dma_handle = swiotlb_virt_to_bus(hwdev, ret);
+   if (dma_coherent_ok(hwdev, *dma_handle, size)) {
+   memset(ret, 0, size);
+   return ret;
+   }


Aren't we leaking the pages here?


Yes, that free_pages got lost somewhere in the rebases, I've added
it back.


Cool.

Robin.


Re: [PATCH 31/33] dma-direct: reject too small dma masks

2018-01-10 Thread Robin Murphy



On 10/01/18 15:32, Christoph Hellwig wrote:

On Wed, Jan 10, 2018 at 11:49:34AM +, Robin Murphy wrote:

+#ifdef CONFIG_ZONE_DMA
+   if (mask < DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
+   return 0;
+#else
+   /*
+* Because 32-bit DMA masks are so common we expect every architecture
+* to be able to satisfy them - either by not supporting more physical
+* memory, or by providing a ZONE_DMA32.  If neither is the case, the
+* architecture needs to use an IOMMU instead of the direct mapping.
+*/
+   if (mask < DMA_BIT_MASK(32))
+   return 0;


Do you think it's worth the effort to be a little more accommodating here?
i.e.:

return dma_max_pfn(dev) >= max_pfn;

We seem to have a fair few 28-31 bit masks for older hardware which
probably associates with host systems packing equivalently small amounts of
RAM.


And those devices don't have a ZONE_DMA?  I think we could do something
like that, but I'd rather have it as a separate commit with a good
explanation.  Maybe you can just send on on top of the series?


Good point - other than the IXP4xx platform and possibly the Broadcom 
network drivers, it's probably only x86-relevant stuff where the concern 
is moot. Let's just keep the simple assumption then, until actually 
proven otherwise.


Robin.


Re: [PATCH 27/33] dma-direct: use node local allocations for coherent memory

2018-01-10 Thread Robin Murphy

On 10/01/18 15:30, Christoph Hellwig wrote:

On Wed, Jan 10, 2018 at 12:06:22PM +, Robin Murphy wrote:

On 10/01/18 08:00, Christoph Hellwig wrote:

To preserve the x86 behavior.


And combined with patch 10/22 of the SWIOTLB refactoring, this means
SWIOTLB allocations will also end up NUMA-aware, right? Great, that's what
we want on arm64 too :)


Well, only for swiotlb allocations that can be satisfied by
dma_direct_alloc.  If we actually have to fall back to the swiotlb
buffers there is not node affinity yet.


Yeah, when I looked into it I reached the conclusion that per-node 
bounce buffers probably weren't worth it - if you have to bounce you've 
already pretty much lost the performance game, and if the CPU doing the 
bouncing happens to be on a different node from the device you've 
certainly lost either way. Per-node CMA zones we definitely *would* 
like, but that's a future problem (it looks technically feasible without 
huge infrastructure changes, but fiddly).


Robin.


DPAA Ethernet problems with mainstream Linux kernels

2018-01-10 Thread Jamie Krueger

Hello all @ linuxppc-dev,

I have been working with a team of people maintaining PowerPC
Linux for the new AmigaONE X5000/20 (a Freescale p5020 SoC based
machine).

We are trying to determine why the submitted Data Path Acceleration
Architecture (DPAA) Ethernet Driver is not fully functional with
the mainstream Linux kernels.

Here is the results from my latest tests. They were performed using
the linux-4.10.17 ppc64, since that represents when the DPAA Ethernet
code was introduced.

Similar tests, with similar results, were also performed
using the latest Linux kernels:

linux-4.15-rc5
linux-4.15-rc6
linux-4.15-rc7

(Hence the reason for falling back to test the kernel right
 after the introduction of the DPAA Ethernet driver sources)

---

All Kernel builds had the DPAA Ethernet enabled in the kernel,
and are using the correct cyrus_p5020.eth.dtb device tree file
(for use on the X5000/20).

The results are quite similar for all kernels in regards to the DPAA 
Ethernet.


All tested kernels setup the two Ethernet interfaces correctly
as eth0 and eth1, and pull the correct MAC addresses from U-Boot
environment variables ethaddr and eth1addr respectively.

So at this point Linux has what it believes is fully configured
hardware, waiting to have an IP Address/Netmask/Gateway
to be set and to bring the interface online.

However, all attempts to communicate with the outside world
do not make it out the physical (PHY) hardware - or do they?

** The following results were captured under linux-4.10.17 **

When I bring the interface up using a static address, in this case
192.168.1.21, I see the following (NOTE TX bytes says 154.0 KB,
while RX bytes says 0.0 B):

jamie@X5000-Linux:$ ifconfig
eth0  Link encap:Ethernet  HWaddr 00:80:10:11:11:11
  inet addr:192.168.1.21  Bcast:192.168.1.255 Mask:255.255.255.0
  inet6 addr: fe80::280:10ff:fe11:/64 Scope:Link
  UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
  RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  TX packets:1428 errors:0 dropped:0 overruns:0 carrier:0
  collisions:0 txqueuelen:1000
  RX bytes:0 (0.0 B)  TX bytes:154066 (154.0 KB)
  Memory:fe4e6000-fe4e6fff

eth1  Link encap:Ethernet  HWaddr 00:80:10:22:22:22
  UP BROADCAST MULTICAST  MTU:1500  Metric:1
  RX packets:0 errors:0 dropped:0 overruns:0 frame:0
  TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
  collisions:0 txqueuelen:1000
  RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
  Memory:fe4e8000-fe4e8fff

lo    Link encap:Local Loopback
  inet addr:127.0.0.1  Mask:255.0.0.0
  inet6 addr: ::1/128 Scope:Host
  UP LOOPBACK RUNNING  MTU:65536  Metric:1
  RX packets:1869 errors:0 dropped:0 overruns:0 frame:0
  TX packets:1869 errors:0 dropped:0 overruns:0 carrier:0
  collisions:0 txqueuelen:1000
  RX bytes:156932 (156.9 KB)  TX bytes:156932 (156.9 KB)

Checking the routing table, everything looks fine there:

jamie@X5000-Linux:$ netstat -r
Kernel IP routing table
Destination Gateway Genmask Flags   MSS Window  irtt 
Iface
default 192.168.1.1 0.0.0.0 UG    0 0  0 
eth0
link-local  *   255.255.0.0 U 0 0  0 
eth0
192.168.1.0 *   255.255.255.0   U 0 0  0 
eth0


Attempting to PING the interface itself works:

jamie@X5000-Linux:$ ping 192.168.1.21
PING 192.168.1.21 (192.168.1.21) 56(84) bytes of data.
64 bytes from 192.168.1.21: icmp_seq=1 ttl=64 time=0.037 ms
64 bytes from 192.168.1.21: icmp_seq=2 ttl=64 time=0.045 ms
64 bytes from 192.168.1.21: icmp_seq=3 ttl=64 time=0.033 ms
^C
--- 192.168.1.21 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2043ms

However, attempts to PING the gateway (192.168.1.1) fail as unreachable:

jamie@X5000-Linux:$ ping 192.168.1.1
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
From 192.168.1.21 icmp_seq=1 Destination Host Unreachable
From 192.168.1.21 icmp_seq=2 Destination Host Unreachable
From 192.168.1.21 icmp_seq=3 Destination Host Unreachable
^C
--- 192.168.1.1 ping statistics ---
7 packets transmitted, 0 received, +3 errors, 100% packet loss, time 6077ms

In order to take a closer look at what is going on I installed Wireshark
both on my test X5000/20 Linux install (Ubuntu 16.04.3 LTS), and on
another Linux box connected to the same network switch (in this case
at IP address 192.168.1.210)

In this test I start the capture on eth0 (X5000/20) before it is put online,
and attempt to bring it up using DHCP to obtain it's address.

What I found was that network traffic *was* being attempted over eth0.
Here is a plain text export of the transmit side (the X5000/20) that
was captured using Wireshark.

(There were more network packets being sent from the X5000/20,
 however, I am only showing DHCP traffic to save space in this post):

---
No. 

Re: [PATCH 21/22] arm64: replace ZONE_DMA with ZONE_DMA32

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 04:55:17PM +0100, Christoph Hellwig wrote:
> On Wed, Jan 10, 2018 at 12:58:14PM +, Robin Murphy wrote:
> > On 10/01/18 08:09, Christoph Hellwig wrote:
> >> arm64 uses ZONE_DMA for allocations below 32-bits.  These days we
> >> name the zone for that ZONE_DMA32, which will allow to use the
> >> dma-direct and generic swiotlb code as-is, so rename it.
> >
> > I do wonder if we could also "upgrade" GFP_DMA to GFP_DMA32 somehow when 
> > !ZONE_DMA - there are almost certainly arm64 drivers out there using a 
> > combination of GFP_DMA and streaming mappings which will no longer get the 
> > guaranteed 32-bit addresses they expect after this. I'm not sure quite how 
> > feasible that is, though :/
> 
> I can't find anything obvious in the tree. The alternative would be
> to keep ZONE_DMA and set ARCH_ZONE_DMA_BITS.
> 
> > That said, I do agree that this is an appropriate change (the legacy of 
> > GFP_DMA is obviously horrible), so, provided we get plenty of time to find 
> > and fix the fallout when it lands:
> >
> > Reviewed-by: Robin Murphy 
> 
> I was hoping to get this into 4.15.  What would be proper time to
> fix the fallout?

Err, 4.16 of course.


Re: [PATCH 21/22] arm64: replace ZONE_DMA with ZONE_DMA32

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 12:58:14PM +, Robin Murphy wrote:
> On 10/01/18 08:09, Christoph Hellwig wrote:
>> arm64 uses ZONE_DMA for allocations below 32-bits.  These days we
>> name the zone for that ZONE_DMA32, which will allow to use the
>> dma-direct and generic swiotlb code as-is, so rename it.
>
> I do wonder if we could also "upgrade" GFP_DMA to GFP_DMA32 somehow when 
> !ZONE_DMA - there are almost certainly arm64 drivers out there using a 
> combination of GFP_DMA and streaming mappings which will no longer get the 
> guaranteed 32-bit addresses they expect after this. I'm not sure quite how 
> feasible that is, though :/

I can't find anything obvious in the tree. The alternative would be
to keep ZONE_DMA and set ARCH_ZONE_DMA_BITS.

> That said, I do agree that this is an appropriate change (the legacy of 
> GFP_DMA is obviously horrible), so, provided we get plenty of time to find 
> and fix the fallout when it lands:
>
> Reviewed-by: Robin Murphy 

I was hoping to get this into 4.15.  What would be proper time to
fix the fallout?


[PATCH v7 for 4.16 03/11] powerpc: membarrier: Skip memory barrier in switch_mm()

2018-01-10 Thread Mathieu Desnoyers
Allow PowerPC to skip the full memory barrier in switch_mm(), and
only issue the barrier when scheduling into a task belonging to a
process that has registered to use expedited private.

Threads targeting the same VM but which belong to different thread
groups is a tricky case. It has a few consequences:

It turns out that we cannot rely on get_nr_threads(p) to count the
number of threads using a VM. We can use
(atomic_read(>mm_users) == 1 && get_nr_threads(p) == 1)
instead to skip the synchronize_sched() for cases where the VM only has
a single user, and that user only has a single thread.

It also turns out that we cannot use for_each_thread() to set
thread flags in all threads using a VM, as it only iterates on the
thread group.

Therefore, test the membarrier state variable directly rather than
relying on thread flags. This means
membarrier_register_private_expedited() needs to set the
MEMBARRIER_STATE_PRIVATE_EXPEDITED flag, issue synchronize_sched(), and
only then set MEMBARRIER_STATE_PRIVATE_EXPEDITED_READY which allows
private expedited membarrier commands to succeed.
membarrier_arch_switch_mm() now tests for the
MEMBARRIER_STATE_PRIVATE_EXPEDITED flag.

Changes since v1:
- Use test_ti_thread_flag(next, ...) instead of test_thread_flag() in
  powerpc membarrier_arch_sched_in(), given that we want to specifically
  check the next thread state.
- Add missing ARCH_HAS_MEMBARRIER_HOOKS in Kconfig.
- Use task_thread_info() to pass thread_info from task to
  *_ti_thread_flag().

Changes since v2:
- Move membarrier_arch_sched_in() call to finish_task_switch().
- Check for NULL t->mm in membarrier_arch_fork().
- Use membarrier_sched_in() in generic code, which invokes the
  arch-specific membarrier_arch_sched_in(). This fixes allnoconfig
  build on PowerPC.
- Move asm/membarrier.h include under CONFIG_MEMBARRIER, fixing
  allnoconfig build on PowerPC.
- Build and runtime tested on PowerPC.

Changes since v3:
- Simply rely on copy_mm() to copy the membarrier_private_expedited mm
  field on fork.
- powerpc: test thread flag instead of reading
  membarrier_private_expedited in membarrier_arch_fork().
- powerpc: skip memory barrier in membarrier_arch_sched_in() if coming
  from kernel thread, since mmdrop() implies a full barrier.
- Set membarrier_private_expedited to 1 only after arch registration
  code, thus eliminating a race where concurrent commands could succeed
  when they should fail if issued concurrently with process
  registration.
- Use READ_ONCE() for membarrier_private_expedited field access in
  membarrier_private_expedited. Matches WRITE_ONCE() performed in
  process registration.

Changes since v4:
- Move powerpc hook from sched_in() to switch_mm(), based on feedback
  from Nicholas Piggin.

Changes since v5:
- Rebase on v4.14-rc6.
- Fold "Fix: membarrier: Handle CLONE_VM + !CLONE_THREAD correctly on
  powerpc (v2)"

Changes since v6:
- Rename MEMBARRIER_STATE_SWITCH_MM to MEMBARRIER_STATE_PRIVATE_EXPEDITED.

Signed-off-by: Mathieu Desnoyers 
CC: Peter Zijlstra 
CC: Paul E. McKenney 
CC: Boqun Feng 
CC: Andrew Hunter 
CC: Maged Michael 
CC: Avi Kivity 
CC: Benjamin Herrenschmidt 
CC: Paul Mackerras 
CC: Michael Ellerman 
CC: Dave Watson 
CC: Alan Stern 
CC: Will Deacon 
CC: Andy Lutomirski 
CC: Ingo Molnar 
CC: Alexander Viro 
CC: Nicholas Piggin 
CC: linuxppc-dev@lists.ozlabs.org
CC: linux-a...@vger.kernel.org
---
 MAINTAINERS   |  1 +
 arch/powerpc/Kconfig  |  1 +
 arch/powerpc/include/asm/membarrier.h | 26 ++
 arch/powerpc/mm/mmu_context.c |  7 +++
 include/linux/sched/mm.h  | 13 -
 init/Kconfig  |  3 +++
 kernel/sched/core.c   | 10 --
 kernel/sched/membarrier.c |  8 
 8 files changed, 58 insertions(+), 11 deletions(-)
 create mode 100644 arch/powerpc/include/asm/membarrier.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 95c3fa1f520f..a0ad9fe5735b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8931,6 +8931,7 @@ L:linux-ker...@vger.kernel.org
 S: Supported
 F: kernel/sched/membarrier.c
 F: include/uapi/linux/membarrier.h
+F: arch/powerpc/include/asm/membarrier.h
 
 MEMORY MANAGEMENT
 L: linux...@kvack.org
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c51e6ce42e7a..a63adb082c0a 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -140,6 +140,7 @@ config PPC
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_PMEM_APIif PPC64
+   

Re: [PATCH 10/22] swiotlb: refactor coherent buffer allocation

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 12:22:18PM +, Robin Murphy wrote:
>> +if (phys_addr == SWIOTLB_MAP_ERROR)
>> +goto out_warn;
>>   -  /* Confirm address can be DMA'd by device */
>> -if (dev_addr + size - 1 > dma_mask) {
>> -printk("hwdev DMA mask = 0x%016Lx, dev_addr = 
>> 0x%016Lx\n",
>> -   (unsigned long long)dma_mask,
>> -   (unsigned long long)dev_addr);
>> +*dma_handle = swiotlb_phys_to_dma(dev, phys_addr);
>
> nit: this should probably go after the dma_coherent_ok() check (as with the 
> original logic).

But the originall logic also needs the dma_addr_t for the
dma_coherent_ok check:

dev_addr = swiotlb_phys_to_dma(hwdev, paddr);
/* Confirm address can be DMA'd by device */
if (dev_addr + size - 1 > dma_mask) {
...
goto err_warn;
}

or do you mean assining to *dma_handle?  The dma_handle is not
valid for a failure return, so I don't think this should matter.

>> +if (ret) {
>> +*dma_handle = swiotlb_virt_to_bus(hwdev, ret);
>> +if (dma_coherent_ok(hwdev, *dma_handle, size)) {
>> +memset(ret, 0, size);
>> +return ret;
>> +}
>
> Aren't we leaking the pages here?

Yes, that free_pages got lost somewhere in the rebases, I've added
it back.


Re: [PATCH 11/33] dma-mapping: move swiotlb arch helpers to a new header

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 03:31:08PM +, Robin Murphy wrote:
> Yes indeed, modulo Vladimir's comments - it does seem prudent to fix the 
> obvious off-by-ones as we touch them. I've wanted to do something like this 
> for ages, but never got around to it myself.

I've fixed these now in a separate patch.  I'm taking this as an
Acked-by.


Re: [PATCH 08/22] swiotlb: wire up ->dma_supported in swiotlb_dma_ops

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 12:16:15PM +, Robin Murphy wrote:
> On 10/01/18 08:09, Christoph Hellwig wrote:
>> To properly reject too small DMA masks based on the addressability of the
>> bounce buffer.
>
> I reckon this is self-evident enough that it should simply be squashed into 
> the previous patch.

x86 didn't wire it up before, so I want a clear blaimpoint for this
change instead of mixing it up.


Re: [PATCH 31/33] dma-direct: reject too small dma masks

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 11:49:34AM +, Robin Murphy wrote:
>> +#ifdef CONFIG_ZONE_DMA
>> +if (mask < DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
>> +return 0;
>> +#else
>> +/*
>> + * Because 32-bit DMA masks are so common we expect every architecture
>> + * to be able to satisfy them - either by not supporting more physical
>> + * memory, or by providing a ZONE_DMA32.  If neither is the case, the
>> + * architecture needs to use an IOMMU instead of the direct mapping.
>> + */
>> +if (mask < DMA_BIT_MASK(32))
>> +return 0;
>
> Do you think it's worth the effort to be a little more accommodating here? 
> i.e.:
>
>   return dma_max_pfn(dev) >= max_pfn;
>
> We seem to have a fair few 28-31 bit masks for older hardware which 
> probably associates with host systems packing equivalently small amounts of 
> RAM.

And those devices don't have a ZONE_DMA?  I think we could do something
like that, but I'd rather have it as a separate commit with a good
explanation.  Maybe you can just send on on top of the series?


Re: [PATCH 11/33] dma-mapping: move swiotlb arch helpers to a new header

2018-01-10 Thread Robin Murphy

On 10/01/18 15:26, Christoph Hellwig wrote:

On Wed, Jan 10, 2018 at 02:56:01PM +, Robin Murphy wrote:

I took a look at these, and it seems their phys_to_dma() usage is doing the
thing which we subsequently formalised as dma_map_resource(). I've had a
crack at a quick patch to update the CESA driver; qcom_nandc looks slightly
more complex in that the changes probably need to span the BAM dmaengine
driver as well.


Sounds great, although probably something for the next merge window.

In the meantime does this patch looks good to you?


Yes indeed, modulo Vladimir's comments - it does seem prudent to fix the 
obvious off-by-ones as we touch them. I've wanted to do something like 
this for ages, but never got around to it myself.


Thanks,
Robin.


Re: [PATCH 27/33] dma-direct: use node local allocations for coherent memory

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 12:06:22PM +, Robin Murphy wrote:
> On 10/01/18 08:00, Christoph Hellwig wrote:
>> To preserve the x86 behavior.
>
> And combined with patch 10/22 of the SWIOTLB refactoring, this means 
> SWIOTLB allocations will also end up NUMA-aware, right? Great, that's what 
> we want on arm64 too :)

Well, only for swiotlb allocations that can be satisfied by
dma_direct_alloc.  If we actually have to fall back to the swiotlb
buffers there is not node affinity yet.


Re: [PATCH 20/33] dma-mapping: clear harmful GFP_* flags in common code

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 11:59:30AM +, Robin Murphy wrote:
> Just a note that if we're all happy to enshrine the "allocations are always 
> zeroed" behaviour in the API (I am too, for the record), we should remember 
> to follow up once the dust settles to update the docs and I guess just 
> #define dma_zalloc_coherent dma_alloc_coherent.

And then just remove it.  But yes, another item for the todo list..


Re: [PATCH 11/33] dma-mapping: move swiotlb arch helpers to a new header

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 02:56:01PM +, Robin Murphy wrote:
> I took a look at these, and it seems their phys_to_dma() usage is doing the 
> thing which we subsequently formalised as dma_map_resource(). I've had a 
> crack at a quick patch to update the CESA driver; qcom_nandc looks slightly 
> more complex in that the changes probably need to span the BAM dmaengine 
> driver as well.

Sounds great, although probably something for the next merge window.

In the meantime does this patch looks good to you?


Re: [PATCH 11/33] dma-mapping: move swiotlb arch helpers to a new header

2018-01-10 Thread Christoph Hellwig
On Wed, Jan 10, 2018 at 09:31:45AM +, Vladimir Murzin wrote:
> I know it is copy, but it seems it has off by one error and it should be
> 
> return addr + size - 1 <= *dev->dma_mask;

I've added a new patch to fix the mips dma_capable() definition,
thanks.


Re: [PATCH 11/33] dma-mapping: move swiotlb arch helpers to a new header

2018-01-10 Thread Robin Murphy

On 10/01/18 08:00, Christoph Hellwig wrote:

phys_to_dma, dma_to_phys and dma_capable are helpers published by
architecture code for use of swiotlb and xen-swiotlb only.  Drivers are
not supposed to use these directly, but use the DMA API instead.

Move these to a new asm/dma-direct.h helper, included by a
linux/dma-direct.h wrapper that provides the default linear mapping
unless the architecture wants to override it.

Signed-off-by: Christoph Hellwig 
---

[...]

  drivers/crypto/marvell/cesa.c  |  1 +
  drivers/mtd/nand/qcom_nandc.c  |  1 +


I took a look at these, and it seems their phys_to_dma() usage is doing 
the thing which we subsequently formalised as dma_map_resource(). I've 
had a crack at a quick patch to update the CESA driver; qcom_nandc looks 
slightly more complex in that the changes probably need to span the BAM 
dmaengine driver as well.


In the process, though, I stumbled across gen_pool_dma_alloc() - yuck, 
something needs doing there, for sure...


Robin.


[PATCH] powerpc/xmon: Don't print hashed pointers in paca dump

2018-01-10 Thread Michael Ellerman
Remember when the biggest problem we had to worry about was hashed
pointers, those were the days.

These were missed in my earlier patch because they don't match "%p",
but the macro is hiding a "%p", so these all end up being hashed,
which is not what we want in xmon. Convert them to "%px".

Signed-off-by: Michael Ellerman 
---
 arch/powerpc/xmon/xmon.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index b3bb5beec54a..0ddc7ac6c5f1 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2344,10 +2344,10 @@ static void dump_one_paca(int cpu)
DUMP(p, kernel_toc, "lx");
DUMP(p, kernelbase, "lx");
DUMP(p, kernel_msr, "lx");
-   DUMP(p, emergency_sp, "p");
+   DUMP(p, emergency_sp, "px");
 #ifdef CONFIG_PPC_BOOK3S_64
-   DUMP(p, nmi_emergency_sp, "p");
-   DUMP(p, mc_emergency_sp, "p");
+   DUMP(p, nmi_emergency_sp, "px");
+   DUMP(p, mc_emergency_sp, "px");
DUMP(p, in_nmi, "x");
DUMP(p, in_mce, "x");
DUMP(p, hmi_event_available, "x");
@@ -2382,14 +2382,14 @@ static void dump_one_paca(int cpu)
 #endif
DUMP(p, dscr_default, "llx");
 #ifdef CONFIG_PPC_BOOK3E
-   DUMP(p, pgd, "p");
-   DUMP(p, kernel_pgd, "p");
-   DUMP(p, tcd_ptr, "p");
-   DUMP(p, mc_kstack, "p");
-   DUMP(p, crit_kstack, "p");
-   DUMP(p, dbg_kstack, "p");
+   DUMP(p, pgd, "px");
+   DUMP(p, kernel_pgd, "px");
+   DUMP(p, tcd_ptr, "px");
+   DUMP(p, mc_kstack, "px");
+   DUMP(p, crit_kstack, "px");
+   DUMP(p, dbg_kstack, "px");
 #endif
-   DUMP(p, __current, "p");
+   DUMP(p, __current, "px");
DUMP(p, kstack, "lx");
printf(" kstack_base  = 0x%016lx\n", p->kstack & ~(THREAD_SIZE 
- 1));
DUMP(p, stab_rr, "lx");
@@ -2407,7 +2407,7 @@ static void dump_one_paca(int cpu)
 #endif
 
 #ifdef CONFIG_PPC_POWERNV
-   DUMP(p, core_idle_state_ptr, "p");
+   DUMP(p, core_idle_state_ptr, "px");
DUMP(p, thread_idle_state, "x");
DUMP(p, thread_mask, "x");
DUMP(p, subcore_sibling_mask, "x");
-- 
2.14.3



Re: [PATCH V6] cxl: Add support for ASB_Notify on POWER9

2018-01-10 Thread Frederic Barrat

Hi Christophe,


Couple of comments about file.c, the rest of the patch looks ok to me.



@@ -193,6 +194,7 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
amr = work.amr & mfspr(SPRN_UAMOR);

ctx->mmio_err_ff = !!(work.flags & CXL_START_WORK_ERR_FF);
+   ctx->wflags = work.flags;



I would prefer to add a	boolean "need to allocate a TID" to the context 
instead of saving the full user land flags, that seems more in-line with 
the existing code.




/*
 * Increment the mapped context count for adapter. This also checks
@@ -263,6 +265,12 @@ static long afu_ioctl_start_work(struct cxl_context *ctx,
goto out;
}

+   if (work.flags & CXL_START_WORK_TID) {
+   work.tid = ctx->tidr;
+   if (copy_to_user(uwork, , sizeof(work)))
+   return -EFAULT;
+   }
+


In case of error writing the TID value to user space, we still need to 
release the mutex and mark the context as STARTED.


  Fred



ctx->status = STARTED;
rc = 0;
  out:
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index 02b6b45..0cccf27 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -16,6 +16,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 

  #include "cxl.h"
@@ -655,6 +656,7 @@ static void update_ivtes_directed(struct cxl_context *ctx)
  static int process_element_entry_psl9(struct cxl_context *ctx, u64 wed, u64 
amr)
  {
u32 pid;
+   int rc;

cxl_assign_psn_space(ctx);

@@ -673,7 +675,16 @@ static int process_element_entry_psl9(struct cxl_context 
*ctx, u64 wed, u64 amr)
pid = ctx->mm->context.id;
}

-   ctx->elem->common.tid = 0;
+   /* Assign a unique TIDR (thread id) for the current thread */
+   if (!(ctx->tidr) && (ctx->wflags & CXL_START_WORK_TID)) {
+   rc = set_thread_tidr(current);
+   if (rc)
+   return -ENODEV;
+   ctx->tidr = current->thread.tidr;
+   pr_devel("%s: current tidr: %d\n", __func__, ctx->tidr);
+   }
+
+   ctx->elem->common.tid = cpu_to_be32(ctx->tidr);
ctx->elem->common.pid = cpu_to_be32(pid);

ctx->elem->sr = cpu_to_be64(calculate_sr(ctx));
diff --git a/include/uapi/misc/cxl.h b/include/uapi/misc/cxl.h
index 49e8fd0..56376d3 100644
--- a/include/uapi/misc/cxl.h
+++ b/include/uapi/misc/cxl.h
@@ -20,20 +20,22 @@ struct cxl_ioctl_start_work {
__u64 work_element_descriptor;
__u64 amr;
__s16 num_interrupts;
-   __s16 reserved1;
-   __s32 reserved2;
+   __u16 tid;
+   __s32 reserved1;
+   __u64 reserved2;
__u64 reserved3;
__u64 reserved4;
__u64 reserved5;
-   __u64 reserved6;
  };

  #define CXL_START_WORK_AMR0x0001ULL
  #define CXL_START_WORK_NUM_IRQS   0x0002ULL
  #define CXL_START_WORK_ERR_FF 0x0004ULL
+#define CXL_START_WORK_TID 0x0008ULL
  #define CXL_START_WORK_ALL(CXL_START_WORK_AMR |\
 CXL_START_WORK_NUM_IRQS |\
-CXL_START_WORK_ERR_FF)
+CXL_START_WORK_ERR_FF |\
+CXL_START_WORK_TID)


  /* Possible modes that an afu can be in */





[PATCH] powerpc/xmon: Add RFI flush related fields to paca dump

2018-01-10 Thread Michael Ellerman
Signed-off-by: Michael Ellerman 
---
 arch/powerpc/xmon/xmon.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index cab24f549e7c..b3bb5beec54a 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -2375,6 +2375,10 @@ static void dump_one_paca(int cpu)
DUMP(p, slb_cache_ptr, "x");
for (i = 0; i < SLB_CACHE_ENTRIES; i++)
printf(" slb_cache[%d]:= 0x%016lx\n", i, 
p->slb_cache[i]);
+
+   DUMP(p, rfi_flush_fallback_area, "px");
+   DUMP(p, l1d_flush_congruence, "llx");
+   DUMP(p, l1d_flush_sets, "llx");
 #endif
DUMP(p, dscr_default, "llx");
 #ifdef CONFIG_PPC_BOOK3E
-- 
2.14.3



Re: [PATCH 22/22] arm64: use swiotlb_alloc and swiotlb_free

2018-01-10 Thread Robin Murphy

On 10/01/18 08:09, Christoph Hellwig wrote:

The generic swiotlb_alloc and swiotlb_free routines already take care
of CMA allocations and adding GFP_DMA32 where needed, so use them
instead of the arm specific helpers.


It took a while to satisfy myself that the GFP_DMA(32) handling ends up 
equivalent to the current behaviour, but I think it checks out. This 
will certainly help with the long-overdue cleanup of this file that I've 
had sat around half-finished for ages.


Reviewed-by: Robin Murphy 


Signed-off-by: Christoph Hellwig 
---
  arch/arm64/Kconfig  |  1 +
  arch/arm64/mm/dma-mapping.c | 46 +++--
  2 files changed, 4 insertions(+), 43 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6b6985f15d02..53205c02b18a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -59,6 +59,7 @@ config ARM64
select COMMON_CLK
select CPU_PM if (SUSPEND || CPU_IDLE)
select DCACHE_WORD_ACCESS
+   select DMA_DIRECT_OPS
select EDAC_SUPPORT
select FRAME_POINTER
select GENERIC_ALLOCATOR
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 0d641875b20e..a96ec0181818 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -91,46 +91,6 @@ static int __free_from_pool(void *start, size_t size)
return 1;
  }
  
-static void *__dma_alloc_coherent(struct device *dev, size_t size,

- dma_addr_t *dma_handle, gfp_t flags,
- unsigned long attrs)
-{
-   if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
-   dev->coherent_dma_mask <= DMA_BIT_MASK(32))
-   flags |= GFP_DMA32;
-   if (dev_get_cma_area(dev) && gfpflags_allow_blocking(flags)) {
-   struct page *page;
-   void *addr;
-
-   page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
-get_order(size), flags);
-   if (!page)
-   return NULL;
-
-   *dma_handle = phys_to_dma(dev, page_to_phys(page));
-   addr = page_address(page);
-   memset(addr, 0, size);
-   return addr;
-   } else {
-   return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
-   }
-}
-
-static void __dma_free_coherent(struct device *dev, size_t size,
-   void *vaddr, dma_addr_t dma_handle,
-   unsigned long attrs)
-{
-   bool freed;
-   phys_addr_t paddr = dma_to_phys(dev, dma_handle);
-
-
-   freed = dma_release_from_contiguous(dev,
-   phys_to_page(paddr),
-   size >> PAGE_SHIFT);
-   if (!freed)
-   swiotlb_free_coherent(dev, size, vaddr, dma_handle);
-}
-
  static void *__dma_alloc(struct device *dev, size_t size,
 dma_addr_t *dma_handle, gfp_t flags,
 unsigned long attrs)
@@ -152,7 +112,7 @@ static void *__dma_alloc(struct device *dev, size_t size,
return addr;
}
  
-	ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs);

+   ptr = swiotlb_alloc(dev, size, dma_handle, flags, attrs);
if (!ptr)
goto no_mem;
  
@@ -173,7 +133,7 @@ static void *__dma_alloc(struct device *dev, size_t size,

return coherent_ptr;
  
  no_map:

-   __dma_free_coherent(dev, size, ptr, *dma_handle, attrs);
+   swiotlb_free(dev, size, ptr, *dma_handle, attrs);
  no_mem:
return NULL;
  }
@@ -191,7 +151,7 @@ static void __dma_free(struct device *dev, size_t size,
return;
vunmap(vaddr);
}
-   __dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs);
+   swiotlb_free(dev, size, swiotlb_addr, dma_handle, attrs);
  }
  
  static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,




Re: [PATCH 21/22] arm64: replace ZONE_DMA with ZONE_DMA32

2018-01-10 Thread Robin Murphy

On 10/01/18 08:09, Christoph Hellwig wrote:

arm64 uses ZONE_DMA for allocations below 32-bits.  These days we
name the zone for that ZONE_DMA32, which will allow to use the
dma-direct and generic swiotlb code as-is, so rename it.


I do wonder if we could also "upgrade" GFP_DMA to GFP_DMA32 somehow when 
!ZONE_DMA - there are almost certainly arm64 drivers out there using a 
combination of GFP_DMA and streaming mappings which will no longer get 
the guaranteed 32-bit addresses they expect after this. I'm not sure 
quite how feasible that is, though :/


That said, I do agree that this is an appropriate change (the legacy of 
GFP_DMA is obviously horrible), so, provided we get plenty of time to 
find and fix the fallout when it lands:


Reviewed-by: Robin Murphy 

Robin.


Signed-off-by: Christoph Hellwig 
---
  arch/arm64/Kconfig  |  2 +-
  arch/arm64/mm/dma-mapping.c |  6 +++---
  arch/arm64/mm/init.c| 16 
  3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c9a7e9e1414f..6b6985f15d02 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -227,7 +227,7 @@ config GENERIC_CSUM
  config GENERIC_CALIBRATE_DELAY
def_bool y
  
-config ZONE_DMA

+config ZONE_DMA32
def_bool y
  
  config HAVE_GENERIC_GUP

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 6840426bbe77..0d641875b20e 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -95,9 +95,9 @@ static void *__dma_alloc_coherent(struct device *dev, size_t 
size,
  dma_addr_t *dma_handle, gfp_t flags,
  unsigned long attrs)
  {
-   if (IS_ENABLED(CONFIG_ZONE_DMA) &&
+   if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
dev->coherent_dma_mask <= DMA_BIT_MASK(32))
-   flags |= GFP_DMA;
+   flags |= GFP_DMA32;
if (dev_get_cma_area(dev) && gfpflags_allow_blocking(flags)) {
struct page *page;
void *addr;
@@ -397,7 +397,7 @@ static int __init atomic_pool_init(void)
page = dma_alloc_from_contiguous(NULL, nr_pages,
 pool_size_order, GFP_KERNEL);
else
-   page = alloc_pages(GFP_DMA, pool_size_order);
+   page = alloc_pages(GFP_DMA32, pool_size_order);
  
  	if (page) {

int ret;
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 00e7b900ca41..8f03276443c9 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -217,7 +217,7 @@ static void __init reserve_elfcorehdr(void)
  }
  #endif /* CONFIG_CRASH_DUMP */
  /*
- * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It
+ * Return the maximum physical address for ZONE_DMA32 (DMA_BIT_MASK(32)). It
   * currently assumes that for memory starting above 4G, 32-bit devices will
   * use a DMA offset.
   */
@@ -233,8 +233,8 @@ static void __init zone_sizes_init(unsigned long min, 
unsigned long max)
  {
unsigned long max_zone_pfns[MAX_NR_ZONES]  = {0};
  
-	if (IS_ENABLED(CONFIG_ZONE_DMA))

-   max_zone_pfns[ZONE_DMA] = PFN_DOWN(max_zone_dma_phys());
+   if (IS_ENABLED(CONFIG_ZONE_DMA32))
+   max_zone_pfns[ZONE_DMA32] = PFN_DOWN(max_zone_dma_phys());
max_zone_pfns[ZONE_NORMAL] = max;
  
  	free_area_init_nodes(max_zone_pfns);

@@ -251,9 +251,9 @@ static void __init zone_sizes_init(unsigned long min, 
unsigned long max)
memset(zone_size, 0, sizeof(zone_size));
  
  	/* 4GB maximum for 32-bit only capable devices */

-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ZONE_DMA32
max_dma = PFN_DOWN(arm64_dma_phys_limit);
-   zone_size[ZONE_DMA] = max_dma - min;
+   zone_size[ZONE_DMA32] = max_dma - min;
  #endif
zone_size[ZONE_NORMAL] = max - max_dma;
  
@@ -266,10 +266,10 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)

if (start >= max)
continue;
  
-#ifdef CONFIG_ZONE_DMA

+#ifdef CONFIG_ZONE_DMA32
if (start < max_dma) {
unsigned long dma_end = min(end, max_dma);
-   zhole_size[ZONE_DMA] -= dma_end - start;
+   zhole_size[ZONE_DMA32] -= dma_end - start;
}
  #endif
if (end > max_dma) {
@@ -467,7 +467,7 @@ void __init arm64_memblock_init(void)
early_init_fdt_scan_reserved_mem();
  
  	/* 4GB maximum for 32-bit only capable devices */

-   if (IS_ENABLED(CONFIG_ZONE_DMA))
+   if (IS_ENABLED(CONFIG_ZONE_DMA32))
arm64_dma_phys_limit = max_zone_dma_phys();
else
arm64_dma_phys_limit = PHYS_MASK + 1;



Re: consolidate swiotlb dma_map implementations

2018-01-10 Thread Christian König

Acked-by: Christian König  for the whole series.

Regards,
Christian.

Am 10.01.2018 um 09:09 schrieb Christoph Hellwig:

A lot of architectures have essentially identical dma_map_ops
implementations to use swiotlb.  This series adds new generic
swiotlb_alloc/free helpers that take the attrs argument exposed
in dma_map_ops, and which do an enhanced direct allocation
modelled after x86 and reused from the dma-direct code, and
then switches most architectures over to it.  The only exceptions
are mips, which requires additional cache flushing which will
need a new abstraction, and x86 itself which will be handled in
a later series with other x86 dma mapping changes.

To support the generic code a few architectures that currently
use ZONE_DMA/GFP_DMA for <= 32-bit allocations are switched to
implement ZONE_DMA32 instead.

This series is based on the previously sent series to consolidate
the direct dma mapping implementation.  A git tree with this
series as well as the prerequisites is available here:

git://git.infradead.org/users/hch/misc.git swiotlb

Gitweb:

http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/swiotlb




Re: [PATCH 10/22] swiotlb: refactor coherent buffer allocation

2018-01-10 Thread Robin Murphy

On 10/01/18 08:09, Christoph Hellwig wrote:

Factor out a new swiotlb_alloc_buffer helper that allocates DMA coherent
memory from the swiotlb bounce buffer.

This allows to simplify the swiotlb_alloc implemenation that uses
dma_direct_alloc to try to allocate a reachable buffer first.

Signed-off-by: Christoph Hellwig 
---
  lib/swiotlb.c | 122 +++---
  1 file changed, 65 insertions(+), 57 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 1a147f1354a1..bf2d19ee91c1 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -709,75 +709,79 @@ void swiotlb_tbl_sync_single(struct device *hwdev, 
phys_addr_t tlb_addr,
  }
  EXPORT_SYMBOL_GPL(swiotlb_tbl_sync_single);
  
-void *

-swiotlb_alloc_coherent(struct device *hwdev, size_t size,
-  dma_addr_t *dma_handle, gfp_t flags)
+static inline bool dma_coherent_ok(struct device *dev, dma_addr_t addr,
+   size_t size)
  {
-   bool warn = !(flags & __GFP_NOWARN);
-   dma_addr_t dev_addr;
-   void *ret;
-   int order = get_order(size);
-   u64 dma_mask = DMA_BIT_MASK(32);
+   u64 mask = DMA_BIT_MASK(32);
  
-	if (hwdev && hwdev->coherent_dma_mask)

-   dma_mask = hwdev->coherent_dma_mask;
+   if (dev && dev->coherent_dma_mask)
+   mask = dev->coherent_dma_mask;
+   return addr + size - 1 <= mask;
+}
  
-	ret = (void *)__get_free_pages(flags, order);

-   if (ret) {
-   dev_addr = swiotlb_virt_to_bus(hwdev, ret);
-   if (dev_addr + size - 1 > dma_mask) {
-   /*
-* The allocated memory isn't reachable by the device.
-*/
-   free_pages((unsigned long) ret, order);
-   ret = NULL;
-   }
-   }
-   if (!ret) {
-   /*
-* We are either out of memory or the device can't DMA to
-* GFP_DMA memory; fall back on map_single(), which
-* will grab memory from the lowest available address range.
-*/
-   phys_addr_t paddr = map_single(hwdev, 0, size, DMA_FROM_DEVICE,
-  warn ? 0 : DMA_ATTR_NO_WARN);
-   if (paddr == SWIOTLB_MAP_ERROR)
-   goto err_warn;
+static void *
+swiotlb_alloc_buffer(struct device *dev, size_t size, dma_addr_t *dma_handle,
+   unsigned long attrs)
+{
+   phys_addr_t phys_addr;
+
+   if (swiotlb_force == SWIOTLB_NO_FORCE)
+   goto out_warn;
  
-		ret = phys_to_virt(paddr);

-   dev_addr = swiotlb_phys_to_dma(hwdev, paddr);
+   phys_addr = swiotlb_tbl_map_single(dev,
+   swiotlb_phys_to_dma(dev, io_tlb_start),
+   0, size, DMA_FROM_DEVICE, 0);
+   if (phys_addr == SWIOTLB_MAP_ERROR)
+   goto out_warn;
  
-		/* Confirm address can be DMA'd by device */

-   if (dev_addr + size - 1 > dma_mask) {
-   printk("hwdev DMA mask = 0x%016Lx, dev_addr = 
0x%016Lx\n",
-  (unsigned long long)dma_mask,
-  (unsigned long long)dev_addr);
+   *dma_handle = swiotlb_phys_to_dma(dev, phys_addr);


nit: this should probably go after the dma_coherent_ok() check (as with 
the original logic).


  
-			/*

-* DMA_TO_DEVICE to avoid memcpy in unmap_single.
-* The DMA_ATTR_SKIP_CPU_SYNC is optional.
-*/
-   swiotlb_tbl_unmap_single(hwdev, paddr,
-size, DMA_TO_DEVICE,
-DMA_ATTR_SKIP_CPU_SYNC);
-   goto err_warn;
-   }
-   }
+   if (dma_coherent_ok(dev, *dma_handle, size))
+   goto out_unmap;
  
-	*dma_handle = dev_addr;

-   memset(ret, 0, size);
+   memset(phys_to_virt(phys_addr), 0, size);
+   return phys_to_virt(phys_addr);
  
-	return ret;

+out_unmap:
+   dev_warn(dev, "hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
+   (unsigned long long)(dev ? dev->coherent_dma_mask : 0),
+   (unsigned long long)*dma_handle);
  
-err_warn:

-   if (warn && printk_ratelimit()) {
-   pr_warn("swiotlb: coherent allocation failed for device %s 
size=%zu\n",
-   dev_name(hwdev), size);
+   /*
+* DMA_TO_DEVICE to avoid memcpy in unmap_single.
+* DMA_ATTR_SKIP_CPU_SYNC is optional.
+*/
+   swiotlb_tbl_unmap_single(dev, phys_addr, size, DMA_TO_DEVICE,
+   DMA_ATTR_SKIP_CPU_SYNC);
+out_warn:
+   if ((attrs & DMA_ATTR_NO_WARN) && printk_ratelimit()) {
+   dev_warn(dev,
+   "swiotlb: coherent allocation failed, size=%zu\n",
+   

Re: [PATCH 08/22] swiotlb: wire up ->dma_supported in swiotlb_dma_ops

2018-01-10 Thread Robin Murphy

On 10/01/18 08:09, Christoph Hellwig wrote:

To properly reject too small DMA masks based on the addressability of the
bounce buffer.


I reckon this is self-evident enough that it should simply be squashed 
into the previous patch.


Robin.


Signed-off-by: Christoph Hellwig 
---
  lib/swiotlb.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 0fae2f45c3c0..539fd1099ba9 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -1128,5 +1128,6 @@ const struct dma_map_ops swiotlb_dma_ops = {
.unmap_sg   = swiotlb_unmap_sg_attrs,
.map_page   = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page,
+   .dma_supported  = swiotlb_dma_supported,
  };
  #endif /* CONFIG_DMA_DIRECT_OPS */



Re: [PATCH 02/22] arm64: rename swiotlb_dma_ops

2018-01-10 Thread Robin Murphy

On 10/01/18 08:09, Christoph Hellwig wrote:

We'll need that name for a generic implementation soon.


Reviewed-by: Robin Murphy 


Signed-off-by: Christoph Hellwig 
---
  arch/arm64/mm/dma-mapping.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index f3a637b98487..6840426bbe77 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -368,7 +368,7 @@ static int __swiotlb_dma_mapping_error(struct device 
*hwdev, dma_addr_t addr)
return 0;
  }
  
-static const struct dma_map_ops swiotlb_dma_ops = {

+static const struct dma_map_ops arm64_swiotlb_dma_ops = {
.alloc = __dma_alloc,
.free = __dma_free,
.mmap = __swiotlb_mmap,
@@ -923,7 +923,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, 
u64 size,
const struct iommu_ops *iommu, bool coherent)
  {
if (!dev->dma_ops)
-   dev->dma_ops = _dma_ops;
+   dev->dma_ops = _swiotlb_dma_ops;
  
  	dev->archdata.dma_coherent = coherent;

__iommu_setup_dma_ops(dev, dma_base, size, iommu);



Re: [PATCH 27/33] dma-direct: use node local allocations for coherent memory

2018-01-10 Thread Robin Murphy

On 10/01/18 08:00, Christoph Hellwig wrote:

To preserve the x86 behavior.


And combined with patch 10/22 of the SWIOTLB refactoring, this means 
SWIOTLB allocations will also end up NUMA-aware, right? Great, that's 
what we want on arm64 too :)


Reviewed-by: Robin Murphy 


Signed-off-by: Christoph Hellwig 
---
  lib/dma-direct.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index a9ae98be7af3..f04a424f91fa 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -38,7 +38,7 @@ static void *dma_direct_alloc(struct device *dev, size_t size,
if (gfpflags_allow_blocking(gfp))
page = dma_alloc_from_contiguous(dev, count, page_order, gfp);
if (!page)
-   page = alloc_pages(gfp, page_order);
+   page = alloc_pages_node(dev_to_node(dev), gfp, page_order);
if (!page)
return NULL;
  



Re: [v3 PATCH 2/3] powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous pstates

2018-01-10 Thread Rafael J. Wysocki
On Wednesday, January 10, 2018 9:55:45 AM CET Gautham R Shenoy wrote:
> Hi Rafael,
> 
> On Wed, Jan 03, 2018 at 11:47:58PM +1100, Balbir Singh wrote:
> > On Wed, Jan 3, 2018 at 11:07 PM, Rafael J. Wysocki  
> > wrote:
> > > On Monday, December 18, 2017 9:38:20 AM CET Gautham R Shenoy wrote:
> > >> Hi Balbir,
> > >>
> > >> On Sun, Dec 17, 2017 at 02:15:25PM +1100, Balbir Singh wrote:
> > >> > On Wed, Dec 13, 2017 at 5:57 PM, Gautham R. Shenoy
> > >> >  wrote:
> > >> > > From: "Gautham R. Shenoy" 
> > >> > >
> > >> > > The code in powernv-cpufreq, makes the following two assumptions 
> > >> > > which
> > >> > > are not guaranteed by the device-tree bindings:
> > >> > >
> > >> > > 1) Pstate ids are continguous: This is used in pstate_to_idx() to
> > >> > >obtain the reverse map from a pstate to it's corresponding
> > >> > >entry into the cpufreq frequency table.
> > >> > >
> > >> > > 2) Every Pstate should always lie between the max and the min
> > >> > >pstates that are explicitly reported in the device tree: This
> > >> > >is used to determine whether a pstate reported by the PMSR is
> > >> > >out of bounds.
> > >> > >
> > >> > > Both these assumptions are unwarranted and can change on future
> > >> > > platforms.
> > >> >
> > >> > While this is a good thing, I wonder if it is worth the complexity. 
> > >> > Pstates
> > >> > are contiguous because they define transitions in incremental value
> > >> > of change in frequency and I can't see how this can be broken in the
> > >> > future?
> > >>
> > >> In the future, we can have the OPAL firmware give us a smaller set of
> > >> pstates instead of expose every one of them. As it stands today, for
> > >> most of the workloads, we will need at best 20-30 pstates and not
> > >> beyond that.
> > >
> > > I'm not sure about the status here.
> > >
> > > Is this good to go as is or is it going to be updated?
> > >
> > 
> > I have no major objections, except some of the added complexity, but
> > Gautham makes a point that this is refactoring for the future
> 
> I have tested this across POWER8 and POWER9. The additional complexity
> introduced by the second patch is required for the future when we are
> going to reduce the number of pstates.

I have applied the series, thanks!



Re: [PATCH 20/33] dma-mapping: clear harmful GFP_* flags in common code

2018-01-10 Thread Robin Murphy

On 10/01/18 08:00, Christoph Hellwig wrote:
[...]

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 9f28b2fa329e..88bcb1a8211d 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -518,6 +518,13 @@ static inline void *dma_alloc_attrs(struct device *dev, 
size_t size,
if (dma_alloc_from_dev_coherent(dev, size, dma_handle, _addr))
return cpu_addr;
  
+	/*

+* Let the implementation decide on the zone to allocate from, and
+* decide on the way of zeroing the memory given that the memory
+* returned should always be zeroed.
+*/


Just a note that if we're all happy to enshrine the "allocations are 
always zeroed" behaviour in the API (I am too, for the record), we 
should remember to follow up once the dust settles to update the docs 
and I guess just #define dma_zalloc_coherent dma_alloc_coherent.


Robin.


+   flag &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM | __GFP_ZERO);
+
if (!arch_dma_alloc_attrs(, ))
return NULL;
if (!ops->alloc)



Re: [PATCH 31/33] dma-direct: reject too small dma masks

2018-01-10 Thread Robin Murphy

On 10/01/18 08:00, Christoph Hellwig wrote:

Signed-off-by: Christoph Hellwig 
---
  include/linux/dma-direct.h |  1 +
  lib/dma-direct.c   | 19 +++
  2 files changed, 20 insertions(+)

diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index 4788bf0bf683..bcdb1a3e4b1f 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -42,5 +42,6 @@ void *dma_direct_alloc(struct device *dev, size_t size, 
dma_addr_t *dma_handle,
gfp_t gfp, unsigned long attrs);
  void dma_direct_free(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_addr, unsigned long attrs);
+int dma_direct_supported(struct device *dev, u64 mask);
  
  #endif /* _LINUX_DMA_DIRECT_H */

diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index 784a68dfdbe3..40b1f92f2214 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -122,6 +122,24 @@ static int dma_direct_map_sg(struct device *dev, struct 
scatterlist *sgl,
return nents;
  }
  
+int dma_direct_supported(struct device *dev, u64 mask)

+{
+#ifdef CONFIG_ZONE_DMA
+   if (mask < DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
+   return 0;
+#else
+   /*
+* Because 32-bit DMA masks are so common we expect every architecture
+* to be able to satisfy them - either by not supporting more physical
+* memory, or by providing a ZONE_DMA32.  If neither is the case, the
+* architecture needs to use an IOMMU instead of the direct mapping.
+*/
+   if (mask < DMA_BIT_MASK(32))
+   return 0;


Do you think it's worth the effort to be a little more accommodating 
here? i.e.:


return dma_max_pfn(dev) >= max_pfn;

We seem to have a fair few 28-31 bit masks for older hardware which 
probably associates with host systems packing equivalently small amounts 
of RAM.


Otherwise though,

Reviewed-by: Robin Murphy 

Robin.


+#endif
+   return 1;
+}
+
  static int dma_direct_mapping_error(struct device *dev, dma_addr_t dma_addr)
  {
return dma_addr == DIRECT_MAPPING_ERROR;
@@ -132,6 +150,7 @@ const struct dma_map_ops dma_direct_ops = {
.free   = dma_direct_free,
.map_page   = dma_direct_map_page,
.map_sg = dma_direct_map_sg,
+   .dma_supported  = dma_direct_supported,
.mapping_error  = dma_direct_mapping_error,
  };
  EXPORT_SYMBOL(dma_direct_ops);



Re: [PATCH 10/33] arm64: don't override dma_max_pfn

2018-01-10 Thread Robin Murphy

On 10/01/18 08:00, Christoph Hellwig wrote:

The generic version now takes dma_pfn_offset into account, so there is no
more need for an architecture override.


Reviewed-by: Robin Murphy 


Signed-off-by: Christoph Hellwig 
---
  arch/arm64/include/asm/dma-mapping.h | 9 -
  1 file changed, 9 deletions(-)

diff --git a/arch/arm64/include/asm/dma-mapping.h 
b/arch/arm64/include/asm/dma-mapping.h
index 0df756b24863..eada887a93bf 100644
--- a/arch/arm64/include/asm/dma-mapping.h
+++ b/arch/arm64/include/asm/dma-mapping.h
@@ -76,14 +76,5 @@ static inline void dma_mark_clean(void *addr, size_t size)
  {
  }
  
-/* Override for dma_max_pfn() */

-static inline unsigned long dma_max_pfn(struct device *dev)
-{
-   dma_addr_t dma_max = (dma_addr_t)*dev->dma_mask;
-
-   return (ulong)dma_to_phys(dev, dma_max) >> PAGE_SHIFT;
-}
-#define dma_max_pfn(dev) dma_max_pfn(dev)
-
  #endif/* __KERNEL__ */
  #endif/* __ASM_DMA_MAPPING_H */



Re: [PATCH 09/33] dma-mapping: take dma_pfn_offset into account in dma_max_pfn

2018-01-10 Thread Robin Murphy

On 10/01/18 08:00, Christoph Hellwig wrote:

This makes sure the generic version can be used with architectures /
devices that have a DMA offset in the direct mapping.


Reviewed-by: Robin Murphy 


Signed-off-by: Christoph Hellwig 
---
  include/linux/dma-mapping.h | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 81ed9b2d84dc..d84951865be7 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -692,7 +692,7 @@ static inline int dma_set_seg_boundary(struct device *dev, 
unsigned long mask)
  #ifndef dma_max_pfn
  static inline unsigned long dma_max_pfn(struct device *dev)
  {
-   return *dev->dma_mask >> PAGE_SHIFT;
+   return (*dev->dma_mask >> PAGE_SHIFT) + dev->dma_pfn_offset;
  }
  #endif
  



[PATCH] powerpc : Fix sleeping-in-atomic section warning triggered by /proc/cpuinfo

2018-01-10 Thread Shriya
Commit cd77b5ce208c ("Fix the frequency read by /proc/cpuinfo")
to fix /proc/cpuinfo on POWERNV triggered a sleeping-in-atomic section
warning. This was because the place where we cpufreq_get (which takes
an rwsem) from show_cpuinfo is in a preempt_disabled. However, the
preempt_disable() in show_cpuinfo is for protection against
CPU-Hotplug, since we don't want to report the information of offline
CPUs in /proc/cpuinfo.

Fix this by replacing preempt_disable()/preempt_enable() in
show_cpuinfo() by get_online_cpus()/put_online_cpus() giving a proper
protection against CPU-Hotplug.
---
 arch/powerpc/kernel/setup-common.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/setup-common.c 
b/arch/powerpc/kernel/setup-common.c
index 2075322..f772442 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -244,9 +244,9 @@ static int show_cpuinfo(struct seq_file *m, void *v)

/* We only show online cpus: disable preempt (overzealous, I
 * knew) to prevent cpu going down. */
-   preempt_disable();
+   get_online_cpus();
if (!cpu_online(cpu_id)) {
-   preempt_enable();
+   put_online_cpus();
return 0;
}

@@ -359,7 +359,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_printf(m, "\n");
 #endif

-   preempt_enable();
+   put_online_cpus();

/* If this is the last cpu, print the summary */
if (cpumask_next(cpu_id, cpu_online_mask) >= nr_cpu_ids)
--
1.9.1



Re: [v3 PATCH 0/3] powernv-cpufreq: Multiple pstate related fixes.

2018-01-10 Thread Viresh Kumar
On 13-12-17, 12:27, Gautham R. Shenoy wrote:
> From: "Gautham R. Shenoy" 
> 
>  This is a third version of the patch to fix pstate related issues in
>  the powernv-cpufreq driver.

Acked-by: Viresh Kumar 

-- 
viresh


Re: [PATCH 29/33] dma-direct: retry allocations using GFP_DMA for small masks

2018-01-10 Thread Vladimir Murzin
On 10/01/18 08:00, Christoph Hellwig wrote:
> If an attempt to allocate memory succeeded, but isn't inside the
> supported DMA mask, retry the allocation with GFP_DMA set as a
> last resort.
> 
> Based on the x86 code, but an off by one error in what is now
> dma_coherent_ok has been fixed vs the x86 code.
> 
> Signed-off-by: Christoph Hellwig 
> ---
>  lib/dma-direct.c | 25 -
>  1 file changed, 24 insertions(+), 1 deletion(-)
> 
> diff --git a/lib/dma-direct.c b/lib/dma-direct.c
> index 8f76032ebc3c..4e43c2bb7f5f 100644
> --- a/lib/dma-direct.c
> +++ b/lib/dma-direct.c
> @@ -35,6 +35,11 @@ check_addr(struct device *dev, dma_addr_t dma_addr, size_t 
> size,
>   return true;
>  }
>  
> +static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t 
> size)
> +{
> + return phys_to_dma(dev, phys) + size - 1 <= dev->coherent_dma_mask;
> +}
> +
>  static void *dma_direct_alloc(struct device *dev, size_t size,
>   dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
>  {
> @@ -48,11 +53,29 @@ static void *dma_direct_alloc(struct device *dev, size_t 
> size,
>   if (dev->coherent_dma_mask <= DMA_BIT_MASK(32) && !(gfp & GFP_DMA))
>   gfp |= GFP_DMA32;
>  
> +again:
>   /* CMA can be used only in the context which permits sleeping */
> - if (gfpflags_allow_blocking(gfp))
> + if (gfpflags_allow_blocking(gfp)) {
>   page = dma_alloc_from_contiguous(dev, count, page_order, gfp);
> + if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
> + dma_release_from_contiguous(dev, page, count);
> + page = NULL;
> + }
> + }
>   if (!page)
>   page = alloc_pages_node(dev_to_node(dev), gfp, page_order);
> +
> + if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
> + __free_pages(page, page_order);
> + page = NULL;
> +
> + if (dev->coherent_dma_mask < DMA_BIT_MASK(32) &&
> + !(gfp & GFP_DMA)) {
> + gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
> + goto again;
> + }
> + }
> +
>   if (!page)
>   return NULL;
>  
> 

Reviewed-by: Vladimir Murzin 

Cheers
Vladimir


Re: [PATCH 11/33] dma-mapping: move swiotlb arch helpers to a new header

2018-01-10 Thread Vladimir Murzin
On 10/01/18 08:00, Christoph Hellwig wrote:
> index 9110988b92a1..f00833acb626 100644
> --- a/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
> +++ b/arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
> @@ -61,6 +61,14 @@ static inline void plat_post_dma_flush(struct device *dev)
>  {
>  }
>  
> +static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t 
> size)
> +{
> + if (!dev->dma_mask)
> + return false;
> +
> + return addr + size <= *dev->dma_mask;
> +}
> +

I know it is copy, but it seems it has off by one error and it should be

return addr + size - 1 <= *dev->dma_mask;


>  dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr);
>  phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr);
>  

snip...

> diff --git a/arch/mips/include/asm/mach-loongson64/dma-coherence.h 
> b/arch/mips/include/asm/mach-loongson64/dma-coherence.h
> index 1602a9e9e8c2..5cfda8f893e9 100644
> --- a/arch/mips/include/asm/mach-loongson64/dma-coherence.h
> +++ b/arch/mips/include/asm/mach-loongson64/dma-coherence.h
> @@ -17,6 +17,14 @@
>  
>  struct device;
>  
> +static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t 
> size)
> +{
> + if (!dev->dma_mask)
> + return false;
> +
> + return addr + size <= *dev->dma_mask;


ditto

Cheers
Vladimir


Re: [v3 PATCH 2/3] powernv-cpufreq: Fix pstate_to_idx() to handle non-continguous pstates

2018-01-10 Thread Gautham R Shenoy
Hi Rafael,

On Wed, Jan 03, 2018 at 11:47:58PM +1100, Balbir Singh wrote:
> On Wed, Jan 3, 2018 at 11:07 PM, Rafael J. Wysocki  wrote:
> > On Monday, December 18, 2017 9:38:20 AM CET Gautham R Shenoy wrote:
> >> Hi Balbir,
> >>
> >> On Sun, Dec 17, 2017 at 02:15:25PM +1100, Balbir Singh wrote:
> >> > On Wed, Dec 13, 2017 at 5:57 PM, Gautham R. Shenoy
> >> >  wrote:
> >> > > From: "Gautham R. Shenoy" 
> >> > >
> >> > > The code in powernv-cpufreq, makes the following two assumptions which
> >> > > are not guaranteed by the device-tree bindings:
> >> > >
> >> > > 1) Pstate ids are continguous: This is used in pstate_to_idx() to
> >> > >obtain the reverse map from a pstate to it's corresponding
> >> > >entry into the cpufreq frequency table.
> >> > >
> >> > > 2) Every Pstate should always lie between the max and the min
> >> > >pstates that are explicitly reported in the device tree: This
> >> > >is used to determine whether a pstate reported by the PMSR is
> >> > >out of bounds.
> >> > >
> >> > > Both these assumptions are unwarranted and can change on future
> >> > > platforms.
> >> >
> >> > While this is a good thing, I wonder if it is worth the complexity. 
> >> > Pstates
> >> > are contiguous because they define transitions in incremental value
> >> > of change in frequency and I can't see how this can be broken in the
> >> > future?
> >>
> >> In the future, we can have the OPAL firmware give us a smaller set of
> >> pstates instead of expose every one of them. As it stands today, for
> >> most of the workloads, we will need at best 20-30 pstates and not
> >> beyond that.
> >
> > I'm not sure about the status here.
> >
> > Is this good to go as is or is it going to be updated?
> >
> 
> I have no major objections, except some of the added complexity, but
> Gautham makes a point that this is refactoring for the future

I have tested this across POWER8 and POWER9. The additional complexity
introduced by the second patch is required for the future when we are
going to reduce the number of pstates.


> 
> Balbir Singh.
> 
--
Thanks and Regards
gautham.



[PATCH 22/22] arm64: use swiotlb_alloc and swiotlb_free

2018-01-10 Thread Christoph Hellwig
The generic swiotlb_alloc and swiotlb_free routines already take care
of CMA allocations and adding GFP_DMA32 where needed, so use them
instead of the arm specific helpers.

Signed-off-by: Christoph Hellwig 
---
 arch/arm64/Kconfig  |  1 +
 arch/arm64/mm/dma-mapping.c | 46 +++--
 2 files changed, 4 insertions(+), 43 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6b6985f15d02..53205c02b18a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -59,6 +59,7 @@ config ARM64
select COMMON_CLK
select CPU_PM if (SUSPEND || CPU_IDLE)
select DCACHE_WORD_ACCESS
+   select DMA_DIRECT_OPS
select EDAC_SUPPORT
select FRAME_POINTER
select GENERIC_ALLOCATOR
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 0d641875b20e..a96ec0181818 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -91,46 +91,6 @@ static int __free_from_pool(void *start, size_t size)
return 1;
 }
 
-static void *__dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flags,
- unsigned long attrs)
-{
-   if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
-   dev->coherent_dma_mask <= DMA_BIT_MASK(32))
-   flags |= GFP_DMA32;
-   if (dev_get_cma_area(dev) && gfpflags_allow_blocking(flags)) {
-   struct page *page;
-   void *addr;
-
-   page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
-get_order(size), flags);
-   if (!page)
-   return NULL;
-
-   *dma_handle = phys_to_dma(dev, page_to_phys(page));
-   addr = page_address(page);
-   memset(addr, 0, size);
-   return addr;
-   } else {
-   return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
-   }
-}
-
-static void __dma_free_coherent(struct device *dev, size_t size,
-   void *vaddr, dma_addr_t dma_handle,
-   unsigned long attrs)
-{
-   bool freed;
-   phys_addr_t paddr = dma_to_phys(dev, dma_handle);
-
-
-   freed = dma_release_from_contiguous(dev,
-   phys_to_page(paddr),
-   size >> PAGE_SHIFT);
-   if (!freed)
-   swiotlb_free_coherent(dev, size, vaddr, dma_handle);
-}
-
 static void *__dma_alloc(struct device *dev, size_t size,
 dma_addr_t *dma_handle, gfp_t flags,
 unsigned long attrs)
@@ -152,7 +112,7 @@ static void *__dma_alloc(struct device *dev, size_t size,
return addr;
}
 
-   ptr = __dma_alloc_coherent(dev, size, dma_handle, flags, attrs);
+   ptr = swiotlb_alloc(dev, size, dma_handle, flags, attrs);
if (!ptr)
goto no_mem;
 
@@ -173,7 +133,7 @@ static void *__dma_alloc(struct device *dev, size_t size,
return coherent_ptr;
 
 no_map:
-   __dma_free_coherent(dev, size, ptr, *dma_handle, attrs);
+   swiotlb_free(dev, size, ptr, *dma_handle, attrs);
 no_mem:
return NULL;
 }
@@ -191,7 +151,7 @@ static void __dma_free(struct device *dev, size_t size,
return;
vunmap(vaddr);
}
-   __dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs);
+   swiotlb_free(dev, size, swiotlb_addr, dma_handle, attrs);
 }
 
 static dma_addr_t __swiotlb_map_page(struct device *dev, struct page *page,
-- 
2.14.2



[PATCH 21/22] arm64: replace ZONE_DMA with ZONE_DMA32

2018-01-10 Thread Christoph Hellwig
arm64 uses ZONE_DMA for allocations below 32-bits.  These days we
name the zone for that ZONE_DMA32, which will allow to use the
dma-direct and generic swiotlb code as-is, so rename it.

Signed-off-by: Christoph Hellwig 
---
 arch/arm64/Kconfig  |  2 +-
 arch/arm64/mm/dma-mapping.c |  6 +++---
 arch/arm64/mm/init.c| 16 
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index c9a7e9e1414f..6b6985f15d02 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -227,7 +227,7 @@ config GENERIC_CSUM
 config GENERIC_CALIBRATE_DELAY
def_bool y
 
-config ZONE_DMA
+config ZONE_DMA32
def_bool y
 
 config HAVE_GENERIC_GUP
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 6840426bbe77..0d641875b20e 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -95,9 +95,9 @@ static void *__dma_alloc_coherent(struct device *dev, size_t 
size,
  dma_addr_t *dma_handle, gfp_t flags,
  unsigned long attrs)
 {
-   if (IS_ENABLED(CONFIG_ZONE_DMA) &&
+   if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
dev->coherent_dma_mask <= DMA_BIT_MASK(32))
-   flags |= GFP_DMA;
+   flags |= GFP_DMA32;
if (dev_get_cma_area(dev) && gfpflags_allow_blocking(flags)) {
struct page *page;
void *addr;
@@ -397,7 +397,7 @@ static int __init atomic_pool_init(void)
page = dma_alloc_from_contiguous(NULL, nr_pages,
 pool_size_order, GFP_KERNEL);
else
-   page = alloc_pages(GFP_DMA, pool_size_order);
+   page = alloc_pages(GFP_DMA32, pool_size_order);
 
if (page) {
int ret;
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 00e7b900ca41..8f03276443c9 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -217,7 +217,7 @@ static void __init reserve_elfcorehdr(void)
 }
 #endif /* CONFIG_CRASH_DUMP */
 /*
- * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It
+ * Return the maximum physical address for ZONE_DMA32 (DMA_BIT_MASK(32)). It
  * currently assumes that for memory starting above 4G, 32-bit devices will
  * use a DMA offset.
  */
@@ -233,8 +233,8 @@ static void __init zone_sizes_init(unsigned long min, 
unsigned long max)
 {
unsigned long max_zone_pfns[MAX_NR_ZONES]  = {0};
 
-   if (IS_ENABLED(CONFIG_ZONE_DMA))
-   max_zone_pfns[ZONE_DMA] = PFN_DOWN(max_zone_dma_phys());
+   if (IS_ENABLED(CONFIG_ZONE_DMA32))
+   max_zone_pfns[ZONE_DMA32] = PFN_DOWN(max_zone_dma_phys());
max_zone_pfns[ZONE_NORMAL] = max;
 
free_area_init_nodes(max_zone_pfns);
@@ -251,9 +251,9 @@ static void __init zone_sizes_init(unsigned long min, 
unsigned long max)
memset(zone_size, 0, sizeof(zone_size));
 
/* 4GB maximum for 32-bit only capable devices */
-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ZONE_DMA32
max_dma = PFN_DOWN(arm64_dma_phys_limit);
-   zone_size[ZONE_DMA] = max_dma - min;
+   zone_size[ZONE_DMA32] = max_dma - min;
 #endif
zone_size[ZONE_NORMAL] = max - max_dma;
 
@@ -266,10 +266,10 @@ static void __init zone_sizes_init(unsigned long min, 
unsigned long max)
if (start >= max)
continue;
 
-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ZONE_DMA32
if (start < max_dma) {
unsigned long dma_end = min(end, max_dma);
-   zhole_size[ZONE_DMA] -= dma_end - start;
+   zhole_size[ZONE_DMA32] -= dma_end - start;
}
 #endif
if (end > max_dma) {
@@ -467,7 +467,7 @@ void __init arm64_memblock_init(void)
early_init_fdt_scan_reserved_mem();
 
/* 4GB maximum for 32-bit only capable devices */
-   if (IS_ENABLED(CONFIG_ZONE_DMA))
+   if (IS_ENABLED(CONFIG_ZONE_DMA32))
arm64_dma_phys_limit = max_zone_dma_phys();
else
arm64_dma_phys_limit = PHYS_MASK + 1;
-- 
2.14.2



[PATCH 20/22] mips: use swiotlb_{alloc,free}

2018-01-10 Thread Christoph Hellwig
These already include the GFP_DMA/GFP_DMA32 usage, and will use CMA
memory if enabled, thus avoiding the GFP_NORETRY hack.

Signed-off-by: Christoph Hellwig 
---
 arch/mips/cavium-octeon/Kconfig   |  1 +
 arch/mips/cavium-octeon/dma-octeon.c  | 26 +++---
 arch/mips/loongson64/Kconfig  |  1 +
 arch/mips/loongson64/common/dma-swiotlb.c | 21 ++---
 4 files changed, 7 insertions(+), 42 deletions(-)

diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
index 204a1670fd9b..b5eee1a57d6c 100644
--- a/arch/mips/cavium-octeon/Kconfig
+++ b/arch/mips/cavium-octeon/Kconfig
@@ -75,6 +75,7 @@ config NEED_SG_DMA_LENGTH
 
 config SWIOTLB
def_bool y
+   select DMA_DIRECT_OPS
select IOMMU_HELPER
select NEED_SG_DMA_LENGTH
 
diff --git a/arch/mips/cavium-octeon/dma-octeon.c 
b/arch/mips/cavium-octeon/dma-octeon.c
index 5baf79fce643..c7bb8a407041 100644
--- a/arch/mips/cavium-octeon/dma-octeon.c
+++ b/arch/mips/cavium-octeon/dma-octeon.c
@@ -159,33 +159,13 @@ static void octeon_dma_sync_sg_for_device(struct device 
*dev,
 static void *octeon_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
 {
-   void *ret;
-
-   if (IS_ENABLED(CONFIG_ZONE_DMA) && dev == NULL)
-   gfp |= __GFP_DMA;
-   else if (IS_ENABLED(CONFIG_ZONE_DMA) &&
-dev->coherent_dma_mask <= DMA_BIT_MASK(24))
-   gfp |= __GFP_DMA;
-   else if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
-dev->coherent_dma_mask <= DMA_BIT_MASK(32))
-   gfp |= __GFP_DMA32;
-
-   /* Don't invoke OOM killer */
-   gfp |= __GFP_NORETRY;
-
-   ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
+   void *ret = swiotlb_alloc(dev, size, dma_handle, gfp, attrs);
 
mb();
 
return ret;
 }
 
-static void octeon_dma_free_coherent(struct device *dev, size_t size,
-   void *vaddr, dma_addr_t dma_handle, unsigned long attrs)
-{
-   swiotlb_free_coherent(dev, size, vaddr, dma_handle);
-}
-
 static dma_addr_t octeon_unity_phys_to_dma(struct device *dev, phys_addr_t 
paddr)
 {
return paddr;
@@ -225,7 +205,7 @@ EXPORT_SYMBOL(dma_to_phys);
 static struct octeon_dma_map_ops octeon_linear_dma_map_ops = {
.dma_map_ops = {
.alloc = octeon_dma_alloc_coherent,
-   .free = octeon_dma_free_coherent,
+   .free = swiotlb_free,
.map_page = octeon_dma_map_page,
.unmap_page = swiotlb_unmap_page,
.map_sg = octeon_dma_map_sg,
@@ -311,7 +291,7 @@ void __init plat_swiotlb_setup(void)
 static struct octeon_dma_map_ops _octeon_pci_dma_map_ops = {
.dma_map_ops = {
.alloc = octeon_dma_alloc_coherent,
-   .free = octeon_dma_free_coherent,
+   .free = swiotlb_free,
.map_page = octeon_dma_map_page,
.unmap_page = swiotlb_unmap_page,
.map_sg = octeon_dma_map_sg,
diff --git a/arch/mips/loongson64/Kconfig b/arch/mips/loongson64/Kconfig
index 0d249fc3cfe9..6f109bb54cdb 100644
--- a/arch/mips/loongson64/Kconfig
+++ b/arch/mips/loongson64/Kconfig
@@ -136,6 +136,7 @@ config SWIOTLB
bool "Soft IOMMU Support for All-Memory DMA"
default y
depends on CPU_LOONGSON3
+   select DMA_DIRECT_OPS
select IOMMU_HELPER
select NEED_SG_DMA_LENGTH
select NEED_DMA_MAP_STATE
diff --git a/arch/mips/loongson64/common/dma-swiotlb.c 
b/arch/mips/loongson64/common/dma-swiotlb.c
index 15388c24a504..7bbcf89475f3 100644
--- a/arch/mips/loongson64/common/dma-swiotlb.c
+++ b/arch/mips/loongson64/common/dma-swiotlb.c
@@ -13,29 +13,12 @@
 static void *loongson_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
 {
-   void *ret;
+   void *ret = swiotlb_alloc(dev, size, dma_handle, gfp, attrs);
 
-   if ((IS_ENABLED(CONFIG_ISA) && dev == NULL) ||
-   (IS_ENABLED(CONFIG_ZONE_DMA) &&
-dev->coherent_dma_mask < DMA_BIT_MASK(32)))
-   gfp |= __GFP_DMA;
-   else if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
-dev->coherent_dma_mask < DMA_BIT_MASK(40))
-   gfp |= __GFP_DMA32;
-
-   gfp |= __GFP_NORETRY;
-
-   ret = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
mb();
return ret;
 }
 
-static void loongson_dma_free_coherent(struct device *dev, size_t size,
-   void *vaddr, dma_addr_t dma_handle, unsigned long attrs)
-{
-   swiotlb_free_coherent(dev, size, vaddr, dma_handle);
-}
-
 static dma_addr_t loongson_dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size,
enum dma_data_direction dir,
@@ -106,7 +89,7 @@ phys_addr_t dma_to_phys(struct device 

[PATCH 19/22] mips/netlogic: remove swiotlb support

2018-01-10 Thread Christoph Hellwig
nlm_swiotlb_dma_ops is unused code, so the whole swiotlb support is dead.
If it gets resurrected at some point it should use the generic
swiotlb_dma_ops instead.

Signed-off-by: Christoph Hellwig 
---
 arch/mips/include/asm/netlogic/common.h |  3 --
 arch/mips/netlogic/Kconfig  |  5 --
 arch/mips/netlogic/common/Makefile  |  1 -
 arch/mips/netlogic/common/nlm-dma.c | 94 -
 4 files changed, 103 deletions(-)
 delete mode 100644 arch/mips/netlogic/common/nlm-dma.c

diff --git a/arch/mips/include/asm/netlogic/common.h 
b/arch/mips/include/asm/netlogic/common.h
index a6e6cbebe046..57616649b4f3 100644
--- a/arch/mips/include/asm/netlogic/common.h
+++ b/arch/mips/include/asm/netlogic/common.h
@@ -87,9 +87,6 @@ unsigned int nlm_get_cpu_frequency(void);
 extern const struct plat_smp_ops nlm_smp_ops;
 extern char nlm_reset_entry[], nlm_reset_entry_end[];
 
-/* SWIOTLB */
-extern const struct dma_map_ops nlm_swiotlb_dma_ops;
-
 extern unsigned int nlm_threads_per_core;
 extern cpumask_t nlm_cpumask;
 
diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig
index 8296b13affd2..7fcfc7fe9f14 100644
--- a/arch/mips/netlogic/Kconfig
+++ b/arch/mips/netlogic/Kconfig
@@ -89,9 +89,4 @@ config IOMMU_HELPER
 config NEED_SG_DMA_LENGTH
bool
 
-config SWIOTLB
-   def_bool y
-   select NEED_SG_DMA_LENGTH
-   select IOMMU_HELPER
-
 endif
diff --git a/arch/mips/netlogic/common/Makefile 
b/arch/mips/netlogic/common/Makefile
index 60d00b5d748e..89f6e3f39fed 100644
--- a/arch/mips/netlogic/common/Makefile
+++ b/arch/mips/netlogic/common/Makefile
@@ -1,6 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-y  += irq.o time.o
-obj-y  += nlm-dma.o
 obj-y  += reset.o
 obj-$(CONFIG_SMP)  += smp.o smpboot.o
 obj-$(CONFIG_EARLY_PRINTK) += earlycons.o
diff --git a/arch/mips/netlogic/common/nlm-dma.c 
b/arch/mips/netlogic/common/nlm-dma.c
deleted file mode 100644
index 49c975b6aa28..
--- a/arch/mips/netlogic/common/nlm-dma.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-*  Copyright (C) 2003-2013 Broadcom Corporation
-*  All Rights Reserved
- *
- * This software is available to you under a choice of one of two
- * licenses.  You may choose to be licensed under the terms of the GNU
- * General Public License (GPL) Version 2, available from the file
- * COPYING in the main directory of this source tree, or the Broadcom
- * license below:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *notice, this list of conditions and the following disclaimer in
- *the documentation and/or other materials provided with the
- *distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
- * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-static char *nlm_swiotlb;
-
-static void *nlm_dma_alloc_coherent(struct device *dev, size_t size,
-   dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
-{
-#ifdef CONFIG_ZONE_DMA32
-   if (dev->coherent_dma_mask <= DMA_BIT_MASK(32))
-   gfp |= __GFP_DMA32;
-#endif
-
-   /* Don't invoke OOM killer */
-   gfp |= __GFP_NORETRY;
-
-   return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
-}
-
-static void nlm_dma_free_coherent(struct device *dev, size_t size,
-   void *vaddr, dma_addr_t dma_handle, unsigned long attrs)
-{
-   swiotlb_free_coherent(dev, size, vaddr, dma_handle);
-}
-
-const struct dma_map_ops nlm_swiotlb_dma_ops = {
-   .alloc = nlm_dma_alloc_coherent,
-   .free = nlm_dma_free_coherent,
-   .map_page = swiotlb_map_page,
-   .unmap_page = swiotlb_unmap_page,
-   .map_sg = swiotlb_map_sg_attrs,
-   .unmap_sg = swiotlb_unmap_sg_attrs,
-   .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
-   .sync_single_for_device = swiotlb_sync_single_for_device,
-   

[PATCH 18/22] tile: use generic swiotlb_ops

2018-01-10 Thread Christoph Hellwig
These are identical to the tile ops, and would also support CMA
if enabled on tile.

Signed-off-by: Christoph Hellwig 
---
 arch/tile/Kconfig  |  1 +
 arch/tile/kernel/pci-dma.c | 36 +++-
 2 files changed, 4 insertions(+), 33 deletions(-)

diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 30c586686f29..ef9d403cbbe4 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -261,6 +261,7 @@ config NEED_SG_DMA_LENGTH
 config SWIOTLB
bool
default TILEGX
+   select DMA_DIRECT_OPS
select IOMMU_HELPER
select NEED_SG_DMA_LENGTH
select ARCH_HAS_DMA_SET_COHERENT_MASK
diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c
index a267fa740048..6a1efe5543fa 100644
--- a/arch/tile/kernel/pci-dma.c
+++ b/arch/tile/kernel/pci-dma.c
@@ -509,39 +509,9 @@ EXPORT_SYMBOL(gx_pci_dma_map_ops);
 /* PCI DMA mapping functions for legacy PCI devices */
 
 #ifdef CONFIG_SWIOTLB
-static void *tile_swiotlb_alloc_coherent(struct device *dev, size_t size,
-dma_addr_t *dma_handle, gfp_t gfp,
-unsigned long attrs)
-{
-   gfp |= GFP_DMA32;
-   return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
-}
-
-static void tile_swiotlb_free_coherent(struct device *dev, size_t size,
-  void *vaddr, dma_addr_t dma_addr,
-  unsigned long attrs)
-{
-   swiotlb_free_coherent(dev, size, vaddr, dma_addr);
-}
-
-static const struct dma_map_ops pci_swiotlb_dma_ops = {
-   .alloc = tile_swiotlb_alloc_coherent,
-   .free = tile_swiotlb_free_coherent,
-   .map_page = swiotlb_map_page,
-   .unmap_page = swiotlb_unmap_page,
-   .map_sg = swiotlb_map_sg_attrs,
-   .unmap_sg = swiotlb_unmap_sg_attrs,
-   .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
-   .sync_single_for_device = swiotlb_sync_single_for_device,
-   .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
-   .sync_sg_for_device = swiotlb_sync_sg_for_device,
-   .dma_supported = swiotlb_dma_supported,
-   .mapping_error = swiotlb_dma_mapping_error,
-};
-
 static const struct dma_map_ops pci_hybrid_dma_ops = {
-   .alloc = tile_swiotlb_alloc_coherent,
-   .free = tile_swiotlb_free_coherent,
+   .alloc = swiotlb_alloc,
+   .free = swiotlb_free,
.map_page = tile_pci_dma_map_page,
.unmap_page = tile_pci_dma_unmap_page,
.map_sg = tile_pci_dma_map_sg,
@@ -552,7 +522,7 @@ static const struct dma_map_ops pci_hybrid_dma_ops = {
.sync_sg_for_device = tile_pci_dma_sync_sg_for_device,
 };
 
-const struct dma_map_ops *gx_legacy_pci_dma_map_ops = _swiotlb_dma_ops;
+const struct dma_map_ops *gx_legacy_pci_dma_map_ops = _dma_ops;
 const struct dma_map_ops *gx_hybrid_pci_dma_map_ops = _hybrid_dma_ops;
 #else
 const struct dma_map_ops *gx_legacy_pci_dma_map_ops;
-- 
2.14.2



[PATCH 17/22] tile: replace ZONE_DMA with ZONE_DMA32

2018-01-10 Thread Christoph Hellwig
tile uses ZONE_DMA for allocations below 32-bits.  These days we
name the zone for that ZONE_DMA32, which will allow to use the
dma-direct and generic swiotlb code as-is, so rename it.

Signed-off-by: Christoph Hellwig 
---
 arch/tile/Kconfig  | 2 +-
 arch/tile/kernel/pci-dma.c | 4 ++--
 arch/tile/kernel/setup.c   | 8 
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/arch/tile/Kconfig b/arch/tile/Kconfig
index 02f269cfa538..30c586686f29 100644
--- a/arch/tile/Kconfig
+++ b/arch/tile/Kconfig
@@ -249,7 +249,7 @@ config HIGHMEM
 
  If unsure, say "true".
 
-config ZONE_DMA
+config ZONE_DMA32
def_bool y
 
 config IOMMU_HELPER
diff --git a/arch/tile/kernel/pci-dma.c b/arch/tile/kernel/pci-dma.c
index f2abedc8a080..a267fa740048 100644
--- a/arch/tile/kernel/pci-dma.c
+++ b/arch/tile/kernel/pci-dma.c
@@ -54,7 +54,7 @@ static void *tile_dma_alloc_coherent(struct device *dev, 
size_t size,
 * which case we will return NULL.  But such devices are uncommon.
 */
if (dma_mask <= DMA_BIT_MASK(32)) {
-   gfp |= GFP_DMA;
+   gfp |= GFP_DMA32;
node = 0;
}
 
@@ -513,7 +513,7 @@ static void *tile_swiotlb_alloc_coherent(struct device 
*dev, size_t size,
 dma_addr_t *dma_handle, gfp_t gfp,
 unsigned long attrs)
 {
-   gfp |= GFP_DMA;
+   gfp |= GFP_DMA32;
return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
 }
 
diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c
index ad83c1e66dbd..eb4e198f6f93 100644
--- a/arch/tile/kernel/setup.c
+++ b/arch/tile/kernel/setup.c
@@ -814,11 +814,11 @@ static void __init zone_sizes_init(void)
 #endif
 
if (start < dma_end) {
-   zones_size[ZONE_DMA] = min(zones_size[ZONE_NORMAL],
+   zones_size[ZONE_DMA32] = min(zones_size[ZONE_NORMAL],
   dma_end - start);
-   zones_size[ZONE_NORMAL] -= zones_size[ZONE_DMA];
+   zones_size[ZONE_NORMAL] -= zones_size[ZONE_DMA32];
} else {
-   zones_size[ZONE_DMA] = 0;
+   zones_size[ZONE_DMA32] = 0;
}
 
/* Take zone metadata from controller 0 if we're isolnode. */
@@ -830,7 +830,7 @@ static void __init zone_sizes_init(void)
   PFN_UP(node_percpu[i]));
 
/* Track the type of memory on each node */
-   if (zones_size[ZONE_NORMAL] || zones_size[ZONE_DMA])
+   if (zones_size[ZONE_NORMAL] || zones_size[ZONE_DMA32])
node_set_state(i, N_NORMAL_MEMORY);
 #ifdef CONFIG_HIGHMEM
if (end != start)
-- 
2.14.2



[PATCH 16/22] unicore32: use generic swiotlb_ops

2018-01-10 Thread Christoph Hellwig
These are identical to the unicore32 ops, and would also support CMA
if enabled on unicore32.

Signed-off-by: Christoph Hellwig 
---
 arch/unicore32/include/asm/dma-mapping.h |  9 +-
 arch/unicore32/mm/Kconfig|  1 +
 arch/unicore32/mm/Makefile   |  2 --
 arch/unicore32/mm/dma-swiotlb.c  | 48 
 4 files changed, 2 insertions(+), 58 deletions(-)
 delete mode 100644 arch/unicore32/mm/dma-swiotlb.c

diff --git a/arch/unicore32/include/asm/dma-mapping.h 
b/arch/unicore32/include/asm/dma-mapping.h
index f2bfec273aa7..790bc2ef4af2 100644
--- a/arch/unicore32/include/asm/dma-mapping.h
+++ b/arch/unicore32/include/asm/dma-mapping.h
@@ -12,18 +12,11 @@
 #ifndef __UNICORE_DMA_MAPPING_H__
 #define __UNICORE_DMA_MAPPING_H__
 
-#ifdef __KERNEL__
-
-#include 
-#include 
 #include 
 
-extern const struct dma_map_ops swiotlb_dma_map_ops;
-
 static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 {
-   return _dma_map_ops;
+   return _dma_ops;
 }
 
-#endif /* __KERNEL__ */
 #endif
diff --git a/arch/unicore32/mm/Kconfig b/arch/unicore32/mm/Kconfig
index c256460cd363..e9154a59d561 100644
--- a/arch/unicore32/mm/Kconfig
+++ b/arch/unicore32/mm/Kconfig
@@ -42,6 +42,7 @@ config CPU_TLB_SINGLE_ENTRY_DISABLE
 
 config SWIOTLB
def_bool y
+   select DMA_DIRECT_OPS
 
 config IOMMU_HELPER
def_bool SWIOTLB
diff --git a/arch/unicore32/mm/Makefile b/arch/unicore32/mm/Makefile
index 681c0ef5ec9e..8106260583ab 100644
--- a/arch/unicore32/mm/Makefile
+++ b/arch/unicore32/mm/Makefile
@@ -6,8 +6,6 @@
 obj-y  := extable.o fault.o init.o pgd.o mmu.o
 obj-y  += flush.o ioremap.o
 
-obj-$(CONFIG_SWIOTLB)  += dma-swiotlb.o
-
 obj-$(CONFIG_MODULES)  += proc-syms.o
 
 obj-$(CONFIG_ALIGNMENT_TRAP)   += alignment.o
diff --git a/arch/unicore32/mm/dma-swiotlb.c b/arch/unicore32/mm/dma-swiotlb.c
deleted file mode 100644
index 525413d6690e..
--- a/arch/unicore32/mm/dma-swiotlb.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Contains routines needed to support swiotlb for UniCore32.
- *
- * Copyright (C) 2010 Guan Xuetao
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- */
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-#include 
-
-static void *unicore_swiotlb_alloc_coherent(struct device *dev, size_t size,
-   dma_addr_t *dma_handle, gfp_t flags,
-   unsigned long attrs)
-{
-   return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
-}
-
-static void unicore_swiotlb_free_coherent(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_addr,
- unsigned long attrs)
-{
-   swiotlb_free_coherent(dev, size, vaddr, dma_addr);
-}
-
-const struct dma_map_ops swiotlb_dma_map_ops = {
-   .alloc = unicore_swiotlb_alloc_coherent,
-   .free = unicore_swiotlb_free_coherent,
-   .map_sg = swiotlb_map_sg_attrs,
-   .unmap_sg = swiotlb_unmap_sg_attrs,
-   .dma_supported = swiotlb_dma_supported,
-   .map_page = swiotlb_map_page,
-   .unmap_page = swiotlb_unmap_page,
-   .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
-   .sync_single_for_device = swiotlb_sync_single_for_device,
-   .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
-   .sync_sg_for_device = swiotlb_sync_sg_for_device,
-   .mapping_error = swiotlb_dma_mapping_error,
-};
-EXPORT_SYMBOL(swiotlb_dma_map_ops);
-- 
2.14.2



[PATCH 15/22] ia64: remove an ifdef around the content of pci-dma.c

2018-01-10 Thread Christoph Hellwig
The file is only compiled if CONFIG_INTEL_IOMMU is set to start with.

Signed-off-by: Christoph Hellwig 
---
 arch/ia64/kernel/pci-dma.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index 35e0cad33b7d..b5df084c0af4 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -12,12 +12,7 @@
 #include 
 #include 
 #include 
-
-
-#ifdef CONFIG_INTEL_IOMMU
-
 #include 
-
 #include 
 
 dma_addr_t bad_dma_address __read_mostly;
@@ -115,5 +110,3 @@ void __init pci_iommu_alloc(void)
}
 #endif /* CONFIG_SWIOTLB */
 }
-
-#endif
-- 
2.14.2



[PATCH 14/22] ia64: clean up swiotlb support

2018-01-10 Thread Christoph Hellwig
Move the few remaining bits of swiotlb glue towards their callers,
and remove the pointless on ia64 swiotlb variable.

Signed-off-by: Christoph Hellwig 
---
 arch/ia64/include/asm/dma-mapping.h |  1 -
 arch/ia64/include/asm/swiotlb.h | 18 --
 arch/ia64/kernel/dma-mapping.c  |  9 +
 arch/ia64/kernel/pci-dma.c  | 12 ++--
 arch/ia64/kernel/pci-swiotlb.c  | 36 
 drivers/iommu/intel-iommu.c |  2 +-
 6 files changed, 20 insertions(+), 58 deletions(-)
 delete mode 100644 arch/ia64/include/asm/swiotlb.h
 delete mode 100644 arch/ia64/kernel/pci-swiotlb.c

diff --git a/arch/ia64/include/asm/dma-mapping.h 
b/arch/ia64/include/asm/dma-mapping.h
index eabee56d995c..76e4d6632d68 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -8,7 +8,6 @@
  */
 #include 
 #include 
-#include 
 #include 
 
 #define ARCH_HAS_DMA_GET_REQUIRED_MASK
diff --git a/arch/ia64/include/asm/swiotlb.h b/arch/ia64/include/asm/swiotlb.h
deleted file mode 100644
index 841e2c7d0b21..
--- a/arch/ia64/include/asm/swiotlb.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef ASM_IA64__SWIOTLB_H
-#define ASM_IA64__SWIOTLB_H
-
-#include 
-#include 
-
-#ifdef CONFIG_SWIOTLB
-extern int swiotlb;
-extern void pci_swiotlb_init(void);
-#else
-#define swiotlb 0
-static inline void pci_swiotlb_init(void)
-{
-}
-#endif
-
-#endif /* ASM_IA64__SWIOTLB_H */
diff --git a/arch/ia64/kernel/dma-mapping.c b/arch/ia64/kernel/dma-mapping.c
index 7a82c9259609..f2d57e66fd86 100644
--- a/arch/ia64/kernel/dma-mapping.c
+++ b/arch/ia64/kernel/dma-mapping.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include 
+#include 
 #include 
 
 /* Set this to 1 if there is a HW IOMMU in the system */
@@ -23,3 +24,11 @@ const struct dma_map_ops *dma_get_ops(struct device *dev)
return dma_ops;
 }
 EXPORT_SYMBOL(dma_get_ops);
+
+#ifdef CONFIG_SWIOTLB
+void __init swiotlb_dma_init(void)
+{
+   dma_ops = _dma_ops;
+   swiotlb_init(1);
+}
+#endif
diff --git a/arch/ia64/kernel/pci-dma.c b/arch/ia64/kernel/pci-dma.c
index 3ba87c22dfbc..35e0cad33b7d 100644
--- a/arch/ia64/kernel/pci-dma.c
+++ b/arch/ia64/kernel/pci-dma.c
@@ -104,8 +104,16 @@ void __init pci_iommu_alloc(void)
detect_intel_iommu();
 
 #ifdef CONFIG_SWIOTLB
-   pci_swiotlb_init();
-#endif
+   if (!iommu_detected) {
+#ifdef CONFIG_IA64_GENERIC
+   printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n");
+   machvec_init("dig");
+   swiotlb_dma_init();
+#else
+   panic("Unable to find Intel IOMMU");
+#endif /* CONFIG_IA64_GENERIC */
+   }
+#endif /* CONFIG_SWIOTLB */
 }
 
 #endif
diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c
deleted file mode 100644
index 0f8d5fbd86bd..
--- a/arch/ia64/kernel/pci-swiotlb.c
+++ /dev/null
@@ -1,36 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Glue code to lib/swiotlb.c */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-int swiotlb __read_mostly;
-EXPORT_SYMBOL(swiotlb);
-
-void __init swiotlb_dma_init(void)
-{
-   dma_ops = _dma_ops;
-   swiotlb_init(1);
-}
-
-void __init pci_swiotlb_init(void)
-{
-   if (!iommu_detected) {
-#ifdef CONFIG_IA64_GENERIC
-   swiotlb = 1;
-   printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n");
-   machvec_init("dig");
-   swiotlb_init(1);
-   dma_ops = _dma_ops;
-#else
-   panic("Unable to find Intel IOMMU");
-#endif
-   }
-}
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 4a2de34895ec..a1373cf34326 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4808,7 +4808,7 @@ int __init intel_iommu_init(void)
up_write(_global_lock);
pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
 
-#ifdef CONFIG_SWIOTLB
+#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
swiotlb = 0;
 #endif
dma_ops = _dma_ops;
-- 
2.14.2



[PATCH 13/22] ia64: use generic swiotlb_ops

2018-01-10 Thread Christoph Hellwig
These are identical to the ia64 ops, and would also support CMA
if enabled on ia64.

Signed-off-by: Christoph Hellwig 
---
 arch/ia64/Kconfig|  5 +
 arch/ia64/hp/common/hwsw_iommu.c |  4 ++--
 arch/ia64/hp/common/sba_iommu.c  |  6 +++---
 arch/ia64/kernel/pci-swiotlb.c   | 38 +++---
 4 files changed, 13 insertions(+), 40 deletions(-)

diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 888acdb163cb..29148fe4bf5a 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -146,6 +146,7 @@ config IA64_GENERIC
bool "generic"
select NUMA
select ACPI_NUMA
+   select DMA_DIRECT_OPS
select SWIOTLB
select PCI_MSI
help
@@ -166,6 +167,7 @@ config IA64_GENERIC
 
 config IA64_DIG
bool "DIG-compliant"
+   select DMA_DIRECT_OPS
select SWIOTLB
 
 config IA64_DIG_VTD
@@ -181,6 +183,7 @@ config IA64_HP_ZX1
 
 config IA64_HP_ZX1_SWIOTLB
bool "HP-zx1/sx1000 with software I/O TLB"
+   select DMA_DIRECT_OPS
select SWIOTLB
help
  Build a kernel that runs on HP zx1 and sx1000 systems even when they
@@ -204,6 +207,7 @@ config IA64_SGI_UV
bool "SGI-UV"
select NUMA
select ACPI_NUMA
+   select DMA_DIRECT_OPS
select SWIOTLB
help
  Selecting this option will optimize the kernel for use on UV based
@@ -214,6 +218,7 @@ config IA64_SGI_UV
 
 config IA64_HP_SIM
bool "Ski-simulator"
+   select DMA_DIRECT_OPS
select SWIOTLB
depends on !PM
 
diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index 41279f0442bd..58969039bed2 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -19,7 +19,7 @@
 #include 
 #include 
 
-extern const struct dma_map_ops sba_dma_ops, ia64_swiotlb_dma_ops;
+extern const struct dma_map_ops sba_dma_ops;
 
 /* swiotlb declarations & definitions: */
 extern int swiotlb_late_init_with_default_size (size_t size);
@@ -38,7 +38,7 @@ static inline int use_swiotlb(struct device *dev)
 const struct dma_map_ops *hwsw_dma_get_ops(struct device *dev)
 {
if (use_swiotlb(dev))
-   return _swiotlb_dma_ops;
+   return _dma_ops;
return _dma_ops;
 }
 EXPORT_SYMBOL(hwsw_dma_get_ops);
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index 8c0a9ae6afec..aec4a3354abe 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -2096,7 +2096,7 @@ static int __init acpi_sba_ioc_init_acpi(void)
 /* This has to run before acpi_scan_init(). */
 arch_initcall(acpi_sba_ioc_init_acpi);
 
-extern const struct dma_map_ops ia64_swiotlb_dma_ops;
+extern const struct dma_map_ops swiotlb_dma_ops;
 
 static int __init
 sba_init(void)
@@ -2111,7 +2111,7 @@ sba_init(void)
 * a successful kdump kernel boot is to use the swiotlb.
 */
if (is_kdump_kernel()) {
-   dma_ops = _swiotlb_dma_ops;
+   dma_ops = _dma_ops;
if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
panic("Unable to initialize software I/O TLB:"
  " Try machvec=dig boot option");
@@ -2133,7 +2133,7 @@ sba_init(void)
 * If we didn't find something sba_iommu can claim, we
 * need to setup the swiotlb and switch to the dig machvec.
 */
-   dma_ops = _swiotlb_dma_ops;
+   dma_ops = _dma_ops;
if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
panic("Unable to find SBA IOMMU or initialize "
  "software I/O TLB: Try machvec=dig boot option");
diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c
index 4a9a6e58ad6a..0f8d5fbd86bd 100644
--- a/arch/ia64/kernel/pci-swiotlb.c
+++ b/arch/ia64/kernel/pci-swiotlb.c
@@ -6,8 +6,7 @@
 #include 
 #include 
 #include 
-
-#include 
+#include 
 #include 
 #include 
 #include 
@@ -15,40 +14,9 @@
 int swiotlb __read_mostly;
 EXPORT_SYMBOL(swiotlb);
 
-static void *ia64_swiotlb_alloc_coherent(struct device *dev, size_t size,
-dma_addr_t *dma_handle, gfp_t gfp,
-unsigned long attrs)
-{
-   if (dev->coherent_dma_mask != DMA_BIT_MASK(64))
-   gfp |= GFP_DMA32;
-   return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
-}
-
-static void ia64_swiotlb_free_coherent(struct device *dev, size_t size,
-  void *vaddr, dma_addr_t dma_addr,
-  unsigned long attrs)
-{
-   swiotlb_free_coherent(dev, size, vaddr, dma_addr);
-}
-
-const struct dma_map_ops ia64_swiotlb_dma_ops = {
-   .alloc = ia64_swiotlb_alloc_coherent,
-   .free = ia64_swiotlb_free_coherent,
-   .map_page = swiotlb_map_page,

[PATCH 12/22] ia64: replace ZONE_DMA with ZONE_DMA32

2018-01-10 Thread Christoph Hellwig
ia64 uses ZONE_DMA for allocations below 32-bits.  These days we
name the zone for that ZONE_DMA32, which will allow to use the
dma-direct and generic swiotlb code as-is, so rename it.

Signed-off-by: Christoph Hellwig 
---
 arch/ia64/Kconfig  | 2 +-
 arch/ia64/kernel/pci-swiotlb.c | 2 +-
 arch/ia64/mm/contig.c  | 4 ++--
 arch/ia64/mm/discontig.c   | 8 
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 4d18fca885ee..888acdb163cb 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -66,7 +66,7 @@ config 64BIT
select ATA_NONSTANDARD if ATA
default y
 
-config ZONE_DMA
+config ZONE_DMA32
def_bool y
depends on !IA64_SGI_SN2
 
diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c
index f1ae873a8c35..4a9a6e58ad6a 100644
--- a/arch/ia64/kernel/pci-swiotlb.c
+++ b/arch/ia64/kernel/pci-swiotlb.c
@@ -20,7 +20,7 @@ static void *ia64_swiotlb_alloc_coherent(struct device *dev, 
size_t size,
 unsigned long attrs)
 {
if (dev->coherent_dma_mask != DMA_BIT_MASK(64))
-   gfp |= GFP_DMA;
+   gfp |= GFP_DMA32;
return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
 }
 
diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c
index 52715a71aede..7d64b30913d1 100644
--- a/arch/ia64/mm/contig.c
+++ b/arch/ia64/mm/contig.c
@@ -237,9 +237,9 @@ paging_init (void)
unsigned long max_zone_pfns[MAX_NR_ZONES];
 
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ZONE_DMA32
max_dma = virt_to_phys((void *) MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-   max_zone_pfns[ZONE_DMA] = max_dma;
+   max_zone_pfns[ZONE_DMA32] = max_dma;
 #endif
max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c
index 9b2d994cddf6..ac46f0d60b66 100644
--- a/arch/ia64/mm/discontig.c
+++ b/arch/ia64/mm/discontig.c
@@ -38,7 +38,7 @@ struct early_node_data {
struct ia64_node_data *node_data;
unsigned long pernode_addr;
unsigned long pernode_size;
-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ZONE_DMA32
unsigned long num_dma_physpages;
 #endif
unsigned long min_pfn;
@@ -669,7 +669,7 @@ static __init int count_node_pages(unsigned long start, 
unsigned long len, int n
 {
unsigned long end = start + len;
 
-#ifdef CONFIG_ZONE_DMA
+#ifdef CONFIG_ZONE_DMA32
if (start <= __pa(MAX_DMA_ADDRESS))
mem_data[node].num_dma_physpages +=
(min(end, __pa(MAX_DMA_ADDRESS)) - start) >>PAGE_SHIFT;
@@ -724,8 +724,8 @@ void __init paging_init(void)
}
 
memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
-#ifdef CONFIG_ZONE_DMA
-   max_zone_pfns[ZONE_DMA] = max_dma;
+#ifdef CONFIG_ZONE_DMA32
+   max_zone_pfns[ZONE_DMA32] = max_dma;
 #endif
max_zone_pfns[ZONE_NORMAL] = max_pfn;
free_area_init_nodes(max_zone_pfns);
-- 
2.14.2



[PATCH 11/22] swiotlb: remove various exports

2018-01-10 Thread Christoph Hellwig
All these symbols are only used by arch dma_ops implementations or
xen-swiotlb.  None of which can be modular.

Signed-off-by: Christoph Hellwig 
---
 lib/swiotlb.c | 13 -
 1 file changed, 13 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index bf2d19ee91c1..1eac51ff77a4 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -605,7 +605,6 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
 
return tlb_addr;
 }
-EXPORT_SYMBOL_GPL(swiotlb_tbl_map_single);
 
 /*
  * Allocates bounce buffer and returns its kernel virtual address.
@@ -675,7 +674,6 @@ void swiotlb_tbl_unmap_single(struct device *hwdev, 
phys_addr_t tlb_addr,
}
spin_unlock_irqrestore(_tlb_lock, flags);
 }
-EXPORT_SYMBOL_GPL(swiotlb_tbl_unmap_single);
 
 void swiotlb_tbl_sync_single(struct device *hwdev, phys_addr_t tlb_addr,
 size_t size, enum dma_data_direction dir,
@@ -707,7 +705,6 @@ void swiotlb_tbl_sync_single(struct device *hwdev, 
phys_addr_t tlb_addr,
BUG();
}
 }
-EXPORT_SYMBOL_GPL(swiotlb_tbl_sync_single);
 
 static inline bool dma_coherent_ok(struct device *dev, dma_addr_t addr,
size_t size)
@@ -884,7 +881,6 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page 
*page,
 
return swiotlb_phys_to_dma(dev, io_tlb_overflow_buffer);
 }
-EXPORT_SYMBOL_GPL(swiotlb_map_page);
 
 /*
  * Unmap a single streaming mode DMA translation.  The dma_addr and size must
@@ -925,7 +921,6 @@ void swiotlb_unmap_page(struct device *hwdev, dma_addr_t 
dev_addr,
 {
unmap_single(hwdev, dev_addr, size, dir, attrs);
 }
-EXPORT_SYMBOL_GPL(swiotlb_unmap_page);
 
 /*
  * Make physical memory consistent for a single streaming mode DMA translation
@@ -963,7 +958,6 @@ swiotlb_sync_single_for_cpu(struct device *hwdev, 
dma_addr_t dev_addr,
 {
swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_CPU);
 }
-EXPORT_SYMBOL(swiotlb_sync_single_for_cpu);
 
 void
 swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
@@ -971,7 +965,6 @@ swiotlb_sync_single_for_device(struct device *hwdev, 
dma_addr_t dev_addr,
 {
swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_DEVICE);
 }
-EXPORT_SYMBOL(swiotlb_sync_single_for_device);
 
 /*
  * Map a set of buffers described by scatterlist in streaming mode for DMA.
@@ -1023,7 +1016,6 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct 
scatterlist *sgl, int nelems,
}
return nelems;
 }
-EXPORT_SYMBOL(swiotlb_map_sg_attrs);
 
 /*
  * Unmap a set of streaming mode DMA translations.  Again, cpu read rules
@@ -1043,7 +1035,6 @@ swiotlb_unmap_sg_attrs(struct device *hwdev, struct 
scatterlist *sgl,
unmap_single(hwdev, sg->dma_address, sg_dma_len(sg), dir,
 attrs);
 }
-EXPORT_SYMBOL(swiotlb_unmap_sg_attrs);
 
 /*
  * Make physical memory consistent for a set of streaming mode DMA translations
@@ -1071,7 +1062,6 @@ swiotlb_sync_sg_for_cpu(struct device *hwdev, struct 
scatterlist *sg,
 {
swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_CPU);
 }
-EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
 
 void
 swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
@@ -1079,14 +1069,12 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct 
scatterlist *sg,
 {
swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE);
 }
-EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
 
 int
 swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
 {
return (dma_addr == swiotlb_phys_to_dma(hwdev, io_tlb_overflow_buffer));
 }
-EXPORT_SYMBOL(swiotlb_dma_mapping_error);
 
 /*
  * Return whether the given device DMA address mask can be supported
@@ -1099,7 +1087,6 @@ swiotlb_dma_supported(struct device *hwdev, u64 mask)
 {
return swiotlb_phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
 }
-EXPORT_SYMBOL(swiotlb_dma_supported);
 
 #ifdef CONFIG_DMA_DIRECT_OPS
 void *swiotlb_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
-- 
2.14.2



[PATCH 10/22] swiotlb: refactor coherent buffer allocation

2018-01-10 Thread Christoph Hellwig
Factor out a new swiotlb_alloc_buffer helper that allocates DMA coherent
memory from the swiotlb bounce buffer.

This allows to simplify the swiotlb_alloc implemenation that uses
dma_direct_alloc to try to allocate a reachable buffer first.

Signed-off-by: Christoph Hellwig 
---
 lib/swiotlb.c | 122 +++---
 1 file changed, 65 insertions(+), 57 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 1a147f1354a1..bf2d19ee91c1 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -709,75 +709,79 @@ void swiotlb_tbl_sync_single(struct device *hwdev, 
phys_addr_t tlb_addr,
 }
 EXPORT_SYMBOL_GPL(swiotlb_tbl_sync_single);
 
-void *
-swiotlb_alloc_coherent(struct device *hwdev, size_t size,
-  dma_addr_t *dma_handle, gfp_t flags)
+static inline bool dma_coherent_ok(struct device *dev, dma_addr_t addr,
+   size_t size)
 {
-   bool warn = !(flags & __GFP_NOWARN);
-   dma_addr_t dev_addr;
-   void *ret;
-   int order = get_order(size);
-   u64 dma_mask = DMA_BIT_MASK(32);
+   u64 mask = DMA_BIT_MASK(32);
 
-   if (hwdev && hwdev->coherent_dma_mask)
-   dma_mask = hwdev->coherent_dma_mask;
+   if (dev && dev->coherent_dma_mask)
+   mask = dev->coherent_dma_mask;
+   return addr + size - 1 <= mask;
+}
 
-   ret = (void *)__get_free_pages(flags, order);
-   if (ret) {
-   dev_addr = swiotlb_virt_to_bus(hwdev, ret);
-   if (dev_addr + size - 1 > dma_mask) {
-   /*
-* The allocated memory isn't reachable by the device.
-*/
-   free_pages((unsigned long) ret, order);
-   ret = NULL;
-   }
-   }
-   if (!ret) {
-   /*
-* We are either out of memory or the device can't DMA to
-* GFP_DMA memory; fall back on map_single(), which
-* will grab memory from the lowest available address range.
-*/
-   phys_addr_t paddr = map_single(hwdev, 0, size, DMA_FROM_DEVICE,
-  warn ? 0 : DMA_ATTR_NO_WARN);
-   if (paddr == SWIOTLB_MAP_ERROR)
-   goto err_warn;
+static void *
+swiotlb_alloc_buffer(struct device *dev, size_t size, dma_addr_t *dma_handle,
+   unsigned long attrs)
+{
+   phys_addr_t phys_addr;
+
+   if (swiotlb_force == SWIOTLB_NO_FORCE)
+   goto out_warn;
 
-   ret = phys_to_virt(paddr);
-   dev_addr = swiotlb_phys_to_dma(hwdev, paddr);
+   phys_addr = swiotlb_tbl_map_single(dev,
+   swiotlb_phys_to_dma(dev, io_tlb_start),
+   0, size, DMA_FROM_DEVICE, 0);
+   if (phys_addr == SWIOTLB_MAP_ERROR)
+   goto out_warn;
 
-   /* Confirm address can be DMA'd by device */
-   if (dev_addr + size - 1 > dma_mask) {
-   printk("hwdev DMA mask = 0x%016Lx, dev_addr = 
0x%016Lx\n",
-  (unsigned long long)dma_mask,
-  (unsigned long long)dev_addr);
+   *dma_handle = swiotlb_phys_to_dma(dev, phys_addr);
 
-   /*
-* DMA_TO_DEVICE to avoid memcpy in unmap_single.
-* The DMA_ATTR_SKIP_CPU_SYNC is optional.
-*/
-   swiotlb_tbl_unmap_single(hwdev, paddr,
-size, DMA_TO_DEVICE,
-DMA_ATTR_SKIP_CPU_SYNC);
-   goto err_warn;
-   }
-   }
+   if (dma_coherent_ok(dev, *dma_handle, size))
+   goto out_unmap;
 
-   *dma_handle = dev_addr;
-   memset(ret, 0, size);
+   memset(phys_to_virt(phys_addr), 0, size);
+   return phys_to_virt(phys_addr);
 
-   return ret;
+out_unmap:
+   dev_warn(dev, "hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
+   (unsigned long long)(dev ? dev->coherent_dma_mask : 0),
+   (unsigned long long)*dma_handle);
 
-err_warn:
-   if (warn && printk_ratelimit()) {
-   pr_warn("swiotlb: coherent allocation failed for device %s 
size=%zu\n",
-   dev_name(hwdev), size);
+   /*
+* DMA_TO_DEVICE to avoid memcpy in unmap_single.
+* DMA_ATTR_SKIP_CPU_SYNC is optional.
+*/
+   swiotlb_tbl_unmap_single(dev, phys_addr, size, DMA_TO_DEVICE,
+   DMA_ATTR_SKIP_CPU_SYNC);
+out_warn:
+   if ((attrs & DMA_ATTR_NO_WARN) && printk_ratelimit()) {
+   dev_warn(dev,
+   "swiotlb: coherent allocation failed, size=%zu\n",
+   size);
dump_stack();
}
-
return NULL;
 }
+
+void *

[PATCH 09/22] swiotlb: refactor coherent buffer freeing

2018-01-10 Thread Christoph Hellwig
Factor out a new swiotlb_free_buffer helper that checks if an address
is allocated from the swiotlb bounce buffer, and if yes frees it.

This allows to simplify the swiotlb_free implemenation that uses
dma_direct_free to free the non-bounce buffer allocations.

Signed-off-by: Christoph Hellwig 
---
 lib/swiotlb.c | 35 +--
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 539fd1099ba9..1a147f1354a1 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -780,22 +780,31 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 }
 EXPORT_SYMBOL(swiotlb_alloc_coherent);
 
+static bool swiotlb_free_buffer(struct device *dev, size_t size,
+   dma_addr_t dma_addr)
+{
+   phys_addr_t phys_addr = dma_to_phys(dev, dma_addr);
+
+   WARN_ON_ONCE(irqs_disabled());
+
+   if (!is_swiotlb_buffer(phys_addr))
+   return false;
+
+   /*
+* DMA_TO_DEVICE to avoid memcpy in swiotlb_tbl_unmap_single.
+* DMA_ATTR_SKIP_CPU_SYNC is optional.
+*/
+   swiotlb_tbl_unmap_single(dev, phys_addr, size, DMA_TO_DEVICE,
+DMA_ATTR_SKIP_CPU_SYNC);
+   return true;
+}
+
 void
 swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
  dma_addr_t dev_addr)
 {
-   phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
-
-   WARN_ON(irqs_disabled());
-   if (!is_swiotlb_buffer(paddr))
+   if (!swiotlb_free_buffer(hwdev, size, dev_addr))
free_pages((unsigned long)vaddr, get_order(size));
-   else
-   /*
-* DMA_TO_DEVICE to avoid memcpy in swiotlb_tbl_unmap_single.
-* DMA_ATTR_SKIP_CPU_SYNC is optional.
-*/
-   swiotlb_tbl_unmap_single(hwdev, paddr, size, DMA_TO_DEVICE,
-DMA_ATTR_SKIP_CPU_SYNC);
 }
 EXPORT_SYMBOL(swiotlb_free_coherent);
 
@@ -1110,9 +1119,7 @@ void *swiotlb_alloc(struct device *dev, size_t size, 
dma_addr_t *dma_handle,
 void swiotlb_free(struct device *dev, size_t size, void *vaddr,
dma_addr_t dma_addr, unsigned long attrs)
 {
-   if (is_swiotlb_buffer(dma_to_phys(dev, dma_addr)))
-   swiotlb_free_coherent(dev, size, vaddr, dma_addr);
-   else
+   if (!swiotlb_free_buffer(dev, size, dma_addr))
dma_direct_free(dev, size, vaddr, dma_addr, attrs);
 }
 
-- 
2.14.2



[PATCH 08/22] swiotlb: wire up ->dma_supported in swiotlb_dma_ops

2018-01-10 Thread Christoph Hellwig
To properly reject too small DMA masks based on the addressability of the
bounce buffer.

Signed-off-by: Christoph Hellwig 
---
 lib/swiotlb.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 0fae2f45c3c0..539fd1099ba9 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -1128,5 +1128,6 @@ const struct dma_map_ops swiotlb_dma_ops = {
.unmap_sg   = swiotlb_unmap_sg_attrs,
.map_page   = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page,
+   .dma_supported  = swiotlb_dma_supported,
 };
 #endif /* CONFIG_DMA_DIRECT_OPS */
-- 
2.14.2



[PATCH 07/22] swiotlb: add common swiotlb_map_ops

2018-01-10 Thread Christoph Hellwig
Currently all architectures that want to use swiotlb have to implement
their own dma_map_ops instances.  Provide a generic one based on the
x86 implementation which first calls into dma_direct to try a full blown
direct mapping implementation (including e.g. CMA) before falling back
allocating from the swiotlb buffer.

Signed-off-by: Christoph Hellwig 
---
 include/linux/swiotlb.h |  8 
 lib/swiotlb.c   | 43 +++
 2 files changed, 51 insertions(+)

diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 606375e35d87..5b1f2a00491c 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -66,6 +66,12 @@ extern void swiotlb_tbl_sync_single(struct device *hwdev,
enum dma_sync_target target);
 
 /* Accessory functions. */
+
+void *swiotlb_alloc(struct device *hwdev, size_t size, dma_addr_t *dma_handle,
+   gfp_t flags, unsigned long attrs);
+void swiotlb_free(struct device *dev, size_t size, void *vaddr,
+   dma_addr_t dma_addr, unsigned long attrs);
+
 extern void
 *swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags);
@@ -126,4 +132,6 @@ extern void swiotlb_print_info(void);
 extern int is_swiotlb_buffer(phys_addr_t paddr);
 extern void swiotlb_set_max_segment(unsigned int);
 
+extern const struct dma_map_ops swiotlb_dma_ops;
+
 #endif /* __LINUX_SWIOTLB_H */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index cf5311908fa9..0fae2f45c3c0 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -1087,3 +1087,46 @@ swiotlb_dma_supported(struct device *hwdev, u64 mask)
return swiotlb_phys_to_dma(hwdev, io_tlb_end - 1) <= mask;
 }
 EXPORT_SYMBOL(swiotlb_dma_supported);
+
+#ifdef CONFIG_DMA_DIRECT_OPS
+void *swiotlb_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+   gfp_t gfp, unsigned long attrs)
+{
+   void *vaddr;
+
+   /*
+* Don't print a warning when the first allocation attempt fails.
+* swiotlb_alloc_coherent() will print a warning when the DMA memory
+* allocation ultimately failed.
+*/
+   gfp |= __GFP_NOWARN;
+
+   vaddr = dma_direct_alloc(dev, size, dma_handle, gfp, attrs);
+   if (!vaddr)
+   vaddr = swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
+   return vaddr;
+}
+
+void swiotlb_free(struct device *dev, size_t size, void *vaddr,
+   dma_addr_t dma_addr, unsigned long attrs)
+{
+   if (is_swiotlb_buffer(dma_to_phys(dev, dma_addr)))
+   swiotlb_free_coherent(dev, size, vaddr, dma_addr);
+   else
+   dma_direct_free(dev, size, vaddr, dma_addr, attrs);
+}
+
+const struct dma_map_ops swiotlb_dma_ops = {
+   .mapping_error  = swiotlb_dma_mapping_error,
+   .alloc  = swiotlb_alloc,
+   .free   = swiotlb_free,
+   .sync_single_for_cpu= swiotlb_sync_single_for_cpu,
+   .sync_single_for_device = swiotlb_sync_single_for_device,
+   .sync_sg_for_cpu= swiotlb_sync_sg_for_cpu,
+   .sync_sg_for_device = swiotlb_sync_sg_for_device,
+   .map_sg = swiotlb_map_sg_attrs,
+   .unmap_sg   = swiotlb_unmap_sg_attrs,
+   .map_page   = swiotlb_map_page,
+   .unmap_page = swiotlb_unmap_page,
+};
+#endif /* CONFIG_DMA_DIRECT_OPS */
-- 
2.14.2



[PATCH 06/22] swiotlb: rename swiotlb_free to swiotlb_exit

2018-01-10 Thread Christoph Hellwig
Signed-off-by: Christoph Hellwig 
---
 arch/powerpc/kernel/dma-swiotlb.c | 2 +-
 arch/x86/kernel/pci-swiotlb.c | 2 +-
 include/linux/swiotlb.h   | 4 ++--
 lib/swiotlb.c | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/kernel/dma-swiotlb.c 
b/arch/powerpc/kernel/dma-swiotlb.c
index 506ac4fafac5..88f3963ca30f 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -121,7 +121,7 @@ static int __init check_swiotlb_enabled(void)
if (ppc_swiotlb_enable)
swiotlb_print_info();
else
-   swiotlb_free();
+   swiotlb_exit();
 
return 0;
 }
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 0d77603c2f50..0ee0f8f34251 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -120,7 +120,7 @@ void __init pci_swiotlb_late_init(void)
 {
/* An IOMMU turned us off. */
if (!swiotlb)
-   swiotlb_free();
+   swiotlb_exit();
else {
printk(KERN_INFO "PCI-DMA: "
   "Using software bounce buffering for IO (SWIOTLB)\n");
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 24ed817082ee..606375e35d87 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -115,10 +115,10 @@ extern int
 swiotlb_dma_supported(struct device *hwdev, u64 mask);
 
 #ifdef CONFIG_SWIOTLB
-extern void __init swiotlb_free(void);
+extern void __init swiotlb_exit(void);
 unsigned int swiotlb_max_segment(void);
 #else
-static inline void swiotlb_free(void) { }
+static inline void swiotlb_exit(void) { }
 static inline unsigned int swiotlb_max_segment(void) { return 0; }
 #endif
 
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 125c1062119f..cf5311908fa9 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -417,7 +417,7 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
return -ENOMEM;
 }
 
-void __init swiotlb_free(void)
+void __init swiotlb_exit(void)
 {
if (!io_tlb_orig_addr)
return;
-- 
2.14.2



[PATCH 05/22] x86: rename swiotlb_dma_ops

2018-01-10 Thread Christoph Hellwig
We'll need that name for a generic implementation soon.

Signed-off-by: Christoph Hellwig 
---
 arch/x86/kernel/pci-swiotlb.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 9d3e35c33d94..0d77603c2f50 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -48,7 +48,7 @@ void x86_swiotlb_free_coherent(struct device *dev, size_t 
size,
dma_generic_free_coherent(dev, size, vaddr, dma_addr, attrs);
 }
 
-static const struct dma_map_ops swiotlb_dma_ops = {
+static const struct dma_map_ops x86_swiotlb_dma_ops = {
.mapping_error = swiotlb_dma_mapping_error,
.alloc = x86_swiotlb_alloc_coherent,
.free = x86_swiotlb_free_coherent,
@@ -112,7 +112,7 @@ void __init pci_swiotlb_init(void)
 {
if (swiotlb) {
swiotlb_init(0);
-   dma_ops = _dma_ops;
+   dma_ops = _swiotlb_dma_ops;
}
 }
 
-- 
2.14.2



[PATCH 04/22] powerpc: rename swiotlb_dma_ops

2018-01-10 Thread Christoph Hellwig
We'll need that name for a generic implementation soon.

Signed-off-by: Christoph Hellwig 
---
 arch/powerpc/include/asm/swiotlb.h | 2 +-
 arch/powerpc/kernel/dma-swiotlb.c  | 4 ++--
 arch/powerpc/kernel/dma.c  | 2 +-
 arch/powerpc/sysdev/fsl_pci.c  | 2 +-
 4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/include/asm/swiotlb.h 
b/arch/powerpc/include/asm/swiotlb.h
index 9341ee804d19..f65ecf57b66c 100644
--- a/arch/powerpc/include/asm/swiotlb.h
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -13,7 +13,7 @@
 
 #include 
 
-extern const struct dma_map_ops swiotlb_dma_ops;
+extern const struct dma_map_ops powerpc_swiotlb_dma_ops;
 
 extern unsigned int ppc_swiotlb_enable;
 int __init swiotlb_setup_bus_notifier(void);
diff --git a/arch/powerpc/kernel/dma-swiotlb.c 
b/arch/powerpc/kernel/dma-swiotlb.c
index f1e99b9cee97..506ac4fafac5 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -46,7 +46,7 @@ static u64 swiotlb_powerpc_get_required(struct device *dev)
  * map_page, and unmap_page on highmem, use normal dma_ops
  * for everything else.
  */
-const struct dma_map_ops swiotlb_dma_ops = {
+const struct dma_map_ops powerpc_swiotlb_dma_ops = {
.alloc = __dma_nommu_alloc_coherent,
.free = __dma_nommu_free_coherent,
.mmap = dma_nommu_mmap_coherent,
@@ -89,7 +89,7 @@ static int ppc_swiotlb_bus_notify(struct notifier_block *nb,
 
/* May need to bounce if the device can't address all of DRAM */
if ((dma_get_mask(dev) + 1) < memblock_end_of_DRAM())
-   set_dma_ops(dev, _dma_ops);
+   set_dma_ops(dev, _swiotlb_dma_ops);
 
return NOTIFY_DONE;
 }
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 76079841d3d0..da20569de9d4 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -33,7 +33,7 @@ static u64 __maybe_unused get_pfn_limit(struct device *dev)
struct dev_archdata __maybe_unused *sd = >archdata;
 
 #ifdef CONFIG_SWIOTLB
-   if (sd->max_direct_dma_addr && dev->dma_ops == _dma_ops)
+   if (sd->max_direct_dma_addr && dev->dma_ops == _swiotlb_dma_ops)
pfn = min_t(u64, pfn, sd->max_direct_dma_addr >> PAGE_SHIFT);
 #endif
 
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index e4d0133bbeeb..61e07c78d64f 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -118,7 +118,7 @@ static void setup_swiotlb_ops(struct pci_controller *hose)
 {
if (ppc_swiotlb_enable) {
hose->controller_ops.dma_dev_setup = pci_dma_dev_setup_swiotlb;
-   set_pci_dma_ops(_dma_ops);
+   set_pci_dma_ops(_swiotlb_dma_ops);
}
 }
 #else
-- 
2.14.2



[PATCH 03/22] ia64: rename swiotlb_dma_ops

2018-01-10 Thread Christoph Hellwig
We'll need that name for a generic implementation soon.

Signed-off-by: Christoph Hellwig 
---
 arch/ia64/hp/common/hwsw_iommu.c | 4 ++--
 arch/ia64/hp/common/sba_iommu.c  | 6 +++---
 arch/ia64/kernel/pci-swiotlb.c   | 6 +++---
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c
index 63d8e1d2477f..41279f0442bd 100644
--- a/arch/ia64/hp/common/hwsw_iommu.c
+++ b/arch/ia64/hp/common/hwsw_iommu.c
@@ -19,7 +19,7 @@
 #include 
 #include 
 
-extern const struct dma_map_ops sba_dma_ops, swiotlb_dma_ops;
+extern const struct dma_map_ops sba_dma_ops, ia64_swiotlb_dma_ops;
 
 /* swiotlb declarations & definitions: */
 extern int swiotlb_late_init_with_default_size (size_t size);
@@ -38,7 +38,7 @@ static inline int use_swiotlb(struct device *dev)
 const struct dma_map_ops *hwsw_dma_get_ops(struct device *dev)
 {
if (use_swiotlb(dev))
-   return _dma_ops;
+   return _swiotlb_dma_ops;
return _dma_ops;
 }
 EXPORT_SYMBOL(hwsw_dma_get_ops);
diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c
index aec4a3354abe..8c0a9ae6afec 100644
--- a/arch/ia64/hp/common/sba_iommu.c
+++ b/arch/ia64/hp/common/sba_iommu.c
@@ -2096,7 +2096,7 @@ static int __init acpi_sba_ioc_init_acpi(void)
 /* This has to run before acpi_scan_init(). */
 arch_initcall(acpi_sba_ioc_init_acpi);
 
-extern const struct dma_map_ops swiotlb_dma_ops;
+extern const struct dma_map_ops ia64_swiotlb_dma_ops;
 
 static int __init
 sba_init(void)
@@ -2111,7 +2111,7 @@ sba_init(void)
 * a successful kdump kernel boot is to use the swiotlb.
 */
if (is_kdump_kernel()) {
-   dma_ops = _dma_ops;
+   dma_ops = _swiotlb_dma_ops;
if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
panic("Unable to initialize software I/O TLB:"
  " Try machvec=dig boot option");
@@ -2133,7 +2133,7 @@ sba_init(void)
 * If we didn't find something sba_iommu can claim, we
 * need to setup the swiotlb and switch to the dig machvec.
 */
-   dma_ops = _dma_ops;
+   dma_ops = _swiotlb_dma_ops;
if (swiotlb_late_init_with_default_size(64 * (1<<20)) != 0)
panic("Unable to find SBA IOMMU or initialize "
  "software I/O TLB: Try machvec=dig boot option");
diff --git a/arch/ia64/kernel/pci-swiotlb.c b/arch/ia64/kernel/pci-swiotlb.c
index 5e50939aa03e..f1ae873a8c35 100644
--- a/arch/ia64/kernel/pci-swiotlb.c
+++ b/arch/ia64/kernel/pci-swiotlb.c
@@ -31,7 +31,7 @@ static void ia64_swiotlb_free_coherent(struct device *dev, 
size_t size,
swiotlb_free_coherent(dev, size, vaddr, dma_addr);
 }
 
-const struct dma_map_ops swiotlb_dma_ops = {
+const struct dma_map_ops ia64_swiotlb_dma_ops = {
.alloc = ia64_swiotlb_alloc_coherent,
.free = ia64_swiotlb_free_coherent,
.map_page = swiotlb_map_page,
@@ -48,7 +48,7 @@ const struct dma_map_ops swiotlb_dma_ops = {
 
 void __init swiotlb_dma_init(void)
 {
-   dma_ops = _dma_ops;
+   dma_ops = _swiotlb_dma_ops;
swiotlb_init(1);
 }
 
@@ -60,7 +60,7 @@ void __init pci_swiotlb_init(void)
printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n");
machvec_init("dig");
swiotlb_init(1);
-   dma_ops = _dma_ops;
+   dma_ops = _swiotlb_dma_ops;
 #else
panic("Unable to find Intel IOMMU");
 #endif
-- 
2.14.2



[PATCH 02/22] arm64: rename swiotlb_dma_ops

2018-01-10 Thread Christoph Hellwig
We'll need that name for a generic implementation soon.

Signed-off-by: Christoph Hellwig 
---
 arch/arm64/mm/dma-mapping.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index f3a637b98487..6840426bbe77 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -368,7 +368,7 @@ static int __swiotlb_dma_mapping_error(struct device 
*hwdev, dma_addr_t addr)
return 0;
 }
 
-static const struct dma_map_ops swiotlb_dma_ops = {
+static const struct dma_map_ops arm64_swiotlb_dma_ops = {
.alloc = __dma_alloc,
.free = __dma_free,
.mmap = __swiotlb_mmap,
@@ -923,7 +923,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, 
u64 size,
const struct iommu_ops *iommu, bool coherent)
 {
if (!dev->dma_ops)
-   dev->dma_ops = _dma_ops;
+   dev->dma_ops = _swiotlb_dma_ops;
 
dev->archdata.dma_coherent = coherent;
__iommu_setup_dma_ops(dev, dma_base, size, iommu);
-- 
2.14.2



[PATCH 01/22] swiotlb: suppress warning when __GFP_NOWARN is set

2018-01-10 Thread Christoph Hellwig
From: Christian König 

TTM tries to allocate coherent memory in chunks of 2MB first to improve
TLB efficiency and falls back to allocating 4K pages if that fails.

Suppress the warning when the 2MB allocations fails since there is a
valid fall back path.

Signed-off-by: Christian König 
Reported-by: Mike Galbraith 
Acked-by: Konrad Rzeszutek Wilk 
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=104082
CC: sta...@vger.kernel.org
Signed-off-by: Christoph Hellwig 
---
 lib/swiotlb.c | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 6583f3512386..125c1062119f 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -586,7 +586,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
 
 not_found:
spin_unlock_irqrestore(_tlb_lock, flags);
-   if (printk_ratelimit())
+   if (!(attrs & DMA_ATTR_NO_WARN) && printk_ratelimit())
dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes)\n", 
size);
return SWIOTLB_MAP_ERROR;
 found:
@@ -713,6 +713,7 @@ void *
 swiotlb_alloc_coherent(struct device *hwdev, size_t size,
   dma_addr_t *dma_handle, gfp_t flags)
 {
+   bool warn = !(flags & __GFP_NOWARN);
dma_addr_t dev_addr;
void *ret;
int order = get_order(size);
@@ -738,8 +739,8 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
 * GFP_DMA memory; fall back on map_single(), which
 * will grab memory from the lowest available address range.
 */
-   phys_addr_t paddr = map_single(hwdev, 0, size,
-  DMA_FROM_DEVICE, 0);
+   phys_addr_t paddr = map_single(hwdev, 0, size, DMA_FROM_DEVICE,
+  warn ? 0 : DMA_ATTR_NO_WARN);
if (paddr == SWIOTLB_MAP_ERROR)
goto err_warn;
 
@@ -769,9 +770,11 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
return ret;
 
 err_warn:
-   pr_warn("swiotlb: coherent allocation failed for device %s size=%zu\n",
-   dev_name(hwdev), size);
-   dump_stack();
+   if (warn && printk_ratelimit()) {
+   pr_warn("swiotlb: coherent allocation failed for device %s 
size=%zu\n",
+   dev_name(hwdev), size);
+   dump_stack();
+   }
 
return NULL;
 }
-- 
2.14.2



consolidate swiotlb dma_map implementations

2018-01-10 Thread Christoph Hellwig
A lot of architectures have essentially identical dma_map_ops
implementations to use swiotlb.  This series adds new generic
swiotlb_alloc/free helpers that take the attrs argument exposed
in dma_map_ops, and which do an enhanced direct allocation
modelled after x86 and reused from the dma-direct code, and
then switches most architectures over to it.  The only exceptions
are mips, which requires additional cache flushing which will
need a new abstraction, and x86 itself which will be handled in
a later series with other x86 dma mapping changes.

To support the generic code a few architectures that currently
use ZONE_DMA/GFP_DMA for <= 32-bit allocations are switched to
implement ZONE_DMA32 instead.

This series is based on the previously sent series to consolidate
the direct dma mapping implementation.  A git tree with this
series as well as the prerequisites is available here:

   git://git.infradead.org/users/hch/misc.git swiotlb

Gitweb:

   http://git.infradead.org/users/hch/misc.git/shortlog/refs/heads/swiotlb


[PATCH 33/33] h8300: use dma-direct

2018-01-10 Thread Christoph Hellwig
Replace the bare-bones h8300 direct dma mapping implementation with
the fully featured generic dma-direct one.

Signed-off-by: Christoph Hellwig 
---
 arch/h8300/Kconfig   |  1 +
 arch/h8300/include/asm/Kbuild|  1 +
 arch/h8300/include/asm/dma-mapping.h | 12 ---
 arch/h8300/kernel/Makefile   |  2 +-
 arch/h8300/kernel/dma.c  | 66 
 5 files changed, 3 insertions(+), 79 deletions(-)
 delete mode 100644 arch/h8300/include/asm/dma-mapping.h
 delete mode 100644 arch/h8300/kernel/dma.c

diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig
index f8d3fde08190..091d6d04b5e5 100644
--- a/arch/h8300/Kconfig
+++ b/arch/h8300/Kconfig
@@ -23,6 +23,7 @@ config H8300
select HAVE_ARCH_KGDB
select HAVE_ARCH_HASH
select CPU_NO_EFFICIENT_FFS
+   select DMA_DIRECT_OPS
 
 config CPU_BIG_ENDIAN
def_bool y
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild
index bc077491d299..642752c94306 100644
--- a/arch/h8300/include/asm/Kbuild
+++ b/arch/h8300/include/asm/Kbuild
@@ -9,6 +9,7 @@ generic-y += delay.h
 generic-y += device.h
 generic-y += div64.h
 generic-y += dma.h
+generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += exec.h
 generic-y += extable.h
diff --git a/arch/h8300/include/asm/dma-mapping.h 
b/arch/h8300/include/asm/dma-mapping.h
deleted file mode 100644
index 21bb1fc3a6f1..
--- a/arch/h8300/include/asm/dma-mapping.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _H8300_DMA_MAPPING_H
-#define _H8300_DMA_MAPPING_H
-
-extern const struct dma_map_ops h8300_dma_map_ops;
-
-static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
-{
-   return _dma_map_ops;
-}
-
-#endif
diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile
index b62e830525c6..307aa51576dd 100644
--- a/arch/h8300/kernel/Makefile
+++ b/arch/h8300/kernel/Makefile
@@ -7,7 +7,7 @@ extra-y := vmlinux.lds
 
 obj-y := process.o traps.o ptrace.o \
 signal.o setup.o syscalls.o \
-irq.o entry.o dma.o
+irq.o entry.o
 
 obj-$(CONFIG_ROMKERNEL) += head_rom.o
 obj-$(CONFIG_RAMKERNEL) += head_ram.o
diff --git a/arch/h8300/kernel/dma.c b/arch/h8300/kernel/dma.c
deleted file mode 100644
index d44ba5db4ac3..
--- a/arch/h8300/kernel/dma.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-
-static void *dma_alloc(struct device *dev, size_t size,
-  dma_addr_t *dma_handle, gfp_t gfp,
-  unsigned long attrs)
-{
-   void *ret;
-
-   if (dev == NULL || (*dev->dma_mask < 0x))
-   gfp |= GFP_DMA;
-   ret = (void *)__get_free_pages(gfp, get_order(size));
-
-   if (ret != NULL) {
-   memset(ret, 0, size);
-   *dma_handle = virt_to_phys(ret);
-   }
-   return ret;
-}
-
-static void dma_free(struct device *dev, size_t size,
-void *vaddr, dma_addr_t dma_handle,
-unsigned long attrs)
-
-{
-   free_pages((unsigned long)vaddr, get_order(size));
-}
-
-static dma_addr_t map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction,
- unsigned long attrs)
-{
-   return page_to_phys(page) + offset;
-}
-
-static int map_sg(struct device *dev, struct scatterlist *sgl,
- int nents, enum dma_data_direction direction,
- unsigned long attrs)
-{
-   struct scatterlist *sg;
-   int i;
-
-   for_each_sg(sgl, sg, nents, i) {
-   sg->dma_address = sg_phys(sg);
-   }
-
-   return nents;
-}
-
-const struct dma_map_ops h8300_dma_map_ops = {
-   .alloc = dma_alloc,
-   .free = dma_free,
-   .map_page = map_page,
-   .map_sg = map_sg,
-};
-EXPORT_SYMBOL(h8300_dma_map_ops);
-- 
2.14.2



[PATCH 32/33] cris: use dma-direct

2018-01-10 Thread Christoph Hellwig
cris currently has an incomplete direct mapping dma_map_ops implementation
is PCI support is enabled.  Replace it with the fully feature generic
dma-direct implementation.

Signed-off-by: Christoph Hellwig 
Acked-by: Jesper Nilsson 
---
 arch/cris/Kconfig   |  4 ++
 arch/cris/arch-v32/drivers/pci/Makefile |  2 +-
 arch/cris/arch-v32/drivers/pci/dma.c| 77 -
 arch/cris/include/asm/Kbuild|  1 +
 arch/cris/include/asm/dma-mapping.h | 20 -
 5 files changed, 6 insertions(+), 98 deletions(-)
 delete mode 100644 arch/cris/arch-v32/drivers/pci/dma.c
 delete mode 100644 arch/cris/include/asm/dma-mapping.h

diff --git a/arch/cris/Kconfig b/arch/cris/Kconfig
index 54d3f426763b..cd5a0865c97f 100644
--- a/arch/cris/Kconfig
+++ b/arch/cris/Kconfig
@@ -33,6 +33,9 @@ config GENERIC_CALIBRATE_DELAY
 config NO_IOPORT_MAP
def_bool y if !PCI
 
+config NO_DMA
+   def_bool y if !PCI
+
 config FORCE_MAX_ZONEORDER
int
default 6
@@ -72,6 +75,7 @@ config CRIS
select GENERIC_SCHED_CLOCK if ETRAX_ARCH_V32
select HAVE_DEBUG_BUGVERBOSE if ETRAX_ARCH_V32
select HAVE_NMI
+   select DMA_DIRECT_OPS if PCI
 
 config HZ
int
diff --git a/arch/cris/arch-v32/drivers/pci/Makefile 
b/arch/cris/arch-v32/drivers/pci/Makefile
index bff7482f2444..93c8be6170b1 100644
--- a/arch/cris/arch-v32/drivers/pci/Makefile
+++ b/arch/cris/arch-v32/drivers/pci/Makefile
@@ -2,4 +2,4 @@
 # Makefile for Etrax cardbus driver
 #
 
-obj-$(CONFIG_ETRAX_CARDBUS)+= bios.o dma.o
+obj-$(CONFIG_ETRAX_CARDBUS)+= bios.o
diff --git a/arch/cris/arch-v32/drivers/pci/dma.c 
b/arch/cris/arch-v32/drivers/pci/dma.c
deleted file mode 100644
index 8c3802244ef3..
--- a/arch/cris/arch-v32/drivers/pci/dma.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Dynamic DMA mapping support.
- *
- * On cris there is no hardware dynamic DMA address translation,
- * so consistent alloc/free are merely page allocation/freeing.
- * The rest of the dynamic DMA mapping interface is implemented
- * in asm/pci.h.
- *
- * Borrowed from i386.
- */
-
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-
-static void *v32_dma_alloc(struct device *dev, size_t size,
-   dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
-{
-   void *ret;
-
-   if (dev == NULL || (dev->coherent_dma_mask < 0x))
-   gfp |= GFP_DMA;
-
-   ret = (void *)__get_free_pages(gfp,  get_order(size));
-
-   if (ret != NULL) {
-   memset(ret, 0, size);
-   *dma_handle = virt_to_phys(ret);
-   }
-   return ret;
-}
-
-static void v32_dma_free(struct device *dev, size_t size, void *vaddr,
-   dma_addr_t dma_handle, unsigned long attrs)
-{
-   free_pages((unsigned long)vaddr, get_order(size));
-}
-
-static inline dma_addr_t v32_dma_map_page(struct device *dev,
-   struct page *page, unsigned long offset, size_t size,
-   enum dma_data_direction direction, unsigned long attrs)
-{
-   return page_to_phys(page) + offset;
-}
-
-static inline int v32_dma_map_sg(struct device *dev, struct scatterlist *sg,
-   int nents, enum dma_data_direction direction,
-   unsigned long attrs)
-{
-   printk("Map sg\n");
-   return nents;
-}
-
-static inline int v32_dma_supported(struct device *dev, u64 mask)
-{
-/*
- * we fall back to GFP_DMA when the mask isn't all 1s,
- * so we can't guarantee allocations that must be
- * within a tighter range than GFP_DMA..
- */
-if (mask < 0x00ff)
-return 0;
-   return 1;
-}
-
-const struct dma_map_ops v32_dma_ops = {
-   .alloc  = v32_dma_alloc,
-   .free   = v32_dma_free,
-   .map_page   = v32_dma_map_page,
-   .map_sg = v32_dma_map_sg,
-   .dma_supported  = v32_dma_supported,
-};
-EXPORT_SYMBOL(v32_dma_ops);
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild
index 460349cb147f..8cf45ac30c1b 100644
--- a/arch/cris/include/asm/Kbuild
+++ b/arch/cris/include/asm/Kbuild
@@ -5,6 +5,7 @@ generic-y += cmpxchg.h
 generic-y += current.h
 generic-y += device.h
 generic-y += div64.h
+generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += exec.h
 generic-y += extable.h
diff --git a/arch/cris/include/asm/dma-mapping.h 
b/arch/cris/include/asm/dma-mapping.h
deleted file mode 100644
index 1553bdb30a0c..
--- a/arch/cris/include/asm/dma-mapping.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_CRIS_DMA_MAPPING_H
-#define _ASM_CRIS_DMA_MAPPING_H
-
-#ifdef CONFIG_PCI
-extern const struct dma_map_ops v32_dma_ops;
-
-static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)

[PATCH 31/33] dma-direct: reject too small dma masks

2018-01-10 Thread Christoph Hellwig
Signed-off-by: Christoph Hellwig 
---
 include/linux/dma-direct.h |  1 +
 lib/dma-direct.c   | 19 +++
 2 files changed, 20 insertions(+)

diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index 4788bf0bf683..bcdb1a3e4b1f 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -42,5 +42,6 @@ void *dma_direct_alloc(struct device *dev, size_t size, 
dma_addr_t *dma_handle,
gfp_t gfp, unsigned long attrs);
 void dma_direct_free(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_addr, unsigned long attrs);
+int dma_direct_supported(struct device *dev, u64 mask);
 
 #endif /* _LINUX_DMA_DIRECT_H */
diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index 784a68dfdbe3..40b1f92f2214 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -122,6 +122,24 @@ static int dma_direct_map_sg(struct device *dev, struct 
scatterlist *sgl,
return nents;
 }
 
+int dma_direct_supported(struct device *dev, u64 mask)
+{
+#ifdef CONFIG_ZONE_DMA
+   if (mask < DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
+   return 0;
+#else
+   /*
+* Because 32-bit DMA masks are so common we expect every architecture
+* to be able to satisfy them - either by not supporting more physical
+* memory, or by providing a ZONE_DMA32.  If neither is the case, the
+* architecture needs to use an IOMMU instead of the direct mapping.
+*/
+   if (mask < DMA_BIT_MASK(32))
+   return 0;
+#endif
+   return 1;
+}
+
 static int dma_direct_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
return dma_addr == DIRECT_MAPPING_ERROR;
@@ -132,6 +150,7 @@ const struct dma_map_ops dma_direct_ops = {
.free   = dma_direct_free,
.map_page   = dma_direct_map_page,
.map_sg = dma_direct_map_sg,
+   .dma_supported  = dma_direct_supported,
.mapping_error  = dma_direct_mapping_error,
 };
 EXPORT_SYMBOL(dma_direct_ops);
-- 
2.14.2



[PATCH 30/33] dma-direct: make dma_direct_{alloc, free} available to other implementations

2018-01-10 Thread Christoph Hellwig
So that they don't need to indirect through the operation vector.

Signed-off-by: Christoph Hellwig 
Reviewed-by: Vladimir Murzin 
---
 arch/arm/mm/dma-mapping-nommu.c | 9 +++--
 include/linux/dma-direct.h  | 5 +
 lib/dma-direct.c| 6 +++---
 3 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mm/dma-mapping-nommu.c b/arch/arm/mm/dma-mapping-nommu.c
index 4d8042521e89..619f24a42d09 100644
--- a/arch/arm/mm/dma-mapping-nommu.c
+++ b/arch/arm/mm/dma-mapping-nommu.c
@@ -11,7 +11,7 @@
 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 #include 
@@ -39,7 +39,6 @@ static void *arm_nommu_dma_alloc(struct device *dev, size_t 
size,
 unsigned long attrs)
 
 {
-   const struct dma_map_ops *ops = _direct_ops;
void *ret;
 
/*
@@ -48,7 +47,7 @@ static void *arm_nommu_dma_alloc(struct device *dev, size_t 
size,
 */
 
if (attrs & DMA_ATTR_NON_CONSISTENT)
-   return ops->alloc(dev, size, dma_handle, gfp, attrs);
+   return dma_direct_alloc(dev, size, dma_handle, gfp, attrs);
 
ret = dma_alloc_from_global_coherent(size, dma_handle);
 
@@ -70,10 +69,8 @@ static void arm_nommu_dma_free(struct device *dev, size_t 
size,
   void *cpu_addr, dma_addr_t dma_addr,
   unsigned long attrs)
 {
-   const struct dma_map_ops *ops = _direct_ops;
-
if (attrs & DMA_ATTR_NON_CONSISTENT) {
-   ops->free(dev, size, cpu_addr, dma_addr, attrs);
+   dma_direct_free(dev, size, cpu_addr, dma_addr, attrs);
} else {
int ret = dma_release_from_global_coherent(get_order(size),
   cpu_addr);
diff --git a/include/linux/dma-direct.h b/include/linux/dma-direct.h
index 10e924b7cba7..4788bf0bf683 100644
--- a/include/linux/dma-direct.h
+++ b/include/linux/dma-direct.h
@@ -38,4 +38,9 @@ static inline void dma_mark_clean(void *addr, size_t size)
 }
 #endif /* CONFIG_ARCH_HAS_DMA_MARK_CLEAN */
 
+void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+   gfp_t gfp, unsigned long attrs);
+void dma_direct_free(struct device *dev, size_t size, void *cpu_addr,
+   dma_addr_t dma_addr, unsigned long attrs);
+
 #endif /* _LINUX_DMA_DIRECT_H */
diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index 4e43c2bb7f5f..784a68dfdbe3 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -40,8 +40,8 @@ static bool dma_coherent_ok(struct device *dev, phys_addr_t 
phys, size_t size)
return phys_to_dma(dev, phys) + size - 1 <= dev->coherent_dma_mask;
 }
 
-static void *dma_direct_alloc(struct device *dev, size_t size,
-   dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
+void *dma_direct_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
+   gfp_t gfp, unsigned long attrs)
 {
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
int page_order = get_order(size);
@@ -84,7 +84,7 @@ static void *dma_direct_alloc(struct device *dev, size_t size,
return page_address(page);
 }
 
-static void dma_direct_free(struct device *dev, size_t size, void *cpu_addr,
+void dma_direct_free(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_addr, unsigned long attrs)
 {
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-- 
2.14.2



[PATCH 29/33] dma-direct: retry allocations using GFP_DMA for small masks

2018-01-10 Thread Christoph Hellwig
If an attempt to allocate memory succeeded, but isn't inside the
supported DMA mask, retry the allocation with GFP_DMA set as a
last resort.

Based on the x86 code, but an off by one error in what is now
dma_coherent_ok has been fixed vs the x86 code.

Signed-off-by: Christoph Hellwig 
---
 lib/dma-direct.c | 25 -
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index 8f76032ebc3c..4e43c2bb7f5f 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -35,6 +35,11 @@ check_addr(struct device *dev, dma_addr_t dma_addr, size_t 
size,
return true;
 }
 
+static bool dma_coherent_ok(struct device *dev, phys_addr_t phys, size_t size)
+{
+   return phys_to_dma(dev, phys) + size - 1 <= dev->coherent_dma_mask;
+}
+
 static void *dma_direct_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
 {
@@ -48,11 +53,29 @@ static void *dma_direct_alloc(struct device *dev, size_t 
size,
if (dev->coherent_dma_mask <= DMA_BIT_MASK(32) && !(gfp & GFP_DMA))
gfp |= GFP_DMA32;
 
+again:
/* CMA can be used only in the context which permits sleeping */
-   if (gfpflags_allow_blocking(gfp))
+   if (gfpflags_allow_blocking(gfp)) {
page = dma_alloc_from_contiguous(dev, count, page_order, gfp);
+   if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
+   dma_release_from_contiguous(dev, page, count);
+   page = NULL;
+   }
+   }
if (!page)
page = alloc_pages_node(dev_to_node(dev), gfp, page_order);
+
+   if (page && !dma_coherent_ok(dev, page_to_phys(page), size)) {
+   __free_pages(page, page_order);
+   page = NULL;
+
+   if (dev->coherent_dma_mask < DMA_BIT_MASK(32) &&
+   !(gfp & GFP_DMA)) {
+   gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
+   goto again;
+   }
+   }
+
if (!page)
return NULL;
 
-- 
2.14.2



[PATCH 28/33] dma-direct: add support for allocation from ZONE_DMA and ZONE_DMA32

2018-01-10 Thread Christoph Hellwig
This allows to dip into zones for lower memory if they are available.
If one of the zones is not available the corresponding GFP_* flag
will evaluate to 0 so they won't change anything.  We provide an
arch tunable for those architectures that do not use GFP_DMA for
the lowest 24-bits, given that there are a few.

Roughly based on the x86 code.

Signed-off-by: Christoph Hellwig 
---
 lib/dma-direct.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index f04a424f91fa..8f76032ebc3c 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -12,6 +12,14 @@
 
 #define DIRECT_MAPPING_ERROR   0
 
+/*
+ * Most architectures use ZONE_DMA for the first 16 Megabytes, but
+ * some use it for entirely different regions:
+ */
+#ifndef ARCH_ZONE_DMA_BITS
+#define ARCH_ZONE_DMA_BITS 24
+#endif
+
 static bool
 check_addr(struct device *dev, dma_addr_t dma_addr, size_t size,
const char *caller)
@@ -34,6 +42,12 @@ static void *dma_direct_alloc(struct device *dev, size_t 
size,
int page_order = get_order(size);
struct page *page = NULL;
 
+   /* GFP_DMA32 and GFP_DMA are no ops without the corresponding zones: */
+   if (dev->coherent_dma_mask <= DMA_BIT_MASK(ARCH_ZONE_DMA_BITS))
+   gfp |= GFP_DMA;
+   if (dev->coherent_dma_mask <= DMA_BIT_MASK(32) && !(gfp & GFP_DMA))
+   gfp |= GFP_DMA32;
+
/* CMA can be used only in the context which permits sleeping */
if (gfpflags_allow_blocking(gfp))
page = dma_alloc_from_contiguous(dev, count, page_order, gfp);
-- 
2.14.2



[PATCH 27/33] dma-direct: use node local allocations for coherent memory

2018-01-10 Thread Christoph Hellwig
To preserve the x86 behavior.

Signed-off-by: Christoph Hellwig 
---
 lib/dma-direct.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index a9ae98be7af3..f04a424f91fa 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -38,7 +38,7 @@ static void *dma_direct_alloc(struct device *dev, size_t size,
if (gfpflags_allow_blocking(gfp))
page = dma_alloc_from_contiguous(dev, count, page_order, gfp);
if (!page)
-   page = alloc_pages(gfp, page_order);
+   page = alloc_pages_node(dev_to_node(dev), gfp, page_order);
if (!page)
return NULL;
 
-- 
2.14.2



[PATCH 25/33] dma-direct: add dma address sanity checks

2018-01-10 Thread Christoph Hellwig
Roughly based on the x86 pci-nommu implementation.

Signed-off-by: Christoph Hellwig 
---
 lib/dma-direct.c | 31 ++-
 1 file changed, 30 insertions(+), 1 deletion(-)

diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index 12ea9653781b..32fd4d9e4c47 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -9,6 +9,23 @@
 #include 
 #include 
 
+#define DIRECT_MAPPING_ERROR   0
+
+static bool
+check_addr(struct device *dev, dma_addr_t dma_addr, size_t size,
+   const char *caller)
+{
+   if (unlikely(dev && !dma_capable(dev, dma_addr, size))) {
+   if (*dev->dma_mask >= DMA_BIT_MASK(32)) {
+   dev_err(dev,
+   "%s: overflow %pad+%zu of device mask %llx\n",
+   caller, _addr, size, *dev->dma_mask);
+   }
+   return false;
+   }
+   return true;
+}
+
 static void *dma_direct_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
 {
@@ -31,7 +48,11 @@ static dma_addr_t dma_direct_map_page(struct device *dev, 
struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
unsigned long attrs)
 {
-   return phys_to_dma(dev, page_to_phys(page)) + offset;
+   dma_addr_t dma_addr = phys_to_dma(dev, page_to_phys(page)) + offset;
+
+   if (!check_addr(dev, dma_addr, size, __func__))
+   return DIRECT_MAPPING_ERROR;
+   return dma_addr;
 }
 
 static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
@@ -44,16 +65,24 @@ static int dma_direct_map_sg(struct device *dev, struct 
scatterlist *sgl,
BUG_ON(!sg_page(sg));
 
sg_dma_address(sg) = phys_to_dma(dev, sg_phys(sg));
+   if (!check_addr(dev, sg_dma_address(sg), sg->length, __func__))
+   return 0;
sg_dma_len(sg) = sg->length;
}
 
return nents;
 }
 
+static int dma_direct_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+   return dma_addr == DIRECT_MAPPING_ERROR;
+}
+
 const struct dma_map_ops dma_direct_ops = {
.alloc  = dma_direct_alloc,
.free   = dma_direct_free,
.map_page   = dma_direct_map_page,
.map_sg = dma_direct_map_sg,
+   .mapping_error  = dma_direct_mapping_error,
 };
 EXPORT_SYMBOL(dma_direct_ops);
-- 
2.14.2



[PATCH 26/33] dma-direct: add support for CMA allocation

2018-01-10 Thread Christoph Hellwig
Try the CMA allocator for coherent allocations if supported.

Roughly modelled after the x86 code.

Signed-off-by: Christoph Hellwig 
---
 lib/dma-direct.c | 24 ++--
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index 32fd4d9e4c47..a9ae98be7af3 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -7,6 +7,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define DIRECT_MAPPING_ERROR   0
@@ -29,19 +30,30 @@ check_addr(struct device *dev, dma_addr_t dma_addr, size_t 
size,
 static void *dma_direct_alloc(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
 {
-   void *ret;
+   unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+   int page_order = get_order(size);
+   struct page *page = NULL;
 
-   ret = (void *)__get_free_pages(gfp, get_order(size));
-   if (ret)
-   *dma_handle = phys_to_dma(dev, virt_to_phys(ret));
+   /* CMA can be used only in the context which permits sleeping */
+   if (gfpflags_allow_blocking(gfp))
+   page = dma_alloc_from_contiguous(dev, count, page_order, gfp);
+   if (!page)
+   page = alloc_pages(gfp, page_order);
+   if (!page)
+   return NULL;
 
-   return ret;
+   *dma_handle = phys_to_dma(dev, page_to_phys(page));
+   memset(page_address(page), 0, size);
+   return page_address(page);
 }
 
 static void dma_direct_free(struct device *dev, size_t size, void *cpu_addr,
dma_addr_t dma_addr, unsigned long attrs)
 {
-   free_pages((unsigned long)cpu_addr, get_order(size));
+   unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
+
+   if (!dma_release_from_contiguous(dev, virt_to_page(cpu_addr), count))
+   free_pages((unsigned long)cpu_addr, get_order(size));
 }
 
 static dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
-- 
2.14.2



[PATCH 24/33] dma-direct: use phys_to_dma

2018-01-10 Thread Christoph Hellwig
This means it uses whatever linear remapping scheme that the architecture
provides is used in the generic dma_direct ops.

Signed-off-by: Christoph Hellwig 
Reviewed-by: Vladimir Murzin 
---
 lib/dma-direct.c | 18 +++---
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/lib/dma-direct.c b/lib/dma-direct.c
index 0ec3262a3148..12ea9653781b 100644
--- a/lib/dma-direct.c
+++ b/lib/dma-direct.c
@@ -1,12 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * lib/dma-noop.c
- *
- * DMA operations that map to physical addresses without flushing memory.
+ * DMA operations that map physical memory directly without using an IOMMU or
+ * flushing caches.
  */
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 
@@ -17,7 +16,7 @@ static void *dma_direct_alloc(struct device *dev, size_t size,
 
ret = (void *)__get_free_pages(gfp, get_order(size));
if (ret)
-   *dma_handle = virt_to_phys(ret) - PFN_PHYS(dev->dma_pfn_offset);
+   *dma_handle = phys_to_dma(dev, virt_to_phys(ret));
 
return ret;
 }
@@ -32,7 +31,7 @@ static dma_addr_t dma_direct_map_page(struct device *dev, 
struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir,
unsigned long attrs)
 {
-   return page_to_phys(page) + offset - PFN_PHYS(dev->dma_pfn_offset);
+   return phys_to_dma(dev, page_to_phys(page)) + offset;
 }
 
 static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
@@ -42,12 +41,9 @@ static int dma_direct_map_sg(struct device *dev, struct 
scatterlist *sgl,
struct scatterlist *sg;
 
for_each_sg(sgl, sg, nents, i) {
-   dma_addr_t offset = PFN_PHYS(dev->dma_pfn_offset);
-   void *va;
-
BUG_ON(!sg_page(sg));
-   va = sg_virt(sg);
-   sg_dma_address(sg) = (dma_addr_t)virt_to_phys(va) - offset;
+
+   sg_dma_address(sg) = phys_to_dma(dev, sg_phys(sg));
sg_dma_len(sg) = sg->length;
}
 
-- 
2.14.2



  1   2   >