summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicolin Chen <nicoleotsuka@gmail.com>2019-09-23 06:08:10 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2019-09-27 14:30:13 -0400
commitb960bc448a252428bacca271f3416a8bda3b599b (patch)
treea0fa007a4abf5d671dbfb2a2473ac04bf7504c8a
parent4ee7dde4c777f14cb0f98dd201491bf6cc15899b (diff)
mmc: tegra: Implement ->set_dma_mask()
The SDHCI controller on Tegra186 supports 40-bit addressing, which is usually enough to address all of system memory. However, if the SDHCI controller is behind an IOMMU, the address space can go beyond. This happens on Tegra186 and later where the ARM SMMU has an input address space of 48 bits. If the DMA API is backed by this ARM SMMU, the top- down IOVA allocator will cause IOV addresses to be returned that the SDHCI controller cannot access. Unfortunately, prior to the introduction of the ->set_dma_mask() host operation, the SDHCI core would set either a 64-bit DMA mask if the controller claimed to support 64-bit addressing, or a 32-bit DMA mask otherwise. Since the full 64 bits cannot be addressed on Tegra, this had to be worked around in commit 68481a7e1c84 ("mmc: tegra: Mark 64 bit dma broken on Tegra186") by setting the SDHCI_QUIRK2_BROKEN_64_BIT_DMA quirk, which effectively restricts the DMA mask to 32 bits. One disadvantage of this is that dma_map_*() APIs will now try to use the swiotlb to bounce DMA to addresses beyond of the controller's DMA mask. This in turn caused degraded performance and can lead to situations where the swiotlb buffer is exhausted, which in turn leads to DMA transfers to fail. With the recent introduction of the ->set_dma_mask() host operation, this can now be properly fixed. For each generation of Tegra, the exact supported DMA mask can be configured. This kills two birds with one stone: it avoids the use of bounce buffers because system memory never exceeds the addressable memory range of the SDHCI controllers on these devices, and at the same time when an IOMMU is involved, it prevents IOV addresses from being allocated beyond the addressible range of the controllers. Since the DMA mask is now properly handled, the 64-bit DMA quirk can be removed. Signed-off-by: Nicolin Chen <nicoleotsuka@gmail.com> [treding@nvidia.com: provide more background in commit message] Tested-by: Nicolin Chen <nicoleotsuka@gmail.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Thierry Reding <treding@nvidia.com> Cc: stable@vger.kernel.org # v4.15 + Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/sdhci-tegra.c48
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 02d8f524bb9e..7bc950520fd9 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -4,6 +4,7 @@
4 */ 4 */
5 5
6#include <linux/delay.h> 6#include <linux/delay.h>
7#include <linux/dma-mapping.h>
7#include <linux/err.h> 8#include <linux/err.h>
8#include <linux/module.h> 9#include <linux/module.h>
9#include <linux/init.h> 10#include <linux/init.h>
@@ -104,6 +105,7 @@
104 105
105struct sdhci_tegra_soc_data { 106struct sdhci_tegra_soc_data {
106 const struct sdhci_pltfm_data *pdata; 107 const struct sdhci_pltfm_data *pdata;
108 u64 dma_mask;
107 u32 nvquirks; 109 u32 nvquirks;
108 u8 min_tap_delay; 110 u8 min_tap_delay;
109 u8 max_tap_delay; 111 u8 max_tap_delay;
@@ -1233,11 +1235,25 @@ static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = {
1233 .update_dcmd_desc = sdhci_tegra_update_dcmd_desc, 1235 .update_dcmd_desc = sdhci_tegra_update_dcmd_desc,
1234}; 1236};
1235 1237
1238static int tegra_sdhci_set_dma_mask(struct sdhci_host *host)
1239{
1240 struct sdhci_pltfm_host *platform = sdhci_priv(host);
1241 struct sdhci_tegra *tegra = sdhci_pltfm_priv(platform);
1242 const struct sdhci_tegra_soc_data *soc = tegra->soc_data;
1243 struct device *dev = mmc_dev(host->mmc);
1244
1245 if (soc->dma_mask)
1246 return dma_set_mask_and_coherent(dev, soc->dma_mask);
1247
1248 return 0;
1249}
1250
1236static const struct sdhci_ops tegra_sdhci_ops = { 1251static const struct sdhci_ops tegra_sdhci_ops = {
1237 .get_ro = tegra_sdhci_get_ro, 1252 .get_ro = tegra_sdhci_get_ro,
1238 .read_w = tegra_sdhci_readw, 1253 .read_w = tegra_sdhci_readw,
1239 .write_l = tegra_sdhci_writel, 1254 .write_l = tegra_sdhci_writel,
1240 .set_clock = tegra_sdhci_set_clock, 1255 .set_clock = tegra_sdhci_set_clock,
1256 .set_dma_mask = tegra_sdhci_set_dma_mask,
1241 .set_bus_width = sdhci_set_bus_width, 1257 .set_bus_width = sdhci_set_bus_width,
1242 .reset = tegra_sdhci_reset, 1258 .reset = tegra_sdhci_reset,
1243 .platform_execute_tuning = tegra_sdhci_execute_tuning, 1259 .platform_execute_tuning = tegra_sdhci_execute_tuning,
@@ -1257,6 +1273,7 @@ static const struct sdhci_pltfm_data sdhci_tegra20_pdata = {
1257 1273
1258static const struct sdhci_tegra_soc_data soc_data_tegra20 = { 1274static const struct sdhci_tegra_soc_data soc_data_tegra20 = {
1259 .pdata = &sdhci_tegra20_pdata, 1275 .pdata = &sdhci_tegra20_pdata,
1276 .dma_mask = DMA_BIT_MASK(32),
1260 .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 | 1277 .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 |
1261 NVQUIRK_ENABLE_BLOCK_GAP_DET, 1278 NVQUIRK_ENABLE_BLOCK_GAP_DET,
1262}; 1279};
@@ -1283,6 +1300,7 @@ static const struct sdhci_pltfm_data sdhci_tegra30_pdata = {
1283 1300
1284static const struct sdhci_tegra_soc_data soc_data_tegra30 = { 1301static const struct sdhci_tegra_soc_data soc_data_tegra30 = {
1285 .pdata = &sdhci_tegra30_pdata, 1302 .pdata = &sdhci_tegra30_pdata,
1303 .dma_mask = DMA_BIT_MASK(32),
1286 .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 | 1304 .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 |
1287 NVQUIRK_ENABLE_SDR50 | 1305 NVQUIRK_ENABLE_SDR50 |
1288 NVQUIRK_ENABLE_SDR104 | 1306 NVQUIRK_ENABLE_SDR104 |
@@ -1295,6 +1313,7 @@ static const struct sdhci_ops tegra114_sdhci_ops = {
1295 .write_w = tegra_sdhci_writew, 1313 .write_w = tegra_sdhci_writew,
1296 .write_l = tegra_sdhci_writel, 1314 .write_l = tegra_sdhci_writel,
1297 .set_clock = tegra_sdhci_set_clock, 1315 .set_clock = tegra_sdhci_set_clock,
1316 .set_dma_mask = tegra_sdhci_set_dma_mask,
1298 .set_bus_width = sdhci_set_bus_width, 1317 .set_bus_width = sdhci_set_bus_width,
1299 .reset = tegra_sdhci_reset, 1318 .reset = tegra_sdhci_reset,
1300 .platform_execute_tuning = tegra_sdhci_execute_tuning, 1319 .platform_execute_tuning = tegra_sdhci_execute_tuning,
@@ -1316,6 +1335,7 @@ static const struct sdhci_pltfm_data sdhci_tegra114_pdata = {
1316 1335
1317static const struct sdhci_tegra_soc_data soc_data_tegra114 = { 1336static const struct sdhci_tegra_soc_data soc_data_tegra114 = {
1318 .pdata = &sdhci_tegra114_pdata, 1337 .pdata = &sdhci_tegra114_pdata,
1338 .dma_mask = DMA_BIT_MASK(32),
1319}; 1339};
1320 1340
1321static const struct sdhci_pltfm_data sdhci_tegra124_pdata = { 1341static const struct sdhci_pltfm_data sdhci_tegra124_pdata = {
@@ -1325,22 +1345,13 @@ static const struct sdhci_pltfm_data sdhci_tegra124_pdata = {
1325 SDHCI_QUIRK_NO_HISPD_BIT | 1345 SDHCI_QUIRK_NO_HISPD_BIT |
1326 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 1346 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
1327 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 1347 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
1328 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 1348 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
1329 /*
1330 * The TRM states that the SD/MMC controller found on
1331 * Tegra124 can address 34 bits (the maximum supported by
1332 * the Tegra memory controller), but tests show that DMA
1333 * to or from above 4 GiB doesn't work. This is possibly
1334 * caused by missing programming, though it's not obvious
1335 * what sequence is required. Mark 64-bit DMA broken for
1336 * now to fix this for existing users (e.g. Nyan boards).
1337 */
1338 SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
1339 .ops = &tegra114_sdhci_ops, 1349 .ops = &tegra114_sdhci_ops,
1340}; 1350};
1341 1351
1342static const struct sdhci_tegra_soc_data soc_data_tegra124 = { 1352static const struct sdhci_tegra_soc_data soc_data_tegra124 = {
1343 .pdata = &sdhci_tegra124_pdata, 1353 .pdata = &sdhci_tegra124_pdata,
1354 .dma_mask = DMA_BIT_MASK(34),
1344}; 1355};
1345 1356
1346static const struct sdhci_ops tegra210_sdhci_ops = { 1357static const struct sdhci_ops tegra210_sdhci_ops = {
@@ -1349,6 +1360,7 @@ static const struct sdhci_ops tegra210_sdhci_ops = {
1349 .write_w = tegra210_sdhci_writew, 1360 .write_w = tegra210_sdhci_writew,
1350 .write_l = tegra_sdhci_writel, 1361 .write_l = tegra_sdhci_writel,
1351 .set_clock = tegra_sdhci_set_clock, 1362 .set_clock = tegra_sdhci_set_clock,
1363 .set_dma_mask = tegra_sdhci_set_dma_mask,
1352 .set_bus_width = sdhci_set_bus_width, 1364 .set_bus_width = sdhci_set_bus_width,
1353 .reset = tegra_sdhci_reset, 1365 .reset = tegra_sdhci_reset,
1354 .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, 1366 .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
@@ -1369,6 +1381,7 @@ static const struct sdhci_pltfm_data sdhci_tegra210_pdata = {
1369 1381
1370static const struct sdhci_tegra_soc_data soc_data_tegra210 = { 1382static const struct sdhci_tegra_soc_data soc_data_tegra210 = {
1371 .pdata = &sdhci_tegra210_pdata, 1383 .pdata = &sdhci_tegra210_pdata,
1384 .dma_mask = DMA_BIT_MASK(34),
1372 .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL | 1385 .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
1373 NVQUIRK_HAS_PADCALIB | 1386 NVQUIRK_HAS_PADCALIB |
1374 NVQUIRK_DIS_CARD_CLK_CONFIG_TAP | 1387 NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
@@ -1383,6 +1396,7 @@ static const struct sdhci_ops tegra186_sdhci_ops = {
1383 .read_w = tegra_sdhci_readw, 1396 .read_w = tegra_sdhci_readw,
1384 .write_l = tegra_sdhci_writel, 1397 .write_l = tegra_sdhci_writel,
1385 .set_clock = tegra_sdhci_set_clock, 1398 .set_clock = tegra_sdhci_set_clock,
1399 .set_dma_mask = tegra_sdhci_set_dma_mask,
1386 .set_bus_width = sdhci_set_bus_width, 1400 .set_bus_width = sdhci_set_bus_width,
1387 .reset = tegra_sdhci_reset, 1401 .reset = tegra_sdhci_reset,
1388 .set_uhs_signaling = tegra_sdhci_set_uhs_signaling, 1402 .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
@@ -1398,20 +1412,13 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
1398 SDHCI_QUIRK_NO_HISPD_BIT | 1412 SDHCI_QUIRK_NO_HISPD_BIT |
1399 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 1413 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
1400 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 1414 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
1401 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | 1415 .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
1402 /* SDHCI controllers on Tegra186 support 40-bit addressing.
1403 * IOVA addresses are 48-bit wide on Tegra186.
1404 * With 64-bit dma mask used for SDHCI, accesses can
1405 * be broken. Disable 64-bit dma, which would fall back
1406 * to 32-bit dma mask. Ideally 40-bit dma mask would work,
1407 * But it is not supported as of now.
1408 */
1409 SDHCI_QUIRK2_BROKEN_64_BIT_DMA,
1410 .ops = &tegra186_sdhci_ops, 1416 .ops = &tegra186_sdhci_ops,
1411}; 1417};
1412 1418
1413static const struct sdhci_tegra_soc_data soc_data_tegra186 = { 1419static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
1414 .pdata = &sdhci_tegra186_pdata, 1420 .pdata = &sdhci_tegra186_pdata,
1421 .dma_mask = DMA_BIT_MASK(40),
1415 .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL | 1422 .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
1416 NVQUIRK_HAS_PADCALIB | 1423 NVQUIRK_HAS_PADCALIB |
1417 NVQUIRK_DIS_CARD_CLK_CONFIG_TAP | 1424 NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |
@@ -1424,6 +1431,7 @@ static const struct sdhci_tegra_soc_data soc_data_tegra186 = {
1424 1431
1425static const struct sdhci_tegra_soc_data soc_data_tegra194 = { 1432static const struct sdhci_tegra_soc_data soc_data_tegra194 = {
1426 .pdata = &sdhci_tegra186_pdata, 1433 .pdata = &sdhci_tegra186_pdata,
1434 .dma_mask = DMA_BIT_MASK(39),
1427 .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL | 1435 .nvquirks = NVQUIRK_NEEDS_PAD_CONTROL |
1428 NVQUIRK_HAS_PADCALIB | 1436 NVQUIRK_HAS_PADCALIB |
1429 NVQUIRK_DIS_CARD_CLK_CONFIG_TAP | 1437 NVQUIRK_DIS_CARD_CLK_CONFIG_TAP |