summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu
diff options
context:
space:
mode:
authorKonsta Holtta <kholtta@nvidia.com>2014-09-10 10:23:31 -0400
committerDan Willemsen <dwillemsen@nvidia.com>2015-03-18 15:11:19 -0400
commitad178917259b30330e8432e2cd33d50c03e9602b (patch)
tree194c769517bfa3707bd0fb8f0b89e5d00f4ea5f4 /drivers/gpu/nvgpu
parent91ada92f61eeb41026a678b58863acafa7a33674 (diff)
gpu: nvgpu: implement poll() for semaphores
Add poll interface and control ioctls for waiting for GPU job completion via semaphores. Poll on a gk20a channel file waits for events from pending semaphore interrupts (stalling) of that channel. New ioctls enable and disable the events, and clear a single interrupt event so that next poll doesn't wake up for it again. Bug 1528781 Change-Id: I5c6238966b5d0900c8ab263c6a7f8f2611901f33 Signed-off-by: Konsta Holtta <kholtta@nvidia.com> Reviewed-on: http://git-master/r/497750 Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com> Tested-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu/nvgpu')
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.c121
-rw-r--r--drivers/gpu/nvgpu/gk20a/channel_gk20a.h13
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c1
-rw-r--r--drivers/gpu/nvgpu/gk20a/gr_gk20a.c1
4 files changed, 136 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
index 1e71c1c7..2c6013c8 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.c
@@ -773,6 +773,10 @@ struct channel_gk20a *gk20a_open_new_channel(struct gk20a *g)
773 init_waitqueue_head(&ch->semaphore_wq); 773 init_waitqueue_head(&ch->semaphore_wq);
774 init_waitqueue_head(&ch->submit_wq); 774 init_waitqueue_head(&ch->submit_wq);
775 775
776 mutex_init(&ch->poll_events.lock);
777 ch->poll_events.events_enabled = false;
778 ch->poll_events.num_pending_events = 0;
779
776 return ch; 780 return ch;
777} 781}
778 782
@@ -1891,6 +1895,119 @@ notif_clean_up:
1891 return ret; 1895 return ret;
1892} 1896}
1893 1897
1898/* poll events for semaphores */
1899
1900static void gk20a_channel_events_enable(struct channel_gk20a_poll_events *ev)
1901{
1902 gk20a_dbg_fn("");
1903
1904 mutex_lock(&ev->lock);
1905
1906 ev->events_enabled = true;
1907 ev->num_pending_events = 0;
1908
1909 mutex_unlock(&ev->lock);
1910}
1911
1912static void gk20a_channel_events_disable(struct channel_gk20a_poll_events *ev)
1913{
1914 gk20a_dbg_fn("");
1915
1916 mutex_lock(&ev->lock);
1917
1918 ev->events_enabled = false;
1919 ev->num_pending_events = 0;
1920
1921 mutex_unlock(&ev->lock);
1922}
1923
1924static void gk20a_channel_events_clear(struct channel_gk20a_poll_events *ev)
1925{
1926 gk20a_dbg_fn("");
1927
1928 mutex_lock(&ev->lock);
1929
1930 if (ev->events_enabled &&
1931 ev->num_pending_events > 0)
1932 ev->num_pending_events--;
1933
1934 mutex_unlock(&ev->lock);
1935}
1936
1937static int gk20a_channel_events_ctrl(struct channel_gk20a *ch,
1938 struct nvhost_channel_events_ctrl_args *args)
1939{
1940 int ret = 0;
1941
1942 gk20a_dbg(gpu_dbg_fn | gpu_dbg_info,
1943 "channel events ctrl cmd %d", args->cmd);
1944
1945 switch (args->cmd) {
1946 case NVHOST_IOCTL_CHANNEL_EVENTS_CTRL_CMD_ENABLE:
1947 gk20a_channel_events_enable(&ch->poll_events);
1948 break;
1949
1950 case NVHOST_IOCTL_CHANNEL_EVENTS_CTRL_CMD_DISABLE:
1951 gk20a_channel_events_disable(&ch->poll_events);
1952 break;
1953
1954 case NVHOST_IOCTL_CHANNEL_EVENTS_CTRL_CMD_CLEAR:
1955 gk20a_channel_events_clear(&ch->poll_events);
1956 break;
1957
1958 default:
1959 gk20a_err(dev_from_gk20a(ch->g),
1960 "unrecognized channel events ctrl cmd: 0x%x",
1961 args->cmd);
1962 ret = -EINVAL;
1963 break;
1964 }
1965
1966 return ret;
1967}
1968
1969void gk20a_channel_event(struct channel_gk20a *ch)
1970{
1971 mutex_lock(&ch->poll_events.lock);
1972
1973 if (ch->poll_events.events_enabled) {
1974 gk20a_dbg_info("posting event on channel id %d",
1975 ch->hw_chid);
1976 gk20a_dbg_info("%d channel events pending",
1977 ch->poll_events.num_pending_events);
1978
1979 ch->poll_events.num_pending_events++;
1980 /* not waking up here, caller does that */
1981 }
1982
1983 mutex_unlock(&ch->poll_events.lock);
1984}
1985
1986unsigned int gk20a_channel_poll(struct file *filep, poll_table *wait)
1987{
1988 unsigned int mask = 0;
1989 struct channel_gk20a *ch = filep->private_data;
1990
1991 gk20a_dbg(gpu_dbg_fn | gpu_dbg_info, "");
1992
1993 poll_wait(filep, &ch->semaphore_wq, wait);
1994
1995 mutex_lock(&ch->poll_events.lock);
1996
1997 if (ch->poll_events.events_enabled &&
1998 ch->poll_events.num_pending_events > 0) {
1999 gk20a_dbg_info("found pending event on channel id %d",
2000 ch->hw_chid);
2001 gk20a_dbg_info("%d channel events pending",
2002 ch->poll_events.num_pending_events);
2003 mask = (POLLPRI | POLLIN);
2004 }
2005
2006 mutex_unlock(&ch->poll_events.lock);
2007
2008 return mask;
2009}
2010
1894static int gk20a_channel_set_priority(struct channel_gk20a *ch, 2011static int gk20a_channel_set_priority(struct channel_gk20a *ch,
1895 u32 priority) 2012 u32 priority)
1896{ 2013{
@@ -2314,6 +2431,10 @@ long gk20a_channel_ioctl(struct file *filp,
2314 err = gk20a_fifo_force_reset_ch(ch, true); 2431 err = gk20a_fifo_force_reset_ch(ch, true);
2315 gk20a_idle(dev); 2432 gk20a_idle(dev);
2316 break; 2433 break;
2434 case NVHOST_IOCTL_CHANNEL_EVENTS_CTRL:
2435 err = gk20a_channel_events_ctrl(ch,
2436 (struct nvhost_channel_events_ctrl_args *)buf);
2437 break;
2317 default: 2438 default:
2318 dev_err(&dev->dev, "unrecognized ioctl cmd: 0x%x", cmd); 2439 dev_err(&dev->dev, "unrecognized ioctl cmd: 0x%x", cmd);
2319 err = -ENOTTY; 2440 err = -ENOTTY;
diff --git a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
index 37ca8244..bb9f314c 100644
--- a/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/channel_gk20a.h
@@ -26,6 +26,8 @@
26#include <linux/wait.h> 26#include <linux/wait.h>
27#include <linux/mutex.h> 27#include <linux/mutex.h>
28#include <linux/nvhost_ioctl.h> 28#include <linux/nvhost_ioctl.h>
29#include <linux/poll.h>
30
29struct gk20a; 31struct gk20a;
30struct gr_gk20a; 32struct gr_gk20a;
31struct dbg_session_gk20a; 33struct dbg_session_gk20a;
@@ -74,6 +76,12 @@ struct channel_gk20a_job {
74 struct list_head list; 76 struct list_head list;
75}; 77};
76 78
79struct channel_gk20a_poll_events {
80 struct mutex lock;
81 bool events_enabled;
82 int num_pending_events;
83};
84
77/* this is the priv element of struct nvhost_channel */ 85/* this is the priv element of struct nvhost_channel */
78struct channel_gk20a { 86struct channel_gk20a {
79 struct gk20a *g; 87 struct gk20a *g;
@@ -148,6 +156,9 @@ struct channel_gk20a {
148#ifdef CONFIG_TEGRA_GR_VIRTUALIZATION 156#ifdef CONFIG_TEGRA_GR_VIRTUALIZATION
149 u64 virt_ctx; 157 u64 virt_ctx;
150#endif 158#endif
159
160 /* event support */
161 struct channel_gk20a_poll_events poll_events;
151}; 162};
152 163
153static inline bool gk20a_channel_as_bound(struct channel_gk20a *ch) 164static inline bool gk20a_channel_as_bound(struct channel_gk20a *ch)
@@ -180,6 +191,8 @@ long gk20a_channel_ioctl(struct file *filp,
180int gk20a_channel_release(struct inode *inode, struct file *filp); 191int gk20a_channel_release(struct inode *inode, struct file *filp);
181struct channel_gk20a *gk20a_get_channel_from_file(int fd); 192struct channel_gk20a *gk20a_get_channel_from_file(int fd);
182void gk20a_channel_update(struct channel_gk20a *c, int nr_completed); 193void gk20a_channel_update(struct channel_gk20a *c, int nr_completed);
194unsigned int gk20a_channel_poll(struct file *filep, poll_table *wait);
195void gk20a_channel_event(struct channel_gk20a *ch);
183 196
184void gk20a_init_channel(struct gpu_ops *gops); 197void gk20a_init_channel(struct gpu_ops *gops);
185 198
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index 7d744f42..acae38aa 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -100,6 +100,7 @@ static const struct file_operations gk20a_channel_ops = {
100 .compat_ioctl = gk20a_channel_ioctl, 100 .compat_ioctl = gk20a_channel_ioctl,
101#endif 101#endif
102 .unlocked_ioctl = gk20a_channel_ioctl, 102 .unlocked_ioctl = gk20a_channel_ioctl,
103 .poll = gk20a_channel_poll,
103}; 104};
104 105
105static const struct file_operations gk20a_ctrl_ops = { 106static const struct file_operations gk20a_ctrl_ops = {
diff --git a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
index f5c3bd62..db655c32 100644
--- a/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gr_gk20a.c
@@ -5075,6 +5075,7 @@ static int gk20a_gr_handle_semaphore_pending(struct gk20a *g,
5075 struct fifo_gk20a *f = &g->fifo; 5075 struct fifo_gk20a *f = &g->fifo;
5076 struct channel_gk20a *ch = &f->channel[isr_data->chid]; 5076 struct channel_gk20a *ch = &f->channel[isr_data->chid];
5077 5077
5078 gk20a_channel_event(ch);
5078 wake_up(&ch->semaphore_wq); 5079 wake_up(&ch->semaphore_wq);
5079 5080
5080 return 0; 5081 return 0;