Hi,
This series enables IOMMU support for 2d/3d HW on Tegra30/114, as a result userspace that uses 2d/3d could work with the active IOMMU.
Dmitry Osipenko (5): drm/tegra: dc: Balance IOMMU group refcounting drm/tegra: gr2d: Add IOMMU support drm/tegra: gr3d: Add IOMMU support ARM: dts: tegra30: Add IOMMU nodes to Host1x and its clients ARM: dts: tegra114: Add IOMMU nodes to Host1x and its clients
arch/arm/boot/dts/tegra114.dtsi | 5 +++++ arch/arm/boot/dts/tegra30.dtsi | 14 +++++++++++++ drivers/gpu/drm/tegra/dc.c | 35 ++++++++++++++++----------------- drivers/gpu/drm/tegra/dc.h | 2 +- drivers/gpu/drm/tegra/drm.h | 2 +- drivers/gpu/drm/tegra/gr2d.c | 31 +++++++++++++++++++++++++++-- drivers/gpu/drm/tegra/gr3d.c | 27 +++++++++++++++++++++++++ 7 files changed, 94 insertions(+), 22 deletions(-)
Remove unneeded iommu_group_get() and add missing iommu_group_put(), correcting IOMMU group refcount. This is a minor correction / cleanup that doesn't really fix anything because Tegra's IOMMU driver are built-in and hence groups refcounting can't hold IOMMU driver from unloading.
Signed-off-by: Dmitry Osipenko digetx@gmail.com --- drivers/gpu/drm/tegra/dc.c | 35 +++++++++++++++++------------------ drivers/gpu/drm/tegra/dc.h | 2 +- drivers/gpu/drm/tegra/drm.h | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index d7a0f62c6e2e..9fc34c6a7218 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1927,7 +1927,6 @@ static irqreturn_t tegra_dc_irq(int irq, void *data) static int tegra_dc_init(struct host1x_client *client) { struct drm_device *drm = dev_get_drvdata(client->parent); - struct iommu_group *group = iommu_group_get(client->dev); unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; struct tegra_dc *dc = host1x_client_to_dc(client); struct tegra_drm *tegra = drm->dev_private; @@ -1939,20 +1938,21 @@ static int tegra_dc_init(struct host1x_client *client) if (!dc->syncpt) dev_warn(dc->dev, "failed to allocate syncpoint\n");
- if (group && tegra->domain) { - if (group != tegra->group) { - err = iommu_attach_group(tegra->domain, group); + if (tegra->domain) { + dc->group = iommu_group_get(client->dev); + + if (dc->group && dc->group != tegra->dc_group) { + err = iommu_attach_group(tegra->domain, dc->group); if (err < 0) { dev_err(dc->dev, "failed to attach to domain: %d\n", err); + iommu_group_put(dc->group); return err; }
- tegra->group = group; + tegra->dc_group = dc->group; } - - dc->domain = tegra->domain; }
if (dc->soc->wgrps) @@ -2017,13 +2017,13 @@ static int tegra_dc_init(struct host1x_client *client) if (!IS_ERR(primary)) drm_plane_cleanup(primary);
- if (group && dc->domain) { - if (group == tegra->group) { - iommu_detach_group(dc->domain, group); - tegra->group = NULL; + if (dc->group) { + if (dc->group && dc->group == tegra->dc_group) { + iommu_detach_group(tegra->domain, dc->group); + tegra->dc_group = NULL; }
- dc->domain = NULL; + iommu_group_put(dc->group); }
return err; @@ -2032,7 +2032,6 @@ static int tegra_dc_init(struct host1x_client *client) static int tegra_dc_exit(struct host1x_client *client) { struct drm_device *drm = dev_get_drvdata(client->parent); - struct iommu_group *group = iommu_group_get(client->dev); struct tegra_dc *dc = host1x_client_to_dc(client); struct tegra_drm *tegra = drm->dev_private; int err; @@ -2045,13 +2044,13 @@ static int tegra_dc_exit(struct host1x_client *client) return err; }
- if (group && dc->domain) { - if (group == tegra->group) { - iommu_detach_group(dc->domain, group); - tegra->group = NULL; + if (dc->group) { + if (dc->group && dc->group == tegra->dc_group) { + iommu_detach_group(tegra->domain, dc->group); + tegra->dc_group = NULL; }
- dc->domain = NULL; + iommu_group_put(dc->group); }
host1x_syncpt_free(dc->syncpt); diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index ca5cac6bf8ea..5ca4e07333bb 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -94,7 +94,7 @@ struct tegra_dc {
const struct tegra_dc_soc_info *soc;
- struct iommu_domain *domain; + struct iommu_group *group; };
static inline struct tegra_dc * diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 4f41aaec8530..7777640a6911 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -46,7 +46,7 @@ struct tegra_drm { struct drm_device *drm;
struct iommu_domain *domain; - struct iommu_group *group; + struct iommu_group *dc_group; struct mutex mm_lock; struct drm_mm mm;
On Fri, May 04, 2018 at 02:47:19AM +0300, Dmitry Osipenko wrote:
Remove unneeded iommu_group_get() and add missing iommu_group_put(), correcting IOMMU group refcount. This is a minor correction / cleanup that doesn't really fix anything because Tegra's IOMMU driver are built-in and hence groups refcounting can't hold IOMMU driver from unloading.
Signed-off-by: Dmitry Osipenko digetx@gmail.com
drivers/gpu/drm/tegra/dc.c | 35 +++++++++++++++++------------------ drivers/gpu/drm/tegra/dc.h | 2 +- drivers/gpu/drm/tegra/drm.h | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index d7a0f62c6e2e..9fc34c6a7218 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1927,7 +1927,6 @@ static irqreturn_t tegra_dc_irq(int irq, void *data) static int tegra_dc_init(struct host1x_client *client) { struct drm_device *drm = dev_get_drvdata(client->parent);
- struct iommu_group *group = iommu_group_get(client->dev); unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; struct tegra_dc *dc = host1x_client_to_dc(client); struct tegra_drm *tegra = drm->dev_private;
@@ -1939,20 +1938,21 @@ static int tegra_dc_init(struct host1x_client *client) if (!dc->syncpt) dev_warn(dc->dev, "failed to allocate syncpoint\n");
- if (group && tegra->domain) {
if (group != tegra->group) {
err = iommu_attach_group(tegra->domain, group);
- if (tegra->domain) {
dc->group = iommu_group_get(client->dev);
if (dc->group && dc->group != tegra->dc_group) {
err = iommu_attach_group(tegra->domain, dc->group); if (err < 0) { dev_err(dc->dev, "failed to attach to domain: %d\n", err);
iommu_group_put(dc->group); return err; }
tegra->group = group;
}tegra->dc_group = dc->group;
dc->domain = tegra->domain;
}
if (dc->soc->wgrps)
@@ -2017,13 +2017,13 @@ static int tegra_dc_init(struct host1x_client *client) if (!IS_ERR(primary)) drm_plane_cleanup(primary);
- if (group && dc->domain) {
if (group == tegra->group) {
iommu_detach_group(dc->domain, group);
tegra->group = NULL;
- if (dc->group) {
if (dc->group && dc->group == tegra->dc_group) {
You can drop the dc->group check from the second conditional.
iommu_detach_group(tegra->domain, dc->group);
}tegra->dc_group = NULL;
dc->domain = NULL;
iommu_group_put(dc->group);
}
return err;
@@ -2032,7 +2032,6 @@ static int tegra_dc_init(struct host1x_client *client) static int tegra_dc_exit(struct host1x_client *client) { struct drm_device *drm = dev_get_drvdata(client->parent);
- struct iommu_group *group = iommu_group_get(client->dev); struct tegra_dc *dc = host1x_client_to_dc(client); struct tegra_drm *tegra = drm->dev_private; int err;
@@ -2045,13 +2044,13 @@ static int tegra_dc_exit(struct host1x_client *client) return err; }
- if (group && dc->domain) {
if (group == tegra->group) {
iommu_detach_group(dc->domain, group);
tegra->group = NULL;
- if (dc->group) {
if (dc->group && dc->group == tegra->dc_group) {
iommu_detach_group(tegra->domain, dc->group);
}tegra->dc_group = NULL;
dc->domain = NULL;
iommu_group_put(dc->group);
}
host1x_syncpt_free(dc->syncpt);
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index ca5cac6bf8ea..5ca4e07333bb 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -94,7 +94,7 @@ struct tegra_dc {
const struct tegra_dc_soc_info *soc;
- struct iommu_domain *domain;
- struct iommu_group *group;
};
static inline struct tegra_dc * diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 4f41aaec8530..7777640a6911 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -46,7 +46,7 @@ struct tegra_drm { struct drm_device *drm;
struct iommu_domain *domain;
- struct iommu_group *group;
- struct iommu_group *dc_group;
It's not obvious to me why this needs to be renamed.
Thierry
On 04.05.2018 13:45, Thierry Reding wrote:
On Fri, May 04, 2018 at 02:47:19AM +0300, Dmitry Osipenko wrote:
Remove unneeded iommu_group_get() and add missing iommu_group_put(), correcting IOMMU group refcount. This is a minor correction / cleanup that doesn't really fix anything because Tegra's IOMMU driver are built-in and hence groups refcounting can't hold IOMMU driver from unloading.
Signed-off-by: Dmitry Osipenko digetx@gmail.com
drivers/gpu/drm/tegra/dc.c | 35 +++++++++++++++++------------------ drivers/gpu/drm/tegra/dc.h | 2 +- drivers/gpu/drm/tegra/drm.h | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index d7a0f62c6e2e..9fc34c6a7218 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1927,7 +1927,6 @@ static irqreturn_t tegra_dc_irq(int irq, void *data) static int tegra_dc_init(struct host1x_client *client) { struct drm_device *drm = dev_get_drvdata(client->parent);
- struct iommu_group *group = iommu_group_get(client->dev); unsigned long flags = HOST1X_SYNCPT_CLIENT_MANAGED; struct tegra_dc *dc = host1x_client_to_dc(client); struct tegra_drm *tegra = drm->dev_private;
@@ -1939,20 +1938,21 @@ static int tegra_dc_init(struct host1x_client *client) if (!dc->syncpt) dev_warn(dc->dev, "failed to allocate syncpoint\n");
- if (group && tegra->domain) {
if (group != tegra->group) {
err = iommu_attach_group(tegra->domain, group);
- if (tegra->domain) {
dc->group = iommu_group_get(client->dev);
if (dc->group && dc->group != tegra->dc_group) {
err = iommu_attach_group(tegra->domain, dc->group); if (err < 0) { dev_err(dc->dev, "failed to attach to domain: %d\n", err);
iommu_group_put(dc->group); return err; }
tegra->group = group;
}tegra->dc_group = dc->group;
dc->domain = tegra->domain;
}
if (dc->soc->wgrps)
@@ -2017,13 +2017,13 @@ static int tegra_dc_init(struct host1x_client *client) if (!IS_ERR(primary)) drm_plane_cleanup(primary);
- if (group && dc->domain) {
if (group == tegra->group) {
iommu_detach_group(dc->domain, group);
tegra->group = NULL;
- if (dc->group) {
if (dc->group && dc->group == tegra->dc_group) {
You can drop the dc->group check from the second conditional.
Indeed.
iommu_detach_group(tegra->domain, dc->group);
}tegra->dc_group = NULL;
dc->domain = NULL;
iommu_group_put(dc->group);
}
return err;
@@ -2032,7 +2032,6 @@ static int tegra_dc_init(struct host1x_client *client) static int tegra_dc_exit(struct host1x_client *client) { struct drm_device *drm = dev_get_drvdata(client->parent);
- struct iommu_group *group = iommu_group_get(client->dev); struct tegra_dc *dc = host1x_client_to_dc(client); struct tegra_drm *tegra = drm->dev_private; int err;
@@ -2045,13 +2044,13 @@ static int tegra_dc_exit(struct host1x_client *client) return err; }
- if (group && dc->domain) {
if (group == tegra->group) {
iommu_detach_group(dc->domain, group);
tegra->group = NULL;
- if (dc->group) {
if (dc->group && dc->group == tegra->dc_group) {
iommu_detach_group(tegra->domain, dc->group);
}tegra->dc_group = NULL;
dc->domain = NULL;
iommu_group_put(dc->group);
}
host1x_syncpt_free(dc->syncpt);
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index ca5cac6bf8ea..5ca4e07333bb 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -94,7 +94,7 @@ struct tegra_dc {
const struct tegra_dc_soc_info *soc;
- struct iommu_domain *domain;
- struct iommu_group *group;
};
static inline struct tegra_dc * diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 4f41aaec8530..7777640a6911 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -46,7 +46,7 @@ struct tegra_drm { struct drm_device *drm;
struct iommu_domain *domain;
- struct iommu_group *group;
- struct iommu_group *dc_group;
It's not obvious to me why this needs to be renamed.
tegra->group is only used by the dc.c and seems its sole purpose is to avoid re-attaching DC group if DC0 and DC1 share the same group, like DC's on newer Tegra's do. I think it's better to rename 'group' to 'dc_group' for the clarity.
On Fri, May 04, 2018 at 02:47:19AM +0300, Dmitry Osipenko wrote:
Remove unneeded iommu_group_get() and add missing iommu_group_put(), correcting IOMMU group refcount. This is a minor correction / cleanup that doesn't really fix anything because Tegra's IOMMU driver are built-in and hence groups refcounting can't hold IOMMU driver from unloading.
Signed-off-by: Dmitry Osipenko digetx@gmail.com
drivers/gpu/drm/tegra/dc.c | 35 +++++++++++++++++------------------ drivers/gpu/drm/tegra/dc.h | 2 +- drivers/gpu/drm/tegra/drm.h | 2 +- 3 files changed, 19 insertions(+), 20 deletions(-)
Applied, thanks.
Thierry
Attach GR2D to the display IOMMU group in order to provide GR2D access to BO's IOVA.
Signed-off-by: Dmitry Osipenko digetx@gmail.com --- drivers/gpu/drm/tegra/gr2d.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c index 9a8ea93016a9..8eb530a85dd0 100644 --- a/drivers/gpu/drm/tegra/gr2d.c +++ b/drivers/gpu/drm/tegra/gr2d.c @@ -7,12 +7,14 @@ */
#include <linux/clk.h> +#include <linux/iommu.h>
#include "drm.h" #include "gem.h" #include "gr2d.h"
struct gr2d { + struct iommu_group *group; struct tegra_drm_client client; struct host1x_channel *channel; struct clk *clk; @@ -30,7 +32,9 @@ static int gr2d_init(struct host1x_client *client) struct tegra_drm_client *drm = host1x_to_drm_client(client); struct drm_device *dev = dev_get_drvdata(client->parent); unsigned long flags = HOST1X_SYNCPT_HAS_BASE; + struct tegra_drm *tegra = dev->dev_private; struct gr2d *gr2d = to_gr2d(drm); + int err;
gr2d->channel = host1x_channel_request(client->dev); if (!gr2d->channel) @@ -42,23 +46,46 @@ static int gr2d_init(struct host1x_client *client) return -ENOMEM; }
- return tegra_drm_register_client(dev->dev_private, drm); + if (tegra->domain) { + gr2d->group = iommu_group_get(client->dev); + + if (gr2d->group) { + err = iommu_attach_group(tegra->domain, gr2d->group); + if (err < 0) { + dev_err(client->dev, + "failed to attach to domain: %d\n", + err); + host1x_syncpt_free(client->syncpts[0]); + host1x_channel_put(gr2d->channel); + iommu_group_put(gr2d->group); + return err; + } + } + } + + return tegra_drm_register_client(tegra, drm); }
static int gr2d_exit(struct host1x_client *client) { struct tegra_drm_client *drm = host1x_to_drm_client(client); struct drm_device *dev = dev_get_drvdata(client->parent); + struct tegra_drm *tegra = dev->dev_private; struct gr2d *gr2d = to_gr2d(drm); int err;
- err = tegra_drm_unregister_client(dev->dev_private, drm); + err = tegra_drm_unregister_client(tegra, drm); if (err < 0) return err;
host1x_syncpt_free(client->syncpts[0]); host1x_channel_put(gr2d->channel);
+ if (gr2d->group) { + iommu_detach_group(tegra->domain, gr2d->group); + iommu_group_put(gr2d->group); + } + return 0; }
On Fri, May 04, 2018 at 02:47:20AM +0300, Dmitry Osipenko wrote:
Attach GR2D to the display IOMMU group in order to provide GR2D access to BO's IOVA.
Signed-off-by: Dmitry Osipenko digetx@gmail.com
drivers/gpu/drm/tegra/gr2d.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c index 9a8ea93016a9..8eb530a85dd0 100644 --- a/drivers/gpu/drm/tegra/gr2d.c +++ b/drivers/gpu/drm/tegra/gr2d.c @@ -7,12 +7,14 @@ */
#include <linux/clk.h> +#include <linux/iommu.h>
#include "drm.h" #include "gem.h" #include "gr2d.h"
struct gr2d {
- struct iommu_group *group; struct tegra_drm_client client; struct host1x_channel *channel; struct clk *clk;
@@ -30,7 +32,9 @@ static int gr2d_init(struct host1x_client *client) struct tegra_drm_client *drm = host1x_to_drm_client(client); struct drm_device *dev = dev_get_drvdata(client->parent); unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
struct tegra_drm *tegra = dev->dev_private; struct gr2d *gr2d = to_gr2d(drm);
int err;
gr2d->channel = host1x_channel_request(client->dev); if (!gr2d->channel)
@@ -42,23 +46,46 @@ static int gr2d_init(struct host1x_client *client) return -ENOMEM; }
- return tegra_drm_register_client(dev->dev_private, drm);
- if (tegra->domain) {
gr2d->group = iommu_group_get(client->dev);
if (gr2d->group) {
err = iommu_attach_group(tegra->domain, gr2d->group);
if (err < 0) {
dev_err(client->dev,
"failed to attach to domain: %d\n",
err);
host1x_syncpt_free(client->syncpts[0]);
host1x_channel_put(gr2d->channel);
iommu_group_put(gr2d->group);
return err;
}
}
- }
This is almost identical to the code in DC, perhaps we should factor this out into a separate helper? Nothing that needs to be done right now, I'll take a look at it and see if I can come up with something good in a follow-up patch.
- return tegra_drm_register_client(tegra, drm);
}
static int gr2d_exit(struct host1x_client *client) { struct tegra_drm_client *drm = host1x_to_drm_client(client); struct drm_device *dev = dev_get_drvdata(client->parent);
- struct tegra_drm *tegra = dev->dev_private; struct gr2d *gr2d = to_gr2d(drm); int err;
- err = tegra_drm_unregister_client(dev->dev_private, drm);
err = tegra_drm_unregister_client(tegra, drm); if (err < 0) return err;
host1x_syncpt_free(client->syncpts[0]); host1x_channel_put(gr2d->channel);
if (gr2d->group) {
iommu_detach_group(tegra->domain, gr2d->group);
iommu_group_put(gr2d->group);
}
return 0;
}
Thierry
On 04.05.2018 13:54, Thierry Reding wrote:
On Fri, May 04, 2018 at 02:47:20AM +0300, Dmitry Osipenko wrote:
Attach GR2D to the display IOMMU group in order to provide GR2D access to BO's IOVA.
Signed-off-by: Dmitry Osipenko digetx@gmail.com
drivers/gpu/drm/tegra/gr2d.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c index 9a8ea93016a9..8eb530a85dd0 100644 --- a/drivers/gpu/drm/tegra/gr2d.c +++ b/drivers/gpu/drm/tegra/gr2d.c @@ -7,12 +7,14 @@ */
#include <linux/clk.h> +#include <linux/iommu.h>
#include "drm.h" #include "gem.h" #include "gr2d.h"
struct gr2d {
- struct iommu_group *group; struct tegra_drm_client client; struct host1x_channel *channel; struct clk *clk;
@@ -30,7 +32,9 @@ static int gr2d_init(struct host1x_client *client) struct tegra_drm_client *drm = host1x_to_drm_client(client); struct drm_device *dev = dev_get_drvdata(client->parent); unsigned long flags = HOST1X_SYNCPT_HAS_BASE;
struct tegra_drm *tegra = dev->dev_private; struct gr2d *gr2d = to_gr2d(drm);
int err;
gr2d->channel = host1x_channel_request(client->dev); if (!gr2d->channel)
@@ -42,23 +46,46 @@ static int gr2d_init(struct host1x_client *client) return -ENOMEM; }
- return tegra_drm_register_client(dev->dev_private, drm);
- if (tegra->domain) {
gr2d->group = iommu_group_get(client->dev);
if (gr2d->group) {
err = iommu_attach_group(tegra->domain, gr2d->group);
if (err < 0) {
dev_err(client->dev,
"failed to attach to domain: %d\n",
err);
host1x_syncpt_free(client->syncpts[0]);
host1x_channel_put(gr2d->channel);
iommu_group_put(gr2d->group);
return err;
}
}
- }
This is almost identical to the code in DC, perhaps we should factor this out into a separate helper? Nothing that needs to be done right now, I'll take a look at it and see if I can come up with something good in a follow-up patch.
Sounds good.
On Fri, May 04, 2018 at 02:47:20AM +0300, Dmitry Osipenko wrote:
Attach GR2D to the display IOMMU group in order to provide GR2D access to BO's IOVA.
Signed-off-by: Dmitry Osipenko digetx@gmail.com
drivers/gpu/drm/tegra/gr2d.c | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-)
Applied, thanks.
Thierry
Attach GR3D to the displays IOMMU group in order to provide GR3D access to BO's IOVA.
Signed-off-by: Dmitry Osipenko digetx@gmail.com --- drivers/gpu/drm/tegra/gr3d.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index 28c4ef63065b..ce5120683091 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -9,6 +9,7 @@
#include <linux/clk.h> #include <linux/host1x.h> +#include <linux/iommu.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/reset.h> @@ -20,6 +21,7 @@ #include "gr3d.h"
struct gr3d { + struct iommu_group *group; struct tegra_drm_client client; struct host1x_channel *channel; struct clk *clk_secondary; @@ -40,7 +42,9 @@ static int gr3d_init(struct host1x_client *client) struct tegra_drm_client *drm = host1x_to_drm_client(client); struct drm_device *dev = dev_get_drvdata(client->parent); unsigned long flags = HOST1X_SYNCPT_HAS_BASE; + struct tegra_drm *tegra = dev->dev_private; struct gr3d *gr3d = to_gr3d(drm); + int err;
gr3d->channel = host1x_channel_request(client->dev); if (!gr3d->channel) @@ -52,6 +56,23 @@ static int gr3d_init(struct host1x_client *client) return -ENOMEM; }
+ if (tegra->domain) { + gr3d->group = iommu_group_get(client->dev); + + if (gr3d->group) { + err = iommu_attach_group(tegra->domain, gr3d->group); + if (err < 0) { + dev_err(client->dev, + "failed to attach to domain: %d\n", + err); + host1x_syncpt_free(client->syncpts[0]); + host1x_channel_put(gr3d->channel); + iommu_group_put(gr3d->group); + return err; + } + } + } + return tegra_drm_register_client(dev->dev_private, drm); }
@@ -59,6 +80,7 @@ static int gr3d_exit(struct host1x_client *client) { struct tegra_drm_client *drm = host1x_to_drm_client(client); struct drm_device *dev = dev_get_drvdata(client->parent); + struct tegra_drm *tegra = dev->dev_private; struct gr3d *gr3d = to_gr3d(drm); int err;
@@ -69,6 +91,11 @@ static int gr3d_exit(struct host1x_client *client) host1x_syncpt_free(client->syncpts[0]); host1x_channel_put(gr3d->channel);
+ if (gr3d->group) { + iommu_detach_group(tegra->domain, gr3d->group); + iommu_group_put(gr3d->group); + } + return 0; }
On Fri, May 04, 2018 at 02:47:21AM +0300, Dmitry Osipenko wrote:
Attach GR3D to the displays IOMMU group in order to provide GR3D access to BO's IOVA.
Signed-off-by: Dmitry Osipenko digetx@gmail.com
drivers/gpu/drm/tegra/gr3d.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
Applied, thanks.
Thierry
Enable IOMMU support for Host1x and its clients.
Signed-off-by: Dmitry Osipenko digetx@gmail.com --- arch/arm/boot/dts/tegra30.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi index a110cf84d85f..09087b9c5e26 100644 --- a/arch/arm/boot/dts/tegra30.dtsi +++ b/arch/arm/boot/dts/tegra30.dtsi @@ -112,6 +112,7 @@ clocks = <&tegra_car TEGRA30_CLK_HOST1X>; resets = <&tegra_car 28>; reset-names = "host1x"; + iommus = <&mc TEGRA_SWGROUP_HC>;
#address-cells = <1>; #size-cells = <1>; @@ -125,6 +126,8 @@ clocks = <&tegra_car TEGRA30_CLK_MPE>; resets = <&tegra_car 60>; reset-names = "mpe"; + + iommus = <&mc TEGRA_SWGROUP_MPE>; };
vi@54080000 { @@ -134,6 +137,8 @@ clocks = <&tegra_car TEGRA30_CLK_VI>; resets = <&tegra_car 20>; reset-names = "vi"; + + iommus = <&mc TEGRA_SWGROUP_VI>; };
epp@540c0000 { @@ -143,6 +148,8 @@ clocks = <&tegra_car TEGRA30_CLK_EPP>; resets = <&tegra_car 19>; reset-names = "epp"; + + iommus = <&mc TEGRA_SWGROUP_EPP>; };
isp@54100000 { @@ -152,6 +159,8 @@ clocks = <&tegra_car TEGRA30_CLK_ISP>; resets = <&tegra_car 23>; reset-names = "isp"; + + iommus = <&mc TEGRA_SWGROUP_ISP>; };
gr2d@54140000 { @@ -161,6 +170,8 @@ clocks = <&tegra_car TEGRA30_CLK_GR2D>; resets = <&tegra_car 21>; reset-names = "2d"; + + iommus = <&mc TEGRA_SWGROUP_G2>; };
gr3d@54180000 { @@ -172,6 +183,9 @@ resets = <&tegra_car 24>, <&tegra_car 98>; reset-names = "3d", "3d2"; + + iommus = <&mc TEGRA_SWGROUP_NV>, + <&mc TEGRA_SWGROUP_NV2>; };
dc@54200000 {
On Fri, May 04, 2018 at 02:47:22AM +0300, Dmitry Osipenko wrote:
Enable IOMMU support for Host1x and its clients.
Signed-off-by: Dmitry Osipenko digetx@gmail.com
arch/arm/boot/dts/tegra30.dtsi | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
Applied, thanks.
Thierry
Enable IOMMU support for Host1x and its clients.
Signed-off-by: Dmitry Osipenko digetx@gmail.com --- arch/arm/boot/dts/tegra114.dtsi | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi index 0e4a13295d8a..84c4358dacac 100644 --- a/arch/arm/boot/dts/tegra114.dtsi +++ b/arch/arm/boot/dts/tegra114.dtsi @@ -19,6 +19,7 @@ clocks = <&tegra_car TEGRA114_CLK_HOST1X>; resets = <&tegra_car 28>; reset-names = "host1x"; + iommus = <&mc TEGRA_SWGROUP_HC>;
#address-cells = <1>; #size-cells = <1>; @@ -32,6 +33,8 @@ clocks = <&tegra_car TEGRA114_CLK_GR2D>; resets = <&tegra_car 21>; reset-names = "2d"; + + iommus = <&mc TEGRA_SWGROUP_G2>; };
gr3d@54180000 { @@ -40,6 +43,8 @@ clocks = <&tegra_car TEGRA114_CLK_GR3D>; resets = <&tegra_car 24>; reset-names = "3d"; + + iommus = <&mc TEGRA_SWGROUP_NV>; };
dc@54200000 {
On Fri, May 04, 2018 at 02:47:23AM +0300, Dmitry Osipenko wrote:
Enable IOMMU support for Host1x and its clients.
Signed-off-by: Dmitry Osipenko digetx@gmail.com
arch/arm/boot/dts/tegra114.dtsi | 5 +++++ 1 file changed, 5 insertions(+)
Applied, thanks.
Thierry
On Fri, May 04, 2018 at 02:47:18AM +0300, Dmitry Osipenko wrote:
Hi,
This series enables IOMMU support for 2d/3d HW on Tegra30/114, as a result userspace that uses 2d/3d could work with the active IOMMU.
Dmitry Osipenko (5): drm/tegra: dc: Balance IOMMU group refcounting drm/tegra: gr2d: Add IOMMU support drm/tegra: gr3d: Add IOMMU support ARM: dts: tegra30: Add IOMMU nodes to Host1x and its clients ARM: dts: tegra114: Add IOMMU nodes to Host1x and its clients
arch/arm/boot/dts/tegra114.dtsi | 5 +++++ arch/arm/boot/dts/tegra30.dtsi | 14 +++++++++++++ drivers/gpu/drm/tegra/dc.c | 35 ++++++++++++++++----------------- drivers/gpu/drm/tegra/dc.h | 2 +- drivers/gpu/drm/tegra/drm.h | 2 +- drivers/gpu/drm/tegra/gr2d.c | 31 +++++++++++++++++++++++++++-- drivers/gpu/drm/tegra/gr3d.c | 27 +++++++++++++++++++++++++ 7 files changed, 94 insertions(+), 22 deletions(-)
Overall I think this is great. No need to resend for the two comments on patch 1, I can fix those up when I apply if you have no objections.
Thierry
On 04.05.2018 13:56, Thierry Reding wrote:
On Fri, May 04, 2018 at 02:47:18AM +0300, Dmitry Osipenko wrote:
Hi,
This series enables IOMMU support for 2d/3d HW on Tegra30/114, as a result userspace that uses 2d/3d could work with the active IOMMU.
Dmitry Osipenko (5): drm/tegra: dc: Balance IOMMU group refcounting drm/tegra: gr2d: Add IOMMU support drm/tegra: gr3d: Add IOMMU support ARM: dts: tegra30: Add IOMMU nodes to Host1x and its clients ARM: dts: tegra114: Add IOMMU nodes to Host1x and its clients
arch/arm/boot/dts/tegra114.dtsi | 5 +++++ arch/arm/boot/dts/tegra30.dtsi | 14 +++++++++++++ drivers/gpu/drm/tegra/dc.c | 35 ++++++++++++++++----------------- drivers/gpu/drm/tegra/dc.h | 2 +- drivers/gpu/drm/tegra/drm.h | 2 +- drivers/gpu/drm/tegra/gr2d.c | 31 +++++++++++++++++++++++++++-- drivers/gpu/drm/tegra/gr3d.c | 27 +++++++++++++++++++++++++ 7 files changed, 94 insertions(+), 22 deletions(-)
Overall I think this is great. No need to resend for the two comments on patch 1, I can fix those up when I apply if you have no objections.
No objections from me, thanks.
dri-devel@lists.freedesktop.org