diff options
author | Konsta Holtta <kholtta@nvidia.com> | 2014-09-10 10:23:31 -0400 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:11:19 -0400 |
commit | ad178917259b30330e8432e2cd33d50c03e9602b (patch) | |
tree | 194c769517bfa3707bd0fb8f0b89e5d00f4ea5f4 /drivers/gpu/nvgpu/gk20a/channel_gk20a.c | |
parent | 91ada92f61eeb41026a678b58863acafa7a33674 (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/gk20a/channel_gk20a.c')
-rw-r--r-- | drivers/gpu/nvgpu/gk20a/channel_gk20a.c | 121 |
1 files changed, 121 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 | |||
1900 | static 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 | |||
1912 | static 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 | |||
1924 | static 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 | |||
1937 | static 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 | |||
1969 | void 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 | |||
1986 | unsigned 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 | |||
1894 | static int gk20a_channel_set_priority(struct channel_gk20a *ch, | 2011 | static 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; |