From 1691cf160048c0753036d0b3fad7f239234dab56 Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Sat, 28 May 2016 07:04:38 +0000 Subject: btrfs: Use __u64 in exported linux/btrfs.h. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes this build error. /usr/include/linux/btrfs.h:121:3: error: unknown type name ‘u64’ u64 devid; ^~~ Fixes: 6b526ed70cf1 ("btrfs: introduce device delete by devid") Signed-off-by: Vinson Lee Signed-off-by: David Sterba --- include/uapi/linux/btrfs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/uapi') diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h index 23c6960e94a4..2bdd1e3e7007 100644 --- a/include/uapi/linux/btrfs.h +++ b/include/uapi/linux/btrfs.h @@ -118,7 +118,7 @@ struct btrfs_ioctl_vol_args_v2 { }; union { char name[BTRFS_SUBVOL_NAME_MAX + 1]; - u64 devid; + __u64 devid; }; }; -- cgit v1.2.3 From 0358ccc8ffd8d9b76992b8deab58fb9a721fb18a Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Tue, 31 May 2016 09:12:04 -0400 Subject: ALSA: uapi: Add three missing header files to Kbuild file include/uapi/sound/Kbuild was missing the inclusion of three header files in that directory. Signed-off-by: Robert P. J. Day Signed-off-by: Takashi Iwai --- include/uapi/sound/Kbuild | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/sound/Kbuild b/include/uapi/sound/Kbuild index a7f27704f980..691984cb0b91 100644 --- a/include/uapi/sound/Kbuild +++ b/include/uapi/sound/Kbuild @@ -1,5 +1,6 @@ # UAPI Header export list header-y += asequencer.h +header-y += asoc.h header-y += asound.h header-y += asound_fm.h header-y += compress_offload.h @@ -10,3 +11,5 @@ header-y += hdsp.h header-y += hdspm.h header-y += sb16_csp.h header-y += sfnt_info.h +header-y += tlv.h +header-y += usb_stream.h -- cgit v1.2.3 From 7b01b8e847d00cf9cf0c2c3aa8fdfc4126dca024 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 6 Jun 2016 16:08:41 +0100 Subject: gtp: #define _UAPI_LINUX_GTP_H_ and not _UAPI_LINUX_GTP_H__ Fix clang build warning: ./include/uapi/linux/gtp.h:1:9: warning: '_UAPI_LINUX_GTP_H_' is used as a header guard here, followed by #define of a different macro [-Wheader-guard] fix by defining _UAPI_LINUX_GTP_H_ and not _UAPI_LINUX_GTP_H__ Signed-off-by: Colin Ian King Acked-by: Pablo Neira Ayuso Signed-off-by: David S. Miller --- include/uapi/linux/gtp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/uapi') diff --git a/include/uapi/linux/gtp.h b/include/uapi/linux/gtp.h index ca1054dd8249..72a04a0e8cce 100644 --- a/include/uapi/linux/gtp.h +++ b/include/uapi/linux/gtp.h @@ -1,5 +1,5 @@ #ifndef _UAPI_LINUX_GTP_H_ -#define _UAPI_LINUX_GTP_H__ +#define _UAPI_LINUX_GTP_H_ enum gtp_genl_cmds { GTP_CMD_NEWPDP, -- cgit v1.2.3 From 8f45927c3cae4db85887700e5415286f766cbaf9 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 17 Jun 2016 12:54:18 +0200 Subject: netfilter: xt_SYNPROXY: add missing header to Kbuild Matt Whitlock says: Without this line, the file xt_SYNPROXY.h does not get installed in /usr/include/linux/netfilter/, and thus user-space programs cannot make use of it. Reported-by: Matt Whitlock Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/Kbuild | 1 + 1 file changed, 1 insertion(+) (limited to 'include/uapi') diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild index 1d973d2ba417..cd26d7a0fd07 100644 --- a/include/uapi/linux/netfilter/Kbuild +++ b/include/uapi/linux/netfilter/Kbuild @@ -33,6 +33,7 @@ header-y += xt_NFLOG.h header-y += xt_NFQUEUE.h header-y += xt_RATEEST.h header-y += xt_SECMARK.h +header-y += xt_SYNPROXY.h header-y += xt_TCPMSS.h header-y += xt_TCPOPTSTRIP.h header-y += xt_TEE.h -- cgit v1.2.3 From 1463847e93fe693e89c52b03ab4ede6800d717c1 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 17 Jun 2016 12:54:18 +0200 Subject: netfilter: xt_SYNPROXY: include missing ./usr/include/linux/netfilter/xt_SYNPROXY.h:11: found __[us]{8,16,32,64} type without #include Reported-by: kbuild test robot Signed-off-by: Pablo Neira Ayuso --- include/uapi/linux/netfilter/xt_SYNPROXY.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/linux/netfilter/xt_SYNPROXY.h b/include/uapi/linux/netfilter/xt_SYNPROXY.h index 2d59fbaa93c6..ca67e61d2a61 100644 --- a/include/uapi/linux/netfilter/xt_SYNPROXY.h +++ b/include/uapi/linux/netfilter/xt_SYNPROXY.h @@ -1,6 +1,8 @@ #ifndef _XT_SYNPROXY_H #define _XT_SYNPROXY_H +#include + #define XT_SYNPROXY_OPT_MSS 0x01 #define XT_SYNPROXY_OPT_WSCALE 0x02 #define XT_SYNPROXY_OPT_SACK_PERM 0x04 -- cgit v1.2.3 From 3720b69bafe9ccb989b9a8604f3e3f89b3610685 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sat, 18 Jun 2016 10:10:26 -0700 Subject: Input: add BUS_CEC type Inputs can come in over the HDMI CEC bus, so add a new type for this. Signed-off-by: Hans Verkuil Signed-off-by: Dmitry Torokhov --- include/uapi/linux/input.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/uapi') diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index 01113841190d..c51494119817 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -247,6 +247,7 @@ struct input_mask { #define BUS_ATARI 0x1B #define BUS_SPI 0x1C #define BUS_RMI 0x1D +#define BUS_CEC 0x1E /* * MT_TOOL types -- cgit v1.2.3 From 488326947cd1f038da8d2c9068a0d07b913b7983 Mon Sep 17 00:00:00 2001 From: Kamil Debski Date: Sat, 18 Jun 2016 10:10:56 -0700 Subject: Input: add HDMI CEC specific keycodes Add HDMI CEC specific keycodes to the keycodes definition. Signed-off-by: Kamil Debski Signed-off-by: Hans Verkuil Signed-off-by: Dmitry Torokhov --- include/uapi/linux/input-event-codes.h | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'include/uapi') diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index 87cf351bab03..737fa32faad4 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -611,6 +611,37 @@ #define KEY_KBDINPUTASSIST_ACCEPT 0x264 #define KEY_KBDINPUTASSIST_CANCEL 0x265 +/* Diagonal movement keys */ +#define KEY_RIGHT_UP 0x266 +#define KEY_RIGHT_DOWN 0x267 +#define KEY_LEFT_UP 0x268 +#define KEY_LEFT_DOWN 0x269 + +#define KEY_ROOT_MENU 0x26a /* Show Device's Root Menu */ +/* Show Top Menu of the Media (e.g. DVD) */ +#define KEY_MEDIA_TOP_MENU 0x26b +#define KEY_NUMERIC_11 0x26c +#define KEY_NUMERIC_12 0x26d +/* + * Toggle Audio Description: refers to an audio service that helps blind and + * visually impaired consumers understand the action in a program. Note: in + * some countries this is referred to as "Video Description". + */ +#define KEY_AUDIO_DESC 0x26e +#define KEY_3D_MODE 0x26f +#define KEY_NEXT_FAVORITE 0x270 +#define KEY_STOP_RECORD 0x271 +#define KEY_PAUSE_RECORD 0x272 +#define KEY_VOD 0x273 /* Video on Demand */ +#define KEY_UNMUTE 0x274 +#define KEY_FASTREVERSE 0x275 +#define KEY_SLOWREVERSE 0x276 +/* + * Control a data application associated with the currently viewed channel, + * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.) + */ +#define KEY_DATA 0x275 + #define BTN_TRIGGER_HAPPY 0x2c0 #define BTN_TRIGGER_HAPPY1 0x2c0 #define BTN_TRIGGER_HAPPY2 0x2c1 -- cgit v1.2.3 From 9a9b6aa6a8759c83024627d681eff982d6ee03b7 Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 28 Jun 2016 10:32:00 -0700 Subject: Input: add SW_PEN_INSERTED define Some devices with a pen may have a switch that can be used to detect when the pen is inserted or removed to a slot on the device. Let's add a define to the input event codes so that everyone can be on the same page for what event we should generate when the pen is inserted or removed. In general the pen switch could be used by the software on the device to kick off any number of actions when the pen is inserted or removed. Signed-off-by: Douglas Anderson Signed-off-by: Dmitry Torokhov --- include/uapi/linux/input-event-codes.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/uapi') diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index 737fa32faad4..d6d071fc3c56 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -780,6 +780,7 @@ #define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */ #define SW_LINEIN_INSERT 0x0d /* set = inserted */ #define SW_MUTE_DEVICE 0x0e /* set = device disabled */ +#define SW_PEN_INSERTED 0x0f /* set = pen inserted */ #define SW_MAX 0x0f #define SW_CNT (SW_MAX+1) -- cgit v1.2.3 From 5c672ab3f0ee0f78f7acad183f34db0f8781a200 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 30 Jun 2016 13:10:49 +0200 Subject: fuse: serialize dirops by default Negotiate with userspace filesystems whether they support parallel readdir and lookup. Disable parallelism by default for fear of breaking fuse filesystems. Signed-off-by: Miklos Szeredi Fixes: 9902af79c01a ("parallel lookups: actual switch to rwsem") Fixes: d9b3dbdcfd62 ("fuse: switch to ->iterate_shared()") --- fs/fuse/dir.c | 4 ++++ fs/fuse/fuse_i.h | 9 +++++++++ fs/fuse/inode.c | 19 ++++++++++++++++++- include/uapi/linux/fuse.h | 7 ++++++- 4 files changed, 37 insertions(+), 2 deletions(-) (limited to 'include/uapi') diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index ccd4971cc6c1..264f07c7754e 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -341,8 +341,10 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, struct dentry *newent; bool outarg_valid = true; + fuse_lock_inode(dir); err = fuse_lookup_name(dir->i_sb, get_node_id(dir), &entry->d_name, &outarg, &inode); + fuse_unlock_inode(dir); if (err == -ENOENT) { outarg_valid = false; err = 0; @@ -1341,7 +1343,9 @@ static int fuse_readdir(struct file *file, struct dir_context *ctx) fuse_read_fill(req, file, ctx->pos, PAGE_SIZE, FUSE_READDIR); } + fuse_lock_inode(inode); fuse_request_send(fc, req); + fuse_unlock_inode(inode); nbytes = req->out.args[0].size; err = req->out.h.error; fuse_put_request(fc, req); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index eddbe02c4028..929c383432b0 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -110,6 +110,9 @@ struct fuse_inode { /** Miscellaneous bits describing inode state */ unsigned long state; + + /** Lock for serializing lookup and readdir for back compatibility*/ + struct mutex mutex; }; /** FUSE inode state bits */ @@ -540,6 +543,9 @@ struct fuse_conn { /** write-back cache policy (default is write-through) */ unsigned writeback_cache:1; + /** allow parallel lookups and readdir (default is serialized) */ + unsigned parallel_dirops:1; + /* * The following bitfields are only for optimization purposes * and hence races in setting them will not cause malfunction @@ -956,4 +962,7 @@ int fuse_do_setattr(struct inode *inode, struct iattr *attr, void fuse_set_initialized(struct fuse_conn *fc); +void fuse_unlock_inode(struct inode *inode); +void fuse_lock_inode(struct inode *inode); + #endif /* _FS_FUSE_I_H */ diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 1ce67668a8e1..9961d8432ce3 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -97,6 +97,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) INIT_LIST_HEAD(&fi->queued_writes); INIT_LIST_HEAD(&fi->writepages); init_waitqueue_head(&fi->page_waitq); + mutex_init(&fi->mutex); fi->forget = fuse_alloc_forget(); if (!fi->forget) { kmem_cache_free(fuse_inode_cachep, inode); @@ -117,6 +118,7 @@ static void fuse_destroy_inode(struct inode *inode) struct fuse_inode *fi = get_fuse_inode(inode); BUG_ON(!list_empty(&fi->write_files)); BUG_ON(!list_empty(&fi->queued_writes)); + mutex_destroy(&fi->mutex); kfree(fi->forget); call_rcu(&inode->i_rcu, fuse_i_callback); } @@ -351,6 +353,18 @@ int fuse_reverse_inval_inode(struct super_block *sb, u64 nodeid, return 0; } +void fuse_lock_inode(struct inode *inode) +{ + if (!get_fuse_conn(inode)->parallel_dirops) + mutex_lock(&get_fuse_inode(inode)->mutex); +} + +void fuse_unlock_inode(struct inode *inode) +{ + if (!get_fuse_conn(inode)->parallel_dirops) + mutex_unlock(&get_fuse_inode(inode)->mutex); +} + static void fuse_umount_begin(struct super_block *sb) { fuse_abort_conn(get_fuse_conn_super(sb)); @@ -898,6 +912,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) fc->async_dio = 1; if (arg->flags & FUSE_WRITEBACK_CACHE) fc->writeback_cache = 1; + if (arg->flags & FUSE_PARALLEL_DIROPS) + fc->parallel_dirops = 1; if (arg->time_gran && arg->time_gran <= 1000000000) fc->sb->s_time_gran = arg->time_gran; } else { @@ -928,7 +944,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO | - FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT; + FUSE_WRITEBACK_CACHE | FUSE_NO_OPEN_SUPPORT | + FUSE_PARALLEL_DIROPS; req->in.h.opcode = FUSE_INIT; req->in.numargs = 1; req->in.args[0].size = sizeof(*arg); diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index 5974fae54e12..27e17363263a 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -105,6 +105,9 @@ * * 7.24 * - add FUSE_LSEEK for SEEK_HOLE and SEEK_DATA support + * + * 7.25 + * - add FUSE_PARALLEL_DIROPS */ #ifndef _LINUX_FUSE_H @@ -140,7 +143,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 24 +#define FUSE_KERNEL_MINOR_VERSION 25 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 @@ -234,6 +237,7 @@ struct fuse_file_lock { * FUSE_ASYNC_DIO: asynchronous direct I/O submission * FUSE_WRITEBACK_CACHE: use writeback cache for buffered writes * FUSE_NO_OPEN_SUPPORT: kernel supports zero-message opens + * FUSE_PARALLEL_DIROPS: allow parallel lookups and readdir */ #define FUSE_ASYNC_READ (1 << 0) #define FUSE_POSIX_LOCKS (1 << 1) @@ -253,6 +257,7 @@ struct fuse_file_lock { #define FUSE_ASYNC_DIO (1 << 15) #define FUSE_WRITEBACK_CACHE (1 << 16) #define FUSE_NO_OPEN_SUPPORT (1 << 17) +#define FUSE_PARALLEL_DIROPS (1 << 18) /** * CUSE INIT request/reply flags -- cgit v1.2.3 From 000cab9a61ea9e8dc42144e39a6eb8333a402b86 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Sun, 12 Jun 2016 15:44:44 +0800 Subject: drm/amdgpu: factor out the AMDGPU_INFO_FW_VERSION case branch into amdgpu_firmware_info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The new amdgpu_firmware_info function will be used on amdgpu firmware version debugfs. Suggested-by: Christian König Signed-off-by: Huang Rui Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 116 ++++++++++++++++++-------------- include/uapi/drm/amdgpu_drm.h | 32 ++++----- 2 files changed, 81 insertions(+), 67 deletions(-) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index d851ea15059f..56c857f6e7ca 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -142,6 +142,65 @@ out: return r; } +static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, + struct drm_amdgpu_query_fw *query_fw, + struct amdgpu_device *adev) +{ + switch (query_fw->fw_type) { + case AMDGPU_INFO_FW_VCE: + fw_info->ver = adev->vce.fw_version; + fw_info->feature = adev->vce.fb_version; + break; + case AMDGPU_INFO_FW_UVD: + fw_info->ver = adev->uvd.fw_version; + fw_info->feature = 0; + break; + case AMDGPU_INFO_FW_GMC: + fw_info->ver = adev->mc.fw_version; + fw_info->feature = 0; + break; + case AMDGPU_INFO_FW_GFX_ME: + fw_info->ver = adev->gfx.me_fw_version; + fw_info->feature = adev->gfx.me_feature_version; + break; + case AMDGPU_INFO_FW_GFX_PFP: + fw_info->ver = adev->gfx.pfp_fw_version; + fw_info->feature = adev->gfx.pfp_feature_version; + break; + case AMDGPU_INFO_FW_GFX_CE: + fw_info->ver = adev->gfx.ce_fw_version; + fw_info->feature = adev->gfx.ce_feature_version; + break; + case AMDGPU_INFO_FW_GFX_RLC: + fw_info->ver = adev->gfx.rlc_fw_version; + fw_info->feature = adev->gfx.rlc_feature_version; + break; + case AMDGPU_INFO_FW_GFX_MEC: + if (query_fw->index == 0) { + fw_info->ver = adev->gfx.mec_fw_version; + fw_info->feature = adev->gfx.mec_feature_version; + } else if (query_fw->index == 1) { + fw_info->ver = adev->gfx.mec2_fw_version; + fw_info->feature = adev->gfx.mec2_feature_version; + } else + return -EINVAL; + break; + case AMDGPU_INFO_FW_SMC: + fw_info->ver = adev->pm.fw_version; + fw_info->feature = 0; + break; + case AMDGPU_INFO_FW_SDMA: + if (query_fw->index >= adev->sdma.num_instances) + return -EINVAL; + fw_info->ver = adev->sdma.instance[query_fw->index].fw_version; + fw_info->feature = adev->sdma.instance[query_fw->index].feature_version; + break; + default: + return -EINVAL; + } + return 0; +} + /* * Userspace get information ioctl */ @@ -292,63 +351,16 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0; case AMDGPU_INFO_FW_VERSION: { struct drm_amdgpu_info_firmware fw_info; + int ret; /* We only support one instance of each IP block right now. */ if (info->query_fw.ip_instance != 0) return -EINVAL; - switch (info->query_fw.fw_type) { - case AMDGPU_INFO_FW_VCE: - fw_info.ver = adev->vce.fw_version; - fw_info.feature = adev->vce.fb_version; - break; - case AMDGPU_INFO_FW_UVD: - fw_info.ver = adev->uvd.fw_version; - fw_info.feature = 0; - break; - case AMDGPU_INFO_FW_GMC: - fw_info.ver = adev->mc.fw_version; - fw_info.feature = 0; - break; - case AMDGPU_INFO_FW_GFX_ME: - fw_info.ver = adev->gfx.me_fw_version; - fw_info.feature = adev->gfx.me_feature_version; - break; - case AMDGPU_INFO_FW_GFX_PFP: - fw_info.ver = adev->gfx.pfp_fw_version; - fw_info.feature = adev->gfx.pfp_feature_version; - break; - case AMDGPU_INFO_FW_GFX_CE: - fw_info.ver = adev->gfx.ce_fw_version; - fw_info.feature = adev->gfx.ce_feature_version; - break; - case AMDGPU_INFO_FW_GFX_RLC: - fw_info.ver = adev->gfx.rlc_fw_version; - fw_info.feature = adev->gfx.rlc_feature_version; - break; - case AMDGPU_INFO_FW_GFX_MEC: - if (info->query_fw.index == 0) { - fw_info.ver = adev->gfx.mec_fw_version; - fw_info.feature = adev->gfx.mec_feature_version; - } else if (info->query_fw.index == 1) { - fw_info.ver = adev->gfx.mec2_fw_version; - fw_info.feature = adev->gfx.mec2_feature_version; - } else - return -EINVAL; - break; - case AMDGPU_INFO_FW_SMC: - fw_info.ver = adev->pm.fw_version; - fw_info.feature = 0; - break; - case AMDGPU_INFO_FW_SDMA: - if (info->query_fw.index >= adev->sdma.num_instances) - return -EINVAL; - fw_info.ver = adev->sdma.instance[info->query_fw.index].fw_version; - fw_info.feature = adev->sdma.instance[info->query_fw.index].feature_version; - break; - default: - return -EINVAL; - } + ret = amdgpu_firmware_info(&fw_info, &info->query_fw, adev); + if (ret) + return ret; + return copy_to_user(out, &fw_info, min((size_t)size, sizeof(fw_info))) ? -EFAULT : 0; } diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h index cdecf87576e8..462246aa200e 100644 --- a/include/uapi/drm/amdgpu_drm.h +++ b/include/uapi/drm/amdgpu_drm.h @@ -487,6 +487,22 @@ struct drm_amdgpu_cs_chunk_data { #define AMDGPU_INFO_MMR_SH_INDEX_SHIFT 8 #define AMDGPU_INFO_MMR_SH_INDEX_MASK 0xff +struct drm_amdgpu_query_fw { + /** AMDGPU_INFO_FW_* */ + __u32 fw_type; + /** + * Index of the IP if there are more IPs of + * the same type. + */ + __u32 ip_instance; + /** + * Index of the engine. Whether this is used depends + * on the firmware type. (e.g. MEC, SDMA) + */ + __u32 index; + __u32 _pad; +}; + /* Input structure for the INFO ioctl */ struct drm_amdgpu_info { /* Where the return value will be stored */ @@ -522,21 +538,7 @@ struct drm_amdgpu_info { __u32 flags; } read_mmr_reg; - struct { - /** AMDGPU_INFO_FW_* */ - __u32 fw_type; - /** - * Index of the IP if there are more IPs of - * the same type. - */ - __u32 ip_instance; - /** - * Index of the engine. Whether this is used depends - * on the firmware type. (e.g. MEC, SDMA) - */ - __u32 index; - __u32 _pad; - } query_fw; + struct drm_amdgpu_query_fw query_fw; }; }; -- cgit v1.2.3 From af713795c59fea36161a7debf97dbc10bf652cf7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 1 Jul 2016 13:10:38 -0700 Subject: drm/vc4: Add a getparam ioctl for getting the V3D identity regs. As I extend the driver to support different V3D revisions, userspace needs to know what version it's targeting. This is most easily detected using the V3D identity registers. v2: Make sure V3D is runtime PM on when reading the registers. v3: Switch to a 64-bit param value (suggested by Rob Clark in review) Signed-off-by: Eric Anholt Acked-by: Daniel Vetter (v2) Reviewed-by: Rob Clark (v3, over irc) --- drivers/gpu/drm/vc4/vc4_drv.c | 42 ++++++++++++++++++++++++++++++++++++++++++ include/uapi/drm/vc4_drm.h | 12 ++++++++++++ 2 files changed, 54 insertions(+) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 2f30214ee810..047d7a265ceb 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "drm_fb_cma_helper.h" #include "uapi/drm/vc4_drm.h" @@ -43,6 +44,46 @@ void __iomem *vc4_ioremap_regs(struct platform_device *dev, int index) return map; } +static int vc4_get_param_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct vc4_dev *vc4 = to_vc4_dev(dev); + struct drm_vc4_get_param *args = data; + int ret; + + if (args->pad != 0) + return -EINVAL; + + switch (args->param) { + case DRM_VC4_PARAM_V3D_IDENT0: + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + if (ret) + return ret; + args->value = V3D_READ(V3D_IDENT0); + pm_runtime_put(&vc4->v3d->pdev->dev); + break; + case DRM_VC4_PARAM_V3D_IDENT1: + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + if (ret) + return ret; + args->value = V3D_READ(V3D_IDENT1); + pm_runtime_put(&vc4->v3d->pdev->dev); + break; + case DRM_VC4_PARAM_V3D_IDENT2: + ret = pm_runtime_get_sync(&vc4->v3d->pdev->dev); + if (ret) + return ret; + args->value = V3D_READ(V3D_IDENT2); + pm_runtime_put(&vc4->v3d->pdev->dev); + break; + default: + DRM_DEBUG("Unknown parameter %d\n", args->param); + return -EINVAL; + } + + return 0; +} + static void vc4_lastclose(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); @@ -74,6 +115,7 @@ static const struct drm_ioctl_desc vc4_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(VC4_CREATE_SHADER_BO, vc4_create_shader_bo_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(VC4_GET_HANG_STATE, vc4_get_hang_state_ioctl, DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(VC4_GET_PARAM, vc4_get_param_ioctl, DRM_RENDER_ALLOW), }; static struct drm_driver vc4_drm_driver = { diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h index af12e8a184c8..1143e954048d 100644 --- a/include/uapi/drm/vc4_drm.h +++ b/include/uapi/drm/vc4_drm.h @@ -37,6 +37,7 @@ extern "C" { #define DRM_VC4_MMAP_BO 0x04 #define DRM_VC4_CREATE_SHADER_BO 0x05 #define DRM_VC4_GET_HANG_STATE 0x06 +#define DRM_VC4_GET_PARAM 0x07 #define DRM_IOCTL_VC4_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_SUBMIT_CL, struct drm_vc4_submit_cl) #define DRM_IOCTL_VC4_WAIT_SEQNO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_WAIT_SEQNO, struct drm_vc4_wait_seqno) @@ -45,6 +46,7 @@ extern "C" { #define DRM_IOCTL_VC4_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_MMAP_BO, struct drm_vc4_mmap_bo) #define DRM_IOCTL_VC4_CREATE_SHADER_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_CREATE_SHADER_BO, struct drm_vc4_create_shader_bo) #define DRM_IOCTL_VC4_GET_HANG_STATE DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_HANG_STATE, struct drm_vc4_get_hang_state) +#define DRM_IOCTL_VC4_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_VC4_GET_PARAM, struct drm_vc4_get_param) struct drm_vc4_submit_rcl_surface { __u32 hindex; /* Handle index, or ~0 if not present. */ @@ -280,6 +282,16 @@ struct drm_vc4_get_hang_state { __u32 pad[16]; }; +#define DRM_VC4_PARAM_V3D_IDENT0 0 +#define DRM_VC4_PARAM_V3D_IDENT1 1 +#define DRM_VC4_PARAM_V3D_IDENT2 2 + +struct drm_vc4_get_param { + __u32 param; + __u32 pad; + __u64 value; +}; + #if defined(__cplusplus) } #endif -- cgit v1.2.3 From 12cb22bb8ae9aff9d72a9c0a234f26d641b20eb6 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 14 Jul 2016 12:07:15 -0700 Subject: uapi: export lirc.h header This header contains the userspace API for lirc. This is a fixup for commit b7be755733dc ("[media] bz#75751: Move internal header file lirc.h to uapi/"). It moved the header to the right place, but it forgot to add it at Kbuild. So, despite being at uapi, it is not copied to the right place. Fixes: b7be755733dc44c72 ("[media] bz#75751: Move internal header file lirc.h to uapi/") Link: http://lkml.kernel.org/r/320c765d32bfc82c582e336d52ffe1026c73c644.1468439021.git.mchehab@s-opensource.com Signed-off-by: Mauro Carvalho Chehab Cc: Alec Leamas Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/uapi/linux/Kbuild | 1 + 1 file changed, 1 insertion(+) (limited to 'include/uapi') diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index 8bdae34d1f9a..ec10cfef166a 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -245,6 +245,7 @@ endif header-y += hw_breakpoint.h header-y += l2tp.h header-y += libc-compat.h +header-y += lirc.h header-y += limits.h header-y += llc.h header-y += loop.h -- cgit v1.2.3 From 7363cee5b467c31dc3af2ac98df0634bb8bbc668 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Sat, 2 Jul 2016 14:14:27 -0700 Subject: drm/vc4: Add a getparam to signal support for branches. Userspace needs to know if it can create shaders that do branching. Otherwise, for backwards compatibility with old kernels it needs to lower if statements to conditional assignments. Signed-off-by: Eric Anholt --- drivers/gpu/drm/vc4/vc4_drv.c | 3 +++ include/uapi/drm/vc4_drm.h | 1 + 2 files changed, 4 insertions(+) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index 047d7a265ceb..9435894822d5 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -76,6 +76,9 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void *data, args->value = V3D_READ(V3D_IDENT2); pm_runtime_put(&vc4->v3d->pdev->dev); break; + case DRM_VC4_PARAM_SUPPORTS_BRANCHES: + args->value = true; + break; default: DRM_DEBUG("Unknown parameter %d\n", args->param); return -EINVAL; diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h index 1143e954048d..ad7edc3edf7c 100644 --- a/include/uapi/drm/vc4_drm.h +++ b/include/uapi/drm/vc4_drm.h @@ -285,6 +285,7 @@ struct drm_vc4_get_hang_state { #define DRM_VC4_PARAM_V3D_IDENT0 0 #define DRM_VC4_PARAM_V3D_IDENT1 1 #define DRM_VC4_PARAM_V3D_IDENT2 2 +#define DRM_VC4_PARAM_SUPPORTS_BRANCHES 3 struct drm_vc4_get_param { __u32 param; -- cgit v1.2.3 From 4cd33c48ea25ba17e9d0383fe914c3e58b48f7dd Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Tue, 17 May 2016 15:44:49 -0400 Subject: drm/msm: add madvise ioctl Doesn't do anything too interesting until we wire up shrinker. Pretty much lifted from i915. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/msm/msm_drv.h | 1 + drivers/gpu/drm/msm/msm_gem.c | 35 +++++++++++++++++++++++++++++++++-- drivers/gpu/drm/msm/msm_gem.h | 5 +++++ include/uapi/drm/msm_drm.h | 25 ++++++++++++++++++++++++- 5 files changed, 102 insertions(+), 3 deletions(-) (limited to 'include/uapi') diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 435a8f90c290..00881f3ed32e 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -690,6 +690,44 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, return msm_wait_fence(priv->gpu->fctx, args->fence, &timeout, true); } +static int msm_ioctl_gem_madvise(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_msm_gem_madvise *args = data; + struct drm_gem_object *obj; + int ret; + + switch (args->madv) { + case MSM_MADV_DONTNEED: + case MSM_MADV_WILLNEED: + break; + default: + return -EINVAL; + } + + ret = mutex_lock_interruptible(&dev->struct_mutex); + if (ret) + return ret; + + obj = drm_gem_object_lookup(file, args->handle); + if (!obj) { + ret = -ENOENT; + goto unlock; + } + + ret = msm_gem_madvise(obj, args->madv); + if (ret >= 0) { + args->retained = ret; + ret = 0; + } + + drm_gem_object_unreference(obj); + +unlock: + mutex_unlock(&dev->struct_mutex); + return ret; +} + static const struct drm_ioctl_desc msm_ioctls[] = { DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_AUTH|DRM_RENDER_ALLOW), @@ -698,6 +736,7 @@ static const struct drm_ioctl_desc msm_ioctls[] = { DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT, msm_ioctl_gem_submit, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE, msm_ioctl_wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE, msm_ioctl_gem_madvise, DRM_AUTH|DRM_RENDER_ALLOW), }; static const struct vm_operations_struct vm_ops = { diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index be01e3895178..a49d7fd67ec3 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -195,6 +195,7 @@ int msm_gem_prime_pin(struct drm_gem_object *obj); void msm_gem_prime_unpin(struct drm_gem_object *obj); void *msm_gem_vaddr_locked(struct drm_gem_object *obj); void *msm_gem_vaddr(struct drm_gem_object *obj); +int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv); int msm_gem_sync_object(struct drm_gem_object *obj, struct msm_fence_context *fctx, bool exclusive); void msm_gem_move_to_active(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 69836f5685b1..c40db08647d1 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -413,6 +413,21 @@ void *msm_gem_vaddr(struct drm_gem_object *obj) return ret; } +/* Update madvise status, returns true if not purged, else + * false or -errno. + */ +int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv) +{ + struct msm_gem_object *msm_obj = to_msm_bo(obj); + + WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); + + if (msm_obj->madv != __MSM_MADV_PURGED) + msm_obj->madv = madv; + + return (msm_obj->madv != __MSM_MADV_PURGED); +} + /* must be called before _move_to_active().. */ int msm_gem_sync_object(struct drm_gem_object *obj, struct msm_fence_context *fctx, bool exclusive) @@ -464,6 +479,7 @@ void msm_gem_move_to_active(struct drm_gem_object *obj, struct msm_gpu *gpu, bool exclusive, struct fence *fence) { struct msm_gem_object *msm_obj = to_msm_bo(obj); + WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED); msm_obj->gpu = gpu; if (exclusive) reservation_object_add_excl_fence(msm_obj->resv, fence); @@ -532,13 +548,27 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) struct reservation_object_list *fobj; struct fence *fence; uint64_t off = drm_vma_node_start(&obj->vma_node); + const char *madv; WARN_ON(!mutex_is_locked(&obj->dev->struct_mutex)); - seq_printf(m, "%08x: %c %2d (%2d) %08llx %p %zu\n", + switch (msm_obj->madv) { + case __MSM_MADV_PURGED: + madv = " purged"; + break; + case MSM_MADV_DONTNEED: + madv = " purgeable"; + break; + case MSM_MADV_WILLNEED: + default: + madv = ""; + break; + } + + seq_printf(m, "%08x: %c %2d (%2d) %08llx %p %zu%s\n", msm_obj->flags, is_active(msm_obj) ? 'A' : 'I', obj->name, obj->refcount.refcount.counter, - off, msm_obj->vaddr, obj->size); + off, msm_obj->vaddr, obj->size, madv); rcu_read_lock(); fobj = rcu_dereference(robj->fence); @@ -688,6 +718,7 @@ static int msm_gem_new_impl(struct drm_device *dev, msm_obj->vram_node = (void *)&msm_obj[1]; msm_obj->flags = flags; + msm_obj->madv = MSM_MADV_WILLNEED; if (resv) { msm_obj->resv = resv; diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 9facd4b6ffd9..fa8e1f16f18e 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -29,6 +29,11 @@ struct msm_gem_object { uint32_t flags; + /** + * Advice: are the backing pages purgeable? + */ + uint8_t madv; + /* And object is either: * inactive - on priv->inactive_list * active - on one one of the gpu's active_list.. well, at diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h index bf19d2cd9078..49f778de8e06 100644 --- a/include/uapi/drm/msm_drm.h +++ b/include/uapi/drm/msm_drm.h @@ -201,6 +201,27 @@ struct drm_msm_wait_fence { struct drm_msm_timespec timeout; /* in */ }; +/* madvise provides a way to tell the kernel in case a buffers contents + * can be discarded under memory pressure, which is useful for userspace + * bo cache where we want to optimistically hold on to buffer allocate + * and potential mmap, but allow the pages to be discarded under memory + * pressure. + * + * Typical usage would involve madvise(DONTNEED) when buffer enters BO + * cache, and madvise(WILLNEED) if trying to recycle buffer from BO cache. + * In the WILLNEED case, 'retained' indicates to userspace whether the + * backing pages still exist. + */ +#define MSM_MADV_WILLNEED 0 /* backing pages are needed, status returned in 'retained' */ +#define MSM_MADV_DONTNEED 1 /* backing pages not needed */ +#define __MSM_MADV_PURGED 2 /* internal state */ + +struct drm_msm_gem_madvise { + __u32 handle; /* in, GEM handle */ + __u32 madv; /* in, MSM_MADV_x */ + __u32 retained; /* out, whether backing store still exists */ +}; + #define DRM_MSM_GET_PARAM 0x00 /* placeholder: #define DRM_MSM_SET_PARAM 0x01 @@ -211,7 +232,8 @@ struct drm_msm_wait_fence { #define DRM_MSM_GEM_CPU_FINI 0x05 #define DRM_MSM_GEM_SUBMIT 0x06 #define DRM_MSM_WAIT_FENCE 0x07 -#define DRM_MSM_NUM_IOCTLS 0x08 +#define DRM_MSM_GEM_MADVISE 0x08 +#define DRM_MSM_NUM_IOCTLS 0x09 #define DRM_IOCTL_MSM_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GET_PARAM, struct drm_msm_param) #define DRM_IOCTL_MSM_GEM_NEW DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_NEW, struct drm_msm_gem_new) @@ -220,6 +242,7 @@ struct drm_msm_wait_fence { #define DRM_IOCTL_MSM_GEM_CPU_FINI DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_GEM_CPU_FINI, struct drm_msm_gem_cpu_fini) #define DRM_IOCTL_MSM_GEM_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_SUBMIT, struct drm_msm_gem_submit) #define DRM_IOCTL_MSM_WAIT_FENCE DRM_IOW (DRM_COMMAND_BASE + DRM_MSM_WAIT_FENCE, struct drm_msm_wait_fence) +#define DRM_IOCTL_MSM_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_MSM_GEM_MADVISE, struct drm_msm_gem_madvise) #if defined(__cplusplus) } -- cgit v1.2.3 From 4077798484459a2eced2050045099a466ecb618a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 15 Jul 2016 09:31:11 +0100 Subject: drm/vgem: Attach sw fences to exported vGEM dma-buf (ioctl) vGEM buffers are useful for passing data between software clients and hardware renders. By allowing the user to create and attach fences to the exported vGEM buffers (on the dma-buf), the user can implement a deferred renderer and queue hardware operations like flipping and then signal the buffer readiness (i.e. this allows the user to schedule operations out-of-order, but have them complete in-order). This also makes it much easier to write tightly controlled testcases for dma-buf fencing and signaling between hardware drivers. v2: Don't pretend the fences exist in an ordered timeline, but allocate a separate fence-context for each fence so that the fences are unordered. v3: Make the debug output more interesting, and show the signaled status. v4: Automatically signal the fence to prevent userspace from indefinitely hanging drivers. Testcase: igt/vgem_basic/dmabuf-fence Testcase: igt/vgem_slow/nohang Signed-off-by: Chris Wilson Cc: Sean Paul Cc: Zach Reizner Cc: Gustavo Padovan Cc: Daniel Vetter Acked-by: Zach Reizner Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1468571471-12610-1-git-send-email-chris@chris-wilson.co.uk --- drivers/gpu/drm/vgem/Makefile | 2 +- drivers/gpu/drm/vgem/vgem_drv.c | 34 +++++ drivers/gpu/drm/vgem/vgem_drv.h | 16 +++ drivers/gpu/drm/vgem/vgem_fence.c | 283 ++++++++++++++++++++++++++++++++++++++ include/uapi/drm/vgem_drm.h | 62 +++++++++ 5 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/vgem/vgem_fence.c create mode 100644 include/uapi/drm/vgem_drm.h (limited to 'include/uapi') diff --git a/drivers/gpu/drm/vgem/Makefile b/drivers/gpu/drm/vgem/Makefile index 3f4c7b842028..bfcdea1330e6 100644 --- a/drivers/gpu/drm/vgem/Makefile +++ b/drivers/gpu/drm/vgem/Makefile @@ -1,4 +1,4 @@ ccflags-y := -Iinclude/drm -vgem-y := vgem_drv.o +vgem-y := vgem_drv.o vgem_fence.o obj-$(CONFIG_DRM_VGEM) += vgem.o diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index 29c2aab3c1a7..c15bafb06665 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -83,6 +83,34 @@ static const struct vm_operations_struct vgem_gem_vm_ops = { .close = drm_gem_vm_close, }; +static int vgem_open(struct drm_device *dev, struct drm_file *file) +{ + struct vgem_file *vfile; + int ret; + + vfile = kzalloc(sizeof(*vfile), GFP_KERNEL); + if (!vfile) + return -ENOMEM; + + file->driver_priv = vfile; + + ret = vgem_fence_open(vfile); + if (ret) { + kfree(vfile); + return ret; + } + + return 0; +} + +static void vgem_preclose(struct drm_device *dev, struct drm_file *file) +{ + struct vgem_file *vfile = file->driver_priv; + + vgem_fence_close(vfile); + kfree(vfile); +} + /* ioctls */ static struct drm_gem_object *vgem_gem_create(struct drm_device *dev, @@ -164,6 +192,8 @@ unref: } static struct drm_ioctl_desc vgem_ioctls[] = { + DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), }; static int vgem_mmap(struct file *filp, struct vm_area_struct *vma) @@ -271,9 +301,12 @@ static int vgem_prime_mmap(struct drm_gem_object *obj, static struct drm_driver vgem_driver = { .driver_features = DRIVER_GEM | DRIVER_PRIME, + .open = vgem_open, + .preclose = vgem_preclose, .gem_free_object_unlocked = vgem_gem_free_object, .gem_vm_ops = &vgem_gem_vm_ops, .ioctls = vgem_ioctls, + .num_ioctls = ARRAY_SIZE(vgem_ioctls), .fops = &vgem_driver_fops, .dumb_create = vgem_gem_dumb_create, @@ -328,5 +361,6 @@ module_init(vgem_init); module_exit(vgem_exit); MODULE_AUTHOR("Red Hat, Inc."); +MODULE_AUTHOR("Intel Corporation"); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL and additional rights"); diff --git a/drivers/gpu/drm/vgem/vgem_drv.h b/drivers/gpu/drm/vgem/vgem_drv.h index 988cbaae7588..1f8798ad329c 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.h +++ b/drivers/gpu/drm/vgem/vgem_drv.h @@ -32,9 +32,25 @@ #include #include +#include + +struct vgem_file { + struct idr fence_idr; + struct mutex fence_mutex; +}; + #define to_vgem_bo(x) container_of(x, struct drm_vgem_gem_object, base) struct drm_vgem_gem_object { struct drm_gem_object base; }; +int vgem_fence_open(struct vgem_file *file); +int vgem_fence_attach_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file); +int vgem_fence_signal_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file); +void vgem_fence_close(struct vgem_file *file); + #endif diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c new file mode 100644 index 000000000000..e77b52208699 --- /dev/null +++ b/drivers/gpu/drm/vgem/vgem_fence.c @@ -0,0 +1,283 @@ +/* + * Copyright 2016 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software") + * to deal in the software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * them Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTIBILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "vgem_drv.h" + +#define VGEM_FENCE_TIMEOUT (10*HZ) + +struct vgem_fence { + struct fence base; + struct spinlock lock; + struct timer_list timer; +}; + +static const char *vgem_fence_get_driver_name(struct fence *fence) +{ + return "vgem"; +} + +static const char *vgem_fence_get_timeline_name(struct fence *fence) +{ + return "unbound"; +} + +static bool vgem_fence_signaled(struct fence *fence) +{ + return false; +} + +static bool vgem_fence_enable_signaling(struct fence *fence) +{ + return true; +} + +static void vgem_fence_release(struct fence *base) +{ + struct vgem_fence *fence = container_of(base, typeof(*fence), base); + + del_timer_sync(&fence->timer); + fence_free(&fence->base); +} + +static void vgem_fence_value_str(struct fence *fence, char *str, int size) +{ + snprintf(str, size, "%u", fence->seqno); +} + +static void vgem_fence_timeline_value_str(struct fence *fence, char *str, + int size) +{ + snprintf(str, size, "%u", fence_is_signaled(fence) ? fence->seqno : 0); +} + +const struct fence_ops vgem_fence_ops = { + .get_driver_name = vgem_fence_get_driver_name, + .get_timeline_name = vgem_fence_get_timeline_name, + .enable_signaling = vgem_fence_enable_signaling, + .signaled = vgem_fence_signaled, + .wait = fence_default_wait, + .release = vgem_fence_release, + + .fence_value_str = vgem_fence_value_str, + .timeline_value_str = vgem_fence_timeline_value_str, +}; + +static void vgem_fence_timeout(unsigned long data) +{ + struct vgem_fence *fence = (struct vgem_fence *)data; + + fence_signal(&fence->base); +} + +static struct fence *vgem_fence_create(struct vgem_file *vfile, + unsigned int flags) +{ + struct vgem_fence *fence; + + fence = kzalloc(sizeof(*fence), GFP_KERNEL); + if (!fence) + return NULL; + + spin_lock_init(&fence->lock); + fence_init(&fence->base, &vgem_fence_ops, &fence->lock, + fence_context_alloc(1), 1); + + setup_timer(&fence->timer, vgem_fence_timeout, (unsigned long)fence); + + /* We force the fence to expire within 10s to prevent driver hangs */ + mod_timer(&fence->timer, VGEM_FENCE_TIMEOUT); + + return &fence->base; +} + +static int attach_dmabuf(struct drm_device *dev, + struct drm_gem_object *obj) +{ + struct dma_buf *dmabuf; + + if (obj->dma_buf) + return 0; + + dmabuf = dev->driver->gem_prime_export(dev, obj, 0); + if (IS_ERR(dmabuf)) + return PTR_ERR(dmabuf); + + obj->dma_buf = dmabuf; + drm_gem_object_reference(obj); + return 0; +} + +/* + * vgem_fence_attach_ioctl (DRM_IOCTL_VGEM_FENCE_ATTACH): + * + * Create and attach a fence to the vGEM handle. This fence is then exposed + * via the dma-buf reservation object and visible to consumers of the exported + * dma-buf. If the flags contain VGEM_FENCE_WRITE, the fence indicates the + * vGEM buffer is being written to by the client and is exposed as an exclusive + * fence, otherwise the fence indicates the client is current reading from the + * buffer and all future writes should wait for the client to signal its + * completion. Note that if a conflicting fence is already on the dma-buf (i.e. + * an exclusive fence when adding a read, or any fence when adding a write), + * -EBUSY is reported. Serialisation between operations should be handled + * by waiting upon the dma-buf. + * + * This returns the handle for the new fence that must be signaled within 10 + * seconds (or otherwise it will automatically expire). See + * vgem_fence_signal_ioctl (DRM_IOCTL_VGEM_FENCE_SIGNAL). + * + * If the vGEM handle does not exist, vgem_fence_attach_ioctl returns -ENOENT. + */ +int vgem_fence_attach_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file) +{ + struct drm_vgem_fence_attach *arg = data; + struct vgem_file *vfile = file->driver_priv; + struct reservation_object *resv; + struct drm_gem_object *obj; + struct fence *fence; + int ret; + + if (arg->flags & ~VGEM_FENCE_WRITE) + return -EINVAL; + + if (arg->pad) + return -EINVAL; + + obj = drm_gem_object_lookup(file, arg->handle); + if (!obj) + return -ENOENT; + + ret = attach_dmabuf(dev, obj); + if (ret) + goto err; + + fence = vgem_fence_create(vfile, arg->flags); + if (!fence) { + ret = -ENOMEM; + goto err; + } + + /* Check for a conflicting fence */ + resv = obj->dma_buf->resv; + if (!reservation_object_test_signaled_rcu(resv, + arg->flags & VGEM_FENCE_WRITE)) { + ret = -EBUSY; + goto err_fence; + } + + /* Expose the fence via the dma-buf */ + ret = 0; + mutex_lock(&resv->lock.base); + if (arg->flags & VGEM_FENCE_WRITE) + reservation_object_add_excl_fence(resv, fence); + else if ((ret = reservation_object_reserve_shared(resv)) == 0) + reservation_object_add_shared_fence(resv, fence); + mutex_unlock(&resv->lock.base); + + /* Record the fence in our idr for later signaling */ + if (ret == 0) { + mutex_lock(&vfile->fence_mutex); + ret = idr_alloc(&vfile->fence_idr, fence, 1, 0, GFP_KERNEL); + mutex_unlock(&vfile->fence_mutex); + if (ret > 0) { + arg->out_fence = ret; + ret = 0; + } + } +err_fence: + if (ret) { + fence_signal(fence); + fence_put(fence); + } +err: + drm_gem_object_unreference_unlocked(obj); + return ret; +} + +/* + * vgem_fence_signal_ioctl (DRM_IOCTL_VGEM_FENCE_SIGNAL): + * + * Signal and consume a fence ealier attached to a vGEM handle using + * vgem_fence_attach_ioctl (DRM_IOCTL_VGEM_FENCE_ATTACH). + * + * All fences must be signaled within 10s of attachment or otherwise they + * will automatically expire (and a vgem_fence_signal_ioctl returns -ETIMEDOUT). + * + * Signaling a fence indicates to all consumers of the dma-buf that the + * client has completed the operation associated with the fence, and that the + * buffer is then ready for consumption. + * + * If the fence does not exist (or has already been signaled by the client), + * vgem_fence_signal_ioctl returns -ENOENT. + */ +int vgem_fence_signal_ioctl(struct drm_device *dev, + void *data, + struct drm_file *file) +{ + struct vgem_file *vfile = file->driver_priv; + struct drm_vgem_fence_signal *arg = data; + struct fence *fence; + int ret; + + if (arg->flags) + return -EINVAL; + + mutex_lock(&vfile->fence_mutex); + fence = idr_replace(&vfile->fence_idr, NULL, arg->fence); + mutex_unlock(&vfile->fence_mutex); + if (!fence) + return -ENOENT; + if (IS_ERR(fence)) + return PTR_ERR(fence); + + if (fence_is_signaled(fence)) + ret = -ETIMEDOUT; + + fence_signal(fence); + fence_put(fence); + return ret; +} + +int vgem_fence_open(struct vgem_file *vfile) +{ + mutex_init(&vfile->fence_mutex); + idr_init(&vfile->fence_idr); + + return 0; +} + +static int __vgem_fence_idr_fini(int id, void *p, void *data) +{ + fence_signal(p); + fence_put(p); + return 0; +} + +void vgem_fence_close(struct vgem_file *vfile) +{ + idr_for_each(&vfile->fence_idr, __vgem_fence_idr_fini, vfile); + idr_destroy(&vfile->fence_idr); +} diff --git a/include/uapi/drm/vgem_drm.h b/include/uapi/drm/vgem_drm.h new file mode 100644 index 000000000000..bf66f5db6da8 --- /dev/null +++ b/include/uapi/drm/vgem_drm.h @@ -0,0 +1,62 @@ +/* + * Copyright 2016 Intel Corporation + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef _UAPI_VGEM_DRM_H_ +#define _UAPI_VGEM_DRM_H_ + +#include "drm.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + */ +#define DRM_VGEM_FENCE_ATTACH 0x1 +#define DRM_VGEM_FENCE_SIGNAL 0x2 + +#define DRM_IOCTL_VGEM_FENCE_ATTACH DRM_IOWR( DRM_COMMAND_BASE + DRM_VGEM_FENCE_ATTACH, struct drm_vgem_fence_attach) +#define DRM_IOCTL_VGEM_FENCE_SIGNAL DRM_IOW( DRM_COMMAND_BASE + DRM_VGEM_FENCE_SIGNAL, struct drm_vgem_fence_signal) + +struct drm_vgem_fence_attach { + __u32 handle; + __u32 flags; +#define VGEM_FENCE_WRITE 0x1 + __u32 out_fence; + __u32 pad; +}; + +struct drm_vgem_fence_signal { + __u32 fence; + __u32 flags; +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* _UAPI_VGEM_DRM_H_ */ -- cgit v1.2.3